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