4 * Operations to dump the OID tree in a human readable format.
6 * Copyright (c) 1999 Frank Strauss, Technical University of Braunschweig.
7 * Copyright (c) 1999 J. Schoenwaelder, Technical University of Braunschweig.
8 * Copyright (c) 2002 J. Schoenwaelder, University of Osnabrueck.
10 * See the file "COPYING" for information on usage and redistribution
11 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13 * @(#) $Id: dump-tree.c 8090 2008-04-18 12:56:29Z strauss $
26 static SmiModule **pmodv = NULL;
28 static int ignoreconformance = 0;
29 static int ignoreleafs = 0;
31 static int compact = 0;
33 static char *getFlags(SmiNode *smiNode)
36 switch (smiNode->access) {
37 case SMI_ACCESS_UNKNOWN:
39 case SMI_ACCESS_NOT_ACCESSIBLE:
41 case SMI_ACCESS_EVENT_ONLY:
43 case SMI_ACCESS_NOTIFY:
45 case SMI_ACCESS_READ_ONLY:
47 case SMI_ACCESS_READ_WRITE:
49 case SMI_ACCESS_NOT_IMPLEMENTED:
51 case SMI_ACCESS_INSTALL:
53 case SMI_ACCESS_INSTALL_NOTIFY:
55 case SMI_ACCESS_REPORT_ONLY:
64 static char getStatusChar(SmiStatus status)
67 case SMI_STATUS_UNKNOWN:
69 case SMI_STATUS_CURRENT:
71 case SMI_STATUS_DEPRECATED:
73 case SMI_STATUS_MANDATORY:
75 case SMI_STATUS_OPTIONAL:
77 case SMI_STATUS_OBSOLETE:
86 static char *getTypeName(SmiNode *smiNode)
89 SmiType *smiType, *parentType;
91 smiType = smiGetNodeType(smiNode);
93 if (!smiType || smiNode->nodekind == SMI_NODEKIND_TABLE)
96 if (smiType->decl == SMI_DECL_IMPLICIT_TYPE) {
97 parentType = smiGetParentType(smiType);
100 smiType = parentType;
103 type = xstrdup(smiType->name);
109 static void fprintIndex(FILE *f, SmiNode *smiNode)
113 SmiElement *smiElement;
116 for (i = -1, smiElement = smiGetFirstElement(smiNode);
117 smiElement; smiElement = smiGetNextElement(smiElement), i++) {
118 if (i > 0) fprintf(f, ",");
120 fprintf(f, indexname);
122 indexname = smiGetElementNode(smiElement)->name;
127 (smiNode->implied) ? "*" : "",
134 static void fprintObjects(FILE *f, SmiNode *smiNode)
138 SmiElement *smiElement;
141 for (i = -1, smiElement = smiGetFirstElement(smiNode);
143 smiElement = smiGetNextElement(smiElement), i++) {
144 if (i > 0) fprintf(f, ",");
146 fprintf(f, objectname);
148 objectname = smiGetElementNode(smiElement)->name;
151 fprintf(f, "%s%s", (i > 0) ? "," : "", objectname);
157 static int isPartOfLoadedModules(SmiNode *smiNode)
159 SmiModule *smiModule;
162 smiModule = smiGetNodeModule(smiNode);
164 for (i = 0; i < pmodc; i++) {
165 if (strcmp(pmodv[i]->name, smiModule->name) == 0) {
173 * The following function pruneSubTree() is tricky. There are some
174 * interactions between the supported options. See the detailed
175 * comments below. Good examples to test the implemented behaviour
178 * smidump -u -f tree --tree-no-leaf IF-MIB ETHER-CHIPSET-MIB
180 * (And the example above does _not_ work in combination with
181 * --tree-no-conformance so the code below is still broken.)
184 static int pruneSubTree(SmiNode *smiNode)
188 const int confmask = (SMI_NODEKIND_GROUP | SMI_NODEKIND_COMPLIANCE);
189 const int leafmask = (SMI_NODEKIND_GROUP | SMI_NODEKIND_COMPLIANCE
190 | SMI_NODEKIND_COLUMN | SMI_NODEKIND_SCALAR
191 | SMI_NODEKIND_ROW | SMI_NODEKIND_NOTIFICATION);
198 * First, prune all nodes which the user has told us to ignore.
199 * In the case of ignoreleafs, we have to special case nodes with
200 * an unknown status (which actually represent OBJECT-IDENTITY
201 * definitions). More special case code is needed to exclude
202 * module identity nodes.
205 if (ignoreconformance && (smiNode->nodekind & confmask)) {
210 if (smiNode->nodekind & leafmask) {
213 if (smiNode->nodekind == SMI_NODEKIND_NODE
214 && smiNode->status != SMI_STATUS_UNKNOWN) {
215 SmiModule *smiModule = smiGetNodeModule(smiNode);
216 if (smiModule && smiNode != smiGetModuleIdentityNode(smiModule)) {
223 * Next, generally do not prune nodes that belong to the set of
224 * modules we are looking at.
227 if (isPartOfLoadedModules(smiNode)) {
228 if (!ignoreconformance || !smiGetFirstChildNode(smiNode)) {
234 * Finally, prune all nodes where all child nodes are pruned.
237 for (childNode = smiGetFirstChildNode(smiNode);
239 childNode = smiGetNextChildNode(childNode)) {
242 * In the case of ignoreleafs, we have to peek at the child
243 * nodes. Otherwise, we would prune too much. we still want to
244 * see the path to the leafs we have pruned away. This also
245 * interact with the semantics of ignoreconformance since we
246 * still want in combination with ignoreleafs to see the path
247 * to the pruned conformance leafs.
250 if (ignoreleafs && (childNode->nodekind & leafmask)) {
251 if (isPartOfLoadedModules(childNode)) {
252 if (ignoreconformance && (childNode->nodekind & confmask)) {
259 if (! pruneSubTree(childNode)) {
269 static void fprintSubTree(FILE *f, SmiNode *smiNode,
270 char *prefix, size_t typefieldlen)
272 SmiNode *childNode, *indexNode;
273 SmiNodekind lastNodeKind = SMI_NODEKIND_UNKNOWN;
275 int i = 0, cnt, prefixlen;
276 size_t newtypefieldlen = 9;
281 prefixlen = strlen(prefix);
282 switch (smiNode->nodekind) {
283 case SMI_NODEKIND_SCALAR:
284 case SMI_NODEKIND_COLUMN:
286 c = prefix[prefixlen-1];
287 prefix[prefixlen-1] = getStatusChar(smiNode->status);
289 type_name = getTypeName(smiNode);
291 fprintf(f, "%s-- %s %-*s %s(%u)\n",
297 smiNode->oid[smiNode->oidlen-1]);
300 if (prefixlen > 0 && c) {
301 prefix[prefixlen-1] = c;
304 case SMI_NODEKIND_ROW:
306 c = prefix[prefixlen-1];
307 prefix[prefixlen-1] = getStatusChar(smiNode->status);
309 fprintf(f, "%s--%s(%u) [", prefix,
311 smiNode->oid[smiNode->oidlen-1]);
312 switch (smiNode->indexkind) {
313 case SMI_INDEX_INDEX:
314 case SMI_INDEX_REORDER:
315 fprintIndex(f, smiNode);
317 case SMI_INDEX_EXPAND: /* TODO: we have to do more work here! */
319 case SMI_INDEX_AUGMENT:
320 case SMI_INDEX_SPARSE:
321 indexNode = smiGetRelatedNode(smiNode);
323 fprintIndex(f, indexNode);
326 case SMI_INDEX_UNKNOWN:
330 if (prefixlen > 0 && c) {
331 prefix[prefixlen-1] = c;
334 case SMI_NODEKIND_NOTIFICATION:
336 c = prefix[prefixlen-1];
337 prefix[prefixlen-1] = getStatusChar(smiNode->status);
339 fprintf(f, "%s--%s(%u) [", prefix,
341 smiNode->oid[smiNode->oidlen-1]);
342 fprintObjects(f, smiNode);
344 if (prefixlen > 0 && c) {
345 prefix[prefixlen-1] = c;
350 c = prefix[prefixlen-1];
351 prefix[prefixlen-1] = getStatusChar(smiNode->status);
355 fprintf(f, "%s--%s(%u)\n", prefix,
356 smiNode->name ? smiNode->name : " ",
357 smiNode->oid[smiNode->oidlen-1]);
360 fprintf(f, "%s--%s(", prefix,
361 smiNode->name ? smiNode->name : " ");
362 for (j = 0; j < smiNode->oidlen; j++) {
363 fprintf(f, "%s%u", j ? "." : "", smiNode->oid[j]);
368 fprintf(f, "%s--%s(?)\n", prefix,
369 smiNode->name ? smiNode->name : " ");
370 if (prefixlen > 0 && c) {
371 prefix[prefixlen-1] = c;
374 for (childNode = smiGetFirstChildNode(smiNode), cnt = 0;
376 childNode = smiGetNextChildNode(childNode)) {
377 if (! pruneSubTree(childNode)) {
378 type = smiGetNodeType(childNode);
380 type_name = getTypeName(childNode);
382 if (strlen(type_name) > newtypefieldlen) {
383 newtypefieldlen = strlen(type_name);
391 for (childNode = smiGetFirstChildNode(smiNode);
393 childNode = smiGetNextChildNode(childNode)) {
395 if (pruneSubTree(childNode)) {
400 ((childNode->nodekind != SMI_NODEKIND_COLUMN
401 && childNode->nodekind != SMI_NODEKIND_SCALAR)
402 || (lastNodeKind != childNode->nodekind))) {
403 fprintf(f, "%s |\n", prefix);
405 newprefix = xmalloc(strlen(prefix)+10);
406 strcpy(newprefix, prefix);
407 if (cnt == 1 || cnt == i) {
408 strcat(newprefix, " ");
410 strcat(newprefix, " |");
412 fprintSubTree(f, childNode, newprefix, newtypefieldlen);
414 lastNodeKind = childNode->nodekind;
421 static void fprintTree(FILE *f)
428 smiNode = smiGetNode(NULL, "iso");
432 for (childNode = smiGetFirstChildNode(smiNode), cnt = 0, nextNode = NULL;
434 childNode = smiGetNextChildNode(childNode)) {
435 if (! pruneSubTree(childNode)) {
438 nextNode = childNode;
449 fprintSubTree(f, smiNode, "", 0);
455 static void dumpTree(int modc, SmiModule **modv, int flags, char *output)
461 f = fopen(output, "w");
463 fprintf(stderr, "smidump: cannot open %s for writing: ", output);
469 if (flags & SMIDUMP_FLAG_UNITE) {
474 if (! (flags & SMIDUMP_FLAG_SILENT)) {
475 fprintf(f, "# united registration tree (generated by smidump "
476 SMI_VERSION_STRING ")\n\n");
478 if (! (flags & SMIDUMP_FLAG_SILENT) && (flags & SMIDUMP_FLAG_ERROR)) {
479 fprintf(f, "# WARNING: this output may be incorrect due to "
480 "significant parse errors\n\n");
486 for (i = 0; i < modc; i++) {
491 if (! (flags & SMIDUMP_FLAG_SILENT)) {
492 fprintf(f, "# %s registration tree (generated by smidump "
493 SMI_VERSION_STRING ")\n\n", modv[i]->name);
495 if (! (flags & SMIDUMP_FLAG_SILENT) && (flags & SMIDUMP_FLAG_ERROR)) {
496 fprintf(f, "# WARNING: this output may be incorrect due to "
497 "significant parse errors\n\n");
503 if (fflush(f) || ferror(f)) {
504 perror("smidump: write error");
517 static SmidumpDriverOption opt[] = {
518 { "no-conformance", OPT_FLAG, &ignoreconformance, 0,
519 "do not show conformance nodes"},
520 { "no-leafs", OPT_FLAG, &ignoreleafs, 0,
521 "do not show leaf nodes"},
522 { "full-root", OPT_FLAG, &full, 0,
523 "generate the full path to the root"},
524 { "compact", OPT_FLAG, &compact, 0,
525 "generate a more compact representation"},
529 static SmidumpDriver driver = {
534 "structure of the OID tree",
539 smidumpRegisterDriver(&driver);