| /* |
| * 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 <sys/socket.h> |
| #include <sys/un.h> |
| |
| |
| /* |
| * 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); |
| } |