PageRenderTime 57ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 1ms

/libsmi-0.4.8/tools/dump-tree.c

#
C | 540 lines | 417 code | 76 blank | 47 comment | 103 complexity | b2e2fc6053e750a709d72ee79ee50f1d MD5 | raw file
Possible License(s): BSD-3-Clause
  1. /*
  2. * dump-tree.c --
  3. *
  4. * Operations to dump the OID tree in a human readable format.
  5. *
  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.
  9. *
  10. * See the file "COPYING" for information on usage and redistribution
  11. * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  12. *
  13. * @(#) $Id: dump-tree.c 8090 2008-04-18 12:56:29Z strauss $
  14. */
  15. #include <config.h>
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include "smi.h"
  19. #include "smidump.h"
  20. static int pmodc = 0;
  21. static SmiModule **pmodv = NULL;
  22. static int ignoreconformance = 0;
  23. static int ignoreleafs = 0;
  24. static int full = 0;
  25. static int compact = 0;
  26. static char *getFlags(SmiNode *smiNode)
  27. {
  28. switch (smiNode->access) {
  29. case SMI_ACCESS_UNKNOWN:
  30. return "---";
  31. case SMI_ACCESS_NOT_ACCESSIBLE:
  32. return "---";
  33. case SMI_ACCESS_EVENT_ONLY:
  34. return "---";
  35. case SMI_ACCESS_NOTIFY:
  36. return "--n";
  37. case SMI_ACCESS_READ_ONLY:
  38. return "r-n";
  39. case SMI_ACCESS_READ_WRITE:
  40. return "rwn";
  41. case SMI_ACCESS_NOT_IMPLEMENTED:
  42. return "---";
  43. case SMI_ACCESS_INSTALL:
  44. return "-i-";
  45. case SMI_ACCESS_INSTALL_NOTIFY:
  46. return "-in";
  47. case SMI_ACCESS_REPORT_ONLY:
  48. return "--r";
  49. }
  50. return "";
  51. }
  52. static char getStatusChar(SmiStatus status)
  53. {
  54. switch (status) {
  55. case SMI_STATUS_UNKNOWN:
  56. return '+';
  57. case SMI_STATUS_CURRENT:
  58. return '+';
  59. case SMI_STATUS_DEPRECATED:
  60. return 'x';
  61. case SMI_STATUS_MANDATORY:
  62. return '+';
  63. case SMI_STATUS_OPTIONAL:
  64. return '+';
  65. case SMI_STATUS_OBSOLETE:
  66. return 'o';
  67. }
  68. return ' ';
  69. }
  70. static char *getTypeName(SmiNode *smiNode)
  71. {
  72. char *type;
  73. SmiType *smiType, *parentType;
  74. smiType = smiGetNodeType(smiNode);
  75. if (!smiType || smiNode->nodekind == SMI_NODEKIND_TABLE)
  76. return NULL;
  77. if (smiType->decl == SMI_DECL_IMPLICIT_TYPE) {
  78. parentType = smiGetParentType(smiType);
  79. if (!parentType)
  80. return NULL;
  81. smiType = parentType;
  82. }
  83. type = xstrdup(smiType->name);
  84. return type;
  85. }
  86. static void fprintIndex(FILE *f, SmiNode *smiNode)
  87. {
  88. char *indexname;
  89. int i;
  90. SmiElement *smiElement;
  91. indexname = NULL;
  92. for (i = -1, smiElement = smiGetFirstElement(smiNode);
  93. smiElement; smiElement = smiGetNextElement(smiElement), i++) {
  94. if (i > 0) fprintf(f, ",");
  95. if (indexname) {
  96. fprintf(f, indexname);
  97. }
  98. indexname = smiGetElementNode(smiElement)->name;
  99. }
  100. if (indexname) {
  101. fprintf(f, "%s%s%s",
  102. (i > 0) ? "," : "",
  103. (smiNode->implied) ? "*" : "",
  104. indexname);
  105. }
  106. }
  107. static void fprintObjects(FILE *f, SmiNode *smiNode)
  108. {
  109. char *objectname;
  110. int i;
  111. SmiElement *smiElement;
  112. objectname = NULL;
  113. for (i = -1, smiElement = smiGetFirstElement(smiNode);
  114. smiElement;
  115. smiElement = smiGetNextElement(smiElement), i++) {
  116. if (i > 0) fprintf(f, ",");
  117. if (objectname) {
  118. fprintf(f, objectname);
  119. }
  120. objectname = smiGetElementNode(smiElement)->name;
  121. }
  122. if (objectname) {
  123. fprintf(f, "%s%s", (i > 0) ? "," : "", objectname);
  124. }
  125. }
  126. static int isPartOfLoadedModules(SmiNode *smiNode)
  127. {
  128. SmiModule *smiModule;
  129. int i;
  130. smiModule = smiGetNodeModule(smiNode);
  131. for (i = 0; i < pmodc; i++) {
  132. if (strcmp(pmodv[i]->name, smiModule->name) == 0) {
  133. return 1;
  134. }
  135. }
  136. return 0;
  137. }
  138. /*
  139. * The following function pruneSubTree() is tricky. There are some
  140. * interactions between the supported options. See the detailed
  141. * comments below. Good examples to test the implemented behaviour
  142. * are:
  143. *
  144. * smidump -u -f tree --tree-no-leaf IF-MIB ETHER-CHIPSET-MIB
  145. *
  146. * (And the example above does _not_ work in combination with
  147. * --tree-no-conformance so the code below is still broken.)
  148. */
  149. static int pruneSubTree(SmiNode *smiNode)
  150. {
  151. SmiNode *childNode;
  152. const int confmask = (SMI_NODEKIND_GROUP | SMI_NODEKIND_COMPLIANCE);
  153. const int leafmask = (SMI_NODEKIND_GROUP | SMI_NODEKIND_COMPLIANCE
  154. | SMI_NODEKIND_COLUMN | SMI_NODEKIND_SCALAR
  155. | SMI_NODEKIND_ROW | SMI_NODEKIND_NOTIFICATION);
  156. if (! smiNode) {
  157. return 1;
  158. }
  159. /*
  160. * First, prune all nodes which the user has told us to ignore.
  161. * In the case of ignoreleafs, we have to special case nodes with
  162. * an unknown status (which actually represent OBJECT-IDENTITY
  163. * definitions). More special case code is needed to exclude
  164. * module identity nodes.
  165. */
  166. if (ignoreconformance && (smiNode->nodekind & confmask)) {
  167. return 1;
  168. }
  169. if (ignoreleafs) {
  170. if (smiNode->nodekind & leafmask) {
  171. return 1;
  172. }
  173. if (smiNode->nodekind == SMI_NODEKIND_NODE
  174. && smiNode->status != SMI_STATUS_UNKNOWN) {
  175. SmiModule *smiModule = smiGetNodeModule(smiNode);
  176. if (smiModule && smiNode != smiGetModuleIdentityNode(smiModule)) {
  177. return 1;
  178. }
  179. }
  180. }
  181. /*
  182. * Next, generally do not prune nodes that belong to the set of
  183. * modules we are looking at.
  184. */
  185. if (isPartOfLoadedModules(smiNode)) {
  186. if (!ignoreconformance || !smiGetFirstChildNode(smiNode)) {
  187. return 0;
  188. }
  189. }
  190. /*
  191. * Finally, prune all nodes where all child nodes are pruned.
  192. */
  193. for (childNode = smiGetFirstChildNode(smiNode);
  194. childNode;
  195. childNode = smiGetNextChildNode(childNode)) {
  196. /*
  197. * In the case of ignoreleafs, we have to peek at the child
  198. * nodes. Otherwise, we would prune too much. we still want to
  199. * see the path to the leafs we have pruned away. This also
  200. * interact with the semantics of ignoreconformance since we
  201. * still want in combination with ignoreleafs to see the path
  202. * to the pruned conformance leafs.
  203. */
  204. if (ignoreleafs && (childNode->nodekind & leafmask)) {
  205. if (isPartOfLoadedModules(childNode)) {
  206. if (ignoreconformance && (childNode->nodekind & confmask)) {
  207. return 1;
  208. }
  209. return 0;
  210. }
  211. }
  212. if (! pruneSubTree(childNode)) {
  213. return 0;
  214. }
  215. }
  216. return 1;
  217. }
  218. static void fprintSubTree(FILE *f, SmiNode *smiNode,
  219. char *prefix, size_t typefieldlen)
  220. {
  221. SmiNode *childNode, *indexNode;
  222. SmiNodekind lastNodeKind = SMI_NODEKIND_UNKNOWN;
  223. SmiType *type;
  224. int i = 0, cnt, prefixlen;
  225. size_t newtypefieldlen = 9;
  226. char c = 0;
  227. char *type_name;
  228. if (smiNode) {
  229. prefixlen = strlen(prefix);
  230. switch (smiNode->nodekind) {
  231. case SMI_NODEKIND_SCALAR:
  232. case SMI_NODEKIND_COLUMN:
  233. if (prefixlen > 0) {
  234. c = prefix[prefixlen-1];
  235. prefix[prefixlen-1] = getStatusChar(smiNode->status);
  236. }
  237. type_name = getTypeName(smiNode);
  238. if (type_name) {
  239. fprintf(f, "%s-- %s %-*s %s(%u)\n",
  240. prefix,
  241. getFlags(smiNode),
  242. typefieldlen,
  243. type_name,
  244. smiNode->name,
  245. smiNode->oid[smiNode->oidlen-1]);
  246. xfree(type_name);
  247. }
  248. if (prefixlen > 0 && c) {
  249. prefix[prefixlen-1] = c;
  250. }
  251. break;
  252. case SMI_NODEKIND_ROW:
  253. if (prefixlen > 0) {
  254. c = prefix[prefixlen-1];
  255. prefix[prefixlen-1] = getStatusChar(smiNode->status);
  256. }
  257. fprintf(f, "%s--%s(%u) [", prefix,
  258. smiNode->name,
  259. smiNode->oid[smiNode->oidlen-1]);
  260. switch (smiNode->indexkind) {
  261. case SMI_INDEX_INDEX:
  262. case SMI_INDEX_REORDER:
  263. fprintIndex(f, smiNode);
  264. break;
  265. case SMI_INDEX_EXPAND: /* TODO: we have to do more work here! */
  266. break;
  267. case SMI_INDEX_AUGMENT:
  268. case SMI_INDEX_SPARSE:
  269. indexNode = smiGetRelatedNode(smiNode);
  270. if (indexNode) {
  271. fprintIndex(f, indexNode);
  272. }
  273. break;
  274. case SMI_INDEX_UNKNOWN:
  275. break;
  276. }
  277. fprintf(f, "]\n");
  278. if (prefixlen > 0 && c) {
  279. prefix[prefixlen-1] = c;
  280. }
  281. break;
  282. case SMI_NODEKIND_NOTIFICATION:
  283. if (prefixlen > 0) {
  284. c = prefix[prefixlen-1];
  285. prefix[prefixlen-1] = getStatusChar(smiNode->status);
  286. }
  287. fprintf(f, "%s--%s(%u) [", prefix,
  288. smiNode->name,
  289. smiNode->oid[smiNode->oidlen-1]);
  290. fprintObjects(f, smiNode);
  291. fprintf(f, "]\n");
  292. if (prefixlen > 0 && c) {
  293. prefix[prefixlen-1] = c;
  294. }
  295. break;
  296. default:
  297. if (prefixlen > 0) {
  298. c = prefix[prefixlen-1];
  299. prefix[prefixlen-1] = getStatusChar(smiNode->status);
  300. }
  301. if (smiNode->oid)
  302. if (prefixlen > 0) {
  303. fprintf(f, "%s--%s(%u)\n", prefix,
  304. smiNode->name ? smiNode->name : " ",
  305. smiNode->oid[smiNode->oidlen-1]);
  306. } else {
  307. unsigned int j;
  308. fprintf(f, "%s--%s(", prefix,
  309. smiNode->name ? smiNode->name : " ");
  310. for (j = 0; j < smiNode->oidlen; j++) {
  311. fprintf(f, "%s%u", j ? "." : "", smiNode->oid[j]);
  312. }
  313. fprintf(f, ")\n");
  314. }
  315. else
  316. fprintf(f, "%s--%s(?)\n", prefix,
  317. smiNode->name ? smiNode->name : " ");
  318. if (prefixlen > 0 && c) {
  319. prefix[prefixlen-1] = c;
  320. }
  321. }
  322. for (childNode = smiGetFirstChildNode(smiNode), cnt = 0;
  323. childNode;
  324. childNode = smiGetNextChildNode(childNode)) {
  325. if (! pruneSubTree(childNode)) {
  326. type = smiGetNodeType(childNode);
  327. if (type) {
  328. type_name = getTypeName(childNode);
  329. if (type_name) {
  330. if (strlen(type_name) > newtypefieldlen) {
  331. newtypefieldlen = strlen(type_name);
  332. }
  333. xfree(type_name);
  334. }
  335. }
  336. cnt++;
  337. }
  338. }
  339. for (childNode = smiGetFirstChildNode(smiNode);
  340. childNode;
  341. childNode = smiGetNextChildNode(childNode)) {
  342. char *newprefix;
  343. if (pruneSubTree(childNode)) {
  344. continue;
  345. }
  346. i++;
  347. if (! compact &&
  348. ((childNode->nodekind != SMI_NODEKIND_COLUMN
  349. && childNode->nodekind != SMI_NODEKIND_SCALAR)
  350. || (lastNodeKind != childNode->nodekind))) {
  351. fprintf(f, "%s |\n", prefix);
  352. }
  353. newprefix = xmalloc(strlen(prefix)+10);
  354. strcpy(newprefix, prefix);
  355. if (cnt == 1 || cnt == i) {
  356. strcat(newprefix, " ");
  357. } else {
  358. strcat(newprefix, " |");
  359. }
  360. fprintSubTree(f, childNode, newprefix, newtypefieldlen);
  361. xfree(newprefix);
  362. lastNodeKind = childNode->nodekind;
  363. }
  364. }
  365. }
  366. static void fprintTree(FILE *f)
  367. {
  368. SmiNode *smiNode;
  369. SmiNode *childNode;
  370. SmiNode *nextNode;
  371. int cnt;
  372. smiNode = smiGetNode(NULL, "iso");
  373. if (! full) {
  374. do {
  375. for (childNode = smiGetFirstChildNode(smiNode), cnt = 0, nextNode = NULL;
  376. childNode;
  377. childNode = smiGetNextChildNode(childNode)) {
  378. if (! pruneSubTree(childNode)) {
  379. cnt++;
  380. if (! nextNode) {
  381. nextNode = childNode;
  382. }
  383. }
  384. }
  385. if (cnt == 1) {
  386. smiNode = nextNode;
  387. }
  388. } while (cnt == 1);
  389. }
  390. if (smiNode) {
  391. fprintSubTree(f, smiNode, "", 0);
  392. }
  393. }
  394. static void dumpTree(int modc, SmiModule **modv, int flags, char *output)
  395. {
  396. int i;
  397. FILE *f = stdout;
  398. if (output) {
  399. f = fopen(output, "w");
  400. if (!f) {
  401. fprintf(stderr, "smidump: cannot open %s for writing: ", output);
  402. perror(NULL);
  403. exit(1);
  404. }
  405. }
  406. if (flags & SMIDUMP_FLAG_UNITE) {
  407. pmodc = modc;
  408. pmodv = modv;
  409. if (! (flags & SMIDUMP_FLAG_SILENT)) {
  410. fprintf(f, "# united registration tree (generated by smidump "
  411. SMI_VERSION_STRING ")\n\n");
  412. }
  413. if (! (flags & SMIDUMP_FLAG_SILENT) && (flags & SMIDUMP_FLAG_ERROR)) {
  414. fprintf(f, "# WARNING: this output may be incorrect due to "
  415. "significant parse errors\n\n");
  416. }
  417. fprintTree(f);
  418. } else {
  419. for (i = 0; i < modc; i++) {
  420. pmodc = 1;
  421. pmodv = &(modv[i]);
  422. if (! (flags & SMIDUMP_FLAG_SILENT)) {
  423. fprintf(f, "# %s registration tree (generated by smidump "
  424. SMI_VERSION_STRING ")\n\n", modv[i]->name);
  425. }
  426. if (! (flags & SMIDUMP_FLAG_SILENT) && (flags & SMIDUMP_FLAG_ERROR)) {
  427. fprintf(f, "# WARNING: this output may be incorrect due to "
  428. "significant parse errors\n\n");
  429. }
  430. fprintTree(f);
  431. }
  432. }
  433. if (fflush(f) || ferror(f)) {
  434. perror("smidump: write error");
  435. exit(1);
  436. }
  437. if (output) {
  438. fclose(f);
  439. }
  440. }
  441. void initTree()
  442. {
  443. static SmidumpDriverOption opt[] = {
  444. { "no-conformance", OPT_FLAG, &ignoreconformance, 0,
  445. "do not show conformance nodes"},
  446. { "no-leafs", OPT_FLAG, &ignoreleafs, 0,
  447. "do not show leaf nodes"},
  448. { "full-root", OPT_FLAG, &full, 0,
  449. "generate the full path to the root"},
  450. { "compact", OPT_FLAG, &compact, 0,
  451. "generate a more compact representation"},
  452. { 0, OPT_END, 0, 0 }
  453. };
  454. static SmidumpDriver driver = {
  455. "tree",
  456. dumpTree,
  457. SMI_FLAG_NODESCR,
  458. 0,
  459. "structure of the OID tree",
  460. opt,
  461. NULL
  462. };
  463. smidumpRegisterDriver(&driver);
  464. }