Page MenuHomeFreeBSD

D8792.id22915.diff
No OneTemporary

D8792.id22915.diff

Index: etc/inetd.conf
===================================================================
--- etc/inetd.conf
+++ etc/inetd.conf
@@ -117,3 +117,7 @@
#netbios-ssn stream tcp nowait root /usr/local/sbin/smbd smbd
#netbios-ns dgram udp wait root /usr/local/sbin/nmbd nmbd
#swat stream tcp nowait/400 root /usr/local/sbin/swat swat
+#
+# Example entry for the Prometheus sysctl metrics exporter
+#
+#prom-sysctl stream tcp nowait nobody /usr/sbin/prometheus_sysctl_exporter prometheus_sysctl_exporter -dh
Index: etc/services
===================================================================
--- etc/services
+++ etc/services
@@ -2450,6 +2450,7 @@
aurora 9084/tcp #IBM AURORA Performance Visualizer
aurora 9084/udp #IBM AURORA Performance Visualizer
jetdirect 9100/tcp #HP JetDirect card
+prom-sysctl 9124/tcp #prometheus_sysctl_exporter(8)
git 9418/tcp #git pack transfer service
git 9418/udp #git pack transfer service
man 9535/tcp
Index: sbin/sysctl/sysctl.8
===================================================================
--- sbin/sysctl/sysctl.8
+++ sbin/sysctl/sysctl.8
@@ -28,7 +28,7 @@
.\" From: @(#)sysctl.8 8.1 (Berkeley) 6/6/93
.\" $FreeBSD$
.\"
-.Dd December 10, 2015
+.Dd December 14, 2016
.Dt SYSCTL 8
.Os
.Sh NAME
@@ -306,7 +306,8 @@
.Xr sysctl 3 ,
.Xr loader.conf 5 ,
.Xr sysctl.conf 5 ,
-.Xr loader 8
+.Xr loader 8 ,
+.Xr prometheus_sysctl_exporter 8
.Sh HISTORY
A
.Nm
Index: usr.sbin/Makefile
===================================================================
--- usr.sbin/Makefile
+++ usr.sbin/Makefile
@@ -62,6 +62,7 @@
periodic \
powerd \
procctl \
+ prometheus_sysctl_exporter \
pstat \
pw \
pwd_mkdb \
Index: usr.sbin/prometheus_sysctl_exporter/Makefile
===================================================================
--- /dev/null
+++ usr.sbin/prometheus_sysctl_exporter/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+PROG= prometheus_sysctl_exporter
+MAN= prometheus_sysctl_exporter.8
+
+LIBADD= m
+
+.include <bsd.prog.mk>
Index: usr.sbin/prometheus_sysctl_exporter/prometheus_sysctl_exporter.8
===================================================================
--- /dev/null
+++ usr.sbin/prometheus_sysctl_exporter/prometheus_sysctl_exporter.8
@@ -0,0 +1,104 @@
+.\" Copyright (c) 2016 Nuxi, https://nuxi.nl/
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.Dd December 14, 2016
+.Dt PROMETHEUS_SYSCTL_EXPORTER 8
+.Os
+.Sh NAME
+.Nm prometheus_sysctl_exporter
+.Nd print kernel state as Prometheus metrics
+.Sh SYNOPSIS
+.Nm prometheus_sysctl_exporter
+.Op Fl dh
+.Op Ar prefix ...
+.Sh DESCRIPTION
+Prometheus is a monitoring system that gathers metrics from its targets
+by fetching them through HTTP GET requests.
+Metrics are identified by a name and an optional set of labels.
+Sample values are required to be numerical.
+.Pp
+The
+.Nm
+utility prints the values of sysctl nodes to standard output,
+formatted such that they can be scraped by Prometheus directly.
+By default,
+it prints metrics for all numerically representable nodes in the sysctl
+namespace.
+It is also possible to limit output to a smaller number of metrics by
+specifying one or more prefixes as arguments.
+.Pp
+Metrics printed by this utility are named
+.Ql sysctl_ ,
+followed by the name of the sysctl node having its
+.Ql .\&
+separators replaced by
+.Ql _ .
+Components on which it is desirable to aggregate (e.g.\& names of devices)
+are omitted from the metric's name,
+but are appended as labels instead.
+.Pp
+There are two different methods for exporting the output of
+.Nm
+to Prometheus.
+The first method is to periodically invoke this utility through
+.Xr cron 8
+and store its output in a textfile.
+The metrics in this textfile can then be served over HTTP using the
+Prometheus node exporter's textfile collector.
+The second method is to run this utility through
+.Xr inetd 8 .
+TCP port 9124 has been allocated for this purpose.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl d
+Print help descriptions of metrics when available.
+.It Fl h
+Precede the output with a HTTP response header.
+This flag is required when running this utility through
+.Xr inetd 8 .
+.El
+.Sh SEE ALSO
+.Xr cron 8 ,
+.Xr inetd 8 ,
+.Xr sysctl 8 ,
+.Xr SYSCTL_ADD_NODE_WITH_LABEL 9
+.Pp
+Prometheus project:
+.Pa https://prometheus.io/ .
+.Pp
+Prometheus exposition formats:
+.Pa https://prometheus.io/docs/instrumenting/exposition_formats/ .
+.Pp
+Prometheus node exporter:
+.Pa https://github.com/prometheus/node_exporter .
+.Pp
+Prometheus default port allocations:
+.Pa https://github.com/prometheus/prometheus/wiki/Default-port-allocations .
+.Sh HISTORY
+.Nm
+first appeared in
+.Fx 12.0 .
+.Sh AUTHORS
+.An Nuxi : Pa https://nuxi.nl/ .
Index: usr.sbin/prometheus_sysctl_exporter/prometheus_sysctl_exporter.c
===================================================================
--- /dev/null
+++ usr.sbin/prometheus_sysctl_exporter/prometheus_sysctl_exporter.c
@@ -0,0 +1,584 @@
+/*-
+ * Copyright (c) 2016 Nuxi, https://nuxi.nl/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <math.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/*
+ * Cursor for iterating over all of the system's sysctl OIDs.
+ */
+struct oid {
+ int id[CTL_MAXNAME];
+ size_t len;
+};
+
+/* Initializes the cursor to point to start of the tree. */
+static void
+oid_get_root(struct oid *o)
+{
+
+ o->id[0] = 1;
+ o->len = 1;
+}
+
+/* Obtains the OID for a sysctl by name. */
+static void
+oid_get_by_name(struct oid *o, const char *name)
+{
+
+ o->len = sizeof(o->id) / sizeof(o->id[0]);
+ if (sysctlnametomib(name, o->id, &o->len) != 0)
+ err(1, "sysctl(%s)", name);
+}
+
+/* Returns whether an OID is placed below another OID. */
+static bool
+oid_is_beneath(struct oid *oa, struct oid *ob)
+{
+
+ return (oa->len >= ob->len &&
+ memcmp(oa->id, ob->id, ob->len * sizeof(oa->id[0])) == 0);
+}
+
+/* Advances the cursor to the next OID. */
+static bool
+oid_get_next(const struct oid *cur, struct oid *next)
+{
+ int lookup[CTL_MAXNAME + 2];
+ size_t nextsize;
+
+ lookup[0] = 0;
+ lookup[1] = 2;
+ memcpy(lookup + 2, cur->id, cur->len * sizeof(lookup[0]));
+ nextsize = CTL_MAXNAME * sizeof(cur->id[0]);
+ if (sysctl(lookup, 2 + cur->len, &next->id, &nextsize, 0, 0) != 0) {
+ if (errno == ENOENT)
+ return (false);
+ err(1, "sysctl(next)");
+ }
+ next->len = nextsize / sizeof(next->id[0]);
+ return (true);
+}
+
+/*
+ * OID formatting metadata.
+ */
+struct oidformat {
+ unsigned int kind;
+ char format[BUFSIZ];
+};
+
+/* Returns whether the OID represents a temperature value. */
+static bool
+oidformat_is_temperature(const struct oidformat *of)
+{
+
+ return (of->format[0] == 'I' && of->format[1] == 'K');
+}
+
+/* Fetches the formatting metadata for an OID. */
+static bool
+oid_get_format(const struct oid *o, struct oidformat *of)
+{
+ int lookup[CTL_MAXNAME + 2];
+ size_t oflen;
+
+ lookup[0] = 0;
+ lookup[1] = 4;
+ memcpy(lookup + 2, o->id, o->len * sizeof(lookup[0]));
+ oflen = sizeof(*of);
+ if (sysctl(lookup, 2 + o->len, of, &oflen, 0, 0) != 0) {
+ if (errno == ENOENT)
+ return (false);
+ err(1, "sysctl(oidfmt)");
+ }
+ return (true);
+}
+
+/*
+ * Container for holding the value of an OID.
+ */
+struct oidvalue {
+ enum { SIGNED, UNSIGNED, FLOAT } type;
+ union {
+ intmax_t s;
+ uintmax_t u;
+ double f;
+ } value;
+};
+
+/* Extracts the value of an OID, converting it to a floating-point number. */
+static double
+oidvalue_get_float(const struct oidvalue *ov)
+{
+
+ switch (ov->type) {
+ case SIGNED:
+ return (ov->value.s);
+ case UNSIGNED:
+ return (ov->value.u);
+ case FLOAT:
+ return (ov->value.f);
+ }
+}
+
+/* Sets the value of an OID as a signed integer. */
+static void
+oidvalue_set_signed(struct oidvalue *ov, intmax_t s)
+{
+
+ ov->type = SIGNED;
+ ov->value.s = s;
+}
+
+/* Sets the value of an OID as an unsigned integer. */
+static void
+oidvalue_set_unsigned(struct oidvalue *ov, uintmax_t u)
+{
+
+ ov->type = UNSIGNED;
+ ov->value.u = u;
+}
+
+/* Sets the value of an OID as a floating-point number. */
+static void
+oidvalue_set_float(struct oidvalue *ov, double f)
+{
+
+ ov->type = FLOAT;
+ ov->value.f = f;
+}
+
+/* Prints the value of an OID to a file stream. */
+static void
+oidvalue_print(const struct oidvalue *ov, FILE *fp)
+{
+
+ switch (ov->type) {
+ case SIGNED:
+ fprintf(fp, "%jd", ov->value.s);
+ break;
+ case UNSIGNED:
+ fprintf(fp, "%ju", ov->value.u);
+ break;
+ case FLOAT:
+ switch (fpclassify(ov->value.f)) {
+ case FP_INFINITE:
+ if (signbit(ov->value.f))
+ fprintf(fp, "-Inf");
+ else
+ fprintf(fp, "+Inf");
+ break;
+ case FP_NAN:
+ fprintf(fp, "Nan");
+ break;
+ default:
+ fprintf(fp, "%.2f", ov->value.f);
+ break;
+ }
+ break;
+ }
+}
+
+/* Fetches the value of an OID. */
+static bool
+oid_get_value(const struct oid *o, const struct oidformat *of,
+ struct oidvalue *ov)
+{
+
+ switch (of->kind & CTLTYPE) {
+#define GET_VALUE(ctltype, type) \
+ case (ctltype): { \
+ type value; \
+ size_t valuesize; \
+ \
+ valuesize = sizeof(value); \
+ if (sysctl(o->id, o->len, &value, &valuesize, 0, 0) != 0) \
+ return (false); \
+ if ((type)-1 < 0) \
+ oidvalue_set_signed(ov, value); \
+ else \
+ oidvalue_set_unsigned(ov, value); \
+ break; \
+ }
+ GET_VALUE(CTLTYPE_INT, int);
+ GET_VALUE(CTLTYPE_UINT, unsigned int);
+ GET_VALUE(CTLTYPE_LONG, long);
+ GET_VALUE(CTLTYPE_ULONG, unsigned long);
+ GET_VALUE(CTLTYPE_S8, int8_t);
+ GET_VALUE(CTLTYPE_U8, uint8_t);
+ GET_VALUE(CTLTYPE_S16, int16_t);
+ GET_VALUE(CTLTYPE_U16, uint16_t);
+ GET_VALUE(CTLTYPE_S32, int32_t);
+ GET_VALUE(CTLTYPE_U32, uint32_t);
+ GET_VALUE(CTLTYPE_S64, int64_t);
+ GET_VALUE(CTLTYPE_U64, uint64_t);
+#undef GET_VALUE
+ default:
+ return (false);
+ }
+
+ /* Convert temperatures from decikelvin to degrees Celcius. */
+ if (oidformat_is_temperature(of)) {
+ double v;
+ int e;
+
+ v = oidvalue_get_float(ov);
+ if (v < 0) {
+ oidvalue_set_float(ov, NAN);
+ } else {
+ e = of->format[2] >= '0' && of->format[2] <= '9' ?
+ of->format[2] - '0' : 1;
+ oidvalue_set_float(ov, v / pow(10, e) - 273.15);
+ }
+ }
+ return (true);
+}
+
+/*
+ * The full name of an OID, stored as a series of components.
+ */
+struct oidname {
+ int id[CTL_MAXNAME];
+ char name_buf[BUFSIZ];
+ size_t name_end[CTL_MAXNAME + 1];
+ char label_buf[BUFSIZ];
+ size_t label_end[CTL_MAXNAME];
+};
+
+/*
+ * Initializes the OID name object with an empty value.
+ */
+static void
+oidname_init(struct oidname *on)
+{
+
+ on->name_end[0] = 0;
+}
+
+/* Fetches the name of an OID, partiall reusing the previous results. */
+static void
+oid_get_name(const struct oid *o, struct oidname *on)
+{
+ size_t i, name_start, label_start;
+
+ /* No need to fetch components that we already have. */
+ i = name_start = label_start = 0;
+ while (i < o->len && on->name_end[i] != 0 && on->id[i] == o->id[i]) {
+ name_start = on->name_end[i];
+ if (on->label_end[i] != 0)
+ label_start = on->label_end[i];
+ ++i;
+ }
+
+ /* Fetch the remainder. */
+ for (; i < o->len; ++i) {
+ int lookup[CTL_MAXNAME + 2];
+ char buf[BUFSIZ];
+ size_t len;
+
+ /* Look up the name of the component. */
+ lookup[0] = 0;
+ lookup[1] = 1;
+ memcpy(lookup + 2, o->id, (i + 1) * sizeof(lookup[0]));
+ len = sizeof(buf);
+ if (sysctl(lookup, 2 + i + 1, buf, &len, 0, 0) == 0) {
+ char *name;
+
+ name = strrchr(buf, '.');
+ if (name == NULL) {
+ name = buf;
+ } else {
+ ++name;
+ len -= name - buf;
+ }
+
+ assert(name_start + len <= sizeof(on->name_buf));
+ memcpy(on->name_buf + name_start, name, len);
+ on->name_end[i] = name_start += len;
+ } else {
+ err(1, "sysctl(name)");
+ }
+
+ /* Look up the optional label, allowing aggregation. */
+ lookup[1] = 6;
+ len = sizeof(buf);
+ if (sysctl(lookup, 2 + i + 1, buf, &len, 0, 0) == 0) {
+ assert(label_start + len <= sizeof(on->label_buf));
+ memcpy(on->label_buf + label_start, buf, len);
+ on->label_end[i] = label_start += len;
+ } else if (errno == ENOENT) {
+ on->label_end[i] = 0;
+ } else {
+ err(1, "sysctl(oidlabel)");
+ }
+ }
+ on->name_end[o->len] = 0;
+}
+
+/* Prints the name and labels of an OID to a file stream. */
+static void
+oidname_print(const struct oidname *on, const struct oidformat *of,
+ FILE *fp)
+{
+ const char *name, *label;
+ size_t i;
+ char separator;
+
+ /* Print the name of the metric. */
+ fprintf(fp, "sysctl");
+ name = on->name_buf;
+ for (i = 0; on->name_end[i] != 0; ++i) {
+ if (on->label_end[i] == 0) {
+ assert(name[strspn(name,
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789_")] == '\0');
+ fprintf(fp, "_%s", name);
+ }
+ name = on->name_buf + on->name_end[i];
+ }
+ if (oidformat_is_temperature(of))
+ fprintf(fp, "_celcius");
+
+ /* Print the labels of the metric. */
+ label = on->label_buf;
+ name = on->name_buf;
+ separator = '{';
+ for (i = 0; on->name_end[i] != 0; ++i) {
+ if (on->label_end[i] != 0) {
+ assert(name[strspn(name,
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789_-")] == '\0');
+ assert(label[strspn(label,
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789_")] == '\0');
+ fprintf(fp, "%c%s=\"%s\"", separator, label, name);
+ separator = ',';
+ label = on->label_buf + on->label_end[i];
+ }
+ name = on->name_buf + on->name_end[i];
+ }
+ if (separator != '{')
+ fputc('}', fp);
+}
+
+/* Returns whether the OID name has any labels associated to it. */
+static bool
+oidname_has_labels(const struct oidname *on)
+{
+ size_t i;
+
+ for (i = 0; on->name_end[i] != 0; ++i)
+ if (on->label_end[i] != 0)
+ return (true);
+ return (false);
+}
+
+/*
+ * The description of an OID.
+ */
+struct oiddescription {
+ char description[BUFSIZ];
+};
+
+/*
+ * Fetches the description of an OID.
+ */
+static bool
+oid_get_description(const struct oid *o, struct oiddescription *od)
+{
+ int lookup[CTL_MAXNAME + 2];
+ char *newline;
+ size_t odlen;
+
+ lookup[0] = 0;
+ lookup[1] = 5;
+ memcpy(lookup + 2, o->id, o->len * sizeof(lookup[0]));
+ odlen = sizeof(od->description);
+ if (sysctl(lookup, 2 + o->len, &od->description, &odlen, 0, 0) != 0) {
+ if (errno == ENOENT)
+ return (false);
+ err(1, "sysctl(oiddescr)");
+ }
+
+ newline = strchr(od->description, '\n');
+ if (newline != NULL)
+ *newline = '\0';
+
+ return (*od->description != '\0');
+}
+
+/* Prints the description of an OID to a file stream. */
+static void
+oiddescription_print(const struct oiddescription *od, FILE *fp)
+{
+
+ fprintf(fp, "%s", od->description);
+}
+
+static void
+oid_print(const struct oid *o, struct oidname *on, bool print_description,
+ FILE *fp)
+{
+ struct oidformat of;
+ struct oidvalue ov;
+ struct oiddescription od;
+
+ if (!oid_get_format(o, &of) || !oid_get_value(o, &of, &ov))
+ return;
+ oid_get_name(o, on);
+
+ /*
+ * Print the line with the description. Prometheus expects a
+ * single unique description for every metric, which cannot be
+ * guaranteed by sysctl if labels are present. Omit the
+ * description if labels are present.
+ */
+ if (print_description && !oidname_has_labels(on) &&
+ oid_get_description(o, &od)) {
+ fprintf(fp, "# HELP ");
+ oidname_print(on, &of, fp);
+ fputc(' ', fp);
+ oiddescription_print(&od, fp);
+ fputc('\n', fp);
+ }
+
+ /* Print the line with the value. */
+ oidname_print(on, &of, fp);
+ fputc(' ', fp);
+ oidvalue_print(&ov, fp);
+ fputc('\n', fp);
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr,
+ "usage: prometheus_sysctl_exporter [-dh] [sysctl_prefix ...]\n");
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct oidname on;
+ char *http_buf;
+ FILE *fp;
+ size_t http_buflen;
+ int ch;
+ bool http_mode, print_descriptions;
+
+ /* Parse command line flags. */
+ http_mode = print_descriptions = false;
+ while ((ch = getopt(argc, argv, "dh")) != -1) {
+ switch (ch) {
+ case 'd':
+ print_descriptions = true;
+ break;
+ case 'h':
+ http_mode = true;
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ /* HTTP output: cache metrics in buffer. */
+ if (http_mode) {
+ fp = open_memstream(&http_buf, &http_buflen);
+ if (fp == NULL)
+ err(1, "open_memstream");
+ } else {
+ fp = stdout;
+ }
+
+ oidname_init(&on);
+ if (argc == 0) {
+ struct oid o;
+
+ /* Print all OIDs. */
+ oid_get_root(&o);
+ do {
+ oid_print(&o, &on, print_descriptions, fp);
+ } while (oid_get_next(&o, &o));
+ } else {
+ int i;
+
+ /* Print only trees provided as arguments. */
+ for (i = 0; i < argc; ++i) {
+ struct oid o, root;
+
+ oid_get_by_name(&root, argv[i]);
+ o = root;
+ do {
+ oid_print(&o, &on, print_descriptions, fp);
+ } while (oid_get_next(&o, &o) &&
+ oid_is_beneath(&o, &root));
+ }
+ }
+
+ if (http_mode) {
+ if (ferror(fp) || fclose(fp) != 0)
+ err(1, "Cannot generate output");
+
+ /* Print HTTP header and metrics. */
+ dprintf(STDOUT_FILENO,
+ "HTTP/1.1 200 OK\r\n"
+ "Content-Type: text/plain; version=0.0.4\r\n"
+ "Content-Length: %zu\r\n\r\n",
+ http_buflen);
+ write(STDOUT_FILENO, http_buf, http_buflen);
+
+ /* Drain output. */
+ if (shutdown(STDIN_FILENO, SHUT_WR) == 0) {
+ char buf[1024];
+
+ while (read(STDIN_FILENO, buf, sizeof(buf)) > 0) {
+ }
+ }
+ }
+ return (0);
+}

File Metadata

Mime Type
text/plain
Expires
Tue, Feb 3, 2:44 PM (5 h, 39 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28424806
Default Alt Text
D8792.id22915.diff (19 KB)

Event Timeline