1/* 2 * LTunix.c -- Lsof Test UNIX domain socket test 3 * 4 * V. Abell 5 * Purdue University 6 */ 7 8 9/* 10 * Copyright 2002 Purdue Research Foundation, West Lafayette, Indiana 11 * 47907. All rights reserved. 12 * 13 * Written by V. Abell. 14 * 15 * This software is not subject to any license of the American Telephone 16 * and Telegraph Company or the Regents of the University of California. 17 * 18 * Permission is granted to anyone to use this software for any purpose on 19 * any computer system, and to alter it and redistribute it freely, subject 20 * to the following restrictions: 21 * 22 * 1. Neither the authors nor Purdue University are responsible for any 23 * consequences of the use of this software. 24 * 25 * 2. The origin of this software must not be misrepresented, either by 26 * explicit claim or by omission. Credit to the authors and Purdue 27 * University must appear in documentation and sources. 28 * 29 * 3. Altered versions must be plainly marked as such, and must not be 30 * misrepresented as being the original software. 31 * 32 * 4. This notice may not be removed or altered. 33 */ 34 35#ifndef lint 36static char copyright[] = 37"@(#) Copyright 2002 Purdue Research Foundation.\nAll rights reserved.\n"; 38#endif 39 40#include "LsofTest.h" 41#include "lsof_fields.h" 42 43#include <sys/socket.h> 44#include <sys/un.h> 45 46 47/* 48 * Local definitions 49 */ 50 51#if !defined(MAXPATHLEN) 52#define MAXPATHLEN 1024 /* maximum path length */ 53#endif /* !defined(MAXPATHLEN) */ 54 55 56/* 57 * Globals 58 */ 59 60pid_t MyPid = (pid_t)0; /* PID of this process */ 61char *Pn = (char *)NULL; /* program name */ 62int SpFd[2] = {-1,-1}; /* socket pair FDs */ 63char *Path[2] = {(char *)NULL, (char *)NULL}; 64 /* socket pair paths */ 65 66 67/* 68 * Local function prototypes 69 */ 70 71_PROTOTYPE(static void cleanup,(void)); 72_PROTOTYPE(static char *FindUsocks,(void)); 73 74 75/* 76 * Main program 77 */ 78 79int 80main(argc, argv) 81 int argc; /* argument count */ 82 char *argv[]; /* arguments */ 83{ 84 char buf[2048]; /* temporary buffer */ 85 char cwd[MAXPATHLEN + 1]; /* CWD buffer */ 86 char *em; /* error message pointer */ 87 int ti, tj; /* temporary indexes */ 88 struct sockaddr_un ua; /* UNIX socket address */ 89 int xv = 0; /* exit value */ 90/* 91 * Get program name and PID, issue start message, and build space prefix. 92 */ 93 if ((Pn = strrchr(argv[0], '/'))) 94 Pn++; 95 else 96 Pn = argv[0]; 97 MyPid = getpid(); 98 (void) printf("%s ... ", Pn); 99 (void) fflush(stdout); 100 PrtMsg((char *)NULL, Pn); 101/* 102 * Process arguments. 103 */ 104 if (ScanArg(argc, argv, "h", Pn)) 105 xv = 1; 106 if (xv || LTopt_h) { 107 (void) PrtMsg("usage: [-h]", Pn); 108 PrtMsgX(" -h print help (this panel)", Pn, cleanup, xv); 109 } 110/* 111 * See if lsof can be executed and can access kernel memory. 112 */ 113 if ((em = IsLsofExec())) 114 (void) PrtMsgX(em, Pn, cleanup, 1); 115 if ((em = CanRdKmem())) 116 (void) PrtMsgX(em, Pn, cleanup, 1); 117/* 118 * Construct the socket paths. 119 */ 120 121#if defined(USE_GETCWD) 122 if (!getcwd(cwd, sizeof(cwd))) 123#else /* ! defined(USE_GETCWD) */ 124 if (!getwd(cwd)) 125#endif /* defined(USE_GETCWD) */ 126 127 { 128 em = "ERROR!!! can't get CWD"; 129 goto print_errno; 130 } 131 cwd[sizeof(cwd) - 1] = '\0'; 132 if ((strlen(cwd) + strlen("/config.LT#U9223372036854775807") + 1) 133 > sizeof(ua.sun_path)) 134 { 135 strncpy(cwd, "/tmp", sizeof(cwd) - 1); 136 } 137 for (ti = 0; ti < 2; ti++) { 138 (void) snprintf(buf, sizeof(buf) - 1, "%s/config.LT%dU%ld", cwd, ti, 139 (long)MyPid); 140 buf[sizeof(buf) - 1] = '\0'; 141 Path[ti] = MkStrCpy(buf, &tj); 142 (void) unlink(Path[ti]); 143 } 144/* 145 * Get two UNIX domain socket FDs. 146 */ 147 for (ti = 0; ti < 2; ti++) { 148 if ((SpFd[ti] = socket(AF_UNIX, SOCK_STREAM, PF_UNSPEC)) < 0) { 149 em = "socket"; 150 151print_errno_by_ti: 152 153 (void) snprintf(buf, sizeof(buf) - 1, "ERROR!!! %s(%s) failure", 154 em, Path[ti]); 155 buf[sizeof(buf) - 1] = '\0'; 156 em = buf; 157 158print_errno: 159 160 PrtMsg(em, Pn); 161 (void) snprintf(buf, sizeof(buf) - 1, " Errno %d: %s", errno, 162 strerror(errno)); 163 buf[sizeof(buf) - 1] = '\0'; 164 PrtMsgX(buf, Pn, cleanup, 1); 165 } 166 } 167/* 168 * Bind file system names to the sockets. 169 */ 170 for (ti = 0; ti < 2; ti++) { 171 (void) memset((void *)&ua, 0, sizeof(ua)); 172 ua.sun_family = AF_UNIX; 173 (void) strncpy(ua.sun_path, Path[ti], sizeof(ua.sun_path)); 174 ua.sun_path[sizeof(ua.sun_path) - 1] = '\0'; 175 if (bind(SpFd[ti], (struct sockaddr *)&ua, sizeof(ua)) < 0) { 176 em = "bind"; 177 goto print_errno_by_ti; 178 } 179 } 180/* 181 * Look for the open UNIX domain socket files with lsof. 182 */ 183 if ((em = FindUsocks())) 184 (void) PrtMsgX(em, Pn, cleanup, 1); 185/* 186 * Exit successfully. 187 */ 188 (void) PrtMsgX("OK", Pn, cleanup, 0); 189 return(0); 190} 191 192 193/* 194 * cleanup() -- release resources 195 */ 196 197static void 198cleanup() 199{ 200 int ti; 201 202 for (ti = 0; ti < 2; ti++) { 203 if (SpFd[ti] >= 0) { 204 (void) close(SpFd[ti]); 205 SpFd[ti] = -1; 206 } 207 if (Path[ti]) { 208 (void) unlink(Path[ti]); 209 (void) free((void *)Path[ti]); 210 Path[ti] = (char *)NULL; 211 } 212 } 213} 214 215 216/* 217 * FindUsocks() -- find UNIX sockets with lsof 218 */ 219 220static char * 221FindUsocks() 222{ 223 char buf[2048]; /* temporary buffer */ 224 char *cem; /* current error message pointer */ 225 LTfldo_t *cmdp; /* command pointer */ 226 int ff[2]; /* file-found flags */ 227 LTfldo_t *fop; /* field output pointer */ 228 int nf; /* number of fields */ 229 int nl; /* name length */ 230 LTfldo_t *nmp; /* name pointer */ 231 char *opv[5]; /* option vector for ExecLsof() */ 232 char *pem = (char *)NULL; /* previous error message pointer */ 233 pid_t pid; /* PID */ 234 int pids = 0; /* PID found status */ 235 char *tcp; /* temporary character pointer */ 236 int ti, tj; /* temporary integers */ 237 LTfldo_t *typ; /* file type pointer */ 238/* 239 * Build the option vector and start lsof execution. 240 */ 241 ff[0] = ff[1] = ti = 0; 242 opv[ti++] = "-aU"; 243 opv[ti++] = "-p"; 244 (void) snprintf(buf, sizeof(buf) - 1, "%ld", (long)MyPid); 245 buf[sizeof(buf) - 1] = '\0'; 246 opv[ti++] = MkStrCpy(buf, &tj); 247 248#if defined(USE_LSOF_C_OPT) 249 opv[ti++] = "-C"; 250#endif /* defined(USE_LSOF_C_OPT) */ 251 252 opv[ti] = (char *)NULL; 253 if ((cem = ExecLsof(opv))) 254 return(cem); 255/* 256 * Read lsof output. 257 */ 258 while (((ff[0] + ff[1]) < 2) && (fop = RdFrLsof(&nf, &cem))) { 259 if (cem) { 260 if (pem) 261 (void) PrtMsg(pem, Pn); 262 return(cem); 263 } 264 switch (fop->ft) { 265 case LSOF_FID_PID: 266 267 /* 268 * This is a process information line. 269 */ 270 pid = (pid_t)atoi(fop->v); 271 pids = 1; 272 cmdp = (LTfldo_t *)NULL; 273 for (fop++, ti = 1; ti < nf; fop++, ti++) { 274 switch (fop->ft) { 275 case LSOF_FID_CMD: 276 cmdp = fop; 277 break; 278 } 279 } 280 if (!cmdp || (pid != MyPid)) 281 pids = 0; 282 break; 283 case LSOF_FID_FD: 284 285 /* 286 * This is a file descriptor line. Make sure its number matches a 287 * test file descriptor number. 288 */ 289 if (!pids) 290 break; 291 for (ti = 0, tcp = fop->v; *tcp; tcp++) { 292 293 /* 294 * Convert file descriptor to a number. 295 */ 296 if (*tcp == ' ') 297 continue; 298 if (((int)*tcp < (int)'0') || ((int)*tcp > (int)'9')) { 299 ti = -1; 300 break; 301 } 302 ti = (ti * 10) + (int)*tcp - (int)'0'; 303 } 304 for (tj = 0; tj < 2; tj++) { 305 if (ff[tj]) 306 continue; 307 if (SpFd[tj] == ti) 308 break; 309 } 310 if (tj >= 2) 311 break; 312 /* 313 * Scan for name and type. 314 */ 315 nmp = typ = (LTfldo_t *)NULL; 316 for (fop++, ti = 1; ti < nf; fop++, ti++) { 317 switch (fop->ft) { 318 case LSOF_FID_NAME: 319 nmp = fop; 320 break; 321 case LSOF_FID_TYPE: 322 typ = fop; 323 break; 324 } 325 } 326 /* 327 * Check the type of the file. 328 */ 329 if (!typ || strcasecmp(typ->v, "unix")) 330 break; 331 /* 332 * Look for the name. 333 */ 334 if (!nmp) 335 break; 336 nl = strlen(Path[tj]); 337 for (tcp = nmp->v; tcp; tcp = strchr(tcp + 1, '/')) { 338 if (!strncmp(tcp, Path[tj], nl)) { 339 340 /* 341 * Mark a file as found. 342 */ 343 ff[tj] = 1; 344 break; 345 } 346 } 347 } 348 } 349/* 350 * Clean up and return. 351 */ 352 (void) StopLsof(); 353 for (ti = 0; ti < 2; ti++) { 354 if (ff[tj]) 355 continue; 356 (void) snprintf(buf, sizeof(buf) - 1, "ERROR!!! not found: %s", 357 Path[ti]); 358 buf[sizeof(buf) - 1] = '\0'; 359 if (pem) 360 (void) PrtMsg(pem, Pn); 361 pem = MkStrCpy(buf, &tj); 362 } 363 return(pem); 364} 365