summaryrefslogtreecommitdiff
path: root/tests/LTsock.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/LTsock.c')
-rw-r--r--tests/LTsock.c886
1 files changed, 886 insertions, 0 deletions
diff --git a/tests/LTsock.c b/tests/LTsock.c
new file mode 100644
index 0000000..bc0750f
--- /dev/null
+++ b/tests/LTsock.c
@@ -0,0 +1,886 @@
+/*
+ * 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 <netdb.h>
+#include <signal.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+
+/*
+ * Pre-definitions that make be changed or revoked by dialects
+ */
+
+#define SIGHANDLER_T void /* signal handler function type */
+#define LT_SOCKLEN_T int /* socket length type */
+
+
+#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_freebsd)
+/*
+ * FreeBSD-specific items
+ */
+#undef LT_SOCKLEN_T
+#define LT_SOCKLEN_T socklen_t
+#endif /* defined(LT_DIAL_freebsd) */
+
+
+#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);
+}