/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 1994, by Sun Microsytems, Inc. */ #pragma ident "%Z%%M% %I% %E% SMI" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "state.h" static caddr_t g_file_base; /* base address of file */ static char *g_cmdname; /* name of this command */ static int g_raw = B_FALSE; /* output format */ static int g_status = EXIT_SUCCESS; /* exit status (from stdlib.h) */ static const char *print_unsigned = "%u"; static const char *print_unsigned64 = "%llu"; #define OFF(p) (p - g_file_base) static void describe_array (tnf_datum_t); static void describe_brief (tnf_datum_t); static void describe_record (tnf_datum_t); static void describe_struct (tnf_datum_t); static void describe_type (tnf_datum_t); static void read_tnf_file (int, char *); static void usage (void); static void scanargs (int, char **, int *, char ***); int main(int ac, char *av[]) { int numfiles; /* number of files to be printed */ char **filenames; /* start of file names list */ int i; /* internationalization stuff */ (void) setlocale(LC_ALL, ""); #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ #endif (void) textdomain(TEXT_DOMAIN); g_cmdname = av[0]; scanargs(ac, av, &numfiles, &filenames); for (i = 0; i < numfiles; i++) { read_tnf_file(g_raw, filenames[i]); } if (!g_raw) { if (table_get_num_elements() > 0) { print_c_header(); print_sorted_events(); } } exit(g_status); return (0); } static void scanargs(int argc, char **argv, int *nfiles, char ***files) { int c; int errflg = B_FALSE; char *optstr = "rx"; while ((c = getopt(argc, argv, optstr)) != EOF) { switch (c) { case 'r': g_raw = B_TRUE; break; case 'x': print_unsigned = "0x%x"; print_unsigned64 = "0x%llx"; break; case '?': errflg = B_TRUE; break; } } *files = &argv[optind]; *nfiles = argc - optind; if (*nfiles <= 0) { errflg = B_TRUE; } if (errflg) { usage(); } } static void read_tnf_file(int raw, char *path) { int fd; struct stat st; caddr_t p, curr_p, end_p; TNF *tnf; tnf_errcode_t err; tnf_datum_t record; void (*desc_func)(tnf_datum_t) = describe_c_record; if ((fd = open(path, O_RDONLY, 0777)) == -1) { (void) fprintf(stderr, gettext("%s: cannot open %s\n"), g_cmdname, path); g_status = EXIT_FAILURE; return; } if (fstat(fd, &st) != 0) { (void) fprintf(stderr, gettext("%s: fstat error on %s\n"), g_cmdname, path); (void) close(fd); g_status = EXIT_FAILURE; return; } if (st.st_size == 0) { (void) fprintf(stderr, gettext("%s: %s is empty\n"), g_cmdname, path); (void) close(fd); g_status = EXIT_FAILURE; return; } if ((p = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == (caddr_t)-1) { (void) fprintf(stderr, gettext("%s: mmap error on %s\n"), g_cmdname, path); (void) close(fd); g_status = EXIT_FAILURE; return; } if (raw) g_file_base = p; /* for OFF() */ if (*p == 0) { /* * magic word is 0 - catch the error if entire file is zero. * tnf_reader_begin() will catch the "not a TNF file" error. */ curr_p = p; end_p = p + st.st_size; while ((curr_p < end_p) && (*curr_p == 0)) curr_p++; if (curr_p == end_p) { (void) fprintf(stderr, gettext("%s: %s is an empty TNF file\n"), g_cmdname, path); (void) munmap(p, st.st_size); (void) close(fd); return; } } if ((err = tnf_reader_begin(p, st.st_size, &tnf)) != TNF_ERR_NONE) { (void) fprintf(stderr, gettext("%s: error in %s: %s\n"), g_cmdname, path, tnf_error_message(err)); (void) munmap(p, st.st_size); (void) close(fd); g_status = EXIT_FAILURE; return; } /* Describe file header */ record = tnf_get_file_header(tnf); if (raw) { describe_record(record); desc_func = describe_record; } /* Describe all other records */ while ((record = tnf_get_next_record(record)) != TNF_DATUM_NULL) desc_func(record); /* Don't munmap for cooked output because we access records later */ if (raw) (void) munmap(p, st.st_size); (void) close(fd); } static void describe_record(tnf_datum_t datum) { (void) printf("0x%-8x: {\n", OFF(tnf_get_raw(datum))); switch (tnf_get_kind(datum)) { case TNF_K_STRUCT: describe_struct(datum); break; case TNF_K_STRING: case TNF_K_ARRAY: describe_array(datum); break; case TNF_K_TYPE: describe_type(datum); break; default: fail(0, gettext("illegal record at %x (%d)"), tnf_get_raw(datum), tnf_get_kind(datum)); break; } (void) printf("\t}\n"); } void describe_scalar(tnf_datum_t datum) { switch (tnf_get_kind(datum)) { case TNF_K_CHAR: (void) printf("%c", tnf_get_char(datum)); break; case TNF_K_INT8: (void) printf("%d", tnf_get_int8(datum)); break; case TNF_K_UINT8: (void) printf(print_unsigned, (tnf_uint8_t)tnf_get_int8(datum)); break; case TNF_K_INT16: (void) printf("%d", tnf_get_int16(datum)); break; case TNF_K_UINT16: (void) printf(print_unsigned, (tnf_uint16_t)tnf_get_int16(datum)); break; case TNF_K_INT32: (void) printf("%d", (int)tnf_get_int32(datum)); break; case TNF_K_UINT32: if ((tnf_type_get_property(tnf_get_type(datum), TNF_N_OPAQUE)) != TNF_DATUM_NULL) { /* XXX */ (void) printf("0x%x", (tnf_uint32_t)tnf_get_int32(datum)); } else { (void) printf(print_unsigned, (tnf_uint32_t)tnf_get_int32(datum)); } break; case TNF_K_INT64: /* lint not updated, it complains: malformed format string */ (void) printf("%lld", tnf_get_int64(datum)); break; case TNF_K_UINT64: if ((tnf_type_get_property(tnf_get_type(datum), TNF_N_OPAQUE)) != TNF_DATUM_NULL) { (void) printf("0x%llx", (tnf_uint64_t)tnf_get_int64(datum)); } else { /* lint not updated, it complains: malformed format string */ (void) printf(print_unsigned64, (tnf_uint64_t)tnf_get_int64(datum)); } break; case TNF_K_FLOAT32: (void) printf("%f", tnf_get_float32(datum)); break; case TNF_K_FLOAT64: (void) printf("%f", tnf_get_float64(datum)); break; case TNF_K_SCALAR: (void) printf("unhandled scalar"); break; default: fail(0, gettext("not a scalar")); break; } } static void describe_struct(tnf_datum_t datum) { unsigned n, i; char *slotname; n = tnf_get_slot_count(datum); for (i = 0; i < n; i++) { slotname = tnf_get_slot_name(datum, i); (void) printf("%24s ", slotname); describe_brief(tnf_get_slot_indexed(datum, i)); (void) printf("\n"); /* tag_arg heuristic */ if ((i == 0) && tnf_is_record(datum)) { tnf_datum_t tag_arg; if ((tag_arg = tnf_get_tag_arg(datum)) != TNF_DATUM_NULL) { (void) printf("%24s ", TNF_N_TAG_ARG); describe_brief(tag_arg); (void) printf("\n"); } } } } static void describe_array(tnf_datum_t datum) { unsigned n, i; describe_struct(datum); /* XXX */ if (tnf_is_string(datum)) (void) printf("%24s \"%s\"\n", "chars", tnf_get_chars(datum)); else { n = tnf_get_element_count(datum); for (i = 0; i < n; i++) { (void) printf("%24d ", i); describe_brief(tnf_get_element(datum, i)); (void) printf("\n"); } } } static void describe_type(tnf_datum_t datum) { describe_struct(datum); } static void describe_brief(tnf_datum_t datum) { if (datum == TNF_DATUM_NULL) /* allowed */ (void) printf("0x%-8x ", 0); else if (tnf_is_scalar(datum)) describe_scalar(datum); else if (tnf_is_record(datum)) { (void) printf("0x%-8x ", OFF(tnf_get_raw(datum))); /* common */ switch (tnf_get_kind(datum)) { case TNF_K_TYPE: (void) printf("%s", tnf_type_get_name(datum)); break; case TNF_K_STRING: (void) printf("\"%s\"", tnf_get_chars(datum)); break; default: (void) printf("<%s>", tnf_get_type_name(datum)); } } else fail(0, gettext("inline aggregate slots/elements unhandled")); } void fail(int do_perror, char *message, ...) { va_list args; va_start(args, message); (void) fprintf(stderr, gettext("%s: "), g_cmdname); (void) vfprintf(stderr, message, args); va_end(args); if (do_perror) (void) fprintf(stderr, gettext(": %s"), strerror(errno)); (void) fprintf(stderr, gettext("\n")); exit(EXIT_FAILURE); } static void usage(void) { (void) fprintf(stderr, gettext("Usage: %s [-r] [ ...]\n"), g_cmdname); exit(EXIT_FAILURE); }