/* * Connect to the pmdaroot socket as a client, perform version exchange */ int pmdaRootConnect(const char *path) { __pmSockAddr *addr; char *tmpdir; char socketpath[MAXPATHLEN]; char errmsg[PM_MAXERRMSGLEN]; int fd, sts, version, features; /* Initialize the socket address. */ if ((addr = __pmSockAddrAlloc()) == NULL) return -ENOMEM; if (path == NULL) { if ((tmpdir = pmGetOptionalConfig("PCP_TMP_DIR")) == NULL) { __pmSockAddrFree(addr); return PM_ERR_GENERIC; } snprintf(socketpath, sizeof(socketpath), "%s/pmcd/root.socket", tmpdir); } else strncpy(socketpath, path, sizeof(socketpath)); socketpath[sizeof(socketpath)-1] = '\0'; __pmSockAddrSetFamily(addr, AF_UNIX); __pmSockAddrSetPath(addr, socketpath); /* Create client socket connection */ if ((fd = __pmCreateUnixSocket()) < 0) { __pmNotifyErr(LOG_ERR, "pmdaRootConnect: cannot create socket %s: %s\n", socketpath, osstrerror_r(errmsg, sizeof(errmsg))); __pmSockAddrFree(addr); return fd; } sts = __pmConnect(fd, addr, -1); __pmSockAddrFree(addr); if (sts < 0) { if (sts != -EPERM || (pmDebug & DBG_TRACE_LIBPMDA)) __pmNotifyErr(LOG_INFO, "pmdaRootConnect: cannot connect to %s: %s\n", socketpath, osstrerror_r(errmsg, sizeof(errmsg))); __pmCloseSocket(fd); return sts; } /* Check server connection information */ if ((sts = __pmdaRecvRootPDUInfo(fd, &version, &features)) < 0) { __pmNotifyErr(LOG_ERR, "pmdaRootConnect: cannot verify %s server: %s\n", socketpath, pmErrStr_r(sts, errmsg, sizeof(errmsg))); __pmCloseSocket(fd); return sts; } if (pmDebug & DBG_TRACE_LIBPMDA) __pmNotifyErr(LOG_INFO, "pmdaRootConnect: %s server fd=%d version=%d features=0x%x\n", socketpath, fd, version, features); return fd; }
void __pmServerCloseRequestPorts(void) { int i, fd; for (i = 0; i < nReqPorts; i++) { /* No longer advertise our presence on the network. */ if (reqPorts[i].presence != NULL) __pmServerUnadvertisePresence(reqPorts[i].presence); if ((fd = reqPorts[i].fds[INET_FD]) >= 0) __pmCloseSocket(fd); if ((fd = reqPorts[i].fds[IPV6_FD]) >= 0) __pmCloseSocket(fd); } #if defined(HAVE_STRUCT_SOCKADDR_UN) if (localSocketFd >= 0) { __pmCloseSocket(localSocketFd); localSocketFd = -EPROTO; /* We must remove the socket file. */ if (unlink(localSocketPath) != 0 && oserror() != ENOENT) { char errmsg[PM_MAXERRMSGLEN]; __pmNotifyErr(LOG_ERR, "%s: can't unlink %s (uid=%d,euid=%d): %s", pmProgname, localSocketPath, getuid(), geteuid(), osstrerror_r(errmsg, sizeof(errmsg))); } } #endif }
void __pmConfig(__pmConfigCallback formatter) { /* * Scan ${PCP_CONF-$PCP_DIR/etc/pcp.conf} and put all PCP config * variables found therein into the environment. */ FILE *fp; char confpath[32]; char dir[MAXPATHLEN]; char var[MAXPATHLEN]; char *prefix; char *conf; char *val; char *p; PM_INIT_LOCKS(); PM_LOCK(__pmLock_libpcp); prefix = getenv("PCP_DIR"); if ((conf = getenv("PCP_CONF")) == NULL) { strncpy(confpath, "/etc/pcp.conf", sizeof(confpath)); if (prefix == NULL) conf = __pmNativePath(confpath); else { snprintf(dir, sizeof(dir), "%s%s", prefix, __pmNativePath(confpath)); conf = dir; } } if (access((const char *)conf, R_OK) < 0 || (fp = fopen(conf, "r")) == (FILE *)NULL) { char errmsg[PM_MAXERRMSGLEN]; pmprintf("FATAL PCP ERROR: could not open config file \"%s\" : %s\n", conf, osstrerror_r(errmsg, sizeof(errmsg))); pmprintf("You may need to set PCP_CONF or PCP_DIR in your environment.\n"); pmflush(); PM_UNLOCK(__pmLock_libpcp); exit(1); } while (fgets(var, sizeof(var), fp) != NULL) { if (var[0] == '#' || (p = strchr(var, '=')) == NULL) continue; *p = '\0'; val = p+1; if ((p = strrchr(val, '\n')) != NULL) *p = '\0'; if ((p = getenv(var)) != NULL) val = p; else formatter(var, prefix, val); if (pmDebug & DBG_TRACE_CONFIG) fprintf(stderr, "pmGetConfig: (init) %s=%s\n", var, val); } fclose(fp); PM_UNLOCK(__pmLock_libpcp); }
static int http_client_connectunix(const char *path, struct timeval *timeout) { #if defined(HAVE_STRUCT_SOCKADDR_UN) __pmFdSet wfds; __pmSockAddr *myAddr; struct timeval stv, *ptv; int fdFlags = 0; int fd = -1; int sts; int rc; /* Initialize the socket address. */ if ((myAddr = __pmSockAddrAlloc()) == NULL) { if (pmDebug & DBG_TRACE_HTTP) fprintf(stderr, "HTTP connect unix(%s): out of memory\n", path); return -ENOMEM; } __pmSockAddrSetFamily(myAddr, AF_UNIX); __pmSockAddrSetPath(myAddr, path); if ((fd = __pmCreateUnixSocket()) < 0) { if (pmDebug & DBG_TRACE_HTTP) { char errmsg[PM_MAXERRMSGLEN]; fprintf(stderr, "HTTP connect unix(%s) unable to create socket: %s\n", path, osstrerror_r(errmsg, sizeof(errmsg))); } __pmSockAddrFree(myAddr); return fd; } /* Attempt to connect */ fdFlags = __pmConnectTo(fd, myAddr, -1); __pmSockAddrFree(myAddr); if (fdFlags < 0) { __pmCloseSocket(fd); return -ECONNREFUSED; } /* FNDELAY and we're in progress - wait on select */ stv = *timeout; ptv = (stv.tv_sec || stv.tv_usec) ? &stv : NULL; __pmFD_ZERO(&wfds); __pmFD_SET(fd, &wfds); sts = 0; if ((rc = __pmSelectWrite(fd+1, &wfds, ptv)) == 1) sts = __pmConnectCheckError(fd); else if (rc == 0) sts = ETIMEDOUT; else sts = (rc < 0) ? neterror() : EINVAL; if (sts != 0) { /* Unsuccessful connection. */ if (sts == ENOENT) sts = ECONNREFUSED; __pmCloseSocket(fd); fd = -sts; } if (fd < 0) return fd; /* * If we're here, it means we have a valid connection; restore the * flags and make sure this file descriptor is closed if exec() is * called */ return __pmConnectRestoreFlags(fd, fdFlags); #else if (pmDebug & DBG_TRACE_HTTP) __pmNotifyErr(LOG_ERR, "HTTP connect unix(%s) not supported\n", path); return -EOPNOTSUPP; #endif }
/* Return (in result) a list of active pmlogger ports on the local machine. * The return value of the function is the number of elements in the array. * The caller must NOT free any part of the result stucture, it's storage is * managed here. Subsequent calls will overwrite the data so the caller should * copy it if persistence is required. */ int __pmLogFindLocalPorts(int pid, __pmLogPort **result) { char dir[MAXPATHLEN]; int lendir; int i, j, n; int nf; /* number of port files found */ struct dirent **files = NULL; /* array of port file dirents */ char *p; int len; char namebuf[MAXPATHLEN]; int (*scanfn)(const_dirent *dep); FILE *pfile; char buf[MAXPATHLEN]; if (PM_MULTIPLE_THREADS(PM_SCOPE_LOGPORT)) return PM_ERR_THREAD; if (result == NULL) return -EINVAL; if ((p = pmGetOptionalConfig("PCP_TMP_DIR")) == NULL) return PM_ERR_GENERIC; lendir = snprintf(dir, sizeof(dir), "%s%cpmlogger", p, __pmPathSeparator()); /* Set up the appropriate function to select files from the control port * directory. Anticipate that this will usually be an exact match for * the primary logger control port. */ scanfn = is_match; switch (pid) { case PM_LOG_PRIMARY_PID: /* primary logger control (single) */ strcpy(match, "primary"); break; case PM_LOG_ALL_PIDS: /* find all ports */ scanfn = is_portfile; break; default: /* a specific pid (single) */ if (!__pmProcessExists((pid_t)pid)) { #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LOG) { fprintf(stderr, "__pmLogFindLocalPorts() -> 0, " "pid(%d) doesn't exist\n", pid); } #endif *result = NULL; return 0; } snprintf(match, sizeof(match), "%d", pid); break; } nf = scandir(dir, &files, scanfn, alphasort); #ifdef PCP_DEBUG if (nf < 1 && (pmDebug & DBG_TRACE_LOG)) { fprintf(stderr, "__pmLogFindLocalPorts: scandir() -> %d %s\n", nf, pmErrStr(oserror())); } #endif if (nf == -1 && oserror() == ENOENT) nf = 0; else if (nf == -1) { char errmsg[PM_MAXERRMSGLEN]; pmprintf("__pmLogFindLocalPorts: scandir: %s\n", osstrerror_r(errmsg, sizeof(errmsg))); pmflush(); return -oserror(); } if (resize_logports(nf) < 0) { for (i=0; i < nf; i++) free(files[i]); free(files); return -oserror(); } if (nf == 0) { #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LOG) { fprintf(stderr, "__pmLogFindLocalPorts() -> 0, " "num files = 0\n"); } #endif *result = NULL; free(files); return 0; } /* make a buffer for the longest complete pathname found */ len = (int)strlen(files[0]->d_name); for (i = 1; i < nf; i++) if ((j = (int)strlen(files[i]->d_name)) > len) len = j; /* +1 for trailing path separator, +1 for null termination */ len += lendir + 2; /* namebuf is the complete pathname, p points to the trailing filename * within namebuf. */ strcpy(namebuf, dir); p = namebuf + lendir; *p++ = __pmPathSeparator(); /* open the file, try to read the port number and add the port to the * logport array if successful. */ for (i = 0; i < nf; i++) { char *fname = files[i]->d_name; int err = 0; __pmLogPort *lpp = &logport[nlogports]; strcpy(p, fname); if ((pfile = fopen(namebuf, "r")) == NULL) { char errmsg[PM_MAXERRMSGLEN]; pmprintf("__pmLogFindLocalPorts: pmlogger port file %s: %s\n", namebuf, osstrerror_r(errmsg, sizeof(errmsg))); free(files[i]); pmflush(); continue; } if (!err && fgets(buf, MAXPATHLEN, pfile) == NULL) { if (feof(pfile)) { clearerr(pfile); pmprintf("__pmLogFindLocalPorts: pmlogger port file %s empty!\n", namebuf); } else { char errmsg[PM_MAXERRMSGLEN]; pmprintf("__pmLogFindLocalPorts: pmlogger port file %s: %s\n", namebuf, osstrerror_r(errmsg, sizeof(errmsg))); } err = 1; } else { char *endp; lpp->port = (int)strtol(buf, &endp, 10); if (*endp != '\n') { pmprintf("__pmLogFindLocalPorts: pmlogger port file %s: no port number\n", namebuf); err = 1; } else { lpp->pid = (int)strtol(fname, &endp, 10); if (*endp != '\0') { if (strcmp(fname, "primary") == 0) lpp->pid = PM_LOG_PRIMARY_PORT; else { pmprintf("__pmLogFindLocalPorts: unrecognised pmlogger port file %s\n", namebuf); err = 1; } } } } if (err) { pmflush(); fclose(pfile); } else { if (fgets(buf, MAXPATHLEN, pfile) == NULL) { pmprintf("__pmLogFindLocalPorts: pmlogger port file %s: no PMCD host name\n", namebuf); pmflush(); } else { char *q = strchr(buf, '\n'); if (q != NULL) *q = '\0'; lpp->pmcd_host = strdup(buf); if (fgets(buf, MAXPATHLEN, pfile) == NULL) { pmprintf("__pmLogFindLocalPorts: pmlogger port file %s: no archive base pathname\n", namebuf); pmflush(); } else { char *q = strchr(buf, '\n'); if (q != NULL) *q = '\0'; lpp->archive = strdup(buf); } } fclose(pfile); if ((lpp->name = strdup(fname)) != NULL) nlogports++; else { if (lpp->pmcd_host != NULL) { free(lpp->pmcd_host); lpp->pmcd_host = NULL; } if (lpp->archive != NULL) { free(lpp->archive); lpp->archive = NULL; } break; } } free(files[i]); } if (i == nf) { /* all went well */ n = nlogports; *result = logport; } else { /* strdup error on fname, clean up */ *result = NULL; for (j = i; j < nf; j++) free(files[j]); n = -oserror(); } free(files); return n; }