Beispiel #1
0
Datei: aix.c Projekt: Aconex/pcp
/*
 * 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);
}
Beispiel #2
0
Datei: pmda.c Projekt: Aconex/pcp
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);
}
Beispiel #3
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;
        }
    }
}
Beispiel #4
0
/*
 * 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();
}
Beispiel #5
0
/*
 * 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);
}
Beispiel #6
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;
}
Beispiel #7
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);
}
Beispiel #8
0
Datei: pmda.c Projekt: Aconex/pcp
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();
}
Beispiel #9
0
Datei: pmda.c Projekt: Aconex/pcp
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]));
}
Beispiel #10
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);
    }
}
Beispiel #11
0
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);
    }
}
Beispiel #12
0
/*
 * 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));
}
Beispiel #13
0
/*
 * 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);
}
Beispiel #14
0
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");
}
Beispiel #15
0
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);
}
Beispiel #16
0
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);
}
Beispiel #17
0
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);
}
Beispiel #18
0
Datei: aix.c Projekt: Aconex/pcp
/*
 * 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);
}
Beispiel #19
0
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);
    }
}
Beispiel #20
0
/*
 * 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]));
}
Beispiel #21
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");
}
Beispiel #22
0
/*
 * 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;
    }
}
Beispiel #23
0
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);
}
Beispiel #24
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;
}
Beispiel #25
0
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);
}
Beispiel #26
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;
}
Beispiel #27
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;
}
Beispiel #28
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);
}
Beispiel #29
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;
}
Beispiel #30
0
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);
}