/* * Set up the agent if running as a daemon. */ int main(int argc, char **argv) { int sep = __pmPathSeparator(); pmdaInterface desc; _isDSO = 0; __pmSetProgname(argv[0]); __pmGetUsername(&username); snprintf(mypath, sizeof(mypath), "%s%c" "aix" "%c" "help", pmGetConfig("PCP_PMDAS_DIR"), sep, sep); pmdaDaemon(&desc, PMDA_INTERFACE_3, pmProgname, AIX, "aix.log", mypath); pmdaGetOptions(argc, argv, &opts, &desc); if (opts.errors) { pmdaUsageMessage(&opts); exit(1); } if (opts.username) username = opts.username; pmdaOpenLog(&desc); aix_init(&desc); pmdaConnect(&desc); pmdaMain(&desc); exit(0); }
int main(int argc, char **argv) { int c, sep = __pmPathSeparator(); int errflag = 0; char helppath[MAXPATHLEN]; _isDSO = 0; __pmSetProgname(argv[0]); __pmGetUsername(&username); sprintf(helppath, "%s%c" "darwin" "%c" "help", pmGetConfig("PCP_PMDAS_DIR"), sep, sep); pmdaDaemon(&dispatch, PMDA_INTERFACE_3, pmProgname, DARWIN, "darwin.log", helppath); while ((c = pmdaGetOpt(argc, argv, "D:d:i:l:pu:U:6:?", &dispatch, &errflag)) != EOF) { switch(c) { case 'U': username = optarg; break; default: errflag++; } } if (errflag) usage(); pmdaOpenLog(&dispatch); darwin_init(&dispatch); pmdaConnect(&dispatch); pmdaMain(&dispatch); exit(0); }
static void mounts_config_file_check(void) { struct stat statbuf; static int last_error; int sep = __pmPathSeparator(); snprintf(mypath, sizeof(mypath), "%s%c" "mounts" "%c" "mounts.conf", pmGetConfig("PCP_PMDAS_DIR"), sep, sep); if (stat(mypath, &statbuf) == -1) { if (oserror() != last_error) { last_error = oserror(); __pmNotifyErr(LOG_WARNING, "stat failed on %s: %s\n", mypath, pmErrStr(last_error)); } } else { last_error = 0; #if defined(HAVE_ST_MTIME_WITH_E) if (statbuf.st_mtime != file_change.st_mtime) #elif defined(HAVE_ST_MTIME_WITH_SPEC) if (statbuf.st_mtimespec.tv_sec != file_change.st_mtimespec.tv_sec || statbuf.st_mtimespec.tv_nsec != file_change.st_mtimespec.tv_nsec) #else if (statbuf.st_mtim.tv_sec != file_change.st_mtim.tv_sec || statbuf.st_mtim.tv_nsec != file_change.st_mtim.tv_nsec) #endif { mounts_clear_config_info(); mounts_grab_config_info(); file_change = statbuf; } } }
/* * Initialise the agent (both daemon and DSO). */ void __PMDA_INIT_CALL mounts_init(pmdaInterface *dp) { if (isDSO) { int sep = __pmPathSeparator(); snprintf(mypath, sizeof(mypath), "%s%c" "mounts" "%c" "help", pmGetConfig("PCP_PMDAS_DIR"), sep, sep); pmdaDSO(dp, PMDA_INTERFACE_2, "mounts DSO", mypath); } else { __pmSetProcessIdentity(username); } if (dp->status != 0) return; dp->version.two.fetch = mounts_fetch; pmdaSetFetchCallBack(dp, mounts_fetchCallBack); pmdaInit(dp, indomtab, sizeof(indomtab)/sizeof(indomtab[0]), metrictab, sizeof(metrictab)/sizeof(metrictab[0])); /* Let's grab the info right away just to make sure it's there. */ mounts_grab_config_info(); }
/* * Set up the agent if running as a daemon. */ int main(int argc, char **argv) { int c, err = 0; int sep = __pmPathSeparator(); pmdaInterface dispatch; char mypath[MAXPATHLEN]; isDSO = 0; __pmSetProgname(argv[0]); __pmGetUsername(&username); snprintf(mypath, sizeof(mypath), "%s%c" "openbsd" "%c" "help", pmGetConfig("PCP_PMDAS_DIR"), sep, sep); pmdaDaemon(&dispatch, PMDA_INTERFACE_5, pmProgname, OPENBSD, "openbsd.log", mypath); while ((c = pmdaGetOpt(argc, argv, "D:d:i:l:pu:U:6:?", &dispatch, &err)) != EOF) { switch(c) { case 'U': username = optarg; break; default: err++; } } if (err) usage(); pmdaOpenLog(&dispatch); openbsd_init(&dispatch); pmdaConnect(&dispatch); pmdaMain(&dispatch); exit(0); }
int __pmServerCreatePIDFile(const char *spec, int verbose) { char pidpath[MAXPATHLEN]; FILE *pidfile; if (!serviceSpec) __pmServerSetServiceSpec(spec); snprintf(pidpath, sizeof(pidpath), "%s%c%s.pid", pmGetConfig("PCP_RUN_DIR"), __pmPathSeparator(), spec); if ((pidfile = fopen(pidpath, "w")) == NULL) { if (verbose) fprintf(stderr, "Error: cannot open PID file %s\n", pidpath); return -oserror(); } atexit(pidonexit); fprintf(pidfile, "%" FMT_PID, getpid()); #ifdef HAVE_FCHMOD (void)fchmod(fileno(pidfile), S_IRUSR | S_IRGRP | S_IROTH); #else (void)chmod(pidpath, S_IRUSR | S_IRGRP | S_IROTH); #endif fclose(pidfile); return 0; }
/* * Set up agent if running as daemon. */ int main(int argc, char **argv) { int sep = __pmPathSeparator(); pmdaInterface dispatch; isDSO = 0; __pmSetProgname(argv[0]); snprintf(helppath, sizeof(helppath), "%s%c" "papi" "%c" "help", pmGetConfig("PCP_PMDAS_DIR"), sep, sep); pmdaDaemon(&dispatch, PMDA_INTERFACE_6, pmProgname, PAPI, "papi.log", helppath); pmdaGetOptions(argc, argv, &opts, &dispatch); if (opts.errors) { pmdaUsageMessage(&opts); exit(1); } pmdaOpenLog(&dispatch); papi_init(&dispatch); pmdaConnect(&dispatch); pmdaMain(&dispatch); free(ctxtab); free(papi_info); free(values); exit(0); }
void darwin_init(pmdaInterface *dp) { if (_isDSO) { int sep = __pmPathSeparator(); char helppath[MAXPATHLEN]; sprintf(helppath, "%s%c" "darwin" "%c" "help", pmGetConfig("PCP_PMDAS_DIR"), sep, sep); pmdaDSO(dp, PMDA_INTERFACE_3, "darwin DSO", helppath); } else { __pmSetProcessIdentity(username); } if (dp->status != 0) return; dp->version.two.instance = darwin_instance; dp->version.two.fetch = darwin_fetch; pmdaSetFetchCallBack(dp, darwin_fetchCallBack); pmdaSetFlags(dp, PMDA_EXT_FLAG_DIRECT); pmdaInit(dp, indomtab, sizeof(indomtab)/sizeof(indomtab[0]), metrictab, sizeof(metrictab)/sizeof(metrictab[0])); mach_host = mach_host_self(); host_page_size(mach_host, &mach_page_size); mach_page_shift = ffs(mach_page_size) - 1; if (refresh_hertz(&mach_hertz) != 0) mach_hertz = 100; init_network(); }
void etw_init(pmdaInterface *dp, const char *configfile) { char helppath[MAXPATHLEN]; int sep = __pmPathSeparator(); snprintf(helppath, sizeof(helppath), "%s%c" "etw" "%c" "help", pmGetConfig("PCP_PMDAS_DIR"), sep, sep); pmdaDSO(dp, PMDA_INTERFACE_5, "etw DSO", helppath); if (dp->status != 0) return; if (event_table_init() < 0) return; if (event_init() < 0) return; dp->version.four.fetch = etw_fetch; dp->version.four.store = etw_store; dp->version.four.profile = etw_profile; dp->version.four.text = etw_text; pmdaSetFetchCallBack(dp, etw_fetchCallBack); pmdaSetEndContextCallBack(dp, etw_end_contextCallBack); pmdaInit(dp, NULL, 0, metrictab, sizeof(metrictab)/sizeof(metrictab[0])); }
static void pidonexit(void) { char pidpath[MAXPATHLEN]; if (serviceSpec) { snprintf(pidpath, sizeof(pidpath), "%s%c%s.pid", pmGetConfig("PCP_RUN_DIR"), __pmPathSeparator(), serviceSpec); unlink(pidpath); } }
void PmChart::helpManual() { bool ok; QString documents("file://"); QString separator = QString(__pmPathSeparator()); documents.append(pmGetConfig("PCP_HTML_DIR")); documents.append(separator).append("index.html"); ok = QDesktopServices::openUrl(QUrl(documents, QUrl::TolerantMode)); if (!ok) { documents.prepend("Failed to open:\n"); QMessageBox::warning(this, pmProgname, documents); } }
/* * This routine opens the config file and stores the information in the * mounts structure. The mounts structure must be reallocated as * necessary, and also the num_procs structure needs to be reallocated * as we define new mounts. When all of that is done, we fill in the * values in the indomtab structure, those being the number of instances * and the pointer to the mounts structure. */ static void mounts_grab_config_info(void) { FILE *fp; char mount_name[MAXPATHLEN]; char *q; size_t size; int mount_number = 0; int sep = __pmPathSeparator(); snprintf(mypath, sizeof(mypath), "%s%c" "mounts" "%c" "mounts.conf", pmGetConfig("PCP_PMDAS_DIR"), sep, sep); if ((fp = fopen(mypath, "r")) == NULL) { __pmNotifyErr(LOG_ERR, "fopen on %s failed: %s\n", mypath, pmErrStr(-oserror())); if (mounts) { free(mounts); mounts = NULL; mount_number = 0; } goto done; } while (fgets(mount_name, sizeof(mount_name), fp) != NULL) { if (mount_name[0] == '#') continue; /* Remove the newline */ if ((q = strchr(mount_name, '\n')) != NULL) { *q = '\0'; } else { /* This means the line was too long */ __pmNotifyErr(LOG_WARNING, "line %d in the config file too long\n", mount_number+1); } size = (mount_number + 1) * sizeof(pmdaInstid); if ((mounts = realloc(mounts, size)) == NULL) __pmNoMem("process", size, PM_FATAL_ERR); mounts[mount_number].i_name = malloc(strlen(mount_name) + 1); strcpy(mounts[mount_number].i_name, mount_name); mounts[mount_number].i_inst = mount_number; mount_number++; } fclose(fp); done: if (mounts == NULL) __pmNotifyErr(LOG_WARNING, "\"mounts\" instance domain is empty"); indomtab[MOUNTS_INDOM].it_set = mounts; indomtab[MOUNTS_INDOM].it_numinst = mount_number; mount_list = realloc(mount_list, (mount_number)*sizeof(mountinfo)); }
/* * Parse our stomp configuration file, simple format: * host=<hostname> # JMS server machine * port=<port#> # server port number * username=<user> | user=<user> * passcode=<password> | password=<password> * timeout=<seconds> # optional * topic=<JMStopic> # optional */ static void stomp_parse(void) { char config[MAXPATHLEN+1]; FILE *f; int sep = __pmPathSeparator(); if (stompfile) strncat(config, stompfile, sizeof(config)-1); else snprintf(config, sizeof(config), "%s%c" "config" "%c" "pmie" "%c" "stomp", pmGetConfig("PCP_VAR_DIR"), sep, sep, sep); if ((f = fopen(config, "r")) == NULL) { __pmNotifyErr(LOG_ERR, "Cannot open STOMP configuration file %s: %s", config, osstrerror()); exit(1); } while (fgets(buffer, sizeof(buffer), f)) { if (strncmp(buffer, "port=", 5) == 0) port = atoi(isspace_terminate(&buffer[5])); else if (strncmp(buffer, "host=", 5) == 0) hostname = strdup(isspace_terminate(&buffer[5])); else if (strncmp(buffer, "hostname=", 9) == 0) hostname = strdup(isspace_terminate(&buffer[9])); else if (strncmp(buffer, "user="******"username="******"password="******"passcode=", 9) == 0) passcode = strdup(isspace_terminate(&buffer[9])); else if (strncmp(buffer, "timeout=", 8) == 0) /* optional */ timeout = atoi(isspace_terminate(&buffer[8])); else if (strncmp(buffer, "topic=", 6) == 0) /* optional */ topic = strdup(isspace_terminate(&buffer[6])); } fclose(f); if (!hostname) __pmNotifyErr(LOG_ERR, "No host in STOMP config file %s", config); if (port == -1) __pmNotifyErr(LOG_ERR, "No port in STOMP config file %s", config); if (!username) __pmNotifyErr(LOG_ERR, "No username in STOMP config file %s", config); if (!passcode) __pmNotifyErr(LOG_ERR, "No passcode in STOMP config file %s", config); if (port == -1 || !hostname || !username || !passcode) exit(1); }
static void setupEnvironment(void) { char *value; QString confirm = pmGetConfig("PCP_BIN_DIR"); confirm.prepend("PCP_XCONFIRM_PROG="); confirm.append(QChar(__pmPathSeparator())); confirm.append("pmquery"); if ((value = strdup((const char *)confirm.toLatin1())) != NULL) putenv(value); if (getenv("PCP_STDERR") == NULL && // do not overwrite, for QA ((value = strdup("PCP_STDERR=DISPLAY")) != NULL)) putenv(value); QCoreApplication::setOrganizationName("PCP"); QCoreApplication::setApplicationName("pmtime"); }
void HostDialog::nssGuiStart() { QString dbpath = QDir::toNativeSeparators(QDir::homePath()); int sep = __pmPathSeparator(); dbpath.append(sep).append(".pki").append(sep).append("nssdb"); dbpath.prepend("sql:"); // only use sqlite NSS databases QStringList arguments; arguments << "--dbdir"; arguments << dbpath; my.nssGuiProc = new QProcess(this); connect(my.nssGuiProc, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(nssGuiFinished(int, QProcess::ExitStatus))); my.nssGuiProc->start("nss-gui", arguments); }
static char * serverdb(char *path, size_t size, char *db_method) { int sep = __pmPathSeparator(); char *nss_method = getenv("PCP_SECURE_DB_METHOD"); if (nss_method == NULL) nss_method = db_method; /* * Fill in a buffer with the server NSS database specification. * Return a pointer to the filesystem path component - without * the <method>:-prefix - for other routines to work with. */ snprintf(path, size, "%s" "%c" "etc" "%c" "pki" "%c" "nssdb", nss_method, sep, sep, sep); return path + strlen(nss_method); }
void __PMDA_INIT_CALL papi_init(pmdaInterface *dp) { int sts; if (isDSO) { int sep = __pmPathSeparator(); snprintf(helppath, sizeof(helppath), "%s%c" "papi" "%c" "help", pmGetConfig("PCP_PMDAS_DIR"), sep, sep); pmdaDSO(dp, PMDA_INTERFACE_6, "papi DSO", helppath); } if (dp->status != 0) return; dp->comm.flags |= PDU_FLAG_AUTH; if ((sts = papi_internal_init(dp)) < 0) { __pmNotifyErr(LOG_ERR, "papi_internal_init: %s\n", pmErrStr(sts)); dp->status = PM_ERR_GENERIC; return; } if ((sts = papi_setup_auto_af()) < 0) { __pmNotifyErr(LOG_ERR, "papi_setup_auto_af: %s\n", pmErrStr(sts)); dp->status = PM_ERR_GENERIC; return; } dp->version.six.fetch = papi_fetch; dp->version.six.store = papi_store; dp->version.six.attribute = papi_contextAttributeCallBack; dp->version.six.desc = papi_desc; dp->version.any.text = papi_text; dp->version.four.pmid = papi_name_lookup; dp->version.four.children = papi_children; pmdaSetFetchCallBack(dp, papi_fetchCallBack); pmdaSetEndContextCallBack(dp, papi_endContextCallBack); pmdaInit(dp, NULL, 0, NULL, 0); }
/* * Initialise the agent (both daemon and DSO). */ void aix_init(pmdaInterface *dp) { if (_isDSO) { int sep = __pmPathSeparator(); snprintf(mypath, sizeof(mypath), "%s%c" "aix" "%c" "help", pmGetConfig("PCP_PMDAS_DIR"), sep, sep); pmdaDSO(dp, PMDA_INTERFACE_3, "AIX DSO", mypath); } else { __pmSetProcessIdentity(username); } if (dp->status != 0) return; dp->version.two.fetch = aix_fetch; pmdaSetFetchCallBack(dp, aix_fetch_callback); init_data(dp->domain); pmdaInit(dp, indomtab, indomtab_sz, metrictab, metrictab_sz); }
void hotproc_init(void) { char h_configfile[MAXPATHLEN]; FILE *conf; int sep = __pmPathSeparator(); snprintf(h_configfile, sizeof(h_configfile), "%s%c" "proc" "%c" "hotproc.conf", pmGetConfig("PCP_PMDAS_DIR"), sep, sep); conf = open_config(h_configfile); /* Hotproc configured */ if (conf != NULL) { if (read_config(conf)) { conf_gen = 1; } fclose(conf); } }
/* * Initialise the agent (both daemon and DSO). */ void generic_init(pmdaInterface *dp) { if (isDSO) { int sep = __pmPathSeparator(); snprintf(mypath, sizeof(mypath), "%s%c" "generic" "%c" "help", pmGetConfig("PCP_PMDAS_DIR"), sep, sep); pmdaDSO(dp, PMDA_INTERFACE_2, "generic DSO", mypath); } /** else { __pmSetProcessIdentity(username); } */ if (dp->status != 0) return; pmdaSetFetchCallBack(dp, generic_fetchCallBack); pmdaInit(dp, NULL, 0, metrictab, sizeof(metrictab)/sizeof(metrictab[0])); }
/* ** Extract active PCP archive file from latest archive folio, ** use pmcd.hostname by default, unless directed elsewhere. */ void rawfolio(pmOptions *opts) { int sep = __pmPathSeparator(); char path[MAXPATHLEN]; char *logdir; if ((logdir = pmGetOptionalConfig("PCP_LOG_DIR")) == NULL) { fprintf(stderr, "%s: cannot find PCP_LOG_DIR\n", pmProgname); cleanstop(1); } snprintf(path, sizeof(path), "%s%c%s%c%s%c", logdir, sep, "pmlogger", sep, rawlocalhost(opts), sep); if (chdir(path) < 0) { fprintf(stderr, "%s: cannot change to %s: %s\n", pmProgname, path, pmErrStr(-oserror())); cleanstop(1); } __pmAddOptArchiveFolio(opts, "Latest"); }
/* * generate dialog/message when launching application wishes to break * its association with pmlogger * * cmd is one of the following: * D detach pmlogger and let it run forever * Q terminate pmlogger * ? display status * X fatal error or application exit ... user must decide * to detach or quit */ void do_dialog(char cmd) { FILE *msgf = NULL; time_t now; static char lbuf[100+MAXPATHLEN]; double archsize; char *q; char *p = NULL; int nchar; char *msg; #if HAVE_MKSTEMP char tmp[MAXPATHLEN]; #endif time(&now); now -= rsc_start; if (now == 0) /* hack is close enough! */ now = 1; archsize = vol_bytes + ftell(logctl.l_mfp); nchar = add_msg(&p, 0, ""); p[0] = '\0'; snprintf(lbuf, sizeof(lbuf), "PCP recording for the archive folio \"%s\" and the host", folio_name); nchar = add_msg(&p, nchar, lbuf); snprintf(lbuf, sizeof(lbuf), " \"%s\" has been in progress for %ld %s", pmcd_host, now < 240 ? now : now/60, now < 240 ? "seconds" : "minutes"); nchar = add_msg(&p, nchar, lbuf); nchar = add_msg(&p, nchar, " and in that time the pmlogger process has created an"); nchar = add_msg(&p, nchar, " archive of "); q = do_size(archsize); nchar = add_msg(&p, nchar, q); nchar = add_msg(&p, nchar, "."); if (rsc_replay) { nchar = add_msg(&p, nchar, "\n\nThis archive may be replayed with the following command:\n"); snprintf(lbuf, sizeof(lbuf), " $ pmafm %s replay", folio_name); nchar = add_msg(&p, nchar, lbuf); } if (cmd == 'D') { nchar = add_msg(&p, nchar, "\n\nThe application that launched pmlogger has asked pmlogger"); nchar = add_msg(&p, nchar, " to continue independently and the PCP archive will grow at"); nchar = add_msg(&p, nchar, " the rate of "); q = do_size((archsize * 3600) / now); nchar = add_msg(&p, nchar, q); nchar = add_msg(&p, nchar, " per hour or "); q = do_size((archsize * 3600 * 24) / now); nchar = add_msg(&p, nchar, q); nchar = add_msg(&p, nchar, " per day."); } if (cmd == 'X') { nchar = add_msg(&p, nchar, "\n\nThe application that launched pmlogger has exited and you"); nchar = add_msg(&p, nchar, " must decide if the PCP recording session should be terminated"); nchar = add_msg(&p, nchar, " or continued. If recording is continued the PCP archive will"); nchar = add_msg(&p, nchar, " grow at the rate of "); q = do_size((archsize * 3600) / now); nchar = add_msg(&p, nchar, q); nchar = add_msg(&p, nchar, " per hour or "); q = do_size((archsize * 3600 * 24) / now); nchar = add_msg(&p, nchar, q); nchar = add_msg(&p, nchar, " per day."); } if (cmd == 'Q') { nchar = add_msg(&p, nchar, "\n\nThe application that launched pmlogger has terminated"); nchar = add_msg(&p, nchar, " this PCP recording session.\n"); } if (cmd != 'Q') { nchar = add_msg(&p, nchar, "\n\nAt any time this pmlogger process may be terminated with the"); nchar = add_msg(&p, nchar, " following command:\n"); snprintf(lbuf, sizeof(lbuf), " $ pmsignal -s TERM %" FMT_PID "\n", getpid()); nchar = add_msg(&p, nchar, lbuf); } if (cmd == 'X') nchar = add_msg(&p, nchar, "\n\nTerminate this PCP recording session now?"); if (nchar > 0) { char * xconfirm = __pmNativePath(pmGetConfig("PCP_XCONFIRM_PROG")); int fd = -1; #if HAVE_MKSTEMP snprintf(tmp, sizeof(tmp), "%s%cmsgXXXXXX", pmGetConfig("PCP_TMPFILE_DIR"), __pmPathSeparator()); msg = tmp; fd = mkstemp(tmp); #else if ((msg = tmpnam(NULL)) != NULL) fd = open(msg, O_WRONLY|O_CREAT|O_EXCL, 0600); #endif if (fd >= 0) msgf = fdopen(fd, "w"); if (msgf == NULL) { fprintf(stderr, "\nError: failed create temporary message file for recording session dialog\n"); fprintf(stderr, "Reason? %s\n", osstrerror()); if (fd != -1) close(fd); goto failed; } fputs(p, msgf); fclose(msgf); msgf = NULL; if (cmd == 'X') snprintf(lbuf, sizeof(lbuf), "%s -c -header \"%s - %s\" -file %s -icon question " "-B Yes -b No 2>/dev/null", xconfirm, dialog_title, rsc_prog, msg); else snprintf(lbuf, sizeof(lbuf), "%s -c -header \"%s - %s\" -file %s -icon info " "-b Close 2>/dev/null", xconfirm, dialog_title, rsc_prog, msg); if ((msgf = popen(lbuf, "r")) == NULL) { fprintf(stderr, "\nError: failed to start command for recording session dialog\n"); fprintf(stderr, "Command: \"%s\"\n", lbuf); goto failed; } if (fgets(lbuf, sizeof(lbuf), msgf) == NULL) { fprintf(stderr, "\n%s: pmconfirm(1) failed for recording session dialog\n", cmd == '?' ? "Warning" : "Error"); failed: fprintf(stderr, "Dialog:\n"); fputs(p, stderr); strcpy(lbuf, "Yes"); } else { /* strip at first newline */ for (q = lbuf; *q && *q != '\n'; q++) ; *q = '\0'; } if (msgf != NULL) pclose(msgf); unlink(msg); } else { fprintf(stderr, "Error: failed to create recording session dialog message!\n"); fprintf(stderr, "Reason? %s\n", osstrerror()); strcpy(lbuf, "Yes"); } free(p); if (cmd == 'Q' || (cmd == 'X' && strcmp(lbuf, "Yes") == 0)) { run_done(0, "Recording session terminated"); /*NOTREACHED*/ } if (cmd != '?') { /* detach, silently go off to the races ... */ close(rsc_fd); __pmFD_CLR(rsc_fd, &fds); rsc_fd = -1; } }
int main(int argc, char **argv) { static char helppath[MAXPATHLEN]; char *endnum; pmdaInterface desc; long minmem; int c, err = 0, sep = __pmPathSeparator(); minmem = getpagesize(); maxmem = (minmem > DEFAULT_MAXMEM) ? minmem : DEFAULT_MAXMEM; __pmSetProgname(argv[0]); snprintf(helppath, sizeof(helppath), "%s%c" "systemd" "%c" "help", pmGetConfig("PCP_PMDAS_DIR"), sep, sep); pmdaDaemon(&desc, PMDA_INTERFACE_6, pmProgname, SYSTEMD, "systemd.log", helppath); while ((c = pmdaGetOpt(argc, argv, "D:d:l:m:s:U:f?", &desc, &err)) != EOF) { switch (c) { case 'm': maxmem = strtol(optarg, &endnum, 10); if (*endnum != '\0') convertUnits(&endnum, &maxmem); if (*endnum != '\0' || maxmem < minmem) { fprintf(stderr, "%s: invalid max memory '%s' (min=%ld)\n", pmProgname, optarg, minmem); err++; } break; case 's': if (pmParseInterval(optarg, &interval, &endnum) < 0) { fprintf(stderr, "%s: -s requires a time interval: %s\n", pmProgname, endnum); free(endnum); err++; } break; case 'U': username = optarg; break; case 'f': uid_gid_filter_p = 0; break; default: err++; break; } } if (err) usage(); FD_ZERO (&fds); pmdaOpenLog(&desc); /* The systemwide journal may be accessed by the adm user (group); root access is not necessary. */ __pmSetProcessIdentity(username); desc.comm.flags |= PDU_FLAG_AUTH; pmdaConnect(&desc); // After this point, systemd_init is allowed to take some extra time. systemd_init(&desc); // sets some fds systemdMain(&desc); // sets some more fds systemd_shutdown(); exit(0); }
/* 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; }
int main(int argc, char **argv) { int sep = __pmPathSeparator(); int sts; int c; char *p; char pmnsfile[MAXPATHLEN]; char outfname[MAXPATHLEN]; struct stat sbuf; if ((p = getenv("PMNS_DEFAULT")) != NULL) { strncpy(pmnsfile, p, MAXPATHLEN); pmnsfile[MAXPATHLEN-1]= '\0'; } else { snprintf(pmnsfile, sizeof(pmnsfile), "%s%c" "pmns" "%c" "root", pmGetConfig("PCP_VAR_DIR"), sep, sep); } while ((c = pmgetopt_r(argc, argv, &opts)) != EOF) { switch (c) { case 'd': /* duplicate PMIDs are OK */ fprintf(stderr, "%s: Warning: -d deprecated, duplicate PMNS names allowed by default\n", pmProgname); break; case 'D': /* debug flag */ if ((sts = __pmParseDebug(opts.optarg)) < 0) { fprintf(stderr, "%s: unrecognized debug flag specification (%s)\n", pmProgname, opts.optarg); opts.errors++; } else { pmDebug |= sts; } break; case 'n': /* alternative name space file */ strncpy(pmnsfile, opts.optarg, MAXPATHLEN); pmnsfile[MAXPATHLEN-1]= '\0'; break; case '?': default: opts.errors++; break; } } if (opts.errors || opts.optind > argc - 1) { pmUsageMessage(&opts); exit(1); } if ((sts = pmLoadASCIINameSpace(pmnsfile, 1)) < 0) { fprintf(stderr, "%s: Error: pmLoadASCIINameSpace(%s, 1): %s\n", pmProgname, pmnsfile, pmErrStr(sts)); exit(1); } { __pmnsTree *t; t = __pmExportPMNS(); if (t == NULL) { /* sanity check - shouldn't ever happen */ fprintf(stderr, "Exported PMNS is NULL !"); exit(1); } root = t->root; } while (opts.optind < argc) { delpmns(root, fullname = argv[opts.optind]); opts.optind++; } /* * from here on, ignore SIGHUP, SIGINT and SIGTERM to protect * the integrity of the new ouput file */ __pmSetSignalHandler(SIGHUP, SIG_IGN); __pmSetSignalHandler(SIGINT, SIG_IGN); __pmSetSignalHandler(SIGTERM, SIG_IGN); snprintf(outfname, sizeof(outfname), "%s.new", pmnsfile); if ((outf = fopen(outfname, "w")) == NULL) { fprintf(stderr, "%s: Error: cannot open PMNS file \"%s\" for writing: %s\n", pmProgname, outfname, osstrerror()); exit(1); } if (stat(pmnsfile, &sbuf) == 0) { /* * preserve the mode and ownership of any existing PMNS file */ chmod(outfname, sbuf.st_mode & ~S_IFMT); #if defined(HAVE_CHOWN) if (chown(outfname, sbuf.st_uid, sbuf.st_gid) < 0) fprintf(stderr, "%s: chown(%s, ...) failed: %s\n", pmProgname, outfname, osstrerror()); #endif } pmns_output(root, outf); fclose(outf); /* rename the PMNS */ if (rename2(outfname, pmnsfile) == -1) { fprintf(stderr, "%s: cannot rename \"%s\" to \"%s\": %s\n", pmProgname, outfname, pmnsfile, osstrerror()); /* remove the new PMNS */ unlink(outfname); exit(1); } exit(0); }
int __pmConnectLocal(__pmHashCtl *attrs) { int i; __pmDSO *dp; char pathbuf[MAXPATHLEN]; const char *path; #if defined(HAVE_DLOPEN) unsigned int challenge; void (*initp)(pmdaInterface *); #ifdef HAVE_ATEXIT static int atexit_installed = 0; #endif #endif if (numdso == -1) { int sts; sts = build_dsotab(); if (sts < 0) return sts; } for (i = 0; i < numdso; i++) { dp = &dsotab[i]; if (dp->domain == -1 || dp->handle != NULL) continue; /* * __pmLocalPMDA() means the path to the DSO may be something * other than relative to $PCP_PMDAS_DIR ... need to try both * options and also with and without DSO_SUFFIX (so, dll, etc) */ snprintf(pathbuf, sizeof(pathbuf), "%s%c%s", pmGetConfig("PCP_PMDAS_DIR"), __pmPathSeparator(), dp->name); if ((path = __pmFindPMDA(pathbuf)) == NULL) { snprintf(pathbuf, sizeof(pathbuf), "%s%c%s.%s", pmGetConfig("PCP_PMDAS_DIR"), __pmPathSeparator(), dp->name, DSO_SUFFIX); if ((path = __pmFindPMDA(pathbuf)) == NULL) { if ((path = __pmFindPMDA(dp->name)) == NULL) { snprintf(pathbuf, sizeof(pathbuf), "%s.%s", dp->name, DSO_SUFFIX); if ((path = __pmFindPMDA(pathbuf)) == NULL) { pmprintf("__pmConnectLocal: Warning: cannot find DSO at \"%s\" or \"%s\"\n", pathbuf, dp->name); pmflush(); dp->domain = -1; dp->handle = NULL; continue; } } } } #if defined(HAVE_DLOPEN) dp->handle = dlopen(path, RTLD_NOW); if (dp->handle == NULL) { pmprintf("__pmConnectLocal: Warning: error attaching DSO " "\"%s\"\n%s\n\n", path, dlerror()); pmflush(); dp->domain = -1; } #else /* ! HAVE_DLOPEN */ dp->handle = NULL; pmprintf("__pmConnectLocal: Warning: error attaching DSO \"%s\"\n", path); pmprintf("No dynamic DSO/DLL support on this platform\n\n"); pmflush(); dp->domain = -1; #endif if (dp->handle == NULL) continue; #if defined(HAVE_DLOPEN) /* * rest of this only makes sense if the dlopen() worked */ if (dp->init == NULL) initp = NULL; else initp = (void (*)(pmdaInterface *))dlsym(dp->handle, dp->init); if (initp == NULL) { pmprintf("__pmConnectLocal: Warning: couldn't find init function " "\"%s\" in DSO \"%s\"\n", dp->init, path); pmflush(); dlclose(dp->handle); dp->domain = -1; continue; } /* * Pass in the expected domain id. * The PMDA initialization routine can (a) ignore it, (b) check it * is the expected value, or (c) self-adapt. */ dp->dispatch.domain = dp->domain; /* * the PMDA interface / PMAPI version discovery as a "challenge" ... * for pmda_interface it is all the bits being set, * for pmapi_version it is the complement of the one you are using now */ challenge = 0xff; dp->dispatch.comm.pmda_interface = challenge; dp->dispatch.comm.pmapi_version = ~PMAPI_VERSION; dp->dispatch.comm.flags = 0; dp->dispatch.status = 0; (*initp)(&dp->dispatch); if (dp->dispatch.status != 0) { /* initialization failed for some reason */ char errmsg[PM_MAXERRMSGLEN]; pmprintf("__pmConnectLocal: Warning: initialization " "routine \"%s\" failed in DSO \"%s\": %s\n", dp->init, path, pmErrStr_r(dp->dispatch.status, errmsg, sizeof(errmsg))); pmflush(); dlclose(dp->handle); dp->domain = -1; } else { if (dp->dispatch.comm.pmda_interface < PMDA_INTERFACE_2 || dp->dispatch.comm.pmda_interface > PMDA_INTERFACE_LATEST) { pmprintf("__pmConnectLocal: Error: Unknown PMDA interface " "version %d in \"%s\" DSO\n", dp->dispatch.comm.pmda_interface, path); pmflush(); dlclose(dp->handle); dp->domain = -1; } else if (dp->dispatch.comm.pmapi_version != PMAPI_VERSION_2) { pmprintf("__pmConnectLocal: Error: Unknown PMAPI version %d " "in \"%s\" DSO\n", dp->dispatch.comm.pmapi_version, path); pmflush(); dlclose(dp->handle); dp->domain = -1; } else if (dp->dispatch.comm.pmda_interface >= PMDA_INTERFACE_6 && (dp->dispatch.comm.flags & PDU_FLAG_AUTH) != 0) { /* Agent wants to know about connection attributes */ build_dsoattrs(&dp->dispatch, attrs); } } #ifdef HAVE_ATEXIT PM_INIT_LOCKS(); PM_LOCK(__pmLock_libpcp); if (dp->dispatch.comm.pmda_interface >= PMDA_INTERFACE_5 && atexit_installed == 0) { /* install end of local context handler */ atexit(EndLocalContext); atexit_installed = 1; } PM_UNLOCK(__pmLock_libpcp); #endif #endif /* HAVE_DLOPEN */ } return 0; }
int main(int argc, char *argv[]) { int c; int sts; int ctx; int i; int lflag = 0; /* no label by default */ int nfile; int n; char *p; struct dirent **namelist; __pmContext *ctxp; char *archpathname; /* from the command line */ char *archdirname; /* after dirname() */ char archname[MAXPATHLEN]; /* full pathname to base of archive name */ while ((c = pmGetOptions(argc, argv, &opts)) != EOF) { switch (c) { case 'l': /* display the archive label */ lflag = 1; break; case 'v': /* bump verbosity */ vflag++; break; } } if (!opts.errors && opts.optind >= argc) { pmprintf("Error: no archive specified\n\n"); opts.errors++; } if (opts.errors) { pmUsageMessage(&opts); exit(EXIT_FAILURE); } sep = __pmPathSeparator(); setlinebuf(stderr); __pmAddOptArchive(&opts, argv[opts.optind]); opts.flags &= ~PM_OPTFLAG_DONE; __pmEndOptions(&opts); archpathname = argv[opts.optind]; archbasename = strdup(basename(strdup(archpathname))); /* * treat foo, foo.index, foo.meta, foo.NNN as all equivalent * to "foo" */ p = strrchr(archbasename, '.'); if (p != NULL) { if (strcmp(p, ".index") == 0 || strcmp(p, ".meta") == 0) *p = '\0'; else { char *q = p; q++; if (isdigit(*q)) { /* * foo.<digit> ... if archpathname does exist, then * safe to strip digits, else leave as is for the * case of, e.g. archive-20150415.041154 which is the * pmmgr basename for an archive with a first volume * named archive-20150415.041154.0 */ if (access(archpathname, F_OK) == 0) { q++; while (*q && isdigit(*q)) q++; if (*q == '\0') *p = '\0'; } } } } archdirname = dirname(strdup(archpathname)); if (vflag) fprintf(stderr, "Scanning for components of archive \"%s\"\n", archpathname); nfile = scandir(archdirname, &namelist, filter, NULL); if (nfile < 1) { fprintf(stderr, "%s: no PCP archive files match \"%s\"\n", pmProgname, archpathname); exit(EXIT_FAILURE); } /* * Pass 0 for data, metadata and index files ... check physical * archive record structure, then label record */ sts = STS_OK; for (i = 0; i < nfile; i++) { char path[MAXPATHLEN]; if (strcmp(archdirname, ".") == 0) { /* skip ./ prefix */ strncpy(path, namelist[i]->d_name, sizeof(path)); } else { snprintf(path, sizeof(path), "%s%c%s", archdirname, sep, namelist[i]->d_name); } if (pass0(path) == STS_FATAL) /* unrepairable or unrepaired error */ sts = STS_FATAL; } if (meta_state == STATE_MISSING) { fprintf(stderr, "%s%c%s.meta: missing metadata file\n", archdirname, sep, archbasename); sts = STS_FATAL; } if (log_state == STATE_MISSING) { fprintf(stderr, "%s%c%s.0 (or similar): missing log file \n", archdirname, sep, archbasename); sts = STS_FATAL; } if (sts == STS_FATAL) { if (vflag) fprintf(stderr, "Due to earlier errors, cannot continue ... bye\n"); exit(EXIT_FAILURE); } if ((sts = ctx = pmNewContext(PM_CONTEXT_ARCHIVE, archpathname)) < 0) { fprintf(stderr, "%s: cannot open archive \"%s\": %s\n", pmProgname, archpathname, pmErrStr(sts)); fprintf(stderr, "Checking abandoned.\n"); exit(EXIT_FAILURE); } if (pmGetContextOptions(ctx, &opts) < 0) { pmflush(); /* runtime errors only at this stage */ exit(EXIT_FAILURE); } if (lflag) dumpLabel(); /* * Note: ctxp->c_lock remains locked throughout ... __pmHandleToPtr() * is only called once, and a single context is used throughout * ... so there is no PM_UNLOCK(ctxp->c_lock) anywhere in the * pmchecklog code. * This works because ctxp->c_lock is a recursive lock and * pmchecklog is single-threaded. */ if ((n = pmWhichContext()) >= 0) { if ((ctxp = __pmHandleToPtr(n)) == NULL) { fprintf(stderr, "%s: botch: __pmHandleToPtr(%d) returns NULL!\n", pmProgname, n); exit(EXIT_FAILURE); } } else { fprintf(stderr, "%s: botch: %s!\n", pmProgname, pmErrStr(PM_ERR_NOCONTEXT)); exit(EXIT_FAILURE); } if (strcmp(archdirname, ".") == 0) /* skip ./ prefix */ strncpy(archname, archbasename, sizeof(archname) - 1); else snprintf(archname, sizeof(archname), "%s%c%s", archdirname, sep, archbasename); sts = pass1(ctxp, archname); if (index_state == STATE_BAD) { /* prevent subsequent use of bad temporal index */ ctxp->c_archctl->ac_log->l_numti = 0; } sts = pass2(ctxp, archname); sts = pass3(ctxp, archname, &opts); if (vflag) { if (result_count > 0) fprintf(stderr, "Processed %d pmResult records\n", result_count); if (mark_count > 0) fprintf(stderr, "Processed %d <mark> records\n", mark_count); } return 0; }
int main(int argc, char **argv) { static char helppath[MAXPATHLEN]; char *endnum; pmdaInterface desc; long minmem; int c, err = 0, sep = __pmPathSeparator(); __pmSetProgname(argv[0]); __pmGetUsername(&username); minmem = getpagesize(); maxmem = (minmem > DEFAULT_MAXMEM) ? minmem : DEFAULT_MAXMEM; snprintf(helppath, sizeof(helppath), "%s%c" "logger" "%c" "help", pmGetConfig("PCP_PMDAS_DIR"), sep, sep); pmdaDaemon(&desc, PMDA_INTERFACE_5, pmProgname, LOGGER, "logger.log", helppath); while ((c = pmdaGetOpt(argc, argv, "D:d:l:m:s:U:?", &desc, &err)) != EOF) { switch (c) { case 'm': maxmem = strtol(optarg, &endnum, 10); if (*endnum != '\0') convertUnits(&endnum, &maxmem); if (*endnum != '\0' || maxmem < minmem) { fprintf(stderr, "%s: invalid max memory '%s' (min=%ld)\n", pmProgname, optarg, minmem); err++; } break; case 's': if (pmParseInterval(optarg, &interval, &endnum) < 0) { fprintf(stderr, "%s: -s requires a time interval: %s\n", pmProgname, endnum); free(endnum); err++; } break; case 'U': username = optarg; break; default: err++; break; } } if (err || optind != argc -1) usage(); pmdaOpenLog(&desc); logger_init(&desc, argv[optind]); pmdaConnect(&desc); loggerMain(&desc); event_shutdown(); exit(0); }
/* * Determine the hostname associated with the given context. */ char * pmGetContextHostName_r(int ctxid, char *buf, int buflen) { __pmContext *ctxp; char *name; pmID pmid; pmResult *resp; int original; int sts; buf[0] = '\0'; if ((ctxp = __pmHandleToPtr(ctxid)) != NULL) { switch (ctxp->c_type) { case PM_CONTEXT_HOST: /* * Try and establish the hostname from PMCD (possibly remote). * Do not nest the successive actions. That way, if any one of * them fails, we take the default. * Note: we must *temporarily* switch context (see pmUseContext) * in the host case, then switch back afterward. We already hold * locks and have validated the context pointer, so we do a mini * context switch, then switch back. */ if (pmDebug & DBG_TRACE_CONTEXT) fprintf(stderr, "pmGetContextHostName_r context(%d) -> 0\n", ctxid); original = PM_TPD(curcontext); PM_TPD(curcontext) = ctxid; name = "pmcd.hostname"; sts = pmLookupName(1, &name, &pmid); if (sts >= 0) sts = pmFetch(1, &pmid, &resp); if (pmDebug & DBG_TRACE_CONTEXT) fprintf(stderr, "pmGetContextHostName_r reset(%d) -> 0\n", original); PM_TPD(curcontext) = original; if (sts >= 0) { if (resp->vset[0]->numval > 0) { /* pmcd.hostname present */ strncpy(buf, resp->vset[0]->vlist[0].value.pval->vbuf, buflen); pmFreeResult(resp); break; } pmFreeResult(resp); /* FALLTHROUGH */ } /* * We could not get the hostname from PMCD. If the name in the * context structure is a filesystem path (AF_UNIX address) or * 'localhost', then use gethostname(). Otherwise, use the name * from the context structure. */ name = ctxp->c_pmcd->pc_hosts[0].name; if (!name || name[0] == __pmPathSeparator() || /* AF_UNIX */ (strncmp(name, "localhost", 9) == 0)) /* localhost[46] */ gethostname(buf, buflen); else strncpy(buf, name, buflen-1); break; case PM_CONTEXT_LOCAL: gethostname(buf, buflen); break; case PM_CONTEXT_ARCHIVE: strncpy(buf, ctxp->c_archctl->ac_log->l_label.ill_hostname, buflen-1); break; } buf[buflen-1] = '\0'; PM_UNLOCK(ctxp->c_lock); } return buf; }
int main(int argc, char **argv) { int c; int sts; int sep = __pmPathSeparator(); int use_localtime = 0; int isdaemon = 0; char *pmnsfile = PM_NS_DEFAULT; char *username; char *logfile = "pmlogger.log"; /* default log (not archive) file name */ char *endnum; int i; task_t *tp; optcost_t ocp; __pmFdSet readyfds; char *p; char *runtime = NULL; int ctx; /* handle corresponding to ctxp below */ __pmContext *ctxp; /* pmlogger has just this one context */ int niter; pid_t target_pid = 0; __pmGetUsername(&username); /* * Warning: * If any of the pmlogger options change, make sure the * corresponding changes are made to pmnewlog when pmlogger * options are passed through from the control file */ while ((c = pmgetopt_r(argc, argv, &opts)) != EOF) { switch (c) { case 'c': /* config file */ if (access(opts.optarg, F_OK) == 0) configfile = opts.optarg; else { /* does not exist as given, try the standard place */ char *sysconf = pmGetConfig("PCP_VAR_DIR"); int sz = strlen(sysconf)+strlen("/config/pmlogger/")+strlen(opts.optarg)+1; if ((configfile = (char *)malloc(sz)) == NULL) __pmNoMem("config file name", sz, PM_FATAL_ERR); snprintf(configfile, sz, "%s%c" "config%c" "pmlogger%c" "%s", sysconf, sep, sep, sep, opts.optarg); if (access(configfile, F_OK) != 0) { /* still no good, error handling happens below */ free(configfile); configfile = opts.optarg; } } break; case 'D': /* debug flag */ sts = __pmParseDebug(opts.optarg); if (sts < 0) { pmprintf("%s: unrecognized debug flag specification (%s)\n", pmProgname, opts.optarg); opts.errors++; } else pmDebug |= sts; break; case 'h': /* hostname for PMCD to contact */ pmcd_host_conn = opts.optarg; break; case 'l': /* log file name */ logfile = opts.optarg; break; case 'L': /* linger if not primary logger */ linger = 1; break; case 'm': /* note for port map file */ note = opts.optarg; isdaemon = ((strcmp(note, "pmlogger_check") == 0) || (strcmp(note, "pmlogger_daily") == 0)); break; case 'n': /* alternative name space file */ pmnsfile = opts.optarg; break; case 'p': target_pid = (int)strtol(opts.optarg, &endnum, 10); if (*endnum != '\0') { pmprintf("%s: invalid process identifier (%s)\n", pmProgname, opts.optarg); opts.errors++; } else if (!__pmProcessExists(target_pid)) { pmprintf("%s: PID error - no such process (%d)\n", pmProgname, target_pid); opts.errors++; } break; case 'P': /* this is the primary pmlogger */ primary = 1; isdaemon = 1; break; case 'r': /* report sizes of pmResult records */ rflag = 1; break; case 's': /* exit size */ sts = ParseSize(opts.optarg, &exit_samples, &exit_bytes, &exit_time); if (sts < 0) { pmprintf("%s: illegal size argument '%s' for exit size\n", pmProgname, opts.optarg); opts.errors++; } else if (exit_time.tv_sec > 0) { __pmAFregister(&exit_time, NULL, run_done_callback); } break; case 'T': /* end time */ runtime = opts.optarg; break; case 't': /* change default logging interval */ if (pmParseInterval(opts.optarg, &delta, &p) < 0) { pmprintf("%s: illegal -t argument\n%s", pmProgname, p); free(p); opts.errors++; } break; case 'U': /* run as named user */ username = opts.optarg; isdaemon = 1; break; case 'u': /* flush output buffers after each fetch */ /* * all archive write I/O is unbuffered now, so maintain -u * for backwards compatibility only */ break; case 'v': /* volume switch after given size */ sts = ParseSize(opts.optarg, &vol_switch_samples, &vol_switch_bytes, &vol_switch_time); if (sts < 0) { pmprintf("%s: illegal size argument '%s' for volume size\n", pmProgname, opts.optarg); opts.errors++; } else if (vol_switch_time.tv_sec > 0) { vol_switch_afid = __pmAFregister(&vol_switch_time, NULL, vol_switch_callback); } break; case 'V': archive_version = (int)strtol(opts.optarg, &endnum, 10); if (*endnum != '\0' || archive_version != PM_LOG_VERS02) { pmprintf("%s: -V requires a version number of %d\n", pmProgname, PM_LOG_VERS02); opts.errors++; } break; case 'x': /* recording session control fd */ rsc_fd = (int)strtol(opts.optarg, &endnum, 10); if (*endnum != '\0' || rsc_fd < 0) { pmprintf("%s: -x requires a non-negative numeric argument\n", pmProgname); opts.errors++; } else { time(&rsc_start); } break; case 'y': use_localtime = 1; break; case '?': default: opts.errors++; break; } } if (primary && pmcd_host != NULL) { pmprintf( "%s: -P and -h are mutually exclusive; use -P only when running\n" "%s on the same (local) host as the PMCD to which it connects.\n", pmProgname, pmProgname); opts.errors++; } if (!opts.errors && opts.optind != argc - 1) { pmprintf("%s: insufficient arguments\n", pmProgname); opts.errors++; } if (opts.errors) { pmUsageMessage(&opts); exit(1); } if (rsc_fd != -1 && note == NULL) { /* add default note to indicate running with -x */ static char xnote[10]; snprintf(xnote, sizeof(xnote), "-x %d", rsc_fd); note = xnote; } /* if we are running as a daemon, change user early */ if (isdaemon) __pmSetProcessIdentity(username); __pmOpenLog("pmlogger", logfile, stderr, &sts); if (sts != 1) { fprintf(stderr, "%s: Warning: log file (%s) creation failed\n", pmProgname, logfile); /* continue on ... writing to stderr */ } /* base name for archive is here ... */ archBase = argv[opts.optind]; if (pmcd_host_conn == NULL) pmcd_host_conn = "local:"; /* initialise access control */ if (__pmAccAddOp(PM_OP_LOG_ADV) < 0 || __pmAccAddOp(PM_OP_LOG_MAND) < 0 || __pmAccAddOp(PM_OP_LOG_ENQ) < 0) { fprintf(stderr, "%s: access control initialisation failed\n", pmProgname); exit(1); } if (pmnsfile != PM_NS_DEFAULT) { if ((sts = pmLoadASCIINameSpace(pmnsfile, 1)) < 0) { fprintf(stderr, "%s: Cannot load namespace from \"%s\": %s\n", pmProgname, pmnsfile, pmErrStr(sts)); exit(1); } } if ((ctx = pmNewContext(PM_CONTEXT_HOST, pmcd_host_conn)) < 0) { fprintf(stderr, "%s: Cannot connect to PMCD on host \"%s\": %s\n", pmProgname, pmcd_host_conn, pmErrStr(ctx)); exit(1); } pmcd_host = (char *)pmGetContextHostName(ctx); if (strlen(pmcd_host) == 0) { fprintf(stderr, "%s: pmGetContextHostName(%d) failed\n", pmProgname, ctx); exit(1); } if (rsc_fd == -1) { /* no -x, so register client id with pmcd */ __pmSetClientIdArgv(argc, argv); } /* * discover fd for comms channel to PMCD ... */ if ((ctxp = __pmHandleToPtr(ctx)) == NULL) { fprintf(stderr, "%s: botch: __pmHandleToPtr(%d) returns NULL!\n", pmProgname, ctx); exit(1); } pmcdfd = ctxp->c_pmcd->pc_fd; PM_UNLOCK(ctxp->c_lock); if (configfile != NULL) { if ((yyin = fopen(configfile, "r")) == NULL) { fprintf(stderr, "%s: Cannot open config file \"%s\": %s\n", pmProgname, configfile, osstrerror()); exit(1); } } else { /* **ANY** Lex would read from stdin automagically */ configfile = "<stdin>"; } __pmOptFetchGetParams(&ocp); ocp.c_scope = 1; __pmOptFetchPutParams(&ocp); /* prevent early timer events ... */ __pmAFblock(); if (yyparse() != 0) exit(1); if (configfile != NULL) fclose(yyin); yyend(); #ifdef PCP_DEBUG fprintf(stderr, "Config parsed\n"); #endif fprintf(stderr, "Starting %slogger for host \"%s\" via \"%s\"\n", primary ? "primary " : "", pmcd_host, pmcd_host_conn); #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LOG) { fprintf(stderr, "optFetch Cost Parameters: pmid=%d indom=%d fetch=%d scope=%d\n", ocp.c_pmid, ocp.c_indom, ocp.c_fetch, ocp.c_scope); fprintf(stderr, "\nAfter loading config ...\n"); for (tp = tasklist; tp != NULL; tp = tp->t_next) { if (tp->t_numvalid == 0) continue; fprintf(stderr, " state: %sin log, %savail, %s, %s", PMLC_GET_INLOG(tp->t_state) ? "" : "not ", PMLC_GET_AVAIL(tp->t_state) ? "" : "un", PMLC_GET_MAND(tp->t_state) ? "mand" : "adv", PMLC_GET_ON(tp->t_state) ? "on" : "off"); fprintf(stderr, " delta: %ld usec", (long)1000 * tp->t_delta.tv_sec + tp->t_delta.tv_usec); fprintf(stderr, " numpmid: %d\n", tp->t_numpmid); for (i = 0; i < tp->t_numpmid; i++) { fprintf(stderr, " %s (%s):\n", pmIDStr(tp->t_pmidlist[i]), tp->t_namelist[i]); } __pmOptFetchDump(stderr, tp->t_fetch); } } #endif if (!primary && tasklist == NULL && !linger) { fprintf(stderr, "Nothing to log, and not the primary logger instance ... good-bye\n"); exit(1); } if ((sts = __pmLogCreate(pmcd_host, archBase, archive_version, &logctl)) < 0) { fprintf(stderr, "__pmLogCreate: %s\n", pmErrStr(sts)); exit(1); } else { /* * try and establish $TZ from the remote PMCD ... * Note the label record has been set up, but not written yet */ char *name = "pmcd.timezone"; pmID pmid; pmResult *resp; __pmtimevalNow(&epoch); sts = pmUseContext(ctx); if (sts >= 0) sts = pmLookupName(1, &name, &pmid); if (sts >= 0) sts = pmFetch(1, &pmid, &resp); if (sts >= 0) { if (resp->vset[0]->numval > 0) { /* pmcd.timezone present */ strcpy(logctl.l_label.ill_tz, resp->vset[0]->vlist[0].value.pval->vbuf); /* prefer to use remote time to avoid clock drift problems */ epoch = resp->timestamp; /* struct assignment */ if (! use_localtime) pmNewZone(logctl.l_label.ill_tz); } #ifdef PCP_DEBUG else if (pmDebug & DBG_TRACE_LOG) { fprintf(stderr, "main: Could not get timezone from host %s\n", pmcd_host); } #endif pmFreeResult(resp); } } /* do ParseTimeWindow stuff for -T */ if (runtime) { struct timeval res_end; /* time window end */ struct timeval start; struct timeval end; struct timeval last_delta; char *err_msg; /* parsing error message */ time_t now; struct timeval now_tv; time(&now); now_tv.tv_sec = now; now_tv.tv_usec = 0; start = now_tv; end.tv_sec = INT_MAX; end.tv_usec = INT_MAX; sts = __pmParseTime(runtime, &start, &end, &res_end, &err_msg); if (sts < 0) { fprintf(stderr, "%s: illegal -T argument\n%s", pmProgname, err_msg); exit(1); } last_delta = res_end; tsub(&last_delta, &now_tv); __pmAFregister(&last_delta, NULL, run_done_callback); last_stamp = res_end; } fprintf(stderr, "Archive basename: %s\n", archBase); #ifndef IS_MINGW /* detach yourself from the launching process */ if (isdaemon) setpgid(getpid(), 0); #endif /* set up control port */ init_ports(); __pmFD_ZERO(&fds); for (i = 0; i < CFD_NUM; ++i) { if (ctlfds[i] >= 0) __pmFD_SET(ctlfds[i], &fds); } #ifndef IS_MINGW __pmFD_SET(pmcdfd, &fds); #endif if (rsc_fd != -1) __pmFD_SET(rsc_fd, &fds); numfds = maxfd() + 1; if ((sts = do_preamble()) < 0) fprintf(stderr, "Warning: problem writing archive preamble: %s\n", pmErrStr(sts)); sts = 0; /* default exit status */ parse_done = 1; /* enable callback processing */ __pmAFunblock(); for ( ; ; ) { int nready; #ifdef PCP_DEBUG if ((pmDebug & DBG_TRACE_APPL2) && (pmDebug & DBG_TRACE_DESPERATE)) { fprintf(stderr, "before __pmSelectRead(%d,...): run_done_alarm=%d vol_switch_alarm=%d log_alarm=%d\n", numfds, run_done_alarm, vol_switch_alarm, log_alarm); } #endif niter = 0; while (log_alarm && niter++ < 10) { __pmAFblock(); log_alarm = 0; #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_APPL2) fprintf(stderr, "delayed callback: log_alarm\n"); #endif for (tp = tasklist; tp != NULL; tp = tp->t_next) { if (tp->t_alarm) { tp->t_alarm = 0; do_work(tp); } } __pmAFunblock(); } if (vol_switch_alarm) { __pmAFblock(); vol_switch_alarm = 0; #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_APPL2) fprintf(stderr, "delayed callback: vol_switch_alarm\n"); #endif newvolume(VOL_SW_TIME); __pmAFunblock(); } if (run_done_alarm) { #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_APPL2) fprintf(stderr, "delayed callback: run_done_alarm\n"); #endif run_done(0, NULL); /*NOTREACHED*/ } __pmFD_COPY(&readyfds, &fds); nready = __pmSelectRead(numfds, &readyfds, NULL); #ifdef PCP_DEBUG if ((pmDebug & DBG_TRACE_APPL2) && (pmDebug & DBG_TRACE_DESPERATE)) { fprintf(stderr, "__pmSelectRead(%d,...) done: nready=%d run_done_alarm=%d vol_switch_alarm=%d log_alarm=%d\n", numfds, nready, run_done_alarm, vol_switch_alarm, log_alarm); } #endif __pmAFblock(); if (nready > 0) { /* handle request on control port */ for (i = 0; i < CFD_NUM; ++i) { if (ctlfds[i] >= 0 && __pmFD_ISSET(ctlfds[i], &readyfds)) { if (control_req(ctlfds[i])) { /* new client has connected */ __pmFD_SET(clientfd, &fds); if (clientfd >= numfds) numfds = clientfd + 1; } } } if (clientfd >= 0 && __pmFD_ISSET(clientfd, &readyfds)) { /* process request from client, save clientfd in case client * closes connection, resetting clientfd to -1 */ int fd = clientfd; if (client_req()) { /* client closed connection */ __pmFD_CLR(fd, &fds); __pmCloseSocket(clientfd); clientfd = -1; numfds = maxfd() + 1; qa_case = 0; } } #ifndef IS_MINGW if (pmcdfd >= 0 && __pmFD_ISSET(pmcdfd, &readyfds)) { /* * do not expect this, given synchronous commumication with the * pmcd ... either pmcd has terminated, or bogus PDU ... or its * Win32 and we are operating under the different conditions of * our AF.c implementation there, which has to deal with a lack * of signal support on Windows - race condition exists between * this check and the async event timer callback. */ __pmPDU *pb; __pmPDUHdr *php; sts = __pmGetPDU(pmcdfd, ANY_SIZE, TIMEOUT_NEVER, &pb); if (sts <= 0) { if (sts < 0) fprintf(stderr, "Error: __pmGetPDU: %s\n", pmErrStr(sts)); disconnect(sts); } else { php = (__pmPDUHdr *)pb; fprintf(stderr, "Error: Unsolicited %s PDU from PMCD\n", __pmPDUTypeStr(php->type)); disconnect(PM_ERR_IPC); } if (sts > 0) __pmUnpinPDUBuf(pb); } #endif if (rsc_fd >= 0 && __pmFD_ISSET(rsc_fd, &readyfds)) { /* * some action on the recording session control fd * end-of-file means launcher has quit, otherwise we * expect one of these commands * V<number>\n - version * F<folio>\n - folio name * P<name>\n - launcher's name * R\n - launcher can replay * D\n - detach from launcher * Q\n - quit pmlogger */ char rsc_buf[MAXPATHLEN]; char *rp = rsc_buf; char myc; int fake_x = 0; for (rp = rsc_buf; ; rp++) { if (read(rsc_fd, &myc, 1) <= 0) { #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_APPL2) fprintf(stderr, "recording session control: eof\n"); #endif if (rp != rsc_buf) { *rp = '\0'; fprintf(stderr, "Error: incomplete recording session control message: \"%s\"\n", rsc_buf); } fake_x = 1; break; } if (rp >= &rsc_buf[MAXPATHLEN]) { fprintf(stderr, "Error: absurd recording session control message: \"%100.100s ...\"\n", rsc_buf); fake_x = 1; break; } if (myc == '\n') { *rp = '\0'; break; } *rp = myc; } #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_APPL2) { if (fake_x == 0) fprintf(stderr, "recording session control: \"%s\"\n", rsc_buf); } #endif if (fake_x) do_dialog('X'); else if (strcmp(rsc_buf, "Q") == 0 || strcmp(rsc_buf, "D") == 0 || strcmp(rsc_buf, "?") == 0) do_dialog(rsc_buf[0]); else if (rsc_buf[0] == 'F') folio_name = strdup(&rsc_buf[1]); else if (rsc_buf[0] == 'P') rsc_prog = strdup(&rsc_buf[1]); else if (strcmp(rsc_buf, "R") == 0) rsc_replay = 1; else if (rsc_buf[0] == 'V' && rsc_buf[1] == '0') { /* * version 0 of the recording session control ... * this is all we grok at the moment */ ; } else { fprintf(stderr, "Error: illegal recording session control message: \"%s\"\n", rsc_buf); do_dialog('X'); } } } else if (vol_switch_flag) { newvolume(VOL_SW_SIGHUP); vol_switch_flag = 0; } else if (nready < 0 && neterror() != EINTR) fprintf(stderr, "Error: select: %s\n", netstrerror()); __pmAFunblock(); if (target_pid && !__pmProcessExists(target_pid)) exit(EXIT_SUCCESS); if (exit_code) break; } exit(exit_code); }