diff options
author | Bryan Cantrill <bryan@joyent.com> | 2017-07-14 18:27:31 +0000 |
---|---|---|
committer | Robert Mustacchi <rm@joyent.com> | 2017-09-25 18:48:01 +0000 |
commit | b2f2652061ea587b1b2b4e246659e1d7e7313f42 (patch) | |
tree | 163a3b75f1ea2b41537a1913ff506dbc309c8378 /usr/src | |
parent | 745cad278f6b2e392001dd1bf6b4e95d3f250a8d (diff) | |
download | illumos-gate-b2f2652061ea587b1b2b4e246659e1d7e7313f42.tar.gz |
8507 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>
Reviewed by: Yuri Pankov <yuripv@gmx.com>
Approved by: Richard Lowe <richlowe@richlowe.net>
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c | 38 | ||||
-rw-r--r-- | usr/src/cmd/dladm/dladm.c | 56 | ||||
-rw-r--r-- | usr/src/cmd/dlstat/dlstat.c | 39 | ||||
-rw-r--r-- | usr/src/cmd/flowadm/flowadm.c | 32 | ||||
-rw-r--r-- | usr/src/cmd/flowstat/flowstat.c | 32 | ||||
-rw-r--r-- | usr/src/lib/libofmt/common/mapfile-vers | 2 | ||||
-rw-r--r-- | usr/src/lib/libofmt/common/ofmt.c | 94 | ||||
-rw-r--r-- | usr/src/lib/libofmt/common/ofmt.h | 8 |
8 files changed, 126 insertions, 175 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 14f8a70c72..23d665cec1 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. * Copyright 2017 Gary Mills * Copyright (c) 2016, Chris Fraire <cfraire@me.com>. */ @@ -65,6 +66,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; @@ -339,7 +343,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 *); @@ -727,7 +730,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 */ @@ -906,7 +909,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 */ @@ -1851,7 +1854,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); @@ -1986,7 +1989,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; @@ -2144,7 +2147,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); @@ -2190,29 +2193,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 d5b3bd0951..8678c0939e 100644 --- a/usr/src/cmd/dladm/dladm.c +++ b/usr/src/cmd/dladm/dladm.c @@ -194,7 +194,6 @@ 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 *); @@ -1754,7 +1753,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) { @@ -3507,7 +3506,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) { @@ -3673,7 +3672,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) { @@ -4143,7 +4142,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; @@ -4508,7 +4507,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) { @@ -4587,7 +4586,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) { @@ -5204,7 +5203,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) { @@ -5589,7 +5588,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) { @@ -5617,7 +5616,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; /* @@ -5928,7 +5927,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); } @@ -6738,7 +6737,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) { @@ -7509,7 +7508,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; @@ -7641,7 +7640,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) { @@ -8715,7 +8714,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 (;;) { @@ -9043,29 +9042,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. @@ -9263,7 +9239,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; /* @@ -9435,7 +9411,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; /* diff --git a/usr/src/cmd/dlstat/dlstat.c b/usr/src/cmd/dlstat/dlstat.c index a931ba82ff..63e844a895 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; @@ -779,7 +781,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) { @@ -1800,7 +1802,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); @@ -1979,7 +1981,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); @@ -2189,7 +2191,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; @@ -2326,7 +2328,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); @@ -2432,26 +2434,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 374fa1675c..058c1e03d8 100644 --- a/usr/src/cmd/flowadm/flowadm.c +++ b/usr/src/cmd/flowadm/flowadm.c @@ -23,6 +23,10 @@ * Use is subject to license terms. */ +/* + * Copyright 2017 Joyent, Inc. + */ + #include <stdio.h> #include <locale.h> #include <stdarg.h> @@ -81,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; @@ -642,7 +645,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 */ @@ -1186,7 +1189,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 */ @@ -1277,26 +1280,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 1f8c65c957..757fcb5149 100644 --- a/usr/src/cmd/flowstat/flowstat.c +++ b/usr/src/cmd/flowstat/flowstat.c @@ -23,6 +23,10 @@ * Use is subject to license terms. */ +/* + * Copyright 2017 Joyent, Inc. + */ + #include <stdio.h> #include <locale.h> #include <stdarg.h> @@ -86,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} @@ -710,7 +713,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 (;;) { @@ -978,7 +981,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) @@ -1107,26 +1110,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/libofmt/common/mapfile-vers b/usr/src/lib/libofmt/common/mapfile-vers index b2a87b3ecc..fa94086eb6 100644 --- a/usr/src/lib/libofmt/common/mapfile-vers +++ b/usr/src/lib/libofmt/common/mapfile-vers @@ -11,6 +11,7 @@ # # Copyright 2017 Nexenta Systems, Inc. +# Copyright 2017 Joyent, Inc. # # @@ -36,6 +37,7 @@ SYMBOL_VERSION ILLUMOSprivate { ofmt_print; ofmt_strerror; ofmt_update_winsize; + ofmt_check; local: *; diff --git a/usr/src/lib/libofmt/common/ofmt.c b/usr/src/lib/libofmt/common/ofmt.c index bab3da7311..27765b0430 100644 --- a/usr/src/lib/libofmt/common/ofmt.c +++ b/usr/src/lib/libofmt/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 = NULL; - int nfields = 0; ofmt_status_t error = 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++; error = 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); @@ -612,3 +630,31 @@ ofmt_strerror(ofmt_handle_t ofmt, ofmt_status_t error, char *buf, (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/libofmt/common/ofmt.h b/usr/src/lib/libofmt/common/ofmt.h index a1146e51dc..6048367a84 100644 --- a/usr/src/lib/libofmt/common/ofmt.h +++ b/usr/src/lib/libofmt/common/ofmt.h @@ -24,6 +24,10 @@ * Use is subject to license terms. */ +/* + * Copyright 2017 Joyent, Inc. + */ + #ifndef _OFMT_H #define _OFMT_H @@ -205,6 +209,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 |