summaryrefslogtreecommitdiff
path: root/tests/LTbasic.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/LTbasic.c')
-rw-r--r--tests/LTbasic.c445
1 files changed, 445 insertions, 0 deletions
diff --git a/tests/LTbasic.c b/tests/LTbasic.c
new file mode 100644
index 0000000..ce04705
--- /dev/null
+++ b/tests/LTbasic.c
@@ -0,0 +1,445 @@
+/*
+ * 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);
+}