Print this page
11545 Want configurable output field separator for libofmt
Portions contributed by: Cody Peter Mello <cody.mello@joyent.com>
Reviewed by: Jason King <jason.king@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libofmt/common/ofmt.c
+++ new/usr/src/lib/libofmt/common/ofmt.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
↓ open down ↓ |
17 lines elided |
↑ open up ↑ |
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 /*
28 + * Copyright (c) 2015 by Delphix. All rights reserved.
28 29 * Copyright 2017 Joyent, Inc.
29 30 */
30 31
31 32 #include <errno.h>
32 33 #include <sys/types.h>
33 34 #include <stdlib.h>
34 35 #include <string.h>
35 36 #include <strings.h>
36 37 #include <stdio.h>
37 38 #include <ofmt.h>
38 39 #include <sys/termios.h>
39 40 #include <unistd.h>
40 41 #include <sys/sysmacros.h>
41 42 #include <libintl.h>
42 43 #include <assert.h>
43 44
44 45 /*
45 46 * functions and structures to internally process a comma-separated string
↓ open down ↓ |
8 lines elided |
↑ open up ↑ |
46 47 * of fields selected for output.
47 48 */
48 49 typedef struct {
49 50 char *s_buf;
50 51 const char **s_fields; /* array of pointers to the fields in s_buf */
51 52 uint_t s_nfields; /* the number of fields in s_buf */
52 53 uint_t s_currfield; /* the current field being processed */
53 54 } split_t;
54 55
55 56 static void splitfree(split_t *);
57 +static split_t *split_str(const char *, uint_t);
58 +static split_t *split_fields(const ofmt_field_t *, uint_t, uint_t);
56 59
57 60 /*
58 61 * The state of the output is tracked in a ofmt_state_t structure.
59 62 * Each os_fields[i] entry points at an ofmt_field_t array for
60 63 * the sub-command whose contents are provided by the caller, with
61 64 * os_nfields set to the number of requested fields.
62 65 */
63 66 typedef struct ofmt_state_s {
64 - ofmt_field_t *os_fields;
67 + ofmt_field_t *os_fields;
65 68 uint_t os_nfields;
66 69 boolean_t os_lastfield;
67 70 uint_t os_overflow;
68 71 struct winsize os_winsize;
69 72 int os_nrow;
70 73 uint_t os_flags;
71 74 int os_nbad;
72 75 char **os_badfields;
73 76 int os_maxnamelen; /* longest name (f. multiline) */
77 + char os_fs; /* field seperator */
74 78 } ofmt_state_t;
75 79 /*
76 80 * A B_TRUE return value from the callback function will print out the contents
77 81 * of the output buffer, except when the buffer is returned with the empty
78 82 * string "", in which case the OFMT_VAL_UNDEF will be printed.
79 83 *
80 84 * If the callback function returns B_FALSE, the "?" string will be emitted.
81 85 */
82 86 #define OFMT_VAL_UNDEF "--"
83 87 #define OFMT_VAL_UNKNOWN "?"
84 88
89 +#define OFMT_DEFAULT_FS ':'
90 +
85 91 /*
86 92 * The maximum number of rows supported by the OFMT_WRAP option.
87 93 */
88 94 #define OFMT_MAX_ROWS 128
89 95
90 -static void ofmt_print_header(ofmt_state_t *);
91 96 static void ofmt_print_field(ofmt_state_t *, ofmt_field_t *, const char *,
92 97 boolean_t);
93 98
94 99 /*
95 100 * Split `str' into at most `maxfields' fields, Return a pointer to a
96 101 * split_t containing the split fields, or NULL on failure.
97 102 */
98 103 static split_t *
99 104 split_str(const char *str, uint_t maxfields)
100 105 {
101 106 char *field, *token, *lasts = NULL;
102 107 split_t *sp;
103 108
104 109 if (*str == '\0' || maxfields == 0)
105 110 return (NULL);
106 111
107 112 sp = calloc(sizeof (split_t), 1);
108 113 if (sp == NULL)
109 114 return (NULL);
110 115
111 116 sp->s_buf = strdup(str);
112 117 sp->s_fields = malloc(sizeof (char *) * maxfields);
113 118 if (sp->s_buf == NULL || sp->s_fields == NULL)
114 119 goto fail;
115 120
116 121 token = sp->s_buf;
117 122 while ((field = strtok_r(token, ",", &lasts)) != NULL) {
118 123 if (sp->s_nfields == maxfields)
119 124 goto fail;
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
120 125 token = NULL;
121 126 sp->s_fields[sp->s_nfields++] = field;
122 127 }
123 128 return (sp);
124 129 fail:
125 130 splitfree(sp);
126 131 return (NULL);
127 132 }
128 133
129 134 /*
130 - * Split a template into its maximum number of fields (capped by the maxcols
131 - * if it's non-zero). Return a pointer to a split_t containing the split
132 - * fields, or NULL on failure. Invoked when all fields are implicitly
133 - * selected at handle creation.
135 + * Split `fields' into at most `maxfields' fields. Return a pointer to
136 + * a split_t containing the split fields, or NULL on failure. Invoked
137 + * when all fields are implicitly selected at handle creation by
138 + * passing in a NULL fields_str
134 139 */
135 140 static split_t *
136 -split_max(const ofmt_field_t *template, uint_t maxcols)
141 +split_fields(const ofmt_field_t *template, uint_t maxfields, uint_t maxcols)
137 142 {
138 - const ofmt_field_t *ofp;
139 143 split_t *sp;
140 - int i, cols, nfields = 0;
144 + int i, cols;
141 145
142 146 sp = calloc(sizeof (split_t), 1);
143 147 if (sp == NULL)
144 148 return (NULL);
145 149
146 - for (ofp = template; ofp->of_name != NULL; ofp++)
147 - nfields++;
148 -
149 - sp->s_fields = malloc(sizeof (char *) * nfields);
150 + sp->s_fields = malloc(sizeof (char *) * maxfields);
150 151 if (sp->s_fields == NULL)
151 152 goto fail;
152 153 cols = 0;
153 - for (i = 0; i < nfields; i++) {
154 + for (i = 0; i < maxfields; i++) {
154 155 cols += template[i].of_width;
155 156 /*
156 157 * If all fields are implied without explicitly passing
157 158 * in a fields_str, build a list of field names, stopping
158 159 * when we run out of columns.
159 160 */
160 161 if (maxcols > 0 && cols > maxcols)
161 162 break;
162 163 sp->s_fields[sp->s_nfields++] = template[i].of_name;
163 164 }
164 165 return (sp);
165 166 fail:
166 167 splitfree(sp);
167 168 return (NULL);
168 169 }
169 170
170 171 /*
171 172 * Free the split_t structure pointed to by `sp'.
172 173 */
173 174 static void
174 175 splitfree(split_t *sp)
175 176 {
176 177 if (sp == NULL)
177 178 return;
178 179 free(sp->s_buf);
179 180 free(sp->s_fields);
180 181 free(sp);
↓ open down ↓ |
17 lines elided |
↑ open up ↑ |
181 182 }
182 183
183 184 /*
184 185 * Open a handle to be used for printing formatted output.
185 186 */
186 187 ofmt_status_t
187 188 ofmt_open(const char *str, const ofmt_field_t *template, uint_t flags,
188 189 uint_t maxcols, ofmt_handle_t *ofmt)
189 190 {
190 191 split_t *sp;
191 - uint_t i, of_index;
192 + uint_t i, j, of_index;
192 193 const ofmt_field_t *ofp;
193 194 ofmt_field_t *of;
194 195 ofmt_state_t *os = NULL;
196 + uint_t nfields = 0;
195 197 ofmt_status_t error = OFMT_SUCCESS;
196 198 boolean_t parsable = (flags & OFMT_PARSABLE);
197 199 boolean_t wrap = (flags & OFMT_WRAP);
198 200 boolean_t multiline = (flags & OFMT_MULTILINE);
199 201
200 202 *ofmt = NULL;
201 203 if (parsable) {
202 204 if (multiline)
203 205 return (OFMT_EPARSEMULTI);
204 206 /*
205 207 * For parsable output mode, the caller always needs
206 208 * to specify precisely which fields are to be selected,
207 209 * since the set of fields may change over time.
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
208 210 */
209 211 if (str == NULL || str[0] == '\0')
210 212 return (OFMT_EPARSENONE);
211 213 if (strcasecmp(str, "all") == 0)
212 214 return (OFMT_EPARSEALL);
213 215 if (wrap)
214 216 return (OFMT_EPARSEWRAP);
215 217 }
216 218 if (template == NULL)
217 219 return (OFMT_ENOTEMPLATE);
218 -
220 + for (ofp = template; ofp->of_name != NULL; ofp++)
221 + nfields++;
219 222 /*
220 223 * split str into the columns selected, or construct the
221 224 * full set of columns (equivalent to -o all).
222 225 */
223 226 if (str != NULL && strcasecmp(str, "all") != 0) {
224 - const char *c;
225 - int nfields = 1;
226 -
227 - /*
228 - * Get an upper bound on the number of fields by counting
229 - * the commas.
230 - */
231 - for (c = str; *c != '\0'; c++) {
232 - if (*c == ',')
233 - nfields++;
234 - }
235 -
236 227 sp = split_str(str, nfields);
237 228 } else {
238 229 if (parsable || (str != NULL && strcasecmp(str, "all") == 0))
239 230 maxcols = 0;
240 - sp = split_max(template, maxcols);
231 + sp = split_fields(template, nfields, maxcols);
241 232 }
242 233 if (sp == NULL)
243 234 goto nomem;
244 235
245 236 os = calloc(sizeof (ofmt_state_t) +
246 237 sp->s_nfields * sizeof (ofmt_field_t), 1);
247 238 if (os == NULL)
248 239 goto nomem;
249 240 *ofmt = os;
250 241 os->os_fields = (ofmt_field_t *)&os[1];
251 242 os->os_flags = flags;
243 + os->os_fs = OFMT_DEFAULT_FS;
252 244
253 245 of = os->os_fields;
254 246 of_index = 0;
255 247 /*
256 248 * sp->s_nfields is the number of fields requested in fields_str.
257 249 * nfields is the number of fields in template.
258 250 */
259 251 for (i = 0; i < sp->s_nfields; i++) {
260 - for (ofp = template; ofp->of_name != NULL; ofp++) {
261 - if (strcasecmp(sp->s_fields[i], ofp->of_name) == 0)
252 + for (j = 0; j < nfields; j++) {
253 + if (strcasecmp(sp->s_fields[i],
254 + template[j].of_name) == 0) {
262 255 break;
256 + }
263 257 }
264 -
265 - if (ofp->of_name == NULL) {
258 + if (j == nfields) {
266 259 int nbad = os->os_nbad++;
267 260
268 261 error = OFMT_EBADFIELDS;
269 262 if (os->os_badfields == NULL) {
270 263 os->os_badfields = malloc(sp->s_nfields *
271 264 sizeof (char *));
272 265 if (os->os_badfields == NULL)
273 266 goto nomem;
274 267 }
275 268 os->os_badfields[nbad] = strdup(sp->s_fields[i]);
276 269 if (os->os_badfields[nbad] == NULL)
277 270 goto nomem;
278 271 continue;
279 272 }
280 - of[of_index].of_name = strdup(ofp->of_name);
273 + of[of_index].of_name = strdup(template[j].of_name);
281 274 if (of[of_index].of_name == NULL)
282 275 goto nomem;
283 276 if (multiline) {
284 277 int n = strlen(of[of_index].of_name);
285 278
286 279 os->os_maxnamelen = MAX(n, os->os_maxnamelen);
287 280 }
288 - of[of_index].of_width = ofp->of_width;
289 - of[of_index].of_id = ofp->of_id;
290 - of[of_index].of_cb = ofp->of_cb;
281 + of[of_index].of_width = template[j].of_width;
282 + of[of_index].of_id = template[j].of_id;
283 + of[of_index].of_cb = template[j].of_cb;
291 284 of_index++;
292 285 }
293 286 splitfree(sp);
294 287 if (of_index == 0) /* all values in str are bogus */
295 288 return (OFMT_ENOFIELDS);
296 289 os->os_nfields = of_index; /* actual number of fields printed */
297 290 ofmt_update_winsize(*ofmt);
298 291 return (error);
299 292 nomem:
300 293 error = OFMT_ENOMEM;
301 294 if (os != NULL)
302 295 ofmt_close(os);
303 296 *ofmt = NULL;
304 297 splitfree(sp);
305 298 return (error);
306 299 }
307 300
301 +void
302 +ofmt_set_fs(ofmt_handle_t ofmt, char fs)
303 +{
304 + ((ofmt_state_t *)ofmt)->os_fs = fs;
305 +}
306 +
308 307 /*
309 308 * free resources associated with the ofmt_handle_t
310 309 */
311 310 void
312 311 ofmt_close(ofmt_handle_t ofmt)
313 312 {
314 313 ofmt_state_t *os = ofmt;
315 314 int i;
316 315
317 316 if (os == NULL)
318 317 return;
319 318 for (i = 0; i < os->os_nfields; i++)
320 319 free(os->os_fields[i].of_name);
321 320 for (i = 0; i < os->os_nbad; i++)
322 321 free(os->os_badfields[i]);
323 322 free(os->os_badfields);
324 323 free(os);
325 324 }
326 325
327 326 /*
328 327 * Print the value for the selected field by calling the callback-function
329 328 * registered for the field.
330 329 */
331 330 static void
332 331 ofmt_print_field(ofmt_state_t *os, ofmt_field_t *ofp, const char *value,
333 332 boolean_t escsep)
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
334 333 {
335 334 uint_t width = ofp->of_width;
336 335 uint_t valwidth;
337 336 uint_t compress;
338 337 boolean_t parsable = (os->os_flags & OFMT_PARSABLE);
339 338 boolean_t multiline = (os->os_flags & OFMT_MULTILINE);
340 339 boolean_t rightjust = (os->os_flags & OFMT_RIGHTJUST);
341 340 char c;
342 341
343 342 /*
344 - * Parsable fields are separated by ':'. If such a field contains
345 - * a ':' or '\', this character is prefixed by a '\'.
343 + * Parsable fields are separated by os_fs. os_fs and '\' are escaped
344 + * (prefixed by a) '\'.
346 345 */
347 346 if (parsable) {
348 347 if (os->os_nfields == 1) {
349 348 (void) printf("%s", value);
350 349 return;
351 350 }
352 351 while ((c = *value++) != '\0') {
353 - if (escsep && ((c == ':' || c == '\\')))
352 + if (escsep && ((c == os->os_fs || c == '\\')))
354 353 (void) putchar('\\');
355 354 (void) putchar(c);
356 355 }
357 356 if (!os->os_lastfield)
358 - (void) putchar(':');
357 + (void) putchar(os->os_fs);
359 358 } else if (multiline) {
360 359 if (value[0] == '\0')
361 360 value = OFMT_VAL_UNDEF;
362 361 (void) printf("%*.*s: %s", os->os_maxnamelen,
363 362 os->os_maxnamelen, ofp->of_name, value);
364 363 if (!os->os_lastfield)
365 364 (void) putchar('\n');
366 365 } else {
367 366 if (os->os_lastfield) {
368 367 if (rightjust)
369 368 (void) printf("%*s", width, value);
370 369 else
371 370 (void) printf("%s", value);
372 371 os->os_overflow = 0;
373 372 return;
374 373 }
375 374
376 375 valwidth = strlen(value);
377 376 if (valwidth + os->os_overflow >= width) {
378 377 os->os_overflow += valwidth - width + 1;
379 378 if (rightjust)
380 379 (void) printf("%*s ", width, value);
381 380 else
382 381 (void) printf("%s ", value);
383 382 return;
384 383 }
385 384
386 385 if (os->os_overflow > 0) {
387 386 compress = MIN(os->os_overflow, width - valwidth);
388 387 os->os_overflow -= compress;
389 388 width -= compress;
390 389 }
391 390 if (rightjust)
392 391 (void) printf("%*s ", width, value);
393 392 else
394 393 (void) printf("%-*s", width, value);
395 394 }
396 395 }
397 396
398 397 /*
399 398 * Print enough to fit the field width.
400 399 */
401 400 static void
402 401 ofmt_fit_width(split_t **spp, uint_t width, char *value, uint_t bufsize)
403 402 {
404 403 split_t *sp = *spp;
405 404 char *ptr = value, *lim = ptr + bufsize;
406 405 int i, nextlen;
407 406
408 407 if (sp == NULL) {
409 408 sp = split_str(value, OFMT_MAX_ROWS);
410 409 if (sp == NULL)
411 410 return;
412 411
413 412 *spp = sp;
414 413 }
415 414 for (i = sp->s_currfield; i < sp->s_nfields; i++) {
416 415 ptr += snprintf(ptr, lim - ptr, "%s,", sp->s_fields[i]);
417 416 if (i + 1 == sp->s_nfields) {
418 417 nextlen = 0;
419 418 if (ptr > value)
420 419 ptr[-1] = '\0';
421 420 } else {
422 421 nextlen = strlen(sp->s_fields[i + 1]);
423 422 }
424 423
425 424 if (strlen(value) + nextlen > width || ptr >= lim) {
426 425 i++;
427 426 break;
428 427 }
429 428 }
430 429 sp->s_currfield = i;
431 430 }
432 431
433 432 /*
434 433 * Print one or more rows of output values for the selected columns.
435 434 */
436 435 void
437 436 ofmt_print(ofmt_handle_t ofmt, void *arg)
438 437 {
439 438 ofmt_state_t *os = ofmt;
440 439 int i;
441 440 char value[1024];
442 441 ofmt_field_t *of;
443 442 boolean_t escsep, more_rows;
444 443 ofmt_arg_t ofarg;
445 444 split_t **sp = NULL;
446 445 boolean_t parsable = (os->os_flags & OFMT_PARSABLE);
447 446 boolean_t multiline = (os->os_flags & OFMT_MULTILINE);
↓ open down ↓ |
79 lines elided |
↑ open up ↑ |
448 447 boolean_t wrap = (os->os_flags & OFMT_WRAP);
449 448
450 449 if (wrap) {
451 450 sp = calloc(sizeof (split_t *), os->os_nfields);
452 451 if (sp == NULL)
453 452 return;
454 453 }
455 454
456 455 if ((os->os_nrow++ % os->os_winsize.ws_row) == 0 &&
457 456 !parsable && !multiline) {
458 - ofmt_print_header(os);
457 + if (!(os->os_flags & OFMT_NOHEADER))
458 + ofmt_print_header(os);
459 459 os->os_nrow++;
460 460 }
461 461
462 462 if (multiline && os->os_nrow > 1)
463 463 (void) putchar('\n');
464 464
465 465 of = os->os_fields;
466 466 escsep = (os->os_nfields > 1);
467 467 more_rows = B_FALSE;
468 468 for (i = 0; i < os->os_nfields; i++) {
469 469 os->os_lastfield = (i + 1 == os->os_nfields);
470 470 value[0] = '\0';
471 471 ofarg.ofmt_id = of[i].of_id;
472 472 ofarg.ofmt_cbarg = arg;
473 473
474 474 if ((*of[i].of_cb)(&ofarg, value, sizeof (value))) {
475 475 if (wrap) {
476 476 /*
477 477 * 'value' will be split at comma boundaries
478 478 * and stored into sp[i].
479 479 */
480 480 ofmt_fit_width(&sp[i], of[i].of_width, value,
481 481 sizeof (value));
482 482 if (sp[i] != NULL &&
483 483 sp[i]->s_currfield < sp[i]->s_nfields)
484 484 more_rows = B_TRUE;
485 485 }
486 486
487 487 ofmt_print_field(os, &of[i],
488 488 (*value == '\0' && !parsable) ?
489 489 OFMT_VAL_UNDEF : value, escsep);
490 490 } else {
491 491 ofmt_print_field(os, &of[i], OFMT_VAL_UNKNOWN, escsep);
492 492 }
493 493 }
494 494 (void) putchar('\n');
495 495
496 496 while (more_rows) {
497 497 more_rows = B_FALSE;
498 498 for (i = 0; i < os->os_nfields; i++) {
499 499 os->os_lastfield = (i + 1 == os->os_nfields);
500 500 value[0] = '\0';
501 501
502 502 ofmt_fit_width(&sp[i], of[i].of_width,
503 503 value, sizeof (value));
504 504 if (sp[i] != NULL &&
505 505 sp[i]->s_currfield < sp[i]->s_nfields)
506 506 more_rows = B_TRUE;
507 507
508 508 ofmt_print_field(os, &of[i], value, escsep);
509 509 }
510 510 (void) putchar('\n');
511 511 }
512 512 (void) fflush(stdout);
513 513
↓ open down ↓ |
45 lines elided |
↑ open up ↑ |
514 514 if (sp != NULL) {
515 515 for (i = 0; i < os->os_nfields; i++)
516 516 splitfree(sp[i]);
517 517 free(sp);
518 518 }
519 519 }
520 520
521 521 /*
522 522 * Print the field headers
523 523 */
524 -static void
525 -ofmt_print_header(ofmt_state_t *os)
524 +void
525 +ofmt_print_header(ofmt_handle_t ofmt)
526 526 {
527 + ofmt_state_t *os = ofmt;
527 528 int i;
528 529 ofmt_field_t *of = os->os_fields;
529 530 boolean_t escsep = (os->os_nfields > 1);
530 531
531 532 for (i = 0; i < os->os_nfields; i++) {
532 533 os->os_lastfield = (i + 1 == os->os_nfields);
533 534 ofmt_print_field(os, &of[i], of[i].of_name, escsep);
534 535 }
535 536 (void) putchar('\n');
536 537 }
537 538
538 539 /*
539 540 * Update the current window size.
540 541 */
541 542 void
542 543 ofmt_update_winsize(ofmt_handle_t ofmt)
543 544 {
544 545 ofmt_state_t *os = ofmt;
545 546 struct winsize *winsize = &os->os_winsize;
546 547
547 548 if (ioctl(1, TIOCGWINSZ, winsize) == -1 ||
548 549 winsize->ws_col == 0 || winsize->ws_row == 0) {
549 550 winsize->ws_col = 80;
550 551 winsize->ws_row = 24;
551 552 }
552 553 }
553 554
554 555 /*
555 556 * Return error diagnostics using the information in the ofmt_handle_t
556 557 */
557 558 char *
558 559 ofmt_strerror(ofmt_handle_t ofmt, ofmt_status_t error, char *buf,
559 560 uint_t bufsize)
560 561 {
561 562 ofmt_state_t *os = ofmt;
562 563 int i;
563 564 const char *s;
564 565 char ebuf[OFMT_BUFSIZE];
565 566 boolean_t parsable;
566 567
567 568 /*
568 569 * ebuf is intended for optional error-specific data to be appended
569 570 * after the internationalized error string for an error code.
570 571 */
571 572 ebuf[0] = '\0';
572 573
573 574 switch (error) {
574 575 case OFMT_SUCCESS:
575 576 s = "success";
576 577 break;
577 578 case OFMT_EBADFIELDS:
578 579 /*
579 580 * Enumerate the singular/plural version of the warning
580 581 * and error to simplify and improve localization.
581 582 */
582 583 parsable = (os->os_flags & OFMT_PARSABLE);
583 584 if (!parsable) {
584 585 if (os->os_nbad > 1)
585 586 s = "ignoring unknown output fields:";
586 587 else
587 588 s = "ignoring unknown output field:";
588 589 } else {
589 590 if (os->os_nbad > 1)
590 591 s = "unknown output fields:";
591 592 else
592 593 s = "unknown output field:";
593 594 }
594 595 /* set up the bad fields in ebuf */
595 596 for (i = 0; i < os->os_nbad; i++) {
596 597 (void) strlcat(ebuf, " `", sizeof (ebuf));
597 598 (void) strlcat(ebuf, os->os_badfields[i],
598 599 sizeof (ebuf));
599 600 (void) strlcat(ebuf, "'", sizeof (ebuf));
600 601 }
601 602 break;
602 603 case OFMT_ENOFIELDS:
603 604 s = "no valid output fields";
604 605 break;
605 606 case OFMT_EPARSEMULTI:
606 607 s = "multiline mode incompatible with parsable mode";
607 608 break;
608 609 case OFMT_EPARSEALL:
609 610 s = "output field `all' invalid in parsable mode";
610 611 break;
611 612 case OFMT_EPARSENONE:
612 613 s = "output fields must be specified in parsable mode";
613 614 break;
614 615 case OFMT_EPARSEWRAP:
615 616 s = "parsable mode is incompatible with wrap mode";
616 617 break;
617 618 case OFMT_ENOTEMPLATE:
618 619 s = "no template provided for fields";
619 620 break;
620 621 case OFMT_ENOMEM:
621 622 s = strerror(ENOMEM);
622 623 break;
623 624 default:
624 625 (void) snprintf(buf, bufsize,
625 626 dgettext(TEXT_DOMAIN, "unknown ofmt error (%d)"),
626 627 error);
627 628 return (buf);
628 629 }
629 630 (void) snprintf(buf, bufsize, dgettext(TEXT_DOMAIN, s));
630 631 (void) strlcat(buf, ebuf, bufsize);
631 632 return (buf);
632 633 }
633 634
634 635 void
635 636 ofmt_check(ofmt_status_t oferr, boolean_t parsable, ofmt_handle_t ofmt,
636 637 void (*die)(const char *, ...), void (*warn)(const char *, ...))
637 638 {
638 639 char buf[OFMT_BUFSIZE];
639 640
↓ open down ↓ |
103 lines elided |
↑ open up ↑ |
640 641 assert(die != NULL);
641 642 assert(warn != NULL);
642 643
643 644 if (oferr == OFMT_SUCCESS)
644 645 return;
645 646
646 647 (void) ofmt_strerror(ofmt, oferr, buf, sizeof (buf));
647 648
648 649 /*
649 650 * All errors are considered fatal in parsable mode. OFMT_ENOMEM and
650 - * OFMT_ENOFIELDS errors are always fatal, regardless of mode. For
651 + * OFMT_ENOFIELDS errors are always fatal, regardless of mode. For
651 652 * other errors, we print diagnostics in human-readable mode and
652 653 * processs what we can.
653 654 */
654 655 if (parsable || oferr == OFMT_ENOFIELDS || oferr == OFMT_ENOMEM) {
655 656 ofmt_close(ofmt);
656 657 die(buf);
657 658 } else {
658 659 warn(buf);
659 660 }
660 661 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX