lsof-4.86+dfsg.orig/0000755000175000017500000000000011743250563014464 5ustar nicholasnicholaslsof-4.86+dfsg.orig/00TEST0000444000175000017500000010375711741060511015327 0ustar nicholasnicholas The Lsof Test Suite Contents A. Introduction 1. Test Suite Goals 2. Not a FAQ 3. Where have the tests been tested? B. Test Methodology 1. Test Limitations 2. Test Data Base and Scripts 3. The Makefile 3.1 The CkTestDB Script 4. The Lsof Executable and LT_LSOF_PATH 5. Automated Testing C. Configure Script Participation 1. config.cc 2. config.cflags 2.1 config.cflags Contents 3. config.ldflags 4. config.xobj D. Cleaning -- Quick or Spotless E. Test Libraries 1. LTlib.c F. The Individual Tests 1. LTbasic, a Basic Lsof Test 2. LTbigf, Test Sizes and Offsets for Large (> 32 bit) Files 3. LTdnlc, Test the Kernel's Dynamic Name Lookup Cache 4. LTlock, Lock Tests 5. LTnfs, NFS Test 6. LTnlink, Link Count Test 7. LTsock, Test IPv4 Sockets 8. LTszoff, Test Sizes and Offsets for Small (< 32 bit) Files 9. LTunix, Test UNIX Domain Sockets Appendix A, Test Files Appendix B, Test Validations Appendix C, Test Failures A. Introduction =============== Lsof has an automated test suite whose components are located in the tests/ sub-directory of the lsof top-level directory. Configuring, building and testing lsof can be done with these shell commands: $ Configure -n $ make $ cd tests $ make That's all there is to it! But read on for more dirty details. A.1. Test Suite Goals ===================== The lsof test suite attempts to test basic lsof features. It does not promise to test every lsof feature for every supported dialect. (That's a nearly impossible goal.) As a result, the test suite cannot promise that every lsof feature works as documented. At best the test suite gives some assurance that basic, standard and some optional lsof features work. A.2. Not a FAQ ============== One caution: this is not a frequently asked questions (FAQ) file for the lsof test suite. FAQs on the lsof test suite will be found in the one and only lsof FAQ in file 00FAQ of the lsof distribution, or on-line at: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/FAQ A.3. Where have the tests been tested? ====================================== OK, I just said this isn't an FAQ and here comes a question and answer that looks like an FAQ. Consider it a very frequently asked question and indulge me -- let me answer it here. The lsof test suite hasn't been tested everywhere it might be possible to build lsof successfully. That "everywhere" includes dialect versions -- e.g., Solaris < 2.6 -- to which I no longer have access. On some dialect versions to which I have access, some tests won't run because the test system lacks support. In "Appendix B, Test Validations" I've tried to list where I compiled and tested the test suite and information on any tests I was unable to run. In "Appendix C, Test Failures" I list where the test suite fails and why it failed. A.4 Where are the tests? ======================== This is another FAQ whose answer is that the tests are in the tests/ sub-directory of the main lsof source directory. B. Test Methodology =================== The test suite is made up of individual C programs. Test setup is performed by the lsof Configure script itself, which writes a set of dialect configuration files in the tests/ subdirectory. (See "C. Configure Script Participation.") Each program or script performs a specialized tests. Those tests are described below in "F. The Individual Tests". Each test measures lsof functionality by putting a specific lsof command execution at the end of an in-bound (to the test) pipe. The caller asks lsof to write its results to the pipe in field output form. (See the -F option in the lsof man page.) Using an in-bound lsof pipe allows the tests to measure a great deal of lsof functionality, including as an interesting side effect, the performance of field output. Consequently, there's no special field output test. B.1. Test Limitations ===================== One limitation of the tests is that they don't measure lsof formatted output -- i.e., the output normally see when lsof is run. There are just too many variants of lsof output produced across the range of dialects where lsof runs, so field output is a more consistent way to process lsof output. But using field output does mean that the test suite doesn't check for lsof formatting problems, except in the field output itself. B.2. Test Data Base and Scripts =============================== The TestDB file contains a simple data base that describes where the tests have been validated. Entries are formed from a combination of the lines in the config.cflags file produced by the lsof Configure script. The entries can be considered "lsof dialect footprints," hereafter simply called "dialect footprints" or just "footprints." Two shell scripts support TestDB. The first, Add2TestDB, will add a footprint to TestDB. I don't recommend you use this script. Mostly it's for my use when I find that the test suite has been validated on a new dialect. It's also possible to add a footprint to TestDB by simply editing TestDB and pasting into it a copy of the footprint reported by a failed Makefile rule. I don't generally recommend this be done, either. There are Makefile rules that use (and avoid) the CkTestDB script. (See "B.3 The Makefile".) The default (i.e., "all") Makefile rule uses the CkTestDB script to look for the footprint in TestDB. If no footprint is found, the script issues a warning, displays the unfound footprint, and asks if running the test suite should continue. The "auto" Makefile rule also uses CkTestDB, but with a special call that causes CkTestDB to look in TestDB for the footprint, report it when it can't be found, and then fail. That CkTestDB failure causes the "auto" rule to fail, too. The "silent" Makefile rule doesn't use CkTestDB to look in TestDB for the footprint. It runs the standard and basic tests as silently as possible, then returns a failure or success exit code that signals the result of the running of the tests. (Use the "silent" rule carefully, because it will skip proving the tests have previously run on the dialect.) B.3. The Makefile ======================= The Makefile runs the tests in the test suite. It has these rules. all runs the basic test and the standard tests, interacting with the caller should the footprint not be found in TestDB. (This is the default rule.) auto runs the basic test and the standard tests on a previously validated system as silently as possible. The footprint must be found in TestDB for this rule to succeed. (See the "silent" rule for one that avoids checking TestDB.) This rule is designed for lsof build scripts that want a quick noiseless test to make sure what they built works as it previously did. This rule calls CkTestDB in a way that inhibits its normal go-ahead request. (See "B.2.1 The CkTestDB Script".) If CkTestDB finds the footprint and all tests succeed, this rule returns a zero exit code (success). If the footprint isn't found or if any test fails, a non-zero exit code (failure) is returned. ckDB calls the CkTestDB script to look for a footprint. If none is found, the way CkTestDB was called (See "B.3.1 The CkTestDB Script".) causes it to return a non-zero exit code (failure) to this rule, and the rule then returns a non-zero exit code (failure) itself. This rule is used by the "auto" rule. If this rule succeeds (zero exit code), the "auto" rule then uses the "silent" rule. clean removes test and compiler output. (See the "D. Cleaning -- Quick or Spotless" section.) opt runs the optional tests. optional silent runs the lsof basic and standard tests as silently as possible (as the "auto" rule does), but without using CkTestDB to look for a footprint. If all tests succeed, the rule returns a zero exit code (success). If any test fails, the rule returns a non-zero exit code (failure). Use the "silent" rule carefully, because it will skip proving the tests have previously run on the dialect. spotless does what the clean rule does and also removes the config.* files created by ../Configure. (See the "D. Cleaning -- Quick or Spotless" section.) std runs the basic test and the standard tests. standard The Makefile cleaning rules are further described in "D. Cleaning -- Quick or Spotless." B.3.1 The CkTestDB Script ========================= Some Makefile rules (e.g., "all" and "auto") use the CkTestDB script to make sure the tests have been run previously on the dialect. CkTestDB does that by looking for the dialect's footprint in TestDB. If no footprint is found, and if standard input is a TTY, CkTestDB asks for a go-ahead signal. If standard input isn't a TTY, CkTestDB aborts the test run. (See "B.2. Test Data Base and Scripts".) The Makefile "silent" rule does not call CkTestDB. use the "silent" rule carefully, because it will skip proving the tests have previously run on the dialect. B.4. The Lsof Executable and LT_LSOF_PATH ========================================= Normally the programs in the test suite use the lsof executable in their parent directory, ../lsof. Usually that lsof has just been built and testing it is the next logical step. Be careful that ../lsof has sufficient permission to access the necessary kernel resources -- e.g., /dev/kmem, /dev/mem, /proc, etc. If it doesn't the tests will fail. (The tests do check to see if they can open /dev/mem and /dev/kmem for read access if LT_KMEM is defined in config.cflags and if the path to the lsof executable is ../lsof.) Here are two possible ways you can make sure the lsof being tested has sufficient permission: 1) use chmod and chgrp to enable its running and put its path in LT_LSOF_PATH, thus disabling the check in the tests for kernel memory access; or 2) run the tests (and hence the lsof being tested) under a login that has sufficient permission -- e.g., is in a group that can read /dev/kmem. You can direct the tests to use a different lsof executable by specifying its path in the LT_LSOF_PATH environment variable. To test an lsof executable already installed in /usr/local/etc -- provided that lsof is at revision 4.63 or higher -- do this: $ LT_LSOF_PATH=/usr/local/etc/lsof $ export LT_LSOF_PATH $ cd .../lsof_/tests $ make When you specify an alternate executable path via LT_LSOF_PATH, that also prevents the tests from checking to see if they have kernel memory access. B.5 Automated Testing ===================== Normally the lsof test suite is wordy and may require interaction. When you want to avoid those interferences, use the Makefile "auto" or "silent" rules. (See the description of the "auto" and "silent" rules in "B.3 The Makefile".) The footprint must be present in TestDB in order to use the "auto" rule. If it is not, the "auto" rule will fail and report the missing footprint. Footprints in TestDB proclaim that the tests have previously succeeded on the dialect. The footprint need not be present in TestDB in order to use the "silent" rule. Use the "silent" rule carefully, because it will skip proving the tests have previously run on the dialect. C. Configure Script Participation ================================= An important step in setting up the test suite is performed by the Configure script in the lsof home directory (the parent to tests/.) Configure writes four files in tests/ that describe how the tests are to be compiled, configured and loaded. The files also describe options that Configure selected that are important to the test suite. C.1. config.cc ============== This file, config.cc, contains the name of or the path to the C compiler used to compile lsof. The Makefile uses this file in place of the standard make(1) CC string with a shell in-place execution statement -- i.e., `cat config.cc`. If the LSOF_CC environment variable is supplied to the lsof Configure script, its value will appear in the config.cc file. C.2. config.cflags ================== This file, config.cflags, contains C compiler flags that Makefile uses to compile the C programs in the test suite. As with the compiler file, config.cc, the make rules incorporate the contents of this file into C compiler options with `cat config.cflags`. This file is also used by the Add2TestDB and CkTestDB shell scripts to build and match footprints. (See "B.2. Test Data Base and Scripts.") C.2.1 config.cflags Contents ============================ The config.cflags file may contain the following C compiler flags. -DLT_AIXA is present if lsof was built for AIX. It contains the AIX architecture flag. (See the lsof Configure script or dialects/aix/dlsof.h for more information on the AIX architecture flag.) -DLT_BIGF is present if lsof was built for a dialect that has large file (sizes and offsets > 32 bits). -DLT_CC is present if the lsof compiler is cc. -DLT_DIAL_ always ends in (the part) the "canonical" -- i.e., usually the most common abbreviation by which the dialect is known. Example: -DLT_DIAL_solaris -DLT_GCC is present if the lsof compiler is gcc. -DLT_K64 is present if lsof has been built for a 64 bit kernel -DLT_KMEM is present if lsof has been built to use /dev/kmem to obtain kernel values. -DLT_VERS= contains the version number for the dialect, as used in lsof pre-processor tests. Example for Solaris 10: -DLT_VERS=100000 -DLT_VPATH is present if the dialect has the v_path member in the vnode structure (e.g., some versions of Solaris 10). The config.cflags file may also contain dialect-specific compiler flags needed to activate a specific feature on the dialect. For example, for HP-UX config.cflags might contain: -D_LARGEFILE64_SOURCE This compiler flag enables the use of large-file system library functions --e.g., open64(). The lsof Configure script stanzas for the dialects select these options. C.3. config.ldflags =================== This file, config.ldflags, contains the dialect loader flags -- i.e., the equivalent to make(1) LFLAGS -- for loading the test programs. Example for Solaris: -lsocket this adds the socket library to the loading of the lsof test programs. Example for UnixWare: -lsocket -lnsl this adds the socket and name server libraries to the loading of the lsof test programs. C.4. config.xobj ================ This file, config.xobj, contains the paths to any extra object files (.o's) that must be loaded when the test suite C programs are loaded. Like config.cc and config.cflags, it's incorporated into the loader statements of the Makefile's rules with `cat config.xobj`. Examples for DEC OSF/1 and NEXTSTEP: ../lib/snpf.o this loads the private lsof object file that contains an snprintf() function. (The DEC OSF/1 4.0 and NEXTSTEP 3.1 C libraries don't have snprintf().) D. Cleaning -- Quick or Spotless ================================ There are two Makefile rules that clean the tests/ subdirectory -- "clean" and "spotless". They cause different degrees of cleaning. clean a "quick" clean that removes compiled object files, executables and test files. It does NOT remove the configuration files that ../Configure and the config.perl rule wrote. spotless cleans out everything clean does -- plus the configuration files that ../Configure and the config.perl rule wrote. This is the rule used when `./Configure -clean` is specified. If this rule is used, `../Configure -n ` and `../make`) must be run again before the test suite can be used. E. Test Library =============== The lsof test suite provides a C library. E.1. LTlib.c ============ This is a C library of common functions used by tests. Configured at compile time by the contents of config.cflags, it uses the single header file LsofTest.h. LsofTest.h tailors its definitions to the dialect at compile time, using the LT_DIAL_* definitions in config.cflags. Two particularly useful functions in the library are: ExecLsof(), which will execute an lsof child process; and RdFromLsof(), which will read from the in-bound lsof pipe, and decode the fields into structures that are easy for C programs to process. This library is a good model for processing field output in a C program from an in-bound lsof pipe. The source for the library, LTlib.c, contains more documentation. F. The Individual Tests ======================= The individual tests are listed in this section. The listings explain what the tests do, a few errors they might report, and how to use options and environment variables to customize the tests. The test descriptions are listed in this section in alphabetical order, not in the order they are run by Makefile. The Makefile runs the tests in three groups, basic tests, standard tests, and optional tests. The default make "all" rule runs the basic and standard tests. (The "standard", "std", and "test" Makefile rules are synonyms to "all".) If the standard tests succeed, Makefile suggests running the optional tests with the "opt" (or "optional") rule. The Makefile "auto" and "silent" rules run only the basic and standard tests. They do not run or suggest you run the optional tests. The basic test: LTbasic Standard tests: LTnlink LTsock LTszoff LTunix Optional tests: LTbigf LTdnlc LTlock LTnfs The basic and standard tests should all succeed on all dialects, although LTnlink may warn that it can't perform its unlink test on an NFS file system. The optional tests may run, they may be disabled for specific dialects, or they may fail because of special resource needs -- e.g., LTbigf will run only on UNIX dialects where it knows how to handle files whose lengths exceed 32 bits, and LTnfs needs access to an NFS file system mounted from a remote NFS server. Tests that need special resources usually provide a hint about the resources when they fail. Information about special resource needs may also be found in the following sections about the individual tests. G.1. LTbasic, a Basic Lsof Test =============================== This is the basic lsof test. If it doesn't run, it's not likely any other tests will run, either. Hence, if it fails, no Makefile rule runs any other tests. This test uses lsof to locate files in the lsof process, including current working directory, the lsof executable, and the /dev/kmem open file. Finding the lsof executable may not be possible on AIX if lsof was compiled without support for its -X option. Finding /dev/kmem use by lsof is only possible on dialects where lsof uses /dev/kmem. The -DLT_KMEM define indicates that. Run this test: $ ./LTbasic Environment variables: LT_LSOF_PATH defines the path to the lsof executable. (The default is ../lsof.) G.2. LTbigf, Test Sizes and Offsets for Large (> 32 bit) Files ============================================================== This is a test in the optional test group. This test is effective only when ../Configure has put -DLT_BIGF in config.cflags. Without that definition this test simply reports that the dialect doesn't support large files. That report is accompanied by a successful test exit code, so that the runner of the test (e.g., the Makefile) won't believe the test failed. When a dialect does support large files, the test attempts to create a file that looks very large -- e.g., has a length as reported by ls(1) of 0x140000000 bytes. However, the file really has only a small amount of data in it, the rest of the file consists of a large standard UNIX file system "hole." By default the test file is named config.LTbigf, where PID is the Process ID of the LTbigf process. When that file is not on a file system enabled for large files, or when the process that runs LTbigf can't create a big file, LTbigf will report an error. The error will be accompanied by hints that the -p option may need to be used to define a path where the test can write a large file, or the process ulimit file block size may need to be raised -- e.g., to "unlimited." LTbigf can't test file offset reporting on Linux kernels below 2.6.22, because the /proc file systems of those kernels don't make file offsets available to lsof. Run this test: $ ./LTbigf [-p ] Environment variables: LT_LSOF_PATH defines the path to the lsof executable. (The default is ../lsof.) G.3. LTdnlc, Test the Kernel's Dynamic Name Lookup Cache ======================================================== This is a test in the optional test group. This test asks lsof to locate the current working directory of its own process and report the path it has assembled from the components it found in the kernel's Dynamic Name Lookup Cache (DNLC) or via other dialect-specific methods. (E.g., Linux, HP-UX 11.11, and some Tru64 UNIX versions have private name lookup methods.) The test checks what lsof reports as the current working directory path for any missing components and counts the number of full paths returned. (Symbolic link complications prevent testing for exact path matches.) The test is repeated. If full paths are returned at least half the time, the test considers itself successful. This test can't be run on AIX, because lsof can't access the DNLC there. It can't be run on Apple Darwin versions below 8.0, either, because insufficiently reliable DNLC information is available there. This test may fail on other dialects when the file system -- e.g., NFS. /tmp, loopback -- doesn't fully participate in the dialect's DNLC. Run this test: $ ./LTdnlc Environment variables: LT_LSOF_PATH defines the path to the lsof executable. (The default is ../lsof.) G.4. LTlock, Lock Tests ======================= This is a test in the optional test group. This test uses flock() and fcntl() to set and clear file locks, and measures lsof's ability to report them. The choice of system lock call is based on the dialect. (There are LT_DIAL_* pre-processor tests in LTlock.c.) This test can't be run on an NFS client file system, because NFS lock information is kept on the server. Lsof on the client can't see that server kernel data. By default the test attempts to create a file named config.LTlock, where PID is the Process ID of the locking test process. It uses lsof to determine if the file is on a client NFS file system. If it is, the test aborts, hinting that the -p option can be used to specify a non-client-NFS test file path. This test can't be run on Darwin, because insufficient file system lock information is available to lsof there. Run this test: $ ./LTlock [-p ] Environment variables: LT_LSOF_PATH defines the path to the lsof executable. (The default is ../lsof.) G.6. LTnfs, NFS Test ==================== This is a test in the optional test group. This test verifies that lsof can locate files mounted on a client NFS system from an NFS server. By default it creates a test file, config.LTnfs, where PID is the Process ID of the test process. The test then uses lsof to find the file on an NFS file system. If lsof can't find the file the test warns that the test file might not be on an NFS file system and hints that the -p option may be used to specify the path of an NFS file, provided the test can have read access to it there. The test warning also states that the file at the path specified with -p must be a regular file, not a directory. This test can't be run on Darwin versions below 8.0, because insufficient NFS file information is available to lsof there. Run this test: $ ./LTnfs [-p ] Environment variables: LT_LSOF_PATH defines the path to the lsof executable. (The default is ../lsof.) G.7. LTnlink, Link Count Test ============================= This is a test in the standard test group. The test checks lsof's reporting of link count (nlink in UNIX argot.) It creates a test file in the current working directory named config.LTnlink, where PID is the Process ID of the test process. It then uses stat(2) and lsof to measure the link count of the file. If LTnlink creates the test file in the current working directory and it is on an NFS file system, LTnlink won't be able to perform one section of its test. In that section the test file is unlinked so its link count will be zero and lsof is asked to find it among the set of files whose link counts are zero. When an NFS file is unlinked its link count isn't reduced until the last open instance is closed on either the NFS clients or the NFS. That's a consequence of NFS statelessness and leads to the occasional presence of files with names of the form .nfsxxxx. Should LTnlink find its test file on an NFS file system, it disables the unlink section of its tests and issues a warning. It also issues a hint that the test file path can be named via the -p option to give a test file location that isn't on an NFS file system. This test can't be run on Darwin, because insufficient file system link count information is available to lsof there. Because some UNIX dialects delay the reporting of a link count update after a file has been unlinked, LTnlink may not get its expected response from lsof for a while after the test file has been unlinked. In that cause LTnlink may delay for up to a minute, calling lsof once every two seconds and displaying a "waiting for link count update: ..." message. Some file systems -- e.g., ZFS on Solaris 11 -- don't allow LTnlink to unlink its test file, because LTnlink has the file open. LTnlink explains that failure and suggests that it be run with path of the "-p path" option set to a file on /tmp. See 00FAQ for more information. Run this test: $ ./LTnlink [-p ] Environment variables: LT_LSOF_PATH defines the path to the lsof executable. (The default is ../lsof.) G.7. LTsock, Test IPv4 Sockets ============================== This is a test in the standard test group. This test uses lsof to locate open IPv4 socket files that the test has created itself. The test opens a server socket, then forks a child process to connect to that socket. After both are running, the test uses lsof to find the open socket files at their known host and port addresses. Run this test: $ ./LTsock Environment variables: LT_LSOF_PATH defines the path to the lsof executable. (The default is ../lsof.) G.8. LTszoff, Test Sizes and Offsets for Small (< 32 bit) Files =============================================================== This is a test in the standard test group. This test checks lsof's reporting of file size and offset for small (< 32 bits) files. It creates a test file in the current working directory named config.LTszoff. PID is the Process ID of the test process. LTszoff can't test file offset reporting on Linux kernels below 2.6.22, because the /proc file systems of those kernels don't make file offsets available to lsof. Run this test: $ ./LTszoff [-p ] Environment variables: LT_LSOF_PATH defines the path to the lsof executable. (The default is ../lsof.) G.9. LTunix, Test UNIX Domain Sockets ====================================== This is a test in the standard test group. This test checks lsof's reporting of UNIX domain sockets. The test creates a pair of UNIX domain sockets and uses bind(2) to associate the file system names config.LT0U (client) and config.LT1U (server) with them. (PID is the test process ID.) The test then uses lsof to find the two open UNIX domain socket files. Run this test: $ ./LTunix Environment variables: LT_LSOF_PATH defines the path to the lsof executable. (The default is ../lsof.) Appendix A, Test Files ====================== These files may be created by suite tests. Created ./tests Name by Test Use ============ ======= === config.LTbifg** LTbigf to test lsof's large file size and offset reporting config.LTlock* LTlock for locking tests config.LTnfs* LTnfs for NFS tests config.LTnlink* LTnlink for link count tests config.LTszoff* LTszoff for small file size and and offset reporting config.LT[01]U* LTunix two UNIX domain sockets, used to determine if lsof can report their open instances properly Appendix B, Test Validations ============================ This appendix lists the UNIX dialects and their versions where I have validated the test suite. The list indicates the particular tests I was unable to run, mostly LTnfs because the test systems I used had no NFS file systems mounted. The information in the following table is encoded in a test data base file, TestDB, as footprints, using the tests compiler options written to config.cflags by the lsof Configure script. See "B.2. Test Data Base and Scripts" for more information on the test data base, footprints, and the scripts that support them. UNIX Dialect Dialect Description Untested Tests ======= =================== ============== AIX 4.3.3, Power, cc 5.1, Power-32, cc 5.1, Power-32, gcc 5.1, Power-64, cc 5.2, Power-32, cc 5.2, Power-32, gcc 5.2, Power-64, cc 5.2, Power-64, gcc 5.3, Power-64, cc Darwin 1.4, 5.5, 6.x, 7.x gcc Darwin lsof doesn't have adequate support to allow the LTbigf, Ltdnlc, LTlock, LTnfs, and LTnlink tests to run. 8.0, gcc Darwin lsof doesn't have adequate support to allow the LTbigf, LTlock and LTnlink tests to run. 9.0, gcc Darwin lsof doesn't have adequate support to allow the LTlock test to run. 10.0, gcc Darwin lsof doesn't have adequate support to allow the LTlock test to run. 11.0, gcc Darwin lsof doesn't have adequate support to allow the LTlock test to run. FreeBSD 4.5, i386, gcc 4.6, i386, gcc 4.7, i386, gcc 4.8, i386, gcc 4.9, i386, gcc 4.10, i386 gcc 5.0, Alpha, gcc 5.0, Sparc, gcc 5.0, i386, gcc 5.1, Alpha, gcc 5.1, Amd64, gcc 5.1, Sparc, gcc 5.1, i386, gcc 5.2, i386, gcc 5.2, Alpha, gcc 5.2, Amd64, gcc 5.2, Sparc, gcc 5.3, Alpha, gcc 5.4, Alpha, gcc 5.5, Alpha, gcc 6.0, Alpha, gcc 6.0, Amd64, gcc 6.0, Sparc, gcc 6.1, i386, gcc 6.4, i386, gcc 7.0 Alpha, gcc 7.0 Amd64, gcc 7.1 Amd64, gcc 7.2 Amd64, gcc 7.3 Amd64, gcc 7.4 Amd64, gcc 8.0 Amd64, gcc 8.2 Amd64, gcc 8.3 Amd64, gcc 9.0 Amd64, gcc 10.0 Amd64, gcc DEC OSF/1 4.0, cc HP-UX 10.20, cc LTbigf 10.20, gcc (1) LTbigf 11.00-32, ANSI-C LTbigf, LTnfs 11.00-64, ANSI-C 11.11, ANSI-C 11.23, ANSI-C Linux 2.4.12-686 LTbigf, no offset tests LTszoff, no offset tests 2.4.18-686 LTbigf, no offset tests LTszoff, no offset tests 2.4.21-686 LTbigf, no offset tests LTszoff, no offset tests 2.4.23-686 LTbigf, no offset tests LTszoff, no offset tests 2.4.24-686 LTbigf, no offset tests LTszoff, no offset tests 2.4.25-686 LTbigf, no offset tests LTszoff, no offset tests 2.4.26-686 LTbigf, no offset tests LTszoff, no offset tests 2.4.27-686 LTbigf, no offset tests LTszoff, no offset tests 2.4.28-686 LTbigf, no offset tests LTszoff, no offset tests 2.4.29-686 LTbigf, no offset tests LTszoff, no offset tests 2.4.30-686 LTbigf, no offset tests LTszoff, no offset tests 2.6.1-rc2 LTbigf, no offset tests LTszoff, no offset tests 2.6.18-686 LTbigf, no offset tests LTszoff, no offset tests 2.6.22-686 (Note: this Linux kernel supplies file offsets to lsof.) 2.6.32-686 (Note: this Linux kernel supplies file offsets to lsof.) 2.6.38-686 NEXTSTEP 3.1, gcc LTnfs NetBSD 1.4.1, Alpha, gcc LTnfs 1.5x, x86, gcc LTnfs 1.6x, Alpha, gcc LTnfs 1.6x, x86, gcc LTnfs 2.0x, alpha, gcc LTnfs 2.0x, sparc64, gcc LTnfs 2.0x, x86, gcc LTnfs 2.99.9, x86, gcc LTnfs 2.99.10, x86, gcc LTnfs 2.99.11, x86, gcc LTnfs 2.99.12, x86, gcc LTnfs 3.99., x86, gcc LTnfs OpenBSD 3.0, gcc 3.1, gcc 3.2, gcc 3.3, gcc 3.4, gcc 3.5, gcc 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 2.6, gcc LTnfs 7-32, cc 7-32, gcc LTnfs 8-32, cc 8-32, gcc 8-64, cc 8-64, gcc 9-64, Beta-Refresh, cc 9-64, Beta-Refresh, gcc 9-64, FCS, cc 9-64, FCS, gcc 10-32, i86pc, gcc 10-32, i86pc, cc 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 If you are able to run the test suite on dialect versions other than the ones listed above, please send e-mail to , indicating the dialect version where you were able to run the test suite. Please send me the footprint formed by CkTestDB, or run the Add2TestDB script and send me the footprint it reports. If you encounter problems compiling the tests or running them on a dialect version listed above, please send e-mail to , naming the dialect version and providing the output from the lsof Configure script and make operation. 1) John Dzubera did the HP-UX 10.20 gcc testing and provided its footprint. Appendix C, Test Failures ========================= I was unable to make the test suite run on the following dialects. UNIX Dialect and Description Failure =============== ======= HP-UX 11-64, gcc 64 bit gcc 3.0 didn't compile the LTsock test correctly on my 64 bit HP-UX 11 test system. Vic Abell April 10, 2012 lsof-4.86+dfsg.orig/Customize0000555000175000017500000006304710240401140016360 0ustar nicholasnicholas#!/bin/sh # # $Id: Customize,v 1.9 2005/05/11 13:02:18 abe Exp $ # # Customize: customize dialect's machine.h header file. # # Allows easy modification of some important compile-time definitions for # lsof, made in the dialect's machine.h header file, including: # # HASSECURITY the security option # HASNOSOCKSECURITY # the socket oberalization of HASSECURITY # HASDCACHE enabling/disabling the device cache file # (Note: changing the device cache file option isn't # offered when machine.h contains NEVER_HASDCACHE # anywhere, including in a comment.) # HASENVDC enabling/disabling device cache path from environment # HASKERNIDCK enabling/disabling the kernel identity check # (not done for some dialects) # HASPERSDC enabling/disabling personal device cache path # construction # HASPERSDCPATH enabling/disabling additional personal device cache # path component # HASSYSDC enabling/disabling system-wide device cache file path # HASXOPT_ROOT enabling/disabling root use of the -X option # WARNDEVACCESS enabling inaccessible /dev node warnings # (Note: changing the inaccessible /dev/node warning # option isn't offered when machine.h contains # NEVER_WARNDEVACCESS anywhere, including in a # comment.) # WARNINGSTATE enable/disabling default warning message state # # Usage: Customize [dialect_directory] # # where: dialect_directory (optional) is the directory in which the dialect's # dialect's sources, Makefile and scripts are found OLD=machine.h NEW=new_machine.h # Save optional dialect directory. if test $# -eq 1 then DialDir=$1 else DialDir="" fi # Establish trap and stty handling. ISIG=":" trap 'rm -f $NEW; $ISIG; exit 1' 1 2 3 15 stty -a 2>&1 | grep isig > /dev/null if test $? -eq 0 then stty -a 2>&1 | egrep -e -isig > /dev/null if test $? -eq 0 then ISIG="stty -isig" stty isig fi fi # Decide how to use echo. ECHO=`echo -n ""` if test "X$ECHO" = "X-n " then EC="\c" EO="" else EC="" EO="-n" fi # Decide how to use tail(1). TMP1=`tail -n 1 $0 2> /dev/null` if test $? -eq 0 -a "X$TMP1" = "X#LAST_LINE" then TA="-n 1" else TA="-1" fi # Display the introduction and basic explanation. cat << .CAT_MARK You may now customize the machine.h header file for this UNIX dialect. The customizations will take effect when you compile lsof. You may also choose to skip customization and proceed to the compilation of lsof. If you don't know if you need to customize or want to know more about what you can customize, consult the 00DCACHE, 00FAQ, 00PORTING, and 00README files of the lsof distribution. You might also find it helpful to examine the machine.h header file for the dialect you're customizing. You don't need to use this procedure to customize lsof; you can edit the machine.h header file directly. If you later decide you want to use this procedure to customize machine.h, execute the ./Customize script. .CAT_MARK END=0 while test $END -eq 0 do echo "" echo $EO "Do you want to customize (y|n) [y]? $EC" read ANS EXCESS if test "X$ANS" = "Xn" -o "X$ANS" = "XN" then exit 0 fi if test "X$ANS" = "Xy" -o "X$ANS" = "XY" -o "X$ANS" = "X" then echo "" echo "Customizing ..." END=1 else echo "" echo "Please answer y|n [y]." fi done # See if $OLD exists. if test ! -r $OLD then echo "" echo "FATAL: The file \"$OLD\" doesn't exist. Customization can't" echo "continue without it." echo "" echo "Did you run the Configure script?" echo "" echo "Customize quits." echo "" exit 1 fi # See if $NEW exists. if test -r $NEW then echo "" echo "=====================================================================" echo "" echo "WARNING: \"$NEW\" exists. Customization will replace it." END=0 while test $END -eq 0 do echo "" echo $EO "Do you want to remove $NEW (y|n) [y]? $EC" read ANS EXCESS if test "X$ANS" = "Xy" -o "X$ANS" = "XY" -o "X$ANS" = "X" then echo "" echo "Removing $NEW" echo "" rm -f $NEW END=1 else if test "X$ANS" = "Xn" -o "X$ANS" = "XN" then echo "" echo "FATAL: Customize quits; it must be able to create \"$NEW\"." echo "" exit 1 else echo "" echo "Please answer y|n [y]." fi fi done fi # Process HASSECURITY. cat << .CAT_MARK ===================================================================== When HASSECURITY is enabled, only the root user may use lsof to examine all open files; other users may examine only the files belonging to the real user ID of their lsof process. If HASNOSOCKSECURITY is also defined, anyone may list anyone else's open socket files, provided their listing is selected with the "-i" option. When HASSECURITY is disabled, anyone may use lsof to examine all open files. .CAT_MARK grep HASSECURITY $OLD | tail $TA | egrep "^#define" > /dev/null if test $? -eq 0 then echo "HASSECURITY is enabled." NSEC=1 else echo "HASSECURITY is disabled." NSEC=0 fi END=0 while test $END -eq 0 do echo "" if test $NSEC -eq 1 then echo $EO "Disable HASSECURITY (y|n) [n]? $EC" else echo $EO "Enable HASSECURITY (y|n) [n]? $EC" fi read ANS EXCESS if test "X$ANS" = "Xy" -o "X$ANS" = "XY" then echo "" if test $NSEC -eq 1 then NSEC=0 echo "HASSECURITY will be disabled." else NSEC=1 echo "HASSECURITY will be enabled." fi END=1 else if test "X$ANS" = "Xn" -o "X$ANS" = "XN" -o "X$ANS" = "X" then echo "" echo "HASSECURITY will not be changed." END=1 else echo "" echo "Please answer y|n [n]." fi fi done # If HASSECURITY is enabled, see if HASNOSOCKSECURITY should also be defined. if test $NSEC -eq 1 then cat << .CAT_MARK ==================================================================== When HASSECURITY is enabled, you may also define HASNOSOCKSECURITY. When both are defined, no one but root may list all of anyone else's open files -- only their own open files -- but anyone may list anyone else's open socket files. This option is useful with ntop (http://www.ntop.org). .CAT_MARK grep HASNOSOCKSECURITY $OLD | tail $TA | egrep "^#define" > /dev/null if test $? -eq 0 then echo "HASNOSOCKSECURITY is enabled." SOCKSEC=1 else echo "HASNOSOCKSECURITY is disabled." SOCKSEC=0 fi END=0 while test $END -eq 0 do echo "" if test $SOCKSEC -eq 1 then echo $EO "Disable HASNOSOCKSECURITY (y|n) [n]? $EC" else echo $EO "Enable HASNOSOCKSECURITY (y|n) [n]? $EC" fi read ANS EXCESS if test "X$ANS" = "Xy" -o "X$ANS" = "XY" then echo "" if test $SOCKSEC -eq 1 then SOCKSEC=0 echo "HASNOSOCKSECURITY will be disabled." else SOCKSEC=1 echo "HASNOSOCKSECURITY will be enabled." fi END=1 else if test "X$ANS" = "Xn" -o "X$ANS" = "XN" -o "X$ANS" = "X" then echo "" echo "HASNOSOCKSECURITY will not be changed." END=1 else echo "" echo "Please answer y|n [n]." fi fi done else SOCKSEC=0 fi # Process WARNINGSTATE. cat << .CAT_MARK ===================================================================== When WARNINGSTATE is enabled, lsof will will issue whatever warning messages it finds necessary. When WARNINGSTATE is disabled, lsof will issue no warning messages. For individual uses of lsof, -w disables warning state and +w enables it. .CAT_MARK grep WARNINGSTATE $OLD | tail $TA | egrep "^#define" > /dev/null if test $? -eq 0 then echo "WARNINGSTATE is disabled." WST=0 else echo "WARNINGSTATE is enabled." WST=1 fi END=0 NWST=$WST while test $END -eq 0 do echo "" if test $NWST -eq 0 then echo $EO "Enable WARNINGSTATE? (y|n) [n]? $EC" else echo $EO "Disable WARNINGSTATE? (y|n) [n]? $EC" fi read ANS EXCESS if test "X$ANS" = "Xy" -o "X$ANS" = "XY" then echo "" if test $NWST -eq 0 then echo "WARNINGSTATE will be enabled." NWST=1 else echo "WARNINGSTATE will be disabled." NWST=0 fi END=1 else if test "X$ANS" = "Xn" -o "X$ANS" = "XN" -o "X$ANS" = "X" then echo "" echo "WARNINGSTATE will not be changed." END=1 else echo "" echo "Please answer y|n [n]." fi fi done # Process WARNDEVACCESS, unless the dialect's machine.h header file contains # NEVER_WARNDEVACCESS. grep NEVER_WARNDEVACCESS $OLD > /dev/null if test $? -eq 0 then NEVERWDA=1 NWDA=0 else NEVERWDA=0 cat << .CAT_MARK ===================================================================== When WARNDEVACCESS is enabled, lsof will issue warning messages when it can't access nodes in /dev (or /devices), subject to the default or explicit (-w) WARNINGSTATE. When WARNDEVACCESS is disabled, lsof will silently skip nodes in /dev (or /devices) that it can't access. .CAT_MARK grep WARNDEVACCESS $OLD | tail $TA | egrep "^#define" > /dev/null if test $? -eq 0 then echo "WARNDEVACCESS is enabled." WDA=1 else echo "WARNDEVACCESS is disabled." WDA=0 fi END=0 NWDA=$WDA while test $END -eq 0 do echo "" if test $NWDA -eq 1 then echo $EO "Disable WARNDEVACCESS (y|n) [n]? $EC" else echo $EO "Enable WARNDEVACCESS (y|n) [n]? $EC" fi read ANS EXCESS if test "X$ANS" = "Xy" -o "X$ANS" = "XY" then echo "" if test $NWDA -eq 1 then echo "WARNDEVACCESS will be disabled." NWDA=0 else echo "WARNDEVACCESS will be enabled." NWDA=1 fi END=1 else if test "X$ANS" = "Xn" -o "X$ANS" = "XN" -o "X$ANS" = "X" then echo "" echo "WARNDEVACCESS will not be changed." END=1 else echo "" echo "Please answer y|n [n]." fi fi done fi # Process HASDCACHE, unless the dialect's machine.h header file contains # NEVER_HASDCACHE. ENVV="" ENVN=0 PDCV="" PDCN=0 PDCPV="" PDCPN=0 SDCV="" SDCN=0 grep NEVER_HASDCACHE $OLD > /dev/null if test $? -eq 0 then NEVERDC=1 CDC=0 DC=0 NDC=0 else NEVERDC=0 cat << .CAT_MARK ===================================================================== When HASDCACHE is enabled, lsof will write a device cache file that contains information about the nodes in /dev (or /devices). The options HASENVDC, HASPERSDC, HASPERSDCPATH, and HASSYSDC define the device cache file path. When HASDCACHE is disabled, lsof won't write a device cache file. Consult the 00DCACHE and 00FAQ files of the lsof distribution for more information. .CAT_MARK grep HASDCACHE $OLD | tail $TA | egrep "^#define" > /dev/null if test $? -eq 0 then echo "HASDCACHE is enabled." DC=1 else echo "HASDCACHE is disabled." DC=0 fi END=0 NDC=$DC while test $END -eq 0 do echo "" if test $NDC -eq 1 then echo $EO "Disable HASDCACHE (y|n) [n]? $EC" else echo $EO "Enable HASDCACHE (y|n) [n]? $EC" fi read ANS EXCESS if test "X$ANS" = "Xy" -o "X$ANS" = "XY" then echo "" if test $NDC -eq 1 then echo "HASDCACHE will be disabled." NDC=0 else echo "HASDCACHE will be enabled." NDC=1 fi END=1 else if test "X$ANS" = "Xn" -o "X$ANS" = "XN" -o "X$ANS" = "X" then echo "" echo "HASDCACHE will not be changed." END=1 else echo "" echo "Please answer y|n [n]." fi fi done # See if other device cache options need to be declared. if test $DC -eq 1 -a $NDC -eq 1 then cat << .CAT_MARK ===================================================================== You have decided that HASDCACHE should be defined. There are other definitions associated with HASDCACHE that specify options for the formation of the device cache file path. You may change them. Consult the 00DCACHE and 00FAQ files of the lsof distribution for more information. The current path options are: .CAT_MARK grep HASENVDC $OLD | tail $TA | egrep "^#define" egrep "HASPERSDC$|HASPERSDC[ ]" $OLD | tail $TA | egrep "^#define" grep HASPERSDCPATH $OLD | tail $TA | egrep "^#define" grep HASSYSDC $OLD | tail $TA | egrep "^#define" END=0 while test $END -eq 0 do echo "" echo $EO "Do you want to change path options (y|n) [n]? $EC" read ANS EXCESS if test "X$ANS" = "Xy" -o "X$ANS" = "XY" then CDC=1 END=1 else if test "X$ANS" = "Xn" -o "X$ANS" = "XN" then CDC=0 END=1 else if test "X$ANS" = "X" then echo "" echo "The path options will not be changed." CDC=0 END=1 else echo "" echo "Please answer y|n [n]." fi fi fi done else CDC=0 fi if test \( $NDC -eq 1 -a $DC -eq 0 \) -o \( $DC -eq 1 -a $CDC -eq 1 \) then cat << .CAT_MARK ===================================================================== You may specify for HASENVDC the name of the environment variable from which lsof should take the device cache file path for non-root users. Press ENTER to use the current value of HASENVDC: .CAT_MARK echo $EO " $EC" TMP1=`grep HASENVDC $OLD | tail $TA | egrep "^#define"` if test "X$TMP1" != "X" then TMP1=`echo "$TMP1" | sed 's/^#define[ ]HASENVDC[ ]"\([^"]*\)".*$/\1/'` echo "$TMP1" else echo "no current HASENVDC value" fi END=0 GV=0 while test $END -eq 0 do echo "" echo $EO "Do you want to define a name for HASENVDC (y|n) [n]? $EC" read ANS EXCESS if test "X$ANS" = "Xn" -o "X$ANS" = "XN" then ENVV="" END=1 else if test "X$ANS" = "Xy" -o "X$ANS" = "XY" then GV=1 END=1 else if test "X$ANS" = "X" then echo "" echo "HASENVDC will not be changed." ENVV=$TMP1 END=1 else echo "" echo "Please answer y|n [n]." fi fi fi done if test $GV -eq 1 then echo "" echo $EO "Please enter the HASENVDC name (no quotes): $EC" read TMP1 EXCESS ENVV=`echo $TMP1 | sed 's/^\"//' | sed 's/\"$//'` if test "X$ENVV" = "X" then ENVN=1 fi fi cat << .CAT_MARK ===================================================================== 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: .CAT_MARK echo $EO " $EC" TMP1=`egrep "HASPERSDC$|HASPERSDC[ ]" $OLD | tail $TA | egrep "^#define"` if test "X$TMP1" != "X" then TMP1=`echo "$TMP1" | sed 's/^#define[ ]HASPERSDC[ ]"\([^"]*\)".*$/\1/'` echo "$TMP1" else echo "no current HASPERSDC format" fi END=0 GV=0 while test $END -eq 0 do echo "" echo $EO "Do you want to define a format for HASPERSDC (y|n) [n]? $EC" read ANS EXCESS if test "X$ANS" = "Xn" -o "X$ANS" = "XN" then END=1 else if test "X$ANS" = "Xy" -o "X$ANS" = "XY" then GV=1 END=1 else if test "X$ANS" = "X" then echo "" echo "HASPERSDC will not be changed." PDCV=$TMP1 END=1 else echo "" echo "Please answer y|n [n]." fi fi fi done if test $GV -eq 1 then echo "" echo $EO "Please enter the HASPERSDC format (no quotes): $EC" read TMP1 EXCESS PDCV=`echo $TMP1 | sed 's/^\"//' | sed 's/\"$//'` if test "X$PDCV" = "X" then PDCN=1 fi fi cat << .CAT_MARK ===================================================================== Specify for HASPERSDCPATH the name of the environment variable from which lsof should take a path name component to insert at the %p conversion in the HASPERSDC format. Consult the 00FAQ and 00DCACHE files of the lsof distribution for more information on HASPERSDCPATH usage. Press ENTER to use the current value for HASPERSDCPATH: .CAT_MARK echo $EO " $EC" TMP1=`grep HASPERSDCPATH $OLD | tail $TA | egrep "^#define"` if test "X$TMP1" != "X" then TMP1=`echo "$TMP1" | sed 's/^#define[ ]HASPERSDCPATH[ ]"\([^"]*\)".*$/\1/'` echo "$TMP1" else echo "no current HASPERSDCPATH value" fi END=0 GV=0 while test $END -eq 0 do echo "" echo $EO "Do you want to change HASPERSDCPATH (y|n) [n]? $EC" read ANS EXCESS if test "X$ANS" = "Xn" -o "X$ANS" = "XN" -o "X$ANS" = "X" then echo "" echo "HASPERSDCPATH will not be changed." PDCPV=$TMP1 END=1 else if test "X$ANS" = "Xy" -o "X$ANS" = "XY" then GV=1 END=1 else echo "" echo "Please answer y|n [n]." fi fi done if test $GV -eq 1 then echo "" echo $EO "Please enter the HASPERSDCPATH name (no quotes): $EC" read TMP1 EXCESS PDCPV=`echo $TMP1 | sed 's/^\"//' | sed 's/\"$//'` if test "X$PDCPV" = "X" then PDCPN=1 fi fi cat << .CAT_MARK ===================================================================== Specify for HASSYSDC the system-wide device cache file path. Press ENTER to use the current HASSYSDC value: .CAT_MARK echo $EO " $EC" TMP1=`grep HASSYSDC $OLD | tail $TA | egrep "^#define"` if test "X$TMP1" != "X" then TMP1=`echo "$TMP1" | sed 's/^#define[ ]HASSYSDC[ ]"\([^"]*\)".*$/\1/'` echo "$TMP1" else echo "no current HASSYSDC value" fi END=0 GV=0 while test $END -eq 0 do echo "" echo $EO "Do you want to define a system-device path (y|n) [n]? $EC" read ANS EXCESS if test "X$ANS" = "Xn" -o "X$ANS" = "XN" then END=1 else if test "X$ANS" = "Xy" -o "X$ANS" = "XY" then GV=1 END=1 else if test "X$ANS" = "X" then echo "" echo "No HASSYSDC change will be made." SDCV=$TMP1 END=1 else echo "" echo "Please answer y|n [n]." fi fi fi done if test $GV -eq 1 then echo "" echo $EO "Please enter the system-wide path (no quotes): $EC" read TMP1 EXCESS SDCV=`echo $TMP1 | sed 's/^\"//' | sed 's/\"$//'` if test "X$SDCV" = "X" then SDCN=1 fi fi fi fi # If HASXOPT is defined, and HASXOPT_ROOT is mentioned, # ask about changing HASXOPT_ROOT. HXRC=0 grep HASXOPT $OLD | tail $TA | egrep "^#define" > /dev/null if test $? -eq 0 then grep HASXOPT_ROOT $OLD > /dev/null if test $? -eq 0 then cat << .CAT_MARK ===================================================================== HASXOPT is defined. If the dialect for which you are customizing appears in the following list, you may want to change the definition of HASXOPT_ROOT to restrict the use of the X option to lsof processes whose real user ID is root, or enable use of it by all user IDs. AIX the -X option enables the risky operation of letting lsof read library entry structures with readx(). If HASXOPT_ROOT is defined, only processes whose real user ID is root will be allowed to use -X. If HASXOPT_ROOT is undefined, any process will be allowed to use -X. Consult the 00FAQ file of the lsof distribution for more information on why readx() may be risky. .CAT_MARK grep HASXOPT_ROOT $OLD | tail $TA | egrep "^#define" > /dev/null if test $? -eq 0 then echo "HASXOPT_ROOT is defined." HXR="undefine" HXRS=1 else echo "HASXOPT_ROOT is not defined." HXR="define" HXRS=0 fi END=0 while test $END -eq 0 do echo "" echo $EO "Do you want to $HXR HASXOPT_ROOT (y|n) [n]? $EC" read ANS EXCESS if test "X$ANS" = "Xy" -o "X$ANS" = "XY" then HXRA=1 END=1 else if test "X$ANS" = "Xn" -o "X$ANS" = "XN" -o "X$ANS" = "X" then echo "" echo "HASXOPT_ROOT will not be changed." HXRA=0 END=1 else echo "" echo "Please answer y|n [n]." fi fi done if test $HXRA -eq 1 then HXRC=1 fi fi fi # Process HASKERNIDCK. Skip processing for selected dialect directories. case $DialDir in linux/proc) NIDCK=0 ;; *) cat << .CAT_MARK ===================================================================== When HASKERNIDCK is enabled, lsof compares the identity of the kernel where it was built to the identity of the kernel where it is running. This check can detect an lsof executable inappropriate for the system on which it is being run. The kernel identity check can take considerable time on some UNIX dialects -- e.g., AIX -- so there may be occasions when it is desirable to disable it, in spite of the increased risk of using an inappropriate lsof executable. .CAT_MARK grep HASKERNIDCK $OLD | tail $TA | grep "^#define" > /dev/null if test $? -eq 0 then echo "HASKERNIDCK is enabled." IDCK=1 else echo "HASKERNIDCK is disabled." IDCK=0 fi END=0 NIDCK=$IDCK while test $END -eq 0 do echo "" if test $NIDCK -eq 1 then echo $EO "Disable HASKERNIDCK (y|n) [n]? $EC" else echo $EO "Enable HASKERNIDCK (y|n) [n]? $EC" fi read ANS EXCESS if test "X$ANS" = "Xy" -o "X$ANS" = "XY" then echo "" if test $NIDCK -eq 1 then NIDCK=0 echo "HASKERNIDCK will be disabled." else NIDCK=1 echo "HASKERNIDCK will be enabled." fi END=1 else if test "X$ANS" = "Xn" -o "X$ANS" = "XN" -o "X$ANS" = "X" then echo "" echo "HASKERNIDCK will not be changed." END=1 NIDCK=$IDCK else echo "" echo "Please answer y|n [n]." fi fi done ;; esac # Initialize new machine.h. rm -f $NEW cp $OLD $NEW chmod 0644 $NEW echo "" >> $NEW echo "/*" >> $NEW echo $EO " * Added by Customize on $EC" >> $NEW date >> $NEW echo " */" >> $NEW echo "" >> $NEW # Change HASSECURITY and HASNOSOCKSECURITY, as required. echo "#undef HASSECURITY" >> $NEW echo "#undef HASNOSOCKSECURITY" >> $NEW if test $NSEC -eq 1 then echo "#define HASSECURITY 1" >> $NEW if test $SOCKSEC -eq 1 then echo "#define HASNOSOCKSECURITY 1" >> $NEW fi fi # Change WARNDEVACCESS, as required. if test $NEVERWDA -eq 0 then echo "#undef WARNDEVACCESS" >> $NEW if test $NWDA -eq 1 then echo "#define WARNDEVACCESS 1" >> $NEW fi fi # Change WARNINGSTATE, as required. echo "#undef WARNINGSTATE" >> $NEW if test $NWST -eq 0 then echo "#define WARNINGSTATE 1" >> $NEW fi # Change device cache definitions, as required. if test \( $NDC -eq 1 -a $DC -eq 0 \) -o \( $DC -eq 1 -a $CDC -eq 1 \) then if test "X$ENVV" = "X" -a "X$PDCV" = "X" -a "X$SDCV" = "X" then cat << .CAT_MARK FATAL: HASDCACHE is defined, but there is no definition for any of HASENVDC, HASPERSDC, or HASSYSDC No new machine.h has been created. Customize quits. Restart Customize and define at least one of HASENVDC, HASPERSDC, or HASSYSDC. .CAT_MARK rm -f $NEW exit 1 fi fi if test "X$PDCV" != "X" then echo "$PDCV" | grep "%p" > /dev/null if test $? -eq 0 -a $PDCPN -eq 1 then cat << .CAT_MARK FATAL: HASDCACHE is defined and HASPERSDC has a %p conversion, but HASPERSDCPATH is NULL. No new machine.h has been created. Customize quits. Restart Customize and define HASPERSDCPATH. .CAT_MARK rm -f $NEW exit 1 fi fi echo "#undef HASDCACHE" >> $NEW if test $NEVERDC -eq 1 then echo "#undef HASENVDC" >> $NEW echo "#undef HASPERSDC" >> $NEW echo "#undef HASPERSDCPATH" >> $NEW echo "#undef HASSYSDC" >> $NEW else if test $NDC -eq 1 then echo "#define HASDCACHE 1" >> $NEW if test "X$ENVV" != "X" -o $ENVN -eq 1 then echo "#undef HASENVDC" >> $NEW if test $ENVN -eq 0 then echo "#define HASENVDC \"$ENVV\"" >> $NEW fi fi if test "X$PDCV" != "X" -o $PDCN -eq 1 then echo "#undef HASPERSDC" >> $NEW if test $PDCN -eq 0 then echo "#define HASPERSDC \"$PDCV\"" >> $NEW fi fi if test "X$PDCPV" != "X" -o $PDCPN -eq 1 then echo "#undef HASPERSDCPATH" >> $NEW if test $PDCPN -eq 0 then echo "#define HASPERSDCPATH \"$PDCPV\"" >> $NEW fi fi if test "X$SDCV" != "X" -o $SDCN -eq 1 then echo "#undef HASSYSDC" >> $NEW if test $SDCN -eq 0 then echo "#define HASSYSDC \"$SDCV\"" >> $NEW fi fi fi fi # Change HASXOPT_ROOT, as required. if test $HXRC -eq 1 then if test $HXRS -eq 1 then echo "#undef HASXOPT_ROOT" >> $NEW else echo "#define HASXOPT_ROOT 1" >> $NEW fi fi # Change HASKERNIDCK, as required. echo "#undef HASKERNIDCK" >> $NEW if test $NIDCK -eq 1 then echo "#define HASKERNIDCK 1" >> $NEW fi # Replace the current machine.h with the new one, as requested. echo "" echo "=====================================================================" echo "" echo "A new $OLD file has been created in \"$NEW\"." END=0 while test $END -eq 0 do echo "" echo "Do you want to rename $OLD to ${OLD}.old and replace it with" echo $EO "$NEW (y|n) [y]? $EC" read ANS EXCESS if test "X$ANS" = "Xn" -o "X$ANS" = "XN" then END=1 else if test "X$ANS" = "Xy" -o "X$ANS" = "XY" -o "X$ANS" = "X" then rm -f ${OLD}.old mv $OLD ${OLD}.old mv $NEW $OLD END=1 else echo "" echo "Please answer y|n [y]." fi fi done echo "" echo "You may now run the make command -- e.g.," echo "" echo " $ make" echo "" exit 0 #LAST_LINE lsof-4.86+dfsg.orig/tests/0000755000175000017500000000000011741064217015623 5ustar nicholasnicholaslsof-4.86+dfsg.orig/tests/LTunix.c0000444000175000017500000001774611021756742017231 0ustar nicholasnicholas/* * LTunix.c -- Lsof Test UNIX domain socket test * * 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. */ #ifndef lint static char copyright[] = "@(#) Copyright 2002 Purdue Research Foundation.\nAll rights reserved.\n"; #endif #include "LsofTest.h" #include "lsof_fields.h" #include #include /* * Local definitions */ #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 */ char *Path[2] = {(char *)NULL, (char *)NULL}; /* socket pair paths */ /* * Local function prototypes */ _PROTOTYPE(static void cleanup,(void)); _PROTOTYPE(static char *FindUsocks,(void)); /* * Main program */ int main(argc, argv) 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. */ if ((Pn = strrchr(argv[0], '/'))) Pn++; else Pn = argv[0]; MyPid = getpid(); (void) printf("%s ... ", Pn); (void) fflush(stdout); PrtMsg((char *)NULL, Pn); /* * Process arguments. */ if (ScanArg(argc, argv, "h", Pn)) xv = 1; if (xv || LTopt_h) { (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. */ if ((em = IsLsofExec())) (void) PrtMsgX(em, Pn, cleanup, 1); if ((em = CanRdKmem())) (void) PrtMsgX(em, Pn, cleanup, 1); /* * Construct the socket paths. */ #if defined(USE_GETCWD) if (!getcwd(cwd, sizeof(cwd))) #else /* ! defined(USE_GETCWD) */ if (!getwd(cwd)) #endif /* defined(USE_GETCWD) */ { 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); } 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]); } /* * 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"; print_errno_by_ti: (void) snprintf(buf, sizeof(buf) - 1, "ERROR!!! %s(%s) failure", em, Path[ti]); buf[sizeof(buf) - 1] = '\0'; em = buf; 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); } } /* * 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; } } /* * 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); } /* * cleanup() -- release resources */ 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; } } } /* * 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. */ ff[0] = ff[1] = ti = 0; opv[ti++] = "-aU"; opv[ti++] = "-p"; (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) opv[ti++] = "-C"; #endif /* defined(USE_LSOF_C_OPT) */ opv[ti] = (char *)NULL; if ((cem = ExecLsof(opv))) 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; } } } } /* * 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); } return(pem); } lsof-4.86+dfsg.orig/tests/LTsock.c0000444000175000017500000005064510363153551017175 0ustar nicholasnicholas/* * LTsock.c -- Lsof Test IPv4 sockets * * 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. */ #ifndef lint static char copyright[] = "@(#) Copyright 2002 Purdue Research Foundation.\nAll rights reserved.\n"; #endif #include "LsofTest.h" #include "lsof_fields.h" #include #include #include #include #include /* * 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 */ #if defined(LT_DIAL_aix) /* * AIX-specific items */ #undef LT_SOCKLEN_T #define LT_SOCKLEN_T size_t #endif /* defined(LT_DIAL_aix) */ #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 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 defined(LT_DIAL_ou) /* * OpenUNIX-specific items */ #undef LT_SOCKLEN_T #define LT_SOCKLEN_T size_t #endif /* defined(LT_DIAL_ou) */ #if defined(LT_DIAL_uw) /* * UnixWare-specific items */ #undef LT_SOCKLEN_T #define LT_SOCKLEN_T size_t #endif /* defined(LT_DIAL_uw) */ /* * Local definitions */ #define ALARMTM 30 /* alarm timer */ #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 */ #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 */ } 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 */ /* * 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)); /* * Main program */ int main(argc, argv) 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. */ if ((Pn = strrchr(argv[0], '/'))) Pn++; else Pn = argv[0]; MyPid = getpid(); (void) printf("%s ... ", Pn); (void) fflush(stdout); PrtMsg((char *)NULL, Pn); /* * Initalize 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; } /* * Process arguments. */ if (ScanArg(argc, argv, "h", Pn)) xv = 1; if (xv || LTopt_h) { (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. */ if ((cem = IsLsofExec())) (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. */ if (gethostname(hnm, sizeof(hnm) - 1)) { 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; } (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); Myad.sin_family = hp->h_addrtype; /* * 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); } /* * 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; } /* * 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)); ti = LT_SRVR; FdPara[ti].pid = MyPid; if (bind(Ssock, (struct sockaddr *)&ba, sizeof(ba)) < 0) { 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; } (void) memcpy((void *)&FdPara[ti].sa, (void *)&ca, sizeof(FdPara[ti].sa)); if (listen(Ssock, 1) < 0) { ep = "listen"; goto print_errno_by_ti; } /* * 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); case (pid_t)-1: /* * 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; } } /* * 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); tsfd = FdPara[LT_SRVR].fd = accept(Ssock, (struct sockaddr *)&aa, &sal); (void) alarm(0); (void) signal(SIGALRM, SIG_DFL); if (tsfd < 0) { ep = "accept"; goto print_errno_by_ti; } (void) snprintf(buf, bufl - 1, "%d", tsfd); buf[bufl - 1] = '\0'; if (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); 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. */ 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); } } /* * 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); if ((cem = FindSock(LT_FBYIP))) PrtMsgX(cem, Pn, CleanupSrvr, 1); if ((cem = FindSock(LT_FBYPORT))) 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 (pem) (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 */ if ((tfd = FdPara[LT_CLNT].fd) >= 0) { (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 */ if ((Ssock >= 0) && (Ssock != FdPara[LT_SRVR].fd)) { (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 (CPid > 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 */ { 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; 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; 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; default: (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. */ #if defined(USE_LSOF_C_OPT) opv[ti++] = "-C"; #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; } } } /* * Clean up and return. */ (void) StopLsof(); return(pem); } /* * HandleClntAlarm() -- handle client alarm */ static SIGHANDLER_T HandleClntAlarm(sig) int sig; /* the signal (SIGALRM) */ { (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) */ { (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 */ { 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; } if (FdPara[LT_SRVR].fd >= 0) { (void) close(FdPara[LT_SRVR].fd); FdPara[LT_SRVR].fd = -1; } /* * Bind to the local address. */ (void) memcpy((void *)&ba, (void *)&Myad, sizeof(ba)); if (bind(fd, (struct sockaddr *)&ba, sizeof(ba)) < 0) { em = "bind"; 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); } /* * 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); if (cr) { em = "connect"; goto client_errno; } /* * Sleep until the socket closes or the parent kills the process. */ for (br = 0; br >= 0;) { sleep(1); br = read(fd, buf, bufl); } (void) CleanupClnt(); exit(0); } lsof-4.86+dfsg.orig/tests/LTlock.c0000444000175000017500000004177210360777645017204 0ustar nicholasnicholas/* * LTlock.c -- Lsof Test locking tests * * 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. */ #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) /* * AIX-specific items */ #define USE_FCNTL #endif /* defined(LT_DIAL_aix) */ #if defined(LT_DIAL_bsdi) /* * BSDI-specific items */ #define USE_FCNTL #endif /* defined(LT_DIAL_bsdi) */ #if defined(LT_DIAL_darwin) /* * Darwin-specific items */ /* * There is no Darwin USE_* definition, because lock support in lsof for * Darwin is inadequate for this test. */ #endif /* defined(LT_DIAL_darwin) */ #if defined(LT_DIAL_du) /* * DEC_OSF/1|Digital_UNIX|Tru64_UNIX-specific items */ #define USE_FCNTL #endif /* defined(LT_DIAL_du) */ #if defined(LT_DIAL_freebsd) /* * FreeBSD-specific items */ #define USE_FCNTL #endif /* defined(LT_DIAL_freebsd) */ #if defined(LT_DIAL_linux) /* * Linux-specific items */ #define USE_FCNTL #endif /* defined(LT_DIAL_linux) */ #if defined(LT_DIAL_netbsd) /* * NetBSD-specific items */ #define USE_FCNTL #endif /* defined(LT_DIAL_netbsd) */ #if defined(LT_DIAL_openbsd) /* * OpenBSD-specific items */ #define USE_FCNTL #endif /* defined(LT_DIAL_openbsd) */ #if defined(LT_DIAL_hpux) /* * HP-UX-specific items */ #define USE_FCNTL #endif /* defined(LT_DIAL_hpux) */ #if defined(LT_DIAL_ns) /* * NEXTSTEP-specific items */ #define USE_FLOCK #endif /* defined(LT_DIAL_ns) */ #if defined(LT_DIAL_osr) /* * OSR-specific items */ #define USE_FCNTL #endif /* defined(LT_DIAL_osr) */ #if defined(LT_DIAL_ou) /* * OpenUNIX-specific items */ #define USE_FCNTL #endif /* defined(LT_DIAL_ou) */ #if defined(LT_DIAL_openbsd) /* * OpenBSD-specific items */ #define USE_FCNTL #endif /* defined(LT_DIAL_openbsd) */ #if defined(LT_DIAL_solaris) /* * Solaris-specific items */ #define USE_FCNTL #endif /* defined(solaris) */ #if defined(LT_DIAL_uw) /* * UnixWare-specific items */ #define USE_FCNTL #endif /* defined(LT_DIAL_uw) */ #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 */ { char *pn; /* program name */ /* * Get program name and issue error message. */ if ((pn = (char *)strrchr(argv[0], '/'))) pn++; else pn = argv[0]; (void) printf("%s ... %s\n", pn, LT_DONT_DO_TEST); return(0); } #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 */ /* * 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 */ /* * 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)); /* * Main program for dialects that support locking tests. */ int main(argc, argv) 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. */ if ((Pn = strrchr(argv[0], '/'))) Pn++; else Pn = argv[0]; MyPid = getpid(); (void) printf("%s ... ", Pn); (void) fflush(stdout); (void) PrtMsg((char *)NULL, Pn); /* * Process arguments. */ if (ScanArg(argc, argv, "hp:", Pn)) 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); } /* * 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); /* * 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); } /* * Fill buffer for writing to the test file. */ for (ti = 0; ti < sizeof(buf); ti++) { 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); } /* * 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; } /* * Fsync() the file. */ if (fsync(Fd)) { (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. */ 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); } /* * 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); if ((tstW = tstwlsof("-w", "W"))) (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); if ((em = lkfile(FULL_SH_LOCK))) (void) PrtMsgX(em, Pn, cleanup, 1); if ((tstR = tstwlsof("-w", "R"))) (void) PrtMsg(tstR, Pn); # if defined(USE_FLOCK) /* * If using flock(), skip the byte lock tests. */ tstr = tstw = (char *)NULL; # endif /* defined(USE_FLOCK) */ # 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); if ((em = lkfile(PART_EX_LOCK))) (void) PrtMsgX(em, Pn, cleanup, 1); if ((tstw = tstwlsof("-w", "w"))) (void) PrtMsg(tstw, Pn); if ((em = unlkfile(PART_EX_LOCK))) (void) PrtMsgX(em, Pn, cleanup, 1); if ((em = lkfile(PART_SH_LOCK))) (void) PrtMsgX(em, Pn, cleanup, 1); if ((tstr = tstwlsof("-w", "r"))) (void) PrtMsg(tstr, Pn); # endif /* defined(USE_FCNTL) */ /* * Compute exit value and exit. */ if (tstr || tstR || tstw || tstW) { tcp = (char *)NULL; xv = 1; } else { tcp = "OK"; xv = 0; } (void) PrtMsgX(tcp, Pn, cleanup, xv); return(0); } /* * cleanup() -- release resources */ static void cleanup() { if (Fd >= 0) { (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 */ { 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; case FULL_SH_LOCK: fl.l_type = F_RDLCK; break; case PART_EX_LOCK: 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; default: (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(). */ if (fcntl(Fd, F_SETLK, &fl) != -1) 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) { case FULL_EX_LOCK: flf = LOCK_EX; break; case FULL_SH_LOCK: flf = LOCK_SH; break; case PART_EX_LOCK: case PART_SH_LOCK: 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)); } /* * 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)); buf[sizeof(buf) - 1] = '\0'; 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 */ { 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. */ 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); } /* * 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. */ ti = 0; if (opt && *opt) opv[ti++] = opt; #if defined(USE_LSOF_C_OPT) opv[ti++] = "-C"; #endif /* defined(USE_LSOF_C_OPT) */ opv[ti++] = Path; opv[ti] = (char *)NULL; if ((cem = ExecLsof(opv))) 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; } } (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)); } return(pem); } /* * unlkfile() -- unlock the test file */ static char * unlkfile(ty) 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) { case FULL_EX_LOCK: case FULL_SH_LOCK: break; case PART_EX_LOCK: case PART_SH_LOCK: 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)); } /* * 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)); buf[sizeof(buf) - 1] = '\0'; 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; default: (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(). */ 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) */ } #endif /* !defined(USE_FLOCK) && !defined(USE_FCNTL) */ lsof-4.86+dfsg.orig/tests/CkTestDB0000555000175000017500000000500711335335761017160 0ustar nicholasnicholas#!/bin/sh # # CkTestDB -- see if this dialect is has been tested # # This script builds a line from config.flags in the form of lines in # ./TestDB, (See Add2TestDB.) # # It then compares the line to TestDB. If the line is found, the script # exits. if the line is not found, the script issues a warning and requests # a go-ahead confirmation. # # The script will exit 0 if the test line is in the DB or the go-ahead # confirmation is positive. # # $Id: CkTestDB,v 1.3 2010/01/18 19:02:21 abe Exp abe $ # Check for config.flags. if test ! -r config.cflags then echo "$0: no ./config.cflags file" exit 1 fi # Check for a current data base file. if test ! -r TestDB then echo "$0: no ./TestDB file" exit 1 fi # Form a data base line. new="" for i in `LC_ALL=C sort < config.cflags` do w=`echo $i | sed 's/^-D//'` if test "X$new" = "X" then new=$w else new="$new $w" fi done # See if the line is already in the data base. Exit with success (0), if it is. grep "^$new\$" TestDB > /dev/null 2>&1 if test $? -eq 0 then exit 0 fi # This dialect may never have been validated with the test suite. # If the standard input is not a TTY, quit, because no interaction # is possible. tty -s > /dev/null 2>&1 if test $? -ne 0 then echo "" echo "This suite has not been validated on:" echo "" echo " $new" echo "" exit 1 fi # Establish trap and stty handling. ISIG=":" trap '$ISIG; exit 1' 1 2 3 15 stty -a 2>&1 | grep isig > /dev/null if test $? -eq 0 then stty -a 2>&1 | egrep -e -isig > /dev/null if test $? -eq 0 then ISIG="stty -isig" stty isig fi fi # Establish echo type -- Berkeley or SYSV. j=`echo -n ""` if test "X$j" = "X-n " then EC="\c" EO="" else EC="" EO="-n" fi # Display a validation warning. cat << .CAT_MARK > /dev/tty ================================================================== !!!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. This is the computed identity of this dialect, not found in the test data base file, ./TestDB: .CAT_MARK echo " $new" > /dev/tty END=0 while test $END = 0 do echo "" > /dev/tty echo $EO "Do you want to continue (y|n) [n]? $EC" > /dev/tty read ANS EXCESS if test "X$ANS" = "Xn" -o "X$ANS" = "XN" then exit 1 fi if test "X$ANS" = "Xy" -o "X$ANS" = "XY" then exit 0 else echo "Please answer y or n." > /dev/tty fi done # Should never get here! echo "$0: unexpected failure!" exit 2 lsof-4.86+dfsg.orig/tests/Add2TestDB0000555000175000017500000000301007460002507017356 0ustar nicholasnicholas#!/bin/sh # # Add2TestDB -- add the current test to the lsof test suite DB # # This script saves the current TestDB file in TestDB.old and adds # the words in config.cflags to it. "-D" prefixes on the words are # removed, the words are sorted, and they are joint in a single # line that is catenated to TestDB if it isn't already there. # # $Id: Add2TestDB,v 1.2 2002/04/19 11:53:37 abe Exp $ # Check for config.flags. if test ! -r config.cflags then echo "$0: no ./config.cflags file" exit 1 fi # Check for a current data base file. if test ! -r TestDB then echo "$0: no ./TestDB file" exit 1 fi # Form a new data base line. new="" for i in `sort < config.cflags` do w=`echo $i | sed 's/^-D//'` if test "X$new" = "X" then new=$w else new="$new $w" fi done # See if the new line is already in the data base. grep "$new" TestDB > /dev/null 2>&1 if test $? -eq 0 then echo "\"$new\" is already in TestDB." exit 1 fi # Build a new data base file. if test ! -w TestDB then echo "$0: can't write the following to the end of TestDB:" echo " \"$new\"" exit 1 fi rm -f TestDB.new cp TestDB TestDB.new chmod 644 TestDB.new echo "$new" >> TestDB.new # Archive the current data base file, if possible. if test -d OLD then dt=`date` dtm="========== $dt ==========" if test -r OLD/TestDB then echo "$dtm" >> OLD/TestDB else echo "$dtm" > OLD/TestDB fi cat TestDB >> OLD/TestDB fi # Put the new data base file in place. mv TestDB.new TestDB echo "\"$new\" added to TestDB." exit 0 lsof-4.86+dfsg.orig/tests/LTlib.c0000444000175000017500000006155211021717305016776 0ustar nicholasnicholas/* * LTlib.c -- the lsof test library * * 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. */ #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) */ #if defined(LT_DIAL_aix) /* * AIX-specific items */ #include # if defined(LT_AIXA) && LT_AIXA>=1 /* * Note: the DEVNO64 and ISDEVNO54 #define's come from , but * only when _KERNEL is #define'd. */ #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) */ #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) */ #if defined(LT_DIAL_osr) /* * OpenUNIX-specific items */ #include #endif /* defined(LT_DIAL_osr) */ #if defined(LT_DIAL_ou) /* * OpenUNIX-specific items */ #include #endif /* defined(LT_DIAL_ou) */ #if defined(LT_DIAL_solaris) /* * Solaris-specific items */ #include /* * 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 * . */ # else /* LT_VERS<20501 */ #define LT_MJX 0x3fff /* Avoid 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)) # if defined(LT_K64) /* * Solaris 64 bit kernel */ #undef X2DEV_T #define X2DEV_T unsigned long long #undef XDINDEV #define XDINDEV 16 #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) */ /* * 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) /* * UnixWare-specific items */ #include #endif /* defined(LT_DIAL_uw) */ /* * 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 */ /* * 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 */ /* * 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)); /* * Default major, minor, and unit macros. */ #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(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(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(); if (!strcmp(LsofPath, LT_DEF_LSOF_PATH)) return((char *)NULL); /* * Check /dev/kmem access. */ dn = "/dev/kmem"; if (stat(dn, &sb)) { em = "stat"; 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)); } if ((fd = open(dn, O_RDONLY, 0)) < 0) { em = "open"; goto kmem_error; } (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 ((fd = open(dn, O_RDONLY, 0)) < 0) { em = "open"; goto kmem_error; } (void) close(fd); #endif /* defined(LT_KMEM) */ return((char *)NULL); } /* * closepipe() -- close pipe from lsof */ 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; } } /* * 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 *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"); if (!ldev) return("ERROR!!! no ConvLsofDev() result pointer"); if (strncmp(dev, "0x", 2)) 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. */ ldev->maj = (unsigned int)major_X(dp, &em); if (em) return(em); ldev->min = (unsigned int)minor_X(dp, &em); if (em) return(em); ldev->unit = (unsigned int)unit_X(dp, &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 */ { /* * Check function arguments. */ if (!dev) return("ERROR!!! no ConvStatDev() device"); if (!ldev) 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); } /* * 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 */ { 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"); if (!opt) return("ERROR!!! no ExecLsof() option list"); for (optc = 0, tcpp = opt; *tcpp; optc++, tcpp++) ; /* * Make sure lsof is executable. */ if ((em = IsLsofExec())) 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)); } /* * 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; } 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++; } } 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. */ 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)); 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"); } /* * 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); } /* * 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 */ if (LsofPath) return; if ((tcp = getenv("LT_LSOF_PATH"))) LsofPath = MkStrCpy(tcp, &ti); else LsofPath = LT_DEF_LSOF_PATH; } /* * GetOpt() -- Local get option * * Borrowed from lsof's main.c source file. * * 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, 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() */ *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; } /* * 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); } 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); } 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); } 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; } /* * Return the option character. */ return(c); } /* * IsLsofExec() -- see if lsof is executable */ char * IsLsofExec() { char buf[2048]; /* temporary buffer */ int len; /* temporary length */ (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)); } return((char *)NULL); } /* * LTlibClean() -- clean up LTlib resource accesses */ void LTlibClean() { (void) StopLsof(); } /* * MkStrCpy() -- make string copy */ char * MkStrCpy(src, len) char *src; /* string source to copy */ int *len; /* returned length allocation */ { char *rp; /* return pointer */ int srclen; /* source string length */ if (!src) { (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) 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 */ { 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; } /* * Process the message. */ if (MsgStat) (void) printf("%s", pfx); if (mp && *mp) { (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 */ { if (mp) PrtMsg(mp, pn); if (f) (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 */ { 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); if (!nf) { *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. */ for (ti = 0, tfop = Fo; (ti < Ufo); ti++, tfop++) { 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). */ 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++) { /* * 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); } } /* * 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); } *nf = Ufo; *em = (char *)NULL; 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 */ { 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; } /* * 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); } } for (; GOx1 < ac; GOx1++) { /* * Report extraneous arguments. */ rv = 1; (void) snprintf(embf, sizeof(embf) - 1, "ERROR!!! extraneous option: \"%s\"", av[GOx1]); PrtMsg(embf, pn); } return(rv); } /* * StopLsof() -- stop a running lsof process and close the pipe from it */ 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; } (void) closepipe(); } /* * x2dev() -- convert hex string to device number */ static X2DEV_T x2dev(x, em) 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 */ if (!x || !*x) { *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); } /* * 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); } /* * Return result and no error indication. */ *em = (char *)NULL; return(dev); } lsof-4.86+dfsg.orig/tests/00README0000444000175000017500000000563407455352577016671 0ustar nicholasnicholas .../lsof_/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 lsof-4.86+dfsg.orig/tests/LTnlink.c0000444000175000017500000003450011622767403017347 0ustar nicholasnicholas/* * LTnlink.c -- Lsof Test nlink tests * * 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. */ #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 */ /* * Dialect-specific items */ #if defined(LT_DIAL_darwin) /* * Darwin-specific items */ # if defined(LT_KMEM) #undef DO_TEST # endif /* defined(LT_KMEM) */ #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 */ /* * 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)); /* * Main program */ int main(argc, argv) 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. */ if ((Pn = strrchr(argv[0], '/'))) Pn++; else Pn = argv[0]; MyPid = getpid(); (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) */ /* * 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. */ 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); } /* * 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); 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. */ 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; } /* * 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); } /* * 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. */ if ((em = ConvStatDev(&tfsb.st_dev, &tfdc))) PrtMsgX(em, Pn, cleanup, 1); (void) snprintf(ibuf, sizeof(ibuf) - 1, "%u", (unsigned int)tfsb.st_ino); ibuf[sizeof(szbuf) - 1] = '\0'; (void) snprintf(xlnk, sizeof(xlnk) - 1, "%d", (int)tfsb.st_nlink); ibuf[sizeof(szbuf) - 1] = '\0'; (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); 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; } /* * 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. */ 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/\".\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); } /* * cleanup() -- release resources */ static void cleanup() { if (Fd >= 0) { (void) close(Fd); Fd = -1; } if (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 */ { 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); *ff = 0; /* * Complete the option vector and start lsof execution. */ ti = 0; if (opt && *opt) opv[ti++] = opt; #if defined(USE_LSOF_C_OPT) opv[ti++] = "-C"; #endif /* defined(USE_LSOF_C_OPT) */ if (strcmp(xlnk, "0")) opv[ti++] = Path; opv[ti] = (char *)NULL; if ((cem = ExecLsof(opv))) { if (ie) return((char *)NULL); return(cem); } /* * 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); } } /* * 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 (ie) return((char *)NULL); return(pem); } lsof-4.86+dfsg.orig/tests/LTszoff.c0000444000175000017500000003031311033720141017341 0ustar nicholasnicholas/* * LTszoff.c -- Lsof Test small file (< 32 bits) size and offset tests * * 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. */ #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 */ #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) */ /* * 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 */ /* * 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 */ /* * Local function prototypes */ _PROTOTYPE(static void cleanup,(void)); _PROTOTYPE(static char *testlsof,(int tt, char *opt, char *xval)); /* * Main program */ int main(argc, argv) 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. */ if ((Pn = strrchr(argv[0], '/'))) Pn++; else Pn = argv[0]; MyPid = getpid(); (void) printf("%s ... ", Pn); (void) fflush(stdout); PrtMsg((char *)NULL, Pn); /* * 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); } #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. */ if ((em = IsLsofExec())) (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. */ if (!(Path = LTopt_p)) { (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); } /* * Write the test file to its expected size. */ for (ti = 0; ti < sizeof(buf); ti++) { 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; } } /* * Fsync() the file. */ if (fsync(Fd)) { (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); xbuf[sizeof(xbuf) - 1] = '\0'; if ((tstsz = testlsof(TYTST_SZ, "-s", xbuf))) (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); } else { 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. */ if (tstsz || tst0to || tst0xo) { tcp = (char *)NULL; xv = 1; } else { tcp = "OK"; xv = 0; } (void) PrtMsgX(tcp, Pn, cleanup, xv); return(0); } #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); } #endif /* defined(LT_DIAL_linux) */ /* * cleanup() -- release resources */ static void cleanup() { if (Fd >= 0) { (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 */ { 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; case TYTST_0to: tnm1 = " 0t"; tnm2 = " offset"; break; case TYTST_0xo: 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); } /* * 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); } /* * 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, "%u", (unsigned int)sb.st_ino); ibuf[sizeof(ibuf) - 1] = '\0'; /* * Complete the option vector and start lsof execution. */ ti = 0; if (opt && *opt) opv[ti++] = opt; #if defined(USE_LSOF_C_OPT) opv[ti++] = "-C"; #else /* !defined(USE_LSOF_C_OPT) */ opv[ti++] = "--"; #endif /* defined(USE_LSOF_C_OPT) */ opv[ti++] = Path; opv[ti] = (char *)NULL; if ((cem = ExecLsof(opv))) 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; } } (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); } return(pem); } lsof-4.86+dfsg.orig/tests/LTnfs.c0000444000175000017500000003110211036663741017014 0ustar nicholasnicholas/* * LTnfs.c -- Lsof Test NFS tests * * 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. */ #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 */ #if defined(LT_DIAL_darwin) /* * Darwin-specific items */ # 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 */ /* * Local function prototypes */ _PROTOTYPE(static void cleanup,(void)); _PROTOTYPE(static char *FindNFSfile,(int *ff, char *szbuf)); /* * Main program */ int main(argc, argv) 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. */ if ((Pn = strrchr(argv[0], '/'))) Pn++; else Pn = argv[0]; MyPid = getpid(); (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)) { /* * 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 { /* * 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'; } /* * 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, 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); } /* * cleanup() -- release resources */ static void cleanup() { if (Fd >= 0) { (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 */ { 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); *ff = 0; /* * 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); } /* * 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); ibuf[sizeof(ibuf) - 1] = '\0'; (void) snprintf(nlkbuf, sizeof(nlkbuf) - 1, "%d", (int)sb.st_nlink); nlkbuf[sizeof(nlkbuf) - 1] = '\0'; /* * Complete the option vector and start lsof execution. */ ti = 0; opv[ti++] = "-s"; opv[ti++] = "-Na"; #if defined(USE_LSOF_C_OPT) opv[ti++] = "-C"; #endif /* defined(USE_LSOF_C_OPT) */ opv[ti++] = Path; opv[ti] = (char *)NULL; if ((cem = ExecLsof(opv))) 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); } } /* * 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); buf[sizeof(buf) - 1] = '\0'; return(MkStrCpy(buf, &ti)); } lsof-4.86+dfsg.orig/tests/LTbigf.c0000444000175000017500000004503511033721236017136 0ustar nicholasnicholas/* * LTbigf.c -- Lsof Test big file size and offset tests * * 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. */ #ifndef lint static char copyright[] = "@(#) Copyright 2002 Purdue Research Foundation.\nAll rights reserved.\n"; #endif #include "LsofTest.h" #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 */ { char *pn; /* program name */ /* * Get program name and issue start and exit message. */ if ((pn = (char *)strrchr(argv[0], '/'))) pn++; else pn = argv[0]; (void) printf("%s ... %s\n", pn, LT_DONT_DO_TEST); return(0); } #else /* defined(LT_BIGF) */ /* * Here begins the version of this program for dialects that support * large files. */ #include "lsof_fields.h" /* * Pre-definitions that may be changed by specific dialects */ #define OFFTST_STAT 1 /* offset tests status */ #if defined(LT_DIAL_aix) /* * AIX-specific definitions */ #define OFFSET_T off64_t /* define offset type */ #endif /* defined(LT_DIAL_aix) */ #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) */ #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 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) */ #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) */ #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 */ _PROTOTYPE(static int ck_Linux_offset_support,(void)); #endif /* defined(LT_DIAL_linux) */ #if defined(LT_DIAL_hpux) /* * HP-UX-specific definitions */ #define OFFSET_T off64_t /* define offset type */ #endif /* defined(LT_DIAL_hpux) */ #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) */ #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) */ #if defined(LT_DIAL_ou) /* * OpenUNIX-specific items */ #include #define IGNORE_SIGXFSZ #define OFFSET_T off64_t /* define offset type */ #endif /* defined(LT_DIAL_ou) */ #if defined(LT_DIAL_solaris) /* * Solaris-specific definitions */ #define OFFSET_T off64_t /* define offset type */ #endif /* defined(LT_DIAL_solaris) */ #if defined(LT_DIAL_uw) /* * UnixWare-specific items */ #include #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(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(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 */ /* * 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 */ /* * Local function prototypes */ _PROTOTYPE(static void cleanup,(void)); _PROTOTYPE(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 */ { 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++; else Pn = argv[0]; MyPid = getpid(); (void) printf("%s ... ", Pn); (void) fflush(stdout); PrtMsg((char *)NULL, Pn); /* * 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); } #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. */ if ((em = IsLsofExec())) (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. */ if (!(Path = LTopt_p)) { (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. */ for (i = 0; i < sizeof(buf); i++) { 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: /* * 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. */ 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; } 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; } /* * 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; } 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; } /* * Fsync() the file. */ if (fsync(Fd)) { (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 (!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); } /* * Do file size test. */ tsz = tstwlsof(TST_SZ, "-s", sz); /* * If enabled, do offset tests. */ if (!tofft) tofft = tstwlsof(TST_OFFT, "-oo20", sz); if (!toffx) toffx = tstwlsof(TST_OFFX, "-oo2", sz); /* * Compute exit value and exit. */ if ((tsz != 1) || (tofft != 1) || (toffx != 1)) { tcp = (char *)NULL; xv = 1; } else { tcp = "OK"; xv = 0; } (void) PrtMsgX(tcp, Pn, cleanup, xv); return(0); } #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); } #endif /* defined(LT_DIAL_linux) */ /* * cleanup() -- release resources */ 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; } } /* * 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) */ { 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; default: (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. */ 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); } /* * Extract components from test file's device number. */ if ((em = ConvStatDev(&sb.st_dev, &stdc))) { (void) PrtMsg(em, Pn); return(0); } /* * Complete the option vector and start lsof execution. */ ti = 0; if (opt && *opt) opv[ti++] = opt; #if defined(USE_LSOF_C_OPT) opv[ti++] = "-C"; #else /* !defined(USE_LSOF_C_OPT) */ opv[ti++] = "--"; #endif /* defined(USE_LSOF_C_OPT) */ opv[ti++] = Path; opv[ti] = (char *)NULL; if ((em = ExecLsof(opv))) { (void) PrtMsg(em, Pn); return(0); } /* * 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; } } (void) StopLsof(); if (em) { /* * 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; } return(xv); } #endif /* defined(LT_BIG) */ lsof-4.86+dfsg.orig/tests/LsofTest.h0000444000175000017500000001664711033717575017561 0ustar nicholasnicholas/* * LsofTest.h -- header file for lsof tests */ /* * 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. */ /* * $Id: LsofTest.h,v 1.12 2008/07/05 16:21:07 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__) */ /* * 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 */ /* * Necessary header files. */ #include #include #include #include #include #include #include /* * 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 */ # if defined(LT_DIAL_aix) /* * AIX-specific items */ #include #include #include #include #include #undef USE_LSOF_C_OPT #define USE_LSOF_X_OPT # endif /* defined(LT_DIAL_aix) */ # if defined(LT_DIAL_bsdi) /* * OpenBSD-specific items */ #include #include #include #include #include # endif /* defined(LT_DIAL_bsdi) */ # if defined(LT_DIAL_darwin) /* * Darwin-specific items */ #include #include #include #include #include #undef USE_LSOF_C_OPT # endif /* defined(LT_DIAL_darwin) */ # if defined(LT_DIAL_du) /* * DEC_OSF/1|Digital_UNIX|Tru64_UNIX-specific items */ #include #include #include #include # 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) /* * FreeBSD-specific items */ #include #include #include #include #include # endif /* defined(LT_DIAL_freebsd) */ # if defined(LT_DIAL_linux) /* * Linux-specific items */ #include #include #include #include #include #undef USE_LSOF_C_OPT # endif /* defined(LT_DIAL_linux) */ # if defined(LT_DIAL_hpux) /* * HP-UX-specific items */ #include #include #include #include #include # endif /* defined(LT_DIAL_hpux) */ # if defined(LT_DIAL_netbsd) /* * NetBSD-specific items */ #include #include #include #include #include # endif /* defined(LT_DIAL_netbsd) */ # if defined(LT_DIAL_openbsd) /* * OpenBSD-specific items */ #include #include #include #include #include # endif /* defined(LT_DIAL_openbsd) */ # if defined(LT_DIAL_ou) /* * OpenUNIX-specific items */ #include #include #include #include # endif /* defined(LT_DIAL_ou) */ # if defined(LT_DIAL_osr) /* * OSR-specific items */ #include #include #include #include # endif /* defined(LT_DIAL_osr) */ # if defined(LT_DIAL_ns) /* * NEXTSTEP-specific items */ #include #include #include #include typedef int pid_t; #define snprintf snpf #undef USE_GETCWD # endif /* defined(LT_DIAL_ns) */ # if defined(LT_DIAL_solaris) /* * Solaris-specific items */ #include #include #include #include #include # if defined(LT_VPATH) #undef USE_LSOF_C_OPT #endif /* defined(LT_VPATH) */ # endif /* defined(LT_DIAL_solaris) */ # if defined(LT_DIAL_uw) /* * UnixWare-specific items */ #include #include #include #include # 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) */ /* * 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) */ } 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 */ } LTfldo_t; #define LT_FLDO_ALLOC 16 /* LTfldo_t allocation increment */ /* * Lsof test library global variable external declarations: * * 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 */ /* * External declarations */ extern int errno; /* error number */ /* * Lsof test library function prototypes: * * 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 */ lsof-4.86+dfsg.orig/tests/TestDB0000644000175000017500000001565211722564307016710 0ustar nicholasnicholas# TestDB -- lsof test suite data base # # This file contains the sorted words from config.cflags, less any leading "-D" # strings, joined on one line. # # See Add2TestDB for a script that will build a line for this file. # # $Id: TestDB,v 1.37 2011/09/27 17:36:16 abe Exp abe $ LT_AIXA=0 LT_BIGF LT_CC LT_DIAL_aix LT_KMEM LT_VERS=4320 LT_AIXA=0 LT_BIGF LT_CC LT_DIAL_aix LT_KMEM LT_VERS=4330 LT_AIXA=1 LT_BIGF LT_CC LT_DIAL_aix LT_K64 LT_KMEM LT_VERS=5000 LT_AIXA=0 LT_BIGF LT_CC LT_DIAL_aix LT_KMEM LT_VERS=5100 LT_AIXA=0 LT_BIGF LT_DIAL_aix LT_GCC LT_KMEM LT_VERS=5100 LT_AIXA=1 LT_BIGF LT_CC LT_DIAL_aix LT_K64 LT_KMEM LT_VERS=5100 LT_AIXA=0 LT_BIGF LT_CC LT_DIAL_aix LT_KMEM LT_VERS=5200 LT_AIXA=0 LT_BIGF LT_DIAL_aix LT_GCC LT_KMEM LT_VERS=5200 LT_AIXA=1 LT_BIGF LT_CC LT_DIAL_aix LT_K64 LT_KMEM LT_VERS=5200 LT_AIXA=1 LT_BIGF LT_DIAL_aix LT_GCC LT_K64 LT_KMEM LT_VERS=5200 LT_AIXA=1 LT_BIGF LT_CC LT_DIAL_aix LT_K64 LT_KMEM LT_VERS=5300 LT_BIGF LT_DIAL_bsdi LT_GCC LT_KMEM LT_VERS=40100 LT_BIGF LT_DIAL_bsdi LT_GCC LT_KMEM LT_VERS=40300 LT_CC LT_DIAL_darwin LT_KMEM LT_VERS=140 LT_CC LT_DIAL_darwin LT_KMEM LT_VERS=530 LT_CC LT_DIAL_darwin LT_KMEM LT_VERS=600 LT_CC LT_DIAL_darwin LT_KMEM LT_VERS=700 LT_CC LT_DIAL_darwin LT_KMEM LT_VERS=800 LT_CC LT_DIAL_darwin LT_VERS=800 LT_BIGF LT_CC LT_DIAL_darwin LT_KMEM LT_VERS=800 LT_CC LT_DIAL_darwin LT_VERS=900 LT_BIGF LT_CC LT_DIAL_darwin LT_VERS=900 LT_BIGF LT_CC LT_DIAL_darwin LT_VERS=1000 LT_BIGF LT_CC LT_DIAL_darwin LT_VERS=1100 LT_BIGF LT_CC LT_DIAL_du LT_K64 LT_KMEM LT_VERS=40000 LT_BIGF LT_CC LT_DIAL_du LT_K64 LT_KMEM LT_VERS=50000 LT_BIGF LT_CC LT_DIAL_du LT_K64 LT_KMEM LT_VERS=50100 LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=4050 LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=4060 LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=4070 LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=4080 LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=4090 LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=4100 LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=4110 LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=5000 LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=5010 LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=5020 LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=5030 LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=5040 LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=5050 LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=6000 LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=6010 LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=6020 LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=6040 LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=7000 LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=7010 LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=7020 LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=7030 LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=7040 LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=8000 LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=8020 LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=8030 LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=9000 LT_BIGF LT_CC LT_DIAL_freebsd LT_KMEM LT_VERS=10000 LT_BIGF LT_CC LT_DIAL_hpux LT_KMEM LT_VERS=1020 _LARGEFILE64_SOURCE LT_BIGF LT_DIAL_hpux LT_GCC LT_KMEM LT_VERS=1020 _LARGEFILE64_SOURCE LT_BIGF LT_CC LT_DIAL_hpux LT_KMEM LT_VERS=1100 _LARGEFILE64_SOURCE LT_BIGF LT_CC LT_DIAL_hpux LT_K64 LT_KMEM LT_VERS=1100 _LARGEFILE64_SOURCE LT_BIGF LT_CC LT_DIAL_hpux LT_K64 LT_VERS=1111 _LARGEFILE64_SOURCE LT_BIGF LT_CC LT_DIAL_hpux LT_K64 LT_VERS=1123 _LARGEFILE64_SOURCE LT_BIGF LT_DIAL_hpux LT_GCC LT_K64 LT_VERS=1123 _LARGEFILE64_SOURCE LT_BIGF LT_CC LT_DIAL_hpux LT_K64 LT_VERS=1131 _LARGEFILE64_SOURCE LT_BIGF LT_CC LT_DIAL_linux LT_VERS=24012 _FILE_OFFSET_BITS=64 LT_BIGF LT_CC LT_DIAL_linux LT_VERS=24018 _FILE_OFFSET_BITS=64 LT_BIGF LT_CC LT_DIAL_linux LT_VERS=24021 _FILE_OFFSET_BITS=64 LT_BIGF LT_CC LT_DIAL_linux LT_VERS=24023 _FILE_OFFSET_BITS=64 LT_BIGF LT_CC LT_DIAL_linux LT_VERS=24024 _FILE_OFFSET_BITS=64 LT_BIGF LT_CC LT_DIAL_linux LT_VERS=24025 _FILE_OFFSET_BITS=64 LT_BIGF LT_CC LT_DIAL_linux LT_VERS=24026 _FILE_OFFSET_BITS=64 LT_BIGF LT_CC LT_DIAL_linux LT_VERS=24027 _FILE_OFFSET_BITS=64 LT_BIGF LT_CC LT_DIAL_linux LT_VERS=24028 _FILE_OFFSET_BITS=64 LT_BIGF LT_CC LT_DIAL_linux LT_VERS=24029 _FILE_OFFSET_BITS=64 LT_BIGF LT_CC LT_DIAL_linux LT_VERS=24030 _FILE_OFFSET_BITS=64 LT_BIGF LT_CC LT_DIAL_linux LT_VERS=26000 _FILE_OFFSET_BITS=64 LT_BIGF LT_CC LT_DIAL_linux LT_VERS=26018 _FILE_OFFSET_BITS=64 LT_BIGF LT_CC LT_DIAL_linux LT_VERS=26022 _FILE_OFFSET_BITS=64 LT_BIGF LT_CC LT_DIAL_linux LT_VERS=26032 _FILE_OFFSET_BITS=64 LT_BIGF LT_CC LT_DIAL_linux LT_VERS=26038 _FILE_OFFSET_BITS=64 LT_BIGF LT_CC LT_DIAL_linux LT_VERS=31008 _FILE_OFFSET_BITS=64 LT_BIGF LT_CC LT_DIAL_netbsd LT_KMEM LT_VERS=1005000 LT_BIGF LT_CC LT_DIAL_netbsd LT_KMEM LT_VERS=1006000 LT_BIGF LT_CC LT_DIAL_netbsd LT_KMEM LT_VERS=2000000 LT_BIGF LT_CC LT_DIAL_netbsd LT_KMEM LT_VERS=2099009 LT_BIGF LT_CC LT_DIAL_netbsd LT_KMEM LT_VERS=2099010 LT_BIGF LT_CC LT_DIAL_netbsd LT_KMEM LT_VERS=2099011 LT_BIGF LT_CC LT_DIAL_netbsd LT_KMEM LT_VERS=2099012 LT_BIGF LT_CC LT_DIAL_netbsd LT_KMEM LT_VERS=3099000 LT_CC LT_DIAL_netbsd LT_KMEM LT_VERS=1040 LT_BIGF LT_CC LT_DIAL_openbsd LT_KMEM LT_VERS=3000 LT_BIGF LT_CC LT_DIAL_openbsd LT_KMEM LT_VERS=3010 LT_BIGF LT_CC LT_DIAL_openbsd LT_KMEM LT_VERS=3020 LT_BIGF LT_CC LT_DIAL_openbsd LT_KMEM LT_VERS=3030 LT_BIGF LT_CC LT_DIAL_openbsd LT_KMEM LT_VERS=3040 LT_BIGF LT_CC LT_DIAL_openbsd LT_KMEM LT_VERS=3050 LT_BIGF LT_CC LT_DIAL_openbsd LT_KMEM LT_VERS=3060 LT_BIGF LT_CC LT_DIAL_openbsd LT_KMEM LT_VERS=3070 LT_BIGF LT_CC LT_DIAL_openbsd LT_KMEM LT_VERS=3090 LT_CC LT_DIAL_osr LT_KMEM LT_VERS=504 LT_CC LT_DIAL_osr LT_KMEM LT_VERS=506 LT_DIAL_ns LT_GCC LT_KMEM LT_VERS=31 LT_CC LT_DIAL_ns LT_KMEM LT_VERS=42 LT_CC LT_DIAL_solaris LT_KMEM LT_VERS=20600 LT_DIAL_solaris LT_GCC LT_KMEM LT_VERS=20600 LT_BIGF LT_CC LT_DIAL_solaris LT_KMEM LT_VERS=70000 LT_BIGF LT_CC LT_DIAL_solaris LT_K64 LT_KMEM LT_VERS=70000 LT_BIGF LT_DIAL_solaris LT_GCC LT_KMEM LT_VERS=70000 LT_BIGF LT_CC LT_DIAL_solaris LT_KMEM LT_VERS=80000 LT_BIGF LT_DIAL_solaris LT_GCC LT_KMEM LT_VERS=80000 LT_BIGF LT_DIAL_solaris LT_GCC LT_K64 LT_KMEM LT_VERS=80000 LT_BIGF LT_CC LT_DIAL_solaris LT_K64 LT_KMEM LT_VERS=80000 LT_BIGF LT_DIAL_solaris LT_GCC LT_KMEM LT_VERS=90000 LT_BIGF LT_CC LT_DIAL_solaris LT_K64 LT_KMEM LT_VERS=90000 LT_BIGF LT_DIAL_solaris LT_GCC LT_K64 LT_KMEM LT_VERS=90000 LT_BIGF LT_CC LT_DIAL_solaris LT_KMEM LT_VERS=100000 LT_BIGF LT_CC LT_DIAL_solaris LT_K64 LT_KMEM LT_VERS=100000 LT_VPATH LT_BIGF LT_DIAL_solaris LT_GCC LT_KMEM LT_VERS=100000 LT_BIGF LT_DIAL_solaris LT_GCC LT_KMEM LT_VERS=100000 LT_VPATH LT_BIGF LT_CC LT_DIAL_solaris LT_K64 LT_KMEM LT_VERS=100000 LT_BIGF LT_DIAL_solaris LT_GCC LT_K64 LT_KMEM LT_VERS=100000 LT_BIGF LT_DIAL_solaris LT_GCC LT_K64 LT_KMEM LT_VERS=100000 LT_VPATH LT_BIGF LT_CC LT_DIAL_solaris LT_K64 LT_KMEM LT_VERS=110000 LT_VPATH LT_BIGF LT_DIAL_solaris LT_GCC LT_K64 LT_KMEM LT_VERS=110000 LT_VPATH 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 lsof-4.86+dfsg.orig/tests/Makefile0000444000175000017500000000706710360776250017276 0ustar nicholasnicholas# Makefile for testing lsof # # V. Abell # Purdue University # # $Id: Makefile,v 1.17 2005/05/17 00:40:53 abe Exp abe $ DEBUG= CFLAGS= ${DEBUG} -I. -I.. HDR= LsofTest.h CKTSTDB= CkTestDB CONFCFL= ./config.cflags CONFIG= ./config.cc ${CONFCFL} ./config.xobj LTOBJ= LTlib.o LTSRC= LTlib.c LIBOBJ= ${LTOBJ} BASTST= LTbasic STDTST= LTnlink LTsock LTszoff LTunix OPTTST= LTbigf LTdnlc LTlock LTnfs all: ${CKTSTDB} ${BASTST} ${STDTST} FRC @./${CKTSTDB}; xv=$$?; \ if [ $$xv -ne 0 ]; then \ exit 1 ;\ fi @rm -f config.LT* -@err=0; \ echo ""; \ echo "Basic test:"; \ ./${BASTST}; \ if [ $$? -ne 0 ]; then \ exit 1; \ fi; \ echo ""; \ echo "Standard tests:"; \ for i in ${STDTST}; do \ ./$$i; \ if [ $$? -ne 0 ]; then \ err=`expr $$err + 1`; \ fi; \ done; \ if [ $$err -ne 0 ]; then \ echo "Failed tests: $$err"; \ echo ""; \ echo "See 00FAQ and 00TEST for more information."; \ else \ echo "All standard tests succeeded."; \ echo ""; \ grep LT_DIAL_darwin ${CONFCFL} > /dev/null 2>&1; \ if [ $$? -ne 0 ]; then \ echo "Suggestion: try the optional tests: \"make opt\""; \ echo ""; \ fi; \ fi; @rm -f config.LT* auto: ckDB silent FRC ckDB: ${CKTSTDB} FRC @echo "" | ./${CKTSTDB}; xv=$$?; \ if [ $$xv -ne 0 ]; then \ exit 1 ;\ fi clean: FRC rm -f ${BASTST} ${STDTST} ${OPTTST} *.o *.err *.out config.LT* FRC: LTbasic: LTbasic.c ${CONFIG} ${LIBOBJ} ${HDR} `cat config.cc` ${CFLAGS} `cat config.cflags` LTbasic.c \ ${LIBOBJ} `cat config.xobj` -o LTbasic LTbigf: LTbigf.c ${CONFIG} ${LIBOBJ} ${HDR} `cat config.cc` ${CFLAGS} `cat config.cflags` LTbigf.c \ ${LIBOBJ} `cat config.xobj` -o LTbigf LTdnlc: LTdnlc.c ${CONFIG} ${LIBOBJ} ${HDR} `cat config.cc` ${CFLAGS} `cat config.cflags` LTdnlc.c \ ${LIBOBJ} `cat config.xobj` -o LTdnlc LTlock: LTlock.c ${CONFIG} ${LIBOBJ} ${HDR} `cat config.cc` ${CFLAGS} `cat config.cflags` LTlock.c \ ${LIBOBJ} `cat config.xobj` -o LTlock ${LTOBJ}: ${HDR} ${LTSRC} config.cflags config.cc `cat config.cc` ${CFLAGS} `cat config.cflags` -c ${LTSRC} \ -o ${LTOBJ} LTnfs: LTnfs.c ${CONFIG} ${LIBOBJ} ${HDR} `cat config.cc` ${CFLAGS} `cat config.cflags` LTnfs.c \ ${LIBOBJ} `cat config.xobj` -o LTnfs LTnlink: LTnlink.c ${CONFIG} ${LIBOBJ} ${HDR} `cat config.cc` ${CFLAGS} `cat config.cflags` LTnlink.c \ ${LIBOBJ} `cat config.xobj` -o LTnlink LTsock: LTsock.c ${CONFIG} ${LIBOBJ} ${HDR} `cat config.cc` ${CFLAGS} `cat config.cflags` LTsock.c \ ${LIBOBJ} `cat config.xobj` -o LTsock `cat config.ldflags` LTszoff: LTszoff.c ${CONFIG} ${LIBOBJ} ${HDR} `cat config.cc` ${CFLAGS} `cat config.cflags` LTszoff.c \ ${LIBOBJ} `cat config.xobj` -o LTszoff LTunix: LTunix.c ${CONFIG} ${LIBOBJ} ${HDR} config.ldflags `cat config.cc` ${CFLAGS} `cat config.cflags` LTunix.c \ ${LIBOBJ} `cat config.xobj` -o LTunix `cat config.ldflags` opt: ${CKTSTDB} ${OPTTST} FRC @rm -f config.LT* -@err=0; \ echo ""; \ echo "Optional tests:"; \ for i in ${OPTTST}; do \ ./$$i; \ if [ $$? -ne 0 ]; then \ err=`expr $$err + 1`; \ fi; \ done; \ if [ $$err -ne 0 ]; then \ echo "Failed tests: $$err"; \ else \ echo "All optional tests succeeded."; \ fi; \ echo ""; @rm -f config.LT* optional: opt silent: ${BASTST} ${STDTST} FRC @rm -f config.LT* @err=0; \ ./${BASTST} > /dev/null 2>&1; \ if [ $$? -ne 0 ]; then \ exit 1; \ fi; \ for i in ${STDTST}; do \ ./$$i > /dev/null 2>&1; \ if [ $$? -ne 0 ]; then \ err=`expr $$err + 1`; \ fi; \ done; \ rm -f config.LT*; \ if [ $$err -ne 0 ]; then \ exit 1; \ fi spotless: clean rm -f config.* standard: all std: all test: all lsof-4.86+dfsg.orig/tests/LTbasic.c0000444000175000017500000002512010360776661017317 0ustar nicholasnicholas/* * LTbasic.c -- Lsof Test basic tests * * The basic tests measure the finding by lsof of its own open CWD, open * executable (when possible), and open /dev/kmem files. * * 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. */ #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 */ /* * Local function prototypes */ _PROTOTYPE(static void cleanup,(void)); _PROTOTYPE(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 */ { 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++; else Pn = argv[0]; (void) printf("%s ... ", Pn); (void) fflush(stdout); PrtMsg((char *)NULL, Pn); /* * Process arguments. */ if (ScanArg(argc, argv, "h", Pn)) xv = 1; if (xv || LTopt_h) { (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. */ if ((em = IsLsofExec())) (void) PrtMsgX(em, Pn, cleanup, 1); if ((em = CanRdKmem())) (void) PrtMsgX(em, Pn, cleanup, 1); /* * Test lsof. */ if ((em = tstlsof(&texec, &tkmem, &tproc))) PrtMsg(em, Pn); if (texec) PrtMsg(texec, Pn); if (tkmem) PrtMsg(tkmem, Pn); if (tproc) 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); } (void) PrtMsgX("OK", Pn, cleanup, 0); return(0); } /* * cleanup() -- release resources */ 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 */ { 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; } else if ((cem = ConvStatDev(&lsofsb.st_dev, &lsofdc))) { if (pem) (void) PrtMsg(pem, Pn); pem = cem; execs = 1; } #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; } else if ((cem = ConvStatDev(&kmemsb.st_rdev, &kmemdc))) { if (pem) (void) PrtMsg(pem, Pn); pem = cem; kmems = 1; } #else /* !defined(LT_KMEM) */ kmems = 1; #endif /* defined(LT_KMEM) */ /* * 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; } else if ((cem = ConvStatDev(&cwdsb.st_dev, &cwddc))) { if (pem) (void) PrtMsg(pem, Pn); pem = cem; procs = 1; } /* * Complete the option vector and start lsof execution. */ ti = 0; #if defined(USE_LSOF_C_OPT) opv[ti++] = "-C"; #endif /* defined(USE_LSOF_C_OPT) */ #if defined(USE_LSOF_X_OPT) opv[ti++] = "-X"; #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); } /* * 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, "%u", (unsigned int)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, "%u", (unsigned int)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, "%u", (unsigned int)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(); if (!execs) *texec = "ERROR!!! open lsof executable wasn't found."; if (!kmems) *tkmem = "ERROR!!! open lsof /dev/kmem usage wasn't found."; if (!procs) *tproc = "ERROR!!! lsof process wasn't found."; return(pem); } lsof-4.86+dfsg.orig/tests/LTdnlc.c0000444000175000017500000002356510360777547017175 0ustar nicholasnicholas/* * LTdnlc.c -- Lsof Test Dynamic Name Lookup Cache test * * 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. */ #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 */ /* * Dialect-specific items */ #if defined(LT_DIAL_aix) /* * AIX-specific items */ #undef DO_TEST #endif /* defined(LT_DIAL_aix) */ #if defined(LT_DIAL_darwin) /* * Darwin-specific items */ # 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 */ /* * Globals */ 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)); /* * Main program */ int main(argc, argv) 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. */ if ((Pn = strrchr(argv[0], '/'))) Pn++; else Pn = argv[0]; MyPid = getpid(); (void) printf("%s ... ", Pn); (void) fflush(stdout); PrtMsg((char *)NULL, Pn); /* * Process arguments. */ if (ScanArg(argc, argv, "h", Pn)) xv = 1; if (xv || LTopt_h) { (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) */ /* * 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); /* * Get the CWD and form the ls(1) system() command. */ #if defined(USE_GETCWD) em = "getcwd"; if (!getcwd(cwd, sizeof(cwd))) #else /* ! defined(USE_GETCWD) */ em = "getwd"; if (!getwd(cwd)) #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(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); } if ((em = ConvStatDev(&sb.st_dev, &cwddc))) PrtMsgX(em, Pn, cleanup, 1); (void) snprintf(ibuf, sizeof(ibuf) - 1, "%u", (unsigned int)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. */ (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. */ 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 */ 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); } /* * Exit successfully. */ (void) PrtMsgX("OK", Pn, cleanup, 0); return(0); } /* * cleanup() -- release resources */ 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 */ { 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); *ff = 0; /* * 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); } /* * 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; } } } } /* * Clean up and return. */ (void) StopLsof(); if (pem) { *ff = -1; return(pem); } return((char *)NULL); } lsof-4.86+dfsg.orig/AFSConfig0000555000175000017500000001610606715363347016163 0ustar nicholasnicholas#!/bin/sh # # $Id: AFSConfig,v 1.2 99/05/09 14:49:54 abe Exp $ # # AFSConfig: configure for AFS AFSD=/usr/vice/etc/afsd AH=AFSHeaders AV=AFSVersion STD=/usr/afsws/include # Establish trap and stty handling. ISIG=":" trap 'rm -f $AH $AV; $ISIG; exit 1' 1 2 3 15 stty -a 2>&1 | grep isig > /dev/null if test $? -eq 0 then stty -a 2>&1 | egrep -e -isig > /dev/null if test $? -eq 0 then ISIG="stty -isig" stty isig fi fi # Decide how to use echo. ECHO=`echo -n ""` if test "X$ECHO" = "X-n " then EC="\c" EO="" else EC="" EO="-n" fi # Decide (perhaps for a second time) that AFS is installed. CELL="" if test -r /usr/vice/etc/ThisCell then cell=`awk '{print $1}' /usr/vice/etc/ThisCell` if test -d /afs/$cell then CELL=$cell else CELL=`echo $cell | sed 's/\([^.]*\)\..*/\1/'` if test "X$CELL" != "X" then if test ! -d /afs/$CELL then CELL="" fi fi fi fi if test "X$CELL" = "X" then echo "" echo "This system does not appear to have AFS installed." exit 1 fi # See if AFS configuration is wanted. cat << .CAT_MARK AFS appears to be installed on this system; cell name "$CELL". Lsof needs to be configured for AFS by identifying: 1) the directory that includes the AFS header files needed to compile AFS support into lsof; and 2) the version of AFS that is installed. .CAT_MARK END=0 while test $END = 0 do echo "" echo $EO "Do you want to configure lsof for AFS (y|n) [y]? $EC" read ANS EXCESS if test "X$ANS" = "Xn" -o "X$ANS" = "XN" then exit 1 fi if test "X$ANS" = "Xy" -o "X$ANS" = "XY" -o "X$ANS" = "X" then END=1 else echo "" echo "Please answer y or n." fi done # See if $AH exists and points to a likely place. AHOK="" echo "" echo "=====================================================================" echo "" if test -r $AH then AHP=`cat $AH` if test -r $AHP then if test -r $AHP/afs/afs.h then cat << .CAT_MARK The location of the AFS header files required by lsof has been previously identified as "$AHP". Since can be found there, that's probably correct. .CAT_MARK END=0 while test $END = 0 do echo "" echo $EO "Do you want to use $AHP again (y|n) [y]? $EC" read ANS EXCESS if test "X$ANS" = "Xy" -o "X$ANS" = "XY" -o "X$ANS" = "X" then AHOK="ok" END=1 else if test "X$ANS" = "Xn" -o "X$ANS" = "XN" then rm -f $AH AHP="" END=1 else echo "" echo "Please answer y or n." fi fi done else echo "\"$AHP\" has been previously specified as the location of the" echo "AFS header files, but it lacks an afs/afs.h header file." rm -f $AH AHP="" fi else echo "The file ./$AH exists, but has no AFS header file path in it." rm -f $AH AHP="" fi else echo "No previous header location has been specified." rm -f $AH AHP="" fi # See if the header files are in the "standard" place. if test "X$AHOK" != "Xok" then if test -r $STD then echo "" echo "=====================================================================" echo "" echo "The AFS header files appear to be in the \"standard\" location --" echo "i.e.: \"$STD\"." END=0 while test $END = 0 do echo "" echo $EO "Do you want to let lsof use them (y|n) [y]? $EC" read ANS EXCESS if test "X$ANS" = "Xy" -o "X$ANS" = "XY" -o "X$ANS" = "X" then echo $STD > $AH AHOK="ok" END=1 else if test "X$ANS" = "Xn" -o "X$ANS" = "XN" then END=1 else echo "" echo "Please answer y or n." fi fi done fi fi # Ask for the AFS header file location. if test "X$AHOK" != "Xok" then echo "" echo "=====================================================================" echo "" echo "Please specify the full path where lsof can find the AFS header" echo "files. A possible location is: \"/afs/$CELL//include\"." cat << .CAT_MARK The component of the path is the AFS system name that was used to configure and build AFS on this system. It is usually constructed from a manufacturer or Unix operating system designation, followed by a version number -- e.g., hp800_ux90, sun4m_54, vax_ul43, etc. You may have to consult your AFS documentation to determine what applies to your configuration. .CAT_MARK END=0 while test $END = 0 do echo "" echo $EO "Do you want to see the contents of /afs/$CELL (y|n) [y]? $EC" read ANS EXCESS if test "X$ANS" = "Xn" -o "X$ANS" = "XN" then END=1 else if test "X$ANS" = "Xy" -o "X$ANS" = "XY" -o "X$ANS" = "X" then echo "" ls -C /afs/$CELL END=1 else echo "" echo "Please answer y or n." fi fi done END=0 while test $END = 0 do echo "" echo $EO "AFS header file path: $EC" read ANS EXCESS fc=`expr "${ANS}X" : '\(.\).*'` if test "X$fc" = "X/" then if test -r $ANS/afs/afs.h then echo $ANS > $AH AHOK="ok" END=1 else echo "" echo "$ANS/afs/afs.h doesn't exist." echo "Please enter a path whose afs subdirectory contains afs.h" fi else echo "" echo "Please enter an absolute path name." fi done fi if test "X$AHOK" != "Xok" then echo "AFSConfig: unknown error" exit 1 fi # Determine AFS version. if test -r $AV then echo "" echo "=====================================================================" echo "" AVN=`cat $AV` cat << .CAT_MARK The AFS version was previously specified as: $AVN .CAT_MARK END=0 while test $END = 0 do echo "" echo $EO "Is this the correct version number (y|n) [y]? $EC" read ANS EXCESS if test "X$ANS" = "Xy" -o "X$ANS" = "XY" -o "X$ANS" = "X" then exit 0 fi if test "X$ANS" = "Xn" -o "X$ANS" = "XN" then rm -f $AV END=1 else echo "Please answer y or n." fi done fi # See if the version number can be determined. if test -r $AFSD then ANS=`strings $AFSD | grep "Base configuration afs" | sed 's/^.*ion afs\([^ ]*\) .*/\1/'` TV=`echo $ANS | sed 's/^\([0-9]*\)\.\([0-9]*\)\(.*\)/\1 \2 \3/' | awk '{printf "%d.%d%s\n",$1,$2,$3}'` if test "X$ANS" = "X$TV" then echo "" echo "=====================================================================" echo "" cat << .CAT_MARK Examining $AFSD the AFS version number appears to be: $TV .CAT_MARK END=0 while test $END = 0 do echo "" echo $EO "Do you want to use this version number (y/n) [y]? $EC" read ANS EXCESS if test "X$ANS" = "Xn" -o "X$ANS" = "XN" then END=1 else if test "X$ANS" = "Xy" -o "X$ANS" = "XY" -o "X$ANS" = "X" then echo $TV > $AV exit 0 else echo "" echo "Please answer y or n." fi fi done fi fi # Ask for the version number. echo "" echo "=====================================================================" END=0 while test $END = 0 do echo "" echo $EO "Please enter the AFS version number: $EC" read ANS EXCESS TV=`echo $ANS | sed 's/^\([0-9]*\)\.\([0-9]*\)\(.*\)/\1 \2 \3/' | awk '{printf "%d.%d%s\n",$1,$2,$3}'` if test "X$ANS" = "X$TV" then echo $TV > $AV exit 0 fi done lsof-4.86+dfsg.orig/00FAQ0000444000175000017500000113377611741060354015171 0ustar nicholasnicholas Frequently Asked Questions about lsof ********************************************************************** | The latest release of lsof is always available via anonymous ftp | | from lsof.itap.purdue.edu. Look in pub/lsof.README for its | | location. | ********************************************************************** ______________________________________________________________________ This file contains frequently asked questions about lsof and answers to them. Vic Abell April 10, 2012 ______________________________________________________________________ Table of Contents: 1.0 General Concepts 1.1 Lsof -- what is it? 1.2 Where do I get lsof? 1.2.1 Are there mirror sites? 1.2.2 Are lsof executables available? 1.2.3 How do I check the validity of an lsof distribution? 1.2.4 Why can't I get the sum(1) result reported in README.lsof_? 1.2.5 Why won't gpg accept the lsof-signing PGP public key? 1.3 Where can I get more lsof documentation? 1.4 How do I report an lsof bug? 1.5 Where can I get the lsof FAQ? 1.5.1 How timely is the on-line FAQ? 1.6 Is there a test suite? 1.7 Is lsof vulnerable to the standard I/O descriptor attack? 1.8 Can I alter lsof's make(1) behavior? 1.9 Is there an lsof license? 1.10 Language locale support 1.10.1 Does lsof support language locales? How do I use the support? 1.10.2 Does lsof support wide characters in language locales? 1.11 Are any files in the lsof distribution copyrighted? 1.12 Are there other lsof-related resources? 1.13 What does the "WARNING: unsupported dialect or version" mean? 2.0 Lsof Ports 2.1 What ports exist? 2.2 What about a new port? 2.2.1 User-contributed Ports 2.3 Why isn't there an AT&T SVR4 port? 2.4 Why isn't there an SGI IRIX port? 2.5 Why does lsof's Configure script report "WARNING: unsupported dialect or version"? 3.0 Lsof Problems 3.1 Configuration Problems 3.1.1 Why can't Configure determine the UNIX dialect version? 3.2 Compilation Problems 3.2.1 Why does the compiler complain about missing header files? 3.2.2 Why does gcc complain about the contents of header files distributed by the system's vendor? 3.2.3 Other header file problems 3.3 Why doesn't lsof report full path names? 3.3.1 Why do lsof -r reports show different path names? 3.3.2 Why does lsof report the wrong path names? 3.3.3 Why doesn't lsof report path names for unlinked (rm'd) files? 3.3.4 Why doesn't lsof report the "correct" hard linked file path name? 3.3.5 When will lsof report path names for deleted files? 3.4 Why is lsof so slow? 3.5 Why doesn't lsof's setgid or setuid permission work? 3.6 Does lsof have security problems? 3.7 Will lsof show remote hosts using files via NFS? 3.8 Why doesn't lsof report locks held on NFS files? 3.8.1 Why does lsof report a one byte lock on byte zero as a full file lock? 3.9 Why does lsof report different values for open files on the same file system (the automounter phenomenon)? 3.10 Why don't lsof and netstat output match? 3.10.1 Why can't lsof find accesses to some TCP and UDP ports? 3.11 Why does lsof update the device cache file? 3.12 Why doesn't lsof report state for UDP socket files? 3.13 I am editing a file with vi; why doesn't lsof find the file? 3.14 Why doesn't lsof report TCP/TPI window and queue sizes for my dialect? 3.14.1 Why doesn't lsof report socket options, socket states, and TCP flags and values for my dialect? 3.14.2 Why doesn't lsof report the partial listen queue connection count for my dialect? 3.15 What does "no more information" in the NAME column mean? 3.16 Why doesn't lsof find a process that ps finds? 3.17 Why doesn't -V report a search failure? 3.18 Portmap problems 3.18.1 Why isn't a name displayed for the portmap registration? 3.18.2 How can I display only portmap registrations? 3.18.3 Why doesn't lsof report portmap registrations for some ports? 3.19 Why is `lsof | wc` bigger than my system's open file limit? 3.20 Why doesn't lsof report file offset (position)? 3.20.1 What does lsof report for size when the file doesn't really have one? 3.21 Problems with path name arguments 3.21.1 How do I ask lsof to search a file system? 3.21.2 Why doesn't lsof find all the open files in a file system? 3.21.3 Why does the lsof exit code report it didn't find open files when some files were listed? 3.21.4 Why won't lsof find all the open files in a directory? 3.21.5 Why are the +D and +d options so slow? 3.21.6 Why do the +D and +d options produce warning messages? 3.22 Why can't my C compiler find the rpcent structure definition? 3.23 Why doesn't lsof report fully on file "foo" on UNIX dialect "bar?" 3.24 Why do I get a complaint when I execute lsof that some library file can't be found? 3.25 Why does lsof complain it can't open files? 3.26 Why does lsof warn "compiled for x ... y; this is z."? 3.27 How can I disable the kernel identity check? 3.28 Why don't ps(1) and lsof agree on the owner of a process? 3.29 Why doesn't lsof find an open socket file whose connection state is past CLOSE_WAIT? 3.30 Why don't machine.h definitions work when the surrounding comments are removed? 3.31 What do "can't read inpcb at 0x...", "no protocol control block", "no PCB, CANTSENDMORE, CANTRCVMORE", etc. mean? 3.32 What do the "unknown file system type" warnings mean? 3.33 Installation 3.33.1 How do I install lsof? 3.33.2 How do I install a common lsof when I have machines that need differently constructed lsof binaries? 3.34 Why do lsof 4.53 and above reject device cache files built by earlier lsof revisions? 3.35 What do "like block special" and "like character special" mean in the NAME column? 3.36 Why does an lsof make fail because of undefined symbols? 3.37 Command Regular Expressions (REs) 3.37.1 What are basic and extended regular expressions? 3.37.2 Why can't I put a slash in a command regular expression? 3.37.3 Why does lsof say my command regular expression wasn't found? 3.38 Why doesn't lsof report on shared memory segments? 3.39 Why does lsof report two instances of itself? 3.40 Why does lsof report '\n' in device cache file error messages? 3.41 Kernel Symbol and Address Problems 3.41.1 What does "lsof: WARNING: name cache hash size length error: 0" mean? 3.41.2 Why does lsof produce "garbage" output? 3.42 Why does lsof report open files when run as super user that it doesn't report when run with lesser privileges? 3.43 Test Suite Problems 3.43.1 Errors all tests can report: 3.43.1.1 Why do tests complain "ERROR!!! can't execute ../lsof"? 3.43.1.2 Why do tests complain "ERROR!!! can't find ..." a file? 3.43.1.3 Why do some tests fail to compile? 3.43.1.4 Why do some tests always fail? 3.43.1.5 Why does the test suite say it hasn't been validated on my dialect? 3.43.1.6 Why do the tests complain they can't stat() or open() /dev/mem or /dev/kmem? 3.43.2 LTbigf test issues 3.43.2.1 Why does the LTbigf test say that the dialect doesn't support large files? 3.43.2.2 Why does LTbigf complain about operations on its config.LTbigf* file? 3.43.2.3 Why does LTbigf warn that lsof doesn't return file offsets? 3.43.3 Why does the LTbasic test complain "ERROR!!! lsof this ..." and "ERROR!!! lsof that ..."? 3.43.4 LTnfs test issues 3.43.4.1 Why does the LTnfs test complain "couldn't find NFS file ..."? 3.43.5 LTnlink test issues 3.43.5.1 Why does the LTnlink test complain that its test file is on an NFS file system? 3.43.5.2 Why does LTnlink delay and report "waiting for link count update: ..."? 3.43.5.3 Why does LTnlink fail because of an unlink error? 3.43.6 LTdnlc test issues 3.43.6.1 Why won't the LTdnlc test run? 3.43.6.2 What does the LTdnlc test mean by "... found: 100.00%"? 3.43.6.3 Why does the DNLC test fail? 3.43.7 Why hasn't the test suite been qualified for 64 bit HP-UX 11 when lsof is compiled with gcc? 3.43.8 LTszoff test issues 3.43.8.1 Why does LTszoff warn that lsof doesn't return file offsets? 3.43.9 LTlock test issues 3.44 File descriptor list (the ``-d'' option) problems 3.44.1 Why does lsof reject a ``-d'' FD list? 3.44.2 Why are file descriptors other than those in my FD list reported? 3.45 How can I supply device numbers for inaccessible NFS file systems? 3.46 Why won't lsof find open files on over-mounted file systems? 3.47 What can be done when lsof reports no more space? 3.48 What if the lsof build encounters ar and ld problems? 4.0 AIX Problems 4.1 What is the Stale Segment ID bug and why is -X needed? 4.1.1 Stale Segment ID APAR 4.2 Gcc Work-around for AIX 4.1x 4.3 Gcc and AIX 4.2 4.4 Why won't lsof's Configure allow the use of gcc for AIX below 4.1? 4.5 What is an AIX SMT file type? 4.6 Why does AIX lsof start so slowly? 4.7 Why does exec complain it can't find libc.a[shr.o]? 4.8 What does lsof mean when it says, "TCP no PCB, CANTSENDMORE, CANTRCVMORE" in a socket file's NAME column? 4.9 When the -X option is used on AIX 4.3.3, why does lsof disable it, saying "WARNING: user struct mismatch; -X option disabled?" 4.10 Why doesn't the -X option work on my AIX 5L or 5.[123] system? 4.11 Why doesn't /usr/bin/oslevel report the correct AIX version? 4.11.1 Why doesn't /usr/bin/oslevel report the correct AIX version on AIX 5.1? 4.12 Why does lsof for AIX 5.1 or above Power architecture complain about kernel bit size? 4.13 What can't gcc be used to compile lsof on the ia64 architecture for AIX 5 and above? 4.14 Why does lsof get a segmentation fault when compiled with gcc for a 64 bit Power architecture AIX 5.1 kernel? 4.15 Why does lsof ignore AFS on my AIX system? 4.16 Why does lsof report "system paging space is low" and exit? 4.17 Why does lsof have compilation and execution problems on AIX 5.3 above maintenance level 1? 5.0 Apple Darwin Problems 5.1 What do /dev/kmem-based and libproc-based mean? 5.2 /dev/kmem-based Apple Darwin Questions 5.2.1 Why does Configure ask for a path to the Darwin XNU kernel header files? 5.2.1.1 Why does Configure complain that Darwin XNU kernel header files are missing? 5.2.2 Why doesn't Apple Darwin lsof report text file information? 5.2.3 Why doesn't Apple Darwin lsof support IPv6? 5.2.4 Why does lsof complain about a mismatch between the release for which lsof was compiled and the booted Mac OS X release? 5.2.5 Why does lsof for Apple Darwin 8 and higher report "stat(...): ..." in the NAME column? 5.2.6 What are the limitations of Apple Darwin lsof link count reporting? 5.3 Libproc-based Apple Darwin Questions 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? 8.3 Why doesn't lsof work on the RELEASE version of CURRENT? 8.4 Why can't kvm_open() can't find some file? 8.5 FreeBSD ZFS Problems 8.5.1 Why does FreeBSD lsof report "WARNING: no ZFS support has been 8.6 Why can't Configure create lsof_owner.h for FreeBSD 6 and above? 8.6.1 Why are there lockf structure compiler errors for FreeBSD 6.0 and higher lsof? 8.6.2 Why don't /usr/src/sys/sys/lockf.h and /usr/include/sys/lockf.h match? 8.7 Why won't lsof compile with clang? 9.0 HP-UX Problems 9.1 What do /dev/kmem-based and PSTAT-based mean? 9.2 /dev/kmem-based HP-UX lsof Questions 9.2.1 Why doesn't a /dev/kmem-based HP-UX lsof compilation use -O? 9.2.2 Why doesn't the /dev/kmem-based CCITT support work under 10.x? 9.2.3 Why can't /dev/kmem-based lsof be compiled with `cc -Aa` or `gcc -ansi` under HP-UX 10.x? 9.2.4 Why does /dev/kmem-based lsof complain about no C compiler? 9.2.5 Why does Configure complain about q4 for /dev/kmem-based lsof for HP-UX 11? 9.2.6 When compiling /dev/kmem-based lsof for HP-UX 11 what do the "aCC runtime: ERROR..." messages mean? 9.2.7 Why doesn't /dev/kmem-based lsof for HP-UX 11 report VxFS file link counts, node numbers, and sizes correctly? 9.2.8 Why can't /dev/kmem-based lsof be built with gcc for 64 bit HP-UX 11? 9.2.8.1 How can I acquire a gcc for building lsof for 64 bit HP-UX 11? 9.2.9 Why does /dev/kmem-based lsof for HP-UX 11 report "unknown file system type" for VxFS files? 9.2.10 Why does the ANSI-C compiler complain about comments in HP-UX 11 header files? 9.2.11 Why does dnode1.c cause the HP-UX 11 compiler to complain that is missing or incorrect? 9.3 PSTAT-based HP-UX lsof Questions 9.3.1 Why does PSTAT-based lsof complain about pst_static and other PSTAT structures? 9.3.2 Why does PSTAT-based lsof complain it can't read pst_* structures? 9.3.3 Why does PSTAT-based lsof rebuild the device cache file after each reboot? 9.3.4 Why doesn't PSTAT-based lsof report TCP addresses for telnetd's open socket files? 9.3.5 Why does PSTAT-based lsof cause an HP-UX 11.11 kernel panic? 9.3.6 Why doesn't PSTAT-based lsof report a CWD that is on a loopback (LOFS) file system? 9.3.7 Why do some swinstall packages for PSTAT-based HP-UX 11.11 packages complain about setgid and setuid bits? 9.3.8 Why won't the bundled C compiler build PSTAT-based lsof for PA-RISC HP-UX 11.23? 9.3.9 Why won't gcc build PSTAT-based lsof for PA-RISC HP-UX 11.23? 9.3.10 Why does PSTAT-based lsof complain, "FATAL: pst_stream_size should be: 672; is 72" on HP-UX 11.11 and above? 9.4 Why won't the HP-UX depot install? 10.0 Linux Problems 10.1 What do /dev/kmem-based and /proc-based lsof mean? 10.2 /proc-based Linux lsof Questions 10.2.1 Why doesn't /proc-based lsof report file offsets (positions)? 10.2.2 Why does /proc-based lsof report "can't identify protocol" for some socket files? 10.2.3 Why does /proc-based lsof warn about unsupported formats? 10.2.4 Why does /proc-based lsof report "(deleted)" after a path name? 10.2.5 Why doesn't /proc-based lsof report full open file information for all processes? 10.2.6 Why won't Customize offer to change HASDCACHE or WARNDEVACCESS for /proc-based lsof? 10.2.7 /proc-based lsof Linux NFS questions 10.2.7.1 Why can't lsof find files on an accessible NFS file system? 10.2.7.2 Why can't lsof find files on an inaccessible NFS file system? 10.2.8 Why doesn't /proc-based Linux lsof report socket options and values, socket state flags, and TCP options and values? 10.2.9 Does /proc-based Linux lsof use a device cache? 10.2.10 Why doesn't /proc-based Linux lsof report any or all file structure values for its +fcfgGn option? 10.3 Special Linux file types 10.3.1 Why is ``DEL'' reported as a Linux file type? 10.3.2 Why is ``unknown'' reported as a Linux file type? 10.4 Linux ``mem'' Entry Problems 10.4.1 What do ``path dev=xxx'' and ``path inode=yyy'' mean in the NAME column of Linux ``mem'' file types? 10.4.2 Why is neither link count nor size reported for some Linux ``DEL'' and ``mem'' file types? 10.5 Special Linux NAME column messages 10.5.1 What does ``(stat: xxx)'' mean in the NAME column of Linux files? 10.5.2 What does ``(readlink: xxx)'' mean in the NAME column of Linux files? 10.6 Why is ``NOFD'' reported as a Linux file type? 10.7 Why does Linux lsof report a NAME column value that begins with ``/proc''? 10.8 Linux /proc/net/tcp* and /proc/net/udp* issues 10.8.1 Why use the Linux -X option? 10.8.2 Why does lsof say ``-i is useless when -X is specified''? 10.8.3 Why does lsof say ``can't identify protocol (-X specified)''? 11.0 NetBSD Problems 11.1 Why doesn't lsof report on open kernfs files? 11.2 Why doesn't lsof report on open files on: file descriptor file systems; /proc file systems; 9660 (CD-ROM) file systems; MS-DOS (floppy disk) file systems; or kernel file systems? 11.3 Why does lsof produce confusing results for nullfs file systems? 11.4 NetBSD header file problems 11.4.1 Why can't the compiler find some NetBSD header files? 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? 13.3 problems 13.3.1 Why does the compiler claim nbpg isn't defined? 13.3.2 What value should I assign to nbpg? 13.4 Why doesn't lsof report on open MS-DOS file system (floppy disk) files? 13.5 Why isn't lsof feature xxx enabled for OpenBSD? 14.0 Output problems 14.1 Why do the lsof column sizes change? 14.2 Why does the offset have ``0t' and ``0x'' prefixes? 14.3 What are the values printed in the FILE_FLAG column and why is 0x sometimes included? 14.3.1 Why doesn't lsof display FILE_FLAG values for my dialect? 14.4 Network Addresses 14.4.1 Why does lsof's -n option cause IPv4 addresses, mapped to IPv6, to be displayed in IPv6 notation? 14.5 Why does lsof output \x, ^x, or \xnn for characters sometimes? 14.5.1 Why is space considered a non-printable character in command names? 14.6 Why doesn't lsof print all the characters of a command name? 14.7 Why does lsof reject some -c command names, saying their lengths are "> what system provides (nn)"? 14.8 Why does lsof sometimes print TYPE numbers instead of names? 14.9 Marker line format problems 14.9.1 Why won't lsof accept a marker line format? 14.9.2 Why does lsof reject the NL (%n) marker line format? 14.10 How are protocol state name exclusion and inclusion used? 14.10.1 Why doesn't my dialect support state name exclusion and inclusion? 15.0 Pyramid Version Problems 15.0.5 Statement of deprecation 16.0 SCO Problems 16.1 SCO OpenServer Problems 16.1.1 How can I avoid segmentation faults when compiling lsof? 16.1.2 Where is libsocket.a? 16.1.3 Why do I get "warning C4200" messages when I compile lsof? 16.2 SCO|Caldera UnixWare Problems 16.2.1 Why doesn't lsof compile on my UnixWare 7.1.1 or above system? 16.2.2 Why does lsof complain about node_self() on my UnixWare 7.1.1 or above system? 16.2.3 Why does UnixWare 7.1.1 or above complain about -lcluster, node_self(), or libcluster.so? 16.2.4 Why does UnixWare 7.1.1 or above lsof complain it can't read the kernel name list? 16.2.5 Why doesn't lsof report link count, node number, and size for some UnixWare 7.1.1 or above CFS files? 16.2.6 Why doesn't lsof report open files on all UnixWare 7.1.1 NonStop Cluster (NSC) nodes? 16.2.7 Why doesn't lsof report the UnixWare 7.1.1 NonStop Cluster (NSC) node a process is using? 16.2.8 Why does the compiler complain about missing UnixWare 2.1[.x] header files? 17.0 Sun Problems 17.0.5 Statement of deprecation 17.1 My Sun gcc-compiled lsof doesn't work -- why? 17.2 How can I make lsof compile with gcc under Solaris 2.[456], 2.5.1, 7, 8 or 9? 17.3 Why does Solaris Sun C complain about system header files? 17.4 Why doesn't lsof work under my Solaris 2.4 system? 17.5 Where are the Solaris header files? 17.6 Where is the Solaris /usr/src/uts//sys/machparam.h? 17.7 Why does Solaris lsof say ``can't read proc table''? 17.8 Why does Solaris lsof complain about a bad cached clone device? 17.9 Why doesn't Solaris make generate .o files? 17.10 Why does lsof report some Solaris 2.3 and 2.4 lock types as `N'? 17.11 Why does lsof Configure say "WARNING: no cc in ..."? 17.12 Solaris 7, 8 and 9 Problems 17.12.1 Why does lsof say the compiler isn't adequate for Solaris 7, 8 or 9? 17.12.2 Why does Solaris 7, 8 or 9 lsof say "FATAL: lsof was compiled for..."? 17.12.3 How do I build lsof for a 64 bit Solaris kernel under a 32 bit Solaris kernel? 17.12.4 How do I install lsof for Solaris 7, 8 or 9? 17.12.5 Why does my Solaris 7, 8 or 9 system say it cannot execute lsof? 17.12.6 What gcc will produce 64 bit Solaris 7, 8 and 9 executables? 17.12.7 Why does lsof on my Solaris 7, 8 or 9 system say, "can't read namelist from /dev/ksyms?" 17.13 Solaris and COMMON 17.13.1 What does COMMON mean in the NAME column for a Solaris VCHR file? 17.13.2 Why does a COMMON Solaris VCHR file sometimes seem to have an incorrect minor device number? 17.14 Why don't lsof and Solaris pfiles reports always match? 17.15 Why does lsof say, "kvm_open(namelist=default, core=default): Permission denied?" 17.16 Why is lsof slow on my busy Solaris UFS file system? 17.17 Why is lsof so slow on my Solaris 8 or 9 system? 17.18 Solaris and VxFS 17.18.1 Why doesn't lsof support VxFS 3.4 on Solaris 2.6, and above? 17.18.2 Why does lsof report "vx_inode: vxfsu_get_ioffsets error" for open Solaris 2.6 and above VxFS 3.4 and above files? 17.18.3 Why does Solaris Configure claim there is no VxFS library? 17.18.4 Why doesn't Solaris lsof report VxFS path name components? 17.18.5 Why does Solaris 10 lsof report scrambled VxFS paths? 17.19 Large file problems 17.19.1 Why does lsof complain it can't stat(2) a Solaris 2.5.1 large file? 17.20 Why does lsof get a segmentation fault on 64 bit Solaris 8 using NIS+? 17.21 Will lsof crash the Solaris kernel? 17.22 Why does lsof on Solaris 7, 8, or 9 report a kvm_open() failure? 17.23 Solaris and SAM-FS 17.23.1 Why does Solaris lsof report "(limited SAM-FS info)"? 17.23.2 Why can't lsof locate named SAM-FS files? 17.24 Lsof and Solaris 10 zones 17.24.1 How can I make lsof list the Solaris zone? 17.24.2 Why doesn't lsof work in a Solaris 10 zone? 17.24.3 Why does lsof complain it can't stat() Solaris 10 zone file systems? 17.25 Solaris 10 problems 17.25.1 Why does Solaris 10 lsof sometimes report the wrong path name? 17.25.2 Why does Solaris 10 lsof sometimes report only the mounted-on directory and device? 17.25.3 What does "(deleted)" mean in the NAME column of a Solaris 10 open file? 17.25.4 What does "(?)" mean in the NAME column of a Solaris 10 open file? 17.26 Solaris contract file problems 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.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 and above? 18.0 Lsof Features 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? 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? 18.2.3 How do I put the personal device cache file in /tmp? 18.3 Why doesn't lsof know about AFS files on my favorite dialect? 18.3.1 Why doesn't lsof report node numbers for all AFS volume files, or how do I reveal dynamic module addresses to lsof? ______________________________________________________________________ 1.0 General Concepts 1.1 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, the 00DIST file, the 00QUICKSTART file, and the 00README file of the lsof distribution for more information. 1.2 Where do I get lsof? Lsof is available via anonymous ftp from lsof.itap.purdue.edu. Look in the pub/tools/unix/lsof sub-directory. ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof Bzip2'd, compressed and gzip'd tar files with GPG certificates are available. 1.2.1 Are there mirror sites? On April 28, 2009 these sites appeared to have the lastest lsof revision: ftp://ftp.fu-berlin.de/pub/unix/tools/lsof ftp://sunsite.ualberta.ca/pub/Mirror/lsof 1.2.2 Are lsof executables available? Some lsof executables are available in the subdirectory tree pub/tools/unix/lsof/binaries These are neither guaranteed to be current nor cover every dialect and machine architecture. I don't recommend you use pre-compiled lsof binaries; I recommend you obtain the sources and build your own binary. Even if you're a Sun user without a Sun C compiler, you can use gcc to compile lsof. If you must use a binary file, please be conscious of the security and configuration implications in using an executable of unknown or different origin. The lsof binaries are accompanied by GPG certificates. Please use them! 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. 1.2.3 How do I check the validity of an lsof distribution? There are two ways to check the validity of an lsof distribution: 1. Follow the instructions in the CHECKSUMS_ file found with the lsof distribution. Checking with GPG is the best method. 2. Follow the instructions in the "Security" section of the README.lsof_ file found inside the lsof distribution. Again, checking with GPG is the best method. 1.2.4 Why can't I get the sum(1) result reported in README.lsof_? The "Security" section of the README.lsof_ file found inside the lsof distribution gives md5, sum, and GPG certificate information. The simplest, the sum(1) signature, seems to be the trickiest. That's because there are different sum(1) methods, BSD systems usually have cksum(1) instead of sum(1), and different systems compute the block size value differently. First, the lsof sum results are computed with the old, "alternate" algorithm. On newer systems, you can use sum's "-r" option to get that computation result. Second, on BSD systems you usually must use cksum(1) instead of sum(1), because they have no sum(1). To tell cksum(1) to use the old, "alternate" algorithm, use its "-o1" option. Third, the second value that sum reports, the block count, may be computed differently on different systems -- usually block size is considered to be 512 or 1,024. The lsof block counts were computed on a system with a sum(1) option that considers block size to be 512. The BSD system cksum(1) -o1 option considers block size to be 1,024. If your sum(1) or cksum(1) doesn't report a block count that matches the sum(1) signature given in README.lsof_, check its man page to see what block size it uses, then adjust its reported block count appropriately. 1.2.5 Why won't gpg accept the lsof-signing PGP public key? An older PGP key that once signed lsof distributions is included in lsof revisions prior to 4.70. The PGP key is indeed my key, but is incompatible with GPG. It was created about ten years ago and is still acceptable to PGP versions 2.6.2 through 6.5.2. Lsof revisions 4.70 and above are signed with a copy of my PGP key that has been made acceptable for use with GPG by importing it under GPG's "--allow-non-selfsigned-uid" option. You can find my GPG compatible key in lsof revisions 4.70 and above and at: ftp://lsof.itap.purdue.edu/pub/Victor_A_Abell.gpg If you have an older lsof revision with my PGP key, there are two possible ways to use it: * Use it with a PGP version from 2.6.2 through 6.5.2. * Use GPG's "--allow-non-selfsigned-uid" option when you import my PGP key into your GPG key ring. $ gpg --allow-non-selfsigned-uid --import Victor_A_Abell.pgp 1.3 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, copious documentation in files whose names begin with 00, and a copy of this FAQ in the file 00FAQ (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: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/FAQ man page: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/lsof_man 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 . 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. 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. 1.5 Where can I get the lsof FAQ? This lsof FAQ is available in the file 00FAQ in the lsof distribution and at the URL: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/FAQ 1.5.1 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 send me e-mail at . I may be able to point you at a pre-release distribution that contains the support of interest. Make sure "lsof" appears in the "Subject:" line so my e-mail filter won't classify your letter as Spam. 1.6 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 $ (See 00TEST.) 1.7 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. 1.8 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. 1.9 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. */ 1.10 Language locale support 1.10.1 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. 1.10.2 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 1.11 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. 1.12 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/ 1.13 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. 2.0 Lsof Ports 2.1 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.2, 9.0 and 10.0 for AMD64-based systems 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 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. 2.2 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. 2.2.1 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. 2.3 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 encounted 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 2.4 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 2.5 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, contact me via e-mail at and I may be able to help. Make sure "lsof" appears in the "Subject:" line so my e-mail filter won't classify your letter as Spam. 3.0 Lsof Problems 3.1 Configuration Problems 3.1.1 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. 3.2 Compilation Problems 3.2.1 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. 3.2.2 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 presense 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. 3.2.3 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 . Please follow the reporting guidelines in the "How do I report an lsof bug?" section of this FAQ. 3.3 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 NEXTSTEP OpenBSD OPENSTEP 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 -inum -print and you may get an appreciation of what a file system directory tree search would cost. 3.3.1 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. 3.3.2 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. 3.3.3 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. 3.3.4 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. 3.3.5 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. 3.4 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 '' 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. 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 improvments 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. 3.5 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. 3.6 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 it's 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. 3.7 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. 3.8 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. 3.8.1 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. 3.9 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. 3.10 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. 3.10.1 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. 3.11 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. 3.12 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. 3.13 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. 3.14 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. 3.14.1 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. 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. 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. 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. 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. 3.14.2 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. 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) 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. 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 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. 3.15 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. 3.16 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. 3.17 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. 3.18 Portmap problems 3.18.1 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. 3.18.2 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'. 3.18.3 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). 3.19 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. 3.20 Why doesn't lsof report file offset (position)? Lsof won't report a file offset (position) value if the -s option has been specified, or if the dialect doesn't support the displaying of file offset (position). 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 to discuss the matter. Please follow the reporting guidelines in the "How do I report an lsof bug?" section of this FAQ. 3.20.1 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. 3.21 Problems with path name arguments 3.21.1 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 ` starts with a `b/), you can specify it's 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.) 3.21.2 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.) 3.21.3 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. 3.21.4 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 specify the individual path names of those files, or use the lsof +D and +d options. 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. 3.21.5 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. 3.21.6 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. 3.22 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, , with the rpcent structure definition, and there is a Solaris C pre-processor test that can tell when the BIND is in place and hence 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 and any other header files BIND might have replaced. (I think BIND replaces , , -- and maybe others.) 3.23 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 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. 3.24 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. 3.25 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. 3.26 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. 3.27 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. 3.28 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. 3.29 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. 3.30 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. 3.31 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. 3.32 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. 3.33 Installation 3.33.1 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?" 3.33.2 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. 3.34 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 : 2 sections ... lsof: WARNING: created device cache file: 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. 3.35 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 " or "like character special ". The value for 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.) 3.36 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 . 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. 3.37 Command Regular Expressions (REs) 3.37.1 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). 3.37.2 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 the first character it found after the second slash isn't an lsof command RE modifier -- 'b', 'i', or 'x'. 3.37.3 Why does lsof say my command regular expression wasn't found? When you use both forms of lsof's -c option -- ``-c '' 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 '' 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. 3.38 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. 3.39 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.) 3.40 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. 3.41 Kernel Symbol and Address Problems 3.41.1 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. 3.41.2 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. 3.42 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 $ make More information on the HASSECURITY and HASNOSOCKSECURITY options may be found in the "Security" section of the 00README file of the lsof distribution. 3.43 Test Suite Problems 3.43.1 Errors all tests can report: 3.43.1.1 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. 3.43.1.2 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 ... : 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. 3.43.1.3 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. 3.43.1.4 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. 3.43.1.5 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: No opportunity to continue is offered. The tests/Makefile "silent" rule will skip checking for the validation footprint. 3.43.1.6 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. 3.43.2 LTbigf test issues 3.43.2.1 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 . Make sure "lsof" appears in the "Subject:" line so my e-mail filter won't classify your letter as Spam. 3.43.2.2 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, 3.43.2.3 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. 3.43.3 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. 3.43.4 NFS test issues 3.43.4.1 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.) 3.43.5 LTnlink test issues 3.43.5.1 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 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 3.43.5.2 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. 3.43.5.3 Why does LTnlink fail because of an unlink error? LTnlink may fail with an error similar to: LTnlink ... ERROR!! unlink() 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 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 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/ where is a unique name in /tmp of your choosing. To be safe, create a subdirectory in /tmp, named by your login: $ rm -f /tmp/ $ mkdir /tmp/ $ ./LTnlink -p /tmp// 3.43.6 LTdnlc test issues 3.43.6.1 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. 3.43.6.2 What does the LTdnlc test mean by "... 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% 3.43.6.3 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. 3.43.7 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. 3.43.8 LTszoff test issues 3.43.8.1 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. 3.43.9 LTlock test issues 3.44 File descriptor list (the ``-d'' option) problems 3.44.1 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. 3.44.2 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 3.45 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 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. 3.46 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. 3.47 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. 3.48 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. 4.0 AIX Problems 4.1 What is the Stale Segment ID bug and why is -X needed? Kevin Ruderman reports that he has been informed by IBM that processes using the AIX 3.2.x, 4.1[.12345]], 4.2[.1], and 4.3.x kernel's readx() function can cause other AIX processes to hang because of what appears to be file system corruption. This failure, known as the Stale Segment ID bug, is caused by an error in the AIX kernel's journaled segment memory handler that causes the kernel's dir_search() function erroneously to believe directory entries contain zeroes. The process using the readx() call need not be doing anything wrong. Usually the system must be under such heavy load that the segment ID being used in the readx() call has been freed and then reallocated to another process since it was obtained from kernel memory. Lsof uses the readx() function to access library entry structures, based on the segment ID it finds in the proc structure of a process. Since IBM probably will never fix the kernel bug, I've added an AIX-specific option to lsof that controls its use of the readx() function. By default lsof readx() use is disabled; specifying the ``-X'' option enables readx() use. If you want to change the default readx() behavior of AIX lsof, change the HASXOPT, HASXOPT_ROOT, and HASXOPT_VALUE definitions in dialects/aix/machine.h. You can also use these definitions to enable or disable readx() -- consult the comments in machine.h. You may want to disable readx() use permanently if you plan to make lsof publicly executable. When HASXOPT_ROOT is defined, lsof will restrict use of the -X option to processes whose real UID is root; if HASXOPT_ROOT isn't defined, any user may specify the -X option. The Customize script offers the option to change HASXOPT_ROOT when HASXOPT is defined and HASXOPT_ROOT is named in any dialect's machine.h header file. I have never seen lsof cause a problem with its use of readx(), but I believe there is some chance it could, given the right circumstances. 4.1.1 Stale Segment ID APAR Here are the details of the Stale Segment ID bug and IBM's response, provided by Kevin Ruderman. AIX V3 APAR=ix49183 user process hangs forever in kernel due to file system corruption STAT=closed prs TID=tx2527 ISEV=2 SEV=2 (A "closed prs" is one closed with a Permanent ReStriction.) RCOMP=575603001 aix v3 for rs/6 RREL=r320 AIX V4 (internal defect, no apar #) prefix p name 175671 abstract KERMP: loop for ever in dir_search() Problem description: 1. Some user application -- e.g., lsof -- gets the segment ID (SID) for the process private segment of a target process from the process table. 2. The target process exits, deleting the process private segment. 3. The SID is reallocated for use as a persistent segment. 4. The user application runs again and tries to read the user area structure from /dev/mem, using the SID it read from the process table. 5. The loads done by the driver for /dev/mem cause faults in the directory; new blocks are allocated; the size changed; and zero pages created. 6. The next application that looks for a file in the affected directory hangs in the kernel's dir_search() function because of the zero pages. This occurs because the kernel's dir_search() function loops through the variable length entries one at a time, moving from one to the next by adding the length of the current entry to its address to get the address of the next entry. This process should end when the current pointer passes the end of the known directory length. However, while the directory length has increased, the entry length data has not, so when dir_search() reaches the zero pages, it loops forever, adding a length of zero to the current pointer, never passing the end of the directory length. The application process is hung; it can't be killed or stopped. IBM closed the problem with a PRS code (Permanent ReStriction) under AIX Version 3 and had targeted a fix for AIX 4.2. They have recently (I became aware of it September 10, 1996) cancelled the defect report altogether and have indicated they are not going to fix the defect. 4.2 Gcc Work-around for AIX 4.1x When gcc is used to compile lsof for AIX 4.1x, it doesn't align one element of the user structure correctly. Xlc sees the U_irss element as a type "long long" and aligns it on an 8 byte boundary. That's because the default mode of xlc is -qlonglong; when -qlonglong is enabled, the _LONG_LONG symbol is also defined. Gcc sees U_irss as a two element array of type long, because _LONG_LONG isn't defined. Hence gcc aligns the U_irss element array on a 4 byte boundary, rather than an 8 byte one, making the gcc incantation of the user structure 4 bytes shorter than xlc's. When the length of gcc's user structure is supplied as argument 4 to the undocumented getuser() function of the AIX kernel, getuser() rejects it as an incorrect size and returns EINVAL. Lsof has a work-around for this problem. It involves a special test in the Configure script when the "aixgcc" Configure abbreviation is used -- e.g., $ Configure -n aixgcc The test is to compile a small program with gcc and check the alignment of U_irss. If it's not aligned on an 8 byte boundary, the Configure script makes a special copy of in ./dialects/aix/aix whose U_irss will align properly, and generates compile time options to use it. While I have tested this work-around only with 4.1.4, it should work with earlier versions of AIX 4.1. It does not work for AIX 4.2; a different work-around is employed there. (See the next section.) If you want to use this technique to compile other AIX 4.1x programs with gcc for using getuser(), check the Configure script. Stuart D. Gathman identified this gcc AIX alignment problem. 4.3 Gcc and AIX 4.2[.1] Alignment problems with gcc and AIX 4.2[.1] inside the user structure are more severe, because there are some new 64 bit types in AIX that gcc doesn't yet (as of 2.7.x) support. The U_irss element problem, discussed in 4.3 above, doesn't exist in 4.2[.1]. The AIX lsof machine.h header file has a work-around, provided by Henry Grebler, that bypasses gcc alignment problems. Later versions of gcc (e.g., 2.8.x) will probably bypass the problems as well. 4.4 Why won't lsof's Configure allow the use of gcc for AIX below 4.1? Gcc can't reliably be used to compile lsof for AIX versions below AIX 4.1 because of possible kernel structure element alignment differences between it and xlc. 4.5 What is an AIX SMT file type? When you run AIX X clients with the DISPLAY environment variable set to ``:0.0'' they communicate with the AIX X server via files whose kernel file structure has an undefined type (f_type == 0xf) -- at least there's no definition for it in . These are Shared Memory Transport (SMT) sockets, an artifact of AIXWindows, designed for more efficient data transfers between the X server and its clients. Henry Grebler and David J. Wilson alerted me to the existence of these files. Mike Feldman and others helped me identify them as SMT sockets. The curious reader can find more about SMT sockets in /usr/lpp/X11/README.SMT. 4.6 Why does AIX lsof start so slowly? When AIX lsof starts it compares the running kernel's identity to the one for which it was built, using /usr/bin/oslevel. That comparison can sometimes take a long time to complete, depending on the system's maintenance level and how recently it was examined with oslevel. AIX revisions 4.67 and above for AIX 5 and above don't use oslevel to determine the kernel identity. They use uname(2) instead, and it is much faster. You can skip the oslevel test by suppressing warning messages with lsof's -w option. Doing that carries with it the risk of missing other warning messages, however. You can also disable the kernel identity check by disabling the definition of the HASKERNIDCK symbol by editing AIX machine.h header file or by using the Customize script to disable it. See the "Why does lsof warn "compiled for x ... y; this is z.?" section for more information. 4.7 Why does exec complain it can't find libc.a[shr.o]? When you try to execute lsof you may get this complaint: exec(): 0509-036 Cannot load program ./lsof because of the following errors: 0509-022 Cannot load library libc.a[shr.o]. 0509-026 System error: A file or directory in the path name does not exist. This is probably the result of making lsof when the LIBPATH environment variable contained a directory path that doesn't contain libc.a. You can see what LIBPATH contained when lsof was made by using the dump application on lsof. For example, if LIBPATH contained /foo/bar when lsof was made, you will see this (partial) dump output: $ dump -H lsof ... ***Import File Strings*** INDEX PATH BASE ... 0 /foo/bar To correct the problem, revisit the lsof source directory and remake lsof this way: $ unset LIBPATH; make (sh or ksh) or % unsetenv LIBPATH; make (csh or tcsh) 4.8 What does lsof mean when it says, "no PCB, CANTSENDMORE, CANTRCVMORE" in a socket file's NAME column? When an AIX application calls shutdown(2) on an open socket file, but hasn't called close(2) on the file, the file will remain visible to lsof as an open socket file without any extended protocol information. Lsof reports that state in the NAME column by saying that there is "no PCB" (Protocol Control Block) for the protocol (e.g., TCP in the NODE column). If the open socket file has the state variables SO_CANTSENDMORE and SO_CANTRCVMORE set -- i.e., from the shutdown(2) call -- lsof reports them with the CANTSENDMORE and CANTRCVMORE notes in the NAME column. 4.9 When the -X option is used on AIX 4.3.3, why does lsof disable it, saying "WARNING: user struct mismatch; -X option disabled?" The -X option causes lsof to read the loader information of the user structure from virtual memory via the readx() system call. It does that with the user structure definition from that was compiled into the lsof executable. On AIX 4.3.3 there are two different user structure definitions in two separate header files, distributed at different times by IBM. If lsof was compiled with one and the kernel on which lsof is being run was compiled with the other, lsof normally won't get correct loader information when it calls readx(). In an attempt to compensate for that difference, lsof makes an independent check of the loader information by getting the user structure's open file count via readx() and comparing it to the open file count obtained independently via getprocs(). When the two counts don't match, lsof tries to read the count (and re-read the loader information) with two offsets, based on observed differences between the two user structures. When one of the three attempts produces a correct open file count, lsof uses its corresponding offset on subsequent readings of the loader information. When none of the three attempts produces a correct open file count, lsof issues the WARNING message and disables -X processing. To eliminate this problem, obtain an lsof binary that matches the kernel of the AIX 4.3.3 system where you want to run lsof. Compiling lsof on the target system is the preferred way to get a matching binary. 4.10 Why doesn't the -X option work on my AIX 5L or 5.[123] system? If your AIX 5L or 5.[123] system uses the ia64 architecture, lsof needs setuid-root permission to be able to do the processing that -X requires. Check the output of `uname -a` to determine the architecture type. The work-around is to give lsof setuid-root permission. 4.11 Why doesn't /usr/bin/oslevel report the correct AIX version? The oslevel man page says, "The oslevel command reports the level of the operating system using a subset of all filesets installed on your system." You can see which fileset is below the expected level with oslevel's -l option. For example, if you believe your system is at AIX level 4.3.3, but oslevel reports 4.3.2, use this oslevel command to find the filesets below 4.3.3: $ /usr/bin/oslevel -l 4.3.3.0 If you don't know what level argument to supply to oslevel's -l option, use oslevel's -q option first. 4.11.1 Why doesn't /usr/bin/oslevel report the correct AIX version on AIX 5.1? The subset list for oslevel on AIX 5.1 seems to include at least two filesets, xlsmp.msg.en_US.rte and xlsmp.rte, that do not install from AIX 5.1 media with a 5.1.0.0 level. Hence, oslevel reports 5.0.0.0 instead of the expected 5.1.0.0. If either xlsmp.msg.en_US.rte or xlsmp.rte is installed, lsof's Configure script and run-time tests will identify the AIX version incorrectly. The run-time test will issue a complaint message of this form: lsof: WARNING: compiled for AIX version xxx; this is yyy. You can correct the Configure test by pre-defining the oslevel value, setting the correct value in the LSOF_VSTR environment variable before running the Configure script -- e.g., to pre-define AIX 5.1 when using ksh, do this: $ LSOF_VSTR=5.1.0.0 Configure -n aix You can't affect oslevel output without uninstalling xlsmp.msg.en_US.rte and xlsmp.rte. If you can't do that, you'll have to put up with the run-time complaint. 4.12 Why does lsof for AIX 5.1 or above Power architecture complain about kernel bit size? When you run an lsof binary on an AIX 5.1 or above Power system, it might complain: lsof: FATAL: compiled for a 32 bit kernel. The bit size of this kernel is 64. or exec: 0509-036 Cannot load program ./lsof because of the following errors: 0509-032 Cannot run a 64-bit program on a 32-bit machine. Starting at lsof revision 4.61, lsof binaries for Power architecture systems running AIX 5.1 or above are closely tied to the kernel bit size. Lsof must do that so it can read and understand kernel structures. Lsof's Configure script tunes the lsof configuration so that the binary built in the make(1) step is adjusted to the kernel bit size. An lsof binary knows the bit size for which it was constructed, tests the bit size of the kernel under which it is running, and objects if the two sizes don't match. To see the bit size for which lsof was constructed, run it with its -v option and look for these lines in the output: configuration info: 32 bit kernel or configuration info: 64 bit kernel (Note: these lines will appear only in -v output for AIX 5.1 and above lsof binaries, built for Power architecture.) You can see the kernel bit size test method in the aix stanza of the lsof Configure script and in the get_kernel_access() function of the lsof .../dialects/aix/dproc.c source file. There is more information on pre-defining the kernel bit size when building lsof in Configure, 00PORTING, and 00XCONFIG. The only work-around is to use an lsof binary built to match the running kernel bit size. 4.13 What can't gcc be used to compile lsof on the ia64 architecture for AIX 5 and above? Gcc can't be used to compile lsof on the ia64 architecture for AIX 5 and above because I haven't had access to a system that has a working gcc compiler. The gcc compiler on my one and only ia64 AIX 5.1 test system, provided by IBM, didn't work at all. 4.14 Why does lsof get a segmentation fault when compiled with gcc for a 64 bit Power architecture AIX 5.1 kernel? When lsof is configured with the lsof "aixgcc" Configure abbreviation, the resulting lsof executable may cause a segmentation violation when it is run. I've observed this with gcc version 2.9-aix43-010414-7. As far as I have been able to tell, the segmentation fault is the result of a gcc compilation, loading, or library error. Watching lsof run with gcc's companion debugger, gdb, shows no error in the lsof source code that might explain the fault. The only work-around I know is to use the IBM C compiler in place of gcc -- i.e., use the "aix" lsof Configure abbreviation. 4.15 Why does lsof ignore AFS on my AIX system? The lsof Configure script quits on AIX when AFS is present, the AIX version is greater than 4.3.3.0 or the AFS version is greater than 3.5. That's because I have no test systems available for those AIX and AFS version combinations. When the lsof Configure script detects an AIX and AFS version combination that is unsupported, it will report: !!!FATAL: Lsof does not support AFS on this combination of AIX and AFS versions. To disable AFS, set the value of the AIX_HAS_AFS environment variable to "no". The only work-around is to set the AIX_HAS_AFS environment variable as explained in the error message: $ AIX_HAS_NSF=no; export AIX_HAS_NFS $ ./Configure -n aix 4.16 Why does lsof report "system paging space is low" and exit? When AIX paging space runs low, the AIX kernel sends a SIGDANGER signal to processes, warning them that they should reduce their memory usage. When lsof receives that signal, it issues the following fatal error message and exits: lsof: FATAL: system paging space is low. A possible work-around is to limit the amount of information lsof must cache in its process memory with the "-c", "-g", "-l" and "-p" options. Also see the answer to the "What can be done when lsof reports no more space?" question. 4.17 Why does lsof have a compilation problem on AIX 5.3 above maintenance level 1? On some AIX 5.3 systems with maintenance levels 2 and higher installed, lsof 4.77 and below may not compile properly. The compiler complains the snapshotObject structure definition, needed by , is missing. That problem is fixed in the 4.78 revision. 5.0 Apple Darwin Problems 5.1 What do /dev/kmem-based and libproc-based mean? Lsof for Apple Darwin currently uses /dev/kmem to read kernel data structures from which it gathers and reports open file information. That version of lsof is called /dev/kmem-based lsof. 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. The /dev/kmem-based lsof sources may be found in the kmem subdirectory of the dialects/darwin branch of the lsof source tree. When the supporting version of Apple Darwin is released, the libproc-based lsof sources will be found in .../dialects/darwin/libproc. 5.2 /dev/kmem-based Apple Darwin Questions 5.2.1 Why does Configure ask for a path to the Darwin XNU kernel header files? When lsof was ported to Apple Darwin by Allan Nathanson at revision 4.53, some kernel header files needed by lsof weren't being exported by the developers. (That's still true at lsof revision 4.76.) At first a shell script that Allan provided would get the missing header files by checking them out from the CVS root. Although the script was updated from time to time, eventually the re-organization of Darwin sources has made it impossible to update the script to do an automatic download of the missing header files. At lsof revision 4.69 and above it is necessary for the Darwin lsof builder to download the Darwin XNU kernel headers before attempting to build lsof. The download my be done via a web browser, starting at this URL: http://www.opensource.apple.com/darwinsource/index.html Once there, select the link to the Mac OS X version that matches the one on the system where lsof is to be built. Follow that link's "[ Source ]" link. Once there, select the tar.gz link of the xnu* entry near the bottom of the page. That entry should have a name that matches the xnu* name shown by `uname -a` -- e.g., if uname reports: $ uname -a ... root:xnu/xnu-517.7.21 ... Then the appropriate xnu* entry is xnu-517.7.21. Clicking its link should lead to an "Apple Open Source" page requesting an Apple ID and password. Enter them if they're available. If an Apple ID and password are not available, get them by following the instructions on the page -- i.e., follow the signin.apple.com link. Once a valid Apple ID and its password have been entered, the download will begin. Select the saving of the downloaded xnu*.tar.gz file in an appropriate place on the Mac OS X system. Once the download completes, install it. Use gunzip to decompress the download and tar to extract the archive -- e.g., $ gunzip -c xnu-517.7.21.tar.gz | tar xf - Remember the absolute path to the extracted archive. That is its installed place. E.g., if the xnu-517.7.21.tar archive was extracted to the lsof builder's home directory, its full installation path will be something like: ~/xnu-517.7.21 Now run the lsof Configure script. When it asks for the path to the installed Darwin XNU kernel header files, supply the path to the gunzip'd and extracted xnu* archive -- e.g., ~/xnu-517.7.21. The path to the Darwin XNU kernel headers may also be supplied to the Configure script in the DARWIN_XNUDIR environment variable, eliminating the need to enter it interactively -- e.g., $ DARWIN_XNUDIR=~/xnu-344.49 ./Configure -n darwin 5.2.1.1 Why does Configure complain that Darwin XNU kernel header files are missing? These are some reasons why the lsof Configure script might claim that Darwin XNU header files are missing: * The wrong path to them was specified. * The files and directories in the path are not readable and searchable -- i.e., check the modes and ownerships. * The downloaded archive doesn't match the Mac OS X version of the system. If in doubt, revisit the Darwin XNU kernel header file download instructions in the answer to the question "Why does Configure ask for a path to the Darwin XNU kernel header files?" If Configure still can't find Darwin XNU kernel header files, contact me via e-mail at for help. Make sure "lsof" appears in the "Subject:" line so my e-mail filter won't classify your letter as Spam. 5.2.2 Why doesn't Apple Darwin lsof report text file information? At the first port of lsof to Apple Darwin, revision 4.53, insufficient information was available -- logic and header files -- to permit the installation of VM space scanning for text files. As of lsof 4.70 it is sill not available. Text file support will be added to Apple Darwin lsof after the necessary information becomes available. 5.2.3 Why doesn't Apple Darwin lsof support IPv6? At the first port of lsof to Apple Darwin, revision 4.53, Apple Darwin lacked IPv6 support. IPv6 became available in Apple Darwin version 1.5 and support for it was added to lsof then. 5.2.4 Why does lsof complain about a mismatch between the release for which lsof was compiled and the booted Mac OS X release? When lsof is started on the "Gold Master" Darwin release (aka Mac OS X), it complains: lsof: compiled for 1.0 release; this is 1.3.2. This happens because the lsof binary released with Mac OS X was built on a system whose release number (1.0) doesn't match that of the released system -- usually 1.3.x Lsof makes this check because UNIX dialect OS changes are often accompanied by header file changes that affect lsof. In this specific case, this error can be ignored. If you don't want to do that, get the lsof distribution and build lsof so its built-on and running-on Mac OS X release numbers match. 5.2.5 Why does lsof for Apple Darwin 8 and higher report "stat(...): ..." in the NAME column? Lsof for Apple Darwin 8 may report messages like these in the NAME column: stat(/private/var/run/asl_prune): No such file or directory or stat(/private/var/db/netinfo/local.nidb/Config): Permission denied Those messages indicate that lsof was unable to collect open file information for the paths enclosed in "stat(...)" with the stat(2) function, because the function encountered the reported error. A work-around for the "Permission denied" error is to run lsof with elevated privileges -- e.g., when logged on as the super user. If the stat(2) error message is "No such file or directory", the file probably has been unlinked (removed) and there is no lsof work-around. 5.2.6 What are the limitations of Apple Darwin lsof link count reporting? Lsof for Apple Darwin cannot report link count information reliably. For Apple Darwin below 8 link count information is not always available in the kernel node structures available to lsof. When link count information is available, however, it includes link counts of zero. Thus, using lsof's +L1 option may result in the finding of some files whose link counts are zero. Lsof can report only some link count information for Apple Darwin 8 and above. Link count information is only available for files where lsof can assemble the full file path and has permission to apply stat(2) to it. (See the answer to the "Why does lsof for Apple Darwin 8 and higher report "stat(...): ..." in the NAME column?" question for more information on stat(2) failures.) Apple Darwin 8 and above files that have been unlinked and thus have a link count of zero cannot be found by stat(2) -- i.e., stat(2) returns a "No such file or directory" error. As a result lsof never displays link counts of zero and the use of lsof's +L1 option to find them always fails. 5.3 Libproc-based Apple Darwin Questions 6.0 BSD/OS BSDI Problems 6.0.5 Statement of deprecation As of lsof revision 4.76 support for BSDI BSD/OS has been 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//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? Lsof doesn't report on open FreeBSD kernfs files because the structures lsof needs aren't defined in the kernfs.h header file in /sys/misc/kernfs. 8.2 Why doesn't lsof work on my FreeBSD system? If lsof doesn't work on your FreeBSD system, first make sure you have the latest lsof revision. See the answer to the "Where do I get lsof?" question for information on how to get the latest lsof revision. Once you have gotten the latest lsof revision, Configure and make it. If Configure fails -- e.g., it complains about an unknown FreeBSD version -- then lsof probably hasn't been ported to your FreeBSD version yet, and there's no need to go any further. Follow the answer to the "How do I report an lsof bug" to report the Configure complaint to me. If you are able to Configure and make lsof, run its test suite. (See the answer to the "Is there a test suite?" question for more information on how to use lsof's test suite.) If lsof still fails, make sure your kernel sources, kernel header files, kernel boot file, standard header files and libraries are synchronized. They should all be built from the same CVS refresh. (Don't forget to do a "make buildworld" followed by a "make installworld".) If they aren't, then the KVM library or lsof may be using kernel structure definitions that don't match the booted kernel; or lsof may fail to compile properly because of header files in /usr/src/sys/sys and /usr/include/sys that don't match. If you have synchronized your kernel, header files and libraries, and still can't get lsof to work, follow the steps in the answer to the "How do I report an lsof bug" question to report the problem to me. 8.3 Why doesn't lsof work on the RELEASE version of CURRENT? Lsof tracks the CURRENT release of the current leading edge FreeBSD version, because my access to leading edge FreeBSD is limited to FreeBDSD.org reference systems, all running the CURRENT release. Sometimes that tracking leads to changes in lsof that won't work on an earlier RELEASE version of the current leading edge version. When that happens, please send e-mail to me . Make sure "lsof" appears in the "Subject:" line so my e-mail filter won't classify your letter as Spam. 8.4 Why does kvm_open() complain it can't find some file? If lsof issues this complaint: lsof: kvm_open(execfile=/boot/kernel/kernel, corefile=/dev/mem: No such file or directory Your FreeBSD system might not have a /dev/mem device. If not, create one -- e.g., as root do: # mknod /dev/mem c 0 # chmod 440 /dev/mem # chgrp kmem /dev/mem For use /dev/kmem's major device number. You may have to run kldload, too -- again as root do: # kldload mem 8.5 FreeBSD ZFS Problems 8.5.1 Why does FreeBSD lsof report "WARNING: no ZFS support has been defined."? Lsof issues that message when it detects a file on a ZFS file system, but has not been built with support for ZFS. Lsof's Configure script detects support can be added for ZFS when it finds this file: /usr/src/sys/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h That header file and others in the OpenSolaris files in /usr/src enable lsof to extract information about ZFS files from the kernel structures associated with them. 8.6 Why can't Configure create lsof_owner.h for FreeBSD 6 and above? Lsof may report: Creating ./lockf_owner.h from /usr/src/sys/kern/kern_lockf.c FATAL ERROR: can't read /usr/src/sys/kern/kern_lockf.c FATAL ERROR: ./lockf_owner.h creation failed (see 00FAQ) or Creating ./lockf_owner.h from /usr/src/sys/kern/kern_lockf.c FATAL ERROR: ./lockf_owner.h creation failed (see 00FAQ) Those messages mean that lsof's Configure script failed to create a local header file, ./lockf_owner.h, needed to use the new kernel file locking code of some versions of FreeBSD 6 and above. The changes that implement that new locking code alter the lockf structure in and introduce a new structure, lockf_entry, to that header file. When Configure detects the presence of the lockf_entry definition in , it tries to construct the local header file, ./lockf_owner.h. Configure has to do that because an unfortunate side effect of the new kernel file locking code is that doesn't contain the lockf_owner structure definition referenced in its own lockf structure. Lsof needs to access elements of that lockf_owner structure to determine if a lock belongs to the process that has a file open. The missing lockf_owner structure definition is in the kernel source file, typically /usr/src/sys/kern/kern_lockf.c. Configure tries to extract the lockf_owner structure definition from kern_lockf.c into lsof's local header file, ./lockf_owner.h. If Configure can't do that, it reports: FATAL ERROR: ./lockf_owner.h creation failed If Configure can't even read kern_lockf.c, it first reports: FATAL ERROR: can't read /usr/src/sys/kern/kern_lockf.c The work-around for this problem is to update the FreeBSD kernel /usr/src tree (e.g., do a CVSup or csup) on the system where lsof is to be built and then do a "make buildworld" followed by a "make installworld". 8.6.1 Why are there lockf structure compiler errors for FreeBSD 6.0 and higher lsof? If, when compiling lsof, the compiler complains with error messages like: dnode.c: In function 'get_lock_state': dnode.c:113: error: 'struct lockf' has no member named 'lf_flags' dnode.c:115: error: 'struct lockf' has no member named 'lf_id' ... Then lsof is being built on a system that has new kernel file locking code and lsof's Configure script failed to build a local lockf_owner.h header file with a structure definition lsof needs. See the "Why can't Configure create lsof_owner.h for FreeBSD 6 and above?" section for more information and a work-around. 8.6.2 Why don't /usr/src/sys/sys/lockf.h and /usr/include/sys/lockf.h match? This mismatch can cause the errors explained in the answer to the "Why are there lockf structure compiler errors for FreeBSD 6.0 and higher lsof?" question. If /usr/src/sys/sys/lockf.h has been updated with a CVSup or csup, the new lockf.h won't be propagated to /usr/include/sys until the "make buildworld" and "make installworld" steps have been completed. 8.7 Why won't lsof compile with clang? As of October 2011 lsof revision 4.85 will not compile with clang on FreeBSD because the FreeBSD system header files do not conform to clang requirements. There is no work-around. 9.0 HP-UX Problems 9.1 What do /dev/kmem-based and PSTAT-based mean? Lsof for HP-UX 11.0 and below uses /dev/kmem to read kernel data structures from which it gathers and reports open file information. That version of lsof is called /dev/kmem-based lsof. Starting with HP-UX 10.10, finding definitions for the necessary kernel structures became more difficult as HP no longer distributed header files in /usr/include that defined all kernel structures. So I started "inventing" structure definitions by using Q4 to display them. By HP-UX 11, the process of invention became extremely intensive to support. Following a patch to the ipc_s structure in early 1999, my invented definition of that structure became incorrect. Although I was able to devise a work-around test for the patch with Q4, it was clear that my inventions were bound to cause more problems. Discussion with HP about the patch led to my proposing that an lsof API in the HP-UX kernel was the proper solution. Much to my surprise, HP agreed. I believe Carl Davidson was the prime mover behind that decision, but I know others participated, among them Louis Huemiller, Rich Rauenzahn, and Sailu Yallapragada. I am indebted to these folks and HP for their willingness to do this work. The API was added to the PSTAT interface in a project named PEGL, Pstat Enhancements for Glance and Lsof. Louis and Sailu did the bulk of the design and implementation work and testing began in March, 2000 HP-UX 11.11 is the first version that provides PSTAT support for lsof. HP-UX versions in between 11.0 and 11.11 -- all Beta versions as far as I can determine -- have no lsof support. See the "PSTAT-based HP-UX lsof Questions" section for questions and answers specific to PSTAT-based HP-UX lsof. The next section, "Why doesn't a /dev/kmem-based HP-UX lsof compilation use -O?" covers /dev/kmem-based HP-UX lsof. The /dev/kmem-based lsof sources may be found in the kmem subdirectory of the dialects/hpux branch of the lsof source tree. The PSTAT-based lsof sources may be found in .../dialects/hpux/pstat. 9.2 /dev/kmem-based HP-UX lsof Questions The sources for /dev/kmem-based lsof for HP-UX may be found in lsof_/dialects/hpux/kmem. Lsof's Configure shell script decides to use these sources when it finds that the /usr/include/sys/pstat subdirectory doesn't exist. Lsof can be forced to use the /dev/kmem sources by setting "/dev/kmem" in the HPUX_BASE environment variable. Consult the Configure shell script and 00XPORTING for more information. 9.2.1 Why doesn't a /dev/kmem-based HP-UX lsof compilation use -O? If you only have the standard (bundled) HP-UX C compiler and haven't purchased and installed the optional one, then you can't use cc's -O option. The HP-UX cc(1) man page says this: "Options Note that in the following list, the cc and c89 options -A , -G , -g , -O , -p , -v , -y , +z , and +Z are not supported by the C compiler provided as part of the standard HP-UX operating system. They are supported by the C compiler sold as an optional separate product." Lsof's Configure script tries to detect what C compiler product you have installed by examining your compiler. If that examination reveals a standard (bundled) compiler, lsof avoids using -O. If the Configure compiler test fails, the C compiler will complain that it doesn't support -O. You can suppress that complaint with this make invocation: $ make DEBUG="" 9.2.2 Why doesn't the /dev/kmem-based CCITT support work under 10.x? Pasi Kaara, who originally provided the HP-UX CCITT support, reports that it no longer works under HP-UX 10.x. Consequently, at lsof revision 4.02 it has been disabled. 9.2.3 Why can't /dev/kmem-based lsof be compiled with `cc -Aa` or `gcc -ansi` under HP-UX 10.x? Some HP-UX 10.x header files, needed by lsof, can't be compiled properly in ANSI_C mode; structure element definition and alignment problems result. The f_offset member of the file structure, for example, is incorrect. This ANSI-C obstacle extends to using the -Aa option of the HP C compiler and the -ansi option of gcc. 9.2.4 Why does /dev/kmem-based lsof complain about no C compiler? Lsof's Configure script looks in /bin and /usr/ccs/bin for an HP C compiler, because it needs to know if the compiler is the standard (bundled) one or the optional separate product. If it finds no compiler in either place, Configure quits after complaining: No executable cc in /bin or /usr/ccs/bin If you don't have a C compiler in either of these standard places, you should consider installing it. If you have gcc installed, you can use it by declaring the ``hpuxgcc'' abbreviation to lsof's Configure script. If you have a C compiler in a non-standard location, you can use the HPUX_CCDIR[12] environment variables to name the path to it. Consult the 00XCONFIG file of the lsof distribution for more information. 9.2.5 Why does Configure complain about q4 for /dev/kmem-based lsof for HP-UX 11? When you run Configure on an HP-UX 11 system, it may complain: !!!ERROR!!! !!!ERROR!!! !!!ERROR!!! !!!ERROR!!! Configure can't use /usr/contrib/bin/q4 to examine the ipis_s structure. You must do that yourself, report the result in the HPUX_IPC_S_PATCH environment variable, then repeat the Configure step. Consult the Configure script's use of /usr/contrib/bin/q4 and the 00XCONFIG file for information on ipis_s testing and the setting of HPUX_IPC_S_PATCH. !!!ERROR!!! !!!ERROR!!! !!!ERROR!!! !!!ERROR!!! This message states that Configure cannot use q4 from /usr/contrib/bin to examine the kernel's boot image for the ipis_s structure. Maybe q4 hasn't been installed, or perhaps Configure can't execute it. Lsof needs to gather information about ipis_s to determine if the ipis_s structure is defined in the kernel boot image, if the ipis_s structure of the kernel boot image has an ipis_msgsqueued member, and if the ipc_s structure of the kernel boot image uses has an ipc_ipis member. The ipis_s structure isn't described in any header file HP-UX releases with HP-UX 11. It appears in the private lsof header file .../dialects/hpux/kmem/hpux11/ipc_s.h. Lsof gets local and remote connection addresses (IP and port numbers) from ipc_s, so an incorrect ipc_s definition may cause incorrect reporting of TCP/IP connection addresses. It definitely will cause incorrect reporting on 32 bit kernels. In any case lsof should be compiled with a correct ipc_s definition no matter the kernel bit size, so the Configure script always tests for it when the HP-UX version is 11. For lsof's Configure script to gather the necessary ipis_s information q4 needs to be installed in /usr/contrib/bin and the kernel boot image, /stand/vmunix, needs to have been processed with pxdb. If either is untrue, lsof issues the above error message, perhaps preceded by q4 messages. (Note: lsof's use of q4 may also fail if q4 can't execute nm -- e.g., it can't find /usr/bin/nm, or there is a conflicting, private version of nm earlier in the path.) If /stand/vmunix hasn't been processed by pxdb, the q4 messages will include: q4: (error) vmunix not pxdb'd or q4: (warning) /stand/vmunix has not been processed by pxdb. It's possible to make a suitable private copy of /stand/vmunix for configuring lsof. That requires /opt/langtools/bin/pxdb or the q4 version of pxdb from /usr/contrib/bin/q4pxdb. The path to the result is supplied to the lsof Configure script in the HPUX_BOOTFILE environment variable. Configure still requires /usr/contrib/bin/q4. The following sample Bourne shell commands make a private copy of /stand/vmunix in /tmp, process it with pxdb or q4pxdb, and supply its path to lsof's Configure script in HPUX_BOOTFILE. $ cp /stand/vmunix /tmp/vmunix.lsof $ /opt/langtools/bin/pxdb /tmp/vmunix.lsof or $ /usr/contrib/bin/q4pxdb /tmp/vmunix.lsof ... pxdb messages ... $ HPUX_BOOTFILE=/tmp/vmunix.lsof Configure -n hpux It may also be necessary to use q4 outside the lsof Configure script. In that case q4 can be to determine the state of ipis_s and ipc_s with these q4 commands: $ /usr/contrib/bin/q4 /stand/vmunix ... q4> fields -c struct ipc_s ... q4> fields -c struct ipis_s Look in the q4 output for the ipc_ipis member of the ipc_s structure, and look in the q4 output for the ipis_s structure for the ipis_msgsqueued member. If ipc_s has ipc_ipis but ipis_s lacks ipis_msgsqueued, set HPUX_IPC_S_PATCH environment variable to "1". If ipc_s has ipc_ipis and ipis_s has ipis_msgsqueued, set HPUX_IPC_S_PATCH to "2" -- e.g., $ HPUX_IPC_S_PATCH=1 Configure -n hpux or $ HPUX_IPC_S_PATCH=2 Configure -n hpux If ipc_s has no ipc_ipis member, set HPUX_IPC_S_PATCH to "N" -- e.g., use this Configure step: $ HPUX_IPC_S_PATCH=N Configure -n hpux 9.2.6 When compiling /dev/kmem-based lsof for HP-UX 11 what do the "aCC runtime: ERROR..." messages mean? When the lsof Makefile asks the HP-UX unbundled compiler to load lsof, it may complain: /bin/cc -o lsof -DHPUXV=1100 -DHASVXFS -DHPUXKERNBITS=64 \ -I/home/abe/src/lsof4/dialects/hpux/kmem/hpux11 +DD64 \ -DHAS_IPC_S_PATCH=2 -I/home/abe/src/lsof4/dialects/hpux/kmem \ -DLSOF_VSTR=\"B.11.00\" -g 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 -L./lib -llsof -lelf \ -lnsl aCC runtime: ERROR: Unexpected use of shared libraries aCC runtime: ERROR: Read aCC manpage, +A option /usr/lib/nls/loc/locales.1//is_IS.iso88591 This is a bug in the HP-UX national language support. (Notice the last message with "locales" in it?) Complain to HP -- then use this work-around before executing make: $ unset LANG $ make 9.2.7 Why doesn't /dev/kmem-based lsof for HP-UX 11 report VxFS file link counts, node numbers, and sizes correctly? This is usually the result of running an lsof binary whose revision number is less than 4.57 on a system that has OnlineJFS support installed. It can also happen with lsof 4.57 binaries when the OnlineJFS support with which they were built doesn't match the OnlineJFS status of the system on which they are run. The OnlineJFS status of lsof 4.57 and higher binaries can be determined by running: $ lsof -v 2>&1 | grep HASONLINEJFS If that shell pipe produces output, lsof was compiled with OnlineJFS support enabled; no output, disabled. If OnlineJFS is installed on an HP-UX 11 system the /sbin/fs/vxfs/subtype executable exists and outputs "vxfs3.3" when run. The problem occurs because the optional OnlineJFS support installation doesn't update . Consequently lsof can be compiled with an incorrect definition of the vx_inode structure and look for for link counts, node numbers, and sizes in the wrong places in the structure. The current response I have gotten from HP is that no update will be provided for OnlineJFS. I've addressed this problem temporarily with a work-around (hack) in lsof revision 4.57. 9.2.8 Why can't /dev/kmem-based lsof be built with gcc for 64 bit HP-UX 11? When Configure is given the "hpuxgcc" abbreviation, the HP-UX version is 11, and the kernel bit size is 64, the lsof Configure script may abort with the messages: !!!!!!!!!!!!!!!!! FATAL ERROR !!!!!!!!!!!!!!!!!! APPARENTLY GCC CANNOT BUILD 64 BIT EXECUTABLES. A COMPILER MUST BE USED THAT CAN. SEE 00FAQ FOR MORE INFORMATION. (This is the "more information" in 00FAQ.) This means the Configure script compiled a test program with gcc the result wasn't an ELF-64 binary. Lsof tries two gcc modes, one with no options and another with the -mlp64 option, before it concludes gcc can't be used. See the "How can I acquire a gcc for building lsof for 64 bit HP-UX 11?" answer for information on where you might be able to get a gcc for HP-UX 11 that can produce ELF-64 executables. 9.2.8.1 How can I acquire a gcc for building lsof for 64 bit HP-UX 11? Check this HP URL: http://h21007.www2.hp.com/dspp/tech/tech_TechSoftwareDetailPage_IDX/1,1703,547,00.html (That's one very long link; be careful you cut 'n paste it all.) In November 2001 that URL led to a web page whose title was "gcc for hp-ux 11." The page offered a link for downloading a 64 bit gcc 3.0 compiler for HP-UX 11.0 and 11i. Rich Rauenzahn of HP installed that compiler on an HP test system he allows me to use and I successfully built a 64 bit lsof with it. The HP package may install the 64 bit capable gcc in /usr/local/pa20_64/bin/gcc, so you may have to adjust your path or set the LSOF_CC environment variable to compensate. 9.2.9 Why does /dev/kmem-based lsof for HP-UX 11 report "unknown file system type" for some open files? The lsof binary being used probably doesn't have support for the VxFS file system. To confirm that, check `lsof -v` output for "-DHASVXFS". If it's not present, lsof doesn't have VxFS support. You also need to establish that lsof really is complaining about VxFS files by checking the kernel boot file for the symbol associated with the hexadecimal address reported in the "unknown file system type" message -- e.g., "v_op: 0x8711c8." Use nm(1) to do that: $ nm -x /stand/vmunix | grep 8711c8 If nm reports the symbol associated with the address is vx_vnodeops, then lsof is complaining about an open VxFS file. The solution in that case is to build lsof yourself (The bundled C compiler will do it.), making sure that lsof's Configure script detects the presence of VxFS. Configure does that by finding these two header files: /usr/include/sys/fs/vx_hpux.h /usr/include/sys/fs/vx_inode.h If the system where you are building lsof doesn't have those header files, but does have VxFS, you might be able to install the header files by installing the HP JournalFS package from the CoreOS CD -- in particular the file set JournalFS.VXFS-PRG and its associated patch, PHKL_18543. (My thanks to Steve Bonds for that information.) Finally, if you find that lsof isn't complaining about VxFS when it complains about an unknown file system type, send e-mail to me for further assistance. Make sure "lsof" appears in the "Subject:" line so my e-mail filter won't classify your letter as Spam. 9.2.10 Why does the ANSI-C compiler complain about comments in HP-UX 11 header files? When compiling lsof on HP-UX 11, the HP ANSI-C compiler's pre-processor, cpp, may complain about comments in HP-UX header files -- e.g., cpp: "/usr/include/sys/cdfs.h", line 232: warning 2028: Found comment inside comment started on line 232. cpp: "/usr/include/sys/cdnode.h", line 196: warning 2028: Found comment inside comment started on line 196. cpp: "/usr/include/nfs/snode.h", line 30: warning 2028: Found comment inside comment started on line 30 This is not a problem with lsof. It is a problem with the HP-UX header files; they have non-compliant ANSI-C comment sequences in them -- e.g., : 232 /* struct cdfs *cdfs_link; /* linked list of file systems */ The initial "/*" is not terminated by an ending "*/" before the appearance of a second "/*". 9.2.11 Why does dnode1.c cause the HP-UX 11 compiler to complain that is missing or incorrect? If CFLAGS in the lsof Makefile for an HP-UX 11 compilation includes HASONLINEJFS, indicating the system has OnlineJFS support, lsof needs the header file. Sometimes it is missing from /usr/include/sys/fs. is a header file that must be obtained from Veritas. If that proves impossible, please contact me via e-mail at . Make sure "lsof" appears in the "Subject:" line so my e-mail filter won't classify your letter as Spam. 9.3 PSTAT-based HP-UX lsof Questions The sources for PSTAT-based lsof for HP-UX may be found in lsof_/dialects/hpux/pstat. Lsof's Configure shell script decides to use these sources when it finds that the /usr/include/sys/pstat subdirectory exists. Lsof can be forced to use the PSTAT-based sources by setting "pstat" in the HPUX_BASE environment variable. Consult the Configure shell script and 00XPORTING for more information. 9.3.1 Why does PSTAT-based lsof complain about pst_static and other PSTAT structures? When lsof starts it may issue one of these fatal error messages: lsof: FATAL: can't determine PSTAT static size lsof: FATAL: can't read bytes of pst_static lsof: FATAL: pst_static doesn't contain _size lsof: FATAL: _size should be These messages indicate that lsof's tests for the proper level of PSTAT support have failed. The structure names, given in , and sizes, given in , identify the support deficiency more precisely. You may need to upgrade the PSTAT support in your kernel to be able to use PSTAT-based lsof. 9.3.2 Why does PSTAT-based lsof complain it can't read pst_* structures? Lsof may put messages like the following in the NAME column of its output. can't read cwd pst_filedetails: Permission denied can't read mem pst_filedetails: Permission denied can't read rtd pst_filedetails: Permission denied can't read txt pst_filedetails: Permission denied can't read pst_filedetails: Permission denied can't read 3 stream structures: Permission denied can't read pst_socket: Permission denied These messages indicate that the lsof binary lacks the authority to read the name structures for processes other than ones belonging to the UID under which lsof is running. Authority to read the structures of other processes is limited to root processes -- i.e., lsof must have setuid-root permission if it is to list open files for arbitrary processes. If you want to eliminate these errors, you must run lsof as root or install it with setuid-root permission. 9.3.3 Why does PSTAT-based lsof rebuild the device cache file after each reboot? After each HP-UX rebuild, the first time a user runs lsof it will report: lsof: WARNING: device cache mismatch: /dev/tun... lsof: WARNING: created device cache file: / This happens because the device numbers on /dev/tun* device nodes are recalculated at each reboot. When lsof detects a change in the device number of a /dev/tun* file, it rebuilds its local device cache file. 9.3.4 Why doesn't PSTAT-based lsof report TCP addresses for telnetd's open socket files? When lsof can't report TCP addresses for telnetd's open socket files it is because an unpatched PSTAT kernel interface doesn't report the addresses to lsof. This has been addressed in PSTAT kernel patch PHKL_24047. It is available from the HP IT Resource Center at: http://itrc.hp.com In the page's "maintenance / support" box select the "individual patches" link. Once at its page, select the "hp-ux" link. On that page select the "Series 800" or "Series 700" radio button and select "11.11" from the pull-down list to the right of the button. Under "search or browse the path list" select "Search by Patch IDs" from the pull down list, enter PHKL_24047 in the following text box, and select search. That should lead to information about PHKL_24047 and a link for downloading it. (You may have to log in first and you may have to create a login identity by registering before you can log in.) Some time in March 2006 the PHKL_24047 patch was "lost" by the HP-UX networking lab. It has been "found" again in August 2006 and will be re-released as a GRO patch "some time." I don't yet know when that will be. You must contact HP to learn about the availability of the GRO patch. 9.3.5 Why does PSTAT-based lsof cause an HP-UX 11.11 kernel panic? When PSTAT-based lsof runs on some HP-UX 11.11 kernels, the kernel may panic. Symptoms include: Console message: 0xFBE000301100EF00 00000000 0000EF00 - type 31 = legacy PA HEX chassis-code /var/adm/syslog: ... vmunix: Trap Type 15 (Data page fault) ... vmunix: Instruction Address (pcsq.pcoq) = 0x... The panic is caused by a bug in the way PSTAT's pstat_getstream() function obtains module names from streams managed by the otsam stream driver (part of OSI Transport Services). Lsof calls pstat_getstream() when it encounters an open otsam stream file. An HP-UX 11.11 system uses otsam if otsam appears in /stand/system. HP-UX 11.11 patch PHKL_24507 (available some time after July 15, 2001) fixes the pstat_getstream() bug. See the information in the answer to the "Why doesn't PSTAT-based lsof report TCP addresses for telnetd's open socket files?" question for information on how to obtain the patch. 9.3.6 Why doesn't PSTAT-based lsof report a CWD that is on a loopback (LOFS) file system? When PSTAT-based lsof reports on processes whose current working directory (CWD) is on a loopback file system, lsof can't report the open CWD file. The reason is that the HP-UX 11.11 and above kernel's loopback file system code is not passing the CWD file ID to the kernel's pstat(2) code. Hence lsof is given no information on the lofs CWD. The problem was first reported to me by Ermin Borovac and an internal bug report was filed with the HP-UX file system group on October 26, 2004. That report has now been answered by the patch PHKL_33200 -- s700_800 11.11 lofs cumulative patch. The HP IT Resource Center (http://itrc.hp.com) is a source for the patch. 9.3.7 Why do some swinstall packages for PSTAT-based HP-UX 11.11 packages complain about setgid and setuid bits? First, let me explain that I do not provide lsof swinstall packages for lsof. Others provide them and they should be contacted about problems with their packages. However, I have become aware of a problem with one package about which I have some information I can share. The problem shows up in these swinstall messages: ERROR: Unknown owner and/or group for file "/usr/local/bin/lsof". SUID and/or SGID bit was not set. ERROR: Failed installing fileset "lsof.lsof-RUN,r=4.73". Check the above output for details. The swpackage SUID/SGID functionality was restricted by changes for POSIX compliance, breaking backward compatibility. The patch PHCO_27671 allows SUID/SGID for uid/gid of 0 only, as a compromise between backward compatibility and POSIX conformance. If the setuid bit is to be set on the executable, the UID and GID of the executable must be 0 (zero). 9.3.8 Why won't the bundled C compiler build PSTAT-based lsof for PA-RISC HP-UX 11.23? A PA-RISC HP-UX 11.23 bundled C compiler dated May 2005 or later will not build PSTAT-based lsof. It will deliver error messages related to the system's header file. There is nothing wrong with that header file or lsof. The problem is that the bundled C compiler can't cope with the gssapi.h header file. The work-around is to use the HP ANSI C compiler. Using gcc is not a satisfactory work-around. See the answer to the "Why won't gcc build PSTAT-based lsof for PA-RISC HP-UX 11.23?" question for more information. 9.3.9 Why won't gcc build PSTAT-based lsof for PA-RISC HP-UX 11.23? Gcc will not even compile PSTAT-based lsof revisions below 4.77 for PA-RISC HP-UX 11.23 dated May 2005 or later. It reports errors in lsof's print.c fill_portmap() function about missing members of the rpcent structure. That happens because gcc defines _XOPEN_SOURCE_EXTENDED which disables the definition of the rpcent structure in . Using the HP bundled C compiler is not a viable work-around. That is explained in the answer to the "Why won't the bundled C compiler build PSTAT-based lsof for PA-RISC HP-UX 11.23?" While an lsof revision 4.77 or higher can be compiled with gcc, the results are unreliable. Lsof will compile, but it occasionally produces segment faults when it runs. I have not been able to reproduce the failure reliably or locate a debugger that will work with the gcc-compiled lsof. The only reliable work-around is to use the HP ANSI C compiler. 9.3.10 Why does PSTAT-based lsof complain, "FATAL: pst_stream_size should be: 672; is 72" on HP-UX 11.11 and above? This message indicates a mismatch between the PSTAT header files used to build lsof ( and those in the /usr/include/sys/pstat subdirectory), and those that built the running kernel. Unfortunately the June 2008 patch set for HP-UX 11.23 creates this inconsistency, because it does not contain all the patches needed to match the kernel with the PSTAT header files. Even more serious is that the missing patches update the kernel's PSTAT support to provide TCP/UDP endpoint information to lsof from TCP/TLI streams. The patch inconsistency comes about because, while the following patch is installed, PHKL_36577 1.0 PM-PSTAT section 2 manpage changes other kernel patches are not. The PHKL_36577 patch updates the PSTAT header files and manual pages to match kernel changes that other patches with the following numbers (or patches that contain or supersede them) contain: PHNE_36575 1.0 Cumulative STREAMS Patch PHNE_37670 1.0 cumulative ARPA Transport patch PHNE_37851 1.0 NFS cumulative patch Those patches implement the kernel changes that support the delivery of information promised in patch PHKL_36577. The work-around is to install the missing patches. 9.4 Why won't the HP-UX depot install? I don't distribute lsof depots, so I can't support them. From time to time depots prepared by various sites -- e.g., usually HP-UX software collection sites -- will contain errors that cause installation of the depot to fail. Do not contact me when this happens. Instead, contact the administrator of the site that prepared the depot. As should be clear from the bulk of the lsof documentation, I do not recommend you use pre-built lsof binaries in any form. Instead, I recommend you obtain the lsof source distribution and build lsof yourself. 10.0 Linux 10.1 What do /dev/kmem-based and /proc-based lsof mean? At approximately Linux 2.1.72 and exactly at lsof revision 4.23 support for Linux forks. The first fork, containing the oldest lsof form is based on access to kernel memory structures, and is called /dev/kmem-based lsof. A /dev/kmem-based lsof is heavily intertwined with the Linux kernel version, its header files, and its system map file. Typically a /dev/kmem-based lsof needs only setgid permission to local all open file information. After approximately Linux 2.1.72 and at revision 4.23 lsof obtains all its information from the /proc file system. That lsof is called the /proc-based lsof. A /proc-based lsof does not read kernel memory, needs neither kernel header files nor the system map file, and is less likely to be affected by Linux kernel changes. However, it does require setuid-root permission to list all open files, and it can't report file offsets (positions). After revision 4.52 the /dev/kmem-based Linux sources for lsof are no longer distributed. Information about them may be found in the 00INDEX and README files at: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/OLD/src 10.2 /proc-based Linux lsof Questions 10.2.1 Why doesn't /proc-based lsof report file offsets (positions)? /proc-based lsof revisions 4.79 and above can only report file offsets (positions) for the files of Linux kernels 2.6.22 and above. During its initialization /proc-based lsof tests to see if offset information can be obtained. If it cannot, lsof disables offset reporting. If the -o option was selected, lsof also issues this warning: lsof: WARNING: can't report offset; disregarding -o. 10.2.2 Why does /proc-based lsof report "can't identify protocol" for some socket files? /proc-based lsof may report: COMMAND PID ... TYPE ... NODE NAME pump 226 ... sock ... 309 can't identify protocol This means that it can't identify the protocol (i.e., the AF_* designation) being used by the open socket file. Lsof identifies protocols by matching the node number associated with the /proc//fd entry to the node numbers found in selected files of the /proc/net sub-directory. Currently /proc-based lsof examines these protocol files: /proc/net/ax25 (untested) /proc/net/ipx (needs kernel patch) /proc/net/raw /proc/net/raw6 /proc/net/tcp /proc/net/tcp6 /proc/net/udp /proc/net/udp6 /proc/net/unix If /proc-based lsof says it can't identify the protocol for an open socket file, you may be able to identify the protocol yourself by using grep to look for the specific node number in the files of /proc/net -- e.g., $ grep /proc/net/* You may not be able to find the desired node number, because not all kernel protocol modules fully support /proc/net information. If you find a matching node number in a /proc/net file that is not currently being processed by lsof, contact me via e-mail at . I'll discuss adding support to /proc-based lsof for the protocol of the /proc/net file with you. Make sure "lsof" appears in the "Subject:" line so my e-mail filter won't classify your letter as Spam. The code that matches node numbers of open IPX protocol socket files to those in /proc/net/ipx requires Jonathan Sergent's Linux 2.1.79 patch to /usr/src/linux/net/ipx/af_ipx.c. The patch, suitable for input to Larry Wall's patch program, may be found in the lsof distribution file: .../dialects/linux/proc/patches/net_ipx_af_ipx.c.patch 10.2.3 Why does /proc-based lsof warn about unsupported formats? Lsof may issue the following warning: lsof: WARNING: unsupported format: /proc/net/ if the header line of the indicated in /proc/net -- ax25, ipx, raw, tcp, udp, or unix -- doesn't match what lsof expects to find. When the header line of a /proc/net file isn't what lsof expects, lsof probably can't parse the rest of the file correctly and doesn't try. As a result, lsof can't report any NAME column information (e.g., local and remote addresses) for socket files bound to the indicated network protocol. If you get this warning, please send me e-mail at . Include the contents of the file lsof claims has an unsupported format. Make sure "lsof" appears in the "Subject:" line so my e-mail filter won't classify your letter as Spam. 10.2.4 Why does /proc-based lsof report "(deleted)" after a path name? The "(deleted)" notation following a path name in /proc-based lsof's NAME column comes from the /proc//fd/ entry for the open file. It's the Linux kernel's way of indicating the file is open but has been unlinked (rm'd). 10.2.5 Why doesn't /proc-based lsof report full open file information for all processes? /proc-based lsof can only report on processes whose /proc files it has permission to read. /proc normally grants permission to read all its files only to root or to the owning user ID. Without permission to read most /proc files, lsof can only report full information for processes belonging to the user who is running lsof. /proc-based lsof may be able to report some information for all processes, depending on the permissions of their associated /proc files, but usually /proc-based lsof won't be able to access the files in /proc//fd/ that describe regular open files. If you want /proc-based lsof to report on all processes, you must install it with setuid-root permission. 10.2.6 Why won't Customize offer to change HASDCACHE or WARNDEVACCESS for /proc-based lsof? /proc-based lsof doesn't read device information from /dev or the device cache file, so it makes no sense to change the state of device cache processing or /dev node accessibility warnings. 10.2.7 /proc-based lsof Linux NFS questions 10.2.7.1 Why can't lsof find files on an accessible NFS file system? On occasion lsof may be unable to identify that an open file is on an NFS file system. This is most likely the result of a bug in the way the Linux kernel supplies information to the reader of /proc/mounts (lsof) -- sometimes that pseudo-file is truncated by the kernel. One way to see if this is the case is to search for the NFS file system in /proc/mounts -- e.g., $ grep /proc/mounts If you get no output or the third word of the output isn't "nfs", then lsof won't consider the file system an NFS file system. A second test is to look at the end of /proc/mounts -- e.g., $ tail /proc/mounts If tail reports "# truncated" then /proc/mounts is incomplete because of a Linux kernel bug. The bug is documented at: http://www.xss.co.at/sysinfo/mounts.html The bug is fixed in Linux kernel 2.4.18, and possibly in some earlier Linux kernel versions. 10.2.7.2 Why can't lsof find files on an inaccessible NFS file system? If lsof issues this message about a Linux file system, mounted from an NFS server: lsof: WARNING: can't stat() nfs file system /xxx/yyy Then lsof won't be able to find any open files on the file system. That's because of an inadequacy in the Linux /proc file system. Its /proc/mounts file doesn't give the device doublet (major and minor numbers) of the file system as do many UNIX systems (e.g., Solaris). The only way lsof can get the device doublet for a Linux file system is to call stat(2) on the file system path, which fails if the NFS server isn't accessible. When lsof doesn't know the device doublet of a file system, it can't find open files on the inaccessible file system, because it can't match the doublets of open files to the doublet of the inaccessible file system. This topic is covered extensively in lsof(8) it its ALTERNATE DEVICE NUMBERS and BLOCKS AND TIMEOUTS sections. 10.2.8 Why doesn't /proc-based Linux lsof report socket options and values, socket state flags, and TCP options and values? The Linux /proc file system doesn't report socket options and values, socket states, and TCP options and values to lsof. 10.2.9 Does /proc-based Linux lsof use a device cache? No. The Linux /proc//fd/* entries provide device names to lsof via readlink(2). It is not necessary to enable device cache processing for /proc-based Linux lsof via the Customize script or modifications to the Linux machine.h header file. 10.2.10 Why doesn't /proc-based Linux lsof report any or all file structure values for its +fcfgGn option? /proc-based lsof revisions 4.79 and above can only report some file structure values for Linux kernels below 2.6.22. When running on Linux kernels at 2.6.22 and above lsof 4.79 can report some file flag values -- i.e., in response to the +fg or +fG options. The flag values are obtained from the /proc//fdinfo/ files introduced at Linux kernel 2.6.22. /proc-based Linux lsof tests its availability to obtain file flag values at initialization. If values are not available, lsof disables file flag reporting. If the flags were requested with +fg or +fG, lsof displays this warning: lsof: WARNING: can't report file flags; disregarding +f. As a special note, when Linux lsof can report flag bits, it will not report 'R' for a read-only file. There is no read-only flag bit O_* symbol in (or ) and lsof reports only bits that are set. The absence of O_RDWR and O_WRONLY flag bits implies the file is read-only. 10.3 Special Linux file types 10.3.1 Why is ``DEL'' reported as a Linux file type? Lsof usually reports entries from the Linux /proc//maps file with ``mem'' in the TYPE column. However, when lsof can't stat(2) a path in the process' ``maps'' file and the ``maps'' file entry contains ``(deleted)'', indicating the file was deleted after it had been opened, lsof reports the file type as ``DEL''. 10.3.2 Why is ``unknown'' reported as a Linux file type? Lsof may report a Linux file's type as ``unknown'' in the TYPE column when lsof can't obtain complete stat(2) results for the file. Usually the NAME column will contain a ``(stat: xxx)'' error message, but that could have been suppressed with the lsof ``-w'' option. 10.4 Linux ``mem'' Entry Problems 10.4.1 What do ``path dev=xxx'' and ``path inode=yyy'' mean in the NAME column of Linux ``mem'' file types? When the device or inode number in the process' ``maps'' file entry doesn't match the stat(2) results from the file path, lsof reports the inconsistent information from the stat(2) of the path parenthetically after the path in the NAME column in one of these forms: (path dev=xxx) only the device number, ``xxx'', from a stat(2) of the ``maps'' file entry path differs from the ``maps'' file entry value reported in the DEVICE column. (path inode=yyy) only the inode number, ``yyy'', from a stat(2) of the ``maps'' file entry path differs from the ``maps'' file entry value reported in the NODE column. (path dev=xxx inode=yyy) Both device and inode numbers differ. Lsof reports the ``maps'' file device number in the DEVICE column and the inode number in the NODE column. When device and inode mismatches occur, lsof suppresses the reporting of link count and size. See the answer to the "Why is neither link count nor size reported for some Linux ``DEL'' and ``mem'' file types?" question for more information. Device and inode inconsistencies can occur when a file at a ``maps'' path is replaced after the process has started, or when a different file system with similar path names is mounted on top of the original file system. The device inconsistency parenthetical messages can be suppressed with lsof's ``-w'' option. 10.4.2 Why is neither link count nor size reported for some Linux ``DEL'' and ``mem'' file types? Link count and size are not reported for some entries from the process' ``maps'' file because a stat(2) of the entry file path failed or stat(2) delivered device or inode numbers that don't match the ones in the ``maps'' entry. When the stat(2) device or inode numbers don't match those in the ``maps'' file entry, it is likely that the stat(2) results don't apply to the file that was originally mapped by the process and whose path appears in the ``maps'' file entry, so lsof tries to avoid reporting possibly incorrect information. See the answer to the "What do ``path dev=xxx'' and ``path inode=yyy'' mean in the NAME column of Linux ``mem'' file types?" for more information on how mismatched stat(2) device and inode numbers are reported. 10.5 Special Linux NAME column messages 10.5.1 What does ``(stat: xxx)'' mean in the NAME column of Linux files? When lsof tried to stat(2) the path in the NAME column, the stat(2) system call failed and produced an error message of ``xxx''. This situation usually occurs if the lsof process lacks permission to stat(2) the path -- e.g., the lsof executable lacks root permission, or lsof is attempting to stat(2) a path on an NFS device mounted with the root_squash option. The message can be suppressed with lsof's ``-w'' option. 10.5.2 What does ``(readlink: xxx)'' mean in the NAME column of Linux files? When lsof tried to convert the /proc//fd path, reported in the NAME column, to its full and more meaningful path, the readlink(2) system call used to do the conversion failed. The readlink(2) failure message is ``xxx''. This situation usually occurs if the lsof process lacks permission to readlink(2) some part of the path -- e.g., the lsof executable lacks root permission, or lsof is attempting to stat(2) a path on an NFS device mounted with the root_squash option. The message can be suppressed with lsof's ``-w'' option. 10.6 Why is ``NOFD'' reported as a Linux file type? When lsof lacks permission to use opendir() on the fd/ subdirectory of a process' /proc/ directory, it reports a single file of the type ``NOFD'' (for no file descriptors). Lsof reports the the /proc//path in the NAME column, followed by "(opendir: xxx)", where ``xxx'' is the error message returned by opendir(). The ``NOFD'' entry can be suppressed with lsof's ``-w'' option. 10.7 Why does Linux lsof report a NAME column value that begins with ``/proc''? When lsof has problems processing a ``/proc/'' entry -- e.g., it can't convert the entry to a full and more meaningful path name, or it can't access the /proc//fd subdirectory with opendir() -- it will report the /proc/ path in the NAME column. 10.8 Linux /proc/net/tcp* and /proc/net/udp* issues 10.8.1 Why use the Linux -X option? If you're not interested in TCP/IP socket information for a particular use of lsof, adding the -X option will make lsof run more quickly, because -X inhibits the reading of the /proc/net/tcp* and /proc/net/udp* files. For example, you may only be interested in knowing what process has a particular file open. When the Linux system has a large number of open TCP/IP socket files, the time savings provided by -X can be significant. 10.8.2 Why does lsof say ``-i is useless when -X is specified''? If -X is specified, lsof can't report much information on open TCP/IP socket files. However, lsof's -i option requests that information. Hence, the two options conflict and can't be used together. 10.8.3 Why does lsof say ``can't identify protocol (-X specified)''? If the Linux lsof -X option is specified and an open socket file can't be identified without accessing the /proc/net/tcp* and /proc/net/udp* files, lsof will report that it can't identify the socket's protocol and that the failure may be caused by the -X specification 11.0 NetBSD Problems 11.1 Why doesn't lsof report on open kernfs files? Lsof doesn't report on open NetBSD kernfs files because the structures lsof needs aren't defined in the kernfs.h header file in /sys/misc/kernfs. 11.2 Why doesn't lsof report on open files on: file descriptor file systems; /proc file systems; 9660 (CD-ROM) file systems; MS-DOS (floppy disk) file systems; or kernel file systems? Lsof is not able to report on open files on certain file system if /usr/src/sys/msdosfs didn't exist when the lsof Configure script ran and lsof was made. /usr/src/sys/msdosfs contains header files lsof needs for collecting data on certain file system files. You can tell if an lsof executable above) lacks support for a file system if the following test of `lsof -v` produces nothing: $ lsof -v 2>&1 | grep The will be: File System Type Definition Note ---------------- ---------- ---- File descriptor HASFDESCFS /proc HASPROCFS 9660 HAS9660FS MS-DOS HASMSDOSFS (lsof 4.61 and above) Kernel HASKERNFS The work-around is to install /usr/src/sys, rerun the lsof Configure script, and remake lsof. 11.3 Why does lsof produce confusing results for nullfs file systems? Consider this report from /sbin/mount: /usr/home on /home type null (local) (According to /sbin/mount /usr/home is the mounted-on device and /home is the mounted-on directory.) When lsof is asked to report on open files on /home, it will report them as files on /usr/home instead. That's an artifact of the NetBSD kernel's dynamic name lookup cache (DNLC) and the way the kernel handles nullfs mounted-on directories. While lsof will report all open files on /home when given /home as a file system directory argument, even though reporting them as located on /usr/home, lsof will not find the same files when asked to report on all open files on /usr/home when given /usr/home as a file system device argument. That's because from the mount perspective /usr/home is equivalent to a device, but from the device perspective it is still a directory. So, what this lsof command reports: $ lsof /home ... NAME ... /usr/home/... Won't be duplicated by this lsof command: $ lsof /usr/home Another way to look at this confusing /home and /usr/home example is to consider what stat(2) reports. For /home stat(2) reports a device doublet that matches what lsof finds in open file node structures, while the device doublet stat(2) reports for /usr/home won't match what lsof finds. Nor does the mode reported by stat(2) indicate a block devices, as is the expected case. There is no simple answer to this confusion, nor is there even a simple explanation. Simply be aware that when supplying file system arguments to lsof on NetBSD, use the mounted-on directory name for a nullfs as the lsof argument, and don't be surprised when the NAME column reports the mounted-on device name. 11.4 NetBSD header file problems 11.4.1 Why can't the compiler find some NetBSD header files? If the compiler's pre-processor complains it can't find some header files when it compiles lsof source files, /usr/include and /usr/src may not have all the header files lsof needs. As a work-around use the NETBSD_SYS environment variable to specify to lsof the location of the additional header files -- e.g., % setenv NETBSD_SYS /my_source % ./Configure -n netbsd or $ NETBSD_SYS=/mys_source ./Configure -n netbsd Caution: using this work-around may cause the lsof Configure script to activate or omit different features, depending on where it finds the header files that determine the state of the features. 11.4.2 Why does NetBSD lsof produce incorrect output? If the NetBSD system's kernel was built from header files that don't match those in /usr/include -- e.g., //usr/src has the ones from which the kernel was built -- lsof may build, but won't produce correct output. As a possible work-around, try directing the C compiler to select header files from /usr/src before it selects them from /usr/include. That can be done with the DEBUG make string -- e.g., $ make DEBUG="-I/usr/src -I/usr/include" If that work-around fails, try using the LSOF_INCLUDE and NETBSD_SYS environment variables to swap /usr/include and /usr/src when running the Configure script, then use the make DEBUG string when running make -- e.g., $ LSOF_INCLUDE=/usr/src; export LSOF_INCLUDE $ NETBSD_SYS=/usr/include; export NETBSD_SYS $ ./Configure -n netbsd $ make DEBUG="-I/usr/src -I/usr/include" 11.5 Why isn't lsof feature xxx enabled for NetBSD? Lsof's Configure script enables NetBSD features by locating and examining header files associated with the features, and based on what it finds, setting compile-time definitions in Makefiles. (See 00PORTING for a list of the definitions.) When Configure doesn't find header files or doesn't find appropriate values in header files, that may mean the header file tree lsof is searching is incomplete or out of date. Lsof normally looks for NetBSD header files in /usr/include. It can also be directed to look in other directories -- e.g., /sys -- if told to do so with the contents of the LSOF_INCLUDE and NETBSD_SYS environment variables. To determine what header file enables a missing feature, check the NetBSD stanza in the Configure script. Then check the locations it checks for the indicated header files and contents. See 00XCONFIG for more information on LSOF_INCLUDE and 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 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? Lsof supports the kernel file system on OpenBSD versions whose /sys/miscfs/kernfs/kernfs.h (or header file correctly defines the kern_target structure. The lsof Configure script's openbsd stanza checks for the presence of the structure's kt_name element and activates kernfs support for the CFLAGS -DHASKERNFS definition only when it finds kt_name. The kernfs.h header file is scheduled to be updated in the OpenBSD 2.1 release, according to Kenneth Stailey, who authored its changes. 13.2 Will lsof work on OpenBSD on non-x86-based architectures? I've not tested lsof on an OpenBSD system that uses a non-x86-based architecture, but I've had one report that lsof 4.33 compiles and works on OpenBSD for the pmax architecture (decstation 3100). 13.3 problems 13.3.1 Why does the compiler claim nbpg isn't defined? When compiling lsof on some (older) OpenBSD SPARC versions, the compiler may complain: In file included from ../dlsof.h:191, from ../lsof.h:166, from fino.c:52: /usr/include/sys/pipe.h:83: `nbpg' undeclared here (not in a function) /usr/include/sys/pipe.h:83: size of array `ms' has non-integer type This happens because uses NBPG from to size the `ms' array, and some OpenBSD systems define NBPG in terms of a kernel integer variable, nbpg. Lsof revisions 4.46 and above have a hack to dlsof.h, developed by Volker Borchert that avoids the compiler problem for SPARC OpenBSD 2.3. The hack might work for 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: # if defined(OPENBSDV) # if OPENBSDV==2030 && defined(__sparc__) # if defined(nbpg) #undef nbpg # endif /* defined(nbpg) */ #define nbpg 4096 /* WARNING!!! ... */ # endif /* OPENBSDV==2030 && defined(__sparc__) */ #include #endif /* defined(OPENBSDV) */ You will probably want to change the second #if test to match your OpenBSD version. You may also want to change what value is assigned to nbpg. See the next section, "What value should I assign to nbpg?" 13.3.2 What value should I assign to nbpg? If you need to enable the nbpg hack, described in "Why does the compiler claim nbpg isn't defined?", you may also need to assign a value other than 4096 to nbpg. 4096 works for the sun4c processor and should work for sun4m, but 8192 may be needed for sun4. Check and other OpenBSD documentation to determine the correct nbpg assignment. 13.4 Why doesn't lsof report on open MS-DOS file system (floppy disk) files? Lsof is not able to report on open MS-DOS file system files if /usr/src/sys/msdosfs didn't exist when the lsof Configure script ran and lsof was made. /usr/src/sys/msdosfs contains header files lsof needs for collecting data on MS-DOS file system files. You can tell if an lsof executable (revisions 4.61 and above) lacks MS-DOS file system support if the following command reports nothing: $ lsof -v 2>&1 | grep HASMSDOSFS The work-around is to install /usr/src/sys, rerun the lsof Configure script, and remake lsof. 13.5 Why isn't lsof feature xxx enabled for OpenBSD? Lsof's Configure script enables OpenBSD features by locating and examining header files associated with the features, and based on what if finds, setting compile-time definitions in Makefiles. (See 00PORTING for a list of the definitions.) When Configure doesn't find header files or doesn't find appropriate values in header files, that may mean the header file tree lsof is searching is incomplete or out of date. Lsof normally looks for OpenBSD header files in /usr/include and /sys. It can also be directed to look in other directories if told to do so with the contents of the LSOF_INCLUDE and NETBSD_SYS environment variables. To determine what header file enables a missing feature, check the OpenBSD stanza in the Configure script. Then check the locations it checks for the indicated header files and contents. See 00XCONFIG for more information on LSOF_INCLUDE and and NETBSD_SYS. 14.0 Output Problems 14.1 Why do the lsof column sizes change? Lsof dynamically sizes its output columns each time it runs to make sure that each column takes the minimum space. Column parsing -- e.g., with awk -- is possible, because each column is guaranteed to be separated from the preceding one by at lease one space, and no column except the last (NAME) contains embedded spaces. 14.2 Why does the offset have ``0t' and ``0x'' prefixes? The offset value that appears in the SIZE/OFF column has ``0t' and ``0x'' prefixes to distinguish it from size values that may appear in the same column. Normally if the offset value is less than 100,000,000 (8 digits), it appears in decimal with a ``0t' prefix; over 99,999,999, in hexadecimal with a ``0x'' prefix. A decimal offset is handy, for example, when tracking the progress of an outbound ftp transfer. When lsof reports on the ftp process, it will report the size of the file being sent with its open descriptor; it will report the progress of the transfer via the offset of the outbound open ftp data socket descriptor. The ``-o [n]'' option may be used to specify the maximum number of decimal digits to be printed after ``0t'' before lsof switches to the hexadecimal digits after `0x''. As already noted, the default decimal digit count is 8. 14.3 What are the values printed in the FILE_FLAG column and why is 0x sometimes included? The two comma separated lists, separated by a semicolon, printed in the FILE-FLAG column (when the "+fg" option is specified), are short-hand names or hexadecimal values for the bits lsof finds in the f_flag or f_flags member of file structures for files (the first list, the one before the semicolon), and process open files flags found in various kernel structures, often named "pofile" (the second list, the one after the semicolon). Lsof determines the short-hand names from symbols in the , , , , o, and header files. See the discussion of FILE-FLAG in the OUTPUT section of the lsof man page, and the FF_* and POF_* symbols in lsof.h for a list of the names. Bits with no names defined for them are represented by an 0x member of the comma-separated list -- a hexadecimal integer. When "+fG" is specified (instead of "+fg"), lsof will list all flag values as two hexadecimal integers, separated by a semicolon. When "-FG" is specified to get the flags in an output field, the format defaults to hexadecimal. You can get names instead by following "-FG" with "+fg" -- e.g., $ lsof -FG +fg ... However, when you precede "-FG" with "+fg" -- e.g., $ lsof +fg -FG the format will be hexadecimal; order is important. 14.3.1 Why doesn't lsof display FILE_FLAG values for my dialect? All versions of lsof except the /proc-based Linux lsof report FILE-FLAG values. Lsof can't obtain FILE-FLAG information from the Linux /proc interface. 14.4 Network Addresses 14.4.1 Why does lsof's -n option cause IPv4 addresses, mapped to IPv6, to be displayed in IPv6 notation? When you use the -n option to tell lsof to display numeric network addresses, and an IPv4 address has been mapped to IPv6, lsof displays the address in IPv6 format and puts "ipv4" in the TYPE column. That combination indicates the IPv4 address has been mapped to IPv6. For example, the IPv4 address 1.2.3.4, when mapped to an IPv6 address, will be displayed by lsof as: [::ffff:1.2.3.4] The enclosing brackets are lsof's signal that this is an IPv6 address. Inside the brackets is a standard IPv6 address, reported by inet_ntop(). The first two colons, signifying zeroes in the first 64 bits of the IPv6 address, and the hexadecimal ffff in the next 32 bits, indicate that the last 32 bits contains a mapped IPv4 address, which is then displayed in IPv4 dot notation. 14.5 Why does lsof output \x, ^x, or \xnn for characters sometimes? Lsof displays only printable ASCII characters. Lsof considers a character printable if isprint(3) says it is. If isprint(3) says a character isn't printable, the lsof may page explains: "... 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-printable in the COMMAND column (``\x20'') and printable elsewhere." 14.5.1 Why is space considered a non-printable character in command names? Space is considered an unprintable character in command names because it is sometimes possible to hide the full command name from scripts that parse ps(1) output by embedding a space in the name. 14.6 Why doesn't lsof print all the characters of a command name? By default lsof prints the first nine characters of the names of commands associated with processes. If more characters are required, the "w" value of the "+c w" option may be used to specify a larger width. If "w" is zero ('0') lsof will print all characters of all command names up to the limit of the number of characters supplied by the particular UNIX dialect. When reporting command names, lsof replaces non-printable characters as discussed in the answer to " Why does lsof output \x, ^x, or \xnn for characters sometimes?" See the answer to the "Why is space considered a non-printable character in command names?" question for an explanation of why spaces are replaced by the ``\x20'' representation in command names. The number of command name characters supplied to lsof by UNIX dialects in files and structures varies by dialect. For example, Linux 2.4.27 supplies lsof the first 15 characters of command names and Solaris 9 supplies 16. Thus, even if "w" is zero ('0'), lsof can't report more characters for command names on those two UNIX dialects than they provide lsof. 14.7 Why does lsof reject some -c command names, saying their lengths are "> what system provides (nn)"? The command name length that a specific system provides varies from dialect to dialect. As noted in the answer to the "Why doesn't lsof print all the characters of a command name?" question, Linux and Solaris provide a limited number of command name characters. When more characters are specified in the parameter to the -c option, lsof considers it an error and issues a fatal error message -- e.g., lsof: "-c xxxxyyyy" length (8) > what system provides (7) The only work-around is to specify no more characters to -c that the system provides to lsof. 14.8 Why does lsof sometimes print TYPE numbers instead of names? When lsof can't convert a type number to a name for printing in the TYPE column, it will report the number as four octets. 14.9 Marker line format problems 14.9.1 Why won't lsof accept a marker line format? Lsof's Configure script must find the localtime(3) and strftime(3) functions in the dialect's C library in order to enable support for marker line formats. Check the output of lsof's -v option for the presence of -DHAS_STRFTIME in the compiler flags. If it isn't there, Configure didn't find the necessary two C library functions. If you think lsof should have found the functions, make a copy of the C test program in the Configure script that it uses to find the functions. Then use the copy, or a more informative modification of it, to learn why Configure can't find the functions. You can find that program by searching for strftime. 14.9.2 Why does lsof reject the NL (%n) marker line format? When repeat mode and field output (with -F) have both been specified, lsof won't allow new line (NL) formats to be specified with ``%n''. That's because the marker line is always guaranteed to be a single line. There is no work-around to this restriction. 14.10 How are protocol state name exclusion and inclusion used? Protocol state name inclusion and exclusion with the ``-s p:s'' option and its arguments have some issues to consider. First, there is the problem of determining what state names, if any, the dialect produces. Try running this lsof command to find them: $ lsof -i Knowing the state names of interest, the next problem is to decide on the lsof options and their parameters that will produce the desired output. Here some examples are probably the most useful. To list only TCP socket files in LISTEN and CLOSE_WAIT states, use: $ lsof -itcp -stcp:listen,close_wait or $ lsof -iTCP -sTCP:LISTEN,CLOSE_WAIT Case isn't important to lsof in protocol and state names. To exclude TCP socket files in CLOSE_WAIT state, use: $ lsof -itcp -stcp:^close_wait Note the `^' preceding close_wait; it selects exclusion. You can mix included and excluded names in a comma separated list, but you may not include and exclude the same name for the same protocol. To list TCP files in LISTEN state and UDP files in Idle state, use: $ lsof -i -stcp:listen -sudp:idle Note: if you don't accompany the ``-s p:s'' list option and argguments with the -i option, lsof will list all other regular files, while applying the specified inclusion and exclusion specifications to network files. Generally, then, you want to use -i with -s. 14.10.1 Why doesn't my dialect support state name exclusion and inclusion? When state name inclusion and exclusion was added, I had access to test systems for AIX, Darwin, FreeBSD, Linux, PSTAT-based HP-UX and Solaris. Therefore, I was unable to add and test the support to any other UNIX dialects. If a dialect has the support, then the HASTCPUDPSTATE definition in its machine.h header file will be active; if not, it will be absent or commented out. If your dialect doesn't have the support and you want it added, you will have to provide me Internet access to a test host, where I can compile lsof and have the credentials to test the changes the support requires. If that's possible for you, please contact me via e-mail at . Make sure "lsof" appears in the "Subject:" line so my e-mail filter won't classify your letter as Spam. 15.0 Pyramid Version Problems 15.0.5 Statement of deprecation As of lsof revision 4.52 support for all Pyramid versions has been dropped. Contact me via e-mail at if you are interested in obtaining the last lsof Pyramid distribution. Make sure "lsof" appears in the "Subject:" line so my e-mail filter won't classify your letter as Spam. 16.0 SCO Problems 16.1 SCO OpenServer Problems 16.1.1 How can I avoid segmentation faults when compiling lsof? If you have an older SCO OpenServer compiler, it may get a segmentation fault when compiling some lsof modules. That appears to happen because of the -Ox optimization action requested in the lsof Makefile. Try changing -Ox to -O with this make invocation: $ make DEBUG=-O Bela Lubkin supplied this tip and Steve Williams verified it. 16.1.2 Where is libsocket.a? If you compile lsof and the loader says it can't find the socket library, libsocket.a, called by the -lsocket option in the lsof compile flags, you probably are running an SCO OpenServer release earlier than 5.0 and don't have the TCP/IP Development System package installed. You may have the necessary header files, because you have the TCP/IP run-time package installed, but if you don't have the TCP/IP Development System package installed, you won't have libsocket.a. Your choices are to install the TCP/IP Development System package or upgrade to OpenServer Release 5.0. You will find libsocket.a in 5.0 -- you'll find all the libraries and header files there, in fact -- and you can use gcc to compile lsof if you don't want to install the 5.0 Development System package. 16.1.3 Why do I get "warning C4200" messages when I compile lsof? When you compile lsof under OSR 3.2v4.2 (and perhaps under earlier versions as well), you may get many compiler warning messages of the form: node.c(183) : warning C4200: previous declarator is not compatible with default argument promotion In my opinion this is a bug in the OSR compiler. Because the compiler cannot handle full ANSI-C prototypes, it assumes default types for function parameters as it encounters untyped in a function prototype -- e.g., in this function declaration from node.c, readrnode(ra, r) KA_T ra; struct rnode *r; { ... the compiler assigns default int types to the ra and r arguments. Then, when the compiler encounters the fully typed parameters after the function skeleton and sees parameters with types that don't match the assumptions it previously made, it whines about its own assumptions. You can ignore these messages. 16.2 SCO|Caldera UnixWare Problems 16.2.1 Why doesn't lsof compile on my UnixWare 7.1.1 or above system? When you Configure lsof with the "uw" abbreviation and try to compile it for UnixWare 7.1.1, you may get compiler error messages like this: UX:acomp: ERROR: "dproc.c", line 98: undefined struct/union member: p_pgidp This suggest that you probably have a non-stop cluster UnixWare 7.1.1 system. Its header file differs from the one on the system where I did the lsof port to UnixWare 7.1.1. I currently don't have access to a non-stop cluster system to be able to develop changes to lsof that would make it compile and work there. If you have a non-stop cluster UnixWare 7.1.1 system, want lsof for it, and can offer me a test account on the system, please contact me via e-mail at . Make sure "lsof" appears in the "Subject:" line so my e-mail filter won't classify your letter as Spam. If you have a system with nsc_cfs and can offer me a test account on it, please contact me via e-mail at . Make sure "lsof" appears in the "Subject:" line so my e-mail filter won't classify your letter as Spam. 16.2.2 Why does lsof complain about node_self() on my UnixWare 7.1.1 or above system? If lsof exits immediately after issuing this message: can't identify process NSC node; node_self(): It means that lsof has been built to run on a NonStop Cluster (NSC) UnixWare 7.1.1 or higher system and can't get the number of the node on which it is running. Lsof uses the node number to determine the path to the kernel boot file. You can tell if lsof has been built for NSC by looking for "-DHAS_UW_NSC" in lsof's "-v" option output. If the system on which you're trying to run lsof isn't running an NSC kernel, you will need to build a non-NSC lsof. 16.2.3 Why does UnixWare 7.1.1 or above complain about -lcluster, node_self(), or libcluster.so? When you build, compile, and load lsof for UnixWare 7.1.1 and above, ld may complain that it can't find the -lcluster library or that the node_self symbol is undefined. When you try to run an existing lsof binary it may complain that libcluster.so can't be found. These messages mean the tests made by Configure on your system led it to believe your system is running a NonStop Cluster (NSC) kernel, or the lsof binary you're trying to use was built on a NonStop Cluster system. If an lsof binary was built for NSC, this shell command produces output: $ strings | grep HAS_UW_NSC If that's not the case, and you can rebuild lsof, set the UW_HAS_NSC environment variable to "N" and do this: $ Configure -n clean $ UW_HAS_NSC=N $ export UW_HAS_NSC $ Configure -n uw $ make You can also edit Makefile and lib/Makefile. Remove -DHAS_UW_NSC from the CFGF strings. Remove -lcluster from the CFGL strings. Then run make again. If you have an existing NSC lsof binary and you want one for a non-NSC system, you will have to build lsof yourself on the system where you want to use it. (That's always a good idea anyway.) 16.2.4 Why does UnixWare 7.1.1 or above lsof complain it can't read the kernel name list? If lsof complains: can't read kernel name list from It means that lsof can't find the booted kernel image file at . On NonStop Cluster (NSC) UnixWare 7.1.1 or higher systems lsof determines the booted file path by examining this file: /stand/`node_self`/boot If examining that file doesn't lead to an NSC path, lsof uses: /stand/1/unix On non-NSC systems lsof expects the booted kernel image to be in /stand/unix. If your booted kernel image is in a different place, use lsof's "-k " option to specify its path. 16.2.5 Why doesn't lsof report link count, node number, and size for some UnixWare 7.1.1 or above 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 node where lsof runs, so lsof cannot report them. 16.2.6 Why doesn't lsof report open files on all UnixWare 7.1.1 NonStop Cluster (NSC) nodes? Lsof can only report on files open on the node on which it runs, because the information lsof reports comes from the private kernel memory of the node. This may mean that asking lsof to find a specific open file, or use of a specific Internet address or port, may not report all open instances on nodes other than the one used to run lsof. You can use the NSC onnode(1) command to run lsof on specific nodes, or the onall(1) command to run lsof on all nodes -- e.g., $ onall lsof [options] 2>&1 | less or $ onnode node-number lsof [options] 2>&1 | less Note that, when lsof is run all nodes, the path name component assembly results it reports in its NAME column may vary, because the dynamic name cache from which lsof gets the components is private to the kernel of each node. Also note the use of shell redirection in the examples to merge the standard error file information from onnode and onall with lsof's standard output file output. That will put the onnode and onall node announcements in proper sequence with lsof's output. 16.2.7 Why doesn't lsof report the UnixWare 7.1.1 NonStop Cluster (NSC) node a process is using? To induce lsof to report the node on which a process runs would be a significant, non-standard modification to lsof. It has much wider implications than merely the printing of a number in an output column. I'm not currently (April 2001) prepared to undertake such a modification. If you want node-specific NSC information about open files, run lsof under the control of onall(1) or onnode(1). $ onall lsof [options] 2>&1 | less or $ onnode node-number lsof [options] 2>&1 | less 16.2.8 Why does the compiler complain about missing UnixWare 2.1[.x] header files? SCO|Caldera didn't ship the following header files with UnixWare 2.1 through 2.1.3: Lsof needs those header files for its compilation. Contact SCO|Caldera to get copies of those header files. If you can't get the header files from SCO|Caldera, please contact me via e-mail at . Make sure "lsof" appears in the "Subject:" line so my e-mail filter won't classify your letter as Spam. 17.0 Sun Problems 17.0.5 Statement of deprecation Lsof support for SunOS 4.1.x was last tested at revision 4.51. Contact me via e-mail at if you're interested in obtaining it. Make sure "lsof" appears in the "Subject:" line so my e-mail filter won't classify your letter as Spam. 17.1 My Sun gcc-compiled lsof doesn't work -- why? Gcc can be used to build lsof successfully. However, an improperly installed Sun gcc compiler will usually not produce a working lsof. If your Sun gcc-compiled lsof doesn't report anything, or reports ``can't read proc table,'' or gcc refuses to compile lsof without error, check that the gcc step that "fixes" Sun header files was run on the system where you're using gcc to compile lsof. As an alternative, if you have the SunPro C 5.0 compiler or later available, use it to compile lsof -- e.g., use the solariscc Configure abbreviations. 17.2 How can I make lsof compile with gcc under Solaris 2.[456], 2.5.1, 7, 8 or 9? Presuming your gcc-specific header files are wrong for Solaris, edit the lsof Configure-generated Makefile and lib/Makefile and make this change: CFGF= -Dsolaris=20400 ... to CFGF= -Dsolaris=20400 -D__STDC__=0 -I/usr/include ... or change: CFGF= -Dsolaris=20500 ... to CFGF= -Dsolaris=20500 -D__STDC__=0 -I/usr/include ... or change: CFGF= -Dsolaris=20501 ... to CFGF= -Dsolaris=20501 -D__STDC__=0 -I/usr/include ... This is only a temporary work-around. You really should instruct gcc to to update your gcc-specific header files or install a recent gcc (e.g., 3.2), which has no need for private copies of Solaris include files. 17.3 Why does Solaris Sun C complain about system header files? You're probably trying to use /usr/ucb/cc if you get compiler complaints like: cc -O -Dsun -Dsolaris=20300 ... "/usr/include/sys/machsig.h", line 81: macro BUS_OBJERR redefines previous macro at "/usr/ucbinclude/sys/signal.h", line 444 Note the reference to "/usr/ucbinclude/sys/signal.h". It reveals that the BSD Compatibility Package C compiler is in use. Lsof requires the ANSI C version of the Solaris C compiler, usually found in /usr/opt/bin/cc or /opt/SUNWspro/bin/cc. Try adding a CC string to the lsof Makefile that points to the Sun ANSI C version of the Sun C compiler -- e.g., CC= /usr/opt/bin/cc or CC= /opt/SUNWspro/bin/cc. 17.4 Why doesn't lsof work under my Solaris 2.4 system? If lsof doesn't work under your Solaris 2.4 system -- e.g., it produces no output, little output, or the output is missing command names or file descriptors -- you may have a pair of conflicting Sun patches installed. Solaris patch 101945-32 installs a kernel that was built with a header file whose NUM_*_VECTORS definitions don't match the ones in the updated by Solaris patch 102303-02. NUM_*_VECTORS in the kernel of patch 101945-32 are smaller than the ones in the of patch 102303-02. The consequence is that when lsof is compiled with the whose NUM_*_VECTORS definitions are larger than the ones used to compile the patched kernel, lsof's user structure does not align with the one that the kernel employs. If you have these two patches installed, contact Sun and complain about the mis-match. You may be able to work around the problem by editing /usr/include/sys/auxv.h to have the following NUM_*_VECTORS definitions: #define NUM_GEN_VECTORS 4 #define NUM_SUN_VECTORS 8 The Configure script issues a prominent WARNING that you should try the work-around. I thank Leif Hedstrom for identifying the offending patches. 17.5 Where are the Solaris header files? If you try to compile lsof under Solaris and get a compiler complaint that it can't find system header files, perhaps you forgot to add the header file package, SUNWhea. 17.6 Where is the Solaris /usr/src/uts//sys/machparam.h? When you try to Configure lsof for Solaris 2.[23456], 2.5.1, and 7 -- e.g., on a `uname -m` == sun4m system -- Configure complains: grep: /usr/src/uts/sun4m/sys/machparam.h: No such file or directory grep: /usr/src/uts/sun4m/sys/machparam.h: No such file or directory And when you try to compile the configured lsof, cc or gcc complains: dproc.c:530: `KERNELBASE' undeclared (first use this function) The explanation is that somehow your Solaris system doesn't have the header files in /usr/src/uts it should have. Perhaps someone removed the directory to save space. Perhaps you're using a gcc installation, copied from another system. In any event, you will have to load the header files from the SUNWhea package of your Solaris distribution. KERNELBASE is an important symbol to lsof -- it keeps lsof from sending an illegal kernel value to kvm_read() where a segmentation violation might result (a bug in the kvm library). Lsof can get illegal kernel values because it reads kernel values slowly with kvm_read() calls that the kernel is changing rapidly. Lsof doesn't need KERNELBASE at Solaris 2.5 and above, because it has a KERNELBASE value whose address lsof can find with /dev/ksyms and whose value it can read with kvm_read(). Under Solaris 2.5 /usr/src/uts has moved to /usr/platform. 17.7 Why does Solaris lsof say ``can't read proc table''? When lsof collects data on processes, using the kvm_*() functions to scan the kernel's proc structure table, it checks to make sure it has identified a reasonable number of them -- a minimum of three. When lsof can't identify three processes during a scan, it repeats the scan. When five scans fail to yield three processes, lsof issues the fatal message: lsof: can't read proc table and exits. Usually lsof fails to identify three processes during a scan because its idea of the form of the proc structure differs from that being used by the kernel. Since the proc structure is defined in and other /usr/include header files, the root cause of a proc structure discrepancy usually can be found in the composition of /usr/include. One common way that /usr/include header files can be incorrect is that gcc was used to compile lsof, gcc used its special (i.e., "fixed") header files instead of the ones in /usr/include, and the special gcc header files weren't updated when Solaris was. Answers to these questions: My Sun gcc-compiled lsof doesn't work -- why? How can I make lsof compile with gcc under Solaris 2.[456], 2.5.1, 7, 8 or 9? Why does Solaris Sun C complain about system header files? discuss the gcc header file problem and offer suggestions on how to fix it or work around it. It may also be that you are trying to run a version of lsof that was compiled on an older version of Solaris. For example, an lsof executable, compiled for Solaris 2.4, will produce the ``can't read proc table'' message if you try to run it under Solaris 2.5. If you have compiled lsof under Solaris 2.5 and it still won't work, see if the header files in /usr/include have been updated to 2.5, or still represent a previous version of Solaris. Another source of header file discrepancies to consider is the Solaris patch level and whether a binary kernel patch was not matched with a corresponding header file update. See the "Why doesn't lsof work under my Solaris 2.4 system?" question for an example of one in Solaris 2.4 -- there may be other such patch conflicts I don't know about. 17.8 Why does Solaris lsof complain about a bad cached clone device? When lsof revisions below 4.04 have been run on a Solaris system and have been allowed to create a device cache file, the running of revisions 4.04 and above on the same systems may produce this complaint: lsof: bad cached clone device: ... lsof: WARNING: created device cache file: ... This is the result of a change in the device cache file that took place at lsof revision 4.04. The change introduced a node number into the clone device lines of the device cache file and was done in such a way that lsof could detect device cache files whose clone lines don't have node numbers (lines created by previous lsof revisions) and recognize the need to regenerate the device cache file. 17.9 Why doesn't Solaris make generate .o files? Solaris /usr/ccs/bin/make won't generate .o files from .c files if /usr/share/lib/make/make.rules is missing. It may be found in and installed from the SUNWsport package. 17.10 Why does lsof report some Solaris 2.3 and 2.4 lock types as `N'? For Solaris 2.3 with patch P101318 installed at level 45 or above, and for all versions of Solaris 2.4, NFS locks are represented by a NFS-specific kernel lock structure that sometimes lacks a read or write lock type indicator. When lsof encounters such a lock structure, it reports the lock type as `N'. 17.11 Why does lsof Configure say "WARNING: no cc in ..."? When lsof's Configure script is executed with the solariscc abbreviation it tries to make sure it's using the Sun C compiler and not the UCB substitute from /usr/ucb/cc. Thus, it looks for cc in the "standard" Sun compiler location, /opt/SUNWspro/bin. If Configure can't find cc there, it issues the warning: lsof: WARNING: no cc in /opt/SUNWspro/bin; using cc without path. and uses cc for the compiler name, letting the shell find cc with its PATH environment variable. You can tell Configure where to find your cc with the SOLARIS_CCDIR cross-configuration environment variable. (See 00XCONFIG for more information on SOLARIS_CCDIR). For example, use this Configure shell command: SOLARIS_CCDIR=/usr/special/bin Configure -n solariscc (SOLARIS_CCDIR should be the full path to the directory containing your cc.) 17.12 Solaris 7, 8 and 9 Problems 17.12.1 Why does lsof say the compiler isn't adequate for Solaris 7, 8 or 9? Solaris 7, 8 and 9 kernels come in two flavors, 32 and 64 bit. 64 bit kernels run on machines that support the SPARC v9 instruction set architecture. Separate executables for some programs, -- e.g., ones using libkvm like lsof -- must be built for 32 and 64 bit kernels. Previous Sun (e.g., SC4.0) and earlier gcc compilers will build lsof for 32 bit kernels, but they won't build it for 64 bit kernels. Compilers that will build lsof for 64 bit Solaris 7, 8 and 9 kernels are the Sun WorkShop Compilers C 5.0 and above, and recent gcc versions, e.g., 3.2. When given the ``-xarch=v9'' flag, the C 5.0 compiler and above, and associated loader and 64 bit libraries will build a 64 bit lsof executable; when given the "-m64" or "-mcpu=v9" (deprecated) flags, an appropriate gcc compiler will build a 64 bit lsof executable. When the lsof Configure script detects a 64 bit kernel is in use (e.g., by executing `/bin/isainfo -kv`), and when it finds that the specified compiler is inappropriate, it complains with these messages: For gcc: "!!!WARNING!!!=========!!!WARNING!!!=========!!!WARNING!!!" "! !" "! LSOF NEEDS TO BE CONFIGURED FOR A 64 BIT KERNEL, BUT !" "! THIS GCC DOESN'T SUPPORT THE BUILDING OF 64 BIT !" "! SOLARIS EXECUTABLES. LSOF WILL BE CONFIGURED FOR A !" "! 32 BIT echo KERNEL. !" "! !" "!!!WARNING!!!=========!!!WARNING!!!=========!!!WARNING!!!" For Sun C: !!!WARNING!!!==========!!!WARNING!!!==========!!!WARNING!!! ! ! ! LSOF NEEDS TO BE CONFIGURED FOR A 64 BIT KERNEL, BUT | ! THE VERSION OF SUN C AVAILABLE DOESN'T SUPPORT THE ! ! -xarch=v9 FLAG. LSOF WILL BE CONFIGURED FOR A 32 BIT ! ! KERNEL. ! ! ! !!!WARNING!!!==========!!!WARNING!!!==========!!!WARNING!!! 17.12.2 Why does Solaris 7, 8 or 9 lsof say "FATAL: lsof was compiled for..."? Solaris 7, 8 or 9 lsof may say: lsof: FATAL: lsof was compiled for a xx bit kernel, but this machine has booted a yy bit kernel. Where: xx = 32 or 64 yy = 64 or 32 (xx and yy won't match.) This message indicates that lsof was compiled for one size kernel and is being asked to execute on a different size one. That's not possible for programs like lsof that use libkvm. Depending on the instruction sets for which you need Solaris 7, 8 or 9 lsof, you may need two or more versions of lsof, compiled for each kernel size, installed for use with /usr/lib/isaexec. See the "How do I install lsof for Solaris 7, 8 or 9?" section of this document for more information on that. 17.12.3 How do I build lsof for a 64 bit Solaris kernel under a 32 bit Solaris kernel? If your Solaris system has an appropriate compiler (e.g., WorkShop Compilers C 5.0 and above, or a recent gcc like 3.2) and the 64 bit libraries have been installed, you can force lsof's Configure script to build a 64 bit version of lsof with: $ SOLARIS_KERNBITS=64 Configure -n solariscc The SOLARIS_KERNBITS environment variable is part of the lsof cross-configuration support, described in the 00XCONFIG file of the lsof distribution. 17.12.4 How do I install lsof for Solaris 7, 8 or 9? If you are installing lsof where it will be used only under the bit size kernel for which it was built, no special installation is required. If, however, you are installing different versions of lsof for different bit sizes -- e.g., for use on a 64 bit NFS server and from its 32 bit clients -- you should read the man page for isaexec(3C) and install lsof according to its instructions. The executable at the directory where lsof is to be found should be a hard link to /usr/lib/isaexec or a copy of it. In the directory there must be instruction architecture subdirectories -- e.g., .../sparc/ and .../sparcv9/. The lsof for 64 bit size kernels is installed in the .../sparcv9/ subdirectory; the one for 32 bit size kernels, in .../sparc/. For example, if you're installing 32 and 64 bit lsof executables in /usr/local/etc, you would: # cd /usr/local/etc # ln /usr/lib/isaexec lsof # mkdir sparc sparcv9 # install the 32 bit lsof as sparc/lsof # install the 64 bit lsof as sparcv9/lsof # chmod, chown, and chgrp sparc/lsof and sparcv9/lsof appropriately Lsof permissions and ownerships are the same whether one or more lsof executables are being installed, with or without the /usr/lib/isaexec hard link. 17.12.5 Why does my Solaris 7, 8 or 9 system say it cannot execute lsof? When you attempt to execute lsof, your Solaris 7, 8 or 9 shell may complain: ksh: ./lsof: cannot execute If the lsof executable exists and has the proper execution permissions, this error may be the result of trying to execute an lsof, built for a 64 bit kernel, on a 32 bit kernel. This will tell you about the lsof executable: $ file lsof lsof: ELF 64-bit MSB executable SPARCV9 Version 1, dynamically linked, not stripped The "64-bit" notation indicates the binary was built for a 64 bit kernel. To see the running kernel bit size, use this command: $ isainfo -kv 32-bit sparc kernel modules The "32-bit" notation indicates a 32 bit kernel has been booted. The only work-around is to obtain, or Configure and make, an lsof for the appropriate kernel bit size. If you Configure and make lsof on the kernel where you wish to run it the proper compiler, the lsof Configure step will generate Makefiles that can be used with make to build an appropriate lsof executable. To compile a 64 bit lsof, you must have an appropriate compiler -- i.e., Sun WorkShop Compilers C 5.0 or higher or a recent gcc like 3.2. 17.12.6 What gcc will produce 64 bit Solaris 7, 8 and 9 executables? 8 and 9 executables? Properly built and installed recent gcc versions -- e.g., 3.2 -- will build lsof for 64 bit Solaris kernels. If you update your gcc version to 3.2 or later, make sure the private gcc header files become current -- i.e., clear out any private header files from a previous gcc or Solaris installation before installing the new ones, or build to a new --prefix root and replace the old root with it after the build and installation are complete. 17.12.7 Why does lsof on my Solaris 7, 8 or 9 system say, "can't read namelist from /dev/ksyms?" You're probably trying to use an lsof executable built for an earlier Solaris release on a 64 bit Solaris 7, 8 or 9 kernel. The output from `lsof -v` will tell you the build environment of your lsof executable. You should also have gotten a warning message that lsof is compiled for a different Solaris version than the one under which it is running -- something like this: lsof: WARNING: compiled for Solaris release X; this is Y You need to build lsof on the system where you want to use it. For 64 bit Solaris 7, 8 and 9 you need a compiler that can generate 64 bit Solaris executables -- e.g., the Sun Workshop 5 C compiler or later, or a recent gcc version like 3.2. See the "Why does lsof say the compiler isn't adequate for Solaris 7, 8 or 9?" section and the ones following it for a discussion of building lsof for 64 bit Solaris 7, 8 or 9. 17.13 Solaris and COMMON 17.13.1 What does COMMON mean in the NAME column for a Solaris VCHR file? When lsof puts COMMON or (COMMON) in the NAME column of a Solaris VCHR file, it means that the file is handled by the special file system functions of the kernel through a common vnode. 17.13.2 Why does a COMMON Solaris VCHR file sometimes seem to have an incorrect minor device number? When lsof reports on an open file in a Solaris special file system that uses a COMMON vnode, and the file is a VCHR file, lsof tries to locate the associated device node by looking for matches on the major and minor device numbers first. If no major and minor match results, lsof then looks for a match on pseudo and clone device files. (See /devices/pseudo.) Those device nodes are matched specially by either their major or minor device numbers, but not both. Hence, when lsof finds a match under those special conditions, it may report a value in its output DEVICE column that differs from one of the major and minor numbers of the device node. Here's an example from a sun4m Solaris 7 system: $ ls -li /devices/pseudo/pm@0:pm 151261 crw-rw-rw- 1 root sys 117, 0 ... $ lsof /devices/pseudo/pm@0:pm COMMAND ... DEVICE ... NODE NAME powerd 117,1 ... 151261 /devices/pseudo/pm@0:pm (COMMON) Xsun ... 117,0 ... 151261 /devices/pseudo/pm@0:pm Note that the DEVICE value for the file with (COMMON) in its name field has a different minor device number (1) from what ls reports (0), while the DEVICE value for the file without (COMMON) matches the ls output exactly. Both match on the major device number, 117. The minor device number mis-match is a result of the way the Solaris kernel handles special file system common vnodes, and it's the reason lsof puts (COMMON) after the name to signal that a mis-match is possible. 17.14 Why don't lsof and Solaris pfiles reports always match? /usr/proc/bin/pfiles for Solaris 2.6, 7, 8, and 9 also reports information on open files for processes. Sometimes the information it reports differs from what lsof reports. There are several reasons why this might be true. First, because pfiles is a Sun product, based on Sun kernel features, its developers have a better chance of knowing exactly how open file information is organized. I sometimes have to guess at how kernel file structure linkages are constructed by gleaning hints from header files. Second, lsof is aimed at providing information, specifically device and node numbers, that can be used to identify named file system objects -- i.e., path names. Thus, lsof tries to make sure its device and node numbers match those reported by stat(2). Pfiles doesn't always report numbers that match stat(2) -- e.g., for files using clone and pseudo devices via common vnodes like the nlist() /dev/ksyms usage. Here's the Solaris 7 COMMON VCHR example again with additional pfiles output: $ ls -li /devices/pseudo/pm@0:pm 151261 crw-rw-rw- 1 root sys 117, 0 ... $ lsof /devices/pseudo/pm@0:pm vic1: 10 = lsof /dev/pm COMMAND ... DEVICE ... NODE NAME powerd ... 117,1 ... 151261 /devices/pseudo/pm@0:pm (COMMON) Xsun ... 117,0 ... 151261 /devices/pseudo/pm@0:pm $ pfiles ... 0: S_IFCHR ... dev:32,24 ino:61945 ... rdev:117,1 ... 14: S_IFCHR ... dev:32,24 ino:151261 ... rdev:117,0 Note that the NODE number, reported by lsof, matches what ls(1) and stat(2) report, while the ino value pfiles reports doesn't. Lsof also indicates with the (COMMON) notation that the DEVICE number is a pseudo one, derived from the character device's value. The lsof DEVICE value matches the pfiles rdev value, correct behavior for a character device, but pfiles gives no sign that it's not possible to find that character device number in /devices with ls(1) or stat(2). 17.15 Why does lsof say, "kvm_open(namelist=default, core=default): Permission denied?" Lsof needs permission to read from the /dev/kmem and /dev/mem memory devices. Access to them is opened via a call to the kvm_open() library function and it reports the indicated message. You must give lsof permission to read the memory devices. The super user can almost always do that, but other lsof users can do it if some group -- e.g., sys -- has permission to read the memory devices, and the lsof binary is installed with the group's ownership and with the setgid permission bit enabled. 17.16 Why is lsof slow on my busy Solaris UFS file system? Lsof may be slow on a busy Solaris UFS file system when UFS logging has been enabled with the "logging" mount option. That option can significantly increase disk operations under certain conditions -- e.g., when a lot of files are accessed quickly. When only the "logging" option is specified to mount, all file accesses (atime updates) are logged to the UFS logging queue. Each atime update requires two writes to the disk to complete it. If you want to do UFS logging -- and there are reliability advantages to it -- consider using the "logging,noatime" mount options instead. That will shift atime updates from the logging queue to fewer and independent asynchronous operations, consequently making the UFS logging queue a smaller bottleneck. Consult mount_ufs(1M) for more information on the logging and noatime options. (My thanks to Casper Dik for this tip on improving the performance of UFS logging.) 17.17 Why is lsof so slow on my Solaris 8 or 9 system? Solaris 8 has a post-release feature upgrade modifying kernel name cache (DNLC) handling that can slow lsof throughput dramatically. The feature, sometimes called negative DNLC caching, is standard in Solaris 9. As best I can tell, when you install the Solaris 8 MU1 package, you get negative DNLC caching. If this pipe produces any output, your system has negative DNLC caching. $ nm /dev/ksyms | grep negative_cache_vnode The reason negative DNLC caching perturbs lsof is that a single vnode address (found in the negative_cache_vnode kernel variable) is used to mark entries in the DNLC that are not (the negative part) found on disk. Since a single vnode address (the DNLC key lsof uses) can represent many (I've seen upwards of 30,000.) DNLC entries, their presence overloads lsof's internal DNLC hashing function. An overloaded hash function is a slow hash function, and lsof's slows to a crawl when it encounters thousands of keys that produce the same value when the lsof DNLC hash function is applied to them. The solution is simple -- ignore negative DNLC cache keys. They don't represent path name components lsof can use. Lsof revisions 4.50 and above have an addition that ignores them and the performance of those lsof revisions improves significantly when presented with negative DNLC cache keys. If you don't have an lsof revision at 4.51 or later, there's a work-around. Use lsof's ``-C'' option. It disables lsof's DNLC caching. Of course, that also inhibits the reporting of any path name components from the kernel DNLC. When ``-c'' is used, lsof will continue to report file system and character device paths. 17.18 Solaris and VxFS 17.18.1 Why doesn't lsof support VxFS 3.4 on Solaris 2.6, and above? Lsof will not support VxFS version 3.4 on Solaris 2.6 and above unless some files from VxFS Update 2 have been installed. VxFS 3.4 FCS and VxFS 3.4 update 1 lack the header files lsof normally uses to obtain information from the VxFS 3.4 kernel node structure, vx_inode. VxFS 3.4 Update 2 provides a method whereby lsof can obtain the necessary vx_inode information from the vxfsu_get_ioffsets() function in Veritas utility libraries. The utility libraries (32 bit and 64 bit versions) may be found in /opt/VRTSvxfs/lib. An ancillary header file may be found in /opt/VRTSvxfs/include/sys/fs/vx_libutil.h. Documentation of the vxfsu_get_ioffsets(3) function may be found in /opt/VRTS/man/man3/vxfsu_get_ioffsets.3. Those files of VxFS 3.4 Update 2 may be downloaded from: ftp://ftp.veritas.com/pub/support/vxfs_34.i64243.tar The vxfs_34.i64243.tar archive will unpack into an i64243 directory containing these files: $ ls i64243 README libvxfsutil.sol26.sums libvxfsutil.sol26.tar.Z libvxfsutil.sol27.sums libvxfsutil.sol27.tar.Z libvxfsutil.sol28.sums libvxfsutil.sol28.tar.Z Read README. Select the *.tar.Z file appropriate for your Solaris version. Its contents will unpack into /opt/VRTS and /opt/VRTSvxfs, so you will need sufficient permission -- e.g., do it as root -- to unpack the uncompressed archive. Once you've done that, it's a good idea to compare the checksums of the archive you unpacked with the ones recorded in the appropriate *.sums file. Use `sum -r` to verify the checksums. For example, if you want the Solaris 8 version, uncompress and unpack libvxfsutil.sol28.tar.Z -- e.g., $ su ... # cd i6423 # zcat libvxfsutil.sol28.tar.Z | tar xf - That should create these new files and subdirectories with the indicated checksums: File or subdirectory sum -r /opt/VRTSvxfs/include/vxfsutil.h 03938 /opt/VRTSvxfs/lib/libvxfsutil.a 51794 /opt/VRTSvxfs/lib/sparcv9/ /opt/VRTSvxfs/lib/sparcv9/libvxfsutil.a 07420 /opt/VRTS/man/man3/ /opt/VRTS/man/man3/vxfsu_get_ioffsets.3 62480 Once these files are in place, run lsof's Configure script for the solaris or solariscc abbreviation. Configure will locate the appropriate VxFS 3.4 Update 2 files and set up for the making of an lsof that will properly display open VxFS 3.4 file information. 17.18.2 Why does lsof report "vx_inode: vxfsu_get_ioffsets error" for open Solaris 2.6 and above VxFS 3.4 and above files? Even when lsof supports VxFS 3.4 and above on Solaris 2.6 and above, it may report "vx_inode: vxfsu_get_ioffsets error" in the NAME column for all VxFS files. The usual cause is that lsof doesn't have permission to read the file at the end of the /dev/vxportal symbolic link. If, for example, lsof has been installed setgid(sys), then the /dev/vxportal symbolic link destination should be owned by the sys group and readable by it. Update 2 for VxFS 3.4 sets the modes of the /dev/vxportal symbolic link destination to 0640 and the group ownership to sys. But I have had a report that the modes are wrong in a VxFS 4.0 installation. Another cause may be that the system has more than one version of VxFS installed (Only one can be active.), and lsof's Configure script did not choose the header files and libraries for the active VxFS version. Configure opts for VxFS 4.0 and above header files and libraries (in /opt/VRTS) in preference to those for VxFS below 4.0 (in /opt/VRTSvxfs). Look for the directories /opt/VRTS and /opt/VRTSvxfs. If you have /opt/VRTS, make sure its header and library symbolic links point to those of the active VxFS version. If you have both directories, look at the CFLAGS that Configure constructed for making lsof and see which directory path follows a -I option. If that doesn't match the directory path of the active VxFS version, try pointing Configure at the correct directory with the SOLARIS_VXFSINCL environment variable -- e.g., $ SOLARIS_VXFSINCL=/opt/.../include ./Configure -n solaris 17.18.3 Why does Solaris Configure claim there is no VxFS library? The lsof Configure script, when configuring for Solaris, may report: FATAL: no VxFS .../libvxfsutil.a That fatal error message indicates lsof has found the VxFS utility library's header files, but can't find the library itself in the expected location adjacent to the header files. One possible cause is an incorrect symbolic link from /opt/VRTS/lib/sparcv9/libvxfsutil.a to the library's real location. (Some VxFS distributions declared the link incorrectly.) Use `ls -lL` on that path to see if it exists. If it doesn't exist, the link may be missing an additional leading "../" component. If the problem is a missing "../" from the library's link, you can correct the link or check with Veritas/Symantec for the patch that corrects it. If the problem is not a missing "../", and you know the libvxfsutil.a location, you can define its path in the SOLARIS_VXFSLIB environment variable before running the lsof Configure script. (See 00XCONFIG for information about using the SOLARIS_VXFSLIB environment variable.) If you have no libvxfsutil.a, you must obtain it from Veritas/Symantec or find it in your VxFS installation package. 17.18.4 Why doesn't Solaris lsof report VxFS path name components? Solaris lsof will report path name components for VxFS versions that use the common Solaris Dynamic Name Lookup Cache (DNLC) or on some file systems of VxFS versions that support the VxFS Reverse Name Lookup (RNL) facility. VxFS versions 3.3 (approximately) and below use the common Solaris DNLC. (I haven't been able to determine exactly when VxFS stopped using the DNLC.) For versions above that boundary, but below 4.0, lsof can't report path name components. At VxFS 4.0 and above, lsof can be compiled to use the VxFS RNL facility for reporting path names. If "-DHASVXFSRNL" appears in the compiler flags section of lsof "-v" option output, then the lsof Configure script detected the VxFS RNL facility and lsof has been compiled to use it. Lsof's use of the RNL facility can fail when the VxFS file system disk layout version is below 6. In that case, lsof can report no path name components. For more information, see the vxfs_inotopath(3) manual page. any of the following commands will show the disk layout version for a VxFS file system, when supplied the block device or mount point on which the file system is mounted. fstyp -v or mkfs -m or vxupgrade You must have permission to read the block device -- e.g., be the root user. You may also be able to upgrade an older disk layout to one that will work with the RNL. See the vxupgrade(1M) man page for more information on that. When lsof can't report VxFS path name components, it reports the file system mount point and the path name of device on which it is mounted. The device path name is enclosed in parentheses. 17.18.5 Why does Solaris 10 lsof report scrambled VxFS paths? Solaris 10 lsof may report a bogus, scrambled path for an open VxFS file, when lsof obtains the path from a vnode's cached path. Veritas/Symantec reports that their Solaris 10 implementation has bugs in the way it handles the Solaris 10 vnode cached path and those bugs will be fixed in an upcoming patch some time after August 15, 2005. When Solaris 10 lsof reports a path for an open VxFs file obtained via the VxFS Reverse Name Lookup facility, the path will be correct. Also see the answers to the questions "Why does Solaris 10 lsof sometimes report the wrong path name?" and "Why doesn't Solaris lsof report VxFS path name components?" 17.19 Large file problems 17.19.1 Why does lsof complain it can't stat(2) a Solaris 2.5.1 large file? When given an argument that is the path to a Solaris 2.5.1 file, enable for large file operations with the O_LARGEFILE open(2) option, lsof complains that it can't stat(2) the file. That's because lsof isn't using a stat(2) call and associated structure enabled for large files. This error has been fixed, starting at lsof revision 4.58 for Solaris 2.6 and above. That fix won't work on Solaris 2.5.1 and I no longer have access to a Solaris 2.5.1 test system to develop a separate fix. The work-around is to avoid specifying a O_LARGEFILE path as an argument to lsof on Solaris 2.5.1. Instead use a combination of lsof and grep to achieve the same results, albeit more clumsily. 17.20 Why does lsof get a segmentation fault on 64 bit Solaris 8 using NIS+? I have received a report from Gary Craig that lsof produces a segmentation fault on his 64 bit Solaris 8 system using NIS+. Via an independent test program we have exonerated lsof and tracked the fault to the NIS+ __nis_server_name() function in the C name server library, -lnsl. Lsof causes the __nis_server_name() NIS+ function to be called by calling getservent() to read entries of the port number to service name map. The only Sun bug ID that appears to describe the problem is 4304244, although its text is unclear enough to leave room for doubt. Until Sun eliminates the __nis_server_name() segmentation fault cause, a work-around for lsof is to use its "-P" option, causing lsof to avoid port to service name lookups. 17.21 Will lsof crash the Solaris kernel? I've received and investigated one report that it has when the Sun hardware (a QME interface) was faulty. Today (May 23, 2002) I've learned that Sun has reports of kernel crashes caused by adb, lsof, and mdb. The Sun investigation pinpointed a problem in the /dev/kmem kernel driver and there is a Sun bug report, 4344513, about the problem. There is a fix in Solaris 9, and patches for Solaris 7 and 8 (SPARC and x86). To see if your Solaris system is fixed, look for a /devices/pseudo/*allkmem node. Extensive address filtering was added to lsof revision 4.50 to forestall what I then (July 2001) believed to be only the possibility that lsof might crash Solaris. However, the filtering isn't perfect, since a filtered address might become invalid after lsof has filtered it but before lsof has delivered it to /dev/kmem. That filtering work is described in .../dialects/sun/solaris_kaddr_filters, also available at: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/solaris_kaddr_filters The best and safest work-around is to upgrade to Solaris 9 or install an appropriate patch or its equivalent from this list: Solaris SPARC x86 Version Patch Patch ======= ===== ===== 7 106541-20 106542-20 8 108528-14 108529-14 17.22 Why does lsof on Solaris 7, 8, or 9 report a kvm_open() failure? When lsof is started on some Solaris 7, 8, and 9 systems it may report: lsof: kvm_open(namelist=default, corefile=default): \ No such file or directory Lsof revisions 4.65 and later will first report: lsof: cannot stat /dev/allkmem The second message, not delivered in lsof revisions below 4.65, explains the cause of the kvm_open() failure; it can't find /dev/allkmem. /dev/allkmem is a device added to Solaris 7 and 8 in patches and in the Solaris 9 FCS. See the preceding "Will lsof crash the Solaris kernel?" section for more information on /dev/allkmem and the patches. The kvm_open(3KVM) function in the KVM library of patched Solaris 7 and 8 systems and in Solaris 9 expects to find /dev/allkmem and exits on error when it does not. If you have installed the patch that updated your KVM library to a version that expects /dev/allkmem to be present and it is not, you may need to reconfigure your system's devices with devfsadm(1M) or enter "boot -r" to the OpenBoot monitor's prompt (usually "ok"). 17.23 Solaris and SAM-FS 17.23.1 Why does Solaris lsof report "(limited SAM-FS info)"? Lsof 4.68 and above report "(limited SAM-FS info)" on Solaris in the NAME column after the path or file system name for all files it finds on SAM-FS file systems. That's because no more information is known about the composition of the nodes that follow SAM-FS vnodes. If you can provide that information, please contact me via e-mail at . Make sure "lsof" appears in the "Subject:" line so my e-mail filter won't classify your letter as Spam. 17.23.2 Why can't lsof locate named SAM-GS files? Solaris lsof 4.68 and above can't locate files on SAM-FS file systems when the files are named as lsof arguments because lsof doesn't know how to locate open SAM-FS file device and node number information. (See also 'Why does Solaris lsof report "(limited SAM-FS info)?') 17.24 Lsof and Solaris 10 zones 17.24.1 How can I make lsof list the Solaris zone? Use the lsof "-z [z]" option. 17.24.2 Why doesn't lsof work in a Solaris 10 zone? When run from within a Solaris 10 zone, lsof will usually report: lsof: can't stat(/devices): No such file or directory That's because a Solaris zone usually has no /devices subdirectory, a restriction of the zone implementation intended to limit the ability of zone processes to control global system resources, including physical devices. While a zone may have a /dev subdirectory, that subdirectory usually lacks the /dev/allkmem, /dev/mem and /dev/kmem devices lsof and the KVM library it uses require. The work-around is to run lsof in the global zone. When it is run in a global zone lsof will be able to report on processes running in any zone, including the global zone. 17.24.3 Why does lsof complain it can't stat() Solaris 10 zone file systems? When run from the global zone on Solaris 10 lsof may complain: lsof: WARNING: can't stat() 15 zone file systems; using dev= options The warning message means lsof found the reported number of file system entries in the mount table for which it didn't have permission to get stat(2) results, but which had "zone=" and "dev=" mount table options. That is a normal restriction of Solaris 10 zones. Since the lsof warning message indicates it was able to find "dev=" options for the file systems, lsof will probably work correctly. One work-around is to relax the restrictions on zone mount points, so that lsof can stat() them. While that may be possible by changing directory modes or group ownerships, it is probably not a good idea, because it weakens the restrictions zones are intended to provide. Another work-around is to suppress the warning message with lsof's "-w" option. The down side of that is that it causes the suppression of all warning messages, leading to the possibility that some non-stat() warning messages will be suppressed. 17.25 Solaris 10 problems 17.25.1 Why does Solaris 10 lsof sometimes report the wrong path name? When a path name component is renamed -- e.g., with mv(1) -- Solaris 10 lsof may report the old component for an open file that used the component in its path before the rename. That's because Solaris 10 lsof reports the path name cached in the open file's vnode and the Solaris 10 kernel doesn't update the open vnode's cached path name when a component of it is changed. When an open file is deleted -- e.g., with rm(1) -- the path name by which it was opened remains cached in the vnode. Lsof can be instructed to display that path name with the -X option. The path name might be incorrect because of the rename problem described above. See the answer to the 'What does "(deleted)" mean in the NAME column of a Solaris 10 open file?' question for more information. Lsof is sometimes able to detect that cached path name is incorrect. In that case lsof may report only the mounted-on directory and device of the file system or it may report that the path name is of questionable accuracy by appending a trailing "(?)" to it in the NAME column. See the answer to the "Why does Solaris 10 lsof sometimes report only the mounted-on directory and device?" and 'What does "(?)" mean in the NAME column of a Solaris 10 open file?' questions for more information. 17.25.2 Why does Solaris 10 lsof sometimes report only the mounted-on directory and device? For some regular open files lsof may report only the mounted-on directory and device of the file system on which the file resides. That's because lsof was able to determine that the path name cached in the open file's vnode is incorrect. Lsof detects the cached path name is incorrect by applying stat(2) to it, provided that no error was detected when stat(2) was applied to the file system mounted-on directory during lsof setup. If a mounted-on directory stat(2) error was detected during setup, lsof does no cached path name analysis and simply reports it. When the application of stat(2) to the cached path name returns a no-entry reply (the ENOENT error number), lsof concludes the path no longer exists (i.e., has been unlinked) and reports the mounted-on directory and device of the file system. That behavior can be modified with the -X option in lsof revisions 4.77 and above. See the answer to the 'What does "(deleted)" mean in the NAME column of a Solaris 10 open file?' for more information. When the application of stat(2) to the cached path name returns a permission error reply (the EACCES or EPERM error numbers), lsof reports the cached path name and adds a trailing "(?)" to indicate the reported path name is of questionable accuracy. See the answer to the question 'What does "(?)" mean in the NAME column of a Solaris 10 open file?' for more information. If the application of stat(2) to the cached path name yields any other error reply, lsof reports the mounted-on directory and device of the file system. When the application of stat(2) to the cached path name succeeds, lsof compares the reported device and node numbers to what it has obtained for the open file from kernel structures. If they match, lsof reports the cached path name. If they don't match, lsof instead reports the mounted-on directory and device of the file system. A work-around that allows lsof to apply stat(2) successfully to cached path names is to give lsof sufficient permission to do it -- i.e., run lsof as the root user. 17.25.3 What does "(deleted)" mean in the NAME column of a Solaris 10 open file? When the -X option is specified to Solaris 10 lsof, it will report in its NAME column the path name cached for a deleted file in its vnode. The path name will be followed by "(deleted)". Note that the path name cached in a file's vnode is the path name by which the file was opened. It is not updated by the Solaris kernel when any path name component is changed. Hence, it may not represent the final path name the open file had. See the answer to the "Why does Solaris 10 lsof sometimes report the wrong path name?" question for more information on how changing a path name component affects the correctness of a what lsof reports. 17.25.4 What does "(?)" mean in the NAME column of a Solaris 10 open file? When lsof encounters a path name cached in the open file's vnode that stat(2) reports lsof lacks permission to access, lsof adds "(?)" to the path name reported in the NAME column to indicate the path name is of questionable accuracy. See the answers to the "Why does Solaris 10 lsof sometimes report the wrong path name?" and "Why does Solaris 10 lsof sometimes report only the mounted-on directory and device?" questions for more information on why lsof may report a path name of questionable accuracy. A work-around that allows lsof to apply stat(2) successfully to cached path names is to give lsof sufficient permission to do it -- i.e., run lsof as the root user. 17.26 Solaris contract file problems 17.26.1 Why doesn't lsof report size, link count and node number for Solaris 10 contract files? Lsof doesn't report size, link count or node number for Solaris 10 contract files because I don't know how to obtain them from contract file kernel structures. 17.26.2 Why can't lsof locate a Solaris 10 contract file by path name? Because lsof can't find the node number of Solaris contract files, it can't match the device and node numbers it gets from 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.1 Why does Configure warn that ZFS support is not enabled? To provide ZFS support it is necessary that lsof have access to the definitions of ZFS structures used by the kernel. Those definitions are made available to lsof when it runs by the libctl library. If lsof's Configure script finds that ZFS is indicated by the presence of the header file, but the libctl library is not indicated via the header file, the script concludes that ZFS support is not possible and issues the following warning: WARNING: ZFS support not enabled; libctf.h missing. Install libctf support to remedy this problem. 17.28 Problems with Solaris 9 and above 17.28.1 Why does the compiler complain about lgrp_root on Solaris 9 and above? When compiling lsof 4.84 on later Solaris 9 and 10 systems, the compiler may report the following error: /usr/include/sys/lgrp.h", line ...: identifier redeclared: lgrp_root This error results from a conflict between usage of lgrp_root in both and when _KMEMUSER or _KERNEL is #define'd before is #include'd. This problem is noted in Sunsolve bug ID 5064229. The work-around is to use lsof revision 4.85 sources. 18.0 Lsof Features 18.1 Why doesn't lsof doesn't report on /proc entries on my system? /proc file system support is generally available only for BSD, SYSV R4 dialects, and Tru64 UNIX (Digital UNIX, DEC OSF/1). It's also available for Linux, and Pyramid DC/OSx and Reliant UNIX. Even on some SYSV R4 dialects I encountered many problems while trying to incorporate /proc file system support. The chief problem is that some vendors don't distribute the header file that describes the /proc file system node -- usually called prdata.h. 18.2 How do I disable the device cache file feature or alter it's behavior? To disable the device cache file feature for a dialect, remove the HASDCACHE definition from the machine.h file of the dialect's machine.h header file. You can also use HASDCACHE to change the default prefix (``.lsof'') of the device cache file. Be sure you consider disabling the device cache file feature carefully. Having a device cache file significantly reduces lsof startup overhead by eliminating a full scan of /dev (or /devices) once the device cache file has been created. That full scan also overloads the kernel's name cache with the names of the /dev (or /devices) nodes, reducing the opportunity for lsof to find path name components of open files. If you're worried about the presence of mode 0600 device cache files in the home directories of the real user IDs that execute lsof, consider these checks that lsof makes on the file before using it: 1. To read the device cache file, lsof must gain permission from access(2). 2. The device cache file's modes must be 0600 (0644 if lsof is reading a system-wide device cache file) and its size non-zero. 3. There must be a correctly formatted section count line at the beginning of the file. 4. Each section must have a header line with a count that properly numbers the lines in the section. Legal sections are device, clone, pseudo-device, and CRC. 5. The lines of a section must have the proper format. 6. All lines are included in a 16 bit CRC, and it is recorded in a non-checksummed section line at the end of the file. 7. The checksum computed when the file is read must match the checksum recorded when the file was written. 8. The checksum section line must be followed by end-of-information. 9. Lsof must be able to get matching results from stat(2) on a randomly chosen entry of the device section. For more information on the device cache file, read the 00DCACHE file of the lsof distribution. 18.2.1 What's the risk with a perverted device cache file? Even with the checks that lsof makes on the device cache file, it's conceivable that an intruder could modify it so it would pass lsof's tests. The only serious consequence I know of this change is the removal of a file whose major device number identifies a socket from some user ID's device cache file. When such a device has been removed from the device cache file, and when lsof doesn't detect the removal, lsof may not be able to identify socket files when executed by the affected user ID. Only certain dialects are at risk to this attack -- e.g., SCO OpenServer and Solaris 2.x, 7, 8, and 9. If you're tracking a network intruder with lsof, that could be important to you. If you suspect that someone has corrupted the device cache file you're using, I recommend you use lsof's -Di option to tell it to ignore it and use the contents of /dev (or /devices) instead; or remove the device cache file (usually .lsof_hostname, where hostname is the first component of the host's name returned by gethostname(2)) from the user ID's home directory and let lsof create a new one for you. 18.2.2 How do I put the full host name in a personal device cache file path? Lsof constructs the personal device cache file path name from a format specified in the HASPERSDC #define in the dialect's machine.h header file. As distributed HASPERSDC declares the path to be ``.lsof_'' plus the first component of the host name with the format ``.lsof_%L''. If you want to change the way lsof constructs the personal device cache file path name, you can change the HASPERSDC #define and recompile lsof. If, for example, you #define HASPERSDC to be ``.lsof_%l'' (note the lower case `l'), Configure and remake lsof, then the personal device cache file path will be ``.lsof_'' plus the host name returned by gethostname(2). See the 00DCACHE file of the lsof distribution for more information on the formation of the personal device cache file path and the use of the HASPERSDC #define. 18.2.3 How do I put the personal device cache file in /tmp? Change the HASPERSDC definition in your dialect's machine.h header file. When you redefine HASPERSDC, make sure you put at least one user identification conversion in it to keep separate the device cache files for each user of lsof. Also give some thought to including the ``%0'' conversion to define an alternate path for setuid-root and root processes. Here's a definition that puts a personal device cache file in /tmp with the name ``.lsof_login_hostname_pers''. #define HASPERSDC "/tmp/.lsof_%u_%l_pers" Thus the /tmp personal device cache file path for login "abe" on host "lsof.itap.purdue.edu" would be: /tmp/.lsof_abe_lsof.itap.purdue.edu_pers You can add the User ID (UID) with the "%U" conversion and the first host name component with the ``%L'' conversion. CAUTION: be careful using absolute paths like /tmp lest lsof processes that are setuid-root or whose real UID is root be used to exploit some security weakness via /tmp. Elect instead to add an alternate path for those processes with the ``%0'' conversion. Here's an extension of the previous HASPERSDC format for /tmp that declares an alternate path: #define HASPERSDC "/tmp/.lsof_%u_%l_pers%0%h/.lsof_%L" When the lsof process is setuid-root or its real UID is root, presuming root's home directory is `/' and the host's name is ``lsof.itap.purdue.edu'', the extended format yields: /.lsof_vic 18.3 Why doesn't lsof know about AFS files on my favorite dialect? Lsof currently supports AFS for these dialects: 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 dialects, but I have no way to test that. Lsof may report correct information for AFS files on other dialects, but I can't test that either. AFS support must be custom crafted for each UNIX dialect and then tested. If lsof supports your favorite dialect, but doesn't recognize its AFS files, probably I don't have access to a test system. If you want AFS support badly for your dialect, consider helping me do the development and testing. 18.3.1 Why doesn't lsof report node numbers for all AFS volume files, or how do I reveal dynamic module addresses to lsof? When AFS is implemented via dynamic kernel modules -- e.g., in NEXTSTEP -- lsof can't obtain the addresses of AFS variables in the kernel that it uses to identify AFS vnodes. It can guess that a vnode is assigned to an AFS file and it can obtain other information about AFS files, but it has trouble computing AFS volume node numbers. To determine node numbers for AFS volumes other than the root volume, /afs, lsof needs access to a hashed volume structure pointer table. When it can't find the address of that table, because AFS support is implemented via dynamic kernel modules, lsof will return blanks in the INODE column for AFS volume files. Lsof can identify the root volume's node number (0), and can compute the node numbers for all other AFS files. If you have a name list file that contains the addresses of the AFS dynamic modules -- e.g., you saved module symbols when you created a loadable module kernel with modload(8) by specifying -sym -- lsof may be able to find the kernel addresses it needs in that file. Lsof looks up AFS dynamic kernel addresses for these dialects at these default paths: NEXTSTEP 3.2 /usr/vice/etc/afs_loadable A different path to a name list file with AFS dynamic kernel addresses may be specified with the -A option, when the -A option description appears in lsof's -h or -? (help) output. If any addresses appear in the -A name list file that also appear in the regular kernel name list file -- e.g., /vmunix -- they must match, or lsof will silently ignore the -A addresses on the presumption that they are out of date. lsof-4.86+dfsg.orig/00LSOF-L0000444000175000017500000000537611010636711015502 0ustar nicholasnicholas The Lsof Mailing List, lsof-l Information on lsof is available via a GNU Mailman mailing list, named lsof-l. The server is located on the host rcac.purdue.edu. Subscribing =========== You may subscribe to the lsof-l mailing list by sending e-mail to: lsof-l-subscribe@rcac.purdue.edu The body of your e-mail may be empty. You will receive a confirmation reply, explaining one further step you must take to complete your subscription. The list manager uses the e-mail address and real name in the "From:" line of your request to set those values in your subscription. If you want different values in your subscription, consult the Mailman help information to learn how to specify them on your subscription request. (See the next "Get Help" section on how to obtain Mailman help information.) Get Help ======== More information about the rcac.purdue.edu GNU Mailman server is available by sending e-mail to lsof-l-request@rcac.purdue.edu with "help" in the subject line. The body of your e-mail may be empty. The other information will be delivered by return e-mail. You can also obtain information on the Mailman e-mail commands in section 3.2 of the GNU Mailman documentation at: http://www.gnu.org/software/mailman/mailman-member/mailman-member.html The Web Interface ================= There is a web interface at: https://lists.rcac.purdue.edu/listinfo/lsof-l You can use it to manage your lsof-l list entry. Posting and Moderation ====================== Once you have subscribed to lsof-l (and have an e-mail confirmation that your subscription was accepted), you may post messages to the list by sending e-mail directly to: lsof-l@rcac.purdue.edu I moderate the lsof-l mailing list and try to keep its traffic low, mainly limiting it to announcements of new revisions, patches and security issues. Postings don't appear until I've approved them. Send Bug Reports to Me Via E-Mail ================================= DON'T SEND BUG REPORTS TO lsof-l. Send them directly to me via e-mail at . Make sure lsof appears in the "Subject:" line and make sure you first read the "Bug Reports" section of the 00README file of the lsof distribution. Unsubscribing ============= You can unsubscribe from lsof-l by sending e-mail to: lsof-l-unsubscribe@rcac.purdue.edu The body of your e-mail may be empty. You will receive a confirmation reply, explaining one further step you must take to complete the removal of your subscription. Archive ======= There is an archive; use the link: https://lists.rcac.purdue.edu/listinfo/lsof-l The archive link is the first one on the web page. You will need the password you received or set when you subscribed, or later set via lsof-l-request or the web interface. Vic Abell May 8, 2008 lsof-4.86+dfsg.orig/node.c0000444000175000017500000001270207141601775015557 0ustar nicholasnicholas/* * 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"; static char *rcsid = "$Id: node.c,v 1.5 2000/08/01 17:08:05 abe Exp $"; #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) */ lsof-4.86+dfsg.orig/lsof.80000644000175000017500000034700211741064217015523 0ustar nicholasnicholas.ds VN 4.86 .TH LSOF 8 Revision-\*(VN .if !\n()P .nr )P 1v .SH NAME lsof \- list open files .SH SYNOPSIS .B lsof [ .B \-?abChKlnNOPRtUvVX ] [ .BI -A " A" ] [ .BI \-c " c" ] [ .BI +c " c" ] [ .BI +|\-d " d" ] [ .BI +|\-D " D" ] [ .BI +|\-e " s" ] [ .B +|\-f [cfgGn] ] [ .BI \-F " [f]" ] [ .BI \-g " [s]" ] [ .BI \-i " [i]" ] [ .BI \-k " k" ] [ .BI +|\-L " [l]" ] [ .BI +|\-m " m" ] [ .B +|\-M ] [ .BI \-o " [o]" ] [ .BI \-p " s" ] [ .BI +|\-r " [t[m]]" ] [ .BI \-s " [p:s]" ] [ .BI \-S " [t]" ] [ .BI \-T " [t]" ] [ .BI \-u " s" ] [ .B +|\-w ] [ .BI \-x " [fl]" ] [ .BI \-z " [z]" ] [ .BI \-Z " [Z]" ] [ .B -- ] [\fInames\fP] .SH DESCRIPTION .I Lsof revision \*(VN lists on its standard output file information about files opened by processes for the following UNIX dialects: .PP .nf Apple Darwin 9 and Mac OS X 10.[567] FreeBSD 4.9 and 6.4 for x86-based systems FreeBSD 8.2, 9.0 and 10.0 for AMD64-based systems Linux 2.1.72 and above for x86-based systems Solaris 9, 10 and 11 .fi .PP (See the .B DISTRIBUTION section of this manual page for information on how to obtain the latest .I lsof revision.) .PP 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 selected by path. .PP Instead of a formatted display, .I lsof will produce output that can be parsed by other programs. See the .BR \-F , option description, and the .B "OUTPUT FOR OTHER PROGRAMS" section for more information. .PP In addition to producing a single output list, .I 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 .BI +|\-r " [t[m]]" option description for more information. .SH OPTIONS In the absence of any options, .I lsof lists all open files belonging to all active processes. .PP If any list request option is specified, other list requests must be specifically requested \- e.g., if .B \-U is specified for the listing of UNIX socket files, NFS files won't be listed unless .B \-N is also specified; or if a user list is specified with the .B \-u option, UNIX domain socket files, belonging to users not in the list, won't be listed unless the .B \-U option is also specified. .PP Normally list options that are specifically stated are ORed \- i.e., specifying the .B \-i option without an address and the \fB\-u\fPfoo option produces a listing of all network files OR files belonging to processes owned by user ``foo''. The exceptions are: .TP \w'1)\ 'u 1) the `^' (negated) login name or user ID (UID), specified with the .B \-u option; .TP \w'1)\ 'u 2) the `^' (negated) process ID (PID), specified with the .B \-p option; .TP \w'1)\ 'u 3) the `^' (negated) process group ID (PGID), specified with the .B \-g option; .TP \w'1)\ 'u 4) the `^' (negated) command, specified with the .B \-c option; .TP \w'1)\ 'u 5) the (`^') negated TCP or UDP protocol state names, specified with the .BI \-s " [p:s]" option. .PP Since they represent exclusions, they are applied without ORing or ANDing and take effect before any other selection criteria are applied. .PP The .B \-a option may be used to AND the selections. For example, specifying .BR \-a , .BR \-U , and \fB\-u\fPfoo produces a listing of only UNIX socket files that belong to processes owned by user ``foo''. .PP Caution: the .B \-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 acceptable. Wherever .B \-a is placed, it causes the ANDing of all selection options. .PP Items of the same selection set \- command names, file descriptors, network addresses, process identifiers, user identifiers, zone names, security contexts \- are joined in a single ORed set and applied before the result participates in ANDing. Thus, for example, specifying \fB\-i\fP@aaa.bbb, \fB\-i\fP@ccc.ddd, .BR \-a , and \fB\-u\fPfff,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. .PP Options may be grouped together following a single prefix -- e.g., the option set ``\fB\-a \-b \-C\fP'' may be stated as .BR \-abC . However, since values are optional following .BR +|\-f , .BR \-F , .BR \-g , .BR \-i , .BR +|\-L , .BR \-o , .BR +|\-r , .BR \-s , .BR \-S , .BR \-T , .B \-x and .BR \-z . when you have no values for them be careful that the following character isn't ambiguous. For example, .B \-Fn might represent the .B \-F and .B \-n options, or it might represent the .B n field identifier character following the .B \-F option. When ambiguity is possible, start a new option with a `-' character \- e.g., ``\fB\-F \-n\fP''. If the next option is a file name, follow the possibly ambiguous option with ``--'' \- e.g., ``\fB\-F -- \fIname\fR''. .PP 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., \fB\-i\fP \- 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 options. Be careful of prefix grouping when one or more options in the group does take on separate meanings under different prefixes \- e.g., \fB+|\-M\fP; ``-iM'' is not the same request as ``\-i +M''. When in doubt, use separate options with appropriate prefixes. .TP \w'names'u+4 .B \-? \-h These two equivalent options select a usage (help) output list. .I 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.) .TP \w'names'u+4 .B \-a causes list selection options to be ANDed, as described above. .TP \w'names'u+4 .BI \-A " A" is available on systems configured for AFS whose AFS kernel code is implemented via dynamic modules. It allows the .I lsof user to specify .I A as an alternate name list file where the kernel addresses of the dynamic modules might be found. See the .I lsof FAQ (The \fBFAQ\fP section gives its location.) for more information about dynamic modules, their symbols, and how they affect .IR lsof . .TP \w'names'u+4 .B \-b causes .I lsof to avoid kernel functions that might block \- .IR lstat (2), .IR readlink (2), and .IR stat (2). .IP See the .B "BLOCKS AND TIMEOUTS" and .B "AVOIDING KERNEL BLOCKS" sections for information on using this option. .TP \w'names'u+4 .BI \-c " c" selects the listing of files for processes executing the command that begins with the characters of .IR c . Multiple commands may be specified, using multiple .B \-c options. They are joined in a single ORed set before participating in AND option selection. .IP If .I c begins with a `^', then the following characters specify a command name whose processes are to be ignored (excluded.) .IP If .I c begins and ends with a slash ('/'), the characters between 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: .IP .nf b the regular expression is a basic one. .br i ignore the case of letters. .br x the regular expression is an extended one .br (default). .fi .IP See the .I lsof FAQ (The \fBFAQ\fP section gives its location.) for more information on basic and extended regular expressions. .IP 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 .B \-V option is specified. .TP \w'names'u+4 .BI +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 .I lsof default is nine.) .IP Note that many UNIX dialects do not supply all command name characters to .I lsof in the files and structures from which .I 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. .IP If .I w is zero ('0'), all command characters supplied to .I lsof by the UNIX dialect will be printed. .IP If .I w is less than the length of the column title, ``COMMAND'', it will be raised to that length. .TP \w'names'u+4 .B \-C disables the reporting of any path name components from the kernel's name cache. See the .B "KERNEL NAME CACHE" section for more information. .TP \w'names'u+4 .BI +d " s" causes .I lsof to search for all open instances of directory .I s and the files and directories it contains at its top level. .B +d does NOT descend the directory tree, rooted at .IR s . The .BI +D " D" option may be used to request a full\-descent directory tree search, rooted at directory .IR D . .IP Processing of the .B +d option does not follow symbolic links within .I s unless the .B \-x or .B \-x " l" option is also specified. Nor does it search for open files on file system mount points on subdirectories of .I s unless the .B \-x or .B \-x " f" option is also specified. .IP 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 .IR stat (2) function. .TP \w'names'u+4 .BI \-d " s" specifies a list of file descriptors (FDs) to exclude from or include in the output listing. The file descriptors are specified in the comma\-separated set .I s \&\- e.g., ``cwd,1,3'', ``^6,^2''. (There should be no spaces in the set.) .IP 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. .IP 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 descriptors 0 through 7. .IP Multiple file descriptor numbers are joined in a single ORed set before participating in AND option selection. .IP When there are exclusion and inclusion members in the set, .I lsof reports them as errors and exits with a non\-zero return code. .IP See the description of File Descriptor (FD) output values in the .B OUTPUT section for more information on file descriptor names. .TP \w'names'u+4 .BI +D " D" causes .I lsof to search for all open instances of directory .I D and all the files and directories it contains to its complete depth. .IP Processing of the .B +D option does not follow symbolic links within .I D unless the .B \-x or .B \-x " l" option is also specified. Nor does it search for open files on file system mount points on subdirectories of .I D unless the .B \-x or .B \-x " f" option is also specified. .IP 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 .IR stat (2) function. .IP Further note: .I 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 .IR D , calling .IR 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 .I D is large, these steps can take a long time, so use this option prudently. .TP \w'names'u+4 .BI \-D " D" directs .I lsof's use of the device cache file. The use of this option is sometimes restricted. See the .B "DEVICE CACHE FILE" section and the sections that follow it for more information on this option. .IP .B -D must be followed by a function letter; the function letter may optionally be followed by a path name. .I Lsof recognizes these function letters: .IP .nf \fB?\fP \- report device cache file paths \fBb\fP \- build the device cache file \fBi\fP \- ignore the device cache file \fBr\fP \- read the device cache file \fBu\fP \- read and update the device cache file .fi .IP The .BR b , .BR r , and .B u functions, accompanied by a path name, are sometimes restricted. When these functions are restricted, they will not appear in the description of the .B \-D option that accompanies .B \-h or .B \-? option output. See the .B "DEVICE CACHE FILE" section and the sections that follow it for more information on these functions and when they're restricted. .IP The .B ? function reports the read\-only and write paths that lsof can use for the device cache file, the names of any environment variables whose values .I 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.) .IP When available, the .BR b , .BR r , and .B u functions may be followed by the device cache file's path. The standard default is .I .lsof_hostname in the home directory of the real user ID that executes .IR lsof , but this could have been changed when .I lsof was configured and compiled. (The output of the .B \-h and .B \-? options show the current default prefix \- e.g., ``.lsof''.) The suffix, .IR hostname , is the first component of the host's name returned by .IR gethostname (2) . .IP When available, the .B b function directs .I lsof to build a new device cache file at the default or specified path. .IP The .B i function directs .I lsof to ignore the default device cache file and obtain its information about devices via direct calls to the kernel. .IP The .B r function directs .I 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 improperly structured. The .B r function, when specified without a path name, prevents .I lsof from updating an incorrect or outdated device cache file, or creating a new one in its place. The .B r function is always available when it is specified without a path name argument; it may be restricted by the permissions of the .I lsof process. .IP When available, the .B u function directs .I 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 .B \-D option has been specified. .TP \w'names'u+4 .BI +|\-e " s" exempts the file system whose path name is .I s from being subjected to kernel function calls that might block. The .B +e option exempts .IR stat (2), .IR lstat (2) and most .IR readlink (2) kernel function calls. The .B \-e option exempts only .IR stat(2) and .IR lstat (2) kernel function calls. Multiple file systems may be specified with separate .B +|\-e specifications and each may have .IR readlink (2) calls exempted or not. .IP This option is currently implemented only for Linux. .IP .B 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 .IR stat (2) kernel call and are thus not available, but see the .BI +|\-m " m" option as a possible alternative way to supply device numbers.) \fBUse this option with great care and fully specify the path name of the file system to be exempted.\fP .IP 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 applicable exemption option is added in parentheses to the end of the NAME column. (Some device number information might be made available via the .BI +|\-m " m" option.) .TP \w'names'u+4 .B +|\-f [cfgGn] .B f by itself clarifies how path name arguments are to be interpreted. When followed by .BR c , .BR f , .BR g , .BR G , or .B n in any combination it specifies that the listing of kernel file structure information is to be enabled (`+') or inhibited (`\-'). .IP Normally a path name argument is taken to be a file system name if it matches a mounted\-on directory name reported by .IR mount (8), or if it represents a block device, named in the .I mount output and associated with a mounted directory name. When .B +f is specified, all path name arguments will be taken to be file system names, and .I 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. .IP When .B \-f is specified by itself, all path name arguments will be taken to be simple files. Thus, for example, the ``\fB\-f\fP\ -- /'' arguments direct lsof to search for open files with a `/' path name, not all open files in the `/' (root) file system. .IP Be careful to make sure .B +f and .B \-f are properly terminated and aren't followed by a character (e.g., of the file or file system name) that might be taken as a parameter. For example, use ``--'' after .B +f and .B \-f as in these examples. .IP .nf $ lsof +f -- /file/system/name $ lsof -f -- /file/name .fi .IP The listing of information from kernel file structures, requested with the .B +f [cfgGn] option form, is normally inhibited, and is not available in whole or part for some dialects \- e.g., /proc\-based Linux kernels below 2.6.22. When the prefix to .B f is a plus sign (`+'), these characters request file structure information: .IP .nf \fBc\fR file structure use count (not Linux) \fBf\fR file structure address (not Linux) \fBg\fR file flag abbreviations (Linux 2.6.22 and up) \fBG\fR file flags in hexadecimal (Linux 2.6.22 and up) \fBn\fR file structure node address (not Linux) .fi .IP When the prefix is minus (`\-') the same characters disable the listing of the indicated values. .IP File structure addresses, use counts, flags, and node addresses may be used to detect more readily identical files inherited by child processes and identical files in use by different processes. .I Lsof column output can be sorted by output columns holding the values and listed to identify identical file use, or .I lsof field output can be parsed by an AWK or Perl post\-filter script, or by a C program. .TP \w'names'u+4 .BI \-F " f" specifies a character list, .IR 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 .IR f . The field terminator defaults to NL, but may be changed to NUL (000). See the .B "OUTPUT FOR OTHER PROGRAMS" section for a description of the field identification characters and the field output process. .IP 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. .IP 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. .IP Other combinations of fields and their associated field terminator character must be set with explicit entries in .IR f , as described in the .B "OUTPUT FOR OTHER PROGRAMS" section. .IP When a field selection character identifies an item .I lsof does not normally list \- e.g., PPID, selected with .BR \-R " \-" specification of the field character \- e.g., ``\fB\-FR\fP'' \- also selects the listing of the item. .IP When the field selection character list contains the single character `?', .I lsof will display a help list of the field identification characters. (Escape the `?' character as your shell requires.) .TP \w'names'u+4 .BI \-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 .I s \&\- e.g., ``123'' or ``123,^456''. (There should be no spaces in the set.) .IP PGID numbers that begin with `^' (negation) represent exclusions. .IP Multiple PGID numbers are joined in a single ORed set before participating in AND option selection. However, PGID exclusions are applied without ORing or ANDing and take effect before other selection criteria are applied. .IP The .B \-g 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 .BI \-i " [i]" selects the listing of files any of whose Internet address matches the address specified in \fIi\fP. If no address is specified, this option selects the listing of all Internet and x.25 (HP\-UX) network files. .IP If .BI \-i 4 or .BI \-i 6 is specified with no following address, only files of the indicated IP version, IPv4 or IPv6, are displayed. (An IPv6 specification may be used only if the dialects supports IPv6, as indicated by ``[46]'' and ``IPv[46]'' in .I lsof's .B \-h or .B \-? output.) Sequentially specifying .BR \-i 4, followed by .BR \-i 6 is the same as specifying .BR \-i , and vice-versa. Specifying .BR \-i 4, or .BR \-i 6 after .B \-i is the same as specifying .BR \-i 4 or .BR \-i 6 by itself. .IP Multiple addresses (up to a limit of 100) may be specified with multiple .B \-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. .IP An Internet address is specified in the form (Items in square brackets are optional.): .IP [\fI46\fP][\fIprotocol\fP][@\fIhostname\fP\||\|\fIhostaddr\fP][:\fIservice\fP\||\|\fIport\fP] .IP where: .nf .br \fI46\fP specifies the IP version, IPv4 or IPv6 .br that applies to the following address. .br '6' may be be specified only if the UNIX .br dialect supports IPv6. If neither '4' nor .br '6' is specified, the following address .br applies to all IP versions. .br \fIprotocol\fP is a protocol name \- \fBTCP\fP, \fBUDP\fP .br or \fBUDPLITE\fP. .br \fIhostname\fP is an Internet host name. Unless a .br specific IP version is specified, open .br network files associated with host names .br of all versions will be selected. .br \fIhostaddr\fP is a numeric Internet IPv4 address in .br dot form; or an IPv6 numeric address in .br colon form, enclosed in brackets, if the .br UNIX dialect supports IPv6. When an IP .br version is selected, only its numeric .br addresses may be specified. .br \fIservice\fP is an \fI/etc/services\fP name \- e.g., \fBsmtp\fP \- or a list of them. .br \fIport\fP is a port number, or a list of them. .fi .IP IPv6 options may be used only if the UNIX dialect supports IPv6. To see if the dialect supports IPv6, run .I lsof and specify the .B \-h or .B \-? (help) option. If the displayed description of the .B \-i option contains ``[46]'' and ``IPv[46]'', IPv6 is supported. .IP IPv4 host names and addresses may not be specified if network file selection is limited to IPv6 with .BR \-i " 6." IPv6 host names and addresses may not be specified if network file selection is limited to IPv4 with .BR \-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'. .IP At least one address component \- .BR 4, .BR 6, .IR protocol , .IR hostname , .IR hostaddr , or .I service \&\- must be supplied. The `@' character, leading the host specification, is always required; as is the `:', leading the port specification. Specify either .I hostname or .IR hostaddr . Specify either .I service name list or .I port number list. If a .I service name list is specified, the .I 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 .IR protocol . .IP .I Service names and .I port numbers may be combined in a list whose entries are separated by commas and whose numeric range entries are separated by minus signs. There may be no embedded spaces, and all service names must belong to the specified .IR 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. .IP Here are some sample addresses: .nf .br -i6 \- IPv6 only .br TCP:25 \- TCP and port 25 .br @1.2.3.4 \- Internet IPv4 host address 1.2.3.4 .br @[3ffe:1ebc::1]:1234 \- Internet IPv6 host address 3ffe:1ebc::1, port 1234 .br UDP:who \- UDP who service port .br TCP@lsof.itap:513 \- TCP, port 513 and host name lsof.itap .br tcp@foo:1-10,smtp,99 \- TCP, ports 1 through 10, service name \fIsmtp\fP, port 99, host name foo .br tcp@bar:1-smtp \- TCP, ports 1 through \fIsmtp\fP, host bar .br :time \- either TCP, UDP or UDPLITE time service port .fi .TP \w'names'u+4 .B \-K selects the listing of tasks of processes, on dialects where task reporting is supported. (If help output \- i.e., the output of the .B \-h or .B \-? options \- shows this option, then task reporting is supported by the dialect.) .IP When .B \-K and .B \-a are both specified 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 .B OUTPUT section.) .TP \w'names'u+4 .BI \-k " k" specifies a kernel name list file, .IR k , in place of /vmunix, /mach, etc. .B \-k is not available under AIX on the IBM RISC/System 6000. .TP \w'names'u+4 .B \-l inhibits the conversion of user ID numbers to login names. It is also useful when login name lookup is working improperly or slowly. .TP \w'names'u+4 .BI +|\-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. .IP When .B +L is specified without a following number, all link counts will be listed. When .B \-L is specified (the default), no link counts will be listed. .IP When .B +L is followed by a number, only files having a link count less than that number will be listed. (No number may follow .BR \-L .) A specification of the form ``\fB+L1\fP'' will select open files that have been unlinked. A specification of the form ``\fB+aL1\ \fI\fR'' will select unlinked open files on the specified file system. .IP For other link count comparisons, use field output (\fB\-F\fP) and a post\-processing script or program. .TP \w'names'u+4 .BI +|\-m " m" specifies an alternate kernel memory file or activates mount table supplement processing. .IP The option form .BI \-m " m" specifies a kernel memory file, .IR m , in place of .I /dev/kmem or .I /dev/mem \&\- e.g., a crash dump file. .IP The option form .B +m requests that a mount supplement file be written to the standard output file. All other options are silently ignored. .IP There will be a line in the mount supplement file for each mounted file system, containing the mounted file system directory, followed by a single space, followed by the device number in hexadecimal "0x" format \- e.g., .IP .nf / 0x801 .fi .IP .I Lsof can use the mount supplement file to get device numbers for file systems when it can't get them via .IR stat (2) or .IR lstat (2). .IP The option form .BI +m " m" identifies .I m as a mount supplement file. .IP Note: the .B +m and .BI +m " m" options are not available for all supported dialects. Check the output of .I lsof's .B \-h or .B \-? options to see if the .B +m and .BI +m " m" options are available. .TP \w'names'u+4 .B +|\-M Enables (\fB+\fP) or disables (\fB-\fP) the reporting of portmapper registrations for local TCP, UDP and UDPLITE ports, where port mapping is supported. (See the last paragraph of this option description for information about where portmapper registration reporting is suported.) .IP The default reporting mode is set by the .I lsof builder with the HASPMAPENABLED #define in the dialect's machine.h header file; .I lsof is distributed with the HASPMAPENABLED #define deactivated, so portmapper reporting is disabled by default and must be requested with .BR \+M . Specifying .I lsof's .B \-h or .B \-? option will report the default mode. Disabling portmapper registration when it is already disabled or enabling it when already enabled is acceptable. When portmapper registration reporting is enabled, .I lsof displays the portmapper registration (if any) for local TCP, UDP or UDPLITE ports in square brackets immediately following the port numbers or service names \- e.g., ``:1234[name]'' or ``:name[100083]''. The registration information may be a name or number, depending on what the registering program supplied to the portmapper when it registered the port. .IP When portmapper registration reporting is enabled, .I lsof may run a little more slowly or even become blocked when access to the portmapper becomes congested or stopped. Reverse the reporting mode to determine if portmapper registration reporting is slowing or blocking .IR lsof . .IP For purposes of portmapper registration reporting .I lsof considers a TCP, UDP or UDPLITE port local if: it is found in the local part of its containing kernel structure; or if it is located 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 .I lsof ignore some foreign ports on machines with multiple interfaces when the foreign Internet address is on a different interface from the local one. .IP See the .I lsof FAQ (The \fBFAQ\fP section gives its location.) for further discussion of portmapper registration reporting issues. .IP Portmapper registration reporting is supported only on dialects that have RPC header files. (Some Linux distributions with GlibC 2.14 do not have them.) When portmapper registration reporting is supported, the .B \-h or .B \-? help output will show the .B +|\-M option. .TP \w'names'u+4 .B \-n inhibits the conversion of network numbers to host names for network files. Inhibiting conversion may make .I lsof run faster. It is also useful when host name lookup is not working properly. .TP \w'names'u+4 .B \-N selects the listing of NFS files. .TP \w'names'u+4 .BI \-o directs .I 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 .I lsof can't obtain accurate or consistent file offset information from its kernel data sources, sometimes just for particular kinds of files (e.g., socket files.) Consult the .I lsof FAQ (The \fBFAQ\fP section gives its location.) for more information. .IP The .B \-o and .B \-s options are mutually exclusive; they can't both be specified. When neither is specified, .I lsof displays whatever value \- size or offset \- is appropriate and available for the type of the file. .TP \w'names'u+4 .BI \-o " o" defines the number of decimal digits (\fIo\fP) to be printed after the ``0t'' for a file offset before the form is switched to ``0x...''. An .I o value of zero (unlimited) directs .I lsof to use the ``0t'' form for all offset output. .IP This option does NOT direct .I lsof to display offset at all times; specify .B \-o (without a trailing number) to do that. .BI \-o " o" only specifies the number of digits after ``0t'' in either mixed size and offset or offset\-only output. Thus, for example, to direct .I lsof to display offset at all times with a decimal digit count of 10, use: .IP .nf -o -o 10 or -oo10 .fi .IP 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 .BI \-o " o" option in the output of the .B \-h or .B \-? option to determine the default that is in effect. .TP \w'names'u+4 .B \-O directs .I 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 .B "BLOCKS AND TIMEOUTS" and .B "AVOIDING KERNEL BLOCKS" sections for more information on kernel operations that may block .IR lsof . .IP While use of this option will reduce .I lsof startup overhead, it may also cause .I lsof to hang when the kernel doesn't respond to a function. Use this option cautiously. .TP \w'names'u+4 .BI \-p " s" excludes or selects the listing of files for the processes whose optional process IDentification (PID) numbers are in the comma\-separated set .I s \&\- e.g., ``123'' or ``123,^456''. (There should be no spaces in the set.) .IP PID numbers that begin with `^' (negation) represent exclusions. .IP 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. .TP \w'names'u+4 .B \-P inhibits the conversion of port numbers to port names for network files. Inhibiting the conversion may make .I lsof run a little faster. It is also useful when port name lookup is not working properly. .TP \w'names'u+4 .BI +|\-r " [t[m]]" puts .I lsof in repeat mode. There .I lsof lists open files as selected by other options, delays .I t seconds (default fifteen), then repeats the listing, delaying and listing repetitively until stopped by a condition defined by the prefix to the option. .IP If the prefix is a `\-', repeat mode is endless. .I Lsof must be terminated with an interrupt or quit signal. .IP If the prefix is `+', repeat mode will end the first cycle no open files are listed \- and of course when .I lsof is stopped with an interrupt or quit signal. When repeat mode ends because no files are listed, the process exit code will be zero if any open files were ever listed; one, if none were ever listed. .IP .I Lsof marks the end of each listing: if field output is in progress (the .BR \-F , option has been specified), the default marker is `m'; otherwise the default marker is ``========''. The marker is followed by a NL character. .IP The optional "m" argument specifies a format for the marker line. The characters following `m' are interpreted as a format specification to the .IR strftime (3) function, when both it and the .IR localtime (3) function are available in the dialect's C library. Consult the .IR strftime (3) documentation for what may appear in its format specification. Note that when field output is requested with the .B \-F option, cannot contain the NL format, ``%n''. Note also that when contains spaces or other characters that affect the shell's interpretation of arguments, must be quoted appropriately. .IP Repeat mode reduces .I lsof startup overhead, so it is more efficient to use this mode than to call .I lsof repetitively from a shell script, for example. .IP To use repeat mode most efficiently, accompany .B +|\-r with specification of other .I lsof selection options, so the amount of kernel memory access .I lsof does will be kept to a minimum. Options that filter at the process level \- e.g., .BR \-c , .BR \-g , .BR \-p , .B \-u \&\- are the most efficient selectors. .IP Repeat mode is useful when coupled with field output (see the .BR \-F , option description) and a supervising .I awk or .I Perl script, or a C program. .TP \w'names'u+4 .B \-R directs lsof to list the Parent Process IDentification number in the PPID column. .TP \w'names'u+4 .BI \-s " [p:s]" .B s alone directs .I 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. .IP When followed by a protocol name (\fIp\fR), 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 (\fIs\fP) preceded by a `^'; or included if their name(s) are not preceded by a `^'. .IP When an inclusion list is defined, only network files with state names in the list will be present in the .I lsof output. Thus, specifying one state name means that only network files with that lone state name will be listed. .IP Case is unimportant in the protocol or state names, but there may be no spaces and the colon (`:') separating the protocol name (\fIp\fP) and the state name list (\fIs\fP) is required. .IP If only TCP and UDP files are to be listed, as controlled by the specified exclusions and inclusions, the .B \-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 .B \-i option. .IP For example, to list only network files with TCP state LISTEN, use: .IP .nf \-iTCP \-sTCP:LISTEN .fi .IP Or, for example, to list network files with all UDP states except Idle, use: .IP .nf \-iUDP -sUDP:Idle .fi .IP 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 Unbound and Idle. .IP See the .I lsof FAQ (The \fBFAQ\fP section gives its location.) for more information on how to use protocol state exclusion and inclusion, including examples. .IP The .B \-o (without a following decimal digit count) and .B \-s option (without a following protocol and state name list) are mutually exclusive; they can't both be specified. When neither is specified, .I lsof displays whatever value \- size or offset \- is appropriate and available for the type of file. .IP Since some types of files don't have true sizes \- sockets, FIFOs, pipes, etc. \- lsof displays for their sizes the content amounts in their associated kernel buffers, if possible. .TP \w'names'u+4 .BI \-S " [t]" specifies an optional time-out seconds value for kernel functions \- .IR lstat (2), .IR readlink (2), and .IR stat (2) \- that might otherwise deadlock. The minimum for .I t is two; the default, fifteen; when no value is specified, the default is used. .IP See the .B "BLOCKS AND TIMEOUTS" section for more information. .TP \w'names'u+4 .BI \-T " [t]" controls the reporting of some TCP/TPI information, also reported by .IR 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: .IP .nf QR= QS= SO= SS= TF= WR= WW= .fi .IP Not all values are reported for all UNIX dialects. Items values (when available) are reported after the item name and '='. .IP When the field output mode is in effect (See .BR "OUTPUT FOR OTHER PROGRAMS" .) each item appears as a field with a `T' leading character. .IP .B \-T with no following key characters disables TCP/TPI information reporting. .IP .B \-T with following characters selects the reporting of specific TCP/TPI information: .IP .nf \fBf\fP selects reporting of socket options, states and values, and TCP flags and values. \fBq\fP selects queue length reporting. \fBs\fP selects connection state reporting. \fBw\fP selects window size reporting. .fi .IP Not all selections are enabled for some UNIX dialects. State may be selected for all dialects and is reported by default. The .B \-h or .B \-? help output for the .B \-T option will show what selections may be used with the UNIX dialect. .IP When .B \-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 .BR \-T . (In effect, then, the default is equivalent to .BR -Ts .) For example, if queue lengths and state are desired, use .BR \-Tqs . .IP 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 , and . Consult those header files for the meaning of the flags, options, states and values. .IP ``SO='' precedes socket options and values; ``SS='', socket states; and ``TF='', TCP flags and values. .IP 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: .IP .nf 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) .fi .IP Details on what socket options and values, socket states, and TCP flags and values may be displayed for particular UNIX dialects may be found in the answer to the ``Why doesn't lsof report socket options, socket states, and TCP flags and values for my dialect?'' and ``Why doesn't lsof report the partial listen queue connection count for my dialect?'' questions in the .I lsof FAQ (The \fBFAQ\fP section gives its location.) .TP \w'names'u+4 .B \-t specifies that .I lsof should produce terse output with process identifiers only and no header \- e.g., so that the output may be piped to .IR kill (1). .B \-t selects the .B \-w option. .TP \w'names'u+4 .BI \-u " s" selects the listing of files for the user whose login names or user ID numbers are in the comma\-separated set .I s \&\- e.g., ``abe'', or ``548,root''. (There should be no spaces in the set.) .IP Multiple login names or user ID numbers are joined in a single ORed set before participating in AND option selection. .IP 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 direct .I lsof to exclude the listing of files belonging to root processes, specify ``\-u^root'' or ``\-u^0''. .TP \w'names'u+4 .B \-U selects the listing of UNIX domain socket files. .TP \w'names'u+4 .B \-v selects the listing of .I lsof version information, including: revision number; when the .I lsof binary was constructed; who constructed the binary and where; the name of the compiler used to construct the .I lsof binary; the version number of the compiler when readily available; the compiler and loader flags used to construct the .I lsof binary; and system information, typically the output of .IR uname 's .B \-a option. .TP \w'names'u+4 .B \-V directs .I 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. .IP When other options are ANDed to search options, or compile\-time options restrict the listing of some files, .I 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. .IP 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 HASNOSOCKSECURITY are defined at compile time and they prevent the listing of open files. .TP \w'names'u+4 .B +|\-w Enables (\fB+\fP) or disables (\fB-\fP) the suppression of warning messages. .IP The .I 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 .B \-h or .B \-? option. Disabling warning messages when they are already disabled or enabling them when already enabled is acceptable. .IP The .B \-t option selects the .B \-w option. .TP \w'names'u+4 .BI \-x " [fl]" may accompany the .B +d and .B +D options to direct their processing to cross over symbolic links and|or file system mount points encountered when scanning the directory (\fB+d\fP) or directory tree (\fB+D\fP). .IP If .B -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 .B \-x is specified without a parameter, the next argument must begin with '-' or '+'. .IP The optional 'f' parameter enables file system mount point cross\-over processing; 'l', symbolic link cross\-over processing. .IP The .B \-x option may not be supplied without also supplying a .B +d or .B +D option. .TP \w'names'u+4 .B \-X This is a dialect\-specific option. .HP \w'names'u+4 \ \ \ \ AIX: .br This IBM AIX RISC/System 6000 option requests the reporting of executed text file and shared library references. .IP .B 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. .IP By default use of readx() is disabled. On AIX 5L and above .I lsof may need setuid\-root permission to perform the actions this option requests. .IP The .I lsof builder may specify that the .B \-X option be restricted to processes whose real UID is root. If that has been done, the .B \-X option will not appear in the .B \-h or .B \-? help output unless the real UID of the .I lsof process is root. The default .I lsof distribution allows any UID to specify .BR \-X, so by default it will appear in the help output. .IP When AIX readx() use is disabled, .I lsof may not be able to report 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. .IP The readx() function, used by .I lsof or any other program to access 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 application process, distinct from .IR lsof , asking the kernel to search the directory \- e.g., by using .IR open "(2) \-" can cause dir_search() to loop forever, thus hanging the application process. .IP Consult the .I lsof FAQ (The \fBFAQ\fP section gives its location.) and the .I 00README file of the .I lsof distribution for a more complete description of the Stale Segment ID bug, its APAR, and methods for defining readx() use when compiling .IR lsof . .HP \w'names'u+4 \ \ \ \ Linux: .br This Linux option requests that .I lsof skip the reporting of information on all open TCP, UDP and UDPLITE IPv4 and IPv6 files. .IP This Linux option is most useful when the system has an extremely large number of open TCP, UDP and UDPLITE files, the processing of whose information in the .I /proc/net/tcp* and .I /proc/net/udp* files would take .I lsof a long time, and whose reporting is not of interest. .IP Use this option with care and only when you are sure that the information you want .I lsof to display isn't associated with open TCP, UDP or UDPLITE socket files. .HP \w'names'u+4 \ \ \ \ Solaris 10 and above: .br This Solaris 10 and above option requests the reporting of cached paths for files that have been deleted \- i.e., removed with .IR rm (1) or .IR unlink (2). .IP The cached path is followed by the string ``\ (deleted)'' to indicate that the path by which the file was opened has been deleted. .IP Because intervening changes made to the path \- i.e., renames with .IR mv (1) or .IR rename (2) \- are not recorded in the cached path, what .I lsof reports is only the path by which the file was opened, not its possibly different final path. .TP \w'names'u+4 .BI \-z " [z]" specifies how Solaris 10 and higher zone information is to be handled. .IP Without a following argument \- e.g., NO .IR z " \-" the option specifies that zone names are to be listed in the ZONE output column. .IP The .B \-z option may be followed by a zone name, .BI z . That causes lsof to list only open files for processes in that zone. Multiple .BI \-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 specified by other options and arguments. .TP \w'names'u+4 .BI \-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 .B "OUTPUT FOR OTHER PROGRAMS" for more information on the 'Z' field output character. .IP Without a following argument \- e.g., NO .IR Z " \-" the option specifies that security contexts are to be listed in the SECURITY\-CONTEXT output column. .IP The .B \-Z option may be followed by a wildcard security context name, .BI Z . That causes lsof to list only open files for processes in that security context. Multiple .BI \-Z " Z" option and argument pairs may be specified to form a list of security contexts. Any open file of any process in any of the security contexts will be listed, subject to other conditions specified by other options and arguments. Note that .I Z can be A:B:C or *:B:C or A:B:* or *:*:C to match against the A:B:C context. .TP \w'names'u+4 .B -- 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 option and before the start of the file names. .TP \w'names'u+4 .I names These are path names of specific files to list. Symbolic links are resolved before use. The first name may be separated from the preceding options with the ``--'' option. .IP If a .I name is the mounted\-on directory of a file system or the device of the file system, .I lsof will list all the files open on the file system. To be considered a file system, the .I name must match a mounted\-on directory name in .IR mount (8) output, or match the name of a block device associated with a mounted\-on directory name. The .B +|\-f option may be used to force .I lsof to consider a .I name a file system identifier (\fB+f\fP) or a simple file (\fB\-f\fP). .IP If .I 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 regular file is treated \- i.e., its listing is restricted to processes that have it open as a file or as a process\-specific directory, such as the root or current working directory. To request that .I lsof look for open files inside a directory name, use the .BI +d " s" and .BI +D " D" options. .IP If a .I name is the base name of a family of multiplexed files \- e. g, AIX's .IR /dev/pt[cs] " \-" .I lsof will list all the associated multiplexed files on the device that are open \- e.g., .IR /dev/pt[cs]/1 , .IR /dev/pt[cs]/2 , etc. .IP If a .I name is a UNIX domain socket name, .I 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 structure. (See the next paragraph for an exception to that rule for Linux.) Specifying a relative path \- e.g., .I ./file \&\- in place of the file's absolute path \- e.g., .I /tmp/file \&\- won't work because .I lsof must match the characters you specify with what it finds in the kernel UNIX domain socket structures. .IP If a .I name is a Linux UNIX domain socket name, in one case .I lsof is able to search for it by its device and inode number, allowing .I 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 .I /proc/net/unix file; and it requires that .I lsof be able to obtain the device and node numbers of both the absolute path in .I /proc/net/unix and .I name via successful .IR stat (2) system calls. When those conditions are met, .I lsof will be able to search for the UNIX domain socket when some path to it is is specified in .IR name . Thus, for example, if the path is .IR /dev/log , and an .I lsof search is initiated when the working directory is .IR /dev , then .I name could be .IR ./log . .IP If a .I name is none of the above, .I lsof will list any open files whose device and inode match that of the specified path .IR name . .IP If you have also specified the .B \-b option, the only .I names you may safely specify are file systems for which your mount table supplies alternate device numbers. See the .B "AVOIDING KERNEL BLOCKS" and .B "ALTERNATE DEVICE NUMBERS" sections for more information. .IP Multiple file names are joined in a single ORed set before participating in AND option selection. .SH AFS .I Lsof supports the recognition of AFS files for these dialects (and AFS versions): .PP .nf 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) .fi .PP It may recognize AFS files on other versions of these dialects, but has not been tested there. Depending on how AFS is implemented, .I lsof may recognize AFS files in other dialects, or may have difficulties recognizing AFS files in the supported dialects. .PP .I 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, .I 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 .I lsof can't compute volume node numbers, it reports blank in the NODE column. .PP The .BI \-A " A" option is available in some dialect implementations of .I 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 .I lsof help output, presented in response to the .B \-h or .B \-? .PP See the .I lsof FAQ (The \fBFAQ\fP section gives its location.) for more information about dynamic modules, their symbols, and how they affect .I lsof options. .PP Because AFS path lookups don't seem to participate in the kernel's name cache operations, .I lsof can't identify path name components for AFS files. .SH SECURITY .I 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 .IR lsof . (The list\-all\-open\-files and device cache features may be disabled when .I lsof is compiled.) Third, its .B \-k and .B \-m options name alternate kernel name list or memory files. .PP Restricting the listing of all open files is controlled by the compile\-time HASSECURITY and HASNOSOCKSECURITY options. When HASSECURITY is defined, .I 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 .I lsof process (the one that its user logged on with). .PP However, if HASSECURITY and HASNOSOCKSECURITY are both defined, anyone may list open socket files, provided they are selected with the .B \-i option. .PP When HASSECURITY is not defined, anyone may list all open files. .PP Help output, presented in response to the .B \-h or .B \-? option, gives the status of the HASSECURITY and HASNOSOCKSECURITY definitions. .PP See the .B Security section of the .I 00README file of the .I lsof distribution for information on building .I lsof with the HASSECURITY and HASNOSOCKSECURITY options enabled. .PP Creation and use of a user\-readable and user\-writable device cache file is controlled by the compile\-time HASDCACHE option. See the .B "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 .I lsof distribution, if the real user ID under which .I lsof is executed is root, the device cache file will be written in root's home directory \- e.g., .I / or .IR /root . When HASDCACHE is not defined, .I lsof does not write or attempt to read a device cache file. .PP When HASDCACHE is defined, the .I lsof help output, presented in response to the .BR \-h , .BR \-D? , or .B \-? options, will provide device cache file handling information. When HASDCACHE is not defined, the .B \-h or .B \-? output will have no .B \-D option description. .PP Before you decide to disable the device cache file feature \- enabling it improves the performance of .I lsof by reducing the startup overhead of examining all the nodes in .I /dev (or .IR /devices ) \&\- read the discussion of it in the .I 00DCACHE file of the .I lsof distribution and the .I lsof FAQ (The \fBFAQ\fP section gives its location.) .PP WHEN IN DOUBT, YOU CAN TEMPORARILY DISABLE THE USE OF THE DEVICE CACHE FILE WITH THE .B \-Di OPTION. .PP When .I lsof user declares alternate kernel name list or memory files with the .B \-k and .B \-m options, .I lsof checks the user's authority to read them with .IR access (2). This is intended to prevent whatever special power .I lsof's modes might confer on it from letting it read files not normally accessible via the authority of the real user ID. .SH OUTPUT This section describes the information .I lsof lists for each open file. See the .B "OUTPUT FOR OTHER PROGRAMS" section for additional information on output that can be processed by another program. .PP .I Lsof only outputs printable (declared so by .IR isprint (3)) 8 bit characters. 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\-printable in the COMMAND column (``\\x20'') and printable elsewhere. .PP For some dialects \- if HASSETLOCALE is defined in the dialect's machine.h header file \- .I lsof will print the extended 8 bit characters of a language locale. The .I lsof process must be supplied a language locale environment variable (e.g., LANG) whose value represents a known language locale in which the extended characters are considered printable by .IR isprint (3). Otherwise .I lsof considers the extended characters non\-printable and prints them according to its rules for non\-printable characters, stated above. Consult your dialect's .IR 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. .PP .I Lsof's language locale support for a dialect also covers wide characters \- e.g., UTF-8 \- when HASSETLOCALE and HASWIDECHAR are defined in the dialect's machine.h header file, and when a suitable language locale has been defined in the appropriate environment variable for the .I lsof process. Wide characters are printable under those conditions if .IR iswprint (3) reports them to be. If HASSETLOCALE, HASWIDECHAR and a suitable language locale aren't defined, or if .IR iswprint (3) reports wide characters that aren't printable, .I lsof considers the wide characters non\-printable and prints each of their 8 bits according to its rules for non\-printable characters, stated above. .PP Consult the answers to the "Language locale support" questions in the lsof FAQ (The \fBFAQ\fP section gives its location.) for more information. .PP .I Lsof dynamically sizes the output columns each time it runs, guaranteeing that each column is a minimum size. It also guarantees that each column is separated from its predecessor by at least one space. .TP \w'COMMAND'u+4 COMMAND contains the first nine characters of the name of the UNIX command associated with the process. If a non\-zero .I w value is specified to the .BI +c " w" option, the column contains the first .I w characters of the name of the UNIX command associated with the process up to the limit of characters supplied to .I lsof by the UNIX dialect. (See the description of the .BI +c " w" command or the .I lsof FAQ for more information. The \fBFAQ\fP section gives its location.) .IP If .I w is less than the length of the column title, ``COMMAND'', it will be raised to that length. .IP If a zero .I w value is specified to the .BI +c " w" option, the column contains all the characters of the name of the UNIX command associated with the process. .IP 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 .B "OUTPUT FOR OTHER COMMANDS" section for information on selecting field output and the associated command name descriptor. .TP PID is the Process IDentification number of the process. .TP TID is the task IDentification number, if a task reporting is supported by the dialect and a task is being listed. (If help output \- i.e., the output of the .B \-h or .B \-? options \- shows this option, then task reporting is supported by the dialect.) .IP A blank TID column indicates a process \- i.e., a non\-task. .TP ZONE is the Solaris 10 and higher zone name. This column must be selected with the .B \-z option. .TP SECURITY\-CONTEXT is the SELinux security context. This column must be selected with the .B -Z option. Note that the .B -Z option is inhibited when SELinux is disabled in the running Linux kernel. .TP PPID is the Parent Process IDentification number of the process. It is only displayed when the .B \-R option has been specified. .TP PGID is the process group IDentification number associated with the process. It is only displayed when the .B \-g option has been specified. .TP USER is the user ID number or login name of the user to whom the process belongs, usually the same as reported by .IR ps (1). However, on Linux USER is the user ID number or login that owns the directory in /proc where .I lsof finds information about the process. Usually that is the same value reported by .IR ps (1), but may differ when the process has changed its effective user ID. (See the .B \-l option description for information on when a user ID number or login name is displayed.) .TP FD is the File Descriptor number of the file or: .IP .nf \fBcwd\fP current working directory; .br \fBL\fInn\fR library references (AIX); .br \fBerr\fR FD information error (see NAME column); .br \fBjld\fR jail directory (FreeBSD); .br \fBltx\fP shared library text (code and data); .br \fBMxx\fP 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 \fBpd\fP parent directory; .br \fBrtd\fP root directory; .br \fBtr\fR kernel trace file (OpenBSD); .br \fBtxt\fP program text (code and data); .br \fBv86\fP VP/ix mapped file; .fi .IP FD is followed by one of these characters, describing the mode under which the file is open: .IP \fBr\fP for read access; .br \fBw\fP for write access; .br \fBu\fP for read and write access; .br space if mode unknown and no lock .br character follows; .br `\-' if mode unknown and lock .br character follows. .IP The mode character is followed by one of these lock characters, describing the type of lock applied to the file: .IP \fBN\fP for a Solaris NFS lock of unknown type; .br \fBr\fP for read lock on part of the file; .br \fBR\fP for a read lock on the entire file; .br \fBw\fP for a write lock on part of the file; .br \fBW\fP for a write lock on the entire file; .br \fBu\fP for a read and write lock of any length; .br \fBU\fP for a lock of unknown type; .br \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 space if there is no lock. .IP See the .B LOCKS section for more information on the lock information character. .IP The FD column contents constitutes a single field for parsing in post\-processing scripts. .TP TYPE is the type of the node associated with the file \- e.g., GDIR, GREG, VDIR, VREG, etc. .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 ``ax25'' for a Linux AX.25 socket; .IP or ``inet'' for an Internet domain socket; .IP or ``lla'' for a HP\-UX link level access file; .IP or ``rte'' for an AF_ROUTE socket; .IP or ``sock'' for a socket of unknown domain; .IP or ``unix'' for a UNIX domain socket; .IP or ``x.25'' for an HP\-UX x.25 socket; .IP or ``BLK'' for a block special file; .IP or ``CHR'' for a character special file; .IP or ``DEL'' for a Linux map file that has been deleted; .IP or ``DIR'' for a directory; .IP or ``DOOR'' for a VDOOR file; .IP or ``FIFO'' for a FIFO special file; .IP or ``KQUEUE'' for a BSD style kernel event queue file; .IP or ``LINK'' for a symbolic link file; .IP or ``MPB'' for a multiplexed block file; .IP or ``MPC'' for a multiplexed character file; .IP or ``NOFD'' for a Linux /proc//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; .IP or ``PAXV'' for a .I /proc/auxv file; .IP or ``PCRE'' for a .I /proc/cred file; .IP or ``PCTL'' for a .I /proc control file; .IP or ``PCUR'' for the current .I /proc process; .IP or ``PCWD'' for a .I /proc current working directory; .IP or ``PDIR'' for a .I /proc directory; .IP or ``PETY'' for a .I /proc executable type (\fIetype\fP); .IP or ``PFD'' for a .I /proc file descriptor; .IP or ``PFDR'' for a .I /proc file descriptor directory; .IP or ``PFIL'' for an executable .I /proc file; .IP or ``PFPR'' for a .I /proc FP register set; .IP or ``PGD'' for a .I /proc/pagedata file; .IP or ``PGID'' for a .I /proc group notifier file; .IP or ``PIPE'' for pipes; .IP or ``PLC'' for a .I /proc/lwpctl file; .IP or ``PLDR'' for a .I /proc/lpw directory; .IP or ``PLDT'' for a .I /proc/ldt file; .IP or ``PLPI'' for a .I /proc/lpsinfo file; .IP or ``PLST'' for a .I /proc/lstatus file; .IP or ``PLU'' for a .I /proc/lusage file; .IP or ``PLWG'' for a .I /proc/gwindows file; .IP or ``PLWI'' for a .I /proc/lwpsinfo file; .IP or ``PLWS'' for a .I /proc/lwpstatus file; .IP or ``PLWU'' for a .I /proc/lwpusage file; .IP or ``PLWX'' for a .I /proc/xregs file' .IP or ``PMAP'' for a .I /proc map file (\fImap\fP); .IP or ``PMEM'' for a .I /proc memory image file; .IP or ``PNTF'' for a .I /proc process notifier file; .IP or ``POBJ'' for a .I /proc/object file; .IP or ``PODR'' for a .I /proc/object directory; .IP or ``POLP'' for an old format .I /proc light weight process file; .IP or ``POPF'' for an old format .I /proc PID file; .IP or ``POPG'' for an old format .I /proc page data file; .IP or ``PORT'' for a SYSV named pipe; .IP or ``PREG'' for a .I /proc register file; .IP or ``PRMP'' for a .I /proc/rmap file; .IP or ``PRTD'' for a .I /proc root directory; .IP or ``PSGA'' for a .I /proc/sigact file; .IP or ``PSIN'' for a .I /proc/psinfo file; .IP or ``PSTA'' for a .I /proc status file; .IP or ``PSXSEM'' for a POSIX semaphore file; .IP or ``PSXSHM'' for a POSIX shared memory file; .IP or ``PUSG'' for a .I /proc/usage file; .IP or ``PW'' for a .I /proc/watch file; .IP or ``PXMP'' for a .I /proc/xmap file; .IP or ``REG'' for a regular file; .IP or ``SMT'' for a shared memory transport file; .IP or ``STSO'' for a stream socket; .IP or ``UNNM'' for an unnamed type file; .IP or ``XNAM'' for an OpenServer Xenix special file of unknown type; .IP or ``XSEM'' for an OpenServer Xenix semaphore file; .IP or ``XSD'' for an OpenServer Xenix shared data file; .IP or the four type number octets if the corresponding name isn't known. .TP FILE\-ADDR contains the kernel file structure address when .B f has been specified to .BR +f ; .TP FCT contains the file reference count from the kernel file structure when .B c has been specified to .BR +f ; .TP FILE\-FLAG when .B g or .B G has been specified to .BR +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 semicolon (`;'); the first list may contain short\-hand names for f_flag[s] values from the following table: .IP .nf 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 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 TR truncate W write WKUP parallel I/O synchronization WTG parallel I/O synchronization VH vhangup pending VTXT virtual text XL exclusive lock .fi .IP this list of names was derived from F* #define's in dialect header files , , , , and ; see the lsof.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 for kernel per\-process open file flags from this table: .IP .nf 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) .fi .TP NODE\-ID (or INODE\-ADDR for some dialects) contains a unique identifier for the file node (usually the kernel vnode or inode address, but also occasionally a concatenation of device and node number) when .B n has been specified to .BR +f ; .TP DEVICE contains the device numbers, separated by commas, for a character special, block special, regular, directory or NFS file; .IP or ``memory'' for a memory file system node under Tru64 UNIX; .IP or the address of the private data area of a Solaris socket stream; .IP or a kernel reference address that identifies the file (The kernel reference address may be used for FIFO's, for example.); .IP or the base address or device name of a Linux AX.25 socket device. .IP Usually only the lower thirty two bits of Tru64 UNIX kernel addresses are displayed. .TP 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. .I Lsof displays whatever value \- size or offset \- is appropriate for the type of the file and the version of .IR lsof . .IP On some UNIX dialects .I lsof can't obtain accurate or consistent 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 .I 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 .I lsof FAQ (The \fBFAQ\fP section gives its location.) for more information. .IP The file size is displayed in decimal; the offset is normally displayed in decimal with a leading ``0t'' if it contains 8 digits or less; in hexadecimal with a leading ``0x'' if it is longer than 8 digits. (Consult the .BI \-o " o" option description for information on when 8 might default to some other value.) .IP 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). .IP If the .B \-o option is specified, .I 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. .IP The .I lsof user can control the switch from ``0t'' to ``0x'' with the .BI \-o " o" option. Consult its description for more information. .IP If the .B \-s option is specified, .I lsof always displays the file size (or nothing if no size is available) and labels the column SIZE. The .B \-o and .B \-s options are mutually exclusive; they can't both be specified. .IP For files that don't have a fixed size \- e.g., don't reside on a disk device \- .I 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. .TP NLINK contains the file link count when .B +L has been specified; .TP NODE is the node number of a local file; .IP or the inode number of an NFS file in the server host; .IP or the Internet protocol type \- e. g, ``TCP''; .IP or ``STR'' for a stream; .IP or ``CCITT'' for an HP\-UX x.25 socket; .IP or the IRQ or inode number of a Linux AX.25 socket device. .TP NAME is the name of the mount point and file system on which the file resides; .IP or the name of a file specified in the .I names option (after any symbolic links have been resolved); .IP or the name of a character special or block special device; .IP 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 address; IP addresses may be reported as numbers or names, depending on the .BR +|\-M , .BR \-n , and .B \-P options; colon\-separated IPv6 numbers are enclosed in square brackets; IPv4 INADDR_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 destination; TCP, UDP and UDPLITE remote addresses may be followed by TCP/TPI information in parentheses \- state (e.g., ``(ESTABLISHED)'', ``(Unbound)''), queue sizes, and window sizes (not all dialects) \- in a fashion similar to what .IR netstat (1) reports; see the .B \-T option description or the description of the TCP/TPI field in .B "OUTPUT FOR OTHER PROGRAMS" for more information on state, queue size, and window size; .IP or the address or name of a UNIX domain socket, possibly including 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; .IP or the local and remote mount point names of an NFS file; .IP or ``STR'', followed by the stream name; .IP or a stream character device name, followed by ``->'' and the stream name or a list of stream module names, separated by ``->''; .IP or ``STR:'' followed by the SCO OpenServer stream device and module names, separated by ``->''; .IP or system directory name, `` -- '', and as many components of the path name as .I lsof can find in the kernel's name cache for selected dialects (See the .B "KERNEL NAME CACHE" section for more information.); .IP or ``PIPE->'', followed by a Solaris kernel pipe destination address; .IP or ``COMMON:'', followed by the vnode device information structure's device name, for a Solaris common vnode; .IP or the address family, followed by a slash (`/'), followed by fourteen comma\-separated bytes of a non\-Internet raw socket address; .IP or the HP\-UX x.25 local address, followed by the virtual connection number (if any), followed by the remote address (if any); .IP or ``(dead)'' for disassociated Tru64 UNIX files \- typically terminal files that have been flagged with the TIOCNOTTY ioctl and closed by daemons; .IP or ``rd='' and ``wr='' for the values of the read and write offsets of a FIFO; .IP or ``clone \fIn\fP:/dev/event'' for SCO OpenServer file clones of the .I /dev/event device, where .I n is the minor device number of the file; .IP or ``(socketpair: n)'' for a Solaris 2.6, 8, 9 or 10 UNIX domain socket, created by the .IR socketpair (3N) network function; .IP 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 .IR shutdown (2) function); .IP or the local and remote addresses of a Linux IPX socket file in the form :[:], followed in parentheses by the transmit and receive queue sizes, and the connection state; .IP 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; .IP or the association value, association index, endpoint value, local address, local port, remote address and remote port for Linux SCTP sockets. .PP For dialects that support a ``namefs'' file system, allowing one file to be attached to another with .IR fattach (3C), .I lsof will add ``(FA:)'' to the NAME column. and are hexadecimal vnode addresses. will be ``<-'' if has been fattach'ed to this vnode whose address is ; and ``->'' if , the vnode address of this vnode, has been fattach'ed to . may be omitted if it already appears in the DEVICE column. .PP .I Lsof may add two parenthetical notes to the NAME column for open Solaris 10 files: \&``(?)'' if .I lsof considers the path name of questionable accuracy; and ``(deleted)'' if the .B \-X option has been specified and .I lsof detects the open file's path name has been deleted. Consult the .I lsof FAQ (The \fBFAQ\fP section gives its location.) for more information on these NAME column additions. .SH LOCKS .I 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. .PP Moreover, when a process holds several byte level locks on a file, .I 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 reported for a full file lock. .PP Generally .I lsof can only report on locks held by local processes on local 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 remote locks in local structures. .PP .I Lsof has trouble reporting locks for some UNIX dialects. Consult the .B BUGS section of this manual page or the .I lsof FAQ (The \fBFAQ\fP section gives its location.) for more information. .SH "OUTPUT FOR OTHER PROGRAMS" When the .B \-F option is specified, .I lsof produces output that is suitable for processing by another program \- e.g, an .I awk or .I Perl script, or a C program. .PP 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 extends to the field terminator. .PP 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 command, the process group IDentification (PGID) number, the task number and the user ID (UID) number or login name. .PP A file set begins with a field whose identifier is `f' (for file descriptor). It is followed by lines that describe the file's access mode, lock state, type, device, size, offset, inode, protocol, name and stream module names. It extends to the beginning of the next file or process set, whichever comes first. .PP When the NUL (000) field terminator has been selected with the 0 (zero) field identifier character, .I lsof ends each process and file set with a NL (012) character. .PP .I Lsof always produces one field, the PID (`p') field. All other fields may be declared optionally in the field identifier character list that follows the .B \-F option. When a field selection character identifies an item .I lsof does not normally list \- e.g., PPID, selected with .BR \-R " \-" specification of the field character \- e.g., ``\fB\-FR\fP'' \- also selects the listing of the item. .PP 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, .I lsof supports the .B \-F option; it selects the output of all fields with NL terminators (the .B \-F0 option pair selects the output of all fields with NUL terminators). For compatibility reasons neither .B \-F nor .B \-F0 select the raw device field. .PP These are the fields that .I lsof will produce. The single character listed first is the field identifier. .PP .nf 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) f file descriptor F file structure address (0x) G file flaGs (0x; names if \fB+fg\fP 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 n file name, comment, Internet address N node identifier (ox o file's offset (decimal) p process ID (always selected) P protocol name r raw device number (0x) 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= QS= SO= (not all dialects) SS= (not all dialects) ST= TF= (not all dialects) WR= (not all dialects) WW= (not all dialects) (TCP/TPI information isn't reported for all supported UNIX dialects. The \fB\-h\fP or \fB\-?\fP help output for the \fB\-T\fP 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 \fB\-F?\fP identifies the information to be found in dialect\-specific fields.) .fi .PP You can get on\-line help information on these characters and their descriptions by specifying the .B \-F? option pair. (Escape the `?' character as your shell requires.) Additional information on field content can be found in the .B OUTPUT section. .PP As an example, ``\fB\-F pcfn\fP'' will select the process ID (`p'), command name (`c'), file descriptor (`f') and file name (`n') fields with an NL field terminator character; ``\fB\-F pcfn0\fP'' selects the same output with a NUL (000) field terminator character. .PP .I Lsof doesn't produce all fields for every process or file set, only those that are available. Some fields are mutually exclusive: file device 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. .PP Normally .I lsof ends each field with a NL (012) character. The 0 (zero) field identifier character may be specified to change the field terminator character to a NUL (000). A NUL terminator may be easier to process with .I 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, .I lsof ends each process and file set with a NL (012). .PP Three aids to producing programs that can process .I lsof field output are included in the .I lsof distribution. The first is a C header file, .IR lsof_fields.h , that contains symbols for the field identification characters, indexes for storing them in a table, and explanation strings that may be compiled into programs. .I Lsof uses this header file. .PP The second aid is a set of sample scripts that process field output, written in .IR awk , .I Perl 4, and .I Perl 5. They're located in the .I scripts subdirectory of the .I lsof distribution. .PP The third aid is the C library used for the .I lsof test suite. The test suite is written in C and uses field output to validate the correct operation of .IR lsof . The library can be found in the .I tests/LTlib.c file of the .I lsof distribution. The library uses the first aid, the .I lsof_fields.h header file. .SH "BLOCKS AND TIMEOUTS" .I Lsof can be blocked by some kernel functions that it uses \- .IR lstat (2), .IR readlink (2), and .IR stat (2). These functions are stalled in the kernel, for example, when the hosts where mounted NFS file systems reside become inaccessible. .PP .I Lsof attempts to break these blocks with timers and child processes, but the techniques are not wholly reliable. When .I lsof does manage to break a block, it will report the break with an error message. The messages may be suppressed with the .B \-t and .B \-w options. .PP The default timeout value may be displayed with the .B \-h or .B \-? option, and it may be changed with the .BI \-S " [t]" option. The minimum for .I t is two seconds, but you should avoid small values, since slow system responsiveness can cause short timeouts to expire unexpectedly and perhaps stop .I lsof before it can produce any output. .PP When .I 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. .PP .I Lsof can also be directed to avoid the protection of timers and child processes when using the kernel functions that might block by specifying the .B \-O option. While this will allow .I lsof to start up with less overhead, it exposes .I lsof completely to the kernel situations that might block it. Use this option cautiously. .SH "AVOIDING KERNEL BLOCKS" .PP You can use the .B \-b option to tell .I lsof to avoid using kernel functions that would block. Some cautions apply. .PP First, using this option usually requires that your system supply alternate device numbers in place of the device numbers that .I lsof would normally obtain with the .IR lstat (2) and .IR stat (2) kernel functions. See the .B "ALTERNATE DEVICE NUMBERS" section for more information on alternate device numbers. .PP Second, you can't specify .I names for .I lsof to locate unless they're file system names. This is because .I lsof needs to know the device and inode numbers of files listed with .I names in the .I lsof options, and the .B \-b option prevents .I lsof from obtaining them. Moreover, since .I 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, .I lsof won't be able to locate files on the named file systems. .PP Third, if the names of your file system directories that .I lsof obtains from your system's mount table are symbolic links, .I lsof won't be able to resolve the links. This is because the .B \-b option causes .I lsof to avoid the kernel .IR readlink (2) function it uses to resolve symbolic links. .PP Finally, using the .B \-b option causes .I lsof to issue warning messages when it needs to use the kernel functions that the .B \-b option directs it to avoid. You can suppress these messages by specifying the .B \-w option, but if you do, you won't see the alternate device numbers reported in the warning messages. .SH "ALTERNATE DEVICE NUMBERS" .PP On some dialects, when .I lsof has to break a block because it can't get information about a mounted file system via the .IR lstat (2) and .IR stat (2) kernel functions, or because you specified the .B \-b option, .I lsof can obtain some of the information it needs \- the device number and possibly the file system type \- from the system mount table. When that is possible, .I lsof will report the device number it obtained. (You can suppress the report by specifying the .B \-w option.) .PP You can assist this process if your mount table is supported with an .I /etc/mtab or .I /etc/mnttab file that contains an options field by adding a ``dev=xxxx'' field for mount points that do not have one in their options 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. .PP You may also be able to supply device numbers using the .B +m and .BI +m " m" options, provided they are supported by your dialect. Check the output of .I lsof's .B \-h or .B \-? options to see if the .B +m and .BI +m " m" options are available. .PP The ``xxxx'' portion of the field is the hexadecimal value of the file system's device number. (Consult the .I st_dev field of the output of the .IR lstat (2) and .IR stat (2) functions for the appropriate values for your file systems.) Here's an example from a Sun Solaris 2.6 .I /etc/mnttab for a file system remotely mounted via NFS: .PP .nf nfs ignore,noquota,dev=2a40001 .fi .PP 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 .I lsof on one of its clients, .I lsof probably won't be able to get output from the .IR lstat (2) and .IR 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. .PP Some dialects that do not use an ASCII .I /etc/mtab or .I /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. .I Lsof knows how to obtain the alternative device number for these dialects and uses it when its attempt to .IR lstat (2) or .IR stat (2) the file system is blocked. .PP If you're not sure your dialect supplies alternate device numbers for file systems from its mount table, use this .I lsof incantation to see if it reports any alternate device numbers: .PP .IP lsof -b .PP Look for standard error file warning messages that begin ``assuming "dev=xxxx" from ...''. .SH "KERNEL NAME CACHE" .PP .I Lsof is able to examine the kernel's name cache or use other kernel facilities (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 system operations apparently don't use it, either.) .PP .I Lsof reports the complete paths it finds in the NAME column. If .I 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. .PP When .I lsof is run in repeat mode \- i.e., with the .B \-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 processes can cause the kernel to remove entries from its name cache and replace them with others. .PP .I 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, .I lsof may find a reference to the wrong entry in the cache. The .I lsof FAQ (The \fBFAQ\fP section gives its location.) has more information on this situation. .PP .I Lsof can report path name components for these dialects: .PP .nf FreeBSD HP\-UX Linux NetBSD NEXTSTEP OpenBSD OPENSTEP SCO OpenServer SCO|Caldera UnixWare Solaris Tru64 UNIX .fi .PP .I Lsof can't report path name components for these dialects: .PP .nf AIX .fi .PP If you want to know why .I lsof can't report path name components for some dialects, see the .I lsof FAQ (The \fBFAQ\fP section gives its location.) .SH "DEVICE CACHE FILE" .PP Examining all members of the .I /dev (or .IR /devices ) node tree with .IR stat (2) functions can be time consuming. What's more, the information that .I lsof needs \- device number, inode number, and path \- rarely changes. .PP Consequently, .I lsof normally maintains an ASCII text file of cached .I /dev (or .IR /devices ) information (exception: the /proc\-based Linux .I lsof where it's not needed.) The local system administrator who builds .I lsof can control the way the device cache file path is formed, selecting from these options: .PP .nf Path from the \fB\-D\fP option; Path from an environment variable; System\-wide path; Personal path (the default); Personal path, modified by an environment variable. .fi .PP Consult the output of the .BR \-h , .B \-D? , or .B \-? help options for the current state of device cache support. The help output lists the default read\-mode device cache file path that is in effect for the current invocation of .IR lsof . The .B \-D? option output lists the read\-only and write device cache file paths, the names of any applicable environment variables, and the personal device cache path format. .PP .I Lsof can detect that the current device cache file has been accidentally or maliciously modified by integrity checks, including the computation and verification of a sixteen bit Cyclic Redundancy Check (CRC) sum on the file's contents. When .I 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 legitimately write. .PP The path from which a .I 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 .I 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. .PP If available, the .B \-Dr option will inhibit the writing of a new device cache file. (It's always available when specified without a path name argument.) .PP When a new device is added to the system, the device cache file may need to be recreated. Since .I lsof compares the mtime of the device cache file with the mtime and ctime of the .I /dev (or .IR /devices ) directory, it usually detects that a new device has been added; in that case .I lsof issues a warning message and attempts to rebuild the device cache file. .PP Whenever .I 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. .SH "LSOF PERMISSIONS THAT AFFECT DEVICE CACHE FILE ACCESS" .PP Two permissions of the .I lsof executable affect its ability to access device cache files. The permissions are set by the local system administrator when .I lsof is installed. .PP The first and rarer permission is setuid\-root. It comes into effect when .I lsof is executed; its effective UID is then root, while its real (i.e., that of the logged\-on user) UID is not. The .I lsof distribution recommends that versions for these dialects run setuid\-root. .PP .nf HP-UX 11.11 and 11.23 Linux .fi .PP The second and more common permission is setgid. It comes into effect when the effective group IDentification number (GID) of the .I lsof process is set to one that can access kernel memory devices \- e.g., ``kmem'', ``sys'', or ``system''. .PP An .I lsof process that has setgid permission usually surrenders the permission after it has accessed the kernel memory devices. When it does that, .I lsof can allow more liberal device cache path formations. The .I lsof distribution recommends that versions for these dialects run setgid and be allowed to surrender setgid permission. .PP .nf 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 and [6789].x for 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 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 Tru64 UNIX 5.1 .fi .PP (Note: .I lsof for AIX 5L and above needs setuid\-root permission if its .B \-X option is used.) .PP .I Lsof for these dialects does not support a device cache, so the permissions given to the executable don't apply to the device cache file. .PP .nf Linux .fi .SH "DEVICE CACHE FILE PATH FROM THE \-D OPTION" .PP The .B \-D option provides limited means for specifying the device cache file path. Its .B ? function will report the read\-only and write device cache file paths that .I lsof will use. .PP When the .B \-D .BR b , .BR r , and .B u functions are available, you can use them to request that the cache file be built in a specific location (\fBb\fR[\fIpath\fR]); read but not rebuilt (\fBr\fR[\fIpath\fR]); or read and rebuilt (\fBu\fR[\fIpath\fR]). The .BR b , .BR r , and .B u functions are restricted under some conditions. They are restricted when the .I lsof process is setuid\-root. The path specified with the .B r function is always read\-only, even when it is available. .PP The .BR b , .BR r , and .B u functions are also restricted when the .I lsof process runs setgid and .I lsof doesn't surrender the setgid permission. (See the .B "LSOF PERMISSIONS THAT AFFECT DEVICE CACHE FILE ACCESS" section for a list of implementations that normally don't surrender their setgid permission.) .PP A further .B \-D function, .B i (for ignore), is always available. .PP When available, the .B b function tells .I lsof to read device information from the kernel with the .IR stat (2) function and build a device cache file at the indicated path. .PP When available, the .B r function tells .I lsof to read the device cache file, but not update it. When a path argument accompanies .BR \-Dr , it names the device cache file path. The .B r function is always available when it is specified without a path name argument. If .I lsof is not running setuid\-root and surrenders its setgid permission, a path name argument may accompany the .B r function. .PP When available, the .B u function tells .I 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 .I lsof process effective and real UIDs. .SH "DEVICE CACHE PATH FROM AN ENVIRONMENT VARIABLE" .PP .I Lsof's second choice for the device cache file is the contents of the LSOFDEVCACHE environment variable. It avoids this choice if the .I lsof process is setuid\-root, or the real UID of the process is root. .PP A further restriction applies to a device cache file path taken from the LSOFDEVCACHE environment variable: .I lsof will not write a device cache file to the path if the .I lsof process doesn't surrender its setgid permission. (See the .B "LSOF PERMISSIONS THAT AFFECT DEVICE CACHE FILE ACCESS" section for information on implementations that don't surrender their setgid permission.) .PP The local system administrator can disable the use of the LSOFDEVCACHE environment variable or change its name when building .IR lsof . Consult the output of .B \-D? for the environment variable's name. .SH "SYSTEM-WIDE DEVICE CACHE PATH" .PP The local system administrator may choose to have a system\-wide device cache file when building .IR lsof . That file will generally be constructed by a special system administration procedure when the system is booted or when the contents of .I /dev or .IR /devices ) changes. If defined, it is .I lsof's third device cache file path choice. .PP You can tell that a system\-wide device cache file is in effect for your local installation by examining the .I lsof help option output \- i.e., the output from the .B \-h or .B \-? option. .PP .I Lsof will never write to the system\-wide device cache file path by default. It must be explicitly named with a .B \-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). .SH "PERSONAL DEVICE CACHE PATH (DEFAULT)" .PP The default device cache file path of the .I lsof distribution is one recorded in the home directory of the real UID that executes .IR lsof . Added to the home directory is a second path component of the form .IR .lsof_hostname . .PP This is .I lsof's fourth device cache file path choice, and is usually the default. If a system\-wide device cache file path was defined when .I lsof was built, this fourth choice will be applied when .I lsof can't find the system\-wide device cache file. This is the .B only time .I lsof uses two paths when reading the device cache file. .PP The .I hostname part of the second component is the base name of the executing host, as returned by .IR gethostname (2). The base name is defined to be the characters preceding the first `.' in the .IR gethostname (2) output, or all the .IR gethostname (2) output if it contains no `.'. .PP 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 distinct real user ID on a given host that executes .I lsof has a distinct device cache file. The .I 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. .PP The personal device cache file path formed by this method represents a device cache file that .I lsof will attempt to read, and will attempt to write should it not exist or should its contents be incorrect or outdated. .PP The .B \-Dr option without a path name argument will inhibit the writing of a new device cache file. .PP The .B \-D? option will list the format specification for constructing the personal device cache file. The conversions used in the format specification are described in the .I 00DCACHE file of the .I lsof distribution. .SH "MODIFIED PERSONAL DEVICE CACHE PATH" .PP If this option is defined by the local system administrator when .I lsof is built, the LSOFPERSDCPATH environment variable contents may be used to add a component of the personal device cache file path. .PP The LSOFPERSDCPATH variable contents are inserted in the path at the place marked by the local system administrator with the ``%p'' conversion in the HASPERSDC format specification of the dialect's .I machine.h header file. (It's placed right after the home directory in the default .I lsof distribution.) .PP Thus, for example, if LSOFPERSDCPATH contains ``LSOF'', the home directory 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: .PP .nf /Homes/abe/LSOF/.lsof_vic .fi .PP The LSOFPERSDCPATH environment variable is ignored when the .I lsof process is setuid\-root or when the real UID of the process is root. .PP .I Lsof will not write to a modified personal device cache file path if the .I lsof process doesn't surrender setgid permission. (See the .B "LSOF PERMISSIONS THAT AFFECT DEVICE CACHE FILE ACCESS" section for a list of implementations that normally don't surrender their setgid permission.) .PP 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 .I lsof doesn't surrender its setgid permission, you will have to allow .I lsof to create device cache files at the standard personal path and move them to your subdirectory with shell commands. .PP The local system administrator may: disable this option when .I 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 .B \-D? option for the environment variable's name and the HASPERSDC format specification. .SH DIAGNOSTICS Errors are identified with messages on the standard error file. .PP .I 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 .B \-V option is specified, .I lsof will indicate the search items it failed to list. .PP It returns a zero (0) if no errors were detected and if it was able to list some information about all the specified search arguments. .PP .PP When .I lsof cannot open access to .I /dev (or .IR /devices ) or one of its subdirectories, or get information on a file in them with .IR stat (2), it issues a warning message and continues. That .I lsof will issue warning messages about inaccessible files in .I /dev (or .IR /devices ) is indicated in its help output \- requested with the .B \-h or >B \-? options \- with the message: .PP .nf Inaccessible /dev warnings are enabled. .fi .PP The warning message may be suppressed with the .B \-w option. It may also have been suppressed by the system administrator when .I lsof was compiled by the setting of the WARNDEVACCESS definition. In this case, the output from the help options will include the message: .PP .nf Inaccessible /dev warnings are disabled. .fi .PP Inaccessible device warning messages usually disappear after .I lsof has created a working device cache file. .SH EXAMPLES For a more extensive set of examples, documented more fully, see the .I 00QUICKSTART file of the .I lsof distribution. .PP To list all open files, use: .IP lsof .PP To list all open Internet, x.25 (HP\-UX), and UNIX domain files, use: .IP lsof -i -U .PP To list all open IPv4 network files in use by the process whose PID is 1234, use: .IP lsof -i 4 -a -p 1234 .PP Presuming the UNIX dialect supports IPv6, to list only open IPv6 network files, use: .IP lsof -i 6 .PP To list all files using any protocol on ports 513, 514, or 515 of host wonderland.cc.purdue.edu, use: .IP lsof -i @wonderland.cc.purdue.edu:513-515 .PP To list all files using any protocol on any port of mace.cc.purdue.edu (cc.purdue.edu is the default domain), use: .IP lsof -i @mace .PP To list all open files for login name ``abe'', or user ID 1234, or process 456, or process 123, or process 789, use: .IP lsof -p 456,123,789 -u 1234,abe .PP To list all open files on device /dev/hd4, use: .IP lsof /dev/hd4 .PP To find the process that has /u/abe/foo open, use: .IP lsof /u/abe/foo .PP To send a SIGHUP to the processes that have /u/abe/bar open, use: .IP kill -HUP `lsof -t /u/abe/bar` .PP To find any open file, including an open UNIX domain socket file, with the name .IR /dev/log , use: .IP lsof /dev/log .PP To find processes with open files on the NFS file system named .I /nfs/mount/point whose server is inaccessible, and presuming your mount table supplies the device number for .IR /nfs/mount/point , use: .IP lsof -b /nfs/mount/point .PP To do the preceding search with warning messages suppressed, use: .IP lsof -bw /nfs/mount/point .PP To ignore the device cache file, use: .IP lsof -Di .PP To obtain PID and command name field output for each process, file descriptor, file device number, and file inode number for each file of each process, use: .IP lsof -FpcfDi .PP To list the files at descriptors 1 and 3 of every process running the .I lsof command for login ID ``abe'' every 10 seconds, use: .IP lsof -c lsof -a -d 1 -d 3 -u abe -r10 .PP 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 .BI \-c " c" option: .IP lsof -c /^..o.$/i -a -d cwd .PP To find an IP version 4 socket file by its associated numeric dot\-form address, use: .IP lsof -i@128.210.15.17 .PP To find an IP version 6 socket file (when the UNIX dialect supports IPv6) by its associated numeric colon\-form address, use: .IP lsof -i@[0:1:2:3:4:5:6:7] .PP 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 zeroes in it \- e.g., the loop\-back address \- use: .IP lsof -i@[::1] .PP To obtain a repeat mode marker line that contains the current time, use: .IP lsof -rm====%T==== .PP To add spaces to the previous marker line, use: .IP lsof -r "m==== %T ====" .SH BUGS Since .I lsof reads kernel memory in its search for open files, rapid changes in kernel memory may produce unpredictable results. .PP When a file has multiple record locks, the lock status character (following 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. .PP .I Lsof can't search for files with restrictive access permissions by .I 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. .PP The display of the destination address of a raw socket (e.g., for .IR ping ) depends on the UNIX operating system. Some dialects store the destination address in the raw socket's protocol control block, some do not. .PP .I Lsof can't always represent Solaris device numbers in the same way that .IR ls (1) does. For example, the major and minor device numbers that the .IR lstat (2) and .IR stat (2) functions report for the directory on which CD-ROM files are mounted (typically .IR /cdrom ) are not the same as the ones that it reports for the device on which CD-ROM files are mounted (typically .IR /dev/sr0 ). (\fILsof\fP reports the directory numbers.) .PP The support for .I /proc file systems is available only for BSD and Tru64 UNIX dialects, Linux, and dialects derived from SYSV R4 \- e.g., FreeBSD, NetBSD, OpenBSD, Solaris, UnixWare. .PP Some .I /proc file items \- device number, inode number, and file size \- are unavailable in some dialects. Searching for files in a .I /proc file system may require that the full path name be specified. .PP No text (\fBtxt\fP) 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 .B mem descriptors. .PP .I 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. .PP .I 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 .I lsof FAQ (The \fBFAQ\fP section gives its location.) for details. .PP The AIX SMT file type is a fabrication. It's made up for file structures whose type (15) isn't defined in the AIX .I /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''. .PP The .BI +|\-f [cfgGn] option is not supported under /proc\-based Linux .IR lsof , because it doesn't read kernel structures from kernel memory. .SH ENVIRONMENT .I Lsof may access these environment variables. .TP \w'LSOFPERSDCPATH'u+4 LANG defines a language locale. See .IR setlocale (3) for the names of other variables that can be used in place of LANG \- e.g., LC_ALL, LC_TYPE, etc. .TP LSOFDEVCACHE defines the path to a device cache file. See the .B "DEVICE CACHE PATH FROM AN ENVIRONMENT VARIABLE" section for more information. .TP LSOFPERSDCPATH defines the middle component of a modified personal device cache file path. See the .B "MODIFIED PERSONAL DEVICE CACHE PATH" section for more information. .SH FAQ Frequently-asked questions and their answers (an FAQ) are available in the .I 00FAQ file of the .I lsof distribution. .PP That file is also available via anonymous ftp from .I lsof.itap.purdue.edu at .IR pub/tools/unix/lsof FAQ . The URL is: .IP ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/FAQ .SH FILES .TP \w'.lsof_hostname'u+4 .I /dev/kmem kernel virtual memory device .TP .I /dev/mem physical memory device .TP .I /dev/swap system paging device .TP .I .lsof_hostname .I lsof's device cache file (The suffix, .IR hostname , is the first component of the host's name returned by .IR gethostname (2) .) .SH AUTHORS .I Lsof was written by Victor A. Abell of Purdue University. Many others have contributed to .IR lsof . They're listed in the .I 00CREDITS file of the .I lsof distribution. .SH DISTRIBUTION The latest distribution of .I lsof is available via anonymous ftp from the host .IR lsof.itap.purdue.edu . You'll find the .I lsof distribution in the .I pub/tools/unix/lsof directory. .PP You can also use this URL: .IP ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof .PP .I Lsof is also mirrored elsewhere. When you access .I lsof.itap.purdue.edu and change to its .I pub/tools/unix/lsof directory, you'll be given a list of some mirror sites. The .I pub/tools/unix/lsof directory also contains a more complete list in its .I mirrors file. Use mirrors with caution \- not all mirrors always have the latest .I lsof revision. .PP Some pre\-compiled .I Lsof executables are available on .IR lsof.itap.purdue.edu , but their use is discouraged \- it's better that you build your own from the sources. If you feel you must use a pre\-compiled executable, please read the cautions that appear in the README files of the .I pub/tools/unix/lsof/binaries subdirectories and in the 00* files of the distribution. .PP More information on the .I lsof distribution can be found in its .I README.lsof_ file. If you intend to get the .I lsof distribution and build it, please read .I README.lsof_ and the other 00* files of the distribution before sending questions to the author. .SH SEE ALSO .PP Not all the following manual pages may exist in every UNIX dialect to which .I lsof has been ported. .PP access(2), awk(1), crash(1), fattach(3C), ff(1), fstat(8), fuser(1), gethostname(2), isprint(3), kill(1), localtime(3), lstat(2), modload(8), mount(8), netstat(1), ofiles(8L), perl(1), ps(1), readlink(2), setlocale(3), stat(2), strftime(3), time(2), uname(1). lsof-4.86+dfsg.orig/00XCONFIG0000444000175000017500000005512611650131455015646 0ustar nicholasnicholas Cross-configuring Lsof Introduction ============ Lsof cross-configuration is useful when the target dialect or target dialect version for which lsof is to be configured and built differs from the one on which the Configure operation is done. Marty Leisner suggested the method described here for lsof cross-configuration, and he supplied modifications to the Configure script for cross-configuring Linux lsof. Marty says: "I used this to successfully compile (lsof) on the same machine for (Linux) 2.0.30 and 2.1.42. (I normally don't bring up a 2.1.42 machine all the time). Also it (the 2.0.30 system) doesn't have much storage and compiles on it are slow. Set LSOF_VERS if it's not the (version of the) current system. (Actually, you should get the version out of include/linux/version.h.) Define LINUX_KERNEL to (the path) where the kernel sources are (located). (No longer necessary as of lsof revision 4.53.) This should work on most systems; they put a kernel in /usr/src/linux, which is the default. Now I can just do: LINUX_KERNEL=/some/other/kernel LSOF_VERS=2142 ./Configure linux Comments? Its 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.) I run multiple OSes at a time (not to mention multiple architectures. It's very pleasant to cross-build either operating systems or versions." So, the situation is that you have lsof sources on a UNIX dialect version, and you want to configure them to build lsof for some other version of the same dialect, or perhaps for some other UNIX dialect altogether. The Cross-Configure Method ========================== The lsof cross-configure method uses environment variables to tell the lsof Configure script about the target dialect. The environment variables may specify alternate locations for Configure to examine when it determines characteristics of the target, or they may specify the values Configure would discover when it examined the target's characteristics. Consult each environment variable description for the UNIX dialect in which you're interested to see how it affects the operation of the Configure script. The number and values of the variables differ by dialect. Each variable begins with an upper case version of the dialect's Configure abbreviation -- e.g., AIX for aix or aixgcc, LINUX for linux, UW for uw (UnixWare), etc. Of course, the UNIX dialect's version is probably different from that of the system on which you're doing the cross-configuration, so you will need to specify the new version, too. For example, to configure for FreeBSD 3.0 on a 2.1.7 system, where the standard 3.0 header files are in /3.0/usr/include and the 3.0 system sources are in /3.0/sys, do this: LSOF_VERS=300 LSOF_INCLUDE=/3.0/usr/include \ FREEBSD_SYS=/3.0/sys Configure -n freebsd General Environment Variables ============================= There are some environment variables whose names don't begin with an upper case rendering of a dialect abbreviation. Generally they apply to all dialects. AFS_VICE is for AFS configuration. It need be set only if lsof supports AFS on your dialect and you want to specify an alternate path to the VICE files. default: /usr/vice LSOF_AR is the path to and arguments for the library archive application that is used to build the lsof library, liblsof.a. When this value is placed in the library Makefile as the contents of the AR make string, it is followed by the path to the library and the relative paths of the library module default: ar cr LSOF_ARCH is the architecture type string for the system. Usually this is the output of `uname -m`. Consult the Configure script for details. The LSOF_ARCH value may have to be quoted if it contains spaces. default: auto-detection (e.g., from `uname -m`) LSOF_BLDCMT may be used to introduce a builder's comment into lsof's -v output. It defaults to the null string, causing no builder's comment to appear in -v output. default: none LSOF_CC is the path to the C compiler. You may need to specify it if your C compiler is in a non-standard place, not found by your path. If you specify a compiler different from the expected default, you may have to change the compile time flags by specifying new CFGF, CFGL, and DEBUG strings on the make command line. default: normally cc, but some dialects have other defaults and some have auto-detection. Check the dialect stanza in the lsof Configure script to see how LSOF_CC is set by default. LSOF_CCV is the C compiler version. You should specify it if you have specified a compiler path in LSOF_CC. default: the lsof Configure script knows how to find the version number of gcc and some other dialect-specific compilers. Check the dialect stanza in the lsof Configure script to see how lsof_CCV is set by default. LSOF_CFGF may be used to specify additional configuration values that will appear in the CFGF string of the Makefile. LSOF_CFGL may be used to specify additional library specifications that will appear in the CFGL string of the Makefile. LSOF_HOST may be used to specify a value in lsof's -v output other than the name of the host where lsof was built. A value of "none" inhibits host name display in -v output. default: the dialect's host name application -- e.g., hostname or uname -n LSOF_INCLUDE is the path to the standard header files. You may need to specify it if you want Configure to test header files in a tree different from /usr/include, and you want to compile lsof from the header files in that different tree. LSOF_LOGNAME may be used to specify a value in lsof's -v output other than the one in the LOGNAME environment variable for the login name of the person who built lsof. A value of "none" inhibits login name display in -v output. default: the LOGNAME environment variable LSOF_MAKE is the path to the make command. deafult: 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 connecting dialect sources to the top-level lsof directory. See 00PORTING for more information. default: ln -s LSOF_RANLIB may be used to specify an alternate command for the randomizing of the lsof library. default: ranlib for most dialects none for: IBM AIX; HP-UX; SCO OpenServer; Solaris and SCO|Caldera UnixWare LSOF_SYSINFO may be used to specify a value in lsof's -v output other than the standard system identification -- e.g., output from uname. A value of "none" inhibits system information display in -v output. default: the dialect's standard system identification application output -- e.g., uname, sysinfo LSOF_USER may be used to specify a value in lsof's -v output other than the one in the USER environment variable for the login name of the person who built lsof. A value of "none" inhibits login name display in -v output. default: the USER environment variable LSOF_VERS is the target dialect version number. It must be stated in the dialect's form -- e.g., FreeBSD 2.0.5 is given as 205, Solaris 7 as 70000, etc. The table, "Abbreviations, Variable Prefixes, and Version Numbers," in this file gives the form for LSOF_VERS for each dialect lsof supports. default: auto-detection (e.g., from `uname -r`) LSOF_VSTR is the version string from which LSOF_VERS is derived. Usually this is the output of `uname -r` or `uname -v`. Consult the Configure script for details. The LSOF_VSTR value may have to be quoted if it contains spaces. default: auto-detection (e.g., output from `hostname`, `uname -r`, or `uname -v) Make Strings ============ The CFGF, CFGL, and DEBUG strings can be specified on the make command line to change default values placed in the top-level and library Makefiles by Configure. For example, Configure usually defines the compiler optimization level to be -O, but you can change that with "DEBUG=-g" on the make command -- e.g., $ make DEBUG=-g lsof Similarly, the CFGF string contains miscellaneous compile-time options, and CFGL contains loader options. Consult the Makefiles generated by Configure for the values it defines by default for CFGF and CFGL. As an example, Configure might define CFGL to be "-L./lib -llsof -w" for NextStep 3.1; to remove "-w", use this make invocation: $ make CFGL="-L./lib -llsof" Abbreviations, Variable Prefixes, and Version Numbers ===================================================== The following table describes the relationship between Configure abbreviations, environment variable prefixes, and lsof UNIX dialect version numbers. The lsof UNIX dialect version number must be declared exactly in the listed form when supplied via the LSOF_VERS environment variable. Dialect Lsof Version Configure Variable Version Number for Abbreviation* Prefix Number LSOF_VERS aix AIX 3.2.5 3250 aixgcc 4.1.0 4100 4.1.4 4140 4.1.4 4150 4.2.0 4200 4.2.1 4210 4.3 4300 4.3.1 4310 4.3.2 4320 4.3.3 4330 5.0.x 5000 5.1.x 5100 5.2.x 5200 5.3.x 5300 darwin DARWIN 1.2* 120 1.3* 130 1.4* 140 5.[012] 500 5.[3-9] 530 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 2.1.x 2010 2.2.x 2020 3.x 30x0 4.x 40x0 4.1x 41x0 5.x 50x0 6.x 60x0 7.x 70x0 8.x 80x0 9.x 90x0 hpux HPUX 9.1 901 hpuxgcc HPUX 9.5 905 10.0 1000 10.10 1010 10.20 1020 11.00 1100 11.11 1111 linux LINUX 2.1.x 21xxx 2.2.x 22xxx 2.3.x 23xxx 2.4.x 24xxx 2.6.x 26xxx netbsd NETBSD 1.2 1002000 1.3 1003000 1.4 1004000 1.5 1005000 1.6 1006000 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 2.2 2020 2.3 2030 2.4 2040 2.5 2050 2.6 2060 2.7 2070 2.8 2080 2.9 2090 3.0 3000 3.1 3010 3.2 3020 3.3 3030 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 3.2v4.1 41 3.2v4.2 42 3.2v5.0.0 500 3.2v5.0.2 502 3.2v5.0.4 504 3.2v5.0.6 506 ou OU 8.0.0 80000 solaris SOLARIS 2.3 20300 solariscc SOLARIS 2.4 20400 2.5 20500 2.5.1 20501 2.6 20600 7 70000 8 80000 9 90000 10 100000 uw UW 7.0 70000 7.1.0 70100 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 ====================================== Here are the dialect-specific environment variables, listed alphabetically. The first part of any environment variable will be the dialect abbreviation, as specified to Configure, converted to upper case characters. See the `Configure -help` output for a listing of the abbreviations. AIX_ARCH specifies the AIX architecture when the AIX version is 5.0 or higher. A value of "" signifies POWER; "ia64", 64 bit x86 (Itanium). default: none (tested via `uname -a`) AIX_HAS_AFS specifies the state of AIX ADS support when the AIX version is 4.3.3 or lower. (Lsof doesn't support AFS above AIX 4.3.3.) A value of "" allows the Configure script to determine the AFS support state; "no", disables AFS support; and "yes", forces the enabling of AFS support. default: none (tested via presence of AFS files and the lsof AFSConfig shell script) AIX_KERNBITS specifies the kernel bit size, 32 or 64, of the Power architecture AIX 5.x kernel for which lsof was built. default: determined by the Configure script with a test program that uses macros. AIX_USHACK If this environment variable has a value of "Y" or "y", and if the aixgcc Configure abbreviation is selected, the AIX 4.1 and greater gcc user structure hack is activated; any other non-NULL value, it's not set; a NULL value, it's tested by compilation. default: none (tested by compilation) DARWIN_XNUDIR If this environment variable has a value, the value is used as the path to the Darwin XNU kernel source code. default: none (entry requested) DARWIN_XNU_HEADERS If this environment variable has a value, the value is used as the path to the Darwin XNU kernel header files. This path would match the DSTROOT environment variable used when a "make installhdrs" was executed from the Darwin XNU kernel source directory. 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. default: /386bsd FREEBSD_SYS specifies the path to the FreeBSD system source directory. default: /sys HPUX_BASE specifies the HP-UX lsof source code base, kmem or pstat, to be used. default: determined by testing for the /usr/include/sys/pstat subdirectory HPUX_BOOTFILE specifies the file in which lsof's Configure script can find kernel information. This specification may be useful for defining the path to a copy of /stand/vmunix that has been processed by pxdb or q4pxdb. default: /stand/vmunix HPUX_CCDIR1 specifies the first directory where Configure might find an HP-UX C compiler. This is ignored when LSOF_CC has been specified. default: /bin HPUX_CCDIR2 specifies the second directory where Configure might find an HP-UX C compiler. This is ignored when LSOF_CC has been specified. default: /usr/ccs/bin HPUX_HASONLINEJFS If this environment variable has a value of "Y" or "y", the HASONLINEJFS definition will be enabled in the Makefile CFLAGS. That will cause dnode1.c to use an alternate vx_inode.h header file in the hpux11 sub- directory of dialects/hpux/kmem. default: determined using nm and grep HPUX_IPC_S_PATCH If this environment variable has a value of "1", the ipc_s structure of the HP-UX 11 kernel is assumed to have an ipc_ipis member, but it is assumed the ipis_s structure lacks the ipis_msgsqueued member; "2", ipc_s has ipc_ipis, but ipis_s has ipis_msgsqueued; "n" or "N", ipc_s lacks ipc_ipis; any other non-NULL value is considered an error; a NULL value, HPUX_IPC_S_PATCH is determined by testing. default: determined with q4 and grep HPUX_KERNBITS specifies the number of bits (32 or 64) in the HP-UX 11 "basic kernel word. default: `getconf _SC_KERNEL_BITS` HPUX_LIBC1 specifies the first directory that might contain the HP-UX C library, libc.sl. default: /usr/lib HPUX_LIBC2 specifies the second directory that might contain the HP-UX C library, libc.sl. default: /lib HPUX_RNODE3 If this environment variable has a value of "1", the Configure script will define HASRNODE3 in the Makefile CFGF flags. If it is defined, but not "1", Configure will not define HASRNODE2. default: determined using `nm -x /stand/vmunix` and `grep r_fh3 /usr/include/nfs/rnode.h` HPUX_X25DIR specifies path to the HP-UX X25 directory that contains configuration header files. default: /etc/conf LINUX_CLIB specifies the definition of the Linux C library: default: "" (standard C library) others: -DGLIBCV=2 (glibc2) LINUX_CONF_CC specifies the location of the C compiler to use during the running of the Configure script: default: the value of the LSOF_CC variable, if defined, or cc 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. Default: assumed to be "Y" if exists LINUX_INCL specifies the path to the header file tree: default: /usr/include LINUX_LSEEK If this environment variable has a value of "Y" or "y", Configure uses Makefile.lseek in place of Makefile in order to enable use of the private lseek() function for 2.1.x kernels; any other non-NULL value, Makefile.lseek will isn't used; a NULL value, the alternate lseek() need is determined by compilation. default: determined by test program LINUX_VERSION_CODE specifies the value of the LINUX_VERSION_CODE in the same decimal form as found in the LINUX_VERSION_CODE #define of /usr/include/linux/version.h: default: the value of LINUX_VERSION_CODE in /usr/include/linux/version.h NETBSD_SYS specifies the path to the NetBSD system source directory. default: /usr/include NETBSD_UVM If this environment variable has a value of "Y" or "y", the NetBSD system uses the UVM virtual memory system; any other non-NULL value, it does not; a NULL value, it will be determined by the contents of /etc/mk.conf. default: tested by grep'ping /etc/mk.conf OPENBSD_SYS specifies the path to the OpenBSD system source directory. default: /sys OPENBSD_UVM If this environment variable has a value of "Y" or "y", the OpenBSD system uses the UVM virtual memory system; any other non-NULL value, it does not; a NULL value, it will be determined by examining /bsd. default: tested by grep'ping `nm /bsd` output OSR_CFGF The value of this environment variable is made the initial value for the compiler flags the lsof Configure script constructs for the Makefile CFGF macro. default: "" OSR_CFGL The value of this environment variable is made the initial value for the loader flags the lsof Configure script constructs for the Makefile CFGL macro. default: "" OSR_STATLSTAT If this environment variable has a value of "Y" or "y", HAS_STATLSTAT is defined in the Makefile's CFGL string; any other non-NULL value, it's not defined; a NULL value, it is determined with nm and grep. default: determined with nm and grep SOLARIS_23P101318 If this environment variable has a non-NULL value, the value is interpreted as the patch level of the Solaris 2.3 P101318 patch. default: pkginfo tested with grep SOLARIS_24P101945 If this environment variable has a non-NULL value, the value is interpreted as the patch level of the Solaris 2.4 P101945 patch. default: pkginfo tested with grep SOLARIS_24P102303 If this environment variable has a non-NULL value, the value is interpreted as the patch level of the Solaris 2.4 P102303 patch. default: pkginfo tested with grep SOLARIS_26PR_GWINDOWS If this environment variable has a value of "Y" or "y", the HASPR_GWINDOWS definition is set in the Solaris 2.6 and 7 Makefile's CFG string; any other non-NULL value, it's not set; a NULL value, it's tested by compilation. default: tested by compilation SOLARIS_26PR_LDT If this environment variable has a value of "Y" or "y", the HASPR_LDT definition is set in the Solaris 2.6 Makefile's CFGL string; any other non-NULL value, it's not set; a NULL value, it's tested by compilation. default: tested by compilation SOLARIS_CCDIR specifies the path to the Sun C compiler -- i.e., when `Configure solariscc` is used. This is ignored when LSOF_CC has been specified. default: /opt/SUNWspro/bin SOLARIS_INSTR specifies the Sun C compiler target instruction set when building lsof for a 64 bit kernel -- i.e., when the Configure abbreviation is "solariscc". Possible values include amd64 and sparcv9. This is ignored when the Configure abbreviation is "solaris" -- i.e., the compiler is gcc. default: tested with /bin/isainfo -k SOLARIS_KERNBITS specifies the number of bits in the Solaris 7, 8, 9 or 10 kernel: 32 or 64. default: tested with /bin/isainfo -kv SOLARIS_VSOCK If this environment variable has a value of "Y" or "y", the HAS_VSOCK definition is in the Solaris Makefile's CFGL string; any other non-NULL value, it's not set; a NULL value, it's tested by compilation. default: tested by compilation SOLARIS_VXFSINCL This environment variable defines the path to the header files of the VxFS 3.4 or greater version. If SOLARIS_VXFSINCL is not set, the default is used. default: VxFS < 4.0: /opt/VRTSvxfs/include VxFS 4.0 and above: /opt/VRTSfssdk//include SOLARIS_VXFSLIB This environment variable defines the path to the VxFS 3.4 or greater utility libraries, libvxfsutil.a (32 bit) and libvxfsutil64.a (64 bit). If SOLARIS_VXFSLIB is not set, the default is used. Note: end SOLARIS_VXFSLIB at the "/lib" component; do NOT put "/sparcv9" at its end. The lsof Configure script will add "/sparcv9" if it is required; hence, if Configure finds that "/sparcv9" is needed, your SOLARIS_VXFSLIB directory tree must have a sparcv9 subdirectory. default: `dirname $SOLARIS_VXFSINCL`/lib SUN_AFSAPATHDEF specifies the path to the AFS library modload file for either Solaris or SunOS. default: /usr/vice/etc/modload/libafs Verified with ls. Note: the SunOS support is no longer maintained. UW_HAS_NSC If this environment variable has a value of "Y" or "y", lsof will be configured for a UnixWare 7.1.1 or above NonStop Cluster (NSC) system. default: tested via /bin/node_self Vic Abell September 27, 2011 lsof-4.86+dfsg.orig/00CREDITS0000444000175000017500000002100411741060204015624 0ustar nicholasnicholas 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 Michael Antlitz 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 Albert Chin-A-Young Bernt Christandl Marc Christensen Hans Petter Christiansen Tom Christiansen Yves Christophe Richard Chycoski A. Channing Clark 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 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 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 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 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 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 Gary Millen Timothy Miller Davin Milun Yuliy Minchev Jim Mintha Mike Miscevic Arkadiusz Miskiewicz Janardhan Molumuri Nasser Momtaheni Laurent Montaron 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 Alex Podlecki Lutz Poetschulat, John Polstra Scott Presnell Mark Price Philippe-Andre Prindeville David Putz Tom Qin 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 Ingimar Robertson Sylvain Robitaille Larry Rogers Malgorzata Roos Larry Rosenman Stephan Rossi Kevin Ruderman Wolfgang Rupprecht Pavol Rusnak Conrad J. Sabatier Klaus Saggerer Chris Schanzle Igor Schein Horst Scheuermann Peter Schiffer Michael Schmitz Larry Schwimmer 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 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 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 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 Blair Zajac Karel Zak Donald Zoch Malcom Zung and Waldemar Zurowski If I have omitted a contributor's name, the fault is wholly mine, and I apologize for the error. Vic Abell April 10, 2012 lsof-4.86+dfsg.orig/00README0000444000175000017500000016237111741060455015511 0ustar nicholasnicholas Making and Installing lsof 4 ******************************************************************** | The latest release of lsof is always available via anonymous ftp | | from lsof.itap.purdue.edu. Look in pub/tools/unix/lsof. | ******************************************************************** Contents Pre-built Lsof Binaries Making Lsof Other Configure Script Options Environment Variables Security Run-time Warnings Device Access Warnings NFS Blocks Caches -- Name and Device Raw Sockets Other Compile-time Definitions The AFSConfig Script The Inventory Script The Customize Script Cautions Warranty License Bug Reports The 00FAQ File The lsof-l Mailing List Field Output Example Scripts Field Output C Library Testing Lsof Dialect Notes AFS AIX 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 SCO OpenServer SCO|Caldera UnixWare Solaris 2.x, 7, 8, 9 and 10 Ultrix (no longer available) Veritas VxFS and VxVM User-contributed Dialect Support Dialects No Longer Supported Installing Lsof Setuid-root Lsof Dialects Setgid Lsof Dialects Porting lsof 4 to a New UNIX Dialect Quick Start to Using lsof Cross-configuring Lsof Environment Variables Affecting the Configure Script ======================= Pre-built Lsof Binaries ======================= Avoid using pre-built lsof binaries if you can; build your own instead. I do not support lsof binaries built and packaged by third parties nor lsof binaries built from anything but the latest lsof revision. (See the Bug Reports section for more information on the details of lsof support.) One important reasone for those support restrictions is that when lsof is built its Configure script tunes lsof to the features available on the building system, often embodied in supporting header files and libraries. If the building system doesn't have support for a particular feature, lsof won't be built to support the feature on any system. The Veritas VxFS file system is a good example of a feature that requires build-time support. UNIX dialect version differences -- Solaris 8 versus 9, AIX 4.3.3 vesus 5.2, etc. -- can also render a pre-built lsof binary useless on a different version. So can kernel bit size. There are so many potential pitfalls to using an lsof binary improperly that I strongly recommend lsof be used only where it is built. =========== Making Lsof =========== $ cd $ ./Configure $ make (Consult the 00FAQ and 00XCONFIG files of the lsof distribution for information about using make command invocations and environment variables to override lsof default Makefile strings.) This lsof distribution can be used with many UNIX dialects. However, it must be configured specifically for each dialect. Configuration is done in three ways: 1) by changing definitions in the machine.h header file of the UNIX dialect of interest; 2) by defining environment variable values prior to calling Configure (see the 00XCONFIG file, the Environment Variabls and Environment Variables Affecting the Configure Script sections of this file); and 3) by running the Configure shell script found in the top level of the distribution directory. You may not need to change any machine.h definitions, but you might want to look at them anyway. Pay particular attention to the definitions that are discussed in the Security section of this file. Please read that section. The Configure script calls three other scripts in the lsof distribution: AFSConfig; Inventory; and Customize. The AFSConfig script is called for selected dialects (AIX, HP-UX, NEXTSTEP, and Solaris) to locate AFS header files and determine the AFS version. See The AFSConfig Script section of this file for more information. The Inventory script checks the completeness of the lsof distribution. Configure calls Inventory after it has accepted the dialect abbreviation, but before it configures the top-level directory for the dialect. See The Inventory Script section of this file for more information. Configure calls the Customize script after it has configured the top-level lsof directory for the declared dialect. Customize helps you modify some of the important compile-time definitions of machine.h. See the The Customize Script section. You should also think about where you will install lsof and its man page, and whom you will let execute lsof. Please read the Installing Lsof section of this file for information on installation considerations. Once you have inspected the machine.h file for the dialect for which you want to build lsof, and made any changes you need, run the Configure script, supplying it with the abbreviation for the dialect. (See the following table.) Configure selects the appropriate options for the dialect and runs the Mksrc shell script in the dialect sub-directory to construct the appropriate source files in the top-level distribution directory. Configure may also run the MkKernOpts script in the dialect sub-directory to propagate kernel build options to the dialect Makefile. This is done for only a few dialects -- e.g., DC/OSx, and Reliant UNIX. Configure creates a dialect-specific Makefile. You may want to inspect or edit this Makefile to make it conform to local conventions. If you want the Makefile to install lsof and its man page, you will have to create an appropriate install rule. Lsof may be configured using UNIX dialect abbreviations from the following table. Alternative abbreviations are indicated by a separating `|'. For example, for SCO OpenServer you can use either the ``osr'' or the ``sco'' abbreviation: $ Configure osr or $ Configure sco Abbreviations UNIX Dialect ------------- ------------ 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 hpuxgcc HP-UX 11.00, 11.11 and 11.23, using gcc, both /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 osr6 SCO Openserver 6.0.0, using the SCO C compiler sco SCO OpenServer Release 5.0.6, using the C compiler from the SCO developer's kit 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 If you have an earlier version of a dialect not named in the above list, lsof may still work on your system. I have no way of testing that myself. Try configuring for the named dialect -- e.g., if you're using Solaris 2.1, try configuring for Solaris 2.5.1. After you have configured lsof for your UNIX dialect and have selected options via the Customize script (See the The Customize Script section.) , use the make command to build lsof -- e.g., $ make Other Configure Script Options ============================== There are three other useful options to the Configure script besides the dialect abbreviation: -clean may be specified to remove all traces of a dialect configuration, including the Makefile, symbolic links, and library files. -h may be specified to obtain a list of -help Configure options, including dialect abbreviations. -n may be specified to stop the Configure script from calling the Customize and Inventory scripts. Caution: -n also suppresses the AFSConfig step. Environment Variables ===================== Lsof configuration, building, and execution may be affected by environment variable settings. See the Definitions That Affect Compilation section in the 00PORTING file, the General Environment Variables section in the 00XCONFIG file, the Dialect-Specific Environment Variables section in the 00XCONFIG file, and the Environment Variables Affecting the Configure Script section of this file for more information. Note in the General Environment Variables section of the 00XCONFIG file that there are five environment variables that can be used to pre-define values in lsof's -v output: LSOF_BLDCMT, LSOF_HOST, LSOF_LOGNAME, LSOF_SYSINFO, and LSOF_USER. Security ======== If the symbol HASSECURITY is defined, a security mode is enabled, and lsof will allow only the root user to list all open files. Non-root users may list only open files whose processes have the same user ID as the real user ID of the lsof process (the one that its user logged on with). However, if HASNOSOCKSECURITY is also defined, anyone may list anyone else's open socket files, provided their listing is enabled with the "-i" option. Lsof is distributed with the security mode disabled -- HASSECURITY is not defined. (When HASSECURITY is not defined, the definition of HASNOSOCKSECURITY has no meaning.) You can enable the security mode by defining HASSECURITY in the Makefile or in the machine.h header file for the specific dialect you're using -- e.g. dialects/aix/machine.h. The Customize script, run by Configure when it has finished its work, gives you the opportunity to define HASSECURITY and HASNOSOCKSECURITY. (See the The Customize Script section.) The lsof -h output indicates the state HASSECURITY and HASNOSOCKSECURITY had when lsof was built, reporting: "Only root can list all files;" if HASSECURITY was defined and HASNOSOCKSECURITY wasn't defined; "Only root can list all files, but anyone can list socket files." if HASSECURITY and HASNOSOCKSECURITY were both defined; "Anyone can list all files;" if HASSECURITY wasn't defined. (The definition of HASNOSOCKSECURITY doesn't matter when HASSECURITY isn't defined.) You should carefully consider the implications of using the default security mode. When lsof is compiled in the absence of the HASSECURITY definition, anyone who can execute lsof may be able to see the presence of all open files. This may allow the lsof user to observe open files -- e.g., log files used to track intrusions -- whose presence you would rather not disclose. As distributed, lsof writes a user-readable and user-writable device cache file in the home directory of the real user ID executing lsof. There are other options for constructing the device cache file path, and they each have security implications. The 00DCACHE file in the lsof distribution discusses device cache file path construction in great detail. It tells how to disable the various device cache file path options, or how to disable the entire device cache file feature by removing the HASDCACHE definition from the dialect's machine.h file. There is also information on the device cache file feature in the 00FAQ file. (The 00DCACHE and 00FAQ files are part of the lsof distribution package.) The Customize script, run by Configure after it has finished its work, gives you the opportunity to change the compile-time options related to the device cache file. (See The Customize Script section.) Since lsof may need setgid or setuid-root permission (See the Setgid Lsof Dialects and Setuid-root Lsof Dialects sections.), its security should always be viewed with skepticism. Lest the setgid and setuid-root permissions allow lsof to read kernel name list or memory files, declared with the -k and -m options, that the lsof user can't normally access, lsof uses access(2) to establish its real user's authority to read such files when it can't surrender its power before opening them. This change was added at the suggestion of Tim Ramsey. Lsof surrenders setgid permission on most dialects when it has gained access to the kernel's memory devices. There are exceptions to this rule, and some lsof implementations need to run setuid-root. (The Setgid Lsof Dialects and Setuid-root Lsof Dialects sections contains a list of lsof implementations and the permissions recommended in the distribution's Makefiles.) The surrendering of setgid permission is controlled by the WILLDROPGID definition in the dialect machine.h header files. In the end you must judge for yourself and your installation the risks that lsof presents and restrict access to it according to your circumstances and judgement. Run-time Warnings ================= Lsof can issue warning messages when it runs -- e.g., about the state of the device cache file, about an inability to access an NFS file system, etc. Issuance of warnings are enabled by default in the lsof distribution. Issuance or warnings may be disabled by default by defining WARNINGSTATE in the dialect's machine.h. The Customize script may also be used to change the default warning message issuance state. (See The Customize Script section.) The ``-w'' option description of the ``-h'' option (help) output will indicate the default warning issuance state. Whatever the state may be, it can be reversed with ``-w''. Device Access Warnings ====================== When lsof encounters a /dev (or /devices) directory, one of its sub-directories, or one of their files that it cannot access with opendir(3) or stat(2), it issues a warning message and continues. Lsof will be more likely to issue such a warning when it has been installed with setgid() permission; it won't have trouble if it has been installed with setuid(root) permission or is being run under the root login. The lsof caller can inhibit or enable the warning with the -w option, depending on the issuance state of run-time warnings. (See the Run-time Warnings section.) The warning messages do not appear when lsof obtains device information from a device cache file that it has built and believes to be current or when warning message issuance is disabled by default. (See the "Caches -- Name and Device" section for more information on the device cache file.) The lsof builder can inhibit the warning by disabling the definition of WARNDEVACCESS in the dialect's machine.h or disable all warnings by defining WARNINGSTATE. WARNDEVACCESS is defined by default for most dialects. However, some dialects have some device directory elements that are private -- e.g., HP-UX -- and it is more convenient for the lsof user if warning messages about them are inhibited. Output from lsof's -h option indicates the status of WARNDEVACCESS. If it was defined when lsof was compiled, this message will appear: /dev warnings = enabled If WARNDEVACCESS was not defined when lsof was compiled, this message will appear instead: /dev warnings = disabled The Customize script, run by Configure after it has finished its work, gives you the opportunity to change the WARNDEVACCESS definition. (See The Customize Script section.) NFS Blocks ========== Lsof is susceptible to NFS blocks when it tries to lstat() mounted file systems and when it does further processing -- lstat() and readlink() -- on its optional file and file system arguments. Lsof tries to avoid being stopped completely by NFS blocks by doing the lstat() and readlink() functions in a child process, which returns the function response via a pipe. The lsof parent limits the wait for data to arrive in the pipe with a SIGALRM, and, if the alarm trips, terminates the child process with a SIGINT and a SIGKILL. This is as reliable and portable a method for breaking NFS deadlocks as I have found, although it still fails under some combinations of NFS version, UNIX dialect, and NFS file system mount options. It generally succeeds when the "intr" or "soft" mount options are used; it generally fails when the "hard" mount option is used. When lsof cannot kill the child process, a second timeout causes it to stop waiting for the killed child to complete. While the second timeout allows lsof to complete, it may leave behind a hung child process. Unless warnings are inhibited by default or with the -w option, lsof reports the possible hung child. NFS block handling was updated with suggestions made by Andreas Stolcke. Andreas suggested using the alternate device numbers that appear in the mount tables of some dialects when it is not possible to stat(2) the mount points. The -b option was added to direct lsof to avoid the stat(2) and readlink(2) calls that might block on NFS mount points and always use the alternate device numbers. If warning message issuance is enabled and you don't want warning messages about what lsof is doing, use the -w option, too. The -O option directs lsof to avoid doing the potentially blocking operations in child processes. Instead, when -O is specified, lsof does them directly. While this consumes far less system overhead, it can cause lsof to hang, so I advise you to use -O sparingly. Caches -- Name and Device ========================== Robert Ehrlich suggested that lsof obtain path name components for open files from the kernel's name cache. Where possible, lsof dialect implementations do that. The -C option inhibits kernel name cache examination. Since AFS apparently does not use the kernel's name cache, where lsof supports AFS it is unable to identify AFS files with path name components. Robert also suggested that lsof cache the information it obtains via stat(2) for nodes in /dev (or /devices) to reduce subsequent running time. Lsof does that, too. In the default distribution the device cache file is stored in .lsof_hostname, mode 0600, in the home directory of the login of the user ID that executes lsof. The suffix, hostname, is the first component of the host's name returned by gethostname(2). If lsof is executed by a user ID whose home directory is NFS-mounted from several hosts, the user ID's home directory may collect several device cache files, one for each host from which it was executed. Lsof senses accidental or malicious damage to the device cache file with extensive integrity checks, including the use of a 16 bit CRC. It also tries to sense changes in /dev (or /devices) that indicate the device cache file is out of date. There are other options for forming the device cache file path. Methods the lsof builder can use to control and employ them are documented in the separate 00DCACHE file of the lsof distribution. Raw Sockets =========== On many UNIX systems raw sockets use a separate network control block structure. Display of files for applications using raw sockets -- ping, using ICMP, for example -- need special support for displaying their information. This support is so dialect-specific and information to provide it so difficult to find that not all dialect revisions of lsof handle raw sockets completely. Other Compile-time Definitions ============================== The machine.h and dlsof.h header files for each dialect contains definitions that affect the compilation of lsof. Check the Definitions That Affect Compilation section of the 00PORTING file of the lsof distribution for their descriptions. (Also see The Customize Script section.) The AFSConfig Script ==================== Lsof supports AFS on some combinations of UNIX dialect and AFS version. See the AFS section of this document for a list of supported combinations. When configuring for dialects where AFS is supported, the Configure script calls the AFSConfig script to determine the location of AFS header files and the AFS version. Configure will not call AFSConfig, even for the selected dialects, unless the file /usr/vice/etc/ThisCell exists. The AFS header file location is recorded in the AFSHeaders file; version, AFSVersion. Once these values have been recorded, Configure can be told to skip the calling of AFSConfig by specifying its (Configure's) -n option. The Inventory Script ==================== The lsof distribution contains a script, called Inventory, that checks the distribution for completeness. It uses the file 00MANIFEST in the distribution as a reference point. After the Configure script has accepted the dialect abbreviation, it normally calls the Inventory script to make sure the distribution is complete. After Inventory has run, it creates the file ".ck00MAN" in the top-level directory to record for itself the fact that the inventory has been check. Should Inventory be called again, it senses this file and asks the caller if another check is in order, or if the check should be skipped. The -n option may be supplied to Configure to make it bypass the calling of the Inventory script. (The option also causes Configure to avoid calling the Customize script.) The lsof power user may want to define (touch) the file ".neverInv". Configure avoids calling the Inventory script when ".neverInv" exists. The Customize Script ==================== Normally when the Configure script has finished its work, it calls another shell script in the lsof distribution called Customize. (You can tell Configure to bypass Customize with its -n option.) Customize leads you through the specification of these important compile-time definitions for the dialect's machine.h header file: HASDCACHE device cache file control HASENVDC device cache file environment variable name HASPERSDC personal device cache file path format HASPERSDCPATH name of environment variable that provides an additional component of the personal device cache file path HASSYSDC system-wide device cache file path HASKERNIDCK the build-time to run-time kernel identity check HASSECURITY the security option HASNOSOCKSECURITY the open socket listing option whe HASSECURITY is defined WARNDEVACCESS /dev (or /devices) warning message control WARNINGSTATE warning message issuance state The Customize script accompanies its prompting for entry of new values for these definitions with brief descriptions of each of them. More information on these definitions may be found in this file or in the 00DCACHE and 00FAQ files of the lsof distribution. You don't need to run Customize after Configure. You can run it later or you can edit machine.h directly. The -n option may be supplied to Configure to make it bypass the calling of the Customize script. (The option also causes Configure to avoid calling the Inventory script.) The lsof power user may want to define (touch) the file ".neverCust". Configure avoids calling the Customize script when ".neverCust" exists. Customize CAUTION: the Customize script works best when it is applied to a newly configured lsof source base -- i.e., the machine.h header file has not been previously modified by the Customize script. If you have previously configured lsof, and want to rerun the Customize script, I recommend you clean out the previous configuration and create a new one: $ Configure -clean $ Configure ... Customize in response to the Customize script prompts. Cautions ======== Lsof is a tool that is closely tied to the UNIX operating system version. It uses header files that describe kernel structures and reads kernel structures that typically change from OS version to OS version, and even within a version as vendor patches are applied. DON'T TRY TO USE AN LSOF BINARY, COMPILED FOR ONE UNIX OS VERSION, ON ANOTHER. VENDOR PATCHES INFLUENCE THE VERSION IDENTITY. On some UNIX dialects lsof versions may be even more restricted by architecture type. The bottom line is use lsof where you built it. If you intend to use a common lsof binary on multiple systems, make sure all systems run exactly the same OS version and have exactly the same patches. Warranty ======== Lsof is provided as-is without any warranty of any kind, either expressed or implied, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose. The entire risk as to the quality and performance of lsof is with you. Should lsof prove defective, you assume the cost of all necessary servicing, repair, or correction. License ======= Lsof has no license. Its use and distribution are subject to these terms and conditions, found in each 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. */ Bug Reports =========== Now that the obligatory disclaimer is out of the way, let me hasten to add that I accept lsof bug reports and try hard to respond to them. I will also consider and discuss requests for new features, ports to new dialects, or ports to new OS versions. PLEASE DON'T SEND BUG REPORTS ABOUT LSOF TO THE UNIX DIALECT OR DIALECT OPTION VENDOR. At worst such bug reports will confuse the vendor; at best, the vendor will forward the bug report to me. PLEASE DON'T SEND BUG REPORTS ABOUT LSOF BINARIES BUILT OR DISTRIBUTED BY SOMEONE ELSE, BECAUSE I CAN'T SUPPORT THEM. Before you send me a bug report, please do these things: * Make sure you try the latest lsof revision. + Download the latest revision from: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof + Verify the signatures of what you have downloaded; + While connected to lsof.itap.purdue.edu, check for patches: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/patches + If patches exist, install them in the latest revision you just downloaded. Then build the latest revision and see if it fixes your bug. * If you're having trouble compiling lsof with gcc, try the UNIX dialect vendor's compiler. I don't have access to gcc on all test systems, so my support for it is hit-and-miss, and so is my ability to respond to gcc compilation problem reports. * Check the lsof frequently asked questions file, 00FAQ, to see if there's a question and answer relevant to your problem. * Make sure you're running the lsof you think you are by checking the path to it with which(1). When in doubt, use an absolute path to lsof. Make sure that lsof binary has sufficient permissions to do what you ask, including internal permissions given it (e.g., restrictions on what files lsof may report for whom) during its build. When you send a bug report, make sure you include output from your running of lsof's Configure script. If you were able to compile a running lsof, please also include: * Output from which(1) that shows the absolute path to the lsof binary in question; * Output from running lsof with its -h and -v options at lsof's absolute path; * Output from "ls -l" directed to lsof's absolute path. If you weren't able to compile a running lsof, please send me: the compiler error output; identification of the lsof revision you're using (contents of the lsof version.c file); identification of your system (full uname output or output from whatever other tool identifies the system); and compiler identification (e.g., gcc -v output). Either set of output will help me understand how lsof was configured and what UNIX dialect and lsof revision is involved. Please send all bug reports, requests, etc. to me via e-mail at . Make sure "lsof" appears in the "Subject:" line so my e-mail filter won't classify your letter as Spam. The 00FAQ File ============== The lsof distribution contains an extensive frequently asked questions file on lsof features and problems. I recommend you consult it before sending me e-mail. Use your favorite editor or pager to search 00FAQ -- e.g., supplying as a search argument some fixed text from an lsof error message. The lsof-l Mailing List ======================= Information about lsof, including notices about the availability of new revisions, may be found in mailings of the lsof-l listserv. For more information about it, including instructions on how to subscribe, read the 00LSOF-L file of the lsof distribution. Field Output Example Scripts ============================ Example AWK and Perl 4 or 5 scripts for post-processing lsof field output are locate in the scripts sub-directory of the lsof distribution. The scripts sub-directory contains a 00README file with information about the scripts. Field Output C Library ====================== The lsof test suite (See "Testing Lsof."), checks basic lsof operations using field output. The test suite has its own library of C functions for common test program operations, including processing of field output. The library or selections of its functions could be adapted for use by C programs that want to process lsof field output. See the library in the file LTlib.c in the tests/ sub-directory Testing Lsof ============ Lsof has an automated test suite in the tests/ sub-directory that can be used to test some basic lsof features -- once lsof has been configured and made. Tests are arranged in three groups: basic tests that should run on all dialects; standard tests that should run on all dialects; and optional tests that may not run on all dialects or may need special resources to run. See 00TEST for more information.) CAUTION!!! Before you attempt to use the test suite make sure that the lsof you want to test can access the necessary kernel resources -- e.g., /dev/mem, /dev/kmem, /proc, etc. Usually you want to test the lsof you just built, so this is an important check. (See 00TEST.) To run the basic and standard tests, using the lsof in the parent directory of tests/, do this: $ cd tests $ make test or $ make std or $ make standard The basic and standard tests may be run as silently as possible, using the lsof in the parent directory of tests/, with: $ cd tests $ make auto This is the "automatic" test mode, designed for use by scripts that build lsof. The caller is expected to test the make exit code to determine if the tests succeeded. The caller should divert standard output and standard error to /dev/null to suppress make's error exit message. The optional tests may be run, using the lsof in the parent directory of tests/, with: $ cd tests $ 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 do, and how to run and possibly customize each test. It's possible to run the tests, using an lsof other than the one in the parent directory of /tests, too. See 00TEST for information about using the LT_LSOF_PATH environment variable to do that. ============= Dialect Notes ============= AFS === Lsof recognizes AFS files on the following combinations of UNIX 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) Lsof has not been tested under other combinations -- e.g. HP-UX 10.10 and AFS 3.4a -- and probably won't even compile there. Often when a UNIX dialect version or AFS version changes, the new header files come into conflict, causing compiler objections. AIX === Specify the aix Configure abbreviation for AIX 4.1.[45], 4.2[.1], 4.3[.123], 5L, and 5.[123]. Specify aixgcc on AIX above 4.1 to use the gcc compiler. (Gcc can't be used to compile lsof on AIX 4.1 and below because of kernel structure alignment differences between it and xlc.) Gcc results sometimes depend on the version of the gcc compiler that is used. Compilation of lsof with gcc on AIX 4.3[.123], 5L, and 5.[123] has been sparsely tested with varying degrees of success: it has been reported to succeed on AIX 4.3.3 and 32 bit Power AIX 5.1; to fail on ia64 AIX 5.1 and 64 bit Power AIX 5.1; and to succeed on 32 and 64 bit Power AIX 5.2. Lsof compilation with gcc hasn't been tested on AIX 5.3. At revision 4.61 and above lsof is configured and built to match the bit size of the kernel of Power architecture AIX 5.1 systems. Lsof binaries built for 32 and 64 bit kernels are not interchangeable. See 00FAQ for more information. The Configure script uses /usr/bin/oslevel to determine the AIX version for AIX less than 5 and ``uname -rv'' for AIX 5 and higher. If /usr/bin/oslevel isn't executable on AIX less than 5, the Configure script issues a warning message and uses ``uname -rv'' to determine the AIX version. When Configure must use ``uname -rv'' on AIX less than 5 to determine the AIX version, the result will lack a correct third component -- e.g., the `4' of ``4.1.4''. If your AIX less than 5 system lacks lacks an executable oslevel, I suggest you edit the Configure-produced Makefile and complete the _AIXV definition in the CFGF string. By default lsof avoids using the kernel's readx() function, causing it to be unable to report information on some text and library file references. The ``-X'' option allows the lsof user to ask for the information readx() supplies. Lsof avoids readx() to avoid the possibility of triggering a kernel problem, known as the Stale Segment ID kernel bug. Kevin Ruderman reported this bug to me. The bug shows up when the kernel's dir_search() function hangs, hanging the application process that called it so completely that the application process can neither be killed nor stopped. The hang is the consequence of another process (perhaps lsof) making legitimate use of the kernel's readx() function to access the kernel memory that dir_search() is examining. IBM has indicated they have no plans to fix the bug. A fuller discussion of this bug may be found in the 00FAQ file of the lsof distribution. There you will find a description of the Stale Segment ID bug, the APAR on it, and a discussion of the sequence of events that exposes it. I added the ``-X'' function so you can tell lsof to use readx(), but if you use ``-X'', you should be alert to its possibly serious side effects. Although readx() is normally disabled, its state is controlled with the HASXOPT, HASXOPT_ROOT, and HASXOPT_VALUE definitions in dialects/aix/machine.h, and you can change its default state by changing those definitions. You can also change HASXOPT_ROOT via the Customize script. You can also compile lsof with readx() use permanently enabled or disabled -- see the comments about the definitions in the dialects/aix/machine.h header file. You may want to permanently disable lsof's use of readx() if you plan to make lsof publicly executable. You can also restrict -X to processes whose real UID is root by defining HASXOPT_ROOT. I have never seen lsof cause the Stale Segment ID bug to occur and haven't had a report that it has, but I believe there is a possibility it could. AFS support for AIX was added with help help from Bob Cook and Jan Tax who provided test systems. Henry Grebler and David J. Wilson helped with lsof for AIX 4.2. Bill Pemberton provided an AIX 4.3 test system. Andrew Kephart and Tom Weaver provided AIX 4.3 technical assistance. Niklas Edmundsson did 4.3.1 testing. Doug Crabill provided an AIX 4.3.2 test system. Jeff W. Stewart provided an AIX 4.3.3 test system. The SMT file type for AIX 4.1.[45], 4.2[.1], and 4.3[.12] is my fabrication. See the 00FAQ file more information on it. Loc Le and Nasser Momtaheni of IBM provided test systems for AIX 5L and 5.1. Lsof for AIX 5L and 5.1 needs setuid-root permission to process the -X option on systems whose architecture type is ia64. Dale Talcott of Purdue provided AIX 5.1 and 5.2 test systems. Dale and John Jackson of Purdue provided an AIX 5.3 test system. Apple Darwin ============ The Apple Darwin port was provided by Allan Nathanson for version 1.2. Allan also arranged for access to a test system for maintenance and regression testing. Dale Talcott provided a test system, too. Allan supplied patches for updates to 1.4, 5.x, 6.x, 7.x and 8.x. BSDI BSD/OS =========== As of lsof revision 4.77 support for BSDI BSD/OS has been 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 ======= Bill Bormann of Purdue University provided access to several FreeBSD test systems. Ade Barkah, John Clear, Ralph Forsythe, Michael Haro, Kurt Jaeger, and William McVey have also provided FreeBSD test systems. The FreeBSD distribution header files are augmented by header files in the dialects/freebsd/include directory. David O'Brien maintains the lsof FreeBSD port package. HP-UX ===== Lsof has two HP-UX bases: /dev/kmem for HP-UX 11.0 and earlier; and PSTAT for HP-UX 11.11 and later. The lsof Configure script will pick the appropriate base. To use the CCITT x.25 socket support for HP-UX, you must have the x.25 header files in /etc/conf/x25 Pasi Kaara helped with the HP-UX port, especially with its CCITT x.25 socket support. Richard Allen provided HP-UX 10.x and 11.x test systems, as did Mark Bixby, and Elias Halldor Agustsson. Marc Winkler helped test the 10.20 port. Richard J. Rauenzahn provided a 64 bit HP-UX 11 test system and an HP-UX 11.11 development system. AFS support for HP-UX was added thanks to help from Chaskiel Moses Grundman, who provided a test system. The /dev/kmem-based HP-UX 11.00 support is extremely fragile. It depends on privately developed kernel structure definitions. (See .../dialects/hpux/hpux11 for the header files making the definitions.) Those header files and their definitions will not be updated by HP-UX 11.00 patches, making it likely that any patch changing a kernel structure critical to lsof will break lsof in some way. It's possible to build a 64 bit lsof for 64 bit HP-UX 11.00 with gcc, but you must have a gcc compiler capable of producing 64 bit executables. See the 00FAQ file for more information. The PSTAT-based lsof for HP-UX 11.11 and later is much more solid. I am indebted to the vision of HP for providing an lsof kernel API through the PSTAT implementation. Specifically I appreciate the help of HP staff members Carl Davidson, Louis Huemiller, Rich Rauenzahn, and Sailu Yallapragada that made PSTAT-based HP-UX lsof possible. IPv6 ==== Lsof has IPv6 support that has been tested for these UNIX dialects: AIX 4.3.x; Apple Darwin 5.[12] and 6.0; the INRIA and KAME FreeBSD IPv6 implementations; PSTAT-based HP-UX; /proc-based Linux; the INRIA and KAME NetBSD implementations; and Solaris 8 and 9. Lsof has IPv6 support that hasn't been tested for: OpenBSD (KAME); OpenUNIX 8; Tru64 Unix 5.[01]; and UnixWare 7.1.[34]. Please let me know if your UNIX dialect has IPv6 support and I'll see if it can be supported by lsof. Linux ===== Tim Korb, Steve Logue, Joseph J. Nuspl Jr., and Jonathan Sergent have provided Linux test systems. Michael Shields helped add and test automatic handling of ELF/COFF form names in /System.map, Marty Leisner and Keith Parks have helped test many lsof revisions. Marty has provided valuable suggestions, Linux hints, and code, too. The 00FAQ file gives some Linux tips, including information on coping with system map file problems. To determine the state of the Linux 2.1.x C library lseek() function, the lsof Configure script runs a test program that must have permission to read /dev/kmem. The test determines if the lseek() function properly handles kernel offsets, which appear to be negative because their high order bit is set. If the lseek() test reveals a faulty lseek(), Configure activates the use of a private lseek() function for kernel offset positioning. See the Linux problems section of the 00FAQ file of the lsof distribution for more information. NetBSD ====== Greg Earle and Paul Kranenburg have assisted with the NetBSD ports. 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. 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. Kenneth Stailey has provided OpenBSD testing and advice. John Dzubera (Zube) reports, "lsof 4.33 compiles and runs on OpenBSD 2.3 for the pmax architecture (decstation 3100)." I have not tested lsof on OpenBSD 3.8, but David Mazieres reports revision 4.76 worked on OpenBSD 3.8. Pyramid DC/OSx and Reliant UNIX =============================== As of lsof revision 4.52 support for all Pyramid dialects has been discontinued. Lsof revision 4.51 with Pyramid support may be obtained upon request. Send the request to abe@purdue.edu. These two UNIX dialects are very similar and share dialect-specific source files from the pyramid sub-directory. The Reliant Unix Pyramid C compiler issues warning messages that I haven't found a convenient way to suppress. You can ignore warning messages about casts and conversions that lose bits. The message "warning: undefining __STDC__" is intentionally caused by the lsof MkKernOpts configuration script to suppress warning messages about cast and conversion problems in standard system header files, such as and . Bruce Beare and Kevin Smith provided test systems. Caldera OpenUNIX ================ Larry Rosenman provided an OpenUNIX 8 test system. Matthew Thurmaier provided technical assistance, along with these people from Caldera: Jack Craig, Robert Lipe, and Bela Lubkin. Robert Lipe supplied changes to lsof for OpenUNIX 8.0.1. Those changes were also incorporated in UnixWare 7.1.3 when it became the release name for OpenUNIX 8.0.1. Support for lsof on OpenUNIX ended at lsof revision 4.74. The last lsof revision, 4.74, tested on OpenUNIX, may be found at the lsof "home" ftp site, lsof.itap.purdue.edu, in pub/tools/unix/lsof/OLD/src. SCO OpenServer ============== Dion Johnson, Bela Lubkin, and Nathan Peterson of SCO gave me copies of SCO OpenServer and the SCO OpenServer Development System 3.0 and provided technical advice for the lsof port. Hugh Dickins, Bela Lubkin, Craig B. Olofson, and Nathan Peterson provided version 5.0 and gave technical advice for porting lsof to it. Bela provided the 5.0.4 changes. D. Chris Daniels provided a 5.0.4 test system, Lee Penn provided one for 5.0.5, and John Dubois for 5.0.6. The header file was accidentally omitted from some SCO OpenServer Development System releases. The Configure script will sense its absence and substitute an equivalent from the BSD distribution. The BSD and the header file it includes are located in the dialects/os/include sub-directory tree. To compile lsof from its distribution sources you must have the TCP/IP and NSF headers in /usr/include. While those are optional OpenServer packages, I have access to no system that doesn't have them, so I'm unable to build lsof for such a configuration. However, it should be possible to modify the lsof Configure script and sources so lsof would compile and work without those optional packages. If you have an OpenServer system configured without the TCP/IP and NFS packages, and want to tackle the job of building lsof for it, contact me via e-mail at . I'll identify the Configure script, header file, and source file changes you will need to make. (Caution: this is not a simple task, or I would have already done it.) The optional osrgcc and scogcc Configure abbreviations construct Makefiles for compiling lsof with gcc. The UnixWare 7.1.4 sources are used for OpenServer Release 6.0.0. Hence there is a separate Configure abbreviation for it, "osr6". Richard of SCO provided a test system and technical assistance. SCO|Caldera UnixWare ============ D. Chris Daniels, John Hughes, Ken Laing, Andrew Merril, Lee Penn, and Matthew Thurmaier provided test systems. Bela Lubkin provided technical assistance. Larry Rosenman provided 7.1.[34] test systems. Solaris 2.x, 7, 8, 9 and 10 =========================== SEE THE CAUTIONS SECTION OF THIS DOCUMENT. The latest Solaris revision of lsof 4 might work under Solaris 2.[1-4] and 2.5[.1] and 7 but hasn't been tested there. I have no test systems for those Solaris versions. Lsof will compile with gcc and the Sun C compiler under Solaris. If you want to use the Sun compiler, use the solariscc Configure abbreviation. If you use a gcc version less than 2.8 on Solaris, make sure the gcc-specific includes have been updated for your version of Solaris -- i.e., run the gcc fixincludes script. Solaris 7, 8, 9 and 10 support for 64 bit kernels depends on a Sun WorkShop or Forte C compiler version that supports the "-xarch=v9" flag -- usually 5.0 or greater. Gcc versions 2.95 and above *may* be configured and built for 64 bit support, but it takes some extra work, the resulting compiler may be fragile, and the gcc developers discourage it. I've built 64 bit capable gcc compilers for Solaris 7, 8 and 9 from gcc versions 2.95 through 3.0.1 and produced working lsof executables with them. More information on 64 bit gcc for Solaris may be found in the 00FAQ file. Solaris 10 ZFS support is questionable, because Sun does not distribute the ZFS kernel structure definition header files. The lsof Configure script and source code use some risky work-arounds. ZFS file system support was made possible with help from Horst Scheuermann. Dave Curry and Steve Kirsch provided resources for Solaris 2.x ports. Casper Dik and Gerry Singleton consulted and provided valuable assistance. Henry Katz, Joseph Kowalski, Charles Stephens, Mike Sullivan, and Mike Tracy provided technical assistance. AFS support was added to Solaris lsof with help from Curt Freeland, Heidi Hornstein, Michael L. Lewis, Terry McCoy, Phillip Moore, and Sushila R. Subramanian. Casper Dik provided valuable assistance for the Solaris 8 support. Sun has graciously provided me access to BETA versions of Solaris 2.5, 2.6, 7, 8, and 9. John Dzubera provided Solaris 7 and 8 test systems. Mike Miscevic provided Solaris 10 test systems. Ultrix ====== As of lsof revision 4.52 support for Ultrix is no longer available, because I no longer have an Ultrix test system. Terry Friedrichsen, Dwight McKay, and Jeffrey Mogul helped me with this port. DECnet support was added to Ultrix lsof with the help of John Beacom, who kindly provided a test system. The Configure script decides that DECnet support is available if /usr/lib/libdnet.a and /usr/include/netdnet/dn.h exist and are readable. Veritas VxFS and VxVM ===================== Lsof supports some versions of Veritas VxFS and VxVM on some UNIX dialects. Consult the lsof Configure script for the specific dialect, and consult the lsof dialect-specific source files for the UNIX dialect of interest. Veritas support will usually be found in a source file named dnode[1-9].c. Since Veritas rarely has a version number that can be extracted with shell commands, lsof doesn't use it. Instead, when lsof supports Veritas, the Configure script will form compile-time definitions starting with HASVXFS. Check the lsof 00PORTING documentation file for more information. Lsof Veritas support requires that the supporting Veritas header files be installed -- e.g., in /usr/include/sys/fs. (The location will depend in the dialect's header file conventions.) Some information on lsof support for Veritas extensions may be found in the lsof 00DIST file. Chris Kordish and Andy Thomas have provided Solaris VxFS test systems. ================================ User-contributed Dialect Support ================================ There are some user-contributed dialect versions of lsof; more information on them can be found at: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/contrib Check the 00INDEX file there for details. ============================ Dialects No Longer Supported ============================ Because I don't have access to test systems, these UNIX dialects are no longer supported by lsof: CDC EP/IX /dev/kmem-based Linux MIPS RISC/os Motorola V/88 Pyramid DC/OSx Pyramid Reliant UNIX Sequent DYNIX SGI IRIX SunOS 4.x Ultrix UnixWare below 7.0 Remnants of the support lsof once provided for these dialects may be found in: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/OLD/dialects =============== Installing Lsof =============== The distributed Makefiles do not have actions that will install lsof. I've come to the conclusion there is no standard for installing lsof or its man page, so I no longer distribute make rules for installing them. You should adjust the Makefile for your local preferences. The Makefile does have an install rule that will cause lsof to compile by virtue of its dependency clause. Some Makefiles also have a dependency that causes the production of a man page that is ready to install. However, the actions of the install rule will not cause the lsof executable or its man page to be installed in any UNIX system-wide directory. Instead, after the compilation and optional man page production are completed, the install rule will produce a brief description of what actions you might add to the install rule. The description will suggest the possible modes, ownerships, permissions, and destinations your install rule might employ to install the lsof executable and man page. As you form your install rule, keep in mind that lsof usually needs some type of special permission to do its job. That may be permission 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 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. Don't overlook using ACLs -- e.g., on AIX or Solaris 8 -- to give lsof permission to access memory devices. ACLs, coupled to a separate group like kmem, can be safer than giving lsof setgid authorization to a commonly used system group. When lsof needs to read /proc file system entries, it must be installed with modes that make its effective user identifier root when it runs -- i.e., it must be setuid-root. If lsof must be installed setuid-root (only the AIX 5L, PSTAT-based HPUX, and /proc-based Linux, ports need such power.), then access to memory devices is automatic (or not needed in the case of /proc-based Linux). Your choice of permissions for lsof may also be affected by your desire to allow anyone to use it or your need to restrict its usage to specific individuals. You will have to be guided by local policy and convention in this case. The next two sections, Setgid Lsof Dialect Versions and Setuid-root Lsof Dialect Versions, list recommended install permissions. The system directory where you install the lsof executable is also open to choice. A traditional place for a tool like lsof is /usr/local/etc, but recent changes in directory structure organization suggest that somewhere in /opt may be more suitable. Bear one other factor in mind when choosing a location for the lsof executable -- it usually is a shared executable, requiring access to shared libraries. Thus, locations like /sbin or /usr/sbin are probably unsuitable. Once you've chosen a location for the executable you may find that the location for the man page follows -- e.g., if the executable goes in /usr/local/etc, then the man page goes in /usr/local/man. If the executable location doesn't imply a location for the man page, you'll have to let local custom guide you. Setuid-root Lsof Dialect Versions ================================= These dialect versions should be installed with setuid-root permission -- i.e., the lsof binary should be owned by root and its setuid execution bit (04000) should be set. AIX 5L and above for full use of the -X option Apple Darwin 8.x for Power Macintosh systems PSTAT-based HP-UX 11.11 and 11.23 /proc-based Linux (generally 2.1.72 and above) Setgid Lsof Dialect Versions ============================ These dialect versions should be installed with setgid permission, owned by the group that can read kernel memory devices such as /dev/drum, /dev/kmem, /dev/ksyms, /dev/mem, /dev/swap. ACLs may be another mechanism (e.g., under AIX or Solaris 8) you can use to 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 and [67].x /dev/kmem-based 11.00 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] Solaris 2.6, 8, 9 and 10 Ultrix 4.2 (no longer available) ==================================== Porting lsof 4 to a New UNIX Dialect ==================================== If you're brave enough to consider this, look at the 00PORTING file. Please contact me before you start. I might be able to help you or even do the port myself. Don't overlook the contrib/ directory in pub/tools/unix/lsof on my ftp server, lsof.itap.purdue.edu. It contains user-contributed ports of lsof to dialects I don't distribute, because I can't test new revisions of lsof on them. ========================= Quick Start to Using lsof ========================= For information on how to get started quickly using lsof, consult the 00QUICKSTART file of the lsof distribution. It cuts past the formal density of the lsof man page to provide quick examples of using lsof to solve common open file display problems. ====================== Cross-configuring Lsof ====================== Using environment variables it is possible to Configure (and possibly build) lsof for one UNIX dialect on a different one -- e.g., you are running Configure on a Linux 2.3 system and you want to Configure and build lsof for Linux 2.4. See the 00XCONFIG file of the lsof distribution for a discussion of how to do this. ==================================================== Environment Variables Affecting the Configure Script ==================================================== Configure script actions can be modified by introducing values to the script via environment variables. In many cases the environment variable values take the place of test operations the Configure script makes. For more information on environment variables that can affect Configure, consult the 00XCONFIG file of the lsof distribution. See the General Environment Variables sections for descriptions of ones that affect all dialects. Consult the Dialect-Specific Environment Variables section for ones that might affect the dialect you are trying to configure. Vic Abell April 10, 2012 lsof-4.86+dfsg.orig/regex.h0000444000175000017500000005542507370033446015760 0ustar nicholasnicholas/* * 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 . * * V. Abell * 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 must be included (by the caller) before . */ #if !defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE && defined VMS /* VMS doesn't have `size_t' in , even though POSIX says it should be there. */ # include #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 \ matches . If not set, then \ 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 #endif /* defined(USE_LIB_REGEX) */ lsof-4.86+dfsg.orig/main.c0000444000175000017500000011017711631741203015551 0ustar nicholasnicholas/* * 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"; static char *rcsid = "$Id: main.c,v 1.55 2011/09/07 19:13:49 abe Exp $"; #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[]; { int ad, c, i, n, rv, se1, se2, ss; char *cp; int err = 0; int ev = 0; 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; #if defined(HAS_STRFTIME) char *fmt = (char *)NULL; size_t fmtl; #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 all file descriptors above 2. * * Make sure stderr, stdout, and stdin are open descriptors. Open /dev/null * for ones that aren't. Be terse. * * Make sure umask allows lsof to define its own file permissions. */ for (i = 3, n = GET_MAX_FD(); i < n; i++) (void) close(i); while (((i = open("/dev/null", O_RDWR, 0)) >= 0) && (i < 2)) ; if (i < 0) Exit(1); 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); Exit(1); } Namechl = (size_t)(MAXPATHLEN + 1); /* * Create option mask. */ (void) snpf(options, sizeof(options), "?a%sbc:%sD:d:%sf:F:g:hi:%s%slL:%s%snNo:Op:Pr:%ss:S:tT:u:UvVwx:%s%s%s", #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(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, &rv)) != EOF) { if (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 = 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) */ #if defined(HASEOPT) case 'e': if (enter_efsys(GOv, ((GOp == '+') ? 1 : 0))) err = 1; break; #endif /* defined(HASEOPT) */ 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; 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(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(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'; 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': Ftask = 1; Selflags |= SELTASK; 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 'P': Fport = (GOp == '-') ? 0 : 1; break; case 'r': if (GOp == '+') ev = 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 != 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: 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 result: \"%s\"\n", Pn, (int)fmtl, cp); Exit(1); } if (util_strftime(fmtr, fmtl - 1, fmt) < 1) { (void) fprintf(stderr, "%s: illegal : \"%s\"\n", Pn, fmt); err = 1; } } #else /* !defined(HAS_STRFTIME) */ (void) fprintf(stderr, "%s: m 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; } } /* * 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 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); Exit(1); } 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; Selall = 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)); } Exit(1); } } DevDev = sb.st_dev; /* * Process the file arguments. */ if (GOx1 < argc) { if (ck_file_arg(GOx1, argc, argv, Ffilesys, 0, (struct stat *)NULL)) usage(1, 0, 0); } /* * 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(0); } #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); Exit(1); } } 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) */ /* * 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 (rc) { if (!n) break; else ev = 0; } #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; } } 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 = 0; for (str = Cmdl; str; str = str->next) { /* * Check command specifications. */ if (str->f) continue; rv = 1; 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 = 1; 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 = 1; 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 = 1; 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 = 1; 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 = 1; 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 = 1; 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 = 1; 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 = 1; 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 = 1; 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 = 1; 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 = 1; 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 = 1; 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 = 1; 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 = 1; 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 = 1; 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 = 1; 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); Exit(1); } (void) snpf(cp, l, "%s", f); return(cp); } lsof-4.86+dfsg.orig/lsof.h0000444000175000017500000006520211631741202015572 0ustar nicholasnicholas/* * 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.65 2011/09/07 19:13:49 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 #include # if defined(HASSETLOCALE) #include # endif /* defined(HASSETLOCALE) */ #include #include #include #include #include /* * 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) */ }; /* * 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_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_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 /* just in case -- because utmp.h * may need it */ #include "./regex.h" # if defined(EMPTY) #undef EMPTY # endif /* defined(EMPTY) */ # if defined(HASUTMPX) #include # else /* !defined(HASUTMPX) */ #include # 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_URL "ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/" #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_AUSX 3 /* Auspex LFS node */ #define N_AUTO 4 /* automount node */ #define N_BLK 5 /* block device node */ #define N_CACHE 6 /* cached file system node */ #define N_CDFS 7 /* CD-ROM node */ #define N_CFS 8 /* CFS node */ #define N_CHR 9 /* character device node */ #define N_COM 10 /* streams common device node */ #define N_CTFSADIR 11 /* Solaris CTFS adir node */ #define N_CTFSBUND 12 /* Solaris CTFS bundle node */ #define N_CTFSCDIR 13 /* Solaris CTFS cdir node */ #define N_CTFSCTL 14 /* Solaris CTFS ctl node */ #define N_CTFSEVT 15 /* Solaris CTFS events node */ #define N_CTFSLATE 16 /* Solaris CTFS latest node */ #define N_CTFSROOT 17 /* Solaris CTFS root node */ #define N_CTFSSTAT 18 /* Solaris CTFS status node */ #define N_CTFSSYM 19 /* Solaris CTFS symbolic node */ #define N_CTFSTDIR 20 /* Solaris CTFS type node */ #define N_CTFSTMPL 21 /* Solaris CTFS template node */ #define N_DEV 22 /* DEV FS node */ #define N_DOOR 23 /* DOOR node */ #define N_FD 24 /* FD node */ #define N_FIFO 25 /* FIFO node */ #define N_HSFS 26 /* High Sierra node */ #define N_KERN 27 /* BSD /kern node */ #define N_LOFS 28 /* loopback node */ #define N_MNT 29 /* mount file system device node */ #define N_MPC 30 /* multiplexed device node */ #define N_MVFS 31 /* multi-volume file system node (?) */ #define N_NFS 32 /* NFS node */ #define N_NFS4 33 /* NFS version 4 node */ #define N_NM 34 /* named file system node */ #define N_OBJF 35 /* objfs file system node */ #define N_PCFS 36 /* PC file system node */ #define N_PIPE 37 /* pipe device node */ #define N_PORT 38 /* port node */ #define N_PROC 39 /* /proc node */ #define N_PSEU 49 /* pseudofs node */ #define N_SAMFS 41 /* Solaris SAM-FS */ #define N_SANFS 42 /* AIX SANFS */ #define N_SDEV 43 /* Solaris sdev file system node */ #define N_SHARED 44 /* Solaris sharedfs */ #define N_SOCK 45 /* sock_vnodeops node */ #define N_SPEC 46 /* spec_vnodeops node */ #define N_STREAM 47 /* stream node */ #define N_TMP 48 /* tmpfs node */ #define N_UFS 49 /* UNIX file system node */ #define N_UNKN 50 /* unknown node type */ #define N_VXFS 51 /* Veritas file system node */ #define N_XFS 52 /* XFS node */ #define N_ZFS 53 /* ZFS node */ # 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 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 TIDTTL "TID" extern int TidColW; #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 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 */ /* * 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; 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 Fport; # if !defined(HASNORPC_H) extern int FportMap; # endif /* !defined(HASNORPC_H) */ extern int Fpgid; extern int Fppid; 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 char *InodeFmt_d; extern char *InodeFmt_x; 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 */ 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]; short 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 */ int pid; /* process ID */ # if defined(HASTASKS) int tid; /* task ID */ # 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 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 struct l_dev **Sdev; extern int Selall; extern int Selflags; 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 TaskPrtFl; 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 */ lsof-4.86+dfsg.orig/dialects/0000755000175000017500000000000011743250563016254 5ustar nicholasnicholaslsof-4.86+dfsg.orig/dialects/du/0000755000175000017500000000000011741064217016661 5ustar nicholasnicholaslsof-4.86+dfsg.orig/dialects/du/dstore.c0000444000175000017500000000777007144334763020346 0ustar nicholasnicholas/* * dstore.c - DEC OSF/1, Digital UNIX, Tru64 UNIX global storage for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dstore.c,v 1.10 2000/08/09 20:06:50 abe Exp $"; #endif #include "lsof.h" int CloneMaj; /* clone major device number */ /* * Drive_Nl -- table to drive the building of Nl[] via build_Nl() * (See lsof.h and misc.c.) */ struct drive_Nl Drive_Nl[] = { { "cldev", "clonedev" }, { "fids", "fids" }, { "msfsubc", "msfs_ubcops" }, #if DUV>=50100 { "advfsvfs", "msfs_vfsops" }, { "cdfsvfs", "cdfs_vfsops" }, { "dvdfsvfs", "dvdfs_vfsops" }, { "fdfsvfs", "fdfs_vfsops" }, { "fsfsrvp", "fdfs_root_directory" }, { "nchsz", "nchsz" }, { "ncpus", "ncpus" }, { "nfsvfs", "nfs_vfsops" }, { "nfs3vfs", "nfs3_vfsops" }, { "procptr", "processor_ptr" }, { "ufsvfs", "ufs_vfsops" }, #else /* DUV<50100 */ { X_NCACHE, "namecache" }, { X_NCSIZE, "nchsize" }, #endif /* DUV>=50100 */ { "vnmaxp", "vn_maxprivate" }, #if DUV<30000 { "proc", "proc" }, { "nproc", "nproc" }, #else /* DUV>=30000 */ { "npid", "npid" }, { "pidt", "pidtab" }, #endif /* DUV<30000 */ { "", "", }, { NULL, NULL, } }; struct file *Fileptr; /* for process_file() in lib/prfp.c */ int HaveCloneMaj = 0; /* status of CloneMaj */ int Kd = -1; struct l_vfs *Lvfs = NULL; # if DUV>=30000 KA_T *Pa = NULL; /* kernel proc structure addresses */ # endif /* DUV>=30000 */ #if defined(HASFSTRUCT) /* * Pff_tab[] - table for printing file flags */ struct pff_tab Pff_tab[] = { { (long)FREAD, FF_READ }, { (long)FWRITE, FF_WRITE }, { (long)FNONBLOCK, FF_NBLOCK }, { (long)FNDELAY, FF_NDELAY }, { (long)FAPPEND, FF_APPEND }, { (long)FASYNC, FF_ASYNC }, { (long)FMARK, FF_MARK }, { (long)FDEFER, FF_DEFER }, { (long)FSHLOCK, FF_SHLOCK }, { (long)FEXLOCK, FF_EXLOCK }, # if defined(FKERNEL) { (long)FKERNEL, FF_KERNEL }, # endif /* defined(FKERNEL) */ # if defined(FKERNEL) { (long)FVTEXT, FF_VTEXT }, # endif /* defined(FVTEXT) */ # if defined(FSYNC) { (long)FSYNC, FF_SYNC }, # endif /* defined(FSYNC) */ # if defined(FDSYNC) { (long)FDSYNC, FF_DSYNC }, # endif /* defined(FDSYNC) */ # if defined(FRSYNC) { (long)FRSYNC, FF_RSYNC }, # endif /* defined(FRSYNC) */ { (long)0, NULL } }; /* * Pof_tab[] - table for print process open file flags */ struct pff_tab Pof_tab[] = { # if defined(UF_EXCLOSE) { (long)UF_EXCLOSE, POF_CLOEXEC }, # else /* !defined(UF_EXCLOSE) */ { (long)1, POF_CLOEXEC }, # endif /* defined(UF_EXCLOSE) */ # if defined(UF_MAPPED) { (long)UF_MAPPED, POF_MAPPED }, # endif /* defined(UF_MAPPED) */ # if defined(UF_RESERVED_WAIT) { (long)UF_RESERVED_WAIT, POF_RSVWT }, # endif /* defined(UF_RESERVED_WAIT) */ { (long)0, NULL } }; #endif /* defined(HASFSTRUCT) */ struct proc *Ps = NULL; /* local proc structures */ int Psn = 0; /* entries in Paddr[] and Ps[] */ int Vnmxp; /* vnode's max private area length */ lsof-4.86+dfsg.orig/dialects/du/ddev.c0000444000175000017500000004406510277140667017765 0ustar nicholasnicholas/* * ddev.c - DEC OSF/1, Digital UNIX, Tru64 UNIX device support functions for * lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: ddev.c,v 1.17 2005/08/12 15:35:14 abe Exp $"; #endif #include "lsof.h" /* * Local static values */ #if defined(USELOCALREADDIR) static struct stat Dirsb; #endif /* defined(USELOCALREADDIR) */ /* * Local definitions */ #define LIKE_BLK_SPEC "like block special" #define LIKE_CHR_SPEC "like character special" /* * Local function prototypes */ _PROTOTYPE(static int rmdupdev,(struct l_dev ***dp, int n, char *nm)); #if defined(HASDCACHE) /* * clr_sect() - clear cached clone and pseudo sections */ void clr_sect() { struct clone *c, *c1; if (Clone) { for (c = Clone; c; c = c1) { c1 = c->next; (void) free((FREE_P *)c); } Clone = (struct clone *)NULL; } } #endif /* defined(HASDCACHE) */ /* * printdevname() - print block and character device names */ int printdevname(dev, rdev, f, nty) dev_t *dev; /* device */ dev_t *rdev; /* raw device */ int f; /* 1 = follow with '\n' */ int nty; /* node type: N_BLK or N_CHR */ { struct clone *c; struct l_dev *dp; readdev(0); /* * Search for clone. */ #if defined(HASDCACHE) printdevname_again: #endif /* defined(HASDCACHE) */ if ((nty == N_CHR) && Clone && HAVECLONEMAJ && (*dev == DevDev) && (GET_MAJ_DEV(*rdev) == CLONEMAJ)) { for (c = Clone; c; c = c->next) { if (Devtp[c->dx].rdev == *rdev) { #if defined(HASDCACHE) if (DCunsafe && !Devtp[c->dx].v && !vfy_dev(&Devtp[c->dx])) goto printdevname_again; #endif /* defined(HASDCACHE) */ safestrprt(Devtp[c->dx].name, stdout, f); return(1); } } } /* * Search device table for a full match. */ #if defined(HASBLKDEV) if (nty == N_BLK) dp = lkupbdev(dev, rdev, 1, 0); else #endif /* defined(HASBLKDEV) */ dp = lkupdev(dev, rdev, 1, 0); if (dp) { safestrprt(dp->name, stdout, f); return(1); } /* * Search device table for a match without inode number and dev. */ #if defined(HASBLKDEV) if (nty == N_BLK) dp = lkupbdev(&DevDev, rdev, 0, 0); else #endif /* defined(HASBLKDEV) */ dp = lkupdev(&DevDev, rdev, 0, 0); if (dp) { /* * A raw device match was found. Record it as a name column addition. */ char *cp, *ttl; int len; ttl = (nty == N_BLK) ? LIKE_BLK_SPEC : LIKE_CHR_SPEC; len = (int)(1 + strlen(ttl) + 1 + strlen(dp->name) + 1); if (!(cp = (char *)malloc((MALLOC_S)(len + 1)))) { (void) fprintf(stderr, "%s: no nma space for: (%s %s)\n", Pn, ttl, dp->name); Exit(1); } (void) snpf(cp, len + 1, "(%s %s)", ttl, dp->name); (void) add_nma(cp, len); (void) free((FREE_P *)cp); return(0); } #if defined(HASDCACHE) /* * If the device cache is "unsafe" and we haven't found any match, reload * the device cache. */ if (DCunsafe) { (void) rereaddev(); goto printdevname_again; } #endif /* defined(HASDCACHE) */ return(0); } /* * readdev() - read names, modes and device types of everything in /dev */ void readdev(skip) int skip; /* skip device cache read if 1 */ { #if defined(HASDCACHE) int dcrd; #endif /* defined(HASDCACHE) */ struct clone *c; DIR *dfp; struct DIRTYPE *dp; char *fp = (char *)NULL; int i = 0; #if defined(HASBLKDEV) int j = 0; #endif /* defined(HASBLKDEV) */ MALLOC_S nl; char *path = (char *)NULL; MALLOC_S pl; struct stat sb; if (Sdev) return; #if defined(HASDCACHE) /* * Read device cache, as directed. */ if (!skip) { if (DCstate == 2 || DCstate == 3) { if ((dcrd = read_dcache()) == 0) return; } } else dcrd = 1; #endif /* defined(HASDCACHE) */ Dstk = (char **)NULL; Dstkn = Dstkx = 0; (void) stkdir("/dev"); /* * Unstack the next /dev or /dev/ directory. */ while (--Dstkx >= 0) { if (!(dfp = OpenDir(Dstk[Dstkx]))) { #if defined(WARNDEVACCESS) if (!Fwarn) { (void) fprintf(stderr, "%s: WARNING: can't open: ", Pn); safestrprt(Dstk[Dstkx], stderr, 1); } #endif /* defined(WARNDEVACCESS) */ (void) free((FREE_P *)Dstk[Dstkx]); Dstk[Dstkx] = (char *)NULL; continue; } if (path) { (void) free((FREE_P *)path); path = (char *)NULL; } if (!(path = mkstrcat(Dstk[Dstkx], -1, "/", 1, (char *)NULL, -1, &pl))) { (void) fprintf(stderr, "%s: no space for: ", Pn); safestrprt(Dstk[Dstkx], stderr, 1); Exit(1); } (void) free((FREE_P *)Dstk[Dstkx]); Dstk[Dstkx] = (char *)NULL; /* * Scan the directory. */ for (dp = ReadDir(dfp); dp; dp = ReadDir(dfp)) { if (dp->d_ino == 0 || dp->d_name[0] == '.') continue; /* * Form the full path name and get its status. */ if (fp) { (void) free((FREE_P *)fp); fp = (char *)NULL; } if (!(fp = mkstrcat(path, (int)pl, dp->d_name, dp->d_namlen, (char *)NULL, -1, (MALLOC_S *)NULL))) { (void) fprintf(stderr, "%s: no space for: ", Pn); safestrprt(path, stderr, 0); safestrprt(dp->d_name, stderr, 1); Exit(1); } #if defined(USE_STAT) if (stat(fp, &sb) != 0) #else /* !defined(USE_STAT) */ if (lstat(fp, &sb) != 0) #endif /* defined(USE_STAT) */ { if (errno == ENOENT) /* symbolic link to nowhere? */ continue; #if defined(WARNDEVACCESS) if (!Fwarn) { int errno_save = errno; (void) fprintf(stderr, "%s: can't stat ", Pn); safestrprt(fp, stderr, 0); (void) fprintf(stderr, ": %s\n", strerror(errno_save)); } #endif /* defined(WARNDEVACCESS) */ continue; } /* * If it's a subdirectory, stack its name for later processing. */ if ((sb.st_mode & S_IFMT) == S_IFDIR) { (void) stkdir(fp); continue; } if ((sb.st_mode & S_IFMT) == S_IFCHR) { /* * Save character device information in Devtp[]. */ if (i >= Ndev) { Ndev += DEVINCR; if (!Devtp) Devtp = (struct l_dev *)malloc( (MALLOC_S)(sizeof(struct l_dev)*Ndev)); else Devtp = (struct l_dev *)realloc( (MALLOC_P *)Devtp, (MALLOC_S)(sizeof(struct l_dev)*Ndev)); if (!Devtp) { (void) fprintf(stderr, "%s: no space for character device\n", Pn); Exit(1); } } Devtp[i].inode = (INODETYPE)sb.st_ino; if (!(Devtp[i].name = mkstrcpy(fp, (MALLOC_S *)NULL))) { (void) fprintf(stderr, "%s: no space for: ", Pn); safestrprt(fp, stderr, 1); Exit(1); } Devtp[i].rdev = sb.st_rdev; Devtp[i].v = 0; /* * Save clone device location. */ if (HAVECLONEMAJ && GET_MAJ_DEV(Devtp[i].rdev) == CLONEMAJ) { if (!(c = (struct clone *)malloc(sizeof(struct clone)))) { (void) fprintf(stderr, "%s: no space for clone device: ", Pn); safestrprt(fp, stderr, 1); Exit(1); } c->dx = i; c->next = Clone; Clone = c; } i++; } #if defined(HASBLKDEV) if ((sb.st_mode & S_IFMT) == S_IFBLK) { /* * Save block device information in BDevtp[]. */ if (j >= BNdev) { BNdev += DEVINCR; if (!BDevtp) BDevtp = (struct l_dev *)malloc( (MALLOC_S)(sizeof(struct l_dev)*BNdev)); else BDevtp = (struct l_dev *)realloc( (MALLOC_P *)BDevtp, (MALLOC_S)(sizeof(struct l_dev)*BNdev)); if (!BDevtp) { (void) fprintf(stderr, "%s: no space for block device\n", Pn); Exit(1); } } BDevtp[j].inode = (INODETYPE)sb.st_ino; BDevtp[j].name = fp; fp = (char *)NULL; BDevtp[j].rdev = sb.st_rdev; BDevtp[j].v = 0; j++; } #endif /* defined(HASBLKDEV) */ } (void) CloseDir(dfp); } /* * Free any allocated space. */ if (Dstk) { (void) free((FREE_P *)Dstk); Dstk = (char **)NULL; Dstkn = Dstkx = 0; } if (fp) (void) free((FREE_P *)fp); if (path) (void) free((FREE_P *)path); /* * Reduce the BDevtp[] (optional) and Devtp[] tables to their minimum * sizes; allocate and build sort pointer lists; and sort the tables by * device number. */ #if defined(HASBLKDEV) if (BNdev) { if (BNdev > j) { BNdev = j; BDevtp = (struct l_dev *)realloc((MALLOC_P *)BDevtp, (MALLOC_S)(sizeof(struct l_dev) * BNdev)); } if (!(BSdev = (struct l_dev **)malloc( (MALLOC_S)(sizeof(struct l_dev *) * BNdev)))) { (void) fprintf(stderr, "%s: no space for block device sort pointers\n", Pn); Exit(1); } for (j = 0; j < BNdev; j++) { BSdev[j] = &BDevtp[j]; } (void) qsort((QSORT_P *)BSdev, (size_t)BNdev, (size_t)sizeof(struct l_dev *), compdev); BNdev = rmdupdev(&BSdev, BNdev, "block"); } # if !defined(NOWARNBLKDEV) else { if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: no block devices found\n", Pn); } # endif /* !defined(NOWARNBLKDEV) */ #endif /* defined(HASBLKDEV) */ if (Ndev) { if (Ndev > i) { Ndev = i; Devtp = (struct l_dev *)realloc((MALLOC_P *)Devtp, (MALLOC_S)(sizeof(struct l_dev) * Ndev)); } if (!(Sdev = (struct l_dev **)malloc( (MALLOC_S)(sizeof(struct l_dev *) * Ndev)))) { (void) fprintf(stderr, "%s: no space for character device sort pointers\n", Pn); Exit(1); } for (i = 0; i < Ndev; i++) { Sdev[i] = &Devtp[i]; } (void) qsort((QSORT_P *)Sdev, (size_t)Ndev, (size_t)sizeof(struct l_dev *), compdev); Ndev = rmdupdev(&Sdev, Ndev, "char"); } else { (void) fprintf(stderr, "%s: no character devices found\n", Pn); Exit(1); } #if defined(HASDCACHE) /* * Write device cache file, as required. */ if (DCstate == 1 || (DCstate == 3 && dcrd)) write_dcache(); #endif /* defined(HASDCACHE) */ } #if defined(USELOCALREADDIR) /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * This is a hacked version of NetBSD's readdir() function written to work * around an apparent bug in the Digital UNIX 3.0 getdirentries() system call * and/or their "/dev/fd" filesystem. The problem is that when applied to * "/dev/fs", getdirentries() returns the wrong size, which can cause readdir() * to run off the end of it's internal buffer and return bogus file names. * * The changes from the original NetBSD file are: * * - uses of the field dd_flags in the DIR structure have been removed since * Digital UNIX doesn't have this field (it seems to be mostly used for * dealing with whiteout's in NetBSD's union filesystem). * * - uses of the dd_len field were replaced with dd_bufsiz, since this appears * to be where the Digital UNIX opendir() call stashes the size of the buffer * it mallocs. Why does Digital UNIX have both? No idea -- as far as I * could tell dd_len was always 0. * * - code within "#ifdef BROKEN_GETDIRENTRIES ... #endif" has been added to * workaround the bug. Note: this code uses the (apparently) unused field, * dd_len, in the Digital UNIX DIR structure. This is pretty nasty, but * then, this whole routine *is* just a hack to get around a (hopefully) * temporary problem in Digital UNIX. * * This routine has only been tested on a couple of Digital UNIX 3.0 systems. * I make no guarantees that it will work for you...! * * Duncan McEwan (duncan@comp.vuw.ac.nz) */ /* * Additional changes by Vic Abell : * * - The BROKEN_GETDIRENTRIES symbol was deleted. Use of this function * is controlled in the lsof distribution by the HASLOCALREADDIR * definition. */ /* * CloseDir() - close directory */ int CloseDir(dirp) register DIR *dirp; { return(closedir(dirp)); } /* * OpenDir() - open directory */ DIR * OpenDir(dir) char *dir; { DIR *dirp; if ((dirp = opendir(dir))) { /* * Get a stat(2) buffer for the directory. * * Warn if the stat(2) buffer operation fails, close the directory, * and respond that the open failed. */ if (statsafely(dir, &Dirsb)) { int en = errno; if (!Fwarn) { (void) fprintf(stderr, "%s: WARNING: can't statsafely(", Pn); safestrprt(dir, stderr, 0); (void) fprintf(stderr, "): %s\n", strerror(en)); } (void) CloseDir(dirp); dirp = (DIR *)NULL; errno = en; } } return(dirp); } /* * ReadDir() - read next directory entry */ extern struct DIRTYPE * ReadDir(dirp) register DIR *dirp; { register struct DIRTYPE *dp; /* * Loop through the directory. */ for (;;) { if (dirp->dd_loc >= dirp->dd_size) { dirp->dd_loc = 0; } if (dirp->dd_loc == 0) { dirp->dd_size = getdirentries(dirp->dd_fd, dirp->dd_buf, dirp->dd_bufsiz, &dirp->dd_seek); if (dirp->dd_size <= 0) return((struct DIRTYPE *)NULL); /* * If the size returned by getdirentries() exceeds what it * should be (as determined by a stat(2) of the directory), * set it to the proper value. This is an adjustment for an * apparent bug in the Digital UNIX 3.[02] getdirentries() * function, when applied to a /dev/fd mount point. * * This check was conceived by Duncan McEwan and modified by * Vic Abell. */ if (dirp->dd_size > (long)Dirsb.st_size) dirp->dd_size = (long)Dirsb.st_size; Dirsb.st_size -= (off_t)dirp->dd_size; } dp = (struct DIRTYPE *)(dirp->dd_buf + dirp->dd_loc); if ((long)dp & 03) /* bogus pointer check */ return((struct DIRTYPE *)NULL); if (dp->d_reclen <= 0 || dp->d_reclen > dirp->dd_bufsiz + 1 - dirp->dd_loc) return((struct DIRTYPE *)NULL); dirp->dd_loc += dp->d_reclen; if (dp->d_ino == 0) continue; return (dp); } } #endif /* defined(USELOCALREADDIR) */ #if defined(HASDCACHE) /* * rereaddev() - reread device names, modes and types */ void rereaddev() { (void) clr_devtab(); # if defined(DCACHE_CLR) (void) DCACHE_CLR(); # endif /* defined(DCACHE_CLR) */ readdev(1); DCunsafe = 0; } #endif /* defined(HASDCACHE) */ /* * rmdupdev() - remove duplicate (major/minor/inode) devices */ static int rmdupdev(dp, n, nm) struct l_dev ***dp; /* device table pointers address */ int n; /* number of pointers */ char *nm; /* device table name for error message */ { struct clone *c, *cp; int i, j, k; struct l_dev **p; for (i = j = 0, p = *dp; i < n ;) { for (k = i + 1; k < n; k++) { if (p[i]->rdev != p[k]->rdev || p[i]->inode != p[k]->inode) break; /* * See if we're deleting a duplicate clone device. If so, * delete its clone table entry. */ for (c = Clone, cp = (struct clone *)NULL; c; cp = c, c = c->next) { if (&Devtp[c->dx] != p[k]) continue; if (!cp) Clone = c->next; else cp->next = c->next; (void) free((FREE_P *)c); break; } } if (i != j) p[j] = p[i]; j++; i = k; } if (n == j) return(n); if (!(*dp = (struct l_dev **)realloc((MALLOC_P *)*dp, (MALLOC_S)(j * sizeof(struct l_dev *))))) { (void) fprintf(stderr, "%s: can't realloc %s device pointers\n", Pn, nm); Exit(1); } return(j); } #if defined(HASDCACHE) /* * vfy_dev() - verify a device table entry (usually when DCunsafe == 1) * * Note: rereads entire device table when an entry can't be verified. */ int vfy_dev(dp) struct l_dev *dp; /* device table pointer */ { struct stat sb; if (!DCunsafe || dp->v) return(1); #if defined(USE_STAT) if (stat(dp->name, &sb) != 0 #else /* !defined(USE_STAT) */ if (lstat(dp->name, &sb) != 0 #endif /* defined(USE_STAT) */ || dp->rdev != sb.st_rdev || dp->inode != (INODETYPE)sb.st_ino) { (void) rereaddev(); return(0); } dp->v = 1; return(1); } #endif /* defined(HASDCACHE) */ lsof-4.86+dfsg.orig/dialects/du/dsock.c0000444000175000017500000002143710275734410020135 0ustar nicholasnicholas/* * dsock.c - DEC OSF/1, Digital UNIX, Tru64 UNIX socket processing functions * for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dsock.c,v 1.19 2005/08/08 19:56:44 abe Exp $"; #endif #include "lsof.h" /* * process_socket() - process socket */ void process_socket(sa) KA_T sa; /* socket address in kernel */ { struct domain d; unsigned char *fa = (unsigned char *)NULL; int fam; int fp, lp; struct inpcb inp; KA_T ka; unsigned char *la = (unsigned char *)NULL; struct mbuf mb; struct protosw p; struct socket s; struct tcpcb t; struct unpcb uc, unp; struct sockaddr_un *ua = NULL; struct sockaddr_un un; (void) snpf(Lf->type, sizeof(Lf->type), "sock"); Lf->inp_ty = 2; /* * Read the socket, protocol, and domain structures. */ if (!sa) { enter_nm("no socket address"); return; } if (kread(sa, (char *) &s, sizeof(s))) { (void) snpf(Namech, Namechl, "can't read socket struct from %s", print_kptr(sa, (char *)NULL, 0)); enter_nm(Namech); return; } if (!s.so_type) { enter_nm("no socket type"); return; } if (!s.so_proto || kread((KA_T)s.so_proto, (char *)&p, sizeof(p))) { (void) snpf(Namech, Namechl, "can't read protocol switch from %s", print_kptr((KA_T)s.so_proto, (char *)NULL, 0)); enter_nm(Namech); return; } if (!p.pr_domain || kread((KA_T)p.pr_domain, (char *)&d, sizeof(d))) { (void) snpf(Namech, Namechl, "can't read domain struct from %s", print_kptr((KA_T)p.pr_domain, (char *)NULL, 0)); enter_nm(Namech); return; } /* * Save size information. */ if (Fsize) { if (Lf->access == 'r') Lf->sz = (SZOFFTYPE)s.so_rcv.sb_cc; else if (Lf->access == 'w') Lf->sz = (SZOFFTYPE)s.so_snd.sb_cc; else Lf->sz = (SZOFFTYPE)(s.so_rcv.sb_cc + s.so_snd.sb_cc); Lf->sz_def = 1; } else Lf->off_def = 1; #if defined(HASTCPTPIQ) Lf->lts.rq = s.so_rcv.sb_cc; Lf->lts.sq = s.so_snd.sb_cc; Lf->lts.rqs = Lf->lts.sqs = 1; #endif /* defined(HASTCPTPIQ) */ #if defined(HASSOOPT) Lf->lts.ltm = (unsigned int)s.so_linger; Lf->lts.opt = (unsigned int)s.so_options; Lf->lts.pqlen = (unsigned int)s.so_q0len; Lf->lts.qlen = (unsigned int)s.so_qlen; Lf->lts.qlim = (unsigned int)s.so_qlimit; Lf->lts.rbsz = (unsigned long)s.so_rcv.sb_mbmax; Lf->lts.sbsz = (unsigned long)s.so_snd.sb_mbmax; Lf->lts.pqlens = Lf->lts.qlens = Lf->lts.qlims = Lf->lts.rbszs = Lf->lts.sbszs = (unsigned char)1; #endif /* defined(HASSOOPT) */ #if defined(HASSOSTATE) Lf->lts.ss = (unsigned int)s.so_state; #endif /* defined(HASSOSTATE) */ /* * Process socket by the associated domain family. */ switch ((fam = d.dom_family)) { /* * Process an Internet domain socket. */ case AF_INET: #if defined(HASIPv6) case AF_INET6: (void) snpf(Lf->type, sizeof(Lf->type), (fam == AF_INET) ? "IPv4" : "IPv6"); #else /* !defined(HASIPv6) */ (void) snpf(Lf->type, sizeof(Lf->type), "inet"); #endif /* defined(HASIPv6) */ if (Fnet) { if (!FnetTy || ((FnetTy == 4) && (fam == AF_INET)) #if defined(HASIPv6) || ((FnetTy == 6) && (fam == AF_INET6)) #endif /* defined(HASIPv6) */ ) Lf->sf |= SELNET; } printiproto(p.pr_protocol); /* * Read protocol control block. */ if (!s.so_pcb || kread((KA_T)s.so_pcb, (char *)&inp, sizeof(inp))) { (void) snpf(Namech, Namechl, "can't read inpcb at %s", print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); enter_nm(Namech); return; } /* * Print Internet socket information. */ ka = (KA_T)(inp.inp_ppcb ? inp.inp_ppcb : s.so_pcb); enter_dev_ch(print_kptr((ka & 0xffffffff), (char *)NULL, 0)); #if defined(HASIPv6) if ((fam == AF_INET && IN6_IS_ADDR_UNSPECIFIED(&inp.inp_laddr)) || IN6_IS_ADDR_V4MAPPED(&inp.inp_laddr)) { la = (unsigned char *)&IN6_EXTRACT_V4ADDR(&inp.inp_laddr); fam = AF_INET; } else { la = (unsigned char *)&inp.inp_laddr; fam = AF_INET6; } #else /* !defined(HASIPv6) */ la = (unsigned char *)&inp.inp_laddr; #endif /* defined(HASIPv6) */ lp = (int)ntohs(inp.inp_lport); #if defined(HASIPv6) if (fam == AF_INET) { if (inp.inp_fport || IN6_EXTRACT_V4ADDR(&inp.inp_faddr) != INADDR_ANY) { fa = (unsigned char *)&IN6_EXTRACT_V4ADDR(&inp.inp_faddr); fp = (int)ntohs(inp.inp_fport); } } else { if (inp.inp_fport || !IN6_IS_ADDR_UNSPECIFIED(&inp.inp_faddr)) { fa = (unsigned char *)&inp.inp_faddr; fp = (int)ntohs(inp.inp_fport); } } #else /* !defined(HASIPv6) */ if (inp.inp_faddr.s_addr != INADDR_ANY || inp.inp_fport != 0) { fa = (unsigned char *)&inp.inp_faddr; fp = (int)ntohs(inp.inp_fport); } #endif /* defined(HASIPv6) */ if (fa || la) (void) ent_inaddr(la, lp, fa, fp, fam); if (p.pr_protocol == IPPROTO_TCP && inp.inp_ppcb && !kread((KA_T)inp.inp_ppcb, (char *)&t, sizeof(t))) { Lf->lts.type = 0; Lf->lts.state.i = (int)t.t_state; #if defined(HASSOOPT) Lf->lts.kai = (unsigned int)t.t_timer[TCPT_KEEP]; #endif /* defined(HASSOOPT) */ #if defined(HASTCPOPT) Lf->lts.mss = (unsigned long)t.t_maxseg; Lf->lts.msss = (unsigned char)1; Lf->lts.topt = (unsigned int)t.t_flags; #endif /* defined(HASTCPOPT) */ } break; /* * Process a ROUTE domain socket. */ case AF_ROUTE: (void) snpf(Lf->type, sizeof(Lf->type), "rte"); if (s.so_pcb) { ka = (KA_T)(s.so_pcb); enter_dev_ch(print_kptr((ka & 0xffffffff), (char *)NULL, 0)); } else (void) snpf(Namech, Namechl, "no protocol control block"); if (!Fsize) Lf->off_def = 1; break; /* * Process a Unix domain socket. */ case AF_UNIX: if (Funix) Lf->sf |= SELUNX; (void) snpf(Lf->type, sizeof(Lf->type), "unix"); /* * Read Unix protocol control block and the Unix address structure. */ enter_dev_ch(print_kptr((sa & 0xffffffff), (char *)NULL, 0)); if (kread((KA_T) s.so_pcb, (char *) &unp, sizeof(unp))) { (void) snpf(Namech, Namechl, "can't read unpcb at %s", print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); break; } if ((struct socket *)sa != unp.unp_socket) { (void) snpf(Namech, Namechl, "unp_socket (%s) mismatch", print_kptr((KA_T)unp.unp_socket, (char *)NULL, 0)); break; } if (unp.unp_addr) { if (kread((KA_T) unp.unp_addr, (char *) &mb, sizeof(mb))) { (void) snpf(Namech, Namechl, "can't read unp_addr at %s", print_kptr((KA_T)unp.unp_addr, (char *)NULL, 0)); break; } ua = (struct sockaddr_un *)((char *)&mb + (mb.m_hdr.mh_data - (caddr_t)unp.unp_addr)); ua->sun_family = AF_UNIX; } if (!ua) { ua = &un; (void) zeromem((char *)ua, sizeof(un)); ua->sun_family = AF_UNSPEC; } /* * Print information on Unix socket that has no address bound * to it, although it may be connected to another Unix domain * socket as a pipe. */ if (ua->sun_family != AF_UNIX) { if (ua->sun_family == AF_UNSPEC) { if (unp.unp_conn) { if (kread((KA_T)unp.unp_conn, (char *)&uc, sizeof(uc))) (void) snpf(Namech, Namechl, "can't read unp_conn at %s", print_kptr((KA_T)unp.unp_conn,(char *)NULL,0)); else { ka = (KA_T)uc.unp_socket; (void) snpf(Namech, Namechl, "->%s", print_kptr((ka & 0xffffffff), (char *)NULL, 0)); } } else (void) snpf(Namech, Namechl, "->(none)"); } else (void) snpf(Namech, Namechl, "unknown sun_family (%d)", ua->sun_family); break; } if (ua->sun_path[0]) { if (mb.m_len >= sizeof(struct sockaddr_un)) mb.m_len = sizeof(struct sockaddr_un) - 1; *((char *)ua + mb.m_len) = '\0'; if (Sfile && is_file_named(ua->sun_path, 0)) Lf->sf |= SELNM; if (!Namech[0]) (void) snpf(Namech, Namechl, "%s", ua->sun_path); } else (void) snpf(Namech, Namechl, "no address"); break; default: printunkaf(fam, 1); } if (Namech[0]) enter_nm(Namech); } lsof-4.86+dfsg.orig/dialects/du/dproc.c0000444000175000017500000010666510275734407020156 0ustar nicholasnicholas/* * dproc.c - DEC OSF/1, Digital UNIX, Tru64 UNIX process access functions for * lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dproc.c,v 1.23 2005/08/08 19:56:44 abe Exp $"; #endif #include "lsof.h" #if DUV>=50000 # if DUV>=50100 && defined(HASNCACHE) #include #include #define _KERNEL 1 #include #include #undef _KERNEL #include #include #include # endif /* DUV>=50100 && defined(HASNCACHE) */ _PROTOTYPE(static KA_T vpo2vp,(struct vm_ubc_object *vpo)); #endif /* DUV>=50000 */ _PROTOTYPE(static void enter_vn_text,(KA_T va, int *n)); _PROTOTYPE(static void get_kernel_access,(void)); #if DUV<30000 _PROTOTYPE(static void process_text,(KA_T tp, KA_T utp)); #else /* DUV>=30000 */ _PROTOTYPE(static void process_text,(KA_T tp)); #endif /* DUV<30000 */ _PROTOTYPE(static void read_proc,(void)); /* * Local defintions */ #define PAPSINCR 1024 /* Pa and Ps table increment */ #define PAPSINIT 512 /* Pa and Ps table initial size */ /* * Local static values */ #if DUV<30000 static KA_T Kp; /* kernel proc[] address */ #endif /* DUV<30000 */ static int Np = 0; /* number of processes */ static MALLOC_S Nv = 0; /* allocateed Vp[] entries */ #if DUV>=30000 static KA_T Pidtab; /* kernel pidtab[] address */ #endif /* DUV>=30000 */ static KA_T *Vp = NULL; /* vnode address cache */ /* * enter_vn_text() - enter a vnode text reference */ static void enter_vn_text(va, n) KA_T va; /* vnode address */ int *n; /* number of vnodes in vp[] */ { int i; /* * Ignore the request if the vnode has already been printed. */ for (i = 0; i < *n; i++) { if (va == Vp[i]) return; } /* * Print the vnode. */ alloc_lfile(" txt", -1); FILEPTR = (struct file *)NULL; process_node(va); if (Lf->sf) link_lfile(); if (i >= Nv) { /* * Allocate space for remembering the vnode. */ Nv += 10; if (!Vp) Vp=(KA_T *)malloc((MALLOC_S)(sizeof(KA_T) * 10)); else Vp=(KA_T *)realloc((MALLOC_P *)Vp,(MALLOC_S)(Nv*sizeof(KA_T))); if (!Vp) { (void) fprintf(stderr, "%s: no txt ptr space, PID %d\n", Pn, Lp->pid); Exit(1); } } /* * Remember the vnode. */ Vp[*n] = va; (*n)++; } /* * gather_proc_info() -- gather process information */ void gather_proc_info() { MALLOC_S b; struct file *fp; int i, j; struct pgrp pg; int pgid, px; struct proc *p; short pss, sf; struct ucred pcred; uid_t uid; struct utask ut, *utp; #if DUV>=30000 struct pid_entry pe; #endif /* DUV>=30000 */ #if DUV<50000 static int nufb = 0; static struct file **ufb = (struct file **)NULL; #else /* DUV>=50000 */ int k, l; KA_T ka; struct ufile_entry *ofb[U_FE_OF_ALLOC_SIZE]; struct ufile_entry ufe[U_FE_ALLOC_SIZE]; struct ufile_entry ufeo[U_FE_OF_ALLOC_SIZE]; #endif /* DUV<50000 */ #if defined(HASFSTRUCT) && DUV>=40000 static char *pof = (char *)NULL; static int pofb = 0; long pv; #endif /* defined(HASFSTRUCT) && DUV>=40000 */ /* * Clear file lock information. */ (void) clr_flinfo(); /* * Read process table entries. */ read_proc(); /* * Examine proc structures and their associated information. */ for (p = Ps, px = 0, utp = &ut; px < Psn; p++, px++) { if (p->p_stat == 0 || p->p_stat == SZOMB) continue; if (Fpgid) { if (!p->p_pgrp || kread((KA_T)p->p_pgrp, (char *)&pg, sizeof(pg))) continue; pgid = pg.pg_id; } else pgid = 0; if (p->p_rcred == NULL || kread((KA_T)p->p_rcred, (char *)&pcred, sizeof(pcred))) continue; uid = (uid_t)pcred.cr_uid; if (is_proc_excl(p->p_pid, pgid, (UID_ARG)uid, &pss, &sf)) continue; #if DUV<30000 if (!p->utask || kread((KA_T)p->utask, (char *)&ut, sizeof(ut))) #else /* DUV>=30000 */ if (kread((KA_T)((char *)Pa[px] + sizeof(struct proc)), (char *)&ut, sizeof(ut))) #endif /* DUV<30000 */ continue; /* * Allocate a local process structure. */ if (is_cmd_excl(utp->u_comm, &pss, &sf)) continue; alloc_lproc((int)p->p_pid, pgid, (int)p->p_ppid, (UID_ARG)uid, utp->u_comm, (int)pss, (int)sf); Plf = (struct lfile *)NULL; /* * Save current working directory information. */ if (utp->uu_utnd.utnd_cdir) { alloc_lfile(CWD, -1); FILEPTR = (struct file *)NULL; process_node((KA_T)utp->uu_utnd.utnd_cdir); if (Lf->sf) link_lfile(); } /* * Save root directory information. */ if (utp->uu_utnd.utnd_rdir) { alloc_lfile(RTD, -1); FILEPTR = (struct file *)NULL; process_node((KA_T)utp->uu_utnd.utnd_rdir); if (Lf->sf) link_lfile(); } /* * Print information on the text file. */ #if DUV<30000 if (p->task) process_text((KA_T)p->task, (KA_T)p->utask); #else /* DUV>=30000 */ process_text((KA_T)((char *)Pa[px] - sizeof(struct task))); #endif /* DUV<30000 */ /* * Save information on file descriptors. */ #if DUV<50000 for (i = j = 0; i <= utp->uu_file_state.uf_lastfile; i++) { if (i < NOFILE_IN_U) { fp = utp->uu_file_state.uf_ofile[i]; # if defined(HASFSTRUCT) && DUV>=40000 if (Fsv & FSV_FG) pv = (long)utp->uu_file_state.uf_pofile[i]; # endif /* defined(HASFSTRUCT) && DUV>=40000 */ } else { if (!j) { b = (MALLOC_S)(utp->uu_file_state.uf_of_count * sizeof(struct file *)); if (b > nufb) { if (!ufb) ufb = (struct file **)malloc(b); else ufb = (struct file **)realloc((MALLOC_P *)ufb, b); if (!ufb) { (void) fprintf(stderr, "%s: PID %d, no file * space\n", Pn, Lp->pid); Exit(1); } nufb = b; } if (kread((KA_T)utp->uu_file_state.uf_ofile_of, (char *)ufb, b)) break; # if defined(HASFSTRUCT) && DUV>=40000 if (Fsv & FSV_FG) { b = (MALLOC_S)(utp->uu_file_state.uf_of_count * sizeof(char)); if (b > pofb) { if (!pof) pof = (char *)malloc(b); else pof = (char *)realloc((MALLOC_P *)pof, b); if (!pof) { (void) fprintf(stderr, "%s: PID %d: no file flags space\n", Pn, Lp->pid); Exit(1); } pofb = b; } if (kread((KA_T)utp->uu_file_state.uf_pofile_of, pof, b)) zeromem(pof, b); } # endif /* defined(HASFSTRUCT) && DUV>=40000 */ } fp = ufb[j]; # if defined(HASFSTRUCT) && DUV>=40000 if (Fsv & FSV_FG) pv = pof[j]; # endif /* defined(HASFSTRUCT) && DUV>=40000 */ j++; } if (fp && (ulong)fp != 0xffffffffffffffff) { alloc_lfile(NULL, i); process_file((KA_T)fp); if (Lf->sf) { # if defined(HASFSTRUCT) && DUV>=40000 if (Fsv & FSV_FG) { if ((Lf->pof = pv)) Lf->fsv |= FSV_FG; } # endif /* defined(HASFSTRUCT) && DUV>=40000 */ link_lfile(); } } } #else /* DUV>=50000 */ for (i = j = k = 0; i <= utp->uu_file_state.uf_lastfile; i++) { if (i < NOFILE_IN_U) { if (!k) { l = i/U_FE_ALLOC_SIZE; if (!(ka = (KA_T)utp->uu_file_state.uf_entry[l])) { i += U_FE_ALLOC_SIZE - 1; continue; } } } else { if (!j) { ka = (KA_T)utp->uu_file_state.uf_of_entry; if (!ka || kread(ka, (char *)&ofb, sizeof(ofb))) break; k = 0; } if (!k) { l = j/U_FE_OF_ALLOC_SIZE; if (!(ka = (KA_T)ofb[l])) { j += U_FE_OF_ALLOC_SIZE; i += U_FE_OF_ALLOC_SIZE - 1; continue; } if (kread(ka, (char *)&ufeo, sizeof(ufeo))) break; } fp = ufeo[k].ufe_ofile; # if defined(HASFSTRUCT) && DUV>=40000 if (Fsv & FSV_FG) pv = ufeo[k].ufe_oflags; # endif /* defined(HASFSTRUCT) && DUV>=40000 */ if (++k >= U_FE_OF_ALLOC_SIZE) k = 0; j++; } if (!j) { if (!k) { if (kread(ka, (char *)&ufe, sizeof(ufe))) break; } fp = ufe[k].ufe_ofile; # if defined(HASFSTRUCT) && DUV>=40000 if (Fsv & FSV_FG) pv = ufe[k].ufe_oflags; # endif /* defined(HASFSTRUCT) && DUV>=40000 */ if (++k >= U_FE_ALLOC_SIZE) k = 0; } if (fp && (ulong)fp != 0xffffffffffffffff) { alloc_lfile(NULL, i); process_file((KA_T)fp); if (Lf->sf) { # if defined(HASFSTRUCT) && DUV>=40000 if (Fsv & FSV_FG) { if ((Lf->pof = pv)) Lf->fsv |= FSV_FG; } # endif /* defined(HASFSTRUCT) && DUV>=40000 */ link_lfile(); } } } #endif /* DUV>=50000 */ /* * Examine results. */ if (examine_lproc()) return; } } /* * get_kernel_access() - get access to kernel memory */ static void get_kernel_access() { dev_t dev; int rv; KA_T v; /* * Check kernel version. */ (void) ckkv("DU", LSOF_VSTR, (char *)NULL, (char *)NULL); /* * Set name list file path. */ #if DUV<40000 if (!Nmlst) { if (!(Nmlst = get_nlist_path(1))) { (void) fprintf(stderr, "%s: can't get kernel name list path\n", Pn); Exit(1); } } #endif /* DUV<40000 */ #if defined(WILLDROPGID) /* * If kernel memory isn't coming from KMEM, drop setgid permission * before attempting to open the (Memory) file. */ if (Memory) (void) dropgid(); #else /* !defined(WILLDROPGID) */ /* * See if the non-KMEM memory file is readable. */ if (Memory && !is_readable(Memory, 1)) Exit(1); #endif /* defined(WILLDROPGID) */ /* * Open kernel memory access. */ if ((Kd = open(Memory ? Memory : KMEM, O_RDONLY, 0)) < 0) { (void) fprintf(stderr, "%s: can't open %s: %s\n", Pn, Memory ? Memory : KMEM, sys_errlist[errno]); Exit(1); } #if defined(WILLDROPGID) /* * Drop setgid permission, if necessary. */ if (!Memory) (void) dropgid(); #else /* !defined(WILLDROPGID) */ /* * See if the name list file is readable. */ if (Nmlst && !is_readable(Nmlst, 1)) Exit(1); #endif /* defined(WILLDROPGID) */ /* * Access kernel symbols. */ (void) build_Nl(Drive_Nl); #if DUV>=40000 if (!Nmlst) rv = knlist(Nl); else #endif /* DUV>=40000 */ rv = nlist(Nmlst, Nl); if (rv == -1) { (void) fprintf(stderr, "%s: can't read kernel name list from %s: %s\n", Pn, Nmlst ? Nmlst : "knlist(3)", strerror(errno)); Exit(1); } #if DUV<30000 if (get_Nl_value("proc", Drive_Nl, &v) < 0 || !v || kread(v, (char *)&Kp, sizeof(Kp)) || get_Nl_value("nproc", Drive_Nl, &v) < 0 || !v || kread(v, (char *)&Np, sizeof(Np))) #else /* DUV>=30000 */ if (get_Nl_value("npid", Drive_Nl, &v) < 0 || !v || kread(v, (char *)&Np, sizeof(Np)) || get_Nl_value("pidt", Drive_Nl, &v) < 0 || !v || kread(v, (char *)&Pidtab, sizeof(Pidtab))) #endif /* DUV<30000 */ { (void) fprintf(stderr, "%s: can't read proc table info\n", Pn); Exit(1); } if (get_Nl_value("vnmaxp", Drive_Nl, &v) < 0 || !v || kread(v, (char *)&Vnmxp, sizeof(Vnmxp))) { (void) fprintf(stderr, "%s: can't determine vnode length\n", Pn); Exit(1); } if (get_Nl_value("cldev", Drive_Nl, &v) < 0 || !v || kread(v, (char *)&dev, sizeof(dev))) { if (!Fwarn) (void) fprintf(stderr, "%s: can't read clone device number\n", Pn); HaveCloneMaj = 0; } else { CloneMaj = GET_MAJ_DEV(dev); HaveCloneMaj = 1; } } /* * get_nlist_path() - get kernel name list path */ char * get_nlist_path(ap) int ap; /* on success, return an allocated path * string pointer if 1; return a * constant character pointer if 0; * return NULL if failure */ { char *ba, buf[MAXPATHLEN+2], *ps; int len, rv; /* * Get bootfile name. */ len = 0; if ((rv = getsysinfo(GSI_BOOTEDFILE, &buf[1], sizeof(buf) - 1, &len, (char *)NULL)) != 1) { if (rv < 0) { (void) fprintf(stderr, "%s: can't get booted file name: %s\n", Pn, strerror(errno)); Exit(1); } return((char *)NULL); } /* * Check for a non-NULL path. */ buf[sizeof(buf) - 2] = '\0'; len = strlen(&buf[1]); if (len < 1) return((char *)NULL); /* * If no path return is requested by the value of ap, return a NULL string * pointer. */ if (!ap) return(""); /* * Make sure the path has a leading '/'. */ if (buf[1] != '/') { buf[0] = '/'; ba = buf; len++; } else ba = &buf[1]; /* * Allocate permanent space for the path, copy it to the space, and return * a pointer to the space. */ len++; if (!(ps = (char *)malloc(len))) { (void) fprintf(stderr, "%s: can't allocate %d bytes for boot file path: %s\n", Pn, len, ba); Exit(1); } (void) snpf(ps, len, "%s", ba); return(ps); } /* * initialize() - perform all initialization */ void initialize() { get_kernel_access(); } /* * kread() - read from kernel memory */ int kread(addr, buf, len) KA_T addr; /* kernel memory address */ char *buf; /* buffer to receive data */ READLEN_T len; /* length to read */ { int br; if (lseek(Kd, addr, L_SET) == (off_t)-1L) return(-1); br = read(Kd, buf, len); return((br == len) ? 0 : 1); } /* * process_text() - print text information */ static void #if DUV<30000 process_text(tp, utp) #else /* DUV>=30000 */ process_text(tp) #endif /* DUV<30000 */ KA_T tp; /* kernel task structure */ #if DUV<30000 KA_T utp; /* user task structure address for * the task */ #endif /* DUV<30000 */ { int i; KA_T ka, kb; int n = 0; struct task t; struct vm_anon_object vmao; struct vm_map_entry vmme; struct vm_map vmm; struct vm_object vmo; struct vm_seg vms; #if DUV<40000 struct vm_vp_object vpo; #else /* DUV>=40000 */ struct vm_ubc_object vpo; #endif /* DUV<40000 */ /* * Read task structure from kernel. */ if (kread(tp, (char *)&t, sizeof(t)) #if DUV<30000 || (KA_T)t.u_address != utp #endif /* DUV<30000 */ ) return; /* * Print information about the text vnode referenced in the procfs * structure inside the task structure. */ if (t.procfs.pr_exvp) enter_vn_text((KA_T)t.procfs.pr_exvp, &n); /* * Read the vm_map structure. Search its vm_map_entry structure list. */ if (!t.map || kread((KA_T)t.map, (char *)&vmm, sizeof(vmm))) return; if (!vmm.vm_is_mainmap) return; #if defined(VM_SKIPLIST) for (i = 0, ka = (KA_T)vmm.vm_links.vml_sl_next[0]; i < vmm.vm_nentries && ka != (KA_T)t.map; i++, ka = (KA_T)vmme.vme_links.vml_sl_next[0]) #else /* !defined(VM_SKIPLIST) */ for (i = 0, ka = (KA_T)vmm.vm_links.next; i < vmm.vm_nentries && ka != (KA_T)t.map; i++, ka = (KA_T)vmme.vme_links.next) #endif /* defined(VM_SKIPLIST) */ { /* * Read the next vm_map_entry structure and its object. */ if (kread(ka, (char *)&vmme, sizeof(vmme))) return; if (!(kb = (KA_T)vmme.vme_uobject.vm_object) || kread(kb, (char *)&vmo, sizeof(vmo))) continue; /* * Process by object type. */ switch (vmo.ob_type) { case OT_ANON: /* * If an anonymous object is backed by an OT_UBC or OT_VP object, * read its vm_ubc_object or vm_vp_object to find a vnode pointer. */ if (kread(kb, (char *)&vmao, sizeof(vmao))) break; if (!vmao.ao_bobject || kread((KA_T)vmao.ao_bobject, (char *)&vmo, sizeof(vmo))) break; #if DUV<40000 if (vmo.ob_type != OT_VP || kread((KA_T)vmao.ao_bobject, (char *)&vpo, sizeof(vpo))) break; enter_vn_text((KA_T)vpo.vo_vp, &n); #else /* DUV>=40000 */ if (vmo.ob_type != OT_UBC || kread((KA_T)vmao.ao_bobject, (char *)&vpo, sizeof(vpo))) break; # if DUV>=50000 enter_vn_text(vpo2vp(&vpo), &n); # else /* DUV<50000 */ enter_vn_text((KA_T)vpo.vu_vfp.vp, &n); #endif /* DUV>=50000 */ #endif /* DUV<40000 */ break; /* * If this is a segment object, read the segment map, and search * for backing objects whose object type is OT_UBC or OT_VP. */ case OT_SEG: for (kb=(KA_T)vmme.vme_seg; kb; kb=(KA_T)vms.seg_vnext) { if (kread(kb, (char *)&vms, sizeof(vms))) break; if (!vms.seg_vop || kread((KA_T)vms.seg_vop, (char *)&vmo, sizeof(vmo))) continue; #if DUV<40000 if (vmo.ob_type != OT_VP) #else /* DUV>=40000 */ if (vmo.ob_type != OT_UBC) #endif /* DUV<40000 */ continue; if (kread((KA_T)vms.seg_vop, (char *)&vpo, sizeof(vpo))) break; #if DUV<40000 enter_vn_text((KA_T)vpo.vo_vp, &n); #else /* DUV>=40000 */ # if DUV>=50000 enter_vn_text(vpo2vp(&vpo), &n); # else /* DUV<50000 */ enter_vn_text((KA_T)vpo.vu_vfp.vp, &n); #endif /* DUV<40000 */ #endif /* DUV>=50000 */ } } } } /* * read_proc() - read process table entries */ static void read_proc() { static int ap = 0; MALLOC_S len; struct proc *p; KA_T pa; int px, try; #if DUV>=30000 struct pid_entry pe; #endif /* DUV>=30000 */ if (!Ps) { /* * Allocate local proc table space. */ if (Np < 1) { (void) fprintf(stderr, "%s: proc table has no entries\n", Pn); Exit(1); } len = (MALLOC_S)(PAPSINIT * sizeof(struct proc)); if (!(Ps = (struct proc *)malloc(len))) { (void) fprintf(stderr, "%s: no proc table space (%d bytes)\n", Pn, len); Exit(1); } #if DUV>=30000 /* * Allocate kernel proc address table space. */ len = (MALLOC_S)(PAPSINIT * sizeof(KA_T)); if (!(Pa = (KA_T *)malloc(len))) { (void) fprintf(stderr, "%s: no proc address table space (%d bytes)\n", Pn, len); Exit(1); } #endif /* DUV>=30000 */ ap = PAPSINIT; } /* * Try to read the proc structure table PROCTRYLM times. * The operation must yield PROCMIN structures. */ for (try = 0; try < PROCTRYLM; try++) { for (p = Ps, Psn = px = 0; px < Np; px++) { /* * Insure Ps and Psa space. */ if (Psn >= ap) { ap += PAPSINCR; len = (MALLOC_S)(ap * sizeof(struct proc)); if (!(Ps = (struct proc *)realloc((MALLOC_P *)Ps, len))) { (void) fprintf(stderr, "%s: no more proc table space (%d bytes)\n", Pn, len); Exit(1); } p = &Ps[Psn]; #if DUV>=30000 len = (MALLOC_S)(ap * sizeof(KA_T)); if (!(Pa = (KA_T *)realloc((MALLOC_P *)Pa, len))) { (void) fprintf(stderr, "%s: no more proc address table space (%d bytes)\n", Pn, len); Exit(1); } #endif /* DUV>=30000 */ } #if DUV<30000 pa = Kp + (KA_T)(px * sizeof(struct proc)); if (kread(pa, (char *)p, sizeof(struct proc))) continue; #else /* DUV>=30000 */ pa = Pidtab + (KA_T)(px * sizeof(struct pid_entry)); if (kread(pa, (char *)&pe, sizeof(struct pid_entry))) continue; if ((pa = (KA_T)pe.pe_proc) == NULL || kread(pa, (char *)p, sizeof(struct proc))) continue; if (pe.pe_pid != p->p_pid) continue; Pa[Psn] = pa; #endif /* DUV<30000 */ Psn++; p++; } /* * Check the results of the scan. */ if (Psn >= PROCMIN) break; } /* * Quit if not enough proc structures could be accumulated. */ if (try >= PROCTRYLM) { (void) fprintf(stderr, "%s: can't read proc table\n", Pn); Exit(1); } if (Psn < Np && !RptTm) { /* * Reduce the local proc structure tables to their minimum if * not in repeat mode. */ ap = Psn; len = (MALLOC_S)(Psn * sizeof(struct proc)); if (!(Ps = (struct proc *)realloc((MALLOC_P *)Ps, len))) { (void) fprintf(stderr, "%s: can't reduce proc table to %d bytes\n", Pn, len); Exit(1); } #if DUV>=30000 len = (MALLOC_S)(Psn * sizeof(KA_T)); if (!(Pa = (KA_T *)realloc((MALLOC_P *)Pa, len))) { (void) fprintf(stderr, "%s: can't reduce proc address table to %d bytes\n", Pn, len); Exit(1); } #endif /* DUV>=30000 */ } } #if DUV>=50000 /* * vfp2vp() -- convert VM object's vu_vfp to a vnode pointer */ static KA_T vpo2vp(vpo) struct vm_ubc_object *vpo; /* pointer to local vm_ubc_object */ { struct advfsbfs { /* This structure is referenced in * vm_ubc.h (as msfsbfs), but never * defined in a distributed header * file, so we make a hack definition * here. */ unsigned long d1[18]; /* dummies */ struct vnode *vp; /* vnode */ } bfa; static int ft = 1; KA_T ka; static KA_T ops = (KA_T)0; /* * If this is the first time, get the msfs (AdvFS) UBC operation switch * address. */ if (ft) { ft = 0; #if defined(ADVFSV) if (get_Nl_value("msfsubc", Drive_Nl, &ops) < 0) #endif /* defined(ADVFSV) */ ops = (KA_T)0; } ka = (KA_T)vpo->vu_vfp.vp; if (!ops || ((KA_T)vpo->vu_ops != ops)) return(ka); if (!ka || kread(ka, (char *)&bfa, sizeof(bfa))) return(ka); return((KA_T)bfa.vp); } #endif /* DUV>=50000 */ #if DUV>=50100 && defined(HASNCACHE) /* * Kernel name cache functions and associate definiitions for Tru64 UNIX * 5.1 and above. */ /* * Definitions */ /* * Structures */ struct l_nch { struct namecache *nc; /* namecache entry */ struct l_nch *nxt; /* next hashed entry */ }; /* * Static variables */ static int Hmsk = 0; /* Nchash[] mask -- (size - 1), where * size is a power of two */ static int Nc; /* number of cached namecache structs */ static struct l_nch **Nchash = (struct l_nch **)NULL; /* hash pointers buckets */ static int Ncfirst = 1; /* first-call status */ /* * Definitions */ #define ncachehash(i) (((int)(i*31415)>>3)&Hmsk) /* * Prototypes */ _PROTOTYPE(static struct l_nch *ncache_addr,(unsigned long id)); _PROTOTYPE(static int ncache_ckrootid,(KA_T na, unsigned long id)); _PROTOTYPE(static int ncache_isroot,(KA_T na, char *cp)); /* * ncache_addr() -- look up a node's local ncache address */ static struct l_nch * ncache_addr(id) unsigned long id; /* node's capability ID */ { register struct l_nch *hp; for (hp = Nchash[ncachehash(id)]; hp; hp = hp->nxt) { if ((hp->nc)->nc_vpid == id) return(hp); } return((struct l_nch *)NULL); } /* * ncache_ckrootid() - check for a root node ID */ static int ncache_ckrootid(na, id) KA_T na; /* vnode address */ unsigned long id; /* root ID to check */ { #if defined(ADVFSV) struct advfsmount { /* This structure should be defined in * a distributed header file, but it * isn't, so we make a hack definition * here. */ u_long d1[10]; /* dummies */ struct vnode *am_rootvp; /* root vnode pointer */ } am; static KA_T aops = (KA_T)0; #endif /* defined(ADVFSV) */ struct cdfsmount cm; static KA_T cops = (KA_T)0; struct dvdfsmount dm; static KA_T dops = (KA_T)0; static KA_T fops = (KA_T)0; static KA_T frvp = (KA_T)0; static int ft = 1; register int i; static unsigned long *ic = (unsigned long *)NULL; MALLOC_S len; struct mount m; static int nia = 0; static int niu = 0; struct mntinfo nm; static KA_T nops = (KA_T)0; static KA_T n3ops = (KA_T)0; KA_T rv; struct ufsmount um; static KA_T uops = (KA_T)0; struct vnode v; /* * Check the cache. */ if (ic && niu) { for (i = 0; i < niu; i++) { if (id == ic[i]) return(1); } } /* * Read the vnode and the associated mount structure. */ if (!na || kread(na, (char *)&v, sizeof(v))) return(0); if (!v.v_mount || kread((KA_T)v.v_mount, (char *)&m, sizeof(m))) return(0); /* * If this is the first time this function has been used, get the necessary * kernel addresses. */ if (ft) { ft = 0; #if defined(ADVFSV) if (get_Nl_value("advfsvfs", (struct drive_Nl *)NULL, &aops) < 0) aops = (KA_T)0; #endif /* defined(ADVFSV) */ if (get_Nl_value("cdfsvfs", (struct drive_Nl *)NULL, &cops) < 0) cops = (KA_T)0; if (get_Nl_value("dvdfsvfs", (struct drive_Nl *)NULL, &dops) < 0) dops = (KA_T)0; if (get_Nl_value("fdfsvfs", (struct drive_Nl *)NULL, &fops) < 0) fops = (KA_T)0; if (get_Nl_value("fsfsrvp", (struct drive_Nl *)NULL, &frvp) < 0) frvp = (KA_T)0; if (get_Nl_value("nfsvfs", (struct drive_Nl *)NULL, &nops) < 0) nops = (KA_T)0; if (get_Nl_value("nfs3vfs", (struct drive_Nl *)NULL, &n3ops) < 0) n3ops = (KA_T)0; if (get_Nl_value("ufsvfs", (struct drive_Nl *)NULL, &uops) < 0) uops = (KA_T)0; } /* * See if we know how to find the root vnode pointer for this file system * type. */ #if defined(ADVFSV) if (aops && (aops == (KA_T)m.m_op)) { /* * Set AdvFS (MSFS) root vnode address. */ if (!m.m_info || kread((KA_T)m.m_info, (char *)&am, sizeof(am))) return(0); rv = (KA_T)am.am_rootvp; } else #endif /* defined(ADVFSV) */ if (cops && (cops == (KA_T)m.m_op)) { /* * Set CDFS root vnode address. */ if (!m.m_info || kread((KA_T)m.m_info, (char *)&cm, sizeof(cm))) return(0); rv = (KA_T)cm.um_rootvp; } else if (dops && (dops == (KA_T)m.m_op)) { /* * Set DVDFS root vnode address. */ if (!m.m_info || kread((KA_T)m.m_info, (char *)&dm, sizeof(dm))) return(0); rv = (KA_T)dm.dm_rootvp; } else if (fops && (fops == (KA_T)m.m_op)) { /* * Set FDFS root vnode address. */ rv = frvp; } else if ((nops && (nops == (KA_T)m.m_op)) || (n3ops && (n3ops == (KA_T)m.m_op))) { /* * Set NFS[3] root vnode address. */ if (!m.m_info || kread((KA_T)m.m_info, (char *)&nm, sizeof(nm))) return(0); rv = (KA_T)nm.mi_rootvp; } else if (uops && (uops == (KA_T)m.m_op)) { /* * Set UFS root vnode address. */ if (!m.m_info || kread((KA_T)m.m_info, (char *)&um, sizeof(um))) return(0); rv = (KA_T)um.um_rootvp; } else return(0); /* * Read the root vnode. */ if (!rv || kread(rv, (char *)&v, sizeof(v))) return(0); if (id != v.v_id) return(0); /* * A new root vnode has been located. Cache it. */ if (niu >= nia) { if (!nia) { len = (MALLOC_S)(10 * sizeof(unsigned long)); ic = (unsigned long *)malloc(len); } else { len = (MALLOC_S)((nia + 10) * sizeof(unsigned long)); ic = (unsigned long *)realloc((MALLOC_P *)ic, len); } if (!ic) { (void) fprintf(stderr, "%s: no space for root node VPID table\n", Pn); Exit(1); } nia += 10; } ic[niu++] = id; return(1); } /* * ncache_isroot() - is head of name cache path a file system root? */ static int ncache_isroot(na, cp) KA_T na; /* vnode address */ char *cp; /* partial path */ { char buf[MAXPATHLEN]; int i; MALLOC_S len; struct mounts *mtp; static KA_T *nc = (KA_T *)NULL; static int nca = 0; static int ncn = 0; struct stat sb; struct vnode v; if (!na) return(0); /* * Search the root capability node address cache. */ for (i = 0; i < ncn; i++) { if (na == nc[i]) return(1); } /* * Read the vnode and see if it's a VDIR node with the VROOT flag set. If * it is, then the path is complete. * * If it isn't, and if the file has an inode number, search the mount table * and see if the file system's inode number is known. If it is, form the * possible full path, safely stat() it, and see if it's inode number matches * the one we have for this file. If it does, then the path is complete. */ if (kread((KA_T)na, (char *)&v, sizeof(v)) || v.v_type != VDIR || !(v.v_flag & VROOT)) { /* * The vnode tests failed. Try the inode tests. */ if (Lf->inp_ty != 1 || !Lf->inode || !Lf->fsdir || (len = strlen(Lf->fsdir)) < 1) return(0); if ((len + 1 + strlen(cp) + 1) > sizeof(buf)) return(0); for (mtp = readmnt(); mtp; mtp = mtp->next) { if (!mtp->dir || !mtp->inode) continue; if (strcmp(Lf->fsdir, mtp->dir) == 0) break; } if (!mtp) return(0); (void) strcpy(buf, Lf->fsdir); if (buf[len - 1] != '/') buf[len++] = '/'; (void) strcpy(&buf[len], cp); if (statsafely(buf, &sb) != 0 || (INODETYPE)sb.st_ino != Lf->inode) return(0); } /* * Add the capability ID to the root capability ID cache. */ if (ncn >= nca) { if (!nca) { len = (MALLOC_S)(10 * sizeof(KA_T)); nc = (KA_T *)malloc(len); } else { len = (MALLOC_S)((nca + 10) * sizeof(KA_T)); nc = (KA_T *)realloc((MALLOC_P *)nc, len); } if (!nc) { (void) fprintf(stderr, "%s: no space for root node address table\n", Pn); Exit(1); } nca += 10; } nc[ncn++] = na; return(1); } /* * ncache_load() - load the kernel's name cache */ void ncache_load() { register int h, i, n; KA_T ka, ncp; int len; register struct l_nch *lp; struct l_nch *lpnxt; static struct namecache *nc = (struct namecache *)NULL; static int ncl = 0; static int nchsz = 0; static int ncpc = 0; static int ncpus = 0; register struct namecache *np; static KA_T *pp = (KA_T *)NULL; if (!Fncache) return; if (Ncfirst) { /* * Do startup (first-time) functions. */ Ncfirst = 0; /* * Get CPU count. */ ka = (KA_T)0; if (get_Nl_value("ncpus", (struct drive_Nl *)NULL, &ka) < 0 || !ka || kread(ka, (char *)&ncpus, sizeof(ncpus))) { if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: can't read processor count: %s\n", Pn, print_kptr(ka, (char *)NULL, 0)); ncl = nchsz = ncpc = ncpus = 0; return; } if (ncpus < 1) { if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: processor count: %d\n", Pn, ncpus); ncl = nchsz = ncpc = ncpus = 0; return; } /* * Get the per-processor table address. */ ka = (KA_T)0; if (get_Nl_value("procptr", (struct drive_Nl *)NULL, &ka) < 0 || !ka || kread(ka, (char *)&ka, sizeof(ka)) || !ka) { if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: per processor table address: %s\n", Pn, print_kptr(ka, (char *)NULL, 0)); ncl = nchsz = ncpc = ncpus = 0; return; } /* * Allocate space for the processor structure addresses and read them. */ len = (int)(ncpus * sizeof(KA_T)); if (!(pp = (KA_T *)malloc((MALLOC_S)len))) { (void) fprintf(stderr, "%s: can't allocate %d bytes for processor addresses\n", Pn, len); Exit(1); } if (kread(ka, (char *)pp, len)) { if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: can't read processor addresses: %s\n", Pn, print_kptr(ka, (char *)NULL, 0)); ncl = nchsz = ncpc = ncpus = 0; return; } for (i = 0; i < ncpus; i++) { if (pp[i]) pp[i] = (KA_T)((char *)pp[i] + offsetof(struct processor, namecache)); } /* * Get the per-processor nchash size. */ ka = (KA_T)0; if (get_Nl_value("nchsz", (struct drive_Nl *)NULL, &ka) < 0 || !ka || kread((KA_T)ka, (char *)&nchsz, sizeof(nchsz))) { if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: processor nchash count address: %s\n", Pn, print_kptr(ka, (char *)NULL, 0)); ncl = nchsz = ncpc = ncpus = 0; return; } if (nchsz < 1) { if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: bad per processor nchash count: %d\n", Pn, nchsz); nchsz = ncpus = 1; return; } /* * Allocate space for nchsz * NCHSIZE * ncpus namecache structures. */ ncpc = (int)(nchsz * NCHSIZE); ncl = (int)(ncpc * sizeof(struct namecache)); len = (int)(ncl * ncpus); if (!(nc = (struct namecache *)malloc((MALLOC_S)len))) { (void) fprintf(stderr, "%s: no space for %d namecache entries (%d bytes)\n", Pn, ncpc * ncpus, len); Exit(1); } } else { /* * Do setup for repeat calls. */ if (Nchash) { for (i = 0; i <= Hmsk; i++) { for (lp = Nchash[i]; lp; lp = lpnxt) { lpnxt = lp->nxt; (void) free((MALLOC_P *)lp); } } (void) free((MALLOC_P *)Nchash); Nchash = (struct l_nch **)NULL; Nc = 0; } } /* * Loop through the processors, reading the processor structure pointer * for the processor, then its name cache. Build a local name cache * table of struct namecache entries for all processors. */ for (i = n = 0; i < ncpus; i++) { if (!pp[i]) continue; if (kread(pp[i], (char *)&ncp, sizeof(ncp)) || !ncp) continue; if (kread(ncp, (char *)&nc[n], ncl)) continue; n += ncpc; } /* * Compute a hash table size and allocate it. */ if (!n) return; for (i = 1; i < n; i <<= 1) ; i += i; Hmsk = i - 1; if (!(Nchash = (struct l_nch **)calloc(i, sizeof(struct l_nch *)))) { if (!Fwarn) (void) fprintf(stderr, "%s: no space for %d byte name cache hash buckets\n", Pn, (int)(i * sizeof(struct l_nch *))); Exit(1); } /* * Assign hash pointers to the accumulated namecache entries. */ for (i = Nc = 0; i < n; i++) { if (!nc[i].nc_vpid) continue; if (((len = nc[i].nc_nlen) < 1) || (len > NCHNAMLEN)) continue; if (len < 3 && nc[i].nc_name[0] == '.') { if ((len == 1) || ((len == 2) && (nc[i].nc_name[1] == '.'))) continue; } h = ncachehash(nc[i].nc_vpid); /* * Look for an existing hash entry. Choose among duplicates the one * with the largest nc_dvpid. */ for (lp = Nchash[h]; lp; lp = lp->nxt) { if ((np = lp->nc) && (np->nc_vpid == nc[i].nc_vpid)) { if (nc[i].nc_dvpid > np->nc_dvpid) lp->nc = &nc[i]; break; } } if (lp) continue; /* * Allocate and fill a new local name cache entry. */ if (!(lp = (struct l_nch *)malloc(sizeof(struct l_nch)))) { (void) fprintf(stderr, "%s: can't allocate l_nch entry\n", Pn); Exit(1); } lp->nc = &nc[i]; lp->nxt = Nchash[h]; Nchash[h] = lp; Nc++; } } /* * ncache_lookup() - look up a node's name in the kernel's name cache */ char * ncache_lookup(buf, blen, fp) char *buf; /* receiving name buffer */ int blen; /* receiving buffer length */ int *fp; /* full path reply */ { char *cp = buf; struct l_nch *lc; struct mounts *mtp; struct namecache *nc; int nl, rlen; *cp = '\0'; *fp = 0; # if defined(HASFSINO) /* * If the entry has an inode number that matches the inode number of the * file system mount point, return an empty path reply. That tells the * caller to print the file system mount point name only. */ if (Lf->inp_ty == 1 && Lf->fs_ino && Lf->inode == Lf->fs_ino) return(cp); # endif /* defined(HASFSINO) */ /* * Look up the name cache entry for the node address. */ if (Nc == 0 || !(lc = ncache_addr(Lf->id)) || !(nc = lc->nc)) { /* * If the node has no cache entry, see if it's the mount * point of a known file system. */ if (!Lf->fsdir || !Lf->dev_def || Lf->inp_ty != 1) return((char *)NULL); for (mtp = readmnt(); mtp; mtp = mtp->next) { if (!mtp->dir || !mtp->inode) continue; if ((Lf->dev == mtp->dev) && (mtp->inode == Lf->inode) && (strcmp(mtp->dir, Lf->fsdir) == 0)) return(cp); } return((char *)NULL); } /* * Start the path assembly. */ if ((nl = nc->nc_nlen) > (blen - 1)) return((char *)NULL); cp = buf + blen - nl - 1; rlen = blen - nl - 1; (void) strncpy(cp, nc->nc_name, nl); cp[nl] = '\0'; /* * Look up the name cache entries that are parents of the node address. * Quit when: * * there's no parent; * the name length is too large to fit in the receiving buffer. */ for (;;) { if (!nc->nc_dvpid) { if (ncache_isroot((KA_T)nc->nc_vp, cp)) *fp = 1; break; } if (!(lc = ncache_addr(nc->nc_dvpid))) { if (ncache_ckrootid((KA_T)nc->nc_vp, nc->nc_dvpid)) *fp = 1; break; } if (!(nc = lc->nc)) break; if (((nl = nc->nc_nlen) + 1) > rlen) break; *(cp - 1) = '/'; cp--; rlen--; (void) strncpy(cp - nl, nc->nc_name, nl); cp -= nl; rlen -= nl; } return(cp); } #endif /* DUV>=50100 && defined(HASNCACHE) */ lsof-4.86+dfsg.orig/dialects/du/dproto.h0000444000175000017500000000370106734217533020347 0ustar nicholasnicholas/* * dproto.h - DEC OSF/1, Digital UNIX, Tru64 UNIX function prototypes for lsof * * The _PROTOTYPE macro is defined in the common proto.h. */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: dproto.h,v 1.8 99/06/22 08:15:18 abe Exp $ */ _PROTOTYPE(extern void clr_flinfo,(void)); _PROTOTYPE(extern char *get_nlist_path,(int ap)); _PROTOTYPE(extern int is_file_named,(char *p, int cd)); _PROTOTYPE(extern struct l_vfs *readvfs,(KA_T vm)); #if defined(HASDCACHE) _PROTOTYPE(extern void clr_sect,(void)); #endif /* defined(HASDCACHE) */ #if defined(HASIPv6) _PROTOTYPE(extern struct hostent *gethostbyname2,(char *nm, int prot)); #endif /* defined(HASIPv6) */ #if defined(HASPRIVNMCACHE) _PROTOTYPE(extern int tag_to_path,(char *fs, mlBfTagT t2pb, int nl, char *nlb)); #endif /* defined(HASPRIVNMCACHE) */ #if defined(USELOCALREADDIR) _PROTOTYPE(extern int CloseDir,(DIR *dirp)); _PROTOTYPE(extern DIR *OpenDir,(char *dir)); _PROTOTYPE(extern struct DIRTYPE *ReadDir,(DIR *dirp)); #endif /* defined(USELOCALREADDIR) */ lsof-4.86+dfsg.orig/dialects/du/dlsof.h0000444000175000017500000002256110412046740020140 0ustar nicholasnicholas/* * dlsof.h - DEC OSF/1, Digital UNIX, Tru64 UNIX header file for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: dlsof.h,v 1.27 2006/03/27 20:40:59 abe Exp $ */ #if !defined(DU_LSOF_H) #define DU_LSOF_H 1 #include #include # if DUV<30000 || DUV>=50000 #include # endif /* DUV<30000 || DUV>=50000 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #undef queue #undef queue_t #define queue ___queue #define queue_t ___queue_t #include #undef ___queue #undef ___queue_t #define ___queue queue #define ___queue_t queue_t # if DUV<30000 #include #define KERNEL_FILE #include # endif /* DUV<30000 */ #include # if DUV>=50100 #include #define _SYS_USER_H_ #include #undef _SYS_USER_H_ # endif /* DUV>=50100 */ /* * The following header files need _KERNEL and KERNEL defined. Some * ugly #undef preparation is necessary. */ #define _KERNEL 1 #define KERNEL 1 #undef MACRO_END #undef PIPSIZ #undef i_forw #undef i_gen #undef i_gid #undef i_lock #undef i_mode #undef i_nlink #undef i_rdev #undef i_size #undef i_uid # if DUV>=30000 #undef m_data #undef m_next #include #include # if DUV<50000 #include # endif /* DUV<50000 */ # endif /* DUV>=30000 */ #undef calloc #define calloc ___calloc #undef exit #define exit ___exit #define pmap ___pmap #undef pt_entry_t #define pt_entry_t ___pt_entry_t #undef timer_t #define timer_t ___timer_t # if DUV>=50000 #include "du5_sys_malloc.h" #undef _SYS_WAIT_H_ /* allow to * #include while * _KERNEL is defined */ # endif /* DUV>=50000 */ # if DUV<40000 #include #undef ___calloc #define ___calloc calloc #undef ___exit #define ___exit exit #undef ___pt_entry_t #undef ___timer_t # endif /* DUV<40000 */ #include #include #include #include # if DUV>=40000 #undef ___calloc #define ___calloc calloc #undef ___exit #define ___exit exit # endif /* DUV>=40000 */ #include #undef u_comm #define u_comm uu_comm #include # if DUV>=30000 #undef u #endif /* DUV>=30000 */ #include #include # if DUV>=30000 #define quotactl __quotactl #include #undef quotactl # endif /* DUV>=30000 */ #include #include #include #include # if DUV>=40000 #include # else /* DUV<40000 */ #include # endif /* DUV>=40000 */ # if !defined(HASSPECNODE) /* * The spec_node is not defined in a distributed header file, but in * a kernel source file. */ struct spec_node { struct vnode *sn_vnode; struct vattr sn_vattr; }; # endif /* !defined(HASSPECNODE) */ # if ADVFSV<500 /* * This is an educated guess at an ADVFS/MSFS node for AdvFS versions below 5. * * Information that became available to me for AdvFS 5.0 and higher indicates * multiple adjacent structures are involved. Those definitions may be found * in dnode.c inside an ADVFSV #if|#endif block. */ struct advfsnode { # if ADVFSV<200 unsigned long d1[19]; # else /* ADVFSV>=200 */ # if ADVFSV<300 unsigned long d1[20]; # else /* ADVFSV>=300 */ # if ADVFSV<400 unsigned long d1[21]; # else /* ADVFSV>=400 */ unsigned long d1[17]; # endif /* ADVFSV>=400 */ # endif /* ADVFSV<300 */ # endif /* ADVFSV<200 */ ino_t a_number; int a_seq; unsigned long d3; int d4; dev_t a_rdev; unsigned long a_size; # if ADVFSV>=400 unsigned long d5[5]; int d6; int a_nlink; # endif /* ADVFSV>=400 */ }; # endif /* ADVFSV<500 */ # if defined(HASTAGTOPATH) /* * Define the structure used for passing inode and sequence numbers to the * ADVFS 4.0 and greater tag_to_path() -lmsfs function. * * This structure definition was provided by Dean Brock . */ typedef struct { int ml_ino; int ml_seq; } mlBfTagT; # endif /* defined(HASTAGTOPATH) */ # if DUV<50000 #define COMP_P void typedef unsigned long KA_T; # else /* DUV>=50000 */ #define COMP_P const void typedef off_t KA_T; #endif /* DUV<50000 */ #define DEVINCR 1024 /* device table malloc() increment */ #define DIRTYPE dirent #define KMEM "/dev/kmem" #define MALLOC_P char #define FREE_P MALLOC_P #define MALLOC_S size_t #define MAXSYSCMDL MAXCOMLEN /* max system command name length */ #define PNSIZ 5 /* /proc PID name component length */ #define PR_INOBIAS 64 /* /proc inode number bias */ #define PR_ROOTINO 2 /* /proc root inode number */ #define PROCMIN 3 /* processes that make a "good" scan */ #define PROCTRYLM 5 /* times to try to read proc table */ #define QSORT_P char #define READLEN_T int #define STRNCPY_L int #define U_SIZE sizeof(struct user) /* * Global storage definitions (including their structure definitions) */ extern int CloneMaj; extern struct file *Fileptr; #define FILEPTR Fileptr /* for process_file() in lib/prfp.c */ extern int HaveCloneMaj; extern int Kd; struct l_vfs { KA_T addr; /* kernel address */ fsid_t fsid; /* file system ID */ short type; /* type of file system */ char *dir; /* mounted directory */ char *fsname; /* file system name */ # if defined(HASFSINO) INODETYPE fs_ino; /* file system inode number */ # endif /* defined(HASFSINO) */ dev_t dev; /* device number */ dev_t rdev; /* raw device number */ struct l_vfs *next; /* forward link */ }; extern struct l_vfs *Lvfs; struct mounts { char *dir; /* directory (mounted on) */ char *fsname; /* file system * (symbolic links unresolved) */ char *fsnmres; /* file system * (symbolic links resolved) */ dev_t dev; /* directory st_dev */ dev_t rdev; /* directory st_rdev */ INODETYPE inode; /* directory st_ino */ mode_t mode; /* directory st_mode */ mode_t fs_mode; /* file system st_mode */ struct mounts *next; /* forward link */ fsid_t fsid; /* directory file system ID */ }; extern struct mounts *Mtab; #define X_NCACHE "ncache" #define X_NCSIZE "ncsize" #define NL_NAME n_name struct sfile { char *aname; /* argument file name */ char *name; /* file name (after readlink()) */ char *devnm; /* device name (optional) */ dev_t dev; /* device */ dev_t rdev; /* raw device */ u_short mode; /* S_IFMT mode bits from stat() */ int type; /* file type: 0 = file system * 1 = regular file */ INODETYPE i; /* inode number */ int f; /* file found flag */ struct sfile *next; /* forward link */ }; # if DUV>=30000 extern KA_T *Pa; /* kernel proc structure addresses */ # endif /* DUV>=30000 */ extern struct proc *Ps; /* local proc structures */ extern int Psn; /* entries in Pa[] and Ps[] */ extern int Vnmxp; /* * Definitions for dvch.c, isfn.c, and rdev.c */ #define CLONEMAJ CloneMaj /* clone major variable name */ #define DCACHE_CLR clr_sect /* function to clear clone cache * when reading the device cache * file fails */ #define HASDNAMLEN 1 /* DIRTYPE has d_namlen element */ #define HAS_STD_CLONE 1 /* has standard clone structure */ #define HAVECLONEMAJ HaveCloneMaj /* clone major variable status name */ /* * Definitions for rnam.c */ # if defined(HASNCACHE) && DUV<50100 #include #define NCACHE namecache /* kernel's structure name */ #define NCACHE_NM nc_name /* name in NCACHE */ #define NCACHE_NMLEN nc_nlen /* name length in NCACHE */ #define NCACHE_NODEADDR nc_vp /* node address in NCACHE */ #define NCACHE_PARADDR nc_dvp /* parent node address in NCACHE */ # if defined(HASNCVPID) #define NCACHE_NODEID nc_vpid /* node ID in NCACHE */ #define NCACHE_PARID nc_dvpid /* parent node ID in NCACHE */ # endif /* defined(HASNCVPID) */ # endif /* defined(HASNCACHE) && DUV<50100 */ #endif /* !DU_LSOF_H */ lsof-4.86+dfsg.orig/dialects/du/Mksrc0000555000175000017500000000107706705350051017667 0ustar nicholasnicholas#!/bin/sh # # Mksrc - make DEC OSF/1, Digital UNIX, Tru64 UNIX source files # # WARNING: This script assumes it is running from the main directory # of the lsof, version 4 distribution. # # One environment variable applies: # # LSOF_MKC is the method for creating the source files. # It defaults to "ln -s". A common alternative is "cp". # # $Id: Mksrc,v 1.3 99/04/15 06:40:21 abe Exp $ D=dialects/du L="ddev.c dfile.c dlsof.h dmnt.c dnode.c dproc.c dproto.h dsock.c dstore.c machine.h" for i in $L do rm -f $i $LSOF_MKC $D/$i $i echo "$LSOF_MKC $D/$i $i" done lsof-4.86+dfsg.orig/dialects/du/dnode.c0000444000175000017500000005025410412046742020117 0ustar nicholasnicholas/* * dnode.c - DEC OSF/1, Digital UNIX, Tru64 UNIX node functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dnode.c,v 1.23 2006/03/27 20:40:59 abe Exp $"; #endif #include "lsof.h" /* * Local definitions */ #if ADVFSV>=500 /* * AdvFS (MSFS) definitions for AdvFS version 5.0 and above. */ struct fs_stat { /* file system stat(2) info structure * for AdvFS 5.0 and above */ unsigned int num; /* node number */ unsigned int d1; mode_t d2; uid_t d3; gid_t d4; dev_t rdev; /* character or block device number */ off_t size; /* file size */ # if defined(__arch32__) unsigned int d5; # endif /* defined(__arch32__) */ time_t d6; int d7; time_t d8; int d9; time_t d10; int d11; unsigned int d12[5]; unsigned short nlink; /* link count */ }; struct fsContext { /* file system context for AdvFS 5.0 * and above */ short d1[2]; unsigned int d2[2]; long d3; int d4[2]; lock_data_t d5; long d6; simple_lock_data_t d7; unsigned int d8[2]; long d9; struct fs_stat st; /* file stats */ }; struct advfsnode { /* AdvFS (MSFS) node definition for * AdvFS 5.0 and above */ unsigned long d1; struct fsContext *a_con; /* context pointer */ }; #endif /* ADVFSV>=500 */ #if DUV>=50000 typedef struct cnode { /* CFS node structure definition for * Tru64 UNIX 5.0 and above */ udecl_simple_lock_data(, d1) unsigned int d2; time_t d3; unsigned long d4[3]; # if DUV<50100 int d5[2]; off_t d6; # endif /* DUV<50100 */ unsigned long d7; vattr_t c_attr; /* 96:Cached vnode attributes */ } cnode_t; #endif /* DUV>=50000 */ struct l_lock { /* local lock info */ struct eflock set; /* lock data */ struct l_lock *next; }; struct l_flinfo { /* local file lock info */ struct vnode *vp; /* identity of locked vnode */ struct l_lock *lp; /* lock information */ struct l_flinfo *next; }; #define L_FLINFO_HSZ 256 /* local file lock information hash * table size (must be a power of 2) */ #define L_FLINFO_HASH(va) (((int)((long)(va) * 31415L) >> 5) & (L_FLINFO_HSZ - 1)) /* * Local static variables */ static struct l_flinfo **Flinfo = (struct l_flinfo **)NULL; /* local file lock hash buckets */ static int FlinfoSt = 0; /* Flinfo[] load status */ /* * Local function prototypes */ _PROTOTYPE(static char isvlocked,(struct vnode *vp)); _PROTOTYPE(static int load_flinfo,(void)); _PROTOTYPE(static int readvnode,(KA_T va, struct vnode *v)); _PROTOTYPE(static void get_proc_sz,(struct procnode *pn)); /* * clr_flinfo() - clear local file lock table information */ void clr_flinfo() { struct l_lock *lf, *lfn; int i; struct l_flinfo *fi, *fin; if (!Flinfo && !FlinfoSt) return; for (i = 0; i < L_FLINFO_HSZ; i++) { if (!(fi = Flinfo[i])) continue; do { if ((lf = fi->lp)) { do { lfn = lf->next; (void) free((FREE_P *)lf); } while ((lf = lfn)); } fin = fi->next; (void) free((FREE_P *)fi); } while ((fi = fin)); Flinfo[i] = (struct l_flinfo *)NULL; } FlinfoSt = 0; } /* * get_proc_sz() - get size of /proc file system file */ static void get_proc_sz(pn) struct procnode *pn; /* pointer to procnode */ { struct vm_map m; struct proc *p; KA_T pa; int px; struct task t; /* * Search for procnode's process by PID. */ for (p = Ps, px = 0; px < Psn; p++, px++) { if (p->p_pid == pn->prc_pid) break; } if (px >= Psn) return; /* * Get the task structure address, then read the task structure. Set * the procnode's file size from the memory map information in the task * structure. */ # if DUV<30000 if (!(pa = (KA_T)p->task)) return; # else /* DUV>=30000 */ if (!(pa = Pa[px])) return; pa = (KA_T)((char *)pa - sizeof(t)); # endif /* DUV<30000 */ if (kread(pa, (char *)&t, sizeof(t))) return; if (!t.map || kread((KA_T)t.map, (char *)&m, sizeof(m))) return; Lf->sz = (SZOFFTYPE)m.vm_size; Lf->sz_def = 1; } /* * isvlocked() - is vnode locked? */ static char isvlocked(vp) struct vnode *vp; /* vnode's kernel address */ { struct l_flinfo *fp; int i, l; struct l_lock *lp; if (!Flinfo || !FlinfoSt) { if (!load_flinfo()) return(' '); } /* * Hash the vnode address and see if there's a local file lock information * structure for it. */ i = L_FLINFO_HASH(vp); for (fp = Flinfo[i]; fp; fp = fp->next) { if (fp->vp == vp) break; } if (!fp) return(' '); /* * Search the vnode's lock list for one held by this process. */ for (lp = fp->lp; lp; lp = lp->next) { if (lp->set.l_rsys || lp->set.l_pid != (pid_t)Lp->pid) continue; if (lp->set.l_whence == 0 && lp->set.l_start == 0 && ((lp->set.l_len == 0x8000000000000000) || (lp->set.l_len == 0x7fffffffffffffff))) l = 1; else l = 0; if (lp->set.l_type == F_WRLCK) return(l ? 'W' : 'w'); else if (lp->set.l_type == F_RDLCK) return(l ? 'R' : 'r'); return(' '); } return(' '); } /* * load_flinfo() - load local file lock information */ static int load_flinfo() { struct flino fi; struct filock fl; KA_T fif, fip, flf, flp; int i; struct l_flinfo *lfi; struct l_lock *ll; KA_T v; if (Flinfo && FlinfoSt) return(1); /* * Get kernel fids chain pointer. */ if (get_Nl_value("fids", Drive_Nl, &v) < 0 || !v || kread((KA_T)v, (char *)&fip, sizeof(fip))) return(0); /* * Define local hash buckets, if necessary. */ if (!Flinfo) { if (!(Flinfo = (struct l_flinfo **)calloc(sizeof(struct flinfo *), L_FLINFO_HSZ))) { (void) fprintf(stderr, "%s: can't allocate %d byte local lock hash buckets\n", Pn, L_FLINFO_HSZ * sizeof(struct l_flinfo *)); Exit(1); } } /* * Follow the fids chain. */ if (!(fif = fip)) return(1); /* * Follow the filock chain for this fid entry. * Duplicate it via the lock file lock information hash buckets. */ do { if (kread(fip, (char *)&fi, sizeof(fi))) return(0); if (!(flf = (KA_T)fi.fl_flck)) continue; /* * Allocate a local file lock information structure for this fid. */ if (!(lfi = (struct l_flinfo *)malloc(sizeof(struct l_flinfo)))) { (void) fprintf(stderr, "%s: no space for local vnode lock info struct\n", Pn); Exit(1); } lfi->vp = fi.vp; lfi->lp = (struct l_lock *)NULL; lfi->next = (struct l_flinfo *)NULL; /* * Follow the flino's filock chain, duplicating it locally. */ flp = flf; do { if (kread(flp, (char *)&fl, sizeof(fl))) break; /* * Allocate a local lock information structure and link it * to the chain for its vnode. */ if (!(ll = (struct l_lock *)malloc(sizeof(struct l_lock)))) { (void) fprintf(stderr, "%s: no space for local lock struct\n", Pn); Exit(1); } ll->next = lfi->lp; lfi->lp = ll; ll->set = fl.set; } while ((flp = (KA_T)fl.next) && flp != flf); /* * Link the file lock information structure to its hash bucket. */ i = L_FLINFO_HASH(lfi->vp); lfi->next = Flinfo[i]; Flinfo[i] = lfi; } while ((fip = (KA_T)fi.next) && fip != fif); FlinfoSt = 1; return(1); } /* * process_node() - process vnode */ void process_node(va) KA_T va; /* vnode kernel space address */ { struct advfsnode *a = (struct advfsnode *)NULL; struct cdnode *c = (struct cdnode *)NULL; dev_t dev, rdev; unsigned char devs = 0; unsigned char rdevs = 0; struct inode *i = (struct inode *)NULL; struct mfsnode *m = (struct mfsnode *)NULL; struct procnode *p = (struct procnode *)NULL; struct procfsid *pfi; struct rnode *r = (struct rnode *)NULL; struct spec_node *s = (struct spec_node *)NULL; struct spec_node sn; struct s5inode *s5 = (struct s5inode *)NULL; char *ty; enum vtype type; unsigned long ul; static struct vnode *v = (struct vnode *)NULL; struct l_vfs *vfs; #if DUV>=30000 struct fifonode *f = (struct fifonode *)NULL; struct fifonode fn; static struct vnode *fv = (struct vnode *)NULL; #endif /* DUV>=30000 */ #if DUV>=50000 cnode_t *cn = (cnode_t *)NULL; struct fsContext fsc; int fscs = 0; #endif /* DUV>=50000 */ /* * Read the vnode. */ if (!va) { enter_nm("no vnode address"); return; } if (!v) { /* * Allocate space for the Digital UNIX vnode. */ if (!(v = (struct vnode *)malloc(sizeof(struct vnode)-1+Vnmxp))) { (void) fprintf(stderr, "%s: no space for vnode buffer\n", Pn); Exit(1); } #if DUV>=30000 if (!(fv = (struct vnode *)malloc(sizeof(struct vnode)-1+Vnmxp))) { (void) fprintf(stderr, "%s: no space for fvnode buffer\n", Pn); Exit(1); } #endif /* DUV>=30000 */ } if (readvnode(va, v)) { enter_nm(Namech); return; } #if defined(HASNCACHE) Lf->na = va; # if defined(HASNCVPID) Lf->id = (unsigned long)v->v_id; # endif /* defined(HASNCVPID) */ #endif /* defined(HASNCACHE) */ #if defined(HASFSTRUCT) Lf->fsv |= FSV_NI; Lf->fna = va; #endif /* defined(HASFSTRUCT) */ /* * Get the mount structure and determine the vnode type. */ if (!v->v_mount) vfs = (struct l_vfs *)NULL; else vfs = readvfs((KA_T)v->v_mount); if (vfs) { switch (vfs->type) { case MOUNT_NFS: #if defined(MOUNT_NFS3) case MOUNT_NFS3: #endif /* defined(MOUNT_NFS3) */ Ntype = N_NFS; break; } if (Ntype == N_REGLR) { switch (v->v_type) { case VFIFO: Ntype = N_FIFO; break; } } } /* * Determine the lock type. */ if (FILEPTR && (FILEPTR->f_flag & FSHLOCK)) Lf->lock = 'R'; else if (FILEPTR && (FILEPTR->f_flag & FEXLOCK)) Lf->lock = 'W'; else Lf->lock = isvlocked((struct vnode *)va); /* * Define the specific Digital UNIX node pointer. */ #if DUV>=30000 if (Ntype == N_FIFO) { if (v->v_fifonode && !kread((KA_T)v->v_fifonode, (char *)&fn, sizeof(fn))) f = &fn; } #endif /* DUV>=30000 */ switch (v->v_tag) { case VT_CDFS: c = (struct cdnode *)v->v_data; break; #if DUV>=50000 case VT_CFS: cn = (cnode_t *)v->v_data; break; #endif /* DUV>=50000 */ case VT_MFS: m = (struct mfsnode *)v->v_data; break; case VT_NFS: r = (struct rnode *)v->v_data; break; case VT_NON: #if DUV<20000 if (v->v_specinfo && !kread((KA_T)v->v_specinfo, (char *)&sn, sizeof(sn))) s = &sn; else #else /* DUV>=20000 */ # if DUV>=30000 if (!f) # endif /* DUV>=30000 */ #endif /* DUV<20000 */ s = (struct spec_node *)v->v_data; break; case VT_PRFS: p = (struct procnode *)v->v_data; break; case VT_S5FS: s5 = (struct s5inode *)v->v_data; break; case VT_MSFS: a = (struct advfsnode *)v->v_data; #if ADVFSV>=500 if (a->a_con && !kread((KA_T)a->a_con, (char *)&fsc, sizeof(fsc))) fscs = 1; #endif /* ADVFSV>=500 */ break; case VT_UFS: i = (struct inode *)v->v_data; break; default: (void) snpf(Namech, Namechl, "unknown node type, v_tag=%d", v->v_tag); enter_nm(Namech); return; } /* * Get device and type for printing. */ type = v->v_type; if (a) { if (vfs && vfs->dev) { dev = vfs->dev; devs = 1; } if ((type == VCHR) || (type == VBLK)) { #if ADVFSV>=500 if (fscs) { rdev = fsc.st.rdev; rdevs = 1; } #else /* ADVFSV<500 */ rdev = a->a_rdev; rdevs = 1; #endif /* ADVFSV>=500 */ } } else if (c) { dev = c->cd_dev; devs = 1; } #if DUV>=50000 else if (cn) { if (vfs && vfs->dev) { dev = vfs->dev; devs = 1; } if ((type == VCHR) || (type == VBLK)) { if (cn->c_attr.va_mask & AT_RDEV) { rdev = cn->c_attr.va_rdev; rdevs = 1; } } } #endif /* DUV>=50000 */ else if (i) { if (i->i_dev) { dev = i->i_dev; devs = 1; } else if (vfs && vfs->dev) { dev = vfs->dev; devs = 1; } if ((type == VCHR) || (type == VBLK)) { rdev = i->i_din.di_db[0]; rdevs = 1; } } else if (r) { dev = r->r_attr.va_fsid; devs = 1; if ((type == VCHR) || (type == VBLK)) { rdev = r->r_attr.va_rdev; rdevs = 1; } } else if (s) { if (vfs && vfs->dev) dev = vfs->dev; else dev = DevDev; devs = 1; rdev = s->sn_vattr.va_rdev; rdevs = 1; if (!lkupdev(&dev, &rdev, 0, 0) && HaveCloneMaj) rdev = makedev(CloneMaj, GET_MAJ_DEV(rdev)); } else if (s5) { dev = s5->i_dev; devs = 1; } else if (f) { if (vfs && vfs->dev) { dev = vfs->dev; devs = 1; } } /* * Obtain the inode number. */ if (a) { #if ADVFSV>=500 if (fscs) { Lf->inode = (INODETYPE)fsc.st.num; Lf->inp_ty = 1; } #else /* ADVFSV<500 */ Lf->inode = (INODETYPE)a->a_number; Lf->inp_ty = 1; #endif /* ADVFSV>=500 */ #if defined(HASTAGTOPATH) /* * Record the Digital UNIX 4.0 or greater, ADVFS 4.0 or greater * ADVFS sequence number for later use with tag_to_path(). */ Lf->advfs_seq = a->a_seq; Lf->advfs_seq_stat = 1; #endif /* defined(HASTAGTOPATH) */ } else if (c) { Lf->inode = (INODETYPE)c->cd_number; Lf->inp_ty = 1; } #if DUV>=50000 else if (cn) { if (cn->c_attr.va_mask & AT_NODEID) { Lf->inode = (INODETYPE)cn->c_attr.va_fileid; Lf->inp_ty = 1; } } #endif /* DUV>=50000 */ else if (i) { Lf->inode = (INODETYPE)i->i_number; Lf->inp_ty = 1; } else if (p) { Lf->inode = (INODETYPE)((type == VDIR) ? PR_ROOTINO : p->prc_pid + PR_INOBIAS); Lf->inp_ty = 1; } else if (r) { Lf->inode = (INODETYPE)r->r_attr.va_fileid; Lf->inp_ty = 1; } else if (s5) { Lf->inode = (INODETYPE)s5->i_number; Lf->inp_ty = 1; } #if DUV>=30000 else if (f) { Lf->inode = (INODETYPE)f->fn_fileid; Lf->inp_ty = 1; } #endif /* DUV>=30000 */ /* * Obtain the file size. */ if (Foffset) { Lf->off_def = 1; #if DUV>=30000 if (Ntype == N_FIFO && f) Lf->off = (unsigned long) (Lf->access == 'r') ? f->fn_rptr : f->fn_wptr; #endif /* DUV>=30000 */ } else { switch (Ntype) { case N_FIFO: #if DUV>=30000 if (f) { Lf->sz = (SZOFFTYPE)f->fn_size; Lf->sz_def = 1; } else if (!Fsize) Lf->off_def = 1; #else /* DUV<30000 */ if (!Fsize) Lf->off_def = 1; #endif /* DUV>=30000 */ break; case N_NFS: if (r) { Lf->sz = (SZOFFTYPE)r->r_attr.va_qsize; Lf->sz_def = 1; } break; case N_REGLR: if (type == VREG || type == VDIR) { if (a) { #if ADVFSV>=500 if (fscs) { Lf->sz = (SZOFFTYPE)fsc.st.size; Lf->sz_def = 1; } #else /* ADVFSV<500 */ Lf->sz = (SZOFFTYPE)a->a_size; Lf->sz_def = 1; #endif /* ADVFSV>=500 */ } else if (c) { Lf->sz = (SZOFFTYPE)c->cd_size; Lf->sz_def = 1; } #if DUV>=50000 else if (cn) { if (cn->c_attr.va_mask & AT_SIZE) { Lf->sz = (SZOFFTYPE)cn->c_attr.va_qsize; Lf->sz_def = 1; } } #endif /* DUV>=50000 */ else if (i) { Lf->sz = (SZOFFTYPE)i->i_din.di_qsize; Lf->sz_def = 1; } else if (m) { Lf->sz = (SZOFFTYPE)m->mfs_size; Lf->sz_def = 1; } else if (p) { if (type != VDIR) get_proc_sz(p); } else if (s5) { Lf->sz = (SZOFFTYPE)s5->i_size; Lf->sz_def = 1; } } else if ((type == VBLK) || (type == VCHR) && !Fsize) Lf->off_def = 1; } } if (Fnlink) { switch(Ntype) { case N_FIFO: /* no link count */ break; case N_NFS: Lf->nlink = (long)r->r_attr.va_nlink; Lf->nlink_def = 1; break; case N_REGLR: # if ADVFSV>=400 if (a) { #if ADVFSV>=500 if (fscs) { Lf->nlink = (long)fsc.st.nlink; Lf->nlink_def = 1; } #else /* ADVFSV<500 */ Lf->nlink = (long)a->a_nlink; Lf->nlink_def = 1; #endif /* ADVFSV>=500 */ break; } # endif /* ADVFSV>=400 */ if (c) { Lf->nlink = (long)c->cd_nlink; Lf->nlink_def = 1; } #if DUV>=50000 else if (cn) { if (cn->c_attr.va_mask & AT_NLINK) { Lf->nlink = (long)cn->c_attr.va_nlink; Lf->nlink_def = 1; } } #endif /* DUV>=50000 */ else if (i) { Lf->nlink = (long)i->i_din.di_nlink; Lf->nlink_def = 1; } else if (s5) { Lf->nlink = (long)s5->i_nlink; Lf->nlink_def = 1; } } if (Nlink && Lf->nlink_def && (Lf->nlink < Nlink)) Lf->sf |= SELNLINK; } /* * Record an NFS file selection. */ if (Ntype == N_NFS && Fnfs) Lf->sf |= SELNFS; /* * Save the device numbers and their states. * * Format the vnode type, and possibly the device name. */ Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; switch (type) { case VNON: ty ="VNON"; break; case VREG: case VDIR: ty = (type == VREG) ? "VREG" : "VDIR"; break; case VBLK: ty = "VBLK"; Ntype = N_BLK; break; case VCHR: ty = "VCHR"; Ntype = N_CHR; break; case VLNK: ty = "VLNK"; break; #if defined(VSOCK) case VSOCK: ty = "SOCK"; break; #endif /* defined(VSOCK) */ case VBAD: ty = "VBAD"; break; case VFIFO: ty = "FIFO"; #if DUV>=30000 if ((!devs || !dev) && f) { vfs = (struct l_vfs *)NULL; devs = Lf->dev_def = 0; ul = (unsigned long)v->v_fifonode; enter_dev_ch(print_kptr((KA_T)(ul&0xffffffff),(char *)NULL,0)); } #endif /* DUV>=30000 */ break; default: (void) snpf(Lf->type, sizeof(Lf->type), "%04o", (type & 0xfff)); ty = (char *)NULL; } if (ty) (void) snpf(Lf->type, sizeof(Lf->type), "%s", ty); Lf->ntype = Ntype; /* * Save the file system names. */ if (vfs) { if (vfs->dir && *vfs->dir) Lf->fsdir = vfs->dir; if (vfs->fsname && *vfs->fsname) Lf->fsdev = vfs->fsname; #if defined(HASFSINO) if (vfs->fs_ino) Lf->fs_ino = vfs->fs_ino; #endif /* defined(HASFSINO) */ } /* * Handle some special cases: * * ioctl(fd, TIOCNOTTY) files; * FIFOs (Digital UNIX V3.0 and higher); * memory node files; * /proc files. */ if (type == VBAD) (void) snpf(Namech, Namechl, "(revoked)"); if (m) { devs = Lf->dev_def = Lf->rdev_def = rdevs = 0; (void) snpf(Namech, Namechl, "%#x", m->mfs_baseoff); (void) enter_dev_ch("memory"); } else if (p) { devs = Lf->dev_def = Lf->rdev_def = rdevs = 0; if (type != VDIR) (void) snpf(Namech, Namechl, "/proc/%d", p->prc_pid); else (void) snpf(Namech, Namechl, "/proc"); } #if defined(HASBLKDEV) /* * If this is a VBLK file and it's missing an inode number, try to * supply one. */ if ((Lf->inp_ty == 0) && (type == VBLK)) find_bl_ino(); #endif /* defined(HASBLKDEV) */ /* * If this is a VCHR file and it's missing an inode number, try to * supply one. */ if ((Lf->inp_ty == 0) && (type == VCHR)) find_ch_ino(); /* * Test for specified file. */ if (p) { if (Procsrch) { Procfind = 1; Lf->sf |= SELNM; } else { for (pfi = Procfsid; pfi; pfi = pfi->next) { if ((pfi->pid && pfi->pid == p->prc_pid) #if defined(HASPINODEN) || (Lf->inp_ty == 1 && pfi->inode == Lf->inode) #endif /* defined(HASPINODEN) */ ) { pfi->f = 1; Lf->sf |= SELNM; break; } } } } else { if (Sfile && is_file_named((char *)NULL, (type == VCHR) ? 1 : 0)) Lf->sf |= SELNM; } /* * Enter name characters. */ if (Namech[0]) enter_nm(Namech); } /* * readvnode() - read vnode */ static int readvnode(va, v) KA_T va; /* vnode kernel space address */ struct vnode *v; /* vnode buffer pointer */ { if (kread((KA_T)va, (char *)v, sizeof(struct vnode) - 1 + Vnmxp)) { (void) snpf(Namech, Namechl, "can't read vnode at %s", print_kptr(va, (char *)NULL, 0)); return(1); } return(0); } lsof-4.86+dfsg.orig/dialects/du/dfile.c0000444000175000017500000000614307336216061020113 0ustar nicholasnicholas/* * dfile.c - DEC OSF/1, Digital UNIX, Tru64 UNIX file processing functions for * lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dfile.c,v 1.12 2001/08/14 12:40:12 abe Exp $"; #endif #include "lsof.h" #if defined(HASIPv6) /* * gethostbyname2() -- an RFC2133-compatible get-host-by-name-two function * to get AF_INET and AF_INET6 addresses from host names, * using the RFC2553-compatible getipnodebyname() function */ extern struct hostent * gethostbyname2(nm, prot) char *nm; /* host name */ int prot; /* protocol -- AF_INET or AF_INET6 */ { int err; static struct hostent *hep = (struct hostent *)NULL; if (hep) (void) freehostent(hep); hep = getipnodebyname(nm, prot, 0, &err); return(hep); } #endif /* defined(HASIPv6) */ #if defined(HASPRIVNMCACHE) /* * print_advfs_path() - print an ADVFS file path * * return: 1 if path printed * * This code was provided by Dean Brock . * * This function is called by the name HASPRIVNMCACHE from printname(). */ int print_advfs_path(lf) struct lfile *lf; /* file whose name is to be printed */ { char buf[MAXPATHLEN+1]; mlBfTagT t2pb; /* * Print any non-NULL path returned by tag_to_path() for ADVFS files that * have sequence and inode numbers. */ if (!lf->advfs_seq_stat || lf->inp_ty != 1 || !lf->fsdir || !*lf->fsdir) return(0); t2pb.ml_ino = (int)lf->inode; t2pb.ml_seq = lf->advfs_seq; if (tag_to_path(lf->fsdir, t2pb, MAXPATHLEN, buf) || !*buf) return(0); buf[MAXPATHLEN] = '\0'; safestrprt((buf[0] == '/' && buf[1] == '/') ? &buf[1] : buf, stdout, 0); return(1); } #endif /* defined(HASPRIVNMCACHE) */ /* * print_dev() - print device */ char * print_dev(lf, dev) struct lfile *lf; /* file whose device is to be printed */ dev_t *dev; /* device to be printed */ { static char buf[128]; if (GET_MIN_DEV(*dev) > 9999999) (void) snpf(buf, sizeof(buf), "%d,%#x", GET_MAJ_DEV(*dev), GET_MIN_DEV(*dev)); else (void) snpf(buf, sizeof(buf), "%d,%d", GET_MAJ_DEV(*dev), GET_MIN_DEV(*dev)); return(buf); } lsof-4.86+dfsg.orig/dialects/du/dmnt.c0000444000175000017500000001677410275734405020010 0ustar nicholasnicholas/* * dmnt.c - DEC OSF/1, Digital UNIX, Tru64 UNIX mount support functions for * lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dmnt.c,v 1.11 2005/08/08 19:56:44 abe Exp $"; #endif #include "lsof.h" #undef KERNEL #include /* this defines char *mnt_names[] */ /* * Local static definitions */ static struct mounts *Lmi = (struct mounts *)NULL; /* local mount info */ static int Lmist = 0; /* Lmi status */ /* * readmnt() - read mount table */ struct mounts * readmnt() { char *dn = (char *)NULL; char *ln; struct statfs *mb; struct mounts *mtp; int n; int procfs = 0; struct stat sb; if (Lmi || Lmist) return(Lmi); /* * Access mount information. */ if ((n = getmntinfo(&mb, MNT_NOWAIT)) <= 0) { (void) fprintf(stderr, "%s: no mount information\n", Pn); return(0); } /* * Read mount information. */ for (; n; n--, mb++) { if (mb->f_type == MOUNT_NONE || mb->f_type >= MOUNT_MAXTYPE) continue; /* * Avoid file systems under automounter control if they're not * currently mounted. */ if (mb->f_type == MOUNT_NFS) { /* * The mount-from name of some unmounted file systems under * automounter control end with ``:(pid):'' -- where * is the PID of the automounter process. */ if ((ln = strchr(mb->f_mntfromname, ':'))) { if (strncmp(ln+1, "(pid", 4) == 0 && isdigit(*(ln+5))) { for (ln += 6; *ln && isdigit(*ln); ln++) { ; } if (*ln == ')' && *(ln+1) == '\0') continue; } } /* * Another automounter mount-from name form is "amd:" -- * where is the PID of the automounter process. */ if (strncmp(mb->f_mntfromname, "amd:", 4) == 0 && isdigit(mb->f_mntfromname[4])) { ln = &mb->f_mntfromname[5]; while (*ln && isdigit(*ln)) { ln++; } if (!*ln || (*ln == ':' && *(ln+1) == '\0')) continue; } } /* * Interpolate a possible symbolic directory link. */ if (dn) (void) free((FREE_P *)dn); if (!(dn = mkstrcpy(mb->f_mntonname, (MALLOC_S *)NULL))) { no_space_for_mount: (void) fprintf(stderr, "%s: no space for mount at ", Pn); safestrprt(mb->f_mntonname, stderr, 0); (void) fprintf(stderr, " ("); safestrprt(mb->f_mntfromname, stderr, 0); (void) fprintf(stderr, ")\n"); Exit(1); } if (!(ln = Readlink(dn))) { if (!Fwarn) { (void) fprintf(stderr, " Output information may be incomplete.\n"); } continue; } if (ln != dn) { (void) free((FREE_P *)dn); dn = ln; } if (*dn != '/') continue; /* * Stat() the directory. */ if (statsafely(dn, &sb)) { if (!Fwarn) { (void) fprintf(stderr, "%s: WARNING: can't stat() %s file system: ", Pn, mnt_names[mb->f_type]); safestrprt(mb->f_mntonname, stderr, 1); (void) fprintf(stderr, " Output information may be incomplete.\n"); } if (mb->f_type != MOUNT_PROCFS #if !defined(ADVFSV) || ADVFSV<400 && mb->f_type != MOUNT_MSFS #endif /* !defined(ADVFSV) || ADVFSV<400 */ ) { memset((char *)&sb, 0, sizeof(sb)); sb.st_dev = (dev_t)mb->f_fsid.val[0]; sb.st_mode = S_IFDIR | 0777; if (!Fwarn) { (void) fprintf(stderr, " assuming dev=%x from mount table\n", sb.st_dev); } } else continue; } /* * Allocate and fill a local mount structure. */ if (!(mtp = (struct mounts *)malloc(sizeof(struct mounts)))) goto no_space_for_mount; mtp->dir = dn; dn = (char *)NULL; mtp->dev = sb.st_dev; mtp->fsid = mb->f_fsid; mtp->inode = (INODETYPE)sb.st_ino; mtp->mode = sb.st_mode; mtp->next = Lmi; mtp->rdev = sb.st_rdev; /* * Interpolate a possible file system (mounted-on) device path. */ if (!(dn = mkstrcpy(mb->f_mntfromname, (MALLOC_S *)NULL))) goto no_space_for_mount; mtp->fsname = dn; ln = Readlink(dn); dn = (char *)NULL; /* * Stat the file system (mounted-on) name and add file sysem * information to the local mount table. */ if (!ln || statsafely(ln, &sb)) sb.st_mode = 0; mtp->fsnmres = ln; mtp->fs_mode = sb.st_mode; Lmi = mtp; if (mb->f_type == MOUNT_PROCFS) { /* * Save information on exactly one procfs file system. */ if (procfs) Mtprocfs = (struct mounts *)NULL; else { procfs = 1; Mtprocfs = mtp; } } } /* * Clean up and return the local mount info table address. */ if (dn) (void) free((FREE_P *)dn); Lmist = 1; return(Lmi); } /* * readvfs() - read vfs structure */ struct l_vfs * readvfs(vm) KA_T vm; /* mount address in vnode */ { struct mount m; struct l_vfs *vp; fsid_t f; struct mounts *mp; #if DUV>=40000 int bl; char fb[MAX_MNT_PATHLEN+1]; char ob[MAX_MNT_PATHLEN+1]; #endif /* DUV>=40000 */ /* * Search for match on existing entry. */ for (vp = Lvfs; vp; vp = vp->next) { if (vm == vp->addr) return(vp); } /* * Read the (new) mount structure, allocate a local entry, and fill it. */ if (kread((KA_T)vm, (char *)&m, sizeof(m)) != 0) return((struct l_vfs *)NULL); if (!(vp = (struct l_vfs *)malloc(sizeof(struct l_vfs)))) { (void) fprintf(stderr, "%s: PID %d, no space for vfs\n", Pn, Lp->pid); Exit(1); } #if DUV<40000 if (!(vp->dir = mkstrcpy(m.m_stat.f_mntonname, (MALLOC_S *)NULL)) || !(vp->fsname = mkstrcpy(m.m_stat.f_mntfromname, (MALLOC_S *)NULL))) #else /* DUV>=40000 */ bl = sizeof(ob) - 1; if (!m.m_stat.f_mntonname || kread((KA_T)m.m_stat.f_mntonname, ob, bl)) bl = 0; ob[bl] = '\0'; bl = sizeof(fb) - 1; if (!m.m_stat.f_mntfromname || kread((KA_T)m.m_stat.f_mntfromname, fb, bl)) bl = 0; fb[bl] = '\0'; if (!(vp->dir = mkstrcpy(ob, (MALLOC_S *)NULL)) || !(vp->fsname = mkstrcpy(fb, (MALLOC_S *)NULL))) #endif /* DUV<40000 */ { (void) fprintf(stderr, "%s: PID %d, no space for mount names\n", Pn, Lp->pid); Exit(1); } vp->addr = vm; vp->fsid = m.m_stat.f_fsid; vp->type = m.m_stat.f_type; #if defined(HASFSINO) vp->fs_ino = 0; #endif /* defined(HASFSINO) */ vp->next = Lvfs; Lvfs = vp; /* * Derive the device and raw device numbers from a search for the * file system ID in the local mount table. */ vp->dev = vp->rdev = 0; for (f = vp->fsid, mp = readmnt(); mp; mp = mp->next) { if (f.val[0] == mp->fsid.val[0] && f.val[1] == mp->fsid.val[1]) { vp->dev = mp->dev; vp->rdev = mp->rdev; #if defined(HASFSINO) vp->fs_ino = mp->inode; #endif /* defined(HASFSINO) */ break; } } return(vp); } lsof-4.86+dfsg.orig/dialects/du/machine.h0000444000175000017500000004114111424323052020426 0ustar nicholasnicholas/* * machine.h - DEC OSF/1, Digital UNIX, Tru64 UNIX definitions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: machine.h,v 1.42 2010/07/29 16:02:47 abe Exp $ */ #if !defined(LSOF_MACHINE_H) #define LSOF_MACHINE_H 1 #include #define _KERNEL 1 #include #if DUV>=50000 #include #include #endif /* DUV>=50000 */ #undef _KERNEL #include /* * CAN_USE_CLNT_CREATE is defined for those dialects where RPC clnt_create() * can be used to obtain a CLIENT handle in lieu of clnttcp_create(). */ #if DUV>=40000 #define CAN_USE_CLNT_CREATE 1 #endif /* DUV>=40000 */ /* * DEVDEV_PATH defines the path to the directory that contains device * nodes. */ #define DEVDEV_PATH "/dev" /* * GET_MAX_FD is defined for those dialects that provide a function other than * getdtablesize() to obtain the maximum file descriptor number plus one. */ /* #define GET_MAX_FD ? */ /* * HASAOPT is defined for those dialects that have AFS support; it specifies * that the default path to an alternate AFS kernel name list file may be * supplied with the -A option. */ /* #define HASAOPT 1 */ /* * HASBLKDEV is defined for those dialects that want block device information * recorded in BDevtp[]. * * NOWARNBLKDEV suppresses warnings about no block devices for Tru64 UNIX 5.0 * and above. */ #define HASBLKDEV 1 #if DUV>=50000 #define NOWARNBLKDEV 1 #endif /* DUV>=50000 */ /* * HASDCACHE is defined for those dialects that support a device cache * file. * * HASENVDC defined the name of an environment variable that contains the * device cache file path. The HASENVDC environment variable is ignored when * the lsof process is setuid(root) or its real UID is 0. * * HASPERSDC defines the format for the last component of a personal device * cache file path. The first will be the home directory of the real UID that * executes lsof. * * HASPERSDCPATH defines the environment variable whose value is the middle * component of the personal device cache file path. The middle component * follows the home directory and precedes the results of applying HASPERSDC. * The HASPERSDCPATH environment variable is ignored when the lsof process is * setuid(root) or its real UID is 0. * * HASSYSDC defines a public device cache file path. When it's defined, it's * used as the path from which to read the device cache. * * Consult the 00DCACHE and 00FAQ files of the lsof distribution for more * information on device cache file path construction. */ #define HASDCACHE 1 #define HASENVDC "LSOFDEVCACHE" #define HASPERSDC "%h/%p.lsof_%L" #define HASPERSDCPATH "LSOFPERSDCPATH" /* #define HASSYSDC "/your/choice/of/path" */ /* * HASCDRNODE is defined for those dialects that have CD-ROM nodes. */ /* #define HASCDRNODE 1 */ /* * HASFIFONODE is defined for those dialects that have FIFO nodes. */ /* #define HASFIFONODE 1 */ /* * HASFSINO is defined for those dialects that have the file system * inode element, fs_ino, in the lfile structure definition in lsof.h. */ #define HASFSINO 1 /* * HASFSTRUCT is defined if the dialect has a file structure. * * FSV_DEFAULT defines the default set of file structure values to list. * It defaults to zero (0), but may be made up of a combination of the * FSV_* symbols from lsof.h. * * HASNOFSADDR -- has no file structure address * HASNOFSFLAGS -- has no file structure flags * HASNOFSCOUNT -- has no file structure count * HASNOFSNADDR -- has no file structure node address */ #define HASFSTRUCT 1 /* #define FSV_DEFAULT FSV_? | FSV_? | FSV_? */ /* #define HASNOFSADDR 1 has no file structure address */ /* #define HASNOFSFLAGS 1 has no file structure flags */ /* #define HASNOFSCOUNT 1 has no file structure count */ /* #define HASNOFSNADDR 1 has no file structure node address */ /* * HASGNODE is defined for those dialects that have gnodes. */ /* #define HASGNODE 1 */ /* * HASHSNODE is defined for those dialects that have High Sierra nodes. */ /* #define HASHSNODE 1 */ /* * HASINODE is defined for those dialects that have inodes and wish to * use readinode() from node.c. */ #define HASINODE 1 /* * HASINTSIGNAL is defined for those dialects whose signal function returns * an int. */ /* #define HASINTSIGNAL 1 */ /* * HASKERNIDCK is defined for those dialects that support the comparison of * the build to running kernel identity. */ #define HASKERNIDCK 1 /* * HASKOPT is defined for those dialects that support the -k option of * reading the kernel's name list from an optional file. */ #define HASKOPT 1 /* * HASLFILEADD is defined for those dialects that need additional elements * in struct lfile. The HASLFILEADD definition is a macro that defines * them. If any of the additional elements need to be preset in the * alloc_lfile() function of proc.c, the SETLFILEADD macro may be defined * to do that. * * If any additional elements need to be cleared in alloc_lfile() or in the * free_proc() function of proc.c, the CLRLFILEADD macro may be defined to * do that. Note that CLRLFILEADD takes one argument, the pointer to the * lfile struct. The CLRLFILEADD macro is expected to expand to statements * that are complete -- i.e., have terminating semi-colons -- so the macro is * called without a terminating semicolon by proc.c. * * The HASXOPT definition may be used to select the conditions under which * private lfile elements are used. */ #if defined(HASTAGTOPATH) #define HASLFILEADD int advfs_seq; unsigned char advfs_seq_stat; /* #define CLRLFILEADD(lf) (lf)->... = (type)NULL; */ #define SETLFILEADD Lf->advfs_seq_stat = 0; #endif /* defined(HASTAGTOPATH) */ /* * HASMNTSTAT indicates the dialect supports the mount stat(2) result option * in its l_vfs and mounts structures. */ /* #define HASMNTSTAT 1 */ /* * HASMNTSUP is defined for those dialects that support the mount supplement * option. */ /* #define HASMNTSUP 1 */ /* * HASMOPT is defined for those dialects that support the reading of * kernel memory from an alternate file. */ #define HASMOPT 1 /* * HASNCACHE is defined for those dialects that have a kernel name cache * that lsof can search. A value of 1 directs printname() to prefix the * cache value with the file system directory name; 2, avoid the prefix. * * NCACHELDPFX is a set of C commands to execute before calling ncache_load(). * * NCACHELDSFX is a set of C commands to execute after calling ncache_load(). */ #define HASNCACHE 1 /* #define NCACHELDPFX ??? */ /* #define NCACHELDSFX ??? */ /* * HASNLIST is defined for those dialects that use nlist() to acccess kernel symbols. */ #define HASNLIST 1 /* * HASPIPEFN is defined for those dialects that have a special function to * process DTYPE_PIPE file structure entries. Its value is the name of the * function. * * NOTE: don't forget to define a prototype for this function in dproto.h. */ /* #define HASPIPEFN process_pipe? */ /* * HASPIPENODE is defined for those dialects that have pipe nodes. */ /* #define HASPIPENODE 1 */ /* * HASPMAPENABLED is defined when the reporting of portmapper registration * info is enabled by default. */ /* #define HASPMAPENABLED 1 */ /* * HASPPID is defined for those dialects that support identification of * the parent process IDentifier (PPID) of a process. */ #define HASPPID 1 /* * HASPRINTDEV, HASPRINTINO, HASPRINTNM, HASPRINTOFF, and HASPRINTSZ * define private dialect-specific functions for printing DEVice numbers, * INOde numbers, NaMes, file OFFsets, and file SiZes. The functions are * called from print_file(). */ #define HASPRINTDEV print_dev /* #define HASPRINTINO print_ino? */ /* #define HASPRINTNM print_nm? */ /* #define HASPRINTOFF print_off? */ /* #define HASPRINTSZ print_sz? */ /* * HASPRIVFILETYPE and PRIVFILETYPE are defined for dialects that have a * file structure type that isn't defined by a DTYPE_* symbol. They are * used in lib/prfp.c to select the type's processing. * * PRIVFILETYPE is the definition of the f_type value in the file struct. * * HASPRIVFILETYPE is the name of the processing function. */ /* #define HASPRIVFILETYPE process_shmf? */ /* #define PRIVFILETYPE ?? */ /* * HASPRIVNMCACHE is defined for dialects that have a private method for * printing cached NAME column values for some files. HASPRIVNAMECACHE * is defined to be the name of the function. * * The function takes one argument, a struct lfile pointer to the file, and * returns non-zero if it prints a name to stdout. */ #if defined(HASTAGTOPATH) #define HASPRIVNMCACHE print_advfs_path #endif /* defined(HASTAGTOPATH) */ /* * HASPRIVPRIPP is defined for dialects that have a private function for * printing IP protocol names. When HASPRIVPRIPP isn't defined, the * IP protocol name printing function defaults to printiprto(). */ /* #define HASPRIVPRIPP 1 */ /* * HASPROCFS is defined for those dialects that have a proc file system -- * usually /proc and usually in SYSV4 derivatives. * * HASFSTYPE is defined as 1 for those systems that have a file system type * string, st_fstype, in the stat() buffer; 2, for those systems that have a * file system type integer in the stat() buffer, named MOUNTS_STAT_FSTYPE; * 0, for systems whose stat(2) structure has no file system type member. The * additional symbols MOUNTS_FSTYPE, RMNT_FSTYPE, and RMNT_STAT_FSTYPE may be * defined in dlsof.h to direct how the readmnt() function in lib/rmnt.c * preserves these stat(2) and getmntent(3) buffer values in the local mounts * structure. * * The defined value is the string that names the file system type. * * The HASPROCFS definition usually must be accompanied by the HASFSTYPE * definition and the providing of an fstype element in the local mounts * structure (defined in dlsof.h). * * The HASPROCFS definition may be accompanied by the HASPINODEN definition. * HASPINODEN specifies that searching for files in HASPROCFS is to be done * by inode number. */ #define HASPROCFS "proc" /* #define HASFSTYPE 1 */ #define HASPINODEN 1 /* * HASRNODE is defined for those dialects that have rnodes. */ /* #define HASRNODE 1 */ /* * Define HASSECURITY to restrict the listing of all open files to the * root user. When HASSECURITY is defined, the non-root user may list * only files whose processes have the same user ID as the real user ID * (the one that its user logged on with) of the lsof process. */ /* #define HASSECURITY 1 */ /* * If HASSECURITY is defined, define HASNOSOCKSECURITY to allow users * restricted by HASSECURITY to list any open socket files, provide their * listing is selected by the "-i" option. */ /* #define HASNOSOCKSECURITY 1 */ /* * HASSETLOCALE is defined for those dialects that have and * setlocale(). * * If the dialect also has wide character support for language locales, * HASWIDECHAR activates lsof's wide character support and WIDECHARINCL * defines the header file (if any) that must be #include'd to use the * mblen() and mbtowc() functions. */ #define HASSETLOCALE 1 # if DUV>=40000 #define HASWIDECHAR 1 # endif /* DUV>=40000 */ /* #define WIDECHARINCL */ /* * HASSNODE is defined for those dialects that have snodes. */ /* #define HASSNODE 1 */ /* * HASTASKS is defined for those dialects that have task reporting support. */ /* #define HASTASKS 1 */ /* * HASSOOPT, HASSOSTATE and HASTCPOPT define the availability of information * on socket options (SO_* symbols), socket states (SS_* symbols) and TCP * options. */ #define HASSOOPT 1 /* has socket option information */ #define HASSOSTATE 1 /* has socket state information */ #define HASTCPOPT 1 /* has TCP options or flags */ /* * Define HASSPECDEVD to be the name of a function that handles the results * of a successful stat(2) of a file name argument. * * For example, HASSPECDEVD() for Darwin makes sure that st_dev is set to * what stat("/dev") returns -- i.e., what's in DevDev. * * The function takes two arguments: * * 1: pointer to the full path name of file * 2: pointer to the stat(2) result * * The function returns void. */ /* #define HASSPECDEVD process_dev_stat */ /* * HASSTREAMS is defined for those dialects that support streams. */ /* #define HASSTREAMS 1 */ /* * HASTCPTPIQ is defined for dialects where it is possible to report the * TCP/TPI Recv-Q and Send-Q values produced by netstat. */ #define HASTCPTPIQ 1 /* * HASTCPTPIW is defined for dialects where it is possible to report the * TCP/TPI send and receive window sizes produced by netstat. */ /* #define HASTCPTPIW 1 */ /* * HASTMPNODE is defined for those dialects that have tmpnodes. */ /* #define HASTMPNODE 1 */ /* * HASVNODE is defined for those dialects that use the Sun virtual file system * node, the vnode. BSD derivatives usually do; System V derivatives prior to * R4 usually don't. * * Even though Digital UNIX has vnodes, we don't define HASVNODE, because * private vnode processing is required. (See the readvnode() function * in dnode.c.) */ /* #define HASVNODE 1 */ /* * HASXOPT is defined for those dialects that have an X option. It * defines the text for the usage display. HASXOPT_VALUE defines the * option's default binary value -- 0 or 1. */ /* #define HASXOPT "help text for X option" */ /* #define HASXOPT_VALUE 1 */ /* * INODETYPE and INODEPSPEC define the internal node number type and its * printf specification modifier. These need not be defined and lsof.h * can be allowed to define defaults. * * These are defined here, because they must be used in dlsof.h. */ /* #define INODETYPE unsigned long long */ /* inode number internal storage type */ /* #define INODEPSPEC "ll" * INODETYPE printf specification * modifier */ /* * UID_ARG defines the size of a User ID number when it is passed * as a function argument. */ #define UID_ARG uid_t /* * Each USE_LIB_ is defined for dialects that use the * in the lsof library. * * Note: other definitions and operations may be required to condition the * library function source code. They may be found in the dialect dlsof.h * header files. */ #define USE_LIB_CKKV 1 /* ckkv.c */ /* #define USE_LIB_COMPLETEVFS 1 cvfs.c */ #define USE_LIB_FIND_CH_INO 1 /* fino.c */ #define USE_LIB_IS_FILE_NAMED 1 /* isfn.c */ #define USE_LIB_LKUPDEV 1 /* lkud.c */ /* #define USE_LIB_PRINTDEVNAME 1 pdvn.c */ #define USE_LIB_PROCESS_FILE 1 /* prfp.c */ #define USE_LIB_PRINT_TCPTPI 1 /* ptti.c */ /* #define USE_LIB_READDEV 1 rdev.c */ /* #define USE_LIB_READMNT 1 rmnt.c */ /* #define USE_LIB_REGEX 1 regex.c */ # if DUV<50100 #define USE_LIB_RNAM 1 /* rnam.c */ # else /* DUV>=50100 */ /* Tru64 UNIX 5.1 and above have private name cache functions -- see * ./dproc.c */ # endif /* DUV<50100 */ /* #define USE_LIB_RNCH 1 rnch.c */ /* #define USE_LIB_RNMH 1 rnmh.c */ # if DUV<50000 #define USE_LIB_SNPF 1 /* snpf.c */ # else /* DUV>=50000 */ #define snpf snprintf /* use the system's snprintf() */ # endif /* DUV<50000 */ /* * WARNDEVACCESS is defined for those dialects that should issue a warning * when lsof can't access /dev (or /device) or one of its sub-directories. * The warning can be inhibited by the lsof caller with the -w option. */ #define WARNDEVACCESS 1 /* * WARNINGSTATE is defined for those dialects that want to suppress all lsof * warning messages. */ /* #define WARNINGSTATE 1 warnings are enabled by default */ /* * WILLDROPGID is defined for those dialects whose lsof executable runs * setgid(not_real_GID) and whose setgid power can be relinquished after * the dialect's initialize() function has been executed. */ #define WILLDROPGID 1 /* * zeromem is a macro that uses bzero or memset. */ #define zeromem(a, l) bzero(a, l) #endif /* !defined(LSOF_MACHINE_H) */ lsof-4.86+dfsg.orig/dialects/du/Makefile0000444000175000017500000000743211001126654020316 0ustar nicholasnicholas # DU Makefile # # $Id: Makefile,v 1.13 2008/04/15 13:29:11 abe Exp $ PROG= lsof BIN= ${DESTDIR} DOC= ${DESTDIR} I=/usr/include S=/usr/include/sys L=/usr/include/local P= CDEF= CDEFS= ${CDEF} ${CFGF} INCL= ${DINC} CFLAGS= ${CDEFS} ${INCL} ${DEBUG} GRP= HDR= lsof.h lsof_fields.h dlsof.h machine.h proto.h dproto.h SRC= ddev.c dfile.c dmnt.c dnode.c dproc.c dsock.c dstore.c \ arg.c main.c misc.c node.c print.c proc.c store.c usage.c \ util.c OBJ= ddev.o dfile.o dmnt.o dnode.o dproc.o dsock.o dstore.o \ arg.o main.o misc.o node.o print.o proc.o store.o usage.o \ util.o MAN= lsof.8 OTHER= SHELL= /bin/sh SOURCE= Makefile ${OTHER} ${MAN} ${HDR} ${SRC} all: ${PROG} ${PROG}:${LIB} ${P} ${OBJ} ${CC} -o $@ ${CFLAGS} ${OBJ} ${CFGL} clean: FRC rm -f Makefile.bak ${PROG} a.out core errs lint.out tags *.o version.h rm -f machine.h.old new_machine.h (cd lib; ${MAKE} -f Makefile.skel clean) install: all FRC @echo '' @echo 'Please write your own install rule. Lsof should be installed' @echo 'setgid to the group that can can read /dev/kmem. Normally' @echo 'that is the mem group. Your install rule actions might look' @echo 'something like this:' @echo '' @echo ' installbsd -c -s -m 2755 -g $${GRP} $${PROG} $${BIN}/$${PROG}' @echo ' installbsd -c -m 444 $${MAN} $${DOC}/$${MAN}' @echo '' @echo 'You will have to complete the skeletons for the BIN, DOC, and' @echo 'GRP strings given at the beginning of this Makefile, e.g.,' @echo '' @echo ' BIN= $${DESTDIR}/usr/local/etc' @echo ' DOC= $${DESTDIR}/usr/man/man8' @echo ' GRP= mem' @echo '' ${LIB}: FRC (cd lib; ${MAKE} DEBUG="${DEBUG}" CFGF="${CFGF}") version.h: FRC @echo Constructing version.h @rm -f version.h @echo '#define LSOF_BLDCMT "${LSOF_BLDCMT}"' > version.h; @echo '#define LSOF_CC "${CC}"' >> version.h @echo '#define LSOF_CCV "${CCV}"' >> version.h @echo '#define LSOF_CCDATE "'`date`'"' >> version.h @echo '#define LSOF_CCFLAGS "'`echo ${CFLAGS} | sed 's/\\\\(/\\(/g' | sed 's/\\\\)/\\)/g' | sed 's/"/\\\\"/g'`'"' >> version.h @if [ "X${LSOF_HOST}" = "X" ]; then \ echo '#define LSOF_HOST "'`uname -n`'"' >> version.h; \ else \ if [ "${LSOF_HOST}" = "none" ]; then \ echo '#define LSOF_HOST ""' >> version.h; \ else \ echo '#define LSOF_HOST "${LSOF_HOST}"' >> version.h; \ fi \ fi @echo '#define LSOF_LDFLAGS "${CFGL}"' >> version.h @if [ "X${LSOF_LOGNAME}" = "X" ]; then \ echo '#define LSOF_LOGNAME "${LOGNAME}"' >> version.h; \ else \ if [ "${LSOF_LOGNAME}" = "none" ]; then \ echo '#define LSOF_LOGNAME ""' >> version.h; \ else \ echo '#define LSOF_LOGNAME "${LSOF_LOGNAME}"' >> version.h; \ fi; \ fi @if [ "X${LSOF_SYSINFO}" = "X" ]; then \ echo '#define LSOF_SYSINFO "'`uname -a`'"' >> version.h; \ else \ if [ "${LSOF_SYSINFO}" = "none" ]; then \ echo '#define LSOF_SYSINFO ""' >> version.h; \ else \ echo '#define LSOF_SYSINFO "${LSOF_SYSINFO}"' >> version.h; \ fi \ fi @if [ "X${LSOF_USER}" = "X" ]; then \ echo '#define LSOF_USER "${USER}"' >> version.h; \ else \ if [ "${LSOF_USER}" = "none" ]; then \ echo '#define LSOF_USER ""' >> version.h; \ else \ echo '#define LSOF_USER "${LSOF_USER}"' >> version.h; \ fi \ fi @sed '/VN/s/.ds VN \(.*\)/#define LSOF_VERSION "\1"/' < version >> version.h FRC: # DO NOT DELETE THIS LINE - make depend DEPENDS ON IT ddev.o: ${HDR} ddev.c dfile.o: ${HDR} dfile.c dmnt.o: ${HDR} dmnt.c dnode.o: ${HDR} dnode.c dproc.o: ${HDR} dproc.c dsock.o: ${HDR} dsock.c dstore.o: ${HDR} dstore.c arg.o: ${HDR} arg.c main.o: ${HDR} main.c misc.o: ${HDR} misc.c node.o: ${HDR} node.c print.o: ${HDR} print.c proc.o: ${HDR} proc.c store.o: ${HDR} store.c usage.o: ${HDR} version.h usage.c util.o: ${HDR} util.c # *** Do not add anything here - It will go away. *** lsof-4.86+dfsg.orig/dialects/n+obsd/0000755000175000017500000000000011741064217017431 5ustar nicholasnicholaslsof-4.86+dfsg.orig/dialects/n+obsd/dstore.c0000444000175000017500000000671410165046030021073 0ustar nicholasnicholas/* * dstore.c - NetBSD and OpenBSD global storage for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dstore.c,v 1.9 2004/12/30 18:42:24 abe Exp $"; #endif #include "lsof.h" struct file *Cfp; /* current file's file struct pointer */ /* * Drive_Nl -- table to drive the building of Nl[] via build_Nl() * (See lsof.h and misc.c.) */ struct drive_Nl Drive_Nl[] = { #if (defined(OPENBSDV) && OPENBSDV>=2010) || (defined(NETBSDV) && NETBSDV>=1002000) { X_NCACHE, "_nchashtbl", }, { X_NCSIZE, "_nchash" }, #else /* (defined(OPENBSDV) && OPENBSDV>=2010) || (defined(NETBSDV) && NETBSDV>=1002000) */ # if defined(NetBSD1_0) && NetBSD<1994101 { X_NCACHE, "_nchhead", }, # else /* !defined(NetBSD1_0) || NetBSD>=1994101 */ { X_NCACHE, "_nclruhead" }, # endif /* defined(NetBSD1_0) && NetBSD<1994101 */ { X_NCSIZE, "_numcache" }, #endif /* (defined(OPENBSDV) && OPENBSDV>=2010) || (defined(NETBSDV) && NETBSDV>=1002000) */ { "pgshift", "_pgshift" }, { "", "" }, { NULL, NULL } }; kvm_t *Kd; /* kvm descriptor */ KA_T Kpa; /* kernel proc struct address */ struct l_vfs *Lvfs = NULL; /* local vfs structure table */ int Np = 0; /* number of kernel processes */ #if defined(HASKVMGETPROC2) struct kinfo_proc2 *P = NULL; /* local process table copy */ #else /* !defined(HASKVMGETPROC2) */ struct kinfo_proc *P = NULL; /* local process table copy */ #endif /* defined(HASKVMGETPROC2) */ #if defined(HASFSTRUCT) /* * Pff_tab[] - table for printing file flags */ struct pff_tab Pff_tab[] = { { (long)FREAD, FF_READ }, { (long)FWRITE, FF_WRITE }, { (long)FNONBLOCK, FF_NBLOCK }, { (long)FNDELAY, FF_NDELAY }, { (long)FAPPEND, FF_APPEND }, { (long)FASYNC, FF_ASYNC }, # if defined(FDSYNC) { (long)FDSYNC, FF_DSYNC }, # endif /* defined*FDSYNC) */ { (long)FFSYNC, FF_FSYNC }, # if defined(FRSYNC) { (long)FRSYNC, FF_RSYNC }, # endif /* defined(FRSYNC( */ { (long)FMARK, FF_MARK }, { (long)FDEFER, FF_DEFER }, { (long)FHASLOCK, FF_HASLOCK }, { (long)O_NOCTTY, FF_NOCTTY }, { (long)0, NULL } }; /* * Pof_tab[] - table for print process open file flags */ struct pff_tab Pof_tab[] = { # if defined(UF_EXCLOSE) { (long)UF_EXCLOSE, POF_CLOEXEC }, # endif /* defined(UF_EXCLOSE) */ # if defined(UF_MAPPED) { (long)UF_MAPPED, POF_MAPPED }, # endif /* defined(UF_MAPPED) */ { (long)0, NULL } }; #endif /* defined(HASFSTRUCT) */ int pgshift = 0; /* kernel's page shift */ lsof-4.86+dfsg.orig/dialects/n+obsd/dsock.c0000444000175000017500000002637310275734076020721 0ustar nicholasnicholas/* * dsock.c - NetBSD and OpenBSD socket processing functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dsock.c,v 1.25 2005/08/08 19:53:24 abe Exp $"; #endif #include "lsof.h" #if defined(HASIPv6) /* * IPv6_2_IPv4() -- macro to define the address of an IPv4 address contained * in an IPv6 address */ #define IPv6_2_IPv4(v6) (((uint8_t *)((struct in6_addr *)v6)->s6_addr)+12) #endif /* defined(HASIPv6) */ /* * process_socket() - process socket */ void process_socket(sa) KA_T sa; /* socket address in kernel */ { struct domain d; unsigned char *fa = (unsigned char *)NULL; int fam; int fp, lp; struct inpcb inp; unsigned char *la = (unsigned char *)NULL; struct protosw p; struct socket s; struct tcpcb t; KA_T ta = (KA_T)NULL; struct unpcb uc, unp; struct sockaddr_un *ua = NULL; struct sockaddr_un un; #if defined(HASIPv6) && defined(NETBSDV) && !defined(HASINRIAIPv6) struct in6pcb in6p; #endif /* defined(HASIPv6) && defined(NETBSDV) && !defined(HASINRIAIPv6) */ #define UNPADDR_IN_MBUF #if defined(NETBSDV) # if NETBSDV>=1004000 #undef UNPADDR_IN_MBUF # endif /* NETBSDV>=1004000 */ #endif /* defined(NETBSDV) */ #if defined(UNPADDR_IN_MBUF) struct mbuf mb; #endif /* defined(UNPADDR_IN_MBUF) */ (void) snpf(Lf->type, sizeof(Lf->type), "sock"); Lf->inp_ty = 2; /* * Read the socket, protocol, and domain structures. */ if (!sa) { enter_nm("no socket address"); return; } if (kread(sa, (char *) &s, sizeof(s))) { (void) snpf(Namech, Namechl, "can't read socket struct from %s", print_kptr(sa, (char *)NULL, 0)); enter_nm(Namech); return; } if (!s.so_type) { enter_nm("no socket type"); return; } if (!s.so_proto || kread((KA_T)s.so_proto, (char *)&p, sizeof(p))) { (void) snpf(Namech, Namechl, "can't read protocol switch from %s", print_kptr((KA_T)s.so_proto, (char *)NULL, 0)); enter_nm(Namech); return; } if (!p.pr_domain || kread((KA_T)p.pr_domain, (char *)&d, sizeof(d))) { (void) snpf(Namech, Namechl, "can't read domain struct from %s", print_kptr((KA_T)p.pr_domain, (char *)NULL, 0)); enter_nm(Namech); return; } /* * Save size information. */ if (Fsize) { if (Lf->access == 'r') Lf->sz = (SZOFFTYPE)s.so_rcv.sb_cc; else if (Lf->access == 'w') Lf->sz = (SZOFFTYPE)s.so_snd.sb_cc; else Lf->sz = (SZOFFTYPE)(s.so_rcv.sb_cc + s.so_snd.sb_cc); Lf->sz_def = 1; } else Lf->off_def = 1; #if defined(HASTCPTPIQ) Lf->lts.rq = s.so_rcv.sb_cc; Lf->lts.sq = s.so_snd.sb_cc; Lf->lts.rqs = Lf->lts.sqs = 1; #endif /* defined(HASTCPTPIQ) */ #if defined(HASSOOPT) Lf->lts.ltm = (unsigned int)s.so_linger; Lf->lts.opt = (unsigned int)s.so_options; Lf->lts.pqlen = (unsigned int)s.so_q0len; Lf->lts.qlen = (unsigned int)s.so_qlen; Lf->lts.qlim = (unsigned int)s.so_qlimit; Lf->lts.rbsz = (unsigned long)s.so_rcv.sb_mbmax; Lf->lts.sbsz = (unsigned long)s.so_snd.sb_mbmax; Lf->lts.pqlens = Lf->lts.qlens = Lf->lts.qlims = Lf->lts.rbszs = Lf->lts.sbszs = (unsigned char)1; #endif /* defined(HASSOOPT) */ #if defined(HASSOSTATE) Lf->lts.ss = (unsigned int)s.so_state; #endif /* defined(HASSOSTATE) */ /* * Process socket by the associated domain family. */ switch ((fam = d.dom_family)) { /* * Process an Internet domain socket. */ case AF_INET: #if defined(HASIPv6) case AF_INET6: #endif /* defined(HASIPv6) */ if (Fnet) { if (!FnetTy || ((FnetTy == 4) && (fam == AF_INET)) #if defined(HASIPv6) || ((FnetTy == 6) && (fam == AF_INET6)) #endif /* defined(HASIPv6) */ ) Lf->sf |= SELNET; } printiproto(p.pr_protocol); #if defined(HASIPv6) (void) snpf(Lf->type, sizeof(Lf->type), (fam == AF_INET) ? "IPv4" : "IPv6"); #else /* !defined(HASIPv6) */ (void) snpf(Lf->type, sizeof(Lf->type), "inet"); #endif /* defined(HASIPv6) */ #if defined(HASIPv6) && defined(NETBSDV) && !defined(HASINRIAIPv6) if (fam == AF_INET6) { /* * Read IPv6 protocol control block. */ if (!s.so_pcb || kread((KA_T)s.so_pcb, (char *)&in6p, sizeof(in6p))) { (void) snpf(Namech, Namechl, "can't read in6pcb at %s", print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); enter_nm(Namech); return; } /* * Save IPv6 address information. */ enter_dev_ch(print_kptr((KA_T)(in6p.in6p_ppcb ? in6p.in6p_ppcb : s.so_pcb), (char *)NULL, 0)); if (p.pr_protocol == IPPROTO_TCP) ta = (KA_T)in6p.in6p_ppcb; la = (unsigned char *)&in6p.in6p_laddr; lp = (int)ntohs(in6p.in6p_lport); if (!IN6_IS_ADDR_UNSPECIFIED(&in6p.in6p_faddr) || in6p.in6p_fport) { fa = (unsigned char *)&in6p.in6p_faddr; fp = (int)ntohs(in6p.in6p_fport); } } else #endif /* defined(HASIPv6) && defined(NETBSDV) && !defined(HASINRIAIPv6) */ { /* * Read IPv4 or IPv6 (OpenBSD) protocol control block. */ if (!s.so_pcb || kread((KA_T)s.so_pcb, (char *)&inp, sizeof(inp))) { if (!s.so_pcb) { (void) snpf(Namech, Namechl, "no PCB%s%s", (s.so_state & SS_CANTSENDMORE) ? ", CANTSENDMORE" : "", (s.so_state & SS_CANTRCVMORE) ? ", CANTRCVMORE" : ""); } else { (void) snpf(Namech, Namechl, "can't read inpcb at %s", print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); } enter_nm(Namech); return; } enter_dev_ch(print_kptr((KA_T)(inp.inp_ppcb ? inp.inp_ppcb : s.so_pcb), (char *)NULL, 0)); if (p.pr_protocol == IPPROTO_TCP) ta = (KA_T)inp.inp_ppcb; lp = (int)ntohs(inp.inp_lport); if (fam == AF_INET) { /* * Save IPv4 address information. */ la = (unsigned char *)&inp.inp_laddr; if (inp.inp_faddr.s_addr != INADDR_ANY || inp.inp_fport) { fa = (unsigned char *)&inp.inp_faddr; fp = (int)ntohs(inp.inp_fport); } } #if defined(HASIPv6) && (defined(OPENBSDV) || defined(HASINRIAIPv6)) else { la = (unsigned char *)&inp.inp_laddr6; if (!IN6_IS_ADDR_UNSPECIFIED(&inp.inp_faddr6) || inp.inp_fport) { fa = (unsigned char *)&inp.inp_faddr6; fp = (int)ntohs(inp.inp_fport); } } #endif /* defined(HASIPv6) && (defined(OPENBSDV) || defined(HASINRIAIPv6)) */ } #if defined(HASIPv6) if ((fam == AF_INET6) && ((la && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)la)) || ((fa && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)fa))))) { /* * Adjust for IPv4 addresses mapped in IPv6 addresses. */ if (la) la = (unsigned char *)IPv6_2_IPv4(la); if (fa) fa = (unsigned char *)IPv6_2_IPv4(fa); fam = AF_INET; } #endif /* defined(HASIPv6) */ /* * Enter local and remote addresses by address family. */ if (fa || la) (void) ent_inaddr(la, lp, fa, fp, fam); /* * If the protocol is TCP, and its address is available, read the * TCP protocol control block and save its state. */ if (ta && !kread(ta, (char *)&t, sizeof(t))) { Lf->lts.type = 0; Lf->lts.state.i = (int)t.t_state; #if defined(HASTCPOPT) # if defined(OPENBSDV) Lf->lts.mss = (unsigned long)t.t_maxseg; # else /* !defined(OPENSDV) */ Lf->lts.mss = (unsigned long)t.t_ourmss; # endif /* defined(OPENSDV) */ Lf->lts.msss = (unsigned char)1; Lf->lts.topt = (unsigned int)t.t_flags; #endif /* defined(HASTCPOPT) */ } break; /* * Process a ROUTE domain socket. */ case AF_ROUTE: (void) snpf(Lf->type, sizeof(Lf->type), "rte"); if (s.so_pcb) enter_dev_ch(print_kptr((KA_T)(s.so_pcb), (char *)NULL, 0)); else (void) snpf(Namech, Namechl, "no protocol control block"); if (!Fsize) Lf->off_def = 1; break; /* * Process a Unix domain socket. */ case AF_UNIX: if (Funix) Lf->sf |= SELUNX; (void) snpf(Lf->type, sizeof(Lf->type), "unix"); /* * Read Unix protocol control block and the Unix address structure. */ enter_dev_ch(print_kptr(sa, (char *)NULL, 0)); if (kread((KA_T) s.so_pcb, (char *) &unp, sizeof(unp))) { (void) snpf(Namech, Namechl, "can't read unpcb at %s", print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); break; } if ((struct socket *)sa != unp.unp_socket) { (void) snpf(Namech, Namechl, "unp_socket (%s) mismatch", print_kptr((KA_T)unp.unp_socket, (char *)NULL, 0)); break; } if (unp.unp_addr) { #if defined(UNPADDR_IN_MBUF) if (kread((KA_T)unp.unp_addr, (char *)&mb, sizeof(mb))) #else /* !defined(UNPADDR_IN_MBUF) */ if (kread((KA_T)unp.unp_addr, (char *)&un, sizeof(un))) #endif /* defined(UNPADDR_IN_MBUF) */ { (void) snpf(Namech, Namechl, "can't read unp_addr at %s", print_kptr((KA_T)unp.unp_addr, (char *)NULL, 0)); break; } #if defined(UNPADDR_IN_MBUF) if (mb.m_hdr.mh_len == sizeof(struct sockaddr_un)) ua = (struct sockaddr_un *) ((char *) &mb + (mb.m_hdr.mh_data - (caddr_t) unp.unp_addr)); #else /* !defined(UNPADDR_IN_MBUF) */ ua = &un; #endif /* defined(UNPADDR_IN_MBUF) */ } if (!ua) { ua = &un; (void) bzero((char *)ua, sizeof(un)); ua->sun_family = AF_UNSPEC; } /* * Print information on Unix socket that has no address bound * to it, although it may be connected to another Unix domain * socket as a pipe. */ if (ua->sun_family != AF_UNIX) { if (ua->sun_family == AF_UNSPEC) { if (unp.unp_conn) { if (kread((KA_T)unp.unp_conn, (char *)&uc, sizeof(uc))) (void) snpf(Namech, Namechl, "can't read unp_conn at %s", print_kptr((KA_T)unp.unp_conn,(char *)NULL,0)); else (void) snpf(Namech, Namechl, "->%s", print_kptr((KA_T)uc.unp_socket,(char *)NULL,0)); } else (void) snpf(Namech, Namechl, "->(none)"); } else (void) snpf(Namech, Namechl, "unknown sun_family (%d)", ua->sun_family); break; } if (ua->sun_path[0]) { #if defined(UNPADDR_IN_MBUF) if (mb.m_len >= sizeof(struct sockaddr_un)) mb.m_len = sizeof(struct sockaddr_un) - 1; *((char *)ua + mb.m_len) = '\0'; #else /* !defined(UNPADDR_IN_MBUF) */ ua->sun_path[sizeof(ua->sun_path) - 1] = '\0'; #endif /* defined(UNPADDR_IN_MBUF) */ if (Sfile && is_file_named(ua->sun_path, 0)) Lf->sf |= SELNM; if (!Namech[0]) (void) snpf(Namech, Namechl, "%s", ua->sun_path); } else (void) snpf(Namech, Namechl, "no address"); break; default: printunkaf(fam, 1); } if (Namech[0]) enter_nm(Namech); } lsof-4.86+dfsg.orig/dialects/n+obsd/dproc.c0000444000175000017500000003003310240400150020660 0ustar nicholasnicholas/* * dproc.c - NetBSD and OpenBSD process access functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dproc.c,v 1.17 2005/05/11 12:53:54 abe Exp $"; #endif #include "lsof.h" _PROTOTYPE(static void enter_vn_text,(KA_T va, int *n)); _PROTOTYPE(static void get_kernel_access,(void)); _PROTOTYPE(static void process_text,(KA_T vm)); /* * Local static values */ static MALLOC_S Nv = 0; /* allocated Vp[] entries */ static KA_T *Vp = NULL; /* vnode address cache */ /* * ckkv - check kernel version */ void ckkv(d, er, ev, ea) char *d; /* dialect */ char *er; /* expected release */ char *ev; /* expected version */ char *ea; /* expected architecture */ { #if defined(HASKERNIDCK) size_t l; int m[2]; char v[64]; if (Fwarn) return; /* * Read kernel version. */ m[0] = CTL_KERN; m[1] = KERN_OSRELEASE; l = sizeof(v); if (sysctl(m, 2, v, &l, NULL, 0) < 0) { (void) fprintf(stderr, "%s: CTL_KERN, KERN_OSRELEASE: %s\n", Pn, strerror(errno)); Exit(1); } /* * Warn if the actual and expected releases don't match. */ if (!er || strcmp(v, er)) (void) fprintf(stderr, "%s: WARNING: compiled for %s release %s; this is %s.\n", Pn, d, er ? er : "UNKNOWN", v); #endif /* defined(HASKERNIDCK) */ } /* * enter_vn_text() - enter a vnode text reference */ static void enter_vn_text(va, n) KA_T va; /* vnode address */ int *n; /* Vp[] entries in use */ { int i; /* * Ignore the request if the vnode has already been entered. */ for (i = 0; i < *n; i++) { if (va == Vp[i]) return; } /* * Save the text file information. */ alloc_lfile(" txt", -1); Cfp = (struct file *)NULL; process_node((KA_T)va); if (Lf->sf) link_lfile(); if (i >= Nv) { /* * Allocate space for remembering the vnode. */ Nv += 10; if (!Vp) Vp=(KA_T *)malloc((MALLOC_S)(sizeof(struct vnode *) * 10)); else Vp=(KA_T *)realloc((MALLOC_P *)Vp,(MALLOC_S)(Nv*sizeof(KA_T))); if (!Vp) { (void) fprintf(stderr, "%s: no txt ptr space, PID %d\n", Pn, Lp->pid); Exit(1); } } /* * Remember the vnode. */ Vp[*n] = va; (*n)++; } /* * gather_proc_info() -- gather process information */ void gather_proc_info() { struct filedesc fd; int i, nf; MALLOC_S nb; static struct file **ofb = NULL; static int ofbb = 0; short pss, sf; int px; uid_t uid; #if defined(HASCWDINFO) struct cwdinfo cw; #define CDIR cw.cwdi_cdir #define RDIR cw.cwdi_rdir #else /* !defined(HASCWDINFO) */ #define CDIR fd.fd_cdir #define RDIR fd.fd_rdir #endif /* defined(HASCWDINFO) */ #if defined(HASFSTRUCT) static char *pof = (char *)NULL; static int pofb = 0; #endif /* defined(HASFSTRUCT) */ #if defined(HASKVMGETPROC2) struct kinfo_proc2 *p; #define KVMPROCSZ2 sizeof(struct kinfo_proc2) #else /* !defined(HASKVMGETPROC2) */ struct kinfo_proc *p; #endif /* defined(HASKVMGETPROC2) */ /* * Read the process table. */ #if defined(HASKVMGETPROC2) P = kvm_getproc2(Kd, KERN_PROC_ALL, 0, KVMPROCSZ2, &Np); #else /* !defined(HASKVMGETPROC2) */ P = kvm_getprocs(Kd, KERN_PROC_ALL, 0, &Np); #endif /* defined(HASKVMGETPROC2) &/ if (!P) { (void) fprintf(stderr, "%s: can't read process table: %s\n", Pn, kvm_geterr(Kd)); Exit(1); } /* * Examine proc structures and their associated information. */ for (p = P, px = 0; px < Np; px++, p++) { if (p->P_STAT == 0 || p->P_STAT == SZOMB) continue; /* * Read process information, process group structure (if * necessary), and User ID (if necessary). * * See if process is excluded. * * Read file structure pointers. */ uid = p->P_UID; if (is_proc_excl((int)p->P_PID, (int)p->P_PGID, (UID_ARG)uid, &pss, &sf)) { continue; } if (!p->P_FD || kread((KA_T)p->P_FD, (char *)&fd, sizeof(fd))) continue; if (!fd.fd_refcnt || fd.fd_lastfile > fd.fd_nfiles) continue; #if defined(HASCWDINFO) if (!p->P_CWDI || kread((KA_T)p->P_CWDI, (char *)&cw, sizeof(cw))) CDIR = RDIR = (struct vnode *)NULL; #endif /* defined(HASCWDINFO) */ /* * Allocate a local process structure. */ if (is_cmd_excl(p->P_COMM, &pss, &sf)) continue; alloc_lproc((int)p->P_PID, (int)p->P_PGID, (int)p->P_PPID, (UID_ARG)uid, p->P_COMM, (int)pss, (int)sf); Plf = (struct lfile *)NULL; Kpa = (KA_T)p->P_ADDR; /* * Save current working directory information. */ if (CDIR) { alloc_lfile(CWD, -1); Cfp = (struct file *)NULL; process_node((KA_T)CDIR); if (Lf->sf) link_lfile(); } /* * Save root directory information. */ if (RDIR) { alloc_lfile(RTD, -1); Cfp = (struct file *)NULL; process_node((KA_T)RDIR); if (Lf->sf) link_lfile(); } #if defined(OPENBSDV) && OPENBSDV>=3020 /* * Save trace node information. */ if (p->P_TRACEP) { alloc_lfile("tr", -1); Cfp = (struct file *)NULL; process_node((KA_T)p->P_TRACEP); if (Lf->sf) link_lfile(); } #endif /* defined(OPENBSDV) && OPENBSDV>=3020 */ /* * Save information on the text file. */ if (p->P_VMSPACE) process_text((KA_T)p->P_VMSPACE); /* * Read open file structure pointers. */ if (!fd.fd_ofiles || (nf = fd.fd_nfiles) <= 0) continue; nb = (MALLOC_S)(sizeof(struct file *) * nf); if (nb > ofbb) { if (!ofb) ofb = (struct file **)malloc(nb); else ofb = (struct file **)realloc((MALLOC_P *)ofb, nb); if (!ofb) { (void) fprintf(stderr, "%s: PID %d, no file * space\n", Pn, p->P_PID); Exit(1); } ofbb = nb; } if (kread((KA_T)fd.fd_ofiles, (char *)ofb, nb)) continue; #if defined(HASFSTRUCT) if (Fsv & FSV_FG) { nb = (MALLOC_S)(sizeof(char) * nf); if (nb > pofb) { if (!pof) pof = (char *)malloc(nb); else pof = (char *)realloc((MALLOC_P *)pof, nb); if (!pof) { (void) fprintf(stderr, "%s: PID %d, no file flag space\n", Pn, p->P_PID); Exit(1); } pofb = nb; } if (!fd.fd_ofileflags || kread((KA_T)fd.fd_ofileflags, pof, nb)) zeromem(pof, nb); } #endif /* defined(HASFSTRUCT) */ /* * Save information on file descriptors. */ for (i = 0; i < nf; i++) { if (ofb[i]) { alloc_lfile(NULL, i); process_file((KA_T)(Cfp = ofb[i])); if (Lf->sf) { #if defined(HASFSTRUCT) if (Fsv & FSV_FG) Lf->pof = (long)pof[i]; #endif /* defined(HASFSTRUCT) */ link_lfile(); } } } /* * Examine results. */ if (examine_lproc()) return; } } /* * get_kernel_access() - get access to kernel memory */ static void get_kernel_access() { KA_T v; /* * Check kernel version. */ (void) ckkv( #if defined(NETBSDV) "NetBSD", #else /* !defined(NETBSDV) */ # if defined(OPENBSDV) "OpenBSD", # endif /* defined(OPENBSDV) */ #endif /* defined(NETBSDV) */ LSOF_VSTR, (char *)NULL, (char *)NULL); /* * Set name list file path. */ if (!Nmlst) #if defined(N_UNIX) Nmlst = N_UNIX; #else /* !defined(N_UNIX) */ { if (!(Nmlst = get_nlist_path(1))) { (void) fprintf(stderr, "%s: can't get kernel name list path\n", Pn); Exit(1); } } #endif /* defined(N_UNIX) */ #if defined(WILLDROPGID) /* * If kernel memory isn't coming from KMEM, drop setgid permission * before attempting to open the (Memory) file. */ if (Memory) (void) dropgid(); #else /* !defined(WILLDROPGID) */ /* * See if the non-KMEM memory and name list files are readable. */ if ((Memory && !is_readable(Memory, 1)) || (Nmlst && !is_readable(Nmlst, 1))) Exit(1); #endif /* defined(WILLDROPGID) */ /* * Open kernel memory access. */ if ((Kd = kvm_openfiles(Nmlst, Memory, NULL, O_RDONLY, NULL)) == NULL) { (void) fprintf(stderr, "%s: kvm_openfiles(execfile=%s, corefile=%s): %s\n", Pn, Nmlst, Memory ? Memory : #if defined(_PATH_MEM) _PATH_MEM, #else /* !defined(_PATH_MEM) */ "default", #endif /* defined(_PATH_MEM) */ strerror(errno)); Exit(1); } (void) build_Nl(Drive_Nl); if (kvm_nlist(Kd, Nl) < 0) { (void) fprintf(stderr, "%s: can't read namelist from %s\n", Pn, Nmlst); Exit(1); } #if defined(WILLDROPGID) /* * Drop setgid permission, if necessary. */ if (!Memory) (void) dropgid(); #endif /* defined(WILLDROPGID) */ /* * Read the kernel's page shift amount, if possible. */ if (get_Nl_value("pgshift", Drive_Nl, &v) < 0 || !v || kread((KA_T)v, (char *)&pgshift, sizeof(pgshift))) pgshift = 0; } #if !defined(N_UNIX) /* * get_nlist_path() - get kernel name list path */ char * get_nlist_path(ap) int ap; /* on success, return an allocated path * string pointer if 1; return a * constant character pointer if 0; * return NULL if failure */ { const char *bf; static char *bfc; MALLOC_S bfl; /* * Get bootfile name. */ if ((bf = getbootfile())) { if (!ap) return(""); bfl = (MALLOC_S)(strlen(bf) + 1); if (!(bfc = (char *)malloc(bfl))) { (void) fprintf(stderr, "%s: can't allocate %d bytes for boot file path: %s\n", Pn, bfl, bf); Exit(1); } (void) snpf(bfc, bfl, "%s", bf); return(bfc); } return((char *)NULL); } #endif /* !defined(N_UNIX) */ /* * initialize() - perform all initialization */ void initialize() { get_kernel_access(); } /* * kread() - read from kernel memory */ int kread(addr, buf, len) KA_T addr; /* kernel memory address */ char *buf; /* buffer to receive data */ READLEN_T len; /* length to read */ { int br; br = kvm_read(Kd, (u_long)addr, buf, len); return((br == len) ? 0 : 1); } /* * process_text() - process text information */ void process_text(vm) KA_T vm; /* kernel vm space pointer */ { int i, j; KA_T ka; int n = 0; struct vm_map_entry vmme, *e; struct vmspace vmsp; #if !defined(UVM) struct pager_struct pg; struct vm_object vmo; #endif /* !defined(UVM) */ /* * Read the vmspace structure for the process. */ if (kread(vm, (char *)&vmsp, sizeof(vmsp))) return; /* * Read the vm_map structure. Search its vm_map_entry structure list. */ #if !defined(UVM) if (!vmsp.vm_map.is_main_map) return; #endif /* !defined(UVM) */ for (i = 0; i < vmsp.vm_map.nentries; i++) { /* * Read the next vm_map_entry. */ if (!i) e = &vmsp.vm_map.header; else { if (!(ka = (KA_T)e->next)) return; e = &vmme; if (kread(ka, (char *)e, sizeof(vmme))) return; } #if defined(UVM) /* * Process the uvm_obj pointer of a UVM map entry with a UVM_ET_OBJ * type as a vnode pointer. */ if ((e->etype > UVM_ET_OBJ) && e->object.uvm_obj) (void) enter_vn_text((KA_T)e->object.uvm_obj, &n); #else /* !defined(UVM) */ /* * Read the map entry's object and the object's shadow. * Look for a PG_VNODE pager handle. */ if (e->is_a_map || e->is_sub_map) continue; for (j = 0, ka = (KA_T)e->object.vm_object; j < 2 && ka; j++, ka = (KA_T)vmo.shadow) { if (kread(ka, (char *)&vmo, sizeof(vmo))) break; if (!(ka = (KA_T)vmo.pager) || kread(ka, (char *)&pg, sizeof(pg))) continue; if (!pg.pg_handle || pg.pg_type != PG_VNODE) continue; (void) enter_vn_text((KA_T)pg.pg_handle, &n); } #endif /* defined(UVM) */ } } lsof-4.86+dfsg.orig/dialects/n+obsd/dproto.h0000444000175000017500000000327010275734076021121 0ustar nicholasnicholas/* * dproto.h - NetBSD and OpenBSD function prototypes for lsof * * The _PROTOTYPE macro is defined in the common proto.h. */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: dproto.h,v 1.11 2005/08/08 19:53:24 abe Exp $ */ #if !defined(N_UNIX) _PROTOTYPE(extern char *get_nlist_path,(int ap)); #endif /* !defined(N_UNIX) */ _PROTOTYPE(extern int is_file_named,(char *p, int cd)); _PROTOTYPE(extern struct l_vfs *readvfs,(KA_T vm)); #if defined(HAS_SYS_PIPE_H) _PROTOTYPE(extern void process_pipe,(KA_T pa)); #endif /* defined(HAS_SYS_PIPEH) */ #if defined(HAS9660FS) _PROTOTYPE(extern int read_iso_node,(struct vnode *v, dev_t *d, INODETYPE *ino, long *nl, SZOFFTYPE *sz)); #endif /* defined(HAS9660FS) */ _PROTOTYPE(extern void process_socket,(KA_T sa)); lsof-4.86+dfsg.orig/dialects/n+obsd/dlsof.h0000444000175000017500000003777710412330207020721 0ustar nicholasnicholas/* * dlsof.h - NetBSD and OpenBSD header file for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: dlsof.h,v 1.38 2006/03/28 21:54:08 abe Exp $ */ #if !defined(NETBSD_LSOF_H) #define NETBSD_LSOF_H 1 #include #include #include #include #include #include #include #include # if defined(HASGETBOOTFILE) #include # endif /* defined(HASGETBOOTFILE) */ #include #include # if defined(HAS_LWP_H) #include # endif /* defined(HAS_LWP_H) */ # if (defined(OPENBSDV) && OPENBSDV>=3030) \ || (defined(NETBSDV) && __NetBSD_Version__>=106060000) # if defined(OPENBSDV) || __NetBSD_Version__<399001100 #define _KERNEL # endif /* defined(OPENBSDV) || __NetBSD_Version__<399001100 */ # if defined(NETBSDV) && __NetBSD_Version__<399001100 struct buf; /* dummy for function prototype in */ struct uio; /* dummy for function prototype in */ # endif /* defined(NETBSDV && __NetBSD_Version__<399001100) */ #include # endif /* (defined(OPENBSDV) && OPENBSDV>=3030) || (defined(NETBSDV) && __NetBSD_Version__>=106060000) */ # if defined(NETBSDV) && __NetBSD_Version__<399001100 #include # endif /* defined(NETBSDV) && __NetBSD_Version__<399001100 */ # if (defined(OPENBSDV) && OPENBSDV>=3030) \ || (defined(NETBSDV) && __NetBSD_Version__>=106060000 \ && __NetBSD_Version__<399001100) #undef _KERNEL # endif /* (defined(OPENBSDV) && OPENBSDV>=3030) \ || (defined(NETBSDV) && __NetBSD_Version__>=106060000 \ && __NetBSD_Version__<399001100) */ #define NFS #define m_stat mnt_stat # if (defined(OPENBSDV) && OPENBSDV>=3030) \ || (defined(NETBSDV) && __NetBSD_Version__>=106060000) #define _KERNEL # endif /* (defined(OPENBSDV) && OPENBSDV<3030) || (defined(NETBSDV) && __NetBSD_Version__>=106060000) */ #include # if (defined(OPENBSDV) && OPENBSDV>=3030) \ || (defined(NETBSDV) && __NetBSD_Version__>=106060000) #undef _KERNEL # endif /* (defined(OPENBSDV) && OPENBSDV>=3030) || (defined(NETBSDV) && __NetBSD_Version__>=106060000) */ #include #include # if defined(NETBSDV) && NETBSDV>=1003000 #define sockproto NETBSD_sockproto # endif /* defined(NETBSDV) && NETBSDV>=1003000 */ #include # if defined(HASMSDOSFS) # if HASMSDOSFS==1 #include #include # else /* HASMSDOSFS!=1 */ #include #include # endif /* HASMSDOSFS==1 */ # if (defined(OPENBSDV) && OPENBSDV<3030) \ || (defined(NETBSDV) && __NetBSD_Version__<106060000) /* * The netcred and netexport structures may be needed in the msdosfsmount * structure, defined in . So as a terrible hack, * the lsof Configure script extracts the netcred and netexport structure * definitions from and places them in "netexport.h". * * When needed, the netcred and netexport structures netcred should really * be obtained from . However they are hidden in * under _KERNEL, and that sometimes can't be defined when including * 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 . * * It is no longer needed for NetBSD Versions 1.6F and above, or for OpenBSD * versions 3.3 and above. */ #include "netexport.h" # endif /* (defined(OPENBSDV) && OPENBSDV<3030) || (defined(NETBSDV) && __NetBSD_Version__<106060000) */ #define _KERNEL struct nameidata; /* to satisfy a function prototype in msdosfsmount.h */ #include #undef _KERNEL #include #include # endif /* defined(HASMSDOSFS) */ # if defined(NETBSDV) && NETBSDV>=1003000 #undef sockproto # endif /* defined(NETBSDV) && NETBSDV>=1003000 */ #include #include #include #include #include #include # if defined(HASIPv6) && defined(NETBSDV) && !defined(HASINRIAIPv6) #include #include # endif /* defined(HASIPv6) && defined(NETBSDV) && !defined(HASINRIAIPv6) */ #include #include #include #include #include #include #include #include # if defined(OPENBSDV) # if !defined(TF_ECN_PERMIT) #define TF_ECN_PERMIT 0x00008000 /* other side said I could ECN */ # endif /* !defined(TF_ECN_PERMIT) */ # if !defined(TF_RCVD_CE) #define TF_RCVD_CE 0x00010000 /* send ECE in subsequent segs */ # endif /* !defined(TF_RCVD_CE) */ # if !defined(TF_SEND_CWR) #define TF_SEND_CWR 0x00020000 /* send CWR in next seg */ # endif /* !defined(TF_SEND_CWR) */ # if !defined(TF_DISABLE_ECN) #define TF_DISABLE_ECN 0x00040000 /* disable ECN for this connection */ # endif /* !defined(TF_DISABLE_ECN) */ # endif /* defined(OPENBSDV) */ #include # if defined(UVM) /* * Avoid conflicts with definitions in . */ #undef FALSE #undef TRUE # endif /* defined(UVM) */ #include # if defined(NETBSDV) && NETBSDV>=1003000 /* * Because late in the 1.3I NetBSD development cycle the sockproto structure * was placed under _KERNEL in , and because defining _KERNEL * before #include'ing causes other #include problems, the * sockproto structure definition that might have been in 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 #include #define pmap RPC_pmap #include #include #undef pmap #define KERNEL #include # if defined(DIRBLKSIZ) #define DIRENT_DIRBLKSIZ DIRBLKSIZ #undef DIRBLKSIZ # endif /* defined(DIRBLKSIZ) */ # if defined(HASI_FFS1) #define _KERNEL #include #undef _KERNEL # endif /* defined(HASI_FFS1) */ #include # 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 #undef _KERNEL # endif /* defined(NETBSDV) && NETBSDV>=2099010 */ #endif /* defined(HASBUFQ_H) */ #undef KERNEL #include # if defined(HASNFSPROTO) #include #include # else /* !defined(HASNFSPROTO) */ #include # endif /* defined(HASNFSPROTO) */ #include #include #include #include #include # 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 #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 #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 #undef _KERNEL # endif /* defined(HASNULLFS) */ # if defined(HASPROCFS) # if defined(HASPROCFS_PFSROOT) #define _KERNEL # endif /* defined(HASPROCFS_PFSROOT) */ #include # if defined(HASPROCFS_PFSROOT) #undef _KERNEL #define Proot PFSroot #define Pproc PFSproc #define Pcurproc PFScurproc #define Pmem PFSmem #define Pregs PFSregs #define Pfile PFSfile #define Pfpregs PFSfpregs #define Pctl PFSctl #define Pstatus PFSstatus #define Pnote PFSnote #define Pnotepg PFSnotepg # if defined(NetBSDV) # if NETBSDV>=2000000 #define Pfd PFSfd # endif /* NETBSDV>=2000000 */ # if NETBSDV>=1006000 #define Pmap PFSmap #define Pmaps PFSmaps # endif /* NETBSDV>=1006000 */ # endif /* defined(NetBSDV) */ # endif /* defined(HASPROCFS_PFSROOT) */ #include # endif /* defined(HASPROCFS) */ # if defined(HASPTYFS) #define _KERNEL #include #include #undef _KERNEL # endif /* defined(HASPTYFS) */ #define KERNEL #define _KERNEL #include #include # if defined(HAS_ADVLOCK_ARGS) struct vop_advlock_args; # endif /* defined(HAS_ADVLOCK_ARGS) */ # if defined(DTYPE_KQUEUE) #define HASKQUEUE /* has the kqueue file type */ # if defined(OPENBSDV) #include # endif /* defined(OPENBSDV) */ # endif /* defined(DTYPE_KQUEUE) */ #include #undef KERNEL #undef _KERNEL # if defined(UVM) # if defined(OPENBSDV) #define _UVM_UVM_FAULT_I_H_ 1 /* avoid OpenBSD's /* # endif /* defined(UVM) */ # if defined(HAS_UVM_INCL) #include #include #include #include # else /* !defined(HAS_UVM_INCL) */ #include #include #include #include # endif /* defined(HAS_UVM_INCL) */ # if defined(HAS_SYS_PIPEH) # if OPENBSDV==2030 && defined(__sparc__) # if defined(nbpg) #undef nbpg # endif /* defined(nbpg) */ #define nbpg 4096 /* WARNING!!! This should be 8192 for sun4, * but there's not much chance this value will * ever be used by any lsof code. (See the * use of PIPE_NODIRECT in . */ # endif /* OPENBSDV==2030 && defined(__sparc__) */ #include #endif /* defined(HAS_SYS_PIPEH) */ #define COMP_P const void #define DEVINCR 1024 /* device table malloc() increment */ typedef u_long KA_T; #define KMEM "/dev/kmem" #define MALLOC_P void #define FREE_P MALLOC_P #define MALLOC_S size_t # if !defined(MAXSYSCMDL) #define MAXSYSCMDL MAXCOMLEN /* max system command name length */ # endif /* !defined(MAXSYSCMDL) */ # if defined(N_UNIXV) #define N_UNIX_TMP(x) #x #define N_UNIX_STR(x) N_UNIX_TMP(x) #define N_UNIX N_UNIX_STR(N_UNIXV) # endif /* defined(N_UNIXV) */ #define QSORT_P void #define READLEN_T int #define STRNCPY_L size_t #define SWAP "/dev/drum" #define SZOFFTYPE unsigned long long /* size and offset internal storage * type */ #define SZOFFPSPEC "ll" /* SZOFFTYPE print specification * modifier */ /* * Global storage definitions (including their structure definitions) */ extern struct file *Cfp; extern kvm_t *Kd; extern KA_T Kpa; struct l_vfs { KA_T addr; /* kernel address */ fsid_t fsid; /* file system ID */ char type[MFSNAMELEN]; /* type of file system */ char *dir; /* mounted directory */ char *fsname; /* file system name */ struct l_vfs *next; /* forward link */ }; extern struct l_vfs *Lvfs; struct mounts { char *dir; /* directory (mounted on) */ char *fsname; /* file system * (symbolic links unresolved) */ char *fsnmres; /* file system * (symbolic links resolved) */ dev_t dev; /* directory st_dev */ dev_t rdev; /* directory st_rdev */ INODETYPE inode; /* directory st_ino */ mode_t mode; /* directory st_mode */ mode_t fs_mode; /* file_system st_mode */ struct mounts *next; /* forward link */ }; #define X_NCACHE "ncache" #define X_NCSIZE "ncsize" #define NL_NAME n_name extern int Np; /* number of kernel processes */ # if defined(HASKVMGETPROC2) struct kinfo_proc2 *P; /* local process table copy */ # else /* ! defined(HASKVMGETPROC2) */ struct kinfo_proc *P; /* local process table copy */ # endif /* defined(HASKVMGETPROC2) */ extern int pgshift; /* kernel's page shift */ struct sfile { char *aname; /* argument file name */ char *name; /* file name (after readlink()) */ char *devnm; /* device name (optional) */ dev_t dev; /* device */ dev_t rdev; /* raw device */ u_short mode; /* S_IFMT mode bits from stat() */ int type; /* file type: 0 = file system * 1 = regular file */ INODETYPE i; /* inode number */ int f; /* file found flag */ struct sfile *next; /* forward link */ }; /* * Definitions for rdev.c */ #define DIRTYPE dirent #define HASDNAMLEN 1 /* struct DIRTYPE has d_namlen element */ /* * Definitions for rnam.c and rnmh.c */ # if defined(HASNCACHE) # if (defined(OPENBSDV) && OPENBSDV>=2010) || (defined(NETBSDV) && NETBSDV>=1002000) #include #endif /* (defined(OPENBSDV) && OPENBSDV>=2010) || (defined(NETBSDV) && NETBSDV>=1002000) */ #include #include #define NCACHE namecache /* kernel's structure name */ #define NCACHE_NM nc_name /* name in NCACHE */ #define NCACHE_NMLEN nc_nlen /* name length in NCACHE */ #define NCACHE_NODEADDR nc_vp /* node address in NCACHE */ #define NCACHE_PARADDR nc_dvp /* parent node address in NCACHE */ # if (defined(OPENBSDV) && OPENBSDV>=2010) || (defined(NETBSDV) && NETBSDV>=1002000) #define NCACHE_NXT nc_hash.le_next /* link in NCACHE */ # else /* (defined(OPENBSDV) && OPENBSDV>=2010) || (defined(NETBSDV) && NETBSDV>=1002000) */ # if defined(NetBSD1_0) && NetBSD<1994101 #define NCACHE_NXT nc_nxt /* link in NCACHE */ # else /* !defined(NetBSD1_0) || NetBSD>=1994101 */ #define NCACHE_NXT nc_lru.tqe_next /* link in NCACHE */ # endif /* defined(NetBSD1_0) && NetBSD<1994101 */ # endif /* (defined(OPENBSDV) && OPENBSDV>=2010) || (defined(NETBSDV) && NETBSDV>=1002000) */ # if defined(HASNCVPID) #define NCACHE_PARID nc_dvpid /* parent node ID in NCACHE */ #define NCACHE_NODEID nc_vpid /* node ID in NCACHE */ # endif /* defined(HASNCVPID) */ # endif /* defined(HASNCACHE) */ #endif /* NETBSD_LSOF_H */ lsof-4.86+dfsg.orig/dialects/n+obsd/dnode1.c0000444000175000017500000000453010275734075020756 0ustar nicholasnicholas/* * dnode1.c - NetBSD and OpenBSD node functions for lsof * * This module must be separate to keep separate the multiple kernel inode * structure definitions. */ /* * Copyright 1995 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dnode1.c,v 1.8 2005/08/08 19:53:24 abe Exp $"; #endif #include "lsof.h" #if defined(HAS9660FS) /* * Undo some conflicting node header file definitions. */ #undef doff_t #undef i_dev #undef i_devvp #undef i_number #undef IN_ACCESS #undef IN_LOCKED #undef i_size #undef IN_WANTED /* * At last, #include the desired header files. */ # if HAS9660FS==1 #include #include # else /* HAS9660FS!=1 */ #include #include # endif /* HAS9660FS==1 */ /* * read_iso_node() -- read CD 9660 iso_node */ int read_iso_node(v, d, ino, nl, sz) struct vnode *v; /* containing vnode */ dev_t *d; /* returned device number */ INODETYPE *ino; /* returned inode number */ long *nl; /* returned link count */ SZOFFTYPE *sz; /* returned size */ { struct iso_node i; if (!v->v_data || kread((KA_T)v->v_data, (char *)&i, sizeof(i))) return(1); *d = i.i_dev; *ino = (INODETYPE)i.i_number; *nl = i.inode.iso_links; *sz = (SZOFFTYPE)i.i_size; return(0); } #endif /* defined(HAS9660FS) */ lsof-4.86+dfsg.orig/dialects/n+obsd/Mksrc0000555000175000017500000000105406705350103020430 0ustar nicholasnicholas#!/bin/sh # # Mksrc - make NetBSD and OpenBSD source files # # WARNING: This script assumes it is running from the main directory # of the lsof, version 4 distribution. # # One environment variable applies: # # LSOF_MKC is the method for creating the source files. # It defaults to "ln -s". A common alternative is "cp". # # $Id: Mksrc,v 1.5 99/04/15 06:40:37 abe Exp $ D=dialects/n+obsd L="dlsof.h dmnt.c dnode.c dnode1.c dproc.c dproto.h dsock.c dstore.c machine.h" for i in $L do rm -f $i $LSOF_MKC $D/$i $i echo "$LSOF_MKC $D/$i $i" done lsof-4.86+dfsg.orig/dialects/n+obsd/dnode.c0000444000175000017500000007436610613427256020707 0ustar nicholasnicholas/* * dnode.c - NetBSD and OpenBSD node functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dnode.c,v 1.38 2007/04/24 16:22:02 abe Exp $"; #endif #include "lsof.h" #if defined(HAS_DINODE_U) #define DINODE_U dinode_u #else /* !defined(HAS_DINODE_U) */ #define DINODE_U i_din #endif /* defined(HAS_DINODE_U) */ #if defined(HASFDESCFS) && HASFDESCFS==1 _PROTOTYPE(static int lkup_dev_tty,(dev_t *dr, INODETYPE *ir)); #endif /* defined(HASFDESCFS) && HASFDESCFS==1 */ #if defined(HAS_UM_UFS) #define UFS1 UM_UFS1 #define UFS2 UM_UFS2 #endif /* defined(HAS_UM_UFS) */ #if defined(HASPROCFS) _PROTOTYPE(static void getmemsz,(pid_t pid)); # if !defined(PGSHIFT) #define PGSHIFT pgshift # endif /* !defined(PGSHIFT) */ /* * getmemsz() - get memory size of a /proc//mem entry */ static void getmemsz(pid) pid_t pid; { int n; struct vmspace vm; #if defined(HASKVMGETPROC2) struct kinfo_proc2 *p; #else /* !defined(HASKVMGETPROC2) */ struct kinfo_proc *p; #endif /* defined(HASKVMGETPROC2) */ for (n = 0, p = P; n < Np; n++, p++) { if (p->P_PID == pid) { if (!p->P_VMSPACE || kread((KA_T)p->P_VMSPACE, (char *)&vm, sizeof(vm))) return; # if defined(OPENBSDV) Lf->sz = (SZOFFTYPE)((vm.vm_tsize + vm.vm_dsize + vm.vm_ssize) * sysconf(_SC_PAGESIZE)); # else /* !defined(OPENBSDV */ Lf->sz = (SZOFFTYPE)ctob(vm.vm_tsize + vm.vm_dsize + vm.vm_ssize); # endif /* defined(OPENBSDV) */ Lf->sz_def = 1; return; } } } #undef PGSHIFT #endif /* defined(HASPROCFS) */ #if defined(HASFDESCFS) && HASFDESCFS==1 /* * lkup_dev_tty() - look up /dev/tty */ static int lkup_dev_tty(dr, ir) dev_t *dr; /* place to return device number */ INODETYPE *ir; /* place to return inode number */ { int i; readdev(0); # if defined(HASDCACHE) lkup_dev_tty_again: # endif /* defined(HASDCACHE) */ for (i = 0; i < Ndev; i++) { if (strcmp(Devtp[i].name, "/dev/tty") == 0) { # if defined(HASDCACHE) if (DCunsafe && !Devtp[i].v && !vfy_dev(&Devtp[i])) goto lkup_dev_tty_again; # endif /* defined(HASDCACHE) */ *dr = Devtp[i].rdev; *ir = Devtp[i].inode; return(1); } } # if defined(HASDCACHE) if (DCunsafe) { (void) rereaddev(); goto lkup_dev_tty_again; } # endif /* defined(HASDCACHE) */ return(-1); } #endif /* defined(HASFDESCFS) && HASFDESCFS==1 */ #if defined(HASKQUEUE) /* * process_kqueue() -- process kqueue file * * Strictly speaking this function should appear in dfile.c, because it is * a file processing function. However, the Net and Open BSD sources don't * require a dfile.c, so this is the next best location for the function. */ void process_kqueue(ka) KA_T ka; /* kqueue file structure address */ { # if defined(OPENBSDV) struct kqueue kq; /* kqueue structure */ # endif /* defined(OPENBSDV) */ (void) snpf(Lf->type, sizeof(Lf->type), "KQUEUE"); enter_dev_ch(print_kptr(ka, (char *)NULL, 0)); # if defined(OPENBSDV) if (!ka || kread(ka, (char *)&kq, sizeof(kq))) return; (void) snpf(Namech, Namechl, "count=%d, state=%#x", kq.kq_count, kq.kq_state); enter_nm(Namech); # endif /* defined(OPENBSDV) */ } #endif /* defined(HASKQUEUE) */ /* * process_node() - process vnode */ void process_node(va) KA_T va; /* vnode kernel space address */ { dev_t dev, rdev; unsigned char devs; unsigned char lt; unsigned char ns; unsigned char rdevs; char *ep, *ty; struct lockf lf, *lff, *lfp; struct inode i; struct mfsnode m; struct nfsnode n; enum nodetype {NONODE, CDFSNODE, DOSNODE, EXT2NODE, FDESCNODE, INODE, KERNFSNODE, MFSNODE, NFSNODE, PFSNODE, PTYFSNODE} nty; enum vtype type; struct vnode *v, vb; struct l_vfs *vfs; #if defined(HAS9660FS) dev_t iso_dev; INODETYPE iso_ino; long iso_nlink; int iso_stat; SZOFFTYPE iso_sz; #endif /* defined(HAS9660FS) */ #if defined(HASFDESCFS) struct fdescnode f; # if HASFDESCFS==1 static dev_t f_tty_dev; static INODETYPE f_tty_ino; static int f_tty_s = 0; # endif /* HASFDESCFS==1 */ #endif /* defined(HASFDESCFS) */ #if defined(HASEXT2FS) # if defined(HASI_E2FS_PTR) struct ext2fs_dinode ed; # endif /* defined(HASI_E2FS_PTR) */ struct ext2fs_dinode *edp = (struct ext2fs_dinode *)NULL; #endif /* defined(HASEXT2FS) */ #if defined(HASI_FFS1) unsigned char ffs = 0; unsigned char u1s = 0; unsigned char u2s = 0; struct ufs1_dinode u1; struct ufs2_dinode u2; struct ufsmount um; #endif /* defined(HASI_FFS1) */ #if defined(HASKERNFS) struct kernfs_node kn; struct stat ksb; int ksbs; struct kern_target kt; int ktnl; char ktnm[MAXPATHLEN+1]; #endif /* defined(HASKERNFS) */ #if defined(HASMSDOSFS) struct denode d; u_long dpb; INODETYPE nn; struct msdosfsmount pm; #endif /* defined(HASMSDOSFS) */ #if defined(HASNFSVATTRP) struct vattr nv; #define NVATTR nv #else /* !defined(HASNFSVATTRP) */ #define NVATTR n.n_vattr #endif /* defined(HASNFSVATTRP) */ #if defined(HASNULLFS) struct null_node nu; int sc = 0; struct l_vfs *nvfs = (struct l_vfs *)NULL; #endif /* defined(HASNULLFS) */ #if defined(HASPROCFS) struct pfsnode p; struct procfsid *pfi; size_t sz; #endif /* defined(HASPROCFS) */ #if defined(HASPTYFS) struct ptyfsnode pt; struct specinfo si; #endif /* defined(HASPTYFS) */ #if defined(HASNULLFS) process_overlaid_node: if (++sc > 1024) { (void) snpf(Namech, Namechl, "too many overlaid nodes"); enter_nm(Namech); return; } #endif /* defined(HASNULLFS) */ /* * Initialize miscellaneous variables. This is done so that processing an * overlaid node will be a fresh start. */ devs = rdevs = 0; nty = NONODE; Namech[0] = '\0'; #if defined(HAS9660FS) iso_stat = 0; #endif /* defined(HAS9660FS) */ #if defined(HASKERNFS) ksbs = 0; #endif /* defined(HASKERNFS) */ #if defined(HASEXT2FS) edp = (struct ext2fs_dinode *)NULL; #endif /* defined(HASEXT2FS) */ #if defined(HASI_FFS1) ffs = u1s = u2s = 0; #endif /* defined(HASI_FFS1) */ /* * Read the vnode. */ if (!va) { enter_nm("no vnode address"); return; } v = &vb; if (readvnode(va, v)) { enter_nm(Namech); return; } #if defined(HASNCACHE) Lf->na = va; # if defined(HASNCVPID) Lf->id = v->v_id; # endif /* defined(HASNCVPID) */ #endif /* defined(HASNCACHE) */ #if defined(HASFSTRUCT) Lf->fna = va; Lf->fsv |= FSV_NI; #endif /* defined(HASFSTRUCT) */ /* * Get the vnode type. */ if (!v->v_mount) vfs = (struct l_vfs *)NULL; else { vfs = readvfs((KA_T)v->v_mount); if (vfs) { if (strcmp(vfs->type, MOUNT_NFS) == 0) Ntype = N_NFS; #if defined(HASKERNFS) else if (strcmp(vfs->type, MOUNT_KERNFS) == 0) Ntype = N_KERN; #endif /* defined(HASKERNFS) */ #if defined(HASPROCFS) else if (strcmp(vfs->type, MOUNT_PROCFS) == 0) Ntype = N_PROC; #endif /* defined(HASPROCFS) */ #if defined(HAS9660FS) else if (strcmp(vfs->type, MOUNT_CD9660) == 0) Ntype = N_CDFS; #endif /* defined(HAS9660FS) */ } } if (Ntype == N_REGLR) { switch (v->v_type) { case VFIFO: Ntype = N_FIFO; break; } } /* * Read the successor node. */ switch (v->v_tag) { #if defined(HAS9660FS) case VT_ISOFS: if (read_iso_node(v, &iso_dev, &iso_ino, &iso_nlink, &iso_sz)) { (void) snpf(Namech, Namechl, "can't read iso_node at: %s", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } iso_stat = 1; nty = CDFSNODE; break; #endif /* defined(HAS9660FS) */ #if defined(HASFDESCFS) case VT_FDESC: if (!v->v_data || kread((KA_T)v->v_data, (char *)&f, sizeof(f))) { (void) snpf(Namech, Namechl, "can't read fdescnode at: %x", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } nty = FDESCNODE; break; #endif /* defined(HASFDESCFS) */ #if defined(HASKERNFS) case VT_KERNFS: /* * Read the kernfs_node. */ if (!v->v_data || kread((KA_T)v->v_data, (char *)&kn, sizeof(kn))) { if (v->v_type != VDIR || !(v->v_flag && VROOT)) { (void) snpf(Namech, Namechl, "can't read kernfs_node at: %s", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } else kn.kf_kt = (struct kern_target *)NULL; } /* * Generate the /kern file name by reading the kern_target to which * the kernfs_node points. */ if (kn.kf_kt && kread((KA_T)kn.kf_kt, (char *)&kt, sizeof(kt)) == 0 && (ktnl = (int)kt.kt_namlen) > 0 && kt.kt_name) { if (ktnl > (sizeof(ktnm) - 1)) ktnl = sizeof(ktnm) - 1; if (!kread((KA_T)kt.kt_name, ktnm, ktnl)) { ktnm[ktnl] = 0; ktnl = strlen(ktnm); if (ktnl > (MAXPATHLEN - strlen(_PATH_KERNFS) - 2)) { ktnl = MAXPATHLEN - strlen(_PATH_KERNFS) - 2; ktnm[ktnl] = '\0'; } (void) snpf(Namech, Namechl, "%s/%s", _PATH_KERNFS, ktnm); } } /* * If this is the /kern root directory, its name, inode number and * size are fixed; otherwise, safely stat() the file to get the * inode number and size. */ if (v->v_type == VDIR && (v->v_flag & VROOT)) { (void) snpf(Namech, Namechl, "%s", _PATH_KERNFS); ksb.st_ino = (ino_t)2; ksb.st_size = DEV_BSIZE; ksbs = 1; } else if (Namech[0] && statsafely(Namech, &ksb) == 0) ksbs = 1; nty = KERNFSNODE; break; #endif /* defined(HASKERNFS) */ case VT_MFS: if (!v->v_data || kread((KA_T)v->v_data, (char *)&m, sizeof(m))) { (void) snpf(Namech, Namechl, "can't read mfsnode at: %s", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } nty = MFSNODE; break; #if defined(HASMSDOSFS) case VT_MSDOSFS: if (!v->v_data || kread((KA_T)v->v_data, (char *)&d, sizeof(d))) { (void) snpf(Namech, Namechl, "can't read denode at: %s", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } nty = DOSNODE; break; #endif /* defined(HASMSDOSFS) */ case VT_NFS: if (!v->v_data || kread((KA_T)v->v_data, (char *)&n, sizeof(n))) { (void) snpf(Namech, Namechl, "can't read nfsnode at: %s", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } #if defined(HASNFSVATTRP) if (!n.n_vattr || kread((KA_T)n.n_vattr, (char *)&nv, sizeof(nv))) { (void) snpf(Namech, Namechl, "can't read n_vattr at: %x", print_kptr((KA_T)n.n_vattr, (char *)NULL, 0)); enter_nm(Namech); return; } #endif /* defined(HASNFSVATTRP) */ nty = NFSNODE; break; #if defined(HASNULLFS) case VT_NULL: if ((sc == 1) && vfs) nvfs = vfs; if (!v->v_data || kread((KA_T)v->v_data, (char *)&nu, sizeof(nu))) { (void) snpf(Namech, Namechl, "can't read null_node at: %s", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } if (!nu.null_lowervp) { (void) snpf(Namech, Namechl, "null_node overlays nothing"); enter_nm(Namech); return; } va = (KA_T)nu.null_lowervp; goto process_overlaid_node; #endif /* defined(HASNULLFS) */ #if defined(HASPROCFS) case VT_PROCFS: if (!v->v_data || kread((KA_T)v->v_data, (char *)&p, sizeof(p))) { (void) snpf(Namech, Namechl, "can't read pfsnode at: %s", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } nty = PFSNODE; break; #endif /* defined(HASPROCFS) */ #if defined(HASPTYFS) case VT_PTYFS: if (!v->v_data || kread((KA_T)v->v_data, (char *)&pt, sizeof(pt))) { (void) snpf(Namech, Namechl, "can't read ptyfsnode at: %s", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } nty = PTYFSNODE; break; #endif /* defined(HASPTYFS) */ #if defined(HASEXT2FS) case VT_EXT2FS: #endif /* defined(HASEXT2FS) */ #if defined(HASLFS) case VT_LFS: #endif /* defined(HASLFS) */ case VT_UFS: if (!v->v_data || kread((KA_T)v->v_data, (char *)&i, sizeof(i))) { (void) snpf(Namech, Namechl, "can't read inode at: %s", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } #if defined(HASEXT2FS) if (v->v_tag == VT_EXT2FS) { nty = EXT2NODE; # if defined(HASI_E2FS_PTR) if (i.DINODE_U.e2fs_din && !kread((KA_T)i.DINODE_U.e2fs_din, (char *)&ed, sizeof(ed))) edp = &ed; # else /* !defined(HASI_E2FS_PTR) */ # if HASEXT2FS<2 edp = &i.DINODE_U.e2fs_din; # else /* HASEXT2FS>=2 */ edp = &i.i_e2din; # endif /* HASEXT2FS>=2 */ # endif /* defined(HASI_E2FS_PTR) */ } else #endif /* defined(HASEXT2FS) */ { nty = INODE; #if defined(HASI_FFS1) /* * If there are multiple FFS's, read the relevant structures. */ if (i.i_ump && !kread((KA_T)i.i_ump, (char *)&um, sizeof(um))) { if (um.um_fstype == UFS1) { ffs = 1; if (i.DINODE_U.ffs1_din && !kread((KA_T)i.DINODE_U.ffs1_din, (char *)&u1, sizeof(u1))) { u1s = 1; } } else if (um.um_fstype == UFS2) { ffs = 2; if (i.DINODE_U.ffs2_din && !kread((KA_T)i.DINODE_U.ffs2_din, (char *)&u2, sizeof(u2))) { u2s = 1; } } } #endif /* defined(HASI_FFS1) */ } if ((lff = i.i_lockf)) { /* * Determine the lock state. */ lfp = lff; do { if (kread((KA_T)lfp, (char *)&lf, sizeof(lf))) break; lt = 0; switch(lf.lf_flags & (F_FLOCK|F_POSIX)) { case F_FLOCK: if (Cfp && (struct file *)lf.lf_id == Cfp) lt = 1; break; case F_POSIX: if ((KA_T)lf.lf_id == Kpa) lt = 1; #if defined(HAS_LWP_H) && !defined(HAS_LF_LWP) else { struct lwp lw; if (!kread((KA_T)lf.lf_id, (char *)&lw, sizeof(lw)) && (KA_T)lw.l_proc == Kpa) lt = 1; } #endif /* defined(HAS_LWP_H) && !defined(HAS_LF_LWP) */ break; } if (!lt) continue; if (lf.lf_start == (off_t)0 && lf.lf_end == 0xffffffffffffffffLL) lt = 1; else lt = 0; if (lf.lf_type == F_RDLCK) Lf->lock = lt ? 'R' : 'r'; else if (lf.lf_type == F_WRLCK) Lf->lock = lt ? 'W' : 'w'; else if (lf.lf_type == (F_RDLCK | F_WRLCK)) Lf->lock = 'u'; break; } while ((lfp = lf.lf_next) && lfp != lff); } break; default: if (v->v_type == VBAD || v->v_type == VNON) break; (void) snpf(Namech, Namechl, "unknown file system type: %d", v->v_tag); enter_nm(Namech); return; } /* * Get device and type for printing. */ type = v->v_type; switch (nty) { #if defined(HASMSDOSFS) case DOSNODE: dev = d.de_dev; devs = 1; break; #endif /* defined(HASMSDOSFS) */ #if defined(HASFDESCFS) case FDESCNODE: # if defined(HASFDLINK) if (f.fd_link && !kread((KA_T)f.fd_link, Namech, Namechl - 1)) { Namech[Namechl - 1] = '\0'; break; } # endif /* defined(HASFDLINK) */ # if HASFDESCFS==1 if (f.fd_type == Fctty) { if (f_tty_s == 0) f_tty_s = lkup_dev_tty(&f_tty_dev, &f_tty_ino); if (f_tty_s == 1) { dev = DevDev; rdev = f_tty_dev; Lf->inode = f_tty_ino; devs = Lf->inp_ty = rdevs = 1; } } break; # endif /* HASFDESCFS==1 */ #endif /* defined(HASFDESCFS) */ #if defined(HASEXT2FS) case EXT2NODE: dev = i.i_dev; devs = 1; if ((type == VCHR) || (type == VBLK)) { # if defined(HASI_E2FS_PTR) if (edp) { rdev = edp->e2di_rdev; rdevs = 1; } # else /* !defined(HASI_E2FS_PTR) */ # if HASEXT2FS<2 rdev = i.DINODE_U.e2fs_din.e2di_rdev; # else /* HASEXT2FS>=2 */ rdev = i.i_e2din.e2di_rdev; # endif /* HASEXT2FS>=2 */ rdevs = 1; # endif /* defined(HASI_E2FS_PTR) */ } break; #endif /* defined(HASEXT2FS) */ case INODE: dev = i.i_dev; devs = 1; if ((type == VCHR) || (type == VBLK)) { #if defined(HASI_FFS) rdev = i.i_ffs_rdev; rdevs = 1; #else /* !defined(HASI_FFS) */ # if defined(HASI_FFS1) if (ffs == 1) { if (u1s) { rdev = u1.di_rdev; rdevs = 1; } } else if (ffs == 2) { if (u2s) { rdev = u2.di_rdev; rdevs = 1; } } # else /* !defined(HASI_FFS1) */ rdev = i.i_rdev; rdevs = 1; # endif /* defined(HASI_FFS1) */ #endif /* defined(HASI_FFS) */ } break; #if defined(HASKERNFS) case KERNFSNODE: if (vfs) { # if defined(HASSTATVFS) dev = (dev_t)vfs->fsid.__fsid_val[0]; # else /* !defined(HASSTATVFS) */ dev = (dev_t)vfs->fsid.val[0]; # endif /* defined(HASSTATVFS) */ devs = 1; } break; #endif /* defined(HASKERNFS) */ #if defined(HAS9660FS) case CDFSNODE: if (iso_stat) { dev = iso_dev; devs = 1; } break; #endif /* defined(HAS9660FS) */ case NFSNODE: dev = NVATTR.va_fsid; devs = 1; break; #if defined(HASPTYFS) case PTYFSNODE: if (v->v_un.vu_specinfo && !kread((KA_T)v->v_un.vu_specinfo, (char *)&si, sizeof(si))) { rdev = si.si_rdev; rdevs = 1; } if (vfs) { # if defined(HASSTATVFS) dev = (dev_t)vfs->fsid.__fsid_val[0]; # else /* !defined(HASSTATVFS) */ dev = (dev_t)vfs->fsid.val[0]; # endif /* defined(HASSTATVFS) */ devs = 1; } break; #endif /* defined(HASPTYFS) */ } /* * Obtain the inode number. */ switch (nty) { #if defined(HASMSDOSFS) case DOSNODE: if (d.de_pmp && !kread((KA_T)d.de_pmp, (char *)&pm, sizeof(pm))) { dpb = (u_long)(pm.pm_BytesPerSec / sizeof(struct direntry)); if (d.de_Attributes & ATTR_DIRECTORY) { if (d.de_StartCluster == MSDOSFSROOT) nn = (INODETYPE)1; else nn = (INODETYPE)(cntobn(&pm, d.de_StartCluster) * dpb); } else { if (d.de_dirclust == MSDOSFSROOT) nn = (INODETYPE)(roottobn(&pm, 0) * dpb); else nn = (INODETYPE)(cntobn(&pm, d.de_dirclust) * dpb); nn += (INODETYPE)(d.de_diroffset / sizeof(struct direntry)); } Lf->inode = nn; Lf->inp_ty = 1; } break; #endif /* defined(HASMSDOSFS) */ #if defined(HASEXT2FS) case EXT2NODE: #endif /* defined(HASEXT2FS) */ case INODE: Lf->inode = (INODETYPE)i.i_number; Lf->inp_ty = 1; break; #if defined(HASKERNFS) case KERNFSNODE: if (ksbs) { Lf->inode = (INODETYPE)ksb.st_ino; Lf->inp_ty = 1; } break; #endif /* defined(HASKERNFS) */ #if defined(HAS9660FS) case CDFSNODE: if (iso_stat) { Lf->inode = iso_ino; Lf->inp_ty = 1; } break; #endif /* defined(HAS9660FS) */ case NFSNODE: Lf->inode = (INODETYPE)NVATTR.va_fileid; Lf->inp_ty = 1; break; #if defined(HASPROCFS) case PFSNODE: Lf->inode = (INODETYPE)p.pfs_fileno; Lf->inp_ty = 1; break; #endif /* defined(HASPROCFS) */ #if defined(HASPTYFS) case PTYFSNODE: if (pt.ptyfs_type == PTYFSptc) { if (pt.ptyfs_fileno > 0x3fffffff) Lf->inode = (INODETYPE)(pt.ptyfs_fileno & 0x3fffffff); else Lf->inode = (INODETYPE)(pt.ptyfs_fileno - 1); } else Lf->inode = (INODETYPE)pt.ptyfs_fileno; Lf->inp_ty = 1; break; #endif /* defined(HASPTYFS) */ } /* * Obtain the file size. */ if (Foffset) Lf->off_def = 1; else { switch (Ntype) { #if defined(HAS9660FS) case N_CDFS: if (iso_stat) { Lf->sz = (SZOFFTYPE)iso_sz; Lf->sz_def = 1; } break; #endif /* defined(HAS9660FS) */ case N_FIFO: if (!Fsize) Lf->off_def = 1; break; #if defined(HASKERNFS) case N_KERN: if (ksbs) { Lf->sz = (SZOFFTYPE)ksb.st_size; Lf->sz_def = 1; } break; #endif /* defined(HASKERNFS) */ case N_NFS: if (nty == NFSNODE) { Lf->sz = (SZOFFTYPE)NVATTR.va_size; Lf->sz_def = 1; } break; #if defined(HASPROCFS) case N_PROC: if (nty == PFSNODE) { switch (p.pfs_type) { case Proot: case Pproc: Lf->sz = (SZOFFTYPE)DEV_BSIZE; Lf->sz_def = 1; break; case Pcurproc: Lf->sz = (SZOFFTYPE)DEV_BSIZE; Lf->sz_def = 1; break; case Pmem: (void) getmemsz(p.pfs_pid); break; case Pregs: Lf->sz = (SZOFFTYPE)sizeof(struct reg); Lf->sz_def = 1; break; # if defined(FP_QSIZE) case Pfpregs: Lf->sz = (SZOFFTYPE)sizeof(struct fpreg); Lf->sz_def = 1; break; # endif /* defined(FP_QSIZE) */ } } break; #endif /* defined(HASPROCFS) */ case N_REGLR: if (type == VREG || type == VDIR) { switch (nty) { case INODE: #if defined(HASI_FFS) Lf->sz = (SZOFFTYPE)i.i_ffs_size; Lf->sz_def = 1; break; #else /* !defined(HASI_FFS) */ # if defined(HASI_FFS1) if (ffs == 1) { if (u1s) { Lf->sz = (SZOFFTYPE)u1.di_size; Lf->sz_def = 1; } } else if (ffs == 2) { if (u2s) { Lf->sz = (SZOFFTYPE)u2.di_size; Lf->sz_def = 1; } } break; # else /* !defined(HASI_FFS1) */ Lf->sz = (SZOFFTYPE)i.i_size; Lf->sz_def = 1; # endif /* defined(HASI_FFS1) */ #endif /* defined(HASI_FFS) */ break; #if defined(HASMSDOSFS) case DOSNODE: Lf->sz = (SZOFFTYPE)d.de_FileSize; Lf->sz_def = 1; break; #endif /* defined(HASMSDOSFS) */ case MFSNODE: Lf->sz = (SZOFFTYPE)m.mfs_size; Lf->sz_def = 1; break; #if defined(HASEXT2FS) case EXT2NODE: # if defined(HASI_E2FS_PTR) if (edp) { Lf->sz = (SZOFFTYPE)edp->e2di_size; Lf->sz_def = 1; } # else /* !defined(HASI_E2FS_PTR) */ Lf->sz = (SZOFFTYPE)i.i_e2fs_size; Lf->sz_def = 1; # endif /* defined(HASI_E2FS_PTR) */ break; #endif /* defined(HASEXT2FS) */ } } else if ((type == VCHR || type == VBLK) && !Fsize) Lf->off_def = 1; break; } } /* * Record the link count. */ if (Fnlink) { switch(Ntype) { #if defined(HAS9660FS) case N_CDFS: if (iso_stat) { Lf->nlink = iso_nlink; Lf->nlink_def = 1; } break; #endif /* defined(HAS9660FS) */ #if defined(HASKERNFS) case N_KERN: if (ksbs) { Lf->nlink = (long)ksb.st_nlink; Lf->nlink_def = 1; } break; #endif /* defined(HASKERNFS) */ case N_NFS: if (nty == NFSNODE) { Lf->nlink = (long)NVATTR.va_nlink; Lf->nlink_def = 1; } break; case N_REGLR: switch (nty) { case INODE: #if defined(HASEFFNLINK) Lf->nlink = (long)i.HASEFFNLINK; #else /* !defined(HASEFFNLINK) */ # if defined(HASI_FFS) Lf->nlink = (long)i.i_ffs_nlink; # else /* !defined(HASI_FFS) */ # if defined(HASI_FFS1) if (ffs == 1) { if (u1s) Lf->nlink = (long)u1.di_nlink; } else if (ffs == 2) { if (u2s) Lf->nlink = (long)u2.di_nlink; } # else /* !defined(HASI_FFS1) */ Lf->nlink = (long)i.i_nlink; # endif /* defined(HASI_FFS1) */ # endif /* defined(HASI_FFS) */ #endif /* defined(HASEFFNLINK) */ Lf->nlink_def = 1; break; #if defined(HASMSDOSFS) case DOSNODE: Lf->nlink = (long)d.de_refcnt; Lf->nlink_def = 1; break; #endif /* defined(HASMSDOSFS) */ #if defined(HASEXT2FS) case EXT2NODE: # if defined(HASI_E2FS_PTR) if (edp) { Lf->nlink = (long)edp->e2di_nlink; Lf->nlink_def = 1; } # else /* !defined(HASI_E2FS_PTR) */ Lf->nlink = (long)i.i_e2fs_nlink; Lf->nlink_def = 1; # endif /* defined(HASI_E2FS_PTR) */ break; #endif /* defined(HASEXT2FS) */ } break; } if (Lf->nlink_def && Nlink && (Lf->nlink < Nlink)) Lf->sf |= SELNLINK; } /* * Record an NFS file selection. */ if (Ntype == N_NFS && Fnfs) Lf->sf |= SELNFS; #if defined(HASNULLFS) /* * If there is a saved nullfs vfs pointer, propagate its device number. */ if (nvfs) { # if defined(HASSTATVFS) dev = nvfs->fsid.__fsid_val[0]; # else /* !defined(HASSTATVFS) */ dev = nvfs->fsid.val[0]; # endif /* defined(HASSTATVFS) */ devs = 1; } #endif /* defined(HASNULLFS) */ /* * Save the file system names. */ if (vfs) { Lf->fsdir = vfs->dir; Lf->fsdev = vfs->fsname; } /* * Save the device numbers and their states. * * Format the vnode type, and possibly the device name. */ Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; switch (type) { case VNON: ty ="VNON"; break; case VREG: ty = "VREG"; break; case VDIR: ty = "VDIR"; break; case VBLK: ty = "VBLK"; Ntype = N_BLK; break; case VCHR: ty = "VCHR"; Ntype = N_CHR; break; case VLNK: ty = "VLNK"; break; #if defined(VSOCK) case VSOCK: ty = "SOCK"; break; #endif /* defined(VSOCK) */ case VBAD: ty = "VBAD"; break; case VFIFO: ty = "FIFO"; break; default: (void) snpf(Lf->type, sizeof(Lf->type), "%04o", (type & 0xfff)); ty = NULL; } if (ty) (void) snpf(Lf->type, sizeof(Lf->type), "%s", ty); Lf->ntype = Ntype; /* * Handle some special cases: * * ioctl(fd, TIOCNOTTY) files; * /kern files * memory node files; * /proc files; * ptyfs files. */ if (type == VBAD) (void) snpf(Namech, Namechl, "(revoked)"); else if (nty == MFSNODE) { Lf->dev_def = Lf->rdev_def = 0; (void) snpf(Namech, Namechl, "%#x", m.mfs_baseoff); enter_dev_ch("memory"); } #if defined(HASPROCFS) else if (nty == PFSNODE) { Lf->dev_def= Lf->rdev_def = 0; ty = NULL; (void) snpf(Namech, Namechl, "/%s", HASPROCFS); switch (p.pfs_type) { case Proot: ty = "PDIR"; break; case Pcurproc: ep = endnm(&sz); (void) snpf(ep, sz, "/curproc"); ty = "PCUR"; break; case Pproc: ep = endnm(&sz); (void) snpf(ep, sz, "/%d", p.pfs_pid); ty = "PDIR"; break; case Pfile: ep = endnm(&sz); (void) snpf(ep, sz, "/%d/file", p.pfs_pid); ty = "PFIL"; break; case Pmem: ep = endnm(&sz); (void) snpf(ep, sz, "/%d/mem", p.pfs_pid); ty = "PMEM"; break; case Pregs: ep = endnm(&sz); (void) snpf(ep, sz, "/%d/regs", p.pfs_pid); ty = "PREG"; break; case Pfpregs: ep = endnm(&sz); (void) snpf(ep, sz, "/%d/fpregs", p.pfs_pid); ty = "PFPR"; break; case Pctl: ep = endnm(&sz); (void) snpf(ep, sz, "/%d/ctl", p.pfs_pid); ty = "PCTL"; break; case Pstatus: ep = endnm(&sz); (void) snpf(ep, sz, "/%d/status", p.pfs_pid); ty = "PSTA"; break; case Pnote: ep = endnm(&sz); (void) snpf(ep, sz, "/%d/note", p.pfs_pid); ty = "PNTF"; break; case Pnotepg: ep = endnm(&sz); (void) snpf(ep, sz, "/%d/notepg", p.pfs_pid); ty = "PGID"; break; # if defined(Pfd) case Pfd: ep = endnm(&sz); (void) snpf(ep, sz, "/%d/fd", p.pfs_pid); ty = "PFD"; break; # endif /* defined(Pfd) */ # if defined(Pmap) case Pmap: ep = endnm(&sz); (void) snpf(ep, sz, "/%d/map", p.pfs_pid); ty = "PMAP"; break; # endif /* defined(Pmap) */ # if defined(Pmaps) case Pmaps: ep = endnm(&sz); (void) snpf(ep, sz, "/%d/maps", p.pfs_pid); ty = "PMPS"; break; # endif /* defined(Pmaps) */ } if (ty) (void) snpf(Lf->type, sizeof(Lf->type), ty); } #endif /* defined(HASPROCFS) */ #if defined(HASPTYFS) else if (nty == PTYFSNODE) { (void) snpf(Namech, Namechl, "%s", Lf->fsdir); Lf->nlink = 1; Lf->nlink_def = 1; switch (pt.ptyfs_type) { case PTYFSpts: ep = endnm(&sz); (void) snpf(ep, sz, "/%lu", (unsigned long)pt.ptyfs_pty); break; case PTYFSptc: ep = endnm(&sz); (void) snpf(ep, sz, "/%lu (master)", (unsigned long)pt.ptyfs_pty); break; case PTYFSroot: Lf->sz = 512; Lf->sz_def = 1; break; } if (ty) (void) snpf(Lf->type, sizeof(Lf->type), ty); } #endif /* defined(HASPTYFS) */ #if defined(HASBLKDEV) /* * If this is a VBLK file and it's missing an inode number, try to * supply one. */ if ((Lf->inp_ty == 0) && (type == VBLK)) find_bl_ino(); #endif /* defined(HASBLKDEV) */ /* * If this is a VCHR file and it's missing an inode number, try to * supply one. */ if ((Lf->inp_ty == 0) && (type == VCHR)) find_ch_ino(); /* * Test for specified file. */ #if defined(HASPROCFS) if (Ntype == N_PROC) { if (Procsrch) { Procfind = 1; Lf->sf |= SELNM; } else if (nty == PFSNODE) { for (pfi = Procfsid; pfi; pfi = pfi->next) { if ((pfi->pid && pfi->pid == p.pfs_pid) # if defined(HASPINODEN) || ((Lf->inp_ty == 1) && (pfi->inode == Lf->inode)) # endif /* defined(HASPINODEN) */ ) { pfi->f = 1; if (Namech[0] && pfi->nm) (void) snpf(Namech, Namechl, "%s", pfi->nm); Lf->sf |= SELNM; break; } } } } else #endif /* defined(HASPROCFS) */ { if (Namech[0]) { enter_nm(Namech); ns = 1; } else ns = 0; if (Sfile && is_file_named((char *)NULL, ((type == VCHR) || (type == VBLK)) ? 1 : 0)) { Lf->sf |= SELNM; } if (ns) Namech[0] = '\0'; } /* * Enter name characters. */ if (Namech[0]) enter_nm(Namech); } #if defined(HAS_SYS_PIPEH) /* * process_pipe() - process a file structure whose type is DTYPE_PIPE */ void process_pipe(pa) KA_T pa; /* pipe structure kernel address */ { char *ep; struct pipe p; size_t sz; if (!pa || kread((KA_T)pa, (char *)&p, sizeof(p))) { (void) snpf(Namech, Namechl, "can't read DTYPE_PIPE pipe struct: %#s", print_kptr(pa, (char *)NULL, 0)); enter_nm(Namech); return; } (void) snpf(Lf->type, sizeof(Lf->type), "PIPE"); enter_dev_ch(print_kptr(pa, (char *)NULL, 0)); if (Foffset) Lf->off_def = 1; else { Lf->sz = (SZOFFTYPE)p.pipe_buffer.size; Lf->sz_def = 1; } if (p.pipe_peer) (void) snpf(Namech, Namechl, "->%s", print_kptr((KA_T)p.pipe_peer, (char *)NULL, 0)); else Namech[0] = '\0'; if (p.pipe_buffer.cnt) { ep = endnm(&sz); (void) snpf(ep, sz, ", cnt=%d", p.pipe_buffer.cnt); } if (p.pipe_buffer.in) { ep = endnm(&sz); (void) snpf(ep, sz, ", in=%d", p.pipe_buffer.in); } if (p.pipe_buffer.out) { ep = endnm(&sz); (void) snpf(ep, sz, ", out=%d", p.pipe_buffer.out); } /* * Enter name characters. */ if (Namech[0]) enter_nm(Namech); } #endif /* defined(HAS_SYS_PIPEH) */ lsof-4.86+dfsg.orig/dialects/n+obsd/dmnt.c0000444000175000017500000001414510275734073020547 0ustar nicholasnicholas/* * dmnt.c - NetBSD and OpenBSD mount support functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dmnt.c,v 1.12 2005/08/08 19:53:24 abe Exp $"; #endif #if defined(NETBSDV) && defined(HASSTATVFS) /* * NetBSD needs the statvfs structure to be defined without the * pre-definition of _KERNEL. */ #include #endif /* defined(NETBSDV) && defined(HASSTATVFS) */ #include "lsof.h" /* * Local static definitions */ static struct mounts *Lmi = (struct mounts *)NULL; /* local mount info */ static int Lmist = 0; /* Lmi status */ /* * readmnt() - read mount table */ struct mounts * readmnt() { char *dn = (char *)NULL; char *ln; struct mounts *mtp; int n; struct stat sb; #if defined(HASPROCFS) unsigned char procfs = 0; #endif /* defined(HASPROCFS) */ #if defined(HASSTATVFS) struct statvfs *mb = (struct statvfs *)NULL; #else /* !defined(HASSTATVFS) */ struct statfs *mb = (struct statfs *)NULL; #endif /* defined(HASSTATVFS) */ if (Lmi || Lmist) return(Lmi); /* * Access mount information. */ if ((n = getmntinfo(&mb, MNT_NOWAIT)) <= 0) { (void) fprintf(stderr, "%s: no mount information\n", Pn); return(0); } /* * Read mount information. */ for (; n; n--, mb++) { if (mb->f_fstypename[0] == '\0') continue; mb->f_fstypename[MFSNAMELEN - 1] = '\0'; /* * Interpolate a possible symbolic directory link. */ if (dn) (void) free((FREE_P *)dn); if (!(dn = mkstrcpy(mb->f_mntonname, (MALLOC_S *)NULL))) { no_space_for_mount: (void) fprintf(stderr, "%s: no space for mount at ", Pn); safestrprt(mb->f_mntonname, stderr, 0); (void) fprintf(stderr, " ("); safestrprt(mb->f_mntfromname, stderr, 0); (void) fprintf(stderr, ")\n"); Exit(1); } if ((ln = Readlink(dn)) == NULL) { if (!Fwarn) { (void) fprintf(stderr, " Output information may be incomplete.\n"); } continue; } if (ln != dn) { (void) free((FREE_P *)dn); dn = ln; } if (*dn != '/') continue; /* * Stat() the directory. */ if (statsafely(dn, &sb)) { if (!Fwarn) { (void) fprintf(stderr, "%s: WARNING: can't stat() ", Pn); safestrprt(mb->f_fstypename, stderr, 0); (void) fprintf(stderr, " file system "); safestrprt(mb->f_mntonname, stderr, 1); (void) fprintf(stderr, " Output information may be incomplete.\n"); } (void) bzero((char *)&sb, sizeof(sb)); #if defined(HASSTATVFS) sb.st_dev = (dev_t)mb->f_fsid; #else /* !defined(HASSTATVFS) */ sb.st_dev = (dev_t)mb->f_fsid.val[0]; #endif /* defined(HASSTATVFS) */ sb.st_mode = S_IFDIR | 0777; if (!Fwarn) { (void) fprintf(stderr, " assuming \"dev=%x\" from mount table\n", sb.st_dev); } } /* * Allocate and fill a local mount structure. */ if (!(mtp = (struct mounts *)malloc(sizeof(struct mounts)))) goto no_space_for_mount; mtp->dir = dn; dn = (char *)NULL; #if defined(HASPROCFS) if (strcmp(mb->f_fstypename, MOUNT_PROCFS) == 0) { /* * Save information on exactly one procfs file system. */ if (procfs) Mtprocfs = (struct mounts *)NULL; else { procfs = 1; Mtprocfs = mtp; } } #endif /* defined(HASPROCFS) */ mtp->next = Lmi; mtp->dev = sb.st_dev; mtp->rdev = sb.st_rdev; mtp->inode = (INODETYPE)sb.st_ino; mtp->mode = sb.st_mode; /* * Interpolate a possible file system (mounted-on) device name link. */ if (!(dn = mkstrcpy(mb->f_mntfromname, (MALLOC_S *)NULL))) goto no_space_for_mount; mtp->fsname = dn; ln = Readlink(dn); dn = (char *)NULL; /* * Stat() the file system (mounted-on) name and add file system * information to the local mount table entry. */ if (!ln || statsafely(ln, &sb)) sb.st_mode = 0; mtp->fsnmres = ln; mtp->fs_mode = sb.st_mode; Lmi = mtp; } /* * Clean up and return local mount info table address. */ if (dn) (void) free((FREE_P *)dn); Lmist = 1; return(Lmi); } /* * readvfs() - read vfs structure */ struct l_vfs * readvfs(vm) KA_T vm; /* kernel mount address from vnode */ { struct mount m; struct l_vfs *vp; /* * Search for match on existing entry. */ for (vp = Lvfs; vp; vp = vp->next) { if (vm == vp->addr) return(vp); } /* * Read the (new) mount structure, allocate a local entry, and fill it. */ if (kread(vm, (char *)&m, sizeof(m)) != 0) return((struct l_vfs *)NULL); if (!(vp = (struct l_vfs *)malloc(sizeof(struct l_vfs)))) { (void) fprintf(stderr, "%s: PID %d, no space for vfs\n", Pn, Lp->pid); Exit(1); } if (!(vp->dir = mkstrcpy(m.m_stat.f_mntonname, (MALLOC_S *)NULL)) || !(vp->fsname = mkstrcpy(m.m_stat.f_mntfromname, (MALLOC_S *)NULL))) { (void) fprintf(stderr, "%s: PID %d, no space for mount names\n", Pn, Lp->pid); Exit(1); } vp->addr = vm; #if defined(HASSTATVFS) vp->fsid = m.m_stat.f_fsidx; #else /* !defined(HASSTATVFS) */ vp->fsid = m.m_stat.f_fsid; #endif /* defined(HASSTATVFS) */ (void) snpf(vp->type, sizeof(vp->type), "%s", m.m_stat.f_fstypename); vp->next = Lvfs; Lvfs = vp; return(vp); } lsof-4.86+dfsg.orig/dialects/n+obsd/machine.h0000444000175000017500000004057111424323057021211 0ustar nicholasnicholas/* * machine.h - NetBSD and OpenBSD definitions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: machine.h,v 1.39 2010/07/29 16:02:52 abe Exp $ */ #if !defined(LSOF_MACHINE_H) #define LSOF_MACHINE_H 1 #include #include /* * 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 option. */ /* #define HASAOPT 1 */ /* * HASBLKDEV is defined for those dialects that want block device information * recorded in BDevtp[]. */ #define HASBLKDEV 1 /* * HASDCACHE is defined for those dialects that support a device cache * file. * * HASENVDC defined the name of an environment variable that contains the * device cache file path. The HASENVDC environment variable is ignored when * the lsof process is setuid(root) or its real UID is 0. * * HASPERSDC defines the format for the last component of a personal device * cache file path. The first will be the home directory of the real UID that * executes lsof. * * HASPERSDCPATH defines the environment variable whose value is the middle * component of the personal device cache file path. The middle component * follows the home directory and precedes the results of applying HASPERSDC. * The HASPERSDCPATH environment variable is ignored when the lsof process is * setuid(root) or its real UID is 0. * * HASSYSDC defines a public device cache file path. When it's defined, it's * used as the path from which to read the device cache. * * Consult the 00DCACHE and 00FAQ files of the lsof distribution for more * information on device cache file path construction. */ #define HASDCACHE 1 #define HASENVDC "LSOFDEVCACHE" #define HASPERSDC "%h/%p.lsof_%L" #define HASPERSDCPATH "LSOFPERSDCPATH" /* #define HASSYSDC "/your/choice/of/path" */ /* * HASCDRNODE is defined for those dialects that have CD-ROM nodes. */ /* #define HASCDRNODE 1 */ /* * HASFIFONODE is defined for those dialects that have FIFO nodes. */ /* #define HASFIFONODE 1 */ /* * HASFSINO is defined for those dialects that have the file system * inode element, fs_ino, in the lfile structure definition in lsof.h. */ /* #define HASFSINO 1 */ /* * HASFSTRUCT is defined if the dialect has a file structure. * * FSV_DEFAULT defines the default set of file structure values to list. * It defaults to zero (0), but may be made up of a combination of the * FSV_* symbols from lsof.h. * * HASNOFSADDR -- has no file structure address * HASNOFSFLAGS -- has no file structure flags * HASNOFSCOUNT -- has no file structure count * HASNOFSNADDR -- has no file structure node address */ #define HASFSTRUCT 1 /* #define FSV_DEFAULT FSV_? | FSV_? | FSV_? */ /* #define HASNOFSADDR 1 has no file structure address */ /* #define HASNOFSFLAGS 1 has no file structure flags */ /* #define HASNOFSCOUNT 1 has no file structure count */ /* #define HASNOFSNADDR 1 has no file structure node address */ /* * HASGNODE is defined for those dialects that have gnodes. */ /* #define HASGNODE 1 */ /* * HASHSNODE is defined for those dialects that have High Sierra nodes. */ /* #define HASHSNODE 1 */ /* * HASINODE is defined for those dialects that have inodes and wish to * use readinode() from node.c. */ #define HASINODE 1 /* * HASINTSIGNAL is defined for those dialects whose signal function returns * an int. */ /* #define HASINTSIGNAL 1 */ /* * HASKERNIDCK is defined for those dialects that support the comparison of * the build to running kernel identity. */ #define HASKERNIDCK 1 /* * HASKOPT is defined for those dialects that support the -k option of * reading the kernel's name list from an optional file. */ #define HASKOPT 1 /* * HASLFILEADD is defined for those dialects that need additional elements * in struct lfile. The HASLFILEADD definition is a macro that defines * them. If any of the additional elements need to be preset in the * alloc_lfile() function of proc.c, the SETLFILEADD macro may be defined * to do that. * * If any additional elements need to be cleared in alloc_lfile() or in the * free_proc() function of proc.c, the CLRLFILEADD macro may be defined to * do that. Note that CLRLFILEADD takes one argument, the pointer to the * lfile struct. The CLRLFILEADD macro is expected to expand to statements * that are complete -- i.e., have terminating semi-colons -- so the macro is * called without a terminating semicolon by proc.c. * * The HASXOPT definition may be used to select the conditions under which * private lfile elements are used. */ /* #define HASLFILEADD int ... */ /* #define CLRLFILEADD(lf) (lf)->... = (type)NULL; */ /* #define SETLFILEADD Lf->... */ /* * HASMNTSTAT indicates the dialect supports the mount stat(2) result option * in its l_vfs and mounts structures. */ /* #define HASMNTSTAT 1 */ /* * HASMNTSUP is defined for those dialects that support the mount supplement * option. */ /* #define HASMNTSUP 1 */ /* * HASMOPT is defined for those dialects that support the reading of * kernel memory from an alternate file. */ #define HASMOPT 1 /* * HASNCACHE is defined for those dialects that have a kernel name cache * that lsof can search. A value of 1 directs printname() to prefix the * cache value with the file system directory name; 2, avoid the prefix. * * NCACHELDPFX is a set of C commands to execute before calling ncache_load(). * * NCACHELDSFX is a set of C commands to execute after calling ncache_load(). */ #define HASNCACHE 1 /* #define NCACHELDPFX ??? */ /* #define NCACHELDSFX ??? */ /* * HASNLIST is defined for those dialects that use nlist() to acccess * kernel symbols. */ #define HASNLIST 1 /* * HASPIPEFN is defined for those dialects that have a special function to * process DTYPE_PIPE file structure entries. Its value is the name of the * function. * * NOTE: don't forget to define a prototype for this function in dproto.h. */ # if defined(HAS_SYS_PIPEH) #define HASPIPEFN process_pipe # endif /* defined(HAS_SYS_PIPEH) */ /* * HASPIPENODE is defined for those dialects that have pipe nodes. */ /* #define HASPIPENODE 1 */ /* * HASPMAPENABLED is defined when the reporting of portmapper registration * info is enabled by default. */ /* #define HASPMAPENABLED 1 */ /* * HASPPID is defined for those dialects that support identification of * the parent process IDentifier (PPID) of a process. */ #define HASPPID 1 /* * HASPRINTDEV, HASPRINTINO, HASPRINTNM, HASPRINTOFF, and HASPRINTSZ * define private dialect-specific functions for printing DEVice numbers, * INOde numbers, NaMes, file OFFsets, and file SiZes. The functions are * called from print_file(). */ /* #define HASPRINTDEV print_dev? */ /* #define HASPRINTINO print_ino? */ /* #define HASPRINTNM print_nm? */ /* #define HASPRINTOFF print_off? */ /* #define HASPRINTSZ print_sz? */ /* * HASPRIVFILETYPE and PRIVFILETYPE are defined for dialects that have a * file structure type that isn't defined by a DTYPE_* symbol. They are * used in lib/prfp.c to select the type's processing. * * PRIVFILETYPE is the definition of the f_type value in the file struct. * * HASPRIVFILETYPE is the name of the processing function. */ /* #define HASPRIVFILETYPE process_shmf? */ /* #define PRIVFILETYPE ?? */ /* * HASPRIVNMCACHE is defined for dialects that have a private method for * printing cached NAME column values for some files. HASPRIVNAMECACHE * is defined to be the name of the function. * * The function takes one argument, a struct lfile pointer to the file, and * returns non-zero if it prints a name to stdout. */ /* #define HASPRIVNMCACHE */ /* * 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 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 */ /* * 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_ is defined for dialects that use the * in the lsof library. * * Note: other definitions and operations may be required to condition the * library function source code. They may be found in the dialect dlsof.h * header files. */ /* #define USE_LIB_CKKV 1 ckkv.c */ /* #define USE_LIB_COMPLETEVFS 1 cvfs.c */ #define USE_LIB_FIND_CH_INO 1 /* fino.c */ #define USE_LIB_IS_FILE_NAMED 1 /* isfn.c */ #define USE_LIB_LKUPDEV 1 /* lkud.c */ #define USE_LIB_PRINTDEVNAME 1 /* pdvn.c */ #define USE_LIB_PROCESS_FILE 1 /* prfp.c */ #define USE_LIB_PRINT_TCPTPI 1 /* ptti.c */ #define USE_LIB_READDEV 1 /* rdev.c */ /* #define USE_LIB_READMNT 1 rmnt.c */ /* #define USE_LIB_REGEX 1 regex.c */ # if (defined(OPENBSDV) && OPENBSDV>=2010) || (defined(NETBSDV) && NETBSDV>=1002000) #define USE_LIB_RNMH 1 /* rnmh.c */ # else /* (defined(OPENBSDV) && OPENBSDV<2010) && (defined(NETBSDV) && NETBSDV<1002000) */ #define USE_LIB_RNAM 1 /* rnam.c */ # endif /* (defined(OPENBSDV) && OPENBSDV>=2010) || (defined(NETBSDV) && NETBSDV>=1002000) */ /* #define USE_LIB_RNCH 1 rnch.c */ /* #define USE_LIB_SNPF 1 snpf.c */ #define snpf snprintf /* use the system's snprintf() */ /* * WARNDEVACCESS is defined for those dialects that should issue a warning * when lsof can't access /dev (or /device) or one of its sub-directories. * The warning can be inhibited by the lsof caller with the -w option. */ /* #define WARNDEVACCESS 1 */ /* * WARNINGSTATE is defined for those dialects that want to suppress all lsof * warning messages. */ /* #define WARNINGSTATE 1 warnings are enabled by default */ /* * WILLDROPGID is defined for those dialects whose lsof executable runs * setgid(not_real_GID) and whose setgid power can be relinquished after * the dialect's initialize() function has been executed. */ #define WILLDROPGID 1 /* * zeromem is a macro that uses bzero or memset. */ #define zeromem(a, l) memset(a, 0, l) #endif /* !defined(LSOF_MACHINE_H) */ lsof-4.86+dfsg.orig/dialects/n+obsd/Makefile0000444000175000017500000000756311001126750021070 0ustar nicholasnicholas # N+OBSD Makefile # # $Id: Makefile,v 1.12 2008/04/15 13:30:14 abe Exp $ PROG= lsof BIN= ${DESTDIR} DOC= ${DESTDIR} I=/usr/include S=/usr/include/sys L=/usr/include/local P= CDEF= CDEFS= ${CDEF} ${CFGF} INCL= ${DINC} CFLAGS= ${CDEFS} ${INCL} ${DEBUG} GRP= HDR= lsof.h lsof_fields.h dlsof.h machine.h proto.h dproto.h SRC= dmnt.c dnode.c dnode1.c dproc.c dsock.c dstore.c \ arg.c main.c misc.c node.c print.c proc.c store.c usage.c \ util.c OBJ= dmnt.o dnode.o dnode1.o dproc.o dsock.o dstore.o \ arg.o main.o misc.o node.o print.o proc.o store.o usage.o \ util.o MAN= lsof.8 MANLCL= lsof.0 OTHER= SHELL= /bin/sh SOURCE= Makefile ${OTHER} ${MAN} ${HDR} ${SRC} all: ${PROG} ${MANLCL}: ${MAN} rm -f ${MANLCL} nroff -mandoc -Tlp ${MAN} > ${MANLCL} ${PROG}: ${LIB} ${P} ${OBJ} ${CC} -o $@ ${CFLAGS} ${OBJ} ${CFGL} clean: FRC rm -f Makefile.bak ${PROG} a.out core *.core errs lint.out tags *.o rm -f machine.h.old new_machine.h version.h (cd lib; ${MAKE} -f Makefile.skel clean) install: all ${MANLCL} FRC @echo '' @echo 'Please write your own install rule. Lsof should be installed' @echo 'setgid to the group that can can read /dev/kmem. Normally' @echo 'that is the kmem group. Your install rule actions might look' @echo 'something like this:' @echo '' @echo ' install -cs -m 2755 -g $${GRP} $${PROG} $${BIN}/$${PROG}' @echo ' install -c -m 444 $${MANLCL} $${DOC}/$${MANLCL}' @echo '' @echo 'You will have to complete the skeletons for the BIN, DOC, and' @echo 'GRP strings given at the beginning of this Makefile, e.g.,' @echo '' @echo ' BIN= $${DESTDIR}/usr/local/etc' @echo ' DOC= $${DESTDIR}/usr/local/man/man8' @echo ' GRP= kmem' @echo '' ${LIB}: FRC (cd lib; ${MAKE} DEBUG="${DEBUG}" CFGF="${CFGF}") version.h: FRC @echo Constructing version.h @rm -f version.h @echo '#define LSOF_BLDCMT "${LSOF_BLDCMT}"' > version.h; @echo '#define LSOF_CC "${CC}"' >> version.h @echo '#define LSOF_CCV "${CCV}"' >> version.h @echo '#define LSOF_CCDATE "'`date`'"' >> version.h @echo '#define LSOF_CCFLAGS "'`echo ${CFLAGS} | sed 's/\\\\(/\\(/g' | sed 's/\\\\)/\\)/g' | sed 's/"/\\\\"/g'`'"' >> version.h @if [ "X${LSOF_HOST}" = "X" ]; then \ echo '#define LSOF_HOST "'`uname -n`'"' >> version.h; \ else \ if [ "${LSOF_HOST}" = "none" ]; then \ echo '#define LSOF_HOST ""' >> version.h; \ else \ echo '#define LSOF_HOST "${LSOF_HOST}"' >> version.h; \ fi \ fi @echo '#define LSOF_LDFLAGS "${CFGL}"' >> version.h @if [ "X${LSOF_LOGNAME}" = "X" ]; then \ echo '#define LSOF_LOGNAME "${LOGNAME}"' >> version.h; \ else \ if [ "${LSOF_LOGNAME}" = "none" ]; then \ echo '#define LSOF_LOGNAME ""' >> version.h; \ else \ echo '#define LSOF_LOGNAME "${LSOF_LOGNAME}"' >> version.h; \ fi; \ fi @if [ "X${LSOF_SYSINFO}" = "X" ]; then \ echo '#define LSOF_SYSINFO "'`uname -a`'"' >> version.h; \ else \ if [ "${LSOF_SYSINFO}" = "none" ]; then \ echo '#define LSOF_SYSINFO ""' >> version.h; \ else \ echo '#define LSOF_SYSINFO "${LSOF_SYSINFO}"' >> version.h; \ fi \ fi @if [ "X${LSOF_USER}" = "X" ]; then \ echo '#define LSOF_USER "${USER}"' >> version.h; \ else \ if [ "${LSOF_USER}" = "none" ]; then \ echo '#define LSOF_USER ""' >> version.h; \ else \ echo '#define LSOF_USER "${LSOF_USER}"' >> version.h; \ fi \ fi @sed '/VN/s/.ds VN \(.*\)/#define LSOF_VERSION "\1"/' < version >> version.h FRC: # DO NOT DELETE THIS LINE - make depend DEPENDS ON IT dmnt.o: ${HDR} dmnt.c dnode.o: ${HDR} dnode.c dnode1.o: ${HDR} dnode1.c dproc.o: ${HDR} dproc.c dsock.o: ${HDR} dsock.c dstore.o: ${HDR} dstore.c arg.o: ${HDR} arg.c main.o: ${HDR} main.c misc.o: ${HDR} misc.c node.o: ${HDR} node.c print.o: ${HDR} print.c proc.o: ${HDR} proc.c store.o: ${HDR} store.c usage.o: ${HDR} version.h usage.c util.o: ${HDR} util.c # *** Do not add anything here - It will go away. *** lsof-4.86+dfsg.orig/dialects/sun/0000755000175000017500000000000011741064217017056 5ustar nicholasnicholaslsof-4.86+dfsg.orig/dialects/sun/dstore.c0000444000175000017500000001462011325130244020513 0ustar nicholasnicholas/* * dstore.c - Solaris global storage for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dstore.c,v 1.23 2010/01/18 19:03:54 abe Exp $"; #endif #include "lsof.h" /* * Global storage definitions */ #if defined(HAS_AFS) # if defined(HASAOPT) char *AFSApath = (char *)NULL; /* alternate AFS name list path * (from -a) */ # endif /* defined(HASAOPT) */ dev_t AFSdev; /* AFS file system device number */ int AFSdevStat = 0; /* AFSdev status: 0 = unknown; * 1 = known */ int AFSfstype = -1; /* AFS file system type index */ KA_T AFSVfsp = (KA_T)NULL; /* AFS vfs struct kernel address */ #endif /* defined(HAS_AFS) */ struct clone *Clone = NULL; /* clone list */ major_t CloneMaj; /* clone major device number */ /* * Drive_Nl -- table to drive the building of Nl[] via build_Nl() * (See lsof.h and misc.c.) */ struct drive_Nl Drive_Nl[] = { { "afsops", "afs_ops" }, { "arFid", "afs_rootFid" }, { "avops", "afs_vnodeops" }, { "Avops", "Afs_vnodeops" }, { "avol", "afs_volumes" }, { "auvops", "auto_vnodeops" }, { "ctfsadir", "ctfs_ops_adir" }, { "ctfsbund", "ctfs_ops_bundle" }, { "ctfscdir", "ctfs_ops_cdir" }, { "ctfsctl", "ctfs_ops_ctl", }, { "ctfsevt", "ctfs_ops_event", }, { "ctfslate", "ctfs_ops_latest", }, { "ctfsroot", "ctfs_ops_root", }, { "ctfsstat", "ctfs_ops_stat", }, { "ctfssym", "ctfs_ops_sym", }, { "ctfstdir", "ctfs_ops_tdir", }, { "ctfstmpl", "ctfs_ops_tmpl", }, { "cvops", "cachefs_vnodeops" }, { "clmaj", "clonemaj" }, { "clmaj_alt", "clone_major" }, { "fdops", "fdvnodeops" }, { "fd_ops", "fd_vnodeops" }, { "fvops", "fifo_vnodeops" }, { "hvops", "hsfs_vnodeops" }, { "lvops", "lo_vnodeops" }, { "mntops", "mntvnodeops" }, { "mvops", "mvfs_vnodeops" }, #if solaris<90000 { X_NCACHE, "ncache" }, { X_NCSIZE, "ncsize" }, #else /* solaris>=90000 */ { X_NCACHE, "nc_hash" }, { X_NCSIZE, "nc_hashsz" }, { "hshav", "nc_hashavelen" }, #endif /* solaris<90000 */ #if defined(NCACHE_NEGVN) { NCACHE_NEGVN, NCACHE_NEGVN }, #endif /* defined(NCACHE_NEGVN) */ { "nvops", "nfs_vnodeops" }, { "n3vops", "nfs3_vnodeops" }, { "n4vops", "nfs4_vnodeops" }, { "nmvops", "nm_vnodeops" }, { "nproc", "nproc" }, { "pdvops", "pcfs_dvnodeops" }, { "pfvops", "pcfs_fvnodeops" }, { "portvops", "port_vnodeops" }, { "pract", "practive" }, { "prvops", "prvnodeops" }, { "sam1vops", "samfs_vnodeops" }, { "sam2vops", "samfs_client_vnodeops" }, { "sam3vops", "samfs_vnodeopsp" }, { "sam4vops", "samfs_client_vnodeopsp" }, { "sdevops", "sdev_vnodeops" }, { "sgvops", "segvn_ops" }, { "shvops", "sharefs_ops_data" }, { "sckvops", "sock_vnodeops" }, { "socketvops", "socket_vnodeops" }, { "spvops", "spec_vnodeops" }, { "sncavops", "socknca_vnodeops" }, { "stpivops", "socktpi_vnodeops" }, { "tvops", "tmp_vnodeops" }, { "uvops", "ufs_vnodeops" }, { "vvfops", "fdd_vnops" }, { "vvfcops", "fdd_chain_vnops" }, { "vvfclops", "vx_fcl_vnodeops_p" }, { "vvops", "vx_vnodeops" }, { "vvops_p", "vx_vnodeops_p" }, #if solaris>=20500 { "devops", "dv_vnodeops" }, { "doorops", "door_vnodeops" }, { "kbase", "_kernelbase" }, #endif /* solaris>=20500 */ #if solaris>=20501 { "kasp", "kas" }, #endif /* solaris>=20501 */ #if solaris>=110000 { "devipnetops","devipnet_vnodeops" }, { "devnetops", "devnet_vnodeops" }, { "devptsops", "devpts_vnodeops" }, { "devvtops", "devvt_vnodeops" }, #endif /* solaris>=110000 */ { "zfsdops", "zfs_dvnodeops" }, { "zfseops", "zfs_evnodeops" }, { "zfsfops", "zfs_fvnodeops" }, { "zfsshops", "zfs_sharevnodeops" }, { "zfssymops", "zfs_symvnodeops" }, { "zfsxdops", "zfs_xdvnodeops" }, { "", "" }, { NULL, NULL } }; char **Fsinfo = NULL; /* file system information */ int Fsinfomax = 0; /* maximum file system type */ int HasALLKMEM = 0; /* has ALLKMEM device */ int HaveCloneMaj = 0; /* clone major device number has * been identified and is in * CloneMaj */ kvm_t *Kd = NULL; /* kvm descriptor */ struct l_vfs *Lvfs = NULL; /* local vfs structure table */ struct netclone *Netclone = NULL; /* net clone devices from * /devices/pseudo */ #if defined(HASFSTRUCT) /* * Pff_tab[] - table for printing file flags */ struct pff_tab Pff_tab[] = { { (long)FREAD, FF_READ }, { (long)FWRITE, FF_WRITE }, { (long)FNDELAY, FF_NDELAY }, { (long)FAPPEND, FF_APPEND }, { (long)FSYNC, FF_SYNC }, # if defined(FREVOKED) { (long)FREVOKED, FF_REVOKED }, # endif /* defined(FREVOKED) */ { (long)FDSYNC, FF_DSYNC }, { (long)FRSYNC, FF_RSYNC }, # if defined(FOFFMAX) { (long)FOFFMAX, FF_LARGEFILE }, # endif /* defined(FFOFFMAX) */ { (long)FNONBLOCK, FF_NBLOCK }, { (long)FNOCTTY, FF_NOCTTY }, { (long)FASYNC, FF_ASYNC }, { (long)FNODSYNC, FF_NODSYNC }, { (long)0, NULL } }; /* * Pof_tab[] - table for print process open file flags */ struct pff_tab Pof_tab[] = { # if defined(UF_EXCLOSE) { (long)UF_EXCLOSE, POF_CLOEXEC }, # endif /* defined(UF_EXCLOSE) */ # if defined(FD_CLOEXEC) { (long)FD_CLOEXEC, POF_CLOEXEC }, # endif /* defined(FD_CLOEXEC) */ # if defined(UF_FDLOCK) { (long)UF_FDLOCK, POF_FDLOCK }, # endif /* defined(UF_FDLOCK) */ { (long)0, NULL } }; #endif /* defined(HASFSTRUCT) */ struct pseudo *Pseudo = NULL; /* non-clone devices from * /devices/pseudo */ int Unof; /* u_nofiles value */ lsof-4.86+dfsg.orig/dialects/sun/ddev.c0000444000175000017500000006247510275734306020164 0ustar nicholasnicholas/* * ddev.c - Solaris device support functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: ddev.c,v 1.20 2005/08/08 19:55:41 abe Exp $"; #endif #include "lsof.h" /* * Local definitions */ #define LIKE_BLK_SPEC "like block special" #define LIKE_CHR_SPEC "like character special" /* * Local static values */ static int Devx = 0; /* current Devtp[] index */ /* * Local function prototypes */ _PROTOTYPE(static void make_devtp,(struct stat *s, char *p)); _PROTOTYPE(static int rmdupdev,(struct l_dev ***dp, int n, int ty)); /* * make_devtp() - make Devtp[] entry */ static void make_devtp(s, p) struct stat *s; /* device lstat() buffer */ char *p; /* device path name */ { /* * Make room for another Devtp[] entry. */ if (Devx >= Ndev) { Ndev += DEVINCR; if (!Devtp) Devtp = (struct l_dev *)malloc( (MALLOC_S)(sizeof(struct l_dev) * Ndev)); else Devtp = (struct l_dev *)realloc((MALLOC_P *)Devtp, (MALLOC_S)(sizeof(struct l_dev) * Ndev)); if (!Devtp) { (void) fprintf(stderr, "%s: no space for character device\n", Pn); Exit(1); } } /* * Store the device number, inode number, and name in the Devtp[] entry. */ Devtp[Devx].inode = (INODETYPE)s->st_ino; if (!(Devtp[Devx].name = mkstrcpy(p, (MALLOC_S *)NULL))) { (void) fprintf(stderr, "%s: no space for /dev/", Pn); safestrprt(p, stderr, 1); Exit(1); } Devtp[Devx].rdev = s->st_rdev; Devtp[Devx].v = 0; Devx++; } /* * printdevname() - print block or character device name */ int printdevname(dev, rdev, f, nty) dev_t *dev; /* device */ dev_t *rdev; /* raw device */ int f; /* 1 = print trailing '\n' */ int nty; /* node type: N_BLK or N_CHR */ { struct clone *c; struct l_dev *dp; struct pseudo *p; readdev(0); /* * Search device table for a full match. */ #if defined(HASDCACHE) printchdevname_again: #endif /* defined(HASDCACHE) */ #if defined(HASBLKDEV) if (nty == N_BLK) dp = lkupbdev(dev, rdev, 1, 0); else #endif /* defined(HASBLKDEV) */ dp = lkupdev(dev, rdev, 1, 0); if (dp) { safestrprt(dp->name, stdout, f); return(1); } /* * Search device table for a match without inode number and dev. */ #if defined(HASBLKDEV) if (nty == N_BLK) dp = lkupbdev(&DevDev, rdev, 0, 0); else #endif /* defined(HASBLKDEV) */ dp = lkupdev(&DevDev, rdev, 0, 0); if (dp) { /* * A match was found. Record it as a name column addition. */ char *cp, *ttl; int len; ttl = (nty == N_BLK) ? LIKE_BLK_SPEC : LIKE_CHR_SPEC; len = (int)(1 + strlen(ttl) + 1 + strlen(dp->name) + 1); if (!(cp = (char *)malloc((MALLOC_S)(len + 1)))) { (void) fprintf(stderr, "%s: no nma space for: (%s %s)\n", Pn, ttl, dp->name); Exit(1); } (void) snpf(cp, len + 1, "(%s %s)", ttl, dp->name); (void) add_nma(cp, len); (void) free((MALLOC_P *)cp); return(0); } /* * Search for clone parent. */ if ((nty == N_CHR) && Lf->is_stream && Clone && (*dev == DevDev)) { for (c = Clone; c; c = c->next) { if (GET_MAJ_DEV(*rdev) == GET_MIN_DEV(c->cd.rdev)) { #if defined(HASDCACHE) if (DCunsafe && !c->cd.v && !vfy_dev(&c->cd)) goto printchdevname_again; #endif /* defined(HASDCACHE) */ safestrprt(c->cd.name, stdout, f); return(1); } } } /* * Search for pseudo device match on major device only. */ if ((nty == N_CHR) && *dev == DevDev) { for (p = Pseudo; p; p = p->next) { if (GET_MAJ_DEV(*rdev) == GET_MAJ_DEV(p->pd.rdev)) { # if defined(HASDCACHE) if (DCunsafe && !p->pd.v && vfy_dev(&p->pd)) goto printchdevname_again; # endif /* defined(HASDCACHE) */ safestrprt(p->pd.name, stdout, f); return(1); } } } #if defined(HASDCACHE) /* * If the device cache is "unsafe" and we haven't found any match, reload * the device cache. */ if (DCunsafe) { (void) rereaddev(); goto printchdevname_again; } #endif /* defined(HASDCACHE) */ return(0); } /* * read_clone() - read Solaris clone device information */ void read_clone() { struct clone *c; char *cn; DIR *dfp; struct DIRTYPE *dp; char *fp = (char *)NULL; MALLOC_S fpl; char *path; MALLOC_S pl; struct pseudo *p; struct stat sb; if (Clone || Pseudo) return; /* * Open the /DVCH_DEVPATH/pseudo directory. */ if (!(path = mkstrcat(DVCH_DEVPATH, -1, "/", 1, "pseudo ", -1, &pl))) { (void) fprintf(stderr, "%s: no space for %s/pseudo\n", DVCH_DEVPATH, Pn); Exit(1); } path[pl - 1] = '\0'; if (!(dfp = OpenDir(path))) { #if defined(WARNDEVACCESS) if (!Fwarn) { (void) fprintf(stderr, "%s: WARNING: can't open: ", Pn); safestrprt(path, stderr, 1); } #endif /* defined(WARNDEVACCESS) */ (void) free((FREE_P *)path); return; } path[pl - 1] = '/'; /* * Scan the directory. */ for (dp = ReadDir(dfp); dp; dp = ReadDir(dfp)) { if (dp->d_ino == 0 || dp->d_name[0] == '.') continue; /* * Form the full path name and stat() it. */ if (fp) { (void) free((FREE_P *)fp); fp = (char *)NULL; } if (!(fp = mkstrcat(path, pl, dp->d_name, -1, (char *)NULL, -1, &fpl))) { (void) fprintf(stderr, "%s: no space for: ", Pn); safestrprt(path, stderr, 0); safestrprt(dp->d_name, stderr, 1); Exit(1); } #if defined(USE_STAT) if (stat(fp, &sb) != 0) #else /* !defined(USE_STAT) */ if (lstat(fp, &sb) != 0) #endif /* defined(USE_STAT) */ { if (!Fwarn) { int errno_save = errno; (void) fprintf(stderr, "%s: can't stat: ", Pn); safestrprt(fp, stderr, 0); (void) fprintf(stderr, ": %s\n", strerror(errno_save)); } continue; } /* * Skip subdirectories and all but character devices. */ if ((sb.st_mode & S_IFMT) == S_IFDIR || (sb.st_mode & S_IFMT) != S_IFCHR) continue; /* * Make Devtp[] entry. */ make_devtp(&sb, fp); /* * Create a clone structure entry for "clone*:" devices. * * Make special note of network clones -- tcp, and udp. */ if (strncmp(&fp[pl], "clone", 5) == 0) { if (!(cn = strrchr(&fp[pl], ':'))) continue; /* * Allocate a clone structure. */ if (!(c = (struct clone *)malloc(sizeof(struct clone)))) { (void) fprintf(stderr, "%s: no space for network clone device: ", Pn); safestrprt(fp, stderr, 1); Exit(1); } /* * Allocate space for the path name. */ if (!(c->cd.name = mkstrcpy(fp, (MALLOC_S *)NULL))) { (void) fprintf(stderr, "%s: no space for clone name: ", Pn); safestrprt(fp, stderr, 1); Exit(1); } /* * Save the inode and device numbers. Clear the verify flag. */ c->cd.inode = (INODETYPE)sb.st_ino; c->cd.rdev = sb.st_rdev; c->cd.v = 0; /* * Make special note of a network clone device. */ if (!strcmp(++cn, "tcp") || !strcmp(cn, "udp")) c->n = cn - fp; else c->n = 0; /* * Link the new clone entry to the rest. */ c->next = Clone; Clone = c; continue; } /* * Save pseudo device information. */ if (GET_MIN_DEV(sb.st_rdev) == 0) { /* * Allocate space for the pseduo device entry. */ if (!(p = (struct pseudo *) malloc(sizeof(struct pseudo)))) { (void) fprintf(stderr, "%s: no space for pseudo device: ", Pn); safestrprt(fp, stderr, 1); Exit(1); } /* * Save the path name, and inode and device numbers. Clear the * verify flag. Link the entry to the pseudo chain. */ p->pd.inode = (INODETYPE)sb.st_ino; p->pd.name = fp; fp = (char *)NULL; p->pd.rdev = sb.st_rdev; p->pd.v = 0; p->next = Pseudo; Pseudo = p; } } (void) CloseDir(dfp); if (fp) (void) free((FREE_P *)fp); if (path) (void) free((FREE_P *)path); } /* * readdev() - read names, modes and device types of everything in /dev * or /device (Solaris) */ void readdev(skip) int skip; /* skip device cache read if 1 */ { #if defined(HASDCACHE) int dcrd = 0; #endif /* defined(HASDCACHE) */ DIR *dfp; struct DIRTYPE *dp; char *fp = (char *)NULL; MALLOC_S fpl; int i; #if defined(HASBLKDEV) int j = 0; #endif /* defined(HASBLKDEV) */ char *path = (char *)NULL; char *ppath = (char *)NULL; MALLOC_S pl; struct stat sb; if (Sdev) return; #if defined(HASDCACHE) /* * Read device cache, as directed. */ if (!skip) { if (DCstate == 2 || DCstate == 3) { if ((dcrd = read_dcache()) == 0) return; } } else dcrd = 1; #endif /* defined(HASDCACHE) */ if (!(ppath = mkstrcat(DVCH_DEVPATH, -1, "/", 1, "pseudo", -1, (MALLOC_S *)NULL))) { (void) fprintf(stderr, "%s: no space for: %s/pseudo\n", Pn, DVCH_DEVPATH); Exit(1); } read_clone(); Dstk = (char **)NULL; Dstkn = Dstkx = 0; (void) stkdir(DVCH_DEVPATH); /* * Unstack the next directory. */ while (--Dstkx >= 0) { if (!(dfp = OpenDir(Dstk[Dstkx]))) { #if defined(WARNDEVACCESS) if (!Fwarn) { (void) fprintf(stderr, "%s: WARNING: can't open: ", Pn); safestrprt(Dstk[Dstkx], stderr, 1); } #endif /* defined(WARNDEVACCESS) */ (void) free((FREE_P *)Dstk[Dstkx]); Dstk[Dstkx] = (char *)NULL; continue; } /* * Create a directory name buffer with a trailing slash. */ if (path) { (void) free((FREE_P *)path); path = (char *)NULL; } if (!(path = mkstrcat(Dstk[Dstkx], -1, "/", 1, (char *)NULL, -1, &pl))) { (void) fprintf(stderr, "%s: no space for: ", Pn); safestrprt(Dstk[Dstkx], stderr, 1); Exit(1); } (void) free((FREE_P *)Dstk[Dstkx]); Dstk[Dstkx] = (char *)NULL; /* * Scan the directory. */ for (dp = ReadDir(dfp); dp; dp = ReadDir(dfp)) { if (dp->d_ino == 0 || dp->d_name[0] == '.') continue; /* * Form the full path name and get its status. */ if (fp) { (void) free((FREE_P *)fp); fp = (char *)NULL; } if (!(fp = mkstrcat(path, pl, dp->d_name, -1, (char *)NULL, -1, &fpl))) { (void) fprintf(stderr, "%s: no space for: ", Pn); safestrprt(path, stderr, 0); safestrprt(dp->d_name, stderr, 1); Exit(1); } #if defined(USE_STAT) if (stat(fp, &sb) != 0) #else /* !defined(USE_STAT) */ if (lstat(fp, &sb) != 0) #endif /* defined(USE_STAT) */ { if (errno == ENOENT) /* symbolic link to nowhere? */ continue; #if defined(WARNDEVACCESS) if (!Fwarn) { int errno_save = errno; (void) fprintf(stderr, "%s: can't stat ", Pn); safestrprt(fp, stderr, 0); (void) fprintf(stderr, ": %s\n", strerror(errno_save)); } #endif /* defined(WARNDEVACCESS) */ continue; } /* * If it's a subdirectory, stack its name for later processing. */ if ((sb.st_mode & S_IFMT) == S_IFDIR) { /* * Skip Solaris /DVCH_DEV_PATH/pseudo sub-directory; * it has been examined in read_clone(). */ if (strcmp(fp, ppath) == 0) continue; (void) stkdir(fp); continue; } if ((sb.st_mode & S_IFMT) == S_IFCHR) { /* * Make Devtp[] entry. */ make_devtp(&sb, fp); } #if defined(HASBLKDEV) if ((sb.st_mode & S_IFMT) == S_IFBLK) { /* * Save block device information in BDevtp[]. */ if (j >= BNdev) { BNdev += DEVINCR; if (!BDevtp) BDevtp = (struct l_dev *)malloc( (MALLOC_S)(sizeof(struct l_dev)*BNdev)); else BDevtp = (struct l_dev *)realloc((MALLOC_P *)BDevtp, (MALLOC_S)(sizeof(struct l_dev)*BNdev)); if (!BDevtp) { (void) fprintf(stderr, "%s: no space for block device\n", Pn); Exit(1); } } BDevtp[j].rdev = sb.st_rdev; BDevtp[j].inode = (INODETYPE)sb.st_ino; BDevtp[j].name = fp; fp = (char *)NULL; BDevtp[j].v = 0; j++; } #endif /* defined(HASBLKDEV) */ } (void) CloseDir(dfp); } /* * Free any allocated space. */ if (Dstk) { (void) free((FREE_P *)Dstk); Dstk = (char **)NULL; Dstkn = Dstkx = 0; } if (fp) (void) free((FREE_P *)fp); if (path) (void) free((FREE_P *)path); if (ppath) (void) free((FREE_P *)ppath); /* * Reduce the BDevtp[] (optional) and Devtp[] tables to their minimum * sizes; allocate and build sort pointer lists; and sort the tables by * device number. */ #if defined(HASBLKDEV) if (BNdev) { if (BNdev > j) { BNdev = j; BDevtp = (struct l_dev *)realloc((MALLOC_P *)BDevtp, (MALLOC_S)(sizeof(struct l_dev) * BNdev)); } if (!(BSdev = (struct l_dev **)malloc( (MALLOC_S)(sizeof(struct l_dev *) * BNdev)))) { (void) fprintf(stderr, "%s: no space for block device sort pointers\n", Pn); Exit(1); } for (j = 0; j < BNdev; j++) { BSdev[j] = &BDevtp[j]; } (void) qsort((QSORT_P *)BSdev, (size_t)BNdev, (size_t)sizeof(struct l_dev *), compdev); BNdev = rmdupdev(&BSdev, BNdev, 0); } else { if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: no block devices found\n", Pn); } #endif /* defined(HASBLKDEV) */ if (Ndev) { if (Ndev > Devx) { Ndev = Devx; Devtp = (struct l_dev *)realloc((MALLOC_P *)Devtp, (MALLOC_S)(sizeof(struct l_dev) * Ndev)); } if (!(Sdev = (struct l_dev **)malloc( (MALLOC_S)(sizeof(struct l_dev *) * Ndev)))) { (void) fprintf(stderr, "%s: no space for character device sort pointers\n", Pn); Exit(1); } for (i = 0; i < Ndev; i++) { Sdev[i] = &Devtp[i]; } (void) qsort((QSORT_P *)Sdev, (size_t)Ndev, (size_t)sizeof(struct l_dev *), compdev); Ndev = rmdupdev(&Sdev, Ndev, 1); } else { (void) fprintf(stderr, "%s: no character devices found\n", Pn); Exit(1); } #if defined(HASDCACHE) /* * Write device cache file, as required. */ if (DCstate == 1 || (DCstate == 3 && dcrd)) write_dcache(); #endif /* defined(HASDCACHE) */ } /* * clr_sect() - clear cached clone and pseudo sections */ void clr_sect() { if (Clone) { struct clone *c, *c1; for (c = Clone; c; c = c1) { c1 = c->next; if (c->cd.name) (void) free((FREE_P *)c->cd.name); (void) free((FREE_P *)c); } Clone = (struct clone *)NULL; } if (Pseudo) { struct pseudo *p, *p1; for (p = Pseudo; p; p = p1) { p1 = p->next; if (p->pd.name) (void) free((FREE_P *)p->pd.name); (void) free((FREE_P *)p); } Pseudo = (struct pseudo *)NULL; } } #if defined(HASDCACHE) /* * rw_clone_sect() - read/write the device cache file clone section */ int rw_clone_sect(m) int m; /* mode: 1 = read; 2 = write */ { char buf[MAXPATHLEN*2], *cp; struct clone *c; int i, len, n; if (m == 1) { /* * Read the clone section header and validate it. */ if (!fgets(buf, sizeof(buf), DCfs)) { bad_clone_sect: if (!Fwarn) { (void) fprintf(stderr, "%s: bad clone section header in %s: ", Pn, DCpath[DCpathX]); safestrprt(buf, stderr, 1); } return(1); } (void) crc(buf, strlen(buf), &DCcksum); len = strlen("clone section: "); if (strncmp(buf, "clone section: ", len) != 0) goto bad_clone_sect; if ((n = atoi(&buf[len])) < 0) goto bad_clone_sect; /* * Read the clone section lines and create the Clone list. */ for (i = 0; i < n; i++) { if (!fgets(buf, sizeof(buf), DCfs)) { if (!Fwarn) { (void) fprintf(stderr, "%s: bad clone line in %s: ", Pn, DCpath[DCpathX]); safestrprt(buf, stderr, 1); } return(1); } (void) crc(buf, strlen(buf), &DCcksum); /* * Allocate a clone structure. */ if (!(c = (struct clone *)calloc(1, sizeof(struct clone)))) { (void) fprintf(stderr, "%s: no space for cached clone: ", Pn); safestrprt(buf, stderr, 1); Exit(1); } /* * Enter the clone device number. * * New format clone lines (with an inode number) have a leading * space, so that older lsof versions, not expecting them, will * not use the new format lines. */ if (buf[0] != ' ' || !(cp = x2dev(&buf[1], &c->cd.rdev)) || *cp++ != ' ') { if (!Fwarn) { (void) fprintf(stderr, "%s: bad cached clone device: ", Pn); safestrprt(buf, stderr, 1); } return(1); } /* * Enter the clone network value. */ for (c->n = 0; *cp != ' '; cp++) { if (*cp < '0' || *cp > '9') { if (!Fwarn) { (void) fprintf(stderr, "%s: bad cached clone network flag: ", Pn); safestrprt(buf, stderr, 1); } return(1); } c->n = (c->n * 10) + (int)(*cp - '0'); } /* * Enter the clone device inode number. */ for (c->cd.inode = (INODETYPE)0, ++cp; *cp != ' '; cp++) { if (*cp < '0' || *cp > '9') { if (!Fwarn) { (void) fprintf(stderr, "%s: bad cached clone inode number: ", Pn); safestrprt(buf, stderr, 1); } return(1); } c->cd.inode = (INODETYPE)((c->cd.inode * 10) + (int)(*cp - '0')); } /* * Enter the clone path name. */ if ((len = strlen(++cp)) < 2 || *(cp + len - 1) != '\n') { if (!Fwarn) { (void) fprintf(stderr, "%s: bad cached clone path: ", Pn); safestrprt(buf, stderr, 1); } return(1); } *(cp + len - 1) = '\0'; if (!(c->cd.name = mkstrcpy(cp, (MALLOC_S *)NULL))) { (void) fprintf(stderr, "%s: no space for cached clone path: ", Pn); safestrprt(buf, stderr, 1); Exit(1); } c->cd.v = 0; c->next = Clone; Clone = c; } return(0); } else if (m == 2) { /* * Write the clone section header. */ for (c = Clone, n = 0; c; c = c->next, n++) ; (void) snpf(buf, sizeof(buf), "clone section: %d\n", n); if (wr2DCfd(buf, &DCcksum)) return(1); /* * Write the clone section lines. * * * New format clone lines (with an inode number) have a leading * space, so that older lsof versions, not expecting them, will * not use the new format lines. */ for (c = Clone; c; c = c->next) { (void) snpf(buf, sizeof(buf), " %lx %d %ld %s\n", (long)c->cd.rdev, c->n, (long)c->cd.inode, c->cd.name); if (wr2DCfd(buf, &DCcksum)) return(1); } return(0); } /* * A shouldn't-happen case: mode neither 1 nor 2. */ (void) fprintf(stderr, "%s: internal rw_clone_sect error: %d\n", Pn, m); Exit(1); return(1); /* to make code analyzers happy */ } /* * rereaddev() - reread device names, modes and types */ void rereaddev() { (void) clr_devtab(); (void) clr_sect(); Devx = 0; # if defined(DCACHE_CLR) (void) DCACHE_CLR(); # endif /* defined(DCACHE_CLR) */ readdev(1); DCunsafe = 0; } /* * rw_pseudo_sect() - read/write the device cache pseudo section */ int rw_pseudo_sect(m) int m; /* mode: 1 = read; 2 = write */ { char buf[MAXPATHLEN*2], *cp; struct pseudo *p; int i, len, n; if (m == 1) { /* * Read the pseudo section header and validate it. */ if (!fgets(buf, sizeof(buf), DCfs)) { bad_pseudo_sect: if (!Fwarn) { (void) fprintf(stderr, "%s: bad pseudo section header in %s: ", Pn, DCpath[DCpathX]); safestrprt(buf, stderr, 1); } return(1); } (void) crc(buf, strlen(buf), &DCcksum); len = strlen("pseudo section: "); if (strncmp(buf, "pseudo section: ", len) != 0) goto bad_pseudo_sect; if ((n = atoi(&buf[len])) < 0) goto bad_pseudo_sect; /* * Read the pseudo section lines and create the Pseudo list. */ for (i = 0; i < n; i++) { if (!fgets(buf, sizeof(buf), DCfs)) { if (!Fwarn) { (void) fprintf(stderr, "%s: bad pseudo line in %s: ", Pn, DCpath[DCpathX]); safestrprt(buf, stderr, 1); } return(1); } (void) crc(buf, strlen(buf), &DCcksum); /* * Allocate a pseudo structure. */ if (!(p = (struct pseudo *)calloc(1, sizeof(struct pseudo)))) { (void) fprintf(stderr, "%s: no space for cached pseudo: ", Pn); safestrprt(buf, stderr, 1); Exit(1); } /* * Enter the pseudo device number. * * New format pseudo lines (with an inode number) have a leading * space, so that older lsof versions, not expecting them, will * not use the new format lines. */ if (buf[0] != ' ' || !(cp = x2dev(&buf[1], &p->pd.rdev)) || *cp++ != ' ') { if (!Fwarn) { (void) fprintf(stderr, "%s: bad cached pseudo device: ", Pn); safestrprt(buf, stderr, 1); } return(1); } /* * Enter the pseudo inode number. */ for (p->pd.inode = (INODETYPE)0; *cp != ' '; cp++) { if (*cp < '0' || *cp > '9') { if (!Fwarn) { (void) fprintf(stderr, "%s: bad cached pseudo inode number: ", Pn); safestrprt(buf, stderr, 1); } return(1); } p->pd.inode = (INODETYPE)((p->pd.inode * 10) + (int)(*cp - '0')); } /* * Enter the pseudo path name. * * * New format clone lines (with an inode number) have a leading * space, so that older lsof versions, not expecting them, will * not use the new format lines. */ if ((len = strlen(++cp)) < 2 || *(cp + len - 1) != '\n') { if (!Fwarn) { (void) fprintf(stderr, "%s: bad cached pseudo path: ", Pn); safestrprt(buf, stderr, 1); } return(1); } if (!(p->pd.name = (char *)malloc(len))) { (void) fprintf(stderr, "%s: no space for cached pseudo path: ", Pn); safestrprt(buf, stderr, 1); Exit(1); } *(cp + len - 1) = '\0'; (void) snpf(p->pd.name, len, "%s", cp); p->pd.v = 0; p->next = Pseudo; Pseudo = p; } return(0); } else if (m == 2) { /* * Write the pseudo section header. */ for (p = Pseudo, n = 0; p; p = p->next, n++) ; (void) snpf(buf, sizeof(buf), "pseudo section: %d\n", n); if (wr2DCfd(buf, &DCcksum)) return(1); /* * Write the pseudo section lines. * * * New format pseudo lines (with an inode number) have a leading * space, so that older lsof versions, not expecting them, will * not use the new format lines. */ for (p = Pseudo; p; p = p->next) { (void) snpf(buf, sizeof(buf), " %lx %ld %s\n", (long)p->pd.rdev, (long)p->pd.inode, p->pd.name); if (wr2DCfd(buf, &DCcksum)) return(1); } return(0); } /* * A shouldn't-happen case: mode neither 1 nor 2. */ (void) fprintf(stderr, "%s: internal rw_pseudo_sect error: %d\n", Pn, m); return(1); } /* * vfy_dev() - verify a device table entry (usually when DCunsafe == 1) * * Note: rereads entire device table when an entry can't be verified. */ int vfy_dev(dp) struct l_dev *dp; /* device table pointer */ { struct stat sb; if (!DCunsafe || dp->v) return(1); #if defined(USE_STAT) if (stat(dp->name, &sb) != 0 #else /* !defined(USE_STAT) */ if (lstat(dp->name, &sb) != 0 #endif /* defined(USE_STAT) */ || dp->rdev != sb.st_rdev || dp->inode != (INODETYPE)sb.st_ino) { (void) rereaddev(); return(0); } dp->v = 1; return(1); } #endif /* defined(HASDCACHE) */ /* * rmdupdev() - remove duplicate (major/minor/inode) devices */ static int rmdupdev(dp, n, ty) struct l_dev ***dp; /* device table pointers address */ int n; /* number of pointers */ int ty; /* type: 0 = block, 1 = char */ { struct clone *c, *cp; struct l_dev **d; int i, j, k; struct pseudo *p, *pp; for (i = j = 0, d = *dp; i < n ;) { for (k = i + 1; k < n; k++) { if (d[i]->rdev != d[k]->rdev || d[i]->inode != d[k]->inode) break; if (ty == 0) continue; /* * See if we're deleting a duplicate clone device. If so, * delete its clone table entry. */ for (c = Clone, cp = (struct clone *)NULL; c; cp = c, c = c->next) { if (c->cd.rdev != d[k]->rdev || c->cd.inode != d[k]->inode || strcmp(c->cd.name, d[k]->name)) continue; if (!cp) Clone = c->next; else cp->next = c->next; if (c->cd.name) (void) free((FREE_P *)c->cd.name); (void) free((FREE_P *)c); break; } /* * See if we're deleting a duplicate pseudo device. If so, * delete its pseudo table entry. */ for (p = Pseudo, pp = (struct pseudo *)NULL; p; pp = p, p = p->next) { if (p->pd.rdev != d[k]->rdev || p->pd.inode != d[k]->inode || strcmp(p->pd.name, d[k]->name)) continue; if (!pp) Pseudo = p->next; else pp->next = p->next; if (p->pd.name) (void) free((FREE_P *)p->pd.name); (void) free((FREE_P *)p); break; } } if (i != j) d[j] = d[i]; j++; i = k; } if (n == j) return(n); if (!(*dp = (struct l_dev **)realloc((MALLOC_P *)*dp, (MALLOC_S)(j * sizeof(struct l_dev *))))) { (void) fprintf(stderr, "%s: can't realloc %s device pointers\n", Pn, ty ? "char" : "block"); Exit(1); } return(j); } lsof-4.86+dfsg.orig/dialects/sun/dsock.c0000444000175000017500000014770311617613574020347 0ustar nicholasnicholas/* * dsock.c - Solaris socket processing functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dsock.c,v 1.31 2011/08/07 22:53:42 abe Exp $"; #endif #include "lsof.h" #if solaris>=110000 #include #endif /* solaris>=110000 */ #if defined(HAS_LIBCTF) && solaris>=110000 /* * Icmp_t, rts_t and udp_t structure support for Solaris >=11 via libctf * * These structure definitions may look like kernel structures, but they * are not. They have been defined to have member names that duplicate * those used by the kernel that are of interest to lsof. Member valuess * are obtained via the CTF library, libctf. * * Robert Byrnes developed the CTF library access code and contributed it * to lsof. */ /* * Icmp_t internal structure definition */ typedef struct icmp_s { uint_t icmp_state; /* TPI state */ KA_T *icmp_connp; /* connection structure pointer */ in6_addr_t icmp_bound_v6src; /* Explicitely bound to address */ in6_addr_t icmp_v6src; /* Source address of this stream */ union { uint_t icmp_dummy; uint_t icmp_Debug : 1, /* SO_DEBUG option */ icmp_dontroute : 1, /* SO_DONTROUTE option */ icmp_broadcast : 1, /* SO_BROADCAST option */ icmp_reuseaddr : 1, /* SO_REUSEADDR option */ icmp_useloopback : 1, /* SO_USELOOPBACK option */ icmp_hdrincl : 1, /* IP_HDRINCL option, etc. */ icmp_dgram_errind : 1, /* SO_DGRAM_ERRIND option */ icmp_pad : 25; /* pad to bit 31 */ } icmp_debug; /* This name identifies a single bit * variable of the kernel's union, but * CTF won't read individual bit * variables, so for CTF's purposes * it is declared as a uint_t union, * named by the first bit variable of * the kernel union, whose address CTF * groks. */ } icmp_t; /* * Rts_t internal structure definition */ typedef struct rts_s { uint_t rts_state; /* Provider interface state */ # if defined(HAS_CONN_NEW) KA_T *rts_connp; /* connection structure pointer */ # endif /* defined(HAS_CONN_NEW) */ union { uint_t rts_dummy; uint_t rts_Debug : 1, /* SO_DEBUG option */ rts_dontroute : 1, /* SO_DONTROUTE option */ rts_broadcast : 1, /* SO_BROADCAST option */ rts_reuseaddr : 1, /* SO_REUSEADDR option */ rts_useloopback : 1, /* SO_USELOOPBACK option */ icmp_pad : 27; /* padding to bit 31 */ } rts_debug; /* This name identifies a single bit * variable, but CTF won't read * individual bit variables, so for * CTF's purposes it is declared as a * uint_t union, named by its first * bit variable, whose address CTF * groks. */ } rts_t; /* * Udp_t internal structure definition */ typedef struct udp { uint_t udp_state; /* TPI state */ in_port_t udp_port; /* port bound to this stream */ in_port_t udp_dstport; /* connected port */ in6_addr_t udp_v6src; /* source address of this stream */ in6_addr_t udp_v6dst; /* connected destination */ ushort_t udp_ipversion; /* version -- IPV[46]_VERSION */ KA_T *udp_connp; /* connection structure pointer */ uint_t udp_bits; /* socket option bits */ } udp_t; /* * CTF definitions for icmp_t, rts_t and udp_t */ static int IRU_ctfs = 0; /* CTF initialization status for * icmp_t, rts_t and udp_t */ # if defined(_LP64) #define IRU_MOD_FORMAT "/kernel/%s/genunix" #else /* !defined(_LP64) */ #define IRU_MOD_FORMAT "/kernel/genunix" #endif /* defined(_LP64) */ /* genunix pathname template to which * the kernel's instruction type set * is added for CTF access to icmp_t, * rts_t and udp_t */ /* * Icmp_t, rts_t and udp_t access definitions and structures */ #define ICMP_T_TYPE_NAME "icmp_t" static CTF_member_t icmp_t_members[] = { CTF_MEMBER(icmp_state), #define MX_icmp_state 0 # if defined(HAS_CONN_NEW) CTF_MEMBER(icmp_connp), #define MX_icmp_connp 1 # else /* !defined(HAS_CONN_NEW) */ CTF_MEMBER(icmp_bound_v6src), #define MX_icmp_bound_v6src 1 CTF_MEMBER(icmp_v6src), #define MX_icmp_v6src 2 CTF_MEMBER(icmp_debug), #define MX_icmp_debug 3 # endif /* defined(HAS_CONN_NEW) */ { NULL, 0 } }; #define RTS_T_TYPE_NAME "rts_t" static CTF_member_t rts_t_members[] = { CTF_MEMBER(rts_state), #define MX_rts_state 0 # if defined(HAS_CONN_NEW) CTF_MEMBER(rts_connp), #define MX_rts_connp 1 # else /* !defined(HAS_CONN_NEW) */ CTF_MEMBER(rts_debug), #define MX_rts_debug 1 # endif /* defined(HAS_CONN_NEW) */ { NULL, 0 } }; #define UDP_T_TYPE_NAME "udp_t" static CTF_member_t udp_t_members[] = { CTF_MEMBER(udp_state), #define MX_udp_state 0 CTF_MEMBER(udp_connp), #define MX_udp_connp 1 # if !defined(HAS_CONN_NEW) CTF_MEMBER(udp_port), #define MX_udp_port 2 CTF_MEMBER(udp_dstport), #define MX_udp_dstport 3 CTF_MEMBER(udp_v6src), #define MX_udp_v6src 4 CTF_MEMBER(udp_v6dst), #define MX_udp_v6dst 5 CTF_MEMBER(udp_ipversion), #define MX_udp_ipversion 6 CTF_MEMBER(udp_bits), #define MX_udp_bits 7 # endif /* !defined(HAS_CONN_NEW) */ { NULL, 0 } }; /* * CTF icmp_t, rts_t and udp_t request table */ static CTF_request_t IRU_requests[] = { { ICMP_T_TYPE_NAME, icmp_t_members }, { RTS_T_TYPE_NAME, rts_t_members }, { UDP_T_TYPE_NAME, udp_t_members }, { NULL, NULL } }; /* * Icmp_t, rts_t and udp_t function prototypes */ _PROTOTYPE(static int read_icmp_t,(KA_T va, KA_T ph, KA_T ia, icmp_t *ic)); _PROTOTYPE(static int read_rts_t,(KA_T va, KA_T ph, KA_T ra, rts_t *rt)); _PROTOTYPE(static int read_udp_t,(KA_T ua, udp_t *uc)); #endif /* defined(HAS_LIBCTF) && solaris>=110000 */ #if solaris<80000 || defined(HAS_IPCLASSIFIER_H) /* * Make sure the tcpb structure is always defined. */ typedef struct tcpb { int dummy; } tcpb_t; #endif /* solaris<80000 || defined(HAS_IPCLASSIFIER_H) */ #if defined(HASIPv6) /* * IPv6_2_IPv4() -- macro to define the address of an IPv4 address contained * in an IPv6 address */ #define IPv6_2_IPv4(v6) (((uint8_t *)((struct in6_addr *)v6)->s6_addr)+12) /* * IPv_ADDR_UNSPEC() -- macro to test an IP[46] address for an unspecified * address value */ #define IPv_ADDR_UNSPEC(af, p) \ (((af) == AF_INET6) ? (IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)p)) \ : (((struct in_addr *)(p))->s_addr == INADDR_ANY)) #else /* !defined(HASIPv6) */ /* * IPv_ADDR_UNSPEC() -- IPv4-only form of macro to test for an unspecified * address value */ #define IPv_ADDR_UNSPEC(af, p) (((struct in_addr *)(p))->s_addr == INADDR_ANY) #endif /* !defined(HASIPv6) */ #if defined(HASTCPOPT) # if solaris==20600 #include # endif /* solaris==20600 */ #include #include # if defined(TH_TIMER_NEEDED) #define ACK_TIMER TH_TIMER_NEEDED # else # if defined(TH_ACK_TIMER_NEEDED) #define ACK_TIMER TH_ACK_TIMER_NEEDED # endif /* defined(TH_ACK_TIMER_NEEDED) */ # endif /* defined(TH_TIMER_NEEDED */ #endif /* defined(HASTCPOPT) */ #if defined(HASSOOPT) # if solaris<100000 #define KEEPALIVE_INTERVAL tcp_keepalive_intrvl # else /* solaris>=100000 */ #define KEEPALIVE_INTERVAL tcp_ka_last_intrvl # endif /* solaris<100000 */ #endif /* defined(HASSOOPT) */ /* * Local function prototypes */ _PROTOTYPE(static void save_TCP_size,(tcp_t *tc)); _PROTOTYPE(static void save_TCP_states,(tcp_t *tc, caddr_t *fa, tcpb_t *tb, caddr_t *xp)); /* * build_IPstates() -- build the TCP and UDP state tables */ void build_IPstates() { if (!TcpSt) { (void) enter_IPstate("TCP", "CLOSED", TCPS_CLOSED); (void) enter_IPstate("TCP", "IDLE", TCPS_IDLE); (void) enter_IPstate("TCP", "BOUND", TCPS_BOUND); (void) enter_IPstate("TCP", "LISTEN", TCPS_LISTEN); (void) enter_IPstate("TCP", "SYN_SENT", TCPS_SYN_SENT); (void) enter_IPstate("TCP", "SYN_RCVD", TCPS_SYN_RCVD); (void) enter_IPstate("TCP", "ESTABLISHED", TCPS_ESTABLISHED); (void) enter_IPstate("TCP", "CLOSE_WAIT", TCPS_CLOSE_WAIT); (void) enter_IPstate("TCP", "FIN_WAIT_1", TCPS_FIN_WAIT_1); (void) enter_IPstate("TCP", "CLOSING", TCPS_CLOSING); (void) enter_IPstate("TCP", "LAST_ACK", TCPS_LAST_ACK); (void) enter_IPstate("TCP", "FIN_WAIT_2", TCPS_FIN_WAIT_2); (void) enter_IPstate("TCP", "TIME_WAIT", TCPS_TIME_WAIT); (void) enter_IPstate("TCP", (char *)NULL, 0); } if (!UdpSt) { (void) enter_IPstate("UDP", "Unbound", TS_UNBND); (void) enter_IPstate("UDP", "Wait_BIND_REQ_Ack", TS_WACK_BREQ); (void) enter_IPstate("UDP", "Wait_UNBIND_REQ_Ack", TS_WACK_UREQ); (void) enter_IPstate("UDP", "Idle", TS_IDLE); (void) enter_IPstate("UDP", "Wait_OPT_REQ_Ack", TS_WACK_OPTREQ); (void) enter_IPstate("UDP", "Wait_CONN_REQ_Ack", TS_WACK_CREQ); (void) enter_IPstate("UDP", "Wait_CONN_REQ_Confirm", TS_WCON_CREQ); (void) enter_IPstate("UDP", "Wait_CONN_IND_Response", TS_WRES_CIND); (void) enter_IPstate("UDP", "Wait_CONN_RES_Ack", TS_WACK_CRES); (void) enter_IPstate("UDP", "Wait_Data_Xfr", TS_DATA_XFER); (void) enter_IPstate("UDP", "Wait_Read_Release", TS_WIND_ORDREL); (void) enter_IPstate("UDP", "Wait_Write_Release", TS_WREQ_ORDREL); (void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack", TS_WACK_DREQ6); (void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack", TS_WACK_DREQ7); (void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack", TS_WACK_DREQ9); (void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack", TS_WACK_DREQ10); (void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack", TS_WACK_DREQ11); (void) enter_IPstate("UDP", (char *)NULL, 0); } } /* * print_tcptpi() - print TCP/TPI info */ void print_tcptpi(nl) int nl; /* 1 == '\n' required */ { char *cp = (char *)NULL; char sbuf[128]; int i; int ps = 0; unsigned int u; if (Ftcptpi & TCPTPI_STATE) { switch (Lf->lts.type) { case 0: /* TCP */ if (!TcpSt) (void) build_IPstates(); if ((i = Lf->lts.state.i + TcpStOff) < 0 || i >= TcpNstates) { (void) snpf(sbuf, sizeof(sbuf), "UNKNOWN_TCP_STATE_%d", Lf->lts.state.i); cp = sbuf; } else cp = TcpSt[i]; break; case 1: /* TPI */ if (!UdpSt) (void) build_IPstates(); if ((u = Lf->lts.state.ui + UdpStOff) < 0 || u >= UdpNstates) { (void) snpf(sbuf, sizeof(sbuf), "UNKNOWN_UDP_STATE_%u", Lf->lts.state.ui); cp = sbuf; } else cp = UdpSt[u]; } if (cp) { if (Ffield) (void) printf("%cST=%s%c", LSOF_FID_TCPTPI, cp, Terminator); else { putchar('('); (void) fputs(cp, stdout); } ps++; } } #if defined(HASTCPTPIQ) if (Ftcptpi & TCPTPI_QUEUES) { if (Lf->lts.rqs) { if (Ffield) putchar(LSOF_FID_TCPTPI); else { if (ps) putchar(' '); else putchar('('); } (void) printf("QR=%lu", Lf->lts.rq); if (Ffield) putchar(Terminator); ps++; } if (Lf->lts.sqs) { if (Ffield) putchar(LSOF_FID_TCPTPI); else { if (ps) putchar(' '); else putchar('('); } (void) printf("QS=%lu", Lf->lts.sq); if (Ffield) putchar(Terminator); ps++; } } #endif /* defined(HASTCPTPIQ) */ #if defined(HASSOOPT) if (Ftcptpi & TCPTPI_FLAGS) { int opt; if ((opt = Lf->lts.opt) || Lf->lts.pqlens || Lf->lts.qlens || Lf->lts.qlims || Lf->lts.rbszs || Lf->lts.sbsz ) { char sep = ' '; if (Ffield) sep = LSOF_FID_TCPTPI; else if (!ps) sep = '('; (void) printf("%cSO", sep); ps++; sep = '='; # if defined(SO_BROADCAST) if (opt & SO_BROADCAST) { (void) printf("%cBROADCAST", sep); opt &= ~SO_BROADCAST; sep = ','; } # endif /* defined(SO_BROADCAST) */ # if defined(SO_DEBUG) if (opt & SO_DEBUG) { (void) printf("%cDEBUG", sep); opt &= ~ SO_DEBUG; sep = ','; } # endif /* defined(SO_DEBUG) */ # if defined(SO_DGRAM_ERRIND) if (opt & SO_DGRAM_ERRIND) { (void) printf("%cDGRAM_ERRIND", sep); opt &= ~SO_DGRAM_ERRIND; sep = ','; } # endif /* defined(SO_DGRAM_ERRIND) */ # if defined(SO_DONTROUTE) if (opt & SO_DONTROUTE) { (void) printf("%cDONTROUTE", sep); opt &= ~SO_DONTROUTE; sep = ','; } # endif /* defined(SO_DONTROUTE) */ # if defined(SO_KEEPALIVE) if (opt & SO_KEEPALIVE) { (void) printf("%cKEEPALIVE", sep); if (Lf->lts.kai) (void) printf("=%d", Lf->lts.kai); opt &= ~SO_KEEPALIVE; sep = ','; } # endif /* defined(SO_KEEPALIVE) */ # if defined(SO_LINGER) if (opt & SO_LINGER) { (void) printf("%cLINGER", sep); if (Lf->lts.ltm) (void) printf("=%d", Lf->lts.ltm); opt &= ~SO_LINGER; sep = ','; } # endif /* defined(SO_LINGER) */ # if defined(SO_OOBINLINE) if (opt & SO_OOBINLINE) { (void) printf("%cOOBINLINE", sep); opt &= ~SO_OOBINLINE; sep = ','; } # endif /* defined(SO_OOBINLINE) */ if (Lf->lts.pqlens) { (void) printf("%cPQLEN=%u", sep, Lf->lts.pqlen); sep = ','; } if (Lf->lts.qlens) { (void) printf("%cQLEN=%u", sep, Lf->lts.qlen); sep = ','; } if (Lf->lts.qlims) { (void) printf("%cQLIM=%u", sep, Lf->lts.qlim); sep = ','; } if (Lf->lts.rbszs) { (void) printf("%cRCVBUF=%lu", sep, Lf->lts.rbsz); sep = ','; } # if defined(SO_REUSEADDR) if (opt & SO_REUSEADDR) { (void) printf("%cREUSEADDR", sep); opt &= ~SO_REUSEADDR; sep = ','; } # endif /* defined(SO_REUSEADDR) */ if (Lf->lts.sbszs) { (void) printf("%cSNDBUF=%lu", sep, Lf->lts.sbsz); sep = ','; } # if defined(SO_TIMESTAMP) if (opt & SO_TIMESTAMP) { (void) printf("%cTIMESTAMP", sep); opt &= ~SO_TIMESTAMP; sep = ','; } # endif /* defined(SO_TIMESTAMP) */ # if defined(SO_USELOOPBACK) if (opt & SO_USELOOPBACK) { (void) printf("%cUSELOOPBACK", sep); opt &= ~SO_USELOOPBACK; sep = ','; } # endif /* defined(SO_USELOOPBACK) */ if (opt) (void) printf("%cUNKNOWN=%#x", sep, opt); if (Ffield) putchar(Terminator); } } #endif /* defined(HASSOOPT) */ #if defined(HASTCPOPT) if (Ftcptpi & TCPTPI_FLAGS) { int topt; if ((topt = Lf->lts.topt) || Lf->lts.msss) { char sep = ' '; if (Ffield) sep = LSOF_FID_TCPTPI; else if (!ps) sep = '('; (void) printf("%cTF", sep); ps++; sep = '='; # if defined(TF_ACKNOW) if (topt & TF_ACKNOW) { (void) printf("%cACKNOW", sep); topt &= ~TF_ACKNOW; sep = ','; } # endif /* defined(TF_ACKNOW) */ # if defined(TF_DELACK) if (topt & TF_DELACK) { (void) printf("%cDELACK", sep); topt &= ~TF_DELACK; sep = ','; } # endif /* defined(TF_DELACK) */ if (Lf->lts.msss) { (void) printf("%cMSS=%lu", sep, Lf->lts.mss); sep = ','; } # if defined(TF_NODELAY) if (topt & TF_NODELAY) { (void) printf("%cNODELAY", sep); topt &= ~TF_NODELAY; sep = ','; } # endif /* defined(TF_NODELAY) */ # if defined(TF_NOOPT) if (topt & TF_NOOPT) { (void) printf("%cNOOPT", sep); topt &= ~TF_NOOPT; sep = ','; } # endif /* defined(TF_NOOPT) */ # if defined(TF_SENTFIN) if (topt & TF_SENTFIN) { (void) printf("%cSENTFIN", sep); topt &= ~TF_SENTFIN; sep = ','; } # endif /* defined(TF_SENTFIN) */ if (topt) (void) printf("%cUNKNOWN=%#x", sep, topt); if (Ffield) putchar(Terminator); } } #endif /* defined(HASTCPOPT) */ #if defined(HASTCPTPIW) if (Ftcptpi & TCPTPI_WINDOWS) { if (Lf->lts.rws) { if (Ffield) putchar(LSOF_FID_TCPTPI); else { if (ps) putchar(' '); else putchar('('); } (void) printf("WR=%lu", Lf->lts.rw); if (Ffield) putchar(Terminator); ps++; } if (Lf->lts.wws) { if (Ffield) putchar(LSOF_FID_TCPTPI); else { if (ps) putchar(' '); else putchar('('); } (void) printf("WW=%lu", Lf->lts.ww); if (Ffield) putchar(Terminator); ps++; } } #endif /* defined(HASTCPTPIW) */ if (Ftcptpi && !Ffield && ps) putchar(')'); if (nl) putchar('\n'); } #if solaris>=110000 /* * procss_VSOCK() -- process a VSOCK socket */ # if defined(HAS_CONN_NEW) /* * Adjust for changes in the conn_s structure, introduced at OpenSolaris * level b134. */ #define conn_ulp conn_proto #define conn_rem V4_PART_OF_V6(connua_v6addr.connua_faddr) #define conn_src V4_PART_OF_V6(connua_v6addr.connua_laddr) # endif /* defined(HAS_CONN_NEW) */ int process_VSOCK(va, v, so) KA_T va; /* containing vnode address */ struct vnode *v; /* pointer to containing vnode */ struct sonode *so; /* pointer to socket's sonode */ { int af; /* address family */ struct conn_s cs; /* connection info */ unsigned char *fa = (unsigned char *)NULL; /* foreign address */ u_short fp = (u_short)0; /* foreign port */ u_short lp; /* local port */ icmp_t ic; /* ICMP control structure */ KA_T ka; /* temporary kernel address */ unsigned char *la = (unsigned char *)NULL; /* local address */ KA_T pha; /* protocol handle address */ rts_t rt; /* AF_ROUTE control structure */ int s; /* state */ unsigned char *ta = (unsigned char *)NULL; /* temporary address */ char tbuf[32], tbuf1[32]; /* temporary buffers */ tcp_t tc; /* TCP control structure */ tcph_t th; /* TCP header structure */ # if defined(HAS_CONN_NEW) struct ip_xmit_attr_s xa; caddr_t *xp = (caddr_t *)NULL; # else /* !defined(HAS_CONN_NEW) */ tcph_t *tha = (tcph_t *)NULL; /* TCP header structure address */ # endif /* defined(HAS_CONN_NEW) */ char *ty; /* TCP type */ udp_t uc; /* local UDP control structure */ /* * Read VSOCK's connection information. Enter its address as the protocol * control block device address. */ if (!(pha = (KA_T)so->so_proto_handle)) return(0); if (kread(pha, (char *)&cs, sizeof(cs))) { (void) snpf(Namech, Namechl, "vnode at %s; snode at %s; can't read proto handle at: %s", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)v->v_data, tbuf1, sizeof(tbuf1)), print_kptr(pha, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } enter_dev_ch(print_kptr(pha, (char *)NULL, 0)); /* * Process connection info by protocol. */ switch ((af = so->so_family)) { case AF_INET: case AF_INET6: /* * Set INET type -- IPv4 or IPv6. */ if (af == AF_INET) ty = "IPv4"; else ty = "IPv6"; (void) snpf(Lf->type, sizeof(Lf->type), ty); switch (cs.conn_ulp) { case IPPROTO_TCP: /* * Process TCP socket; read its control structure. */ if (!(ka = (KA_T)cs.conn_proto_priv.cp_tcp) || kread(ka, (char *)&tc, sizeof(tc)) ) { (void) snpf(Namech, Namechl - 1, "can't read TCP socket's control structure: %s", print_kptr((KA_T)ka, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } /* * Set TCP protcol name in Lf->iproto[]. */ (void) snpf(Lf->iproto, IPROTOL - 1, "%s", "TCP"); Lf->iproto[IPROTOL - 1] = '\0'; Lf->inp_ty = 2; /* * Check for TCP state inclusion or exclusion. */ if (TcpNstates) { if ((s = (int)tc.tcp_state + TcpStOff) < TcpNstates) { if (TcpStXn) { if (TcpStX[s]) { Lf->sf |= SELEXCLF; return(1); } } if (TcpStIn) { if (TcpStI[s]) { TcpStI[s] = 2; Lf->sf |= SELNET; } else { Lf->sf |= SELEXCLF; return(1); } } } } /* * Set network file selection status. */ if (Fnet) { if (!FnetTy || ((FnetTy == 4) && (af == AF_INET)) || ((FnetTy == 6) && (af == AF_INET6)) ) { Lf->sf |= SELNET; } } /* * Save local and remote (foreign) TCP address. */ if (af == AF_INET6) { ta = (unsigned char *)&cs.connua_v6addr.connua_faddr; la = (unsigned char *)&cs.connua_v6addr.connua_laddr; } else { ta = (unsigned char *)&cs.conn_rem; la = (unsigned char *)&cs.conn_src; } if (!IPv_ADDR_UNSPEC(af, ta) || (u_short)cs.conn_fport) { fa = ta; fp = (u_short)cs.conn_fport; } if ((af == AF_INET6) && ((la && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)la)) || ((fa && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)fa)))) ) { /* * Convert IPv4 addresses in IPv6 structures to IPv4 addresses * in IPv4 structures. Change the address family to AF_INET. */ if (la) la = (unsigned char *)IPv6_2_IPv4(la); if (fa) fa = (unsigned char *)IPv6_2_IPv4(fa); af = AF_INET; } lp = (u_short)cs.conn_lport; (void) ent_inaddr(la, (int)ntohs(lp), fa, (int)ntohs(fp), af); /* * Save TCP state information. */ # if defined(HAS_CONN_NEW) if ((ka = (KA_T)cs.conn_ixa) && !kread(ka, (char *)&xa, sizeof(xa)) ) { xp = (caddr_t *)&xa; } (void) save_TCP_states(&tc, (caddr_t *)&cs, (tcpb_t *)NULL, xp); # else /* !defined(HAS_CONN_NEW) */ if (tc.tcp_tcp_hdr_len && (ka = (KA_T)tc.tcp_tcph) && !kread(ka, (char *)&th, sizeof(th)) ) { tha = &th; } (void) save_TCP_states(&tc, (caddr_t *)tha, (tcpb_t *)NULL, (caddr_t *)NULL); # endif /* defined(HAS_CONN_NEW) */ Lf->lts.type = 0; Lf->lts.state.i = (int)tc.tcp_state; /* * Save TCP size information. */ (void) save_TCP_size(&tc); break; case IPPROTO_UDP: /* * Process UDP socket; read its control structure. */ if (!(ka = (KA_T)cs.conn_proto_priv.cp_udp) || kread(ka, (char *)&uc, sizeof(uc)) ) { (void) snpf(Namech, Namechl - 1, "can't read UDP socket's control structure: %s", print_kptr((KA_T)ka, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } /* * Set UDP protcol name in Lf->iproto[]. */ (void) snpf(Lf->iproto, IPROTOL - 1, "%s", "UDP"); Lf->iproto[IPROTOL - 1] = '\0'; Lf->inp_ty = 2; /* * Check for UDP state inclusion or exclusion. */ if (UdpNstates) { if ((s = (int)uc.udp_state + TcpStOff) < UdpNstates) { if (UdpStXn) { if (UdpStX[s]) { Lf->sf |= SELEXCLF; return(1); } } if (UdpStIn) { if (UdpStI[s]) { UdpStI[s] = 2; Lf->sf |= SELNET; } else { Lf->sf |= SELEXCLF; return(1); } } } } /* * Set network file selection status. */ if (Fnet) { if (!FnetTy || ((FnetTy == 4) && (af == AF_INET)) || ((FnetTy == 6) && (af == AF_INET6)) ) { Lf->sf |= SELNET; } } /* * Save local and remote (foreign) UDP address. */ if (af == AF_INET6) { ta = (unsigned char *)&cs.connua_v6addr.connua_faddr; la = (unsigned char *)&cs.connua_v6addr.connua_laddr; } else { ta = (unsigned char *)&cs.conn_rem; la = (unsigned char *)&cs.conn_src; } if (!IPv_ADDR_UNSPEC(af, ta) || (u_short)cs.conn_fport) { fa = ta; fp = (u_short)cs.conn_fport; } lp = (u_short)cs.conn_lport; (void) ent_inaddr(la, (int)ntohs(lp), fa, (int)ntohs(fp), af); /* * Save UDP state and size information. */ if (!Fsize) Lf->off_def = 1; Lf->lts.type = 1; Lf->lts.state.ui = (unsigned int)uc.udp_state; # if defined(HASSOOPT) /* * Save UDP flags. */ if (Ftcptpi & TCPTPI_FLAGS) { union { uint_t flags; uint_t udpb_debug : 1, /* SO_DEBUG option */ udpb_dontroute : 1, /* SO_DONTROUTE option */ udpb_broadcast : 1, /* SO_BROADCAST option */ udpb_reuseaddr : 1, /* SO_REUSEADDR option */ udpb_useloopback : 1, /* SO_USELOOPBACK option */ udpb_dgram_errind : 1, /* SO_DGRAM_ERRIND option */ udpb_pad : 26; /* pad to bit 31 */ } ucf; ucf.flags = uc.udp_bits; if (ucf.udpb_debug) Lf->lts.opt |= SO_DEBUG; if (ucf.udpb_dontroute) Lf->lts.opt |= SO_DONTROUTE; if (ucf.udpb_broadcast) Lf->lts.opt |= SO_BROADCAST; if (ucf.udpb_reuseaddr) Lf->lts.opt |= SO_REUSEADDR; if (ucf.udpb_useloopback) Lf->lts.opt |= SO_USELOOPBACK; if (ucf.udpb_dgram_errind) Lf->lts.opt |= SO_DGRAM_ERRIND; } # endif /* defined(HASSOOPT) */ break; case IPPROTO_ICMP: case IPPROTO_ICMPV6: /* * Process ICMP or ICMP6 socket. * * Set protocol name. */ if (cs.conn_ulp == IPPROTO_ICMP) ty = "ICMP"; else ty = "ICMP6"; (void) snpf(Lf->iproto, IPROTOL - 1, "%s", ty); Lf->iproto[IPROTOL - 1] = '\0'; Lf->inp_ty = 2; /* * Read the ICMP control structure. */ if (read_icmp_t(va, pha, (KA_T)cs.conn_proto_priv.cp_icmp, &ic)) return(1); /* * Save ICMP size and state information. */ if (!Fsize) Lf->off_def = 1; Lf->lts.type = 1; Lf->lts.state.ui = (unsigned int)ic.icmp_state; /* * Set network file selection status. */ if (Fnet) { if (!FnetTy || ((FnetTy == 4) && (af == AF_INET)) || ((FnetTy == 6) && (af == AF_INET6)) ) { Lf->sf |= SELNET; } } /* * Save addresses. */ ta = (af == AF_INET6) ? (unsigned char *)&ic.icmp_bound_v6src : (unsigned char *)&V4_PART_OF_V6(ic.icmp_bound_v6src); if (!IPv_ADDR_UNSPEC(af, ta)) la = ta; ta = (af == AF_INET6) ? (unsigned char *)&ic.icmp_v6src : (unsigned char *)&V4_PART_OF_V6(ic.icmp_v6src); if (!IPv_ADDR_UNSPEC(af, ta)) fa = ta; if (la || fa) (void)ent_inaddr(la, 0, fa, 0, af); # if defined(HASSOOPT) /* * Save ICMP flags. */ if (Ftcptpi & TCPTPI_FLAGS) { if (ic.icmp_debug.icmp_Debug) Lf->lts.opt |= SO_DEBUG; if (ic.icmp_debug.icmp_dontroute) Lf->lts.opt |= SO_DONTROUTE; if (ic.icmp_debug.icmp_broadcast) Lf->lts.opt |= SO_BROADCAST; if (ic.icmp_debug.icmp_reuseaddr) Lf->lts.opt |= SO_REUSEADDR; if (ic.icmp_debug.icmp_useloopback) Lf->lts.opt |= SO_USELOOPBACK; if (ic.icmp_debug.icmp_dgram_errind) Lf->lts.opt |= SO_DGRAM_ERRIND; } # endif /* defined(HASSOOPT) */ break; default: (void) snpf(Namech, Namechl - 1, "unsupported conn_s AF_INET%s protocol: %u", (af == AF_INET6) ? "6" : "", (unsigned int)cs.conn_ulp); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } break; case AF_ROUTE: /* * Set INET type -- IPv4 or IPv6. */ if (af == AF_INET) ty = "IPv4"; else ty = "IPv6"; (void) snpf(Lf->type, sizeof(Lf->type), ty); /* * Set protocol name. */ (void) strncpy(Lf->iproto, "ROUTE", IPROTOL - 1); Lf->iproto[IPROTOL - 1] = '\0'; Lf->inp_ty = 2; /* * Read routing control structure. */ if (read_rts_t(va, pha, (KA_T)cs.conn_proto_priv.cp_rts, &rt)) return(1); /* /* * Save AF_ROUTE size and state information. */ if (!Fsize) Lf->off_def = 1; Lf->lts.type = 1; Lf->lts.state.i = (int)rt.rts_state; /* * Set network file selection status. */ if (Fnet) { if (!FnetTy || ((FnetTy == 4) && (af == AF_INET)) || ((FnetTy == 6) && (af == AF_INET6)) ) { Lf->sf |= SELNET; } } # if defined(HASSOOPT) /* * Save ROUTE flags. */ if (Ftcptpi & TCPTPI_FLAGS) { if (rt.rts_debug.rts_Debug) Lf->lts.opt |= SO_DEBUG; if (rt.rts_debug.rts_dontroute) Lf->lts.opt |= SO_DONTROUTE; if (rt.rts_debug.rts_broadcast) Lf->lts.opt |= SO_BROADCAST; if (rt.rts_debug.rts_reuseaddr) Lf->lts.opt |= SO_REUSEADDR; if (rt.rts_debug.rts_useloopback) Lf->lts.opt |= SO_USELOOPBACK; } # endif /* defined(HASSOOPT) */ break; default: (void) printiproto((int)cs.conn_ulp); (void) snpf(Namech, Namechl - 1, "unsupported socket family: %u", so->so_family); Namech[Namechl - 1] = '\0'; enter_nm(Namech); Lf->inp_ty = 2; } return(1); } #endif /* solaris>=110000*/ /* * process_socket() - process Solaris socket */ void process_socket(sa, ty) KA_T sa; /* stream's data address in kernel */ char *ty; /* socket type name */ { int af; unsigned char *fa = (unsigned char *)NULL; int fp = 0; int i, lp; #if solaris<110000 # if solaris>=100000 && defined(HAS_IPCLASSIFIER_H) struct conn_s ic; #define ipc_v6laddr conn_srcv6 #define ipc_v6faddr conn_remv6 #define ipc_fport conn_fport #define ipc_lport conn_lport # else /* solaris<100000 || !defined(HAS_IPCLASSIFIER_H) */ struct ipc_s ic; # endif /* solaris>=100000 && defined(HAS_IPCLASSIFIER_H) */ #else /* solaris>=110000 */ struct conn_s cs; #endif /* solaris<110000 */ int ics = 0; unsigned char *la = (unsigned char *)NULL; struct module_info mi; KA_T ka; u_short p; KA_T pcb = (KA_T)NULL; struct queue q; struct qinit qi; KA_T qp; u_short *s; struct stdata sd; unsigned char *ta; char tbuf[32]; #if solaris<20600 struct tcp_s { /* should come from kernel source * file ../uts/common/inet/tcp.c */ # if solaris>=20400 struct tcp_s *d1[8]; # endif /* solaris>=20400 */ # if defined(P101318) && P101318>=32 struct tcp_s *d1[6]; # endif /* defined(P101318) && P101318>=32 */ int tcp_state; queue_t *d3[2]; mblk_t *d4[2]; u_long d5; mblk_t *d6; u_long d7; u_long tcp_snxt; /* Senders next seq num */ u_long tcp_suna; /* Sender unacknowledged */ u_long tcp_swnd; /* Senders window (relative to suna) */ u_long d8[5]; int tcp_hdr_len; /* combined TCP/IP header length */ tcph_t *tcp_tcph; /* pointer to combined header */ int d9; unsigned int d10; int d11; mblk_t *d12; long d13; mblk_t *d14; u_long d15; # if solaris<20400 && (!defined(P101318) || P101318<32) mblk_t *d16; # endif /* solaris<20400 && (!defined(P101318) || P101318<32) */ unsigned int d17; u_long tcp_rnxt; /* Seq we expect to recv next */ u_long tcp_rwnd; /* Current receive window */ u_long d18; long d19[2]; mblk_t *d20[4]; u_long d21[5]; long d22[3]; # if solaris<20500 u_long d23[2]; u_long tcp_rack; /* Seq # we have acked */ # else /* solaris>=20500 */ u_long d23[3]; # endif /* solaris<20500 */ # if solaris<20400 u_long d24[28]; # else /* solaris>=20400 */ # if solaris<20500 u_long d24[67]; # else /* solaris>=20500 */ # if solaris<20501 u_long d25[6]; # else /* solaris>=20501 */ u_long d25[8]; # endif /* solaris<20501 */ u_long tcp_rack; /* Seq # we have acked */ # if solaris<20501 u_long d26[29]; # else /* solaris>=20501 */ u_long d26[33]; # endif /* solaris>=20501 */ # endif /* solaris<20500 */ # endif /* solaris<20400 */ iph_t tcp_iph; } tc; #else /* solaris>=20600 */ struct tcp_s tc; #endif /* solaris<20600 */ #if solaris>=80000 && !defined(HAS_IPCLASSIFIER_H) tcpb_t tcb; #endif /* solaris>=80000 && !defined(HAS_IPCLASSIFIER_H) */ tcpb_t *tcbp = (tcpb_t *)NULL; int tcs = 0; tcph_t th; tcph_t *tha = (tcph_t *)NULL; #if solaris<110000 struct ud_s { /* should come from kernel source * file ../uts/common/inet/udp.c */ uint udp_state; /* TPI state */ unsigned char d1[2]; unsigned char udp_port[2]; /* port bound to this stream */ unsigned char udp_src[4]; /* source address of this stream */ } uc; #else /* solaris>=110000 */ udp_t uc; /* UDP control structure */ #endif /* solaris<110000 */ int ucs = 0; #if defined(HASIPv6) if (strrchr(ty, '6')) { (void) snpf(Lf->type, sizeof(Lf->type), "IPv6"); af = AF_INET6; } else { (void) snpf(Lf->type, sizeof(Lf->type), "IPv4"); af = AF_INET; } #else /* !defined(HASIPv6) */ (void) snpf(Lf->type, sizeof(Lf->type), "inet"); af = AF_INET; #endif /* defined(HASIPv6) */ /* * Set network file selection status. */ if (Fnet) { if (!FnetTy || ((FnetTy == 4) && (af == AF_INET)) #if defined(HASIPv6) || ((FnetTy == 6) && (af == AF_INET6)) #endif /* defined(HASIPv6) */ ) { if (!TcpStIn && !UdpStIn) Lf->sf |= SELNET; } } Lf->inp_ty = 2; /* * Convert type to upper case protocol name. */ if (ty) { for (i = 0; (ty[i] != '\0') && (i < IPROTOL) && (i < 3); i++) { if (islower((unsigned char)ty[i])) Lf->iproto[i] = toupper((unsigned char)ty[i]); else Lf->iproto[i] = ty[i]; } } else i = 0; Lf->iproto[i] = '\0'; /* * Read stream queue entries to obtain private IP, TCP, and UDP structures. */ if (!sa || readstdata(sa, &sd)) qp = (KA_T)NULL; else qp = (KA_T)sd.sd_wrq; for (i = 0; qp && i < 20; i++, qp = (KA_T)q.q_next) { if (kread(qp, (char *)&q, sizeof(q))) break; if ((ka = (KA_T)q.q_qinfo) == (KA_T)NULL || kread(ka, (char *)&qi, sizeof(qi))) continue; if ((ka = (KA_T)qi.qi_minfo) == (KA_T)NULL || kread(ka, (char *)&mi, sizeof(mi)) || (ka = (KA_T)mi.mi_idname) == (KA_T)NULL) continue; if (kread(ka, (char *)&tbuf, sizeof(tbuf) - 1)) continue; if ((pcb = (KA_T)q.q_ptr) == (KA_T)NULL) continue; #if solaris<110000 if (strncasecmp(tbuf, "IP", 2) == 0) { if (kread(pcb, (char *)&ic, sizeof(ic)) == 0) ics = 1; continue; } #endif /* solaris<110000 */ if (strncasecmp(tbuf, "TCP", 3) == 0) { #if solaris<=90000 || !defined(HAS_IPCLASSIFIER_H) if (!kread((KA_T)pcb, (char *)&tc, sizeof(tc))) # if solaris>=80000 { if (tc.tcp_base && !kread((KA_T)tc.tcp_base, (char *)&tcb, sizeof(tcb))) { tcs = 1; tcbp = &tcb; } tc.tcp_base = &tcb; /* support for macros */ tcb.tcpb_tcp = &tc; /* support for macros */ } # else /* solaris<80000 */ tcs = 1; # endif /* solaris>=80000 */ #else /* solaris>90000 && defined(HAS_IPCLASSIFIER_H) */ # if solaris>=110000 if (!kread(pcb, (char *)&cs, sizeof(cs)) && (cs.conn_ulp == IPPROTO_TCP) ) { ics = 1; if ((ka = (KA_T)cs.conn_proto_priv.cp_tcp) && !kread(ka, (char *)&tc, sizeof(tc)) ) { tcs = 1; } } # else /* solaris<110000 */ if (!kread((KA_T)pcb, (char *)&ic, sizeof(ic)) && ic.conn_tcp && !kread((KA_T)ic.conn_tcp, (char *)&tc, sizeof(tc)) ) { ics = tcs = 1; } # endif /* solaris>=110000 */ #endif /* solaris<=90000 || !defined(HAS_IPCLASSIFIER_H) */ if (tcs && TcpNstates) { int s = (int)tc.tcp_state + TcpStOff; /* * Check for TCP state inclusion or exclusion. */ if (s < TcpNstates) { if (TcpStXn) { if (TcpStX[s]) { Lf->sf &= ~SELNET; Lf->sf |= SELEXCLF; return; } } if (TcpStIn) { if (TcpStI[s]) { TcpStI[s] = 2; Lf->sf |= SELNET; } else { Lf->sf &= ~SELNET; Lf->sf |= SELEXCLF; return; } } } } if (!(Lf->sf & SELNET) && !TcpStIn && UdpStIn) { if (Fnet) { if (!FnetTy || (FnetTy == 4) && (af == AF_INET) #if defined(HASIPv6) || (FnetTy == 6) && (af == AF_INET6) #endif /* defined(HASIPv6) */ ) { Lf->sf |= SELNET; } } } continue; } if (strncasecmp(tbuf, "UDP", 3) == 0) { #if solaris<110000 if (kread(pcb, (char *)&uc, sizeof(uc)) == 0) ucs = 1; #else /* solaris>=110000 */ if (!kread(pcb, (char *)&cs, sizeof(cs)) && (cs.conn_ulp == IPPROTO_UDP) ) { ics = 1; if ((ka = (KA_T)cs.conn_proto_priv.cp_udp) && !read_udp_t(ka, &uc) ) { ucs = 1; } } #endif /* solaris<110000 */ if (ucs && UdpNstates) { unsigned int s = (unsigned int)uc.udp_state + UdpStOff; /* * Check for UDP state inclusion or exclusion. */ if (s < UdpNstates) { if (UdpStXn) { if (UdpStX[s]) { Lf->sf &= ~SELNET; Lf->sf |= SELEXCLF; return; } } if (UdpStIn) { if (UdpStI[s]) { UdpStI[s] = 2; Lf->sf |= SELNET; } else { Lf->sf |= SELEXCLF; return; } } } } if (!(Lf->sf & SELNET) && TcpStIn && !UdpStIn) { if (Fnet) { if (!FnetTy || (FnetTy == 4) && (af == AF_INET) #if defined(HASIPv6) || (FnetTy == 6) && (af == AF_INET6) #endif /* defined(HASIPv6) */ ) { Lf->sf |= SELNET; } } } continue; } } if (ics) { /* * Print stream head's q_ptr address as protocol control block address. */ if (pcb) enter_dev_ch(print_kptr(pcb, (char *)NULL, 0)); if (strncmp(Lf->iproto, "UDP", 3) == 0) { /* * Save UDP address and TPI state. */ #if solaris<20600 la = (unsigned char *)&ic.ipc_udp_addr; p = (u_short)ic.ipc_udp_port; #else /* solaris>=20600 */ # if solaris>=110000 af = (uc.udp_ipversion == IPV6_VERSION) ? AF_INET6 : AF_INET; la = (af == AF_INET6) ? (unsigned char *)&uc.udp_v6src : (unsigned char *)&V4_PART_OF_V6(uc.udp_v6src); p = (u_short)uc.udp_port; # else /* solaris<110000 */ # if defined(HASIPv6) la = (af == AF_INET6) ? (unsigned char *)&ic.ipc_v6laddr : (unsigned char *)IPv6_2_IPv4(&ic.ipc_v6laddr); # else /* !defined(HASIPv6 */ la = (unsigned char *)&ic.ipc_laddr; # endif /* defined(HASIPv6) */ p = (u_short)ic.ipc_lport; # endif /* solaris>=110000 */ #endif /* solaris<20600 */ #if solaris<110000 if (IPv_ADDR_UNSPEC(af, la) && !p && ucs) { /* * If the ipc_s structure has no local address, use * the port in the ud_s structure. */ s = (u_short *)&uc.udp_port[0]; p = *s; } # if defined(HASIPv6) if ((af == AF_INET6) && la && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)la)) { /* * Convert a local IPv4 address in an IPv6 structure to an IPv4 * address in an IPv4 structure. Change the address family to * AF_INET. */ la = (unsigned char *)IPv6_2_IPv4(la); af = AF_INET; } # endif /* defined(HASIPv6) */ #endif /* solaris<110000 */ (void) ent_inaddr(la, (int)ntohs(p), (unsigned char *)NULL, -1, af); if (!Fsize) Lf->off_def = 1; if (ucs) { Lf->lts.type = 1; Lf->lts.state.ui = (unsigned int)uc.udp_state; } } else if (strncmp(Lf->iproto, "TCP", 3) == 0) { if (ics) { /* * Save TCP address. */ #if solaris<20400 la = (unsigned char *)&ic.ipc_tcp_addr[0]; p = (u_short)ic.ipc_tcp_addr[5]; #else /* solaris>=20400 */ # if solaris<20600 la = (unsigned char *)&ic.ipc_tcp_laddr; p = (u_short)((short *)&ic.ipc_tcp_ports)[1]; # else /* solaris>=20600 */ # if solaris>=110000 la = (af == AF_INET6) ? (unsigned char *)&cs.connua_v6addr.connua_laddr : (unsigned char *)&cs.conn_src; lp = cs.conn_lport; # else /* solaris<110000 */ # if defined(HASIPv6) la = (af == AF_INET6) ? (unsigned char *)&ic.ipc_v6laddr : (unsigned char *)IPv6_2_IPv4(&ic.ipc_v6laddr); # else /* !defined(HASIPv6 */ la = (unsigned char *)&ic.ipc_laddr; # endif /* defined(HASIPv6) */ p = (u_short)ic.ipc_lport; # endif /* solaris>=110000 */ # endif /* solaris<20600 */ #endif /* solaris<20400 */ #if solaris<110000 if (IPv_ADDR_UNSPEC(af, la) && !p && tcs) { /* * If the ipc_s structure has no local address, use the * local address in the stream's tcp_iph structure (except * for Solaris 2.4), and the port number in the stream's * tcph structure. */ # if solaris!=20400 && solaris<80000 la = (unsigned char *)&tc.tcp_iph.iph_src[0]; # else /* solaris==20400 || solaris<80000 */ # if solaris>=100000 && defined(HAS_IPCLASSIFIER_H) la = (af == AF_INET6) ? (unsigned char *)&ic.conn_srcv6 : (unsigned char *)IPv6_2_IPv4(&ic.conn_srcv6); # else /* solaris<100000 || !defined(HAS_IPCLASSIFIER_H) */ # if solaris>=80000 # if defined(HASIPv6) la = (af == AF_INET6) ? (unsigned char *)&tcb.tcpb_ip_src_v6 : (unsigned char *)IPv6_2_IPv4(&tcb.tcpb_ip_src_v6); # else /* !defined(HASIPv6) */ la = (unsigned char *)&tcb.tcpb_ip_src; # endif /* defined(HASIPv6) */ # endif /* solaris>=80000 */ # endif /* solaris>=100000 && defined(HAS_IPCLASSIFIER_H) */ # endif /* solaris!=20400 && !defined(HASIPv6) */ if (tc.tcp_hdr_len && tc.tcp_tcph && !kread((KA_T)tc.tcp_tcph, (char *)&th, sizeof(th)) ) { tha = &th; s = (u_short *)&th.th_lport[0]; p = *s; } } #endif /* solaris<110000 */ lp = (int)ntohs(p); #if solaris<20400 if ((int)ic.ipc_tcp_addr[2] != INADDR_ANY || ic.ipc_tcp_addr[4] != 0) { fa = (unsigned char *)&ic.ipc_tcp_addr[2]; fp = (int)ntohs(ic.ipc_tcp_addr[4]); } #else /* solaris>=20400 */ # if solaris<20600 if ((int)ic.ipc_tcp_faddr != INADDR_ANY || ((u_short *) &ic.ipc_tcp_ports)[0] != 0) { fa = (unsigned char *)&ic.ipc_tcp_faddr; fp = (int)ntohs(((u_short *)&ic.ipc_tcp_ports)[0]); } # else /* solaris>=20600 */ # if solaris>=110000 ta = (af == AF_INET6) ? (unsigned char *)&cs.connua_v6addr.connua_faddr : (unsigned char *)&cs.conn_rem; if (!IPv_ADDR_UNSPEC(af, ta) || ((u_short)cs.conn_fport)) { fa = ta; fp = (u_short)cs.conn_fport; } # else /* solaris<110000 */ # if defined(HASIPv6) ta = (af == AF_INET6) ? (unsigned char *)&ic.ipc_v6faddr : (unsigned char *)IPv6_2_IPv4(&ic.ipc_v6faddr); # else /* !defined(HASIPv6) */ ta = (unsigned char *)&ic.ipc_faddr; # endif /* defined(HASIPv6) */ if (!IPv_ADDR_UNSPEC(af, ta) || ((u_short)ic.ipc_fport)) { fa = ta; fp = (int)ntohs(((u_short)ic.ipc_fport)); } # endif /* solaris>=110000 */ # endif /* solaris<20600 */ #endif /* solaris <20400 */ #if defined(HASIPv6) if ((af == AF_INET6) && ((la && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)la)) || ((fa && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)fa)))) ) { /* * Convert IPv4 addresses in IPv6 structures to IPv4 * addresses in IPv4 structures. Change the address * family to AF_INET. */ if (la) la = (unsigned char *)IPv6_2_IPv4(la); if (fa) fa = (unsigned char *)IPv6_2_IPv4(fa); af = AF_INET; } #endif /* defined(HASIPv6) */ if (fa || la) (void) ent_inaddr(la, lp, fa, fp, af); } /* * Save TCP state information. */ if (tcs) { (void) save_TCP_states(&tc, (caddr_t *)tha, tcbp, (caddr_t *)NULL); Lf->lts.type = 0; Lf->lts.state.i = (int)tc.tcp_state; } /* * Save TCP size information. */ if (tcs) (void) save_TCP_size(&tc); } } else (void) strcat(Namech, "no TCP/UDP/IP information available"); /* * Enter name characters if there are some. */ if (Namech[0]) enter_nm(Namech); } #if solaris>=110000 /* * read_icmp_t() - read connections icmp_t info */ static int read_icmp_t(va, ph, ia, ic) KA_T va; /* containing vnode kernel address */ KA_T ph; /* containing protocol handle kernel * address */ KA_T ia; /* icmp_t structure's kernel address */ icmp_t *ic; /* local icmp_t receiver */ { char tbuf[32], tbuf1[32]; /* print_kptr() temporary buffers */ # if defined(HAS_CONN_NEW) struct conn_s cs; /* connection structure */ KA_T ka; /* kernel address */ zeromem((char *)ic, sizeof(icmp_t)); # endif /* defined(HAS_CONN_NEW) */ (void) CTF_init(&IRU_ctfs, IRU_MOD_FORMAT, IRU_requests); if (!ia || CTF_MEMBER_READ(ia, ic, icmp_t_members, icmp_state) # if defined(HAS_CONN_NEW) || CTF_MEMBER_READ(ia, ic, icmp_t_members, icmp_connp) # else /* !defined(HAS_CONN_NEW) */ || CTF_MEMBER_READ(ia, ic, icmp_t_members, icmp_bound_v6src) || CTF_MEMBER_READ(ia, ic, icmp_t_members, icmp_v6src) || CTF_MEMBER_READ(ia, ic, icmp_t_members, icmp_debug) # endif /* defined(HAS_CONN_NEW) */ ) { (void) snpf(Namech, Namechl - 1, "vnode at %s; proto handle at %s; can't read icmp_t at %s", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr(ph, tbuf1, sizeof(tbuf1)), print_kptr(ia, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } # if defined(HAS_CONN_NEW) if ((ka = (KA_T)ic->icmp_connp) && !kread(ka, (char *)&cs, sizeof(cs))) { struct ip_xmit_attr_s xa; /* * Complete the icmp_t structure from the conn_s structure. */ ic->icmp_bound_v6src = cs.conn_bound_addr_v6; ic->icmp_v6src = cs.conn_saddr_v6; ic->icmp_debug.icmp_Debug = cs.conn_debug; ic->icmp_debug.icmp_broadcast = cs.conn_broadcast; ic->icmp_debug.icmp_reuseaddr = cs.conn_reuseaddr; ic->icmp_debug.icmp_useloopback = cs.conn_useloopback; ic->icmp_debug.icmp_dgram_errind = cs.conn_dgram_errind; if ((ka = (KA_T)cs.conn_ixa) && !kread(ka, (char *)&xa, sizeof(xa)) ) { ic->icmp_debug.icmp_dontroute = (xa.ixa_flags & IXAF_DONTROUTE) ? 1 : 0; } } # endif /* defined(HAS_CONN_NEW) */ return(0); } /* * read_rts_t() - read connections rts_t info */ static int read_rts_t(va, ph, ra, rt) KA_T va; /* containing vnode kernel address */ KA_T ph; /* containing protocol handle kernel * address */ KA_T ra; /* rts_t structure's kernel address */ rts_t *rt; /* local rts_t receiver */ { char tbuf[32], tbuf1[32]; /* print_kptr() temporary buffers */ # if defined(HAS_CONN_NEW) struct conn_s cs; /* connextion structure */ KA_T ka; /* kernal address */ zeromem((char *)rt, sizeof(rts_t)); # endif /* defined(HAS_CONN_NEW) */ (void) CTF_init(&IRU_ctfs, IRU_MOD_FORMAT, IRU_requests); if (!ra || CTF_MEMBER_READ(ra, rt, rts_t_members, rts_state) # if defined(HAS_CONN_NEW) || CTF_MEMBER_READ(ra, rt, rts_t_members, rts_connp) # else /* !defined(HAS_CONN_NEW) */ || CTF_MEMBER_READ(ra, rt, rts_t_members, rts_debug) # endif /* defined(HAS_CONN_NEW) */ ) { (void) snpf(Namech, Namechl - 1, "vnode at %s; proto handle at %s; can't read rts_t at %s", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr(ph, tbuf1, sizeof(tbuf1)), print_kptr(ra, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } # if defined(HAS_CONN_NEW) if ((ka = (KA_T)rt->rts_connp) && !kread(ka, (char *)&cs, sizeof(struct conn_s)) ) { struct ip_xmit_attr_s xa; /* * Fill in rts_debug from the connection structure. */ rt->rts_debug.rts_Debug = cs.conn_debug; rt->rts_debug.rts_broadcast = cs.conn_broadcast; rt->rts_debug.rts_reuseaddr = cs.conn_reuseaddr; rt->rts_debug.rts_useloopback = cs.conn_useloopback; if ((ka = (KA_T)cs.conn_ixa) && !kread(ka, (char *)&xa, sizeof(xa)) ) { rt->rts_debug.rts_dontroute = (xa.ixa_flags & IXAF_DONTROUTE) ? 1 : 0; } } # endif /* defined(HAS_CONN_NEW) */ return(0); } /* * read_udp_t() - read UDP control structure */ static int read_udp_t(ua, uc) KA_T ua; /* ucp_t kernel address */ udp_t *uc; /* receiving udp_t structure */ { (void) CTF_init(&IRU_ctfs, IRU_MOD_FORMAT, IRU_requests); if (!ua || CTF_MEMBER_READ(ua, uc, udp_t_members, udp_state) # if defined(HAS_CONN_NEW) || CTF_MEMBER_READ(ua, uc, udp_t_members, udp_connp) # else /* !defined(HAS_CONN_NEW) */ || CTF_MEMBER_READ(ua, uc, udp_t_members, udp_port) || CTF_MEMBER_READ(ua, uc, udp_t_members, udp_dstport) || CTF_MEMBER_READ(ua, uc, udp_t_members, udp_v6src) || CTF_MEMBER_READ(ua, uc, udp_t_members, udp_v6dst) || CTF_MEMBER_READ(ua, uc, udp_t_members, udp_ipversion) || CTF_MEMBER_READ(ua, uc, udp_t_members, udp_bits) # endif /* defined(HAS_CONN_NEW) */ ) { (void) snpf(Namech, Namechl, "can't read udp_t: %s", print_kptr(ua, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } return(0); } #endif /* solaris>=110000 */ /* * save_TCP_size() -- save TCP size information */ static void save_TCP_size(tc) tcp_t *tc; /* pointer to TCP control structure */ { int rq, sq; #if defined(HASTCPTPIQ) || defined(HASTCPTPIW) # if defined(HASTCPTPIW) Lf->lts.rw = (int)tc->tcp_rwnd; Lf->lts.ww = (int)tc->tcp_swnd; Lf->lts.rws = Lf->lts.wws = 1; # endif /* defined(HASTCPTPIW) */ if ((rq = (int)tc->tcp_rnxt - (int)tc->tcp_rack) < 0) rq = 0; if ((sq = (int)tc->tcp_snxt - (int)tc->tcp_suna - 1) < 0) sq = 0; # if defined(HASTCPTPIQ) Lf->lts.rq = (unsigned long)rq; Lf->lts.sq = (unsigned long)sq; Lf->lts.rqs = Lf->lts.sqs = 1; # endif /* defined(HASTCPTPIQ) */ if (Fsize) { if (Lf->access == 'r') Lf->sz = (SZOFFTYPE)rq; else if (Lf->access == 'w') Lf->sz = (SZOFFTYPE)sq; else Lf->sz = (SZOFFTYPE)(rq + sq); Lf->sz_def = 1; } else Lf->off_def = 1; #else /* !defined(HASTCPTPIQ) && !defined(HASTCPTPIW) */ Lf->off_def = 1; #endif /* defined(HASTCPTPIQ) || defined(HASTCPTPIW) */ } /* * save_TCP_states() - save TCP states */ static void save_TCP_states(tc, fa, tb, xp) tcp_t *tc; /* pointer to TCP control structure */ caddr_t *fa; /* flags address (may be NULL): * if HAS_CONN_NEW: conn_s * * if !CONN_HAS_NEW: tcph_t * */ tcpb_t *tb; /* pointer to TCP base structure (may * be NULL) */ caddr_t *xp; /* pointer to struct ip_xmit_attr_s if * HAS_CONN_NEW (may be NULL) */ { if (!tc) return; #if defined(HASSOOPT) # if defined(HAS_CONN_NEW) if (Ftcptpi & TCPTPI_FLAGS && fa) { struct conn_s *cs = (struct conn_s *)fa; if (cs->conn_broadcast) Lf->lts.opt |= SO_BROADCAST; if (cs->conn_debug) Lf->lts.opt |= SO_DEBUG; if (cs->conn_dgram_errind) Lf->lts.opt |= SO_DGRAM_ERRIND; if (xp && (((ip_xmit_attr_t *)xp)->ixa_flags & IXAF_DONTROUTE)) Lf->lts.opt |= SO_DONTROUTE; if (cs->conn_keepalive) { Lf->lts.opt |= SO_KEEPALIVE; Lf->lts.kai = (unsigned int)tc->tcp_ka_interval; } if (cs->conn_linger) { Lf->lts.opt |= SO_LINGER; Lf->lts.ltm = (unsigned int)cs->conn_lingertime; } if (cs->conn_oobinline) Lf->lts.opt |= SO_OOBINLINE; Lf->lts.pqlen = (unsigned int)tc->tcp_conn_req_cnt_q0; Lf->lts.qlen = (unsigned int)tc->tcp_conn_req_cnt_q; Lf->lts.qlim = (unsigned int)tc->tcp_conn_req_max; Lf->lts.pqlens = Lf->lts.qlens = Lf->lts.qlims = (unsigned char)1; if (cs->conn_reuseaddr) Lf->lts.opt |= SO_REUSEADDR; if (cs->conn_useloopback) Lf->lts.opt |= SO_USELOOPBACK; # else /* !defined(HAS_CONN_NEW) */ if (Ftcptpi & TCPTPI_FLAGS) { if (tc->tcp_broadcast) Lf->lts.opt |= SO_BROADCAST; if (tc->tcp_debug) Lf->lts.opt |= SO_DEBUG; if (tc->tcp_dgram_errind) Lf->lts.opt |= SO_DGRAM_ERRIND; if (tc->tcp_dontroute) Lf->lts.opt |= SO_DONTROUTE; if (tc->KEEPALIVE_INTERVAL) { Lf->lts.opt |= SO_KEEPALIVE; Lf->lts.kai = (unsigned int)tc->KEEPALIVE_INTERVAL; } if (tc->tcp_linger) { Lf->lts.opt |= SO_LINGER; Lf->lts.ltm = (unsigned int)tc->tcp_lingertime; } if (tc->tcp_oobinline) Lf->lts.opt |= SO_OOBINLINE; Lf->lts.pqlen = (unsigned int)tc->tcp_conn_req_cnt_q0; Lf->lts.qlen = (unsigned int)tc->tcp_conn_req_cnt_q; Lf->lts.qlim = (unsigned int)tc->tcp_conn_req_max; Lf->lts.pqlens = Lf->lts.qlens = Lf->lts.qlims = (unsigned char)1; # if solaris>=80000 # if defined(HAS_IPCLASSIFIER_H) if (tc->tcp_reuseaddr) # else /* !defined(HAS_IPCLASSIFIER_H) */ if (tb && tb->tcpb_reuseaddr) # endif /* !defined(HAS_IPCLASSIFIER_H) */ Lf->lts.opt |= SO_REUSEADDR; # endif /* solaris>=80000 */ if (tc->tcp_useloopback) Lf->lts.opt |= SO_USELOOPBACK; # endif /* defined(HAS_CONN_NEW) */ #endif /* defined(HASSOOPT) */ #if defined(HASTCPOPT) # if defined(ACK_TIMER) # if !defined(HAS_CONN_NEW) if (fa && (((tcph_t *)fa)->th_flags[0] & ACK_TIMER)) Lf->lts.topt |= TF_DELACK; # endif /* !defined(HAS_CONN_NEW) */ # endif /* defined(ACK_TIMER) */ # if solaris<80000 || defined(HAS_IPCLASSIFIER_H) Lf->lts.mss = (unsigned long)tc->tcp_mss; # else /* solaris>=80000 && !defined(HAS_IPCLASSIFIER_H) */ if (tb) Lf->lts.mss = (unsigned long)tb->tcpb_mss; # endif /* solaris<80000 || defined(HAS_IPCLASSIFIER_H) */ Lf->lts.msss = (unsigned char)1; if (tc->tcp_naglim == 1L) Lf->lts.topt |= TF_NODELAY; if (tc->tcp_fin_sent) Lf->lts.topt |= TF_SENTFIN; } #endif /* defined(HASTCPOPT) */ } lsof-4.86+dfsg.orig/dialects/sun/dproc.c0000444000175000017500000014541211325130241020323 0ustar nicholasnicholas/* * dproc.c - Solaris lsof functions for accessing process information */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dproc.c,v 1.36 2010/01/18 19:03:54 abe Exp $"; #endif #include "lsof.h" #if solaris<20500 #include "kernelbase.h" #endif /* solaris<20500 */ #if defined(HAS_CRED_IMPL_H) # if solaris>=110000 #define _KERNEL # endif /* solaris>=110000 */ #include # if solaris>=110000 #undef _KERNEL # endif /* solaris>=110000 */ #endif /* defined(HAS_CRED_IMPL_H) */ /* * Local definitions */ #if defined(__sparc) || defined(__sparcv9) #define ARCH64B "sparcv9" #else /* !defined(__sparc) && !defined(__sparcv9) */ # if defined(__i386) || defined(__amd64) #define ARCH64B "amd64" # endif /* defined(__i386) || defined(__amd64) */ #endif /* defined(__sparc) || defined(__sparcv9) */ #if solaris>=20501 #define KVMHASHBN 8192 /* KVM hash bucket count -- MUST BE * A POWER OF 2!!! */ #define HASHKVM(va) ((int)((va * 31415) >> 3) & (KVMHASHBN-1)) /* virtual address hash function */ # if solaris<70000 #define KAERR (u_longlong_t)-1 /* kvm_physaddr() error return */ #define KBUFT char /* kernel read buffer type */ #define KPHYS u_longlong_t /* kernel physical address type */ #define KVIRT u_int /* kernel virtual address type */ # else /* solaris>=70000 */ #define KAERR (uint64_t)-1 /* kvm_physaddr() error return */ #define KBUFT void /* kernel read buffer type */ #define KPHYS uint64_t /* kernel physical address type */ #define KVIRT uintptr_t /* kernel virtual address type */ # endif /* solaris<70000 */ #endif /* solaris>=20501 */ /* * Local structures */ #if solaris>=20501 typedef struct kvmhash { KVIRT vpa; /* virtual page address */ KPHYS pa; /* physical address */ struct kvmhash *nxt; /* next virtual address */ } kvmhash_t; #endif /* solaris>=20501 */ /* * Local variables */ #if solaris>=20501 static struct as *Kas = (struct as *)NULL; /* pointer to kernel's address space * map in kernel virtual memory */ static kvmhash_t **KVMhb = (kvmhash_t **)NULL; /* KVM hash buckets */ static int PageSz = 0; /* page size */ static int PSMask = 0; /* page size mask */ static int PSShft = 0; /* page size shift */ # if solaris<70000 static struct as Kam; /* kernel's address space map */ static int Kmd = -1; /* memory device file descriptor */ # endif /* solaris<70000 */ #endif /* solaris>=20501 */ #if solaris>=20500 static KA_T Kb = (KA_T)NULL; /* KERNELBASE for Solaris 2.5 */ #endif /* solaris>=20500 */ static int Np; /* number of P[], Pgid[] and Pid[] * entries */ static int Npa = 0; /* number of P[], Pgid[] and Pid[] * entries for which space has been * allocated */ static struct proc *P = NULL; /* local proc structure table */ static int *Pgid = NULL; /* process group IDs for P[] entries */ static int *Pid = NULL; /* PIDs for P[] entries */ static KA_T PrAct = (KA_T)NULL; /* kernel's *practive address */ static gid_t Savedgid; /* saved (effective) GID */ static KA_T Sgvops; /* [_]segvn_ops address */ static int Switchgid = 0; /* must switch GIDs for kvm_open() */ #if defined(HASZONES) static znhash_t **ZoneNm = (znhash_t **)NULL; /* zone names hash buckets */ #endif /* defined(HASZONES) */ /* * Local function prototypes */ _PROTOTYPE(static void get_kernel_access,(void)); _PROTOTYPE(static void process_text,(KA_T pa)); _PROTOTYPE(static void read_proc,(void)); _PROTOTYPE(static void readfsinfo,(void)); #if solaris>=20501 _PROTOTYPE(static void readkam,(KA_T addr)); #endif /* solaris>=20501 */ #if solaris>=20501 && solaris<70000 _PROTOTYPE(extern u_longlong_t kvm_physaddr,(kvm_t *, struct as *, u_int)); #endif /* solaris>=20501 && solaris<70000 */ #if defined(HASZONES) _PROTOTYPE(static int hash_zn,(char *zn)); #endif /* defined(HASZONES) */ /* * close_kvm() - close kernel virtual memory access */ void close_kvm() { if (!Kd) return; if (Kd) { if (kvm_close(Kd) != 0) { (void) fprintf(stderr, "%s: kvm_close failed\n", Pn); Exit(1); } Kd = (kvm_t *)NULL; } #if solaris>=20501 && solaris<70000 if (Kmd >= 0) { (void) close(Kmd); Kmd = -1; } #endif /* solaris>=20501 && solaris<70000 */ } /* * gather_proc_info() - gather process information */ void gather_proc_info() { short cckreg; /* conditional status of regular file * checking: * 0 = unconditionally check * 1 = conditionally check */ short ckscko; /* socket file only checking status: * 0 = none * 1 = check only socket files, * including TCP and UDP * streams with eXPORT data, * where supported */ static int ft = 1; int i, j; struct proc *p; int pgid, pid, px; long pofv; short pss, sf; struct user *u; uid_t uid; #if solaris>=20400 int k; # if !defined(NFPCHUNK) #define uf_ofile uf_file #define uf_pofile uf_flag #define u_flist u_finfo.fi_list #define u_nofiles u_finfo.fi_nfiles #define NFPREAD 64 # else /* defined(NFPCHUNK) */ #define NFPREAD NFPCHUNK # endif /* !defined(NFPCHUNK) */ uf_entry_t uf[NFPREAD]; #endif /* solaris>=20400 */ #if solaris>=20500 struct cred pc; #endif /* solaris>=20500 */ #if defined(HASZONES) struct zone z; int zh; char zn[ZONENAME_MAX + 1]; znhash_t *zp, *zpn; #endif /* defined(HASZONES) */ if (ft) { /* * Do first-time only operations. */ /* * Get the segment vnodeops address. */ if (get_Nl_value("sgvops", Drive_Nl, &Sgvops) < 0) Sgvops = (KA_T)NULL; ft = 0; } else if (!HasALLKMEM) { /* * If not the first time and the ALLKMEM device isn't available, it is * necessary to close and reopen the KVM device, so that kvm_open() * will acquire a fresh address for the head of the linked list process * table. */ close_kvm(); open_kvm(); #if solaris>=20501 /* * If not the first time and the ALLKMEM device isn't available, * re-read the kernel's address space map. */ readkam((KA_T)NULL); #endif /* solaris>=20501 */ } /* * Define socket and regular file conditional processing flags. * * If only socket files have been selected, or socket files have been * selected, ANDed with other selection options, enable the skipping of * regular files. * * If socket files and some process options have been selected, enable * conditional skipping of regular file; i.e., regular files will be skipped * unless they belong to a process selected by one of the specified options. */ if (Selflags & SELNW) { /* * Some network files selection options have been specified. */ if (Fand || !(Selflags & ~SELNW)) { /* * Selection ANDing or only network file options have been * specified, so set unconditional skipping of regular files * and socket file only checking. */ cckreg = 0; ckscko = 1; } else { /* * If ORed file selection options have been specified, or no * ORed process selection options have been specified, enable * unconditional file checking and clear socket file only * checking. * * If only ORed process selection options have been specified, * enable conditional file skipping and socket file only checking. */ if ((Selflags & SELFILE) || !(Selflags & SELPROC)) cckreg = ckscko = 0; else cckreg = ckscko = 1; } } else { /* * No network file selection options were specified. Enable * unconditional file checking and clear socket file only checking. */ cckreg = ckscko = 0; } /* * Read the process table. */ read_proc(); /* * Loop through processes. */ for (p = P, px = 0; px < Np; p++, px++) { /* * Get the process ID. */ if (Fpgid) pgid = Pgid[px]; else pgid = 0; pid = Pid[px]; #if solaris<20500 uid = p->p_uid; #else /* solaris >=20500 */ /* * Read credentials for Solaris 2.5 and above process. */ if (kread((KA_T)p->p_cred, (char *)&pc, sizeof(pc))) continue; uid = pc.cr_uid; #endif /* solaris<20500 */ /* * See if the process is excluded. */ if (is_proc_excl(pid, pgid, (UID_ARG)uid, &pss, &sf)) continue; #if defined(HASZONES) /* * If the -z (zone) option was specified, get the zone name. */ if (Fzone) { zn[0] = zn[sizeof(zn) - 1] = '\0'; if (p->p_zone && !kread((KA_T)p->p_zone, (char *)&z, sizeof(z))) { if (!z.zone_name || kread((KA_T)z.zone_name, (char *)&zn, sizeof(zn) - 1)) zn[0] = '\0'; } } #endif /* defined(HASZONES) */ /* * Get the user area associated with the process. */ u = &p->p_user; /* * Allocate a local process structure and start filling it. */ if (is_cmd_excl(u->u_comm, &pss, &sf)) continue; if (cckreg) { /* * If conditional checking of regular files is enabled, enable * socket file only checking, based on the process' selection * status. */ ckscko = (sf & SELPROC) ? 0 : 1; } alloc_lproc(pid, pgid, (int)p->p_ppid, (UID_ARG)uid, u->u_comm, (int)pss, (int)sf); Plf = (struct lfile *)NULL; #if defined(HASZONES) /* * If zone processing is enabled and requested, and if there is a zone * name: * * o Skip processes excluded by zone name. * o Save zone name. */ if (Fzone && zn[0]) { zh = hash_zn(zn); if (ZoneArg) { /* * See if zone name excludes the process. */ for (zp = ZoneArg[zh]; zp; zp = zp->next) { if (!strcmp(zn, zp->zn)) break; } if (!zp) continue; zp->f = 1; Lp->pss |= PS_PRI; Lp->sf |= SELZONE; } /* * Make sure the zone name is cached, then save a pointer to it in * the local proc structure. */ if (!ZoneNm) { if (!(ZoneNm = (znhash_t **)calloc(HASHZONE, sizeof(znhash_t *)))) { (void) fprintf(stderr, "%s: no space for zone name hash\n", Pn); Exit(1); } } for (zp = ZoneNm[zh]; zp; zp = zp->next) { if (!strcmp(zn, zp->zn)) break; } if (!zp) { /* * The zone name isn't cached, so cache it. */ if (!(zp = (znhash_t *)malloc((MALLOC_S)sizeof(znhash_t)))) { (void) fprintf(stderr, "%s: no zone name cache space: %s\n", Pn, zn); Exit(1); } if (!(zp->zn = mkstrcpy(zn, (MALLOC_S *)NULL))) { (void) fprintf(stderr, "%s: no zone name space at PID %d: %s\n", Pn, (int)Lp->pid, zn); Exit(1); } zp->next = ZoneNm[zh]; ZoneNm[zh] = zp; } Lp->zn = zp->zn; } #endif /* defined(HASZONES) */ /* * Save file count. */ Unof = u->u_nofiles; /* * Save current working directory information. */ if (!ckscko && u->u_cdir) { alloc_lfile(CWD, -1); #if defined(FILEPTR) FILEPTR = (struct file *)NULL; #endif /* defined(FILEPTR) */ process_node((KA_T)u->u_cdir); if (Lf->sf) link_lfile(); } /* * Save root directory information. */ if (!ckscko && u->u_rdir) { alloc_lfile(RTD, -1); #if defined(FILEPTR) FILEPTR = (struct file *)NULL; #endif /* defined(FILEPTR) */ process_node((KA_T)u->u_rdir); if (Lf->sf) link_lfile(); } /* * Save information on text files. */ if (!ckscko && p->p_as && Sgvops) { #if defined(FILEPTR) FILEPTR = (struct file *)NULL; #endif /* defined(FILEPTR) */ process_text((KA_T)p->p_as); } /* * Save information on file descriptors. * * Under Solaris the file pointers are stored in dynamically-linked * ufchunk structures, each containing NFPREAD file pointers. The * first ufchunk structure is in the user area. * * Under Solaris 2.4 the file pointers are in a dynamically allocated, * contiguous memory block. */ #if solaris<20400 for (i = 0, j = 0; i < u->u_nofiles; i++) { if (++j > NFPCHUNK) { if (!u->u_flist.uf_next) break; if (kread((KA_T)u->u_flist.uf_next, (char *)&u->u_flist, sizeof(struct ufchunk))) break; j = 1; } if (!u->u_flist.uf_ofile[j-1]) #else /* solaris>=20400 */ for (i = 0, j = NFPREAD; i < u->u_nofiles; i++) { if (++j > NFPREAD) { k = u->u_nofiles - i; if (k > NFPREAD) k = NFPREAD; if (kread((KA_T)((unsigned long)u->u_flist + i * sizeof(uf_entry_t)), (char*)&uf, k * sizeof(uf_entry_t))) { break; } j = 1; } if (!uf[j-1].uf_ofile) #endif /* solaris<20400 */ continue; alloc_lfile((char *)NULL, i); #if solaris<20400 pofv = (long)u->u_flist.uf_pofile[j-1]; process_file((KA_T)u->u_flist.uf_ofile[j-1]); #else /* solaris>=20400 */ pofv = uf[j-1].uf_pofile; process_file((KA_T)uf[j-1].uf_ofile); #endif /* solaris <20400 */ if (Lf->sf) { #if defined(HASFSTRUCT) if (Fsv & FSV_FG) Lf->pof = pofv; #endif /* defined(HASFSTRUCT) */ link_lfile(); } } /* * Examine results. */ if (examine_lproc()) return; } } /* * get_kernel_access() - access the required information in the kernel */ static void get_kernel_access() { int i; struct stat sb; KA_T v; #if defined(HAS_AFS) struct nlist *nl = (struct nlist *)NULL; #endif /* defined(HAS_AFS) */ /* * Check the Solaris or SunOS version number; check the SunOS architecture. */ (void) ckkv("Solaris", LSOF_VSTR, (char *)NULL, (char *)NULL); #if solaris>=70000 /* * Compare the Solaris 7 and above lsof compilation bit size with the kernel * bit size. * * Quit on a mismatch. */ { char *cp, isa[1024]; short kbits = 32; # if defined(_LP64) short xkbits = 64; # else /* !defined(_LP64) */ short xkbits = 32; # endif /* defined(_LP64) */ if (sysinfo(SI_ISALIST, isa, (long)sizeof(isa)) < 0) { (void) fprintf(stderr, "%s: can't get ISA list: %s\n", Pn, strerror(errno)); Exit(1); } for (cp = isa; *cp;) { if (strncmp(cp, ARCH64B, strlen(ARCH64B)) == 0) { kbits = 64; break; } if (!(cp = strchr(cp, ' '))) break; cp++; } if (kbits != xkbits) { (void) fprintf(stderr, "%s: FATAL: lsof was compiled for a %d bit kernel,\n", Pn, (int)xkbits); (void) fprintf(stderr, " but this machine has booted a %d bit kernel.\n", (int)kbits); Exit(1); } } #endif /* solaris>=70000 */ /* * Get kernel symbols. */ if (Nmlst && !is_readable(Nmlst, 1)) Exit(1); (void) build_Nl(Drive_Nl); #if defined(HAS_AFS) if (!Nmlst) { /* * If AFS is defined and we're getting kernel symbol values from * from N_UNIX, make a copy of Nl[] for possible use with the AFS * modload file. */ if (!(nl = (struct nlist *)malloc(Nll))) { (void) fprintf(stderr, "%s: no space (%d) for Nl[] copy\n", Pn, Nll); Exit(1); } (void) memcpy((void *)nl, (void *)Nl, (size_t)Nll); } #endif /* defined(HAS_AFS) */ if (nlist(Nmlst ? Nmlst : N_UNIX, Nl) < 0) { (void) fprintf(stderr, "%s: can't read namelist from %s\n", Pn, Nmlst ? Nmlst : N_UNIX); Exit(1); } #if defined(HAS_AFS) if (nl) { /* * If AFS is defined and we're getting kernel symbol values from * N_UNIX, and if any X_AFS_* symbols isn't there, see if it is in the * the AFS modload file. Make sure that other symbols that appear in * both name list files have the same values. */ if ((get_Nl_value("arFID", Drive_Nl, &v) >= 0 && !v) || (get_Nl_value("avops", Drive_Nl, &v) >= 0 && !v) || (get_Nl_value("avol", Drive_Nl, &v) >= 0 && !v)) (void) ckAFSsym(nl); (void) free((MALLOC_P *)nl); } #endif /* defined(HAS_AFS) */ /* * Determine the availability of the ALLKMEM device. If it is available, the * active processes will be gathered directly from the active process chain. * * If ALLKMEM isn't available, the active processes will be gathered via the * kvm_*proc() functions. */ if (statsafely(ALLKMEM, &sb) == 0) HasALLKMEM = 1; #if defined(HASVXFSUTIL) /* * If the VXFS utility library is being used, attempt to get the VXFS inode * offsets before setgid permission is surrendered. */ if (access_vxfs_ioffsets() && !Fwarn) { /* * Warn that the VxFS offsets are unavailable. */ (void) fprintf(stderr, "%s: WARNING: vxfsu_get_ioffsets() returned an error.\n", Pn); (void) fprintf(stderr, "%s: WARNING: Thus, no vx_inode information is available\n", Pn); (void) fprintf(stderr, "%s: WARNING: for display or selection of VxFS files.\n", Pn); } #endif /* defined(HASVXFSUTIL) */ #if defined(WILLDROPGID) /* * If Solaris kernel memory is coming from KMEM, the process is willing to * surrender GID permission, and the ALLKMEM device is not available, set up * for GID switching after the first call to open_kvm(). */ if (!Memory && !HasALLKMEM) { Savedgid = getegid(); if (Setgid) Switchgid = 1; } /* * If kernel memory isn't coming from KMEM, drop setgid permission * before attempting to open the (Memory) file. */ if (Memory) (void) dropgid(); #else /* !defined(WILLDROPGID) */ /* * See if the non-KMEM memory file is readable. */ if (Memory && !is_readable(Memory, 1)) Exit(1); #endif /* defined(WILLDROPGID) */ /* * Open access to kernel memory. */ open_kvm(); #if solaris>=20500 /* * Get the kernel's KERNELBASE value for Solaris 2.5 and above. */ v = (KA_T)0; if (get_Nl_value("kbase", Drive_Nl, &v) < 0 || !v || kread((KA_T)v, (char *)&Kb, sizeof(Kb))) { (void) fprintf(stderr, "%s: can't read kernel base address from %s\n", Pn, print_kptr(v, (char *)NULL, 0)); Exit(1); } #endif /* solaris>=20500 */ /* * Get the Solaris clone major device number, if possible. */ v = (KA_T)0; if ((get_Nl_value("clmaj", Drive_Nl, &v) < 0) || !v) { if (get_Nl_value("clmaj_alt", Drive_Nl, &v) < 0) v = (KA_T)0; } if (v && kread((KA_T)v, (char *)&CloneMaj, sizeof(CloneMaj)) == 0) HaveCloneMaj = 1; /* * If the ALLKMEM device is available, check for the address of the kernel's * active process chain. If it's not available, clear the ALLKMEM status. */ if (HasALLKMEM) { if ((get_Nl_value("pract", Drive_Nl, &PrAct) < 0) || !PrAct) HasALLKMEM = 0; } #if solaris>=20501 /* * If the ALLKMEM device isn't available, get the kernel's virtual to physical * map structure for Solaris 2.5.1 and above. */ if (!HasALLKMEM) { if (get_Nl_value("kasp", Drive_Nl, &v) >= 0 && v) { PageSz = getpagesize(); PSMask = PageSz - 1; for (i = 1, PSShft = 0; i < PageSz; i <<= 1, PSShft++) ; (void) readkam(v); } } #endif /* solaris>=20501 */ #if defined(WILLDROPGID) /* * If the ALLKMEM device is available -- i.e., we're not using the kvm_*proc() * functions to read proc structures -- and if we're willing to drop setgid * permission, do so. */ if (HasALLKMEM) (void) dropgid(); #endif /* defined(WILLDROPGID) */ } #if defined(HASZONES) /* * enter_zone_arg() - enter zone name argument */ int enter_zone_arg(zn) char *zn; /* zone name */ { int zh; znhash_t *zp, *zpn; /* * Allocate zone argument hash space, as required. */ if (!ZoneArg) { if (!(ZoneArg = (znhash_t **)calloc(HASHZONE, sizeof(znhash_t *)))) { (void) fprintf(stderr, "%s: no space for zone arg hash\n", Pn); Exit(1); } } /* * Hash the zone name and search the argument hash. */ zh = hash_zn(zn); for (zp = ZoneArg[zh]; zp; zp = zp->next) { if (!strcmp(zp->zn, zn)) break; } if (zp) { /* * Process a duplicate. */ if (!Fwarn) (void) fprintf(stderr, "%s: duplicate zone name: %s\n", Pn, zn); return(1); } /* * Create a new hash entry and link it to its bucket. */ if (!(zpn = (znhash_t *)malloc((MALLOC_S)sizeof(znhash_t)))) { (void) fprintf(stderr, "%s no hash space for zone: %s\n", Pn, zn); Exit(1); } zpn->f = 0; zpn->zn = zn; zpn->next = ZoneArg[zh]; ZoneArg[zh] = zpn; return(0); } /* * hash_zn() - hash zone name */ static int hash_zn(zn) char *zn; /* zone name */ { register int i, h; size_t l; if (!(l = strlen(zn))) return(0); if (l == 1) return((int)*zn & (HASHZONE - 1)); for (i = h = 0; i < (int)(l - 1); i++) { h ^= ((int)zn[i] * (int)zn[i+1]) << ((i*3)%13); } return(h & (HASHZONE - 1)); } #endif /* defined(HASZONES) */ /* * initialize() - perform all initialization */ void initialize() { get_kernel_access(); /* * Read Solaris file system information and construct the clone table. * * The clone table is needed to identify sockets. */ readfsinfo(); #if defined(HASDCACHE) readdev(0); #else /* !defined(HASDCACHE) */ read_clone(); #endif /*defined(HASDCACHE) */ } /* * kread() - read from kernel memory */ int kread(addr, buf, len) KA_T addr; /* kernel memory address */ char *buf; /* buffer to receive data */ READLEN_T len; /* length to read */ { register int br; /* * Because lsof reads kernel data and follows pointers found there at a * rate considerably slower than the kernel, lsof sometimes acquires * invalid pointers. If the invalid pointers are fed to kvm_[k]read(), * a segmentation violation may result, so legal kernel addresses are * limited by the value of the KERNELBASE symbol (Kb value from the * kernel's _kernelbase variable for Solaris 2.5 and above). */ #if solaris>=20500 #define KVMREAD kvm_kread if (addr < Kb) #else /* solaris<20500 */ #define KVMREAD kvm_read if (addr < (KA_T)KERNELBASE) #endif /* solaris>=20500 */ return(1); #if solaris>=20501 /* * Do extra address checking for Solaris above 2.5 when the ALLKMEM device * isn't available. * * Make sure the virtual address represents real physical memory by testing * it with kvm_physaddr(). * * For Solaris below 7 read the kernel data with llseek() and read(). For * Solaris 7 and above use kvm_pread(). */ if (Kas && !HasALLKMEM) { # if solaris>20501 register int b2r; register char *bp; # endif /* solaris>20501 */ register int h, ip, tb; register kvmhash_t *kp; KPHYS pa; register KVIRT va, vpa; # if solaris<20600 for (tb = 0, va = (KVIRT)addr; tb < len; tb += br, va += (KVIRT)br) # else /* solaris>=20600 */ for (bp = buf, tb = 0, va = (KVIRT)addr; tb < len; bp += br, tb += br, va += (KVIRT)br) # endif /* solaris<20600 */ { vpa = (va & (KVIRT)~PSMask) >> PSShft; ip = (int)(va & (KVIRT)PSMask); h = HASHKVM(vpa); for (kp = KVMhb[h]; kp; kp = kp->nxt) { if (kp->vpa == vpa) { pa = kp->pa; break; } } if (!kp) { if ((pa = kvm_physaddr(Kd, Kas, va)) == KAERR) return(1); if (!(kp = (kvmhash_t *)malloc(sizeof(kvmhash_t)))) { (void) fprintf(stderr, "%s: no kvmhash_t space\n", Pn); Exit(1); } kp->nxt = KVMhb[h]; pa = kp->pa = (pa & ~(KPHYS)PSMask); kp->vpa = vpa; KVMhb[h] = kp; } # if solaris<20600 br = (int)(len - tb); if ((ip + br) > PageSz) br = PageSz - ip; # else /* solaris>=20600 */ b2r = (int)(len - tb); if ((ip + b2r) > PageSz) b2r = PageSz - ip; pa |= (KPHYS)ip; # if solaris<70000 if (llseek(Kmd, (offset_t)pa, SEEK_SET) == (offset_t)-1) return(1); if ((br = (int)read(Kmd, (void *)bp, (size_t)b2r)) <= 0) return(1); # else /* solaris>=70000 */ if ((br = kvm_pread(Kd, pa, (void *)bp, (size_t)b2r)) <= 0) return(1); # endif /* solaris<70000 */ # endif /* solaris<20600 */ } # if solaris>=20600 return(0); # endif /* solaris>=20600 */ } #endif /* solaris>=20501 */ /* * Use kvm_read for Solaris < 2.5; use kvm_kread() Solaris >= 2.5. */ br = KVMREAD(Kd, (u_long)addr, buf, len); return(((READLEN_T)br == len) ? 0 : 1); } /* * open_kvm() - open kernel virtual memory access */ void open_kvm() { if (Kd) return; #if defined(WILLDROPGID) /* * If this Solaris process began with setgid permission and its been * surrendered, regain it. */ (void) restoregid(); #endif /* defined(WILLDROPGID) */ if (!(Kd = kvm_open(Nmlst, Memory, NULL, O_RDONLY, Pn))) { (void) fprintf(stderr, "%s: kvm_open(namelist=%s, corefile=%s): %s\n", Pn, Nmlst ? Nmlst : "default", Memory ? Memory : "default", strerror(errno)); Exit(1); } #if solaris>=20501 && solaris<70000 if ((Kmd = open((Memory ? Memory : KMEM), O_RDONLY)) < 0) { (void) fprintf(stderr, "%s: open(\"/dev/mem\"): %s\n", Pn, strerror(errno)); Exit(1); } #endif /* solaris>=20501 && solaris<70000 */ #if defined(WILLDROPGID) /* * If this process has setgid permission, and is willing to surrender it, * do so. */ (void) dropgid(); /* * If this Solaris process must switch GIDs, enable switching after the * first call to this function. */ if (Switchgid == 1) Switchgid = 2; #endif /* define(WILLDROPGID) */ } /* * process_text() - process text access information */ #if solaris>=90000 #include /* * 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 . */ #define READ_AVL_NODE(n,o,s) \ if (kread((KA_T)AVL_NODE2DATA(n, o), (char*) s, sizeof(*s))) \ return -1 static int get_first_seg(avl_tree_t *av, struct seg *s) { avl_node_t *node = av->avl_root; size_t off = av->avl_offset; int count = 0; while (node != NULL && ++count < MAXSEGS * 2) { READ_AVL_NODE(node, off, s); node = s->s_tree.avl_child[0]; if (node == NULL) return 0; } return -1; } static int get_next_seg(avl_tree_t *av, struct seg *s) { avl_node_t *node = &s->s_tree; size_t off = av->avl_offset; int count = 0; if (node->avl_child[1]) { /* * Has right child, go all the way to the leftmost child of * the right child. */ READ_AVL_NODE(node->avl_child[1], off, s); while (node->avl_child[0] != NULL && ++count < 2 * MAXSEGS) READ_AVL_NODE(node->avl_child[0],off,s); if (count < 2 * MAXSEGS) return 0; } else { /* * No right child, go up until we find a node we're not a right * child of. */ for (;count < 2 * MAXSEGS; count++) { int index = AVL_XCHILD(node); avl_node_t *parent = AVL_XPARENT(node); if (parent == NULL) return -1; READ_AVL_NODE(parent, off, s); if (index == 0) return 0; } } return -1; } static void process_text(pa) KA_T pa; /* address space description pointer */ { struct as as; int i, j, k; struct seg s; struct segvn_data vn; avl_tree_t *avtp; KA_T v[MAXSEGS]; /* * Get address space description. */ if (kread((KA_T)pa, (char *)&as, sizeof(as))) { alloc_lfile(" txt", -1); (void) snpf(Namech, Namechl, "can't read text segment list (%s)", print_kptr(pa, (char *)NULL, 0)); enter_nm(Namech); if (Lf->sf) link_lfile(); return; } /* * Loop through the segments. The loop should stop when the segment * pointer returns to its starting point, but just in case, it's stopped * when MAXSEGS unique segments have been recorded or 2*MAXSEGS segments * have been examined. */ for (avtp = &as.a_segtree, i = j = 0; (i < MAXSEGS) && (j < 2*MAXSEGS); j++) { if (j ? get_next_seg(avtp, &s) : get_first_seg(avtp, &s)) break; if ((KA_T)s.s_ops == Sgvops && s.s_data) { if (kread((KA_T)s.s_data, (char *)&vn, sizeof(vn))) break; if (vn.vp) { /* * This is a virtual node segment. * * If its vnode pointer has not been seen already, record the * vnode pointer and process the vnode. */ for (k = 0; k < i; k++) { if (v[k] == (KA_T)vn.vp) break; } if (k >= i) { v[i++] = (KA_T)vn.vp; alloc_lfile(" txt", -1); # if defined(FILEPTR) FILEPTR = (struct file *)NULL; # endif /* defined(FILEPTR) */ process_node((KA_T)vn.vp); if (Lf->sf) link_lfile(); } } } } } #else /* solaris<90000 */ # if solaris>=20400 #define S_NEXT s_next.list # else /* solaris<20400 */ #define S_NEXT s_next # endif /* solaris>=20400 */ static void process_text(pa) KA_T pa; /* address space description pointer */ { struct as as; int i, j, k; struct seg s; struct segvn_data vn; KA_T v[MAXSEGS]; /* * Get address space description. */ if (kread((KA_T)pa, (char *)&as, sizeof(as))) { alloc_lfile(" txt", -1); (void) snpf(Namech, Namechl, "can't read text segment list (%s)", print_kptr(pa, (char *)NULL, 0)); enter_nm(Namech); if (Lf->sf) link_lfile(); return; } /* * Loop through the segments. The loop should stop when the segment * pointer returns to its starting point, but just in case, it's stopped * when MAXSEGS unique segments have been recorded or 2*MAXSEGS segments * have been examined. */ for (s.s_next = as.a_segs, i = j = 0; i < MAXSEGS && j < 2*MAXSEGS; j++) { if (!s.S_NEXT || kread((KA_T)s.S_NEXT, (char *)&s, sizeof(s))) break; if ((KA_T)s.s_ops == Sgvops && s.s_data) { if (kread((KA_T)s.s_data, (char *)&vn, sizeof(vn))) break; if (vn.vp) { /* * This is a virtual node segment. * * If its vnode pointer has not been seen already, record the * vnode pointer and process the vnode. */ for (k = 0; k < i; k++) { if (v[k] == (KA_T)vn.vp) break; } if (k >= i) { v[i++] = (KA_T)vn.vp; alloc_lfile(" txt", -1); # if defined(FILEPTR) FILEPTR = (struct file *)NULL; # endif /* defined(FILEPTR) */ process_node((KA_T)vn.vp); if (Lf->sf) link_lfile(); } } } /* * Follow the segment link to the starting point in the address * space description. (The i and j counters place an absolute * limit on the loop.) */ # if solaris<20400 if (s.s_next == as.a_segs) # else /* solaris>=20400 */ if (s.s_next.list == as.a_segs.list) # endif /* solaris<20400 */ break; } } #endif /* solaris>=90000 */ /* * readfsinfo() - read file system information */ static void readfsinfo() { char buf[FSTYPSZ+1]; int i, len; if ((Fsinfomax = sysfs(GETNFSTYP)) == -1) { (void) fprintf(stderr, "%s: sysfs(GETNFSTYP) error: %s\n", Pn, strerror(errno)); Exit(1); } if (Fsinfomax == 0) return; if (!(Fsinfo = (char **)malloc((MALLOC_S)(Fsinfomax * sizeof(char *))))) { (void) fprintf(stderr, "%s: no space for sysfs info\n", Pn); Exit(1); } for (i = 1; i <= Fsinfomax; i++) { if (sysfs(GETFSTYP, i, buf) == -1) { (void) fprintf(stderr, "%s: sysfs(GETFSTYP) error: %s\n", Pn, strerror(errno)); Exit(1); } if (buf[0] == '\0') { Fsinfo[i-1] = ""; continue; } buf[FSTYPSZ] = '\0'; len = strlen(buf) + 1; if (!(Fsinfo[i-1] = (char *)malloc((MALLOC_S)len))) { (void) fprintf(stderr, "%s: no space for file system entry %s\n", Pn, buf); Exit(1); } (void) snpf(Fsinfo[i-1], len, "%s", buf); # if defined(HAS_AFS) if (strcasecmp(buf, "afs") == 0) AFSfstype = i; # endif /* defined(HAS_AFS) */ } } #if solaris>=20501 /* * readkam() - read kernel's address map structure */ static void readkam(addr) KA_T addr; /* kernel virtual address */ { register int i; register kvmhash_t *kp, *kpp; static KA_T kas = (KA_T)NULL; if (addr) kas = addr; Kas = (struct as *)NULL; #if solaris<70000 if (kas && !kread(kas, (char *)&Kam, sizeof(Kam))) Kas = (KA_T)&Kam; #else /* solaris>=70000 */ Kas = (struct as *)kas; #endif /* solaris<70000 */ if (Kas) { if (!KVMhb) { if (!(KVMhb = (kvmhash_t **)calloc(KVMHASHBN, sizeof(kvmhash_t *)))) { (void) fprintf(stderr, "%s: no space (%d) for KVM hash buckets\n", Pn, (int)(KVMHASHBN * sizeof(kvmhash_t *))); Exit(1); } } else if (!addr) { for (i = 0; i < KVMHASHBN; i++) { if ((kp = KVMhb[i])) { while (kp) { kpp = kp->nxt; (void) free((void *)kp); kp = kpp; } KVMhb[i] = (kvmhash_t *)NULL; } } } } } #endif /* solaris>=20501 */ /* * read_proc() - read proc structures * * As a side-effect, Kd is set by a call to kvm_open(). */ static void read_proc() { int ct, ctl, knp, n, try; MALLOC_S len; struct proc *p; KA_T pa, paf, pan; struct pid pg, pids; /* * Try PROCTRYLM times to read a valid proc table. */ for (try = 0; try < PROCTRYLM; try++) { /* * Get a proc structure count estimate. */ if (get_Nl_value("nproc", Drive_Nl, &pa) < 0 || !pa || kread(pa, (char *)&knp, sizeof(knp)) || knp < 1) knp = PROCDFLT; /* * Pre-allocate space, as required. */ n = knp + PROCDFLT/4; if (n > Npa) { /* * Allocate proc structure space. */ len = (n * sizeof(struct proc)); if (P) P = (struct proc *)realloc((MALLOC_P *)P, len); else P = (struct proc *)malloc(len); if (!P) { (void) fprintf(stderr, "%s: no proc table space\n", Pn); Exit(1); } /* * Pre-allocate PGID and PID number space. */ len = (MALLOC_S)(n * sizeof(int)); if (Fpgid) { if (Pgid) Pgid = (int *)realloc((MALLOC_P *)Pgid, len); else Pgid = (int *)malloc(len); if (!Pgid) { (void) fprintf(stderr, "%s: no PGID table space\n", Pn); Exit(1); } } if (Pid) Pid = (int *)realloc((MALLOC_P *)Pid, len); else Pid = (int *)malloc(len); if (!Pid) { (void) fprintf(stderr, "%s: no PID table space\n", Pn); Exit(1); } Npa = n; } if (HasALLKMEM) { /* * Prepare for a proc table scan via direct reading of the active * chain. */ if (!PrAct || kread(PrAct, (char *)&paf, sizeof(pa))) { (void) fprintf(stderr, "%s: can't read practive from %s\n", Pn, print_kptr(PrAct, (char *)NULL, 0)); Exit(1); } ct = 1; ctl = knp << 3; pan = paf; pa = (KA_T)NULL; } else { /* * Prepare for a proc table scan via the kvm_*proc() functions. */ if (kvm_setproc(Kd) != 0) { (void) fprintf(stderr, "%s: kvm_setproc: %s\n", Pn, strerror(errno)); Exit(1); } } /* * Accumulate proc structures. */ Np = 0; for (;;) { if (Np >= Npa) { /* * Expand the local proc table. */ Npa += PROCDFLT/2; len = (MALLOC_S)(Npa * sizeof(struct proc)); if (!(P = (struct proc *)realloc((MALLOC_P *)P, len))) { (void) fprintf(stderr, "%s: no more (%d) proc space\n", Pn, Npa); Exit(1); } /* * Expand the PGID and PID tables. */ len = (MALLOC_S)(Npa * sizeof(int)); if (Fpgid) { if (!(Pgid = (int *)realloc((MALLOC_P *)Pgid, len))) { (void) fprintf(stderr, "%s: no more (%d) PGID space\n", Pn, Npa); Exit(1); } } if (!(Pid = (int *)realloc((MALLOC_P *)Pid, len))) { (void) fprintf(stderr, "%s: no more (%d) PID space\n", Pn, Npa); Exit(1); } } /* * Read the next proc structure. */ if (HasALLKMEM) { /* * If the ALLKMEM device exists, read proc structures directly * from the active chain. */ if (!pa) pa = paf; else { pa = pan; if ((pan == paf) || (++ct > ctl)) break; } if (!pa) break; p = (struct proc *)&P[Np]; if (kread(pa, (char *)p, sizeof(struct proc))) break; pan = (KA_T)p->p_next; } else { /* * If the ALLKMEM device doesn't exist, read proc structures * via kbm_getproc(). */ if (!(p = kvm_nextproc(Kd))) break; } /* * Check process status. */ if (p->p_stat == 0 || p->p_stat == SZOMB) continue; #if solaris >=20500 /* * Check Solaris 2.5 and above p_cred pointer. */ if (!p->p_cred) continue; #endif /* solaris >=20500 */ /* * Read Solaris PGID and PID numbers. */ if (Fpgid) { if (!p->p_pgidp || kread((KA_T)p->p_pgidp, (char *)&pg, sizeof(pg))) continue; } if (!p->p_pidp || kread((KA_T)p->p_pidp, (char *)&pids, sizeof(pids))) continue; /* * Save the PGID and PID numbers in local tables. */ if (Fpgid) Pgid[Np] = (int)pg.pid_id; Pid[Np] = (int)pids.pid_id; /* * If the proc structure came from kvm_getproc(), save it in the * local table. */ if (!HasALLKMEM) P[Np] = *p; Np++; } /* * If not enough processes were saved in the local table, try again. * * If the ALLKMEM device isn't available, it is necessary to close and * reopen the KVM device, so that kvm_open() will acquire a fresh * address for the head of the linked list process table. */ if (Np >= PROCMIN) break; if (!HasALLKMEM) { close_kvm(); open_kvm(); } } /* * Quit if no proc structures were stored in the local table. */ if (try >= PROCTRYLM) { (void) fprintf(stderr, "%s: can't read proc table\n", Pn); Exit(1); } if (Np < Npa && !RptTm) { /* * Reduce the local proc structure table size to its minimum if * not in repeat mode. */ len = (MALLOC_S)(Np * sizeof(struct proc)); if (!(P = (struct proc *)realloc((MALLOC_P *)P, len))) { (void) fprintf(stderr, "%s: can't reduce proc table to %d\n", Pn, Np); Exit(1); } /* * Reduce the Solaris PGID and PID tables to their minimum if * not in repeat mode. */ len = (MALLOC_S)(Np * sizeof(int)); if (Fpgid) { if (!(Pgid = (int *)realloc((MALLOC_P *)Pgid, len))) { (void) fprintf(stderr, "%s: can't reduce PGID table to %d\n", Pn, Np); Exit(1); } } if (!(Pid = (int *)realloc((MALLOC_P *)Pid, len))) { (void) fprintf(stderr, "%s: can't reduce PID table to %d\n", Pn, Np); Exit(1); } Npa = Np; } } #if defined(WILLDROPGID) /* * restoregid() -- restore setgid permission, as required */ void restoregid() { if (Switchgid == 2 && !Setgid) { if (setgid(Savedgid) != 0) { (void) fprintf(stderr, "%s: can't set effective GID to %d: %s\n", Pn, (int)Savedgid, strerror(errno)); Exit(1); } Setgid = 1; } } #endif /* defined(WILLDROPGID) */ #if defined(HASNCACHE) && solaris>=90000 /* * Local static values */ static int Mhl; /* local name cache hash mask */ static int Nhl = 0; /* size of local name cache hash * pointer table */ struct l_nch { KA_T vp; /* vnode address */ KA_T dp; /* parent vnode address */ struct l_nch *pa; /* parent Ncache address */ char *nm; /* name */ int nl; /* name length */ }; static struct l_nch *Ncache = (struct l_nch *)NULL; /* the local name cache */ static struct l_nch **Nchash = (struct l_nch **)NULL; /* Ncache hash pointers */ static int Ncfirst = 1; /* first-call status */ static KA_T NegVN = (KA_T)NULL; /* negative vnode address */ static int Nla = 0; /* entries allocated to Ncache[] */ static int Nlu = 0; /* entries used in Ncache[] */ _PROTOTYPE(static struct l_nch *ncache_addr,(KA_T v)); #define ncachehash(v) Nchash+((((int)(v)>>2)*31415)&Mhl) _PROTOTYPE(static int ncache_isroot,(KA_T va, char *cp)); #define LNCHINCRSZ 64 /* local size increment */ #define XNC 15 /* extra name characters to read beyond those * in name[] of the ncache_t structure -- this * is an efficiency hint and MUST BE AT LEAST * ONE. */ /* * ncache_addr() - look up a node's local ncache address */ static struct l_nch * ncache_addr(v) KA_T v; /* vnode's address */ { struct l_nch **hp; for (hp = ncachehash(v); *hp; hp++) { if ((*hp)->vp == v) return(*hp); } return((struct l_nch *)NULL); } /* * ncache_isroot() - is head of name cache path a file system root? */ static int ncache_isroot(va, cp) KA_T va; /* kernel vnode address */ char *cp; /* partial path */ { char buf[MAXPATHLEN]; int i; MALLOC_S len; struct mounts *mtp; struct stat sb; struct vnode v; static int vca = 0; static int vcn = 0; static KA_T *vc = (KA_T *)NULL; if (!va) return(0); /* * Search the root vnode cache. */ for (i = 0; i < vcn; i++) { if (va == vc[i]) return(1); } /* * Read the vnode and see if it's a VDIR node with the VROOT flag set. If * it is, then the path is complete. * * If it isn't, and if the file has an inode number, search the mount table * and see if the file system's inode number is known. If it is, form the * possible full path, safely stat() it, and see if it's inode number matches * the one we have for this file. If it does, then the path is complete. */ if (kread((KA_T)va, (char *)&v, sizeof(v)) || v.v_type != VDIR || !(v.v_flag & VROOT)) { /* * The vnode tests failed. Try the inode tests. */ if (Lf->inp_ty != 1 || !Lf->inode || !Lf->fsdir || (len = strlen(Lf->fsdir)) < 1) return(0); if ((len + 1 + strlen(cp) + 1) > sizeof(buf)) return(0); for (mtp = readmnt(); mtp; mtp = mtp->next) { if (!mtp->dir || !mtp->inode) continue; if (strcmp(Lf->fsdir, mtp->dir) == 0) break; } if (!mtp) return(0); (void) strcpy(buf, Lf->fsdir); if (buf[len - 1] != '/') buf[len++] = '/'; (void) strcpy(&buf[len], cp); if (statsafely(buf, &sb) != 0 || (INODETYPE)sb.st_ino != Lf->inode) return(0); } /* * Add the vnode address to the root vnode cache. */ if (vcn >= vca) { vca += 10; len = (MALLOC_S)(vca * sizeof(KA_T)); if (!vc) vc = (KA_T *)malloc(len); else vc = (KA_T *)realloc(vc, len); if (!vc) { (void) fprintf(stderr, "%s: no space for root vnode table\n", Pn); Exit(1); } } vc[vcn++] = va; return(1); } /* * ncache_load() - load the kernel's name cache */ void ncache_load() { char *cp; struct l_nch **hp, *lc; int h, i, len, n, xl; static int iNch = 0; nc_hash_t *kh; static KA_T kha = (KA_T)NULL; static nc_hash_t *khl = (nc_hash_t *)NULL; KA_T kn; static ncache_t *nc = (ncache_t *)NULL; static int Nch = 0; static int nmo = 0; KA_T v; static int xn = 0; if (!Fncache) return; if (Ncfirst) { /* * Do startup (first-time) functions. */ Ncfirst = 0; /* * Establish DNLC hash size. */ v = (KA_T)0; if (get_Nl_value(X_NCSIZE, (struct drive_Nl *)NULL, &v) < 0 || !v || kread((KA_T)v, (char *)&Nch, sizeof(Nch))) { if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: can't read DNLC hash size: %s\n", Pn, print_kptr(v, (char *)NULL, 0)); iNch = Nch = 0; return; } if ((iNch = Nch) < 1) { if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: DNLC hash size: %d\n", Pn, Nch); iNch = Nch = 0; return; } /* * Get negative vnode address. */ if (get_Nl_value(NCACHE_NEGVN, (struct drive_Nl *)NULL, &NegVN) < 0) NegVN = (KA_T)NULL; /* * Establish DNLC hash address. */ v = (KA_T)0; if (get_Nl_value(X_NCACHE,(struct drive_Nl *)NULL,(KA_T *)&v) < 0 || !v || kread(v, (char *)&kha, sizeof(kha)) || !kha ) { if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: no DNLC hash address\n", Pn); iNch = Nch = 0; return; } /* * Allocate space for a local copy of the kernel's hash table. */ len = Nch * sizeof(nc_hash_t); if (!(khl = (nc_hash_t *)malloc((MALLOC_S)len))) { (void) fprintf(stderr, "%s: can't allocate DNLC hash space: %d\n", Pn, len); Exit(1); } /* * Allocate space for a kernel DNLC entry, plus additional name space * for efficiency. */ xn = XNC; if (!(nc = (ncache_t *)malloc((MALLOC_S)(sizeof(ncache_t) + XNC)))) { (void) fprintf(stderr, "%s: can't allocate DNLC ncache_t space\n", Pn); Exit(1); } nmo = offsetof(struct ncache, name); /* * Allocate estimated space for the local cache, based on the * hash table count and the current average hash length. */ v = (KA_T)0; if ((get_Nl_value("hshav", (struct drive_Nl *)NULL, (KA_T *)&v) < 0) || !v || kread(v, (char *)&i, sizeof(i)) || (i < 1) ) { i = 16; if (!Fwarn) { (void) fprintf(stderr, "%s: can't read DNLC average hash bucket size,", Pn); (void) fprintf(stderr, " using %d\n", i); } } Nla = Nch * i; if (!(Ncache = (struct l_nch *)calloc(Nla, sizeof(struct l_nch)))) { no_local_space: (void) fprintf(stderr, "%s: no space for %d byte local name cache\n", Pn, len); Exit(1); } } else { /* * Do setup for repeat calls. */ if (!iNch || !Nla || !Ncache) return; if (Nchash) { (void) free((FREE_P *)Nchash); Nchash = (struct l_nch **)NULL; } if (Ncache && Nlu) { /* * Free space malloc'd to names in local name cache. */ for (i = 0, lc = Ncache; i < Nlu; i++, lc++) { if (lc->nm) { (void) free((FREE_P *)lc->nm); lc->nm = (char *)NULL; } } } Nch = iNch; Nlu = 0; } /* * Read the kernel's DNLC hash. */ if (kread(kha, (char *)khl, (Nch * sizeof(nc_hash_t)))) { if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: can't read DNLC hash: %s\n", Pn, print_kptr(kha, (char *)NULL, 0)); iNch = Nch = 0; return; } /* * Build a local copy of the kernel name cache. */ for (i = n = 0, kh = khl, lc = Ncache; i < Nch; i++, kh++) { /* * Skip empty hash buckets. */ if (!kh->hash_next || ((KA_T)kh->hash_next == kha)) continue; /* * Process a hash bucket. */ for (kn = (KA_T)kh->hash_next, h = 0; kn && (h < Nch) && (!h || (h && kn != (KA_T)kh->hash_next)); kn = (KA_T)nc->hash_next, h++) { if (kread(kn, (char *)nc, sizeof(ncache_t) + XNC)) break; if (!nc->vp || (len = (int)nc->namlen) < 1) continue; if (NegVN && ((KA_T)nc->vp == NegVN)) continue; if ((len < 3) && (nc->name[0] == '.')) { if ((len < 2) || (nc->name[1] == '.')) continue; } /* * If not all the name has been read, read the rest of it, * allocating more space at the end of the ncache structure as * required. */ if (len > (XNC + 1)) { if (len > (xn + 1)) { while (len > (xn + 1)) xn = xn + xn; xn = ((xn + 7) & ~7) - 1; if (!(nc = (ncache_t *)realloc((MALLOC_P *)nc, (sizeof(ncache_t) + xn))) ) { (void) fprintf(stderr, "%s: can't extend DNLC ncache_t buffer\n", Pn); Exit(1); } } cp = &nc->name[XNC + 1]; v = (KA_T)((char *)kn + nmo + XNC + 1); xl = len - XNC - 1; if (kread(v, cp, xl)) continue; } /* * Allocate space for the name in the local name cache entry. */ if (!(cp = (char *)malloc(len + 1))) { (void) fprintf(stderr, "%s: can't allocate %d bytes for name cache name\n", Pn, len + 1); Exit(1); } (void) strncpy(cp, nc->name, len); cp[len] = '\0'; /* * Make sure there is space for another local name cache entry. * If not, allocate twice as many entries. */ if (n >= Nla) { Nla = Nla + Nla; if (!(Ncache = (struct l_nch *)realloc(Ncache, (MALLOC_S)(Nla * sizeof(struct l_nch)))) ) { (void) fprintf(stderr, "%s: can't enlarge local name cache\n", Pn); Exit(1); } lc = &Ncache[n]; } /* * Complete the local cache entry. */ lc->vp = (KA_T)nc->vp; lc->dp = (KA_T)nc->dp; lc->pa = (struct l_nch *)NULL; lc->nm = cp; lc->nl = len; lc++; n++; } } /* * Reduce memory usage, as required. */ if ((Nlu = n) < 1) { /* * No DNLC entries were located, an unexpected result. */ if (!RptTm && Ncache) { /* * If not in repeat mode, free the space that has been malloc'd * to the local name cache. */ (void) free((FREE_P *)Ncache); Ncache = (struct l_nch *)NULL; Nla = Nlu = 0; } /* * Issue a warning and disable furthe DNLC processing. */ if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: unusable local name cache size: %d\n", Pn, n); iNch = Nch = 0; return; } if ((Nlu < Nla) && !RptTm) { len = Nlu * sizeof(struct l_nch); if (!(Ncache = (struct l_nch *)realloc(Ncache, len))) goto no_local_space; Nla = Nlu; } /* * Build a hash table to locate Ncache entries. */ for (Nhl = 1; Nhl < Nlu; Nhl <<= 1) ; Nhl <<= 1; Mhl = Nhl - 1; if (!(Nchash = (struct l_nch **)calloc(Nhl + Nlu, sizeof(struct l_nch *)))) { (void) fprintf(stderr, "%s: no space for %d name cache hash pointers\n", Pn, Nhl + Nlu); Exit(1); } for (i = 0, lc = Ncache; i < Nlu; i++, lc++) { for (hp = ncachehash(lc->vp), h = 1; *hp; hp++) { if ((*hp)->vp == lc->vp && strcmp((*hp)->nm, lc->nm) == 0 && (*hp)->dp == lc->dp ) { h = 0; break; } } if (h) *hp = lc; } /* * Make a final pass through the local cache and convert parent vnode * addresses to local name cache pointers. */ for (i = 0, lc = Ncache; i < Nlu; i++, lc++) { if (!lc->dp) continue; if (NegVN && (lc->dp == NegVN)) { lc->pa = (struct l_nch *)NULL; continue; } lc->pa = ncache_addr(lc->dp); } } /* * ncache_lookup() - look up a node's name in the kernel's name cache */ char * ncache_lookup(buf, blen, fp) char *buf; /* receiving name buffer */ int blen; /* receiving buffer length */ int *fp; /* full path reply */ { char *cp = buf; struct l_nch *lc; struct mounts *mtp; int nl, rlen; *cp = '\0'; *fp = 0; # if defined(HASFSINO) /* * If the entry has an inode number that matches the inode number of the * file system mount point, return an empty path reply. That tells the * caller to print the file system mount point name only. */ if (Lf->inp_ty == 1 && Lf->fs_ino && Lf->inode == Lf->fs_ino) return(cp); # endif /* defined(HASFSINO) */ /* * Look up the name cache entry for the node address. */ if (!Nlu || !(lc = ncache_addr(Lf->na))) { /* * If the node has no cache entry, see if it's the mount * point of a known file system. */ if (!Lf->fsdir || !Lf->dev_def || Lf->inp_ty != 1) return((char *)NULL); for (mtp = readmnt(); mtp; mtp = mtp->next) { if (!mtp->dir || !mtp->inode) continue; if (Lf->dev == mtp->dev && mtp->inode == Lf->inode && strcmp(mtp->dir, Lf->fsdir) == 0) return(cp); } return((char *)NULL); } /* * Begin the path assembly. */ if ((nl = lc->nl) > (blen - 1)) return((char *)NULL); cp = buf + blen - nl - 1; rlen = blen - nl - 1; (void) strcpy(cp, lc->nm); /* * Look up the name cache entries that are parents of the node address. * Quit when: * * there's no parent; * the name is too large to fit in the receiving buffer. */ for (;;) { if (!lc->pa) { if (ncache_isroot(lc->dp, cp)) *fp = 1; break; } lc = lc->pa; if (((nl = lc->nl) + 1) > rlen) break; *(cp - 1) = '/'; cp--; rlen--; (void) strncpy((cp - nl), lc->nm, nl); cp -= nl; rlen -= nl; } return(cp); } #endif /* defined(HASNCACHE) && solaris>=90000 */ lsof-4.86+dfsg.orig/dialects/sun/dproto.h0000444000175000017500000000706511530274370020543 0ustar nicholasnicholas/* * dproto.h - Solaris function prototypes for lsof * * The _PROTOTYPE macro is defined in the common proto.h. */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: dproto.h,v 1.21 2010/01/18 19:03:54 abe Exp $ */ #if defined(HASVXFSUTIL) _PROTOTYPE(extern int access_vxfs_ioffsets,(void)); #endif /* defined(HASVXFSUTIL) */ _PROTOTYPE(extern void completevfs,(struct l_vfs *vfs, dev_t *dev)); # if defined(HAS_LIBCTF) _PROTOTYPE(extern int CTF_getmem,(ctf_file_t *f, const char *mod, const char *ty, CTF_member_t *mem)); _PROTOTYPE(extern void CTF_init,(int *i, char *t, CTF_request_t *r)); _PROTOTYPE(extern int CTF_memCB,(const char *name, ctf_id_t id, ulong_t offset, void *arg)); # endif /* defined(HAS_LIBCTF) */ _PROTOTYPE(extern int is_file_named,(char *p, int nt, enum vtype vt, int ps)); _PROTOTYPE(extern struct l_vfs *readvfs,(KA_T ka, struct vfs *la, struct vnode *lv)); _PROTOTYPE(extern int vop2ty,(struct vnode *vp, int fx)); #if defined(HAS_AFS) _PROTOTYPE(extern struct vnode *alloc_vcache,(void)); _PROTOTYPE(extern void ckAFSsym,(struct nlist *nl)); _PROTOTYPE(extern int hasAFS,(struct vnode *vp)); _PROTOTYPE(extern int readafsnode,(KA_T va, struct vnode *v, struct afsnode *an)); #endif /* defined(HAS_AFS) */ #if defined(HASDCACHE) _PROTOTYPE(extern int rw_clone_sect,(int m)); _PROTOTYPE(extern void clr_sect,(void)); _PROTOTYPE(extern int rw_pseudo_sect,(int m)); #endif /* defined(HASDCACHE) */ #if defined(HASIPv6) _PROTOTYPE(extern struct hostent *gethostbyname2,(const char *nm, int proto)); #endif /* defined(HASIPv6) */ #if defined(HAS_V_PATH) _PROTOTYPE(extern int print_v_path,(struct lfile *lf)); _PROTOTYPE(extern void read_v_path,(KA_T ka, char *rb, size_t rbl)); #endif /* defined(HAS_V_PATH) */ #if defined(HASVXFS) _PROTOTYPE(extern int read_vxnode,(KA_T va, struct vnode *v, struct l_vfs *vfs, int fx, struct l_ino *li, KA_T *vnops)); # if defined(HASVXFSRNL) _PROTOTYPE(extern int print_vxfs_rnl_path,(struct lfile *lf)); # endif /* defined(HASVXFSRNL) */ #endif /* defined(HASVXFS) */ #if defined(HASZONES) _PROTOTYPE(extern int enter_zone_arg,(char *zn)); #endif /* defined(HASZONES) */ _PROTOTYPE(extern void close_kvm,(void)); _PROTOTYPE(extern void open_kvm,(void)); _PROTOTYPE(extern void process_socket,(KA_T sa, char *ty)); #if solaris>=110000 _PROTOTYPE(extern int process_VSOCK,(KA_T va, struct vnode *v, struct sonode *so)); #endif /* solaris>=11000 */ _PROTOTYPE(extern void read_clone,(void)); #if solaris<20500 _PROTOTYPE(extern int get_max_fd,(void)); #endif /* solaris<20500 */ #if defined(WILLDROPGID) _PROTOTYPE(extern void restoregid,(void)); #endif /* defined(WILLDROPGID) */ lsof-4.86+dfsg.orig/dialects/sun/solaris_kaddr_filters0000444000175000017500000002126410025611653023351 0ustar nicholasnicholas 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 .) 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 . Additionally useful is another undocumented function, kvm_pread() (for physical read), that also is represented by a 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 lsof-4.86+dfsg.orig/dialects/sun/dlsof.h0000444000175000017500000003633511741061172020343 0ustar nicholasnicholas/* * 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 #include #include # if solaris<20600 #define _KMEMUSER 1 # else /* solaris>=20600 */ #include # endif /* solaris<20600 */ #include #include # if defined(HASZONES) #define _KERNEL #include #undef _KERNEL # endif /* defined(HASZONES) */ #include #include #include #include #include #include #include #include #include #include #include #include # if solaris>=110000 #define _KERNEL # endif /* solaris>=110000 */ #include # if solaris>=110000 #undef _KERNEL # endif /* solaris>=110000 */ # if solaris>=70000 #include #include # endif /* solaris>=70000 */ #define _KERNEL #define MI_HRTIMING #include # if solaris<20600 #undef staticf # endif /* solaris<20600 */ #include # if solaris>=70000 #include # endif /* solaris>=70000 */ # if solaris<20600 #include # endif /* solaris<20600 */ # if solaris>=80000 #include #include # endif /* solaris>=80000 */ # if defined(HAS_IPCLASSIFIER_H) #define ffs __kernel_ffs #define inet_ntop __inet_ntop #define inet_pton __inet_pton #define longjmp __kernel_longjmp #define setjmp __kernel_setjmp # if solaris>=110000 #define printf __kernel_printf #define snprintf __kernel_snprintf #define sprintf __kernel_sprintf #define strsignal __kernel_strsignal #define swab __kernel_swab #define vprintf __kernel_vprintf #define vsprintf __kernel_vsprintf #define vsnprintf __kernel_vsnprintf # endif /* solaris>=110000 */ #include #undef ffs #undef inet_ntop #undef inet_pton #undef longjmp #undef setjmp # if solaris>=110000 #undef printf #undef snprintf #undef sprintf #undef strsignal #undef swab #undef vprintf #undef vsprintf #undef vsnprintf # endif /* solaris>=110000 */ # endif /* defined(HAS_IPCLASSIFIER_H) */ #include #undef _KERNEL #undef MI_HRTIMING #define exit kernel_exit #define rval_t char #define strsignal kernel_strsignal #include # if defined(HAS_SOCKET_PROTO_H) #define _KERNEL 1 /* DEBUG */ # endif /* HAS_SOCKET_PROTO_H */ #include # 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 # if solaris>=80000 #undef _KERNEL # endif /* solaris>=80000 */ #include #include #include # if solaris<20600 #undef MAX #undef MIN # endif /* solaris<20600 */ #include #include #include #include #include #include # if solaris>=20600 #define _KERNEL # endif /* solaris>=20600 */ #include # if solaris>=20600 #undef _KERNEL # endif /* solaris>=20600 */ #include # if solaris>=20500 #include #include #include # if solaris>=110000 #define _KERNEL #include #undef _KERNEL # endif /* solaris>=110000 */ #include #include #define _KERNEL #include # 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 #undef printf #undef snprintf #undef sprintf #undef swab #undef vprintf #undef vsnprintf #undef vsprintf #include #include #include # endif /* solaris>=100000 */ #include #undef _KERNEL # endif /* solaris>=20500 */ # if !defined(_NETDB_H_) #include # endif /* !defined(_NETDB_H_) */ #include #include # 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 # endif /* solaris<20400 */ # endif /* solaris>=20300 */ #include #include #include #include #include # if defined(HASCACHEFS) #include # endif /* defined(HACACHEFS) */ #include #include #include #include #include # if solaris>=20600 #undef SLOCKED # endif /* solaris>=20600 */ #include #include # if solaris>=110000 #define _KERNEL # endif /* solaris>=110000 */ #include # if solaris>=110000 #undef _KERNEL # endif /* solaris>=110000 */ # if solaris>=100000 #define _KERNEL # endif /* solaris >= 100000 */ #include # if solaris>=100000 #include #include #include # endif /* solaris>=100000 */ # if solaris>=100000 #undef _KERNEL # endif /* solaris >= 100000 */ #include #include # if defined(HASPROCFS) #include # endif /* defined(HASPROCFS) */ #include #include #include #include #include #include #include #include #include # if solaris<100000 #include # 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 #define CTF_MEMBER_UNDEF ~0UL /* undefined member type */ /* CTF_member_t element definition */ /* * Member structure definition, initialized by CTF_MEMBER() macro calls */ typedef struct CTF_member { char *m_name; /* Member name. */ ulong_t m_offset; /* Member offset, initially in bits, * later bytes */ } CTF_member_t; /* * CTF request structure */ typedef struct CTF_request { char *name; /* structure name */ CTF_member_t *mem; /* member table */ } CTF_request_t; /* * CTF macroes */ #define CTF_MEMBER(name) { #name, CTF_MEMBER_UNDEF } #define CTF_MEMBER_READ(ka, s, members, member) \ kread((KA_T)(ka) + members[MX_ ## member].m_offset, \ (char *)&s->member, sizeof(s->member)) # endif /* defined(HAS_LIBCTF) */ extern char **Fsinfo; extern int Fsinfomax; extern int HasALLKMEM; extern int HaveCloneMaj; extern kvm_t *Kd; struct l_ino { unsigned char dev_def; /* dev member is defined */ unsigned char ino_def; /* ino member is defined */ unsigned char nl_def; /* nl member is defined */ unsigned char rdev_def; /* rdev member is defined */ unsigned char sz_def; /* sz member is defined */ dev_t dev; /* device */ long ino; /* node number */ long nl; /* link count */ dev_t rdev; /* "raw" device */ SZOFFTYPE sz; /* size */ }; struct l_vfs { KA_T addr; /* kernel address */ char *dir; /* mounted directory */ char *fsname; /* file system name */ dev_t dev; /* device */ # if defined(HASFSINO) INODETYPE fs_ino; /* file system inode number */ # endif /* defined(HASFSINO) */ # if defined(HASMNTSTAT) unsigned char mnt_stat; /* mount point stat() status: * 0 = succeeded * 1 = failed */ # endif /* defined(HASMNTSTAT) */ # if solaris>=80000 nlink_t nlink; /* directory link count */ off_t size; /* directory size */ # endif /* solaris>=80000 */ struct l_vfs *next; /* forward link */ }; extern struct l_vfs *Lvfs; struct mounts { char *dir; /* directory (mounted on) */ char *fsname; /* file system * (symbolic links unresolved) */ char *fsnmres; /* file system * (symbolic links resolved) */ dev_t dev; /* directory st_dev */ dev_t rdev; /* directory st_rdev */ INODETYPE inode; /* directory st_ino */ mode_t mode; /* directory st_mode */ mode_t fs_mode; /* file system st_mode */ struct mounts *next; /* forward link */ # if defined(HASFSTYPE) char *fstype; /* file system type */ # endif /* defined(HASFSTYPE) */ # if solaris>=80000 nlink_t nlink; /* directory st_nlink */ off_t size; /* directory st_size */ # endif /* solaris>=80000 */ # if defined(HASMNTSTAT) unsigned char stat; /* mount point stat() status: * 0 = succeeded * 1 = failed */ # endif /* defined(HASMNTSTAT) */ }; struct pseudo { struct l_dev pd; /* device, inode, path, verify */ struct pseudo *next; /* forward link */ }; extern struct pseudo *Pseudo; /* * Solaris 11 sdev definitions */ #define SDVOP_IP 0 /* Sdev[] devipnet_vnodeops index */ #define SDVOP_NET 1 /* Sdev[] devnet_vnodeops index */ #define SDVOP_PTS 2 /* Sdev[] devpts_vnodeops index */ #define SDVOP_VT 3 /* Sdev[] devvt_vnodeops index */ #define SDVOP_NUM 4 /* number of Sdev[] entries */ struct sfile { char *aname; /* file name argument */ char *name; /* file name (after readlink()) */ char *devnm; /* device name (optional) */ dev_t dev; /* device */ dev_t rdev; /* raw device */ u_short mode; /* S_IFMT mode bits from stat() */ int type; /* file type: 0 = file system * 1 = regular file */ INODETYPE i; /* inode number */ int f; /* file found flag */ struct sfile *next; /* forward link */ }; extern int Unof; /* u_nofiles value */ /* * VxFS definitions */ #define VXVOP_FCL 0 /* Vvops[] vx_fcl_vnodeops_p index */ #define VXVOP_FDD 1 /* Vvops[] fdd_vnops index */ #define VXVOP_FDDCH 2 /* Vvops[] fdd_chain_vnops index */ #define VXVOP_REG 3 /* Vvops[] vx_vnodeops index */ #define VXVOP_REG_P 4 /* Vvops[] vx_vnodeops_p index */ #define VXVOP_NUM 5 /* number of Vvops[] entries */ /* * Kernel name list definitions */ #define NL_NAME n_name #define X_NCACHE "ncache" #define X_NCSIZE "ncsize" /* * Definitions for dvch.c */ # if defined(HASDCACHE) #define DCACHE_CLONE rw_clone_sect /* clone function for read_dcache */ #define DCACHE_CLR clr_sect /* function to clear clone and * pseudo caches when reading the * device cache file fails */ #define DCACHE_PSEUDO rw_pseudo_sect /* pseudo function for read_dcache */ # endif /* defined(HASDCACHE) */ #define DVCH_DEVPATH "/devices" /* * Definition for cvfs.c */ #define CVFS_DEVSAVE 1 # if solaris>=80000 #define CVFS_NLKSAVE 1 #define CVFS_SZSAVE 1 # endif /* solaris>=80000 */ /* * Definitions for rnch.c */ # if defined(HASNCACHE) #include # if !defined(NC_NAMLEN) #define HASDNLCPTR 1 # endif /* !defined(NC_NAMLEN) */ # if solaris>=80000 #define NCACHE_NEGVN "negative_cache_vnode" # endif /* solaris>=80000 */ # endif /* defined(HASNCACHE) */ #endif /* SOLARIS_LSOF_H */ lsof-4.86+dfsg.orig/dialects/sun/dnode1.c0000444000175000017500000002417710275734316020412 0ustar nicholasnicholas/* * dnode1.h - Solaris AFS support */ /* * Copyright 1996 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1996 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dnode1.c,v 1.9 2005/08/08 19:55:41 abe Exp $"; #endif #if defined(HAS_AFS) #include "lsof.h" #include #define __XDR_INCLUDE__ #define int32 old_solaris_int32 # if solaris>=20600 #undef SHARED #undef PRIVATE # endif /* solaris>=20600 */ #include #include #include /* * 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 #undef KERNEL /* * Local function prototypes */ _PROTOTYPE(static struct volume *getvolume,(struct VenusFid *f, int *vols)); _PROTOTYPE(static int is_rootFid,(struct vcache *vc, int *rfid)); /* * alloc_vcache() - allocate space for vcache structure */ struct vnode * alloc_vcache() { return((struct vnode *)malloc(sizeof(struct vcache))); } /* * ckAFSsym() - check for missing X_AFS_* symbols in AFS name list file */ void ckAFSsym(nl) struct nlist *nl; /* copy of Nl[] when empty */ { char *path = AFSAPATHDEF; int i; KA_T v; # if defined(HASAOPT) if (AFSApath) path = AFSApath; # endif /* defined(HASAOPT) */ /* * If an alternate AFS name list file was specified, see if it can be read. */ if (!is_readable(path, 0)) { if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: can't access AFS name list file: %s\n", Pn, path); return; } /* * Read the AFS modload symbols and compare its non-zero values with * the non-zero values in Nl[]. Quit if there is any mis-match. */ if (nlist(path, nl) < 0) return; for (i = 0; Nl[i].n_name && Nl[i].n_name[0]; i++) { if (!nl[i].n_value || !Nl[i].n_value) continue; if (nl[i].n_value != Nl[i].n_value) return; } /* * If any AFS symbol that doesn't have a value in Nl[] has one from * the AFS modload file, copy its modload value to Nl[]. */ if ((i = get_Nl_value("arFid", Drive_Nl, &v)) >= 0 && !Nl[i].n_value && nl[i].n_value) Nl[i].n_value = nl[i].n_value; if ((i = get_Nl_value("avops", Drive_Nl, &v)) >= 0 && !Nl[i].n_value && nl[i].n_value) Nl[i].n_value = nl[i].n_value; if ((i = get_Nl_value("avol", Drive_Nl, &v)) >= 0 && !Nl[i].n_value && nl[i].n_value) Nl[i].n_value = nl[i].n_value; } /* * getvolume() - get volume structure */ static struct volume * getvolume(f, vols) struct VenusFid *f; /* file ID pointer */ int *vols; /* afs_volumes status return */ { int i; static KA_T ka = 0; KA_T kh; static struct volume v; KA_T vp; static int w = 0; if (!ka) { if (get_Nl_value("avol", Drive_Nl, &ka) < 0 || !ka) { if (!w && !Fwarn) { (void) fprintf(stderr, "%s: WARNING: no kernel address for afs_volumes\n", Pn); (void) fprintf(stderr, " This may hamper AFS node number reporting.\n"); w = 1; } *vols = 0; return((struct volume *)NULL); } } *vols = 1; i = (NVOLS - 1) & f->Fid.Volume; kh = (KA_T)((char *)ka + (i * sizeof(struct volume *))); if (kread(kh, (char *)&vp, sizeof(vp))) return((struct volume *)NULL); while (vp) { if (kread((KA_T)vp, (char *)&v, sizeof(v))) return((struct volume *)NULL); if (v.volume == f->Fid.Volume && v.cell == f->Cell) return(&v); vp = (KA_T)v.next; } return((struct volume *)NULL); } /* * hasAFS() - test for AFS presence via vfs structure */ int hasAFS(vp) struct vnode *vp; /* vnode pointer */ { struct mounts *mp; int n; struct vfs v; /* * If this vnode has a v_data pointer, then it probably isn't an AFS vnode; * return FALSE. * * If the vfs struct address of /afs is known and this vnode's v_vfsp matches * it, return TRUE. * * Read this vnode's vfs structure and see if it's device (fsid.val[0]) is * AFSdev. If it is, record the AFS vfs struct address and return TRUE. */ if (AFSVfsp && !vp->v_data && (KA_T)vp->v_vfsp == AFSVfsp) return(1); if (!AFSdevStat) (void) readmnt(); if (!AFSdevStat || vp->v_data || !vp->v_vfsp || kread((KA_T)vp->v_vfsp, (char *)&v, sizeof(v)) || v.vfs_data) return(0); if ((dev_t)v.vfs_fsid.val[0] == AFSdev) { AFSVfsp = (KA_T)vp->v_vfsp; return(1); } /* * Search the local mount table for /afs devices. Count /afs devices, * and skip a device number test for them. A match on device number for * non-AFS devices produces a FALSE return. */ for (mp = readmnt(), n = 0; mp; mp = mp->next) { if (AFSdevStat && mp->dev == AFSdev && mp->dir && strcmp(mp->dir, "/afs") == 0 && mp->fsname && strcmp(mp->fsname, "AFS") == 0) n++; else if (mp->dev == (dev_t)v.vfs_fsid.val[0]) return(0); } /* * If there is exactly one /afs device, assume its vfs struct address is * the one for this vnode, record it, and return TRUE. */ if (n == 1) { AFSVfsp = (KA_T)vp->v_vfsp; return(1); } return(0); } /* * is_rootFid() - is the file ID the root file ID * * return: 0 = is not root file ID * 1 = is root file ID * rfid = 0 if root file ID structure address not available * 1 if root file ID structure address available */ static int is_rootFid(vc, rfid) struct vcache *vc; /* vcache structure */ int *rfid; /* root file ID pointer status return */ { KA_T arFid; char *err; static int f = 0; /* rootFid structure status: * -1 = unavailable * 0 = not yet accessed * 1 = available */ static struct VenusFid r; static int w = 0; switch (f) { case -1: if (vc->v.v_flag & VROOT) { *rfid = 1; return(1); } *rfid = 0; return(0); case 0: if (get_Nl_value("arFid", Drive_Nl, &arFid) < 0 || !arFid) { err = "no afs_rootFid kernel address"; rfid_unavailable: if (!w && !Fwarn) { (void) fprintf(stderr, "%s: WARNING: AFS root Fid error: %s\n", Pn, err); (void) fprintf(stderr, " This may hamper AFS node number reporting.\n"); w = 1; } f = -1; if (vc->v.v_flag & VROOT) { *rfid = 1; return(1); } *rfid = 0; return(0); } if (kread(arFid, (char *)&r, sizeof(r))) { err = "can't read afs_rootFid from kernel"; goto rfid_unavailable; } f = 1; /* fall through */ case 1: *rfid = 1; if (vc->fid.Fid.Unique == r.Fid.Unique && vc->fid.Fid.Vnode == r.Fid.Vnode && vc->fid.Fid.Volume == r.Fid.Volume && vc->fid.Cell == r.Cell) return(1); } *rfid = 0; return(0); } /* * readafsnode() - read AFS node */ int readafsnode(va, v, an) KA_T va; /* kernel vnode address */ struct vnode *v; /* vnode buffer pointer */ struct afsnode *an; /* afsnode recipient */ { char *cp, tbuf[32]; KA_T ka; int len, rfid, vols; struct vcache *vc; struct volume *vp; cp = ((char *)v + sizeof(struct vnode)); ka = (KA_T)((char *)va + sizeof(struct vnode)); len = sizeof(struct vcache) - sizeof(struct vnode); if (kread(ka, cp, len)) { (void) snpf(Namech, Namechl, "vnode at %s: can't read vcache remainder from %s", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr(ka, (char *)NULL, 0)); enter_nm(Namech); return(1); } vc = (struct vcache *)v; if (!AFSdevStat) (void) readmnt(); an->dev = AFSdevStat ? AFSdev: 0; an->size = (unsigned long)vc->m.Length; an->nlink = (long)vc->m.LinkCount; an->nlink_st = 1; /* * Manufacture the "inode" number. */ if (vc->mvstat == 2) { if ((vp = getvolume(&vc->fid, &vols))) { an->inode = (INODETYPE)((vp->mtpoint.Fid.Vnode + (vp->mtpoint.Fid.Volume << 16)) & 0x7fffffff); if (an->inode == (INODETYPE)0) { if (is_rootFid(vc, &rfid)) an->ino_st = 1; else if (rfid) { an->inode = (INODETYPE)2; an->ino_st = 1; } else an->ino_st = 0; } else an->ino_st = 1; } else { if (vols) { an->inode = (INODETYPE)2; an->ino_st = 1; } else { if (v->v_flag & VROOT) { an->inode = (INODETYPE)0; an->ino_st = 1; } else an->ino_st = 0; } } } else { an->inode = (INODETYPE)((vc->fid.Fid.Vnode + (vc->fid.Fid.Volume << 16)) & 0x7fffffff); an->ino_st = 1; } return(0); } #endif /* defined(HAS_AFS) */ lsof-4.86+dfsg.orig/dialects/sun/Mksrc0000555000175000017500000000244707212725644020076 0ustar nicholasnicholas#!/bin/sh # # Mksrc - make Solaris source files # # WARNING: This script assumes it is running from the main directory # of the lsof, version 4 distribution. # # One environment variable applies: # # LSOF_MKC is the method for creating the source files. # It defaults to "ln -s". A common alternative is "cp". # # $Id: Mksrc,v 1.4 2000/12/04 14:35:13 abe Exp $ D=dialects/sun L="ddev.c dfile.c dlsof.h dmnt.c dnode.c dnode1.c dnode2.c dproc.c dproto.h dsock.c dstore.c machine.h" for i in $L do rm -f $i $LSOF_MKC $D/$i $i echo "$LSOF_MKC $D/$i $i" done # Assemble kernelbase.h for SunOS and Solaris < 2.5 (5.5) NM=kernelbase.h rm -f $NM if test "X$1" != "Xsolaris" -o $2 -lt 20500 then if test "X$1" = "Xsolaris" then A=`uname -m` if test "$A" = "i86pc" then H=/usr/include/sys/machparam.h else H=/usr/src/uts/$A/sys/machparam.h fi else H=/usr/include/machine/param.h fi echo "#if !defined(KERNELSIZE)" > $NM grep "^#define[ ]*KERNELSIZE" $H >> $NM echo "#endif" >> $NM echo "#if !defined(KERNELBASE)" >> $NM grep "^#define[ ]*KERNELBASE" $H >> $NM echo "#endif" >> $NM else # To keep the dependency list for dproc.o simple in the Makefile, # create an empty kernelbase.h for Solaris 2.5 (5.5) and above. touch $NM fi echo "$NM assembled." lsof-4.86+dfsg.orig/dialects/sun/dnode.c0000444000175000017500000036322411741061174020322 0ustar nicholasnicholas/* * dnode.c - Solaris node reading functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dnode.c,v 1.59 2012/04/10 16:40:23 abe Exp $"; #endif #include "lsof.h" #if solaris>=110000 #include #endif /* solaris>=110000 */ #undef fs_bsize #include #if solaris>=110000 && defined(HAS_LIBCTF) /* * Sockfs support for Solaris 11 via libctf */ /* * Sockfs internal structure definitions * * The structure definitions may look like kernel structures, but they are * not. They have been defined to have member names that duplicate those * used by the kernel that are of interest to lsof. Member values are * obtained via the CTF library, libctf. * * Robert Byrnes developed the CTF library access code and contributed it * to lsof. */ struct soaddr { /* sadly, CTF doesn't grok this * structure */ struct sockaddr *soa_sa; /* address */ t_uscalar_t soa_len; /* length in bytes */ t_uscalar_t soa_maxlen; /* maximum length */ }; typedef struct sotpi_info { dev_t sti_dev; /* sonode device */ struct soaddr sti_laddr; /* local address */ struct soaddr sti_faddr; /* peer address */ struct so_ux_addr sti_ux_laddr; /* bound local address */ struct so_ux_addr sti_ux_faddr; /* bound peer address */ t_scalar_t sti_serv_type; /* service type */ } sotpi_info_t; /* * CTF definitions for sockfs */ static int Sockfs_ctfs = 0; /* CTF initialization status for * sockfs */ # if defined(_LP64) #define SOCKFS_MOD_FORMAT "/kernel/fs/%s/sockfs" # else /* !defined(_LP64) */ #define SOCKFS_MOD_FORMAT "/kernel/fs/sockfs" # endif /* defined(_LP64) */ /* sockfs module pathname template to * which the kernel's instruction type * set is added for CTF access */ /* * Sockfs access definitions and structures */ #define SOADDR_TYPE_NAME "soaddr" static CTF_member_t soaddr_members[] = { CTF_MEMBER(soa_sa), #define MX_soa_sa 0 CTF_MEMBER(soa_len), #define MX_soa_len 1 CTF_MEMBER(soa_maxlen), #define MX_soa_maxlen 2 { NULL, 0 } }; #define SOTPI_INFO_TYPE_NAME "sotpi_info_t" static CTF_member_t sotpi_info_members[] = { CTF_MEMBER(sti_dev), #define MX_sti_dev 0 CTF_MEMBER(sti_laddr), #define MX_sti_laddr 1 CTF_MEMBER(sti_faddr), #define MX_sti_faddr 2 CTF_MEMBER(sti_ux_laddr), #define MX_sti_ux_laddr 3 CTF_MEMBER(sti_ux_faddr), #define MX_sti_ux_faddr 4 CTF_MEMBER(sti_serv_type), #define MX_sti_serv_type 5 { NULL, 0 } }; /* * CTF sockfs request table */ static CTF_request_t Sockfs_requests[] = { { SOTPI_INFO_TYPE_NAME, sotpi_info_members }, { NULL, NULL } }; /* * Sockfs function prototypes */ _PROTOTYPE(static int read_nsti,(struct sonode *so, sotpi_info_t *stpi)); #endif /* solaris>=110000 && defined(HAS_LIBCTF) */ #if defined(HAS_ZFS) && defined(HAS_LIBCTF) /* * ZFS support via libctf */ /* * ZFS internal structure definitions * * The structure definitions may look like kernel structures, but they are * not. They have been defined to have member names that duplicate those * used by the kernel that are of interest to lsof. Member values are * obtained via the CTF library, libctf. * * Robert Byrnes developed the CTF library access code and contributed it * to lsof. */ typedef struct zfsvfs { vfs_t *z_vfs; /* pointer to VFS */ } zfsvfs_t; typedef struct znode_phys { uint64_t zp_size; /* file size (ZFS below 5) */ uint64_t zp_links; /* links (ZFS below 5) */ } znode_phys_t; typedef struct znode { zfsvfs_t *z_zfsvfs; /* pointer to associated vfs */ vnode_t *z_vnode; /* pointer to associated vnode */ uint64_t z_id; /* node ID */ znode_phys_t *z_phys; /* pointer to persistent znode (ZFS * below 5) */ uint64_t z_links; /* links (ZFS 5 and above) */ uint64_t z_size; /* file size (ZFS 5 and above) */ } znode_t; /* * CTF definitions for ZFS */ static int ZFS_ctfs = 0; /* CTF initialization status for ZFS */ # if defined(_LP64) #define ZFS_MOD_FORMAT "/kernel/fs/%s/zfs" # else /* !defined(_LP64) */ #define ZFS_MOD_FORMAT "/kernel/fs/zfs" # endif /* defined(_LP64) */ /* ZFS module pathname template to * which the kernel's instruction type * set is added for CTF access */ /* * ZFS access definitions and structures */ #define ZNODE_TYPE_NAME "znode_t" static CTF_member_t znode_members[] = { CTF_MEMBER(z_zfsvfs), #define MX_z_zfsvfs 0 CTF_MEMBER(z_vnode), #define MX_z_vnode 1 CTF_MEMBER(z_id), #define MX_z_id 2 CTF_MEMBER(z_link_node), #define MX_z_link_node 3 CTF_MEMBER(z_phys), #define MX_z_phys 4 CTF_MEMBER(z_links), #define MX_z_links 5 CTF_MEMBER(z_size), #define MX_z_size 6 { NULL, 0 } }; #define ZNODE_PHYS_TYPE_NAME "znode_phys_t" static CTF_member_t znode_phys_members[] = { CTF_MEMBER(zp_size), #define MX_zp_size 0 CTF_MEMBER(zp_links), #define MX_zp_links 1 { NULL, 0 } }; #define ZFSVFS_TYPE_NAME "zfsvfs_t" static CTF_member_t zfsvfs_members[] = { CTF_MEMBER(z_vfs), #define MX_z_vfs 0 { NULL, 0 } }; /* * CTF ZFS request table */ static CTF_request_t ZFS_requests[] = { { ZNODE_TYPE_NAME, znode_members }, { ZNODE_PHYS_TYPE_NAME, znode_phys_members }, { ZFSVFS_TYPE_NAME, zfsvfs_members }, { NULL, NULL } }; /* * Missing members exceptions -- i.e., CTF_getmem won't consider it * an error if any of these members are undefined. */ typedef struct CTF_exception { char *tynm; /* type name */ char *memnm; /* member name */ } CTF_exception_t; static CTF_exception_t CTF_exceptions[] = { { ZNODE_TYPE_NAME, "z_phys" }, { ZNODE_TYPE_NAME, "z_links" }, { ZNODE_TYPE_NAME, "z_size" }, { NULL, NULL } }; /* * ZFS function prototypes */ _PROTOTYPE(static int read_nzn,(KA_T na, KA_T nza, znode_t *z)); _PROTOTYPE(static int read_nznp,(KA_T nza, KA_T nzpa, znode_phys_t *zp)); _PROTOTYPE(static int read_nzvfs,(KA_T nza, KA_T nzva, zfsvfs_t *zv)); #endif /* defined(HAS_ZFS) && defined(HAS_LIBCTF) */ _PROTOTYPE(static struct l_dev *finddev,(dev_t *dev, dev_t *rdev, int flags)); /* * Finddev() "look-in " flags */ #define LOOKDEV_TAB 0x01 /* look in device table */ #define LOOKDEV_CLONE 0x02 /* look in Clone table */ #define LOOKDEV_PSEUDO 0x04 /* look in Pseudo table */ #define LOOKDEV_ALL (LOOKDEV_TAB | LOOKDEV_CLONE | LOOKDEV_PSEUDO) /* look all places */ /* * SAM-FS definitions */ #define SAMFS_NMA_MSG "(limited SAM-FS info)" /* * Voptab definitions */ typedef struct build_v_optab { char *dnm; /* drive_NL name */ char *fsys; /* file system type name */ int nty; /* node type index (i.e., N_*) */ } build_v_optab_t; static build_v_optab_t Build_v_optab[] = { { "auvops", "autofs", N_AUTO }, { "avops", "afs", N_AFS }, { "afsops", "afs", N_AFS }, { "ctfsadir", NULL, N_CTFSADIR }, { "ctfsbund", NULL, N_CTFSBUND }, { "ctfscdir", NULL, N_CTFSCDIR }, { "ctfsctl", NULL, N_CTFSCTL }, { "ctfsevt", NULL, N_CTFSEVT }, { "ctfslate", NULL, N_CTFSLATE }, { "ctfsroot", NULL, N_CTFSROOT }, { "ctfsstat", NULL, N_CTFSSTAT }, { "ctfssym", NULL, N_CTFSSYM }, { "ctfstdir", NULL, N_CTFSTDIR }, { "ctfstmpl", NULL, N_CTFSTMPL }, #if defined(HASCACHEFS) { "cvops", NULL, N_CACHE }, #endif /* defined(HASCACHEFS) */ { "devops", "devfs", N_DEV }, { "doorops", NULL, N_DOOR }, { "fdops", "fd", N_FD }, { "fd_ops", "fd", N_FD }, { "fvops", "fifofs", N_FIFO }, { "hvops", "hsfs", N_HSFS }, { "lvops", "lofs", N_LOFS }, { "mntops", "mntfs", N_MNT }, { "mvops", "mvfs", N_MVFS }, { "n3vops", NULL, N_NFS }, #if solaris>=100000 { "n4vops", NULL, N_NFS4 }, #else /* solaris<100000 */ { "n4vops", NULL, N_NFS }, #endif /* solaris>=100000 */ { "nmvops", "namefs", N_NM }, { "nvops", NULL, N_NFS }, { "pdvops", "pcfs", N_PCFS }, { "pfvops", "pcfs", N_PCFS }, { "portvops", NULL, N_PORT }, { "prvops", "proc", N_PROC }, { "sam1vops", NULL, N_SAMFS }, { "sam2vops", NULL, N_SAMFS }, { "sam3vops", NULL, N_SAMFS }, { "sam4vops", NULL, N_SAMFS }, { "sckvops", "sockfs", N_SOCK }, { "devipnetops", "sdevfs", N_SDEV }, { "devnetops", "sdevfs", N_SDEV }, { "devptsops", "sdevfs", N_SDEV }, { "devvtops", "sdevfs", N_SDEV }, { "socketvops", "sockfs", N_SOCK }, { "sdevops", "sdevfs", N_SDEV }, { "shvops", "sharedfs", N_SHARED }, { "sncavops", "sockfs", N_SOCK }, { "stpivops", "sockfs", N_SOCK }, { "spvops", "specfs", N_REGLR }, { "tvops", "tmpfs", N_TMP }, { "uvops", "ufs", N_REGLR }, { "vvfclops", "vxfs", N_VXFS }, { "vvfops", "vxfs", N_VXFS }, { "vvfcops", "vxfs", N_VXFS }, { "vvops", "vxfs", N_VXFS }, { "vvops_p", "vxfs", N_VXFS }, { "zfsdops", "zfs", N_ZFS }, { "zfseops", "zfs", N_ZFS }, { "zfsfops", "zfs", N_ZFS }, { "zfsshops", "zfs", N_ZFS }, { "zfssymops", "zfs", N_ZFS }, { "zfsxdops", "zfs", N_ZFS }, { NULL, NULL, 0 } /* table end */ }; typedef struct v_optab { char *fsys; /* file system type name */ int fx; /* Fsinfo[] index (-1 if none) */ int nty; /* node type index (i.e., N_*) */ KA_T v_op; /* vnodeops address */ struct v_optab *next; /* next entry */ } v_optab_t; static v_optab_t **FxToVoptab = (v_optab_t **)NULL; /* table to convert file system index * to Voptab address[] -- built by * build_Voptab() */ static v_optab_t **Voptab = (v_optab_t **)NULL; /* table to convert vnode v_op * addresses to file system name and * node type -- built by build_Voptab() * and addressed through the HASHVOP() * macro */ #define VOPHASHBINS 256 /* number of Voptab[] hash bins -- * MUST BE A POWER OF TWO! */ /* * Local function prototypes */ _PROTOTYPE(static void build_Voptab,(void)); _PROTOTYPE(static char isvlocked,(struct vnode *va)); _PROTOTYPE(static int readinode,(KA_T ia, struct inode *i)); _PROTOTYPE(static void read_mi,(KA_T s, dev_t *dev, caddr_t so, int *so_st, KA_T *so_ad, struct l_dev **sdp)); #if solaris>=20500 # if solaris>=20600 _PROTOTYPE(static int read_nan,(KA_T na, KA_T aa, struct fnnode *rn)); _PROTOTYPE(static int read_nson,(KA_T na, KA_T sa, struct sonode *sn)); _PROTOTYPE(static int read_nusa,(struct soaddr *so, struct sockaddr_un *ua)); # else /* solaris<20600 */ _PROTOTYPE(static int read_nan,(KA_T na, KA_T aa, struct autonode *a)); # endif /* solaris>=20600 */ _PROTOTYPE(static int idoorkeep,(struct door_node *d)); _PROTOTYPE(static int read_ndn,(KA_T na, KA_T da, struct door_node *d)); #endif /* solaris>=20500 */ #if solaris>=110000 _PROTOTYPE(static int read_nsdn,(KA_T na, KA_T sa, struct sdev_node *sdn, struct vattr *sdva)); #endif /* solaris>=110000 */ _PROTOTYPE(static int read_nfn,(KA_T na, KA_T fa, struct fifonode *f)); _PROTOTYPE(static int read_nhn,(KA_T na, KA_T ha, struct hsnode *h)); _PROTOTYPE(static int read_nin,(KA_T na, KA_T ia, struct inode *i)); _PROTOTYPE(static int read_nmn,(KA_T na, KA_T ia, struct mvfsnode *m)); _PROTOTYPE(static int read_npn,(KA_T na, KA_T pa, struct pcnode *p)); _PROTOTYPE(static int read_nrn,(KA_T na, KA_T ra, struct rnode *r)); #if solaris>=100000 _PROTOTYPE(static int read_nctfsn,(int ty, KA_T na, KA_T ca, char *cn)); _PROTOTYPE(static int read_nprtn,(KA_T na, KA_T ra, port_t *p)); _PROTOTYPE(static int read_nrn4,(KA_T na, KA_T ra, struct rnode4 *r)); #endif /* solaris>=100000 */ _PROTOTYPE(static int read_nsn,(KA_T na, KA_T sa, struct snode *s)); _PROTOTYPE(static int read_ntn,(KA_T na, KA_T ta, struct tmpnode *t)); _PROTOTYPE(static int read_nvn,(KA_T na, KA_T va, struct vnode *v)); #if defined(HASPROCFS) _PROTOTYPE(static int read_npi,(KA_T na, struct vnode *v, struct pid *pids)); #endif /* defined(HASPROCFS) */ _PROTOTYPE(static char *ent_fa,(KA_T *a1, KA_T *a2, char *d, int *len)); _PROTOTYPE(static int is_socket,(struct vnode *v)); _PROTOTYPE(static int read_cni,(struct snode *s, struct vnode *rv, struct vnode *v, struct snode *rs, struct dev_info *di, char *din, int dinl)); #if defined(HASCACHEFS) _PROTOTYPE(static int read_ncn,(KA_T na, KA_T ca, struct cnode *cn)); #endif /* defined(HASCACHEFS) */ _PROTOTYPE(static int read_nln,(KA_T na, KA_T la, struct lnode *ln)); _PROTOTYPE(static int read_nnn,(KA_T na, KA_T nna, struct namenode *n)); #if solaris<100000 _PROTOTYPE(static void savesockmod,(struct so_so *so, struct so_so *sop, int *so_st)); #else /* solaris>=100000 */ _PROTOTYPE(static int read_ndvn,(KA_T na, KA_T da, struct dv_node *dv, dev_t *dev, unsigned char *devs)); #endif /* solaris<100000 */ /* * Local static values */ static KA_T Spvops = (KA_T)0; /* specfs vnodeops address -- saved * by build_Voptab() */ static KA_T Vvops[VXVOP_NUM]; /* addresses of: * vx_fcl_dnodeops_p (VXVOP_FCL) * fdd_vnops (VXVOP_FDD) * fdd_chain_vnops (VXVOP_FDDCH), * vx_vnodeops (VXVOP_REG) * vx_vnodeops_p (VXVOP_REG_P) * -- saved by build_Voptab() */ /* * Local macros * * GETVOPS() -- get direct or indirect *vnodeops address * * HASHVOP() -- hash the vnode's v_op address */ #if defined(VOPNAME_OPEN) && solaris>=100000 #define GETVOPS(name, nl, ops) \ if (get_Nl_value(name, nl, &ops) < 0) \ ops = (KA_T)0; \ else if (kread(ops, (char *)&ops, sizeof(ops))) \ ops = (KA_T)0 #else /* !defined(VOPNAME_OPEN) || solaris<100000 */ #define GETVOPS(name, nl, ops) \ if (get_Nl_value(name, nl, &ops) < 0) \ ops = (KA_T)0 #endif /* defined(VOPNAME_OPEN) && solaris>=100000 */ #define HASHVOP(ka) ((int)((((ka &0x1fffffff) * 31415) >> 3) & \ (VOPHASHBINS - 1))) /* * build_Voptab() -- build Voptab[] */ static void build_Voptab() { build_v_optab_t *bp; /* Build_v_optab[] pointer */ int fx; /* temporary file system type index */ int h; /* hash index */ int i, j; /* temporary indexes */ KA_T ka; /* temporary kernel address */ v_optab_t *nv, *vp, *vpp; /* Voptab[] working pointers */ int vv = 0; /* number of Vvops[] addresses that * have been located */ /* * If Voptab[] is allocated, return; otherwise allocate space for Voptab[] * and FxToVoptab[] amd fill them. */ if (Voptab) return; /* * During first call, allocate space for Voptab[] and FxToVoptab[]. */ if (!(Voptab = (v_optab_t **)calloc((MALLOC_S)VOPHASHBINS, sizeof(v_optab_t))) ) { (void) fprintf(stderr, "%s: no space for Voptab\n", Pn); Exit(1); } if (!(FxToVoptab = (v_optab_t **)calloc((MALLOC_S)Fsinfomax, sizeof(v_optab_t *))) ) { (void) fprintf(stderr, "%s: no space for FxToVoptab\n", Pn); Exit(1); } for (i = 0; i < VXVOP_NUM; i++) { Vvops[i] = (KA_T)NULL; } /* * Use Build_v_optab[] to build Voptab[]. */ for (bp = Build_v_optab; bp->dnm; bp++) { /* * Get the kernel address for the symbol. Do nothing if it can't * be determined. */ GETVOPS(bp->dnm, Drive_Nl, ka); if (!ka) continue; /* * Check the Voptab[] for the address. */ h = HASHVOP(ka); for (vp = Voptab[h], vpp = (v_optab_t *)NULL; vp; vp = vp->next) { if (vp->v_op == ka) break; vpp = vp; } if (vp) { /* * Ignore duplicates. */ continue; } /* * No Voptab[] entry was found, so allocate space for a new * v_optab_t structure, determine its file system type index, * fill it and link it to the Voptab[]. */ if (!(nv = (v_optab_t *)malloc((MALLOC_S)sizeof(v_optab_t)))) { (void) fprintf(stderr, "%s: out of Voptab space at: %s\n", Pn, bp->dnm); Exit(1); } nv->fsys = bp->fsys; nv->fx = -1; nv->nty = bp->nty; nv->next = (v_optab_t *)NULL; nv->v_op = ka; if (bp->fsys) { for (i = 0; i < Fsinfomax; i++) { if (!strcmp(bp->fsys, Fsinfo[i])) { nv->fx = i; break; } } } if (!Voptab[h]) Voptab[h] = nv; else vpp->next = nv; /* * Handle special v_op addresses: * * special vnode ops; * VxFS ops. */ if (!Spvops) { if (!strcmp(bp->dnm, "spvops")) Spvops = ka; } for (i = 0; (i < VXVOP_NUM) && (vv < VXVOP_NUM); i++) { if (Vvops[i]) continue; switch (i) { case VXVOP_FCL: if (!strcmp(bp->dnm, "vvfclops")) { Vvops[i] = ka; vv++; } break; case VXVOP_FDD: if (!strcmp(bp->dnm, "vvfops")) { Vvops[i] = ka; vv++; } break; case VXVOP_FDDCH: if (!strcmp(bp->dnm, "vvfcops")) { Vvops[i] = ka; vv++; } break; case VXVOP_REG: if (!strcmp(bp->dnm, "vvops")) { Vvops[i] = ka; vv++; } break; case VXVOP_REG_P: if (!strcmp(bp->dnm, "vvops_p")) { Vvops[i] = ka; vv++; } break; } } } /* * Link Voptab[] entries to FxToVoptab[] entries. */ for (h = 0; h < VOPHASHBINS; h++) { for (vp = Voptab[h]; vp; vp = vp->next) { if (!vp->fsys) continue; if (((fx = vp->fx) >= 0) && (fx < Fsinfomax)) { if (!FxToVoptab[fx]) FxToVoptab[fx] = vp; continue; } for (i = 0; i < Fsinfomax; i++) { if (!strcmp(Fsinfo[i], vp->fsys)) { vp->fx = i; if (!FxToVoptab[i]) FxToVoptab[i] = vp; break; } } } } } #if defined(HAS_LIBCTF) /* * CTF_getmem() -- get CTF members */ int CTF_getmem(f, mod, ty, mem) ctf_file_t *f; /* CTF file handle */ const char *mod; /* module name */ const char *ty; /* type */ CTF_member_t *mem; /* member table */ { int err; /* error flag */ ctf_id_t id; /* CTF ID */ CTF_member_t *mp; /* member pointer */ CTF_exception_t *xp; /* exception table pointer */ int xs; /* exception status */ /* * Look up the type. */ if ((id = ctf_lookup_by_name(f, ty)) == CTF_ERR) { (void) fprintf(stderr, "%s: ctf_lookup_by_name: %s: %s: %s\n", Pn, mod, ty, ctf_errmsg(ctf_errno(f))); return(1); } /* * Get member offsets. */ if (ctf_member_iter(f, id, CTF_memCB, mem) == CTF_ERR) { (void) fprintf(stderr, "%s: ctf_member_iter: %s: %s: %s\n", Pn, mod, ty, ctf_errmsg(ctf_errno(f))); return(1); } /* * Examine members. */ for (err = 0, mp = mem; mp->m_name; mp++) { if (mp->m_offset == CTF_MEMBER_UNDEF) { /* * Check for an undefined member exception. Report an error if * no exception is found. */ for (xp = CTF_exceptions, xs = 0; xp->tynm; xp++) { if (!strcmp(xp->tynm, ty) && !strcmp(xp->memnm, mp->m_name)) { xs = 1; break; } } if (!xs) { (void) fprintf(stderr, "%s: getmembers: %s: %s: %s: struct member undefined\n", Pn, mod, ty, mp->m_name); err = 1; } } else { /* * Convert bit offsets to byte offsets. */ if ((mp->m_offset % NBBY) != 0) { (void) fprintf(stderr, "%s: getmembers: %s: %s: %s: struct member is bit field\n", Pn, mod, ty, mp->m_name); err = 1; } else mp->m_offset /= NBBY; } } return(err); } /* * CTF_init - initialize CTF library access */ void CTF_init(i, t, r) int *i; /* initialization status */ char *t; /* kernel module template */ CTF_request_t *r; /* CTF requests */ { int err; /* error status */ ctf_file_t *f; /* CTF file info handle */ # if defined(_LP64) static char isa[256+1]; /* kernel instruction set name */ static int isas = 0; /* isa[] status */ # endif /* defined(_LP64) */ char kernmod[MAXPATHLEN]; /* kernel module pathname */ char *kmp; /* kernel module path name pointer */ static char pfn[256+1]; /* system platform name */ static int pfns = 0; /* pfn[] status: -1 = request failed * 0 = none requested * >0 = available */ char pfxkernmod[MAXPATHLEN]; /* prefixed kernel module name */ struct stat sb; /* stat(2) buffer */ if (*i) return; # if defined(_LP64) /* * If CTF access hasn't been initialized and a 64 bit kernel is in use, * determine the name of the kernel's instruction set, and construct the * pathname of the kernel module, using the supplied template. */ if (!isas) { if (sysinfo(SI_ARCHITECTURE_K, isa, sizeof(isa) - 1) == -1) { (void) fprintf(stderr, "%s: sysinfo: %s\n", Pn, strerror(errno)); Exit(1); } isas = 1; isa[sizeof(isa) - 1] = '\0'; } (void) snprintf(kernmod, sizeof(kernmod) - 1, t, isa); kernmod[sizeof(kernmod) - 1] = '\0'; # else /* !defined(_LP64) */ /* * If CTF access hasn't been initialized and a 32 bit kernel is in use, the * supplied template is the module path name. */ (void) strncpy(kernmod, t, sizeof(kernmod) - 1); # endif /* defined(_LP64) */ kernmod[sizeof(kernmod) - 1] = '\0'; kmp = kernmod; if (statsafely(kmp, &sb)) { /* * The module at the specified path does not exist or is inaccessible. * * Get the platform name and construct a prefix from it for module path * name and see if that exists and is accessible. * * If it is, let CTF_init() use it; otherwise let CTF_init() fail on * the specified path. */ if (pfns >= 0) { if (!pfns) pfns = sysinfo(SI_MACHINE, pfn, sizeof(pfn) - 1); if (pfns > 0) { pfn[sizeof(pfn) - 1] = '\0'; (void) snprintf(pfxkernmod, sizeof(pfxkernmod) - 1, "/platform/%s/%s", pfn, (kernmod[0] == '/') ? &kernmod[1] : kernmod); pfxkernmod[sizeof(pfxkernmod) - 1] = '\0'; if (!stat(pfxkernmod, &sb)) kmp = pfxkernmod; } } } /* * Open the module file and read its CTF info. */ if ((f = ctf_open(kmp, &err)) == NULL) { (void) fprintf(stderr, "%s: ctf_open: %s: %s\n", Pn, kmp, ctf_errmsg(err)); Exit(1); } for (err = 0; r->name; r++) { if (CTF_getmem(f, kmp, r->name, r->mem)) err = 1; } (void) ctf_close(f); if (err) Exit(1); *i = 1; } /* * CTF_memCB() - Callback function for ctf_member_iter() */ int CTF_memCB(name, id, offset, arg) const char *name; /* structure member name */ ctf_id_t id; /* CTF ID */ ulong_t offset; /* member offset */ void *arg; /* member table */ { CTF_member_t *mp; /* * Check for members of interest and record their offsets. */ for (mp = (CTF_member_t *)arg; mp->m_name; mp++) { if (!strcmp(name, mp->m_name)) { mp->m_offset = offset; break; } } return(0); } #endif /* defined(HAS_LIBCTF) */ /* * ent_fa() - enter fattach addresses in NAME column addition */ static char * ent_fa(a1, a2, d, len) KA_T *a1; /* first fattach address (NULL OK) */ KA_T *a2; /* second fattach address */ char *d; /* direction ("->" or "<-") */ int *len; /* returned description length */ { static char buf[1024]; size_t bufl = sizeof(buf); char tbuf[32]; /* * Form the fattach description. */ if (!a1) #if solaris<20600 (void) snpf(buf, bufl, "(FA:%s%s)", d, print_kptr(*a2, (char *)NULL, 0)); #else /* solaris>=20600 */ (void) snpf(buf, bufl, "(FA:%s%s)", d, print_kptr(*a2, (char *)NULL, 0)); #endif /* solaris<20600 */ else #if solaris<20600 (void) snpf(buf, bufl, "(FA:%s%s%s)", print_kptr(*a1, tbuf, sizeof(tbuf)), d, print_kptr(*a2, (char *)NULL, 0)); #else /* solaris>=20600 */ (void) snpf(buf, bufl, "(FA:%s%s%s)", print_kptr(*a1, tbuf, sizeof(tbuf)), d, print_kptr(*a2, (char *)NULL, 0)); #endif /* solaris<20600 */ *len = (int)strlen(buf); return(buf); } /* * is_socket() - is the stream a socket? */ static int is_socket(v) struct vnode *v; /* vnode pointer */ { char *cp, *ep, *pf; int i, j, len, n, pfl; major_t maj; minor_t min; static struct tcpudp { int ds; major_t maj; minor_t min; char *proto; } tcpudp[] = { { 0, 0, 0, "tcp" }, { 0, 0, 0, "udp" }, #if defined(HASIPv6) { 0, 0, 0, "tcp6" }, { 0, 0, 0, "udp6" }, #endif /* defined(HASIPv6) */ }; #define NTCPUDP (sizeof(tcpudp) / sizeof(struct tcpudp)) static int tcpudps = 0; if (!v->v_stream) return(0); maj = (major_t) GET_MAJ_DEV(v->v_rdev); min = (minor_t) GET_MIN_DEV(v->v_rdev); /* * Fill in tcpudp[], as required. */ if (!tcpudps) { #if solaris<80000 pf = "/devices/pseudo/clone"; #else /* solaris>=80000 */ pf = "/devices/pseudo/"; #endif /* solaris<80000 */ for (i = n = 0, pfl = (int)strlen(pf); (i < Ndev) && (n < NTCPUDP); i++) { if (strncmp(Devtp[i].name, pf, pfl) || !(ep = strrchr((cp = &Devtp[i].name[pfl]), ':')) || (strncmp(++ep, "tcp", 3) && strncmp(ep, "udp", 3))) continue; #if solaris<80000 if (*(ep + 3)) #else /* solaris>=80000 */ len = (*(ep + 3) == '6') ? 4 : 3; if (*(ep + len) || ((cp + len) >= ep) || strncmp(cp, ep, len)) #endif /* solaris<80000 */ continue; for (j = 0; j < NTCPUDP; j++) { if (!tcpudp[j].ds && !strcmp(ep, tcpudp[j].proto)) { tcpudp[j].ds = 1; tcpudp[j].maj = (major_t) GET_MAJ_DEV(Devtp[i].rdev); tcpudp[j].min = (minor_t) GET_MIN_DEV(Devtp[i].rdev); n++; break; } } } tcpudps = n ? 1 : -1; } /* * Check for known IPv[46] TCP or UDP device. */ for (i = 0; (i < NTCPUDP) && (tcpudps > 0); i++) { if (tcpudp[i].ds #if solaris<80000 && (maj == tcpudp[i].min) #else /* solaris>=80000 */ && (maj == tcpudp[i].maj) #endif /* solaris<80000 */ ) { process_socket((KA_T)v->v_stream, tcpudp[i].proto); return(1); } } return(0); } /* * isvlocked() - is Solaris vnode locked? */ static char isvlocked(va) struct vnode *va; /* local vnode address */ { #if solaris<20500 struct filock f; KA_T ff; KA_T fp; #endif /* solaris<20500 */ int i, l; #if solaris>=20300 struct lock_descriptor ld; KA_T lf; KA_T lp; # if solaris<20500 #define LOCK_END ld.info.li_sleep.sli_flock.l_len #define LOCK_FLAGS ld.flags #define LOCK_NEXT ld.next #define LOCK_OWNER ld.owner.pid #define LOCK_START ld.start #define LOCK_TYPE ld.type # else /* solaris>=20500 */ #define LOCK_END ld.l_flock.l_len #define LOCK_FLAGS ld.l_state #define LOCK_NEXT ld.l_next #define LOCK_OWNER ld.l_flock.l_pid #define LOCK_START ld.l_start #define LOCK_TYPE ld.l_type # endif /* solaris<20500 */ #endif /* solaris>=20300 */ if (va->v_filocks == NULL) return(' '); #if solaris<20500 # if solaris>20300 || (solaris==20300 && defined(P101318) && P101318>=45) if (Ntype == N_NFS) # endif /* solaris>20300 || (solaris==20300 && defined(P101318) && P101318>=45) */ { ff = fp = (KA_T)va->v_filocks; i = 0; do { if (kread(fp, (char *)&f, sizeof(f))) return(' '); i++; if (f.set.l_pid != (pid_t)Lp->pid) continue; if (f.set.l_whence == 0 && f.set.l_start == 0 && f.set.l_len == MAXEND) l = 1; else l = 0; switch (f.set.l_type & (F_RDLCK | F_WRLCK)) { case F_RDLCK: return(l ? 'R' : 'r'); case F_WRLCK: return(l ? 'W' : 'w'); case F_RDLCK|F_WRLCK: return('u'); default: return('N'); } } while ((fp = (KA_T)f.next) && (fp != ff) && (i < 10000)); } #endif /* solaris<20500 */ #if solaris>=20300 lf = lp = (KA_T)va->v_filocks; i = 0; do { if (kread(lp, (char *)&ld, sizeof(ld))) return(' '); i++; if (!(LOCK_FLAGS & ACTIVE_LOCK) || LOCK_OWNER != (pid_t)Lp->pid) continue; if (LOCK_START == 0 && (LOCK_END == 0 # if solaris<20500 || LOCK_END == MAXEND # else /* solaris>=20500 */ || LOCK_END == MAXEND # endif /* solaris<20500 */ )) l = 1; else l = 0; switch (LOCK_TYPE) { case F_RDLCK: return(l ? 'R' : 'r'); case F_WRLCK: return(l ? 'W' : 'w'); case (F_RDLCK | F_WRLCK): return('u'); default: return('L'); } } while ((lp = (KA_T)LOCK_NEXT) && (lp != lf) && (i < 10000)); return(' '); #endif /* solaris>=20300 */ } /* * finddev() - look up device by device number */ static struct l_dev * finddev(dev, rdev, flags) dev_t *dev; /* device */ dev_t *rdev; /* raw device */ int flags; /* look flags -- see LOOKDEV_* symbol * definitions */ { struct clone *c; struct l_dev *dp; struct pseudo *p; if (!Sdev) readdev(0); /* * Search device table for match. */ #if defined(HASDCACHE) finddev_again: #endif /* defined(HASDCACHE) */ if (flags & LOOKDEV_TAB) { if ((dp = lkupdev(dev, rdev, 0, 0))) return(dp); } /* * Search for clone. */ if ((flags & LOOKDEV_CLONE) && Clone) { for (c = Clone; c; c = c->next) { if (GET_MAJ_DEV(*rdev) == GET_MIN_DEV(c->cd.rdev)) { #if defined(HASDCACHE) if (DCunsafe && !c->cd.v && !vfy_dev(&c->cd)) goto finddev_again; #endif /* defined(HASDCACHE) */ return(&c->cd); } } } /* * Search for pseudo device match on major device only. */ if ((flags & LOOKDEV_PSEUDO) && Pseudo) { for (p = Pseudo; p; p = p->next) { if (GET_MAJ_DEV(*rdev) == GET_MAJ_DEV(p->pd.rdev)) { #if defined(HASDCACHE) if (DCunsafe && !p->pd.v && !vfy_dev(&p->pd)) goto finddev_again; #endif /* defined(HASDCACHE) */ return(&p->pd); } } } return((struct l_dev *)NULL); } #if solaris>=20500 /* * idoorkeep() -- identify door keeper process */ static int idoorkeep(d) struct door_node *d; /* door's node */ { char buf[1024]; size_t bufl = sizeof(buf); struct proc dp; struct pid dpid; /* * Get the proc structure and its pid structure for the door target. */ if (!d->door_target || kread((KA_T)d->door_target, (char *)&dp, sizeof(dp))) return(0); if (!dp.p_pidp || kread((KA_T)dp.p_pidp, (char *)&dpid, sizeof(dpid))) return(0); /* * Form a description of the door. * * Put the description in the NAME column addition field. If there's already * something there, allocate more space and add the door description to it. */ if (Lp->pid == (int)dpid.pid_id) (void) snpf(buf, bufl, "(this PID's door)"); else { (void) snpf(buf, bufl, "(door to %.64s[%ld])", dp.p_user.u_comm, (long)dpid.pid_id); } (void) add_nma(buf, (int)strlen(buf)); return(1); } #endif /* solaris>=20500 */ /* * process_node() - process vnode */ void process_node(va) KA_T va; /* vnode kernel space address */ { #if defined(HASCACHEFS) struct cnode cn; #endif /* defined(HASCACHEFS) */ dev_t dev, rdev, trdev; unsigned char devs = 0; unsigned char fxs = 0; unsigned char ins = 0; unsigned char kvs = 0; unsigned char nns = 0; unsigned char pnl = 0; unsigned char rdevs = 0; unsigned char rvs = 0; unsigned char rfxs = 0; unsigned char sdns = 0; unsigned char tdef; unsigned char trdevs = 0; unsigned char unix_sock = 0; struct dev_info di; char din[DINAMEL]; char *ep; struct fifonode f; char *fa = (char *)NULL; int fal; static int ft = 1; struct vnode fv, rv; int fx, rfx; struct hsnode h; struct inode i; int j; KA_T ka, vka; struct lnode lo; struct vfs kv, rkv; int len, llc, nl, snl, sepl; struct mvfsnode m; struct namenode nn; struct l_vfs *nvfs, *vfs; struct pcnode pc; struct pcfs pcfs; struct rnode r; KA_T realvp = (KA_T)NULL; struct snode rs; struct snode s; #if solaris>=110000 char *nm, *sep; size_t nmrl, tl; struct sdev_node sdn; struct vattr sdva; sotpi_info_t sti; int stis = 0; #endif /* solaris>=110000 */ struct l_dev *sdp = (struct l_dev *)NULL; size_t sz; struct tmpnode t; char tbuf[128], *ty, ubuf[128]; int tbufx; enum vtype type; struct sockaddr_un ua; static struct vnode *v = (struct vnode *)NULL; KA_T vs; int vty = 0; int vty_tmp; #if solaris>=20500 # if solaris>=20600 struct fnnode fnn; struct pairaddr { short f; unsigned short p; } *pa; KA_T peer; struct sonode so; KA_T soa, sona; # else /* solaris<20600 */ struct autonode au; # endif /* solaris>=20600 */ struct door_node dn; int dns = 0; #endif /* solaris >=20500 */ #if solaris<100000 KA_T so_ad[2]; struct so_so soso; int so_st = 0; #else /* solaris>=100000 */ union { ctfs_adirnode_t adir; ctfs_bunode_t bun; ctfs_cdirnode_t cdir; ctfs_ctlnode_t ctl; ctfs_evnode_t ev; ctfs_latenode_t late; ctfs_rootnode_t root; ctfs_symnode_t sym; ctfs_tdirnode_t tdir; ctfs_tmplnode_t tmpl; } ctfs; dev_t dv_dev; struct dv_node dv; unsigned char dv_devs = 0; unsigned char dvs = 0; port_t pn; struct rnode4 r4; #endif /* solaris<100000 */ #if defined(HASPROCFS) struct procfsid *pfi; struct pid pids; #endif /* defined(HASPROCFS) */ #if defined(HAS_AFS) struct afsnode an; #endif /* defined(HAS_AFS) */ #if defined(HASVXFS) struct l_ino vx; #endif /* defined(HASVXFS) */ #if defined(HAS_ZFS) vfs_t zgvfs; unsigned char zns = 0; znode_t zn; zfsvfs_t zvfs; #endif /* defined(HAS_ZFS) */ /* * Do first-time only operations. */ #if solaris<100000 so_ad[0] = so_ad[1] = (KA_T)0; #endif /* solaris<100000 */ if (ft) { (void) build_Voptab(); ft = 0; } /* * Read the vnode. */ if (!va) { enter_nm("no vnode address"); return; } if (!v) { /* * Allocate space for the vnode or AFS vcache structure. */ #if defined(HAS_AFS) v = alloc_vcache(); #else /* !defined(HAS_AFS) */ v = (struct vnode *) malloc(sizeof(struct vnode)); #endif /* defined(HAS_AFS) */ if (!v) { (void) fprintf(stderr, "%s: can't allocate %s space\n", Pn, #if defined(HAS_AFS) "vcache" #else /* !defined(HAS_AFS) */ "vnode" #endif /* defined(HAS_AFS) */ ); Exit(1); } } if (readvnode(va, v)) { enter_nm(Namech); return; } #if defined(HASNCACHE) Lf->na = va; #endif /* defined(HASNCACHE) */ #if defined(HASFSTRUCT) Lf->fna = va; Lf->fsv |= FSV_NI; #endif /* defined(HASFSTRUCT) */ #if defined(HASLFILEADD) && defined(HAS_V_PATH) Lf->V_path = (KA_T)v->v_path; #endif /* defined(HASLFILEADD) && defined(HAS_V_PATH) */ vs = (KA_T)v->v_stream; /* * Check for a Solaris socket. */ if (is_socket(v)) return; /* * Obtain the Solaris virtual file system structure. */ if ((ka = (KA_T)v->v_vfsp)) { if (kread(ka, (char *)&kv, sizeof(kv))) { vka = va; vfs_read_error: (void) snpf(Namech, Namechl - 1, "vnode at %s: can't read vfs: %s", print_kptr(vka, tbuf, sizeof(tbuf)), print_kptr(ka, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return; } kvs = 1; } else kvs = 0; /* * Derive the virtual file system structure's device number from * its file system ID for NFS and High Sierra file systems. */ if (kvs && ((fx = kv.vfs_fstype - 1) >= 0) && (fx < Fsinfomax)) { fxs = 1; if (strcmp(Fsinfo[fx], "nfs") == 0 || strcmp(Fsinfo[fx], "nfs3") == 0 || strcmp(Fsinfo[fx], "hsfs") == 0) kv.vfs_dev = (dev_t)kv.vfs_fsid.val[0]; } else { fx = -1; fxs = 0; } /* * Determine the Solaris vnode type. */ if ((Ntype = vop2ty(v, fx)) < 0) { if (v->v_type == VFIFO) { vty = N_REGLR; Ntype = N_FIFO; } else if (vs) { Ntype = vty = N_STREAM; Lf->is_stream = 1; } if (Ntype < 0) { (void) snpf(Namech, Namechl - 1, "unknown file system type%s%s%s, v_op: %s", fxs ? " (" : "", fxs ? Fsinfo[fx] : "", fxs ? ")" : "", print_kptr((KA_T)v->v_op, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return; } } else { vty = Ntype; if (v->v_type == VFIFO) Ntype = N_FIFO; else if (vs && Ntype != N_SOCK) { Ntype = vty = N_STREAM; Lf->is_stream = 1; } } /* * See if this Solaris node has been fattach'ed to another node. * If it has, read the namenode, and enter the node addresses in * the NAME column addition. * * See if it's covering a socket as well and process accordingly. */ if (vty == N_NM) { if (read_nnn(va, (KA_T)v->v_data, &nn)) return; nns = 1; if (nn.nm_mountpt) #if solaris>=20500 fa = ent_fa((KA_T *)((Ntype == N_FIFO || v->v_type == VDOOR) ? NULL : &va), (KA_T *)&nn.nm_mountpt, "->", &fal); #else /* solaris<20500 */ fa = ent_fa((KA_T *)((Ntype == N_FIFO) ? NULL : &va), (KA_T *)&nn.nm_mountpt, "->", &fal); #endif /* solaris>=20500 */ if (Ntype != N_FIFO && nn.nm_filevp && !kread((KA_T)nn.nm_filevp, (char *)&rv, sizeof(rv))) { rvs = 1; if ((ka = (KA_T)rv.v_vfsp) && !kread(ka, (char *)&rkv, sizeof(rkv)) && ((rfx = rkv.vfs_fstype - 1) >= 0) && (rfx < Fsinfomax) ) { rfxs = 1; } else { rfx = fx; rfxs = fxs; } #if defined(HASNCACHE) Lf->na = (KA_T)nn.nm_filevp; #endif /* defined(HASNCACHE) */ if (is_socket(&rv)) return; } } if (Selinet && Ntype != N_SOCK) return; /* * See if this Solaris node is served by spec_vnodeops. */ if (Spvops && Spvops == (KA_T)v->v_op) Ntype = N_SPEC; /* * Determine the Solaris lock state. */ Lf->lock = isvlocked(v); /* * Establish the Solaris local virtual file system structure. */ if (!(ka = (KA_T)v->v_vfsp) || !kvs) vfs = (struct l_vfs *)NULL; else if (!(vfs = readvfs(ka, &kv, v))) { vka = va; goto vfs_read_error; } /* * Read the afsnode, autonode, cnode, door_node, fifonode, fnnode, lnode, * inode, pcnode, rnode, snode, tmpnode, znode, etc. */ switch (Ntype) { case N_SPEC: /* * A N_SPEC node is a node that resides in in an underlying file system * type -- e.g. NFS, HSFS. Its vnode points to an snode. Subsequent * node structures are implied by the underlying node type. */ if (read_nsn(va, (KA_T)v->v_data, &s)) return; realvp = (KA_T)s.s_realvp; if (!realvp && s.s_commonvp) { if (read_cni(&s, &rv, v, &rs, &di, din, sizeof(din)) == 1) return; if (!rv.v_stream) { if (din[0]) { (void) snpf(Namech, Namechl, "COMMON: %s", din); Namech[Namechl - 1] = '\0'; Lf->is_com = 1; } break; } } if (!realvp) { /* * If the snode lacks a real vnode (and also lacks a common vnode), * it's original type is N_STREAM or N_REGLR, and it has a stream * pointer, get the module names. */ if ((vty == N_STREAM || vty == N_REGLR) && vs) { Lf->is_stream = 1; vty = N_STREAM; #if solaris<100000 read_mi(vs, (dev_t *)&s.s_dev, (caddr_t)&soso, &so_st, so_ad, &sdp); #else /* solaris>=100000 */ read_mi(vs, (dev_t *)&s.s_dev, NULL, NULL, NULL, &sdp); #endif /* solaris<100000 */ vs = (KA_T)NULL; } } break; #if defined(HAS_AFS) case N_AFS: if (readafsnode(va, v, &an)) return; break; #endif /* defined(HAS_AFS) */ #if solaris>=20500 case N_AUTO: # if solaris<20600 if (read_nan(va, (KA_T)v->v_data, &au)) # else /* solaris>=20600 */ if (read_nan(va, (KA_T)v->v_data, &fnn)) # endif /* solaris<20600 */ return; break; # if solaris>=100000 case N_DEV: if (read_ndvn(va, (KA_T)v->v_data, &dv, &dv_dev, &dv_devs)) return; dvs = 1; break; # endif /* solaris>=100000 */ case N_DOOR: if (read_ndn(va, (KA_T)v->v_data, &dn)) return; dns = 1; break; #endif /* solaris>=20500 */ #if defined(HASCACHEFS) case N_CACHE: if (read_ncn(va, (KA_T)v->v_data, &cn)) return; break; #endif /* defined(HASCACHEFS) */ #if solaris>=100000 case N_CTFSADIR: case N_CTFSBUND: case N_CTFSCDIR: case N_CTFSCTL: case N_CTFSEVT: case N_CTFSLATE: case N_CTFSROOT: case N_CTFSSTAT: case N_CTFSSYM: case N_CTFSTDIR: case N_CTFSTMPL: if (read_nctfsn(Ntype, va, (KA_T)v->v_data, (char *)&ctfs)) return; break; #endif /* solaris>=100000 */ #if solaris>=20600 case N_SOCK: sona = (KA_T)v->v_data; if (read_nson(va, sona, &so)) return; break; #endif /* solaris>=20600 */ case N_MNT: /* Information comes from the l_vfs structure. */ break; case N_MVFS: if (read_nmn(va, (KA_T)v->v_data, &m)) return; break; case N_NFS: if (read_nrn(va, (KA_T)v->v_data, &r)) return; break; #if solaris>=100000 case N_NFS4: if (read_nrn4(va, (KA_T)v->v_data, &r4)) return; break; #endif /* solaris>=100000 */ case N_NM: if (nns) realvp = (KA_T)nn.nm_filevp; #if defined(HASNCACHE) Lf->na = (KA_T)nn.nm_filevp; #endif /* defined(HASNCACHE) */ break; case N_FD: break; /* no successor node */ case N_FIFO: /* * Solaris FIFO vnodes are usually linked to a fifonode. One * exception is a FIFO vnode served by nm_vnodeops; it is linked * to a namenode, and the namenode points to the fifonode. * * Non-pipe fifonodes are linked to a vnode thorough fn_realvp. */ if (vty == N_NM && nns) { if (nn.nm_filevp) { if (read_nfn(va, (KA_T)nn.nm_filevp, &f)) return; realvp = (KA_T)NULL; vty = N_FIFO; } else { (void) snpf(Namech, Namechl - 1, "FIFO namenode at %s: no fifonode pointer", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; return; } } else { if (read_nfn(va, (KA_T)v->v_data, &f)) return; realvp = (KA_T)f.fn_realvp; } if (!realvp) { Lf->inode = (INODETYPE)(nns ? nn.nm_vattr.va_nodeid : f.fn_ino); #if solaris>=80000 /* Solaris 8 and above hack! */ # if defined(_LP64) if (Lf->inode >= (unsigned long)0xbaddcafebaddcafe) # else /* !defined(_LP64) */ if (Lf->inode >= (unsigned long)0xbaddcafe) # endif /* defined(_LP64) */ Lf->inp_ty = 0; else #endif /* solaris>=80000 Solaris 8 and above hack! */ Lf->inp_ty = 1; enter_dev_ch(print_kptr((KA_T)v->v_data, (char *)NULL, 0)); if (f.fn_flag & ISPIPE) { (void) snpf(tbuf, sizeof(tbuf), "PIPE"); tbufx = (int)strlen(tbuf); } else tbufx = 0; #if solaris<20500 if (f.fn_mate) { (void) snpf(&tbuf[tbufx], sizeof(tbuf) - tbufx, "->%s", print_kptr((KA_T)f.fn_mate, (char *)NULL, 0)); tbufx = (int)strlen(tbuf); } #else /* solaris>=20500 */ if (f.fn_dest) { (void) snpf(&tbuf[tbufx], sizeof(tbuf) - tbufx, "->%s", print_kptr((KA_T)f.fn_dest, (char *)NULL, 0)); tbufx = (int)strlen(tbuf); } #endif /* solaris<20500 */ if (tbufx) (void) add_nma(tbuf, tbufx); break; } break; case N_HSFS: if (read_nhn(va, (KA_T)v->v_data, &h)) return; break; case N_LOFS: llc = 0; do { rvs = 0; if (read_nln(va, llc ? (KA_T)rv.v_data : (KA_T)v->v_data, &lo)) { return; } if (!(realvp = (KA_T)lo.lo_vp)) { (void) snpf(Namech, Namechl - 1, "lnode at %s: no real vnode", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return; } if (read_nvn((KA_T)v->v_data, (KA_T)realvp, &rv)) return; rvs = 1; llc++; if ((ka = (KA_T)rv.v_vfsp) && !kread(ka, (char *)&rkv, sizeof(rkv)) && ((rfx = rkv.vfs_fstype - 1) >= 0) && (rfx < Fsinfomax) ) { rfxs = 1; } else { rfx = fx; rfxs = fxs; } if (((vty_tmp = vop2ty(&rv, rfx)) == N_LOFS) && (llc > 1000)) { (void) snpf(Namech, Namechl - 1, "lnode at %s: loop > 1000", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return; } } while (vty_tmp == N_LOFS); break; case N_PCFS: if (read_npn(va, (KA_T)v->v_data, &pc)) return; break; #if solaris>=100000 case N_PORT: if (read_nprtn(va, (KA_T)v->v_data, &pn)) return; break; #endif /* solaris>=100000 */ #if defined(HASPROCFS) case N_PROC: if (read_npi(va, v, &pids)) return; break; #endif /* defined(HASPROCFS) */ #if solaris>=110000 case N_SDEV: if (read_nsdn(va, (KA_T)v->v_data, &sdn, &sdva)) return; sdns = 1; break; #endif /* solaris>=110000 */ case N_SAMFS: (void) add_nma(SAMFS_NMA_MSG, (int)strlen(SAMFS_NMA_MSG)); break; case N_SHARED: break; /* No more sharedfs information is available. */ case N_STREAM: if (read_nsn(va, (KA_T)v->v_data, &s)) return; if (vs) { Lf->is_stream = 1; #if solaris<100000 read_mi(vs, (dev_t *)&s.s_dev, (caddr_t)&soso, &so_st, so_ad, &sdp); #else /* solaris>=100000 */ read_mi(vs, (dev_t *)&s.s_dev, NULL, NULL, NULL, &sdp); #endif /* solaris<100000 */ vs = (KA_T)NULL; } break; case N_TMP: if (read_ntn(va, (KA_T)v->v_data, &t)) return; break; #if defined(HASVXFS) case N_VXFS: if (read_vxnode(va, v, vfs, fx, &vx, Vvops)) return; break; #endif /* defined(HASVXFS) */ #if defined(HAS_ZFS) case N_ZFS: if (read_nzn(va, (KA_T)v->v_data, &zn)) return; zns = 1; break; #endif /* defined(HAS_ZFS) */ case N_REGLR: default: if (read_nin(va, (KA_T)v->v_data, &i)) return; ins = 1; } /* * If the node has a real vnode pointer, follow it. */ if (realvp) { if (rvs) { *v = rv; fx = rfx; fxs = rfxs; } else { if (read_nvn((KA_T)v->v_data, (KA_T)realvp, v)) return; else { #if defined(HASNCACHE) Lf->na = (KA_T)realvp; #endif /* defined(HASNCACHE) */ if ((ka = (KA_T)v->v_vfsp) && !kread(ka, (char *)&kv, sizeof(kv))) { kvs = 1; } if (kvs && ((fx = kv.vfs_fstype - 1) >= 0) && (fx < Fsinfomax) ) { fxs = 1; } } } /* * If the original vnode type is N_STREAM, if there is a stream * pointer and if there is no sdev_node, get the module names. */ if (vty == N_STREAM && vs && !sdns) { Lf->is_stream = 1; #if solaris<100000 read_mi(vs, (dev_t *)&s.s_dev, (caddr_t)&soso, &so_st, so_ad, &sdp); #else /* solaris>=100000 */ read_mi(vs, (dev_t *)&s.s_dev, NULL, NULL, NULL, &sdp); #endif /* solaris<100000 */ vs = (KA_T)NULL; } /* * Get the real vnode's type. */ if ((vty = vop2ty(v, fx)) < 0) { if (Ntype != N_FIFO && vs) vty = N_STREAM; else { #if solaris<100000 (void) snpf(Namech, Namechl - 1, "unknown file system type, v_op: %s", print_kptr((KA_T)v->v_op, (char *)NULL, 0)); #else /* solaris>=100000 */ (void) snpf(Namech, Namechl - 1, "unknown file system type (%s), v_op: %s", fxs ? Fsinfo[fx] : "unknown", print_kptr((KA_T)v->v_op, (char *)NULL, 0)); #endif /* solaris<100000 */ Namech[Namechl - 1] = '\0'; } } if (Ntype == N_NM || Ntype == N_AFS) Ntype = vty; /* * Base further processing on the "real" vnode. */ Lf->lock = isvlocked(v); switch (vty) { #if defined(HAS_AFS) case N_AFS: if (readafsnode(va, v, &an)) return; break; #endif /* defined(HAS_AFS) */ #if solaris>=20500 case N_AUTO: # if solaris<20600 if (read_nan(va, (KA_T)v->v_data, &au)) # else /* solaris>=20600 */ if (read_nan(va, (KA_T)v->v_data, &fnn)) # endif /* solaris<20600 */ return; break; # if solaris>=100000 case N_DEV: if (read_ndvn(va, (KA_T)v->v_data, &dv, &dv_dev, &dv_devs)) return; dvs = 1; break; # endif /* solaris>=100000 */ case N_DOOR: # if solaris<20600 if (read_ndn(realvp, (KA_T)v->v_data, &dn)) # else /* solaris>=20600 */ if (read_ndn(va, (KA_T)v->v_data, &dn)) # endif /* solaris<20500 */ return; dns = 1; break; #endif /* solaris>=20500 */ #if defined(HASCACHEFS) case N_CACHE: if (read_ncn(va, (KA_T)v->v_data, &cn)) return; break; #endif /* defined(HASCACHEFS) */ #if solaris>=100000 case N_CTFSADIR: case N_CTFSBUND: case N_CTFSCDIR: case N_CTFSCTL: case N_CTFSEVT: case N_CTFSLATE: case N_CTFSROOT: case N_CTFSSTAT: case N_CTFSSYM: case N_CTFSTDIR: case N_CTFSTMPL: if (read_nctfsn(vty, va, (KA_T)v->v_data, (char *)&ctfs)) return; break; #endif /* solaris>=100000 */ case N_HSFS: if (read_nhn(va, (KA_T)v->v_data, &h)) return; break; case N_MNT: /* Information comes from the l_vfs structure. */ break; case N_MVFS: if (read_nmn(va, (KA_T)v->v_data, &m)) return; break; case N_NFS: if (read_nrn(va, (KA_T)v->v_data, &r)) return; break; #if solaris>=100000 case N_NFS4: if (read_nrn4(va, (KA_T)v->v_data, &r4)) return; break; #endif /* solaris>=100000 */ case N_NM: if (read_nnn(va, (KA_T)v->v_data, &nn)) return; nns = 1; break; #if solaris>=100000 case N_PORT: if (read_nprtn(va, (KA_T)v->v_data, &pn)) return; break; #endif /* solaris>=100000 */ case N_PCFS: if (read_npn(va, (KA_T)v->v_data, &pc)) return; break; case N_SAMFS: (void) add_nma(SAMFS_NMA_MSG, (int)strlen(SAMFS_NMA_MSG)); #if solaris>=110000 case N_SDEV: if (read_nsdn(va, (KA_T)v->v_data, &sdn, &sdva)) return; if (Lf->is_stream) { /* * This stream's real node is an sdev_node, so it's not really * a stream. Reverse prior stream settings. */ Lf->is_stream = 0; Namech[0] = '\0'; } sdns = 1; break; #endif /* solaris>=110000 */ break; #if solaris>=20600 case N_SOCK: sona = (KA_T)v->v_data; if (read_nson(va, sona, &so)) return; break; #endif /* solaris>=20600 */ case N_STREAM: if (vs) { Lf->is_stream = 1; #if solaris<100000 read_mi(vs, (dev_t *)&s.s_dev, (caddr_t)&soso, &so_st, so_ad, &sdp); #else /* solaris>=100000 */ read_mi(vs, (dev_t *)&s.s_dev, NULL, NULL, NULL, &sdp); #endif /* solaris<100000 */ vs = (KA_T)NULL; } break; case N_TMP: if (read_ntn(va, (KA_T)v->v_data, &t)) return; break; #if defined(HASVXFS) case N_VXFS: if (read_vxnode(va, v, vfs, fx, &vx, Vvops)) return; break; #endif /* defined(HASVXFS) */ #if defined(HAS_ZFS) case N_ZFS: if (read_nzn(va, (KA_T)v->v_data, &zn)) return; zns = 1; break; #endif /* defined(HAS_ZFS) */ case N_REGLR: default: if (read_nin(va, (KA_T)v->v_data, &i)) return; ins = 1; } /* * If this is a Solaris loopback node, use the "real" node type. */ if (Ntype == N_LOFS) Ntype = vty; } /* * Get device and type for printing. */ switch (((Ntype == N_FIFO) || (vty == N_SDEV)) ? vty : Ntype) { #if defined(HAS_AFS) case N_AFS: dev = an.dev; devs = 1; break; #endif /* defined(HAS_AFS) */ #if solaris>=20500 case N_AUTO: if (kvs) { dev = (dev_t)kv.vfs_fsid.val[0]; devs = 1; } break; # if solaris>=100000 case N_DEV: if (dv_devs) { dev = dv_dev; devs = 1; } else if (vfs) { dev = vfs->dev; devs = 1; } rdev = v->v_rdev; rdevs = 1; break; # endif /* solaris>=100000 */ case N_DOOR: # if solaris<20600 if (kvs) { dev = (dev_t)kv.vfs_fsid.val[0]; devs = 1; } # else /* solaris>=20600 */ if (nns) { dev = (dev_t)nn.nm_vattr.va_fsid; devs = 1; } else if (dns) { dev = (dev_t)dn.door_index; devs = 1; } # endif /* solaris<20600 */ break; #endif /* solaris>=20500 */ #if defined(HASCACHEFS) case N_CACHE: #endif /* defined(HASCACHEFS) */ case N_HSFS: case N_PCFS: if (kvs) { dev = kv.vfs_dev; devs = 1; } break; #if solaris>=100000 case N_CTFSADIR: case N_CTFSBUND: case N_CTFSCDIR: case N_CTFSCTL: case N_CTFSEVT: case N_CTFSLATE: case N_CTFSROOT: case N_CTFSSTAT: case N_CTFSSYM: case N_CTFSTDIR: case N_CTFSTMPL: if (kvs) { dev = kv.vfs_dev; devs = 1; } break; #endif /* solaris>=100000 */ case N_FD: if (kvs) { dev = kv.vfs_dev; devs = 1; } if ((v->v_type == VCHR) || (v->v_type == VBLK)) { rdev = v->v_rdev; rdevs = 1; } break; case N_MNT: #if defined(CVFS_DEVSAVE) if (vfs) { dev = vfs->dev; devs = 1; } #endif /* defined(CVFS_DEVSAVE) */ break; case N_MVFS: #if defined(CVFS_DEVSAVE) if (vfs) { dev = vfs->dev; devs = 1; } #endif /* defined(CVFS_DEVSAVE) */ break; case N_NFS: dev = r.r_attr.va_fsid; devs = 1; break; #if solaris>=100000 case N_NFS4: dev = r4.r_attr.va_fsid; devs = 1; break; #endif /* solaris>=100000 */ case N_NM: if (nns) { dev = (dev_t)nn.nm_vattr.va_fsid; devs = 1; } else enter_dev_ch(" NMFS"); break; #if solaris>=100000 case N_PORT: if (kvs) { dev = kv.vfs_dev; devs = 1; } break; #endif /* solaris>=100000 */ #if defined(HASPROCFS) case N_PROC: if (kvs) { dev = kv.vfs_dev; devs = 1; } break; #endif /* defined(HASPROCFS) */ case N_SAMFS: if ((v->v_type == VCHR) || (v->v_type == VBLK)) { rdev = v->v_rdev; rdevs = 1; } else if (vfs) { dev = vfs->dev; devs = 1; } break; #if solaris>=110000 case N_SDEV: if (sdns) { dev = sdva.va_fsid; rdev = sdva.va_rdev; devs = rdevs = 1; } break; #endif /* solaris>=110000 */ case N_SHARED: if (vfs) { dev = vfs->dev; devs = 1; } break; #if solaris>=20600 case N_SOCK: if (so.so_family == AF_UNIX) /* * Process an AF_UNIX socket node. */ # if solaris>=110000 { /* * Process a Solaris >= 11 AF_UNIX socket node: * * Get its sotpi_info_t structure; */ if (read_nsti(&so, &sti)) return; /* * Get its device numbers. If they are located, start the NAME * column with the device name, followed by "->". */ nm = Namech; nmrl = Namechl - 1; Namech[Namechl - 1] = '\0'; if (!sdp) sdp = finddev(&DevDev, &sti.sti_dev, LOOKDEV_ALL); if (sdp) { dev = DevDev; rdev = v->v_rdev; trdev = sdp->rdev; devs = rdevs = trdevs = 1; Lf->inode = (INODETYPE)sdp->inode; Lf->inp_ty = 1; (void) snpf(nm, nmrl, "%s", sdp->name); tl = strlen(nm); nm += tl; nmrl -= tl; sep = "->"; } else { devs = rdevs = trdevs = 0; sep = ""; } /* * Add the socket node's address to the NAME column. */ sepl = strlen(sep); if (sona && ((nmrl - sepl) > 0)) { (void) snpf(nm, nmrl, "%s%s", sep, print_kptr(sona, (char *)NULL, 0)); tl = strlen(nm); nm += tl; nmrl -= tl; } /* * Add the service type to the NAME column. */ switch (sti.sti_serv_type) { case T_CLTS: ty = "dgram"; break; case T_COTS: ty = "stream"; break; case T_COTS_ORD: ty = "stream-ord"; break; default: ty = (char *)NULL; } if (ty && (nmrl > 1)) { (void) snpf(nm, nmrl, " %s", ty); tl = strlen(nm); nm += tl; nmrl -= tl; } /* * Add the vnode and connected addresses to the NAME column, * as indicated by the socket node state. */ if ((so.so_state & SS_ISBOUND) && (nmrl > 36) && (sti.sti_ux_laddr.soua_magic == SOU_MAGIC_EXPLICIT) ) { (void) snpf(nm, nmrl, " Vn=%s", print_kptr((KA_T)sti.sti_ux_laddr.soua_vp, (char *)NULL, 0) ); tl = strlen(nm); nm += tl; nmrl -= tl; } if ((so.so_state & SS_ISCONNECTED) && (nmrl > 38) && (sti.sti_ux_faddr.soua_magic == SOU_MAGIC_EXPLICIT) ) { (void) snpf(nm, nmrl, " Conn=%s ", print_kptr((KA_T)sti.sti_ux_faddr.soua_vp, (char *)NULL, 0) ); tl = strlen(nm); nm += tl; nmrl -= tl; } /* * Put local and connected UNIX addresses in the NAME column, if * they exist and as indicated by the socket node's state. */ if ((so.so_state & SS_ISBOUND) && ((len = read_nusa(&sti.sti_laddr, &ua)) > 0) && (nmrl > (len + 5)) ) { if (Sfile && is_file_named(ua.sun_path, Ntype, VSOCK, 0)) Lf->sf |= SELNM; if (len > nmrl) len = nmrl; if (len > 0) { ua.sun_path[len] = '\0'; (void) snpf(nm, nmrl, " Lcl=%s", ua.sun_path); tl = strlen(nm); nm += tl; nmrl -= tl; } } if ((so.so_state & SS_ISCONNECTED) && ((len = read_nusa(&sti.sti_faddr, &ua)) > 0) && (nmrl > (len + 5)) ) { if (Sfile && is_file_named(ua.sun_path, Ntype, VSOCK, 0)) Lf->sf |= SELNM; if (len > nmrl) len = nmrl; if (len > 0) { ua.sun_path[len] = '\0'; (void) snpf(nm, nmrl, " Rem=%s", ua.sun_path); tl = strlen(nm); nm += tl; nmrl -= tl; } } } else { /* * Process Solaris >= 11 AF_INET, AF_INET6 and AF_ROUTE VSOCK * nodes. */ switch (so.so_family) { case AF_INET: case AF_INET6: case AF_ROUTE: if (process_VSOCK((KA_T)va, v, &so)) return; } } # else /* solaris<110000 */ { /* * Process an AF_UNIX socket node for Solaris < 11: * Locate its device numbers; * Enter the sonode address as the device (netstat's local * address); * Get a non-NULL local sockaddr_un and enter it in Namech; * Get a non-NULL foreign sockaddr_un and enter it in Namech; * Check for matches on sockaddr_un.sun_path names. */ if (!sdp) sdp = finddev(&DevDev, # if solaris<100000 &so.so_vnode.v_rdev, # else /* solaris>=100000 */ &so.so_dev, # endif /* solaris<100000 */ LOOKDEV_ALL); if (sdp) { dev = DevDev; # if solaris<100000 rdev = so.so_vnode.v_rdev; # else /* solaris>=100000 */ rdev = so.so_dev; # endif /* solaris<100000 */ trdev = sdp->rdev; devs = rdevs = trdevs = 1; Lf->inode = (INODETYPE)sdp->inode; Lf->inp_ty = 1; (void) snpf(Namech, Namechl - 1, "%s", sdp->name); Namech[Namechl - 1] = '\0'; } else devs = 0; nl = snl = (int)strlen(Namech); if ((len = read_nusa(&so.so_laddr, &ua))) { if (Sfile && is_file_named(ua.sun_path, Ntype, VSOCK, 0)) Lf->sf |= SELNM; sepl = Namech[0] ? 2 : 0; if (len > (Namechl - nl - sepl - 1)) len = Namechl - nl - sepl - 1; if (len > 0) { ua.sun_path[len] = '\0'; (void) snpf(&Namech[nl], Namechl - nl, "%s%s", sepl ? "->" : "", ua.sun_path); nl += (len + sepl); } } if ((len = read_nusa(&so.so_faddr, &ua))) { if (Sfile && is_file_named(ua.sun_path, Ntype, VSOCK, 0)) Lf->sf |= SELNM; sepl = Namech[0] ? 2 : 0; if (len > (Namechl - nl - sepl - 1)) len = Namechl - nl - sepl - 1; if (len > 0) { ua.sun_path[len] = 0; (void) snpf(&Namech[nl], Namechl - nl, "%s%s", sepl ? "->" : "", ua.sun_path); nl += (len + sepl); } } if ((nl == snl) # if defined(HASSOUXSOUA) && so.so_ux_laddr.soua_magic == SOU_MAGIC_IMPLICIT # else /* !defined(HASSOUXSOUA) */ && so.so_ux_laddr.sou_magic == SOU_MAGIC_IMPLICIT # endif /* defined(HASSOUXSOUA) */ ) { /* * There are no addresses; this must be a socket pair. * Print its identity. */ pa = (struct pairaddr *)&ua; if (!(peer = (KA_T)((int)pa->p))) # if defined(HASSOUXSOUA) peer = (KA_T)so.so_ux_laddr.soua_vp; # else /* !defined(HASSOUXSOUA) */ peer = (KA_T)so.so_ux_laddr.sou_vp; # endif /* defined(HASSOUXSOUA) */ if (peer) (void) snpf(ubuf, sizeof(ubuf), "(socketpair: %s)", print_kptr(peer, (char *)NULL, 0)); else (void) snpf(ubuf, sizeof(ubuf), "(socketpair)"); len = (int)strlen(ubuf); sepl = Namech[0] ? 2 : 0; if (len > (Namechl - nl - sepl - 1)) len = Namechl - nl - sepl - 1; if (len > 0) { (void) snpf(&Namech[nl], Namechl - nl, "%s%s", sepl ? "->" : "", ubuf); nl += (len + sepl); } } /* * Add the local and foreign addresses, ala `netstat -f unix` to * the name. */ # if defined(HASSOUXSOUA) soa = (KA_T)so.so_ux_faddr.soua_vp; # else /* !defined(HASSOUXSOUA) */ soa = (KA_T)so.so_ux_faddr.sou_vp; # endif /* defined(HASSOUXSOUA) */ (void) snpf(ubuf, sizeof(ubuf), "%s(%s%s%s)", Namech[0] ? " " : "", print_kptr((KA_T)v->v_data, (char *)NULL, 0), soa ? "->" : "", soa ? print_kptr(soa, tbuf, sizeof(tbuf)) : ""); len = (int)strlen(ubuf); if (len <= (Namechl - nl - 1)) { (void) snpf(&Namech[nl], Namechl - nl, "%s", ubuf); nl += len; } /* * If there is a bound vnode, add its address to the name. */ if (so.so_ux_bound_vp) { (void) snpf(ubuf, sizeof(ubuf), "%s(Vnode=%s)", Namech[0] ? " " : "", print_kptr((KA_T)so.so_ux_bound_vp, (char *)NULL, 0)); len = (int)strlen(ubuf); if (len <= (Namechl - nl - 1)) { (void) snpf(&Namech[nl], Namechl - nl, "%s", ubuf); nl += len; } } } # endif /* solaris>=110000 */ break; #endif /* solaris>=20600 */ case N_SPEC: #if solaris<100000 if (((Ntype = vty) == N_STREAM) && so_st) { if (Funix) Lf->sf |= SELUNX; unix_sock = 1; if (so_ad[0]) { if (sdp) { if (vfs) { dev = vfs->dev; devs = 1; } rdev = sdp->rdev; rdevs = 1; Lf->inode = (INODETYPE)sdp->inode; Lf->inp_ty = 1; (void) snpf(ubuf, sizeof(ubuf), "(%s%s%s)", print_kptr(so_ad[0], (char *)NULL, 0), so_ad[1] ? "->" : "", so_ad[1] ? print_kptr(so_ad[1], tbuf, sizeof(tbuf)) : ""); } else { enter_dev_ch(print_kptr(so_ad[0], (char *)NULL, 0)); if (so_ad[1]) (void) snpf(ubuf, sizeof(ubuf), "(->%s)", print_kptr(so_ad[1], (char *)NULL, 0)); } if (!Lf->nma && (Lf->nma = (char *) malloc((int)strlen(ubuf) + 1))) { (void) snpf(Lf->nma, (int)strlen(ubuf) + 1, "%s", ubuf); } } else if (soso.lux_dev.addr.tu_addr.ino) { if (vfs) { dev = vfs->dev; devs = 1; } rdev = soso.lux_dev.addr.tu_addr.dev; rdevs = 1; } else { int dc, dl, dr; #if solaris<20400 dl = (soso.lux_dev.addr.tu_addr.dev >> 16) & 0xffff; dr = (soso.rux_dev.addr.tu_addr.dev >> 16) & 0xffff; #else /* solaris>=20400 */ dl = soso.lux_dev.addr.tu_addr.dev & 0xffff; dr = soso.rux_dev.addr.tu_addr.dev & 0xffff; #endif /* solaris<20400 */ dc = (dl << 16) | dr; enter_dev_ch(print_kptr((KA_T)dc, (char *)NULL, 0)); devs = 0; } if (soso.laddr.buf && soso.laddr.len == sizeof(ua)) { if (kread((KA_T)soso.laddr.buf, (char *)&ua, sizeof(ua)) == 0) { ua.sun_path[sizeof(ua.sun_path) - 1] = '\0'; if (ua.sun_path[0]) { if (Sfile && is_file_named(ua.sun_path, Ntype, type, 0)) Lf->sf |= SELNM; len = (int)strlen(ua.sun_path); nl = (int)strlen(Namech); sepl = Namech[0] ? 2 : 0; if (len > (Namechl - nl - sepl - 1)) len = Namechl - nl - sepl - 1; if (len > 0) { ua.sun_path[len] = '\0'; (void) snpf(&Namech[nl], Namechl - nl, "%s%s", sepl ? "->" : "", ua.sun_path); } } } } } else #endif /* solaris<100000 */ { if (vfs) { dev = vfs->dev; devs = 1; } rdev = s.s_dev; rdevs = 1; } break; case N_STREAM: if (vfs) { dev = vfs->dev; devs = 1; } rdev = s.s_dev; rdevs = 1; break; case N_TMP: dev = t.tn_attr.va_fsid; devs = 1; break; #if defined(HASVXFS) case N_VXFS: dev = vx.dev; devs = vx.dev_def; if ((v->v_type == VCHR) || (v->v_type == VBLK)) { rdev = vx.rdev; rdevs = vx.rdev_def; } break; #endif /* defined(HASVXFS) */ #if defined(HAS_ZFS) case N_ZFS: if (zns) { if (!read_nzvfs((KA_T)v->v_data, (KA_T)zn.z_zfsvfs, &zvfs) && zvfs.z_vfs && !kread((KA_T)zvfs.z_vfs, (char *)&zgvfs, sizeof(zgvfs)) ) { dev = zgvfs.vfs_dev; devs = 1; } } if ((v->v_type == VCHR) || (v->v_type == VBLK)) { rdev = v->v_rdev; rdevs = 1; } break; #endif /* defined(HAS_ZFS) */ default: if (ins) { dev = i.i_dev; devs = 1; } else if (nns) { dev = nn.nm_vattr.va_fsid; devs = 1; } else if (vfs) { dev = vfs->dev; devs = 1; } if ((v->v_type == VCHR) || (v->v_type == VBLK)) { rdev = v->v_rdev; rdevs = 1; } } type = v->v_type; if (devs && vfs && !vfs->dir) { (void) completevfs(vfs, &dev); #if defined(HAS_AFS) if (vfs->dir && (Ntype == N_AFS || vty == N_AFS) && !AFSVfsp) AFSVfsp = (KA_T)v->v_vfsp; #endif /* defined(HAS_AFS) */ } /* * Obtain the inode number. */ switch (vty) { #if defined(HAS_AFS) case N_AFS: if (an.ino_st) { Lf->inode = (INODETYPE)an.inode; Lf->inp_ty = 1; } break; #endif /* defined(HAS_AFS) */ #if solaris>=20500 case N_AUTO: # if solaris<20600 Lf->inode = (INODETYPE)au.an_nodeid; # else /* solaris>=20600 */ Lf->inode = (INODETYPE)fnn.fn_nodeid; # endif /* solaris<20600 */ Lf->inp_ty = 1; break; # if solaris>=100000 case N_DEV: if (dvs) { Lf->inode = (INODETYPE)dv.dv_ino; Lf->inp_ty = 1; } break; # endif /* solaris>=100000 */ case N_DOOR: if (nns && (Lf->inode = (INODETYPE)nn.nm_vattr.va_nodeid)) { Lf->inp_ty = 1; break; } if (dns) { if ((Lf->inode = (INODETYPE)dn.door_index)) Lf->inp_ty = 1; } break; #endif /* solaris>=20500 */ #if defined(HASCACHEFS) case N_CACHE: Lf->inode = (INODETYPE)cn.c_fileno; Lf->inp_ty = 1; break; #endif /* defined(HASCACHEFS) */ #if solaris>=100000 case N_CTFSADIR: case N_CTFSBUND: case N_CTFSCDIR: case N_CTFSCTL: case N_CTFSEVT: case N_CTFSLATE: case N_CTFSROOT: case N_CTFSSTAT: case N_CTFSSYM: case N_CTFSTDIR: case N_CTFSTMPL: /* Method of computing CTFS inode not known. */ break; #endif /* solaris>=10000 */ case N_FD: if (v->v_type == VDIR) Lf->inode = (INODETYPE)2; else Lf->inode = (INODETYPE)(GET_MIN_DEV(v->v_rdev) * 100); Lf->inp_ty = 1; break; case N_HSFS: Lf->inode = (INODETYPE)h.hs_nodeid; Lf->inp_ty = 1; break; case N_MNT: #if defined(HASFSINO) if (vfs) { Lf->inode = vfs->fs_ino; Lf->inp_ty = 1; } #endif /* defined(HASFSINO) */ break; case N_MVFS: Lf->inode = (INODETYPE)m.m_ino; Lf->inp_ty = 1; break; case N_NFS: Lf->inode = (INODETYPE)r.r_attr.va_nodeid; Lf->inp_ty = 1; break; #if solaris>=100000 case N_NFS4: Lf->inode = (INODETYPE)r4.r_attr.va_nodeid; Lf->inp_ty = 1; break; #endif /* solaris>=100000 */ case N_NM: Lf->inode = (INODETYPE)nn.nm_vattr.va_nodeid; Lf->inp_ty = 1; break; #if defined(HASPROCFS) case N_PROC: /* * The proc file system inode number is defined when the * prnode is read. */ break; #endif /* defined(HASPROCFS) */ case N_PCFS: if (kvs && kv.vfs_data && !kread((KA_T)kv.vfs_data, (char *)&pcfs, sizeof(pcfs))) { #if solaris>=70000 # if defined(HAS_PC_DIRENTPERSEC) Lf->inode = (INODETYPE)pc_makenodeid(pc.pc_eblkno, pc.pc_eoffset, pc.pc_entry.pcd_attr, IS_FAT32(&pcfs) ? ltohs(pc.pc_entry.pcd_scluster_lo) | (ltohs(pc.pc_entry.un.pcd_scluster_hi) << 16) : ltohs(pc.pc_entry.pcd_scluster_lo), pc_direntpersec(&pcfs)); # else /* !defined(HAS_PC_DIRENTPERSEC) */ Lf->inode = (INODETYPE)pc_makenodeid(pc.pc_eblkno, pc.pc_eoffset, pc.pc_entry.pcd_attr, IS_FAT32(&pcfs) ? ltohs(pc.pc_entry.pcd_scluster_lo) | (ltohs(pc.pc_entry.un.pcd_scluster_hi) << 16) : ltohs(pc.pc_entry.pcd_scluster_lo), pcfs.pcfs_entps); # endif /* defined(HAS_PC_DIRENTPERSEC) */ #else /* solaris<70000 */ Lf->inode = (INODETYPE)pc_makenodeid(pc.pc_eblkno, pc.pc_eoffset, &pc.pc_entry, pcfs.pcfs_entps); #endif /* solaris>=70000 */ Lf->inp_ty = 1; } break; case N_REGLR: if (nns) { if ((Lf->inode = (INODETYPE)nn.nm_vattr.va_nodeid)) Lf->inp_ty = 1; } else if (ins) { if ((Lf->inode = (INODETYPE)i.i_number)) Lf->inp_ty = 1; } break; case N_SAMFS: break; /* No more SAM-FS information is available. */ #if solaris>=110000 case N_SDEV: if (sdns) { Lf->inode = (INODETYPE)sdva.va_nodeid; Lf->inp_ty = 1; } break; #endif /* solaris>=110000 */ case N_SHARED: (void) snpf(Lf->iproto, sizeof(Lf->iproto), "SHARED"); Lf->inp_ty = 2; break; case N_STREAM: #if solaris<100000 if (so_st && soso.lux_dev.addr.tu_addr.ino) { if (Lf->inp_ty) { nl = Lf->nma ? (int)strlen(Lf->nma) : 0; (void) snpf(ubuf, sizeof(ubuf), "%s(Inode=%lu)", nl ? " " : "", (unsigned long)soso.lux_dev.addr.tu_addr.ino); len = nl + (int)strlen(ubuf) + 1; if (Lf->nma) Lf->nma = (char *) realloc(Lf->nma, len); else Lf->nma = (char *) malloc(len); if (Lf->nma) (void) snpf(&Lf->nma[nl], len - nl, "%s", ubuf); } else { Lf->inode = (INODETYPE)soso.lux_dev.addr.tu_addr.ino; Lf->inp_ty = 1; } } #endif /* solaris<100000 */ break; case N_TMP: Lf->inode = (INODETYPE)t.tn_attr.va_nodeid; Lf->inp_ty = 1; break; #if defined(HASVXFS) case N_VXFS: if (vx.ino_def) { Lf->inode = (INODETYPE)vx.ino; Lf->inp_ty = 1; } else if (type == VCHR) pnl = 1; break; #endif /* defined(HASVXFS) */ #if defined(HAS_ZFS) case N_ZFS: if (zns) { Lf->inode = (INODETYPE)zn.z_id; Lf->inp_ty = 1; } break; #endif /* defined(HAS_ZFS) */ } /* * Obtain the file size. */ if (Foffset) Lf->off_def = 1; else { switch (Ntype) { #if defined(HAS_AFS) case N_AFS: Lf->sz = (SZOFFTYPE)an.size; Lf->sz_def = 1; break; #endif /* defined(HAS_AFS) */ #if solaris>=20500 case N_AUTO: # if solaris<20600 Lf->sz = (SZOFFTYPE)au.an_size; # else /* solaris >=20600 */ Lf->sz = (SZOFFTYPE)fnn.fn_size; # endif /* solaris < 20600 */ Lf->sz_def = 1; break; #endif /* solaris>=20500 */ #if defined(HASCACHEFS) case N_CACHE: Lf->sz = (SZOFFTYPE)cn.c_size; Lf->sz_def = 1; break; #endif /* defined(HASCACHEFS) */ #if solaris>=100000 case N_CTFSADIR: case N_CTFSBUND: case N_CTFSCDIR: case N_CTFSCTL: case N_CTFSEVT: case N_CTFSLATE: case N_CTFSROOT: case N_CTFSSTAT: case N_CTFSSYM: case N_CTFSTDIR: case N_CTFSTMPL: /* Method of computing CTFS size not known. */ break; #endif /* solaris>=100000 */ case N_FD: if (v->v_type == VDIR) Lf->sz = (Unof + 2) * 16; else Lf->sz = (unsigned long)0; Lf->sz_def = 1; break; #if solaris>=20600 case N_SOCK: Lf->off_def = 1; break; #endif /* solaris>=20600 */ case N_HSFS: Lf->sz = (SZOFFTYPE)h.hs_dirent.ext_size; Lf->sz_def = 1; break; case N_NM: Lf->sz = (SZOFFTYPE)nn.nm_vattr.va_size; Lf->sz_def = 1; break; # if solaris>=100000 case N_DEV: if (!Fsize) Lf->off_def = 1; break; # endif /* solaris>=100000 */ case N_DOOR: case N_FIFO: if (!Fsize) Lf->off_def = 1; break; case N_MNT: #if defined(CVFS_SZSAVE) if (vfs) { Lf->sz = (SZOFFTYPE)vfs->size; Lf->sz_def = 1; } else #endif /* defined(CVFS_SZSAVE) */ Lf->off_def = 1; break; case N_MVFS: /* The location of file size isn't known. */ break; case N_NFS: if ((type == VCHR || type == VBLK) && !Fsize) Lf->off_def = 1; else { Lf->sz = (SZOFFTYPE)r.r_size; Lf->sz_def = 1; } break; #if solaris>=100000 case N_NFS4: if ((type == VCHR || type == VBLK) && !Fsize) Lf->off_def = 1; else { Lf->sz = (SZOFFTYPE)r4.r_size; Lf->sz_def = 1; } break; #endif /* solaris>=100000 */ case N_PCFS: Lf->sz = (SZOFFTYPE)pc.pc_size; Lf->sz_def = 1; break; #if solaris>=100000 case N_PORT: Lf->sz = (SZOFFTYPE)pn.port_curr; Lf->sz_def = 1; break; #endif /* solaris>=100000 */ #if defined(HASPROCFS) case N_PROC: /* * The proc file system size is defined when the * prnode is read. */ break; #endif /* defined(HASPROCFS) */ case N_REGLR: if (type == VREG || type == VDIR) { if (ins | nns) { Lf->sz = (SZOFFTYPE)(nns ? nn.nm_vattr.va_size : i.i_size); Lf->sz_def = 1; } } else if ((type == VCHR || type == VBLK) && !Fsize) Lf->off_def = 1; break; #if solaris>=110000 case N_SDEV: if (sdns) { if (type == VREG || type == VDIR) { Lf->sz = (SZOFFTYPE)sdva.va_size; Lf->sz_def = 1; } else if ((type == VCHR || type == VBLK) && !Fsize) Lf->off_def = 1; } break; #endif /* solaris>=110000 */ case N_SAMFS: break; /* No more SAM-FS information is available. */ case N_SHARED: break; /* No more sharedfs information is available. */ case N_STREAM: if (!Fsize) Lf->off_def = 1; break; case N_TMP: Lf->sz = (SZOFFTYPE)t.tn_attr.va_size; Lf->sz_def = 1; break; #if defined(HASVXFS) case N_VXFS: if (type == VREG || type == VDIR) { Lf->sz = (SZOFFTYPE)vx.sz; Lf->sz_def = vx.sz_def; } else if ((type == VCHR || type == VBLK) && !Fsize) Lf->off_def = 1; break; #endif /* defined(HASVXFS) */ #if defined(HAS_ZFS) case N_ZFS: if (zns) { if (type == VREG || type == VDIR) { Lf->sz = (SZOFFTYPE)zn.z_size; Lf->sz_def = 1; } else if ((type == VCHR || type == VBLK) && !Fsize) Lf->off_def = 1; } break; #endif /* defined(HAS_ZFS) */ } } /* * Record link count. */ #if !defined(HASXOPT) if (Fnlink) #endif /* !defined(HASXOPT) */ { switch (Ntype) { #if defined(HAS_AFS) case N_AFS: Lf->nlink = an.nlink; Lf->nlink_def = an.nlink_st; break; #endif /* defined(HAS_AFS) */ #if solaris>=20500 case N_AUTO: break; # if defined(HASCACHEFS) case N_CACHE: Lf->nlink = (long)cn.c_attr.va_nlink; Lf->nlink_def = 1; break; # endif /* defined(HASCACHEFS) */ #endif /* solaris>=20500 */ #if solaris>=100000 case N_CTFSADIR: case N_CTFSBUND: case N_CTFSCDIR: case N_CTFSCTL: case N_CTFSEVT: case N_CTFSLATE: case N_CTFSROOT: case N_CTFSSTAT: case N_CTFSSYM: case N_CTFSTDIR: case N_CTFSTMPL: /* Method of computing CTFS link count not known. */ break; #endif /* solaris>=100000 */ case N_FD: Lf->nlink = (v->v_type == VDIR) ? 2 : 1; Lf->nlink_def = 1; break; #if solaris>=20600 case N_SOCK: /* no link count */ break; #endif /* solaris>=20600 */ case N_HSFS: Lf->nlink = (long)h.hs_dirent.nlink; Lf->nlink_def = 1; break; case N_NM: Lf->nlink = (long)nn.nm_vattr.va_nlink; Lf->nlink_def = 1; break; # if solaris>=100000 case N_DEV: if (dvs) { Lf->nlink = (long)dv.dv_nlink; Lf->nlink_def = 1; } break; # endif /* solaris>=100000 */ case N_DOOR: Lf->nlink = (long)v->v_count; Lf->nlink_def = 1; break; case N_FIFO: break; case N_MNT: #if defined(CVFS_NLKSAVE) if (vfs) { Lf->nlink = (long)vfs->nlink; Lf->nlink_def = 1; } #endif /* defined(CVFS_NLKSAVE) */ break; case N_MVFS: /* no link count */ break; case N_NFS: Lf->nlink = (long)r.r_attr.va_nlink; Lf->nlink_def = 1; break; #if solaris>=100000 case N_NFS4: Lf->nlink = (long)r4.r_attr.va_nlink; Lf->nlink_def = 1; break; #endif /* solaris>=100000 */ case N_PCFS: break; #if defined(HASPROCFS) case N_PROC: break; #endif /* defined(HASPROCFS) */ case N_REGLR: if (ins) { Lf->nlink = (long)i.i_nlink; Lf->nlink_def = 1; } break; case N_SAMFS: break; /* No more SAM-FS information is available. */ #if solaris>=110000 case N_SDEV: if (sdns) { Lf->nlink = (long)sdva.va_nlink; Lf->nlink_def = 1; } break; #endif /* solaris>=110000 */ case N_SHARED: break; /* No more sharedfs information is available. */ case N_STREAM: break; case N_TMP: Lf->nlink = (long)t.tn_attr.va_nlink; Lf->nlink_def = 1; break; #if defined(HASVXFS) case N_VXFS: Lf->nlink = vx.nl; Lf->nlink_def = vx.nl_def; break; #endif /* defined(HASVXFS) */ #if defined(HAS_ZFS) case N_ZFS: if (zns) { Lf->nlink = (long)MIN(zn.z_links, UINT32_MAX); Lf->nlink_def = 1; } break; #endif /* defined(HAS_ZFS) */ } if (Nlink && Lf->nlink_def && (Lf->nlink < Nlink)) Lf->sf |= SELNLINK; } #if defined(HASVXFS) /* * Record a VxFS file. */ # if defined(HASVXFSDNLC) Lf->is_vxfs = (Ntype == N_VXFS) ? 1 : 0; # endif /* defined(HASVXFSDNLC) */ #endif /* defined(HASVXFS) */ /* * Record an NFS selection. */ if (Fnfs) { if ((Ntype == N_NFS) || (Ntype == N_NFS4)) Lf->sf |= SELNFS; } #if solaris>=20500 /* * If this is a Solaris 2.5 and greater autofs entry, save the autonode name * (less than Solaris 2.6) or fnnode name (Solaris 2.6 and greater). */ if (Ntype == N_AUTO && !Namech[0]) { # if solaris<20600 if (au.an_name[0]) (void) snpf(Namech, Namechl - 1, "%s", au.an_name); Namech[Namechl - 1] = '\0'; # else /* solaris>=20600 */ if (fnn.fn_name && (len = fnn.fn_namelen) > 0 && len < (Namechl - 1)) { if (kread((KA_T)fnn.fn_name, Namech, len)) Namech[0] = '\0'; else Namech[len] = '\0'; } # endif /* solaris<20600 */ } /* * If there is no local virtual file system pointer, or if its directory and * file system names are NULL, and if there is a namenode, and if we're using * the device number from it, see if its nm_mountpt vnode pointer leads to a * local virtual file system structure with non-NULL directory and file system * names. If it does, switch to that local virtual file system pointer. */ if (nns && (!vfs || (!vfs->dir && !vfs->fsname)) && devs && (dev == nn.nm_vattr.va_fsid) && nn.nm_mountpt) { if (!readvnode((KA_T)nn.nm_mountpt, &fv) && fv.v_vfsp) { if ((nvfs = readvfs((KA_T)fv.v_vfsp, (struct vfs *)NULL, nn.nm_filevp)) && !nvfs->dir) { (void) completevfs(nvfs, &dev); } # if defined(HASNCACHE) if (nvfs && nvfs->dir && nvfs->fsname) { fa = (char *)NULL; vfs = nvfs; } # endif /* defined(HASNCACHE) */ } } # if defined(HASNCACHE) /* * If there's a namenode and its device and node number match this one, * use the nm_mountpt's address for name cache lookups. */ if (nns && devs && (dev == nn.nm_vattr.va_fsid) && (Lf->inp_ty == 1) && (Lf->inode == (INODETYPE)nn.nm_vattr.va_nodeid)) Lf->na = (KA_T)nn.nm_mountpt; # endif /* defined(HASNCACHE) */ #endif /* solaris>=20500 */ /* * Save the file system names. */ if (vfs) { Lf->fsdir = vfs->dir; Lf->fsdev = vfs->fsname; #if defined(HASMNTSTAT) Lf->mnt_stat = vfs->mnt_stat; #endif /* defined(HASMNTSTAT) */ if (!Lf->fsdir && !Lf->fsdev && kvs && fxs) { /* * The file system names are unknown. * * Set the file system device to the file system type and clear * the doubtful device numbers. */ Lf->fsdev = Fsinfo[fx]; devs = 0; rdevs = 0; } #if defined(HASFSINO) else Lf->fs_ino = vfs->fs_ino; #endif /* defined(HASFSINO) */ } /* * Save the device numbers, and their states. * * Format the vnode type, and possibly the device name. */ switch (type) { case VNON: ty ="VNON"; Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; break; case VREG: case VDIR: ty = (type == VREG) ? "VREG" : "VDIR"; Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; break; case VBLK: ty = "VBLK"; Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; Ntype = N_BLK; break; case VCHR: Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; if (unix_sock) { ty = "unix"; break; } ty = "VCHR"; if (Lf->is_stream == 0 && Lf->is_com == 0) Ntype = N_CHR; break; #if solaris>=20500 case VDOOR: Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; ty = "DOOR"; if (dns) (void) idoorkeep(&dn); break; #endif /* solaris>=20500 */ case VLNK: ty = "VLNK"; Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; break; #if solaris>=100000 case VPORT: ty = "PORT"; Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; break; #endif /* solaris>=100000 */ #if solaris>=20600 case VPROC: /* * The proc file system type is defined when the prnode is read. */ Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; ty = (char *)NULL; break; #endif /* solaris>=20600 */ #if defined(HAS_VSOCK) case VSOCK: # if solaris>=20600 if (so.so_family == AF_UNIX) { ty = "unix"; if (Funix) Lf->sf |= SELUNX; } else { if (so.so_family == AF_INET) { # if defined(HASIPv6) ty = "IPv4"; # else /* !defined(HASIPv6) */ ty = "inet"; # endif /* defined(HASIPv6) */ (void) snpf(Namech, Namechl - 1, printsockty(so.so_type)); Namech[Namechl - 1] = '\0'; if (TcpStIn || UdpStIn || TcpStXn || UdpStXn) Lf->sf |= SELEXCLF; else if (Fnet && (FnetTy != 6)) Lf->sf |= SELNET; } # if defined(HASIPv6) else if (so.so_family == AF_INET6) { ty = "IPv6"; (void) snpf(Namech, Namechl - 1, printsockty(so.so_type)); Namech[Namechl - 1] = '\0'; if (TcpStIn || UdpStIn || TcpStXn || UdpStXn) Lf->sf |= SELEXCLF; else if (Fnet && (FnetTy != 4)) Lf->sf |= SELNET; } # endif /* defined(HASIPv6) */ else { ty = "sock"; (void) printunkaf(so.so_family, 0); ep = endnm(&sz); (void) snpf(ep, sz, ", %s", printsockty(so.so_type)); } } # endif /* solaris>=20600 */ Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; break; #endif /* defined(HAS_VSOCK) */ case VBAD: ty = "VBAD"; Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; break; case VFIFO: ty = "FIFO"; if (!Lf->dev_ch || Lf->dev_ch[0] == '\0') { Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; } break; default: Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; (void) snpf(Lf->type, sizeof(Lf->type), "%04o", (type & 0xfff)); ty = (char *)NULL; } if (ty) (void) snpf(Lf->type, sizeof(Lf->type), "%s", ty); Lf->ntype = Ntype; /* * If this a Solaris common vnode/snode void some information. */ if (Lf->is_com) Lf->sz_def = Lf->inp_ty = 0; /* * If a file attach description remains, put it in the NAME column addition. */ if (fa) (void) add_nma(fa, fal); #if defined(HASBLKDEV) /* * If this is a VBLK file and it's missing an inode number, try to * supply one. */ if ((Lf->inp_ty == 0) && (type == VBLK)) find_bl_ino(); #endif /* defined(HASBLKDEV) */ /* * If this is a VCHR file and it's missing an inode number, try to * supply one. */ if ((Lf->inp_ty == 0) && (type == VCHR)) { find_ch_ino(); /* * If the VCHR inode number still isn't known and this is a COMMON * vnode file or a stream, or if a pseudo node ID lookup has been * requested, see if an inode number can be derived from a pseudo * or clone device node. * * If it can, save the pseudo or clone device for temporary * use when searching for a match with a named file argument. */ if ((Lf->inp_ty == 0) && (Lf->is_com || Lf->is_stream || pnl) && (Clone || Pseudo)) { if (!sdp) { if (rdevs || devs) { if (Lf->is_stream && !pnl) sdp = finddev(devs ? &dev : &DevDev, rdevs ? &rdev : &Lf->dev, LOOKDEV_CLONE); else sdp = finddev(devs ? &dev : &DevDev, rdevs ? &rdev : &Lf->dev, LOOKDEV_PSEUDO); if (!sdp) sdp = finddev(devs ? &dev : &DevDev, rdevs ? &rdev : &Lf->dev, LOOKDEV_ALL); if (sdp) { if (!rdevs) { Lf->rdev = Lf->dev; Lf->rdev_def = rdevs = 1; } if (!devs) { Lf->dev = DevDev; devs = Lf->dev_def = 1; } } } } else { /* * A local device structure has been located. Make sure * that it's accompanied by device settings. */ if (!devs && vfs) { dev = Lf->dev = vfs->dev; devs = Lf->dev_def = 1; } if (!rdevs) { Lf->rdev = rdev = sdp->rdev; Lf->rdev_def = rdevs = 1; } } if (sdp) { /* * Process the local device information. */ trdev = sdp->rdev; Lf->inode = sdp->inode; Lf->inp_ty = trdevs = 1; if (!Namech[0] || Lf->is_com) { (void) snpf(Namech, Namechl - 1, "%s", sdp->name); Namech[Namechl - 1] = '\0'; } if (Lf->is_com && !Lf->nma) { len = (int)strlen("(COMMON)") + 1; if (!(Lf->nma = (char *) malloc(len))) { (void) fprintf(stderr, "%s: no space for (COMMON): PID %d; FD %s\n", Pn, Lp->pid, Lf->fd); Exit(1); } (void) snpf(Lf->nma, len, "(COMMON)"); } } } } /* * Record stream status. */ if (Lf->inp_ty == 0 && Lf->is_stream && strcmp(Lf->iproto, "STR") == 0) Lf->inp_ty = 2; /* * Test for specified file. */ #if defined(HASPROCFS) if (Ntype == N_PROC) { if (Procsrch) { Procfind = 1; Lf->sf |= SELNM; } else { for (pfi = Procfsid; pfi; pfi = pfi->next) { if ((pfi->pid && pfi->pid == pids.pid_id) # if defined(HASPINODEN) || (Lf->inp_ty == 1 && Lf->inode == pfi->inode) # endif /* defined(HASPINODEN) */ ) { pfi->f = 1; if (!Namech[0]) { (void) snpf(Namech, Namechl - 1, "%s", pfi->nm); Namech[Namechl - 1] = '\0'; } Lf->sf |= SELNM; break; } } } } else #endif /* defined(HASPROCFS) */ { if (Sfile) { if (trdevs) { rdev = Lf->rdev; Lf->rdev = trdev; tdef = Lf->rdev_def; Lf->rdev_def = 1; } if (is_file_named(NULL, Ntype, type, 1)) Lf->sf |= SELNM; if (trdevs) { Lf->rdev = rdev; Lf->rdev_def = tdef; } } } /* * Enter name characters. */ if (Namech[0]) enter_nm(Namech); } /* * read_cni() - read common snode information */ static int read_cni(s, rv, v, rs, di, din, dinl) struct snode *s; /* starting snode */ struct vnode *rv; /* "real" vnode receiver */ struct vnode *v; /* starting vnode */ struct snode *rs; /* "real" snode receiver */ struct dev_info *di; /* dev_info structure receiver */ char *din; /* device info name receiver */ int dinl; /* sizeof(*din) */ { char tbuf[32]; if (read_nvn((KA_T)v->v_data, (KA_T)s->s_commonvp, rv)) return(1); if (read_nsn((KA_T)s->s_commonvp, (KA_T)rv->v_data, rs)) return(1); *din = '\0'; if (rs->s_dip) { if (kread((KA_T)rs->s_dip, (char *)di, sizeof(struct dev_info))) { (void) snpf(Namech, Namechl - 1, "common snode at %s: no dev info: %s", print_kptr((KA_T)rv->v_data, tbuf, sizeof(tbuf)), print_kptr((KA_T)rs->s_dip, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } if (di->devi_name && kread((KA_T)di->devi_name, din, dinl-1) == 0) din[dinl-1] = '\0'; } return(0); } /* * readinode() - read inode */ static int readinode(ia, i) KA_T ia; /* inode kernel address */ struct inode *i; /* inode buffer */ { if (kread((KA_T)ia, (char *)i, sizeof(struct inode))) { (void) snpf(Namech, Namechl - 1, "can't read inode at %s", print_kptr((KA_T)ia, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } return(0); } #if solaris>=20500 /* * read_ndn() - read node's door node */ static int read_ndn(na, da, dn) KA_T na; /* containing vnode's address */ KA_T da; /* door node's address */ struct door_node *dn; /* door node receiver */ { char tbuf[32]; if (!da || kread((KA_T)da, (char *)dn, sizeof(struct door_node))) { (void) snpf(Namech, Namechl - 1, "vnode at %s: can't read door_node: %s", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr(da, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } return(0); } #endif /* solaris>=20500 */ /* * read_mi() - read stream's module information */ static void read_mi(s, rdev, so, so_st, so_ad, sdp) KA_T s; /* kernel stream pointer address */ dev_t *rdev; /* raw device pointer */ caddr_t so; /* so_so return (Solaris) */ int *so_st; /* so_so status */ KA_T *so_ad; /* so_so addresses */ struct l_dev **sdp; /* returned device pointer */ { struct l_dev *dp; int i, j, k, nl; KA_T ka; struct module_info mi; char mn[STRNML]; struct stdata sd; struct queue q; struct qinit qi; KA_T qp; /* * If there is no stream pointer, or we can't read the stream head, * return. */ if (!s) return; if (kread((KA_T)s, (char *)&sd, sizeof(sd))) { (void) snpf(Namech, Namechl - 1, "can't read stream head: %s", print_kptr(s, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return; } /* * Follow the stream head to each of its queue structures, retrieving the * module names from each queue's q_info->qi_minfo->mi_idname chain of * structures. Separate each additional name from the previous one with * "->". * * Ignore failures to read all but queue structure chain entries. * * Ignore module names that end in "head". */ k = 0; Namech[0] = '\0'; if (!(dp = finddev(&DevDev, rdev, LOOKDEV_CLONE))) dp = finddev(&DevDev, rdev, LOOKDEV_ALL); if (dp) { (void) snpf(Namech, Namechl - 1, "%s", dp->name); Namech[Namechl - 1] = '\0'; k = (int)strlen(Namech); *sdp = dp; } else (void) snpf(Lf->iproto, sizeof(Lf->iproto), "STR"); nl = sizeof(mn) - 1; mn[nl] = '\0'; qp = (KA_T)sd.sd_wrq; for (i = 0; qp && i < 20; i++, qp = (KA_T)q.q_next) { if (!qp || kread(qp, (char *)&q, sizeof(q))) break; if ((ka = (KA_T)q.q_qinfo) == (KA_T)NULL || kread(ka, (char *)&qi, sizeof(qi))) continue; if ((ka = (KA_T)qi.qi_minfo) == (KA_T)NULL || kread(ka, (char *)&mi, sizeof(mi))) continue; if ((ka = (KA_T)mi.mi_idname) == (KA_T)NULL || kread(ka, mn, nl)) continue; if ((j = (int)strlen(mn)) < 1) continue; if (j >= 4 && strcmp(&mn[j - 4], "head") == 0) continue; #if solaris<100000 if (strcmp(mn, "sockmod") == 0) { /* * Save the Solaris sockmod device and inode numbers. */ if (so) { struct so_so s; if (!kread((KA_T)q.q_ptr, (char *)&s, sizeof(s))) { if (!(*so_st)) so_ad[0] = (KA_T)q.q_ptr; else so_ad[1] = (KA_T)q.q_ptr; (void) savesockmod(&s, (struct so_so *)so, so_st); } } } #endif /* solaris<100000 */ if (k) { if ((k + 2) > (Namechl - 1)) break; (void) snpf(&Namech[k], Namechl - k, "->"); k += 2; } if ((k + j) > (Namechl - 1)) break; (void) snpf(&Namech[k], Namechl - k, "%s", mn); k += j; } } #if solaris>=20500 /* * read_nan(na, ca, cn) - read node's autofs node */ static int read_nan(na, aa, rn) KA_T na; /* containing node's address */ KA_T aa; /* autofs node address */ # if solaris<20600 struct autonode *rn; /* autofs node receiver */ # else /* solaris>=20600 */ struct fnnode *rn; /* autofs node receiver */ # endif /* solaris<20600 */ { char tbuf[32]; # if solaris<20600 if (!aa || kread((KA_T)aa, (char *)rn, sizeof(struct autonode))) # else /* solaris>=20600 */ if (!aa || kread((KA_T)aa, (char *)rn, sizeof(struct fnnode))) # endif /* solaris<20600 */ { (void) snpf(Namech, Namechl - 1, # if solaris<20600 "node at %s: can't read autonode: %s", # else /* solaris>=20600 */ "node at %s: can't read fnnode: %s", # endif /* solaris<20600 */ print_kptr(na, tbuf, sizeof(tbuf)), print_kptr(aa, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } return(0); } #endif /* solaris>=20500 */ #if defined(HASCACHEFS) /* * read_ncn(na, ca, cn) - read node's cache node */ static int read_ncn(na, ca, cn) KA_T na; /* containing node's address */ KA_T ca; /* cache node address */ struct cnode *cn; /* cache node receiver */ { char tbuf[32]; if (!ca || kread((KA_T)ca, (char *)cn, sizeof(struct cnode))) { (void) snpf(Namech, Namechl - 1, "node at %s: can't read cnode: %s", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr(ca, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } return(0); } #endif /* defined(HASCACHEFS) */ #if solaris>=100000 /* * read_nctfsn(ty, na, ca, cn) - read node's cache node */ static int read_nctfsn(ty, na, ca, cn) int ty; /* node type -- i.e., N_CTFS* */ KA_T na; /* containing node's address */ KA_T ca; /* cache node address */ char *cn; /* CTFS node receiver */ { char *cp, *nm, tbuf[32]; READLEN_T sz; switch (ty) { case N_CTFSADIR: nm = "ADIR"; sz = (READLEN_T)sizeof(ctfs_adirnode_t); break; case N_CTFSBUND: nm = "BUND"; sz = (READLEN_T)sizeof(ctfs_bunode_t); break; case N_CTFSCDIR: nm = "CDIR"; sz = (READLEN_T)sizeof(ctfs_cdirnode_t); break; case N_CTFSCTL: nm = "CTL"; sz = (READLEN_T)sizeof(ctfs_ctlnode_t); break; case N_CTFSEVT: nm = "EVT"; sz = (READLEN_T)sizeof(ctfs_evnode_t); break; case N_CTFSLATE: nm = "LATE"; sz = (READLEN_T)sizeof(ctfs_latenode_t); break; case N_CTFSROOT: nm = "ROOT"; sz = (READLEN_T)sizeof(ctfs_rootnode_t); break; case N_CTFSSTAT: nm = "STAT"; sz = (READLEN_T)sizeof(ctfs_ctlnode_t); break; case N_CTFSSYM: nm = "SYM"; sz = (READLEN_T)sizeof(ctfs_symnode_t); break; case N_CTFSTDIR: nm = "TDIR"; sz = (READLEN_T)sizeof(ctfs_tdirnode_t); break; case N_CTFSTMPL: nm = "TMPL"; sz = (READLEN_T)sizeof(ctfs_tmplnode_t); break; default: (void) snpf(Namech, Namechl - 1, "unknown CTFS node type: %d", ty); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } if (!ca || kread((KA_T)ca, cn, sz)) { (void) snpf(Namech, Namechl - 1, "node at %s: can't read CTFS %s node: %s", print_kptr(na, tbuf, sizeof(tbuf)), nm, print_kptr(ca, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } return(0); } #endif /* solaris>=100000 */ /* * read_nfn() - read node's fifonode */ static int read_nfn(na, fa, f) KA_T na; /* containing node's address */ KA_T fa; /* fifonode address */ struct fifonode *f; /* fifonode receiver */ { char tbuf[32]; if (!fa || readfifonode(fa, f)) { (void) snpf(Namech, Namechl - 1, "node at %s: can't read fifonode: %s", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr(fa, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } return(0); } /* * read_nhn() - read node's High Sierra node */ static int read_nhn(na, ha, h) KA_T na; /* containing node's address */ KA_T ha; /* hsnode address */ struct hsnode *h; /* hsnode receiver */ { char tbuf[32]; if (!ha || readhsnode(ha, h)) { (void) snpf(Namech, Namechl - 1, "node at %s: can't read hsnode: %s", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr(ha, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } return(0); } /* * read_nin() - read node's inode */ static int read_nin(na, ia, i) KA_T na; /* containing node's address */ KA_T ia; /* kernel inode address */ struct inode *i; /* inode receiver */ { char tbuf[32]; if (!ia || readinode(ia, i)) { (void) snpf(Namech, Namechl - 1, "node at %s: can't read inode: %s", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr(ia, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } return(0); } /* * read_nln(na, la, ln) - read node's loopback node */ static int read_nln(na, la, ln) KA_T na; /* containing node's address */ KA_T la; /* loopback node address */ struct lnode *ln; /* loopback node receiver */ { char tbuf[32]; if (!la || kread((KA_T)la, (char *)ln, sizeof(struct lnode))) { (void) snpf(Namech, Namechl - 1, "node at %s: can't read lnode: %s", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr(la, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } return(0); } /* * read_nnn() - read node's namenode */ static int read_nnn(na, nna, nn) KA_T na; /* containing node's address */ KA_T nna; /* namenode address */ struct namenode *nn; /* namenode receiver */ { char tbuf[32]; if (!nna || kread((KA_T)nna, (char *)nn, sizeof(struct namenode))) { (void) snpf(Namech, Namechl - 1, "node at %s: can't read namenode: %s", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr(nna, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } return(0); } /* * read_nmn() - read node's mvfsnode */ static int read_nmn(na, ma, m) KA_T na; /* containing node's address */ KA_T ma; /* kernel mvfsnode address */ struct mvfsnode *m; /* mvfsnode receiver */ { char tbuf[32]; if (!ma || kread((KA_T)ma, (char *)m, sizeof(struct mvfsnode))) { (void) snpf(Namech, Namechl - 1, "node at %s: can't read mvfsnode: %s", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr(ma, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } return(0); } #if defined(HASPROCFS) /* * read_npi() - read node's /proc file system information */ static int read_npi(na, v, pids) KA_T na; /* containing node's address */ struct vnode *v; /* containing vnode */ struct pid *pids; /* pid structure receiver */ { struct as as; struct proc p; struct prnode pr; char tbuf[32]; #if solaris>=20600 prcommon_t pc, ppc; int pcs, ppcs, prpcs, prppcs; struct proc pp; pid_t prpid; id_t prtid; char *ty = (char *)NULL; #endif /* solaris>=20600 */ if (!v->v_data || kread((KA_T)v->v_data, (char *)&pr, sizeof(pr))) { (void) snpf(Namech, Namechl - 1, "node at %s: can't read prnode: %s", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr((KA_T)v->v_data, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } #if solaris<20600 /* * For Solaris < 2.6: * * Read the proc structure, get the process size and PID; * * Return the PID; * * Enter a name, constructed from the file system and PID; * * Enter an inode number, constructed from the PID. */ if (!pr.pr_proc) { if (v->v_type == VDIR) { (void) snpf(Namech, Namechl - 1, "/%s", HASPROCFS); Namech[Namechl - 1] = '\0'; enter_nm(Namech); Lf->inode = (INODETYPE)PR_ROOTINO; Lf->inp_ty = 1; } else { (void) snpf(Namech, Namechl - 1, "/%s/", HASPROCFS); Namech[Namechl - 1] = '\0'; enter_nm(Namech); Lf->inp_ty = 0; } return(0); } if (kread((KA_T)pr.pr_proc, (char *)&p, sizeof(p))) { (void) snpf(Namech, Namechl - 1, "prnode at %s: can't read proc: %s", print_kptr((KA_T)v->v_data, tbuf, sizeof(tbuf)), print_kptr((KA_T)pr.pr_proc, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } if (p.p_as && !kread((KA_T)p.p_as, (char *)&as, sizeof(as))) { Lf->sz = (SZOFFTYPE)as.a_size; Lf->sz_def = 1; } if (!p.p_pidp || kread((KA_T)p.p_pidp, (char *)pids, sizeof(struct pid))) { (void) snpf(Namech, Namechl - 1, "proc struct at %s: can't read pid: %s", print_kptr((KA_T)pr.pr_proc, tbuf, sizeof(tbuf)), print_kptr((KA_T)p.p_pidp, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } (void) snpf(Namech, Namechl, "/%s/%d", HASPROCFS, (int)pids->pid_id); Namech[Namechl - 1] = '\0'; Lf->inode = (INODETYPE)ptoi(pids->pid_id); Lf->inp_ty = 1; #else /* solaris>=20600 */ /* * Enter the >= Solaris 2.6 inode number. */ Lf->inode = (INODETYPE)pr.pr_ino; Lf->inp_ty = 1; /* * Read the >= Solaris 2.6 prnode common structures. * * Return the PID number. * * Identify the lwp PID (the thread ID). */ if (pr.pr_common && kread((KA_T)pr.pr_common, (char *)&pc, sizeof(pc)) == 0) { pcs = 1; if (pc.prc_proc && kread((KA_T)pc.prc_proc, (char *)&p, sizeof(p)) == 0) prpcs = 1; else prpcs = 0; } else pcs = prpcs = 0; if (pr.pr_pcommon && kread((KA_T)pr.pr_pcommon, (char *)&ppc, sizeof(ppc)) == 0) { ppcs = 1; if (ppc.prc_proc && kread((KA_T)ppc.prc_proc, (char *)&pp, sizeof(pp)) == 0) prppcs = 1; else prppcs = 0; } else ppcs = prppcs = 0; if (pcs && pc.prc_pid) pids->pid_id = prpid = pc.prc_pid; else if (ppcs && ppc.prc_pid) pids->pid_id = prpid = ppc.prc_pid; else pids->pid_id = prpid = (pid_t)0; if (pcs && pc.prc_tid) prtid = pc.prc_tid; else if (ppcs && ppc.prc_tid) prtid = ppc.prc_tid; else prtid = (id_t)0; /* * Identify the Solaris 2.6 /proc file system name, file size, and file type. */ switch (pr.pr_type) { case PR_PROCDIR: (void) snpf(Namech, Namechl - 1, "/%s", HASPROCFS); ty = "PDIR"; break; case PR_PIDDIR: (void) snpf(Namech, Namechl - 1, "/%s/%d", HASPROCFS, (int)prpid); ty = "PDIR"; break; case PR_AS: (void) snpf(Namech, Namechl - 1, "/%s/%d/as", HASPROCFS, (int)prpid); ty = "PAS"; if (prpcs && kread((KA_T)pc.prc_proc, (char *)&p, sizeof(p)) == 0 && p.p_as && kread((KA_T)p.p_as, (char *)&as, sizeof(as)) == 0) { Lf->sz = (SZOFFTYPE)as.a_size; Lf->sz_def = 1; } break; case PR_CTL: (void) snpf(Namech, Namechl - 1, "/%s/%d/ctl", HASPROCFS, (int)prpid); ty = "PCTL"; break; case PR_STATUS: (void) snpf(Namech, Namechl - 1, "/%s/%d/status", HASPROCFS, (int)prpid); ty = "PSTA"; break; case PR_LSTATUS: (void) snpf(Namech, Namechl - 1, "/%s/%d/lstatus", HASPROCFS, (int)prpid); ty = "PLST"; break; case PR_PSINFO: (void) snpf(Namech, Namechl - 1, "/%s/%d/psinfo", HASPROCFS, (int)prpid); ty = "PSIN"; break; case PR_LPSINFO: (void) snpf(Namech, Namechl - 1, "/%s/%d/lpsinfo", HASPROCFS, (int)prpid); ty = "PLPI"; break; case PR_MAP: (void) snpf(Namech, Namechl - 1, "/%s/%d/map", HASPROCFS, (int)prpid); ty = "PMAP"; break; case PR_RMAP: (void) snpf(Namech, Namechl - 1, "/%s/%d/rmap", HASPROCFS, (int)prpid); ty = "PRMP"; break; case PR_XMAP: (void) snpf(Namech, Namechl - 1, "/%s/%d/xmap", HASPROCFS, (int)prpid); ty = "PXMP"; break; case PR_CRED: (void) snpf(Namech, Namechl - 1, "/%s/%d/cred", HASPROCFS, (int)prpid); ty = "PCRE"; break; case PR_SIGACT: (void) snpf(Namech, Namechl - 1, "/%s/%d/sigact", HASPROCFS, (int)prpid); ty = "PSGA"; break; case PR_AUXV: (void) snpf(Namech, Namechl - 1, "/%s/%d/auxv", HASPROCFS, (int)prpid); ty = "PAXV"; break; # if defined(HASPR_LDT) case PR_LDT: (void) snpf(Namech, Namechl - 1, "/%s/%d/ldt", HASPROCFS, (int)prpid); ty = "PLDT"; break; # endif /* defined(HASPR_LDT) */ case PR_USAGE: (void) snpf(Namech, Namechl - 1, "/%s/%d/usage", HASPROCFS, (int)prpid); ty = "PUSG"; break; case PR_LUSAGE: (void) snpf(Namech, Namechl - 1, "/%s/%d/lusage", HASPROCFS, (int)prpid); ty = "PLU"; break; case PR_PAGEDATA: (void) snpf(Namech, Namechl - 1, "/%s/%d/pagedata", HASPROCFS, (int)prpid); ty = "PGD"; break; case PR_WATCH: (void) snpf(Namech, Namechl - 1, "/%s/%d/watch", HASPROCFS, (int)prpid); ty = "PW"; break; case PR_CURDIR: (void) snpf(Namech, Namechl - 1, "/%s/%d/cwd", HASPROCFS, (int)prpid); ty = "PCWD"; break; case PR_ROOTDIR: (void) snpf(Namech, Namechl - 1, "/%s/%d/root", HASPROCFS, (int)prpid); ty = "PRTD"; break; case PR_FDDIR: (void) snpf(Namech, Namechl - 1, "/%s/%d/fd", HASPROCFS, (int)prpid); ty = "PFDR"; break; case PR_FD: (void) snpf(Namech, Namechl - 1, "/%s/%d/fd/%d", HASPROCFS, (int)prpid, pr.pr_index); ty = "PFD"; break; case PR_OBJECTDIR: (void) snpf(Namech, Namechl - 1, "/%s/%d/object", HASPROCFS, (int)prpid); ty = "PODR"; break; case PR_OBJECT: (void) snpf(Namech, Namechl - 1, "/%s/%d/object/", HASPROCFS, (int)prpid); ty = "POBJ"; break; case PR_LWPDIR: (void) snpf(Namech, Namechl - 1, "/%s/%d/lpw", HASPROCFS, (int)prpid); ty = "PLDR"; break; case PR_LWPIDDIR: (void) snpf(Namech, Namechl, "/%s/%d/lwp/%d", HASPROCFS, (int)prpid, (int)prtid); ty = "PLDR"; break; case PR_LWPCTL: (void) snpf(Namech, Namechl - 1, "/%s/%d/lwp/%d/lwpctl", HASPROCFS, (int)prpid, (int)prtid); ty = "PLC"; break; case PR_LWPSTATUS: (void) snpf(Namech, Namechl - 1, "/%s/%d/lwp/%d/lwpstatus", HASPROCFS, (int)prpid, (int)prtid); ty = "PLWS"; break; case PR_LWPSINFO: (void) snpf(Namech, Namechl - 1, "/%s/%d/lwp/%d/lwpsinfo", HASPROCFS, (int)prpid, (int)prtid); ty = "PLWI"; break; case PR_LWPUSAGE: (void) snpf(Namech, Namechl - 1, "/%s/%d/lwp/%d/lwpusage", HASPROCFS, (int)prpid, (int)prtid); ty = "PLWU"; break; case PR_XREGS: (void) snpf(Namech, Namechl - 1, "/%s/%d/lwp/%d/xregs", HASPROCFS, (int)prpid, (int)prtid); ty = "PLWX"; break; # if defined(HASPR_GWINDOWS) case PR_GWINDOWS: (void) snpf(Namech, Namechl - 1, "/%s/%d/lwp/%d/gwindows", HASPROCFS, (int)prpid, (int)prtid); ty = "PLWG"; break; # endif /* defined(HASPR_GWINDOWS) */ case PR_PIDFILE: (void) snpf(Namech, Namechl - 1, "/%s/%d", HASPROCFS, (int)prpid); ty = "POPF"; break; case PR_LWPIDFILE: (void) snpf(Namech, Namechl - 1, "/%s/%d", HASPROCFS, (int)prpid); ty = "POLP"; break; case PR_OPAGEDATA: (void) snpf(Namech, Namechl - 1, "/%s/%d", HASPROCFS, (int)prpid); ty = "POPG"; break; default: ty = (char *)NULL; } if (ty) (void) snpf(Lf->type, sizeof(Lf->type), "%s", ty); else (void) snpf(Lf->type, sizeof(Lf->type), "%04o", (pr.pr_type & 0xfff)); /* * Record the Solaris 2.6 /proc file system inode number. */ Lf->inode = (INODETYPE)pr.pr_ino; Lf->inp_ty = 1; # endif /* solaris<20600 */ Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(0); } #endif /* defined(HASPROCFS) */ /* * read_npn() - read node's pcnode */ static int read_npn(na, pa, p) KA_T na; /* containing node's address */ KA_T pa; /* pcnode address */ struct pcnode *p; /* pcnode receiver */ { char tbuf[32]; if (!pa || kread(pa, (char *)p, sizeof(struct pcnode))) { (void) snpf(Namech, Namechl - 1, "node at %s: can't read pcnode: %s", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr(pa, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } return(0); } #if solaris>=100000 /* * read_nprtn() - read node's port node */ static int read_nprtn(na, pa, p) KA_T na; /* containing node's address */ KA_T pa; /* port node address */ port_t *p; /* port node receiver */ { char tbuf[32]; if (!pa || kread(pa, (char *)p, sizeof(port_t))) { (void) snpf(Namech, Namechl - 1, "node at %s: can't read port node: %s", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr(pa, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } return(0); } #endif /* solaris>=100000 */ /* * read_nrn() - read node's rnode */ static int read_nrn(na, ra, r) KA_T na; /* containing node's address */ KA_T ra; /* rnode address */ struct rnode *r; /* rnode receiver */ { char tbuf[32]; if (!ra || readrnode(ra, r)) { (void) snpf(Namech, Namechl - 1, "node at %s: can't read rnode: %s", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr(ra, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } return(0); } #if solaris>=100000 /* * read_nrn4() - read node's rnode4 */ static int read_nrn4(na, ra, r) KA_T na; /* containing node's address */ KA_T ra; /* rnode address */ struct rnode4 *r; /* rnode receiver */ { char tbuf[32]; if (!ra || kread((KA_T)ra, (char *)r, sizeof(struct rnode4)) ) { (void) snpf(Namech, Namechl - 1, "node at %s: can't read rnode4: %s", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr(ra, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } return(0); } #endif /* solaris>=100000 */ #if solaris>=110000 /* * read_nsdn() - read node's sdev_node */ static int read_nsdn(na, sa, sdn, sdva) KA_T na; /* containing node's adress */ KA_T sa; /* sdev_node address */ struct sdev_node *sdn; /* sdev_node receiver */ struct vattr *sdva; /* sdev_node's vattr receiver */ { KA_T va; char tbuf[32], tbuf1[32]; if (!sa || kread((KA_T)sa, (char *)sdn, sizeof(struct sdev_node))) { (void) snpf(Namech, Namechl - 1, "node at %s: can't read sdev_node: %s", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr(sa, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } if (!(va = (KA_T)sdn->sdev_attr) || kread(va, (char *)sdva, sizeof(struct vattr)) ) { (void) snpf(Namech, Namechl - 1, "node at %s; sdev_node at %s: can't read vattr: %s", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr(sa, tbuf1, sizeof(tbuf1)), print_kptr(va, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } return(0); } #endif /* solaris>=110000 */ #if solaris>=20600 /* * read_nson() - read node's sonode */ static int read_nson(na, sa, sn) KA_T na; /* containing node's address */ KA_T sa; /* sonode address */ struct sonode *sn; /* sonode receiver */ { char tbuf[32]; if (!sa || kread((KA_T)sa, (char *)sn, sizeof(struct sonode))) { (void) snpf(Namech, Namechl - 1, "node at %s: can't read sonode: %s", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr(sa, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } return(0); } #endif /* solaris>=20600 */ /* * read_nsn() - read node's snode */ static int read_nsn(na, sa, s) KA_T na; /* containing node's address */ KA_T sa; /* snode address */ struct snode *s; /* snode receiver */ { char tbuf[32]; if (!sa || readsnode(sa, s)) { (void) snpf(Namech, Namechl - 1, "node at %s: can't read snode: %s", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr(sa, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } return(0); } #if solaris>=110000 /* * read_nsti() - read socket node's info */ static int read_nsti(so, stpi) struct sonode *so; /* socket's sonode */ sotpi_info_t *stpi; /* local socket info receiver */ { char tbuf[32]; (void) CTF_init(&Sockfs_ctfs, SOCKFS_MOD_FORMAT, Sockfs_requests); if (!so || !so->so_priv || CTF_MEMBER_READ(so->so_priv,stpi,sotpi_info_members, sti_dev) || CTF_MEMBER_READ(so->so_priv,stpi,sotpi_info_members, sti_laddr) || CTF_MEMBER_READ(so->so_priv,stpi,sotpi_info_members, sti_faddr) || CTF_MEMBER_READ(so->so_priv,stpi,sotpi_info_members, sti_ux_laddr) || CTF_MEMBER_READ(so->so_priv,stpi,sotpi_info_members, sti_ux_faddr) || CTF_MEMBER_READ(so->so_priv,stpi,sotpi_info_members, sti_serv_type) ) { (void) snpf(Namech, Namechl - 1, "sonode at %s: can't read so_priv: %s", print_kptr((KA_T)so, tbuf, sizeof(tbuf)), print_kptr((KA_T)so->so_priv, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } return(0); } #endif /* solaris>=110000 */ /* * read_ntn() - read node's tmpnode */ static int read_ntn(na, ta, t) KA_T na; /* containing node's address */ KA_T ta; /* tmpnode address */ struct tmpnode *t; /* tmpnode receiver */ { char tbuf[32]; if (!ta || readtnode(ta, t)) { (void) snpf(Namech, Namechl - 1, "node at %s: can't read tnode: %s", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr(ta, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } return(0); } #if solaris>=20600 /* * read_nusa() - read sondode's UNIX socket address */ static int read_nusa(so, ua) struct soaddr *so; /* kernel socket info structure */ struct sockaddr_un *ua; /* local sockaddr_un address */ { KA_T a; int len; int min = offsetof(struct sockaddr_un, sun_path); ua->sun_path[0] = '\0'; if (!(a = (KA_T)so->soa_sa) || (len = so->soa_len) < (min + 2) || len > (int)sizeof(struct sockaddr_un) || kread(a, (char *)ua, len) || ua->sun_family != AF_UNIX) return(0); len -= min; if (len >= sizeof(ua->sun_path)) len = sizeof(ua->sun_path) - 1; ua->sun_path[len] = '\0'; return((int)strlen(ua->sun_path)); } #endif /* solaris>=20600 */ /* * read_nvn() - read node's vnode */ static int read_nvn(na, va, v) KA_T na; /* node's address */ KA_T va; /* vnode address */ struct vnode *v; /* vnode receiver */ { char tbuf[32]; if (readvnode(va, v)) { (void) snpf(Namech, Namechl - 1, "node at %s: can't read real vnode: %s", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr(va, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } return(0); } #if defined(HAS_ZFS) /* * read_nzn() - read node's ZFS node */ static int read_nzn(na, nza, zn) KA_T na; /* containing node's address */ KA_T nza; /* znode address */ znode_t *zn; /* znode receiver */ { int err = 0; /* error flag */ CTF_member_t *mp; /* member pointer */ char tbuf[32]; /* temporary buffer */ znode_phys_t zp; /* physical znode */ (void) CTF_init(&ZFS_ctfs, ZFS_MOD_FORMAT, ZFS_requests); if (!nza || CTF_MEMBER_READ(nza, zn, znode_members, z_zfsvfs) || CTF_MEMBER_READ(nza, zn, znode_members, z_vnode) || CTF_MEMBER_READ(nza, zn, znode_members, z_id) || CTF_MEMBER_READ(nza, zn, znode_members, z_phys) || CTF_MEMBER_READ(nza, zn, znode_members, z_links) || CTF_MEMBER_READ(nza, zn, znode_members, z_size) ) { (void) snpf(Namech, Namechl - 1, "node at %s: can't read znode: %s", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr(nza, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } /* * If the physical znode pointer is defined, read the physizal znode * and propagate its values to the znode. */ if (znode_members[MX_z_phys].m_offset != CTF_MEMBER_UNDEF) { err = read_nznp(nza, (KA_T)zn->z_phys, &zp); if (!err) { zn->z_links = zp.zp_links; zn->z_size = zp.zp_size; } } else { /* * Make sure z_link and z_size are defined when z_phys isn't. */ if (znode_members[MX_z_links].m_offset == CTF_MEMBER_UNDEF) { (void) snpf(Namech, Namechl - 1, "node at %s: can't read z_links: %s", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr(nza, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); err = 1; } if (znode_members[MX_z_size].m_offset == CTF_MEMBER_UNDEF) { (void) snpf(Namech, Namechl - 1, "node at %s: can't read z_size: %s", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr(nza, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); err = 1; } } return(err); } /* * read_nznp() - read znode's persistent znode */ static int read_nznp(nza, nzpa, zp) KA_T nza; /* containing znode's address */ KA_T nzpa; /* persistent znode address */ znode_phys_t *zp; /* persistent znode receiver */ { char tbuf[32]; (void) CTF_init(&ZFS_ctfs, ZFS_MOD_FORMAT, ZFS_requests); if (!nzpa || CTF_MEMBER_READ(nzpa, zp, znode_phys_members, zp_size) || CTF_MEMBER_READ(nzpa, zp, znode_phys_members, zp_links) ) { (void) snpf(Namech, Namechl - 1, "znode at %s: " "can't read znode_phys: %s", print_kptr(nza, tbuf, sizeof(tbuf)), print_kptr(nzpa, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } return(0); } /* * read_nzvfs() - read znode's associated vfs */ static int read_nzvfs(nza, nzva, zv) KA_T nza; /* containing znode's address */ KA_T nzva; /* associated vfs address */ zfsvfs_t *zv; /* associated vfs receiver */ { char tbuf[32]; (void) CTF_init(&ZFS_ctfs, ZFS_MOD_FORMAT, ZFS_requests); if (!nzva || CTF_MEMBER_READ(nzva, zv, zfsvfs_members, z_vfs) ) { (void) snpf(Namech, Namechl - 1, "znode at %s: can't read zfsvfs: %s", print_kptr(nza, tbuf, sizeof(tbuf)), print_kptr(nzva, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } return(0); } #endif /* defined(HAS_ZFS) */ #if solaris<100000 /* * savesockmod() - save addresses from sockmod so_so structure */ static void savesockmod(so, sop, so_st) struct so_so *so; /* new so_so structure pointer */ struct so_so *sop; /* previous so_so structure pointer */ int *so_st; /* status of *sop (0 if not loaded) */ { #if solaris<20500 dev_t d1, d2, d3; #endif /* solaris<20500 */ #define luxadr lux_dev.addr.tu_addr #define luxdev lux_dev.addr.tu_addr.dev #define luxino lux_dev.addr.tu_addr.ino #define ruxadr rux_dev.addr.tu_addr #define ruxdev rux_dev.addr.tu_addr.dev #define ruxino rux_dev.addr.tu_addr.ino #if solaris<20500 /* * If either address in the new structure is missing a device number, clear * its corresponding inode number. Then sort the inode-less device numbers. */ if (!so->luxdev) so->luxino = (ino_t)0; if (!so->ruxdev) so->ruxino = (ino_t)0; if (!so->luxino && !so->ruxino) { if (so->luxdev > so->ruxdev) { d2 = so->luxdev; d1 = so->luxdev = so->ruxdev; so->ruxdev = d2; } else { d1 = so->luxdev; d2 = so->ruxdev; } } else d1 = d2 = (dev_t)0; /* * If the previous structure hasn't been loaded, save the new one in it with * adjusted or sorted addresses. */ if (!*so_st) { if (so->luxdev && so->luxino) { *sop = *so; sop->ruxdev = (dev_t)0; sop->ruxino = (ino_t)0; *so_st = 1; return; } if (so->ruxdev && so->ruxino) { *sop = *so; sop->luxadr = sop->ruxadr; sop->ruxdev = (dev_t)0; sop->ruxino = (ino_t)0; *so_st = 1; return; } *sop = *so; *so_st = 1; return; } /* * See if the new sockmod addresses need to be merged with the previous * ones: * * * Don't merge if the previous so_so structure's lux_dev has a non- * zero device and a non-zero inode number. * * * If either of the device/inode pairs in the new structure is non- * zero, propagate them to the previous so_so structure. * * * Don't merge if the both device numbers in the new structure are * zero. */ if (sop->luxdev && sop->luxino) return; if (so->luxdev && so->luxino) { sop->luxadr = so->luxadr; sop->ruxdev = (dev_t)0; sop->ruxino = (ino_t)0; return; } if (so->ruxdev && so->ruxino) { sop->luxadr = so->ruxadr; sop->ruxdev = (dev_t)0; sop->ruxino = (ino_t)0; return; } if (!so->luxdev && !so->ruxdev) return; /* * Check the previous structure's device numbers: * * * If both are zero, replace the previous structure with the new one. * * * Choose the minimum and maximum non-zero device numbers contained in * either structure. */ if (!sop->luxdev && !sop->ruxdev) { *sop = *so; return; } if (!sop->luxdev && (d1 || d2)) { if (d1) { sop->luxdev = d1; d1 = (dev_t)0; } else { sop->luxdev = d2; d2 = (dev_t)0; } if (sop->luxdev > sop->ruxdev) { d3 = sop->luxdev; sop->luxdev = sop->ruxdev; sop->ruxdev = d3; } } if (!sop->ruxdev && (d1 || d2)) { if (d1) { sop->ruxdev = d1; d1 = (dev_t)0; } else { sop->ruxdev = d2; d2 = (dev_t)0; } if (sop->luxdev > sop->ruxdev) { d3 = sop->luxdev; sop->luxdev = sop->ruxdev; sop->ruxdev = d3; } } if (sop->luxdev && sop->ruxdev) { if (d1) { if (d1 < sop->luxdev) sop->luxdev = d1; else if (d1 > sop->ruxdev) sop->ruxdev = d1; } if (d2) { if (d2 < sop->luxdev) sop->luxdev = d2; else if (d2 > sop->ruxdev) sop->ruxdev = d2; } } #else /* solaris>=20500 */ /* * Save the first sockmod structure. */ if (!*so_st) { *so_st = 1; *sop = *so; } #endif /* solaris<20500 */ } #endif /* solaris<100000 */ /* * vop2ty() - convert vnode operation switch address to internal type */ int vop2ty(vp, fx) struct vnode *vp; /* local vnode pointer */ int fx; /* file system index (-1 if none) */ { int h; register int i; KA_T ka; int nty; v_optab_t *nv, *v, *vt; #if defined(HAS_AFS) static int afs = 0; /* afs test status: -1 = no AFS * 0 = not tested * 1 = AFS */ #endif /* defined(HAS_AFS) */ /* * Locate the node type by hashing the vnode's v_op address into the Voptab[]. */ if (!(ka = (KA_T)vp->v_op)) return(-1); h = HASHVOP(ka); for (v = Voptab[h]; v; v = v->next) { if (ka == v->v_op) break; } if (!v) { /* * If there's no entry in the Voptab[] for the v_op address, see if * an entry can be found via the file system type and FxToVoptab[]. */ if ((fx >= 0) && (fx < Fsinfomax) && (v = FxToVoptab[fx])) { /* * There's an FxToVoptab[] mapping, so add an entry to Voptab[] * for the v_op address. */ if (!(nv = (v_optab_t *)malloc((MALLOC_S)sizeof(v_optab_t)))) { (void) fprintf(stderr, "%s: can't add \"%s\" to Voptab\n", Pn, Fsinfo[fx]); Exit(1); } *nv = *v; nv->v_op = ka; h = HASHVOP(ka); nv->next = Voptab[h]; Voptab[h] = v = nv; } } if (!v) return(-1); #if defined(HAS_AFS) /* * Do special AFS checks. */ if (v->nty == N_AFS) { if (vp->v_data || !vp->v_vfsp) return(-1); switch (afs) { case -1: return(-1); case 0: if (!hasAFS(vp)) { afs = -1; return(-1); } afs = 1; return(N_AFS); case 1: if ((KA_T)vp->v_vfsp == AFSVfsp) return(N_AFS); } return(-1); } #endif /* defined(HAS_AFS) */ return(v->nty); } #if solaris>=100000 /* * read_ndvn() -- read node's dv_node */ static int read_ndvn(na, da, dv, dev, devs) KA_T na; /* containing vnode's address */ KA_T da; /* containing vnode's v_data */ struct dv_node *dv; /* dv_node receiver */ dev_t *dev; /* underlying file system device * number receptor */ unsigned char *devs; /* status of *dev */ { struct vnode rv; struct snode s; char tbuf[32]; struct vfs v; /* * Read the snode. */ if (!da || kread((KA_T)da, (char *)&s, sizeof(s))) { (void) snpf(Namech, Namechl - 1, "dv_node vnode at %s: can't read snode: %s", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr(da, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } /* * Read the snode's real vnode. */ if (!s.s_realvp || kread((KA_T)s.s_realvp, (char *)&rv, sizeof(struct dv_node))) { (void) snpf(Namech, Namechl - 1, "dv_node snode at %s: can't read real vnode: %s", print_kptr(da, tbuf, sizeof(tbuf)), print_kptr((KA_T)s.s_realvp, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } /* * Read the real vnode's dv_node. */ if (!rv.v_data || kread((KA_T)rv.v_data, (char *)dv, sizeof(rv))) { (void) snpf(Namech, Namechl - 1, "dv_node real vnode at %s: can't read dv_node: %s", print_kptr((KA_T)s.s_realvp, tbuf, sizeof(tbuf)), print_kptr((KA_T)rv.v_data, (char *)NULL, 0)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); return(1); } /* * Return the device number of the underlying file system, if possible. */ if (rv.v_vfsp && !kread((KA_T)rv.v_vfsp, (char *)&v, sizeof(v))) { *dev = v.vfs_dev; *devs = 1; } return(0); } #endif /* solaris<100000 */ lsof-4.86+dfsg.orig/dialects/sun/dfile.c0000444000175000017500000003577311162502152020312 0ustar nicholasnicholas/* * dfile.c - Solaris file processing functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dfile.c,v 1.21 2009/03/25 19:22:16 abe Exp $"; #endif #include "lsof.h" /* * Local structures */ struct hsfile { struct sfile *s; /* the Sfile table address */ struct hsfile *next; /* the next hash bucket entry */ }; /* * Local static variables */ static struct hsfile *HbyCd = /* hash by clone buckets */ (struct hsfile *)NULL; static int HbyCdCt = 0; /* HbyCd entry count */ static struct hsfile *HbyFdi = /* hash by file buckets */ (struct hsfile *)NULL; static int HbyFdiCt = 0; /* HbyFdi entry count */ static struct hsfile *HbyFrd = /* hash by file raw device buckets */ (struct hsfile *)NULL; static int HbyFrdCt = 0; /* HbyFrd entry count */ static struct hsfile *HbyFsd = /* hash by file system buckets */ (struct hsfile *)NULL; static int HbyFsdCt = 0; /* HbyFsd entry count */ static struct hsfile *HbyNm = /* hash by name buckets */ (struct hsfile *)NULL; static int HbyNmCt = 0; /* HbyNm entry count */ /* * Local definitions */ #define SFCDHASH 1024 /* Sfile hash by clone device */ #define SFDIHASH 4094 /* Sfile hash by (device,inode) number * pair bucket count (power of 2!) */ #define SFFSHASH 128 /* Sfile hash by file system device * number bucket count (power of 2!) */ #define SFHASHDEVINO(maj, min, ino, mod) ((int)(((int)((((int)(maj+1))*((int)((min+1))))+ino)*31415)&(mod-1))) /* hash for Sfile by major device, * minor device, and inode, modulo m * (m must be a power of 2) */ #define SFNMHASH 4096 /* Sfile hash by name bucket count (power of 2!) */ #define SFRDHASH 1024 /* Sfile hash by raw device number * bucket count (power of 2!) */ #define SFHASHRDEVI(maj, min, rmaj, rmin, ino, mod) ((int)(((int)((((int)(maj+1))*((int)((min+1))))+((int)(rmaj+1)*(int)(rmin+1))+ino)*31415)&(mod-1))) /* hash for Sfile by major device, * minor device, major raw device, * minor raw device, and inode, modulo * mod (mod must be a power of 2) */ #if solaris<20500 /* * get_max_fd() - get maximum file descriptor plus one */ int get_max_fd() { struct rlimit r; if (getrlimit(RLIMIT_NOFILE, &r)) return(-1); return(r.rlim_cur); } #endif /* solaris<20500 */ /* * hashSfile() - hash Sfile entries for use in is_file_named() searches */ void hashSfile() { int cmaj, hvc, i; static int hs = 0; struct sfile *s; struct hsfile *sh, *sn; /* * Do nothing if there are no file search arguments cached or if the * hashes have already been constructed. */ if (!Sfile || hs) return; /* * Preset the clone major device for Solaris. */ if (HaveCloneMaj) { cmaj = CloneMaj; hvc = 1; } else hvc = 0; /* * Allocate hash buckets by clone device, (device,inode), file system device, * and file name. */ if (hvc) { if (!(HbyCd = (struct hsfile *)calloc((MALLOC_S)SFCDHASH, sizeof(struct hsfile)))) { (void) fprintf(stderr, "%s: can't allocate space for %d clone hash buckets\n", Pn, SFCDHASH); Exit(1); } } if (!(HbyFdi = (struct hsfile *)calloc((MALLOC_S)SFDIHASH, sizeof(struct hsfile)))) { (void) fprintf(stderr, "%s: can't allocate space for %d (dev,ino) hash buckets\n", Pn, SFDIHASH); Exit(1); } if (!(HbyFrd = (struct hsfile *)calloc((MALLOC_S)SFRDHASH, sizeof(struct hsfile)))) { (void) fprintf(stderr, "%s: can't allocate space for %d rdev hash buckets\n", Pn, SFRDHASH); Exit(1); } if (!(HbyFsd = (struct hsfile *)calloc((MALLOC_S)SFFSHASH, sizeof(struct hsfile)))) { (void) fprintf(stderr, "%s: can't allocate space for %d file sys hash buckets\n", Pn, SFFSHASH); Exit(1); } if (!(HbyNm = (struct hsfile *)calloc((MALLOC_S)SFNMHASH, sizeof(struct hsfile)))) { (void) fprintf(stderr, "%s: can't allocate space for %d name hash buckets\n", Pn, SFNMHASH); Exit(1); } hs++; /* * Scan the Sfile chain, building file, file system, and file name hash * bucket chains. */ for (s = Sfile; s; s = s->next) { for (i = 0; i < 4; i++) { if (i == 0) { if (!s->aname) continue; sh = &HbyNm[hashbyname(s->aname, SFNMHASH)]; HbyNmCt++; } else if (i == 1) { if (s->type) { sh = &HbyFdi[SFHASHDEVINO(GET_MAJ_DEV(s->dev), GET_MIN_DEV(s->dev), s->i, SFDIHASH)]; HbyFdiCt++; } else { sh = &HbyFsd[SFHASHDEVINO(GET_MAJ_DEV(s->dev), GET_MIN_DEV(s->dev), 0, SFFSHASH)]; HbyFsdCt++; } } else if (i == 2) { if (s->type && ((s->mode == S_IFCHR) || (s->mode == S_IFBLK))) { sh = &HbyFrd[SFHASHRDEVI(GET_MAJ_DEV(s->dev), GET_MIN_DEV(s->dev), GET_MAJ_DEV(s->rdev), GET_MIN_DEV(s->rdev), s->i, SFRDHASH)]; HbyFrdCt++; } else continue; } else { if (!hvc || (GET_MAJ_DEV(s->rdev) != cmaj)) continue; sh = &HbyCd[SFHASHDEVINO(0, GET_MIN_DEV(s->rdev), 0, SFCDHASH)]; HbyCdCt++; } if (!sh->s) { sh->s = s; sh->next = (struct hsfile *)NULL; continue; } else { if (!(sn = (struct hsfile *)malloc( (MALLOC_S)sizeof(struct hsfile)))) { (void) fprintf(stderr, "%s: can't allocate hsfile bucket for: %s\n", Pn, s->aname); Exit(1); } sn->s = s; sn->next = sh->next; sh->next = sn; } } } } /* * is_file_named() - is this file named? */ int is_file_named(p, nt, vt, ps) char *p; /* path name; NULL = search by device * and inode (from *Lf) */ int nt; /* node type -- e.g., N_* */ enum vtype vt; /* vnode type */ int ps; /* print status: 0 = don't copy name * to Namech */ { char *ep; int f = 0; struct sfile *s; struct hsfile *sh; size_t sz; /* * Check for a path name match, as requested. */ if (p && HbyNmCt) { for (sh = &HbyNm[hashbyname(p, SFNMHASH)]; sh; sh = sh->next) { if ((s = sh->s) && strcmp(p, s->aname) == 0) { f = 2; break; } } } /* * Check for a Solaris clone file. */ if (!f && HbyCdCt && nt == N_STREAM && Lf->dev_def && Lf->rdev_def && (Lf->dev == DevDev)) { for (sh = &HbyCd[SFHASHDEVINO(0, GET_MAJ_DEV(Lf->rdev), 0, SFCDHASH)]; sh; sh = sh->next) { if ((s = sh->s) && (GET_MAJ_DEV(Lf->rdev) == GET_MIN_DEV(s->rdev))) { f = 1; break; } } } /* * Check for a regular file. */ if (!f && HbyFdiCt && Lf->dev_def && (Lf->inp_ty == 1 || Lf->inp_ty == 3)) { for (sh = &HbyFdi[SFHASHDEVINO(GET_MAJ_DEV(Lf->dev), GET_MIN_DEV(Lf->dev), Lf->inode, SFDIHASH)]; sh; sh = sh->next) { if ((s = sh->s) && (Lf->dev == s->dev) && (Lf->inode == s->i)) { f = 1; break; } } } /* * Check for a file system match. */ if (!f && HbyFsdCt && Lf->dev_def) { for (sh = &HbyFsd[SFHASHDEVINO(GET_MAJ_DEV(Lf->dev), GET_MIN_DEV(Lf->dev), 0, SFFSHASH)]; sh; sh = sh->next) { if ((s = sh->s) && Lf->dev == s->dev) { f = 1; break; } } } /* * Check for a character or block device match. */ if (!f && HbyFrdCt && ((vt = VCHR) || (vt = VBLK)) && Lf->dev_def && (Lf->dev == DevDev) && Lf->rdev_def && (Lf->inp_ty == 1 || Lf->inp_ty == 3)) { for (sh = &HbyFrd[SFHASHRDEVI(GET_MAJ_DEV(Lf->dev), GET_MIN_DEV(Lf->dev), GET_MAJ_DEV(Lf->rdev), GET_MIN_DEV(Lf->rdev), Lf->inode, SFRDHASH)]; sh; sh = sh->next) { if ((s = sh->s) && (s->dev == Lf->dev) && (s->rdev == Lf->rdev) && (s->i == Lf->inode)) { f = 1; break; } } } /* * Convert the name if a match occurred. */ if (f) { if (f == 2) { if (ps) (void) snpf(Namech, Namechl, "%s", p); } else { if (ps && s->type) { /* * If the search argument isn't a file system, propagate it * to Namech[]; otherwise, let printname() compose the name. */ (void) snpf(Namech, Namechl, "%s", s->name); if (s->devnm) { ep = endnm(&sz); (void) snpf(ep, sz, " (%s)", s->devnm); } } } s->f = 1; return(1); } return(0); } #if defined(HASPRINTDEV) /* * print_dev() - print device */ char * print_dev(lf, dev) struct lfile *lf; /* file whose device is to be printed */ dev_t *dev; /* device to be printed */ { static char buf[128]; /* * Avoid the Solaris major() and minor() functions from makedev(3C) to get * printable major/minor numbers. * * We would like to use the L_MAXMAJ definition from all * the time, but it's not always correct in all versions of Solaris. */ (void) snpf(buf, sizeof(buf), "%d,%d", (int)((*dev >> L_BITSMINOR) & #if solaris>=20501 L_MAXMAJ #else /* solaris<20501 */ 0x3fff #endif /* solaris>=20501 */ ), (int)(*dev & L_MAXMIN)); return(buf); } #endif /* defined(HASPRINTDEV) */ #if defined(HAS_V_PATH) /* * Local definitions */ #define VPRDLEN ((MAXPATHLEN + 7)/8) /* v_path read length increment */ /* * print_v_path() - print path name from vnode's v_path pointer */ extern int print_v_path(lf) struct lfile *lf; /* local file structure */ { char buf[MAXPATHLEN+1]; unsigned char del = 0; unsigned char aperr = 0; # if defined(HASMNTSTAT) struct stat sb; # endif /* defined(HASMNTSTAT) */ # if defined(HASVXFS) && defined(HASVXFSRNL) if (lf->is_vxfs && (lf->inp_ty == 1) && lf->fsdir) { if (print_vxfs_rnl_path(lf)) return(1); } # endif /* defined(HASVXFS) && defined(HASVXFSRNL) */ (void) read_v_path((KA_T)lf->V_path, buf, (size_t)sizeof(buf)); if (buf[0]) { # if defined(HASMNTSTAT) if (!lf->mnt_stat && lf->dev_def && (lf->inp_ty == 1)) { /* * No problem was detected in applying stat(2) to this mount point. * If the device and inode for the file are known, it is probably * safe and worthwhile to apply stat(2) to the v_path. */ if (!statsafely(buf, &sb)) { /* * The stat(2) succeeded. See if the device and inode match. * If they both don't match, ignore the v_path. */ if ((lf->dev != sb.st_dev) || (lf->inode != (INODETYPE)sb.st_ino) ) { return(0); } } else { /* * The stat(2) failed. * * If the error reply is ENOENT and the -X option hasn't been * specified, ignore the v_path. * * If the error reply is ENOENT, the -X option has been * specified and the file's link count is zero, report the * v_path with the "(deleted)" notation. * * If the error reply is EACCES or EPERM, report the v_path, * followed by "(?)", because lsof probably lacks permission * to apply stat(2) to v_path. */ switch (errno) { case EACCES: case EPERM: aperr = 1; break; case ENOENT: # if defined(HASXOPT) if (Fxopt && lf->nlink_def && !lf->nlink) { del = 1; break; } # endif /* defined(HASXOPT) */ return(0); default: return(0); } } } # endif /* defined(HASMNTSTAT) */ /* * Print the v_path. */ safestrprt(buf, stdout, 0); if (del) safestrprt(" (deleted)", stdout, 0); else if (aperr) safestrprt(" (?)", stdout, 0); return(1); } return(0); } /* * read_v_path() - read path name from vnode's v_path pointer */ extern void read_v_path(ka, rb, rbl) KA_T ka; /* kernel path address */ char *rb; /* receiving buffer */ size_t rbl; /* receiving buffer length */ { char *ba; size_t rl, tl; *rb = '\0'; if (!ka) return; for (ba = rb, tl = 0; tl < (rbl - 1); ba += rl, ka += (KA_T)((char *)ka + rl), tl += rl ) { /* * Read v_path VPRDLEN bytes at a time until the local buffer is full * or a NUL byte is reached. */ if ((rl = rbl - 1 - tl) > VPRDLEN) rl = VPRDLEN; else if (rl < 1) { *(rb + rbl - 1) = '\0'; break; } if (!kread(ka, ba, rl)) { *(ba + rl) = '\0'; if (strchr(ba, '\0') < (ba + rl)) break; } else { /* * Can't read a full buffer load; try reducing the length one * byte at a time until it reaches zero. Stop here, since it * has been established that no more bytes can be read. */ for (rl--; rl > 0; rl--) { if (!kread(ka, ba, rl)) { *(ba + rl) = '\0'; break; } } if (rl <= 0) *ba = '\0'; break; } } } #endif /* defined(HAS_V_PATH) */ /* * process_file() - process file */ void process_file(fp) KA_T fp; /* kernel file structure address */ { struct file f; int flag; #if defined(FILEPTR) FILEPTR = &f; #endif /* defined(FILEPTR) */ if (kread(fp, (char *)&f, sizeof(f))) { (void) snpf(Namech, Namechl, "can't read file struct from %s", print_kptr(fp, (char *)NULL, 0)); enter_nm(Namech); return; } Lf->off = (SZOFFTYPE)f.f_offset; if (f.f_count) { /* * Construct access code. */ if ((flag = (f.f_flag & (FREAD | FWRITE))) == FREAD) Lf->access = 'r'; else if (flag == FWRITE) Lf->access = 'w'; else if (flag == (FREAD | FWRITE)) Lf->access = 'u'; #if defined(HASFSTRUCT) /* * Save file structure values. */ if (Fsv & FSV_CT) { Lf->fct = (long)f.f_count; Lf->fsv |= FSV_CT; } if (Fsv & FSV_FA) { Lf->fsa = fp; Lf->fsv |= FSV_FA; } if (Fsv & FSV_FG) { Lf->ffg = (long)f.f_flag; Lf->fsv |= FSV_FG; } if (Fsv & FSV_NI) { Lf->fna = (KA_T)f.f_vnode; Lf->fsv |= FSV_NI; } #endif /* defined(HASFSTRUCT) */ /* * Solaris file structures contain a vnode pointer. Process it. */ process_node((KA_T)f.f_vnode); return; } enter_nm("no more information"); } #if defined(HASIPv6) /* * gethostbyname2() -- an RFC2133-compatible get-host-by-name-two function * to get AF_INET and AF_INET6 addresses from host names, * using the RFC2553-compatible getipnodebyname() function */ extern struct hostent * gethostbyname2(nm, prot) const char *nm; /* host name */ int prot; /* protocol -- AF_INET or AF_INET6 */ { int err; static struct hostent *hep = (struct hostent *)NULL; if (hep) (void) freehostent(hep); return((hep = getipnodebyname(nm, prot, 0, &err))); } #endif /* defined(HASIPv6) */ lsof-4.86+dfsg.orig/dialects/sun/dmnt.c0000444000175000017500000002302110304561135020153 0ustar nicholasnicholas/* * dmnt.c - Solaris mount support functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dmnt.c,v 1.15 2005/08/29 10:24:25 abe Exp $"; #endif #include "lsof.h" /* * Local static definitions */ static struct mounts *Lmi = (struct mounts *)NULL; /* local mount info */ static int Lmist = 0; /* Lmi status */ _PROTOTYPE(static char *getmntdev,(char *o, int l, struct stat *s, char *f)); /* * getmntdev() - get mount entry's device number */ static char * getmntdev(o, l, s, f) char *o; /* start of device option */ int l; /* length of device keyword (not * including `=') */ struct stat *s; /* pointer to stat buffer to create */ char *f; /* file system type */ { char *opte; memset((char *)s, 0, sizeof(struct stat)); if (!(opte = x2dev(o + l + 1, &s->st_dev))) return((char *)NULL); #if solaris>=70000 && L_BITSMAJOR!=L_BITSMAJOR32 /* * If this is a Solaris 7 system with a 64 bit kernel, convert the 32 bit * device number to a 64 bit device number. */ s->st_dev = (((s->st_dev >> L_BITSMINOR32) & L_MAXMAJ32) << L_BITSMINOR) | (s->st_dev & L_MAXMIN32); #endif /* solaris>=70000 && L_BITSMAJOR!=L_BITSMAJOR32 */ s->st_mode = S_IFDIR | 0777; #if defined(HASFSTYPE) if (f) { (void) strncpy(s->st_fstype, f, sizeof(s->st_fstype)); s->st_fstype[sizeof(s->st_fstype) - 1] = '\0'; } #endif /* defined(HASFSTYPE) */ return(opte); } /* * readmnt() - read mount table */ struct mounts * readmnt() { int devl, ignore; char *cp, *dir, *fs; char *dn = (char *)NULL; char *ln; FILE *mfp; struct mounts *mtp; char *dopt, *dopte; struct stat sb; struct mnttab me; struct mnttab *mp; #if defined(HASPROCFS) int procfs = 0; #endif /* defined(HASPROCFS) */ unsigned char stat; char *zopt; #if defined(HASZONES) int zwarn = 0; #endif /* definesd(HASZONES) */ if (Lmi || Lmist) return(Lmi); devl = strlen(MNTOPT_DEV); /* * Open access to the mount table and read mount table entries. */ if (!(mfp = fopen(MNTTAB, "r"))) { (void) fprintf(stderr, "%s: can't access %s\n", Pn, MNTTAB); return(0); } for (mp = &me; getmntent(mfp, mp) == 0;) { /* * Skip loop-back mounts, since they are aliases for legitimate file * systems and there is no way to determine that a vnode refers to a * loop-back alias. */ if (strcmp(mp->mnt_fstype, MNTTYPE_LO) == 0) continue; /* * Save pointers to the directory and file system names for later use. * * Check the file system name. If it doesn't begin with a `/' * but contains a `:' not followed by a '/', ignore this entry. */ dir = mp->mnt_mountp; fs = mp->mnt_special; if (*fs != '/' && (cp = strchr(fs, ':')) && *(cp+1) != '/') continue; /* * Check for a "ignore" type (SunOS) or "ignore" option (Solaris). */ if (hasmntopt(mp, MNTOPT_IGNORE)) ignore = 1; else ignore = 0; /* * Interpolate a possible symbolic directory link. */ if (dn) (void) free((FREE_P *)dn); if (!(dn = mkstrcpy(dir, (MALLOC_S *)NULL))) { no_space_for_mount: (void) fprintf(stderr, "%s: no space for mount ", Pn); safestrprt(fs, stderr, 0); (void) fprintf(stderr, " ("); safestrprt(dir, stderr, 0); (void) fprintf(stderr, ")\n"); Exit(1); } if (!(ln = Readlink(dn))) { if (!Fwarn) { (void) fprintf(stderr, " Output information may be incomplete.\n"); } continue; } if (ln != dn) { (void) free((FREE_P *)dn); dn = ln; } if (*dn != '/') continue; /* * Stat() the directory. * * Avoid the stat() if the mount entry has an "ignore" option and * try to use the mount entry's device number instead. */ dopt = hasmntopt(mp, MNTOPT_DEV); if (ignore) { if (!dopt || !(dopte = getmntdev(dopt, devl, &sb, #if defined(HASFSTYPE) mp->mnt_fstype #else /* !defined(HASFSTYPE) */ (char *)NULL #endif /* defined(HASFSTYPE) */ )) ) continue; stat = 1; } else if (statsafely(dn, &sb)) { if (dopt) { if (!(dopte = getmntdev(dopt, devl, &sb, #if defined(HASFSTYPE) mp->mnt_fstype #else /* !defined(HASFSTYPE) */ (char *)NULL #endif /* defined(HASFSTYPE) */ )) ) dopt = (char *)NULL; } else dopte = (char *)NULL; if (!Fwarn) { #if defined(HASZONES) if ((zopt = hasmntopt(mp, "zone")) && dopte) zwarn++; #else /* !defined(HASZONES) */ zopt = (char *)NULL; #endif /* defined(HASZONES) */ if (!zopt || !dopte) { (void) fprintf(stderr, "%s: WARNING: can't stat() ", Pn); safestrprt(mp->mnt_fstype, stderr, 0); (void) fprintf(stderr, " file system "); safestrprt(dir, stderr, 1); (void) fprintf(stderr, " Output information may be incomplete.\n"); if (dopte) { (void) fprintf(stderr, " assuming \"%.*s\" from %s\n", (int)(dopte - dopt), dopt, MNTTAB); } } } if (!dopt) continue; stat = 1; } else stat = 0; /* * Allocate and fill a local mount structure. */ if (!(mtp = (struct mounts *)malloc(sizeof(struct mounts)))) goto no_space_for_mount; #if defined(HASFSTYPE) if (!(mtp->fstype = mkstrcpy(sb.st_fstype, (MALLOC_S *)NULL))) goto no_space_for_mount; #endif /* defined(HASFSTYPE) */ mtp->dir = dn; dn = (char *)NULL; mtp->next = Lmi; mtp->dev = sb.st_dev; mtp->rdev = sb.st_rdev; mtp->inode = (INODETYPE)sb.st_ino; mtp->mode = sb.st_mode; #if solaris>=80000 mtp->nlink = sb.st_nlink; mtp->size = sb.st_size; #endif /* solaris>=80000 */ #if defined(HASMNTSTAT) mtp->stat = stat; #endif /* defined(HASMNTSTAT) */ #if defined(HASPROCFS) if (strcmp(sb.st_fstype, HASPROCFS) == 0) { /* * Save information on exactly one proc file system. */ if (procfs) Mtprocfs = (struct mounts *)NULL; else { procfs = 1; Mtprocfs = mtp; } } #endif /* defined(HASPROCFS) */ /* * Interpolate a possible file system (mounted-on) device name link. */ if (!(dn = mkstrcpy(fs, (MALLOC_S *)NULL))) goto no_space_for_mount; mtp->fsname = dn; ln = Readlink(dn); dn = (char *)NULL; /* * Stat() the file system (mounted-on) name and add file system * information to the local mount table entry. */ if (!ln || statsafely(ln, &sb)) sb.st_mode = 0; mtp->fsnmres = ln; mtp->fs_mode = sb.st_mode; Lmi = mtp; #if defined(HAS_AFS) /* * If an AFS device number hasn't yet been defined, look for it. */ if (!AFSdevStat && mtp->dir && strcmp(mtp->dir, "/afs") == 0 && mtp->fsname && strcmp(mtp->fsname, "AFS") == 0) { AFSdev = mtp->dev; AFSdevStat = 1; } #endif /* defined(HAS_AFS) && solaris>=20600 */ } (void) fclose(mfp); #if defined(HASZONES) /* * If some zone file systems were encountered, issue a warning. */ if (!Fwarn && zwarn) { (void) fprintf(stderr, "%s: WARNING: can't stat() %d zone file system%s", Pn, zwarn, (zwarn == 1) ? "" : "s"); (void) fprintf(stderr, "; using dev= option%s\n", (zwarn == 1) ? "" : "s"); } #endif /* defined(HASZONES) */ /* * Clean up and return local mount info table address. */ if (dn) (void) free((FREE_P *)dn); Lmist = 1; return(Lmi); } /* * readvfs() - read vfs structure */ struct l_vfs * readvfs(ka, la, lv) KA_T ka; /* vfs structure kernel address, if * must be read from kernel */ struct vfs *la; /* local vfs structure address, non- * NULL if already read from kernel */ struct vnode *lv; /* local vnode */ { struct vfs *v, tv; struct l_vfs *vp; if (!ka && !la) return((struct l_vfs *)NULL); for (vp = Lvfs; vp; vp = vp->next) { if (ka == vp->addr) return(vp); } if (!(vp = (struct l_vfs *)malloc(sizeof(struct l_vfs)))) { (void) fprintf(stderr, "%s: PID %d, no space for vfs\n", Pn, Lp->pid); Exit(1); } vp->dir = (char *)NULL; vp->fsname = (char *)NULL; #if defined(HASFSINO) vp->fs_ino = 0; #endif /* defined(HASFSINO) */ /* * Read vfs structure from kernel, if necessary. */ if (la) v = la; else { v = &tv; if (kread((KA_T)ka, (char *)v, sizeof(tv))) { (void) free((FREE_P *)vp); return((struct l_vfs *)NULL); } } #if defined(HAS_AFS) /* * Fake the device number for an AFS device. */ if (v->vfs_fstype == AFSfstype) { if (!AFSdevStat) (void) readmnt(); v->vfs_dev = AFSdevStat ? AFSdev : 0; } #endif /* defined(HAS_AFS) */ /* * Complete mount information. */ (void) completevfs(vp, (dev_t *)&v->vfs_dev); vp->next = Lvfs; vp->addr = ka; Lvfs = vp; return(vp); } lsof-4.86+dfsg.orig/dialects/sun/dnode2.c0000444000175000017500000003264311325130240020367 0ustar nicholasnicholas/* * dnode2.c - Solaris node functions for lsof * * This module must be separate to keep separate the multiple kernel inode * structure definitions. */ /* * Copyright 1997 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dnode2.c,v 1.23 2010/01/18 19:03:54 abe Exp $"; #endif #include "lsof.h" #if defined(HASVXFS) # if defined(HASVXFSUTIL) #include #define EMSGPFX "vx_inode: " _PROTOTYPE(static char *add2em,(char * em, char *fmt, char *arg)); _PROTOTYPE(static char *ckptr,(char * em, char *ptr, int len, int slen, char *nm)); _PROTOTYPE(static char *getioffs,(char **vx, int *vxl, char **dev, int *devl, char **ino, int *inol, char **nl, int *nll, char **sz, int *szl)); # else /* !defined(HASVXFSUTIL) */ # if defined(HASVXFS_FS_H) && !defined(HASVXFS_VX_INODE) #undef fs_bsize #include # endif /* defined(HASVXFS_FS_H) && !defined(HASVXFS_VX_INODE) */ # if HASVXFS_SOL_H #include # endif /* defined(HSVXFS_SOL_H) */ # if defined(HASVXFS_SOLARIS_H) && defined(HASVXFS_U64_T) #include # 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 # endif /* defined(HASVXFS_MACHDEP_H) */ # if defined(HASVXFS_SOLARIS_H) struct kdm_vnode { /* dummy for */ 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 # endif /* defined(HASVXFS_SOLARIS_H) && !defined(HASVXFS_U64_T) */ #include #include #include # endif /* defined(HASVXFS_SOLARIS_H) */ #include # endif /* defined(HASVXFSUTIL) */ # if defined(HASVXFSUTIL) static struct vx_ioffsets Ioffsets; /* VXFS inode offsets */ static int Ioffs_state = -1; /* Ioffsets state: * -1 = uninitialized * 0 = initialized * >0 = initialization error */ /* * access_vxfs_ioffsets() - access the VXFS inode offsets */ extern int access_vxfs_ioffsets() { /* * This operation is done in an external function, so it can be done before * GID permission has been surrendered. */ Ioffs_state = vxfsu_get_ioffsets(&Ioffsets, sizeof(Ioffsets)); return(Ioffs_state); } /* * add2em() - add to error message */ static char * add2em(em, fmt, arg) char *em; /* current error message */ char *fmt; /* message format */ char *arg; /* format's single string argument */ { MALLOC_S al, eml, nl; char msg[1024]; MALLOC_S msgl = (MALLOC_S)sizeof(msg); (void) snpf(msg, msgl, fmt, arg); msg[msgl - 1] = '\0'; nl = (MALLOC_S)strlen(msg); if (!em) { al = (MALLOC_S)strlen(EMSGPFX) + nl + 1; em = (char *)malloc((MALLOC_S)al); eml = (MALLOC_S)0; } else { if (!(eml = (MALLOC_S)strlen(em))) { (void) fprintf(stderr, "%s: add2em: previous message empty\n", Pn); Exit(1); } al = eml + nl + 3; em = (char *)realloc((MALLOC_P *)em, al); } if (!em) { (void) fprintf(stderr, "%s: no VxFS error message space\n", Pn); Exit(1); } (void) snpf(em + eml, al - eml, "%s%s%s", eml ? "" : EMSGPFX, eml ? "; " : "", msg); return(em); } /* * ckptr() - check pointer and length */ static char * ckptr(em, ptr, len, slen, nm) char *em; /* pointer to previous error message */ char *ptr; /* pointer to check */ int len; /* pointer's value length */ int slen; /* value's storage length */ char *nm; /* element name */ { #if defined(_LP64) #define PTR_CAST unsigned long long #else /* !defined(_LP64) */ #define PTR_CAST unsigned long #endif /* defined(_LP64) */ PTR_CAST m; char tbuf[1024]; if (!ptr) return(add2em(em, "no %s pointer", nm ? nm : "(null)")); if (len > slen) { (void) snpf(tbuf, sizeof(tbuf) - 1, "%s size, %d, > %d", nm ? nm : "(null)", len, slen); tbuf[sizeof(tbuf) - 1] = '\0'; return(add2em(em, "%s", tbuf)); } if ((m = (PTR_CAST)(len - 1)) < (PTR_CAST)1) return(em); if ((PTR_CAST)ptr & m) return(add2em(em, "%s misaligned", nm ? nm : "(null)")); return(em); } /* * getioffs() - get the vx_inode offsets */ static char * getioffs(vx, vxl, dev, devl, ino, inol, nl, nll, sz, szl) char **vx; /* pointer to allocated vx_inode space */ int *vxl; /* sizeof(*vx) */ char **dev; /* pointer to device number element of *vx */ int *devl; /* sizeof(*dev) */ char **ino; /* pointer to node number element of *vx */ int *inol; /* sizeof(*ino) */ char **nl; /* pointer to nlink element of *vx */ int *nll; /* sizeof(*nl) */ char **sz; /* pointer to size element of *vx */ int *szl; /* sizeof(*sz) */ { char *tv; int tvl; if (Ioffs_state) return(add2em((char *)NULL, "%s error", "vxfsu_get_ioffsets")); tvl = (int)(Ioffsets.ioff_dev + Ioffsets.ioff_dev_sz); if ((Ioffsets.ioff_nlink + Ioffsets.ioff_nlink_sz) > tvl) tvl = (int)(Ioffsets.ioff_nlink + Ioffsets.ioff_nlink_sz); if ((Ioffsets.ioff_number + Ioffsets.ioff_number_sz) > tvl) tvl = (int)(Ioffsets.ioff_number + Ioffsets.ioff_number_sz); if ((Ioffsets.ioff_size + Ioffsets.ioff_size_sz) > tvl) tvl = (int)(Ioffsets.ioff_size + Ioffsets.ioff_size_sz); if (!tvl) return(add2em((char *)NULL, "zero length %s", "vx_inode")); if (!(tv = (char *)malloc((MALLOC_S)tvl))) { (void) fprintf(stderr, "%s: no vx_inode space\n", Pn); Exit(1); } *vx = tv; *vxl = tvl; *dev = tv + Ioffsets.ioff_dev; *devl = (int)Ioffsets.ioff_dev_sz; *ino = tv + Ioffsets.ioff_number; *inol = (int)Ioffsets.ioff_number_sz; *nl = tv + Ioffsets.ioff_nlink; *nll = (int)Ioffsets.ioff_nlink_sz; *sz = tv + Ioffsets.ioff_size; *szl = (int)Ioffsets.ioff_size_sz; return((char *)NULL); } # if defined(HASVXFSRNL) #define RNLCINIT 64 /* inital RNL cache size */ #define RNLCINCR 32 /* RNL cache increment */ /* * print_vxfs_rnl_path() -- print VxFS RNL path */ int print_vxfs_rnl_path(lf) struct lfile *lf; /* file whose name is to be printed */ { char **bp = (char **)NULL; int i, j, n, p; typedef struct rmc { /* RNL mount point cache */ char *mp; /* mount point */ unsigned char s; /* RNL status: 0 = supported * 1 = not supported */ } rmc_t; static rmc_t *rm = (rmc_t *)NULL; /* RNL mount point cache */ static int rma = 0; /* allocated cache entries */ static int rmu = 0; /* used cache entries */ size_t sz; /* * This must be a VxFS file, it must have an inode and its mount point must * be known. */ if (!lf->is_vxfs || (lf->inp_ty != 1) || !lf->fsdir) return(0); /* * Locate or create an RNL mount point cache entry. */ for (i = 0; i < rmu; i++) { if (rm[i].mp == lf->fsdir) break; } if (i >= rmu) { /* * A new entry must be created. */ if (i >= rma) { /* * RNL mount point cache space must be allocated. */ rma += rm ? RNLCINCR : RNLCINIT; sz = (size_t)(rma * sizeof(rmc_t)); if (rm) rm = (rmc_t *)realloc((MALLOC_P *)rm, (MALLOC_S)sz); else rm = (rmc_t *)malloc((MALLOC_S)sz); if (!rm) { (void) fprintf(stderr, "%s: no RNL mount point cache space\n", Pn); Exit(1); } } i = rmu; rm[rmu].mp = lf->fsdir; rm[rmu++].s = 0; } if (rm[i].s) return(0); /* * Get the RNL path for this mount point and inode. */ if (vxfs_inotopath(lf->fsdir, (uint64_t)lf->inode, 0, &bp, &n)) { if (errno == ENOTSUP) rm[i].s = 1; return(0); } /* * Print the first RNL path, then free the allocated function reply space. */ if (bp) { for (j = 0; j < n; j++) { if (bp[j] && *bp[j]) { safestrprt(bp[j], stdout, 0); p = 1; break; } } for (j = 0; j < n; j++) { if (bp[j]) (void) free((FREE_P *)bp[j]); } (void) free((FREE_P *)bp); } else p = 0; return(p); } # endif /* defined(HASVXFSRNL) */ # endif /* defined(HASVXFSUTIL) */ /* * read_vxnode() - read Veritas file system inode information */ int read_vxnode(va, v, vfs, fx, li, vnops) KA_T va; /* containing vnode's address */ struct vnode *v; /* containing vnode */ struct l_vfs *vfs; /* local vfs structure */ int fx; /* file system index (-1 if none) */ struct l_ino *li; /* local inode value receiver */ KA_T *vnops; /* table of VxFS v_op values */ { struct vnode cv; char tbuf[32]; # if defined(HASVXFS_VX_INODE) struct vx_inode vx; int vxl = (int)sizeof(vx); dev_t *vxn_dev = (dev_t *)&vx.i_dev; int *vxn_nlink = (int *)&vx.i_nlink; unsigned int *vxn_ino = (unsigned int *)&vx.i_number; SZOFFTYPE *vxn_sz = (SZOFFTYPE *)&vx.i_size; char *vxp = (char *)&vx; # else /* !defined(HASVXFS_VX_INODE) */ # if defined(HASVXFSUTIL) static char *em = (char *)NULL; int devl, nll, szl; static int inol; static char *vxp = (char *)NULL; static int vxl = 0; static dev_t *vxn_dev = (dev_t *)NULL; static int *vxn_nlink = (int *)NULL; static char *vxn_ino = (char *)NULL; static SZOFFTYPE *vxn_sz = (SZOFFTYPE *)NULL; # else /* !defined(HASVXFSUTIL) */ struct inode vx; int vxl = sizeof(vx); dev_t *vxn_dev = (dev_t *)&vx.i_dev; int *vxn_nlink = (int *)&vx.i_nlink; long *vxn_ino = (long *)&vx.i_number; SZOFFTYPE *vxn_sz = (SZOFFTYPE *)&vx.i_size; char *vxp = (char &)&vx; # endif /* defined(HASVXFSUTIL) */ # endif /* defined(HASVXFS_VX_INODE) */ li->dev_def = li->ino_def = li->nl_def = li->rdev_def = li->sz_def = 0; /* * See if this is vnode is served by fdd_chain_vnops. If it is, its * v_data pointer leads to the "real" vnode. */ if (v->v_data && v->v_op && (VXVOP_FDDCH < VXVOP_NUM) && vnops[VXVOP_FDDCH] && ((KA_T)v->v_op == vnops[VXVOP_FDDCH])) { if (kread((KA_T)v->v_data, (char *)&cv, sizeof(cv))) { (void) snpf(Namech, Namechl, "node at %s: can't read real vx vnode: %s", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return(1); } # if defined(HASNCACHE) Lf->na = (KA_T)v->v_data; # endif /* defined(HASNCACHE) */ *v = cv; Ntype = vop2ty(v, fx); } # if defined(HASVXFSUTIL) /* * If libvxfsutil[64].a is in use, establish the vx_inode size and the * locations and sizes of its device, link count, node number, and size * elements. * * If an error was detected while determining the vx_inode values, repeat * the error explanation in the NAME column. */ if (!vxp && !em) { em = getioffs(&vxp, &vxl, (char **)&vxn_dev, &devl, &vxn_ino, &inol, (char **)&vxn_nlink, &nll, (char **)&vxn_sz, &szl); if (!em) { /* * Check the returned pointers and their sizes. */ em = ckptr(em, (char *)vxn_dev, devl, sizeof(dev_t), "dev"); em = ckptr(em, (char *)vxn_ino, inol, sizeof(INODETYPE), "ino"); em = ckptr(em, (char *)vxn_nlink, nll, sizeof(int), "nlink"); em = ckptr(em, (char *)vxn_sz, szl, sizeof(SZOFFTYPE), "sz"); } } if (em) { (void) snpf(Namech, Namechl, "%s", em); (void) enter_nm(Namech); return(1); } # endif /* !defined(HASVXFSUTIL) */ /* * Read vnode's vx_inode. */ if (!v->v_data || kread((KA_T)v->v_data, vxp, vxl)) { (void) snpf(Namech, Namechl, "node at %s: can't read vx_inode: %s", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)v->v_data, (char *)NULL, 0)); (void) enter_nm(Namech); return(1); } /* * Return device number, inode number, link count, raw device number, and size. */ if (vfs && vfs->fsname) { li->dev = (dev_t)vfs->dev; li->dev_def = 1; } else if (vxn_dev) { li->dev = (dev_t)*vxn_dev; li->dev_def = 1; } if (vxn_ino) { # if defined(HASVXFSUTIL) switch (inol) { case sizeof(short): li->ino = (INODETYPE)*((short *)vxn_ino); li->ino_def = 1; break; case sizeof(unsigned int): li->ino = (INODETYPE)*((unsigned int *)vxn_ino); li->ino_def = 1; break; case sizeof(unsigned long long): li->ino = (INODETYPE)*((unsigned long long *)vxn_ino); li->ino_def = 1; break; default: break; } # else /* !defined(HASVXFSUTIL) */ li->ino = (INODETYPE)*vxn_ino; li->ino_def = 1; # endif /* defined(HASVXFSUTIL) */ } if (vxn_nlink) { li->nl = (long)*vxn_nlink; li->nl_def = 1; } li->rdev = v->v_rdev; li->rdev_def = 1; if (vxn_sz) { li->sz = (SZOFFTYPE)*vxn_sz; li->sz_def = 1; } return(0); } #endif /* defined(HASVXFS) */ lsof-4.86+dfsg.orig/dialects/sun/machine.h0000444000175000017500000004731411631741367020650 0ustar nicholasnicholas/* * machine.h - Solaris definitions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: machine.h,v 1.47 2011/09/07 19:16:00 abe Exp $ */ #if !defined(LSOF_MACHINE_H) #define LSOF_MACHINE_H 1 # if defined(HAS_LGRP_ROOT_CONFLICT) /* * 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 * and a macro in . */ #include # endif /* defined(HAS_LGRP_ROOT_CONFLICT) */ # if solaris>=100000 /* * Define a dummy aio_req structure for Solaris >= 10, because #include'ing * with _KERNEL defined creates too many problems. */ typedef struct aio_req { int dummy; } aio_req_t; /* * Include 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 # endif /* solaris>=100000 */ # if solaris>=20600 /* * must be #include'd for Solaris >= 2.6 while _KMEMUSER is * defined. Since also #include's and * 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 * from colliding with * the Solaris */ # 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 when _KERNEL is defined, and * doing that causes other difficulties. * * So 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 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 # if solaris>=80000 #include #include #define _KERNEL 1 #include #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 option. */ #define HASAOPT 1 /* * HASBLKDEV is defined for those dialects that want block device information * recorded in BDevtp[]. */ #define HASBLKDEV 1 /* * HASDCACHE is defined for those dialects that support a device cache * file. * * HASENVDC defined the name of an environment variable that contains the * device cache file path. The HASENVDC environment variable is ignored when * the lsof process is setuid(root) or its real UID is 0. * * HASPERSDC defines the format for the last component of a personal device * cache file path. The first will be the home directory of the real UID that * executes lsof. * * HASPERSDCPATH defines the environment variable whose value is the middle * component of the personal device cache file path. The middle component * follows the home directory and precedes the results of applying HASPERSDC. * The HASPERSDCPATH environment variable is ignored when the lsof process is * setuid(root) or its real UID is 0. * * HASSYSDC defines a public device cache file path. When it's defined, it's * used as the path from which to read the device cache. * * Consult the 00DCACHE and 00FAQ files of the lsof distribution for more * information on device cache file path construction. */ #define HASDCACHE 1 #define HASENVDC "LSOFDEVCACHE" #define HASPERSDC "%h/%p.lsof_%L" #define HASPERSDCPATH "LSOFPERSDCPATH" /* #define HASSYSDC "/your/choice/of/path" */ /* * HASCDRNODE is defined for those dialects that have CD-ROM nodes. */ /* #define HASCDRNODE 1 */ /* * HASEOPT is defined for dialects that support the +|-e option. */ /* #define HASEOPT 1 */ /* * HASFIFONODE is defined for those dialects that have FIFO nodes. */ #define HASFIFONODE 1 /* * HASFSINO is defined for those dialects that have the file system * inode element, fs_ino, in the lfile structure definition in lsof.h. */ #define HASFSINO 1 /* * HASFSTRUCT is defined if the dialect has a file structure. * * FSV_DEFAULT defines the default set of file structure values to list. * It defaults to zero (0), but may be made up of a combination of the * FSV_* symbols from lsof.h. * * If any file structure value is unavailable, its use may be suppressed * with any of the following definitions: * * HASNOFSADDR -- has no file structure address * HASNOFSFLAGS -- has no file structure flags * HASNOFSCOUNT -- has no file structure count * HASNOFSNADDR -- has no file structure node address */ #define HASFSTRUCT 1 /* #define FSV_DEFAULT FSV_? | FSV_? | FSV_? */ /* #define HASNOFSADDR 1 has no file structure address */ /* #define HASNOFSFLAGS 1 has no file structure flags */ /* #define HASNOFSCOUNT 1 has no file structure count */ /* #define HASNOFSNADDR 1 has no file structure node address */ /* * HASGNODE is defined for those dialects that have gnodes. */ /* #define HASGNODE 1 */ /* * HASHSNODE is defined for those dialects that have High Sierra nodes. */ #define HASHSNODE 1 /* * HASINODE is defined for those dialects that have inodes and wish to * use readinode() from node.c. */ /* #define HASINODE 1 */ /* * HASINTSIGNAL is defined for those dialects whose signal function returns * an int. */ /* #define HASINTSIGNAL 1 */ /* * HASKERNIDCK is defined for those dialects that support the comparison of * the build to running kernel identity. */ #define HASKERNIDCK 1 /* * HASKOPT is defined for those dialects that support the -k option of * reading the kernel's name list from an optional file. */ #define HASKOPT 1 /* * HASLFILEADD is defined for those dialects that need additional elements * in struct lfile. The HASLFILEADD definition is a macro that defines them. * * If any additional elements need to be preset in the alloc_lfile() function * of proc.c, the SETLFILEADD macro may be defined to do that. * * If any additional elements need to be cleared in alloc_lfile() or in the * free_proc() function of proc.c, the CLRLFILEADD macro may be defined to * do that. Note that CLRLFILEADD takes one argument, the pointer to the * lfile struct. The CLRLFILEADD macro is expected to expand to statements * that are complete -- i.e., have terminating semi-colons -- so the macro is * called without a terminating semicolon by proc.c. * * The HASXOPT definition may be used to select the conditions under which * private lfile elements are used. */ # if solaris>=10000 && defined(HAS_V_PATH) #define HASLFILEADD KA_T V_path; #define CLRLFILEADD(lf) (lf)->V_path = (KA_T)NULL; #define SETLFILEADD Lf->V_path = (KA_T)NULL; # endif /* solaris>=10000 && defined(HAS_V_PATH) */ /* * HASMNTSTAT indicates the dialect supports the mount stat(2) result option * in its l_vfs and mounts structures. */ # if solaris>=10000 && defined(HAS_V_PATH) #define HASMNTSTAT 1 # endif /* solaris>=10000 && defined(HAS_V_PATH) */ /* * HASMNTSUP is defined for those dialects that support the mount supplement * option. */ /* #define HASMNTSUP 1 */ /* * HASMOPT is defined for those dialects that support the reading of * kernel memory from an alternate file. */ #define HASMOPT 1 /* * HASNCACHE is defined for those dialects that have a kernel name cache * that lsof can search. A value of 1 directs printname() to prefix the * cache value with the file system directory name; 2, avoid the prefix. * * NCACHELDPFX is a set of C commands to execute before calling ncache_load(). * * NCACHELDSFX is a set of C commands to execute after calling ncache_load(). */ # if solaris>=10000 && defined(HAS_V_PATH) /* #define HASNCACHE 1 */ #else /* solaris<10 || !defined(HAS_V_PATH) */ #define HASNCACHE 1 # endif /* solaris>=10000 && defined(HAS_V_PATH) */ #define NCACHELDPFX open_kvm(); /* do before calling ncache_load() */ /* #define NCACHELDSFX ??? */ /* * HASNLIST is defined for those dialects that use nlist() to acccess * kernel symbols. */ #define HASNLIST 1 /* * HASPIPEFN is defined for those dialects that have a special function to * process DTYPE_PIPE file structure entries. Its value is the name of the * function. * * NOTE: don't forget to define a prototype for this function in dproto.h. */ /* #define HASPIPEFN process_pipe? */ /* * HASPIPENODE is defined for those dialects that have pipe nodes. */ /* #define HASPIPENODE 1 */ /* * HASPMAPENABLED is defined when the reporting of portmapper registration * info is enabled by default. */ /* #define HASPMAPENABLED 1 */ /* * HASPPID is defined for those dialects that support identification of * the parent process IDentifier (PPID) of a process. */ #define HASPPID 1 /* * HASPRINTDEV, HASPRINTINO, HASPRINTNM, HASPRINTOFF, and HASPRINTSZ * define private dialect-specific functions for printing DEVice numbers, * INOde numbers, NaMes, file OFFsets, and file SiZes. The functions are * called from print_file(). */ # if solaris<100000 #define HASPRINTDEV print_dev # endif /* solaris<100000 */ /* #define HASPRINTINO print_ino? */ /* #define HASPRINTNM print_nm? */ /* #define HASPRINTOFF print_off? */ /* #define HASPRINTSZ print_sz? */ /* * HASPRIVFILETYPE and PRIVFILETYPE are defined for dialects that have a * file structure type that isn't defined by a DTYPE_* symbol. They are * used in lib/prfp.c to select the type's processing. * * PRIVFILETYPE is the definition of the f_type value in the file struct. * * HASPRIVFILETYPE is the name of the processing function. */ /* #define HASPRIVFILETYPE process_shmf? */ /* #define PRIVFILETYPE ?? */ /* * HASPRIVNMCACHE is defined for dialects that have a private method for * printing cached NAME column values for some files. HASPRIVNAMECACHE * is defined to be the name of the function. * * The function takes one argument, a struct lfile pointer to the file, and * returns non-zero if it prints a name to stdout. */ # if solaris>=10000 && defined(HAS_V_PATH) #define HASPRIVNMCACHE print_v_path # else /* solaris<10 || !defined(HAS_V_PATH) */ # if defined(HASVXFSRNL) #define HASPRIVNMCACHE print_vxfs_rnl_path # else /* !defined(HASVXFSRNL) */ /* #define HASPRIVNMCACHE */ # 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 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 * , do that here. */ #define HASSETLOCALE 1 #define HASWIDECHAR 1 #define WIDECHARINCL #define __XPG4_CHAR_CLASS__ #include #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_ is defined for dialects that use the * in the lsof library. * * Note: other definitions and operations may be required to condition the * library function source code. They may be found in the dialect dlsof.h * header files. */ #define USE_LIB_CKKV 1 /* ckkv.c */ #define USE_LIB_COMPLETEVFS 1 /* cvfs.c */ #define USE_LIB_FIND_CH_INO 1 /* fino.c */ /* #define USE_LIB_IS_FILE_NAMED 1 isfn.c */ #define USE_LIB_LKUPDEV 1 /* lkud.c */ /* #define USE_LIB_PRINTDEVNAME 1 pdvn.c */ /* #define USE_LIB_PROCESS_FILE 1 prfp.c */ /* #define USE_LIB_PRINT_TCPTPI 1 ptti.c */ /* #define USE_LIB_READDEV 1 rdev.c */ /* #define USE_LIB_READMNT 1 rmnt.c */ /* #define USE_LIB_REGEX 1 regex.c */ /* #define USE_LIB_RNAM 1 rnam.c */ # if solaris<90000 #define USE_LIB_RNCH 1 /* rnch.c */ # endif /* solaris<90000 */ /* #define USE_LIB_RNMH 1 rnmh.c */ # if solaris<20600 #define USE_LIB_SNPF 1 /* snpf.c */ # else /* solaris>=20600 */ #define snpf snprintf /* use the system's snprintf() */ # endif /* solaris<20600 */ /* * WARNDEVACCESS is defined for those dialects that should issue a warning * when lsof can't access /dev (or /device) or one of its sub-directories. * The warning can be inhibited by the lsof caller with the -w option. */ #define WARNDEVACCESS 1 /* * WARNINGSTATE is defined for those dialects that want to suppress all lsof * warning messages. */ /* #define WARNINGSTATE 1 warnings are enabled by default */ /* * WILLDROPGID is defined for those dialects whose lsof executable runs * setgid(not_real_GID) and whose setgid power can be relinquished after * the dialect's initialize() function has been executed. */ #define WILLDROPGID 1 /* * zeromem is a macro that uses bzero or memset. */ #define zeromem(a, l) memset((void *)a, 0, l) #endif /* !defined(LSOF_MACHINE_H) */ lsof-4.86+dfsg.orig/dialects/sun/Makefile0000444000175000017500000001031411001127015020474 0ustar nicholasnicholas # 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 -m 2755 -g kmem ${PROG} ' @echo ' install -m 444 ${MAN} ' @echo '' @echo 'Your Solaris install rule actions might look something like @echo 'this:' @echo '' @echo ' install -[cf] -m 2755 -g sys ${PROG}' @echo ' install -[cf] -m 444 ${MAN}' @echo '' @echo 'You may have to put additional values in , 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 ; the appropriate destination for the' @echo 'man page in .' @echo '' ${LIB}: FRC (cd lib; ${MAKE} DEBUG="${DEBUG}" CFGF="${CFGF}") version.h: FRC @echo Constructing version.h @rm -f version.h @echo '#define LSOF_BLDCMT "${LSOF_BLDCMT}"' > version.h; @echo '#define LSOF_CC "${CC}"' >> version.h @echo '#define LSOF_CCV "${CCV}"' >> version.h @echo '#define LSOF_CCDATE "'`date`'"' >> version.h @echo '#define LSOF_CCFLAGS "'`echo ${CFLAGS} | sed 's/\\\\(/\\(/g' | sed 's/\\\\)/\\)/g' | sed 's/"/\\\\"/g'`'"' >> version.h @echo '#define LSOF_CINFO "${CINFO}"' >> version.h @if [ "X${LSOF_HOST}" = "X" ]; then \ echo '#define LSOF_HOST "'`uname -n`'"' >> version.h; \ else \ if [ "${LSOF_HOST}" = "none" ]; then \ echo '#define LSOF_HOST ""' >> version.h; \ else \ echo '#define LSOF_HOST "${LSOF_HOST}"' >> version.h; \ fi \ fi @echo '#define LSOF_LDFLAGS "${CFGL}"' >> version.h @if [ "X${LSOF_LOGNAME}" = "X" ]; then \ echo '#define LSOF_LOGNAME "${LOGNAME}"' >> version.h; \ else \ if [ "${LSOF_LOGNAME}" = "none" ]; then \ echo '#define LSOF_LOGNAME ""' >> version.h; \ else \ echo '#define LSOF_LOGNAME "${LSOF_LOGNAME}"' >> version.h; \ fi; \ fi @if [ "X${LSOF_SYSINFO}" = "X" ]; then \ echo '#define LSOF_SYSINFO "'`uname -a`'"' >> version.h; \ else \ if [ "${LSOF_SYSINFO}" = "none" ]; then \ echo '#define LSOF_SYSINFO ""' >> version.h; \ else \ echo '#define LSOF_SYSINFO "${LSOF_SYSINFO}"' >> version.h; \ fi \ fi @if [ "X${LSOF_USER}" = "X" ]; then \ echo '#define LSOF_USER "${USER}"' >> version.h; \ else \ if [ "${LSOF_USER}" = "none" ]; then \ echo '#define LSOF_USER ""' >> version.h; \ else \ echo '#define LSOF_USER "${LSOF_USER}"' >> version.h; \ fi \ fi @sed '/VN/s/.ds VN \(.*\)/#define LSOF_VERSION "\1"/' < version >> version.h FRC: # DO NOT DELETE THIS LINE - make depend DEPENDS ON IT ddev.o: ${HDR} ddev.c dfile.o: ${HDR} dfile.c dmnt.o: ${HDR} dmnt.c dnode.o: ${HDR} dnode.c dnode1.o: ${HDR} dnode1.c dnode2.o: ${HDR} dnode2.c dproc.o: ${HDR} kernelbase.h dproc.c dsock.o: ${HDR} dsock.c dstore.o: ${HDR} dstore.c arg.o: ${HDR} arg.c main.o: ${HDR} main.c misc.o: ${HDR} misc.c node.o: ${HDR} node.c print.o: ${HDR} print.c proc.o: ${HDR} proc.c store.o: ${HDR} store.c usage.o: ${HDR} version.h usage.c util.o: ${HDR} util.c # *** Do not add anything here - It will go away. *** lsof-4.86+dfsg.orig/dialects/n+os/0000755000175000017500000000000011741064216017122 5ustar nicholasnicholaslsof-4.86+dfsg.orig/dialects/n+os/dstore.c0000444000175000017500000000647507334473633020612 0ustar nicholasnicholas/* * dstore.c - NEXTSTEP and OPENSTEP global storage for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dstore.c,v 1.10 2001/08/09 11:44:07 abe Exp $"; #endif #include "lsof.h" /* * Global storage definitions */ #if defined(HAS_AFS) # if defined(HASAOPT) char *AFSApath = (char *)NULL; /* alternate AFS name list path * (from -a) */ # endif /* defined(HASAOPT) */ struct vfs *AFSVfsp = (struct vfs *)NULL; /* AFS vfs struct kernel address */ #endif /* defined(HAS_AFS) */ /* * Drive_Nl -- table to drive the building of Nl[] via build_Nl() * (See lsof.h and misc.c.) */ struct drive_Nl Drive_Nl[] = { { "arFid", "_afs_rootFid" }, { "avops", "_afs_vnodeops" }, { "avol", "_afs_volumes" }, { "aproc", "_allproc" }, { "fvops", "_fifo_vnodeops" }, { "lfsvh", "_lf_svnode_hash" }, { "mxproc", "_max_proc" }, #if defined(X_NCACHE) { X_NCACHE, "_ncache" }, #endif /* defined(X_NCACHE) */ #if defined(X_NCSIZE) { X_NCSIZE, "_ncsize" }, #endif /* defined(X_NCSIZE) */ { "nvops", "_nfs_vnodeops" }, { "svops", "_spec_vnodeops" }, { "uvops", "_ufs_vnodeops" }, { "", "", }, { NULL, NULL }, }; struct file *Fileptr; /* for process_file() in lib/prfp.c */ int Kd = -1; /* /dev/kmem file descriptor */ #if defined(HASFSTRUCT) /* * Pff_tab[] - table for printing file flags */ struct pff_tab Pff_tab[] = { { (long)FREAD, FF_READ }, { (long)FWRITE, FF_WRITE }, { (long)FNDELAY, FF_NDELAY }, { (long)FAPPEND, FF_APPEND }, { (long)FASYNC, FF_ASYNC }, { (long)FMARK, FF_MARK }, { (long)FDEFER, FF_DEFER }, { (long)FSHLOCK, FF_SHLOCK }, { (long)FEXLOCK, FF_EXLOCK }, #if defined(POSIX_KERN) { (long)FPOSIX_PIPE, FF_POSIX_PIPE }, #endif /* defined(POSIX_KERN) */ { (long)0, NULL } }; /* * Pof_tab[] - table for print process open file flags */ struct pff_tab Pof_tab[] = { # if defined(UF_EXCLOSE) { (long)UF_EXCLOSE, POF_CLOEXEC }, # endif /* defined(UF_EXCLOSE) */ # if defined(UF_MAPPED) { (long)UF_MAPPED, POF_MAPPED }, # endif /* defined(UF_MAPPED) */ # if defined(UF_FDLOCK) { (long)UF_FDLOCK, POF_FDLOCK }, # endif /* defined(UF_FDLOCK) */ { (long)0, NULL } }; #endif /* defined(HASFSTRUCT) */ lsof-4.86+dfsg.orig/dialects/n+os/dsock.c0000444000175000017500000002072510275734141020377 0ustar nicholasnicholas/* * dsock.c - NEXTSTEP and OPENSTEP socket processing functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dsock.c,v 1.17 2005/08/08 19:54:03 abe Exp $"; #endif #include "lsof.h" /* * process_socket() - process socket */ void process_socket(sa) KA_T sa; /* socket address in kernel */ { struct domain d; char *ep; unsigned char *fa = (unsigned char *)NULL; int fam; int fp, lp; struct inpcb inp; unsigned char *la = (unsigned char *)NULL; struct mbuf mb; struct protosw p; struct rawcb raw; struct socket s; size_t sz; struct tcpcb t; struct unpcb uc, unp; struct sockaddr_un *ua = NULL; struct sockaddr_un un; (void) snpf(Lf->type, sizeof(Lf->type), "sock"); Lf->inp_ty = 2; /* * Read socket structure. */ if (!sa) { enter_nm("no socket address"); return; } if (kread((KA_T) sa, (char *) &s, sizeof(s))) { (void) snpf(Namech,Namechl,"can't read socket struct from %#x",sa); enter_nm(Namech); return; } if (!s.so_type) { enter_nm("no socket type"); return; } /* * Read protocol switch and domain structures. */ if (!s.so_proto || kread((KA_T) s.so_proto, (char *) &p, sizeof(p))) { (void) snpf(Namech, Namechl, "no protocol switch"); enter_nm(Namech); return; } if (kread((KA_T) p.pr_domain, (char *) &d, sizeof(d))) { (void) snpf(Namech, Namechl, "can't read domain struct from %s", print_kptr((KA_T)p.pr_domain, (char *)NULL, 0)); enter_nm(Namech); return; } /* * Save size information. */ if (Fsize) { if (Lf->access == 'r') Lf->sz = (SZOFFTYPE)s.so_rcv.sb_cc; else if (Lf->access == 'w') Lf->sz = (SZOFFTYPE)s.so_snd.sb_cc; else Lf->sz = (SZOFFTYPE)(s.so_rcv.sb_cc + s.so_snd.sb_cc); Lf->sz_def = 1; } else Lf->off_def = 1; #if defined(HASTCPTPIQ) Lf->lts.rq = (unsigned long)s.so_rcv.sb_cc; Lf->lts.sq = (unsigned long)s.so_snd.sb_cc; Lf->lts.rqs = Lf->lts.sqs = 1; #endif /* defined(HASTCPTPIQ) */ #if defined(HASSOOPT) Lf->lts.ltm = (unsigned int)s.so_linger; Lf->lts.opt = (unsigned int)s.so_options; Lf->lts.pqlen = (unsigned int)s.so_q0len; Lf->lts.qlen = (unsigned int)s.so_qlen; Lf->lts.qlim = (unsigned int)s.so_qlimit; Lf->lts.rbsz = (unsigned long)s.so_rcv.sb_mbmax; Lf->lts.sbsz = (unsigned long)s.so_snd.sb_mbmax; Lf->lts.pqlens = Lf->lts.qlens = Lf->lts.qlims = Lf->lts.rbszs = Lf->lts.sbszs = (unsigned char)1; #endif /* defined(HASSOOPT) */ #if defined(HASSOSTATE) Lf->lts.ss = (unsigned int)s.so_state; #endif /* defined(HASSOSTATE) */ /* * Process socket by the associated domain family. */ switch ((fam = d.dom_family)) { /* * Process an Internet domain socket. */ case AF_INET: if (Fnet) Lf->sf |= SELNET; (void) snpf(Lf->type, sizeof(Lf->type), "inet"); printiproto(p.pr_protocol); /* * Read protocol control block. */ if (!s.so_pcb) { (void) snpf(Namech, Namechl, "no PCB%s%s", (s.so_state & SS_CANTSENDMORE) ? ", CANTSENDMORE" : "", (s.so_state & SS_CANTRCVMORE) ? ", CANTRCVMORE" : ""); enter_nm(Namech); return; } if (s.so_type == SOCK_RAW) { /* * Print raw socket information. */ if (kread((KA_T) s.so_pcb, (char *)&raw, sizeof(raw)) || (struct socket *)sa != raw.rcb_socket) { (void) snpf(Namech, Namechl, "can't read rawcb at %s", print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); enter_nm(Namech); return; } enter_dev_ch(print_kptr((KA_T)(raw.rcb_pcb ? raw.rcb_pcb : s.so_pcb), (char *)NULL, 0)); if (raw.rcb_laddr.sa_family == AF_INET) la = (unsigned char *)&raw.rcb_laddr.sa_data[2]; else if (raw.rcb_laddr.sa_family) printrawaddr(&raw.rcb_laddr); if (raw.rcb_faddr.sa_family == AF_INET) fa = (unsigned char *)&raw.rcb_faddr.sa_data[2]; else if (raw.rcb_faddr.sa_family) { ep = endnm(&sz); (void) snpf(ep, sz, "->"); printrawaddr(&raw.rcb_faddr); } if (fa || la) (void) ent_inaddr(la, -1, fa, -1, AF_INET); } else { /* * Print Internet socket information. */ if (kread((KA_T)s.so_pcb, (char *) &inp, sizeof(inp)) || (struct socket *)sa != inp.inp_socket) { (void) snpf(Namech, Namechl, "can't read inpcb at %s", print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); enter_nm(Namech); return; } enter_dev_ch(print_kptr((KA_T)(inp.inp_ppcb ? inp.inp_ppcb : s.so_pcb), (char *)NULL, 0)); /* * If the protocol is TCP, try to read the TCP protocol * control block to record its state. */ if (p.pr_protocol == IPPROTO_TCP && inp.inp_ppcb && kread((KA_T)inp.inp_ppcb, (char *)&t, sizeof(t)) == 0) { Lf->lts.type = 0; Lf->lts.state.i = (int)t.t_state; #if defined(HASTCPOPT) Lf->lts.mss = (unsigned long)t.t_maxseg; Lf->lts.msss = (unsigned char)1; Lf->lts.topt = (unsigned int)t.t_flags; #endif /* defined(HASTCPOPT) */ } /* * Process the local and foreign addresses from the Internet * control block. */ la = (unsigned char *)&inp.inp_laddr; lp = (int)ntohs(inp.inp_lport); if (inp.inp_faddr.s_addr != INADDR_ANY || inp.inp_fport != 0) { fa = (unsigned char *)&inp.inp_faddr; fp = (int)ntohs(inp.inp_fport); } if (fa || la) (void) ent_inaddr(la, lp, fa, fp, AF_INET); } break; /* * Process a Unix domain socket. */ case AF_UNIX: if (Funix) Lf->sf |= SELUNX; (void) snpf(Lf->type, sizeof(Lf->type), "unix"); /* * Read Unix protocol control block and the Unix address structure. */ enter_dev_ch(print_kptr(sa, (char *)NULL, 0)); if (kread((KA_T) s.so_pcb, (char *) &unp, sizeof(unp))) { (void) snpf(Namech, Namechl, "can't read unpcb at %s", print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); break; } if ((struct socket *)sa != unp.unp_socket) { (void) snpf(Namech, Namechl, "unp_socket (%s) mismatch", print_kptr((KA_T)unp.unp_socket, (char *)NULL, 0)); break; } if (unp.unp_addr) { if (kread((KA_T) unp.unp_addr, (char *) &mb, sizeof(mb))) { (void) snpf(Namech, Namechl, "can't read unp_addr at %s", print_kptr((KA_T)unp.unp_addr, (char *)NULL, 0)); break; } ua = (struct sockaddr_un *)(((char *)&mb) + mb.m_off); } if (!ua) { ua = &un; (void) bzero((char *)ua, sizeof(un)); ua->sun_family = AF_UNSPEC; } /* * Print information on Unix socket that has no address bound * to it, although it may be connected to another Unix domain * socket as a pipe. */ if (ua->sun_family != AF_UNIX) { if (ua->sun_family == AF_UNSPEC) { if (unp.unp_conn) { if (kread((KA_T)unp.unp_conn, (char *) &uc, sizeof(uc))) { (void) snpf(Namech, Namechl, "can't read unp_conn at %s", print_kptr((KA_T)unp.unp_conn,(char *)NULL,0)); } else { (void) snpf(Namech, Namechl, "->%s", print_kptr((KA_T)uc.unp_socket,(char *)NULL,0)); } } else (void) snpf(Namech, Namechl, "->(none)"); } else (void) snpf(Namech, Namechl, "unknown sun_family (%d)", ua->sun_family); break; } if (ua->sun_path[0]) { if (mb.m_len >= sizeof(struct sockaddr_un)) mb.m_len = sizeof(struct sockaddr_un) - 1; *((char *)ua + mb.m_len) = '\0'; if (Sfile && is_file_named(ua->sun_path, 0)) Lf->sf |= SELNM; if (!Namech[0]) (void) snpf(Namech, Namechl, "%s", ua->sun_path); } else (void) snpf(Namech, Namechl, "no address"); break; default: printunkaf(fam, 1); } if (Namech[0]) enter_nm(Namech); } lsof-4.86+dfsg.orig/dialects/n+os/dproc.c0000444000175000017500000004216707334473626020421 0ustar nicholasnicholas/* * dproc.c - NEXTSTEP and OPENSTEP process access functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dproc.c,v 1.12 2001/08/09 11:44:07 abe Exp $"; #endif #include "lsof.h" /* * Local static values */ static int Mxp = 0; /* maximum number of processes */ static int Np; /* number of entries in P[] */ static int Nv = 0; /* allocated Vp[] entries */ static struct proc *P = (struct proc *)NULL; /* local proc structure table */ static KA_T *Pa = (KA_T *)NULL; /* kernel address for each P[] entry */ static KA_T Kp; /* kernel process table pointer */ static KA_T *Vp = (KA_T *)NULL; /* vnode address cache */ _PROTOTYPE(static void get_kernel_access,(void)); _PROTOTYPE(static void process_map,(caddr_t map)); _PROTOTYPE(static void read_proc,(void)); /* * ckkv - check kernel version */ void ckkv(d, er, ev, ea) char *d; /* dialect */ char *er; /* expected release */ char *ev; /* expected version */ char *ea; /* expected architecture */ { #if defined(HASKERNIDCK) char m[128], *t; kernel_version_t kv; kern_return_t kr; char *vt = (char *)NULL; if (Fwarn) return; /* * Read Mach kernel version. */ if ((kr = host_kernel_version(host_self(), kv)) != KERN_SUCCESS) { (void) snpf(m, sizeof(m), "%s: can't get kernel version:", Pn); mach_error(m, kr); Exit(1); } /* * Skip blank-separated tokens until reaching "Mach". The kernel version * string follows. Eliminate anything but decimal digits and periods from * the kernel version string. */ if ((t = strtok(kv, " "))) { do { if (strcmp(t, "Mach") == 0) break; } while ((t = strtok((char *)NULL, " "))); if (t) vt = strtok((char *)NULL, " "); } if (vt) { for (t = vt; *t; t++) { if (*t == '.' || (*t >= '0' && *t <= '9')) continue; *t = '\0'; break; } } /* * Warn if the actual and expected versions don't match. */ if (!ev || !vt || strcmp(ev, vt)) (void) fprintf(stderr, "%s: WARNING: compiled for %s version %s; this is %s\n", Pn, d, ev ? ev : "UNKNOWN", vt ? vt : "UNKNOWN"); #endif /* defined(HASKERNIDCK) */ } /* * gather_proc_info() -- gather process information */ void gather_proc_info() { int i, nf, px; MALLOC_S nb; short pss, sf; struct task { /* (Should come from .) */ caddr_t d1[SIMPLE_LOCK_SIZE + 2]; caddr_t map; caddr_t d2[SIMPLE_LOCK_SIZE + 9]; struct utask *u_address; struct proc *proc; } t; struct utask *u; static struct file **uf = (struct file **)NULL; static MALLOC_S ufb = 0; struct utask ut; #if defined(HASFSTRUCT) static char *pof = (char *)NULL; static MALLOC_S pofb = 0; #endif /* defined(HASFSTRUCT) */ /* * Clear previously loaded tables and read the process table. */ #if STEPV>=31 (void) clr_svnc(); #endif /* STEPV>=31 */ (void) read_proc(); /* * Process proc structures pre-loaded in initialize(). */ for (px = 0, u = &ut; px < Np; px++) { if (is_proc_excl(P[px].p_pid, (int)P[px].p_pgrp, (UID_ARG)P[px].p_uid, &pss, &sf)) continue; /* * Read the task associated with the process, and the user * area assocated with the task. */ if (kread((KA_T)P[px].task, (char *)&t, sizeof(t))) continue; if ((KA_T)t.proc != Pa[px]) continue; if (kread((KA_T)t.u_address, (char *)&ut, sizeof(ut))) continue; if ((KA_T)ut.uu_procp != Pa[px]) continue; /* * Allocate a local process structure and start filling it. */ if (is_cmd_excl(u->u_comm, &pss, &sf)) continue; alloc_lproc(P[px].p_pid, (int)P[px].p_pgrp, (int)P[px].p_ppid, (UID_ARG)P[px].p_uid, u->u_comm, (int)pss, (int)sf); Plf = (struct lfile *)NULL; /* * Save current working directory information. */ if (u->u_cdir) { alloc_lfile(CWD, -1); FILEPTR = (struct file *)NULL; process_node((KA_T)u->u_cdir); if (Lf->sf) link_lfile(); } /* * Save root directory information. */ if (u->u_rdir) { alloc_lfile(RTD, -1); FILEPTR = (struct file *)NULL; process_node((KA_T)u->u_rdir); if (Lf->sf) link_lfile(); } /* * Print information on the text files of the virtual memory * address map. */ if (t.map) process_map(t.map); /* * Save information on file descriptors. * * NEXTSTEP file pointers come from a structure whose pointer is * in the user task area. */ nf = ut.uu_ofile_cnt; nb = (MALLOC_S)(sizeof(struct file *) * nf); if (nb > ufb) { if (!uf) uf = (struct file **)malloc(nb); else uf = (struct file **)realloc((MALLOC_P *)uf, nb); if (!uf) { (void) fprintf(stderr, "%s: no uu_ofile space\n", Pn); Exit(1); } ufb = nb; } if (kread((KA_T)ut.uu_ofile, (char *)uf, nb)) continue; #if defined(HASFSTRUCT) if (Fsv & FSV_FG) { nb = (MALLOC_S)(sizeof(char) * nf); if (nb > pofb) { if (!pof) pof = (char *)malloc(nb); else pof = (char *)realloc((MALLOC_P *)pof, nb); if (!pof) { (void) fprintf(stderr, "%s: no uu_pofile space\n", Pn); Exit(1); } pofb = nb; } if (kread((KA_T)ut.uu_pofile, (char *)pof, nb)) zeromem(pof, nb); } #endif /* defined(HASFSTRUCT) */ for (i = 0; i < nf; i++) { if (uf[i]) { alloc_lfile((char *)NULL, i); process_file((KA_T)uf[i]); if (Lf->sf) { #if defined(HASFSTRUCT) if (Fsv & FSV_FG) Lf->pof = (long)pof[i]; #endif /* defined(HASFSTRUCT) */ link_lfile(); } } } /* * Examine results. */ if (examine_lproc()) return; } } /* * get_kernel_access() - access the required information in the kernel */ static void get_kernel_access() { int i; KA_T lv; #if defined(HAS_AFS) struct nlist *nl = (struct nlist *)NULL; unsigned long v[3]; #endif /* defined(HAS_AFS) */ /* * Check kernel version against compiled version. */ ckkv("NEXTSTEP", (char *)NULL, LSOF_VSTR, (char *)NULL); #if defined(WILLDROPGID) /* * If kernel memory isn't coming from KMEM, drop setgid permission * before attempting to open the (Memory) file. */ if (Memory) (void) dropgid(); #else /* !defined(WILLDROPGID) */ /* * See if the non-KMEM memory file is readable. */ if (Memory && !is_readable(Memory, 1)) Exit(1); #endif /* defined(WILLDROPGID) */ /* * Access the kernel memory file. */ if ((Kd = open(Memory ? Memory : KMEM, O_RDONLY, 0)) < 0) { (void) fprintf(stderr, "%s: can't open %s: %s\n", Pn, Memory ? Memory : KMEM, strerror(errno)); Exit(1); } #if defined(WILLDROPGID) /* * Drop setgid permission, if necessary. */ if (!Memory) (void) dropgid(); #else /* !defined(WILLDROPGID) */ /* * See if the name list file is readable. Build Nl. */ if (Nmlst && !is_readable(Nmlst, 1)) Exit(1); #endif /* defined(WILLDROPGID) */ (void) build_Nl(Drive_Nl); #if defined(HAS_AFS) if (!Nmlst) { /* * If AFS is defined and we're getting kernel symbol values from * from N_UNIX, make a copy of Nl[] for possible use with the AFS * module name list file. */ if (!(nl = (struct nlist *)malloc(Nll))) { (void) fprintf(stderr, "%s: no space (%d) for Nl[] copy\n", Pn, Nll); Exit(1); } (void) bcopy((char *)Nl, (char *)nl, Nll); } #endif /* defined(HAS_AFS) */ /* * Access the name list file. */ if (nlist(Nmlst ? Nmlst : VMUNIX, Nl) < 0) { (void) fprintf(stderr, "%s: can't read namelist from %s\n", Pn, Nmlst ? Nmlst : VMUNIX); Exit(1); } if (get_Nl_value("aproc", Drive_Nl, &lv) < 0 || !lv) { (void) fprintf(stderr, "%s: can't get proc table address\n", Pn); Exit(1); } #if defined(HAS_AFS) if (nl) { /* * If AFS is defined and we're getting kernel symbol values from * N_UNIX, and if any X_AFS_* symbols isn't there, see if it is in the * the AFS module name list file. Make sure that other symbols that * appear in both name list files have the same values. */ if (get_Nl_value("arFID", Drive_Nl, &v[0]) >= 0 && get_Nl_value("avol", Drive_Nl, &v[1]) >= 0 && get_Nl_value("avol", Drive_Nl, &v[2]) >= 0 && (!vo[0] || !v[1] || !v[2])) (void) ckAFSsym(nl); (void) free((MALLOC_P *)nl); } #endif /* defined(HAS_AFS) */ /* * Establish a maximum process count estimate. */ if (get_Nl_value("mxproc", Drive_Nl, &lv) < 0 || kread((KA_T)lv, (char *)&Mxp, sizeof(Mxp)) || Mxp < 1) Mxp = PROCDFLT; } /* * initialize() - perform all initialization */ void initialize() { get_kernel_access(); } /* * kread() - read from kernel memory */ int kread(addr, buf, len) KA_T addr; /* kernel memory address */ char *buf; /* buffer to receive data */ READLEN_T len; /* length to read */ { int br; if (lseek(Kd, (off_t)addr, L_SET) == (off_t)-1L) return(-1); br = read(Kd, buf, len); return((br == len) ? 0 : 1); } /* * process_map() - process vm map for vnode references */ static void process_map(map) caddr_t map; { int i, j, n, ne; #if STEPV<40 /* * Structures for NeXTSTEP and OPENSTEP < 4.0. */ struct vm_map_entry { /* (Should come from ). */ struct vm_map_entry *prev; struct vm_map_entry *next; unsigned int start; unsigned int end; caddr_t object; unsigned int offset; unsigned int is_a_map:1, is_sub_map:1, copy_on_write:1, needs_copy:1; int protection; int max_protection; int inheritance; int wired_count; } vme, *vmep; #define VME_NEXT(entry) entry.next struct vm_map { /* (Should come from .) */ caddr_t d1[SIMPLE_LOCK_SIZE + 2]; struct vm_map_entry header; int nentries; caddr_t pmap; unsigned int size; boolean_t is_main_map; } vmm; struct vm_object { /* (Should come from .) */ caddr_t d1[SIMPLE_LOCK_SIZE + 4]; unsigned int size; short ref_count, resident_page_count; caddr_t copy; caddr_t pager; int pager_request, pager_name; unsigned int paging_offset; caddr_t shadow; } vmo, vmso; #else /* STEPV>=40 */ /* * Structures for OPENSTEP >= 4.0. */ struct vm_map_links { /* (Should come from ). */ struct vm_map_entry *prev; struct vm_map_entry *next; unsigned int start; unsigned int end; }; struct vm_map_entry { /* (Should come from ). */ struct vm_map_links links; caddr_t object; unsigned int offset; unsigned int is_shared:1, is_sub_map:1, in_transition:1, needs_wakeup:1, behavior:2, needs_copy:1, protection:3, max_protection:3, inheritance:2, pad1:1, alias:8; unsigned short wired_count; unsigned short user_wired_count; } vme, *vmep; #define VME_NEXT(entry) entry.links.next struct vm_map_header { /* (Should come from .) */ struct vm_map_links links; int nentries; int entries_pageable; }; struct vm_map { /* (Should come from .) */ caddr_t d1[SIMPLE_LOCK_SIZE + 2]; struct vm_map_header hdr; caddr_t pmap; unsigned int size; boolean_t is_main_map; /* Darwin header has this as ref_count, * but we'll take some liberties ... */ } vmm; struct vm_object { /* (Should come from .) */ caddr_t d1[SIMPLE_LOCK_SIZE + 4]; unsigned int size; short ref_count, resident_page_count; caddr_t copy; caddr_t shadow; unsigned int shadow_offset; caddr_t pager; unsigned int paging_offset; int pager_request; } vmo, vmso; #endif /* STEPV<40 */ struct vstruct { /* (Should come from .) */ boolean_t is_device; caddr_t vs_pf; caddr_t pfMapEntry; unsigned int vs_swapfile:1; short vs_count; int vs_size; caddr_t vs_vp; } vmp; /* * Read the vm map. */ if (!map || kread((KA_T)map, (char *)&vmm, sizeof(vmm))) return; if (!vmm.is_main_map) return; /* * Look for non-map and non-sub-map vm map entries that have an object * with a shadow whose pager pointer addresses a non-swap-file istruct * that has a vnode pointer. Process the unique vnodes found. */ #if STEPV<40 vme = vmm.header; ne = vmm.nentries; #else /* STEPV>=40 */ if (!vmm.hdr.links.next || kread((KA_T)vmm.hdr.links.next, (char *)&vme, sizeof(vme))) return; ne = vmm.hdr.nentries; #endif /* STEPV<40 */ if (ne > 1000) ne = 1000; for (i = n = 0; i < ne; i++) { if (i) { if (!VME_NEXT(vme) || kread((KA_T)VME_NEXT(vme), (char *)&vme, sizeof(vme))) continue; } #if STEPV<40 if (vme.is_a_map || vme.is_sub_map) #else /* STEPV>=40 */ if (vme.is_sub_map) #endif /* STEPV<40 */ continue; if (!vme.object || kread((KA_T)vme.object, (char *)&vmo, sizeof(vmo))) continue; if (!vmo.shadow || kread((KA_T)vmo.shadow, (char *)&vmso, sizeof(vmso))) continue; if (!vmso.pager || kread((KA_T)vmso.pager, (char *)&vmp, sizeof(vmp))) continue; if (vmp.is_device || vmp.vs_swapfile || !vmp.vs_vp) continue; /* * See if the vnode has been processed before. */ for (j = 0; j < n; j++) { if ((KA_T)vmp.vs_vp == Vp[j]) break; } if (j < n) continue; /* * Process a new vnode. */ alloc_lfile("txt", -1); FILEPTR = (struct file *)NULL; process_node((KA_T)vmp.vs_vp); if (Lf->sf) link_lfile(); /* * Allocate space for remembering the vnode. */ if (!Vp) { if (!(Vp = (KA_T *)malloc((MALLOC_S) (sizeof(struct vnode *) * 10)))) { (void) fprintf(stderr, "%s: no txt ptr space, PID %d\n", Pn, Lp->pid); Exit(1); } Nv = 10; } else if (n >= Nv) { Nv += 10; if (!(Vp = (KA_T *)realloc((MALLOC_P *)Vp, (MALLOC_S)(Nv * sizeof(struct vnode *))))) { (void) fprintf(stderr, "%s: no more txt ptr space, PID %d\n", Pn, Lp->pid); Exit(1); } } Vp[n++] = (KA_T)vmp.vs_vp; } } /* * read_proc() - read proc structures */ static void read_proc() { static KA_T apav = (KA_T)0; static int apax = -1; int i, try; static int sz = 0; KA_T kp; struct proc *p; /* * Try PROCTRYLM times to read a valid proc table. */ for (try = 0; try < PROCTRYLM; try++) { /* * Read kernel's process list pointer. This needs to be done each * time lsof rereads the process list. */ if (apax < 0) { if ((apax = get_Nl_value("aproc", Drive_Nl, &apav)) < 0) { (void) fprintf(stderr, "%s: can't get process table address pointer\n", Pn); Exit(1); } } if (kread((KA_T)apav, (char *)&Kp, sizeof(Kp))) { if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: can't read %s from %#x\n", Pn, Nl[apax].n_un.n_name, apav); continue; } /* * Pre-allocate proc structure space. */ if (sz == 0) { sz = Mxp; if (!(P = (struct proc *)malloc((MALLOC_S) (sz * sizeof(struct proc))))) { (void) fprintf(stderr, "%s: no proc table space\n", Pn); Exit(1); } if (!(Pa = (KA_T *)malloc((MALLOC_S)(sz * sizeof(KA_T))))) { (void) fprintf(stderr, "%s: no proc pointer space\n", Pn); Exit(1); } } /* * Accumulate proc structures. */ for (kp = Kp, Np = 0; kp; ) { if (kread(kp, (char *)&P[Np], sizeof(struct proc))) { Np = 0; break; } Pa[Np] = kp; kp = (KA_T)P[Np].p_nxt; if (P[Np].p_stat == 0 || P[Np].p_stat == SZOMB) continue; Np++; if (Np >= sz) { /* * Expand the local proc table. */ sz += PROCDFLT/2; if (!(P = (struct proc *)realloc((MALLOC_P *)P, (MALLOC_S)(sizeof(struct proc) * sz)))) { (void) fprintf(stderr, "%s: no more (%d) proc space\n", Pn, sz); Exit(1); } if (!(Pa = (KA_T *)realloc((MALLOC_P *)Pa, (MALLOC_S)(sizeof(KA_T) * sz)))) { (void) fprintf(stderr, "%s: no more (%d) proc ptr space\n", Pn, sz); Exit(1); } } } /* * If not enough processes were saved in the local table, try again. */ if (Np >= PROCMIN) break; } /* * Quit if no proc structures were stored in the local table. */ if (try >= PROCTRYLM) { (void) fprintf(stderr, "%s: can't read proc table\n", Pn); Exit(1); } if (Np < sz && !RptTm) { /* * Reduce the local proc structure table size to a minimum if * not in repeat mode. */ if (!(P = (struct proc *)realloc((MALLOC_P *)P, (MALLOC_S)(sizeof(struct proc) * Np)))) { (void) fprintf(stderr, "%s: can't reduce proc table to %d\n", Pn, Np); Exit(1); } if (!(Pa = (KA_T *)realloc((MALLOC_P *)Pa, (MALLOC_S)(sizeof(KA_T) * Np)))) { (void) fprintf(stderr, "%s: can't reduce proc ptrs to %d\n", Pn, Np); Exit(1); } } } lsof-4.86+dfsg.orig/dialects/n+os/dproto.h0000444000175000017500000000320707334473630020611 0ustar nicholasnicholas/* * dproto.h - NEXTSTEP and OPENSTEP function prototypes for lsof * * The _PROTOTYPE macro is defined in the common proto.h. */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: dproto.h,v 1.6 2001/08/09 11:44:07 abe Exp $ */ #if STEPV>=31 _PROTOTYPE(extern void clr_svnc,(void)); #endif /* STEPV>=31 */ _PROTOTYPE(extern int is_file_named,(char *p, int cd)); #if defined(HAS_AFS) _PROTOTYPE(extern struct vnode *alloc_vcache,(void)); _PROTOTYPE(extern void ckAFSsym,(struct nlist *nl)); _PROTOTYPE(extern int hasAFS,(struct vnode *vp)); _PROTOTYPE(extern void process_socket,(KA_T vp)); _PROTOTYPE(extern int readafsnode,(caddr_t va, struct vnode *v, struct afsnode * an)); #endif /* defined(HAS_AFS) */ lsof-4.86+dfsg.orig/dialects/n+os/dlsof.h0000444000175000017500000001424210412331727020401 0ustar nicholasnicholas/* * dlsof.h - NEXTSTEP and OPENSTEP header file for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: dlsof.h,v 1.14 2006/03/28 22:08:17 abe Exp $ */ #if !defined(LSOF_NEXT_H) #define LSOF_NEXT_H 1 #include #include #include #include #include #include #include # if !defined(NCPUS) #define NCPUS 1 # endif #include #include #include #include #include #include #include #include #include #include #include # if !defined(KERNEL) #define KERNEL # endif #include #undef KERNEL #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include # if !defined(SHOW_UTT) #define SHOW_UTT # endif /* * Define simple_lock_t size. */ # if STEPV>=40 && defined(m68k) #define SIMPLE_LOCK_SIZE 0 # elif defined(hppa) /* && (STEPV<40 || !defined(m68k)) */ #define SIMPLE_LOCK_SIZE 4 # else /* (STEPV<40 || !defined(m68k)) && !defined(hppa) */ #define SIMPLE_LOCK_SIZE 1 # endif /* STEPV>=40 && defined(m68k) */ # if !defined(SIMPLE_LOCK_SIZE) #define SIMPLE_LOCK_SIZE 1 # endif /* !defined(SIMPLE_LOCK_SIZE) */ # if STEPV>=40 /* * Define lock_data_t that was removed from OPENSTEP 4.x's . */ typedef struct lock { char *thread; unsigned int read_count:16, want_upgrade:1, want_write:1, waiting:1, can_sleep:1, recursion_depth:12; # if SIMPLE_LOCK_SIZE>0 caddr_t interlock[SIMPLE_LOCK_SIZE]; # endif /* SIMPLE_LOCK_SIZE>0 */ } lock_data_t; # endif /* STEPV>=40 */ #include #define u_comm uu_comm #define u_cdir uu_cdir #define u_rdir uu_rdir #undef SHOW_UTT #include #include #include typedef int pid_t; /* * The following substitution compensates for the snode.h that NeXT does * not supply in NEXTSTEP 2.0 and above. The value of interest is s_realvp. */ struct snode { struct snode *s_next; /* must be first */ struct vnode s_vnode; /* vnode associated with this snode */ struct vnode *s_realvp; /* vnode for the fs entry (if any) */ }; /* * Miscellaneous definitions. */ #define COMP_P const void #define DEVINCR 1024 /* device table malloc() increment */ typedef off_t KA_T; #define KMEM "/dev/kmem" #define MALLOC_P void #define FREE_P MALLOC_P #define MALLOC_S size_t #define MAXSYSCMDL MAXCOMLEN /* max system command name length */ #define PROCDFLT 256 /* default size of local proc table */ #define PROCMIN 5 /* processes that make a "good" scan */ #define PROCSIZE sizeof(struct proc) #define PROCTRYLM 5 /* times to try to read proc table */ #define QSORT_P void #define READLEN_T int #define STRNCPY_L int #define U_SIZE sizeof(struct user) # if !defined(VMUNIX) #define VMUNIX "/mach" # endif #define N_UNIX VMUNIX # if defined(HAS_AFS) /* * AFS definitions */ #define AFSAPATHDEF "/usr/vice/etc/afs_loadable" #define AFSDEV 1 /* AFS "fake" device number */ # if defined(HASAOPT) extern char *AFSApath; /* alternate AFS name list path * (from -A) */ # endif /* defined(HASAOPT) */ extern struct vfs *AFSVfsp; /* AFS struct vfs kernel pointer */ # endif /* defined(HAS_AFS) */ /* * Local mount information */ struct mounts { char *dir; /* directory (mounted on) */ char *fsname; /* file system * (symbolic links unresolved) */ char *fsnmres; /* file system * (symbolic links resolved) */ dev_t dev; /* directory st_dev */ dev_t rdev; /* directory st_rdev */ INODETYPE inode; /* directory inode number */ u_short mode; /* directory st_mode */ u_short fs_mode; /* file system st_mode */ struct mounts *next; /* forward link */ }; /* * Defines for kernel name list */ #define NL_NAME n_un.n_name /* * For kernel name cache processing */ # if defined(HASNCACHE) #include #define X_NCACHE "nch" #define X_NCSIZE "ncsz" # endif /* defined(HASNCACHE) */ /* * Defines for library readdev() function */ #define DIRTYPE direct #define HASDNAMLEN 1 /* * Search file information */ struct sfile { char *aname; /* file name argument */ char *name; /* file name (after readlink()) */ char *devnm; /* device name (optional) */ dev_t dev; /* device */ dev_t rdev; /* raw device */ u_short mode; /* S_IFMT mode bits from stat() */ int type; /* file type: 0 = file system * 1 = regular file */ INODETYPE i; /* inode number */ int f; /* file found flag */ struct sfile *next; /* forward link */ }; /* * Miscellaneous external definitions */ extern struct file *Fileptr; #define FILEPTR Fileptr /* for process_file() in lib/prfp.c */ extern int Kd; #endif /* LSOF_NEXT_H */ lsof-4.86+dfsg.orig/dialects/n+os/dnode1.c0000444000175000017500000002232210275734141020441 0ustar nicholasnicholas/* * dnode1.h - NEXTSTEP and OPENSTEP AFS support */ /* * Copyright 1996 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1996 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dnode1.c,v 1.7 2005/08/08 19:54:03 abe Exp $"; #endif #if defined(HAS_AFS) #include "lsof.h" #include #define __XDR_INCLUDE__ #include #include #include #include /* * This is an emulation of the afs_rwlock_t definition that appears in * the AFS sources in afs/lock.h. */ struct afs_lock { # if HAS_AFS<304 unsigned char d1[4]; # else /* HAS_AFS>=304 */ unsigned char d1[6]; # endif /* HAS_AFS<304 */ }; typedef struct afs_lock afs_lock_t; typedef struct afs_lock afs_rwlock_t; /* * This is an emulation of the afs_bozoLock_t definition that appears in * the AFS sources in afs/lock.h. */ struct afs_bozoLock { short d1; char d2[2]; char *d3; }; typedef struct afs_bozoLock afs_bozoLock_t; #define KERNEL #include #undef KERNEL /* * Local function prototypes */ _PROTOTYPE(static struct volume *getvolume,(struct VenusFid *f, int *vols)); _PROTOTYPE(static int is_rootFid,(struct vcache *vc, int *rfid)); /* * alloc_vcache() - allocate space for vcache structure */ struct vnode * alloc_vcache() { return((struct vnode *)malloc(sizeof(struct vcache))); } /* * ckAFSsym() - check for missing X_AFS_* symbols in AFS name list file */ void ckAFSsym(nl) struct nlist *nl; /* copy of Nl[] when empty */ { char *path = AFSAPATHDEF; int i; # if defined(HASAOPT) if (AFSApath) path = AFSApath; # endif /* defined(HASAOPT) */ /* * See if the alternate AFS name list file can be read. */ if (!is_readable(path, 0)) { if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: can't access AFS name list file: %s\n", Pn, path); return; } /* * Read the AFS modload symbols and compare its non-zero values with * the non-zero values in Nl[]. Quit if there is any mis-match. */ if (nlist(path, nl) < 0) return; for (i = 0; Nl[i].n_un.n_name && Nl[i].n_un.n_name[0]; i++) { if (!nl[i].n_value || !Nl[i].n_value) continue; if (nl[i].n_value != Nl[i].n_value) return; } /* * If any AFS kernel name list symbol that doesn't have a value in Nl[] has * one from the AFS modload file, copy its modload value to Nl[]. */ if ((i = get_Nl_value("arFid", Drive_Nl, NULL)) >= 0 && !Nl[i].n_value && nl[i].n_value) Nl[i].n_value = nl[i].n_value; if ((i = get_Nl_value("avops", Drive_Nl, NULL)) >= 0 && !Nl[i].n_value && nl[i].n_value) Nl[i].n_value = nl[i].n_value; if ((i = get_Nl_value("avol", Drive_Nl, NULL)) >= 0 && !Nl[i].n_value && nl[i].n_value) Nl[i].n_value = nl[i].n_value; } /* * getvolume() - get volume structure */ static struct volume * getvolume(f, vols) struct VenusFid *f; /* file ID pointer */ int *vols; /* afs_volumes status return */ { int i; static KA_T ka = 0; KA_T kh; static struct volume v; struct volume *vp; static int w = 0; if (!ka) { if (get_Nl_value("avol", Drive_Nl, (unsigned long *)&ka) < 0 || !ka) { if (!w && !Fwarn) { (void) fprintf(stderr, "%s: WARNING: no kernel address for afs_volumes\n", Pn); (void) fprintf(stderr, " This may hamper AFS node number reporting.\n"); w = 1; } *vols = 0; return((struct volume *)NULL); } } *vols = 1; i = (NVOLS - 1) & f->Fid.Volume; kh = (KA_T)((char *)ka + (i * sizeof(struct volume *))); if (kread(kh, (char *)&vp, sizeof(vp))) return((struct volume *)NULL); while (vp) { if (kread((KA_T)vp, (char *)&v, sizeof(v))) return((struct volume *)NULL); if (v.volume == f->Fid.Volume && v.cell == f->Cell) return(&v); vp = v.next; } return((struct volume *)NULL); } /* * hasAFS() - test for AFS presence via vfs structure */ int hasAFS(vp) struct vnode *vp; /* vnode pointer */ { struct mounts *mp; int n; struct vfs v; /* * If this vnode has a v_data pointer, then it probably isn't an AFS vnode; * return FALSE. * * If the vfs struct address of /afs is known and this vnode's v_vfsp matches * it, return TRUE. * * Read this vnode's vfs structure and see if it's device (fsid.val[0]) is * AFSDEV. If it is, record the AFS vfs struct address and return TRUE. */ if (AFSVfsp && !vp->v_data && vp->v_vfsp == AFSVfsp) return(1); if (vp->v_data || !vp->v_vfsp || kread((KA_T)vp->v_vfsp, (char *)&v, sizeof(v)) || v.vfs_data) return(0); if (v.vfs_fsid.val[0] == AFSDEV) { AFSVfsp = vp->v_vfsp; return(1); } /* * Search the local mount table for /afs devices or a match on device number. * Count /afs devices and skip a device number test for them. A match on * device number for non-AFS devices produces a FALSE return. */ for (mp = readmnt(), n = 0; mp; mp = mp->next) { if (mp->dev == AFSDEV && mp->dir && strcmp(mp->dir, "/afs") == 0 && mp->fsname && strcmp(mp->fsname, "AFS") == 0) n++; else if (mp->dev == (dev_t)v.vfs_fsid.val[0]) return(0); } /* * If there is exactly one /afs device, assume its vfs struct address is * the one for this vnode, record it, and return TRUE. */ if (n == 1) { AFSVfsp = vp->v_vfsp; return(1); } return(0); } /* * is_rootFid() - is the file ID the root file ID * * return: 0 = is not root file ID * 1 = is root file ID * rfid = 0 if root file ID structure address not available * 1 if root file ID structure address available */ static int is_rootFid(vc, rfid) struct vcache *vc; /* vcache structure */ int *rfid; /* root file ID pointer status return */ { unsigned long arFid; char *err; static int f = 0; /* rootFid structure status: * -1 = unavailable * 0 = not yet accessed * 1 = available */ static struct VenusFid r; static int w = 0; switch (f) { case -1: if (vc->v.v_flag & VROOT) { *rfid = 1; return(1); } *rfid = 0; return(0); case 0: if (get_Nl_value("arFid", Drive_Nl, &arFid) < 0 || !arFid) { err = "no _afs_rootFid kernel address"; rfid_unavailable: if (!w && !Fwarn) { (void) fprintf(stderr, "%s: WARNING: AFS root Fid error: %s\n", Pn, err); (void) fprintf(stderr, " This may hamper AFS node number reporting.\n"); w = 1; } f = -1; if (vc->v.v_flag & VROOT) { *rfid = 1; return(1); } *rfid = 0; return(0); } if (kread((KA_T)arFid, (char *)&r, sizeof(r))) { err = "can't read _afs_rootFid from kernel"; goto rfid_unavailable; } f = 1; /* fall through */ case 1: *rfid = 1; if (vc->fid.Fid.Unique == r.Fid.Unique && vc->fid.Fid.Vnode == r.Fid.Vnode && vc->fid.Fid.Volume == r.Fid.Volume && vc->fid.Cell == r.Cell) return(1); } *rfid = 0; return(0); } /* * readafsnode() - read AFS node */ int readafsnode(va, v, an) caddr_t va; /* kernel vnode address */ struct vnode *v; /* vnode buffer pointer */ struct afsnode *an; /* afsnode recipient */ { char *cp; KA_T ka; int len, rfid, vols; struct vcache *vc; struct volume *vp; cp = ((char *)v + sizeof(struct vnode)); ka = (KA_T)((char *)va + sizeof(struct vnode)); len = sizeof(struct vcache) - sizeof(struct vnode); if (kread(ka, cp, len)) { (void) snpf(Namech, Namechl, "vnode at %#x: can't read vcache remainder from %#x", va, ka); enter_nm(Namech); return(1); } vc = (struct vcache *)v; an->dev = AFSDEV; an->size = (unsigned long)vc->m.Length; an->nlink = (long)vc->m.LinkCount; an->nlink_st = 1; /* * Manufacture the "inode" number. */ if (vc->mvstat == 2) { if ((vp = getvolume(&vc->fid, &vols))) { an->inode = (INODETYPE)(vp->mtpoint.Fid.Vnode + (vp->mtpoint.Fid.Volume << 16)); if (an->inode == (INODETYPE)0) { if (is_rootFid(vc, &rfid)) an->ino_st = 1; else if (rfid) { an->inode = (INODETYPE)2; an->ino_st = 1; } else an->ino_st = 0; } else an->ino_st = 1; } else { if (vols) { an->inode = (INODETYPE)2; an->ino_st = 1; } else { if (v->v_flag & VROOT) { an->inode = (INODETYPE)0; an->ino_st = 1; } else an->ino_st = 0; } } } else { an->inode = (INODETYPE)((vc->fid.Fid.Vnode + (vc->fid.Fid.Volume << 16)) & 0x7fffffff); an->ino_st = 1; } return(0); } #endif /* defined(HAS_AFS) */ lsof-4.86+dfsg.orig/dialects/n+os/Mksrc0000555000175000017500000000105407334473613020135 0ustar nicholasnicholas#!/bin/sh # # Mksrc - make NEXTSTEP and OPENSTEP source files # # WARNING: This script assumes it is running from the main directory # of the lsof, version 4 distribution. # # One environment variable is supplied: # # LSOF_MKC is the method for creating the source files. # It defaults to "ln -s". A common alternative is "cp". # # $Id: Mksrc,v 1.6 2001/08/09 11:44:07 abe Exp $ D=dialects/n+os L="dlsof.h dnode.c dnode1.c dproc.c dproto.h dsock.c dstore.c machine.h" for i in $L do rm -f $i $LSOF_MKC $D/$i $i echo "$LSOF_MKC $D/$i $i" done lsof-4.86+dfsg.orig/dialects/n+os/dnode.c0000444000175000017500000003453310412331731020356 0ustar nicholasnicholas/* * dnode.c - NEXTSTEP and OPENSTEP node functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dnode.c,v 1.17 2006/03/28 22:08:17 abe Exp $"; #endif #include "lsof.h" #if STEPV>=31 /* * Local definitions */ struct l_lockf { /* local lock info */ short type; /* lock type */ off_t start, end; /* lock start and end */ pid_t pid; /* owning process ID */ struct l_lockf *next; }; struct l_svn { /* shadow vnode */ KA_T vp; /* associated vnode */ struct l_lockf *lp; /* local lock chain */ struct l_svn *next; }; struct posix_proc { pid_t p_pid; }; #define POSIX_KERN 1 #include #define SVNHASH(n) (((int)((long)(n) * 31415l) >> 5) & (LF_SVNODE_HSZ - 1)) /* * Local static variables */ static struct l_svn **Svnc = (struct l_svn **)NULL; /* local shadow vnode cache */ static int SvncSt = 0; /* Svnc[] load status */ /* * Local function prototypes */ _PROTOTYPE(static char isvlocked,(KA_T vp)); _PROTOTYPE(static int load_svnc,(void)); /* * clr_svnc() - clear shadow vnode cache */ void clr_svnc() { struct l_lockf *lf, *lfn; int i; struct l_svn *sv, *svn; if (!Svnc || !SvncSt) return; for (i = 0; i < LF_SVNODE_HSZ; i++) { if (!(sv = Svnc[i])) continue; do { if ((lf = sv->lp)) { do { lfn = lf->next; (void) free((FREE_P *)lf); } while ((lf = lfn)); } svn = sv->next; (void) free((FREE_P *)sv); } while ((sv = svn)); Svnc[i] = (struct l_svn *)NULL; } SvncSt = 0; } /* * isvlocked() - is vnode locked? */ static char isvlocked(vp) KA_T vp; /* vnode's kernel address */ { int i; struct l_lockf *lp; struct l_svn *sv; if (!Svnc || !SvncSt) { if (!load_svnc()) return(' '); } /* * Hash the vnode address and see if there's a shadow (lock) vnode structure * assigned to it. */ i = SVNHASH(vp); for (sv = Svnc[i]; sv; sv = sv->next) { if ((KA_T)sv->vp == vp) break; } if (!sv) return(' '); /* * Search the lock owners represented by the shadow vnode's lock chain * for this process. */ for (lp = sv->lp; lp; lp = lp->next) { if (lp->pid == (pid_t)Lp->pid) { if (lp->start == 0 && lp->end == 0x7fffffff) i = 1; else i = 0; if (lp->type == F_RDLCK) return(i ? 'R' : 'r'); else if (lp->type == F_WRLCK) return(i ? 'W' : 'w'); return(' '); } } return(' '); } /* * load_svnc() - load the shadow vnode cache */ int load_svnc() { int i, j; static KA_T kp = (KA_T)NULL; struct lockf lf, *lp; struct l_lockf *lsf; struct l_svn *lsv; struct posix_proc p; struct lf_svnode *sn, *sp[LF_SVNODE_HSZ], sv; if (Svnc && SvncSt) return(1); /* * Get the shadow vnode hash table address from the kernel. */ if (!kp) { if (get_Nl_value("lfsvh", Drive_Nl, &kp) < 0 || !kp) return(0); } /* * Define local hash buckets, if necessary. */ if (!Svnc) { if (!(Svnc = (struct l_svn **)calloc(sizeof(struct l_svn *), LF_SVNODE_HSZ))) { (void) fprintf(stderr, "%s: no space for %d local shadow vnode hash buckets\n", Pn, LF_SVNODE_HSZ); Exit(1); } } /* * Search the hash buckets of the shadow vnode table. */ if (kread(kp, (char *)&sp, sizeof(sp))) return(0); for (i = 0; i < LF_SVNODE_HSZ; i++) { if (!(sn = sp[i])) continue; do { /* * Duplicate the chain of shadow vnodes in the bucket. */ if (kread((KA_T)sn, (char *)&sv, sizeof(sv)) || !sv.lf_vnodep || !sv.lf_lockfp) break; /* * Allocate and initialize a local shadow vnode structure. */ if (!(lsv = (struct l_svn *)malloc(sizeof(struct l_svn)))) { (void) fprintf(stderr, "%s: no space for local shadow vnode -- PID: %ld\n", Pn, Lp->pid); Exit(1); } lsv->vp = (KA_T)sv.lf_vnodep; lsv->lp = (struct l_lockf *)NULL; lsv->next = (struct l_svn *)NULL; lp = sv.lf_lockfp; do { /* * Duplicate the lock chain for this shadow vnode. */ if (kread((KA_T)lp, (char *)&lf, sizeof(lf))) break; if (!lf.lf_posix_procp || kread((KA_T)lf.lf_posix_procp, (char *)&p, sizeof(p)) || !p.p_pid) continue; if (!(lsf=(struct l_lockf *)malloc(sizeof(struct l_lockf)))) { (void) fprintf(stderr, "%s: no space for local lock struct -- PID: %ld\n", Pn, Lp->pid); Exit(1); } lsf->type = lf.lf_type; lsf->start = lf.lf_start; lsf->end = lf.lf_end; lsf->pid = (pid_t)p.p_pid; lsf->next = lsv->lp; lsv->lp = lsf; } while ((lp = lf.lf_next)); /* * Link the shadow vnode to its local hash bucket. */ j = SVNHASH(lsv->vp); lsv->next = Svnc[j]; Svnc[j] = lsv; } while ((sn = sv.lf_next)); } SvncSt = 1; return(1); } #endif /* STEPV>=31 */ /* * process_node() - process vnode */ void process_node(va) KA_T va; /* vnode kernel space address */ { dev_t dev, rdev; int devs = 0; static int ft = 1; static KA_T fvops = (KA_T)0; struct inode i; int ins = 0; static KA_T nvops = (KA_T)0; struct rnode r; int rdevs = 0; struct vnode rv; struct snode s; static KA_T svops = (KA_T)0; char tbuf[32], *ty; static KA_T uvops = (KA_T)0; enum vtype type; static struct vnode *v = (struct vnode *)NULL; #if defined(HAS_AFS) static int afs = 0; /* AFS test status: -1 = no AFS * 0 = not tested * 1 = AFS present */ struct afsnode an; static KA_T avops = (KA_T)0; #endif /* defined(HAS_AFS) */ /* * Read the vnode. */ if (!va) { enter_nm("no vnode address"); return; } /* * Read the vnode. */ if (!v) { /* * Allocate space for the vnode or AFS vcache structure. */ #if defined(HAS_AFS) v = alloc_vcache(); #else /* !defined(HAS_AFS) */ v = (struct vnode *)malloc(sizeof(struct vnode)); #endif /* defined(HAS_AFS) */ if (!v) { (void) fprintf(stderr, "%s: can't allocate %s space\n", Pn, #if defined(HAS_AFS) "vcache" #else /* !defined(HAS_AFS) */ "vnode" #endif /* defined(HAS_AFS) */ ); Exit(1); } } if (readvnode(va, v)) { enter_nm(Namech); return; } # if defined(HASNCACHE) Lf->na = va; # endif /* defined(HASNCACHE) */ # if defined(HASFSTRUCT) Lf->fna = va; Lf->fsv |= FSV_NI; # endif /* defined(HASFSTRUCT) */ /* * Get vnode operations addresses, as required. */ if (ft) { #if defined(HAS_AFS) (void) get_Nl_value("avops", Drive_Nl, &avops); #endif /* defined(HAS_AFS) */ (void) get_Nl_value("fvops", Drive_Nl, &fvops); (void) get_Nl_value("nvops", Drive_Nl, &nvops); (void) get_Nl_value("svops", Drive_Nl, &svops); (void) get_Nl_value("uvops", Drive_Nl, &uvops); ft = 0; } /* * Determine the vnode type. */ if ((uvops && (KA_T)v->v_op == uvops) || (svops && (KA_T)v->v_op == svops)) Ntype = N_REGLR; else if (nvops && (KA_T)v->v_op == nvops) Ntype = N_NFS; else if (fvops && (KA_T)v->v_op == fvops) Ntype = N_FIFO; #if defined(HAS_AFS) /* * Caution: this AFS test should be the last one. */ else if (avops) { if ((KA_T)v->v_op == avops) Ntype = N_AFS; else { unknown_v_op: (void) snpf(Namech, Namechl, "unknown file system type; v_op: %s", print_kptr((KA_T)v->v_op, (char *)NULL, 0)); enter_nm(Namech); return; } } else if (v->v_data || !v->v_vfsp) goto unknown_v_op; else { switch (afs) { case -1: goto unknown_v_op; case 0: if (!hasAFS(v)) { afs = -1; goto unknown_v_op; } afs = 1; Ntype = N_AFS; AFSVfsp = (KA_T)v->v_vfsp; break; case 1: if ((KA_T)v->v_vfsp == AFSVfsp) Ntype = N_AFS; else goto unknown_v_op; } } #else /* !defined(HAS_AFS) */ else { (void) snpf(Namech, Namechl, "unknown file system type; v_op: %s", print_kptr((KA_T)v->v_op, (char *)NULL, 0)); enter_nm(Namech); return; } #endif /* defined(HAS_AFS) */ /* * Determine the lock type. */ if (v->v_shlockc || v->v_exlockc) { if (FILEPTR && (FILEPTR->f_flag & FSHLOCK)) Lf->lock = 'R'; else if (FILEPTR && (FILEPTR->f_flag & FEXLOCK)) Lf->lock = 'W'; else #if STEPV>=31 Lf->lock = isvlocked(va); #else /* STEPV<31 */ Lf->lock = ' '; #endif /* STEPV>=31 */ } /* * Read the inode, rnode, snode, or vcache struct. */ switch (Ntype) { #if defined(HAS_AFS) case N_AFS: if (readafsnode(va, v, &an)) return; break; #endif /* defined(HAS_AFS) */ case N_NFS: if (!v->v_data || readrnode((KA_T)v->v_data, &r)) { (void) snpf(Namech, Namechl, "vnode at %s: can't read rnode (%s)", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } break; case N_REGLR: default: /* * VBLK, VCHR and VFIFO vnodes point to an snode. The snode's s_realvp * usually points to a real vnode, which points to an inode. */ if (v->v_type == VBLK || v->v_type == VCHR || v->v_type == VFIFO) { if (!v->v_data || readsnode((KA_T)v->v_data, &s)) { (void) snpf(Namech, Namechl, "vnode at %s: can't read snode(%s)", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } if (s.s_realvp) { if (readvnode((KA_T)s.s_realvp, &rv)) { (void) snpf(Namech, Namechl, "snode at %s: can't read real vnode (%s)", print_kptr((KA_T)v->v_data, tbuf, sizeof(tbuf)), print_kptr((KA_T)s.s_realvp, (char *)NULL, 0)); enter_nm(Namech); return; } if (!rv.v_data || readinode((KA_T)rv.v_data, &i)) { (void) snpf(Namech, Namechl, "snode at %s: can't read inode (%s)", print_kptr((KA_T)v->v_data, tbuf, sizeof(tbuf)), print_kptr((KA_T)rv.v_data, (char *)NULL, 0)); enter_nm(Namech); return; } ins = 1; } break; } else { if (!v->v_data || readinode((KA_T)v->v_data, &i)) { (void) snpf(Namech, Namechl, "vnode at %s: can't read inode (%s)", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } ins = 1; } } /* * Get device and type for printing. */ switch (Ntype) { #if defined(HAS_AFS) case N_AFS: dev = an.dev; devs = 1; break; #endif /* defined(HAS_AFS) */ case N_NFS: dev = r.r_attr.va_fsid; devs = 1; if (dev & 0x8000) dev |= 0xff00; break; case N_FIFO: case N_REGLR: if (ins) { dev = i.i_dev; devs = 1; } if ((v->v_type == VBLK) || (v->v_type == VCHR)) { rdev = v->v_rdev; rdevs = 1; } } type = v->v_type; /* * Obtain the inode number. */ switch(Ntype) { #if defined(HAS_AFS) case N_AFS: if (an.ino_st) { Lf->inode = (INODETYPE)an.inode; Lf->inp_ty = 1; } break; #endif /* defined(HAS_AFS) */ case N_NFS: Lf->inode = (INODETYPE)r.r_attr.va_nodeid; Lf->inp_ty = 1; break; case N_FIFO: case N_REGLR: if (ins) { Lf->inode = (INODETYPE)i.i_number; Lf->inp_ty = 1; } } /* * Obtain the file size. */ if (Foffset) Lf->off_def = 1; else { switch (Ntype) { #if defined(HAS_AFS) case N_AFS: Lf->sz = (SZOFFTYPE)an.size; Lf->sz_def = 1; break; #endif /* defined(HAS_AFS) */ case N_NFS: Lf->sz = (SZOFFTYPE)r.r_attr.va_size; Lf->sz_def = 1; break; case N_FIFO: Lf->off_def = 1; break; case N_REGLR: if (type == VREG || type == VDIR) { if (ins) { Lf->sz = (SZOFFTYPE)i.i_size; Lf->sz_def = 1; } } else if ((type == VCHR || type == VBLK) && !Fsize) Lf->off_def = 1; break; } } /* * Record the link count. */ if (Fnlink) { #if defined(HAS_AFS) case N_AFS: Lf->nlink = an.nlink; Lf->nlink_def = an.nlink_st; break; #endif /* defined(HAS_AFS) */ switch (Ntype) { case N_NFS: Lf->nlink = (long)r.r_attr.va_nlink; Lf->nlink_def = 1; break; case N_REGLR: if (ins) { Lf->nlink = (long)i.i_nlink; Lf->nlink_def = 1; } break; } if (Lf->nlink_def && Nlink && (Lf->nlink < Nlink)) Lf->sf |= SELNLINK; } /* * Record an NFS file selection. */ if (Ntype == N_NFS && Fnfs) Lf->sf |= SELNFS; /* * Defer file system info lookup until printname(). */ Lf->lmi_srch = 1; /* * Save the device numbers and their states. * * Format the vnode type. */ Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; switch (type) { case VNON: ty ="VNON"; break; case VREG: case VDIR: ty = (type == VREG) ? "VREG" : "VDIR"; break; case VBLK: ty = "VBLK"; Ntype = N_BLK; break; case VCHR: ty = "VCHR"; Ntype = N_CHR; break; case VLNK: ty = "VLNK"; break; #if defined(VSOCK) case VSOCK: ty = "SOCK"; break; #endif case VBAD: ty = "VBAD"; break; case VFIFO: ty = "FIFO"; break; default: (void) snpf(Lf->type, sizeof(Lf->type), "%04o", (type & 0xfff)); ty = NULL; } if (ty) (void) snpf(Lf->type, sizeof(Lf->type), ty); Lf->ntype = Ntype; /* * If this is a VBLK file and it's missing an inode number, try to * supply one. */ if ((Lf->inp_ty == 0) && (Lf->ntype == N_BLK)) find_bl_ino(); /* * If this is a VCHR file and it's missing an inode number, try to * supply one. */ if ((Lf->inp_ty == 0) && (Lf->ntype == N_CHR)) find_ch_ino(); /* * Test for specified file. */ if (Sfile && is_file_named((char *)NULL, ((type == VCHR) || (type == VBLK)) ? 1 : 0)) Lf->sf |= SELNM; /* * Enter name characters. */ if (Namech[0]) enter_nm(Namech); } lsof-4.86+dfsg.orig/dialects/n+os/machine.h0000444000175000017500000003765111424323061020703 0ustar nicholasnicholas/* * machine.h - NEXTSTEP and OPENSTEP definitions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: machine.h,v 1.37 2010/07/29 16:02:55 abe Exp $ */ #if !defined(LSOF_MACHINE_H) #define LSOF_MACHINE_H 1 #include /* * 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 option. */ #define HASAOPT 1 /* * HASBLKDEV is defined for those dialects that want block device information * recorded in BDevtp[]. */ #define HASBLKDEV 1 /* * HASDCACHE is defined for those dialects that support a device cache * file. * * HASENVDC defined the name of an environment variable that contains the * device cache file path. The HASENVDC environment variable is ignored when * the lsof process is setuid(root) or its real UID is 0. * * HASPERSDC defines the format for the last component of a personal device * cache file path. The first will be the home directory of the real UID that * executes lsof. * * HASPERSDCPATH defines the environment variable whose value is the middle * component of the personal device cache file path. The middle component * follows the home directory and precedes the results of applying HASPERSDC. * The HASPERSDCPATH environment variable is ignored when the lsof process is * setuid(root) or its real UID is 0. * * HASSYSDC defines a public device cache file path. When it's defined, it's * used as the path from which to read the device cache. * * Consult the 00DCACHE and 00FAQ files of the lsof distribution for more * information on device cache file path construction. */ #define HASDCACHE 1 #define HASENVDC "LSOFDEVCACHE" #define HASPERSDC "%h/%p.lsof_%L" #define HASPERSDCPATH "LSOFPERSDCPATH" /* #define HASSYSDC "/your/choice/of/path" */ /* * HASCDRNODE is defined for those dialects that have CD-ROM nodes. */ /* #define HASCDRNODE 1 */ /* * HASFIFONODE is defined for those dialects that have FIFO nodes. */ /* #define HASFIFONODE 1 */ /* * HASFSINO is defined for those dialects that have the file system * inode element, fs_ino, in the lfile structure definition in lsof.h. */ #define HASFSINO 1 /* * HASFSTRUCT is defined if the dialect has a file structure. * * FSV_DEFAULT defines the default set of file structure values to list. * It defaults to zero (0), but may be made up of a combination of the * FSV_* symbols from lsof.h. * * HASNOFSADDR -- has no file structure address * HASNOFSFLAGS -- has no file structure flags * HASNOFSCOUNT -- has no file structure count * HASNOFSNADDR -- has no file structure node address */ #define HASFSTRUCT 1 /* #define FSV_DEFAULT FSV_? | FSV_? | FSV_? */ /* #define HASNOFSADDR 1 has no file structure address */ /* #define HASNOFSFLAGS 1 has no file structure flags */ /* #define HASNOFSCOUNT 1 has no file structure count */ /* #define HASNOFSNADDR 1 has no file structure node address */ /* * HASGNODE is defined for those dialects that have gnodes. */ /* #define HASGNODE 1 */ /* * HASHSNODE is defined for those dialects that have High Sierra nodes. */ /* #define HASHSNODE 1 */ /* * HASINODE is defined for those dialects that have inodes and wish to * use readinode() from node.c. */ #define HASINODE 1 /* * HASINTSIGNAL is defined for those dialects whose signal function returns * an int. */ /* #define HASINTSIGNAL 1 */ /* * HASKERNIDCK is defined for those dialects that support the comparison of * the build to running kernel identity. */ #define HASKERNIDCK 1 /* * HASKOPT is defined for those dialects that support the -k option of * reading the kernel's name list from an optional file. */ #define HASKOPT 1 /* * HASLFILEADD is defined for those dialects that need additional elements * in struct lfile. The HASLFILEADD definition is a macro that defines * them. If any of the additional elements need to be preset in the * alloc_lfile() function of proc.c, the SETLFILEADD macro may be defined * to do that. * * If any additional elements need to be cleared in alloc_lfile() or in the * free_proc() function of proc.c, the CLRLFILEADD macro may be defined to * do that. Note that CLRLFILEADD takes one argument, the pointer to the * lfile struct. The CLRLFILEADD macro is expected to expand to statements * that are complete -- i.e., have terminating semi-colons -- so the macro is * called without a terminating semicolon by proc.c. * * The HASXOPT definition may be used to select the conditions under which * private lfile elements are used. */ /* #define HASLFILEADD int ... */ /* #define CLRLFILEADD(lf) (lf)->... = (type)NULL; */ /* #define SETLFILEADD Lf->... */ /* * HASMNTSTAT indicates the dialect supports the mount stat(2) result option * in its l_vfs and mounts structures. */ /* #define HASMNTSTAT 1 */ /* * HASMNTSUP is defined for those dialects that support the mount supplement * option. */ /* #define HASMNTSUP 1 */ /* * HASMOPT is defined for those dialects that support the reading of * kernel memory from an alternate file. */ #define HASMOPT 1 /* * HASNCACHE is defined for those dialects that have a kernel name cache * that lsof can search. A value of 1 directs printname() to prefix the * cache value with the file system directory name; 2, avoid the prefix. * * NCACHELDPFX is a set of C commands to execute before calling ncache_load(). * * NCACHELDSFX is a set of C commands to execute after calling ncache_load(). */ #define HASNCACHE 1 /* #define NCACHELDPFX ??? */ /* #define NCACHELDSFX ??? */ /* * HASNLIST is defined for those dialects that use nlist() to acccess * kernel symbols. */ #define HASNLIST 1 /* * HASPIPEFN is defined for those dialects that have a special function to * process DTYPE_PIPE file structure entries. Its value is the name of the * function. * * NOTE: don't forget to define a prototype for this function in dproto.h. */ /* #define HASPIPEFN process_pipe? */ /* * HASPIPENODE is defined for those dialects that have pipe nodes. */ /* #define HASPIPENODE 1 */ /* * HASPMAPENABLED is defined when the reporting of portmapper registration * info is enabled by default. */ /* #define HASPMAPENABLED 1 */ /* * HASPPID is defined for those dialects that support identification of * the parent process IDentifier (PPID) of a process. */ #define HASPPID 1 /* * HASPRINTDEV, HASPRINTINO, HASPRINTNM, HASPRINTOFF, and HASPRINTSZ * define private dialect-specific functions for printing DEVice numbers, * INOde numbers, NaMes, file OFFsets, and file SiZes. The functions are * called from print_file(). */ /* #define HASPRINTDEV print_dev? */ /* #define HASPRINTINO print_ino? */ /* #define HASPRINTNM print_nm? */ /* #define HASPRINTOFF print_off? */ /* #define HASPRINTSZ print_sz? */ /* * HASPRIVFILETYPE and PRIVFILETYPE are defined for dialects that have a * file structure type that isn't defined by a DTYPE_* symbol. They are * used in lib/prfp.c to select the type's processing. * * PRIVFILETYPE is the definition of the f_type value in the file struct. * * HASPRIVFILETYPE is the name of the processing function. */ /* #define HASPRIVFILETYPE process_shmf? */ /* #define PRIVFILETYPE ?? */ /* * HASPRIVNMCACHE is defined for dialects that have a private method for * printing cached NAME column values for some files. HASPRIVNAMECACHE * is defined to be the name of the function. * * The function takes one argument, a struct lfile pointer to the file, and * returns non-zero if it prints a name to stdout. */ /* #define HASPRIVNMCACHE */ /* * 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 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 */ /* * HASSNODE is defined for those dialects that have snodes. */ #define HASSNODE 1 /* * HASTASKS is defined for those dialects that have task reporting support. */ /* #define HASTASKS 1 */ /* * HASSOOPT, HASSOSTATE and HASTCPOPT define the availability of information * on socket options (SO_* symbols), socket states (SS_* symbols) and TCP * options. */ #define HASSOOPT 1 /* has socket option information */ #define HASSOSTATE 1 /* has socket state information */ #define HASTCPOPT 1 /* has TCP options or flags */ /* * Define HASSPECDEVD to be the name of a function that handles the results * of a successful stat(2) of a file name argument. * * For example, HASSPECDEVD() for Darwin makes sure that st_dev is set to * what stat("/dev") returns -- i.e., what's in DevDev. * * The function takes two arguments: * * 1: pointer to the full path name of file * 2: pointer to the stat(2) result * * The function returns void. */ /* #define HASSPECDEVD process_dev_stat */ /* * HASSTREAMS is defined for those dialects that support streams. */ /* #define HASSTREAMS 1 */ /* * HASTCPTPIQ is defined for dialects where it is possible to report the * TCP/TPI Recv-Q and Send-Q values produced by netstat. */ #define HASTCPTPIQ 1 /* * HASTCPTPIW is defined for dialects where it is possible to report the * TCP/TPI send and receive window sizes produced by netstat. */ /* #define HASTCPTPIW 1 */ /* * HASTMPNODE is defined for those dialects that have tmpnodes. */ /* #define HASTMPNODE 1 */ /* * HASVNODE is defined for those dialects that use the Sun virtual file * system node, the vnode. BSD derivatives usually do; System V derivatives * prior to R4 usually don't. */ #define HASVNODE 1 /* * HASXOPT is defined for those dialects that have an X option. It * defines the text for the usage display. HASXOPT_VALUE defines the * option's default binary value -- 0 or 1. */ /* #define HASXOPT "help text for X option" */ /* #define HASXOPT_VALUE 1 */ /* * INODETYPE and INODEPSPEC define the internal node number type and its * printf specification modifier. These need not be defined and lsof.h * can be allowed to define defaults. * * These are defined here, because they must be used in dlsof.h. */ /* #define INODETYPE unsigned long long */ /* inode number internal storage type */ /* #define INODEPSPEC "ll" * INODETYPE printf specification * modifier */ # if !defined(MACH) /* * The definition of MACH for NEXTSTEP is required for proper header * file configuration -- i. e., some header files have ``#ifdef MACH'' * statements that affect the size of kernel structures. */ #define MACH 1 # endif /* * UID_ARG defines the size of a User ID number when it is passed * as a function argument. */ #define UID_ARG int /* * Each USE_LIB_ is defined for dialects that use the * in the lsof library. * * Note: other definitions and operations may be required to condition the * library function source code. They may be found in the dialect dlsof.h * header files. */ /* #define USE_LIB_CKKV 1 ckkv.c */ /* #define USE_LIB_COMPLETEVFS 1 cvfs.c */ #define USE_LIB_FIND_CH_INO 1 /* fino.c */ #define USE_LIB_IS_FILE_NAMED 1 /* isfn.c */ #define USE_LIB_LKUPDEV 1 /* lkud.c */ #define USE_LIB_PRINTDEVNAME 1 /* pdvn.c */ #define USE_LIB_PROCESS_FILE 1 /* prfp.c */ #define USE_LIB_PRINT_TCPTPI 1 /* ptti.c */ #define USE_LIB_READDEV 1 /* rdev.c */ #define USE_LIB_READMNT 1 /* rmnt.c */ #define USE_LIB_REGEX 1 /* regex.c */ /* #define USE_LIB_RNAM 1 rnam.c */ #define USE_LIB_RNCH 1 /* rnch.c */ /* #define USE_LIB_RNMH 1 rnmh.c */ #define HAS_NO_LONG_LONG 1 /* disable snpf()'s * long long support */ #define USE_LIB_SNPF 1 /* snpf.c */ /* * WARNDEVACCESS is defined for those dialects that should issue a warning * when lsof can't access /dev (or /device) or one of its sub-directories. * The warning can be inhibited by the lsof caller with the -w option. */ #define WARNDEVACCESS 1 /* * WARNINGSTATE is defined for those dialects that want to suppress all lsof * warning messages. */ /* #define WARNINGSTATE 1 warnings are enabled by default */ /* * WILLDROPGID is defined for those dialects whose lsof executable runs * setgid(not_real_GID) and whose setgid power can be relinquished after * the dialect's initialize() function has been executed. */ #define WILLDROPGID 1 /* * zeromem is a macro that uses bzero or memset. */ #define zeromem(a, l) bzero(a, l) #endif /* !defined(LSOF_MACHINE_H) */ lsof-4.86+dfsg.orig/dialects/n+os/Makefile0000444000175000017500000001033311001126765020555 0ustar nicholasnicholas # N+OS Makefile # # $Id: Makefile,v 1.14 2008/04/15 13:30:27 abe Exp $ PROG= lsof BIN= ${DESTDIR} DOC= ${DESTDIR} I=/usr/include S=/usr/include/sys L=/usr/include/local P= # Use the RC_CFLAGS environment variable to define architecture types. # To create a "fat" executable, supporting more than one architecture, # set RC_CFLAGS before executing make -- e.g., to build a "fat" executable # for m68k, i486, hppa, and SPARC, using /bin/sh: # # $ cd # $ ./Configure ns # $ RC_CFLAGS="-arch m68k -arch i486 -arch hppa -arch sparc" # $ export RC_CFLAGS # $ make CDEF= ${RC_CFLAGS} CDEFS= ${CDEF} ${CFGF} INCL= ${DINC} CFLAGS= ${CDEFS} ${INCL} ${DEBUG} GRP= HDR= lsof.h lsof_fields.h dlsof.h machine.h proto.h dproto.h SRC= dnode.c denode1.c dproc.c dsock.c dstore.c \ arg.c main.c misc.c node.c print.c proc.c store.c usage.c \ util.c OBJ= dnode.o dnode1.o dproc.o dsock.o dstore.o \ arg.o main.o misc.o node.o print.o proc.o store.o usage.o \ util.o MAN= lsof.8 OTHER= SHELL= /bin/sh SOURCE= Makefile ${OTHER} ${MAN} ${HDR} ${SRC} all: ${PROG} ${PROG}: ${LIB} ${P} ${OBJ} ${CC} -o $@ ${CFLAGS} ${OBJ} ${CFGL} clean: FRC rm -f Makefile.bak ${PROG} a.out core errs lint.out tags *.o version.h rm -f machine.h.old new_machine.h (cd lib; ${MAKE} -f Makefile.skel clean) install: all FRC @echo '' @echo 'Please write your own install rule. Lsof should be installed' @echo 'setgid to the group that can can read /dev/kmem. Normally' @echo 'that is the kmem group. Your install rule actions might look' @echo 'something like this:' @echo '' @echo ' install -cs -m 2755 -g $${GRP} $${PROG} $${BIN}/$${PROG}' @echo ' install -c -m 444 $${MAN} $${DOC}/$${MAN}' @echo '' @echo 'You will have to complete the skeletons for the BIN, DOC, and' @echo 'GRP strings given at the beginning of this Makefile, e.g.,' @echo '' @echo ' BIN= $${DESTDIR}/usr/local/etc' @echo ' DOC= $${DESTDIR}/usr/man/man8' @echo ' GRP= kmem' @echo '' ${LIB}: FRC (cd lib; ${MAKE} DEBUG="${DEBUG}" CFGF="${CFGF}") version.h: FRC @echo Constructing version.h @rm -f version.h @echo '#define LSOF_BLDCMT "${LSOF_BLDCMT}"' > version.h; @echo '#define LSOF_CC "${CC}"' >> version.h @echo '#define LSOF_CCV "${CCV}"' >> version.h @echo '#define LSOF_CCDATE "'`date`'"' >> version.h @echo '#define LSOF_CCFLAGS "'`echo ${CFLAGS} | sed 's/\\\\(/\\(/g' | sed 's/\\\\)/\\)/g' | sed 's/"/\\\\"/g'`'"' >> version.h @echo '#define LSOF_LDFLAGS "${CFGL}"' >> version.h @if [ "X${LSOF_LOGNAME}" = "X" ]; then \ echo '#define LSOF_LOGNAME "${LOGNAME}"' >> version.h; \ else \ if [ "${LSOF_LOGNAME}" = "none" ]; then \ echo '#define LSOF_LOGNAME ""' >> version.h; \ else \ echo '#define LSOF_LOGNAME "${LSOF_LOGNAME}"' >> version.h; \ fi; \ fi @if [ "X${LSOF_HOST}" = "X" ]; then \ echo '#define LSOF_HOST "'`hostname`'"' >> version.h; \ else \ if [ "${LSOF_HOST}" = "none" ]; then \ echo '#define LSOF_HOST ""' >> version.h; \ else \ echo '#define LSOF_HOST "${LSOF_HOST}"' >> version.h; \ fi \ fi @if [ "X${LSOF_SYSINFO}" = "X" ]; then \ echo '#define LSOF_SYSINFO "'`hostinfo | head -2 | tail -1`'"' >> version.h; \ else \ if [ "${LSOF_SYSINFO}" = "none" ]; then \ echo '#define LSOF_SYSINFO ""' >> version.h; \ else \ echo '#define LSOF_SYSINFO "${LSOF_SYSINFO}"' >> version.h; \ fi \ fi @if [ "X${LSOF_USER}" = "X" ]; then \ echo '#define LSOF_USER "${USER}"' >> version.h; \ else \ if [ "${LSOF_USER}" = "none" ]; then \ echo '#define LSOF_USER ""' >> version.h; \ else \ echo '#define LSOF_USER "${LSOF_USER}"' >> version.h; \ fi \ fi @sed '/VN/s/.ds VN \(.*\)/#define LSOF_VERSION "\1"/' < version >> version.h FRC: # DO NOT DELETE THIS LINE - make depend DEPENDS ON IT ddev.o: ${HDR} ddev.c dfile.o: ${HDR} dfile.c dmnt.o: ${HDR} dmnt.c dnode.o: ${HDR} dnode.c dnode1.o: ${HDR} dnode1.c dproc.o: ${HDR} dproc.c dsock.o: ${HDR} dsock.c dstore.o: ${HDR} dstore.c arg.o: ${HDR} arg.c main.o: ${HDR} main.c misc.o: ${HDR} misc.c node.o: ${HDR} node.c print.o: ${HDR} print.c proc.o: ${HDR} proc.c store.o: ${HDR} store.c usage.o: ${HDR} version.h usage.c util.o: ${HDR} util.c # *** Do not add anything here - It will go away. *** lsof-4.86+dfsg.orig/dialects/freebsd/0000755000175000017500000000000011741064217017663 5ustar nicholasnicholaslsof-4.86+dfsg.orig/dialects/freebsd/dstore.c0000444000175000017500000000615311001127113021312 0ustar nicholasnicholas/* * dstore.c - FreeBSD global storage for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dstore.c,v 1.8 2008/04/15 13:31:47 abe Exp $"; #endif #include "lsof.h" struct file *Cfp; /* curent file's file struct pointer */ /* * Drive_Nl -- table to drive the building of Nl[] via build_Nl() * (See lsof.h and misc.c.) */ struct drive_Nl Drive_Nl[] = { #if FREEBSDV<2005 { X_NCACHE, "_nchhead" }, #else /* FREEBSDV>=2005 */ # if FREEBSDV<2010 { X_NCACHE, "_nclruhead" }, # else /* FREEBSDV>=2010 */ { X_NCACHE, "_nchashtbl" }, # endif /* FREEBSDV<2010 */ #endif /* FREEBSDV<2005 */ #if FREEBSDV<2010 { X_NCSIZE, "_numcache" }, #else /* FREEBSDV>=2010 */ { X_NCSIZE, "_nchash" }, #endif /* FREEBSDV<2010 */ { "", "" }, { NULL, NULL } }; #if FREEBSDV>=2000 kvm_t *Kd = NULL; /* kvm descriptor */ #endif /* FREEBSDV>=2000 */ #if defined(P_ADDR) KA_T Kpa; /* kernel proc struct address */ #endif /* defined(P_ADDR) */ struct l_vfs *Lvfs = NULL; /* local vfs structure table */ int Np = 0; /* number of kernel processes */ #if FREEBSDV>=2000 struct kinfo_proc *P = NULL; /* local process table copy */ #endif /* FREEBSDV>=2000 */ #if defined(HASFSTRUCT) /* * Pff_tab[] - table for printing file flags */ struct pff_tab Pff_tab[] = { { (long)FREAD, FF_READ }, { (long)FWRITE, FF_WRITE }, { (long)FNONBLOCK, FF_NBLOCK }, { (long)FNDELAY, FF_NDELAY }, { (long)FAPPEND, FF_APPEND }, { (long)FASYNC, FF_ASYNC }, { (long)FFSYNC, FF_FSYNC }, # if defined(FMARK) { (long)FMARK, FF_MARK }, # endif /* defined(FMARK) */ # if defined(FDEFER) { (long)FDEFER, FF_DEFER }, # endif /* defined(FDEFER) */ { (long)FHASLOCK, FF_HASLOCK }, { (long)O_NOCTTY, FF_NOCTTY }, { (long)0, NULL } }; /* * Pof_tab[] - table for print process open file flags */ struct pff_tab Pof_tab[] = { # if defined(UF_EXCLOSE) { (long)UF_EXCLOSE, POF_CLOEXEC }, # endif /* defined(UF_EXCLOSE) */ # if defined(UF_MAPPED) { (long)UF_MAPPED, POF_MAPPED }, # endif /* defined(UF_MAPPED) */ { (long)0, NULL } }; #endif /* defined(HASFSTRUCT) */ lsof-4.86+dfsg.orig/dialects/freebsd/dsock.c0000444000175000017500000003235611162502241021130 0ustar nicholasnicholas/* * dsock.c - FreeBSD socket processing functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dsock.c,v 1.28 2009/03/25 19:23:06 abe Exp $"; #endif #include "lsof.h" #if defined(HASIPv6) /* * IPv6_2_IPv4() -- macro to define the address of an IPv4 address contained * in an IPv6 address */ #define IPv6_2_IPv4(v6) (((uint8_t *)((struct in6_addr *)v6)->s6_addr)+12) # if defined(HAS_NO_6PORT) /* * If the in_pcb structure no longer has the KAME accommodations of * in6p_[fl]port, redefine them to inp_[fl]port. */ #define in6p_fport inp_fport #define in6p_lport inp_lport # endif /* defined(HAS_NO_6PORT) */ # if defined(HAS_NO_6PPCB) /* * If the in_pcb structure no longer has the KAME accommodation of in6p_pcb, * redefine it to inp_ppcb. */ #define in6p_ppcb inp_ppcb # endif /* defined(HAS_NO_6PPCB) */ #endif /* defined(HASIPv6) */ /* * Local function prototypes */ _PROTOTYPE(static int ckstate,(KA_T ta, struct tcpcb *t, int fam)); /* * ckstate() -- read TCP control block and check TCP state for inclusion * or exclusion * return: -1 == no TCP CB available * 0 == TCP DB available; continue processing file * 1 == stop processing file */ static int ckstate(ta, t, fam) KA_T ta; /* TCP control block address */ struct tcpcb *t; /* TCP control block receptor */ int fam; /* protocol family */ { int tsnx; /* * Read TCP control block. */ if (kread(ta, (char *)t, sizeof(struct tcpcb))) return(-1); if (TcpStXn || TcpStIn) { /* * If there are TCP state inclusions or exclusions, check them. */ tsnx = (int)t->t_state + TcpStOff; if (TcpStXn) { if (TcpStX[tsnx]) { Lf->sf &= ~SELNET; Lf->sf |= SELEXCLF; return(1); } } if (TcpStIn) { if (TcpStI[tsnx]) { TcpStI[tsnx] = 2; Lf->sf |= SELNET; } else { Lf->sf &= ~SELNET; Lf->sf |= SELEXCLF; return(1); } } } if (!(Lf->sf & SELNET) && !TcpStIn) { /* * See if this TCP file should be selected. */ if (Fnet) { if (!FnetTy || (FnetTy == 4) && (fam == AF_INET) #if defined(HASIPv6) || (FnetTy == 6) && (fam == AF_INET6) #endif /* defined(HASIPv6) */ ) { Lf->sf |= SELNET; } } } return(0); } /* * process_socket() - process socket */ void process_socket(sa) KA_T sa; /* socket address in kernel */ { struct domain d; unsigned char *fa = (unsigned char *)NULL; int fam; int fp, lp; struct inpcb inp; unsigned char *la = (unsigned char *)NULL; struct protosw p; struct socket s; struct tcpcb t; int ts = -1; struct unpcb uc, unp; struct sockaddr_un *ua = NULL; struct sockaddr_un un; #if FREEBSDV<4050 struct mbuf mb; #else /* FREEBSDV>=4050 */ int unl; #endif /* FREEBSDV<4050 */ #if defined(HASIPv6) && !defined(HASINRIAIPv6) struct in6pcb in6p; #endif /* defined(HASIPv6) && !defined(HASINRIAIPv6) */ (void) snpf(Lf->type, sizeof(Lf->type), "sock"); Lf->inp_ty = 2; /* * Read the socket, protocol, and domain structures. */ if (!sa) { enter_nm("no socket address"); return; } if (kread(sa, (char *) &s, sizeof(s))) { (void) snpf(Namech, Namechl, "can't read socket struct from %s", print_kptr(sa, (char *)NULL, 0)); enter_nm(Namech); return; } if (!s.so_type) { enter_nm("no socket type"); return; } if (!s.so_proto || kread((KA_T)s.so_proto, (char *)&p, sizeof(p))) { (void) snpf(Namech, Namechl, "can't read protocol switch from %s", print_kptr((KA_T)s.so_proto, (char *)NULL, 0)); enter_nm(Namech); return; } if (!p.pr_domain || kread((KA_T)p.pr_domain, (char *)&d, sizeof(d))) { (void) snpf(Namech, Namechl, "can't read domain struct from %s", print_kptr((KA_T)p.pr_domain, (char *)NULL, 0)); enter_nm(Namech); return; } /* * Save size information. */ if (Fsize) { if (Lf->access == 'r') Lf->sz = (SZOFFTYPE)s.so_rcv.sb_cc; else if (Lf->access == 'w') Lf->sz = (SZOFFTYPE)s.so_snd.sb_cc; else Lf->sz = (SZOFFTYPE)(s.so_rcv.sb_cc + s.so_snd.sb_cc); Lf->sz_def = 1; } else Lf->off_def = 1; #if defined(HASTCPTPIQ) Lf->lts.rq = s.so_rcv.sb_cc; Lf->lts.sq = s.so_snd.sb_cc; Lf->lts.rqs = Lf->lts.sqs = 1; #endif /* defined(HASTCPTPIQ) */ #if defined(HASSOOPT) Lf->lts.ltm = (unsigned int)s.so_linger; Lf->lts.opt = (unsigned int)s.so_options; Lf->lts.pqlen = (unsigned int)s.so_incqlen; Lf->lts.qlen = (unsigned int)s.so_qlen; Lf->lts.qlim = (unsigned int)s.so_qlimit; Lf->lts.rbsz = (unsigned long)s.so_rcv.sb_mbmax; Lf->lts.sbsz = (unsigned long)s.so_snd.sb_mbmax; Lf->lts.pqlens = Lf->lts.qlens = Lf->lts.qlims = Lf->lts.rbszs = Lf->lts.sbszs = (unsigned char)1; #endif /* defined(HASSOOPT) */ #if defined(HASSOSTATE) Lf->lts.ss = (unsigned int)s.so_state; # if defined(HASSBSTATE) Lf->lts.sbs_rcv = s.so_rcv.sb_state; Lf->lts.sbs_snd = s.so_snd.sb_state; # endif /* defined(HASSBSTATE) */ #endif /* defined(HASSOSTATE) */ /* * Process socket by the associated domain family. */ switch ((fam = d.dom_family)) { /* * Process an Internet domain socket. */ case AF_INET: #if defined(HASIPv6) case AF_INET6: #endif /* defined(HASIPv6) */ if (Fnet) { if (!FnetTy || ((FnetTy == 4) && (fam == AF_INET)) #if defined(HASIPv6) || ((FnetTy == 6) && (fam == AF_INET6)) #endif /* defined(HASIPv6) */ ) { if (!TcpStIn && !UdpStIn) Lf->sf |= SELNET; } } printiproto(p.pr_protocol); #if defined(HASIPv6) (void) snpf(Lf->type, sizeof(Lf->type), (fam == AF_INET) ? "IPv4" : "IPv6"); #else /* !defined(HASIPv6) */ (void) snpf(Lf->type, sizeof(Lf->type), "inet"); #endif /* defined(HASIPv6) */ #if defined(HASIPv6) && !defined(HASINRIAIPv6) if (fam == AF_INET6) { /* * Read IPv6 protocol control block. */ if (!s.so_pcb || kread((KA_T)s.so_pcb, (char *)&in6p, sizeof(in6p))) { (void) snpf(Namech, Namechl, "can't read in6pcb at %s", print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); enter_nm(Namech); return; } /* * Save IPv6 address information. */ if (p.pr_protocol == IPPROTO_TCP) { if (in6p.in6p_ppcb) { if ((ts = ckstate((KA_T)in6p.in6p_ppcb, &t, fam)) == 1) return; } } enter_dev_ch(print_kptr((KA_T)(in6p.in6p_ppcb ? in6p.in6p_ppcb : s.so_pcb), (char *)NULL, 0)); la = (unsigned char *)&in6p.in6p_laddr; lp = (int)ntohs(in6p.in6p_lport); if (!IN6_IS_ADDR_UNSPECIFIED(&in6p.in6p_faddr) || in6p.in6p_fport) { fa = (unsigned char *)&in6p.in6p_faddr; fp = (int)ntohs(in6p.in6p_fport); } } else #endif /* defined(HASIPv6) && !defined(HASINRIAIPv6) */ { /* * Read Ipv4 or IPv6 (INRIA) protocol control block. */ if (!s.so_pcb || kread((KA_T) s.so_pcb, (char *) &inp, sizeof(inp))) { if (!s.so_pcb) { (void) snpf(Namech, Namechl, "no PCB%s%s", #if defined(HASSBSTATE) (s.so_snd.sb_state & SBS_CANTSENDMORE) ? #else /* !defined(HASSBSTATE) */ (s.so_state & SS_CANTSENDMORE) ? #endif /* defined(HASSBSTATE) */ ", CANTSENDMORE" : "", #if defined(HASSBSTATE) (s.so_rcv.sb_state & SBS_CANTRCVMORE) ? #else /* !defined(HASSBSTATE) */ (s.so_state & SS_CANTRCVMORE) ? #endif /* defined(HASSBSTATE) */ ", CANTRCVMORE" : ""); } else { (void) snpf(Namech, Namechl, "can't read inpcb at %s", print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); } enter_nm(Namech); return; } if (p.pr_protocol == IPPROTO_TCP) { if (inp.inp_ppcb) { if ((ts = ckstate((KA_T)inp.inp_ppcb, &t, fam)) == 1) return; } } enter_dev_ch(print_kptr((KA_T)(inp.inp_ppcb ? inp.inp_ppcb : s.so_pcb), (char *)NULL, 0)); lp = (int)ntohs(inp.inp_lport); if (fam == AF_INET) { /* * Save IPv4 address information. */ la = (unsigned char *)&inp.inp_laddr; if (inp.inp_faddr.s_addr != INADDR_ANY || inp.inp_fport) { fa = (unsigned char *)&inp.inp_faddr; fp = (int)ntohs(inp.inp_fport); } } #if defined(HASIPv6) && defined(HASINRIAIPv6) else { la = (unsigned char *)&inp.inp_laddr6; if (!IN6_IS_ADDR_UNSPECIFIED(&inp.inp_faddr6) || inp.inp_fport) { fa = (unsigned char *)&inp.inp_faddr6; fp = (int)ntohs(inp.inp_fport); } } #endif /* defined(HASIPv6) && defined(HASINRIAIPv6) */ } #if defined(HASIPv6) if ((fam == AF_INET6) && ((la && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)la)) || ((fa && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)fa))))) { /* * Adjust for IPv4 addresses mapped in IPv6 addresses. */ if (la) la = (unsigned char *)IPv6_2_IPv4(la); if (fa) fa = (unsigned char *)IPv6_2_IPv4(fa); fam = AF_INET; } #endif /* defined(HASIPv6) */ /* * Enter local and remote addresses by address family. */ if (fa || la) (void) ent_inaddr(la, lp, fa, fp, fam); if (ts == 0) { Lf->lts.type = 0; Lf->lts.state.i = (int)t.t_state; #if defined(HASTCPOPT) Lf->lts.mss = (unsigned long)t.t_maxseg; Lf->lts.msss = (unsigned char)1; Lf->lts.topt = (unsigned int)t.t_flags; #endif /* defined(HASTCPOPT) */ } break; /* * Process a ROUTE domain socket. */ case AF_ROUTE: (void) snpf(Lf->type, sizeof(Lf->type), "rte"); if (s.so_pcb) enter_dev_ch(print_kptr((KA_T)(s.so_pcb), (char *)NULL, 0)); else (void) snpf(Namech, Namechl, "no protocol control block"); if (!Fsize) Lf->off_def = 1; break; /* * Process a Unix domain socket. */ case AF_UNIX: if (Funix) Lf->sf |= SELUNX; (void) snpf(Lf->type, sizeof(Lf->type), "unix"); /* * Read Unix protocol control block and the Unix address structure. */ enter_dev_ch(print_kptr(sa, (char *)NULL, 0)); if (kread((KA_T) s.so_pcb, (char *) &unp, sizeof(unp))) { (void) snpf(Namech, Namechl, "can't read unpcb at %s", print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); break; } if ((struct socket *)sa != unp.unp_socket) { (void) snpf(Namech, Namechl, "unp_socket (%s) mismatch", print_kptr((KA_T)unp.unp_socket, (char *)NULL, 0)); break; } if (unp.unp_addr) { #if FREEBSDV<4050 if (kread((KA_T)unp.unp_addr, (char *)&mb, sizeof(mb))) #else /* FREEBSDV>=4050 */ if (kread((KA_T)unp.unp_addr, (char *)&un, sizeof(un))) #endif /* FREEBSDV<4050 */ { (void) snpf(Namech, Namechl, "can't read unp_addr at %s", print_kptr((KA_T)unp.unp_addr, (char *)NULL, 0)); break; } #if FREEBSDV<4050 if (mb.m_hdr.mh_len == sizeof(struct sockaddr_un)) ua = (struct sockaddr_un *) ((char *) &mb + (mb.m_hdr.mh_data - (caddr_t) unp.unp_addr)); #else /* FREEBSDV>=4050 */ ua = &un; #endif /* FREEBSDV<4050 */ } if (!ua) { ua = &un; (void) bzero((char *)ua, sizeof(un)); ua->sun_family = AF_UNSPEC; } /* * Print information on Unix socket that has no address bound * to it, although it may be connected to another Unix domain * socket as a pipe. */ if (ua->sun_family != AF_UNIX) { if (ua->sun_family == AF_UNSPEC) { if (unp.unp_conn) { if (kread((KA_T)unp.unp_conn, (char *)&uc, sizeof(uc))) (void) snpf(Namech, Namechl, "can't read unp_conn at %s", print_kptr((KA_T)unp.unp_conn,(char *)NULL,0)); else (void) snpf(Namech, Namechl, "->%s", print_kptr((KA_T)uc.unp_socket,(char *)NULL,0)); } else (void) snpf(Namech, Namechl, "->(none)"); } else (void) snpf(Namech, Namechl, "unknown sun_family (%d)", ua->sun_family); break; } if (ua->sun_path[0]) { #if FREEBSDV<4050 if (mb.m_len >= sizeof(struct sockaddr_un)) mb.m_len = sizeof(struct sockaddr_un) - 1; *((char *)ua + mb.m_len) = '\0'; #else /* FREEBSDV>=4050 */ # if FREEBSDV>4060 unl = ua->sun_len - offsetof(struct sockaddr_un, sun_path); # else /* FREEBSDV<4060 */ unl = sizeof(ua->sun_path) - 1; # endif /* FREEBSDV>4060 */ if ((unl < 0) || (unl >= sizeof(ua->sun_path))) unl = sizeof(ua->sun_path) - 1; ua->sun_path[unl] = '\0'; #endif /* FREEBSDV<4050 */ if (ua->sun_path[0] && Sfile && is_file_named(ua->sun_path, 0)) Lf->sf |= SELNM; if (ua->sun_path[0] && !Namech[0]) (void) snpf(Namech, Namechl, "%s", ua->sun_path); } else (void) snpf(Namech, Namechl, "no address"); break; default: printunkaf(fam, 1); } if (Namech[0]) enter_nm(Namech); } lsof-4.86+dfsg.orig/dialects/freebsd/dzfs.h0000444000175000017500000000577211617613372021017 0ustar nicholasnicholas/* * dzfs.h - FreeBSD header file for ZFS */ /* * Copyright 2008 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: dzfs.h,v 1.3 2011/08/07 22:51:28 abe Exp $ */ #if !defined(FREEBSD_ZFS_H) #define FREEBSD_ZFS_H 1 # if defined(HAS_ZFS) /* * The _PROTOTYPE macro provides strict ANSI C prototypes if __STDC__ * is defined, and old-style K&R prototypes otherwise. * * (With thanks to Andy Tanenbaum) */ # if defined(__STDC__) #define _PROTOTYPE(function, params) function params # else /* !defined(__STDC__) */ #define _PROTOTYPE(function, params) function() # endif /* defined(__STDC__) */ /* * The following define keeps gcc>=2.7 from complaining about the failure * of the Exit() function to return. * * Paul Eggert supplied it. */ # if defined(__GNUC__) && !(__GNUC__<2 || (__GNUC__==2 && __GNUC_MINOR__<7)) #define exiting __attribute__((__noreturn__)) # else /* !gcc || gcc<2.7 */ #define exiting # endif /* gcc && gcc>=2.7 */ # if !defined(INODETYPE) #define INODETYPE unsigned long long # endif /* !defined(INODETYPE) */ # if !defined(FREEBSD_KA_T) # if FREEBSDV<2000 typedef off_t KA_T; # else /* FREEBSDV>=2000 */ typedef u_long KA_T; # endif /* FREEBSDV<2000 */ #define FREEBSD_KA_T 1 /* for dlsof.h */ # endif /* !defined(FREEBSD_KA_T) */ # if !defined(READLEN_T) #define READLEN_T int # endif /* !defined(READLEN_T) */ # if !defined(SZOFFTYPE) #define SZOFFTYPE unsigned long long # endif /* !defined(SZOFFTYPE) */ /* * Structure for passing znode info */ typedef struct zfs_info { INODETYPE ino; /* inode number */ KA_T lockf; /* znode's z_lockf pointer */ long nl; /* number of links */ dev_t rdev; /* "raw" device number */ SZOFFTYPE sz; /* size */ unsigned char ino_def; /* ino defined status */ unsigned char nl_def; /* nl defined status */ unsigned char rdev_def; /* rdev defined status */ unsigned char sz_def; /* sz defined status */ } zfs_info_t; _PROTOTYPE(extern int kread,(KA_T addr, char *buf, READLEN_T len)); _PROTOTYPE(extern char *readzfsnode,(KA_T va, zfs_info_t *zi, int vr)); # endif /* defined(HAS_ZFS) */ #endif /* defined(FREEBSD_DZFS_H) */ lsof-4.86+dfsg.orig/dialects/freebsd/include/0000755000175000017500000000000007057254111021305 5ustar nicholasnicholaslsof-4.86+dfsg.orig/dialects/freebsd/include/procfs/0000755000175000017500000000000007057254112022602 5ustar nicholasnicholaslsof-4.86+dfsg.orig/dialects/freebsd/include/procfs/pfsnode.h0000644000175000017500000001402206301100335024374 0ustar nicholasnicholas/* * Copyright (c) 1993 Paul Kranenburg * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Paul Kranenburg. * 4. The name of the author may not be used to endorse or promote products * derived from this software withough specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $Id: pfsnode.h,v 1.1 1993/12/12 12:26:39 davidg Exp $ */ /* * This structure defines the control data for the proc file system. */ struct pfsnode { struct pfsnode *pfs_next; /* next on list */ struct vnode *pfs_vnode; /* vnode associated with this pfsnode */ pid_t pfs_pid; /* associated process */ u_short pfs_mode; /* mode bits for stat() */ uid_t pfs_uid; /* process' owner */ gid_t pfs_gid; /* process' group */ u_long pfs_vflags; /* chflags() flags */ u_long pfs_flags; /* open flags */ struct vmspace *pfs_vs; }; struct pfsnode *pfshead; /* * Format of a directory entry in /proc */ struct pfsdent { unsigned long d_fileno; unsigned short d_reclen; unsigned short d_namlen; char d_nam[8]; }; #define PFSDENTSIZE (sizeof(struct direct) - MAXNAMELEN + 8) #ifndef DIRBLKSIZ #define DIRBLKSIZ DEV_BSIZE #endif #ifdef DEBUG int pfs_debug; #endif /* * Convert between pfsnode pointers and vnode pointers */ #define VTOPFS(vp) ((struct pfsnode *)(vp)->v_data) #define PFSTOV(pfsp) ((pfsp)->pfs_vnode) /* * Prototypes for PFS operations on vnodes. */ int pfs_badop(); int pfs_doio(); int pfs_lookup __P(( \ struct vnode *vp, \ struct nameidata *ndp, \ struct proc *p)); #define pfs_create ((int (*) __P(( \ struct nameidata *ndp, \ struct vattr *vap, \ struct proc *p))) pfs_badop) #define pfs_mknod ((int (*) __P(( \ struct nameidata *ndp, \ struct vattr *vap, \ struct ucred *cred, \ struct proc *p))) pfs_badop) int pfs_open __P(( struct vnode *vp, int mode, struct ucred *cred, struct proc *p)); int pfs_close __P(( struct vnode *vp, int fflag, struct ucred *cred, struct proc *p)); int pfs_access __P(( struct vnode *vp, int mode, struct ucred *cred, struct proc *p)); int pfs_getattr __P(( struct vnode *vp, struct vattr *vap, struct ucred *cred, struct proc *p)); int pfs_setattr __P(( struct vnode *vp, struct vattr *vap, struct ucred *cred, struct proc *p)); #define pfs_read ((int (*) __P(( \ struct vnode *vp, \ struct uio *uio, \ int ioflag, \ struct ucred *cred))) pfs_doio) #define pfs_write ((int (*) __P(( \ struct vnode *vp, \ struct uio *uio, \ int ioflag, \ struct ucred *cred))) pfs_doio) int pfs_ioctl __P(( struct vnode *vp, int command, caddr_t data, int fflag, struct ucred *cred, struct proc *p)); #define pfs_select ((int (*) __P(( \ struct vnode *vp, \ int which, \ int fflags, \ struct ucred *cred, \ struct proc *p))) pfs_badop) #define pfs_mmap ((int (*) __P(( \ struct vnode *vp, \ int fflags, \ struct ucred *cred, \ struct proc *p))) pfs_badop) #define pfs_fsync ((int (*) __P(( \ struct vnode *vp, \ int fflags, \ struct ucred *cred, \ int waitfor, \ struct proc *p))) pfs_badop) #define pfs_seek ((int (*) __P(( \ struct vnode *vp, \ off_t oldoff, \ off_t newoff, \ struct ucred *cred))) pfs_badop) #define pfs_remove ((int (*) __P(( \ struct nameidata *ndp, \ struct proc *p))) pfs_badop) #define pfs_link ((int (*) __P(( \ struct vnode *vp, \ struct nameidata *ndp, \ struct proc *p))) pfs_badop) #define pfs_rename ((int (*) __P(( \ struct nameidata *fndp, \ struct nameidata *tdnp, \ struct proc *p))) pfs_badop) #define pfs_mkdir ((int (*) __P(( \ struct nameidata *ndp, \ struct vattr *vap, \ struct proc *p))) pfs_badop) #define pfs_rmdir ((int (*) __P(( \ struct nameidata *ndp, \ struct proc *p))) pfs_badop) #define pfs_symlink ((int (*) __P(( \ struct nameidata *ndp, \ struct vattr *vap, \ char *target, \ struct proc *p))) pfs_badop) int pfs_readdir __P(( struct vnode *vp, struct uio *uio, struct ucred *cred, int *eofflagp)); #define pfs_readlink ((int (*) __P(( \ struct vnode *vp, \ struct uio *uio, \ struct ucred *cred))) pfs_badop) #define pfs_abortop ((int (*) __P(( \ struct nameidata *ndp))) pfs_badop) int pfs_inactive __P(( struct vnode *vp, struct proc *p)); int pfs_reclaim __P(( struct vnode *vp)); #define pfs_lock ((int (*) __P(( \ struct vnode *vp))) nullop) #define pfs_unlock ((int (*) __P(( \ struct vnode *vp))) nullop) int pfs_bmap __P(( struct vnode *vp, daddr_t bn, struct vnode **vpp, daddr_t *bnp)); int pfs_strategy __P(( struct buf *bp)); void pfs_print __P(( struct vnode *vp)); #define pfs_islocked ((int (*) __P(( \ struct vnode *vp))) nullop) #define pfs_advlock ((int (*) __P(( \ struct vnode *vp, \ caddr_t id, \ int op, \ struct flock *fl, \ int flags))) pfs_badop) lsof-4.86+dfsg.orig/dialects/freebsd/dproc.c0000444000175000017500000003375311077400115021140 0ustar nicholasnicholas/* * dproc.c - FreeBSD process access functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dproc.c,v 1.16 2008/10/21 16:16:06 abe Exp $"; #endif #include "lsof.h" _PROTOTYPE(static void enter_vn_text,(KA_T va, int *n)); _PROTOTYPE(static void get_kernel_access,(void)); _PROTOTYPE(static void process_text,(KA_T vm)); /* * Local static values */ static MALLOC_S Nv = 0; /* allocated Vp[] entries */ static KA_T *Vp = NULL; /* vnode address cache */ /* * enter_vn_text() - enter a vnode text reference */ static void enter_vn_text(va, n) KA_T va; /* vnode address */ int *n; /* Vp[] entries in use */ { int i; /* * Ignore the request if the vnode has already been entered. */ for (i = 0; i < *n; i++) { if (va == Vp[i]) return; } /* * Save the text file information. */ alloc_lfile(" txt", -1); Cfp = (struct file *)NULL; process_node(va); if (Lf->sf) link_lfile(); if (i >= Nv) { /* * Allocate space for remembering the vnode. */ Nv += 10; if (!Vp) Vp=(KA_T *)malloc((MALLOC_S)(sizeof(struct vnode *)*10)); else Vp=(KA_T *)realloc((MALLOC_P *)Vp,(MALLOC_S)(Nv*sizeof(KA_T))); if (!Vp) { (void) fprintf(stderr, "%s: no txt ptr space, PID %d\n", Pn, Lp->pid); Exit(1); } } /* * Remember the vnode. */ Vp[*n] = va; (*n)++; } /* * gather_proc_info() -- gather process information */ void gather_proc_info() { short cckreg; /* conditional status of regular file * checking: * 0 = unconditionally check * 1 = conditionally check */ short ckscko; /* socket file only checking status: * 0 = none * 1 = check only socket files, * including TCP and UDP * streams with eXPORT data, * where supported */ struct filedesc fd; int i, nf; MALLOC_S nb; static struct file **ofb = NULL; static int ofbb = 0; int pgid, pid; int ppid = 0; short pss, sf; int px; uid_t uid; #if FREEBSDV<2000 struct proc *p; struct pcred pc; struct pgrp pg; #else /* FREEBSDV>=2000 */ struct kinfo_proc *p; #endif /* FREEBSDV<2000 */ #if defined(HASFSTRUCT) static char *pof = (char *)NULL; static int pofb = 0; #endif /* defined(HASFSTRUCT) */ /* * Define socket and regular file conditional processing flags. * * If only socket files have been selected, or socket files have been * selected, ANDed with other selection options, enable the skipping of * regular files. * * If socket files and some process options have been selected, enable * conditional skipping of regular file; i.e., regular files will be skipped * unless they belong to a process selected by one of the specified options. */ if (Selflags & SELNW) { /* * Some network files selection options have been specified. */ if (Fand || !(Selflags & ~SELNW)) { /* * Selection ANDing or only network file options have been * specified, so set unconditional skipping of regular files * and socket file only checking. */ cckreg = 0; ckscko = 1; } else { /* * If ORed file selection options have been specified, or no * ORed process selection options have been specified, enable * unconditional file checking and clear socket file only * checking. * * If only ORed process selection options have been specified, * enable conditional file skipping and socket file only checking. */ if ((Selflags & SELFILE) || !(Selflags & SELPROC)) cckreg = ckscko = 0; else cckreg = ckscko = 1; } } else { /* * No network file selection options were specified. Enable * unconditional file checking and clear socket file only checking. */ cckreg = ckscko = 0; } /* * Read the process table. */ #if FREEBSDV<2000 if ((Np = kvm_getprocs(KINFO_PROC_ALL, 0)) < 0) #else /* FREEBSDV>=2000 */ if ((P = kvm_getprocs(Kd, KERN_PROC_ALL, 0, &Np)) == NULL) #endif /* FREEBSDV<2000 */ { (void) fprintf(stderr, "%s: can't read process table: %s\n", Pn, #if FREEBSDV<2000 kvm_geterr() #else /* FREEBSDV>=2000 */ kvm_geterr(Kd) #endif /* FREEBSDV<2000 */ ); Exit(1); } /* * Examine proc structures and their associated information. */ #if FREEBSDV<2000 for (px = 0; px < Np; px++) #else /* FREEBSDV>=2000 */ for (p = P, px = 0; px < Np; p++, px++) #endif /* FREEBSDV<2000 */ { #if FREEBSDV<2000 /* * Read process information, process group structure (if * necessary), and User ID (if necessary). */ if (!(p = kvm_nextproc())) continue; if (p->P_STAT == 0 || p->P_STAT == SZOMB) continue; pg.pg_id = 0; if (Fpgid && p->P_PGID) { if (kread((KA_T)p->P_PGID, (char *)&pg, sizeof(pg))) continue; } pgid = pg.pg_id; if (!p->p_cred || kread((KA_T)p->p_cred, (char *)&pc, sizeof(pc))) continue; uid = pc.p_ruid; #else /* FREEBSDV>=2000 */ if (p->P_STAT == 0 || p->P_STAT == SZOMB) continue; pgid = p->P_PGID; # if FREEBSDV<5000 uid = p->kp_eproc.e_ucred.cr_uid; # else /* FREEBSDV>=5000 */ uid = p->ki_uid; # endif /* FREEBSDV<5000 */ #endif /* FREEBSDV<2000 */ #if defined(HASPPID) ppid = p->P_PPID; #endif /* defined(HASPPID) */ /* * See if process is excluded. * * Read file structure pointers. */ if (is_proc_excl(p->P_PID, pgid, (UID_ARG)uid, &pss, &sf)) continue; if (!p->P_FD || kread((KA_T)p->P_FD, (char *)&fd, sizeof(fd))) continue; if (!fd.fd_refcnt || fd.fd_lastfile > fd.fd_nfiles) continue; /* * Allocate a local process structure. */ if (is_cmd_excl(p->P_COMM, &pss, &sf)) continue; if (cckreg) { /* * If conditional checking of regular files is enabled, enable * socket file only checking, based on the process' selection * status. */ ckscko = (sf & SELPROC) ? 0 : 1; } alloc_lproc(p->P_PID, pgid, ppid, (UID_ARG)uid, p->P_COMM, (int)pss, (int)sf); Plf = (struct lfile *)NULL; #if defined(P_ADDR) /* * Save the kernel proc struct address, if P_ADDR is defined. */ Kpa = (KA_T)p->P_ADDR; #endif /* defined(P_ADDR) */ /* * Save current working directory information. */ if (!ckscko && fd.fd_cdir) { alloc_lfile(CWD, -1); Cfp = (struct file *)NULL; process_node((KA_T)fd.fd_cdir); if (Lf->sf) link_lfile(); } /* * Save root directory information. */ if (!ckscko && fd.fd_rdir) { alloc_lfile(RTD, -1); Cfp = (struct file *)NULL; process_node((KA_T)fd.fd_rdir); if (Lf->sf) link_lfile(); } #if FREEBSDV>=5000 /* * Save jail directory information. */ if (!ckscko && fd.fd_jdir) { alloc_lfile("jld", -1); Cfp = (struct file *)NULL; process_node((KA_T)fd.fd_jdir); if (Lf->sf) link_lfile(); } #endif /* FREEBSDV>=5000 */ /* * Save information on the text file. */ if (!ckscko && p->P_VMSPACE) process_text((KA_T)p->P_VMSPACE); /* * Read open file structure pointers. */ if (!fd.fd_ofiles || (nf = fd.fd_nfiles) <= 0) continue; nb = (MALLOC_S)(sizeof(struct file *) * nf); if (nb > ofbb) { if (!ofb) ofb = (struct file **)malloc(nb); else ofb = (struct file **)realloc((MALLOC_P *)ofb, nb); if (!ofb) { (void) fprintf(stderr, "%s: PID %d, no file * space\n", Pn, p->P_PID); Exit(1); } ofbb = nb; } if (kread((KA_T)fd.fd_ofiles, (char *)ofb, nb)) continue; #if defined(HASFSTRUCT) if (Fsv & FSV_FG) { nb = (MALLOC_S)(sizeof(char) * nf); if (nb > pofb) { if (!pof) pof = (char *)malloc(nb); else pof = (char *)realloc((MALLOC_P *)pof, nb); if (!pof) { (void) fprintf(stderr, "%s: PID %d, no file flag space\n", Pn, p->P_PID); Exit(1); } pofb = nb; } if (!fd.fd_ofileflags || kread((KA_T)fd.fd_ofileflags, pof, nb)) zeromem(pof, nb); } #endif /* defined(HASFSTRUCT) */ /* * Save information on file descriptors. */ for (i = 0; i < nf; i++) { if (ofb[i]) { alloc_lfile(NULL, i); process_file((KA_T)(Cfp = ofb[i])); if (Lf->sf) { #if defined(HASFSTRUCT) if (Fsv & FSV_FG) Lf->pof = (long)pof[i]; #endif /* defined(HASFSTRUCT) */ link_lfile(); } } } /* * Examine results. */ if (examine_lproc()) return; } } /* * get_kernel_access() - get access to kernel memory */ static void get_kernel_access() { /* * Check kernel version. */ (void) ckkv("FreeBSD", LSOF_VSTR, (char *)NULL, (char *)NULL); /* * Set name list file path. */ if (!Nmlst) #if defined(N_UNIX) Nmlst = N_UNIX; #else /* !defined(N_UNIX) */ { if (!(Nmlst = get_nlist_path(1))) { (void) fprintf(stderr, "%s: can't get kernel name list path\n", Pn); Exit(1); } } #endif /* defined(N_UNIX) */ #if defined(WILLDROPGID) /* * If kernel memory isn't coming from KMEM, drop setgid permission * before attempting to open the (Memory) file. */ if (Memory) (void) dropgid(); #else /* !defined(WILLDROPGID) */ /* * See if the non-KMEM memory and the name list files are readable. */ if ((Memory && !is_readable(Memory, 1)) || (Nmlst && !is_readable(Nmlst, 1))) Exit(1); #endif /* defined(WILLDROPGID) */ /* * Open kernel memory access. */ #if FREEBSDV<2000 if (kvm_openfiles(Nmlst, Memory, NULL) == -1) #else /* FREEBSDV>=2000 */ if ((Kd = kvm_open(Nmlst, Memory, NULL, O_RDONLY, NULL)) == NULL) #endif /* FREEBSDV<2000 */ { (void) fprintf(stderr, "%s: kvm_open%s(execfile=%s, corefile=%s): %s\n", Pn, #if FREEBSDV<2000 "files", #else /* FREEBSDV>=2000 */ "", #endif /* FREEBSDV<2000 */ Nmlst ? Nmlst : "default", Memory ? Memory : #if defined(_PATH_MEM) _PATH_MEM, #else /* !defined(_PATH_MEM) */ "default", #endif /* defined(_PATH_MEM) */ strerror(errno)); Exit(1); } (void) build_Nl(Drive_Nl); if (kvm_nlist(Kd, Nl) < 0) { (void) fprintf(stderr, "%s: can't read namelist from %s\n", Pn, Nmlst); Exit(1); } #if defined(WILLDROPGID) /* * Drop setgid permission, if necessary. */ if (!Memory) (void) dropgid(); #endif /* defined(WILLDROPGID) */ } #if !defined(N_UNIX) /* * get_nlist_path() - get kernel name list path */ char * get_nlist_path(ap) int ap; /* on success, return an allocated path * string pointer if 1; return a * constant character pointer if 0; * return NULL if failure */ { const char *bf; static char *bfc; MALLOC_S bfl; /* * Get bootfile name. */ if ((bf = getbootfile())) { if (!ap) return(""); bfl = (MALLOC_S)(strlen(bf) + 1); if (!(bfc = (char *)malloc(bfl))) { (void) fprintf(stderr, "%s: can't allocate %d bytes for boot file path: %s\n", Pn, bfl, bf); Exit(1); } (void) snpf(bfc, bfl, "%s", bf); return(bfc); } return((char *)NULL); } #endif /* !defined(N_UNIX) */ /* * initialize() - perform all initialization */ void initialize() { get_kernel_access(); } /* * kread() - read from kernel memory */ int kread(addr, buf, len) KA_T addr; /* kernel memory address */ char *buf; /* buffer to receive data */ READLEN_T len; /* length to read */ { int br; #if FREEBSDV<2000 br = kvm_read((void *)addr, (void *)buf, len); #else /* FREEBSDV>=2000 */ br = kvm_read(Kd, (u_long)addr, buf, len); #endif /* FREEBSDV<2000 */ return((br == len) ? 0 : 1); } /* * process_text() - process text information */ void process_text(vm) KA_T vm; /* vm space pointer */ { int i, j; KA_T ka; int n = 0; struct vm_map_entry vmme, *e; struct vm_object vmo; struct vmspace vmsp; #if FREEBSDV<2020 struct pager_struct pg; #endif /* FREEBSDV<2020 */ /* * Read the vmspace structure for the process. */ if (kread(vm, (char *)&vmsp, sizeof(vmsp))) return; /* * Read the vm_map structure. Search its vm_map_entry structure list. */ for (i = 0; i < vmsp.vm_map.nentries; i++) { /* * Read the next vm_map_entry. */ if (i == 0) e = &vmsp.vm_map.header; else { if (!(ka = (KA_T)e->next)) return; e = &vmme; if (kread(ka, (char *)e, sizeof(vmme))) return; } #if defined(MAP_ENTRY_IS_A_MAP) if (e->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP)) #else /* !defined(MAP_ENTRY_IS_A_MAP) */ if (e->is_a_map || e->is_sub_map) #endif /* defined(MAP_ENTRY_IS_A_MAP) */ continue; /* * Read the map entry's object and the object's shadow. * Look for: a PG_VNODE pager handle (FreeBSD < 2.2); * an OBJT_VNODE object type (FreeBSD >= 2.2). */ for (j = 0, ka = (KA_T)e->object.vm_object; j < 2 && ka; j++, #if FREEBSDV<2020 ka = (KA_T)vmo.shadow #else /* FREEBSDV>=2020 */ ka = (KA_T)vmo.backing_object #endif /* FREEBSDV<2020 */ ) { if (kread(ka, (char *)&vmo, sizeof(vmo))) break; #if FREEBSDV<2020 if ((ka = (KA_T)vmo.pager) == NULL || kread(ka, (char *)&pg, sizeof(pg))) continue; if (pg.pg_handle == NULL || pg.pg_type != PG_VNODE) continue; (void) (enter_vn_text((KA_T)pg.pg_handle, &n)); #else /* FREEBSDV>=2020 */ if (vmo.type != OBJT_VNODE || vmo.handle == (void *)NULL) continue; (void) (enter_vn_text((KA_T)vmo.handle, &n)); #endif /* FREEBSDV<2020 */ } } } lsof-4.86+dfsg.orig/dialects/freebsd/dproto.h0000444000175000017500000000421311162502240021327 0ustar nicholasnicholas/* * dproto.h - FreeBSD function prototypes for lsof * * The _PROTOTYPE macro is defined in the common proto.h. */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: dproto.h,v 1.14 2009/03/25 19:23:06 abe Exp $ */ #if FREEBSDV>=5000 && defined(HAS_NO_SI_UDEV) # if defined(HAS_CONF_MINOR)|| defined(HAS_CDEV2PRIV) _PROTOTYPE(extern dev_t Dev2Udev,(KA_T c)); # else /* !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV) */ _PROTOTYPE(extern dev_t Dev2Udev,(struct cdev *c)); # endif /* defined(HAS_CONF_MINOR) || defined(HAS_CDEV2PRIV) */ #endif /* FREEBSDV>=5000 && defined(HAS_NO_SI_UDEV) */ #if !defined(N_UNIX) _PROTOTYPE(extern char *get_nlist_path,(int ap)); #endif /* !defined(N_UNIX) */ _PROTOTYPE(extern int is_file_named,(char *p, int cd)); _PROTOTYPE(extern void process_socket,(KA_T sa)); _PROTOTYPE(extern struct l_vfs *readvfs,(KA_T vm)); #if defined(HASKQUEUE) _PROTOTYPE(extern void process_kqueue,(KA_T ka)); #endif /* defined(HASKQUEUE) */ #if FREEBSDV>=2020 _PROTOTYPE(extern void process_pipe,(KA_T pa)); #endif /* FREEBSDV>=2020 */ #if defined(HAS9660FS) _PROTOTYPE(extern int read_iso_node,(struct vnode *v, dev_t *d, int *dd, INODETYPE *ino, long *nl, SZOFFTYPE *sz)); #endif /* defined(HAS9660FS) */ lsof-4.86+dfsg.orig/dialects/freebsd/dlsof.h0000444000175000017500000003765611631741271021162 0ustar nicholasnicholas/* * dlsof.h - FreeBSD header file for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: dlsof.h,v 1.44 2011/09/07 19:14:59 abe Exp $ */ #if !defined(FREEBSD_LSOF_H) #define FREEBSD_LSOF_H 1 #include #include #include #include #include #include # if FREEBSDV>=4000 # if FREEBSDV>=5000 # if FREEBSDV<6020 # if defined(__alpha__) /* * For Alpha below 6.2, #include before #define'ing _KERNEL. * Then #define PCPU_MD_FIELDS independently. This hack avoids a compiler * complaint about register use. */ #include #define PCPU_MD_FIELDS \ struct alpha_pcb pc_idlepcb; /* pcb for idling */ \ u_int64_t pc_idlepcbphys; /* pa of pc_idlepcb */ \ u_int64_t pc_pending_ipis; /* pending IPI's */ \ u_int32_t pc_next_asn; /* next ASN to alloc */ \ u_int32_t pc_current_asngen /* ASN rollover check */ # endif /* defined(__alpha__) */ # endif /* FREEBSDV<6020 */ #define _KERNEL 1 # endif /* FREEBSDV>=5000 */ # if defined(HAS_VM_MEMATTR_T) /* * The d_mmap2_t function typedef in may need the definition * of vm_memattr_t for a pointer, but that definition is only available * under _KERNEL in . Defining _KERNEL before including * causes many compilation problems, so this expediency * (hack) is used when the vm_memattr_t definition is needed. */ #define vm_memattr_t void # endif /* defined(HAS_VM_MEMATTR_T) */ # if defined(NEEDS_BOOLEAN_T) /* * In FreeBSD 9 and above the boolean_t typedef is also needed and is also * under _KERNEL in . */ #define boolean_t int # endif /* defined(NEEDS_BOOLEAN_T) */ #include # if defined(HAS_VM_MEMATTR_T) #undef vm_memattr_t # endif /* defined(HAS_VM_MEMATTR_T) */ # if defined(NEEDS_BOOLEAN_T) #undef boolean_t # endif /* defined(NEEDS_BOOLEAN_T) */ # if defined(HAS_CONF_MINOR) #undef minor #include "fbsd_minor.h" # endif /* defined(HAS_CONF_MINOR) */ # if FREEBSDV>=5000 #undef _KERNEL # endif /* FREEBSDV>=5000 */ # endif /* FREEBSDV>=4000 */ #include #include #define NFS #define m_stat mnt_stat # if FREEBSDV>=3020 #define _KERNEL # endif /* FREEBSDV>=3020 */ #include # if FREEBSDV>=3020 #undef _KERNEL # endif /* FREEBSDV>=3020 */ #include #include #include #include #include #include # if FREEBSDV>=3000 #undef INADDR_LOOPBACK # endif /* FREEBSDV>=3000 */ #include #include #include #include #include #include #include #include #include #include #include #include #include # if defined(HAS_KVM_VNODE) #define _KVM_VNODE # endif /* defined(HAS_KVM_VNODE) */ #include # if defined(HAS_KVM_VNODE) #undef _KVM_VNODE # endif /* defined(HAS_KVM_VNODE) */ #include #include #define pmap RPC_pmap #include #include #undef pmap # if FREEBSDV<2000 #include #include #include #include # else /* FREEBSDV>=2000 */ #include #include # if FREEBSDV>=4000 && FREEBSDV<5000 # if defined(__alpha__) || defined(__sparc64__) #define dev_t void * # endif /* defined(__alpha__) || defined(__sparc64__) */ # endif /* FREEBSDV>=4000 && FREEBSDV<5000 */ #include # if defined(HAS_UFS1_2) #define _KERNEL struct vop_getextattr_args; struct vop_deleteextattr_args; struct vop_setextattr_args; #include #define psignal LSOF_psignal #define panicstr bp #include #undef psignal #undef panicstr #undef _KERNEL # endif /* defined(HAS_UFS1_2) */ # if FREEBSDV>=5010 #undef i_devvp # endif /* FREEBSDV>=5010 */ # if FREEBSDV>=4000 && FREEBSDV<5000 # if defined(__alpha__) || defined(__sparc64__) #undef dev_t # endif /* defined(__alpha__) || defined(__sparc64__) */ # endif /* FREEBSDV>=4000 && FREEBSDV<5000 */ # if FREEBSDV<2020 #include # endif /* FREEBSDV<2020 */ # endif /* FREEBSDV<2000 */ # if FREEBSDV<5000 #include # else /* FREEBSDV>=5000 */ #include # endif /* FREEBSDV<5000 */ # if defined(HASRPCV2H) #include # endif /* defined(HASRPCV2H) */ # if FREEBSDV>=5000 #include #include # else /* FREEBSDV<5000 */ #include #include # endif /* FREEBSDV>=5000 */ #include #include #undef TRUE #undef FALSE # if FREEBSDV<2000 #include # else /* FREEBSDV>=2000 */ #include # endif /* FREEBSDV<2000 */ # if defined(HASFDESCFS) #define _KERNEL #define KERNEL # if FREEBSDV>=5000 #include # else /* FREEBSDV<5000 */ #include # endif /* FREEBSDV>=5000 */ #undef _KERNEL #undef KERNEL # endif /* defined(HASFDESCFS) */ # if defined(HASNULLFS) #define _KERNEL #define KERNEL struct vop_generic_args; # if FREEBSDV>=5000 #include # else /* FREEBSDV<5000 */ #include # endif /* FREEBSDV>=5000 */ #undef _KERNEL #undef KERNEL # endif /* defined(HASNULLFS) */ # if defined(HASPROCFS) # if FREEBSDV<2000 #include # else /* FREEBSDV>=2000 */ # if FREEBSDV<5000 #include # endif /* FREEBSDV<5000 */ #include # endif /* FREEBSDV<2000 */ #define PNSIZ 5 # endif /* defined(HASPROCFS) */ # if defined(HASPSEUDOFS) #include # endif /* defined(HASPSEUDOFS) */ # if defined(HAS_ZFS) #include "dzfs.h" # endif /* defined(HAS_ZFS) */ # if FREEBSDV<2000 #define P_COMM p_comm #define P_FD p_fd #define P_PID p_pid #define P_PGID p_pgrp #define P_STAT p_stat #define P_VMSPACE p_vmspace # else /* FREEBSDV>=2000 */ # if FREEBSDV<5000 #define P_ADDR kp_eproc.e_paddr #define P_COMM kp_proc.p_comm #define P_FD kp_proc.p_fd #define P_PID kp_proc.p_pid #define P_PGID kp_eproc.e_pgid #define P_PPID kp_eproc.e_ppid #define P_STAT kp_proc.p_stat #define P_VMSPACE kp_proc.p_vmspace # else /* FREEBSDV>=5000 */ #define P_ADDR ki_paddr #define P_COMM ki_comm #define P_FD ki_fd #define P_PID ki_pid #define P_PGID ki_pgid #define P_PPID ki_ppid #define P_STAT ki_stat #define P_VMSPACE ki_vmspace # endif /* FREEBSDV<5000 */ # endif /* FREEBSDV<2000 */ #define _KERNEL #define KERNEL #include /* * The following circumventions were first needed in FreeBSD 8.0-CURRENT some * time in August 2008 to avoid conflicts in /usr/src/sys/sys/libkern.h> and * /usr/src/sys/sys/systm.h, called by or the header files it * #include's when KERNEL or _KERNEL is #define'd. * * The circumventions may be needed or may be erroneous for earlier FreeBSD * versions where testing was not possible. */ #define intrmask_t int #define log log_kernel_lsof #define pause pause_kernel_lsof #define setenv setenv_kernel_lsof #define uintfptr_t int #define _SYS_LIBKERN_H_ #include /* * Attempt to remove the circumventions. */ #undef _SYS_LIBKERN_H_ #undef intrmask_t_lsof #undef log_kernel_lsof #undef pause_kernel_lsof #undef setenv_kernel_lsof #undef uintfptr_t #undef _KERNEL #undef KERNEL # if defined(DTYPE_KQUEUE) #define HASKQUEUE /* has the kqueue file type */ # if FREEBSDV>=4090 #define _KERNEL # endif /* FREEBSDV>=4090 */ #include # if FREEBSDV>=4090 #undef _KERNEL # endif /* FREEBSDV>=4090 */ # endif /* defined(DTYPE_KQUEUE) */ # if FREEBSDV<2000 #include # else /* FREEBSDV>=2000 */ struct vop_advlock_args { int dummy; }; /* to pacify lf_advlock() prototype */ # if FREEBSDV>=5000 #undef MALLOC_DECLARE #define MALLOC_DECLARE(type) extern struct malloc_type type[1] /* to pacify */ #define _KERNEL # if defined(HAS_SYS_SX_H) #include # endif /* defined(HAS_SYS_SX_H) */ # if defined(HAS_SI_PRIV) || defined(HAS_CONF_MINOR) || defined(HAS_CDEV2PRIV) #include # endif /* defined(SI_PRIV) || defined(HAS_CONF_MINOR) || defined(HAS_CDEV2PRIV) */ #include #undef _KERNEL # endif /* FREEBSDV>=5000 */ #include # endif /* FREEBSDV<2000 */ #include # if FREEBSDV>=2020 # if FREEBSDV>=4090 #define _KERNEL # endif /* FREEBSDV>=4090 */ #include # if FREEBSDV>=4090 #undef _KERNEL # endif /* FREEBSDV>=4090 */ # if defined(HASVMLOCKH) #include # endif /* defined(HASVMLOCKH) */ #include # endif /* FREEBSDV>=2020 */ #include /* * Compensate for removal of MAP_ENTRY_IS_A_MAP from , * This work-around was supplied by John Polstra . */ #if defined(MAP_ENTRY_IS_SUB_MAP) && !defined(MAP_ENTRY_IS_A_MAP) #define MAP_ENTRY_IS_A_MAP 0 #endif /* defined(MAP_ENTRY_IS_SUB_MAP) && !defined(MAP_ENTRY_IS_A_MAP) */ #include #include # if FREEBSDV>=2020 #undef B_NEEDCOMMIT # if FREEBSDV>=5000 #include # endif /* FREEBSDV>=5000 */ #include #include # if FREEBSDV<5000 #include # endif /* FREEBSDV<5000 */ # endif /* FREEBSDV>=2020 */ #include #define COMP_P const void #define DEVINCR 1024 /* device table malloc() increment */ # if !defined(FREEBSD_KA_T) # if FREEBSDV<2000 typedef off_t KA_T; # else /* FREEBSDV>=2000 */ typedef u_long KA_T; # endif /* FREEBSDV<2000 */ # endif /* !defined(FREEBSD_KA_T) */ #define KMEM "/dev/kmem" #define MALLOC_P void #define FREE_P MALLOC_P #define MALLOC_S size_t #define MAXSYSCMDL MAXCOMLEN /* max system command name length */ # if defined(N_UNIXV) #define N_UNIX_TMP(x) #x #define N_UNIX_STR(x) N_UNIX_TMP(x) #define N_UNIX N_UNIX_STR(N_UNIXV) # endif /* defined(N_UNIXV) */ #define QSORT_P void # if !defined(READLEN_T) #define READLEN_T int # endif /* !defined(READLEN_T) */ #define STRNCPY_L size_t #define SWAP "/dev/drum" #define SZOFFTYPE unsigned long long /* size and offset internal storage * type */ #define SZOFFPSPEC "ll" /* SZOFFTYPE print specification * modifier */ /* * Global storage definitions (including their structure definitions) */ struct file * Cfp; # if FREEBSDV>=2000 extern kvm_t *Kd; # endif /* FREEBSDV>=2000 */ # if defined(P_ADDR) extern KA_T Kpa; # endif /* defined(P_ADDR) */ struct l_vfs { KA_T addr; /* kernel address */ fsid_t fsid; /* file system ID */ # if defined(MOUNT_NONE) short type; /* type of file system */ # else /* !defined(MOUNT_NONE) */ char *typnm; /* file system type name */ # endif /* defined(MOUNT_NONE) */ char *dir; /* mounted directory */ char *fsname; /* file system name */ struct l_vfs *next; /* forward link */ }; extern struct l_vfs *Lvfs; struct mounts { char *dir; /* directory (mounted on) */ char *fsname; /* file system * (symbolic links unresolved) */ char *fsnmres; /* file system * (symbolic links resolved) */ dev_t dev; /* directory st_dev */ dev_t rdev; /* directory st_rdev */ INODETYPE inode; /* directory st_ino */ mode_t mode; /* directory st_mode */ mode_t fs_mode; /* file system st_mode */ struct mounts *next; /* forward link */ }; #define X_NCACHE "ncache" #define X_NCSIZE "ncsize" #define NL_NAME n_name extern int Np; /* number of kernel processes */ # if FREEBSDV>=2000 extern struct kinfo_proc *P; /* local process table copy */ # endif /* FREEBSDV>=2000 */ struct sfile { char *aname; /* argument file name */ char *name; /* file name (after readlink()) */ char *devnm; /* device name (optional) */ dev_t dev; /* device */ dev_t rdev; /* raw device */ u_short mode; /* S_IFMT mode bits from stat() */ int type; /* file type: 0 = file system * 1 = regular file */ INODETYPE i; /* inode number */ int f; /* file found flag */ struct sfile *next; /* forward link */ }; # if FREEBSDV==4100 || FREEBSDV==4110 #define XDR_VOID (xdrproc_t)xdr_void #define XDR_PMAPLIST (xdrproc_t)xdr_pmaplist # endif /* FREEBSDV==4100 || FREEBSDV==4110 */ # if FREEBSDV>=5000 #define XDR_VOID (const xdrproc_t)xdr_void #define XDR_PMAPLIST (const xdrproc_t)xdr_pmaplist # endif /* FREEBSDV>=5000 */ /* * Definitions for rdev.c */ #define DIRTYPE dirent #define HASDNAMLEN 1 /* struct DIRTYPE has d_namlen element */ /* * Definitions for rnam.c and rnmh.c */ # if defined(HASNCACHE) #include # if FREEBSDV<4000 || (FREEBSDV>=4000 && defined(HASNAMECACHE)) #include # else /* FREEBSDV>=4000 && !defined(HASNAMECACHE) */ /* * The namecache struct definition should come from a header file that * can be #include'd, but it has been moved to a kernel source file in * 4.0-current for some reason unclear to me. * * So we must take the risk of defining it here. !!!! DANGER !!!! */ struct namecache { LIST_ENTRY(namecache) nc_hash; /* hash chain */ LIST_ENTRY(namecache) nc_src; /* source vnode list */ TAILQ_ENTRY(namecache) nc_dst; /* destination vnode list */ struct vnode *nc_dvp; /* vnode of parent of name */ struct vnode *nc_vp; /* vnode the name refers to */ u_char nc_flag; /* flag bits */ u_char nc_nlen; /* length of name */ char nc_name[16]; /* segment name -- Strictly composed, * the size of nc_name[] should be zero * and rnmh.c in lsof/lib should read * the name with a separate call to * kvm_read(). Since that causes extra * (and slow) calls to kvm_read(), the * size is set here to an experimentally * derived guess. The same experiment * didn't reveal any extra kvm_read() * suggesting the guess is a safe one. * (VAA, 10 Apr 2002) */ }; # endif /* FREEBSDV<4000 || (FREEBSDV>=4000 && defined(HASNAMECACHE)) */ #define NCACHE namecache /* kernel's structure name */ #define NCACHE_NM nc_name /* name in NCACHE */ #define NCACHE_NMLEN nc_nlen /* name length in NCACHE */ # if FREEBSDV<2005 #define NCACHE_NXT nc_nxt /* link in NCACHE */ # else /* FREEBSDV>=2005 */ # if FREEBSDV<2010 #define NCACHE_NXT nc_lru.tqe_next /* link in NCACHE */ # else /* FREEBSDV>=2010 */ #include #define NCACHE_NXT nc_hash.le_next /* link in NCACHE */ # endif /* FREEBSDV<2010 */ # endif /* FREEBSDV<2005 */ #define NCACHE_NODEADDR nc_vp /* node address in NCACHE */ #define NCACHE_PARADDR nc_dvp /* parent node address in NCACHE */ # if defined(HASNCVPID) #define NCACHE_NODEID nc_vpid /* node ID in NCACHE */ #define NCACHE_PARID nc_dvpid /* parent node ID in NCACHE */ # endif /* DEFINED(HASNCVPID) */ # endif /* defined(HASNCACHE) */ #if FREEBSDV>=5000 #define VNODE_VFLAG v_iflag #define NCACHE_VROOT VV_ROOT #endif /* FREEBSDV>=5000 */ #endif /* defined(FREEBSD_LSOF_H) */ lsof-4.86+dfsg.orig/dialects/freebsd/dnode1.c0000444000175000017500000000715111147407027021203 0ustar nicholasnicholas/* * dnode1.c - FreeBSD node functions for lsof * * This module must be separate to keep separate the multiple kernel inode * structure definitions. */ /* * Copyright 1995 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dnode1.c,v 1.10 2008/10/21 16:16:06 abe Exp abe $"; #endif #include "lsof.h" #if defined(HAS9660FS) /* * Do a little preparation for #include'ing cd9660_node.h, then #include it. */ #undef i_size #undef doff_t #undef IN_ACCESS # if FREEBSDV>=4000 && defined(__alpha__) #define dev_t void * # endif /* FREEBSDV>=4000 && defined(__alpha__) */ #include "cd9660_node.h" # if defined(HAS_NO_ISO_DEV) #define _KERNEL #include #undef _KERNEL # endif /* defined(HAS_NO_ISO_DEV) */ # if FREEBSDV>=4000 && defined(__alpha__) #undef dev_t # endif /* FREEBSDV>=4000 && defined(__alpha__) */ /* * read_iso_node() -- read CD 9660 iso_node */ int read_iso_node(v, d, dd, ino, nl, sz) struct vnode *v; /* containing vnode */ dev_t *d; /* returned device number */ int *dd; /* returned device-defined flag */ INODETYPE *ino; /* returned inode number */ long *nl; /* returned number of links */ SZOFFTYPE *sz; /* returned size */ { # if FREEBSDV<2000 struct iso_node *ip; # else /* FREEBSDV>=2000 */ struct iso_node i; # endif /* FREEBSDV<2000 */ # if FREEBSDV>=4000 # if FREEBSDV<5000 struct specinfo udev; # else /* FREEBSDV>=5000 */ struct cdev udev; # if defined(HAS_NO_ISO_DEV) struct iso_mnt im; # endif /* defined(HAS_NO_ISO_DEV) */ # endif /* FREEBSDV<5000 */ # endif /* FREEBSDV>=4000 */ # if FREEBSDV<2000 ip = (struct iso_node *)v->v_data; *d = ip->i_dev; *dd = 1; *ino = (INODETYPE)ip->i_number; *nl = (long)ip->inode.iso_links; *sz = (SZOFFTYPE)ip->i_size; # else /* FREEBSDV>=2000 */ if (!v->v_data || kread((KA_T)v->v_data, (char *)&i, sizeof(i))) return(1); # if FREEBSDV>=4000 # if defined(HAS_NO_ISO_DEV) if (i.i_mnt && !kread((KA_T)i.i_mnt, (char *)&im, sizeof(im)) && im.im_dev && !kread((KA_T)im.im_dev, (char *)&udev, sizeof(udev))) # else /* !defined(HAS_NO_ISO_DEV) */ if (i.i_dev && !kread((KA_T)i.i_dev, (char *)&udev, sizeof(udev))) # endif /* defined(HAS_NO_ISO_DEV) */ { # if defined(HAS_NO_SI_UDEV) *d = Dev2Udev(&udev); # else /* !defined(HAS_NO_SI_UDEV) */ *d = udev.si_udev; # endif /* defined(HAS_NO_SI_UDEV) */ *dd = 1; } # else /* FREEBSDV<4000 */ *d = i.i_dev; *dd = 1; # endif /* FREEBSDV>=4000 */ *ino = (INODETYPE)i.i_number; *nl = (long)i.inode.iso_links; *sz = (SZOFFTYPE)i.i_size; # endif /* FREEBSDV<2000 */ return(0); } #endif /* defined(HAS9660FS) */ lsof-4.86+dfsg.orig/dialects/freebsd/Mksrc0000555000175000017500000000114211001127106020646 0ustar nicholasnicholas#!/bin/sh # # Mksrc - make FreeBSD source files # # WARNING: This script assumes it is running from the main directory # of the lsof, version 4 distribution. # # One environment variable applies: # # LSOF_MKC is the method for creating the source files. # It defaults to "ln -s". A common alternative is "cp". # # $Id: Mksrc,v 1.5 2008/04/15 13:31:47 abe Exp $ D=dialects/freebsd L="dlsof.h dmnt.c dnode.c dnode1.c dnode2.c dproc.c dproto.h dsock.c dstore.c dzfs.h machine.h" for i in $L do rm -f $i $LSOF_MKC $D/$i $i echo "$LSOF_MKC $D/$i $i" done # For ZFS rm -f vnode_if.h touch vnode_if.h lsof-4.86+dfsg.orig/dialects/freebsd/dnode.c0000444000175000017500000007706711617613371021142 0ustar nicholasnicholas/* * dnode.c - FreeBSD node functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dnode.c,v 1.41 2011/08/07 22:51:28 abe Exp $"; #endif #include "lsof.h" #if defined(HAS_LOCKF_ENTRY) #include "./lockf_owner.h" #endif /* defined(HAS_LOCKF_ENTRY) */ #if defined(HAS_ZFS) #include "dzfs.h" #endif /* defined(HAS_ZFS) */ #if defined(HASFDESCFS) && HASFDESCFS==1 _PROTOTYPE(static int lkup_dev_tty,(dev_t *dr, INODETYPE *ir)); #endif /* defined(HASFDESCFS) && HASFDESCFS==1 */ _PROTOTYPE(static void get_lock_state,(KA_T f)); /* * get_lock_state() -- get the lock state */ static void get_lock_state(f) KA_T f; /* inode's lock pointer */ { struct lockf lf; /* lockf structure */ int lt; /* lock type */ #if defined(HAS_LOCKF_ENTRY) struct lockf_entry le; /* lock_entry structure */ KA_T lef, lep; /* lock_entry pointers */ struct lock_owner lo; /* lock owner structure */ if (!f || kread(f, (char *)&lf, sizeof(lf))) return; if (!(lef = (KA_T)lf.ls_active.lh_first)) return; lep = lef; do { if (kread(lep, (char *)&le, sizeof(le))) return; if (!le.lf_owner || kread((KA_T)le.lf_owner, (char *)&lo, sizeof(lo))) continue; if (lo.lo_pid == (pid_t)Lp->pid) { if (le.lf_start == (off_t)0 && le.lf_end == 0x7fffffffffffffffLL) lt = 1; else lt = 0; if (le.lf_type == F_RDLCK) Lf->lock = lt ? 'R' : 'r'; else if (le.lf_type == F_WRLCK) Lf->lock = lt ? 'W' : 'w'; else if (le.lf_type == (F_RDLCK | F_WRLCK)) Lf->lock = 'u'; return; } } while ((lep = (KA_T)le.lf_link.le_next) && (lep != lef)); #else /* !defined(HAS_LOCKF_ENTRY) */ unsigned char l; /* lock status */ KA_T lfp; /* lockf structure pointer */ if ((lfp = f)) { /* * Determine the lock state. */ do { if (kread(lfp, (char *)&lf, sizeof(lf))) break; l = 0; switch (lf.lf_flags & (F_FLOCK|F_POSIX)) { case F_FLOCK: if (Cfp && (struct file *)lf.lf_id == Cfp) l = 1; break; case F_POSIX: # if defined(P_ADDR) if ((KA_T)lf.lf_id == Kpa) l = 1; # endif /* defined(P_ADDR) */ break; } if (!l) continue; if (lf.lf_start == (off_t)0 && lf.lf_end == 0xffffffffffffffffLL) lt = 1; else lt = 0; if (lf.lf_type == F_RDLCK) Lf->lock = lt ? 'R' : 'r'; else if (lf.lf_type == F_WRLCK) Lf->lock = lt ? 'W' : 'w'; else if (lf.lf_type == (F_RDLCK | F_WRLCK)) Lf->lock = 'u'; break; } while ((lfp = (KA_T)lf.lf_next) && (lfp != f)); } #endif /* defined(HAS_LOCKF_ENTRY) */ } #if FREEBSDV>=2000 # if defined(HASPROCFS) _PROTOTYPE(static void getmemsz,(pid_t pid)); /* * getmemsz() - get memory size of a /proc//mem entry */ static void getmemsz(pid) pid_t pid; { int n; struct kinfo_proc *p; struct vmspace vm; for (n = 0, p = P; n < Np; n++, p++) { if (p->P_PID == pid) { if (!p->P_VMSPACE || kread((KA_T)p->P_VMSPACE, (char *)&vm, sizeof(vm))) return; Lf->sz = (SZOFFTYPE)ctob(vm.vm_tsize+vm.vm_dsize+vm.vm_ssize); Lf->sz_def = 1; return; } } } # endif /* defined(HASPROCFS) */ #endif /* FREEBSDV>=2000 */ #if defined(HASFDESCFS) && HASFDESCFS==1 /* * lkup_dev_tty() - look up /dev/tty */ static int lkup_dev_tty(dr, ir) dev_t *dr; /* place to return device number */ INODETYPE *ir; /* place to return inode number */ { int i; readdev(0); # if defined(HASDCACHE) lkup_dev_tty_again: # endif /* defined(HASDCACHE) */ for (i = 0; i < Ndev; i++) { if (strcmp(Devtp[i].name, "/dev/tty") == 0) { # if defined(HASDCACHE) if (DCunsafe && !Devtp[i].v && !vfy_dev(&Devtp[i])) goto lkup_dev_tty_again; # endif /* defined(HASDCACHE) */ *dr = Devtp[i].rdev; *ir = Devtp[i].inode; return(1); } } # if defined(HASDCACHE) if (DCunsafe) { (void) rereaddev(); goto lkup_dev_tty_again; } # endif /* defined(HASDCACHE) */ return(-1); } #endif /* defined(HASFDESCFS) && HASFDESCFS==1 */ #if defined(HASKQUEUE) /* * process_kqueue() -- process kqueue file * * Strictly speaking this function should appear in dfile.c, because it is * a file processing function. However, the Net and Open BSD sources don't * require a dfile.c, so this is the next best location for the function. */ void process_kqueue(ka) KA_T ka; /* kqueue file structure address */ { struct kqueue kq; /* kqueue structure */ (void) snpf(Lf->type, sizeof(Lf->type), "KQUEUE"); enter_dev_ch(print_kptr(ka, (char *)NULL, 0)); if (!ka || kread(ka, (char *)&kq, sizeof(kq))) return; (void) snpf(Namech, Namechl, "count=%d, state=%#x", kq.kq_count, kq.kq_state); enter_nm(Namech); } #endif /* defined(HASKQUEUE) */ /* * process_node() - process vnode */ void process_node(va) KA_T va; /* vnode kernel space address */ { dev_t dev, rdev; unsigned char devs; unsigned char rdevs; char dev_ch[32], *ep; struct inode *i; struct nfsnode *n; size_t sz; char *ty; enum vtype type; struct vnode *v, vb; struct l_vfs *vfs; #if FREEBSDV>=2000 struct inode ib; struct nfsnode nb; # if FREEBSDV>=4000 # if FREEBSDV<5000 struct specinfo si; # else /* FREEBSDV>=5000 */ # if !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV) struct cdev si; # endif /* !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV) */ # endif /* FREEBSDV<5000 */ # endif /* FREEBSDV>=4000 */ #endif /* FREEBSDV>=2000 */ #if FREEBSDV<5000 struct mfsnode *m; # if FREEBSDV>=2000 struct mfsnode mb; # endif /* FREEBSDV>=2000 */ #endif /* FREEBSDV<5000 */ #if defined(HAS9660FS) dev_t iso_dev; int iso_dev_def, iso_stat; INODETYPE iso_ino; long iso_links; SZOFFTYPE iso_sz; #endif /* defined(HAS9660FS) */ #if defined(HASFDESCFS) struct fdescnode *f; # if HASFDESCFS==1 static dev_t f_tty_dev; static INODETYPE f_tty_ino; static int f_tty_s = 0; # endif /* HASFDESCFS==1 */ # if FREEBSDV>=2000 struct fdescnode fb; # endif /* FREEBSDV>=2000 */ #endif /* defined(HASFDESCFS) */ #if FREEBSDV>=5000 # if defined(HAS_UFS1_2) int ufst; struct ufsmount um; struct ufs1_dinode d1; struct ufs2_dinode d2; # endif /* !defined(HAS_UFS1_2) */ # if !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV) struct cdev cd; # endif /* !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV) */ int cds; struct devfs_dirent de; struct devfs_dirent *d; char vtbuf[32]; char *vtbp; enum vtagtype { VT_DEVFS, VT_FDESC, VT_ISOFS, VT_PSEUDOFS, VT_NFS, VT_NULL, VT_UFS, VT_ZFS, VT_UNKNOWN }; #endif /* FREEBSDV>=5000 */ #if defined(HASNULLFS) # if !defined(HASPRINTDEV) char dbuf[32]; # endif /* !defined(HASPRINTDEV) */ char *dp, *np, tbuf[1024]; struct null_node nu; int sc = 0; #endif /* defined(HASNULLFS) */ #if defined(HASPROCFS) struct pfsnode *p; struct procfsid *pfi; static int pgsz = -1; struct vmspace vm; # if FREEBSDV>=2000 struct pfsnode pb; # endif /* FREEBSDV>=2000 */ #endif /* defined(HASPROCFS) */ #if defined(HASPSEUDOFS) struct pfs_node pn; struct pfs_node *pnp; #endif /* defined(HASPSEUDOFS) */ #if defined(HAS_ZFS) zfs_info_t *z = (zfs_info_t *)NULL; zfs_info_t zi; char *zm = (char *)NULL; #else /* !defined(HAS_ZFS) */ static unsigned char zw = 0; #endif /* HAS_VFS */ enum vtagtype vtag; /* placed here to use the * artificial vtagtype * definition required for * FREEBSDV>=5000 */ #if defined(HASNULLFS) process_overlaid_node: if (++sc > 1024) { (void) snpf(Namech, Namechl, "too many overlaid nodes"); enter_nm(Namech); return; } #endif /* defined(HASNULLFS) */ /* * Initialize miscellaneous variables. This is done so that processing an * overlaid node will be a fresh start. */ devs = rdevs = 0; i = (struct inode *)NULL; n = (struct nfsnode *)NULL; Namech[0] = '\0'; #if defined(HAS9660FS) iso_dev_def = iso_stat = 0; #endif /* defined(HAS9660FS) */ #if defined(HASFDESCFS) f = (struct fdescnode *)NULL; #endif /* defined(HASFDESCFS) */ #if FREEBSDV<5000 m = (struct mfsnode *)NULL; #else /* FREEBSDV>=5000 */ cds = 0; d = (struct devfs_dirent *)NULL; # if defined(HAS_UFS1_2) ufst = 0; # endif /* !defined(HAS_UFS1_2) */ #endif /* FREEBSDV<5000 */ #if defined(HASPROCFS) p = (struct pfsnode *)NULL; #endif /* defined(HASPROCFS) */ #if defined(HASPSEUDOFS) pnp = (struct pfs_node *)NULL; #endif /* defined(HASPSEUDOFS) */ #if defined(HAS_ZFS) z = (zfs_info_t *)NULL; zm = (char *)NULL; #endif /* defined(HAS_ZFS) */ /* * Read the vnode. */ if ( ! va) { enter_nm("no vnode address"); return; } v = &vb; if (readvnode(va, v)) { enter_nm(Namech); return; } #if defined(HASNCACHE) Lf->na = va; # if defined(HASNCVPID) Lf->id = v->v_id; # endif /* defined(HASNCVPID) */ #endif /* defined(HASNCACHE) */ #if defined(HASFSTRUCT) Lf->fna = va; Lf->fsv |= FSV_NI; #endif /* defined(HASFSTRUCT) */ /* * Get the vnode type. */ if (!v->v_mount) vfs = (struct l_vfs *)NULL; else { vfs = readvfs((KA_T)v->v_mount); if (vfs) { #if defined(MOUNT_NONE) switch (vfs->type) { case MOUNT_NFS: Ntype = N_NFS; break; # if defined(HASPROCFS) case MOUNT_PROCFS: Ntype = N_PROC; break; # endif /* defined(HASPROCFS) */ } #else /* !defined(MOUNT_NONE) */ if (strcasecmp(vfs->typnm, "nfs") == 0) Ntype = N_NFS; # if defined(HASPROCFS) else if (strcasecmp(vfs->typnm, "procfs") == 0) Ntype = N_PROC; # endif /* defined(HASPROCFS) */ # if defined(HASPSEUDOFS) else if (strcasecmp(vfs->typnm, "pseudofs") == 0) Ntype = N_PSEU; # endif /* defined(HASPSEUDOFS) */ #endif /* defined(MOUNT_NONE) */ } } if (Ntype == N_REGLR) { switch (v->v_type) { case VFIFO: Ntype = N_FIFO; break; default: break; } } #if FREEBSDV>=5000 /* * For FreeBSD 5 and above VCHR and VBLK vnodes get the v_rdev structure. */ if (((v->v_type == VCHR) || (v->v_type == VBLK)) && v->v_rdev # if !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV) && !kread((KA_T)v->v_rdev, (char *)&cd, sizeof(cd)) # endif /* !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV) */ ) { cds = 1; } #endif /* FREEBSDV>=5000 */ /* * Define the specific node pointer. */ #if FREEBSDV>=5000 /* * Get the pseudo vnode tag type for FreeBSD >= 5. */ vtag = VT_UNKNOWN; if (v->v_tag && !kread((KA_T)v->v_tag, (char *)&vtbuf, sizeof(vtbuf))) { vtbuf[sizeof(vtbuf) - 1] = '\0'; vtbp = vtbuf; if (!strcmp(vtbuf, "ufs")) vtag = VT_UFS; else if (!strcmp(vtbuf, "zfs")) { #if !defined(HAS_ZFS) if (!Fwarn && !zw) { (void) fprintf(stderr, "%s: WARNING: no ZFS support has been defined.\n", Pn); (void) fprintf(stderr, " See 00FAQ for more information.\n"); zw = 1; } #else /* defined(HAS_ZFS) */ vtag = VT_ZFS; #endif /* !defined(HAS_ZFS) */ } else if (!strcmp(vtbuf, "devfs")) vtag = VT_DEVFS; else if (!strcmp(vtbuf, "nfs")) vtag = VT_NFS; else if (!strcmp(vtbuf, "isofs")) vtag = VT_ISOFS; else if (!strcmp(vtbuf, "pseudofs")) vtag = VT_PSEUDOFS; else if (!strcmp(vtbuf, "null")) vtag = VT_NULL; else if (!strcmp(vtbuf, "fdesc")) vtag = VT_FDESC; } else vtbp = "(unknown)"; #else /* FREEBSDV<5000 */ vtag = v->v_tag; #endif /* FREEBSDV>=5000 */ switch (vtag) { #if FREEBSDV>=5000 case VT_DEVFS: if (!v->v_data || kread((KA_T)v->v_data, (char *)&de, sizeof(de))) { (void) snpf(Namech, Namechl, "no devfs node: %s", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } d = &de; if (v->v_type == VDIR) { if (!d->de_dir || kread((KA_T)d->de_dir, (char *)&de, sizeof(de))) { (void) snpf(Namech, Namechl, "no devfs dir node: %s", print_kptr((KA_T)d->de_dir, (char *)NULL, 0)); enter_nm(Namech); return; } } break; #endif /* FREEBSDV>=5000 */ #if defined(HASFDESCFS) case VT_FDESC: # if FREEBSDV<2000 f = (struct fdescnode *)v->v_data; # else /* FREEBSDV>=2000 */ if (kread((KA_T)v->v_data, (char *)&fb, sizeof(fb)) != 0) { (void) snpf(Namech, Namechl, "can't read fdescnode at: %s", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } f = &fb; break; # endif /* FREEBSDV<2000 */ #endif /* defined(HASFDESCFS) */ #if defined(HAS9660FS) case VT_ISOFS: if (read_iso_node(v, &iso_dev, &iso_dev_def, &iso_ino, &iso_links, &iso_sz)) { (void) snpf(Namech, Namechl, "no iso node: %s", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } iso_stat = 1; break; #endif /* defined(HAS9660FS) */ #if FREEBSDV<5000 case VT_MFS: # if FREEBSDV<2000 m = (struct mfsnode *)v->v_data; # else /* FREEBSDV>=2000 */ if (!v->v_data || kread((KA_T)v->v_data, (char *)&mb, sizeof(mb))) { (void) snpf(Namech, Namechl, "no mfs node: %s", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } m = &mb; # endif /* FREEBSDV<2000 */ #endif /* FREEBSDV<5000 */ break; case VT_NFS: #if FREEBSDV<2000 n = (struct nfsnode *)v->v_data; #else /* FREEBSDV>=2000 */ if (!v->v_data || kread((KA_T)v->v_data, (char *)&nb, sizeof(nb))) { (void) snpf(Namech, Namechl, "no nfs node: %s", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } n = &nb; #endif /* FREEBSDV<2000 */ break; #if defined(HASNULLFS) case VT_NULL: if (sc == 1) { /* * If this is the first null_node, enter a name addition containing * the mounted-on directory, the file system name, and the device * number. */ if (vfs && (vfs->dir || vfs->fsname || vfs->fsid.val[0])) { if (vfs->fsid.val[0]) { #if defined(HASPRINTDEV) dp = HASPRINTDEV(Lf, &dev); #else /* !defined(HASPRINTDEV) */ (void) snpf(dbuf, sizeof(dbuf) - 1, "%d,%d", GET_MAJ_DEV(dev), GET_MIN_DEV(dev)); dbuf[sizeof(dbuf) - 1] = '\0'; dp = dbuf; #endif /* defined(HASPRINTDEV) */ } else dp = (char *)NULL; (void) snpf(tbuf, sizeof(tbuf) - 1, "(nullfs%s%s%s%s%s%s%s)", (vfs && vfs->fsname) ? " " : "", (vfs && vfs->fsname) ? vfs->fsname : "", (vfs && vfs->dir) ? " on " : "", (vfs && vfs->dir) ? vfs->dir : "", (dp && vfs && vfs->dir) ? " (" : "", (dp && vfs && vfs->dir) ? dp : "", (dp && vfs && vfs->dir) ? ")" : ""); tbuf[sizeof(tbuf) - 1] = '\0'; np = tbuf; } else np = "(nullfs)"; (void) add_nma(np, (int)strlen(np)); } if (!v->v_data || kread((KA_T)v->v_data, (char *)&nu, sizeof(nu))) { (void) snpf(Namech, Namechl, "can't read null_node at: %s", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } if (!nu.null_lowervp) { (void) snpf(Namech, Namechl, "null_node overlays nothing"); enter_nm(Namech); return; } va = (KA_T)nu.null_lowervp; goto process_overlaid_node; #endif /* defined(HASNULLFS) */ #if defined(HASPROCFS) case VT_PROCFS: # if FREEBSDV<2000 p = (struct pfsnode *)v->v_data; # else /* FREEBSDV>=2000 */ if (!v->v_data || kread((KA_T)v->v_data, (char *)&pb, sizeof(pb))) { (void) snpf(Namech, Namechl, "no pfs node: %s", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } p = &pb; # endif /* FREEBSDV<2000 */ break; #endif /* defined(HASPROCFS) */ #if defined(HASPSEUDOFS) case VT_PSEUDOFS: if (!v->v_data || kread((KA_T)v->v_data, (char *)&pn, sizeof(pn))) { (void) snpf(Namech, Namechl, "no pfs_node: %s", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } pnp = &pn; break; #endif /* defined(HASPSEUDOFS) */ case VT_UFS: #if FREEBSDV<2000 i = (struct inode *)v->v_data; #else /* FREEBSDV>=2000 */ if (!v->v_data || kread((KA_T)v->v_data, (char *)&ib, sizeof(ib))) { (void) snpf(Namech, Namechl, "no ufs node: %s", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } i = &ib; # if defined(HAS_UFS1_2) if (i->i_ump && !kread((KA_T)i->i_ump, (char *)&um, sizeof(um))) { if (um.um_fstype == UFS1) { if (i->i_din1 && !kread((KA_T)i->i_din1, (char *)&d1, sizeof(d1))) ufst = 1; } else { if (i->i_din2 && !kread((KA_T)i->i_din2, (char *)&d2, sizeof(d2))) ufst = 2; } } # endif /* defined(HAS_UFS1_2) */ #endif /* FREEBSDV<2000 */ #if defined(HAS_V_LOCKF) if (v->v_lockf) (void) get_lock_state((KA_T)v->v_lockf); #else /* !defined(HAS_V_LOCKF) */ if (i->i_lockf) (void) get_lock_state((KA_T)i->i_lockf); #endif /* defined(HAS_V_LOCKF) */ break; #if defined(HAS_ZFS) case VT_ZFS: if (!v->v_data || (zm = readzfsnode((KA_T)v->v_data, &zi, ((v->v_vflag & VV_ROOT) ? 1 : 0))) ) { (void) snpf(Namech, Namechl, "%s: %s", zm, print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } z = &zi; #if defined(HAS_V_LOCKF) if (v->v_lockf) (void) get_lock_state((KA_T)v->v_lockf); #else /* !defined(HAS_V_LOCKF) */ if (z->lockf) (void) get_lock_state((KA_T)z->lockf); #endif /* defined(HAS_V_LOCKF) */ break; #endif /* defined(HAS_ZFS) */ default: if (v->v_type == VBAD || v->v_type == VNON) break; #if FREEBSDV<5000 (void) snpf(Namech,Namechl,"unknown file system type: %d",v->v_tag); #else /* FREEBSDV>=5000 */ (void) snpf(Namech, Namechl, "unknown file system type: %s", vtbp); #endif /* FREEBSDV<5000 */ enter_nm(Namech); return; } /* * Get device and type for printing. */ type = v->v_type; if (n) { dev = n->n_vattr.va_fsid; devs = 1; if ((type == VCHR) || (type == VBLK)) { rdev = n->n_vattr.va_rdev; rdevs = 1; } } else if (i) { #if FREEBSDV>=4000 if (i->i_dev # if !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV) && !kread((KA_T)i->i_dev, (char *)&si, sizeof(si)) # endif /* !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV) */ ) { # if defined(HAS_NO_SI_UDEV) # if defined(HAS_CONF_MINOR) || defined(HAS_CDEV2PRIV) dev = Dev2Udev((KA_T)i->i_dev); # else /* !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV) */ dev = Dev2Udev(&si); # endif /* defined(HAS_CONF_MINOR) || defined(HAS_CDEV2PRIV) */ # else /* !defined(HAS_NO_SI_UDEV) */ dev = si.si_udev; # endif /* defined(HAS_NO_SI_UDEV) */ devs = 1; } #else /* FREEBSDV<4000 */ dev = i->i_dev; devs = 1; #endif /* FREEBSDV>=4000 */ if ((type == VCHR) || (type == VBLK)) { #if FREEBSDV>=5000 # if defined(HAS_UFS1_2) if (ufst == 1) { rdev = d1.di_rdev; rdevs = 1; } else if (ufst == 2) { rdev = d2.di_rdev; rdevs = 1; } else # endif /* defined(HAS_UFS1_2) */ if (cds) { # if defined(HAS_NO_SI_UDEV) # if defined(HAS_CONF_MINOR) || defined(HAS_CDEV2PRIV) rdev = Dev2Udev((KA_T)v->v_rdev); # else /* !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV) */ rdev = Dev2Udev(&cd); # endif /* defined(HAS_CONF_MINOR) || defined(HAS_CDEV2PRIV) */ # else /* !defined(HAS_NO_SI_UDEV) */ rdev = cd.si_udev; # endif /* defined(HAS_NO_SI_UDEV) */ rdevs = 1; } #else /* FREEBSDV<5000 */ rdev = i->i_rdev; rdevs = 1; #endif /* FREEBSDV>=5000 */ } } #if defined(HAS_ZFS) else if (z) { /* * Record information returned by readzfsnode(). */ if (vfs) { dev = vfs->fsid.val[0]; devs = 1; } if ((type == VCHR) || (type == VBLK)) { if (z->rdev_def) { rdev = z->rdev; rdevs = 1; } } } #endif /* defined(HAS_ZFS) */ #if defined(HASFDESCFS) && (defined(HASFDLINK) || HASFDESCFS==1) else if (f) { # if defined(HASFDLINK) if (f->fd_link && kread((KA_T)f->fd_link, Namech, Namechl - 1) == 0) Namech[Namechl - 1] = '\0'; # if HASFDESCFS==1 else # endif /* HASFDESFS==1 */ # endif /* defined(HASFDLINK) */ # if HASFDESCFS==1 if (f->fd_type == Fctty) { if (f_tty_s == 0) f_tty_s = lkup_dev_tty(&f_tty_dev, &f_tty_ino); if (f_tty_s == 1) { dev = f_tty_dev; Lf->inode = f_tty_ino; devs = Lf->inp_ty = 1; } } # endif /* HASFDESFS==1 */ } #endif /* defined(HASFDESCFS) && (defined(HASFDLINK) || HASFDESCFS==1) */ #if defined(HAS9660FS) else if (iso_stat && iso_dev_def) { dev = iso_dev; devs = Lf->inp_ty = 1; } #endif /* defined(HAS9660FS) */ #if FREEBSDV>=5000 else if (d) { if (vfs) { dev = vfs->fsid.val[0]; devs = 1; } else { dev = DevDev; devs = 1; } if ((type == VCHR)) { # if defined(HAS_UFS1_2) if (ufst == 1) { rdev = d1.di_rdev; rdevs = 1; } else if (ufst == 2) { rdev = d2.di_rdev; rdevs = 1; } else # endif /* defined(HAS_UFS1_2) */ if (cds) { # if defined(HAS_NO_SI_UDEV) # if defined(HAS_CONF_MINOR) || defined(HAS_CDEV2PRIV) rdev = Dev2Udev((KA_T)v->v_rdev); # else /* !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV) */ rdev = Dev2Udev(&cd); # endif /* defined(HAS_CONF_MINOR) || defined(HAS_CDEV2PRIV) */ # else /* !defined(HAS_NO_SI_UDEV) */ rdev = cd.si_udev; # endif /* defined(HAS_NO_SI_UDEV) */ rdevs = 1; } } } #endif /* FREEBSDV>=5000 */ #if defined(HASPSEUDOFS) else if (pnp) { if (vfs) { dev = vfs->fsid.val[0]; devs = 1; } } #endif /* defined(HASPSEUDOFS) */ /* * Obtain the inode number. */ if (i) { Lf->inode = (INODETYPE)i->i_number; Lf->inp_ty = 1; } #if defined(HAS_ZFS) else if (z) { if (z->ino_def) { Lf->inode = z->ino; Lf->inp_ty = 1; } } #endif /* defined(HAS_ZFS) */ else if (n) { Lf->inode = (INODETYPE)n->n_vattr.va_fileid; Lf->inp_ty = 1; } #if defined(HAS9660FS) else if (iso_stat) { Lf->inode = iso_ino; Lf->inp_ty = 1; } #endif /* defined(HAS9660FS) */ #if defined(HASPROCFS) # if FREEBSDV>=2000 else if (p) { Lf->inode = (INODETYPE)p->pfs_fileno; Lf->inp_ty = 1; } # endif /* FREEBSDV>=2000 */ #endif /* defined(HASPROCFS) */ #if defined(HASPSEUDOFS) else if (pnp) { Lf->inode = (INODETYPE)pnp->pn_fileno; Lf->inp_ty = 1; } #endif /* defined(HASPSEUDOFS) */ #if FREEBSDV>=5000 else if (d) { Lf->inode = (INODETYPE)d->de_inode; Lf->inp_ty = 1; } #endif /* FREEBSDV>=5000 */ /* * Obtain the file size. */ if (Foffset) Lf->off_def = 1; else { switch (Ntype) { case N_FIFO: if (!Fsize) Lf->off_def = 1; break; case N_NFS: if (n) { Lf->sz = (SZOFFTYPE)n->n_vattr.va_size; Lf->sz_def = 1; } break; #if defined(HASPROCFS) case N_PROC: # if FREEBSDV<2000 if (type == VDIR || !p || !p->pfs_vs || kread((KA_T)p->pfs_vs, (char *)&vm, sizeof(vm))) break; if (pgsz < 0) pgsz = getpagesize(); Lf->sz = (SZOFFTYPE)((pgsz * vm.vm_tsize) + (pgsz * vm.vm_dsize) + (pgsz * vm.vm_ssize)); Lf->sz_def = 1; break; # else /* FREEBSDV>=2000 */ if (p) { switch(p->pfs_type) { case Proot: case Pproc: Lf->sz = (SZOFFTYPE)DEV_BSIZE; Lf->sz_def = 1; break; case Pmem: (void) getmemsz(p->pfs_pid); break; case Pregs: Lf->sz = (SZOFFTYPE)sizeof(struct reg); Lf->sz_def = 1; break; case Pfpregs: Lf->sz = (SZOFFTYPE)sizeof(struct fpreg); Lf->sz_def = 1; break; } } # endif /* FREEBSDV<2000 */ #endif /* defined(HASPROCFS) */ #if defined(HASPSEUDOFS) case N_PSEU: Lf->sz = 0; Lf->sz_def = 1; break; #endif /* defined(PSEUDOFS) */ case N_REGLR: if (type == VREG || type == VDIR) { if (i) { #if defined(HAS_UFS1_2) if (ufst == 1) Lf->sz = (SZOFFTYPE)d1.di_size; else if (ufst == 2) Lf->sz = (SZOFFTYPE)d2.di_size; else #endif /* defined(HAS_UFS1_2) */ Lf->sz = (SZOFFTYPE)i->i_size; Lf->sz_def = 1; } #if defined(HAS_ZFS) else if (z) { if (z->sz_def) { Lf->sz = z->sz; Lf->sz_def = 1; } } #endif /* defined(HAS_ZFS) */ #if FREEBSDV<5000 else if (m) { Lf->sz = (SZOFFTYPE)m->mfs_size; Lf->sz_def = 1; } #endif /* FREEBSDV<5000 */ #if defined(HAS9660FS) else if (iso_stat) { Lf->sz = (SZOFFTYPE)iso_sz; Lf->sz_def = 1; } #endif /* defined(HAS9660FS) */ } else if ((type == VCHR || type == VBLK) && !Fsize) Lf->off_def = 1; break; } } /* * Record the link count. */ if (Fnlink) { switch(Ntype) { case N_NFS: if (n) { Lf->nlink = (long)n->n_vattr.va_nlink; Lf->nlink_def = 1; } break; case N_REGLR: if (i) { #if defined(HASEFFNLINK) Lf->nlink = (long)i->HASEFFNLINK; #else /* !defined(HASEFFNLINK) */ Lf->nlink = (long)i->i_nlink; #endif /* defined(HASEFFNLINK) */ Lf->nlink_def = 1; } #if defined(HAS_ZFS) else if (z) { if (z->nl_def) { Lf->nlink = z->nl; Lf->nlink_def = 1; } } #endif /* defined(HAS_ZFS) */ #if defined(HAS9660FS) else if (iso_stat) { Lf->nlink = iso_links; Lf->nlink_def = 1; } #endif /* defined(HAS9660FS) */ #if FREEBSDV>=5000 else if (d) { Lf->nlink = d->de_links; Lf->nlink_def = 1; } #endif /* FREEBSDV>=5000 */ break; #if defined(HASPSEUODOFS) case N_PSEU: if (pnp) { Lf->nlink = 1L; Lf->nlink_def = 1; } break; #endif /* defined(HASPSEUODOFS) */ } if (Lf->nlink_def && Nlink && (Lf->nlink < Nlink)) Lf->sf |= SELNLINK; } /* * Record an NFS file selection. */ if (Ntype == N_NFS && Fnfs) Lf->sf |= SELNFS; /* * Save the file system names. */ if (vfs) { Lf->fsdir = vfs->dir; Lf->fsdev = vfs->fsname; } /* * Save the device numbers and their states. * * Format the vnode type, and possibly the device name. */ Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; switch (type) { case VNON: ty ="VNON"; break; case VREG: case VDIR: ty = (type == VREG) ? "VREG" : "VDIR"; break; case VBLK: ty = "VBLK"; Ntype = N_BLK; break; case VCHR: ty = "VCHR"; Ntype = N_CHR; break; case VLNK: ty = "VLNK"; break; #if defined(VSOCK) case VSOCK: ty = "SOCK"; break; #endif /* defined(VSOCK) */ case VBAD: ty = "VBAD"; break; case VFIFO: ty = "FIFO"; break; default: (void) snpf(Lf->type, sizeof(Lf->type), "%04o", (type & 0xfff)); ty = (char *)NULL; } if (ty) (void) snpf(Lf->type, sizeof(Lf->type), "%s", ty); Lf->ntype = Ntype; /* * Handle some special cases: * * ioctl(fd, TIOCNOTTY) files; * memory node files; * /proc files. */ if (type == VBAD) (void) snpf(Namech, Namechl, "(revoked)"); #if FREEBSDV<5000 else if (m) { Lf->dev_def = Lf->rdev_def = 0; (void) snpf(Namech, Namechl, "%#x", m->mfs_baseoff); (void) snpf(dev_ch, sizeof(dev_ch), " memory"); enter_dev_ch(dev_ch); } #endif /* FREEBSDV<5000 */ #if defined(HASPROCFS) else if (p) { Lf->dev_def = Lf->rdev_def = 0; # if FREEBSDV<2000 if (type == VDIR) (void) snpf(Namech, Namechl, "/%s", HASPROCFS); else (void) snpf(Namech, Namechl, "/%s/%0*d", HASPROCFS, PNSIZ, p->pfs_pid); enter_nm(Namech); # else /* FREEBSDV>=2000 */ ty = (char *)NULL; (void) snpf(Namech, Namechl, "/%s", HASPROCFS); switch (p->pfs_type) { case Proot: ty = "PDIR"; break; case Pproc: ep = endnm(&sz); (void) snpf(ep, sz, "/%d", p->pfs_pid); ty = "PDIR"; break; case Pfile: ep = endnm(&sz); (void) snpf(ep, sz, "/%d/file", p->pfs_pid); ty = "PFIL"; break; case Pmem: ep = endnm(&sz); (void) snpf(ep, sz, "/%d/mem", p->pfs_pid); ty = "PMEM"; break; case Pregs: ep = endnm(&sz); (void) snpf(ep, sz, "/%d/regs", p->pfs_pid); ty = "PREG"; break; case Pfpregs: ep = endnm(&sz); (void) snpf(ep, sz, "/%d/fpregs", p->pfs_pid); ty = "PFPR"; break; case Pctl: ep = endnm(&sz); (void) snpf(ep, sz, "/%d/ctl", p->pfs_pid); ty = "PCTL"; break; case Pstatus: ep = endnm(&sz); (void) snpf(ep, sz, "/%d/status", p->pfs_pid); ty = "PSTA"; break; case Pnote: ep = endnm(&sz); (void) snpf(ep, sz, "/%d/note", p->pfs_pid); ty = "PNTF"; break; case Pnotepg: ep = endnm(&sz); (void) snpf(ep, sz, "/%d/notepg", p->pfs_pid); ty = "PGID"; break; # if FREEBSDV>=3000 case Pmap: ep = endnm(&sz); (void) snpf(ep, sz, "/%d/map", p->pfs_pid); ty = "PMAP"; break; case Ptype: ep = endnm(&sz); (void) snpf(ep, sz, "/%d/etype", p->pfs_pid); ty = "PETY"; break; # endif /* FREEBSDV>=3000 */ } if (ty) (void) snpf(Lf->type, sizeof(Lf->type), "%s", ty); enter_nm(Namech); # endif /* FREEBSDV<2000 */ } #endif /* defined(HASPROCFS) */ #if defined(HASBLKDEV) /* * If this is a VBLK file and it's missing an inode number, try to * supply one. */ if ((Lf->inp_ty == 0) && (type == VBLK)) find_bl_ino(); #endif /* defined(HASBLKDEV) */ /* * If this is a VCHR file and it's missing an inode number, try to * supply one. */ if ((Lf->inp_ty == 0) && (type == VCHR)) find_ch_ino(); /* * Test for specified file. */ #if defined(HASPROCFS) if (Ntype == N_PROC) { if (Procsrch) { Procfind = 1; Lf->sf |= SELNM; } else { for (pfi = Procfsid; pfi; pfi = pfi->next) { if ((pfi->pid && pfi->pid == p->pfs_pid) # if defined(HASPINODEN) || (Lf->inp_ty == 1 && Lf->inode == pfi->inode) # else /* !defined(HASPINODEN) */ if (pfi->pid == p->pfs_pid) # endif /* defined(HASPINODEN) */ ) { pfi->f = 1; if (!Namech[0]) (void) snpf(Namech, Namechl, "%s", pfi->nm); Lf->sf |= SELNM; break; } } } } else #endif /* defined(HASPROCFS) */ { if (Sfile && is_file_named((char *)NULL, ((type == VCHR) || (type == VBLK)) ? 1 : 0)) Lf->sf |= SELNM; } /* * Enter name characters. */ if (Namech[0]) enter_nm(Namech); } #if FREEBSDV>=2020 /* * process_pipe() - process a file structure whose type is DTYPE_PIPE */ void process_pipe(pa) KA_T pa; /* pipe structure address */ { char dev_ch[32], *ep; struct pipe p; size_t sz; if (!pa || kread(pa, (char *)&p, sizeof(p))) { (void) snpf(Namech, Namechl, "can't read DTYPE_PIPE pipe struct: %s", print_kptr((KA_T)pa, (char *)NULL, 0)); enter_nm(Namech); return; } (void) snpf(Lf->type, sizeof(Lf->type), "PIPE"); (void) snpf(dev_ch, sizeof(dev_ch), "%s", print_kptr(pa, (char *)NULL, 0)); enter_dev_ch(dev_ch); if (Foffset) Lf->off_def = 1; else { Lf->sz = (SZOFFTYPE)p.pipe_buffer.size; Lf->sz_def = 1; } if (p.pipe_peer) (void) snpf(Namech, Namechl, "->%s", print_kptr((KA_T)p.pipe_peer, (char *)NULL, 0)); else Namech[0] = '\0'; if (p.pipe_buffer.cnt) { ep = endnm(&sz); (void) snpf(ep, sz, ", cnt=%d", p.pipe_buffer.cnt); } if (p.pipe_buffer.in) { ep = endnm(&sz); (void) snpf(ep, sz, ", in=%d", p.pipe_buffer.in); } if (p.pipe_buffer.out) { ep = endnm(&sz); (void) snpf(ep, sz, ", out=%d", p.pipe_buffer.out); } /* * Enter name characters. */ if (Namech[0]) enter_nm(Namech); } #endif /* FREEBSDV>=2020 */ lsof-4.86+dfsg.orig/dialects/freebsd/dmnt.c0000444000175000017500000002544311162502237020773 0ustar nicholasnicholas/* * dmnt.c - FreeBSD mount support functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dmnt.c,v 1.16 2009/03/25 19:23:06 abe Exp $"; #endif #include "lsof.h" /* * Local static information */ static struct mounts *Lmi = (struct mounts *)NULL; /* local mount info */ static int Lmist = 0; /* Lmi status */ #undef HAS_MNT_NAMES #if FREEBSDV<2000 static char *mnt_names[] = { "none", "ufs", "nfs", "mfs", "pc", "iso9600", "procfs", "devfs" }; #define HAS_MNT_NAMES 1 #else /* FREEBSDV>=2000 */ # if defined(MOUNT_NONE) static char *mnt_names[] = INITMOUNTNAMES; #define HAS_MNT_NAMES 1 # endif /* defined(MOUNT_NONE)) */ #endif /* FREEBSDV<2000 */ #if FREEBSDV>=5000 && defined(HAS_NO_SI_UDEV) /* * Dev2Udev() -- convert a kernel device number to a user device number */ dev_t Dev2Udev(c) # if defined(HAS_CONF_MINOR) || defined(HAS_CDEV2PRIV) KA_T c; # else /* !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV) */ struct cdev *c; # endif /* defined(HAS_CONF_MINOR) || defined(HAS_CDEV2PRIV) */ { # if !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV) char *cp; char *dn = (char *)NULL; char *ln = (char *)NULL; struct statfs *mb; int n, sr; static u_int s; struct stat sb; static int ss = 0; # endif /* !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV) */ # if defined(HAS_CONF_MINOR) || defined(HAS_CDEV2PRIV) KA_T ca; struct cdev_priv cp; if (!c) return(NODEV); # if defined(HAS_CDEV2PRIV) ca = (KA_T)cdev2priv(c); # else /* !defined(HAS_CDEV2PRIV) */ ca = (KA_T)member2struct(cdev_priv, cdp_c, c); # endif /* defined(HAS_CDEV2PRIV) */ if (kread((KA_T)ca, (char *)&cp, sizeof(cp))) return(NODEV); return((dev_t)cp.cdp_inode); # else /* !defined(HAS_CONF_MINOR) && !defined(HAS_CDEV2PRIV) */ # if defined(HAS_SI_PRIV) /* * If the cdev structure has a private sub-structure, read it. */ struct cdev_priv sp; if (!c->si_priv || kread((KA_T)c->si_priv, (char *)&sp, sizeof(sp))) return(0); # endif /* defined(HAS_SI_PRIV) */ if (ss) { # if defined(HAS_SI_PRIV) return(sp.cdp_inode ^ s); # else /* !defined(HAS_SI_PRIV) */ return(c->si_inode ^ s); # endif /* defined(HAS_SI_PRIV) */ } /* * Determine the random udev seed from stat(2) operations on "/" and * its device. */ if ((n = getmntinfo(&mb, MNT_NOWAIT)) <= 0) { (void) fprintf(stderr, "%s: no mount information\n", Pn); Exit(1); } for (; n; n--, mb++) { # if defined(MOUNT_NONE) if (mb->f_type == MOUNT_NONE || mb->f_type >= MOUNT_MAXTYPE) # else /* !defined(MOUNT_NONE) */ if (!mb->f_type) # endif /* defined(MOUNT_NONE) */ continue; /* * Get the real directory name. Ignore all but the root directory; * safely stat("/"). */ if (dn) (void) free((FREE_P *)dn); if (!(dn = mkstrcpy(mb->f_mntonname, (MALLOC_S *)NULL))) { Dev2Udev_no_space: (void) fprintf(stderr, "%s: no space for mount at ", Pn); safestrprt(mb->f_mntonname, stderr, 0); (void) fprintf(stderr, " ("); safestrprt(mb->f_mntfromname, stderr, 0); (void) fprintf(stderr, ")\n"); Exit(1); } if (!(ln = Readlink(dn))) { if (!Fwarn) { (void) fprintf(stderr, " Output information may be incomplete.\n"); } continue; } if (ln != dn) { (void) free((FREE_P *)dn); dn = ln; } ln = (char *)NULL; if (strcmp(dn, "/")) continue; if (statsafely(dn, &sb)) continue; /* * Get the real device name and safely stat(2) it. */ (void) free((FREE_P *)dn); if (!(dn = mkstrcpy(mb->f_mntfromname, (MALLOC_S *)NULL))) goto Dev2Udev_no_space; ln = Readlink(dn); if ((sr = statsafely(ln, &sb))) { /* * If the device stat(2) failed, see if the device name indicates * an NFS mount, a cd9660 device, or a ZFS mount. If any condition * is true, set the user device number seed to zero. */ if (((cp = strrchr(ln, ':')) && (*(cp + 1) == '/')) || !strcasecmp(mb->f_fstypename, "cd9660") || !strcasecmp(mb->f_fstypename, "zfs") ) { ss = 1; s = (u_int)0; } } if (ln != dn) (void) free((FREE_P *)ln); ln = (char *)NULL; (void) free((FREE_P *)dn); dn = (char *)NULL; if (sr && !ss) continue; if (!ss) { ss = 1; s = (u_int)sb.st_ino ^ (u_int)sb.st_rdev; } break; } /* * Free string copies, as required. */ if (dn) (void) free((FREE_P *)dn); if (ln) (void) free((FREE_P *)ln); /* * If the device seed is known, return its application to the cdev structure's * inode. */ if (ss) { # if defined(HAS_SI_PRIV) return(sp.cdp_inode ^ s); # else /* !defined(HAS_SI_PRIV) */ return(c->si_inode ^ s); # endif /* defined(HAS_SI_PRIV) */ } (void) fprintf(stderr, "%s: can't determine user device random seed.\n", Pn); Exit(1); # endif /* !defined(HAS_CONF_MINOR) */ } #endif /* FREEBSDV>=5000 && defined(HAS_NO_SI_UDEV) */ /* * readmnt() - read mount table */ struct mounts * readmnt() { char *dn = (char *)NULL; char *ln; struct statfs *mb; struct mounts *mtp; int n; struct stat sb; #if defined(HASPROCFS) unsigned char procfs = 0; #endif /* defined(HASPROCFS) */ if (Lmi || Lmist) return(Lmi); /* * Access mount information. */ if ((n = getmntinfo(&mb, MNT_NOWAIT)) <= 0) { (void) fprintf(stderr, "%s: no mount information\n", Pn); return(0); } /* * Read mount information. */ for (; n; n--, mb++) { #if defined(MOUNT_NONE) if (mb->f_type == MOUNT_NONE || mb->f_type >= MOUNT_MAXTYPE) #else /* !defined(MOUNT_NONE) */ if (!mb->f_type) #endif /* defined(MOUNT_NONE) */ continue; /* * Interpolate a possible symbolic directory link. */ if (dn) (void) free((FREE_P *)dn); if (!(dn = mkstrcpy(mb->f_mntonname, (MALLOC_S *)NULL))) { no_space_for_mount: (void) fprintf(stderr, "%s: no space for mount at ", Pn); safestrprt(mb->f_mntonname, stderr, 0); (void) fprintf(stderr, " ("); safestrprt(mb->f_mntfromname, stderr, 0); (void) fprintf(stderr, ")\n"); Exit(1); } if (!(ln = Readlink(dn))) { if (!Fwarn) { (void) fprintf(stderr, " Output information may be incomplete.\n"); } continue; } if (ln != dn) { (void) free((FREE_P *)dn); dn = ln; } if (*dn != '/') continue; /* * Stat() the directory. */ if (statsafely(dn, &sb)) { if (!Fwarn) { (void) fprintf(stderr, "%s: WARNING: can't stat() ", Pn); #if defined(HAS_MNT_NAMES) safestrprt(mnt_names[mb->f_type], stderr, 0); #else /* !defined(HAS_MNT_NAMES) */ safestrprt(mb->f_fstypename, stderr, 0); #endif /* defined(HAS_MNT_NAMES) */ (void) fprintf(stderr, " file system "); safestrprt(mb->f_mntonname, stderr, 1); (void) fprintf(stderr, " Output information may be incomplete.\n"); } (void) bzero((char *)&sb, sizeof(sb)); sb.st_dev = (dev_t)mb->f_fsid.val[0]; sb.st_mode = S_IFDIR | 0777; if (!Fwarn) { (void) fprintf(stderr, " assuming \"dev=%x\" from mount table\n", sb.st_dev); } } /* * Allocate and fill a local mount structure. */ if (!(mtp = (struct mounts *)malloc(sizeof(struct mounts)))) goto no_space_for_mount; mtp->dir = dn; dn = (char *)NULL; #if defined(HASPROCFS) #if defined(MOUNT_NONE) if (mb->f_type == MOUNT_PROCFS) #else /* !defined(MOUNT_NONE) */ if (strcasecmp(mb->f_fstypename, "procfs") == 0) #endif /* defined(MOUNT_NONE) */ { /* * Save information on exactly one procfs file system. */ if (procfs) Mtprocfs = (struct mounts *)NULL; else { procfs = 1; Mtprocfs = mtp; } } #endif /* defined(HASPROCFS) */ mtp->next = Lmi; mtp->dev = sb.st_dev; mtp->rdev = sb.st_rdev; mtp->inode = (INODETYPE)sb.st_ino; mtp->mode = sb.st_mode; /* * Interpolate a possible file system (mounted-on) device name link. */ if (!(dn = mkstrcpy(mb->f_mntfromname, (MALLOC_S *)NULL))) goto no_space_for_mount; mtp->fsname = dn; ln = Readlink(dn); dn = (char *)NULL; /* * Stat() the file system (mounted-on) name and add file system * information to the local mount table entry. */ if (!ln || statsafely(ln, &sb)) sb.st_mode = 0; mtp->fsnmres = ln; mtp->fs_mode = sb.st_mode; Lmi = mtp; } /* * Clean up and return the local mount info table address. */ if (dn) (void) free((FREE_P *)dn); Lmist = 1; return(Lmi); } /* * readvfs() - read vfs structure */ struct l_vfs * readvfs(vm) KA_T vm; /* kernel mount address from vnode */ { struct mount m; struct l_vfs *vp; /* * Search for match on existing entry. */ for (vp = Lvfs; vp; vp = vp->next) { if (vm == vp->addr) return(vp); } /* * Read the (new) mount structure, allocate a local entry, and fill it. */ if (kread((KA_T)vm, (char *)&m, sizeof(m)) != 0) return((struct l_vfs *)NULL); if (!(vp = (struct l_vfs *)malloc(sizeof(struct l_vfs)))) { (void) fprintf(stderr, "%s: PID %d, no space for vfs\n", Pn, Lp->pid); Exit(1); } if (!(vp->dir = mkstrcpy(m.m_stat.f_mntonname, (MALLOC_S *)NULL)) || !(vp->fsname = mkstrcpy(m.m_stat.f_mntfromname, (MALLOC_S *)NULL))) { (void) fprintf(stderr, "%s: PID %d, no space for mount names\n", Pn, Lp->pid); Exit(1); } vp->addr = vm; vp->fsid = m.m_stat.f_fsid; #if defined(MOUNT_NONE) vp->type = m.m_stat.f_type; #else /* !defined(MOUNT_NONE) */ { int len; if ((len = strlen(m.m_stat.f_fstypename))) { if (len > (MFSNAMELEN - 1)) len = MFSNAMELEN - 1; if (!(vp->typnm = mkstrcat(m.m_stat.f_fstypename, len, (char *)NULL, -1, (char *)NULL, -1, (MALLOC_S *)NULL))) { (void) fprintf(stderr, "%s: no space for fs type name: ", Pn); safestrprt(m.m_stat.f_fstypename, stderr, 1); Exit(1); } } else vp->typnm = ""; } #endif /* defined(MOUNT_NONE) */ vp->next = Lvfs; Lvfs = vp; return(vp); } lsof-4.86+dfsg.orig/dialects/freebsd/dnode2.c0000444000175000017500000000630611617613371021210 0ustar nicholasnicholas/* * dnode2.c - FreeBSD ZFS node functions for lsof * * This module must be separate to permit use of the OpenSolaris ZFS header * files. */ /* * Copyright 2008 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 2008 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dnode2.c,v 1.3 2011/08/07 22:51:28 abe Exp $"; #endif #if defined(HAS_ZFS) #define _KERNEL #include #undef _KERNEL #include "dzfs.h" /* * readzfsnode() -- read the ZFS node */ char * readzfsnode(za, zi, vr) KA_T za; /* ZFS node address */ zfs_info_t *zi; /* return ZFS info structure pointer */ int vr; /* vnode's (v_flag & VROOT) */ { struct znode zn; /* ZFS node */ # if defined(HAS_Z_PHYS) znode_phys_t zp; /* ZFS physical node */ # else /* !defined(HAS_Z_PHYS) */ KA_T ka; /* temporary kernel address */ zfsvfs_t zv; /* znode's zfsvfs structure */ # endif /* defined(HAS_Z_PHYS) */ memset((void *)zi, 0, sizeof(zfs_info_t)); if (!za || kread(za, (char *)&zn, sizeof(zn)) ) { if (!za) return("No ZFS node address"); return("Can't read znode"); } /* * Return items contained in the znode. */ zi->ino = (INODETYPE)zn.z_id; zi->ino_def = 1; # if !defined(HAS_V_LOCKF) zi->lockf = (KA_T)zn.z_lockf; # endif /* !defined(HAS_V_LOCKF) */ # if defined(HAS_Z_PHYS) /* * If the physical znode exists in this ZFS implementation, read it. */ if (!zn.z_phys || kread((KA_T)zn.z_phys, (char *)&zp, sizeof(zp)) ) { if (!zn.z_phys) return("No physical znode address"); return("Can't read physical znode"); } /* * Return items contained in the physical znode. */ zi->nl = (long)zp.zp_links; zi->rdev = zp.zp_rdev; zi->sz = (SZOFFTYPE)zp.zp_size; zi->nl_def = zi->rdev_def = zi->sz_def = 1; # else /* !defined(HAS_Z_PHYS) */ /* * If this implementation has no physical znode, return items now contained * in the znode. */ zi->nl = (long)zn.z_links; if (vr && (ka = (KA_T)zn.z_zfsvfs)) { if (!kread(ka, (char *)&zv, sizeof(zv))) { if ((zn.z_id == zv.z_root) && (zv.z_ctldir != NULL) && (zv.z_show_ctldir) ) { zi->nl++; } } } zi->sz = (SZOFFTYPE)zn.z_size; zi->nl_def = zi->sz_def = 1; # endif /* defined(HAS_Z_PHYS) */ return((char *)NULL); } #endif /* defined(HAS_ZFS) */ lsof-4.86+dfsg.orig/dialects/freebsd/machine.h0000444000175000017500000004244311424323217021441 0ustar nicholasnicholas/* * machine.h - FreeBSD definitions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: machine.h,v 1.38 2010/07/29 16:04:28 abe Exp $ */ #if !defined(LSOF_MACHINE_H) #define LSOF_MACHINE_H 1 #include # if defined(HAS_CONF_MINOR) #undef minor # endif /* defined(HAS_CONF_MINOR) */ #if defined(HASCPUMASK_T) /* * In FreeBSD >= 5.2 when the cpumask_t typedef is present, it may be defined * in only if _KERNEL is predefined. However, predefining * _KERNEL before #include'ing causes redefinition errors for * boolean_t and vm_page_t when is #include'd with _KERNEL * predefined. Since lsof must have _KERNEL predefined when is * #include'd, the expedient choice is made to duplicate the cpumask_t typedef * here. * * Note: the Configure script defines HASCPUMASK_T if and * both have cpumask_t references and if the reference in * is valid only when _KERNEL is defined. */ typedef __cpumask_t cpumask_t; #endif /* defined(HASCPUMASK_T) */ #include /* * 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 option. */ /* #define HASAOPT 1 */ /* * HASBLKDEV is defined for those dialects that want block device information * recorded in BDevtp[]. */ # if FREEBSDV<4000 #define HASBLKDEV 1 # endif /* FREEBSDV<4000 */ /* * HASDCACHE is defined for those dialects that support a device cache * file. * * HASENVDC defined the name of an environment variable that contains the * device cache file path. The HASENVDC environment variable is ignored when * the lsof process is setuid(root) or its real UID is 0. * * HASPERSDC defines the format for the last component of a personal device * cache file path. The first will be the home directory of the real UID that * executes lsof. * * HASPERSDCPATH defines the environment variable whose value is the middle * component of the personal device cache file path. The middle component * follows the home directory and precedes the results of applying HASPERSDC. * The HASPERSDCPATH environment variable is ignored when the lsof process is * setuid(root) or its real UID is 0. * * HASSYSDC defines a public device cache file path. When it's defined, it's * used as the path from which to read the device cache. * * Consult the 00DCACHE and 00FAQ files of the lsof distribution for more * information on device cache file path construction. */ #define HASDCACHE 1 #define HASENVDC "LSOFDEVCACHE" #define HASPERSDC "%h/%p.lsof_%L" #define HASPERSDCPATH "LSOFPERSDCPATH" /* #define HASSYSDC "/your/choice/of/path" */ /* * HASCDRNODE is defined for those dialects that have CD-ROM nodes. */ /* #define HASCDRNODE 1 */ /* * HASFIFONODE is defined for those dialects that have FIFO nodes. */ /* #define HASFIFONODE 1 */ /* * HASFSINO is defined for those dialects that have the file system * inode element, fs_ino, in the lfile structure definition in lsof.h. */ /* #define HASFSINO 1 */ /* * HASFSTRUCT is defined if the dialect has a file structure. * * FSV_DEFAULT defines the default set of file structure values to list. * It defaults to zero (0), but may be made up of a combination of the * FSV_* symbols from lsof.h. * * HASNOFSADDR -- has no file structure address * HASNOFSFLAGS -- has no file structure flags * HASNOFSCOUNT -- has no file structure count * HASNOFSNADDR -- has no file structure node address */ #define HASFSTRUCT 1 /* #define FSV_DEFAULT FSV_? | FSV_? | FSV_? */ /* #define HASNOFSADDR 1 has no file structure address */ /* #define HASNOFSFLAGS 1 has no file structure flags */ /* #define HASNOFSCOUNT 1 has no file structure count */ /* #define HASNOFSNADDR 1 has no file structure node address */ /* * HASGNODE is defined for those dialects that have gnodes. */ /* #define HASGNODE 1 */ /* * HASHSNODE is defined for those dialects that have High Sierra nodes. */ /* #define HASHSNODE 1 */ /* * HASINODE is defined for those dialects that have inodes and wish to * use readinode() from node.c. */ #define HASINODE 1 /* * HASINTSIGNAL is defined for those dialects whose signal function returns * an int. */ /* #define HASINTSIGNAL 1 */ /* * HASKERNIDCK is defined for those dialects that support the comparison of * the build to running kernel identity. */ #define HASKERNIDCK 1 /* * HASKOPT is defined for those dialects that support the -k option of * reading the kernel's name list from an optional file. */ #define HASKOPT 1 /* * HASLFILEADD is defined for those dialects that need additional elements * in struct lfile. The HASLFILEADD definition is a macro that defines * them. If any of the additional elements need to be preset in the * alloc_lfile() function of proc.c, the SETLFILEADD macro may be defined * to do that. * * If any additional elements need to be cleared in alloc_lfile() or in the * free_proc() function of proc.c, the CLRLFILEADD macro may be defined to * do that. Note that CLRLFILEADD takes one argument, the pointer to the * lfile struct. The CLRLFILEADD macro is expected to expand to statements * that are complete -- i.e., have terminating semi-colons -- so the macro is * called without a terminating semicolon by proc.c. * * The HASXOPT definition may be used to select the conditions under which * private lfile elements are used. */ /* #define HASLFILEADD int ... */ /* #define CLRLFILEADD(lf) (lf)->... = (type)NULL; */ /* #define SETLFILEADD Lf->... */ /* * HASMNTSTAT indicates the dialect supports the mount stat(2) result option * in its l_vfs and mounts structures. */ /* #define HASMNTSTAT 1 */ /* * HASMNTSUP is defined for those dialects that support the mount supplement * option. */ /* #define HASMNTSUP 1 */ /* * HASMOPT is defined for those dialects that support the reading of * kernel memory from an alternate file. */ #define HASMOPT 1 /* * HASNCACHE is defined for those dialects that have a kernel name cache * that lsof can search. A value of 1 directs printname() to prefix the * cache value with the file system directory name; 2, avoid the prefix. * * NCACHELDPFX is a set of C commands to execute before calling ncache_load(). * * NCACHELDSFX is a set of C commands to execute after calling ncache_load(). */ #define HASNCACHE 1 /* #define NCACHELDPFX ??? */ /* #define NCACHELDSFX ??? */ /* * HASNLIST is defined for those dialects that use nlist() to acccess * kernel symbols. */ #define HASNLIST 1 /* * HASPIPEFN is defined for those dialects that have a special function to * process DTYPE_PIPE file structure entries. Its value is the name of the * function. * * NOTE: don't forget to define a prototype for this function in dproto.h. */ # if FREEBSDV>=2020 #define HASPIPEFN process_pipe # endif /* FREEBSDV>=2020 */ /* * HASPIPENODE is defined for those dialects that have pipe nodes. */ /* #define HASPIPENODE 1 */ /* * HASPMAPENABLED is defined when the reporting of portmapper registration * info is enabled by default. */ /* #define HASPMAPENABLED 1 */ /* * HASPPID is defined for those dialects that support identification of * the parent process IDentifier (PPID) of a process. */ # if FREEBSDV>=2000 #define HASPPID 1 # endif /* FREEBSDV>=2000 */ /* * HASPRINTDEV, HASPRINTINO, HASPRINTNM, HASPRINTOFF, and HASPRINTSZ * define private dialect-specific functions for printing DEVice numbers, * INOde numbers, NaMes, file OFFsets, and file SiZes. The functions are * called from print_file(). */ /* #define HASPRINTDEV print_dev? */ /* #define HASPRINTINO print_ino? */ /* #define HASPRINTNM print_nm? */ /* #define HASPRINTOFF print_off? */ /* #define HASPRINTSZ print_sz? */ /* * HASPRIVFILETYPE and PRIVFILETYPE are defined for dialects that have a * file structure type that isn't defined by a DTYPE_* symbol. They are * used in lib/prfp.c to select the type's processing. * * PRIVFILETYPE is the definition of the f_type value in the file struct. * * HASPRIVFILETYPE is the name of the processing function. */ /* #define HASPRIVFILETYPE process_shmf? */ /* #define PRIVFILETYPE ?? */ /* * HASPRIVNMCACHE is defined for dialects that have a private method for * printing cached NAME column values for some files. HASPRIVNAMECACHE * is defined to be the name of the function. * * The function takes one argument, a struct lfile pointer to the file, and * returns non-zero if it prints a name to stdout. */ /* #define HASPRIVNMCACHE */ /* * HASPRIVPRIPP is defined for dialects that have a private function for * printing IP protocol names. When HASPRIVPRIPP isn't defined, the * IP protocol name printing function defaults to printiprto(). */ /* #define HASPRIVPRIPP 1 */ /* * HASPROCFS is defined for those dialects that have a proc file system -- * usually /proc and usually in SYSV4 derivatives. For FreeBSD 2.0 and * above the Configure script defines HASPROCFS when it can find * /usr/src/sys/miscfs/procfs/procfs.h; below 2.0, Configure always defines * HASPROCFS. * * HASFSTYPE is defined as 1 for those systems that have a file system type * string, st_fstype, in the stat() buffer; 2, for those systems that have a * file system type integer in the stat() buffer, named MOUNTS_STAT_FSTYPE; * 0, for systems whose stat(2) structure has no file system type member. The * additional symbols MOUNTS_FSTYPE, RMNT_FSTYPE, and RMNT_STAT_FSTYPE may be * defined in dlsof.h to direct how the readmnt() function in lib/rmnt.c * preserves these stat(2) and getmntent(3) buffer values in the local mounts * structure. * * The defined value is the string that names the file system type. * * The HASPROCFS definition usually must be accompanied by the HASFSTYPE * definition and the providing of an fstype element in the local mounts * structure (defined in dlsof.h). * * The HASPROCFS definition may be accompanied by the HASPINODEN definition. * HASPINODEN specifies that searching for files in HASPROCFS is to be done * by inode number. */ # if defined(HASPROCFS) #undef HASPROCFS #define HASPROCFS "proc" # endif /* defined(HASPROCFS) */ /* #define HASPROCFS "proc?" */ /* #define HASFSTYPE 1 */ # if FREEBSDV>=2000 #define HASPINODEN 1 # endif /* FREEBSDV>=2000 */ /* * HASRNODE is defined for those dialects that have rnodes. */ /* #define HASRNODE 1 */ /* * Define HASSECURITY to restrict the listing of all open files to the * root user. When HASSECURITY is defined, the non-root user may list * only files whose processes have the same user ID as the real user ID * (the one that its user logged on with) of the lsof process. */ /* #define HASSECURITY 1 */ /* * If HASSECURITY is defined, define HASNOSOCKSECURITY to allow users * restricted by HASSECURITY to list any open socket files, provide their * listing is selected by the "-i" option. */ /* #define HASNOSOCKSECURITY 1 */ /* * HASSETLOCALE is defined for those dialects that have and * setlocale(). * * If the dialect also has wide character support for language locales, * HASWIDECHAR activates lsof's wide character support and WIDECHARINCL * defines the header file (if any) that must be #include'd to use the * mblen() and mbtowc() functions. */ #define HASSETLOCALE 1 # if FREEBSDV>=5200 #define HASWIDECHAR 1 # endif /* FREEBSDV>=5020 */ /* #define WIDECHARINCL */ /* * HASSNODE is defined for those dialects that have snodes. */ /* #define HASSNODE 1 */ /* * HASTASKS is defined for those dialects that have task reporting support. */ /* #define HASTASKS 1 */ /* * HASSOOPT, HASSOSTATE and HASTCPOPT define the availability of information * on socket options (SO_* symbols), socket states (SS_* symbols) and TCP * options. */ #define HASSOOPT 1 /* has socket option information */ #define HASSOSTATE 1 /* has socket state information */ #define HASTCPOPT 1 /* has TCP options or flags */ /* * Define HASSPECDEVD to be the name of a function that handles the results * of a successful stat(2) of a file name argument. * * For example, HASSPECDEVD() for Darwin makes sure that st_dev is set to * what stat("/dev") returns -- i.e., what's in DevDev. * * The function takes two arguments: * * 1: pointer to the full path name of file * 2: pointer to the stat(2) result * * The function returns void. */ /* #define HASSPECDEVD process_dev_stat */ /* * HASSTREAMS is defined for those dialects that support streams. */ /* #define HASSTREAMS 1 */ /* * HASTCPTPIQ is defined for dialects where it is possible to report the * TCP/TPI Recv-Q and Send-Q values produced by netstat. */ #define HASTCPTPIQ 1 /* * HASTCPTPIW is defined for dialects where it is possible to report the * TCP/TPI send and receive window sizes produced by netstat. */ /* #define HASTCPTPIW 1 */ /* * HASTCPUDPSTATE is defined for dialects that have TCP and UDP state * support -- i.e., for the "-stcp|udp:state" option and its associated * speed improvements. */ #define HASTCPUDPSTATE 1 /* * HASTMPNODE is defined for those dialects that have tmpnodes. */ /* #define HASTMPNODE 1 */ /* * HASVNODE is defined for those dialects that use the Sun virtual file system * node, the vnode. BSD derivatives usually do; System V derivatives prior * to R4 usually don't. * doesn't. */ #define HASVNODE 1 /* * HASXOPT is defined for those dialects that have an X option. It * defines the text for the usage display. HASXOPT_VALUE defines the * option's default binary value -- 0 or 1. */ /* #define HASXOPT "help text for X option" */ /* #define HASXOPT_VALUE 1 */ /* * INODETYPE and INODEPSPEC define the internal node number type and its * printf specification modifier. These need not be defined and lsof.h * can be allowed to define defaults. * * These are defined here, because they must be used in dlsof.h. */ #define INODETYPE unsigned long long /* inode number internal storage type */ #define INODEPSPEC "ll" /* INODETYPE printf specification * modifier */ /* * UID_ARG defines the size of a User ID number when it is passed * as a function argument. */ #define UID_ARG int /* * Each USE_LIB_ is defined for dialects that use the * in the lsof library. * * Note: other definitions and operations may be required to condition the * library function source code. They may be found in the dialect dlsof.h * header files. */ #define USE_LIB_CKKV 1 /* ckkv.c */ /* #define USE_LIB_COMPLETEVFS 1 cvfs.c */ #define USE_LIB_FIND_CH_INO 1 /* fino.c */ #define USE_LIB_IS_FILE_NAMED 1 /* isfn.c */ #define USE_LIB_LKUPDEV 1 /* lkud.c */ #define USE_LIB_PRINTDEVNAME 1 /* pdvn.c */ #define USE_LIB_PROCESS_FILE 1 /* prfp.c */ #define USE_LIB_PRINT_TCPTPI 1 /* ptti.c */ #define USE_LIB_READDEV 1 /* rdev.c */ /* #define USE_LIB_READMNT 1 rmnt.c */ /* #define USE_LIB_REGEX 1 regex.c */ # if FREEBSDV<2010 #define USE_LIB_RNAM 1 /* rnam.c */ # else /* FREEBSDV>=2010 */ #define USE_LIB_RNMH 1 /* rnmh.c */ # endif /* FREEBSDV<2010 */ /* #define USE_LIB_RNCH 1 rnch.c */ /* #define USE_LIB_SNPF 1 snpf.c */ #define snpf snprintf /* use the system's snprintf() */ /* * WARNDEVACCESS is defined for those dialects that should issue a warning * when lsof can't access /dev (or /device) or one of its sub-directories. * The warning can be inhibited by the lsof caller with the -w option. */ #define WARNDEVACCESS 1 /* * WARNINGSTATE is defined for those dialects that want to suppress all lsof * warning messages. */ /* #define WARNINGSTATE 1 warnings are enabled by default */ /* * WILLDROPGID is defined for those dialects whose lsof executable runs * setgid(not_real_GID) and whose setgid power can be relinquished after * the dialect's initialize() function has been executed. */ #define WILLDROPGID 1 /* * zeromem is a macro that uses bzero or memset. */ #define zeromem(a, l) memset(a, 0, l) #endif /* !defined(LSOF_MACHINE_H) */ lsof-4.86+dfsg.orig/dialects/freebsd/Makefile0000444000175000017500000000775711162502235021333 0ustar nicholasnicholas # FreeBSD Makefile remainder # # $Id: Makefile,v 1.12 2009/03/25 19:23:06 abe Exp $ PROG= lsof BIN= ${DESTDIR} DOC= ${DESTDIR} I=/usr/include S=/usr/include/sys L=/usr/include/local P= CDEF= CDEFS= ${CDEF} ${CFGF} INCL= ${DINC} CFLAGS= ${CDEFS} ${INCL} ${DEBUG} GRP= HDR= lsof.h lsof_fields.h dlsof.h machine.h proto.h dproto.h dzfs.h SRC= dmnt.c dnode.c dnode1.c dnode2.c dproc.c dsock.c dstore.c \ arg.c main.c misc.c node.c print.c proc.c store.c usage.c \ util.c OBJ= dmnt.o dnode.o dnode1.o dnode2.o dproc.o dsock.o dstore.o \ arg.o main.o misc.o node.o print.o proc.o store.o usage.o \ util.o MAN= lsof.8 OTHER= SHELL= /bin/sh SOURCE= Makefile ${OTHER} ${MAN} ${HDR} ${SRC} all: ${PROG} ${PROG}: ${LIB} ${P} ${OBJ} ${CC} -o $@ ${CFLAGS} ${OBJ} ${CFGL} clean: FRC rm -f Makefile.bak ${PROG} a.out core errs lint.out tags *.o version.h rm -f machine.h.old new_machine.h (cd lib; ${MAKE} -f Makefile.skel clean) install: all FRC @echo '' @echo 'Please write your own install rule. Lsof should be installed' @echo 'setgid to the group that can can read /dev/kmem. Normally' @echo 'that is the kmem group. Your install rule actions might look' @echo 'something like this:' @echo '' @echo ' install -cs -m 2755 -g $${GRP} $${PROG} $${BIN}/$${PROG}' @echo ' install -c -m 444 $${MAN} $${DOC}/$${MAN}' @echo '' @echo 'You will have to complete the skeletons for the BIN, DOC, and' @echo 'GRP strings given at the beginning of this Makefile, e.g.,' @echo '' @echo ' BIN= $${DESTDIR}/usr/local/etc' @echo ' DOC= $${DESTDIR}/usr/local/man/man8' @echo ' GRP= kmem' @echo '' ${LIB}: FRC (cd lib; ${MAKE} DEBUG="${DEBUG}" CFGF="${CFGF}") version.h: FRC @echo Constructing version.h @rm -f version.h @echo '#define LSOF_BLDCMT "${LSOF_BLDCMT}"' > version.h; @echo '#define LSOF_CC "${CC}"' >> version.h @echo '#define LSOF_CCV "${CCV}"' >> version.h @echo '#define LSOF_CCDATE "'`date`'"' >> version.h @echo '#define LSOF_CCFLAGS "'`echo ${CFLAGS} | sed 's/\\\\(/\\(/g' | sed 's/\\\\)/\\)/g' | sed 's/"/\\\\"/g'`'"' >> version.h @if [ "X${LSOF_HOST}" = "X" ]; then \ echo '#define LSOF_HOST "'`uname -n`'"' >> version.h; \ else \ if [ "${LSOF_HOST}" = "none" ]; then \ echo '#define LSOF_HOST ""' >> version.h; \ else \ echo '#define LSOF_HOST "${LSOF_HOST}"' >> version.h; \ fi \ fi @echo '#define LSOF_LDFLAGS "${CFGL}"' >> version.h @if [ "X${LSOF_LOGNAME}" = "X" ]; then \ echo '#define LSOF_LOGNAME "${LOGNAME}"' >> version.h; \ else \ if [ "${LSOF_LOGNAME}" = "none" ]; then \ echo '#define LSOF_LOGNAME ""' >> version.h; \ else \ echo '#define LSOF_LOGNAME "${LSOF_LOGNAME}"' >> version.h; \ fi; \ fi @if [ "X${LSOF_SYSINFO}" = "X" ]; then \ echo '#define LSOF_SYSINFO "'`uname -a`'"' >> version.h; \ else \ if [ "${LSOF_SYSINFO}" = "none" ]; then \ echo '#define LSOF_SYSINFO ""' >> version.h; \ else \ echo '#define LSOF_SYSINFO "${LSOF_SYSINFO}"' >> version.h; \ fi \ fi @if [ "X${LSOF_USER}" = "X" ]; then \ echo '#define LSOF_USER "${USER}"' >> version.h; \ else \ if [ "${LSOF_USER}" = "none" ]; then \ echo '#define LSOF_USER ""' >> version.h; \ else \ echo '#define LSOF_USER "${LSOF_USER}"' >> version.h; \ fi \ fi @sed '/VN/s/.ds VN \(.*\)/#define LSOF_VERSION "\1"/' < version >> version.h FRC: # DO NOT DELETE THIS LINE - make depend DEPENDS ON IT dmnt.o: ${HDR} dmnt.c dnode.o: ${HDR} dnode.c dnode1.o: ${HDR} dnode1.c dnode2.o: dzfs.h dnode2.c @if [ -f ./Makefile.zfs ]; then \ ${MAKE} -f Makefile.zfs dnode2.o; \ else \ echo "${CC} ${CFLAGS} -c dnode2.c"; \ ${CC} ${CFLAGS} -c dnode2.c; \ fi; dproc.o: ${HDR} dproc.c dsock.o: ${HDR} dsock.c dstore.o: ${HDR} dstore.c arg.o: ${HDR} arg.c main.o: ${HDR} main.c misc.o: ${HDR} misc.c node.o: ${HDR} node.c print.o: ${HDR} print.c proc.o: ${HDR} proc.c store.o: ${HDR} store.c usage.o: ${HDR} version.h usage.c util.o: ${HDR} util.c # *** Do not add anything here - It will go away. *** lsof-4.86+dfsg.orig/dialects/freebsd/Makefile.zfs0000444000175000017500000000110211617613366022123 0ustar nicholasnicholas # Makefile.zfs -- FreeBSD Makefile remainder for ZFS modules # # $Id: Makefile.zfs,v 1.3 2011/08/07 22:51:28 abe Exp $ CFLAGS+=-D_SOLARIS_C_SOURCE CFLAGS+=${DEBUG} CFLAGS+=-I${OPENSOLARIS}/compat/opensolaris CFLAGS+=-I${OPENSOLARIS}/contrib/opensolaris/uts/common/fs/zfs CFLAGS+=-I${OPENSOLARIS}/contrib/opensolaris/uts/common/zmod CFLAGS+=-I${OPENSOLARIS}/contrib/opensolaris/uts/common CFLAGS+=-I${OPENSOLARIS}/contrib/opensolaris/common/zfs CFLAGS+=-I${OPENSOLARIS}/contrib/opensolaris/common CFLAGS+=-I${.CURDIR}/usr/src/include CFLAGS+=-I`pwd` dnode2.o: dzfs.h dnode2.c lsof-4.86+dfsg.orig/dialects/darwin/0000755000175000017500000000000011741064216017534 5ustar nicholasnicholaslsof-4.86+dfsg.orig/dialects/darwin/get-hdr-loc.sh0000555000175000017500000000556510245700256022210 0ustar nicholasnicholas#!/bin/sh # # get-hdr-loc.sh -- get Darwin XNU kernel header file location # # Interactively requests the specification of the path to the host's Darwin # XNU kernel header files. Checks that path and returns it to the caller. # # Usage: file1 file2 ... fileN # # Where: file1 first header file needed # file2 second header file needed # ... # fileN last header file needed # # Exit: # # Exit code: 0 if path found; path returned on STDOUT # # 1 if path not found: error message returned # on STDOUT # #set -x # for DEBUGging # Check argument count. There must be at least one argument. if test $# -lt 1 # { then echo "insufficient arguments: $#" exit 1 fi # } lst=$* # Request the path to the Darwin XNU kernel header files. trap 'stty echo; echo interrupted; exit 1' 1 2 3 15 FOREVER=1 while test $FOREVER -ge 1 # { do if test $FOREVER -eq 1 # { then echo "---------------------------------------------------------------" 1>&2 echo "" 1>&2 echo "Lsof cannot find some Darwin XNU kernel header files it needs." 1>&2 echo "They should have already been downloaded from:" 1>&2 echo "" 1>&2 echo " http://www.opensource.apple.com/darwinsource/index.html" 1>&2 echo "" 1>&2 echo "and then installed. (See 00FAQ for download and installation" 1>&2 echo "instructions.)" 1>&2 echo "" 1>&2 echo "Please specify the path to the place where they were installed." 1>&2 echo "" 1>&2 echo "---------------------------------------------------------------" 1>&2 fi # } END=0 while test $END = 0 # { do echo "" 1>&2 echo -n "What is the path? " 1>&2 read HP EXCESS HP=`echo echo $HP | /bin/csh -fs` if test $? -eq 0 # { then if test "X$HP" = "X" # { then echo "" 1>&2 echo "+================================+" 1>&2 echo "| Please enter a non-empty path. |" 1>&2 echo "+================================+" 1>&2 echo "" 1>&2 else END=1 fi # } else echo "" 1>&2 echo "+============================+" 1>&2 echo "| Please enter a legal path. |" 1>&2 echo "+============================+" 1>&2 echo "" 1>&2 fi # } done # } # See if the header files are available in the specified path. MH="" for i in $lst # { do if test ! -f ${HP}/bsd/$i -a ! -f ${HP}/osfmk/$i # { then if test "X$MH" = "X" # { then MH=$i else MH="$MH $i" fi # } fi # } done # } if test "X$MH" = "X" # { then # All header files are available, so return the path and exit cleanly. echo $HP exit 0 else echo "" 1>&2 echo "ERROR: not all header files are in:" 1>&2 echo "" 1>&2 echo " ${HP}" 1>&2 echo "" 1>&2 echo " These are missing:" 1>&2 echo "" 1>&2 echo " $MH" 1>&2 FOREVER=2 fi # } done # } echo "unknown error" exit 1 lsof-4.86+dfsg.orig/dialects/darwin/libproc/0000755000175000017500000000000011741064216021166 5ustar nicholasnicholaslsof-4.86+dfsg.orig/dialects/darwin/libproc/dstore.c0000444000175000017500000000460511077400031022624 0ustar nicholasnicholas/* * dstore.c -- Darwin global storage for libproc-based lsof */ /* * Portions Copyright 2005 Apple Computer, Inc. All rights reserved. * * Copyright 2005 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Allan Nathanson, Apple Computer, Inc., and Victor A. * Abell, Purdue University. * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors, nor Apple Computer, Inc. nor Purdue University * are responsible for any consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either * by explicit claim or by omission. Credit to the authors, Apple * Computer, Inc. and Purdue University must appear in documentation * and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 2005 Apple Computer, Inc. and Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dstore.c,v 1.4 2008/10/21 16:15:16 abe Exp $"; #endif #include "lsof.h" #if defined(HASFSTRUCT) /* * Pff_tab[] - table for printing file flags */ struct pff_tab Pff_tab[] = { { (long)FREAD, FF_READ }, { (long)FWRITE, FF_WRITE }, { (long)FNONBLOCK, FF_NBLOCK }, { (long)FNDELAY, FF_NDELAY }, { (long)FAPPEND, FF_APPEND }, { (long)FASYNC, FF_ASYNC }, { (long)FFSYNC, FF_FSYNC }, # if defined(FHASLOCK) { (long)FHASLOCK, FF_HASLOCK }, # endif /* defined(FHASLOCK) */ { (long)O_NOCTTY, FF_NOCTTY }, { (long)O_EVTONLY, FF_EVTONLY }, { (long)0, NULL } }; /* * Pof_tab[] - table for print process open file flags */ struct pff_tab Pof_tab[] = { # if defined(UF_CLOSING) { (long)UF_CLOSING, POF_CLOSING }, # endif /* defined(UF_CLOSING) */ # if defined(UF_EXCLOSE) { (long)UF_EXCLOSE, POF_CLOEXEC }, # endif /* defined(UF_EXCLOSE) */ # if defined(UF_RESERVED) { (long)UF_RESERVED, POF_RESERVED }, # endif /* defined(UF_RESERVED) */ { (long)0, NULL } }; #endif /* defined(HASFSTRUCT) */ lsof-4.86+dfsg.orig/dialects/darwin/libproc/ddev.c0000444000175000017500000003074010412071756022257 0ustar nicholasnicholas/* * ddev.c -- Darwin device support functions for libproc-based lsof */ /* * Portions Copyright 2005 Apple Computer, Inc. All rights reserved. * * Copyright 2005 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Allan Nathanson, Apple Computer, Inc., and Victor A. * Abell, Purdue University. * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors, nor Apple Computer, Inc. nor Purdue University * are responsible for any consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either * by explicit claim or by omission. Credit to the authors, Apple * Computer, Inc. and Purdue University must appear in documentation * and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 2005 Apple Computer, Inc. and Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: ddev.c,v 1.2 2006/03/27 23:23:13 abe Exp $"; #endif #include "lsof.h" /* * Local definitions */ #if defined(DVCH_DEVPATH) #define DDEV_DEVPATH DVCH_DEVPATH #else /* !defined(DVCH_DEVPATH) */ #define DDEV_DEVPATH "/dev" #endif /* defined(DVCH_DEVPATH) */ #define LIKE_BLK_SPEC "like block special" #define LIKE_CHR_SPEC "like character special" #if defined(USE_STAT) #define STATFN stat #else /* !defined(USE_STAT) */ #define STATFN lstat #endif /* defined(USE_STAT) */ /* * Local static variables. */ static dev_t *ADev = (dev_t *) NULL; /* device numbers besides DevDev found * inside DDEV_DEVPATH */ static int ADevA = 0; /* entries allocated to ADev[] */ static int ADevU = 0; /* entries used in ADev[] */ /* * Local function prototypes */ _PROTOTYPE(static int rmdupdev,(struct l_dev ***dp, int n, char *nm)); _PROTOTYPE(static void saveADev,(struct stat *s)); #if defined(HASSPECDEVD) /* * HASSPECDEVD() -- process stat(2) result to see if the device number is * inside DDEV_DEVPATH "/" * * exit: s->st_dev changed to DevDev, as required */ void HASSPECDEVD(p, s) char *p; /* file path */ struct stat *s; /* stat(2) result for file */ { int i; switch (s->st_mode & S_IFMT) { case S_IFCHR: case S_IFBLK: if (s->st_dev == DevDev) return; (void) readdev(0); if (!ADev) return; for (i = 0; i < ADevU; i++) { if (s->st_dev == ADev[i]) { s->st_dev = DevDev; return; } } } } #endif /* defined(HASSPECDEVD) */ /* * printdevname() -- print character device name */ int printdevname(dev, rdev, f, nty) dev_t *dev; /* device */ dev_t *rdev; /* raw device */ int f; /* 1 = follow with '\n' */ int nty; /* node type: N_BLK or N_chr */ { char *cp, *ttl; struct l_dev *dp; int i, len; /* * See if the device node resides in DDEV_DEVPATH. If it does, return zero * to indicate the vnode path is to be used for the NAME column. */ if (*dev == DevDev) return(0); readdev(0); for (i = 0; i < ADevU; i++) { if (*dev == ADev[i]) return(0); } /* * This device is not in DDEV_DEVPATH. * * See if it has a DDEV_DEVPATH analogue by searching the device table for a * match without inode number and dev. */ #if defined(HASBLKDEV) if (nty == N_BLK) dp = lkupbdev(&DevDev, rdev, 0, 1); else #endif /* defined(HASBLKDEV) */ dp = lkupdev(&DevDev, rdev, 0, 1); if (dp) { /* * A match was found. Record it as a name column addition. */ ttl = (nty == N_BLK) ? LIKE_BLK_SPEC : LIKE_CHR_SPEC; len = (int)(1 + strlen(ttl) + 1 + strlen(dp->name) + 1); if (!(cp = (char *)malloc((MALLOC_S)(len + 1)))) { (void) fprintf(stderr, "%s: no nma space for: (%s %s)\n", Pn, ttl, dp->name); Exit(1); } (void) snpf(cp, len + 1, "(%s %s)", ttl, dp->name); (void) add_nma(cp, len); (void) free((MALLOC_P *)cp); } /* * Return zero to indicate the vnode path is to be used for the NAME column. */ return(0); } /* * readdev() -- read device names, modes and types */ void readdev(skip) int skip; /* skip device cache read if 1 -- * ignored since device cache not * used */ { DIR *dfp; int dnamlen; struct dirent *dp; char *fp = (char *)NULL; char *path = (char *)NULL; int i = 0; int j = 0; MALLOC_S pl, sz; struct stat sb; /* * Read device names but once. */ if (Sdev) return; /* * Prepare to scan DDEV_DEVPATH. */ Dstkn = Dstkx = 0; Dstk = (char **)NULL; (void) stkdir(DDEV_DEVPATH); /* * Unstack the next directory. */ while (--Dstkx >= 0) { if (!(dfp = OpenDir(Dstk[Dstkx]))) { # if defined(WARNDEVACCESS) if (!Fwarn) { (void) fprintf(stderr, "%s: WARNING: can't open: ", Pn); safestrprt(Dstk[Dstkx], stderr, 1); } # endif /* defined(WARNDEVACCESS) */ (void) free((FREE_P *)Dstk[Dstkx]); Dstk[Dstkx] = (char *)NULL; continue; } if (path) { (void) free((FREE_P *)path); path = (char *)NULL; } if (!(path = mkstrcat(Dstk[Dstkx], -1, "/", 1, (char *)NULL, -1, &pl))) { (void) fprintf(stderr, "%s: no space for: ", Pn); safestrprt(Dstk[Dstkx], stderr, 1); Exit(1); } (void) free((FREE_P *)Dstk[Dstkx]); Dstk[Dstkx] = (char *)NULL; /* * Scan the directory. */ for (dp = ReadDir(dfp); dp; dp = ReadDir(dfp)) { if (dp->d_ino == 0 || dp->d_name[0] == '.') continue; /* * Form the full path name and get its status. */ dnamlen = (int)dp->d_namlen; if (fp) { (void) free((FREE_P *)fp); fp = (char *)NULL; } if (!(fp = mkstrcat(path, pl, dp->d_name, dnamlen, (char *)NULL, -1, (MALLOC_S *)NULL))) { (void) fprintf(stderr, "%s: no space for: ", Pn); safestrprt(path, stderr, 0); safestrprtn(dp->d_name, dnamlen, stderr, 1); Exit(1); } if (STATFN(fp, &sb) != 0) { if (errno == ENOENT) /* a sym link to nowhere? */ continue; # if defined(WARNDEVACCESS) if (!Fwarn) { int errno_save = errno; (void) fprintf(stderr, "%s: can't stat ", Pn); safestrprt(fp, stderr, 0); (void) fprintf(stderr, ": %s\n", strerror(errno_save)); } # endif /* defined(WARNDEVACCESS) */ continue; } /* * If it's a subdirectory, stack its name for later * processing. */ if ((sb.st_mode & S_IFMT) == S_IFDIR) { /* * Skip /dev/fd. */ if (strcmp(fp, "/dev/fd")) (void) stkdir(fp); continue; } if ((sb.st_mode & S_IFMT) == S_IFLNK) { /* * Ignore symbolic links. */ continue; } if ((sb.st_mode & S_IFMT) == S_IFCHR) { /* * Save character device information in Devtp[]. */ if (i >= Ndev) { Ndev += DEVINCR; if (!Devtp) Devtp = (struct l_dev *)malloc( (MALLOC_S)(sizeof(struct l_dev)*Ndev)); else Devtp = (struct l_dev *)realloc((MALLOC_P *)Devtp, (MALLOC_S)(sizeof(struct l_dev)*Ndev)); if (!Devtp) { (void) fprintf(stderr, "%s: no space for character device\n", Pn); Exit(1); } } Devtp[i].rdev = sb.st_rdev; Devtp[i].inode = (INODETYPE)sb.st_ino; if (!(Devtp[i].name = mkstrcpy(fp, (MALLOC_S *)NULL))) { (void) fprintf(stderr, "%s: no space for device name: ", Pn); safestrprt(fp, stderr, 1); Exit(1); } Devtp[i].v = 0; i++; } # if defined(HASBLKDEV) if ((sb.st_mode & S_IFMT) == S_IFBLK) { /* * Save block device information in BDevtp[]. */ if (j >= BNdev) { BNdev += DEVINCR; if (!BDevtp) BDevtp = (struct l_dev *)malloc( (MALLOC_S)(sizeof(struct l_dev)*BNdev)); else BDevtp = (struct l_dev *)realloc((MALLOC_P *)BDevtp, (MALLOC_S)(sizeof(struct l_dev)*BNdev)); if (!BDevtp) { (void) fprintf(stderr, "%s: no space for block device\n", Pn); Exit(1); } } BDevtp[j].name = fp; fp = (char *)NULL; BDevtp[j].inode = (INODETYPE)sb.st_ino; BDevtp[j].rdev = sb.st_rdev; BDevtp[j].v = 0; j++; } # endif /* defined(HASBLKDEV) */ /* * Save a possible new st_dev number within DDEV_DEVPATH. */ if (sb.st_dev != DevDev) (void) saveADev(&sb); } (void) CloseDir(dfp); } /* * Free any unneeded space that was allocated. */ if (ADev && (ADevU < ADevA)) { /* * Reduce space allocated to additional DDEV_DEVPATH device numbers. */ if (!ADevU) { /* * If no space was used, free the entire allocation. */ (void) free((FREE_P *)ADev); ADev = (dev_t *)NULL; ADevA = 0; } else { /* * Reduce the allocation to what was used. */ sz = (MALLOC_S)(ADevU * sizeof(dev_t)); if (!(ADev = (dev_t *)realloc((MALLOC_P *)ADev, sz))) { (void) fprintf(stderr, "%s: can't reduce ADev[]\n", Pn); Exit(1); } } } if (!Dstk) { (void) free((FREE_P *)Dstk); Dstk = (char **)NULL; } if (fp) (void) free((FREE_P *)fp); if (path) (void) free((FREE_P *)path); # if defined(HASBLKDEV) /* * Reduce the BDevtp[] (optional) and Devtp[] tables to their minimum * sizes; allocate and build sort pointer lists; and sort the tables by * device number. */ if (BNdev) { if (BNdev > j) { BNdev = j; BDevtp = (struct l_dev *)realloc((MALLOC_P *)BDevtp, (MALLOC_S)(sizeof(struct l_dev) * BNdev)); } if (!(BSdev = (struct l_dev **)malloc( (MALLOC_S)(sizeof(struct l_dev *) * BNdev)))) { (void) fprintf(stderr, "%s: no space for block device sort pointers\n", Pn); Exit(1); } for (j = 0; j < BNdev; j++) { BSdev[j] = &BDevtp[j]; } (void) qsort((QSORT_P *)BSdev, (size_t)BNdev, (size_t)sizeof(struct l_dev *), compdev); BNdev = rmdupdev(&BSdev, BNdev, "block"); } # if !defined(NOWARNBLKDEV) else { if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: no block devices found\n", Pn); } # endif /* !defined(NOWARNBLKDEV) */ # endif /* defined(HASBLKDEV) */ if (Ndev) { if (Ndev > i) { Ndev = i; Devtp = (struct l_dev *)realloc((MALLOC_P *)Devtp, (MALLOC_S)(sizeof(struct l_dev) * Ndev)); } if (!(Sdev = (struct l_dev **)malloc( (MALLOC_S)(sizeof(struct l_dev *) * Ndev)))) { (void) fprintf(stderr, "%s: no space for character device sort pointers\n", Pn); Exit(1); } for (i = 0; i < Ndev; i++) { Sdev[i] = &Devtp[i]; } (void) qsort((QSORT_P *)Sdev, (size_t)Ndev, (size_t)sizeof(struct l_dev *), compdev); Ndev = rmdupdev(&Sdev, Ndev, "char"); } else { (void) fprintf(stderr, "%s: no character devices found\n", Pn); Exit(1); } } /* * rmdupdev() - remove duplicate (major/minor/inode) devices */ static int rmdupdev(dp, n, nm) struct l_dev ***dp; /* device table pointers address */ int n; /* number of pointers */ char *nm; /* device table name for error message */ { int i, j, k; struct l_dev **p; for (i = j = 0, p = *dp; i < n ;) { for (k = i + 1; k < n; k++) { if (p[i]->rdev != p[k]->rdev || p[i]->inode != p[k]->inode) break; } if (i != j) p[j] = p[i]; j++; i = k; } if (n == j) return(n); if (!(*dp = (struct l_dev **)realloc((MALLOC_P *)*dp, (MALLOC_S)(j * sizeof(struct l_dev *))))) { (void) fprintf(stderr, "%s: can't realloc %s device pointers\n", Pn, nm); Exit(1); } return(j); } /* * saveADev() - save additional device number appearing inside DDEV_DEVPATH */ static void saveADev(s) struct stat *s; /* stat(2) buffer for file */ { int i; MALLOC_S sz; /* * Process VCHR files. * * Optionally process VBLK files. */ #if defined(HASBLKDEV) if (((s->st_mode & S_IFMT) != S_IFBLK) && ((s->st_mode & S_IFMT) != S_IFCHR)) #else /* !defined(HASBLKDEV) */ if ((s->st_mode & S_IFCHR) != S_IFCHR) #endif /* defined(HASBLKDEV) */ return; /* * See if this is a new VBLK or VCHR st_dev value for ADev[]. */ for (i = 0; i < ADevU; i++) { if (s->st_dev == ADev[i]) return; } /* * This is a new device number to add to ADev[]. */ if (ADevU >= ADevA) { ADevA += 16; sz = (MALLOC_S)(ADevA * sizeof(dev_t)); if (ADev) ADev = (dev_t *)realloc((MALLOC_P *)ADev, sz); else ADev = (dev_t *)malloc(sz); if (!ADev) { (void) fprintf(stderr, "%s: no space for ADev[]\n", Pn); Exit(1); } } ADev[ADevU++] = s->st_dev; } lsof-4.86+dfsg.orig/dialects/darwin/libproc/dsock.c0000444000175000017500000003040611741061251022432 0ustar nicholasnicholas/* * dsock.c -- Darwin socket processing functions for libproc-based lsof */ /* * Portions Copyright 2005 Apple Computer, Inc. All rights reserved. * * Copyright 2005 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Allan Nathanson, Apple Computer, Inc., and Victor A. * Abell, Purdue University. * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors, nor Apple Computer, Inc. nor Purdue University * are responsible for any consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either * by explicit claim or by omission. Credit to the authors, Apple * Computer, Inc. and Purdue University must appear in documentation * and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 2005 Apple Computer, Inc. and Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dsock.c,v 1.7 2012/04/10 16:41:04 abe Exp $"; #endif #include "lsof.h" /* * IPv6_2_IPv4() -- macro to define the address of an IPv4 address contained * in an IPv6 address */ #define IPv6_2_IPv4(v6) (((uint8_t *)((struct in6_addr *)v6)->s6_addr)+12) /* * process_socket() -- process socket file */ static void process_socket_common(si) struct socket_fdinfo *si; { unsigned char *fa = (unsigned char *)NULL; int fam, fp, lp, unl; unsigned char *la = (unsigned char *)NULL; /* * Enter basic socket values. */ (void) snpf(Lf->type, sizeof(Lf->type), "sock"); Lf->inp_ty = 2; /* * Enter basic file information. */ enter_file_info(&si->pfi); /* * Enable size or offset display. */ if (Fsize) { if (Lf->access == 'r') Lf->sz = (SZOFFTYPE)si->psi.soi_rcv.sbi_cc; else if (Lf->access == 'w') Lf->sz = (SZOFFTYPE)si->psi.soi_snd.sbi_cc; else Lf->sz = (SZOFFTYPE)(si->psi.soi_rcv.sbi_cc + si->psi.soi_snd.sbi_cc); Lf->sz_def = 1; } else Lf->off_def = 1; #if defined(HASTCPTPIQ) /* * Enter send and receive queue sizes. */ Lf->lts.rq = si->psi.soi_rcv.sbi_cc; Lf->lts.sq = si->psi.soi_snd.sbi_cc; Lf->lts.rqs = Lf->lts.sqs = (unsigned char)1; #endif /* defined(HASTCPTPIQ) */ #if defined(HASSOOPT) /* * Enter socket options. */ Lf->lts.ltm = (unsigned int)(si->psi.soi_linger & 0xffff); Lf->lts.opt = (unsigned int)(si->psi.soi_options & 0xffff); Lf->lts.pqlen = (unsigned int)si->psi.soi_incqlen; Lf->lts.qlen = (unsigned int)si->psi.soi_qlen; Lf->lts.qlim = (unsigned int)si->psi.soi_qlimit; Lf->lts.rbsz = (unsigned long)si->psi.soi_rcv.sbi_mbmax; Lf->lts.sbsz = (unsigned long)si->psi.soi_snd.sbi_mbmax; Lf->lts.pqlens = Lf->lts.qlens = Lf->lts.qlims = Lf->lts.rbszs = Lf->lts.sbszs = (unsigned char)1; #endif /* defined(HASSOOPT) */ #if defined(HASSOSTATE) /* * Enter socket state. */ Lf->lts.ss = (unsigned int)si->psi.soi_state; #endif /* defined(HASSOSTATE) */ /* * Process socket by its associated domain family. */ switch ((fam = si->psi.soi_family)) { case AF_INET: case AF_INET6: /* * Process IPv[46] sockets. */ (void) snpf(Lf->type, sizeof(Lf->type), (fam == AF_INET) ? "IPv4" : "IPv6"); if ((si->psi.soi_kind != SOCKINFO_IN) && (si->psi.soi_kind != SOCKINFO_TCP)) { break; } /* * Process TCP state inclusions and exclusions, as required. */ if ((si->psi.soi_kind == SOCKINFO_TCP) && (TcpStXn || TcpStIn)) { int tsnx = (int)si->psi.soi_proto.pri_tcp.tcpsi_state + TcpStOff; if ((tsnx >= 0) && (tsnx < TcpNstates)) { if (TcpStXn) { if (TcpStX[tsnx]) { Lf->sf |= SELEXCLF; return; } } if (TcpStIn) { if (TcpStI[tsnx]) TcpStI[tsnx] = 2; else { Lf->sf |= SELEXCLF; return; } } } } /* * Process an Internet domain socket. */ if (Fnet) { if (!FnetTy || ((FnetTy == 4) && (fam == AF_INET)) || ((FnetTy == 6) && (fam == AF_INET6)) ) Lf->sf |= SELNET; } printiproto(si->psi.soi_protocol); if ((si->psi.soi_kind == SOCKINFO_TCP) && si->psi.soi_proto.pri_tcp.tcpsi_tp) { enter_dev_ch(print_kptr((KA_T)si->psi.soi_proto.pri_tcp.tcpsi_tp, (char *)NULL, 0)); } else enter_dev_ch(print_kptr((KA_T)si->psi.soi_pcb, (char *)NULL, 0)); if (fam == AF_INET) { /* * Enter IPv4 address information. */ if (si->psi.soi_kind == SOCKINFO_TCP) { /* * Enter information for a TCP socket. */ la = (unsigned char *)&si->psi.soi_proto.pri_tcp.tcpsi_ini.insi_laddr.ina_46.i46a_addr4; lp = (int)ntohs(si->psi.soi_proto.pri_tcp.tcpsi_ini.insi_lport); fa = (unsigned char *)&si->psi.soi_proto.pri_tcp.tcpsi_ini.insi_faddr.ina_46.i46a_addr4; fp = (int)ntohs(si->psi.soi_proto.pri_tcp.tcpsi_ini.insi_fport); } else { /* * Enter information for a non-TCP socket. */ la = (unsigned char *)&si->psi.soi_proto.pri_in.insi_laddr.ina_46.i46a_addr4; lp = (int)ntohs(si->psi.soi_proto.pri_in.insi_lport); fa = (unsigned char *)&si->psi.soi_proto.pri_in.insi_faddr.ina_46.i46a_addr4; fp = (int)ntohs(si->psi.soi_proto.pri_in.insi_fport); } if ((fa && (*fa == INADDR_ANY)) && !fp) { fa = (unsigned char *)NULL; fp = 0; } } else { /* * Enter IPv6 address information */ int v4mapped = 0; if (si->psi.soi_kind == SOCKINFO_TCP) { /* * Enter TCP socket information. */ la = (unsigned char *)&si->psi.soi_proto.pri_tcp.tcpsi_ini.insi_laddr.ina_6; lp = (int)ntohs(si->psi.soi_proto.pri_tcp.tcpsi_ini.insi_lport); fa = (unsigned char *)&si->psi.soi_proto.pri_tcp.tcpsi_ini.insi_faddr.ina_6; fp = (int)ntohs(si->psi.soi_proto.pri_tcp.tcpsi_ini.insi_fport); if ((si->psi.soi_proto.pri_tcp.tcpsi_ini.insi_vflag & INI_IPV4) != 0) v4mapped = 1; } else { /* * Enter non-TCP socket information. */ la = (unsigned char *)&si->psi.soi_proto.pri_in.insi_laddr.ina_6; lp = (int)ntohs(si->psi.soi_proto.pri_in.insi_lport); fa = (unsigned char *)&si->psi.soi_proto.pri_in.insi_faddr.ina_6; fp = (int)ntohs(si->psi.soi_proto.pri_in.insi_fport); if ((si->psi.soi_proto.pri_in.insi_vflag & INI_IPV4) != 0) v4mapped = 1; } if (IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)fa) && !fp) { fa = (unsigned char *)NULL; fp = 0; } if (v4mapped) { /* * Adjust IPv4 addresses mapped in IPv6 addresses. */ fam = AF_INET; if (la) la = (unsigned char *)IPv6_2_IPv4(la); if (fa) fa = (unsigned char *)IPv6_2_IPv4(fa); } } /* * Enter local and remote addresses by address family. */ if (fa || la) (void) ent_inaddr(la, lp, fa, fp, fam); if (si->psi.soi_kind == SOCKINFO_TCP) { /* * Enter a TCP socket definition and its state. */ Lf->lts.type = 0; Lf->lts.state.i = (int)si->psi.soi_proto.pri_tcp.tcpsi_state; /* * Enter TCP options. */ #if defined(HASSOOPT) Lf->lts.kai = (unsigned int)si->psi.soi_proto.pri_tcp.tcpsi_timer[TCPT_KEEP]; #endif /* defined(HASSOOPT) */ #if defined(HASTCPOPT) Lf->lts.mss = (unsigned long)si->psi.soi_proto.pri_tcp.tcpsi_mss; Lf->lts.msss = (unsigned char)1; Lf->lts.topt = (unsigned int)si->psi.soi_proto.pri_tcp.tcpsi_flags; #endif /* defined(HASTCPOPT) */ } break; case AF_UNIX: /* * Process a UNIX domain socket. */ (void) snpf(Lf->type, sizeof(Lf->type), "unix"); if (si->psi.soi_kind != SOCKINFO_UN) break; if (Funix) Lf->sf |= SELUNX; enter_dev_ch(print_kptr((KA_T)si->psi.soi_pcb, (char *)NULL, 0)); /* * Enter information on a UNIX domain socket that has no address bound * to it, although it may be connected to another UNIX domain socket * as a pipe. */ if (si->psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_family != AF_UNIX) { if (si->psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_family == AF_UNSPEC) { if (si->psi.soi_proto.pri_un.unsi_conn_pcb) { (void) snpf(Namech, Namechl, "->%s", print_kptr((KA_T)si->psi.soi_proto.pri_un.unsi_conn_pcb, (char *)NULL, 0)); } else (void) snpf(Namech, Namechl, "->(none)"); } else (void) snpf(Namech, Namechl, "unknown sun_family (%d)", si->psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_family); break; } if (si->psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_path[0]) { unl = si->psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_len - offsetof(struct sockaddr_un, sun_path); if ((unl < 0) || (unl >= sizeof(si->psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_path))) unl = sizeof(si->psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_path) - 1; si->psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_path[unl] = '\0'; if (si->psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_path[0] && Sfile && is_file_named(si->psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_path, 0)) Lf->sf |= SELNM; if (si->psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_path[0] && !Namech[0]) (void) snpf(Namech, Namechl, "%s", si->psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_path); } else (void) snpf(Namech, Namechl, "no address"); break; case AF_ROUTE: /* * Process a ROUTE domain socket. */ (void) snpf(Lf->type, sizeof(Lf->type), "rte"); if (!Fsize) Lf->off_def = 1; break; case AF_NDRV: /* * Process an NDRV domain socket. */ (void) snpf(Lf->type, sizeof(Lf->type), "ndrv"); if (si->psi.soi_kind != SOCKINFO_NDRV) break; enter_dev_ch(print_kptr((KA_T)si->psi.soi_pcb, (char *)NULL, 0)); si->psi.soi_proto.pri_ndrv.ndrvsi_if_name[sizeof(si->psi.soi_proto.pri_ndrv.ndrvsi_if_name) - 1] = '\0'; (void) snpf(Namech, Namechl, "-> %s%d", si->psi.soi_proto.pri_ndrv.ndrvsi_if_name, si->psi.soi_proto.pri_ndrv.ndrvsi_if_unit); break; case pseudo_AF_KEY: /* * Process an [internal] key-management function socket. */ (void) snpf(Lf->type, sizeof(Lf->type), "key"); enter_dev_ch(print_kptr((KA_T)si->psi.soi_pcb, (char *)NULL, 0)); break; case AF_SYSTEM: /* * Process a SYSTEM domain socket. */ (void) snpf(Lf->type, sizeof(Lf->type), "systm"); if (si->psi.soi_kind != SOCKINFO_KERN_EVENT) break; enter_dev_ch(print_kptr((KA_T)si->psi.soi_pcb, (char *)NULL, 0)); (void) snpf(Namech, Namechl, "[%x:%x:%x]", si->psi.soi_proto.pri_kern_event.kesi_vendor_code_filter, si->psi.soi_proto.pri_kern_event.kesi_class_filter, si->psi.soi_proto.pri_kern_event.kesi_subclass_filter); break; case AF_PPP: /* * Process a PPP domain socket. */ (void) snpf(Lf->type, sizeof(Lf->type), "ppp"); enter_dev_ch(print_kptr((KA_T)si->psi.soi_pcb, (char *)NULL, 0)); break; default: printunkaf(fam, 1); } /* * If there are NAME column characters, enter them. */ if (Namech[0]) enter_nm(Namech); } void process_socket(pid, fd) int pid; /* PID */ int32_t fd; /* FD */ { int nb; struct socket_fdinfo si; /* * Get socket information. */ nb = proc_pidfdinfo(pid, fd, PROC_PIDFDSOCKETINFO, &si, sizeof(si)); if (nb <= 0) { (void) err2nm("socket"); return; } else if (nb < sizeof(si)) { (void) fprintf(stderr, "%s: PID %d, FD %d: proc_pidfdinfo(PROC_PIDFDSOCKETINFO);\n", Pn, pid, fd); (void) fprintf(stderr, " too few bytes; expected %ld, got %d\n", sizeof(si), nb); Exit(1); } process_socket_common(&si); } #ifdef PROC_PIDLISTFILEPORTS void process_fileport_socket(pid, fp) int pid; /* PID */ uint32_t fp; /* FILEPORT */ { int nb; struct socket_fdinfo si; /* * Get socket information. */ nb = proc_pidfileportinfo(pid, fp, PROC_PIDFILEPORTSOCKETINFO, &si, sizeof(si)); if (nb <= 0) { (void) err2nm("socket"); return; } else if (nb < sizeof(si)) { (void) fprintf(stderr, "%s: PID %d, FILEPORT %u: proc_pidfileportinfo(PROC_PIDFILEPORTSOCKETINFO);\n", Pn, pid, fp); (void) fprintf(stderr, " too few bytes; expected %ld, got %d\n", sizeof(si), nb); Exit(1); } process_socket_common(&si); } #endif /* PROC_PIDLISTFILEPORTS */ lsof-4.86+dfsg.orig/dialects/darwin/libproc/dproc.c0000444000175000017500000005026611741061250022443 0ustar nicholasnicholas/* * dproc.c -- Darwin process access functions for libproc-based lsof */ /* * Portions Copyright 2005-2007 Apple Inc. All rights reserved. * * Copyright 2005 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Allan Nathanson, Apple Inc., and Victor A. Abell, Purdue * University. * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors, nor Apple Inc. nor Purdue University are * responsible for any consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either * by explicit claim or by omission. Credit to the authors, Apple * Inc. and Purdue University must appear in documentation and sources. * and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 2005-2007 Apple Inc. and Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dproc.c,v 1.8 2012/04/10 16:41:04 abe Exp $"; #endif #include "lsof.h" /* * Local definitions */ #define PIDS_INCR (sizeof(int) * 32) /* PID space increment */ #define VIPS_INCR 16 /* Vips space increment */ #if DARWINV>=900 #define THREADS_INCR (sizeof(uint64_t) * 32) /* Threads space increment */ #endif /* DARWINV>=900 */ #ifdef PROC_PIDLISTFILEPORTS #define FILEPORTS_INCR (sizeof(struct proc_fileportinfo) * 32) /* Fileports space increment */ #endif /* PROC_PIDLISTFILEPORTS */ /* * Local static variables */ static struct proc_fdinfo *Fds = (struct proc_fdinfo *)NULL; /* FD buffer */ static int NbPids = 0; /* bytes allocated to Pids */ static int NbFds = 0; /* bytes allocated to FDs */ static int *Pids = (int *)NULL; /* PID buffer */ #if DARWINV>=900 static int NbThreads = 0; /* Threads bytes allocated */ static uint64_t *Threads = (uint64_t *)NULL; /* Thread buffer */ #endif /* DARWINV>=900 */ #ifdef PROC_PIDLISTFILEPORTS static struct proc_fileportinfo *Fps = (struct proc_fileportinfo *)NULL; /* fileport buffer */ static int NbFps = 0; /* bytes allocated to fileports */ #endif /* PROC_PIDLISTFILEPORTS */ /* * Local structure definitions */ static struct vips_info { dev_t dev; ino_t ino; } *Vips = (struct vips_info *)NULL; /* recorded vnodes */ static int NbVips = 0; /* bytes allocated to Vips */ static int NVips = 0; /* entries allocated to Vips */ /* * Local function prototypes */ _PROTOTYPE(static void enter_vn_text,(struct vnode_info_path *vip, int *n)); _PROTOTYPE(static void process_fds,(int pid, uint32_t n, int ckscko)); _PROTOTYPE(static void process_text,(int pid)); #if DARWINV>=900 _PROTOTYPE(static void process_threads,(int pid, uint32_t n)); #endif /* DARWINV>=900 */ #ifdef PROC_PIDLISTFILEPORTS _PROTOTYPE(static void process_fileports,(int pid, int ckscko)); #endif /* PROC_PIDLISTFILEPORTS */ /* * enter_vn_text() -- enter vnode information text reference */ static void enter_vn_text(vip, n) struct vnode_info_path *vip; /* vnode info */ int *n; /* number of vips[] entries in use */ { int i; /* * Ignore the request if the vnode information has already been entered. */ for (i = 0; i < *n; i++) { if ((vip->vip_vi.vi_stat.vst_dev == Vips[i].dev) && (vip->vip_vi.vi_stat.vst_ino == Vips[i].ino)) { return; } } /* * Save the text file information. */ alloc_lfile(" txt", -1); Cfp = (struct file *)NULL; (void) enter_vnode_info(vip); if (Lf->sf) link_lfile(); /* * Record the entry of the vnode information. */ if (i >= NVips) { /* * Allocate space for recording the vnode information. */ NVips += VIPS_INCR; NbVips += (int)(VIPS_INCR * sizeof(struct vips_info)); if (!Vips) Vips = (struct vips_info *)malloc((MALLOC_S)NbVips); else Vips = (struct vips_info *)realloc((MALLOC_P *)Vips, (MALLOC_S)NbVips); if (!Vips) { (void) fprintf(stderr, "%s: PID %d: no text recording space\n", Pn, Lp->pid); Exit(1); } } /* * Record the vnode information. */ Vips[*n].dev = vip->vip_vi.vi_stat.vst_dev; Vips[*n].ino = vip->vip_vi.vi_stat.vst_ino; (*n)++; } /* * gather_proc_info() -- gather process information */ void gather_proc_info() { short cckreg; /* conditional status of regular file * checking: * 0 = unconditionally check * 1 = conditionally check */ short ckscko; /* socket file only checking status: * 0 = none * 1 = check only socket files, * including TCP and UDP * streams with eXPORT data, * where supported */ int cre, cres, ef, i, nb, np, pid; short pss, sf; struct proc_taskallinfo tai; struct proc_vnodepathinfo vpi; /* * Define socket and regular file conditional processing flags. * * If only socket files have been selected, or socket files have been * selected, ANDed with other selection options, enable the skipping of * regular files. * * If socket files and some process options have been selected, enable * conditional skipping of regular file; i.e., regular files will be skipped * unless they belong to a process selected by one of the specified options. */ if (Selflags & SELNW) { /* * Some network files selection options have been specified. */ if (Fand || !(Selflags & ~SELNW)) { /* * Selection ANDing or only network file options have been * specified, so set unconditional skipping of regular files * and socket file only checking. */ cckreg = 0; ckscko = 1; } else { /* * If ORed file selection options have been specified, or no * ORed process selection options have been specified, enable * unconditional file checking and clear socket file only * checking. * * If only ORed process selection options have been specified, * enable conditional file skipping and socket file only checking. */ if ((Selflags & SELFILE) || !(Selflags & SELPROC)) cckreg = ckscko = 0; else cckreg = ckscko = 1; } } else { /* * No network file selection options were specified. Enable * unconditional file checking and clear socket file only checking. */ cckreg = ckscko = 0; } /* * Determine how many bytes are needed to contain the PIDs on the system; * make sure sufficient buffer space is allocated to hold them (and a few * extra); then read the list of PIDs. */ if ((nb = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0)) <= 0) { (void) fprintf(stderr, "%s: can't get PID byte count: %s\n", Pn, strerror(errno)); Exit(1); } if (nb > NbPids) { while (nb > NbPids) { NbPids += PIDS_INCR; } if (!Pids) Pids = (int *)malloc((MALLOC_S)NbPids); else Pids = (int *)realloc((MALLOC_P *)Pids, (MALLOC_S)NbPids); if (!Pids) { (void) fprintf(stderr, "%s: can't allocate space for %d PIDs\n", Pn, (int)(NbPids / sizeof(int *))); Exit(1); } } /* * Get the list of PIDs. */ for (ef = 0; !ef;) { if ((nb = proc_listpids(PROC_ALL_PIDS, 0, Pids, NbPids)) <= 0) { (void) fprintf(stderr, "%s: can't get list of PIDs: %s\n", Pn, strerror(errno)); Exit(1); } if ((nb + sizeof(int)) < NbPids) { /* * There is room in the buffer for at least one more PID. */ np = nb / sizeof(int); ef = 1; } else { /* * The PID buffer must be enlarged. */ NbPids += PIDS_INCR; Pids = (int *)realloc((MALLOC_P *)Pids, (MALLOC_S)NbPids); if (!Pids) { (void) fprintf(stderr, "%s: can't allocate space for %d PIDs\n", Pn, (int)(NbPids / sizeof(int *))); Exit(1); } } } /* * Loop through the identified processes. */ for (i = 0; i < np; i++) { if (!(pid = Pids[i])) continue; nb = proc_pidinfo(pid, PROC_PIDTASKALLINFO, 0, &tai, sizeof(tai)); if (nb <= 0) { if ((errno == EPERM) || (errno == ESRCH)) continue; if (!Fwarn) { (void) fprintf(stderr, "%s: PID %d information error: %s\n", Pn, pid, strerror(errno)); } continue; } else if (nb < sizeof(tai)) { (void) fprintf(stderr, "%s: PID %d: proc_pidinfo(PROC_PIDTASKALLINFO);\n", Pn, pid); (void) fprintf(stderr, " too few bytes; expected %ld, got %d\n", sizeof(tai), nb); Exit(1); } /* * Check for process or command exclusion. */ if (is_proc_excl((int)pid, (int)tai.pbsd.pbi_rgid, (UID_ARG)tai.pbsd.pbi_uid, &pss, &sf)) { continue; } tai.pbsd.pbi_comm[sizeof(tai.pbsd.pbi_comm) - 1] = '\0'; if (is_cmd_excl(tai.pbsd.pbi_comm, &pss, &sf)) continue; if (tai.pbsd.pbi_name[0]) { tai.pbsd.pbi_name[sizeof(tai.pbsd.pbi_name) - 1] = '\0'; if (is_cmd_excl(tai.pbsd.pbi_name, &pss, &sf)) continue; } if (cckreg) { /* * If conditional checking of regular files is enabled, enable * socket file only checking, based on the process' selection * status. */ ckscko = (sf & SELPROC) ? 0 : 1; } /* * Get root and current directory information. */ if (!ckscko) { nb = proc_pidinfo(pid, PROC_PIDVNODEPATHINFO, 0, &vpi, sizeof(vpi)); if (nb <= 0) { cre = errno; cres = 1; } else if (nb < sizeof(vpi)) { (void) fprintf(stderr, "%s: PID %d: proc_pidinfo(PROC_PIDVNODEPATHINFO);\n", Pn, pid); (void) fprintf(stderr, " too few bytes; expected %ld, got %d\n", sizeof(vpi), nb); Exit(1); } else cres = 0; } /* * Allocate local process space. */ alloc_lproc((int)pid, (int)tai.pbsd.pbi_rgid, (int)tai.pbsd.pbi_ppid, (UID_ARG)tai.pbsd.pbi_uid, (tai.pbsd.pbi_name[0] != '\0') ? tai.pbsd.pbi_name : tai.pbsd.pbi_comm, (int)pss, (int)sf); Plf = (struct lfile *)NULL; /* * Save current working directory information. */ if (!ckscko) { if (cres || vpi.pvi_cdir.vip_path[0]) { alloc_lfile(CWD, -1); Cfp = (struct file *)NULL; if (cres) { /* * If the CWD|RTD information access error is ESRCH, * ignore it; otherwise report the error's message in the * CWD's NAME column. */ if (cre != ESRCH) { (void) snpf(Namech, Namechl, "%s|%s info error: %s", CWD + 1, RTD + 1, strerror(cre)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); if (Lf->sf) link_lfile(); } } else { (void) enter_vnode_info(&vpi.pvi_cdir); if (Lf->sf) link_lfile(); } } } /* * Save root directory information. */ if (!ckscko) { if (!cres && vpi.pvi_rdir.vip_path[0]) { alloc_lfile(RTD, -1); Cfp = (struct file *)NULL; (void) enter_vnode_info(&vpi.pvi_rdir); if (Lf->sf) link_lfile(); } } #if DARWINV>=900 /* * Check for per-thread current working directories */ if (!ckscko) { if (tai.pbsd.pbi_flags & PROC_FLAG_THCWD) { (void) process_threads(pid, tai.ptinfo.pti_threadnum); } } #endif /* DARWINV>=900 */ /* * Print text file information. */ if (!ckscko) (void) process_text(pid); #ifdef PROC_PIDLISTFILEPORTS /* * Loop through the fileports */ (void) process_fileports(pid, ckscko); #endif /* PROC_PIDLISTFILEPORTS */ /* * Loop through the file descriptors. */ (void) process_fds(pid, tai.pbsd.pbi_nfiles, ckscko); /* * Examine results. */ if (examine_lproc()) return; } } /* * initialize() -- perform all initialization */ void initialize() { } /* * process_fds() -- process file descriptors */ static void process_fds(pid, n, ckscko) int pid; /* PID of interest */ uint32_t n; /* max FDs */ int ckscko; /* check socket files only */ { int i, isock, nb, nf; struct proc_fdinfo *fdp; /* * Make sure an FD buffer has been allocated. */ if (!Fds) { NbFds = sizeof(struct proc_fdinfo) * n; Fds = (struct proc_fdinfo *)malloc((MALLOC_S)NbFds); } else if (NbFds < sizeof(struct proc_fdinfo) * n) { /* * More proc_fdinfo space is required. Allocate it. */ NbFds = sizeof(struct proc_fdinfo) * n; Fds = (struct proc_fdinfo *)realloc((MALLOC_P *)Fds, (MALLOC_S)NbFds); } if (!Fds) { (void) fprintf(stderr, "%s: PID %d: can't allocate space for %d FDs\n", Pn, pid, (int)(NbFds / sizeof(struct proc_fdinfo))); Exit(1); } /* * Get FD information for the process. */ nb = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, Fds, NbFds); if (nb <= 0) { if (errno == ESRCH) { /* * Quit if no FD information is available for the process. */ return; } /* * Make a dummy file entry with an error message in its NAME column. */ alloc_lfile(" err", -1); (void) snpf(Namech, Namechl, "FD info error: %s", strerror(errno)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); if (Lf->sf) link_lfile(); return; } nf = (int)(nb / sizeof(struct proc_fdinfo)); /* * Loop through the file descriptors. */ for (i = 0; i < nf; i++) { fdp = &Fds[i]; alloc_lfile(NULL, (int)fdp->proc_fd); /* * Process the file by its type. */ isock = 0; switch (fdp->proc_fdtype) { case PROX_FDTYPE_ATALK: if (!ckscko) (void) process_atalk(pid, fdp->proc_fd); break; case PROX_FDTYPE_FSEVENTS: if (!ckscko) (void) process_fsevents(pid, fdp->proc_fd); break; case PROX_FDTYPE_KQUEUE: if (!ckscko) (void) process_kqueue(pid, fdp->proc_fd); break; case PROX_FDTYPE_PIPE: if (!ckscko) (void) process_pipe(pid, fdp->proc_fd); break; case PROX_FDTYPE_PSEM: if (!ckscko) (void) process_psem(pid, fdp->proc_fd); break; case PROX_FDTYPE_SOCKET: (void) process_socket(pid, fdp->proc_fd); isock = 1; break; case PROX_FDTYPE_PSHM: (void) process_pshm(pid, fdp->proc_fd); break; case PROX_FDTYPE_VNODE: (void) process_vnode(pid, fdp->proc_fd); break; default: (void) snpf(Namech, Namechl - 1, "unknown file type: %d", fdp->proc_fdtype); Namech[Namechl - 1] = '\0'; (void) enter_nm(Namech); break; } if (Lf->sf) { if (!ckscko || isock) link_lfile(); } } } #ifdef PROC_PIDLISTFILEPORTS /* * process_fileports() -- process fileports */ static void process_fileports(pid, ckscko) int pid; /* PID of interest */ int ckscko; /* check socket files only */ { int ef, i, isock, nb = 0, nf; struct proc_fileportinfo *fpi; /* * Get fileport information for the process. */ for (ef = 0; !ef;) { nb = proc_pidinfo(pid, PROC_PIDLISTFILEPORTS, 0, Fps, NbFps); if (nb == 0) { /* * Quit if no fileport information */ return; } else if (nb < 0) { if (errno == ESRCH) { /* * Quit if no fileport information is available for the process. */ return; } /* * Make a dummy file entry with an error message in its NAME column. */ alloc_lfile(" err", -1); (void) snpf(Namech, Namechl, "FILEPORT info error: %s", strerror(errno)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); if (Lf->sf) link_lfile(); } if ((nb + sizeof(struct proc_fileportinfo)) < NbFps) { /* * There is room in the buffer for at least one more fileport. */ ef = 1; } else { if (Fps && ((nb = proc_pidinfo(pid, PROC_PIDLISTFILEPORTS, 0, NULL, 0)) <= 0)) { (void) fprintf(stderr, "%s: can't get fileport byte count: %s\n", Pn, strerror(errno)); Exit(1); } /* * The fileport buffer must be enlarged. */ while (nb > NbFps) { NbFps += FILEPORTS_INCR; } if (!Fps) Fps = (struct proc_fileportinfo *)malloc((MALLOC_S)NbFps); else Fps = (struct proc_fileportinfo *)realloc((MALLOC_P *)Fps, (MALLOC_S)NbFps); } } /* * Loop through the fileports. */ nf = (int)(nb / sizeof(struct proc_fileportinfo)); for (i = 0; i < nf; i++) { fpi = &Fps[i]; /* * fileport reported as "fp." with "(fileport=0xXXXX)" in the Name column */ alloc_lfile(" fp.", -1); Lf->fileport = fpi->proc_fileport; /* * Process the file by its type. */ isock = 0; switch (fpi->proc_fdtype) { case PROX_FDTYPE_PIPE: if (!ckscko) (void) process_fileport_pipe(pid, fpi->proc_fileport); break; case PROX_FDTYPE_SOCKET: (void) process_fileport_socket(pid, fpi->proc_fileport); isock = 1; break; case PROX_FDTYPE_PSHM: (void) process_fileport_pshm(pid, fpi->proc_fileport); break; case PROX_FDTYPE_VNODE: (void) process_fileport_vnode(pid, fpi->proc_fileport); break; default: (void) snpf(Namech, Namechl - 1, "unknown file type: %d", fpi->proc_fileport); Namech[Namechl - 1] = '\0'; (void) enter_nm(Namech); break; } if (Lf->sf) { if (!ckscko || isock) link_lfile(); } } } #endif /* PROC_PIDLISTFILEPORTS */ /* * process_text() -- process text information */ static void process_text(pid) int pid; /* PID */ { uint64_t a; int i, n, nb; struct proc_regionwithpathinfo rwpi; for (a = (uint64_t)0, i = n = 0; i < 10000; i++) { nb = proc_pidinfo(pid, PROC_PIDREGIONPATHINFO, a, &rwpi, sizeof(rwpi)); if (nb <= 0) { if ((errno == ESRCH) || (errno == EINVAL)) { /* * Quit if no more text information is available for the * process. */ return; } /* * Warn about all other errors via a NAME column message. */ alloc_lfile(" txt", -1); Cfp = (struct file *)NULL; (void) snpf(Namech, Namechl, "region info error: %s", strerror(errno)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); if (Lf->sf) link_lfile(); return; } else if (nb < sizeof(rwpi)) { (void) fprintf(stderr, "%s: PID %d: proc_pidinfo(PROC_PIDREGIONPATHINFO);\n", Pn, pid); (void) fprintf(stderr, " too few bytes; expected %ld, got %d\n", sizeof(rwpi), nb); Exit(1); } if (rwpi.prp_vip.vip_path[0]) enter_vn_text(&rwpi.prp_vip, &n); a = rwpi.prp_prinfo.pri_address + rwpi.prp_prinfo.pri_size; } } #if DARWINV>=900 /* * process_threads() -- process thread information */ #define TWD " twd" /* per-thread current working directory * fd name */ static void process_threads(pid, n) int pid; /* PID */ uint32_t n; /* number of threads */ { int i, nb, nt; /* * Make sure a thread buffer has been allocated. */ n += 10; if (n > NbThreads) { while (n > NbThreads) { NbThreads += THREADS_INCR; } if (!Threads) Threads = (uint64_t *)malloc((MALLOC_S)NbThreads); else Threads = (uint64_t *)realloc((MALLOC_P *)Threads, (MALLOC_S)NbThreads); if (!Threads) { (void) fprintf(stderr, "%s: can't allocate space for %d Threads\n", Pn, (int)(NbThreads / sizeof(int *))); Exit(1); } } /* * Get thread information for the process. */ nb = proc_pidinfo(pid, PROC_PIDLISTTHREADS, 0, Threads, NbThreads); if (nb <= 0) { if (errno == ESRCH) { /* * Quit if no thread information is available for the * process. */ return; } } nt = (int)(nb / sizeof(uint64_t)); /* * Loop through the threads. */ for (i = 0; i < nt; i++) { uint64_t t; struct proc_threadwithpathinfo tpi; t = Threads[i]; nb = proc_pidinfo(pid, PROC_PIDTHREADPATHINFO, t, &tpi, sizeof(tpi)); if (nb <= 0) { if ((errno == ESRCH) || (errno == EINVAL)) { /* * Quit if no more thread information is available for the * process. */ return; } /* * Warn about all other errors via a NAME column message. */ alloc_lfile(TWD, -1); Cfp = (struct file *)NULL; (void) snpf(Namech, Namechl, "thread info error: %s", strerror(errno)); Namech[Namechl - 1] = '\0'; enter_nm(Namech); if (Lf->sf) link_lfile(); return; } else if (nb < sizeof(tpi)) { (void) fprintf(stderr, "%s: PID %d: proc_pidinfo(PROC_PIDTHREADPATHINFO);\n", Pn, pid); (void) fprintf(stderr, " too few bytes; expected %ld, got %d\n", sizeof(tpi), nb); Exit(1); } if (tpi.pvip.vip_path[0]) { alloc_lfile(TWD, -1); Cfp = (struct file *)NULL; (void) enter_vnode_info(&tpi.pvip); if (Lf->sf) link_lfile(); } } } #endif /* DARWINV>=900 */ lsof-4.86+dfsg.orig/dialects/darwin/libproc/dproto.h0000444000175000017500000000466011741061250022645 0ustar nicholasnicholas/* * dproto.h -- Darwin function prototypes for libproc-based lsof * * The _PROTOTYPE macro is defined in the common proto.h. */ /* * Portions Copyright 2005 Apple Computer, Inc. All rights reserved. * * Copyright 2005 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Allan Nathanson, Apple Computer, Inc., and Victor A. * Abell, Purdue University. * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors, nor Apple Computer, Inc. nor Purdue University * are responsible for any consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either * by explicit claim or by omission. Credit to the authors, Apple * Computer, Inc. and Purdue University must appear in documentation * and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: dproto.h,v 1.6 2012/04/10 16:41:04 abe Exp $ */ _PROTOTYPE(extern void enter_file_info,(struct proc_fileinfo *pfi)); _PROTOTYPE(extern void enter_vnode_info,(struct vnode_info_path *vip)); _PROTOTYPE(extern void err2nm,(char *pfx)); _PROTOTYPE(extern int is_file_named,(char *p, int cd)); _PROTOTYPE(extern void process_atalk,(int pid, int32_t fd)); _PROTOTYPE(extern void process_fsevents,(int pid, int32_t fd)); _PROTOTYPE(extern void process_kqueue,(int pid, int32_t fd)); _PROTOTYPE(extern void process_pipe,(int pid, int32_t fd)); _PROTOTYPE(extern void process_psem,(int pid, int32_t fd)); _PROTOTYPE(extern void process_pshm,(int pid, int32_t fd)); _PROTOTYPE(extern void process_socket,(int pid, int32_t fd)); _PROTOTYPE(extern void process_vnode,(int pid, int32_t fd)); #ifdef PROC_PIDLISTFILEPORTS _PROTOTYPE(extern void process_fileport_pipe,(int pid, uint32_t fileport)); _PROTOTYPE(extern void process_fileport_pshm,(int pid, uint32_t fileport)); _PROTOTYPE(extern void process_fileport_socket,(int pid, uint32_t fileport)); _PROTOTYPE(extern void process_fileport_vnode,(int pid, uint32_t fileport)); #endif /* PROC_PIDLISTFILEPORTS */ lsof-4.86+dfsg.orig/dialects/darwin/libproc/dlsof.h0000444000175000017500000000753511741061246022456 0ustar nicholasnicholas/* * dlsof.h -- Darwin header file for libproc-based lsof */ /* * Portions Copyright 2005-2007 Apple Inc. All rights reserved. * * Copyright 2005 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Allan Nathanson, Apple Inc., and Victor A. Abell, Purdue * University. * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors, nor Apple Inc. nor Purdue University are * responsible for any consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either * by explicit claim or by omission. Credit to the authors, Apple * Inc. and Purdue University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: dlsof.h,v 1.8 2012/04/10 16:41:04 abe Exp $ */ #if !defined(DARWIN_LSOF_H) #define DARWIN_LSOF_H 1 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include # if DARWINV<900 #define vst_blksize st_blksize #define vst_dev st_dev #define vst_ino st_ino #define vst_mode st_mode #define vst_nlink st_nlink #define vst_rdev st_rdev #define vst_size st_size # endif /* DARWINV<=900 */ #define COMP_P const void #define DEVINCR 1024 /* device table malloc() increment */ #define DIRTYPE dirent /* directory entry type */ typedef uintptr_t KA_T; #define KA_T_FMT_X "0x%08lx" #define LOGINML MAXLOGNAME #define MALLOC_P void #define FREE_P MALLOC_P #define MALLOC_S size_t #define MAXSYSCMDL (MAXCOMLEN - 1) /* max system command name length */ #define MOUNTED MNT_MNTTAB #define QSORT_P void #define READLEN_T int #define STRNCPY_L size_t #define SZOFFTYPE unsigned long long /* size and offset internal storage * type */ #define SZOFFPSPEC "ll" /* SZOFFTYPE printf specification * modifier */ /* * Global storage definitions (including their structure definitions) */ struct file *Cfp; struct mounts { char *dir; /* directory (mounted on) */ char *fsname; /* file system * (symbolic links unresolved) */ char *fsnmres; /* file system * (symbolic links resolved) */ dev_t dev; /* directory st_dev */ dev_t rdev; /* directory st_rdev */ INODETYPE inode; /* directory st_ino */ mode_t mode; /* directory st_mode */ mode_t fs_mode; /* file system st_mode */ int is_nfs; /* 1 if NFS file system, 0 if not */ struct mounts *next; /* forward link */ }; struct sfile { char *aname; /* argument file name */ char *name; /* file name (after readlink()) */ char *devnm; /* device name (optional) */ dev_t dev; /* device */ dev_t rdev; /* raw device */ u_short mode; /* S_IFMT mode bits from stat() */ int type; /* file type: 0 = file system * 1 = regular file */ INODETYPE i; /* inode number */ int f; /* file found flag */ struct sfile *next; /* forward link */ }; #define XDR_VOID (const xdrproc_t)xdr_void #define XDR_PMAPLIST (const xdrproc_t)xdr_pmaplist # if !defined(offsetof) #define offsetof(type, member) ((size_t)(&((type *)0)->member)) # endif /* !defined(offsetof) */ #endif /* DARWIN_LSOF_H */ lsof-4.86+dfsg.orig/dialects/darwin/libproc/Mksrc0000555000175000017500000000107411021705226022165 0ustar nicholasnicholas#!/bin/sh # # Mksrc -- make Darwin libproc-based lsof source files # # WARNING: This script assumes it is running from the main directory # of the lsof, version 4 distribution. # # One environment variable applies: # # LSOF_MKC is the method for creating the source files. # It defaults to "ln -s". A common alternative is "cp". # # $Id: Mksrc,v 1.5 2005/11/06 12:50:09 abe Exp $ D=dialects/darwin/libproc L="dlsof.h ddev.c dfile.c dmnt.c dproc.c dproto.h dsock.c dstore.c machine.h" for i in $L do rm -f $i $LSOF_MKC $D/$i $i echo "$LSOF_MKC $D/$i $i" done lsof-4.86+dfsg.orig/dialects/darwin/libproc/dfile.c0000444000175000017500000003432311741061244022416 0ustar nicholasnicholas/* * dfile.c -- Darwin file processing functions for libproc-based lsof */ /* * Portions Copyright 2005-2007 Apple Inc. All rights reserved. * * Copyright 2005 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Allan Nathanson, Apple Inc., and Victor A. Abell, Purdue * University. * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors, nor Apple Inc. nor Purdue University are * responsible for any consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either * by explicit claim or by omission. Credit to the authors, Apple * Inc. and Purdue University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 2005-2007 Apple Inc. and Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dfile.c,v 1.8 2012/04/10 16:41:04 abe Exp $"; #endif #include "lsof.h" /* * enter_file_info() -- enter file information */ void enter_file_info(pfi) struct proc_fileinfo *pfi; /* pointer to process file info */ { int f; /* * Construct access code */ f = pfi->fi_openflags & (FREAD | FWRITE); if (f == FREAD) Lf->access = 'r'; else if (f == FWRITE) Lf->access = 'w'; else if (f == (FREAD | FWRITE)) Lf->access = 'u'; /* * Save the offset / size */ Lf->off = (SZOFFTYPE)pfi->fi_offset; if (Foffset) Lf->off_def = 1; /* * Save file structure information as requested. */ if (Fsv & FSV_FG) { Lf->ffg = (long)pfi->fi_openflags; Lf->fsv |= FSV_FG; } } /* * enter_vnode_info() -- enter vnode information */ void enter_vnode_info(vip) struct vnode_info_path *vip; /* pointer to vnode info with path */ { char buf[32], *cp; dev_t dev = 0; int devs = 0; struct mounts *mp; /* * Derive file type. */ switch ((int)(vip->vip_vi.vi_stat.vst_mode & S_IFMT)) { case S_IFIFO: cp = "FIFO"; Ntype = N_FIFO; break; case S_IFCHR: cp = "CHR"; Ntype = N_CHR; break; case S_IFDIR: cp = "DIR"; Ntype = N_REGLR; break; case S_IFBLK: cp = "BLK"; Ntype = N_BLK; break; case S_IFREG: cp = "REG"; Ntype = N_REGLR; break; default: (void) snpf(buf, sizeof(buf), "%04o", (((vip->vip_vi.vi_stat.vst_mode & S_IFMT) >> 12) & 0xfff)); cp = buf; Ntype = N_REGLR; } if (!Lf->type[0]) (void) snpf(Lf->type, sizeof(Lf->type), "%s", cp); Lf->ntype = Ntype; /* * Save device number and path */ switch (Ntype) { case N_FIFO: break; case N_CHR: case N_BLK: Lf->rdev = vip->vip_vi.vi_stat.vst_rdev; Lf->rdev_def = 1; /* fall through */ default: Lf->dev = dev = vip->vip_vi.vi_stat.vst_dev; Lf->dev_def = devs = 1; } /* * Save path name. */ vip->vip_path[sizeof(vip->vip_path) - 1] = '\0'; if (vip->vip_path[0] != '\0') { Lf->V_path = mkstrcpy(vip->vip_path, (MALLOC_S *)NULL); } /* * Save node number. */ Lf->inode = (INODETYPE)vip->vip_vi.vi_stat.vst_ino; Lf->inp_ty = 1; /* * Save link count, as requested. */ if (Fnlink) { Lf->nlink = vip->vip_vi.vi_stat.vst_nlink; Lf->nlink_def = 1; if (Nlink && (Lf->nlink < Nlink)) Lf->sf |= SELNLINK; } /* * If a device number is defined, locate file system and save its identity. */ if (devs) { for (mp = readmnt(); mp; mp = mp->next) { if (dev == mp->dev) { Lf->fsdir = mp->dir; Lf->fsdev = mp->fsname; if (mp->is_nfs && Fnfs) Lf->sf |= SELNFS; break; } } } /* * Save the file size. */ switch (Ntype) { case N_CHR: case N_FIFO: Lf->off_def = 1; break; default: Lf->sz = (SZOFFTYPE)vip->vip_vi.vi_stat.vst_size; Lf->sz_def = 1; } /* * Test for specified file. */ if (Sfile && is_file_named(NULL, ((Ntype == N_CHR) || (Ntype == N_BLK) ? 1 : 0))) { Lf->sf |= SELNM; } /* * Enter name characters. */ if (!Lf->nm && Namech[0]) enter_nm(Namech); } /* * err2nm() -- convert errno to a message in Namech */ void err2nm(pfx) char *pfx; /* Namech message prefix */ { char *sfx; switch (errno) { case EBADF: /* * The file descriptor is no longer available. */ sfx = "FD unavailable"; break; case ESRCH: /* * The process is no longer available. */ sfx = "process unavailable"; break; default: /* * All other errors are reported with strerror() information. */ sfx = strerror(errno); } (void) snpf(Namech, Namechl, "%s: %s", pfx, sfx); enter_nm(Namech); } /* * print_nm() -- print Name column */ void print_nm(lf) struct lfile *lf; { printname(0); #ifdef PROC_PIDLISTFILEPORTS if (lf->fileport) { (void) printf(" (fileport=0x%04x)", lf->fileport); } #endif /* PROC_PIDLISTFILEPORTS */ putchar('\n'); } /* * print_v_path() -- print vnode's path */ int print_v_path(lf) struct lfile *lf; { if (lf->V_path) { safestrprt(lf->V_path, stdout, 0); return(1); } return(0); } /* * process_atalk() -- process an Apple Talk file */ void process_atalk(pid, fd) int pid; /* PID */ int32_t fd; /* FD */ { (void) snpf(Lf->type, sizeof(Lf->type), "ATALK"); return; } /* * process_fsevents() -- process a file system events file */ void process_fsevents(pid, fd) int pid; /* PID */ int32_t fd; /* FD */ { (void) snpf(Lf->type, sizeof(Lf->type), "FSEVENTS"); } /* * process_kqueue() -- process a kernel queue file */ void process_kqueue(pid, fd) int pid; /* PID */ int32_t fd; /* FD */ { struct kqueue_fdinfo kq; int nb; /* * Get the kernel queue file information. */ (void) snpf(Lf->type, sizeof(Lf->type), "KQUEUE"); nb = proc_pidfdinfo(pid, fd, PROC_PIDFDKQUEUEINFO, &kq, sizeof(kq)); if (nb <= 0) { (void) err2nm("kqueue"); return; } else if (nb < sizeof(kq)) { (void) fprintf(stderr, "%s: PID %d, FD %d; proc_pidfdinfo(PROC_PIDFDKQUEUEINFO);\n", Pn, pid, fd); (void) fprintf(stderr, " too few bytes; expected %ld, got %d\n", sizeof(kq), nb); Exit(1); } /* * Enter the kernel queue file information. */ enter_file_info(&kq.pfi); /* * Enter queue counts as NAME column information. */ (void) snpf(Namech, Namechl, "count=%" SZOFFPSPEC "u, state=%#x", (SZOFFTYPE)kq.kqueueinfo.kq_stat.vst_size, kq.kqueueinfo.kq_state); enter_nm(Namech); } /* * process_pipe() -- process pipe file */ static void process_pipe_common(pi) struct pipe_fdinfo *pi; { char dev_ch[32], *ep; size_t sz; (void) snpf(Lf->type, sizeof(Lf->type), "PIPE"); /* * Enter the pipe handle as the device. */ (void) snpf(dev_ch, sizeof(dev_ch), "%s", print_kptr((KA_T)pi->pipeinfo.pipe_handle, (char *)NULL, 0)); enter_dev_ch(dev_ch); /* * Enable offset or size reporting. */ if (Foffset) Lf->off_def = 1; else { Lf->sz = (SZOFFTYPE)pi->pipeinfo.pipe_stat.vst_blksize; Lf->sz_def = 1; } /* * If there is a peer handle, enter it in as NAME column information. */ if (pi->pipeinfo.pipe_peerhandle) { (void) snpf(Namech, Namechl, "->%s", print_kptr((KA_T)pi->pipeinfo.pipe_peerhandle, (char *)NULL, 0)); enter_nm(Namech); } else Namech[0] = '\0'; /* * If the pipe has a count, add it to the NAME column. */ if (pi->pipeinfo.pipe_stat.vst_size) { ep = endnm(&sz); (void) snpf(ep, sz, ", cnt=%" SZOFFPSPEC "u", (SZOFFTYPE)pi->pipeinfo.pipe_stat.vst_size); } } void process_pipe(pid, fd) int pid; /* PID */ int32_t fd; /* FD */ { int nb; struct pipe_fdinfo pi; /* * Get pipe file information. */ nb = proc_pidfdinfo(pid, fd, PROC_PIDFDPIPEINFO, &pi, sizeof(pi)); if (nb <= 0) { (void) err2nm("pipe"); return; } else if (nb < sizeof(pi)) { (void) fprintf(stderr, "%s: PID %d, FD %d; proc_pidfdinfo(PROC_PIDFDPIPEINFO);\n", Pn, pid, fd); (void) fprintf(stderr, " too few bytes; expected %ld, got %d\n", sizeof(pi), nb); Exit(1); } process_pipe_common(&pi); } #ifdef PROC_PIDLISTFILEPORTS void process_fileport_pipe(pid, fp) int pid; /* PID */ uint32_t fp; /* FILEPORT */ { int nb; struct pipe_fdinfo pi; /* * Get pipe file information. */ nb = proc_pidfileportinfo(pid, fp, PROC_PIDFILEPORTPIPEINFO, &pi, sizeof(pi)); if (nb <= 0) { (void) err2nm("pipe"); return; } else if (nb < sizeof(pi)) { (void) fprintf(stderr, "%s: PID %d, FILEPORT %u; proc_pidfileportinfo(PROC_PIDFILEPORTPIPEINFO);\n", Pn, pid, fp); (void) fprintf(stderr, " too few bytes; expected %ld, got %d\n", sizeof(pi), nb); Exit(1); } process_pipe_common(&pi); } #endif /* PROC_PIDLISTFILEPORTS */ /* * process_psem() -- process a POSIX semaphore file */ void process_psem(pid, fd) int pid; /* PID */ int32_t fd; /* FD */ { int nb; struct psem_fdinfo ps; /* * Get the sempaphore file information. */ (void) snpf(Lf->type, sizeof(Lf->type), "PSXSEM"); nb = proc_pidfdinfo(pid, fd, PROC_PIDFDPSEMINFO, &ps, sizeof(ps)); if (nb <= 0) { (void) err2nm("semaphore"); return; } else if (nb < sizeof(ps)) { (void) fprintf(stderr, "%s: PID %d, FD %d; proc_pidfdinfo(PROC_PIDFDPSEMINFO);\n", Pn, pid, fd); (void) fprintf(stderr, " too few bytes; expected %ld, got %d\n", sizeof(ps), nb); Exit(1); } /* * Enter the semaphore file information. */ enter_file_info(&ps.pfi); /* * If there is a semaphore file name, enter it. */ if (ps.pseminfo.psem_name[0]) { ps.pseminfo.psem_name[sizeof(ps.pseminfo.psem_name) - 1] = '\0'; (void) snpf(Namech, Namechl, "%s", ps.pseminfo.psem_name); enter_nm(Namech); } /* * Unless file size has been specifically requested, enable the printing of * file offset. */ if (!Fsize) Lf->off_def = 1; } /* * process_pshm() -- process POSIX shared memory file */ static void process_pshm_common(ps) struct pshm_fdinfo *ps; { (void) snpf(Lf->type, sizeof(Lf->type), "PSXSHM"); /* * Enter the POSIX shared memory file information. */ enter_file_info(&ps->pfi); /* * If the POSIX shared memory file has a path name, enter it; otherwise, if it * has a mapping address, enter that. */ if (ps->pshminfo.pshm_name[0]) { ps->pshminfo.pshm_name[sizeof(ps->pshminfo.pshm_name) - 1] = '\0'; (void) snpf(Namech, Namechl, "%s", ps->pshminfo.pshm_name); enter_nm(Namech); } else if (ps->pshminfo.pshm_mappaddr) { (void) snpf(Namech, Namechl, "obj=%s", print_kptr((KA_T)ps->pshminfo.pshm_mappaddr, (char *)NULL, 0)); enter_nm(Namech); } /* * Enable offset or size reporting. */ if (Foffset) Lf->off_def = 1; else { Lf->sz = (SZOFFTYPE)ps->pshminfo.pshm_stat.vst_size; Lf->sz_def = 1; } } void process_pshm(pid, fd) int pid; /* PID */ int32_t fd; /* FD */ { int nb; struct pshm_fdinfo ps; /* * Get the POSIX shared memory file information. */ nb = proc_pidfdinfo(pid, fd, PROC_PIDFDPSHMINFO, &ps, sizeof(ps)); if (nb <= 0) { (void) err2nm("POSIX shared memory"); return; } else if (nb < sizeof(ps)) { (void) fprintf(stderr, "%s: PID %d, FD %d; proc_pidfdinfo(PROC_PIDFDPSHMINFO);\n", Pn, pid, fd); (void) fprintf(stderr, " too few bytes; expected %ld, got %d\n", sizeof(ps), nb); Exit(1); } process_pshm_common(&ps); } #ifdef PROC_PIDLISTFILEPORTS void process_fileport_pshm(pid, fp) int pid; /* PID */ uint32_t fp; /* FILEPORT */ { int nb; struct pshm_fdinfo ps; /* * Get the POSIX shared memory file information. */ nb = proc_pidfileportinfo(pid, fp, PROC_PIDFILEPORTPSHMINFO, &ps, sizeof(ps)); if (nb <= 0) { (void) err2nm("POSIX shared memory"); return; } else if (nb < sizeof(ps)) { (void) fprintf(stderr, "%s: PID %d, FILEPORT %u; proc_pidfileportinfo(PROC_PIDFILEPORTPSHMINFO);\n", Pn, pid, fp); (void) fprintf(stderr, " too few bytes; expected %ld, got %d\n", sizeof(ps), nb); Exit(1); } process_pshm_common(&ps); } #endif /* PROC_PIDLISTFILEPORTS */ /* * process_vnode() -- process a vnode file */ static void process_vnode_common(vi) struct vnode_fdinfowithpath *vi; { /* * Enter the file and vnode information. */ enter_file_info(&vi->pfi); enter_vnode_info(&vi->pvip); } void process_vnode(pid, fd) int pid; /* PID */ int32_t fd; /* FD */ { int nb; struct vnode_fdinfowithpath vi; nb = proc_pidfdinfo(pid, fd, PROC_PIDFDVNODEPATHINFO, &vi, sizeof(vi)); if (nb <= 0) { if (errno == ENOENT) { /* * The file descriptor's vnode may have been revoked. This is a * bit of a hack, since an ENOENT error might not always mean the * descriptor's vnode has been revoked. As the libproc API * matures, this code may need to be revisited. */ enter_nm("(revoked)"); } else (void) err2nm("vnode"); return; } else if (nb < sizeof(vi)) { (void) fprintf(stderr, "%s: PID %d, FD %d: proc_pidfdinfo(PROC_PIDFDVNODEPATHINFO);\n", Pn, pid, fd); (void) fprintf(stderr, " too few bytes; expected %ld, got %d\n", sizeof(vi), nb); Exit(1); } process_vnode_common(&vi); } #ifdef PROC_PIDLISTFILEPORTS void process_fileport_vnode(pid, fp) int pid; /* PID */ uint32_t fp; /* FILEPORT */ { int nb; struct vnode_fdinfowithpath vi; nb = proc_pidfileportinfo(pid, fp, PROC_PIDFILEPORTVNODEPATHINFO, &vi, sizeof(vi)); if (nb <= 0) { if (errno == ENOENT) { /* * The file descriptor's vnode may have been revoked. This is a * bit of a hack, since an ENOENT error might not always mean the * descriptor's vnode has been revoked. As the libproc API * matures, this code may need to be revisited. */ enter_nm("(revoked)"); } else (void) err2nm("vnode"); return; } else if (nb < sizeof(vi)) { (void) fprintf(stderr, "%s: PID %d, FILEPORT %u: proc_pidfdinfo(PROC_PIDFDVNODEPATHINFO);\n", Pn, pid, fp); (void) fprintf(stderr, " too few bytes; expected %ld, got %d\n", sizeof(vi), nb); Exit(1); } process_vnode_common(&vi); } #endif /* PROC_PIDLISTFILEPORTS */ lsof-4.86+dfsg.orig/dialects/darwin/libproc/dmnt.c0000444000175000017500000001226111741061247022275 0ustar nicholasnicholas/* * dmnt.c -- Darwin mount support functions for libproc-based lsof */ /* * Portions Copyright 2005 Apple Computer, Inc. All rights reserved. * * Copyright 2005 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Allan Nathanson, Apple Computer, Inc., and Victor A. * Abell, Purdue University. * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors, nor Apple Computer, Inc. nor Purdue University * are responsible for any consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either * by explicit claim or by omission. Credit to the authors, Apple * Computer, Inc. and Purdue University must appear in documentation * and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 2005 Apple Computer, Inc. and Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dmnt.c,v 1.6 2012/04/10 16:41:04 abe Exp $"; #endif #include "lsof.h" /* * Local static information */ static struct mounts *Lmi = (struct mounts *)NULL; /* local mount info */ static int Lmist = 0; /* Lmi status */ /* * readmnt() -- read mount table */ struct mounts * readmnt() { #if defined(DIR_MNTSTATUS_TRIGGER) struct { uint32_t length; uint32_t mount_flags; } ab; struct attrlist al; #endif /* defined(DIR_MNTSTATUS_TRIGGER) */ char *dn = (char *)NULL; char *ln; struct statfs *mb = (struct statfs *)NULL; struct mounts *mtp; int n; struct stat sb; if (Lmi || Lmist) return(Lmi); /* * Access mount information. */ if ((n = getmntinfo(&mb, MNT_NOWAIT)) <= 0) { (void) fprintf(stderr, "%s: no mount information\n", Pn); return(0); } /* * Read mount information. */ for (; n; n--, mb++) { if (!mb->f_type) continue; /* * Avoid file systems that are not appropriate paths to * user data (e.g. automount maps, triggers). */ #if defined(DIR_MNTSTATUS_TRIGGER) (void) bzero((char *)&al, sizeof(al)); al.bitmapcount = ATTR_BIT_MAP_COUNT; al.dirattr = ATTR_DIR_MOUNTSTATUS; if (getattrlist(mb->f_mntonname, &al, &ab, sizeof(ab), 0) == 0) { if (ab.mount_flags & DIR_MNTSTATUS_TRIGGER) continue; // if mount trigger } #else /* !defined(DIR_MNTSTATUS_TRIGGER) */ if (mb->f_flags & MNT_AUTOMOUNTED) { if (!strncmp(mb->f_mntfromname, "map ", 4) || !strcmp(mb->f_mntfromname, "trigger")) continue; } #endif /* defined(DIR_MNTSTATUS_TRIGGER) */ /* * Interpolate a possible symbolic directory link. */ if (dn) (void) free((FREE_P *)dn); if (!(dn = mkstrcpy(mb->f_mntonname, (MALLOC_S *)NULL))) { no_space_for_mount: (void) fprintf(stderr, "%s: no space for mount at ", Pn); safestrprt(mb->f_mntonname, stderr, 0); (void) fprintf(stderr, " ("); safestrprt(mb->f_mntfromname, stderr, 0); (void) fprintf(stderr, ")\n"); Exit(1); } if (!(ln = Readlink(dn))) { if (!Fwarn) { (void) fprintf(stderr, " Output information may be incomplete.\n"); } continue; } if (ln != dn) { (void) free((FREE_P *)dn); dn = ln; } if (*dn != '/') continue; /* * Stat() the directory. */ if (statsafely(dn, &sb)) { if (!Fwarn) { (void) fprintf(stderr, "%s: WARNING: can't stat() ", Pn); safestrprt(mb->f_fstypename, stderr, 0); (void) fprintf(stderr, " file system "); safestrprt(mb->f_mntonname, stderr, 1); (void) fprintf(stderr, " Output information may be incomplete.\n"); } (void) bzero((char *)&sb, sizeof(sb)); sb.st_dev = (dev_t)mb->f_fsid.val[0]; sb.st_mode = S_IFDIR | 0777; if (!Fwarn) { (void) fprintf(stderr, " assuming \"dev=%x\" from mount table\n", sb.st_dev); } } /* * Allocate and fill a local mount structure. */ if (!(mtp = (struct mounts *)malloc(sizeof(struct mounts)))) goto no_space_for_mount; mtp->dir = dn; dn = (char *)NULL; mtp->next = Lmi; mtp->dev = sb.st_dev; mtp->rdev = sb.st_rdev; mtp->inode = (INODETYPE)sb.st_ino; mtp->mode = sb.st_mode; mtp->is_nfs = strcasecmp(mb->f_fstypename, "nfs") ? 0 : 1; /* * Interpolate a possible file system (mounted-on) device name link. */ if (!(dn = mkstrcpy(mb->f_mntfromname, (MALLOC_S *)NULL))) goto no_space_for_mount; mtp->fsname = dn; ln = Readlink(dn); dn = (char *)NULL; /* * Stat() the file system (mounted-on) name and add file system * information to the local mount table entry. */ if (!ln || statsafely(ln, &sb)) sb.st_mode = 0; mtp->fsnmres = ln; mtp->fs_mode = sb.st_mode; Lmi = mtp; } /* * Clean up and return the local mount info table address. */ if (dn) (void) free((FREE_P *)dn); Lmist = 1; return(Lmi); } lsof-4.86+dfsg.orig/dialects/darwin/libproc/machine.h0000444000175000017500000004053611741061251022745 0ustar nicholasnicholas/* * machine.h -- Darwin definitions for libproc-based lsof */ /* * Portions Copyright 2005 Apple Computer, Inc. All rights reserved. * * Copyright 2005 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Allan Nathanson, Apple Computer, Inc., and Victor A. * Abell, Purdue University. * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors, nor Apple Computer, Inc. nor Purdue University * are responsible for any consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either * by explicit claim or by omission. Credit to the authors, Apple * Computer, Inc. and Purdue University must appear in documentation * and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: machine.h,v 1.9 2012/04/10 16:41:04 abe Exp $ */ #if !defined(LSOF_MACHINE_H) #define LSOF_MACHINE_H 1 #include #include #include "/usr/include/string.h" /* * CAN_USE_CLNT_CREATE is defined for those dialects where RPC clnt_create() * can be used to obtain a CLIENT handle in lieu of clnttcp_create(). */ #define CAN_USE_CLNT_CREATE 1 /* * DEVDEV_PATH defines the path to the directory that contains device * nodes. */ #define DEVDEV_PATH "/dev" /* * GET_MAX_FD is defined for those dialects that provide a function other than * getdtablesize() to obtain the maximum file descriptor number plus one. */ /* #define GET_MAX_FD ? */ /* * HASAOPT is defined for those dialects that have AFS support; it specifies * that the default path to an alternate AFS kernel name list file may be * supplied with the -A option. */ /* #define HASAOPT 1 */ /* * HASBLKDEV is defined for those dialects that want block device information * recorded in BDevtp[]. */ #define HASBLKDEV 1 /* * HASDCACHE is defined for those dialects that support a device cache * file. * * HASENVDC defined the name of an environment variable that contains the * device cache file path. The HASENVDC environment variable is ignored when * the lsof process is setuid(root) or its real UID is 0. * * HASPERSDC defines the format for the last component of a personal device * cache file path. The first will be the home directory of the real UID that * executes lsof. * * HASPERSDCPATH defines the environment variable whose value is the middle * component of the personal device cache file path. The middle component * follows the home directory and precedes the results of applying HASPERSDC. * The HASPERSDCPATH environment variable is ignored when the lsof process is * setuid(root) or its real UID is 0. * * HASSYSDC defines a public device cache file path. When it's defined, it's * used as the path from which to read the device cache. * * Consult the 00DCACHE and 00FAQ files of the lsof distribution for more * information on device cache file path construction. */ /* #define HASDCACHE 1 */ /* #define HASENVDC "LSOFDEVCACHE" */ /* #define HASPERSDC "%h/%p.lsof_%L" */ /* #define HASPERSDCPATH "LSOFPERSDCPATH" */ /* #define HASSYSDC "/your/choice/of/path" */ /* * HASCDRNODE is defined for those dialects that have CD-ROM nodes. */ /* #define HASCDRNODE 1 */ /* * HASFIFONODE is defined for those dialects that have FIFO nodes. */ /* #define HASFIFONODE 1 */ /* * HASFSINO is defined for those dialects that have the file system * inode element, fs_ino, in the lfile structure definition in lsof.h. */ #define HASFSINO 1 /* * HASFSTRUCT is defined if the dialect has a file structure. * * FSV_DEFAULT defines the default set of file structure values to list. * It defaults to zero (0), but may be made up of a combination of the * FSV_* symbols from lsof.h. * * HASNOFSADDR -- has no file structure address * HASNOFSFLAGS -- has no file structure flags * HASNOFSCOUNT -- has no file structure count * HASNOFSNADDR -- has no file structure node address */ #define HASFSTRUCT 1 /* #define FSV_DEFAULT FSV_? | FSV_? | FSV_? */ #define HASNOFSADDR 1 /* has no file structure address */ /* #define HASNOFSFLAGS 1 has no file structure flags */ /* #define HASNOFSCOUNT 1 has no file structure count */ #define HASNOFSNADDR 1 /* has no file structure node address */ /* * HASGNODE is defined for those dialects that have gnodes. */ /* #define HASGNODE 1 */ /* * HASHSNODE is defined for those dialects that have High Sierra nodes. */ /* #define HASHSNODE 1 */ /* * HASINODE is defined for those dialects that have inodes and wish to * use readinode() from node.c. */ /* #define HASINODE 1 */ /* * HASINTSIGNAL is defined for those dialects whose signal function returns * an int. */ /* #define HASINTSIGNAL 1 */ /* * HASKERNIDCK is defined for those dialects that support the comparison of * the build to running kernel identity. */ #define HASKERNIDCK 1 /* * HASKOPT is defined for those dialects that support the -k option of * reading the kernel's name list from an optional file. */ /* #define HASKOPT 1 */ /* * HASLFILEADD is defined for those dialects that need additional elements * in struct lfile. The HASLFILEADD definition is a macro that defines * them. If any of the additional elements need to be preset in the * alloc_lfile() function of proc.c, the SETLFILEADD macro may be defined * to do that. * * If any additional elements need to be cleared in alloc_lfile() or in the * free_proc() function of proc.c, the CLRLFILEADD macro may be defined to * do that. Note that CLRLFILEADD takes one argument, the pointer to the * lfile struct. The CLRLFILEADD macro is expected to expand to statements * that are complete -- i.e., have terminating semi-colons -- so the macro is * called without a terminating semicolon by proc.c. * * The HASXOPT definition may be used to select the conditions under which * private lfile elements are used. */ #define HASLFILEADD char *V_path; \ mach_port_t fileport; #define CLRLFILEADD(lf) if (lf->V_path) { \ (void) free((FREE_P *)lf->V_path); \ lf->V_path = (char *)NULL; \ } \ lf->fileport = MACH_PORT_NULL; #define SETLFILEADD Lf->V_path = (char *)NULL; \ Lf->fileport = MACH_PORT_NULL; /* * HASMNTSTAT indicates the dialect supports the mount stat(2) result option * in its l_vfs and mounts structures. */ /* #define HASMNTSTAT 1 */ /* * HASMNTSUP is defined for those dialects that support the mount supplement * option. */ /* #define HASMNTSUP 1 */ /* * HASMOPT is defined for those dialects that support the reading of * kernel memory from an alternate file. */ /* #define HASMOPT 1 */ /* * HASNCACHE is defined for those dialects that have a kernel name cache * that lsof can search. A value of 1 directs printname() to prefix the * cache value with the file system directory name; 2, avoid the prefix. * * NCACHELDPFX is a set of C commands to execute before calling ncache_load(). * * NCACHELDSFX is a set of C commands to execute after calling ncache_load(). */ /* #define HASNCACHE 1 */ /* #define NCACHELDPFX ??? */ /* #define NCACHELDSFX ??? */ /* * HASNLIST is defined for those dialects that use nlist() to acccess * kernel symbols. */ /* #define HASNLIST 1 */ /* * HASPIPEFN is defined for those dialects that have a special function to * process DTYPE_PIPE file structure entries. Its value is the name of the * function. * * NOTE: don't forget to define a prototype for this function in dproto.h. */ /* #define HASPIPEFN process_pipe? */ /* * HASPIPENODE is defined for those dialects that have pipe nodes. */ /* #define HASPIPENODE 1 */ /* * HASPMAPENABLED is defined when the reporting of portmapper registration * info is enabled by default. */ /* #define HASPMAPENABLED 1 */ /* * HASPPID is defined for those dialects that support identification of * the parent process IDentifier (PPID) of a process. */ #define HASPPID 1 /* * HASPRINTDEV, HASPRINTINO, HASPRINTNM, HASPRINTOFF, and HASPRINTSZ * define private dialect-specific functions for printing DEVice numbers, * INOde numbers, NaMes, file OFFsets, and file SiZes. The functions are * called from print_file(). */ /* #define HASPRINTDEV print_dev */ /* #define HASPRINTINO print_ino? */ #define HASPRINTNM print_nm /* #define HASPRINTOFF print_off? */ /* #define HASPRINTSZ print_sz? */ /* * HASPRIVFILETYPE and PRIVFILETYPE are defined for dialects that have a * file structure type that isn't defined by a DTYPE_* symbol. They are * used in lib/prfp.c to select the type's processing. * * PRIVFILETYPE is the definition of the f_type value in the file struct. * * HASPRIVFILETYPE is the name of the processing function. */ /* #define HASPRIVFILETYPE process_shmf? */ /* #define PRIVFILETYPE ?? */ /* * HASPRIVNMCACHE is defined for dialects that have a private method for * printing cached NAME column values for some files. HASPRIVNAMECACHE * is defined to be the name of the function. * * The function takes one argument, a struct lfile pointer to the file, and * returns non-zero if it prints a name to stdout. */ #define HASPRIVNMCACHE print_v_path /* * HASPRIVPRIPP is defined for dialects that have a private function for * printing IP protocol names. When HASPRIVPRIPP isn't defined, the * IP protocol name printing function defaults to printiprto(). */ /* #define HASPRIVPRIPP 1 */ /* * HASPROCFS is defined for those dialects that have a proc file system -- * usually /proc and usually in SYSV4 derivatives. * * HASFSTYPE is defined as 1 for those systems that have a file system type * string, st_fstype, in the stat() buffer; 2, for those systems that have a * file system type integer in the stat() buffer, named MOUNTS_STAT_FSTYPE; * 0, for systems whose stat(2) structure has no file system type member. The * additional symbols MOUNTS_FSTYPE, RMNT_FSTYPE, and RMNT_STAT_FSTYPE may be * defined in dlsof.h to direct how the readmnt() function in lib/rmnt.c * preserves these stat(2) and getmntent(3) buffer values in the local mounts * structure. * * The defined value is the string that names the file system type. * * The HASPROCFS definition usually must be accompanied by the HASFSTYPE * definition and the providing of an fstype element in the local mounts * structure (defined in dlsof.h). * * The HASPROCFS definition may be accompanied by the HASPINODEN definition. * HASPINODEN specifies that searching for files in HASPROCFS is to be done * by inode number. */ /* #define HASPROCFS "proc?" */ /* #define HASFSTYPE 1 */ /* #define HASPINODEN 1 */ /* * HASRNODE is defined for those dialects that have rnodes. */ /* #define HASRNODE 1 */ /* * Define HASSECURITY to restrict the listing of all open files to the * root user. When HASSECURITY is defined, the non-root user may list * only files whose processes have the same user ID as the real user ID * (the one that its user logged on with) of the lsof process. */ /* #define HASSECURITY 1 */ /* * If HASSECURITY is defined, define HASNOSOCKSECURITY to allow users * restricted by HASSECURITY to list any open socket files, provide their * listing is selected by the "-i" option. */ /* #define HASNOSOCKSECURITY 1 */ /* * HASSETLOCALE is defined for those dialects that have 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 */ /* * HASSNODE is defined for those dialects that have snodes. */ /* #define HASSNODE 1 */ /* * HASTASKS is defined for those dialects that have task reporting support. */ /* #define HASTASKS 1 */ /* * HASSOOPT, HASSOSTATE and HASTCPOPT define the availability of information * on socket options (SO_* symbols), socket states (SS_* symbols) and TCP * options. */ #define HASSOOPT 1 /* has socket option information */ #define HASSOSTATE 1 /* has socket state information */ #define HASTCPOPT 1 /* has TCP options or flags */ /* * Define HASSPECDEVD to be the name of a function that handles the results * of a successful stat(2) of a file name argument. * * For example, HASSPECDEVD() for Darwin makes sure that st_dev is set to * what stat("/dev") returns -- i.e., what's in DevDev. * * The function takes two arguments: * * 1: pointer to the full path name of file * 2: pointer to the stat(2) result * * The function returns void. */ #define HASSPECDEVD process_dev_stat /* * HASSTREAMS is defined for those dialects that support streams. */ /* #define HASSTREAMS 1 */ /* * HASTCPTPIQ is defined for dialects where it is possible to report the * TCP/TPI Recv-Q and Send-Q values produced by netstat. */ #define HASTCPTPIQ 1 /* * HASTCPTPIW is defined for dialects where it is possible to report the * TCP/TPI send and receive window sizes produced by netstat. */ /* #define HASTCPTPIW 1 */ /* * HASTCPUDPSTATE is defined for dialects that have TCP and UDP state * support -- i.e., for the "-stcp|udp:state" option and its associated * speed improvements. */ #define HASTCPUDPSTATE 1 /* * HASTMPNODE is defined for those dialects that have tmpnodes. */ /* #define HASTMPNODE 1 */ /* * HASVNODE is defined for those dialects that use the Sun virtual file system * node, the vnode. BSD derivatives usually do; System V derivatives prior to * R4 usually don't. */ /* #define HASVNODE 1 */ /* * HASXOPT is defined for those dialects that have an X option. It * defines the text for the usage display. HASXOPT_VALUE defines the * option's default binary value -- 0 or 1. */ /* #define HASXOPT "help text for X option" */ /* #define HASXOPT_VALUE 1 */ /* * INODETYPE and INODEPSPEC define the internal node number type and its * printf specification modifier. These need not be defined and lsof.h * can be allowed to define defaults. * * These are defined here, because they must be used in dlsof.h. */ #define INODETYPE unsigned long long /* inode number internal storage type */ #define INODEPSPEC "ll" /* INODETYPE printf specification * modifier */ /* * UID_ARG defines the size of a User ID number when it is passed * as a function argument. */ #define UID_ARG int /* * Each USE_LIB_ is defined for dialects that use the * in the lsof library. * * Note: other definitions and operations may be required to condition the * library function source code. They may be found in the dialect dlsof.h * header files. */ #define USE_LIB_CKKV 1 /* ckkv.c */ /* #define USE_LIB_COMPLETEVFS 1 cvfs.c */ #define USE_LIB_FIND_CH_INO 1 /* fino.c */ #define USE_LIB_IS_FILE_NAMED 1 /* isfn.c */ #define USE_LIB_LKUPDEV 1 /* lkud.c */ /* #define USE_LIB_PRINTDEVNAME 1 pdvn.c */ /* #define USE_LIB_PROCESS_FILE 1 prfp.c */ #define USE_LIB_PRINT_TCPTPI 1 /* ptti.c */ /* #define USE_LIB_READDEV 1 rdev.c */ /* #define USE_LIB_READMNT 1 rmnt.c */ /* #define USE_LIB_REGEX 1 regex.c */ /* #define USE_LIB_RNAM 1 rnam.c */ /* #define USE_LIB_RNCH 1 rnch.c */ /* #define USE_LIB_RNMH 1 rnmh.c */ /* #define USE_LIB_SNPF 1 snpf.c */ #define snpf snprintf /* use the system's snprintf() */ /* * WARNDEVACCESS is defined for those dialects that should issue a warning * when lsof can't access /dev (or /device) or one of its sub-directories. * The warning can be inhibited by the lsof caller with the -w option. */ /* #define WARNDEVACCESS 1 */ /* * WARNINGSTATE is defined for those dialects that want to suppress all lsof * warning messages. */ /* #define WARNINGSTATE 1 warnings are enabled by default */ /* * WILLDROPGID is defined for those dialects whose lsof executable runs * setgid(not_real_GID) and whose setgid power can be relinquished after * the dialect's initialize() function has been executed. */ #define WILLDROPGID 1 /* * zeromem is a macro that uses bzero or memset. */ #define zeromem(a, l) memset(a, 0, l) #endif /* !defined(LSOF_MACHINE_H) */ lsof-4.86+dfsg.orig/dialects/darwin/libproc/Makefile0000444000175000017500000001066411162502103022620 0ustar nicholasnicholas # Darwin libproc-based lsof Makefile # # $Id: Makefile,v 1.7 2009/03/25 19:21:37 abe Exp $ PROG= lsof BIN= ${DSTROOT}/usr/sbin DOC= ${DSTROOT}/usr/share/man/man8 I=/usr/include S=/usr/include/sys L=/usr/include/local P= CDEF= ${RC_CFLAGS} CDEFS= ${CDEF} ${CFGF} INCL= ${DINC} override CFLAGS= ${CDEFS} ${INCL} ${DEBUG} GRP= wheel HDR= lsof.h lsof_fields.h dlsof.h machine.h proto.h dproto.h SRC= ddev.c dfile.c dmnt.c dproc.c dsock.c dstore.c \ arg.c main.c misc.c node.c print.c proc.c store.c usage.c util.c OBJ= ddev.o dfile.o dmnt.o dproc.o dsock.o dstore.o \ arg.o main.o misc.o node.o print.o proc.o store.o usage.o util.o MAN= lsof.8 OTHER= SHELL= /bin/sh SOURCE= Makefile ${OTHER} ${MAN} ${HDR} ${SRC} all: ${PROG} ${PROG}: ${LIB} ${P} ${OBJ} ${CC} -o $@ ${CFLAGS} ${OBJ} ${CFGL} clean: FRC rm -f Makefile.bak ${PROG} a.out core errs lint.out tags *.o version.h rm -f machine.h.old new_machine.h (cd lib; ${MAKE} -f Makefile.skel clean) install-strip: all FRC @if [ -n "${SYMROOT}" ]; then \ mkdir -p ${SYMROOT}; \ cp -p ${PROG} ${SYMROOT}/${PROG}; \ fi mkdir -p ${BIN} install -c -s -m 755 -g ${GRP} ${PROG} ${BIN} mkdir -p ${DOC} install -c -m 444 ${MAN} ${DOC} install: all FRC @echo '' @echo 'Please write your own install rule. Lsof for Darwin below 8' @echo 'should be installed setgid to the group that has permission' @echo 'to read /dev/kmem, often kmem or sys. Lsof for Darwin 8 and' @echo 'above should be installed setuid-root. Your install rule' @echo 'actions for Darwin below 8 might look something like this:' @echo '' @echo ' install -m 2xxx -g $${GRP} $${PROG} $${BIN}' @echo ' install -m 444 $${MAN} $${DOC}' @echo '' @echo 'Your install rule actions for Darwin 8 and above might look' @echo 'something like this:' @echo '' @echo ' install -m 4xxx -o root $${PROG} $${BIN}' @echo ' install -m 444 $${MAN} $${DOC}' @echo '' @echo 'You will have to complete the xxx modes, the GRP value, and' @echo 'the skeletons for the BIN and DOC strings, given at the' @echo 'beginning of this Makefile, e.g.,' @echo '' @echo ' BIN= $${DESTDIR}/usr/local/etc' @echo ' DOC= $${DESTDIR}/usr/man/man8' @echo ' GRP= kmem' @echo '' ${LIB}: FRC (cd lib; ${MAKE} DEBUG="${DEBUG}" CFGF="${CFGF}") version.h: FRC @echo Constructing version.h @rm -f version.h @echo '#define LSOF_BLDCMT "${LSOF_BLDCMT}"' > version.h; @echo '#define LSOF_CC "${CC}"' >> version.h @echo '#define LSOF_CCV "${CCV}"' >> version.h @echo '#define LSOF_CCDATE "'`date`'"' >> version.h @echo '#define LSOF_CCFLAGS "'`echo ${CFLAGS} | sed 's/\\\\(/\\(/g' | sed 's/\\\\)/\\)/g' | sed 's/"/\\\\"/g'`'"' >> version.h @echo '#define LSOF_CINFO "${CINFO}"' >> version.h @if [ "X${LSOF_HOST}" = "X" ]; then \ echo '#define LSOF_HOST "'`uname -n`'"' >> version.h; \ else \ if [ "${LSOF_HOST}" = "none" ]; then \ echo '#define LSOF_HOST ""' >> version.h; \ else \ echo '#define LSOF_HOST "${LSOF_HOST}"' >> version.h; \ fi \ fi @echo '#define LSOF_LDFLAGS "${CFGL}"' >> version.h @if [ "X${LSOF_LOGNAME}" = "X" ]; then \ echo '#define LSOF_LOGNAME "${LOGNAME}"' >> version.h; \ else \ if [ "${LSOF_LOGNAME}" = "none" ]; then \ echo '#define LSOF_LOGNAME ""' >> version.h; \ else \ echo '#define LSOF_LOGNAME "${LSOF_LOGNAME}"' >> version.h; \ fi; \ fi @if [ "X${LSOF_SYSINFO}" = "X" ]; then \ echo '#define LSOF_SYSINFO "'`uname -a`'"' >> version.h; \ else \ if [ "${LSOF_SYSINFO}" = "none" ]; then \ echo '#define LSOF_SYSINFO ""' >> version.h; \ else \ echo '#define LSOF_SYSINFO "${LSOF_SYSINFO}"' >> version.h; \ fi \ fi @if [ "X${LSOF_USER}" = "X" ]; then \ echo '#define LSOF_USER "${USER}"' >> version.h; \ else \ if [ "${LSOF_USER}" = "none" ]; then \ echo '#define LSOF_USER ""' >> version.h; \ else \ echo '#define LSOF_USER "${LSOF_USER}"' >> version.h; \ fi \ fi @sed '/VN/s/.ds VN \(.*\)/#define LSOF_VERSION "\1"/' < version >> version.h FRC: # DO NOT DELETE THIS LINE - make depend DEPENDS ON IT ddev.o: ${HDR} ddev.c dfile.o: ${HDR} dfile.c dmnt.o: ${HDR} dmnt.c dproc.o: ${HDR} dproc.c dsock.o: ${HDR} dsock.c dstore.o: ${HDR} dstore.c arg.o: ${HDR} arg.c main.o: ${HDR} main.c misc.o: ${HDR} misc.c node.o: ${HDR} node.c print.o: ${HDR} print.c proc.o: ${HDR} proc.c store.o: ${HDR} store.c usage.o: ${HDR} version.h usage.c util.o: ${HDR} util.c # *** Do not add anything here - It will go away. *** lsof-4.86+dfsg.orig/dialects/darwin/kmem/0000755000175000017500000000000011741064216020465 5ustar nicholasnicholaslsof-4.86+dfsg.orig/dialects/darwin/kmem/dstore.c0000444000175000017500000000524310331747446022142 0ustar nicholasnicholas/* * dstore.c - Darwin global storage for /dev/kmem-based lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dstore.c,v 1.5 2005/11/01 20:24:51 abe Exp $"; #endif #include "lsof.h" struct file *Cfp; /* curent file's file struct pointer */ /* * Drive_Nl -- table to drive the building of Nl[] via build_Nl() * (See lsof.h and misc.c.) */ struct drive_Nl Drive_Nl[] = { { "aproc", "_allproc" }, { "nproc", "_nprocs" }, { X_NCACHE, "_nchashtbl" }, { X_NCSIZE, "_nchash" }, { "", "" }, { NULL, NULL } }; int Kd = -1; /* KMEM descriptor */ KA_T Kpa; /* kernel proc struct address */ struct l_vfs *Lvfs = NULL; /* local vfs structure table */ int Np = 0; /* number of kernel processes */ struct kinfo_proc *P = NULL; /* local process table copy */ #if defined(HASFSTRUCT) /* * Pff_tab[] - table for printing file flags */ struct pff_tab Pff_tab[] = { { (long)FREAD, FF_READ }, { (long)FWRITE, FF_WRITE }, { (long)FNONBLOCK, FF_NBLOCK }, { (long)FNDELAY, FF_NDELAY }, { (long)FAPPEND, FF_APPEND }, { (long)FASYNC, FF_ASYNC }, { (long)FFSYNC, FF_FSYNC }, { (long)FMARK, FF_MARK }, { (long)FDEFER, FF_DEFER }, { (long)FHASLOCK, FF_HASLOCK }, { (long)O_NOCTTY, FF_NOCTTY }, { (long)O_EVTONLY, FF_EVTONLY }, { (long)0, NULL } }; /* * Pof_tab[] - table for print process open file flags */ struct pff_tab Pof_tab[] = { # if defined(UF_EXCLOSE) { (long)UF_EXCLOSE, POF_CLOEXEC }, # endif /* defined(UF_EXCLOSE) */ # if defined(UF_MAPPED) { (long)UF_MAPPED, POF_MAPPED }, # endif /* defined(UF_MAPPED) */ { (long)0, NULL } }; #endif /* defined(HASFSTRUCT) */ lsof-4.86+dfsg.orig/dialects/darwin/kmem/ddev.c0000444000175000017500000002535610412072107021554 0ustar nicholasnicholas/* * ddev.c - Darwin device support functions for /dev/kmem-based lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: ddev.c,v 1.5 2006/03/27 23:24:50 abe Exp $"; #endif #include "lsof.h" /* * Local definitions */ #if defined(DVCH_DEVPATH) #define DDEV_DEVPATH DVCH_DEVPATH #else /* !defined(DVCH_DEVPATH) */ #define DDEV_DEVPATH "/dev" #endif /* defined(DVCH_DEVPATH) */ #if defined(USE_STAT) #define STATFN stat #else /* !defined(USE_STAT) */ #define STATFN lstat #endif /* defined(USE_STAT) */ /* * Local static variables. */ static dev_t *ADev = (dev_t *) NULL; /* device numbers besides DevDev found * inside DDEV_DEVPATH */ static int ADevA = 0; /* entries allocated to ADev[] */ static int ADevU = 0; /* entries used in ADev[] */ /* * Local function prototypes */ _PROTOTYPE(static int rmdupdev,(struct l_dev ***dp, int n, char *nm)); _PROTOTYPE(static void saveADev,(struct stat *s)); #if defined(HASSPECDEVD) /* * HASSPECDEVD() -- process stat(2) result to see if the device number is * inside DDEV_DEVPATH "/" * * exit: s->st_dev changed to DevDev, as required */ void HASSPECDEVD(p, s) char *p; /* file path */ struct stat *s; /* stat(2) result for file */ { int i; switch (s->st_mode & S_IFMT) { case S_IFCHR: case S_IFBLK: if (s->st_dev == DevDev) return; (void) readdev(0); if (!ADev) return; for (i = 0; i < ADevU; i++) { if (s->st_dev == ADev[i]) { s->st_dev = DevDev; return; } } } } #endif /* defined(HASSPECDEVD) */ /* * readdev() - read device names, modes and types */ void readdev(skip) int skip; /* skip device cache read if 1 -- * ignored since device cache not * used */ { DIR *dfp; int dnamlen; struct dirent *dp; char *fp = (char *)NULL; char *path = (char *)NULL; int i = 0; int j = 0; MALLOC_S pl, sz; struct stat sb; /* * Read device names but once. */ if (Sdev) return; /* * Prepare to scan DDEV_DEVPATH. */ Dstkn = Dstkx = 0; Dstk = (char **)NULL; (void) stkdir(DDEV_DEVPATH); /* * Unstack the next directory. */ while (--Dstkx >= 0) { if (!(dfp = OpenDir(Dstk[Dstkx]))) { # if defined(WARNDEVACCESS) if (!Fwarn) { (void) fprintf(stderr, "%s: WARNING: can't open: ", Pn); safestrprt(Dstk[Dstkx], stderr, 1); } # endif /* defined(WARNDEVACCESS) */ (void) free((FREE_P *)Dstk[Dstkx]); Dstk[Dstkx] = (char *)NULL; continue; } if (path) { (void) free((FREE_P *)path); path = (char *)NULL; } if (!(path = mkstrcat(Dstk[Dstkx], -1, "/", 1, (char *)NULL, -1, &pl))) { (void) fprintf(stderr, "%s: no space for: ", Pn); safestrprt(Dstk[Dstkx], stderr, 1); Exit(1); } (void) free((FREE_P *)Dstk[Dstkx]); Dstk[Dstkx] = (char *)NULL; /* * Scan the directory. */ for (dp = ReadDir(dfp); dp; dp = ReadDir(dfp)) { if (dp->d_ino == 0 || dp->d_name[0] == '.') continue; /* * Form the full path name and get its status. */ dnamlen = (int)dp->d_namlen; if (fp) { (void) free((FREE_P *)fp); fp = (char *)NULL; } if (!(fp = mkstrcat(path, pl, dp->d_name, dnamlen, (char *)NULL, -1, (MALLOC_S *)NULL))) { (void) fprintf(stderr, "%s: no space for: ", Pn); safestrprt(path, stderr, 0); safestrprtn(dp->d_name, dnamlen, stderr, 1); Exit(1); } if (STATFN(fp, &sb) != 0) { if (errno == ENOENT) /* a sym link to nowhere? */ continue; # if defined(WARNDEVACCESS) if (!Fwarn) { int errno_save = errno; (void) fprintf(stderr, "%s: can't stat ", Pn); safestrprt(fp, stderr, 0); (void) fprintf(stderr, ": %s\n", strerror(errno_save)); } # endif /* defined(WARNDEVACCESS) */ continue; } /* * If it's a subdirectory, stack its name for later * processing. */ if ((sb.st_mode & S_IFMT) == S_IFDIR) { /* * Skip /dev/fd. */ if (strcmp(fp, "/dev/fd")) (void) stkdir(fp); continue; } if ((sb.st_mode & S_IFMT) == S_IFLNK) { /* * Ignore symbolic links. */ continue; } if ((sb.st_mode & S_IFMT) == S_IFCHR) { /* * Save character device information in Devtp[]. */ if (i >= Ndev) { Ndev += DEVINCR; if (!Devtp) Devtp = (struct l_dev *)malloc( (MALLOC_S)(sizeof(struct l_dev)*Ndev)); else Devtp = (struct l_dev *)realloc((MALLOC_P *)Devtp, (MALLOC_S)(sizeof(struct l_dev)*Ndev)); if (!Devtp) { (void) fprintf(stderr, "%s: no space for character device\n", Pn); Exit(1); } } Devtp[i].rdev = sb.st_rdev; Devtp[i].inode = (INODETYPE)sb.st_ino; if (!(Devtp[i].name = mkstrcpy(fp, (MALLOC_S *)NULL))) { (void) fprintf(stderr, "%s: no space for device name: ", Pn); safestrprt(fp, stderr, 1); Exit(1); } Devtp[i].v = 0; i++; } # if defined(HASBLKDEV) if ((sb.st_mode & S_IFMT) == S_IFBLK) { /* * Save block device information in BDevtp[]. */ if (j >= BNdev) { BNdev += DEVINCR; if (!BDevtp) BDevtp = (struct l_dev *)malloc( (MALLOC_S)(sizeof(struct l_dev)*BNdev)); else BDevtp = (struct l_dev *)realloc((MALLOC_P *)BDevtp, (MALLOC_S)(sizeof(struct l_dev)*BNdev)); if (!BDevtp) { (void) fprintf(stderr, "%s: no space for block device\n", Pn); Exit(1); } } BDevtp[j].name = fp; fp = (char *)NULL; BDevtp[j].inode = (INODETYPE)sb.st_ino; BDevtp[j].rdev = sb.st_rdev; BDevtp[j].v = 0; j++; } # endif /* defined(HASBLKDEV) */ /* * Save a possible new st_dev number within DDEV_DEVPATH. */ if (sb.st_dev != DevDev) (void) saveADev(&sb); } (void) CloseDir(dfp); } /* * Free any unneeded space that was allocated. */ if (ADev && (ADevU < ADevA)) { /* * Reduce space allocated to additional DDEV_DEVPATH device numbers. */ if (!ADevU) { /* * If no space was used, free the entire allocation. */ (void) free((FREE_P *)ADev); ADev = (dev_t *)NULL; ADevA = 0; } else { /* * Reduce the allocation to what was used. */ sz = (MALLOC_S)(ADevU * sizeof(dev_t)); if (!(ADev = (dev_t *)realloc((MALLOC_P *)ADev, sz))) { (void) fprintf(stderr, "%s: can't reduce ADev[]\n", Pn); Exit(1); } } } if (!Dstk) { (void) free((FREE_P *)Dstk); Dstk = (char **)NULL; } if (fp) (void) free((FREE_P *)fp); if (path) (void) free((FREE_P *)path); # if defined(HASBLKDEV) /* * Reduce the BDevtp[] (optional) and Devtp[] tables to their minimum * sizes; allocate and build sort pointer lists; and sort the tables by * device number. */ if (BNdev) { if (BNdev > j) { BNdev = j; BDevtp = (struct l_dev *)realloc((MALLOC_P *)BDevtp, (MALLOC_S)(sizeof(struct l_dev) * BNdev)); } if (!(BSdev = (struct l_dev **)malloc( (MALLOC_S)(sizeof(struct l_dev *) * BNdev)))) { (void) fprintf(stderr, "%s: no space for block device sort pointers\n", Pn); Exit(1); } for (j = 0; j < BNdev; j++) { BSdev[j] = &BDevtp[j]; } (void) qsort((QSORT_P *)BSdev, (size_t)BNdev, (size_t)sizeof(struct l_dev *), compdev); BNdev = rmdupdev(&BSdev, BNdev, "block"); } # if !defined(NOWARNBLKDEV) else { if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: no block devices found\n", Pn); } # endif /* !defined(NOWARNBLKDEV) */ # endif /* defined(HASBLKDEV) */ if (Ndev) { if (Ndev > i) { Ndev = i; Devtp = (struct l_dev *)realloc((MALLOC_P *)Devtp, (MALLOC_S)(sizeof(struct l_dev) * Ndev)); } if (!(Sdev = (struct l_dev **)malloc( (MALLOC_S)(sizeof(struct l_dev *) * Ndev)))) { (void) fprintf(stderr, "%s: no space for character device sort pointers\n", Pn); Exit(1); } for (i = 0; i < Ndev; i++) { Sdev[i] = &Devtp[i]; } (void) qsort((QSORT_P *)Sdev, (size_t)Ndev, (size_t)sizeof(struct l_dev *), compdev); Ndev = rmdupdev(&Sdev, Ndev, "char"); } else { (void) fprintf(stderr, "%s: no character devices found\n", Pn); Exit(1); } } /* * rmdupdev() - remove duplicate (major/minor/inode) devices */ static int rmdupdev(dp, n, nm) struct l_dev ***dp; /* device table pointers address */ int n; /* number of pointers */ char *nm; /* device table name for error message */ { int i, j, k; struct l_dev **p; for (i = j = 0, p = *dp; i < n ;) { for (k = i + 1; k < n; k++) { if (p[i]->rdev != p[k]->rdev || p[i]->inode != p[k]->inode) break; } if (i != j) p[j] = p[i]; j++; i = k; } if (n == j) return(n); if (!(*dp = (struct l_dev **)realloc((MALLOC_P *)*dp, (MALLOC_S)(j * sizeof(struct l_dev *))))) { (void) fprintf(stderr, "%s: can't realloc %s device pointers\n", Pn, nm); Exit(1); } return(j); } /* * saveADev() - save additional device number appearing inside DDEV_DEVPATH */ static void saveADev(s) struct stat *s; /* stat(2) buffer for file */ { int i; MALLOC_S sz; /* * Process VCHR files. * * Optionally process VBLK files. */ #if defined(HASBLKDEV) if (((s->st_mode & S_IFMT) != S_IFBLK) && ((s->st_mode & S_IFMT) != S_IFCHR)) #else /* !defined(HASBLKDEV) */ if ((s->st_mode & S_IFCHR) != S_IFCHR) #endif /* defined(HASBLKDEV) */ return; /* * See if this is a new VBLK or VCHR st_dev value for ADev[]. */ for (i = 0; i < ADevU; i++) { if (s->st_dev == ADev[i]) return; } /* * This is a new device number to add to ADev[]. */ if (ADevU >= ADevA) { ADevA += 16; sz = (MALLOC_S)(ADevA * sizeof(dev_t)); if (ADev) ADev = (dev_t *)realloc((MALLOC_P *)ADev, sz); else ADev = (dev_t *)malloc(sz); if (!ADev) { (void) fprintf(stderr, "%s: no space for ADev[]\n", Pn); Exit(1); } } ADev[ADevU++] = s->st_dev; } lsof-4.86+dfsg.orig/dialects/darwin/kmem/dsock.c0000444000175000017500000003055410331747445021747 0ustar nicholasnicholas/* * dsock.c - Darwin socket processing functions for /dev/kmem-based lsof */ /* * Special Darwin socket info: Justin Walker, 000927 */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dsock.c,v 1.11 2005/11/01 20:24:51 abe Exp $"; #endif #include "lsof.h" #if defined(HASIPv6) /* * IPv6_2_IPv4() -- macro to define the address of an IPv4 address contained * in an IPv6 address */ #define IPv6_2_IPv4(v6) (((uint8_t *)((struct in6_addr *)v6)->s6_addr)+12) #endif /* defined(HASIPv6) */ /* * process_socket() - process socket */ void process_socket(sa) KA_T sa; /* socket address in kernel */ { struct domain d; unsigned char *fa = (unsigned char *)NULL; int fam, lp; int fp = 0; struct inpcb inp; unsigned char *la = (unsigned char *)NULL; struct protosw p; struct socket s; struct tcpcb t; KA_T ta = (KA_T)NULL; struct unpcb uc, unp; struct sockaddr_un *ua = NULL; struct sockaddr_un un; int unl; #if defined(HASIPv6) struct in6pcb in6p; #endif /* defined(HASIPv6) */ #if defined(AF_SYSTEM) struct kern_event_pcb kev_cb; #endif /* defined(AF_SYSTEM) */ #if defined(AF_NDRV) char buf[IFNAMSIZ]; struct ndrv_cb ndrv_cb; struct ifnet ifnet; #endif /* defined(AF_NDRV) */ (void) snpf(Lf->type, sizeof(Lf->type), "sock"); Lf->inp_ty = 2; /* * Read the socket, protocol, and domain structures. */ if (!sa) { enter_nm("no socket address"); return; } if (kread(sa, (char *)&s, sizeof(s))) { (void) snpf(Namech, Namechl, "can't read socket struct from %s", print_kptr(sa, (char *)NULL, 0)); enter_nm(Namech); return; } if (!s.so_type) { enter_nm("no socket type"); return; } if (!s.so_proto || kread((KA_T)s.so_proto, (char *)&p, sizeof(p))) { (void) snpf(Namech, Namechl, "can't read protocol switch from %s", print_kptr((KA_T)s.so_proto, (char *)NULL, 0)); enter_nm(Namech); return; } if (!p.pr_domain || kread((KA_T)p.pr_domain, (char *)&d, sizeof(d))) { (void) snpf(Namech, Namechl, "can't read domain struct from %s", print_kptr((KA_T)p.pr_domain, (char *)NULL, 0)); enter_nm(Namech); return; } /* * Save size information. */ if (Fsize) { if (Lf->access == 'r') Lf->sz = (SZOFFTYPE)s.so_rcv.sb_cc; else if (Lf->access == 'w') Lf->sz = (SZOFFTYPE)s.so_snd.sb_cc; else Lf->sz = (SZOFFTYPE)(s.so_rcv.sb_cc + s.so_snd.sb_cc); Lf->sz_def = 1; } else Lf->off_def = 1; #if defined(HASTCPTPIQ) Lf->lts.rq = s.so_rcv.sb_cc; Lf->lts.sq = s.so_snd.sb_cc; Lf->lts.rqs = Lf->lts.sqs = 1; #endif /* defined(HASTCPTPIQ) */ #if defined(HASSOOPT) Lf->lts.ltm = (unsigned int)(s.so_linger & 0xffff); Lf->lts.opt = (unsigned int)(s.so_options & 0xffff); Lf->lts.pqlen = (unsigned int)s.so_incqlen; Lf->lts.qlen = (unsigned int)s.so_qlen; Lf->lts.qlim = (unsigned int)s.so_qlimit; Lf->lts.rbsz = (unsigned long)s.so_rcv.sb_mbmax; Lf->lts.sbsz = (unsigned long)s.so_snd.sb_mbmax; Lf->lts.pqlens = Lf->lts.qlens = Lf->lts.qlims = Lf->lts.rbszs = Lf->lts.sbszs = (unsigned char)1; #endif /* defined(HASSOOPT) */ #if defined(HASSOSTATE) Lf->lts.ss = (unsigned int)s.so_state; #endif /* defined(HASSOSTATE) */ /* * Process socket by the associated domain family. */ switch ((fam = d.dom_family)) { /* * Process an Internet domain socket. */ case AF_INET: #if defined(HASIPv6) case AF_INET6: #endif /* defined(HASIPv6) */ if (Fnet) { if (!FnetTy || ((FnetTy == 4) && (fam == AF_INET)) #if defined(HASIPv6) || ((FnetTy == 6) && (fam == AF_INET6)) #endif /* defined(HASIPv6) */ ) Lf->sf |= SELNET; } printiproto(p.pr_protocol); #if defined(HASIPv6) (void) snpf(Lf->type, sizeof(Lf->type), (fam == AF_INET) ? "IPv4" : "IPv6"); #else /* !defined(HASIPv6) */ (void) snpf(Lf->type, sizeof(Lf->type), "inet"); #endif /* defined(HASIPv6) */ #if defined(HASIPv6) if (fam == AF_INET6) { /* * Read IPv6 protocol control block. */ if (!s.so_pcb || kread((KA_T)s.so_pcb, (char *)&in6p, sizeof(in6p))) { (void) snpf(Namech, Namechl, "can't read in6pcb at %s", print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); enter_nm(Namech); return; } /* * Save IPv6 address information. */ enter_dev_ch(print_kptr((KA_T)(in6p.in6p_ppcb ? in6p.in6p_ppcb : s.so_pcb), (char *)NULL, 0)); if (p.pr_protocol == IPPROTO_TCP) ta = (KA_T)in6p.in6p_ppcb; la = (unsigned char *)&in6p.in6p_laddr; lp = (int)ntohs(in6p.in6p_lport); if (!IN6_IS_ADDR_UNSPECIFIED(&in6p.in6p_faddr) || in6p.in6p_fport) { fa = (unsigned char *)&in6p.in6p_faddr; fp = (int)ntohs(in6p.in6p_fport); } } else #endif /* defined(HASIPv6) */ { /* * Read IPv4 protocol control block. */ if (!s.so_pcb || kread((KA_T)s.so_pcb, (char *)&inp, sizeof(inp))) { if (!s.so_pcb) { (void) snpf(Namech, Namechl, "no PCB%s%s", (s.so_state & SS_CANTSENDMORE) ? ", CANTSENDMORE" : "", (s.so_state & SS_CANTRCVMORE) ? ", CANTRCVMORE" : ""); } else { (void) snpf(Namech, Namechl, "can't read inpcb at %s", print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); } enter_nm(Namech); return; } /* * Print Internet socket information. */ enter_dev_ch(print_kptr((KA_T)(inp.inp_ppcb ? inp.inp_ppcb : s.so_pcb), (char *)NULL, 0)); /* * Save IPv4 address information. */ if (p.pr_protocol == IPPROTO_TCP) ta = (KA_T)inp.inp_ppcb; la = (unsigned char *)&inp.inp_laddr; lp = (int)ntohs(inp.inp_lport); if (inp.inp_faddr.s_addr != INADDR_ANY || inp.inp_fport) { fa = (unsigned char *)&inp.inp_faddr; fp = (int)ntohs(inp.inp_fport); } } #if defined(HASIPv6) if ((fam == AF_INET6) && ((la && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)la)) || ((fa && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)fa))))) { /* * Adjust for IPv4 addresses mapped in IPv6 addresses. */ if (la) la = (unsigned char *)IPv6_2_IPv4(la); if (fa) fa = (unsigned char *)IPv6_2_IPv4(fa); fam = AF_INET; } #endif /* defined(HASIPv6) */ /* * Enter local and remote addresses by address family. */ if (fa || la) (void) ent_inaddr(la, lp, fa, fp, fam); if (ta && !kread(ta, (char *)&t, sizeof(t))) { Lf->lts.type = 0; Lf->lts.state.i = (int)t.t_state; #if defined(HASSOOPT) Lf->lts.kai = (unsigned int)t.t_timer[TCPT_KEEP]; #endif /* defined(HASSOOPT) */ #if defined(HASTCPOPT) Lf->lts.mss = (unsigned long)t.t_maxseg; Lf->lts.msss = (unsigned char)1; Lf->lts.topt = (unsigned int)t.t_flags; #endif /* defined(HASTCPOPT) */ } break; #if defined(AF_NDRV) /* * Process an NDRV domain socket. */ case AF_NDRV: { (void) snpf(Lf->type, sizeof(Lf->type), "ndrv"); /* * Read protocol control block. */ if (!s.so_pcb || kread((KA_T)s.so_pcb, (char *)&ndrv_cb, sizeof(ndrv_cb))) { (void) snpf(Namech, Namechl, "can't read ndrv_cb at %s", print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); enter_nm(Namech); return; } /* * Print NDRV socket information. */ enter_dev_ch(print_kptr((KA_T)(s.so_pcb), (char *)NULL, 0)); /* * Print device name, if bound */ if (!ndrv_cb.nd_if || kread((KA_T)ndrv_cb.nd_if, (char *)&ifnet, sizeof(ifnet))) { (void) snpf(Namech, Namechl, "can't read ifnet at %s", print_kptr((KA_T)ndrv_cb.nd_if, (char *)NULL, 0)); enter_nm(Namech); return; } if (!ifnet.if_name || kread((KA_T)ifnet.if_name, buf, sizeof(buf))) { (void) snpf(Namech, Namechl, "can't read ifnet.if_name at %s", print_kptr((KA_T)ifnet.if_name, (char *)NULL, 0)); enter_nm(Namech); return; } (void) snpf(Namech, Namechl, "-> %s%d", buf, ifnet.if_unit); } break; #endif /* defined(AF_NDRV) */ #if defined(pseudo_AF_KEY) /* * Process an [internal] key-management function socket */ case pseudo_AF_KEY: (void) snpf(Lf->type, sizeof(Lf->type), "key"); break; #endif /* defined(pseudo_AF_KEY) */ #if defined(AF_SYSTEM) /* * Process a SYSTEM domain socket */ case AF_SYSTEM: (void) snpf(Lf->type, sizeof(Lf->type), "systm"); /* * Read protocol control block. */ if (!s.so_pcb || kread((KA_T)s.so_pcb, (char *)&kev_cb, sizeof(kev_cb))) { (void) snpf(Namech, Namechl, "can't read kev_cb at %s", print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); enter_nm(Namech); return; } /* * Print SYSTEM socket information. */ enter_dev_ch(print_kptr((KA_T)(s.so_pcb), (char *)NULL, 0)); (void) snpf(Namech, Namechl, "[%lx:%lx:%lx]", kev_cb.vendor_code_filter, kev_cb.class_filter, kev_cb.subclass_filter); break; #endif /* defined(AF_SYSTEM) */ #if defined(AF_PPP) /* * Process a PPP domain socket */ case AF_PPP: (void) snpf(Lf->type, sizeof(Lf->type), "ppp"); break; #endif /* defined(AF_PPP) */ /* * Process a ROUTE domain socket. */ case AF_ROUTE: (void) snpf(Lf->type, sizeof(Lf->type), "rte"); if (s.so_pcb) enter_dev_ch(print_kptr((KA_T)(s.so_pcb), (char *)NULL, 0)); else (void) snpf(Namech, Namechl, "no protocol control block"); if (!Fsize) Lf->off_def = 1; break; /* * Process a Unix domain socket. */ case AF_UNIX: if (Funix) Lf->sf |= SELUNX; (void) snpf(Lf->type, sizeof(Lf->type), "unix"); /* * Read Unix protocol control block and the Unix address structure. */ enter_dev_ch(print_kptr(sa, (char *)NULL, 0)); if (!s.so_pcb || kread((KA_T)s.so_pcb, (char *)&unp, sizeof(unp))) { (void) snpf(Namech, Namechl, "can't read unpcb at %s", print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); break; } if ((struct socket *)sa != unp.unp_socket) { (void) snpf(Namech, Namechl, "unp_socket (%s) mismatch", print_kptr((KA_T)unp.unp_socket, (char *)NULL, 0)); break; } if (unp.unp_addr) { if (kread((KA_T)unp.unp_addr, (char *)&un, sizeof(un))) { (void) snpf(Namech, Namechl, "can't read unp_addr at %s", print_kptr((KA_T)unp.unp_addr, (char *)NULL, 0)); break; } ua = &un; } if (!ua) { ua = &un; (void) bzero((char *)ua, sizeof(un)); ua->sun_family = AF_UNSPEC; } /* * Print information on Unix socket that has no address bound * to it, although it may be connected to another Unix domain * socket as a pipe. */ if (ua->sun_family != AF_UNIX) { if (ua->sun_family == AF_UNSPEC) { if (unp.unp_conn) { if (kread((KA_T)unp.unp_conn, (char *)&uc, sizeof(uc))) (void) snpf(Namech, Namechl, "can't read unp_conn at %s", print_kptr((KA_T)unp.unp_conn,(char *)NULL,0)); else (void) snpf(Namech, Namechl, "->%s", print_kptr((KA_T)uc.unp_socket,(char *)NULL,0)); } else (void) snpf(Namech, Namechl, "->(none)"); } else (void) snpf(Namech, Namechl, "unknown sun_family (%d)", ua->sun_family); break; } if (ua->sun_path[0]) { unl = ua->sun_len - offsetof(struct sockaddr_un, sun_path); if ((unl < 0) || (unl >= sizeof(ua->sun_path))) unl = sizeof(ua->sun_path) - 1; ua->sun_path[unl] = '\0'; if (ua->sun_path[0] && Sfile && is_file_named(ua->sun_path, 0)) Lf->sf |= SELNM; if (ua->sun_path[0] && !Namech[0]) (void) snpf(Namech, Namechl, "%s", ua->sun_path); } else (void) snpf(Namech, Namechl, "no address"); break; default: printunkaf(fam, 1); } if (Namech[0]) enter_nm(Namech); } lsof-4.86+dfsg.orig/dialects/darwin/kmem/dproc.c0000444000175000017500000004071510331747443021751 0ustar nicholasnicholas/* * dproc.c - Darwin process access functions for /dev/kmem-based lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dproc.c,v 1.8 2005/11/01 20:24:51 abe Exp $"; #endif #include "lsof.h" #include #include #include #include /* * Local definitions */ #define NPHASH 1024 /* Phash bucket count -- * MUST BE A POWER OF 2!!! */ #define PHASH(a) (((int)((a * 31415) >> 3)) & (NPHASH - 1)) #define PINCRSZ 256 /* Proc[] size inrement */ /* * Local structures */ struct phash { KA_T ka; /* kernel proc struct address */ struct proc *la; /* local proc struct address */ struct phash *next; /* next phash entry */ }; /* * Local function prototypes */ _PROTOTYPE(static pid_t get_parent_pid,(KA_T kpa)); _PROTOTYPE(static int read_procs,()); _PROTOTYPE(static void process_map,(pid_t pid)); _PROTOTYPE(static void enter_vn_text,(KA_T va, int *n)); #if DARWINV>=700 _PROTOTYPE(static char *getcmdnm,(pid_t pid)); #endif /* DARWINV>=700 */ _PROTOTYPE(static void get_kernel_access,(void)); /* * Local static values */ static KA_T Akp = (KA_T)NULL; /* kernel allproc chain address */ static int Np = 0; /* PA[] and Proc[] entry count */ static int Npa = 0; /* Proc[] structure allocation count */ static MALLOC_S Nv = 0; /* allocated Vp[] entries */ static KA_T *Pa = (KA_T *)NULL; /* Proc[] addresses */ struct phash **Phash = (struct phash **)NULL; /* kernel proc address hash pointers */ static struct proc *Proc = (struct proc *)NULL; /* local copy of prc struct chain */ static KA_T *Vp = NULL; /* vnode address cache */ /* * enter_vn_text() - enter a vnode text reference */ static void enter_vn_text(va, n) KA_T va; /* vnode address */ int *n; /* Vp[] entries in use */ { int i; /* * Ignore the request if the vnode has already been entered. */ for (i = 0; i < *n; i++) { if (va == Vp[i]) return; } /* * Save the text file information. */ alloc_lfile(" txt", -1); Cfp = (struct file *)NULL; process_node(va); if (Lf->sf) link_lfile(); if (i >= Nv) { /* * Allocate space for remembering the vnode. */ Nv += 10; if (!Vp) Vp=(KA_T *)malloc((MALLOC_S)(sizeof(struct vnode *)*10)); else Vp=(KA_T *)realloc((MALLOC_P *)Vp,(MALLOC_S)(Nv*sizeof(KA_T))); if (!Vp) { (void) fprintf(stderr, "%s: no txt ptr space, PID %d\n", Pn, Lp->pid); Exit(1); } } /* * Remember the vnode. */ Vp[*n] = va; (*n)++; } /* * gather_proc_info() -- gather process information */ void gather_proc_info() { char *cmd; struct filedesc fd; int i, nf; MALLOC_S nb; static struct file **ofb = NULL; static int ofbb = 0; struct proc *p; int pgid; int ppid = 0; static char *pof = (char *)NULL; static int pofb = 0; short pss, sf; int px; uid_t uid; #if DARWINV<800 struct pcred pc; #else /* DARWINV>=800 */ struct ucred uc; #endif /* DARWINV<800 */ /* * Read the process table. */ if (read_procs()) { (void) fprintf(stderr, "%s: can't read process table\n", Pn); Exit(1); } /* * Examine proc structures and their associated information. */ for (p = Proc, px = 0; px < Np; p++, px++) { #if DARWINV<800 if (!p->p_cred || kread((KA_T)p->p_cred, (char *)&pc, sizeof(pc))) continue; pgid = pc.p_rgid; uid = pc.p_ruid; #else /* DARWINV>=800 */ if (!p->p_ucred || kread((KA_T)p->p_ucred, (char *)&uc, sizeof(uc))) continue; pgid = uc.cr_rgid; uid = uc.cr_uid; #endif /* DARWINV<800 */ #if defined(HASPPID) ppid = get_parent_pid((KA_T)p->p_pptr); #endif /* defined(HASPPID) */ /* * Get the command name. */ #if DARWINV<700 cmd = p->P_COMM; #else /* DARWINV>=700 */ if (!strcmp(p->p_comm, "LaunchCFMApp")) { if (!(cmd = getcmdnm(p->p_pid))) cmd = p->p_comm; } else cmd = p->p_comm; #endif /* DARWINV<700 */ /* * See if process is excluded. * * Read file structure pointers. */ if (is_proc_excl(p->p_pid, pgid, (UID_ARG)uid, &pss, &sf)) continue; if (!p->p_fd || kread((KA_T)p->p_fd, (char *)&fd, sizeof(fd))) continue; if (!fd.fd_refcnt || fd.fd_lastfile > fd.fd_nfiles) continue; /* * Allocate a local process structure. * * Set kernel's proc structure address. */ if (is_cmd_excl(cmd, &pss, &sf)) continue; alloc_lproc(p->p_pid, pgid, ppid, (UID_ARG)uid, cmd, (int)pss, (int)sf); Plf = (struct lfile *)NULL; Kpa = Pa[px]; /* * Save current working directory information. */ if (fd.fd_cdir) { alloc_lfile(CWD, -1); Cfp = (struct file *)NULL; process_node((KA_T)fd.fd_cdir); if (Lf->sf) link_lfile(); } /* * Save root directory information. */ if (fd.fd_rdir) { alloc_lfile(RTD, -1); Cfp = (struct file *)NULL; process_node((KA_T)fd.fd_rdir); if (Lf->sf) link_lfile(); } /* * Process the VM map. */ process_map(p->p_pid); /* * Read open file structure pointers. */ if (!fd.fd_ofiles || (nf = fd.fd_nfiles) <= 0) continue; nb = (MALLOC_S)(sizeof(struct file *) * nf); if (nb > ofbb) { if (!ofb) ofb = (struct file **)malloc(nb); else ofb = (struct file **)realloc((MALLOC_P *)ofb, nb); if (!ofb) { (void) fprintf(stderr, "%s: PID %d, no file * space\n", Pn, p->p_pid); Exit(1); } ofbb = nb; } if (kread((KA_T)fd.fd_ofiles, (char *)ofb, nb)) continue; nb = (MALLOC_S)(sizeof(char) * nf); if (nb > pofb) { if (!pof) pof = (char *)malloc(nb); else pof = (char *)realloc((MALLOC_P *)pof, nb); if (!pof) { (void) fprintf(stderr, "%s: PID %d, no file flag space\n", Pn, p->p_pid); Exit(1); } pofb = nb; } if (!fd.fd_ofileflags || kread((KA_T)fd.fd_ofileflags, pof, nb)) zeromem(pof, nb); /* * Save information on file descriptors. */ for (i = 0; i < nf; i++) { if (ofb[i] && !(pof[i] & UF_RESERVED)) { alloc_lfile(NULL, i); process_file((KA_T)(Cfp = ofb[i])); if (Lf->sf) { #if defined(HASFSTRUCT) if (Fsv & FSV_FG) Lf->pof = (long)pof[i]; #endif /* defined(HASFSTRUCT) */ link_lfile(); } } } /* * Examine results. */ if (examine_lproc()) return; } } #if DARWINV>=700 static char * getcmdnm(pid) pid_t pid; /* process ID */ { static int am; static char *ap = (char *)NULL; char *cp, *ep, *sp; int mib[3]; size_t sz; if (!ap) { /* * Allocate space for the maximum argument size. */ mib[0] = CTL_KERN; mib[1] = KERN_ARGMAX; sz = sizeof(am); if (sysctl(mib, 2, &am, &sz, NULL, 0) == -1) { (void) fprintf(stderr, "%s: can't get arg max, PID %d\n", Pn, pid); Exit(1); } if (!(ap = (char *)malloc((MALLOC_S)am))) { (void) fprintf(stderr, "%s: no arg ptr (%d) space, PID %d\n", Pn, am, pid); Exit(1); } } /* * Get the arguments for the process. */ mib[0] = CTL_KERN; mib[1] = KERN_PROCARGS; mib[2] = pid; sz = (size_t)am; if (sysctl(mib, 3, ap, &sz, NULL, 0) == -1) return((char *)NULL); /* * Skip to the first NUL character, which should end the saved exec path. */ for (cp = ap; *cp && (cp < (ap + sz)); cp++) { ; } if (cp >= (ap + sz)) return((char *)NULL); /* * Skip trailing NULs, which should find the beginning of the command. */ while (!*cp && (cp < (ap + sz))) { cp++; } if (cp >= (ap + sz)) return((char *)NULL); /* * Make sure that the command is NUL-terminated. */ for (sp = cp; *cp && (cp < (ap + sz)); cp++) { ; } if (cp >= (ap + sz)) return((char *)NULL); ep = cp; /* * Locate the start of the command's base name and return it. */ for (ep = cp, cp--; cp >= sp; cp--) { if (*cp == '/') { return(cp + 1); } } return(sp); } #endif /* DARWINV>=700 */ /* * get_kernel_access() - get access to kernel memory */ static void get_kernel_access() { /* * Check kernel version. */ (void) ckkv("Darwin", LSOF_VSTR, (char *)NULL, (char *)NULL); /* * Set name list file path. */ if (!Nmlst) Nmlst = N_UNIX; #if defined(WILLDROPGID) /* * If kernel memory isn't coming from KMEM, drop setgid permission * before attempting to open the (Memory) file. */ if (Memory) (void) dropgid(); #else /* !defined(WILLDROPGID) */ /* * See if the non-KMEM memory and the name list files are readable. */ if ((Memory && !is_readable(Memory, 1)) || (Nmlst && !is_readable(Nmlst, 1))) Exit(1); #endif /* defined(WILLDROPGID) */ /* * Open kernel memory access. */ if ((Kd = open(Memory ? Memory : KMEM, O_RDONLY, 0)) < 0) { (void) fprintf(stderr, "%s: open(%s): %s\n", Pn, Memory ? Memory : KMEM, strerror(errno)); Exit(1); } (void) build_Nl(Drive_Nl); if (nlist(Nmlst, Nl) < 0) { (void) fprintf(stderr, "%s: can't read namelist from %s\n", Pn, Nmlst); Exit(1); } #if defined(WILLDROPGID) /* * Drop setgid permission, if necessary. */ if (!Memory) (void) dropgid(); #endif /* defined(WILLDROPGID) */ } /* * get_parent_pid() - get parent process PID */ static pid_t get_parent_pid(kpa) KA_T kpa; /* kernel parent process address */ { struct phash *ph; if (kpa) { for (ph = Phash[PHASH(kpa)]; ph; ph = ph->next) { if (ph->ka == kpa) return((pid_t)ph->la->p_pid); } } return((pid_t)0); } /* * initialize() - perform all initialization */ void initialize() { get_kernel_access(); } /* * kread() - read from kernel memory */ int kread(addr, buf, len) KA_T addr; /* kernel memory address */ char *buf; /* buffer to receive data */ READLEN_T len; /* length to read */ { int br; if ((off_t)addr & (off_t)0x3) { /* * No read is possible if the address is not aligned on a word * boundary. */ return(1); } if (lseek(Kd, (off_t)addr, SEEK_SET) == (off_t)-1) return(1); br = read(Kd, buf, len); return((br == len) ? 0 : 1); } /* * prcess_map() - process VM map */ static void process_map(pid) pid_t pid; /* process id */ { vm_address_t address = 0; mach_msg_type_number_t count; vm_region_extended_info_data_t e_info; int n = 0; mach_port_t object_name; vm_size_t size = 0; vm_map_t task; vm_region_top_info_data_t t_info; struct vm_object { /* should come from */ #if DARWINV<800 KA_T Dummy1[15]; #else /* DARWINV>=800 */ KA_T Dummy1[14]; #endif /* DARWINV>=800 */ memory_object_t pager; } vmo; struct vnode_pager { /* from */ KA_T Dummy1[4]; struct vnode *vnode; } vp; /* * Get the task port associated with the process */ if (task_for_pid((mach_port_name_t)mach_task_self(), pid, (mach_port_name_t *)&task) != KERN_SUCCESS) { return; } /* * Go through the task's address space, looking for blocks of memory * backed by an external pager (i.e, a "vnode") */ for (address = 0;; address += size) { count = VM_REGION_EXTENDED_INFO_COUNT; if (vm_region(task, &address, &size, VM_REGION_EXTENDED_INFO, (vm_region_info_t)&e_info, &count, &object_name) != KERN_SUCCESS) { break; } if (!e_info.external_pager) continue; count = VM_REGION_TOP_INFO_COUNT; if (vm_region(task, &address, &size, VM_REGION_TOP_INFO, (vm_region_info_t)&t_info, &count, &object_name) != KERN_SUCCESS) { break; } /* * The returned "obj_id" is the "vm_object_t" address. */ if (!t_info.obj_id) continue; if (kread(t_info.obj_id, (char *)&vmo, sizeof(vmo))) break; /* * If the "pager" is backed by a vnode then the "vm_object_t" * "memory_object_t" address is actually a "struct vnode_pager *". */ if (!vmo.pager) continue; if (kread((KA_T)vmo.pager, (char *)&vp, sizeof(vp))) break; (void) enter_vn_text((KA_T)vp.vnode, &n); } return; } /* * read_procs() - read proc structures */ static int read_procs() { int h, i, np, pe; KA_T kp, kpn; MALLOC_S msz; struct proc *p; struct phash *ph, *phn; if (!Akp) { /* * Get kernel allproc structure pointer once. */ if (get_Nl_value("aproc", Drive_Nl, &Akp) < 0 || !Akp) { (void) fprintf(stderr, "%s: can't get proc table address\n", Pn); Exit(1); } } /* * Get the current number of processes and calculate PA and Proc[] allocation * sizes large enough to handle it. */ if (get_Nl_value("nproc", Drive_Nl, &kp) < 0 || !kp) { (void) fprintf(stderr, "%s: can't get nproc address\n", Pn); Exit(1); } if (kread(kp, (char *)&np, sizeof(np))) { (void) fprintf(stderr, "%s: can't read process count from %s\n", Pn, print_kptr(kp, (char *)NULL, 0)); Exit(1); } for (np += np, pe = PINCRSZ; pe < np; pe += PINCRSZ) ; /* * Allocate or reallocate the Pa[] and Proc[] tables. */ msz = (MALLOC_S)(pe * sizeof(struct proc)); if (!Proc) Proc = (struct proc *)malloc(msz); else if (pe > Npa) Proc = (struct proc *)realloc((MALLOC_P *)Proc, msz); if (!Proc) { (void) fprintf(stderr, "%s: no space for proc table\n", Pn); Exit(1); } msz = (MALLOC_S)(pe * sizeof(KA_T)); if (!Pa) Pa = (KA_T *)malloc(msz); else if (pe > Npa) Pa = (KA_T *)realloc((MALLOC_P *)Pa, msz); if (!Pa) { (void) fprintf(stderr, "%s: no space for proc addr table\n", Pn); Exit(1); } Npa = pe; /* * Allocate or reset the Phash[] table. */ if (!Phash) { Phash = (struct phash **)calloc(NPHASH, sizeof(struct phash *)); } else { for (h = 0; h < NPHASH; h++) { for (ph = Phash[h]; ph; ph = phn) { phn = ph->next; (void) free((MALLOC_P *)ph); } Phash[h] = (struct phash *)NULL; } } if (!Phash) { (void) fprintf(stderr, "%s: no space for proc address hash\n", Pn); Exit(1); } /* * Read the proc structures on the kernel's chain. */ for (i = Np = 0, kp = Akp, p = Proc, pe += pe; kp && i < pe; i++, kp = kpn) { if (kread(kp, (char *)p, sizeof(struct proc))) break; kpn = (KA_T)(((KA_T)p->p_list.le_next == Akp) ? NULL : p->p_list.le_next); if (p->p_stat == 0 || p->p_stat == SZOMB) continue; /* * Cache the proc structure's addresses. */ h = PHASH(kp); if (!(ph = (struct phash *)malloc((MALLOC_S)sizeof(struct phash)))) { (void) fprintf(stderr, "%s: no space for phash struct\n", Pn); Exit(1); } ph->ka = kp; ph->la = p; ph->next = Phash[h]; Phash[h] = ph; p++; Pa[Np++] = kp; if (Np >= Npa) { /* * Enlarge Pa[] and Proc[]. */ msz = (int)((Npa + PINCRSZ) * sizeof(struct proc)); if (!(Proc = (struct proc *)realloc((MALLOC_P *)Proc, msz))) { (void) fprintf(stderr, "%s: no additional proc space\n", Pn); Exit(1); } msz = (int)((Npa + PINCRSZ) * sizeof(KA_T)); if (!(Pa = (KA_T *)realloc((MALLOC_P *)Pa, msz))) { (void) fprintf(stderr, "%s: no additional proc addr space\n", Pn); Exit(1); } Npa += PINCRSZ; } } /* * If too many processes were read, the chain following probably failed; * report that and exit. */ if (i >= pe) { (void) fprintf(stderr, "%s: can't follow kernel proc chain\n", Pn); Exit(1); } /* * If not in repeat mode, reduce Pa[] and Proc[] to their minimums. */ if (Np < Npa && !RptTm) { msz = (MALLOC_S)(Np * sizeof(struct proc)); if (!(Proc = (struct proc *)realloc((MALLOC_P *)Proc, msz))) { (void) fprintf(stderr, "%s: can't reduce proc table\n", Pn); Exit(1); } msz = (MALLOC_S)(Np * sizeof(KA_T)); if (!(Pa = (KA_T *)realloc((MALLOC_P *)Pa, msz))) { (void) fprintf(stderr, "%s: can't reduce proc addr table\n", Pn); Exit(1); } Npa = Np; } /* * Return 0 if any processes were loaded; 1 if none were. */ return((Np > 0) ? 0 : 1); } lsof-4.86+dfsg.orig/dialects/darwin/kmem/dproto.h0000444000175000017500000000362210331747444022153 0ustar nicholasnicholas/* * dproto.h - Darwin function prototypes for /dev/kmem-based lsof * * The _PROTOTYPE macro is defined in the common proto.h. */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: dproto.h,v 1.4 2005/11/01 20:24:51 abe Exp $ */ _PROTOTYPE(extern int is_file_named,(char *p, int cd)); _PROTOTYPE(extern struct l_vfs *readvfs,(KA_T vm)); #if defined(HASKQUEUE) _PROTOTYPE(extern void process_kqueue,(KA_T ka)); #endif /* defined(HASKQUEUE) */ #if defined(HASPIPEFN) _PROTOTYPE(extern void process_pipe,(KA_T pa)); #endif /* defined(HASPIPEFN) */ #if defined(HASPSXSEM) _PROTOTYPE(extern void process_psxsem,(KA_T pa)); #endif /* defined(HASPSXSEM) */ #if defined(HASPSXSHM) _PROTOTYPE(extern void process_psxshm,(KA_T pa)); #endif /* defined(HASPSXSHM) */ #if defined(HAS9660FS) _PROTOTYPE(extern int read_iso_node,(struct vnode *v, dev_t *d, int *dd, INODETYPE *ino, long *nl, SZOFFTYPE *sz)); #endif /* defined(HAS9660FS) */ _PROTOTYPE(extern void process_socket,(KA_T sa)); lsof-4.86+dfsg.orig/dialects/darwin/kmem/dlsof.h0000444000175000017500000002016710331747436021757 0ustar nicholasnicholas/* * dlsof.h - Darwin header file for /dev/kmem-based lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: dlsof.h,v 1.11 2005/11/01 20:24:51 abe Exp $ */ #if !defined(DARWIN_LSOF_H) #define DARWIN_LSOF_H 1 #include #include #include #include #include #include #include #include #include #if DARWINV<800 #include #define m_stat mnt_stat #else /* DARWINV>=800 */ #include #define m_stat mnt_vfsstat #endif /* DARWINV>=800 */ #if DARWINV<800 #include #include #else /* DARWINV>=800 */ #include #define _SYS_SYSTM_H_ struct nameidata { int dummy; }; /* to satisfy function prototypes */ #include #endif /* DARWINV>=800 */ #include #define KERNEL_PRIVATE #include #undef KERNEL_PRIVATE #include #include #include #include # if defined(AF_NDRV) #include #define KERNEL #include #undef KERNEL #include # if DARWINV>=530 #define KERNEL 1 #include #undef KERNEL # endif /* DARWINV>=530 */ # endif /* defined(AF_NDRV) */ # if defined(AF_SYSTEM) #include #define KERNEL #include #undef KERNEL # endif /* defined(AF_SYSTEM) */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define pmap RPC_pmap #include #include #undef pmap #include #include # if DARWINV<800 #include #undef MAXNAMLEN #include #include #include #include #include #include #include #include # if DARWINV<600 #include #undef offsetof # else /* DARWINV>=600 */ #define KERNEL #include #undef KERNEL # endif /* DARWINV<600 */ # endif /* DARWINV<800 */ # if DARWINV<800 #define time t1 /* hack to make dn_times() happy */ #include #undef time # endif /* DARWINV<800 */ # if DARWINV<800 #define KERNEL #include #undef KERNEL # endif /* DARWINV<800 */ # if DARWINV<800 #include # else /* DARWINV>=800 */ #define PROC_DEF_ENABLED #define sleep kernel_sleep #include #undef sleep # endif /* DARWINV<800 */ #include #undef TRUE #undef FALSE # if DARWINV<800 #include # else /* DARWINV>=800 */ #include "/usr/include/sys/sysctl.h" # endif /* DARWINV<800 */ # if DARWINV<800 #define KERNEL #include #include #undef KERNEL # else /* DARWINV>=800 */ #include #include # endif /* DARWINV<800 */ # if defined(HASKQUEUE) #include # endif /* defined(HASKQUEUE) */ # if defined(DTYPE_PSXSEM) #define HASPSXSEM /* has the POSIX semaphore file * type */ # endif /* defined(DTYPE_PSXSEM) */ # if defined(DTYPE_PSXSHM) #define HASPSXSHM /* has the POSIX shared memory * file type */ # endif /* defined(DTYPE_PSXSHM) */ struct vop_advlock_args { int dummy; }; /* to satisfy lf_advlock() prototype */ #include #include /* * Compensate for removal of MAP_ENTRY_IS_A_MAP from , * This work-around was supplied by John Polstra . */ # if defined(MAP_ENTRY_IS_SUB_MAP) && !defined(MAP_ENTRY_IS_A_MAP) #define MAP_ENTRY_IS_A_MAP 0 # endif /* defined(MAP_ENTRY_IS_SUB_MAP) && !defined(MAP_ENTRY_IS_A_MAP) */ #undef B_NEEDCOMMIT #include #include #define user_sigaltstack sigaltstack #include #define COMP_P const void #define DEVINCR 1024 /* device table malloc() increment */ #define DIRTYPE dirent /* directory entry type */ typedef u_long KA_T; #define KMEM "/dev/kmem" #define LOGINML MAXLOGNAME #define MALLOC_P void #define FREE_P MALLOC_P #define MALLOC_S size_t #define N_UNIX "/mach_kernel" #define QSORT_P void #define READLEN_T int #define STRNCPY_L size_t #define SWAP "/dev/drum" # if DARWINV>=800 #define SZOFFTYPE unsigned long long /* size and offset internal storage * type */ #define SZOFFPSPEC "ll" /* SZOFFTYPE printf specification * modifier */ # endif /* DARWINV>=800 */ /* * Global storage definitions (including their structure definitions) */ struct file * Cfp; extern int Kd; /* KMEM descriptor */ extern KA_T Kpa; struct l_vfs { KA_T addr; /* kernel address */ fsid_t fsid; /* file system ID */ # if defined(MOUNT_NONE) short type; /* type of file system */ # else /* !defined(MOUNT_NONE) */ char *typnm; /* file system type name */ # endif /* defined(MOUNT_NONE) */ char *dir; /* mounted directory */ char *fsname; /* file system name */ struct l_vfs *next; /* forward link */ }; extern struct l_vfs *Lvfs; struct mounts { char *dir; /* directory (mounted on) */ char *fsname; /* file system * (symbolic links unresolved) */ char *fsnmres; /* file system * (symbolic links resolved) */ dev_t dev; /* directory st_dev */ dev_t rdev; /* directory st_rdev */ INODETYPE inode; /* directory st_ino */ mode_t mode; /* directory st_mode */ mode_t fs_mode; /* file system st_mode */ struct mounts *next; /* forward link */ }; #define X_NCACHE "ncache" #define X_NCSIZE "ncsize" #define NL_NAME n_name struct sfile { char *aname; /* argument file name */ char *name; /* file name (after readlink()) */ char *devnm; /* device name (optional) */ dev_t dev; /* device */ dev_t rdev; /* raw device */ u_short mode; /* S_IFMT mode bits from stat() */ int type; /* file type: 0 = file system * 1 = regular file */ INODETYPE i; /* inode number */ int f; /* file found flag */ struct sfile *next; /* forward link */ }; #define XDR_VOID (const xdrproc_t)xdr_void #define XDR_PMAPLIST (const xdrproc_t)xdr_pmaplist /* * Definitions for rnmh.c */ # if defined(HASNCACHE) #include #include # if !defined(offsetof) #define offsetof(type, member) ((size_t)(&((type *)0)->member)) # endif /* !defined(offsetof) */ #define NCACHE namecache /* kernel's structure name */ #define NCACHE_NM nc_name /* name in NCACHE */ # if DARWINV<700 #define NCACHE_NMLEN nc_nlen /* name length in NCACHE */ # endif /* DARWINV<700 */ #define NCACHE_NXT nc_hash.le_next /* link in NCACHE */ #define NCACHE_NODEADDR nc_vp /* node address in NCACHE */ #define NCACHE_PARADDR nc_dvp /* parent node address in NCACHE */ # if defined(HASNCVPID) #define NCACHE_NODEID nc_vpid /* node ID in NCACHE */ #define NCACHE_PARID nc_dvpid /* parent node ID in NCACHE */ # endif /* defined(HASNCVPID) */ # endif /* defined(HASNCACHE) */ #endif /* DARWIN_LSOF_H */ lsof-4.86+dfsg.orig/dialects/darwin/kmem/dnode1.c0000444000175000017500000000605010331747443022006 0ustar nicholasnicholas/* * dnode1.c - Darwin node functions for /dev/kmem-based lsof * * This module must be separate to keep separate the multiple kernel inode * structure definitions. */ /* * Copyright 1995 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dnode1.c,v 1.3 2005/11/01 20:24:51 abe Exp $"; #endif #include "lsof.h" #if defined(HAS9660FS) /* * Do a little preparation for #include'ing cd9660_node.h, then #include it. */ #undef i_size; #undef doff_t #undef IN_ACCESS struct vop_abortop_args { int dummy; }; struct vop_access_args { int dummy; }; struct vop_blkatoff_args { int dummy; }; struct vop_bmap_args { int dummy; }; struct vop_close_args { int dummy; }; struct vop_getattr_args { int dummy; }; struct vop_inactive_args { int dummy; }; struct vop_ioctl_args { int dummy; }; struct vop_islocked_args { int dummy; }; struct vop_lock_args { int dummy; }; struct vop_lookup_args { int dummy; }; struct vop_mmap_args { int dummy; }; struct vop_open_args { int dummy; }; struct vop_pathconf_args { int dummy; }; struct vop_print_args { int dummy; }; struct vop_read_args { int dummy; }; struct vop_readdir_args { int dummy; }; struct vop_readlink_args { int dummy; }; struct vop_reclaim_args { int dummy; }; struct vop_seek_args { int dummy; }; struct vop_select_args { int dummy; }; struct vop_strategy_args { int dummy; }; struct vop_unlock_args { int dummy; }; #include /* * read_iso_node() -- read CD 9660 iso_node */ int read_iso_node(v, d, dd, ino, nl, sz) struct vnode *v; /* containing vnode */ dev_t *d; /* returned device number */ int *dd; /* returned device-defined flag */ INODETYPE *ino; /* returned inode number */ long *nl; /* returned number of links */ SZOFFTYPE *sz; /* returned size */ { struct iso_node i; if (!v->v_data || kread((KA_T)v->v_data, (char *)&i, sizeof(i))) return(1); *d = i.i_dev; *dd = 1; *ino = (INODETYPE)i.i_number; *nl = (long)i.inode.iso_links; *sz = (SZOFFTYPE)i.i_size; return(0); } #endif /* defined(HAS9660FS) */ lsof-4.86+dfsg.orig/dialects/darwin/kmem/Mksrc0000555000175000017500000000111310412072106021453 0ustar nicholasnicholas#!/bin/sh # # Mksrc - make Darwin /dev/kmem-based lsof source files # # WARNING: This script assumes it is running from the main directory # of the lsof, version 4 distribution. # # One environment variable applies: # # LSOF_MKC is the method for creating the source files. # It defaults to "ln -s". A common alternative is "cp". # # $Id: Mksrc,v 1.5 2006/03/27 23:24:50 abe Exp $ D=dialects/darwin/kmem L="dlsof.h ddev.c dfile.c dmnt.c dnode.c dnode1.c dproc.c dproto.h dsock.c dstore.c machine.h" for i in $L do rm -f $i $LSOF_MKC $D/$i $i echo "$LSOF_MKC $D/$i $i" done lsof-4.86+dfsg.orig/dialects/darwin/kmem/dnode.c0000444000175000017500000005155710412072110021717 0ustar nicholasnicholas/* * dnode.c - Darwin node functions for /dev/kmem-based lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dnode.c,v 1.11 2006/03/27 23:24:50 abe Exp $"; #endif #include "lsof.h" /* * Local function prototypes */ #if DARWINV<600 _PROTOTYPE(static int lkup_dev_tty,(dev_t *dr, dev_t *rdr, INODETYPE *ir)); #endif /* DARWINV<600 */ #if DARWINV>=800 _PROTOTYPE(static char *getvpath,(KA_T va, struct vnode *rv)); _PROTOTYPE(static int readvname,(KA_T addr, char *buf, int buflen)); #endif /* DARWINV>=800 */ #if DARWINV>=800 /* * getvpath() - get vnode path * adapted from build_path() (.../bsd/vfs/vfs_subr.c) */ static char * getvpath(va, rv) KA_T va; /* kernel address of the rightmost * vnode in the path */ struct vnode *rv; /* pointer to rightmost vnode */ { char *ap; static char *bp = (char *)NULL; static size_t bl = (size_t)(MAXPATHLEN + MAXPATHLEN + 1); static char *cb = (char *)NULL; static size_t cbl = (size_t)0; static int ce = 0; struct mount mb; int pl, vnl; char *pp, vn[MAXPATHLEN+1]; struct vnode vb; KA_T vas = va; /* * Initialize the path assembly. */ if (!bp) { if (!(bp = (char *)malloc((MALLOC_S)bl))) { (void) fprintf(stderr, "%s: no space (%d) for path assembly\n", Pn, (int)bl); Exit(1); } } pp = bp + bl - 1; *pp = '\0'; pl = 0; /* * Process the starting vnode. */ if (!va) return(0); if ((rv->v_flag & VROOT) && rv->v_mount) { /* * This is the root of a file system and it has a mount structure. * Read the mount structure. */ if (kread((KA_T)rv->v_mount, (char *)&mb, sizeof(mb))) return(0); if (mb.mnt_flag & MNT_ROOTFS) { /* * This is the root file system, so the path is "/". */ pp--; *pp = '/'; pl = 1; goto getvpath_alloc; } else { /* * Get the covered vnode's pointer and read it. Use it to * form the path. */ if ((va = (KA_T)mb.mnt_vnodecovered)) { if (readvnode(va, &vb)) return(0); } } } else { /* * Use the supplied vnode. */ vb = *rv; } /* * Accumulate the path from the vnode chain. */ while (va && ((KA_T)vb.v_parent != va)) { if (!vb.v_name) { /* * If there is no name pointer or parent, the assembly is complete. */ if (vb.v_parent) { /* * It is an error if there is a parent but no name. */ return((char *)NULL); } break; } /* * Read the name and add it to the assembly. */ if ((vnl = readvname((KA_T)vb.v_name, vn, sizeof(vn))) <= 0) return((char *)NULL); if ((vnl + 1 + pl + 1) > bl) return((char *)NULL); memmove((void *)(pp - vnl), (void *)vn, vnl); pp -= (vnl + 1); *pp = '/'; pl += vnl + 1; if ((va == vas) && (vb.v_flag & VROOT)) { /* * This is the starting vnode and it is a root vnode. Read its * mount structure. */ if (vb.v_mount) { if (kread((KA_T)vb.v_mount, (char *)&mb, sizeof(mb))) return((char *)NULL); if (mb.mnt_vnodecovered) { /* * If there's a covered vnode, read it and use it's parent * vnode pointer. */ if ((va = (KA_T)mb.mnt_vnodecovered)) { if (readvnode(va, &vb)) return((char *)NULL); va = (KA_T)vb.v_parent; } } else va = (KA_T)NULL; } else va = (KA_T)NULL; } else va = (KA_T)vb.v_parent; /* * If there's a parent vnode, read it. */ if (va) { if (readvnode(va, &vb)) return((char *)NULL); if ((vb.v_flag & VROOT) && vb.v_mount) { /* * The mount point has been reached. Read the mount structure * and use its covered vnode pointer. */ if (kread((KA_T)vb.v_mount, (char *)&mb, sizeof(mb))) return((char *)NULL); if ((va = (KA_T)mb.mnt_vnodecovered)) { if (readvnode(va, &vb)) return((char *)NULL); } } } } /* * As a special case the following code attempts to trim a path that is * larger than MAXPATHLEN by seeing if the lsof process CWD can be removed * from the start of the path to make it MAXPATHLEN characters or less. */ if (pl > MAXPATHLEN) { /* * Get the cwd. If that can't be done, return an error. */ if (ce) return((char *)NULL); if (!cb) { if (!(cb = (char *)malloc((MALLOC_S)(MAXPATHLEN + 1)))) { (void) fprintf(stderr, "%s: no space (%d) for CWD\n", Pn, (int)bl); Exit(1); } if (!getcwd(cb, (size_t)(MAXPATHLEN + 1))) { if (!Fwarn) { (void) fprintf(stderr, "%s: WARNING: can't get CWD\n", Pn); } ce = 1; return((char *)NULL); } cb[MAXPATHLEN - 1] = '\0'; if (!(cbl = (size_t)strlen(cb))) { if (!Fwarn) { (void) fprintf(stderr, "%s: WARNING: CWD is NULL\n", Pn); } ce = 1; return((char *)NULL); } } /* * See if trimming the CWD shortens the path to MAXPATHLEN or less. */ if ((pl <= cbl) || strncmp(cb, pp, cbl)) return((char *)NULL); pp += cbl; pl -= cbl; if (cb[cbl - 1] == '/') { /* * The CWD ends in a '/', so the path must not begin with one. If * it does, no trimming can be done. */ if (*pp == '/') return((char *)NULL); } else { /* * The CWD doesn't end in a '/', so the path must begin with one. * If it doesn't, no trimming can be done. */ if (*pp != '/') return((char *)NULL); /* * Skip all leading path '/' characters. Some characters must * remain. */ while ((pl > 0) && (*pp == '/')) { pp++; pl--; } if (!pl) return((char *)NULL); } } /* * Allocate space for the assembled path, including terminator, and return its * pointer. */ getvpath_alloc: if (!(ap = (char *)malloc(pl + 1))) { (void) fprintf(stderr, "%s: no getvpath space (%d)\n", Pn, pl + 1); Exit(1); } (void) memmove(ap, pp, pl + 1); return(ap); } #endif /* DARWINV>=800 */ #if DARWINV<600 /* * lkup_dev_tty() - look up /dev/tty */ static int lkup_dev_tty(dr, rdr, ir) dev_t *dr; /* place to return device number */ dev_t *rdr; /* place to return raw device number */ INODETYPE *ir; /* place to return inode number */ { int i; readdev(0); for (i = 0; i < Ndev; i++) { if (strcmp(Devtp[i].name, "/dev/tty") == 0) { *dr = DevDev; *rdr = Devtp[i].rdev; *ir = (INODETYPE)Devtp[i].inode; return(1); } } return(-1); } #endif /* DARWINV<600 */ /* * process_node() - process vnode */ void process_node(va) KA_T va; /* vnode kernel space address */ { dev_t dev = (dev_t)0; dev_t rdev = (dev_t)0; unsigned char devs = 0; unsigned char rdevs = 0; #if DARWINV<800 struct devnode *d = (struct devnode *)NULL; struct devnode db; unsigned char lt; char dev_ch[32]; # if defined(HASFDESCFS) struct fdescnode *f = (struct fdescnode *)NULL; struct fdescnode fb; # endif /* defined(HASFDESCFS) */ static INODETYPE fi; static dev_t fdev, frdev; static int fs = 0; struct inode *i = (struct inode *)NULL; struct inode ib; struct lockf lf, *lff, *lfp; struct nfsnode *n = (struct nfsnode *)NULL; struct nfsnode nb; #else /* DARWINV>=800 */ struct stat sb; char *vn; #endif /* DARWINV<800 */ char *ty; enum vtype type; struct vnode *v, vb; struct l_vfs *vfs; #if DARWINV<600 struct hfsnode *h = (struct hfsnode *)NULL; struct hfsnode hb; struct hfsfilemeta *hm = (struct hfsfilemeta *)NULL; struct hfsfilemeta hmb; #else /* DARWINV>=600 */ # if DARWINV<800 struct cnode *h = (struct cnode *)NULL; struct cnode hb; struct filefork *hf = (struct filefork *)NULL; struct filefork hfb; # endif /* DARWINV<800 */ #endif /* DARWINV<600 */ #if defined(HAS9660FS) dev_t iso_dev; int iso_dev_def = 0; INODETYPE iso_ino; long iso_links; int iso_stat = 0; SZOFFTYPE iso_sz; #endif /* defined(HAS9660FS) */ /* * Read the vnode. */ if ( ! va) { enter_nm("no vnode address"); return; } v = &vb; if (readvnode(va, v)) { enter_nm(Namech); return; } type = v->v_type; #if defined(HASNCACHE) Lf->na = va; # if defined(HASNCVPID) Lf->id = v->v_id; # endif /* defined(HASNCVPID) */ #endif /* defined(HASNCACHE) */ #if defined(HASFSTRUCT) Lf->fna = va; Lf->fsv |= FSV_NI; #endif /* defined(HASFSTRUCT) */ /* * Get the vnode type. */ if (!v->v_mount) vfs = (struct l_vfs *)NULL; else { vfs = readvfs((KA_T)v->v_mount); if (vfs) { if (strcasecmp(vfs->typnm, "nfs") == 0) Ntype = N_NFS; #if DARWINV<130 else if (strcasecmp(vfs->typnm, "afpfs") == 0) Ntype = N_AFPFS; #endif /* DARWINV<130 */ } } if (Ntype == N_REGLR) { switch (v->v_type) { case VFIFO: Ntype = N_FIFO; break; default: break; } } #if DARWINV<800 /* * Define the specific node pointer. */ switch (v->v_tag) { # if DARWINV>120 case VT_AFP: break; # endif /* DARWINV>120 */ # if DARWINV>120 case VT_CDDA: break; # endif /* DARWINV>120 */ # if DARWINV>120 case VT_CIFS: break; # endif /* DARWINV>120 */ case VT_DEVFS: if (!v->v_data || kread((KA_T)v->v_data, (char *)&db, sizeof(db))) { (void) snpf(Namech, Namechl, "no devfs node: %#x", v->v_data); enter_nm(Namech); return; } d = &db; break; # if defined(HASFDESCFS) case VT_FDESC: if (!v->v_data || kread((KA_T)v->v_data, (char *)&fb, sizeof(fb))) { (void) snpf(Namech, Namechl, "no fdesc node: %s", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } f = &fb; break; # endif /* defined(HASFDESCFS) */ case VT_HFS: # if DARWINV<130 if (Ntype != N_AFPFS) { # endif /* DARWINV<130 */ if (!v->v_data || kread((KA_T)v->v_data, (char *)&hb, sizeof(hb))) { (void) snpf(Namech, Namechl, "no hfs node: %s", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } h = &hb; # if DARWINV<600 if (!h->h_meta || kread((KA_T)h->h_meta, (char *)&hmb, sizeof(hmb))) { (void) snpf(Namech, Namechl, "no hfs node metadata: %s", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } hm = &hmb; # else /* DARWINV>=600 */ if (v->v_type == VDIR) break; if (h->c_rsrc_vp == v) hf = h->c_rsrcfork; else hf = h->c_datafork; if (!hf || kread((KA_T)hf, (char *)&hfb, sizeof(hfb))) { (void) snpf(Namech, Namechl, "no hfs node fork: %s", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } hf = &hfb; # endif /* DARWINV<600 */ # if DARWINV<130 } # endif /* DARWINV<130 */ break; # if defined(HAS9660FS) case VT_ISOFS: if (read_iso_node(v, &iso_dev, &iso_dev_def, &iso_ino, &iso_links, &iso_sz)) { (void) snpf(Namech, Namechl, "no iso node: %s", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } iso_stat = 1; break; # endif /* defined(HAS9660FS) */ case VT_NFS: if (!v->v_data || kread((KA_T)v->v_data, (char *)&nb, sizeof(nb))) { (void) snpf(Namech, Namechl, "no nfs node: %s", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } n = &nb; break; # if DARWINV>120 case VT_UDF: break; # endif /* DARWINV>120 */ case VT_UFS: if (!v->v_data || kread((KA_T)v->v_data, (char *)&ib, sizeof(ib))) { (void) snpf(Namech, Namechl, "no ufs node: %s", print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } i = &ib; if ((lff = i->i_lockf)) { /* * Determine the lock state. */ lfp = lff; do { if (kread((KA_T)lfp, (char *)&lf, sizeof(lf))) break; lt = 0; switch (lf.lf_flags & (F_FLOCK|F_POSIX)) { case F_FLOCK: if (Cfp && (struct file *)lf.lf_id == Cfp) lt = 1; break; case F_POSIX: if ((KA_T)lf.lf_id == Kpa) lt = 1; break; } if (!lt) continue; if (lf.lf_start == (off_t)0 && lf.lf_end == 0xffffffffffffffffLL) lt = 1; else lt = 0; if (lf.lf_type == F_RDLCK) Lf->lock = lt ? 'R' : 'r'; else if (lf.lf_type == F_WRLCK) Lf->lock = lt ? 'W' : 'w'; else if (lf.lf_type == (F_RDLCK | F_WRLCK)) Lf->lock = 'u'; break; } while ((lfp = lf.lf_next) && lfp != lff); } break; # if DARWINV>120 case VT_WEBDAV: break; # endif /* DARWINV>120 */ default: if (v->v_type == VBAD || v->v_type == VNON) break; (void) snpf(Namech, Namechl, "unknown file system type: %d", v->v_tag); enter_nm(Namech); return; } /* * Get device and type for printing. */ if (n) { dev = n->n_vattr.va_fsid; devs = 1; } else if (i) { dev = i->i_dev; devs = 1; if ((type == VCHR) || (type == VBLK)) { rdev = i->i_rdev ; rdevs = 1; } } # if defined(HASFDESCFS) else if (f) { if (f->fd_link && !kread((KA_T)f->fd_link, Namech, Namechl -1)) Namech[Namechl - 1] = '\0'; # if DARWINV<600 else if (f->fd_type == Fctty) { if (fs == 0) fs = lkup_dev_tty(&fdev, &frdev, &fi); if (fs == 1) { dev = fdev; rdev = frdev; devs = Lf->inp_ty = rdevs = 1; Lf->inode = fi; } } } # endif /* DARWINV<600 */ # endif /* defined(HASFDESCFS) */ else if (h) { # if DARWINV<600 dev = hm->h_dev; # else /* DARWINV>=600 */ dev = h->c_dev; # endif /* DARWINV<600 */ devs = 1; if ((type == VCHR) || (type == VBLK)) { # if DARWINV<600 rdev = hm->h_rdev; # else /* DARWINV>=600 */ rdev = h->c_rdev; # endif /* DARWINV<600 */ rdevs = 1; } } else if (d) { dev = DevDev; devs = 1; rdev = d->dn_typeinfo.dev; rdevs = 1; } # if defined(HAS9660FS) else if (iso_stat && iso_dev_def) { dev = iso_dev; devs = Lf->inp_ty = 1; } # endif /* defined(HAS9660FS) */ /* * Obtain the inode number. */ if (i) { Lf->inode = (INODETYPE)i->i_number; Lf->inp_ty = 1; } else if (n) { Lf->inode = (INODETYPE)n->n_vattr.va_fileid; Lf->inp_ty = 1; } else if (h) { # if DARWINV<600 Lf->inode = (INODETYPE)hm->h_nodeID; # else /* DARWINV>=600 */ Lf->inode = (INODETYPE)h->c_fileid; # endif /* DARWINV<600 */ Lf->inp_ty = 1; } # if defined(HAS9660FS) else if (iso_stat) { Lf->inode = iso_ino; Lf->inp_ty = 1; } # endif /* defined(HAS9660FS) */ /* * Obtain the file size. */ if (Foffset) Lf->off_def = 1; else { switch (Ntype) { case N_FIFO: if (!Fsize) Lf->off_def = 1; break; case N_NFS: if (n) { Lf->sz = (SZOFFTYPE)n->n_vattr.va_size; Lf->sz_def = 1; } break; # if DARWINV<130 case N_AFPFS: break; # endif /* DARWINV<130 */ case N_REGLR: if (type == VREG || type == VDIR) { if (i) { Lf->sz = (SZOFFTYPE)i->i_size; Lf->sz_def = 1; } else if (h) { # if DARWINV<600 Lf->sz = (type == VDIR) ? (SZOFFTYPE)hm->h_size : (SZOFFTYPE)h->fcbEOF; # else /* DARWINV>=600 */ if (type == VDIR) Lf->sz = (SZOFFTYPE)h->c_nlink * 128; else Lf->sz = (SZOFFTYPE)hf->ff_size; # endif /* DARWINV<600 */ Lf->sz_def = 1; } # if defined(HAS9660FS) else if (iso_stat) { Lf->sz = (SZOFFTYPE)iso_sz; Lf->sz_def = 1; } # endif /* defined(HAS9660FS) */ } else if ((type == VCHR || type == VBLK) && !Fsize) Lf->off_def = 1; break; } } /* * Record the link count. */ if (Fnlink) { switch(Ntype) { case N_NFS: if (n) { Lf->nlink = (long)n->n_vattr.va_nlink; Lf->nlink_def = 1; } break; # if DARWINV<130 case N_AFPFS: break; # endif /* DARWINV<130 */ case N_REGLR: if (i) { Lf->nlink = (long)i->i_nlink; Lf->nlink_def = 1; } else if (h) { # if DARWINV<600 Lf->nlink = (long)hm->h_nlink; # else /* DARWINV>=600 */ Lf->nlink = (long)h->c_nlink; # endif /* DARWINV<600 */ Lf->nlink_def = 1; } # if defined(HAS9660FS) else if (iso_stat) { Lf->nlink = iso_links; Lf->nlink_def = 1; } # endif /* defined(HAS9660FS) */ break; } if (Lf->nlink_def && Nlink && (Lf->nlink < Nlink)) Lf->sf |= SELNLINK; } #else /* DARWINV>=800 */ /* * Process a vnode for Darwin >= 8.0. */ if ((vn = getvpath(va, v))) { /* * If the vnode yields a path, get the file's information by doing * a "safe" stat(2) of the path. */ if (!statsafely(vn, &sb)) { /* * Save file size or offset. */ if (Foffset) { Lf->off_def = 1; } else { switch (Ntype) { case N_FIFO: if (!Fsize) Lf->off_def = 1; break; case N_NFS: case N_REGLR: if (type == VREG || type == VDIR) { Lf->sz = sb.st_size; Lf->sz_def = 1; } else if ((type == VCHR || type == VBLK) && !Fsize) Lf->off_def = 1; break; } } /* * Save node number. */ Lf->inode = (INODETYPE)sb.st_ino; Lf->inp_ty = 1; /* * Optionally save link count. */ if (Fnlink) { Lf->nlink = sb.st_nlink; Lf->nlink_def = 1; } /* * Save device number and path. */ switch (v->v_tag) { case VT_DEVFS: if (vn) (void) free((FREE_P *)vn); dev = DevDev; devs = 1; break; default : Lf->V_path = vn; dev = sb.st_dev; devs = 1; break; } /* * Save character and block device number. */ if ((type == VCHR) || (type == VBLK)) { rdev = sb.st_rdev; rdevs = 1; } } else { /* * Indicate a stat(2) failure in Namech[]. */ (void) snpf(Namech, Namechl, "stat(%s): %s", vn, strerror(errno)); (void) free((FREE_P *)vn); } /* * Record an NFS file. */ if (vfs && !strcmp(vfs->typnm, "nfs")) Ntype = N_NFS; } #endif /* DARWINV>=800 */ /* * Record an NFS file selection. */ if (Ntype == N_NFS && Fnfs) Lf->sf |= SELNFS; /* * Save the file system names. */ if (vfs) { Lf->fsdir = vfs->dir; Lf->fsdev = vfs->fsname; } /* * Save the device numbers and their states. * * Format the vnode type, and possibly the device name. */ Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; switch (type) { case VNON: ty ="VNON"; break; case VREG: ty = "VREG"; break; case VDIR: ty = "VDIR"; break; case VBLK: ty = "VBLK"; Ntype = N_BLK; break; case VCHR: ty = "VCHR"; Ntype = N_CHR; break; case VLNK: ty = "VLNK"; break; #if defined(VSOCK) case VSOCK: ty = "SOCK"; break; #endif /* defined(VSOCK) */ case VBAD: ty = "VBAD"; break; case VFIFO: ty = "FIFO"; break; default: (void) snpf(Lf->type, sizeof(Lf->type), "%04o", (type & 0xfff)); ty = (char *)NULL; } if (ty) (void) snpf(Lf->type, sizeof(Lf->type), "%s", ty); Lf->ntype = Ntype; /* * Handle some special cases: * * ioctl(fd, TIOCNOTTY) files; * memory node files; * /proc files. */ if (type == VBAD) (void) snpf(Namech, Namechl, "(revoked)"); #if defined(HASBLKDEV) /* * If this is a VBLK file and it's missing an inode number, try to * supply one. */ if ((Lf->inp_ty == 0) && (type == VBLK)) find_bl_ino(); #endif /* defined(HASBLKDEV) */ /* * If this is a VCHR file and it's missing an inode number, try to * supply one. */ if ((Lf->inp_ty == 0) && (type == VCHR)) find_ch_ino(); /* * Test for specified file. */ if (Sfile && is_file_named((char *)NULL, ((type == VCHR) || (type == VBLK) ? 1 : 0))) Lf->sf |= SELNM; /* * Enter name characters. */ if (Namech[0]) enter_nm(Namech); } #if DARWINV>=800 /* * readvname() - read vnode's path name */ static int readvname(addr, buf, buflen) KA_T addr; /* kernel v_path address */ char *buf; /* receiving buffer */ int buflen; /* sizeof(buf) */ { int n, rl; /* * Read the name 32 characters at a time, until a NUL character * has been read or the buffer has been filled. */ for (n = 0; n < buflen; addr += 32, n += 32) { rl = buflen - n; if (rl > 32) rl = 32; if (kread(addr, &buf[n], rl)) return(0); buf[n + rl] = '\0'; if ((rl = (int)strlen(&buf[n])) < 32) { return(n + rl); } } return(0); } #endif /* DARWINV>=800 */ lsof-4.86+dfsg.orig/dialects/darwin/kmem/dfile.c0000644000175000017500000002031610331747121021713 0ustar nicholasnicholas/* * dfile.c - Darwin file processing functions for /dev/kmem-based lsof */ /* * Copyright 2005 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 2005 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id$"; #endif #include "lsof.h" /* * Local definitions */ #if DARWINV>=800 #define file fileglob #define f_flag fg_flag #define f_type fg_type #define f_count fg_count #define f_ops fg_ops #define f_offset fg_offset #define f_data fg_data #endif /* DARWINV>=800 */ #if defined(HASPSXSEM) #define PSEMNAMLEN 31 /* from kern/posix_sem.c */ #endif /* defined(HASPSXSEM) */ #if defined(HASPSXSHM) #define PSHMNAMLEN 31 /* from kern/posix_shm.c */ #endif /* defined(HASPSXSHM) */ /* * Local structure definitions */ #if defined(HASPSXSEM) struct pseminfo { /* from kern/posix_sem.c */ unsigned int psem_flags; unsigned int psem_usecount; mode_t psem_mode; uid_t psem_uid; gid_t psem_gid; char psem_name[PSEMNAMLEN + 1]; void *psem_semobject; struct proc *sem_proc; }; struct psemnode { struct pseminfo *pinfo; }; #endif /* defined(HASPSXSEM) */ #if defined(HASPSXSHM) /* from kern/posix_shm.c */ struct pshminfo { unsigned int pshm_flags; unsigned int pshm_usecount; off_t pshm_length; mode_t pshm_mode; uid_t pshm_uid; gid_t pshm_gid; char pshm_name[PSHMNAMLEN + 1]; void *pshm_memobject; }; struct pshmnode { off_t mapp_addr; # if DARWINV<800 size_t map_size; # else /* DARWINV>=800 */ user_size_t map_size; # endif /* DARWINV>=800 */ struct pshminfo *pinfo; }; #endif /* defined(HASPSXSHM) */ #if DARWINV>=800 /* * print_v_path() - print vnode's path */ int print_v_path(lf) struct lfile *lf; { if (lf->V_path) { safestrprt(lf->V_path, stdout, 0); return(1); } return(0); } #endif /* DARWINV>=800 */ #if defined(HASKQUEUE) /* * process_kqueue() -- process kqueue file */ void process_kqueue(ka) KA_T ka; /* kqueue file structure address */ { struct kqueue kq; /* kqueue structure */ (void) snpf(Lf->type, sizeof(Lf->type), "KQUEUE"); enter_dev_ch(print_kptr(ka, (char *)NULL, 0)); if (!ka || kread(ka, (char *)&kq, sizeof(kq))) return; (void) snpf(Namech, Namechl, "count=%d, state=%#x", kq.kq_count, kq.kq_state); enter_nm(Namech); } #endif /* defined(HASKQUEUE) */ #if DARWINV>=800 /* * process_pipe() - process a file structure whose type is DTYPE_PIPE */ void process_pipe(pa) KA_T pa; /* pipe structure address */ { (void) snpf(Lf->type, sizeof(Lf->type), "PIPE"); enter_dev_ch(print_kptr(pa, (char *)NULL, 0)); Namech[0] = '\0'; } #endif /* DARWINV>=800 */ #if defined(HASPSXSEM) /* * process_psxsem() -- process POSIX semaphore file */ void process_psxsem(pa) KA_T pa; /* psxsem file structure address */ { struct pseminfo pi; struct psemnode pn; (void) snpf(Lf->type, sizeof(Lf->type), "PSXSEM"); enter_dev_ch(print_kptr(pa, (char *)NULL, 0)); if (!Fsize) Lf->off_def = 1; if (pa && !kread(pa, (char *)&pn, sizeof(pn))) { if (pn.pinfo && !kread((KA_T)pn.pinfo, (char *)&pi, sizeof(pi))) { if (pi.psem_name[0]) { pi.psem_name[PSEMNAMLEN] = '\0'; (void) snpf(Namech, Namechl, "%s", pi.psem_name); enter_nm(Namech); } } } } #endif /* defined(HASPSXSEM) */ #if defined(HASPSXSHM) /* * process_psxshm() -- process POSIX shared memory file */ void process_psxshm(pa) KA_T pa; /* psxshm file structure address */ { struct pshminfo pi; struct pshmnode pn; int pns = 0; (void) snpf(Lf->type, sizeof(Lf->type), "PSXSHM"); enter_dev_ch(print_kptr(pa, (char *)NULL, 0)); if (pa && !kread(pa, (char *)&pn, sizeof(pn))) { pns = 1; if (pn.pinfo && !kread((KA_T)pn.pinfo, (char *)&pi, sizeof(pi))) { if (pi.pshm_name[0]) { pi.pshm_name[PSEMNAMLEN] = '\0'; (void) snpf(Namech, Namechl, "%s", pi.pshm_name); enter_nm(Namech); } else if (pi.pshm_memobject) { (void) snpf(Namech, Namechl, "obj=%s", print_kptr((KA_T)pi.pshm_memobject, (char *)NULL, 0)); enter_nm(Namech); } } } if (Foffset) Lf->off_def = 1; else if (pns) { Lf->sz = (SZOFFTYPE)pn.map_size; Lf->sz_def = 1; } } #endif /* defined(HASPSXSHM) */ /* * process_file() - process file */ /* * The caller may define: * * FILEPTR as the name of the location to store a pointer * to the current file struct -- e.g., * * struct file *foobar; * #define FILEPTR foobar */ void process_file(fp) KA_T fp; /* kernel file structure address */ { #if DARWINV<800 struct file f; #else /* DARWINV>=800 */ struct fileglob f; struct fileproc fileproc; #endif /* DARWINV>=800 */ int flag; #if defined(FILEPTR) /* * Save file structure address for process_node(). */ FILEPTR = &f; #endif /* defined(FILEPTR) */ /* * Read file structure. */ #if DARWINV<800 if (kread((KA_T)fp, (char *)&f, sizeof(f))) { (void) snpf(Namech, Namechl, "can't read file struct from %s", print_kptr(fp, (char *)NULL, 0)); enter_nm(Namech); return; } #else /* DARWINV>=800 */ if (kread((KA_T)fp, (char *)&fileproc, sizeof(fileproc))) { (void) snpf(Namech, Namechl, "can't read fileproc struct from %s", print_kptr(fp, (char *)NULL, 0)); enter_nm(Namech); return; } if (kread((KA_T)fileproc.f_fglob, (char *)&f, sizeof(f))) { (void) snpf(Namech, Namechl, "can't read fileglob struct from %s", print_kptr((KA_T)fileproc.f_fglob, (char *)NULL, 0)); enter_nm(Namech); return; } #endif /* DARWINV>=800 */ Lf->off = (SZOFFTYPE)f.f_offset; if (f.f_count) { /* * Construct access code. */ if ((flag = (f.f_flag & (FREAD | FWRITE))) == FREAD) Lf->access = 'r'; else if (flag == FWRITE) Lf->access = 'w'; else if (flag == (FREAD | FWRITE)) Lf->access = 'u'; #if defined(HASFSTRUCT) /* * Save file structure values. */ if (Fsv & FSV_CT) { Lf->fct = (long)f.f_count; Lf->fsv |= FSV_CT; } if (Fsv & FSV_FA) { Lf->fsa = fp; Lf->fsv |= FSV_FA; } if (Fsv & FSV_FG) { Lf->ffg = (long)f.f_flag; Lf->fsv |= FSV_FG; } if (Fsv & FSV_NI) { Lf->fna = (KA_T)f.f_data; Lf->fsv |= FSV_NI; } #endif /* defined(HASFSTRUCT) */ /* * Process structure by its type. */ switch (f.f_type) { #if defined(DTYPE_PIPE) case DTYPE_PIPE: # if defined(HASPIPEFN) if (!Selinet) HASPIPEFN((KA_T)f.f_data); # endif /* defined(HASPIPEFN) */ return; #endif /* defined(DTYPE_PIPE) */ case DTYPE_VNODE: if (!Selinet) process_node((KA_T)f.f_data); return; case DTYPE_SOCKET: process_socket((KA_T)f.f_data); return; #if defined(HASKQUEUE) case DTYPE_KQUEUE: process_kqueue((KA_T)f.f_data); return; #endif /* defined(HASKQUEUE) */ #if defined(HASPSXSEM) case DTYPE_PSXSEM: process_psxsem((KA_T)f.f_data); return; #endif /* defined(HASPSXSEM) */ #if defined(HASPSXSHM) case DTYPE_PSXSHM: process_psxshm((KA_T)f.f_data); return; #endif /* defined(HASPSXSHM) */ #if defined(HASPRIVFILETYPE) case PRIVFILETYPE: HASPRIVFILETYPE((KA_T)f.f_data); return; #endif /* defined(HASPRIVFILETYPE) */ default: if (f.f_type || f.f_ops) { (void) snpf(Namech, Namechl, "%s file struct, ty=%#x, op=%p", print_kptr(fp, (char *)NULL, 0), f.f_type, f.f_ops); enter_nm(Namech); return; } } } enter_nm("no more information"); } lsof-4.86+dfsg.orig/dialects/darwin/kmem/dmnt.c0000444000175000017500000001265310331747440021601 0ustar nicholasnicholas/* * dmnt.c - Darwin mount support functions for /dev/kmem-based lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dmnt.c,v 1.4 2005/11/01 20:24:51 abe Exp $"; #endif #include "lsof.h" /* * Local static information */ static struct mounts *Lmi = (struct mounts *)NULL; /* local mount info */ static int Lmist = 0; /* Lmi status */ /* * readmnt() - read mount table */ struct mounts * readmnt() { char *dn = (char *)NULL; char *ln; struct statfs *mb = (struct statfs *)NULL; struct mounts *mtp; int n; struct stat sb; if (Lmi || Lmist) return(Lmi); /* * Access mount information. */ if ((n = getmntinfo(&mb, MNT_NOWAIT)) <= 0) { (void) fprintf(stderr, "%s: no mount information\n", Pn); return(0); } /* * Read mount information. */ for (; n; n--, mb++) { if (!mb->f_type) continue; /* * Interpolate a possible symbolic directory link. */ if (dn) (void) free((FREE_P *)dn); if (!(dn = mkstrcpy(mb->f_mntonname, (MALLOC_S *)NULL))) { no_space_for_mount: (void) fprintf(stderr, "%s: no space for mount at ", Pn); safestrprt(mb->f_mntonname, stderr, 0); (void) fprintf(stderr, " ("); safestrprt(mb->f_mntfromname, stderr, 0); (void) fprintf(stderr, ")\n"); Exit(1); } if (!(ln = Readlink(dn))) { if (!Fwarn) { (void) fprintf(stderr, " Output information may be incomplete.\n"); } continue; } if (ln != dn) { (void) free((FREE_P *)dn); dn = ln; } if (*dn != '/') continue; /* * Stat() the directory. */ if (statsafely(dn, &sb)) { if (!Fwarn) { (void) fprintf(stderr, "%s: WARNING: can't stat() ", Pn); safestrprt(mb->f_fstypename, stderr, 0); (void) fprintf(stderr, " file system "); safestrprt(mb->f_mntonname, stderr, 1); (void) fprintf(stderr, " Output information may be incomplete.\n"); } (void) bzero((char *)&sb, sizeof(sb)); sb.st_dev = (dev_t)mb->f_fsid.val[0]; sb.st_mode = S_IFDIR | 0777; if (!Fwarn) { (void) fprintf(stderr, " assuming \"dev=%x\" from mount table\n", sb.st_dev); } } /* * Allocate and fill a local mount structure. */ if (!(mtp = (struct mounts *)malloc(sizeof(struct mounts)))) goto no_space_for_mount; mtp->dir = dn; dn = (char *)NULL; mtp->next = Lmi; mtp->dev = sb.st_dev; mtp->rdev = sb.st_rdev; mtp->inode = (INODETYPE)sb.st_ino; mtp->mode = sb.st_mode; /* * Interpolate a possible file system (mounted-on) device name link. */ if (!(dn = mkstrcpy(mb->f_mntfromname, (MALLOC_S *)NULL))) goto no_space_for_mount; mtp->fsname = dn; ln = Readlink(dn); dn = (char *)NULL; /* * Stat() the file system (mounted-on) name and add file system * information to the local mount table entry. */ if (!ln || statsafely(ln, &sb)) sb.st_mode = 0; mtp->fsnmres = ln; mtp->fs_mode = sb.st_mode; Lmi = mtp; } /* * Clean up and return the local mount info table address. */ if (dn) (void) free((FREE_P *)dn); Lmist = 1; return(Lmi); } /* * readvfs() - read vfs structure */ struct l_vfs * readvfs(vm) KA_T vm; /* kernel mount address from vnode */ { struct mount m; struct l_vfs *vp; /* * Search for match on existing entry. */ for (vp = Lvfs; vp; vp = vp->next) { if (vm == vp->addr) return(vp); } /* * Read the (new) mount structure, allocate a local entry, and fill it. */ if (kread((KA_T)vm, (char *)&m, sizeof(m)) != 0) return((struct l_vfs *)NULL); if (!(vp = (struct l_vfs *)malloc(sizeof(struct l_vfs)))) { (void) fprintf(stderr, "%s: PID %d, no space for vfs\n", Pn, Lp->pid); Exit(1); } if (!(vp->dir = mkstrcpy(m.m_stat.f_mntonname, (MALLOC_S *)NULL)) || !(vp->fsname = mkstrcpy(m.m_stat.f_mntfromname, (MALLOC_S *)NULL))) { (void) fprintf(stderr, "%s: PID %d, no space for mount names\n", Pn, Lp->pid); Exit(1); } vp->addr = vm; vp->fsid = m.m_stat.f_fsid; { int len; if ((len = strlen(m.m_stat.f_fstypename))) { if (len > (MFSNAMELEN - 1)) len = MFSNAMELEN - 1; if (!(vp->typnm = mkstrcat(m.m_stat.f_fstypename, len, (char *)NULL, -1, (char *)NULL, -1, (MALLOC_S *)NULL))) { (void) fprintf(stderr, "%s: no space for fs type name: ", Pn); safestrprt(m.m_stat.f_fstypename, stderr, 1); Exit(1); } } else vp->typnm = ""; } vp->next = Lvfs; Lvfs = vp; return(vp); } lsof-4.86+dfsg.orig/dialects/darwin/kmem/machine.h0000444000175000017500000004116411424323072022242 0ustar nicholasnicholas/* * machine.h - Darwin definitions for /dev/kmem-based lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: machine.h,v 1.16 2010/07/29 16:03:04 abe Exp $ */ #if !defined(LSOF_MACHINE_H) #define LSOF_MACHINE_H 1 #include #include # if DARWINV>=800 #include "/usr/include/string.h" # endif /* DARWINV>=800 */ /* * CAN_USE_CLNT_CREATE is defined for those dialects where RPC clnt_create() * can be used to obtain a CLIENT handle in lieu of clnttcp_create(). */ #define CAN_USE_CLNT_CREATE 1 /* * DEVDEV_PATH defines the path to the directory that contains device * nodes. */ #define DEVDEV_PATH "/dev" /* * GET_MAX_FD is defined for those dialects that provide a function other than * getdtablesize() to obtain the maximum file descriptor number plus one. */ /* #define GET_MAX_FD ? */ /* * HASAOPT is defined for those dialects that have AFS support; it specifies * that the default path to an alternate AFS kernel name list file may be * supplied with the -A option. */ /* #define HASAOPT 1 */ /* * HASBLKDEV is defined for those dialects that want block device information * recorded in BDevtp[]. */ #define HASBLKDEV 1 /* * HASDCACHE is defined for those dialects that support a device cache * file. * * HASENVDC defined the name of an environment variable that contains the * device cache file path. The HASENVDC environment variable is ignored when * the lsof process is setuid(root) or its real UID is 0. * * HASPERSDC defines the format for the last component of a personal device * cache file path. The first will be the home directory of the real UID that * executes lsof. * * HASPERSDCPATH defines the environment variable whose value is the middle * component of the personal device cache file path. The middle component * follows the home directory and precedes the results of applying HASPERSDC. * The HASPERSDCPATH environment variable is ignored when the lsof process is * setuid(root) or its real UID is 0. * * HASSYSDC defines a public device cache file path. When it's defined, it's * used as the path from which to read the device cache. * * Consult the 00DCACHE and 00FAQ files of the lsof distribution for more * information on device cache file path construction. */ /* #define HASDCACHE 1 */ /* #define HASENVDC "LSOFDEVCACHE" */ /* #define HASPERSDC "%h/%p.lsof_%L" */ /* #define HASPERSDCPATH "LSOFPERSDCPATH" */ /* #define HASSYSDC "/your/choice/of/path" */ /* * HASCDRNODE is defined for those dialects that have CD-ROM nodes. */ /* #define HASCDRNODE 1 */ /* * HASFIFONODE is defined for those dialects that have FIFO nodes. */ /* #define HASFIFONODE 1 */ /* * HASFSINO is defined for those dialects that have the file system * inode element, fs_ino, in the lfile structure definition in lsof.h. */ /* #define HASFSINO 1 */ /* * HASFSTRUCT is defined if the dialect has a file structure. * * FSV_DEFAULT defines the default set of file structure values to list. * It defaults to zero (0), but may be made up of a combination of the * FSV_* symbols from lsof.h. * * HASNOFSADDR -- has no file structure address * HASNOFSFLAGS -- has no file structure flags * HASNOFSCOUNT -- has no file structure count * HASNOFSNADDR -- has no file structure node address */ #define HASFSTRUCT 1 /* #define FSV_DEFAULT FSV_? | FSV_? | FSV_? */ /* #define HASNOFSADDR 1 has no file structure address */ /* #define HASNOFSFLAGS 1 has no file structure flags */ /* #define HASNOFSCOUNT 1 has no file structure count */ /* #define HASNOFSNADDR 1 has no file structure node address */ /* * HASGNODE is defined for those dialects that have gnodes. */ /* #define HASGNODE 1 */ /* * HASHSNODE is defined for those dialects that have High Sierra nodes. */ /* #define HASHSNODE 1 */ /* * HASINODE is defined for those dialects that have inodes and wish to * use readinode() from node.c. */ # if DARWINV<800 #define HASINODE 1 # endif /* DARWINV<800 */ /* * HASINTSIGNAL is defined for those dialects whose signal function returns * an int. */ /* #define HASINTSIGNAL 1 */ /* * HASKERNIDCK is defined for those dialects that support the comparison of * the build to running kernel identity. */ #define HASKERNIDCK 1 /* * HASKOPT is defined for those dialects that support the -k option of * reading the kernel's name list from an optional file. */ #define HASKOPT 1 /* * HASLFILEADD is defined for those dialects that need additional elements * in struct lfile. The HASLFILEADD definition is a macro that defines * them. If any of the additional elements need to be preset in the * alloc_lfile() function of proc.c, the SETLFILEADD macro may be defined * to do that. * * If any additional elements need to be cleared in alloc_lfile() or in the * free_proc() function of proc.c, the CLRLFILEADD macro may be defined to * do that. Note that CLRLFILEADD takes one argument, the pointer to the * lfile struct. The CLRLFILEADD macro is expected to expand to statements * that are complete -- i.e., have terminating semi-colons -- so the macro is * called without a terminating semicolon by proc.c. * * The HASXOPT definition may be used to select the conditions under which * private lfile elements are used. */ # if DARWINV>=800 #define HASLFILEADD char *V_path; #define CLRLFILEADD(lf) if (lf->V_path) { \ (void) free((FREE_P *)lf->V_path); \ lf->V_path = (char *)NULL; \ } #define SETLFILEADD Lf->V_path = (char *)NULL; # endif /* DARWINV>=800 */ /* * HASMNTSTAT indicates the dialect supports the mount stat(2) result option * in its l_vfs and mounts structures. */ /* #define HASMNTSTAT 1 */ /* * HASMNTSUP is defined for those dialects that support the mount supplement * option. */ /* #define HASMNTSUP 1 */ /* * HASMOPT is defined for those dialects that support the reading of * kernel memory from an alternate file. */ #define HASMOPT 1 /* * HASNCACHE is defined for those dialects that have a kernel name cache * that lsof can search. A value of 1 directs printname() to prefix the * cache value with the file system directory name; 2, avoid the prefix. * * NCACHELDPFX is a set of C commands to execute before calling ncache_load(). * * NCACHELDSFX is a set of C commands to execute after calling ncache_load(). */ # if DARWINV<800 #define HASNCACHE 1 /* #define NCACHELDPFX ??? */ /* #define NCACHELDSFX ??? */ # else /* DARWINV>=800 */ /* #define HASNCACHE 1 */ /* #define NCACHELDPFX ??? */ /* #define NCACHELDSFX ??? */ # endif /* DARWINV<800 */ /* * HASNLIST is defined for those dialects that use nlist() to acccess * kernel symbols. */ #define HASNLIST 1 /* * HASPIPEFN is defined for those dialects that have a special function to * process DTYPE_PIPE file structure entries. Its value is the name of the * function. * * NOTE: don't forget to define a prototype for this function in dproto.h. */ # if DARWINV<800 /* #define HASPIPEFN process_pipe? */ # else /* DARWINV>=800 */ #define HASPIPEFN process_pipe # endif /* DARWINV<800 */ /* * HASPIPENODE is defined for those dialects that have pipe nodes. */ /* #define HASPIPENODE 1 */ /* * HASPMAPENABLED is defined when the reporting of portmapper registration * info is enabled by default. */ /* #define HASPMAPENABLED 1 */ /* * HASPPID is defined for those dialects that support identification of * the parent process IDentifier (PPID) of a process. */ #define HASPPID 1 /* * HASPRINTDEV, HASPRINTINO, HASPRINTNM, HASPRINTOFF, and HASPRINTSZ * define private dialect-specific functions for printing DEVice numbers, * INOde numbers, NaMes, file OFFsets, and file SiZes. The functions are * called from print_file(). */ /* #define HASPRINTDEV print_dev? */ /* #define HASPRINTINO print_ino? */ /* #define HASPRINTNM print_nm? */ /* #define HASPRINTOFF print_off? */ /* #define HASPRINTSZ print_sz? */ /* * HASPRIVFILETYPE and PRIVFILETYPE are defined for dialects that have a * file structure type that isn't defined by a DTYPE_* symbol. They are * used in lib/prfp.c to select the type's processing. * * PRIVFILETYPE is the definition of the f_type value in the file struct. * * HASPRIVFILETYPE is the name of the processing function. */ /* #define HASPRIVFILETYPE process_shmf? */ /* #define PRIVFILETYPE ?? */ /* * HASPRIVNMCACHE is defined for dialects that have a private method for * printing cached NAME column values for some files. HASPRIVNAMECACHE * is defined to be the name of the function. * * The function takes one argument, a struct lfile pointer to the file, and * returns non-zero if it prints a name to stdout. */ # if DARWINV<800 /* #define HASPRIVNMCACHE */ # else /* DARWINV>=800 */ #define HASPRIVNMCACHE print_v_path # endif /* DARWINV<800 */ /* * HASPRIVPRIPP is defined for dialects that have a private function for * printing IP protocol names. When HASPRIVPRIPP isn't defined, the * IP protocol name printing function defaults to printiprto(). */ /* #define HASPRIVPRIPP 1 */ /* * HASPROCFS is defined for those dialects that have a proc file system -- * usually /proc and usually in SYSV4 derivatives. * * HASFSTYPE is defined as 1 for those systems that have a file system type * string, st_fstype, in the stat() buffer; 2, for those systems that have a * file system type integer in the stat() buffer, named MOUNTS_STAT_FSTYPE; * 0, for systems whose stat(2) structure has no file system type member. The * additional symbols MOUNTS_FSTYPE, RMNT_FSTYPE, and RMNT_STAT_FSTYPE may be * defined in dlsof.h to direct how the readmnt() function in lib/rmnt.c * preserves these stat(2) and getmntent(3) buffer values in the local mounts * structure. * * The defined value is the string that names the file system type. * * The HASPROCFS definition usually must be accompanied by the HASFSTYPE * definition and the providing of an fstype element in the local mounts * structure (defined in dlsof.h). * * The HASPROCFS definition may be accompanied by the HASPINODEN definition. * HASPINODEN specifies that searching for files in HASPROCFS is to be done * by inode number. */ # if defined(HASPROCFS) #undef HASPROCFS #define HASPROCFS "proc" # endif /* defined(HASPROCFS) */ /* #define HASPROCFS "proc?" */ /* #define HASFSTYPE 1 */ #define HASPINODEN 1 /* * HASRNODE is defined for those dialects that have rnodes. */ /* #define HASRNODE 1 */ /* * Define HASSECURITY to restrict the listing of all open files to the * root user. When HASSECURITY is defined, the non-root user may list * only files whose processes have the same user ID as the real user ID * (the one that its user logged on with) of the lsof process. */ /* #define HASSECURITY 1 */ /* * If HASSECURITY is defined, define HASNOSOCKSECURITY to allow users * restricted by HASSECURITY to list any open socket files, provide their * listing is selected by the "-i" option. */ /* #define HASNOSOCKSECURITY 1 */ /* * HASSETLOCALE is defined for those dialects that have and * setlocale(). * * If the dialect also has wide character support for language locales, * HASWIDECHAR activates lsof's wide character support and WIDECHARINCL * defines the header file (if any) that must be #include'd to use the * mblen() and mbtowc() functions. */ #define HASSETLOCALE 1 # if DARWINV>=700 #define HASWIDECHAR 1 # endif /* DARWINV>=700 */ /* #define WIDECHARINCL */ /* * HASSNODE is defined for those dialects that have snodes. */ /* #define HASSNODE 1 */ /* * HASTASKS is defined for those dialects that have task reporting support. */ /* #define HASTASKS 1 */ /* * HASSOOPT, HASSOSTATE and HASTCPOPT define the availability of information * on socket options (SO_* symbols), socket states (SS_* symbols) and TCP * options. */ #define HASSOOPT 1 /* has socket option information */ #define HASSOSTATE 1 /* has socket state information */ #define HASTCPOPT 1 /* has TCP options or flags */ /* * Define HASSPECDEVD to be the name of a function that handles the results * of a successful stat(2) of a file name argument. * * For example, HASSPECDEVD() for Darwin makes sure that st_dev is set to * what stat("/dev") returns -- i.e., what's in DevDev. * * The function takes two arguments: * * 1: pointer to the full path name of file * 2: pointer to the stat(2) result * * The function returns void. */ #define HASSPECDEVD process_dev_stat /* * HASSTREAMS is defined for those dialects that support streams. */ /* #define HASSTREAMS 1 */ /* * HASTCPTPIQ is defined for dialects where it is possible to report the * TCP/TPI Recv-Q and Send-Q values produced by netstat. */ #define HASTCPTPIQ 1 /* * HASTCPTPIW is defined for dialects where it is possible to report the * TCP/TPI send and receive window sizes produced by netstat. */ /* #define HASTCPTPIW 1 */ /* * HASTMPNODE is defined for those dialects that have tmpnodes. */ /* #define HASTMPNODE 1 */ /* * HASVNODE is defined for those dialects that use the Sun virtual file system * node, the vnode. BSD derivatives usually do; System V derivatives prior * to R4 usually don't. * doesn't. */ #define HASVNODE 1 /* * HASXOPT is defined for those dialects that have an X option. It * defines the text for the usage display. HASXOPT_VALUE defines the * option's default binary value -- 0 or 1. */ /* #define HASXOPT "help text for X option" */ /* #define HASXOPT_VALUE 1 */ /* * INODETYPE and INODEPSPEC define the internal node number type and its * printf specification modifier. These need not be defined and lsof.h * can be allowed to define defaults. * * These are defined here, because they must be used in dlsof.h. */ # if DARWINV>=800 #define INODETYPE unsigned long long /* inode number internal storage type */ #define INODEPSPEC "ll" /* INODETYPE printf specification * modifier */ # endif /* DARWINV>=800 */ /* * UID_ARG defines the size of a User ID number when it is passed * as a function argument. */ #define UID_ARG int /* * Each USE_LIB_ is defined for dialects that use the * in the lsof library. * * Note: other definitions and operations may be required to condition the * library function source code. They may be found in the dialect dlsof.h * header files. */ #define USE_LIB_CKKV 1 /* ckkv.c */ /* #define USE_LIB_COMPLETEVFS 1 cvfs.c */ #define USE_LIB_FIND_CH_INO 1 /* fino.c */ #define USE_LIB_IS_FILE_NAMED 1 /* isfn.c */ #define USE_LIB_LKUPDEV 1 /* lkud.c */ #define USE_LIB_PRINTDEVNAME 1 /* pdvn.c */ /* #define USE_LIB_PROCESS_FILE 1 prfp.c */ #define USE_LIB_PRINT_TCPTPI 1 /* ptti.c */ /* #define USE_LIB_READDEV 1 rdev.c */ /* #define USE_LIB_READMNT 1 rmnt.c */ /* #define USE_LIB_REGEX 1 regex.c */ /* #define USE_LIB_RNAM 1 rnam.c */ #if DARWINV<800 #define USE_LIB_RNMH 1 /* rnmh.c */ #else /* DARWINV>800 */ /* #define USE_LIB_RNMH 1 rnmh.c */ #endif /* DARWINV<800 */ /* #define USE_LIB_RNCH 1 rnch.c */ /* #define USE_LIB_SNPF 1 snpf.c */ #define snpf snprintf /* use the system's snprintf() */ /* * WARNDEVACCESS is defined for those dialects that should issue a warning * when lsof can't access /dev (or /device) or one of its sub-directories. * The warning can be inhibited by the lsof caller with the -w option. */ #define WARNDEVACCESS 1 /* * WARNINGSTATE is defined for those dialects that want to suppress all lsof * warning messages. */ /* #define WARNINGSTATE 1 warnings are enabled by default */ /* * WILLDROPGID is defined for those dialects whose lsof executable runs * setgid(not_real_GID) and whose setgid power can be relinquished after * the dialect's initialize() function has been executed. */ #define WILLDROPGID 1 /* * zeromem is a macro that uses bzero or memset. */ #define zeromem(a, l) memset(a, 0, l) #endif /* !defined(LSOF_MACHINE_H) */ lsof-4.86+dfsg.orig/dialects/darwin/kmem/Makefile0000444000175000017500000001063511077400052022122 0ustar nicholasnicholas # Darwin /dev/kmem-based lsof Makefile # # $Id: Makefile,v 1.8 2008/10/21 16:15:34 abe Exp $ PROG= lsof BIN= ${DSTROOT}/usr/sbin DOC= ${DSTROOT}/usr/share/man/man8 I=/usr/include S=/usr/include/sys L=/usr/include/local P= CDEF= ${RC_CFLAGS} CDEFS= ${CDEF} ${CFGF} INCL= ${DINC} override CFLAGS= ${CDEFS} ${INCL} ${DEBUG} GRP= HDR= lsof.h lsof_fields.h dlsof.h machine.h proto.h dproto.h SRC= ddev.c dfile.c dmnt.c dnode.c dnode1.c dproc.c dsock.c dstore.c \ arg.c main.c misc.c node.c print.c proc.c store.c usage.c util.c OBJ= ddev.o dfile.o dmnt.o dnode.o dnode1.o dproc.o dsock.o dstore.o \ arg.o main.o misc.o node.o print.o proc.o store.o usage.o util.o MAN= lsof.8 OTHER= SHELL= /bin/sh SOURCE= Makefile ${OTHER} ${MAN} ${HDR} ${SRC} all: ${PROG} ${PROG}: ${LIB} ${P} ${OBJ} ${CC} -o $@ ${CFLAGS} ${OBJ} ${CFGL} clean: FRC rm -f Makefile.bak ${PROG} a.out core errs lint.out tags *.o version.h rm -f machine.h.old new_machine.h (cd lib; ${MAKE} -f Makefile.skel clean) install-strip: all FRC mkdir -p ${BIN} install -c -s -m 2755 -g kmem ${PROG} ${BIN} mkdir -p ${DOC} install -c -m 444 ${MAN} ${DOC} install: all FRC @echo '' @echo 'Please write your own install rule. Lsof for Darwin below 8' @echo 'should be installed setgid to the group that has permission' @echo 'to read /dev/kmem, often kmem or sys. Lsof for Darwin 8 and' @echo 'above should be installed setuid-root. Your install rule' @echo 'actions for Darwin below 8 might look something like this:' @echo '' @echo ' install -m 2xxx -g $${GRP} $${PROG} $${BIN}' @echo ' install -m 444 $${MAN} $${DOC}' @echo '' @echo 'Your install rule actions for Darwin 8 and above might look' @echo 'something like this:' @echo '' @echo ' install -m 4xxx -o root $${PROG} $${BIN}' @echo ' install -m 444 $${MAN} $${DOC}' @echo '' @echo 'You will have to complete the xxx modes, the GRP value, and' @echo 'the skeletons for the BIN and DOC strings, given at the' @echo 'beginning of this Makefile, e.g.,' @echo '' @echo ' BIN= $${DESTDIR}/usr/local/etc' @echo ' DOC= $${DESTDIR}/usr/man/man8' @echo ' GRP= kmem' @echo '' ${LIB}: FRC (cd lib; ${MAKE} DEBUG="${DEBUG}" CFGF="${CFGF}") version.h: FRC @echo Constructing version.h @rm -f version.h @echo '#define LSOF_BLDCMT "${LSOF_BLDCMT}"' > version.h; @echo '#define LSOF_CC "${CC}"' >> version.h @echo '#define LSOF_CCV "${CCV}"' >> version.h @echo '#define LSOF_CCDATE "'`date`'"' >> version.h @echo '#define LSOF_CCFLAGS "'`echo ${CFLAGS} | sed 's/\\\\(/\\(/g' | sed 's/\\\\)/\\)/g' | sed 's/"/\\\\"/g'`'"' >> version.h @echo '#define LSOF_CINFO "${CINFO}"' >> version.h @if [ "X${LSOF_HOST}" = "X" ]; then \ echo '#define LSOF_HOST "'`uname -n`'"' >> version.h; \ else \ if [ "${LSOF_HOST}" = "none" ]; then \ echo '#define LSOF_HOST ""' >> version.h; \ else \ echo '#define LSOF_HOST "${LSOF_HOST}"' >> version.h; \ fi \ fi @echo '#define LSOF_LDFLAGS "${CFGL}"' >> version.h @if [ "X${LSOF_LOGNAME}" = "X" ]; then \ echo '#define LSOF_LOGNAME "${LOGNAME}"' >> version.h; \ else \ if [ "${LSOF_LOGNAME}" = "none" ]; then \ echo '#define LSOF_LOGNAME ""' >> version.h; \ else \ echo '#define LSOF_LOGNAME "${LSOF_LOGNAME}"' >> version.h; \ fi; \ fi @if [ "X${LSOF_SYSINFO}" = "X" ]; then \ echo '#define LSOF_SYSINFO "'`uname -a`'"' >> version.h; \ else \ if [ "${LSOF_SYSINFO}" = "none" ]; then \ echo '#define LSOF_SYSINFO ""' >> version.h; \ else \ echo '#define LSOF_SYSINFO "${LSOF_SYSINFO}"' >> version.h; \ fi \ fi @if [ "X${LSOF_USER}" = "X" ]; then \ echo '#define LSOF_USER "${USER}"' >> version.h; \ else \ if [ "${LSOF_USER}" = "none" ]; then \ echo '#define LSOF_USER ""' >> version.h; \ else \ echo '#define LSOF_USER "${LSOF_USER}"' >> version.h; \ fi \ fi @sed '/VN/s/.ds VN \(.*\)/#define LSOF_VERSION "\1"/' < version >> version.h FRC: # DO NOT DELETE THIS LINE - make depend DEPENDS ON IT ddev.o: ${HDR} ddev.c dfile.o: ${HDR} dfile.c dmnt.o: ${HDR} dmnt.c dnode.o: ${HDR} dnode.c dnode1.o: ${HDR} dnode1.c dproc.o: ${HDR} dproc.c dsock.o: ${HDR} dsock.c dstore.o: ${HDR} dstore.c arg.o: ${HDR} arg.c main.o: ${HDR} main.c misc.o: ${HDR} misc.c node.o: ${HDR} node.c print.o: ${HDR} print.c proc.o: ${HDR} proc.c store.o: ${HDR} store.c usage.o: ${HDR} version.h usage.c util.o: ${HDR} util.c # *** Do not add anything here - It will go away. *** lsof-4.86+dfsg.orig/dialects/osr/0000755000175000017500000000000011741064216017053 5ustar nicholasnicholaslsof-4.86+dfsg.orig/dialects/osr/dstore.c0000444000175000017500000001047607573173306020536 0ustar nicholasnicholas/* * dstore.c - SCO OpenServer global storage for lsof */ /* * Copyright 1995 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1995 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dstore.c,v 1.9 2002/12/03 18:23:08 abe Exp $"; #endif #include "lsof.h" char **Cdevsw = NULL; /* names from kernel's cdevsw[].d_name */ int Cdevcnt = 0; /* Cdevsw[] count */ int CloneMajor; /* clone major device */ /* * Drive_Nl -- table to drive the building of Nl[] via build_Nl() * (See lsof.h and misc.c.) */ struct drive_Nl Drive_Nl[] = { { "ncdev", "cdevcnt" }, { "cdev", "cdevsw" }, { "dnlc", "dnlc__cache" }, /* OSRV>=504 */ { "ndnlc", "dnlc__cacheents" }, /* OSRV>=504 */ { "pdnlc", "dnlc__cache_is_ptr" }, /* OSRV>=507 */ { "dtnc", "dtcache" }, /* 500<=OSRV<504 */ { "htnc", "htcache" }, /* 500<=OSRV<504 */ { "hz", "Hz" }, { "lbolt", "lbolt" }, { "nfnc", "ncache" }, /* HAS_NFS */ { "nnfnc", "nc_size" }, /* HAS_NFS */ { "nxdm", "nxdevmaps" }, /* OSRV>=40 */ { "pregpp", "pregpp" }, /* OSRV<500 */ { "proc", "proc" }, { "scouts", "scoutsname" }, /* OSRV>=500 */ { "sockd", "sockdev" }, { "sockt", "socktab" }, { "s5nc", "s5cache" }, /* OSRV<504 */ { "var", "v" }, { "ndtnc", "v_dtcacheents" }, /* 500<=OSRV<504 */ { "nhtnc", "v_htcacheents" }, /* 500<=OSRV<504 */ { "ns5nc", "v_s5cacheents" }, /* 500<=OSRV<504 */ { "xdm", "xdevmap" }, /* OSRV>=40 */ { NULL, NULL } }; int EventMajor; /* event major device number */ char **Fsinfo = NULL; /* file system information */ int Fsinfomax = 0; /* maximum file system type */ int HaveCloneMajor = 0; /* have clone major device number = 1 */ int HaveEventMajor = 0; /* have event major device number */ int HaveSockdev = 0; /* socket device number status: 1 = available */ int Hz = -1; /* system clock frequency */ int Kd = -1; /* /dev/kmem file descriptor */ KA_T Lbolt = (KA_T)0; /* kernel's lbolt variable address */ int Sockdev; /* socket device number */ KA_T Socktab = (KA_T)0; /* address of socket pointer table */ #if defined(HASFSTRUCT) /* * Pff_tab[] - table for printing file flags */ struct pff_tab Pff_tab[] = { { (long)FREAD, FF_READ }, { (long)FWRITE, FF_WRITE }, { (long)FNDELAY, FF_NDELAY }, { (long)FAPPEND, FF_APPEND }, { (long)FNONBLOCK, FF_NBLOCK }, { (long)FRCACH, FF_RCACH }, { (long)FSTOPIO, FF_STOPIO }, # if defined(FASYNC) { (long)FASYNC, FF_ASYNC }, # endif /* defined(FASYNC`) */ # if defined(FNET) { (long)FNET, FF_NET }, # endif /* defined(FNET) */ # if defined(FSYNC) { (long)FSYNC, FF_SYNC }, # endif /* defined(FSYNC) */ { (long)0, NULL } }; /* * Pof_tab[] - table for print process open file flags */ struct pff_tab Pof_tab[] = { { (long)EXCLOSE, POF_CLOEXEC }, # if defined(AUD_READ) { (long)AUD_READ, POF_BNRD }, # endif /* defined(AUD_READ) */ # if defined(AUD_WRITE) { (long)AUD_WRITE, POF_BNWR }, # endif /* defined(AUDWRITE) */ # if defined(SEC_SIGHUPPED) { (long)SEC_SIGHUPPED, POF_BNHUP }, # endif /* defined(SEC_SIGHUPPED) */ { (long)0, NULL } }; #endif /* defined(HASFSTRUCT) */ #if OSRV>=40 /* * The following items are needed by the internal kernel major() * and minor() macros for mapping extended minor numbers. */ int nxdevmaps = -1; /* maximum kernel xdevmap[] index */ struct XDEVMAP *Xdevmap; /* dynamically allocated xdevmap[] */ #endif /* OSRV>=40 */ lsof-4.86+dfsg.orig/dialects/osr/dsock.c0000444000175000017500000002602010023725056020316 0ustar nicholasnicholas/* * dsock.c - SCO OpenServer socket processing functions for lsof */ /* * Copyright 1995 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1995 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dsock.c,v 1.15 2004/03/10 23:52:12 abe Exp $"; #endif #include "lsof.h" /* * process_socket() - process socket */ void process_socket(i) struct inode *i; /* inode pointer */ { char *cp; struct domain d; unsigned char *fa = (unsigned char *)NULL; int fam, j, k; int fp, lp; unsigned char *la = (unsigned char *)NULL; int p; struct inpcb pcb; short pcbs = 0; short udpsf, udpsl; struct socket s; KA_T sa, spa; struct stdata sd; struct queue sh; short shs = 0; struct tcpcb t; short ts = 0; struct udpdev udp; short udptm = 0; #if OSRV<500 struct sockaddr_in *si; #else /* OSRV>=500 */ struct sockaddr_in si; struct un_dev ud; #endif /* OSRV<500 */ (void) snpf(Lf->type, sizeof(Lf->type), "sock"); /* * Read socket. */ if (!Socktab) { (void) enter_nm("No kernel socket table"); return; } spa = Socktab + (GET_MIN_DEV(i->i_rdev) * sizeof(struct socket *)); if (kread(spa, (char *)&sa, sizeof(sa))) { (void) snpf(Namech, Namechl, "can't read socket pointer at %s", print_kptr(spa, (char *)NULL, 0)); enter_nm(Namech); } if (kread(sa, (char *)&s, sizeof(s))) { (void) snpf(Namech, Namechl, "can't read socket structure at %s", print_kptr(sa, (char *)NULL, 0)); enter_nm(Namech); return; } /* * Read domain structure. */ if (!s.so_proto.pr_domain || kread((KA_T)s.so_proto.pr_domain, (char *)&d, sizeof(d))) { (void) snpf(Namech, Namechl, "can't read protocol domain from %s", print_kptr((KA_T)s.so_proto.pr_domain, (char *)NULL, 0)); enter_nm(Namech); return; } /* * Process by protocol domain. */ switch ((fam = d.dom_family)) { case AF_INET: if (Fnet) Lf->sf |= SELNET; (void) snpf(Lf->type, sizeof(Lf->type), "inet"); printiproto((int)s.so_proto.pr_protocol); Lf->inp_ty = 2; /* * Get protocol control block address from stream head queue structure. */ if (s.so_stp && !readstdata((KA_T)s.so_stp, &sd) && !readsthead((KA_T)sd.sd_wrq, &sh)) shs = 1; if (shs && sh.q_ptr) { enter_dev_ch(print_kptr((KA_T)sh.q_ptr, (char *)NULL, 0)); if (kread((KA_T)sh.q_ptr, (char *)&pcb, sizeof(pcb)) == 0) pcbs = 1; } /* * Print local and remote addresses. */ if (pcbs) { if (pcb.inp_ppcb && strcasecmp(Lf->iproto, "udp") == 0) { /* * If this is a UDP socket file, get the udpdev structure * at the PCB's per-protocol control block address. It * may contain a foreign address. */ if (!kread((KA_T)pcb.inp_ppcb, (char *)&udp, sizeof(udp))) { #if OSRV>=500 if (udp.ud_lsin.sin_addr.s_addr != INADDR_ANY || udp.ud_lsin.sin_port != 0) udpsl = 1; else udpsl = 0; #endif /* OSRV>=500 */ if (udp.ud_fsin.sin_addr.s_addr != INADDR_ANY || udp.ud_fsin.sin_port != 0) udpsf = 1; else udpsf = 0; } } else udpsf = udpsl = 0; /* * Print the local address from the PCB. If there is none, and if * this is a 5.0.0 or greater UDP stream, and if it has a local * address set, use it. */ la = (unsigned char *)&pcb.inp_laddr; lp = (int)ntohs(pcb.inp_lport); #if OSRV>=500 if (((struct in_addr *)la)->s_addr == INADDR_ANY && lp == 0 && udpsl) { la = (unsigned char *)&udp.ud_lsin.sin_addr; lp = (int)ntohs(udp.ud_lsin.sin_port); } #endif /* OSRV>=500 */ /* * Use the PCB's foreign address if it is set. If not, and if this * is a UDP socket file, use the udpdev structure's foreign address * if it's set. */ if (pcb.inp_faddr.s_addr != INADDR_ANY || pcb.inp_fport != 0) { fa = (unsigned char *)&pcb.inp_faddr; fp = (int)ntohs(pcb.inp_fport); } else if (udpsf) { fa = (unsigned char *)&udp.ud_fsin.sin_addr; fp = (int)ntohs(udp.ud_fsin.sin_port); udptm = 1; } if (la || fa) { (void) ent_inaddr(la, lp, fa, fp, AF_INET); if (udptm && !Lf->nma) (void)udp_tm(udp.ud_ftime); } if (pcb.inp_ppcb && strcasecmp(Lf->iproto, "tcp") == 0 && kread((KA_T)pcb.inp_ppcb, (char *)&t, sizeof(t)) == 0) { ts = 1; /* * Save the TCP state from its control block. */ Lf->lts.type = 0; Lf->lts.state.i = (int)t.t_state; } } else { #if OSRV<500 if ((si = (struct sockaddr_in *)&s.so_name)) { la = (unsigned char *)&si->sin_addr; lp = (int)ntohs(si->sin_port); } if ((si = (struct sockaddr_in *)&s.so_peer)) { if (si->sin_addr.s_addr != INADDR_ANY || si->sin_port != 0) { fa = (unsigned char *)&si->sin_addr; fp = (int)ntohs(si->sin_port); } } #else /* OSRV>=500 */ if (s.so_name && !kread((KA_T)s.so_name, (char *)&si, sizeof(si))) { la = (unsigned char *)&si.sin_addr; lp = (int)ntohs(si.sin_port); } if (s.so_peer && !kread((KA_T)s.so_peer, (char *)&si, sizeof(si))) { if (si.sin_addr.s_addr != INADDR_ANY || si.sin_port != 0) { fa = (unsigned char *)&si.sin_addr; fp = (int)ntohs(si.sin_port); } } #endif /* OSRV<500 */ if (la || fa) (void) ent_inaddr(la, lp, fa, fp, AF_INET); } /* * Save options, sizes, states and values. */ #if defined(HASSOOPT) Lf->lts.ltm = (unsigned int)s.so_linger; Lf->lts.opt = (unsigned int)s.so_options; Lf->lts.qlen = (unsigned int)s.so_qlen; Lf->lts.qlim = (unsigned int)s.so_qlimit; Lf->lts.qlens = Lf->lts.qlims = (unsigned char)1; if (ts && t.t_timer[TCPT_KEEP]) { Lf->lts.opt |= SO_KEEPALIVE; Lf->lts.kai = (unsigned long)t.t_timer[TCPT_KEEP]; } #endif /* defined(HASSOOPT) */ #if defined(HASSOSTATE) Lf->lts.ss = s.so_state; #endif /* defined(HASSOSTATE) */ if (ts) { #if defined(HASTCPOPT) Lf->lts.topt = (unsigned int)t.t_flags; Lf->lts.mss = (unsigned long)t.t_maxseg; Lf->lts.msss = (unsigned char)1; #endif /* defined(HASTCPOPT) */ #if defined(HASTCPTPIQ) Lf->lts.rq = (unsigned long)t.t_iqsize; Lf->lts.sq = (unsigned long)t.t_qsize; Lf->lts.rqs = Lf->lts.sqs = 1; #endif /* defined(HASTCPTPIQ) */ if (Fsize) { if (Lf->access == 'r') Lf->sz = (SZOFFTYPE)t.t_iqsize; else if (Lf->access == 'w') Lf->sz = (SZOFFTYPE)t.t_qsize; else Lf->sz = (SZOFFTYPE)(t.t_iqsize + t.t_qsize); Lf->sz_def = 1; } else Lf->off_def = 1; } else if (shs) { if (Fsize) { Lf->sz = (SZOFFTYPE)sh.q_count; Lf->sz_def = 1; } else Lf->off_def = 1; } else Lf->off_def = 1; break; #if OSRV>=500 case AF_UNIX: if (Funix) Lf->sf |= SELUNX; (void) snpf(Lf->type, sizeof(Lf->type), "unix"); /* * Read Unix protocol control block and the Unix address structure. */ enter_dev_ch(print_kptr(sa, (char *)NULL, 0)); Lf->off_def = 1; if (s.so_stp && !readstdata((KA_T)s.so_stp, &sd) && !readsthead((KA_T)sd.sd_wrq, &sh)) { if (!sh.q_ptr || kread((KA_T)sh.q_ptr, (char *)&ud, sizeof(ud))) { (void) snpf(Namech, Namechl, "can't read un_dev from %s", print_kptr((KA_T)sh.q_ptr, (char *)NULL, 0)); break; } if (ud.so_rq) enter_dev_ch(print_kptr((KA_T)ud.so_rq, (char *)NULL, 0)); if (ud.local_addr.sun_family == AF_UNIX) { Lf->inode = (unsigned long)ud.bnd_param.user_addr.inode_no; Lf->inp_ty = 1; ud.local_addr.sun_path[sizeof(ud.local_addr.sun_path) - 1] = '\0'; if (Sfile && is_file_named(ud.local_addr.sun_path, 0)) Lf->sf |= SELNM; if (!Namech[0]) (void) snpf(Namech,Namechl,"%s",ud.local_addr.sun_path); } else if (ud.for_addr.sun_family == AF_UNIX) { Lf->inode = (unsigned long)ud.bnd_param.user_addr.inode_no; Lf->inp_ty = 1; ud.for_addr.sun_path[sizeof(ud.for_addr.sun_path) - 1] = '\0'; if (Sfile && is_file_named(ud.for_addr.sun_path, 0)) Lf->sf |= SELNM; else (void) snpf(Namech,Namechl,"%s",ud.for_addr.sun_path); } else if (ud.other_q) (void) snpf(Namech, Namechl, "->%s", print_kptr((KA_T)ud.other_q, (char *)NULL, 0)); } else (void) snpf(Namech, Namechl, "can't get un_dev"); break; #endif /* OSRV>=500 */ default: printunkaf(fam, 1); } enter_nm(Namech); } /* * udp_tm() - compute time since UDP packet was last sent */ void udp_tm(tm) time_t tm; /* time when packet was sent */ { static char buf[32], *cp; time_t et, lbolt; MALLOC_S len; short hr, min, sec; /* * Read the lightning bolt timer and compute the elapsed time. * No elapsed time is returned if: * the global clock frequency variable, Hz, is negative; * the lightning bolt timer is unavailable; * the lightning bolt time is less than the UDP send time; * the elapsed time is zero. */ if (!Lbolt) return; if (Hz < 0 || kread((KA_T)Lbolt, (char *)&lbolt, sizeof(lbolt)) || tm >= lbolt || (et = (time_t)((lbolt - tm) / Hz)) == 0) return; /* * If the time is 100 hours or greater, return the elapsed time as seconds. */ if (et >= (100 * 60 * 60)) { (void) snpf(buf, sizeof(buf), "%lds", et); cp = &buf[strlen(buf)]; } else { /* * Convert seconds to hours, minutes and seconds. */ hr = (short)(et / (60 * 60)); et %= (60 * 60); min = (short)(et / 60); sec = (short)(et % 60); cp = buf; /* * Format the elapsed time and attach single character suffixes to * represent the units: * * `h' = hours * `m' = minutes * `s' = seconds */ if (hr) { (void) snpf(cp, sizeof(buf) - (cp - buf), "%dh", hr); cp += 2 + ((hr > 9) ? 1 : 0); } if (min) { (void) snpf(cp, sizeof(buf) - (cp - buf), "%dm", min); cp += 2 + ((min > 9) ? 1 : 0); } if (sec) { (void) snpf(cp, sizeof(buf) - (cp - buf), "%ds", sec); cp += 2 + ((sec > 9) ? 1 : 0); } } /* * Add the `` ago'' trailer. Return the string's address and length. */ (void) snpf(cp, sizeof(buf) - (cp - buf), " ago"); len = (MALLOC_S)(strlen(buf) + 1); if (len < 2) return; if (!(cp = (char *)malloc(len))) { (void) fprintf(stderr, "%s: no space for %d character UDP time\n", Pn, len); Exit(1); } (void) snpf(cp, len, "%s", buf); Lf->nma = cp; } lsof-4.86+dfsg.orig/dialects/osr/include/0000755000175000017500000000000007057254246020507 5ustar nicholasnicholaslsof-4.86+dfsg.orig/dialects/osr/include/sys/0000755000175000017500000000000007057254245021324 5ustar nicholasnicholaslsof-4.86+dfsg.orig/dialects/osr/include/sys/cdefs.h0000644000175000017500000000717606301074044022560 0ustar nicholasnicholas/* * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)cdefs.h 8.2 (Berkeley) 10/4/93 */ #ifndef _CDEFS_H_ #define _CDEFS_H_ #if defined(__cplusplus) #define __BEGIN_DECLS extern "C" { #define __END_DECLS }; #else #define __BEGIN_DECLS #define __END_DECLS #endif /* * The __CONCAT macro is used to concatenate parts of symbol names, e.g. * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo. * The __CONCAT macro is a bit tricky -- make sure you don't put spaces * in between its arguments. __CONCAT can also concatenate double-quoted * strings produced by the __STRING macro, but this only works with ANSI C. */ #if defined(__STDC__) || defined(__cplusplus) #define __P(protos) protos /* full-blown ANSI C */ #define __CONCAT(x,y) x ## y #define __STRING(x) #x #if !defined(__GNUC__) && !defined(__cplusplus) #define inline #endif #else /* !(__STDC__ || __cplusplus) */ #define __P(protos) () /* traditional C preprocessor */ #define __CONCAT(x,y) x/**/y #define __STRING(x) "x" #ifdef __GNUC__ #define const __const /* GCC: ANSI C with -traditional */ #define inline __inline #define signed __signed #define volatile __volatile #else /* !__GNUC__ */ #define const /* delete ANSI C keywords */ #define inline #define signed #define volatile #endif /* !__GNUC__ */ #endif /* !(__STDC__ || __cplusplus) */ /* * GCC has extensions for declaring functions as `pure' (always returns * the same value given the same inputs, i.e., has no external state and * no side effects) and `dead' (nonreturning). These mainly affect * optimization and warnings. Unfortunately, GCC complains if these are * used under strict ANSI mode (`gcc -ansi -pedantic'), hence we need to * define them only if compiling without this. */ #if defined(__GNUC__) && !defined(__STRICT_ANSI__) #define __dead __volatile #define __pure __const #else #define __dead #define __pure #endif #endif /* !_CDEFS_H_ */ lsof-4.86+dfsg.orig/dialects/osr/include/netdb.h0000644000175000017500000001101206301074043021731 0ustar nicholasnicholas/*- * Copyright (c) 1980, 1983, 1988 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)netdb.h 5.15 (Berkeley) 4/3/91 */ #ifndef _NETDB_H_ #define _NETDB_H_ #define _PATH_HEQUIV "/etc/hosts.equiv" #define _PATH_HOSTS "/etc/hosts" #define _PATH_NETWORKS "/etc/networks" #define _PATH_PROTOCOLS "/etc/protocols" #define _PATH_SERVICES "/etc/services" /* * Structures returned by network data base library. All addresses are * supplied in host order, and returned in network order (suitable for * use in system calls). */ struct hostent { char *h_name; /* official name of host */ char **h_aliases; /* alias list */ int h_addrtype; /* host address type */ int h_length; /* length of address */ char **h_addr_list; /* list of addresses from name server */ #define h_addr h_addr_list[0] /* address, for backward compatiblity */ }; /* * Assumption here is that a network number * fits in 32 bits -- probably a poor one. */ struct netent { char *n_name; /* official name of net */ char **n_aliases; /* alias list */ int n_addrtype; /* net address type */ unsigned long n_net; /* network # */ }; struct servent { char *s_name; /* official service name */ char **s_aliases; /* alias list */ int s_port; /* port # */ char *s_proto; /* protocol to use */ }; struct protoent { char *p_name; /* official protocol name */ char **p_aliases; /* alias list */ int p_proto; /* protocol # */ }; /* * Error return codes from gethostbyname() and gethostbyaddr() * (left in extern int h_errno). */ #define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */ #define TRY_AGAIN 2 /* Non-Authoritive Host not found, or SERVERFAIL */ #define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ #define NO_DATA 4 /* Valid name, no data record of requested type */ #define NO_ADDRESS NO_DATA /* no address, look for MX record */ #include __BEGIN_DECLS void endhostent __P((void)); void endnetent __P((void)); void endprotoent __P((void)); /* void endservent __P((void)); */ struct hostent *gethostbyaddr __P((const char *, int, int)); struct hostent *gethostbyname __P((char *)); struct hostent *gethostent __P((void)); struct netent *getnetbyaddr __P((long, int)); /* u_long? */ struct netent *getnetbyname __P((const char *)); struct netent *getnetent __P((void)); struct protoent *getprotobyname __P((const char *)); struct protoent *getprotobynumber __P((int)); struct protoent *getprotoent __P((void)); struct servent *getservbyname __P((const char *, const char *)); struct servent *getservbyport __P((int, const char *)); struct servent *getservent __P((void)); void herror __P((const char *)); void sethostent __P((int)); /* void sethostfile __P((const char *)); */ void setnetent __P((int)); void setprotoent __P((int)); /* void setservent __P((int)); */ __END_DECLS #endif /* !_NETDB_H_ */ lsof-4.86+dfsg.orig/dialects/osr/dproc.c0000444000175000017500000012777610613427325020351 0ustar nicholasnicholas/* * dproc.c - SCO OpenServer process access functions for lsof */ /* * Copyright 1995 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1995 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dproc.c,v 1.18 2007/04/24 16:22:40 abe Exp $"; #endif #include "lsof.h" /* * Local static values */ static KA_T Kp; /* kernel process table address */ static KA_T *Nc = (KA_T *)NULL; /* node cache */ static int Nn = 0; /* number of Nc[] entries allocated */ #if OSRV<500 static int Npp = 0; /* number of pregions per process */ static struct pregion *Pr = (struct pregion *)NULL; /* pregion buffer */ static int Prsz = 0; /* size of Pr */ #endif /* OSRV<500 */ static struct var Var; /* kernel variables */ _PROTOTYPE(static void get_cdevsw,(void)); _PROTOTYPE(static void get_kernel_access,(void)); #if !defined(N_UNIX) _PROTOTYPE(static int is_boot,(char *p)); #endif /* !defined(N_UNIX) */ _PROTOTYPE(static int open_kmem,(int nx)); _PROTOTYPE(static void process_text,(KA_T prp)); _PROTOTYPE(static void readfsinfo,(void)); /* * Ckkv - check kernel version */ static void Ckkv(d, er, ev, ea) char *d; /* dialect */ char *er; /* expected release */ char *ev; /* expected version */ char *ea; /* expected architecture */ { #if defined(HASKERNIDCK) struct scoutsname s; if (Fwarn) return; /* * Read OSR kernel information. */ if (__scoinfo(&s, sizeof(s)) < 0) { (void) fprintf(stderr, "%s: can't get __scoinfo: %s\n", Pn, strerror(errno)); Exit(1); } /* * Warn if the actual and expected releases don't match. */ if (!er || strcmp(er, s.release)) (void) fprintf(stderr, "%s: WARNING: compiled for %s release %s; this is %s.\n", Pn, d, er ? er : "UNKNOWN", s.release); #endif /* defined(HASKERNIDCK) */ } /* * gather_proc_info() -- gather process information */ void gather_proc_info() { int i, j, nf, pbc, px; struct proc *p; static char *pb = (char *)NULL; int pid, pgrp; short pss, sf; static struct user *u; static char *ua = (char *)NULL; static MALLOC_S ual = 0; unsigned int uid; #if defined(HASFSTRUCT) static MALLOC_S npofb = 0; char *pof; static char *pofb = (char *)NULL; #endif /* defined(HASFSTRUCT) */ /* * Allocate user structure buffer. */ if (!ua) { ual = (MALLOC_S)(MAXUSIZE * NBPC); if (!(ua = (char *)malloc(ual))) { (void) fprintf(stderr, "%s: no space for %d byte user structure buffer\n", Pn, ual); Exit(1); } u = (struct user *)ua; } /* * Allocate proc structure buffer. */ if (!pb) { if (!(pb = (char *)malloc(sizeof(struct proc) * PROCBFRD))) { (void) fprintf(stderr, "%s: no space for %d proc structures\n", Pn, PROCBFRD); Exit(1); } } /* * Examine proc structures and their associated information. */ for (pbc = px = 0; px < Var.v_proc; px++) { if (px >= pbc) { /* * Refill proc buffer. */ i = Var.v_proc - px; if (i > PROCBFRD) i = PROCBFRD; j = kread((KA_T)(Kp + (px * sizeof(struct proc))), pb, sizeof(struct proc) * i); pbc = px + i; p = (struct proc *)pb; if (j) { px += i; continue; } } else p++; if (p->p_stat == 0 || p->p_stat == SZOMB) continue; /* * Get Process ID, Process group ID, and User ID. */ pid = (int)p->p_pid; pgrp = (int)p->p_pgrp; uid = (unsigned int)p->p_uid; if (is_proc_excl(pid, pgrp, (UID_ARG)uid, &pss, &sf)) continue; /* * Get the user area associated with the process. */ if (sysi86(RDUBLK, pid, ua, MAXUSIZE * NBPC) == -1) continue; /* * Allocate a local process structure. */ if (is_cmd_excl(u->u_comm, &pss, &sf)) continue; alloc_lproc(pid, pgrp, (int)p->p_ppid, (UID_ARG)uid, u->u_comm, (int)pss, (int)sf); Plf = (struct lfile *)NULL; /* * Save current working directory information. */ if (u->u_cdir) { alloc_lfile(CWD, -1); process_node((KA_T)u->u_cdir); if (Lf->sf) link_lfile(); } /* * Save root directory information. */ if (u->u_rdir) { alloc_lfile(RTD, -1); process_node((KA_T)u->u_rdir); if (Lf->sf) link_lfile(); } /* * Print information on the text file. */ if (p->p_region) process_text((KA_T)p->p_region); /* * Save information on file descriptors. */ #if OSRV<42 nf = Var.v_nofiles; #else /* OSRV>=42 */ nf = u->u_nofiles ? u->u_nofiles : Var.v_nofiles; #endif /* OSRV<42 */ #if defined(HASFSTRUCT) if (Fsv & FSV_FG) { /* * If u_pofile is in the u block, set its address. */ if (nf && u->u_pofile && ((unsigned)u->u_pofile >= UVUBLK) && ((MALLOC_S)((unsigned)u->u_pofile - UVUBLK + nf) <= ual)) { pof = ua + (unsigned)u->u_pofile - UVUBLK; } else if (nf && u->u_pofile) { /* * Allocate space for u_pofile and read it from kernel memory. */ if (nf > npofb) { if (!pofb) pofb = (char *)malloc((MALLOC_S)nf); else pofb = (char *)realloc((MALLOC_P *)pofb, (MALLOC_S)nf); if (!pofb) { (void) fprintf(stderr, "%s: no pofile space\n", Pn); Exit(1); } npofb = nf; } if (kread((KA_T)u->u_pofile, pofb, nf)) pof = (char *)NULL; else pof = pofb; } else pof = (char *)NULL; } #endif /* defined(HASFSTRUCT) */ for (i = 0; i < nf; i++) { if (u->u_ofile[i]) { alloc_lfile((char *)NULL, i); process_file((KA_T)u->u_ofile[i]); if (Lf->sf) { #if defined(HASFSTRUCT) if (Fsv & FSV_FG && pof) Lf->pof = (long)pof[i]; #endif /* defined(HASFSTRUCT) */ link_lfile(); } } } /* * Examine results. */ if (examine_lproc()) return; } } /* * get_cdevsw() - get cdevsw[] names and record clone major device number */ void get_cdevsw() { char buf[16]; struct cdevsw *c, *tmp; int i, j, len; struct stat sb; KA_T v[2]; /* * Check cdevsw[] kernel addresses. * Read cdevsw[] count from kernel's cdevcnt. */ if (get_Nl_value("cdev", Drive_Nl, &v[0]) < 0 || get_Nl_value("ncdev", Drive_Nl, &v[1]) < 0 || !v[0] || !v[1] || kread(v[1], (char *)&Cdevcnt, sizeof(Cdevcnt)) || Cdevcnt < 1) return; /* * Allocate cache space. */ if (!(Cdevsw = (char **)malloc(Cdevcnt * sizeof(char *)))) { (void) fprintf(stderr, "%s: no space for %d cdevsw[] names\n", Pn, Cdevcnt); Exit(1); } /* * Allocate temporary space for a copy of cdevsw[] and read it. */ i = Cdevcnt * sizeof(struct cdevsw); if (!(tmp = (struct cdevsw *)malloc(i))) { (void) fprintf(stderr, "%s: no space for %d cdevsw[] entries\n", Pn, Cdevcnt); Exit(1); } if (kread((KA_T)v[0], (char *)tmp, i)) { (void) free((FREE_P *)Cdevsw); Cdevsw = (char **)NULL; Cdevcnt = 0; (void) free((FREE_P *)tmp); return; } /* * Cache the names from cdevsw[].d_name. * Record the number of the "clone" device. */ j = sizeof(buf) - 1; buf[j] = '\0'; for (c = tmp, i = 0; i < Cdevcnt; c++, i++) { Cdevsw[i] = (char *)NULL; if (!c->d_name) continue; if (kread((KA_T)c->d_name, buf, j)) { (void) fprintf(stderr, "%s: WARNING: can't read name for cdevsw[%d]: %#x\n", Pn, i, c->d_name); continue; } if (!buf[0]) continue; len = strlen(buf) + 1; if (!(Cdevsw[i] = (char *)malloc(len))) { (void) fprintf(stderr, "%s: no space for cdevsw[%d] name: %s\n", Pn, i, buf); Exit(1); } (void) snpf(Cdevsw[i], len, "%s", buf); if (!HaveCloneMajor && strcmp(buf, "clone") == 0) { CloneMajor = i; HaveCloneMajor = 1; continue; } if (!HaveEventMajor && strcmp(buf, "ev") == 0) { if (stat("/dev/event", &sb) == 0 && GET_MAJ_DEV(sb.st_rdev) == i) { EventMajor = i; HaveEventMajor = 1; } } } (void) free((FREE_P *)tmp); } /* * get_kernel_access() - get access to kernel memory */ static void get_kernel_access() { time_t lbolt; MALLOC_S len; KA_T v; /* * Check kernel version. */ (void) Ckkv("OSR", LSOF_VSTR, (char *)NULL, (char *)NULL); /* * See if the name list file is readable. */ if (Nmlst && !is_readable(Nmlst, 1)) Exit(1); /* * Access kernel symbols. */ #if defined(N_UNIX) (void) build_Nl(Drive_Nl); if (nlist(Nmlst ? Nmlst : N_UNIX, Nl) < 0) #else /* !defined(N_UNIX) */ if (!get_nlist_path(0)) #endif /* defined(N_UNIX) */ { (void) fprintf(stderr, "%s: can't read kernel name list.\n", Pn); Exit(1); } /* * Open access to kernel memory. */ (void) open_kmem(0); #if defined(WILLDROPGID) /* * Drop setgid permission. */ (void) dropgid(); #endif /* defined(WILLDROPGID) */ /* * Check proc table pointer. */ if (get_Nl_value("proc", Drive_Nl, &Kp) < 0 || !Kp) { (void) fprintf(stderr, "%s: no proc table pointer\n", Pn); Exit(1); } #if OSRV<500 /* * Read pregion information. */ v = (KA_T)0; if (get_Nl_value("pregpp", Drive_Nl, &v) < 0 || !v || kread(v, (char *)&Npp, sizeof(Npp)) || Npp < 1) { (void) fprintf(stderr, "%s: can't read pregion count (%d) from %s\n", Pn, Npp, print_kptr(v, (char *)NULL, 0)); Exit(1); } Prsz = (MALLOC_S)(Npp * sizeof(struct pregion)); if (!(Pr = (struct pregion *)malloc(Prsz))) { (void) fprintf(stderr, "%s: can't allocate space for %d pregions\n", Pn, Npp); Exit(1); } #endif /* OSRV< 500 */ /* * Read system configuration information. */ if (get_Nl_value("var", Drive_Nl, &v) < 0 || !v || kread((KA_T)v, (char *)&Var, sizeof(Var))) { (void) fprintf(stderr, "%s: can't read system configuration info\n", Pn); Exit(1); } /* * Read system clock values -- Hz and lightning bolt timer. */ v = (KA_T)0; if (get_Nl_value("hz", Drive_Nl, &v) < 0 || !v || kread(v, (char *)&Hz, sizeof(Hz))) { if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: can't read Hz from %s\n", Pn, print_kptr(v, (char *)NULL, 0)); Hz = -1; } if (get_Nl_value("lbolt", Drive_Nl, &Lbolt) < 0 || !v || kread((KA_T)v, (char *)&lbolt, sizeof(lbolt))) { if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: can't read lightning bolt timer from %s\n", Pn, print_kptr(v, (char *)NULL, 0)); Lbolt = (KA_T)0; } /* * Get socket device number and socket table address. */ if (get_Nl_value("sockd", Drive_Nl, &v) < 0 || !v || kread(v, (char *)&Sockdev, sizeof(Sockdev))) { (void) fprintf(stderr, "%s: WARNING: can't identify socket device.\n", Pn); (void) fprintf(stderr, " Socket output may be incomplete.\n"); return; } if (get_Nl_value("sockt", Drive_Nl, &Socktab) < 0 || !Socktab) { (void) fprintf(stderr, "%s: WARNING: socket table address is NULL.\n", Pn); (void) fprintf(stderr, " Socket output may be incomplete.\n"); return; } #if OSRV>=40 /* * Get extended device table parameters. These are needed by the kernel * versions of the major() and minor() device number macros; they also * identify socket devices and assist in the conversion of socket device * numbers to socket table addresses. */ v = (KA_T)0; if (get_Nl_value("nxdm", Drive_Nl, &v) < 0 || !v || kread(v, (char *)&nxdevmaps, sizeof(nxdevmaps)) || nxdevmaps < 0) { (void) fprintf(stderr, "%s: bad extended device table size (%d) at %s.\n", Pn, nxdevmaps, print_kptr(v, (char *)NULL, 0)); Exit(1); } len = (MALLOC_S)((nxdevmaps + 1) * sizeof(struct XDEVMAP)); if (!(Xdevmap = (struct XDEVMAP *)malloc(len))) { (void) fprintf(stderr, "%s: no space for %d byte xdevmap table\n", Pn, len); Exit(1); } v = (KA_T)0; if (get_Nl_value("xdm", Drive_Nl, &v) < 0 || !v || kread((KA_T)v, (char *)Xdevmap, len)) { (void) fprintf(stderr, "%s: can't read %d byte xdevmap table at #x\n", Pn, len, v); Exit(1); } #endif /* OSRV>=40 */ HaveSockdev = 1; } #if !defined(N_UNIX) /* * get_nlist_path() - get kernel nlist() path * * As a side effect on a successful return (non-NULL character pointer), the * boot path's name list will have been loaded into Nl[]. */ char * get_nlist_path(ap) int ap; /* on success, return an allocated path * string pointer if 1; return a * constant character pointer if 0; * return NULL if failure */ { FILE *bf; char *bfp, b1[MAXPATHLEN+1], b2[MAXPATHLEN+1], *pp, *tp; struct dirent *de; char *dir[] = { "/", "/stand/", NULL }; DIR *dp; int i; MALLOC_S len; /* * If a kernel name list file was specified, use it. */ if (Nmlst) { if (is_boot(Nmlst)) return(Nmlst); return((char *)NULL); } /* * If it's possible to open /etc/ps/booted system, search it for a preferred * boot path, defined by the value of a line that begins with "KERNEL=". */ bfp = pp = (char *)NULL; if ((bf = fopen("/etc/ps/booted.system", "r"))) { len = strlen("KERNEL="); while (fgets(b1, sizeof(b1), bf)) { if (strncmp(b1, "KERNEL=", len) != 0) continue; if ((tp = strrchr(&b1[len], '\n'))) { *tp = '\0'; if (b1[len]) { bfp = &b1[len]; if (is_boot(bfp)) { pp = bfp; (void) fclose(bf); goto get_nlist_return_path; } break; } } } (void) fclose(bf); } /* * Look for possible unix* boot paths. */ for (i = 0; dir[i]; i++) { if (!(dp = opendir(dir[i]))) continue; while ((de = readdir(dp))) { /* * Use the next entry that begins with "unix". */ if (strncmp("unix", de->d_name, 4) != 0) continue; /* * Construct a temporary copy of the path name, * If it matches the preferred boot name, skip it. */ len = strlen(dir[i]) + strlen(de->d_name) + 1; if (len >= sizeof(b2)) continue; (void) snpf(b2, sizeof(b2), "%s%s", dir[i], de->d_name); if (bfp && strcmp(b2, bfp) == 0) continue; /* * See if it's the booted kernel. */ if (is_boot(b2)) { (void) closedir(dp); pp = b2; get_nlist_return_path: /* * A boot path has been located. As requested return a * malloc'd pointer to it. */ if (!ap) return(""); len = (MALLOC_S)(strlen(pp) + 1); if (!(tp = (char *)malloc(len))) { (void) fprintf(stderr, "%s: can't allocate %d bytes for: %s\n", Pn, len , pp); Exit(1); } (void) snpf(tp, len, "%s", pp); return(tp); } } if (dp) (void) closedir(dp); } return((char *)NULL); } #endif /* !defined(N_UNIX) */ /* * initialize() - perform all initialization */ void initialize() { get_kernel_access(); get_cdevsw(); readfsinfo(); if (Fsv & FSV_NI) NiTtl = "INODE-ADDR"; } #if !defined(N_UNIX) /* * is_boot() - does the specified path lead to a booted kernel */ is_boot(p) char *p; /* specified path */ { int i; KA_T ka; union { struct scoutsname s; unsigned char sc[sizeof(struct scoutsname)]; } s1, s2; /* * Get the scoutsname structure via __scoinfo() to use as a reference against * the one obtained via kread()'ing from the nlist() address. * If __scoinfo() fails, return the default boot path. */ if (__scoinfo(&s1.s, sizeof(s1.s)) < 0) return 0; /* * Get the name list for this boot path. Using the scoutsname address, read * the scoutsname structure and compare it to the _s_scoinfo() one. If the * two match, this is the boot path. */ if (Nl) { (void) free((FREE_P *)Nl); Nl = (struct NLIST_TYPE *)NULL; } (void) build_Nl(Drive_Nl); if (nlist(p, Nl) < 0) return(0); if (get_Nl_value("scouts", Drive_Nl, &ka) < 0 || !ka) return(0); if (Kd < 0) { if (open_kmem(1)) return(0); } if (kread(ka, (char *)&s2.s, sizeof(s2.s))) return(0); for (i = 0; i < sizeof(struct scoutsname); i++) { if (s1.sc[i] != s2.sc[i]) return(0); } return(1); } #endif /* !defined(N_UNIX) */ /* * kread() - read from kernel memory */ int kread(addr, buf, len) KA_T addr; /* kernel memory address */ char *buf; /* buffer to receive data */ READLEN_T len; /* length to read */ { int br; if (lseek(Kd, (off_t)addr, SEEK_SET) == (off_t)-1L) return(1); if ((br = read(Kd, buf, len)) < 0) return(1); return(((READLEN_T)br == len) ? 0 : 1); } /* * open_kmem() - open kernel memory access */ static int open_kmem(nx) int nx; /* no Exit(1) if 1 */ { if (Kd >= 0) return(0); /* * See if the non-KMEM memory file is readable. */ if (Memory && !is_readable(Memory, 1)) { if (nx) return(1); Exit(1); } /* * Open kernel memory access. */ if ((Kd = open(Memory ? Memory : KMEM, O_RDONLY, 0)) < 0) { if (nx) return(1); (void) fprintf(stderr, "%s: can't open %s: %s\n", Pn, Memory ? Memory : KMEM, strerror(errno)); Exit(1); } return(0); } /* * process_text() - process text access information */ static void process_text(prp) KA_T prp; /* process region pointer */ { int i, j, k; struct pregion *p; struct region r; KA_T na; char *ty, tyb[8]; #if OSRV>=500 KA_T pc; struct pregion ps; #endif /* OSRV>=500 */ /* * Read and process the pregions. */ #if OSRV<500 if (kread(prp, (char *)Pr, Prsz)) return; for (i = j = 0, p = Pr; i < Npp; i++, p++) #else /* OSRV>=500 */ for (i = j = 0, p = &ps, pc = prp; pc; pc = (KA_T)p->p_next, i++) #endif /* OSRV<500 */ { #if OSRV>=500 /* * Avoid infinite loop. */ if (i > 1000) { if (!Fwarn) (void) fprintf(stderr, "%s: too many virtual address regions for PID %d\n", Pn, Lp->pid); return; } if ((i && pc == prp) || kread((KA_T)pc, (char *)p, sizeof(ps))) return; #endif /* OSRV>=500 */ if (!p->p_reg) continue; /* * Read the region. * Skip entries with no node pointers and duplicate node addresses. */ if (kread((KA_T)p->p_reg, (char *)&r, sizeof(r))) continue; if (!(na = (KA_T)r.r_iptr)) continue; for (k = 0; k < j; k++) { if (Nc[k] == na) break; } if (k < j) continue; /* * Cache the node address for duplicate checking. */ if (!Nc) { if (!(Nc = (KA_T *)malloc((MALLOC_S)(sizeof(KA_T) * 10)))) { (void) fprintf(stderr, "%s: no txt ptr space, PID %d\n", Pn, Lp->pid); Exit(1); } Nn = 10; } else if (j >= Nn) { Nn += 10; if (!(Nc = (KA_T *)realloc((MALLOC_P *)Nc, (MALLOC_S)(Nn * sizeof(KA_T))))) { (void) fprintf(stderr, "%s: no more txt ptr space, PID %d\n", Pn, Lp->pid); Exit(1); } } Nc[j++] = na; /* * Save text node and mapped region information. */ switch (p->p_type) { case PT_DATA: /* data and text of */ case PT_TEXT: /* executing binaries */ ty = " txt"; break; case PT_LIBDAT: /* shared library data and */ case PT_LIBTXT: /* COFF format text */ ty = " ltx"; break; case PT_SHFIL: /* memory mapped file */ ty = " mem"; break; case PT_V86: /* virtual 8086 mode */ ty = " v86"; break; case PT_VM86: /* MERGE386 vm86 region */ ty = " m86"; break; default: /* all others as a hex number */ (void) snpf(tyb, sizeof(tyb), " M%02x", p->p_type & 0xff); ty = tyb; } if (ty) { alloc_lfile(ty, -1); process_node(na); if (Lf->sf) link_lfile(); } } } /* * readfsinfo() - read file system information */ static void readfsinfo() { char buf[FSTYPSZ+1]; int i, len; if ((Fsinfomax = sysfs(GETNFSTYP)) == -1) { (void) fprintf(stderr, "%s: sysfs(GETNFSTYP) error: %s\n", Pn, strerror(errno)); Exit(1); } if (Fsinfomax == 0) return; if (!(Fsinfo = (char **)malloc((MALLOC_S)(Fsinfomax * sizeof(char *))))) { (void) fprintf(stderr, "%s: no space for sysfs info\n", Pn); Exit(1); } for (i = 1; i <= Fsinfomax; i++) { if (sysfs(GETFSTYP, i, buf) == -1) { (void) fprintf(stderr, "%s: sysfs(GETFSTYP) error: %s\n", Pn, strerror(errno)); Exit(1); } buf[FSTYPSZ] = '\0'; len = strlen(buf) + 1; if (!(Fsinfo[i-1] = (char *)malloc((MALLOC_S)len))) { (void) fprintf(stderr, "%s: no space for file system entry %s\n", Pn, buf); Exit(1); } (void) snpf(Fsinfo[i-1], len, "%s", buf); } } #if defined(HASNCACHE) /* * Prepare for and #include the appropriate header files. */ # if OSRV>=500 #undef IFIR #undef IFIW #undef IRCOLL #undef IWCOLL # endif /* OSRV>=500 */ #include # if defined(HAS_NFS) #include # endif /* defined(HAS_NFS) */ # if OSRV>=500 # if OSRV<504 #include #undef IFIR #undef IFIW #undef IRCOLL #undef IWCOLL #define _INKERNEL #include #undef _INKERNEL # else /* OSRV>=504 */ #include # endif /* OSRV<504 */ # endif /* OSRV>=500 */ /* * Determine the maximum size of the cache name character array. */ # if OSRV<504 #define MAXNSZ DIRSIZ # if OSRV>=500 && DTNCMAX>MAXNSZ #undef MAXNSZ #define MAXNSZ DTNCMAX # endif /* OSRV>=500 && DTNCMAX>MAXNSZ */ # else /* OSRV>=504 */ #define MAXNSZ DNLC_NAMELEN # endif /* OSRV<504 */ # if defined(HAS_NFS) && NC_NAMLEN>MAXNSZ #undef MAXNSZ #define MAXNSZ NC_NAMLEN # endif /* defined(HAS_NFS) && NC_NAMLEN>MAXNSZ */ /* * Define the local name cache structures. */ struct lnch { /* local name cache structure */ union { struct ldev { /* device-inode info */ dev_t dev; /* device */ unsigned long inum; /* inode number */ unsigned long pa_inum; /* parent inode number */ } ld; struct lnfs { /* NFS info */ KA_T rp; /* rnode address */ KA_T dp; /* parent rnode address */ } ln; } u; char nm[MAXNSZ+1]; /* name */ unsigned char nl; /* name length */ unsigned char dup; /* duplicate if 1 */ unsigned char type; /* type: 0 = device-inode; 1 = NFS */ struct lnch *pa; /* parent address */ struct lnch *next; /* link to next same-type structure */ }; struct lnch_hh { /* device-inode and NFS hash head */ struct lnch *hp[2]; /* [0] = device-inode; [1] = NFS*/ }; /* * Local name cache (LNC) definitions, macros, and static values */ #define LCHUNKSZ 256 /* local "chunk" size for reading the * kernel DNLC -- used for OSRV>=504 */ static int LNC_asz = 0; /* LNC cache allocated size */ static int LNC_csz = 0; /* LNC cache current size */ #define LNCHHLEN 64 /* hash head length (must be a * power of 2) */ #define LNCINCR 256 /* LNC size increment */ #define LNCINIT 1024 /* LNC initial size */ #define DIN_hash(d, i) &LNC_hh[((((int)(d + i)>>2)*31415)&(LNCHHLEN-1))] # if defined(HAS_NFS) #define NFS_hash(r) &LNC_hh[((((int)(r)>>2)*31415)&(LNCHHLEN-1))] # endif /* defined(HAS_NFS) */ static struct lnch_hh *LNC_hh = (struct lnch_hh *)NULL; /* LNC hash head pointers */ static struct lnch *LNC_nc = (struct lnch *)NULL; /* the linear LNC */ /* * Local function prototypes */ _PROTOTYPE(static struct lnch *DIN_addr,(dev_t *d, unsigned long i)); # if OSRV>=500 # if OSRV>=504 _PROTOTYPE(static void DNLC_load,()); # else /* OSRV<504 */ _PROTOTYPE(static void DTFS_load,()); _PROTOTYPE(static void HTFS_load,()); # endif /* OSRV>=504 */ # endif /* OSRV>=500 */ _PROTOTYPE(static int LNC_enter,(struct lnch *le, char *nm, int nl, char *fs)); _PROTOTYPE(static void LNC_nosp,(int len)); # if defined(HAS_NFS) _PROTOTYPE(static struct lnch *NFS_addr,(KA_T r)); _PROTOTYPE(static void NFS_load,(void)); _PROTOTYPE(static int NFS_root,(KA_T r)); # endif /* defined(HAS_NFS) */ # if OSRV<504 _PROTOTYPE(static void SYSV_load,()); # endif /* OSRV<504 */ /* * DIN_addr() - look up a node's local device-inode address */ static struct lnch * DIN_addr(d, i) dev_t *d; /* device number */ unsigned long i; /* inode number */ { struct lnch_hh *hh = DIN_hash(*d, i); struct lnch *lc = hh->hp[0]; while (lc) { if (lc->u.ld.dev == *d && lc->u.ld.inum == i) return(lc); lc = lc->next; } return((struct lnch *)NULL); } # if OSRV>=504 /* * DNLC_load() - load DNLC cache */ static void DNLC_load() { int ccl; /* current "chunk" length */ int ccs; /* current "chunk" size */ int ccx; /* current "chunk" index */ static int cha = 0; /* "chunk" allocation size */ static int chl = 0; /* "chunk" allocation length */ struct dnlc__cachent *cp; static struct dnlc__cachent *dnlc = (struct dnlc__cachent *)NULL; static int dnlce = 0; int i, len; static KA_T ka = (KA_T)0; struct lnch lc; char nm[DNLC_NAMELEN+1]; KA_T v; char *wa; /* "working" kernel DNLC * address */ /* * Do first-time setup, as required. */ if (dnlce == 0) { /* * Quit if the DNLC name cache address is unknown. */ if (get_Nl_value("dnlc", Drive_Nl, &ka) < 0 || !ka) return; /* * Determine of the DNLC name cache address is that of an array or a * pointer to the array. */ v = (KA_T)NULL; if (get_Nl_value("pdnlc", Drive_Nl, &v) >= 0 && v) { /* * If the DNLC name cache address is that of a pointer to an array, * get the array's address. If that fails, return without comment * and without further action. */ if (kread(ka, (char *)&ka, sizeof(ka))) return; } /* * Get the kernel's DNLC name cache size. */ if (get_Nl_value("ndnlc", Drive_Nl, &v) < 0 || !v || kread(v, (char *)&dnlce, sizeof(dnlce)) || dnlce < 1) return; /* * Allocate space for a copy of a portion ("chunk") of the kernel's * DNLC name cache. */ cha = (dnlce <= LCHUNKSZ) ? dnlce : LCHUNKSZ; chl = sizeof(struct dnlc__cachent) * cha; if (!(dnlc = (struct dnlc__cachent *)malloc(chl))) { (void) fprintf(stderr, "%s: can't allocate %d bytes for DNLC chunk\n", Pn, chl); cha = 0; Exit(1); } } /* * Prepare to read the kernel's DNLC name cache. */ if (!cha || !chl || !dnlc || !ka) return; /* * Build a local copy of the kernel's DNLC name cache, reading the kernel data * a "chunk" at a time. */ nm[DNLC_NAMELEN] = '\0'; lc.type = 0; for (ccl = ccs = i = 0, wa = (char *)ka; i < dnlce; i += ccs, wa += ccl) { /* * Read the next "chunk". */ ccs = ((dnlce - i) < cha) ? (dnlce - i) : cha; ccl = sizeof(struct dnlc__cachent) * ccs; if (kread((KA_T)wa, (char *)dnlc, ccl)) break; /* * Process the "chunk". */ for (ccx = 0, cp = dnlc; ccx < ccs; cp++, ccx++) { if (!cp->dev && !cp->newinum) continue; (void) strncpy(nm, cp->name, DNLC_NAMELEN); if ((len = strlen(nm)) < 1) continue; if (len < 3 && nm[0] == '.') { if (len == 1 || (len == 2 && nm[1] == '.')) continue; } lc.u.ld.dev = cp->dev; lc.u.ld.inum = (unsigned long)cp->newinum; lc.u.ld.pa_inum = (unsigned long)cp->inum; if (LNC_enter(&lc, nm, len, "DNLC")) break; } } /* * If not repeating, free kernel DNLC name cache buffer space. */ if (dnlc && !RptTm) { (void) free((MALLOC_P *)dnlc); dnlc = (struct dnlc__cachent *)NULL; dnlce = cha = chl = 0; } } # endif /* OSRV>=504 */ # if OSRV>=500 && OSRV<504 /* * DTFS_load() - load DTFS cache */ static void DTFS_load() { struct dtcachent *cp; static struct dtcachent *dtnc = (struct dtcachent *)NULL; static int dtnce = 0; int i, len; static KA_T ka = (KA_T)NULL; static int kcl = 0; struct lnch lc; char nm[DTNCMAX+1]; KA_T v; /* * Do first-time setup, as required. */ if (dtnce == 0) { /* * Quit if the DTFS name cache address is unknown. */ if (get_Nl_value("dtnc", Drive_Nl, &ka) < 0 || !ka) return; /* * Get the kernel's DTFS name cache size. */ if (get_Nl_value("ndtnc", Drive_Nl, &v) < 0 || !v || kread(v, (char *)&dtnce, sizeof(dtnce)) || dtnce < 1) return; /* * Allocate space for a copy of the kernel's DTFS name cache. */ kcl = sizeof(struct dtcachent) * dtnce; if (!(dtnc = (struct dtcachent *)malloc(kcl))) { (void) fprintf(stderr, "%s: can't allocate %d bytes for DTFS name cache\n", Pn, kcl); Exit(1); } } /* * Read the kernel's DTFS name cache. */ if (!dtnc || !kcl || !ka || kread(ka, (char *)dtnc, kcl)) return; /* * Build a local copy of the kernel's DTFS name cache. */ lc.type = 0; nm[DTNCMAX] = '\0'; for (cp = dtnc, i = 0; i < dtnce; cp++, i++) { if (!cp->dn_dev && !cp->dn_newinum) continue; (void) strncpy(nm, cp->dn_name, DTNCMAX); if ((len = strlen(nm)) < 1) continue; if (len < 3 && cp->dn_name[0] == '.') { if (len == 1 || (len == 2 && cp->dn_name[1] == '.')) continue; } lc.u.ld.dev = cp->dn_dev; lc.u.ld.inum = (unsigned long)cp->dn_newinum; lc.u.ld.pa_inum = (unsigned long)cp->dn_inum; if (LNC_enter(&lc, nm, len, "DTFS")) break; } /* * If not repeating, free kernel DTFS name cache buffer space. */ if (dtnc && !RptTm) { (void) free((MALLOC_P *)dtnc); dtnc = (struct dtcachent *)NULL; dtnce = kcl = 0; } } /* * HTFS_load() - load HTFS cache */ static void HTFS_load() { struct htcachent *cp; static struct htcachent *htnc = (struct htcachent *)NULL; static int htnce = 0; int i, len; static KA_T ka = (KA_T)NULL; static int kcl = 0; struct lnch lc; char nm[DIRSIZ+1]; KA_T v; /* * Do first-time setup, as required. */ if (htnce == 0) { /* * Quit if the HTFS name cache address is unknown. */ if (get_Nl_value("htnc", Drive_Nl, &ka) < 0 || !ka) return; /* * Get the kernel's HTFS name cache size. */ if (get_Nl_value("nhtnc", Drive_Nl, &v) < 0 || !v || kread(v, (char *)&htnce, sizeof(htnce)) || htnce < 1) return; /* * Allocate space for a copy of the kernel's HTFS name cache. */ kcl = sizeof(struct htcachent) * htnce; if (!(htnc = (struct htcachent *)malloc(kcl))) { (void) fprintf(stderr, "%s: can't allocate %d bytes for HTFS name cache\n", Pn, kcl); Exit(1); } } /* * Read the kernel's HTFS name cache. */ if (!htnc || !kcl || !ka || kread(ka, (char *)htnc, kcl)) return; /* * Build a local copy of the kernel's HTFS name cache. */ lc.type = 0; nm[DIRSIZ] = '\0'; for (cp = htnc, i = 0; i < htnce; cp++, i++) { if (!cp->dev && !cp->newinum) continue; (void) strncpy(nm, cp->name, DIRSIZ); if ((len = strlen(nm)) < 1) continue; if (len < 3 && cp->name[0] == '.') { if (len == 1 || (len == 2 && cp->name[1] == '.')) continue; } lc.u.ld.dev = (dev_t)cp->dev; lc.u.ld.inum = (unsigned long)cp->newinum; lc.u.ld.pa_inum = (unsigned long)cp->inum; if (LNC_enter(&lc, nm, len, "HTFS")) break; } /* * If not repeating, free kernel HTFS name cache buffer space. */ if (htnc && !RptTm) { (void) free((MALLOC_P *)htnc); htnc = (struct htcachent *)NULL; htnce = kcl = 0; } } # endif /* OSRV>=500 && OSRV<504 */ /* * LNC_enter() - make a local name cache entry */ static int LNC_enter(le, nm, nl, fs) struct lnch *le; /* skeleton local entry */ char *nm; /* name */ int nl; /* name length */ char *fs; /* file system name */ { struct lnch *lc; MALLOC_S len; if (LNC_csz >= LNC_asz) { LNC_asz += LNCINCR; len = (MALLOC_S)(LNC_asz * sizeof(struct lnch)); if (!(LNC_nc = (struct lnch *)realloc(LNC_nc, len))) { (void) fprintf(stderr, "%s: no more space for %d byte local name cache: %s\n", Pn, len, fs); Exit(1); } } lc = &LNC_nc[LNC_csz]; if ((lc->type = le->type) == 1) { /* * Make an NFS entry. */ lc->u.ln.rp = le->u.ln.rp; lc->u.ln.dp = le->u.ln.dp; } else { /* * Make a device-inode entry. */ lc->u.ld.dev = le->u.ld.dev; lc->u.ld.inum = le->u.ld.inum; lc->u.ld.pa_inum = le->u.ld.pa_inum; } /* * Enter the name and its size, clear the duplicate flag, * and advance the linear cache entry count. */ if (nl > MAXNSZ) { if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: length for \"%s\" too large: %d\n", Pn, nm, nl); nl = MAXNSZ; } (void) strncpy(lc->nm, nm, nl); lc->nm[nl] = '\0'; lc->nl = (unsigned char)nl; lc->dup = 0; lc->next = lc->pa = (struct lnch *)NULL; LNC_csz++; return(0); } /* * LNC_nosp() - notify that we're out of space for the local name cache */ static void LNC_nosp(len) int len; /* attempted length */ { if (!Fwarn) (void) fprintf(stderr, "%s: no space for %d byte local name cache\n", Pn, len); Exit(1); } /* * ncache_load() - load the kernel's NFS and DEV name caches */ void ncache_load() { struct lnch_hh *hh; struct lnch *hl, *hlp, *lc; int f, i, len; if (!Fncache) return; /* * Initialize local name cache, as required. */ if (LNC_asz == 0) { LNC_asz = LNCINIT; len = LNCINIT * sizeof(struct lnch); if (!(LNC_nc = (struct lnch *)malloc((MALLOC_S)len))) (void) LNC_nosp(len); } LNC_csz = 0; # if defined(HAS_NFS) /* * Load NFS cache. */ (void) NFS_load(); # endif /* defined(HAS_NFS) */ # if OSRV<504 /* * Load the device-inode SYSV file system cache. */ (void) SYSV_load(); # if OSRV>=500 /* * Load the device-inode DT and HT file system caches. */ (void) DTFS_load(); (void) HTFS_load(); # endif /* OSRV>=500 */ # else /* OSRV>=504 */ /* * Load the device-inode combined file system cache. */ (void) DNLC_load(); # endif /* OSRV<504 */ /* * Reduce local name cache memory usage, as required. */ if (LNC_csz < 1) { LNC_csz = 0; if (!RptTm) { (void) free((FREE_P *)LNC_nc); LNC_nc = (struct lnch *)NULL; } return; } if (LNC_csz < LNC_asz && !RptTm) { len = LNC_csz * sizeof(struct lnch); if (!(LNC_nc = (struct lnch *)realloc(LNC_nc, len))) (void)LNC_nosp(len); LNC_asz = LNC_csz; } /* * Initialize hash head pointers. */ if (!LNC_hh) { LNC_hh = (struct lnch_hh *)calloc(LNCHHLEN, sizeof(struct lnch_hh)); if (!LNC_hh) { (void) fprintf(stderr, "%s: can't allocate %d bytes for name cache hash table\n", Pn, LNCHHLEN * sizeof(struct lnch_hh)); Exit(1); } } else (void) zeromem((void *)LNC_hh, (LNCHHLEN * sizeof(struct lnch_hh))); /* * Enter local name cache pointers in the hash table. Look for entries with * the same identifications that have different names. */ for (i = 0, lc = LNC_nc; i < LNC_csz; i++, lc++) { # if defined(HAS_NFS) if (lc->type) hh = NFS_hash(lc->u.ln.rp); else # endif /* defined(HAS_NFS) */ hh = DIN_hash(lc->u.ld.dev, lc->u.ld.inum); if (!(hl = hh->hp[lc->type])) { hh->hp[lc->type] = lc; continue; } for (f = 0, hlp = hl; hl; hlp = hl, hl = hl->next) { # if defined(HAS_NFS) if (lc->type == 1) { if (lc->u.ln.rp != hl->u.ln.rp) continue; } else # endif /* defined(HAS_NFS) */ { if (lc->u.ld.dev != hl->u.ld.dev || lc->u.ld.inum != hl->u.ld.inum) continue; } if (strcmp(lc->nm, hl->nm) == 0) f = 1; else { f = 2; /* same identifiers, different names */ break; } } if (!f) hlp->next = lc; else if (f == 2) { /* * Since entries with the same identification but different names * were located, mark entries with the same identification as * duplicates. */ for (hl = hh->hp[lc->type]; hl; hl = hl->next) { # if defined(HAS_NFS) if (lc->type == 1) { if (lc->u.ln.rp == hl->u.ln.rp) hl->dup = 1; continue; } # endif /* defined(HAS_NFS) */ if (hl->u.ld.dev == lc->u.ld.dev && hl->u.ld.inum == lc->u.ld.inum) hl->dup = 1; } } } /* * Make a final pass through the local name cache and convert parent * identifications to local name cache pointers. Ignore duplicates. */ for (i = 0, lc = LNC_nc; i < LNC_csz; i++, lc++) { if (lc->dup) continue; # if defined(HAS_NFS) if (lc->type == 1) { if (lc->u.ln.dp) lc->pa = NFS_addr(lc->u.ln.dp); continue; } # endif /* defined(HAS_NFS) */ if (lc->u.ld.dev && lc->u.ld.pa_inum) lc->pa = DIN_addr(&lc->u.ld.dev, lc->u.ld.pa_inum); } } /* * ncache_lookup() - look up a node's name in the kernel's name caches */ char * ncache_lookup(buf, blen, fp) char *buf; /* receiving name buffer */ int blen; /* receiving buffer length */ int *fp; /* full path reply */ { char *cp = buf; int nl, rlen; struct lnch *lc; *cp = '\0'; *fp = 0; /* * If the entry has an inode number that matches the inode number of the * file system mount point, return an empty path reply. That tells the * caller to print the file system mount point name only. */ if (Lf->inp_ty == 1 && Lf->fs_ino && Lf->inode == Lf->fs_ino) return(cp); if (!LNC_nc) return((char *)NULL); #if defined(HAS_NFS) /* * Look up the NFS name cache entry. */ if (Lf->is_nfs) { if ((lc = NFS_addr(Lf->na)) && !lc->dup) { if ((nl = (int)lc->nl) > (blen - 1)) return(*cp ? cp : (char *)NULL); cp = buf + blen - nl - 1; rlen = blen - nl - 1; (void) snpf(cp, nl + 1, "%s", lc->nm); /* * Look up the NFS name cache entries that are parents of the * rnode address. Quit when: * * there's no parent; * the parent is a duplicate; * the name is too large to fit in the receiving buffer. */ for (;;) { if (!lc->pa) { if (NFS_root(lc->u.ln.dp)) *fp = 1; break; } lc = lc->pa; if (lc->dup) break; if (((nl = (int)lc->nl) + 1) > rlen) break; *(cp - 1) = '/'; cp--; rlen--; (void) strncpy((cp - nl), lc->nm, nl); cp -= nl; rlen -= nl; } return(*cp ? cp : (char *)NULL); } return((char *)NULL); } # endif /* defined(HAS_NFS) */ /* * Look up the device-inode name cache entry. */ if (Lf->dev_def && Lf->inp_ty == 1 && (lc = DIN_addr(&Lf->dev, Lf->inode)) && !lc->dup) { if ((nl = (int)lc->nl) > (blen - 1)) return(*cp ? cp : (char *)NULL); cp = buf + blen - nl - 1; rlen = blen - nl - 1; (void) snpf(cp, nl + 1, "%s", lc->nm); /* * Look up the LNC name cache entries that are parents of the * device and inode number. Quit when: * * there's no parent; * the parent is a duplicate cache entry; * the name is too large to fit in the receiving buffer. */ for (;;) { if (!lc->pa) { if (lc->u.ld.pa_inum && Lf->fs_ino && lc->u.ld.pa_inum == Lf->fs_ino) *fp = 1; break; } lc = lc->pa; if (lc->dup) break; if (lc->u.ld.inum && Lf->fs_ino && lc->u.ld.inum == Lf->fs_ino) { *fp = 1; break; } if (((nl = (int)lc->nl) + 1) > rlen) break; *(cp - 1) = '/'; cp--; rlen--; (void) strncpy((cp - nl), lc->nm, nl); cp -= nl; rlen -= nl; } return(*cp ? cp : (char *)NULL); } return((char *)NULL); } # if defined(HAS_NFS) /* * NFS_addr() - look up a node's local NFS_nc address */ static struct lnch * NFS_addr(r) KA_T r; /* rnode's address */ { struct lnch_hh *hh = NFS_hash(r); struct lnch *lc = hh->hp[1]; while (lc) { if (lc->u.ln.rp == r) return(lc); lc = lc->next; } return((struct lnch *)NULL); } /* * NFS_load() -- load kernel's NFS name cache */ static void NFS_load() { struct ncache *cp; int i, len; struct lnch lc; static KA_T ka = (KA_T)NULL; static int kcl = 0; static struct ncache *nfnc = (struct ncache *)NULL; static int nfnce = 0; char nm[NC_NAMLEN+1]; KA_T v; /* * Do first-time setup, as required. */ if (nfnce == 0) { /* * Quit if the NFS name cache address is unknown. */ if (get_Nl_value("nfnc", Drive_Nl, &ka) < 0 || !ka) return; /* * Get the kernel's NFS name cache size. */ if (get_Nl_value("nnfnc", Drive_Nl, &v) < 0 || !v || kread(v, (char *)&nfnce, sizeof(nfnce)) || nfnce < 1) return; /* * Allocate space for a copy of the kernel's NFS name cache. */ kcl = nfnce * sizeof(struct ncache); if (!(nfnc = (struct ncache *)malloc(kcl))) { (void) fprintf(stderr, "%s: can't allocate %d bytes for NFS name cache\n", Pn, kcl); Exit(1); } } /* * Read the kernel's NFS name cache. */ if (!nfnc || !kcl || !ka || kread(ka, (char *)nfnc, kcl)) return; /* * Build a local copy of the kernel's NFS name cache. */ lc.type = 1; for (cp = nfnc, i = 0; i < nfnce; cp++, i++) { if (!cp->rp) continue; if ((len = cp->namlen) < 0 || len > NC_NAMLEN) continue; (void) strncpy(nm, cp->name, len); nm[len] = '\0'; if ((len = strlen(nm)) < 1) continue; if (len < 3 && nm[0] == '.') { if (len == 1 || (len == 2 && nm[1] == '.')) continue; } lc.u.ln.rp = (KA_T)cp->rp; lc.u.ln.dp = (KA_T)cp->dp; if (LNC_enter(&lc, nm, len, "NFS")) break; } /* * If not repeating, free kernel NFS name cache buffer space. */ if (nfnc && !RptTm) { (void) free((MALLOC_P *)nfnc); nfnc = (struct ncache *)NULL; kcl = nfnce = 0; } } static int NFS_root(r) KA_T r; /* node's rnode address */ { int i; MALLOC_S len; static int rnc = 0; static int rnca = 0; static KA_T *rc = (KA_T *)NULL; struct rnode rn; unsigned short *n; unsigned long nnum; # if OSRV>=500 unsigned short *n1; # endif /* OSRV>=500 */ if (!Lf->fs_ino || !r) return(0); /* * Search NFS root rnode cache. */ for (i = 0; i < rnc; i++) { if (rc[i] == r) return(1); } /* * Read rnode and get the node number. */ if (kread(r, (char *)&rn, sizeof(rn))) return(0); # if OSRV<500 n = (unsigned short *)&rn.r_fh.fh_pad[14]; if (!(nnum = (unsigned long)ntohs(*n))) nnum = (unsigned long)rn.r_fh.fh_u.fh_fgen_u; # else /* OSRV>=500 */ n = (unsigned short *)&rn.r_fh.fh_u.fh_fid_u[4]; n1 = (unsigned short *)&rn.r_fh.fh_u.fh_fid_u[2]; if (!(nnum = (unsigned long)*n)) nnum = (unsigned long)*n1; # endif /* OSRV<500 */ if (!nnum || nnum != Lf->fs_ino) return(0); /* * Add the rnode address to the NFS root rnode cache. */ if (rnc >= rnca) { if (rnca == 0) { len = (MALLOC_S)(10 * sizeof(KA_T)); if ((rc = (KA_T *)malloc(len))) rnca = 10; } else { len = (MALLOC_S)((rnca + 10) * sizeof(KA_T)); if ((rc = (KA_T *)realloc(rc, len))) rnca += 10; } if (!rc) { (void) fprintf(stderr, "%s: no space for root rnode table\n", Pn); Exit(1); } } rc[rnc++] = r; return(1); } # endif /* defined(HAS_NFS) */ # if OSRV<504 /* * SYSV_load() - load SYSV cache */ static void SYSV_load() { struct s5cachent *cp; int i, len; static KA_T ka = (KA_T)NULL; static int kcl = 0; struct lnch lc; char nm[DIRSIZ+1]; static struct s5cachent *s5nc = (struct s5cachent *)NULL; static int s5nce = 0; KA_T v; /* * Do first-time setup, as required. */ if (s5nce == 0) { /* * Quit if the SYSV name cache address is unknown. */ if (get_Nl_value("s5nc", Drive_Nl, &ka) < 0 || !ka) return; /* * Get the kernel's SYSV name cache size. */ # if OSRV<500 s5nce = Var.v_s5cacheents; # else /* OSRV>=500 */ if (get_Nl_value("nsfnc", Drive_Nl, &v) < 0 || !v || kread(v, (char *)&s5nce, sizeof(s5nce))) return; # endif /* OSRV<500 */ if (s5nce < 1) return; /* * Allocate space for a copy of the kernel's SYSV name cache. */ kcl = sizeof(struct s5cachent) * s5nce; if (!(s5nc = (struct s5cachent *)malloc(kcl))) { (void) fprintf(stderr, "%s: can't allocate %d bytes for SYSV name cache\n", Pn, kcl); Exit(1); } } /* * Read the kernel's SYSV name cache. */ if (!s5nc || !kcl || !ka || kread(ka, (char *)s5nc, kcl)) return; /* * Build a local copy of the kernel's SYSV name cache. */ nm[DIRSIZ] = '\0'; lc.type = 0; for (cp = s5nc, i = 0; i < s5nce; cp++, i++) { if (!cp->dev && !cp->newinum) continue; (void) strncpy(nm, cp->name, DIRSIZ); if ((len = strlen(nm)) < 1) continue; if (len < 3 && cp->name[0] == '.') { if (len == 1 || (len == 2 && cp->name[1] == '.')) continue; } lc.u.ld.dev = (dev_t)cp->dev; lc.u.ld.inum = (unsigned long)cp->newinum; lc.u.ld.pa_inum = (unsigned long)cp->inum; if (LNC_enter(&lc, nm, len, "SYSV")) break; } /* * If not repeating, free kernel SYSV name cache buffer space. */ if (s5nc && !RptTm) { (void) free((MALLOC_P *)s5nc); s5nc = (struct s5cachent *)NULL; kcl = s5nce = 0; } } # endif /* OSRV<504 */ #endif /* defined(HASNCACHE) */ lsof-4.86+dfsg.orig/dialects/osr/dproto.h0000444000175000017500000000363306733707025020545 0ustar nicholasnicholas/* * dproto.h - SCO OpenServer function prototypes for lsof * * The _PROTOTYPE macro is defined in the common proto.h. */ /* * Copyright 1995 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: dproto.h,v 1.5 99/06/22 08:22:28 abe Exp $ */ _PROTOTYPE(extern int is_file_named,(char *p, int cd)); _PROTOTYPE(extern void process_socket,(struct inode *i)); _PROTOTYPE(extern int get_max_fd,(void)); #if OSRV<500 _PROTOTYPE(extern int endservent,(void)); _PROTOTYPE(extern int setservent,(int)); # if defined(HASSTATLSTAT) _PROTOTYPE(extern int statlstat,(const char *, struct stat *)); # endif /* defined(HASTSTATLSTAT) */ _PROTOTYPE(extern int strcasecmp,(char *, char *)); _PROTOTYPE(extern int strncasecmp,(char *, char *, unsigned int)); _PROTOTYPE(extern pid_t wait,()); #endif /* OSRV<500 */ _PROTOTYPE(extern int sysi86,()); _PROTOTYPE(extern int sysfs,()); _PROTOTYPE(extern void udp_tm,(time_t tm)); #if !defined(N_UNIX) _PROTOTYPE(extern char *get_nlist_path,(int pd)); #endif /* !defined(N_UNIX) */ lsof-4.86+dfsg.orig/dialects/osr/dlsof.h0000444000175000017500000001503410613427323020333 0ustar nicholasnicholas/* * dlsof.h - SCO OpenServer header file for lsof */ /* * Copyright 1995 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: dlsof.h,v 1.14 2007/04/24 16:22:40 abe Exp $ */ #if !defined(OSR_LSOF_H) #define OSR_LSOF_H 1 #include #include #include #include #include #include #include # if OSRV>=500 #include # endif /* OSRV>=500 */ #include #include #include #include #include #include #include #include #include #include #include /* * This confusing sequence of redefinitions of xdevmap allows lsof to size * its copy of the kernel's xdevmap[] table dynamically, based on the * kernel's nxdevmaps value. * * The net result is that there is a dummy struct XDEVMAP[1], defined in * dstore.c, that is never used. The copy of the kernel's xdevmap[] table * is stored in the space malloc()'d in dproc.c and addressed by Xdevmap. * The last redefinition of xdevmap to Xdevmap causes the macros of * to use Xdevmap. * * All this is done: 1) to avoid having to allocate a large amount of fixed * space in advance to a copy of the kernel's xdevmap; and 2) to keep CC from * complaining about the absence of a "struct xdevmap xdevmap[]," matching * the "extern struct xdevmap xdevmap[]" declaration in , * while still allowing lsof to use the equivalent of a "struct xdevmap *" * construct instead, particularly with the kernel forms of the major() and * minor() macros. */ #define xdevmap XDEVMAP #define _INKERNEL #include #undef _INKERNEL extern struct XDEVMAP *Xdevmap; #undef xdevmap #define xdevmap Xdevmap #include #include #include #include #include # if defined(HAS_NFS) #define multiple_groups 1 #include #include #include #include # endif /* defined(HAS_NFS) */ #include #include #undef NOGROUP #include #include # if OSRV<500 #include #include # else /* OSRV>=500 */ #include #include #include #include # endif /* OSRV<500 */ #include #include #include #include #include #include #include #include #include #include #define INKERNEL #include #undef INKERNEL /* * Adjust for the availability of symbolic links. */ # if defined(HAS_STATLSTAT) #define lstat statlstat # else /* !defined(HAS_STATLSTAT) */ #define lstat stat #define readlink(path, buf, len) (-1) # endif /* defined(HAS_STATLSTAT) */ #define COMP_P const void #define DEVINCR 1024 /* device table malloc() increment */ #define DIRTYPE dirent typedef off_t KA_T; #define KMEM "/dev/kmem" #define MALLOC_P void #define MNTTAB "/etc/mnttab" #define FREE_P MALLOC_P #define MALLOC_S size_t # if !defined(MAXPATHLEN) #define MAXPATHLEN 1024 # endif /* !defined(MAXPATHLEN) */ #define MAXSEGS 100 /* maximum text segments */ #define MAXSYSCMDL (PSCOMSIZ - 1) /* max system command name length */ # if OSRV<500 #define N_UNIX "/unix" # endif /* OSRV<500 */ #define PROCBFRD 16 /* count of proc structures buffered */ #define PROCSIZE sizeof(struct proc) #define QSORT_P void #define READLEN_T unsigned #define STRNCPY_L size_t #define STRNML 32 #define U_SIZE sizeof(struct user) /* * Global storage definitions (including their structure definitions) */ extern char **Cdevsw; extern int Cdevcnt; extern int CloneMajor; extern int EventMajor; extern char **Fsinfo; extern int Fsinfomax; extern int HaveCloneMajor; extern int HaveEventMajor; extern int HaveSockdev; extern int Hz; extern int Kd; extern KA_T Lbolt; extern int nxdevmaps; /* maximum kernel xdevmap[] index */ struct mounts { char *dir; /* directory (mounted on) */ char *fsname; /* file system * (symbolic links unresolved) */ char *fsnmres; /* file system * (symbolic links resolved) */ dev_t dev; /* directory st_dev */ dev_t rdev; /* directory st_rdev */ INODETYPE inode; /* directory st_ino */ mode_t mode; /* directory st_mode */ mode_t fs_mode; /* file system st_mode */ struct mounts *next; /* forward link */ # if defined(HASFSTYPE) char *fstype; /* st_fstype */ # endif }; #define NL_NAME n_name /* name element in struct nlist */ struct sfile { char *aname; /* argument file name */ char *name; /* file name (after readlink()) */ char *devnm; /* device name (optional) */ dev_t dev; /* device */ dev_t rdev; /* raw device */ mode_t mode; /* S_IFMT mode bits from stat() */ int type; /* file type: 0 = file system * 1 = regular file */ INODETYPE i; /* inode number */ int f; /* file found flag */ struct sfile *next; /* forward link */ }; extern int Sockdev; extern KA_T Socktab; /* * Definitions for dvch.c, isfn.c, and rdev.c */ #define CLONEMAJ CloneMajor /* clone major variable name */ # if defined(HASDCACHE) # if OSRV<500 #define DVCH_CHOWN 1 /* no fchown() below release 5.0 */ # endif /* OSRV<500 */ # endif /* defined(HASDCACHE) */ #define HAS_STD_CLONE 1 /* has standard clone structure */ #define HAVECLONEMAJ HaveCloneMajor /* clone major status variable name */ #endif /* OSR_LSOF_H */ lsof-4.86+dfsg.orig/dialects/osr/Mksrc0000555000175000017500000000106606733706722020073 0ustar nicholasnicholas#!/bin/sh # # Mksrc - make SCO OpenServer source files # # WARNING: This script assumes it is running from the main directory # of the lsof, version 4 distribution. # # One environment variable applies: # # LSOF_MKC is the method for creating the source files. # It defaults to "ln -s". A common alternative is "cp". # # $Id: Mksrc,v 1.4 99/06/22 08:21:19 abe Exp $ D=dialects/osr F=dialects/common L="dfile.c dlsof.h dmnt.c dnode.c dproc.c dproto.h dsock.c dstore.c machine.h" for i in $L do rm -f $i $LSOF_MKC $D/$i $i echo "$LSOF_MKC $D/$i $i" done lsof-4.86+dfsg.orig/dialects/osr/dnode.c0000444000175000017500000003670010412332041020300 0ustar nicholasnicholas/* * dnode.c - SCO OpenServer node functions for lsof */ /* * Copyright 1995 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1995 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dnode.c,v 1.21 2006/03/28 22:09:23 abe Exp $"; #endif #include "lsof.h" _PROTOTYPE(static struct l_dev * finddev,(dev_t *dev, dev_t *rdev, int stream)); /* * finddev() - look up device by device number */ static struct l_dev * finddev(dev, rdev, stream) dev_t *dev; /* device */ dev_t *rdev; /* raw device */ int stream; /* stream if 1 */ { struct clone *c; struct l_dev *dp; /* * Search device table for match. */ #if defined(HASDCACHE) finddev_again: #endif /* defined(HASDCACHE) */ if ((dp = lkupdev(dev, rdev, 0, 0))) return(dp); /* * Search for clone. */ if (stream && Clone) { for (c = Clone; c; c = c->next) { if (GET_MAJ_DEV(*rdev) == GET_MIN_DEV(Devtp[c->dx].rdev)) { #if defined(HASDCACHE) if (DCunsafe && !Devtp[c->dx].v && !vfy_dev(&Devtp[c->dx])) goto finddev_again; #endif /* defined(HASDCACHE) */ return(&Devtp[c->dx]); } } } return((struct l_dev *)NULL); } /* * process_node() - process node */ void process_node(na) KA_T na; /* inode kernel space address */ { char *cp, tbuf[32]; short dl; struct l_dev *dp; unsigned char *fa = (unsigned char *)NULL; struct filock fl; KA_T flf, flp; int fp, lp; struct inode i; short ity, udpsf, udpsl; int j, k, l; KA_T ka, qp; unsigned char *la = (unsigned char *)NULL; struct mounts *lm; struct module_info mi; unsigned short *n; KA_T p; struct inpcb pcb; int port; int pt = -1; struct queue q; struct qinit qi; struct stdata sd; char *tn; int type; struct udpdev udp; short udptm = 0; #if defined(HAS_NFS) struct rnode r; #endif /* defined(HAS_NFS) */ #if OSRV>=500 short hpps = 0; unsigned short *n1; struct pipeinode pi; #endif /* OSRV>=500 */ /* * Read the inode. */ if ( ! na) { enter_nm("no inode address"); return; } if (readinode(na, &i)) { enter_nm(Namech); return; } #if defined(HASNCACHE) Lf->na = na; #endif /* defined(HASNCACHE) */ #if defined(HASFSTRUCT) Lf->fna = na; Lf->fsv |= FSV_NI; #endif /* defined(HASFSTRUCT) */ /* * Identify the node type. */ if (HaveSockdev && (i.i_ftype & IFMT) == IFCHR && GET_MAJ_DEV(i.i_rdev) == Sockdev) { /* * Process a socket. */ process_socket(&i); return; } if (Selinet) return; ity = i.i_fstyp; type = i.i_ftype & IFMT; if (ity < 1 || ity > Fsinfomax || !Fsinfo[ity-1]) { #if OSRV>=500 if (ity) { #endif /* OSRV>=500 */ (void) snpf(Namech,Namechl,"unknown fstyp (%d) in inode",ity); enter_nm(Namech); return; #if OSRV>=500 } #endif /* OSRV>=500 */ } if (ity && strcasecmp(Fsinfo[ity-1], "HS") == 0) Ntype = N_HSFS; #if defined(HAS_NFS) else if (ity && strcasecmp(Fsinfo[ity-1], "NFS") == 0) { /* * Get information on NFS file. */ Ntype = N_NFS; Lf->is_nfs = 1; if (Fnfs) Lf->sf |= SELNFS; if (!i.i_fsptr || readrnode((KA_T)i.i_fsptr, &r)) { (void) snpf(Namech, Namechl, "can't read rnode (%s)", print_kptr((KA_T)i.i_fsptr, (char *)NULL, 0)); enter_nm(Namech); return; } # if defined(HASNCACHE) Lf->na = (KA_T)i.i_fsptr; # endif /* defined(HASNCACHE) */ } #endif /* defined(HAS_NFS) */ else { /* * Determine the node type from the inode file type. */ switch (type) { case IFBLK: Ntype = N_BLK; break; case IFCHR: Ntype = N_CHR; break; case IFIFO: Ntype = N_FIFO; break; case IFMPB: case IFMPC: Ntype = N_MPC; break; case IFNAM: Ntype = N_NM; break; } } /* * Obtain lock information. */ if ((flf = (KA_T)i.i_filocks)) { flp = flf; do { if ((kread(flp, (char *)&fl, sizeof(fl)))) break; if (fl.set.l_pid != (pid_t)Lp->pid) continue; if (fl.set.l_whence == (short)0 && fl.set.l_start == (off_t)0 && fl.set.l_len == 0x7fffffff) l = 1; else l = 0; #if OSRV<500 if (i.i_flag & IXLOCKED) #else /* OSRV>=500 */ if (fl.flags & F_XOUT) #endif /* OSRV<500 */ Lf->lock = l ? 'X' : 'x'; else if (fl.set.l_type == F_RDLCK) Lf->lock = l ? 'R' : 'r'; else if (fl.set.l_type == F_WRLCK) Lf->lock = l ? 'W' : 'w'; else if (fl.set.l_type == (F_RDLCK | F_WRLCK)) Lf->lock = 'u'; break; } while ((flp = (KA_T)fl.next) && flp != flf); } #if OSRV>=500 /* * See if a FIFO node is an HPPS node -- 3.2v5.0.0 and higher. */ if (Ntype == N_FIFO && ity && strcasecmp(Fsinfo[ity-1], "HPPS") == 0) { hpps = 1; if (i.i_fsptr) { enter_dev_ch(print_kptr((KA_T)i.i_fsptr, (char )NULL, 0)); if (kread((KA_T)i.i_fsptr, (char *)&pi, sizeof(pi)) == 0) hpps = 2; } } #endif /* OSRV>=500 */ /* * Determine the device. */ switch (Ntype) { case N_BLK: Lf->dev = i.i_dev; Lf->rdev = i.i_rdev; Lf->dev_def = Lf->rdev_def = 1; break; case N_FIFO: case N_HSFS: case N_NM: case N_REGLR: #if OSRV>=500 if (hpps) break; #endif /* OSRV>=500 */ Lf->dev = i.i_dev; Lf->dev_def = 1; break; case N_CHR: Lf->dev = i.i_dev; Lf->rdev = i.i_rdev; Lf->dev_def = Lf->rdev_def = 1; if (i.i_sptr) { /* * Namech may be: * /dev/* name if it exists for i.i_rdev; * cdevsw[].d_name if it exists for GET_MAJ_DEV(i.i_rdev); * "STR:" otherwise. */ (void) snpf(Namech, Namechl, "STR:"); Lf->is_stream = 1; k = strlen(Namech); cp = (char *)NULL; if ((dp = finddev(&Lf->dev, &Lf->rdev, 1))) { (void) snpf(&Namech[k], Namechl - k, dp->name); k += strlen(dp->name); if ((cp = strrchr(dp->name, '/'))) cp++; } else if ((j = GET_MAJ_DEV(i.i_rdev)) < Cdevcnt && (cp = Cdevsw[j])) { (void) snpf(Namech, Namechl, "%s", cp); k += strlen(cp); } /* * Get the module names of all queue elements of the stream's * sd_wrq queue. Skip module names that end in "head", * match the last component of the /dev name, or match the * cdevsw[].d_name. */ p = (KA_T)NULL; if (!kread((KA_T)i.i_sptr, (char *)&sd, sizeof(sd))) { dl = sizeof(tbuf) - 1; tbuf[dl] = '\0'; qp = (KA_T)sd.sd_wrq; for (j = 0; qp && j < 20; j++, qp = (KA_T)q.q_next) { if (kread(qp, (char *)&q, sizeof(q))) break; if (!(ka = (KA_T)q.q_qinfo) || kread(ka, (char *)&qi, sizeof(qi))) continue; if (!(ka = (KA_T)qi.qi_minfo) || kread(ka, (char *)&mi, sizeof(mi))) continue; if (!(ka = (KA_T)mi.mi_idname) || kread(ka, tbuf, dl)) continue; if ((l = strlen(tbuf)) < 1) continue; if (l >= 4 && strcmp(&tbuf[l - 4], "head") == 0) continue; if (cp && strcmp(cp, tbuf) == 0) { if (q.q_ptr && pt < 0) { /* * If this is a TCP or UDP module and the * queue structure has a private pointer in * q_ptr, save it as a PCB address. */ if (strcasecmp(cp, "tcp") == 0) { pt = 0; (void) snpf(Lf->iproto, sizeof(Lf->iproto), "TCP"); } else if (strcasecmp(cp, "udp") == 0) { pt = 1; (void) snpf(Lf->iproto, sizeof(Lf->iproto), "UDP"); } if (pt >= 0) p = (KA_T)q.q_ptr; else pt = -1; } continue; } if (k) { if ((k + 2) > (Namechl - 1)) break; (void) snpf(&Namech[k], Namechl - k, "->"); k += 2; } if ((k + l) > (Namechl - 1)) break; (void) snpf(&Namech[k], Namechl - k, tbuf); k += l; } } if (p && pt >= 0) { /* * If the stream has a TCP or UDP module with a PCB pointer, * print any associated local and foreign Internet addresses. */ if (kread(p, (char *)&pcb, sizeof(pcb))) break; if (Fnet) Lf->sf |= SELNET; if ((k + 1) > (Namechl - 1)) break; if (pt == 1 && pcb.inp_ppcb) { /* * If this is a UDP stream, get the udpdev structure at the * PCB's per-protocol address. It may contain addresses. */ if (kread((KA_T)pcb.inp_ppcb, (char *)&udp, sizeof(udp)) == 0) { #if OSRV>=500 if (udp.ud_lsin.sin_addr.s_addr != INADDR_ANY || udp.ud_lsin.sin_port != 0) udpsl = 1; else udpsl = 0; #endif /* OSRV>=500 */ if (udp.ud_fsin.sin_addr.s_addr != INADDR_ANY || udp.ud_fsin.sin_port != 0) udpsf = 1; else udpsf = 0; } } else udpsf = udpsl = 0; /* * Enter the local address from the PCB. If there is none, * and if this is a 5.0.0 or greater UDP stream, and if it * has a local address set, use it. */ la = (unsigned char *)&pcb.inp_laddr; lp = (int)ntohs(pcb.inp_lport); #if OSRV>=500 if (((struct in_addr *)la)->s_addr == INADDR_ANY && lp == 0 && udpsl) { la = (unsigned char *)&udp.ud_lsin.sin_addr; lp = (int)ntohs(udp.ud_lsin.sin_port); } #endif /* OSRV>=500 */ /* * Enter the foreign address from the PCB. If there is * none, and if this is a 5.0.0 or greater UDP stream, and * if it has a local address set, use it. */ if (pcb.inp_faddr.s_addr!=INADDR_ANY || pcb.inp_fport!=0) { fa = (unsigned char *)&pcb.inp_faddr; fp = (int)ntohs(pcb.inp_fport); } else if (udpsf) { fa = (unsigned char *)&udp.ud_fsin.sin_addr; fp = (int)ntohs(udp.ud_fsin.sin_port); udptm = 1; } if (fa || la) { (void) ent_inaddr(la, lp, fa, fp, AF_INET); if (udptm && !Lf->nma) (void) udp_tm(udp.ud_ftime); } if (!i.i_number) Lf->inp_ty = 2; } } else { if (ity) { if (strcasecmp(Fsinfo[ity-1], "COM") == 0) Ntype = N_COM; else Ntype = N_CHR; } else { Ntype = N_CHR; if (!finddev(&i.i_dev, &i.i_rdev, 0) && HaveEventMajor && GET_MAJ_DEV(i.i_rdev) == EventMajor) (void) snpf(Namech, Namechl, "clone %d:/dev/event", GET_MIN_DEV(i.i_rdev)); } } break; #if defined(HAS_NFS) case N_NFS: #if OSRV<500 Lf->dev = (dev_t)_makedev(~GET_MAJ_DEV(i.i_dev), GET_MIN_DEV(i.i_dev)); Lf->rdev = (dev_t)_makedev(~GET_MAJ_DEV(i.i_rdev), GET_MIN_DEV(i.i_rdev)); #else /* OSRV>=500 */ Lf->dev = i.i_dev; Lf->rdev = i.i_rdev; #endif /* OSRV<500 */ Lf->dev_def = Lf->rdev_def = 1; break; #endif /* defined(HAS_NFS) */ } /* * Determine the inode number. */ switch (Ntype) { case N_HSFS: #if OSRV<500 /* * High Sierra inode numbers for versions below 5.0.0, as reported * by "ls -i" and stat(2), are the lower 16 bits of i_number. */ if ((Lf->inode = (unsigned long)(i.i_number & 0xffff))) #else /* OSRV>=500 */ if ((Lf->inode = (unsigned long)i.i_number)) #endif /* OSRV<500 */ Lf->inp_ty = 1; break; #if defined(HAS_NFS) case N_NFS: #if OSRV<500 n = (unsigned short *)&r.r_fh.fh_pad[14]; if ((Lf->inode = (unsigned long)ntohs(*n))) Lf->inp_ty = 1; else if ((Lf->inode = (unsigned long)r.r_fh.fh_u.fh_fgen_u)) #else /* OSRV>=500 */ n = (unsigned short *)&r.r_fh.fh_u.fh_fid_u[4]; n1 = (unsigned short *)&r.r_fh.fh_u.fh_fid_u[2]; if ((Lf->inode = (unsigned long)*n)) Lf->inp_ty = 1; else if ((Lf->inode = (unsigned long)*n1)) #endif /* OSRV<500 */ Lf->inp_ty = 1; break; #endif /* defined(HAS_NFS) */ case N_BLK: case N_CHR: case N_COM: case N_FIFO: case N_NM: case N_REGLR: #if OSRV>=500 /* * Inodes for some 5.0.x HPPS FIFOs have an i_number that is the same * as i_fsptr. If it is, ignore it, because i_fsptr has already been * recorded for the DEVICE column. */ if (hpps && i.i_fsptr && i.i_number && (unsigned long)i.i_fsptr == (unsigned long)i.i_number) break; #endif /* OSRV>=500 */ if (i.i_number) { Lf->inode = (unsigned long)i.i_number; Lf->inp_ty = 1; } break; } /* * Determine the file size. */ if (Foffset) Lf->off_def = 1; else { switch (Ntype) { case N_BLK: if (!Fsize) Lf->off_def = 1; break; case N_CHR: case N_COM: if (!Fsize) Lf->off_def = 1; break; case N_FIFO: #if OSRV>=500 if (hpps == 2) { Lf->sz = (SZOFFTYPE)pi.count; Lf->sz_def = 1; break; } #endif /* OSRV>=500 */ if (!Fsize) Lf->off_def = 1; break; case N_HSFS: #if defined(HAS_NFS) case N_NFS: Lf->sz = (SZOFFTYPE)i.i_size; Lf->sz_def = 1; break; #endif /* defined(HAS_NFS) */ case N_REGLR: if (type == IFREG || type == IFDIR) { Lf->sz = (SZOFFTYPE)i.i_size; Lf->sz_def = 1; } break; } } /* * Record link count. */ if (Fnlink) { Lf->nlink = (long)i.i_nlink; Lf->nlink_def = 1; if (Nlink && (Lf->nlink < Nlink)) Lf->sf |= SELNLINK; } /* * Format the type name. */ switch (type) { case IFDIR: tn = "DIR"; break; case IFBLK: tn = "BLK"; break; case IFCHR: tn = "CHR"; break; case IFREG: tn = "REG"; break; case IFMPC: tn = "MPC"; break; case IFMPB: tn = "MPB"; break; case IFNAM: if (i.i_rdev == S_INSEM) tn = "XSEM"; else if (i.i_rdev == S_INSHD) tn = "XSD"; else { tn = "XNAM"; (void) snpf(Namech, Namechl, "unknown Xenix special file type: %x", i.i_rdev); } break; case IFIFO: tn = "FIFO"; break; #if defined(IFLNK) case IFLNK: tn = "LINK"; break; #endif /* defined(IFLNK) */ default: (void) snpf(Lf->type, sizeof(Lf->type), "%04o", ((type >> 12) & 0xfff)); tn = NULL; } if (tn) (void) snpf(Lf->type, sizeof(Lf->type), "%s", tn); /* * Save the file system names. */ switch (Ntype) { case N_BLK: case N_CHR: case N_FIFO: case N_HSFS: #if defined(HAS_NFS) case N_NFS: #endif /* defined(HAS_NFS) */ case N_NM: case N_REGLR: if (Lf->dev_def) { /* * Defer the local mount info table search until printname(). */ Lf->lmi_srch = 1; } break; } Lf->ntype = Ntype; #if defined(HASBLKDEV) /* * If this is a IFBLK file and it's missing an inode number, try to * supply one. */ if ((Lf->inp_ty == 0) && (type == IFBLK)) find_bl_ino(); #endif /* defined(HASBLKDEV) */ /* * If this is a IFCHR file and it's missing an inode number, try to * supply one. */ if ((Lf->inp_ty == 0) && (type == IFCHR)) find_ch_ino(); /* * Test for specified file. */ if (Sfile && is_file_named((char *)NULL, ((type == IFCHR) || (type == IFBLK) || (type == IFNAM)) ? 1 : 0)) Lf->sf |= SELNM; #if OSRV>=500 /* * If this is an HPPS node and no other name characters have been * entered, enter HPPS as the name. */ if (hpps && Namech[0] == '\0') (void) snpf(Namech, Namechl, "HPPS"); #endif /* OSRV>=500 */ /* * Enter name characters. */ if (Namech[0]) enter_nm(Namech); } lsof-4.86+dfsg.orig/dialects/osr/dfile.c0000444000175000017500000000660007334235172020306 0ustar nicholasnicholas/* * dfile.c - SCO OpenServer file processing functions for lsof */ /* * Copyright 1995 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1995 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dfile.c,v 1.11 2000/12/04 14:32:49 abe Exp abe $"; #endif #include "lsof.h" /* * get_max_fd() - get maximum file descriptor plus one */ int get_max_fd() { #if defined(F_GETHFDO) || defined(_SC_OPEN_MAX) int nd; #endif /* defined(F_GETHFDO) || defined(_SC_OPEN_MAX) */ #if defined(F_GETHFDO) if ((nd = fcntl(-1, F_GETHFDO, 0)) >= 0) return(nd); #endif /* defined(F_GETHFDO) */ #if defined(_SC_OPEN_MAX) if ((nd = sysconf(_SC_OPEN_MAX)) >= 0) return(nd); #endif /* defined(_SC_OPEN_MAX) */ return(getdtablesize()); } /* * print_dev() - print dev */ char * print_dev(lf, dev) struct lfile *lf; /* file whose device is to be printed */ dev_t *dev; /* device to be printed */ { static char buf[128]; (void) snpf(buf, sizeof(buf), "%d,%d", lf->is_nfs ? ((~(*dev >> 8)) & 0xff) : emajor(*dev), eminor(*dev)); return(buf); } /* * print_ino() - print inode */ char * print_ino(lf) struct lfile *lf; /* file whose device is to be printed */ { static char buf[128]; (void) snpf(buf, sizeof(buf), (lf->inode & 0x80000000) ? "%#x" : "%lu", lf->inode); return(buf); } /* * process_file() - process file */ void process_file(fp) KA_T fp; /* kernel file structure address */ { struct file f; int flag; if (kread(fp, (char *)&f, sizeof(f))) { (void) snpf(Namech, Namechl, "can't read file struct from %s", print_kptr(fp, (char *)NULL, 0)); enter_nm(Namech); return; } Lf->off = (SZOFFTYPE)f.f_offset; if (f.f_count) { /* * Construct access code. */ if ((flag = (f.f_flag & (FREAD | FWRITE))) == FREAD) Lf->access = 'r'; else if (flag == FWRITE) Lf->access = 'w'; else if (flag == (FREAD | FWRITE)) Lf->access = 'u'; /* * Process structure. */ #if defined(HASFSTRUCT) /* * Save file structure values. */ if (Fsv & FSV_CT) { Lf->fct = (long)f.f_count; Lf->fsv |= FSV_CT; } if (Fsv & FSV_FA) { Lf->fsa = fp; Lf->fsv |= FSV_FA; } if (Fsv & FSV_FG) { Lf->ffg = (long)f.f_flag; Lf->fsv |= FSV_FG; } if (Fsv & FSV_NI) { Lf->fna = (KA_T)f.f_inode; Lf->fsv |= FSV_NI; } #endif /* defined(HASFSTRUCT) */ process_node((KA_T)f.f_inode); return; } enter_nm("no more information"); } lsof-4.86+dfsg.orig/dialects/osr/dmnt.c0000444000175000017500000001242710275734177020200 0ustar nicholasnicholas/* * dmnt.c - SCO OpenServer mount support functions for lsof */ /* * Copyright 1995 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1995 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dmnt.c,v 1.8 2005/08/08 19:54:32 abe Exp $"; #endif #include "lsof.h" /* * Local static definitions */ static struct mounts *Lmi = (struct mounts *)NULL; /* local mount info */ static int Lmist = 0; /* Lmi status */ /* * readmnt() - read mount table */ struct mounts * readmnt() { int br, fd; int bx = sizeof(struct mnttab); char *cp; char dvnm[MAXPATHLEN], fsnm[MAXPATHLEN]; MALLOC_S dvnml, fsnml; MALLOC_S len; char *ln = (char *)NULL; struct mnttab m; struct mounts *mtp; struct stat sb; if (Lmi || Lmist) return(Lmi); /* * Open access to the mount table. */ if ((fd = open(MNTTAB, O_RDONLY, 0)) < 0) { (void) fprintf(stderr, "%s: can't open %s\n", Pn, MNTTAB); Exit(1); } /* * Read the first mount table entry. */ br = read(fd, (char *)&m, bx); dvnml = fsnml = 0; /* * Process the next complete mount table entry. */ while (br == bx) { if (!dvnml) { /* * Start the device and file system name assemblies. */ dvnml = strlen(m.mt_dev); if (dvnml >= MAXPATHLEN) dvnml = MAXPATHLEN - 1; (void) strncpy(dvnm, m.mt_dev, dvnml); dvnm[dvnml] = '\0'; fsnml = strlen(m.mt_filsys); if (fsnml >= MAXPATHLEN) fsnml = MAXPATHLEN - 1; (void) strncpy(fsnm, m.mt_filsys, fsnml); fsnm[fsnml] = '\0'; } while ((br = read(fd, (char *)&m, bx)) == bx && strcmp(m.mt_filsys, "nothing") == 0 && strcmp(m.mt_dev, "nowhere") == 0) { /* * Add the "nothing/nowhere" extensions to the assemblies. */ len = strlen(&m.mt_dev[8]); if (len >= (MAXPATHLEN - dvnml)) len = MAXPATHLEN - dvnml - 1; if (len) { (void) strncpy(&dvnm[dvnml], &m.mt_dev[8], len); dvnml += len; dvnm[dvnml] = '\0'; } len = strlen(&m.mt_filsys[8]); if (len >= (MAXPATHLEN - fsnml)) len = MAXPATHLEN - fsnml - 1; if (len) { (void) strncpy(&fsnm[fsnml], &m.mt_filsys[8], len); fsnml += len; fsnm[fsnml] = '\0'; } } /* * Skip automount place markers. */ if ((cp = strrchr(dvnm, ':')) && strncmp(cp, ":(pid", 5) == 0) { dvnml = fsnml = 0; continue; } /* * Interpolate a possible symbolic directory link. */ if (ln) { (void) free((FREE_P *)ln); ln = (char *)NULL; } if (!(ln = Readlink(fsnm))) { if (!Fwarn){ (void) fprintf(stderr, " Output information may be incomplete.\n"); } dvnml = fsnml = 0; continue; } if (*ln != '/') continue; if (ln == fsnm) { /* * Allocate space for a copy of the file system name. */ if (!(ln = mkstrcpy(fsnm, (MALLOC_S *)NULL))) { no_space_for_mount: (void) fprintf(stderr, "%s: no space for mount at ", Pn); safestrprt(fsnm, stderr, 0); (void) fprintf(stderr, " ("); safestrprt(dvnm, stderr, 0); (void) fprintf(stderr, ")\n"); Exit(1); } } /* * Stat() the directory. */ if (statsafely(ln, &sb)) { if (!Fwarn) { (void) fprintf(stderr, "%s: WARNING: can't stat() file system: ", Pn); safestrprt(fsnm, stderr, 1); (void) fprintf(stderr, " Output information may be incomplete.\n"); } dvnml = fsnml = 0; continue; } /* * Allocate and fill a local mount structure. */ if (!(mtp = (struct mounts *)malloc(sizeof(struct mounts)))) goto no_space_for_mount; mtp->dir = ln; ln = (char *)NULL; mtp->next = Lmi; mtp->dev = sb.st_dev; mtp->rdev = sb.st_rdev; mtp->inode = (INODETYPE)sb.st_ino; mtp->mode = sb.st_mode; /* * Interpolate a possible file system (mounted-on) device name link */ if (!(cp = mkstrcpy(dvnm, (MALLOC_S *)NULL))) goto no_space_for_mount; mtp->fsname = cp; ln = Readlink(cp); /* * Stat() the file system (mounted-on) name and add file system * information to the local mount table entry. */ if (statsafely(ln, &sb)) sb.st_mode = 0; mtp->fsnmres = ln; ln = (char *)NULL; mtp->fs_mode = sb.st_mode; Lmi = mtp; dvnml = fsnml = 0; } (void) close(fd); /* * Clean up and return the local mount information table address. */ if (ln) (void) free((FREE_P *)ln); Lmist = 1; return(Lmi); } lsof-4.86+dfsg.orig/dialects/osr/machine.h0000444000175000017500000003755711424323064020644 0ustar nicholasnicholas/* * machine.h - SCO OpenServer definitions for lsof */ /* * Copyright 1995 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: machine.h,v 1.36 2010/07/29 16:02:57 abe Exp $ */ #if !defined(LSOF_MACHINE_H) #define LSOF_MACHINE_H 1 #include #include /* * CAN_USE_CLNT_CREATE is defined for those dialects where RPC clnt_create() * can be used to obtain a CLIENT handle in lieu of clnttcp_create(). */ #if OSRV>=42 #define CAN_USE_CLNT_CREATE 1 #endif /* OSRV>=42 */ /* * DEVDEV_PATH defines the path to the directory that contains device * nodes. */ #define DEVDEV_PATH "/dev" /* * GET_MAX_FD is defined for those dialects that provide a function other than * getdtablesize() to obtain the maximum file descriptor number plus one. */ #define GET_MAX_FD get_max_fd /* * HASAOPT is defined for those dialects that have AFS support; it specifies * that the default path to an alternate AFS kernel name list file may be * supplied with the -A option. */ /* #define HASAOPT 1 */ /* * HASBLKDEV is defined for those dialects that want block device information * recorded in BDevtp[]. */ #define HASBLKDEV 1 /* * HASDCACHE is defined for those dialects that support a device cache * file. * * HASENVDC defined the name of an environment variable that contains the * device cache file path. The HASENVDC environment variable is ignored when * the lsof process is setuid(root) or its real UID is 0. * * HASPERSDC defines the format for the last component of a personal device * cache file path. The first will be the home directory of the real UID that * executes lsof. * * HASPERSDCPATH defines the environment variable whose value is the middle * component of the personal device cache file path. The middle component * follows the home directory and precedes the results of applying HASPERSDC. * The HASPERSDCPATH environment variable is ignored when the lsof process is * setuid(root) or its real UID is 0. * * HASSYSDC defines a public device cache file path. When it's defined, it's * used as the path from which to read the device cache. * * Consult the 00DCACHE and 00FAQ files of the lsof distribution for more * information on device cache file path construction. */ #define HASDCACHE 1 #define HASENVDC "LSOFDEVCACHE" #define HASPERSDC "%h/%p.lsof_%L" #define HASPERSDCPATH "LSOFPERSDCPATH" /* #define HASSYSDC "/your/choice/of/path" */ /* * HASCDRNODE is defined for those dialects that have CD-ROM nodes. */ /* #define HASCDRNODE 1 */ /* * HASFIFONODE is defined for those dialects that have FIFO nodes. */ /* #define HASFIFONODE 1 */ /* * HASFSINO is defined for those dialects that have the file system * inode element, fs_ino, in the lfile structure definition in lsof.h. */ #define HASFSINO 1 /* * HASFSTRUCT is defined if the dialect has a file structure. * * FSV_DEFAULT defines the default set of file structure values to list. * It defaults to zero (0), but may be made up of a combination of the * FSV_* symbols from lsof.h. * * HASNOFSADDR -- has no file structure address * HASNOFSFLAGS -- has no file structure flags * HASNOFSCOUNT -- has no file structure count * HASNOFSNADDR -- has no file structure node address */ #define HASFSTRUCT 1 /* #define FSV_DEFAULT FSV_? | FSV_? | FSV_? */ /* #define HASNOFSADDR 1 has no file structure address */ /* #define HASNOFSFLAGS 1 has no file structure flags */ /* #define HASNOFSCOUNT 1 has no file structure count */ /* #define HASNOFSNADDR 1 has no file structure node address */ /* * HASGNODE is defined for those dialects that have gnodes. */ /* #define HASGNODE 1 */ /* * HASHSNODE is defined for those dialects that have High Sierra nodes. */ /* #define HASHSNODE 1 */ /* * HASINODE is defined for those dialects that have inodes and wish to * use readinode() from node.c. */ #define HASINODE 1 /* * HASINTSIGNAL is defined for those dialects whose signal function returns * an int. */ /* #define HASINTSIGNAL 1 */ /* * HASKERNIDCK is defined for those dialects that support the comparison of * the build to running kernel identity. */ #define HASKERNIDCK 1 /* * HASKOPT is defined for those systems that support the -k option of * reading the kernel's name list from an optional file. */ #define HASKOPT 1 /* * HASLFILEADD is defined for those dialects that need additional elements * in struct lfile. The HASLFILEADD definition is a macro that defines * them. If any of the additional elements need to be preset in the * alloc_lfile() function of proc.c, the SETLFILEADD macro may be defined * to do that. * * If any additional elements need to be cleared in alloc_lfile() or in the * free_proc() function of proc.c, the CLRLFILEADD macro may be defined to * do that. Note that CLRLFILEADD takes one argument, the pointer to the * lfile struct. The CLRLFILEADD macro is expected to expand to statements * that are complete -- i.e., have terminating semi-colons -- so the macro is * called without a terminating semicolon by proc.c. * * The HASXOPT definition may be used to select the conditions under which * private lfile elements are used. */ /* #define HASLFILEADD int ... */ /* #define CLRLFILEADD(lf) (lf)->... = (type)NULL; */ /* #define SETLFILEADD Lf->... */ /* * HASMNTSTAT indicates the dialect supports the mount stat(2) result option * in its l_vfs and mounts structures. */ /* #define HASMNTSTAT 1 */ /* * HASMNTSUP is defined for those dialects that support the mount supplement * option. */ /* #define HASMNTSUP 1 */ /* * HASMOPT is defined for those dialects that support the reading of * kernel memory from an alternate file. */ #define HASMOPT 1 /* * HASNCACHE is defined for those dialects that have a kernel name cache * that lsof can search. A value of 1 directs printname() to prefix the * cache value with the file system directory name; 2, avoid the prefix. * * NCACHELDPFX is a set of C commands to execute before calling ncache_load(). * * NCACHELDSFX is a set of C commands to execute after calling ncache_load(). */ #define HASNCACHE 1 /* #define NCACHELDPFX ??? */ /* #define NCACHELDSFX ??? */ /* * HASNLIST is defined for those systems that use nlist() to acccess * kernel symbols. */ #define HASNLIST 1 /* * HASPIPEFN is defined for those dialects that have a special function to * process DTYPE_PIPE file structure entries. Its value is the name of the * function. * * NOTE: don't forget to define a prototype for this function in dproto.h. */ /* #define HASPIPEFN process_pipe? */ /* * HASPIPENODE is defined for those dialects that have pipe nodes. */ /* #define HASPIPENODE 1 */ /* * HASPMAPENABLED is defined when the reporting of portmapper registration * info is enabled by default. */ /* #define HASPMAPENABLED 1 */ /* * HASPPID is defined for those dialects that support identification of * the parent process IDentifier (PPID) of a process. */ #define HASPPID 1 /* * HASPRINTDEV, HASPRINTINO, HASPRINTNM, HASPRINTOFF, and HASPRINTSZ * define private dialect-specific functions for printing DEVice numbers, * INOde numbers, NaMes, file OFFsets, and file SiZes. The functions are * called from print_file(). */ #define HASPRINTDEV print_dev #define HASPRINTINO print_ino /* #define HASPRINTNM print_nm? */ /* #define HASPRINTOFF print_off? */ /* #define HASPRINTSZ print_sz? */ /* * HASPRIVFILETYPE and PRIVFILETYPE are defined for dialects that have a * file structure type that isn't defined by a DTYPE_* symbol. They are * used in lib/prfp.c to select the type's processing. * * PRIVFILETYPE is the definition of the f_type value in the file struct. * * HASPRIVFILETYPE is the name of the processing function. */ /* #define HASPRIVFILETYPE process_shmf? */ /* #define PRIVFILETYPE ?? */ /* * HASPRIVNMCACHE is defined for dialects that have a private method for * printing cached NAME column values for some files. HASPRIVNAMECACHE * is defined to be the name of the function. * * The function takes one argument, a struct lfile pointer to the file, and * returns non-zero if it prints a name to stdout. */ /* #define HASPRIVNMCACHE */ /* * HASPRIVPRIPP is defined for dialects that have a private function for * printing IP protocol names. When HASPRIVPRIPP isn't defined, the * IP protocol name printing function defaults to printiprto(). */ /* #define HASPRIVPRIPP 1 */ /* * HASPROCFS is defined for those dialects that have a proc file system -- * usually /proc and usually in SYSV4 derivatives. * * HASFSTYPE is defined as 1 for those systems that have a file system type * string, st_fstype, in the stat() buffer; 2, for those systems that have a * file system type integer in the stat() buffer, named MOUNTS_STAT_FSTYPE; * 0, for systems whose stat(2) structure has no file system type member. The * additional symbols MOUNTS_FSTYPE, RMNT_FSTYPE, and RMNT_STAT_FSTYPE may be * defined in dlsof.h to direct how the readmnt() function in lib/rmnt.c * preserves these stat(2) and getmntent(3) buffer values in the local mounts * structure. * * The defined value is the string that names the file system type. * * The HASPROCFS definition usually must be accompanied by the HASFSTYPE * definition and the providing of an fstype element in the local mounts * structure (defined in dlsof.h). * * The HASPROCFS definition may be accompanied by the HASPINODEN definition. * HASPINODEN specifies that searching for files in HASPROCFS is to be done * by inode number. */ /* #define HASPROCFS "proc?" */ /* #define HASFSTYPE 1 */ /* #define HASPINODEN 1 */ /* * HASRNODE is defined for those dialects that have rnodes. */ # if defined(HAS_NFS) #define HASRNODE 1 # endif /* defined(HAS_NFS) */ /* * Define HASSECURITY to restrict the listing of all open files to the * root user. When HASSECURITY is defined, the non-root user may list * only files whose processes have the same user ID as the real user ID * (the one that its user logged on with) of the lsof process. */ /* #define HASSECURITY 1 */ /* * If HASSECURITY is defined, define HASNOSOCKSECURITY to allow users * restricted by HASSECURITY to list any open socket files, provide their * listing is selected by the "-i" option. */ /* #define HASNOSOCKSECURITY 1 */ /* * HASSETLOCALE is defined for those dialects that have and * setlocale(). * * If the dialect also has wide character support for language locales, * HASWIDECHAR activates lsof's wide character support and WIDECHARINCL * defines the header file (if any) that must be #include'd to use the * mblen() and mbtowc() functions. */ #define HASSETLOCALE 1 # if OSRV>=506 #define HASWIDECHAR 1 # endif /* OSRV>=506 */ /* #define WIDECHARINCL */ /* * HASSNODE is defined for those dialects that have snodes. */ /* #define HASSNODE 1 */ /* * HASTASKS is defined for those dialects that have task reporting support. */ /* #define HASTASKS 1 */ /* * HASSOOPT, HASSOSTATE and HASTCPOPT define the availability of information * on socket options (SO_* symbols), socket states (SS_* symbols) and TCP * options. */ #define HASSOOPT 1 /* has socket option information */ #define HASSOSTATE 1 /* has socket state information */ #define HASTCPOPT 1 /* has TCP options or flags */ /* * Define HASSPECDEVD to be the name of a function that handles the results * of a successful stat(2) of a file name argument. * * For example, HASSPECDEVD() for Darwin makes sure that st_dev is set to * what stat("/dev") returns -- i.e., what's in DevDev. * * The function takes two arguments: * * 1: pointer to the full path name of file * 2: pointer to the stat(2) result * * The function returns void. */ /* #define HASSPECDEVD process_dev_stat */ /* * HASSTREAMS is defined for those systems that support streams. */ #define HASSTREAMS 1 /* * HASTCPTPIQ is defined for dialects where it is possible to report the * TCP/TPI Recv-Q and Send-Q values produced by netstat. */ #define HASTCPTPIQ 1 /* * HASTCPTPIW is defined for dialects where it is possible to report the * TCP/TPI send and receive window sizes produced by netstat. */ /* #define HASTCPTPIW 1 */ /* * HASTMPNODE is defined for those dialects that have tmpnodes. */ /* #define HASTMPNODE 1 */ /* * HASVNODE is defined for those dialects that use the Sun virtual file * system node, the vnode. BSD derivatives usually do; System V derivatives * prior to R4 usually don't. */ /* #define HASVNODE 1 */ /* * HASXOPT is defined for those dialects that have an X option. It * defines the text for the usage display. HASXOPT_VALUE defines the * option's default binary value -- 0 or 1. */ /* #define HASXOPT "help text for X option" */ /* #define HASXOPT_VALUE 1 */ /* * INODETYPE and INODEPSPEC define the internal node number type and its * printf specification modifier. These need not be defined and lsof.h * can be allowed to define defaults. * * These are defined here, because they must be used in dlsof.h. */ /* #define INODETYPE unsigned long long */ /* inode number internal storage type */ /* #define INODEPSPEC "ll" * INODETYPE printf specification * modifier */ /* * UID_ARG defines the size of a User ID number when it is passed * as a function argument. */ #define UID_ARG int /* * Each USE_LIB_ is defined for dialects that use the * in the lsof library. * * Note: other definitions and operations may be required to condition the * library function source code. They may be found in the dialect dlsof.h * header files. */ /* #define USE_LIB_CKKV 1 ckkv.c */ /* #define USE_LIB_COMPLETEVFS 1 cvfs.c */ #define USE_LIB_FIND_CH_INO 1 /* fino.c */ #define USE_LIB_IS_FILE_NAMED 1 /* isfn.c */ #define USE_LIB_LKUPDEV 1 /* lkud.c */ #define USE_LIB_PRINTDEVNAME 1 /* pdvn.c */ /* #define USE_LIB_PROCESS_FILE 1 prfp.c */ #define USE_LIB_PRINT_TCPTPI 1 /* ptti.c */ #define USE_LIB_READDEV 1 /* rdev.c */ /* #define USE_LIB_READMNT 1 rmnt.c */ /* #define USE_LIB_REGEX 1 regex.c */ /* #define USE_LIB_RNAM 1 rnam.c */ /* #define USE_LIB_RNCH 1 rnch.c */ /* #define USE_LIB_RNMH 1 rnmh.c */ # if OSRV<500 #define USE_LIB_SNPF 1 /* snpf.c */ # else /* OSRV>=500 */ #define snpf snprintf /* use the system's snprintf() */ # endif /* OSRV<500 */ /* * WARNDEVACCESS is defined for those dialects that should issue a warning * when lsof can't access /dev (or /device) or one of its sub-directories. * The warning can be inhibited by the lsof caller with the -w option. */ /* #define WARNDEVACCESS 1 */ /* * WARNINGSTATE is defined for those dialects that want to suppress all lsof * warning messages. */ /* #define WARNINGSTATE 1 warnings are enabled by default */ /* * WILLDROPGID is defined for those dialects whose lsof executable runs * setgid(not_real_GID) and whose setgid power can be relinquished after * the dialect's initialize() function has been executed. */ #define WILLDROPGID 1 /* * zeromem is a macro that uses bzero or memset. */ #define zeromem(a, l) memset(a, 0, l) #endif /* !defined(LSOF_MACHINE_H) */ lsof-4.86+dfsg.orig/dialects/osr/Makefile0000444000175000017500000000772011001127003020476 0ustar nicholasnicholas # OSR Makefile # # $Id: Makefile,v 1.12 2008/04/15 13:30:40 abe Exp $ PROG= lsof BIN= ${DESTDIR} DOC= ${DESTDIR} I=/usr/include S=/usr/include/sys L=/usr/include/local P= CDEF= CDEFS= ${CDEF} ${CFGF} INCL= ${DINC} CFLAGS= ${CDEFS} ${INCL} ${DEBUG} GRP= HDR= lsof.h lsof_fields.h dlsof.h machine.h proto.h dproto.h MODE= 2755 OWN= bin SRC= dfile.c dmnt.c dnode.c dproc.c dsock.c dstore.c \ arg.c main.c misc.c node.c print.c proc.c store.c usage.c \ util.c OBJ= dfile.o dmnt.o dnode.o dproc.o dsock.o dstore.o \ arg.o main.o misc.o node.o print.o proc.o store.o usage.o \ util.o MAN= lsof.man MANLCL= lsof.LOCAL OTHER= SHELL= /bin/sh SOURCE= Makefile ${OTHER} ${MAN} ${HDR} ${SRC} all: ${PROG} ${MANLCL}: ${MAN} rm -f ${MANLCL} cp ${MAN} ${MANLCL} ${PROG}: ${LIB} ${P} ${OBJ} ${CC} -o $@ ${CFLAGS} ${OBJ} ${CFGL} clean: FRC rm -f Makefile.bak ${PROG} a.out core errs lint.out tags *.o version.h ${MANLCL} rm -f machine.h.old new_machine.h (cd lib; ${MAKE} -f Makefile.skel clean) install: all ${MANLCL} FRC @echo '' @echo 'Please write your own install rule. Lsof should be installed' @echo 'setgid to the group that can can read /dev/kmem. Normally' @echo 'that is the mem group. Your install rule actions might look' @echo 'something like this:' @echo '' @echo ' strip $${PROG}' @echo ' mcs -d $${PROG}' @echo ' /etc/install -o -m -u -g -f $${BIN} $${PROG}' @echo ' /etc/install -o -m 444 -f $${DOC} $${MANLCL}' @echo '' @echo 'You will have to set values for , and ,' @echo 'and complete the skeletons for the BIN and DOC strings given' @echo 'at the beginning of this Makefile, e.g.,' @echo '' @echo ' BIN= $${DESTDIR}/usr/local/etc' @echo ' DOC= $${DESTDIR}/usr/man/man8' @echo '' ${LIB}: FRC (cd lib; ${MAKE} DEBUG="${DEBUG}" CFGF="${CFGF}") version.h: FRC @echo Constructing version.h @rm -f version.h @echo '#define LSOF_BLDCMT "${LSOF_BLDCMT}"' > version.h; @echo '#define LSOF_CC "${CC}"' >> version.h @echo '#define LSOF_CCV "${CCV}"' >> version.h @echo '#define LSOF_CCDATE "'`date`'"' >> version.h @echo '#define LSOF_CCFLAGS "'`echo ${CFLAGS} | sed 's/\\\\(/\\(/g' | sed 's/\\\\)/\\)/g' | sed 's/"/\\\\"/g'`'"' >> version.h @echo '#define LSOF_LDFLAGS "${CFGL}"' >> version.h @if [ "X${LSOF_LOGNAME}" = "X" ]; then \ echo '#define LSOF_LOGNAME "${LOGNAME}"' >> version.h; \ else \ if [ "${LSOF_LOGNAME}" = "none" ]; then \ echo '#define LSOF_LOGNAME ""' >> version.h; \ else \ echo '#define LSOF_LOGNAME "${LSOF_LOGNAME}"' >> version.h; \ fi; \ fi @if [ "X${LSOF_HOST}" = "X" ]; then \ echo '#define LSOF_HOST "'`uname -n`'"' >> version.h; \ else \ if [ "${LSOF_HOST}" = "none" ]; then \ echo '#define LSOF_HOST ""' >> version.h; \ else \ echo '#define LSOF_HOST "${LSOF_HOST}"' >> version.h; \ fi \ fi @if [ "X${LSOF_SYSINFO}" = "X" ]; then \ echo '#define LSOF_SYSINFO "${LSOF_SYSINFO}"' >> version.h; \ else \ if [ "${LSOF_SYSINFO}" = "none" ]; then \ echo '#define LSOF_SYSINFO ""' >> version.h; \ else \ echo '#define LSOF_SYSINFO "'`uname -X`'"' >> version.h; \ fi \ fi @if [ "X${LSOF_USER}" = "X" ]; then \ echo '#define LSOF_USER "${USER}"' >> version.h; \ else \ if [ "${LSOF_USER}" = "none" ]; then \ echo '#define LSOF_USER ""' >> version.h; \ else \ echo '#define LSOF_USER "${LSOF_USER}"' >> version.h; \ fi \ fi @sed '/VN/s/.ds VN \(.*\)/#define LSOF_VERSION "\1"/' < version >> version.h FRC: # DO NOT DELETE THIS LINE - make depend DEPENDS ON IT dfile.o: ${HDR} dfile.c dmnt.o: ${HDR} dmnt.c dnode.o: ${HDR} dnode.c dproc.o: ${HDR} dproc.c dsock.o: ${HDR} dsock.c dstore.o: ${HDR} dstore.c arg.o: ${HDR} arg.c main.o: ${HDR} main.c misc.o: ${HDR} misc.c node.o: ${HDR} node.c print.o: ${HDR} print.c proc.o: ${HDR} proc.c store.o: ${HDR} store.c usage.o: ${HDR} version.h usage.c util.o: ${HDR} util.c # *** Do not add anything here - It will go away. *** lsof-4.86+dfsg.orig/dialects/hpux/0000755000175000017500000000000011424323013017223 5ustar nicholasnicholaslsof-4.86+dfsg.orig/dialects/hpux/pstat/0000755000175000017500000000000011741064217020370 5ustar nicholasnicholaslsof-4.86+dfsg.orig/dialects/hpux/pstat/dstore.c0000444000175000017500000000414210120335663022027 0ustar nicholasnicholas/* * dstore.c - pstat-based HP-UX global storage for lsof */ /* * Copyright 1999 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1999 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id"; #endif #include "lsof.h" /* * Global storage definitions */ _T_LONG_T CloneMaj; /* clone major device number */ int HasNFS = -1; /* NFS-mounted file system status: * -1: not yet tested; * 0: tested and none mounted; * 1: tested and some mounted */ int HaveCloneMaj = 0; /* CloneMaj status */ #if defined(HASFSTRUCT) /* * Pff_tab[] - table for printing file flags */ struct pff_tab Pff_tab[] = { { (long)PS_FRDONLY, FF_READ }, { (long)PS_FWRONLY, FF_WRITE }, { (long)PS_FAPPEND, FF_APPEND }, { (long)PS_FNODELY, FF_NDELAY }, { (long)PS_FNBLOCK, FF_NBLOCK }, { (long)PS_FSYNC, FF_SYNC }, { (long)PS_FDSYNC, FF_DSYNC }, { (long)PS_FRSYNC, FF_RSYNC }, { (long)PS_FLGFILE, FF_LARGEFILE }, { (long)0, NULL } }; /* * Pof_tab[] - table for print process open file flags */ struct pff_tab Pof_tab[] = { { (long)PS_FEXCLOS, POF_CLOEXEC }, { (long)0, NULL } }; #endif /* defined(HASFSTRUCT) */ lsof-4.86+dfsg.orig/dialects/hpux/pstat/dsock.c0000444000175000017500000012203311036721706021636 0ustar nicholasnicholas/* * dsock.c -- pstat-based HP-UX socket and stream processing functions for lsof */ /* * Copyright 1999 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1999 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id"; #endif #include "lsof.h" /* * Local function prototypes */ #if defined(PS_STR_XPORT_DATA) _PROTOTYPE(static void make_sock,(struct pst_fileinfo2 *f, struct pst_stream *sh, struct pst_socket *s)); #endif /* defined(PS_STR_XPORT_DATA) */ _PROTOTYPE(static void printpsproto,(uint32_t p)); /* * Local macros */ #if defined(HASIPv6) /* * IPv6_2_IPv4() -- macro to define the address of an IPv4 address contained * in an IPv6 address */ #define IPv6_2_IPv4(v6) (((uint8_t *)((struct in6_addr *)v6)->s6_addr)+12) #endif /* defined(HASIPv6) */ /* * build_IPstates() -- build the TCP and UDP state tables */ void build_IPstates() { if (!TcpSt) { (void) enter_IPstate("TCP", "CLOSED", PS_TCPS_CLOSED); (void) enter_IPstate("TCP", "IDLE", PS_TCPS_IDLE); (void) enter_IPstate("TCP", "BOUND", PS_TCPS_BOUND); (void) enter_IPstate("TCP", "LISTEN", PS_TCPS_LISTEN); (void) enter_IPstate("TCP", "SYN_SENT", PS_TCPS_SYN_SENT); (void) enter_IPstate("TCP", "SYN_RCVD", PS_TCPS_SYN_RCVD); (void) enter_IPstate("TCP", "ESTABLISHED", PS_TCPS_ESTABLISHED); (void) enter_IPstate("TCP", "CLOSE_WAIT", PS_TCPS_CLOSE_WAIT); (void) enter_IPstate("TCP", "FIN_WAIT_1", PS_TCPS_FIN_WAIT_1); (void) enter_IPstate("TCP", "CLOSING", PS_TCPS_CLOSING); (void) enter_IPstate("TCP", "LAST_ACK", PS_TCPS_LAST_ACK); (void) enter_IPstate("TCP", "FIN_WAIT_2", PS_TCPS_FIN_WAIT_2); (void) enter_IPstate("TCP", "TIME_WAIT", PS_TCPS_TIME_WAIT); (void) enter_IPstate("TCP", (char *)NULL, 0); } if (!UdpSt) { (void) enter_IPstate("UDP", "Uninitialized", PS_TS_UNINIT); (void) enter_IPstate("UDP", "Unbound", PS_TS_UNBND); (void) enter_IPstate("UDP", "Wait_BIND_REQ_Ack", PS_TS_WACK_BREQ); (void) enter_IPstate("UDP", "Wait_UNBIND_REQ_Ack", PS_TS_WACK_UREQ); (void) enter_IPstate("UDP", "Idle", PS_TS_IDLE); (void) enter_IPstate("UDP", "Wait_OPT_REQ_Ack", PS_TS_WACK_OPTREQ); (void) enter_IPstate("UDP", "Wait_CONN_REQ_Ack", PS_TS_WACK_CREQ); (void) enter_IPstate("UDP", "Wait_CONN_REQ_Confirm", PS_TS_WCON_CREQ); (void) enter_IPstate("UDP", "Wait_CONN_IND_Response", PS_TS_WRES_CIND); (void) enter_IPstate("UDP", "Wait_CONN_RES_Ack", PS_TS_WACK_CRES); (void) enter_IPstate("UDP", "Wait_Data_Xfr", PS_TS_DATA_XFER); (void) enter_IPstate("UDP", "Wait_Read_Release", PS_TS_WIND_ORDREL); (void) enter_IPstate("UDP", "Wait_Write_Release", PS_TS_WREQ_ORDREL); (void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack", PS_TS_WACK_DREQ6); (void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack", PS_TS_WACK_DREQ7); (void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack", PS_TS_WACK_DREQ9); (void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack", PS_TS_WACK_DREQ10); (void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack", PS_TS_WACK_DREQ11); (void) enter_IPstate("UDP", "Internal", PS_TS_WACK_ORDREL); (void) enter_IPstate("UDP", (char *)NULL, 0); } } #if defined(PS_STR_XPORT_DATA) /* * make_sock() -- make a socket from the eXPORT data in a stream's head */ static void make_sock(f, sh, s) struct pst_fileinfo2 *f; /* pst_fileinfo2 */ struct pst_stream *sh; /* stream head */ struct pst_socket *s; /* constructed socket */ { size_t sz; /* * Zero the destination pst_socket structure and propagate its file and node * IDs from the stream head. Also propagate the linger time. */ (void)memset((void *)s, 0, sizeof(struct pst_socket)); s->pst_hi_fileid = sh->val.head.pst_hi_fileid; s->pst_lo_fileid = sh->val.head.pst_lo_fileid; s->pst_hi_nodeid = sh->val.head.pst_hi_nodeid; s->pst_lo_nodeid = sh->val.head.pst_lo_nodeid; s->pst_linger = sh->pst_str_xport_linger; /* * Convert stream family to socket family and stream protocol to socket * protocol. * * This could be avoided if PSTAT were to use a common set of family and * protocol symbols. */ switch (sh->pst_str_xport_family) { case PS_STR_XPORT_AFINET: s->pst_family = PS_AF_INET; break; case PS_STR_XPORT_AFINET6: s->pst_family = PS_AF_INET6; break; default: s->pst_family = sh->pst_str_xport_family; } switch (sh->pst_str_xport_protocol) { case PS_STR_XPORT_TCP_PROTO: s->pst_protocol = PS_PROTO_TCP; break; case PS_STR_XPORT_UDP_PROTO: s->pst_protocol = PS_PROTO_UDP; break; default: s->pst_protocol = sh->pst_str_xport_protocol; } /* * Copy stream size information. */ s->pst_qlimit = sh->pst_str_xport_qlimit; s->pst_qlen = sh->pst_str_xport_qlen; s->pst_idata = sh->pst_str_xport_idata; s->pst_ibufsz = sh->pst_str_xport_ibufsz; s->pst_rwnd = sh->pst_str_xport_rwnd; s->pst_swnd = sh->pst_str_xport_swnd; s->pst_odata = sh->pst_str_xport_odata; s->pst_obufsz = sh->pst_str_xport_obufsz; /* * Propagate protocol state from stream symbol values to socket ones. * * This could be avoided if PSTAT were to use a common set of protocol * state symbols. */ if (s->pst_protocol == PS_PROTO_TCP) { switch (sh->pst_str_xport_pstate) { #if defined(PS_STR_XPORT_TCPS_CLOSED) && defined(PS_TCPS_CLOSED) \ && (PS_STR_XPORT_TCPS_CLOSED != PS_TCPS_CLOSED) case PS_STR_XPORT_TCPS_CLOSED: s->pst_pstate = PS_TCPS_CLOSED; break; #endif #if defined(PS_STR_XPORT_TCPS_IDLE) && defined(PS_TCPS_IDLE) \ && (PS_STR_XPORT_TCPS_IDLE != PS_TCPS_IDLE) case PS_STR_XPORT_TCPS_IDLE: s->pst_pstate = PS_TCPS_IDLE; break; #endif #if defined(PS_STR_XPORT_TCPS_BOUND) && defined(PS_TCPS_BOUND) \ && (PS_STR_XPORT_TCPS_BOUND != PS_TCPS_BOUND) case PS_STR_XPORT_TCPS_BOUND: s->pst_pstate = PS_TCPS_BOUND; break; #endif #if defined(PS_STR_XPORT_TCPS_LISTEN) && defined(PS_TCPS_LISTEN) \ && (PS_STR_XPORT_TCPS_LISTEN != PS_TCPS_LISTEN) case PS_STR_XPORT_TCPS_LISTEN: s->pst_pstate = PS_TCPS_LISTEN; break; #endif #if defined(PS_STR_XPORT_TCPS_SYN_SENT) && defined(PS_TCPS_SYN_SENT) \ && (PS_STR_XPORT_TCPS_SYN_SENT != PS_TCPS_SYN_SENT) case PS_STR_XPORT_TCPS_SYN_SENT: s->pst_pstate = PS_TCPS_SYN_SENT; break; #endif #if defined(PS_STR_XPORT_TCPS_SYN_RCVD) && defined(PS_TCPS_SYN_RCVD) \ && (PS_STR_XPORT_TCPS_SYN_RCVD != PS_TCPS_SYN_RCVD) case PS_STR_XPORT_TCPS_SYN_RCVD: s->pst_pstate = PS_TCPS_SYN_RCVD; break; #endif #if defined(PS_STR_XPORT_TCPS_ESTABLISHED) && defined(PS_TCPS_ESTABLISHED) \ && (PS_STR_XPORT_TCPS_ESTABLISHED != PS_TCPS_ESTABLISHED) case PS_STR_XPORT_TCPS_ESTABLISHED: s->pst_pstate = PS_TCPS_ESTABLISHED; break; #endif #if defined(PS_STR_XPORT_TCPS_CLOSE_WAIT) && defined(PS_TCPS_CLOSE_WAIT) \ && (PS_STR_XPORT_TCPS_CLOSE_WAIT != PS_TCPS_CLOSE_WAIT) case PS_STR_XPORT_TCPS_CLOSE_WAIT: s->pst_pstate = PS_TCPS_CLOSE_WAIT; break; #endif #if defined(PS_STR_XPORT_TCPS_FIN_WAIT_1) && defined(PS_TCPS_FIN_WAIT_1) \ && (PS_STR_XPORT_TCPS_FIN_WAIT_1 != PS_TCPS_FIN_WAIT_1) case PS_STR_XPORT_TCPS_FIN_WAIT_1: s->pst_pstate = PS_TCPS_FIN_WAIT_1; break; #endif #if defined(PS_STR_XPORT_TCPS_CLOSING) && defined(PS_TCPS_CLOSING) \ && (PS_STR_XPORT_TCPS_CLOSING != PS_TCPS_CLOSING) case PS_STR_XPORT_TCPS_CLOSING: s->pst_pstate = PS_TCPS_CLOSING; break; #endif #if defined(PS_STR_XPORT_TCPS_LAST_ACK) && defined(PS_TCPS_LAST_ACK) \ && (PS_STR_XPORT_TCPS_LAST_ACK != PS_TCPS_LAST_ACK) case PS_STR_XPORT_TCPS_LAST_ACK: s->pst_pstate = PS_TCPS_LAST_ACK; break; #endif #if defined(PS_STR_XPORT_TCPS_FIN_WAIT_2) && defined(PS_TCPS_FIN_WAIT_2) \ && (PS_STR_XPORT_TCPS_FIN_WAIT_2 != PS_TCPS_FIN_WAIT_2) case PS_STR_XPORT_TCPS_FIN_WAIT_2: s->pst_pstate = PS_TCPS_FIN_WAIT_2; break; #endif #if defined(PS_STR_XPORT_TCPS_TIME_WAIT) && defined(PS_TCPS_TIME_WAIT) \ && (PS_STR_XPORT_TCPS_TIME_WAIT != PS_TCPS_TIME_WAIT) case PS_STR_XPORT_TCPS_TIME_WAIT: s->pst_pstate = PS_TCPS_TIME_WAIT; break; #endif default: s->pst_pstate = sh->pst_str_xport_pstate; } } else if (s->pst_protocol == PS_PROTO_UDP) { switch (sh->pst_str_xport_pstate) { #if defined(PS_STR_XPORT_TS_UNINIT) && defined(PS_TS_UNINIT) \ && (PS_STR_XPORT_TS_UNINIT != PS_TS_UNINIT) case PS_STR_XPORT_TS_UNINIT: s->pst_pstate = PS_TS_UNINIT; break; #endif #if defined(PS_STR_XPORT_TS_UNBND) && defined(PS_TS_UNBND) \ && (PS_STR_XPORT_TS_UNBND != PS_TS_UNBND) case PS_STR_XPORT_TS_UNBND: s->pst_pstate = PS_TS_UNBND; break; #endif #if defined(PS_STR_XPORT_TS_WACK_BREQ) && defined(PS_TS_WACK_BREQ) \ && (PS_STR_XPORT_TS_WACK_BREQ != PS_TS_WACK_BREQ) case PS_STR_XPORT_TS_WACK_BREQ: s->pst_pstate = PS_TS_WACK_BREQ; break; #endif #if defined(PS_STR_XPORT_TS_WACK_UREQ) && defined(PS_TS_WACK_UREQ) \ && (PS_STR_XPORT_TS_WACK_UREQ != PS_TS_WACK_UREQ) case PS_STR_XPORT_TS_WACK_UREQ: s->pst_pstate = PS_TS_WACK_UREQ; break; #endif #if defined(PS_STR_XPORT_TS_IDLE) && defined(PS_TS_IDLE) \ && (PS_STR_XPORT_TS_IDLE != PS_TS_IDLE) case PS_STR_XPORT_TS_IDLE: s->pst_pstate = PS_TS_IDLE; break; #endif #if defined(PS_STR_XPORT_TS_WACK_OPTREQ) && defined(PS_TS_WACK_OPTREQ) \ && (PS_STR_XPORT_TS_WACK_OPTREQ != PS_TS_WACK_OPTREQ) case PS_STR_XPORT_TS_WACK_OPTREQ: s->pst_pstate = PS_TS_WACK_OPTREQ; break; #endif #if defined(PS_STR_XPORT_TS_WACK_CREQ) && defined(PS_TS_WACK_CREQ) \ && (PS_STR_XPORT_TS_WACK_CREQ != PS_TS_WACK_CREQ) case PS_STR_XPORT_TS_WACK_CREQ: s->pst_pstate = PS_TS_WACK_CREQ; break; #endif #if defined(PS_STR_XPORT_TS_WCON_CREQ) && defined(PS_TS_WCON_CREQ) \ && (PS_STR_XPORT_TS_WCON_CREQ != PS_TS_WCON_CREQ) case PS_STR_XPORT_TS_WCON_CREQ: s->pst_pstate = PS_TS_WCON_CREQ; break; #endif #if defined(PS_STR_XPORT_TS_WRES_CIND) && defined(PS_TS_WRES_CIND) \ && (PS_STR_XPORT_TS_WRES_CIND != PS_TS_WRES_CIND) case PS_STR_XPORT_TS_WRES_CIND: s->pst_pstate = PS_TS_WRES_CIND; break; #endif #if defined(PS_STR_XPORT_TS_WACK_CRES) && defined(PS_TS_WACK_CRES) \ && (PS_STR_XPORT_TS_WACK_CRES != PS_TS_WACK_CRES) case PS_STR_XPORT_TS_WACK_CRES: s->pst_pstate = PS_TS_WACK_CRES; break; #endif #if defined(PS_STR_XPORT_TS_DATA_XFER) && defined(PS_TS_DATA_XFER) \ && (PS_STR_XPORT_TS_DATA_XFER != PS_TS_DATA_XFER) case PS_STR_XPORT_TS_DATA_XFER: s->pst_pstate = PS_TS_DATA_XFER; break; #endif #if defined(PS_STR_XPORT_TS_WIND_ORDREL) && defined(PS_TS_WIND_ORDREL) \ && (PS_STR_XPORT_TS_WIND_ORDREL != PS_TS_WIND_ORDREL) case PS_STR_XPORT_TS_WIND_ORDREL: s->pst_pstate = PS_TS_WIND_ORDREL; break; #endif #if defined(PS_STR_XPORT_TS_WREQ_ORDREL) && defined(PS_TS_WREQ_ORDREL) \ && (PS_STR_XPORT_TS_WREQ_ORDREL != PS_TS_WREQ_ORDREL) case PS_STR_XPORT_TS_WREQ_ORDREL: s->pst_pstate = PS_TS_WREQ_ORDREL; break; #endif #if defined(PS_STR_XPORT_TS_WACK_DREQ6) && defined(PS_TS_WACK_DREQ6) \ && (PS_STR_XPORT_TS_WACK_DREQ6 != PS_TS_WACK_DREQ6) case PS_STR_XPORT_TS_WACK_DREQ6: s->pst_pstate = PS_TS_WACK_DREQ6; break; #endif #if defined(PS_STR_XPORT_TS_WACK_DREQ7) && defined(PS_TS_WACK_DREQ7) \ && (PS_STR_XPORT_TS_WACK_DREQ7 != PS_TS_WACK_DREQ7) case PS_STR_XPORT_TS_WACK_DREQ7: s->pst_pstate = PS_TS_WACK_DREQ7; break; #endif #if defined(PS_STR_XPORT_TS_WACK_DREQ9) && defined(PS_TS_WACK_DREQ9) \ && (PS_STR_XPORT_TS_WACK_DREQ9 != PS_TS_WACK_DREQ9) case PS_STR_XPORT_TS_WACK_DREQ9: s->pst_pstate = PS_TS_WACK_DREQ9; break; #endif #if defined(PS_STR_XPORT_TS_WACK_DREQ10) && defined(PS_TS_WACK_DREQ10) \ && (PS_STR_XPORT_TS_WACK_DREQ10 != PS_TS_WACK_DREQ10) case PS_STR_XPORT_TS_WACK_DREQ10: s->pst_pstate = PS_TS_WACK_DREQ10; break; #endif #if defined(PS_STR_XPORT_TS_WACK_DREQ11) && defined(PS_TS_WACK_DREQ11) \ && (PS_STR_XPORT_TS_WACK_DREQ11 != PS_TS_WACK_DREQ11) case PS_STR_XPORT_TS_WACK_DREQ11: s->pst_pstate = PS_TS_WACK_DREQ11; break; #endif #if defined(PS_STR_XPORT_TS_WACK_ORDREL) && defined(PS_TS_WACK_ORDREL) \ && (PS_STR_XPORT_TS_WACK_ORDREL != PS_TS_WACK_ORDREL) case PS_STR_XPORT_TS_WACK_ORDREL: s->pst_pstate = PS_TS_WACK_ORDREL; break; #endif #if defined(PS_STR_XPORT_TS_NOSTATES) && defined(PS_TS_NOSTATES) \ && (PS_STR_XPORT_TS_NOSTATES != PS_TS_NOSTATES) case PS_STR_XPORT_TS_NOSTATES: s->pst_pstate = PS_TS_NOSTATES; break; #endif default: s->pst_pstate = sh->pst_str_xport_pstate; } } else s->pst_pstate = sh->pst_str_xport_pstate; /* * Now propagate the bound and remote address information from pst_stream * to the pst_socket structure. Validate the copy lengths. */ sz = (size_t)sh->pst_str_xport_boundaddr_len; if (sz > sizeof(s->pst_boundaddr)) sz = sizeof(s->pst_boundaddr); if ((s->pst_boundaddr_len = sz)) { (void) memcpy((void *)s->pst_boundaddr, (const void *)sh->pst_str_xport_boundaddr, sz); } sz = (size_t)sh->pst_str_xport_remaddr_len; if (sz > sizeof(s->pst_remaddr)) sz = sizeof(s->pst_remaddr); if ((s->pst_remaddr_len = sz)) { (void) memcpy((void *)s->pst_remaddr, (const void *)sh->pst_str_xport_remaddr, sz); } } #endif /* defined(PS_STR_XPORT_DATA) */ /* * printpsproto() -- print PSTAT protocol name */ static void printpsproto(p) uint32_t p; /* protocol number */ { int i; static int m = -1; char *s; switch (p) { case PS_PROTO_IP: s = "IP"; break; case PS_PROTO_ICMP: s = "ICMP"; break; case PS_PROTO_IGMP: s = "IGMP"; break; case PS_PROTO_GGP: s = "GGP"; break; case PS_PROTO_IPIP: s = "IPIP"; break; case PS_PROTO_TCP: s = "TCP"; break; case PS_PROTO_EGP: s = "EGP"; break; case PS_PROTO_IGP: s = "IGP"; break; case PS_PROTO_PUP: s = "PUP"; break; case PS_PROTO_UDP: s = "UDP"; break; case PS_PROTO_IDP: s = "IDP"; break; case PS_PROTO_XTP: s = "XTP"; break; case PS_PROTO_ESP: s = "ESP"; break; case PS_PROTO_AH: s = "AH"; break; case PS_PROTO_OSPF: s = "OSPF"; break; case PS_PROTO_IPENCAP: s = "IPENCAP"; break; case PS_PROTO_ENCAP: s = "ENCAP"; break; case PS_PROTO_PXP: s = "PXP"; break; case PS_PROTO_RAW: s = "RAW"; break; default: s = (char *)NULL; } if (s) (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL-1, s); else { if (m < 0) { for (i = 0, m = 1; i < IPROTOL-2; i++) m *= 10; } if (m > p) (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%d?", p); else (void) snpf(Lf->iproto, sizeof(Lf->iproto), "*%d?", p % (m/10)); } } /* * print_tcptpi() -- print TCP/TPI info */ void print_tcptpi(nl) int nl; /* 1 == '\n' required */ { char *cp = (char *)NULL; char sbuf[128]; int i; int ps = 0; unsigned int u; if (Ftcptpi & TCPTPI_STATE) { switch (Lf->lts.type) { case 0: /* TCP */ if (!TcpSt) (void) build_IPstates(); if ((i = Lf->lts.state.i + TcpStOff) < 0 || i >= TcpNstates) { (void) snpf(sbuf, sizeof(sbuf), "UknownState_%d", Lf->lts.state.i); cp = sbuf; } else cp = TcpSt[i]; break; case 1: /* UDP */ if (!UdpSt) (void) build_IPstates(); if ((u = Lf->lts.state.ui + UdpStOff) > UdpNstates) { (void) snpf(sbuf, sizeof(sbuf), "UNKNOWN_TPI_STATE_%u", Lf->lts.state.ui); cp = sbuf; } else cp = UdpSt[u]; } if (cp) { if (Ffield) (void) printf("%cST=%s%c", LSOF_FID_TCPTPI, cp, Terminator); else { putchar('('); (void) fputs(cp, stdout); } ps++; } } #if defined(HASTCPTPIQ) if (Ftcptpi & TCPTPI_QUEUES) { if (Lf->lts.rqs) { if (Ffield) putchar(LSOF_FID_TCPTPI); else { if (ps) putchar(' '); else putchar('('); } (void) printf("QR=%lu", Lf->lts.rq); if (Ffield) putchar(Terminator); ps++; } if (Lf->lts.sqs) { if (Ffield) putchar(LSOF_FID_TCPTPI); else { if (ps) putchar(' '); else putchar('('); } (void) printf("QS=%lu", Lf->lts.sq); if (Ffield) putchar(Terminator); ps++; } } #endif /* defined(HASTCPTPIQ) */ #if defined(HASSOOPT) if (Ftcptpi & TCPTPI_FLAGS) { int opt; if ((opt = Lf->lts.opt) || Lf->lts.qlens || Lf->lts.qlims) { char sep = ' '; if (Ffield) sep = LSOF_FID_TCPTPI; else if (!ps) sep = '('; (void) printf("%cSO", sep); ps++; sep = '='; # if defined(PS_SO_ACCEPTCONN) if (opt & PS_SO_ACCEPTCONN) { (void) printf("%cACCEPTCONN", sep); opt &= ~PS_SO_ACCEPTCONN; sep = ','; } # endif /* defined(PS_SO_ACCEPTCONN) */ # if defined(PS_SO_BROADCAST) if (opt & PS_SO_BROADCAST) { (void) printf("%cBROADCAST", sep); opt &= ~PS_SO_BROADCAST; sep = ','; } # endif /* defined(PS_SO_BROADCAST) */ # if defined(PS_SO_DEBUG) if (opt & PS_SO_DEBUG) { (void) printf("%cDEBUG", sep); opt &= ~PS_SO_DEBUG; sep = ','; } # endif /* defined(PS_SO_DEBUG) */ # if defined(PS_SO_DONTROUTE) if (opt & PS_SO_DONTROUTE) { (void) printf("%cDONTROUTE", sep); opt &= ~PS_SO_DONTROUTE; sep = ','; } # endif /* defined(PS_SO_DONTROUTE) */ # if defined(PS_SO_GETIFADDR) if (opt & PS_SO_GETIFADDR) { (void) printf("%cGETIFADDR", sep); opt &= ~PS_SO_GETIFADDR; sep = ','; } # endif /* defined(PS_SO_GETIFADDR) */ # if defined(PS_SO_INPCB_COPY) if (opt & PS_SO_INPCB_COPY) { (void) printf("%cINPCB_COPY", sep); opt &= ~PS_SO_INPCB_COPY; sep = ','; } # endif /* defined(PS_SO_INPCB_COPY) */ # if defined(PS_SO_KEEPALIVE) if (opt & PS_SO_KEEPALIVE) { (void) printf("%cKEEPALIVE", sep); if (Lf->lts.kai) (void) printf("=%d", Lf->lts.kai); opt &= ~PS_SO_KEEPALIVE; sep = ','; } # endif /* defined(PS_SO_KEEPALIVE) */ # if defined(PS_SO_LINGER) if (opt & PS_SO_LINGER) { (void) printf("%cLINGER", sep); if (Lf->lts.ltm) (void) printf("=%d", Lf->lts.ltm); opt &= ~PS_SO_LINGER; sep = ','; } # endif /* defined(PS_SO_LINGER) */ # if defined(PS_SO_OOBINLINE) if (opt & PS_SO_OOBINLINE) { (void) printf("%cOOBINLINE", sep); opt &= ~PS_SO_OOBINLINE; sep = ','; } # endif /* defined(PS_SO_OOBINLINE) */ # if defined(PS_SO_PMTU) if (opt & PS_SO_PMTU) { (void) printf("%cPMTU", sep); opt &= ~PS_SO_PMTU; sep = ','; } # endif /* defined(PS_SO_PMTU) */ if (Lf->lts.qlens) { (void) printf("%cQLEN=%u", sep, Lf->lts.qlen); sep = ','; } if (Lf->lts.qlims) { (void) printf("%cQLIM=%u", sep, Lf->lts.qlim); sep = ','; } # if defined(PS_SO_REUSEADDR) if (opt & PS_SO_REUSEADDR) { (void) printf("%cREUSEADDR", sep); opt &= ~PS_SO_REUSEADDR; sep = ','; } # endif /* defined(PS_SO_REUSEADDR) */ # if defined(PS_SO_REUSEPORT) if (opt & PS_SO_REUSEPORT) { (void) printf("%cREUSEPORT", sep); opt &= ~PS_SO_REUSEPORT; sep = ','; } # endif /* defined(PS_SO_REUSEPORT) */ # if defined(PS_SO_USELOOPBACK) if (opt & PS_SO_USELOOPBACK) { (void) printf("%cUSELOOPBACK", sep); opt &= ~PS_SO_USELOOPBACK; sep = ','; } # endif /* defined(PS_SO_USELOOPBACK) */ if (opt) (void) printf("%cUNKNOWN=%#x", sep, opt); if (Ffield) putchar(Terminator); } } #endif /* defined(HASSOOPT) */ #if defined(HASSOSTATE) if (Ftcptpi & TCPTPI_FLAGS) { int ss; if ((ss = Lf->lts.ss)) { char sep = ' '; if (Ffield) sep = LSOF_FID_TCPTPI; else if (!ps) sep = '('; (void) printf("%cSS", sep); ps++; sep = '='; # if defined(PS_SS_ASYNC) if (ss & PS_SS_ASYNC) { (void) printf("%cASYNC", sep); ss &= ~PS_SS_ASYNC; sep = ','; } # endif /* defined(PS_SS_ASYNC) */ # if defined(PS_SS_BOUND) if (ss & PS_SS_BOUND) { (void) printf("%cBOUND", sep); ss &= ~PS_SS_BOUND; sep = ','; } # endif /* defined(PS_SS_BOUND) */ # if defined(PS_SS_CANTRCVMORE) if (ss & PS_SS_CANTRCVMORE) { (void) printf("%cCANTRCVMORE", sep); ss &= ~PS_SS_CANTRCVMORE; sep = ','; } # endif /* defined(PS_SS_CANTRCVMORE) */ # if defined(PS_SS_CANTSENDMORE) if (ss & PS_SS_CANTSENDMORE) { (void) printf("%cCANTSENDMORE", sep); ss &= ~PS_SS_CANTSENDMORE; sep = ','; } # endif /* defined(PS_SS_CANTSENDMORE) */ # if defined(PS_SS_ISCONNECTED) if (ss & PS_SS_ISCONNECTED) { (void) printf("%cISCONNECTED", sep); ss &= ~PS_SS_ISCONNECTED; sep = ','; } # endif /* defined(PS_SS_ISCONNECTED) */ # if defined(PS_SS_ISCONNECTING) if (ss & PS_SS_ISCONNECTING) { (void) printf("%cISCONNECTING", sep); ss &= ~PS_SS_ISCONNECTING; sep = ','; } # endif /* defined(PS_SS_ISCONNECTING) */ # if defined(PS_SS_ISDISCONNECTI) if (ss & PS_SS_ISDISCONNECTI) { (void) printf("%cISDISCONNECTI", sep); ss &= ~PS_SS_ISDISCONNECTI; sep = ','; } # endif /* defined(PS_SS_ISDISCONNECTI) */ # if defined(PS_SS_INTERRUPTED) if (ss & PS_SS_INTERRUPTED) { (void) printf("%cINTERRUPTED", sep); ss &= ~PS_SS_INTERRUPTED; sep = ','; } # endif /* defined(PS_SS_INTERRUPTED) */ # if defined(PS_SS_NBIO) if (ss & PS_SS_NBIO) { (void) printf("%cNBIO", sep); ss &= ~PS_SS_NBIO; sep = ','; } # endif /* defined(PS_SS_NBIO) */ # if defined(PS_SS_NOFDREF) if (ss & PS_SS_NOFDREF) { (void) printf("%cNOFDREF", sep); ss &= ~PS_SS_NOFDREF; sep = ','; } # endif /* defined(PS_SS_NOFDREF) */ # if defined(PS_SS_NOUSER) if (ss & PS_SS_NOUSER) { (void) printf("%cNOUSER", sep); ss &= ~PS_SS_NOUSER; sep = ','; } # endif /* defined(PS_SS_NOUSER) */ # if defined(PS_SS_NOWAIT) if (ss & PS_SS_NOWAIT) { (void) printf("%cNOWAIT", sep); ss &= ~PS_SS_NOWAIT; sep = ','; } # endif /* defined(PS_SS_NOWAIT) */ # if defined(PS_SS_PRIV) if (ss & PS_SS_PRIV) { (void) printf("%cPRIV", sep); ss &= ~PS_SS_PRIV; sep = ','; } # endif /* defined(PS_SS_PRIV) */ # if defined(PS_SS_RCVATMARK) if (ss & PS_SS_RCVATMARK) { (void) printf("%cRCVATMARK", sep); ss &= ~PS_SS_RCVATMARK; sep = ','; } # endif /* defined(PS_SS_RCVATMARK) */ # if defined(PS_SS_XOPEN_EXT1) if (ss & PS_SS_XOPEN_EXT1) { (void) printf("%cXOPEN_EXT1", sep); ss &= ~PS_SS_XOPEN_EXT1; sep = ','; } # endif /* defined(PS_SS_XOPEN_EXT1) */ if (ss) (void) printf("%cUNKNOWN=%#x", sep, ss); if (Ffield) putchar(Terminator); } } #endif /* defined(HASSOSTATE) */ #if defined(HASTCPTPIW) if (Ftcptpi & TCPTPI_WINDOWS) { if (Lf->lts.rws) { if (Ffield) putchar(LSOF_FID_TCPTPI); else { if (ps) putchar(' '); else putchar('('); } (void) printf("WR=%lu", Lf->lts.rw); if (Ffield) putchar(Terminator); ps++; } if (Lf->lts.wws) { if (Ffield) putchar(LSOF_FID_TCPTPI); else { if (ps) putchar(' '); else putchar('('); } (void) printf("WW=%lu", Lf->lts.ww); if (Ffield) putchar(Terminator); ps++; } } #endif /* defined(HASTCPTPIW) */ if (Ftcptpi && !Ffield && ps) putchar(')'); if (nl) putchar('\n'); } /* * process_socket() -- process socket */ void process_socket(f, s) struct pst_fileinfo2 *f; /* file information */ struct pst_socket *s; /* optional socket information * NULL == none */ { int af, err, fp, lp, tx; char buf[1024], tbuf[32]; unsigned char *fa = (unsigned char *)NULL; unsigned char *la = (unsigned char *)NULL; size_t len; KA_T na, nau; char *nma = (char *)NULL; struct pst_filedetails pd; struct sockaddr_in *sa; int sx; #if defined(HASIPv6) struct sockaddr_in6 *sa6; #endif /* defined(HASIPv6) */ struct sockaddr_un *ua; /* * Read socket info, as required, so that the protocol state names can be * tested as soon as possible. */ if (!s) { if (!(s = read_sock(f))) { (void) snpf(Namech, Namechl, "can't read pst_socket%s%s", errno ? ": " : "", errno ? strerror(errno) : ""); (void) enter_nm(Namech); return; } } /* * Collect protocol details so the protocol state name might be tested, * as requested by options. */ switch (s->pst_family) { case PS_AF_INET: af = 4; break; #if defined(HASIPv6) case PS_AF_INET6: af = 6; break; #endif /* defined(HASIPv6) */ default: af = -1; } switch (s->pst_protocol) { case PS_PROTO_TCP: sx = (int)s->pst_pstate + TcpStOff; tx = 0; break; case PS_PROTO_UDP: sx = (unsigned int)s->pst_pstate + UdpStOff; tx = 1; break; default: sx = tx = -1; } /* * Test the protocol state and name, setting the SELNET flag where possible. */ switch (tx) { case 0: /* TCP */ if (TcpStXn) { /* * Check for TCP state exclusion. */ if (sx >= 0 && sx < TcpNstates) { if (TcpStX[sx]) { Lf->sf |= SELEXCLF; return; } } } if (TcpStIn) { if (sx >= 0 && sx < TcpNstates) { if (TcpStI[sx]) TcpStI[sx] = 2; else { Lf->sf |= SELEXCLF; return; } } } break; case 1: /* UDP */ if (UdpStXn) { /* * Check for UDP state exclusion. */ if (sx >= 0 && sx < UdpNstates) { if (UdpStX[sx]) { Lf->sf |= SELEXCLF; return; } } } if (UdpStIn) { if (sx >= 0 && sx < UdpNstates) { if (UdpStI[sx]) UdpStI[sx] = 2; else { Lf->sf |= SELEXCLF; return; } } } break; } /* * Set default type. */ (void) snpf(Lf->type, sizeof(Lf->type), "sock"); Lf->inp_ty = 2; /* * Generate and save node ID. */ na = (KA_T)(((KA_T)(f->psf_hi_nodeid & 0xffffffff) << 32) | (KA_T)(f->psf_lo_nodeid & 0xffffffff)); #if defined(HASFSTRUCT) if (na && (Fsv & FSV_NI)) { if (na) { Lf->fna = na; Lf->fsv |= FSV_NI; } } #endif /* defined(HASFSTRUCT) */ /* * Save size information, as requested. */ if (Fsize) { if (Lf->access == 'r') Lf->sz = (SZOFFTYPE)s->pst_idata; else if (Lf->access == 'w') Lf->sz = (SZOFFTYPE)s->pst_odata; else Lf->sz = (SZOFFTYPE)(s->pst_idata + s->pst_odata); Lf->sz_def = 1; } else Lf->off_def = 1; #if defined(HASTCPTPIQ) /* * Enter queue sizes. */ switch (s->pst_family) { case PS_AF_INET: case PS_AF_INET6: Lf->lts.rq = (unsigned long)s->pst_idata; Lf->lts.sq = (unsigned long)s->pst_odata; Lf->lts.rqs = Lf->lts.sqs = (unsigned char)1; } #endif /* defined(HASTCPTPIQ) */ #if defined(HASSOOPT) /* * Enter socket options. */ Lf->lts.opt = (unsigned int)s->pst_options; Lf->lts.ltm = (unsigned int)s->pst_linger; Lf->lts.qlen = (unsigned int)s->pst_qlen; Lf->lts.qlim = (unsigned int)s->pst_qlimit; Lf->lts.qlens = Lf->lts.qlims = (unsigned char)1; #endif /* defined(HASSOOPT) */ #if defined(HASSOSTATE) /* * Enter socket state flags. */ Lf->lts.ss = (unsigned int)s->pst_state; #endif /* defined(HASSOSTATE) */ #if defined(HASTCPTPIW) /* * Enter window sizes. */ switch (s->pst_family) { case PS_AF_INET: case PS_AF_INET6: Lf->lts.rw = (unsigned long)s->pst_rwnd; Lf->lts.ww = (unsigned long)s->pst_swnd; Lf->lts.rws = Lf->lts.wws = (unsigned char)1; } #endif /* defined(HASTCPTPIW) */ /* * Process socket by the associated domain family. */ switch (s->pst_family) { case PS_AF_INET: if (Fnet && (!FnetTy || (FnetTy != 6))) Lf->sf |= SELNET; (void) snpf(Lf->type, sizeof(Lf->type), #if defined(HASIPv6) "IPv4" #else /* !defined(HASIPv6) */ "inet" #endif /* defined(HASIPv6) */ ); printpsproto(s->pst_protocol); enter_dev_ch(print_kptr(na, (char *)NULL, 0)); switch (s->pst_protocol) { case PS_PROTO_TCP: Lf->lts.type = 0; Lf->lts.state.i = (int)s->pst_pstate; break; case PS_PROTO_UDP: Lf->lts.type = 1; Lf->lts.state.ui = (unsigned int)s->pst_pstate; } /* * Enter local and remote addresses, being careful to generate * proper IPv4 address alignment by copying, since IPv4 addresses * may not be properly aligned in pst_boundaddr[] and pst_remaddr[]. */ if ((size_t)s->pst_boundaddr_len == sizeof(struct sockaddr_in)) { sa = (struct sockaddr_in *)s->pst_boundaddr; la = (unsigned char *)&sa->sin_addr; lp = (int)htons(sa->sin_port); } if ((size_t)s->pst_remaddr_len == sizeof(struct sockaddr_in)) { sa = (struct sockaddr_in *)s->pst_remaddr; fp = (int)htons(sa->sin_port); if ((sa->sin_addr.s_addr != INADDR_ANY) || fp) fa = (unsigned char *)&sa->sin_addr; } if (fa || la) (void) ent_inaddr(la, lp, fa, fp, AF_INET); break; #if defined(HASIPv6) case PS_AF_INET6: af = AF_INET6; if (Fnet && (!FnetTy || (FnetTy != 4))) Lf->sf |= SELNET; (void) snpf(Lf->type, sizeof(Lf->type), "IPv6"); printpsproto(s->pst_protocol); enter_dev_ch(print_kptr(na, (char *)NULL, 0)); switch (s->pst_protocol) { case PS_PROTO_TCP: Lf->lts.type = 0; Lf->lts.state.i = (int)s->pst_pstate; break; case PS_PROTO_UDP: Lf->lts.type = 1; Lf->lts.state.ui = (unsigned int)s->pst_pstate; } /* * Enter local and remote addresses, being careful to generate * proper IPv6 address alignment by copying, since IPv6 addresses * may not be properly aligned in pst_boundaddr[] and pst_remaddr[]. */ if ((size_t)s->pst_boundaddr_len == sizeof(struct sockaddr_in6)) { sa6 = (struct sockaddr_in6 *)s->pst_boundaddr; la = (unsigned char *)&sa6->sin6_addr; lp = (int)htons(sa6->sin6_port); } if ((size_t)s->pst_remaddr_len == sizeof(struct sockaddr_in6)) { sa6 = (struct sockaddr_in6 *)s->pst_remaddr; if ((fp = (int)htons(sa6->sin6_port)) || !IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr)) fa = (unsigned char *)&sa6->sin6_addr; } if (la || fa) { if ((la && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)la)) || (fa && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)fa))) { if (la) la = (unsigned char *)IPv6_2_IPv4(la); if (fa) fa = (unsigned char *)IPv6_2_IPv4(fa); af = AF_INET; } } if (fa || la) (void) ent_inaddr(la, lp, fa, fp, af); break; #endif /* defined(HASIPv6) */ case PS_AF_UNIX: if (Funix) Lf->sf |= SELUNX; (void) snpf(Lf->type, sizeof(Lf->type), "unix"); if (((len = (size_t)s->pst_boundaddr_len) > 0) && (len <= sizeof(struct sockaddr_un))) { ua = (struct sockaddr_un *)s->pst_boundaddr; if (ua->sun_path[0]) { /* * The AF_UNIX socket has a bound address (file path). * * Save it. If there is a low nodeid, put that in * parentheses after the name. If there is a low peer * nodeid, put that in the parentheses, too. */ s->pst_boundaddr[PS_ADDR_SZ - 1] = '\0'; if (s->pst_lo_nodeid) { (void) snpf(buf, sizeof(buf), "(%s%s%s)", print_kptr((KA_T)s->pst_lo_nodeid, tbuf, sizeof(tbuf)), s->pst_peer_lo_nodeid ? "->" : "", s->pst_peer_lo_nodeid ? print_kptr((KA_T)s->pst_peer_lo_nodeid, (char *)NULL, 0) : "" ); len = strlen(buf) + 1; if (!(nma = (char *)malloc((MALLOC_S)len))) { (void) fprintf(stderr, "%s: no unix nma space(1): PID %ld, FD %s", Pn, (long)Lp->pid, Lf->fd); } (void) snpf(nma, len, "%s", buf); Lf->nma = nma; } /* * Read the pst_filedetails for the bound address and process * them as for a regular file. The already-entered file type, * file name, size or offset, and name appendix will be * preserved. */ if ((nau = read_det(&f->psf_fid, f->psf_hi_fileid, f->psf_lo_fileid, f->psf_hi_nodeid, f->psf_lo_nodeid, &pd))) { enter_nm(ua->sun_path); (void) process_finfo(&pd, &f->psf_fid, &f->psf_id, nau); return; } else { /* * Couldn't read file details. Erase any name appendix. * Put the socket nodeid in the DEVICE column, put the * bound address (path) in the NAME column, and build * a new name appendix with the peer address. Add an * error message if pstat_getfiledetails() set errno to * something other than ENOENT. */ if ((err = errno) == ENOENT) err = 0; if (nma) { (void) free((MALLOC_P *)nma); Lf->nma = (char *)NULL; } if (s->pst_lo_nodeid) { enter_dev_ch(print_kptr((KA_T)s->pst_lo_nodeid, (char *)NULL, 0)); } (void) snpf(Namech, Namechl, "%s", ua->sun_path); if (err || s->pst_peer_lo_nodeid) { (void) snpf(buf, sizeof(buf), "%s%s%s%s%s%s%s", err ? "(Error: " : "", err ? strerror(err) : "", err ? ")" : "", (err && s->pst_peer_lo_nodeid) ? " " : "", s->pst_peer_lo_nodeid ? "(->" : "", s->pst_peer_lo_nodeid ? print_kptr((KA_T)s->pst_peer_lo_nodeid, (char *)NULL, 0) : "", s->pst_peer_lo_nodeid ? ")" : "" ); len = strlen(buf) + 1; if (!(nma = (char *)malloc((MALLOC_S)len))) { (void) fprintf(stderr, "%s: no unix nma space(2): PID %ld, FD %s", Pn, (long)Lp->pid, Lf->fd); } (void) snpf(nma, len, "%s", buf); Lf->nma = nma; } if (Sfile && is_file_named(ua->sun_path, 0)) Lf->sf |= SELNM; break; } } } /* * If the UNIX socket has no bound address (file path), display the * low nodeid in the DEVICE column and the peer's low nodeid in the * NAME column. */ if (s->pst_peer_lo_nodeid) { (void) snpf(Namech, Namechl, "->%s", print_kptr((KA_T)s->pst_peer_lo_nodeid, (char *)NULL, 0)); } if (s->pst_lo_nodeid) enter_dev_ch(print_kptr((KA_T)s->pst_lo_nodeid,(char *)NULL,0)); break; default: (void) snpf(Namech, Namechl, "unsupported family: AF_%d", s->pst_family); } if (Namech[0]) enter_nm(Namech); } /* * process_stream() -- process stream */ void process_stream(f, ckscko) struct pst_fileinfo2 *f; /* pst_fileinfo2 */ int ckscko; /* socket file only checking * if 1 */ { struct clone *cl; char *cp; struct l_dev *dp = (struct l_dev *)NULL; int hx, i, ncx, nsn, nsr; size_t nb, nl; KA_T na; static int nsa = 0; dev_t rdev; static struct pst_stream *s = (struct pst_stream *)NULL; struct pst_socket sck; static size_t sz = sizeof(struct pst_stream); #if !defined(PS_STR_XPORT_DATA) /* * If socket file only checking is enabled and this HP-UX PSTAT instance * doesn't support TCP or UDP stream eXPORT data, return without further * action. */ if (ckscko == 1) return; #endif /* !defined(PS_STR_XPORT_DATA) */ /* * Generate and save node ID. */ na = (KA_T)(((KA_T)(f->psf_hi_nodeid & 0xffffffff) << 32) | (KA_T)(f->psf_lo_nodeid & 0xffffffff)); #if defined(HASFSTRUCT) if (na && (Fsv & FSV_NI)) { Lf->fna = na; Lf->fsv |= FSV_NI; } #endif /* defined(HASFSTRUCT) */ /* * Enter type. */ switch (f->psf_ftype) { case PS_TYPE_STREAMS: cp = "STR"; break; case PS_TYPE_SOCKET: if (f->psf_subtype == PS_SUBTYPE_SOCKSTR) { cp = "STSO"; break; } /* fall through */ default: cp = "unkn"; } (void) snpf(Lf->type, sizeof(Lf->type), "%s", cp); /* * Allocate sufficient space for stream structures, then read them. */ if ((nsn = f->psf_nstrentt) && (nsn >= nsa)) { nb = (size_t)(nsn * sizeof(struct pst_stream)); if (s) s = (struct pst_stream *)realloc((MALLOC_P *)s, nb); else s = (struct pst_stream *)malloc(nb); if (!s) { (void) fprintf(stderr, "%s: no space for %ld pst_stream bytes\n", Pn, (long)nb); Exit(1); } nsa = nsn; } errno = 0; if ((nsr = pstat_getstream(s, sz, (size_t)nsn, 0, &f->psf_fid)) < 1) { if (nsn) { (void) snpf(Namech, Namechl, "can't read %d stream structures%s%s", nsn, errno ? ": " : "", errno ? strerror(errno) : ""); enter_nm(Namech); } else enter_nm("no stream structures present"); return; } /* * Find the stream head. */ for (hx = 0; hx < nsn; hx++) { if (s[hx].type == PS_STR_HEAD) break; } if (hx >= nsn) { enter_nm("no stream head located"); return; } /* * Make sure the stream head's fileid and nodeid match the ones in the * pst_fileino2 structure. */ if ((f->psf_hi_fileid != s[hx].val.head.pst_hi_fileid) | (f->psf_lo_fileid != s[hx].val.head.pst_lo_fileid) | (f->psf_hi_nodeid != s[hx].val.head.pst_hi_nodeid) | (f->psf_lo_nodeid != s[hx].val.head.pst_lo_nodeid)) { enter_nm("no matching stream data available"); return; } #if defined(PS_STR_XPORT_DATA) /* * See if this stream has eXPORT data available and is a TCP or * UDP stream. */ if ((s[hx].pst_extn_flags & PS_STR_XPORT_DATA) && ((s[hx].pst_str_xport_protocol == PS_STR_XPORT_TCP_PROTO) || (s[hx].pst_str_xport_protocol == PS_STR_XPORT_UDP_PROTO)) ) { /* * Make a socket from the eXPORT data and process it. */ (void) make_sock(f, &s[hx], &sck); (void) process_socket(f, &sck); return; } else if (ckscko || Selinet) { /* * If socket file or Internet file only processing is enabled, return. */ return; } #endif /* defined(PS_STR_XPORT_DATA) */ /* * Enter size from stream head's structure, if requested. */ if (Fsize) { if (Lf->access == 'r') { Lf->sz = (SZOFFTYPE)s[hx].val.head.pst_rbytes; Lf->sz_def = 1; } else if (Lf->access == 'w') { Lf->sz = (SZOFFTYPE)s[hx].val.head.pst_wbytes; Lf->sz_def = 1; } else if (Lf->access == 'u') { Lf->sz = (SZOFFTYPE)s[hx].val.head.pst_rbytes + (SZOFFTYPE)s[hx].val.head.pst_wbytes; Lf->sz_def = 1; } } /* * Get the the device number from the stream head. * * If the stream is a clone: * * if there's a clone list, search it for the device, based on the stream * head's minor device number only; * if there's no clone list, search Devtp[], using a device number made * from the stream head's major and minor device numbers; * set the printable clone device number to one whose major device number * is the stream head's minor device number, and whose minor device * number is the stream head's device sequence number. * * If the stream isn't a clone, make the device number from the stream head's * major and minor numbers, and look up the non-clone device number in Devtp[]. */ if (!Sdev) readdev(0); if (s[hx].val.head.pst_flag & PS_STR_ISACLONE) { if (HaveCloneMaj && (CloneMaj == s[hx].val.head.pst_dev_major)) { for (cl = Clone; cl; cl = cl->next) { if (GET_MIN_DEV(Devtp[cl->dx].rdev) == s[hx].val.head.pst_dev_minor) { dp = &Devtp[cl->dx]; break; } } } else { rdev = makedev(s[hx].val.head.pst_dev_major, s[hx].val.head.pst_dev_minor); dp = lkupdev(&DevDev, &rdev, 0, 1); } rdev = makedev(s[hx].val.head.pst_dev_minor, s[hx].val.head.pst_dev_seq); } else { rdev = makedev(s[hx].val.head.pst_dev_major, s[hx].val.head.pst_dev_minor); dp = lkupdev(&DevDev, &rdev, 0, 1); } Lf->dev = DevDev; Lf->rdev = rdev; Lf->dev_def = Lf->rdev_def = 1; /* * If the device was located, enter the device name and save the node number. * * If the device wasn't located, save a positive file ID number from the * pst_fileinfo as a node number. */ if (dp) { (void) snpf(Namech, Namechl, "%s", dp->name); ncx = strlen(Namech); Lf->inode = (INODETYPE)dp->inode; Lf->inp_ty = 1; } else { ncx = (size_t)0; if (f->psf_id.psf_fileid > 0) { Lf->inode = (INODETYPE)f->psf_id.psf_fileid; Lf->inp_ty = 1; } } /* * Enter stream module names. */ for (i = 1; i < nsr; i++) { if (!(nl = strlen(s[i].val.module.pst_name))) continue; if (ncx) { if ((ncx + 2) > (Namechl - 1)) break; (void) snpf(&Namech[ncx], Namechl - ncx, "->"); ncx += 2; } if ((ncx + nl) > (Namechl - 1)) break; (void) snpf(Namech+ncx,Namechl-ncx,"%s",s[i].val.module.pst_name); ncx += nl; } /* * Set node type. * * Set offset defined if file size not requested or if no size was * obtained from the stream head. */ Lf->ntype = N_STREAM; Lf->is_stream = 1; if (!Fsize || (Fsize && !Lf->sz_def)) Lf->off_def = 1; /* * Test for specified file. */ if ((f->psf_subtype == PS_SUBTYPE_CHARDEV) || (f->psf_subtype == PS_SUBTYPE_BLKDEV)) i = 1; else i = 0; if (Sfile && is_file_named((char *)NULL, i)) Lf->sf |= SELNM; /* * Enter any name characters. */ if (Namech[0]) enter_nm(Namech); } /* * read_sock() -- read pst_socket info for file */ struct pst_socket * read_sock(f) struct pst_fileinfo2 *f; /* file information */ { static struct pst_socket s; errno = 0; if (f) { if (pstat_getsocket(&s, sizeof(s), &f->psf_fid) > 0 && f->psf_hi_fileid == s.pst_hi_fileid && f->psf_lo_fileid == s.pst_lo_fileid && f->psf_hi_nodeid == s.pst_hi_nodeid && f->psf_lo_nodeid == s.pst_lo_nodeid) return(&s); } return((struct pst_socket *)NULL); } lsof-4.86+dfsg.orig/dialects/hpux/pstat/dproc.c0000444000175000017500000005463711033762311021652 0ustar nicholasnicholas/* * dproc.c -- pstat-based HP-UX process access functions for lsof */ /* * Copyright 1999 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1999 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id"; #endif #include "lsof.h" /* * Local definitions */ #define FDS_ALLOC_INCR 256 /* fds[] allocation increment */ #define FDS_ALLOC_INIT 64 /* initial fds[] allocation */ #define FINFOINCR 128 /* pst_fileinfo2 table allocation * increment */ #define INCLMEM(s, m) ((size_t)(offsetof(struct s, m) \ + sizeof(((struct s *)0)->m))) /* size of struct s, including * member m */ #define PSTATINCR 512 /* pst_status table allocation * increment */ #define TXTVMINCR 64 /* text and vm info table table * allocation increment */ #define VMREGINCR 64 /* VM region table table allocation * increment */ /* * Local structures */ struct pstatck { size_t moff; /* offset of size member in pst_static * -- from offsetof(...member) */ size_t msz; /* structure's pst_static member * inclusion size -- from INCLMEM(s, m) * macro */ size_t ssz; /* structure size -- from * sizeof(struct) */ char *sn; /* structure name */ } PstatCk[] = { { (size_t)offsetof(struct pst_static, pst_status_size), (size_t)INCLMEM(pst_static, pst_status_size), sizeof(struct pst_status), "pst_status" }, { (size_t)offsetof(struct pst_static, pst_vminfo_size), (size_t)INCLMEM(pst_static, pst_vminfo_size), sizeof(struct pst_vminfo), "pst_vminfo" }, { (size_t)offsetof(struct pst_static, pst_filedetails_size), (size_t)INCLMEM(pst_static, pst_filedetails_size), sizeof(struct pst_filedetails), "pst_filedetails" }, { (size_t)offsetof(struct pst_static, pst_socket_size), (size_t)INCLMEM(pst_static, pst_socket_size), sizeof(struct pst_socket), "pst_socket" }, { (size_t)offsetof(struct pst_static, pst_stream_size), (size_t)INCLMEM(pst_static, pst_stream_size), sizeof(struct pst_stream), "pst_stream" }, { (size_t)offsetof(struct pst_static, pst_mpathnode_size), (size_t)INCLMEM(pst_static, pst_mpathnode_size), sizeof(struct pst_mpathnode), "pst_mpathnode" }, { (size_t)offsetof(struct pst_static, pst_fileinfo2_size), (size_t)INCLMEM(pst_static, pst_fileinfo2_size), sizeof(struct pst_fileinfo2), "pst_fileinfo2" }, }; #define NPSTATCK (sizeof(PstatCk) /sizeof(struct pstatck)) /* * Local static variables */ static int HvRtPsfid = -1; /* "/" psfileid status: * -1: not yet tested; * 0: tested and unknown; * 1: tested and known */ static struct psfileid RtPsfid; /* "/" psfileid */ /* * Local function prototypes */ _PROTOTYPE(static void get_kernel_access,(void)); _PROTOTYPE(static void process_text,(struct pst_status *p)); _PROTOTYPE(static struct pst_fileinfo2 *read_files,(struct pst_status *p, int *n)); _PROTOTYPE(static struct pst_status *read_proc,(int *n)); _PROTOTYPE(static struct pst_vm_status *read_vmreg,(struct pst_status *p, int *n)); /* * gather_proc_info() -- gather process information */ void gather_proc_info() { short cckreg; /* conditional status of regular file * checking: * 0 = unconditionally check * 1 = conditionally check */ short ckscko; /* socket file only checking status: * 0 = none * 1 = check only socket files, * including TCP and UDP * streams with eXPORT data, * where supported */ int cwds, fd, *fds, fdsa, i, j, l, nf, np, rtds; struct pst_fileinfo2 *f; long flag; KA_T ka, na; MALLOC_S nb; struct pst_status *p; struct pst_filedetails pd; struct pst_socket *s; short pss, sf; /* * Compute current working and root directory statuses and the statuses of * the first FDS_ALLOC_INIT FDs. */ if (Fand && Fdl) { cwds = (ck_fd_status(CWD, -1) != 2) ? 0 : 1; rtds = (ck_fd_status(RTD, -1) != 2) ? 0 : 1; nb = (MALLOC_S)(sizeof(int) * FDS_ALLOC_INIT); if (!(fds = (int *)malloc(nb))) { (void) fprintf(stderr, "%s: can't allocate %d FD status entries\n", Pn, FDS_ALLOC_INIT); Exit(1); } for (fdsa = 0; fdsa < FDS_ALLOC_INIT; fdsa++) { if (Fand && Fdl) fds[fdsa] = (ck_fd_status(NULL, fdsa) == 2) ? 1 : 0; else fds[fdsa] = 1; } } else { cwds = rtds = 1; fdsa = 0; fds = (int *)NULL; } /* * If only socket files have been selected, or socket files have been selected * ANDed with other selection options, enable the skipping of regular files. * * If socket files and some process options have been selected, enable * conditional skipping of regular file; i.e., regular files will be skipped * unless they belong to a process selected by one of the specified options. */ if (Selflags & SELNW) { /* * Some network files selection options have been specified. */ if (Fand || !(Selflags & ~SELNW)) { /* * Selection ANDing or only network file options have been * specified, so set unconditional skipping of regular files * and socket file only checking. */ cckreg = 0; ckscko = 1; } else { /* * If ORed file selection options have been specified, or no ORed * process selection options have been specified, enable * unconditional file checking and clear socket file only checking. * * If only ORed process selection options have been specified, * enable conditional file skipping and socket file only checking. */ if ((Selflags & SELFILE) || !(Selflags & SELPROC)) cckreg = ckscko = 0; else cckreg = ckscko = 1; } } else { /* * No network file selection options were specified. Enable * unconditional file checking and clear socket file only checking. */ cckreg = ckscko = 0; } /* * Examine proc structures and their associated information. */ for (i = 0, p = read_proc(&np); i < np; i++, p++) { if (!p->pst_stat || p->pst_stat == PS_ZOMBIE) continue; if (is_proc_excl((int)p->pst_pid, (int)p->pst_pgrp, (UID_ARG)p->pst_uid, &pss, &sf)) continue; /* * Make sure the command name is NUL-terminated. */ p->pst_ucomm[PST_UCOMMLEN - 1] = '\0'; if (is_cmd_excl(p->pst_ucomm, &pss, &sf)) continue; if (cckreg) { /* * If conditional checking of regular files is enabled, enable * socket file only checking, based on the process' selection * status. */ ckscko = (sf & SELPROC) ? 0 : 1; } alloc_lproc((int)p->pst_pid, (int)p->pst_pgrp, (int)p->pst_ppid, (UID_ARG)p->pst_uid, p->pst_ucomm, (int)pss, (int)sf); Plf = (struct lfile *)NULL; /* * Save current working directory information. */ if (!ckscko && cwds && IS_PSFILEID(&p->pst_cdir) && (p->pst_cdir.psf_fileid > 0) ) { alloc_lfile(CWD, -1); if ((na = read_det(&p->pst_fid_cdir, p->pst_hi_fileid_cdir, p->pst_lo_fileid_cdir, p->pst_hi_nodeid_cdir, p->pst_lo_nodeid_cdir, &pd))) (void) process_finfo(&pd, &p->pst_fid_cdir, &p->pst_cdir, na); else { (void) snpf(Namech, Namechl, "can't read %s pst_filedetails%s%s", CWD, errno ? ": " : "", errno ? strerror(errno) : ""); enter_nm(Namech); } if (Lf->sf) link_lfile(); } /* * Save root directory information. */ if (!ckscko && rtds && IS_PSFILEID(&p->pst_rdir) && (p->pst_rdir.psf_fileid > 0) ) { if (HvRtPsfid < 0) (void) scanmnttab(); if (!HvRtPsfid || memcmp((void *)&RtPsfid, (void *)&p->pst_rdir, sizeof(RtPsfid))) { alloc_lfile(RTD, -1); if ((na = read_det(&p->pst_fid_rdir, p->pst_hi_fileid_rdir, p->pst_lo_fileid_rdir, p->pst_hi_nodeid_rdir, p->pst_lo_nodeid_rdir, &pd))) (void) process_finfo(&pd, &p->pst_fid_rdir, &p->pst_rdir, na); else { (void) snpf(Namech, Namechl, "can't read %s pst_filedetails%s%s", RTD, errno ? ": " : "", errno ? strerror(errno) : ""); enter_nm(Namech); } if (Lf->sf) link_lfile(); } } /* * Print information on the text files. */ if (!ckscko) (void) process_text(p); /* * Loop through user's files. */ for (j = 0, f = read_files(p, &nf); j < nf; j++, f++) { fd = (int)f->psf_fd; /* * Check FD status and allocate local file space, as required. */ if (Fand && Fdl && fds) { /* * Check and update the FD status array. */ if (fd >= fdsa) { for (l = fdsa; l <= fd; l += FDS_ALLOC_INCR) ; nb = (MALLOC_S)(l * sizeof(int)); if (!(fds = (int *)realloc((MALLOC_P *)fds, nb))) { (void) fprintf(stderr, "%s: can't reallocate %d FD status entries\n", Pn, l); Exit(1); } while (fdsa < l) { fds[fdsa] = (ck_fd_status(NULL, fdsa) == 2) ? 1 : 0; fdsa++; } } if (!fds[fd]) continue; } alloc_lfile(NULL, (int)f->psf_fd); /* * Construct access code. */ if ((flag = (long)(f->psf_flag & ~PS_FEXCLOS)) == (long)PS_FRDONLY) Lf->access = 'r'; else if (flag == (long)PS_FWRONLY) Lf->access = 'w'; else Lf->access = 'u'; #if defined(HASFSTRUCT) /* * Save file structure values. */ if (Fsv & FSV_CT) { Lf->fct = (long)f->psf_count; Lf->fsv |= FSV_CT; } if (Fsv & FSV_FA) { ka = (((KA_T)(f->psf_hi_fileid & 0xffffffff) << 32) | (KA_T)(f->psf_lo_fileid & 0xffffffff)); if ((Lf->fsa = ka)) Lf->fsv |= FSV_FA; } if (Fsv & FSV_FG) { Lf->ffg = flag; Lf->fsv |= FSV_FG; } Lf->pof = (long)(f->psf_flag & PS_FEXCLOS); #endif /* defined(HASFSTRUCT) */ /* * Save file offset. _PSTAT64 should alwaus be defined, but just * to be safe, check for it. */ #if defined(_PSTAT64) Lf->off = (SZOFFTYPE)f->_PSF_OFFSET64; #else /* !defined(_PSTAT64) */ Lf->off = (SZOFFTYPE)f->psf_offset; #endif /* defined(_PSTAT64) */ /* * Process the file by its type. */ switch (f->psf_ftype) { case PS_TYPE_VNODE: if (ckscko || Selinet) break; if ((na = read_det(&f->psf_fid, f->psf_hi_fileid, f->psf_lo_fileid, f->psf_hi_nodeid, f->psf_lo_nodeid, &pd))) (void) process_finfo(&pd, &f->psf_fid, &f->psf_id, na); else { (void) snpf(Namech, Namechl, "can't read pst_filedetails%s%s", errno ? ": " : "", errno ? strerror(errno) : ""); enter_nm(Namech); } break; case PS_TYPE_SOCKET: switch (f->psf_subtype) { case PS_SUBTYPE_SOCK: (void) process_socket(f, (struct pst_socket *)NULL); break; case PS_SUBTYPE_SOCKSTR: if ((s = read_sock(f))) (void) process_socket(f, s); else (void) process_stream(f, (int)ckscko); break; default: (void) snpf(Namech, Namechl, "unknown socket sub-type: %d", (int)f->psf_subtype); enter_nm(Namech); } break; case PS_TYPE_STREAMS: (void) process_stream(f, (int)ckscko); break; case PS_TYPE_UNKNOWN: (void) snpf(Lf->type, sizeof(Lf->type), "UNKN"); (void) enter_nm("no more information"); break; case PS_TYPE_UNSP: (void) snpf(Lf->type, sizeof(Lf->type), "UNSP"); (void) enter_nm("no more information"); break; case PS_TYPE_LLA: (void) snpf(Lf->type, sizeof(Lf->type), "LLA"); (void) enter_nm("no more information"); break; } if (Lf->sf) link_lfile(); } /* * Examine results. */ if (examine_lproc()) return; } } /* * get_kernel_access() -- access the required information in the kernel */ static void get_kernel_access() { int err = 0; int i; struct pst_static pst; _T_LONG_T *szp; /* * Check the kernel version. */ (void) ckkv("HP-UX", LSOF_VSTR, (char *)NULL, (char *)NULL); /* * Check PSTAT support. First make sure we can read pst_static up through * its pst_static_size member. If not, quit. If we can, read the full * pst_static structure. */ if (pstat_getstatic(&pst, (size_t)INCLMEM(pst_static, pst_static_size), 1, 0) != 1) { (void) fprintf(stderr, "%s: FATAL: can't determine PSTAT static size: %s\n", Pn, strerror(errno)); Exit(1); } if (pstat_getstatic(&pst, (size_t)pst.pst_static_size, 1, 0) != 1) { (void) fprintf(stderr, "%s: FATAL: can't read %ld bytes of pst_static\n", Pn, (long)pst.pst_static_size); Exit(1); } /* * Check all the pst_static members defined in PstatCk[]. */ for (i = 0; i < NPSTATCK; i++) { if (pst.pst_static_size < PstatCk[i].msz) { (void) fprintf(stderr, "%s: FATAL: pst_static doesn't contain %s_size\n", Pn, PstatCk[i].sn); err = 1; continue; } szp = (_T_LONG_T *)(((char *)&pst) + PstatCk[i].moff); if (*szp < PstatCk[i].ssz) { (void) fprintf(stderr, "%s: FATAL: %s_size should be: %llu; is %llu\n", Pn, PstatCk[i].sn, (unsigned long long)PstatCk[i].ssz, (unsigned long long)*szp); err = 1; } } /* * Save the clone major device number, if pst_static is big enough to hold it. */ if (pst.pst_static_size >= (size_t)INCLMEM(pst_static, clonemajor)) { CloneMaj = pst.clonemajor; HaveCloneMaj = 1; } if (!err) return; Exit(1); } /* * initialize() -- perform all initialization */ void initialize() { get_kernel_access(); } /* * process_text() -- process text access information */ static void process_text(p) struct pst_status *p; /* pst_status for process */ { int i, j, nr, ntvu; int meme = 0; static int mems = -1; KA_T na; MALLOC_S nb; static int ntva; struct pst_vm_status *rp; static int txts = -1; struct txtvm { char *fd; struct pst_fid opfid; struct psfileid psfid; KA_T na; struct pst_filedetails pd; }; static struct txtvm *tv = (struct txtvm *)NULL; /* * Get and remember "mem" and "txt" FD statuses. */ if (mems < 0) { if (Fand && Fdl) mems = (ck_fd_status("mem", -1) == 2) ? 1 : 0; else mems = 1; } if (txts < 0) { if (Fand && Fdl) txts = (ck_fd_status("txt", -1) == 2) ? 1 : 0; else txts = 1; } if (!mems && !txts) return; /* * Pre-allocate sufficient tv[] space for text file. */ if (!tv) { ntva = TXTVMINCR; nb = (MALLOC_S)(ntva * sizeof(struct txtvm)); if (!(tv = (struct txtvm *)malloc(nb))) { no_txtvm_space: (void) fprintf(stderr, "%s: no memory for text and VM info array; PID: %d\n", Pn, (int)p->pst_pid); Exit(1); } } /* * Enter text file in tv[], if possible. */ if (txts && IS_PSFILEID(&p->pst_text) && (p->pst_text.psf_fileid > 0)) { if ((na = read_det(&p->pst_fid_text, p->pst_hi_fileid_text, p->pst_lo_fileid_text, p->pst_hi_nodeid_text, p->pst_lo_nodeid_text, &tv[0].pd))) { tv[0].fd = "txt"; tv[0].na = na; tv[0].opfid = p->pst_fid_text; tv[0].psfid = p->pst_text; ntvu = 1; } else { alloc_lfile("txt", -1); (void) snpf(Namech, Namechl, "can't read txt pst_filedetails%s%s", errno ? ": " : "", errno ? strerror(errno) : ""); enter_nm(Namech); if (Lf->sf) link_lfile(); ntvu = 0; } } else ntvu = 0; /* * Get unique VM regions. */ if (mems) { for (i = 0, rp = read_vmreg(p, &nr); (i < nr); i++, rp++) { /* * Skip duplicate regions. */ for (j = 0; j < ntvu; j++) { if (memcmp((void *)&rp->pst_id, (void *)&tv[j].psfid, sizeof(struct psfileid)) == 0) break; } if (j < ntvu) continue; /* * Make sure there's tv[] space for this region. */ if (ntvu >= ntva) { ntva += TXTVMINCR; nb = (MALLOC_S)(ntva * sizeof(struct txtvm)); if (!(tv = (struct txtvm *)realloc((MALLOC_P *)tv, nb))) goto no_txtvm_space; } /* * See if we can read the file details for this region. */ if ((na = read_det(&rp->pst_fid, rp->pst_hi_fileid, rp->pst_lo_fileid, rp->pst_hi_nodeid, rp->pst_lo_nodeid, &tv[ntvu].pd))) { tv[ntvu].fd = "mem"; tv[ntvu].na = na; tv[ntvu].opfid = rp->pst_fid; tv[ntvu].psfid = rp->pst_id; ntvu++; } else if (!meme) { alloc_lfile("mem", -1); (void) snpf(Namech, Namechl, "can't read mem pst_filedetails%s%s", errno ? ": " : "", errno ? strerror(errno) : ""); enter_nm(Namech); if (Lf->sf) link_lfile(); meme = 1; } } } /* * Process information for unique regions. */ for (i = 0; i < ntvu; i++) { alloc_lfile(tv[i].fd, -1); (void) process_finfo(&tv[i].pd, &tv[i].opfid, &tv[i].psfid, tv[i].na); if (Lf->sf) link_lfile(); } } /* * read_det() -- read the pst_filedetails structure */ KA_T read_det(ki, hf, lf, hn, ln, pd) struct pst_fid *ki; /* kernel file ID */ uint32_t hf; /* high file ID bits */ uint32_t lf; /* low file ID bits */ uint32_t hn; /* high node ID bits */ uint32_t ln; /* low node ID bits */ struct pst_filedetails *pd; /* details receiver */ { KA_T na; errno = 0; na = (KA_T)(((KA_T)(hn & 0xffffffff) << 32) | (KA_T)(ln & 0xffffffff)); if (pstat_getfiledetails(pd, sizeof(struct pst_filedetails), ki) <= 0 || hf != pd->psfd_hi_fileid || lf != pd->psfd_lo_fileid || hn != pd->psfd_hi_nodeid || ln != pd->psfd_lo_nodeid) return((KA_T)0); return(na); } /* * read_files() -- read the file descriptor information for a process */ static struct pst_fileinfo2 * read_files(p, n) struct pst_status *p; /* pst_status for the process */ int *n; /* returned fi[] entry count */ { size_t ec; static struct pst_fileinfo2 *fi = (struct pst_fileinfo2 *)NULL; MALLOC_S nb; int nf = 0; static int nfa = 0; int rc; static size_t sz = sizeof(struct pst_fileinfo2); /* * Read the pst_fileinfo2 information for all files of the process * into fi[]. */ do { if (nf >= nfa) { /* * Increase the size of fi[]. */ nfa += FINFOINCR; nb = (MALLOC_S)(nfa * sizeof(struct pst_fileinfo2)); if (!fi) fi = (struct pst_fileinfo2 *)malloc(nb); else fi = (struct pst_fileinfo2 *)realloc((MALLOC_P *)fi, nb); if (!fi) { (void) fprintf(stderr, "%s: can't allocate %d bytes for pst_filinfo\n", Pn, nb); Exit(1); } } /* * Read the next block of pst_fileinfo2 structures. */ ec = (size_t)(nfa - nf); if ((rc = pstat_getfile2(fi + nf, sz, ec, nf, p->pst_pid)) > 0) { nf += rc; if (rc < (int)ec) rc = 0; } } while (rc > 0); *n = nf; return(fi); } /* * read_proc() -- read process table status information */ static struct pst_status * read_proc(n) int *n; /* returned ps[] entry count */ { size_t el; int i = 0; MALLOC_S nb; int np = 0; static int npa = 0; static struct pst_status *ps = (struct pst_status *)NULL; int rc; size_t sz = sizeof(struct pst_status); /* * Read the pst_status information for all processes into ps[]. */ do { if (np >= npa) { /* * Increase the size of ps[]. */ npa += PSTATINCR; nb = (MALLOC_S)(npa * sizeof(struct pst_status)); if (!ps) ps = (struct pst_status *)malloc(nb); else ps = (struct pst_status *)realloc((MALLOC_P *)ps, nb); if (!ps) { ps_alloc_error: (void) fprintf(stderr, "%s: can't allocate %d bytes for pst_status table\n", Pn, nb); Exit(1); } } /* * Read the next block of pst_status structures. */ el = (size_t)(npa - np); if ((rc = pstat_getproc(ps + np, sz, el, i)) > 0) { np += rc; i = (ps + np - 1)->pst_idx + 1; if (rc < el) rc = 0; } } while (rc > 0); /* * Reduce ps[] to a minimum, unless repeat mode is in effect. */ if (!RptTm && ps && np && (np < npa)) { nb = (MALLOC_S)(np * sizeof(struct pst_status)); if (!(ps = (struct pst_status *)realloc((MALLOC_P *)ps, nb))) goto ps_alloc_error; } *n = np; return(ps); } /* * read_vmreg() -- read info about the VM regions of a process */ static struct pst_vm_status * read_vmreg(p, n) struct pst_status *p; /* pst_status for process */ int *n; /* returned region count */ { size_t ec = (size_t)p->pst_pid; MALLOC_S nb; int nr, rx; static int nra = 0; struct pst_vm_status *rp; static struct pst_vm_status *reg = (struct pst_vm_status *)NULL; size_t sz = sizeof(struct pst_vm_status); /* * Read all VM region information for the process. */ for (nr = rx = 0;; rx++) { if (nr >= nra) { /* * Increase the region table size. */ nra += VMREGINCR; nb = (MALLOC_S)(nra * sizeof(struct pst_vm_status)); if (!reg) reg = (struct pst_vm_status *)malloc(nb); else reg = (struct pst_vm_status *)realloc((MALLOC_P *)reg, nb); if (!reg) { (void) fprintf(stderr, "%s: can't allocate %d bytes for pst_vm_status\n", Pn, nb); Exit(1); } } /* * Read the pst_vm_status structure for the next region. */ rp = reg + nr; if (pstat_getprocvm(rp, sz, ec, rx) != 1) break; if (IS_PSFILEID(&rp->pst_id) && (rp->pst_id.psf_fileid > 0)) nr++; } *n = nr; return(reg); } /* * scanmnttab() -- scan mount table */ extern void scanmnttab() { struct mounts *mp; /* * Scan the mount table to identify NFS file systems and form the psfileid * for "/". * * This function allows the mount table scan to be deferred until its * information is needed. */ if ((HvRtPsfid >= 0) && (HasNFS >= 0)) return; (void) memset((void *)&RtPsfid, 0, sizeof(RtPsfid)); for (HasNFS = HvRtPsfid = 0, mp = readmnt(); mp; mp = mp->next) { if (mp->MOUNTS_FSTYPE && (strcmp(mp->MOUNTS_FSTYPE, MNTTYPE_NFS) == 0 || strcmp(mp->MOUNTS_FSTYPE, MNTTYPE_NFS3) == 0)) { HasNFS = 1; mp->is_nfs = 1; } else mp->is_nfs = 0; if (!HvRtPsfid && !strcmp(mp->dir, "/")) { HvRtPsfid = 1; RtPsfid.psf_fsid.psfs_id = mp->dev; RtPsfid.psf_fsid.psfs_type = mp->MOUNTS_STAT_FSTYPE; RtPsfid.psf_fileid = mp->inode; } } } lsof-4.86+dfsg.orig/dialects/hpux/pstat/dproto.h0000444000175000017500000000407211077400263022046 0ustar nicholasnicholas/* * dproto.h - pstat-based HP-UX function prototypes for lsof * * The _PROTOTYPE macro is defined in the common proto.h. */ /* * Copyright 1999 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: dproto.h,v 1.5 2008/10/21 16:17:50 abe Exp $ */ _PROTOTYPE(extern int get_max_fd,(void)); _PROTOTYPE(extern int is_file_named,(char *p, int cd)); _PROTOTYPE(extern void process_finfo,(struct pst_filedetails *pd, struct pst_fid *opfid, struct psfileid *psfid, KA_T na)); _PROTOTYPE(extern void process_socket,(struct pst_fileinfo2 *f, struct pst_socket *s)); _PROTOTYPE(extern void process_stream,(struct pst_fileinfo2 *f, int ckscko)); _PROTOTYPE(extern KA_T read_det,(struct pst_fid *ki, uint32_t hf, uint32_t lf, uint32_t hn, uint32_t ln, struct pst_filedetails *pd)); _PROTOTYPE(extern struct pst_socket *read_sock,(struct pst_fileinfo2 *f)); #if defined(HASIPv6) _PROTOTYPE(extern struct hostent *gethostbyname2,(char *nm, int proto)); #endif /* defined(HASIPv6) */ #if defined(HASVXFS) _PROTOTYPE(extern int read_vxnode,(struct vnode *v, struct l_vfs *vfs, dev_t *dev)); #endif /* defined(HASVXFS) */ _PROTOTYPE(extern void scanmnttab,(void)); lsof-4.86+dfsg.orig/dialects/hpux/pstat/dlsof.h0000444000175000017500000001251411077400261021644 0ustar nicholasnicholas/* * 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 #include #include #include #include #include #include #include #include # if defined(HASIPv6) #include # endif /* defined(HASIPv6) */ #include #include #include #include #include #include #include # 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 # 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 #include /* * This definition is needed for the common function prototype definitions * in "proto.h". The /proc-based lsof also uses it to make sure its * manufactured node ID number has 64 bits. */ typedef unsigned long long KA_T; #define KA_T_FMT_X "%#llx" /* * Local definitions */ # if defined(HAS_CONST) #define COMP_P const void # else /* !defined(HAS_CONST) */ #define COMP_P void # endif /* defined(HAS_CONST) */ #define DEVINCR 1024 /* device table malloc() increment */ #define MALLOC_P void #define FREE_P void #define MALLOC_S unsigned #define MOUNTED MNT_MNTTAB #define QSORT_P void #define READLEN_T int #define STRNCPY_L size_t #define SZOFFTYPE unsigned long long #define SZOFFPSPEC "ll" /* SZOFFTYPE printf specification modifier */ #define XDR_PMAPLIST (xdrproc_t)xdr_pmaplist #define XDR_VOID (xdrproc_t)xdr_void /* * Local macros */ #define IS_PSFILEID(p) ((p)->psf_fsid.psfs_id || (p)->psf_fsid.psfs_type) /* is psfiled active? */ /* * Global storage definitions (including their structure definitions) */ extern _T_LONG_T CloneMaj; /* clone major device number */ extern int HaveCloneMaj; /* clone major status */ struct mounts { char *dir; /* directory (mounted on) */ char *fsname; /* file system * (symbolic links unresolved) */ char *fsnmres; /* file system * (symbolic links resolved) */ char *mnt_fstype; /* file system type -- e.g., * MNTTYPE_NFS */ int stat_fstype; /* st_fstype */ dev_t dev; /* directory st_dev */ dev_t rdev; /* directory st_rdev */ INODETYPE inode; /* directory st_ino */ mode_t mode; /* directory st_mode */ mode_t fs_mode; /* file system st_mode */ u_char is_nfs; /* file system type is MNTTYPE_NFS or * MNTTYPE_NFS3 */ struct mounts *next; /* forward link */ }; struct sfile { char *aname; /* argument file name */ char *name; /* file name (after readlink()) */ char *devnm; /* device name (optional) */ dev_t dev; /* device */ dev_t rdev; /* raw device */ u_short mode; /* S_IFMT mode bits from stat() */ int type; /* file type: 0 = file system * 1 = regular file */ INODETYPE i; /* inode number */ int f; /* file found flag */ struct sfile *next; /* forward link */ }; extern char **Fsinfo; extern int Fsinfomax; extern int HasNFS; /* * Definitions for dvch.c, isfn.c, and rdev.c */ #define CLONEMAJ CloneMaj /* clone major variable name */ #define DIRTYPE dirent #define HASDNAMLEN 1 /* DIRTYPE has d_namlen element */ #define HAS_STD_CLONE 1 /* uses standard clone structure */ #define HAVECLONEMAJ HaveCloneMaj /* clone major status variable name */ #define MAXSYSCMDL (PST_UCOMMLEN - 1) /* max system command name length */ /* * Definition for rmnt.c */ #define MNTSKIP \ { if (strcmp(mp->mnt_type, MNTTYPE_IGNORE) == 0) \ continue; } #define RMNT_FSTYPE mnt_type #define MOUNTS_FSTYPE mnt_fstype # if defined(HASFSTYPE) && HASFSTYPE==2 #define RMNT_STAT_FSTYPE st_fstype #define MOUNTS_STAT_FSTYPE stat_fstype # endif /* defined(HASFSTYPE) && HASFSTYPE==2 */ #endif /* HPUX_LSOF_H */ lsof-4.86+dfsg.orig/dialects/hpux/pstat/Mksrc0000555000175000017500000000104706722563115021401 0ustar nicholasnicholas#!/bin/sh # # Mksrc - make pstat-based HP-UX source files # # WARNING: This script assumes it is running from the main directory # of the lsof, version 4 distribution. # # One environment variable applies: # # LSOF_MKC is the method for creating the source files. # It defaults to "ln -s". A common alternative is "cp". # # $Id: Mksrc,v 1.1 99/05/25 13:04:50 abe Exp $ D=dialects/hpux/pstat L="dfile.c dlsof.h dfile.c dproc.c dproto.h dsock.c dstore.c machine.h" for i in $L do rm -f $i $LSOF_MKC $D/$i $i echo "$LSOF_MKC $D/$i $i" done lsof-4.86+dfsg.orig/dialects/hpux/pstat/dfile.c0000444000175000017500000004277210564464023021632 0ustar nicholasnicholas/* * dfile.c -- pstat-based HP-UX file functions for lsof */ /* * Copyright 1999 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1999 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id"; #endif #include "lsof.h" #if defined(HASNCACHE) /* * Local definitions */ #define DNLCINCR 2048 /* DNLC read increment */ #define NFSIDH 256 /* file system ID hash count * -- MUST BE A POWER OF TWO!!! */ #define NFSID sizeof(struct psfsid) /* size of psfsid structure */ #define NL_NC sizeof(struct l_nc) /* size of l_nc structure */ #define NPSTM sizeof(struct pst_mpathnode) /* size of pst_mpathnode */ /* * Local structure definitions */ struct l_nc { /* local name cache */ struct psfileid id; /* node's PSTAT ID */ struct psfileid par; /* parent's PSTAT ID */ struct l_nc *pl; /* local parent name cache entry -- * NULL if not found or not yet * accessed (see pls) */ int pls; /* status of pl: 0 = not accessed * 1 = accessed */ int nl; /* name length */ char *nm; /* name */ struct l_nc *next; /* next hash bucket link */ }; struct l_fic { /* file system ID cache */ struct psfsid fsid; /* file system ID */ int nc; /* files cached for file system */ struct l_fic *next; /* next hash bucket link */ }; /* * Local static variables */ static int Nceh; /* number of Nchash entries allocated */ static struct l_nc **Nchash = (struct l_nc **)NULL; /* the name cache hash buckets */ static int Ncmask; /* power of two mask for the name * cache -- sized from Nc */ static int Ndnlc; /* number of DNLC entries via * pst_dynamic.psd_dnlc_size */ static struct l_fic **Ncfsid = (struct l_fic **)NULL; /* the file system hash buckets */ static struct pst_fid Nzpf; /* zeroed pst_fid (for memcmp()) */ static struct psfileid Nzps; /* zeroed psfilid (for memcmp()) */ static int Nzpfs = 0; /* Nzpf status: 1 = zeroed */ static int Nzpss = 0; /* Nzps status: 1 = zeroed */ /* * Local macros */ #define HASHFSID(i) (Ncfsid + \ (((int)(((((struct psfsid *)i)->psfs_id * 31415) << 3)&0xfffffff) \ + (int)((((((struct psfsid *)i)->psfs_type * 31415) << 5)&0xfffffff))) \ & (NFSIDH - 1))) #define HASHPSFILEID(p) (Nchash + \ (((int)(((int)((((struct psfileid *)p)->psf_fsid.psfs_id * 31415) << 3)\ & 0xfffffff) \ + (int)(((((struct psfileid *)p)->psf_fsid.psfs_type * 31415) << 5) \ & 0xfffffff) \ + (int)(((((struct psfileid *)p)->psf_fileid * 31415) << 7) \ & 0xfffffff))) \ & Ncmask)) /* * Local function prototypes */ _PROTOTYPE(static struct l_nc *ncache_addr,(struct psfileid *ps)); _PROTOTYPE(static void ncache_free,(void)); _PROTOTYPE(static int ncache_isroot,(struct psfileid *ps)); _PROTOTYPE(static void ncache_size,(void)); #endif /* defined(HASNCACHE) */ #if defined(HASIPv6) /* * gethostbyname2() -- an RFC2133-compatible get-host-by-name-two function * to get AF_INET and AF_INET6 addresses from host names, * using the gethostbyname() and RFC2553-compatible * getipnodebyname() functions */ extern struct hostent * gethostbyname2(nm, prot) char *nm; /* host name */ int prot; /* protocol -- AF_INET or AF_INET6 */ { int err; if (prot == AF_INET) { /* * This shouldn't be necessary if /etc/nsswitch.conf is correct, but * it's a good fail-safe in case /etc/nsswitch.conf is missing or * incorrect. */ return(gethostbyname(nm)); } return(getipnodebyname(nm, prot, 0, &err)); } #endif /* defined(HASIPv6) */ /* * get_max_fd() -- get maximum file descriptor plus one */ int get_max_fd() { struct rlimit r; if (getrlimit(RLIMIT_NOFILE, &r)) return(-1); return(r.rlim_cur); } #if defined(HASNCACHE) /* * ncache_addr() -- get ncache entry address */ static struct l_nc * ncache_addr(ps) struct psfileid *ps; /* parent's psfileid */ { struct l_nc **hp, *lc; for (hp = HASHPSFILEID(ps), lc = *hp; lc; lc = lc->next) { if (!memcmp((void *)ps, (void *)&lc->id, sizeof(struct psfileid))) return(lc); } return((struct l_nc *)NULL); } /* * ncache_alloc() -- allocate name cache space */ static void ncache_alloc() { if (Nchash || Ncfsid) ncache_free(); (void) ncache_size(); if (!(Nchash = (struct l_nc **)calloc(Nceh, sizeof(struct l_nc *)))) { (void) fprintf(stderr, "%s: can't allocate %d local name cache entries\n", Pn, Nceh); Exit(1); } if (Ncfsid) return; if (!(Ncfsid = (struct l_fic **)calloc(NFSIDH, sizeof(struct l_fic *)))) { (void) fprintf(stderr, "%s: can't allocate %d local file system cache entries\n", Pn, NFSIDH); Exit(1); } } /* * ncache_free() -- free previous ncache allocations */ static void ncache_free() { int i; struct l_fic **fh, *fp, *fx; struct l_nc **nh, *np, *nx; if (Ncfsid) { /* * Free file system ID hash bucket contents. */ for (fh = Ncfsid, i = 0; i < NFSIDH; fh++, i++) { for (fp = *fh; fp; fp = fx) { fx = fp->next; (void) free((MALLOC_P *)fp); } Ncfsid[i] = (struct l_fic *)NULL; } } if (Nchash) { /* * Free name cache. */ for (i = 0, nh = Nchash; i < Nceh; i++, nh++) { for (np = *nh; np; np = nx) { nx = np->next; if (np->nm) (void) free((MALLOC_P *)np->nm); (void) free((MALLOC_P *)np); } } (void) free((MALLOC_P *)Nchash); Nchash = (struct l_nc **)NULL; } } /* * ncache_isroot() -- does psfileid represent the root of a file system? */ static int ncache_isroot(ps) struct psfileid *ps; /* psfileid */ { if (!ps->psf_fsid.psfs_id && !ps->psf_fsid.psfs_type && ps->psf_fileid == -1) return(1); # if defined(HASFSINO) if (!Lf->fs_ino || (Lf->inp_ty != 1) || !Lf->dev_def) return(0); if ((Lf->dev == (dev_t)ps->psf_fsid.psfs_id) && (Lf->fs_ino == (unsigned long)ps->psf_fileid)) return(1); # endif /* defined(HASFSINO) */ return(0); } /* * ncache_load() -- load name cache */ void ncache_load() { if (!Fncache) return; (void) ncache_alloc(); if (!Nzpfs) { (void)memset((void *)&Nzpf, 0, sizeof(Nzpf)); Nzpfs = 1; } if (!Nzpss) { (void)memset((void *)&Nzps, 0, sizeof(Nzps)); Nzpss = 1; } } /* * ncache_loadfs() -- load the name cache for a file system */ struct l_fic * ncache_loadfs(fsid, fh) struct psfsid *fsid; /* ID of file system to add */ struct l_fic **fh; /* Ncfsid hash bucket */ { char *cp; struct l_fic *f; int i, nl, nr; struct pst_mpathnode mp[DNLCINCR]; struct l_nc **nh, *nn, *nt, *ntp; int x = 0; /* * Allocate a new file system pointer structure and link it to its bucket. */ if (!(f = (struct l_fic *)malloc(sizeof(struct l_fic)))) { (void) fprintf(stderr, "%s: no fsid structure space\n", Pn); Exit(1); } f->fsid = *fsid; f->nc = 0; f->next = *fh; *fh = f; while ((nr = pstat_getmpathname(&mp[0], NPSTM, DNLCINCR, x, fsid)) > 0) { x = mp[nr - 1].psr_idx + 1; for (i = 0; i < nr; i++) { /* * Ignore NUL names, ".", and "..". */ if (!(nl = (int)strlen(mp[i].psr_name))) continue; if ((nl < 3) && (mp[i].psr_name[0] == '.')) { if ((nl == 1) || (mp[i].psr_name[1] == '.')) continue; } /* * Allocate name and name cache structure space. */ if (!(cp = (char *)malloc((MALLOC_S)(nl + 1)))) { (void) fprintf(stderr, "%s: no name entry space (%d) for:%s\n", Pn, nl + 1, mp[i].psr_name); Exit(1); } if (!(nn = (struct l_nc *)malloc(sizeof(struct l_nc)))) { (void) fprintf(stderr, "%s: no name cache entry space (%d) for: %s\n", Pn, (int)sizeof(struct l_nc), mp[i].psr_name); Exit(1); } /* * Fill in name cache entry, complete with name and name length. */ (void) snpf(cp, nl + 1, "%s", mp[i].psr_name); nn->id = mp[i].psr_file; nn->par = mp[i].psr_parent; nn->nm = cp; nn->nl = nl; nn->pl = nn->next = (struct l_nc *)NULL; nn->pls = 0; nh = HASHPSFILEID(&mp[i].psr_file); /* * Skip to the end of the hash bucket chain, looking for * duplicates along the way. */ for (nt = *nh, ntp = (struct l_nc *)NULL; nt; ntp = nt, nt = nt->next) { if (memcmp((void *)&nt->id, (void *)&nn->id, NL_NC) == 0) break; } if (nt) { /* * Remove a duplicate. */ if (ntp) ntp = nt->next; else *nh = nt->next; (void) free((MALLOC_P *)nt->nm); (void) free((MALLOC_P *)nt); (void) free((MALLOC_P *)nn->nm); (void) free((MALLOC_P *)nn); } else { /* * Link a new entry. */ if (ntp) ntp->next = nn; else *nh = nn; f->nc++; } } if (nr < DNLCINCR) break; } return(f); } /* * ncache_lookup() -- look up a node's name in the kernel's name cache */ char * ncache_lookup(buf, blen, fp) char *buf; /* receiving name buffer */ int blen; /* receiving buffer length */ int *fp; /* full path reply */ { char *cp = buf; int ef; struct l_fic **fh, *fs; struct l_nc *lc; int nl, rlen; char *pc; *cp = '\0'; *fp = 0; # if defined(HASFSINO) /* * If the entry has an inode number that matches the inode number of the * file system mount point, return an empty path reply. That tells the * caller that the already-printed system mount point name is sufficient. */ if (Lf->inp_ty == 1 && Lf->fs_ino && Lf->inode == Lf->fs_ino) return(cp); # endif /* defined(HASFSINO) */ /* * See if cache has been loaded for this pfsid. Don't try to load if cache * loading has been inhibited with -C, or unless the real or effective UID of * this process is root. */ if ((!Myuid || Setuidroot) && Fncache) { for (fh = HASHFSID(&Lf->psfid.psf_fsid), fs = *fh; fs; fs = fs->next) { if (memcmp((void *)&fs->fsid, (void *)&Lf->psfid.psf_fsid, NFSID) == 0) break; } if (!fs) fs = ncache_loadfs(&Lf->psfid.psf_fsid, fh); } else fs = (struct l_fic *)NULL; /* * Search the cache for an entry whose psfileid matches. */ if (!fs || !fs->nc || !(lc = ncache_addr(&Lf->psfid))) { /* * If the node has no cache entry, see if it's the root of the file * system. */ # if defined(HASFSINO) if (Lf->fs_ino && (Lf->inp_ty == 1) && (Lf->fs_ino == Lf->inode)) return(cp); # endif /* defined(HASFSINO) */ /* * If the file system's cache couldn't be loaded -- e.g., this lsof * process lacks permission to load it or cache lookup is inhibited * with -C -- but the UID of the file's process matches the UID of the * lsof process, see if it's possible to read the single path name for * this particular file. (The file must have a non-zero opaque ID.) */ if (!fs) { if (Fncache && (Myuid == Lp->uid) && memcmp((void *)&Lf->opfid, (void *)&Nzpf, sizeof(Nzpf)) && (nl = pstat_getpathname(buf, (blen - 1), &Lf->opfid)) > 0) { buf[nl] = '\0'; if (*buf == '/') *fp = 1; return(buf); } } return((char *)NULL); } if (ncache_isroot(&lc->id)) { /* * If the node is the root of the file system, return a response * that will cause the root directory to be displayed. */ return(cp); } /* * Start the path assembly. */ if ((nl = lc->nl) > (blen - 1)) return((char *)NULL); cp = buf + blen - nl - 1; rlen = blen - nl - 1; (void) snpf(cp, nl + 1, "%s", lc->nm); /* * Look up the name cache entries that are parents of the node address. * Quit when: * * there's no parent; * the file system root is reached; * the name length is too large to fit in the receiving buffer. */ for (ef = 0; !ef;) { if (!lc->pl) { if (!lc->pls) { /* * If there is a parent, look up its Ncache address; * otherwise quit on an incomplete path assembly. */ if (memcmp((void *)&lc->par, (void *)&Nzps, sizeof(Nzps))) { lc->pl = ncache_addr(&lc->par); lc->pls = 1; } else break; } } if (ncache_isroot(&lc->par)) { /* * If the parent entry is the file system root, enter the file * system root directory, and indicate that the assembly should * stop after this entry. */ if (!(pc = Lf->fsdir)) break; nl = (int)strlen(pc); ef = 1; } else { /* * Use the parent link if it exists; otherwise exit on an * incomplete path assembly. */ if (!(lc = lc->pl)) break; pc = lc->nm; nl = lc->nl; } /* * Prefix the next path component. Intersperse a '/' if the * component doesn't end in one. */ if (!nl) break; if (pc[nl - 1] != '/') { if (1 > rlen) break; *(cp - 1) = '/'; cp--; rlen--; } if (nl > rlen) break; (void) strncpy((cp - nl), pc, nl); cp -= nl; rlen -= nl; if (ef) { /* * If the file system root directory was just prefixed, return * a full-path indication. */ *fp = 1; break; } } return(cp); } /* * ncache_size() -- get DNLC size */ static void ncache_size() { struct pst_dynamic pd; if (pstat_getdynamic(&pd, sizeof(pd), 1, 0) != 1) { (void) fprintf(stderr, "%s: can't get dynamic status\n", Pn); Exit(1); } Ndnlc = (int)pd.psd_dnlc_size; for (Nceh = 1; Nceh < (Ndnlc + Ndnlc); Nceh <<= 1) ; Ncmask = Nceh - 1; } #endif /* defined(HASNCACHE) */ /* * print_dev() -- print device */ char * print_dev(lf, dev) struct lfile *lf; /* file whose device is to be printed */ dev_t *dev; /* device to be printed */ { static char buf[128]; (void) snpf(buf, sizeof(buf), "%d,%#x", GET_MAJ_DEV(*dev), GET_MIN_DEV(*dev)); return(buf); } /* * process_finfo() -- process file information */ void process_finfo(pd, opfid, psfid, na) struct pst_filedetails *pd; /* file details */ struct pst_fid *opfid; /* opaque file ID for this file */ struct psfileid *psfid; /* PSTAT file ID for this file */ KA_T na; /* node address */ { char *cp, buf[32]; dev_t dev; int devs = 0; int32_t lk; struct mounts *mp; /* * Save file IDs for later use in name lookup. */ Lf->opfid = *opfid; Lf->psfid = *psfid; #if defined(HASFSTRUCT) /* * Save node ID. */ if (na && (Fsv & FSV_NI)) { Lf->fna = na; Lf->fsv |= FSV_NI; } #endif /* defined(HASFSTRUCT) */ /* * Construct lock code. */ if ((lk = pd->psfd_lckflag) & PS_FPARTRDLCK) Lf->lock = 'r'; else if (lk & PS_FPARTWRLCK) Lf->lock = 'w'; else if (lk & PS_FFULLRDLCK) Lf->lock = 'R'; else if (lk & PS_FFULLWRLCK) Lf->lock = 'W'; else Lf->lock = ' '; /* * Derive type from modes. */ switch ((int)(pd->psfd_mode & PS_IFMT)) { case PS_IFREG: cp = "REG"; Ntype = N_REGLR; break; case PS_IFBLK: cp = "BLK"; Ntype = N_BLK; break; case PS_IFDIR: cp = "DIR"; Ntype = N_REGLR; break; case PS_IFCHR: cp = "CHR"; Ntype = N_CHR; break; case PS_IFIFO: cp = "FIFO"; Ntype = N_FIFO; break; default: (void) snpf(buf, sizeof(buf), "%04o", (unsigned int)(((pd->psfd_mode & PS_IFMT) >> 12) & 0xfff)); cp = buf; Ntype = N_REGLR; } if (!Lf->type[0]) (void) snpf(Lf->type, sizeof(Lf->type), "%s", cp); Lf->ntype = Ntype; /* * Save device number. */ switch (Ntype) { case N_FIFO: (void) enter_dev_ch(print_kptr(na, (char *)NULL, 0)); break; default: dev = Lf->dev = (dev_t)pd->psfd_dev; devs = Lf->dev_def = 1; if ((Ntype == N_CHR) || (Ntype == N_BLK)) { Lf->rdev = (dev_t)pd->psfd_rdev; Lf->rdev_def = 1; } } /* * Save node number. */ Lf->inode = (INODETYPE)pd->psfd_ino; Lf->inp_ty = 1; /* * Save link count. */ if (Fnlink) { /* * Ignore a zero link count only if the file is a FIFO. */ if ((Lf->nlink = (long)pd->psfd_nlink) || (Ntype != N_FIFO)) Lf->nlink_def = 1; if (Lf->nlink_def && Nlink && (Lf->nlink < Nlink)) Lf->sf |= SELNLINK; } /* * Save file system identity. */ if (devs) { for (mp = readmnt(); mp; mp = mp->next) { if (dev == mp->dev) { Lf->fsdir = mp->dir; Lf->fsdev = mp->fsname; #if defined(HASFSINO) Lf->fs_ino = (unsigned long)mp->inode; #endif /* defined(HASFSINO) */ break; } } } else mp = (struct mounts *)NULL; /* * If no offset has been activated and no size saved, activate the offset or * save the size. */ if (!Lf->off_def && !Lf->sz_def) { if (Foffset) Lf->off_def = 1; else { switch (Ntype) { case N_CHR: case N_FIFO: Lf->off_def = 1; break; default: Lf->sz = (SZOFFTYPE)pd->psfd_size; Lf->sz_def = 1; } } } /* * See if this is an NFS file. */ if (Fnfs) { if (HasNFS < 0) (void) scanmnttab(); if (HasNFS && mp && mp->is_nfs) Lf->sf |= SELNFS; } /* * Test for specified file. */ if (Sfile && is_file_named(NULL, ((Ntype == N_CHR) || (Ntype == N_BLK) ? 1 : 0))) Lf->sf |= SELNM; /* * Enter name characters. */ if (!Lf->nm && Namech[0]) enter_nm(Namech); } lsof-4.86+dfsg.orig/dialects/hpux/pstat/machine.h0000444000175000017500000004164211424323103022140 0ustar nicholasnicholas/* * 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 # 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 # 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 option. */ /* #define HASAOPT 1 */ /* * HASBLKDEV is defined for those dialects that want block device information * recorded in BDevtp[]. */ #define HASBLKDEV 1 /* * HASCDRNODE is defined for those dialects that have CD-ROM nodes. */ /* #define HASCDRNODE 1 */ /* * HASDCACHE is defined for those dialects that support a device cache * file. * * HASENVDC defined the name of an environment variable that contains the * device cache file path. The HASENVDC environment variable is ignored when * the lsof process is setuid(root) or its real UID is 0. * * HASPERSDC defines the format for the last component of a personal device * cache file path. The first will be the home directory of the real UID that * executes lsof. * * HASPERSDCPATH defines the environment variable whose value is the middle * component of the personal device cache file path. The middle component * follows the home directory and precedes the results of applying HASPERSDC. * The HASPERSDCPATH environment variable is ignored when the lsof process is * setuid(root) or its real UID is 0. * * HASSYSDC defines a public device cache file path. When it's defined, it's * used as the path from which to read the device cache. * * Consult the 00DCACHE and 00FAQ files of the lsof distribution for more * information on device cache file path construction. */ #define HASDCACHE 1 #define HASENVDC "LSOFDEVCACHE" #define HASPERSDC "%h/%p.lsof_%L" #define HASPERSDCPATH "LSOFPERSDCPATH" /* #define HASSYSDC "/your/choice/of/path" */ /* * HASFIFONODE is defined for those dialects that have FIFO nodes. */ /* #define HASFIFONODE 1 */ /* * HASFSINO is defined for those dialects that have the file system * inode element, fs_ino, in the lfile structure definition in lsof.h. */ #define HASFSINO 1 /* * HASFSTRUCT is defined if the dialect has a file structure. * * FSV_DEFAULT defines the default set of file structure values to list. * It defaults to zero (0), but may be made up of a combination of the * FSV_* symbols from lsof.h. * * HASNOFSADDR -- has no file structure address * HASNOFSFLAGS -- has no file structure flags * HASNOFSCOUNT -- has no file structure count * HASNOFSNADDR -- has no file structure node address */ #define HASFSTRUCT 1 /* #define FSV_DEFAULT FSV_? | FSV_? | FSV_? */ /* #define HASNOFSADDR 1 has no file structure address */ /* #define HASNOFSFLAGS 1 has no file structure flags */ /* #define HASNOFSCOUNT 1 has no file structure count */ /* #define HASNOFSNADDR 1 has no file structure node address */ /* * HASGNODE is defined for those dialects that have gnodes. */ /* #define HASGNODE 1 */ /* * HASHSNODE is defined for those dialects that have High Sierra nodes. */ /* #define HASHSNODE 1 */ /* * HASINODE is defined for those dialects that have inodes and wish to * use readinode() from node.c. */ /* #define HASINODE 1 */ /* * HASINTSIGNAL is defined for those dialects whose signal function returns * an int. */ /* #define HASINTSIGNAL 1 */ /* * HASKERNIDCK is defined for those dialects that support the comparison of * the build to running kernel identity. */ #define HASKERNIDCK 1 /* * HASKOPT is defined for those dialects that support the -k option of * reading the kernel's name list from an optional file. */ /* #define HASKOPT 1 */ /* * HASLFILEADD is defined for those dialects that need additional elements * in struct lfile. The HASLFILEADD definition is a macro that defines * them. If any of the additional elements need to be preset in the * alloc_lfile() function of proc.c, the SETLFILEADD macro may be defined * to do that. * * If any additional elements need to be cleared in alloc_lfile() or in the * free_proc() function of proc.c, the CLRLFILEADD macro may be defined to * do that. Note that CLRLFILEADD takes one argument, the pointer to the * lfile struct. The CLRLFILEADD macro is expected to expand to statements * that are complete -- i.e., have terminating semi-colons -- so the macro is * called without a terminating semicolon by proc.c. * * The HASXOPT definition may be used to select the conditions under which * private lfile elements are used. */ #define HASLFILEADD struct pst_fid opfid; \ struct psfileid psfid; /* #define CLRLFILEADD(lf) (lf)->... = (type)NULL; */ #define SETLFILEADD memset((void *)&Lf->opfid, 0, sizeof(struct pst_fid)); \ memset((void *)&Lf->psfid, 0, sizeof(struct psfileid)); /* * HASMNTSTAT indicates the dialect supports the mount stat(2) result option * in its l_vfs and mounts structures. */ /* #define HASMNTSTAT 1 */ /* * HASMNTSUP is defined for those dialects that support the mount supplement * option. */ /* #define HASMNTSUP 1 */ /* * HASMOPT is defined for those dialects that support the reading of * kernel memory from an alternate file. */ /* #define HASMOPT 1 */ /* * HASNCACHE is defined for those dialects that have a kernel name cache * that lsof can search. A value of 1 directs printname() to prefix the * cache value with the file system directory name; 2, avoid the prefix. * * NCACHELDPFX is a set of C commands to execute before calling ncache_load(). * * NCACHELDSFX is a set of C commands to execute after calling ncache_load(). */ #define HASNCACHE 2 /* #define NCACHELDPFX ??? */ /* #define NCACHELDSFX ??? */ /* * HASNLIST is defined for those dialects that use nlist() to acccess * kernel symbols. */ /* #define HASNLIST 1 */ /* * HASPIPEFN is defined for those dialects that have a special function to * process DTYPE_PIPE file structure entries. Its value is the name of the * function. * * NOTE: don't forget to define a prototype for this function in dproto.h. */ /* #define HASPIPEFN process_pipe? */ /* * HASPIPENODE is defined for those dialects that have pipe nodes. */ /* #define HASPIPENODE 1 */ /* * HASPMAPENABLED is defined when the reporting of portmapper registration * info is enabled by default. */ /* #define HASPMAPENABLED 1 */ /* * HASPPID is defined for those dialects that support identification of * the parent process IDentifier (PPID) of a process. */ #define HASPPID 1 /* * HASPRINTDEV, HASPRINTINO, HASPRINTNM, HASPRINTOFF, and HASPRINTSZ * define private dialect-specific functions for printing DEVice numbers, * INOde numbers, NaMes, file OFFsets, and file SiZes. The functions are * called from print_file(). */ #define HASPRINTDEV print_dev /* #define HASPRINTINO print_ino? */ /* #define HASPRINTNM print_nm? */ /* #define HASPRINTOFF print_off? */ /* #define HASPRINTSZ print_sz? */ /* * HASPRIVFILETYPE and PRIVFILETYPE are defined for dialects that have a * file structure type that isn't defined by a DTYPE_* symbol. They are * used in lib/prfp.c to select the type's processing. * * PRIVFILETYPE is the definition of the f_type value in the file struct. * * HASPRIVFILETYPE is the name of the processing function. */ /* #define HASPRIVFILETYPE process_shmf? */ /* #define PRIVFILETYPE ?? */ /* * HASPRIVNMCACHE is defined for dialects that have a private method for * printing cached NAME column values for some files. HASPRIVNAMECACHE * is defined to be the name of the function. * * The function takes one argument, a struct lfile pointer to the file, and * returns non-zero if it prints a name to stdout. */ /* #define HASPRIVNMCACHE */ /* * 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 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 /* * 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_ is defined for dialects that use the * in the lsof library. * * Note: other definitions and operations may be required to condition the * library function source code. They may be found in the dialect dlsof.h * header files. */ #define USE_LIB_CKKV 1 /* ckkv.c */ /* #define USE_LIB_COMPLETEVFS 1 cvfs.c */ /* #define USE_LIB_FIND_CH_INO 1 fino.c */ #define USE_LIB_IS_FILE_NAMED 1 /* isfn.c */ #define USE_LIB_LKUPDEV 1 /* lkud.c */ #define USE_LIB_PRINTDEVNAME 1 /* pdvn.c */ /* #define USE_LIB_PROCESS_FILE 1 prfp.c */ /* #define USE_LIB_PRINT_TCPTPI 1 ptti.c */ /* #define USE_LIB_PRINT_TCPTPI 1 ptti.c */ #define USE_LIB_READDEV 1 /* rdev.c */ #define USE_LIB_READMNT 1 /* rmnt.c */ /* #define USE_LIB_REGEX 1 regex.c */ /* #define USE_LIB_RNAM 1 rnam.c */ /* #define USE_LIB_RNCH 1 rnch.c */ /* #define USE_LIB_RNMH 1 rnmh.c */ /* #define USE_LIB_SNPF 1 snpf.c */ #define snpf snprintf /* use the system's snprintf() */ /* * WARNDEVACCESS is defined for those dialects that should issue a warning * when lsof can't access /dev (or /device) or one of its sub-directories. * The warning can be inhibited by the lsof caller with the -w option. */ /* #define WARNDEVACCESS 1 */ /* * WARNINGSTATE is defined for those dialects that want to suppress all lsof * warning messages. */ /* #define WARNINGSTATE 1 warnings are enabled by default */ /* * WILLDROPGID is defined for those dialects whose lsof executable runs * setgid(not_real_GID) and whose setgid power can be relinquished after * the dialect's initialize() function has been executed. */ /* #define WILLDROPGID 1 */ /* * zeromem is a macro that uses bzero or memset. */ #define zeromem(a, l) memset((void *)a, 0, l) #endif /* !defined(LSOF_MACHINE_H) */ lsof-4.86+dfsg.orig/dialects/hpux/pstat/Makefile0000444000175000017500000000737011011044350022017 0ustar nicholasnicholas # 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 $${PROG} $${BIN}' @echo ' install -m 444 $${MAN} $${DOC}' @echo '' @echo 'You will have to complete the 4xxx modes, the value,' @echo 'and the skeletons for the BIN and DOC strings, given at the' @echo 'beginning of this Makefile, e.g.,' @echo '' @echo ' BIN= $${DESTDIR}/usr/local/etc' @echo ' DOC= $${DESTDIR}/usr/man/man8' @echo ' GRP= sys' @echo '' ${LIB}: FRC (cd lib; ${MAKE} DEBUG="${DEBUG}" CFGF="${CFGF}") version.h: FRC @echo Constructing version.h @rm -f version.h @echo '#define LSOF_BLDCMT "${LSOF_BLDCMT}"' > version.h; @echo '#define LSOF_CC "${CC}"' >> version.h @echo '#define LSOF_CCV "${CCV}"' >> version.h @echo '#define LSOF_CCDATE "'`date`'"' >> version.h @echo '#define LSOF_CCFLAGS "'`echo ${CFLAGS} | sed 's/\\\\(/\\(/g' | sed 's/\\\\)/\\)/g' | sed 's/"/\\\\"/g'`'"' >> version.h @echo '#define LSOF_CINFO "${CINFO}"' >> version.h @if [ "X${LSOF_HOST}" = "X" ]; then \ echo '#define LSOF_HOST "'`uname -n`'"' >> version.h; \ else \ if [ "${LSOF_HOST}" = "none" ]; then \ echo '#define LSOF_HOST ""' >> version.h; \ else \ echo '#define LSOF_HOST "${LSOF_HOST}"' >> version.h; \ fi \ fi @echo '#define LSOF_LDFLAGS "${CFGL}"' >> version.h @if [ "X${LSOF_LOGNAME}" = "X" ]; then \ echo '#define LSOF_LOGNAME "${LOGNAME}"' >> version.h; \ else \ if [ "${LSOF_LOGNAME}" = "none" ]; then \ echo '#define LSOF_LOGNAME ""' >> version.h; \ else \ echo '#define LSOF_LOGNAME "${LSOF_LOGNAME}"' >> version.h; \ fi; \ fi @if [ "X${LSOF_SYSINFO}" = "X" ]; then \ echo '#define LSOF_SYSINFO "'`uname -a`'"' >> version.h; \ else \ if [ "${LSOF_SYSINFO}" = "none" ]; then \ echo '#define LSOF_SYSINFO ""' >> version.h; \ else \ echo '#define LSOF_SYSINFO "${LSOF_SYSINFO}"' >> version.h; \ fi \ fi @if [ "X${LSOF_USER}" = "X" ]; then \ echo '#define LSOF_USER "${USER}"' >> version.h; \ else \ if [ "${LSOF_USER}" = "none" ]; then \ echo '#define LSOF_USER ""' >> version.h; \ else \ echo '#define LSOF_USER "${LSOF_USER}"' >> version.h; \ fi \ fi @@sed '/VN/s/.ds VN \(.*\)/#define LSOF_VERSION "\1"/' < version >> version.h FRC: # DO NOT DELETE THIS LINE - make depend DEPENDS ON IT dfile.o: ${HDR} dfile.c dproc.o: ${HDR} dproc.c dsock.o: ${HDR} dsock.c dstore.o: ${HDR} dstore.c arg.o: ${HDR} arg.c main.o: ${HDR} main.c misc.o: ${HDR} misc.c node.o: ${HDR} node.c print.o: ${HDR} print.c proc.o: ${HDR} proc.c store.o: ${HDR} store.c usage.o: ${HDR} version.h usage.c util.o: ${HDR} util.c # *** Do not add anything here - It will go away. *** lsof-4.86+dfsg.orig/dialects/hpux/kmem/0000755000175000017500000000000011741064216020165 5ustar nicholasnicholaslsof-4.86+dfsg.orig/dialects/hpux/kmem/dstore.c0000444000175000017500000001401410613427600021624 0ustar nicholasnicholas/* * dstore.c - /dev/kmem-based HP-UX global storage for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dstore.c,v 1.12 2007/04/24 16:25:30 abe Exp $"; #endif #include "lsof.h" /* * Global storage definitions */ #if defined(HAS_AFS) # if defined(HASAOPT) char *AFSApath = (char *)NULL; /* alternate AFS name list path * (from -A) */ # endif /* defined(HASAOPT) */ struct vfs *AFSVfsp = (struct vfs *)NULL; /* AFS vfs struct kernel address */ #endif /* defined(HAS_AFS) */ int CloneMaj; /* clone major device number */ /* * Drive_Nl -- table to drive the building of Nl[] via build_Nl() * (See lsof.h and misc.c.) */ struct drive_Nl Drive_Nl[] = { # if defined(hp9000s300) || defined(__hp9000s300) { "arFid", "_afs_rootFid" }, { "avops", "_afs_vnodeops" }, { "avol", "_afs_volumes" }, { X_NCACHE, "_ncache" }, { X_NCSIZE, "_ncsize" }, { "proc", "_proc" }, { "nvops", "_nfs_vnodeops" }, { "nvops3", "_nfs_vnodeops3" }, { "nv3ops", "_nfs3_vnodeops" }, { "nproc", "_nproc" }, { "uvops", "_ufs_vnodeops" }, { "vfops", "_vnodefops" }, # if HPUXV<800 { "upmap", "_Usrptmap" }, { "upt", "_usrpt" }, # endif /* HPUXV<800 */ # endif /* defined(hp9000s300) || defined(__hp9000s300) */ # if defined(hp9000s800) || defined(__hp9000s800) { "arFid", "afs_rootFid" }, { "avops", "afs_vnodeops" }, { "avol", "afs_volumes" }, { X_NCACHE, "ncache" }, { X_NCSIZE, "ncsize" }, { "proc", "proc" }, { "nvops", "nfs_vnodeops" }, { "nvops3", "nfs_vnodeops3" }, { "nv3ops", "nfs3_vnodeops" }, { "nproc", "nproc" }, { "uvops", "ufs_vnodeops" }, { "vfops", "vnodefops" }, # if HPUXV<800 { "ubase", "ubase" }, { "npids", "npids" }, # else /* HPUXV>=800 */ # if HPUXV>=1000 # if HPUXV>=1030 { "clmaj", "clonemajor" }, # endif /* HPUXV>=1030 */ { "cvops", "cdfs_vnodeops" }, { "fvops", "fifo_vnodeops" }, { "pvops", "pipe_vnodeops" }, { "svops", "spec_vnodeops" }, { "vvops", "vx_vnodeops" }, # endif /* HPUXV>=1000 */ # endif /* HPUXV<800 */ # endif /* defined(hp9000s800) || defined(__hp9000s800) */ { "mvops", "mvfs_vnodeops" }, # if HPUXV>=1100 { "chunksz", "sizeof_fd_chunk_t" }, # endif /* HPUXV>=1100 */ { "", "" }, { NULL, NULL } }; int HaveCloneMaj = 0; /* CloneMaj status */ int Kd = -1; /* /dev/kmem file descriptor */ KA_T Kpa; /* kernel proc structure address */ #if HPUXV>=1010 KA_T Ktp; /* kernel thread pointer from proc * struct */ #endif /* HPUXV>=1010 */ struct l_vfs *Lvfs = NULL; /* local vfs structure table */ #if HPUXV<800 int Mem = -1; /* /dev/mem file descriptor */ #endif /* HPUXV<800 */ #if HPUXV<800 && defined(hp9000s800) int npids; /* number of PIDs (for uvadd()) */ struct proc *proc; /* process table address (for uvadd()) */ #endif /* HPUXV<800 && defined(hp9000s300) */ #if defined(HASFSTRUCT) /* * Pff_tab[] - table for printing file flags */ struct pff_tab Pff_tab[] = { { (long)FREAD, FF_READ }, { (long)FWRITE, FF_WRITE }, { (long)FNDELAY, FF_NDELAY }, { (long)FAPPEND, FF_APPEND }, { (long)FMARK, FF_MARK }, { (long)FDEFER, FF_DEFER }, { (long)FNBLOCK, FF_NBLOCK }, { (long)FNOCTTY, FF_NOCTTY }, # if defined(FSYNC) { (long)FSYNC, FF_SYNC }, # else /* !defined(FSYNC) */ # if defined(O_SYNC) { (long)O_SYNC, FF_SYNC }, # endif /* defined(O_SYNC) */ # endif /* defined(FSYNC) */ # if defined(FCOPYAVOID) { (long)FCOPYAVOID, FF_COPYAVOID }, # endif /* defined(FCOPYAVOID) */ # if defined(FPOSIX_AIO) { (long)FPOSIX_AIO, FF_POSIX_AIO }, # endif /* defined(FPOSIX_AIO) */ # if defined(FLARGEFILE) { (long)FLARGEFILE, FF_LARGEFILE }, # else /* !defined(FLARGEFILE) */ # if HPUXV>=1100 { (long)0x800, FF_LARGEFILE }, # endif /* HPUXV>=1100 */ # endif /* defined(FLARGEFILE) */ { (long)0x100, FF_KERNEL }, { (long)0, NULL } }; /* * Pof_tab[] - table for print process open file flags */ # if HPUXV>=1020 #define UF_EXCLOSE 0x1 #define UF_MAPPED 0x2 #define UF_FDLOCK 0x4 #define UF_INUSE 0x8 # endif /* HPUXV>=1020 */ struct pff_tab Pof_tab[] = { # if defined(UF_EXCLOSE) { (long)UF_EXCLOSE, POF_CLOEXEC }, # endif /* defined(UF_EXCLOSE) */ # if defined(UF_MAPPED) { (long)UF_MAPPED, POF_MAPPED }, # endif /* defined(UF_MAPPED) */ # if defined(UF_FDLOCK) { (long)UF_FDLOCK, POF_FDLOCK }, # endif /* defined(UF_FDLOCK) */ # if defined(UF_INUSE) { (long)UF_INUSE, POF_INUSE }, # endif /* defined(UF_INUSE) */ { (long)0, NULL } }; #endif /* defined(HASFSTRUCT) */ #if HPUXV<800 int Swap = -1; /* swap device file descriptor */ #endif /* HPUXV<800 */ #if HPUXV<800 && defined(hp9000s800) struct user *ubase; /* user area base (for uvadd()) */ #endif /* HPUXV<800 && defined(hp9000s800) */ #if HPUXV<800 && defined(hp9000s300) struct user *ubase; /* user area base (for uvadd()) */ struct pte *Usrptmap; /* user page table map pointer */ struct pte *usrpt; /* user page table pointer * (for bktomx from vmmac.h) */ #endif /* HPUXV<800 && defined(hp9000s300) */ KA_T Vnfops; /* vnodefops switch address */ lsof-4.86+dfsg.orig/dialects/hpux/kmem/hpux11/0000755000175000017500000000000011741064216021313 5ustar nicholasnicholaslsof-4.86+dfsg.orig/dialects/hpux/kmem/hpux11/ipc_s.h0000444000175000017500000000520706711672527022576 0ustar nicholasnicholas/* * ipc_s.h for HP-UX 10.30 and above * * This header file defines the ipc_s structure for lsof. The ipc_s structure * is the streams equivalent of a Berkeley-style inpcb (Internet Protocol * Control Block). The ipc_s holds the TCP/IP address for a stream. * * The original HP-UX 11 distribution has a flat ipc_s structure, with hash * links to other ipc_s structures, and direct links to the the read and write * sections of the stream. * * After patch bundle B11.00.43 the ipc_s structure definition requires * two other Q4-derived structures, mirg_s and ipis_s. The ipis_s structure * contains the hash and stream links formerly contained in ipc_s. * * V. Abell * February, 1998 * * Patch bundle update supplied by: Kevin Vajk * February, 1999 */ #if !defined(LSOF_IPC_S_H) #define LSOF_IPC_S_H #include "kernbits.h" #include 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) */ lsof-4.86+dfsg.orig/dialects/hpux/kmem/hpux11/tcp_s.h0000444000175000017500000001345610140136204022570 0ustar nicholasnicholas/* * 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 #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) */ lsof-4.86+dfsg.orig/dialects/hpux/kmem/hpux11/lla.h0000444000175000017500000000341506665512171022244 0ustar nicholasnicholas/* * 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 * February, 1998 */ #if !defined(LSOF_LLA_H) #define LSOF_LLA_H #include "kernbits.h" #include #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 lsof-4.86+dfsg.orig/dialects/hpux/kmem/hpux11/rnode.h0000444000175000017500000000342406665512272022605 0ustar nicholasnicholas/* * rnode.h for HP-UX 10.30 and above * * This header file defines the rnode structure for lsof. Lsof uses it to get * infomation about remote (NFS) nodes -- e.g., node number and size. * * V. Abell * February, 1998 */ #if !defined(LSOF_RNODE_H) #define LSOF_RNODE_H #include "kernbits.h" #define _KERNEL #include #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) */ lsof-4.86+dfsg.orig/dialects/hpux/kmem/hpux11/nfs_clnt.h0000444000175000017500000000310006677667174023312 0ustar nicholasnicholas/* * 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 #undef TCP_NODELAY #undef TCP_MAXSEG #include #include #include #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) */ lsof-4.86+dfsg.orig/dialects/hpux/kmem/hpux11/kernbits.h0000444000175000017500000000107606665512146023320 0ustar nicholasnicholas/* * 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) */ lsof-4.86+dfsg.orig/dialects/hpux/kmem/hpux11/proc.h0000444000175000017500000001162610336130551022426 0ustar nicholasnicholas/* * 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 * February, 1998 */ #if !defined(LSOF_PROC_H) #define LSOF_PROC_H #include "kernbits.h" #include #include #include 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) */ lsof-4.86+dfsg.orig/dialects/hpux/kmem/hpux11/vnode.h0000444000175000017500000000553706665512477022627 0ustar nicholasnicholas/* * 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 * February, 1998 */ #if !defined(LSOF_VNODE_H) #define LSOF_VNODE_H #define _SYS_VNODE_INCLUDED /* prevent inclusion of */ #include "kernbits.h" #include #include #include #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) */ lsof-4.86+dfsg.orig/dialects/hpux/kmem/hpux11/udp_s.h0000444000175000017500000000343006665512456022611 0ustar nicholasnicholas/* * 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) */ lsof-4.86+dfsg.orig/dialects/hpux/kmem/hpux11/sth.h0000444000175000017500000000322607234544416022272 0ustar nicholasnicholas/* * 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 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) */ lsof-4.86+dfsg.orig/dialects/hpux/kmem/dsock.c0000444000175000017500000006672010275733610021447 0ustar nicholasnicholas/* * dsock.c - /dev/kmem-based HP-UX socket processing functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dsock.c,v 1.20 2005/08/08 19:50:23 abe Exp $"; #endif #if defined(HPUXKERNBITS) && HPUXKERNBITS>=64 #define _INO_T typedef int ino_t; #define _TIME_T typedef int time_t; #endif /* defined(HPUXKERNBITS) && HPUXKERNBITS>=64 */ #include "lsof.h" #if HPUXV>=800 && defined(HPUX_CCITT) #include #include #include #include #include #endif /* HPUXV>=800 && defined(HPUX_CCITT) */ /* * Local definitions */ #if defined(HASTCPOPT) #define TF_NODELAY 0x1 /* TCP_NODELAY (Nagle algorithm) */ #endif /* defined(HASTCPOPT) */ #if HPUXV>=1030 /* * print_tcptpi() - print TCP/TPI info */ void print_tcptpi(nl) int nl; /* 1 == '\n' required */ { char *cp = (char *)NULL; char sbuf[128]; int i, t; int ps = 0; unsigned int u; if (Ftcptpi & TCPTPI_STATE) { switch ((t = Lf->lts.type)) { case 0: /* TCP */ switch ((i = Lf->lts.state.i)) { case TCPS_CLOSED: cp = "CLOSED"; break; case TCPS_IDLE: cp = "IDLE"; break; case TCPS_BOUND: cp = "BOUND"; break; case TCPS_LISTEN: cp = "LISTEN"; break; case TCPS_SYN_SENT: cp = "SYN_SENT"; break; case TCPS_SYN_RCVD: cp = "SYN_RCVD"; break; case TCPS_ESTABLISHED: cp = "ESTABLISHED"; break; case TCPS_CLOSE_WAIT: cp = "CLOSE_WAIT"; break; case TCPS_FIN_WAIT_1: cp = "FIN_WAIT_1"; break; case TCPS_CLOSING: cp = "CLOSING"; break; case TCPS_LAST_ACK: cp = "LAST_ACK"; break; case TCPS_FIN_WAIT_2: cp = "FIN_WAIT_2"; break; case TCPS_TIME_WAIT: cp = "TIME_WAIT"; break; default: (void) snpf(sbuf, sizeof(sbuf), "UknownState_%d", i); cp = sbuf; } break; case 1: /* TPI */ switch ((u = Lf->lts.state.ui)) { case TS_UNINIT: cp = "Uninitialized"; break; case TS_UNBND: cp = "Unbound"; break; case TS_WACK_BREQ: cp = "Wait_BIND_REQ_Ack"; break; case TS_WACK_UREQ: cp = "Wait_UNBIND_REQ_Ack"; break; case TS_IDLE: cp = "Idle"; break; case TS_WACK_OPTREQ: cp = "Wait_OPT_REQ_Ack"; break; case TS_WACK_CREQ: cp = "Wait_CONN_REQ_Ack"; break; case TS_WCON_CREQ: cp = "Wait_CONN_REQ_Confirm"; break; case TS_WRES_CIND: cp = "Wait_CONN_IND_Response"; break; case TS_WACK_CRES: cp = "Wait_CONN_RES_Ack"; break; case TS_DATA_XFER: cp = "Wait_Data_Xfr"; break; case TS_WIND_ORDREL: cp = "Wait_Read_Release"; break; case TS_WREQ_ORDREL: cp = "Wait_Write_Release"; break; case TS_WACK_DREQ6: case TS_WACK_DREQ7: case TS_WACK_DREQ9: case TS_WACK_DREQ10: case TS_WACK_DREQ11: cp = "Wait_DISCON_REQ_Ack"; break; case TS_WACK_ORDREL: cp = "Internal"; break; default: (void) snpf(sbuf, sizeof(sbuf), "UNKNOWN_TPI_STATE_%u", u); cp = sbuf; } } if (Ffield) (void) printf("%cST=%s%c", LSOF_FID_TCPTPI, cp, Terminator); else { putchar('('); (void) fputs(cp, stdout); } ps++; } # if defined(HASTCPTPIQ) if (Ftcptpi & TCPTPI_QUEUES) { if (Lf->lts.rqs) { if (Ffield) putchar(LSOF_FID_TCPTPI); else { if (ps) putchar(' '); else putchar('('); } (void) printf("QR=%lu", Lf->lts.rq); if (Ffield) putchar(Terminator); ps++; } if (Lf->lts.sqs) { if (Ffield) putchar(LSOF_FID_TCPTPI); else { if (ps) putchar(' '); else putchar('('); } (void) printf("QS=%lu", Lf->lts.sq); if (Ffield) putchar(Terminator); ps++; } } # endif /* defined(HASTCPTPIQ) */ #if defined(HASSOOPT) if (Ftcptpi & TCPTPI_FLAGS) { int opt; if ((opt = Lf->lts.opt) || Lf->lts.qlens || Lf->lts.qlims || Lf->lts.rbszs || Lf->lts.sbsz ) { char sep = ' '; if (Ffield) sep = LSOF_FID_TCPTPI; else if (!ps) sep = '('; (void) printf("%cSO", sep); ps++; sep = '='; # if defined(SO_BROADCAST) if (opt & SO_BROADCAST) { (void) printf("%cBROADCAST", sep); opt &= ~SO_BROADCAST; sep = ','; } # endif /* defined(SO_BROADCAST) */ # if defined(SO_DEBUG) if (opt & SO_DEBUG) { (void) printf("%cDEBUG", sep); opt &= ~ SO_DEBUG; sep = ','; } # endif /* defined(SO_DEBUG) */ # if defined(SO_DONTROUTE) if (opt & SO_DONTROUTE) { (void) printf("%cDONTROUTE", sep); opt &= ~SO_DONTROUTE; sep = ','; } # endif /* defined(SO_DONTROUTE) */ # if defined(SO_KEEPALIVE) if (opt & SO_KEEPALIVE) { (void) printf("%cKEEPALIVE", sep); if (Lf->lts.kai) (void) printf("=%d", Lf->lts.kai); opt &= ~SO_KEEPALIVE; sep = ','; } # endif /* defined(SO_KEEPALIVE) */ # if defined(SO_LINGER) if (opt & SO_LINGER) { (void) printf("%cLINGER", sep); if (Lf->lts.ltm) (void) printf("=%d", Lf->lts.ltm); opt &= ~SO_LINGER; sep = ','; } # endif /* defined(SO_LINGER) */ # if defined(SO_OOBINLINE) if (opt & SO_OOBINLINE) { (void) printf("%cOOBINLINE", sep); opt &= ~SO_OOBINLINE; sep = ','; } # endif /* defined(SO_OOBINLINE) */ if (Lf->lts.qlens) { (void) printf("%cQLEN=%u", sep, Lf->lts.qlen); sep = ','; } if (Lf->lts.qlims) { (void) printf("%cQLIM=%u", sep, Lf->lts.qlim); sep = ','; } # if defined(SO_REUSEADDR) if (opt & SO_REUSEADDR) { (void) printf("%cREUSEADDR", sep); opt &= ~SO_REUSEADDR; sep = ','; } # endif /* defined(SO_REUSEADDR) */ # if defined(SO_REUSEPORT) if (opt & SO_REUSEPORT) { (void) printf("%cREUSEPORT", sep); opt &= ~SO_REUSEPORT; sep = ','; } # endif /* defined(SO_REUSEPORT) */ # if defined(SO_USELOOPBACK) if (opt & SO_USELOOPBACK) { (void) printf("%cUSELOOPBACK", sep); opt &= ~SO_USELOOPBACK; sep = ','; } # endif /* defined(SO_USELOOPBACK) */ if (opt) (void) printf("%cUNKNOWN=%#x", sep, opt); if (Ffield) putchar(Terminator); } } #endif /* defined(HASSOOPT) */ #if defined(HASTCPOPT) if (Ftcptpi & TCPTPI_FLAGS) { int topt; if ((topt = Lf->lts.topt) || Lf->lts.msss) { char sep = ' '; if (Ffield) sep = LSOF_FID_TCPTPI; else if (!ps) sep = '('; (void) printf("%cTF", sep); ps++; sep = '='; if (Lf->lts.msss) { (void) printf("%cMSS=%lu", sep, Lf->lts.mss); sep = ','; } # if defined(TF_NODELAY) if (topt & TF_NODELAY) { (void) printf("%cNODELAY", sep); topt &= ~TF_NODELAY; sep = ','; } # endif /* defined(TF_NODELAY) */ if (topt) (void) printf("%cUNKNOWN=%#x", sep, topt); if (Ffield) putchar(Terminator); } } # endif /* defined(HASTCPOPT) */ # if defined(HASTCPTPIW) if (Ftcptpi & TCPTPI_WINDOWS) { if (Lf->lts.rws) { if (Ffield) putchar(LSOF_FID_TCPTPI); else { if (ps) putchar(' '); else putchar('('); } (void) printf("WR=%lu", Lf->lts.rw); if (Ffield) putchar(Terminator); ps++; } if (Lf->lts.wws) { if (Ffield) putchar(LSOF_FID_TCPTPI); else { if (ps) putchar(' '); else putchar('('); } (void) printf("WW=%lu", Lf->lts.ww); if (Ffield) putchar(Terminator); ps++; } } # endif /* defined(HASTCPTPIW) */ if (Ftcptpi && !Ffield && ps) putchar(')'); if (nl) putchar('\n'); } #endif /* HPUXV>=1030 */ #if defined(DTYPE_LLA) /* * process_lla() - process link level access socket file */ void process_lla(la) KA_T la; /* link level CB address in kernel */ { char *ep; struct lla_cb lcb; size_t sz; (void) snpf(Lf->type, sizeof(Lf->type), "lla"); Lf->inp_ty = 2; enter_dev_ch(print_kptr(la, (char *)NULL, 0)); /* * Read link level access control block. */ if (!la || kread((KA_T)la, (char *)&lcb, sizeof(lcb))) { (void) snpf(Namech, Namechl, "can't read LLA CB (%s)", print_kptr(la, (char *)NULL, 0)); enter_nm(Namech); return; } /* * Determine access mode. */ if ((lcb.lla_flags & LLA_FWRITE | LLA_FREAD) == LLA_FWRITE) Lf->access = 'w'; else if ((lcb.lla_flags & LLA_FWRITE | LLA_FREAD) == LLA_FREAD) Lf->access = 'r'; else if (lcb.lla_flags & LLA_FWRITE | LLA_FREAD) Lf->access = 'u'; /* * Determine the open mode, if possible. */ if (lcb.lla_flags & LLA_IS_ETHER) (void) snpf(Lf->iproto, sizeof(Lf->iproto), "Ether"); else if (lcb.lla_flags & (LLA_IS_8025|LLA_IS_SNAP8025|LLA_IS_FA8025)) { (void) snpf(Lf->iproto, sizeof(Lf->iproto), "802.5"); if (lcb.lla_flags & LLA_IS_SNAP8025) (void) snpf(Namech, Namechl, "SNAP"); else if (lcb.lla_flags & LLA_IS_FA8025) (void) snpf(Namech, Namechl, "function address"); } /* * Add any significant flags. */ if (lcb.lla_flags & ~(LLA_FWRITE | LLA_FREAD)) { ep = endnm(&sz); (void) snpf(ep, sz, "%s(flags = %#x)", (ep == Namech) ? "" : " ", lcb.lla_flags); } if (Namech[0]) enter_nm(Namech); } #endif /* DTYPE_LLA */ /* * process_socket() - process socket */ void process_socket(sa) KA_T sa; /* socket address in kernel */ { unsigned char *fa = (unsigned char *)NULL; char *ep, tbuf[32]; int fam; int fp, mbl, lp; unsigned char *la = (unsigned char *)NULL; struct protosw p; struct socket s; size_t sz; struct unpcb uc, unp; struct sockaddr_un *ua = (struct sockaddr_un *)NULL; struct sockaddr_un un; #if HPUXV>=800 struct domain d; # if defined(HPUX_CCITT) int i; struct x25pcb xp; struct x25pcb_extension xpe; # endif /* defined(HPUX_CCITT) */ # if HPUXV<1030 struct mbuf mb; struct inpcb inp; struct rawcb raw; struct tcpcb t; # else /* HPUXV>=1030 */ struct datab db; static char *dbf = (char *)NULL; static int dbl = 0; struct msgb mb; struct sockbuf rb, sb; # endif /* HPUXV<1030 */ #endif /* HPUXV>=800 */ (void) snpf(Lf->type, sizeof(Lf->type), "sock"); Lf->inp_ty = 2; /* * Read socket structure. */ if (!sa) { enter_nm("no socket address"); return; } if (kread((KA_T) sa, (char *) &s, sizeof(s))) { (void) snpf(Namech, Namechl, "can't read socket struct from %s", print_kptr(sa, (char *)NULL, 0)); enter_nm(Namech); return; } /* * Read protocol switch and domain structure (HP-UX 8 and above). */ if (!s.so_type) { (void) snpf(Namech, Namechl, "no socket type"); enter_nm(Namech); return; } if (!s.so_proto || kread((KA_T) s.so_proto, (char *) &p, sizeof(p))) { (void) snpf(Namech, Namechl, "no protocol switch"); enter_nm(Namech); return; } #if HPUXV>=800 if (kread((KA_T) p.pr_domain, (char *) &d, sizeof(d))) { (void) snpf(Namech, Namechl, "can't read domain struct from %s", print_kptr((KA_T)p.pr_domain, (char *)NULL, 0)); enter_nm(Namech); return; } #endif /* HPUXV>=800 */ #if HPUXV<1030 /* * Save size information for HP-UX < 10.30. */ if (Fsize) { if (Lf->access == 'r') Lf->sz = (SZOFFTYPE)s.so_rcv.sb_cc; else if (Lf->access == 'w') Lf->sz = (SZOFFTYPE)s.so_snd.sb_cc; else Lf->sz = (SZOFFTYPE)(s.so_rcv.sb_cc + s.so_snd.sb_cc); Lf->sz_def = 1; } else Lf->off_def = 1; # if defined(HASTCPTPIQ) Lf->lts.rq = s.so_rcv.sb_cc; Lf->lts.sq = s.so_snd.sb_cc; Lf->lts.rqs = Lf->lts.sqs = 1; # endif /* defined(HASTCPTPIQ) */ #endif /* HPUXV<1030 */ /* * Process socket by the associated domain family. */ #if HPUXV>=800 switch ((fam = d.dom_family)) #else /* HPUXV<800 */ switch ((fam = p.pr_family)) #endif /* HPUXV>=800 */ { #if HPUXV>=800 && HPUXV<1030 && defined(HPUX_CCITT) /* * Process an HP-UX [89].x CCITT X25 domain socket. */ case AF_CCITT: if (Fnet) Lf->sf |= SELNET; (void) snpf(Lf->type, sizeof(Lf->type), "x.25"); (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL, "CCITT"); /* * Get the X25 PCB and its extension. */ if (!s.so_pcb || kread((KA_T)s.so_pcb, (char *)&xp, sizeof(xp))) { (void) snpf(Namech, Namechl, "can't read x.25 pcb at %s", print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); enter_nm(Namech); return; } enter_dev_ch(print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); if (!xp.x25pcb_extend || kread((KA_T)xp.x25pcb_extend, (char *)&xpe, sizeof(xpe))) { (void) snpf(Namech, Namechl, "can't read x.25 pcb (%s) extension at %s", print_kptr((KA_T)s.so_pcb, tbuf, sizeof(tbuf)), print_kptr((KA_T)xp.x25pcb_extend, (char *)NULL, 0)); enter_nm(Namech); return; } /* * Format local address. */ for (i = 0; i < xpe.x25pcbx_local_addr.x25hostlen/2; i++) { ep = endnm(&sz); (void) snpf(ep, sz, "%02x", xpe.x25pcbx_local_addr.x25_host[i]); } if (i*2 != xpe.x25pcbx_local_addr.x25hostlen) { ep = endnm(&sz); (void) snpf(ep, sz, "%01x", xpe.x25pcbx_local_addr.x25_host[i] >> 4); } /* * Display the virtual connection number, if it's defined. */ if (xp.x25pcb_vcn >= 0) { ep = endnm(&sz); (void) snpf(ep, sz, ":%d", xp.x25pcb_vcn + 1); } /* * Format peer address, if there is one. */ if (xpe.x25pcbx_peer_addr.x25hostlen > 0) { ep = endnm(&sz); (void) snpf(ep, sz, "->"); for (i = 0; i < xpe.x25pcbx_peer_addr.x25hostlen/2; i++) { ep = endnm(&sz); (void) snpf(ep, sz, "%02x", xpe.x25pcbx_peer_addr.x25_host[i]); } if (i*2 != xpe.x25pcbx_peer_addr.x25hostlen) { ep = endnm(&sz); (void) snpf(ep, sz, "%01x", xpe.x25pcbx_peer_addr.x25_host[i] >> 4); } } enter_nm(Namech); break; #endif /* HPUXV>=800 && HPUXV<1030 && defined(HPUX_CCITT) */ /* * Process an Internet domain socket. */ case AF_INET: if (Fnet) Lf->sf |= SELNET; (void) snpf(Lf->type, sizeof(Lf->type), "inet"); printiproto(p.pr_protocol); #if HPUXV>=1030 /* * Handle HP-UX 10.30 and above socket streams. */ if (s.so_sth) { KA_T ip, pcb; char *pn = (char *)NULL; /* * Read module information. */ if (read_mi((KA_T)s.so_sth, &ip, &pcb, &pn)) return; if (ip && pcb) { /* * If IP and TCP or UDP modules are present, process as a * stream socket. */ process_stream_sock(ip, pcb, pn, VNON); return; } /* * If an IP module's PCB address is present, print it as the * device characters. */ if (ip && !Lf->dev_def) enter_dev_ch(print_kptr(ip, (char *)NULL, 0)); if (!strlen(Namech)) { /* * If there are no NAME field characters, enter an error * message. */ if (!ip) { (void) snpf(Namech, Namechl, "no IP module for stream socket"); } else { (void) snpf(Namech, Namechl, "no TCP/UDP module for stream socket"); } } enter_nm(Namech); return; } #else /* HPUXV<1030 */ /* * Read protocol control block. */ if (!s.so_pcb) { enter_nm("no protocol control block"); return; } if (s.so_type == SOCK_RAW) { /* * Print raw socket information. */ if (kread((KA_T)s.so_pcb, (char *)&raw, sizeof(raw)) || (struct socket *)sa != (struct socket *)raw.rcb_socket) { (void) snpf(Namech, Namechl, "can't read rawcb at %s", print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); enter_nm(Namech); return; } enter_dev_ch(print_kptr((KA_T)(raw.rcb_pcb ? raw.rcb_pcb : s.so_pcb), (char *)NULL, 0)); if (raw.rcb_laddr.sa_family == AF_INET) la = (unsigned char *)&raw.rcb_laddr.sa_data[2]; else if (raw.rcb_laddr.sa_family) printrawaddr(&raw.rcb_laddr); if (raw.rcb_faddr.sa_family == AF_INET) fa = (unsigned char *)&raw.rcb_faddr.sa_data[2]; else if (raw.rcb_faddr.sa_family) { ep = endnm(&sz); (void) snpf(ep, sz, "->"); printrawaddr(&raw.rcb_faddr); } if (fa || la) (void) ent_inaddr(la, -1, fa, -1, AF_INET); } else { /* * Print Internet socket information. */ if (kread((KA_T)s.so_pcb, (char *)&inp, sizeof(inp))) { (void) snpf(Namech, Namechl, "can't read inpcb at %s", print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); enter_nm(Namech); return; } enter_dev_ch(print_kptr((KA_T)(inp.inp_ppcb ? inp.inp_ppcb : s.so_pcb), (char *)NULL, 0)); la = (unsigned char *)&inp.inp_laddr; lp = (int)ntohs(inp.inp_lport); if (inp.inp_faddr.s_addr != INADDR_ANY || inp.inp_fport != 0) { fa = (unsigned char *)&inp.inp_faddr; fp = (int)ntohs(inp.inp_fport); } if (fa || la) (void) ent_inaddr(la, lp, fa, fp, AF_INET); if (p.pr_protocol == IPPROTO_TCP && inp.inp_ppcb && kread((KA_T)inp.inp_ppcb, (char *)&t, sizeof(t)) == 0) { Lf->lts.type = 0; Lf->lts.state.i = (int)t.t_state; } } break; #endif /* HPUXV>=1030 */ /* * Process a Unix domain socket. */ case AF_UNIX: if (Funix) Lf->sf |= SELUNX; (void) snpf(Lf->type, sizeof(Lf->type), "unix"); #if HPUXV>=1030 /* * Save size information for HP-UX 10.30 and above. */ if (Fsize) { if (!s.so_rcv || kread((KA_T)s.so_rcv, (char *)&rb, sizeof(rb))) rb.sb_cc = 0; if (!s.so_snd || kread((KA_T)s.so_snd, (char *)&sb, sizeof(sb))) sb.sb_cc = 0; if (Lf->access == 'r') Lf->sz = (SZOFFTYPE)rb.sb_cc; else if (Lf->access == 'w') Lf->sz = (SZOFFTYPE)sb.sb_cc; else Lf->sz = (SZOFFTYPE)(rb.sb_cc + sb.sb_cc); Lf->sz_def = 1; } else Lf->off_def = 1; #endif /* HPUXV>=1030 */ /* * Read Unix protocol control block and the Unix address structure. */ enter_dev_ch(print_kptr(sa, (char *)NULL, 0)); if (kread((KA_T) s.so_pcb, (char *) &unp, sizeof(unp))) { (void) snpf(Namech, Namechl, "can't read unpcb at %s", print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); break; } if ((struct socket *)sa != unp.unp_socket) { (void) snpf(Namech, Namechl, "unp_socket (%s) mismatch", print_kptr((KA_T)unp.unp_socket, (char *)NULL, 0)); break; } #if HPUXV<1030 /* * Read UNIX domain socket address information for HP-UX below 10.30. */ if (unp.unp_addr) { if (kread((KA_T) unp.unp_addr, (char *) &mb, sizeof(mb))) { (void) snpf(Namech, Namechl, "can't read unp_addr at %s", print_kptr((KA_T)unp.unp_addr, (char *)NULL, 0)); break; } ua = (struct sockaddr_un *)(((char *)&mb) + mb.m_off); mbl = mb.m_len; } #else /* HPUXV>=1030 */ /* * Obtain UNIX domain socket address information for HP-UX 10.30 and * above. */ if (unp.unp_ino) { Lf->inode = (INODETYPE)unp.unp_ino; Lf->inp_ty = 1; } ua = (struct sockaddr_un *)NULL; mbl = 0; if (unp.unp_addr && kread((KA_T)unp.unp_addr, (char *)&mb, sizeof(mb)) == 0 && mb.b_datap && kread((KA_T)mb.b_datap, (char *)&db, sizeof(db)) == 0) { if (db.db_base) { if (dbl < (db.db_size + 1)) { dbl = db.db_size + 1; if (dbf) dbf = (char *)realloc((MALLOC_P *)dbf, (MALLOC_S) dbl); else dbf = (char *)malloc((MALLOC_S)dbl); if (!dbf) { (void) fprintf(stderr, "%s: no space (%d) for UNIX socket address\n", Pn, dbl); Exit(1); } } if (kread((KA_T)db.db_base, dbf, db.db_size) == 0) { mbl = db.db_size; dbf[mbl] = '\0'; ua = (struct sockaddr_un *)dbf; } } } #endif /* HPUXV>=1030 */ if (!ua) { ua = &un; (void) bzero((char *)ua, sizeof(un)); ua->sun_family = AF_UNSPEC; } /* * Print information on Unix socket that has no address bound * to it, although it may be connected to another Unix domain * socket as a pipe. */ if (ua->sun_family != AF_UNIX) { if (ua->sun_family == AF_UNSPEC) { if (unp.unp_conn) { if (kread((KA_T)unp.unp_conn, (char *) &uc, sizeof(uc))) (void) snpf(Namech, Namechl, "can't read unp_conn at %s", print_kptr((KA_T)unp.unp_conn,(char *)NULL,0)); else (void) snpf(Namech, Namechl, "->%s", print_kptr((KA_T)uc.unp_socket,(char *)NULL,0)); } else (void) snpf(Namech, Namechl, "->(none)"); } else (void) snpf(Namech, Namechl, "unknown sun_family (%d)", ua->sun_family); break; } if (ua->sun_path[0]) { if (mbl >= sizeof(struct sockaddr_un)) mbl = sizeof(struct sockaddr_un) - 1; *((char *)ua + mbl) = '\0'; if (Sfile && is_file_named(ua->sun_path, 0)) Lf->sf |= SELNM; if (!Namech[0]) (void) snpf(Namech, Namechl, "%s", ua->sun_path); } else (void) snpf(Namech, Namechl, "no address"); break; default: printunkaf(fam, 1); } if (Namech[0]) enter_nm(Namech); } #if HPUXV>=1030 /* * process_stream_sock() - process stream socket */ void process_stream_sock(ip, pcb, pn, vt) KA_T ip; /* IP module's q_ptr */ KA_T pcb; /* protocol's q_ptr */ char *pn; /* protocol name */ enum vtype vt; /* vnode type */ { unsigned char *fa = (unsigned char *)NULL; char *ep; int fp, lp, rq, sq; struct ipc_s ic; unsigned char *la = (unsigned char *)NULL; size_t sz; u_short pt; struct tcp_s tc; tcph_t th; struct udp_s ud; /* * Set file type and protocol. If AF_INET selection is in effect, set its flag. */ if (Fnet) Lf->sf |= SELNET; (void) snpf(Lf->type, sizeof(Lf->type), "inet"); if (pn) { (void) snpf(Lf->iproto, sizeof(Lf->iproto), pn); Lf->inp_ty = 2; } else if (Sfile && (vt != VNON) && Lf->dev_def && (Lf->inp_ty == 1)) { /* * If the protocol name isn't known and this stream socket's vnode type * isn't VNON, the stream socket will be handled mostly as a stream. * Thus, a named file check is appropriate. */ if (is_file_named((char *)NULL, (vt == VCHR) ? 1 : 0)) Lf->sf |= SELNM; } /* * Get IP structure. */ *Namech = '\0'; if (!ip || kread(ip, (char *)&ic, sizeof(ic))) { ep = endnm(&sz); (void) snpf(ep, sz, "%scan't read IP control structure from %s", sz ? " " : "", print_kptr(ip, (char *)NULL, 0)); enter_nm(Namech); return; } if (!Lf->dev_def) enter_dev_ch(print_kptr(ip, (char *)NULL, 0)); /* * Check for protocol control block address. Enter if non-NULL and clear * device definition flag. */ if (!pcb) { ep = endnm(&sz); (void) snpf(ep, sz, "%ssocket stream has no TCP or UDP module", sz ? " " : ""); enter_nm(Namech); return; } /* * Select processing by protocol name. */ if (pn && !strcmp(pn, "TCP")) { /* * Process TCP socket. */ if (kread(pcb, (char *)&tc, sizeof(tc))) { ep = endnm(&sz); (void) snpf(ep, sz, "%scan't read TCP PCB from %s", sz ? " " : "", print_kptr(pcb, (char *)NULL, 0)); enter_nm(Namech); return; } /* * Save TCP address. */ la = (unsigned char *)&ic.ipc_tcp_laddr; pt = (u_short)ic.ipc_tcp_lport; if (((struct in_addr *)la)->s_addr == INADDR_ANY && pt == 0) { /* * If the ipc_s structure has no local address, use the local * address in its tcp_iph structure, and the port number in its * tcph structure. */ la = (unsigned char *)&tc.tcp_u.tcp_u_iph.iph_src[0]; if (tc.tcp_hdr_len && tc.tcp_tcph && kread((KA_T)tc.tcp_tcph, (char *)&th, sizeof(th)) == 0) pt = (u_short)th.th_lport; } lp = (int)ntohs(pt); if ((int)ic.ipc_tcp_faddr != INADDR_ANY || (u_short)ic.ipc_tcp_fport != 0) { fa = (unsigned char *)&ic.ipc_tcp_faddr; fp = (int)ntohs((u_short)ic.ipc_tcp_fport); } if (fa || la) (void) ent_inaddr(la, lp, fa, fp, AF_INET); /* * Save TCP state and size information. */ Lf->lts.type = 0; Lf->lts.state.i = (int)tc.tcp_state; # if defined(HASTCPTPIQ) || defined(HASTCPTPIW) # if defined(HASTCPTPIW) Lf->lts.rw = (int)tc.tcp_rwnd; Lf->lts.ww = (int)tc.tcp_swnd; Lf->lts.rws = Lf->lts.wws = 1; # endif /* defined(HASTCPTPIW) */ if ((rq = (int)tc.tcp_rnxt - (int)tc.tcp_rack - 1) < 0) rq = 0; if ((sq = (int)tc.tcp_snxt - (int)tc.tcp_suna - 1) < 0) sq = 0; # if defined(HASTCPTPIQ) Lf->lts.rq = (unsigned long)rq; Lf->lts.sq = (unsigned long)sq; Lf->lts.rqs = Lf->lts.sqs = 1; # endif /* defined(HASTCPTPIQ) */ if (Fsize) { if (Lf->access == 'r') Lf->sz = (SZOFFTYPE)rq; else if (Lf->access == 'w') Lf->sz = (SZOFFTYPE)sq; else Lf->sz = (SZOFFTYPE)(rq + sq); Lf->sz_def = 1; } else Lf->off_def = 1; # else /* !defined(HASTCPTPIQ) && !defined(HASTCPTPIW) */ if (!Fsize) Lf->off_def = 1; # endif /* defined(HASTCPTPIQ) || defined(HASTCPTPIW) */ # if defined(HASTCPOPT) if (Ftcptpi & TCPTPI_FLAGS) { /* * Save TCP options and values.. */ if (tc.tcp_naglim == (uint)1) Lf->lts.topt |= TF_NODELAY; Lf->lts.mss = (unsigned long)tc.tcp_mss; Lf->lts.msss = (unsigned char)1; } # endif /* defined(HASTCPOPT) */ # if defined(HASSOOPT) if (Ftcptpi & TCPTPI_FLAGS) { /* * Save socket options. */ if (tc.tcp_broadcast) Lf->lts.opt |= SO_BROADCAST; if (tc.tcp_so_debug) Lf->lts.opt |= SO_DEBUG; if (tc.tcp_dontroute) Lf->lts.opt |= SO_DONTROUTE; if (tc.tcp_keepalive_intrvl && (tc.tcp_keepalive_intrvl != 7200000) ) { Lf->lts.opt |= SO_KEEPALIVE; Lf->lts.kai = (unsigned int)tc.tcp_keepalive_intrvl; } if (tc.tcp_lingering) { Lf->lts.opt |= SO_LINGER; Lf->lts.ltm = (unsigned int)tc.tcp_linger; } if (tc.tcp_oobinline) Lf->lts.opt |= SO_OOBINLINE; if (tc.tcp_reuseaddr) Lf->lts.opt |= SO_REUSEADDR; if (tc.tcp_reuseport) Lf->lts.opt |= SO_REUSEPORT; if (tc.tcp_useloopback) Lf->lts.opt |= SO_USELOOPBACK; Lf->lts.qlen = (unsigned int)tc.tcp_conn_ind_cnt; Lf->lts.qlim = (unsigned int)tc.tcp_conn_ind_max; if (Lf->lts.qlen || Lf->lts.qlim) Lf->lts.qlens = Lf->lts.qlims = (unsigned char)1; } # endif /* defined(HASSOOPT) */ Namech[0] = '\0'; return; } else if (pn && !strcmp(pn, "UDP")) { /* * Process UDP socket. */ if (kread(pcb, (char *)&ud, sizeof(ud))) { ep = endnm(&sz); (void) snpf(ep, sz, "%scan't read UDP PCB from %s", sz ? " " : "", print_kptr(pcb, (char *)NULL, 0)); enter_nm(Namech); return; } /* * Save UDP address and TPI state. */ la = (unsigned char *)&ic.ipc_udp_addr; pt = (u_short)ic.ipc_udp_port; if (((struct in_addr *)la)->s_addr == INADDR_ANY && pt == 0) { /* * If the ipc_s structure has no local address, use the one in the * udp_s structure. */ pt = (u_short)ud.udp_port[0]; } (void) ent_inaddr(la, (int)ntohs(pt), (unsigned char *)NULL, -1, AF_INET); if (!Fsize) Lf->off_def = 1; Lf->lts.type = 1; Lf->lts.state.ui = (unsigned int)ud.udp_state; Namech[0] = '\0'; return; } else { /* * Record an unknown protocol. */ ep = endnm(&sz); (void) snpf(ep, sz, "%sunknown stream protocol: %s", sz ? " " : "", pn ? pn : "NUll"); } if (Namech[0]) enter_nm(Namech); } #endif /* HPUXV>=1030 */ lsof-4.86+dfsg.orig/dialects/hpux/kmem/dproc.c0000444000175000017500000004607011073132307021440 0ustar nicholasnicholas/* * dproc.c - /dev/kmem-based HP-UX process access functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dproc.c,v 1.18 2008/10/08 13:24:36 abe Exp $"; #endif #if defined(HPUXKERNBITS) # if HPUXKERNBITS>=64 #define _INO_T typedef int ino_t; #define _TIME_T typedef int time_t; # else /* HPUXKERNBITS<64 */ #define _RLIM_T # if !defined(__STDC_32_MODE__) typedef unsigned long long rlim_t; # else /* defined(__STDC_32_MODE__) */ typedef unsigned long rlim_t; # endif /* !defined(__STDC_32_MODE__) */ # endif /* HPUXKERNBITS>=64 */ #endif /* defined(HPUXKERNBITS) */ #include "lsof.h" #if defined(HASNCACHE) #include #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 #define SZOMB 3 # if HPUXV<1020 struct proc { caddr_t d1[2]; /* dummy to occupy space */ caddr_t p_firstthreadp; /* thread pointer */ caddr_t d2[4]; /* dummy to occupy space */ int p_stat; /* process status */ caddr_t d3[9]; /* dummy to occupy space */ uid_t p_uid; /* UID */ caddr_t d4[2]; /* dummy to occupy space */ gid_t p_pgid; /* process group ID */ pid_t p_pid; /* PID */ pid_t p_ppid; /* parent PID */ caddr_t d5[9]; /* dummy to occupy space */ vas_t *p_vas; /* virtual address space */ caddr_t d6[16]; /* dummy to occupy space */ int p_maxof; /* max open files allowed */ struct vnode *p_cdir; /* current directory */ struct vnode *p_rdir; /* root directory */ struct ofile_t **p_ofilep; /* file descriptor chunks */ caddr_t d7[43]; /* dummy to occupy space */ }; # endif /* HPUXV<1020 */ # if HPUXV>=1020 && HPUXV<1030 struct proc { caddr_t d1[2]; /* dummy to occupy space */ caddr_t p_firstthreadp; /* thread pointer */ caddr_t d2[6]; /* dummy to occupy space */ int p_stat; /* process status */ caddr_t d3[14]; /* dummy to occupy space */ uid_t p_uid; /* real UID */ uid_t p_suid; /* effective UID */ caddr_t d4; /* dummy to occupy space */ gid_t p_pgid; /* process group ID */ pid_t p_pid; /* PID */ pid_t p_ppid; /* parent PID */ caddr_t d5[9]; /* dummy to occupy space */ vas_t *p_vas; /* virtual address space */ caddr_t d6[16]; /* dummy to occupy space */ int p_maxof; /* max open files allowed */ struct vnode *p_cdir; /* current directory */ struct vnode *p_rdir; /* root directory */ struct ofile_t **p_ofilep; /* file descriptor chunks */ caddr_t d7[84]; /* dummy to occupy space */ }; # endif /* HPUXV>=1020 && HPUXV<1030 */ #endif /* HPUXV<1010 */ /* * Local static values */ static KA_T Kp; /* kernel's process table address */ static int Np; /* number of kernel processes */ #if HPUXV>=800 static MALLOC_S Nva = 0; /* number of entries allocated to * vnode address cache */ static KA_T *Vp = (KA_T *)NULL; /* vnode address cache */ #endif /* HPUXV>=800 */ _PROTOTYPE(static void get_kernel_access,(void)); #if HPUXV>=800 _PROTOTYPE(static void process_text,(KA_T vasp)); #endif /* HPUXV>=800 */ /* * gather_proc_info() -- gather process information */ void gather_proc_info() { KA_T fp; int err, i, j; #if HPUXV>=1020 && HPUXV<1100 struct ofile_t { struct ofa { KA_T ofile; int d1; int pofile; } ofa[SFDCHUNK]; }; struct ofa *ofap; int ofasz = (int)sizeof(struct ofa); struct ofile_t oft; char *oftp = (char *)&oft; int oftsz = (int)sizeof(struct ofile_t); #else /* HPUXV<1020 || HPUXV>=1100 */ # if HPUXV>=1100 struct ofa { KA_T ofile; int d1; short d2; char d3; char pofile; }; struct ofa *ofap; int ofasz = (int)sizeof(struct ofa); char *oftp = (char *)NULL; int oftsz = (int)(sizeof(struct ofa) * SFDCHUNK); KA_T v; # endif /* HPUXV>=1100 */ #endif /* HPUXV>=1020 && HPUXV<1100 */ #if HPUXV>=800 char *c, *s; KA_T pfp, ofp; #if HPUXV<1020 struct ofile_t oft; char *oftp = (char *)&oft; int oftsz = (int)sizeof(struct ofile_t); #endif /* HPUXV<1020 */ struct pst_status ps; # if HPUXV<1010 struct user us; # else /* HPUXV>=1010 */ struct user { char u_comm[PST_CLEN]; } us; # endif /* HPUXV<1010 */ #else /* HPUXV<800 */ int k; long sw; char us[U_SIZE]; /* must read HP-UX SWAP in DEV_BSIZE chunks */ # if defined(hp9000s300) struct pte pte1, pte2; KA_T pte_off, pte_addr; # endif /* defined(hp9000s300) */ #endif /* HPUXV>=800 */ struct proc *p; struct proc pbuf; short pss, sf; int px; struct user *u; #if defined(HASFSTRUCT) # if HPUXV>=1020 || (HPUXV>=900 && HPUXV<1000) #define USESPOFILE 1 long pof; # endif /* HPUXV>=1020 || (HPUXV>=900 && HPUXV<1000) */ #endif /* defined(HASFSTRUCT) */ #if HPUXV>=1100 /* * Define FD chunk size and pointer for HP-UX >= 11. */ if (!oftp) { if ((get_Nl_value("chunksz", Drive_Nl, &v) >= 0) && v) { if (kread(v, (char *)&oftsz, sizeof(oftsz))) { (void) fprintf(stderr, "%s: can't get FD chunk size\n", Pn); Exit(1); } if (!oftsz) { (void) fprintf(stderr, "%s: bad FD chunk size: %d\n", Pn, oftsz); Exit(1); } } ofasz = (int)(oftsz / SFDCHUNK); if (oftsz != (ofasz * SFDCHUNK)) { (void) fprintf(stderr, "%s: FD chunk size (%d) not exact multiple of %d\n", Pn, oftsz, SFDCHUNK); Exit(1); } if (!(oftp = (char *)malloc((MALLOC_S)oftsz))) { (void) fprintf(stderr, "%s: no space for %d FD bytes\n", Pn, oftsz); Exit(1); } } #endif /* HPUXV>=1100 */ /* * Examine proc structures and their associated information. */ #if HPUXV>=800 u = &us; (void) zeromem((char *)u, U_SIZE); for (p = &pbuf, px = 0; px < Np; px++) #else /* HPUXV<800 */ for (p = &pbuf, px = 0, u = (struct user *)us; px < Np; px++) #endif /* HPUXV>=800 */ { Kpa = Kp + (KA_T)(px * sizeof(struct proc)); if (kread(Kpa, (char *)&pbuf, sizeof(pbuf))) continue; if (p->p_stat == 0 || p->p_stat == SZOMB) continue; /* * See if process is excluded. */ if (is_proc_excl(p->p_pid, (int)p->p_pgid, (UID_ARG)p->p_uid, &pss, &sf)) continue; #if HPUXV>=1010 /* * Save the kernel thread pointer. */ Ktp = (KA_T)p->p_firstthreadp; #endif /* HPUXV>=1010 */ /* * Read the user area. */ #if HPUXV>=800 /* * Use the pstat() syscall to read process status. */ if (pstat(PSTAT_PROC, &ps, sizeof(ps), 0, p->p_pid) != 1) { if (!Fwarn) (void) fprintf(stderr, "%s: can't pstat process %d: %s\n", Pn, p->p_pid, strerror(errno)); continue; } /* * Use the pst_cmd command buffer. */ c = ps.pst_cmd; ps.pst_cmd[PST_CLEN - 1] = '\0'; /* paranoia */ /* * Skip to the last component of the first path name. Also skip any * leading `-', signifying a login shell. Copy the result to u_comm[]. */ if (*c == '-') c++; for (s = c; *c && (*c != ' '); c++) { if (*c == '/') s = c + 1; } for (i = 0; i < MAXCOMLEN; i++) { if (*s == '\0' || *s == ' ' || *s == '/') break; u->u_comm[i] = *s++; } u->u_comm[i] = '\0'; #else /* HPUXV<800 */ /* * Read the user area from the swap file or memory. */ if ((p->p_flag & SLOAD) == 0) { /* * If the process is not loaded, read the user area from the swap * file. */ if (Swap < 0) continue; sw = (long)p->p_swaddr; # if defined(hp9000s800) sw += (long)ctod(btoc(STACKSIZE * NBPG)); # endif /* defined(hp9000s800) */ if (lseek(Swap, (off_t)dtob(sw), L_SET) == (off_t)-1 || read(Swap, u, U_SIZE) != U_SIZE) continue; } else { /* * Read the user area via the page table. */ # if defined(hp9000s300) pte_off = (KA_T) &Usrptmap[btokmx(p->p_p0br) + p->p_szpt - 1]; if (kread(pte_off, (char *)&pte1, sizeof(pte1))) continue; pte_addr = (KA_T)(ctob(pte1.pg_pfnum + 1) - ((UPAGES + FLOAT) * sizeof(pte2))); if (mread(pte_addr, (char *)&pte2, sizeof(pte2))) continue; if (mread((KA_T)ctob(pte2.pg_pfnum), (char *)u, sizeof(struct user))) continue; # endif /* defined(hp9000s300) */ # if defined(hp9000s800) if (kread((KA_T)uvadd((struct proc *)Kpa), (char *)u, sizeof(struct user))) continue; } # endif /* defined(hp9000s800) */ #endif /* HPUXV>=800 */ /* * Allocate a local process structure. */ if (is_cmd_excl(u->u_comm, &pss, &sf)) continue; alloc_lproc(p->p_pid, (int)p->p_pgid, (int)p->p_ppid, (UID_ARG)p->p_uid, u->u_comm, (int)pss, (int)sf); Plf = (struct lfile *)NULL; /* * Save current working directory information. */ if (CURDIR) { alloc_lfile(CWD, -1); process_node((KA_T)CURDIR); if (Lf->sf) link_lfile(); } /* * Save root directory information. */ if (ROOTDIR) { alloc_lfile(RTD, -1); process_node((KA_T)ROOTDIR); if (Lf->sf) link_lfile(); } #if HPUXV>=800 /* * Print information on the text file. */ if (p->p_vas) process_text((KA_T)p->p_vas); #endif /* HPUXV>=800 */ /* * Loop through user's files. */ #if HPUXV>=800 for (i = 0, j = SFDCHUNK, pfp = (KA_T)p->p_ofilep; i < p->p_maxof; i++) #else /* HPUXV<800 */ for (i = j = k = 0;; i++) #endif /* HPUXV>=800 */ { #if HPUXV>=800 if (j >= SFDCHUNK) { if (!pfp || kread((KA_T)pfp, (char *)&ofp, sizeof(ofp)) || !ofp || kread((KA_T)ofp, oftp, oftsz)) break; j = 0; pfp += sizeof(KA_T); # if HPUXV>=1020 ofap = (struct ofa *)oftp; # endif /* HPUXV>=1020 */ } j++; # if HPUXV>=1020 # if defined(USESPOFILE) pof = (long)ofap->pofile; # endif /* defined(USESPOFILE) */ fp = (KA_T)ofap->ofile; ofap = (struct ofa *)((char *)ofap + ofasz); if (fp) # else /* HPUXV<1020 */ # if defined(USESPOFILE) pof = (long)oft.pofile[j - 1]; # endif /* defined(USESPOFILE) */ if ((fp = (KA_T)oft.ofile[j - 1])) # endif /* HPUXV>=1020 */ #else /* HPUXV<800 */ if (j >= SFDCHUNK) { /* * Get next file pointer "chunk". */ while (++k < NFDCHUNKS && !u->u_ofilep[k]) ; if (k >= NFDCHUNKS) break; if (kread((KA_T)u->u_ofilep[k], (char *)&u->u_ofile, sizeof(struct ofile_t))) { break; } j = 0; } j++; if ((fp = (KA_T)u->u_ofile.ofile[j - 1])) #endif /* HPUXV>=800 */ /* * Process the file pointer. */ { alloc_lfile(NULL, i); process_file(fp); if (Lf->sf) { #if defined(USESPOFILE) if (Fsv & FSV_FG) Lf->pof = pof; #endif /* defined(USESPOFILE) */ link_lfile(); } } } /* * Examine results. */ if (examine_lproc()) return; } } /* * get_kernel_access() - access the required information in the kernel */ static void get_kernel_access() { KA_T v; /* * Check the kernel version. */ (void) ckkv("HP-UX", LSOF_VSTR, (char *)NULL, (char *)NULL); #if HPUXV>=1030 /* * See if build and run bit sizes match. Exit if they don't. */ { long rv; if ((rv = sysconf(_SC_KERNEL_BITS)) < 0) { (void) fprintf(stderr, "%s: sysconf(_SC_KERNEL_BITS) returns: %s\n", Pn, strerror(errno)); Exit(1); } if (rv != (long)HPUXKERNBITS) { (void) fprintf(stderr, "%s: FATAL: %s was built for a %d bit kernel, but this\n", Pn, Pn, HPUXKERNBITS); (void) fprintf(stderr, " is a %ld bit kernel.\n", rv); Exit(1); } } #endif /* HPUXV>=1030 */ #if defined(HAS_AFS) struct NLIST_TYPE *nl = (struct NLIST_TYPE *)NULL; #endif /* defined(HAS_AFS) */ #if HPUXV<800 /* * Open access to /dev/mem and SWAP. */ if ((Mem = open("/dev/mem", O_RDONLY, 0)) < 0) { (void) fprintf(stderr, "%s: can't open /dev/mem: %s\n", Pn, strerror(errno)); err = 1; } if (!Memory || strcmp(Memory, KMEM) == 0) { if ((Swap = open(SWAP, O_RDONLY, 0)) < 0) { (void) fprintf(stderr, "%s: %s: %s\n", Pn, SWAP, strerror(errno)); err = 1; } } #endif /* HPUXV<800 */ #if defined(WILLDROPGID) /* * If kernel memory isn't coming from KMEM, drop setgid permission * before attempting to open the (Memory) file. */ if (Memory) (void) dropgid(); #else /* !defined(WILLDROPGID) */ /* * See if the non-KMEM memory file is readable. */ if (Memory && !is_readable(Memory, 1)) Exit(1); #endif /* defined(WILLDROPGID) */ /* * Open kernel memory access. */ if ((Kd = open(Memory ? Memory : KMEM, O_RDONLY, 0)) < 0) { int errno_save = errno; (void) fprintf(stderr, "%s: can't open ", Pn); safestrprt(Memory ? Memory : KMEM, stderr, 0); (void) fprintf(stderr, ": %s\n", strerror(errno_save)); Exit(1); } #if defined(WILLDROPGID) /* * Drop setgid permission, if necessary. */ if (!Memory) (void) dropgid(); #else /* !defined(WILLDROPGID) */ /* * See if the name list file is readable. */ if (Nmlst && !is_readable(Nmlst, 1)) Exit(1); #endif /* defined(WILLDROPGID) */ (void) build_Nl(Drive_Nl); #if defined(HAS_AFS) if (!Nmlst) { /* * If AFS is defined and we're getting kernel symbol values from * from N_UNIX, make a copy of Nl[] for possible use with the AFS * module name list file. */ if (!(nl = (struct NLIST_TYPE *)malloc(Nll))) { (void) fprintf(stderr, "%s: no space (%d) for Nl[] copy\n", Pn, Nll); Exit(1); } (void) memcpy((void *)nl, (void *)Nl, (size_t)Nll); } #endif /* defined(HAS_AFS) */ /* * Access kernel symbols. */ if (NLIST_TYPE(Nmlst ? Nmlst : N_UNIX, Nl) < 0) { (void) fprintf(stderr, "%s: can't read namelist from: ", Pn); safestrprt(Nmlst ? Nmlst : N_UNIX, stderr, 1); Exit(1); } if (get_Nl_value("proc", Drive_Nl, &v) < 0 || !v || kread((KA_T)v, (char *)&Kp, sizeof(Kp)) || get_Nl_value("nproc", Drive_Nl, &v) < 0 || !v || kread((KA_T)v, (char *)&Np, sizeof(Np)) || !Kp || Np < 1) { (void) fprintf(stderr, "%s: can't read proc table info\n", Pn); Exit(1); } if (get_Nl_value("vfops", Drive_Nl, (KA_T *)&Vnfops) < 0) Vnfops = (KA_T)NULL; #if HPUXV<800 && defined(hp9000s300) if (get_Nl_value("upmap", Drive_Nl, (unsigned long *)&Usrptmap) < 0) { (void) fprintf(stderr, "%s: can't get kernel's Usrptmap\n", Pn); Exit(1); } if (get_Nl_value("upt", Drive_Nl, (unsigned long *)&usrpt) < 0) { (void) fprintf(stderr, "%s: can't get kernel's usrpt\n", Pn); Exit(1); } #endif /* HPUXV<800 && defined(hp9000s300) */ #if HPUXV<800 && defined(hp9000s800) proc = (struct proc *)Kp; if (get_Nl_value("ubase", Drive_Nl, (unsigned long *)&ubase) < 0) { (void) fprintf(stderr, "%s: can't get kernel's ubase\n", Pn); Exit(1); } if (get_Nl_value("npids", Drive_Nl, &v) < 0 || !v || kread((KA_T)v, (char *)&npids, sizeof(npids))) { (void) fprintf(stderr, "%s: can't get kernel's npids\n", Pn); Exit(1); } #endif /* HPUXV<800 && defined(hp9000s800) */ #if HPUXV>=1030 if (get_Nl_value("clmaj", Drive_Nl, &v) < 0 || !v || kread((KA_T)v, (char *)&CloneMaj, sizeof(CloneMaj))) HaveCloneMaj = 0; else HaveCloneMaj = 1; #endif /* HPUXV>=1030 */ #if defined(HAS_AFS) if (nl) { /* * If AFS is defined and we're getting kernel symbol values from * N_UNIX, and if any X_AFS_* symbols isn't there, see if it is in the * the AFS module name list file. Make sure that other symbols that * appear in both name list files have the same values. */ if ((get_Nl_value("arFid", Drive_Nl, &v) >= 0 && !v) || (get_Nl_value("avops", Drive_Nl, &v) >= 0 && !v) || (get_Nl_value("avol", Drive_Nl, &v) >= 0 && !v)) (void) ckAFSsym(nl); (void) free((FREE_P *)nl); } #endif /* defined(HAS_AFS) */ } /* * initialize() - perform all initialization */ void initialize() { get_kernel_access(); } /* * kread() - read from kernel memory */ int kread(addr, buf, len) KA_T addr; /* kernel memory address */ char *buf; /* buffer to receive data */ READLEN_T len; /* length to read */ { int br; if (lseek(Kd, (off_t)addr, L_SET) == (off_t)-1L) return(-1); br = read(Kd, buf, len); return((br == len) ? 0 : 1); } #if HPUXV<800 /* * mread() -- read from /dev/mem */ static int mread(addr, buf, len) KA_T addr; /* /dev/mem address */ char *buf; /* buffer to receive data */ READLEN_T len; /* length to read */ { int br; if (lseek(Mem, addr, L_SET) == (off_t)-1L) return(1); br = read(Mem, buf, len); return((br == len) ? 0 : 1); } #endif /* HPUXV<800 */ #if HPUXV>=800 /* * process_text() - process text access information */ static void process_text(vasp) KA_T vasp; /* kernel's virtual address space * pointer */ { char fd[FDLEN]; int i, j, lm; MALLOC_S len; struct pregion p; KA_T prp; struct region r; struct vas v; KA_T va; /* * Read virtual address space pointer. */ if (kread(vasp, (char *)&v, sizeof(v))) return; /* * Follow the virtual address space pregion structure chain. */ for (i = lm = 0, prp = (KA_T)v.va_next; prp != vasp; prp = (KA_T)p.p_next, lm++) { /* * Avoid infinite loop. */ if (lm > 1000) { if (!Fwarn) (void) fprintf(stderr, "%s: too many virtual address regions for PID %d\n", Pn, Lp->pid); return; } /* * Read the pregion and region. */ if (kread(prp, (char *)&p, sizeof(p))) return; if (kread((KA_T)p.p_reg, (char *)&r, sizeof(r))) return; /* * Skip file entries with no file pointers. */ if (!(va = (KA_T)r.r_fstore)) continue; /* * Skip entries whose vnodes have already been displayed. * * Record new, unique vnode pointers. */ for (j = 0; j < i; j++) { if (Vp[j] == va) break; } if (j < i) continue; if (i >= Nva) { Nva += 10; len = (MALLOC_S)(Nva * sizeof(KA_T)); if (!Vp) Vp = (KA_T *)malloc(len); else Vp = (KA_T *)realloc((MALLOC_P *)Vp, len); if (!Vp) { (void) fprintf(stderr, "%s: no more space for text vnode pointers\n", Pn); Exit(1); } } Vp[i++] = va; /* * Allocate local file structure. */ switch (p.p_type) { case PT_DATA: case PT_TEXT: alloc_lfile(" txt", -1); break; case PT_MMAP: alloc_lfile(" mem", -1); break; default: (void) snpf(fd, sizeof(fd), "R%02d", p.p_type); alloc_lfile(fd, -1); } /* * Save vnode information. */ process_node(va); if (Lf->sf) link_lfile(); } } #endif /* HPUXV>=800 */ lsof-4.86+dfsg.orig/dialects/hpux/kmem/dproto.h0000444000175000017500000000437207212724623021654 0ustar nicholasnicholas/* * dproto.h - /dev/kmem-based HP-UX function prototypes for lsof * * The _PROTOTYPE macro is defined in the common proto.h. */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: dproto.h,v 1.7 2000/12/04 14:26:14 abe Exp $ */ #if HPUXV>=800 _PROTOTYPE(extern void completevfs,(struct l_vfs *vfs, dev_t *dev, struct vfs *v)); #else _PROTOTYPE(extern void completevfs,(struct l_vfs *vfs, dev_t *dev)); #endif /* HPUXV>=800 */ _PROTOTYPE(extern int is_file_named,(char *p, int cd)); _PROTOTYPE(extern int get_max_fd,(void)); #if defined(DTYPE_LLA) _PROTOTYPE(extern void process_lla,(KA_T la)); #endif _PROTOTYPE(extern struct l_vfs *readvfs,(struct vnode *lv)); #if HPUXV>=1030 _PROTOTYPE(extern void process_stream_sock,(KA_T ip, KA_T pcb, char *pn, enum vtype vt)); _PROTOTYPE(extern int read_mi,(KA_T sh, KA_T *ip, KA_T *pcb, char **pn)); #endif /* HPUXV>=1030 */ #if defined(HAS_AFS) _PROTOTYPE(extern struct vnode *alloc_vcache,(void)); _PROTOTYPE(extern void ckAFSsym,(struct nlist *nl)); _PROTOTYPE(extern int hasAFS,(struct vnode *vp)); _PROTOTYPE(extern int readafsnode,(KA_T va, struct vnode *v, struct afsnode *an)); #endif /* defined(HAS_AFS) */ #if defined(HASVXFS) _PROTOTYPE(extern int read_vxnode,(struct vnode *v, struct l_vfs *vfs, dev_t *dev, int *devs, dev_t *rdev, int *rdevs)); #endif /* defined(HASVXFS) */ lsof-4.86+dfsg.orig/dialects/hpux/kmem/dlsof.h0000444000175000017500000002331010613427574021451 0ustar nicholasnicholas/* * 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 # endif /* HPUXV>=1030 */ #include #include #include #include #include #include #include # if HPUXV<1020 #include # 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 # if HPUXV>=1020 #define _INCLUDE_STRUCT_FILE # endif /* HPUXV>=1020 */ # if HPUXV>=1030 struct uio { /* to satisfy function prototypes in */ int dummy; }; # endif /* HPUXV>=1030 */ #include # if HPUXV>=1020 #undef _INCLUDE_STRUCT_FILE # endif /* HPUXV>=1020 */ # if HPUXV>=1030 #include #include "sth.h" # endif /* HPUXV>=1030 */ #include # if HPUXV>=800 #undef _PROTOTYPES #include # endif /* HPUXV>=800 */ #include # if HPUXV<1010 #include # endif /* HPUXV<1010 */ #include #include #include #include #include # if HPUXV<1030 #include #include # endif /* HPUXV<1030 */ #include #include #include # if HPUXV<1030 #include #include #include # else /* HPUXV>=1030 */ #include /* * 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 #include #include # if HPUXV>=1030 #include # endif /* HPUXV>=1030 */ # if HPUXV>=1000 #include #include #include #include #include #include # endif /* HPUXV>=1000 */ #include /* * 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 # if defined(HASRNODE3) /* * This rnode structure definition should come from , 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 . * * 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 # endif /* defined(HASRNODE3) */ # endif /* HPUXV<1030 */ #include # if HPUXV>=1000 #define _KERNEL #include #undef _KERNEL # endif /* HPUXV>=1000 */ # if defined(DTYPE_LLA) && HPUXV<1030 #define _KERNEL 1 #include #undef _KERNEL # endif /* defined(DTYPE_LLA) && HPUXV<1030 */ #include #include #include #include #include /* * The hpux_mount.h header file is manufactured from by the * Configure script to get the mount structure without needing to define * _KERNEL when including . Defining _KERNEL causes unresolvable * header file complications. */ #include "hpux_mount.h" # if HPUXV>=800 /* * These definitions are from , defined under the _KERNEL symbol. * Unfortunately, defining _KERNEL causes to include other * header files not in . */ #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 # if HPUXV<1000 #define ADDR_NCACHE 1 # endif /* HPUXV<1000 */ # endif /* defined(HASNCACHE) */ #endif /* HPUX_LSOF_H */ lsof-4.86+dfsg.orig/dialects/hpux/kmem/dnode1.c0000444000175000017500000000776010275733607021523 0ustar nicholasnicholas/* * dnode1.c - /dev/kmem-based HP-UX node functions for lsof * * This module must be separate to keep separate the multiple kernel inode * structure definitions. */ /* * Copyright 1995 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dnode1.c,v 1.11 2005/08/08 19:50:23 abe Exp $"; #endif #if defined(HASVXFS) # if defined(HPUXKERNBITS) && HPUXKERNBITS>=64 #define _INO_T typedef int ino_t; #define _TIME_T typedef int time_t; # endif /* defined(HPUXKERNBITS) && HPUXKERNBITS>=64 */ #include "lsof.h" /* * HP-UX versions below 10.20: * * The pool_id_t type does not seem to be defined in the header files * distributed by HP. However, requires it when * _KERNEL is defined. So we fake the pool_id_t definition. * * also requires sv_sema_t. It's defined in * when _KERNEL is defined, but some other header file has * already included 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 conflict */ # endif /* HPUXV>=1030 */ #include #include #include # 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 #include #undef _KERNEL # endif /* HPUXV>=1020 */ /* * read_vxnode() - read Veritas file system inode information */ int read_vxnode(v, vfs, dev, devs, rdev, rdevs) struct vnode *v; /* local containing vnode */ struct l_vfs *vfs; /* local vfs structure */ dev_t *dev; /* device number receiver */ int *devs; /* device status receiver */ dev_t *rdev; /* raw device number receiver */ int *rdevs; /* raw device status receiver */ { struct vx_inode i; if (!v->v_data || kread((KA_T)v->v_data, (char *)&i, sizeof(i))) return(1); /* * Return device numbers. */ if (vfs && vfs->fsname) *dev = vfs->dev; else *dev = i.i_dev; *devs = 1; if ((v->v_type == VCHR) || (v->v_type == VBLK)) { *rdev = v->v_rdev; *rdevs = 1; } /* * Record inode number. */ Lf->inode = (INODETYPE)i.i_number; Lf->inp_ty = 1; /* * Record size. */ if (Foffset || ((v->v_type == VCHR || v->v_type == VBLK) && !Fsize)) Lf->off_def = 1; else { Lf->sz = (SZOFFTYPE)i.i_size; Lf->sz_def = 1; } /* * Record link count. */ if (Fnlink) { Lf->nlink = (long)i.i_nlink; Lf->nlink_def = 1; if (Nlink && (Lf->nlink < Nlink)) Lf->sf |= SELNLINK; } return(0); } #endif /* defined(HASVXFS) */ lsof-4.86+dfsg.orig/dialects/hpux/kmem/Mksrc0000555000175000017500000000110306711421752021166 0ustar nicholasnicholas#!/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 lsof-4.86+dfsg.orig/dialects/hpux/kmem/dnode.c0000444000175000017500000005464010613427576021442 0ustar nicholasnicholas/* * dnode.c - /dev/kmem-based HP-UX node functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dnode.c,v 1.21 2007/04/24 16:25:30 abe Exp $"; #endif #if defined(HPUXKERNBITS) && HPUXKERNBITS>=64 #define _INO_T typedef int ino_t; #define _TIME_T typedef int time_t; #endif /* defined(HPUXKERNBITS) && HPUXKERNBITS>=64 */ #include "lsof.h" #include #if HPUXV>=900 _PROTOTYPE(static void enter_nma,(char *b)); _PROTOTYPE(static int islocked,(KA_T lp)); #endif /* HPUXV>=900 */ _PROTOTYPE(static int getnodety,(struct vnode *v)); _PROTOTYPE(static int readinode,(KA_T ia, struct inode *i)); _PROTOTYPE(static int read_nmn,(KA_T na, KA_T ia, struct mvfsnode *m)); #if HPUXV>=900 /* * enter_nma() - enter NAME column addition */ static void enter_nma(b) char *b; /* addition buffer */ { if (Lf->nma) return; if (strlen(b) < 1) return; Lf->nma = mkstrcpy(b, (MALLOC_S *)NULL); } /* * islocked() - is node locked? */ static int islocked(lp) KA_T lp; /* local locklist struct pointer */ { static int ety = -1; static unsigned int ei = 0; static SZOFFTYPE el = 0; int l; struct locklist ll; KA_T llf, llp; if (!(llf = (KA_T)lp)) return((int)' '); llp = llf; /* * Compute the end test value the first time through. */ if (ety == -1) { # if HPUXV<1020 ety = 0; ei = 0x7fffffff; # else /* HPUXV>=1020 */ if (sizeof(ll.ll_end) == 4) { ety = 0; ei = 0x80000000; } else { ety = 1; el = 0x10000000000ll; } # endif /* HPUXV<1020 */ } /* * Search the locklist chain for this process. */ do { if (kread(llp, (char *)&ll, sizeof(ll))) return((int)' '); #if !defined(L_REMOTE) #define L_REMOTE 0x1 /* from HP-UX 9.01 */ #endif /* !defined(L_REMOTE) */ # if HPUXV<1010 if (ll.ll_flags & L_REMOTE || ll.ll_proc != (KA_T)Kpa) # else /* HPUXV>=1010 */ if (ll.ll_flags & L_REMOTE || (KA_T)ll.ll_kthreadp != Ktp) # endif /* HPUXV<1010 */ continue; l = 0; if (ll.ll_start == 0) { switch (ety) { case 0: if (ll.ll_end == ei) l = 1; break; case 1: if (ll.ll_end == el) l = 1; break; } } if (ll.ll_type == F_WRLCK) return((int)(l ? 'W' : 'w')); else if (ll.ll_type == F_RDLCK) return((int)(l ? 'R' : 'r')); return((int)' '); } # if HPUXV<1010 while ((llp = (KA_T)ll.ll_link) && llp != llf); # else /* HPUXV>=1010 */ while ((llp = (KA_T)ll.ll_fwd) && llp != llf); # endif /* HPUXV<1010 */ return((int)' '); } #endif /* HPUXV>=900 */ /* * getnodety() - get node type */ static int getnodety(v) struct vnode *v; /* local vnode copy */ { #if defined(HAS_AFS) static int afs = 0; /* AFS test status: -1 = no AFS * 0 = not tested * 1 = AFS present */ struct afsnode an; #endif /* defined(HAS_AFS) */ static int ft = 1; static KA_T avops; static KA_T cvops; static KA_T fvops; static KA_T mvops; static KA_T nvops; static KA_T nvops3; static KA_T nv3ops; static KA_T pvops; static KA_T svops; static KA_T uvops; static KA_T vvops; /* * Do first-time only operations. */ if (ft) { if (get_Nl_value("avops", Drive_Nl, &avops) < 0) avops = (unsigned long)0; if (get_Nl_value("cvops", Drive_Nl, &cvops) < 0) cvops = (unsigned long)0; if (get_Nl_value("fvops", Drive_Nl, &fvops) < 0) fvops = (unsigned long)0; if (get_Nl_value("mvops", Drive_Nl, &mvops) < 0) mvops = (unsigned long)0; if (get_Nl_value("nvops", Drive_Nl, &nvops) < 0) nvops = (unsigned long)0; if (get_Nl_value("nvops3", Drive_Nl, &nvops3) < 0) nvops3 = (unsigned long)0; if (get_Nl_value("nv3ops", Drive_Nl, &nv3ops) < 0) nv3ops = (unsigned long)0; if (get_Nl_value("pvops", Drive_Nl, &pvops) < 0) pvops = (unsigned long)0; if (get_Nl_value("svops", Drive_Nl, &svops) < 0) svops = (unsigned long)0; if (get_Nl_value("uvops", Drive_Nl, &uvops) < 0) uvops = (unsigned long)0; if (get_Nl_value("vvops", Drive_Nl, &vvops) < 0) vvops = (unsigned long)0; ft = 0; } /* * Determine the vnode type. */ if (uvops && uvops == (unsigned long)v->v_op) return(N_REGLR); else if (nvops && nvops == (unsigned long)v->v_op) return(N_NFS); else if (nvops3 && nvops3 == (unsigned long)v->v_op) return(N_NFS); else if (nv3ops && nv3ops == (unsigned long)v->v_op) return(N_NFS); else if (mvops && mvops == (unsigned long)v->v_op) return(N_MVFS); #if defined(HASVXFS) else if (vvops && vvops == (unsigned long)v->v_op) return(N_VXFS); #endif /* defined(HASVXFS) */ #if HPUXV>=1000 else if (cvops && cvops == (unsigned long)v->v_op) return(N_CDFS); else if (fvops && fvops == (unsigned long)v->v_op) return(N_FIFO); else if (pvops && pvops == (unsigned long)v->v_op) return(N_PIPE); else if (svops && svops == (unsigned long)v->v_op) return(N_SPEC); #else /* HPUXV<1000 */ else if (v->v_type == VFIFO) return(N_FIFO); #endif /* HPUXV<1000 */ #if defined(HAS_AFS) /* * Caution: this AFS test should be the last one. */ else if (avops) { if (avops == (unsigned long)v->v_op) return(N_AFS); else { unknown_v_op: (void) snpf(Namech, Namechl, "unknown file system type; v_op: %s", print_kptr((KA_T)v->v_op, (char *)NULL, 0)); enter_nm(Namech); return(-1); } } else if (v->v_data || !v->v_vfsp) goto unknown_v_op; else { switch (afs) { case -1: goto unknown_v_op; case 0: if (!hasAFS(v)) { afs = -1; goto unknown_v_op; } afs = 1; return(N_AFS); break; case 1: if (v->v_vfsp == AFSVfsp) return(N_AFS); else goto unknown_v_op; } } #else /* !defined(HAS_AFS) */ else { (void) snpf(Namech, Namechl, "unknown file system type; v_op: %s", print_kptr((KA_T)v->v_op, (char *)NULL, 0)); enter_nm(Namech); return(-1); } #endif /* defined(HAS_AFS) */ } /* * process_node() - process vnode */ void process_node(va) KA_T va; /* vnode kernel space address */ { #if defined(HAS_AFS) struct afsnode an; #endif /* defined(HAS_AFS) */ dev_t dev, rdev; int devs = 0; struct inode i; int ins = 0; struct mvfsnode m; struct rnode r; int rdevs = 0; int rns = 0; char tbuf[32], *ty; enum vtype type; static struct vnode *v = (struct vnode *)NULL; struct l_vfs *vfs; int vty; #if HPUXV>=900 char fb[128]; int fns = 0; int rp, sz, wp; struct vnode rv; struct snode s; #endif /* HPUXV>=900 */ #if HPUXV>=1000 struct cdnode c; struct fifonode f; struct vattr vat; int vats = 0; #endif /* HPUXV>=1000 */ /* * Read the vnode. */ if ( ! va) { enter_nm("no vnode address"); return; } if (!v) { /* * Allocate space for the vnode or AFS vcache structure. */ #if defined(HAS_AFS) v = alloc_vcache(); #else /* !defined(HAS_AFS) */ v = (struct vnode *)malloc(sizeof(struct vnode)); #endif /* defined(HAS_AFS) */ if (!v) { (void) fprintf(stderr, "%s: can't allocate %s space\n", Pn, #if defined(HAS_AFS) "vcache" #else /* !defined(HAS_AFS) */ "vnode" #endif /* defined(HAS_AFS) */ ); Exit(1); } } if (readvnode(va, v)) { enter_nm(Namech); return; } #if defined(HASNCACHE) Lf->na = va; #endif /* defined(HASNCACHE) */ #if defined(HASFSTRUCT) Lf->fna = va; Lf->fsv |= FSV_NI; #endif /* defined(HASFSTRUCT) */ /* * Get the primary vnode type. */ vty = getnodety(v); if (vty == -1) return; Ntype = vty; /* * Determine lock type. */ #if HPUXV<900 if (v->v_shlockc || v->v_exlockc) { if (v->v_shlockc && v->v_exlockc) Lf->lock = 'u'; else if (v->v_shlockc) Lf->lock = 'R'; else Lf->lock = 'W'; } #else /* HPUXV>900 */ # if HPUXV>=1000 Lf->lock = (char)islocked((KA_T)v->v_locklist); # endif /* HPUXV>=1000 */ #endif /* HPUXV<900 */ /* * Establish the local virtual file system structure. */ if (!v->v_vfsp) vfs = (struct l_vfs *)NULL; else if (!(vfs = readvfs(v))) { (void) snpf(Namech, Namechl, "can't read vfs for %s at %s", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)v->v_vfsp, (char *)NULL, 0)); enter_nm(Namech); return; } /* * Read the cdnode, fifonode, inode, rnode, snode, or vache struct. */ switch (Ntype) { #if defined(HAS_AFS) case N_AFS: if (readafsnode(va, v, &an)) return; break; #endif /* defined(HAS_AFS) */ #if defined(HASVXFS) case N_VXFS: if (!v->v_data || read_vxnode(v, vfs, &dev, &devs, &rdev, &rdevs)) { (void) snpf(Namech, Namechl, "vnode at %s: can't read vx_inode (%s)", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } break; #endif /* defined(HASVXFS) */ #if HPUXV>=1000 case N_CDFS: if (!v->v_data || kread((KA_T)v->v_data, (char *)&c, sizeof(c))) { (void) snpf(Namech, Namechl, "vnode at %s: can't read cdnode (%s)", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } break; case N_FIFO: case N_PIPE: if (!v->v_data || kread((KA_T)v->v_data, (char *)&f, sizeof(f))) { (void) snpf(Namech, Namechl, "vnode at %s: can't read fifonode (%s)", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } fns = 1; if (f.fn_vap && kread((KA_T)f.fn_vap, (char *)&vat, sizeof(vat)) == 0) vats = 1; break; #endif /* HPUXV>=1000 */ case N_MVFS: if (read_nmn(va, (KA_T)v->v_data, &m)) return; break; case N_NFS: if (!v->v_data || readrnode((KA_T)v->v_data, &r)) { (void) snpf(Namech, Namechl, "vnode at %s: can't read rnode (%s)", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } rns = 1; break; #if HPUXV>=1000 case N_SPEC: if ((v->v_type == VBLK) || (v->v_type == VCHR)) { if (!v->v_data || readsnode((KA_T)v->v_data, &s)) { (void) snpf(Namech, Namechl, "vnode at %s: can't read snode(%s)", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } if (!s.s_realvp || readvnode((KA_T)s.s_realvp, &rv)) { (void) snpf(Namech, Namechl, "snode at %s: can't read real vnode (%s)", print_kptr((KA_T)v->v_data, tbuf, sizeof(tbuf)), print_kptr((KA_T)s.s_realvp, (char *)NULL, 0)); enter_nm(Namech); return; } #if defined(HASVXFS) if (getnodety(&rv) == N_VXFS) { if (!rv.v_data || read_vxnode(&rv, vfs, &dev, &devs, &rdev, &rdevs)) { (void) snpf(Namech, Namechl, "vnode at %s: can't read vx_inode (%s)", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)rv.v_data, (char *)NULL, 0)); enter_nm(Namech); return; } Ntype = N_VXFS; break; } #endif /* defined(HASVXFS) */ if (!rv.v_data || readinode((KA_T)rv.v_data, &i)) { (void) snpf(Namech, Namechl, "snode at %s: can't read inode (%s)", print_kptr((KA_T)v->v_data, tbuf, sizeof(tbuf)), print_kptr((KA_T)rv.v_data, (char *)NULL, 0)); enter_nm(Namech); return; } ins = 1; break; } if (!v->v_data || readinode((KA_T)v->v_data, &i)) { (void) snpf(Namech, Namechl, "vnode at %s: can't read inode (%s)", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } ins = 1; break; #endif /* HPUXV>=1000 */ #if HPUXV>=900 && HPUXV<1000 case N_FIFO: if (v->v_fstype == VNFS_FIFO) { if (!v->v_data || readsnode((KA_T)v->v_data, &s)) { (void) snpf(Namech, Namechl, "vnode at %s: can't read snode (%s)", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } if (!s.s_realvp || readvnode((KA_T)s.s_realvp, &rv)) { (void) snpf(Namech, Namechl, "snode at %s: can't read real vnode (%s)", print_kptr((KA_T)v->v_data, tbuf, sizeof(tbuf)), print_kptr((KA_T)s.s_realvp, (char *)NULL, 0)); enter_nm(Namech); return; } if (!rv.v_data || readrnode((KA_T)rv.v_data, &r)) { (void) snpf(Namech, Namechl, "snode at %s: can't read real rnode (%s)", print_kptr((KA_T)v->v_data, tbuf, sizeof(tbuf)), print_kptr((KA_T)s.s_realvp, (char *)NULL, 0)); enter_nm(Namech); return; } rns = 1; break; } /* fall through */ #endif /* HPUXV>=900 && HPUXV<1000 */ case N_REGLR: default: if (!v->v_data || readinode((KA_T)v->v_data, &i)) { (void) snpf(Namech, Namechl, "vnode at %s: can't read inode (%s)", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)v->v_data, (char *)NULL, 0)); enter_nm(Namech); return; } ins = 1; #if HPUXV>=900 && HPUXV<1000 if (v->v_type == VFIFO) Ntype = N_FIFO; #endif /* HPUXV>=900 && HPUXV<1000 */ } #if HPUXV>=900 && HPUXV<1000 Lf->lock = (char)islocked((KA_T)i.i_locklist); #endif /* HPUXV>=900 && HPUXV<1000 */ /* * Get device and type for printing. */ switch (Ntype) { #if defined(HAS_AFS) case N_AFS: dev = an.dev; devs = 1; break; #endif /* defined(HAS_AFS) */ case N_MVFS: if (vfs) { dev = vfs->dev; devs = 1; } break; case N_NFS: dev = vfs ? vfs->dev : 0; devs = 1; break; #if HPUXV>=1000 case N_CDFS: dev = c.cd_dev; devs = 1; break; case N_FIFO: case N_PIPE: if (vfs && vfs->fsname) { dev = vfs->dev; devs = 1; } else if (vats && (dev_t)vat.va_fsid != NODEV) { dev = (dev_t)vat.va_fsid; devs = 1; } else enter_dev_ch(print_kptr(va, (char *)NULL, 0)); break; #endif /* _HPUX>=1000 */ #if defined(HASVXFS) case N_VXFS: /* obtained via read_vxnode */ break; #endif /* defined(HASVXFS) */ case N_SPEC: default: #if HPUXV>=800 if (vfs && vfs->fsname) { dev = vfs->dev; devs = 1; } else if (ins) { dev = i.i_dev; devs = 1; } if ((v->v_type == VBLK) || (v->v_type == VCHR)) { rdev = v->v_rdev; rdevs = 1; } #else /* HPUXV<800 */ if (ins) { dev = i.i_dev; devs = 1; } if ((v->v_type == VCHR) || (v->v_type == VBLK)) { rdev = v->v_rdev; rdevs = 1; } #endif /* HPUXV>=800 */ } type = v->v_type; /* * Obtain the inode number. */ switch (Ntype) { #if defined(HAS_AFS) case N_AFS: if (an.ino_st) { Lf->inode = (INODETYPE)an.inode; Lf->inp_ty = 1; } break; #endif /* defined(HAS_AFS) */ case N_MVFS: Lf->inode = (INODETYPE)m.m_ino; Lf->inp_ty = 1; break; case N_NFS: #if HPUXV<1030 Lf->inode = (INODETYPE)r.r_nfsattr.na_nodeid; #else /* HPUXV>=1030 */ Lf->inode = (INODETYPE)r.r_attr.va_nodeid; #endif /* HPUXV<1030 */ Lf->inp_ty = 1; break; #if HPUXV>=1000 case N_CDFS: Lf->inode = (INODETYPE)c.cd_num; Lf->inp_ty = 1; break; case N_FIFO: case N_PIPE: if (vats) { Lf->inode = (INODETYPE)vat.va_nodeid; Lf->inp_ty = 1; } else { Lf->inode = (INODETYPE)v->v_nodeid; Lf->inp_ty = 1; } break; #endif /* HPUXV>=1000 */ #if defined(HASVXFS) case N_VXFS: /* set in read_vxnode() */ break; #endif /* defined(HASVXFS) */ #if HPUXV<1000 case N_FIFO: # if HPUXV>=900 if (rns) { Lf->inode = (INODETYPE)r.r_nfsattr.na_nodeid; Lf->inp_ty = 1; break; } # endif /* HPUXV>=900 */ /* fall through */ #endif /* HPUXV<1000 */ case N_BLK: case N_REGLR: case N_SPEC: if (ins) { Lf->inode = (INODETYPE)i.i_number; Lf->inp_ty = 1; } } #if HPUXV>=1030 /* * Check for an HP-UX 10.30 and above stream. */ if (v->v_stream) { KA_T ip, pcb; char *pn = (char *)NULL; Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; if (read_mi((KA_T)v->v_stream, &ip, &pcb, &pn)) return; if (ip && pcb) { process_stream_sock(ip, pcb, pn, type); return; } Lf->is_stream = 1; } #endif /* HPUXV>=1030 */ /* * Obtain the file size. */ if (Foffset) Lf->off_def = 1; else { switch (Ntype) { #if defined(HAS_AFS) case N_AFS: Lf->sz = (SZOFFTYPE)an.size; Lf->sz_def = 1; break; #endif /* defined(HAS_AFS) */ #if HPUXV>=1000 case N_CDFS: Lf->sz = (SZOFFTYPE)c.cd_cdc.cdc_size; Lf->sz_def = 1; break; case N_PIPE: if (vats) { Lf->sz = (SZOFFTYPE)vat.va_size; Lf->sz_def = 1; } break; #endif /* HPUXV>=1000 */ #if HPUXV>=900 case N_FIFO: # if HPUXV<1000 if (ins) { rp = i.i_frptr; sz = (int)i.i_fifosize; wp = i.i_fwptr; } else if (rns) Lf->sz = (SZOFFTYPE)r.r_nfsattr.na_size; # else /* HPUXV>=1000 */ if (fns) { rp = f.fn_rptr; sz = f.fn_size; wp = f.fn_wptr; } # endif /* HPUXV<1000 */ if (Fsize || (Lf->access != 'r' && Lf->access != 'w')) { if (fns || ins) { (void) snpf(fb, sizeof(fb), "rd=%#x; wr=%#x", rp, wp); (void) enter_nma(fb); } if (fns || ins || rns) { Lf->sz = (SZOFFTYPE)sz; Lf->sz_def = 1; } break; } if (fns || ins) { Lf->off = (unsigned long)((Lf->access == 'r') ? rp : wp); (void) snpf(fb, sizeof(fb), "%s=%#x", (Lf->access == 'r') ? "rd" : "wr", (Lf->access == 'r') ? rp : wp); (void) enter_nma(fb); } Lf->off_def = 1; break; #endif /* HPUXV>=900 */ case N_MVFS: /* The location of the file size isn't known. */ break; case N_NFS: #if HPUXV<1030 Lf->sz = (SZOFFTYPE)r.r_nfsattr.na_size; #else /* HPUXV>=1030 */ Lf->sz = (SZOFFTYPE)r.r_attr.va_size; #endif /* HPUXV<1030 */ Lf->sz_def = 1; break; #if defined(HASVXFS) case N_VXFS: /* set in read_vxnode() */ break; #endif /* defined(HASVXFS) */ case N_SPEC: case N_REGLR: if ((type == VCHR || type == VBLK) && !Fsize) Lf->off_def = 1; else if (ins) { Lf->sz = (SZOFFTYPE)i.i_size; Lf->sz_def = 1; } break; } } /* * Record link count. */ if (Fnlink) { switch(Ntype) { # if defined(HAS_AFS) case N_AFS: Lf->nlink = an.nlink; Lf->nlink_def = an.nlink_st; break; # endif /* defined(HAS_AFS) */ case N_MVFS: /* The location of the link count isn't known. */ break; case N_NFS: #if HPUXV<1030 Lf->nlink = r.r_nfsattr.na_nlink; #else /* HPUXV>=1030 */ Lf->nlink = r.r_attr.va_nlink; #endif /* HPUXV<1030 */ Lf->nlink_def = 1; break; # if HPUXV>=1000 case N_CDFS: /* no link count? */ break; # endif /* HPUXV>=1000 */ case N_FIFO: case N_PIPE: # if HPUXV>=1000 if (vats) { Lf->nlink = (long)vat.va_nlink; Lf->nlink_def = 1; } # endif /* HPUXV>=1000 */ break; # if defined(HASVXFS) case N_VXFS: /* set in read_vxnode() */ break; # endif /* defined(HASVXFS) */ case N_SPEC: default: if (ins) { Lf->nlink = (long)i.i_nlink; Lf->nlink_def = 1; } break; } if (Nlink && Lf->nlink_def && (Lf->nlink < Nlink)) Lf->sf |= SELNLINK; } /* * Record an NFS file selection. */ if (Ntype == N_NFS && Fnfs) Lf->sf |= SELNFS; /* * Save the file system names. */ if (vfs) { Lf->fsdir = vfs->dir; Lf->fsdev = vfs->fsname; #if defined(HASFSINO) Lf->fs_ino = vfs->fs_ino; #endif /* defined(HASFSINO) */ } /* * Save the device numbers and their states. * * Format the vnode type, and possibly the device name. */ Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; switch (type) { case VNON: ty ="VNON"; break; case VREG: case VDIR: ty = (type == VREG) ? "VREG" : "VDIR"; break; case VBLK: ty = "VBLK"; Ntype = N_BLK; break; case VCHR: ty = "VCHR"; Ntype = N_CHR; break; case VLNK: ty = "VLNK"; break; #if defined(VSOCK) case VSOCK: ty = "SOCK"; break; #endif /* defined(VSOCK) */ case VBAD: ty = "VBAD"; break; case VFIFO: switch (Ntype) { #if HPUXV>=1000 case N_FIFO: ty = "FIFO"; break; case N_PIPE: ty = "PIPE"; break; #endif /* HPUXV>=1000 */ default: ty = "FIFO"; } break; default: (void) snpf(Lf->type, sizeof(Lf->type), "%04o", (type & 0xfff)); ty = (char *)NULL; } if (ty) (void) snpf(Lf->type, sizeof(Lf->type), "%s", ty); Lf->ntype = Ntype; #if defined(HASBLKDEV) /* * If this is a VBLK file and it's missing an inode number, try to * supply one. */ if ((Lf->inp_ty == 0) && (type == VBLK)) find_bl_ino(); #endif /* defined(HASBLKDEV) */ /* * If this is a VCHR file and it's missing an inode number, try to * supply one. */ if ((Lf->inp_ty == 0) && (type == VCHR)) find_ch_ino(); /* * Test for specified file. */ if (Sfile && is_file_named((char *)NULL, ((type == VCHR) || (type == VBLK) ? 1 : 0))) Lf->sf |= SELNM; /* * Enter name characters. */ if (Namech[0]) enter_nm(Namech); } /* * readinode() - read inode */ static int readinode(ia, i) KA_T ia; /* inode kernel address */ struct inode *i; /* inode buffer */ { if (kread((KA_T)ia, (char *)i, sizeof(struct inode))) { (void) snpf(Namech, Namechl, "can't read inode at %s", print_kptr(ia, (char *)NULL, 0)); return(1); } return(0); } /* * read_nmn() - read node's mvfsnode */ static int read_nmn(na, ma, m) KA_T na; /* containing node's address */ KA_T ma; /* kernel mvfsnode address */ struct mvfsnode *m; /* mvfsnode receiver */ { char tbuf[32]; if (!ma || kread((KA_T)ma, (char *)m, sizeof(struct mvfsnode))) { (void) snpf(Namech, Namechl, "node at %s: can't read mvfsnode: %s", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr(ma, (char *)NULL, 0)); enter_nm(Namech); return(1); } return(0); } lsof-4.86+dfsg.orig/dialects/hpux/kmem/dfile.c0000444000175000017500000001424607336223476021433 0ustar nicholasnicholas/* * dfile.c - /dev/kmem-based HP-UX file processing functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dfile.c,v 1.14 2001/08/14 13:27:16 abe Exp $"; #endif #if defined(HPUXKERNBITS) && HPUXKERNBITS>=64 #define _TIME_T typedef int time_t; /* * CAUTION!!! CAUTION!!! CAUTION!!! CAUTION!!! CAUTION!!! CAUTION!!! * * Do NOT: * * #define INO_T * typedef int ino_t; * * in this source file for HP-UX >= 10.30. Doing so will cause the kernel's * ino_t type to be erroneously used instead of the application's. * * CAUTION!!! CAUTION!!! CAUTION!!! CAUTION!!! CAUTION!!! CAUTION!!! */ #endif /* defined(HPUXKERNBITS) && HPUXKERNBITS>=64 */ #include "lsof.h" /* * get_max_fd() - get maximum file descriptor plus one */ int get_max_fd() { struct rlimit r; if (getrlimit(RLIMIT_NOFILE, &r)) return(-1); return(r.rlim_cur); } /* * print_dev() - print device */ char * print_dev(lf, dev) struct lfile *lf; /* file whose device is to be printed */ dev_t *dev; /* device to be printed */ { static char buf[128]; (void) snpf(buf, sizeof(buf), "%d,%#x", GET_MAJ_DEV(*dev), GET_MIN_DEV(*dev)); return(buf); } /* * process_file() - process file */ void process_file(fp) KA_T fp; /* kernel file structure address */ { struct file f; int flag; if (kread((KA_T)fp, (char *)&f, sizeof(f))) { (void) snpf(Namech, Namechl, "can't read file struct from %s", print_kptr(fp, (char *)NULL, 0)); enter_nm(Namech); return; } Lf->off = (SZOFFTYPE)f.f_offset; if (f.f_count) { #if defined(HASFSTRUCT) /* * Save file structure values. */ if (Fsv & FSV_CT) { Lf->fct = (long)f.f_count; Lf->fsv |= FSV_CT; } if (Fsv & FSV_FA) { Lf->fsa = fp; Lf->fsv |= FSV_FA; } if (Fsv & FSV_FG) { Lf->ffg = (long)f.f_flag; Lf->fsv |= FSV_FG; } if (Fsv & FSV_NI) { Lf->fna = (KA_T)f.f_data; Lf->fsv |= FSV_NI; } #endif /* defined(HASFSTRUCT) */ /* * Construct access code. */ if ((flag = (f.f_flag & (FREAD | FWRITE))) == FREAD) Lf->access = 'r'; else if (flag == FWRITE) Lf->access = 'w'; else if (flag == (FREAD | FWRITE)) Lf->access = 'u'; /* * Process structure by its type. */ switch (f.f_type) { #if defined(DTYPE_LLA) case DTYPE_LLA: process_lla((KA_T)f.f_data); return; #endif /* DTYPE_LLA */ case DTYPE_VNODE: process_node((KA_T)f.f_data); return; case DTYPE_SOCKET: process_socket((KA_T)f.f_data); return; default: if (!f.f_type || (f.f_ops && (KA_T)f.f_ops != Vnfops)) { (void) snpf(Namech, Namechl, "%s file struct, ty=%#x, op=%#x", print_kptr(fp, (char *)NULL, 0), f.f_type, f.f_ops); enter_nm(Namech); return; } } } enter_nm("no more information"); } #if HPUXV>=1030 /* * read_mi() - read stream's module information * * Note: this function is included in this module, because ino_t is not * redfined to the kernel's type, but is left at the application's type. * See the CAUTION statement inside the HPUXKERNBITS>=64 #if/#endif * block at the beginning of this file. */ int read_mi(sh, ip, pcb, pn) KA_T sh; /* stream head address */ KA_T *ip; /* returned IP q_ptr */ KA_T *pcb; /* returned TCP or UDP q_ptr */ char **pn; /* returned protocol name */ { struct l_dev *dp; char *ep = Namech; struct sth_s hd; int i; size_t len, ml; char mn[32]; KA_T ka, qa; struct module_info mi; struct queue q; struct qinit qi; size_t sz = Namechl; if (!sh || kread(sh, (char *)&hd, sizeof(hd))) { (void) snpf(Namech, Namechl, "can't read stream head: %s", print_kptr(sh, (char *)NULL, 0)); return(1); } if (!Lf->rdev_def) dp = (struct l_dev *)NULL; else dp = lkupdev(&DevDev, &Lf->rdev, 1, 0); if (dp) (void) snpf(ep, sz, "%s", dp->name); else *ep = '\0'; /* * Follow the stream head to each of its queue structures, retrieving the * module names for each queue's q_info->qi_minfo->mi_idname chain of * structures. Separate each additional name from the previous one with * "->". * * Ignore failures to read all but queue structure chain entries. * * Ignore module names that end in "head". * * Save the q_ptr value for "tcp" and "udp" modules. */ ml = sizeof(mn) - 1; mn[ml] = '\0'; *ip = *pcb = (KA_T)NULL; qa = (KA_T)hd.sth_wq; for (i = 0; i < 20; i++, qa = (KA_T)q.q_next) { if (!qa || kread(qa, (char *)&q, sizeof(q))) break; if (!(ka = (KA_T)q.q_qinfo) || kread(ka, (char *)&qi, sizeof(qi))) continue; if (!(ka = (KA_T)qi.qi_minfo) || kread(ka, (char *)&mi, sizeof(mi))) continue; if (!(ka = (KA_T)mi.mi_idname) || kread(ka, mn, ml)) continue; if ((len = strlen(mn)) < 1) continue; if (len >= 3 && !strcmp(&mn[len - 3], "sth")) continue; ep = endnm(&sz); (void) snpf(ep, sz, "%s%s", (ep == Namech) ? "" : "->", mn); if (!q.q_ptr) continue; if (!*ip && !strcmp(mn, "ip")) { *ip = (KA_T)q.q_ptr; continue; } if (!*pcb && !strcmp(mn, "tcpm")) { *pcb = (KA_T)q.q_ptr; *pn = "TCP"; continue; } if (!*pcb && !strcmp(mn, "udpm")) { *pcb = (KA_T)q.q_ptr; *pn = "UDP"; } } return(0); } #endif /* HPUXV>=1030 */ lsof-4.86+dfsg.orig/dialects/hpux/kmem/dmnt.c0000444000175000017500000001277210275733606021311 0ustar nicholasnicholas/* * dmnt.c - /dev/kmem-based HP-UX mount support functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dmnt.c,v 1.8 2005/08/08 19:50:23 abe Exp $"; #endif #if defined(HPUXKERNBITS) && HPUXKERNBITS>=64 #define _TIME_T typedef int time_t; #endif /* defined(HPUXKERNBITS) && HPUXKERNBITS>=64 */ #include "lsof.h" /* * Local static definitions */ static struct mounts *Lmi = (struct mounts *)NULL; /* local mount info */ /* * completevfs() - complete local vfs structure */ void #if HPUXV>=800 completevfs(vfs, dev, v) struct l_vfs *vfs; /* local vfs structure pointer */ dev_t *dev; /* device */ struct vfs *v; /* kernel vfs structure */ #else /* HPUXV<800 */ completevfs(vfs, dev) struct l_vfs *vfs; /* local vfs structure pointer */ dev_t *dev; /* device */ #endif /* HPUXV>=800 */ { struct mounts *mp; /* * If only Internet socket files are selected, don't bother completing the * local vfs structure. */ if (Selinet) return; #if HPUXV>=800 /* * On HP-UX 8 and above, first search the local mount table for a match on * the file system name from the vfs structure. */ if (v) { for (mp = readmnt(); mp; mp = mp->next) { if (strcmp(mp->fsname, v->vfs_name) == 0) { vfs->dev = mp->dev; vfs->dir = mp->dir; vfs->fsname = mp->fsname; # if defined(HASFSINO) vfs->fs_ino = mp->inode; # endif /* defined(HASFSINO) */ return; } } } #endif /* HPUXV>=800 */ /* * Search for a match on device number. */ for (mp = readmnt(); mp; mp = mp->next) { if (mp->dev == *dev) { vfs->dev = mp->dev; vfs->dir = mp->dir; vfs->fsname = mp->fsname; #if defined(HASFSINO) vfs->fs_ino = mp->inode; #endif /* defined(HASFSINO) */ return; } } #if HPUXV>=800 /* * If the file system name and device number searches fail, use the * vfs structure name, if there is one. Determine the device number * with statsafely(). */ if (v && v->vfs_name[0]) { struct stat sb; if (!(vfs->dir = mkstrcpy(v->vfs_name, (MALLOC_S *)NULL))) { (void) fprintf(stderr, "%s: no space for vfs name: ", Pn); safestrprt(v->vfs_name, stderr, 1); Exit(1); } if (statsafely(v->vfs_name, &sb) == 0) vfs->dev = sb.st_dev; else vfs->dev = (dev_t)0; # if defined(HASFSINO) vfs->fs_ino = (INODETYPE)0; # endif /* defined(HASFSINO) */ } #endif /* HPUXV>=800 */ } /* * readvfs() - read vfs structure */ struct l_vfs * readvfs(lv) struct vnode *lv; /* local vnode */ { struct mount m; struct mntinfo mi; int ms; dev_t td; struct vfs v; struct l_vfs *vp; if (!lv->v_vfsp) return((struct l_vfs *)NULL); for (vp = Lvfs; vp; vp = vp->next) { if ((KA_T)lv->v_vfsp == vp->addr) return(vp); } if ((vp = (struct l_vfs *)malloc(sizeof(struct l_vfs))) == NULL) { (void) fprintf(stderr, "%s: PID %d, no space for vfs\n", Pn, Lp->pid); Exit(1); } vp->dev = 0; vp->dir = (char *)NULL; vp->fsname = (char *)NULL; #if defined(HASFSINO) vp->fs_ino = 0; #endif /* defined(HASFSINO) */ if (lv->v_vfsp && kread((KA_T)lv->v_vfsp, (char *)&v, sizeof(v))) { (void) free((FREE_P *)vp); return((struct l_vfs *)NULL); } /* * Complete the mount information. */ if (Ntype == N_NFS) { /* * The device number for an NFS file is found by following the vfs * private data pointer to an mntinfo structure. */ if (v.vfs_data && kread((KA_T)v.vfs_data, (char *)&mi, sizeof(mi)) == 0) { #if HPUXV<1020 td = (dev_t)makedev(255, (int)mi.mi_mntno); #else /* HPUXV>=1020 */ td = mi.mi_mntno; #endif /* HPUXV<1020 */ #if HPUXV>=800 (void) completevfs(vp, &td, (struct vfs *)NULL); #else /* HPUXV<800 */ (void) completevfs(vp, &td); #endif /* HPUXV>=800 */ } } else { if (v.vfs_data) { if (kread((KA_T)v.vfs_data, (char *)&m, sizeof(m)) == 0) ms = 1; else ms = 0; } #if defined(HAS_AFS) /* * Fake the device number for an AFS device. */ else if (Ntype == N_AFS) { m.m_dev = AFSDEV; ms = 1; } #endif /* defined(HAS_AFS) */ else ms = 0; if (ms) #if HPUXV>=800 # if HPUXV<1000 (void) completevfs(vp, (dev_t *)&m.m_dev, &v); # else /* HPUXV>=1000 */ (void) completevfs(vp, v.vfs_dev ? (dev_t *)&v.vfs_dev : (dev_t *)&m.m_dev, &v); # endif /* HPUXV<1000 */ #else /* HPUXV<800 */ (void) completevfs(vp, (dev_t *)&m.m_dev); #endif /* HPUXV>=800 */ } /* * Complete local vfs structure and link to the others. */ vp->next = Lvfs; vp->addr = (KA_T)lv->v_vfsp; Lvfs = vp; return(vp); } lsof-4.86+dfsg.orig/dialects/hpux/kmem/dnode2.c0000444000175000017500000002073610275733610021514 0ustar nicholasnicholas/* * dnode2.c - /dev/kmem-based HP-UX AFS support */ /* * Copyright 1996 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1996 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dnode2.c,v 1.7 2005/08/08 19:50:23 abe Exp $"; #endif #if defined(HAS_AFS) # if defined(HPUXKERNBITS) && HPUXKERNBITS>=64 #define _INO_T typedef int ino_t; #define _TIME_T typedef int time_t; # endif /* defined(HPUXKERNBITS) && HPUXKERNBITS>=64 */ #include "lsof.h" #include #include #undef __dontcare__ #include #include /* * 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 #undef KERNEL /* * Local function prototypes */ _PROTOTYPE(static struct volume *getvolume,(struct VenusFid *f, int *vols)); _PROTOTYPE(static int is_rootFid,(struct vcache *vc, int *rfid)); /* * alloc_vcache() - allocate space for vcache structure */ struct vnode * alloc_vcache() { return((struct vnode *)malloc(sizeof(struct vcache))); } /* * ckAFSsym() - check for missing X_AFS_* symbols in AFS name list file */ void ckAFSsym(nl) struct nlist *nl; /* copy of Nl[] when empty */ { char *path = AFSAPATHDEF; int i; # if defined(HASAOPT) if (AFSApath) path = AFSApath; # endif /* defined(HASAOPT) */ /* * See if the alternate AFS name list file can be read. */ if (!is_readable(path, 0)) { if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: can't access AFS name list file: %s\n", Pn, path); return; } /* * Read the AFS modload symbols and compare its non-zero values with * the non-zero values in Nl[]. Quit if there is any mis-match. */ if (nlist(path, nl) < 0) return; for (i = 0; Nl[i].n_name && Nl[i].n_name[0]; i++) { if (!nl[i].n_value || !Nl[i].n_value) continue; if (nl[i].n_value != Nl[i].n_value) return; } /* * If any X_AFS_* symbol that doesn't have a value in Nl[] has one from * the AFS modload file, copy its modload value to Nl[]. */ if (((i = get_Nl_value("arFid", Drive_Nl, NULL)) >= 0) && !Nl[i].n_value && nl[i].n_value) Nl[i].n_value = nl[i].n_value; if (((i = get_Nl_value("avops", Drive_Nl, NULL)) >= 0) && !Nl[i].n_value && nl[i].n_value) Nl[i].n_value = nl[i].n_value; if (((i = get_Nl_value("avol", Drive_Nl, NULL)) >= 0) && !Nl[i].n_value && nl[i].n_value) Nl[i].n_value = nl[i].n_value; } /* * getvolume() - get volume structure */ static struct volume * getvolume(f, vols) struct VenusFid *f; /* file ID pointer */ int *vols; /* afs_volumes status return */ { int i; static KA_T ka = 0; KA_T kh; static struct volume v; struct volume *vp; static int w = 0; if (!ka) { if (get_Nl_value("avol", Drive_Nl, (unsigned long *)&ka) < 0 || !ka) { if (!w && !Fwarn) { (void) fprintf(stderr, "%s: WARNING: no afs_volumes kernel address\n", Pn); (void) fprintf(stderr, " This may hamper AFS node number reporting.\n"); w = 1; } *vols = 0; return((struct volume *)NULL); } } *vols = 1; i = (NVOLS - 1) & f->Fid.Volume; kh = (KA_T)((char *)ka + (i * sizeof(struct volume *))); if (kread(kh, (char *)&vp, sizeof(vp))) return((struct volume *)NULL); while (vp) { if (kread((KA_T)vp, (char *)&v, sizeof(v))) return((struct volume *)NULL); if (v.volume == f->Fid.Volume && v.cell == f->Cell) return(&v); vp = v.next; } return((struct volume *)NULL); } /* * hasAFS() - test for AFS presence via vfs structure */ int hasAFS(vp) struct vnode *vp; /* vnode pointer */ { struct vfs v; /* * If this vnode has a v_data pointer, then it probably isn't an AFS vnode; * return FALSE. * * If the vfs struct address of /afs is known and this vnode's v_vfsp matches * it, return TRUE. * * Read this vnode's vfs structure and its mount structure. See if the file * system name is AFS. If it isn't, return FALSE. If it is, save the vnode's * v_vfsp as AFSVfsp and return TRUE. */ if (AFSVfsp && !vp->v_data && vp->v_vfsp == AFSVfsp) return(1); if (vp->v_data || !vp->v_vfsp || kread((KA_T)vp->v_vfsp, (char *)&v, sizeof(v)) || v.vfs_data || strcmp(v.vfs_name, "AFS") != 0) return(0); AFSVfsp = vp->v_vfsp; return(1); } /* * is_rootFid() - is the file ID the root file ID * * return: 0 = is not root file ID * 1 = is root file ID * rfid = 0 if root file ID structure address not available * 1 if root file ID structure address available */ static int is_rootFid(vc, rfid) struct vcache *vc; /* vcache structure */ int *rfid; /* root file ID pointer status return */ { char *err; static int f = 0; /* rootFID structure status: * -1 = unavailable * 0 = not yet accessed * 1 = available */ static struct VenusFid r; unsigned long v; static int w = 0; switch (f) { case -1: if (vc->v.v_flag & VROOT) { *rfid = 1; return(1); } *rfid = 0; return(0); case 0: if (get_Nl_value("arFid", Drive_Nl, &v) < 0 || !v) { err = "no kernel address"; rfid_unavailable: if (!w && !Fwarn) { (void) fprintf(stderr, "%s: WARNING: AFS root Fid: %s\n", Pn, err); (void) fprintf(stderr, " This may hamper AFS node number reporting.\n"); w = 1; } f = -1; if (vc->v.v_flag & VROOT) { *rfid = 1; return(1); } *rfid = 0; return(0); } if (kread((KA_T)v, (char *)&r, sizeof(r))) { err = "can't read from kernel"; goto rfid_unavailable; } f = 1; /* fall through */ case 1: *rfid = 1; if (vc->fid.Fid.Unique == r.Fid.Unique && vc->fid.Fid.Vnode == r.Fid.Vnode && vc->fid.Fid.Volume == r.Fid.Volume && vc->fid.Cell == r.Cell) return(1); } *rfid = 0; return(0); } /* * readafsnode() - read AFS node */ int readafsnode(va, v, an) KA_T va; /* kernel vnode address */ struct vnode *v; /* vnode buffer pointer */ struct afsnode *an; /* afsnode recipient */ { char *cp, tbuf[32]; KA_T ka; int len, rfid, vols; struct vcache *vc; struct volume *vp; cp = ((char *)v + sizeof(struct vnode)); ka = (KA_T)((char *)va + sizeof(struct vnode)); len = sizeof(struct vcache) - sizeof(struct vnode); if (kread(ka, cp, len)) { (void) snpf(Namech, Namechl, "vnode at %s: can't read vcache remainder from %s", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)ka, (char *)NULL, 0)); enter_nm(Namech); return(1); } vc = (struct vcache *)v; an->dev = AFSDEV; an->size = (unsigned long)vc->m.Length; an->nlink = (long)vc->m.LinkCount; an->nlink_st = 1; /* * Manufacture the "inode" number. */ if (vc->mvstat == 2) { if ((vp = getvolume(&vc->fid, &vols))) { an->inode = (INODETYPE)(vp->mtpoint.Fid.Vnode + (vp->mtpoint.Fid.Volume << 16)); if (an->inode == (INODETYPE)0) { if (is_rootFid(vc, &rfid)) an->ino_st = 1; else if (rfid) { an->inode = (INODETYPE)2; an->ino_st = 1; } else an->ino_st = 0; } else an->ino_st = 1; } else { if (vols) { an->inode = (INODETYPE)2; an->ino_st = 1; } else { if (v->v_flag & VROOT) { an->inode = (INODETYPE)0; an->ino_st = 1; } else an->ino_st = 0; } } } else { an->inode = (INODETYPE)((vc->fid.Fid.Vnode + (vc->fid.Fid.Volume << 16)) & 0x7fffffff); an->ino_st = 1; } return(0); } #endif /* defined(HAS_AFS) */ lsof-4.86+dfsg.orig/dialects/hpux/kmem/machine.h0000444000175000017500000004222311424323100021727 0ustar nicholasnicholas/* * 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 #include "kernbits.h" # else /* HPUXV<1030 */ # if HPUXV>=1020 /* * Since we need kernel structures from the HP-UX 10.20 , and * since defining _KERNEL before #include'ing it causes a conflict between * its FILE enum and the FILE struct definition in , redefine FILE, * #include , revoke the FILE redefinition, define _KERNEL, * #include , 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 # endif /* defined(__GNUC__) */ #define FILE STDIO_FILE #include #undef FILE #define _KERNEL 1 #include #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 option. */ #define HASAOPT 1 /* * HASBLKDEV is defined for those dialects that want block device information * recorded in BDevtp[]. */ #define HASBLKDEV 1 /* * HASDCACHE is defined for those dialects that support a device cache * file. * * HASENVDC defined the name of an environment variable that contains the * device cache file path. The HASENVDC environment variable is ignored when * the lsof process is setuid(root) or its real UID is 0. * * HASPERSDC defines the format for the last component of a personal device * cache file path. The first will be the home directory of the real UID that * executes lsof. * * HASPERSDCPATH defines the environment variable whose value is the middle * component of the personal device cache file path. The middle component * follows the home directory and precedes the results of applying HASPERSDC. * The HASPERSDCPATH environment variable is ignored when the lsof process is * setuid(root) or its real UID is 0. * * HASSYSDC defines a public device cache file path. When it's defined, it's * used as the path from which to read the device cache. * * Consult the 00DCACHE and 00FAQ files of the lsof distribution for more * information on device cache file path construction. */ #define HASDCACHE 1 #define HASENVDC "LSOFDEVCACHE" #define HASPERSDC "%h/%p.lsof_%L" #define HASPERSDCPATH "LSOFPERSDCPATH" /* #define HASSYSDC "/your/choice/of/path" */ /* * HASCDRNODE is defined for those dialects that have CD-ROM nodes. */ /* #define HASCDRNODE 1 */ /* * HASFIFONODE is defined for those dialects that have FIFO nodes. */ /* #define HASFIFONODE 1 */ /* * HASFSINO is defined for those dialects that have the file system * inode element, fs_ino, in the lfile structure definition in lsof.h. */ #define HASFSINO 1 /* * HASFSTRUCT is defined if the dialect has a file structure. * * FSV_DEFAULT defines the default set of file structure values to list. * It defaults to zero (0), but may be made up of a combination of the * FSV_* symbols from lsof.h. * * HASNOFSADDR -- has no file structure address * HASNOFSFLAGS -- has no file structure flags * HASNOFSCOUNT -- has no file structure count * HASNOFSNADDR -- has no file structure node address */ #define HASFSTRUCT 1 /* #define FSV_DEFAULT FSV_? | FSV_? | FSV_? */ /* #define HASNOFSADDR 1 has no file structure address */ /* #define HASNOFSFLAGS 1 has no file structure flags */ /* #define HASNOFSCOUNT 1 has no file structure count */ /* #define HASNOFSNADDR 1 has no file structure node address */ /* * HASGNODE is defined for those dialects that have gnodes. */ /* #define HASGNODE 1 */ /* * HASHSNODE is defined for those dialects that have High Sierra nodes. */ /* #define HASHSNODE 1 */ /* * HASINODE is defined for those dialects that have inodes and wish to * use readinode() from node.c. */ /* #define HASINODE 1 */ /* * HASINTSIGNAL is defined for those dialects whose signal function returns * an int. */ /* #define HASINTSIGNAL 1 */ /* * HASKERNIDCK is defined for those dialects that support the comparison of * the build to running kernel identity. */ #define HASKERNIDCK 1 /* * HASKOPT is defined for those dialects that support the -k option of * reading the kernel's name list from an optional file. */ #define HASKOPT 1 /* * HASLFILEADD is defined for those dialects that need additional elements * in struct lfile. The HASLFILEADD definition is a macro that defines * them. If any of the additional elements need to be preset in the * alloc_lfile() function of proc.c, the SETLFILEADD macro may be defined * to do that. * * If any additional elements need to be cleared in alloc_lfile() or in the * free_proc() function of proc.c, the CLRLFILEADD macro may be defined to * do that. Note that CLRLFILEADD takes one argument, the pointer to the * lfile struct. The CLRLFILEADD macro is expected to expand to statements * that are complete -- i.e., have terminating semi-colons -- so the macro is * called without a terminating semicolon by proc.c. * * The HASXOPT definition may be used to select the conditions under which * private lfile elements are used. */ /* #define HASLFILEADD int ... */ /* #define CLRLFILEADD(lf) (lf)->... = (type)NULL; */ /* #define SETLFILEADD Lf->... */ /* * HASMNTSTAT indicates the dialect supports the mount stat(2) result option * in its l_vfs and mounts structures. */ /* #define HASMNTSTAT 1 */ /* * HASMNTSUP is defined for those dialects that support the mount supplement * option. */ /* #define HASMNTSUP 1 */ /* * HASMOPT is defined for those dialects that support the reading of * kernel memory from an alternate file. */ #define HASMOPT 1 /* * HASNCACHE is defined for those dialects that have a kernel name cache * that lsof can search. * * NCACHELDPFX is a set of C commands to execute before calling ncache_load(). * * NCACHELDSFX is a set of C commands to execute after calling ncache_load(). */ #define HASNCACHE 1 /* #define NCACHELDPFX ??? */ /* #define NCACHELDSFX ??? */ /* * HASNCACHE is defined for those dialects that have a kernel name cache * that lsof can search. A value of 1 directs printname() to prefix the * cache value with the file system directory name; 2, avoid the prefix. */ #define HASNLIST 1 /* * HASPIPEFN is defined for those dialects that have a special function to * process DTYPE_PIPE file structure entries. Its value is the name of the * function. * * NOTE: don't forget to define a prototype for this function in dproto.h. */ /* #define HASPIPEFN process_pipe? */ /* * HASPIPENODE is defined for those dialects that have pipe nodes. */ /* #define HASPIPENODE 1 */ /* * HASPMAPENABLED is defined when the reporting of portmapper registration * info is enabled by default. */ /* #define HASPMAPENABLED 1 */ /* * HASPPID is defined for those dialects that support identification of * the parent process IDentifier (PPID) of a process. */ #define HASPPID 1 /* * HASPRINTDEV, HASPRINTINO, HASPRINTNM, HASPRINTOFF, and HASPRINTSZ * define private dialect-specific functions for printing DEVice numbers, * INOde numbers, NaMes, file OFFsets, and file SiZes. The functions are * called from print_file(). */ #define HASPRINTDEV print_dev /* #define HASPRINTINO print_ino? */ /* #define HASPRINTNM print_nm? */ /* #define HASPRINTOFF print_off? */ /* #define HASPRINTSZ print_sz? */ /* * HASPRIVFILETYPE and PRIVFILETYPE are defined for dialects that have a * file structure type that isn't defined by a DTYPE_* symbol. They are * used in lib/prfp.c to select the type's processing. * * PRIVFILETYPE is the definition of the f_type value in the file struct. * * HASPRIVFILETYPE is the name of the processing function. */ /* #define HASPRIVFILETYPE process_shmf? */ /* #define PRIVFILETYPE ?? */ /* * HASPRIVNMCACHE is defined for dialects that have a private method for * printing cached NAME column values for some files. HASPRIVNAMECACHE * is defined to be the name of the function. * * The function takes one argument, a struct lfile pointer to the file, and * returns non-zero if it prints a name to stdout. */ /* #define HASPRIVNMCACHE */ /* * 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 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 */ /* * 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_ is defined for dialects that use the * in the lsof library. * * Note: other definitions and operations may be required to condition the * library function source code. They may be found in the dialect dlsof.h * header files. */ #define USE_LIB_CKKV 1 /* ckkv.c */ /* #define USE_LIB_COMPLETEVFS 1 cvfs.c */ #define USE_LIB_FIND_CH_INO 1 /* fino.c */ #define USE_LIB_IS_FILE_NAMED 1 /* isfn.c */ #define USE_LIB_LKUPDEV 1 /* lkud.c */ #define USE_LIB_PRINTDEVNAME 1 /* pdvn.c */ /* #define USE_LIB_PROCESS_FILE 1 prfp.c */ # if HPUXV<1030 #define USE_LIB_PRINT_TCPTPI 1 /* ptti.c */ # else /* HPUXV>=1030 */ /* #define USE_LIB_PRINT_TCPTPI 1 ptti.c */ # endif /* HPUXV<1030 */ #define USE_LIB_READDEV 1 /* rdev.c */ #define USE_LIB_READMNT 1 /* rmnt.c */ /* #define USE_LIB_REGEX 1 regex.c */ /* #define USE_LIB_RNAM 1 rnam.c */ #define USE_LIB_RNCH 1 /* rnch.c */ /* #define USE_LIB_RNMH 1 rnmh.c */ # if HPUXV<1030 #define USE_LIB_SNPF 1 /* snpf.c */ # else /* HPUXV>=1030 */ #define snpf snprintf /* use the system's snprintf() */ # endif /* HPUXV<1030 */ /* * WARNDEVACCESS is defined for those dialects that should issue a warning * when lsof can't access /dev (or /device) or one of its sub-directories. * The warning can be inhibited by the lsof caller with the -w option. */ /* #define WARNDEVACCESS 1 */ /* * WARNINGSTATE is defined for those dialects that want to suppress all lsof * warning messages. */ /* #define WARNINGSTATE 1 warnings are enabled by default */ /* * WILLDROPGID is defined for those dialects whose lsof executable runs * setgid(not_real_GID) and whose setgid power can be relinquished after * the dialect's initialize() function has been executed. */ #define WILLDROPGID 1 /* * zeromem is a macro that uses bzero or memset. */ #define zeromem(a, l) bzero(a, l) #endif /* !defined(LSOF_MACHINE_H) */ lsof-4.86+dfsg.orig/dialects/hpux/kmem/Makefile0000444000175000017500000000767611001126712021630 0ustar nicholasnicholas # HP-UX /dev/kmem-based Makefile # # $Id: Makefile,v 1.15 2008/04/15 13:29:43 abe Exp $ PROG= lsof BIN= ${DESTDIR} DOC= ${DESTDIR} I=/usr/include S=/usr/include/sys L=/usr/include/local P= CDEF= CDEFS= ${CDEF} ${CFGF} INCL= ${DINC} CFLAGS= ${CDEFS} ${INCL} ${DEBUG} GRP= HDR= lsof.h lsof_fields.h dlsof.h machine.h proto.h dproto.h SRC= dfile.c dmnt.c dnode.c dnode1.c dnode2.c dproc.c dsock.c \ dstore.c \ arg.c main.c misc.c node.c print.c proc.c store.c usage.c util.c OBJ= dfile.o dmnt.o dnode.o dnode1.o dnode2.o dproc.o dsock.o \ dstore.o \ arg.o main.o misc.o node.o print.o proc.o store.o usage.o util.o MAN= lsof.8 OTHER= SHELL= /bin/sh SOURCE= Makefile ${OTHER} ${MAN} ${HDR} ${SRC} all: ${PROG} ${PROG}: ${LIB} ${P} ${OBJ} ${CC} -o $@ ${CFLAGS} ${OBJ} ${CFGL} clean: FRC rm -f Makefile.bak ${PROG} a.out core errs lint.out tags *.o version.h rm -f machine.h.old new_machine.h (cd lib; ${MAKE} -f Makefile.skel clean) install: all FRC @echo '' @echo 'Please write your own install rule. Lsof should be installed' @echo 'setgid to the group that can read /dev/kmem. Normally that is' @echo 'the sys group. Your install rule actions might look something' @echo 'like this:' @echo '' @echo ' install -i -g $${GRP} $${PROG} $${BIN}' @echo ' chmod 2755 $${BIN}/$${PROG}' @echo ' install -i $${MAN} $${DOC}' @echo ' chmod 444 $${DOC}/$${MAN}' @echo '' @echo 'You will have to complete the skeletons for the BIN, DOC, and' @echo 'GRP strings given at the beginning of this Makefile, e.g.,' @echo '' @echo ' BIN= $${DESTDIR}/usr/local/etc' @echo ' DOC= $${DESTDIR}/usr/man/man8' @echo ' GRP= sys' @echo '' ${LIB}: FRC (cd lib; ${MAKE} DEBUG="${DEBUG}" CFGF="${CFGF}") version.h: FRC @echo Constructing version.h @rm -f version.h @echo '#define LSOF_BLDCMT "${LSOF_BLDCMT}"' > version.h; @echo '#define LSOF_CC "${CC}"' >> version.h @echo '#define LSOF_CCV "${CCV}"' >> version.h @echo '#define LSOF_CCDATE "'`date`'"' >> version.h @echo '#define LSOF_CCFLAGS "'`echo ${CFLAGS} | sed 's/\\\\(/\\(/g' | sed 's/\\\\)/\\)/g' | sed 's/"/\\\\"/g'`'"' >> version.h @echo '#define LSOF_CINFO "${CINFO}"' >> version.h @if [ "X${LSOF_HOST}" = "X" ]; then \ echo '#define LSOF_HOST "'`uname -n`'"' >> version.h; \ else \ if [ "${LSOF_HOST}" = "none" ]; then \ echo '#define LSOF_HOST ""' >> version.h; \ else \ echo '#define LSOF_HOST "${LSOF_HOST}"' >> version.h; \ fi \ fi @echo '#define LSOF_LDFLAGS "${CFGL}"' >> version.h @if [ "X${LSOF_LOGNAME}" = "X" ]; then \ echo '#define LSOF_LOGNAME "${LOGNAME}"' >> version.h; \ else \ if [ "${LSOF_LOGNAME}" = "none" ]; then \ echo '#define LSOF_LOGNAME ""' >> version.h; \ else \ echo '#define LSOF_LOGNAME "${LSOF_LOGNAME}"' >> version.h; \ fi; \ fi @if [ "X${LSOF_SYSINFO}" = "X" ]; then \ echo '#define LSOF_SYSINFO "'`uname -a`'"' >> version.h; \ else \ if [ "${LSOF_SYSINFO}" = "none" ]; then \ echo '#define LSOF_SYSINFO ""' >> version.h; \ else \ echo '#define LSOF_SYSINFO "${LSOF_SYSINFO}"' >> version.h; \ fi \ fi @if [ "X${LSOF_USER}" = "X" ]; then \ echo '#define LSOF_USER "${USER}"' >> version.h; \ else \ if [ "${LSOF_USER}" = "none" ]; then \ echo '#define LSOF_USER ""' >> version.h; \ else \ echo '#define LSOF_USER "${LSOF_USER}"' >> version.h; \ fi \ fi @sed '/VN/s/.ds VN \(.*\)/#define LSOF_VERSION "\1"/' < version >> version.h FRC: # DO NOT DELETE THIS LINE - make depend DEPENDS ON IT dfile.o: ${HDR} dfile.c dmnt.o: ${HDR} dmnt.c dnode.o: ${HDR} dnode.c dnode1.o: ${HDR} dnode1.c dnode2.o: ${HDR} dnode2.c dproc.o: ${HDR} dproc.c dsock.o: ${HDR} dsock.c dstore.o: ${HDR} dstore.c arg.o: ${HDR} arg.c main.o: ${HDR} main.c misc.o: ${HDR} misc.c node.o: ${HDR} node.c print.o: ${HDR} print.c proc.o: ${HDR} proc.c store.o: ${HDR} store.c usage.o: ${HDR} version.h usage.c util.o: ${HDR} util.c # *** Do not add anything here - It will go away. *** lsof-4.86+dfsg.orig/dialects/aix/0000755000175000017500000000000011741064217017032 5ustar nicholasnicholaslsof-4.86+dfsg.orig/dialects/aix/dstore.c0000444000175000017500000002366610165045677020521 0ustar nicholasnicholas/* * dstore.c - AIX global storage for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dstore.c,v 1.12 2004/12/30 18:40:59 abe Exp $"; #endif #include "lsof.h" /* * Global storage definitions */ #if defined(HAS_AFS) struct nlist AFSnl[] = { { "afs_rootFid", 0, 0, 0, 0, 0 }, { "afs_volumes", 0, 0, 0, 0, 0 }, }; # if defined(HASAOPT) char *AFSApath = (char *)NULL; /* alternate AFS name list path * (from -a) */ # endif /* defined(HASAOPT) */ KA_T AFSVfsp = (KA_T)NULL; /* AFS vfs struct kernel address */ #endif /* defined(HAS_AFS) */ # if AIXV>=4140 struct clone *Clone = (struct clone *)NULL; /* local clone information */ int CloneMaj = -1; /* clone major device number */ int ClonePtc = -1; /* /dev/ptc minor device number */ # endif /* AIXV>=4140 */ int Kd = -1; /* /dev/kmem file descriptor */ struct l_vfs *Lvfs = NULL; /* local vfs structure table */ int Km = -1; /* /dev/mem file descriptor */ struct nlist Nl[] = { #if AIXV<4100 { "u", 0, 0, 0, 0, 0 }, #else /* AIXV>=4100 */ { "__ublock", 0, 0, 0, 0, 0 }, #endif /* AIXV<4100 */ }; #if defined(HASFSTRUCT) /* * Pff_tab[] - table for printing file flags */ struct pff_tab Pff_tab[] = { # if defined(FREAD) { (long)FREAD, FF_READ }, # else /* !defined(FREAD) */ # if defined(_FREAD) { (long)_FREAD, FF_READ }, # endif /* defined(_FREAD) */ # endif /* defined(FREAD) */ # if defined(FWRITE) { (long)FWRITE, FF_WRITE }, # else /* !defined(FWRITE) */ # if defined(_FWRITE) { (long)_FWRITE, FF_WRITE }, # endif /* defined(_FWRITE) */ # endif /* defined(FWRITE) */ # if defined(FNONBLOCK) { (long)FNONBLOCK, FF_NBLOCK }, # else /* !defined(FNONBLOCK) */ # if defined(_FNONBLOCK) { (long)_FNONBLOCK, FF_NBLOCK }, # endif /* defined(_FNONBLOCK) */ # endif /* defined(FNONBLOCK) */ # if defined(FAPPEND) { (long)FAPPEND, FF_APPEND }, # else /* !defined(FAPPEND) */ # if defined(_FAPPEND) { (long)_FAPPEND, FF_APPEND }, # endif /* defined(_FAPPEND) */ # endif /* defined(FAPPEND) */ # if defined(FSYNC) { (long)FSYNC, FF_SYNC }, # else /* !defined(FSYNC) */ # if defined(_FSYNC) { (long)_FSYNC, FF_SYNC }, # endif /* defined(_FSYNC) */ # endif /* defined(FSYNC) */ # if defined(FEXEC) { (long)FEXEC, FF_EXEC }, # else /* !defined(FEXEC) */ # if defined(_FEXEC) { (long)_FEXEC, FF_EXEC }, # endif /* defined(_FEXEC) */ # endif /* defined(FEXEC) */ # if defined(FCREAT) { (long)FCREAT, FF_CREAT }, # else /* !defined(FCREAT) */ # if defined(_FCREAT) { (long)_FCREAT, FF_CREAT }, # endif /* defined(_FCREAT) */ # endif /* defined(FCREAT) */ # if defined(FTRUNC) { (long)FTRUNC, FF_TRUNC }, # else /* !defined(FTRUNC) */ # if defined(_FTRUNC) { (long)_FTRUNC, FF_TRUNC }, # endif /* defined(_FTRUNC) */ # endif /* defined(FTRUNC) */ # if defined(FEXCL) { (long)FEXCL, FF_EXCL }, # else /* !defined(FEXCL) */ # if defined(_FEXCL) { (long)_EXCL, FF_EXCL }, # endif /* defined(_FEXCL) */ # endif /* defined(FEXCL) */ # if defined(FNOCTTY) { (long)FNOCTTY, FF_NOCTTY }, # else /* !defined(FNOCTTY) */ # if defined(_FNOCTTY) { (long)_FNOCTTY, FF_NOCTTY }, # endif /* defined(_FNOCTTY) */ # endif /* defined(FNOCTTY) */ # if defined(FRSHARE) { (long)FRSHARE, FF_RSHARE }, # else /* !defined(FRSHARE) */ # if defined(_FRSHARE) { (long)_FRSHARE, FF_RSHARE }, # endif /* defined(_FRSHARE) */ # endif /* defined(FRSHARE) */ # if defined(FDEFER) { (long)FDEFER, FF_DEFER }, # else /* !defined(FDEFER) */ # if defined(_FDEFER) { (long)_FDEFER, FF_DEFER }, # endif /* defined(_FDEFER) */ # endif /* defined(FDEFER) */ # if defined(FDELAY) { (long)FDELAY, FF_DELAY }, # else /* !defined(FDELAY) */ # if defined(_FDELAY) { (long)_FDELAY, FF_DELAY }, # endif /* defined(_FDELAY) */ # endif /* defined(FDELAY) */ # if defined(FNDELAY) { (long)FNDELAY, FF_NDELAY }, # else /* !defined(FNDELAY) */ # if defined(_FNDELAY) { (long)_FNDELAY, FF_NDELAY }, # endif /* defined(_FNDELAY) */ # endif /* defined(FNDELAY) */ # if defined(FNSHARE) { (long)FNSHARE, FF_NSHARE }, # else /* !defined(FNSHARE) */ # if defined(_FNSHARE) { (long)_FNSHARE, FF_NSHARE }, # endif /* defined(_FNSHARE) */ # endif /* defined(FNSHARE) */ # if defined(FASYNC) { (long)FASYNC, FF_ASYNC }, # else /* !defined(FASYNC) */ # if defined(_FASYNC) { (long)_FASYNC, FF_ASYNC }, # endif /* defined(_FASYNC) */ # endif /* defined(FASYNC) */ # if defined(FAIO) { (long)FAIO, FF_AIO }, # else /* !defined(FAIO) */ # if defined(_FAIO) { (long)_FAIO, FF_AIO }, # endif /* defined(_FAIO) */ # endif /* defined(FAIO) */ # if defined(FCIO) { (long)FCIO, FF_CIO }, # else /* !defined(FCIO) */ # if defined(_FCIO) { (long)_FCIO, FF_CIO }, # endif /* defined(_FCIO) */ # endif /* defined(FCIO) */ # if defined(FMOUNT) { (long)FMOUNT, FF_MOUNT }, # else /* !defined(FMOUNT) */ # if defined(_FMOUNT) { (long)_FMOUNT, FF_MOUNT }, # endif /* defined(_FMOUNT) */ # endif /* defined(FMOUNT) */ # if defined(FSYNCALL) { (long)FSYNCALL, FF_SYNC }, # else /* !defined(FSYNCALL) */ # if defined(_FSYNCALL) { (long)_FSYNCALL, FF_SYNC }, # endif /* defined(_FSYNCALL) */ # endif /* defined(FSYNCALL) */ # if defined(FNOCACHE) { (long)FNOCACHE, FF_NOCACHE }, # else /* defined(FNOCACHE) */ # if defined(_FNOCACHE) { (long)_FNOCACHE, FF_NOCACHE }, # endif /* defined(_FNOCACHE) */ # endif /* defined(FNOCACHE) */ # if defined(FREADSYNC) { (long)FREADSYNC, FF_RSYNC }, # else /* !defined(FREADSYNC) */ # if defined(_FREADSYNC) { (long)_FREADSYNC, FF_RSYNC }, # endif /* defined(_FREADSYNC) */ # endif /* defined(FREADSYNC) */ # if defined(FDATASYNC) { (long)FDATASYNC, FF_DSYNC }, # else /* !defined(FDATASYNC) */ # if defined(_FDATASYNC) { (long)_FDATASYNC, FF_DSYNC }, # endif /* defined(_FDATASYNC) */ # endif /* defined(FDATASYNC) */ # if defined(FDEFERIND) { (long)FDEFERIND, FF_DEFERIND }, # else /* !defined(FDEFERIND) */ # if defined(_FDEFERIND) { (long)_FDEFERIND, FF_DEFERIND }, # endif /* defined(_FDEFERIND) */ # endif /* defined(FDEFERIND) */ # if defined(FDATAFLUSH) { (long)FDATAFLUSH, FF_DATAFLUSH }, # else /* !defined(FDATAFLUSH) */ # if defined(_FDATAFLUSH) { (long)_FDATAFLUSH, FF_DATAFLUSH }, # endif /* defined(_FDATAFLUSH) */ # endif /* defined(FDATAFLUSH) */ # if defined(FCLREAD) { (long)FCLREAD, FF_CLREAD }, # else /* !defined(FCLREAD) */ # if defined(_FCLREAD) { (long)_FCLREAD, FF_CLREAD }, # endif /* defined(_FCLREAD) */ # endif /* defined(FCLREAD) */ # if defined(FLARGEFILE) { (long)FLARGEFILE, FF_LARGEFILE }, # else /* !defined(FLARGEFILE) */ # if defined(_FLARGEFILE) { (long)_FLARGEFILE, FF_LARGEFILE }, # endif /* defined(_FLARGEFILE) */ # endif /* defined(FLARGEFILE) */ # if defined(FDIRECT) { (long)FDIRECT, FF_DIRECT }, # else /* !defined(FDIRECT) */ # if defined(_FDIRECT) { (long)_FDIRECT, FF_DIRECT }, # endif /* defined(_FDIRECT) */ # endif /* defined(FDIRECT) */ # if defined(FSNAPSHOT) { (long)FSNAPSHOT, FF_SNAP }, # else /* !defined(FSNAPSHOT) */ # if defined(_FSNAPSHOT) { (long)_FSNAPSHOT, FF_SNAP }, # endif /* defined(_FSNAPSHOT) */ # endif /* defined(FAIO) */ # if defined(FDOCLONE) { (long)FDOCLONE, FF_DOCLONE }, # else /* !defined(FDOCLONE) */ # if defined(_FDOCLONE) { (long)_FDOCLONE, FF_DOCLONE }, # endif /* defined(_FDOCLONE) */ # endif /* defined(FDOCLONE) */ # if defined(FKERNEL) { (long)FKERNEL, FF_KERNEL }, # else /* !defined(FKERNEL) */ # if defined(_FKERNEL) { (long)_FKERNEL, FF_KERNEL }, # endif /* defined(_FKERNEL) */ # endif /* defined(FKERNEL) */ # if defined(FMSYNC) { (long)FMSYNC, FF_MSYNC }, # else /* !defined(FMSYNC) */ # if defined(_FMSYNC) { (long)_FMSYNC, FF_MSYNC }, # endif /* defined(_FMSYNC) */ # endif /* defined(FMSYNC) */ # if defined(GCFDEFER) { (long)GCFDEFER, FF_GCFDEFER }, # endif /* defined(GCFDEFER) */ # if defined(GCFMARK) { (long)GCFMARK, FF_GCFMARK }, # endif /* defined(GCFMARK) */ { (long)0, NULL } }; /* * Pof_tab[] - table for print process open file flags */ struct pff_tab Pof_tab[] = { # if defined(UF_EXCLOSE) { (long)UF_EXCLOSE, POF_CLOEXEC }, # endif /* defined(UF_EXCLOSE) */ # if defined(UF_MAPPED) { (long)UF_MAPPED, POF_MAPPED }, # endif /* defined(UF_MAPPED) */ # if defined(UF_FDLOCK) { (long)UF_FDLOCK, POF_FDLOCK }, # endif /* defined(UF_FDLOCK) */ # if defined(UF_AUD_READ) { (long)UF_AUD_READ, POF_BNRD }, # endif /* defined(UF_AUD_READ) */ # if defined(UF_AUD_WRITE) { (long)UF_AUD_WRITE, POF_BNWR }, # endif /* defined(UF_AUD_WRITE) */ # if defined(UF_FSHMAT) { (long)UF_FSHMAT, POF_FSHMAT }, # endif /* defined(UF_FSHMAT) */ # if defined(UF_CLOSING) { (long)UF_CLOSING, POF_CLOSING }, # endif /* defined(UF_CLOSING) */ # if defined(UF_ALLOCATED) { (long)UF_ALLOCATED, POF_ALLOCATED }, # endif /* defined(UF_ALLOCATED) */ { (long)0, NULL } }; #endif /* defined(HASFSTRUCT) */ #if AIXV>=4110 struct ublock __ublock; /* dummy so we can define _KERNEL * for */ # if AIXA>2 void aix_dstore_dummy_function() {} /* for ia64 idebug */ # endif /* AIXA>2 */ #endif /* AIXV>=4110 */ lsof-4.86+dfsg.orig/dialects/aix/ddev.c0000444000175000017500000003752610275733241020134 0ustar nicholasnicholas/* * ddev.c - AIX device support functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: ddev.c,v 1.14 2005/08/08 19:46:38 abe Exp $"; #endif #include "lsof.h" /* * Local definitions */ #define LIKE_BLK_SPEC "like block special" #define LIKE_CHR_SPEC "like character special" /* * Local function prototypes */ _PROTOTYPE(static int rmdupdev,(struct l_dev ***dp, int n, char *nm)); #if defined(HASDCACHE) && AIXV>=4140 /* * clr_sect() - clear cached clone and pseudo sections */ void clr_sect() { struct clone *c, *c1; if (Clone) { for (c = Clone; c; c = c1) { c1 = c->next; if (c->cd.name) (void) free((FREE_P *)c->cd.name); (void) free((FREE_P *)c); } Clone = (struct clone *)NULL; } } #endif /* defined(HASDCACHE) && AIXV>=4140 */ /* * getchan() - get channel from file path name */ int getchan(p) char *p; /* file path name */ { int ch; char *s; if (!(s = strrchr(p, '/'))) return(-1); if (*(++s) == '\0') return(-1); for (ch = 0; *s; s++) { #if defined(__STDC__) if ( ! isdigit(*s)) #else if ( ! isascii(*s) || ! isdigit(*s)) #endif /* __STDC__ */ return(-1); ch = (ch * 10) + *s - '0'; } return(ch); } /* * printdevname() - print device name */ int printdevname(dev, rdev, f, nty) dev_t *dev; /* device */ dev_t *rdev; /* raw device */ int f; /* 1 = follow with '\n' */ int nty; /* node type: N_BLK or N_CHR */ { struct l_dev *dp; /* * Search device table for a full match. */ if ((dp = lkupdev(dev, rdev, 1, 1))) { if (Lf->ch < 0) safestrprt(dp->name, stdout, f); else { safestrprt(dp->name, stdout, 0); (void) printf("/%d%s", Lf->ch, f ? "\n" : ""); } return(1); } /* * Search device table for a match without inode number and dev. */ if ((dp = lkupdev(&DevDev, rdev, 0, 1))) { /* * A raw device match was found. Record it as a name column addition. */ char *cp, *ttl; int len; ttl = (nty == N_BLK) ? LIKE_BLK_SPEC : LIKE_CHR_SPEC; len = (int)(1 + strlen(ttl) + 1 + strlen(dp->name) + 1); if (!(cp = (char *)malloc((MALLOC_S)(len + 1)))) { (void) fprintf(stderr, "%s: no nma space for: (%s %s)\n", Pn, ttl, dp->name); Exit(1); } (void) snpf(cp, len + 1, "(%s %s)", ttl, dp->name); (void) add_nma(cp, len); (void) free((MALLOC_P *)cp); return(0); } return(0); } /* * readdev() - read device names, modes and types */ void readdev(skip) int skip; /* skip device cache read if 1 */ { #if defined(HASDCACHE) int dcrd; #endif /* defined(HASDCACHE) */ DIR *dfp; struct dirent *dp; char *fp = (char *)NULL; int i = 0; #if defined(HASBLKDEV) int j = 0; #endif /* defined(HASBLKDEV) */ char *path = (char *)NULL; MALLOC_S pl; struct stat sb; #if AIXV>=4140 struct clone *c; dev_t cd; #endif /* AIXV >=4140 */ if (Sdev) return; #if defined(HASDCACHE) /* * Read device cache, as directed. */ if (!skip) { if (DCstate == 2 || DCstate == 3) { if ((dcrd = read_dcache()) == 0) return; } } else dcrd = 1; #endif /* defined(HASDCACHE) */ #if AIXV>=4140 /* * Establish the clone major device for AIX 4.1.4 and above. */ if (stat("/dev/clone", &sb) == 0) { cd = sb.st_rdev; CloneMaj = GET_MAJ_DEV(cd); } #endif /* AIXV >=4140 */ Dstk = (char **)NULL; Dstkn = Dstkx = 0; (void) stkdir("/dev"); /* * Unstack the next /dev or /dev/ directory. */ while (--Dstkx >= 0) { if (!(dfp = opendir(Dstk[Dstkx]))) { #if defined(WARNDEVACCESS) if (!Fwarn) { (void) fprintf(stderr, "%s: WARNING: can't open: ", Pn); safestrprt(Dstk[Dstkx], stderr, 1); } #endif /* defined(WARNDEVACCESS) */ (void) free((FREE_P *)Dstk[Dstkx]); Dstk[Dstkx] = (char *)NULL; continue; } if (path) { (void) free((FREE_P *)path); path = (char *)NULL; } if (!(path = mkstrcat(Dstk[Dstkx], -1, "/", 1, (char *)NULL, -1, &pl))) { (void) fprintf(stderr, "%s: no space for: ", Pn); safestrprt(Dstk[Dstkx], stderr, 1); Exit(1); } (void) free((FREE_P *)Dstk[Dstkx]); Dstk[Dstkx] = (char *)NULL; /* * Scan the directory. */ for (dp = readdir(dfp); dp; dp = readdir(dfp)) { if (!dp->d_ino || (dp->d_name[0] == '.')) continue; /* * Form the full path name and get its status. */ if (fp) { (void) free((FREE_P *)fp); fp = (char *)NULL; } if (!(fp = mkstrcat(path, (int)pl, dp->d_name, dp->d_namlen, (char *)NULL, -1, (MALLOC_S *)NULL))) { (void) fprintf(stderr, "%s: no space for: ", Pn); safestrprt(path, stderr, 0); safestrprt(dp->d_name, stderr, 1); Exit(1); } #if defined(USE_STAT) if (stat(fp, &sb) != 0) #else /* !defined(USE_STAT) */ if (lstat(fp, &sb) != 0) #endif /* defined(USE_STAT) */ { if (errno == ENOENT) /* symbolic link to nowhere? */ continue; #if defined(WARNDEVACCESS) if (!Fwarn) { int errno_save = errno; (void) fprintf(stderr, "%s: can't stat: ", Pn); safestrprt(fp, stderr, 0); (void) fprintf(stderr, ": %s\n", strerror(errno_save)); } #endif /* defined(WARNDEVACCESS) */ continue; } /* * If it's a subdirectory, stack its name for later processing. */ if ((sb.st_mode & S_IFMT) == S_IFDIR) { (void) stkdir(fp); continue; } if ((sb.st_mode & S_IFMT) == S_IFCHR) { /* * Save character device information. */ if (i >= Ndev) { Ndev += DEVINCR; if (!Devtp) Devtp = (struct l_dev *)malloc( (MALLOC_S)(sizeof(struct l_dev)*Ndev)); else Devtp = (struct l_dev *)realloc( (MALLOC_P *)Devtp, (MALLOC_S)(sizeof(struct l_dev)*Ndev)); if (!Devtp) { (void) fprintf(stderr, "%s: no space for character device\n", Pn); Exit(1); } } Devtp[i].rdev = sb.st_rdev; Devtp[i].inode = (INODETYPE)sb.st_ino; if (!(Devtp[i].name = mkstrcpy(fp, (MALLOC_S *)NULL))) { (void) fprintf(stderr, "%s: no space for: ", Pn); safestrprt(fp, stderr, 1); Exit(1); } Devtp[i].v = 0; i++; #if AIXV>=4140 /* * Save information on AIX 4.1.4 and above clone devices. */ if (CloneMaj >= 0 && CloneMaj == GET_MAJ_DEV(sb.st_rdev)) { if (!(c = (struct clone *)malloc( (MALLOC_S)sizeof(struct clone)))) { (void) fprintf(stderr, "%s: no space for clone device: ", Pn); safestrprt(fp, stderr, 1); exit(1); } if (!(c->cd.name = mkstrcpy(fp, (MALLOC_S)NULL))) { (void) fprintf(stderr, "%s: no space for clone name: ", Pn); safestrprt(fp, stderr, 1); exit(1); } c->cd.inode = (INODETYPE)sb.st_ino; c->cd.rdev = sb.st_rdev; c->cd.v = 0; c->next = Clone; Clone = c; if (ClonePtc < 0 && strcmp(path, "/dev/ptc") == 0) ClonePtc = GET_MIN_DEV(sb.st_rdev); } #endif /* AIXV >=4140 */ } #if defined(HASBLKDEV) if ((sb.st_mode & S_IFMT) == S_IFBLK) { /* * Save block device information in BDevtp[]. */ if (j >= BNdev) { BNdev += DEVINCR; if (!BDevtp) BDevtp = (struct l_dev *)malloc( (MALLOC_S)(sizeof(struct l_dev)*BNdev)); else BDevtp = (struct l_dev *)realloc( (MALLOC_P *)BDevtp, (MALLOC_S)(sizeof(struct l_dev)*BNdev)); if (!BDevtp) { (void) fprintf(stderr, "%s: no space for block device\n", Pn); Exit(1); } } BDevtp[j].rdev = sb.st_rdev; BDevtp[j].inode = (INODETYPE)sb.st_ino; BDevtp[j].name = fp; fp = (char *)NULL; BDevtp[j].v = 0; j++; } #endif /* defined(HASBLKDEV) */ } (void) closedir(dfp); } /* * Free any allocated space. */ if (Dstk) { (void) free((FREE_P *)Dstk); Dstk = (char **)NULL; Dstkn = Dstkx = 0; } if (fp) (void) free((FREE_P *)fp); if (path) (void) free((FREE_P *)path); /* * Reduce the BDevtp[] (optional) and Devtp[] tables to their minimum * sizes; allocate and build sort pointer lists; and sort the tables by * device number. */ #if defined(HASBLKDEV) if (BNdev) { if (BNdev > j) { BNdev = j; BDevtp = (struct l_dev *)realloc((MALLOC_P *)BDevtp, (MALLOC_S)(sizeof(struct l_dev) * BNdev)); } if (!(BSdev = (struct l_dev **)malloc( (MALLOC_S)(sizeof(struct l_dev *) * BNdev)))) { (void) fprintf(stderr, "%s: no space for block device sort pointers\n", Pn); Exit(1); } for (j = 0; j < BNdev; j++) { BSdev[j] = &BDevtp[j]; } (void) qsort((QSORT_P *)BSdev, (size_t)BNdev, (size_t)sizeof(struct l_dev *), compdev); BNdev = rmdupdev(&BSdev, BNdev, "block"); } else { if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: no block devices found\n", Pn); } #endif /* defined(HASBLKDEV) */ if (Ndev) { if (Ndev > i) { Ndev = i; Devtp = (struct l_dev *)realloc((MALLOC_P *)Devtp, (MALLOC_S)(sizeof(struct l_dev) * Ndev)); } if (!(Sdev = (struct l_dev **)malloc( (MALLOC_S)(sizeof(struct l_dev *) * Ndev)))) { (void) fprintf(stderr, "%s: no space for character device sort pointers\n", Pn); Exit(1); } for (i = 0; i < Ndev; i++) { Sdev[i] = &Devtp[i]; } (void) qsort((QSORT_P *)Sdev, (size_t)Ndev, (size_t)sizeof(struct l_dev *), compdev); Ndev = rmdupdev(&Sdev, Ndev, "char"); } else { (void) fprintf(stderr, "%s: no character devices found\n", Pn); Exit(1); } #if defined(HASDCACHE) /* * Write device cache file, as required. */ if (DCstate == 1 || (DCstate == 3 && dcrd)) write_dcache(); #endif /* defined(HASDCACHE) */ } #if defined(HASDCACHE) /* * rereaddev() - reread device names, modes and types */ void rereaddev() { (void) clr_devtab(); # if defined(DCACHE_CLR) (void) DCACHE_CLR(); # endif /* defined(DCACHE_CLR) */ readdev(1); DCunsafe = 0; } #endif /* defined(HASDCACHE) */ /* * rmdupdev() - remove duplicate (major/minor/inode) devices */ static int rmdupdev(dp, n, nm) struct l_dev ***dp; /* device table pointers address */ int n; /* number of pointers */ char *nm; /* device table name for error message */ { #if AIXV>=4140 struct clone *c, *cp; #endif /* AIXV>=4140 */ int i, j, k; struct l_dev **p; for (i = j = 0, p = *dp; i < n ;) { for (k = i + 1; k < n; k++) { if (p[i]->rdev != p[k]->rdev || p[i]->inode != p[k]->inode) break; #if AIXV>=4140 /* * See if we're deleting a duplicate clone device. If so, * delete its clone table entry. */ for (c = Clone, cp = (struct clone *)NULL; c; cp = c, c = c->next) { if (c->cd.rdev != p[k]->rdev || c->cd.inode != p[k]->inode || strcmp(c->cd.name, p[k]->name)) continue; if (!cp) Clone = c->next; else cp->next = c->next; if (c->cd.name) (void) free((FREE_P *)c->cd.name); (void) free((FREE_P *)c); break; } #endif /* AIXV>=4140 */ } if (i != j) p[j] = p[i]; j++; i = k; } if (n == j) return(n); if (!(*dp = (struct l_dev **)realloc((MALLOC_P *)*dp, (MALLOC_S)(j * sizeof(struct l_dev *))))) { (void) fprintf(stderr, "%s: can't realloc %s device pointers\n", Pn, nm); Exit(1); } return(j); } #if defined(HASDCACHE) && AIXV>=4140 /* * rw_clone_sect() - read/write the device cache file clone section */ int rw_clone_sect(m) int m; /* mode: 1 = read; 2 = write */ { char buf[MAXPATHLEN*2], *cp; struct clone *c; int i, len, n; if (m == 1) { /* * Read the clone section header and validate it. */ if (!fgets(buf, sizeof(buf), DCfs)) { bad_clone_sect: if (!Fwarn) { (void) fprintf(stderr, "%s: bad clone section header in %s: ", Pn, DCpath[DCpathX]); safestrprt(buf, stderr, 1); } return(1); } (void) crc(buf, strlen(buf), &DCcksum); len = strlen("clone section: "); if (strncmp(buf, "clone section: ", len) != 0) goto bad_clone_sect; if ((n = atoi(&buf[len])) < 0) goto bad_clone_sect; /* * Read the clone section lines and create the Clone list. */ for (i = 0; i < n; i++) { if (!fgets(buf, sizeof(buf), DCfs)) { if (!Fwarn) { (void) fprintf(stderr, "%s: bad clone line in %s: ", Pn, DCpath[DCpathX]); safestrprt(buf, stderr, 1); } return(1); } (void) crc(buf, strlen(buf), &DCcksum); /* * Allocate a clone structure. */ if (!(c = (struct clone *)calloc(1, sizeof(struct clone)))) { (void) fprintf(stderr, "%s: no space for cached clone: ", Pn); safestrprt(buf, stderr, 1); Exit(1); } /* * Enter the clone device number. */ if (!(cp = x2dev(buf, &c->cd.rdev)) || *cp++ != ' ') { bad_cached_clone: if (!Fwarn) { (void) fprintf(stderr, "%s: bad cached clone device: ", Pn); safestrprt(buf, stderr, 1); } return(1); } CloneMaj = GET_MAJ_DEV(c->cd.rdev); /* * Enter the clone inode number. */ for (c->cd.inode = (INODETYPE)0; *cp != ' '; cp++) { if (*cp < '0' || *cp > '9') goto bad_cached_clone; c->cd.inode = (INODETYPE)((c->cd.inode * 10) + (*cp - '0')); } /* * Enter the clone path name. */ if ((len = strlen(++cp)) < 2 || *(cp + len - 1) != '\n') { if (!Fwarn) { (void) fprintf(stderr, "%s: bad cached clone path: ", Pn); safestrprt(buf, stderr, 1); } return(1); } *(cp + len - 1) = '\0'; if (!(c->cd.name = mkstrcpy(cp, (MALLOC_S *)NULL))) { (void) fprintf(stderr, "%s: no space for cached clone path: ", Pn); safestrprt(buf, stderr, 1); Exit(1); } c->cd.v = 0; c->next = Clone; Clone = c; if (ClonePtc < 0 && strcmp(c->cd.name, "/dev/ptc") == 0) ClonePtc = GET_MIN_DEV(c->cd.rdev); } return(0); } else if (m == 2) { /* * Write the clone section header. */ for (c = Clone, n = 0; c; c = c->next, n++) ; (void) snpf(buf, sizeof(buf), "clone section: %d\n", n); if (wr2DCfd(buf, &DCcksum)) return(1); /* * Write the clone section lines. */ for (c = Clone; c; c = c->next) { (void) snpf(buf, sizeof(buf), "%x %ld %s\n", c->cd.rdev, (long)c->cd.inode, c->cd.name); if (wr2DCfd(buf, &DCcksum)) return(1); } return(0); } /* * A shouldn't-happen case: mode neither 1 nor 2. */ (void) fprintf(stderr, "%s: internal rw_clone_sect error: %d\n", Pn, m); Exit(1); } #endif /* defined(HASDCACHE) && AIXV>=4140 */ #if defined(HASDCACHE) /* * vfy_dev() - verify a device table entry (usually when DCunsafe == 1) * * Note: rereads entire device table when an entry can't be verified. */ int vfy_dev(dp) struct l_dev *dp; /* device table pointer */ { struct stat sb; if (!DCunsafe || dp->v) return(1); #if defined(USE_STAT) if (stat(dp->name, &sb) != 0 #else /* !defined(USE_STAT) */ if (lstat(dp->name, &sb) != 0 #endif /* defined(USE_STAT) */ || dp->rdev != sb.st_rdev || dp->inode != (INODETYPE)sb.st_ino) { (void) rereaddev(); return(0); } dp->v = 1; return(1); } #endif /* defined(HASDCACHE) */ lsof-4.86+dfsg.orig/dialects/aix/dsock.c0000444000175000017500000002642011077377737020323 0ustar nicholasnicholas/* * dsock.c - AIX socket processing functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dsock.c,v 1.24 2008/10/21 16:14:18 abe Exp $"; #endif #include "lsof.h" /* * We include here instead of "dlsof.h" for gcc's benefit. * Its loader can't handle the multiple CONST u_char arrays declared in * -- e.g., etherbroadcastaddr[]. ( * #include's .) */ #include #include /* * process_socket() - process socket file */ void process_socket(sa) KA_T sa; /* socket address in kernel */ { struct domain d; unsigned char *fa = (unsigned char *)NULL; int fam; int fp, lp, uo; struct gnode g; struct l_ino i; struct inpcb inp; int is = 0; unsigned char *la = (unsigned char *)NULL; struct protosw p; struct socket s; struct tcpcb t; int ts = 0; int tsn, tsnx; struct unpcb uc, unp; struct sockaddr_un *ua = (struct sockaddr_un *)NULL; struct sockaddr_un un; struct vnode v; struct mbuf mb; /* * Set socket file variables. */ (void) snpf(Lf->type, sizeof(Lf->type), "sock"); Lf->inp_ty = 2; /* * Read socket and protocol switch structures. */ if (!sa) { enter_nm("no socket address"); return; } if (kread(sa, (char *) &s, sizeof(s))) { (void) snpf(Namech, Namechl, "can't read socket struct from %s", print_kptr(sa, (char *)NULL, 0)); enter_nm(Namech); return; } if (!s.so_type) { enter_nm("no socket type"); return; } if (!s.so_proto || kread((KA_T)s.so_proto, (char *)&p, sizeof(p))) { (void) snpf(Namech, Namechl, "can't read protocol switch from %s", print_kptr((KA_T)s.so_proto, (char *)NULL, 0)); enter_nm(Namech); return; } /* * Save size information. */ if (Fsize) { if (Lf->access == 'r') Lf->sz = (SZOFFTYPE)s.so_rcv.sb_cc; else if (Lf->access == 'w') Lf->sz = (SZOFFTYPE)s.so_snd.sb_cc; else Lf->sz = (SZOFFTYPE)(s.so_rcv.sb_cc + s.so_snd.sb_cc); Lf->sz_def = 1; } else Lf->off_def = 1; #if defined(HASTCPTPIQ) Lf->lts.rq = s.so_rcv.sb_cc; Lf->lts.sq = s.so_snd.sb_cc; Lf->lts.rqs = Lf->lts.sqs = 1; #endif /* defined(HASTCPTPIQ) */ #if defined(HASSOOPT) Lf->lts.ltm = (unsigned int)s.so_linger; Lf->lts.opt = (unsigned int)s.so_options; Lf->lts.pqlen = (unsigned int)s.so_q0len; Lf->lts.qlen = (unsigned int)s.so_qlen; Lf->lts.qlim = (unsigned int)s.so_qlimit; Lf->lts.rbsz = (unsigned long)s.so_rcv.sb_mbmax; Lf->lts.sbsz = (unsigned long)s.so_snd.sb_mbmax; Lf->lts.pqlens = Lf->lts.qlens = Lf->lts.qlims = Lf->lts.rbszs = Lf->lts.sbszs = (unsigned char)1; #endif /* defined(HASSOOPT) */ #if defined(HASSOSTATE) Lf->lts.ss = (unsigned int)s.so_state; #endif /* defined(HASSOSTATE) */ /* * Process socket by the associated domain family. */ if (!p.pr_domain || kread((KA_T)p.pr_domain, (char *)&d, sizeof(d))) { (void) snpf(Namech, Namechl, "can't read domain struct from %s", print_kptr((KA_T)p.pr_domain, (char *)NULL, 0)); enter_nm(Namech); return; } switch ((fam = d.dom_family)) { /* * Process an Internet domain socket. */ case AF_INET: #if defined(HASIPv6) case AF_INET6: #endif /* defined(HASIPv6) */ /* * Read protocol control block. */ if (!s.so_pcb || kread((KA_T) s.so_pcb, (char *) &inp, sizeof(inp))) { if (!s.so_pcb) { (void) snpf(Namech, Namechl, "no PCB%s%s", (s.so_state & SS_CANTSENDMORE) ? ", CANTSENDMORE" : "", (s.so_state & SS_CANTRCVMORE) ? ", CANTRCVMORE" : ""); } else { (void) snpf(Namech, Namechl, "can't read inpcb at %s", print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); } enter_nm(Namech); return; } if (p.pr_protocol == IPPROTO_TCP) { /* * If this is a TCP socket, read its control block. */ if (inp.inp_ppcb && !kread((KA_T)inp.inp_ppcb, (char *)&t, sizeof(t))) { ts = 1; tsn = (int)t.t_state; tsnx = tsn + TcpStOff; } } if (ts && (TcpStIn || TcpStXn) && (tsnx >= 0) && (tsnx < TcpNstates) ) { /* * Check TCP state name inclusion and exclusions. */ if (TcpStXn) { if (TcpStX[tsnx]) { Lf->sf |= SELEXCLF; return; } } if (TcpStIn) { if (TcpStI[tsnx]) TcpStI[tsnx] = 2; else { Lf->sf |= SELEXCLF; return; } } } if (Fnet) { /* * Set SELNET flag for the file, as requested. */ if (!FnetTy || ((FnetTy == 4) && (fam == AF_INET)) #if defined(HASIPv6) || ((FnetTy == 6) && (fam == AF_INET6)) #endif /* defined(HASIPv6) */ ) Lf->sf |= SELNET; } printiproto(p.pr_protocol); #if defined(HASIPv6) (void) snpf(Lf->type, sizeof(Lf->type), fam == AF_INET ? "IPv4" : "IPv6"); #else /* !defined(HASIPv6) */ (void) snpf(Lf->type, sizeof(Lf->type), "inet"); #endif /* defined(HASIPv6) */ /* * Save Internet socket information. */ enter_dev_ch(print_kptr((KA_T)(inp.inp_ppcb ? inp.inp_ppcb : s.so_pcb), (char *)NULL, 0)); #if defined(HASIPv6) /* * If this is an IPv6 (AF_INET6) socket and IPv4 compatibility * mode is enabled, use the IPv4 address, change the family * indicator from AF_INET6 to AF_INET. Otherwise, use the IPv6 * address. Don't ignore empty addresses. */ if (fam == AF_INET6) { if (inp.inp_flags & INP_COMPATV4) { fam = AF_INET; la = (unsigned char *)&inp.inp_laddr; } else la = (unsigned char *)&inp.inp_laddr6; } else #endif /* defined(HASIPv6) */ la = (unsigned char *)&inp.inp_laddr; lp = (int)ntohs(inp.inp_lport); if (fam == AF_INET && (inp.inp_faddr.s_addr != INADDR_ANY || inp.inp_fport != 0)) { fa = (unsigned char *)&inp.inp_faddr; fp = (int)ntohs(inp.inp_fport); } #if defined(HASIPv6) else if (fam == AF_INET6) { /* * If this is an IPv6 (AF_INET6) socket and IPv4 compatibility * mode is enabled, use the IPv4 address, change the family * indicator from AF_INET6 to AF_INET. Otherwise, use the IPv6 * address. Ignore empty addresses. */ if (inp.inp_flags & INP_COMPATV4) { fam = AF_INET; if (inp.inp_faddr.s_addr != INADDR_ANY || inp.inp_fport != 0) { fa = (unsigned char *)&inp.inp_faddr; fp = (int)ntohs(inp.inp_fport); } } else { if (!IN6_IS_ADDR_UNSPECIFIED(&inp.inp_faddr6)) { fa = (unsigned char *)&inp.inp_faddr6; fp = (int)ntohs(inp.inp_fport); } } } #endif /* defined(HASIPv6) */ if (fa || la) (void) ent_inaddr(la, lp, fa, fp, fam); if (ts) { Lf->lts.type = 0; Lf->lts.state.i = tsn; #if defined(HASSOOPT) Lf->lts.kai = (unsigned int)t.t_timer[TCPT_KEEP]; #endif /* defined(HASSOOPT) */ #if defined(HASTCPOPT) Lf->lts.mss = (unsigned long)t.t_maxseg; Lf->lts.msss = (unsigned char)1; Lf->lts.topt = (unsigned int)t.t_flags; #endif /* defined(HASTCPOPT) */ } break; /* * Process a ROUTE domain socket. */ case AF_ROUTE: (void) snpf(Lf->type, sizeof(Lf->type), "rte"); if (s.so_pcb) enter_dev_ch(print_kptr((KA_T)(s.so_pcb), (char *)NULL, 0)); else (void) snpf(Namech, Namechl, "no protocol control block"); if (!Fsize) Lf->off_def = 1; break; /* * Process a Unix domain socket. */ case AF_UNIX: if (Funix) Lf->sf |= SELUNX; (void) snpf(Lf->type, sizeof(Lf->type), "unix"); /* * Read Unix protocol control block and the Unix address structure. */ enter_dev_ch(print_kptr(sa, (char *)NULL, 0)); if (kread((KA_T) s.so_pcb, (char *)&unp, sizeof(unp))) { (void) snpf(Namech, Namechl, "can't read unpcb at %s", print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); break; } if ((struct socket *)sa != unp.unp_socket) { (void) snpf(Namech, Namechl, "unp_socket (%s) mismatch", print_kptr((KA_T)unp.unp_socket, (char *)NULL, 0)); break; } if (unp.unp_addr) { if (kread((KA_T) unp.unp_addr, (char *)&mb, sizeof(mb))) { (void) snpf(Namech, Namechl, "can't read unp_addr at %s", print_kptr((KA_T)unp.unp_addr, (char *)NULL, 0)); break; } #if AIXV>=3200 uo = (int)(mb.m_hdr.mh_data - (caddr_t)unp.unp_addr); if ((uo + sizeof(struct sockaddr)) <= sizeof(mb)) ua = (struct sockaddr_un *)((char *)&mb + uo); else { if (mb.m_hdr.mh_data && !kread((KA_T)mb.m_hdr.mh_data, (char *)&un, sizeof(un)) ) { ua = &un; } } #else /* AIXV<3200 */ ua = (struct sockaddr_un *)(((char *)&mb) + mb.m_off); #endif /* AIXV>=3200 */ } if (!ua) { ua = &un; (void) bzero((char *)ua, sizeof(un)); ua->sun_family = AF_UNSPEC; } /* * Print information on Unix socket that has no address bound * to it, although it may be connected to another Unix domain * socket as a pipe. */ if (ua->sun_family != AF_UNIX) { if (ua->sun_family == AF_UNSPEC) { if (unp.unp_conn) { if (kread((KA_T)unp.unp_conn, (char *)&uc, sizeof(uc))) (void) snpf(Namech, Namechl, "can't read unp_conn at %s", print_kptr((KA_T)unp.unp_conn,(char *)NULL,0)); else (void) snpf(Namech, Namechl, "->%s", print_kptr((KA_T)uc.unp_socket,(char *)NULL,0)); } else (void) snpf(Namech, Namechl, "->(none)"); } else (void) snpf(Namech, Namechl, "unknown sun_family (%d)", ua->sun_family); break; } /* * Read any associated vnode and then read its gnode and inode. */ g.gn_type = VSOCK; if (unp.unp_vnode && !readvnode((KA_T)unp.unp_vnode, &v)) { if (v.v_gnode && !readgnode((KA_T)v.v_gnode, &g)) { Lf->lock = isglocked(&g); if (g.gn_type == VSOCK && g.gn_data && !readlino(&g, &i)) is = 1; } } /* * Print Unix socket information. */ if (is) { Lf->dev = i.dev; Lf->dev_def = i.dev_def; if (Lf->dev_ch) { (void) free((FREE_P *)Lf->dev_ch); Lf->dev_ch = (char *)NULL; } Lf->inode = (INODETYPE)i.number; Lf->inp_ty = i.number_def; } if (ua->sun_path[0]) { if (mb.m_len > sizeof(struct sockaddr_un)) mb.m_len = sizeof(struct sockaddr_un); *((char *)ua + mb.m_len - 1) = '\0'; if (Sfile && is_file_named(ua->sun_path, VSOCK, 0, 0)) Lf->sf |= SELNM; if (!Namech[0]) (void) snpf(Namech, Namechl, "%s", ua->sun_path); } else (void) snpf(Namech, Namechl, "no address"); break; default: printunkaf(fam, 1); } if (Namech[0]) enter_nm(Namech); } lsof-4.86+dfsg.orig/dialects/aix/dproc.c0000444000175000017500000010215411077377737020326 0ustar nicholasnicholas/* * dproc.c - AIX process access functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dproc.c,v 1.26 2008/10/21 16:14:18 abe Exp $"; #endif #include "lsof.h" _PROTOTYPE(static void get_kernel_access,(void)); #if AIXA<2 _PROTOTYPE(static struct le *getle,(KA_T a, KA_T sid, char **err)); #endif /* AIXA<2 */ #if AIXV>=4110 _PROTOTYPE(static void getlenm,(struct le *le, KA_T sid)); #endif /* AIXV>=4110 */ _PROTOTYPE(static int kreadx,(KA_T addr, char *buf, int len, KA_T sid)); #if AIXA<2 _PROTOTYPE(static void process_text,(KA_T sid)); #else /* AIXA>=2 */ _PROTOTYPE(static void getsoinfo,(void)); _PROTOTYPE(static void process_text,(pid_t pid)); #endif /* AIXA<2 */ #if defined(SIGDANGER) # if defined(HASINTSIGNAL) _PROTOTYPE(static int lowpgsp,(int sig)); # else /* !defined(HASINTSIGNAL) */ _PROTOTYPE(static void lowpgsp,(int sig)); # endif /* defined(HASINTSIGNAL) */ #endif /* defined(SIGDANGER) */ /* * Local definitions */ #if AIXV<4300 #define PROCINFO procinfo #else /* AIXV>=4300 */ #define PROCINFO_INCR 256 # if AIXA<1 #define FDSINFO fdsinfo #define GETPROCS getprocs #define PROCINFO procsinfo # else /* AIXA>=1 */ #define FDSINFO fdsinfo64 #define GETPROCS getprocs64 #define PROCINFO procentry64 # if AIXA>1 /* * AIX 5 and greater ia64 loader definitions */ #include #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=4110 /* * Loader access definitions for AIX 4.1.1 and above. */ #define LIBNMLN 40 /* maximum library table name * length */ #define LIBMASK 0xf0000000 /* library table mask */ #define LIBNMCOMP 0xd0000000 /* library table name has * multiple components */ # if AIXA<1 #define RDXMASK 0x0fffffff /* kreadx() address mask */ # else /* AIXA>=1 */ #define RDXMASK 0x0fffffffffffffff /* kreadx() address mask */ #define URDXMASK 0x0fffffff00000000 /* upper part of RDXMASK */ # endif /* AIXA<1 */ #endif /* AIXV>=4110 */ /* * Loader structure definitions. (AIX doesn't supply ld_data.h.) */ struct le { /* loader entry */ struct le *next; /* next entry pointer */ #if AIXV<4300 ushort dummy1; ushort dummy2; uint dummy3; struct file *fp; /* file table entry pointer */ # if AIXV>=4110 int ft; /* file type indicator */ unsigned dummy4; char *dummy5; unsigned dummy6; char *dummy7[3]; char *nm; /* name */ # endif /* AIXV>=4110 */ #else /* AIXV>=4300 */ # if AIXA<2 uint flags; struct file *fp; /* file table entry pointer */ char *nm; /* name */ # else /* AIXA>=2 */ KA_T d1[2]; KA_T nm; /* name */ KA_T d2[10]; struct file *fp; /* file table entry pointer */ # endif /* AIXA<2 */ #endif /* AIXV<4300 */ }; #if AIXV>=4300 /* * The elements of interest from the AIX >= 4.3 loader anchor structure. */ struct la { /* loader anchor */ # if AIXA<2 struct le *list; struct le *exec; # else /* AIXA>=2 */ KA_T exec; KA_T list; # endif /* AIXA<2 */ }; #endif /* AIXV>=4300 */ /* * Local static values */ static int Np = 0; /* number of processes */ static struct PROCINFO *P = (struct PROCINFO *)NULL; /* the process table */ static struct user *Up; /* user structure */ #if AIXV>=4110 # if AIXA<2 static KA_T Soff; /* shared library VM offset */ int Soff_stat = 0; /* Soff-available status */ # endif /* AIXA<2 */ static KA_T Uo; /* user area VM offset */ #endif /* AIXV>=4110 */ /* * ckkv() - check kernel version */ void ckkv(d, er, ev, ea) char *d; /* dialect */ char *er; /* expected release */ char *ev; /* expected version */ char *ea; /* expected architecture */ { #if defined(HASKERNIDCK) # if AIXV<5000 /* * Use oslevel below AIX 5. */ int br, p[2], pid; char buf[128], *cp; struct stat sb; if (Fwarn) return; /* * Make sure we can execute OSLEVEL. If OSLEVEL doesn't exist and the AIX * version is below 4.1, return quietly. */ #define OSLEVEL "oslevel" #define OSLEVELPATH "/usr/bin/oslevel" if (stat(OSLEVELPATH, &sb)) { # if AIXV<4100 if (errno == ENOENT) return; # endif /* AIXV<4100 */ (void) fprintf(stderr, "%s: can't execute %s: %s\n", Pn, OSLEVELPATH, strerror(errno)); Exit(1); } if ((sb.st_mode & (S_IROTH | S_IXOTH)) != (S_IROTH | S_IXOTH)) { (void) fprintf(stderr, "%s: can't execute %s, modes: %o\n", Pn, OSLEVELPATH, sb.st_mode); Exit(1); } /* * Open a pipe for receiving the version number from OSLEVEL. Fork a * child to run OSLEVEL. Retrieve the OSLEVEL output. */ if (pipe(p)) { (void) fprintf(stderr, "%s: can't create pipe to: %s\n", Pn, OSLEVELPATH); Exit(1); } if ((pid = fork()) == 0) { (void) close(1); (void) close(2); (void) close(p[0]); dup2(p[1], 1); dup2(p[1], 2); (void) close(p[1]); execl(OSLEVELPATH, OSLEVEL, NULL); _exit(0); } if (pid < 0) { (void) fprintf(stderr, "%s: can't fork a child for %s: %s\n", Pn, OSLEVELPATH, strerror(errno)); Exit(1); } (void) close(p[1]); br = read(p[0], buf, sizeof(buf) - 1); (void) close(p[0]); (void) wait(NULL); /* * Warn if the actual and expected versions don't match. */ if (br > 0) { buf[br] = '\0'; if ((cp = strrchr(buf, '\n'))) *cp = '\0'; } else (void) snpf(buf, sizeof(buf), "UNKNOWN"); # else /* AIXV>=5000 */ /* * Use uname() for AIX 5 and above. */ char buf[64]; struct utsname u; (void) memset((void *)&u, 0, sizeof(u)); (void) uname(&u); (void) snpf(buf, sizeof(buf) - 1, "%s.%s.0.0", u.version, u.release); buf[sizeof(buf) - 1] = '\0'; # endif /* AIXV<5000 */ if (!ev || strcmp(buf, ev)) (void) fprintf(stderr, "%s: WARNING: compiled for %s version %s; this is %s.\n", Pn, d, ev ? ev : "UNKNOWN", buf); #endif /* defined(HASKERNIDCK) */ } /* * gather_proc_info() - gather process information */ void gather_proc_info() { short cckreg; /* conditional status of regular file * checking: * 0 = unconditionally check * 1 = conditionally check */ short ckscko; /* socket file only checking status: * 0 = none * 1 = check only socket files, * including TCP and UDP * streams with eXPORT data, * where supported */ KA_T cdir, fp, pdir, rdir; char *cmd; int hl, i, nf, np; struct PROCINFO *p; short pss, sf; struct user us; #if AIXV>=4300 static struct FDSINFO *fds = (struct FDSINFO *)NULL; MALLOC_S msz; # if AIXA==1 pid32_t pid; /* Since we're operating with types defined * under _KERNEL (see machine.), but * getprocs64() expects application types * (where pid_t is 32 bits), the pid variable * must be cast in an application-compatible * manner. */ # else /* AIXA!=1 */ pid_t pid; # endif /* AIXA==1 */ # if AIXV==4330 static int trx = 0; unsigned int mxof; static int uo = 0; # endif /* AIXV==4330 */ #endif /* AIXV>=4300 */ /* * Define socket and regular file conditional processing flags. * * If only socket files have been selected, or socket files have been * selected, ANDed with other selection options, enable the skipping of * regular files. * * If socket files and some process options have been selected, enable * conditional skipping of regular file; i.e., regular files will be skipped * unless they belong to a process selected by one of the specified options. */ if (Selflags & SELNW) { /* * Some network files selection options have been specified. */ if (Fand || !(Selflags & ~SELNW)) { /* * Selection ANDing or only network file options have been * specified, so set unconditional skipping of regular files * and socket file only checking. */ cckreg = 0; ckscko = 1; } else { /* * If ORed file selection options have been specified, or no * ORed process selection options have been specified, enable * unconditional file checking and clear socket file only * checking. * * If only ORed process selection options have been specified, * enable conditional file skipping and socket file only checking. */ if ((Selflags & SELFILE) || !(Selflags & SELPROC)) cckreg = ckscko = 0; else cckreg = ckscko = 1; } } else { /* * No network file selection options were specified. Enable * unconditional file checking and clear socket file only checking. */ cckreg = ckscko = 0; } /* * Read the process table. */ #if AIXV<4300 if (!P) { if (!(P = (struct PROCINFO *)malloc((MALLOC_S)PROCSIZE))) { (void) fprintf(stderr, "%s: can't allocate space for 1 proc\n", Pn); Exit(1); } Np = 1; } while (((np = getproc(P, Np, PROCSIZE)) == -1) && errno == ENOSPC) { Np = P->p_pid + 10; if (!(P = (struct PROCINFO *)realloc((MALLOC_P *)P, (size_t)(Np * PROCSIZE)))) { (void) fprintf(stderr, "%s: no space for %d procinfo's\n", Pn, Np); Exit(1); } } #else /* AIXV>=4300 */ if (!P) { msz = (MALLOC_S)(PROCSIZE * PROCINFO_INCR); if (!(P = (struct PROCINFO *)malloc(msz))) { (void) fprintf(stderr, "%s: can't allocate space for %d procs\n", Pn, PROCINFO_INCR); Exit(1); } Np = PROCINFO_INCR; } np = pid = 0; p = P; while ((i = GETPROCS(p, PROCSIZE, (struct FDSINFO *)NULL, 0, &pid, PROCINFO_INCR)) == PROCINFO_INCR) { np += PROCINFO_INCR; if (np >= Np) { msz = (MALLOC_S)(PROCSIZE * (Np + PROCINFO_INCR)); if (!(P = (struct PROCINFO *)realloc((MALLOC_P *)P, msz))) { (void) fprintf(stderr, "%s: no more space for proc storage\n", Pn); Exit(1); } Np += PROCINFO_INCR; } p = (struct PROCINFO *)((char *)P + (np * PROCSIZE)); } if (i > 0) np += i; #endif /* AIXV<4300 */ /* * Loop through processes. */ for (p = P, Up = &us; np > 0; np--, p++) { if (p->p_stat == 0 || p->p_stat == SZOMB) continue; if (is_proc_excl(p->p_pid, (int)p->p_pgid, (UID_ARG)p->p_uid, &pss, &sf)) continue; #if AIXV<4300 /* * Get user structure for AIX < 4.3. * * If AIX version is below 4.1.1, use getuser(). * * If AIX version is 4.1.1 or above: if readx() is disabled (no -X * option, use getuser(); if readx() is enabled (-X), use readx(). */ # if AIXV>=4110 if (Fxopt && kreadx(Uo, (char *)Up, U_SIZE, (KA_T)p->pi_adspace) == 0) i = 1; else i = 0; if (i == 0) { if (getuser(p, PROCSIZE, Up, U_SIZE) != 0) continue; } hl = i; # else /* AIXV<4110 */ if (getuser(p, PROCSIZE, Up, U_SIZE) != 0) continue; hl = 1; # endif /* AIXV>=4110 */ /* * Save directory vnode addresses, command name address, and open file * count from user structure. * * Skip processes excluded by the user structure command name. */ cdir = (KA_T)Up->u_cdir; # if AIXV<4100 pdir = (KA_T)Up->u_pdir; # endif /* AIXV<4100 */ rdir = (KA_T)Up->u_rdir; cmd = Up->u_comm; nf = Up->u_maxofile; if (is_cmd_excl(cmd, &pss, &sf)) continue; if (cckreg) { /* * If conditional checking of regular files is enabled, enable * socket file only checking, based on the process' selection * status. */ ckscko = (sf & SELPROC) ? 0 : 1; } #else /* AIXV>=4300 */ /* * For AIX 4.3 and above, skip processes excluded by the procsinfo * command name. Use getprocs() to get the file descriptors for * included processes. * * If readx is enabled (-X), use it to get the loader_anchor structure. */ if (is_cmd_excl(p->pi_comm, &pss, &sf)) continue; if (cckreg) { /* * If conditional checking of regular files is enabled, enable * socket file only checking, based on the process' selection * status. */ ckscko = (sf & SELPROC) ? 0 : 1; } if (!fds) { if (!(fds = (struct FDSINFO *)malloc((MALLOC_S)FDSINFOSIZE))) { (void) fprintf(stderr, "%s: can't allocate fdsinfo struct for PID %d\n", Pn, pid); Exit(1); } } pid = p->p_pid; if (GETPROCS((struct PROCINFO *)NULL, PROCSIZE, fds, FDSINFOSIZE, &pid, 1) != 1) continue; hl = 0; # if AIXV==4330 /* * Handle readx() for AIX 4.3.3 specially, because 4.3.3 was released * with two different user struct definitions in 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 header files differed. U_maxofile * follows U_loader by the same number of elements in both * user structs, so the U_loader offset should be the same as * the U_maxofile offset. */ if (!kreadx((KA_T)((char *)Uo + offsetof(struct user,U_maxofile) + uo), (char *)&mxof, sizeof(mxof), (KA_T)p->pi_adspace) && (mxof == p->pi_maxofile)) { hl = trx = 1; break; } if (uo == 0) uo = 48; else if (uo == 48) uo = -48; else { Fxopt = hl = 0; trx = 1; if (!Fwarn) { (void) fprintf(stderr, "%s: WARNING: user struct mismatch;", Pn); (void) fprintf(stderr, " -X option disabled.\n"); } break; } } } # else /* AIXV!=4330 */ if (Fxopt && kreadx((KA_T)((char *)Uo + offsetof(struct user, U_loader)), (char *)&Up->U_loader, sizeof(struct la), (KA_T)p->pi_adspace) == 0) hl = 1; # endif /* AIXV==4330 */ /* * Save directory vnode addresses, command name, and open file count * from procinfo structure. */ cdir = (KA_T)p->pi_cdir; pdir = (KA_T)NULL; rdir = (KA_T)p->pi_rdir; cmd = p->pi_comm; nf = p->pi_maxofile; #endif /* AIXV<4300 */ /* * Allocate a local process structure and start filling it. */ alloc_lproc(p->p_pid, (int)p->p_pgid, (int)p->p_ppid, (UID_ARG)p->p_uid, cmd, (int)pss, (int)sf); Plf = (struct lfile *)NULL; /* * Save current working directory information. */ if (!ckscko && cdir) { alloc_lfile(CWD, -1); process_node(cdir); if (Lf->sf) link_lfile(); } /* * Save root directory information. */ if (!ckscko && rdir) { alloc_lfile(RTD, -1); process_node(rdir); if (Lf->sf) link_lfile(); } #if AIXV<4100 /* * Save parent directory information. */ if (!ckscko && pdir) { alloc_lfile(" pd", -1); process_node(pdir); if (Lf->sf) link_lfile(); } #endif /* AIXV<4100 */ /* * Save information on text files. */ if (!ckscko && hl) { #if AIXA<2 # if AIXA<1 process_text((KA_T)p->pi_adspace); # else /* AIXA==1 */ { int ck = 1; KA_T sid = (KA_T)p->pi_adspace; if ((Up->U_loader[0] & URDXMASK) || (Up->U_loader[1] & URDXMASK)) { /* * If the upper part of either loader map address is * non-zero and this is not the lsof process, skip the * processing of text files. If this is the lsof process, * set the segment address to zero, forcing text file * information to come from kmem rather than mem. */ if (Mypid == p->p_pid) sid = (KA_T)0; else ck = 0; } if (ck) process_text(sid); } # endif /* AIXA<1 */ #else /* AIXA>=2 */ process_text(p->p_pid); #endif /* AIXA<2 */ } /* * Save information on file descriptors. */ for (i = 0; i < nf; i++) { #if AIXV<4300 fp = (KA_T)Up->u_ufd[i].fp; #else /* AIXV>=4300 */ fp = (KA_T)fds->pi_ufd[i].fp; #endif /* AIXV<4300 */ if (fp) { alloc_lfile((char *)NULL, i); process_file(fp); if (Lf->sf) { #if defined(HASFSTRUCT) if (Fsv & FSV_FG) # if AIXV<4300 Lf->pof = (long)(Up->u_ufd[i].flags & 0x7f); #else /* AIXV>=4300 */ Lf->pof = (long)(fds->pi_ufd[i].flags & 0x7f); #endif /* AIXV<4300 */ #endif /* defined(HASFSTRUCT) */ link_lfile(); } } } /* * Examine results. */ if (examine_lproc()) return; } } /* * get_kernel_access() - get access to kernel memory */ static void get_kernel_access() { int oe = 0; #if defined(AIX_KERNBITS) int kb; char *kbb, *kbr; /* * Check the kernel bit size against the size for which this executable was * configured. */ if (__KERNEL_32()) { kb = 32; kbr = "32"; } else if (__KERNEL_64()) { kb = 64; kbr = "64"; } else { kb = 0; kbr = "unknown"; } if ((AIX_KERNBITS == 0) || !kb || (kb != AIX_KERNBITS)) { if (AIX_KERNBITS == 32) kbb = "32"; else if (AIX_KERNBITS == 64) kbb = "64"; else kbb = "unknown"; (void) fprintf(stderr, "%s: FATAL: compiled for a kernel of %s bit size.\n", Pn, kbb); (void) fprintf(stderr, " The bit size of this kernel is %s.\n", kbr); Exit(1); } #endif /* defined(AIX_KERNBITS) */ /* * Access /dev/mem. */ if ((Km = open("/dev/mem", O_RDONLY, 0)) < 0) { (void) fprintf(stderr, "%s: can't open /dev/mem: %s\n", Pn, strerror(errno)); oe++; } #if defined(WILLDROPGID) /* * If kernel memory isn't coming from KMEM, drop setgid permission * before attempting to open the (Memory) file. */ if (Memory) (void) dropgid(); #else /* !defined(WILLDROPGID) */ /* * See if the non-KMEM memory file is readable. */ if (Memory && !is_readable(Memory, 1)) Exit(1); #endif /* defined(WILLDROPGID) */ /* * Access kernel memory file. */ if ((Kd = open(Memory ? Memory : KMEM, O_RDONLY, 0)) < 0) { (void) fprintf(stderr, "%s: can't open %s: %s\n", Pn, Memory ? Memory : KMEM, strerror(errno)); oe++; } if (oe) Exit(1); #if defined(WILLDROPGID) /* * Drop setgid permission, if necessary. */ if (!Memory) (void) dropgid(); #endif /* defined(WILLDROPGID) */ /* * Get kernel symbols. */ if (knlist(Nl, X_NL_NUM, sizeof(struct nlist)) || !Nl[X_UADDR].n_value) { (void) fprintf(stderr, "%s: can't get kernel's %s address\n", Pn, Nl[X_UADDR].n_name); Exit(1); } #if defined(HAS_AFS) (void) knlist(AFSnl, X_AFSNL_NUM, sizeof(struct nlist)); #endif /* defined(HAS_AFS) */ #if AIXV>=4110 /* * Get user area and shared library VM offsets for AIX 4.1.1 and above. */ if (Fxopt) { struct ublock *ub; # if AIXA<2 struct nlist ll[] = { { "library_anchor" }, # if AIXV>=4330 { "library_le_handle" }, # else /* AIXV<4330 */ { "library_data_handle" }, # endif /* AIXV>=4330 */ { (char *)NULL } }; if (nlist(N_UNIX, ll) == 0 && ll[0].n_value != (long)0 && ll[1].n_value != (long)0 && kreadx((KA_T)(ll[1].n_value & RDXMASK), (char *)&Soff, sizeof(Soff), (KA_T)0) == 0) Soff_stat++; # endif /* AIXA<2 */ ub = (struct ublock *)Nl[X_UADDR].n_value; Uo = (KA_T)((KA_T)&ub->ub_user & RDXMASK); } #endif /* AIXV>=4110 */ /* * Check the kernel version number. */ (void) ckkv("AIX", (char *)NULL, LSOF_VSTR, (char *)NULL); #if defined(SIGDANGER) /* * If SIGDANGER is defined, enable its handler. */ (void) signal(SIGDANGER, lowpgsp); #endif /* defined(SIGDANGER) */ } #if AIXA<2 /* * getle() - get loader entry structure */ static struct le * getle(a, sid, err) KA_T a; /* loader entry kernel address */ KA_T sid; /* user structure segment ID */ char **err; /* error message (if return is NULL) */ { static struct le le; #if AIXV<4110 if (a < Nl[X_UADDR].n_value) { *err = "address too small"; return((struct le *)NULL); } if (((char *)a + sizeof(le)) <= ((char *)Nl[X_UADDR].n_value + U_SIZE)) return((struct le *)((char *)Up + a - Nl[X_UADDR].n_value)); #endif /* AIXV<4110 */ if (!Fxopt) { *err = "readx() disabled for Stale Segment ID bug (see -X)"; return((struct le *)NULL); } #if AIXV>=4110 if (!sid) { if (!kread(a, (char *)&le, sizeof(le))) return(&le); } else { if (!kreadx((KA_T)(a & RDXMASK),(char *)&le,sizeof(le),(KA_T)sid)) return(&le); } #else /* AIXV<4110 */ if (!kreadx((KA_T)a, (char *)&le, sizeof(le), (KA_T)sid)) return(&le); #endif /* AIXV>=4110 */ getle_err: *err = "can't readx()"; return((struct le *)NULL); } #endif /* AIXA<2 */ #if AIXV>=4110 /* * getlenm() - get loader entry file name for AIX >= 4.1.1 */ static void getlenm(le, sid) struct le *le; /* loader entry structure */ KA_T sid; /* segment ID */ { char buf[LIBNMLN]; int i; # if AIXV<4300 if ((le->ft & LIBMASK) != LIBNMCOMP) return; #else /* AIXV>=4300 */ # if AIXA<2 if (!sid) { if (kread((KA_T)le->nm, buf, LIBNMLN)) return; } else { if (!Soff_stat || !le->nm || kreadx((KA_T)le->nm & (KA_T)RDXMASK, buf, LIBNMLN, (KA_T)Soff)) return; } buf[LIBNMLN - 1] = '\0'; i = strlen(buf); if (i < (LIBNMLN - 3) && buf[i+1]) enter_nm(&buf[i+1]); else if (buf[0]) enter_nm(buf); # else /* AIXA>=2 */ if (!le->nm || kread(le->nm, buf, sizeof(buf))) return; buf[LIBNMLN - 1] = '\0'; if (!strlen(buf)) return; enter_nm(buf); # endif /* AIXA<2 */ #endif /* AIXV<4300 */ } #endif /* AIXV>=4110 */ #if AIXA>1 /* * getsoinfo() - get *.so information for ia64 AIX >= 5 */ static void getsoinfo() { char buf[65536]; uint bufsz = (uint) sizeof(buf); int ct, h; char *ln = (char *)NULL; char *rn = (char *)NULL; LDR_Mod_info_t *lp; struct stat sb; so_hash_t *sp; /* * See if loader information is needed. Warn if this process has insufficient * permission to acquire it from all processes. */ if (!Fxopt) return; if ((Myuid != 0) && !Setuidroot && !Fwarn) { (void) fprintf(stderr, "%s: WARNING: insufficient permission to access all", Pn); (void) fprintf(stderr, " /%s/object sub-\n", HASPROCFS); (void) fprintf(stderr, " directories; some loader information may", Pn); (void) fprintf(stderr, " be unavailable.\n"); } /* * Get the loader module table. Allocate hash space for it. */ if ((ct = ldr_get_modules(SOL_GLOBAL, (void *)buf, &bufsz)) < 1) return; if (!(SoHash = (so_hash_t **)calloc((MALLOC_S)SOHASHBUCKS, sizeof(so_hash_t *)))) { (void) fprintf(stderr, "%s: no space for *.so hash buckets\n", Pn); Exit(1); } /* * Cache the loader module information, complete with stat(2) results. */ for (lp = (LDR_Mod_info_t *)buf; ct; ct--, lp++) { /* * Release previous name space allocations. */ if (ln) { (void) free((MALLOC_P *)ln); ln = (char *)NULL; } if (rn) { (void) free((MALLOC_P *)rn); rn = (char *)NULL; } /* * Make a copy of the loader module name. */ if (!(rn = mkstrcpy(lp->mi_name, (MALLOC_S *)NULL))) { (void) fprintf(stderr, "%s: no space for name: %s\n", Pn, lp->mi_name); Exit(1); } /* * Resolve symbolic links. */ ln = Readlink(rn); if (ln == rn) rn = (char *)NULL; /* * Get stat(2) information. */ if (statsafely(ln, &sb)) { if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: can't stat: %s\n", Pn, ln); continue; } /* * Allocate and fill a loader information hash structure. */ if (!(sp = (so_hash_t *)malloc((MALLOC_S)sizeof(so_hash_t)))) { (void) fprintf(stderr, "%s: no space for *.so hash entry: %s\n", Pn, ln); Exit(1); } sp->dev = sb.st_dev; sp->nlink = (int)sb.st_nlink; sp->nm = ln; ln = (char *)NULL; sp->node = (INODETYPE)sb.st_ino; sp->sz = (SZOFFTYPE)sb.st_size; /* * Link the structure to the appropriate hash bucket. */ h = SOHASH(sb.st_dev, (INODETYPE)sb.st_ino); if (SoHash[h]) sp->next = SoHash[h]; else sp->next = (so_hash_t *)NULL; SoHash[h] = sp; } /* * Free any unused name space that was allocated. */ if (ln) (void) free((MALLOC_P *)ln); if (rn) (void) free((MALLOC_P *)rn); } #endif /* AIXA>1 */ /* * initialize() - perform all initialization */ void initialize() { get_kernel_access(); #if AIXA>1 (void) getsoinfo(); #endif /* AIXA>1 */ } /* * kread() - read from kernel memory */ int kread(addr, buf, len) KA_T addr; /* kernel memory address */ char *buf; /* buffer to receive data */ READLEN_T len; /* length to read */ { int br; #if AIXV<4200 if (lseek(Kd, (off_t)addr, L_SET) == (off_t)-1) #else /* AIXV>=4200 */ if (lseek64(Kd, (off64_t)addr, L_SET) == (off64_t)-1) #endif /* AIXV<4200 */ return(1); br = read(Kd, buf, len); return((br == len) ? 0 : 1); } /* * kreadx() - read kernel segmented memory */ int kreadx(addr, buf, len, sid) KA_T addr; /* kernel address */ char *buf; /* destination buffer */ int len; /* length */ KA_T sid; /* segment ID */ { int br; #if AIXV<4200 if (lseek(Km, addr, L_SET) == (off_t)-1) #else /* AIXV>=4200 */ if (lseek64(Km, (off64_t)addr, L_SET) == (off64_t)-1) #endif /* AIXV<4200 */ return(1); br = readx(Km, buf, len, sid); return (br == len ? 0 : 1); } #if defined(SIGDANGER) /* * lowpgsp() - hangle a SIGDANGER signal about low paging space */ # if defined(HASINTSIGNAL) static int # else /* !defined(HASINTSIGNAL) */ static void # endif /* defined(HASINTSIGNAL) */ lowpgsp(sig) int sig; { (void) fprintf(stderr, "%s: FATAL: system paging space is low.\n", Pn); Exit(1); } #endif /* defined(SIGDANGER) */ #if AIXA<2 /* * process_text() - process text file information for non-ia64 AIX */ static void process_text(sid) KA_T sid; /* user area segment ID */ { char *err, fd[8]; static struct file **f = (struct file **)NULL; int i, j, n; struct le *le; KA_T ll; MALLOC_S msz; static MALLOC_S nf = 0; struct file *xf = (struct file *)NULL; #if AIXV>=4300 struct la *la = (struct la *)&Up->U_loader; #endif /* AIXV>=4300 */ /* * Display information on the exec'd entry. */ #if AIXV<4300 if ((ll = (KA_T)Up->u_loader[1])) #else /* AIXV>=4300 */ if ((ll = (KA_T)la->exec)) #endif /* AIXV<4300 */ { alloc_lfile(" txt", -1); if ((le = getle(ll, sid, &err))) { if ((xf = le->fp)) { process_file((KA_T)xf); if (Lf->sf) { #if AIXV>=4110 && AIXV<4300 if (!Lf->nm || !Lf->nm[0]) getlenm(le, sid); #endif /* AIXV>=4110 && AIXV<4300 */ link_lfile(); } } } else { (void) snpf(Namech, Namechl, "text entry at %s: %s", print_kptr((KA_T)ll, (char *)NULL, 0), err); enter_nm(Namech); if (Lf->sf) link_lfile(); } } /* * Display the loader list. */ for (i = n = 0, #if AIXV<4300 ll = (KA_T)Up->u_loader[0]; #else /* AIXV>=4300 */ ll = (KA_T)la->list; #endif /* AIXV<4300 */ ll; ll = (KA_T)le->next) { (void) snpf(fd, sizeof(fd), " L%02d", i); alloc_lfile(fd, -1); if (!(le = getle(ll, sid, &err))) { (void) snpf(Namech, Namechl, "loader entry at %s: %s", print_kptr((KA_T)ll, (char *)NULL, 0), err); enter_nm(Namech); if (Lf->sf) link_lfile(); return; } /* * Skip entries with no file pointers, the exec'd file, and entries * that have already been processed. */ if (!le->fp || (le->fp == xf)) continue; for (j = 0; j < n; j++) { if (f[j] == le->fp) break; } if (j < n) continue; if (n >= nf) { /* * Allocate file structure address cache space. */ nf += 10; msz = (MALLOC_S)(nf * sizeof(struct file *)); if (f) f = (struct file **)realloc((MALLOC_P *)f, msz); else f = (struct file **)malloc(msz); if (!f) { (void) fprintf(stderr, "%s: no space for text file pointers\n", Pn); Exit(1); } } f[n++] = le->fp; /* * Save the loader entry. */ process_file((KA_T)le->fp); if (Lf->sf) { #if AIXV>=4110 if (!Lf->nm || !Lf->nm[0]) getlenm(le, sid); #endif /* AIXV>=4110 */ link_lfile(); i++; } } } #else /* AIXA>=2 */ /* * process_text() - process text file information for ia64 AIX >= 5 */ static void process_text(pid) pid_t pid; /* process PID */ { char buf[MAXPATHLEN+1], fd[8], *nm, *pp; size_t bufl = sizeof(buf); DIR *dfp; struct dirent *dp; int i; struct la *la = (struct la *)&Up->U_loader; struct le le; struct lfile *lf; struct stat sb; so_hash_t *sp; size_t sz; dev_t xdev; INODETYPE xnode; int xs = 0; /* * Display information on the exec'd entry. */ if (la->exec && !kread((KA_T)la->exec, (char *)&le, sizeof(le)) && le.fp) { alloc_lfile(" txt", -1); process_file((KA_T)le.fp); if (Lf->dev_def && (Lf->inp_ty == 1)) { xdev = Lf->dev; xnode = Lf->inode; xs = 1; } if (Lf->sf) { if (!Lf->nm || !Lf->nm[0]) getlenm(&le, (KA_T)0); link_lfile(); } } /* * Collect devices and names for the entries in /HASPROCFS/PID/object -- the * AIX 5 loader list equivalent. When things fail in this processing -- most * likely for insufficient permissions -- be silent; a warning was issued by * getsoinfo(). */ (void) snpf(buf, bufl, "/%s/%ld/object", HASPROCFS, (long)pid); if (!(dfp = opendir(buf))) return; if ((sz = strlen(buf)) >= bufl) return; buf[sz++] = '/'; pp = &buf[sz]; sz = bufl - sz; /* * Read the entries in the /HASPROCFS/PID/object subdirectory. */ for (dp = readdir(dfp), i = 0; dp; dp = readdir(dfp)) { /* * Skip '.', "..", entries with no node number, and entries whose * names are too long. */ if (!dp->d_ino || (dp->d_name[0] == '.')) continue; if ((dp->d_namlen + 1) >= sz) continue; (void) strncpy(pp, dp->d_name, dp->d_namlen); pp[dp->d_namlen] = '\0'; /* * Get stat(2) information. */ if (statsafely(buf, &sb)) continue; /* * Ignore the exec'd and non-regular files. */ if (xs && (xdev == sb.st_dev) && (xnode == (INODETYPE)sb.st_ino)) continue; if (!S_ISREG(sb.st_mode)) continue; /* * Allocate space for a file entry. Set its basic characteristics. */ (void) snpf(fd, sizeof(fd), "L%02d", i++); alloc_lfile(fd, -1); Lf->dev_def = Lf->inp_ty = Lf->nlink_def = Lf->sz_def = 1; Lf->dev = sb.st_dev; Lf->inode = (INODETYPE)sb.st_ino; (void) snpf(Lf->type, sizeof(Lf->type), "VREG"); /* * Look for a match on device and node numbers in the *.so cache. */ for (sp = SoHash[SOHASH(sb.st_dev, (INODETYPE)sb.st_ino)]; sp; sp = sp->next) { if ((sp->dev == sb.st_dev) && (sp->node == (INODETYPE)sb.st_ino)) { /* * A match was found; use its name, link count, and size. */ nm = sp->nm; Lf->nlink = sp->nlink; Lf->sz = sp->sz; break; } } if (!sp) { /* * No match was found; use the /HASPROCFS/object name, its link * count, and its size. */ nm = pp; Lf->nlink_def = sb.st_nlink; Lf->sz = sb.st_size; } /* * Do selection tests: NFS; link count; file name; and file system. */ # if defined(HAS_NFS) if (Fnfs && (GET_MIN_DEV(Lf->dev_def) & SDEV_REMOTE)) Lf->sf |= SELNFS; # endif /* defined(HAS_NFS) */ if (Nlink && (Lf->nlink < Nlink)) Lf->sf |= SELNLINK; if (Sfile && is_file_named(NULL, VREG, 0, 0)) Lf->sf |= SELNM; if (Lf->sf) { /* * If the file was selected, enter its name and link it to the * other files of the process. */ enter_nm(nm); link_lfile(); } } (void) closedir(dfp); } #endif /* AIXA<2 */ lsof-4.86+dfsg.orig/dialects/aix/dproto.h0000444000175000017500000000421210023724577020513 0ustar nicholasnicholas/* * dproto.h - AIX function prototypes for lsof * * The _PROTOTYPE macro is defined in the common proto.h. */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: dproto.h,v 1.4 2004/03/10 23:49:13 abe Exp $ */ #if !defined(DPROTO_H) #define DPROTO_H # if defined(HAS_AFS) _PROTOTYPE(extern struct vnode *alloc_vcache,(void)); _PROTOTYPE(extern int hasAFS,(struct vnode *vp)); _PROTOTYPE(extern int readafsnode,(KA_T va, struct vnode *v, struct afsnode *an)); # endif /* defined(HAS_AFS) */ # if defined(HAS_JFS2) _PROTOTYPE(extern int readj2lino,(struct gnode *ga, struct l_ino *li)); # endif /* defined(HAS_JFS2) */ _PROTOTYPE(extern int getchan,(char *p)); _PROTOTYPE(extern int is_file_named,(char *p, enum vtype ty, chan_t ch, int ic)); _PROTOTYPE(extern char isglocked,(struct gnode *ga)); _PROTOTYPE(extern int readlino,(struct gnode *ga, struct l_ino *li)); _PROTOTYPE(extern struct l_vfs *readvfs,(struct vnode *vn)); # if AIXV>=4200 _PROTOTYPE(extern void process_shmt,(KA_T sa)); # endif /* AIV>=4200 */ # if defined(HASDCACHE) && AIXV>=4140 _PROTOTYPE(extern void clr_sect,(void)); _PROTOTYPE(extern int rw_clone_sect,(int m)); # endif /* defined(HASDCACHE) && AIXV>=4140 */ #endif /* !defined(DPROTO_H) */ lsof-4.86+dfsg.orig/dialects/aix/dlsof.h0000444000175000017500000002333210412070245020303 0ustar nicholasnicholas/* * dlsof.h - AIX header file for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ /* * $Id: dlsof.h,v 1.32 2006/03/27 23:09:21 abe Exp $ */ #if !defined(AIX_LSOF_H) #define AIX_LSOF_H 1 /* * AIXA stands for AIX architecure. It is given these values in the * aix stanza of the lsof Configure script: * * 0 The AIX version is < 5, or the AIX architecture is power and * the kernel bit size is 32. * * 1 The AIX version is >= 5, the AIX architecture is Power, and * the kernel bit size is 64. * * 2 The AIX version is > 5 and the architecture is IA64. */ # if AIXA>1 #include # endif /* AIXA>1 */ #include #include #include #include #include # if !defined(_KERNEL) #define _KERNEL 1 # endif /* !defined(_KERNEL) */ #include #include #include /* #includes */ #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 # endif /* AIXV<4300 */ #define p_uid pi_uid #undef sleep #undef _KERNEL # if AIXA>1 #define _NET_NET_MALLOC /* to keep from #include'ing * , which is missing from * ia64 AIX 5L */ # endif /* AIXA>1 */ #include #include #include #include #include # if AIXV>=4140 #include # endif /* AIXV>=4140 */ #include #include #include # if defined(HASKERNIDCK) && AIXV>=5000 #include # endif /* defined(HASKERNIDCK) && AIXV>=5000 */ #include #include #include # if AIXV>=4100 #include # endif /* AIXV>=4100 */ #include #include #include #include #include #include #include #include #include #include #include # if defined(HAS_AFS) #define __XDR_INCLUDE__ # endif /* defined(HAS_AFS) */ #include #include # 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 # 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 . */ # 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 #include #include #include # endif /* defined(HAS_AFS) */ /* * Miscellaneous definitions. */ # if defined(HAS_AFS) #define AFSAPATHDEF "/usr/vice/etc/dkload/???" #define AFSDEV 1 /* AFS "fake" device number */ # if !defined(MNT_AFS) #define MNT_AFS AFS_MOUNT_AFS # endif /* !defined(MNT_AFS) */ # endif /* defined(HAS_AFS) */ #define COMP_P const void #define DEVINCR 1024 /* device table malloc() increment */ # if AIXV<4200 typedef off_t KA_T; # else /* AIXV>=4200 */ # if AIXA<1 typedef unsigned int KA_T; # else /* AIXA>=1 */ typedef u_longlong_t KA_T; #define GET_MAJ_DEV(d) (ISDEVNO64(d) ? major64(d) : major(d & ~SDEV_REMOTE)) #define GET_MIN_DEV(d) (ISDEVNO64(d) ? (minor64(d) & ~SDEV_REMOTE) : minor(d)) #define KA_T_FMT_X "%#llx" # endif /* AIXA<1 */ # endif /* AIXV<4200 */ #define KMEM "/dev/kmem" # if defined(HASSTAT64) #define fstat fstat64 #define lstat lstat64 #define stat stat64 # endif /* defined(HASSTAT64) */ #define MALLOC_P char #define FREE_P MALLOC_P #define MALLOC_S size_t #define MAXSYSCMDL MAXCOMLEN /* max system command name length */ #define N_UNIX "/unix" #define QSORT_P void #define READLEN_T size_t #define STRNCPY_L size_t # if AIXV>=4200 #define SZOFFTYPE unsigned long long /* size and offset type definition */ #define SZOFFPSPEC "ll" /* SZOFFTYPE print specification modifier */ # endif /* AIXV>=4200 */ #define U_SIZE sizeof(struct user) /* * Name list (Nl[]) indexes */ #define X_UADDR 0 #define X_NL_NUM 1 /* * Definition for ckfa.c */ #define CKFA_MPXCHAN 1 /* * Definitions for dvch.c */ # if AIXV>=4140 #define DCACHE_CLONE rw_clone_sect /* clone function for read_dcache */ #define DCACHE_CLR clr_sect /* function to clear clone and * pseudo caches when reading the * device cache file fails */ # endif /* AIXV>=4140 */ /* * Definitions for enter_dir() */ #define DIRTYPE dirent #define HASDNAMLEN 1 # if defined(HAS_AFS) /* * AFS name list (AFSnl[]) indexes */ #define X_AFS_FID 0 #define X_AFS_VOL 1 #define X_AFSNL_NUM 2 # endif /* defined(HAS_AFS) */ # if AIXV>=4140 /* * Local clone information */ struct clone { struct l_dev cd; /* device, inode, name, verify status */ struct clone *next; /* next entry */ }; extern struct clone *Clone; extern int CloneMaj; extern int ClonePtc; #endif /* AIXV>=4140 */ /* * Local inode information */ struct l_ino { dev_t dev; /* device */ long nlink; /* link count */ INODETYPE number; /* inode number */ SZOFFTYPE size; /* file size */ unsigned char dev_def; /* link count is defined */ unsigned char nlink_def; /* link count is defined */ unsigned char number_def; /* number is defined */ unsigned char size_def; /* size is defined */ }; /* * Local vfs information */ struct l_vfs { KA_T addr; /* kernel address */ dev_t dev; /* device */ char *dir; /* mounted directory */ char *fsname; /* file system name */ int vmt_flags; /* vmount flags */ int vmt_gfstype; /* vmount gfs type */ struct l_vfs *next; /* forward link */ }; extern struct l_vfs *Lvfs; /* * Local mount information */ struct mounts { char *dir; /* directory (mounted on) */ char *fsname; /* file system * (symbolic links unresolved) */ char *fsnmres; /* file system * (symbolic links resolved) */ dev_t dev; /* directory st_dev */ dev_t rdev; /* directory st_rdev */ INODETYPE inode; /* directory st_ino */ u_short mode; /* directory st_mode */ u_short fs_mode; /* file system st_mode */ # if defined(HASFSTYPE) int fstype; /* fs type */ # endif /* defined(HASFSTYPE) */ struct mounts *next; /* forward link */ }; extern struct mounts *Mtab; /* * Search file information */ struct sfile { char *aname; /* file name argument */ char *name; /* file name (after readlink()) */ char *devnm; /* device name (optional) */ dev_t dev; /* device */ dev_t rdev; /* raw device */ chan_t ch; /* channel (last path component, * (if numeric) */ u_short mode; /* S_IFMT mode bits from stat() */ int type; /* file type: 0 = file system * 1 = regular file */ INODETYPE i; /* inode number */ int f; /* file found flag */ struct sfile *next; /* forward link */ }; /* * Miscellaneous external definitions */ # if defined(HAS_AFS) extern struct nlist AFSnl[]; /* AFS kernel symbol name list table */ # if defined(HASAOPT) extern char *AFSApath; /* alternate AFS name list path (from -a) */ # endif /* defined(HASAOPT) */ extern KA_T AFSVfsp; /* AFS struct vfs kernel pointer */ # endif /* defined(HAS_AFS) */ extern int Kd; extern int Km; extern struct nlist Nl[]; # if defined(TCPSTATES) && AIXV<=3250 /* * For AIX 3.2.5 and below, there is no header file with the definition * of tcpstates[], needed by ptti.c's print_tcptpi() function. */ static char *tcpstates[] = { "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD", "ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING", "LAST_ACK", "FIN_WAIT_2", "TIME_WAIT" }; # endif /* defined(TCPSTATES) && AIXV<=3250 */ # if AIXA>1 /* * This AIX 5 or above ia64 hack prevents the loader from linking lsof's * kread() in preference to the kread() that read() uses. The very existence * of a system kread() is an unwarrranted invasion of user name space! */ #define kread lsof_kread /* avoid conflict with the kread() * in libc.so */ # endif /* AIXA>1 */ #endif /* AIX_LSOF_H */ lsof-4.86+dfsg.orig/dialects/aix/dnode1.c0000444000175000017500000001605410275733246020362 0ustar nicholasnicholas/* * dnode1.c - AIX AFS support */ /* * Copyright 1996 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1996 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dnode1.c,v 1.10 2005/08/08 19:46:38 abe Exp $"; #endif #if defined(HAS_AFS) #include "lsof.h" /* * This is an emulation of the afs_rwlock_t definition that appears in * the AFS sources in afs/lock.h. */ struct afs_lock { # if HAS_AFS<304 unsigned long d1[4]; # else /* HAS_AFS>=304 */ unsigned char d1[2]; unsigned short d2[3]; struct timeval d3; unsigned int d4[3]; # endif /* HAS_AFS<304 */ }; typedef struct afs_lock afs_lock_t; typedef struct afs_lock afs_rwlock_t; #define KERNEL #include #undef KERNEL /* * Local function prototypes */ _PROTOTYPE(static struct volume *getvolume,(struct VenusFid *f, int *vols)); _PROTOTYPE(static int is_rootFid,(struct vcache *vc, int *rfid)); /* * alloc_vcache() - allocate space for vcache structure */ struct vnode * alloc_vcache() { return((struct vnode *)malloc((MALLOC_S)sizeof(struct vcache))); } /* * getvolume() - get volume structure */ static struct volume * getvolume(f, vols) struct VenusFid *f; /* file ID pointer */ int *vols; /* afs_volumes status return */ { int i; static KA_T ka = 0; KA_T kh; static struct volume v; struct volume *vp; static int w = 0; if (!ka) { if ((ka = (KA_T)AFSnl[X_AFS_VOL].n_value) == (KA_T)0) { if (!w && !Fwarn) { (void) fprintf(stderr, "%s: WARNING: no kernel address for: %s\n", Pn, AFSnl[X_AFS_VOL]._n._n_name); (void) fprintf(stderr, " This may hamper AFS node number reporting.\n"); w = 1; } *vols = 0; return((struct volume *)NULL); } } *vols = 1; i = (NVOLS - 1) & f->Fid.Volume; kh = (KA_T)((char *)ka + (i * sizeof(struct volume *))); if (kread(kh, (char *)&vp, sizeof(vp))) return((struct volume *)NULL); while (vp) { if (kread((KA_T)vp, (char *)&v, sizeof(v))) return((struct volume *)NULL); if (v.volume == f->Fid.Volume && v.cell == f->Cell) return(&v); vp = v.next; } return((struct volume *)NULL); } /* * hasAFS() - test for AFS presence via vfs structure */ int hasAFS(vp) struct vnode *vp; /* vnode pointer */ { struct vmount vm; struct vfs v; /* * If this vnode has a v_data pointer, then it probably isn't an AFS vnode; * return FALSE. * * If the vfs struct address of /afs is known and this vnode's v_vfsp matches * it, return TRUE. * * Read this vnode's vfs structure and its mount data. If the gfs type isn't * AFS, return FALSE. If it is, save the vnode's v_vfsp as AFSVfsp and return * TRUE. */ if (AFSVfsp && !vp->v_data && (KA_T)vp->v_vfsp == AFSVfsp) return(1); if (vp->v_data || !vp->v_vfsp) return(0); if (kread((KA_T)vp->v_vfsp, (char *)&v, sizeof(v))) return(0); if (!v.vfs_mdata || kread((KA_T)v.vfs_mdata, (char *)&vm, sizeof(vm))) return(0); if (vm.vmt_gfstype != MNT_AFS) return(0); AFSVfsp = (KA_T)vp->v_vfsp; return(1); } /* * is_rootFid() - is the file ID the root file ID * * return: 0 = is not root file ID * 1 = is root file ID * rfid = 0 if root file ID structure address not available * 1 if root file ID structure address available */ static int is_rootFid(vc, rfid) struct vcache *vc; /* vcache entry */ int *rfid; /* root file ID pointer status return */ { int err; static int f = 0; /* rootFID structure status: * -1 = unavailable * 0 = not yet accessed * 1 = available */ static struct VenusFid r; static int w = 0; switch (f) { case -1: if (vc->v.v_flag & V_ROOT) { *rfid = 1; return(1); } *rfid = 0; return(0); case 0: if (!AFSnl[X_AFS_FID].n_value) { err = 1; rfid_unavailable: if (!w && !Fwarn) { (void) fprintf(stderr, "%s: WARNING: %s: %s\n", Pn, err ? "no kernel address" : "can't read from kernel", AFSnl[X_AFS_VOL]._n._n_name); (void) fprintf(stderr, " This may hamper AFS node number reporting.\n"); w = 1; } f = -1; if (vc->v.v_flag & V_ROOT) { *rfid = 1; return(1); } *rfid = 0; return(0); } if (kread((KA_T)AFSnl[X_AFS_FID].n_value, (char *)&r, sizeof(r))) { err = 0; goto rfid_unavailable; } f = 1; /* fall through */ case 1: *rfid = 1; if (vc->fid.Fid.Unique == r.Fid.Unique && vc->fid.Fid.Vnode == r.Fid.Vnode && vc->fid.Fid.Volume == r.Fid.Volume && vc->fid.Cell == r.Cell) return(1); } *rfid = 0; return(0); } /* * readafsnode() - read AFS node */ int readafsnode(va, v, an) KA_T va; /* kernel vnode address */ struct vnode *v; /* vnode buffer pointer */ struct afsnode *an; /* afsnode recipient */ { char *cp, tbuf[32]; KA_T ka; int len, rfid, vols; struct vcache *vc; struct volume *vp; cp = ((char *)v + sizeof(struct vnode)); ka = (KA_T)((char *)va + sizeof(struct vnode)); len = sizeof(struct vcache) - sizeof(struct vnode); if (kread(ka, cp, len)) { (void) snpf(Namech, Namechl, "vnode at %s: can't read vcache remainder from %s", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr(ka, (char *)NULL, 0)); enter_nm(Namech); return(1); } vc = (struct vcache *)v; an->dev = AFSDEV; an->size = (unsigned long)vc->m.Length; an->nlink = (long)vc->m.LinkCount; an->nlink_st = 1; /* * Manufacture the "inode" number. */ if (vc->mvstat == 2) { if ((vp = getvolume(&vc->fid, &vols))) { an->inode = (INODETYPE)((vp->mtpoint.Fid.Vnode + (vp->mtpoint.Fid.Volume << 16)) & 0x7fffffff); if (an->inode == (INODETYPE)0) { if (is_rootFid(vc, &rfid)) an->ino_st = 1; else if (rfid) { an->inode = (INODETYPE)2; an->ino_st = 1; } else an->ino_st = 0; } else an->ino_st = 1; } else { if (vols) { an->inode = (INODETYPE)2; an->ino_st = 1; } else { if (v->v_flag & V_ROOT) { an->inode = (INODETYPE)0; an->ino_st = 1; } else an->ino_st = 0; } } } else { an->inode = (INODETYPE)((vc->fid.Fid.Vnode + (vc->fid.Fid.Volume << 16)) & 0x7fffffff); an->ino_st = 1; } return(0); } #endif /* defined(HAS_AFS) */ lsof-4.86+dfsg.orig/dialects/aix/Mksrc0000555000175000017500000000106410774407461020045 0ustar nicholasnicholas#!/bin/sh # # Mksrc - make AIX source files # # WARNING: This script assumes it is running from the main directory # of the lsof, version 4 distribution. # # One environment variable applies: # # LSOF_MKC is the method for creating the source files. # It defaults to "ln -s". A common alternative is "cp". # # $Id: Mksrc,v 1.3 2003/03/21 17:39:46 abe Exp $ D=dialects/aix L="dlsof.h ddev.c dfile.c dmnt.c dnode.c dnode1.c dnode2.c dproc.c dproto.h dsock.c dstore.c machine.h" for i in $L do rm -f $i $LSOF_MKC $D/$i $i echo "$LSOF_MKC $D/$i $i" done lsof-4.86+dfsg.orig/dialects/aix/dnode.c0000444000175000017500000007015011077377735020306 0ustar nicholasnicholas/* * dnode.c - AIX node reading functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dnode.c,v 1.25 2008/10/21 16:14:18 abe Exp $"; #endif #include "lsof.h" /* * Local definitions */ #if AIXV<5000 #define FL_NEXT next #else /* AIXV>=5000 */ #define FL_NEXT fl_next # if !defined(ISVDEV) #define ISVDEV(t) (((t)==VBLK)||((t)==VCHR)||((t)==VFIFO)||((t)==VMPC)) # endif /* !defined(ISVDEV) */ #endif /* AIXV<5000 */ # if defined(HAS_NFS) # if AIXV<4210 #include # else /* AIXV>=4210 */ # if AIXA<2 /* * Private rnode struct definitions for AIX 4.2.1 and above * * The rnode struct IBM ships in doesn't match the one * the kernel uses. The kernel's rnode struct definition comes from * , a header file IBM does not ship with AIX. * * The rnode64 struct is for AIX above 4.3.3 whose "width" is 64. * (See dnode.c for the method used to determine width.) */ struct rnode { caddr_t r_d1[11]; /* dummies; links? */ struct vnode r_vnode; /* vnode for remote file */ struct gnode r_gnode; /* gnode for remote file */ caddr_t r_d2[29]; /* dummies; rnode elements? */ off_t r_size; /* client's view of file size (long)*/ struct vattr r_attr; /* cached vnode attributes */ }; # if AIXV>4330 struct rnode64 { # if AIXV<5200 caddr_t r_d1[11]; /* dummies; links? */ # else /* AIXV>=5200 */ # if AIXV<5300 caddr_t r_d1[12]; /* dummies; links? */ # else /* AIXV>=5300 */ caddr_t r_d1[7]; /* dummies; links? */ # endif /* AIXV<5300 */ # endif /* AIXV<5200 */ struct vnode r_vnode; /* vnode for remote file */ struct gnode r_gnode; /* gnode for remote file */ # if AIXV<5300 caddr_t r_d2[15]; /* dummies; rnode elements? */ # else /* AIXV>=5300 */ caddr_t r_d2[11]; /* dummies; rnode elements? */ # endif /* AIXV<5300 */ off_t r_size; /* client's view of file size (long)*/ struct vattr r_attr; /* cached vnode attributes */ }; # endif /* AIXV>4330 */ # else /* AIXA>=2 */ struct rnode { KA_T d1[7]; /* dummies */ struct vnode r_vnode; /* vnode for remote file */ struct gnode r_gnode; /* gnode for remote file */ KA_T d2[19]; /* dummies */ off_t r_size; /* client's view of file size (long)*/ struct vattr r_attr; /* cached vnode attributes */ }; # endif /* AIXA<2 */ # endif /* AIXV<4210 */ # endif /* defined(HAS_NFS) */ /* * isglocked() - is a gnode locked */ char isglocked(ga) struct gnode *ga; /* local gnode address */ { struct filock *cfp, f, *ffp; int l; if (!(ffp = ga->gn_filocks)) return(' '); cfp = ffp; #if AIXV>=4140 do { #endif /* AIXV>=4140 */ if (kread((KA_T)cfp, (char *)&f, sizeof(f))) return(' '); #if AIXV>=4140 if (f.set.l_sysid || f.set.l_pid != (pid_t)Lp->pid) continue; #endif /* AIXV>=4140 */ if (f.set.l_whence == 0 && f.set.l_start == 0 #if AIXV>=4200 && f.set.l_end == 0x7fffffffffffffffLL #else /* AIXV<4200 */ && f.set.l_end == 0x7fffffff #endif /* AIXV>=4200 */ ) l = 1; else l = 0; switch (f.set.l_type & (F_RDLCK | F_WRLCK)) { case F_RDLCK: return((l) ? 'R' : 'r'); case F_WRLCK: return((l) ? 'W' : 'w'); case (F_RDLCK + F_WRLCK): return('u'); } return(' '); #if AIXV>=4140 } while ((cfp = f.FL_NEXT) && cfp != ffp); return(' '); #endif /* AIXV>=4140 */ } /* * process_node() - process vnode */ void process_node(va) KA_T va; /* vnode kernel space address */ { struct cdrnode c; dev_t dev, rdev; int devs = 0; struct gnode g; struct l_ino i; int ic = 0; int ins = 0; struct vfs *la = NULL; int rdevs = 0; size_t sz; char tbuf[32], *ty; enum vtype type; struct l_vfs *vfs; static struct vnode *v = (struct vnode *)NULL; #if AIXV>=3200 struct devnode dn; struct gnode pg; struct specnode sn; struct fifonode f; #endif /* AIXV>=3200 */ #if defined(HAS_AFS) static int afs = 0; /* AFS test status: -1 = no AFS * 0 = not tested * 1 = AFS present */ struct afsnode an; #endif /* defined(HAS_AFS) */ #if defined(HAS_NFS) struct vattr nfs_attr; int nfss = 0; static struct rnode r; static char *rp = (char *)&r; static int rsz = sizeof(r); # if AIXV>4330 && AIXA<2 static struct rnode64 r64; # endif /* AIXV>4330 && AIXA<2 */ # if AIXA<2 static int width = -1; # else /* AIXA>=2 */ static width = 64; # endif /* AIXA<2 */ #endif /* defined(HAS_NFS) */ #if defined(HAS_SANFS) struct sanfs_node { /* DEBUG */ /* * This is a DEBUG version of the SANFS node structure. When IBM makes * the SANFS header files available in /usr/include, this definition * will be removed. */ u_long san_d1[20]; /* DEBUG */ struct gnode san_gnode; /* DEBUG */ u_long san_d2[128]; /* DEBUG */ } san; int sans = 0; #endif /* defined(HAS_SANFS) */ #if AIXV>=4140 struct clone *cl; KA_T ka; struct module_info mi; int ml, nx; char mn[32]; struct queue q; struct qinit qi; KA_T qp, xp; int ql; struct sth_s { /* stream head */ KA_T *dummy; /* dummy */ KA_T *sth_wq; /* write queue */ } sh; struct xticb { /* XTI control block */ int d1; long d2; int d3; struct socket *xti_so; /* socket pointer */ } xt; #endif /* AIXV>=4140 */ /* * Read the vnode. */ if (!va) { enter_nm("no vnode address"); return; } if (!v) { /* * Allocate space for the vnode or AFS vcache structure. */ #if defined(HAS_AFS) v = alloc_vcache(); #else /* !defined(HAS_AFS) */ v = (struct vnode *)malloc((MALLOC_S)sizeof(struct vnode)); #endif /* defined(HAS_AFS) */ if (!v) { (void) fprintf(stderr, "%s: can't allocate %s space\n", Pn, #if defined(HAS_AFS) "vcache" #else /* !defined(HAS_AFS) */ "vnode" #endif /* defined(HAS_AFS) */ ); Exit(1); } } /* * Read the vnode. */ if (readvnode(va, v)) { enter_nm(Namech); return; } #if defined(HASFSTRUCT) Lf->fsv |= FSV_NI; Lf->fna = va; #endif /* defined(HASFSTRUCT) */ /* * Read the gnode. */ if (!v->v_gnode || readgnode((KA_T)v->v_gnode, &g)) { if (Selinet) { Lf->sf = SELEXCLF; return; } (void) snpf(Namech, Namechl, "vnode at %s has no gnode\n", print_kptr(va, (char *)NULL, 0)); enter_nm(Namech); return; } #if AIXV>=3200 /* * Under AIX 3.2 and above, if the vnode type is ISVDEV, then there is a * special node and a fifonode or devnode. Behind them are the "real" * gnode, inode and vnode. */ if (ISVDEV(g.gn_type)) { switch (g.gn_type) { case VBLK: Ntype = N_BLK; break; case VCHR: Ntype = N_CHR; break; case VFIFO: Ntype = N_FIFO; break; case VMPC: Ntype = N_MPC; break; default: (void) snpf(Namech, Namechl, "vnode at %s: unknown ISVDEV(%#x)", print_kptr(va, (char *)NULL, 0), g.gn_type); enter_nm(Namech); return; } /* * Read the special node. */ if (!g.gn_data || kread((KA_T)g.gn_data, (char *)&sn, sizeof(sn))) { if (Selinet) { Lf->sf = SELEXCLF; return; } (void) snpf(Namech, Namechl, "vnode at %s: can't read specnode (%s)", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)g.gn_data, (char *)NULL, 0)); enter_nm(Namech); return; } /* * Read the PFS gnode and its inode and vnode. */ if (sn.sn_pfsgnode) { if (Selinet) { Lf->sf = SELEXCLF; return; } if (readgnode((KA_T)sn.sn_pfsgnode, &g)) { (void) snpf(Namech, Namechl, "vnode at %s: can't read pfsgnode (%s)", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)sn.sn_pfsgnode, (char *)NULL, 0)); enter_nm(Namech); return; } if (!g.gn_data || readlino(&g, &i)) { (void) snpf(Namech, Namechl, "pfsgnode at %s: can't read inode (%s)", print_kptr((KA_T)sn.sn_pfsgnode, tbuf, sizeof(tbuf)), print_kptr((KA_T)g.gn_data, (char *)NULL, 0)); enter_nm(Namech); return; } ins = 1; if (!g.gn_vnode || readvnode((KA_T)g.gn_vnode, v)) { (void) snpf(Namech, Namechl, "pfsgnode at %s: can't read vnode (%s)", print_kptr((KA_T)sn.sn_pfsgnode, tbuf, sizeof(tbuf)), print_kptr((KA_T)g.gn_vnode, (char *)NULL, 0)); enter_nm(Namech); return; } } else { (void) zeromem((char *)&i, sizeof(i)); #if AIXV>=4140 /* * See if this is a clone device, connected to a stream. * * the clone major device number must be known; * the specnode must have a devnode pointer; * and the devnode must have a stream head pointer. */ if (CloneMaj >= 0 && sn.sn_devnode && kread((KA_T)sn.sn_devnode, (char *)&dn, sizeof(dn)) == 0 && (ka = (KA_T)dn.dv_pdata)) { # if defined(HASDCACHE) process_clone_again: # endif /* defined(HASDCACHE) */ for (cl = Clone; cl; cl = cl->next) { if (GET_MAJ_DEV(g.gn_rdev) == GET_MIN_DEV(cl->cd.rdev)) { # if defined(HASDCACHE) if (DCunsafe && !cl->cd.v && !vfy_dev(&cl->cd)) goto process_clone_again; # endif /* defined(HASDCACHE) */ /* * Identify this file as a clone. Save the clone * device inode number as the file's inode number. */ ic = 1; Lf->inode = cl->cd.inode; Lf->inp_ty = 1; if (ClonePtc >= 0 && GET_MAJ_DEV(g.gn_rdev) == ClonePtc) { if (Selinet) { Lf->sf = SELEXCLF; return; } /* * If this is a /dev/ptc stream, enter the device * name and the channel. */ (void) snpf(Namech, Namechl, "%s/%d", cl->cd.name, (int)GET_MIN_DEV(g.gn_rdev)); break; } /* * If this isn't a /dev/ptc stream, collect the names * of the modules on the stream. Ignore the stream * head and look for an "xtiso" module. Limit the * module depth to 25. */ (void) snpf(Namech, Namechl, "STR:%s", cl->cd.name); nx = (int) strlen(Namech); if (!kread(ka, (char *)&sh, sizeof(sh))) qp = (KA_T)sh.sth_wq; else qp = (KA_T)NULL; for (mn[sizeof(mn) - 1] = '\0', ql = 0; qp && (ql < 25); ql++, qp = (KA_T)q.q_next) { /* * Read the queue structure. If it can't be read, * end module name collection. * * The queue structure should lead to a qinfo * structure, and the qinfo structure should lead * to a module_info structure, where the module * name should be found. If there's no queue * structure. * * If the qinfo or module_info structures can't be * read, skip to the next queue structure. */ if (kread(qp, (char *)&q, sizeof(q))) break; if (!(ka = (KA_T)q.q_qinfo) || kread(ka, (char *)&qi, sizeof(qi))) continue; if (!(ka = (KA_T)qi.qi_minfo) || kread(ka, (char *)&mi, sizeof(mi))) continue; if (!(ka = (KA_T)mi.mi_idname) || kread(ka, mn, sizeof(mn) - 1) || !(ml = (int) strlen(mn)) || !strcmp(mn, "sth")) continue; if (!strcmp(mn, "xtiso") && (xp = (KA_T)q.q_ptr) && !kread(xp, (char *)&xt, sizeof(xt)) && (ka = (KA_T)xt.xti_so)) { /* * The xtiso module's private queue pointer * leads to an xticb with a non-NULL socket * pointer. Process the stream as a socket. */ Namech[0] = '\0'; Lf->inp_ty = 0; (void) process_socket(ka); return; } /* * Save the module name in Mamech[] as a "->" * prefixed chain, beginning with "STR:". */ if ((nx + ml + 2) > (Namechl - 1)) continue; (void) snpf(&Namech[nx], Namechl, "->%s", mn); nx += (ml + 2); } break; } } } #endif /* AIXV>=4140 */ if (Selinet) { Lf->sf = SELEXCLF; return; } } /* * If it's a FIFO, read its fifonode. */ if (Ntype == N_FIFO) { if (!sn.sn_fifonode ||readfifonode((KA_T)sn.sn_fifonode, &f)) { (void) snpf(Namech, Namechl, "vnode at %s: can't read fifonode (%s)", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)sn.sn_fifonode, (char *)NULL, 0)); enter_nm(Namech); return; } /* * Otherwise, read the devnode and its gnode. */ } else { if (!sn.sn_devnode || kread((KA_T)sn.sn_devnode,(char *)&dn,sizeof(dn))) { (void) snpf(Namech, Namechl, "vnode at %s: can't read devnode (%s)", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)sn.sn_devnode, (char *)NULL, 0)); enter_nm(Namech); return; } g = dn.dv_gnode; } } #endif /* AIXV>=3200 */ /* * Read the AIX virtual file system structure. */ if (Ntype != N_AFS && g.gn_rdev == NODEVICE) { vfs = (struct l_vfs *)NULL; enter_dev_ch(print_kptr(va, (char *)NULL, 0)); } else { if (!(vfs = readvfs(v))) { (void) snpf(Namech, Namechl, "can't read vfs for %s at %s", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)v->v_vfsp, (char *)NULL, 0)); enter_nm(Namech); return; } } /* * Set special node types: NFS, PROC or SANFS. */ #if defined(MNT_REMOTE) if (vfs && vfs->vmt_flags & MNT_REMOTE) { switch(vfs->vmt_gfstype) { # if defined(HAS_NFS) case MNT_NFS: # if defined(MNT_NFS3) case MNT_NFS3: # endif /* defined(MNT_NFS3) */ # if defined(MNT_NFS4) case MNT_NFS4: # endif /* defined(MNT_NFS4) */ # if defined(HAS_AFS) if (!AFSVfsp || (KA_T)v->v_vfsp != AFSVfsp) # endif /* defined(HAS_AFS) && defined(HAS_NFS) */ Ntype = N_NFS; # endif /* defined(HAS_NFS) */ break; # if defined(HAS_SANFS) && defined(MNT_SANFS) case MNT_SANFS: Ntype = N_SANFS; break; # endif /* defined(HAS_SANFS) && defined(MNT_SANFS) */ } } #endif /* defined(MNT_REMOTE) */ #if defined(HASPROCFS) if (vfs && (vfs->vmt_gfstype == MNT_PROCFS)) Ntype = N_PROC; #endif /* defined(HASPROCFS) */ /* * Get the lock status. */ Lf->lock = isglocked(&g); switch (Ntype) { #if defined(HAS_NFS) /* * Read an NFS rnode. */ case N_NFS: # if AIXA<2 if (width == -1) { /* * Establish the architecture's bit width and set NFS rnode * access parameters accordingly. */ # if AIXV<=4330 width = 32; # else /* AIXV>4330 */ if (__KERNEL_64()) { width = 64; rp = (char *)&r64; rsz = sizeof(r64); } else if (__KERNEL_32()) { width = 32; } else { if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: unknown kernel bit size\n", Pn); width = -2; } # endif /* AIXV<-4330 */ } # endif /* AIXA<2 */ if (width > 0) { if (!g.gn_data || kread((KA_T)g.gn_data, rp, rsz)) { (void) snpf(Namech, Namechl, "remote gnode at %s has no rnode", print_kptr((KA_T)v->v_gnode, (char *)NULL, 0)); enter_nm(Namech); return; } # if AIXV<=4330 || AIXA>=2 nfs_attr = r.r_attr; nfss = 1; # else /* AIXV>4330 && AIXA<2 */ switch (width) { case 32: nfs_attr = r.r_attr; nfss = 1; break; case 64: nfs_attr = r64.r_attr; nfss = 1; break; } # endif /* AIXV<=4330 || AIXA>=2 */ } break; #endif /* defined(HAS_NFS) */ #if defined(HAS_SANFS) /* * Read SANFS node and associated structures. */ case N_SANFS: if (!g.gn_data || kread((KA_T)g.gn_data, &san, sizeof(san)) ) { (void) snpf(Namech, Namechl, "gnode at %s has no SANFS node", print_kptr((KA_T)v->v_gnode, (char *)NULL, 0)); enter_nm(Namech); return; } /* * DEBUG: this code is insufficient. It can't be completed until IBM * makes the SANFS header files available in /usr/include. There are * apparently two node structures following the SANFS node and file * attributes (size, etc.) are in the second structure. */ sans = 1; break; #endif /* defined(HAS_SANFS) */ /* * Read N_REGLR nodes. */ case N_REGLR: if (vfs && vfs->vmt_gfstype == MNT_CDROM) { /* * Read a CD-ROM cdrnode. */ if (!g.gn_data || readcdrnode((KA_T)g.gn_data, &c)) { (void) snpf(Namech, Namechl, "gnode at %s has no cdrnode", print_kptr((KA_T)v->v_gnode, (char *)NULL, 0)); enter_nm(Namech); return; } (void) zeromem((char *)&i, sizeof(i)); i.number = (INODETYPE)c.cn_inumber; i.size = (off_t)c.cn_size; i.number_def = i.size_def = 1; /* * Otherwise, read the inode. */ } else if (g.gn_data) { if (readlino(&g, &i)) { (void) snpf(Namech, Namechl, "gnode at %s can't read inode: %s", print_kptr((KA_T)v->v_gnode, tbuf, sizeof(tbuf)), print_kptr((KA_T)g.gn_data, (char *)NULL, 0)); enter_nm(Namech); return; } ins = 1; } #if defined(HAS_AFS) else { /* * See if this is an AFS node. */ if (AFSVfsp && (KA_T)v->v_vfsp == AFSVfsp) Ntype = N_AFS; else if (v->v_vfsp) { switch (afs) { case -1: break; case 0: if (!hasAFS(v)) { afs = 1; break; } afs = 1; Ntype = N_AFS; break; case 1: if ((KA_T)v->v_vfsp == AFSVfsp) Ntype = N_AFS; } } /* * If this is an AFS node, read the afsnode. */ if (Ntype == N_AFS) { if (readafsnode(va, v, &an)) return; } else { (void) snpf(Namech, Namechl, "gnode at %s has no inode", print_kptr((KA_T)v->v_gnode, (char *)NULL, 0)); enter_nm(Namech); return; } } #else /* !defined(HAS_AFS) */ else { (void) snpf(Namech, Namechl, "gnode at %s has no inode", print_kptr((KA_T)v->v_gnode, (char *)NULL, 0)); enter_nm(Namech); return; } #endif /* defined(HAS_AFS) */ } /* * Get device and type for printing. */ #if defined(HAS_NFS) if (Ntype == N_NFS) { if (vfs) { dev = vfs->dev; devs = 1; } } else #endif /* defined(HAS_NFS) */ #if defined(HAS_AFS) if (Ntype == N_AFS) { dev = an.dev; devs = 1; } else #endif /* defined(HAS_AFS) */ #if defined(HASPROCFS) if (Ntype == N_PROC) { /* WARNING!!! WARNING!!! The following hack should be removed ASAP!!! */ dev = vfs ? (vfs->dev & 0x7fffffffffffffff) : 0; /* WARNING!!! WARNING!!! The above hack should be removed ASAP!!! */ devs = 1; } else #endif /* defined(HASPROCFS) */ #if defined(HAS_SANFS) if ((Ntype == N_SANFS) && vfs) { dev = vfs->dev; devs = 1; } else #endif /* defined(HAS_SANFS) */ { if (vfs) { dev = vfs->dev; devs = 1; } rdev = g.gn_rdev; rdevs = 1; } #if AIXV>=3200 if (Ntype == N_MPC) type = VMPC; else #endif /* AIXV>=3200 */ type = g.gn_type; /* * Obtain the inode number. */ switch (Ntype) { #if defined(HAS_AFS) case N_AFS: if (an.ino_st) { Lf->inode = (INODETYPE)an.inode; Lf->inp_ty = 1; } break; #endif /* defined(HAS_AFS) */ #if defined(HAS_NFS) case N_NFS: if (nfss) { Lf->inode = (INODETYPE)nfs_attr.va_serialno; Lf->inp_ty = 1; } break; #endif /* defined(HAS_NFS) */ #if defined(HAS_SANFS) case N_SANFS: if (sans) { /* * DEBUG: this code is insufficient. It can't be completed until * IBM makes the SANFS header files available in /usr/include. */ /* Lf->inode = ??? DEBUG */ Lf->inp_ty = 1; } break; #endif /* defined(HAS_SANFS) */ # if AIXV>=3200 case N_BLK: case N_CHR: case N_FIFO: case N_MPC: # endif /* AIXV>=3200 */ case N_REGLR: if (ins) { Lf->inode = (INODETYPE)i.number; Lf->inp_ty = i.number_def; } } /* * Obtain the file size. */ if (Foffset) Lf->off_def = 1; else { switch (Ntype) { #if defined(HAS_AFS) case N_AFS: Lf->sz = (SZOFFTYPE)an.size; Lf->sz_def = 1; break; #endif /* defined(HAS_AFS) */ #if AIXV>=3200 case N_FIFO: Lf->sz = (SZOFFTYPE)f.ff_size; Lf->sz_def = 1; break; #endif /* AIXV>=3200 */ #if defined(HAS_NFS) case N_NFS: if (nfss) { Lf->sz = (SZOFFTYPE)nfs_attr.va_size; Lf->sz_def = 1; } break; #endif /* defined(HAS_NFS) */ #if defined(HAS_SANFS) case N_SANFS: if (sans) { /* * DEBUG: this code is insufficient. It can't be completed * until IBM makes the SANFS header files available in * /usr/include. */ /* Lf->sz = (SZOFFTYPE)??? DEBUG */ Lf->sz_def = 1; } break; #endif /* defined(HAS_SANFS) */ #if AIXV>=3200 case N_BLK: if (!Fsize) Lf->off_def = 1; break; case N_CHR: case N_MPC: if (!Fsize) Lf->off_def = 1; break; #endif /* AIXV>=3200 */ case N_REGLR: if (type == VREG || type == VDIR) { if (ins) { Lf->sz = (SZOFFTYPE)i.size; Lf->sz_def = i.size_def; } } else if (((type == VBLK) || (type == VCHR) || (type == VMPC)) && !Fsize) Lf->off_def = 1; break; } } /* * Record link count. */ if (Fnlink) { switch(Ntype) { #if defined(HAS_AFS) case N_AFS: Lf->nlink = an.nlink; Lf->nlink_def = an.nlink_st; break; #endif /* defined(HAS_AFS) */ #if defined(HAS_NFS) case N_NFS: if (nfss) { Lf->nlink = (long)nfs_attr.va_nlink; Lf->nlink_def = 1; } break; #endif /* defined(HAS_NFS) */ #if defined(HAS_SANFS) case N_SANFS: if (sans) { /* * DEBUG: this code is insufficient. It can't be completed * until IBM makes the SANFS header files available in * /usr/include. */ /* Lf->nlink = (long)??? DEBUG */ Lf->nlink_def = 1; } break; #endif /* defined(HAS_SANFS) */ #if AIXV>=3200 case N_BLK: case N_CHR: case N_FIFO: case N_MPC: #endif /* AIXV>=3200 */ case N_REGLR: if (ins) { Lf->nlink = (long)i.nlink; Lf->nlink_def = i.nlink_def; } break; } if (Nlink && Lf->nlink_def && (Lf->nlink < Nlink)) Lf->sf |= SELNLINK; } #if defined(HAS_NFS) /* * Record an NFS file selection. */ if (Ntype == N_NFS && Fnfs) Lf->sf |= SELNFS; #endif /* defined(HAS_NFS) */ /* * Save the file system names. */ if (vfs) { Lf->fsdir = vfs->dir; Lf->fsdev = vfs->fsname; } /* * Save the device numbers and their states. * * Format the vnode type. */ switch (type) { case VNON: ty ="VNON"; Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; break; case VREG: case VDIR: ty = (type == VREG) ? "VREG" : "VDIR"; Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; break; case VBLK: ty = "VBLK"; Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; Ntype = N_BLK; break; case VCHR: ty = "VCHR"; Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; Ntype = N_CHR; break; case VLNK: ty = "VLNK"; Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; break; #if defined(VSOCK) case VSOCK: ty = "SOCK"; Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; break; #endif case VBAD: ty = "VBAD"; Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; break; case VFIFO: if (!Lf->dev_ch || Lf->dev_ch[0] == '\0') { Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; } ty = "FIFO"; break; case VMPC: Lf->rdev = g.gn_rdev; Lf->rdev_def = 1; if (vfs) { Lf->dev = vfs->dev; Lf->dev_def = 1; } Lf->ch = g.gn_chan; #if AIXV<3200 Lf->inp_ty = 0; #endif /* AIXV<3200 */ Ntype = N_CHR; ty = "VMPC"; break; default: Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; (void) snpf(Lf->type, sizeof(Lf->type), "%04o", (type & 0xfff)); ty = (char *)NULL; } if (ty) (void) snpf(Lf->type, sizeof(Lf->type), "%s", ty); Lf->ntype = Ntype; #if defined(HASBLKDEV) /* * If this is a VBLK file and it's missing an inode number, try to * supply one. */ if ((Lf->inp_ty == 0) && (type == VBLK)) find_bl_ino(); #endif /* defined(HASBLKDEV) */ /* * If this is a VCHR file and it's missing an inode number, try to * supply one. */ if ((Lf->inp_ty == 0) && (type == VCHR)) find_ch_ino(); /* * Test for specified file. */ if (Sfile && is_file_named(NULL, type, g.gn_chan, ic)) Lf->sf |= SELNM; /* * Enter name characters. */ if (Namech[0]) enter_nm(Namech); } #if defined(HASPRIVFILETYPE) /* * process_shmt() -- process shared memory transport file */ void process_shmt(sa) KA_T sa; /* shared memory transport node struct * address ??? */ { struct shmtnode { /* shared memory transport node * struct ??? */ struct shmtnode *peer; /* peer shmtnode struct */ caddr_t d1[2]; /* dummy to fill space */ int sz; /* buffer size */ caddr_t d2[3]; /* dyummy to fill space */ int free; /* free bytes in buffer */ caddr_t d3[17]; /* dummy to fill space */ pid_t pid; /* process ID */ } mn, pn; /* * Ignore this file if only Internet files are selected. */ if (Selinet) { Lf->sf |= SELEXCLF; return; } /* * Set type to " SMT" and put shmtnode structure address in device column. */ (void) snpf(Lf->type, sizeof(Lf->type), " SMT"); if (!sa || kread((KA_T)sa, (char *)&mn, sizeof(mn))) { (void) snpf(Namech, Namechl, "can't read shmtnode: %s", print_kptr(sa, (char *)NULL, 0)); enter_nm(Namech); return; } enter_dev_ch(print_kptr(sa, (char *)NULL, 0)); /* * If offset display has been requested or if buffer size less free bytes is * negative, enable offset display. Otherwise set the file size as buffer * size less free bytes. */ if (Foffset || mn.free > mn.sz) Lf->off_def = 1; else { Lf->sz = (SZOFFTYPE)(mn.sz - mn.free); Lf->sz_def = 1; } /* * If there is a peer, read its shmtnode structure. */ if (!mn.peer) (void) snpf(Namech, Namechl, "->(unknown)"); else { if (kread((KA_T)mn.peer, (char *)&pn, sizeof(pn))) (void) snpf(Namech, Namechl, "can't read peer shmtnode: %s", print_kptr((KA_T)mn.peer, (char *)NULL, 0)); else { if (pn.pid) (void) snpf(Namech, Namechl, "->%s (PID %d)", print_kptr((KA_T)mn.peer, (char *)NULL, 0), pn.pid); else (void) snpf(Namech, Namechl, "->%s", print_kptr((KA_T)mn.peer, (char *)NULL, 0)); } } enter_nm(Namech); } #endif /* AIXV>=4200 */ /* * readlino() -- read local inode */ int readlino(ga, li) struct gnode *ga; /* gnode address */ struct l_ino *li; /* local inode receiver */ { struct inode i; /* "regular" inode */ #if defined(HAS_JFS2) static struct vnodeops *j2va = (struct vnodeops *)NULL; /* j2_vnops address */ static int j2vas = 0; /* j2nl[] status */ #endif /* defined(HAS_JFS2) */ zeromem((char *)li, sizeof(struct l_ino)); if (!ga || !ga->gn_data) return(0); #if defined(HAS_JFS2) if (!j2vas) { /* * Get the j2_vnops address once. */ struct nlist j2nl[] = { { "j2_vnops" }, { (char *)NULL } }; if (nlist(N_UNIX, j2nl) == 0) j2va = (struct vnodeops *)j2nl[0].n_value; if (!j2va && !Fwarn) { (void) fprintf(stderr, "%s: WARNING: can't identify jfs2 files\n", Pn); } j2vas = 1; } /* * If this system has jfs2, see if this gnode's operation structure pointer * references j2_vnops. */ if (ga->gn_ops && j2va && (ga->gn_ops == j2va)) return(readj2lino(ga, li)); #endif /* defined(HAS_JFS2) */ /* * Read a "standard" inode. */ if (readinode((KA_T)ga->gn_data, &i)) return(1); li->dev = i.i_dev; li->nlink = i.i_nlink; li->number = (INODETYPE)i.i_number; li->size = i.i_size; li->dev_def = li->nlink_def = li->number_def = li->size_def = 1; return(0); } lsof-4.86+dfsg.orig/dialects/aix/dfile.c0000444000175000017500000003411410275733243020265 0ustar nicholasnicholas/* * dfile.c - AIX file processing functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dfile.c,v 1.13 2005/08/08 19:46:38 abe Exp $"; #endif #include "lsof.h" /* * Local structures */ struct hsfile { struct sfile *s; /* the Sfile table address */ struct hsfile *next; /* the next hash bucket entry */ }; /* * Local static variables */ static struct hsfile *HbyFdi = /* hash by file buckets */ (struct hsfile *)NULL; static int HbyFdiCt = 0; /* HbyFdi entry count */ static struct hsfile *HbyFrd = /* hash by file raw device buckets */ (struct hsfile *)NULL; static int HbyFrdCt = 0; /* HbyFrd entry count */ static struct hsfile *HbyFsd = /* hash by file system buckets */ (struct hsfile *)NULL; static int HbyFsdCt = 0; /* HbyFsd entry count */ static struct hsfile *HbyMPC = /* hash by MPC file buckets */ (struct hsfile *)NULL; static int HbyMPCCt = 0; /* HbyMPC entry count */ static struct hsfile *HbyNm = /* hash by name buckets */ (struct hsfile *)NULL; static int HbyNmCt = 0; /* HbyNm entry count */ /* * Local definitions */ #define SFDIHASH 4094 /* Sfile hash by (device,inode) number * pair bucket count (power of 2!) */ #define SFFSHASH 128 /* Sfile hash by file system device * number bucket count (power of 2!) */ #define SFHASHDEVINO(maj, min, ino, mod) ((int)(((int)((((int)(maj+1))*((int)((min+1))))+ino)*31415)&(mod-1))) /* hash for Sfile by major device, * minor device, and inode, modulo m * (m must be a power of 2) */ #define SFMPCHASH 1024 /* Sfile hash by MPC device number */ #define SFNMHASH 4096 /* Sfile hash by name bucket count (power of 2!) */ #define SFRDHASH 1024 /* Sfile hash by raw device number * bucket count (power of 2!) */ #define SFHASHRDEVI(maj, min, rmaj, rmin, ino, mod) ((int)(((int)((((int)(maj+1))*((int)((min+1))))+((int)(rmaj+1)*(int)(rmin+1))+ino)*31415)&(mod-1))) /* hash for Sfile by major device, * minor device, major raw device, * minor raw device, and inode, modulo * mod (mod must be a power of 2) */ /* * hashSfile() - hash Sfile entries for use in is_file_named() searches */ void hashSfile() { static int hs = 0; int i; struct sfile *s; struct hsfile *sh, *sn; /* * Do nothing if there are no file search arguments cached or if the * hashes have already been constructed. */ if (!Sfile || hs) return; /* * Allocate hash buckets by (device,inode), file system device, MPC device, * and file name. */ if (!(HbyFdi = (struct hsfile *)calloc((MALLOC_S)SFDIHASH, sizeof(struct hsfile)))) { (void) fprintf(stderr, "%s: can't allocate space for %d (dev,ino) hash buckets\n", Pn, SFDIHASH); Exit(1); } if (!(HbyFrd = (struct hsfile *)calloc((MALLOC_S)SFRDHASH, sizeof(struct hsfile)))) { (void) fprintf(stderr, "%s: can't allocate space for %d rdev hash buckets\n", Pn, SFRDHASH); Exit(1); } if (!(HbyFsd = (struct hsfile *)calloc((MALLOC_S)SFFSHASH, sizeof(struct hsfile)))) { (void) fprintf(stderr, "%s: can't allocate space for %d file sys hash buckets\n", Pn, SFFSHASH); Exit(1); } if (!(HbyMPC = (struct hsfile *)calloc((MALLOC_S)SFMPCHASH, sizeof(struct hsfile)))) { (void) fprintf(stderr, "%s: can't allocate space for %d MPC file hash buckets\n", Pn, SFMPCHASH); Exit(1); } if (!(HbyNm = (struct hsfile *)calloc((MALLOC_S)SFNMHASH, sizeof(struct hsfile)))) { (void) fprintf(stderr, "%s: can't allocate space for %d name hash buckets\n", Pn, SFNMHASH); Exit(1); } hs++; /* * Scan the Sfile chain, building file, file system, MPC file, and file * name hash bucket chains. */ for (s = Sfile; s; s = s->next) { for (i = 0; i < 4; i++) { if (i == 0) { if (!s->aname) continue; sh = &HbyNm[hashbyname(s->aname, SFNMHASH)]; HbyNmCt++; } else if (i == 1) { if (s->type) { sh = &HbyFdi[SFHASHDEVINO(GET_MAJ_DEV(s->dev), GET_MIN_DEV(s->dev), s->i, SFDIHASH)]; HbyFdiCt++; } else { sh = &HbyFsd[SFHASHDEVINO(GET_MAJ_DEV(s->dev), GET_MIN_DEV(s->dev), 0, SFFSHASH)]; HbyFsdCt++; } } else if (i == 2) { if (s->type && (s->ch < 0) && (s->mode == S_IFCHR)) { sh = &HbyMPC[SFHASHDEVINO(GET_MAJ_DEV(s->dev), GET_MIN_DEV(s->dev), 0, SFMPCHASH)]; HbyMPCCt++; } else continue; } else if (i == 3) { if (s->type && (((s->mode == S_IFCHR) && (s->ch < 0)) || ((s->mode == S_IFBLK)))) { sh = &HbyFrd[SFHASHRDEVI(GET_MAJ_DEV(s->dev), GET_MIN_DEV(s->dev), GET_MAJ_DEV(s->rdev), GET_MIN_DEV(s->rdev), s->i, SFRDHASH)]; HbyFrdCt++; } else continue; } if (!sh->s) { sh->s = s; sh->next = (struct hsfile *)NULL; continue; } else { if (!(sn = (struct hsfile *)malloc( (MALLOC_S)sizeof(struct hsfile)))) { (void) fprintf(stderr, "%s: can't allocate hsfile bucket for: %s\n", Pn, s->aname); Exit(1); } sn->s = s; sn->next = sh->next; sh->next = sn; } } } } /* * is_file_named() - is file named? */ int is_file_named(p, ty, ch, ic) char *p; /* path name; NULL = search by device * and inode (from *Lf) */ enum vtype ty; /* vnode type */ chan_t ch; /* gnode channel */ int ic; /* is clone file (4.1.4 and above) */ { int dmaj, dmin, maj, min, rmaj, rmin; static int dsplit = 0; char *ep; int f = 0; struct sfile *s; struct hsfile *sh; size_t sz; /* * Split the device numbers into their major and minor numbers. * * THis is necessitated by 64 bit AIX architectures, which store two different * types of device numbers in 64 bit dev_t's. The two types can't be compared * directly, but must be compared by extracting their major and minor numbers * and comparing them. */ readdev(0); if (!dsplit) { dmaj = GET_MAJ_DEV(DevDev); dmin = GET_MIN_DEV(DevDev); dsplit = 1; } if (Lf->dev_def) { maj = GET_MAJ_DEV(Lf->dev); min = GET_MIN_DEV(Lf->dev); } if (Lf->rdev_def) { rmaj = GET_MAJ_DEV(Lf->rdev); rmin = GET_MIN_DEV(Lf->rdev); } #if AIXV>=4140 /* * Check for a clone match. */ if (ic && HbyFdiCt && CloneMaj >= 0 && (Lf->dev_def && (maj = dmaj) && (min == dmin)) && Lf->rdev_def && (Lf->inp_ty == 1 || Lf->inp_ty == 3)) { for (sh=&HbyFdi[SFHASHDEVINO(CloneMaj, rmaj, Lf->inode, SFDIHASH)]; sh; sh = sh->next) { if ((s = sh->s) && (GET_MAJ_DEV(s->rdev) == CloneMaj) && (GET_MIN_DEV(s->rdev) == rmaj) && (s->i == Lf->inode)) { f = 3; break; } } } #endif /* AIXV>=4140 */ /* * Check for a path name match, as requested. */ if (!f && p && HbyNmCt) { for (sh = &HbyNm[hashbyname(p, SFNMHASH)]; sh; sh = sh->next) { if ((s = sh->s) && strcmp(p, s->aname) == 0) { f = 2; break; } } } /* * Check for a regular AIX multiplexed file, matching the channel if * it was supplied by the caller. */ if (!f && HbyMPCCt && ty == VMPC && (Lf->dev_def && (maj == dmaj) && (min == dmin)) && Lf->rdev_def) { for (sh = &HbyMPC[SFHASHDEVINO(rmaj, rmin, 0, SFMPCHASH)]; sh; sh = sh->next) { if ((s = sh->s) && (GET_MAJ_DEV(s->dev) == rmaj) && (GET_MIN_DEV(s->dev) == rmin) && (s->ch < 0 || ch == s->ch)) { f = 1; break; } } } /* * Check for a regular file. */ if (!f && HbyFdiCt && Lf->dev_def && (Lf->inp_ty == 1 || Lf->inp_ty == 3)) { for (sh = &HbyFdi[SFHASHDEVINO(maj, min, Lf->inode, SFDIHASH)]; sh; sh = sh->next) { if ((s = sh->s) && (maj == GET_MAJ_DEV(s->dev)) && (min == GET_MIN_DEV(s->dev)) && (Lf->inode == s->i)) { f = 1; break; } } } /* * Check for a file system. */ if (!f && HbyFsdCt && Lf->dev_def) { for (sh = &HbyFsd[SFHASHDEVINO(maj, min, 0, SFFSHASH)]; sh; sh = sh->next) { if ((s = sh->s) && (maj == GET_MAJ_DEV(s->dev)) && (min == GET_MIN_DEV(s->dev)) ) { f = 1; break; } } } /* * Check for a character or block device file. */ if (!f && HbyFrdCt && ((ty == VCHR) || (ty == VBLK)) && (Lf->dev_def && (maj == dmaj) && (min == dmin)) && Lf->rdev_def && (Lf->inp_ty == 1 || Lf->inp_ty == 3)) { for (sh = &HbyFrd[SFHASHRDEVI(maj, min, rmaj, rmin, Lf->inode, SFRDHASH)]; sh; sh = sh->next) { if ((s = sh->s) && (GET_MAJ_DEV(s->rdev) == rmaj) && (GET_MIN_DEV(s->rdev) == rmin) && (((ty == VCHR) && (s->mode == S_IFCHR) && (s->ch < 0)) || ((ty == VBLK) && (s->mode == S_IFBLK)))) { f = 1; break; } } } /* * Convert the name if a match occurred. */ if (f) { if (f == 2) { (void) snpf(Namech, Namechl, "%s", p); #if AIXV>=4140 } else if (f == 3 && ClonePtc >= 0 && (maj == ClonePtc)) { (void) snpf(Namech, Namechl, "%s/%d", s->name, min); #endif /* AIXV>=4140 */ } else if (s->type) { /* * If the search argument isn't a file system, propagate it * to Namech[]; otherwise, let printname() compose the name. */ (void) snpf(Namech, Namechl, "%s", s->name); if (ty == VMPC && s->ch < 0) { ep = endnm(&sz); (void) snpf(ep, sz, "/%d", ch); } if (s->devnm) { ep = endnm(&sz); (void) snpf(ep, sz, " (%s)", s->devnm); } } s->f = 1; return(1); } return(0); } /* * print_dev() - print device */ char * print_dev(lf, dev) struct lfile *lf; /* file whose device to be printed */ dev_t *dev; /* pointer to device to be printed */ { static char buf[128]; int maj = GET_MAJ_DEV(*dev); int min = GET_MIN_DEV(*dev); #if AIXV>=3200 if (*dev & SDEV_REMOTE) { (void) snpf(buf, sizeof(buf), "NFS,%d", (min & ~SDEV_REMOTE)); return(buf); } #endif /* AIXV>=3200 */ (void) snpf(buf, sizeof(buf), "%d,%d", maj, min); return(buf); } /* * readvfs() - read vfs structure */ struct l_vfs * readvfs(vn) struct vnode *vn; /* vnode */ { struct gfs g; void *mp; char *s1, *s2; uint ul; struct vfs v; struct vmount *vm; struct l_vfs *vp; if (!vn->v_vfsp) return((struct l_vfs *)NULL); for (vp = Lvfs; vp; vp = vp->next) { if ((KA_T)vn->v_vfsp == vp->addr) return(vp); } if (!(vp = (struct l_vfs *)malloc((MALLOC_S)sizeof(struct l_vfs)))) { (void) fprintf(stderr, "%s: PID %d, no space for vfs\n", Pn, Lp->pid); Exit(1); } vp->dir = (char *)NULL; vp->fsname = (char *)NULL; /* * Read the vfs structure. */ if (kread((KA_T)vn->v_vfsp, (char *)&v, sizeof(v))) { vfs_exit: (void) free((FREE_P *)vp); return((struct l_vfs *)NULL); } /* * Locate AIX mount information. */ if (!v.vfs_gfs || kread((KA_T)v.vfs_gfs, (char *)&g, sizeof(g))) goto vfs_exit; if (!v.vfs_mdata || kread((KA_T)((char *)v.vfs_mdata + offsetof(struct vmount, vmt_length)), (char *)&ul, sizeof(ul))) goto vfs_exit; if (!(mp = (void *)malloc((MALLOC_S)ul))) { (void) fprintf(stderr, "%s: PID %d, no space for mount data\n", Pn, Lp->pid); Exit(1); } if (kread((KA_T)v.vfs_mdata, (char *)mp, (int)ul)) { (void) free((FREE_P *)mp); goto vfs_exit; } vm = (struct vmount *)mp; vp->vmt_flags = vm->vmt_flags; vp->vmt_gfstype = vm->vmt_gfstype; #if AIXV>=3200 if ((vp->vmt_flags & MNT_REMOTE) # if defined(HAS_SANFS) && defined(MNT_SANFS) && (vp->vmt_gfstype != MNT_SANFS) # endif /* defined(HAS_SANFS) && defined(MNT_SANFS) */ ) { vp->dev = 0x80000000 | vm->vmt_vfsnumber; # if AIXA>=1 vp->dev |= 0x8000000000000000; # endif /* AIXA>=1 */ } else #endif /* AIXV>=3200 */ #if defined(HAS_AFS) if (vm->vmt_gfstype == MNT_AFS) vp->dev = AFSDEV; else #endif /* defined(HAS_AFS) */ #if AIXA>1 if (vm->vmt_gfstype == MNT_PROCFS) { /* * !!!DEBUG!!! !!!DEBUG!!! !!!DEBUG!!! !!!DEBUG!!! !!!DEBUG!!! * * The following *hack* is required to make the vmount structure's * device number match what stat(2) errnoneously returns in ia64 * AIX >= 5. * * REMOVE THIS CODE WHEN STAT(2) IS FIXED!!! */ vp->dev = (dev_t)(vm->vmt_fsid.fsid_dev & 0x7fffffffffffffff); /* * !!!DEBUG!!! !!!DEBUG!!! !!!DEBUG!!! !!!DEBUG!!! !!!DEBUG!!! */ } else #endif /* AIXA>1 */ vp->dev = (dev_t)vm->vmt_fsid.fsid_dev; if ((s1 = vmt2dataptr(vm, VMT_STUB))) { if (!(vp->dir = mkstrcpy(s1, (MALLOC_S *)NULL))) { readvfs_aix1: (void) fprintf(stderr, "%s: PID %d, readvfs, no space\n", Pn, Lp->pid); Exit(1); } } else vp->dir = (char *)NULL; s1 = vmt2dataptr(vm, VMT_HOST); if (!(s2 = vmt2dataptr(vm, VMT_OBJECT)) || *s1 == '\0') s2 = g.gfs_name; if (!s1 && !s2) vp->fsname = (char *)NULL; else { if (vm->vmt_flags & MNT_REMOTE) { if (!(vp->fsname = mkstrcat(s1 ? s1 : "", -1, (s1 && *s1) ? ":" : "", -1, s2, -1, (MALLOC_S *)NULL))) goto readvfs_aix1; } else { if (!(vp->fsname = mkstrcpy(s2, (MALLOC_S *)NULL))) goto readvfs_aix1; } } (void) free((FREE_P *)mp); vp->next = Lvfs; vp->addr = (KA_T)vn->v_vfsp; #if defined(HAS_AFS) if (!AFSVfsp && vm->vmt_gfstype == MNT_AFS) AFSVfsp = (KA_T)vn->v_vfsp; #endif /* defined(HAS_AFS) */ Lvfs = vp; return(vp); } lsof-4.86+dfsg.orig/dialects/aix/dmnt.c0000444000175000017500000001627310275733244020153 0ustar nicholasnicholas/* * dmnt.c - AIX mount support functions for lsof */ /* * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dmnt.c,v 1.13 2005/08/08 19:46:38 abe Exp $"; #endif #include "lsof.h" /* * Local static definitions */ static struct mounts *Lmi = (struct mounts *)NULL; /* local mount info */ static int Lmist = 0; /* Lmi status */ /* * readmnt() - read mount table */ struct mounts * readmnt() { char *dir, *fs, *h, *ln, *ty; char *dn = (char *)NULL; struct mounts *mtp; int nm; struct stat sb; MALLOC_S sz; struct vmount *v; struct vmount *vt = (struct vmount *)NULL; if (Lmi || Lmist) return(Lmi); /* * Read the table of vmount structures. */ for (sz = sizeof(struct vmount);;) { if (!(vt = (struct vmount *)malloc(sz))) { (void) fprintf(stderr, "%s: no space for vmount table\n", Pn); return(0); } nm = mntctl(MCTL_QUERY, sz, (unsigned char *)vt); if (nm > 0) { if (vt->vmt_revision != VMT_REVISION) { (void) fprintf(stderr, "%s: stale file system, rev %d != %d\n", Pn, vt->vmt_revision, VMT_REVISION); return(0); } break; } if (nm == 0) { sz = (unsigned)vt->vmt_revision; (void) free((FREE_P *)vt); } else { (void) fprintf(stderr, "%s: mntctl error: %s\n", Pn, strerror(errno)); return(0); } } /* * Scan the vmount structures and build Lmi. */ for (v = vt; nm--; v = (struct vmount *)((char *)v + v->vmt_length)) { dir = (char *)vmt2dataptr(v, VMT_STUB); fs = (char *)vmt2dataptr(v, VMT_OBJECT); h = (char *)vmt2dataptr(v, VMT_HOST); if (statsafely(dir, &sb)) { if (!Fwarn) { /* * Issue stat() failure warning. */ switch(v->vmt_gfstype) { #if defined(HAS_AFS) case MNT_AFS: ty = "afs"; break; #endif /* defined(HAS_AFS) */ #if defined(MNT_AIX) && defined(MNT_J2) && MNT_AIX==MNT_J2 case MNT_AIX: ty = "jfs2"; break; #else /* !defined(MNT_AIX) || !defined(MNT_J2) || MNT_AIX!=MNT_J2 */ # if defined(MNT_AIX) case MNT_AIX: ty = "oaix"; break; # endif /* defined(MNT_AIX) */ # if defined(MNT_J2) case MNT_J2: ty = "jfs2"; break; # endif /* defined(MNT_J2) */ #endif /* defined(MNT_AIX) && defined(MNT_H2) && MNT_AIX==MNT_J2 */ case MNT_CDROM: ty = "cdrom"; break; case MNT_JFS: ty = "jfs"; break; case MNT_NFS: ty = "nfs"; break; #if defined(MNT_NFS3) case MNT_NFS3: ty = "nfs3"; break; #endif /* defined(MNT_NFS3) */ #if defined(HASPROCFS) case MNT_PROCFS: ty = HASPROCFS; break; #endif /* defined(HASPROCFS) */ #if defined(MNT_SANFS) case MNT_SANFS: ty = "sanfs"; break; #endif /* defined(MNT_SANFS) */ default: ty = "unknown"; } (void) fprintf(stderr, "%s: WARNING: can't stat() %s file system %s\n", Pn, ty, dir); (void) fprintf(stderr, " Output information may be incomplete.\n"); } /* * Assemble alternate device number and mode flags. */ (void) bzero((char *)&sb, sizeof(sb)); if (v->vmt_flags & MNT_REMOTE) { #if AIXA<2 sb.st_dev = (dev_t)(SDEV_REMOTE | v->vmt_vfsnumber); #else /* AIXA>=2 */ sb.st_dev = (dev_t)(SDEV_REMOTE | (SDEV_REMOTE << 32) | v->vmt_vfsnumber); #endif /* AIXA<2 */ } else { #if defined(HAS_AFS) if (v->vmt_gfstype == MNT_AFS) sb.st_dev = AFSDEV; else #endif /* defined(HAS_AFS) */ #if AIXA>=2 && defined(HASPROCFS) if (v->vmt_gfstype == MNT_PROCFS) { /* * !!!DEBUG!!! !!!DEBUG!!! !!!DEBUG!!! !!!DEBUG!!! * * The following *hack* is required to make the vmount * structure's device number match what stat(2) * errnoneously returns on ia64 AIX 5L. * * REMOVE THIS CODE WHEN STAT(2) IS FIXED!!! */ sb.st_dev = (dev_t)(v->vmt_fsid.val[0] & 0x7fffffffffffffff); /* * !!!DEBUG!!! !!!DEBUG!!! !!!DEBUG!!! !!!DEBUG!!! */ } else #endif /* AIXA>=2 && defined(HASPROCFS) */ sb.st_dev = (dev_t)v->vmt_fsid.val[0]; } if (!Fwarn) (void) fprintf(stderr, " assuming \"dev=%#lx\" from mount table\n", sb.st_dev); sb.st_mode = S_IFDIR | 0777; } /* * Allocate space for the directory (mounted on) and resolve * any symbolic links. */ if (dn) (void) free((FREE_P *)dn); if (!(dn = mkstrcpy(dir, (MALLOC_S *)NULL))) { no_space_for_mount: (void) fprintf(stderr, "%s: no space for mount at %s (%s)\n", Pn, fs, dir); Exit(1); } if (!(ln = Readlink(dn))) { if (!Fwarn) { (void) fprintf(stderr, " Output information may be incomplete.\n"); } continue; } if (ln != dn) { (void) free((FREE_P *)dn); dn = ln; } if (*dn != '/') continue; /* * Allocate a local mounts structure and fill the directory information. */ if (!(mtp = (struct mounts *)malloc( (MALLOC_S)sizeof(struct mounts)))) goto no_space_for_mount; mtp->dir = dn; dn = (char *)NULL; mtp->dev = sb.st_dev; mtp->inode = (INODETYPE)sb.st_ino; mtp->mode = sb.st_mode; mtp->rdev = sb.st_rdev; #if defined(HASFSTYPE) mtp->fstype = sb.st_vfstype; #endif /* defined(HASFSTYPE) */ mtp->next = Lmi; /* * Form the file system (mounted-on) device name. Resolve any * symbolic links. Allocate space for the result and store it in * the local mounts structure. */ if (h && (v->vmt_flags & MNT_REMOTE)) { if (!(dn = mkstrcat(h, -1, *h ? ":" : "", 1, fs, -1, (MALLOC_S *)NULL))) goto no_space_for_mount; } else { if (!(dn = mkstrcpy(fs, (MALLOC_S *)NULL))) goto no_space_for_mount; } mtp->fsname = dn; ln = Readlink(dn); dn = (char *)NULL; /* * Stat the file system (mounted-on) device name to get its modes. * Set the modes to zero if the stat fails. Add file system * (mounted-on) device information to the local mountsstructure. */ if (!ln || statsafely(ln, &sb)) sb.st_mode = 0; mtp->fsnmres = ln; mtp->fs_mode = sb.st_mode; Lmi = mtp; } /* * Clean up and return local mount info table address. */ if (dn) (void) free((FREE_P *)dn); if (vt) (void) free((FREE_P *)vt); Lmist = 1; return(Lmi); } lsof-4.86+dfsg.orig/dialects/aix/dnode2.c0000444000175000017500000000442410275733247020362 0ustar nicholasnicholas/* * dnode2.c - AIX jfs2 support * * V. Abell * Purdue University */ /* * Copyright 2003 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 2003 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dnode2.c,v 1.4 2005/08/08 19:46:38 abe Exp $"; #endif #if defined(HAS_JFS2) #define _H_JFS_INO /* prevent */ #define _H_JFS_INODE /* prevent */ #define PROTO_H /* prevent "proto.h" and * "dproto.h" until struct * inode is available from * */ #define DPROTO_H #include "lsof.h" #define _KERNEL #include #undef PROTO_H /* enable "proto.h" */ #undef DPROTO_H /* enable "dproto.h" */ #include "proto.h" #include "dproto.h" int readj2lino(ga, li) struct gnode *ga; /* gnode address */ struct l_ino *li; /* local inode receiver */ { struct inode i; /* jfs2 inode */ /* * Read the jfs2 inode and fill in the local inode receiver. * * Note: the caller is responsible for initializing *li to zeroes. */ if (!ga || !ga->gn_data || kread((KA_T)ga->gn_data, (char *)&i, sizeof(i))) return(1); li->dev = i.i_dev; li->nlink = i.i_nlink; li->number = (INODETYPE)i.i_number; li->size = i.i_size; li->dev_def = li->nlink_def = li->number_def = li->size_def = 1; return(0); } #endif /* defined(HAS_JFS2) */ lsof-4.86+dfsg.orig/dialects/aix/aix5/0000755000175000017500000000000007630500022017667 5ustar nicholasnicholaslsof-4.86+dfsg.orig/dialects/aix/aix5/README0000644000175000017500000000041507630500101020545 0ustar nicholasnicholasThis 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 lsof-4.86+dfsg.orig/dialects/aix/aix5/j2/0000755000175000017500000000000010511044140020176 5ustar nicholasnicholaslsof-4.86+dfsg.orig/dialects/aix/aix5/j2/private_j2_snapshot.h0000644000175000017500000000073410511050255024343 0ustar nicholasnicholas/* * 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) */ lsof-4.86+dfsg.orig/dialects/aix/aix5/j2/j2_lock.h0000644000175000017500000000066707630477000021720 0ustar nicholasnicholas/* * j2_lock.h -- lsof private copy * * Needed for: * * AIX 5L, because it's missing there; * AIX 5.2, because it includes and that header * file is missing from AIX 5.2. * * V. Abell * 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) */ lsof-4.86+dfsg.orig/dialects/aix/machine.h0000444000175000017500000004343311424323047020611 0ustar nicholasnicholas/* * 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 requires that _SUN be defined to * be able to get the rpcent structure definition. */ #define _SUN #include #undef _SUN # endif /* AIXV<=3250 */ # if AIXV>=4200 /* * AIX 4.2 requires that be #include'd early. It needs * and _KERNEL. * * AIX 4.3 requires that _KERNEL be defined before the #include of * * * For gcc's sake, some redefinitions after including 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 # if AIXA>0 #include # 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 #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 option. */ /* #define HASAOPT 1 */ /* * HASBLKDEV is defined for those dialects that want block device information * recorded in BDevtp[]. */ #define HASBLKDEV 1 /* * HASDCACHE is defined for those dialects that support a device cache * file. * * HASENVDC defined the name of an environment variable that contains the * device cache file path. The HASENVDC environment variable is ignored when * the lsof process is setuid(root) or its real UID is 0. * * HASPERSDC defines the format for the last component of a personal device * cache file path. The first will be the home directory of the real UID that * executes lsof. * * HASPERSDCPATH defines the environment variable whose value is the middle * component of the personal device cache file path. The middle component * follows the home directory and precedes the results of applying HASPERSDC. * The HASPERSDCPATH environment variable is ignored when the lsof process is * setuid(root) or its real UID is 0. * * HASSYSDC defines a public device cache file path. When it's defined, it's * used as the path from which to read the device cache. * * Consult the 00DCACHE and 00FAQ files of the lsof distribution for more * information on device cache file path construction. */ #define HASDCACHE 1 #define HASENVDC "LSOFDEVCACHE" #define HASPERSDC "%h/%p.lsof_%L" #define HASPERSDCPATH "LSOFPERSDCPATH" /* #define HASSYSDC "/your/choice/of/path" */ /* * HASCDRNODE is defined for those dialects that have CD-ROM nodes. */ #define HASCDRNODE 1 /* * HASFIFONODE is defined for those dialects that have FIFO nodes. */ # if AIXV>=3200 #define HASFIFONODE 1 # endif /* AIXV>=3200 */ /* * HASFSINO is defined for those dialects that have the file system * inode element, fs_ino, in the lfile structure definition in lsof.h. */ /* #define HASFSINO 1 */ /* * HASFSTRUCT is defined if the dialect has a file structure. * * FSV_DEFAULT defines the default set of file structure values to list. * It defaults to zero (0), but may be made up of a combination of the * FSV_* symbols from lsof.h. * * HASNOFSADDR -- has no file structure address * HASNOFSFLAGS -- has no file structure flags * HASNOFSCOUNT -- has no file structure count * HASNOFSNADDR -- has no file structure node address */ #define HASFSTRUCT 1 /* #define FSV_DEFAULT FSV_? | FSV_? | FSV_? */ /* #define HASNOFSADDR 1 has no file structure address */ /* #define HASNOFSFLAGS 1 has no file structure flags */ /* #define HASNOFSCOUNT 1 has no file structure count */ /* #define HASNOFSNADDR 1 has no file structure node address */ /* * HASGNODE is defined for those dialects that have gnodes. */ #define HASGNODE 1 /* * HASHSNODE is defined for those dialects that have High Sierra nodes. */ /* #define HASHSNODE 1 */ /* * HASINODE is defined for those dialects that have inodes and wish to * use readinode() from node.c. */ #define HASINODE 1 /* * HASINTSIGNAL is defined for those dialects whose signal function returns * an int. */ /* #define HASINTSIGNAL 1 */ /* * HASKERNIDCK is defined for those dialects that support the comparison of * the build to running kernel identity. */ #define HASKERNIDCK 1 /* * HASKOPT is defined for those dialects that support the -k option of * reading the kernel's name list from an optional file. */ /* #define HASKOPT 1 */ /* * HASLFILEADD is defined for those dialects that need additional elements * in struct lfile. The HASLFILEADD definition is a macro that defines * them. If any of the additional elements need to be preset in the * alloc_lfile() function of proc.c, the SETLFILEADD macro may be defined * to do that. * * If any additional elements need to be cleared in alloc_lfile() or in the * free_proc() function of proc.c, the CLRLFILEADD macro may be defined to * do that. Note that CLRLFILEADD takes one argument, the pointer to the * lfile struct. The CLRLFILEADD macro is expected to expand to statements * that are complete -- i.e., have terminating semi-colons -- so the macro is * called without a terminating semicolon by proc.c. * * The HASXOPT definition may be used to select the conditions under which * private lfile elements are used. */ /* #define HASLFILEADD int ... */ /* #define CLRLFILEADD(lf) (lf)->... = (type)NULL; */ /* #define SETLFILEADD Lf->... */ /* * HASMNTSTAT indicates the dialect supports the mount stat(2) result option * in its l_vfs and mounts structures. */ /* #define HASMNTSTAT 1 */ /* * HASMNTSUP is defined for those dialects that support the mount supplement * option. */ /* #define HASMNTSUP 1 */ /* * HASMOPT is defined for those dialects that support the reading of * kernel memory from an alternate file. */ #define HASMOPT 1 /* * HASNCACHE is defined for those dialects that have a kernel name cache * that lsof can search. A value of 1 directs printname() to prefix the * cache value with the file system directory name; 2, avoid the prefix. * * NCACHELDPFX is a set of C commands to execute before calling ncache_load(). * * NCACHELDSFX is a set of C commands to execute after calling ncache_load(). */ /* #define HASNCACHE 1 */ /* #define NCACHELDPFX ??? */ /* #define NCACHELDSFX ??? */ /* * HASNLIST is defined for those dialects that use nlist() to acccess * kernel symbols. (AIX lsof doesn't use nlist, it uses knlist.) */ /* #define HASNLIST 1 */ /* * HASPIPEFN is defined for those dialects that have a special function to * process DTYPE_PIPE file structure entries. Its value is the name of the * function. * * NOTE: don't forget to define a prototype for this function in dproto.h. */ /* #define HASPIPEFN process_pipe? */ /* * HASPIPENODE is defined for those dialects that have pipe nodes. */ /* #define HASPIPENODE 1 */ /* * HASPMAPENABLED is defined when the reporting of portmapper registration * info is enabled by default. */ /* #define HASPMAPENABLED 1 */ /* * HASPPID is defined for those dialects that support identification of * the parent process IDentifier (PPID) of a process. */ #define HASPPID 1 /* * HASPRINTDEV, HASPRINTINO, HASPRINTNM, HASPRINTOFF, and HASPRINTSZ * define private dialect-specific functions for printing DEVice numbers, * INOde numbers, NaMes, file OFFsets, and file SiZes. The functions are * called from print_file(). */ #define HASPRINTDEV print_dev /* #define HASPRINTINO print_ino? */ /* #define HASPRINTNM print_nm? */ /* #define HASPRINTOFF print_off? */ /* #define HASPRINTSZ print_sz? */ /* * HASPRIVFILETYPE and PRIVFILETYPE are defined for dialects that have a * file structure type that isn't defined by a DTYPE_* symbol. They are * used in lib/prfp.c to select the type's processing. * * PRIVFILETYPE is the definition of the f_type value in the file struct. * * HASPRIVFILETYPE is the name of the processing function. */ # if AIXV>=4140 #define HASPRIVFILETYPE process_shmt #define PRIVFILETYPE 15 # endif /* AIXV>=4140 */ /* * HASPRIVNMCACHE is defined for dialects that have a private method for * printing cached NAME column values for some files. HASPRIVNAMECACHE * is defined to be the name of the function. * * The function takes one argument, a struct lfile pointer to the file, and * returns non-zero if it prints a name to stdout. */ /* #define HASPRIVNMCACHE */ /* * 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 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 */ /* * 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_ is defined for dialects that use the * in the lsof library. * * Note: other definitions and operations may be required to condition the * library function source code. They may be found in the dialect dlsof.h * header files. */ /* #define USE_LIB_CKKV 1 ckkv.c */ /* #define USE_LIB_COMPLETEVFS 1 cvfs.c */ #define USE_LIB_FIND_CH_INO 1 /* fino.c */ /* #define USE_LIB_IS_FILE_NAMED 1 isfn.c */ #define USE_LIB_LKUPDEV 1 /* lkud.c */ /* #define USE_LIB_PRINTDEVNAME 1 pdvn.c */ #define USE_LIB_PROCESS_FILE 1 /* prfp.c */ #define USE_LIB_PRINT_TCPTPI 1 /* ptti.c */ /* #define USE_LIB_READDEV 1 rdev.c */ /* #define USE_LIB_READMNT 1 rmnt.c */ /* #define USE_LIB_REGEX 1 regex.c */ /* #define USE_LIB_RNAM 1 rnam.c */ /* #define USE_LIB_RNCH 1 rnch.c */ /* #define USE_LIB_RNMH 1 rnmh.c */ /* #define USE_LIB_SNPF 1 snpf.c */ #define snpf snprintf /* use the system's snprintf() */ /* * WARNDEVACCESS is defined for those dialects that should issue a warning * when lsof can't access /dev (or /device) or one of its sub-directories. * The warning can be inhibited by the lsof caller with the -w option. */ #define WARNDEVACCESS 1 /* * WARNINGSTATE is defined for those dialects that want to suppress all lsof * warning messages. */ /* #define WARNINGSTATE 1 warnings are enabled by default */ /* * WILLDROPGID is defined for those dialects whose lsof executable runs * setgid(not_real_GID) and whose setgid power can be relinquished after * the dialect's initialize() function has been executed. */ #define WILLDROPGID 1 /* * zeromem is a macro that uses bzero or memset. */ #define zeromem(a, l) bzero(a, l) #endif /* !defined(LSOF_MACHINE_H) */ lsof-4.86+dfsg.orig/dialects/aix/Makefile0000444000175000017500000001057411001126573020470 0ustar nicholasnicholas # AIX Makefile # # $Id: Makefile,v 1.14 2008/04/15 13:28:12 abe Exp $ PROG= lsof BIN= ${DESTDIR} DOC= ${DESTDIR} I=/usr/include S=/usr/include/sys L=/usr/include/local P= CDEF= CDEFS= ${CDEF} ${CFGF} INCL= ${DINC} CFLAGS= ${CDEFS} ${INCL} ${DEBUG} GRP= HDR= lsof.h lsof_fields.h dlsof.h machine.h proto.h dproto.h SRC= ddev.c dfile.c dmnt.c dnode.c dnode1.c dnode2.c dproc.c dsock.c \ dstore.c arg.c main.c misc.c node.c print.c proc.c store.c usage.c \ util.o OBJ= ddev.o dfile.o dmnt.o dnode.o dnode1.o dnode2.o dproc.o dsock.o \ dstore.o arg.o main.o misc.o node.o print.o proc.o store.o usage.o \ util.o MAN= lsof.8 OTHER= SHELL= /bin/sh SOURCE= Makefile ${OTHER} ${MAN} ${HDR} ${SRC} all: ${PROG} ${PROG}: ${LIB} ${P} ${OBJ} ${CC} -o $@ ${CFLAGS} ${OBJ} ${CFGL} clean: FRC rm -f Makefile.bak ${PROG} a.out core errs lint.out tags *.o version.h rm -f machine.h.old new_machine.h (cd lib; ${MAKE} -f Makefile.skel clean) install: all FRC @echo '' @echo 'Please write your own install rule. Lsof Needs to be able to' @echo 'read /dev/kmem and /dev/mem'. Installing it segid to the group' @echo 'that can read those devices is one way to allow it to read them.' @echo 'normally that group is the system group and your install rule' @echo 'might look something like this:' @echo '' @echo ' install -f $${BIN} -S -M 2755 -G $${GRP} $${PROG}' @echo ' install -f $${DOC} -M 444 $${MAN}' @echo '' @echo 'You will have to complete the skeletons for the BIN, DOC, and' @echo 'GRP strings given at the beginning of this Makefile, e.g.,' @echo '' @echo ' BIN= $${DESTDIR}/usr/local/etc' @echo ' DOC= $${DESTDIR}/usr/man/man8' @echo ' GRP= system' @echo '' @echo 'You might also consider giving lsof permission to read /dev/kmem' @echo 'and /dev/mem via ACLs. First, establish a new group to which' @echo 'you will setgid lsof -- e.g., group kmem. Next, change the ACLs' @echo 'for /dev/kmem and /dev/mem to permit group kmem members to read' @echo 'them. Finally, install lsof setgid the kmem group with: @echo '' @echo ' GRP= kmem' ${LIB}: FRC (cd lib; ${MAKE} DEBUG="${DEBUG}" CFGF="${CFGF}") version.h: FRC @echo Constructing version.h @rm -f version.h @echo '#define LSOF_BLDCMT "${LSOF_BLDCMT}"' > version.h; @echo '#define LSOF_CC "${CC}"' >> version.h @echo '#define LSOF_CCV "${CCV}"' >> version.h @echo '#define LSOF_CCDATE "'`date`'"' >> version.h @echo '#define LSOF_CCFLAGS "'`echo ${CFLAGS} | sed 's/\\\\(/\\(/g' | sed 's/\\\\)/\\)/g' | sed 's/"/\\\\"/g'`'"' >> version.h @echo '#define LSOF_CINFO "${CINFO}"' >> version.h @if [ "X${LSOF_HOST}" = "X" ]; then \ echo '#define LSOF_HOST "'`uname -n`'"' >> version.h; \ else \ if [ "${LSOF_HOST}" = "none" ]; then \ echo '#define LSOF_HOST ""' >> version.h; \ else \ echo '#define LSOF_HOST "${LSOF_HOST}"' >> version.h; \ fi \ fi @echo '#define LSOF_LDFLAGS "${CFGL}"' >> version.h @if [ "X${LSOF_LOGNAME}" = "X" ]; then \ echo '#define LSOF_LOGNAME "${LOGNAME}"' >> version.h; \ else \ if [ "${LSOF_LOGNAME}" = "none" ]; then \ echo '#define LSOF_LOGNAME ""' >> version.h; \ else \ echo '#define LSOF_LOGNAME "${LSOF_LOGNAME}"' >> version.h; \ fi; \ fi @if [ "X${LSOF_SYSINFO}" = "X" ]; then \ echo '#define LSOF_SYSINFO "'`uname -a`'"' >> version.h; \ else \ if [ "${LSOF_SYSINFO}" = "none" ]; then \ echo '#define LSOF_SYSINFO ""' >> version.h; \ else \ echo '#define LSOF_SYSINFO "${LSOF_SYSINFO}"' >> version.h; \ fi \ fi @if [ "X${LSOF_USER}" = "X" ]; then \ echo '#define LSOF_USER "${USER}"' >> version.h; \ else \ if [ "${LSOF_USER}" = "none" ]; then \ echo '#define LSOF_USER ""' >> version.h; \ else \ echo '#define LSOF_USER "${LSOF_USER}"' >> version.h; \ fi \ fi @sed '/VN/s/.ds VN \(.*\)/#define LSOF_VERSION "\1"/' < version >> version.h FRC: # DO NOT DELETE THIS LINE - make depend DEPENDS ON IT ddev.o: ${HDR} ddev.c dfile.o: ${HDR} dfile.c dmnt.o: ${HDR} dmnt.c dnode.o: ${HDR} dnode.c dnode1.o: ${HDR} dnode1.c dproc.o: ${HDR} dproc.c dnode2.o: ${HDR} dnode2.c dsock.o: ${HDR} dsock.c dstore.o: ${HDR} dstore.c arg.o: ${HDR} arg.c main.o: ${HDR} main.c misc.o: ${HDR} misc.c node.o: ${HDR} node.c print.o: ${HDR} print.c proc.o: ${HDR} proc.c store.o: ${HDR} store.c usage.o: ${HDR} version.h usage.c util.o: ${HDR} util.c # *** Do not add anything here - It will go away. *** lsof-4.86+dfsg.orig/dialects/linux/0000755000175000017500000000000011741064217017410 5ustar nicholasnicholaslsof-4.86+dfsg.orig/dialects/linux/dstore.c0000444000175000017500000000571611631740426021064 0ustar nicholasnicholas/* * 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"; static char *rcsid = "$Id: dstore.c,v 1.4 2011/09/07 19:07:45 abe Exp $"; #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 */ int OffType = 0; /* offset type: * 0 == unknown * 1 == lstat's st_size * 2 == from /proc//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) */ { (long)0, NULL } }; /* * Pof_tab[] - table for print process open file flags */ struct pff_tab Pof_tab[] = { { (long)0, NULL } }; lsof-4.86+dfsg.orig/dialects/linux/dsock.c0000444000175000017500000025512611741061143020663 0ustar nicholasnicholas/* * 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"; static char *rcsid = "$Id: dsock.c,v 1.38 2012/04/10 16:39:50 abe Exp $"; #endif #include "lsof.h" /* * 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)) /* * 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 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; /* locaal 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 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_udp *next; }; #if defined(HASIPv6) struct tcp_udp6 { /* IPv6 TCP and UDP socket * information */ INODETYPE inode; struct in6_addr faddr, laddr; /* foreign and 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; }; #endif /* defined(HASIPv6) */ 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 */ struct uxsin *next; }; /* * 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 *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(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 */ #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 struct uxsin **Uxsin = (struct uxsin **)NULL; /* UNIX socket info, hashed by inode */ /* * Local function prototypes */ _PROTOTYPE(static struct ax25sin *check_ax25,(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 struct uxsin *check_unix,(INODETYPE i)); _PROTOTYPE(static void get_ax25,(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)); #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_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); } #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); } #endif /* defined(HASIPv6) */ /* * check_unix() - check for UNIX domain socket */ static struct uxsin * check_unix(i) INODETYPE i; /* socket file's inode number */ { int h; struct uxsin *up; h = INOHASH(i); for (up = Uxsin[h]; up; up = up->next) { if (i == up->inode) return(up); } return((struct uxsin *)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 *))); Exit(1); } } /* * 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]); Exit(1); } (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]); Exit(1); } (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]); Exit(1); } (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)); Exit(1); } 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); } /* * 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 *))); Exit(1); } } /* * 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]); Exit(1); } (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]); Exit(1); } (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)); Exit(1); } 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 *))); Exit(1); } } /* * 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)); Exit(1); } 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 *))); Exit(1); } } /* * 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)); Exit(1); } 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 *))); Exit(1); } } /* * 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]); Exit(1); } (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]); Exit(1); } (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]); Exit(1); } (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)); Exit(1); } 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 *))); Exit(1); } } /* * 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]); Exit(1); } 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]); Exit(1); } 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]); Exit(1); } 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]); Exit(1); } 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); Exit(1); } 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); Exit(1); } (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); Exit(1); } 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); Exit(1); } (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)); Exit(1); } 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; /* * 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; (void) free((FREE_P *)tp); } TcpUdp[h] = (struct tcp_udp *)NULL; } } /* * 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 *))); Exit(1); } } /* * 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)); Exit(1); } 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; } (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); (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 *))); Exit(1); } } /* * 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]); Exit(1); } (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]); Exit(1); } (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]); Exit(1); } (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)); Exit(1); } 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; /* * 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; (void) free((FREE_P *)tp6); } TcpUdp6[h] = (struct tcp_udp6 *)NULL; } } } 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 *))); Exit(1); } } /* * 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)); Exit(1); } 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; } (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; struct uxsin *np, *up; FILE *us; static char *vbuf = (char *)NULL; static size_t vsz = (size_t)0; /* * 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 (up->path) (void) free((FREE_P *)up->path); if (up->pcb) (void) free((FREE_P *)up->pcb); (void) free((FREE_P *)up); } Uxsin[h] = (struct uxsin *)NULL; } } else { Uxsin = (struct uxsin **)calloc(INOBUCKS, sizeof(struct uxsin *)); if (!Uxsin) { (void) fprintf(stderr, "%s: can't allocate %d bytes for Unix socket info\n", Pn, (int)(INOBUCKS * sizeof(struct uxsin *))); } } /* * 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]); Exit(1); } (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]); Exit(1); } (void) snpf(path, len + 1, "%s", fp[7]); } else path = (char *)NULL; /* * Allocate and fill a Unix socket info structure; link it to its * hash bucket. */ if (!(up = (struct uxsin *)malloc(sizeof(struct uxsin)))) { (void) fprintf(stderr, "%s: can't allocate %d bytes for uxsin struct\n", Pn, (int)sizeof(struct uxsin)); Exit(1); } up->inode = inode; up->pcb = pcb; up->sb_def = 0; 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; } } up->next = Uxsin[h]; Uxsin[h] = up; } (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; if ((ad->s6_addr32[i] = (uint32_t)strtoul(buf, &ep, 16)) == (uint32_t)UINT32_MAX || !ep || *ep) break; } 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); Exit(1); } (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); Exit(1); } (void) snpf(cp, pl + 1, "%s", pbuf); Lf->nma = cp; } /* * 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 ((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, s, ss, l, lss) char *p; /* node's readlink() path */ 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, tbuf[64]; unsigned char *fa, *la; struct in_addr fs, ls; struct ipxsin *ip; int i, len, nl; struct nlksin *np; struct packin *pp; char *pr; struct rawsin *rp; struct sctpsin *sp; struct tcp_udp *tp; struct uxsin *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); 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"); switch (np->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) */ default: snpf(Namech, Namechl, "unknown protocol: %d", np->pr); cp = (char *)NULL; } if (cp) (void) snpf(Namech, Namechl, "%s", cp); 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"); switch(pp->ty) { #if defined(SOCK_STREAM) case SOCK_STREAM: cp = "STREAM"; break; #endif /* defined(SOCK_STREAM) */ #if defined(SOCK_DGRAM) case SOCK_DGRAM: cp = "DGRAM"; break; #endif /* defined(SOCK_DGRAM) */ #if defined(SOCK_RAW) case SOCK_RAW: cp = "RAW"; break; #endif /* defined(SOCK_RAW) */ #if defined(SOCK_RDM) case SOCK_RDM: cp = "RDM"; break; #endif /* defined(SOCK_RDM) */ #if defined(SOCK_SEQPACKET) case SOCK_SEQPACKET: cp = "SEQPACKET"; break; #endif /* defined(SOCK_SEQPACKET) */ #if defined(SOCK_PACKET) case SOCK_PACKET: cp = "PACKET"; break; #endif /* defined(SOCK_PACKET) */ default: snpf(Namech, Namechl, "unknown type: %d", pp->ty); cp = (char *)NULL; } if (cp) (void) snpf(Namech, Namechl, "type=SOCK_%s", 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: 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); if (ss & SB_INO) { Lf->inode = (INODETYPE)s->st_ino; Lf->inp_ty = 1; } path = up->path ? up->path : p; (void) enter_nm(path); 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, path, (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); } 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) */ 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); } 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) */ 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; } /* * 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; } enter_nm(Fxopt ? "can't identify protocol (-X specified)" : "can't identify protocol"); } /* * 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, &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"); } lsof-4.86+dfsg.orig/dialects/linux/dproc.c0000444000175000017500000011254611741061141020663 0ustar nicholasnicholas/* * 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"; static char *rcsid = "$Id: dproc.c,v 1.26 2012/04/10 16:39:50 abe Exp $"; #endif #include "lsof.h" /* * Local definitions */ #define FDINFO_FLAGS 1 /* fdinfo flags available */ #define FDINFO_POS 2 /* fdinfo position available */ #define FDINFO_ALL (FDINFO_FLAGS | FDINFO_POS) #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 */ }; /* * 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 int get_fdinfo,(char *p, struct l_fdinfo *fi)); _PROTOTYPE(static int getlinksrc,(char *ln, char *src, int srcl)); _PROTOTYPE(static int isefsys,(char *path, char *type, int l, efsys_list_t **rep, struct lfile **lfr)); _PROTOTYPE(static int nm2id,(char *nm, int *id, int *idl)); _PROTOTYPE(static int read_id_stat,(int ty, char *p, int id, char **cmd, int *ppid, int *pgid)); _PROTOTYPE(static 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)); _PROTOTYPE(static int statEx,(char *p, struct stat *s, int *ss)); #if defined(HASSELINUX) _PROTOTYPE(static int cmp_cntx_eq,(char *pcntx, char *ucntx)); #include /* * 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); Exit(1); } cntxp->f = 0; cntxp->cntx = cntx; cntxp->next = CntxArg; CntxArg = cntxp; return(0); } #endif /* defined(HASSELINUX) */ /* * gather_proc_info() -- gather process information */ void gather_proc_info() { char *cmd, *tcmd; struct dirent *dp; unsigned char ht, pidts; int n, nl, pgid, pid, ppid, 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/\"\n", Pn, (int)pidpathl, PROCFS); Exit(1); } (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); Exit(1); } } 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); Exit(1); } } (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; #if defined(HASTASKS) /* * If task reporting is selected, check the tasks of the process first, * so that the "-p -aK" options work properly. */ if ((Selflags & SELTASK)) { (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); Exit(1); } } (void) snpf(tidpath, tidpathl, "%s/%s/stat", taskpath, dp->d_name); /* * Check the task state. */ rv = read_id_stat(1, tidpath, tid, &tcmd, &tppid, &tpgid); if ((rv < 0) || (rv == 1)) continue; /* * Attempt to record the task. */ if (!process_id(tidpath, (tx + 1 + nl+ 1), tcmd, uid, pid, tppid, tpgid, tid)) { 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. */ (void) make_proc_path(pidpath, n, &path, &pathl, "stat"); if (((rv = read_id_stat(0, path, pid, &cmd, &ppid, &pgid)) >= 0) && (rv != 1)) { tid = (Fand && ht && pidts && (Selflags & SELTASK)) ? pid : 0; if ((!process_id(pidpath, n, cmd, uid, pid, ppid, pgid, tid)) && tid) { Lp->tid = 0; } } } } /* * get_fdinfo() - get values from /proc/fdinfo/FD */ static int get_fdinfo(p, fi) char *p; /* path to fdinfo file */ 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 (!p || !*p || !(fs = fopen(p, "r"))) return(0); /* * Read the fdinfo file. */ while (fgets(buf, sizeof(buf), fs)) { if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < 2) continue; if (!fp[0] || !*fp[0] || !fp[1] || !*fp[1]) continue; if (!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) == FDINFO_ALL) break; } else if (!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) == FDINFO_ALL) 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//fd/ link */ static int getlinksrc(ln, src, srcl) char *ln; /* link path */ char *src; /* link source path return address */ int srcl; /* length of src[] */ { char *cp; int ll; 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); } 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//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, &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// */ 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); Exit(1); } *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 Exit(1) */ { 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)); Exit(1); } /* * 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); Exit(1); } *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)); Exit(1); } 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) 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 */ { int av; 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; 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)) return(1); if (Cckreg) { /* * If conditional checking of regular files is enabled, enable * socket file only checking, based on the process' selection * status. */ Ckscko = (sf & SELPROC) ? 0 : 1; } alloc_lproc(pid, pgid, ppid, uid, cmd, (int)pss, (int)sf); Lp->tid = tid; Plf = (struct lfile *)NULL; /* * Process the ID's current working directory info. */ if (!Ckscko) { (void) make_proc_path(idp, idpl, &path, &pathl, "cwd"); alloc_lfile(CWD, -1); efs = 0; if (getlinksrc(path, pbuf, sizeof(pbuf)) < 1) { if (!Fwarn) { (void) memset((void *)&sb, 0, sizeof(sb)); lnk = ss = 0; (void) snpf(nmabuf, sizeof(nmabuf), "(readlink: %s)", strerror(errno)); nmabuf[sizeof(nmabuf) - 1] = '\0'; (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, &sb, ss, (struct stat *)NULL, 0); if (Lf->sf) link_lfile(); } } /* * Process the ID's root directory info. */ if (!Ckscko) { (void) make_proc_path(idp, idpl, &path, &pathl, "root"); alloc_lfile(RTD, -1); if (getlinksrc(path, pbuf, sizeof(pbuf)) < 1) { if (!Fwarn) { (void) memset((void *)&sb, 0, sizeof(sb)); lnk = ss = 0; (void) snpf(nmabuf, sizeof(nmabuf), "(readlink: %s)", strerror(errno)); nmabuf[sizeof(nmabuf) - 1] = '\0'; (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, &sb, ss, (struct stat *)NULL, 0); if (Lf->sf) link_lfile(); } } /* * Process the ID's execution info. */ if (!Ckscko) { txts = 0; (void) make_proc_path(idp, idpl, &path, &pathl, "exe"); alloc_lfile("txt", -1); if (getlinksrc(path, pbuf, sizeof(pbuf)) < 1) { (void) memset((void *)&sb, 0, sizeof(sb)); lnk = ss = 0; 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, &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); Exit(1); } } } 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)) < 1) { (void) memset((void *)&sb, 0, sizeof(sb)); lnk = ss = 0; if (!Fwarn) { (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) { (void) make_proc_path(ipath, j, &pathi, &pathil, fp->d_name); if ((av = get_fdinfo(pathi, &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, &sb, ss, &lsb, ls); 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//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); Exit(1); } } 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. */ (void) memset((void *)&sb, 0, 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)); } } (void) memset((void *)&sb, 0, 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], &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(ty, p, id, cmd, ppid, pgid) int ty; /* type: 0 == PID, 1 == LWP */ 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; static char *cbf = (char *)NULL; static MALLOC_S cbfa = 0; FILE *fs; MALLOC_S len; int nf; 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); cp = fgets(buf, sizeof(buf), fs); (void) fclose(fs); if (!cp) return(-1); /* * Separate the line into fields on white space separators. Expect five fields * for a PID type and three for an LWP type. */ if ((nf = get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0)) < (ty ? 5 : 3)) { return(-1); } /* * Convert the first field to an integer; its conversion must match the * ID argument. */ if (!fp[0] || (atoi(fp[0]) != id)) return(-1); /* * Get the command name from the second field. Strip a starting '(' and * an ending ')'. Allocate space to hold the result and return the space * pointer. */ if (!(cp = fp[1])) return(-1); if (cp && *cp == '(') cp++; if ((cp1 = strrchr(cp, ')'))) *cp1 = '\0'; if ((len = strlen(cp) + 1) > cbfa) { cbfa = len; if (cbf) cbf = (char *)realloc((MALLOC_P *)cbf, cbfa); else cbf = (char *)malloc(cbfa); if (!cbf) { (void) fprintf(stderr, "%s: can't allocate %d bytes for command \"%s\"\n", Pn, (int)cbfa, cp); Exit(1); } } (void) snpf(cbf, len, "%s", cp); *cmd = cbf; /* * Convert and return parent process (fourth field) and process group (fifth * field) IDs. */ if (fp[3] && *fp[3]) *ppid = atoi(fp[3]); else return(-1); if (fp[4] && *fp[4]) *pgid = atoi(fp[4]); else return(-1); /* * Check the state in the third field. If it is 'Z', return that indication. */ if (fp[2] && !strcmp(fp[2], "Z")) return(1); else if (fp[2] && !strcmp(fp[2], "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); Exit(1); } 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. */ memset((void *)s, 0, 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); } lsof-4.86+dfsg.orig/dialects/linux/dproto.h0000444000175000017500000000363711741061142021071 0ustar nicholasnicholas/* * 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.8 2012/04/10 16:39:50 abe Exp $ */ #if defined(HASSELINUX) _PROTOTYPE(extern int enter_cntx_arg,(char *cnxt)); #endif /* defined(HASSELINUX) */ _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, struct stat *s, int ss, struct stat *l, int ls)); _PROTOTYPE(extern void process_proc_sock,(char *p, struct stat *s, int ss, struct stat *l, int ls)); _PROTOTYPE(extern void set_net_paths,(char *p, int pl)); lsof-4.86+dfsg.orig/dialects/linux/dlsof.h0000444000175000017500000001214411741061136020665 0ustar nicholasnicholas/* * 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.22 2012/04/10 16:39:50 abe Exp $ */ #if !defined(LINUX_LSOF_H) #define LINUX_LSOF_H 1 #include #define DIRTYPE dirent /* for arg.c's enter_dir() */ #define __USE_GNU /* to get all O_* symbols in fcntl.h */ #include #include #include #include #include #include #include #include # if defined(GLIBCV) || defined(__UCLIBC__) #include # else /* !defined(GLIBCV) && !defined(__UCLIBC__) */ #include # endif /* defined(GLIBCV) || defined(__UCLIBC__) */ # if !defined(HASNORPC_H) #include #include # endif /* !defined(HASNORPC_H) */ #if defined(HASSELINUX) #include #endif /* defined(HASSELINUX) */ #include #include #include #include #include /* * 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 , 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 */ }; extern int HasNFS; extern int OffType; #endif /* LINUX_LSOF_H */ lsof-4.86+dfsg.orig/dialects/linux/Mksrc0000555000175000017500000000106507212725254020420 0ustar nicholasnicholas#!/bin/sh # # 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 $ D=dialects/linux L="dfile.c dlsof.h dmnt.c dnode.c dproc.c dproto.h dsock.c dstore.c machine.h" for i in $L do rm -f $i $LSOF_MKC $D/$i $i echo "$LSOF_MKC $D/$i $i" done lsof-4.86+dfsg.orig/dialects/linux/dnode.c0000444000175000017500000002610611741061140020640 0ustar nicholasnicholas/* * 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"; static char *rcsid = "$Id: dnode.c,v 1.22 2012/04/10 16:39:50 abe Exp $"; #endif #include "lsof.h" /* * 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 HASHPID(pid) (((int)((pid * 31415) >> 3)) & (PIDBUCKS - 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)); /* * 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; } } } /* * 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); Exit(1); } } 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)); Exit(1); } } /* * 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); Exit(1); } 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, s, ss, l, ls) char *p; /* node's readlink() path */ 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, s, ss, l, ls); return; } } 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 (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; } /* * 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: tn = "REG"; break; case S_IFLNK: tn = "LINK"; break; case S_ISVTX: tn = "VTXT"; break; default: (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); } lsof-4.86+dfsg.orig/dialects/linux/dfile.c0000444000175000017500000002330311741061132020627 0ustar nicholasnicholas/* * 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"; static char *rcsid = "$Id: dfile.c,v 1.8 2012/04/10 16:39:50 abe Exp $"; #endif #include "lsof.h" /* * Local structures */ struct hsfile { struct sfile *s; /* the Sfile table address */ struct hsfile *next; /* the next hash bucket entry */ }; /* * Local static variables */ static struct hsfile *HbyFdi = /* hash by file (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); Exit(1); } if (!(HbyFrd = (struct hsfile *)calloc((MALLOC_S)SFRDHASH, sizeof(struct hsfile)))) { (void) fprintf(stderr, "%s: can't allocate space for %d rdev hash buckets\n", Pn, SFRDHASH); Exit(1); } if (!(HbyFsd = (struct hsfile *)calloc((MALLOC_S)SFFSHASH, sizeof(struct hsfile)))) { (void) fprintf(stderr, "%s: can't allocate space for %d file sys hash buckets\n", Pn, SFFSHASH); Exit(1); } if (!(HbyNm = (struct hsfile *)calloc((MALLOC_S)SFNMHASH, sizeof(struct hsfile)))) { (void) fprintf(stderr, "%s: can't allocate space for %d name hash buckets\n", Pn, SFNMHASH); Exit(1); } hs++; /* * Scan the Sfile chain, building file, file system, 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); Exit(1); } 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); } lsof-4.86+dfsg.orig/dialects/linux/dmnt.c0000444000175000017500000003732611741061137020525 0ustar nicholasnicholas/* * 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"; static char *rcsid = "$Id: dmnt.c,v 1.19 2012/04/10 16:39:50 abe Exp $"; #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); Exit(1); } /* * 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); Exit(1); } } /* * 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); Exit(1); } } 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); Exit(1); } if (!(mpn->dn = (char *)malloc(sz + 1))) { (void) fprintf(stderr, "%s: no space for mount supplement path: %d \"%s\"\n", Pn, ln, buf); Exit(1); } (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)) { memset((void *)s, 0, 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; 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 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 (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); Exit(1); } } 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 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); Exit(1); } 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); } lsof-4.86+dfsg.orig/dialects/linux/machine.h0000444000175000017500000004151511741061144021165 0ustar nicholasnicholas/* * machine.h - Linux definitions 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: machine.h,v 1.36 2012/04/10 16:39:50 abe Exp $ */ #if !defined(LSOF_MACHINE_H) #define LSOF_MACHINE_H 1 #include #include /* * 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 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. * * CAUTION!!! Do not enable HASDCACHE for /proc-based Linux lsof. The source * code cannot support it. * * The presence of NEVER_HASDCACHE in this comment prevents the Customize * script from offering to change HASDCACHE. * * * 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. * * CAUTION!!! Do not enable HASDCACHE for /proc-based Linux lsof. The source * code cannot support it. */ /* #define HASDCACHE 1 !!!DON'T ENABLE!!! -- see above comment */ /* #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 */ /* * HASEOPT is defined for dialects that support the -e option */ #define HASEOPT 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->... */ /* * HASLWP is defined for dialects that have LWP support inside processes. */ #define HASLWP 1 /* * HASMNTSTAT indicates the dialect supports the mount stat(2) result option * in its l_vfs and mounts structures. */ /* #define HASMNTSTAT 1 */ /* * HASMNTSUP is defined for those dialects that support the mount supplement * option. */ #define HASMNTSUP 1 /* * HASMOPT is defined for those dialects that support the reading of * kernel memory from an alternate file. */ /* #define HASMOPT 1 */ /* * HASNCACHE is defined for those dialects that have a kernel name cache * that lsof can search. A value of 1 directs printname() to prefix the * cache value with the file system directory name; 2, avoid the prefix. * * NCACHELDPFX is a set of C commands to execute before calling ncache_load(). * * NCACHELDSFX is a set of C commands to execute after calling ncache_load(). */ /* #define HASNCACHE 1 */ /* #define NCACHELDPFX ??? */ /* #define NCACHELDSFX ??? */ /* * HASNLIST is defined for those dialects that use nlist() to acccess * kernel symbols. */ /* #define HASNLIST 1 */ /* * HASPIPEFN is defined for those dialects that have a special function to * process DTYPE_PIPE file structure entries. Its value is the name of the * function. * * NOTE: don't forget to define a prototype for this function in dproto.h. */ /* #define HASPIPEFN process_pipe? */ /* * HASPIPENODE is defined for those dialects that have pipe nodes. */ /* #define HASPIPENODE 1 */ /* * HASPMAPENABLED is defined when the reporting of portmapper registration * info is enabled by default. */ /* #define HASPMAPENABLED 1 */ /* * HASPPID is defined for those dialects that support identification of * the parent process IDentifier (PPID) of a process. */ #define HASPPID 1 /* * HASPRINTDEV, HASPRINTINO, HASPRINTNM, HASPRINTOFF, and HASPRINTSZ * define private dialect-specific functions for printing DEVice numbers, * INOde numbers, NaMes, file OFFsets, and file SiZes. The functions are * called from print_file(). */ /* #define HASPRINTDEV print_dev? */ /* #define HASPRINTINO print_ino? */ /* #define HASPRINTNM print_nm? */ /* #define HASPRINTOFF print_off? */ /* #define HASPRINTSZ print_sz? */ /* * HASPRIVFILETYPE and PRIVFILETYPE are defined for dialects that have a * file structure type that isn't defined by a DTYPE_* symbol. They are * used in lib/prfp.c to select the type's processing. * * PRIVFILETYPE is the definition of the f_type value in the file struct. * * HASPRIVFILETYPE is the name of the processing function. */ /* #define HASPRIVFILETYPE process_shmf? */ /* #define PRIVFILETYPE ?? */ /* * HASPRIVNMCACHE is defined for dialects that have a private method for * printing cached NAME column values for some files. HASPRIVNAMECACHE * is defined to be the name of the function. * * The function takes one argument, a struct lfile pointer to the file, and * returns non-zero if it prints a name to stdout. */ /* #define HASPRIVNMCACHE */ /* * 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 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 /* * HASSNODE is defined for those dialects that have snodes. */ /* #define HASSNODE 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 */ /* * HASTASKS is defined for those dialects that have task reporting support. */ #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 /* * HASTCPTPIW is defined for dialects where it is possible to report the * TCP/TPI send and receive window sizes produced by netstat. */ /* #define HASTCPTPIW 1 */ /* * HASTCPUDPSTATE is defined for dialects that have TCP and UDP state * support -- i.e., for the "-stcp|udp:state" option and its associated * speed improvements. */ #define HASTCPUDPSTATE 1 /* * HASTMPNODE is defined for those dialects that have tmpnodes. */ /* #define HASTMPNODE 1 */ /* * HASVNODE is defined for those dialects that use the Sun virtual file system * node, the vnode. BSD derivatives usually do; System V derivatives prior to * R4 usually don't. * doesn't. */ /* #define HASVNODE 1 */ /* * HASXOPT is defined for those dialects that have an X option. It * defines the text for the usage display. HASXOPT_VALUE defines the * option's default binary value -- 0 or 1. */ #define HASXOPT "skip TCP&UDP* files" #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. */ #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 /* * Each USE_LIB_ is defined for dialects that use the * in the lsof library. * * Note: other definitions and operations may be required to condition the * library function source code. They may be found in the dialect dlsof.h * header files. */ /* #define USE_LIB_CKKV 1 ckkv.c */ /* #define USE_LIB_COMPLETEVFS 1 cvfs.c */ /* #define USE_LIB_FIND_CH_INO 1 fino.c */ /* #define USE_LIB_IS_FILE_NAMED 1 isfn.c */ /* #define USE_LIB_LKUPDEV 1 lkud.c */ /* #define USE_LIB_PRINTDEVNAME 1 pdvn.c */ /* #define USE_LIB_PROCESS_FILE 1 prfp.c */ /* #define USE_LIB_PRINT_TCPTPI 1 ptti.c */ /* #define USE_LIB_READDEV 1 rdev.c */ /* #define USE_LIB_READMNT 1 rmnt.c */ /* #define USE_LIB_REGEX 1 regex.c */ /* #define USE_LIB_RNAM 1 rnam.c */ /* #define USE_LIB_RNCH 1 rnch.c */ /* #define USE_LIB_RNMH 1 rnmh.c */ /* #define USE_LIB_SNPF 1 snpf.c */ #define snpf snprintf /* use the system's snprintf() */ /* * WARNDEVACCESS is defined for those dialects that should issue a warning * when lsof can't access /dev (or /device) or one of its sub-directories. * The warning can be inhibited by the lsof caller with the -w option. * * CAUTION!!! Don't enable the WARNDEVACCESS definiton for /proc-based Linux * lsof; it doesn't process /dev at all. * * The presence of NEVER_WARNDEVACCESS in this comment prevents the Customize * script from offering to change WARNDEVACCESS. */ /* #define WARNDEVACCESS 1 DON'T ENABLE!!! -- see above comment */ /* * 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) */ lsof-4.86+dfsg.orig/dialects/linux/Makefile0000444000175000017500000000754511001126734021051 0ustar nicholasnicholas # Linux /proc-based Makefile # # $Id: Makefile,v 1.11 2008/04/15 13:30:01 abe Exp $ PROG= lsof BIN= ${DESTDIR} DOC= ${DESTDIR} I=/usr/include S=/usr/include/sys L=/usr/include/local P= CDEF= CDEFS= ${CDEF} ${CFGF} DEP= ${CFGD} ${CFGDN} INCL= ${DINC} CFLAGS= ${CDEFS} ${INCL} ${DEP} ${DEBUG} GRP= HDR= lsof.h lsof_fields.h dlsof.h machine.h 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 \ util.c OBJ= dfile.o dmnt.o dnode.o dproc.o dsock.o dstore.o \ arg.o main.o misc.o node.o print.o proc.o store.o usage.o \ util.o MAN= lsof.8 OTHER= SHELL= /bin/sh SOURCE= Makefile ${OTHER} ${MAN} ${HDR} ${SRC} all: ${PROG} ${PROG}: ${P} ${LIB} ${OBJ} ${CC} -o $@ ${OBJ} ${CFGL} clean: FRC rm -f Makefile.bak ${PROG} a.out core errs lint.out tags *.o version.h ${CFGDN} 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 $${GRP} $${PROG} $${BIN}' @echo ' install -m 444 $${MAN} $${DOC}' @echo '' @echo 'You will have to complete the 4xxx modes, the GRP value, and' @echo 'the skeletons for the BIN and DOC strings, given at the' @echo 'beginning of this Makefile, e.g.,' @echo '' @echo ' BIN= $${DESTDIR}/usr/local/etc' @echo ' DOC= $${DESTDIR}/usr/man/man8' @echo ' GRP= sys' @echo '' ${LIB}: FRC (cd lib; ${MAKE} DEBUG="${DEBUG}" CFGF="${CFGF}") version.h: FRC @echo Constructing version.h @rm -f version.h @echo '#define LSOF_BLDCMT "${LSOF_BLDCMT}"' > version.h; @echo '#define LSOF_CC "${CC}"' >> version.h @echo '#define LSOF_CCV "${CCV}"' >> version.h @echo '#define LSOF_CCDATE "'`date`'"' >> version.h @echo '#define LSOF_CCFLAGS "'`echo ${CFLAGS} | sed 's/\\\\(/\\(/g' | sed 's/\\\\)/\\)/g' | sed 's/"/\\\\"/g'`'"' >> version.h @echo '#define LSOF_CINFO "${CINFO}"' >> version.h @if [ "X${LSOF_HOST}" = "X" ]; then \ echo '#define LSOF_HOST "'`uname -n`'"' >> version.h; \ else \ if [ "${LSOF_HOST}" = "none" ]; then \ echo '#define LSOF_HOST ""' >> version.h; \ else \ echo '#define LSOF_HOST "${LSOF_HOST}"' >> version.h; \ fi \ fi @echo '#define LSOF_LDFLAGS "${CFGL}"' >> version.h @if [ "X${LSOF_LOGNAME}" = "X" ]; then \ echo '#define LSOF_LOGNAME "${LOGNAME}"' >> version.h; \ else \ if [ "${LSOF_LOGNAME}" = "none" ]; then \ echo '#define LSOF_LOGNAME ""' >> version.h; \ else \ echo '#define LSOF_LOGNAME "${LSOF_LOGNAME}"' >> version.h; \ fi; \ fi @if [ "X${LSOF_SYSINFO}" = "X" ]; then \ echo '#define LSOF_SYSINFO "'`uname -a`'"' >> version.h; \ else \ if [ "${LSOF_SYSINFO}" = "none" ]; then \ echo '#define LSOF_SYSINFO ""' >> version.h; \ else \ echo '#define LSOF_SYSINFO "${LSOF_SYSINFO}"' >> version.h; \ fi \ fi @if [ "X${LSOF_USER}" = "X" ]; then \ echo '#define LSOF_USER "${USER}"' >> version.h; \ else \ if [ "${LSOF_USER}" = "none" ]; then \ echo '#define LSOF_USER ""' >> version.h; \ else \ echo '#define LSOF_USER "${LSOF_USER}"' >> version.h; \ fi \ fi @sed '/VN/s/.ds VN \(.*\)/#define LSOF_VERSION "\1"/' < version >> version.h FRC: # DO NOT DELETE THIS LINE - make depend DEPENDS ON IT dfile.o: ${HDR} dfile.c dmnt.o: ${HDR} dmnt.c dnode.o: ${HDR} dnode.c 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. *** lsof-4.86+dfsg.orig/print.c0000444000175000017500000016453211741060076015771 0ustar nicholasnicholas/* * 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"; static char *rcsid = "$Id: print.c,v 1.54 2012/04/10 16:30:51 abe Exp $"; #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); Exit(1); } 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); Exit(1); } 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); Exit(1); } 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); Exit(1); } 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); Exit(1); } /* * 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); Exit(1); } } 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"); Exit(1); } } } #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); Exit(1); } /* * 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); Exit(1); } 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 (TaskPrtFl) (void) printf(" %*s", TidColW, TIDTTL); #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. */ if (!PrPass) { if (Lp->tid) { (void) snpf(buf, sizeof(buf), "%d", Lp->tid); if ((len = strlen(buf)) > TidColW) TidColW = len; TaskPrtFl = 1; } } else if (TaskPrtFl) { if (Lp->tid) (void) printf(" %*d", TidColW, Lp->tid); else (void) printf(" %*s", TidColW, ""); } #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() { PrPass = (Ffield || Fterse) ? 1 : 0; 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); TaskPrtFl = 0; #if defined(HASTASKS) TidColW = strlen(TIDTTL); #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)); Exit(1); } } /* * 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 *)))); Exit(1); } 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); Exit(1); } (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); Exit(1); } (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) */ lsof-4.86+dfsg.orig/misc.c0000444000175000017500000010504411077400637015564 0ustar nicholasnicholas/* * 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"; static char *rcsid = "$Id: misc.c,v 1.26 2008/10/21 16:21:41 abe Exp $"; #endif #include "lsof.h" #if defined(HASWIDECHAR) && defined(WIDECHARINCL) #include WIDECHARINCL #endif /* defined(HASWIDECHAR) && defined(WIDECHARINCL) */ /* * 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) */ _PROTOTYPE(static char *safepup,(unsigned int c, int *cl)); /* * 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); Exit(1); } 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))); Exit(1); } 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); Exit(1); } /* * 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)); Exit(1); } /* * Fork a child to execute functions. */ if ((Cpid = fork()) == 0) { /* * Begin the child process. */ int fd, nd, r_al, r_rbln; char r_arg[MAXPATHLEN+1], r_rbuf[MAXPATHLEN+1]; int (*r_fn)(); /* * Close all open file descriptors except Pipes[0] and * Pipes[3]. */ for (fd = 0, nd = GET_MAX_FD(); fd < nd; 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; } /* * 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_rbuf)) break; rv = r_fn(r_arg, 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_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)); Exit(1); } (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)); Exit(1); } 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); Exit(1); } 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); Exit(1); } 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); Exit(1); } /* * 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); Exit(1); } } 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); Exit(1); } } 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); Exit(1); } /* * 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); Exit(1); } /* * 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); Exit(1); } 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); Exit(1); } 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); Exit(1); } if (Lf->nm) (void) free((FREE_P *)Lf->nm); Lf->nm = mp; } /* * Exit() - do a clean exit() */ void Exit(xv) int 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); } #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); Exit(1); } 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); stk = (char **)NULL; ss = sx = 0; 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) */ static char * safepup(c, cl) unsigned int c; /* unprintable (i.e., !isprint()) * character */ 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 { (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 == c) { if (*sp < 0x20 || (unsigned char)*sp == 0xff) 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 (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 (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); Exit(1); } } /* * 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); Exit(1); } 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); } lsof-4.86+dfsg.orig/lsof.man0000644000175000017500000044714211741064217016135 0ustar nicholasnicholas Maintenance Procedures LSOF(8) NAME lsof - list open files SYNOPSIS lsof [ -?abChKlnNOPRtUvVX ] [ -A A ] [ -c c ] [ +c c ] [ +|-d d ] [ +|-D D ] [ +|-e s ] [ +|-f [cfgGn] ] [ -F [f] ] [ -g [s] ] [ -i [i] ] [ -k k ] [ +|-L [l] ] [ +|-m m ] [ +|-M ] [ -o [o] ] [ -p s ] [ +|-r [t[m]] ] [ -s [p:s] ] [ -S [t] ] [ -T [t] ] [ -u s ] [ +|-w ] [ -x [fl] ] [ -z [z] ] [ -Z [Z] ] [ -- ] [names] DESCRIPTION Lsof revision 4.86 lists on its standard output file infor- mation about files opened by processes for the following UNIX dialects: Apple Darwin 9 and Mac OS X 10.[567] FreeBSD 4.9 and 6.4 for x86-based systems FreeBSD 8.2, 9.0 and 10.0 for AMD64-based systems Linux 2.1.72 and above for x86-based systems Solaris 9, 10 and 11 (See the DISTRIBUTION section of this manual page for infor- mation 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 selected 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 OUTPUT 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]] 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 specified; or if a user list is specified with the -u option, UNIX domain socket files, belonging to users not in the list, won't be listed unless SunOS 5.9 Last change: Revision-4.86 1 Maintenance Procedures LSOF(8) the -U option is also specified. Normally list options that are specifically stated are ORed - i.e., specifying the -i option without an address and the -ufoo option produces a listing of all network files OR 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 option; 4) the `^' (negated) command, specified with the -c option; 5) the (`^') negated TCP or UDP protocol state names, speci- fied with the -s [p:s] option. Since they represent exclusions, they are applied without ORing or ANDing and take effect before any other selection criteria are applied. The -a option may be used to AND the selections. For exam- ple, specifying -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 acceptable. Wherever -a is placed, it causes the ANDing of all selection options. Items of the same selection set - command names, file descriptors, network addresses, process identifiers, user identifiers, zone names, security 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 SunOS 5.9 Last change: Revision-4.86 2 Maintenance Procedures LSOF(8) and -n options, or it might represent the n field identifier character following the -F option. When ambiguity is possi- ble, start a new option with a `-' character - e.g., ``-F -n''. If the next option is a file name, follow the possi- bly ambiguous option with ``--'' - e.g., ``-F -- name''. 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 options. 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 alter- nate 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 sections for information on using this option. -c c selects the listing of files for processes execut- ing the command that begins with the characters of c. Multiple commands may be specified, using mul- tiple -c options. They are joined in a single ORed set before participating in AND option selection. If c begins with a `^', then the following charac- ters specify a command name whose processes are to be ignored (excluded.) SunOS 5.9 Last change: Revision-4.86 3 Maintenance Procedures LSOF(8) If c begins and ends with a slash ('/'), the char- acters between 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 loca- tion.) 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 com- mand name characters to lsof in the files and structures from which lsof obtains command name. Often dialects limit the number of characters sup- plied 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 con- tains 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 SunOS 5.9 Last change: Revision-4.86 4 Maintenance Procedures LSOF(8) search, rooted at directory D. Processing of the +d option does not follow sym- bolic 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 speci- fied. Note: the authority of the user of this option lim- its it to searching for files that the user has permission to examine with the system stat(2) func- tion. -d s specifies a list of file descriptors (FDs) to exclude from or include in the output listing. The file descriptors are specified 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 permit- ted. 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 descrip- tors 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. +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 sym- bolic links within D unless the -x or -x l option is also specified. Nor does it search for open SunOS 5.9 Last change: Revision-4.86 5 Maintenance Procedures LSOF(8) files on file system mount points on subdirectories of D unless the -x or -x f option is also speci- fied. Note: the authority of the user of this option lim- its it to searching for files that the user has permission to examine with the system stat(2) func- tion. 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 func- tion 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 func- tions are restricted, they will not appear in the description of the -D option that accompanies -h or -? option output. See the DEVICE CACHE FILE sec- tion and the sections that follow it for more information 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 environment 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.) SunOS 5.9 Last change: Revision-4.86 6 Maintenance Procedures LSOF(8) 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 con- figured and compiled. (The output of the -h and -? options show the current default prefix - e.g., ``.lsof''.) The suffix, hostname, is the first component of the host's name returned by gethost- name(2). When available, the b function directs lsof to build a new device 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 improperly structured. The r function, when specified without a path name, prevents lsof from updating an incorrect or outdated device cache file, or creat- ing a new one in its place. The r function is always available when it is specified without a path name argument; it may be restricted by the permissions 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 subjected to kernel function calls that might block. The +e option 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 SunOS 5.9 Last change: Revision-4.86 7 Maintenance Procedures LSOF(8) and inode numbers. (Device and inode numbers are acquired via the potentially blocking stat(2) ker- nel call and are thus not available, but see the +|-m m option as a possible alternative way to sup- ply 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'' pre- face 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.) +|-f [cfgGn] f by itself clarifies how path name arguments are to be interpreted. When followed by c, f, g, G, or n in any combination it specifies that the listing of kernel file structure information 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 associ- ated 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 argu- ments will be taken to be simple files. Thus, for example, the ``-f -- /'' arguments direct lsof to search for open files with a `/' path name, not all open files in the `/' (root) file system. Be careful to make sure +f and -f are properly ter- minated and aren't followed by a character (e.g., of the file or file system name) that might be taken as a parameter. For example, use ``--'' after +f and -f as in these examples. $ lsof +f -- /file/system/name $ lsof -f -- /file/name SunOS 5.9 Last change: Revision-4.86 8 Maintenance Procedures LSOF(8) The listing of information from kernel file struc- tures, requested with the +f [cfgGn] option form, is normally inhibited, and is not available in whole or part for some dialects - e.g., /proc-based Linux kernels below 2.6.22. When the prefix 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) 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 addresses may be used to detect more readily identical files inherited by child processes and identical files in use by different 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 pro- gram, 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 OUTPUT 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 terminator character must be set with expli- cit entries in f, as described in the OUTPUT FOR OTHER PROGRAMS section. SunOS 5.9 Last change: Revision-4.86 9 Maintenance Procedures LSOF(8) When a field selection character identifies an item lsof does not normally list - e.g., PPID, selected with -R - specification of the field character - 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 IDentifica- tion (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 exclusions. Multiple PGID numbers are joined in a single ORed set before participating in AND option selection. However, PGID exclusions are applied without ORing or ANDing and take effect before 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. -i [i] selects the listing of files any of whose Internet address matches the address specified in i. If no address is specified, this option selects the list- ing 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 displayed. (An IPv6 specifica- tion may be used only if the dialects 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 parti- cipating in AND option selection. An Internet address is specified in the form (Items SunOS 5.9 Last change: Revision-4.86 10 Maintenance Procedures LSOF(8) 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 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 specify 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 hos- taddr. 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 SunOS 5.9 Last change: Revision-4.86 11 Maintenance Procedures LSOF(8) - for protocol. Service names and port numbers may be combined in a list whose entries are separated by commas and whose numeric range entries are separated by minus signs. There may be no embedded spaces, and all service names must belong to the specified proto- col. 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 selects the listing of tasks of processes, on dialects where task reporting is supported. (If help output - i.e., the output of the -h or -? options - shows this option, then task reporting is supported by the dialect.) When -K and -a are both specified 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 descrip- tion of the TID column in the OUTPUT section.) -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 SunOS 5.9 Last change: Revision-4.86 12 Maintenance Procedures LSOF(8) 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 '' 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 directory, followed by a single space, followed by the device number in hexadecimal "0x" format - e.g., / 0x801 Lsof can use the mount supplement file to get dev- ice numbers for file systems when it can't get them via stat(2) or lstat(2). The option form +m m identifies m as a mount sup- plement file. Note: the +m and +m m options are not available for all supported dialects. Check the output of lsof's -h or -? options to see if the +m and +m m options are available. +|-M Enables (+) or disables (-) the reporting of port- mapper registrations for local TCP, UDP and UDPLITE ports, where port mapping is supported. (See the last paragraph of this option description for information about where portmapper registration reporting is suported.) SunOS 5.9 Last change: Revision-4.86 13 Maintenance Procedures LSOF(8) The default reporting mode is set by the lsof builder with the HASPMAPENABLED #define in the dialect's machine.h header file; lsof is distri- buted with the HASPMAPENABLED #define deactivated, 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 enabled 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 immediately following the port numbers or service names - e.g., ``:1234[name]'' or ``:name[100083]''. The registration information may be a name or number, depending on what the registering 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 cong- ested or stopped. Reverse the reporting mode to determine if portmapper registration reporting is slowing or blocking lsof. For purposes of portmapper registration reporting lsof considers a TCP, UDP or UDPLITE port local if: it is found in the local part of its containing kernel structure; or if it is located 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 inter- face from the local one. See the lsof FAQ (The FAQ section gives its loca- tion.) for further discussion of portmapper regis- tration reporting issues. Portmapper registration reporting is supported only on dialects that have RPC header files. (Some Linux distributions with GlibC 2.14 do not have them.) When portmapper registration reporting is supported, the -h or -? help output will show the +|-M option. -n inhibits the conversion of network numbers to host SunOS 5.9 Last change: Revision-4.86 14 Maintenance Procedures LSOF(8) names for network files. Inhibiting conversion may make lsof run faster. It is also useful when host name lookup is not working 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 consistent 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 sec- tion gives its location.) for more information. The -o and -s options are mutually exclusive; they can't both be specified. When neither is speci- fied, lsof displays whatever 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 example, to direct lsof to display offset at all times with a decimal 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 operations that may block lsof. SunOS 5.9 Last change: Revision-4.86 15 Maintenance Procedures LSOF(8) 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 exclusions. Multiple process ID numbers are joined in a single ORed set before participating in AND option selec- tion. However, PID exclusions are applied without ORing or ANDing and take effect before other selec- tion criteria are applied. -P inhibits the conversion of port numbers to port names for network files. Inhibiting the conversion may make lsof run a little faster. It is also use- ful when port name lookup is not working properly. +|-r [t[m]] puts lsof in repeat mode. There lsof lists open files as selected by other options, delays t seconds (default fifteen), then repeats the list- ing, delaying and listing repetitively until stopped by a condition defined by the prefix to the option. If the prefix is a `-', repeat mode is endless. Lsof must be terminated with an interrupt or quit signal. 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 because 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 out- put is in progress (the -F, option has been speci- fied), the default marker is `m'; otherwise the default marker is ``========''. The marker is fol- lowed by a NL character. The optional "m" argument specifies a format SunOS 5.9 Last change: Revision-4.86 16 Maintenance Procedures LSOF(8) for the marker line. The characters follow- ing `m' are interpreted 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) docu- mentation for what may appear in its format specif- ication. Note that when field output is requested with the -F option, cannot contain the NL format, ``%n''. Note also that when contains spaces or other characters that affect the shell's interpretation of arguments, must be quoted appropriately. Repeat mode reduces lsof startup overhead, so it is more efficient to use this mode than to call lsof repetitively from a shell script, for example. To use repeat mode most efficiently, accompany +|-r with specification of other lsof selection options, so the amount of kernel memory access lsof does will be kept to a minimum. Options 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 out- put (see the -F, option description) and a supervising awk or Perl script, or a C program. -R directs lsof to list the Parent Process IDentifica- tion number in the PPID column. -s [p:s] s alone directs lsof to display file size at all times. It causes the SIZE/OFF output column title to be changed to SIZE. If the file does not have a size, nothing is displayed. When 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 `^'. 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 SunOS 5.9 Last change: Revision-4.86 17 Maintenance Procedures LSOF(8) list (s) is required. If only TCP and UDP files are to be listed, as con- trolled 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 except 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 Unbound and Idle. See the lsof FAQ (The FAQ section gives its loca- tion.) 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 mutually 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, FIFOs, 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 functions - lstat(2), readlink(2), and stat(2) - that might otherwise deadlock. The minimum for t is two; the default, fifteen; when no value is specified, the default is used. See the BLOCKS AND TIMEOUTS section for more infor- mation. SunOS 5.9 Last change: Revision-4.86 18 Maintenance Procedures LSOF(8) -T [t] controls the reporting of some TCP/TPI information, also reported 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: QR= QS= SO= SS= TF= WR= WW= Not all values are reported for all UNIX dialects. Items values (when available) are reported after the item name and '='. When the field output mode is in effect (See OUTPUT FOR OTHER PROGRAMS.) each item appears as a field with a `T' leading character. -T with no following key characters disables TCP/TPI information reporting. -T with following characters selects the reporting of specific TCP/TPI information: 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 out- put for the -T option will show what selections 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. SunOS 5.9 Last change: Revision-4.86 19 Maintenance Procedures LSOF(8) 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 , and . Consult those header files for the meaning 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 dialects 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 sec- tion gives its location.) -t specifies that lsof should produce terse output with process identifiers only and no header - e.g., so that the output may be piped to kill(1). -t selects 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.) SunOS 5.9 Last change: Revision-4.86 20 Maintenance Procedures LSOF(8) 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 nei- ther 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 direct 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 compile-time options restrict the listing of some files, lsof may not report that it failed to find a search item when an ANDed option or compile-time option prevents the listing of the open file con- taining 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 HASNOSOCKSECURITY are defined at compile time and they prevent the list- ing of open files. +|-w Enables (+) or disables (-) the suppression of warning messages. The lsof builder may choose to have warning mes- sages disabled or enabled by default. The default SunOS 5.9 Last change: Revision-4.86 21 Maintenance Procedures LSOF(8) 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 selects 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 without 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 processing. The -x option may not be supplied without also sup- plying a +d or +D option. -X This is a dialect-specific option. AIX: This IBM AIX RISC/System 6000 option requests the reporting of executed text file and shared library references. WARNING: because this option uses the kernel readx() function, its use on a busy AIX system might cause an application process to hang so com- pletely that it can neither be killed nor stopped. I have never seen this happen or had a report of its happening, but I think there is a remote possi- bility 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 unless the real UID of the lsof process is root. The default lsof distri- bution allows any UID to specify -X, so by default it will appear in the help output. SunOS 5.9 Last change: Revision-4.86 22 Maintenance Procedures LSOF(8) When AIX readx() use is disabled, lsof may not be able to report 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 access 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 application 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 dis- tribution for a more complete description of the Stale Segment ID bug, its APAR, and methods for defining readx() use when compiling lsof. Linux: This Linux option requests that lsof skip the reporting of information on all open TCP, UDP and UDPLITE IPv4 and IPv6 files. This Linux option is most useful when the system has an extremely large number of open TCP, UDP and UDPLITE files, the processing of whose information in the /proc/net/tcp* and /proc/net/udp* files would take lsof a long time, and whose reporting is not of interest. Use this option with care and only when you are 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 SunOS 5.9 Last change: Revision-4.86 23 Maintenance Procedures LSOF(8) only the path by which the file was opened, not its possibly different final path. -z [z] specifies how Solaris 10 and higher zone informa- tion is to be handled. Without a following argument - e.g., NO z - the option specifies that zone names are to be listed in the ZONE output column. The -z option may be followed by a zone name, z. That causes lsof to list only open files for processes in that zone. Multiple -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 con- ditions specified by other options and arguments. -Z [Z] specifies how SELinux security contexts are to be handled. It and 'Z' field output character support are inhibited when SELinux is disabled in the run- ning Linux kernel. See OUTPUT FOR OTHER PROGRAMS for more information on the 'Z' field output char- acter. Without a following argument - e.g., NO Z - the option specifies that security contexts are to be listed in the SECURITY-CONTEXT output column. The -Z option may be followed by a wildcard secu- rity context name, Z. That causes lsof to list only open files for processes in that security con- text. Multiple -Z Z option and argument pairs may be specified to form a list of security contexts. Any open file of any process in any of the security contexts will be listed, subject to other condi- tions 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 sig- nals 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 signi- fied by the presence of a minus sign in the follow- ing option 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 separated from the preceding options with the ``--'' option. SunOS 5.9 Last change: Revision-4.86 24 Maintenance Procedures LSOF(8) 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 regular file is treated - i.e., its listing is restricted to processes 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 multi- plexed 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 structure. (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 dev- ice and inode number, allowing name to be a rela- tive 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 absolute path in /proc/net/unix and name via successful stat(2) sys- tem 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 directory is /dev, then name could be ./log. SunOS 5.9 Last change: Revision-4.86 25 Maintenance Procedures LSOF(8) 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 ALTER- NATE DEVICE NUMBERS sections for more information. 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 recognizing AFS files in the supported dialects. Lsof may have trouble identifying all aspects of AFS files in supported dialects when AFS kernel support is implemented via dynamic modules whose addresses do not appear in the kernel's variable name list. In that case, lsof may have to guess at the identity of AFS files, and might not be able to obtain volume information from the kernel that is needed for 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 information 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. SunOS 5.9 Last change: Revision-4.86 26 Maintenance Procedures LSOF(8) 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 alternate kernel name list or memory files. Restricting the listing of all open files is controlled by the compile-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 IDentifica- tion number as the real user ID number of the lsof process (the one that its user logged on with). However, if HASSECURITY and HASNOSOCKSECURITY are both defined, anyone may list open socket files, provided they are selected with the -i option. When HASSECURITY is not defined, anyone may list all open files. Help output, presented in response to the -h or -? option, gives the status of the HASSECURITY and HASNOSOCKSECURITY definitions. See the Security section of the 00README file of the lsof distribution for information on building lsof with the HASSECURITY and HASNOSOCKSECURITY 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 defined, 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 dev- ice cache file handling information. When HASDCACHE is not defined, the -h or -? output will have no -D option descrip- tion. Before you decide to disable the device cache file feature - enabling it improves the performance of lsof by reducing the SunOS 5.9 Last change: Revision-4.86 27 Maintenance Procedures LSOF(8) 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 characters. Non-printable characters are printed in one of three forms: the C ``\[bfrnt]'' form; the control char- acter `^' form (e.g., ``^@''); or hexadecimal leading ``\x'' form (e.g., ``\xab''). Space is non-printable in the COM- MAND column (``\x20'') and printable elsewhere. For some dialects - if HASSETLOCALE is defined in the dialect's machine.h header file - lsof will print the extended 8 bit characters of a language locale. The lsof process must be supplied a language locale environment vari- able (e.g., LANG) whose value represents a known language locale in which the extended characters are considered 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 characters - e.g., UTF-8 - when HASSETLOCALE and HASWIDECHAR are defined in the dialect's machine.h header file, and when a suitable language locale has been defined in the appropriate environment variable for the lsof pro- cess. 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 print- able, lsof considers the wide characters non-printable and prints each of their 8 bits according to its rules for SunOS 5.9 Last change: Revision-4.86 28 Maintenance Procedures LSOF(8) non-printable characters, stated above. Consult the answers to the "Language locale support" ques- tions in the lsof FAQ (The FAQ section gives its location.) for more information. Lsof dynamically sizes the output columns each time it runs, guaranteeing that each column is a minimum size. It also guarantees that each column is separated from its predeces- sor 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 charac- ters of the name of the UNIX command associated with the process up to the limit of characters supplied to lsof by the UNIX dialect. (See the description of the +c w command or the lsof FAQ for more information. The FAQ section gives its location.) If w is less than the length of the column title, ``COMMAND'', it will be raised to that length. If a zero w value is specified to the +c w option, the column contains all the characters of the name of the UNIX command associated with the process. All command name characters maintained by the 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 pro- cess. TID is the task IDentification number, if a task reporting is supported by the dialect and a task is being listed. (If help output - i.e., the output of the -h or -? options - shows this option, then task reporting is supported by the dialect.) A blank TID column indicates a process - i.e., a non-task. ZONE is the Solaris 10 and higher zone name. This column must be selected with the -z option. SunOS 5.9 Last change: Revision-4.86 29 Maintenance Procedures LSOF(8) SECURITY-CONTEXT is the SELinux security context. This column must be selected with the -Z option. Note that the -Z option is inhibited when SELinux is dis- abled in the running Linux kernel. 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 asso- ciated 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 information on when a user ID number or login name is displayed.) FD is the File Descriptor number of the file or: cwd current working directory; Lnn library references (AIX); err FD information error (see NAME column); jld jail directory (FreeBSD); ltx shared library text (code and data); Mxx hex memory-mapped type number xx. m86 DOS Merge mapped file; mem memory-mapped file; mmap memory-mapped device; pd parent directory; rtd root directory; tr kernel trace file (OpenBSD); 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 SunOS 5.9 Last change: Revision-4.86 30 Maintenance Procedures LSOF(8) character follows. The mode character is followed by one of these lock characters, 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 information character. The FD column contents constitutes a single field for parsing in post-processing scripts. TYPE is the type of the node associated with the file - e.g., GDIR, GREG, VDIR, VREG, etc. or ``IPv4'' for an IPv4 socket; or ``IPv6'' for an open IPv6 network file - even if its address is IPv4, mapped in an IPv6 address; or ``ax25'' for a Linux AX.25 socket; or ``inet'' for an Internet domain socket; or ``lla'' for a HP-UX link level access file; or ``rte'' for an AF_ROUTE socket; or ``sock'' for a socket of unknown domain; or ``unix'' for a UNIX domain socket; or ``x.25'' for an HP-UX x.25 socket; or ``BLK'' for a block special file; or ``CHR'' for a character special file; SunOS 5.9 Last change: Revision-4.86 31 Maintenance Procedures LSOF(8) or ``DEL'' for a Linux map file that has been deleted; or ``DIR'' for a directory; or ``DOOR'' for a VDOOR file; or ``FIFO'' for a FIFO special file; 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 ``NOFD'' for a Linux /proc//fd directory that can't be opened -- the directory path appears in the NAME column, followed by an error message; or ``PAS'' for a /proc/as file; or ``PAXV'' for a /proc/auxv file; 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 direc- tory; 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 direc- tory; 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; SunOS 5.9 Last change: Revision-4.86 32 Maintenance Procedures LSOF(8) 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 ``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 ``PRTD'' for a /proc root directory; or ``PSGA'' for a /proc/sigact file; SunOS 5.9 Last change: Revision-4.86 33 Maintenance Procedures LSOF(8) or ``PSIN'' for a /proc/psinfo file; or ``PSTA'' for a /proc status file; or ``PSXSEM'' for a POSIX semaphore file; or ``PSXSHM'' for a POSIX shared memory 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 ``SMT'' for a shared memory transport file; or ``STSO'' for a stream socket; or ``UNNM'' for an unnamed type file; or ``XNAM'' for an OpenServer Xenix special file of unknown type; or ``XSEM'' for an OpenServer Xenix semaphore file; or ``XSD'' for an OpenServer Xenix shared data file; or the four type number octets if the correspond- ing 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 semicolon (`;'); the first list may contain short-hand names for f_flag[s] values from the following table: SunOS 5.9 Last change: Revision-4.86 34 Maintenance Procedures LSOF(8) 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 SunOS 5.9 Last change: Revision-4.86 35 Maintenance Procedures LSOF(8) 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 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 , , , , and ; see the lsof.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 table: 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) SunOS 5.9 Last change: Revision-4.86 36 Maintenance Procedures LSOF(8) NODE-ID (or INODE-ADDR for some dialects) contains a unique identifier for the file node (usually the kernel vnode or inode address, but also occasion- ally 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 example.); or the base address or device name of a Linux AX.25 socket device. Usually only the lower thirty two bits of Tru64 UNIX kernel addresses are displayed. SIZE, SIZE/OFF, or OFFSET is the size of the file or the file offset in bytes. A value is displayed in this column only if it is available. Lsof displays whatever value - size or offset - is appropriate for the type of the file and the version of lsof. On some UNIX dialects lsof can't obtain accurate or consistent file offset information from its kernel data sources, sometimes just for particu- lar 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 normally displayed in decimal with a leading ``0t'' if it contains 8 digits or less; in hexa- decimal with a leading ``0x'' if it is longer than 8 digits. (Consult the -o o option descrip- tion for information on when 8 might default to some other value.) SunOS 5.9 Last change: Revision-4.86 37 Maintenance Procedures LSOF(8) 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 information. If the -s option is specified, lsof always displays the file size (or nothing if no size is available) and labels the column SIZE. The -o and -s options are mutually exclusive; they can't both be specified. For files that don't have a fixed size - e.g., don't reside on a disk device - lsof will display appropriate information about the current size or position of the file if it is available in the kernel structures that define the file. NLINK contains the file link count when +L has been specified; NODE is the node number of a local file; 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 spe- cial device; SunOS 5.9 Last change: Revision-4.86 38 Maintenance Procedures LSOF(8) 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 address; IP addresses may be reported as numbers or names, depending on the +|-M, -n, and -P options; colon-separated IPv6 numbers are enclosed in square brackets; IPv4 INADDR_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., ``(ESTABLISHED)'', ``(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 information on state, queue size, and window size; or the address or name of a UNIX domain socket, possibly including 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; SunOS 5.9 Last change: Revision-4.86 39 Maintenance Procedures LSOF(8) 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='' and ``wr='' for the values of the read and write offsets of a FIFO; or ``clone n:/dev/event'' for SCO OpenServer file clones of the /dev/event device, where n is the minor device number of the file; or ``(socketpair: n)'' for a Solaris 2.6, 8, 9 or 10 UNIX domain socket, created by the socketpair(3N) network function; or ``no PCB'' for socket files that do not have a protocol block associated with them, optionally followed by ``, CANTSENDMORE'' if sending on the socket has been disabled, or ``, CANTRCVMORE'' if receiving on the socket has been disabled (e.g., by the shutdown(2) function); or the local and remote addresses of a Linux IPX socket file in the form :[:], 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, end- point value, local address, local port, remote address and remote port for Linux SCTP sockets. For dialects that support a ``namefs'' file system, allowing one file to be attached to another with fattach(3C), lsof will add ``(FA:)'' to the NAME column. and are hexadecimal vnode addresses. will be ``<-'' if has been fattach'ed to this vnode whose address is SunOS 5.9 Last change: Revision-4.86 40 Maintenance Procedures LSOF(8) ; and ``->'' if , the vnode address of this vnode, has been fattach'ed to . may be omitted if it already appears in the DEVICE column. Lsof may add two parenthetical notes to the NAME column for open Solaris 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 informa- tion it finds in the kernel and the limitations of the reporting format. Moreover, when a process holds several byte level locks on a file, lsof only reports the status of the first lock it encounters. If it is a byte level lock, then the lock char- acter will be reported in lower case - i.e., `r', `w', or `x' - rather than the upper case equivalent reported for a full file lock. Generally lsof can only report on locks held by local processes on local files. When a local process sets a lock 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 remote 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 iden- tified 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 extends 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 SunOS 5.9 Last change: Revision-4.86 41 Maintenance Procedures LSOF(8) `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 command, the process group IDentification (PGID) number, the task number and the user ID (UID) number or login name. A file set begins with a field whose identifier is `f' (for file descriptor). It is followed by lines that describe the file's access mode, lock state, type, device, size, offset, inode, protocol, name and stream module names. It extends 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 pro- cess and file set with a NL (012) character. Lsof always produces one field, the PID (`p') field. All other fields may be declared optionally in the field iden- tifier 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. It is entirely possible to select a set of fields that can- not easily be parsed - e.g., if the field descriptor field is not selected, it may be difficult to identify file sets. To help you avoid this difficulty, lsof supports the -F option; it selects the output of all fields with NL termina- tors (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) f file descriptor F file structure address (0x) G file flaGs (0x; names if +fg follows) g process group ID i file's inode number K tasK ID k link count l file's lock status SunOS 5.9 Last change: Revision-4.86 42 Maintenance Procedures LSOF(8) L process login name m marker between repeated output n file name, comment, Internet address N node identifier (ox o file's offset (decimal) p process ID (always selected) P protocol name r raw device number (0x) 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= QS= SO= (not all dialects) SS= (not all dialects) ST= TF= (not all dialects) WR= (not all dialects) WW= (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 descriptions by specifying the -F? option pair. (Escape the `?' character as your shell requires.) Addi- tional information on field content can be found in the OUT- PUT 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 ter- minator character. Lsof doesn't produce all fields for every process or file set, only those that are available. Some fields are mutu- ally exclusive: file device 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 SunOS 5.9 Last change: Revision-4.86 43 Maintenance Procedures LSOF(8) 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 terminator 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 out- put. 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 characters, indexes for storing them in a table, and explanation strings that may be com- piled 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 operation 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 become 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 responsiveness 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. SunOS 5.9 Last change: Revision-4.86 44 Maintenance Procedures LSOF(8) Lsof can also be directed to avoid the protection of timers and child processes when using the kernel functions that might block by specifying 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 alternate 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 option prevents lsof from obtaining them. Moreover, since lsof only has device numbers for the file systems that have alternates, its abil- ity to locate files on file systems depends completely on the availability and accuracy of the alternates. If no 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 mes- sages 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 speci- fied the -b option, lsof can obtain some of the information it needs - the device number and possibly the file system type - from the system mount table. When that is possible, lsof will report the device number it obtained. (You can suppress the report by specifying the -w option.) SunOS 5.9 Last change: Revision-4.86 45 Maintenance Procedures LSOF(8) 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 options 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 options, provided they are supported by your dialect. Check the output of lsof's -h or -? options to see if the +m and +m m options are available. The ``xxxx'' portion of the field is the hexadecimal value of the file system's device number. (Consult the st_dev field of the output of the lstat(2) and stat(2) functions for the appropriate values for your file systems.) Here's an example from a Sun Solaris 2.6 /etc/mnttab for a file system remotely mounted via NFS: nfs ignore,noquota,dev=2a40001 There's an advantage to having ``dev=xxxx'' entries in your mount table file, especially for file systems that are mounted from remote NFS servers. When a remote server crashes and you want to identify its users by running lsof 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 alternative 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 SunOS 5.9 Last change: Revision-4.86 46 Maintenance Procedures LSOF(8) Lsof is able to examine the kernel's name cache or use other kernel facilities (e.g., the ADVFS 4.x tag_to_path() func- tion 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 system 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 com- ponents for the same file may vary from cycle to cycle. That's because other running processes 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 location.) has more information on this situa- tion. Lsof can report path name components for these dialects: FreeBSD HP-UX Linux NetBSD NEXTSTEP OpenBSD OPENSTEP SCO OpenServer SCO|Caldera UnixWare Solaris Tru64 UNIX Lsof can't report path name components for these dialects: AIX If you want to know why lsof can't report path name com- ponents for some dialects, see the lsof FAQ (The FAQ section SunOS 5.9 Last change: Revision-4.86 47 Maintenance Procedures LSOF(8) 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 invocation of lsof. The -D? option output lists the read-only and write device cache file paths, the names of any applicable environment vari- ables, and the personal device cache path format. Lsof can detect that the current device cache file has been accidentally or maliciously modified by integrity checks, including the computation 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 legitimately 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 dif- ferent 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 speci- fied 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 SunOS 5.9 Last change: Revision-4.86 48 Maintenance Procedures LSOF(8) the /dev (or /devices) directory, it usually detects that a new device has been added; in that case lsof issues a warn- ing message and attempts to rebuild the device cache file. Whenever lsof writes a device cache file, it sets its owner- ship to the real UID of the executing process, and its per- mission 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 device cache files. The permissions are set by the local system administrator 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 ker- nel memory devices - e.g., ``kmem'', ``sys'', or ``system''. An lsof process that has setgid permission usually surrenders the permission after it has accessed the kernel memory devices. When it does that, lsof can allow more liberal device cache path formations. The lsof distribution recommends that versions for these dialects run setgid 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 and [6789].x for 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 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 Tru64 UNIX 5.1 SunOS 5.9 Last change: Revision-4.86 49 Maintenance Procedures LSOF(8) (Note: lsof for AIX 5L and above needs setuid-root permis- sion if its -X option is used.) Lsof for these dialects does not support a device cache, so the permissions 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 dev- ice 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 res- tricted under some conditions. They are restricted 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 permission.) 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 accom- panies -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 running setuid-root and surrenders its setgid permission, a path name argument 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 out- dated, 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. SunOS 5.9 Last change: Revision-4.86 50 Maintenance Procedures LSOF(8) DEVICE CACHE PATH FROM AN ENVIRONMENT VARIABLE Lsof's second choice for the device cache file is the con- tents 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 pro- cess 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 environ- ment 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 adminis- tration procedure when the system is booted or when the con- tents 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 default. 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. SunOS 5.9 Last change: Revision-4.86 51 Maintenance Procedures LSOF(8) The hostname part of the second component is the base name of the executing 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 gethost- name(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 distinct real user ID on a given host that exe- cutes 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 outdated. 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 con- structing the personal device cache file. The conversions used in the format specification 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 dev- ice cache file path. The LSOFPERSDCPATH variable contents are inserted in the path at the place marked by the local system administrator with the ``%p'' conversion in the HASPERSDC format specifi- cation of the dialect's machine.h header file. (It's placed right after the home directory in the default lsof distribu- tion.) Thus, for example, if LSOFPERSDCPATH contains ``LSOF'', the home directory 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 pro- cess is root. SunOS 5.9 Last change: Revision-4.86 52 Maintenance Procedures LSOF(8) Lsof will not write to a modified personal device cache file path if the lsof process doesn't surrender setgid permis- sion. (See the LSOF PERMISSIONS THAT AFFECT DEVICE CACHE FILE ACCESS section for a list of implementations that nor- mally don't surrender their setgid permission.) If, for example, you want to create a sub-directory of per- sonal 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 personal 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. It returns a zero (0) if no errors were detected and if it was able to list some information about all the specified search arguments. When lsof cannot open access to /dev (or /devices) or one of its subdirectories, 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 mes- sage: 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 output from the help options will include the message: SunOS 5.9 Last change: Revision-4.86 53 Maintenance Procedures LSOF(8) 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 Presuming the UNIX dialect supports IPv6, to list only open IPv6 network 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, use: lsof /u/abe/foo SunOS 5.9 Last change: Revision-4.86 54 Maintenance Procedures LSOF(8) 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 pro- cess, file descriptor, file device number, and file inode number for each file of each process, use: lsof -FpcfDi To list the files at descriptors 1 and 3 of every process running the lsof command for login ID ``abe'' every 10 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, SunOS 5.9 Last change: Revision-4.86 55 Maintenance Procedures LSOF(8) 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 zeroes 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 char- acter (following 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 permis- sions by name unless it is installed with root set-UID per- mission. Otherwise it is limited to searching for files to which its user or its set-GID group (if any) has access per- mission. The display of the destination address of a raw socket (e.g., for ping) depends on the UNIX operating system. Some dialects store the destination 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 SunOS 5.9 Last change: Revision-4.86 56 Maintenance Procedures LSOF(8) SYSV R4 - e.g., FreeBSD, 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 structures 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 vari- able set to ``:0.0''. The +|-f[cfgGn] option is not supported under /proc-based Linux lsof, because it doesn't read kernel structures from kernel memory. ENVIRONMENT Lsof may access these environment variables. LANG defines a language locale. See setlo- cale(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 DEVICE CACHE PATH FROM AN ENVIRON- MENT VARIABLE section for more informa- tion. LSOFPERSDCPATH defines the middle component of a modified personal device cache file path. See the MODIFIED PERSONAL DEVICE CACHE PATH sec- tion for more information. FAQ Frequently-asked questions and their answers (an FAQ) are available in the 00FAQ file of the lsof distribution. SunOS 5.9 Last change: Revision-4.86 57 Maintenance Procedures LSOF(8) That file is also available via anonymous ftp from lsof.itap.purdue.edu at pub/tools/unix/lsofFAQ. The URL is: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/FAQ 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 of Pur- due University. Many others have contributed to lsof. They're listed in the 00CREDITS file of the lsof distribu- tion. DISTRIBUTION The latest distribution of lsof is available via anonymous ftp from the host lsof.itap.purdue.edu. You'll find the lsof distribution in the pub/tools/unix/lsof directory. You can also use this URL: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof Lsof is also mirrored elsewhere. When you access lsof.itap.purdue.edu and change to its pub/tools/unix/lsof directory, you'll be given a list of some mirror sites. The pub/tools/unix/lsof directory also contains a more complete list in its mirrors file. Use mirrors with caution - not all mirrors always have the latest lsof revision. Some pre-compiled Lsof executables are available on lsof.itap.purdue.edu, but their use is discouraged - it's better that you build your own from the sources. If you feel you must use a pre-compiled executable, please read the cautions that appear in the README files of the pub/tools/unix/lsof/binaries subdirectories and in the 00* files of the distribution. More information on the lsof distribution can be found in its README.lsof_ file. If you intend to get the lsof distribution and build it, please read README.lsof_ and the other 00* files of the distri- bution before sending questions to the author. SunOS 5.9 Last change: Revision-4.86 58 Maintenance Procedures LSOF(8) 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), modload(8), mount(8), netstat(1), ofiles(8L), perl(1), ps(1), readlink(2), setlocale(3), stat(2), strftime(3), time(2), uname(1). SunOS 5.9 Last change: Revision-4.86 59 lsof-4.86+dfsg.orig/00.README.FIRST0000444000175000017500000000226607460023324016446 0ustar nicholasnicholasNow that you have the lsof distribution, I suggest: * If you're unfamiliar with lsof, read 00README for information on Configuring and building lsof, 00QUICKSTART for tips on using lsof. If you're too impatient for that, do this: $ ./Configure (Do the inventory step, as you prefer.) (Do the customization step, as you prefer.) $ make $ ./lsof -h To get a list of UNIX dialect abbreviations: $ Configure -h Please don't be impatient -- read the documentation first. * Read the current distribution's details in 00DIST. * If you want technical details, read 00DCACHE and 00PORTING. * If you want to cross-configure, read 00XCONFIG. * Use the test suite, described in 00TEST, by: $ cd tests $ make and possibly: $ make opt * If you're having trouble, read 00FAQ. (Please read 00FAQ before you send a bug report.) * Lsof contributors may find their names in 00CREDITS. (Thanks, again.) * Read the lsof.man page file. Its nroff source is in lsof.8. * Consider subscribing to the lsof-l mailing list -- read 00LSOF-L for details. Vic Abell April 19, 2002 lsof-4.86+dfsg.orig/usage.c0000444000175000017500000005710111631741210015724 0ustar nicholasnicholas/* * 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"; static char *rcsid = "$Id: usage.c,v 1.30 2011/09/07 19:13:49 abe Exp $"; #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(xv, fh, version) int xv; /* exit value */ int fh; /* ``-F ?'' status */ int version; /* ``-v'' status */ { char buf[MAXPATHLEN+1], *cp, *cp1, *cp2; int col, i; if (Fhelp || xv) { (void) fprintf(stderr, "%s %s\n latest revision: %s\n", Pn, LSOF_VERSION, LSOF_URL); (void) fprintf(stderr, " latest FAQ: %sFAQ\n", LSOF_URL); (void) fprintf(stderr, " latest man page: %slsof_man\n", LSOF_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]", #if defined(HASDCACHE) "|-" #else /* !defined(HASDCACHE) */ "" #endif /* defined(HASDCACHE) */ ); (void) fprintf(stderr, " [+|-f%s%s%s%s%s%s]%s\n [-F [f]] [-g [s]] [-i [i]]", #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(HASEOPT) " [+|-e s]" #else /* !defined(HASEOPT) */ "" #endif /* defined(HASEOPT) */ ); #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 (xv && !Fhelp) { (void) fprintf(stderr, "Use the ``-h'' option to get more help information.\n"); if (!fh) Exit(xv); } 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"; # 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) col = print_in_col(col, "-K list 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"); #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"); (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]", #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; m must separate %s", "t from and\n"); (void) fprintf(stderr, " 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_URL); (void) fprintf(stderr, " latest FAQ: %sFAQ\n", LSOF_URL); (void) fprintf(stderr, " latest man page: %slsof_man\n", LSOF_URL); #if defined(LSOF_CINFO) if ((cp = isnullstr(LSOF_CINFO))) (void) fprintf(stderr, " configuration info: %s\n", cp); #endif /* defined(LSOF_CINFO) */ if ((cp = isnullstr(LSOF_CCDATE))) (void) fprintf(stderr, " constructed: %s\n", cp); 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(xv); } lsof-4.86+dfsg.orig/Configure0000555000175000017500000042410611741060544016334 0ustar nicholasnicholas#!/bin/sh # # Configure -- configure lsof # # See the LSOF_HLP here document for usage. # # See the lsof distribution file 00XCONFIG for information on setting # environment variables for cross-configuring lsof -- e.g., for configuring # for Linux 2.3 on a machine running 2.4. Marty Leisner suggested this # support and provided the Linux Configure stanza modifications. # # When configuring for a particular dialect, , this script # requires that the subdirectory ./dialects/ contain a # shell script, named $LSOF_MK, that places its source modules in this # directory. # # $Id: Configure,v 1.161 2012/04/10 16:35:46 abe Exp $ # LSOF_CFLAGS_OVERRIDE=1 may be introduced through the environment to cause # the library Makefile's CFLAGS definition to override any in the # environment. # LSOF_DISTRIBKVM may be introduced through the environment to specify the # Sun4 kernel virtual memory type of distrib.cf LSOF_F="ddev.c dfile.c dlsof.h dmnt.c dnode*.c dproc.c dproto.h dsock.c dstore.c dzfs.h kernelbase.h machine.h machine.h.old new_machine.h __lseek.s" LSOF_HLP_BASE=./cfghlp. LSOF_HLP=${LSOF_HLP_BASE}$$ # LSOF_LOCALSUFFIX may be introduced through the environment to select a local # version of a Makefile. It is used as a suffix to $LSOF_MKF. # LSOF_MAKE may be introduced through the environment to specify a path to the # make command. It defaults to `which make`, if that is non-NULL; # otherwise to the string "make". if test "X$LSOF_MAKE" = "X" # { then LSOF_MAKE=`which make` if test "X$LSOF_MAKE" = "X" # { then LSOF_MAKE=make fi # } fi # } LSOF_MK=Mksrc # LSOF_MKC is the dialect's Mksrc create command -- default "ln -s". # LSOF_MKFC may be introduced though the environment to change the name # used for the created make file. if test "X$LSOF_MKFC" = "X" # { then LSOF_MKFC=Makefile fi # } LSOF_LIB=lib LSOF_MKF=Makefile LSOF_LIBMKF=Makefile LSOF_LIBMKFSKEL=Makefile.skel LSOF_VF=version # Make sure no other variable important to Makefile construction is # already set in the environment. # # $AFS_VICE locatiion of AFS VICE directory # (default = /usr/vice) # $LSOF_AFS AFS temporary # $LSOF_AFS_NQ AFS-not-qualified flag # $LSOF_AFSV AFS version # $LSOF_AR archive command and its arguments for making the # lsof library # $LSOF_ARCH Unix dialect architecture as a string (may be # supplied externally) # $LSOF_CC C compiler name (may be supplied externally) # $LSOF_CCV C compiler version (may be supplied externally) # $LSOF_CDIR configuration directory # $LSOF_CFGD depend options # $LSOF_CFGDN depend file name # $LSOF_CFGF C flags -- e.g., -D's # $LSOF_CFGL last lsof library loader flags -- e.g., -l's # $LSOF_CINFO Configure information for LSOF_CINFO in version.h # $LSOF_CTFH Solaris 10 and above libctf.h status # $LSOF_CTFL Solaris 10 and above -lctf status # $LSOF_DEBUG Makefile's DEBUG string # $LSOF_DINC include flags -- -I's # $LSOF_DINC_ADD include flags status # $LSOF_DOC special document (man page) directory path # $LSOF_ERR internal error flag # $LSOF_FCFGL first lsof library loader flags -- e.g., -l's # that must precede $LSOF_LIB # $LSOF_FBSD_ZFS FreeBSD $LSOF_FBSD_ZFS_MKF status # $LSOF_FBSD_ZFS_CFGF FreeBSD ZFS configure flags # $LSOF_FBSD_ZFS_MKF FreeBSD ZFS Makefile name # $LSOF_FBSD_ZFS_SYS FreeBSD ZFS system sources location # $LSOF_HOST host name (e.g., from uname -n) # $LSOF_INCLUDE directory where header files are found # (default = /usr/include) # $LSOF_LD loader name if not $LSOF_CC # $LSOF_LIB_NO if "N" don't configure the lsof library # $LSOF_LOCALSUFFIX local suffix for Makefile # $LSOF_NBSD_BUFQH NetBSD copy status # $LSOF_NBSD_PTYFS NetBSD ${NETBSD_SYS}/sys/fs/ptyfs/ copy status # $LSOF_N_UNIXV *BSD system's kernel file # $LSOF_PL patch level # $LSOF_RANLIB randomizing command for the lsof library # $LSOF_RANLIB_SUP if non-NULL $LSOF_RANLIB was supplied # $LSOF_SCRIPT_CALL Customize and Inventory scripts call status # $LSOF_SPMKF Special Makefile name # $LSOF_TGT canonical target abbreviation (shortest) # $LSOF_TMP internal temporary # $LSOF_TMP1 internal temporary # $LSOF_TMP2 internal temporary # $LSOF_TMP3 internal temporary # $LSOF_TMP4 internal temporary # $LSOF_TMP5 internal temporary # $LSOF_TMP6 internal temporary # $LSOF_TMPC_BASE base name for $LSOF_TMPC # $LSOF_TMPC temporary C source file base name # $LSOF_TSTBIGF big file capability (for $LSOF_TSTCFLG) # $LSOF_TSTCC tests CC file # $LSOF_TSTCFLG tests CFLAGS file # $LSOF_TSTDFLG dialect-specific values for $LSOF_TSTCFLG # $LSOF_TSTK64 status of 64 bit kernel (for $LSOF_TSTCFLG) # $LSOF_TSTKMEM /dev/kmem usage status (for $LSOF_TSTCFLG) # $LSOF_TSTLFF tests LDFLAGS file # $LSOF_TSTLFLG tests LDFLAGS values # $LSOF_TSTSUBD test subdirectory # $LSOF_TSTVPATH test v_path state (for $LSOF_TSTCFLG) # $LSOF_TSTXO test extra objects (for $LSOF_TSTXOC) # $LSOF_TSTXOC test extra objects file # $LSOF_UNSUP Lsof is unsupported on this dialect # $LSOF_VERS Unix dialect version as a decimal number (may # be supplied externally) # $LSOF_VSTR Unix dialect version as a string -- may be supplied # externally if test "X$AFS_VICE" = "X" # { then AFS_VICE="/usr/vice" fi # } LSOF_AFS="" LSOF_AFS_NQ="" LSOF_AFSV="" if test "X$LSOF_ARCH" = "X" # { then LSOF_ARCH="" fi # } LSOF_CDIR="" LSOF_CFGD="" LSOF_CFGDN="" LSOF_CINFO="" LSOF_CTFH=0 LSOF_CTFL=0 LSOF_DEBUG="" LSOF_DOC="" LSOF_ERR="" LSOF_FCFGL="" LSOF_FBSD_ZFS=0 LSOF_FBSD_ZFS_CFGF="" LSOF_FBSD_ZFS_MKF="Makefile.zfs" LSOF_FBSD_ZFS_SYS="" LSOF_HOST="" if test "X$LSOF_INCLUDE" = "X" # { then LSOF_DINC="" LSOF_INCLUDE="/usr/include" else LSOF_DINC="-I$LSOF_INCLUDE" fi # } LSOF_LD="" LSOF_LIB_NO="" LSOF_PL="" if test "X$LSOF_RANLIB" = "X" # { then LSOF_RANLIB="ranlib" LSOF_RANLIB_SUP="" else LSOF_RANLIB_SUP="Y" fi # } LSOF_SCRIPT_CALL="yes" LSOF_SPMKF="" LSOF_TMP1="" LSOF_TMP2="" LSOF_TMPC_BASE=./lsof_Configure_tmp_ LSOF_TMPC=${LSOF_TMPC_BASE}$$ LSOF_TSTBIGF="" LSOF_TSTSUBD="./tests" LSOF_TSTCC="${LSOF_TSTSUBD}/config.cc" LSOF_TSTCFLG="${LSOF_TSTSUBD}/config.cflags" LSOF_TSTDFLG="" LSOF_TSTK64=0 LSOF_TSTKMEM=1 LSOF_TSTLFF="${LSOF_TSTSUBD}/config.ldflags" LSOF_TSTLFLG="" LSOF_TSTVPATH=0 LSOF_TSTXO="" LSOF_TSTXOC="${LSOF_TSTSUBD}/config.xobj" LSOF_UNSUP="WARNING: unsupported dialect or version" if test "X$LSOF_VERS" = "X" # { then LSOF_VERS="" fi # } if test "X$LSOF_VSTR" = "X" # { then LSOF_VSTR="" fi # } # Establish echo type -- Berkeley or SYSV. j=`echo -n ""` if test "X$j" = "X-n " then EC="\c" EO="" else EC="" EO="-n" fi # Make sure temporary files are removed before an abnormal exit. trap 'rm -f ${LSOF_HLP_BASE}* ${LSOF_TMPC_BASE}*; exit 1' 1 2 3 15 rm -f $LSOF_HLP cat > $LSOF_HLP << LSOF_HLP Usage: Configure : -clean : clean up previous configuration -d|-dialects : display a list of supported dialect versions -h|-help : display help information -n : avoid AFS, customization, and inventory checks (****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 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 LSOF_TGT="no-target" args=$# while test $args -gt 0 # { do case $1 in # { -clean) if test -r $LSOF_MKFC # { then echo "$LSOF_MAKE -f $LSOF_MKFC clean" $LSOF_MAKE -f $LSOF_MKFC clean else if test -r ${LSOF_LIB}/${LSOF_LIBMKF} # { then echo "(cd ${LSOF_LIB}; $LSOF_MAKE -f ${LSOF_LIBMKF} clean)" (cd ${LSOF_LIB}; $LSOF_MAKE -f ${LSOF_LIBMKF} clean) else if test -r ${LSOF_LIB}/${LSOF_LIBMKF}.skel # { then echo "(cd ${LSOF_LIB}; $LSOF_MAKE -f ${LSOF_LIBMKF}.skel clean)" (cd ${LSOF_LIB}; $LSOF_MAKE -f ${LSOF_LIBMKF}.skel clean) fi # } fi # } fi # } if test -r ${LSOF_TSTSUBD}/Makefile # { then echo "(cd ${LSOF_TSTSUBD}; $LSOF_MAKE spotless)" (cd ${LSOF_TSTSUBD}; $LSOF_MAKE spotless) else echo '(cd ${LSOF_TSTSUBD}; rm *.o config.*)' (cd ${LSOF_TSTSUBD}; rm *.o config.*) fi # } rm -f $LSOF_F $LSOF_MKFC $LSOF_FBSD_ZFS_MKF ${LSOF_TMPC_BASE}* echo rm -f $LSOF_F $LSOF_MKFC $LSOF_FBSD_ZFS_MKF ${LSOF_TMPC_BASE}* rm -rf AFSHeaders AFSVersion solaris11 version.h vnode_if.h echo "rm -rf AFSHeaders AFSVersion solaris11 version.h vnode_if.h" rm -f ${LSOF_HLP_BASE}* cd9660_node.h lockf_owner.h fbsd_minor.h echo "rm -f ${LSOF_HLP_BASE}* cd9660_node.h lockf_owner.h fbsd_minor.h" rm -f dialects/aix/aix5/j2/j2_snapshot.h echo "rm -f dialects/aix/aix5/j2/j2_snapshot.h" rm -f dialects/sun/solaris10 # DEBUG -- for s10_44 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 -f dialects/uw/uw7/vm/swap.h echo "rm -f dialects/uw/uw7/vm/swap.h" rm -f ${LSOF_LIB}/${LSOF_LIBMKF} echo "rm -f ${LSOF_LIB}/${LSOF_LIBMKF}" exit 0 ;; -d|-dialects) if test -r ./00DIALECTS -a -r ./version # { then V=`sed '/VN/s/.ds VN \(.*\)/\1/' version` echo "lsof $V has been *tested* on these UNIX dialect versions:" cat 00DIALECTS echo Although "$V hasn't been tested on other versions of these dialects," echo "it may work. Try \`Configure \` and \`make\` to see." rm -f $LSOF_HLP exit 0 else echo "Can't display UNIX dialect version information:" if test ! -r ./00DIALECTS # { then echo " ./00DIALECTS is inaccessible." fi # } if test ! -r ./version # { then echo " ./version is inaccessible." fi # } rm -f $LSOF_HLP exit 1 fi # } ;; -h|-help) cat $LSOF_HLP rm -f $LSOF_HLP exit 0 ;; -n*) LSOF_SCRIPT_CALL="no" ;; *) if test "X$LSOF_TGT" != "Xno-target" # { then echo "Only one dialect may be configured at a time." echo 'Both "$LSOF_TGT" and "$1" were specified.' cat $LSOF_HLP rm -f $LSOF_HLP exit 1 else LSOF_TGT=$1 fi # } ;; esac # } shift args=`expr $args - 1` done # } case $LSOF_TGT in # { no-target) echo "No target dialect was specified." cat $LSOF_HLP rm -f $LSOF_HLP exit 1 ;; # Configure for AIX xlc and AIX gcc. aix|aixgcc) # AIXA stands for AIX architecture. It is assigned these values in this # stanza: # # 0 The AIX version is < 5.0, or the AIX 5.0 architecture is # Power and the kernel bit size is 32. # # 1 The AIX version is >= 5.0, the AIX architecture is Power, # and the kernel bit size is 64. # # 2 The AIX version is >= 5.0 and the architecture is IA64. if test "X$LSOF_RANLIB_SUP" = "X" # { then LSOF_RANLIB="@echo \\\\\\\\c" # AIX make doesn't like a null ${RANLIB}. fi # } if test "X$LSOF_VSTR" = "X" # { then # If the AIX version isn't pre-defined, determine it. LSOF_TMP1=`uname -v` if test "X$LSOF_TMP1" = "X5" # { then # If the AIX version is 5, build the version string with `uname -rv` # output. LSOF_VSTR=`uname -r | awk '{printf "5.%d.0.0\n",\$1}'` echo "Uname reports the version is $LSOF_VSTR." else # See if oslevel can determine the version. LSOF_TMP1=/usr/bin/oslevel if test -x $LSOF_TMP1 # { then 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." else # 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; edit CFGF in Makefile and" echo " lib/Makefile to refine AIXV and LSOF_VSTR." fi # } fi # } fi # } if test "X$LSOF_VERS" = "X" # { then LSOF_VERS=`echo $LSOF_VSTR | sed 's/\.//g'` fi # } if test $LSOF_VERS -ge 4320 # { then LSOF_TSTBIGF=" " fi # } if test "X$LSOF_CC" = "X" # { then if test "X$LSOF_TGT" = "Xaixgcc" # { then LSOF_CC=gcc LSOF_CCV=`$LSOF_CC -v 2>&1 | sed -n 's/.*version \(.*\)/\1/p'` else LSOF_CC=cc fi # } fi # } LSOF_TGT="aix" echo $LSOF_CC | grep gcc > /dev/null if test $? -eq 0 # { then # Prevent use of gcc for AIX below 4.1. if test $LSOF_VERS -lt 4100 # { then echo "********************************************************" echo "* Sorry, but gcc can't be used to compile lsof for AIX *" echo "* versions less than 4.1, because of possible kernel *" echo "* structure alignment differences between it and xlc. *" echo "********************************************************" rm -f $LSOF_HLP exit 1 fi # } fi # } # Test for AFS. if test "X$AIX_HAS_AFS" != "X" # { then LSOF_AFS=$AIX_HAS_AFS fi # } if test "X$LSOF_AFS" != "Xno" # { then if test "X$LSOF_AFS" = "Xyes" -o -r ${AFS_VICE}/etc/ThisCell # { then if test "X$LSOF_AFS" != "Xyes" # { 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 # } fi # } if test "X$LSOF_AFS" = "Xyes" # { then if test "X$LSOF_AFSV" = "X" # { then if test -r ./AFSVersion # { then LSOF_AFSV=`cat ./AFSVersion | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1 \2/' | awk '{printf "%d%02d\n",\$1,\$2}'` else echo "!!!FATAL: no ./AFSVersion file. It should have been" echo " created by a previous AFS configuration run." rm -f $LSOF_HLP exit 1 fi # } fi # } if test $LSOF_VERS -gt 4330 -o LSOF_AFSV -gt 305 # { then echo "!!!FATAL: Lsof does not support AFS on this combination of" echo " AIX ($LSOF_VERS) and AFS ($LSOF_AFSV) versions." echo " To disable AFS, set the value of the AIX_HAS_AFS" echo " environment variable to \"no\"." rm -f $LSOF_HLP exit 1 else LSOF_CFGF="$LSOF_CFGF -DHAS_AFS=$LSOF_AFSV" LSOF_DINC="$LSOF_DINC -I`cat ./AFSHeaders`" if test -r ${LSOF_INCLUDE}/sys/inttypes.h # { then grep "^typedef.*int16;" ${LSOF_INCLUDE}/sys/inttypes.h > /dev/null if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASINT16TYPE" fi # } grep "^typedef.*u_int32;" ${LSOF_INCLUDE}/sys/inttypes.h > /dev/null if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASUINT16TYPE" fi # } grep "^typedef.*int32;" ${LSOF_INCLUDE}/sys/inttypes.h > /dev/null if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASINT32TYPE" fi # } fi # } fi # } fi # } fi # } fi # } # Miscellaneous AIX tests if test -d ${LSOF_INCLUDE}/nfs # { then LSOF_CFGF="$LSOF_CFGF -DHAS_NFS" fi # } echo $LSOF_CC | grep cc | grep -v gcc > /dev/null if test $? -eq 0 -a $LSOF_VERS -ge 4140 -a $LSOF_VERS -lt 5000 # { then LSOF_CFGL="$LSOF_CFGL -bnolibpath" fi # } if test -r ${LSOF_INCLUDE}/sys/socket.h # { then grep AF_INET6 ${LSOF_INCLUDE}/sys/socket.h > /dev/null if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASIPv6" fi # } fi # } if test -r ${LSOF_INCLUDE}/sys/stat.h # { then grep stat64 ${LSOF_INCLUDE}/sys/stat.h > /dev/null if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASSTAT64" fi # } fi # } #DEBUG SANFS if test -r ${LSOF_INCLUDE}/sys/sanfs/sanfsnode.h??? # { #DEBUG SANFS then #DEBUG SANFS LSOF_CFGF="$LSOF_CFGF -DHAS_SANFS" #DEBUG SANFS fi # } if test $LSOF_VERS -ge 5000 # { then # This is AIX 5 or greater. if test -d ${LSOF_INCLUDE}/j2 # { then # 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) LSOF_CFGF="$LSOF_CFGF -DHAS_JFS2" LSOF_CFGF="$LSOF_CFGF -I`pwd`/dialects/aix/aix5" if test $LSOF_VERS -ge 5200 # { then if test -r ${LSOF_INCLUDE}/j2/j2_snapshot.h # { then # 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 fi # } echo $LSOF_CC | grep gcc > /dev/null if test $? -eq 0 # { then # Test gcc version for AIX 5.2. LSOF_TMP1=`echo $LSOF_CCV | awk -F . '{printf "%d%02d",$1,$2}'` if test $LSOF_TMP1 -ge 303 # { then # Add gcc >= 3.3 option to handle use of i_dev from the wInode # anonymous structure reference in the JFS2 inode structure of # . LSOF_CFGF="$LSOF_CFGF -fms-extensions" fi # } fi #} fi # } fi # } # Determine the AIX architecture type and set AIXA accordingly. if test "X$AIX_ARCH" = "X" # { then uname -a | grep -i ia64 > /dev/null if test $? -eq 0 # { then AIX_ARCH="ia64" else AIX_ARCH="" fi # } fi # } if test "X$AIX_ARCH" = "Xia64" # { then # This is AIX >= 5 on ia64. LSOF_TSTK64=1 echo $LSOF_CC | grep gcc > /dev/null if test $? -eq 0 # { then # Quit if gcc was specified as the compiler, since the gcc options to # do an ia64 lsof compilation are unknown. echo "*************************************************************" echo "* *" echo "* !!!!!!!!!!!!!!!!!!!!! FATAL ERROR !!!!!!!!!!!!!!!!!!!!!!! *" echo "* *" echo "* Gcc can't be used to compile lsof for AIX 5 and above on *" echo "* the ia64 architecture. Consult lsof's FAQ (in the file *" echo "* 00FAQ) for more information. *" echo "* *" echo "*************************************************************" rm -f $LSOF_HLP exit 1 fi # } LSOF_TMP1=2 if test "X$LSOF_AR" = "X" # { then LSOF_AR="/usr/bin/ar cr" fi # } LSOF_CFGF="$LSOF_CFGF -q64" LSOF_CFGL="$LSOF_CFGL -lelf" else # This is AIX >= 5 on Power architecture. echo $LSOF_CC | grep cc | grep -v gcc > /dev/null if test $? -eq 0 # { then LSOF_CFGL="$LSOF_CFGL -bnolibpath" fi # } if test "X$AIX_KERNBITS" = "X" # { then # The kernel bit size wasn't predefined. Determine it by compiling # and executing a test program. rm -f ${LSOF_TMPC}.* echo "#include " > ${LSOF_TMPC}.c echo '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 echo "Testing kernel bit size with $LSOF_CC" $LSOF_CC ${LSOF_TMPC}.c -o ${LSOF_TMPC}.x if test ! -x ${LSOF_TMPC}.x # { then echo "!!!FATAL: can't compile test program, ${LSOF_TMPC}.c." rm -f $LSOF_HLP rm -f ${LSOF_TMPC}.* exit 1 fi # } AIX_KERNBITS=`./${LSOF_TMPC}.x` rm -f ${LSOF_TMPC}.* fi # } # Use the kernel bit size specification to select archiver and compiler # options, and to update AIXA. case $AIX_KERNBITS in # { 32) if test "X$LSOF_AR" = "X" # { then LSOF_AR="/usr/bin/ar cr" fi # } LSOF_TMP1=0 ;; 64) if test "X$LSOF_AR" = "X" # { then LSOF_AR="/usr/bin/ar -X 64 -v -q" fi # } LSOF_TSTK64=1 LSOF_TMP1=1 echo $LSOF_CC | grep gcc > /dev/null if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -maix64" else LSOF_CFGF="$LSOF_CFGF -q64" fi # } ;; *) echo "!!!FATAL: unrecognized kernel bit size: $AIX_KERNBITS" rm -f $LSOF_HLP exit 1 esac # } # Put kernel bit size information in $LSOF_CINFO and $LSOF_CFGF. echo "Kernel bit size: $AIX_KERNBITS" LSOF_TMP2="${AIX_KERNBITS} bit kernel" if test "X$LSOF_CINFO" != "X" # { then LSOF_CINFO="${LSOF_CINFO} ${LSOF_TMP2}" else LSOF_CINFO="${LSOF_TMP2}" fi # } LSOF_CFGF="$LSOF_CFGF -DAIX_KERNBITS=${AIX_KERNBITS}" fi # } LSOF_CFGF="$LSOF_CFGF -DAIXA=$LSOF_TMP1" if test "X$LSOF_TSTDFLG" = "X" # { then LSOF_TSTDFLG="-DLT_AIXA=$LSOF_TMP1" else LSOF_TSTDFLG="$LSOF_TSTDFLG -DLT_AIXA=$LSOF_TMP1" fi # } else # AIX is < 5, so set AIXA accordingly. LSOF_CFGF="$LSOF_CFGF -DAIXA=0" if test "X$LSOF_TSTDFLG" = "X" # { then LSOF_TSTDFLG="-DLT_AIXA=0" else LSOF_TSTDFLG="$LSOF_TSTDFLG -DLT_AIXA=0" fi # } fi #} LSOF_CFGF="$LSOF_CFGF -DAIXV=$LSOF_VERS" LSOF_DIALECT_DIR=aix echo $LSOF_CC | grep gcc > /dev/null if test $? -eq 0 # { then # Do gcc tests. if test $LSOF_VERS -ge 4100 -a $LSOF_VERS -lt 4200 # { then if test "X$AIX_USHACK" = "X" # { then # Compile and run a gcc test program to evaluate the user structure. rm -f ${LSOF_TMPC}.* echo "#include " > ${LSOF_TMPC}.c echo "#include " >> ${LSOF_TMPC}.c echo "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 # { then LSOF_TMP1=1 else LSOF_TMP1=0 fi # } rm -f ${LSOF_TMPC}.* else if test "$AIX_USHACK" = "Y" -o "$AIX_USHACK" = "y" # { then LSOF_TMP1=1 else LSOF_TMP1=0 fi # } fi # } if test ${LSOF_TMP1} -eq 1 # { then echo "Applying gcc AIX 4.1+ user struct alignment hack" rm -rf ./dialects/aix/aix$LSOF_VERS mkdir ./dialects/aix/aix$LSOF_VERS mkdir ./dialects/aix/aix${LSOF_VERS}/sys sed 's/U_irss\[/dummy_for_alignment, U_irss\[/' < ${LSOF_INCLUDE}/sys/user.h > ./dialects/aix/aix${LSOF_VERS}/sys/user.h LSOF_CFGF="$LSOF_CFGF -U_LONG_LONG -I`pwd`/dialects/aix/aix$LSOF_VERS" fi # } fi # } else # Get xlc version number rm -f ${LSOF_TMPC}.* echo "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/'` rm ${LSOF_TMPC}.* echo "The version is \"${LSOF_CCV}\"." echo $LSOF_CCV | grep "Version [0-9]" > /dev/null if test $? -eq 0 # { then LSOF_TMP=`echo $LSOF_CCV | sed 's/.*Version \([0-9]*\).*/\1/'` if test "X$LSOF_TMP" != "X" -a $LSOF_TMP -ge 4 # { then if test $LSOF_TMP -ge 6 # { then LSOF_CFGF="$LSOF_CFGF -qmaxmem=-1" else LSOF_CFGF="$LSOF_CFGF -qmaxmem=16384" fi # } fi # } fi # } fi # } if test $LSOF_VERS -ge 5300 # { then LSOF_UNSUP="" fi # } ;; # Configure for Apple Darwin. darwin) if test "X$LSOF_CC" = "X" # { then LSOF_CC=cc LSOF_CCV=`$LSOF_CC -v 2>&1 | sed -n 's/.*version \(.*\)/\1/p'` fi # } if test "X$LSOF_VSTR" = "X" # { then LSOF_VSTR=`uname -r` fi # } if test "X$LSOF_VERS" = "X" # { then # If the Darwin / Mac OS X version isn't pre-defined, determine it. case $LSOF_VSTR in # { 1.2*) LSOF_VERS=120 ;; 1.3*) LSOF_VERS=130 ;; 1.4*) LSOF_VERS=140 ;; 5.[012]*) LSOF_VERS=500 ;; 5.[3-9]*) LSOF_VERS=530 ;; 6.*) LSOF_VERS=600 ;; 7.*) # Mac OS X 10.3 (Panther) LSOF_VERS=700 ;; 8.*) # Mac OS X 10.4 (Tiger) LSOF_VERS=800 ;; 9.*) # Mac OS X 10.5 (Leopard) LSOF_VERS=900 ;; 10.*) # Mac OS X 10.6 (SnowLeopard) LSOF_VERS=1000 ;; 11.*) # Mac OS X 10.7 (Lion) LSOF_VERS=1100 ;; 12.*) # Next Mac OS X LSOF_VERS=1200 ;; *) echo Unknown Darwin release: `uname -r` echo Assuming Darwin 11.0 LSOF_VERS=1100 ;; esac # } fi # } # Do Darwin version-specific stuff. case $LSOF_VERS in # { 120|130) LSOF_TMP1="hfs/hfs.h hfs/hfs_macos_defs.h miscfs/devfs/devfsdefs.h miscfs/devfs/devfs_proto.h miscfs/fdesc/fdesc.h" ;; 140|500) LSOF_TMP1="hfs/hfs.h hfs/hfs_macos_defs.h hfs/rangelist.h miscfs/devfs/devfsdefs.h miscfs/devfs/devfs_proto.h miscfs/fdesc/fdesc.h" ;; 530) LSOF_TMP1="hfs/hfs.h hfs/hfs_macos_defs.h hfs/rangelist.h miscfs/devfs/devfsdefs.h miscfs/devfs/devfs_proto.h miscfs/fdesc/fdesc.h net/ndrv.h net/ndrv_var.h" ;; 600) LSOF_CFGF="$LSOF_CFGF -DHASIPv6" LSOF_TMP1="hfs/hfs.h hfs/hfs_catalog.h hfs/hfs_cnode.h hfs/hfs_macos_defs.h hfs/rangelist.h miscfs/devfs/devfsdefs.h miscfs/devfs/devfs_proto.h miscfs/fdesc/fdesc.h net/ndrv_var.h net/raw_cb.h netinet/ip_var.h netinet/tcp_var.h" ;; 700) LSOF_CFGF="$LSOF_CFGF -DHASIPv6" LSOF_TMP1="hfs/hfs.h hfs/hfs_catalog.h hfs/hfs_cnode.h hfs/hfs_macos_defs.h hfs/rangelist.h miscfs/devfs/devfsdefs.h miscfs/devfs/devfs_proto.h miscfs/fdesc/fdesc.h net/ndrv_var.h net/raw_cb.h netinet/ip_var.h netinet/tcp_var.h sys/eventvar.h" ;; 800) LSOF_CFGF="$LSOF_CFGF -DHASIPv6" LSOF_TMP1="net/ndrv_var.h net/raw_cb.h netinet/ip_var.h netinet/tcp_var.h sys/eventvar.h sys/file_internal.h sys/mount_internal.h sys/proc_internal.h sys/vnode_internal.h" ;; 900|1000|1100) LSOF_CFGF="$LSOF_CFGF -DHASIPv6" LSOF_TMP1="" LSOF_UNSUP="" LSOF_TSTBIGF=" " # enable LTbigf test ;; 1200) LSOF_CFGF="$LSOF_CFGF -DHASIPv6" LSOF_TMP1="" ;; *) echo "Unsupported Darwin version: $LSOF_VERS" rm -f $LSOF_HLP exit 1 ;; esac # } LSOF_TMP2="" LSOF_TMP3="" LSOF_TMP4="" 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" # { then LSOF_TMP5="" if test $LSOF_VERS -ge 800 -o "X$DARWIN_BASE" = "Xlibproc" # { then if test -r ${LSOF_INCLUDE}/libproc.h # { then DARWIN_BASE="libproc" else if test -r ${LSOF_INCLUDE}/../local/include/libproc.h # { then DARWIN_BASE="libproc" LSOF_TMP5="-I${LSOF_INCLUDE}/../local/include" else echo "FATAL: can't find libproc.h" rm -f $LSOF_HLP exit 1 fi # } fi # } else # The default Darwin base is /dev/kmem. DARWIN_BASE="/dev/kmem" fi # } fi # } if test "X$DARWIN_BASE" = "Xlibproc" # { then # Configure for libproc-based Darwin lsof. echo "Configuring libproc-based Darwin lsof" LSOF_CINFO="libproc-based" LSOF_DIALECT_DIR=darwin/libproc if test $LSOF_VERS -lt 1000 # { then LSOF_CFGL="$LSOF_CFGL -lproc" fi # } LSOF_TSTKMEM=0 LSOF_DINC="$LSOF_DINC $LSOF_TMP5" if test ! -r ${LSOF_INCLUDE}/sys/proc_info.h # { then if test "X$LSOF_TMP5" = "X" -o ! -r ${LSOF_TMP5}/sys/proc_info.h # { then echo "FATAL: can't find sys/proc_info.h" rm -f $LSOF_HLP exit 1 fi # } fi # } # Add header file paths for libproc-based Darwin lsof. for i in $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 # } # Do other libproc-based Darwin lsof setups. if test -r ${LSOF_INCLUDE}/utmpx.h # { 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 if test "X$LSOF_CC" = "X" # { then LSOF_CC=cc LSOF_CCV=`$LSOF_CC -v 2>&1 | sed -n 's/.*version \(.*\)/\1/p'` fi # } if test "X$LSOF_VSTR" = "X" # { then LSOF_VSTR=`uname -r` fi # } if test "X$LSOF_VERS" = "X" # { then # If the FreeBSD version isn't pre-defined, determine it. case $LSOF_VSTR in # { 1.*) LSOF_VERS=1000 ;; 2.0-*) LSOF_VERS=2000 ;; 2.0.5-*) LSOF_VERS=2005 ;; 2.1*) LSOF_VERS=2010 ;; 2.2*) LSOF_VERS=2020 ;; 3.0*) LSOF_VERS=3000 ;; 3.1*) LSOF_VERS=3010 ;; 3.2*) LSOF_VERS=3020 ;; 3.3*) LSOF_VERS=3030 ;; 3.4*) LSOF_VERS=3040 ;; 3.5*) LSOF_VERS=3050 ;; 3*) LSOF_VERS=3050 echo "!!!WARNING!!! Unsupported FreeBSD version: $LSOF_VSTR" echo "!!!WARNING!!! Configuring for FreeBSD 3.5" ;; 4.0*) LSOF_TSTBIGF=" " LSOF_VERS=4000 ;; 4.1-*) LSOF_TSTBIGF=" " LSOF_VERS=4010 ;; 4.2*) LSOF_TSTBIGF=" " LSOF_VERS=4020 ;; 4.3*) LSOF_TSTBIGF=" " LSOF_VERS=4030 ;; 4.4*) LSOF_TSTBIGF=" " LSOF_VERS=4040 ;; 4.5*) LSOF_TSTBIGF=" " LSOF_VERS=4050 ;; 4.6*) LSOF_TSTBIGF=" " LSOF_VERS=4060 ;; 4.7*) LSOF_TSTBIGF=" " LSOF_VERS=4070 ;; 4.8*) LSOF_TSTBIGF=" " LSOF_VERS=4080 ;; 4.9*) LSOF_TSTBIGF=" " LSOF_VERS=4090 ;; 4.10*) LSOF_TSTBIGF=" " LSOF_VERS=4100 ;; 4.11*) LSOF_TSTBIGF=" " LSOF_VERS=4110 ;; 4*) LSOF_VERS=4100 echo "!!!WARNING!!! Unsupported FreeBSD version: $LSOF_VSTR" echo "!!!WARNING!!! Configuring for FreeBSD 4.10" ;; 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 ;; 9*) LSOF_TSTBIGF=" " LSOF_VERS=9000 ;; 10*) LSOF_TSTBIGF=" " LSOF_VERS=10000 ;; *) echo Unknown FreeBSD release: `uname -r` rm -f $LSOF_HLP exit 1 ;; esac # } fi # } # Clear LSOF_UNSUP message for supported versions of FreeBSD. case $LSOF_VERS in # { 4090|8020|8030|9000|10000) LSOF_UNSUP="" ;; esac # } # Get system CFLAGS from FREEBSD_MAKE_CONF (default=/etc/make.conf). if test "X$FREEBSD_MAKE_CONF" = "X" # { then FREEBSD_MAKE_CONF="/etc/make.conf" fi # } if test -r $FREEBSD_MAKE_CONF # { then LSOF_TMP1=`echo "all:\n.include " | $LSOF_MAKE -f- -VCFLAGS` LSOF_TMP=1 while test $LSOF_TMP -eq 1 # { do echo $LSOF_TMP1 | grep -q -e '-O' if test $? -eq 0 # { then if test "X$LSOF_DEBUG" = "X" then # { LSOF_DEBUG=`echo $LSOF_TMP1 | sed 's/.*\(-O[^ $]*\).*/\1/'` fi # } LSOF_TMP1=`echo $LSOF_TMP1 | sed 's/\(.*\)-O[^ $]*\(.*\)/\1 \2/' | sed 's/^ *//g' | sed 's/ */ /g' | sed 's/ *$//'` else LSOF_TMP=0 fi # } LSOF_FBSD_ZFS_CFGF="$LSOF_CFGF $LSOF_TMP1" done # } LSOF_CFGF="$LSOF_CFGF $LSOF_TMP1" fi # } # Determine path to FreeBSD sources. LSOF_DINC_ADD=0 if test "X$FREEBSD_SYS" = "X" # { then if test -d /usr/src/sys # { then FREEBSD_SYS=/usr/src/sys else if test -d /sys # { then FREEBSD_SYS="/sys" else echo "!!!WARNING!!! No kernel sources in /usr/src/sys or /sys" fi # } fi # } fi # } # Do FreeBSD version-specific stuff. case $LSOF_VERS in # { 1000) LSOF_CFGF="$LSOF_CFGF -DHASPROCFS" LSOF_CFGL="$LSOF_CFGL -lutil" LSOF_DINC="$LSOF_DINC -I`pwd`/dialects/freebsd/include" if test "X$FREEBSD_KERNEL" = "X" # { then LSOF_N_UNIXV="/386bsd" else LSOF_N_UNIXV=$FREEBSD_KERNEL fi # } ;; 2000|2005|2010) LSOF_CFGL="$LSOF_CFGL -lkvm" ;; 2020) LSOF_CFGL="$LSOF_CFGL -lkvm" if test -r ${LSOF_INCLUDE}/vm/lock.h # { then LSOF_CFGF="$LSOF_CFGF -DHASVMLOCKH" fi # } ;; 3000|3010|3020|3030|3040|3050) LSOF_CFGL="$LSOF_CFGL -lkvm" if test -r ${LSOF_INCLUDE}/nfs/rpcv2.h # { then LSOF_CFGF="$LSOF_CFGF -DHASRPCV2H" fi # } if test -r ${LSOF_INCLUDE}/vm/lock.h # { then LSOF_CFGF="$LSOF_CFGF -DHASVMLOCKH" fi # } ;; *) if test -r ${LSOF_INCLUDE}/nfs/rpcv2.h # { then LSOF_CFGF="$LSOF_CFGF -DHASRPCV2H" fi # } if test -r ${LSOF_INCLUDE}/sys/namei.h # { then grep -q "^struct[ ]*namecache[ ]*{" ${LSOF_INCLUDE}/sys/namei.h if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASNAMECACHE" fi # } 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 # } fi # } if test -r ${LSOF_INCLUDE}/sys/file.h # { then grep -q f_vnode ${LSOF_INCLUDE}/sys/file.h if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASF_VNODE" fi # } fi # } LSOF_CFGL="$LSOF_CFGL -lkvm" if test $LSOF_VERS -ge 5000 # { then # Do FreeBSD 5 and higher version-specific stuff. if test -r ${LSOF_INCLUDE}/sys/vnode.h # { then grep VT_FDESC ${LSOF_INCLUDE}/sys/vnode.h > /dev/null 2>&1 if test $? -eq 0 # { then if test ! -r ${LSOF_INCLUDE}/fs/devfs/devfs.h # { then if test -r ${FREEBSD_SYS}/fs/devfs/devfs.h # { then LSOF_DINC_ADD=1 else echo "!!!FATAL: lsof cannot locate the devfs.h header file" echo " in ${LSOF_INCLUDE}/fs/devfs/devfs.h or" echo " ${FREEBSD_SYS}/fs/devfs/devfs.h. Consult" echo " 00FAQ for an explanation." rm -f $LSOF_HLP exit 1 fi # } fi # } fi # } fi # } # Do FreeBSD 5.2 and higher version-specific stuff. if test $LSOF_VERS -ge 5020 # { then # Determine the status of the cpumask_t typedef. rm -f ${LSOF_TMPC}.* cat > ${LSOF_TMPC}.c << .LSOF_END_HERE_DOC3 #undef _KERNEL #include main() { cpumask_t c; } .LSOF_END_HERE_DOC3 $LSOF_CC ${LSOF_TMPC}.c -o ${LSOF_TMPC}.x > /dev/null 2>&1 LSOF_TMP1=$? rm -f ${LSOF_TMPC}.* if test $LSOF_TMP1 -ne 0 # { then # The cpumask_t typedef is unknown when _KERNEL is not defined. if test -r ${LSOF_INCLUDE}/sys/types.h \ -a -r ${LSOF_INCLUDE}/machine/_types.h # { then grep -q cpumask_t ${LSOF_INCLUDE}/sys/types.h if test $? -eq 0 # { then grep -q __cpumask_t ${LSOF_INCLUDE}/machine/_types.h if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASCPUMASK_T" else $LSOF_CC -E ${LSOF_INCLUDE}/machine/_types.h 2>/dev/null | grep -q __cpumask_t if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASCPUMASK_T" fi # } fi # } fi # } fi # } fi # } if test -r ${LSOF_INCLUDE}/sys/socketvar.h # { then grep -q SBS_CANT ${LSOF_INCLUDE}/sys/socketvar.h if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASSBSTATE" fi # } fi # } fi # } if test $LSOF_VERS -ge 5030 # { then # Do FreeBSD 5.3 and higher version-specific stuff. if test -r ${LSOF_INCLUDE}/sys/vnode.h # { then grep -q "defined(_KVM_VNODE)" ${LSOF_INCLUDE}/sys/vnode.h if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHAS_KVM_VNODE" fi #} fi # } fi # } if test $LSOF_VERS -ge 6000 # { then # Do FreeBSD 6.0 and higher version-specific stuff. if test -r ${LSOF_INCLUDE}/ufs/ufs/inode.h # { then grep -q i_din2 ${LSOF_INCLUDE}/ufs/ufs/inode.h if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHAS_UFS1_2" fi # } fi # } if test -r ${LSOF_INCLUDE}/sys/conf.h # { then grep -q vm_memattr_t ${LSOF_INCLUDE}/sys/conf.h if test $? -eq 0 #{ then LSOF_CFGF="$LSOF_CFGF -DHAS_VM_MEMATTR_T" fi # } grep -q "^#define minor(" ${LSOF_INCLUDE}/sys/conf.h if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHAS_CONF_MINOR" rm -f fbsd_minor.h if test -r ${LSOF_INCLUDE}/sys/types.h # { then LSOF_TMP1=`grep "^#define[ ]minor(" ${LSOF_INCLUDE}/sys/types.h` if test "X$LSOF_TMP1" != "X" # { then echo "Creating fbsd_minor.h" cat > fbsd_minor.h << FBSD_MINOR1 /* * fbsd_minor.h -- created by lsof Configure script on FBSD_MINOR1 echo $EO " * $EC" >> ./fbsd_minor.h date >> ./fbsd_minor.h cat >> ./fbsd_minor.h << FBSD_MINOR2 */ #if !defined(FBSD_MINOR_H) #define FBSD_MINOR_H FBSD_MINOR2 echo $EO "${LSOF_TMP1}${EC}" >> fbsd_minor.h cat >> ./fbsd_minor.h << FBSD_MINOR3 #endif /* defined(FBSD_MINOR_H) */ FBSD_MINOR3 fi # } fi # } else if test -r ${FREEBSD_SYS}/fs/devfs/devfs_int.h # { then grep -q cdev2priv ${FREEBSD_SYS}/fs/devfs/devfs_int.h if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHAS_CDEV2PRIV" 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 LSOF_CFGF="$LSOF_CFGF -DHAS_SI_PRIV" fi # } fi # } if test -r ${LSOF_INCLUDE}/sys/sx.h # { then LSOF_CFGF="$LSOF_CFGF -DHAS_SYS_SX_H" fi # } # Do ZFS test. Try for the newer OpenSolaris files first -- i.e., # the ones in ${FREEBSD_SYS}/cddl/contrib/opensolaris. If that fails, # try for the older ones in ${FREEBSD}/contrib/opensolaris. LSOF_FBSD_ZFS_SYS=${FREEBSD_SYS}/cddl if test ! -r ${LSOF_FBSD_ZFS_SYS}/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h # { then LSOF_FBSD_ZFS_SYS=${FREEBSD_SYS} if test ! -r ${LSOF_FBSD_ZFS_SYS}/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h # { then LSOF_FBSD_ZFS_SYS="" fi # } fi # } if test "X$LSOF_FBSD_ZFS_SYS" != "X" # { then LSOF_CFGF="$LSOF_CFGF -DHAS_ZFS" LSOF_FBSD_ZFS=1 LSOF_FBSD_ZFS_CFGF="$LSOF_FBSD_ZFS_CFGF -DFREEBSDV=$LSOF_VERS" LSOF_FBSD_ZFS_CFGF="$LSOF_FBSD_ZFS_CFGF -DHAS_ZFS" grep -q z_phys ${LSOF_FBSD_ZFS_SYS}/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h if test $? -eq 0 # { then LSOF_FBSD_ZFS_CFGF="$LSOF_FBSD_ZFS_CFGF -DHAS_Z_PHYS" fi # } fi # } if test -r ${LSOF_INCLUDE}/sys/vnode.h # { then # See if the vnode contains the byte level lock pointer. grep -q v_lockf ${LSOF_INCLUDE}/sys/vnode.h if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHAS_V_LOCKF" if test $LSOF_FBSD_ZFS -eq 1 # { then LSOF_FBSD_ZFS_CFGF="$LSOF_FBSD_ZFS_CFGF -DHAS_V_LOCKF" fi # } fi # } fi # } if test -r ${LSOF_INCLUDE}/sys/lockf.h # { then # Determine the type of locking structure to which the inode or # vnode points. grep -q "^struct lockf_entry" ${LSOF_INCLUDE}/sys/lockf.h if test $? -eq 0 # { then # Build the ./lockf_owner.h header file. LSOF_TMP1="" LSOF_TMP2=0 echo "Creating ./lockf_owner.h from ${FREEBSD_SYS}/kern/kern_lockf.c" rm -f ./lockf_owner.h if test -r ${FREEBSD_SYS}/kern/kern_lockf.c # { then LSOF_TMP1=`grep -n "^struct lock_owner" ${FREEBSD_SYS}/kern/kern_lockf.c | sed 's/\([0-9]*\):.*$/\1/'` if test "X$LSOF_TMP1" != "X" # { then LSOF_TMP2=0 for i in `grep -n "};" ${FREEBSD_SYS}/kern/kern_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_owner.h << LOCKF_OWNER1 /* * lockf_owner.h -- created by lsof Configure script on LOCKF_OWNER1 echo $EO " * $EC" >> ./lockf_owner.h date >> ./lockf_owner.h cat >> ./lockf_owner.h << LOCKF_OWNER2 */ #if !defined(LOCKF_OWNER_H) #define LOCKF_OWNER_H LOCKF_OWNER2 ed -s ${FREEBSD_SYS}/kern/kern_lockf.c >> ./lockf_owner.h << LOCKF_OWNER3 ${LSOF_TMP1},${LSOF_TMP2}p LOCKF_OWNER3 if test $? -ne 0 # { then LSOF_TMP1="" else cat >> ./lockf_owner.h << LOCKF_OWNER4 #endif /* defined(LOCKF_OWNER_H) */ LOCKF_OWNER4 fi # } fi # } fi # } else echo "FATAL ERROR: can't read ${FREEBSD_SYS}/kern/kern_lockf.c" fi # } if test "X$LSOF_TMP1" != "X" -a "X$LSOF_TMP2" != "X0" # { then echo "./lockf_owner.h creation succeeded." LSOF_CFGF="$LSOF_CFGF -DHAS_LOCKF_ENTRY" else echo "FATAL ERROR: ./lockf_owner.h creation failed (see 00FAQ)" rm -f $LSOF_HLP exit 1 fi # } fi # } # Test for in6p_.port in inpcb structure. if test -r ${LSOF_INCLUDE}/netinet/in_pcb.h # { then grep -q 'in6p_.port' ${LSOF_INCLUDE}/netinet/in_pcb.h if test $? -ne 0 # { then LSOF_CFGF="$LSOF_CFGF -DHAS_NO_6PORT" fi # } fi # } # Test for in6p_ppcb in inpcb structure. if test -r ${LSOF_INCLUDE}/netinet/in_pcb.h # { then grep -q 'in6p_ppcb' ${LSOF_INCLUDE}/netinet/in_pcb.h if test $? -ne 0 # { then LSOF_CFGF="$LSOF_CFGF -DHAS_NO_6PPCB" fi # } fi # } if test -r ${LSOF_INCLUDE}/sys/conf.h # { then grep -q 'doadump(boolean_t)' ${LSOF_INCLUDE}/sys/conf.h if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DNEEDS_BOOLEAN_T" fi # } fi # | fi # } fi # } fi # } ;; esac # } LSOF_CFGF="$LSOF_CFGF -DFREEBSDV=$LSOF_VERS" if test $LSOF_VERS -lt 2000 -a "X$FREEBSD_KERNEL" = "X" # { then if test ! -x $LSOF_N_UNIXV # { then echo "Hmmm -- $LSOF_N_UNIXV doesn't appear to be your kernel file." echo "Please enter the name of the file in / that contains" echo "the kernel for this host. It must be a regular file," echo "not a directory, and must be executable." LSOF_LOOP=1 while test $LSOF_LOOP = 1 # { do echo "" echo "/ contains:" echo "" ls -CF / echo "" echo -n "Kernel file name? " read LSOF_N_UNIXV LSOF_EXCESS LSOF_N_UNIXV="/$LSOF_N_UNIXV" if test ! -d $LSOF_N_UNIXV -a -x $LSOF_N_UNIXV # { then LSOF_LOOP=0 else echo "" echo $LSOF_N_UNIXV is not a regular executable file. fi # } done # } fi # } LSOF_N_UNIXV=`echo $LSOF_N_UNIXV | sed 's#^/*#/#'` LSOF_CFGF="$LSOF_CFGF -DN_UNIXV=$LSOF_N_UNIXV" fi # } if test -r ${FREEBSD_SYS}/miscfs/fdesc/fdesc.h # { then LSOF_TMP1=${FREEBSD_SYS}/miscfs/fdesc/fdesc.h else if test $LSOF_VERS -ge 5000 -a -r ${LSOF_INCLUDE}/fs/fdescfs/fdesc.h # { then LSOF_TMP1=${LSOF_INCLUDE}/fs/fdescfs/fdesc.h else LSOF_TMP1="" fi # } fi # } if test "X$LSOF_TMP1" != "X" # { then grep -q Fctty $LSOF_TMP1 if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASFDESCFS=1" else LSOF_CFGF="$LSOF_CFGF -DHASFDESCFS=2" fi # } grep -q fd_link $LSOF_TMP1 if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASFDLINK" fi # } LSOF_DINC_ADD=1 fi # } if test $LSOF_VERS -ge 5000 # { then LSOF_TMP1="fs" 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 # } fi # } if test -r ${LSOF_INCLUDE}/${LSOF_TMP1}/nullfs/null.h # { then LSOF_CFGF="$LSOF_CFGF -DHASNULLFS" else if test -r ${FREEBSD_SYS}/${LSOF_TMP1}/nullfs/null.h # { then LSOF_CFGF="$LSOF_CFGF -DHASNULLFS" LSOF_DINC_ADD=1 fi # } fi # } if test -r ${FREEBSD_SYS}/isofs/cd9660/cd9660_node.h # { then rm -f cd9660_node.h grep -q "^#ifdef [_]*KERNEL" ${FREEBSD_SYS}/isofs/cd9660/cd9660_node.h if test $? -eq 0 # { then ln -s ${FREEBSD_SYS}/isofs/cd9660/cd9660_node.h cd9660_node.h else sed -e '/^ \* Prototypes for ISOFS vnode operations/,$c\ \ The ISOFS prototypes were removed by Configure. */' \ < ${FREEBSD_SYS}/isofs/cd9660/cd9660_node.h > cd9660_node.h 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 grep -q nc_vpid ${LSOF_INCLUDE}/sys/namei.h if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASNCVPID" fi # } fi # } if test $LSOF_DINC_ADD -eq 1 # { then if test "X$LSOF_DINC" = "X" # { then LSOF_DINC="-I${FREEBSD_SYS}" else LSOF_DINC="$LSOF_DINC -I${LSOF_INCLUDE} -I${FREEBSD_SYS}" fi # } fi # } if test -r ${LSOF_INCLUDE}/netinet/in.h # { then grep IPV6_INRIA_VERSION ${LSOF_INCLUDE}/netinet/in.h > /dev/null if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASIPv6 -DHASINRIAIPv6" fi # } fi # } echo $CFGF | grep HASIPv6 > /dev/null if test $? -ne 0 -a -r ${LSOF_INCLUDE}/netinet6/in6.h # { then LSOF_CFGF="$LSOF_CFGF -DHASIPv6" fi # } if test -r ${LSOF_INCLUDE}/utmpx.h # { then LSOF_CFGF="$LSOF_CFGF -DHASUTMPX" fi # } LSOF_DIALECT_DIR=freebsd ;; # Configure for HP-UX and HP-UX gcc. hpux|hpuxgcc) if test "X$LSOF_RANLIB_SUP" = "X" # { then LSOF_RANLIB="" fi # } if test "X$LSOF_VSTR" = "X" # { then LSOF_VSTR=`uname -r` fi # } if test "X$LSOF_VERS" = "X" # { then # If the HP-UX version isn't pre-defined, determine it. LSOF_VERS=`echo $LSOF_VSTR | awk -F. '{printf "%d%02d",\$2,\$3}'` fi # } if test $LSOF_VERS -ge 1020 # { then LSOF_TSTBIGF="-D_LARGEFILE64_SOURCE" fi # } # Determine compiler. if test "X$LSOF_CC" = "X" # { then if test "X$LSOF_TGT" = "Xhpuxgcc" # { then LSOF_CC=gcc else if test "X$HPUX_CCDIR1" = "X" # { then HPUX_CCDIR1="/bin" fi # } if test "X$HPUX_CCDIR2" = "X" # { then HPUX_CCDIR2="/usr/ccs/bin" fi # } if test -x ${HPUX_CCDIR1}/cc # { then LSOF_CC=${HPUX_CCDIR1}/cc else if test -x ${HPUX_CCDIR2}/cc # { then LSOF_CC=${HPUX_CCDIR2}/cc else echo "No executable cc in $HPUX_CCDIR1 or $HPUX_CCDIR2" rm -f $LSOF_HLP exit 1 fi # } fi # } $LSOF_CC -O < /dev/null 2>&1 | grep -q Bundled if test $? -eq 0 # { then LSOF_DEBUG="No-O" # to disable -O if test "X$HPUX_LIBC1" = "X" # { then HPUX_LIBC1="/usr/lib" fi # } if test -r ${HPUX_LIBC1}/libc.sl # { then LSOF_FCFGL="-L$HPUX_LIBC -lc" else if test "X$HPUX_LIBC2" = "X" # { then HPUX_LIBC2="/usr/lib" fi # } if test -r ${HPUX_LIBC2}/libc.sl # { then LSOF_FCFGL="-L$HPUX_LIBC2 -lc" fi # } fi # } fi # } fi # } fi # } echo $LSOF_CC | grep gcc > /dev/null if test $? -eq 0 # { then LSOF_CCV=`$LSOF_CC -v 2>&1 | sed -n 's/.*version \(.*\)/\1/p'` else $LSOF_CC -O < /dev/null 2>&1 | grep -q Bundled if test $? -eq 0 # { then LSOF_DEBUG="No-O" # to disable -O fi # } fi # } LSOF_TGT=hpux # Test for "const void" support. rm -f ${LSOF_TMPC}.* echo "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 LSOF_CFGF="$LSOF_CFGF -DHAS_CONST" fi # } rm -f ${LSOF_TMPC}.* # Test HP-UX base. if test "X$HPUX_BASE" = "X" # { then if test -d $LSOF_INCLUDE/sys/pstat -a $LSOF_VERS -ge 1111 # { then HPUX_BASE="pstat" else HPUX_BASE="/dev/kmem" fi # } fi # } if test "X$HPUX_BASE" = "Xpstat" # { then # Configure for pstat-based HP-UX lsof. LSOF_CINFO="PSTAT-based" echo "Configuring PSTAT-based HP-UX lsof" LSOF_DIALECT_DIR=hpux/pstat LSOF_CFGF="$LSOF_CFGF -DHPUXV=$LSOF_VERS -D_PSTAT64" LSOF_CFGL="$LSOF_CFGL -lnsl" LSOF_TSTKMEM=0 LSOF_TSTK64=1 ls -l $LSOF_CC | grep -q ansic LSOF_TMP1=$? ls -l $LSOF_CC | grep -q aCC if test $? -eq 0 -o $LSOF_TMP1 -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -Ae +DD32" else echo $LSOF_CC | grep -q gcc if test $? -ne 0 # { then LSOF_CFGF="$LSOF_CFGF +DD32" fi # } fi # } if test -r ${LSOF_INCLUDE}/netinet/in6.h # { then LSOF_CFGF="$LSOF_CFGF -DHASIPv6" fi # } if test -r ${LSOF_INCLUDE}/sys/pstat/stream_pstat_body.h # { then grep -q PS_STR_XPORT_DATA ${LSOF_INCLUDE}/sys/pstat/stream_pstat_body.h if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -D_PSTAT_STREAM_GET_XPORT" fi # } fi # } if test $LSOF_VERS -ge 1123 # { then LSOF_CFGF="$LSOF_CFGF -D_LARGEFILE64_SOURCE" fi # } else if test "X$HPUX_BASE" = "X/dev/kmem" # { then # Configure for /dev/kmem-based HP-UX lsof. if test "X$HPUX_BOOTFILE" = "X" # { then HPUX_BOOTFILE="/stand/vmunix" fi # } if test $LSOF_VERS -gt 1100 # { then echo "" echo "************************************************" echo "* *" echo "* !!!!!!!!!!!!!!! FATAL ERROR !!!!!!!!!!!!!!!! *" echo "* *" echo "* LSOF DOES NOT SUPPORT THIS VERSION OF HP-UX. *" echo "* *" echo "************************************************" echo "" rm -f $LSOF_HLP exit 1 fi # } LSOF_CFGF="$LSOF_CFGF -DHPUXV=$LSOF_VERS" LSOF_CINFO="/dev/kmem-based" LSOF_DIALECT_DIR=hpux/kmem echo "Configuring /dev/kmem-based HP-UX lsof" if test $LSOF_VERS -lt 1000 # { then if test "X$HPUX_X25DIR" = "X" # { then HPUX_X25DIR="/etc/conf" else HPUX_X25DIR=$HPUX_X25DIR fi # } if test -r ${HPUX_X25DIR}/x25/x25addrstr.h # { then LSOF_CFGF="$LSOF_CFGF -DHPUX_CCITT" LSOF_DINC="$LSOF_DINC -I$HPUX_X25DIR" fi # } fi # } if test -r ${LSOF_INCLUDE}/sys/fs/vx_inode.h -a -r ${LSOF_INCLUDE}/sys/fs/vx_hpux.h # { then LSOF_CFGF="$LSOF_CFGF -DHASVXFS" fi # } if test $LSOF_VERS -ge 1030 # { then if test "X$HPUX_KERNBITS" = "X" # { then HPUX_KERNBITS=`getconf _SC_KERNEL_BITS` fi # } LSOF_CFGF="$LSOF_CFGF -DHPUXKERNBITS=${HPUX_KERNBITS} -I`pwd`/dialects/hpux/kmem/hpux11" if test $HPUX_KERNBITS -eq 64 # { then LSOF_TSTK64=1 echo "" echo "*****************************************" echo "* *" echo "* NOTICE! Configuring for 64 bit HP-UX *" echo "* *" echo "*****************************************" echo $LSOF_CC | grep gcc > /dev/null if test $? -eq 0 # { then # Test gcc for 64 bit support, trying gcc with no options, then # with -mlp64, testing the result with file. echo "" echo "Testing $LSOF_CC for 64 bit support" rm -f ${LSOF_TMPC}.* echo "main(){}" > ${LSOF_TMPC}.c LSOF_TMP1="" $LSOF_CC ${LSOF_TMPC}.c -o ${LSOF_TMPC}.x > /dev/null 2>&1 if test $? -eq 0 # { then /bin/file ${LSOF_TMPC}.x | /bin/grep 64 > /dev/null if test $? -eq 0 # { then LSOF_TMP1=" " fi # } fi # } if test "X$LSOF_TMP1" = "X" # { then rm -f ${LSOF_TMPC}.x $LSOF_CC ${LSOF_TMPC}.c -mlp64 -o ${LSOF_TMPC}.x > /dev/null 2>&1 if test $? -eq 0 # { then /bin/file ${LSOF_TMPC}.x | /bin/grep 64 > /dev/null if test $? -eq 0 # { then LSOF_TMP1="-mlp64" fi # } fi # } fi # } rm -f ${LSOF_TMPC}.* if test "X$LSOF_TMP1" = "X" # { then echo "" echo "***************************************************" echo "* *" echo "* !!!!!!!!!!!!!!!!! FATAL ERROR !!!!!!!!!!!!!!!!! *" echo "* *" echo "* APPARENTLY GCC CANNOT BUILD 64 BIT EXECUTABLES. *" echo "* A COMPILER MUST BE USED THAT CAN. SEE 00FAQ *" echo "* FOR MORE INFORMATION. *" echo "* *" echo "***************************************************" echo "" rm -f $LSOF_HLP exit 1 else if test "X$LSOF_TMP1" != "X " # { then LSOF_CFGF="$LSOF_CFGF $LSOF_TMP1" fi # } LSOF_CFGL="$LSOF_CFGL -lelf" LSOF_CINFO="${LSOF_CINFO}, 64 bit HP-UX" fi # } else # Set options for the HP-UX compiler. LSOF_CFGF="$LSOF_CFGF +DD64" LSOF_CFGL="$LSOF_CFGL -lelf" LSOF_CINFO="${LSOF_CINFO}, 64 bit HP-UX" fi # } else LSOF_CFGF="$LSOF_CFGF -D_FILE_OFFSET_BITS=64" LSOF_CINFO="${LSOF_CINFO}, 32 bit HP-UX" echo $LSOF_CC | grep gcc > /dev/null if test $? -ne 0 # { then LSOF_CFGF="$LSOF_CFGF +DAportable" fi # } fi # } LSOF_CFGL="$LSOF_CFGL -lnsl" else # When HP-UX is less than 10.30, but greater than or equal to 10, # check NFS3 rnode status. if test $LSOF_VERS -ge 1000 # { then LSOF_TMP1=0 if test "X$HPUX_RNODE3" = "X" # { then nm -x $HPUX_BOOTFILE | grep -q nfs_vnodeops3 if test $? -eq 0 # { then if test -r ${LSOF_INCLUDE}/nfs/rnode.h # { then grep -q r_fh3 ${LSOF_INCLUDE}/nfs/rnode.h if test $? -ne 0 # { then LSOF_TMP1=1 fi # } fi # } fi # } else if test "X$HPUX_RNODE3" = "X1" # { then LSOF_TMP1=1 fi # } fi # } if test $LSOF_TMP1 -eq 1 # { then LSOF_CFGF="$LSOF_CFGF -DHASRNODE3" fi # } fi # } fi # } if test $LSOF_VERS -eq 1100 # { then # Test for the ipis_s structure. If it is present, set HAS_IPC_S_PATCH. if test "X$HPUX_IPC_S_PATCH" = "X" # { then if test -x /usr/contrib/Q4/bin/q4exe # { then LSOF_TMP=/usr/contrib/Q4/bin/q4exe else LSOF_TMP=/usr/contrib/bin/q4 fi # } if test -x $LSOF_TMP # { then rm -f ${LSOF_TMPC}.out echo "" echo $EO "Looking in $HPUX_BOOTFILE for ipis_s with $LSOF_TMP ... $EC" echo "yes\\nfields -c struct ipis_s" | $LSOF_TMP $HPUX_BOOTFILE > ${LSOF_TMPC}.out 2>&1 if test $? -ne 0 # { then echo "" echo "" echo "!!!ERROR!!! $LSOF_TMP failed and produced the following output." echo "" cat ${LSOF_TMPC}.out HPUX_IPC_S_PATCH=fail else grep ipis_s ${LSOF_TMPC}.out > /dev/null 2>&1 if test $? -eq 0 # { then echo "ipis_s exists." # See if ipis_msgsqueued is present. grep ipis_msgsqueued ${LSOF_TMPC}.out > /dev/null 2>&1 if test $? -eq 0 # { then HPUX_IPC_S_PATCH=2 else HPUX_IPC_S_PATCH=1 fi # } else echo "ipis_s doesn't exist." HPUX_IPC_S_PATCH=N fi # } fi # } rm -f ${LSOF_TMPC}.out else echo "Can't locate or execute $LSOF_TMP" echo $EO "ls says: $EC" ls -ld $LSOF_TMP HPUX_IPC_S_PATCH=fail fi # } fi # } if test "X$HPUX_IPC_S_PATCH" = "Xfail" # { then echo "" echo "!!!ERROR!!! !!!ERROR!!! !!!ERROR!!! !!!ERROR!!!" echo "Configure can't use $LSOF_TMP to examine the ipis_s" echo "structure. You must do that yourself, report the result in" echo "the HPUX_IPC_S_PATCH environment variable, then repeat the" echo "Configure step. Consult the Configure script's use of" echo "$LSOF_TMP and the 00XCONFIG file for information" echo "on ipis_s testing and the setting of HPUX_IPC_S_PATCH." echo "!!!ERROR!!! !!!ERROR!!! !!!ERROR!!! !!!ERROR!!!" echo "" rm -f $LSOF_HLP exit 1 fi # } if test "X$HPUX_IPC_S_PATCH" = "X1" -o "X$HPUX_IPC_S_PATCH" = "X2" # { then LSOF_CFGF="$LSOF_CFGF -DHAS_IPC_S_PATCH=$HPUX_IPC_S_PATCH" else if test "X$HPUX_IPC_S_PATCH" != "Xn" -a "X$HPUX_IPC_S_PATCH" != "XN" # { then echo "Illegal value for HPUX_IPC_S_PATCH: $HPUX_IPC_S_PATCH" rm -f $LSOF_HLP exit 1 fi # } fi # } fi #} # Manufacture an hpux_mount.h header file with a mount struct in it, as # required. if test -r ${LSOF_INCLUDE}/sys/mount.h # { then LSOF_TMP1="dialects/${LSOF_DIALECT_DIR}/hpux_mount.h" rm -f $LSOF_TMP1 echo "#if !defined(MANUFACTURED_HPUX_SYS_MOUNT_H)" > $LSOF_TMP1 echo "#define MANUFACTURED_HPUX_SYS_MOUNT_H" >> $LSOF_TMP1 echo "/* By lsof Configure:" `date` " */" >> $LSOF_TMP1 echo "struct mount" >> $LSOF_TMP1 sed '1,/struct mount/d' ${LSOF_INCLUDE}/sys/mount.h | sed -n '1,/m_dev/p' >> $LSOF_TMP1 echo "};" >> $LSOF_TMP1 echo "#endif" >> $LSOF_TMP1 LSOF_CFGF="$LSOF_CFGF -I`pwd`/dialects/${LSOF_DIALECT_DIR}" fi # } # Test for OnlineJFS. if test $LSOF_VERS -ge 1100 # { then if test "X$HPUX_HASONLINEJFS" = "X" -a -x /sbin/fs/vxfs/subtype # { then LSOF_TMP1=`/sbin/fs/vxfs/subtype` if test "X$LSOF_TMP1" = "Xvxfs3.3" then HPUX_HASONLINEJFS="Y" fi # } fi # } if test "X$HPUX_HASONLINEJFS" = "XY" -o "X$HPUX_HASONLINEJFS" = "Xy" # { then LSOF_CFGF="$LSOF_CFGF -DHASONLINEJFS" fi # } fi # } # Test for AFS. if test -r ${AFS_VICE}/etc/ThisCell # { 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 # } fi # } else echo "HP-UX base unrecognized: $HPUX_BASE" rm -f $LSOF_HLP exit 1 fi # } fi # } ;; # Configure for Linux. linux) LSOF_TSTBIGF="-D_FILE_OFFSET_BITS=64" LSOF_TSTKMEM=0 if test "X$LSOF_CC" = "X" # { then LSOF_CC=cc LSOF_CCV=`$LSOF_CC -v 2>&1 | sed -n 's/.*version \(.*\)/\1/p'` fi # } if test "X$LINUX_CONF_CC" = "X" # { then LINUX_CONF_CC=$LSOF_CC fi #} LSOF_DIALECT_DIR="" if test "X$LINUX_INCL" = "X" # { then LINUX_INCL=/usr/include else LSOF_DINC="$LSOF_DINC -I${LINUX_INCL}" fi # } if test "X$LINUX_VERSION_CODE" = "X" # { then if test -r "$LINUX_INCL/linux/version.h" # { then LINUX_VERSION_CODE=`cat $LINUX_INCL/linux/version.h | sed -n 's/.\+LINUX_VERSION_CODE \([[:digit:]]\+\)$/\1/p'` fi # } fi # } LSOF_VSTR=`echo $LINUX_VERSION_CODE | perl -e '$version=; chomp($version); printf("%d.%d.%d\n", ($version >> 16) & 0xFF, ($version >> 8) & 0xFF, $version & 0xFF);'` if test "X$LSOF_VSTR" = "X" # { then LSOF_VSTR=`uname -r` fi # } if test "X$LSOF_VERS" = "X" # { then # If the Linux version isn't predefined, determine it. LSOF_VERS=`echo $LSOF_VSTR | sed 's/\./ /g' | awk '{printf "%d%d%03d",\$1,\$2,\$3}'` fi # } LSOF_CFGF="$LSOF_CFGF -DLINUXV=$LSOF_VERS" if test $LSOF_VERS -lt 21072 # { then echo "" echo "!!!WARNING!!!==!!!WARNING!!!==!!!WARNING!!!==!!!WARNING!!!" echo "! !" echo "! THE /PROC-BASED LSOF SOURCES HAVE NOT BEEN TESTED ON !" echo "! LINUX KERNELS BELOW 2.1.72, AND MAY NOT WORK ON THIS !" echo "! KERNEL. IT SHOULD USE A /DEV/KMEM-BASED LSOF. !" echo "! !" echo "!!!WARNING!!!==!!!WARNING!!!==!!!WARNING!!!==!!!WARNING!!!" echo "" else LSOF_UNSUP="" fi # } # If the Linux C library type isn't predefined, determine it. if test "X$LINUX_CLIB" = "X" # { then echo -n "Testing C library type with $LINUX_CONF_CC ... " rm -f ${LSOF_TMPC}.* cat > $LSOF_TMPC.c << .LSOF_END_HERE_DOC1 #include main() { #if defined(__GLIBC__) && defined(__GLIBC_MINOR__) printf("-DGLIBCV=%d\n",__GLIBC__*100+__GLIBC_MINOR__); #elif defined(__GLIBC__) printf("-DGLIBCV=%d00\n",__GLIBC__); #else printf("\n"); #endif return(0); } .LSOF_END_HERE_DOC1 $LINUX_CONF_CC ${LSOF_TMPC}.c -I$LSOF_INCLUDE -o ${LSOF_TMPC}.x > /dev/null 2>&1 if test -x ${LSOF_TMPC}.x # { then LINUX_CLIB=`${LSOF_TMPC}.x` LSOF_TMP=$? else LINUX_CLIB="" LSOF_TMP=1 fi # } rm -f ${LSOF_TMPC}.* echo "done" if test $LSOF_TMP -ne 0 # { then echo "Cannot determine C library type; assuming it is not glibc." LINUX_CLIB="" else if test "X$LINUX_CLIB" = "X" # { then echo "The C library type is not glibc." else echo "The C library type is glibc, version \"$LINUX_CLIB\"." fi # } fi # } fi # } if test "X$LINUX_CLIB" != "X" # { then LSOF_CFGF="$LSOF_CFGF $LINUX_CLIB" fi # } # Test for IPv6 support. if test -r ${LSOF_INCLUDE}/netinet/ip6.h # { then LSOF_CFGF="$LSOF_CFGF -DHASIPv6" fi # } # Test for . if ! test -r ${LSOF_INCLUDE}/rpc/rpc.h # { then LSOF_CFGF="$LSOF_CFGF -DHASNORPC_H" fi # } # Test for SELinux support. LSOF_TMP1=0 if test "X$LINUX_HASSELINUX" = "X" # { then if test -r ${LSOF_INCLUDE}/selinux/selinux.h # { then LSOF_TMP1=1 fi # } else if test "X$LINUX_HASSELINUX" = "XY" -o "X$LINUX_HASSELINUX" = "Xy" # { then LSOF_TMP1=1 fi # } fi # } if test $LSOF_TMP1 -eq 1 # { then LSOF_CFGF="$LSOF_CFGF -DHASSELINUX" LSOF_CFGL="$LSOF_CFGL -lselinux" fi # } LSOF_DIALECT_DIR="linux" LSOF_CFGF="$LSOF_CFGF -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE" ;; # Configure for NetBSD. netbsd) if test "X$LSOF_CC" = "X" # { then LSOF_CC=cc LSOF_CCV=`$LSOF_CC -v 2>&1 | sed -n 's/.*version \(.*\)/\1/p'` fi # } if test "X$LSOF_VSTR" = "X" # { then LSOF_VSTR=`uname -r` fi # } if test "X$LSOF_VERS" = "X" # { then # Validate the NetBSD version. case $LSOF_VSTR in # { 1.2*) LSOF_VERS="1002000" ;; 1.3*) LSOF_VERS="1003000" ;; 1.4*) LSOF_VERS="1004000" ;; 1.5*) LSOF_TSTBIGF=" " LSOF_VERS="1005000" ;; 1.6*) LSOF_TSTBIGF=" " LSOF_VERS="1006000" ;; 1*) LSOF_VERS="1006000" echo "!!!WARNING!!! Unsupported NetBSD version: $LSOF_VSTR" echo "!!!WARNING!!! Configuring for NetBSD 1.6" ;; 2.0*) LSOF_TSTBIGF=" " LSOF_VERS="2000000" ;; 2.99.9) LSOF_TSTBIGF=" " LSOF_VERS="2099009" ;; 2.99.10) LSOF_TSTBIGF=" " LSOF_VERS="2099010" ;; 2.99.*) LSOF_TSTBIGF=" " LSOF_VERS="2099010" ;; 2*) LSOF_VERS="2000000" echo "!!!WARNING!!! Unsupported NetBSD version: $LSOF_VSTR" echo "!!!WARNING!!! Configuring for NetBSD 2.0" ;; 3.0*) LSOF_TSTBIGF=" " LSOF_VERS="3000000" ;; 3.99.*) LSOF_TSTBIGF=" " LSOF_VERS="3099000" ;; 3*) LSOF_VERS="3000000" echo "!!!WARNING!!! Unsupported NetBSD version: $LSOF_VSTR" echo "!!!WARNING!!! Configuring for NetBSD 3.0" ;; *) echo "Unknown NetBSD release: $LSOF_VSTR" echo Assuming NetBSD 1.6 LSOF_VERS="1006000" ;; 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 # } LSOF_CFGF="$LSOF_CFGF -DNETBSDV=$LSOF_VERS" LSOF_TMP1="-DN_UNIXV=/netbsd" if test -r ${LSOF_INCLUDE}/util.h # { then grep -q getbootfile ${LSOF_INCLUDE}/util.h if test $? -eq 0 # { then LSOF_CFGL="$LSOF_CFGL -lutil" LSOF_TMP1="-DHASGETBOOTFILE" fi # } fi # } LSOF_CFGF="$LSOF_CFGF $LSOF_TMP1" if test -r ${LSOF_INCLUDE}/kvm.h # { then grep -q kvm_getproc2 ${LSOF_INCLUDE}/kvm.h if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASKVMGETPROC2" fi # } fi # } # Here begin the dual tests on header files that may be in $LSOF_INCLUDE # or $NETBSD_SYS. # # Note that $LSOF_TMP1 holds an indicator of the need for -I$NETBSD_SYS. # LSOF_TMP4 contains a temporary indicator of the use of $NETBSD_SYS. LSOF_TMP1=0 if test "X$NETBSD_SYS" = "X" # { then if test -d /usr/src # { then NETBSD_SYS="/usr/src/sys" else NETBSD_SYS=$LSOF_INCLUDE fi # } fi # } LSOF_TMP2="nfs/nfsproto.h" if test -r ${LSOF_INCLUDE}/$LSOF_TMP2 # { then LSOF_TMP3="${LSOF_INCLUDE}/$LSOF_TMP2" LSOF_TMP4=0 else if test -r ${NETBSD_SYS}/$LSOF_TMP2 # { then LSOF_TMP3="${NETBSD_SYS}/$LSOF_TMP2" LSOF_TMP4=1 else LSOF_TMP3="" fi # } fi # } if test "X$LSOF_TMP3" != "X" # { then LSOF_CFGF="$LSOF_CFGF -DHASNFSPROTO" if test $LSOF_TMP1 -eq 0 -a $LSOF_TMP4 -eq 1 # { then LSOF_TMP1=1 fi # } fi # } LSOF_TMP2="netinet/ip6.h" if test -r ${LSOF_INCLUDE}/$LSOF_TMP2 # { then LSOF_TMP3="${LSOF_INCLUDE}/$LSOF_TMP2" LSOF_TMP4=0 else if test -r ${NETBSD_SYS}/$LSOF_TMP2 # { then LSOF_TMP3="${NETBSD_SYS}/$LSOF_TMP2" LSOF_TMP4=1 else LSOF_TMP3="" fi # } fi # } if test "X$LSOF_TMP3" != "X" # { then LSOF_CFGF="$LSOF_CFGF -DHASIPv6" if test $LSOF_TMP1 -eq 0 -a $LSOF_TMP4 -eq 1 # { then LSOF_TMP1=1 fi # } else LSOF_TMP2="netinet/in.h" if test -r ${LSOF_INCLUDE}/$LSOF_TMP2 # { then LSOF_TMP3="${LSOF_INCLUDE}/$LSOF_TMP2" LSOF_TMP4=0 else if test -r ${NETBSD_SYS}/$LSOF_TMP2 # { then LSOF_TMP3="${NETBSD_SYS}/$LSOF_TMP2" LSOF_TMP4=1 else LSOF_TMP3="" fi # } fi # } if test "X$LSOF_TMP3" != "X" # { then grep -q IPV6_INRIA_VERSION $LSOF_TMP3 if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASIPv6 -DHASINRIAIPv6" if test $LSOF_TMP1 -eq 0 -a $LSOF_TMP4 -eq 1 # { then LSOF_TMP1=1 fi # } fi # } fi # } fi # } LSOF_TMP2="miscfs/fdesc/fdesc.h" if test -r ${LSOF_INCLUDE}/$LSOF_TMP2 # { then LSOF_TMP3="${LSOF_INCLUDE}/$LSOF_TMP2" else if test -r ${NETBSD_SYS}/$LSOF_TMP2 # { then LSOF_TMP3="${NETBSD_SYS}/$LSOF_TMP2" LSOF_TMP4=1 else LSOF_TMP3="" fi # } fi # } if test "X$LSOF_TMP3" != "X" # { then grep -q Fctty $LSOF_TMP3 if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASFDESCFS=1" else LSOF_CFGF="$LSOF_CFGF -DHASFDESCFS=2" fi # } grep -q fd_link $LSOF_TMP3 if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASFDLINK" fi # } if test $LSOF_TMP1 -eq 0 -a $LSOF_TMP4 -eq 1 # { then LSOF_TMP1=1 fi # } fi # } LSOF_TMP2="miscfs/nullfs/null.h" if test -r ${LSOF_INCLUDE}/$LSOF_TMP2 # { then LSOF_TMP3="${LSOF_INCLUDE}/$LSOF_TMP2" LSOF_TMP4=0 else if test -r ${NETBSD_SYS}/$LSOF_TMP2 # { then LSOF_TMP3="${NETBSD_SYS}/$LSOF_TMP2" LSOF_TMP4=1 else LSOF_TMP3="" fi # } fi # } if test "X$LSOF_TMP3" != "X" # { then LSOF_CFGF="$LSOF_CFGF -DHASNULLFS" if test $LSOF_TMP1 -eq 0 -a $LSOF_TMP4 -eq 1 # { then LSOF_TMP1=1 fi # } fi # } LSOF_TMP2="miscfs/procfs" if test -d ${LSOF_INCLUDE}/$LSOF_TMP2 # { then LSOF_TMP3="${LSOF_INCLUDE}/$LSOF_TMP2" LSOF_TMP4=0 else if test -d ${NETBSD_SYS}/$LSOF_TMP2 # { then LSOF_TMP3="${NETBSD_SYS}/$LSOF_TMP2" LSOF_TMP4=1 else LSOF_TMP3="" fi # } fi # } if test "X$LSOF_TMP3" != "X" # { then LSOF_CFGF="$LSOF_CFGF -DHASPROCFS" if test $LSOF_TMP1 -eq 0 -a $LSOF_TMP4 -eq 1 # { then LSOF_TMP1=1 fi # } if test -r ${LSOF_TMP3}/procfs.h # { then grep -q PFSroot ${LSOF_TMP3}/procfs.h if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASPROCFS_PFSROOT" fi # } fi # } fi # } LSOF_TMP2="sys/bufq.h" LSOF_NBSD_BUFQH=0 if test -r ${LSOF_INCLUDE}/$LSOF_TMP2 # { then LSOF_CFGF="$LSOF_CFGF -DHASBUFQ_H" else if test -r ${NETBSD_SYS}/$LSOF_TMP2 # { then if test $NETBSD_SYS != $LSOF_INCLUDE # { then LSOF_CFGF="$LSOF_CFGF -DHASBUFQ_H" LSOF_NBSD_BUFQH=1 fi # } fi # } fi # } LSOF_TMP2="isofs/cd9660" if test -d ${LSOF_INCLUDE}/$LSOF_TMP2 # { then LSOF_TMP3="${LSOF_INCLUDE}/$LSOF_TMP2" LSOF_TMP4=0 else if test -d ${NETBSD_SYS}/$LSOF_TMP2 # { then LSOF_TMP3="${NETBSD_SYS}/$LSOF_TMP2" LSOF_TMP4=1 else LSOF_TMP3="" fi # } fi # } if test "X$LSOF_TMP3" != "X" # { then LSOF_CFGF="$LSOF_CFGF -DHAS9660FS=1" if test $LSOF_TMP1 -eq 0 -a $LSOF_TMP4 -eq 1 # { then LSOF_TMP1=1 fi # } else LSOF_TMP2="fs/cd9660" if test -d ${LSOF_INCLUDE}/$LSOF_TMP2 # { then LSOF_TMP3="${LSOF_INCLUDE}/$LSOF_TMP2" LSOF_TMP4=0 else if test -d ${NETBSD_SYS}/$LSOF_TMP2 # { then LSOF_TMP3="${NETBSD_SYS}/$LSOF_TMP2" LSOF_TMP4=1 else LSOF_TMP3="" fi # } fi # } if test "X$LSOF_TMP3" != "X" # { then LSOF_CFGF="$LSOF_CFGF -DHAS9660FS=1" if test $LSOF_TMP1 -eq 0 -a $LSOF_TMP4 -eq 1 # { then LSOF_TMP1=1 fi # } fi # } fi # } LSOF_TMP2="msdosfs" if test -d ${LSOF_INCLUDE}/$LSOF_TMP2 # { then LSOF_TMP3="${LSOF_INCLUDE}/$LSOF_TMP2" LSOF_TMP4=0 else if test -d ${NETBSD_SYS}/$LSOF_TMP2 # { then LSOF_TMP3="${NETBSD_SYS}/$LSOF_TMP2" LSOF_TMP4=1 else LSOF_TMP3="" fi # } fi # } if test "X$LSOF_TMP3" != "X" # { then LSOF_CFGF="$LSOF_CFGF -DHASMSDOSFS=1" if test $LSOF_TMP1 -eq 0 -a $LSOF_TMP4 -eq 1 # { then LSOF_TMP1=1 fi # } else LSOF_TMP2="fs/msdosfs" if test -d ${LSOF_INCLUDE}/$LSOF_TMP2 # { then LSOF_TMP3="${LSOF_INCLUDE}/$LSOF_TMP2" LSOF_TMP4=0 else if test -d ${NETBSD_SYS}/$LSOF_TMP2 # { then LSOF_TMP3="${NETBSD_SYS}/$LSOF_TMP2" LSOF_TMP4=1 else LSOF_TMP3="" fi # } fi # } if test "X$LSOF_TMP3" != "X" # { then LSOF_CFGF="$LSOF_CFGF -DHASMSDOSFS=2" if test $LSOF_TMP1 -eq 0 -a $LSOF_TMP4 -eq 1 # { then LSOF_TMP1=1 fi # } fi # } fi # } LSOF_TMP2="miscfs/kernfs/kernfs.h" if test -r ${LSOF_INCLUDE}/$LSOF_TMP2 # { then LSOF_TMP3="${LSOF_INCLUDE}/$LSOF_TMP2" LSOF_TMP4=0 else if test -r ${NETBSD_SYS}/$LSOF_TMP2 # { then LSOF_TMP3="${NETBSD_SYS}/$LSOF_TMP2" LSOF_TMP4=1 else LSOF_TMP3="" fi # } fi # } if test "X$LSOF_TMP3" != "X" # { then grep -q "kt_name;" $LSOF_TMP3 if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASKERNFS" if test $LSOF_TMP1 -eq 0 -a $LSOF_TMP4 -eq 1 # { then LSOF_TMP1=1 fi # } grep -q "*kfs_kt;" $LSOF_TMP3 if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASKERNFS_KFS_KT" fi # } fi # } fi # } LSOF_TMP2="sys/namei.h" if test -r ${LSOF_INCLUDE}/$LSOF_TMP2 # { then LSOF_TMP3="${LSOF_INCLUDE}/$LSOF_TMP2" LSOF_TMP4=0 else if test -r ${NETBSD_SYS}/$LSOF_TMP2 # { then LSOF_TMP3="${NETBSD_SYS}/$LSOF_TMP2" LSOF_TMP4=1 else LSOF_TMP3="" fi # } fi # } if test "X$LSOF_TMP3" != "X" # { then grep -q nc_vpid $LSOF_TMP3 if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASNCVPID" if test $LSOF_TMP1 -eq 0 -a $LSOF_TMP4 -eq 1 # { then LSOF_TMP1=1 fi # } fi # } fi # } LSOF_TMP2="ufs/ufs/inode.h" if test -r ${LSOF_INCLUDE}/$LSOF_TMP2 # { then LSOF_TMP3="${LSOF_INCLUDE}/$LSOF_TMP2" LSOF_TMP4=0 else if test -r ${NETBSD_SYS}/$LSOF_TMP2 # { then LSOF_TMP3="${NETBSD_SYS}/$LSOF_TMP2" LSOF_TMP4=1 else LSOF_TMP3="" fi # } fi # } if test "X$LSOF_TMP3" != "X" # { then grep -q i_ffs_size $LSOF_TMP3 if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASI_FFS" if test $LSOF_TMP1 -eq 0 -a $LSOF_TMP4 -eq 1 # { then LSOF_TMP1=1 fi # } else grep -q i_ffs1_size $LSOF_TMP3 if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASI_FFS1" if test $LSOF_TMP1 -eq 0 -a $LSOF_TMP4 -eq 1 # { then LSOF_TMP1=1 fi # } fi # } fi # } grep -q i_ffs_effnlink $LSOF_TMP3 if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASEFFNLINK=i_ffs_effnlink" if test $LSOF_TMP1 -eq 0 -a $LSOF_TMP4 -eq 1 # { then LSOF_TMP1=1 fi # } fi # } fi # } LSOF_TMP2="sys/vnode.h" LSOF_NBSD_PTYFS=0 if test -r ${LSOF_INCLUDE}/$LSOF_TMP2 # { then LSOF_TMP3="${LSOF_INCLUDE}/$LSOF_TMP2" LSOF_TMP4=0 else if test -r ${NETBSD_SYS}/$LSOF_TMP2 # { then LSOF_TMP3="${NETBSD_SYS}/$LSOF_TMP2" LSOF_TMP4=1 else LSOF_TMP3="" fi # } fi # } if test "XLSOF_TMP3" != "X" # { then grep -q VT_EXT2FS $LSOF_TMP3 if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASEXT2FS" if test $LSOF_TMP1 -eq 0 -a $LSOF_TMP4 -eq 1 # { then LSOF_TMP1=1 fi # } LSOF_TMP2="ufs/ufs/inode.h" if test -r ${LSOF_INCLUDE}/$LSOF_TMP2 # { then LSOF_TMP5="${LSOF_INCLUDE}/$LSOF_TMP2" LSOF_TMP6=0 else if test -r ${NETBSD_SYS}/$LSOF_TMP2 # { then LSOF_TMP5="${NETBSD_SYS}/$LSOF_TMP2" LSOF_TMP6=1 else LSOF_TMP5="" fi # } fi # } if test "X$LSOF_TMP5" != "X" # { then grep -q "*e2fs_din" $LSOF_TMP5 if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASI_E2FS_PTR" if test $LSOF_TMP1 -eq 0 -a $LSOF_TMP4 -eq 1 # { then LSOF_TMP1=$LSOF_TMP6 fi # } fi # } fi # } fi # } grep -q VT_LFS $LSOF_TMP3 if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASLFS" if test $LSOF_TMP1 -eq 0 -a $LSOF_TMP4 -eq 1 # { then LSOF_TMP1=1 fi # } fi # } grep -q VT_PTYFS $LSOF_TMP3 if test $? -eq 0 # { then LSOF_TMP2="fs/ptyfs/ptyfs.h" if test -r ${LSOF_INCLUDE}/$LSOF_TMP2 # { then LSOF_CFGF="$LSOF_CFGF -DHASPTYFS" else if test -r ${NETBSD_SYS}/$LSOF_TMP2 # { then if test $NETBSD_SYS != $LSOF_INCLUDE # { then LSOF_CFGF="$LSOF_CFGF -DHASPTYFS" LSOF_NBSD_PTYFS=1 fi # } fi # } fi # } fi # } if test "X$NETBSD_UVM" = "X" # { then grep -q UVM $LSOF_TMP3 if test $? -ne 0 # { then egrep -q "v_uvm;|v_uobj;" $LSOF_TMP3 if test $? -eq 0 # { then NETBSD_UVM="Y" fi # } fi # } fi # } fi # } LSOF_TMP2="nfs/nfsnode.h" if test -r ${LSOF_INCLUDE}/$LSOF_TMP2 # { then LSOF_TMP3="${LSOF_INCLUDE}/$LSOF_TMP2" LSOF_TMP4=0 else if test -r ${NETBSD_SYS}/$LSOF_TMP2 # { then LSOF_TMP3="${NETBSD_SYS}/$LSOF_TMP2" LSOF_TMP4=1 else LSOF_TMP3="" fi # } fi # } if test "X$LSOF_TMP3" != "X" # { then grep -q "*n_vattr" $LSOF_TMP3 if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASNFSVATTRP" if test $LSOF_TMP1 -eq 0 -a $LSOF_TMP4 -eq 1 # { then LSOF_TMP1=1 fi # } fi # } fi # } LSOF_TMP2="sys/lockf.h" if test -r ${LSOF_INCLUDE}/$LSOF_TMP2 # { then LSOF_TMP3="${LSOF_INCLUDE}/$LSOF_TMP2" LSOF_TMP4=0 else if test -r ${NETBSD_SYS}/$LSOF_TMP2 # { then LSOF_TMP3="${NETBSD_SYS}/$LSOF_TMP2" LSOF_TMP4=1 else LSOF_TMP3="" fi # } fi # } if test "X$LSOF_TMP3" != "X" # { then grep -q vop_advlock_args $LSOF_TMP3 if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHAS_ADVLOCK_ARGS" if test $LSOF_TMP1 -eq 0 -a $LSOF_TMP4 -eq 1 # { then LSOF_TMP1=1 fi # } fi # } grep -q lf_lwp $LSOF_TMP3 if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHAS_LF_LWP" if test $LSOF_TMP1 -eq 0 -a $LSOF_TMP4 -eq 1 # { then LSOF_TMP1=1 fi # } fi # } fi # } LSOF_TMP2="sys/lwp.h" if test -r ${LSOF_INCLUDE}/$LSOF_TMP2 # { then LSOF_TMP3="${LSOF_INCLUDE}/$LSOF_TMP2" LSOF_TMP4=0 else if test -r ${NETBSD_SYS}/$LSOF_TMP2 # { then LSOF_TMP3="${NETBSD_SYS}/$LSOF_TMP2" LSOF_TMP4=1 else LSOF_TMP3="" fi # } fi # } if test "X$LSOF_TMP3" != "X" # { then LSOF_CFGF="$LSOF_CFGF -DHAS_LWP_H" if test $LSOF_TMP1 -eq 0 -a $LSOF_TMP4 -eq 1 # { then LSOF_TMP1=1 fi # } fi # } LSOF_TMP2="sys/filedesc.h" if test -r ${LSOF_INCLUDE}/$LSOF_TMP2 # { then LSOF_TMP3="${LSOF_INCLUDE}/$LSOF_TMP2" LSOF_TMP4=0 else if test -r ${NETBSD_SYS}/$LSOF_TMP2 # { then LSOF_TMP3="${NETBSD_SYS}/$LSOF_TMP2" LSOF_TMP4=1 else LSOF_TMP3="" fi # } fi # } if test "X$LSOF_TMP3" != "X" # { then grep -q "^struct cwdinfo {" $LSOF_TMP3 if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASCWDINFO" if test $LSOF_TMP1 -eq 0 -a $LSOF_TMP4 -eq 1 # { then LSOF_TMP1=1 fi # } fi # } fi # } LSOF_TMP2="sys/pipe.h" if test -r ${LSOF_INCLUDE}/$LSOF_TMP2 # { then LSOF_TMP3="${LSOF_INCLUDE}/$LSOF_TMP2" LSOF_TMP4=0 else if test -r ${NETBSD_SYS}/$LSOF_TMP2 # { then LSOF_TMP3="${NETBSD_SYS}/$LSOF_TMP2" LSOF_TMP4=1 else LSOF_TMP3="" fi # } fi # } if test "X$LSOF_TMP3" != "X" # { then LSOF_CFGF="$LSOF_CFGF -DHAS_SYS_PIPEH" if test $LSOF_TMP1 -eq 0 -a $LSOF_TMP4 -eq 1 # { then LSOF_TMP1=1 fi # } fi # } if test -r ${LSOF_INCLUDE}/sys/statvfs.h # { then grep -q '^struct statvfs {' ${LSOF_INCLUDE}/sys/statvfs.h if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASSTATVFS" fi # } fi # } # Here end the dual NetBSD tests for header files in $LSOF_INCLUDE or # NETBSD_SYS. # # After this LSOF_TMP1 may be reused. if test $LSOF_TMP1 -eq 1 # { then LSOF_DINC="-I$LSOF_INCLUDE -I$NETBSD_SYS" fi # } # Build special header files, as required. rm -rf dialects/n+obsd/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" if test -d ${LSOF_INCLUDE}/uvm # { then LSOF_CFGF="$LSOF_CFGF -DHAS_UVM_INCL" fi # } fi # } LSOF_TMP2="sys/mount.h" if test -r ${LSOF_INCLUDE}/$LSOF_TMP2 # { then LSOF_TMP3="${LSOF_INCLUDE}/$LSOF_TMP2" else if test -r ${NETBSD_SYS}/$LSOF_TMP2 # { then LSOF_TMP3="${NETBSD_SYS}/$LSOF_TMP2" else LSOF_TMP3="" fi # } fi # } if test "X$LSOF_TMP3" != "X" # { then # Build a local NetBSD netexport.h header file for possible use by # . 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 " >> $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 $LSOF_NBSD_BUFQH -eq 1 # { then # Make a local copy of $NETBSD_SYS/sys/bufq.h. if test ! -d dialects/n+obsd/include # { then mkdir dialects/n+obsd/include fi # } if test ! -d dialects/n+obsd/include/sys # { then mkdir dialects/n+obsd/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 if test $? -ne 0 # { then LSOF_CFGF="$LSOF_CFGF -I`pwd`/dialects/n+obsd/include" fi # } fi # } if test $LSOF_NBSD_PTYFS -eq 1 # { then # Make a local copy of $NETBSD_SYS/sys/fs/ptyfs/. if test ! -d dialects/n+obsd/include # { then mkdir dialects/n+obsd/include fi # } if test ! -d dialects/n+obsd/include/fs # { then mkdir dialects/n+obsd/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 if test $? -ne 0 # { then LSOF_CFGF="$LSOF_CFGF -I`pwd`/dialects/n+obsd/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" # { then # If the NeXSTEP version isn't predefined, determine it. 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 # { 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'` fi # } 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 # { 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 # } fi # } ;; # Configure for OpenBSD. (OpenBSD uses NetBSD dialect sources and version # numbering. openbsd) if test "X$LSOF_CC" = "X" # { then LSOF_CC=cc LSOF_CCV=`$LSOF_CC -v 2>&1 | sed -n 's/.*version \(.*\)/\1/p'` fi # } if test "X$LSOF_VSTR" = "X" # { then LSOF_VSTR=`uname -r` fi # } if test "X$LSOF_VERS" = "X" # { then # If the OpenBSD version isn't pre-defined, determine it. case $LSOF_VSTR in # { 1*) LSOF_VERS=1020 echo "!!!WARNING!!! Unsupported OpenBSD 1.x version: $LSOF_VSTR" echo "!!!WARNING!!! Configuring for OpenBSD 1.2" ;; 2.5*) LSOF_VERS=2050 ;; 2.6*) LSOF_VERS=2060 ;; 2.7*) LSOF_TSTBIGF=" " LSOF_VERS=2070 ;; 2.8*) LSOF_TSTBIGF=" " LSOF_VERS=2080 ;; 2.9*) LSOF_TSTBIGF=" " LSOF_VERS=2090 ;; 2*) LSOF_TSTBIGF=" " LSOF_VERS=2090 echo "!!!WARNING!!! Unsupported OpenBSD 2.x version: $LSOF_VSTR" echo "!!!WARNING!!! Configuring for OpenBSD 2.9" ;; 3.0*) LSOF_TSTBIGF=" " LSOF_VERS=3000 ;; 3.1*) LSOF_TSTBIGF=" " LSOF_VERS=3010 ;; 3.2*) LSOF_TSTBIGF=" " LSOF_VERS=3020 ;; 3.3*) LSOF_TSTBIGF=" " LSOF_VERS=3030 ;; 3.4*) LSOF_TSTBIGF=" " LSOF_VERS=3040 ;; 3.5*) LSOF_TSTBIGF=" " LSOF_VERS=3050 ;; 3.6*) LSOF_TSTBIGF=" " LSOF_VERS=3060 ;; 3.7*) LSOF_TSTBIGF=" " LSOF_VERS=3070 ;; 3.8*) LSOF_TSTBIGF=" " LSOF_VERS=3080 ;; 3.9*) LSOF_TSTBIGF=" " LSOF_VERS=3090 ;; 3*) LSOF_TSTBIGF=" " LSOF_VERS=3090 echo "!!!WARNING!!! Unsupported OpenBSD 3.x version: $LSOF_VSTR" echo "!!!WARNING!!! Configuring for OpenBSD 3.9" ;; *) echo "Unknown OpenBSD release: $LSOF_VSTR" echo Assuming OpenBSD 3.9 LSOF_VERS=3090 ;; esac # } fi # } # 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) ;; *) echo "Unknown OpenBSD version: $LSOF_VERS" rm -f $LSOF_HLP 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 # . 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 " >> $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 ;; # Configure for SCO OpenServer. osr|osrgcc|sco|scogcc) if test "X$LSOF_RANLIB_SUP" = "X" # { then LSOF_RANLIB="" fi # } if test "X$OSR_CFGF" != "X" # { then # Adopt LSOF_CFGF from OSR_CFGF in environment. LSOF_CFGF=$OSR_CFGF fi # } if test "X$OSR_CFGL" != "X" # { then # Adopt LSOF_CFGL from OSR_CFGL in environment. LSOF_CFGL=$OSR_CFGL fi # } # Evaluate compiler specification. if test "X$LSOF_CC" = "X" # { then if test "X$LSOF_TGT" = "Xosr" -o "X$LSOF_TGT" = "Xsco" # { then LSOF_CC=cc LSOF_TMP1=1 else LSOF_CC=gcc LSOF_CCV=`$LSOF_CC -v 2>&1 | sed -n 's/.*version \(.*\)/\1/p'` LSOF_TMP1=2 fi # } else LSOF_TMP1=0 fi # } LSOF_TGT="osr" # Determine version. if test "X$LSOF_VSTR" = "X" # { then LSOF_VSTR="`LANG=C_C.C /bin/uname -X 2>/dev/null | grep Release | sed 's/Release = \(.*\)/\1/'`" fi # } if test "X$LSOF_VERS" = "X" # { then # If the SCO OpenServer release version isn't predefined, determine it. case $LSOF_VSTR in # { 3.2v2.0) LSOF_VERS="20" ;; 3.2v2.1) LSOF_VERS="21" ;; 3.2v4.0) LSOF_VERS="40" ;; 3.2v4.1) LSOF_VERS="41" ;; 3.2v4.2) LSOF_VERS="42" ;; 3.2v5.*) LSOF_TSTLFLG="-lsocket" LSOF_VERS="`echo $LSOF_VSTR | sed 's/3\.2v//; s/\.//g'`" ;; *) echo Unknown SCO OpenServer release: $LSOF_VSTR echo Assuming 3.2.0 or 3.2.1 LSOF_VERS="0" ;; esac # } fi # } # Do SCO OpenServer specific stuff. case $LSOF_VERS in # { 0) if test $LSOF_TMP1 -eq 1 # { then LSOF_CFGF="$LSOF_CFGF -nointl" LSOF_DEBUG="-Ox" fi # } LSOF_CFGL="$LSOF_CFGL -lrpc -lsocket -lc_s" LSOF_MKC="cp" ;; 20) if test $LSOF_TMP1 -eq 1 # { then LSOF_DEBUG="-Ox" fi # } LSOF_CFGL="$LSOF_CFGL -lrpc -lsocket -lc_s" LSOF_MKC="cp" ;; 21) if test $LSOF_TMP1 -eq 1 # { then LSOF_CFGF="$LSOF_CFGF -nointl" LSOF_DEBUG="-Ox" fi # } LSOF_CFGL="$LSOF_CFGL -lrpc -lsocket -lc_s" LSOF_MKC="cp" ;; 40) if test $LSOF_TMP1 -eq 1 # { then LSOF_CFGF="$LSOF_CFGF -nointl" LSOF_DEBUG="-Ox" fi # } LSOF_CFGL="$LSOF_CFGL -lrpc -lsocket -lc_s" ;; 41) if test $LSOF_TMP1 -eq 1 # { then LSOF_CFGF="$LSOF_CFGF -nointl" LSOF_DEBUG="-Ox" fi # } LSOF_CFGL="$LSOF_CFGL -lrpc -lsocket -lc_s" ;; 42) if test $LSOF_TMP1 -eq 1 # { then LSOF_CFGF="$LSOF_CFGF -nointl" LSOF_DEBUG="-Ox" fi # } LSOF_CFGL="$LSOF_CFGL -lrpc -lsocket -lc_s" ;; 5*) if test $LSOF_TMP1 -eq 1 # { then LSOF_CFGF="$LSOF_CFGF -belf" LSOF_DEBUG="-O3 -Kspace" fi # } LSOF_CFGL="$LSOF_CFGL -lsocket" ;; *) echo "Unsupported SCO OpenServer release: $LSOF_VERS" rm -f $LSOF_HLP exit 1 ;; esac # } LSOF_CFGF="$LSOF_CFGF -DOSRV=$LSOF_VERS" if test "X$OSR_STATLSTAT" = "X" # { then echo "Testing libc.a for statlstat" /bin/nm /lib/libc.a | grep statlstat > /dev/null 2>&1 if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHAS_STATLSTAT" fi # } else if test "X$OSR_STATLSTAT" = "XY" -o "X$OSR_STATLSTAT" = "Xy" # { then LSOF_CFGF="$LSOF_CFGF -DHAS_STATLSTAT" fi # } fi # } if test -r ${LSOF_INCLUDE}/sys/fs/nfs/rnode.h # { then LSOF_CFGF="$LSOF_CFGF -DHAS_NFS" fi # } if test ! -r ${LSOF_INCLUDE}/netdb.h # { then LSOF_DINC="$LSOF_DINC -I`pwd`/dialects/osr/include" fi # } LSOF_DIALECT_DIR=osr ;; # Configure for Sun Solaris, SunPro C and gcc. solaris|solariscc) if test "X$LSOF_RANLIB_SUP" = "X" # { then LSOF_RANLIB="" fi # } if test "X$LSOF_CC" = "X" # { then if test "X$LSOF_TGT" = "Xsolariscc" # { then if test "X$SOLARIS_CCDIR" = "X" # { then SOLARIS_CCDIR="/opt/SUNWspro/bin" fi # } if test -x ${SOLARIS_CCDIR}/cc # { then LSOF_CC=${SOLARIS_CCDIR}/cc else if test -x /opt/SunStudioExpress/bin/cc # { then LSOF_CC=/opt/SunStudioExpress/bin/cc else echo "WARNING: no cc in ${SOLARIS_CCDIR}; using cc without path." LSOF_CC=cc fi # } fi # } LSOF_CCV=`$LSOF_CC -V 2>&1 | sed -n 's/^cc: \(.*\)/\1/p'` else LSOF_CC=gcc LSOF_CCV=`$LSOF_CC -v 2>&1 | sed -n 's/.*version \(.*\)/\1/p'` fi # } fi # } LSOF_TGT="solaris" if test "X$LSOF_VSTR" = "X" # { then LSOF_VSTR=`uname -r` fi # } if test "X$LSOF_VERS" = "X" # { then # If the Solaris version isn't predefined, determine it. case $LSOF_VSTR in # { 5.[0-2]) LSOF_VERS="20300" ;; 5.3) LSOF_VERS="20300" ;; 5.4) LSOF_VERS="20400" ;; 5.5) LSOF_VERS="20500" ;; 5.5.1) LSOF_VERS="20501" ;; 5.6*) LSOF_TSTLFLG="-lsocket -lnsl" LSOF_VERS="20600" ;; 5.7*) LSOF_TSTBIGF=" " LSOF_TSTLFLG="-lsocket -lnsl" LSOF_VERS="70000" ;; 5.8*) LSOF_TSTBIGF=" " LSOF_TSTLFLG="-lsocket -lnsl" LSOF_VERS="80000" ;; 5.9*) LSOF_TSTBIGF=" " LSOF_TSTLFLG="-lsocket -lnsl" LSOF_VERS="90000" ;; 5.10*) LSOF_TSTBIGF=" " LSOF_TSTLFLG="-lsocket -lnsl" LSOF_VERS="100000" ;; 5.11*) LSOF_TSTBIGF=" " LSOF_TSTLFLG="-lsocket -lnsl" LSOF_VERS="110000" ;; *) echo Unknown Solaris version: $LSOF_VSTR rm -f $LSOF_HLP exit 1 esac # } fi # } # Clear LSOF_UNSUP message for selected Solaris versions. case $LSOF_VERS in # { 90000|100000|110000) LSOF_UNSUP="" ;; esac # } # Do Solaris version-specific stuff. case $LSOF_VERS in # { 20300) # Solaris patch 101318-32 creates a longer kernel tcp_s structure, # and 101318-45 changes the way the vnode's v_filocks member is # handled. The following code creates a symbol definition for # patch 101318 whose value is the patch level. No symbol is defined # if the patch level is not greater than zero. if test "X$SOLARIS_23P101318" = "X" # { then LSOF_PL=`grep -h SUNW_PATCHID=101318 /var/sadm/pkg/SUNWcar*/pkginfo | sed 's/.*-//' | sort -u | tail -1` if test "X$LSOF_PL" = "X" # { then LSOF_PL=0 fi # } else LSOF_PL=$SOLARIS_23P101318 fi # } if test $LSOF_PL -gt 0 # { then LSOF_CFGF="$LSOF_CFGF -DP101318=$LSOF_PL" fi # } ;; 20400) if test "X$SOLARIS_24P101945" = "X" # { then LSOF_PL=`grep -h SUNW_PATCHID=101945 /var/sadm/pkg/SUNWcar*/pkginfo | sed 's/.*-//' | sort -u | tail -1` if test "X$LSOF_PL" = "X" # { then LSOF_PL=0 fi # } else LSOF_PL=$SOLARIS_24P101945 fi # } if test $LSOF_PL -ge 32 # { then if test "X$SOLARIS_24P102303" = "X" # { then LSOF_PL=`grep -h SUNW_PATCHID=102303 /var/sadm/pkg/SUNWhea*/pkginfo | sed 's/.*-//' | sort -u | tail -1` if test "X$LSOF_PL" = "X" # { then LSOF_PL=0 fi # } else LSOF_PL=$SOLARIS_24P102303 fi # } if test $LSOF_PL -ge 2 # { then echo "WARNING: your Solaris 2.4 system appears to have patches 101945-32 and 102303-2" echo " installed. This probably means the NUM_*_VECTORS definitions in" echo " don't match the ones used to build your kernel. Consult" echo " the Sun Problems section of the 00FAQ file of the lsof distribution" echo " for more information on how to work around the problem." fi # } fi # } ;; 20500|20501) ;; 20600|70000|80000|90000|100000|110000) if test "X$SOLARIS_26PR_GWINDOWS" = "X" # { then rm -f ${LSOF_TMPC}.* echo "#define _KMEMUSER" > ${LSOF_TMPC}.c echo "#include " >> ${LSOF_TMPC}.c echo "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 if test $? -eq 0 # { then $LSOF_CC ${LSOF_TMPC}.c -o ${LSOF_TMPC}.x > /dev/null 2>&1 else $LSOF_CC ${LSOF_TMPC}.c -I$LSOF_INCLUDE -o ${LSOF_TMPC}.x > /dev/null 2>&1 fi # } if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASPR_GWINDOWS" fi # } else if test "X$SOLARIS_26PR_GWINDOWS" = "XY" -o "X$SOLARIS_26PR_GWINDOWS" = "Xy" # { then LSOF_CFGF="$LSOF_CFGF -DHASPR_GWINDOWS" fi # } fi # } if test "X$SOLARIS_26PR_LDT" = "X" # { then rm -f ${LSOF_TMPC}.* echo "#define _KMEMUSER" > ${LSOF_TMPC}.c echo "#include " >> ${LSOF_TMPC}.c echo "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 if test $? -eq 0 # { then $LSOF_CC ${LSOF_TMPC}.c -o ${LSOF_TMPC}.x > /dev/null 2>&1 else $LSOF_CC ${LSOF_TMPC}.c -I$LSOF_INCLUDE -o ${LSOF_TMPC}.x > /dev/null 2>&1 fi # } if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASPR_LDT" fi # } rm -f ${LSOF_TMPC}.* else if test "X$SOLARIS_26PR_LDT" = "XY" -o "X$SOLARIS_26PR_LDT" = "Xy" # { then LSOF_CFGF="$LSOF_CFGF -DHASPR_LDT" fi # } fi # } if test $LSOF_VERS -ge 70000 # { then # Do tests for Solaris 7 and above. if test "X$SOLARIS_KERNBITS" = "X" # { then SOLARIS_KERNBITS=`/bin/isainfo -kv` fi # } if test "X$SOLARIS_INSTR" = "X" # { then SOLARIS_INSTR=`/bin/isainfo -k` fi #} echo $SOLARIS_KERNBITS | grep 64 > /dev/null if test $? -eq 0 # { then echo $LSOF_CC | grep gcc > /dev/null if test $? -eq 0 # { then # Test gcc for 64 bit support. echo "Testing $LSOF_CC for 64 bit support" rm -f ${LSOF_TMPC}.* echo "main(){}" > ${LSOF_TMPC}.c LSOF_TMP1="" # First try gcc's -m64 option -- it's the most current possibility. $LSOF_CC ${LSOF_TMPC}.c -m64 -o ${LSOF_TMPC}.x > /dev/null 2>&1 if test $? -eq 0 # { then /bin/file ${LSOF_TMPC}.x | /bin/grep 64 > /dev/null if test $? -eq 0 # { then LSOF_TMP1="-m64" fi # } fi # } rm -f ${LSOF_TMPC}.* if test "X$LSOF_TMP1" = "X" # { then # Try using the older -mcpu=v9 option with gcc instead of -m64. echo "main(){}" > ${LSOF_TMPC}.c $LSOF_CC ${LSOF_TMPC}.c -mcpu=v9 -o ${LSOF_TMPC}.x > /dev/null 2>&1 if test $? -eq 0 # { then /bin/file ${LSOF_TMPC}.x | /bin/grep 64 > /dev/null if test $? -eq 0 # { then LSOF_TMP1="-mcpu=v9" fi # } fi # } rm -f ${LSOF_TMPC}.* fi # } if test "X$LSOF_TMP1" = "X" # { then echo "" echo "!!!WARNING!!!=========!!!WARNING!!!=========!!!WARNING!!!" echo "! !" echo "! LSOF NEEDS TO BE CONFIGURED FOR A 64 BIT KERNEL, BUT !" echo "! THIS GCC DOESN'T SUPPORT THE BUILDING OF 64 BIT !" echo "! SOLARIS EXECUTABLES. LSOF WILL BE CONFIGURED FOR A !" echo "! 32 BIT KERNEL. !" echo "! !" echo "!!!WARNING!!!=========!!!WARNING!!!=========!!!WARNING!!!" echo "" else echo "" echo "*********************************" echo "* Configuring for 64 bit kernel *" echo "*********************************" echo "" LSOF_CFGF="$LSOF_CFGF $LSOF_TMP1" LSOF_CINFO="64 bit kernel" LSOF_TSTK64=1 fi # } else # Test Sun compiler for 64 bit support. case $SOLARIS_INSTR in # { amd64*) LSOF_TMP1="amd64" LSOF_TMP2="amd64" ;; sparc*) LSOF_TMP1="v9" LSOF_TMP2="sparcv9" ;; *) LSOF_TMP1="" ;; esac # } if test "X$LSOF_TMP1" != "X" # { then echo "Testing $LSOF_CC for 64 bit $LSOF_TMP2 support" rm -f ${LSOF_TMPC}.* LSOF_TMP3="-xarch=$LSOF_TMP1" echo "main(){}" > ${LSOF_TMPC}.c LSOF_TMP4=`$LSOF_CC ${LSOF_TMPC}.c $LSOF_TMP3 -o ${LSOF_TMPC}.x 2>&1` if test $? -eq 0 # { then /bin/file ${LSOF_TMPC}.x | /bin/grep 64 > /dev/null if test $? -ne 0 # { then LSOF_TMP3="" else echo "X$LSOF_TMP4" | grep "use -m64" > /dev/null 2>&1 if test $? -eq 0 # { then LSOF_TMP3=-m64 fi # } fi # } fi # } rm -f ${LSOF_TMPC}.* else LSOF_TMP3="" fi # } if test "X$LSOF_TMP3" != "X" # { then echo "" echo "*********************************" echo "* Configuring for 64 bit kernel *" echo "*********************************" echo "" LSOF_CFGF="$LSOF_CFGF $LSOF_TMP3" LSOF_CINFO="64 bit kernel" LSOF_TSTK64=1 else echo "" echo "!!!WARNING!!!==========!!!WARNING!!!==========!!!WARNING!!!" echo "!" echo "! LSOF NEEDS TO BE CONFIGURED FOR A 64 BIT KERNEL, BUT" echo "! THE VERSION OF SUN C AVAILABLE DOESN'T SUPPORT THE" echo "! \"$LSOF_TMP2\" INSTRUCTION SET." echo "!" echo "! LSOF WILL BE CONFIGURED FOR A 32 BIT KERNEL." echo "!" echo "!!!WARNING!!!==========!!!WARNING!!!==========!!!WARNING!!!" echo "" fi # } fi # } else echo "" echo "*********************************" echo "* Configuring for 32 bit kernel *" echo "*********************************" echo "" LSOF_CINFO="32 bit kernel" fi # } fi # } # Do tests specific to Solaris 8 and above. if test $LSOF_VERS -ge 80000 # { then if test -r ${LSOF_INCLUDE}/netinet/ip6.h # { then LSOF_CFGF="$LSOF_CFGF -DHASIPv6" fi # } fi # } # Do tests specific to Solaris 9 and above. if test $LSOF_VERS -ge 90000 # { then if test -r ${LSOF_INCLUDE}/sys/socketvar.h # { then grep soua_vp ${LSOF_INCLUDE}/sys/socketvar.h > /dev/null 2>&1 if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASSOUXSOUA" fi # } fi # } if test $LSOF_VERS -lt 110000 # { then # Do tests specific to Solaris 9 and 10. if test -r ${LSOF_INCLUDE}/sys/lgrp_user.h # { then if test -r ${LSOF_INCLUDE}/sys/lgrp.h # { then grep lgrp_root ${LSOF_INCLUDE}/sys/lgrp_user.h > /dev/null 2>&1 if test $? -eq 0 # { then grep lgrp_root ${LSOF_INCLUDE}/sys/lgrp.h > /dev/null 2>&1 if test $? -eq 0 then LSOF_CFGF="$LSOF_CFGF -DHAS_LGRP_ROOT_CONFLICT" fi # } fi # } fi # } fi # } fi # } fi # } # Do tests specific to Solaris 10 and above. if test $LSOF_VERS -eq 100000 # { then if test -r ${LSOF_INCLUDE}/sys/socket_proto.h # { then LSOF_CFGF="$LSOF_CFGF -DHAS_SOCKET_PROTO_H" fi # } fi # } if test $LSOF_VERS -ge 100000 # { then if test -r ${LSOF_INCLUDE}/inet/ipclassifier.h # { then LSOF_CFGF="$LSOF_CFGF -DHAS_IPCLASSIFIER_H" grep conn_ixa ${LSOF_INCLUDE}/inet/ipclassifier.h > /dev/null 2>&1 if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHAS_CONN_NEW" fi #} fi # } if test -r ${LSOF_INCLUDE}/sys/cred_impl.h # { then LSOF_CFGF="$LSOF_CFGF -DHAS_CRED_IMPL_H" # DEBUG -- Begin temporary hack for Solaris 10, build s10_44. grep "c2/audit.h" ${LSOF_INCLUDE}/sys/cred_impl.h > /dev/null if test $? -eq 0 # { then rm -rf `pwd`/dialects/sun/solaris10 mkdir `pwd`/dialects/sun/solaris10 mkdir `pwd`/dialects/sun/solaris10/c2 touch `pwd`/dialects/sun/solaris10/c2/audit.h LSOF_CFGF="$LSOF_CFGF -I`pwd`/dialects/sun/solaris10" fi # } # DEBUG -- End temporary hack for Solaris 10, build s10_44. fi # } if test -r ${LSOF_INCLUDE}/sys/vnode.h # { then grep v_path ${LSOF_INCLUDE}/sys/vnode.h > /dev/null 2>&1 if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHAS_V_PATH" LSOF_TSTVPATH=1 fi # } fi # } if test -r ${LSOF_INCLUDE}/sys/fs/pc_fs.h # { then grep pc_direntpersec ${LSOF_INCLUDE}/sys/fs/pc_fs.h > /dev/null 2>&1 if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHAS_PC_DIRENTPERSEC" fi # } fi # } fi # } if test -r ${LSOF_INCLUDE}/sys/zone.h # { then LSOF_CFGF="$LSOF_CFGF -DHASZONES" fi # } # Check for Solaris 10 or higher CTF library and things that depend # on it. if test -r ${LSOF_INCLUDE}/libctf.h # { then LSOF_CTFH=1 fi # } if test -r ${LSOF_INCLUDE}/sys/fs/zfs.h # { then if test $LSOF_CTFH -eq 1 # { then LSOF_CFGF="$LSOF_CFGF -DHAS_ZFS" LSOF_CTFL=1 else echo "WARNING: ZFS support not enabled; libctf.h missing." fi # } fi # } if test $LSOF_VERS -ge 110000 # { then # Do things specific to Solaris 11 and above. if test $LSOF_CTFH -eq 1 # { then LSOF_CTFL=1 else echo "WARNING: socket support not enabled; libctf.h missing." fi # } rm -rf ./solaris11 mkdir ./solaris11 mkdir ./solaris11/sys touch ./solaris11/sys/extdirent.h echo "./solaris11/sys/extdirent.h created" LSOF_CFGF="$LSOF_CFGF -I`pwd`/solaris11" if test -r ${LSOF_INCLUDE}/sys/mutex.h # { then # Check 'for pad_mutex_t;'. grep 'pad_mutex_t;' ${LSOF_INCLUDE}/sys/mutex.h > /dev/null 2>&1 if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHAS_PAD_MUTEX" fi # } fi # ) fi # } # If -lctf was added to LSOF_CFGL, define HAS_LIBCTF. if test $LSOF_CTFL -eq 1 # { then LSOF_CFGF="$LSOF_CFGF -DHAS_LIBCTF" LSOF_CFGL="$LSOF_CFGL -lctf" fi # } ;; *) echo "Unsupported Solaris version: $LSOF_VERS" rm -f $LSOF_HLP exit 1 ;; esac # } LSOF_CFGF="$LSOF_CFGF -Dsolaris=$LSOF_VERS" # Test for . if test -r ${LSOF_INCLUDE}/sys/fs/cachefs_fs.h # { then LSOF_CFGF="$LSOF_CFGF -DHASCACHEFS" fi # } # Test for if test -r ${LSOF_INCLUDE}/utmpx.h # { then LSOF_CFGF="$LSOF_CFGF -DHASUTMPX" fi # } # Test for VSOCK. if test "X$SOLARIS_VSOCK" = "X" # { then rm -f ${LSOF_TMPC}.* echo "#include " > ${LSOF_TMPC}.c echo "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 if test $? -eq 0 # { then $LSOF_CC ${LSOF_TMPC}.c -o ${LSOF_TMPC}.x > /dev/null 2>&1 else $LSOF_CC ${LSOF_TMPC}.c -I$LSOF_INCLUDE -o ${LSOF_TMPC}.x > /dev/null 2>&1 fi # } if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHAS_VSOCK" fi # } rm -f ${LSOF_TMPC}.* else if test "X$SOLARIS_VSOCK" = "XY" -o "X$SOLARIS_VSOCK" = "Xy" # { then LSOF_CFGF="$LSOF_CFGF -DHAS_VSOCK" fi # } fi # } # Test for AFS. if test -r ${AFS_VICE}/etc/ThisCell # { 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 if test "X$SUN_AFSAPATHDEF" = "X" # { then ls /usr/vice/etc/modload/libafs > /dev/null 2>&1 if test $? -ne 0 # { then LSOF_TMP1=`ls /usr/vice/etc/modload/libafs* 2>/dev/null | wc -l` if test $LSOF_TMP1 -ne 0 # { then SUN_AFSAPATHDEF=`ls -t /usr/vice/etc/modload/libafs* | head -1` fi # } fi # } fi # } if test "X$SUN_AFSAPATHDEF" != "X" # { then LSOF_CFGF="$LSOF_CFGF -DAFSAPATHDEF=\\\"$SUN_AFSAPATHDEF\\\"" fi # } 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 # } fi # } # Test for VxFS. # # If the location of the VxFS header files hasn't been defined in the # environment, establish their likely locations. LSOF_TMP2=$SOLARIS_VXFSINCL if test -d /opt/VRTS/include # { then LSOF_TMP2="$LSOF_TMP2 /opt/VRTS/include" fi # } if test -d /opt/VRTSvxfs/include # { then LSOF_TMP2="$LSOF_TMP2 /opt/VRTSvxfs/include" fi # } LSOF_TMP1=0 for i in $LSOF_TMP2 # { do if test -r ${i}/vxfsutil.h # { then LSOF_TMP1=1 SOLARIS_VXFSINCL=$i break fi # } done # } if test $LSOF_TMP1 -eq 1 # { then # The VxFS header files are for VxFS version 3.4 or above. Enable VxFS # for those versions. LSOF_CFGF="$LSOF_CFGF -DHASVXFS -DHASVXFSUTIL -I$SOLARIS_VXFSINCL" # Determine which libvxfsutil.a is required -- 32 or 64 bit. LSOF_TMP2="" # assume 32 bit echo "X$LSOF_CINFO" | grep "^X64" > /dev/null 2>&1 if test $? -eq 0-a "X$SOLARIS_INSTR" != "X" # { then case $SOLARIS_INSTR in # { amd64*) LSOF_TMP2="/amd64" ;; sparcv9*) LSOF_TMP2="/sparcv9" ;; esac # } fi # } # See if the correct library has been specified and exists. if test "X$SOLARIS_VXFSLIB" = "X" # { then SOLARIS_VXFSLIB=`dirname $SOLARIS_VXFSINCL`/lib fi # } LSOF_TMP3="${SOLARIS_VXFSLIB}${LSOF_TMP2}/libvxfsutil.a" if test ! -r $LSOF_TMP3 # { then echo "!!!FATAL: no VxFS $LSOF_TMP3" exit 1 fi # } LSOF_CFGL="$LSOF_CFGL -L$SOLARIS_VXFSLIB${LSOF_TMP2} -lvxfsutil -ldl" # See if the library has the Reverse Name Lookup (RNL) function. nm $LSOF_TMP3 | grep vxfs_inotopath > /dev/null 2>&1 if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASVXFSRNL -DHASVXFSDNLC" fi # } else # See if there are VxFS header files for VxFS versions below 3.4. if test -r ${LSOF_INCLUDE}/sys/fs/vx_inode.h # { then # Define VxFS for VxFS versions below 3.4. Make additional header # file tests. LSOF_CFGF="$LSOF_CFGF -DHASVXFS" if test -r ${LSOF_INCLUDE}/sys/fs/vx_fs.h # { then LSOF_CFGF="$LSOF_CFGF -DHASVXFS_FS_H" fi # } if test -r ${LSOF_INCLUDE}/sys/fs/vx_sol.h # { then LSOF_CFGF="$LSOF_CFGF -DHASVXFS_SOL_H" fi # } if test -r ${LSOF_INCLUDE}/sys/fs/vx_machdep.h # { then LSOF_CFGF="$LSOF_CFGF -DHASVXFS_MACHDEP_H" fi # } if test -r ${LSOF_INCLUDE}/sys/fs/vx_solaris.h # { then LSOF_CFGF="$LSOF_CFGF -DHASVXFS_SOLARIS_H" grep "off32_t;" ${LSOF_INCLUDE}/sys/fs/vx_machdep.h > /dev/null if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASVXFS_OFF32_T" fi # } grep "off64_t;" ${LSOF_INCLUDE}/sys/fs/vx_solaris.h > /dev/null if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASVXFS_OFF64_T" fi # } grep "vx_u64_t;" ${LSOF_INCLUDE}/sys/fs/vx_solaris.h > /dev/null if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASVXFS_U64_T" fi # } fi # } egrep "struct[ ]vx_inode[ ]\{" ${LSOF_INCLUDE}/sys/fs/vx_inode.h > /dev/null # } (dummy '}' to match '{' in above egrep) if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHASVXFS_VX_INODE" fi # } fi # } fi # } # Set libraries and dialect subdirectory. LSOF_CFGL="$LSOF_CFGL -lkvm -lelf -lsocket -lnsl" LSOF_DIALECT_DIR=sun # Set local-specific stuff. if test "X$LSOF_LOCALSUFFIX" = "XLOCAL" # { then LSOF_DOC="\${DESTDIR}/usr/local/man" fi # } ;; # Configure for SCO|Caldera OpenServer Release 6.0.0 and UnixWare. osr6|unixware|uw) LSOF_TMP1=$LSOF_TGT LSOF_TGT="uw" if test "X$LSOF_RANLIB_SUP" = "X" # { then LSOF_RANLIB="" fi # } if test "X$LSOF_VSTR" = "X" # { then LSOF_VSTR=`uname -v` fi # } if test "X$LSOF_VERS" = "X" # { then # If the Openserver Release 6.0.0 or UnixWare version isn't pre-defined, # determine it. LSOF_VERS=`echo $LSOF_VSTR | sed 's/\([0-9\.]*\).*/\1/; s/\./ /g' | awk '{printf "%d%02d%02d\n", $1, $2, $3;}'` fi # } if test $LSOF_TMP1 = "osr6" # { then LSOF_CINFO="OSR6 support via UnixWare sources" # Convert the OpenServer Release 6.0.0 version number to a UnixWare one. case $LSOF_VERS in # { 60000) LSOF_VERS=70104 ;; *) echo "Unknown OpenServer Release version: $LSOF_VERS" rm -f $LSOF_HLP exit 1 esac # } fi # } LSOF_CFGF="$LSOF_CFGF -DUNIXWAREV=$LSOF_VERS" # Do OpenServer Release 6.0.0 and UnixWare version-specific stuff. case $LSOF_VERS in # { 20100|20101|20102|20103) if test -r ${LSOF_INCLUDE}/sys/fs/vx_inode.h # { then LSOF_CFGF="$LSOF_CFGF -DHASVXFS" fi # } LSOF_CFGL="$LSOF_CFGL -lsocket -lnsl -lelf -lgen" ;; 70000|70001|70100|70101|70103|70104) LSOF_TSTBIGF=" " LSOF_TSTLFLG="-lsocket -lnsl" if test $LSOF_VERS -lt 70103 # { then LSOF_DINC="$LSOF_DINC -I`pwd`/dialects/uw/uw7" else # $LSOF_VERS -ge 70103 # Process 7.1.3 and above. if test -r ${LSOF_INCLUDE}/netinet/in6.h # { then LSOF_CFGF="$LSOF_CFGF -DHASIPv6" fi # } if test $LSOF_VERS -ge 70104 # { then # Process 7.1.4 and above. LSOF_TMP1=0 if test -r ${LSOF_INCLUDE}/netinet/in_pcb.h # { then grep INKERNEL ${LSOF_INCLUDE}/netinet/in_pcb.h > /dev/null 2>&1 if test $? -eq 0 # { then LSOF_TMP1=1 fi # } fi # } if test $LSOF_TMP1 -eq 0 -a -r ${LSOF_INCLUDE}/netinet/tcp_var.h # { then grep INKERNEL ${LSOF_INCLUDE}/netinet/tcp_var.h > /dev/null 2>&1 if test $? -eq 0 # { then LSOF_TMP1=1 fi # } fi # } if test $LSOF_TMP1 -eq 1 # { then LSOF_CFGF="$LSOF_CFGF -DHAS_INKERNEL" fi # } fi # } fi # } if test ! -r ${LSOF_INCLUDE}/vm/swap.h -a -r ${LSOF_INCLUDE}/sys/swap.h # { then (cd ./dialects/uw/uw7/vm; rm -f swap.h; ln -s ${LSOF_INCLUDE}/sys/swap.h swap.h) fi # } if test -r ${LSOF_INCLUDE}/sys/fs/vx_gemini.h # { then LSOF_CFGF="$LSOF_CFGF -DHASVXFS" fi # } LSOF_CFGL="$LSOF_CFGL -lsocket -lnsl -lelf -lgen" /bin/pkginfo 2> /dev/null | grep -i patch | grep -i ptf7038 > /dev/null if test -r ${LSOF_INCLUDE}/sys/file.h # { then grep f_open ${LSOF_INCLUDE}/sys/file.h > /dev/null if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHAS_F_OPEN" fi # } fi # } if test -r ${LSOF_INCLUDE}/sys/fs/cdfs_fs.h # { then grep "cdfs_LogSecShift;" ${LSOF_INCLUDE}/sys/fs/cdfs_fs.h > /dev/null 2>&1 if test $? -eq 0 # { then LSOF_TMP=`grep "cdfs_LogSecShift;" ${LSOF_INCLUDE}/sys/fs/cdfs_fs.h | sed 's/^[ ]*\([^ ]*\).*/\1/'` if test "X$LSOF_TMP" != "X" # { then LSOF_CFGF="$LSOF_CFGF -DTYPELOGSECSHIFT=$LSOF_TMP" fi # } fi # } fi # } if test -r ${LSOF_INCLUDE}/sys/proc.h # { then grep p_pgid ${LSOF_INCLUDE}/sys/proc.h > /dev/null if test $? -eq 0 # { then LSOF_CFGF="$LSOF_CFGF -DHAS_P_PGID" fi # } fi # } if test $LSOF_VERS -ge 70101 # { then # Do OpenServer Release 6.0.0 and UnixWare 7.1.1 and above tests, as # required. if test "X$UW_HAS_NSC" = "X" # { then UW_HAS_NSC=N if test -x /bin/node_self # { then /bin/node_self > /dev/null 2>&1 if test $? -eq 0 # { then UW_HAS_NSC=Y fi # } fi # } fi # } if test "X$UW_HAS_NSC" = "XY" -o "X$UW_HAS_NSC" = "Xy" # { then LSOF_CFGF="$LSOF_CFGF -DHAS_UW_NSC" LSOF_CFGL="$LSOF_CFGL -lcluster" fi # } if test -r ${LSOF_INCLUDE}/sys/nsc_synch.h # { then LSOF_CFGF="$LSOF_CFGF -DHAS_UW_CFS" fi # } fi # } ;; *) echo Unsupported UnixWare version: `uname -v` rm -f $LSOF_HLP exit 1 ;; esac # } if test -r ${LSOF_INCLUDE}/sys/fs/xnamnode.h # { then LSOF_CFGF="$LSOF_CFGF -DHASXNAMNODE" fi # } LSOF_DIALECT_DIR=uw ;; # Handle unknown abbreviation. *) echo "Can't configure for $LSOF_TGT." cat $LSOF_HLP rm -f $LSOF_HLP exit 1 ;; # End of LSOF_TGT cases esac # } # Do an inventory of the distribution, as required. if test "X$LSOF_SCRIPT_CALL" = "Xyes" -a ! -r ./.neverInv # { then if test ! -f ./Inventory # Want -x, but Ultrix doesn't grok it. # { then echo "Can't find Inventory script." rm -f $LSOF_HLP exit 1 fi # } ./Inventory fi # } # Make sure target directory exists. if test ! -d ./dialects/$LSOF_DIALECT_DIR # { then echo "Can't configure for $LSOF_TGT -- ./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 # { then echo "Can't configure for $LSOF_TGT -- ./dialects/$LSOF_DIALECT_DIR/$LSOF_MK doesn't exist." rm -f $LSOF_HLP exit 1 fi # } # Make sure $LSOF_MKF, $LSOF_SPMKF, or $LSOF_MKF.$LSOF_LOCALSUFFIX) exists # in the target directory. if test "X$LSOF_SPMKF" != "X" # { then LSOF_TMP1=$LSOF_SPMKF else LSOF_TMP1=$LSOF_MKF fi # } if test "X$LSOF_LOCALSUFFIX" != "X" # { then LSOF_REST=$LSOF_TMP1.$LSOF_LOCALSUFFIX else LSOF_REST=$LSOF_TMP1 fi # } if test ! -r ./dialects/$LSOF_DIALECT_DIR/$LSOF_REST # { then echo "Can't configure for $LSOF_TGT -- ./dialects/$LSOF_DIALECT_DIR/$LSOF_REST doesn't exist." rm -f $LSOF_HLP exit 1 fi # } # If this is FreeBSD, make sure $LSOF_FBSD_ZFS_MKF exists. if test $LSOF_FBSD_ZFS -eq 1 # { then if test ! ./dialects/$LSOF_DIALECT_DIR/$LSOF_FBSD_ZFS_MKF # { then echo "Can't configure for $LSOF_TGT -- ./dialects/$LSOF_DIALECT_DIR/$LSOF_FBSD_ZFS_MKF doesn't exist." rm -f $LSOF_HLP exit 1 fi # } fi # }} # Make sure $LSOF_VF exists. Extract the version number from it. if test ! -r $LSOF_VF # { then echo "Version number file, ./$LSOF_VF, doesn't exist." rm -f $LSOF_HLP exit 1 else LSOF_VN=`sed "s/.ds VN \(.*\)/\1/" < $LSOF_VF` fi # } # Clean up in advance. rm -f $LSOF_F $LSOF_MKFC $LSOF_FBSD_ZFS_MKF $LSOF_TSTCFLG $LSOF_TSTCC rm -f $LSOF_TSTXOC $LSOF_TSTLFF echo "rm -f $LSOF_F $LSOF_MKFC $LSOF_FBSD_ZFS_MKF $LSOF_TSTCFLG" echo "rm -f $LSOF_TSTCC $LSOF_TSTXOC $LSOF_TSTLFF" # Make sure there's a C compiler name. if test "X$LSOF_CC" = "X" # { then LSOF_CC=cc fi # } # Do common feature analyses. # Check for localtime(3) and strftime(3). rm -f ${LSOF_TMPC}.* cat > $LSOF_TMPC.c << .LSOF_END_HERE_DOC2 #include main(){ time_t cl; struct tm *ts; char bf[32]; if ((cl = time(NULL)) == (time_t)-1) return(1); ts = localtime(&cl); if (strftime(bf, sizeof(bf), "%D", ts) != 8) return(1); if ((bf[2] != '/') || (bf[5] != '/')) return (1); return(0); } .LSOF_END_HERE_DOC2 echo $EO "Testing C library for localtime() and strftime(), using $LSOF_CC ... $EC" $LSOF_CC ${LSOF_TMPC}.c -o ${LSOF_TMPC}.x > /dev/null 2>&1 if test -x ${LSOF_TMPC}.x # { then ./${LSOF_TMPC}.x if test $? -eq 0 # } then LSOF_CFGF="$LSOF_CFGF -DHAS_STRFTIME" echo "present" else echo "unusable" fi # } else echo "missing" fi # } rm -f ${LSOF_TMPC}.[cox] # Make the dialect sources. 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 # Make $LSOF_MKFC and ${LSOF_LIB}/$LSOF_LIBMKF. echo "# $LSOF_TGT Makefile for lsof revision $LSOF_VN" > $LSOF_MKFC echo "" >> $LSOF_MKFC echo "CC= $LSOF_CC" >> $LSOF_MKFC if test "X$LSOF_CCV" != "X" # { then echo "" >> $LSOF_MKFC echo "CCV= $LSOF_CCV" >> $LSOF_MKFC fi # } if test "X$LSOF_LIB_NO" = "X" # { then echo "" >> $LSOF_MKFC echo "LIB= ${LSOF_LIB}/liblsof.a" >> $LSOF_MKFC fi # } if test "X$LSOF_LD" != "X" # { then echo "" >> $LSOF_MKFC echo "LD= $LSOF_LD" >> $LSOF_MKFC fi # } if test "X$LSOF_CINFO" != "X" # { then echo "" >> $LSOF_MKFC echo "CINFO= $LSOF_CINFO" >> $LSOF_MKFC fi # } if test "X$LSOF_CFGD" != "X" # { then echo "CFGD= $LSOF_CFGD" >> $LSOF_MKFC fi # } if test "X$LSOF_CFGDN" != "X" # { then echo "CFGDN= $LSOF_CFGDN" >> $LSOF_MKFC fi # } if test "X$LSOF_ARCH" != "X" # { then LSOF_CFGF="$LSOF_CFGF -DLSOF_ARCH=\\\"$LSOF_ARCH\\\"" fi # } if test "X$LSOF_VSTR" != "X" # { then LSOF_TMP=`echo $LSOF_VSTR | sed 's/(/\\\\(/g' | sed 's/)/\\\\)/g'` LSOF_CFGF="$LSOF_CFGF -DLSOF_VSTR=\\\"$LSOF_TMP\\\"" fi # } echo "" >> $LSOF_MKFC echo "CFGF= $LSOF_CFGF" >> $LSOF_MKFC if test "X$LSOF_LIB_NO" = "X" # { then echo "" >> $LSOF_MKFC echo "CFGL= $LSOF_FCFGL -L./$LSOF_LIB -llsof $LSOF_CFGL" >> $LSOF_MKFC fi # } echo "" >> $LSOF_MKFC if test "X$LSOF_DEBUG" = "X" # { then LSOF_DEBUG="-O" else if test "X$LSOF_DEBUG" = "XNo-O" # { then LSOF_DEBUG="" fi # } fi # } echo "DEBUG= $LSOF_DEBUG" >> $LSOF_MKFC if test "X$LSOF_DINC" != "X" # { then echo "" >> $LSOF_MKFC echo "DINC= $LSOF_DINC" >> $LSOF_MKFC fi # } if test "X$LSOF_DOC" != "X" # { then echo "" >> $LSOF_MKFC echo "DOC=$LSOF_DOC" >> $LSOF_MKFC fi # } if test "X$LSOF_DISTRIBKVM" != "X" -a "X$LSOF_DISTRIBKVM" != "XKVM" # { then echo "" >> $LSOF_MKFC echo "KVM= $LSOF_DISTRIBKVM" >> $LSOF_MKFC fi # } 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 if test "X$LSOF_LIB_NO" = "X" # { then # Put archiving and optional randomizing strings in ${LSOF_LIB}/$LSOF_LIBMKF. # # Process optional CFLAGS override. # # Add the library Makefile skeleton section. echo "" >> ${LSOF_LIB}/$LSOF_LIBMKF if test "X$LSOF_AR" = "X" # { then echo "AR= ar cr \${LIB} \${OBJ}" >> ${LSOF_LIB}/$LSOF_LIBMKF else echo "AR= $LSOF_AR \${LIB} \${OBJ}" >> ${LSOF_LIB}/$LSOF_LIBMKF fi # } if test "X$LSOF_RANLIB" != "X" # { then echo "" >> ${LSOF_LIB}/$LSOF_LIBMKF echo "RANLIB= $LSOF_RANLIB \${LIB}" >> ${LSOF_LIB}/$LSOF_LIBMKF fi # } echo "" >> ${LSOF_LIB}/$LSOF_LIBMKF if test "X$LSOF_CFLAGS_OVERRIDE" = "X" # { then echo "CFLAGS= \${CDEFS} \${INCL} \${DEBUG}" >> ${LSOF_LIB}/$LSOF_LIBMKF else echo "override CFLAGS=\${CDEFS} \${INCL} \${DEBUG}" >> ${LSOF_LIB}/$LSOF_LIBMKF fi # } echo "" >> ${LSOF_LIB}/$LSOF_LIBMKF cat ${LSOF_LIB}/$LSOF_LIBMKFSKEL >> ${LSOF_LIB}/$LSOF_LIBMKF echo $LSOF_MKFC and ${LSOF_LIB}/$LSOF_LIBMKF created. else echo $LSOF_MKFC created. fi # } # If this is FreeBSD, create $LSOF_FBSD_ZFS_MKF. if test $LSOF_FBSD_ZFS -eq 1 # { then rm -f $LSOF_FBSD_ZFS_MKF echo "# $LSOF_TGT ZFS Makefile for lsof revision $LSOF_VN" > $LSOF_FBSD_ZFS_MKF echo "" >> $LSOF_FBSD_ZFS_MKF echo "CC= $LSOF_CC" >> $LSOF_FBSD_ZFS_MKF echo "" >> $LSOF_FBSD_ZFS_MKF echo "CFLAGS= $LSOF_FBSD_ZFS_CFGF" >> $LSOF_FBSD_ZFS_MKF echo "" >> $LSOF_FBSD_ZFS_MKF if test "X$LSOF_DEBUG" = "X" # { then LSOF_DEBUG="-O" else if test "X$LSOF_DEBUG" = "XNo-O" # { then LSOF_DEBUG="" fi # } fi # } echo "DEBUG= $LSOF_DEBUG" >> $LSOF_FBSD_ZFS_MKF echo "" >> $LSOF_FBSD_ZFS_MKF echo "OPENSOLARIS= $LSOF_FBSD_ZFS_SYS" >> $LSOF_FBSD_ZFS_MKF echo "" >> $LSOF_FBSD_ZFS_MKF cat ./dialects/$LSOF_DIALECT_DIR/$LSOF_FBSD_ZFS_MKF >> $LSOF_FBSD_ZFS_MKF echo $LSOF_FBSD_ZFS_MKF created. fi # } # Create test cc file. echo "$LSOF_CC" > $LSOF_TSTCC echo "$LSOF_TSTCC created" # Create test cflags file. echo "-DLT_DIAL_$LSOF_TGT" > $LSOF_TSTCFLG if test "X$LSOF_TSTBIGF" != "X" # { then echo "-DLT_BIGF" >> $LSOF_TSTCFLG if test "X$LSOF_TSTBIGF" != "X " # { then for i in $LSOF_TSTBIGF # { do echo "$i" >> $LSOF_TSTCFLG done # } fi # } fi # } if test "X$LSOF_TSTDFLG" != "X" # { then for i in $LSOF_TSTDFLG # { do echo "$i" >> $LSOF_TSTCFLG done # } fi # } echo $LSOF_CC | grep gcc > /dev/null 2>&1 if test $? -eq 0 # { then echo "-DLT_GCC" >> $LSOF_TSTCFLG else echo "-DLT_CC" >> $LSOF_TSTCFLG fi # r} if test $LSOF_TSTKMEM -eq 1 # { then echo "-DLT_KMEM" >> $LSOF_TSTCFLG fi # } if test $LSOF_TSTK64 -eq 1 # { then echo "-DLT_K64" >> $LSOF_TSTCFLG fi # } echo "-DLT_VERS=$LSOF_VERS" >> $LSOF_TSTCFLG if test $LSOF_TSTVPATH -eq 1 # { then echo "-DLT_VPATH" >> $LSOF_TSTCFLG fi # } echo "$LSOF_TSTCFLG created" # Create tests loader flags file. echo $LSOF_TSTLFLG > $LSOF_TSTLFF echo "$LSOF_TSTLFF created" # Create test extra objects file. echo "$LSOF_TSTXO" > $LSOF_TSTXOC echo "$LSOF_TSTXOC created" rm -f $LSOF_HLP # Call Customize, as required. if test "X$LSOF_SCRIPT_CALL" = "Xyes" -a ! -r ./.neverCust # { then if test ! -f ./Customize # { Want -x, but Ultrix doesn't grok it. then echo "Can't find Customize script." exit 1 fi # } ./Customize $LSOF_DIALECT_DIR fi # } # Issue unsupported warning, as appropriate. if test "X$LSOF_UNSUP" != "X" # { then echo "$LSOF_UNSUP" fi #} exit 0 lsof-4.86+dfsg.orig/version0000444000175000017500000000001411645074344016067 0ustar nicholasnicholas.ds VN 4.86 lsof-4.86+dfsg.orig/lib/0000755000175000017500000000000011741064216015226 5ustar nicholasnicholaslsof-4.86+dfsg.orig/lib/lkud.c0000444000175000017500000001066611077377612016351 0ustar nicholasnicholas/* * lkud.c -- device lookup functions 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. */ /* * lkud.c -- lookup device * * The caller may define: * * HASBLKDEV to activate block device lookup */ #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"; static char *rcsid = "$Id: lkud.c,v 1.7 2008/10/21 16:12:36 abe Exp $"; # 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) /* * 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 */ { 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) 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(HASBLKDEV) */ #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 */ { 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) 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(USE_LIB_LKUPDEV) */ lsof-4.86+dfsg.orig/lib/isfn.c0000444000175000017500000002413411077377610016342 0ustar nicholasnicholas/* * isfn.c -- is_file_named() 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. */ /* * To use this source file: * * 1. Define USE_LIB_IS_FILE_NAMED. * * 2. If clone support is required: * * a. Define HAVECLONEMAJ to be the name of the variable that * contains the status of the clone major device -- e.g., * * #define HAVECLONEMAJ HaveCloneMaj * * b. Define CLONEMAJ to be the name of the constant or * variable that defines the clone major device -- e.g., * * #define CLONEMAJ CloneMaj * * c. Make sure that clone devices are identified by an lfile * element is_stream value of 1. * * d. Accept clone searching by device number only. */ #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"; static char *rcsid = "$Id: isfn.c,v 1.10 2008/10/21 16:12:36 abe Exp $"; # endif /* !defined(lint) */ #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 */ # 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!) */ /* * 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); Exit(1); } 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); Exit(1); } if (!(HbyFrd = (struct hsfile *)calloc((MALLOC_S)SFRDHASH, sizeof(struct hsfile)))) { (void) fprintf(stderr, "%s: can't allocate space for %d rdev hash buckets\n", Pn, SFRDHASH); Exit(1); } if (!(HbyFsd = (struct hsfile *)calloc((MALLOC_S)SFFSHASH, sizeof(struct hsfile)))) { (void) fprintf(stderr, "%s: can't allocate space for %d file sys hash buckets\n", Pn, SFFSHASH); Exit(1); } if (!(HbyNm = (struct hsfile *)calloc((MALLOC_S)SFNMHASH, sizeof(struct hsfile)))) { (void) fprintf(stderr, "%s: can't allocate space for %d name hash buckets\n", Pn, SFNMHASH); Exit(1); } hs++; /* * Scan the Sfile chain, building file, file system, 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); Exit(1); } 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 */ { 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); } #else /* !defined(USE_LIB_IS_FILE_NAMED) */ char isfn_d1[] = "d"; char *isfn_d2 = isfn_d1; #endif /* defined(USE_LIB_IS_FILE_NAMED) */ lsof-4.86+dfsg.orig/lib/prfp.c0000444000175000017500000001125711077377613016357 0ustar nicholasnicholas/* * prfp.c -- process_file() 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_PROCESS_FILE) # if !defined(lint) static char copyright[] = "@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: prfp.c,v 1.14 2008/10/21 16:12:36 abe Exp $"; # endif /* !defined(lint) */ #include "../lsof.h" /* * process_file() - process file */ /* * The caller may define: * * FILEPTR as the name of the location to store a pointer * to the current file struct -- e.g., * * struct file *foobar; * #define FILEPTR foobar */ void process_file(fp) KA_T fp; /* kernel file structure address */ { 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_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 (f.f_type || f.f_ops) { (void) snpf(Namech, Namechl, "%s file struct, ty=%#x, 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"); } #else /* !defined(USE_LIB_PROCESS_FILE) */ char prfp_d1[] = "d"; char *prfp_d2 = prfp_d1; #endif /* defined(USE_LIB_PROCESS_FILE) */ lsof-4.86+dfsg.orig/lib/pdvn.c0000444000175000017500000001055011077377612016351 0ustar nicholasnicholas/* * pdvn.c -- print device name functions 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_PRINTDEVNAME) # if !defined(lint) static char copyright[] = "@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: pdvn.c,v 1.8 2008/10/21 16:12:36 abe Exp $"; # 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) */ /* * To use this source file: * * 1. Define USE_LIB_PRINTDEVNAME, or both. * * 2. Define HAS_STD_CLONE to enable standard clone searches in * printdevname(). * * 3. Define HASBLDKDEV to enable block device processing. */ /* * Local definitions */ #define LIKE_BLK_SPEC "like block special" #define LIKE_CHR_SPEC "like character special" # 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 */ { # if defined(HAS_STD_CLONE) struct clone *c; # endif /* defined(HAS_STD_CLONE) */ struct l_dev *dp; int r = 1; # 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); Exit(1); } (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(USE_LIB_PRINTDEVNAME) */ lsof-4.86+dfsg.orig/lib/rnch.c0000444000175000017500000004533211077377655016351 0ustar nicholasnicholas/* * rnch.c -- Sun format name cache functions 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(HASNCACHE) && defined(USE_LIB_RNCH) # if !defined(lint) static char copyright[] = "@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: rnch.c,v 1.11 2008/10/21 16:13:23 abe Exp $"; # endif /* !defined(lint) */ #include "../lsof.h" /* * rnch.c - read Sun format (struct ncache) name cache * * This code is effective only when HASNCACHE is defined. */ /* * The caller must: * * #include the relevant header file -- e.g., . * * Define X_NCSIZE as the nickname for the kernel cache size variable, * or, if X_NCSIZE is undefined, define FIXED_NCSIZE as the size of the * kernel cache. * * Define X_NCACHE as the nickname for the kernel cache address and * define ADDR_NCACHE if the address is the address of the cache, * rather than the address of a pointer to it. * * Define NCACHE_NXT if the kernel's name cache is a linked list, starting * at the X_NCACHE address, rather than a table, starting at that address. * * Define any of the following casts that differ from their defaults: * * NCACHE_SZ_CAST cast for X_NCACHE (default int) * * The caller may: * * Define NCACHE_DP as the name of the element in the * ncache structure that contains the * parent vnode pointer. * * Default: dp * * Define NCACHE_NAME as the name of the element in the * ncache structure that contains the * name. * * Default: name * * Define NCACHE_NAMLEN as the name of the element in the * ncache structure that contains the * name length. * * Deafult: namlen * * Define NCACHE_NEGVN as the name of the name list element * whose value is a vnode address to * ignore when loading the kernel name * cache. * * Define NCACHE_NODEID as the name of the element in the * ncache structure that contains the * vnode's capability ID. * * Define NCACHE_PARID as the name of the element in the * ncache structure that contains the * parent vnode's capability ID. * * Define NCACHE_VP as the name of the element in the * ncache structure that contains the * vnode pointer. * * Default: vp * * Note: if NCACHE_NODEID is defined, then NCACHE_PARID must be defined. * * * The caller must: * * Define this prototype for ncache_load(): * * _PROTOTYPE(void ncache_load,(void)); */ /* * Local static values */ static int Mch; /* name cache hash mask */ # 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 */ struct l_nch { 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) */ 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 */ # 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) */ _PROTOTYPE(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 */ # 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_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 */ { 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) 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); } /* * ncache_isroot() - is head of name cache path a file system root? */ static int ncache_isroot(va, cp) KA_T va; /* kernel vnode address */ char *cp; /* partial path */ { char buf[MAXPATHLEN]; int i; MALLOC_S len; struct mounts *mtp; struct stat sb; struct vnode v; static int vca = 0; static int vcn = 0; static KA_T *vc = (KA_T *)NULL; if (!va) return(0); /* * Search the root vnode cache. */ for (i = 0; i < vcn; i++) { if (va == vc[i]) return(1); } /* * Read the vnode and see if it's a VDIR node with the VROOT flag set. If * it is, then the path is complete. * * If it isn't, and if the file has an inode number, search the mount table * and see if the file system's inode number is known. If it is, form the * possible full path, safely stat() it, and see if it's inode number matches * the one we have for this file. If it does, then the path is complete. */ if (kread((KA_T)va, (char *)&v, sizeof(v)) || v.v_type != VDIR || !(v.v_flag & VROOT)) { /* * The vnode tests failed. Try the inode tests. */ if (Lf->inp_ty != 1 || !Lf->inode || !Lf->fsdir || (len = strlen(Lf->fsdir)) < 1) return(0); if ((len + 1 + strlen(cp) + 1) > sizeof(buf)) return(0); for (mtp = readmnt(); mtp; mtp = mtp->next) { if (!mtp->dir || !mtp->inode) continue; if (strcmp(Lf->fsdir, mtp->dir) == 0) break; } if (!mtp) return(0); (void) strcpy(buf, Lf->fsdir); if (buf[len - 1] != '/') buf[len++] = '/'; (void) strcpy(&buf[len], cp); if (statsafely(buf, &sb) != 0 || (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); Exit(1); } } 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); Exit(1); } # 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); Exit(1); } } 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); Exit(1); } } 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); Exit(1); } (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); Exit(1); } 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); Exit(1); } 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 *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) */ lsof-4.86+dfsg.orig/lib/ckkv.c0000444000175000017500000000466411077377572016356 0ustar nicholasnicholas/* * cvfs.c -- ckkv() function for lsof library */ /* * 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. */ #include "../machine.h" #if defined(USE_LIB_CKKV) # if !defined(lint) static char copyright[] = "@(#) Copyright 1998 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: ckkv.c,v 1.3 2008/10/21 16:12:36 abe Exp $"; # endif /* !defined(lint) */ #include "../lsof.h" #include /* * 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 */ { # 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)); Exit(1); } 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) */ lsof-4.86+dfsg.orig/lib/cvfs.c0000444000175000017500000000536711077377605016357 0ustar nicholasnicholas/* * cvfs.c -- completevfs() 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. */ /* * The caller must define CVFS_DEVSAVE to have the device number moved * from the mounts entry to the local vfs structure. * * The caller must define CVFS_NLKSAVE to have the link count moved from * the mounts entry to the local vfs structure. * * The caller must define CVFS_SZSAVE to have the size moved from the * mounts entry to the local vfs structure. */ #include "../machine.h" #if defined(USE_LIB_COMPLETEVFS) # if !defined(lint) static char copyright[] = "@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: cvfs.c,v 1.6 2008/10/21 16:12:36 abe Exp $"; # endif /* !defined(lint) */ #include "../lsof.h" /* * completevfs() - complete local vfs structure */ void completevfs(vfs, dev) 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; } } } #else /* !defined(USE_LIB_COMPLETEVFS) */ char cvfs_d1[] = "d"; char *cvfs_d2 = cvfs_d1; #endif /* defined(USE_LIB_COMPLETEVFS) */ lsof-4.86+dfsg.orig/lib/rnam.c0000444000175000017500000003776411077377654016365 0ustar nicholasnicholas/* * rnam.c -- BSD format name cache functions 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(HASNCACHE) && defined(USE_LIB_RNAM) # if !defined(lint) static char copyright[] = "@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: rnam.c,v 1.11 2008/10/21 16:13:23 abe Exp $"; # endif /* !defined(lint) */ #include "../lsof.h" /* * rnam.c - read BSD format (struct namecache or nch) name cache * * This code is effective only when HASNCACHE is defined. */ /* * The caller must: * * #include the relevant header file -- e.g., . * * Define X_NCACHE as the nickname for the kernel cache address. * * Define X_NCSIZE as the nickname for the size of the kernel cache. * * Define NCACHE_NXT if the kernel's name cache is a linked list, starting * at the X_NCACHE address, rather than a table, starting at that address. * * Define NCACHE_NO_ROOT if the calling dialect doesn't support * the locating of the root node of a file system. * * Define the name of the name cache structure -- e.g., * * #define NCACHE * * Define the following casts, if they differ from the defaults: * * NCACHE_SZ_CAST cast for X_NCSIZE (default int) * * e.g., * #define NCACHE_SZ_CAST unsigned long * * Define the names of these elements of struct NCACHE: * * must #define NCACHE_NM * must #define NCACHE_NMLEN * must #define NCACHE_NODEADDR * must #define NCACHE_NODEID * optional #define NCACHE_PARID >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) */ #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) */ /* * ncache_addr() - look up a node's local ncache address */ 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 */ { 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) 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); } # 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 */ { 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); Exit(1); } nca += 10; } nc[ncn++] = na; return(1); } # 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); Exit(1); } # 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); Exit(1); } } 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(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(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); Exit(1); } 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); Exit(1); } 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 *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) */ lsof-4.86+dfsg.orig/lib/rmnt.c0000444000175000017500000001456611077377654016403 0ustar nicholasnicholas/* * rmnt.c -- readmnt() 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_READMNT) # if !defined(lint) static char copyright[] = "@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: rmnt.c,v 1.12 2008/10/21 16:13:23 abe Exp $"; # endif /* !defined(lint) */ #include "../lsof.h" /* * The caller may define: * * 1. An RMNT_EXPDEV macro to expand (ala EP/IX) device numbers; * * EP/IX, for example, uses: * * #define RMNT_EXPDEV(n) expdev(n) * * 2. A custom macro, MNTSKIP, for making decisions to skip entries * -- e.g., ones whose mnt_type is MNTTYPE_IGNORE. * * 3. RMNT_FSTYPE to specify the member name of the character string of the * mntent structure containing the file system type, and MOUNTS_FSTYPE to * specify the member name of the character string pointer of the local * mounts structure where RMNT_FSTYPE is to be copied. * * 4. RMNT_STAT_FSTYPE to specify the member name of the stat structure * containing an integer file system type, and MOUNTS_STAT_FSTYPE to * specify the member name of the integer in the local mounts structure * where RMNT_STAT_FSTYPE is to be copied. * */ #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); Exit(1); } /* * 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"); Exit(1); } 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); Exit(1); } (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) */ lsof-4.86+dfsg.orig/lib/fino.c0000444000175000017500000000647311077377607016352 0ustar nicholasnicholas/* * fino.c -- find inode functions 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. */ /* * fino.c -- find block (optional) and character device file inode numbers * * The caller must define: * * HASBLKDEV to activate the block device inode lookup */ #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"; static char *rcsid = "$Id: fino.c,v 1.5 2008/10/21 16:12:36 abe Exp $"; # endif /* !defined(lint) */ #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) */ #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; readdev(0); # 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(HASBLKDEV) */ #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; readdev(0); # 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(USE_LIB_FIND_CH_INO) */ lsof-4.86+dfsg.orig/lib/rnmh.c0000444000175000017500000004327011077377656016363 0ustar nicholasnicholas/* * rnmh.c -- functions to read BSD format name cache information from a * kernel hash table */ /* * 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(HASNCACHE) && defined(USE_LIB_RNMH) # if !defined(lint) static char copyright[] = "@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: rnmh.c,v 1.13 2008/10/21 16:13:23 abe Exp $"; # endif /* !defined(lint) */ #include "../lsof.h" /* * rnmh.c - read BSD format hashed kernel name cache */ /* * The caller must: * * #include the relevant header file -- e.g., . * * Define X_NCACHE as the nickname for the kernel cache hash tables * address. * * Define X_NCSIZE as the nickname for the size of the kernel cache has * table length. * * Define NCACHE_NO_ROOT if the calling dialect doesn't support * the locating of the root node of a file system. * * Define the name of the name cache structure -- e.g., * * #define NCACHE * * * Define the following casts, if they differ from the defaults: * * NCACHE_SZ_CAST case for X_NCSIZE (default unsigned long) * * Define the names of these elements of struct NCACHE: * * #define NCACHE_NM * #define NCACHE_NXT * #define NCACHE_NODEADDR * #define NCACHE_PARADDR * * Optionally define: * * #define NCACHE_NMLEN * * Optionally define *both*: * * #define NCACHE_NODEID * #define NCACHE_PARID * * The caller may need to: * * Define this prototype for ncache_load(): * * _PROTOTYPE(static void ncache_load,(void)); * * Define NCACHE_VROOT to be the value of the flag that signifies that * the vnode is the root of its file system. * * E.g., for BSDI >= 5: * * #define NCACHE_VROOT VV_ROOT * * If not defined, NCACHE_VROOT is defined as "VROOT". * * Define VNODE_VFLAG if the vnode's flag member's name isn't v_flag. * * Note: if NCHNAMLEN is defined, the name is assumed to be in * NCACHE_NM[NCHNAMLEN]; if it isn't defined, the name is assumed to be in an * extension that begins at NCACHE_NM[0]. * * Note: if NCACHE_NMLEN is not defined, then NCACHE_NM must be a pointer to * a kernel allocated, NUL-terminated, string buffer. */ /* * Casts */ # 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_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 */ 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) */ }; static struct l_nch *Ncache = (struct l_nch *)NULL; /* the head of the local name cache */ static struct l_nch **Nchash = (struct l_nch **)NULL; /* 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) */ /* * ncache_addr() - look up a node's local ncache address */ 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 */ { 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) 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); } # 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 */ { 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); Exit(1); } nca += 10; } nc[ncn++] = na; return(1); } # 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); Exit(1); } 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); Exit(1); } 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); Exit(1); } 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 *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); } #else /* !defined(HASNCACHE) || !defined(USE_LIB_RNMH) */ char rnmh_d1[] = "d"; char *rnmh_d2 = rnmh_d1; #endif /* defined(HASNCACHE) && defined(USE_LIB_RNMH) */ lsof-4.86+dfsg.orig/lib/dvch.c0000444000175000017500000010131711077377606016333 0ustar nicholasnicholas/* * dvch.c -- device cache functions 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(HASDCACHE) # if !defined(lint) static char copyright[] = "@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dvch.c,v 1.16 2008/10/21 16:12:36 abe Exp $"; # endif /* !defined(lint) */ #include "../lsof.h" /* * dvch.c - module that contains common device cache functions * * The caller may define the following: * * DCACHE_CLONE is the name of the function that reads and writes the * clone section of the device cache file. The clone * section follows the device section. If DCACHE_CLONE * isn't defined, but HAS_STD_CLONE is defined to be 1, * DCACHE_CLONE defaults to the local static function * rw_clone_sect() that reads and writes a standard * clone cache. * * DCACHE_CLR is the name of the function that clears the clone and * pseudo caches when reading the device cache fails. If * DCACHE_CLR isn't defined, but HAS_STD_CLONE is defined * to be 1, DCACHE_CLR defaults to the local static * function clr_sect() that clears a standard clone cache. * * DCACHE_PSEUDO is the name of the function that reads and writes * the pseudo section of the device cache file. The * pseudo section follows the device section and the * clone section, if there is one. * * DVCH_CHOWN if the dialect has no fchown() function, so * chown() must be used instead. * * DVCH_DEVPATH if the path to the device directory isn't "/dev". * * DVCH_EXPDEV if st_rdev must be expanded with the expdev() * macro before use. (This is an EP/IX artifact.) * * HASBLKDEV if block device information is stored in BDevtp[]. */ /* * Local definitions */ # if !defined(DVCH_DEVPATH) #define DVCH_DEVPATH "/dev" # endif /* !defined(DVCH_DEVPATH) */ /* * Local storage */ 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) /* * 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); Exit(1); } 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); Exit(1); } } # 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); Exit(1); } if (!(Sdev = (struct l_dev **)malloc((MALLOC_S)(sizeof(struct l_dev *) * Ndev)))) { (void) fprintf(stderr, "%s: no space for device pointers\n", Pn); Exit(1); } } /* * 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) */ } # 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) */ /* * 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 */ { 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; } } /* * 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 */ { 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) Exit(1); /* * 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 */ { 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); Exit(1); } 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); Exit(1); } 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); Exit(1); } 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); } # 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 */ { 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); Exit(1); } 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); Exit(1); return(1); /* This useless return(1) keeps some * compilers happy. */ } # 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; } } /* * wr2DCfd() - write to the DCfd file descriptor */ int wr2DCfd(b, c) 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); } #else /* !defined(HASDCACHE) */ char dvch_d1[] = "d"; char *dvch_d2 = dvch_d1; #endif /* defined(HASDCACHE) */ lsof-4.86+dfsg.orig/lib/regex.c0000444000175000017500000061044411021540167016506 0ustar nicholasnicholas/* * 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 * 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 #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 #else /* We need this for `regex.h', and perhaps for the Emacs include files. */ # include #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: must be included before . */ # include # include #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 # include # include #endif /* This is for other GNU distributions with internationalized messages. */ #if HAVE_LIBINTL_H || defined _LIBC # include # 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 # 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 # 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 # 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 #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 */ #include "../regex.h" /* isalpha etc. are used for the character classes. */ #include /* 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 # 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 /* It is useful to test things that ``must'' be true when debugging. */ # include 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 (®_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 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 set_number_at succeed_n jump_n (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; /* \ has been turned into a `duplicate' command which is followed by the numeric value of 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 ? ®s : (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) */ lsof-4.86+dfsg.orig/lib/Makefile.skel0000444000175000017500000000201507242114006017611 0ustar nicholasnicholas# Lsof library Makefile skeleton # # This skeleton is added to definitions established by Configure. # # $Id: Makefile.skel,v 1.13 2001/02/13 02:12:16 abe Exp $ LIB= liblsof.a CDEF= ${RC_CFLAGS} CDEFS= ${CDEF} ${CFGF} INCL= ${DINC} HDR= ../lsof.h ../proto.h ../dlsof.h ../dproto.h ../machine.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 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 all: ${LIB} ${LIB}: ${OBJ} ${AR} ${RANLIB} clean: FRC rm -f ${LIB} ${OBJ} errs Makefile.bak a.out core FRC: ckkv.o: ${HDR} ckkv.c cvfs.o: ${HDR} cvfs.c dvch.o: ${HDR} dvch.c fino.o: ${HDR} fino.c isfn.o: ${HDR} isfn.c lkud.o: ${HDR} lkud.c pdvn.o: ${HDR} pdvn.c prfp.o: ${HDR} prfp.c 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 rnch.o: ${HDR} rnch.c rnmh.o: ${HDR} rnmh.c snpf.o: ${HDR} snpf.c lsof-4.86+dfsg.orig/lib/snpf.c0000444000175000017500000004703711077377656016372 0ustar nicholasnicholas/* * 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 #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 = ""; 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) */ lsof-4.86+dfsg.orig/lib/ptti.c0000444000175000017500000007351411077377650016375 0ustar nicholasnicholas/* * 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"; static char *rcsid = "$Id: ptti.c,v 1.6 2008/10/21 16:13:23 abe Exp $"; # 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) */ lsof-4.86+dfsg.orig/lib/rdev.c0000444000175000017500000003067311077377652016356 0ustar nicholasnicholas/* * rdev.c -- readdev() 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_READDEV) # if !defined(lint) static char copyright[] = "@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: rdev.c,v 1.12 2008/10/21 16:13:23 abe Exp $"; # endif /* !defined(lint) */ #include "../lsof.h" _PROTOTYPE(static int rmdupdev,(struct l_dev ***dp, int n, char *nm)); /* * To use this source file: * * 1. Define DIRTYPE as: * * #define DIRTYPE direct * or #define DIRTYPE dirent * * 2. Define HASDNAMLEN if struct DIRTYPE has a d_namlen element, giving * the length of d_name. * * 3. Define the RDEV_EXPDEV macro to apply special handling to device * numbers, as required. For example, for EP/IX 2.1.1: * * #define RDEV_EXPDEV(n) expdev(n) * * to use the expdev() function to expand device numbers. If * no RDEV_EXPDEV macro is defined, it defaults to: * * #define RDEV_EXPDEV(n) (n) * * 4. Define HASBLKDEV to request that information on S_IFBLK devices be * recorded in BDevtp[]. * * Define NOWARNBLKDEV to suppress the issuance of a warning when no * block devices are found. * * 5. Define RDEV_STATFN to be a stat function other than stat() or lstat() * -- e.g., * * #define RDEV_STATFN private_stat * * 6. Define HAS_STD_CLONE to request that clone device information be stored * in standard clone structures (defined in lsof.h and addressed via * Clone). If HAS_STD_CLONE is defined, these must also be defined: * * a. Define CLONEMAJ to be the name of the constant or * variable that defines the clone major device -- e.g., * * #define CLONEMAJ CloneMaj * * b. Define HAVECLONEMAJ to be the name of the variable that * contains the status of the clone major device -- e.g., * * #define HAVECLONEMAJ HaveCloneMaj * * Define HAS_STD_CLONE to be 1 if readdev() is expected to build the * clone table, the clone table is cached (if HASDCACHE is defined), and * there is a function to clear the cache table when the device table must * be reloaded. (See dvch.c for naming the clone cache build and clear * functions.) */ # 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) */ /* * readdev() - read device names, modes and types */ void readdev(skip) 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/ directory. */ while (--Dstkx >= 0) { if (!(dfp = OpenDir(Dstk[Dstkx]))) { # if defined(WARNDEVACCESS) if (!Fwarn) { (void) fprintf(stderr, "%s: WARNING: can't open: ", Pn); safestrprt(Dstk[Dstkx], stderr, 1); } # endif /* defined(WARNDEVACCESS) */ (void) free((FREE_P *)Dstk[Dstkx]); Dstk[Dstkx] = (char *)NULL; continue; } if (path) { (void) free((FREE_P *)path); path = (char *)NULL; } if (!(path = mkstrcat(Dstk[Dstkx], -1, "/", 1, (char *)NULL, -1, &pl))) { (void) fprintf(stderr, "%s: no space for: ", Pn); safestrprt(Dstk[Dstkx], stderr, 1); Exit(1); } (void) free((FREE_P *)Dstk[Dstkx]); Dstk[Dstkx] = (char *)NULL; /* * Scan the directory. */ for (dp = ReadDir(dfp); dp; dp = ReadDir(dfp)) { if (dp->d_ino == 0 || dp->d_name[0] == '.') continue; /* * Form the full path name and get its status. */ # if 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); Exit(1); } 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); Exit(1); } } 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); Exit(1); } 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); Exit(1); } 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); Exit(1); } } 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); Exit(1); } for (j = 0; j < BNdev; j++) { BSdev[j] = &BDevtp[j]; } (void) qsort((QSORT_P *)BSdev, (size_t)BNdev, (size_t)sizeof(struct l_dev *), compdev); BNdev = rmdupdev(&BSdev, BNdev, "block"); } # if !defined(NOWARNBLKDEV) else { if (!Fwarn) (void) fprintf(stderr, "%s: WARNING: no block devices found\n", Pn); } # endif /* !defined(NOWARNBLKDEV) */ # endif /* defined(HASBLKDEV) */ if (Ndev) { if (Ndev > i) { Ndev = i; Devtp = (struct l_dev *)realloc((MALLOC_P *)Devtp, (MALLOC_S)(sizeof(struct l_dev) * Ndev)); } if (!(Sdev = (struct l_dev **)malloc( (MALLOC_S)(sizeof(struct l_dev *) * Ndev)))) { (void) fprintf(stderr, "%s: no space for character device sort pointers\n", Pn); Exit(1); } for (i = 0; i < Ndev; i++) { Sdev[i] = &Devtp[i]; } (void) qsort((QSORT_P *)Sdev, (size_t)Ndev, (size_t)sizeof(struct l_dev *), compdev); Ndev = rmdupdev(&Sdev, Ndev, "char"); } else { (void) fprintf(stderr, "%s: no character devices found\n", Pn); Exit(1); } # if defined(HASDCACHE) /* * Write device cache file, as required. */ if (DCstate == 1 || (DCstate == 3 && dcrd)) write_dcache(); # endif /* defined(HASDCACHE) */ } # if defined(HASDCACHE) /* * rereaddev() - reread device names, modes and types */ void rereaddev() { (void) clr_devtab(); # if defined(DCACHE_CLR) (void) DCACHE_CLR(); # endif /* defined(DCACHE_CLR) */ readdev(1); DCunsafe = 0; } #endif /* defined(HASDCACHE) */ /* * rmdupdev() - remove duplicate (major/minor/inode) devices */ static int rmdupdev(dp, n, nm) struct l_dev ***dp; /* device table pointers address */ int n; /* number of pointers */ char *nm; /* device table name for error message */ { # if 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); Exit(1); } return(j); } # if defined(HASDCACHE) /* * vfy_dev() - verify a device table entry (usually when DCunsafe == 1) * * Note: rereads entire device table when an entry can't be verified. */ int vfy_dev(dp) struct l_dev *dp; /* device table pointer */ { struct stat sb; if (!DCunsafe || dp->v) return(1); if (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); } # endif /* defined(HASDCACHE) */ #else /* !defined(USE_LIB_READDEV) */ char rdev_d1[] = "d"; char *rdev_d2 = rdev_d1; #endif /* defined(USE_LIB_READDEV) */ lsof-4.86+dfsg.orig/Inventory0000555000175000017500000001003406732003006016371 0ustar nicholasnicholas#!/bin/sh # # Inventory -- take an inventory of the lsof distribution's 00MANIFEST # Establish trap and stty handling. ISIG=":" trap '$ISIG; exit 1' 1 2 3 15 stty -a 2>&1 | grep isig > /dev/null if test $? -eq 0 then stty -a 2>&1 | egrep -e -isig > /dev/null if test $? -eq 0 then ISIG="stty -isig" stty isig fi fi # Establish echo type -- Berkeley or SYSV. j=`echo -n ""` if test "X$j" = "X-n " then EC="\c" EO="" else EC="" EO="-n" fi # Display the introduction and basic explanation. cat << .CAT_MARK This configuration step (the Inventory script) takes inventory of the lsof distribution. The script runs for a minute or two while it checks that all the subdirectories, information files, scripts, header files and source files that should be present really are. It's not absolutely necessary that you take inventory, but it's a good idea to do it right after the lsof distribution has been unpacked. Once the inventory has been taken, this script creates the file ./.ck00MAN as a signal that the inventory step has been done. You can call the Inventory script directly at any time to take inventory. You can inhibit the inventory step permanently by creating the file ./.neverInv, and you can tell the Configure script to skip the inventory and customization steps with the -n option. .CAT_MARK END=0 while test $END = 0 do echo "" echo $EO "Do you want to take inventory (y|n) [y]? $EC" read ANS EXCESS if test "X$ANS" = "Xn" -o "X$ANS" = "XN" then exit 0 fi if test "X$ANS" = "Xy" -o "X$ANS" = "XY" -o "X$ANS" = "X" then END=1 else echo "" echo "Please answer y or n." fi done # The current directory is assumed to be the lsof distribution home. D=`pwd` # If .ck00MAN exists, the manifest has already been checked. # See if the caller wants to check it again. CK=$D/.ck00MAN if test -r $CK then cat << .CAT_MARK ====================================================================== The lsof distribution inventory in 00MANIFEST has already been checked. .CAT_MARK END=0 while test $END = 0 do echo "" echo $EO "Do you want to check the inventory again (y|n) [n]? $EC" read ANS EXCESS if test "X$ANS" = "Xn" -o "X$ANS" = "XN" -o "X$ANS" = "X" then exit 0 else if test "X$ANS" = "Xy" -o "X$ANS" = "XY" then END=1 else echo "" echo "Please answer y or n." fi fi done fi echo "" # See if manifest exists. Exit if it does not. if test ! -r 00MANIFEST then echo "FATAL: 00MANIFEST file not found or not readable; Inventory exits." echo "" exit 1 fi # Start the inventory. S="" echo "Conducting an inventory of the lsof distribution; this will take a while." echo "" echo $EO "Examining ${D}:$EC" ERR=0 OK=1 for i in `cat 00MANIFEST | sed 's/\*$//'` do if test "X$i" != "X" then j=`expr $i : '\(.*\)/$'` if test "X$j" != "X" -a "X$j" != "X0" then # Check a subdirectory reference. if test ! -d ${D}/${S}/$j then if test $OK = 1 then echo "" fi echo " Subdirectory ${S}/$j is missing. ++++" ERR=1 OK=0 fi else s=`expr $i : '\(.*\):$'` if test "X$s" != "X" -a "X$s" != "X0" then # Process a subdirectory change. if test $OK -eq 1 then echo " OK" fi OK=1 S=$s echo $EO "Examining $S:$EC" if test ! -d ${D}/$S then echo " ERROR" echo " Subdirectory $S is missing. ++++" ERR=1 OK=0 fi else # Process a file reference. if test ! -r ${D}/${S}/$i then if test $OK -eq 1 then echo " ERROR" fi echo " File ${S}/$i is missing. ++++" ERR=1 OK=0 fi fi fi fi done if test $OK -eq 1 then echo " OK" fi echo "" if test $ERR -ne 0 then echo "+++++++++++++++++++++++++++++++++++++++++++++++" echo "+ +" echo "+ SOME FILES OR DIRECTORIES MAY BE MISSING! +" echo "+ +" echo "+++++++++++++++++++++++++++++++++++++++++++++++" else echo "This lsof distribution seems to be complete." fi echo "" echo "" >> $CK exit $ERR lsof-4.86+dfsg.orig/00DCACHE0000444000175000017500000007423111741060266015460 0ustar nicholasnicholas Configuring The Device Cache File Path Contents A. Introduction and History B. Device Cache File Format 1. Integrity Checks 2. The Setgid and Setuid-root States C. Device Cache File Path Options 1. Path Named by ``-D'' 2. Path Named in Environment Variable 3. Default System-wide Path a. Build Procedure 4. Default Personal Path 5. Modified Default Personal Path D. Displaying the Default Path Appendix A, Unix Dialects Without a Device Cache Appendix B, Lsof Dialects and Their Permissions 1. Setuid-root Lsof Dialects 2. Setgid Lsof Dialects That Surrender Setgid Permission A. Introduction and History =========================== Lsof writes a file of information about the contents of the nodes in /dev (or /devices) to reduce its startup overhead on later calls. It does this for all Unix dialects, except those noted in Appendix A. This file, called the device cache file, enables lsof to avoid calling the kernel stat(2) function on every node in /dev (or /devices) from which it builds a table of correspondence between major/minor device numbers and device names. A full scan of /dev (or /devices) on some systems may involve calling the sometimes-slow stat(2) function 10,000 times or more. Furthermore, each stat(2) call consumes space in the kernel's name cache, forcing from it path name components that would be more useful when lsof tries to associate them with open files. While it's hard to question the usefulness of the device cache, it's also hard to decide where it should be written. When the feature was first added, the device cache file was written to /tmp, and its ownership was set to that of the real user ID (UID) under which the creating lsof process was run. However, to enable any process to update it when /dev (or /devices) changed, lsof set its modes to 0666, thus allowing anyone to read or write it. The writing of a world-readable and world-writable device cache file to any place has security weaknesses. A clever intruder who carefully preserves the integrity of the file might be able to remove devices that would prevent lsof from observing the intruder's files. A clever intruder might also be able to put a symbolic link in place and trick lsof into writing to the link's destination with its effective permissions, thus bypassing the real user's (possibly weaker) permissions. Later the location of the device cache file was changed. It was converted to a personal file, located in the home directory of each real UID that executed lsof, and owned by that UID. Thus it was no longer possible for one user to affect lsof's access to the device cache file, nor was it possible for a user to mount a symbolic link attack on a restricted file, but the result was that each lsof user had a private copy of the device cache file. The device cache file feature has undergone some further refinements in path name formation to reach its present state. This documentation describes the path name formation options open to the lsof builder and user after those refinements, and how lsof attempts to insure that none of the options presents a security risk. B. Device Cache File Format =========================== The device cache file is a flat file of ASCII text. It has an initial statement of how many sections the file might contain -- the possible sections are character devices, block devices, clone devices, pseudo devices, and checksum. The character devices and checksum sections are always present. Each section has a header that numbers the entries in the section. The last section is a checksum section that contains a 16 bit cyclic redundancy (CRC) checksum of everything in the file but the checksum section itself. Lsof always sets the permission modes of the device cache file to 0600, and the owner to the real UID of the process that executes lsof; the group, the real group ID (GID) of the lsof process. Setting the permission modes to 0600 means that a system-wide device cache file won't be usable unless the procedure that builds it changes the modes after lsof has written it. A suitable procedure for building a system-wide device cache that shows how to adjust these inadequate permission modes is given in the Default System-wide Path section. B.1. Integrity Checks ===================== When lsof opens the device cache file it makes these integrity checks: 1. Lsof must gain permission from access(2) to be able to open the file for reading. If lsof is writing the file, it usually cedes permission control to the applicable directory and file modes and ownerships. (Some additional checks apply and they're described in the sections on path options.) By explicit design lsof never writes to the system-wide device cache file, even when the real UID of its process is root. The system-wide device cache file must be written with a root-owned procedure via the ``-D[b|u'' options -- i.e., under the system administrator's control. (See the Build Procedure sub-section of the Default System-wide Path section.) 2. The device cache file's modes must be 0600 (0644 if lsof is reading a system-wide device cache file) and its size must be non-zero. 3. There must be a correctly formatted section count line at the beginning of the file. 4. Each section must have a header line with a count that properly numbers the lines in the section. The first words of legal section titles are "device", "block", "clone", "pseudo", and "CRC". 5. The lines of a section must have the proper format. 6. All lines are included in a 16 bit CRC, and it is recorded in a non-checksummed section line at the end of the file. 7. The checksum computed when the file is read must match the checksum recorded when the file was written. 8. The checksum section line must be followed by end-of- information. 9. Lsof must be able to get matching results from stat(2) on a randomly chosen entry of the device section. B.2. The Setgid and Setuid-root States ====================================== There are two fundamental ways in which lsof is granted access to restricted system resources. Both access methods are related to the effective permissions given the lsof binary or executable. The first and preferable way to grant lsof access to system resources through the permissions endowed on its executable is the giving of set group ID (setgid) permission. The group is the one that has permission to read the kernel memory and swap devices -- e.g., /dev/kmem, /dev/mem, /dev/swap, etc. This method of granting access is called setgid mode because it enables lsof to run with an effective group ID set to the one granted by the permissions of its executable file and by the group that owns the executable file. See the getegid(2) man page for a further discussion of effective group ID. Usually lsof only needs setgid permission to open access to the kernel memory files. After they're open, lsof drops its setgid permission. The second and least preferable way to grant lsof access to system resources through the permissions endowed on its executable is the giving of set user ID to root (setuid-root) permission. This is much too strong a permission, but necessary: to use the -X option fully for the version of lsof for AIX 5 and above; to use the version of lsof for HP-UX 11.11 and above; and to use the version of lsof for Linux 2.1.72 and above. These lsof implementations require setuid-root permission to be able to access restricted resources -- e.g., the individual files of the /proc file system. (But note that the setuid-root Linux lsof doesn't need and has no device cache support.) Lsof never drops setuid-root permission, because it needs that power throughout its execution. However, when the lsof process is setuid-root, lsof disallows these device cache file path options: 1. It ignores the ``-D[b|r|u]'' options. It accepts only the ``-Di'' and ``-Dr'' options. 2. It refuses to recognize a path supplied via an environment variable. 3. It refuses to accept an additional path component from an environment variable to be inserted in the middle of a personal device cache file path. Each restriction is imposed because setuid-root power might allow a malicious user to form a device cache file path that would give read access to a normally inaccessible place (That's bad enough.), or write access to a critical system file (That's the worst case.) There is one further state that lsof can enter that is slightly different from the setuid-root and setgid states. That state occurs when lsof is being run from a root shell -- i.e., the lsof real user ID is root. To avoid accidental complications, when lsof is in this state, it ignores all environment variable options. In the rest of this document you will find more detailed discussion of the special restrictions caused by the type of permission that has been given the lsof executable. C. Device Cache File Path Options ================================= Lsof offers five options for constructing the path to the device cache file. Each has special conditions and safeguards that surround its use. The options are: 1. A device cache file that is named in the component of the parameters of lsof's ``-D'' option. ========================================================= * This is a default option of the lsof distribution. * * * * Paths specified with this option are read-only unless * * the real UID of the lsof process is root (0), or the * * lsof process is able to surrender setgid permission * * (See Appendix B) and it is not setuid-root. * ========================================================= 2. A device cache file whose name is specified by an environment variable. ========================================================= * This is a default option of the lsof distribution. * * * * This option is enabled when the lsof dialect is able * * to surrender setgid permission (See Appendix B.), and * * the lsof process is not setuid-root. * * * * The environment variable path is read-only if the * * lsof process does not surrender setgid permission * * (See Appendix B.) * ========================================================= 3. A system-wide default device cache file, located at a path determined by the builder of lsof. The lsof builder is also responsible for building the device cache file, using a different lsof path formation option at a suitable time -- e.g., when the system is booted. ========================================================= * This is option is disabled by default in the lsof * * distribution. * * * * The path specified with this option is read-only. * ========================================================= 4. A default personal device cache file, located in the UID's home directory. ========================================================= * This is a default option of the lsof distribution. * ========================================================= 5. A personal device cache file whose name is modified by an environment variable. ========================================================= * This is a default option of the lsof distribution. * * * * The modified personal path is read-only if the lsof * * process does not surrender setgid permission. * * * * This option is disabled when the lsof process is * * setuid-root or its real UID is root (0). * ========================================================= When there are multiple choices for the device cache file path, lsof chooses from the above list in the order the list is given, subject to restrictions based on the effective group and user IDs that are in effect. Each possible path name is discussed in a later section that describes the restrictions that apply to it and the method for building lsof to use it. In one special case lsof will use two paths in order. When a system-wide device cache file is enabled, and lsof finds that it doesn't exist, lsof will attempt to use a personal device cache file. C.1. Path Named by ``-D'' ========================= The ``-D[b|r|u]'' option can name a path for the device cache file where it is unconditionally built (`b'); read, but never rebuilt (`r'); and read and rebuilt, if necessary (`u'). If the lsof process is setuid-root, no path may be specified with the ``-D'' option -- i.e., only the `i' function is accepted. The `r' option may be used if it doesn't have a path argument. If the lsof process is not setuid-root, nor is the real UID of the lsof process root, a path may accompany the `b', `r', and `u' functions if the lsof process surrenders setgid permission. (See Appendix B.) If the process doesn't surrender setgid permission, then a path may accompany only `r'. Lsof's permission to access a device cache file at a path specified with ``-D[b|r|u]'' depends completely on the permission modes and ownerships of the file and its directory components. When the real UID of the lsof process is root (0), paths may be specified with ``-D[b|r|u]''. ==================================================================== * * * The ``-D[b|r|u]'' option is enabled by default in the lsof * * distribution by the following definition in the dialect's * * machine.h header file: * * * * #define HASDCACHE 1 * * * * To disable all device cache file options, including all ``-D'' * * forms, change the above line in the dialect's machine.h file to: * * * * /* #define HASDCACHE 1 */ * * * * or remove it. * * * * The ``-D[b|r|u]'' options are disabled when the lsof * * process is setuid-root. If the lsof process isn't setuid-root, * * nor is its real UID root (0), and if the lsof process surrenders * * setgid permission, ``-D[b|r|u]'' may be accompanied by a path. * * * * A path may accompany ``-D[b|u]'' when the real UID of the lsof * * process is root. * * * * ``-Dr'' without a path name argument is always acceptable. * * * ==================================================================== C.2. Path Named in Environment Variable ======================================= A device cache file path may be declared in an environment variable. This option is defined in the dialect's machine.h header file with the HASENVDC definition. The value of the HASENVDC definition is the environment variable's name. Lsof will use the value of the environment variable named by HASENVDC for the device cache file path unless either of the following conditions apply: 1. The lsof process is in the setuid-root state. or 2. The effective and real UIDs of the lsof process are root (0). Lsof uses the value of the HASENVDC environment variable as the device cache file path after it senses there is no path declared by a ``-D'' option. A path from an environment variable is read-only unless the lsof process surrenders setgid permission. (See Appendix B.) ==================================================================== * * * The path name environment variable option is enabled by default, * * and the environment variable is named LSOFDEVCACHE in the lsof * * distribution by the following definition in the dialect's * * machine.h header file: * * * * #define HASENVDC "LSOFDEVCACHE" * * * * To disable the path name environment variable option, change * * the above line in the dialect's machine.h header file to: * * * * /* #define HASENVDC "LSOFDEVCACHE" */ * * * * or remove it. To change the name of the environment variable, * * change the quoted value of the HASENVDC definition -- e.g., this * * form changes the environment variable name to "FOOBAR": * * * * #define HASENVDC "FOOBAR" * * * * You can disable the path name environment option by disabling * * all device cache file processing when you remove or by disabling * * the HASDCACHE definition in the dialect's machine.h header file. * * * * The path name environment option is disabled when the lsof * * process is setuid-root or when the real UID of the lsof process * * is root (0). * * * * The path named in an environment variable is read-only unless * * the lsof process surrenders setgid permission. (See Appendix * * B.) * * * ==================================================================== C.3. Default System-wide Path ============================= When a default system-wide device cache file path is defined (It's not enabled by default in the lsof distribution.), lsof will use it after it discovers no path has been specified by a ``-D'' option and no path has been specified in the environment variable named in the string #define HASENVDC of the dialect's machine.h header file. Lsof must be able to open the system-wide device cache file -- i.e., it must have read access to the file and search access to the directories that lead it. As part of its integrity checks, lsof requires that the system-wide device cache file's permission modes be 0644. When lsof discovers that the named system-wide device cache file doesn't exist, it will attempt to open a personal device cache file should that path formation option be enabled. This is the *only* case where lsof will attempt to use two device cache file paths. The system-wide device cache file is read-only; lsof will never attempt to write to it. However, when the real UID of the lsof process is root, that process may name the system-wide device cache file with ``-D[b|u]''. ==================================================================== * * * The system-wide file path option is disabled by default in the * * lsof distribution. This place-marking definition in a dialect's * * machine.h header file may be altered to enable a system-wide * * device cache file path: * * * * /* #define HASSYSDC "/your/choice/of/path" */ * * * * To enable the system-wide name option, declaring that its path * * is ``/foo/bar/lsof.dc'', change the above line in the dialect's * * machine.h header file to: * * * * #define HASSYSDC "/foo/bar/lsof.dc" * * * * or change the quoted string of the definition to the path of * * your choice. * * * * You can disable the path name environment option by disabling * * all device cache file processing when you remove or disable the * * HASDCACHE definition in the dialect's machine.h header file. * * * * The system-wide device cache file is read-only. * * * ==================================================================== C.3.a. Build Procedure ====================== The system administrator must build the system-wide device cache file at an appropriate time -- e.g., each time the system is booted, and each time a node is added, deleted or modified in /dev (or /devices). The procedure that builds the system-wide device cache file must use lsof's ``-D[b|u]'' options to build the file, and must change the file's permission modes to 0644 after it has been built. Here's a simple shell script procedure to build a system-wide device cache file. It assumes: 1. The Unix dialect's kernel supports the interpreter script execution option -- i.e., a script whose first line has the form ``#!''. 2. The chmod, echo, rm, sh, and test programs are located in ``/bin''. 3. The string value of the HASSYSDC definition in the dialect's machine.h header file is the path ``/your/choice/of/path''. 4. The lsof executable is located in ``/usr/local/etc''. #!/bin/sh # # Simple script to build a system-wide device cache file # for lsof. HASSYSDC=/your/choice/of/path /bin/rm -f $HASSYSDC /usr/local/etc/lsof -Du$HASSYSDC > /dev/null 2>&1 if /bin/test $? -ne 0 then /bin/echo "WARNING: failed to create $HASSYSDC" exit 1 fi /bin/chmod 0644 $HASSYSDC exit 0 The invocation of lsof uses the ``-Du$HASSYSDC'' option to read the device cache file and recreate it if necessary. The invocation can be made more efficient if a known process PID -- e.g., ``-p1'' -- can be specified. However, if that PID is not always active when lsof is called, lsof might set its exit code non-zero, causing the subsequent test to believe that the lsof call failed. When in doubt, omit the PID specification and accept the extra lsof processing time for reporting and discarding all open file information. C.4. Default Personal Path ========================== The default personal path option is defined by default in the lsof distribution. The path is formed of the home directory of the real UID of the lsof process, followed optionally by the contents of the HASPERSDCPATH environment variable, followed by ``.lsof_'', followed by the first component (characters up to the first period) of the name returned by gethostname(2). If gethostname(2) returns nothing, then nothing will follow the ``.lsof_'' string. If the first character of what gethostname(2) returns is a `.', then all the gethostname(2) value will follow the ``/lsof_'' string. (See the ``%l'' conversion for a way to make lsof include the entire host name in the path.) ==================================================================== * * * The personal path option is enabled by default in the lsof * * distribution. The HASPERSDC #define in a dialect's machine.h * * header is a format specification that tells lsof how to form the * * personal device cache file path. The conversions in the format * * specification begin with `%' , ala the printf(3) function of the * * standard I/O library. These conversions are supported: * * * * ``%%'' causes a single `%' to appear in the path. * * * * ``%0'' is a separator that marks the beginning of a path * * for a setuid-root lsof process or one whose real * * UID is 0. When lsof reaches this conversion and * * the process is setuid-root or has a real UID of * * root, it erases any previously formed path and * * restarts with the next HASPERSDC format character. * * If lsof reaches this conversion and the process is * * not setuid-root and its real UID is not root, path * * formation is ended. * * * * ``%h'' causes the home directory of the real UID of the * * lsof process to appear in the path. * * * * ``%l'' causes the full name returned by gethostname(2) to * * appear in the path. * * * * ``%L'' causes the first component of the name returned by * * gethostname(2) to appear in the path. The first * * component is defined to be what appears to the * * left of the first `.'. If nothing appears to the * * left then everything will appear in the path. * * * * ``%p'' causes the value of (HASPERSDCPATH) from the * * process environment to appear in the path. If the * * (HASPERSDCPATH) value doesn't end in a '/', one * * will be added. * * * * ``%u'' causes the login name associated with the real UID * * of the lsof process to appear in the path. * * * * ``%U'' causes the real UID of the lsof process, converted * * to a decimal string, to appear in the path. * * * * All other characters are copied from the format to the * * path. CAUTION: THINK VERY CAREFULLY ABOUT THE EFFECT OF * * USING CHARACTERS THAT FORM AN ABSOLUTE COMPONENT LIKE * * ``/tmp'' IN THE FORMAT. Consider what power your dialect * * might have (e.g., if it is setuid-root) when lsof must * * create a device cache file at the path. Consider using a * * ``%0'' conversion to declare an alternate path for lsof * * processes that are setuid-root or whose real uid is root. * * See the "How do I put the personal device cache file in * * /tmp?" question and answer in 00FAQ for an explanation of * * this example: * * * * #define HASPERSDC "/tmp/.lsof_%u_%l_pers%0%h/.lsof_%L" * * * * This is the format specification that appears in the machine.h * * header files of the lsof distribution: * * * * #define HASPERSDC "%h/%p.lsof_%L" * * * * It causes the path to be formed from the home directory of the * * real UID of the lsof process (``%h''), followed by `/', followed * * by the contents of the environment variable named by * * HASPERSDCPATH and a trailing `/', as needed (``%p''), followed * * by the string ``.lsof_'', and terminated with the first * * component of the host's name (``%L''). * * * * To change the personal path option, change the HASPERSDC string * * and recompile lsof. To disable the personal path option, remove * * or disable HASPERSDC. The personal path option is disabled when * * HASDCACHE is not defined. * * * ==================================================================== C.5. Modified Default Personal Path =================================== The modified default personal path form is a special case of the default personal path. In this form the value of the environment variable named by the HASPERSDCPATH #define is inserted in the personal path when the ``%p'' conversion appears in the HASPERSDC format specification. This allows, for example, the lsof user to move personal device cache files to another branch of the home directory, perhaps to a sub-directory where multiple device cache files may appear from different machines that use the same NFS- mounted home directory. The HASPERSDCPATH definition of the dialect's machine.h header file names the environment variable. By default in the lsof distribution it is LSOFPERSDCPATH. The modified personal path component is ignored when lsof process is setuid-root is root, lest it be maliciously or accidentally used in some convoluted form to access paths the real UID cannot. The modified personal path component is also ignored when the real UID of the lsof process is root (0), so that lsof will not accidentally use a personal environment value. If the lsof process surrenders setgid permission (See Appendix B.), lsof can read from and write to the modified personal path. If, however, the lsof process doesn't surrender setgid permission, the modified personal path is read-only. If your dialect runs setuid-root or doesn't surrender its setgid permission, and you want to use the LSOFPERSDCPATH environment variable to address a collection of device cache files in a subdirectory, you will have to gather the collection in the subdirectory yourself with shell copy or move commands. ==================================================================== * * * The modified personal path option is enabled by default in the * * lsof distribution with these definitions in the dialect's * * machine.h header file: * * * * #define HASPERSDCPATH "LSOFPERSDCPATH" * * and * * #define HASPERSDC "%h/%p.lsof_%L" * * * * The value of the definition is the name of the environment * * variable that contains the modified personal path name * * component that is inserted in the personal path when ``%p'' * * appears in HASPERSDC. See the Default Personal Path section * * for a complete description of the ``%p'' conversion. * * * * To disable the modified personal path name component, disable * * the HASPERSDCPATH definition in the dialect's machine.h header * * file -- e.g., change it to: * * * * /* #define HASPERSDCPATH "LSOFPERSDCPATH" */ * * * * or remove the definition altogether. If you do this, don't * * forget to remove any ``%p'' conversion from HASPERSDC. * * * * The modified personal path option is disabled when HASDCACHE is * * not defined. * * * * The modified personal path environment variable value is ignored * * when the lsof process is setuid-root or when the real UID of * * the lsof process is root (0). * * * * The modified personal path is read-only when the lsof process * * doesn't surrender its setgid permission. * * * ==================================================================== D. Displaying the Default Path ============================== Whatever device cache file path formation options you decide to use, remember that the lsof help output, displayed in response to its ``-h'' or ``-?'' help options, will display the read-mode default (the highest numbered) path that lsof has been enabled to form from which it will read. Since some paths are read-only, the path displayed in help option output may not be the one to which lsof will write, should that become necessary. To see the read-only and write device cache file paths, environment variable names, and the personal device cache file format specification (HASPERSDC), use the -D? option. Appendix A, Unix Dialects Without a Device Cache ================================================ Linux lsof implementations that obtain their information from files in the /proc file system do not have device cache support. Generally lsof for Linux versions 2.1.72 and greater are /proc based. Appendix B, Lsof Dialects and Their Permissions =============================================== These are the permissions recommended in the lsof distribution. Appendix B.1 Setuid-root Lsof Dialects ====================================== These dialect versions of lsof need root permission. For general use they may have to be installed setuid-root. Apple Darwin 9 and Mac OS X 10.[567] HP-UX 11.11 and 11.23 Linux (no device cache support needed) Appendix B.2 Setgid Lsof Dialects That Surrender Setgid Permission ================================================================== Lsof versions for these dialects have WILLDROPGID defined in their machine.h header files. AIX 5.[12] and 5.3-ML1 FreeBSD 4.x, 4.1x, 5.x and [6789].x for x86-based systems FreeBSD 5.x, [6789].x fnd 10.xor Alpha, AMD64 and Sparc64-a based systems 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 April 10, 2012 lsof-4.86+dfsg.orig/proto.h0000444000175000017500000002526311631741204015777 0ustar nicholasnicholas/* * 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.36 2011/09/07 19:13:49 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)); _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,(int xv)) exiting; _PROTOTYPE(extern void find_ch_ino,(void)); _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_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 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 xv, 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) */ lsof-4.86+dfsg.orig/lsof_fields.h0000444000175000017500000001126511424322553017124 0ustar nicholasnicholas/* * 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.12 2010/07/29 15:59:28 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: * * * 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" #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" #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_NAME 'n' #define LSOF_FIX_NAME 14 #define LSOF_FNM_NAME "comment, name, Internet addresses" #define LSOF_FID_NI 'N' #define LSOF_FIX_NI 15 #define LSOF_FNM_NI "file struct node ID as 0x" #define LSOF_FID_OFFSET 'o' #define LSOF_FIX_OFFSET 16 #define LSOF_FNM_OFFSET "file offset as 0t or 0x" #define LSOF_FID_PID 'p' #define LSOF_FIX_PID 17 #define LSOF_FNM_PID "process ID (PID)" #define LSOF_FID_PGID 'g' #define LSOF_FIX_PGID 18 #define LSOF_FNM_PGID "process group ID (PGID)" #define LSOF_FID_PROTO 'P' #define LSOF_FIX_PROTO 19 #define LSOF_FNM_PROTO "protocol name" #define LSOF_FID_RDEV 'r' #define LSOF_FIX_RDEV 20 #define LSOF_FNM_RDEV "raw device number as 0x" #define LSOF_FID_PPID 'R' #define LSOF_FIX_PPID 21 #define LSOF_FNM_PPID "paRent PID" #define LSOF_FID_SIZE 's' #define LSOF_FIX_SIZE 22 #define LSOF_FNM_SIZE "file size" #define LSOF_FID_STREAM 'S' #define LSOF_FIX_STREAM 23 #define LSOF_FNM_STREAM "stream module and device names" #define LSOF_FID_TYPE 't' #define LSOF_FIX_TYPE 24 #define LSOF_FNM_TYPE "file type" #define LSOF_FID_TCPTPI 'T' #define LSOF_FIX_TCPTPI 25 #define LSOF_FNM_TCPTPI "TCP/TPI info" #define LSOF_FID_UID 'u' #define LSOF_FIX_UID 26 #define LSOF_FNM_UID "user ID (UID)" #define LSOF_FID_ZONE 'z' #define LSOF_FIX_ZONE 27 #define LSOF_FNM_ZONE "zone name" #define LSOF_FID_CNTX 'Z' #define LSOF_FIX_CNTX 28 #define LSOF_FNM_CNTX "security context" #define LSOF_FID_TERM '0' #define LSOF_FIX_TERM 29 #define LSOF_FNM_TERM "(zero) use NUL field terminator instead of NL" #endif /* !defined(LSOF_FORMAT_H) */ lsof-4.86+dfsg.orig/00PORTING0000444000175000017500000017621511741060407015675 0ustar nicholasnicholas Guide to Porting lsof 4 to Unix OS Dialects ********************************************************************** | The latest release of lsof is always available via anonymous ftp | | from lsof.itap.purdue.edu. Look in pub/lsof.README for its | | location. | ********************************************************************** Contents How Lsof Works /proc-based Linux Lsof -- a Different Approach General Guidelines Organization Source File Naming Conventions Coding Philosophies Data Requirements Dlsof.h and #include's Definitions That Affect Compilation Options: Common and Special Defining Dialect-Specific Symbols and Global Storage Coding Dialect-specific Functions Function Prototype Definitions and the _PROTOTYPE Macro The Makefile The Mksrc Shell Script The MkKernOpts Shell Script Testing and the lsof Test Suite Where Next? How Lsof Works -------------- Before getting on with porting guidelines, just a word or two about how lsof works. Lsof obtains data about open UNIX dialect files by reading the kernel's proc structure information, following it to the related user structure, then reading the open file structures stored (usually) in the user structure. Typically lsof uses the kernel memory devices, /dev/kmem, /dev/mem, etc. to read kernel data. Lsof stores information from the proc and user structures in an internal, local proc structure table. It then processes the open file structures by reading the file system nodes that lie behind them, extracting and storing relevant data in internal local file structures that are linked to the internal local process structure. Once all data has been gathered, lsof reports it from its internal, local tables. There are a few variants on this subject. Some systems don't have just proc structures, but have task structures, too, (e.g., NeXTSTEP and OSF/1 derivatives). For some dialects lsof gets proc structures or process information (See "/proc-based Linux Lsof -- a Different Approach) from files of the /proc file system. It's not necessary for lsof to read user structures on some systems (recent versions of HP-UX), because the data lsof needs can be found in the task or proc structures. In the end lsof gathers the same data, just from slightly different sources. /proc-based Linux Lsof -- a Different Approach ============================================== For a completely different approach to lsof construction, take a look at the /proc-based Linux sources in .../dialects/linux/proc. (The sources in .../dialects/linux/kmem are for a traditional lsof that uses /dev/kmem to read information from kernel structures.) The /proc-based lsof obtains all its information from the Linux /proc file system. Consequently, it is relatively immune to changes in Linux kernel structures and doesn't need to be re-compiled each time the Linux kernel version changes. There are some down-sides to the Linux /proc-based lsof: * It must run setuid-root in order to be able to read the /proc file system branches for all processes. In contrast, the /dev/kmem-based Linux lsof usually needs only setgid permission. * It depends on the exact character format of /proc files, so it is sensitive to changes in /proc file composition. * It is limited to the information a /proc file system implementor decides to provide. For example, if a /proc/net/ file lacks an inode number, the /proc-based lsof can't connect open socket files to that protocol. Another deficiency is that the /proc-based may not be able to report file offset (position) information, when it isn't available in the /proc//fd/ entry for a file. In contrast the /dev/kmem-based lsof has full access to kernel structures and "sees" new data as soon as it appears. Of course, that new data requires that lsof be recompiled and usually also requires changes to lsof. Overall the switch from a /dev/kmem base to a /proc one is an advantage to Linux lsof. The switch was made at lsof revision 4.23 for Linux kernel versions 2.1.72 (approximately) and higher. The reason I'm not certain at which Linux kernel version a /proc-based lsof becomes possible is that the /proc additions needed to implement it have been added gradually to Linux 2.1.x in ways that I cannot measure. /proc-based lsof functions in many ways the same as /dev/kmem-based lsof. It scans the /proc directory, looking for / subdirectories. Inside each one it collects process-related data from the cwd, exe, maps, root, and stat information files. It collects open file information from the fd/ subdirectory of each / subdirectory. The lstat(2), readlink(2), and stat(2) system calls gather information about the files from the kernel. Lock information comes from /proc/locks. It is matched to open files by inode number. Mount information comes from /proc/mounts. Per domain protocol information comes from the files of /proc/net; it's matched to open socket files by inode number. The Linux /proc file system implementors have done an amazing job of providing the information lsof needs. The /proc-based lsof project has so far generated only two kernel modification: * A modification to /usr/src/linux/net/ipx/af_ipx.c adds the inode number to the entries of /proc/net/ipx. Jonathan Sergent did this kernel modification. It may be found in the .../dialects/linux/proc/patches subdirectory of the lsof distribution. * An experimental modification to /usr/src/linux/fs/stat.c allows lstat(2) to return file position information for /proc//fd/ files. Contact me for this modification. One final note about the /proc-based Linux lsof: it doesn't need any functions from the lsof library in the lib/ subdirectory. General Guidelines ------------------ These are the general guidelines for porting lsof 4 to a new Unix dialect: * Understand the organization of the lsof sources and the philosophies that guide their coding. * Understand the data requirements and determine the methods of locating the necessary data in the new dialect's kernel. * Pick a name for the subdirectory in lsof4/dialects for your dialect. Generally I use a vendor operating system name abbreviation. * Locate the necessary header files and #include them in the dialect's dlsof.h file. (You may not be able to complete this step until you have coded all dialect-specific functions.) * Determine the optional library functions of lsof to be used and set their definitions in the dialect's machine.h file. * Define the dialect's specific symbols and global storage in the dialect's dlsof.h and dstore.c files. * Code the dialect-specific functions in the appropriate source files of the dialect's subdirectory. Include the necessary prototype definitions of the dialect- specific functions in the dproto.h file in the dialect's subdirectory. * Define the dialect's Makefile and source construction shell script, Mksrc. * If there are #define's that affect how kernel structures are organized, and those #define's are needed when compiling lsof, build a MkKernOpts shell script to locate the #define's and supply them to the Configure shell script. Organization ------------ The code in a dialect-specific version of lsof comes from three sources: 1) functions common to all versions, located in the top level directory, lsof4; 2) functions specific to the dialect, located in the dialect's subdirectory -- e.g., lsof4/dialects/sun; 3) functions that are common to several dialects, although not to all, organized in a library, liblsof.a. The functions in the library source can be selected and customized with definitions in the dialect machine.h header files. The tree looks like this: lsof4 ----------------------+ 3) library -- | \ lsof4/lib 1) fully common functions + \ e.g., lsof4/main.c + lsof4/dialects/ / / / / \ + + + + + 2) dialect-specific subdirectories -- e.g., lsof4/dialects/sun The code for a dialect-specific version is constructed from these three sources by the Configure shell script in the top level lsof4 directory and definitions in the dialect machine.h header files. Configure uses the Mksrc shell script in each dialect's subdirectory, and may use an optional MkKernOpts shell script in selected dialect subdirectories. Configure calls the Mksrc shell script in each dialect's subdirectory to assemble the dialect-specific sources in the main lsof directory. Configure may call MkKernOpts to determine kernel compile-time options that are needed for compiling kernel structures correctly for use by lsof. Configure puts the options in a dialect-specific Makefile it build, using a template in the dialect subdirectory. The assembly of dialect-specific sources in the main lsof directory is usually done by creating symbolic links from the top level to the dialect's subdirectory. The LSOF_MKC environment variable may be defined prior to using Configure to change the technique used to assemble the sources -- most commonly to use cp instead of ln -s. The Configure script completes the dialect's Makefile by adding string definitions, including the necessary kernel compile-time options, to a dialect skeleton Makefile while copying it from the dialect subdirectory to the top level lsof4 directory. Optionally Makefile may call the dialect's MkKernOpts script to add string definitions. When the lsof library, lsof4/lib/liblsof.a, is compiled its functions are selected and customized by #define's in the dialect machine.h header file. Source File Naming Conventions ------------------------------ With one exception, dialect-specific source files begin with a lower case `d' character -- ddev.c, dfile.c, dlsof.h. The one exception is the header file that contains dialect-specific definitions for the optional features of the common functions. It's called machine.h for historical reasons. Currently all dialects use almost the same source file names. One exception to the rule happens in dialects where there must be 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 Customize does some customization of the selected lsof dialect Inventory takes an inventory of the files in an lsof distribution version the version number dialects/ the dialects subdirectory 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 header files main.c common main function for lsof 4 misc.c common miscellaneous functions -- e.g., special versions of stat() and readlink() node.c common node reading functions -- readinode(), readvnode() print.c common print support functions proc.c common process and file structure functions proto.h common prototype definitions, including the definition of the _PROTOTYPE() macro store.c common global storage version.h the current lsof version number, derived from the file version by the Makefile usage.c functions to display lsof usage panel These are the dialect-specific files: Makefile the Makefile skeleton Mksrc a shell script that assists the Configure script in configuring dialect sources MkKernOpts an optional shell script that identifies kernel compile-time options for selected dialects -- e.g., Pyramid DC/OSx and Reliant UNIX ddev.c device support functions -- readdev() -- may be eliminated by functions from lsof4/lib/ dfile.c file processing functions -- may be eliminated by functions from lsof4/lib/ dlsof.h dialect-specific header file -- contains #include's for system header files and dialect-specific global storage declarations dmnt.c mount support functions -- may be eliminated by functions from lsof4/lib/ dnode.c node processing functions -- e.g., for gnode or vnode dnode?.c additional node processing functions, used when node header files have duplicate and conflicting element names. dproc.c functions to access, read, examine and cache data about dialect-specific process structures -- this file contains the dialect-specific "main" function, gather_proc_info() dproto.h dialect-specific prototype declarations dsock.c dialect-specific socket processing functions dstore.c dialect-specific global storage -- e.g., the nlist() structure machine.h dialect specific definitions of common function options -- e.g., a HASINODE definition to activate the readinode() function in lsof4/node.c The machine.h header file also selects and customizes the functions of lsof4/lib/. These are the lib/ files. Definitions in the dialect machine.h header files select and customize the contained functions that are to be compiled and archived to liblsof.a. Makefile.skel is a skeleton Makefile, used by Configure to construct the Makefile for the lsof library. cvfs.c completevfs() function USE_LIB_COMPLETEVFS selects it. CVFS_DEVSAVE, CVFS_NLKSAVE, CVFS_SZSAVE, and HASFSINO customize it. dvch.c device cache functions HASDCACHE selects them. DCACHE_CLONE, DCACHE_CLR, DCACHE_PSEUDO, DVCH_CHOWN, DVCH_DEVPATH, DVCH_EXPDEV, HASBLKDEV, HASENVDC, HASSYSDC, HASPERSDC, HASPERSDCPATH, and NOWARNBLKDEV customize them. fino.c find block and character device inode functions HASBLKDEV and USE_LIB_FIND_CH_INO select them. isfn.c hashSfile() and is_file_named() functions USE_LIB_IS_FILE_NAMED selects it. lkud.c device lookup functions HASBLKDEV and USE_LIB_LKUPDEV select them. pdvn.c print device name functions HASBLKDEV and USE_LIB_PRINTDEVNAME select them. prfp.c process_file() function USE_LIB_PROCESS_FILE selects it. FILEPTR, DTYPE_PIPE, HASPIPEFN, DTYPE_GNODE, DTYPE_INODE, DTYPE_PORT, DTYPE_VNODE, HASF_VNODE, HASKQUEUE, HASPRIVFILETYPE, HASPSXSHM and HASPSXSEM customize it. ptti.c print_tcptpi() function USE_LIB_PRINT_TCPTPI selects it. HASSOOPT, HASSBSTATE, HASSOSTATE, AHSTCPOPT, HASTCPTPIQ and HASTCPTPIW customize it. rdev.c readdev() function USE_LIB_READDEV selects it. DIRTYPE, HASBLKDEV, HASDCACHE, HASDNAMLEN, RDEV_EXPDEV, RDEV_STATFN, USE_STAT, and WARNDEVACCESS customize it. rmnt.c readmnt() function USE_LIB_READMNT selects it. HASFSTYPE, MNTSKIP, RMNT_EXPDEV, RMNT_FSTYPE, and MOUNTS_FSTYPE customize it. rnam.c BSD format name cache functions HASNCACHE and USE_LIB_RNAM select them. HASFSINO, NCACHE, NCACHE_NC_CAST, NCACHE_NM, NCACHE_NMLEN, NCACHE_NODEADDR, NCACHE_NODEID, NCACHE_NO_ROOT, NCACHE_NXT, NCACHE_PARADDR, NCACHE_PARID, NCACHE_SZ_CAST, NCHNAMLEN, X_NCACHE, and X_NCSIZE, customize them. rnch.c Sun format name cache functions HASNCACHE and USE_LIB_RNCH select them. ADDR_NCACHE, HASDNLCPTR, HASFSINO, NCACHE_DP, NCACHE_NAME, NCACHE_NAMLEN, NCACHE_NEGVN, NCACHE_NODEID, NCACHE_NXT, NCACHE_PARID, 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. Coding Philosophies ------------------- A few basic philosophies govern the coding of lsof 4 functions: * Use as few #if/#else/#endif constructs as possible, even at the cost of nearly-duplicate code. When #if/#else/#endif constructs are necessary: o Use the form #if defined(s) in preference to #ifdef to allow easier addition of tests to the #if. o Indent them to signify their level -- e.g., #if /* level one */ # if /* level two */ # endif /* level two */ #else /* level one */ #endif /* level one */ o Use ANSI standard comments on #else and #endif statements. * Document copiously. * Aim for ANSI-C compatibility: o Use function prototypes for all functions, hiding them from compilers that cannot handle them with the _PROTOTYPE() macro. o Use the compiler's ANSI conformance checking wherever possible -- e.g., gcc's -ansi option. Data Requirements ----------------- Lsof's strategy in obtaining open file information is to access the process table via its proc structures, then obtain the associated user area and open file structures. The open file structures then lead lsof to file type specific structures -- cdrnodes, fifonodes, inodes, gnodes, hsfsnodes, pipenodes, pcnodes, rnodes, snodes, sockets, tmpnodes, and vnodes. The specific node structures must yield data about the open files. The most important items and device number (raw and cooked) and node number. (Lsof uses them to identify files and file systems named as arguments.) Link counts and file sizes are important, too, as are the special characteristics of sockets, pipes, FIFOs, etc. This means that to begin an lsof port to a new Unix dialect you must understand how to obtain these structures from the dialect's kernel. Look for kernel access functions -- e.g., the AIX readx() function, Sun and Sun-like kvm_*() functions, or SGI's syssgi() function. Look for clues in header files -- e.g. external declarations and macros. If you have access to them, look at sources to programs like ps(1), or the freely available monitor and top programs. They may give you important clues on reading proc and user area structures. An appeal to readers of dialect-specific news groups may uncover correspondents who can help. Careful reading of system header files -- e.g., -- may give hints about how kernel storage is organized. Look for global variables declared under a KERNEL or _KERNEL #if. Run nm(1) across the kernel image (/vmunix, /unix, etc.) and look for references to structures of interest. Even if there are support functions for reading structures, like the kvm_*() functions, you must still understand how to read data from kernel memory. Typically this requires an understanding of the nlist() function, and how to use /dev/kmem, /dev/mem, and /dev/swap. Don't overlook the possibility that you may have to use the process file system -- e.g., /proc. I try to avoid using /proc when I can, since it usually requires that lsof have setuid(root) permission to read the individual /proc "files". Once you can access kernel structures, you must understand how they're connected. You must answer questions like: * How big are kernel addresses? How are they type cast? * How are kernel variable names converted to addresses? Nlist()? * How are the proc structures organized? Is it a static table? Are the proc structures linked? Is there a kernel pointer to the first proc structure? Is there a proc structure count? * How does one obtain copies of the proc structures? Via /dev/kmem? Via a vendor API? * If this is a Mach derivative, is it necessary to obtain the task and thread structures? How? * How does one obtain the user area (or the utask area in Mach systems) that corresponds to a process? * Where are the file structures located for open file descriptors and how are they located? Are all file structures in the user area? Is the file structure space extensible? * Where do the private data pointers in file structures lead? To gnodes? To inodes? To sockets? To vnodes? Hint: look in for DTYPE_* instances and further pointers. * How are the nodes organized? To what other nodes do they lead and how? Where are the common bits of information in nodes -- device, node number, size -- stored? Hint: look in the header files for nodes for macros that may be used to obtain the address of one node from another -- e.g., the VTOI() macro that leads from a vnode to an inode. * Are text reference nodes identified and how? Is it necessary to examine the virtual memory map of a process or a task to locate text references? Some kernels have text node pointers in the proc structures; some, in the user area; Mach kernels may have text information in the task structure, reached in various ways from the proc, user area, or user task structure. * How is the device table -- e.g., /dev or /devices -- organized? How is it read? Using direct or dirent structures? How are major/minor device numbers represented? How are device numbers assembled and disassembled? Are there clone devices? How are they identified? * How is mount information obtained? Getmntinfo()? Getmntent()? Some special kernel call? * How are sockets identified and organized? BSD-style? As streams? Are there streams? * Are there special nodes -- CD-ROM nodes, FIFO nodes, etc.? * How is the kernel's name cache organized? Can lsof access it to get partial name components? Dlsof.h and #include's ---------------------- Once you have identified the kernel's data organization and know what structures it provides, you must add #include's to dlsof.h to access their definitions. Sometimes it is difficult to locate the header files -- you may need to introduce -I specifications in the Makefile via the DINC shell variable in the Configure script. Sometimes it is necessary to define special symbols -- e.g., KERNEL, _KERNEL, _KMEMUSER -- to induce system header files to yield kernel structure definitions. Sometimes making those symbol definitions cause other header file and definition conflicts. There's no good general rule on how to proceed when conflicts occur. Rarely it may be necessary to extract structure definitions from system header files and move them to dlsof.h, create special versions of system header files, or obtain special copies of system header files from "friendly" (e.g., vendor) sources. The dlsof.h header file in lsof4/dialects/sun shows examples of the first case; the second, no examples; the third, the irix5hdr subdirectory in lsof4/dialects/irix (a mixture of the first and third). Building up the necessary #includes in dlsof.h is an iterative process that requires attention as you build the dialect-specific functions that references kernel structures. Be prepared to revisit dlsof.h frequently. Definitions That Affect Compilation ----------------------------------- The source files at the top level and in the lib/ subdirectory contain optional functions that may be activated with definitions in a dialect's machine.h header file. Some are functions for reading node structures that may not apply to all dialects -- e.g. CD-ROM nodes (cdrnode), or `G' nodes (gnode) -- and others are common functions that may occasionally be replaced by dialect-specific ones. Once you understand your kernel's data organization, you'll be able to decide the optional common node functions to activate. Definitions in machine.h and dlsof.h also enable or disable other optional common features. The following is an attempt to list all the definitions that affect lsof code, but CAUTION, it is only attempt and may be incomplete. Always check lsof4 source code in lib/ and dialects/, and dialect machine.h header files for other possibilities AFS_VICE See 00XCONFIG. AIX_KERNBITS specifies the kernel bit size, 32 or 64, of the Power architecture AIX 5.x kernel for which lsof was built. CAN_USE_CLNT_CREATE is defined for dialects where the more modern RPC function clnt_create() can be used in place of the deprecated clnttcp_create(). CLONEMAJ defines the name of the variable that contains the clone major device number. (Also see HAS_STD_CLONE and HAVECLONEMAJ.) DEVDEV_PATH defines the path to the directory where device nodes are stored, usually /dev. Solaris 10 uses /devices. DIALECT_WARNING may be defined by a dialect to provide a warning message that will be displayed with help (-h) and version (-v) output. 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). GET_MAJ_DEV is a macro to get major portion from device number instead of via the standard major() macro. GET_MIN_DEV is a macro to get minor portion from device number instead of via the standard minor() macro. GET_MAX_FD the name of the function that returns an int for the maximum open file descriptor plus one. If not defined, defaults to getdtablesize. HAS9660FS enables CD9660 file system support in a BSD dialect. HAS_ADVLOCK_ARGS is defined for NetBSD and OpenBSD dialects whose references vop_advlock_args. HAS_AFS enables AFS support code for the dialect. HAS_ATOMIC_T indicates the Linux version has an 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 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 header file. 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_CONN_NEW indicates the Solaris version has the new form of the conn_s structure, introduced in b134 of Solaris 11. This will always accompany the HAS_IPCLASSIFIER_H definition. HAS_CONST indicates that the compiler supports the const keyword. HASCPUMASK_T indicates the FreeBSD 5.2 or higher dialect has cpumask_t typedef's. HAS_CRED_IMPL_H indicates the Solaris 10 dialect has the header file available. HASCWDINFO indicates the cwdinfo structure is defined in the NetBSD . HASDCACHE enables device file cache file support. The device cache file contains information about the names, device numbers and inode numbers of entries in the /dev (or /device) node subtree that lsof saves from call to call. See the 00DCACHE file of the lsof distribution for more information on this feature. HASDENTRY indicates the Linux version has a dentry struct defined in . 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. HASDNLCPTR is defined when the name cache entry of has a name character pointer rather than a name character array. HASEFFNLINK indicates the *BSD system has the i_effnlink member in the inode structure. HASENVDC enables the use of an environment-defined device cache file path and defines the name of the environment variable from which lsof may take it. (See the 00DCACHE file of the lsof distribution for information on when HASENVDC is used or ignored.) HASEOPT indicates the dialect supports the -e option to eliminate kernel blocks on a named file system. HASEXT2FS is defined for BSD dialects for which ext2fs file system support can be provided. A value of 1 indicates that the i_e2din member does not exist; 2, it exists. HASF_VNODE indicates the dialect's file structure has an f_vnode member in it. HASFDESCFS enables file descriptor file system support for the dialect. A value of 1 indicates has a Fctty definition; 2, it does not. HASFDLINK indicates the file descriptor file system node has the fd_link member. HASFIFONODE enables/disables readfifonode() in node.c. HAS_FL_FD indicates the Linux version has an fl_fd element in the lock structure of . HAS_FL_FILE indicates the Linux version has an fl_file element in the lock structure of . HAS_FL_WHENCE indicates the Linux version has an fl_whence element in the lock structure of . 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. This contains the file system's inode number and may be needed when searching the kernel name cache. See dialects/osr/dproc.c for an example. HAS_JFS2 The AIX >= 5.0 dialect has jfs2 support. HASFSTRUCT indicates the dialect has a file structure the listing of whose element values can be enabled with +f[cfn]. FSV_DEFAULT defines the default listing values. HASFSTYPE enables/disables the use of the file system's stat(2) st_fstype member. If the HASFSTYPE value is 1, st_fstype is treated as a character array; 2, it is treated as an integer. See also the RMNT_EXPDEV and RMNT_FSTYPE documentation in lib/rmnt.c 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 its inode to the EXTFS dinode. HASI_FFS indicates the BSD dialect has i_ffs_size in . HASI_FFS1 indicates the BSD dialect supports the fast UFS1 and UFS2 file systems. HAS_INKERNEL indicates the SCO OSR 6.0.0 or higher, or UnixWare 7.1.4 or higher system uses the INKERNEL symbol in or . 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.) HASINT16TYPE is defined when the dialect has a typedef for int16 that may conflict with some other header file's redefinition (e.g., ). HASINT32TYPE is defined when the dialect has a typedef for int32 that may conflict with some other header file's redefinition (e.g., ). HASINTSIGNAL is defined when signal() returns an int. HAS_IPCLASSIFIER_H is defined for Solaris dialects that have the header file. HAS_IPC_S_PATCH is defined when the HP-UX 11 dialect has the ipc_s patch installed. It has a value of 1 if the ipc_s structure has an ipc_ipis member, but the ipis_s structure lacks the ipis_msgsqueued member; 2, if ipc_s has ipc_ipis, but ipis_s lacks ipis_msgsqueued. HASIPv6 indicates the dialect supports the IPv6 Internet address family. HASKERNELKEYT indicates the Linux version has a __kernel_key_t typedef in . HASKERNFS is defined for BSD dialects for which /kern file system support can be provided. HASKERNFS_KFS_KT indicates *kfs_kt is in the BSD dialect's . HASKOPT enables/disables the ability to read the kernel's name list from a file -- e.g., from a crash dump file. HASKQUEUE indicates the dialect supports the kqueue file type. HASKVMGETPROC2 The *BSD dialect has the kvm_gettproc2() function. HAS_KVM_VNODE indicates the FreeBSD 5.3 or higher dialect has "defined(_KVM_VNODE)" in . HASLFILEADD defines additional, dialect-specific elements SETLFILEADD in the lfile structure (defined in lsof.h). HASLFILEADD is a macro. The accompanying SETFILEADD macro is used in the alloc_lfile() function of proc.c to preset the additional elements. HAS_LF_LWP is defined for BSD dialects where the lockf structure has an lf_lwp member. HASLFS indicates the *BSD dialect has log-structured file system support. HAS_LGRP_ROOT_CONFLICT indicates the Solaris 9 or Solaris 10 system has a conflict over the lgrp_root symbol in the and header files. HAS_LIBCTF indicates the Solaris 10 and above system has the CTF library. HAS_LOCKF_ENTRY indicates the FreeBSD version has a lockf_entry structure in its header file. HAS_LWP_H is defined for BSD dialects that have the header file. HASMOPT enables/disables the ability to read kernel memory from a file -- e.g., from a crash dump file. HASMSDOSFS enables MS-DOS file system support in a BSD dialect. HASMNTSTAT indicates the dialect has a stat(2) status element in its mounts structure. HASMNTSUP indicates the dialect supports the mount supplement option. HASNAMECACHE indicates the FreeBSD dialect has a namecache structure definition in . HASNCACHE enables the probing of the kernel's name cache to obtain path name components. A value of 1 directs printname() to prefix the cache value with the file system directory name; 2, avoid the prefix. 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. HASNFSVATTRP indicates the n_vattr member of the nfsnode of the *BSD dialect is a pointer. HASNLIST enables/disables nlist() function support. (See NLIST_TYPE.) HASNOFSADDR is defined if the dialect has no file structure addresses. (HASFSTRUCT must be defined.) HASNOFSCOUNT is defined if the dialect has no file structure counts. (HASFSTRUCT must be defined.) HASNOFSFLAGS is defined if the dialect has no file structure flags. (HASFSTRUCT must be defined.) HASNOFSNADDR is defined if the dialect has no file structure node addresses. (HASFSTRUCT must be defined.) HAS_NO_6PORT is defined if the FreeBSD in_pcb.h has no in6p_.port definitions. HAS_NO_6PPCB is defined if the FreeBSD in_pcb.h has no in6p_ppcb definition. 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. 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 running lsof, provided socket file listing is selected with the "-i" option. This definition is only effective when HASSECURITY is also defined. HASNULLFS indicates the dialect (usually *BSD) has a null file system. HASOBJFS indicates the Pyramid version has OBJFS support. HASONLINEJFS indicates the HP-UX 11 dialect has the optional OnlineJFS package installed. HAS_PC_DIRENTPERSEC indicates the Solaris 10 system's header file has the pc_direntpersec() macro. HAS_PAD_MUTEX indicates the Solaris 11 system has the pad_mutex_t typedef in its header file. HASPERSDC enables the use of a personal device cache file path and specifies a format by which it is constructed. See the 00DCACHE file of the lsof distribution for more information on the format. HASPERSDCPATH enables the use of a modified personal device cache file path and specifies the name of the environment variable from which its component may be taken. See the 00DCACHE file of the lsof distribution for more information on the modified personal device cache file path. HASPINODEN declares that the inode number of a /proc file should be stored in its procfsid structure. HASPIPEFN defines the function that processes DTYPE_PIPE file structures. It's used in the prfp.c library source file. See the FreeBSD dialect source for an example. HASPIPENODE enables/disables readpipenode() in node.c. HASPMAPENABLED enables the automatic reporting of portmapper registration information for TCP and UDP ports that have been registered. HASPPID indicates the dialect has parent PID support. HASPR_LDT indicates the Solaris dialect has a pr_ldt member in the pronodetype enum. HASPR_GWINDOWS indicates the Solaris dialect has a pr_windows member in the pronodetype enum. HASPRINTDEV this value defines a private function for printing the dialect's device number. Used by print.c/print_file(). Takes one argument: char *HASPRINTDEV(struct lfile *) HASPRINTINO this value names a private function for printing the dialect's inode number. Used by print.c/print_file(). Takes one argument: char *HASPRINTINO(struct lfile *) HASPRINTNM this value names a private function for printing the dialect's file name. Used by print.c/print_file(). Takes one argument: 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 format; 1, 0x. 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. HASPRIVFILETYPE defines the function that processes the file struct's f_data member. Processing is initiated from the process_file() function of the prfp.c library source file or from the dialect's own process_file() function. HASPRIVNMCACHE enables printing of a file path from a private name cache. HASPRIVNMCACHE defines the name of the printing function. The function takes one argument, a struct lfile pointer to the file, and returns non-zero if it prints a cached name to stdout. HASPRIVPRIPP is defined for dialects that have a private function for printing the IP protocol name. When this is not defined, the function to do that defaults to printiproto(). HASPROCFS defines the name (if any) of the process file system -- e.g., /proc. HASPROCFS_PFSROOT indicates PFSroot is in the BSD dialect's . HASPSEUDOFS indicates the FreeBSD dialect has pseudofs file system support. HASPSXSEM indicates the dialect has support for the POSIX semaphore file type. HASPSXSHM indicates the dialect has support for the POSIX shared memory file type. HASPTYFS indicates the *BSD dialect has a ptyfs file system. HASRNODE enables/disables readrnode() in node.c. HASRNODE3 indicates the HPUX 10.20 or lower dialect has NFS3 support with a modified rnode structure. HASRPCV2H The FreeBSD dialect has . HAS_SANFS indicates the AIX system has SANFS file system support. HASSBSTATE indicates the dialect has socket buffer state information (e.g., SBS_* symbols) available. HASSECURITY enables/disables restricting open file information access. (Also see HASNOSOCKSECURITY.) HASSELINUX indicates the Linux dialect has SELinux security context support available. HASSETLOCALE is defined if the dialect has and setlocale(). HAS_SI_PRIV indicates the FreeBSD 6.0 and higher cdev structure has an si_priv member. HAS_SOCKET_PROTO_H indicates the Solaris 10 system has the header file . HASSOUXSOUA indicates that the Solaris has soua_* members in its so_ux_addr structure. HASSPECDEVD indicates the dialect has a special device directory and defines the name of a function 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 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. HASSOSTATE indicates the dialect has socket state information (e.g., SS_* symbols) available. HASSTATVFS indicates the NetBSD dialect has a statvfs struct definition. HASSTAT64 indicates the dialect's contains stat64. HAS_STD_CLONE indicates the dialect uses a standard clone device structure that can be used in common library function clone processing. If the value is 1, the clone table will be built by readdev() and cached when HASDCACHE is defined; if the value is 2, it is assumed the clone table is built independently. (Also see CLONEMAJ and HAVECLONEMAJ.) HASSTREAMS enables/disables streams. CAUTION, requires specific support code in the dialect sources. HAS_STRFTIME indicates the dialect has the gmtime() and strftime() C library functions that support the -r marker format option. Configure tests for the functions and defines this symbol. HASSYSDC enables the use of a system-wide device cache file and defines its path. See the 00DCACHE file of the lsof distribution for more information on the system-wide device cache file path option. HAS_SYS_PIPEH indicates the dialect has a header file. HAS_SYS_SX_H indicates the FreeBSD 7.0 and higher system has a header file. HASTAGTOPATH indicates the DEC OSF/1, Digital UNIX, or Tru64 UNIX dialect has a libmsfs.so, containing tag_to_path(). HASTMPNODE enables/disables readtnode() in node.c. HASTCPOPT indicates the dialect has TCP option information (i.e., from TF_* symbols) available. HASTCPTPIQ is defined when the dialect can duplicate the receive and send queue sizes reported by netstat. HASTCPTPIW is defined when the dialect can duplicate the receive and send window sizes reported by netstat. HASTCPUDPSTATE is defined when the dialect has support for TCP and UDP state, including the "-s p:s" option and associated speed ehancements. HASTFS indicates that the Pyramid dialect has TFS file system support. HAS_UFS1_2 indicates the FreeBSD 6 and higher system has UFS1 and UFS2 members in its inode structure. 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., ). HASUTMPX indicates the dialect has a header file. HAS_UVM_INCL indicates the NetBSD or OpenBSD dialect has a include directory. HAS_UW_CFS indicates the UnixWare 7.1.1 or above dialect has CFS file system support. HAS_UW_NSC indicates the UnixWare 7.1.1 or above dialect has a NonStop Cluster (NSC) kernel. HAS_V_LOCKF indicates the FreeBSD version has a v_lockf member in the vode structure, defined in . HAS_VM_MEMATTR_T indicates the FreeBSD uses the vm_memattr_t typedef. HASVMLOCKH indicates the FreeBSD dialect has . HASVNODE enables/disables readvnode() function in node.c. HAS_V_PATH indicates the dialect's vnode structure has a v_path member. HAS_VSOCK indicates that the Solaris version has a VSOCK member in the vtype enum HASVXFS enables Veritas VxFS file system support for the dialect. CAUTION, the dialect sources must have the necessary support code. HASVXFSDNLC indicates the VxFS file system has its own name cache. HASVXFS_FS_H indicates exists. HASVXFS_MACHDEP_H indicates exists. HASVXFS_OFF64_T indicates exists and has an off64_t typedef. HASXVFSRNL indicates the dialect has VxFS Reverse Name Lookup (RNL) support. HASVXFS_SOL_H indicates exists. HASVXFS_SOLARIS_H indicates exists. HASVXFS_U64_T if HASVXFS_SOLARIS_H is defined, this variable indicates that has a vx_u64_t typedef. HASVXFSUTIL indicates the Solaris dialect has VxFS 3.4 or higher and has the utility libraries, libvxfsutil.a (32 bit) and libvxfsutil64.a (64 bit). HASVXFS_VX_INODE indicates that contains a vx_inode structure. HASWIDECHAR indicates the dialect has the wide-character support functions iswprint(), mblen() and mbtowc(). HASXNAMNODE indicates the OSR dialect has . HASXOPT defines help text for dialect-specific X option and enables X option processing in usage.c and main.c. HASXOPT_ROOT when defined, restricts the dialect-specific X option to processes whose real user ID is root. HAS_ZFS indicates the dialect has support for the ZFS file system. HASXOPT_VALUE defines the default binary value for the X option in store.c. HASZONES the Solaris dialect has zones. HAVECLONEMAJ defines the name of the status variable that indicates a clone major device number is available in CLONEMAJ. (Also see CLONEMAJ and HAS_STD_CLONE.) HPUX_KERNBITS defines the number of bits in the HP-UX 10.30 and above kernel "basic" word: 32 or 64. KA_T defines the type cast required to assign space to kernel pointers. When not defined by a dialect header file, KA_T defaults to unsigned long. KA_T_FMT_X defines the printf format for printing a KA_T -- the default is "%#lx" for the default unsigned long KA_T cast. LSOF_ARCH See 00XCONFIG. LSOF_BLDCMT See 00XCONFIG. LSOF_CC See 00XCONFIG. LSOF_CCV See 00XCONFIG. LSOF_HOST See 00XCONFIG. LSOF_INCLUDE See 00XCONFIG. LSOF_LOGNAME See 00XCONFIG. LSOF_MKC See the "The Mksrc Shell Script" section of this file. LSOF_SYSINFO See 00XCONFIG. LSOF_USER See 00XCONFIG. LSOF_VERS See 00XCONFIG. LSOF_VSTR See 00XCONFIG. MACH defines a MACH system. N_UNIXV defines an alternate value for the N_UNIV symbol. NCACHELDPFX defines C code to be executed before calling ncache_load(). NCACHELDSFX defines C code to be executed after calling ncache_load(). NEEDS_BOOLEAN_T indicates the FreeBSD 9 and above system needs a boolean_t definition for . NEVER_HASDCACHE keeps the Customize script from offering to change HASDCACHE by its presence anywhere in a dialect's machine.h header file -- e.g., in a comment. See the Customize script or machine.h in dialects/linux/proc. NEVER_WARNDEVACCESS keeps the Customize script from offering to change WARNDEVACCESS by its presence anywhere in a dialect's machine.h header file -- including in a comment. See the Customize script or machine.h in dialects/linux/proc. NLIST_TYPE is the type of the nlist table, Nl[], if it is not nlist. HASNLIST must be set for this definition to be effective. NOWARNBLKDEV specifies that no warning is to be issued when no block devices are found. This definiton is used only when HASBLKDEV is also defined. OFFDECDIG specifies how many decimal digits will be printed for the file offset in a 0t form before switching to a 0x form. The count includes the "0t". A count of zero means the size is unlimited. PRIVFILETYPE is the number of a private file type, found in the f_type member of the file struct, to be processed by the HASPRIVFILETYPE function. See the AIX dialect sources for an example. _PSTAT_STREAM_GET_XPORT indicates the HP-UX PSTAT header files require this symbol to be defined for proper handling of stream export data. SAVE_MP_IN_SFILE indicates the dialect needs to have the mounts structure pointer for a file system search argument recorded in the dialect's sfile structure. This definition is made in the dialect's dlsof.h header file within the sfile structure. TIMEVAL_LSOF defines the name of the timeval structure. The default is timeval. /dev/kmem-based Linux lsof redefines timeval with this symbol to avoid conflicts between glibc and kernel definitions. TYPELOGSECSHIFT defines the type of the cdfs_LogSecShift member of the cdfs structure for UnixWare 7 and higher. UID_ARG_T defines the cast on a User ID when passed as a function argument. USE_LIB_COMPLETEVFS selects the use of the completevfs() function in lsof4/lib/cvfs.c. USE_LIB_FIND_CH_INO selects the use of the find_ch_ino() inode function in lsof4/lib/fino.c. Note: HASBLKDEV selects the has_bl_ino() function. USE_LIB_IS_FILE_NAMED selects the use of the is_file_named() function in lsof4/lib/isfn.c. USE_LIB_LKUPDEV selects the use of the lkupdev() function in lsof4/lib/lkud.c. Note: HASBLKDEV selects the lkupbdev() function. USE_LIB_PRINTDEVNAME selects the use of the printdevname() function in lsof4/lib/pdvn.c. Note: HASBLKDEV selects the printbdevname() function. USE_LIB_PRINT_TCPTPI selects the use of the print_tcptpi() function in lsof4/lib/ptti.c. USE_LIB_PROCESS_FILE selects the use of the process_file() function in lsof4/lib/prfp.c. USE_LIB_READDEV selects the use of the readdev() and stkdir() functions in lsof4/lib/rdev.c. USE_LIB_READMNT selects the use of the readmnt() function in lsof4/lib/rmnt.c. USE_LIB_RNAM selects the use of the device cache functions in lsof4/lib/rnam.c. Note: HASNCACHE must also be defined. USE_LIB_RNCH selects the use of the device cache functions in lsof4/lib/rnch.c. Note: HASNCACHE must also be defined. USE_STAT is defined for those dialects that must use the stat(2) function instead of lstat(2) to scan /dev -- i.e., in the readdev() function. VNODE_VFLAG is an alternate name for the vnode structure's v_flag member. WARNDEVACCESS enables the issuing of a warning message when lsof is unable to access /dev (or /device) or one of its subdirectories, or stat(2) a file in them. Some dialects (e.g., HP-UX) have many inaccessible subdirectories and it is appropriate to inhibit the warning for them with WARNDEVACCESS. The -w option will also inhibit these warnings. WARNINGSTATE when defined, disables the default issuing of warning messages. WARNINGSTATE is undefined by default for all dialects in the lsof distribution. WIDECHARINCL defines the header file to be included (if any) when wide-character support is enabled with HASWIDECHAR. zeromem() defines a macro to zero memory -- e.g., using bzero() or memset(). Any dialect's machine.h file and Configure stanza can serve as a template for building your own. All machine.h files usually have all definitions, disabling some (with comment prefix and suffix) and enabling others. Options: Common and Special --------------------------- All but one lsof option is common; the specific option is ``-X''. If a dialect does not support a common option, the related #define in machine.h -- e.g., HASCOPT -- should be deselected. The specific option, ``-X'', may be used by any dialect for its own purpose. Right now (May 30, 1995) the ``-X'' option is binary (i.e., it's not allowed arguments of its own, and its value must be 0 or 1) but that could be changed should the need arise. The option is enabled with the HASXOPT definition in machine.h; its default value is defined by HASXOPT_VALUE. The value of HASXOPT should be the text displayed for ``-X'' by the usage() function in usage.c. HASXOPT_VALUE should be the default value, 0 or 1. AIX for the IBM RICS System/6000 defines the ``-X'' option to control readx() usage, since there is a bug in AIX kernels that readx() can expose for other processes. Defining Dialect-Specific Symbols and Global Storage ---------------------------------------------------- A dialect's dlsof.h and dstore.c files contain dialect-specific symbol and global storage definitions. There are symbol definitions, for example, for function and data casts, and for file paths. Dslof.h defines lookup names the nlist() table -- X_* symbols -- when nlist() is being used. Global storage definitions include such things as structures for local Virtual File System (vfs) information; mount information; search file information; and kernel memory file descriptors -- e.g., Kmem for /dev/kmem, Mem for /dev/mem, Swap for /dev/drum. Coding Dialect-specific Functions --------------------------------- Each supported dialect must have some basic functions that the common functions of the top level may call. Some of them may be obtained from the library in lsof4/lib, selected and customized by #define's in the dialect machine.h header file. Others may have to be coded specifically for the dialect. Each supported dialect usually has private functions, too. Those are wholly determined by the needs of the dialect's data organization and access. These are some of the basic functions that each dialect must supply -- they're all defined in proto.h: initialize() function to initialize the dialect is_file_named() function to check if a file was named by an optional file name argument (lsof4/lib/isfn.c) gather_proc_info() function to gather process table and related information and cache it printchdevname() function to locate and optionally print the name of a character device (lsof4/lib/pdvn.c) print_tcptpistate() function to print the TCP or TPI state for a TCP or UDP socket file, if the one in lib/ptti.c isn't suitable (define USE_LIB_PRINT_TCPTPI to activate lib/ptti.c) process_file() function to process an open file structure (lsof4/lib/prfp.c) process_node() function to process a primary node process_socket() function to process a socket readdev() and stkdir() functions to read and cache device information (lsof4/lib/rdev.c) readmnt() function to read mount table information (lsof4/lib/rmnt.c) Other common functions may be needed, and might be obtained from lsof4/lib, depending on the needs of the dialect's node and socket file processing functions. Check the functions in lsof4/lib and specific lsof4/dialects/* files for examples. As you build these functions you will probably have to add #include's to dlsof.h. Function Prototype Definitions and the _PROTOTYPE Macro ------------------------------------------------------- Once you've defined your dialect-specific definitions, you should define their prototypes in dproto.h or locally in the file where they occur and are used. Do this even if your compiler is not ANSI compliant -- the _PROTOTYPE macro knows how to cope with that and will avoid creating prototypes that will confuse your compiler. The Makefile ------------ Here are some general rules for constructing the dialect Makefile. * Use an existing dialect's Makefile as a template. * Make sure the echo actions of the install rule are appropriate. * Use the DEBUG string to set debugging options, like ``-g''. You may also need to use the -O option when forking and SIGCHLD signals defeat your debugger. * Don't put ``\"'' in a compiler flags -D= clause in your Makefile. Leave off the ``\"'' even though you want to be a string literal and instead adapt the N_UNIX* macros you'll find in Makefiles for FreeBSD and Linux. That will allow the Makefile's version.h rule to put CFLAGS into version.h without having to worry about the ``\"'' sequences. * Finally, remember that strings can be passed from the top level's Configure shell script. That's an appropriate way to handle options, especially if there are multiple versions of the Unix dialect to which you are porting lsof 4. The Mksrc Shell Script ---------------------- Pattern your Mksrc shell script after an existing one from another dialect. Change the D shell variable to the name of your dialect's subdirectory in lsof4/dialects. Adjust any other shell variable to your local conditions. (Probably that won't be necessary.) Note that, if using symbolic links from the top level to your dialect subdirectory is impossible or impractical, you can set the LSOF_MKC shell variable in Configure to something other than "ln -s" -- e.g., "cp," and Configure will pass it to the Mksrc shell script in the M environment variable. The MkKernOpts Shell Script --------------------------- The MkKernOptrs shell script is used by some dialects -- e.g., Pyramid DC/OSx and Reliant UNIX -- to determine the compile-time options used to build the current kernel that affect kernel structure definitions, so those same options can be used to build lsof. Configure calls MkKernOpts for the selected dialects. If your kernel is built with options that affect structure definitions. -- most commonly affected are the proc structure from and the user structure from -- check the MkKernOpts in lsof4/dialects/irix for a comprehensive example. Testing and the Lsof Test Suite ------------------------------- Once you have managed to create a port, here are some tips for testing it. * First look at the test suite in the tests/ sub-directory of the lsof distribution. While it will need to be customized to be usable with a new port, it should provide ideas on things to test. Look for more information about the test suite in the 00TEST file. * Pick a simple process whose open files you are likely to know and see if the lsof output agrees with what you know. (Hint: select the process with `lsof -p `.) Are the device numbers and device names correct? Are the file system names and mount points correct? Are inode numbers and sizes correct? Are command names, file descriptor numbers, UIDs, PIDs, PGIDs, and PPIDs correct? A simple tool that does a stat(2) of the files being examined and reports the stat struct contents can provide a reference for some values; so can `ls -l /dev/`. * Let lsof list information about all open files and ask the same questions. Look also for error messages about not being able to read a node or structure. * Pick a file that you know is open -- open it and hold it that way with a C program (not vi), if you must. Ask lsof to find the file's open instance by specifying its path to lsof. * Create a C program that opens a large number of files and holds them open. Background the test process and ask lsof to list its files. * Generate some locks -- you may need to write a C program to do this, hold the locked file open, and see if lsof can identify the lock properly. You may need to write several C programs if your dialect supports different lock functions -- fnctl(), flock(), lockf(), locking(). * Identify a process with known Internet file usage -- inetd is a good one -- and ask lsof to list its open files. See if protocols and service names are listed properly. See if your lsof identifies Internet socket files properly for rlogind or telnetd processes. * Create a UNIX domain socket file, if your dialect allows it, hold it open by backgrounding the process, and see if lsof can identify the open UNIX domain socket file properly. * Create a FIFO file and see what lsof says about it. * Watch an open pipe -- `lsof -u | less` is a good way to do this. * See if lsof can identify NFS files and their devices properly. Open and hold open an NFS file and see if lsof can find the open instance by path. * If your test system has CD-ROM and floppy disk devices, open files on them and see if lsof reports their information correctly. Such devices often have special kernel structures associated with them and need special attention from lsof for their identification. Pay particular attention to the inode numbers lsof reports for CD-ROM and floppy disk files -- often they are calculated dynamically, rather than stored in a kernel node structure. * If your implementation can probe the kernel name cache, look at some processes with open files whose paths you know to see if lsof identifies any name components. If it doesn't, make sure the name components are in the name cache by accessing the files yourself with ls or a similar tool. * If your dialect supports the /proc file system, use a C program to open files there, background a test process, and ask lsof to report its open files. * If your dialect supports fattach(), create a small test program to use it, background a test process, and ask lsof to report its open files. I can supply some quick-and-dirty tools for reporting stat buffer contents, holding files open, creating UNIX domain files, creating FIFOs, etc., if you need them. Where Next? ----------- Is this document complete? Certainly not! One might wish that it were accompanied by man pages for all lsof functions, by free beer or chocolates, by ... (You get the idea.) But those things are not likely to happen as long as lsof is a privately supported, one man operation. So, if you need more information on how lsof is constructed or works in order to do a port of your own, you'll have to read the lsof source code. You can also ask me questions via email, but keep in mind the private, one-man nature of current lsof support. Vic Abell April 10, 2012 lsof-4.86+dfsg.orig/store.c0000444000175000017500000003545611631741205015771 0ustar nicholasnicholas/* * 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"; static char *rcsid = "$Id: store.c,v 1.40 2011/09/07 19:13:49 abe Exp $"; #endif #include "lsof.h" /* * Global storage definitions */ #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] */ 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 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 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_NAME, 0, LSOF_FNM_NAME, NULL, 0 }, /* 14 */ { LSOF_FID_NI, 0, LSOF_FNM_NI, &Fsv, FSV_NI }, /* 15 */ { LSOF_FID_OFFSET, 0, LSOF_FNM_OFFSET, NULL, 0 }, /* 16 */ { LSOF_FID_PID, 1, LSOF_FNM_PID, NULL, 0 }, /* 17 */ { LSOF_FID_PGID, 0, LSOF_FNM_PGID, &Fpgid, 1 }, /* 18 */ { LSOF_FID_PROTO, 0, LSOF_FNM_PROTO, NULL, 0 }, /* 19 */ { LSOF_FID_RDEV, 0, LSOF_FNM_RDEV, NULL, 0 }, /* 20 */ { LSOF_FID_PPID, 0, LSOF_FNM_PPID, &Fppid, 1 }, /* 21 */ { LSOF_FID_SIZE, 0, LSOF_FNM_SIZE, NULL, 0 }, /* 22 */ { LSOF_FID_STREAM, 0, LSOF_FNM_STREAM, NULL, 0 }, /* 23 */ { LSOF_FID_TYPE, 0, LSOF_FNM_TYPE, NULL, 0 }, /* 24 */ { LSOF_FID_TCPTPI, 0, LSOF_FNM_TCPTPI, &Ftcptpi, TCPTPI_ALL }, /* 25 */ { LSOF_FID_UID, 0, LSOF_FNM_UID, NULL, 0 }, /* 26 */ { LSOF_FID_ZONE, 0, LSOF_FNM_ZONE, &Fzone, 1 }, /* 27 */ { LSOF_FID_CNTX, 0, LSOF_FNM_CNTX, &Fcntx, 1 }, /* 28 */ { LSOF_FID_TERM, 0, LSOF_FNM_TERM, NULL, 0 }, /* 29 */ { ' ', 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 */ 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 */ 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 */ struct l_dev **Sdev = (struct l_dev **)NULL; /* pointer to Devtp[] pointers, sorted * by device */ int Selall = 1; /* all processes are selected (default) */ int Selflags = 0; /* selection flags -- see SEL* in lsof.h */ 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 TaskPrtFl = 0; /* task print 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 TidColW = 0; /* 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 */ lsof-4.86+dfsg.orig/00QUICKSTART0000444000175000017500000011034311325130021016217 0ustar nicholasnicholas 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 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 opetion and its output piped to a grep on the address yields: $ lsof -U | grep ffffff0084253b68 squid 1638 nobody 12u unix 18,98 0t10 9437188 /devices/pseudo/tl@0:ticots->0xffffff0084253b68 stream-ord $ lsof -U | 8. Finding Files Open to a Named Command ========================================= 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 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 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 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 -ad9,10 -r or $ lsof -p -ad10,11 -r Some options need explaining: -p specifies that lsof is to restrict its attention to the process whose ID is . 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 -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 or $ lsof -u 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 exits 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 lsof detects an error and makes an unsuccessful exit, it returns an exit code of 1 (one). 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 > /dev/null 2>&1 if test $? -eq 0 then echo " has some users." else echo " may have no users." 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 and -u 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 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, , 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 -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 January 18, 2010 lsof-4.86+dfsg.orig/proc.c0000444000175000017500000006752411424322557015606 0ustar nicholasnicholas/* * 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"; static char *rcsid = "$Id: proc.c,v 1.46 2010/07/29 15:59:28 abe Exp $"; #endif #include "lsof.h" /* * Local function prototypes */ _PROTOTYPE(static int is_file_sel,(struct lproc *lp, struct lfile *lf)); /* * 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); Exit(1); } 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); Exit(1); } *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); Exit(1); } /* * 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(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); Exit(1); } 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); Exit(1); } } Lp = &Lproc[Nlproc++]; Lp->pid = pid; #if defined(HASTASKS) Lp->tid = 0; #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); Exit(1); } #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) && !Selall) { 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; } } /* * 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^" 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 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 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? */ static 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 (Selall) 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 (Selall) { *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; 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(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 defined(HASTASKS) /* * If this is a task of a process, skip it. */ if (Lp->tid) return(0); #endif /* defined(HASTASKS) */ /* * 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); #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 dialects-specific formatted * output. */ if (!Ffield) { print_file(); continue; } /* * Print selected fields. */ lc = st = 0; if (FieldSel[LSOF_FIX_FD].st) { for (cp = Lf->fd; *cp == ' '; cp++) ; if (*cp) { (void) printf("%c%s%c", LSOF_FID_FD, cp, Terminator); lc++; } } 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); } lsof-4.86+dfsg.orig/00MANIFEST0000444000175000017500000000633011171617372015755 0ustar nicholasnicholas.: 00.README.FIRST 00CREDITS 00DCACHE 00DIALECTS 00DIST 00FAQ 00LSOF-L 00MANIFEST 00PORTING 00QUICKSTART 00README 00TEST 00XCONFIG AFSConfig* Configure* Customize* Inventory* arg.c dialects/ lib/ lsof.8 lsof.h lsof.man 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 ./dialects: aix/ darwin/ du/ freebsd/ hpux/ linux/ n+obsd/ n+os/ 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: get-hdr-loc.sh* kmem/ libproc/ ./dialects/darwin/kmem: Makefile Mksrc* ddev.c dfile.c dlsof.h dmnt.c dnode.c dnode1.c dproc.c dproto.h dsock.c dstore.c machine.h ./dialects/darwin/libproc: 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 dnode.c dproc.c dproto.h dsock.c dstore.c machine.h ./dialects/n+obsd: Makefile Mksrc* 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/osr/include/sys: cdefs.h ./dialects/sun: Makefile 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 pdvn.c prfp.c ptti.c rdev.c regex.c rmnt.c rnam.c rnch.c rnmh.c snpf.c ./scripts: 00MANIFEST 00README big_brother.perl5* count_pf.perl* count_pf.perl5* identd.perl5* idrlogin.perl* idrlogin.perl5* list_NULf.perl5* list_fields.awk list_fields.perl* shared.perl5* sort_res.perl5* watch_a_file.perl* xusers.awk* ./tests: 00README Add2TestDB* CkTestDB* LTbasic.c LTbigf.c LTdnlc.c LTlib.c LTlock.c LTnfs.c LTnlink.c LTsock.c LTszoff.c LTunix.c LsofTest.h Makefile TestDB lsof-4.86+dfsg.orig/00DIALECTS0000444000175000017500000000031011720254345015724 0ustar nicholasnicholas Apple Darwin 9 and Mac OS X 10.[567] FreeBSD 4.9 and 6.4 for x86-based systems FreeBSD 8.2, 9.0 and 10.0 for AMD64-based systems Linux 2.1.72 and above for x86-based systems Solaris 9, 10 and 11 lsof-4.86+dfsg.orig/util.c0000444000175000017500000000377011630546405015610 0ustar nicholasnicholas/* * dutil.c - AIX utility functions whose compilation conflicts with the * general header file tree defined by lsof.h and dlsof.h -- e.g., * the conflict between and for the time(2) * and localtime(3) functions * * V. Abell * Purdue University */ /* * Copyright 2008 Purdue Research Foundation, West Lafayette, Indiana * 47907. All rights reserved. * * Written by Victor A. Abell * * This software is not subject to any license of the American Telephone * and Telegraph Company or the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. Neither the authors nor Purdue University are responsible for any * consequences of the use of this software. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Credit to the authors and Purdue * University must appear in documentation and sources. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 4. This notice may not be removed or altered. */ #ifndef lint static char copyright[] = "@(#) Copyright 2008 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: util.c,v 1.1 2008/04/01 11:56:53 abe Exp $"; #endif #if defined(HAS_STRFTIME) #include #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 */ { #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) */ } lsof-4.86+dfsg.orig/00DIST0000444000175000017500000051565311741060717015325 0ustar nicholasnicholas Notes for the distribution of lsof version 4 ******************************************************************** | The latest release of lsof is always available via anonymous ftp | | from lsof.itap.purdue.edu. Look in pub/tools/unix/lsof. | ******************************************************************** Contents Dialects Supported How Lsof Works Lsof Output Getting Started Quickly Limiting, Filtering, and Selecting Lsof Output Parsing Lsof Output with Another Program Repeat Mode Distribution Restrictions Cautions Distribution Contents Warranty Bug Reports The lsof-l Mailing List Version 3 Release Notes 3.0, May 24, 1994 ... 3.88, February 17, 1997 What's New in Version 4 Version 4 Release Notes 4.0, February 24, 1997 4.01, March 3, 1997 4.02, March 21, 1997 4.03, April 7, 1997 4.04, April 17, 1997 4.04 supplement, April 18, 1997 4.05, April 24, 1997 4.06, April 30, 1997 4.07, May 12, 1997 4.08, May 23, 1997 4.09, June 1, 1997 4.10, June 8, 1997 4.11, June 12, 1997 4.12, June 24, 1997 4.13, July 9, 1997 4.14, July 22, 1997 4.15, August 15, 1997 4.16, September 25, 1997 4.17, October 14, 1997 4.18, October 25, 1997 4.19, October 30, 1997 4.20, November 11, 1997 4.21, December 1, 1997 4.22, December 15, 1997 4.23, January 16, 1998 4.24, January 28, 1998 4.25, February 7, 1998 4.26, February 17, 1998 4.27, March 6, 1998 4.28, March 10, 1998 4.29, March 26, 1998 4.30, April 9, 1998 4.31, April 21, 1998 4.32, May 13, 1998 4.33, May 22, 1998 4.34, June 26, 1998 4.35, July 17, 1998 4.36, August 4, 1998 4.37, September 15, 1998 4.38, November 25, 1998 4.39, December 29, 1998 4.40, January 25, 1999 4.41, February 27, 1999 4.42, March 30, 1999 4.43, May 11, 1999 4.44, June 24, 1999 4.45, July 30, 1999 4.46, October 23, 1999 4.47, November 29, 1999 4.48, January 14, 2000 4.49, April 3, 2000 4.50, June 29, 2000 4.51, August 21, 2000 4.52, November 8, 2000 4.53, December 6, 2000 4.54, January 19, 2001 4.55, February 15, 2001 4.56, May 3, 2001 4.57, July 19, 2001 4.58, September 13, 2001 4.59, October 20, 2001 4.60, November 9, 2001 4.61, January 22, 2002 4.62, March 7, 2002 4.63, April 23, 2002 4.64, June 26, 2002 4.65, October 10, 2002 4.66, December 22, 2002 4.67, March 27, 2003 4.68, June 18, 2003 4.69, October 16, 2003 4.70, January 16, 2004 4.71, March 11, 2004 4.72, July 13, 2004 4.73, October 21, 2004 4.74, January 17, 2005 4.75, May 16, 2005 4.76, August 30, 2005 4.77, April 10, 2006 4.78, April 24, 2007 4.79, April 15, 2008 4.80, May 12, 2008 4.81, October 21, 2008 4.82, March 25, 2009 4.83, January 18, 2010 4.84, July 29, 2010 4.85, September 27, 2011 4.86, April 10, 2012 Dialects Supported ================== Lsof (for LiSt Open Files) lists files opened by processes on selected Unix systems. Version 4 is a source reorganization of version 3, itself a major revision of version 2. Version 4 has been tested on: Apple Darwin 9 and Mac OS X 10.[567] FreeBSD 4.9 and 6.4 for x86-based systems FreeBSD 8.2, 9.0 and 10.0 for AMD64-based systems Linux 2.1.72 and above for x86-based systems Solaris 9, 10 and 11 (The pub/tools/unix/lsof/contrib directory on lsof.itap.purdue.edu 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 . Version 3 of lsof was tested on: 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 through 2.0.27 for x86-based systems NetBSD 1.0, 1.1, and 1.2 for x86 and SPARC-based systems NEXTSTEP 2.1 and 3.[0123] 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 Release 1.1, 3.0, and 5.0.x 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 Version 3 and its predecessor, version 2, may be found at: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/OLD How Lsof Works ============== Using available kernel data access methods -- getproc(), getuser(), kvm_*(), nlist(), pstat(), read(), readx(), /proc -- lsof reads process table entries, task table entries, user areas and file pointers to reach the underlying structures that describe files opened by processes. Lsof interprets most file node structures -- advfsnodes, autonodes, cnodes, cdrnodes, devnodes, fifonodes, gnodes, hsnodes, inodes, mfsnodes, pcnodes, procnodes, rnodes, snodes, specnodes, s5inodes, tmpnodes. It understands NFS connections. It recognizes FIFOs, multiplexed files, Unix and Internet sockets. It knows about streams. It understands /proc file systems for some dialects. On many dialects it recognizes execution text and library references. It knows about AFS on some Unix dialects. Lsof Output =========== The lsof output describes: * the identification number of the process (PID) that has opened the file; * the process group identification number (PGID) of the process (optional); * the process identification number of the parent process (PPID) (optional); * the command the process is executing; * the owner of the process; * for all files in use by the process, including the executing text file and the shared libraries it is using: * the file descriptor number of the file, if applicable; * the file's access mode; * the file's lock status; * the file's device numbers; * the file's inode number; * the file's size or offset; * the name of the file system containing the file; * any available components of the file's path name; * the names of the file's stream components; * the file's local and remote network addresses; * the TLI network (typically UDP) state of the file; * the TCP state, read queue length, and write queue length of the file; * the file's TCP window read and write lengths (Solaris only); * other file or dialect-specific values. Getting Started Quickly ======================= If you want to get started using lsof quickly, or see some examples of how lsof can be used, consult the 00QUICKSTART file of the lsof distribution. The 00QUICKSTART file won't help you build or install lsof, but it will cut through the density of the lsof man page, giving you more readily an idea of what you can do with lsof. For information on building and installing lsof, consult the 00README file of the lsof distribution. Limiting, Filtering, and Selecting Lsof Output ============================================== Lsof accepts options to limit, filter, and select its output. These are the possible criteria: * Process ID (PID) number -- to list the open files for a given process; * Process Group ID (PGID) -- to list the open files for all the processes of a given process group; * User ID number or login name -- to list the open files for all the processes of a given user; * Internet address -- to list the open files using a given Internet address (host name), protocol, or port (number or name); or to list all open Internet files; * command name; * file descriptor name or number; * list all open NFS files; * list all open Unix domain socket files; * list all uses of a specific file; * list all open files on a file system. Selection options are normally ORed -- i.e., an open file meeting any of the criteria is listed. The selection options may be ANDed so that an open file will be listed only if it meets all the criteria. In the absence of any selection criteria, lsof lists files open to all processes. Parsing Lsof Output with Another Program ======================================== The lsof -F option directs it to produce "field" output that can easily be parsed by another program. The lsof distribution contains sample awk, perl 4, and perl 5 scripts in its scripts subdirectory that show how to post-process field output. Repeat Mode =========== Lsof can be directed to produce output, delay for a specified time, then repeat the output, cycling until stopped by an interrupt or quit signal. This mode is useful for monitoring the status of some file operation -- e.g., an ftp transfer or a tape backup operation. Repeat mode is more efficient when combined with lsof's selection options, since they limit lsof overhead. It's possible to use lsof's field output options to supply repeat mode output to another process for its manipulation. The scripts subdirectory of the lsof distribution has sample Perl scripts showing how to consume lsof repeat mode output from a pipe. Distribution Restrictions ========================= Lsof may be used and distributed freely, subject to these limitations: 1. Neither the author nor Purdue University is 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 author 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 from or altered in the lsof source files. Cautions ======== Lsof is a tool that is closely tied to the Unix operating system version. It uses header files that describe kernel structures and reads kernel structures that typically change from OS version to OS version. DON'T TRY TO USE AN LSOF BINARY, COMPILED FOR ONE UNIX OS VERSION, ON ANOTHER. On some Unix dialects, notably SunOS and Solaris, lsof versions may be even more restricted by architecture type. An lsof binary, compiled for SunOS 4.1.3 on a sun4c machine, for example, won't work on a sun4m machine. AN LSOF BINARY, COMPILED FOR ONE SOLARIS 1.X ARCHITECTURE, ISN'T GUARANTEED TO WORK ON A DIFFERENT SOLARIS 1.X ARCHITECTURE. Distribution Contents ===================== The lsof distribution is checked for completeness when it is constructed and by the Inventory script when you run the Configure script. (See The Inventory Script section of the 00README file of this distribution.) Lsof is organized in these parts: * The main lsof directory, containing common sources, configuration and setup scripts and three subdirectories: dialects/, lib/, and scripts/. Lsof is compiled in the main lsof directory after configuration. The selected dialect sources are copied or linked from the specified subdirectory. (Symbolic linking is the standard method.) Common lsof definitions may be found in lsof.h; common function prototypes, proto.h; and common storage, store.c. * The dialects/ subdirectory contains subdirectories with sources specific to UNIX dialect implementations -- e.g., the dialects/sun/ subdirectory contains sources for the SunOS (Solaris 1.x) and Solaris (2.x) implementations of lsof. The dialects subdirectories also contain Makefiles and scripts for assisting dialect source configuration. Dialect configuration definitions may be found in dlsof.h; other dialect definitions, dlsof.h; dialect prototypes, dproto.h; and dialect storage, dstore.c. * The lib/ subdirectory contains sources for common lsof functions. Not all dialects use the functions -- some have their own versions of them. The lib/ functions are enabled and customized with #define's in the dialect machine.h header files. * The scripts/ subdirectory contains sample scripts for processing lsof field (-F) output. The scripts are written in AWK, Perl 4, and Perl 5. The 00PORTING file of the lsof distribution has more information on lsof components, configuration, and construction. Warranty ======== Lsof is provided as-is without any warranty of any kind, either expressed or implied, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose. The entire risk as to the quality and performance of lsof is with you. Should lsof prove defective, you assume the cost of all necessary servicing, repair, or correction. Bug Reports =========== Now that the obligatory disclaimer is out of the way, let me hasten to add that I accept lsof bug reports and try hard to respond to them. I will also consider and discuss requests for new features, ports to new dialects, or ports to new OS versions. PLEASE DON'T SEND A BUG REPORT ABOUT LSOF TO THE UNIX DIALECT 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 . The lsof-l Mailing List ======================= Information about lsof, including notices about the availability of new revisions, may be found in mailings of the lsof-l listserv. For more information about it, including instructions on how to subscribe, read the 00LSOF-L file of the lsof distribution. Version 3 Release Notes ======================= See 00DIST in the last lsof 3 revision 3.88, for its complete set of release notes. Lsof revision 3.88 may be found at: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/OLD 3.0 May 24, 1994 This is the first official release of lsof 3. ... 3.88 February 17, 1997 +======================================+ | This is the last version 3 revision. | +======================================+ Added documentation files -- 00.README.FIRST[_] and 00RELEASE.SUMMARY_ -- to the distribution. What's new in Version 4 ======================= The main goal of version 4 was to eliminate the confusing common/ fragment source file technique. Changing the version number also provided an opportunity to restart the numbering, which at 3.88 had risen to a large value. The sources that appeared in the dialects/common subdirectory of version 3 in fragment files have been incorporated into the version 4 liblsof.a library as *.c files. This results in significant changes to many source files, scripts, and Makefiles of all dialect versions. It allows elimination of some source files -- ddev.c, dfile.c, dmnt.c -- for dialects now obtaining functions from liblsof.a that formerly came from making dialect source files by combining fragment files. The version 4 liblsof.a sources are stored in the lib/ subdirectory of the main lsof directory. The liblsof.a functions are activated and conditioned in their source files by values #define'd in the dialect dlsof.h and machine.h header files. Dialects that provide a private version of a library function refrain from #define'ing the symbol that would activate the library function code. Version 4 Release Notes ======================= 4.0 February 24, 1997 +====================================+ | This is the first lsof 4 revision. | +====================================+ Reorganized sources: eliminated code fragment files and created a library in their place. Modified or deleted many dialect source and header files. Changed documentation accordingly. Added a warning to sgi/Makefile and 00FAQ that advises against using the IRIX C compiler -n32 option when compiling lsof. Thanks go to Peter Ilieve for bringing this to my attention. Dropped IRIX 5.2 in mid-stream, because my 5.2 test system was upgraded to 5.3. 4.01 March 3, 1997 Added TFS support for Pyramid dialects. Added test to Configure and to the IRIX dnode.c for the different cnode struct that appears in on the 6.2 IMPACT distribution. Heddy Boubaker alerted me to the cnode change and helped test this lsof adjustment. Shut down the lsof child process before doing a -r sleep(). A comment from Dan Mercer prompted this. 4.02 March 21, 1997 Based on a report from Pasi Kaara , disabled HP-UX CCIT support in lsof for HP-UX versions 10 and above. Pasi's report also led to changes in the HP-UX machine.h to support use of gcc to compile lsof for HP-UX 10.20 and warnings against using `cc -Aa` or `gcc -ansi` to compile lsof under HP-UX 10.x. With help from Richard Allen taught HP-UX 10.x lsof to name file systems better by using the virtual file system device number. Elias Halldor Agustsson provided a test system. Changed NEXTSTEP and UNIXWARE Makefiles to use safer quoting when generating version.h. The change was suggested by Bob Farmer . Added SHELL=/bin/sh string to all Makefiles. Added support for Linux 2.1.28 on a test system, kindly provided by Jonathan Sergent . Configure tests the Linux 2.1.x's C library lseek() function for proper handling of kernel offsets. If lseek() appears suspect, Configure activates the use of a private lseek() function. Changed the private nlist() function to nlist_private() and taught it to use the query_module() syscall in place of the deprecated get_kernel_syms() one. Added rudimentary AX.25 support for Pierfrancesco Caci who helped test it. Updated the old get_kernel_syms() code to recognize and skip module name entries. Prompted by Marty Leisner , eased the requirement that service name lookup for the -i option be accompanied by a protocol name. The name is not needed if both TCP and UDP names yield the same port number. Added xusers.awk script from Dan Mercer to the distribution scripts/ subdirectory. Changed Configure script to use LSOF_VERS for all UNIX dialect version numbers and to pass LSOF_VERS to the dialect Mksrc functions. Also added the ability for a dialect stanza to declare a different dialect Makefile source. Modified dialect Mksrc files -- e.g., linux and sun -- accordingly. Added support for BSD/OS 3.0 with help from Jim Reid . Terry Kennedy kindly provided a test system. During the port corrected a bug that prevented proper handling of revoked files. 4.03 April 7, 1997 At the suggestion of Dan Mercer , made HP-UX building of lsof aware of differences between the HP-UX bundled and unbundled C compilers. Added the ability for the lsof builder to define the default warning message issuance state. By default the issuance of warning messages is disabled; defining WARNINGSTATE in machine.h disables it. The Customize script was updated to handle WARNINGSTATE. Dan Mercer suggested this. Eliminated compiler complaint about improperly cast get_Nl_value() argument in ncache_load() in lib/rnch.c. Corrected zeromem() argument error in SCO dproc.c. Sped up parent directory cache lookup slightly. Updated for PTX 4.4, including additional VxFS (EFS) file system support. 4.04 April 17, 1997 At the suggestion of Bela Lubkin changed device cache handling to be more tolerant of a device cache file whose [cm]times are older than the ones on /dev or /devices. The change required adding information to Solaris device cache file clone lines, so the first time lsof 4.04 is run under Solaris it will complain about a bad cached clone device in a previous device cache file, then regenerate it. Added boot file path detection for SCO OSR 5 and above, based on information supplied by Bela. Fixed two bugs in DEC OSF/1 lsof -- an error in reporting locks and a missing continue statement in readdev() after a failure to open a directory. Jan Ole Suhr reported the second bug and supplied a fix. Fixed XFS problems with IRIX 6.2 by abandoning the idea that SGI will distribute XFS header files and defining an lsof-private xfs_inode structure. John Paul Morrison helped develop and test the 5.3 definition. John R. Vanderpool helped develop and test the 6.2 definition. Remove obsolete comments about common/*.frag files. Updated Linux lsof for Linux version 2.1.35. 4.04 April 18, 1997 Supplement Regenerated the 4.04 distribution to correct a non- device-cache #define misplacement in the Solaris and SunOS dlsof.h. Alexandre Oliva reported the problem. 4.05 April 24, 1997 Corrected an error in 00DCACHE. Made sure SCO /etc/ps/booted.systems is closed. Based on an observation by Bela Lubkin that the lsof child had needless file descriptors open, closed all but the open pipes between the lsof parent and child. Decommissioned CDC EP/IX support; I no longer have a test system. Based on a suggestion from Patrick Connor , added -xansi to CFLAGS for IRIX 5.3 and 6.[234]. Also at Patrick's suggestion changed Configure to propagate exact SunOS 4.1.x version to the main and library Makefiles. This allowed the sunos413 and sunos413cc Configure abbreviations to be shortened to sunos and sunoscc. Updated obsolete argument uses (-H changed to -n) in count_pf.perl* and watch_a_file.perl scripts. Adjusted Solaris 2.6 lsof for Beta_Update with tips from Casper Dik . Fixed a Solaris 2.4 TCP address reporting bug. 4.06 April 30, 1997 Added a step to the Makefile clean rules that does a make clean in the lib subdirectory; suggested by Casper Dik . (Configure's -clean argument already did this.) Fixed an incorrect awk argument in the sunos*) Configure stanza, reported by Alexandre Oliva . Added CD9660 (aka ISO) file system support to FreeBSD, NetBSD, and OpenBSD with mods and help from Kenneth Stailey . (BSDI already had CD9660 support.) While at it, added file descriptor system support to BSDI and FreeBSD. Added /kern file system support to OpenBSD. The support wasn't extended to BSDI, FreeBSD, or NetBSD, because it requires Kenneth Stailey's changes to /sys/miscfs/kernfs/kernfs.h. Updated IRIX 6.3 support after getting access to a test system, provided by John Paul Morrison . Improved the handling of IRIX 5.1 and greater FIFOs. 4.07 May 12, 1997 Based on AIX problem reports from David Capshaw , changed the aix* Configure script stanza to avoid -bnolibpath for gcc (which the GNU loader doesn't grok) and AIX below 4.1.4 (where -bnolibpath hasn't been tested or is known to be unimplemented), and to refuse to use gcc for compiling lsof in AIX versions below 4.1 (because of possible structure alignment problems). Updated 00FAQ appropriately. Added OpenBSD support for EXT2FS. This support has yet to be tested. Tested lsof under OpenBSD 2.1. Activated /kern file system support for NetBSD when Configure senses that /sys/miscfs/kernfs/kernfs.h defines the kern_target structure. This support has not been tested under NetBSD, although it has been tested under OpenBSD. Made some simple changes to the BSDI machine.h, suggested by Jeffrey C. Honig . Improved handling of alternate dialect Configure abbreviations -- aix and aixgcc, hpux and hpuxgcc, solaris and solariscc, and sunos and sunoscc. 4.08 May 23, 1997 Cleaned up dialect Makefile's, staring with a suggestion from Christopher Schanzle . Improved Configure's -clean processing. Corrected bugs in Solaris lock reporting. Changed NetBSD Configure stanza to put -I/usr/include before -I/sys. 4.09 June 1, 1997 Adjusted for latest FreeBSD 3.0 release. This required adding a new kernel name cache module for reading BSD-form hashed kernel name cache entries, rnmh.c, to the lsof library, and adding a #define to each machine.h to select it. Activated rnmh.c for BSDI 2.1, BSDI 3.0, NetBSD 1.2, and OpenBSD 2.1. 4.10 June 8, 1997 Adjusted for Linux 2.1.x (x > 35) kernels with hashed task structure pointers. Marty Leisner and Jonathan Sergent tested the adjustment. Replaced readdev() stat() calls with lstat() to reduce device table and cache entries with the same device number and inode values. Added code to remove all remaining duplicates. This fixes a Linux problem reported by Jonathan Sergent and makes device node name output predictable. Corrected a bug in UnixWare stream file handling that prevented searching for the stream file by its associated character device name. Added Pyramid code to determine Reliant UNIX clone major device number differently from that of DC/OSx. 4.11 June 12, 1997 Changed Configure to sense that the PTX inp_[fl]addr members of the inpcb structure of have a struct type and set HASINADDRSTR for use in PTX dnode.c and dsock.c tests. Changed PTX version 4.1.4 tests to use 4.1.3 instead. Carson Wilson reported the need to do this and tested the change. Fixed a block device table indexing bug in lib/rdev.c, reported by Carson Wilson. The same bug was squashed in pyramid/ddev.c. Added code to the Pyramid Reliant UNIX kread() function to compensate for an address boundary error in the kernel's /dev/kmem driver. Verified that lsof compiles and works under AIX 4.2.1. Added an AIX test for the presence of NFS header files, defined HAS_NFS and adjusted AIX dialect sources accordingly. Based on a suggestion from Gaylord Holder , added DEC OSF/1 code to auto-detect the booted file, whence kernel symbol addresses are obtained. 4.12 June 24, 1997 Corrected a device number sign extension problem in the reading and writing of device cache file. The problem was reported by Bela Lubkin and he suggested a fix. Fixed an SCO stream device lookup problem. The report and solution came from Bela Lubkin Enhanced the Configure script to enable cross- configuration of lsof, based on suggestions from Marty Leisner . A new documentation file, 00XCONFIG, describes the process. Made Pyramid OBJFS support conditional on the presence of supporting header files. Corrected the Pyramid MkKernOpts script so it generates the necessary -D's for the Nile/Jolt architecture. Richard Coley helped. Added another IRIX xfs_inode variant for 6.2, 32 bits, no XFS rollup patch. Tested under UnixWare 2.1.2. 4.13 July 9, 1997 Taught Pyramid lsof to grok ttyfs vnodes with help from Richard Coley . Fixed some minor bugs in Pyramid FIFO reporting. Eliminated use of the Pyramid UCB compatibility library at Richard's suggestion. Eliminated reporting of "strange" inode numbers for SCO OSR 3.2v5.0.x HPPS files with help from Bela Lubkin Modified port to service name lookup to use a small number of getservbyport() calls before reading the entire map with getservent(). Changed port reporting to represent a zero as `*' to be consistent with other prt number reporting tools like netstat. Casper Dik suggested these changes -- the getserv*() one to improve performance for large NIS service name maps. Changed all readdev() functions to make the absence of block devices a warning instead of a fatal error after Brian Redman reported his IRIX 6.4 system had no block devices. (It really did have block devices, but readdev()'s lstat() use caused it to miss them in a directory symbolically linked from /dev/dsk->/hw/disk.) Fixed Brian's real problem by changing the IRIX readdev() to use stat() on /dev nodes if a Configure test shows /hw is readable. Extended the potential to do the same to all readdev() functions. For consistency and convenience changed some Configure abbreviations and dialect subdirectory names: "decosf" abbreviation and "osf" dialect subdirectory name to "du"; "netbsd" dialect subdirectory name to "n+obsd"; "next3" abbreviation and "next" dialect subdirectory name to "ns"; "sco" abbreviation and dialect subdirectory name to "osr"; "sgi" dialect subdirectory name to "irix"; and "unixware" abbreviation and dialect subdirectory name to "uw". Added #if/#endif clauses to the AIX rmdupdev() function to avoid clone processing for AIX versions less than 4.1.4. The problem was reported by Toralf Foerster , who supplied corrective code. Added support for new style NetBSD inode with i_ffs and i_e2fs union members. Improved Configure and 00FAQ information on Digital UNIX configuration subdirectory with suggestions from Brad Krebs . 4.14 July 22, 1997 Reorganized the Solaris handling of the inode structure header file, ufs_inode.h, to eliminate VxFS structure definition conflicts for Solaris 2.4, based on information from Greg Earle . Cleaned up some typos and confusion in Configure's help output, based on comments from Bela Lubkin Added a 00DIALECTS file, containing UNIX dialect version numbers, that can be used by Configure and the man page. 4.15 August 15, 1997 Aligned `Configure -help` output better. Removed Configure's 2.6 Beta test adjustments. Added improved Solaris VxFS configuration and handling, based on information from Greg Earle . Added socket state -- TCO or TPI -- for socket files at the suggestion of Ian Fitchet . 4.16 September 25, 1997 Added reporting of TCP/TPI queue lengths and window sizes ala netstat to NAME column. Added -T option to select or de-select TCP/TPI info reporting. (Window sizes are only reported for Solaris.) Fixed anomalies along the way in SIZE/OFF processing for some dialects. Fixed service name argument processor to allow minus signs as part of the name. Consequently this disallows names with embedded minus signs from being specified as the start of a range. Added 00FAQ entries explaining why lsof won't find a file being edited with vi, why window sizes aren't reported for all dialects, and what the "no more information" message means. Forced Pyramid CC to be /usr/ccs/bin/cc to avoid accidental use of the BSD variant in /usr/ucb/cc. Added support for Linux glibc2, including a Configure test; cross-Configure support (00XCONFIG); and much unfortunate and risky sleight-of-hand in lsof Linux dialect header and source files, forced upon lsof by incompatibilities between Linux kernel and glibc2 header files. Included in scripts/identd.perl5 a Perl 5 implementation of an identd server, using lsof, provided by Kapil Chowksey . Updated IRIX 6.4 xfs_inode guess. 4.17 October 14, 1997 Added -V option for verbose search result reporting. Verbose reports are prepared for failure to locate file names, command names, Internet addresses or files, login names, NFS files, PIDs, PGIDs, and UIDs. Augmented Linux NFS file test to cope with kernels whose NFS code is in a loadable module. Need for the test was pointed out by Jonathan Sergent . The change required that Linux have private dmnt.c source, Completed a Linux 2.1.57 port on a system provided by Jonathan Sergent. 4.18 October 25, 1997 Eliminated memory leaks in alloc_lfile(), lkup_port(), and NEXTSTEP's process_text() function. Added recognition of OpenBSD 2.2 in Configure, supplied by Kenneth Stailey . Consolidated print_file() functions to use the one in lib/prtf.c. Made it configurable and changed it to size print columns dynamically. !!! WARNING !!! WITH DYNAMICALLY SIZED PRINT COLUMNS LSOF 4.18 PRODUCES OUTPUT SIGNIFICANTLY DIFFERENT FROM THAT OF PREVIOUS REVISIONS. LINES ARE GENERALLY SHORTER AND THERE IS GENERALLY LESS BLANK SPACE BETWEEN COLUMNS AND THE ITEMS IN THEM. THERE ARE NO LONGER ANY SPACES BETWEEN DEVICE NUMBER ELEMENTS, ONLY COMMAS. !!! WARNING !!! Added special types and print specification modifiers for file size and offset to handle UNIX dialects with 64 bit sizes and offsets. Paul Eggert reported the need for this addition. With Paul Eggert's help picked lint from the lsof library, the main level lsof sources, and the Sun dialect sources. Added documentation, including the file 00LSOF-L, about the lsof-l LISTSERV. Added support for Reliant UNIX on the RM600. Bob Passarella supplied the changes. Kevin Smith helped arrange test systems. While incorporating Bob's changes, modified lib/rnch.c to handle kernel ncache structs whose name is accessed via a char *, rather than in a char array. Changed #include order of for Solaris 2.x. W. Richard Stevens pointed out the need to do this. 4.19 October 30, 1997 Changed Pyramid Reliant RM600 proc scan to skip SSYS (p_flag) processes, since they don't seem to have a readable u_cdir vnode. Enabled Pyramid Reliant UNIX kread() work-around for DC/OSx, too, since its read(/dev/kmem) kernel driver seems to share the page boundary bug this work-around circumvents. Changed SzOffFtm_d and SzOffFtm_dv (new formats at 4.18 to print size and offset) from signed to unsigned. Setting them signed at 4.18 was an oversight. Plugged a memory leak that caused the loss of 130 bytes per repeat-mode pass. Fixed it with a simple work-around in main(). Lionel Cons reported the leak. 4.20 November 11, 1997 Tested under BSDI 3.1. Added support for Reliant UNIX Mesh IPC files with help from Billy Ho . Added support to Digital UNIX lsof that uses the libmsfs tag_to_path() function (when it exists) to look up AdvFS path names. The idea and sample code came from Dean Brock . Converted Dean's code into more general purpose support for private name cache lookups via the HASPRIVNMCACHE #define in the dialect machine.h file and code conditional on it in the printname() function. Taught Digital UNIX lsof to recognize NFS3 file systems. Corrected Digital UNIX lsof DEVICE column alignment. 4.21 December 1, 1997 Squashed bug, introduced at revision 4.18, that resulted in double reporting of each selected PID when terse mode (-t) was specified. Corrected minor bug, also introduced at 4.18, that might cause an extra print_proc() pass when one PID has been specified. Added -R to lsof options in scripts/idrlogin.perl*. The option should have been there -- it was supposed to be mandatory for PGID reporting -- but a bug, corrected in revision 4.18, previously made -R unnecessary. Enabled configuring for BSDI BSD/OS 4.0 per a suggestion from Jeff Honig . Enabled replacement of scoff_t with off64_t (scoff_t is used to type r_size and r_localsize in the rnode struct) for IRIX 5.3 systems that have the NFS kernel rollup patch (1477). This compensates for SGI's failure to distribute an updated with their patch. Validated under Linux 2.0.3[12], Linux 2.1.64, and NetBSD 1.3. Added FreeBSD root directory reporting, courtesy of Dan Nelson . 4.22 December 15, 1997 Made adjustments for Linux 2.1.7[02]. Improved NAME information for Linux UNIX domain sockets. Added option +|-M to control the reporting of portmapper registration information in square brackets after the TCP or UDP port or service name. Kenneth Stailey suggested the feature and provided sample code from OpenBSD. Reporting is disabled by default in the distribution and may be enabled with +M; if lsof is compiled with HASPMAPENABLED (e.g., from machine.h), reporting will be enabled by default and can be disabled with -M. Changed the -w option to +|-w to match the syntax of the +|-M option and to eliminate any options that flip meaning when a symbol is defined at compile time. For both +|-M and +|-w, specifying `-' when the default state is disabled or specifying `+' when the default state is enabled causes no problems. !!!WARNING The -w option has changed in lsof 4.22. WARNING!!! Made the +|- prefix legal for most options, but didn't document it in the man page or help panel. Most options that disable something -- e.g., -b, -C, -n, -P -- now disable when the prefix is `-' and enable when it is `+'. Since the states these options disable are enabled by default, I chose to avoid documentation complexity and confusion by not mentioning that they can be used with the `+' prefix. Condensed the help panel. Made sure Digital UNIX Configure stanza puts normal include path (e.g., /usr/include) before system include paths. Added IPX socket information reporting to Linux with help from Jonathan Sergent . 4.23 January 16, 1998 Fixed conflict arising from the quondam replacement of the Sun Solaris with a BIND/BSD version. With help from Jonathan Sergent developed a /proc file system based Linux lsof. It needs some Linux 2.1.x release to work -- I'm not sure which, but I tested under 2.1.72, 2.1.76, and 2.1.79. The Configure script selects special sources for this lsof, so the full lsof distribution now contains both /dev/kmem and /proc based sources for Linux lsof. An optional kernel mod, written by Jonathan, enhances the /proc-based lsof ability to recognize IPX socket files. Reorganized and augmented the Linux sections in 00FAQ to explain the two types of Linux lsof. Defined DOSTAT_FUNCTION for dostat() in misc.c to select the function, stat() or lstat(), it will use. DOSTAT_FUNCTION is normally undefined, defaults to lstat(), and is only defined for the /proc-based Linux lsof in its dlsof.h. Made conditional on the presence of IRIX 6.4 XFS rollup patch #6 an XFS node change introduced in revision 4.16. Identified the patch with help from John R. Vanderpool . Added NFS node compensation for NetBSD 1.3. The code and suggestion for it was supplied by Jean-Luc Richier . Added diagnostic messages to the /dev/kmem-based Linux Mksrc script to report errors during the construction of the kernel name cache header file, kncache.h. Added 00FAQ information on kncache.h. Added a new Linux test host, running 2.0.33 and GlibC, provided by Steve Logue . Ported to PTX 4.1.3 and 4.4.2. Adjusted lib/rnch.c for 4.4.2 to allow customization f additional ncache struct element names. 4.24 January 28, 1998 Changed /proc-based Linux lsof offset test to use "/" instead of "/etc/passwd". To assist Jim Mintha with the packaging of lsof for Debian Linux, added a DEBIAN_LINUX_LSOF #define to trigger the activation of special system map file location code in the /dev/kmem-based dproc.c. Applied modification to dialects/bsdi/dlsof.h from Ingimar Robertson , enabling lsof to compile for BSDI BSD/OS 2.0. Corrected a documentation error in 00DCACHE, pointed out by Thomas Anders . The error was created when the -V option was added at lsof 4.17. Made IRIX 5.3 through 6.3 lsof aware of IRIX SCSI tape devices (e.g., /dev/tape). Dave Olson of SGI and Randolph J. Herber of FNAL provided valuable advice, and Igor Schein helped test. Added a machine.h symbol (NEVER_HASDCACHE) that prevents Customize from offering to change HASDCACHE. The symbol may appear anywhere in machine.h -- e.g., in a comment. Included the symbol in a comment of the HASDCACHE section of the /proc-based Linux lsof machine.h, and accompanied it with warnings against #define'ing HASDCACHE. Did the same thing for WARNDEVACCESS (NEVER_WARNDEVACCESS is the suppressant.) 4.25 February 7, 1998 Corrected an IRIX mis-cast of file offset (position). Igor Schein reported the problem. This was offered as a patch to 4.24. Picked some lint Igor pointed out. At Igor's suggestion added an optional decimal digit size argument to the -o option. This argument specifies how many file offset decimal digits can follow "0t" before lsof switches to a "0x..." form. The argument size specification doesn't count the two characters of the "0t". A size of 0 means unlimited. The default is OFFDECDIG (8), preserving compatibility with existing lsof output; it can be changed by the lsof builder. When size is specified with -o it does not force offset display; -o without a size still must be used to do that. Added an IRIX 6.2, 32 bit system, XFS node patch, courtesy of Ulrich Bernhard . For my own convenience enabled Configure to use /usr/local/bin/gcc for NEXTSTEP. This allows circumvention of a gcc 2.8.0 ranlib problem on my test 3.1 `040 cube. Added flags recommended by the RISC/os and Ultrix compilers for the updated (and longer) main.c. Updated FreeBSD cd9660_node.h Configure test. 4.26 February 17, 1998 Added shared process group processing for IRIX 5.3, and IRIX 6.1 and above, based on investigation of a bug report from Igor Schein . Igor helped test this addition. Improved handling of file system name arguments. It's now done in a manner similar to fuser. The -f argument forces path names to be considered as simple files, rather than as file system names. The +f flag forces them to be considered as file system names. Normally path arguments are considered file system names when they match a mounted-on directory in the system's mount table, or when they match a mounted file system's block device. Igor Schein helped test this change. Igor also suggests that the proper compilation of the IRIX 6.4 proc structure after patch 2536 has been installed may need -DPIOMEMOPS. So lsof's MkKernOpts script was updated to propagate that option from CCOPTS in /var/sysgen/system/irix.sm, even though patch 2536 doesn't add -DPIOMEMOPS to it. Added a 00FAQ item on this patch. Added a fatal warning message about names forced to be file system names (with +f) that have no match in the mount table. Improved the -V message for files and file systems for which no open files were found. Added reporting of /proc file and file system search failures. Did some code reorganization to combine the multiple ck_file_arg() functions into one. Moved the new function from the library to the top level and put it in arg.c; moved the usage function from arg.c to a new top-level source file, usage.c, to balance top-level source file size. The new usage.c depends on version.h; arg.c no longer does. Added flag recommended by the DU compiler for the updated (and longer) main.c. 4.27 March 6, 1998 At the request of Igor Schein added a conditional repeat mode option, using the `+' prefix to the `r' option. +r operates as does -r with the exception that it exits the first time no open files have been listed during a cycle. The exit code will be zero when any open files have been listed; one, if none were ever listed. Ported lsof to HP-UX 11.0 with the help of Richard Allen. This port hasn't been tested on a 64 bit kernel; I'm sure it won't work there without more mods. It may not work on PA 2 architectures; I've only tested it under PA 1 and a separate, busy tester reported PA 2 problems that I've been unable to investigate. In anticipation of getting access to a 64 bit HP-UX kernel and the pending start of the Solaris 2.7 Beta test (It will have 64 bit kernel addressing.), started adding support for 64 bit kernel pointers. This includes: ubiquitous use of the KA_T cast for kernel pointers; a format to print them, KA_T_FMT_X; a function to print them, print_kptr(); and modifications to most kernel-related functions -- e.g., process_file(), process_node(), process_socket(), readvfs() -- to process kernel addresses as KA_T types. Fixed minor bug in handling path name arguments that end with a `/'. Removed support for RISC/os; its test system is no longer available. Made modifications to insure that lsof output doesn't contain non-printable characters. All such characters are now printed in the printf form "\x%02x". Several new common functions were installed in misc.c to support "safe" printing. This second major modification in 4.27 to common and dialect code could have introduced bugs not yet detected. 4.28 March 10, 1998 Refined unprintable format to use \b, \f, \r, \n, \t, and ^* (for CTRL) forms. Corrected omission of safestrprt() use for field output command name. These changes were offered as patches to 4.27. Made space an unprintable character (\x20) in the COMMAND column; printable elsewhere, including the NAME column, field output, and error messages. Made sure FD column is parseable as a single entity -- i.e., has no embedded space. Thus, if the access mode is unknown but there is a known lock mode, (a very rare case) the access mode will be printed as `-'. Picked lint with gcc 2.8.0 under Solaris 2.6. With the help of Dave Olson of SGI identified a proc struct element that should have been added to by IRIX 6.4 patch 2536. Added a work-around for it to the lsof Configure script. Igor Schein identified that the patch caused a proc structure length complaint from lsof. Removed an obsolete 00FAQ item on the patch, installed at lsof 4.26, explaining that no solution was yet available. Added a 00FAQ item on how BIND installs its own header files, including , which may cause the rpcent struct definition to vanish. Solaris has an automatic lsof work-around, but that hasn't been (and probably can't be) propagated to all dialects supported by lsof. The 00FAQ item recommends re-installation of the vendor header files that BIND has replaced. (Others include , , and .) Made AIX AFS fixes. 4.29 March 26, 1998 Corrected bug in Internet address matching. The matching formerly stopped if the foreign address matched, thus failing to check the local address for a match. That led to a possible false "Internet address not located" warning (i.e., in response to -V) about the local address, when both foreign and local addresses were specified with -i. This correction was offered as a patch to 4.28. Changed readmnt() usage in an attempt to defer mount readlink() and stat() delays until they are necessary. Corrected two bugs in the Digital UNIX readdev() function. Made the correction available as a patch to 4.28 and regenerated the 4.28 DU binaries. Added a missing argument to a print-kptr() call in the HP-UX dsock.c. The missing argument causes a fatal gcc error. The problem was reported by Eyal Shaynis . The fix was offered as a 4.28 patch. Adjusted for Digital UNIX 4.0D; the spec_node structure is now defined in . Kris Chandrasekhar identified the need for the adjustment. Incorporated a bug fix from Brian McAllister to the DU readmnt() function. This fix was offered as a patch to 4.28. Added "safe" printing to a SunOS clone device error message. Corrected bug in tabling of Linux /proc-based lock info. Corrected bug in handling of SunOS TLI streams. Dan Farmer reported the problem. Added a Solaris 2.6 work-around to keep the BIND from colliding with the Solaris . Strengthened the Configure test for /proc-based Linux lsof, based on a report from Marty Leisner . Tested on OpenBSD 2.3. Made AIX changes that allow use with 3.2.5. The changes were suggested and tested by Brett Hogden . Added Solaris 2.6 AFS support. Disabled reporting of some node numbers for Solaris 2.5 and above open AFS files. The node number computation algorithms used for SunOS 4.1.x and Solaris less than 2.5 no longer always work under Solaris 2.5 and above. 4.30 April 9, 1998 Corrected a pid structure member naming error for UnixWare < 2.1.2. The problem was reported by Richard van Meurs . He supplied the correction. This was offered as a patch to 4.29. Had a report from Igor Schein that IRIX 6.4 patch 2839 is another SGI kernel patch, along with 2536, that changes the size of the proc structure in the kernel without changing the proc structure in . Upon further investigation found that the effect of these patches on the proc structure is not consistent. Therefore, dropped the Configure patch test for IRIX 6.4 and made the code in irix/dproc.c slightly more tolerant of proc structure size differences for IRIX 6.4. Igor help test the change. Corrected Solaris >= 2.5 AFS inode number generation. Craig Everhart helped find the cause of the problem. This was offered as a patch to 4.29. Refined the Linux /dev/kmem-based glibc evasion for the timeval structure to make it work with glibc version 2.0.7. This required defining a new global symbol, TIMEVAL_LSOF, default timeval, that the /dev/kmem-based Linux lsof can set to its private glibc timeval name, distinct from the kernel timeval name. Added support for Alpha to the /dev/kmem-based Linux lsof. Alexandre Oliva provided a test system. Added an item to 00FAQ about lsof, the Alpha processor, and Linux. Added a 00FAQ item about lsof year 2000 compliance. Basically it says lsof is probably compliant, because its only date or time computations are done with time_t values, but I haven't done any specific Y2K validation. I don't have plans to do any. Added support for UnixWare 7. Chris Daniels provided a test system and Don Draper provided technical information. Added BFS and SFS file system support to lsof for UW 2.1.[12] and 7. Updated Solaris VxFS support for VxFS 3.2.1. Greg Earle reported the need for the update. Greg and Roger Klorese provided technical information. Scott McClung tested. Changed IRIX XFS patch detection in anticipation of learning there are multiple XFS patches for IRIX 6.4 that require different versions of the lsof-invented xfs_inode structure. 4.31 April 21, 1998 Added a VxFS #if/#endif wrap to a section of the HP-UX dnode.c that wasn't properly protected. The problem was reported by Peter Klosky . This was offered as a patch to 4.30. Added support for Solaris 2.7 (first Beta release). Mike Sullivan provided technical advice and helped test. Charles Stephens also helped test. Fixed bug in /proc-based Linux that caused it to access /proc/mounts excessively. Marty Leisner provided a syscall trace that identified the bug. The fix was offered as a patch to 4.30. Adjusted the IRIX 6.4 private structure definition for the XFS node to accommodate patch 2970. Igor Schein identified the patch and the required adjustment. 4.32 May 11, 1998 Corrected Solaris 2.7 code for reporting PCFS (floppy disk) node numbers. Casper Dik supplied the fix. The fix was offered as a patch to 4.31. Corrected a bug in conditional repeat mode handling pointed out by Igor Schein . This was offered as a patch to 4.31. Improved reporting of AIX open(/dev/memory device) errors. Corrected a Solaris < 2.5 KA_T declaration error, pointed out by Robert Kiessling . Changed KA_T from a #define to a typedef for all dialects to prevent future problems of this kind. Changed the sample Perl 5 script big_brother.perl5 to report a four digit year from localtime(). Added support for AIX 4.3[.1]. Bill Pemberton provided a test system. Andrew Kephart and Tom Weaver provided technical assistance. Niklas Edmundsson did 4.3.1 testing. Added -qmaxmem option to CFLAGs for an AIX compilation with an xlc version 4.x compiler. Adjusted Linux socket handling for changes in the AX25 members of the sock struct. Richard Green pointed out the problem. Tested /dev/kmem-based lsof under Linux 2.0.34. 4.33 May 22, 1998 Added generic IPv6 support to common lsof sources and specific IPv6 support to AIX sources. Andrew Kephart supplied the additions and helped with testing. Bill Pemberton provided a test system. The modification affected sources for every dialect, whether it supports IPv6 or not, by changing the interfaces to the common Internet address function ent_inaddr(). Added support for the NetBSD UVM virtual memory system. Paul Kranenburg supplied technical details. Bracketed HP-UX 11 use of with #if/#endif _KERNEL. Corrected printing of PCB address in DEVICE column for IRIX. 4.34 June 26, 1998 Updated 00FAQ to discuss TCP and UDP ports private to the AIX kernel and 00README to describe how ACLs can be used to give lsof permission to read the kernel memory devices. Add information to 00FAQ and 00README about other OpenBSD architectures where lsof is reported to compile and run. Added section to 00FAQ discussing how an incorrect loader path environment variable value can prevent lsof from loading correctly. Improved Solaris namefs and doorfs support so that it is now possible to search for an open VDOOR file by the path name of its fattached file system object. Igor Schein requested the ability to do such a search. Even with the change, lsof can't always identify path names for open VDOOR files. Also at Igor's request, improved reporting of information on open Solaris VCHR files that share a common vnode, and Solaris UNIX domain socket files. Corrected print_kptr() argument error in PTX dnode.c, reported by Mark Price . Compensated for ncache element naming differences, introduced at PTX 4.4.2; Kurtis D. Rader reported the problem. Changed output column title from INODE to NODE to better reflect the column's contents of node IDs for more than just inodes. Improved Configuration and processing for Solaris AFS. Corrected AIX AFS 3.4 afs_rwlock_t simulation. Corrected a cast problem with two AIX knlist() calls, thus quieting an AIX 4.2.1 compiler argument type warning. Jon Champlin reported the problem. Added support to most dialect versions (exception: /proc-based Linux) to warn when the identity of the kernel where lsof was compiled doesn't match the running identity. The warning can be suppressed with -w. Note: determining AIX state requires calling oslevel, a potentially slow operation. Jon Champlin suggested this addition. !!!! WARNING !!!! !!!! WARNING !!!! !!!! WARNING !!!! Those using the lsof cross-configuration capability (see 00XCONFIG), should be aware that the kernel identity test feature introduces two new basic cross configuration environment variables, LSOF_ARCH and LSOF_VSTR. !!!! WARNING !!!! !!!! WARNING !!!! !!!! WARNING !!!! Identified a situation where a Solaris UNIX domain socket name is known and can be searched for by name; added the necessary code. 4.35 July 17, 1998 Made the kernel identity check an option with the HASKERNIDCK #define in machine.h. Enabled altering of HASKERNIDCK with the Customize script. Added a clause to the help output that indicates the build-time HASKERNIDCK status. Added more information to the NAME column for Solaris UNIX domain sockets. Made them searchable by their clone device path name. Igor Schein requested this. Completed the HP-UX 11 port with support for its optional 64 bit kernel. Rich Rauenzahn provided a test system. Corrected errors with HP-UX 11 lock reporting and private kernel structure and type definitions. Added support for HP-UX NFS3 files. Limited mount table warnings -- e.g., when -b is used -- to one set per mount point. Fixed some mount table scanning and usage bugs, including one in Solaris, reported by Kjetil Torgrim Homme . 4.36 August 4, 1998 Made corrections and additions to IPv6 support and to AF_ROUTE socket handling, supplied by Jean-Luc Richier . Jean-Luc's additions provide IPv6 support for the Inria IPv6 implementations on FreeBSD and NetBSD. Fixed two Solaris 2.5, 2.5.1, 2.6 and 2.7 TCP and UDP host name or IP address reporting bugs, reported by James Mathiesen . This fix was offered as a patch to 4.35. Updated the Customize script to cause ENTER to use all defaults. Amir J. Katz suggested this and helped test the changes. Updated Solaris ICMP and IP stream handling, based on a report from Igor Schein . Fixed a bug in the Digital UNIX mount table handling, reported by Bob Ward . While working on the bug, found and updated some obsolete AdvFS code. This fix was offered as a patch to 4.35. 4.37 September 15, 1998 Deactivated SGI IRIX support and archived revision 4.36 sources and binaries in pub/tools/unix/lsof/OLD. Improved performance of FD searching. This was offered as a patch to 4.36. Amir J. Katz pointed out that ranlib isn't needed for AIX or Solaris. Made appropriate Configure script changes. Fixed a file offset reporting bug for HP-UX VCHR and VBLK device nodes located on a VxFS root. Doug Siebert reported the bug. The fix was offered as a patch to 4.36. Resolved an HP-UX root device name reporting bug, partly caused by an out-dated local copy of the mount structure, by generating a local header file with the structure that can be compiled without needing _KERNEL defined. Doug Siebert also reported this bug. Changed some dialect source code -- Digital UNIX, Solaris, SunOS, and UnixWare -- to make more consistent with ps the user ID lsof reports in the USER column. Added a 00FAQ entry about it. Igor Schein reported the Solaris and SunOS lsof inconsistencies with what ps(1) reports. Ported lsof to Pyramid ReliantUNIX 5.44. Added brackets as comments to case, do, done, else, endif, esac, if, and while statements in Configure to assist in navigating its clauses. Added more Linux 2.0.x glibc work-arounds. Added support for UnixWare 7.0.1. Ralph Forsythe provided a new FreeBSD test system. 4.38 November 25, 1998 Added support for recent FreeBSD 3.0 distributions. A 3.0 test system was provided by David O'Brien . This was offered as a patch to 4.37. Updated the scripts/idrlogin.perl* files to look for sshd processes in addition to rlogind and telnetd ones. Added support for DU 5.0 Beta. Berkley Shands provided a test system. Added support for OpenBSD 2.4 with changes supplied by Kenneth Stailey . Changed the Solaris 2.7 tests and documentation to Solaris 7. Made some changes to the header files for NEXTSTEP 3.3 and added support for OPENSTEP 4.x with help from Michael A. Hovan III and Carl Lindberg . The combined dialect subdirectory is named n+os. One of Carl's changes propagates RC_CFLAGS to the library Makefile. Timothy J. Luoma helped test under NEXTSTEP 3.3 and OPENSTEP 4.2. Made UW 7.x version sensitive to the presence of ptf7038. Added peer PCB address to Unix domain socket Name column, even when a path name has been located. Information for these changes was supplied by Francis Le Bourse . Lee Penn provided a test system. Tested lsof under OSR 5.0.5 on a test system also provided by Lee Penn. Made path name argument processing more tolerant of errors per a suggestion from Julian Gordon . Acquired a new UnixWare 2.x test system, generously provided by Computer Classroom, Inc. -- Matthew Thurmaier , Ken Laing , and Andrew Merril . Updated Configure to accept a UnixWare version of 2.1.3. Updated kmem-based lsof for Linux 2.0.36. Updated NetBSD sources for a change in a UVM virtual mapping header file. Corrected a cache allocation bug in Sun format kernel name cache handling. The bug only shows up when the kernel name cache is inaccessible. 4.39 December 29, 1998 Corrected problems with large device number handling for 64 bit Solaris 7. The problems were reported by Steve Bellenot . Steve helped test the fixes. The fixes were offered as two patches to lsof 4.38. Improved FreeBSD Configure operations for header files that must be obtained from the kernel source tree, based on a suggestion from David O'Brien . For Bela Lubkin made optional with +f[cfn] the display of file structure address, shared use count, and node structure address. /proc-based Linux doesn't implement this feature, because it doesn't read kernel structures from kernel memory. Modified the PTX -X option to take advantage of the new file structure display option. Added shared.perl5 to the scripts/ subdirectory to provide an example of how +f[fn] might be used to track shared file descriptors and files. Added more /dev/kmem-based Linux glibc evasions, provided by Jeff Johnson and Maciej Lesniewski . Jeff helped test them on various Linux architectures. Tested on AIX 4.3.2; no changes were required. Doug Crabill provided a test system. Fixed -c option to detect missing command name when following option begins with `+'. 4.40 January 25, 1999 Added support for using the CDS compiler for Reliant Unix 5.44 and above. Made Reliant Unix MIPC support optional, dependent on the presence of . Based on a report from Michael Schmitz that /dev/kmem-based lsof misbehaves on a Linux 2.0.x m68k kernel without module support, made the absence of query_module() or get_kernel_syms() Linux kernel support a fatal error. Updated relevant sections of 00FAQ to reflect the change. Added the ability to force the Linux Configure stanza to use the /proc or /dev/kmem source base via a LINUX_BASE environment variable specification. This is a cross-configuration assist. Added "+D " and "+d " options for directory searching. +D searches the entire tree, starting at , including , its contents, and its subdirectory branches; +d searches only and its contents, but not its subdirectory branches. Improved lsof's searching of the specified name list to compensate for anticipated long lists from +d and +D. Made an egrep in the Solaris Configure stanza usable by the standard and XPG4 egrep's. Kenneth Stailey pointed out the improvement. Fixed bugs in /dev/kmem-based Linux and UnixWare Unix domain socket name searching. Changed a Linux Alpha #include to be conditional on the presence of its named header file, so that lsof will compile on Red Hat 5.1 and 5.2 (Linux kernel 2.0.35) where the header file is absent. The problem was reported by Alexandre Oliva . Fixed an AIX 4.3+ bug in procinfo struct space allocation, reported by Jeff Stewart . This was offered as a patch to 4.39. Added an lstatsafely() function to offer the same isolation for lstat() calls that statsafely() offers for stat() calls. This made DOSTAT_FUNCTION no longer necessary, so deleted it. With help from Laurent P. Montaron ported lsof to PTX 4.4.4. Laurent did a monumental job of identifying TCP/IP changes by their TCP version, rather than by their PTX (With mix 'n match PTX and TCP/IP versions, the PTX version often has no bearing on the TCP/IP version.), and changed the Configure script and pre-processor #if/#else/#endif blocks to match. He also updated Unix domain socket handling for PTX TCP/IP versions 4.5 and above. Updated CLIENT handle acquisition of fill_portmap() in print.c to use the more modern RPC function clnt_create() in place of clnttcp_create() where possible. PTX 4.4.4 requires clnt_create(). 4.41 February 27, 1999 Added FreeBSD 3.1 and and 4.0 support with help from Sheldon Hearn , David O'Brien , and John Polstra . Corrected bungled AIX 4.3+ patch that went into lsof 4.40. Reorganized the Configure script to improve Makefile construction. A specific impetus for this was to allow FreeBSD system-wide make flags to be propagated to the lsof Makefiles, but other goals were to make sure that the DEBUG= make entry can over-ride standard CFLAGS values, and to better manage the identification of compilers and their versions. Two compiler-related values may now be supplied in environment variables: 1) the compiler path in LSOF_CC; and 2) the compiler version in LSOF_CCV. 00XCONFIG documents them. Added support for Pyramid Reliant Unix bsdsfs, msockfs, and sockfs file systems. Added an optional LSOF_CINFO string to Configure, producing a CINFO string in selected Makefiles, producing a #define LSOF_CINFO in selected version.h header files. The purpose of this is to allow Configure the option to propagate information to the lsof -v output. It is now used for Linux to identify the code base, and for HP-UX 10.30 and 11.0 and Solaris 7 to identify the kernel bit size. Added system information to NEXTSTEP and OPENSTEP -v output, from the second line of hostinfo's output. Fixed a login name buffer overflow problem in the processing of -u option values. This was offered as a patch to 4.40. !!!THIS IS A SERIOUS STACK OVERFLOW BUG; A LINUX EXPLOIT EXISTS FOR IT THAT OPENS A BASH SHELL WITH LSOF'S AUTHORITY -- E.G, SETGID(KMEM) POWER!!! Improved the Solaris mount table filter so the volume manager's fake mount point, "/vol", is ignored and doesn't supplant "/" in NAME column path assemblies. Igor Schein reported this bug and provided important help in finding it. This was offered as a patch to 4.40. Changed the Linux /dev/kmem-based lock ownership test to answer a problem reported by Tom Christiansen . This was offered as a patch to 4.40. Installed an HP-UX 11 patch, suggested by Kevin Vajk , that adjusts a private lsof kernel header file, derived via Q4, to correspond to an HP-UX patch bundle. Made NetBSD 1.3I sockproto structure adjustment. 4.42 March 30, 1999 Fixed a typo in the HP-UX dfile.c that caused +fF and +fN output controls to swap effect. Enabled for OpenBSD 2.5 per notice from Kenneth Stailey Made more VM accommodations for FreeBSD 4.0. Improved file system search reporting to include path name components when they're available, instead of mindlessly reporting the file system name in the NAME column. Guy Dallaire brought the need for this change to my attention. Updated Solaris 2.6 VxFS for Veritas Oracle Database Edition 2.0, VxFS version 3.3, and VxVm version 2.5.4, based on a report from Chris Kordish . Chris kindly provided a test system. Improved HP-UX ipc_s patch detection in Configure, response in .../dialects/hpux/hpux11/ipc_s.h, and documentation in 00FAQ, Kevin Vajk helped test. Added to Customize the option to suppress HASKERNIDCK selection for specified dialects. Suppressed it for /proc-based Linux lsof, and removed its test and code from there. Tin Le alerted me to the need for this update. Ported to official Digital UNIX 5.0 release. Changed DU lsof to use the knlist(3) function when no kernel file has been specified with -k. This change was suggested by Erich Wimmer . Updated Configure for latest NetBSD (1.3I?) with UVM support the default. 4.43 May 11, 1999 Corrected a typo in the Solaris gcc discussion in 00FAQ. Made changes to the Solaris 2.5[.1] private tcp_s structure. Both changes were done in response to reports from Igor Schein , who tested the Solaris 2.5 change. Made more IPv6 adjustments to lsof for Tru64 UNIX (Digital UNIX) 5.0, based on information obtained from Compaq by Berkley Shands . Corrected HP-UX error message about HP-UX 11 q4 usage. Amir Katz reported the correction. Fixed a GlibC 2.1 conflict in /proc-based Linux lsof. Fixed a man page typo reported by Vlad Harchev . Changed some Solaris 2.7 references to Solaris 7 in Configure and 00XPORTING. Added a Solaris example to the echo statements that are the install rule in the SunOS/Solaris Makefile. Added a field to the file structure output -- FILE-FLAG (file structure open flags, f_flag[s], and process file flags, typically u_pofile)) -- enabled with +f[gG]. Its field output character is 'G'. Figured out another piece of the HP-UX 11 patched ipc_s structure puzzle with the help of Keith Kalet . Fixed a PTX real vnode to real inode interpretation bug. Added link count to lsof output. Eric Dumazet requested and helped test it. The new +L option enables and filters it. Its field output character is `k'. Updated Configure script to recognize NetBSD 1.4. Updated AFSConfig to handle default answers to questions. Incorporated patch from Jonathan Sergent that enables /proc-based Linux lsof to run on both 32 and 64 bit kernels. Updated Configure script with a patch from David O'Brien that recognizes FreeBSD 3.2. 4.44 June 24, 1999 Corrected use of nlink member of hsnode for SunOS 4.1.x High Sierra File System files. John Dzubera reported the problem and helped test the fix. Also fixed a SunOS segmentation fault bug. These fixes were offered as a patch to 4.43. Improved handling of /proc-based Linux UNIX PCB address. Fixed a NEXTSTEP and OPENSTEP bug that made repeat option (-r) processing malfunction. This fix was offered as a patch to 4.43. Fixed Configure so it doesn't use -O in the Cflags for the bundled HP-UX C compiler. Jim Ankenbrandt reported the problem. Corrected output ordering of parent PID and process group ID when both -R and -g are specified. Enhanced the pdev.c and pdvn.c library modules for wider use. These dialect versions use the new library modules: DEC OSF/1, Digital UNIX, and Tru64 UNIX; Pyramid DC/OSx and Reliant UNIX; SCO OSR and UnixWare; and Sequent PTX. Added basic clone device support to /dev/kmem-based HP-UX lsof for HP-UX 10.30 and higher. Added raw socket support to /proc-based Linux lsof. Changed NODE-ADDR column title to NODE-ID in anticipation of using more general identification information in the column. Ported to UnixWare 7.1, using a test system kindly provided by Matt Thurmaier and Don Draper . Updated for NetBSD 1.4C VM changes, and a new current and root working directory structure. Made minor adjustment for latest Tru64 UNIX 5.0 Beta release. 4.45 July 30, 1999 Fixed quoting problem in DEC OSF/1, Digital Unix, and Tru64 UNIX Makefile's install rule. The problem was reported by Berkley Shands . Fixed bug in Tru64 UNIX 4 lsof that caused FDs to be skipped. These fixes were offered in a patch to 4.44. Fixed a repeat-mode /proc-based Linux lsof bug, reported by Sami Farin . This was offered as a patch to 4.44. Picked lint, some reported by Sami Farin. Corrected a 00DCACHE documentation error in a sample shell script. The problem was reported by Chad R. Larson . Changed commented-out entries in machine.h files so they require more thought and work when the comments are removed, based on a remark by Chad. Compensated for the practice of Solaris 7 and above to record the dev= value in /etc/mnttab in 32 bit mode, even on 64 bit systems. This was offered as a patch to 4.44. Added a C library test for /proc-based Linux lsof, so that the #include files can be adjusted for a non-GlibC environment. The need for this was reported by Andrew Hill . This was offered as a patch to 4.44. Added support for Auspex LFS 1.8.1 and 1.9.2 to SunOS 4.1.4 lsof. The support was requested by Quentin Fennessy , who provided information and did testing. Enabled IPv6 support code for NetBSD and OpenBSD, conditional on Configure script tests. Wolfgang Rupprecht supplied the NetBSD code and tested it. The OpenBSD code I constructed has been compiled but not tested. Updated the identd Perl 5 script, based on a report from Wendy Lin that the space in its response line in front of the user name violates RFC 1413. Added IPv6 support to /proc-based Linux lsof. Jonathan Sergent and Andrew Thomas Sydelko kindly provided a test system. Updated man page description of AIX multiplexed files to indicate that they might be /dev/ptc or /dev/pts, depending on the AIX version. The correction was suggested by Onno van der Linden . Sylvain Robitaille reports lsof passes his Y2K tests. 4.46 October 23, 1999 Corrected /proc-based Linux lsof to detect that an IPv6 address is a mapped IPv4 address. The problem was reported and analyzed by Arkadiusz Miskiewicz , who also tested the fix. Added a libc5 library /dev/kmem-based Linux lsof circumvention, supplied by Jason Lingohr . Corrected a bug in -t (terse) AIX output, reported by Wendy Lin . I introduced the bug at revision 4.43 when adding FILE_FLAG reporting. This was offered as a patch to 4.45. Added a work-around for a problem in the OpenBSD 2.3 header file. Volker Borchert provided and tested it. Improved description of cross-building lsof for a 64 bit Solaris 7 system on a 32 bit system with suggestions from Phillip Edwards . Fixed a gawk POSIX-mode pattern error in the Linux /dev/kmem-based Mksrc script, based on a tip from Ambrose C. Li . Fixed a bug in the Tru64 UNIX IPv6 handling, courtesy of a report from Casper Dik . Enabled support for OpenBSD 2.6. Enabled support for BSDI BSD/OS 4.1, based on a report from Jeffrey C Honig that only a Configure script change is necessary. Enabled Configure script to use gcc for building lsof for a 64 bit Solaris 7 and 8 kernels, if the gcc version is 2.95 or above. Improved -i option handling for systems with IPv6 support so that it will search for a host name in both IPv4 and IPv6 families, when that is possible. As a companion modification, changed -V processing to report a single error when a multiple host name match is requested. Casper Dik helped test. Fixed a DEC OSF/1, Digital UNIX, Tru64 UNIX repeat mode bug, reported by Mayer Ilovitz . Mayer helped test the fix. The fix was offered as a patch to 4.45. Changed Solaris socket file recognition scheme, so it is (nearly) the same through Solaris 8, where the previous clone device scheme no longer works. With significant assistance from Casper Dik, added support for Solaris 8 Beta and Beta refresh. The IPv6 support in Solaris 8 is still in some flux, so there are temporary compensations for the differences between Beta IPv6 support and Beta refresh IPv6 support. Casper and I hope those differences disappear by FCS. Improved the delivery of information on Solaris 2.5.1, 2.6, 7, and 8 door files. Fixed a repeat mode bug that surfaces when /etc/passwd changes between cycles. The bug report and diagnostic help were supplied by Igor Schein . The fix was offered as a patch to 4.45. Added support for INRIA IPv6 to NetBSD. Jean-Luc Richier provided patches and a test system on which to verify them. Added support for AIX 4.3.3. Jeff W. Stewart provided a test system. Made adjustments for FreeBSD 4.0-current. Improved reporting of information for AIX sockets that lack protocol control blocks. 4.47 November 29, 1999 Based on a query from Jean-Pierre Radley , changed the lsof top-level Makefile to propagate CFGF to the library Makefile. (DEBUG was already being propagated.) Added osrgcc and scogcc Configure abbreviations (to use gcc) for Jean-Pierre. In response to a query from Igor Schein , improved the Configure script test for Solaris 7 and 8 that decides if the compiler can produce 64 bit executables. Made an ugly hack, based on making a private rnode structure definition from q4 output, to compensate for HP-UX 10.20 and lower recent NFS3 patches. HP didn't supply an updated with the patches. The problem was reported by Will Partain . Elias Halldor Agustsson helped identify the patches as PHNE_18173, PHNE_19426, PHNE_19937, and PHNE_20091, and provided a test system. Switched BSDI test system from 2.1 and 3.1 to 4.0.1, courtesy of Terry Kennedy . Added some more dev_t hacks for Alpha FreeBSD 4.0. Added support for IPv6 on BSD 4.x. The support hasn't yet been tested, just compiled. Added support for the mnt file system (mntfs or /etc/mnttab) on Solaris 8. Tested on Solaris 8 BETA-Refresh. Made selection of optional fields (e.g., PPID with -FR) in a field output specification select the optional field, too, so that the option selector for the field (e.g., -R) isn't also required. This change was made in response to an inquiry from John DuBois . This may require some revision to scripts that parse all field output; two scripts in the lsof distribution's scripts/ subdirectory had to be updated. Corrected handling of Linux IPv4 addresses mapped in IPv6 addresses. Tested under OpenBSD 2.6. 4.48 January 14, 2000 Modified -i argument processing of colon-separated IPv6 addresses to recognize an IPv4 address mapped in an IPv6 address and handle it as an IPv4 address. This was offered as a patch to 4.47. Added a defined symbol (NOWARNBLKDEV) to control (inhibit) the issuance of a warning when no block devices are found. This was done anticipating its need in FreeBSD 4.x, but that dialect version no longer has any block devices, so HASBLKDEV was disabled for it instead. NOWARNBLKDEV was left in place for possible use in the future. Enabled KAME IPv6 Configure support for FreeBSD when is found. Disabled use of gcc to compile lsof for 64 bit HP-UX 11. Updated Configure to recognized FreeBSD 3.4. Based on suggestions from Bernt Christandl improved AFS configuration for AIX and Solaris, and updated AIX AFS 3.5 support. Johannes Tax , Hung T. Pham , and Curt Freeland provided test systems. Updated lsof's private rnode definition for AIX 4.3.3, since IBM still doesn't ship the header file and the rnode structure definition in doesn't match what the kernel uses. This was offered as a patch to 4.47. Weakened the test in the Linux /proc-based lsof of the field count of data lines in /proc/net/{tcp,udp}. It appears that recent 2.3.x Linux kernels have added untitled fields to these files. The bug report came from Gabor Liptak . Adjusted for a FreeBSD 4.0 change in the definition of [_]KERNEL. David O'Brien reported the problem and provided a test system. Removed the HASPPID bracket from Fppid (the -R option state variable) so that the field select table will compile even when HASPPID is not defined. This problem was introduced at revision 4.47 with code that causes some field output characters to set option states. The problem was reported by David Bacon . 4.49 April 3, 2000 Made clearer in man page that "Lxx" FDs are AIX loader table references. Also updated the 00FAQ discussion of the Stale Segment ID bug to include AIX 4.3.x. Modified support for NetBSD 1.4Q to include the header file to cope with an MFS change. Added support for OpenBSD UVM virtual memory. Added support for AIX systems with > 2GB of memory. Chris Sylvain reported the problem and provided the solution. Chris also supplied some minor code cleanup. This was offered as a patch to 4.48. Based on new information from Igor Schein made additional compensation in Configure script for 64 bit Solaris 7 and 8 gcc. Added some 00FAQ info on the effect ordering of the +fg and -FG options has on output format. Improved NetBSD IPv6 configuration, based on a suggestion from Thomas Klausner . Added code to convert IPv4-mapped-in-IPv6 addresses to IPv4 addresses. Updated the information in 00FAQ and the HP-UX 11 binary directory README files on the HP-UX 11 ipis_s patch with new information supplied by Eric McWhorter . Added documentation on changes to HASFSTYPE and HASNCACHE, and the new HASPRIVPRIPP. Adjusted Configure for FreeBSD 5.0. Made additional, necessary changes to Configure and the BSDI sources to eliminate load errors. Added KAME IPv6 support to FreeBSD at the request of Ollivier Robert , who provided a test system. Corrected the script that generates the CHECKSUMS files for binaries to correctly name the detached PGP certificate. The documentation bug was reported by Michael Hennecke . 4.50 June 29, 2000 Added a NetBSD alpha test host, courtesy of Ray Phillips . An lsof 4.49 binary, built on Ray's 1.4.1 system was made available prior to the 3.50 release. Upgraded the system map file tests in /dev/kmem-based Linux lsof, making the use of DEBIAN_LINUX_LSOF unnecessary. Tested the changes on a system made available by Vincent Kujala and Jim Mintha . Forced AIX to use the large-file-enabled versions of lstat (lstat64) and stat (stat64) if contains stat64. This should allow lsof to stat() AIX files > 2GB even when the builder has not defined the "large file enabled programming environment." Configure tests and puts -DHASSTAT64 in the Makefile's CFLAGS to make this happen. Fernando A.B. Whitaker reported the problem. This was offered as a patch to 4.48. Enabled Configure script to handle OpenBSD 2.7. Angelos D. Keromytis reported the availability of OpenBSD 2.7 and supplied the Configure script patch. Improved handling of DOOR and fattach()'d files in Solaris. Changed message about missing kernel symbol file from "not yet determined" to "none found". Updated FreeBSD, NetBSD, NEXTSTEP, OpenBSD, and OPENSTEP support to report "no PCB" and the values of the SO_CANTSENDMORE and SO_CANTRCVMORE state flags when a socket structure has no inpcb pointer. This modification was made to AIX lsof at revision 4.46. Added an entry to 00FAQ about sockets that have no inpcb pointer. Upgraded support for FreeBSD 5.0-CURRENT. Ben Smithurst supplied patches and did testing. David O'Brien supplied a test system. The update included dropping the Fctty part of file descriptor file system support, conditional on a Configure script test. I propagated those changes to BSDI, NetBSD, and OpenBSD in anticipation of their having the modification in the future. David also arranged with Michael Haro for a FreeBSD 3.4 test system. In response to an lsof 3.72 bug report from Jim Mewes , added more kernel address filtering to the lsof function, kread(), that reads Solaris kernel data. In response to a report from Marc Duponcheel , added tests to the /proc-based Linux lsof to ignore file systems of types "autofs" and "pipfs". Based on a report and information supplied by Casper Dik , updated the ncache_load() function in lib/rnch.c with new code that deals with a post Solaris 8 change in kernel name cache (DNLC) handling. Casper tested the update, which should be invisible to Solaris versions without the new DNLC code. Added support for Solaris VxFS QIO files, based on a report from Kieran Broadfoot . Kieran help test the support. Added support for PTX 4.4.6 and 4.5[.1] with help from the usual cast of good people at Sequent. Added support for 64 bit file sizes and offsets on BSDI, FreeBSD, NetBSD, and OpenBSD, based on a report from Dan Nelson . Dan supplied a patch and did FreeBSD testing. Added Configure script recognition of NetBSD 1.5, based on a report from Andrew Brown . Thomas Klausner updated the NetBSD port package to use a pre-release of this addition. At the last minute saw a notice via deja.com's UseNet search service that FreeBSD 3.5 had been released and lsof didn't grok it. Added recognition of 3.5 to lsof's Configure script, but didn't have the opportunity to test lsof on 3.5. 4.51 August 21, 2000 Added Configure script support for the upcoming Solaris 9 release based on suggestions from Casper Dik . Changed sample Perl scripts to assume that /usr/local/bin/perl is Perl 5 and Perl 4 may be found in /usr/local/bin/perl4. Updated Configure to recognize FreeBSD 4.1 and made a FreeBSD pre-release distribution available. Bela Lubkin tested lsof on the upcoming SCO OSR 5.0.6 release and reports that lsof appears to work properly. Updated the AIX compiler test in Configure to recognize its version 5. Updated AIX 4.3.3 support with automatic recognition of the proper rnode structure, based on machine bit width. Also added code to detect when processing the -X option that lsof has been compiled with the "other" AIX 4.3.3 user structure and to apply compensations. When a compensation method works, it's applied during subsequent -X processing; when none works, further -X processing is disabled. Added Tru64 UNIX 5.1 support. Updated Tru64 UNIX library text file support to recognize new kernel support for AdvFS library files. Berkley Shands and Klaus Saggerer USG [saggerer@zk3.dec.com> helped put me in contact with Chang Song , the developer of 5.1's new kernel name cache and he helped me develop new code in lsof to access it. Corrected reporting of PTX fattach()'d address. Changed Configure and dlsof.h for NetBSD and OpenBSD to use /usr/include/uvm header files when available. Andrew Brown , Thomas Klausner , and Wolfgang Rupprecht pointed out the need to do this for NetBSD. Andrew provided access to a NetBSD 1.5 system for verifying the changes. Installed snprintf() support, including a private version in the lsof library for those UNIX dialects without the function. Changed all sources to use it instead of sprintf() and strcpy(). Fixed a memory leak in the readvfs() functions of BSDI, DEC/OSF1, Digital UNIX, FreeBSD, NetBSD, OpenBSD, and Tru64 UNIX. Tested on Linux 2.4. Modified the Pyramid MkKernOpts script to compensate for `uname -s` configuration alternatives. Robert Dahlem supplied the modification. Obtained access to an FCS Solaris 8 64 bit system and built lsof on it, using Sun Workshop C 5.0 and gcc 2.96 20000814 (experimental). Both compilers produce a working lsof. 4.52 November 8, 2000 Completed work on an HP-UX 11.11 port that uses a pstat(2) interface provided by HP. To distinguish it from its predecessors for HP-UX, this lsof version is called PSTAT-based and the predecessor versions are now called /dev/kmem-based. I am indebted to the far-sightedness and support of these good people at HP for making PSTAT-based lsof possible: Carl Davidson, Louis Huemiller, Rich Rauenzahn, and Sailu Yallapragada. The PSTAT-based sources are in lsof_4.52/dialects/hpux/pstat, the /dev/kmem-based ones in lsof_4.52/dialects/hpux/kmem. Ported to IBM Monterey for Merced|Itanium, aka AIX 5L. It configures via the Configure script's "aix" abbreviation and has been tested on AIX 5L Beta 3. Jay Beck, Steve Dibbell, Loc Le, Nasser Momtaheni, and Malcom Zung of IBM provided generous support. Since AIX 5L is still in Beta testing, this port can't be considered complete. Added Configure support for OpenBSD 2.8. David Mazieres provided a test system. Based on a report from Marc Christensen added sockfs to the mount scan exemption list for /proc-based Linux lsof. Added large file, CDFS, and DOSFS for UnixWare 7.x. Added UnixWare device memory mapping support. All UnixWare changes were supplied by Eric Dumazet Eric also supplied some miscellaneous bug fixes. Deferred name cache loading until printname() needs to use the name cache. Terminated Pyramid, SunOS 4.1.x, and Ultrix support, because test systems are no longer available. Final Pyramid and Ultrix source code distributions for lsof revision 4.51 may be found on lsof.itap.purdue.edu in pub/tools/unix/lsof/OLD/src. The no longer supported SunOS 4.1.x source code is still distributed with the Solaris source code. Added code to set Solaris node address to real vnode address, when applicable. John Speno provided information that enabled me to update the Tru64 AdvFS (MSFS) node definition for AdvFS version 5. Added Tru64 5.x CFS support with help from Kris Chandrasekhar , Diane Lebel , and John Speno. The support only provides information about cached file attributes. Installed a Configure patch for HP-UX 11 supplied by Kenneth Stailey that adds another command to q4 input. Tested on FreeBSD 4.2. Will Day and Frank Winkler graciously supplied Solaris 8 binaries. Added Solaris 9 text file support, supplied by Casper Dik . 4.53 December 6, 2000 Added the AIX 5L j2_lock.h to the distribution with a Configure script step to use it when it's missing from /usr/include/j2. Removed SunOS 4.1.x support. Removed Linux 2.0.x /dev/kmem support. Fixed VBLK and VCHR special device file reporting to handle /dev information more accurately. Added a Apple Darwin / Mac OS X 1.2 port, provided by Allan Nathanson . Allan also arranged for a test system so I can maintain this port. An additional test system was provided by Dale Talcott. Dropped claims of support for all UnixWare versions except 7.1.0, since that is the only version on which I can test lsof. Even though lsof 4.53 is deprecated for UnixWare 2.1.3, installed a patch for it with testing done by A. Channing Clark . Dropped claims of support for all SCO OpenServer versions except 5.0.5, since that is the only version on which I can test lsof. 4.54 January 19, 2001 Added compensation for a change that made the FreeBSD mount structure invisible. I can only test back to 3.2 and the compensation works there, so it's been #ifdef'd for 3.2 and above. David O'Brien provided the necessary clue. Based on a report from Valdis Kletnieks , changed all IPv6 support to report a TYPE of IPv6 for sockets with IPv4 addresses mapped in IPv6 addresses. The previous lsof behavior was to report their TYPE as IPv4. Restored the Linux GlibC test to Configure, removed at revision 4.53, based on a report from John Dzubera , that RedHat Linux 6.0 still needs the test. Made setting of link count for Solaris more selective. Limited Readlink() recursion to MAXSYMLINKS. The bug was reported by Jan Dvorak . Dropped the *claim* that lsof runs on Solaris 2.5.1. It may well do so, but I no longer have access to a test system. Fixed an #endif comment typo, reported by Igor Schein. Fixed a typo in a cast for a Tru64 UNIX 5.1 function and updated Configure for Tru64 UNIX 5.0 and 5.1 with information from Jesse Perry . Corrected non-fatal typos in the AdvFS support in dnode.c for Tru64 UNIX. Added msdos file system support for NetBSD and OpenBSD. Andrew Brown requested and helped test it. 4.55 February 15, 2001 Based on a report from Bernd Eckenfels added support in lsof for files in /proc//maps that have been deleted. Changed PGRP output title to PGID, conforming to the most common current abbreviation for Process Group ID (PGID). While some systems continue to use *pgrp for internal kernel variable names, most systems that support the display of PGID via ps(1) now title it PGID. The lsof -g and -Fg options operations are unchanged in function; only titles and descriptions have changed. Also changed internal variable names from *PGRP and *pgrp to *PGID and *pgid where possible. Dropped the *claim* that lsof runs on HP-UX 9.x. It may well do so, but I no longer have access to a test system. In response to a suggestion from Jeff Howie added support for command name selection by regular expression. A new form of the -c option value is use to identify and specify a regular expression. Restore the *claim* that lsof works on UnixWare 7.0, since I re-acquired a test system. 4.56 May 3, 2001 Corrected some problems Amir Katz found with Insure++, one in lib/dvch.c, the rest in Solaris sources. Amir's report also helped me find an error in an snpf() call that caused (the unsupported) Solaris 2.5.1 lsof to crash. Wally Winzer, Jr. helped test. Added support for UnixWare 7.1.1 and above in-kernel UNIX sockets. John Hughes kindly provided code and access to a test system. John also provided a test system and advice for adding UnixWare 7.1.1 NonStop Cluster and CFS support. More help with that effort came from Kurt Gollhardt (SCO), Barbara Howe (SCO), Bela Lubkin (SCO), and Dewan Rashid . Archived a set of compilation hints (patches) from Bill Melvin that make it possible to compile the old, unsupported lsof 3.08 sources on UnixWare 1.x without NFS or CDFS support. Installed support supplied by Allan Nathanson for the Darwin "Gold Master" release, Mac OS X 10.0 (aka Darwin 1.3 in its public source version). Added Allan's CVS repository suggestions to the script that gets additional header files from an open source repository. Tested an HP-UX 11.11 kernel patch from Sailu Yallapragada that enables reporting of TCP/IP information for telnetd processes that use the telnet multiplexor. I don't yet know the kernel patch ID. Made the Solaris inclusion of conditional on the Solaris version. (It's apparently not needed at 2.6 and above.) Bill Watson brought this to my attention. Added alternate Linux 2.4.x lock extent test, supplied by Jim Mintha . Rearranged the lines and pre-processor tests in regex.h, lib/regex.c, and lib/snpf.c so that unifdef can be used to eliminate copyright and GPL statements when the files aren't being used for a particular dialect. (USE_LIB_* definitions in a dialect's machine.h header file determine if one or more of those three files are to be used.) Added preliminary support for Solaris 8 with VxFS 3.4. This support will be refined as I get information from Veritas about how they will distribute the kernel header files lsof needs. Those header files were omitted from the standard VxFS 3.4 distribution. Technical assistance and testing were provided by Calle Dybedahl , Gary Millen , Rainer Orth , Peter C. Vernam , and Donna Yobs Tested on FreeBSD 4.3-STABLE. Dropped the *claim* that lsof works on UNIX dialects where I no longer have test systems: BSDI 2.1, 3.[01] and 4.0; DEC OSF/1, Digital UNIX and True 64 UNIX 2.0 and 3.2; FreeBSD 2.1.[67], 2.2[.x], 3.[012345] and 4.[01]; HP-UX 10.20; NetBSD 1.[234]; SCO OpenServer 5.0.5; and SCO UnixWare 7.0 Tested on Solaris 9 BETA, s81_36. 4.57 July 19, 2001 Help (-h) and version (-v) output now have URLs for the newly created and timeliest lsof FAQ (00FAQ in the lsof distribution) at: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/FAQ and the man page for the current lsof distribution at: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/lsof_man Based on a report from Steve Laubscher , modified dlsof.h for PTX 4.6[.1] to avoid a temporary dnlc_t definition needed at PTX 4.5.1. Corrected test for old Linux kernels in Configure. Henri Karrenbeld brought the error to my attention. Limited Linux claims to 2.1.72 and above in the documentation. Improved HP-UX 11 Configure stanza and stream socket handling. Constructed a work-around for the HP-UX 11 optional OnlineJFS package. The work-around sadly requires lsof to have a private version of the vx_inode structure, since the OnlineJFS package doesn't update . Troyan Krastev brought the bug to my attention and Michael Bracewell provided a test system where I developed the work-around. Added locale support to lsof's isprint() test, based on a suggestion from Dan Mercer . Lsof will use setlocale(), when that function and its supporting header file are available. Added OpenBSD 2.9 support. Based on a report from Aaron Rhodes and with testing help from Aaron, made the lsof 4.56 revision compile and work on OpenBSD 2.6. While that OpenBSD version is no longer supported, Aaron's report exposed a Configure script bug affecting OpenBSD versions lsof does support. Updated for FreeBSD 5.0-CURRENT. Szilveszter Adam help test. The lsof FreeBSD ports packager, David O'Brien , assisted. Tested on AIX 5.1. Loc Le and Nasser Momtaheni of IBM provided test systems. 4.58 September 13, 2001 Added options to safestrprt() and safestrprtn() to surround the string with '"' and to suppress the printing of an ending '\n'. Use of these functions in device cache file error message reporting answers a suggestion for better error reporting from John Jackson . Fixed a Solaris 2.6 and above problem related to searching for "large" (O_LARGEFILE) files by name; lsof was using the wrong version of [l]stat(2). The bug was reported by Daniel Trinkle . Added AIX 4.1.4 and above XTI socket support. Added OSR Xenix Shared Data and Semaphore file type support with modifications supplied by Bela Lubkin. Updated OPENSTEP support with modifications from Carl E. Lindberg . The changes enable the correct reporting of executable and library open files ("txt" type). Limited claims of OpenServer support to the versions where I currently test, 5.0.4 and 5.0.6. (Lsof probably works on 5.0.5.) Enabled processing of -C option for PSTAT-based HP-UX lsof. Enabled and tested on FreeBSD 4.4. Corrected a file system test example in 00QUICKSTART, based on a report from Jun Biao WANG . Made available for re-distribution a user-contributed port of lsof 4.51 to Reliant UNIX 5.45. Thomas Mauterer contributed the port. 4.59 October 20, 2001 With the closing of the Sequent Synergy Links Lab by IBM, terminated lsof support for PTX. The last tested PTX lsof revision, 4.58, is available on lsof.itap.purdue.edu in .../lsof/OLD/src. Adjusted for FreeBSD 5.0-CURRENT NFS header file changes, based on a report from Jos Backus . Corrected a bug in the way Linux lsof identifies the owner of a process. Lionel Cons reported the problem and tested the fix. Added code to avoid stat(2) calls on regular Linux files whenever possible. Lionel reported the need to do this (AFS files) and tested the new code. Added new output field for raw device number in hex. The field is identified with 'r'. This field is NOT selected when -F or -F0 is specified so that its appearance won't disturb existing scripts that process field output. Added support for OpenUNIX 8. A test system was provided by Larry Rosenman . Matthew Thurmaier and many people from Caldera provided technical assistance. Added an additional UVM test to the NetBSD Configure stanza. Andrew Brown supplied the test; it recognizes NetBSD 1.5Y UVM changes to the vnode structure recently committed by Chuck Silvers. Applied Configure and get-xnu-headers.sh script changes suppled by Allan Nathanson for Darwin 1.4. Added for Bela Lubkin OSR-specific environment variables to supply values to the Configure script. The variables are described in 00XCONFIG. Added an IP version selector to the -i option parameters. 4.60 November 9, 2001 Added special handling to and corrected bugs in the matching of IPv4 in IPv6 addresses to -i6:<...> selectors. Made 00FAQ corrections and updates, based on discussions with Igor Schein . Modified Configure script to detect a 64 bit capable gcc compiler and permit it to be used to build 64 bit (PA-RISC 2) lsof for HP-UX 11.00. Tested with HP's gcc package, which Rich Rauenzahn of HP kindly installed on a test system at HP. Stefan Marquardt helped test. Made lsof's method of killing its child process more robust, based on a suggestion from Bela Lubkin . Modified all dialect Makefile segments to accept select -v #define's from the environment -- a builder's comment, host, logname, system information and user name. This was done for Bela Lubkin, so he can "tune" the -v output when he packages lsof in the upcoming Caldera OSR 5.0.7 release. Changed Perl scripts in scripts/ to put the lsof path consistently in $LSOF. Also added a fix from Bela Lubkin to scripts/big_brother.perl5 that allows it to tolerate SCO OSR "ago" clauses in open UDP file information. Strengthened emphasis in scripts/00README that the scripts are examples that shouldn't be expected to run on all UNIX dialects without modification. At Bela Lubkin's suggestion changed the device cache file format examples in 00DCACHE and 00FAQ to avoid "%U%". That's an SCCS escape sequence. Added support for OpenBSD 3.0. Added +DAportable to CFLAGS for 32 bit HP-UX 11. Amir Katz suggested the addition. 4.61 January 22, 2002 Updated field output example Perl scripts in the scripts/ subdirectory to discover the lsof path, starting at .. and proceeding through the PATH environment variable's directories. Added minor OSR Configure script fixes, provided by Bela Lubkin . In response to a report from Joshua Wright modified NetBSD and OpenBSD Configure stanzas and sources so that lsof can be built when there is no system source tree (e.g., /usr/src/sys). In response to a report from Peter Valchev improved the UVM test in the OpenBSD Configure stanza. Updated Configure script to recognize FreeBSD 4.5. Updated for FreeBSD 5.0 procfs and pseudofs changes. Updated HP-UX stanza to see if the compiler named in the LSOF_CC environment variable is the bundled compiler. If it is, "-O" is omitted from the compiler flags. Updated Digital UNIX 4.x and Tru64 UNIX error message related to kernel name list failures. Added an FAQ section about how a kloadsrv daemon failure can cause knlist(3) to fail. The condition was reported by Douglas B. Jones Based on a report from Mark W. Eichin made Linux lsof capable of handling and reporting file sizes greater than 32 bits. Tested on Solaris 9 BETA-Refresh. Corrected a bug in the matching of IPv4 addresses, mapped in IPv6 addresses, to an IPv4 parameter to an -i option. Ported to 64 bit Power AIX 5.1 kernel with advice from David Clissold and Marc Stephenson , and on a test system provided by Loc Le . 4.62 March 7, 2002 Updated 00README to reflect the usefulness of gcc for building AIX lsof. Documented a report from Brian L. Gentry of success on AIX 4.3.3. I documented my success on 32 bit Power AIX 5.1 and my lack of success on ia64 AIX 5.1 and 64 bit Power AIX 5.1. Improved UnixWare >=7.1.1 reporting of UNIX socket NAME field information for NonStop Cluster systems with a patch provided by John Hughes . Offered John's improvement as a patch to lsof 4.61. Corrected bugs in handling of open files on block devices by OSR lsof. The bugs were reported by Bela Lubkin . Fixed bug in writing >32 bit device numbers for block devices to the device cache file. Added support for reporting block special nodes not in /dev (or /devices). That required "like device special" be changed to "like block special" and "like character special". (00FAQ was updated.) Based on a report from Peter Valchev improved the definition of the source for NetBSD and OpenBSD kernel symbols (the nlist() source file). NetBSD now defaults to getbootfile(3) if it is available, /netbsd otherwise. OpenBSD now defaults to /dev/ksyms if it is available, /bsd otherwise. Made possible compilation under BSD/OS (BSDI) 5.0 with changes to Configure, dialects/bsdi/dlsof, dialects/bsdi/dproc.c and lib/rnmh.c. The changes were suggested by Steven Hinkle . Note that these changes do not substantiate a claim that lsof works on BSDI 5.0, because I haven't tested it there. Updated OpenUNIX private , based on a report from Larry Rosenman that it had been updated by Caldera patch OU800PK3. Unfortunately the patch only corrects some of the problems with the header file, so it is still necessary to distribute a private patched version of it with the lsof sources. Applied a man page correction reported by Frederic Delanoy . Corrected cast bugs related to using the HP-UX bundled C compiler on HP-UX 11.11. 4.63 April 23, 2002 Added HPUX_BOOTFILE environment variable for use by the Configure script in determining HP-UX kernel configuration information -- e.g., the state of the ipis_s structure in the HP-UX 11 kernel. The change was suggested by Marc Bejarano . Marc also suggested some changes to the HP-UX section in 00FAQ that discusses Configure's use of q4 for HP-UX 11. Fixed a bug in the Solaris lsof file system matching code. It was not reporting that VCHR files in /devices were in / when /devices was in /, too. Corrected bugs in device number, file size, file offset, and raw device number field output generation. Added recognition of OpenBSD 3.1 to the Configure script with a suggestion from Peter Valchev . Note that this change does not constitute a claim that lsof works on OpenBSD 3.1, because I haven't tested it there. Built an automated test suite. (See 00TEST and the tests/ sub-directory of the lsof main directory). Bela Lubkin requested it. Dale Talcott, John Hughes, and Larry Rosenman helped me validate it on their systems. During the development of the test suite I discovered the following lsof bugs or missing features, and corrected or supplied them. * Corrected the reporting of locks for: o Digital UNIX 4.0d and Tru64 Unix 5.[01]; o HP-UX 10.30 and 11.00; o OpenUNIX 8; o UnixWare 7.1.1. * Enabled HP-UX 10.30 and 11.00 to report open NFS file link counts. * Corrected the reporting of UNIX domain socket names for Apple Darwin, FreeBSD 4.5 and above, NetBSD 1.4.1 and above, and for OpenBSD 3.0 and above. * Enabled HP-UX 11.11 to stat(2) large files. * Fixed handling of combination 32 and 64 bit device numbers in AIX 64 bit architectures. Updated the AIX 4.3.3 NFS rnode recognition code, first installed at revision 4.51. It looks like some IBM update has restored a single rnode structure independent of the machine bit width. Updated the NetBSD and OpenBSD sources so NetBSD can process DTYPE_PIPE files, as OpenBSD was already able to do. Updated Darwin get-xnu-headers.sh script to reflect information about a recent reorganization of the Darwin CVS hierarchy, supplied by Allan Nathanson . Added defense against the standard I/O descriptor attack. 4.64 June 26, 2002 Corrected some FreeBSD pre-processor directives. David O'Brien pointed them out. Updated lsof's main() function to: 1) close all open file descriptors above 2 before starting; and 2) to set a non-interfering umask. Moved GET_MAX_FD test from misc.c to proto.h, so that main() could use it. Added multiple-include protection to proto.h. Moved FAQ's test suite Q's & A's to a more appropriate section. Added a Q&A on HASSECURITY option and its affect on searching for open files. (That was already in the man page.) Updated hpux/kmem/dnode.c for HP-UX < 11 compilation with information from John Dzubera . While lsof doesn't support HP-UX < 11 any more, I try to avoid disabling it there when possible, and a locking fix for HP-UX >= 11 in lsof 4.63 inadvertently disabled compilation of lsof for HP-UX < 11. Fixed long-standing bug in HP-UX 10.20 lock reporting. Removed language from the test suite programs that requires an ANSI-C compiler. This allowed the test suite to be validated with cc and gcc on the un- supported HP-UX 10.20. At the suggestion of Manuel Bouyer switched NetBSD and OpenBSD lsof from using nlist() to using kvm_nlist(). Made the same change for BSDI, Darwin, and FreeBSD. Validated test suite on OPENSTEP 4.2. In response to a suggestion from Jeff Stoner enhanced support for the FD list of the -d option to allow it to be either an exclusion or inclusion list, using the '^' prefix to denote exclusions. Made adjustments for FreeBSD 4.6 and 5.0-CURRENT. Fixed a FreeBSD /etc/make.conf CFLAGS extraction bug, reported by Kris Kennaway , and new a bug in the fix, reported by Eric Cronin Added nullfs support for FreeBSD, NetBSD, and OpenBSD at the request of Andrew Brown . Modified all readmnt() functions to ignore mounted-on directory names that don't begin with '/'. Tested on NetBSD 1.6A and OpenBSD 3.1. Upgraded to Solaris 9 FCS with two changes to the BETA-Refresh support: 1) an adjustment to dnode.c for a change in the so_so (sonode) structure; and 2) addition of Solaris 9 FCS specific DNLC code. David Comay sent me the dnode.c change and Casper Dik helped with the new DNLC support code. Applied OpenUNIX changes that permit lsof to compile and run on the upcoming 8.0.1 release. The changes were supplied by Robert Lipe . Larry Rosenman provided a test system. Added Solaris fd file system support. 4.65 October 10, 2002 Adjusted for change in FreeBSD 5.0-CURRENT inode structure, reported by David O'Brien . Adjusted for changes in FreeBSD 5.0-CURRENT . One change was reported by Anders Nordby . Adjusted for FreeBSD 5.0-CURRENT on sparc64 architecture. Enhanced the error reporting of Solaris lsof when it detects a kvm_open() failure, and added a 00FAQ entry on the cause, based on a report from Peter J. Bertoncini . Enabled compiling of lsof for NetBSD 1.5 with the NULL file system, using a patch from Andrew Brown . Removed a hack in the LTbigf test program that was once needed when it was compiled on Solaris 9 BETA- Refresh with gcc. The hack isn't needed on Solaris 9 FCS. Janet Hempstead brought the need for this change to my attention. Applied a patch, supplied by Andrew Brown , that updates lsof for NetBSD version 1.6F. Corrected handling of the NetBSD nullfs. Updated to BSDI BSD/OS 4.3 on a test system kindly provided by Terry Kennedy . Updated to FreeBSD 4.7. Updated to Apple Darwin 1.5, 5.x and 6.x with patches supplied by Allan Nathanson . The patches include IPv6 support. Updated Configure to use the -bnolibpath loader option when building lsof on a PowerPC, running AIX 5 or greater. Valdis Kletnieks informed me this was needed. Lsof for AIX 5.x was initially developed on the IA64, where -bnolibpath can't be used and I didn't think to restore it to PowerPC loads when AIX 5.x became available for that architecture. Updated to UnixWare 7.1.3 on a test system provided by Larry Rosenman . Removed claims that lsof works on OpenUNIX 8.0.1, because UnixWare 7.1.3 is the release name of OpenUNIX 8.0.1. Based on a comment that his e-mail address was wrong in the lsof distribution from Kenneth Stailey , removed all e-mail addresses from lsof documentation files except this one, 00DIST. The addresses in 00DIST are used to send revision release notices to those who contributed to a revision, but the addresses in this file for previous revisions and in other documentation files sometimes grow stale and are never validated. 4.66 December 22, 2002 Acquired Solaris 7 and 8 test systems, courtesy of John Dzubera . Updated 00TEST and tests/TestDB accordingly. Clarified FreeBSD 5.0 architecture claims at the suggestion of David O'Brien . Also implemented David's suggestion to change Intel to x86. Installed changes to DNLC handling in OSR lsof in preparation for handling changes in the OSR 5.0.7 DNLC cache. Information about the changes and patches to handle them were supplied by Bela Lubkin . Upgraded True 64 UNIX support to the 5.1B release on a test system provided by Berkley Shands Had to used relaxed ANSI compilation because of an error in a system header file and other lsof source usages. Implemented the HASNOSOCKSECURITY compile-time option. When it and HASSECURITY are defined, lsof will be built to list only the user's open files, but will also list anyone else's open socket files, provided the "-i" option selects their listing. Updated the Customize script to ask about setting HASNOSOCKSECURITY. Left it undefined in all dialect machine.h header files. This change was requested by Kenneth Stailey for use with ntop. Added support for OpenBSD 3.2 and its kernel trace file. Improved lsof help (-h) and version (-v) information reporting. Fixed a FreeBSD 4.7 and above off-by-two UNIX domain socket path termination bug, reported by Ken Stailey 4.67 March 27, 2003 Began the transition of the lsof ftp server host name from vic.cc.purdue.edu to lsof.itap.purdue.edu. That reflects Purdue organizational changes. This first step makes the new name an alias to the old one. The old name, vic.cc.purdue.edu, will remain usable for an extended period. Corrected a revision number reference in section 17.17 of 00FAQ on the appearance of Solaris negative DNLC caching handing. Updated 00FAQ discussion of compilers for 64 bit Solaris. Validated test suite for 64 bit Solaris 8 and gcc. At the request of Alek O. Komarnitsky added the "+c " option to enable optional changing of the COMMAND column output maximum width from the default to . The default maximum width remains CMDL, as defined in lsof.h. Fixed three AIX kernel bit size detection bugs, one in the AIX Configure script stanza, the second and third in the AIX dproc.c get_kernel_access() function. The bugs were reported by Pierre-Yves Fontaniere , who tested the fixes. Added kernel event queue file support for FreeBSD, NetBSD and OpenBSD. Andrew Brown supplied the code. Updated to AIX 5.2 on a test system provided by Dale Talcott . Had to build work-arounds for two missing AIX 5.2 header files, and . Corrected an off-by-one UNIX socket addressing bug. Taught AIX lsof to handle both jfs and jfs2 files at the same time. Adjusted for an IBM mistake in the sizing of the fdsinfo structure in Toshiya Nakamura helped test, Updated to FreeBSD 4.8. Corrected another bug in FreeBSD UNIX domain socket name handling. Corrected gcc build problems on HP-UX 11i, reported by Yuliy Minchev . Updated BSDI BSD/OS support to 4.3.1. Augmented a lock ID test on NetBSD to check if the ID is an LWP pointer. 4.68 June 18, 2003 Enhanced Configure script's cleanup operations. Added support for OpenBSD 3.3, based on a report from Peter Valchev . Improved the description of the detached PGP signature certificate file in the main lsof README file, based on a suggestion from Diana Stockdale . Installed a work-around for FreeBSD 5.0-CURRENT on Alpha to avoid a compiler register use complaint. Corrected a 'c' option error message. Gnele reported the problem. Upgraded EXT2FS and UFS support for NetBSD and OpenBSD to handle new inode information, and the fast UFS1 and UFS2 file systems. With the help of Andrew Brown determined the NetBSD snapshot (1.6F) at which could be included under _KERNEL, thus eliminating the lsof netexport.h hack. The same change applies to OpenBSD versions 3.3 and above. Applied a patch from Armin Gruner that corrects the use of the HASPROCFS definition in the FreeBSD dialect sources. Corrected spelling errors in 00FAQ and in the generated 00.README.FIRST_ file of the distribution archive. John Jackson and Ray Phillips spotted and reported the errors. Corrected a spelling error in a comment and incorrect use of an alarm function in the LTsock test program. At the suggestion of Stuart Anderson added preliminary (and incomplete) SAM-FS file system support to Solaris lsof. Completion awaits availability of SAM-FS internals. Fixed a Solaris device name printing bug, reported by Ric Anderson , only visible when HASDCACHE is not defined. Ric helped test the fix. Fixed an AIX kernel bit size handling bug related to the NFS node (rnode) structure. Corrected a print_kptr() function call error in the AIX AFS code, reported by David Steiner . Upon further reflection and because I no longer have appropriate AIX AFS test systems, disabled AIX AFS support in the Configure script for AIX versions above 4.3.3.0 or AIX AFS versions above 3.5. Added support for FreeBSD 5.1. With advice from Allan Nathanson adjusted the Darwin get-xnu-headers.sh script to access the kernel header files needed by lsof from a new form of the Apple open source repository. Installed Linux and lsof library bug fixes and improvements, supplied by Marian Jancar . One Linux improvement handles mount strings that have octal escapes in them, eg., \040 for embedded blanks. Marian tested the changes. 4.69 October 16, 2003 Received and applied an OpenBSD patch from Peter Valchev that replaces a ctob() call with a sysconf() call. Peter claims sysconf() is needed for OpenBSD on SPARC. (It is not needed for NetBSD on SPARC.) With the upgrade of my only Solaris 7 test system to, Solaris 8, dropped the *claim* that lsof works on Solaris 7. That doesn't mean it won't work there, so those who want lsof for Solaris 7 probably should be able to build it there and it probably will work there. Revised lsof's DNLC handling for BSD derivatives, including: BSDI; Darwin, DEC OSF/1, Digital UNIX and Tru64 UNIX; FreeBSD; NetBSD; and OpenBSD. The latest NetBSD distribution's dropping of the vnode capability ID (v_id) required the revision. Adjusted to the latest FreeBSD 5.1-CURRENT. Added NetBSD support for using kvm_getproc2(). Added a patch from Andrew Brown to handle NetBSD enum conflicts and changes in the and header files. Added a "#define _KERNEL" to the AIX dnode2.c source file for compatibility with a new AIX 5.2 header file version. The addition was supplied by Dick Dunbar and was offered as a patch to lsof 4.68/ Added support for a second type of Solaris SAMFS. Stuart Anderson provided the support. SAMFS support in lsof SOLARIS remains scanty, because Sun won't release any details on its kernel structures. Dropped the *claim* that lsof works on AIX 4.3.3, because I was unable to test it there. That doesn't mean it won't work there, so those who want lsof for AIX 4.3.3 probably should be able to build it there and it probably will work there. Updated for Solaris 10 on test systems provided by Mike Miscevic . Casper Dik provided significant help. During the Solaris 10 port found and fixed an lofs handling bug that prevented reporting of open lofs file lock status. Updated the DNLC test, LTdnlc, to provide a possible explanation about file systems on which the test might fail. Modified the procedure for obtaining missing Darwin XNU kernel header files. The new one requires more manual intervention, but is the best that can be done with the way Apple open sources are now organized. 00FAQ explains the new procedures for those not used to downloading Apple open source files. Added support for Apple Darwin 7.0 (Mac OS X 10.3) with patches supplied by Allan Nathanson . Dropped the *claim* that lsof builds and works on Apple Darwin below 6.0. Validated lsof on FreeBSD 4.9, using a test system provided by Ben Lewis . Validated lsof on FreeBSD 5.1-CURRENT for Amd64. David O'Brien provided a test system. Changed the NetBSD Configure stanza to do header file searches in /usr/include by default. The LSOF_INCLUDE and NETBSD_SYS environment variables may still be used to specify other search paths. Discussions with Andrew Brown and Wolfgang S. Rupprecht led to the change. 4.70 January 16, 2004 Improved shell-portability of the linux stanza of the Configure script with a patch from Paul Jarc . Added a "silent" rule to tests/Makefile for Paul. Updated, extended and clarified the test suite documentation in 00FAQ and 00TEST. Fixed Solaris 10 dlsof.h typo, reported by Mike Miscevic . The typo prevents lsof from loading cleanly in Solaris 10 builds past 40. Fixed a Solaris HSFS node number reporting bug and added a structure definition work-around for Solaris 10. Converted PGP signing to GPG. My previous PGP key can be used, but the gpg "--allow-non-selfsigned-uid" option may have to be used when it is imported into a GPG key ring. Added bz2 compression. Updated for OpenBSD 3.4. Added a work-around for a missing header file in the s10_44 Solaris 10 build. Added support for FreeBSD 5.2-BETA and 5.2-CURRENT. Updated Linux AX25 support with modifications supplied by Lutz Poetschulat . Added raw IPv6 support to Linux lsof. Improved handling of parameters after "-i@". Improved file name test in LTdnlc.c. Added loop count controls to the reading of Solaris lock chains. The change was implemented as a result of a report from Steve Gonczi . Based on a report from John Jackson , enabled a Solaris 10 work-around for Solaris 9, too. (Patch 112233 installs an lgrp.h on Solaris 9 that needs the work-around.) With help from Andrew Brown and John Heasley added log-structured file system (LFS) support for NetBSD and OpenBSD. Added AMD64 to the list of FreeBSD 5.x-CURRENT supported architectures. FreeBSD.org provides a test system, courtesy of (I believe) David O'Brien . Added a cast to lseek() in the HP-UX /dev/kmem-based kread() function to make it work properly with the bundled HP C compiler. 4.71 March 11, 2004 Added text file support to Apple Darwin lsof and enabled the lsof executable portion of the LTbasic test. Added support for Darwin kernel queue, POSIX semaphore and POSIX shared memory files. Tested on Darwin 7.2 (aka Mac OS 10.3.2). Added process_kqueue() function prototypes for FreeBSD, NetBSD and OpenBSD. Picked some lint in AIX sources, lib/rnmh.c and tests/LTsock.c. Added "-x [fl]" cross-over option, which enables +d and +D processing to cross over symbolic links and|or file system mount points. Discussion with Johan Lindquist and Eric Williams (aka The Ghost In The Machine) on Linux news groups revealed the need for the option. Updated support for UnixWare 7.1.4. Added support for the optional reporting of socket options, socket states and TCP flags for most currently supported dialects. John Smith and Tristan Nefzger requested the information. The dialects and their versions for which this feature has become available include: AIX 4.3.2 and 5.[12] Apple Darwin 7.2 BSDI BSD/OS 4.3.1 Digital UNIX and Tru64 UNIX 4.0 FreeBSD 4.9 and 5.2 HP-UX 11 and 11.11 (aka 11i) NetBSD 1.6ZH OpenBSD 3.4 OPENSTEP 4.2 OpenUNIX 8 SCO OpenServer Release 5.0.6 Solaris 2.6, 8, 9 and 10 UnixWare 7.1.[134] Modified the Configure stanza for HP-UX 11 with better q4 detection. Steve Bonds <3vhmxxm02@sneakemail.com> supplied the modification. Applied a patch from Mike Miscevic to enable lsof to compile with the zone support in the Solaris 10 s10_b51 release. Added information on lsof zone behavior to 00FAQ. Added a "-z [z]" option to Solaris 10 lsof. It enables the listing of zone name and can also be used to select the listing of processes and their files from specified zones. 4.72 July 13, 2004 Corrected Solaris 10 ZONE column title display bug with a patch from Joep Vesseur . Joep's fix was offered as a patch to 4.71. Based on a report from Jean-Pierre Radley about an unexpected GNU uname Configure interaction on OSR, and working from information received from Bela Lubkin, changed the OSR Configure stanza to use /bin/uname instead of uname. Added an FAQ entry about Configure version detection problems. Added the +m and "+m m" options in response to a dialog with Robert T. Brown . The options allow the creation of a mount table supplement file which can be used on selected dialects to get device numbers when stat(2) and lstat(2) can't deliver them. (That's generally the result of an inaccessible NFS server.) Currently the new options are supported only on Linux. Made cpumask_t typedef _KERNEL compensation for FreeBSD 5.2-CURRENT. Refined it for 5.2.1-RELEASE with testing help from Scott Ellentuch . Added support for FreeBSD 4.10. Larry Rosenmann kindly provided a test system. Added support for NetBSD 2.0 with patches supplied by Andrew Brown . Andrew also provided two test systems. Made handling of Linux maps file more robust, based on a report from Jan Blunck . As a side benefit, made handling of generated stat(2) information more flexible. As a result of a discussion with Jason Fortezzo , adjusted lsof for Solaris to obtain the maximum user name length from ut_name of the utmpx structure, if exists. Tested under OpenBSD 3.5. Updated 00README information about using gcc (via the Configure aixgcc abbrevisiation) to compile lsof on AIX. Ann Janssen made me aware the information was out of date. Added an AIX SIGDANGER handler and some 00FAQ sections on lsof memory usage after a discussion with Tom Qin about lsof memory usage. Added scripts/sort_res.perl5, contributed by Fabian Frederick . The script displays lsof output sorted by size and path name. Improved handling of files on Linux NFS mount points that use the root_squash option, based on discussions with Paul Szabo . Updated FreeBSD 5.2-CURRENT support, based on a problem report from Filippo Natali . Corrected improper FreeeBSD 5.x-CURRENT #if condition, reported by Kim Culhan . Added a Configure script work-around for AIX 5.2 lsof with JFS2, compiled by gcc >= 3.3. The work-around was supplied by Florian M. Weps . 4.73 October 21, 2004 Added an __XPG4_CHAR_CLASS__ #define before #include'ing on Solaris to restore lsof's ability to display special characters such as acute-e. Added wide-character (e.g., UTF-8) support where possible, prompted by a request from Kyungjoon Lee . Some older dialects -- e.g., NetBSD 1.4.1 -- don't support wide characters, so the wide character support is enabled by definitions in each dialect's machine.h. Dialects with wide- character support are listed in 00FAQ. Make a FreeBSD 5.2-CURRENT adjustment for , supplied by Sergey A. Osokin . Implemented a Linux feature request made by Jakub Jelinek that enhances lsof's ability to locate UNIX domain sockets whose paths are named as arguments. Jakub supplied suggested code. Dropped *claims* that lsof works on AIX below 5.1, SCO Dropped *claims* that lsof works on AIX below 5.1, SCO Openserver 5.0.4, Tru64 UNIX 5.0, and UnixWare below 7.1.4. Lsof will probably build and work on those UNIX dialect versions, but I no longer have any way to test lsof on them. Added support for FreeBSD 5.3 and 6.0. The FreeBSD 5.3 support hasn't been tested. Added FD test code that will allow dialect versions to test FD option selections. Used the new code in the PSTAT-based HP-UX lsof to enable it to avoid scanning the mount table when its information is not needed. The addition was made in response to a query from Harvey Garner about lsof performance in a busy NFS environment. Upgraded lsof's AIX support level to AIX 5.3, based on a report from Dick Dunbar . (I have not tested lsof under AIX 5.3.) Based on Dick's recommendation and local testing changed the C for AIX version 6 and higher -qmaxmem option value to -1. Made LSOF_AR environment variable more useful and documented it in 00XCONFIG. Corrected the use of sum(1) to generate signatures for the lsof distribution and binaries to match the documentation that claims it is sum -r output. Jin Guojun noticed and reported the problem. Tested under OpenBSD 3.6. Added checksum and GPG certificate files for the bz2, gz and Z lsof distribution archives. The new files reside with the distribution archives and supplement the signature information already inside the archives. Validated on Solaris 10, i8xpc, build s10_63. 4.74 January 17, 2005 Fixed a Solaris segment fault bug on systems that lack a /dev/allkmem device. Offered the fix as a patch to lsof 4.73. The bug was reported by Donald Zoch . Updated lsof for FreeBSD 6.0 and higher for a change in , based on a report from Sergey A. Osokin . Made the update available in a 4.74 'A' edition pre-release. Filed an HP bug report about missing pstat(2) CWD info for LOFS on HP-UX 11.11 and higher. The missing CWD info was noticed by Ermin Borovac . Added info to 00FAQ about the problem, which can cause the lsof test suite's LTbasic test to fail. Updated the q4-generated tcp_s.h in the lsof distribution and added socket option support for HP-UX 11.00. Erwin Reyns helped test. Updated for Solaris 10, build s10_69, with a patch supplied by Mike Miscevic . Added v_path support to Solaris 10 lsof. That relieves it of having to read and decode the kernel DNLC, and delivers full paths more reliably. Added specialized NFS4 support to Solaris 10 lsof. Applied Solaris 10 patches to lsof supplied by Casper Dik . Updated lsof for NetBSD 2.99.10 and tested it on a system provided by Andrew Brown . Added support for the FreeBSD 6.0-CURRENT f_vnode pointer in the file structure. Added BSDI, FreeBSD, NetBSD and OpenBSD support for the *effnlink member of the inode structure. This makes the lsof LTnlink test run faster on all modified dialects and correctly on OpenBSD. Added ptyfs support for NetBSD, using modifications provided by Andrew Brown. Changed the netbsd Configure stanza to look by default for system header files in both /usr/include and /usr/src. (The NETBSD_SYS environment variable can still be used to select an alternate for /usr/src.) Corrects two FreeBSD 4.10 RPC/XDR type definitions. Added an FAQ Q&A about setuid and setgid restrictions in HP-UX 11.11. The information in the answer was supplied by Frank Sanders . Added abbreviations for AXI FCIO and FSNAPSHOT file flags. Holger VanKoll reported the missing FCIO. Adjusted lsof's private AIX 64 bit rnode structure for 64 bit AIX 5.2 systems. (IBM doesn't distribute a correct for it.) Corrected a Linux socket inode printing bug reported by Igor Schein . Updated for FreeBSD 4.11. The support compiles but hasn't been tested. Back-ported a FreeBSD 6.0-CURRENT fix to FreeBSD 5.3-RELEASE-p1. That was done to solve a compilation problem reported by Radko Keves . 4.75 May 16, 2005 Dropped the *claim* that lsof works on DEC OSF/1 and Digital UNIX, since my last 4.0 test system has been removed. The last tested distribution of lsof on DEC OSF/1 and Digital UNIX was revision 4.74. It has been archived on lsof.itap.purdue.edu in pub/tools/unix/lsof/OLD/src. Added negation forms to the values in the -g (PGID) and -p (PID) lists. Negated PGID and PID values, like negated UID or login name values, are applied without ORing or ANDing and take effect before any other selection criteria are applied. At the request of Marcin Gozdalik added a -X option for Linux. The option inhibits the reading of the /proc/net/tcp* and /proc/net/udp* files. Based on a report from David Gutierrez changed DEC OSF/1 process table allocation to request memory in smaller increments. Based on a report from jayjwa updated the Customize script to use "tail -n 1" where possible. Enabled support for FreeBSD 5.4. Improved the BSDI, FreeBSD, NetBSD, OpenBSD and Solaris kvm_open() and kvm_openfiles() error messages. Enabled support for NetBSD 2.99.12. Improved HP-UX Configure stanza with help from Piet Starreveld . Picked some lint Piet found. Enabled IPv6 support for HP-UX > 11. Piet Starreveld helped test it on 11.23, among others. Updated for HP-UX 11.23 on the ia64 architecture. Updated to latest FreeBSD 6.0-CURRENT, using a test system provided by Andrzej Tobola . Added support for SCO OSR 6.0.0 and UnixWare 7.1.4 with help from Richard at SCO. Corrected a Linux bug in NFS handling, reported by Karel Zak . Karel supplied a patch. Improved the code for accessing an AIX 3.2 and higher sockaddr_un structure, thus eliminating a segmentation fault possibility. Updated for AIX 5.3. Added preliminary (DEBUG) support for the AIX SANFS file system. Fixed a bug in the Solaris 10 processing of the vnode's v_path pointer with code supplied by Edward Jajko . The fix was offered as a patch to 4.74. Dropped support for OpenUNIX 8, since a test system is no longer available. Archived an OpenUNIX-only distribution of the last revision (4.74) tested on OpenUNIX in pub/tools/unix/lsof/OLD/src. Tested under Openbsd 3.7. Tested under Darwin 7.7.0. Enabled building on amd64 Solaris 10 with hints from Marc Aurele La France . Marc provided a test system. Supplied a missing quote in the FreeBSD Configure stanza. Carl Cook reported the problem. Removed "-O" option from tests/Makefile so that the HP-UX bundled compiler won't complain. 4.76 August 30, 2005 Corrected an example and spelling errors in man page. Updated for Apple Darwin 8.x with changes supplied by Allan Nathanson . Allan also provided a test system. Completed documentation of CLRLFILEADD in all machine.h files. At the request of Chris Markle added partial listen queue length to socket options displayed when -Tf is specified. Partial queue length is not reported for all dialects. (00FAQ lists the ones where it is reported.) Updated for FreeBSD 7.0 with information supplied by Andrzej Tobola . Updated Solaris VxFS support for VxFS versions 4 and above with technical advice from Craig Harmer , Gary Millen and Chuck Silvers . Testing help was provided by Michael Antlitz , Steve Ginsberg and Kenneth Stailey . Fixed a Solaris address space map processing bug. Janardhan Molumuri reported the bug and help me identify it. Made the fix available as 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 to get inode number, size and link count. (There's a new 00FAQ entry about that.) Investigated a report from Christopher J Warweg that the CHECKSUMS for the lsof 4.75 binary for 64 bit Solaris 8 was incorrect. It was my packaging error. I rebuilt and repackaged the binary. Enabled support for Linux map file names with embedded spaces. 4.77 April 10, 2006 Added -X option support for Solaris 10 and above. When -X is specified lsof will report cached v_node path names for unlinked files, followed by "(deleted)". Improved cached vnode path name handling by adding "(?)" to the end of path names of questionable accuracy. Updated 00FAQ to reflect these changes. Updated for FreeBSD 7.0-CURRENT. Fixed name addition spacing bug, reported by Stuart Anderson . Also updated Solaris 10 SAMFS support at Stuart's request. Added missing "break;" and another HASSTATVFS test to the NetBSD and OpenBSD dnode.c. Bill Behr reported those needs. Fixed an HP-UX 11 file descriptor "chunk" size problem, reported by Per Allansson . Per helped devise the fix and tested it. This fix was offered as a patch to lsof 4.76. Updated for FreeBSD 6.0-STABLE and FreeBSD 6.1-PRERELEASE. Updated scripts/sort_res.perl5 with changes supplied by Frederick Fabian , the author of the script. Corrected +|-M man page documentation error, reported by Roger Cornelius . Improved FreeBSD user device random seed generation in response to a problem report from Danny Braniss . Eliminated three syntax error bugs and other compiler complaints from the PSTAT-based lsof. H. Merijn Brand reported the problems and tested the fixes. Eliminated compiler complaints in the test suite. Investigated problems with the building of lsof on PA-RISC HP-UX 11.23, based on a report from John Orndorff . Found that neither the HP bundled C compiler nor gcc would build lsof, but the the HP unbundled ANSI C compiler would. Concluded that HP bundled C compiler can't handle . Devised a work-around to gcc's omission of the rpcent structure definition of that allows it to compile lsof's print.c, but the resulting binary doesn't run reliably. Documented the situation in 00FAQ. Changed reporting of unknown file types. The number of an unknown type is now reported as four octets. The change was made in response to a Linux lsof bug report from Karel Zak . Dropped the *claim* that lsof works on BSDI BSD/OS since my last test system has been removed. The last tested distribution of lsof for BSDI BSD/OS was revision 4.76. It has been archived on lsof.itap.purdue.edu in pub/tools/unix/lsof/OLD/src. As a result of discussing the lsof source tar's MD5 checksum with Andrew Bell , changed the description of a suitable MD5 tool in the lsof distribution's documentation to name the openssl "dgst" command. Enabled compilation on Solaris 10 1/06 with a fix sent by Jason Fortezzo . Made the fix available as a patch to 4.76. Adjusted to FreeBSD 5.5-PRERELEASE. Corrected a bug in the lsof library's process_file() function to enable the locating of AIX XTI sockets by their TCP/IP address values. The bug was reported by Michel Dubois . Based on a bug report from Karel Zak added command name length checking to as many dialects as possible (Linux for Karel) for the "-c c" option. Updated for OpenBSD 3.[89]. Tested the 3.9 update on a system provided by David Mazieres. I have not tested on OpenBSD 3.8, but David reports lsof 4.76 worked there. Ended regression testing of lsof on 32 bit Solaris 8 with the ending of access to a test system. Lsof continues to be tested on 64 bit Solaris 8. 4.78 April 24, 2007 Added more information to the lsof FAQ about missing link counts and sizes on Linux files. Simplified Linux stat() and lstat() usage. Relocated #define's that prevent OpenBSD compilation on systems without a /proc file system. Pieter Bowman reported the problem. Added code to avoid processing Linux /proc//maps file entries with zero device and node numbers. Some such entries now have names associated with them that are not path names -- e.g., "[heap]", "[stack]" or "[vdso]". Scott Worley reported lsof's mishandling of such entries. Added SELinux security context support, provided by James Antill . I have not tested this, but James and Karel Zak have. Added the #include of to Solaris lsof to enabled compilation on Solaris 10 6/06. Peter Harvey Peter.Harvey@Sun.COM diagnosed the problem and supplied a patch. Added better support for JFS2 on AIX 5.2 and 5.3, based on bug reports and help from Thomas Braunbeck and Tom Whitty . Documented that lsof supports AIX 5.3 only up through maintenance level 1 (ML1). Enabled Solaris lsof to locate the AFS vnode operation address for OpenAFS 1.4.1. The fix was supplied by Robert Jelinek . Enabled support for Solaris 10 ZFS. If the necessary ZFS header files aren't found, lsof offers the option to drop ZFS support, to use internal, possibly inaccurate structure definitions, or to supply a path to the missing header files. Horst Scheuermann provided a development system and helped test the support. Corrected a typo in the man page, reported by Eric S. Raymond . Changed the spelling of macroes to macros in lsof source and documentations files, based on a suggestion from Josh Soref and verification with the OED. The following dialects are no longer supported: 32 bit AIX 5.2, HP-UX 11, OpenStep 4.2, Solaris 2.6, Solaris 8, True Unix 64 and UnixWare 7.1.4. Lsof may work on them, but I no longer have test systems for them. Support for OpenBSD ends at its version 3.9 for lack of interest in the port. 4.79 April 15, 2008 **************** IMPORTANT NOTE ****************** * * * Lsof support has been reduced to the following * * dialects: AIX, FreeBSD, Linux and Solaris, and * * only in selected versions of those dialects. * * The selected versions are listed in this file * * and in other lsof documentation. * * * * I have made this move because of retirement * * and because I no longer have many test systems * * available to me. * * * * Vic Abell * * * ************************************************** Fixed a Solaris VXFS permission problem when accessing the VXFS inode offsets. The bug was reported by Gregory A. Ivanov . Gregory tested the fix. Moved an #include later in FreeBSD dlsof.h to enable compilation on recent FreeBSD releases. The change was supplied by Roy Marples . Improved Linux /proc file stream reading speed by applying an expanded version of a patch from Eric Dumazet that allocates a page size buffer to each stream. Improved TCP, TCP6, UDP and UDP6 hashing by determining the hash bucket count from the /proc/net sockstat and sockstat6 files. The improvement was suggested by Eric and he provided sample code. Eric also tested both improvements. Modified Configure script to build lsof on FreeBSD 6.2. Tested it on a system provided by Larry Rosenman . Fixed a Linux maps file processing bug that prevented path names from having an embedded colon. James Lingard reported the bug and helped with its fix. Based on reports from Eric Dumazet and Samuel Thibault added support for the Linux 2.6.22 kernel's /proc//fdinfo files -- i.e., file offset and flags. Samuel Thibault provided a test system. Fixed a Linux UNIX socket memory leak, reported by Philip Shin . Phillip supplied the fix. With generous assistance from HP added support for an HP-UX 11.23 patch that makes TLI/XTI socket address information available. Fixed a header file problem for FreeBSD 6.2 on the Alpha architecture. The problem was reported by Pekka Honkanen . Pekka tested the fix. Based on a report and using suggested fixes from Karel Zak , made these changes to Linux lsof: corrected a getpidcon() error message; insured that inode numbers are handled correctly for their unsigned long long type; and improved SELinux handling. At the request of Alon Bar-Lev added the LINUX_HASSELINUX environment variable to enable or inhibit SElinux support unconditionally. Updated Configure for FreeBSD 8.0-CURRENT and tested lsof on AMD64 there. Added a patch provided by Oles Hnatkevych for FreeBSD systems where the root file system is on a CD9660 device. Added compensation for the disappearance of FMARK and FDEFER from the FreeBSD 8.0-CURRENT . Updated FreeBSD lsof with ZFS support. Larry Rosenman , Erwin Lansing , Wesley Shields and Dmitry Morozovsky provided test systems. Fixed a socket file identification problem reported by Pavol Rusnak . Pavol also reported the cause of the problem. Added the ability to format the repeat mode marker line with strftime(3), where the dialect supports the localtime(3) and strftime(3) C library functions. The addition was suggested by Mike Depot , who also tested it. The addition required creating a new main lsof source module, util.c, that contains functions whose compilation conflicts with the general header file tree defined by lsof.h and dlsof.h. Based on reports from Andrei V. Lavreniyuk and Pav Lucistnik updated the FreeBSD 7.0 and above file lock handling to use new locking structures. The update requires a terrible hack to get a definition for the lock owner structure from a kernel source module into a local lsof header file. 4.80 May 12, 2008 Updated for a FreeBSD 7.0 and above byte level locking change. The problem was reported by Conrad J. Sabatier , who helped test the update. Wesley Shields provided an 8.0-CURRENT test system. Propagated the FreeBSD 7.0 and above locking changes to FreeBSD 6.x, based on a report from Edwin Groothuis . Added warnings for unsupported dialects or versions. Added Linux support for the UDPLITE protocol. Eric Dumazet supplied a patch. Added a missing quote to the Configure script's FreeBSD stanza. Added a usage.o rule to the HP-UX PSTAT-based Makefile. I mistakenly deleted the rule at revision 4.79. The missing rule was reported by Kawaljeet Kaur who tested the corrected Makefile. 4.81 October 21, 2008 Updated the Darwin libproc sources with changes from Allan Nathanson . Tested them on a iMac mini, provided by Apple Inc. Changed dummy declarations in library source files to eliminate complaints about unused variables and empty object files. This change may not work on dialects I can no longer test; it has been tested on some versions of AIX, Darwin, FreeBSD, Linux and Solaris. At the request of Hal Brooks added support for Linux /proc/net/packet files. Hal tested it. Added socket file only performance enhancements to Linux and PSTAT-based HPUX lsof. Added htonl call around improper usage of INADDR_LOOPBACK; report from an Apple engineer forwarded by Allan Nathanson . Adjusted for FreeBSD-8.0 change in device number handling. The adjustment should work for FreeBSD 5 and above, should the 8.0 change be propagated downward. The problem was reported by Pav Lucistnik . An updated test system was provided by Erwin Lansing . Reduced AIX support to version 5.3, since test systems with older versions are no longer available to me. At the request of Marjo F. Mercado and Phil Shin applied some speed improvements to lsof, particularly when the files of interest are /Internet files -- i.e., selected with lsof's -i" option. Added a two new options to assist the improvements: 1) "-c^" to tell lsof to exclude the named command(s); and 2) "-stcp|ud>:[^]state' to tell lsof to include in its reporting or exclude ('^') from its reporting Internet files in the named states (e.g., LISTEN, ^CLOSE_WAIT, IDLE, etc.) For the most part these changes apply only to AIX, Darwin, FreeBSD, PSTAT-based HP-UX, Linux and Solaris, since those are the only places I could test them. They are controlled by the HASTCPUDPSTATE definition in each dialect's machine.h header file. Marjo and Phil provided HP-UX 11.23 and 11.31 test systems. Fixed a stat(2) problem on HP-UX 11.31 while testing the speed improvements. Adjusted for kernel header file changes in FreeBSD 8.0-CURRENT. Larry Rosenman provided a test system. Added a warning for Solaris systems where VxFS node info can't be obtained from the VxFS utility library. The warning was requested by Tom Matthews . Corrected mishandling of file system path name arguments that have trailing slashes, except, of course, the root file system, "/". Allan Nathanson reported the bug. 4.82 March 25, 2009 Corrected an over-zealous exclusion test that caused lsof to report nothing when it was given no arguments and built with HASSECURITY and HASNOSOCKSECURITY enabled. Joshua Kinard reported the bug and supplied information for reproducing it. Based on a report from Dan Trinkle corrected use of for 32 bit Solaris 10 and above compilations. Simultaneously eliminated a casting complaint in arg.c and updated Configure to use the appropriate 64 bit compilation option (-xarch=v9 or -m64) with the Solaris Sun C compiler. Updated for FreeBSD 7.1-PRERELEASE with information supplied by Larry Rosenman . Updated the Darwin libproc sources with changes from Allan Nathanson . Tested them on a iMac mini, provided by Apple Inc. Allan also provided man page corrections. Updated the FreeBSD Makefile to use the ${MAKE} variable for ZFS dnode2.c module compilation, based on a suggestion from Alexis Ballier . Improved the Solaris VxFS library location test, based on a suggestion from Jason Fortezzo . Jason tested the change. Updated Solaris 10 ZFS support for ZFS version 4 and ZFS pool version 10, using a test system kindly provided by Vladislav Nespor . Renata Maria Dart tested on ZFS version 4, verifying that the update works there, too. (ZFS pool version 10 is apparently the ZFS version shipped with the 10/08 update to Solaris. The original ZFS support targeted ZFS version 3.) I still consider ZFS support in Solaris lsof a hack, because it depends on a znode structure definition that I developed using dbx. Sun is remiss in not distributing the ZFS header files used to build the distributed kernel. Because of the znode structure definition hack, I can't guarantee that lsof ZFS support will work for any other versions of ZFS. Solaris 10: adjusted to a change in the way devices are stored in the kernel; fixed a problem in zone handling; and added rudimentary sharedfs support. Carson Gaspar reported the device number problem, provided a test system, and tested the changes. Peter Vines reported the zone handling problem and tested the fix. Adapted to FreeBSD 8.0-CURRENT changes in device number computation. Problem was reported by Erwin Lansing . Larry Rosenman provided a test system. Corrected Solaris Configure test for appropriate VxFS library when using gcc to compile lsof. Updated for loss of KAME IPv6 FreeBSD accommodations. Adapted to FreeBSD 7.2. Made Configure script recognized FreeBSD 6.3. 4.83 January 18, 2010 Converted Solaris 10 and above ZFS support to use the CTF debugger library, libctf. Code was supplied by Robert Byrnes . Corrected a typo in the testing of the LINUX_HASSELINUX environment variable in the Configure script. The error was reported by Mike Frysinger . At Mike's request made Configure script accept LSOF_RANLIB (ranlib command), LSOF_CFGF (additional configuration flags) and LSOF_CFGL (additional library specifications) from the environment. Enabled complilation of Solaris 10 lsof after a recent Sun patch which changed the PC file system's structure. Peter Vernam reported the problem and helped with the fix. Made the sort of configuration CFLAGS in the CkTestDB script impervious to locale settings. Ported to Solaris 11, using a test system kindly provided by David Day . Adjusted to the disappearance of in FreeBSD 8.0-BETA1. Changed Solaris node type lookup to a hashed method and added some ability for it to handle duplicate vnodeop names in /dev/ksyms. Updated for FreeBSD 9.0-CURRENT. Andrzej Tobola provided a test system. Extends the fix to FreeBSD 6.0 and above via a Configure test and a compile-time definition. The need for the extension was reported by Erik Trulsson > Made corrections to FAQ typographical errors, suggested by Josh Soref . Added __UCLIBC__ test to Linux dlsof.h so lsof would compile on an Intel ARM XScale processor. The addition was provided by Doug Kehn . Added test for to FreeBSD configuration. Improved its use in lsof.h. The changes were supplied by Martin Wilke . 4.84 July 29, 2010 Fixed a man page nroff command error with a correction supplied by Josh Soref . Made Configure script recognize FreeBSD 7.3. Larry Rosenman provided a test system. Improved task support, initially for Linux only, with help provided by Jerome Marchand and Miklos Szeredi . The support includes a new compile-time definition, HASTASKS, and a new run time option, "-K" to select task reporting. While adding help output support for "-K", reorganized the printing of help columns to make it much easier to add a new option description. Updated the Solaris PC file system structure patch in revision 4.83 so it will compile with gcc. Disabled the Solaris lgrp_root work-around in the Solaris machine.h so it won't cause compilation problems on Solaris 11. It no longer causes compilation problems on my Solaris 9 and 10 test systems, but some older Solaris 9 and 10 versions may still need it, so the work-around was left in the Sun machine.h and a FAQ entry was created about it. Updated for Solaris 11 b134, using a test system kindly provided by Carson Gaspar . Made provisions for the next ZFS version. Added info about the failure of the LTnlink test on ZFS file systems. Corrected typo in Configure script, reported by Dmitry Berezin . 4.85 September 27, 2011 John Dzubera kindly provided a patched Solaris 9 test system with the lgrp_root conflict and I was able to devise an automatic work-around for the conflict. The special note in .../dialects/sun/machine.h was removed and the 17.28.1 FAQ entry was modified to reflect the update. Added a Solaris 11 work-around for a typedef problem with . Carson Gaspar reported the problem and supplied the work-around. Added support for FreeBSD 7.4 and 8.2; tested on systems provided by Larry Rosenman . Added support for 32 bit Solaris 11 lsof with mods supplied by Jan Wortelboer . Added Solaris 11 support for using an alternate genunix location. Bill Goodridge reported the alternate location. Added further Linux cross configuration support to lsof's Configure script. The additional support was supplied by Grant Erickson . See the descriptions of the LINUX_* environmen variables in 00XCONFIG for more information. Tested lsof on Linux kernel 2.6.32 and picked some lint that surfaced during the test. Added fixes and changes for Apple Mac OS X 10.6, provided by Allan Nathanson . Allan also provided a test system. Tested on FreeBSD 6.4 i386, using a test system provided by Terry Kennedy . Updated for recent FreeBSD ZFS changes on an 8.2 amd64 test system also provided by Terry. Changed documentation to indicate FreeBSD 7.x is no longer supported, since I no longer have a test system. Made some changes to the lsof man page, suggested by Navid . Added compensation for Solaris 10 systems that have patch 144488-10. The patch requires that the new header file be included while _KERNEL is defined. Brett Bartick reported the problem first, followed by Stuart Anderson . Michael Hocke suggested a work-around which I refined to limit it to the specific Solaris 10 instance and then tested on a system provided by Charles Stephens Added the +|-e option for Linux. It exempts file systems named by path from function calls that might block in the kernel -- i.e., stat(2) and lstat(2), and when the +e form is used, readlink (2). The new packager of lsof for the Linux Fedora and RHEL distributions, Peter Schiffer , asked for the feature so it could be used with Clearcase file systems, whose implementation can block stat(2) calls. I consider this feature very risky and easy to misuse -- e.g., specifying the file system as '/' would exempt all file systems. I don't intend to propagate this option to any other UNIX dialect that lsof currently supports. Made FreeBSD 9 adjustment. Fixed a Linux bug that prevented the display of paths for abstact UNIX sockets. Masatake Yamato reported the bug and supplied a patch. Added compensation for the removal of RPC header files from GlibC 2.14 for Linux. Marek Behun reported the problem and supplied a patch. Added support for Linux Netlink protocol. Masatake Yamato requested the support and supplied a patch. Peter Schiffer provided a test system. Corrected Linux UDP6-lite path. The error was reported by Masatake Yamato and he also supplied a patch. 4.86 April 10, 2012 Lsof for AIX is no longer supported on any versions of that operating system. Added information about the clang compiler for FreeBSD to the FAQ. Corrected an arg.c bug in the accumulation of +|-e option values, reported by Peter Schiffer . This correction was supplied as a patch to revision 4.85. Enabled FreeBSD 10 support and tested it there on a system provided by Larry Rosenman . Updated for latest Solaris 11 with patches supplied by Carson Gaspar . Carson supplied a test system. Adjusted Linux file system search method to compensate for NFS mounts that have duplicate device numbers. The problem was reported by Peter Schiffer , who provided a test system. At the request of Peter Schiffer , added support for Linux SCTP socket files. Peter provided a test system. Applied a warning patch supplied by Peter. Added support for Mac OS X 10.7 (Lion), provided by Allan Nathanson . Allan also supplied a test system. Enabled FreeBSD 8.3 support and tested it there on a system provided by Larry Rosenman . Corrected the FAQ information on ZFS with Solaris 10 after Steven Blackmon and Prasad Jampala pointed out that it was incorrect -- i.e., outdated by the libctf changes at revision 4.83. Added code to handle a Linux NFS-mounted root. Jia He reported the need for this. Vic Abell April 10, 2012 lsof-4.86+dfsg.orig/arg.c0000444000175000017500000015342111741060036015375 0ustar nicholasnicholas/* * 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"; static char *rcsid = "$Id: arg.c,v 1.51 2012/04/10 16:30:06 abe Exp $"; #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) 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 */ { 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); Exit(1); } (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); Exit(1); } } mmp[nm++] = mp; } if (fv == 2 && nm == 0) { (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); Exit(1); } 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; (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); Exit(1); } #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); Exit(1); } #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); Exit(1); } #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); Exit(1); } 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 (!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); Exit(1); } } 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); Exit(1); } (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); Exit(1); } } 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); Exit(1); } 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)) 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); Exit(1); } 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); Exit(1); } /* * 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); Exit(1); } 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); Exit(1); } 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; 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)) { 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); Exit(1); } } (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); Exit(1); } } (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)) { 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); Exit(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++; /* * 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" : ""); Exit(1); } } 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); Exit(1); } } 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); Exit(1); } } 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); Exit(1); } 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); Exit(1); } } if (nn) { if (!(lp = mkstrcpy(lnm, (MALLOC_S *)NULL))) { (void) fprintf(stderr, "%s: no space for login: ", Pn); safestrprt(lnm, stderr, 1); Exit(1); } 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); } lsof-4.86+dfsg.orig/scripts/0000755000175000017500000000000011741064217016150 5ustar nicholasnicholaslsof-4.86+dfsg.orig/scripts/big_brother.perl50000555000175000017500000001244207374004635021420 0ustar nicholasnicholas#!/usr/local/bin/perl -w #+############################################################################## # # # File: big_brother.perl # # # # Description: check the network sockets with lsof to detect new connections # # # # Contributed by Lionel Cons # # # #-############################################################################## # @(#)big_brother 1.12 08/14/96 Written by Lionel.Cons@cern.ch # no waranty! use this at your own risks! # # init & setup # $verbose = 1; $lsof_opt = "-itcp -iudp -Di -FcLPn -r 5"; $SIG{'HUP'} = \&hangup; chop($hostname = `/bin/hostname`); $fq_hostname = (gethostbyname($hostname))[0]; # Set path to lsof. if (($LSOF = &isexec("../lsof")) eq "") { # Try .. first if (($LSOF = &isexec("lsof")) eq "") { # Then try . and $PATH print "can't execute $LSOF\n"; exit 1 } } # # spy forever... # $| = 1; die "$LSOF is not executable\n" unless -x $LSOF; while (1) { $lsof_pid = open(PIPE, "$LSOF $lsof_opt 2>&1 |") || die "can't start $LSOF: $!\n"; print "# ", ×tamp, " $LSOF $lsof_opt, pid=$lsof_pid\n" if $verbose; print "#COMMAND PID USER P NAME\n"; $printed = $hanguped = $pid = $proto = 0; while () { if (/^lsof: PID \d+, /) { # fatal error message? print "*** $_"; last; } elsif (/^lsof: /) { # warning warn "* $_"; } elsif (/^p(\d+)$/) { &flush; $pid = $1; $proto = 0; } elsif (/^c(.*)$/) { $command = $1; } elsif (/^L(.*)$/) { $user = $1; } elsif (/^P(.*)$/) { &flush; $proto = $1; } elsif (/^n(.*)$/) { $name = $1; # replace local hostname by 'localhost' $name =~ s/\Q$fq_hostname\E/localhost/g; $name =~ s/[0-9hms]+ ago//g; } elsif (/^m$/) { &flush; &clean; } else { warn "* bad output ignored: $_"; } } kill('INT', $lsof_pid); kill('KILL', $lsof_pid); close(PIPE); } sub hangup { $hanguped = 1; $SIG{'HUP'} = \&hangup; } sub flush { return unless $pid && $proto; return if &skip; $tag = sprintf("%-9s %5d %8s %1s %s", $command, $pid, $user, substr($proto, 0, 1), $name); unless (defined($seen{$tag})) { print "+$tag\n"; $printed++; } $seen{$tag} = 1; } sub clean { my(@to_delete, $tag); if ($hanguped) { $hanguped = 0; @to_delete = keys(%seen); print "# ", ×tamp, " hangup received, rescanning all connections\n" if $verbose; } else { @to_delete = (); foreach $tag (keys(%seen)) { if ($seen{$tag} == 0) { # not seen this time: delete it push(@to_delete, $tag); print "-$tag\n"; $printed++; } else { # seen this time: reset the flag $seen{$tag} = 0; } } } grep(delete($seen{$_}), @to_delete); if ($printed > 10) { print "# ", ×tamp, "\n" if $verbose; $printed = 0; } } sub skip { # # put stuff here to ignore some connections, for instance: # # what we get when the socket gets created... return(1) if $name eq '*:0'; return(1) if $name =~ /^localhost:(\d+)$/ && $1 > 1000; # # UDP & TCP stuff # # # ignore common daemons # if ($name =~ /^\*:/ && $user eq 'root' && $pid < 300) { return(1) if $command =~ /^inetd(\.afs)?$/; return(1) if $command =~ /^rpc\.(stat|lock)d$/; return(1) if $command eq 'syslogd' && $name eq '*:syslog'; } # # forking beasts: portmap, ypbind, inetd # if ($command eq 'portmap' && $user eq 'daemon') { return(1) if $name =~ /^\*:/; } elsif ($command eq 'ypbind') { return(1) if $name =~ /^\*:\d+$/; } # # TCP-only stuff # return(0) unless $proto eq 'TCP'; # # outgoing commands: ftp, telnet, r* # if ($command eq 'ftp') { return(1) if $name =~ /:ftp(-data)?$/; } elsif ($command eq 'telnet') { return(1) if $name =~ /:telnet$/; } elsif ($command eq 'remsh') { if ($name =~ /:(\d?\d\d\d)->.+:(\d?\d\d\d)$/) { return(1) if $1 < 1024 && $1 > 990 && $2 < 1024 && $2 > 990; } elsif ($name =~ /:(\d?\d\d\d)->.+:(shell|ta-rauth)$/) { return(1) if $1 < 1024 && $1 > 990; } elsif ($name =~ /^\*:(\d?\d\d\d)$/) { return(1) if $1 < 1024 && $1 > 990; } } return(0); } sub timestamp { my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst); ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); sprintf("%d/%02d/%02d-%02d:%02d:%02d", $year + 1900, $mon+1, $mday, $hour, $min, $sec); } ## isexec($path) -- is $path executable # # $path = absolute or relative path to file to test for executabiity. # Paths that begin with neither '/' nor '.' that arent't found as # simple references are also tested with the path prefixes of the # PATH environment variable. sub isexec { my ($path) = @_; my ($i, @P, $PATH); $path =~ s/^\s+|\s+$//g; if ($path eq "") { return(""); } if (($path =~ m#^[\/\.]#)) { if (-x $path) { return($path); } return(""); } $PATH = $ENV{PATH}; @P = split(":", $PATH); for ($i = 0; $i <= $#P; $i++) { if (-x "$P[$i]/$path") { return("$P[$i]/$path"); } } return(""); } lsof-4.86+dfsg.orig/scripts/idrlogin.perl50000555000175000017500000001220207375723655020746 0ustar nicholasnicholas#!/usr/local/bin/perl # # $Id: idrlogin.perl5,v 1.5 2001/11/18 12:20:46 abe Exp $ # # idrlogin.perl5 -- sample Perl 5 script to identify the network source of a # network (remote) login via rlogind, sshd, or telnetd # IMPORTANT DEFINITIONS # ===================== # # 1. Set the interpreter line of this script to the local path of the # Perl 5 executable. # 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. # Initialize variables. $dev = $faddr = $tty = ""; # fd variables $pidst = 0; # process state $cmd = $login = $pgrp = $pid = $ppid = ""; # process var. # Set path to lsof. if (($LSOF = &isexec("../lsof")) eq "") { # Try .. first if (($LSOF = &isexec("lsof")) eq "") { # Then try . and $PATH print "can't execute $LSOF\n"; exit 1 } } # Open a pipe from lsof if (! -x "$LSOF") { die "Can't execute $LSOF\n"; } open (P, "$LSOF -R -FcDfLpPRn0|") || die "Can't pipe from $LSOF\n"; # Process the lsof output a line at a time while (

) { chop; @F = split('\0', $_, 999); if ($F[0] =~ /^p/) { # A process set begins with a PID field whose ID character is `p'. if ($pidst) { &save_proc } foreach $i (0 .. ($#F - 1)) { PROC: { if ($F[$i] =~ /^c(.*)/) { $cmd = $1; last PROC } if ($F[$i] =~ /^p(.*)/) { $pid = $1; last PROC } if ($F[$i] =~ /^R(.*)/) { $ppid = $1; last PROC } if ($F[$i] =~ /^L(.*)/) { $login = $1; last PROC } } } $pidst = 1; next; } # A file descriptor set begins with a file descriptor field whose ID # character is `f'. if ($F[0] =~ /^f/) { if ($faddr ne "") { next; } $proto = $name = ""; foreach $i (0 .. ($#F - 1)) { FD: { if ($F[$i] =~ /^P(.*)/) { $proto = $1; last FD; } if ($F[$i] =~ /^n(.*)/) { $name = $1; last FD; } if ($F[$i] =~ /^D(.*)/) { $dev = $1; last FD; } } } if ($proto eq "TCP" && $faddr eq "" && (($cmd =~ /rlogind/) || ($cmd =~ /sshd/) || ($cmd =~ /telnetd/))) { if (($name =~ /[^:]*:[^-]*->([^:]*):.*/)) { $faddr = $1; } } elsif ($tty eq "" && ($cmd =~ /.*sh$/)) { if (($name =~ m#/dev.*ty.*#)) { ($tty) = ($name =~ m#/dev.*/(.*)#); } elsif (($name =~ m#/dev/(pts/\d+)#)) { $tty = $1; } elsif (($name =~ m#/dev.*pts.*#)) { $d = oct($dev); $tty = sprintf("pts/%d", $d & 0xffff); } } next; } } # Flush any stored file or process output. if ($pidst) { &save_proc } # List the shell processes that have rlogind/sshd/telnetd parents. $hdr = 0; foreach $pid (sort keys(%shcmd)) { $p = $pid; if (!defined($raddr{$pid})) { for ($ff = 0; !$ff && defined($Ppid{$p}); ) { $p = $Ppid{$p}; if ($p < 2 || defined($raddr{$p})) { $ff = 1; } } } else { $ff = 2; } if ($ff && defined($raddr{$p})) { if (!$hdr) { printf "%-8.8s %-8.8s %6s %-10.10s %6s %-10.10s %s\n", "Login", "Shell", "PID", "Via", "PID", "TTY", "From"; $hdr = 1; } printf "%-8.8s %-8.8s %6d %-10.10s %6s %-10.10s %s\n", $shlogin{$pid}, $shcmd{$pid}, $pid, ($ff == 2) ? "(direct)" : $rcmd{$p}, ($ff == 2) ? "" : $p, ($shtty{$pid} eq "") ? "(unknown)" : $shtty{$pid}, $raddr{$p}; } } exit(0); # save_proc -- save process information # Values are stored inelegantly in global variables. sub save_proc { if (!defined($Ppid{$pid})) { $Ppid{$pid} = $ppid; } if ($faddr ne "") { $raddr{$pid} = $faddr; if (($cmd =~ /.*sh$/)) { $shcmd{$pid} = $cmd; $shlogin{$pid} = $login; } else { $rcmd{$pid} = $cmd; } } if ($tty ne "") { $shcmd{$pid} = $cmd; $shtty{$pid} = $tty; $shlogin{$pid} = $login; } # Clear variables. $cmd = $dev = $faddr = $pgrp = $pid = $ppid = $tty = ""; $pidst = 0; } ## isexec($path) -- is $path executable # # $path = absolute or relative path to file to test for executabiity. # Paths that begin with neither '/' nor '.' that arent't found as # simple references are also tested with the path prefixes of the # PATH environment variable. sub isexec { my ($path) = @_; my ($i, @P, $PATH); $path =~ s/^\s+|\s+$//g; if ($path eq "") { return(""); } if (($path =~ m#^[\/\.]#)) { if (-x $path) { return($path); } return(""); } $PATH = $ENV{PATH}; @P = split(":", $PATH); for ($i = 0; $i <= $#P; $i++) { if (-x "$P[$i]/$path") { return("$P[$i]/$path"); } } return(""); } lsof-4.86+dfsg.orig/scripts/list_NULf.perl50000555000175000017500000001176007133644003020763 0ustar nicholasnicholas#!/usr/local/bin/perl # # $Id: list_NULf.perl5,v 1.5 2000/07/14 17:03:37 abe Exp $ # # list_NULf.perl5 -- sample Perl 5 script to list lsof NUL-terminated # full field output (i.e., -F0 output) # # This script has been tested under perl version 5.001e. # # 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. # Initialize variables. $fhdr = 0; # fd hdr. flag $fdst = 0; # fd state $access = $devch = $devn = $fd = $inode = $lock = $name = ""; # | file descr. $offset = $proto = $size = $state = $stream = $type = ""; # | variables $pidst = 0; # process state $cmd = $login = $pgrp = $pid = $ppid = $uid = ""; # process var. # Process the ``lsof -F'' output a line at a time, gathering # the variables for a process together before printing them; # then gathering the variables for each file descriptor # together before printing them. while (<>) { chop; @F = split('\0', $_, 999); if ($F[0] =~ /^p/) { # A process set begins with a PID field whose ID character is `p'. if ($pidst) { &list_proc } if ($fdst) { &list_fd; $fdst = 0; } foreach $i (0 .. ($#F - 1)) { PROC: { if ($F[$i] =~ /^c(.*)/) { $cmd = $1; last PROC } if ($F[$i] =~ /^g(.*)/) { $pgrp = $1; last PROC } if ($F[$i] =~ /^p(.*)/) { $pid = $1; last PROC } if ($F[$i] =~ /^u(.*)/) { $uid = $1; last PROC } if ($F[$i] =~ /^L(.*)/) { $login = $1; last PROC } if ($F[$i] =~ /^R(.*)/) { $ppid = $1; last PROC } print "ERROR: unrecognized process field: \"$F[$i]\"\n"; } } $pidst = 1; next; } # A file descriptor set begins with a file descriptor field whose ID # character is `f'. if ($F[0] =~ /^f/) { if ($pidst) { &list_proc } if ($fdst) { &list_fd } foreach $i (0 .. ($#F - 1)) { FD: { if ($F[$i] =~ /^a(.*)/) { $access = $1; last FD; } if ($F[$i] =~ /^C(.*)/) { last FD; } if ($F[$i] =~ /^f(.*)/) { $fd = $1; last FD; } if ($F[$i] =~ /^F(.*)/) { last FD; } if ($F[$i] =~ /^d(.*)/) { $devch = $1; last FD; } if ($F[$i] =~ /^D(.*)/) { $devn = $1; last FD; } if ($F[$i] =~ /^G(.*)/) { last FD; } if ($F[$i] =~ /^i(.*)/) { $inode = $1; last FD; } if ($F[$i] =~ /^k(.*)/) { last FD; } if ($F[$i] =~ /^l(.*)/) { $lock = $1; last FD; } if ($F[$i] =~ /^N(.*)/) { last FD; } if ($F[$i] =~ /^o(.*)/) { $offset = $1; last FD; } if ($F[$i] =~ /^P(.*)/) { $proto = $1; last FD; } if ($F[$i] =~ /^s(.*)/) { $size = $1; last FD; } if ($F[$i] =~ /^S(.*)/) { $stream = $1; last FD; } if ($F[$i] =~ /^t(.*)/) { $type = $1; last FD; } if ($F[$i] =~ /^T(.*)/) { if ($state eq "") { $state = "(" . $1; } else { $state = $state . " " . $1; } last FD; } if ($F[$i] =~ /^n(.*)/) { $name = $1; last FD; } print "ERROR: unrecognized file set field: \"$F[$i]\"\n"; } } $fdst = 1; next; } print "ERROR: unrecognized: \"$_\"\n"; } # Flush any stored file or process output. if ($fdst) { &list_fd } if ($pidst) { &list_proc } exit(0); ## list_fd -- list file descriptor information # Values are stored inelegantly in global variables. sub list_fd { if ( ! $fhdr) { # Print header once. print " FD TYPE DEVICE SIZE/OFF INODE NAME\n"; $fhdr = 1; } printf " %4s%1.1s%1.1s %4.4s", $fd, $access, $lock, $type; $tmp = $devn; if ($devch ne "") { $tmp = $devch } printf " %10.10s", $tmp; $tmp = $size; if ($offset ne "") { $tmp = $offset } printf " %10.10s", $tmp; $tmp = $inode; if ($proto ne "") { $tmp = $proto } printf " %10.10s", $tmp; $tmp = $stream; if ($name ne "") { $tmp = $name } print " ", $tmp; if ($state ne "") { printf " %s)\n", $state; } else { print "\n"; } # Clear variables. $access = $devch = $devn = $fd = $inode = $lock = ""; $name = $offset = $proto = $size = $state = $stream = $type = ""; } # list_proc -- list process information # Values are stored inelegantly in global variables. sub list_proc { print "COMMAND PID PGRP PPID USER\n"; $tmp = $uid; if ($login ne "") {$tmp = $login } printf "%-9.9s %6d %6d %6d %s\n", $cmd, $pid, $pgrp, $ppid, $tmp; # Clear variables. $cmd = $login = $pgrp = $pid = $uid = ""; $fhdr = $pidst = 0; } lsof-4.86+dfsg.orig/scripts/watch_a_file.perl0000555000175000017500000000430107374004730021441 0ustar nicholasnicholas#!/usr/local/bin/perl # # watch_a_file.perl -- use lsof -F output to watch a specific file # (or file system) # # usage: watch_a_file.perl file_name ## Interrupt handler sub interrupt { wait; print "\n"; exit 0; } ## Start main program $Pn = "watch_a_file"; # Check file argument. if ($#ARGV != 0) { print "$#ARGV\n"; die "$Pn usage: file_name\n"; } $fnm = $ARGV[0]; if (! -r $fnm) { die "$Pn: can't read $fnm\n"; } # Do setup. $RPT = 15; # lsof repeat time $| = 1; # unbuffer output $SIG{'INT'} = 'interrupt'; # catch interrupt # Set path to lsof. if (($LSOF = &isexec("../lsof")) eq "") { # Try .. first if (($LSOF = &isexec("lsof")) eq "") { # Then try . and $PATH print "can't execute $LSOF\n"; exit 1 } } # Read lsof -nPF output from a pipe and gather the PIDs of the processes # and file descriptors to watch. open(P, "$LSOF -nPFpf $fnm|") || die "$Pn: can't pipe to $LSOF\n"; $curpid = -1; $pids = ""; while (

) { chop; if (/^p(.*)/) { $curpid = $1; next; } # Identify process. if (/^f/) { if ($curpid > 0) { if ($pids eq "") { $pids = $curpid; } else { $pids = $pids . "," . $curpid; } $curpid = -1; } } } close(P); wait; if ($pids eq "") { die "$Pn: no processes using $fnm located.\n"; } print "watch_file: $fnm being used by processes:\n\t$pids\n\n"; # Read repeated lsof output from a pipe and display. $pipe = "$LSOF -ap $pids -r $RPT $fnm"; open(P, "$pipe|") || die "$Pn: can't pipe: $pipe\n"; while (

) { print $_; } close(P); print "$Pn: unexpected EOF from \"$pipe\"\n"; exit 1; ## isexec($path) -- is $path executable # # $path = absolute or relative path to file to test for executabiity. # Paths that begin with neither '/' nor '.' that arent't found as # simple references are also tested with the path prefixes of the # PATH environment variable. sub isexec { my ($path) = @_; my ($i, @P, $PATH); $path =~ s/^\s+|\s+$//g; if ($path eq "") { return(""); } if (($path =~ m#^[\/\.]#)) { if (-x $path) { return($path); } return(""); } $PATH = $ENV{PATH}; @P = split(":", $PATH); for ($i = 0; $i <= $#P; $i++) { if (-x "$P[$i]/$path") { return("$P[$i]/$path"); } } return(""); } lsof-4.86+dfsg.orig/scripts/identd.perl50000555000175000017500000000632107374004666020404 0ustar nicholasnicholas#!/usr/local/bin/perl ################################################################### # identd.perl5 : An implementation of RFC 1413 Ident Server # using Vic Abell's lsof. # # - Started from inetd with 'nowait' option. This entry in # /etc/inetd.conf will suffice : # # ident stream tcp nowait root /usr/local/bin/identd.perl5 -t200 # # - Multiple instances of the server are not a performance penalty # since they shall use lsof's cacheing mechanism. (compare with # Peter Eriksson's pidentd) # - assumes 'lsof' binary in /usr/local/sbin # - Command line arguments : # -t TIMEOUT Number of seconds to wait for a query before aborting. # Default is 120. # # Kapil Chowksey ################################################################### use Socket; require 'getopts.pl'; # Set path to lsof. if (($LSOF = &isexec("../lsof")) eq "") { # Try .. first if (($LSOF = &isexec("lsof")) eq "") { # Then try . and $PATH print "can't execute $LSOF\n"; exit 1 } } # redirect lsof's warnings/errors to /dev/null close(STDERR); open(STDERR, ">/dev/null"); $Timeout = "120"; &Getopts('t:'); if ($opt_t) { $Timeout = $opt_t; } ($port, $iaddr) = sockaddr_in(getpeername(STDIN)); $peer_addr = inet_ntoa($iaddr); # read ident-query from socket (STDIN) with a timeout. $timeout = int($Timeout); eval { local $SIG{ALRM} = sub { die "alarm\n" }; alarm $timeout; $query = ; alarm 0; }; die if $@ && $@ ne "alarm\n"; if ($@) { # timed out exit; } # remove all white-spaces from query $query =~ s/\s//g; $serv_port = ""; $cli_port = ""; ($serv_port,$cli_port) = split(/,/,$query); if ($serv_port =~ /^[0-9]+$/) { if (int($serv_port) < 1 || int($serv_port) > 65535) { print $query." : ERROR : INVALID-PORT"."\n"; exit; } } else { print $query." : ERROR : INVALID-PORT"."\n"; exit; } if ($cli_port =~ /^[0-9]+$/) { if (int($cli_port) < 1 || int($cli_port) > 65535) { print $query." : ERROR : INVALID-PORT"."\n"; exit; } } else { print $query." : ERROR : INVALID-PORT"."\n"; exit; } open(LSOFP,"$LSOF -nPDi -T -FLn -iTCP@".$peer_addr.":".$cli_port."|"); $user = "UNKNOWN"; while ($a_line = ) { # extract user name. if ($a_line =~ /^L.*/) { ($user) = ($a_line =~ /^L(.*)/); } # make sure local port matches. if ($a_line =~ /^n.*:\Q$serv_port->/) { print $serv_port.", ".$cli_port." : USERID : UNIX :".$user."\n"; exit; } } print $serv_port.", ".$cli_port." : ERROR : NO-USER"."\n"; ## isexec($path) -- is $path executable # # $path = absolute or relative path to file to test for executabiity. # Paths that begin with neither '/' nor '.' that arent't found as # simple references are also tested with the path prefixes of the # PATH environment variable. sub isexec { my ($path) = @_; my ($i, @P, $PATH); $path =~ s/^\s+|\s+$//g; if ($path eq "") { return(""); } if (($path =~ m#^[\/\.]#)) { if (-x $path) { return($path); } return(""); } $PATH = $ENV{PATH}; @P = split(":", $PATH); for ($i = 0; $i <= $#P; $i++) { if (-x "$P[$i]/$path") { return("$P[$i]/$path"); } } return(""); } lsof-4.86+dfsg.orig/scripts/shared.perl50000555000175000017500000002447707375723657020430 0ustar nicholasnicholas#!/usr/local/bin/perl # # $Id: shared.perl5,v 1.4 2001/11/18 12:20:46 abe Exp $ # # shared.perl5 -- sample Perl 5 script to list processes that share # file descriptors or files, using `lsof +ffn -F..." # output # # Usage: shared [fd|file] # # where: fd to list file descriptors (default) # # file to list files # # This script has been tested under perl version 5.001e. # IMPORTANT DEFINITIONS # ===================== # # 1. Set the interpreter line of this script to the local path of the # Perl5 executable. # 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. # Initialize variables. $Access = $Devch = $Devn = $Fd = $Fsa = $Inode = $Lock = # file $Na = $Name = ""; # | descriptor $Cmd = $Login = $Pgrp = $Pid = $Ppid = $Uid = ""; # process var. $Fdst = 0; # fd state $Hdr = 0; # header state $Offset = $Proto = $Size = $State = $Stream = $Type = ""; # | variables $Pidst = 0; # process state $Pn = "shared"; # Set path to lsof. if (($LSOF = &isexec("../lsof")) eq "") { # Try .. first if (($LSOF = &isexec("lsof")) eq "") { # Then try . and $PATH print "can't execute $LSOF\n"; exit 1 } } # Define print field constants. $CmdTtl = "CMD"; $CmdW = length($CmdTtl); $DevTtl = "DEVICE"; $DevW = length($DevTtl); $FdTtl = "FD"; $FdW = length($FdTtl); $InoTtl = "NODE"; $InoW = length($InoTtl); $KeyTtl = "FILEADDR"; $KeyW = length($KeyTtl); $PidTtl = "PID"; $PidW = length($PidTtl); $PpidTtl = "PPID"; $PpidW = length(PpidTtl); # Process one (optional) argument. if ($#ARGV >= 0) { $err = 0; if ($#ARGV > 1) { $err = 1; } elsif ($ARGV[0] eq "fd") { $KeyTtl = "FILEADDR"; $Shfd = 1; $Shfile = 0; } elsif ($ARGV[0] eq "file") { $KeyTtl = "NODEID"; $Shfd = 0; $Shfile = 1; } else { $err = 1; } if ($err) { die "$Pn: usage [fd|file]\n"; } shift; } else { $Shfd = 1; $Shfile = 0; } $KeyW = length($KeyTtl); # Open a pipe from lsof. if (!open(LSOF_PIPE, "$LSOF -R +ffn -F0pcRDfFinN |")) { die "$Pn: can't open pipe to: $LSOF\n"; } # Process the lsof output a line at a time, gathering the variables for # processes and files. while () { chop; @F = split('\0', $_, 999); if ($F[0] =~ /^p/) { # A process set begins with a PID field whose ID character is `p'. if ($Fdst) { &End_fd } if ($Pidst) { &End_proc } foreach $i (0 .. ($#F - 1)) { PROC: { if ($F[$i] =~ /^c(.*)/) { $Cmd = $1; last PROC } if ($F[$i] =~ /^g(.*)/) { $Pgrp = $1; last PROC } if ($F[$i] =~ /^p(.*)/) { $Pid = $1; last PROC } if ($F[$i] =~ /^u(.*)/) { $Uid = $1; last PROC } if ($F[$i] =~ /^L(.*)/) { $Login = $1; last PROC } if ($F[$i] =~ /^R(.*)/) { $Ppid = $1; last PROC } print "ERROR: unrecognized process field: \"$F[$i]\"\n"; } } $Pidst = 1; next; } # A file descriptor set begins with a file descriptor field whose ID # character is `f'. if ($F[0] =~ /^f/) { if ($Fdst) { &End_fd } foreach $i (0 .. ($#F - 1)) { FD: { if ($F[$i] =~ /^a(.*)/) { $Access = $1; last FD; } if ($F[$i] =~ /^f(.*)/) { $Fd = $1; last FD; } if ($F[$i] =~ /^F(.*)/) { $Fsa = $1; last FD; } if ($F[$i] =~ /^l(.*)/) { $Lock = $1; last FD; } if ($F[$i] =~ /^t(.*)/) { $Type = $1; last FD; } if ($F[$i] =~ /^d(.*)/) { $Devch = $1; last FD; } if ($F[$i] =~ /^D(.*)/) { $Devn = $1; last FD; } if ($F[$i] =~ /^s(.*)/) { $Size = $1; last FD; } if ($F[$i] =~ /^o(.*)/) { $Offset = $1; last FD; } if ($F[$i] =~ /^i(.*)/) { $Inode = $1; last FD; } if ($F[$i] =~ /^P(.*)/) { $Proto = $1; last FD; } if ($F[$i] =~ /^S(.*)/) { $Stream = $1; last FD; } if ($F[$i] =~ /^T(.*)/) { if ($State eq "") { $State = "(" . $1; } else { $State = $State . " " . $1; } last FD; } if ($F[$i] =~ /^n(.*)/) { $Name = $1; last FD; } if ($F[$i] =~ /^N(.*)/) { $Na = $1; last FD; } print "ERROR: unrecognized file set field: \"$F[$i]\"\n"; } } $Fdst = 1; next; } print "ERROR: unrecognized: \"$_\"\n"; } close(LSOF_PIPE); if ($Fdst) { &End_fd } if ($Pidst) { &End_proc } # List matching files or file descriptors. for ($pass = 0; $pass < 2; $pass++) { foreach $key (sort keys(%Fds)) { @Praw = split(' ', $Fds{$key}, 999); if ($#Praw < 1) { next; } if ($Shfd) { @P = sort Sort_by_FD_and_PID @Praw; } else { @P = sort Sort_by_PID_and_FD @Praw; } # Accumulate and print blocks of (key, PID, FD) triplets. for ($i = 0; $i < $#P; $i++) { if ($Shfile) { for ($n = 0; $n <= $#P; $n++) { ($pid, $fd) = split(",", $P[$n], 999); $PrtPid[$n] = $pid; $PrtFd[$n] = $fd; } $i = $n; } else { ($pid, $fd) = split(",", $P[$i], 999); $PrtFd[0] = $fd; $PrtPid[0] = $pid; for ($n = 1; $i < $#P; $i++, $n++) { ($nxtpid, $nxtfd) = split(",", $P[$i + 1], 999); if ($fd ne $nxtfd) { last; } $PrtFd[$n] = $nxtfd; $PrtPid[$n] = $nxtpid; } } if ($n > 1) { &Print_block($key, $n, $pass); } } } } exit(0); ## End_fd() -- process end of file descriptor sub End_fd { local ($key); if ($Fdst && $Pidst && $Pid ne "") { if ($Cmd ne "") { $Cmds{$Pid} = $Cmd; } if ($Ppid ne "") { $Ppids{$Pid} = $Ppid; } $key = $Shfd ? $Fsa : $Na; if ($key ne "") { if (!defined($Fds{$key})) { $Fds{$key} = "$Pid,$Fd"; } else { $Fds{$key} .= " $Pid,$Fd"; } if ($Name ne "" && !defined($Name{$key})) { $Name{$key} = $Name } if ($Inode ne "" && !defined($Inodes{$key})) { $Inodes{$key} = $Inode; } if ($Devn ne "" && !defined($Devns{$key})) { $Devns{$key} = $Devn; } } } # Clear variables. $Access = $Devch = $Devn = $Fd = $Fsa = $Inode = $Lock = ""; $Na = $Name = $Offset = $Proto = $Size = $State = $Stream = $Type = ""; $Fdst = 0; } ## End_proc() -- process end of process sub End_proc { # Clear variables. $Cmd = $Login = $Pgrp = $Pid = $Ppid = $Uid = ""; $Fdst = $Pidst = 0; } ## Print_block() -- print a block of entries # # entry: # # @_[0] = block's key # @_[1] = number of entries in the block # @_[2] = print pass status (1 == print) sub Print_block { my ($key, $n, $pass) = @_; local ($fd, $i, $pid, $t, $tW); if ($pass) { if (!$Hdr) { printf "%${KeyW}.${KeyW}s", $KeyTtl; printf " %${PidW}.${PidW}s", $PidTtl; printf " %${PpidW}.${PpidW}s", $PpidTtl; printf " %-${CmdW}.${CmdW}s", $CmdTtl; printf " %${FdW}.${FdW}s", $FdTtl; printf " %${DevW}.${DevW}s", $DevTtl; printf " %${InoW}.${InoW}s", $InoTtl; printf " NAME\n"; $Hdr = 1; } else { print "\n"; } } # Loop through block. During a non-print pass, caclulate maximum field widths. for ($i = 0; $i < $n; $i++) { $fd = $PrtFd[$i]; $pid = $PrtPid[$i]; # Process key. if (!$pass) { $tW = length(sprintf("%s", $key)); if ($tW > $KeyW) { $KeyW = $tW; } } else { printf "%s", $key; } # Process PID. if (!$pass) { $tW = length(sprintf(" %s", $pid)); if ($tW > $PidW) { $PidW = $tW; } } else { printf " %${PidW}.${PidW}s", $pid; } # Process parent PID. $t = defined($Ppids{$pid}) ? $Ppids{$pid} : ""; if (!$pass) { $tW = length(sprintf(" %s", $t)); if ($tW > $PpidW) { $PpidW = $tW; } } else { printf " %${PpidW}.${PpidW}s", $t; } # Process command name. $t = defined($Cmds{$pid}) ? $Cmds{$pid} : ""; if (!$pass) { $tW = length(sprintf(" %s", $t)); if ($tW > $CmdW) { $CmdW = $tW; } } else { printf " %-${CmdW}.${CmdW}s", $t; } # Process file descriptor. if (!$pass) { $tW = length(sprintf(" %s", $fd)); if ($tW > $FdW) { $FdW = $tW; } } else { printf " %${FdW}.${FdW}s", $fd; } # Process device number. $t = defined($Devns{$key}) ? $Devns{$key} : ""; if (!$pass) { $tW = length(sprintf(" %s", $t)); if ($tW > $DevW) { $DevW = $tW; } } else { printf " %${DevW}.${DevW}s", $t; } # Process node number. $t = defined($Inodes{$key}) ? $Inodes{$key} : $t; if (!$pass) { $tW = length(sprintf (" %s", $t)); if ($tW > $InoW) { $InoW = $tW; } } else { printf " %${InoW}.${InoW}s", $t; } # Print name and line terminater, if this is a print pass. if ($pass) { if (defined($Name{$key})) { print " $Name{$key}\n"; } else { print "\n"; } } } } ## Sort_by_FD_and_PID() -- sort (PID,FD) doublets by FD first, then PID sub Sort_by_FD_and_PID { local ($pida, $pidb, $fda, $fdj, $rv); ($pida, $fda) = split(",", $a); ($pidb, $fdb) = split(",", $b); if ($fda < $fdb) { return(-1); } if ($fda > $fdb) { return(1); } if ($pida < $pidb) { return(-1); } if ($pida > $pidb) { return(1); } return(0); } ## Sort_by_PID_and_FD() -- sort (PID,FD) doublets by PID first, then FD sub Sort_by_PID_and_FD { local ($pida, $pidb, $fda, $fdj, $rv); ($pida, $fda) = split(",", $a); ($pidb, $fdb) = split(",", $b); if ($pida < $pidb) { return(-1); } if ($pida > $pidb) { return(1); } if ($fda < $fdb) { return(-1); } return(0); if ($fda > $fdb) { return(1); } } ## isexec($path) -- is $path executable # # $path = absolute or relative path to file to test for executabiity. # Paths that begin with neither '/' nor '.' that arent't found as # simple references are also tested with the path prefixes of the # PATH environment variable. sub isexec { my ($path) = @_; my ($i, @P, $PATH); $path =~ s/^\s+|\s+$//g; if ($path eq "") { return(""); } if (($path =~ m#^[\/\.]#)) { if (-x $path) { return($path); } return(""); } $PATH = $ENV{PATH}; @P = split(":", $PATH); for ($i = 0; $i <= $#P; $i++) { if (-x "$P[$i]/$path") { return("$P[$i]/$path"); } } return(""); } lsof-4.86+dfsg.orig/scripts/00README0000444000175000017500000000401207453143177017173 0ustar nicholasnicholas Notes on Using the Scripts in This Subdirectory The scripts in this subdirectory are examples of post-processing lsof field output. Some are contributed by lsof users and are reproduced substantially as written by those users. Since the scripts are examples, they are not guaranteed to work on all UNIX dialects. Use them to learn about processing field output, don't expect them to be ready for production, and expect to be required to modify them to make them work. If you want to do field output post-processing in a C program, take a look at the test suite C library in ../tests/LTlib.c. You may be able to adapt it to your needs. The scripts are written in AWK, Perl 4 (4.036), and Perl 5 (5.001e through 5.006). AWK scripts have a suffix of ``.awk''; Perl 4 (which will work under Perl 5) scripts have a ``.perl4'' suffix; and Perl 5 scripts, ``.perl''. Supply AWK scripts to your AWK interpreter with its -f option. Supply lsof field output via a pipe -- e.g., lsof -F | awk -f list_fields.awk The Perl scripts use the Unix command interpreter line feature to specify the location of Perl -- i.e., the first line begins with ``#!'' and the path to the Perl interpreter follows. If your system supports the command interpreter feature, but your Perl interpreters have different paths to them, just change the interpreter lines in the scripts. These scripts assume: Path to: Is: ======= == Perl 4 /usr/local/bin/perl4 Perl 5 /usr/local/bin/perl If your system doesn't support the command interpreter feature, you'll have to supply the scripts to your Perl interpreter on its command line -- e.g., lsof -F | / list_fields.perl The Perl scripts attempt to establish a path to lsof, putting their result in the $LSOF variable. Assuming you'll run them from the scripts subdirectory, they look there first, then in the directories of the PATH environment variable. If that proves unsuitable, modify the &isexec() subroutine calls in the scripts to suit your lsof location. Vic Abell April 4, 2002 lsof-4.86+dfsg.orig/scripts/idrlogin.perl0000555000175000017500000001226207375723654020666 0ustar nicholasnicholas#!/usr/local/bin/perl # # $Id: idrlogin.perl,v 1.5 2001/11/18 12:20:46 abe Exp $ # # idrlogin.perl -- sample Perl script to identify the network source of a # network (remote) login via rlogind, sshd, or telnetd # IMPORTANT DEFINITIONS # ===================== # # 1. Set the interpreter line of this script to the local path of the # Perl executable. # # 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. # Initialize variables. $dev = $name = $proto = ""; # fd variables $fdst = 0; # fd state $pidst = 0; # process state $cmd = $login = $pid = $ppid = ""; # process var. # Set path to lsof. if (($LSOF = &isexec("../lsof")) eq "") { # Try .. first if (($LSOF = &isexec("lsof")) eq "") { # Then try . and $PATH print "can't execute $LSOF\n"; exit 1 } } # Open a pipe from lsof. open(P, "$LSOF -R -FcDfLpPRn|") || die "Can't pipe from $LSOF\n"; # Process the ``lsof -FcDfLpPRn'' output a line at a time while (

) { chop; if (/^p(.*)/) { # A process set begins with a PID field whose ID character is `p'. $tpid = $1; if ($pidst && $fdst) { &save_proc } $pidst = 1; $pid = $tpid; $cmd = $login = $ppid = ""; $fdst = 0; $dev = $name = $proto = ""; next; } # Save process-related values. if (/^c(.*)/) { $cmd = $1; next; } if (/^L(.*)/) { $login = $1; next; } if (/^R(.*)/) { $ppid = $1; next; } # A file set begins with a file descriptor field. if (/^f/) { if ($pidst && $fdst) { &save_proc } $fdst = 0; $dev = $name = $proto = ""; next; } # Accumulate file information. if (/^D(.*)/) { $dev = $1; next; } if (/^P(.*)/) { $proto = $1; next; } if (/^n(.*)/) { $name = $1; $fdst = 1; next; } } # Flush any stored file or process output. if ($pidst && $fdst) { &save_proc } # List the shell processes that have rlogind/sshd//telnetd parents. $hdr = 0; foreach $pid (sort keys(%shcmd)) { $p = $pid; if (!defined($raddr{$pid})) { for ($ff = 0; !$ff && defined($Ppid{$p}); ) { $p = $Ppid{$p}; if ($p < 2 || defined($raddr{$p})) { $ff = 1; } } } else { $ff = 2; } if ($ff && defined($raddr{$p})) { if (!$hdr) { printf "%-8.8s %-8.8s %6s %-10.10s %6s %-10.10s %s\n", "Login", "Shell", "PID", "Via", "PID", "TTY", "From"; $hdr = 1; } printf "%-8.8s %-8.8s %6d %-10.10s %6s %-10.10s %s\n", $shlogin{$pid}, $shcmd{$pid}, $pid, ($ff == 2) ? "(direct)" : $rcmd{$p}, ($ff == 2) ? "" : $p, ($shtty{$pid} eq "") ? "(unknown)" : $shtty{$pid}, $raddr{$p}; } } exit(0); # save_proc -- save process information # Values are stored inelegantly in global variables. sub save_proc { if ($cmd eq "" || $login eq "" || $ppid eq "" || $pid eq "" || $name eq "" ) { return; } if (!defined($Ppid{$pid})) { $Ppid{$pid} = $ppid; } if ($proto eq "TCP" && (($cmd =~ /rlogind/) || ($cmd =~ /sshd/) || ($cmd =~ /telnetd/))) { if (defined($raddr{$pid})) { return; } if (($name =~ /[^:]*:[^-]*->([^:]*):.*/)) { $raddr{$pid} = $1; $rcmd{$pid} = $cmd; return; } } if (($cmd =~ /.*sh$/)) { if (defined($shcmd{$pid})) { return; } if ($proto eq "TCP") { if (defined($raddr{$pid})) { return; } if (($name =~ /[^:]*:[^-]*->([^:]*):.*/)) { $raddr{$pid} = $1; $shcmd{$pid} = $cmd; $shlogin{$pid} = $login; } } if (($name =~ m#/dev.*ty.*#)) { ($tty) = ($name =~ m#/dev.*/(.*)#); } elsif (($name =~ m#/dev/(pts/\d+)#)) { $tty = $1; } elsif (($name =~ m#/dev.*pts.*#)) { $d = oct($dev); $tty = sprintf("pts/%d", $d & 0xffff); } else { return; } } else { return; } $shcmd{$pid} = $cmd; $shtty{$pid} = $tty; $shlogin{$pid} = $login; } ## isexec($path) -- is $path executable # # $path = absolute or relative path to file to test for executabiity. # Paths that begin with neither '/' nor '.' that arent't found as # simple references are also tested with the path prefixes of the # PATH environment variable. sub isexec { my ($path) = @_; my ($i, @P, $PATH); $path =~ s/^\s+|\s+$//g; if ($path eq "") { return(""); } if (($path =~ m#^[\/\.]#)) { if (-x $path) { return($path); } return(""); } $PATH = $ENV{PATH}; @P = split(":", $PATH); for ($i = 0; $i <= $#P; $i++) { if (-x "$P[$i]/$path") { return("$P[$i]/$path"); } } return(""); } lsof-4.86+dfsg.orig/scripts/count_pf.perl0000555000175000017500000000347707374004647020675 0ustar nicholasnicholas#!/usr/local/bin/perl # # count_pf.perl-- run lsof in repeat mode and count processes and # files sub interrupt { print "\n"; exit 0; } $RPT = 15; # lsof repeat time # Set path to lsof. if (($LSOF = &isexec("../lsof")) eq "") { # Try .. first if (($LSOF = &isexec("lsof")) eq "") { # Then try . and $PATH print "can't execute $LSOF\n"; exit 1 } } # Read lsof -nPF output repeatedly from a pipe. $| = 1; # unbuffer output $SIG{'INT'} = 'interrupt'; # catch interrupt $proc = $files = $proto{'TCP'} = $proto{'UDP'} = 0; $progress="/"; # used to show "progress" open(P, "$LSOF -nPF -r $RPT|") || die "can't open pipe to $LSOF\n"; while (

) { chop; if (/^m/) { # A marker line signals the end of an lsof repetition. printf "%s Processes: %5d, Files: %6d, TCP: %6d, UDP: %6d\r", $progress, $proc, $files, $proto{'TCP'}, $proto{'UDP'}; $proc = $files = $proto{'TCP'} = $proto{'UDP'} = 0; if ($progress eq "/") { $progress = "\\"; } else { $progress = "/"; } next; } if (/^p/) { $proc++; next; } # Count processes. if (/^f/) { $files++; next; } # Count files. if (/^P(.*)/) { $proto{$1}++; next; } # Count protocols. } ## isexec($path) -- is $path executable # # $path = absolute or relative path to file to test for executabiity. # Paths that begin with neither '/' nor '.' that arent't found as # simple references are also tested with the path prefixes of the # PATH environment variable. sub isexec { my ($path) = @_; my ($i, @P, $PATH); $path =~ s/^\s+|\s+$//g; if ($path eq "") { return(""); } if (($path =~ m#^[\/\.]#)) { if (-x $path) { return($path); } return(""); } $PATH = $ENV{PATH}; @P = split(":", $PATH); for ($i = 0; $i <= $#P; $i++) { if (-x "$P[$i]/$path") { return("$P[$i]/$path"); } } return(""); } lsof-4.86+dfsg.orig/scripts/xusers.awk0000555000175000017500000000760706311065231020212 0ustar nicholasnicholas#!/usr/bin/awk -f ################################################################ # # Program Name : xusers # Date Created : 02-27-97 # Author : Dan A. Mercer # Email : damercer@mmm.com # : # Description : Print list of users and applications signed on # : X workstations ################################################################ # standard help message function help(hlpmsg) { basename = ARGV[0] sub(/.*\//,"",basename) printf "Format: %s [o=[hi]] [s=cdlp] [pattern]\n", basename print "Print list of users and applications signed on X workstations" print "NOTE: applicationname is truncated to 9 chars" print "Arguments:" print " o=[h|i] - Options" print " h - help - print this message" print " i - case insensitive pattern search" print " s=[c|d|l|p] - Sort Options" print " c - sort by command" print " d - sort by display name" print " l - sort by login name" print " p - sort by pid" print " pattern - regex pattern to search commands against" if (length(hlpmsg)) print hlpmsg exit } BEGIN { # process command line for (i=1;i 0) { type = substr(field,1,1) sub("^.","",field) if ("p" == type) { # always output first pid = field PID[pid] = ++ct } else if ("c" == type) { # always output second XAPPL[pid] = field } else if ("L" == type) { # always output fourth USER[pid] = field } else if ("n" == type) { # may be multiple instances - we just use the last gsub(".*->|:6000","",field) DPY[pid] = field } } close(cmd) printf "%8s %5s %-9s %s\n","USER","PID","COMMAND","DISPLAY" for (pid in PID) { if (((igncase) ? tolower(XAPPL[pid]) : XAPPL[pid]) ~ pattern) printf "%8s %5d %-9s %s\n", USER[pid],pid,XAPPL[pid],DPY[pid] | sort } close(sort) exit } lsof-4.86+dfsg.orig/scripts/list_fields.perl0000555000175000017500000001077107133644004021342 0ustar nicholasnicholas#!/usr/local/bin/perl4 # # $Id: list_fields.perl,v 1.5 2000/07/14 17:03:37 abe Exp $ # # list_fields.perl -- sample Perl script to list lsof full field output # (i.e., -F output without -0) # # This script has been tested under perl versions 4.036 and 5.001e. # # 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. # Initialize variables. $fhdr = 0; # fd hdr. flag $fdst = 0; # fd state $access = $devch = $devn = $fd = $inode = $lock = $name = ""; # | file descr. $offset = $proto = $size = $state = $stream = $type = ""; # | variables $pidst = 0; # process state $cmd = $login = $pgrp = $pid = $ppid = $uid = ""; # process var. # Process the ``lsof -F'' output a line at a time, gathering # the variables for a process together before printing them; # then gathering the variables for each file descriptor # together before printing them. while (<>) { chop; if (/^p(.*)/) { # A process set begins with a PID field whose ID character is `p'. $tpid = $1; if ($pidst) { &list_proc } $pidst = 1; $pid = $tpid; if ($fdst) { &list_fd; $fdst = 0; } next; } # Save process-related values. if (/^g(.*)/) { $pgrp = $1; next; } if (/^c(.*)/) { $cmd = $1; next; } if (/^u(.*)/) { $uid = $1; next; } if (/^L(.*)/) { $login = $1; next; } if (/^R(.*)/) { $ppid = $1; next; } # A file descriptor set begins with a file descriptor field whose ID # character is `f'. if (/^f(.*)/) { $tfd = $1; if ($pidst) { &list_proc } if ($fdst) { &list_fd } $fd = $tfd; $fdst = 1; next; } # Save file set information. if (/^a(.*)/) { $access = $1; next; } if (/^C(.*)/) { next; } if (/^d(.*)/) { $devch = $1; next; } if (/^D(.*)/) { $devn = $1; next; } if (/^F(.*)/) { next; } if (/^G(.*)/) { next; } if (/^i(.*)/) { $inode = $1; next; } if (/^k(.*)/) { next; } if (/^l(.*)/) { $lock = $1; next; } if (/^N(.*)/) { next; } if (/^o(.*)/) { $offset = $1; next; } if (/^P(.*)/) { $proto = $1; next; } if (/^s(.*)/) { $size = $1; next; } if (/^S(.*)/) { $stream = $1; next; } if (/^t(.*)/) { $type = $1; next; } if (/^T(.*)/) { if ($state eq "") { $state = "(" . $1; } else { $state = $state . " " . $1; } next; } if (/^n(.*)/) { $name = $1; next; } print "ERROR: unrecognized: \"$_\"\n"; } # Flush any stored file or process output. if ($fdst) { &list_fd } if ($pidst) { &list_proc } exit(0); ## list_fd -- list file descriptor information # Values are stored inelegantly in global variables. sub list_fd { if ( ! $fhdr) { # Print header once. print " FD TYPE DEVICE SIZE/OFF INODE NAME\n"; $fhdr = 1; } printf " %4s%1.1s%1.1s %4.4s", $fd, $access, $lock, $type; $tmp = $devn; if ($devch ne "") { $tmp = $devch } printf " %10.10s", $tmp; $tmp = $size; if ($offset ne "") { $tmp = $offset } printf " %10.10s", $tmp; $tmp = $inode; if ($proto ne "") { $tmp = $proto } printf " %10.10s", $tmp; $tmp = $stream; if ($name ne "") { $tmp = $name } print " ", $tmp; if ($state ne "") { printf " %s)\n", $state; } else { print "\n"; } # Clear variables. $access = $devch = $devn = $fd = $inode = $lock = $name = ""; $offset = $proto = $size = $state = $stream = $type = ""; } # list_proc -- list process information # Values are stored inelegantly in global variables. sub list_proc { print "COMMAND PID PGRP PPID USER\n"; $tmp = $uid; if ($login ne "") {$tmp = $login } printf "%-9.9s %6d %6d %6d %s\n", $cmd, $pid, $pgrp, $ppid, $tmp; # Clear variables. $cmd = $login = $pgrp = $pid = $uid = ""; $fhdr = $pidst = 0; } lsof-4.86+dfsg.orig/scripts/count_pf.perl50000555000175000017500000000375407374004656020760 0ustar nicholasnicholas#!/usr/local/bin/perl # # count_pf.perl5 -- run lsof in repeat mode and count processes and # files sub interrupt { print "\n"; exit 0; } $RPT = 15; # lsof repeat time # Set path to lsof. if (($LSOF = &isexec("../lsof")) eq "") { # Try .. first if (($LSOF = &isexec("lsof")) eq "") { # Then try . and $PATH print "can't execute $LSOF\n"; exit 1 } } # Read lsof -nPF0 output repeatedly from a pipe. $| = 1; # unbuffer output $SIG{'INT'} = 'interrupt'; # catch interrupt $proc = $files = $tcp = $udp = 0; $progress="/"; open(P, "$LSOF -nPF0 -r $RPT|") || die "can't open pipe to $LSOF\n"; LSOF_LINE: while (

) { chop; if (/^m/) { # A marker line signals the end of an lsof repetition. printf "%s Processes: %5d, Files: %6d, TCP: %6d, UDP: %6d\r", $progress, $proc, $files, $tcp, $udp; $proc = $files = $tcp = $udp = 0; if ($progress eq "/") { $progress = "\\"; } else { $progress = "/"; } next LSOF_LINE; } if (/^p/) { # Count process. $proc++; next LSOF_LINE; } if (/^f/) { # Count files. $files++; @F = split("\0", $_, 999); foreach $i (0 .. ($#F - 1)) { # Search for protocol field. if ($F[$i] =~ /^P(.*)/) { # Count instances of TCP and UDP protocols. if ($1 eq "TCP") { $tcp++; } elsif ($1 eq "UDP") { $udp++; } next LSOF_LINE; } } } } ## isexec($path) -- is $path executable # # $path = absolute or relative path to file to test for executabiity. # Paths that begin with neither '/' nor '.' that arent't found as # simple references are also tested with the path prefixes of the # PATH environment variable. sub isexec { my ($path) = @_; my ($i, @P, $PATH); $path =~ s/^\s+|\s+$//g; if ($path eq "") { return(""); } if (($path =~ m#^[\/\.]#)) { if (-x $path) { return($path); } return(""); } $PATH = $ENV{PATH}; @P = split(":", $PATH); for ($i = 0; $i <= $#P; $i++) { if (-x "$P[$i]/$path") { return("$P[$i]/$path"); } } return(""); } lsof-4.86+dfsg.orig/scripts/list_fields.awk0000444000175000017500000001330406411751412021152 0ustar nicholasnicholas# $Id: list_fields.awk,v 1.3 97/09/23 09:32:38 abe Exp $ # # list_fields.awk -- sample awk script to list lsof full field output # (i.e., -F output without -0) # # NB: this is not particularly elegant awk; several sections were # replicated, perhaps unnecessarily, to produce a sample quickly # and simply. # # # 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. # Clear file and process status. BEGIN { fhdr = fdst = pidst = 0; access = dev = devch = fd = inode = lock = name = offset = ""; proto = size = state = stream = type = ""; cmd = login = pgrp = pid = ppid = uid = ""; } # Start a new process. /^p/ { val = substr($0, 2); if (pidst) { # Print a previously accumulated process set. printf "COMMAND PID PGRP PPID USER\n"; printf "%-9.9s %6d %6d %6d", cmd, pid, pgrp, ppid; if (login != "") { printf " %s\n", login } else { printf " %s\n", uid } pidst = 0; cmd = login = pgrp = pid = uid = ""; } if (fdst) { # Print a previously accumulated file set. if (fhdr == 0) { printf " FD TYPE DEVICE SIZE/OFF INODE NAME\n"; } printf " %4.4s%1.1s%1.1s %4.4s", fd, access, lock, type; t = dev; if (devch != "") { t = devch } printf(" %10.10s", t); t = size; if (offset != "") { t = offset } printf " %10.10s", t; t = inode; if (proto != "") { t = proto } printf " %10.10s", t; t = stream; if (name != "") {t = name } printf " %s", t; if (state != "") { printf " %s)\n", state } else { printf "\n" } access = dev = devch = fd = inode = lock = name = offset = ""; proto = size = state = stream = type = ""; fdst = fhdr = 0 } # Record a new process. pidst = 1; pid = val; } /^g|^c|^u|^L|^R/ { # Save process set information. id = substr($0, 1, 1); val = substr($0, 2); if (id == "g") { pgrp = val; next } # PGRP if (id == "c") { cmd = val; next } # command if (id == "u") { uid = val; next } # UID if (id == "L") { login = val; next } # login name if (id == "R") { ppid = val; next } # PPID } /^f|^a|^l|^t|^d|^D|^s|^o|^i|^P|^S|^T|^n/ { # Save file set information. id = substr($0, 1, 1); val = substr($0, 2); if (id == "f") { if (pidst) { # Print a previously accumulated process set. printf "COMMAND PID PGRP PPID USER\n"; printf "%-9.9s %6d %6d %6d", cmd, pid, pgrp, ppid; if (login != "") { printf " %s\n", login } else { printf " %s\n", uid } pidst = 0; cmd = login = pgrp = pid = uid = ""; } if (fdst) { # Print a previously accumulated file set. if (fhdr == 0) { printf " FD TYPE DEVICE SIZE/OFF INODE NAME\n"; } fhdr = 1; printf " %4.4s%1.1s%1.1s %4.4s", fd, access, lock, type; t = dev; if (devch != "") { t = devch } printf(" %10.10s", t); t = size; if (offset != "") { t = offset } printf " %10.10s", t; t = inode; if (proto != "") { t = proto } printf " %10.10s", t; t = stream; if (name != "") {t = name } printf " %s", t; if (state != "") { printf " %s)\n", state } else { printf "\n" } access = dev = devch = fd = inode = lock = name = offset = ""; proto = size = state = stream = type = ""; } # Start an new file set. fd = val; fdst = 1; next; } # Save file set information. if (id == "a") { access = val; next } # access if (id == "l") { lock = val; next } # lock if (id == "t") { type = val; next } # type if (id == "d") { devch = val; next } # device characters if (id == "D") { dev = val; next } # device major/minor numbers if (id == "s") { size = val; next } # size if (id == "o") { offset = val; next } # offset if (id == "i") { inode = val; next } # inode number if (id == "P") { proto = val; next } # protocol if (id == "S") { stream = val; next } # stream name if (id == "T") { # TCP/TPI state if (state == "") { state = sprintf("(%s", val); } else { state = sprintf("%s %s", state, val); } next } if (id == "n") { name = val; next } # name, comment, etc. } END { if (pidst) { # Print last process set. printf "COMMAND PID PGRP PPID USER\n"; printf "%-9.9s %6d %6d %6d", cmd, pid, pgrp, ppid; if (login != "") { printf " %s\n", login } else { printf " %s\n", uid } } if (fdst) { # Print last file set. if (fhdr == 0) { printf " FD TYPE DEVICE SIZE/OFF INODE NAME\n"; } printf " %4.4s%1.1s%1.1s %4.4s", fd, access, lock, type; t = dev; if (devch != "") { t = devch } printf(" %10.10s", t); t = size; if (offset != "") { t = offset } printf " %10.10s", t; t = inode; if (proto != "") { t = proto } printf " %10.10s", t; t = stream; if (name != "") {t = name } printf " %s", t; if (state != "") { printf " %s)\n", state; } else { printf "\n"; } } } lsof-4.86+dfsg.orig/scripts/00MANIFEST0000444000175000017500000000341710063333420017433 0ustar nicholasnicholasThe scripts in this subdirectory give examples of using lsof's field output. big_brother.perl5 Perl 5 script, contributed by Lionel Cons , that watches for new network connections. count_pf.perl Perl 4 or 5 script that runs lsof in repeat mode, gathering process, file, TCP, and UDP counts count_pf.perl5 Perl 5 script that runs lsof in repeat mode, gathering process, file, TCP, and UDP counts This script uses NUL terminated lsof field output. identd.perl5 Perl 5 script, contributed by Kapil Chowksey that implements an identd server. (Thanks, Kapil!) idrlogin.perl Perl 4 script that identifies the shell and network source address of users who have logged on from remote locations via rlogin, ssh, or telnet idrlogin.perl5 Perl 5 script that identifies the shell and network source address of users who have logged on from remote locations via rlogin, ssh, or telnet list_NULf.perl5 Perl 5 script that prints lsof's NUL terminated field output list_fields.awk AWK script that prints lsof's field output list_fields.perl Perl 4 or 5 script that prints lsof's field output shared.perl5 Perl 5 script that uses +ffn output to produce a list of file descriptors or files shared by processes. sort_res.perl5 Perl 5 script, contributed by Fabian Frederick , to display top resource usage. watch_a_file.perl Perl 4 or 5 script that watches the use of a named file xusers.awk an AWK (actually NAWK) script, written by Dan A. Mercer that, "Prints list of users and applications signed on X workstations." This script was developed and is used with lsof on HP-UX systems. Vic Abell December 28, 1998 lsof-4.86+dfsg.orig/scripts/sort_res.perl50000555000175000017500000000723510352274353020772 0ustar nicholasnicholas#!/usr/bin/perl # sort_res.perl5 - Script to group & sort lsof output by resource # # Copyright (c) 2004, 2005 - Fabian Frederick # # This program/include file is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as published # by the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program/include file 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program (in the main directory of the Linux-NTFS # distribution in the file COPYING); if not, write to the Free Software # Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Note : # -This script uses lsof released by Victor A. Abell # -lsof path recovery comes from standard perl scripts in there. # # Usage : # perl sort_res.perl5 -> display used resources + size # or perl sort_res.perl5 # # 12/2005 (FabF) # -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. # -display global size require 'getopts.pl'; my @args = @_; # Set path to lsof. if (($LSOF = &isexec("../lsof")) eq "") { # Some distros use lsof # out of $PATH if (($LSOF = &isexec("lsof")) eq "") { # Then try . and $PATH if (($LSOF = &isexec("../lsof")) eq "") { # Then try .. print "can't execute $LSOF\n"; exit 1 } } } if ($ARGV[0] ne ""){ $cmd="$LSOF -nPl -Fcns -c".$ARGV[0]."|"; }else{ $cmd="$LSOF -nPl -Fcns|"; } #Parse lsof output to gather command, resource name, pid and size #Some extradata stand to keep script genericity $i=0; if (open(FILE, $cmd)){ while (defined ($line=)){ $cline=$line; $cline =~ s"^(.)""; $cline =~ s/^\s+|\s+$//g; if($line=~m/^p/){ $pid=$cline; }else{ if($line=~/^s/){ $size = $cline; }else{ if($line=~/^c/){ $command = $cline; }else{ if($line=~/^n/){ $name = $cline; $data{$i} = { command => $command, name => $name, pid => $pid , size => $size}; $size=0; $i = $i+1; } } } } } } #Resource name sorting sub byresname { $data{$a}{name} cmp $data{$b}{name}} @ks=sort byresname (keys %data); #Resource grouping $i=0; $cname="a"; foreach $k (@ks){ if ($data{$k}{name} ne $cname){ $dgroup{$i} = { name => $data{$k}{name}, size => $data{$k}{size}}; $cname = $data{$k}{name}; $i++; } } #Size sort on resource hash sub bysize { $dgroup{$a}{size} <=> $dgroup{$b}{size} } @ks=sort bysize (keys %dgroup); $gsize=0; printf(" -- KB -- -- Resource --\n", ); foreach $k (@ks){ printf("%10d %s\n", $dgroup{$k}{size}/1024, $dgroup{$k}{name}); $gsize+=$dgroup{$k}{size}; } printf("Total KB : %10d\n", $gsize/1024); ## isexec($path) -- is $path executable # # $path = absolute or relative path to file to test for executabiity. # Paths that begin with neither '/' nor '.' that arent't found as # simple references are also tested with the path prefixes of the # PATH environment variable. sub isexec { my ($path) = @_; my ($i, @P, $PATH); $path =~ s/^\s+|\s+$//g; if ($path eq "") { return(""); } if (($path =~ m#^[\/\.]#)) { if (-x $path) { return($path); } return(""); } $PATH = $ENV{PATH}; @P = split(":", $PATH); for ($i = 0; $i <= $#P; $i++) { if (-x "$P[$i]/$path") { return("$P[$i]/$path"); } } return(""); }