xref: /titanic_52/usr/src/lib/libofmt/common/ofmt.h (revision 071ca66ea5e45078699d3a2ade8c6ca5c00bba2c)
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