Exemplo n.º 1
0
/*
 * Hostname extracted and cached for later use during protocol negotiations
 */
static void
GetProxyHostname(void)
{
    __pmHostEnt	*hep;
    char        host[MAXHOSTNAMELEN];

    if (gethostname(host, MAXHOSTNAMELEN) < 0) {
        __pmNotifyErr(LOG_ERR, "%s: gethostname failure\n", pmProgname);
        DontStart();
    }
    host[MAXHOSTNAMELEN-1] = '\0';

    hep = __pmGetAddrInfo(host);
    if (hep == NULL) {
        __pmNotifyErr(LOG_ERR, "%s: __pmGetAddrInfo failure\n", pmProgname);
        DontStart();
    } else {
        hostname = __pmHostEntGetName(hep);
        if (!hostname) {	/* no reverse DNS lookup for local hostname */
            hostname = strdup(host);
            if (!hostname)	/* out of memory, we're having a bad day!?! */
                __pmNoMem("PMPROXY.hostname", strlen(host), PM_FATAL_ERR);
        }
        __pmHostEntFree(hep);
    }
}
Exemplo n.º 2
0
/*
 * Return 1 if hostname corresponds to the current host, 0 if not and < 0 for
 * an error.
 */
int
__pmIsLocalhost(const char *hostname)
{
    int sts = 0;

    if (strcasecmp(hostname, "localhost") == 0 ||
	strncmp(hostname, "local:", 6) == 0 ||
	strncmp(hostname, "unix:", 5) == 0)
	return 1;
    else {
	char lhost[MAXHOSTNAMELEN+1];
	__pmHostEnt *servInfo1;

	if (gethostname(lhost, MAXHOSTNAMELEN) < 0)
	   return -oserror();

	if ((servInfo1 = __pmGetAddrInfo(lhost)) != NULL) {
	    __pmHostEnt		*servInfo2;
	    __pmSockAddr	*addr1, *addr2;
	    void		*enumIx1, *enumIx2;

	    if ((servInfo2 = __pmGetAddrInfo(hostname)) == NULL) {
		__pmHostEntFree(servInfo1);
		return -EHOSTUNREACH;
	    }
	    enumIx1 = NULL;
	    for (addr1 = __pmHostEntGetSockAddr(servInfo1, &enumIx1);
		 addr1 != NULL;
		 addr1 = __pmHostEntGetSockAddr(servInfo1, &enumIx1)) {
		enumIx2 = NULL;
		for (addr2 = __pmHostEntGetSockAddr(servInfo2, &enumIx2);
		     addr2 != NULL;
		     addr2 = __pmHostEntGetSockAddr(servInfo2, &enumIx2)) {
		    if (__pmSockAddrCompare(addr1, addr2) == 0) {
			__pmHostEntFree(servInfo1);
			__pmHostEntFree(servInfo2);
			return 1;
		    }
		}
	    }
	    __pmHostEntFree(servInfo1);
	    __pmHostEntFree(servInfo2);
	}
    }

    return sts;
}
Exemplo n.º 3
0
	/*
	 * Opens a TCP socket and returns the descriptor
	 * Returns:
	 *	socket descriptor, or
	 *	-1 on error
	 */
int makeSocket(const char *host)
	{
	int sock;										/* Socket descriptor */
	int ret;
	int port;
	char *p;
	__pmFdSet wfds;
	struct timeval tv;
	struct timeval	*ptv;
	__pmSockAddr *myaddr;
	__pmHostEnt *servInfo;
	void *enumIx;
	int flags = 0;
	
	/* Check for port number specified in URL */
	p = strchr(host, ':');
	if(p)
	    {
		port = atoi(p + 1);
		*p = '\0';
	    }
	else
	    port = PORT_NUMBER;

	servInfo = __pmGetAddrInfo(host);
	if(servInfo == NULL) { errorSource = H_ERRNO; return -1; }

	sock = -1;
	enumIx = NULL;
	for (myaddr = __pmHostEntGetSockAddr(servInfo, &enumIx);
	     myaddr != NULL;
	     myaddr = __pmHostEntGetSockAddr(servInfo, &enumIx)) {
	    /* Create a socket */
	    if (__pmSockAddrIsInet(myaddr))
		sock = __pmCreateSocket();
	    else if (__pmSockAddrIsIPv6(myaddr))
		sock = __pmCreateIPv6Socket();
	    else
		sock = -1;

	    if (sock < 0) {
		__pmSockAddrFree(myaddr);
		continue; /* Try the next address */
	    }

	    /* Attempt to connect */
	    flags = __pmConnectTo(sock, myaddr, port);
	    __pmSockAddrFree(myaddr);

	    if (flags < 0) {
		/*
		 * Mark failure in case we fall out the end of the loop
		 * and try next address. sock has been closed in __pmConnectTo().
		 */
		sock = -1;
		continue;
	    }

	    /* FNDELAY and we're in progress - wait on select */
	    tv.tv_sec = timeout;
	    tv.tv_usec = 0;
	    ptv = (tv.tv_sec || tv.tv_usec) ? &tv : NULL;
	    __pmFD_ZERO(&wfds);
	    __pmFD_SET(sock, &wfds);
	    ret = __pmSelectWrite(sock+1, &wfds, ptv);

	    /* Was the connection successful? */
	    if (ret < 0) {
		if (oserror() == EINTR)
		    return _makeSocketErr(sock, FETCHER_ERROR, HF_CONNECTTIMEOUT);
		return _makeSocketErr(sock, ERRNO, 0);
	    }
	    ret = __pmConnectCheckError(sock);
	    if (ret == 0)
		break;

	    /* Unsuccessful connection. */
	    __pmCloseSocket(sock);
	    sock = -1;
	} /* loop over addresses */

	__pmHostEntFree(servInfo);

	if(sock == -1) { errorSource = ERRNO; return -1; }

	sock = __pmConnectRestoreFlags(sock, flags);
	if(sock < 0) { errorSource = ERRNO; return -1; }

	return sock;
	}
Exemplo n.º 4
0
static int
http_client_connectto(const char *host, int port, struct timeval *timeout)
{
    struct timeval	stv, *ptv;
    __pmHostEnt		*servInfo;
    __pmSockAddr	*myAddr;
    __pmFdSet		readyFds, allFds;
    void		*enumIx;
    int			fdFlags[FD_SETSIZE];
    int			i, fd, sts, maxFd;

    if ((servInfo = __pmGetAddrInfo(host)) == NULL) {
	if (pmDebug & DBG_TRACE_HTTP)
	    fprintf(stderr, "HTTP connect(%s, %d): hosterror=%d, ``%s''\n",
		    host, port, hosterror(), hoststrerror());
	return -EHOSTUNREACH;
    }
    /*
     * We want to respect the connect timeout that has been configured, but we
     * may have more than one address to try.  Do this by creating a socket for
     * each address and then using __pmSelectWrite() to wait for one of them to
     * respond.  That way, the timeout is applied to all of the addresses
     * simultaneously.  First, create the sockets, add them to the fd set and
     * try to establish connectections.
     */
    __pmFD_ZERO(&allFds);
    maxFd = -1;
    enumIx = NULL;
    for (myAddr = __pmHostEntGetSockAddr(servInfo, &enumIx);
	 myAddr != NULL;
	 myAddr = __pmHostEntGetSockAddr(servInfo, &enumIx)) {
	/* Create a socket */
	if (__pmSockAddrIsInet(myAddr))
	    fd = __pmCreateSocket();
	else if (__pmSockAddrIsIPv6(myAddr))
	    fd = __pmCreateIPv6Socket();
	else {
	    if (pmDebug & DBG_TRACE_HTTP)
		fprintf(stderr, "HTTP connect(%s, %d): bad address family %d\n",
			host, port, __pmSockAddrGetFamily(myAddr));
	    fd = -EINVAL;
	}
	if (fd < 0) {
	    __pmSockAddrFree(myAddr);
	    continue; /* Try the next address */
	}

	/* Attempt to connect */
	fdFlags[fd] = __pmConnectTo(fd, myAddr, port);
	__pmSockAddrFree(myAddr);
	if (fdFlags[fd] < 0) {
	    /*
	     * Mark failure in case we fall out the end of the loop
	     * and try next address
	     */
	    __pmCloseSocket(fd);
	    continue;
	}

	/* Add it to the fd set. */
	__pmFD_SET(fd, &allFds);
	if (fd > maxFd)
	    maxFd = fd;
    }
    __pmHostEntFree(servInfo);

    /* If we were unable to open any sockets, then give up. */
    if (maxFd == -1)
	return -ECONNREFUSED;

    /* FNDELAY and we're in progress - wait on select */
    __pmFD_COPY(&readyFds, &allFds);
    stv = *timeout;
    ptv = (stv.tv_sec || stv.tv_usec) ? &stv : NULL;
    sts = __pmSelectWrite(maxFd+1, &readyFds, ptv);

    /* Figure out what happened. */
    if (sts == 0)
	fd = -ETIMEDOUT;
    else if (sts < 0)
	fd = -neterror();
    else {
	/* Scan fd set, find first successfully connected socket (if any). */
	fd = -EINVAL;
	for (i = 0; i <= maxFd; ++i) {
	    if (__pmFD_ISSET(i, &readyFds)) {
		/* Successful connection? */
		sts = __pmConnectCheckError(i);
		if (sts == 0) {
		    fd = i;
		    break;
		}
		fd = -sts;
	    }
	}
    }

    /* Clean up the unused fds. */
    for (i = 0; i <= maxFd; ++i) {
	if (i != fd && __pmFD_ISSET(i, &allFds))
	    __pmCloseSocket(i);
    }

    if (fd < 0)
	return fd;

    /*
     * If we're here, it means we have a valid connection; restore the
     * flags and make sure this file descriptor is closed if exec() is
     * called
     */
    return __pmConnectRestoreFlags(fd, fdFlags[fd]);
}
Exemplo n.º 5
0
static int stomp_connect(const char *hostname, int port)
{
    __pmSockAddr *myaddr;
    __pmHostEnt *servinfo;
    void *enumIx;
    struct timeval tv;
    struct timeval *ptv;
    __pmFdSet wfds;
    int ret;
    int flags = 0;

    if ((servinfo = __pmGetAddrInfo(hostname)) == NULL)
	return -1;

    fd = -1;
    enumIx = NULL;
    for (myaddr = __pmHostEntGetSockAddr(servinfo, &enumIx);
	 myaddr != NULL;
	 myaddr = __pmHostEntGetSockAddr(servinfo, &enumIx)) {
	/* Create a socket */
	if (__pmSockAddrIsInet(myaddr))
	    fd = __pmCreateSocket();
	else if (__pmSockAddrIsIPv6(myaddr))
	    fd = __pmCreateIPv6Socket();
	else
	    fd = -1;

	if (fd < 0) {
	    __pmSockAddrFree(myaddr);
	    continue; /* Try the next address */
	}

	/* Attempt to connect */
	flags = __pmConnectTo(fd, myaddr, port);
	__pmSockAddrFree(myaddr);

	if (flags < 0) {
	    /*
	     * Mark failure in case we fall out the end of the loop
	     * and try next address. fd has been closed in __pmConnectTo().
	     */
	    fd = -1;
	    continue;
	}

	/* FNDELAY and we're in progress - wait on select */
	tv.tv_sec = timeout;
	tv.tv_usec = 0;
	ptv = (tv.tv_sec || tv.tv_usec) ? &tv : NULL;
	__pmFD_ZERO(&wfds);
	__pmFD_SET(fd, &wfds);
	ret = __pmSelectWrite(fd+1, &wfds, ptv);

	/* Was the connection successful? */
	if (ret <= 0) {
	    if (oserror() == EINTR)
		return -2;
	    continue;
	}
	ret = __pmConnectCheckError(fd);
	if (ret == 0)
	    break;

	/* Unsuccessful connection. */
	__pmCloseSocket(fd);
	fd = -1;
    } /* loop over addresses */

    __pmHostEntFree(servinfo);

    if(fd == -1)
	return -4;

    fd = __pmConnectRestoreFlags(fd, flags);
    if(fd < 0)
	return -5;

    return fd;
}
Exemplo n.º 6
0
int
do_preamble(void)
{
    int		sts;
    int		i;
    int		j;
    pid_t	mypid = getpid();
    pmResult	*res;
    __pmPDU	*pb;
    pmAtomValue	atom;
    __pmTimeval	tmp;
    char	path[MAXPATHLEN];
    char	host[MAXHOSTNAMELEN];
    int		free_cp;

    /* start to build the pmResult */
    res = (pmResult *)malloc(sizeof(pmResult) + (n_metric - 1) * sizeof(pmValueSet *));
    if (res == NULL)
	return -oserror();

    res->numpmid = n_metric;
    last_stamp = res->timestamp = epoch;	/* struct assignment */
    tmp.tv_sec = (__int32_t)epoch.tv_sec;
    tmp.tv_usec = (__int32_t)epoch.tv_usec;

    for (i = 0; i < n_metric; i++)
	res->vset[i] = NULL;

    for (i = 0; i < n_metric; i++) {
	res->vset[i] = (pmValueSet *)malloc(sizeof(pmValueSet));
	if (res->vset[i] == NULL) {
	    sts = -oserror();
	    goto done;
	}
	res->vset[i]->pmid = desc[i].pmid;
	res->vset[i]->numval = 1;
	/* special case for each value 0 .. n_metric-1 */
	free_cp = 0;
	if (desc[i].pmid == PMID(2,3,3)) {
	    __pmHostEnt *servInfo;
	    /* my fully qualified hostname, cloned from the pmcd PMDA */
	    (void)gethostname(host, MAXHOSTNAMELEN);
	    host[MAXHOSTNAMELEN-1] = '\0';
	    if ((servInfo = __pmGetAddrInfo(host)) == NULL)
		atom.cp = host;
	    else {
		atom.cp = __pmHostEntGetName(servInfo);
		__pmHostEntFree(servInfo);
		if (atom.cp == NULL)
		    atom.cp = host;
		else
		    free_cp = 1;
	    }
	 }
	 else if (desc[i].pmid == PMID(2,3,0)) {
	    /* my control port number, from ports.c */
	    atom.l = ctlport;
	 }
	 else if (desc[i].pmid == PMID(2,3,2)) {
	    /*
	     * the full pathname to the base of the archive, cloned
	     * from GetPort() in ports.c
	     */
	    if (__pmAbsolutePath(archBase))
		atom.cp = archBase;
	    else {
		if (getcwd(path, MAXPATHLEN) == NULL)
		    atom.cp = archBase;
		else {
		    strcat(path, "/");
		    strcat(path, archBase);
		    atom.cp = path;
		}
	    }
	}

	sts = __pmStuffValue(&atom, &res->vset[i]->vlist[0], desc[i].type);
	if (free_cp)
	    free(atom.cp);
	if (sts < 0)
	    goto done;
	res->vset[i]->vlist[0].inst = (int)mypid;
	res->vset[i]->valfmt = sts;
    }

    if ((sts = __pmEncodeResult(fileno(logctl.l_mfp), res, &pb)) < 0)
	goto done;

    __pmOverrideLastFd(fileno(logctl.l_mfp));	/* force use of log version */
    /* and start some writing to the archive log files ... */
    sts = __pmLogPutResult2(&logctl, pb);
    __pmUnpinPDUBuf(pb);
    if (sts < 0)
	goto done;

    for (i = 0; i < n_metric; i++) {
	if ((sts = __pmLogPutDesc(&logctl, &desc[i], 1, &names[i])) < 0)
	    goto done;
	if (desc[i].indom == PM_INDOM_NULL)
	    continue;
	for (j = 0; j < i; j++) {
	    if (desc[i].indom == desc[j].indom)
		break;
	}
	if (j == i) {
	    /* need indom ... force one with my PID as the only instance */
	    int		*instid;
	    char	**instname;

	    if ((instid = (int *)malloc(sizeof(*instid))) == NULL) {
		sts = -oserror();
		goto done;
	    }
	    *instid = (int)mypid;
	    snprintf(path, sizeof(path), "%" FMT_PID, mypid);
	    if ((instname = (char **)malloc(sizeof(char *)+strlen(path)+1)) == NULL) {
		free(instid);
		sts = -oserror();
		goto done;
	    }
	    /*
	     * this _is_ correct ... instname[] is a one element array
	     * with the string value immediately following
	     */
	    instname[0] = (char *)&instname[1];
            strcpy(instname[0], path);
	    /*
	     * Note.	DO NOT free instid and instname ... they get hidden
	     *		away in addindom() below __pmLogPutInDom()
	     */
	    if ((sts = __pmLogPutInDom(&logctl, desc[i].indom, &tmp, 1, instid, instname)) < 0)
		goto done;
	}
    }

    /* fudge the temporal index */
    fseek(logctl.l_mfp, sizeof(__pmLogLabel)+2*sizeof(int), SEEK_SET);
    fseek(logctl.l_mdfp, sizeof(__pmLogLabel)+2*sizeof(int), SEEK_SET);
    __pmLogPutIndex(&logctl, &tmp);
    fseek(logctl.l_mfp, 0L, SEEK_END);
    fseek(logctl.l_mdfp, 0L, SEEK_END);
    sts = 0;

    /*
     * and now free stuff
     */
done:
    for (i = 0; i < n_metric; i++) {
	if (res->vset[i] != NULL)
	    free(res->vset[i]);
    }
    free(res);

    return sts;
}
Exemplo n.º 7
0
Arquivo: trace.c Projeto: tongfw/pcp
static int
_pmauxtraceconnect(void)
{
    int			port = TRACE_PORT;
    char		hostname[MAXHOSTNAMELEN];
    struct timeval	timeout = { 3, 0 };     /* default 3 secs */
    __pmSockAddr	*myaddr;
    __pmHostEnt		*servinfo;
    void		*enumIx;
#ifndef IS_MINGW
    struct itimerval	_pmolditimer;
    void		(*old_handler)(int foo);
#endif
    int			rc, sts;
    int			flags = 0;
    char		*sptr, *endptr, *endnum;
    struct timeval	canwait = { 5, 000000 };
    struct timeval	stv;
    struct timeval	*pstv;
    __pmFdSet		wfds;

#ifdef PMTRACE_DEBUG
    if (__pmstate & PMTRACE_STATE_NOAGENT) {
	fprintf(stderr, "_pmtraceconnect: connecting to PMDA (skipped)\n");
	return 0;
    }
    else if (__pmstate & PMTRACE_STATE_COMMS)
	fprintf(stderr, "_pmtraceconnect: connecting to PMDA ...\n");
#endif

    /*
     * get optional stuff from environment ...
     *  PCP_TRACE_HOST, PCP_TRACE_PORT, PCP_TRACE_TIMEOUT, and
     *  PCP_TRACE_NOAGENT
     */
    if ((sptr = getenv(TRACE_ENV_HOST)) != NULL)
	strcpy(hostname, sptr);
    else {
       (void)gethostname(hostname, MAXHOSTNAMELEN);
       hostname[MAXHOSTNAMELEN-1] = '\0';
    }
    if ((sptr = getenv(TRACE_ENV_PORT)) != NULL) {
	port = (int)strtol(sptr, &endnum, 0);
	if (*endnum != '\0' || port < 0) {
	    fprintf(stderr, "trace warning: bad PCP_TRACE_PORT ignored.");
	    port = TRACE_PORT;
	}
    }
    if ((sptr = getenv(TRACE_ENV_TIMEOUT)) != NULL) {
	double timesec = strtod(sptr, &endptr);
	if (*endptr != '\0' || timesec < 0.0)
	    fprintf(stderr, "trace warning: bogus PCP_TRACE_TIMEOUT.");
	else {
	    timeout.tv_sec = (time_t)timesec;
	    timeout.tv_usec = (int)((timesec - (double)timeout.tv_sec)*1000000);
	}
    }
    if (getenv(TRACE_ENV_NOAGENT) != NULL)
	__pmstate |= PMTRACE_STATE_NOAGENT;

    if ((servinfo = __pmGetAddrInfo(hostname)) == NULL) {
#ifdef PMTRACE_DEBUG
	if (__pmstate & PMTRACE_STATE_COMMS)
	    fprintf(stderr, "_pmtraceconnect(__pmGetAddrInfo(hostname=%s): "
		    "hosterror=%d, ``%s''\n", hostname, hosterror(),
		    hoststrerror());
#endif
	return -EHOSTUNREACH;
    }

    /* Try each address in turn until one connects. */
    sts = EHOSTUNREACH;
    __pmfd = -1;
    enumIx = NULL;
    for (myaddr = __pmHostEntGetSockAddr(servinfo, &enumIx);
	 myaddr != NULL;
	 myaddr = __pmHostEntGetSockAddr(servinfo, &enumIx)) {
	/* Create a socket */
	if (__pmSockAddrIsInet(myaddr))
	    __pmfd = __pmCreateSocket();
	else if (__pmSockAddrIsIPv6(myaddr))
	    __pmfd = __pmCreateIPv6Socket();
	else {
	    fprintf(stderr, "_pmtraceconnect(invalid address family): %d\n",
		    __pmSockAddrGetFamily(myaddr));
	}
	if (__pmfd < 0) {
	    sts = neterror();
	    __pmSockAddrFree(myaddr);
	    continue; /* Try the next address */
	}

	/* Set the port. */
	__pmSockAddrSetPort(myaddr, port);

#ifndef IS_MINGW
	/* arm interval timer */
	_pmmyitimer.it_value.tv_sec = timeout.tv_sec;
	_pmmyitimer.it_value.tv_usec = timeout.tv_usec;
	_pmmyitimer.it_interval.tv_sec = 0;
	_pmmyitimer.it_interval.tv_usec = 0;
	old_handler = signal(SIGALRM, _pmtracealarm);
	setitimer(ITIMER_REAL, &_pmmyitimer, &_pmolditimer);
#endif

#ifdef PMTRACE_DEBUG
	if (__pmstate & PMTRACE_STATE_COMMS) {
	    char *name = __pmHostEntGetName (servinfo);
	    fprintf(stderr, "_pmtraceconnect: PMDA host=%s port=%d timeout=%d"
		    "secs\n", name == NULL ? "unknown" : name, port, (int)timeout.tv_sec);
	    if (name != NULL)
		free(name);
	}
#endif

	/* Attempt to connect */
	flags = __pmConnectTo(__pmfd, myaddr, port);
	__pmSockAddrFree(myaddr);

	if (flags < 0) {
	    /*
	     * Mark failure in case we fall out the end of the loop
	     * and try next address. __pmfd has been closed in __pmConnectTo().
	     */
	    sts = -flags;
	    __pmfd = -1;
	    continue;
	}

	/* FNDELAY and we're in progress - wait on select */
	stv = canwait;
	pstv = (stv.tv_sec || stv.tv_usec) ? &stv : NULL;
	__pmFD_ZERO(&wfds);
	__pmFD_SET(__pmfd, &wfds);
	if ((rc = __pmSelectWrite(__pmfd+1, &wfds, pstv)) == 1) {
	    sts = __pmConnectCheckError(__pmfd);
	}
	else if (rc == 0) {
	    sts = ETIMEDOUT;
	}
	else {
	    sts = (rc < 0) ? neterror() : EINVAL;
	}
 
#ifndef IS_MINGW
	/* re-arm interval timer */
	setitimer(ITIMER_REAL, &off_itimer, &_pmmyitimer);
	signal(SIGALRM, old_handler);
	if (_pmolditimer.it_value.tv_sec != 0 && _pmolditimer.it_value.tv_usec != 0) {
	    _pmolditimer.it_value.tv_usec -= timeout.tv_usec - _pmmyitimer.it_value.tv_usec;
	    while (_pmolditimer.it_value.tv_usec < 0) {
		_pmolditimer.it_value.tv_usec += 1000000;
		_pmolditimer.it_value.tv_sec--;
	    }
	    while (_pmolditimer.it_value.tv_usec > 1000000) {
		_pmolditimer.it_value.tv_usec -= 1000000;
		_pmolditimer.it_value.tv_sec++;
	    }
	    _pmolditimer.it_value.tv_sec -= timeout.tv_sec - _pmmyitimer.it_value.tv_sec;
	    if (_pmolditimer.it_value.tv_sec < 0) {
		/* missed the user's itimer, pretend there is 1 msec to go! */
		_pmolditimer.it_value.tv_sec = 0;
		_pmolditimer.it_value.tv_usec = 1000;
	    }
	    setitimer(ITIMER_REAL, &_pmolditimer, &_pmmyitimer);
	}
#endif

	/* Was the connection successful? */
	if (sts == 0)
	    break;

	/* Unsuccessful connection. */
	__pmCloseSocket(__pmfd);
	__pmfd = -1;
    } /* loop over addresses */

    __pmHostEntFree(servinfo);

    /* Was the connection successful? */
    if (__pmfd < 0) {
#ifdef PMTRACE_DEBUG
	if (__pmstate & PMTRACE_STATE_COMMS)
	    fprintf(stderr, "_pmtraceconnect(socket failed): %s\n",
		    netstrerror());
#endif
	return -sts;
    }

    _pmtimedout = 0;

    /* Restore the original file status flags. */
    if (__pmSetFileStatusFlags(__pmfd, flags) < 0) {
#ifdef PMTRACE_DEBUG
	if (__pmstate & PMTRACE_STATE_COMMS)
	    fprintf(stderr, ":_pmtraceconnect: cannot restore file status flags\n");
#endif
	return -oserror();
    }

    /* make sure this file descriptor is closed if exec() is called */
    if ((flags = __pmGetFileDescriptorFlags(__pmfd)) != -1)
	sts = __pmSetFileDescriptorFlags(__pmfd, flags | FD_CLOEXEC);
    else
	sts = -1;
    if (sts == -1)
	return -oserror();

    if (__pmtraceprotocol(TRACE_PROTOCOL_QUERY) == TRACE_PROTOCOL_ASYNC) {
	/* in the asynchronoous protocol - ensure no delay after close */
	if ((flags = __pmGetFileStatusFlags(__pmfd)) != -1)
	    sts = __pmSetFileStatusFlags(__pmfd, flags | FNDELAY);
	else
	    sts = -1;
	if (sts == -1)
	    return -oserror();
#ifdef PMTRACE_DEBUG
	if (__pmstate & PMTRACE_STATE_COMMS)
	    fprintf(stderr, "_pmtraceconnect: async protocol setup complete\n");
#endif
    }
    else
#ifdef PMTRACE_DEBUG
	if (__pmstate & PMTRACE_STATE_COMMS)
	    fprintf(stderr, "_pmtraceconnect: sync protocol setup complete\n");
#endif

    /* trace PMDA sends an ACK on successful connect */
    sts = _pmtracegetack(sts, 0);

    return sts;
}