summaryrefslogtreecommitdiffstats
path: root/usr.sbin/pmcstat/pmcstat_log.c
diff options
context:
space:
mode:
authorjkoshy <jkoshy@FreeBSD.org>2006-04-02 12:52:16 +0000
committerjkoshy <jkoshy@FreeBSD.org>2006-04-02 12:52:16 +0000
commit80251d4f05948e213f6f292db20a93ad4cf36852 (patch)
treef82c027fa9baa5cc1c2c54f83529b6118bd99a57 /usr.sbin/pmcstat/pmcstat_log.c
parent19f9c1efe47d365dd95231c4ba6a1e467157f00a (diff)
downloadFreeBSD-src-80251d4f05948e213f6f292db20a93ad4cf36852.zip
FreeBSD-src-80251d4f05948e213f6f292db20a93ad4cf36852.tar.gz
- Teach pmcstat(8) to log over the network; the -O option now
takes a host:port specification. - Update the manual page and add an example showing how log over the network using pmcstat(8) and nc(1). Document the current inability to process logs in cross-platform manner. - Have pmcstat_open_log() call err(3) directly in case of an error; this simplifies error handling in its caller. MFC after: 1 week
Diffstat (limited to 'usr.sbin/pmcstat/pmcstat_log.c')
-rw-r--r--usr.sbin/pmcstat/pmcstat_log.c73
1 files changed, 67 insertions, 6 deletions
diff --git a/usr.sbin/pmcstat/pmcstat_log.c b/usr.sbin/pmcstat/pmcstat_log.c
index 8cf3087..0beb7c7 100644
--- a/usr.sbin/pmcstat/pmcstat_log.c
+++ b/usr.sbin/pmcstat/pmcstat_log.c
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mman.h>
#include <sys/pmc.h>
#include <sys/queue.h>
+#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/wait.h>
@@ -47,9 +48,11 @@ __FBSDID("$FreeBSD$");
#include <assert.h>
#include <err.h>
+#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <limits.h>
+#include <netdb.h>
#include <pmc.h>
#include <pmclog.h>
#include <sysexits.h>
@@ -1639,19 +1642,77 @@ pmcstat_close_log(struct pmcstat_args *a)
int
pmcstat_open_log(const char *path, int mode)
{
- int fd;
+ int error, fd;
+ size_t hlen;
+ const char *p, *errstr;
+ struct addrinfo hints, *res, *res0;
+ char hostname[MAXHOSTNAMELEN];
+
+ errstr = NULL;
+ fd = -1;
/*
* If 'path' is "-" then open one of stdin or stdout depending
- * on the value of 'mode'. Otherwise, treat 'path' as a file
- * name and open that.
+ * on the value of 'mode'.
+ *
+ * If 'path' contains a ':' and does not start with a '/' or '.',
+ * and is being opened for writing, treat it as a "host:port"
+ * specification and open a network socket.
+ *
+ * Otherwise, treat 'path' as a file name and open that.
*/
if (path[0] == '-' && path[1] == '\0')
fd = (mode == PMCSTAT_OPEN_FOR_READ) ? 0 : 1;
- else
- fd = open(path, mode == PMCSTAT_OPEN_FOR_READ ?
+ else if (mode == PMCSTAT_OPEN_FOR_WRITE && path[0] != '/' &&
+ path[0] != '.' && strchr(path, ':') != NULL) {
+
+ p = strrchr(path, ':');
+ hlen = p - path;
+ if (p == path || hlen >= sizeof(hostname)) {
+ errstr = strerror(EINVAL);
+ goto done;
+ }
+
+ assert(hlen < sizeof(hostname));
+ (void) strncpy(hostname, path, hlen);
+ hostname[hlen] = '\0';
+
+ (void) memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ if ((error = getaddrinfo(hostname, p+1, &hints, &res0)) != 0) {
+ errstr = gai_strerror(error);
+ goto done;
+ }
+
+ fd = -1;
+ for (res = res0; res; res = res->ai_next) {
+ if ((fd = socket(res->ai_family, res->ai_socktype,
+ res->ai_protocol)) < 0) {
+ errstr = strerror(errno);
+ continue;
+ }
+ if (connect(fd, res->ai_addr, res->ai_addrlen) < 0) {
+ errstr = strerror(errno);
+ (void) close(fd);
+ fd = -1;
+ continue;
+ }
+ errstr = NULL;
+ break;
+ }
+ freeaddrinfo(res0);
+
+ } else if ((fd = open(path, mode == PMCSTAT_OPEN_FOR_READ ?
O_RDONLY : (O_WRONLY|O_CREAT|O_TRUNC),
- S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
+ errstr = strerror(errno);
+
+ done:
+ if (errstr)
+ errx(EX_OSERR, "ERROR: Cannot open \"%s\" for %s: %s.", path,
+ (mode == PMCSTAT_OPEN_FOR_READ ? "reading" : "writing"),
+ errstr);
return (fd);
}
OpenPOWER on IntegriCloud