1*071ca66eSYuri Pankov /* 2*071ca66eSYuri Pankov * CDDL HEADER START 3*071ca66eSYuri Pankov * 4*071ca66eSYuri Pankov * The contents of this file are subject to the terms of the 5*071ca66eSYuri Pankov * Common Development and Distribution License (the "License"). 6*071ca66eSYuri Pankov * You may not use this file except in compliance with the License. 7*071ca66eSYuri Pankov * 8*071ca66eSYuri Pankov * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*071ca66eSYuri Pankov * or http://www.opensolaris.org/os/licensing. 10*071ca66eSYuri Pankov * See the License for the specific language governing permissions 11*071ca66eSYuri Pankov * and limitations under the License. 12*071ca66eSYuri Pankov * 13*071ca66eSYuri Pankov * When distributing Covered Code, include this CDDL HEADER in each 14*071ca66eSYuri Pankov * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*071ca66eSYuri Pankov * If applicable, add the following below this CDDL HEADER, with the 16*071ca66eSYuri Pankov * fields enclosed by brackets "[]" replaced with your own identifying 17*071ca66eSYuri Pankov * information: Portions Copyright [yyyy] [name of copyright owner] 18*071ca66eSYuri Pankov * 19*071ca66eSYuri Pankov * CDDL HEADER END 20*071ca66eSYuri Pankov */ 21*071ca66eSYuri Pankov 22*071ca66eSYuri Pankov /* 23*071ca66eSYuri Pankov * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24*071ca66eSYuri Pankov * Use is subject to license terms. 25*071ca66eSYuri Pankov */ 26*071ca66eSYuri Pankov 27*071ca66eSYuri Pankov #ifndef _OFMT_H 28*071ca66eSYuri Pankov #define _OFMT_H 29*071ca66eSYuri Pankov 30*071ca66eSYuri Pankov /* 31*071ca66eSYuri Pankov * Data structures and routines for printing output. 32*071ca66eSYuri Pankov * 33*071ca66eSYuri Pankov * All output is assumed to be in a columnar format, where each column 34*071ca66eSYuri Pankov * represents a field to be printed out. Multiple fields in parsable output 35*071ca66eSYuri Pankov * are separated by ':', with the ':' character itself escaped by a \ 36*071ca66eSYuri Pankov * (e.g., IPv6 addresses may be printed as "fe80\:\:1"); single field output 37*071ca66eSYuri Pankov * is printed as-is. 38*071ca66eSYuri Pankov * In multiline mode, every [field,value] pair is printed in a line of 39*071ca66eSYuri Pankov * its own, thus: "field: value". 40*071ca66eSYuri Pankov * 41*071ca66eSYuri Pankov * The caller must open a handle for each set of fields to be printed by 42*071ca66eSYuri Pankov * invoking ofmt_open(). The invocation to ofmt_open must provide the list of 43*071ca66eSYuri Pankov * supported fields, along with formatting information (e.g., field width), and 44*071ca66eSYuri Pankov * a pointer to a callback function that can provide a string representation of 45*071ca66eSYuri Pankov * the value to be printed out. The set of supported fields must be a NULL 46*071ca66eSYuri Pankov * terminated array of type ofmt_field_t *ofields[]. The contents of the 47*071ca66eSYuri Pankov * ofmt_field_t structure are used to construct the string that is emitted by 48*071ca66eSYuri Pankov * ofmt_print(), and the interpretation of these contents is described with the 49*071ca66eSYuri Pankov * semantics of ofmt_print() below. 50*071ca66eSYuri Pankov * 51*071ca66eSYuri Pankov * In addition, the call to ofmt_open() should provide a comma-separated 52*071ca66eSYuri Pankov * list of the fields, char *fields_str, that have been selected for output 53*071ca66eSYuri Pankov * (typically the string passed to -o in the command-line). The caller may 54*071ca66eSYuri Pankov * also specify machine-parsable mode by specifying OFMT_PARSABLE in the oflags 55*071ca66eSYuri Pankov * argument. Specifying a null or empty fields_str in the machine-parsable mode 56*071ca66eSYuri Pankov * will result in a returned error value of OFMT_EPARSENONE. An attempt to 57*071ca66eSYuri Pankov * create a handle in machine-parsable mode with the fields_str set to "all" 58*071ca66eSYuri Pankov * will result in a returned error value of OFMT_EPARSEALL. In human-friendly 59*071ca66eSYuri Pankov * (non machine-parsable) mode, a NULL fields_str, or a value of "all" for 60*071ca66eSYuri Pankov * fields_str, is treated as a request to print all allowable fields that fit 61*071ca66eSYuri Pankov * other applicable constraints. 62*071ca66eSYuri Pankov * To achieve multiline mode, OFMT_MULTILINE needs to be specified in oflags. 63*071ca66eSYuri Pankov * Specifying both OFMT_MULTILINE and OFMT_PARSABLE will result in 64*071ca66eSYuri Pankov * OFMT_EPARSEMULTI. 65*071ca66eSYuri Pankov * 66*071ca66eSYuri Pankov * Thus a typical invocation to open the ofmt_handle would be: 67*071ca66eSYuri Pankov * 68*071ca66eSYuri Pankov * ofmt_handle_t ofmt; 69*071ca66eSYuri Pankov * ofmt_status_t ofmt_err; 70*071ca66eSYuri Pankov * 71*071ca66eSYuri Pankov * ofmt_err = ofmt_open(fields_str, ofields, oflags, maxcols, &ofmt); 72*071ca66eSYuri Pankov * 73*071ca66eSYuri Pankov * where ofields is an array of the form: 74*071ca66eSYuri Pankov * 75*071ca66eSYuri Pankov * static ofmt_field_t ofields[] = { 76*071ca66eSYuri Pankov * {<name>, <field width>, <id>, <callback> }, 77*071ca66eSYuri Pankov * : 78*071ca66eSYuri Pankov * {<name>, <field width>, <id>, <callback> }, 79*071ca66eSYuri Pankov * {NULL, 0, 0, NULL}} 80*071ca66eSYuri Pankov * 81*071ca66eSYuri Pankov * <callback> is the application-specified function that provides a string 82*071ca66eSYuri Pankov * representation of the value to be printed for the field. The calling 83*071ca66eSYuri Pankov * application may provide unique values of <id> that will be passed back to 84*071ca66eSYuri Pankov * <callback>, allowing a single <callback> to be shared between multiple 85*071ca66eSYuri Pankov * fields in ofields[] with the value of <id> identifying the field that 86*071ca66eSYuri Pankov * triggers the callback. 87*071ca66eSYuri Pankov * 88*071ca66eSYuri Pankov * If successful, ofmt_open() will return OFMT_SUCCESS, with a non-null 89*071ca66eSYuri Pankov * ofmt_handle. The function returns a failure code otherwise, and more 90*071ca66eSYuri Pankov * information about the type of failure can be obtained by calling 91*071ca66eSYuri Pankov * ofmt_strerror() 92*071ca66eSYuri Pankov * 93*071ca66eSYuri Pankov * In order to print a row of output, the calling application should invoke 94*071ca66eSYuri Pankov * 95*071ca66eSYuri Pankov * ofmt_print(ofmt_handle, cbarg); 96*071ca66eSYuri Pankov * 97*071ca66eSYuri Pankov * where 'cbarg' points at the arguments to be passed to the <callback> 98*071ca66eSYuri Pankov * function for each column in the row. The call to ofmt_print() will then 99*071ca66eSYuri Pankov * result in the <callback> function of each selected field from ofields[] 100*071ca66eSYuri Pankov * invoked with cbarg embedded in the ofmt_arg as 101*071ca66eSYuri Pankov * 102*071ca66eSYuri Pankov * (*callback)(ofmt_arg_t *ofmt_arg, char *buf, uint_t bufsize) 103*071ca66eSYuri Pankov * 104*071ca66eSYuri Pankov * Columns selected for output are identified by a match between the of_name 105*071ca66eSYuri Pankov * value in the ofmt_field_t and the fields_str requested. For each selected 106*071ca66eSYuri Pankov * column, the callback function (*of_cb)() is invoked, and is passed the of_id 107*071ca66eSYuri Pankov * value from the ofmt_field_t structure for the field. 108*071ca66eSYuri Pankov * 109*071ca66eSYuri Pankov * The interpretation of the of_id field is completely private to the caller, 110*071ca66eSYuri Pankov * and can be optionally used by the callback function as a cookie 111*071ca66eSYuri Pankov * to identify the field being printed when a single callback function is 112*071ca66eSYuri Pankov * shared between multiple ofmt_field_t entries. 113*071ca66eSYuri Pankov * 114*071ca66eSYuri Pankov * The callback function should fill `buf' with the string to be printed for 115*071ca66eSYuri Pankov * the field using the data in cbarg. 116*071ca66eSYuri Pankov * 117*071ca66eSYuri Pankov * The calling application should invoke ofmt_close(ofmt_handle) to free up any 118*071ca66eSYuri Pankov * resources allocated for the handle after all printing is completed. 119*071ca66eSYuri Pankov * 120*071ca66eSYuri Pankov * The printing library computes the current size of the output window when the 121*071ca66eSYuri Pankov * handle is first created. If the caller wishes to adjust the window size 122*071ca66eSYuri Pankov * after the handle has been created (e.g., on the reception of SIGWINCH by the 123*071ca66eSYuri Pankov * caller), the function ofmt_update_winsize(handle) may be called. 124*071ca66eSYuri Pankov */ 125*071ca66eSYuri Pankov 126*071ca66eSYuri Pankov #ifdef __cplusplus 127*071ca66eSYuri Pankov extern "C" { 128*071ca66eSYuri Pankov #endif 129*071ca66eSYuri Pankov 130*071ca66eSYuri Pankov /* 131*071ca66eSYuri Pankov * Recommended buffer size for buffers passed, for example, to ofmt_strerror(). 132*071ca66eSYuri Pankov */ 133*071ca66eSYuri Pankov #define OFMT_BUFSIZE 256 134*071ca66eSYuri Pankov 135*071ca66eSYuri Pankov typedef enum { 136*071ca66eSYuri Pankov OFMT_SUCCESS = 0, 137*071ca66eSYuri Pankov OFMT_ENOMEM, /* out of memory */ 138*071ca66eSYuri Pankov OFMT_EBADFIELDS, /* one or more bad fields with good fields */ 139*071ca66eSYuri Pankov OFMT_ENOFIELDS, /* no valid output fields */ 140*071ca66eSYuri Pankov OFMT_EPARSEALL, /* 'all' invalid in parsable mode */ 141*071ca66eSYuri Pankov OFMT_EPARSENONE, /* output fields missing in parsable mode */ 142*071ca66eSYuri Pankov OFMT_EPARSEWRAP, /* parsable mode incompatible with wrap mode */ 143*071ca66eSYuri Pankov OFMT_ENOTEMPLATE, /* no template provided for fields */ 144*071ca66eSYuri Pankov OFMT_EPARSEMULTI /* parsable and multiline don't mix */ 145*071ca66eSYuri Pankov } ofmt_status_t; 146*071ca66eSYuri Pankov 147*071ca66eSYuri Pankov /* 148*071ca66eSYuri Pankov * The callback function for each field is invoked with a pointer to the 149*071ca66eSYuri Pankov * ofmt_arg_t structure that contains the <id> registered by the application 150*071ca66eSYuri Pankov * for that field, and the cbarg used by the application when invoking 151*071ca66eSYuri Pankov * ofmt_output(). 152*071ca66eSYuri Pankov */ 153*071ca66eSYuri Pankov typedef struct ofmt_arg_s { 154*071ca66eSYuri Pankov uint_t ofmt_id; 155*071ca66eSYuri Pankov uint_t ofmt_width; 156*071ca66eSYuri Pankov uint_t ofmt_index; 157*071ca66eSYuri Pankov void *ofmt_cbarg; 158*071ca66eSYuri Pankov } ofmt_arg_t; 159*071ca66eSYuri Pankov 160*071ca66eSYuri Pankov /* 161*071ca66eSYuri Pankov * ofmt callback function that provides a string representation of the value to 162*071ca66eSYuri Pankov * be printed for the field. 163*071ca66eSYuri Pankov */ 164*071ca66eSYuri Pankov typedef boolean_t ofmt_cb_t(ofmt_arg_t *, char *, uint_t); 165*071ca66eSYuri Pankov typedef struct ofmt_field_s { 166*071ca66eSYuri Pankov char *of_name; /* column name */ 167*071ca66eSYuri Pankov uint_t of_width; /* output column width */ 168*071ca66eSYuri Pankov uint_t of_id; /* implementation specific cookie */ 169*071ca66eSYuri Pankov ofmt_cb_t *of_cb; /* callback function defined by caller */ 170*071ca66eSYuri Pankov } ofmt_field_t; 171*071ca66eSYuri Pankov 172*071ca66eSYuri Pankov /* 173*071ca66eSYuri Pankov * ofmt_open() must be called to create the ofmt_handle_t; Resources allocated 174*071ca66eSYuri Pankov * for the handle are freed by ofmt_close(); 175*071ca66eSYuri Pankov */ 176*071ca66eSYuri Pankov typedef struct ofmt_state_s *ofmt_handle_t; 177*071ca66eSYuri Pankov extern ofmt_status_t ofmt_open(const char *, const ofmt_field_t *, uint_t, 178*071ca66eSYuri Pankov uint_t, ofmt_handle_t *); 179*071ca66eSYuri Pankov 180*071ca66eSYuri Pankov #define OFMT_PARSABLE 0x00000001 /* machine parsable mode */ 181*071ca66eSYuri Pankov #define OFMT_WRAP 0x00000002 /* wrap output if field width is exceeded */ 182*071ca66eSYuri Pankov #define OFMT_MULTILINE 0x00000004 /* "long" output: "name: value" lines */ 183*071ca66eSYuri Pankov #define OFMT_RIGHTJUST 0x00000008 /* right justified output */ 184*071ca66eSYuri Pankov 185*071ca66eSYuri Pankov /* 186*071ca66eSYuri Pankov * ofmt_close() must be called to free resources associated 187*071ca66eSYuri Pankov * with the ofmt_handle_t 188*071ca66eSYuri Pankov */ 189*071ca66eSYuri Pankov extern void ofmt_close(ofmt_handle_t); 190*071ca66eSYuri Pankov 191*071ca66eSYuri Pankov /* 192*071ca66eSYuri Pankov * ofmt_print() emits one row of output 193*071ca66eSYuri Pankov */ 194*071ca66eSYuri Pankov extern void ofmt_print(ofmt_handle_t, void *); 195*071ca66eSYuri Pankov 196*071ca66eSYuri Pankov /* 197*071ca66eSYuri Pankov * ofmt_update_winsize() updates the window size information for ofmt_handle_t 198*071ca66eSYuri Pankov */ 199*071ca66eSYuri Pankov extern void ofmt_update_winsize(ofmt_handle_t); 200*071ca66eSYuri Pankov 201*071ca66eSYuri Pankov /* 202*071ca66eSYuri Pankov * ofmt_strerror() provides error diagnostics in the buffer that it is passed. 203*071ca66eSYuri Pankov */ 204*071ca66eSYuri Pankov extern char *ofmt_strerror(ofmt_handle_t, ofmt_status_t, char *, uint_t); 205*071ca66eSYuri Pankov 206*071ca66eSYuri Pankov #ifdef __cplusplus 207*071ca66eSYuri Pankov } 208*071ca66eSYuri Pankov #endif 209*071ca66eSYuri Pankov 210*071ca66eSYuri Pankov #endif /* _OFMT_H */ 211