diff options
author | Bryan Cantrill <bryan@joyent.com> | 2017-05-12 20:53:05 +0000 |
---|---|---|
committer | Bryan Cantrill <bryan@joyent.com> | 2017-05-15 23:42:11 +0000 |
commit | c5bf6dbcaf952d0108897703c878c1c0eb4be27f (patch) | |
tree | 824a414cbcbfaa82d814f9e40a949f3ceb739a5f | |
parent | d7b3c0f0f9f6c7bd9fbafc475db0d96a54372712 (diff) | |
download | illumos-joyent-c5bf6dbcaf952d0108897703c878c1c0eb4be27f.tar.gz |
OS-6057 dladm show-link segfaults if you specify too many fields
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Ryan Zezeski <ryan.zeseski@joyent.com>
Approved by: Ryan Zezeski <ryan.zeseski@joyent.com>
-rw-r--r-- | usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c | 38 | ||||
-rw-r--r-- | usr/src/cmd/dladm/dladm.c | 60 | ||||
-rw-r--r-- | usr/src/cmd/dlstat/dlstat.c | 44 | ||||
-rw-r--r-- | usr/src/cmd/flowadm/flowadm.c | 33 | ||||
-rw-r--r-- | usr/src/cmd/flowstat/flowstat.c | 33 | ||||
-rw-r--r-- | usr/src/lib/libinetutil/common/mapfile-vers | 2 | ||||
-rw-r--r-- | usr/src/lib/libinetutil/common/ofmt.c | 94 | ||||
-rw-r--r-- | usr/src/lib/libinetutil/common/ofmt.h | 8 |
8 files changed, 131 insertions, 181 deletions
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c b/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c index c4b7fd225f..041414fa85 100644 --- a/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c +++ b/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c @@ -22,6 +22,7 @@ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2017 Nexenta Systems, Inc. + * Copyright 2017 Joyent, Inc. */ #include <arpa/inet.h> @@ -63,6 +64,9 @@ static cmdfunc_t do_create_addr, do_delete_addr, do_show_addr; static cmdfunc_t do_enable_addr, do_disable_addr; static cmdfunc_t do_up_addr, do_down_addr, do_refresh_addr; +static void warn(const char *, ...); +static void die(const char *, ...); + typedef struct cmd { char *c_name; cmdfunc_t *c_fn; @@ -334,7 +338,6 @@ static char *progname; static void die(const char *, ...); static void die_opterr(int, int, const char *); static void warn_ipadmerr(ipadm_status_t, const char *, ...); -static void ipadm_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t); static void ipadm_check_propstr(const char *, boolean_t, const char *); static void process_misc_addrargs(int, char **, const char *, int *, uint32_t *); @@ -726,7 +729,7 @@ do_show_ifprop(int argc, char **argv, const char *use) if (state.sps_parsable) ofmtflags |= OFMT_PARSABLE; oferr = ofmt_open(fields_str, intfprop_fields, ofmtflags, 0, &ofmt); - ipadm_ofmt_check(oferr, state.sps_parsable, ofmt); + ofmt_check(oferr, state.sps_parsable, ofmt, die, warn); state.sps_ofmt = ofmt; /* retrieve interface(s) and print the properties */ @@ -905,7 +908,7 @@ do_show_prop(int argc, char **argv, const char *use) else ofmtflags |= OFMT_WRAP; oferr = ofmt_open(fields_str, modprop_fields, ofmtflags, 0, &ofmt); - ipadm_ofmt_check(oferr, state.sps_parsable, ofmt); + ofmt_check(oferr, state.sps_parsable, ofmt, die, warn); state.sps_ofmt = ofmt; /* handles all the errors */ @@ -1827,7 +1830,7 @@ do_show_addr(int argc, char *argv[], const char *use) fields_str = def_fields_str; oferr = ofmt_open(fields_str, show_addr_fields, ofmtflags, 0, &ofmt); - ipadm_ofmt_check(oferr, state.sa_parsable, ofmt); + ofmt_check(oferr, state.sa_parsable, ofmt, die, warn); state.sa_ofmt = ofmt; status = ipadm_addr_info(iph, ifname, &ainfo, 0, LIFC_DEFAULT); @@ -1962,7 +1965,7 @@ do_show_if(int argc, char *argv[], const char *use) if (state.si_parsable) ofmtflags |= OFMT_PARSABLE; oferr = ofmt_open(fields_str, show_if_fields, ofmtflags, 0, &ofmt); - ipadm_ofmt_check(oferr, state.si_parsable, ofmt); + ofmt_check(oferr, state.si_parsable, ofmt, die, warn); state.si_ofmt = ofmt; bzero(&sargs, sizeof (sargs)); sargs.si_state = &state; @@ -2120,7 +2123,7 @@ do_show_addrprop(int argc, char *argv[], const char *use) if (state.sps_parsable) ofmtflags |= OFMT_PARSABLE; oferr = ofmt_open(fields_str, addrprop_fields, ofmtflags, 0, &ofmt); - ipadm_ofmt_check(oferr, state.sps_parsable, ofmt); + ofmt_check(oferr, state.sps_parsable, ofmt, die, warn); state.sps_ofmt = ofmt; status = ipadm_addr_info(iph, ifname, &ainfop, 0, LIFC_DEFAULT); @@ -2166,29 +2169,6 @@ do_show_addrprop(int argc, char *argv[], const char *use) } } -static void -ipadm_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); - } -} - /* * check if the `pstr' adheres to following syntax * - prop=<value[,...]> (for set) diff --git a/usr/src/cmd/dladm/dladm.c b/usr/src/cmd/dladm/dladm.c index dce24dd440..40c28ad6ab 100644 --- a/usr/src/cmd/dladm/dladm.c +++ b/usr/src/cmd/dladm/dladm.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2015 Joyent, Inc. All rights reserved. + * Copyright 2017 Joyent, Inc. * Copyright 2016 Nexenta Systems, Inc. */ @@ -199,7 +199,6 @@ 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 ofmt_cb_t print_overlay_cb, print_overlay_fma_cb, print_overlay_targ_cb; -static void dladm_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t); typedef void cmdfunc_t(int, char **, const char *); @@ -1864,7 +1863,7 @@ do_show_usage(int argc, char *argv[], const char *use) &ofmt); } - dladm_ofmt_check(oferr, state.us_parsable, ofmt); + ofmt_check(oferr, state.us_parsable, ofmt, die, warn); state.us_ofmt = ofmt; if (d_arg) { @@ -3625,7 +3624,7 @@ do_show_link(int argc, char *argv[], const char *use) ofmtflags |= OFMT_WRAP; oferr = ofmt_open(fields_str, link_fields, ofmtflags, 0, &ofmt); - dladm_ofmt_check(oferr, state.ls_parsable, ofmt); + ofmt_check(oferr, state.ls_parsable, ofmt, die, warn); state.ls_ofmt = ofmt; if (linkid == DATALINK_ALL_LINKID) { @@ -3791,7 +3790,7 @@ do_show_aggr(int argc, char *argv[], const char *use) if (state.gs_parsable) ofmtflags |= OFMT_PARSABLE; oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt); - dladm_ofmt_check(oferr, state.gs_parsable, ofmt); + ofmt_check(oferr, state.gs_parsable, ofmt, die, warn); state.gs_ofmt = ofmt; if (s_arg) { @@ -4261,7 +4260,7 @@ do_show_iptun(int argc, char *argv[], const char *use) oferr = ofmt_open(fields_str, iptun_fields, ofmtflags, DLADM_DEFAULT_COL, &ofmt); - dladm_ofmt_check(oferr, state.ls_parsable, ofmt); + ofmt_check(oferr, state.ls_parsable, ofmt, die, warn); state.ls_ofmt = ofmt; state.ls_flags = flags; @@ -4626,7 +4625,7 @@ do_show_phys(int argc, char *argv[], const char *use) if (state.ls_parsable) ofmtflags |= OFMT_PARSABLE; oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt); - dladm_ofmt_check(oferr, state.ls_parsable, ofmt); + ofmt_check(oferr, state.ls_parsable, ofmt, die, warn); state.ls_ofmt = ofmt; if (linkid == DATALINK_ALL_LINKID) { @@ -4705,7 +4704,7 @@ do_show_vlan(int argc, char *argv[], const char *use) 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); + ofmt_check(oferr, state.ls_parsable, ofmt, die, warn); state.ls_ofmt = ofmt; if (linkid == DATALINK_ALL_LINKID) { @@ -5360,7 +5359,7 @@ do_show_vnic_common(int argc, char *argv[], const char *use, if (state.vs_parsable) ofmtflags |= OFMT_PARSABLE; oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt); - dladm_ofmt_check(oferr, state.vs_parsable, ofmt); + ofmt_check(oferr, state.vs_parsable, ofmt, die, warn); state.vs_ofmt = ofmt; if (s_arg) { @@ -5745,7 +5744,7 @@ do_show_simnet(int argc, char *argv[], const char *use) if (state.ls_parsable) ofmtflags |= OFMT_PARSABLE; oferr = ofmt_open(fields_str, simnet_fields, ofmtflags, 0, &ofmt); - dladm_ofmt_check(oferr, state.ls_parsable, ofmt); + ofmt_check(oferr, state.ls_parsable, ofmt, die, warn); state.ls_ofmt = ofmt; if (linkid == DATALINK_ALL_LINKID) { @@ -5773,7 +5772,7 @@ link_stats(datalink_id_t linkid, uint_t interval, char *fields_str, 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); + ofmt_check(oferr, state->ls_parsable, ofmt, die, warn); state->ls_ofmt = ofmt; /* @@ -6084,7 +6083,7 @@ parse_wifi_fields(char *str, ofmt_handle_t *ofmt, uint_t cmdtype, oferr = ofmt_open(str, template, (parsable ? OFMT_PARSABLE : 0), 0, ofmt); - dladm_ofmt_check(oferr, parsable, *ofmt); + ofmt_check(oferr, parsable, *ofmt, die, warn); return (0); } @@ -6899,7 +6898,7 @@ do_show_linkprop(int argc, char **argv, const char *use) ofmtflags |= OFMT_WRAP; oferr = ofmt_open(fields_str, linkprop_fields, ofmtflags, 0, &ofmt); - dladm_ofmt_check(oferr, state.ls_parsable, ofmt); + ofmt_check(oferr, state.ls_parsable, ofmt, die, warn); state.ls_ofmt = ofmt; if (linkid == DATALINK_ALL_LINKID) { @@ -7685,7 +7684,7 @@ do_show_secobj(int argc, char **argv, const char *use) 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); + ofmt_check(oferr, state.ss_parsable, ofmt, die, warn); state.ss_ofmt = ofmt; flags = state.ss_persist ? DLADM_OPT_PERSIST : 0; @@ -7817,7 +7816,7 @@ do_show_ether(int argc, char **argv, const char *use) ofmtflags |= OFMT_PARSABLE; oferr = ofmt_open(fields_str, ether_fields, ofmtflags, DLADM_DEFAULT_COL, &ofmt); - dladm_ofmt_check(oferr, state.es_parsable, ofmt); + ofmt_check(oferr, state.es_parsable, ofmt, die, warn); state.es_ofmt = ofmt; if (state.es_link == NULL) { @@ -8891,7 +8890,7 @@ do_show_bridge(int argc, char **argv, const char *use) if (parsable) ofmtflags |= OFMT_PARSABLE; oferr = ofmt_open(fields_str, field_arr, ofmtflags, 0, &ofmt); - dladm_ofmt_check(oferr, brstate.state.ls_parsable, ofmt); + ofmt_check(oferr, brstate.state.ls_parsable, ofmt, die, warn); brstate.state.ls_ofmt = ofmt; for (;;) { @@ -9262,29 +9261,6 @@ print_default_cb(ofmt_arg_t *ofarg, char *buf, uint_t 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); - } -} - /* * Called from the walker dladm_walk_datalink_id() for each IB partition to * display IB partition specific information. @@ -9482,7 +9458,7 @@ do_show_part(int argc, char *argv[], const char *use) if (state.ps_parsable) ofmtflags |= OFMT_PARSABLE; oferr = ofmt_open(fields_str, part_fields, ofmtflags, 0, &ofmt); - dladm_ofmt_check(oferr, state.ps_parsable, ofmt); + ofmt_check(oferr, state.ps_parsable, ofmt, die, warn); state.ps_ofmt = ofmt; /* @@ -9654,7 +9630,7 @@ do_show_ib(int argc, char *argv[], const char *use) if (state.is_parsable) ofmtflags |= OFMT_PARSABLE; oferr = ofmt_open(fields_str, ib_fields, ofmtflags, 0, &ofmt); - dladm_ofmt_check(oferr, state.is_parsable, ofmt); + ofmt_check(oferr, state.is_parsable, ofmt, die, warn); state.is_ofmt = ofmt; /* @@ -10455,7 +10431,7 @@ do_show_overlay(int argc, char *argv[], const char *use) fields_str = NULL; oferr = ofmt_open(fields_str, fieldsp, ofmtflags, 0, &ofmt); - dladm_ofmt_check(oferr, parse, ofmt); + ofmt_check(oferr, parse, ofmt, die, warn); err = 0; if (argc > optind) { diff --git a/usr/src/cmd/dlstat/dlstat.c b/usr/src/cmd/dlstat/dlstat.c index 2615fdbb12..8c1749475b 100644 --- a/usr/src/cmd/dlstat/dlstat.c +++ b/usr/src/cmd/dlstat/dlstat.c @@ -23,6 +23,10 @@ * Use is subject to license terms. */ +/* + * Copyright 2017 Joyent, Inc. + */ + #include <stdio.h> #include <ctype.h> #include <locale.h> @@ -88,8 +92,6 @@ typedef struct show_history_state_s { */ static ofmt_cb_t print_default_cb; -static void dlstat_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t); - typedef void cmdfunc_t(int, char **, const char *); static cmdfunc_t do_show, do_show_history, do_show_phys, do_show_link; @@ -782,7 +784,7 @@ do_show_history(int argc, char *argv[], const char *use) &ofmt); } - dlstat_ofmt_check(oferr, state.hs_parsable, ofmt); + ofmt_check(oferr, state.hs_parsable, ofmt, die, warn); state.hs_ofmt = ofmt; if (d_arg) { @@ -992,7 +994,7 @@ done: } void * -print_rx_generic_ring_stats(const char *linkname, const char *zonename, +print_rx_generic_ring_stats(const char *linkname, const char *zonename, void *statentry, char unit, boolean_t parsable) { ring_stat_entry_t *sentry = statentry; @@ -1288,7 +1290,8 @@ done: void * print_tx_lane_stats(const char *linkname, const char *zonename, void *statentry, - char unit, boolean_t parsable) { + char unit, boolean_t parsable) +{ tx_lane_stat_entry_t *sentry = statentry; tx_lane_stat_t *link_stats = &sentry->tle_stats; tx_lane_fields_buf_t *buf = NULL; @@ -1814,7 +1817,7 @@ do_show(int argc, char *argv[], const char *use) } oferr = ofmt_open(fields_str, oftemplate, ofmtflags, 0, &ofmt); - dlstat_ofmt_check(oferr, state.ls_parsable, ofmt); + ofmt_check(oferr, state.ls_parsable, ofmt, die, warn); state.ls_ofmt = ofmt; show_link_stats(linkid, state, interval); @@ -1993,7 +1996,7 @@ do_show_phys(int argc, char *argv[], const char *use) } oferr = ofmt_open(fields_str, oftemplate, ofmtflags, 0, &ofmt); - dlstat_ofmt_check(oferr, state.ls_parsable, ofmt); + ofmt_check(oferr, state.ls_parsable, ofmt, die, warn); state.ls_ofmt = ofmt; show_link_stats(linkid, state, interval); @@ -2203,7 +2206,7 @@ do_show_link(int argc, char *argv[], const char *use) } oferr = ofmt_open(fields_str, oftemplate, ofmtflags, 0, &ofmt); - dlstat_ofmt_check(oferr, state.ls_parsable, ofmt); + ofmt_check(oferr, state.ls_parsable, ofmt, die, warn); state.ls_ofmt = ofmt; @@ -2340,7 +2343,7 @@ do_show_aggr(int argc, char *argv[], const char *use) } oferr = ofmt_open(fields_str, oftemplate, ofmtflags, 0, &ofmt); - dlstat_ofmt_check(oferr, state.ls_parsable, ofmt); + ofmt_check(oferr, state.ls_parsable, ofmt, die, warn); state.ls_ofmt = ofmt; show_link_stats(linkid, state, interval); @@ -2446,26 +2449,3 @@ print_default_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) (void) strlcpy(buf, value, bufsize); return (B_TRUE); } - -static void -dlstat_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/flowadm/flowadm.c b/usr/src/cmd/flowadm/flowadm.c index 34e597dc78..a1f1c7387e 100644 --- a/usr/src/cmd/flowadm/flowadm.c +++ b/usr/src/cmd/flowadm/flowadm.c @@ -21,7 +21,10 @@ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. - * Copyright 2011 Joyent, Inc. All rights reserved. + */ + +/* + * Copyright 2017 Joyent, Inc. */ #include <stdio.h> @@ -82,7 +85,6 @@ static void warn_dlerr(dladm_status_t, const char *, ...); /* callback functions for printing output */ static ofmt_cb_t print_flowprop_cb, print_default_cb; -static void flowadm_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t); typedef struct cmd { char *c_name; @@ -661,7 +663,7 @@ do_show_flow(int argc, char *argv[]) } oferr = ofmt_open(fields_str, flow_fields, ofmtflags, 0, &ofmt); - flowadm_ofmt_check(oferr, state.fs_parsable, ofmt); + ofmt_check(oferr, state.fs_parsable, ofmt, die, warn); state.fs_ofmt = ofmt; /* Show attributes of one flow */ @@ -1205,7 +1207,7 @@ do_show_flowprop(int argc, char **argv) state.fs_status = DLADM_STATUS_OK; oferr = ofmt_open(fields_str, flowprop_fields, ofmtflags, 0, &ofmt); - flowadm_ofmt_check(oferr, state.fs_parsable, ofmt); + ofmt_check(oferr, state.fs_parsable, ofmt, die, warn); state.fs_ofmt = ofmt; /* Show properties for one flow */ @@ -1296,26 +1298,3 @@ print_default_cb(ofmt_arg_t *of_arg, char *buf, uint_t bufsize) (void) strlcpy(buf, value, bufsize); return (B_TRUE); } - -static void -flowadm_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/flowstat/flowstat.c b/usr/src/cmd/flowstat/flowstat.c index faabd74a14..ab1797922c 100644 --- a/usr/src/cmd/flowstat/flowstat.c +++ b/usr/src/cmd/flowstat/flowstat.c @@ -21,7 +21,10 @@ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. - * Copyright 2011 Joyent, Inc. All rights reserved. + */ + +/* + * Copyright 2017 Joyent, Inc. */ #include <stdio.h> @@ -87,7 +90,6 @@ static void warn(const char *, ...); /* callback functions for printing output */ static ofmt_cb_t print_default_cb, print_flow_stats_cb; -static void flowstat_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t); #define NULL_OFMT {NULL, 0, 0, NULL} @@ -719,7 +721,7 @@ main(int argc, char *argv[]) } oferr = ofmt_open(fields_str, flow_s_fields, ofmtflags, 0, &ofmt); - flowstat_ofmt_check(oferr, state.fs_parsable, ofmt); + ofmt_check(oferr, state.fs_parsable, ofmt, die, warn); state.fs_ofmt = ofmt; for (;;) { @@ -987,7 +989,7 @@ do_show_history(int argc, char *argv[]) 0, &ofmt); } - flowstat_ofmt_check(oferr, state.us_parsable, ofmt); + ofmt_check(oferr, state.us_parsable, ofmt, die, warn); state.us_ofmt = ofmt; if (F_arg && d_arg) @@ -1116,26 +1118,3 @@ print_default_cb(ofmt_arg_t *of_arg, char *buf, uint_t bufsize) (void) strlcpy(buf, value, bufsize); return (B_TRUE); } - -static void -flowstat_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/lib/libinetutil/common/mapfile-vers b/usr/src/lib/libinetutil/common/mapfile-vers index f47657c56e..39069ca83d 100644 --- a/usr/src/lib/libinetutil/common/mapfile-vers +++ b/usr/src/lib/libinetutil/common/mapfile-vers @@ -20,6 +20,7 @@ # # # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2017 Joyent, Inc. # # @@ -68,6 +69,7 @@ SYMBOL_VERSION SUNWprivate_1.1 { ofmt_print; ofmt_update_winsize; ofmt_strerror; + ofmt_check; mask2plen; plen2mask; sockaddrcmp; diff --git a/usr/src/lib/libinetutil/common/ofmt.c b/usr/src/lib/libinetutil/common/ofmt.c index 63d744cdc9..9fd1c53eee 100644 --- a/usr/src/lib/libinetutil/common/ofmt.c +++ b/usr/src/lib/libinetutil/common/ofmt.c @@ -23,6 +23,11 @@ * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ + +/* + * Copyright 2017 Joyent, Inc. + */ + #include <errno.h> #include <sys/types.h> #include <stdlib.h> @@ -34,6 +39,7 @@ #include <unistd.h> #include <sys/sysmacros.h> #include <libintl.h> +#include <assert.h> /* * functions and structures to internally process a comma-separated string @@ -45,9 +51,8 @@ typedef struct { uint_t s_nfields; /* the number of fields in s_buf */ uint_t s_currfield; /* the current field being processed */ } 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. @@ -122,26 +127,30 @@ fail: } /* - * 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 + * Split a template into its maximum number of fields (capped by the maxcols + * if it's non-zero). 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. */ static split_t * -split_fields(const ofmt_field_t *template, uint_t maxfields, uint_t maxcols) +split_max(const ofmt_field_t *template, uint_t maxcols) { + const ofmt_field_t *ofp; split_t *sp; - int i, cols; + int i, cols, nfields = 0; sp = calloc(sizeof (split_t), 1); if (sp == NULL) return (NULL); - sp->s_fields = malloc(sizeof (char *) * maxfields); + for (ofp = template; ofp->of_name != NULL; ofp++) + nfields++; + + sp->s_fields = malloc(sizeof (char *) * nfields); if (sp->s_fields == NULL) goto fail; cols = 0; - for (i = 0; i < maxfields; i++) { + for (i = 0; i < nfields; i++) { cols += template[i].of_width; /* * If all fields are implied without explicitly passing @@ -179,11 +188,10 @@ ofmt_open(const char *str, const ofmt_field_t *template, uint_t flags, uint_t maxcols, ofmt_handle_t *ofmt) { split_t *sp; - uint_t i, j, of_index; + uint_t i, of_index; const ofmt_field_t *ofp; ofmt_field_t *of; ofmt_state_t *os; - int nfields = 0; ofmt_status_t err = OFMT_SUCCESS; boolean_t parsable = (flags & OFMT_PARSABLE); boolean_t wrap = (flags & OFMT_WRAP); @@ -207,18 +215,29 @@ ofmt_open(const char *str, const ofmt_field_t *template, uint_t flags, } if (template == NULL) return (OFMT_ENOTEMPLATE); - for (ofp = template; ofp->of_name != NULL; ofp++) - nfields++; + /* * split str into the columns selected, or construct the * full set of columns (equivalent to -o all). */ if (str != NULL && strcasecmp(str, "all") != 0) { + const char *c; + int nfields = 1; + + /* + * Get an upper bound on the number of fields by counting + * the commas. + */ + for (c = str; *c != '\0'; c++) { + if (*c == ',') + nfields++; + } + sp = split_str(str, nfields); } else { if (parsable || (str != NULL && strcasecmp(str, "all") == 0)) maxcols = 0; - sp = split_fields(template, nfields, maxcols); + sp = split_max(template, maxcols); } if (sp == NULL) goto nomem; @@ -238,13 +257,12 @@ ofmt_open(const char *str, const ofmt_field_t *template, uint_t flags, * 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) { + for (ofp = template; ofp->of_name != NULL; ofp++) { + if (strcasecmp(sp->s_fields[i], ofp->of_name) == 0) break; - } } - if (j == nfields) { + + if (ofp->of_name == NULL) { int nbad = os->os_nbad++; err = OFMT_EBADFIELDS; @@ -259,7 +277,7 @@ ofmt_open(const char *str, const ofmt_field_t *template, uint_t flags, goto nomem; continue; } - of[of_index].of_name = strdup(template[j].of_name); + of[of_index].of_name = strdup(ofp->of_name); if (of[of_index].of_name == NULL) goto nomem; if (multiline) { @@ -267,9 +285,9 @@ ofmt_open(const char *str, const ofmt_field_t *template, uint_t flags, os->os_maxnamelen = MAX(n, os->os_maxnamelen); } - 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[of_index].of_width = ofp->of_width; + of[of_index].of_id = ofp->of_id; + of[of_index].of_cb = ofp->of_cb; of_index++; } splitfree(sp); @@ -611,3 +629,31 @@ ofmt_strerror(ofmt_handle_t ofmt, ofmt_status_t err, char *buf, uint_t bufsize) (void) strlcat(buf, ebuf, bufsize); return (buf); } + +void +ofmt_check(ofmt_status_t oferr, boolean_t parsable, ofmt_handle_t ofmt, + void (*die)(const char *, ...), void (*warn)(const char *, ...)) +{ + char buf[OFMT_BUFSIZE]; + + assert(die != NULL); + assert(warn != NULL); + + if (oferr == OFMT_SUCCESS) + return; + + (void) ofmt_strerror(ofmt, oferr, buf, sizeof (buf)); + + /* + * All errors are considered fatal in parsable mode. OFMT_ENOMEM and + * OFMT_ENOFIELDS 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 || oferr == OFMT_ENOMEM) { + ofmt_close(ofmt); + die(buf); + } else { + warn(buf); + } +} diff --git a/usr/src/lib/libinetutil/common/ofmt.h b/usr/src/lib/libinetutil/common/ofmt.h index e69d43e20a..f2cf1ac682 100644 --- a/usr/src/lib/libinetutil/common/ofmt.h +++ b/usr/src/lib/libinetutil/common/ofmt.h @@ -24,6 +24,10 @@ * Use is subject to license terms. */ +/* + * Copyright 2017 Joyent, Inc. + */ + #ifndef _OFMT_H #define _OFMT_H @@ -203,6 +207,10 @@ extern void ofmt_update_winsize(ofmt_handle_t); */ extern char *ofmt_strerror(ofmt_handle_t, ofmt_status_t, char *, uint_t); +extern void ofmt_check(ofmt_status_t oferr, boolean_t parsable, + ofmt_handle_t ofmt, + void (*die)(const char *, ...), void (*warn)(const char *, ...)); + #ifdef __cplusplus } #endif |