summaryrefslogtreecommitdiff
path: root/usr
diff options
context:
space:
mode:
authorSowmini Varadhan <Sowmini.Varadhan@Sun.COM>2009-03-17 19:00:36 -0400
committerSowmini Varadhan <Sowmini.Varadhan@Sun.COM>2009-03-17 19:00:36 -0400
commit8002d4117c1ea26aff1f16f584ae97bdbd5b21d5 (patch)
treeb5ce2731eff163feaf43cbd0b6a64bfb5dd37930 /usr
parentc5f9a89643b6d7175323dcb29f1a665661143c67 (diff)
downloadillumos-joyent-8002d4117c1ea26aff1f16f584ae97bdbd5b21d5.tar.gz
6782154 one copy of parse_output_fields() & friends is enough.
6751617 dladm show-link -s -i needs to flush stdout after each line 6687693 dladm show-aggr -s -i 1 in nv shows the column header only once per invocation
Diffstat (limited to 'usr')
-rw-r--r--usr/src/cmd/cmd-inet/usr.sbin/ipmpstat/Makefile2
-rw-r--r--usr/src/cmd/cmd-inet/usr.sbin/ipmpstat/ipmpstat.c747
-rw-r--r--usr/src/cmd/cmd-inet/usr.sbin/ipmpstat/ipmpstat.xcl3
-rw-r--r--usr/src/cmd/dladm/dladm.c1820
-rw-r--r--usr/src/cmd/dladm/dladm.xcl5
-rw-r--r--usr/src/cmd/flowadm/Makefile4
-rw-r--r--usr/src/cmd/flowadm/flowadm.c606
-rw-r--r--usr/src/lib/Makefile1
-rw-r--r--usr/src/lib/libinetutil/Makefile15
-rw-r--r--usr/src/lib/libinetutil/Makefile.com6
-rw-r--r--usr/src/lib/libinetutil/common/llib-linetutil12
-rw-r--r--usr/src/lib/libinetutil/common/mapfile-vers5
-rw-r--r--usr/src/lib/libinetutil/common/ofmt.c480
-rw-r--r--usr/src/lib/libinetutil/common/ofmt.h198
-rw-r--r--usr/src/pkgdefs/etc/exception_list_i3861
-rw-r--r--usr/src/pkgdefs/etc/exception_list_sparc1
16 files changed, 1844 insertions, 2062 deletions
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/ipmpstat/Makefile b/usr/src/cmd/cmd-inet/usr.sbin/ipmpstat/Makefile
index a256cf5f49..fb30e8af09 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/ipmpstat/Makefile
+++ b/usr/src/cmd/cmd-inet/usr.sbin/ipmpstat/Makefile
@@ -29,7 +29,7 @@ ROOTUSRSBINLINKS = $(PROG:%=$(ROOTUSRSBIN)/%)
include $(SRC)/cmd/Makefile.cmd
C99MODE = $(C99_ENABLE)
-LDLIBS += -lipmp -lsocket -lsysevent -lnvpair
+LDLIBS += -lipmp -lsocket -lsysevent -lnvpair -linetutil
XGETFLAGS += -a -x $(PROG).xcl
.KEEP_STATE:
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/ipmpstat/ipmpstat.c b/usr/src/cmd/cmd-inet/usr.sbin/ipmpstat/ipmpstat.c
index c28c426d4f..f5155e6745 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/ipmpstat/ipmpstat.c
+++ b/usr/src/cmd/cmd-inet/usr.sbin/ipmpstat/ipmpstat.c
@@ -33,6 +33,7 @@
#include <libsysevent.h>
#include <locale.h>
#include <netdb.h>
+#include <ofmt.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
@@ -62,28 +63,27 @@
* Since target information is included with the interface information,
* both -i and -t use the interface walker (walk_if()).
*
- * * The ipmpstat_sfunc_t function pointers (sfunc_*) obtain a given
- * value for a given IPMP object. Each ipmpstat_sunc_t is passed a
- * buffer to write its result into, the buffer's size, and an
- * ipmpstat_sfunc_arg_t state structure. The state structure consists
- * of a pointer to the IPMP object to obtain information from
- * (sa_data), and an open libipmp handle (sa_ih) which can be used to
- * do additional libipmp queries, if necessary (e.g., because the
- * object does not have all of the needed information).
+ * * The ofmt_sfunc_t function pointers (sfunc_*) obtain a given value
+ * for a given IPMP object. Each ofmt_sfunc_t is passed a buffer to
+ * write its result into, the buffer's size, and an ipmpstat_sfunc_arg_t
+ * state structure. The state structure consists of a pointer to the
+ * IPMP object to obtain information from (sa_data), and an open libipmp
+ * handle (sa_ih) which can be used to do additional libipmp queries, if
+ * necessary (e.g., because the object does not have all of the needed
+ * information).
*
- * * The ipmpstat_field_t structure provides the list of supported fields
- * for a given output format, along with output formatting information
- * (e.g., field width), and a pointer to an ipmpstat_sfunc_t function
- * that can obtain the value for a IPMP given object. For a given
- * ipmpstat output format, there's a corresponding array of
- * ipmpstat_field_t structures. Thus, one ipmpstat_field_t array is
- * used per ipmpstat invocation.
+ * * The ofmt_field_t arrays (*_fields[]) provide the supported fields for
+ * a given output format, along with output formatting information
+ * (e.g., field width) and a pointer to an ofmt_sfunc_t function that
+ * can obtain the value for a given IPMP object. One ofmt_field_t array
+ * is used per ipmpstat invocation, and is passed to ofmt_open() (along
+ * with the output fields and modes requested by the user) to create an
+ * ofmt_t.
*
- * * The ipmpstat_ofmt_t provides an ordered list of the requested
- * ipmpstat_field_t's (e.g., via -o) for a given ipmpstat invocation.
- * It is built at runtime from the command-line arguments. This
- * structure (and a given IPMP object) is used by ofmt_output() to
- * output a single line of information about that IPMP object.
+ * * The ofmt_t structure is a handle that tracks all information
+ * related to output formatting and is used by libinetutil`ofmt_print()
+ * (indirectly through our local ofmt_output() utility routine) to
+ * output a single line of information about the provided IPMP object.
*
* * The ipmpstat_cbfunc_t function pointers (*_cbfunc) are called back
* by the walkers. They are used both internally to implement nested
@@ -105,25 +105,6 @@ typedef struct ipmpstat_sfunc_arg {
void *sa_data;
} ipmpstat_sfunc_arg_t;
-typedef void ipmpstat_sfunc_t(ipmpstat_sfunc_arg_t *, char *, uint_t);
-
-/*
- * Data type that describes how to output a field; used by ofmt_output*().
- */
-typedef struct ipmpstat_field {
- const char *f_name; /* field name */
- uint_t f_width; /* output width */
- ipmpstat_sfunc_t *f_sfunc; /* value->string function */
-} ipmpstat_field_t;
-
-/*
- * Data type that specifies the output field order; used by ofmt_output*()
- */
-typedef struct ipmpstat_ofmt {
- const ipmpstat_field_t *o_field; /* current field info */
- struct ipmpstat_ofmt *o_next; /* next field */
-} ipmpstat_ofmt_t;
-
/*
* Function pointers used to iterate through IPMP objects.
*/
@@ -150,8 +131,8 @@ typedef struct ipmpstat_enum {
* Data type used to pass state between probe_output() and probe_event().
*/
typedef struct ipmpstat_probe_state {
- ipmp_handle_t ps_ih; /* open IPMP handle */
- ipmpstat_ofmt_t *ps_ofmt; /* requested ofmt string */
+ ipmp_handle_t ps_ih; /* open IPMP handle */
+ ofmt_handle_t ps_ofmt; /* open formatted-output handle */
} ipmpstat_probe_state_t;
/*
@@ -177,22 +158,19 @@ enum {
static const char *progname;
static hrtime_t probe_output_start;
-static struct winsize winsize;
static ipmpstat_opt_t opt;
+static ofmt_handle_t ofmt;
static ipmpstat_enum_t addr_state[], group_state[], if_state[], if_link[];
static ipmpstat_enum_t if_probe[], targ_mode[];
-static ipmpstat_field_t addr_fields[], group_fields[], if_fields[];
-static ipmpstat_field_t probe_fields[], targ_fields[];
+static ofmt_field_t addr_fields[], group_fields[], if_fields[];
+static ofmt_field_t probe_fields[], targ_fields[];
static ipmpstat_cbfunc_t walk_addr_cbfunc, walk_if_cbfunc;
static ipmpstat_cbfunc_t info_output_cbfunc, targinfo_output_cbfunc;
static ipmpstat_walker_t walk_addr, walk_if, walk_group;
static int probe_event(sysevent_t *, void *);
-static void probe_output(ipmp_handle_t, ipmpstat_ofmt_t *);
-static ipmpstat_field_t *field_find(ipmpstat_field_t *, const char *);
-static ipmpstat_ofmt_t *ofmt_create(const char *, ipmpstat_field_t []);
-static void ofmt_output(const ipmpstat_ofmt_t *, ipmp_handle_t, void *);
-static void ofmt_destroy(ipmpstat_ofmt_t *);
+static void probe_output(ipmp_handle_t, ofmt_handle_t);
+static void ofmt_output(ofmt_handle_t, ipmp_handle_t, void *);
static void enum2str(const ipmpstat_enum_t *, int, char *, uint_t);
static void sockaddr2str(const struct sockaddr_storage *, char *, uint_t);
static void sighandler(int);
@@ -208,12 +186,14 @@ main(int argc, char **argv)
int c;
int err;
const char *ofields = NULL;
+ ofmt_status_t ofmterr;
+ ofmt_field_t *fields = NULL;
+ uint_t ofmtflags = 0;
ipmp_handle_t ih;
ipmp_qcontext_t qcontext = IPMP_QCONTEXT_SNAP;
- ipmpstat_ofmt_t *ofmt;
- ipmpstat_field_t *fields = NULL;
ipmpstat_cbfunc_t *cbfunc;
ipmpstat_walker_t *walker;
+ char errbuf[OFMT_BUFSIZE];
if ((progname = strrchr(argv[0], '/')) == NULL)
progname = argv[0];
@@ -237,6 +217,7 @@ main(int argc, char **argv)
break;
case 'P':
opt |= IPMPSTAT_OPT_PARSABLE;
+ ofmtflags |= OFMT_PARSABLE;
break;
case 'o':
ofields = optarg;
@@ -273,13 +254,20 @@ main(int argc, char **argv)
if (argc > optind || fields == NULL)
usage();
- if (opt & IPMPSTAT_OPT_PARSABLE) {
- if (ofields == NULL) {
- die("output field list (-o) required in parsable "
- "output mode\n");
- } else if (strcasecmp(ofields, "all") == 0) {
- die("\"all\" not allowed in parsable output mode\n");
- }
+ /*
+ * Open a handle to the formatted output engine.
+ */
+ ofmterr = ofmt_open(ofields, fields, ofmtflags, IPMPSTAT_NCOL, &ofmt);
+ if (ofmterr != OFMT_SUCCESS) {
+ /*
+ * If some fields were badly formed in human-friendly mode, we
+ * emit a warning and continue. Otherwise exit immediately.
+ */
+ (void) ofmt_strerror(ofmt, ofmterr, errbuf, sizeof (errbuf));
+ if (ofmterr != OFMT_EBADFIELDS || (opt & IPMPSTAT_OPT_PARSABLE))
+ die("%s\n", errbuf);
+ else
+ warn("%s\n", errbuf);
}
/*
@@ -287,7 +275,6 @@ main(int argc, char **argv)
* is used to redisplay the output headers when necessary.
*/
(void) sigset(SIGWINCH, sighandler);
- sighandler(SIGWINCH);
if ((err = ipmp_open(&ih)) != IPMP_SUCCESS)
die_ipmperr(err, "cannot create IPMP handle");
@@ -296,12 +283,6 @@ main(int argc, char **argv)
die("cannot contact in.mpathd(1M) -- is IPMP in use?\n");
/*
- * Create the ofmt linked list that will eventually be passed to
- * to ofmt_output() to output the fields.
- */
- ofmt = ofmt_create(ofields, fields);
-
- /*
* If we've been asked to display probes, then call the probe output
* function. Otherwise, snapshot IPMP state (or use live state) and
* invoke the specified walker with the specified callback function.
@@ -318,7 +299,7 @@ main(int argc, char **argv)
(*walker)(ih, cbfunc, ofmt);
}
- ofmt_destroy(ofmt);
+ ofmt_close(ofmt);
ipmp_close(ih);
return (EXIT_SUCCESS);
@@ -430,24 +411,27 @@ walk_addr_cbfunc(ipmp_handle_t ih, void *infop, void *arg)
}
}
-static void
-sfunc_nvwarn(const char *nvname, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_nvwarn(const char *nvname)
{
warn("cannot retrieve %s\n", nvname);
- (void) strlcpy(buf, "?", bufsize);
+ return (B_FALSE);
}
-static void
-sfunc_addr_address(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_addr_address(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
ipmp_addrinfo_t *adinfop = arg->sa_data;
sockaddr2str(&adinfop->ad_addr, buf, bufsize);
+ return (B_TRUE);
}
-static void
-sfunc_addr_group(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_addr_group(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
int err;
ipmp_addrinfo_t *adinfop = arg->sa_data;
ipmp_groupinfo_t *grinfop;
@@ -456,32 +440,37 @@ sfunc_addr_group(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
if (err != IPMP_SUCCESS) {
warn_ipmperr(err, "cannot get info for group `%s'",
adinfop->ad_group);
- (void) strlcpy(buf, "?", bufsize);
- return;
+ return (B_FALSE);
}
(void) strlcpy(buf, grinfop->gr_ifname, bufsize);
ipmp_freegroupinfo(grinfop);
+ return (B_TRUE);
}
-static void
-sfunc_addr_state(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_addr_state(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
ipmp_addrinfo_t *adinfop = arg->sa_data;
enum2str(addr_state, adinfop->ad_state, buf, bufsize);
+ return (B_TRUE);
}
-static void
-sfunc_addr_inbound(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_addr_inbound(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
ipmp_addrinfo_t *adinfop = arg->sa_data;
(void) strlcpy(buf, adinfop->ad_binding, bufsize);
+ return (B_TRUE);
}
-static void
-sfunc_addr_outbound(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_addr_outbound(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
int err;
uint_t i, nactive = 0;
ipmp_ifinfo_t *ifinfop;
@@ -490,14 +479,14 @@ sfunc_addr_outbound(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
ipmp_groupinfo_t *grinfop;
if (adinfop->ad_state == IPMP_ADDR_DOWN)
- return;
+ return (B_TRUE);
/*
* If there's no inbound interface for this address, there can't
* be any outbound traffic.
*/
if (adinfop->ad_binding[0] == '\0')
- return;
+ return (B_TRUE);
/*
* The address can use any active interface in the group, so
@@ -507,8 +496,7 @@ sfunc_addr_outbound(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
if (err != IPMP_SUCCESS) {
warn_ipmperr(err, "cannot get info for group `%s'",
adinfop->ad_group);
- (void) strlcpy(buf, "?", bufsize);
- return;
+ return (B_FALSE);
}
iflistp = grinfop->gr_iflistp;
@@ -528,46 +516,56 @@ sfunc_addr_outbound(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
ipmp_freeifinfo(ifinfop);
}
ipmp_freegroupinfo(grinfop);
+ return (B_TRUE);
}
-static void
-sfunc_group_name(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_group_name(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
ipmp_groupinfo_t *grinfop = arg->sa_data;
(void) strlcpy(buf, grinfop->gr_name, bufsize);
+ return (B_TRUE);
}
-static void
-sfunc_group_ifname(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_group_ifname(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
ipmp_groupinfo_t *grinfop = arg->sa_data;
(void) strlcpy(buf, grinfop->gr_ifname, bufsize);
+ return (B_TRUE);
}
-static void
-sfunc_group_state(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_group_state(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
ipmp_groupinfo_t *grinfop = arg->sa_data;
enum2str(group_state, grinfop->gr_state, buf, bufsize);
+ return (B_TRUE);
}
-static void
-sfunc_group_fdt(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_group_fdt(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
ipmp_groupinfo_t *grinfop = arg->sa_data;
if (grinfop->gr_fdt == 0)
- return;
+ return (B_TRUE);
(void) snprintf(buf, bufsize, "%.2fs", MS2FLOATSEC(grinfop->gr_fdt));
+ return (B_TRUE);
}
-static void
-sfunc_group_interfaces(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_group_interfaces(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
int err;
uint_t i;
char *active, *inactive, *unusable;
@@ -627,30 +625,36 @@ sfunc_group_interfaces(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
(void) strlcat(buf, unusable, bufsize);
(void) strlcat(buf, "]", bufsize);
}
+ return (B_TRUE);
}
-static void
-sfunc_if_name(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_if_name(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
ipmp_ifinfo_t *ifinfop = arg->sa_data;
(void) strlcpy(buf, ifinfop->if_name, bufsize);
+ return (B_TRUE);
}
-static void
-sfunc_if_active(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_if_active(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
ipmp_ifinfo_t *ifinfop = arg->sa_data;
if (ifinfop->if_flags & IPMP_IFFLAG_ACTIVE)
(void) strlcpy(buf, "yes", bufsize);
else
(void) strlcpy(buf, "no", bufsize);
+ return (B_TRUE);
}
-static void
-sfunc_if_group(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_if_group(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
int err;
ipmp_ifinfo_t *ifinfop = arg->sa_data;
ipmp_groupinfo_t *grinfop;
@@ -659,17 +663,18 @@ sfunc_if_group(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
if (err != IPMP_SUCCESS) {
warn_ipmperr(err, "cannot get info for group `%s'",
ifinfop->if_group);
- (void) strlcpy(buf, "?", bufsize);
- return;
+ return (B_TRUE);
}
(void) strlcpy(buf, grinfop->gr_ifname, bufsize);
ipmp_freegroupinfo(grinfop);
+ return (B_TRUE);
}
-static void
-sfunc_if_flags(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_if_flags(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
int err;
ipmp_ifinfo_t *ifinfop = arg->sa_data;
ipmp_groupinfo_t *grinfop;
@@ -695,7 +700,7 @@ sfunc_if_flags(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
if (err != IPMP_SUCCESS) {
warn_ipmperr(err, "cannot get broadcast/multicast info for "
"group `%s'", ifinfop->if_group);
- return;
+ return (B_TRUE);
}
if (strcmp(grinfop->gr_m4ifname, ifinfop->if_name) == 0)
@@ -708,175 +713,174 @@ sfunc_if_flags(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
buf[IPMPSTAT_BFLAG_INDEX] = 'b';
ipmp_freegroupinfo(grinfop);
+ return (B_TRUE);
}
-static void
-sfunc_if_link(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_if_link(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
ipmp_ifinfo_t *ifinfop = arg->sa_data;
enum2str(if_link, ifinfop->if_linkstate, buf, bufsize);
+ return (B_TRUE);
}
-static void
-sfunc_if_probe(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_if_probe(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
ipmp_ifinfo_t *ifinfop = arg->sa_data;
enum2str(if_probe, ifinfop->if_probestate, buf, bufsize);
+ return (B_TRUE);
}
-static void
-sfunc_if_state(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_if_state(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
ipmp_ifinfo_t *ifinfop = arg->sa_data;
enum2str(if_state, ifinfop->if_state, buf, bufsize);
+ return (B_TRUE);
}
-static void
-sfunc_probe_id(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_probe_id(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
uint32_t probe_id;
nvlist_t *nvl = arg->sa_data;
- if (nvlist_lookup_uint32(nvl, IPMP_PROBE_ID, &probe_id) != 0) {
- sfunc_nvwarn("IPMP_PROBE_ID", buf, bufsize);
- return;
- }
+ if (nvlist_lookup_uint32(nvl, IPMP_PROBE_ID, &probe_id) != 0)
+ return (sfunc_nvwarn("IPMP_PROBE_ID"));
(void) snprintf(buf, bufsize, "%u", probe_id);
+ return (B_TRUE);
}
-static void
-sfunc_probe_ifname(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_probe_ifname(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
char *ifname;
nvlist_t *nvl = arg->sa_data;
- if (nvlist_lookup_string(nvl, IPMP_IF_NAME, &ifname) != 0) {
- sfunc_nvwarn("IPMP_IF_NAME", buf, bufsize);
- return;
- }
+ if (nvlist_lookup_string(nvl, IPMP_IF_NAME, &ifname) != 0)
+ return (sfunc_nvwarn("IPMP_IF_NAME"));
(void) strlcpy(buf, ifname, bufsize);
+ return (B_TRUE);
}
-static void
-sfunc_probe_time(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_probe_time(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
hrtime_t start;
nvlist_t *nvl = arg->sa_data;
- if (nvlist_lookup_hrtime(nvl, IPMP_PROBE_START_TIME, &start) != 0) {
- sfunc_nvwarn("IPMP_PROBE_START_TIME", buf, bufsize);
- return;
- }
+ if (nvlist_lookup_hrtime(nvl, IPMP_PROBE_START_TIME, &start) != 0)
+ return (sfunc_nvwarn("IPMP_PROBE_START_TIME"));
(void) snprintf(buf, bufsize, "%.2fs",
(float)(start - probe_output_start) / NANOSEC);
+ return (B_TRUE);
}
-static void
-sfunc_probe_target(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_probe_target(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
uint_t nelem;
struct sockaddr_storage *target;
nvlist_t *nvl = arg->sa_data;
if (nvlist_lookup_byte_array(nvl, IPMP_PROBE_TARGET,
- (uchar_t **)&target, &nelem) != 0) {
- sfunc_nvwarn("IPMP_PROBE_TARGET", buf, bufsize);
- return;
- }
+ (uchar_t **)&target, &nelem) != 0)
+ return (sfunc_nvwarn("IPMP_PROBE_TARGET"));
sockaddr2str(target, buf, bufsize);
+ return (B_TRUE);
}
-static void
-sfunc_probe_rtt(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_probe_rtt(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
hrtime_t start, ackproc;
nvlist_t *nvl = arg->sa_data;
uint32_t state;
- if (nvlist_lookup_uint32(nvl, IPMP_PROBE_STATE, &state) != 0) {
- sfunc_nvwarn("IPMP_PROBE_STATE", buf, bufsize);
- return;
- }
+ if (nvlist_lookup_uint32(nvl, IPMP_PROBE_STATE, &state) != 0)
+ return (sfunc_nvwarn("IPMP_PROBE_STATE"));
if (state != IPMP_PROBE_ACKED)
- return;
+ return (B_TRUE);
- if (nvlist_lookup_hrtime(nvl, IPMP_PROBE_START_TIME, &start) != 0) {
- sfunc_nvwarn("IPMP_PROBE_START_TIME", buf, bufsize);
- return;
- }
+ if (nvlist_lookup_hrtime(nvl, IPMP_PROBE_START_TIME, &start) != 0)
+ return (sfunc_nvwarn("IPMP_PROBE_START_TIME"));
- if (nvlist_lookup_hrtime(nvl, IPMP_PROBE_ACKPROC_TIME, &ackproc) != 0) {
- sfunc_nvwarn("IPMP_PROBE_ACKPROC_TIME", buf, bufsize);
- return;
- }
+ if (nvlist_lookup_hrtime(nvl, IPMP_PROBE_ACKPROC_TIME, &ackproc) != 0)
+ return (sfunc_nvwarn("IPMP_PROBE_ACKPROC_TIME"));
(void) snprintf(buf, bufsize, "%.2fms", NS2FLOATMS(ackproc - start));
+ return (B_TRUE);
}
-static void
-sfunc_probe_netrtt(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_probe_netrtt(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
hrtime_t sent, ackrecv;
nvlist_t *nvl = arg->sa_data;
uint32_t state;
- if (nvlist_lookup_uint32(nvl, IPMP_PROBE_STATE, &state) != 0) {
- sfunc_nvwarn("IPMP_PROBE_STATE", buf, bufsize);
- return;
- }
+ if (nvlist_lookup_uint32(nvl, IPMP_PROBE_STATE, &state) != 0)
+ return (sfunc_nvwarn("IPMP_PROBE_STATE"));
if (state != IPMP_PROBE_ACKED)
- return;
+ return (B_TRUE);
- if (nvlist_lookup_hrtime(nvl, IPMP_PROBE_SENT_TIME, &sent) != 0) {
- sfunc_nvwarn("IPMP_PROBE_SENT_TIME", buf, bufsize);
- return;
- }
+ if (nvlist_lookup_hrtime(nvl, IPMP_PROBE_SENT_TIME, &sent) != 0)
+ return (sfunc_nvwarn("IPMP_PROBE_SENT_TIME"));
- if (nvlist_lookup_hrtime(nvl, IPMP_PROBE_ACKRECV_TIME, &ackrecv) != 0) {
- sfunc_nvwarn("IPMP_PROBE_ACKRECV_TIME", buf, bufsize);
- return;
- }
+ if (nvlist_lookup_hrtime(nvl, IPMP_PROBE_ACKRECV_TIME, &ackrecv) != 0)
+ return (sfunc_nvwarn("IPMP_PROBE_ACKRECV_TIME"));
(void) snprintf(buf, bufsize, "%.2fms", NS2FLOATMS(ackrecv - sent));
+ return (B_TRUE);
}
-static void
-sfunc_probe_rttavg(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_probe_rttavg(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
int64_t rttavg;
nvlist_t *nvl = arg->sa_data;
- if (nvlist_lookup_int64(nvl, IPMP_PROBE_TARGET_RTTAVG, &rttavg) != 0) {
- sfunc_nvwarn("IPMP_PROBE_TARGET_RTTAVG", buf, bufsize);
- return;
- }
+ if (nvlist_lookup_int64(nvl, IPMP_PROBE_TARGET_RTTAVG, &rttavg) != 0)
+ return (sfunc_nvwarn("IPMP_PROBE_TARGET_RTTAVG"));
if (rttavg != 0)
(void) snprintf(buf, bufsize, "%.2fms", NS2FLOATMS(rttavg));
+ return (B_TRUE);
}
-static void
-sfunc_probe_rttdev(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_probe_rttdev(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
int64_t rttdev;
nvlist_t *nvl = arg->sa_data;
- if (nvlist_lookup_int64(nvl, IPMP_PROBE_TARGET_RTTDEV, &rttdev) != 0) {
- sfunc_nvwarn("IPMP_PROBE_TARGET_RTTDEV", buf, bufsize);
- return;
- }
+ if (nvlist_lookup_int64(nvl, IPMP_PROBE_TARGET_RTTDEV, &rttdev) != 0)
+ return (sfunc_nvwarn("IPMP_PROBE_TARGET_RTTDEV"));
if (rttdev != 0)
(void) snprintf(buf, bufsize, "%.2fms", NS2FLOATMS(rttdev));
+ return (B_TRUE);
}
/* ARGSUSED */
@@ -891,7 +895,7 @@ probe_enabled_cbfunc(ipmp_handle_t ih, void *infop, void *arg)
}
static void
-probe_output(ipmp_handle_t ih, ipmpstat_ofmt_t *ofmt)
+probe_output(ipmp_handle_t ih, ofmt_handle_t ofmt)
{
char sub[MAX_SUBID_LEN];
evchan_t *evch;
@@ -972,34 +976,41 @@ out:
return (0);
}
-static void
-sfunc_targ_ifname(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_targ_ifname(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
ipmp_targinfo_t *targinfop = arg->sa_data;
(void) strlcpy(buf, targinfop->it_name, bufsize);
+ return (B_TRUE);
}
-static void
-sfunc_targ_mode(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_targ_mode(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
ipmp_targinfo_t *targinfop = arg->sa_data;
enum2str(targ_mode, targinfop->it_targmode, buf, bufsize);
+ return (B_TRUE);
}
-static void
-sfunc_targ_testaddr(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_targ_testaddr(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
ipmp_targinfo_t *targinfop = arg->sa_data;
if (targinfop->it_targmode != IPMP_TARG_DISABLED)
sockaddr2str(&targinfop->it_testaddr, buf, bufsize);
+ return (B_TRUE);
}
-static void
-sfunc_targ_targets(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
+static boolean_t
+sfunc_targ_targets(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
+ ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
uint_t i;
char *targname = alloca(bufsize);
ipmp_targinfo_t *targinfop = arg->sa_data;
@@ -1011,6 +1022,7 @@ sfunc_targ_targets(ipmpstat_sfunc_arg_t *arg, char *buf, uint_t bufsize)
if ((i + 1) < targlistp->al_naddr)
(void) strlcat(buf, " ", bufsize);
}
+ return (B_TRUE);
}
static void
@@ -1039,227 +1051,18 @@ targinfo_output_cbfunc(ipmp_handle_t ih, void *infop, void *arg)
}
/*
- * Creates an ipmpstat_ofmt_t field list from the comma-separated list of
- * user-specified fields passed via `ofields'. The table of known fields
- * (and their attributes) is passed via `fields'.
- */
-static ipmpstat_ofmt_t *
-ofmt_create(const char *ofields, ipmpstat_field_t fields[])
-{
- char *token, *lasts, *ofields_dup;
- const char *fieldname;
- ipmpstat_ofmt_t *ofmt, *ofmt_head = NULL, *ofmt_tail;
- ipmpstat_field_t *fieldp;
- uint_t cols = 0;
-
- /*
- * If "-o" was omitted or "-o all" was specified, build a list of
- * field names. If "-o" was omitted, stop building the list when
- * we run out of columns.
- */
- if (ofields == NULL || strcasecmp(ofields, "all") == 0) {
- for (fieldp = fields; fieldp->f_name != NULL; fieldp++) {
- cols += fieldp->f_width;
- if (ofields == NULL && cols > IPMPSTAT_NCOL)
- break;
-
- if ((ofmt = calloc(sizeof (*ofmt), 1)) == NULL)
- die("cannot allocate output format list");
-
- ofmt->o_field = fieldp;
- if (ofmt_head == NULL) {
- ofmt_head = ofmt;
- ofmt_tail = ofmt;
- } else {
- ofmt_tail->o_next = ofmt;
- ofmt_tail = ofmt;
- }
- }
- return (ofmt_head);
- }
-
- if ((ofields_dup = strdup(ofields)) == NULL)
- die("cannot allocate output format list");
-
- token = ofields_dup;
- while ((fieldname = strtok_r(token, ",", &lasts)) != NULL) {
- token = NULL;
-
- if ((fieldp = field_find(fields, fieldname)) == NULL) {
- /*
- * Since machine parsers are unlikely to be able to
- * gracefully handle missing fields, die if we're in
- * parsable mode. Otherwise, just print a warning.
- */
- if (opt & IPMPSTAT_OPT_PARSABLE)
- die("unknown output field `%s'\n", fieldname);
-
- warn("ignoring unknown output field `%s'\n", fieldname);
- continue;
- }
-
- if ((ofmt = calloc(sizeof (*ofmt), 1)) == NULL)
- die("cannot allocate output format list");
-
- ofmt->o_field = fieldp;
- if (ofmt_head == NULL) {
- ofmt_head = ofmt;
- ofmt_tail = ofmt;
- } else {
- ofmt_tail->o_next = ofmt;
- ofmt_tail = ofmt;
- }
- }
-
- free(ofields_dup);
- if (ofmt_head == NULL)
- die("no valid output fields specified\n");
-
- return (ofmt_head);
-}
-
-/*
- * Destroys the provided `ofmt' field list.
+ * Outputs one row of values. The values to output are obtained through the
+ * callback function pointers. The actual values are computed from the `ih'
+ * and `arg' structures passed to the callback function.
*/
static void
-ofmt_destroy(ipmpstat_ofmt_t *ofmt)
+ofmt_output(const ofmt_handle_t ofmt, ipmp_handle_t ih, void *arg)
{
- ipmpstat_ofmt_t *ofmt_next;
+ ipmpstat_sfunc_arg_t sfunc_arg;
- for (; ofmt != NULL; ofmt = ofmt_next) {
- ofmt_next = ofmt->o_next;
- free(ofmt);
- }
-}
-
-/*
- * Outputs a header for the fields named by `ofmt'.
- */
-static void
-ofmt_output_header(const ipmpstat_ofmt_t *ofmt)
-{
- const ipmpstat_field_t *fieldp;
-
- for (; ofmt != NULL; ofmt = ofmt->o_next) {
- fieldp = ofmt->o_field;
-
- if (ofmt->o_next == NULL)
- (void) printf("%s", fieldp->f_name);
- else
- (void) printf("%-*s", fieldp->f_width, fieldp->f_name);
- }
- (void) printf("\n");
-}
-
-/*
- * Outputs one row of values for the fields named by `ofmt'. The values to
- * output are obtained through the `ofmt' function pointers, which are
- * indirectly passed the `ih' and `arg' structures for state; see the block
- * comment at the start of this file for details.
- */
-static void
-ofmt_output(const ipmpstat_ofmt_t *ofmt, ipmp_handle_t ih, void *arg)
-{
- int i;
- char buf[1024];
- boolean_t escsep;
- static int nrow;
- const char *value;
- uint_t width, valwidth;
- uint_t compress, overflow = 0;
- const ipmpstat_field_t *fieldp;
- ipmpstat_sfunc_arg_t sfunc_arg;
-
- /*
- * For each screenful of data, display the header.
- */
- if ((nrow++ % winsize.ws_row) == 0 && !(opt & IPMPSTAT_OPT_PARSABLE)) {
- ofmt_output_header(ofmt);
- nrow++;
- }
-
- /*
- * Check if we'll be displaying multiple fields per line, and thus
- * need to escape the field separator.
- */
- escsep = (ofmt != NULL && ofmt->o_next != NULL);
-
- for (; ofmt != NULL; ofmt = ofmt->o_next) {
- fieldp = ofmt->o_field;
-
- sfunc_arg.sa_ih = ih;
- sfunc_arg.sa_data = arg;
-
- buf[0] = '\0';
- (*fieldp->f_sfunc)(&sfunc_arg, buf, sizeof (buf));
-
- if (opt & IPMPSTAT_OPT_PARSABLE) {
- for (i = 0; buf[i] != '\0'; i++) {
- if (escsep && (buf[i] == ':' || buf[i] == '\\'))
- (void) putchar('\\');
- (void) putchar(buf[i]);
- }
- if (ofmt->o_next != NULL)
- (void) putchar(':');
- } else {
- value = (buf[0] == '\0') ? "--" : buf;
-
- /*
- * To avoid needless line-wraps, for the last field,
- * don't include any trailing whitespace.
- */
- if (ofmt->o_next == NULL) {
- (void) printf("%s", value);
- continue;
- }
-
- /*
- * For other fields, grow the width as necessary to
- * ensure the value completely fits. However, if
- * there's unused whitespace in subsequent fields,
- * then "compress" that whitespace to attempt to get
- * the columns to line up again.
- */
- width = fieldp->f_width;
- valwidth = strlen(value);
-
- if (valwidth + overflow >= width) {
- overflow += valwidth - width + 1;
- (void) printf("%s ", value);
- continue;
- }
-
- if (overflow > 0) {
- compress = MIN(overflow, width - valwidth);
- overflow -= compress;
- width -= compress;
- }
- (void) printf("%-*s", width, value);
- }
- }
- (void) printf("\n");
-
- /*
- * In case stdout has been redirected to e.g. a pipe, flush stdout so
- * that commands can act on our output immediately.
- */
- (void) fflush(stdout);
-}
-
-/*
- * Searches the `fields' array for a field matching `fieldname'. Returns
- * a pointer to that field on success, or NULL on failure.
- */
-static ipmpstat_field_t *
-field_find(ipmpstat_field_t *fields, const char *fieldname)
-{
- ipmpstat_field_t *fieldp;
-
- for (fieldp = fields; fieldp->f_name != NULL; fieldp++) {
- if (strcasecmp(fieldp->f_name, fieldname) == 0)
- return (fieldp);
- }
- return (NULL);
+ sfunc_arg.sa_ih = ih;
+ sfunc_arg.sa_data = arg;
+ ofmt_print(ofmt, &sfunc_arg);
}
/*
@@ -1318,11 +1121,7 @@ sighandler(int sig)
{
assert(sig == SIGWINCH);
- if (ioctl(1, TIOCGWINSZ, &winsize) == -1 ||
- winsize.ws_col == 0 || winsize.ws_row == 0) {
- winsize.ws_col = 80;
- winsize.ws_row = 24;
- }
+ ofmt_update_winsize(ofmt);
}
static void
@@ -1415,94 +1214,94 @@ die_ipmperr(int ipmperr, const char *format, ...)
exit(EXIT_FAILURE);
}
-static ipmpstat_field_t addr_fields[] = {
- { "ADDRESS", 26, sfunc_addr_address },
- { "STATE", 7, sfunc_addr_state },
- { "GROUP", 12, sfunc_addr_group },
- { "INBOUND", 12, sfunc_addr_inbound },
- { "OUTBOUND", 23, sfunc_addr_outbound },
- { NULL, 0, NULL }
+static ofmt_field_t addr_fields[] = {
+ { "ADDRESS", 26, 0, sfunc_addr_address },
+ { "STATE", 7, 0, sfunc_addr_state },
+ { "GROUP", 12, 0, sfunc_addr_group },
+ { "INBOUND", 12, 0, sfunc_addr_inbound },
+ { "OUTBOUND", 23, 0, sfunc_addr_outbound },
+ { NULL, 0, 0, NULL }
};
-static ipmpstat_field_t group_fields[] = {
- { "GROUP", 12, sfunc_group_ifname },
- { "GROUPNAME", 12, sfunc_group_name },
- { "STATE", 10, sfunc_group_state },
- { "FDT", 10, sfunc_group_fdt },
- { "INTERFACES", 30, sfunc_group_interfaces },
- { NULL, 0, NULL }
+static ofmt_field_t group_fields[] = {
+ { "GROUP", 12, 0, sfunc_group_ifname },
+ { "GROUPNAME", 12, 0, sfunc_group_name },
+ { "STATE", 10, 0, sfunc_group_state },
+ { "FDT", 10, 0, sfunc_group_fdt },
+ { "INTERFACES", 30, 0, sfunc_group_interfaces },
+ { NULL, 0, 0, NULL }
};
-static ipmpstat_field_t if_fields[] = {
- { "INTERFACE", 12, sfunc_if_name },
- { "ACTIVE", 8, sfunc_if_active },
- { "GROUP", 12, sfunc_if_group },
- { "FLAGS", 10, sfunc_if_flags },
- { "LINK", 10, sfunc_if_link },
- { "PROBE", 10, sfunc_if_probe },
- { "STATE", 10, sfunc_if_state },
- { NULL, 0, NULL }
+static ofmt_field_t if_fields[] = {
+ { "INTERFACE", 12, 0, sfunc_if_name },
+ { "ACTIVE", 8, 0, sfunc_if_active },
+ { "GROUP", 12, 0, sfunc_if_group },
+ { "FLAGS", 10, 0, sfunc_if_flags },
+ { "LINK", 10, 0, sfunc_if_link },
+ { "PROBE", 10, 0, sfunc_if_probe },
+ { "STATE", 10, 0, sfunc_if_state },
+ { NULL, 0, 0, NULL }
};
-static ipmpstat_field_t probe_fields[] = {
- { "TIME", 10, sfunc_probe_time },
- { "INTERFACE", 12, sfunc_probe_ifname },
- { "PROBE", 7, sfunc_probe_id },
- { "NETRTT", 10, sfunc_probe_netrtt },
- { "RTT", 10, sfunc_probe_rtt },
- { "RTTAVG", 10, sfunc_probe_rttavg },
- { "TARGET", 20, sfunc_probe_target },
- { "RTTDEV", 10, sfunc_probe_rttdev },
- { NULL, 0, NULL }
+static ofmt_field_t probe_fields[] = {
+ { "TIME", 10, 0, sfunc_probe_time },
+ { "INTERFACE", 12, 0, sfunc_probe_ifname },
+ { "PROBE", 7, 0, sfunc_probe_id },
+ { "NETRTT", 10, 0, sfunc_probe_netrtt },
+ { "RTT", 10, 0, sfunc_probe_rtt },
+ { "RTTAVG", 10, 0, sfunc_probe_rttavg },
+ { "TARGET", 20, 0, sfunc_probe_target },
+ { "RTTDEV", 10, 0, sfunc_probe_rttdev },
+ { NULL, 0, 0, NULL }
};
-static ipmpstat_field_t targ_fields[] = {
- { "INTERFACE", 12, sfunc_targ_ifname },
- { "MODE", 10, sfunc_targ_mode },
- { "TESTADDR", 20, sfunc_targ_testaddr },
- { "TARGETS", 38, sfunc_targ_targets },
- { NULL, 0, NULL }
+static ofmt_field_t targ_fields[] = {
+ { "INTERFACE", 12, 0, sfunc_targ_ifname },
+ { "MODE", 10, 0, sfunc_targ_mode },
+ { "TESTADDR", 20, 0, sfunc_targ_testaddr },
+ { "TARGETS", 38, 0, sfunc_targ_targets },
+ { NULL, 0, 0, NULL }
};
static ipmpstat_enum_t addr_state[] = {
- { "up", IPMP_ADDR_UP },
- { "down", IPMP_ADDR_DOWN },
- { NULL, 0 }
+ { "up", IPMP_ADDR_UP },
+ { "down", IPMP_ADDR_DOWN },
+ { NULL, 0 }
};
static ipmpstat_enum_t group_state[] = {
- { "ok", IPMP_GROUP_OK },
- { "failed", IPMP_GROUP_FAILED },
- { "degraded", IPMP_GROUP_DEGRADED },
- { NULL, 0 }
+ { "ok", IPMP_GROUP_OK },
+ { "failed", IPMP_GROUP_FAILED },
+ { "degraded", IPMP_GROUP_DEGRADED },
+ { NULL, 0 }
};
static ipmpstat_enum_t if_link[] = {
- { "up", IPMP_LINK_UP },
- { "down", IPMP_LINK_DOWN },
- { "unknown", IPMP_LINK_UNKNOWN },
- { NULL, 0 }
+ { "up", IPMP_LINK_UP },
+ { "down", IPMP_LINK_DOWN },
+ { "unknown", IPMP_LINK_UNKNOWN },
+ { NULL, 0 }
};
static ipmpstat_enum_t if_probe[] = {
- { "ok", IPMP_PROBE_OK },
- { "failed", IPMP_PROBE_FAILED },
- { "unknown", IPMP_PROBE_UNKNOWN },
- { "disabled", IPMP_PROBE_DISABLED },
- { NULL, 0 }
+ { "ok", IPMP_PROBE_OK },
+ { "failed", IPMP_PROBE_FAILED },
+ { "unknown", IPMP_PROBE_UNKNOWN },
+ { "disabled", IPMP_PROBE_DISABLED },
+ { NULL, 0 }
};
static ipmpstat_enum_t if_state[] = {
- { "ok", IPMP_IF_OK },
- { "failed", IPMP_IF_FAILED },
- { "unknown", IPMP_IF_UNKNOWN },
- { "offline", IPMP_IF_OFFLINE },
- { NULL, 0 }
+ { "ok", IPMP_IF_OK },
+ { "failed", IPMP_IF_FAILED },
+ { "unknown", IPMP_IF_UNKNOWN },
+ { "offline", IPMP_IF_OFFLINE },
+ { NULL, 0 }
};
static ipmpstat_enum_t targ_mode[] = {
- { "disabled", IPMP_TARG_DISABLED },
- { "routes", IPMP_TARG_ROUTES },
- { "multicast", IPMP_TARG_MULTICAST },
- { NULL, 0 }
+ { "disabled", IPMP_TARG_DISABLED },
+ { "routes", IPMP_TARG_ROUTES },
+ { "multicast", IPMP_TARG_MULTICAST },
+ { NULL, 0 }
};
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/ipmpstat/ipmpstat.xcl b/usr/src/cmd/cmd-inet/usr.sbin/ipmpstat/ipmpstat.xcl
index e2398aaf64..3948397e7f 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/ipmpstat/ipmpstat.xcl
+++ b/usr/src/cmd/cmd-inet/usr.sbin/ipmpstat/ipmpstat.xcl
@@ -27,15 +27,14 @@ msgid "%.2fms"
msgid "%.2fs"
msgid "%d-%s"
msgid "%s"
+msgid "%s\n"
msgid "%s "
msgid "%s: "
msgid "%u"
msgid "("
msgid ")"
msgid ","
-msgid "--"
msgid ": %s\n"
-msgid "?"
msgid "["
msgid "]"
msgid "<%d>"
diff --git a/usr/src/cmd/dladm/dladm.c b/usr/src/cmd/dladm/dladm.c
index d8be7d92da..d98fba69f1 100644
--- a/usr/src/cmd/dladm/dladm.c
+++ b/usr/src/cmd/dladm/dladm.c
@@ -65,8 +65,8 @@
#include <arpa/inet.h>
#include <net/if_types.h>
#include <stddef.h>
+#include <ofmt.h>
-#define STR_UNDEF_VAL "--"
#define MAXPORT 256
#define MAXVNIC 256
#define BUFLEN(lim, ptr) (((lim) > (ptr)) ? ((lim) - (ptr)) : 0)
@@ -74,141 +74,23 @@
#define SMF_UPGRADE_FILE "/var/svc/profile/upgrade"
#define SMF_UPGRADEDATALINK_FILE "/var/svc/profile/upgrade_datalink"
#define SMF_DLADM_UPGRADE_MSG " # added by dladm(1M)"
+#define DLADM_DEFAULT_COL 80
-#define CMD_TYPE_ANY 0xffffffff
+/*
+ * used by the wifi show-* commands to set up ofmt_field_t structures.
+ */
#define WIFI_CMD_SCAN 0x00000001
#define WIFI_CMD_SHOW 0x00000002
#define WIFI_CMD_ALL (WIFI_CMD_SCAN | WIFI_CMD_SHOW)
-/*
- * Data structures and routines for printing output.
- * All non-parseable output is assumed to be in a columnar format.
- * Multiple fields in parsable output are separated by ':'; single
- * field output is printed as-is.
- *
- * Each sub-command is associated with a global array of pointers,
- * print_field_t *fields[], where the print_field_t contains information
- * about the format in which the output is to be printed.
- *
- * Sub-commands may be implemented in one of two ways:
- * (i) the implementation could get all field values into a character
- * buffer, with pf_offset containing the offset (for pf_name) within
- * the buffer. The sub-command would make the needed system calls
- * to obtain all possible column values and then invoke the
- * dladm_print_field() function to print the specific fields
- * requested in the command line. See the comments for dladm_print_field
- * for further details.
- * (ii) Alternatively, each fields[i] entry could store a pf_index value
- * that uniquely identifies the column to be printed. The implementation
- * of the sub-command would then invoke dladm_print_output() with a
- * callback function whose semantics are described below (see comments
- * for dladm_print_output())
- *
- * Thus, an implementation of a sub-command must provide the following:
- *
- * static print_field_t sub_command_fields[] = {
- * {<name>, <header>,<field width>, <offset_or_index>, cmdtype},
- * :
- * {<name>, <header>,<field width>, <offset_or_index>, cmdtype}
- * };
- *
- * #define SUB_COMMAND_MAX_FIELDS sizeof \
- * (sub_comand_fields) / sizeof (print_field_t))
- *
- * print_state_t sub_command_print_state;
- *
- * The function that parses command line arguments (typically
- * do_sub_command()) should then contain an invocation like:
- *
- * fields = parse_output_fields(fields_str, sub_command_fields,
- * SUB_COMMAND_MAX_FIELDS, CMD_TYPE_ANY, &nfields);
- *
- * and store the resulting fields and nfields value in a print_state_t
- * structure tracked for the command.
- *
- * sub_command_print_state.ps_fields = fields;
- * sub_command_print_state.ps_nfields = nfields;
- *
- * To print the column header for the output, the print_header()
- * function must then be invoked by do_sub_command().
- *
- * Then if method (i) is used for the sub_command, the do_sub_command()
- * function should make the necessary system calls to fill up the buffer
- * and then invoke dladm_print_field(). An example of this method is
- * the implementation of do_show_link() and show_link();
- *
- * If method (ii) is used, do_sub_command should invoke dladm_print_output()
- * with a callback function that will be called for each field to be printed.
- * The callback function will be passed a pointer to the print_field_t
- * for the field, and the pf_index may then be used to identify the
- * system call required to find the value to be printed.
- */
-
-typedef struct print_field_s {
- const char *pf_name; /* name of column to be printed */
- const char *pf_header; /* header for this column */
- uint_t pf_width;
- union {
- uint_t _pf_index; /* private index for sub-command */
- size_t _pf_offset;
- }_pf_un;
-#define pf_index _pf_un._pf_index
-#define pf_offset _pf_un._pf_offset;
- uint_t pf_cmdtype;
-} print_field_t;
-
-/*
- * The state of the output is tracked in a print_state_t structure.
- * Each ps_fields[i] entry points at the global print_field_t array for
- * the sub-command, where ps_nfields is the number of requested fields.
- */
-typedef struct print_state_s {
- print_field_t **ps_fields;
- uint_t ps_nfields;
- boolean_t ps_lastfield;
- uint_t ps_overflow;
-} print_state_t;
-
-typedef char *(*print_callback_t)(print_field_t *, void *);
-static print_field_t **parse_output_fields(char *, print_field_t *, int,
- uint_t, uint_t *);
-/*
- * print the header for the output
- */
-static void print_header(print_state_t *);
-static void print_field(print_state_t *, print_field_t *, const char *,
- boolean_t);
-
-/*
- * to print output values, call dladm_print_output with a callback
- * function (*func)() that should parse the args and return an
- * unformatted character buffer with the value to be printed.
- *
- * dladm_print_output() prints the character buffer using the formatting
- * information provided in the print_field_t for that column.
- */
-static void dladm_print_output(print_state_t *, boolean_t,
- print_callback_t, void *);
-
-/*
- * helper function that, when invoked as dladm_print_field(pf, buf)
- * prints string which is offset by pf->pf_offset within buf.
- */
-static char *dladm_print_field(print_field_t *, void *);
-
-
-#define MAX_FIELD_LEN 32
-
-
typedef struct show_state {
boolean_t ls_firstonly;
boolean_t ls_donefirst;
pktsum_t ls_prevstats;
uint32_t ls_flags;
dladm_status_t ls_status;
- print_state_t ls_print;
- boolean_t ls_parseable;
- boolean_t ls_printheader;
+ ofmt_handle_t ls_ofmt;
+ boolean_t ls_parsable;
boolean_t ls_mac;
boolean_t ls_hwgrp;
} show_state_t;
@@ -217,14 +99,13 @@ typedef struct show_grp_state {
pktsum_t gs_prevstats[MAXPORT];
uint32_t gs_flags;
dladm_status_t gs_status;
- boolean_t gs_parseable;
+ boolean_t gs_parsable;
boolean_t gs_lacp;
boolean_t gs_extended;
boolean_t gs_stats;
boolean_t gs_firstonly;
boolean_t gs_donefirst;
- boolean_t gs_printheader;
- print_state_t gs_print;
+ ofmt_handle_t gs_ofmt;
} show_grp_state_t;
typedef struct show_vnic_state {
@@ -232,8 +113,7 @@ typedef struct show_vnic_state {
datalink_id_t vs_link_id;
char vs_vnic[MAXLINKNAMELEN];
char vs_link[MAXLINKNAMELEN];
- boolean_t vs_parseable;
- boolean_t vs_printheader;
+ boolean_t vs_parsable;
boolean_t vs_found;
boolean_t vs_firstonly;
boolean_t vs_donefirst;
@@ -244,18 +124,28 @@ typedef struct show_vnic_state {
boolean_t vs_etherstub;
dladm_status_t vs_status;
uint32_t vs_flags;
- print_state_t vs_print;
+ ofmt_handle_t vs_ofmt;
} show_vnic_state_t;
typedef struct show_usage_state_s {
boolean_t us_plot;
- boolean_t us_parseable;
+ boolean_t us_parsable;
boolean_t us_printheader;
boolean_t us_first;
boolean_t us_showall;
- print_state_t us_print;
+ ofmt_handle_t us_ofmt;
} show_usage_state_t;
+/*
+ * callback functions for printing output and error diagnostics.
+ */
+static ofmt_cb_t print_default_cb, print_link_stats_cb, print_linkprop_cb;
+static ofmt_cb_t print_lacp_cb, print_phys_one_mac_cb;
+static ofmt_cb_t print_xaggr_cb, print_aggr_stats_cb;
+static ofmt_cb_t print_phys_one_hwgrp_cb, print_wlan_attr_cb;
+static ofmt_cb_t print_wifi_status_cb, print_link_attr_cb;
+static void dladm_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t);
+
typedef void cmdfunc_t(int, char **, const char *);
static cmdfunc_t do_show_link, do_show_wifi, do_show_phys;
@@ -420,6 +310,7 @@ static const struct option show_lopts[] = {
{"statistics", no_argument, 0, 's'},
{"continuous", no_argument, 0, 'S'},
{"interval", required_argument, 0, 'i'},
+ {"parsable", no_argument, 0, 'p'},
{"parseable", no_argument, 0, 'p'},
{"extended", no_argument, 0, 'x'},
{"output", required_argument, 0, 'o'},
@@ -433,12 +324,14 @@ static const struct option prop_longopts[] = {
{"output", required_argument, 0, 'o' },
{"root-dir", required_argument, 0, 'R' },
{"prop", required_argument, 0, 'p' },
+ {"parsable", no_argument, 0, 'c' },
{"parseable", no_argument, 0, 'c' },
{"persistent", no_argument, 0, 'P' },
{ 0, 0, 0, 0 }
};
static const struct option wifi_longopts[] = {
+ {"parsable", no_argument, 0, 'p' },
{"parseable", no_argument, 0, 'p' },
{"output", required_argument, 0, 'o' },
{"essid", required_argument, 0, 'e' },
@@ -457,6 +350,7 @@ static const struct option wifi_longopts[] = {
{ 0, 0, 0, 0 }
};
static const struct option showeth_lopts[] = {
+ {"parsable", no_argument, 0, 'p' },
{"parseable", no_argument, 0, 'p' },
{"extended", no_argument, 0, 'x' },
{"output", required_argument, 0, 'o' },
@@ -505,31 +399,33 @@ typedef struct ether_fields_buf_s
char eth_rem_fault[16];
} ether_fields_buf_t;
-static print_field_t ether_fields[] = {
-/* name, header, field width, offset, cmdtype */
-{ "link", "LINK", 15,
- offsetof(ether_fields_buf_t, eth_link), CMD_TYPE_ANY},
-{ "ptype", "PTYPE", 8,
- offsetof(ether_fields_buf_t, eth_ptype), CMD_TYPE_ANY},
-{ "state", "STATE", 8,
- offsetof(ether_fields_buf_t, eth_state), CMD_TYPE_ANY},
-{ "auto", "AUTO", 5,
- offsetof(ether_fields_buf_t, eth_autoneg), CMD_TYPE_ANY},
-{ "speed-duplex", "SPEED-DUPLEX", 31,
- offsetof(ether_fields_buf_t, eth_spdx), CMD_TYPE_ANY},
-{ "pause", "PAUSE", 6,
- offsetof(ether_fields_buf_t, eth_pause), CMD_TYPE_ANY},
-{ "rem_fault", "REM_FAULT", 16,
- offsetof(ether_fields_buf_t, eth_rem_fault), CMD_TYPE_ANY}}
+static ofmt_field_t ether_fields[] = {
+/* name, field width, offset callback */
+{ "LINK", 16,
+ offsetof(ether_fields_buf_t, eth_link), print_default_cb},
+{ "PTYPE", 9,
+ offsetof(ether_fields_buf_t, eth_ptype), print_default_cb},
+{ "STATE", 9,
+ offsetof(ether_fields_buf_t, eth_state),
+ print_default_cb},
+{ "AUTO", 6,
+ offsetof(ether_fields_buf_t, eth_autoneg), print_default_cb},
+{ "SPEED-DUPLEX", 32,
+ offsetof(ether_fields_buf_t, eth_spdx), print_default_cb},
+{ "PAUSE", 7,
+ offsetof(ether_fields_buf_t, eth_pause), print_default_cb},
+{ "REM_FAULT", 17,
+ offsetof(ether_fields_buf_t, eth_rem_fault), print_default_cb},
+{NULL, 0,
+ 0, NULL}}
;
-#define ETHER_MAX_FIELDS (sizeof (ether_fields) / sizeof (print_field_t))
typedef struct print_ether_state {
const char *es_link;
- boolean_t es_parseable;
+ boolean_t es_parsable;
boolean_t es_header;
boolean_t es_extended;
- print_state_t es_print;
+ ofmt_handle_t es_ofmt;
} print_ether_state_t;
/*
@@ -545,24 +441,21 @@ typedef enum {
LINK_S_OERRORS
} link_s_field_index_t;
-static print_field_t link_s_fields[] = {
-/* name, header, field width, index, cmdtype */
-{ "link", "LINK", 15, LINK_S_LINK, CMD_TYPE_ANY},
-{ "ipackets", "IPACKETS", 10, LINK_S_IPKTS, CMD_TYPE_ANY},
-{ "rbytes", "RBYTES", 8, LINK_S_RBYTES, CMD_TYPE_ANY},
-{ "ierrors", "IERRORS", 10, LINK_S_IERRORS, CMD_TYPE_ANY},
-{ "opackets", "OPACKETS", 12, LINK_S_OPKTS, CMD_TYPE_ANY},
-{ "obytes", "OBYTES", 12, LINK_S_OBYTES, CMD_TYPE_ANY},
-{ "oerrors", "OERRORS", 8, LINK_S_OERRORS, CMD_TYPE_ANY}}
+static ofmt_field_t link_s_fields[] = {
+/* name, field width, index, callback */
+{ "LINK", 15, LINK_S_LINK, print_link_stats_cb},
+{ "IPACKETS", 10, LINK_S_IPKTS, print_link_stats_cb},
+{ "RBYTES", 8, LINK_S_RBYTES, print_link_stats_cb},
+{ "IERRORS", 10, LINK_S_IERRORS, print_link_stats_cb},
+{ "OPACKETS", 12, LINK_S_OPKTS, print_link_stats_cb},
+{ "OBYTES", 12, LINK_S_OBYTES, print_link_stats_cb},
+{ "OERRORS", 8, LINK_S_OERRORS, print_link_stats_cb}}
;
-#define LINK_S_MAX_FIELDS \
- (sizeof (link_s_fields) / sizeof (print_field_t))
typedef struct link_args_s {
char *link_s_link;
pktsum_t *link_s_psum;
} link_args_t;
-static char *print_link_stats(print_field_t *, void *);
/*
* buffer used by print functions for show-{link,phys,vlan} commands.
@@ -585,20 +478,20 @@ typedef struct link_fields_buf_s {
/*
* structures for 'dladm show-link'
*/
-static print_field_t link_fields[] = {
-/* name, header, field width, offset, cmdtype */
-{ "link", "LINK", 11,
- offsetof(link_fields_buf_t, link_name), CMD_TYPE_ANY},
-{ "class", "CLASS", 8,
- offsetof(link_fields_buf_t, link_class), CMD_TYPE_ANY},
-{ "mtu", "MTU", 6,
- offsetof(link_fields_buf_t, link_mtu), CMD_TYPE_ANY},
-{ "state", "STATE", 8,
- offsetof(link_fields_buf_t, link_state), CMD_TYPE_ANY},
-{ "over", "OVER", DLPI_LINKNAME_MAX,
- offsetof(link_fields_buf_t, link_over), CMD_TYPE_ANY}}
+static ofmt_field_t link_fields[] = {
+/* name, field width, index, callback */
+{ "LINK", 12,
+ offsetof(link_fields_buf_t, link_name), print_default_cb},
+{ "CLASS", 9,
+ offsetof(link_fields_buf_t, link_class), print_default_cb},
+{ "MTU", 7,
+ offsetof(link_fields_buf_t, link_mtu), print_default_cb},
+{ "STATE", 9,
+ offsetof(link_fields_buf_t, link_state), print_default_cb},
+{ "OVER", DLPI_LINKNAME_MAX,
+ offsetof(link_fields_buf_t, link_over), print_default_cb},
+{ NULL, 0, 0, NULL}}
;
-#define DEV_LINK_FIELDS (sizeof (link_fields) / sizeof (print_field_t))
/*
* structures for 'dladm show-aggr'
@@ -619,25 +512,25 @@ typedef struct laggr_args_s {
dladm_status_t *laggr_status;
pktsum_t *laggr_pktsumtot; /* -s only */
pktsum_t *laggr_prevstats; /* -s only */
- boolean_t laggr_parseable;
+ boolean_t laggr_parsable;
} laggr_args_t;
-static print_field_t laggr_fields[] = {
-/* name, header, field width, offset, cmdtype */
-{ "link", "LINK", 15,
- offsetof(laggr_fields_buf_t, laggr_name), CMD_TYPE_ANY},
-{ "policy", "POLICY", 8,
- offsetof(laggr_fields_buf_t, laggr_policy), CMD_TYPE_ANY},
-{ "addrpolicy", "ADDRPOLICY", ETHERADDRL * 3 + 2,
- offsetof(laggr_fields_buf_t, laggr_addrpolicy), CMD_TYPE_ANY},
-{ "lacpactivity", "LACPACTIVITY", 13,
- offsetof(laggr_fields_buf_t, laggr_lacpactivity), CMD_TYPE_ANY},
-{ "lacptimer", "LACPTIMER", 11,
- offsetof(laggr_fields_buf_t, laggr_lacptimer), CMD_TYPE_ANY},
-{ "flags", "FLAGS", 7,
- offsetof(laggr_fields_buf_t, laggr_flags), CMD_TYPE_ANY}}
+static ofmt_field_t laggr_fields[] = {
+/* name, field width, offset, callback */
+{ "LINK", 16,
+ offsetof(laggr_fields_buf_t, laggr_name), print_default_cb},
+{ "POLICY", 9,
+ offsetof(laggr_fields_buf_t, laggr_policy), print_default_cb},
+{ "ADDRPOLICY", ETHERADDRL * 3 + 3,
+ offsetof(laggr_fields_buf_t, laggr_addrpolicy), print_default_cb},
+{ "LACPACTIVITY", 14,
+ offsetof(laggr_fields_buf_t, laggr_lacpactivity), print_default_cb},
+{ "LACPTIMER", 12,
+ offsetof(laggr_fields_buf_t, laggr_lacptimer), print_default_cb},
+{ "FLAGS", 8,
+ offsetof(laggr_fields_buf_t, laggr_flags), print_default_cb},
+{ NULL, 0, 0, NULL}}
;
-#define LAGGR_MAX_FIELDS (sizeof (laggr_fields) / sizeof (print_field_t))
/*
* structures for 'dladm show-aggr -x'.
@@ -652,18 +545,17 @@ typedef enum {
AGGR_X_PORTSTATE
} aggr_x_field_index_t;
-static print_field_t aggr_x_fields[] = {
-/* name, header, field width, index, cmdtype */
-{ "link", "LINK", 11, AGGR_X_LINK, CMD_TYPE_ANY},
-{ "port", "PORT", 14, AGGR_X_PORT, CMD_TYPE_ANY},
-{ "speed", "SPEED", 4, AGGR_X_SPEED, CMD_TYPE_ANY},
-{ "duplex", "DUPLEX", 9, AGGR_X_DUPLEX, CMD_TYPE_ANY},
-{ "state", "STATE", 9, AGGR_X_STATE, CMD_TYPE_ANY},
-{ "address", "ADDRESS", 18, AGGR_X_ADDRESS, CMD_TYPE_ANY},
-{ "portstate", "PORTSTATE", 15, AGGR_X_PORTSTATE, CMD_TYPE_ANY}}
+static ofmt_field_t aggr_x_fields[] = {
+/* name, field width, index callback */
+{ "LINK", 12, AGGR_X_LINK, print_xaggr_cb},
+{ "PORT", 15, AGGR_X_PORT, print_xaggr_cb},
+{ "SPEED", 5, AGGR_X_SPEED, print_xaggr_cb},
+{ "DUPLEX", 10, AGGR_X_DUPLEX, print_xaggr_cb},
+{ "STATE", 10, AGGR_X_STATE, print_xaggr_cb},
+{ "ADDRESS", 19, AGGR_X_ADDRESS, print_xaggr_cb},
+{ "PORTSTATE", 16, AGGR_X_PORTSTATE, print_xaggr_cb},
+{ NULL, 0, 0, NULL}}
;
-#define AGGR_X_MAX_FIELDS \
- (sizeof (aggr_x_fields) / sizeof (print_field_t))
/*
* structures for 'dladm show-aggr -s'.
@@ -679,27 +571,17 @@ typedef enum {
AGGR_S_OPKTDIST
} aggr_s_field_index_t;
-static print_field_t aggr_s_fields[] = {
-/* name, header, field width, index, cmdtype */
-{ "link", "LINK", 11, AGGR_S_LINK,
- CMD_TYPE_ANY},
-{ "port", "PORT", 9, AGGR_S_PORT,
- CMD_TYPE_ANY},
-{ "ipackets", "IPACKETS", 7, AGGR_S_IPKTS,
- CMD_TYPE_ANY},
-{ "rbytes", "RBYTES", 7, AGGR_S_RBYTES,
- CMD_TYPE_ANY},
-{ "opackets", "OPACKETS", 7, AGGR_S_OPKTS,
- CMD_TYPE_ANY},
-{ "obytes", "OBYTES", 7, AGGR_S_OBYTES,
- CMD_TYPE_ANY},
-{ "ipktdist", "IPKTDIST", 8, AGGR_S_IPKTDIST,
- CMD_TYPE_ANY},
-{ "opktdist", "OPKTDIST", 14, AGGR_S_OPKTDIST,
- CMD_TYPE_ANY}}
+static ofmt_field_t aggr_s_fields[] = {
+{ "LINK", 12, AGGR_S_LINK, print_aggr_stats_cb},
+{ "PORT", 10, AGGR_S_PORT, print_aggr_stats_cb},
+{ "IPACKETS", 8, AGGR_S_IPKTS, print_aggr_stats_cb},
+{ "RBYTES", 8, AGGR_S_RBYTES, print_aggr_stats_cb},
+{ "OPACKETS", 8, AGGR_S_OPKTS, print_aggr_stats_cb},
+{ "OBYTES", 8, AGGR_S_OBYTES, print_aggr_stats_cb},
+{ "IPKTDIST", 9, AGGR_S_IPKTDIST, print_aggr_stats_cb},
+{ "OPKTDIST", 15, AGGR_S_OPKTDIST, print_aggr_stats_cb},
+{ NULL, 0, 0, NULL}}
;
-#define AGGR_S_MAX_FIELDS \
- (sizeof (aggr_s_fields) / sizeof (print_field_t))
/*
* structures for 'dladm show-aggr -L'.
@@ -715,50 +597,41 @@ typedef enum {
AGGR_L_EXPIRED
} aggr_l_field_index_t;
-static print_field_t aggr_l_fields[] = {
-/* name, header, field width, index, cmdtype */
-{ "link", "LINK", 11, AGGR_L_LINK,
- CMD_TYPE_ANY},
-{ "port", "PORT", 12, AGGR_L_PORT,
- CMD_TYPE_ANY},
-{ "aggregatable", "AGGREGATABLE", 12, AGGR_L_AGGREGATABLE,
- CMD_TYPE_ANY},
-{ "sync", "SYNC", 4, AGGR_L_SYNC,
- CMD_TYPE_ANY},
-{ "coll", "COLL", 4, AGGR_L_COLL,
- CMD_TYPE_ANY},
-{ "dist", "DIST", 4, AGGR_L_DIST,
- CMD_TYPE_ANY},
-{ "defaulted", "DEFAULTED", 9, AGGR_L_DEFAULTED,
- CMD_TYPE_ANY},
-{ "expired", "EXPIRED", 14, AGGR_L_EXPIRED,
- CMD_TYPE_ANY}}
+static ofmt_field_t aggr_l_fields[] = {
+/* name, field width, index */
+{ "LINK", 12, AGGR_L_LINK, print_lacp_cb},
+{ "PORT", 13, AGGR_L_PORT, print_lacp_cb},
+{ "AGGREGATABLE", 13, AGGR_L_AGGREGATABLE, print_lacp_cb},
+{ "SYNC", 5, AGGR_L_SYNC, print_lacp_cb},
+{ "COLL", 5, AGGR_L_COLL, print_lacp_cb},
+{ "DIST", 5, AGGR_L_DIST, print_lacp_cb},
+{ "DEFAULTED", 10, AGGR_L_DEFAULTED, print_lacp_cb},
+{ "EXPIRED", 15, AGGR_L_EXPIRED, print_lacp_cb},
+{ NULL, 0, 0, NULL}}
;
-#define AGGR_L_MAX_FIELDS \
- (sizeof (aggr_l_fields) / sizeof (print_field_t))
/*
* structures for 'dladm show-phys'
*/
-static print_field_t phys_fields[] = {
-/* name, header, field width, offset, cmdtype */
-{ "link", "LINK", 12,
- offsetof(link_fields_buf_t, link_name), CMD_TYPE_ANY},
-{ "media", "MEDIA", 20,
- offsetof(link_fields_buf_t, link_phys_media), CMD_TYPE_ANY},
-{ "state", "STATE", 10,
- offsetof(link_fields_buf_t, link_phys_state), CMD_TYPE_ANY},
-{ "speed", "SPEED", 6,
- offsetof(link_fields_buf_t, link_phys_speed), CMD_TYPE_ANY},
-{ "duplex", "DUPLEX", 9,
- offsetof(link_fields_buf_t, link_phys_duplex), CMD_TYPE_ANY},
-{ "device", "DEVICE", 12,
- offsetof(link_fields_buf_t, link_phys_device), CMD_TYPE_ANY},
-{ "flags", "FLAGS", 6,
- offsetof(link_fields_buf_t, link_flags), CMD_TYPE_ANY}}
+static ofmt_field_t phys_fields[] = {
+/* name, field width, offset */
+{ "LINK", 13,
+ offsetof(link_fields_buf_t, link_name), print_default_cb},
+{ "MEDIA", 21,
+ offsetof(link_fields_buf_t, link_phys_media), print_default_cb},
+{ "STATE", 11,
+ offsetof(link_fields_buf_t, link_phys_state), print_default_cb},
+{ "SPEED", 7,
+ offsetof(link_fields_buf_t, link_phys_speed), print_default_cb},
+{ "DUPLEX", 10,
+ offsetof(link_fields_buf_t, link_phys_duplex), print_default_cb},
+{ "DEVICE", 13,
+ offsetof(link_fields_buf_t, link_phys_device), print_default_cb},
+{ "FLAGS", 7,
+ offsetof(link_fields_buf_t, link_flags), print_default_cb},
+{ NULL, 0, NULL, 0}}
;
-#define PHYS_MAX_FIELDS (sizeof (phys_fields) / sizeof (print_field_t))
/*
* structures for 'dladm show-phys -m'
@@ -772,15 +645,15 @@ typedef enum {
PHYS_M_CLIENT
} phys_m_field_index_t;
-static print_field_t phys_m_fields[] = {
-/* name, header, field width, offset, cmdtype */
-{ "link", "LINK", 12, PHYS_M_LINK, CMD_TYPE_ANY},
-{ "slot", "SLOT", 8, PHYS_M_SLOT, CMD_TYPE_ANY},
-{ "address", "ADDRESS", 18, PHYS_M_ADDRESS, CMD_TYPE_ANY},
-{ "inuse", "INUSE", 4, PHYS_M_INUSE, CMD_TYPE_ANY},
-{ "client", "CLIENT", 12, PHYS_M_CLIENT, CMD_TYPE_ANY}}
+static ofmt_field_t phys_m_fields[] = {
+/* name, field width, offset */
+{ "LINK", 13, PHYS_M_LINK, print_phys_one_mac_cb},
+{ "SLOT", 9, PHYS_M_SLOT, print_phys_one_mac_cb},
+{ "ADDRESS", 19, PHYS_M_ADDRESS, print_phys_one_mac_cb},
+{ "INUSE", 5, PHYS_M_INUSE, print_phys_one_mac_cb},
+{ "CLIENT", 13, PHYS_M_CLIENT, print_phys_one_mac_cb},
+{ NULL, 0, 0, NULL}}
;
-#define PHYS_M_MAX_FIELDS (sizeof (phys_m_fields) / sizeof (print_field_t))
/*
* structures for 'dladm show-phys -H'
@@ -794,49 +667,55 @@ typedef enum {
PHYS_H_CLIENTS
} phys_h_field_index_t;
-static print_field_t phys_h_fields[] = {
-/* name, header, field width, offset, cmdtype */
-{ "link", "LINK", 12, PHYS_H_LINK, CMD_TYPE_ANY},
-{ "group", "GROUP", 8, PHYS_H_GROUP, CMD_TYPE_ANY},
-{ "grouptype", "TYPE", 6, PHYS_H_GRPTYPE, CMD_TYPE_ANY},
-{ "rings", "NUM-RINGS", 16, PHYS_H_RINGS, CMD_TYPE_ANY},
-{ "clients", "CLIENTS", 20, PHYS_H_CLIENTS, CMD_TYPE_ANY}}
+static ofmt_field_t phys_h_fields[] = {
+{ "LINK", 13, PHYS_H_LINK, print_phys_one_hwgrp_cb},
+{ "GROUP", 9, PHYS_H_GROUP, print_phys_one_hwgrp_cb},
+{ "GROUPTYPE", 7, PHYS_H_GRPTYPE, print_phys_one_hwgrp_cb},
+{ "RINGS", 17, PHYS_H_RINGS, print_phys_one_hwgrp_cb},
+{ "CLIENTS", 21, PHYS_H_CLIENTS, print_phys_one_hwgrp_cb},
+{ NULL, 0, 0, NULL}}
;
-#define PHYS_H_MAX_FIELDS (sizeof (phys_h_fields) / sizeof (print_field_t))
/*
* structures for 'dladm show-vlan'
*/
-static print_field_t vlan_fields[] = {
-/* name, header, field width, offset, cmdtype */
-{ "link", "LINK", 15,
- offsetof(link_fields_buf_t, link_name), CMD_TYPE_ANY},
-{ "vid", "VID", 8,
- offsetof(link_fields_buf_t, link_vlan_vid), CMD_TYPE_ANY},
-{ "over", "OVER", 12,
- offsetof(link_fields_buf_t, link_over), CMD_TYPE_ANY},
-{ "flags", "FLAGS", 6,
- offsetof(link_fields_buf_t, link_flags), CMD_TYPE_ANY}}
+static ofmt_field_t vlan_fields[] = {
+{ "LINK", 16,
+ offsetof(link_fields_buf_t, link_name), print_default_cb},
+{ "VID", 9,
+ offsetof(link_fields_buf_t, link_vlan_vid), print_default_cb},
+{ "OVER", 13,
+ offsetof(link_fields_buf_t, link_over), print_default_cb},
+{ "FLAGS", 7,
+ offsetof(link_fields_buf_t, link_flags), print_default_cb},
+{ NULL, 0, 0, NULL}}
;
-#define VLAN_MAX_FIELDS (sizeof (vlan_fields) / sizeof (print_field_t))
+/*
+ * structures common to 'dladm scan-wifi' and 'dladm show-wifi'
+ * callback will be determined in parse_wifi_fields.
+ */
+static ofmt_field_t wifi_common_fields[] = {
+{ "LINK", 11, 0, NULL},
+{ "ESSID", 20, DLADM_WLAN_ATTR_ESSID, NULL},
+{ "BSSID", 18, DLADM_WLAN_ATTR_BSSID, NULL},
+{ "IBSSID", 18, DLADM_WLAN_ATTR_BSSID, NULL},
+{ "MODE", 7, DLADM_WLAN_ATTR_MODE, NULL},
+{ "SPEED", 7, DLADM_WLAN_ATTR_SPEED, NULL},
+{ "BSSTYPE", 9, DLADM_WLAN_ATTR_BSSTYPE, NULL},
+{ "SEC", 7, DLADM_WLAN_ATTR_SECMODE, NULL},
+{ "STRENGTH", 11, DLADM_WLAN_ATTR_STRENGTH, NULL},
+{ NULL, 0, 0, NULL}};
/*
- * structures for 'dladm show-wifi'
+ * the 'show-wifi' command supports all the fields in wifi_common_fields
+ * plus the AUTH and STATUS fields.
*/
-static print_field_t wifi_fields[] = {
-{ "link", "LINK", 10, 0, WIFI_CMD_ALL},
-{ "essid", "ESSID", 19, DLADM_WLAN_ATTR_ESSID, WIFI_CMD_ALL},
-{ "bssid", "BSSID/IBSSID", 17, DLADM_WLAN_ATTR_BSSID, WIFI_CMD_ALL},
-{ "ibssid", "BSSID/IBSSID", 17, DLADM_WLAN_ATTR_BSSID, WIFI_CMD_ALL},
-{ "mode", "MODE", 6, DLADM_WLAN_ATTR_MODE, WIFI_CMD_ALL},
-{ "speed", "SPEED", 6, DLADM_WLAN_ATTR_SPEED, WIFI_CMD_ALL},
-{ "auth", "AUTH", 8, DLADM_WLAN_ATTR_AUTH, WIFI_CMD_SHOW},
-{ "bsstype", "BSSTYPE", 8, DLADM_WLAN_ATTR_BSSTYPE, WIFI_CMD_ALL},
-{ "sec", "SEC", 6, DLADM_WLAN_ATTR_SECMODE, WIFI_CMD_ALL},
-{ "status", "STATUS", 17, DLADM_WLAN_LINKATTR_STATUS, WIFI_CMD_SHOW},
-{ "strength", "STRENGTH", 10, DLADM_WLAN_ATTR_STRENGTH, WIFI_CMD_ALL}}
-;
+static ofmt_field_t wifi_show_fields[A_CNT(wifi_common_fields) + 2] = {
+{ "AUTH", 9, DLADM_WLAN_ATTR_AUTH, NULL},
+{ "STATUS", 18, DLADM_WLAN_LINKATTR_STATUS, print_wifi_status_cb},
+/* copy wifi_common_fields here */
+};
static char *all_scan_wifi_fields =
"link,essid,bssid,sec,strength,mode,speed,bsstype";
@@ -847,8 +726,6 @@ static char *def_scan_wifi_fields =
static char *def_show_wifi_fields =
"link,status,essid,sec,strength,mode,speed";
-#define WIFI_MAX_FIELDS (sizeof (wifi_fields) / sizeof (print_field_t))
-
/*
* structures for 'dladm show-linkprop'
*/
@@ -861,17 +738,16 @@ typedef enum {
LINKPROP_POSSIBLE
} linkprop_field_index_t;
-static print_field_t linkprop_fields[] = {
-/* name, header, field width, index, cmdtype */
-{ "link", "LINK", 12, LINKPROP_LINK, CMD_TYPE_ANY},
-{ "property", "PROPERTY", 15, LINKPROP_PROPERTY, CMD_TYPE_ANY},
-{ "perm", "PERM", 4, LINKPROP_PERM, CMD_TYPE_ANY},
-{ "value", "VALUE", 14, LINKPROP_VALUE, CMD_TYPE_ANY},
-{ "default", "DEFAULT", 14, LINKPROP_DEFAULT, CMD_TYPE_ANY},
-{ "possible", "POSSIBLE", 20, LINKPROP_POSSIBLE, CMD_TYPE_ANY}}
+static ofmt_field_t linkprop_fields[] = {
+/* name, field width, index */
+{ "LINK", 13, LINKPROP_LINK, print_linkprop_cb},
+{ "PROPERTY", 16, LINKPROP_PROPERTY, print_linkprop_cb},
+{ "PERM", 5, LINKPROP_PERM, print_linkprop_cb},
+{ "VALUE", 15, LINKPROP_VALUE, print_linkprop_cb},
+{ "DEFAULT", 15, LINKPROP_DEFAULT, print_linkprop_cb},
+{ "POSSIBLE", 21, LINKPROP_POSSIBLE, print_linkprop_cb},
+{ NULL, 0, 0, NULL}}
;
-#define LINKPROP_MAX_FIELDS \
- (sizeof (linkprop_fields) / sizeof (print_field_t))
#define MAX_PROP_LINE 512
@@ -880,12 +756,12 @@ typedef struct show_linkprop_state {
char *ls_line;
char **ls_propvals;
dladm_arg_list_t *ls_proplist;
- boolean_t ls_parseable;
+ boolean_t ls_parsable;
boolean_t ls_persist;
boolean_t ls_header;
dladm_status_t ls_status;
dladm_status_t ls_retstatus;
- print_state_t ls_print;
+ ofmt_handle_t ls_ofmt;
} show_linkprop_state_t;
typedef struct set_linkprop_state {
@@ -909,16 +785,16 @@ typedef struct secobj_fields_buf_s {
char ss_class[20];
char ss_val[30];
} secobj_fields_buf_t;
-static print_field_t secobj_fields[] = {
-/* name, header, field width, offset, cmdtype */
-{ "object", "OBJECT", 20,
- offsetof(secobj_fields_buf_t, ss_obj_name), CMD_TYPE_ANY},
-{ "class", "CLASS", 20,
- offsetof(secobj_fields_buf_t, ss_class), CMD_TYPE_ANY},
-{ "value", "VALUE", 30,
- offsetof(secobj_fields_buf_t, ss_val), CMD_TYPE_ANY}}
+
+static ofmt_field_t secobj_fields[] = {
+{ "OBJECT", 21,
+ offsetof(secobj_fields_buf_t, ss_obj_name), print_default_cb},
+{ "CLASS", 21,
+ offsetof(secobj_fields_buf_t, ss_class), print_default_cb},
+{ "VALUE", 31,
+ offsetof(secobj_fields_buf_t, ss_val), print_default_cb},
+{ NULL, 0, 0, NULL}}
;
-#define DEV_SOBJ_FIELDS (sizeof (secobj_fields) / sizeof (print_field_t))
/*
* structures for 'dladm show-vnic'
@@ -933,22 +809,21 @@ typedef struct vnic_fields_buf_s
char vnic_vid[6];
} vnic_fields_buf_t;
-static print_field_t vnic_fields[] = {
-/* name, header, field width, offset, cmdtype */
-{ "link", "LINK", 12,
- offsetof(vnic_fields_buf_t, vnic_link), CMD_TYPE_ANY},
-{ "over", "OVER", 12,
- offsetof(vnic_fields_buf_t, vnic_over), CMD_TYPE_ANY},
-{ "speed", "SPEED", 6,
- offsetof(vnic_fields_buf_t, vnic_speed), CMD_TYPE_ANY},
-{ "macaddress", "MACADDRESS", 20,
- offsetof(vnic_fields_buf_t, vnic_macaddr), CMD_TYPE_ANY},
-{ "macaddrtype", "MACADDRTYPE", 19,
- offsetof(vnic_fields_buf_t, vnic_macaddrtype), CMD_TYPE_ANY},
-{ "vid", "VID", 6,
- offsetof(vnic_fields_buf_t, vnic_vid), CMD_TYPE_ANY}}
+static ofmt_field_t vnic_fields[] = {
+{ "LINK", 13,
+ offsetof(vnic_fields_buf_t, vnic_link), print_default_cb},
+{ "OVER", 13,
+ offsetof(vnic_fields_buf_t, vnic_over), print_default_cb},
+{ "SPEED", 7,
+ offsetof(vnic_fields_buf_t, vnic_speed), print_default_cb},
+{ "MACADDRESS", 21,
+ offsetof(vnic_fields_buf_t, vnic_macaddr), print_default_cb},
+{ "MACADDRTYPE", 20,
+ offsetof(vnic_fields_buf_t, vnic_macaddrtype), print_default_cb},
+{ "VID", 7,
+ offsetof(vnic_fields_buf_t, vnic_vid), print_default_cb},
+{ NULL, 0, 0, NULL}}
;
-#define VNIC_MAX_FIELDS (sizeof (vnic_fields) / sizeof (print_field_t))
/*
* structures for 'dladm show-usage'
@@ -964,25 +839,24 @@ typedef struct usage_fields_buf_s {
char usage_bandwidth[14];
} usage_fields_buf_t;
-static print_field_t usage_fields[] = {
-/* name, header, field width, offset, cmdtype */
-{ "link", "LINK", 12,
- offsetof(usage_fields_buf_t, usage_link), CMD_TYPE_ANY},
-{ "duration", "DURATION", 10,
- offsetof(usage_fields_buf_t, usage_duration), CMD_TYPE_ANY},
-{ "ipackets", "IPACKETS", 9,
- offsetof(usage_fields_buf_t, usage_ipackets), CMD_TYPE_ANY},
-{ "rbytes", "RBYTES", 10,
- offsetof(usage_fields_buf_t, usage_rbytes), CMD_TYPE_ANY},
-{ "opackets", "OPACKETS", 9,
- offsetof(usage_fields_buf_t, usage_opackets), CMD_TYPE_ANY},
-{ "obytes", "OBYTES", 10,
- offsetof(usage_fields_buf_t, usage_obytes), CMD_TYPE_ANY},
-{ "bandwidth", "BANDWIDTH", 14,
- offsetof(usage_fields_buf_t, usage_bandwidth), CMD_TYPE_ANY}}
+static ofmt_field_t usage_fields[] = {
+{ "LINK", 13,
+ offsetof(usage_fields_buf_t, usage_link), print_default_cb},
+{ "DURATION", 11,
+ offsetof(usage_fields_buf_t, usage_duration), print_default_cb},
+{ "IPACKETS", 10,
+ offsetof(usage_fields_buf_t, usage_ipackets), print_default_cb},
+{ "RBYTES", 11,
+ offsetof(usage_fields_buf_t, usage_rbytes), print_default_cb},
+{ "OPACKETS", 10,
+ offsetof(usage_fields_buf_t, usage_opackets), print_default_cb},
+{ "OBYTES", 11,
+ offsetof(usage_fields_buf_t, usage_obytes), print_default_cb},
+{ "BANDWIDTH", 15,
+ offsetof(usage_fields_buf_t, usage_bandwidth), print_default_cb},
+{ NULL, 0, 0, NULL}}
;
-#define USAGE_MAX_FIELDS (sizeof (usage_fields) / sizeof (print_field_t))
/*
* structures for 'dladm show-usage link'
@@ -997,25 +871,23 @@ typedef struct usage_l_fields_buf_s {
char usage_l_bandwidth[14];
} usage_l_fields_buf_t;
-static print_field_t usage_l_fields[] = {
-/* name, header, field width, offset, cmdtype */
-{ "link", "LINK", 12,
- offsetof(usage_l_fields_buf_t, usage_l_link), CMD_TYPE_ANY},
-{ "start", "START", 13,
- offsetof(usage_l_fields_buf_t, usage_l_stime), CMD_TYPE_ANY},
-{ "end", "END", 13,
- offsetof(usage_l_fields_buf_t, usage_l_etime), CMD_TYPE_ANY},
-{ "rbytes", "RBYTES", 8,
- offsetof(usage_l_fields_buf_t, usage_l_rbytes), CMD_TYPE_ANY},
-{ "obytes", "OBYTES", 8,
- offsetof(usage_l_fields_buf_t, usage_l_obytes), CMD_TYPE_ANY},
-{ "bandwidth", "BANDWIDTH", 14,
- offsetof(usage_l_fields_buf_t, usage_l_bandwidth), CMD_TYPE_ANY}}
+static ofmt_field_t usage_l_fields[] = {
+/* name, field width, offset */
+{ "LINK", 13,
+ offsetof(usage_l_fields_buf_t, usage_l_link), print_default_cb},
+{ "START", 14,
+ offsetof(usage_l_fields_buf_t, usage_l_stime), print_default_cb},
+{ "END", 14,
+ offsetof(usage_l_fields_buf_t, usage_l_etime), print_default_cb},
+{ "RBYTES", 9,
+ offsetof(usage_l_fields_buf_t, usage_l_rbytes), print_default_cb},
+{ "OBYTES", 9,
+ offsetof(usage_l_fields_buf_t, usage_l_obytes), print_default_cb},
+{ "BANDWIDTH", 15,
+ offsetof(usage_l_fields_buf_t, usage_l_bandwidth), print_default_cb},
+{ NULL, 0, 0, NULL}}
;
-#define USAGE_L_MAX_FIELDS \
- (sizeof (usage_l_fields) /sizeof (print_field_t))
-
static char *progname;
static sig_atomic_t signalled;
@@ -1193,14 +1065,7 @@ show_usage_time(dladm_usage_t *usage, void *arg)
(void) snprintf(ubuf.usage_l_bandwidth, sizeof (ubuf.usage_l_bandwidth),
"%s Mbps", dladm_bw2str(usage->du_bandwidth, buf));
- if (!state->us_parseable && !state->us_printheader) {
- print_header(&state->us_print);
- state->us_printheader = B_TRUE;
- }
-
- dladm_print_output(&state->us_print, state->us_parseable,
- dladm_print_field, (void *)&ubuf);
-
+ ofmt_print(state->us_ofmt, &ubuf);
return (DLADM_STATUS_OK);
}
@@ -1243,13 +1108,7 @@ show_usage_res(dladm_usage_t *usage, void *arg)
(void) snprintf(ubuf.usage_bandwidth, sizeof (ubuf.usage_bandwidth),
"%s Mbps", dladm_bw2str(usage->du_bandwidth, buf));
- if (!state->us_parseable && !state->us_printheader) {
- print_header(&state->us_print);
- state->us_printheader = B_TRUE;
- }
-
- dladm_print_output(&state->us_print, state->us_parseable,
- dladm_print_field, (void *)&ubuf);
+ ofmt_print(state->us_ofmt, &ubuf);
return (DLADM_STATUS_OK);
}
@@ -1279,15 +1138,14 @@ do_show_usage(int argc, char *argv[], const char *use)
boolean_t F_arg = B_FALSE;
char *fields_str = NULL;
char *formatspec_str = NULL;
- print_field_t **fields;
- uint_t nfields;
- char *all_fields =
- "link,duration,ipackets,rbytes,opackets,obytes,bandwidth";
char *all_l_fields =
"link,start,end,rbytes,obytes,bandwidth";
+ ofmt_handle_t ofmt;
+ ofmt_status_t oferr;
+ uint_t ofmtflags = 0;
bzero(&state, sizeof (show_usage_state_t));
- state.us_parseable = B_FALSE;
+ state.us_parsable = B_FALSE;
state.us_printheader = B_FALSE;
state.us_plot = B_FALSE;
state.us_first = B_TRUE;
@@ -1339,30 +1197,27 @@ do_show_usage(int argc, char *argv[], const char *use)
}
}
+ if (F_arg && d_arg)
+ die("incompatible -d and -F options");
+
+ if (F_arg && valid_formatspec(formatspec_str) == B_FALSE)
+ die("Format specifier %s not supported", formatspec_str);
+
+ if (state.us_parsable)
+ ofmtflags |= OFMT_PARSABLE;
+
if (resource == NULL && stime == NULL && etime == NULL) {
- if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0))
- fields_str = all_fields;
- fields = parse_output_fields(fields_str, usage_fields,
- USAGE_MAX_FIELDS, CMD_TYPE_ANY, &nfields);
+ oferr = ofmt_open(fields_str, usage_fields, ofmtflags, 0,
+ &ofmt);
} else {
if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0))
fields_str = all_l_fields;
- fields = parse_output_fields(fields_str, usage_l_fields,
- USAGE_L_MAX_FIELDS, CMD_TYPE_ANY, &nfields);
- }
+ oferr = ofmt_open(fields_str, usage_l_fields, ofmtflags, 0,
+ &ofmt);
- if (fields == NULL) {
- die("invalid fields(s) specified");
- return;
}
- state.us_print.ps_fields = fields;
- state.us_print.ps_nfields = nfields;
-
- if (F_arg && d_arg)
- die("incompatible -d and -F options");
-
- if (F_arg && valid_formatspec(formatspec_str) == B_FALSE)
- die("Format specifier %s not supported", formatspec_str);
+ dladm_ofmt_check(oferr, state.us_parsable, ofmt);
+ state.us_ofmt = ofmt;
if (d_arg) {
/* Print log dates */
@@ -1385,6 +1240,7 @@ do_show_usage(int argc, char *argv[], const char *use)
if (status != DLADM_STATUS_OK)
die_dlerr(status, "show-usage");
+ ofmt_close(ofmt);
}
static void
@@ -2233,11 +2089,7 @@ print_link_topology(show_state_t *state, datalink_id_t linkid,
dladm_status_t status = DLADM_STATUS_OK;
char tmpbuf[MAXLINKNAMELEN];
- if (!state->ls_parseable)
- (void) sprintf(lbuf->link_over, STR_UNDEF_VAL);
- else
- (void) sprintf(lbuf->link_over, "");
-
+ (void) sprintf(lbuf->link_over, "");
if (class == DATALINK_CLASS_VLAN) {
dladm_vlan_attr_t vinfo;
@@ -2389,59 +2241,46 @@ show_link(dladm_handle_t dh, datalink_id_t linkid, void *arg)
if (status != DLADM_STATUS_OK)
goto done;
- if (!state->ls_parseable && !state->ls_printheader) {
- print_header(&state->ls_print);
- state->ls_printheader = B_TRUE;
- }
-
- dladm_print_output(&state->ls_print, state->ls_parseable,
- dladm_print_field, (void *)&lbuf);
+ ofmt_print(state->ls_ofmt, &lbuf);
done:
state->ls_status = status;
return (DLADM_WALK_CONTINUE);
}
-static char *
-print_link_stats(print_field_t *pf, void *arg)
+static boolean_t
+print_link_stats_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
{
- link_args_t *largs = arg;
+ link_args_t *largs = ofarg->ofmt_cbarg;
pktsum_t *diff_stats = largs->link_s_psum;
- static char buf[DLADM_STRSIZE];
- switch (pf->pf_index) {
+ switch (ofarg->ofmt_id) {
case LINK_S_LINK:
- (void) snprintf(buf, sizeof (buf), "%s", largs->link_s_link);
+ (void) snprintf(buf, bufsize, "%s", largs->link_s_link);
break;
case LINK_S_IPKTS:
- (void) snprintf(buf, sizeof (buf), "%llu",
- diff_stats->ipackets);
+ (void) snprintf(buf, bufsize, "%llu", diff_stats->ipackets);
break;
case LINK_S_RBYTES:
- (void) snprintf(buf, sizeof (buf), "%llu",
- diff_stats->rbytes);
+ (void) snprintf(buf, bufsize, "%llu", diff_stats->rbytes);
break;
case LINK_S_IERRORS:
- (void) snprintf(buf, sizeof (buf), "%u",
- diff_stats->ierrors);
+ (void) snprintf(buf, bufsize, "%u", diff_stats->ierrors);
break;
case LINK_S_OPKTS:
- (void) snprintf(buf, sizeof (buf), "%llu",
- diff_stats->opackets);
+ (void) snprintf(buf, bufsize, "%llu", diff_stats->opackets);
break;
case LINK_S_OBYTES:
- (void) snprintf(buf, sizeof (buf), "%llu",
- diff_stats->obytes);
+ (void) snprintf(buf, bufsize, "%llu", diff_stats->obytes);
break;
case LINK_S_OERRORS:
- (void) snprintf(buf, sizeof (buf), "%u",
- diff_stats->oerrors);
+ (void) snprintf(buf, bufsize, "%u", diff_stats->oerrors);
break;
default:
die("invalid input");
break;
}
- return (buf);
+ return (B_TRUE);
}
static int
@@ -2483,8 +2322,7 @@ show_link_stats(dladm_handle_t dh, datalink_id_t linkid, void *arg)
largs.link_s_link = link;
largs.link_s_psum = &diff_stats;
- dladm_print_output(&state->ls_print, state->ls_parseable,
- print_link_stats, &largs);
+ ofmt_print(state->ls_ofmt, &largs);
state->ls_prevstats = stats;
return (DLADM_WALK_CONTINUE);
@@ -2521,36 +2359,29 @@ print_aggr_info(show_grp_state_t *state, const char *link,
(void) snprintf(lbuf.laggr_flags, sizeof (lbuf.laggr_flags), "%c----",
ginfop->lg_force ? 'f' : '-');
- if (!state->gs_parseable && !state->gs_printheader) {
- print_header(&state->gs_print);
- state->gs_printheader = B_TRUE;
- }
-
- dladm_print_output(&state->gs_print, state->gs_parseable,
- dladm_print_field, (void *)&lbuf);
+ ofmt_print(state->gs_ofmt, &lbuf);
return (DLADM_STATUS_OK);
}
-static char *
-print_xaggr_callback(print_field_t *pf, void *arg)
+static boolean_t
+print_xaggr_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
{
- const laggr_args_t *l = arg;
+ const laggr_args_t *l = ofarg->ofmt_cbarg;
int portnum;
- static char buf[DLADM_STRSIZE];
boolean_t is_port = (l->laggr_lport >= 0);
+ static char tmpbuf[DLADM_STRSIZE];
dladm_aggr_port_attr_t *portp;
dladm_phys_attr_t dpa;
- dladm_status_t *stat, status;
+ dladm_status_t *stat, status = DLADM_STATUS_OK;
stat = l->laggr_status;
- *stat = DLADM_STATUS_OK;
if (is_port) {
portnum = l->laggr_lport;
portp = &(l->laggr_ginfop->lg_ports[portnum]);
if ((status = dladm_datalink_id2info(handle,
- portp->lp_linkid, NULL, NULL, NULL, buf, sizeof (buf))) !=
+ portp->lp_linkid, NULL, NULL, NULL, buf, bufsize)) !=
DLADM_STATUS_OK) {
goto err;
}
@@ -2561,24 +2392,24 @@ print_xaggr_callback(print_field_t *pf, void *arg)
}
}
- switch (pf->pf_index) {
+ switch (ofarg->ofmt_id) {
case AGGR_X_LINK:
- (void) snprintf(buf, sizeof (buf), "%s",
- (is_port && !l->laggr_parseable ? " " : l->laggr_link));
+ (void) snprintf(buf, bufsize, "%s",
+ (is_port && !l->laggr_parsable ? " " : l->laggr_link));
break;
case AGGR_X_PORT:
if (is_port)
break;
- return ("");
- break;
+ *stat = DLADM_STATUS_OK;
+ return (B_TRUE);
case AGGR_X_SPEED:
if (is_port) {
- (void) snprintf(buf, sizeof (buf), "%uMb",
+ (void) snprintf(buf, bufsize, "%uMb",
(uint_t)((get_ifspeed(dpa.dp_dev,
B_FALSE)) / 1000000ull));
} else {
- (void) snprintf(buf, sizeof (buf), "%uMb",
+ (void) snprintf(buf, bufsize, "%uMb",
(uint_t)((get_ifspeed(l->laggr_link,
B_TRUE)) / 1000000ull));
}
@@ -2586,36 +2417,36 @@ print_xaggr_callback(print_field_t *pf, void *arg)
case AGGR_X_DUPLEX:
if (is_port)
- (void) get_linkduplex(dpa.dp_dev, B_FALSE, buf);
+ (void) get_linkduplex(dpa.dp_dev, B_FALSE, tmpbuf);
else
- (void) get_linkduplex(l->laggr_link, B_TRUE, buf);
+ (void) get_linkduplex(l->laggr_link, B_TRUE, tmpbuf);
+ (void) strlcpy(buf, tmpbuf, bufsize);
break;
case AGGR_X_STATE:
if (is_port)
- (void) get_linkstate(dpa.dp_dev, B_FALSE, buf);
+ (void) get_linkstate(dpa.dp_dev, B_FALSE, tmpbuf);
else
- (void) get_linkstate(l->laggr_link, B_TRUE, buf);
+ (void) get_linkstate(l->laggr_link, B_TRUE, tmpbuf);
+ (void) strlcpy(buf, tmpbuf, bufsize);
break;
case AGGR_X_ADDRESS:
(void) dladm_aggr_macaddr2str(
(is_port ? portp->lp_mac : l->laggr_ginfop->lg_mac),
- buf);
+ tmpbuf);
+ (void) strlcpy(buf, tmpbuf, bufsize);
break;
case AGGR_X_PORTSTATE:
- if (is_port)
- (void) dladm_aggr_portstate2str(
- portp->lp_state, buf);
- else
- return ("");
+ if (is_port) {
+ (void) dladm_aggr_portstate2str(portp->lp_state,
+ tmpbuf);
+ (void) strlcpy(buf, tmpbuf, bufsize);
+ }
break;
}
- return (buf);
-
err:
*stat = status;
- buf[0] = '\0';
- return (buf);
+ return (B_TRUE);
}
static dladm_status_t
@@ -2626,27 +2457,20 @@ print_aggr_extended(show_grp_state_t *state, const char *link,
dladm_status_t status;
laggr_args_t largs;
- if (!state->gs_parseable && !state->gs_printheader) {
- print_header(&state->gs_print);
- state->gs_printheader = B_TRUE;
- }
-
largs.laggr_lport = -1;
largs.laggr_link = link;
largs.laggr_ginfop = ginfop;
largs.laggr_status = &status;
- largs.laggr_parseable = state->gs_parseable;
+ largs.laggr_parsable = state->gs_parsable;
- dladm_print_output(&state->gs_print, state->gs_parseable,
- print_xaggr_callback, &largs);
+ ofmt_print(state->gs_ofmt, &largs);
if (status != DLADM_STATUS_OK)
goto done;
for (i = 0; i < ginfop->lg_nports; i++) {
largs.laggr_lport = i;
- dladm_print_output(&state->gs_print, state->gs_parseable,
- print_xaggr_callback, &largs);
+ ofmt_print(state->gs_ofmt, &largs);
if (status != DLADM_STATUS_OK)
goto done;
}
@@ -2656,20 +2480,18 @@ done:
return (status);
}
-
-static char *
-print_lacp_callback(print_field_t *pf, void *arg)
+static boolean_t
+print_lacp_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
{
- const laggr_args_t *l = arg;
+ const laggr_args_t *l = ofarg->ofmt_cbarg;
int portnum;
- static char buf[DLADM_STRSIZE];
boolean_t is_port = (l->laggr_lport >= 0);
dladm_aggr_port_attr_t *portp;
dladm_status_t *stat, status;
aggr_lacp_state_t *lstate;
if (!is_port) {
- return (NULL); /* cannot happen! */
+ return (B_FALSE); /* cannot happen! */
}
stat = l->laggr_status;
@@ -2678,58 +2500,61 @@ print_lacp_callback(print_field_t *pf, void *arg)
portp = &(l->laggr_ginfop->lg_ports[portnum]);
if ((status = dladm_datalink_id2info(handle, portp->lp_linkid,
- NULL, NULL, NULL, buf, sizeof (buf))) != DLADM_STATUS_OK) {
+ NULL, NULL, NULL, buf, bufsize)) != DLADM_STATUS_OK) {
goto err;
}
lstate = &(portp->lp_lacp_state);
- switch (pf->pf_index) {
+ switch (ofarg->ofmt_id) {
case AGGR_L_LINK:
- (void) snprintf(buf, sizeof (buf), "%s",
+ (void) snprintf(buf, bufsize, "%s",
(portnum > 0 ? "" : l->laggr_link));
break;
case AGGR_L_PORT:
+ /*
+ * buf already contains portname as a result of the
+ * earlier call to dladm_datalink_id2info().
+ */
break;
case AGGR_L_AGGREGATABLE:
- (void) snprintf(buf, sizeof (buf), "%s",
+ (void) snprintf(buf, bufsize, "%s",
(lstate->bit.aggregation ? "yes" : "no"));
break;
case AGGR_L_SYNC:
- (void) snprintf(buf, sizeof (buf), "%s",
+ (void) snprintf(buf, bufsize, "%s",
(lstate->bit.sync ? "yes" : "no"));
break;
case AGGR_L_COLL:
- (void) snprintf(buf, sizeof (buf), "%s",
+ (void) snprintf(buf, bufsize, "%s",
(lstate->bit.collecting ? "yes" : "no"));
break;
case AGGR_L_DIST:
- (void) snprintf(buf, sizeof (buf), "%s",
+ (void) snprintf(buf, bufsize, "%s",
(lstate->bit.distributing ? "yes" : "no"));
break;
case AGGR_L_DEFAULTED:
- (void) snprintf(buf, sizeof (buf), "%s",
+ (void) snprintf(buf, bufsize, "%s",
(lstate->bit.defaulted ? "yes" : "no"));
break;
case AGGR_L_EXPIRED:
- (void) snprintf(buf, sizeof (buf), "%s",
+ (void) snprintf(buf, bufsize, "%s",
(lstate->bit.expired ? "yes" : "no"));
break;
}
*stat = DLADM_STATUS_OK;
- return (buf);
+ return (B_TRUE);
err:
*stat = status;
- buf[0] = '\0';
- return (buf);
+ return (B_TRUE);
}
static dladm_status_t
@@ -2740,19 +2565,13 @@ print_aggr_lacp(show_grp_state_t *state, const char *link,
dladm_status_t status;
laggr_args_t largs;
- if (!state->gs_parseable && !state->gs_printheader) {
- print_header(&state->gs_print);
- state->gs_printheader = B_TRUE;
- }
-
largs.laggr_link = link;
largs.laggr_ginfop = ginfop;
largs.laggr_status = &status;
for (i = 0; i < ginfop->lg_nports; i++) {
largs.laggr_lport = i;
- dladm_print_output(&state->gs_print, state->gs_parseable,
- print_lacp_callback, &largs);
+ ofmt_print(state->gs_ofmt, &largs);
if (status != DLADM_STATUS_OK)
goto done;
}
@@ -2762,12 +2581,11 @@ done:
return (status);
}
-static char *
-print_aggr_stats_callback(print_field_t *pf, void *arg)
+static boolean_t
+print_aggr_stats_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
{
- const laggr_args_t *l = arg;
+ const laggr_args_t *l = ofarg->ofmt_cbarg;
int portnum;
- static char buf[DLADM_STRSIZE];
boolean_t is_port = (l->laggr_lport >= 0);
dladm_aggr_port_attr_t *portp;
dladm_phys_attr_t dpa;
@@ -2788,7 +2606,7 @@ print_aggr_stats_callback(print_field_t *pf, void *arg)
get_mac_stats(dpa.dp_dev, &port_stat);
if ((status = dladm_datalink_id2info(handle,
- portp->lp_linkid, NULL, NULL, NULL, buf, sizeof (buf))) !=
+ portp->lp_linkid, NULL, NULL, NULL, buf, bufsize)) !=
DLADM_STATUS_OK) {
goto err;
}
@@ -2796,81 +2614,77 @@ print_aggr_stats_callback(print_field_t *pf, void *arg)
dladm_stats_diff(&diff_stats, &port_stat, l->laggr_prevstats);
}
- switch (pf->pf_index) {
+ switch (ofarg->ofmt_id) {
case AGGR_S_LINK:
- (void) snprintf(buf, sizeof (buf), "%s",
+ (void) snprintf(buf, bufsize, "%s",
(is_port ? "" : l->laggr_link));
break;
case AGGR_S_PORT:
- if (is_port)
- break;
- return ("");
+ /*
+ * if (is_port), buf has port name. Otherwise we print
+ * STR_UNDEF_VAL
+ */
break;
case AGGR_S_IPKTS:
if (is_port) {
- (void) snprintf(buf, sizeof (buf), "%llu",
+ (void) snprintf(buf, bufsize, "%llu",
diff_stats.ipackets);
} else {
- (void) snprintf(buf, sizeof (buf), "%llu",
+ (void) snprintf(buf, bufsize, "%llu",
l->laggr_pktsumtot->ipackets);
}
break;
case AGGR_S_RBYTES:
if (is_port) {
- (void) snprintf(buf, sizeof (buf), "%llu",
+ (void) snprintf(buf, bufsize, "%llu",
diff_stats.rbytes);
} else {
- (void) snprintf(buf, sizeof (buf), "%llu",
+ (void) snprintf(buf, bufsize, "%llu",
l->laggr_pktsumtot->rbytes);
}
break;
case AGGR_S_OPKTS:
if (is_port) {
- (void) snprintf(buf, sizeof (buf), "%llu",
+ (void) snprintf(buf, bufsize, "%llu",
diff_stats.opackets);
} else {
- (void) snprintf(buf, sizeof (buf), "%llu",
+ (void) snprintf(buf, bufsize, "%llu",
l->laggr_pktsumtot->opackets);
}
break;
case AGGR_S_OBYTES:
if (is_port) {
- (void) snprintf(buf, sizeof (buf), "%llu",
+ (void) snprintf(buf, bufsize, "%llu",
diff_stats.obytes);
} else {
- (void) snprintf(buf, sizeof (buf), "%llu",
+ (void) snprintf(buf, bufsize, "%llu",
l->laggr_pktsumtot->obytes);
}
break;
case AGGR_S_IPKTDIST:
if (is_port) {
- (void) snprintf(buf, sizeof (buf), "%-6.1f",
+ (void) snprintf(buf, bufsize, "%-6.1f",
(double)diff_stats.opackets/
(double)l->laggr_pktsumtot->ipackets * 100);
- } else {
- return ("");
}
break;
case AGGR_S_OPKTDIST:
if (is_port) {
- (void) snprintf(buf, sizeof (buf), "%-6.1f",
+ (void) snprintf(buf, bufsize, "%-6.1f",
(double)diff_stats.opackets/
(double)l->laggr_pktsumtot->opackets * 100);
- } else {
- return ("");
}
break;
}
- return (buf);
+ return (B_TRUE);
err:
*stat = status;
- buf[0] = '\0';
- return (buf);
+ return (B_TRUE);
}
static dladm_status_t
@@ -2900,19 +2714,13 @@ print_aggr_stats(show_grp_state_t *state, const char *link,
&state->gs_prevstats[i]);
}
- if (!state->gs_parseable && !state->gs_printheader) {
- print_header(&state->gs_print);
- state->gs_printheader = B_TRUE;
- }
-
largs.laggr_lport = -1;
largs.laggr_link = link;
largs.laggr_ginfop = ginfop;
largs.laggr_status = &status;
largs.laggr_pktsumtot = &pktsumtot;
- dladm_print_output(&state->gs_print, state->gs_parseable,
- print_aggr_stats_callback, &largs);
+ ofmt_print(state->gs_ofmt, &largs);
if (status != DLADM_STATUS_OK)
goto done;
@@ -2920,8 +2728,7 @@ print_aggr_stats(show_grp_state_t *state, const char *link,
for (i = 0; i < ginfop->lg_nports; i++) {
largs.laggr_lport = i;
largs.laggr_prevstats = &state->gs_prevstats[i];
- dladm_print_output(&state->gs_print, state->gs_parseable,
- print_aggr_stats_callback, &largs);
+ ofmt_print(state->gs_ofmt, &largs);
if (status != DLADM_STATUS_OK)
goto done;
}
@@ -2971,13 +2778,8 @@ static int
show_aggr(dladm_handle_t dh, datalink_id_t linkid, void *arg)
{
show_grp_state_t *state = arg;
- dladm_status_t status;
-
- if ((status = print_aggr(state, linkid)) != DLADM_STATUS_OK)
- goto done;
-done:
- state->gs_status = status;
+ state->gs_status = print_aggr(state, linkid);
return (DLADM_WALK_CONTINUE);
}
@@ -2997,12 +2799,13 @@ do_show_link(int argc, char *argv[], const char *use)
dladm_status_t status;
boolean_t o_arg = B_FALSE;
char *fields_str = NULL;
- print_field_t **fields;
- uint_t nfields;
char *all_active_fields = "link,class,mtu,state,over";
char *all_inactive_fields = "link,class,over";
char *allstat_fields =
"link,ipackets,rbytes,ierrors,opackets,obytes,oerrors";
+ ofmt_handle_t ofmt;
+ ofmt_status_t oferr;
+ uint_t ofmtflags = 0;
bzero(&state, sizeof (state));
@@ -3110,7 +2913,7 @@ do_show_link(int argc, char *argv[], const char *use)
fields_str = all_inactive_fields;
}
- state.ls_parseable = p_arg;
+ state.ls_parsable = p_arg;
state.ls_flags = flags;
state.ls_donefirst = B_FALSE;
@@ -3118,15 +2921,11 @@ do_show_link(int argc, char *argv[], const char *use)
link_stats(linkid, interval, fields_str, &state);
return;
}
-
- fields = parse_output_fields(fields_str, link_fields, DEV_LINK_FIELDS,
- CMD_TYPE_ANY, &nfields);
-
- if (fields == NULL)
- die("invalid field(s) specified");
-
- state.ls_print.ps_fields = fields;
- state.ls_print.ps_nfields = nfields;
+ if (state.ls_parsable)
+ ofmtflags |= OFMT_PARSABLE;
+ oferr = ofmt_open(fields_str, link_fields, ofmtflags, 0, &ofmt);
+ dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
+ state.ls_ofmt = ofmt;
if (linkid == DATALINK_ALL_LINKID) {
(void) dladm_walk_datalink_id(show_link, handle, &state,
@@ -3138,6 +2937,7 @@ do_show_link(int argc, char *argv[], const char *use)
argv[optind]);
}
}
+ ofmt_close(ofmt);
}
static void
@@ -3157,8 +2957,6 @@ do_show_aggr(int argc, char *argv[], const char *use)
dladm_status_t status;
boolean_t o_arg = B_FALSE;
char *fields_str = NULL;
- print_field_t **fields;
- uint_t nfields;
char *all_fields =
"link,policy,addrpolicy,lacpactivity,lacptimer,flags";
char *all_lacp_fields =
@@ -3167,8 +2965,10 @@ do_show_aggr(int argc, char *argv[], const char *use)
"link,port,ipackets,rbytes,opackets,obytes,ipktdist,opktdist";
char *all_extended_fields =
"link,port,speed,duplex,state,address,portstate";
- print_field_t *pf;
- int pfmax;
+ ofmt_field_t *pf;
+ ofmt_handle_t ofmt;
+ ofmt_status_t oferr;
+ uint_t ofmtflags = 0;
bzero(&state, sizeof (state));
@@ -3265,7 +3065,7 @@ do_show_aggr(int argc, char *argv[], const char *use)
state.gs_lacp = L_arg;
state.gs_stats = s_arg;
state.gs_flags = flags;
- state.gs_parseable = p_arg;
+ state.gs_parsable = p_arg;
state.gs_extended = x_arg;
if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) {
@@ -3281,30 +3081,23 @@ do_show_aggr(int argc, char *argv[], const char *use)
if (state.gs_lacp) {
pf = aggr_l_fields;
- pfmax = AGGR_L_MAX_FIELDS;
} else if (state.gs_stats) {
pf = aggr_s_fields;
- pfmax = AGGR_S_MAX_FIELDS;
} else if (state.gs_extended) {
pf = aggr_x_fields;
- pfmax = AGGR_X_MAX_FIELDS;
} else {
pf = laggr_fields;
- pfmax = LAGGR_MAX_FIELDS;
}
- fields = parse_output_fields(fields_str, pf, pfmax, CMD_TYPE_ANY,
- &nfields);
- if (fields == NULL) {
- die("invalid field(s) specified");
- return;
- }
-
- state.gs_print.ps_fields = fields;
- state.gs_print.ps_nfields = nfields;
+ if (state.gs_parsable)
+ ofmtflags |= OFMT_PARSABLE;
+ oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt);
+ dladm_ofmt_check(oferr, state.gs_parsable, ofmt);
+ state.gs_ofmt = ofmt;
if (s_arg) {
aggr_stats(linkid, &state, interval);
+ ofmt_close(ofmt);
return;
}
@@ -3318,6 +3111,7 @@ do_show_aggr(int argc, char *argv[], const char *use)
argv[optind]);
}
}
+ ofmt_close(ofmt);
}
static dladm_status_t
@@ -3367,13 +3161,7 @@ print_phys_default(show_state_t *state, datalink_id_t linkid,
"%c----", flags & DLADM_OPT_ACTIVE ? '-' : 'r');
}
- if (!state->ls_parseable && !state->ls_printheader) {
- print_header(&state->ls_print);
- state->ls_printheader = B_TRUE;
- }
-
- dladm_print_output(&state->ls_print, state->ls_parseable,
- dladm_print_field, (void *)&pattr);
+ ofmt_print(state->ls_ofmt, &pattr);
done:
return (status);
@@ -3385,32 +3173,33 @@ typedef struct {
dladm_macaddr_attr_t *ms_mac_attr;
} print_phys_mac_state_t;
-/* callback of dladm_print_output() */
-static char *
-print_phys_one_mac_callback(print_field_t *pf, void *arg)
+/*
+ * callback for ofmt_print()
+ */
+static boolean_t
+print_phys_one_mac_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
{
- print_phys_mac_state_t *mac_state = arg;
+ print_phys_mac_state_t *mac_state = ofarg->ofmt_cbarg;
dladm_macaddr_attr_t *attr = mac_state->ms_mac_attr;
- static char buf[DLADM_STRSIZE];
boolean_t is_primary = (attr->ma_slot == 0);
- boolean_t is_parseable = mac_state->ms_state->ls_parseable;
+ boolean_t is_parsable = mac_state->ms_state->ls_parsable;
- switch (pf->pf_index) {
+ switch (ofarg->ofmt_id) {
case PHYS_M_LINK:
- (void) snprintf(buf, sizeof (buf), "%s",
- (is_primary || is_parseable) ? mac_state->ms_link : " ");
+ (void) snprintf(buf, bufsize, "%s",
+ (is_primary || is_parsable) ? mac_state->ms_link : " ");
break;
case PHYS_M_SLOT:
if (is_primary)
- (void) snprintf(buf, sizeof (buf), gettext("primary"));
+ (void) snprintf(buf, bufsize, gettext("primary"));
else
- (void) snprintf(buf, sizeof (buf), "%d", attr->ma_slot);
+ (void) snprintf(buf, bufsize, "%d", attr->ma_slot);
break;
case PHYS_M_ADDRESS:
(void) dladm_aggr_macaddr2str(attr->ma_addr, buf);
break;
case PHYS_M_INUSE:
- (void) snprintf(buf, sizeof (buf), "%s",
+ (void) snprintf(buf, bufsize, "%s",
attr->ma_flags & DLADM_MACADDR_USED ? gettext("yes") :
gettext("no"));
break;
@@ -3419,11 +3208,11 @@ print_phys_one_mac_callback(print_field_t *pf, void *arg)
* CR 6678526: resolve link id to actual link name if
* it is valid.
*/
- (void) snprintf(buf, sizeof (buf), "%s", attr->ma_client_name);
+ (void) snprintf(buf, bufsize, "%s", attr->ma_client_name);
break;
}
- return (buf);
+ return (B_TRUE);
}
typedef struct {
@@ -3432,60 +3221,57 @@ typedef struct {
dladm_hwgrp_attr_t *hs_grp_attr;
} print_phys_hwgrp_state_t;
-static char *
-print_phys_one_hwgrp_callback(print_field_t *pf, void *arg)
+static boolean_t
+print_phys_one_hwgrp_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
{
- print_phys_hwgrp_state_t *hg_state = arg;
+ print_phys_hwgrp_state_t *hg_state = ofarg->ofmt_cbarg;
dladm_hwgrp_attr_t *attr = hg_state->hs_grp_attr;
- static char buf[DLADM_STRSIZE];
- switch (pf->pf_index) {
+ switch (ofarg->ofmt_id) {
case PHYS_H_LINK:
- (void) snprintf(buf, sizeof (buf), "%s", attr->hg_link_name);
+ (void) snprintf(buf, bufsize, "%s", attr->hg_link_name);
break;
case PHYS_H_GROUP:
- (void) snprintf(buf, sizeof (buf), "%d", attr->hg_grp_num);
+ (void) snprintf(buf, bufsize, "%d", attr->hg_grp_num);
break;
case PHYS_H_GRPTYPE:
- (void) snprintf(buf, sizeof (buf), "%s",
+ (void) snprintf(buf, bufsize, "%s",
attr->hg_grp_type == DLADM_HWGRP_TYPE_RX ? "RX" : "TX");
break;
case PHYS_H_RINGS:
- (void) snprintf(buf, sizeof (buf), "%d", attr->hg_n_rings);
+ (void) snprintf(buf, bufsize, "%d", attr->hg_n_rings);
break;
case PHYS_H_CLIENTS:
if (attr->hg_client_names[0] == '\0') {
- (void) snprintf(buf, sizeof (buf), "--");
+ (void) snprintf(buf, bufsize, "--");
} else {
- (void) snprintf(buf, sizeof (buf), "%s ",
+ (void) snprintf(buf, bufsize, "%s ",
attr->hg_client_names);
}
break;
}
- return (buf);
+ return (B_TRUE);
}
-/* callback of dladm_walk_macaddr, invoked for each MAC address slot */
+/*
+ * callback for dladm_walk_macaddr, invoked for each MAC address slot
+ */
static boolean_t
print_phys_mac_callback(void *arg, dladm_macaddr_attr_t *attr)
{
print_phys_mac_state_t *mac_state = arg;
show_state_t *state = mac_state->ms_state;
- if (!state->ls_parseable && !state->ls_printheader) {
- print_header(&state->ls_print);
- state->ls_printheader = B_TRUE;
- }
-
mac_state->ms_mac_attr = attr;
- dladm_print_output(&state->ls_print, state->ls_parseable,
- print_phys_one_mac_callback, mac_state);
+ ofmt_print(state->ls_ofmt, mac_state);
return (B_TRUE);
}
-/* invoked by show-phys -m for each physical data-link */
+/*
+ * invoked by show-phys -m for each physical data-link
+ */
static dladm_status_t
print_phys_mac(show_state_t *state, datalink_id_t linkid, char *link)
{
@@ -3498,20 +3284,17 @@ print_phys_mac(show_state_t *state, datalink_id_t linkid, char *link)
print_phys_mac_callback));
}
-/* callback of dladm_walk_hwgrp, invoked for each MAC hwgrp */
+/*
+ * callback for dladm_walk_hwgrp, invoked for each MAC hwgrp
+ */
static boolean_t
print_phys_hwgrp_callback(void *arg, dladm_hwgrp_attr_t *attr)
{
print_phys_hwgrp_state_t *hwgrp_state = arg;
show_state_t *state = hwgrp_state->hs_state;
- if (!state->ls_parseable && !state->ls_printheader) {
- print_header(&state->ls_print);
- state->ls_printheader = B_TRUE;
- }
hwgrp_state->hs_grp_attr = attr;
- dladm_print_output(&state->ls_print, state->ls_parseable,
- print_phys_one_hwgrp_callback, hwgrp_state);
+ ofmt_print(state->ls_ofmt, hwgrp_state);
return (B_TRUE);
}
@@ -3623,13 +3406,7 @@ show_vlan(dladm_handle_t dh, datalink_id_t linkid, void *arg)
if (status != DLADM_STATUS_OK)
goto done;
- if (!state->ls_parseable && !state->ls_printheader) {
- print_header(&state->ls_print);
- state->ls_printheader = B_TRUE;
- }
-
- dladm_print_output(&state->ls_print, state->ls_parseable,
- dladm_print_field, (void *)&lbuf);
+ ofmt_print(state->ls_ofmt, &lbuf);
done:
state->ls_status = status;
@@ -3649,16 +3426,16 @@ do_show_phys(int argc, char *argv[], const char *use)
show_state_t state;
dladm_status_t status;
char *fields_str = NULL;
- print_field_t **fields;
- uint_t nfields;
char *all_active_fields =
"link,media,state,speed,duplex,device";
char *all_inactive_fields = "link,device,media,flags";
char *all_mac_fields = "link,slot,address,inuse,client";
char *all_hwgrp_fields =
"link,group,grouptype,rings,clients";
- print_field_t *pf;
- int pfmax;
+ ofmt_field_t *pf;
+ ofmt_handle_t ofmt;
+ ofmt_status_t oferr;
+ uint_t ofmtflags = 0;
bzero(&state, sizeof (state));
opterr = 0;
@@ -3712,7 +3489,7 @@ do_show_phys(int argc, char *argv[], const char *use)
usage();
}
- state.ls_parseable = p_arg;
+ state.ls_parsable = p_arg;
state.ls_flags = flags;
state.ls_donefirst = B_FALSE;
state.ls_mac = m_arg;
@@ -3740,25 +3517,17 @@ do_show_phys(int argc, char *argv[], const char *use)
if (state.ls_mac) {
pf = phys_m_fields;
- pfmax = PHYS_M_MAX_FIELDS;
} else if (state.ls_hwgrp) {
pf = phys_h_fields;
- pfmax = PHYS_H_MAX_FIELDS;
} else {
pf = phys_fields;
- pfmax = PHYS_MAX_FIELDS;
- }
-
- fields = parse_output_fields(fields_str, pf,
- pfmax, CMD_TYPE_ANY, &nfields);
-
- if (fields == NULL) {
- die("invalid field(s) specified");
- return;
}
- state.ls_print.ps_fields = fields;
- state.ls_print.ps_nfields = nfields;
+ if (state.ls_parsable)
+ ofmtflags |= OFMT_PARSABLE;
+ oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt);
+ dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
+ state.ls_ofmt = ofmt;
if (linkid == DATALINK_ALL_LINKID) {
(void) dladm_walk_datalink_id(show_phys, handle, &state,
@@ -3770,6 +3539,7 @@ do_show_phys(int argc, char *argv[], const char *use)
"failed to show physical link %s", argv[optind]);
}
}
+ ofmt_close(ofmt);
}
static void
@@ -3783,9 +3553,9 @@ do_show_vlan(int argc, char *argv[], const char *use)
dladm_status_t status;
boolean_t o_arg = B_FALSE;
char *fields_str = NULL;
- print_field_t **fields;
- uint_t nfields;
- char *all_fields = "link,vid,over,flags";
+ ofmt_handle_t ofmt;
+ ofmt_status_t oferr;
+ uint_t ofmtflags = 0;
bzero(&state, sizeof (state));
@@ -3815,12 +3585,6 @@ do_show_vlan(int argc, char *argv[], const char *use)
}
}
- if (p_arg && !o_arg)
- die("-p requires -o");
-
- if (p_arg && strcasecmp(fields_str, "all") == 0)
- die("\"-o all\" is invalid with -p");
-
/* get link name (optional last argument) */
if (optind == (argc-1)) {
if ((status = dladm_name2info(handle, argv[optind], &linkid,
@@ -3831,22 +3595,18 @@ do_show_vlan(int argc, char *argv[], const char *use)
usage();
}
- state.ls_parseable = p_arg;
+ state.ls_parsable = p_arg;
state.ls_flags = flags;
state.ls_donefirst = B_FALSE;
if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0))
- fields_str = all_fields;
-
- fields = parse_output_fields(fields_str, vlan_fields, VLAN_MAX_FIELDS,
- CMD_TYPE_ANY, &nfields);
+ fields_str = NULL;
- if (fields == NULL) {
- die("invalid field(s) specified");
- return;
- }
- state.ls_print.ps_fields = fields;
- state.ls_print.ps_nfields = nfields;
+ if (state.ls_parsable)
+ ofmtflags |= OFMT_PARSABLE;
+ oferr = ofmt_open(fields_str, vlan_fields, ofmtflags, 0, &ofmt);
+ dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
+ state.ls_ofmt = ofmt;
if (linkid == DATALINK_ALL_LINKID) {
(void) dladm_walk_datalink_id(show_vlan, handle, &state,
@@ -3858,6 +3618,7 @@ do_show_vlan(int argc, char *argv[], const char *use)
argv[optind]);
}
}
+ ofmt_close(ofmt);
}
static void
@@ -4289,13 +4050,7 @@ print_vnic(show_vnic_state_t *state, datalink_id_t linkid)
"%d", vnic->va_vid);
}
- if (!state->vs_parseable && !state->vs_printheader) {
- print_header(&state->vs_print);
- state->vs_printheader = B_TRUE;
- }
-
- dladm_print_output(&state->vs_print, state->vs_parseable,
- dladm_print_field, (void *)&vbuf);
+ ofmt_print(state->vs_ofmt, &vbuf);
return (DLADM_STATUS_OK);
}
@@ -4326,14 +4081,11 @@ do_show_vnic_common(int argc, char *argv[], const char *use,
dladm_status_t status;
boolean_t o_arg = B_FALSE;
char *fields_str = NULL;
- print_field_t **fields;
- print_field_t *pf;
- int pfmax;
- uint_t nfields;
- char *all_fields =
- "link,over,speed,macaddress,macaddrtype,vid";
- char *all_e_fields =
- "link";
+ ofmt_field_t *pf;
+ char *all_e_fields = "link";
+ ofmt_handle_t ofmt;
+ ofmt_status_t oferr;
+ uint_t ofmtflags = 0;
bzero(&state, sizeof (state));
opterr = 0;
@@ -4341,7 +4093,7 @@ do_show_vnic_common(int argc, char *argv[], const char *use,
NULL)) != -1) {
switch (option) {
case 'p':
- state.vs_parseable = B_TRUE;
+ state.vs_parsable = B_TRUE;
break;
case 'P':
flags = DLADM_OPT_PERSIST;
@@ -4381,12 +4133,6 @@ do_show_vnic_common(int argc, char *argv[], const char *use,
}
}
- if (state.vs_parseable && !o_arg)
- die("-p requires -o");
-
- if (state.vs_parseable && strcasecmp(fields_str, "all") == 0)
- die("\"-o all\" is invalid with -p");
-
if (i_arg && !s_arg)
die("the option -i can be used only with -s");
@@ -4421,27 +4167,19 @@ do_show_vnic_common(int argc, char *argv[], const char *use,
if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) {
if (etherstub)
fields_str = all_e_fields;
- else
- fields_str = all_fields;
}
-
pf = vnic_fields;
- pfmax = VNIC_MAX_FIELDS;
-
- fields = parse_output_fields(fields_str, pf, pfmax, CMD_TYPE_ANY,
- &nfields);
-
- if (fields == NULL) {
- die("invalid field(s) specified");
- return;
- }
- state.vs_print.ps_fields = fields;
- state.vs_print.ps_nfields = nfields;
+ if (state.vs_parsable)
+ ofmtflags |= OFMT_PARSABLE;
+ oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt);
+ dladm_ofmt_check(oferr, state.vs_parsable, ofmt);
+ state.vs_ofmt = ofmt;
if (s_arg) {
/* Display vnic statistics */
vnic_stats(&state, interval);
+ ofmt_close(ofmt);
return;
}
@@ -4455,10 +4193,12 @@ do_show_vnic_common(int argc, char *argv[], const char *use,
} else {
(void) show_vnic(handle, linkid, &state);
if (state.vs_status != DLADM_STATUS_OK) {
+ ofmt_close(ofmt);
die_dlerr(state.vs_status, "failed to show vnic '%s'",
state.vs_vnic);
}
}
+ ofmt_close(ofmt);
}
static void
@@ -4535,18 +4275,15 @@ static void
link_stats(datalink_id_t linkid, uint_t interval, char *fields_str,
show_state_t *state)
{
- print_field_t **fields;
- uint_t nfields;
+ ofmt_handle_t ofmt;
+ ofmt_status_t oferr;
+ uint_t ofmtflags = 0;
- fields = parse_output_fields(fields_str, link_s_fields,
- LINK_S_MAX_FIELDS, CMD_TYPE_ANY, &nfields);
- if (fields == NULL) {
- die("invalid field(s) specified");
- return;
- }
-
- state->ls_print.ps_fields = fields;
- state->ls_print.ps_nfields = nfields;
+ if (state->ls_parsable)
+ ofmtflags |= OFMT_PARSABLE;
+ oferr = ofmt_open(fields_str, link_s_fields, ofmtflags, 0, &ofmt);
+ dladm_ofmt_check(oferr, state->ls_parsable, ofmt);
+ state->ls_ofmt = ofmt;
/*
* If an interval is specified, continuously show the stats
@@ -4554,8 +4291,6 @@ link_stats(datalink_id_t linkid, uint_t interval, char *fields_str,
*/
state->ls_firstonly = (interval != 0);
- if (!state->ls_parseable)
- print_header(&state->ls_print);
for (;;) {
state->ls_donefirst = B_FALSE;
if (linkid == DATALINK_ALL_LINKID) {
@@ -4571,6 +4306,7 @@ link_stats(datalink_id_t linkid, uint_t interval, char *fields_str,
(void) sleep(interval);
}
+ ofmt_close(ofmt);
}
static void
@@ -4819,129 +4555,50 @@ get_linkduplex(const char *name, boolean_t islink, char *buf)
return (dladm_linkduplex2str(linkduplex, buf));
}
-typedef struct {
- char *s_buf;
- char **s_fields; /* array of pointer to the fields in s_buf */
- uint_t s_nfields; /* the number of fields in s_buf */
-} split_t;
-
-/*
- * Free the split_t structure pointed to by `sp'.
- */
-static void
-splitfree(split_t *sp)
-{
- free(sp->s_buf);
- free(sp->s_fields);
- free(sp);
-}
-
-/*
- * Split `str' into at most `maxfields' fields, each field at most `maxlen' in
- * length. Return a pointer to a split_t containing the split fields, or NULL
- * on failure.
- */
-static split_t *
-split(const char *str, uint_t maxfields, uint_t maxlen)
-{
- char *field, *token, *lasts = NULL;
- split_t *sp;
-
- if (*str == '\0' || maxfields == 0 || maxlen == 0)
- return (NULL);
-
- sp = calloc(sizeof (split_t), 1);
- if (sp == NULL)
- return (NULL);
-
- sp->s_buf = strdup(str);
- sp->s_fields = malloc(sizeof (char *) * maxfields);
- if (sp->s_buf == NULL || sp->s_fields == NULL)
- goto fail;
-
- token = sp->s_buf;
- while ((field = strtok_r(token, ",", &lasts)) != NULL) {
- if (sp->s_nfields == maxfields || strlen(field) > maxlen)
- goto fail;
- token = NULL;
- sp->s_fields[sp->s_nfields++] = field;
- }
- return (sp);
-fail:
- splitfree(sp);
- return (NULL);
-}
-
static int
-parse_wifi_fields(char *str, print_field_t ***fields, uint_t *countp,
- uint_t cmdtype)
+parse_wifi_fields(char *str, ofmt_handle_t *ofmt, uint_t cmdtype,
+ boolean_t parsable)
{
+ ofmt_field_t *template, *of;
+ ofmt_cb_t *fn;
+ ofmt_status_t oferr;
if (cmdtype == WIFI_CMD_SCAN) {
+ template = wifi_common_fields;
if (str == NULL)
str = def_scan_wifi_fields;
if (strcasecmp(str, "all") == 0)
str = all_scan_wifi_fields;
+ fn = print_wlan_attr_cb;
} else if (cmdtype == WIFI_CMD_SHOW) {
+ bcopy(wifi_common_fields, &wifi_show_fields[2],
+ sizeof (wifi_common_fields));
+ template = wifi_show_fields;
if (str == NULL)
str = def_show_wifi_fields;
if (strcasecmp(str, "all") == 0)
str = all_show_wifi_fields;
+ fn = print_link_attr_cb;
} else {
return (-1);
}
- *fields = parse_output_fields(str, wifi_fields, WIFI_MAX_FIELDS,
- cmdtype, countp);
- if (*fields != NULL)
- return (0);
- return (-1);
-}
-static print_field_t **
-parse_output_fields(char *str, print_field_t *template, int max_fields,
- uint_t cmdtype, uint_t *countp)
-{
- split_t *sp;
- boolean_t good_match = B_FALSE;
- uint_t i, j;
- print_field_t **pf = NULL;
- sp = split(str, max_fields, MAX_FIELD_LEN);
-
- if (sp == NULL)
- return (NULL);
-
- pf = malloc(sp->s_nfields * sizeof (print_field_t *));
- if (pf == NULL)
- goto fail;
-
- for (i = 0; i < sp->s_nfields; i++) {
- for (j = 0; j < max_fields; j++) {
- if (strcasecmp(sp->s_fields[i],
- template[j].pf_name) == 0) {
- good_match = template[j]. pf_cmdtype & cmdtype;
- break;
- }
- }
- if (!good_match)
- goto fail;
-
- good_match = B_FALSE;
- pf[i] = &template[j];
+ for (of = template; of->of_name != NULL; of++) {
+ if (of->of_cb == NULL)
+ of->of_cb = fn;
}
- *countp = i;
- splitfree(sp);
- return (pf);
-fail:
- free(pf);
- splitfree(sp);
- return (NULL);
+
+ oferr = ofmt_open(str, template, (parsable ? OFMT_PARSABLE : 0),
+ 0, ofmt);
+ dladm_ofmt_check(oferr, parsable, *ofmt);
+ return (0);
}
typedef struct print_wifi_state {
char *ws_link;
- boolean_t ws_parseable;
+ boolean_t ws_parsable;
boolean_t ws_header;
- print_state_t ws_print_state;
+ ofmt_handle_t ws_ofmt;
} print_wifi_state_t;
typedef struct wlan_scan_args_s {
@@ -4949,102 +4606,52 @@ typedef struct wlan_scan_args_s {
void *ws_attr;
} wlan_scan_args_t;
-static void
-print_field(print_state_t *statep, print_field_t *pfp, const char *value,
- boolean_t parseable)
-{
- uint_t width = pfp->pf_width;
- uint_t valwidth;
- uint_t compress;
-
- /*
- * Parsable fields are separated by ':'. If such a field contains
- * a ':' or '\', this character is prefixed by a '\'.
- */
- if (parseable) {
- char c;
-
- if (statep->ps_nfields == 1) {
- (void) printf("%s", value);
- return;
- }
- while ((c = *value++) != '\0') {
- if (c == ':' || c == '\\')
- (void) putchar('\\');
- (void) putchar(c);
- }
- if (!statep->ps_lastfield)
- (void) putchar(':');
- return;
- } else {
- if (value[0] == '\0')
- value = STR_UNDEF_VAL;
- if (statep->ps_lastfield) {
- (void) printf("%s", value);
- statep->ps_overflow = 0;
- return;
- }
-
- valwidth = strlen(value);
- if (valwidth > width) {
- statep->ps_overflow += valwidth - width;
- } else if (valwidth < width && statep->ps_overflow > 0) {
- compress = min(statep->ps_overflow, width - valwidth);
- statep->ps_overflow -= compress;
- width -= compress;
- }
- (void) printf("%-*s", width, value);
- }
-
- if (!statep->ps_lastfield)
- (void) putchar(' ');
-}
-
-static char *
-print_wlan_attr(print_field_t *wfp, void *warg)
+static boolean_t
+print_wlan_attr_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
{
- static char buf[DLADM_STRSIZE];
- wlan_scan_args_t *w = warg;
+ wlan_scan_args_t *w = ofarg->ofmt_cbarg;
print_wifi_state_t *statep = w->ws_state;
dladm_wlan_attr_t *attrp = w->ws_attr;
+ char tmpbuf[DLADM_STRSIZE];
- if (wfp->pf_index == 0) {
- return ((char *)statep->ws_link);
+ if (ofarg->ofmt_id == 0) {
+ (void) strlcpy(buf, (char *)statep->ws_link, bufsize);
+ return (B_TRUE);
}
- if ((wfp->pf_index & attrp->wa_valid) == 0) {
- return ("");
- }
+ if ((ofarg->ofmt_id & attrp->wa_valid) == 0)
+ return (B_TRUE);
- switch (wfp->pf_index) {
+ switch (ofarg->ofmt_id) {
case DLADM_WLAN_ATTR_ESSID:
- (void) dladm_wlan_essid2str(&attrp->wa_essid, buf);
+ (void) dladm_wlan_essid2str(&attrp->wa_essid, tmpbuf);
break;
case DLADM_WLAN_ATTR_BSSID:
- (void) dladm_wlan_bssid2str(&attrp->wa_bssid, buf);
+ (void) dladm_wlan_bssid2str(&attrp->wa_bssid, tmpbuf);
break;
case DLADM_WLAN_ATTR_SECMODE:
- (void) dladm_wlan_secmode2str(&attrp->wa_secmode, buf);
+ (void) dladm_wlan_secmode2str(&attrp->wa_secmode, tmpbuf);
break;
case DLADM_WLAN_ATTR_STRENGTH:
- (void) dladm_wlan_strength2str(&attrp->wa_strength, buf);
+ (void) dladm_wlan_strength2str(&attrp->wa_strength, tmpbuf);
break;
case DLADM_WLAN_ATTR_MODE:
- (void) dladm_wlan_mode2str(&attrp->wa_mode, buf);
+ (void) dladm_wlan_mode2str(&attrp->wa_mode, tmpbuf);
break;
case DLADM_WLAN_ATTR_SPEED:
- (void) dladm_wlan_speed2str(&attrp->wa_speed, buf);
- (void) strlcat(buf, "Mb", sizeof (buf));
+ (void) dladm_wlan_speed2str(&attrp->wa_speed, tmpbuf);
+ (void) strlcat(tmpbuf, "Mb", sizeof (tmpbuf));
break;
case DLADM_WLAN_ATTR_AUTH:
- (void) dladm_wlan_auth2str(&attrp->wa_auth, buf);
+ (void) dladm_wlan_auth2str(&attrp->wa_auth, tmpbuf);
break;
case DLADM_WLAN_ATTR_BSSTYPE:
- (void) dladm_wlan_bsstype2str(&attrp->wa_bsstype, buf);
+ (void) dladm_wlan_bsstype2str(&attrp->wa_bsstype, tmpbuf);
break;
}
+ (void) strlcpy(buf, tmpbuf, bufsize);
- return (buf);
+ return (B_TRUE);
}
static boolean_t
@@ -5053,18 +4660,10 @@ print_scan_results(void *arg, dladm_wlan_attr_t *attrp)
print_wifi_state_t *statep = arg;
wlan_scan_args_t warg;
- if (statep->ws_header) {
- statep->ws_header = B_FALSE;
- if (!statep->ws_parseable)
- print_header(&statep->ws_print_state);
- }
-
- statep->ws_print_state.ps_overflow = 0;
bzero(&warg, sizeof (warg));
warg.ws_state = statep;
warg.ws_attr = attrp;
- dladm_print_output(&statep->ws_print_state, statep->ws_parseable,
- print_wlan_attr, &warg);
+ ofmt_print(statep->ws_ofmt, &warg);
return (B_TRUE);
}
@@ -5088,27 +4687,32 @@ scan_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg)
return (DLADM_WALK_CONTINUE);
}
-static char *
-print_link_attr(print_field_t *wfp, void *warg)
+static boolean_t
+print_wifi_status_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
{
- static char buf[DLADM_STRSIZE];
- char *ptr;
- wlan_scan_args_t *w = warg, w1;
- print_wifi_state_t *statep = w->ws_state;
+ static char tmpbuf[DLADM_STRSIZE];
+ wlan_scan_args_t *w = ofarg->ofmt_cbarg;
dladm_wlan_linkattr_t *attrp = w->ws_attr;
- if (strcmp(wfp->pf_name, "status") == 0) {
- if ((wfp->pf_index & attrp->la_valid) != 0)
- (void) dladm_wlan_linkstatus2str(
- &attrp->la_status, buf);
- return (buf);
+ if ((ofarg->ofmt_id & attrp->la_valid) != 0) {
+ (void) dladm_wlan_linkstatus2str(&attrp->la_status, tmpbuf);
+ (void) strlcpy(buf, tmpbuf, bufsize);
}
- statep->ws_print_state.ps_overflow = 0;
+ return (B_TRUE);
+}
+
+static boolean_t
+print_link_attr_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
+{
+ wlan_scan_args_t *w = ofarg->ofmt_cbarg, w1;
+ print_wifi_state_t *statep = w->ws_state;
+ dladm_wlan_linkattr_t *attrp = w->ws_attr;
+
bzero(&w1, sizeof (w1));
w1.ws_state = statep;
w1.ws_attr = &attrp->la_wlan_attr;
- ptr = print_wlan_attr(wfp, &w1);
- return (ptr);
+ ofarg->ofmt_cbarg = &w1;
+ return (print_wlan_attr_cb(ofarg, buf, bufsize));
}
static int
@@ -5132,18 +4736,10 @@ show_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg)
statep->ws_link = link;
- if (statep->ws_header) {
- statep->ws_header = B_FALSE;
- if (!statep->ws_parseable)
- print_header(&statep->ws_print_state);
- }
-
- statep->ws_print_state.ps_overflow = 0;
bzero(&warg, sizeof (warg));
warg.ws_state = statep;
warg.ws_attr = &attr;
- dladm_print_output(&statep->ws_print_state, statep->ws_parseable,
- print_link_attr, &warg);
+ ofmt_print(statep->ws_ofmt, &warg);
return (DLADM_WALK_CONTINUE);
}
@@ -5152,9 +4748,7 @@ do_display_wifi(int argc, char **argv, int cmd, const char *use)
{
int option;
char *fields_str = NULL;
- print_field_t **fields;
int (*callback)(dladm_handle_t, datalink_id_t, void *);
- uint_t nfields;
print_wifi_state_t state;
datalink_id_t linkid = DATALINK_ALL_LINKID;
dladm_status_t status;
@@ -5166,7 +4760,7 @@ do_display_wifi(int argc, char **argv, int cmd, const char *use)
else
return;
- state.ws_parseable = B_FALSE;
+ state.ws_parsable = B_FALSE;
state.ws_header = B_TRUE;
opterr = 0;
while ((option = getopt_long(argc, argv, ":o:p",
@@ -5176,17 +4770,17 @@ do_display_wifi(int argc, char **argv, int cmd, const char *use)
fields_str = optarg;
break;
case 'p':
- state.ws_parseable = B_TRUE;
+ state.ws_parsable = B_TRUE;
break;
default:
die_opterr(optopt, option, use);
}
}
- if (state.ws_parseable && fields_str == NULL)
+ if (state.ws_parsable && fields_str == NULL)
die("-p requires -o");
- if (state.ws_parseable && strcasecmp(fields_str, "all") == 0)
+ if (state.ws_parsable && strcasecmp(fields_str, "all") == 0)
die("\"-o all\" is invalid with -p");
if (optind == (argc - 1)) {
@@ -5198,20 +4792,17 @@ do_display_wifi(int argc, char **argv, int cmd, const char *use)
usage();
}
- if (parse_wifi_fields(fields_str, &fields, &nfields, cmd) < 0)
+ if (parse_wifi_fields(fields_str, &state.ws_ofmt, cmd,
+ state.ws_parsable) < 0)
die("invalid field(s) specified");
- bzero(&state.ws_print_state, sizeof (state.ws_print_state));
- state.ws_print_state.ps_fields = fields;
- state.ws_print_state.ps_nfields = nfields;
-
if (linkid == DATALINK_ALL_LINKID) {
(void) dladm_walk_datalink_id(callback, handle, &state,
DATALINK_CLASS_PHYS, DL_WIFI, DLADM_OPT_ACTIVE);
} else {
(void) (*callback)(handle, linkid, &state);
}
- free(fields);
+ ofmt_close(state.ws_ofmt);
}
static void
@@ -5247,23 +4838,33 @@ static int
parse_wlan_keys(char *str, dladm_wlan_key_t **keys, uint_t *key_countp)
{
uint_t i;
- split_t *sp;
dladm_wlan_key_t *wk;
+ int nfields = 1;
+ char *field, *token, *lasts = NULL, c;
- sp = split(str, DLADM_WLAN_MAX_WEPKEYS, DLADM_WLAN_MAX_KEYNAME_LEN);
- if (sp == NULL)
+ token = str;
+ while ((c = *token++) != NULL) {
+ if (c == ',')
+ nfields++;
+ }
+ token = strdup(str);
+ if (token == NULL)
return (-1);
- wk = malloc(sp->s_nfields * sizeof (dladm_wlan_key_t));
+ wk = malloc(nfields * sizeof (dladm_wlan_key_t));
if (wk == NULL)
goto fail;
- for (i = 0; i < sp->s_nfields; i++) {
+ token = str;
+ for (i = 0; i < nfields; i++) {
char *s;
dladm_secobj_class_t class;
dladm_status_t status;
- (void) strlcpy(wk[i].wk_name, sp->s_fields[i],
+ field = strtok_r(token, ",", &lasts);
+ token = NULL;
+
+ (void) strlcpy(wk[i].wk_name, field,
DLADM_WLAN_MAX_KEYNAME_LEN);
wk[i].wk_idx = 1;
@@ -5291,11 +4892,11 @@ parse_wlan_keys(char *str, dladm_wlan_key_t **keys, uint_t *key_countp)
}
*keys = wk;
*key_countp = i;
- splitfree(sp);
+ free(token);
return (0);
fail:
free(wk);
- splitfree(sp);
+ free(token);
return (-1);
}
@@ -5579,8 +5180,8 @@ print_linkprop(datalink_id_t linkid, show_linkprop_state_t *statep,
ptr = buf;
lim = buf + DLADM_STRSIZE;
for (i = 0; i < valcnt; i++) {
- if (propvals[i][0] == '\0' && !statep->ls_parseable)
- ptr += snprintf(ptr, lim - ptr, STR_UNDEF_VAL",");
+ if (propvals[i][0] == '\0' && !statep->ls_parsable)
+ ptr += snprintf(ptr, lim - ptr, "--,");
else
ptr += snprintf(ptr, lim - ptr, "%s,", propvals[i]);
if (ptr >= lim)
@@ -5590,7 +5191,7 @@ print_linkprop(datalink_id_t linkid, show_linkprop_state_t *statep,
buf[strlen(buf) - 1] = '\0';
lim = statep->ls_line + MAX_PROP_LINE;
- if (statep->ls_parseable) {
+ if (statep->ls_parsable) {
*pptr += snprintf(*pptr, lim - *pptr,
"%s", buf);
} else {
@@ -5598,17 +5199,17 @@ print_linkprop(datalink_id_t linkid, show_linkprop_state_t *statep,
}
}
-static char *
-linkprop_callback(print_field_t *pf, void *ls_arg)
+static boolean_t
+print_linkprop_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
{
- linkprop_args_t *arg = ls_arg;
+ linkprop_args_t *arg = ofarg->ofmt_cbarg;
char *propname = arg->ls_propname;
show_linkprop_state_t *statep = arg->ls_state;
char *ptr = statep->ls_line;
char *lim = ptr + MAX_PROP_LINE;
datalink_id_t linkid = arg->ls_linkid;
- switch (pf->pf_index) {
+ switch (ofarg->ofmt_id) {
case LINKPROP_LINK:
(void) snprintf(ptr, lim - ptr, "%s", statep->ls_link);
break;
@@ -5653,12 +5254,11 @@ linkprop_callback(print_field_t *pf, void *ls_arg)
die("invalid input");
break;
}
- return (ptr);
+ (void) strlcpy(buf, ptr, bufsize);
+ return (B_TRUE);
skip:
- if (statep->ls_status != DLADM_STATUS_OK)
- return (NULL);
- else
- return ("");
+ return ((statep->ls_status == DLADM_STATUS_OK) ?
+ B_TRUE : B_FALSE);
}
static boolean_t
@@ -5701,11 +5301,6 @@ show_linkprop(dladm_handle_t dh, datalink_id_t linkid, const char *propname,
ls_arg.ls_propname = (char *)propname;
ls_arg.ls_linkid = linkid;
- if (statep->ls_header) {
- statep->ls_header = B_FALSE;
- if (!statep->ls_parseable)
- print_header(&statep->ls_print);
- }
/*
* This will need to be fixed when kernel interfaces are added
* to enable walking of all known private properties. For now,
@@ -5714,12 +5309,11 @@ show_linkprop(dladm_handle_t dh, datalink_id_t linkid, const char *propname,
if ((propname[0] == '_') && !statep->ls_persist &&
(statep->ls_proplist == NULL))
return (DLADM_WALK_CONTINUE);
- if (!statep->ls_parseable &&
+ if (!statep->ls_parsable &&
!linkprop_is_supported(linkid, propname, statep))
return (DLADM_WALK_CONTINUE);
- dladm_print_output(&statep->ls_print, statep->ls_parseable,
- linkprop_callback, (void *)&ls_arg);
+ ofmt_print(statep->ls_ofmt, &ls_arg);
return (DLADM_WALK_CONTINUE);
}
@@ -5735,19 +5329,15 @@ do_show_linkprop(int argc, char **argv, const char *use)
uint32_t flags = DLADM_OPT_ACTIVE;
dladm_status_t status;
char *fields_str = NULL;
- print_field_t **fields;
- uint_t nfields;
- boolean_t o_arg = B_FALSE;
- char *all_fields =
- "link,property,perm,value,default,possible";
-
- fields_str = all_fields;
+ ofmt_handle_t ofmt;
+ ofmt_status_t oferr;
+ uint_t ofmtflags = 0;
bzero(propstr, DLADM_STRSIZE);
opterr = 0;
state.ls_propvals = NULL;
state.ls_line = NULL;
- state.ls_parseable = B_FALSE;
+ state.ls_parsable = B_FALSE;
state.ls_persist = B_FALSE;
state.ls_header = B_TRUE;
state.ls_retstatus = DLADM_STATUS_OK;
@@ -5762,18 +5352,14 @@ do_show_linkprop(int argc, char **argv, const char *use)
die("property list too long '%s'", propstr);
break;
case 'c':
- state.ls_parseable = B_TRUE;
+ state.ls_parsable = B_TRUE;
break;
case 'P':
state.ls_persist = B_TRUE;
flags = DLADM_OPT_PERSIST;
break;
case 'o':
- o_arg = B_TRUE;
- if (strcasecmp(optarg, "all") == 0)
- fields_str = all_fields;
- else
- fields_str = optarg;
+ fields_str = optarg;
break;
default:
die_opterr(optopt, option, use);
@@ -5781,12 +5367,6 @@ do_show_linkprop(int argc, char **argv, const char *use)
}
}
- if (state.ls_parseable && !o_arg)
- die("-c requires -o");
-
- if (state.ls_parseable && fields_str == all_fields)
- die("\"-o all\" is invalid with -c");
-
if (optind == (argc - 1)) {
if ((status = dladm_name2info(handle, argv[optind], &linkid,
NULL, NULL, NULL)) != DLADM_STATUS_OK) {
@@ -5799,27 +5379,22 @@ do_show_linkprop(int argc, char **argv, const char *use)
if (dladm_parse_link_props(propstr, &proplist, B_TRUE)
!= DLADM_STATUS_OK)
die("invalid link properties specified");
-
- bzero(&state.ls_print, sizeof (print_state_t));
state.ls_proplist = proplist;
state.ls_status = DLADM_STATUS_OK;
- fields = parse_output_fields(fields_str, linkprop_fields,
- LINKPROP_MAX_FIELDS, CMD_TYPE_ANY, &nfields);
-
- if (fields == NULL) {
- die("invalid field(s) specified");
- return;
- }
+ if (state.ls_parsable)
+ ofmtflags |= OFMT_PARSABLE;
+ oferr = ofmt_open(fields_str, linkprop_fields, ofmtflags, 0, &ofmt);
+ dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
+ state.ls_ofmt = ofmt;
- state.ls_print.ps_fields = fields;
- state.ls_print.ps_nfields = nfields;
if (linkid == DATALINK_ALL_LINKID) {
(void) dladm_walk_datalink_id(show_linkprop_onelink, handle,
&state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, flags);
} else {
(void) show_linkprop_onelink(handle, linkid, &state);
}
+ ofmt_close(ofmt);
dladm_free_props(proplist);
if (state.ls_retstatus != DLADM_STATUS_OK) {
@@ -6442,9 +6017,10 @@ do_delete_secobj(int argc, char **argv, const char *use)
{
int i, option;
boolean_t temp = B_FALSE;
- split_t *sp = NULL;
boolean_t success;
dladm_status_t status, pstatus;
+ int nfields = 1;
+ char *field, *token, *lasts = NULL, c;
opterr = 0;
status = pstatus = DLADM_STATUS_OK;
@@ -6468,27 +6044,31 @@ do_delete_secobj(int argc, char **argv, const char *use)
}
if (optind == (argc - 1)) {
- sp = split(argv[optind], MAX_SECOBJS, MAX_SECOBJ_NAMELEN);
- if (sp == NULL) {
- die("invalid secure object name(s): '%s'",
- argv[optind]);
+ token = argv[optind];
+ if (token == NULL)
+ die("secure object name required");
+ while ((c = *token++) != NULL) {
+ if (c == ',')
+ nfields++;
}
+ token = strdup(argv[optind]);
+ if (token == NULL)
+ die("no memory");
} else if (optind != argc)
usage();
- if (sp == NULL || sp->s_nfields < 1)
- die("secure object name required");
-
success = check_auth(LINK_SEC_AUTH);
audit_secobj(LINK_SEC_AUTH, "unknown", argv[optind], success, B_FALSE);
if (!success)
die("authorization '%s' is required", LINK_SEC_AUTH);
- for (i = 0; i < sp->s_nfields; i++) {
- status = dladm_unset_secobj(handle, sp->s_fields[i],
- DLADM_OPT_ACTIVE);
+ for (i = 0; i < nfields; i++) {
+
+ field = strtok_r(token, ",", &lasts);
+ token = NULL;
+ status = dladm_unset_secobj(handle, field, DLADM_OPT_ACTIVE);
if (!temp) {
- pstatus = dladm_unset_secobj(handle, sp->s_fields[i],
+ pstatus = dladm_unset_secobj(handle, field,
DLADM_OPT_PERSIST);
} else {
pstatus = DLADM_STATUS_OK;
@@ -6496,13 +6076,14 @@ do_delete_secobj(int argc, char **argv, const char *use)
if (status != DLADM_STATUS_OK) {
warn_dlerr(status, "could not delete secure object "
- "'%s'", sp->s_fields[i]);
+ "'%s'", field);
}
if (pstatus != DLADM_STATUS_OK) {
warn_dlerr(pstatus, "could not persistently delete "
- "secure object '%s'", sp->s_fields[i]);
+ "secure object '%s'", field);
}
}
+ free(token);
if (status != DLADM_STATUS_OK || pstatus != DLADM_STATUS_OK) {
dladm_close(handle);
@@ -6512,9 +6093,9 @@ do_delete_secobj(int argc, char **argv, const char *use)
typedef struct show_secobj_state {
boolean_t ss_persist;
- boolean_t ss_parseable;
+ boolean_t ss_parsable;
boolean_t ss_header;
- print_state_t ss_print;
+ ofmt_handle_t ss_ofmt;
} show_secobj_state_t;
@@ -6539,12 +6120,6 @@ show_secobj(dladm_handle_t dh, void *arg, const char *obj_name)
if (status != DLADM_STATUS_OK)
die_dlerr(status, "cannot get secure object '%s'", obj_name);
- if (statep->ss_header) {
- statep->ss_header = B_FALSE;
- if (!statep->ss_parseable)
- print_header(&statep->ss_print);
- }
-
(void) snprintf(sbuf.ss_obj_name, sizeof (sbuf.ss_obj_name),
obj_name);
(void) dladm_secobjclass2str(class, buf);
@@ -6557,8 +6132,7 @@ show_secobj(dladm_handle_t dh, void *arg, const char *obj_name)
(void) snprintf(sbuf.ss_val,
sizeof (sbuf.ss_val), "%s", val);
}
- dladm_print_output(&statep->ss_print, statep->ss_parseable,
- dladm_print_field, (void *)&sbuf);
+ ofmt_print(statep->ss_ofmt, &sbuf);
return (B_TRUE);
}
@@ -6570,26 +6144,27 @@ do_show_secobj(int argc, char **argv, const char *use)
dladm_status_t status;
boolean_t o_arg = B_FALSE;
uint_t i;
- split_t *sp;
uint_t flags;
char *fields_str = NULL;
- print_field_t **fields;
- uint_t nfields;
char *def_fields = "object,class";
char *all_fields = "object,class,value";
+ char *field, *token, *lasts = NULL, c;
+ ofmt_handle_t ofmt;
+ ofmt_status_t oferr;
+ uint_t ofmtflags = 0;
opterr = 0;
bzero(&state, sizeof (state));
- state.ss_parseable = B_FALSE;
+ state.ss_parsable = B_FALSE;
fields_str = def_fields;
state.ss_persist = B_FALSE;
- state.ss_parseable = B_FALSE;
+ state.ss_parsable = B_FALSE;
state.ss_header = B_TRUE;
while ((option = getopt_long(argc, argv, ":pPo:",
wifi_longopts, NULL)) != -1) {
switch (option) {
case 'p':
- state.ss_parseable = B_TRUE;
+ state.ss_parsable = B_TRUE;
break;
case 'P':
state.ss_persist = B_TRUE;
@@ -6607,35 +6182,41 @@ do_show_secobj(int argc, char **argv, const char *use)
}
}
- if (state.ss_parseable && !o_arg)
+ if (state.ss_parsable && !o_arg)
die("option -c requires -o");
- if (state.ss_parseable && fields_str == all_fields)
+ if (state.ss_parsable && fields_str == all_fields)
die("\"-o all\" is invalid with -p");
- fields = parse_output_fields(fields_str, secobj_fields,
- DEV_SOBJ_FIELDS, CMD_TYPE_ANY, &nfields);
-
- if (fields == NULL) {
- die("invalid field(s) specified");
- return;
- }
- state.ss_print.ps_fields = fields;
- state.ss_print.ps_nfields = nfields;
+ if (state.ss_parsable)
+ ofmtflags |= OFMT_PARSABLE;
+ oferr = ofmt_open(fields_str, secobj_fields, ofmtflags, 0, &ofmt);
+ dladm_ofmt_check(oferr, state.ss_parsable, ofmt);
+ state.ss_ofmt = ofmt;
flags = state.ss_persist ? DLADM_OPT_PERSIST : 0;
if (optind == (argc - 1)) {
- sp = split(argv[optind], MAX_SECOBJS, MAX_SECOBJ_NAMELEN);
- if (sp == NULL) {
- die("invalid secure object name(s): '%s'",
- argv[optind]);
+ uint_t obj_fields = 1;
+
+ token = argv[optind];
+ if (token == NULL)
+ die("secure object name required");
+ while ((c = *token++) != NULL) {
+ if (c == ',')
+ obj_fields++;
}
- for (i = 0; i < sp->s_nfields; i++) {
- if (!show_secobj(handle, &state, sp->s_fields[i]))
+ token = strdup(argv[optind]);
+ if (token == NULL)
+ die("no memory");
+ for (i = 0; i < obj_fields; i++) {
+ field = strtok_r(token, ",", &lasts);
+ token = NULL;
+ if (!show_secobj(handle, &state, field))
break;
}
- splitfree(sp);
+ free(token);
+ ofmt_close(ofmt);
return;
} else if (optind != argc)
usage();
@@ -6644,6 +6225,7 @@ do_show_secobj(int argc, char **argv, const char *use)
if (status != DLADM_STATUS_OK)
die_dlerr(status, "show-secobj");
+ ofmt_close(ofmt);
}
/*ARGSUSED*/
@@ -6707,19 +6289,14 @@ do_show_ether(int argc, char **argv, const char *use)
int option;
datalink_id_t linkid;
print_ether_state_t state;
- print_field_t **fields;
- boolean_t o_arg = B_FALSE;
- char *fields_str;
- uint_t nfields;
- char *all_fields =
- "link,ptype,state,auto,speed-duplex,pause,rem_fault";
- char *default_fields =
- "link,ptype,state,auto,speed-duplex,pause";
+ char *fields_str = NULL;
+ ofmt_handle_t ofmt;
+ ofmt_status_t oferr;
+ uint_t ofmtflags = 0;
- fields_str = default_fields;
bzero(&state, sizeof (state));
state.es_link = NULL;
- state.es_parseable = B_FALSE;
+ state.es_parsable = B_FALSE;
while ((option = getopt_long(argc, argv, "o:px",
showeth_lopts, NULL)) != -1) {
@@ -6728,14 +6305,10 @@ do_show_ether(int argc, char **argv, const char *use)
state.es_extended = B_TRUE;
break;
case 'p':
- state.es_parseable = B_TRUE;
+ state.es_parsable = B_TRUE;
break;
case 'o':
- o_arg = B_TRUE;
- if (strcasecmp(optarg, "all") == 0)
- fields_str = all_fields;
- else
- fields_str = optarg;
+ fields_str = optarg;
break;
default:
die_opterr(optopt, option, use);
@@ -6743,24 +6316,15 @@ do_show_ether(int argc, char **argv, const char *use)
}
}
- if (state.es_parseable && !o_arg)
- die("-p requires -o");
-
- if (state.es_parseable && fields_str == all_fields)
- die("\"-o all\" is invalid with -p");
-
if (optind == (argc - 1))
state.es_link = argv[optind];
- fields = parse_output_fields(fields_str, ether_fields,
- ETHER_MAX_FIELDS, CMD_TYPE_ANY, &nfields);
-
- if (fields == NULL)
- die("invalid field(s) specified");
-
- state.es_print.ps_fields = fields;
- state.es_print.ps_nfields = nfields;
-
+ if (state.es_parsable)
+ ofmtflags |= OFMT_PARSABLE;
+ oferr = ofmt_open(fields_str, ether_fields, ofmtflags,
+ DLADM_DEFAULT_COL, &ofmt);
+ dladm_ofmt_check(oferr, state.es_parsable, ofmt);
+ state.es_ofmt = ofmt;
if (state.es_link == NULL) {
(void) dladm_walk_datalink_id(show_etherprop, handle, &state,
@@ -6771,15 +6335,7 @@ do_show_ether(int argc, char **argv, const char *use)
die("invalid link specified");
(void) show_etherprop(handle, linkid, &state);
}
-}
-
-static char *
-dladm_print_field(print_field_t *pf, void *arg)
-{
- char *value;
-
- value = (char *)arg + pf->pf_offset;
- return (value);
+ ofmt_close(ofmt);
}
static int
@@ -6796,11 +6352,6 @@ show_etherprop(dladm_handle_t dh, datalink_id_t linkid, void *arg)
return (DLADM_WALK_CONTINUE);
}
- if (!statep->es_header && !statep->es_parseable) {
- print_header(&statep->es_print);
- statep->es_header = B_TRUE;
- }
-
status = dladm_ether_info(dh, linkid, &eattr);
if (status != DLADM_STATUS_OK)
goto cleanup;
@@ -6820,8 +6371,7 @@ show_etherprop(dladm_handle_t dh, datalink_id_t linkid, void *arg)
(eattr.lei_attr[CURRENT].le_fault ? "fault" : "none"),
sizeof (ebuf.eth_rem_fault));
- dladm_print_output(&statep->es_print, statep->es_parseable,
- dladm_print_field, &ebuf);
+ ofmt_print(statep->es_ofmt, &ebuf);
if (statep->es_extended)
show_ether_xprop(arg, &eattr);
@@ -7043,44 +6593,11 @@ show_ether_xprop(void *arg, dladm_ether_info_t *eattr)
(void) strlcpy(ebuf.eth_rem_fault,
(eattr->lei_attr[i].le_fault ? "fault" : "none"),
sizeof (ebuf.eth_rem_fault));
- dladm_print_output(&statep->es_print, statep->es_parseable,
- dladm_print_field, &ebuf);
+ ofmt_print(statep->es_ofmt, &ebuf);
}
}
-static void
-dladm_print_output(print_state_t *statep, boolean_t parseable,
- print_callback_t fn, void *arg)
-{
- int i;
- char *value;
- print_field_t **pf;
-
- pf = statep->ps_fields;
- for (i = 0; i < statep->ps_nfields; i++) {
- statep->ps_lastfield = (i + 1 == statep->ps_nfields);
- value = (*fn)(pf[i], arg);
- if (value != NULL)
- print_field(statep, pf[i], value, parseable);
- }
- (void) putchar('\n');
-}
-
-static void
-print_header(print_state_t *ps)
-{
- int i;
- print_field_t **pf;
-
- pf = ps->ps_fields;
- for (i = 0; i < ps->ps_nfields; i++) {
- ps->ps_lastfield = (i + 1 == ps->ps_nfields);
- print_field(ps, pf[i], pf[i]->pf_header, B_FALSE);
- }
- (void) putchar('\n');
-}
-
static boolean_t
link_is_ether(const char *link, datalink_id_t *linkid)
{
@@ -7094,3 +6611,40 @@ link_is_ether(const char *link, datalink_id_t *linkid)
}
return (B_FALSE);
}
+
+/*
+ * default output callback function that, when invoked,
+ * prints string which is offset by ofmt_arg->ofmt_id within buf.
+ */
+static boolean_t
+print_default_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
+{
+ char *value;
+
+ value = (char *)ofarg->ofmt_cbarg + ofarg->ofmt_id;
+ (void) strlcpy(buf, value, bufsize);
+ return (B_TRUE);
+}
+
+static void
+dladm_ofmt_check(ofmt_status_t oferr, boolean_t parsable,
+ ofmt_handle_t ofmt)
+{
+ char buf[OFMT_BUFSIZE];
+
+ if (oferr == OFMT_SUCCESS)
+ return;
+ (void) ofmt_strerror(ofmt, oferr, buf, sizeof (buf));
+ /*
+ * All errors are considered fatal in parsable mode.
+ * NOMEM errors are always fatal, regardless of mode.
+ * For other errors, we print diagnostics in human-readable
+ * mode and processs what we can.
+ */
+ if (parsable || oferr == OFMT_ENOFIELDS) {
+ ofmt_close(ofmt);
+ die(buf);
+ } else {
+ warn(buf);
+ }
+}
diff --git a/usr/src/cmd/dladm/dladm.xcl b/usr/src/cmd/dladm/dladm.xcl
index 09192c7f4d..2c74c5fbf4 100644
--- a/usr/src/cmd/dladm/dladm.xcl
+++ b/usr/src/cmd/dladm/dladm.xcl
@@ -18,7 +18,7 @@
#
# CDDL HEADER END
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#
@@ -27,6 +27,8 @@ msgid ""
msgid "\t%-10llu"
msgid "\t%-6.1f"
msgid "\t-"
+msgid "--"
+msgid "--,"
msgid "\tipackets rbytes opackets obytes "
msgid "\n"
msgid " "
@@ -300,6 +302,7 @@ msgid "opktdist"
msgid "output"
msgid "over"
msgid "parseable"
+msgid "parsable"
msgid "pause"
msgid "pd:si:"
msgid "peeradv"
diff --git a/usr/src/cmd/flowadm/Makefile b/usr/src/cmd/flowadm/Makefile
index b6af8b2b79..2230ed1623 100644
--- a/usr/src/cmd/flowadm/Makefile
+++ b/usr/src/cmd/flowadm/Makefile
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -34,7 +34,7 @@ include ../Makefile.cmd
XGETFLAGS += -a -x $(PROG).xcl
LDLIBS += -L$(ROOT)/lib
-LDLIBS += -ldladm -lkstat
+LDLIBS += -ldladm -lkstat -linetutil
ROOTCFGDIR= $(ROOTETC)/dladm
ROOTCFGFILES= $(CONFIGFILES:%=$(ROOTCFGDIR)/%)
diff --git a/usr/src/cmd/flowadm/flowadm.c b/usr/src/cmd/flowadm/flowadm.c
index dfa718ff68..886c233fca 100644
--- a/usr/src/cmd/flowadm/flowadm.c
+++ b/usr/src/cmd/flowadm/flowadm.c
@@ -49,74 +49,27 @@
#include <inet/ip.h>
#include <inet/ip6.h>
#include <stddef.h>
-
-#define CMD_TYPE_ANY 0xffffffff
-#define STR_UNDEF_VAL "--"
-
-
-/*
- * data structures and routines for printing output.
- */
-
-typedef struct print_field_s {
- const char *pf_name;
- const char *pf_header;
- uint_t pf_width;
- union {
- uint_t _pf_index;
- size_t _pf_offset;
- }_pf_un;
-#define pf_index _pf_un._pf_index
-#define pf_offset _pf_un._pf_offset;
- uint_t pf_cmdtype;
-} print_field_t;
-
-typedef struct print_state_s {
- print_field_t **ps_fields;
- uint_t ps_nfields;
- boolean_t ps_lastfield;
- uint_t ps_overflow;
-} print_state_t;
+#include <ofmt.h>
typedef struct show_usage_state_s {
boolean_t us_plot;
- boolean_t us_parseable;
+ boolean_t us_parsable;
boolean_t us_printheader;
boolean_t us_first;
boolean_t us_showall;
- print_state_t us_print;
+ ofmt_handle_t us_ofmt;
} show_usage_state_t;
-typedef char *(*print_callback_t)(print_field_t *, void *);
-static print_field_t **parse_output_fields(char *, print_field_t *, int,
- uint_t, uint_t *);
-
-static void print_header(print_state_t *);
-static void print_field(print_state_t *, print_field_t *, const char *,
- boolean_t);
-
-static void flowadm_print_output(print_state_t *, boolean_t,
- print_callback_t, void *);
-
-/*
- * helper function that, when invoked as flowadm(print_field(pf, buf)
- * prints string which is offset by pf->pf_offset within buf.
- */
-static char *flowadm_print_field(print_field_t *, void *);
-
-#define MAX_FIELD_LEN 32
-
typedef struct show_flow_state {
boolean_t fs_firstonly;
boolean_t fs_donefirst;
pktsum_t fs_prevstats;
uint32_t fs_flags;
dladm_status_t fs_status;
- print_state_t fs_print;
+ ofmt_handle_t fs_ofmt;
const char *fs_flow;
const char *fs_link;
- boolean_t fs_parseable;
- boolean_t fs_printheader;
+ boolean_t fs_parsable;
boolean_t fs_persist;
boolean_t fs_stats;
uint64_t fs_mask;
@@ -150,6 +103,10 @@ static void die_dlerr(dladm_status_t, const char *, ...);
static void warn(const char *, ...);
static void warn_dlerr(dladm_status_t, const char *, ...);
+/* callback functions for printing output */
+static ofmt_cb_t print_flowprop_cb, print_default_cb, print_flow_stats_cb;
+static void flowadm_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t);
+
typedef struct cmd {
char *c_name;
void (*c_fn)(int, char **);
@@ -168,6 +125,7 @@ static cmd_t cmds[] = {
static const struct option longopts[] = {
{"link", required_argument, 0, 'l'},
+ {"parsable", no_argument, 0, 'p'},
{"parseable", no_argument, 0, 'p'},
{"statistics", no_argument, 0, 's'},
{"interval", required_argument, 0, 'i'},
@@ -188,7 +146,6 @@ static const struct option prop_longopts[] = {
/*
* structures for 'flowadm remove-flow'
*/
-
typedef struct remove_flow_state {
boolean_t fs_tempop;
const char *fs_altroot;
@@ -198,6 +155,7 @@ typedef struct remove_flow_state {
#define PROTO_MAXSTR_LEN 7
#define PORT_MAXSTR_LEN 6
#define DSFIELD_MAXSTR_LEN 10
+#define NULL_OFMT {NULL, 0, 0, NULL}
typedef struct flow_fields_buf_s
{
@@ -209,24 +167,23 @@ typedef struct flow_fields_buf_s
char flow_dsfield[DSFIELD_MAXSTR_LEN];
} flow_fields_buf_t;
-static print_field_t flow_fields[] = {
-/* name, header, field width, index, cmdtype */
-{ "flow", "FLOW", 11,
- offsetof(flow_fields_buf_t, flow_name), CMD_TYPE_ANY},
-{ "link", "LINK", 11,
- offsetof(flow_fields_buf_t, flow_link), CMD_TYPE_ANY},
-{ "ipaddr", "IPADDR", 30,
- offsetof(flow_fields_buf_t, flow_ipaddr), CMD_TYPE_ANY},
-{ "proto", "PROTO", 6,
- offsetof(flow_fields_buf_t, flow_proto), CMD_TYPE_ANY},
-{ "port", "PORT", 7,
- offsetof(flow_fields_buf_t, flow_port), CMD_TYPE_ANY},
-{ "dsfld", "DSFLD", 9,
- offsetof(flow_fields_buf_t, flow_dsfield), CMD_TYPE_ANY}}
+static ofmt_field_t flow_fields[] = {
+/* name, field width, index */
+{ "FLOW", 12,
+ offsetof(flow_fields_buf_t, flow_name), print_default_cb},
+{ "LINK", 12,
+ offsetof(flow_fields_buf_t, flow_link), print_default_cb},
+{ "IPADDR", 31,
+ offsetof(flow_fields_buf_t, flow_ipaddr), print_default_cb},
+{ "PROTO", 7,
+ offsetof(flow_fields_buf_t, flow_proto), print_default_cb},
+{ "PORT", 8,
+ offsetof(flow_fields_buf_t, flow_port), print_default_cb},
+{ "DSFLD", 10,
+ offsetof(flow_fields_buf_t, flow_dsfield), print_default_cb},
+NULL_OFMT}
;
-#define FLOW_MAX_FIELDS (sizeof (flow_fields) / sizeof (print_field_t))
-
/*
* structures for 'flowadm show-flowprop'
*/
@@ -238,16 +195,15 @@ typedef enum {
FLOWPROP_POSSIBLE
} flowprop_field_index_t;
-static print_field_t flowprop_fields[] = {
-/* name, header, fieldwidth, index, cmdtype */
-{ "flow", "FLOW", 12, FLOWPROP_FLOW, CMD_TYPE_ANY},
-{ "property", "PROPERTY", 15, FLOWPROP_PROPERTY, CMD_TYPE_ANY},
-{ "value", "VALUE", 14, FLOWPROP_VALUE, CMD_TYPE_ANY},
-{ "default", "DEFAULT", 14, FLOWPROP_DEFAULT, CMD_TYPE_ANY},
-{ "possible", "POSSIBLE", 20, FLOWPROP_POSSIBLE, CMD_TYPE_ANY}}
+static ofmt_field_t flowprop_fields[] = {
+/* name, fieldwidth, index, callback */
+{ "FLOW", 13, FLOWPROP_FLOW, print_flowprop_cb},
+{ "PROPERTY", 16, FLOWPROP_PROPERTY, print_flowprop_cb},
+{ "VALUE", 15, FLOWPROP_VALUE, print_flowprop_cb},
+{ "DEFAULT", 15, FLOWPROP_DEFAULT, print_flowprop_cb},
+{ "POSSIBLE", 21, FLOWPROP_POSSIBLE, print_flowprop_cb},
+NULL_OFMT}
;
-#define FLOWPROP_MAX_FIELDS \
- (sizeof (flowprop_fields) / sizeof (print_field_t))
#define MAX_PROP_LINE 512
@@ -257,12 +213,12 @@ typedef struct show_flowprop_state {
char *fs_line;
char **fs_propvals;
dladm_arg_list_t *fs_proplist;
- boolean_t fs_parseable;
+ boolean_t fs_parsable;
boolean_t fs_persist;
boolean_t fs_header;
dladm_status_t fs_status;
dladm_status_t fs_retstatus;
- print_state_t fs_print;
+ ofmt_handle_t fs_ofmt;
} show_flowprop_state_t;
typedef struct set_flowprop_state {
@@ -290,29 +246,26 @@ typedef enum {
FLOW_S_OERRORS
} flow_s_field_index_t;
-static print_field_t flow_s_fields[] = {
-/* name, header, field width, index, cmdtype */
-{ "flow", "FLOW", 15, FLOW_S_FLOW, CMD_TYPE_ANY},
-{ "ipackets", "IPACKETS", 10, FLOW_S_IPKTS, CMD_TYPE_ANY},
-{ "rbytes", "RBYTES", 8, FLOW_S_RBYTES, CMD_TYPE_ANY},
-{ "ierrors", "IERRORS", 10, FLOW_S_IERRORS, CMD_TYPE_ANY},
-{ "opackets", "OPACKETS", 12, FLOW_S_OPKTS, CMD_TYPE_ANY},
-{ "obytes", "OBYTES", 12, FLOW_S_OBYTES, CMD_TYPE_ANY},
-{ "oerrors", "OERRORS", 8, FLOW_S_OERRORS, CMD_TYPE_ANY}}
+static ofmt_field_t flow_s_fields[] = {
+/* name, field width, index, callback */
+{ "FLOW", 15, FLOW_S_FLOW, print_flow_stats_cb},
+{ "IPACKETS", 10, FLOW_S_IPKTS, print_flow_stats_cb},
+{ "RBYTES", 8, FLOW_S_RBYTES, print_flow_stats_cb},
+{ "IERRORS", 10, FLOW_S_IERRORS, print_flow_stats_cb},
+{ "OPACKETS", 12, FLOW_S_OPKTS, print_flow_stats_cb},
+{ "OBYTES", 12, FLOW_S_OBYTES, print_flow_stats_cb},
+{ "OERRORS", 8, FLOW_S_OERRORS, print_flow_stats_cb},
+NULL_OFMT}
;
-#define FLOW_S_MAX_FIELDS \
- (sizeof (flow_s_fields) / sizeof (print_field_t))
typedef struct flow_args_s {
char *flow_s_flow;
pktsum_t *flow_s_psum;
} flow_args_t;
-static char *print_flow_stats(print_field_t *, void *);
/*
* structures for 'flowadm show-usage'
*/
-
typedef struct usage_fields_buf_s {
char usage_flow[12];
char usage_duration[10];
@@ -323,26 +276,25 @@ typedef struct usage_fields_buf_s {
char usage_bandwidth[14];
} usage_fields_buf_t;
-static print_field_t usage_fields[] = {
-/* name, header, field width, offset, cmdtype */
-{ "flow", "FLOW", 12,
- offsetof(usage_fields_buf_t, usage_flow), CMD_TYPE_ANY},
-{ "duration", "DURATION", 10,
- offsetof(usage_fields_buf_t, usage_duration), CMD_TYPE_ANY},
-{ "ipackets", "IPACKETS", 9,
- offsetof(usage_fields_buf_t, usage_ipackets), CMD_TYPE_ANY},
-{ "rbytes", "RBYTES", 10,
- offsetof(usage_fields_buf_t, usage_rbytes), CMD_TYPE_ANY},
-{ "opackets", "OPACKETS", 9,
- offsetof(usage_fields_buf_t, usage_opackets), CMD_TYPE_ANY},
-{ "obytes", "OBYTES", 10,
- offsetof(usage_fields_buf_t, usage_obytes), CMD_TYPE_ANY},
-{ "bandwidth", "BANDWIDTH", 14,
- offsetof(usage_fields_buf_t, usage_bandwidth), CMD_TYPE_ANY}}
+static ofmt_field_t usage_fields[] = {
+/* name, field width, offset */
+{ "FLOW", 13,
+ offsetof(usage_fields_buf_t, usage_flow), print_default_cb},
+{ "DURATION", 11,
+ offsetof(usage_fields_buf_t, usage_duration), print_default_cb},
+{ "IPACKETS", 10,
+ offsetof(usage_fields_buf_t, usage_ipackets), print_default_cb},
+{ "RBYTES", 11,
+ offsetof(usage_fields_buf_t, usage_rbytes), print_default_cb},
+{ "OPACKETS", 10,
+ offsetof(usage_fields_buf_t, usage_opackets), print_default_cb},
+{ "OBYTES", 11,
+ offsetof(usage_fields_buf_t, usage_obytes), print_default_cb},
+{ "BANDWIDTH", 15,
+ offsetof(usage_fields_buf_t, usage_bandwidth), print_default_cb},
+NULL_OFMT}
;
-#define USAGE_MAX_FIELDS (sizeof (usage_fields) / sizeof (print_field_t))
-
/*
* structures for 'dladm show-usage link'
*/
@@ -356,25 +308,23 @@ typedef struct usage_l_fields_buf_s {
char usage_l_bandwidth[14];
} usage_l_fields_buf_t;
-static print_field_t usage_l_fields[] = {
-/* name, header, field width, offset, cmdtype */
-{ "flow", "FLOW", 12,
- offsetof(usage_l_fields_buf_t, usage_l_flow), CMD_TYPE_ANY},
-{ "start", "START", 13,
- offsetof(usage_l_fields_buf_t, usage_l_stime), CMD_TYPE_ANY},
-{ "end", "END", 13,
- offsetof(usage_l_fields_buf_t, usage_l_etime), CMD_TYPE_ANY},
-{ "rbytes", "RBYTES", 8,
- offsetof(usage_l_fields_buf_t, usage_l_rbytes), CMD_TYPE_ANY},
-{ "obytes", "OBYTES", 8,
- offsetof(usage_l_fields_buf_t, usage_l_obytes), CMD_TYPE_ANY},
-{ "bandwidth", "BANDWIDTH", 14,
- offsetof(usage_l_fields_buf_t, usage_l_bandwidth), CMD_TYPE_ANY}}
+static ofmt_field_t usage_l_fields[] = {
+/* name, field width, offset */
+{ "FLOW", 13,
+ offsetof(usage_l_fields_buf_t, usage_l_flow), print_default_cb},
+{ "START", 14,
+ offsetof(usage_l_fields_buf_t, usage_l_stime), print_default_cb},
+{ "END", 14,
+ offsetof(usage_l_fields_buf_t, usage_l_etime), print_default_cb},
+{ "RBYTES", 9,
+ offsetof(usage_l_fields_buf_t, usage_l_rbytes), print_default_cb},
+{ "OBYTES", 9,
+ offsetof(usage_l_fields_buf_t, usage_l_obytes), print_default_cb},
+{ "BANDWIDTH", 15,
+ offsetof(usage_l_fields_buf_t, usage_l_bandwidth), print_default_cb},
+NULL_OFMT}
;
-#define USAGE_L_MAX_FIELDS \
- (sizeof (usage_l_fields) /sizeof (print_field_t))
-
#define PRI_HI 100
#define PRI_LO 10
#define PRI_NORM 50
@@ -588,14 +538,7 @@ show_usage_time(dladm_usage_t *usage, void *arg)
(void) snprintf(ubuf.usage_l_bandwidth, sizeof (ubuf.usage_l_bandwidth),
"%s Mbps", dladm_bw2str(usage->du_bandwidth, buf));
- if (!state->us_parseable && !state->us_printheader) {
- print_header(&state->us_print);
- state->us_printheader = B_TRUE;
- }
-
- flowadm_print_output(&state->us_print, state->us_parseable,
- flowadm_print_field, (void *)&ubuf);
-
+ ofmt_print(state->us_ofmt, (void *)&ubuf);
return (DLADM_STATUS_OK);
}
@@ -634,13 +577,7 @@ show_usage_res(dladm_usage_t *usage, void *arg)
(void) snprintf(ubuf.usage_bandwidth, sizeof (ubuf.usage_bandwidth),
"%s Mbps", dladm_bw2str(usage->du_bandwidth, buf));
- if (!state->us_parseable && !state->us_printheader) {
- print_header(&state->us_print);
- state->us_printheader = B_TRUE;
- }
-
- flowadm_print_output(&state->us_print, state->us_parseable,
- flowadm_print_field, (void *)&ubuf);
+ ofmt_print(state->us_ofmt, (void *)&ubuf);
return (DLADM_STATUS_OK);
}
@@ -669,15 +606,16 @@ do_show_usage(int argc, char *argv[])
boolean_t F_arg = B_FALSE;
char *fields_str = NULL;
char *formatspec_str = NULL;
- print_field_t **fields;
- uint_t nfields;
char *all_fields =
"flow,duration,ipackets,rbytes,opackets,obytes,bandwidth";
char *all_l_fields =
"flow,start,end,rbytes,obytes,bandwidth";
+ ofmt_handle_t ofmt;
+ ofmt_status_t oferr;
+ uint_t ofmtflags = 0;
bzero(&state, sizeof (show_usage_state_t));
- state.us_parseable = B_FALSE;
+ state.us_parsable = B_FALSE;
state.us_printheader = B_FALSE;
state.us_plot = B_FALSE;
state.us_first = B_TRUE;
@@ -726,24 +664,22 @@ do_show_usage(int argc, char *argv[])
resource = argv[optind];
}
+ if (state.us_parsable)
+ ofmtflags |= OFMT_PARSABLE;
if (resource == NULL && stime == NULL && etime == NULL) {
if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0))
fields_str = all_fields;
- fields = parse_output_fields(fields_str, usage_fields,
- USAGE_MAX_FIELDS, CMD_TYPE_ANY, &nfields);
+ oferr = ofmt_open(fields_str, usage_fields, ofmtflags,
+ 0, &ofmt);
} else {
if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0))
fields_str = all_l_fields;
- fields = parse_output_fields(fields_str, usage_l_fields,
- USAGE_L_MAX_FIELDS, CMD_TYPE_ANY, &nfields);
+ oferr = ofmt_open(fields_str, usage_l_fields, ofmtflags,
+ 0, &ofmt);
}
- if (fields == NULL) {
- die("invalid fields(s) specified");
- return;
- }
- state.us_print.ps_fields = fields;
- state.us_print.ps_nfields = nfields;
+ flowadm_ofmt_check(oferr, state.us_parsable, ofmt);
+ state.us_ofmt = ofmt;
if (F_arg && d_arg)
die("incompatible -d and -F options");
@@ -770,6 +706,7 @@ do_show_usage(int argc, char *argv[])
DLADM_LOGTYPE_FLOW, file, stime, etime, &state);
}
+ ofmt_close(ofmt);
if (status != DLADM_STATUS_OK)
die_dlerr(status, "show-usage");
}
@@ -949,15 +886,6 @@ remove_flow(dladm_flow_attr_t *attr, void *arg)
return (DLADM_WALK_TERMINATE);
}
-static char *
-flowadm_print_field(print_field_t *pf, void *arg)
-{
- char *value;
-
- value = (char *)arg + pf->pf_offset;
- return (value);
-}
-
/*ARGSUSED*/
static dladm_status_t
print_flow(show_flow_state_t *state, dladm_flow_attr_t *attr,
@@ -1007,13 +935,7 @@ show_flow(dladm_flow_attr_t *attr, void *arg)
if (status != DLADM_STATUS_OK)
goto done;
- if (!statep->fs_parseable && !statep->fs_printheader) {
- print_header(&statep->fs_print);
- statep->fs_printheader = B_TRUE;
- }
-
- flowadm_print_output(&statep->fs_print, statep->fs_parseable,
- flowadm_print_field, (void *)&fbuf);
+ ofmt_print(statep->fs_ofmt, (void *)&fbuf);
done:
statep->fs_status = status;
@@ -1067,48 +989,47 @@ get_flow_stats(const char *flowname, pktsum_t *stats)
(void) kstat_close(kcp);
}
-
-static char *
-print_flow_stats(print_field_t *pf, void *arg)
+static boolean_t
+print_flow_stats_cb(ofmt_arg_t *of_arg, char *buf, uint_t bufsize)
{
- flow_args_t *fargs = arg;
+ flow_args_t *fargs = of_arg->ofmt_cbarg;
pktsum_t *diff_stats = fargs->flow_s_psum;
- static char buf[DLADM_STRSIZE];
- switch (pf->pf_index) {
+ switch (of_arg->ofmt_id) {
case FLOW_S_FLOW:
- (void) snprintf(buf, sizeof (buf), "%s", fargs->flow_s_flow);
+ (void) snprintf(buf, bufsize, "%s", fargs->flow_s_flow);
break;
case FLOW_S_IPKTS:
- (void) snprintf(buf, sizeof (buf), "%llu",
+ (void) snprintf(buf, bufsize, "%llu",
diff_stats->ipackets);
break;
case FLOW_S_RBYTES:
- (void) snprintf(buf, sizeof (buf), "%llu",
+ (void) snprintf(buf, bufsize, "%llu",
diff_stats->rbytes);
break;
case FLOW_S_IERRORS:
- (void) snprintf(buf, sizeof (buf), "%u",
+ (void) snprintf(buf, bufsize, "%u",
diff_stats->ierrors);
break;
case FLOW_S_OPKTS:
- (void) snprintf(buf, sizeof (buf), "%llu",
+ (void) snprintf(buf, bufsize, "%llu",
diff_stats->opackets);
break;
case FLOW_S_OBYTES:
- (void) snprintf(buf, sizeof (buf), "%llu",
+ (void) snprintf(buf, bufsize, "%llu",
diff_stats->obytes);
break;
case FLOW_S_OERRORS:
- (void) snprintf(buf, sizeof (buf), "%u",
+ (void) snprintf(buf, bufsize, "%u",
diff_stats->oerrors);
break;
default:
die("invalid input");
break;
}
- return (buf);
+ return (B_TRUE);
}
+
/* ARGSUSED */
static int
show_flow_stats(dladm_flow_attr_t *attr, void *arg)
@@ -1131,9 +1052,7 @@ show_flow_stats(dladm_flow_attr_t *attr, void *arg)
fargs.flow_s_flow = name;
fargs.flow_s_psum = &diff_stats;
- flowadm_print_output(&state->fs_print, state->fs_parseable,
- print_flow_stats, &fargs);
-
+ ofmt_print(state->fs_ofmt, (void *)&fargs);
state->fs_prevstats = stats;
return (DLADM_WALK_CONTINUE);
@@ -1160,18 +1079,13 @@ flow_stats(const char *flow, datalink_id_t linkid, uint_t interval,
char *fields_str, show_flow_state_t *state)
{
dladm_flow_attr_t attr;
- print_field_t **fields;
- uint_t nfields;
+ ofmt_handle_t ofmt;
+ ofmt_status_t oferr;
+ uint_t ofmtflags = 0;
- fields = parse_output_fields(fields_str, flow_s_fields,
- FLOW_S_MAX_FIELDS, CMD_TYPE_ANY, &nfields);
- if (fields == NULL) {
- die("invalid field(s) specified");
- return;
- }
-
- state->fs_print.ps_fields = fields;
- state->fs_print.ps_nfields = nfields;
+ oferr = ofmt_open(fields_str, flow_s_fields, ofmtflags, 0, &ofmt);
+ flowadm_ofmt_check(oferr, state->fs_parsable, ofmt);
+ state->fs_ofmt = ofmt;
if (flow != NULL &&
dladm_flow_info(handle, flow, &attr) != DLADM_STATUS_OK)
@@ -1183,8 +1097,6 @@ flow_stats(const char *flow, datalink_id_t linkid, uint_t interval,
*/
state->fs_firstonly = (interval != 0);
- if (!state->fs_parseable)
- print_header(&state->fs_print);
for (;;) {
state->fs_donefirst = B_FALSE;
@@ -1210,6 +1122,7 @@ flow_stats(const char *flow, datalink_id_t linkid, uint_t interval,
(void) sleep(interval);
}
+ ofmt_close(ofmt);
}
static void
@@ -1227,12 +1140,9 @@ do_show_flow(int argc, char *argv[])
uint32_t interval = 0;
show_flow_state_t state;
char *fields_str = NULL;
- print_field_t **fields;
- uint_t nfields;
- char *all_fields =
- "flow,link,ipaddr,proto,port,dsfld";
- char *allstat_fields =
- "flow,ipackets,rbytes,ierrors,opackets,obytes,oerrors";
+ ofmt_handle_t ofmt;
+ ofmt_status_t oferr;
+ uint_t ofmtflags = 0;
bzero(&state, sizeof (state));
@@ -1241,7 +1151,8 @@ do_show_flow(int argc, char *argv[])
longopts, NULL)) != -1) {
switch (option) {
case 'p':
- state.fs_parseable = B_TRUE;
+ state.fs_parsable = B_TRUE;
+ ofmtflags |= OFMT_PARSABLE;
break;
case 'P':
state.fs_persist = B_TRUE;
@@ -1288,7 +1199,6 @@ do_show_flow(int argc, char *argv[])
break;
}
}
-
if (i_arg && !(s_arg || S_arg))
die("the -i option can be used only with -s or -S");
@@ -1309,28 +1219,14 @@ do_show_flow(int argc, char *argv[])
return;
}
- if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) {
- if (s_arg)
- fields_str = allstat_fields;
- else
- fields_str = all_fields;
- }
-
if (s_arg) {
flow_stats(state.fs_flow, linkid, interval, fields_str, &state);
return;
}
- fields = parse_output_fields(fields_str, flow_fields, FLOW_MAX_FIELDS,
- CMD_TYPE_ANY, &nfields);
-
- if (fields == NULL) {
- die("invalid fields(s) specified");
- return;
- }
-
- state.fs_print.ps_fields = fields;
- state.fs_print.ps_nfields = nfields;
+ oferr = ofmt_open(fields_str, flow_fields, ofmtflags, 0, &ofmt);
+ flowadm_ofmt_check(oferr, state.fs_parsable, ofmt);
+ state.fs_ofmt = ofmt;
/* Show attributes of one flow */
if (state.fs_flow != NULL) {
@@ -1346,6 +1242,7 @@ do_show_flow(int argc, char *argv[])
&state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE,
DLADM_OPT_ACTIVE);
}
+ ofmt_close(ofmt);
}
static dladm_status_t
@@ -1693,8 +1590,8 @@ print_flowprop(const char *flowname, show_flowprop_state_t *statep,
ptr = buf;
lim = buf + DLADM_STRSIZE;
for (i = 0; i < valcnt; i++) {
- if (propvals[i][0] == '\0' && !statep->fs_parseable)
- ptr += snprintf(ptr, lim - ptr, STR_UNDEF_VAL",");
+ if (propvals[i][0] == '\0' && !statep->fs_parsable)
+ ptr += snprintf(ptr, lim - ptr, "--,");
else
ptr += snprintf(ptr, lim - ptr, "%s,", propvals[i]);
if (ptr >= lim)
@@ -1704,7 +1601,7 @@ print_flowprop(const char *flowname, show_flowprop_state_t *statep,
buf[strlen(buf) - 1] = '\0';
lim = statep->fs_line + MAX_PROP_LINE;
- if (statep->fs_parseable) {
+ if (statep->fs_parsable) {
*pptr += snprintf(*pptr, lim - *pptr,
"%s", buf);
} else {
@@ -1712,17 +1609,17 @@ print_flowprop(const char *flowname, show_flowprop_state_t *statep,
}
}
-static char *
-flowprop_callback(print_field_t *pf, void *fs_arg)
+static boolean_t
+print_flowprop_cb(ofmt_arg_t *of_arg, char *buf, uint_t bufsize)
{
- flowprop_args_t *arg = fs_arg;
+ flowprop_args_t *arg = of_arg->ofmt_cbarg;
char *propname = arg->fs_propname;
show_flowprop_state_t *statep = arg->fs_state;
char *ptr = statep->fs_line;
char *lim = ptr + MAX_PROP_LINE;
char *flowname = arg->fs_flowname;
- switch (pf->pf_index) {
+ switch (of_arg->ofmt_id) {
case FLOWPROP_FLOW:
(void) snprintf(ptr, lim - ptr, "%s", statep->fs_flow);
break;
@@ -1760,12 +1657,12 @@ flowprop_callback(print_field_t *pf, void *fs_arg)
die("invalid input");
break;
}
- return (ptr);
+ (void) strlcpy(buf, ptr, bufsize);
+ return (B_TRUE);
skip:
- if (statep->fs_status != DLADM_STATUS_OK)
- return (NULL);
- else
- return ("");
+ buf[0] = '\0';
+ return ((statep->fs_status == DLADM_STATUS_OK) ?
+ B_TRUE : B_FALSE);
}
static int
@@ -1779,13 +1676,7 @@ show_one_flowprop(void *arg, const char *propname)
fs_arg.fs_propname = (char *)propname;
fs_arg.fs_flowname = (char *)statep->fs_flow;
- if (statep->fs_header) {
- statep->fs_header = B_FALSE;
- if (!statep ->fs_parseable)
- print_header(&statep->fs_print);
- }
- flowadm_print_output(&statep->fs_print, statep->fs_parseable,
- flowprop_callback, (void *)&fs_arg);
+ ofmt_print(statep->fs_ofmt, (void *)&fs_arg);
return (DLADM_WALK_CONTINUE);
}
@@ -1820,20 +1711,17 @@ static void
do_show_flowprop(int argc, char **argv)
{
int option;
- boolean_t o_arg = B_FALSE;
dladm_arg_list_t *proplist = NULL;
show_flowprop_state_t state;
char *fields_str = NULL;
- print_field_t **fields;
- uint_t nfields;
- char *all_fields =
- "flow,property,value,default,possible";
+ ofmt_handle_t ofmt;
+ ofmt_status_t oferr;
+ uint_t ofmtflags = 0;
- fields_str = all_fields;
opterr = 0;
state.fs_propvals = NULL;
state.fs_line = NULL;
- state.fs_parseable = B_FALSE;
+ state.fs_parsable = B_FALSE;
state.fs_persist = B_FALSE;
state.fs_header = B_TRUE;
state.fs_retstatus = DLADM_STATUS_OK;
@@ -1849,7 +1737,8 @@ do_show_flowprop(int argc, char **argv)
die("invalid flow properties specified");
break;
case 'c':
- state.fs_parseable = B_TRUE;
+ state.fs_parsable = B_TRUE;
+ ofmtflags |= OFMT_PARSABLE;
break;
case 'P':
state.fs_persist = B_TRUE;
@@ -1860,11 +1749,7 @@ do_show_flowprop(int argc, char **argv)
die("invalid link '%s'", optarg);
break;
case 'o':
- o_arg = B_TRUE;
- if (strcasecmp(optarg, "all") == 0)
- fields_str = all_fields;
- else
- fields_str = optarg;
+ fields_str = optarg;
break;
default:
die_opterr(optopt, option);
@@ -1872,12 +1757,6 @@ do_show_flowprop(int argc, char **argv)
}
}
- if (state.fs_parseable && !o_arg)
- die("-p requires -o");
-
- if (state.fs_parseable && strcasecmp(fields_str, "all") == 0)
- die("\"-o all\" is invalid with -p");
-
if (optind == (argc - 1)) {
if (strlen(argv[optind]) >= MAXFLOWNAMELEN)
die("flow name too long");
@@ -1885,20 +1764,12 @@ do_show_flowprop(int argc, char **argv)
} else if (optind != argc) {
usage();
}
- bzero(&state.fs_print, sizeof (print_state_t));
state.fs_proplist = proplist;
state.fs_status = DLADM_STATUS_OK;
- fields = parse_output_fields(fields_str, flowprop_fields,
- FLOWPROP_MAX_FIELDS, CMD_TYPE_ANY, &nfields);
-
- if (fields == NULL) {
- die("invalid field(s) specified");
- return;
- }
-
- state.fs_print.ps_fields = fields;
- state.fs_print.ps_nfields = nfields;
+ oferr = ofmt_open(fields_str, flowprop_fields, ofmtflags, 0, &ofmt);
+ flowadm_ofmt_check(oferr, state.fs_parsable, ofmt);
+ state.fs_ofmt = ofmt;
/* Show properties for one flow */
if (state.fs_flow != NULL) {
@@ -1916,6 +1787,7 @@ do_show_flowprop(int argc, char **argv)
}
dladm_free_props(proplist);
+ ofmt_close(ofmt);
}
static void
@@ -1974,179 +1846,39 @@ show_flowprop_one_flow(void *arg, const char *flow)
statep->fs_flow = savep;
}
-typedef struct {
- char *s_buf;
- char **s_fields; /* array of pointer to the fields in s_buf */
- uint_t s_nfields; /* the number of fields in s_buf */
-} split_t;
-
-/*
- * Free the split_t structure pointed to by `sp'.
- */
-static void
-splitfree(split_t *sp)
-{
- free(sp->s_buf);
- free(sp->s_fields);
- free(sp);
-}
-
/*
- * Split `str' into at most `maxfields' fields, each field at most `maxlen' in
- * length. Return a pointer to a split_t containing the split fields, or NULL
- * on failure.
+ * default output callback function that, when invoked from dladm_print_output,
+ * prints string which is offset by of_arg->ofmt_id within buf.
*/
-static split_t *
-split(const char *str, uint_t maxfields, uint_t maxlen)
-{
- char *field, *token, *lasts = NULL;
- split_t *sp;
-
- if (*str == '\0' || maxfields == 0 || maxlen == 0)
- return (NULL);
-
- sp = calloc(sizeof (split_t), 1);
- if (sp == NULL)
- return (NULL);
-
- sp->s_buf = strdup(str);
- sp->s_fields = malloc(sizeof (char *) * maxfields);
- if (sp->s_buf == NULL || sp->s_fields == NULL)
- goto fail;
-
- token = sp->s_buf;
- while ((field = strtok_r(token, ",", &lasts)) != NULL) {
- if (sp->s_nfields == maxfields || strlen(field) > maxlen)
- goto fail;
- token = NULL;
- sp->s_fields[sp->s_nfields++] = field;
- }
- return (sp);
-fail:
- splitfree(sp);
- return (NULL);
-}
-
-static print_field_t **
-parse_output_fields(char *str, print_field_t *template, int max_fields,
- uint_t cmdtype, uint_t *countp)
-{
- split_t *sp;
- boolean_t good_match = B_FALSE;
- uint_t i, j;
- print_field_t **pf = NULL;
-
- sp = split(str, max_fields, MAX_FIELD_LEN);
-
- if (sp == NULL)
- return (NULL);
-
- pf = malloc(sp->s_nfields * sizeof (print_field_t *));
- if (pf == NULL)
- goto fail;
-
- for (i = 0; i < sp->s_nfields; i++) {
- for (j = 0; j < max_fields; j++) {
- if (strcasecmp(sp->s_fields[i],
- template[j].pf_name) == 0) {
- good_match = template[j]. pf_cmdtype & cmdtype;
- break;
- }
- }
- if (!good_match)
- goto fail;
-
- good_match = B_FALSE;
- pf[i] = &template[j];
- }
- *countp = i;
- splitfree(sp);
- return (pf);
-fail:
- free(pf);
- splitfree(sp);
- return (NULL);
-}
-
-static void
-flowadm_print_output(print_state_t *statep, boolean_t parseable,
- print_callback_t fn, void *arg)
+static boolean_t
+print_default_cb(ofmt_arg_t *of_arg, char *buf, uint_t bufsize)
{
- int i;
char *value;
- print_field_t **pf;
-
- pf = statep->ps_fields;
- for (i = 0; i < statep->ps_nfields; i++) {
- statep->ps_lastfield = (i + 1 == statep->ps_nfields);
- value = (*fn)(pf[i], arg);
- if (value != NULL)
- print_field(statep, pf[i], value, parseable);
- }
- (void) putchar('\n');
-}
-
-static void
-print_header(print_state_t *ps)
-{
- int i;
- print_field_t **pf;
- pf = ps->ps_fields;
- for (i = 0; i < ps->ps_nfields; i++) {
- ps->ps_lastfield = (i + 1 == ps->ps_nfields);
- print_field(ps, pf[i], pf[i]->pf_header, B_FALSE);
- }
- (void) putchar('\n');
+ value = (char *)of_arg->ofmt_cbarg + of_arg->ofmt_id;
+ (void) strlcpy(buf, value, bufsize);
+ return (B_TRUE);
}
static void
-print_field(print_state_t *statep, print_field_t *pfp, const char *value,
- boolean_t parseable)
+flowadm_ofmt_check(ofmt_status_t oferr, boolean_t parsable,
+ ofmt_handle_t ofmt)
{
- uint_t width = pfp->pf_width;
- uint_t valwidth;
- uint_t compress;
+ char buf[OFMT_BUFSIZE];
+ if (oferr == OFMT_SUCCESS)
+ return;
+ (void) ofmt_strerror(ofmt, oferr, buf, sizeof (buf));
/*
- * Parsable fields are separated by ':'. If such a field contains
- * a ':' or '\', this character is prefixed by a '\'.
+ * All errors are considered fatal in parsable mode.
+ * NOMEM errors are always fatal, regardless of mode.
+ * For other errors, we print diagnostics in human-readable
+ * mode and processs what we can.
*/
- if (parseable) {
- char c;
-
- if (statep->ps_nfields == 1) {
- (void) printf("%s", value);
- return;
- }
- while ((c = *value++) != '\0') {
- if (c == ':' || c == '\\')
- (void) putchar('\\');
- (void) putchar(c);
- }
- if (!statep->ps_lastfield)
- (void) putchar(':');
- return;
+ if (parsable || oferr == OFMT_ENOFIELDS) {
+ ofmt_close(ofmt);
+ die(buf);
} else {
- if (value[0] == '\0')
- value = STR_UNDEF_VAL;
- if (statep->ps_lastfield) {
- (void) printf("%s", value);
- statep->ps_overflow = 0;
- return;
- }
-
- valwidth = strlen(value);
- if (valwidth > width) {
- statep->ps_overflow += valwidth - width;
- } else if (valwidth < width && statep->ps_overflow > 0) {
- compress = min(statep->ps_overflow, width - valwidth);
- statep->ps_overflow -= compress;
- width -= compress;
- }
- (void) printf("%-*s", width, value);
+ warn(buf);
}
-
- if (!statep->ps_lastfield)
- (void) putchar(' ');
}
diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile
index bd432a268e..2ec74c85d6 100644
--- a/usr/src/lib/Makefile
+++ b/usr/src/lib/Makefile
@@ -314,6 +314,7 @@ MSGSUBDIRS= \
libidmap \
libinetcfg \
libipmp \
+ libinetutil \
libnsl \
libpam \
libpicl \
diff --git a/usr/src/lib/libinetutil/Makefile b/usr/src/lib/libinetutil/Makefile
index 980894ba78..0bc13a5c87 100644
--- a/usr/src/lib/libinetutil/Makefile
+++ b/usr/src/lib/libinetutil/Makefile
@@ -19,19 +19,22 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
#
include ../Makefile.lib
-HDRS = libinetutil.h
+HDRS = libinetutil.h ofmt.h
HDRDIR = common
SUBDIRS = $(MACH)
$(BUILD64)SUBDIRS += $(MACH64)
+POFILE = libinetutil.po
+MSGFILES = common/ofmt.c
+XGETFLAGS = -a
+
all := TARGET = all
clean := TARGET = clean
clobber := TARGET = clobber
@@ -46,9 +49,15 @@ install_h: $(ROOTHDRS)
check: $(CHECKHDRS)
+$(POFILE): $(MSGFILES)
+ $(BUILDPO.msgfiles)
+
+_msg: $(MSGDOMAINPOFILE)
+
$(SUBDIRS): FRC
@cd $@; pwd; $(MAKE) $(TARGET)
FRC:
+include $(SRC)/Makefile.msg.targ
include ../Makefile.targ
diff --git a/usr/src/lib/libinetutil/Makefile.com b/usr/src/lib/libinetutil/Makefile.com
index cd3a0d6e33..231dadfb58 100644
--- a/usr/src/lib/libinetutil/Makefile.com
+++ b/usr/src/lib/libinetutil/Makefile.com
@@ -25,7 +25,8 @@
LIBRARY = libinetutil.a
VERS = .1
-OBJECTS = octet.o inetutil.o ifspec.o ifaddrlist.o ifaddrlistx.o eh.o tq.o
+OBJECTS = octet.o inetutil.o ifspec.o ifaddrlist.o ifaddrlistx.o eh.o tq.o \
+ ofmt.o
include ../../Makefile.lib
@@ -38,7 +39,8 @@ SRCDIR = ../common
COMDIR = $(SRC)/common/net/dhcp
SRCS = $(COMDIR)/octet.c $(SRCDIR)/inetutil.c \
$(SRCDIR)/ifspec.c $(SRCDIR)/eh.c $(SRCDIR)/tq.c \
- $(SRCDIR)/ifaddrlist.c $(SRCDIR)/ifaddrlistx.c
+ $(SRCDIR)/ifaddrlist.c $(SRCDIR)/ifaddrlistx.c \
+ $(SRCDIR)/ofmt.c
$(LINTLIB):= SRCS = $(SRCDIR)/$(LINTSRC)
LDLIBS += -lsocket -lc
diff --git a/usr/src/lib/libinetutil/common/llib-linetutil b/usr/src/lib/libinetutil/common/llib-linetutil
index 5e87f60dea..9dd868fa9f 100644
--- a/usr/src/lib/libinetutil/common/llib-linetutil
+++ b/usr/src/lib/libinetutil/common/llib-linetutil
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,13 +19,12 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 2001 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/* LINTLIBRARY */
/* PROTOLIB1 */
#include <libinetutil.h>
+#include <ofmt.h>
diff --git a/usr/src/lib/libinetutil/common/mapfile-vers b/usr/src/lib/libinetutil/common/mapfile-vers
index cd0d88de08..8bc79dd4cb 100644
--- a/usr/src/lib/libinetutil/common/mapfile-vers
+++ b/usr/src/lib/libinetutil/common/mapfile-vers
@@ -63,6 +63,11 @@ SUNWprivate_1.1 {
iu_unregister_event;
octet_to_hexascii;
sockaddrcmp;
+ ofmt_open;
+ ofmt_close;
+ ofmt_print;
+ ofmt_update_winsize;
+ ofmt_strerror;
local:
*;
};
diff --git a/usr/src/lib/libinetutil/common/ofmt.c b/usr/src/lib/libinetutil/common/ofmt.c
new file mode 100644
index 0000000000..2f9fe3f91d
--- /dev/null
+++ b/usr/src/lib/libinetutil/common/ofmt.c
@@ -0,0 +1,480 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#include <errno.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <stdio.h>
+#include <ofmt.h>
+#include <sys/termios.h>
+#include <unistd.h>
+#include <sys/sysmacros.h>
+#include <libintl.h>
+
+/*
+ * functions and structures to internally process a comma-separated string
+ * of fields selected for output.
+ */
+typedef struct {
+ char *s_buf;
+ const char **s_fields; /* array of pointers to the fields in s_buf */
+ uint_t s_nfields; /* the number of fields in s_buf */
+} split_t;
+static void splitfree(split_t *);
+static split_t *split_str(const char *, uint_t);
+static split_t *split_fields(const ofmt_field_t *, uint_t, uint_t);
+
+/*
+ * The state of the output is tracked in a ofmt_state_t structure.
+ * Each os_fields[i] entry points at an ofmt_field_t array for
+ * the sub-command whose contents are provided by the caller, with
+ * os_nfields set to the number of requested fields.
+ */
+typedef struct ofmt_state_s {
+ ofmt_field_t *os_fields;
+ uint_t os_nfields;
+ boolean_t os_lastfield;
+ uint_t os_overflow;
+ struct winsize os_winsize;
+ int os_nrow;
+ boolean_t os_parsable;
+ int os_nbad;
+ char **os_badfields;
+} ofmt_state_t;
+/*
+ * A B_TRUE return value from the callback function will print out the contents
+ * of the output buffer, except when the buffer is returned with the empty
+ * string "", in which case the OFMT_VAL_UNDEF will be printed.
+ *
+ * If the callback function returns B_FALSE, the "?" string will be emitted.
+ */
+#define OFMT_VAL_UNDEF "--"
+#define OFMT_VAL_UNKNOWN "?"
+static void ofmt_print_header(ofmt_state_t *);
+static void ofmt_print_field(ofmt_state_t *, ofmt_field_t *, const char *,
+ boolean_t);
+
+/*
+ * Split `str' into at most `maxfields' fields, Return a pointer to a
+ * split_t containing the split fields, or NULL on failure.
+ */
+static split_t *
+split_str(const char *str, uint_t maxfields)
+{
+ char *field, *token, *lasts = NULL;
+ split_t *sp;
+
+ if (*str == '\0' || maxfields == 0)
+ return (NULL);
+
+ sp = calloc(sizeof (split_t), 1);
+ if (sp == NULL)
+ return (NULL);
+
+ sp->s_buf = strdup(str);
+ sp->s_fields = malloc(sizeof (char *) * maxfields);
+ if (sp->s_buf == NULL || sp->s_fields == NULL)
+ goto fail;
+
+ token = sp->s_buf;
+ while ((field = strtok_r(token, ",", &lasts)) != NULL) {
+ if (sp->s_nfields == maxfields)
+ goto fail;
+ token = NULL;
+ sp->s_fields[sp->s_nfields++] = field;
+ }
+ return (sp);
+fail:
+ splitfree(sp);
+ return (NULL);
+}
+
+/*
+ * Split `fields' into at most `maxfields' fields. Return a pointer to
+ * a split_t containing the split fields, or NULL on failure. Invoked
+ * when all fields are implicitly selected at handle creation by
+ * passing in a NULL fields_str
+ */
+static split_t *
+split_fields(const ofmt_field_t *template, uint_t maxfields, uint_t maxcols)
+{
+ split_t *sp;
+ int i, cols;
+
+ sp = calloc(sizeof (split_t), 1);
+ if (sp == NULL)
+ return (NULL);
+
+ sp->s_fields = malloc(sizeof (char *) * maxfields);
+ if (sp->s_fields == NULL)
+ goto fail;
+ cols = 0;
+ for (i = 0; i < maxfields; i++) {
+ cols += template[i].of_width;
+ /*
+ * If all fields are implied without explicitly passing
+ * in a fields_str, build a list of field names, stopping
+ * when we run out of columns.
+ */
+ if (maxcols > 0 && cols > maxcols)
+ break;
+ sp->s_fields[sp->s_nfields++] = template[i].of_name;
+ }
+ return (sp);
+fail:
+ splitfree(sp);
+ return (NULL);
+}
+
+/*
+ * Free the split_t structure pointed to by `sp'.
+ */
+static void
+splitfree(split_t *sp)
+{
+ if (sp == NULL)
+ return;
+ free(sp->s_buf);
+ free(sp->s_fields);
+ free(sp);
+}
+
+/*
+ * Open a handle to be used for printing formatted output.
+ */
+ofmt_status_t
+ofmt_open(const char *str, ofmt_field_t *template, uint_t flags,
+ uint_t maxcols, ofmt_handle_t *ofmt)
+{
+ split_t *sp;
+ uint_t i, j, of_index;
+ ofmt_field_t *of;
+ ofmt_state_t *os;
+ int nfields = 0;
+ ofmt_status_t err = OFMT_SUCCESS;
+ boolean_t parsable = (flags & OFMT_PARSABLE);
+
+ *ofmt = NULL;
+ if (parsable) {
+ /*
+ * For parsable output mode, the caller always needs
+ * to specify precisely which fields are to be selected,
+ * since the set of fields may change over time.
+ */
+ if (str == NULL || str[0] == '\0')
+ return (OFMT_EPARSENONE);
+ if (strcmp(str, "all") == 0)
+ return (OFMT_EPARSEALL);
+ }
+ if (template == NULL)
+ return (OFMT_ENOTEMPLATE);
+ for (of = template; of->of_name != NULL; of++)
+ nfields++;
+ /*
+ * split str into the columns selected, or construct the
+ * full set of columns (equivalent to -o all).
+ */
+ if (str != NULL && strcmp(str, "all") != 0) {
+ sp = split_str(str, nfields);
+ } else {
+ if (parsable || (str != NULL && strcmp(str, "all") == 0))
+ maxcols = 0;
+ sp = split_fields(template, nfields, maxcols);
+ }
+ if (sp == NULL)
+ goto nomem;
+
+ os = calloc(sizeof (ofmt_state_t) +
+ sp->s_nfields * sizeof (ofmt_field_t), 1);
+ if (os == NULL)
+ goto nomem;
+ *ofmt = os;
+ os->os_fields = (ofmt_field_t *)&os[1];
+ os->os_parsable = parsable;
+ of = os->os_fields;
+ of_index = 0;
+ /*
+ * sp->s_nfields is the number of fields requested in fields_str.
+ * nfields is the number of fields in template.
+ */
+ for (i = 0; i < sp->s_nfields; i++) {
+ for (j = 0; j < nfields; j++) {
+ if (strcasecmp(sp->s_fields[i],
+ template[j].of_name) == 0) {
+ break;
+ }
+ }
+ if (j == nfields) {
+ int nbad = os->os_nbad++;
+
+ err = OFMT_EBADFIELDS;
+ if (os->os_badfields == NULL) {
+ os->os_badfields = malloc(sp->s_nfields *
+ sizeof (char *));
+ if (os->os_badfields == NULL)
+ goto nomem;
+ }
+ os->os_badfields[nbad] = strdup(sp->s_fields[i]);
+ if (os->os_badfields[nbad] == NULL)
+ goto nomem;
+ continue;
+ }
+ of[of_index].of_name = strdup(template[j].of_name);
+ if (of[of_index].of_name == NULL)
+ goto nomem;
+ of[of_index].of_width = template[j].of_width;
+ of[of_index].of_id = template[j].of_id;
+ of[of_index].of_cb = template[j].of_cb;
+ of_index++;
+ }
+ splitfree(sp);
+ if (of_index == 0) /* all values in str are bogus */
+ return (OFMT_ENOFIELDS);
+ os->os_nfields = of_index; /* actual number of fields printed */
+ ofmt_update_winsize(*ofmt);
+ return (err);
+nomem:
+ err = OFMT_ENOMEM;
+ if (os != NULL)
+ ofmt_close(os);
+ *ofmt = NULL;
+ splitfree(sp);
+ return (err);
+}
+
+/*
+ * free resources associated with the ofmt_handle_t
+ */
+void
+ofmt_close(ofmt_handle_t ofmt)
+{
+ ofmt_state_t *os = ofmt;
+ int i;
+
+ if (os == NULL)
+ return;
+ for (i = 0; i < os->os_nfields; i++)
+ free(os->os_fields[i].of_name);
+ for (i = 0; i < os->os_nbad; i++)
+ free(os->os_badfields[i]);
+ free(os->os_badfields);
+ free(os);
+}
+
+/*
+ * Print the value for the selected field by calling the callback-function
+ * registered for the field.
+ */
+static void
+ofmt_print_field(ofmt_state_t *os, ofmt_field_t *ofp, const char *value,
+ boolean_t escsep)
+{
+ uint_t width = ofp->of_width;
+ uint_t valwidth;
+ uint_t compress;
+ boolean_t parsable = os->os_parsable;
+ char c;
+
+ /*
+ * Parsable fields are separated by ':'. If such a field contains
+ * a ':' or '\', this character is prefixed by a '\'.
+ */
+ if (parsable) {
+ if (os->os_nfields == 1) {
+ (void) printf("%s", value);
+ return;
+ }
+ while ((c = *value++) != '\0') {
+ if (escsep && ((c == ':' || c == '\\')))
+ (void) putchar('\\');
+ (void) putchar(c);
+ }
+ if (!os->os_lastfield)
+ (void) putchar(':');
+ return;
+ } else {
+ if (value[0] == '\0')
+ value = OFMT_VAL_UNDEF;
+ if (os->os_lastfield) {
+ (void) printf("%s", value);
+ os->os_overflow = 0;
+ return;
+ }
+
+ valwidth = strlen(value);
+ if (valwidth + os->os_overflow >= width) {
+ os->os_overflow += valwidth - width + 1;
+ (void) printf("%s ", value);
+ return;
+ }
+
+ if (os->os_overflow > 0) {
+ compress = MIN(os->os_overflow, width - valwidth);
+ os->os_overflow -= compress;
+ width -= compress;
+ }
+ (void) printf("%-*s", width, value);
+ }
+}
+
+/*
+ * print one row of output values for the selected columns.
+ */
+void
+ofmt_print(ofmt_handle_t ofmt, void *arg)
+{
+ ofmt_state_t *os = ofmt;
+ int i;
+ char value[1024];
+ ofmt_field_t *of;
+ boolean_t escsep;
+ ofmt_arg_t ofarg;
+
+ if ((os->os_nrow++ % os->os_winsize.ws_row) == 0 && !os->os_parsable) {
+ ofmt_print_header(os);
+ os->os_nrow++;
+ }
+
+ of = os->os_fields;
+ escsep = (os->os_nfields > 1);
+ for (i = 0; i < os->os_nfields; i++) {
+ os->os_lastfield = (i + 1 == os->os_nfields);
+ value[0] = '\0';
+ ofarg.ofmt_id = of[i].of_id;
+ ofarg.ofmt_cbarg = arg;
+ if ((*of[i].of_cb)(&ofarg, value, sizeof (value)))
+ ofmt_print_field(os, &of[i], value, escsep);
+ else
+ ofmt_print_field(os, &of[i], OFMT_VAL_UNKNOWN, escsep);
+ }
+ (void) putchar('\n');
+ (void) fflush(stdout);
+}
+
+/*
+ * Print the field headers
+ */
+static void
+ofmt_print_header(ofmt_state_t *os)
+{
+ int i;
+ ofmt_field_t *of = os->os_fields;
+ boolean_t escsep = (os->os_nfields > 1);
+
+ for (i = 0; i < os->os_nfields; i++) {
+ os->os_lastfield = (i + 1 == os->os_nfields);
+ ofmt_print_field(os, &of[i], of[i].of_name, escsep);
+ }
+ (void) putchar('\n');
+}
+
+/*
+ * Update the current window size.
+ */
+void
+ofmt_update_winsize(ofmt_handle_t ofmt)
+{
+ ofmt_state_t *os = ofmt;
+ struct winsize *winsize = &os->os_winsize;
+
+ if (ioctl(1, TIOCGWINSZ, winsize) == -1 ||
+ winsize->ws_col == 0 || winsize->ws_row == 0) {
+ winsize->ws_col = 80;
+ winsize->ws_row = 24;
+ }
+}
+
+/*
+ * Return error diagnostics using the information in the ofmt_handle_t
+ */
+char *
+ofmt_strerror(ofmt_handle_t ofmt, ofmt_status_t err, char *buf, uint_t bufsize)
+{
+ ofmt_state_t *os = ofmt;
+ int i;
+ const char *s;
+ char ebuf[OFMT_BUFSIZE];
+
+ /*
+ * ebuf is intended for optional error-specific data to be appended
+ * after the internationalized error string for an error code.
+ */
+ ebuf[0] = '\0';
+
+ switch (err) {
+ case OFMT_SUCCESS:
+ s = "success";
+ break;
+ case OFMT_EBADFIELDS:
+ /*
+ * Enumerate the singular/plural version of the warning
+ * and error to simplify and improve localization.
+ */
+ if (!os->os_parsable) {
+ if (os->os_nbad > 1)
+ s = "ignoring unknown output fields:";
+ else
+ s = "ignoring unknown output field:";
+ } else {
+ if (os->os_nbad > 1)
+ s = "unknown output fields:";
+ else
+ s = "unknown output field:";
+ }
+ /* set up the bad fields in ebuf */
+ for (i = 0; i < os->os_nbad; i++) {
+ (void) strlcat(ebuf, " `", sizeof (ebuf));
+ (void) strlcat(ebuf, os->os_badfields[i],
+ sizeof (ebuf));
+ (void) strlcat(ebuf, "'", sizeof (ebuf));
+ }
+ break;
+ case OFMT_ENOFIELDS:
+ s = "no valid output fields";
+ break;
+ case OFMT_EPARSEALL:
+ s = "output field `all' invalid in parsable mode";
+ break;
+ case OFMT_EPARSENONE:
+ s = "output fields must be specified in parsable mode";
+ break;
+ case OFMT_ENOTEMPLATE:
+ s = "no template provided for fields";
+ break;
+ case OFMT_ENOMEM:
+ s = strerror(ENOMEM);
+ break;
+ default:
+ (void) snprintf(buf, bufsize,
+ dgettext(TEXT_DOMAIN, "unknown ofmt error (%d)"),
+ err);
+ return (buf);
+ }
+ (void) snprintf(buf, bufsize, dgettext(TEXT_DOMAIN, s));
+ (void) strlcat(buf, ebuf, bufsize);
+ return (buf);
+}
diff --git a/usr/src/lib/libinetutil/common/ofmt.h b/usr/src/lib/libinetutil/common/ofmt.h
new file mode 100644
index 0000000000..ff03b80ae0
--- /dev/null
+++ b/usr/src/lib/libinetutil/common/ofmt.h
@@ -0,0 +1,198 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _OFMT_H
+#define _OFMT_H
+
+/*
+ * Data structures and routines for printing output.
+ *
+ * All output is assumed to be in a columnar format, where each column
+ * represents a field to be printed out. Multiple fields in parsable output
+ * are separated by ':', with the ':' character itself escaped by a \
+ * (e.g., IPv6 addresses may be printed as "fe80\:\:1"); single field output
+ * is printed as-is.
+ *
+ * The caller must open a handle for each set of fields to be printed by
+ * invoking ofmt_open(). The invocation to ofmt_open must provide the list of
+ * supported fields, along with formatting information (e.g., field width), and
+ * a pointer to a callback function that can provide a string representation of
+ * the value to be printed out. The set of supported fields must be a NULL
+ * terminated array of type ofmt_field_t *ofields[]. The contents of the
+ * ofmt_field_t structure are used to construct the string that is emitted by
+ * ofmt_print(), and the interpretation of these contents is described with the
+ * semantics of ofmt_print() below.
+ *
+ * In addition, the call to ofmt_open() should provide a comma-separated
+ * list of the fields, char *fields_str, that have been selected for output
+ * (typically the string passed to -o in the command-line). The caller may
+ * also specify machine-parsable mode by specifying OFMT_PARSABLE in the oflags
+ * argument. Specifying a null or empty fields_str in the machine-parsable mode
+ * will result in a returned error value of OFMT_EPARSENONE. An attempt to
+ * create a handle in machine-parsable mode with the fields_str set to "all"
+ * will result in a returned error value of OFMT_EPARSEALL. In human-friendly
+ * (non machine-parsable) mode, a NULL fields_str, or a value of "all" for
+ * fields_str, is treated as a request to print all allowable fields that fit
+ * other applicable constraints.
+ *
+ * Thus a typical invocation to open the ofmt_handle would be:
+ *
+ * ofmt_handle_t ofmt;
+ * ofmt_status_t ofmt_err;
+ *
+ * ofmt_err = ofmt_open(fields_str, ofields, oflags, maxcols, &ofmt);
+ *
+ * where ofields is an array of the form:
+ *
+ * static ofmt_field_t ofields[] = {
+ * {<name>, <field width>, <id>, <callback> },
+ * :
+ * {<name>, <field width>, <id>, <callback> },
+ * {NULL, 0, 0, NULL}}
+ *
+ * <callback> is the application-specified function that provides a string
+ * representation of the value to be printed for the field. The calling
+ * application may provide unique values of <id> that will be passed back to
+ * <callback>, allowing a single <callback> to be shared between multiple
+ * fields in ofields[] with the value of <id> identifying the field that
+ * triggers the callback.
+ *
+ * If successful, ofmt_open() will return OFMT_SUCCESS, with a non-null
+ * ofmt_handle. The function returns a failure code otherwise, and more
+ * information about the type of failure can be obtained by calling
+ * ofmt_strerror()
+ *
+ * In order to print a row of output, the calling application should invoke
+ *
+ * ofmt_print(ofmt_handle, cbarg);
+ *
+ * where 'cbarg' points at the arguments to be passed to the <callback>
+ * function for each column in the row. The call to ofmt_print() will then
+ * result in the <callback> function of each selected field from ofields[]
+ * invoked with cbarg embedded in the ofmt_arg as
+ *
+ * (*callback)(ofmt_arg_t *ofmt_arg, char *buf, uint_t bufsize)
+ *
+ * Columns selected for output are identified by a match between the of_name
+ * value in the ofmt_field_t and the fields_str requested. For each selected
+ * column, the callback function (*of_cb)() is invoked, and is passed the of_id
+ * value from the ofmt_field_t structure for the field.
+ *
+ * The interpretation of the of_id field is completely private to the caller,
+ * and can be optionally used by the callback function as a cookie
+ * to identify the field being printed when a single callback function is
+ * shared between multiple ofmt_field_t entries.
+ *
+ * The callback function should fill `buf' with the string to be printed for
+ * the field using the data in cbarg.
+ *
+ * The calling application should invoke ofmt_close(ofmt_handle) to free up any
+ * resources allocated for the handle after all printing is completed.
+ *
+ * The printing library computes the current size of the output window when the
+ * handle is first created. If the caller wishes to adjust the window size
+ * after the handle has been created (e.g., on the reception of SIGWINCH by the
+ * caller), the function ofmt_update_winsize(handle) may be called.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Recommended buffer size for buffers passed, for example, to ofmt_strerror().
+ */
+#define OFMT_BUFSIZE 256
+
+typedef enum {
+ OFMT_SUCCESS = 0,
+ OFMT_ENOMEM, /* out of memory */
+ OFMT_EBADFIELDS, /* one or more bad fields with good fields */
+ OFMT_ENOFIELDS, /* no valid output fields */
+ OFMT_EPARSEALL, /* 'all' invalid in parsable mode */
+ OFMT_EPARSENONE, /* output fields missing in parsable mode */
+ OFMT_ENOTEMPLATE /* no template provided for fields */
+} ofmt_status_t;
+
+/*
+ * The callback function for each field is invoked with a pointer to the
+ * ofmt_arg_t structure that contains the <id> registered by the application
+ * for that field, and the cbarg used by the application when invoking
+ * ofmt_output().
+ */
+typedef struct ofmt_arg_s {
+ uint_t ofmt_id;
+ void *ofmt_cbarg;
+} ofmt_arg_t;
+
+/*
+ * ofmt callback function that provides a string representation of the value to
+ * be printed for the field.
+ */
+typedef boolean_t ofmt_cb_t(ofmt_arg_t *, char *, uint_t);
+typedef struct ofmt_field_s {
+ char *of_name; /* column name */
+ uint_t of_width; /* output column width */
+ uint_t of_id; /* implementation specific cookie */
+ ofmt_cb_t *of_cb; /* callback function defined by caller */
+} ofmt_field_t;
+
+/*
+ * ofmt_open() must be called to create the ofmt_handle_t; Resources allocated
+ * for the handle are freed by ofmt_close();
+ */
+typedef struct ofmt_state_s *ofmt_handle_t;
+extern ofmt_status_t ofmt_open(const char *, ofmt_field_t *, uint_t,
+ uint_t, ofmt_handle_t *);
+
+#define OFMT_PARSABLE 0x00000001 /* machine parsable mode */
+
+/*
+ * ofmt_close() must be called to free resources associated
+ * with the ofmt_handle_t
+ */
+extern void ofmt_close(ofmt_handle_t);
+
+/*
+ * ofmt_print() emits one row of output
+ */
+extern void ofmt_print(ofmt_handle_t, void *);
+
+/*
+ * ofmt_update_winsize() updates the window size information for ofmt_handle_t
+ */
+extern void ofmt_update_winsize(ofmt_handle_t);
+
+/*
+ * ofmt_strerror() provides error diagnostics in the buffer that it is passed.
+ */
+extern char *ofmt_strerror(ofmt_handle_t, ofmt_status_t, char *, uint_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _OFMT_H */
diff --git a/usr/src/pkgdefs/etc/exception_list_i386 b/usr/src/pkgdefs/etc/exception_list_i386
index a81a4443ad..7804bef6db 100644
--- a/usr/src/pkgdefs/etc/exception_list_i386
+++ b/usr/src/pkgdefs/etc/exception_list_i386
@@ -508,6 +508,7 @@ usr/lib/libinetsvc.so i386
# the shared object is shipped.
#
usr/include/libinetutil.h i386
+usr/include/ofmt.h i386
usr/include/netinet/inetutil.h i386
usr/lib/llib-linetutil i386
usr/lib/llib-linetutil.ln i386
diff --git a/usr/src/pkgdefs/etc/exception_list_sparc b/usr/src/pkgdefs/etc/exception_list_sparc
index 834b4c05b6..41261c76ff 100644
--- a/usr/src/pkgdefs/etc/exception_list_sparc
+++ b/usr/src/pkgdefs/etc/exception_list_sparc
@@ -511,6 +511,7 @@ usr/lib/libinetsvc.so sparc
# the shared object is shipped.
#
usr/include/libinetutil.h sparc
+usr/include/ofmt.h sparc
usr/include/netinet/inetutil.h sparc
usr/lib/llib-linetutil sparc
usr/lib/llib-linetutil.ln sparc