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