Imported Upstream version 0.4.8
[platform/upstream/libsmi.git] / tools / smidump.c
1 /*
2  * smidump.c --
3  *
4  *      Dump a MIB module conforming to a given format.
5  *
6  * Copyright (c) 1999 Frank Strauss, Technical University of Braunschweig.
7  * Copyright (c) 1999 J. Schoenwaelder, Technical University of Braunschweig.
8  *
9  * See the file "COPYING" for information on usage and redistribution
10  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11  *
12  * @(#) $Id: smidump.c 7870 2008-03-11 19:29:58Z schoenw $
13  */
14
15 #include <config.h>
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #ifdef HAVE_UNISTD_H
21 #include <unistd.h>
22 #endif
23 #ifdef HAVE_WIN_H
24 #include "win.h"
25 #endif
26
27 #include "smi.h"
28 #include "shhopt.h"
29 #include "smidump.h"
30
31
32
33 static void help(void);
34 static void usage(void);
35 static void version(void);
36 static void config(char *filename);
37 static void level(int lev);
38 static void quiet(void);
39 static void preload(char *module);
40 static void unified(void);
41 static void format(char *form);
42
43
44 static int flags;
45 static int mFlag = 0;   /* show the name for error messages */
46 static int sFlag = 0;   /* show the severity for error messages */
47 static int kFlag = 0;   /* keep going after severe errors */
48 static SmidumpDriver *driver;
49 static SmidumpDriver *firstDriver;
50 static SmidumpDriver *lastDriver;
51 static SmidumpDriver *defaultDriver;
52 static char *output;
53
54 static int opts;
55 static optStruct *opt;
56 static optStruct genericOpt[] = {
57     /* short long              type        var/func       special       */
58     { 'h', "help",           OPT_FLAG,   help,          OPT_CALLFUNC },
59     { 'V', "version",        OPT_FLAG,   version,       OPT_CALLFUNC },
60     { 'c', "config",         OPT_STRING, config,        OPT_CALLFUNC },
61     { 'l', "level",          OPT_INT,    level,         OPT_CALLFUNC },
62     { 'p', "preload",        OPT_STRING, preload,       OPT_CALLFUNC },
63     { 'l', "level",          OPT_INT,    level,         OPT_CALLFUNC },
64     { 'q', "quiet",          OPT_FLAG,   quiet,         OPT_CALLFUNC },
65     { 'm', "error-names",    OPT_FLAG,   &mFlag,        0 },
66     { 's', "severity",       OPT_FLAG,   &sFlag,        0 },
67     { 'u', "unified",        OPT_FLAG,   unified,       OPT_CALLFUNC },
68     { 'f', "format",         OPT_STRING, format,        OPT_CALLFUNC },
69     { 'o', "output",         OPT_STRING, &output,       0            },
70     { 'k', "keep-going",     OPT_FLAG,   &kFlag,        0 },
71     { 0, 0, OPT_END, 0, 0 }  /* no more options */
72 };
73
74
75
76 void *xmalloc(size_t size)
77 {
78     char *m = malloc(size);
79     if (! m) {
80         fprintf(stderr, "smidump: malloc failed - running out of memory\n");
81         exit(1);
82     }
83
84     return m;
85 }
86
87
88
89 void *xrealloc(void *ptr, size_t size)
90 {
91     char *m = realloc(ptr, size);
92     if (! m) {
93         fprintf(stderr, "smidump: realloc failed - running out of memory\n");
94         exit(1);
95     }
96     return m;
97 }
98
99
100
101 void *xcalloc(size_t nmemb, size_t size)
102 {
103     char *m = calloc(nmemb, size);
104     if (! m) {
105         fprintf(stderr, "smidump: calloc failed - running out of memory\n");
106         exit(1);
107     }
108     return m;
109 }
110
111
112
113 char *xstrdup(const char *s)
114 {
115     char *m = strdup(s);
116     if (! m) {
117         fprintf(stderr, "smidump: strdup failed - running out of memory\n");
118         exit(1);
119     }
120     return m;
121 }
122
123
124
125 void xfree(void *ptr)
126 {
127     free(ptr);
128 }
129
130
131
132 void smidumpRegisterDriver(SmidumpDriver *driver)
133 {
134     int i;
135     
136     if (!firstDriver) {
137         firstDriver = driver;
138         lastDriver = driver;
139     } else {
140         lastDriver->next = driver;
141         lastDriver = driver;
142     }
143
144     for (i = 0; driver->opt && driver->opt[i].type != OPT_END; i++) {
145         opt = xrealloc(opt, (opts+1) * sizeof(optStruct));
146         memcpy(&opt[opts], &opt[opts-1], sizeof(optStruct));
147         opt[opts-1].shortName = 0;
148         opt[opts-1].longName  = xmalloc(strlen(driver->name) +
149                                  strlen(driver->opt[i].name) + 2);
150         sprintf(opt[opts-1].longName, "%s-%s",
151                 driver->name, driver->opt[i].name);
152         opt[opts-1].type      = driver->opt[i].type;
153         opt[opts-1].arg       = driver->opt[i].arg;
154         opt[opts-1].flags     = driver->opt[i].flags;
155         opts++;
156     }
157 }
158
159
160
161 static void formats()
162 {
163     SmidumpDriver *driver = firstDriver;
164     
165     for (driver = firstDriver; driver; driver = driver->next) {
166         fprintf(stderr, "  %-14s: %s\n", driver->name,
167                 driver->descr ? driver->descr : "...");
168     }
169 }
170
171
172
173 static void usage()
174 {
175     int i;
176     SmidumpDriver *driver;
177     char *value = NULL;
178 #ifdef _MSC_VER
179     #if _MSC_VER >= 1400
180 /*
181    %n in printf is a security vulnerability. Ref:
182    http://en.wikipedia.org/wiki/Format_string_vulnerabilities
183    MS decided it was important enough to disble it by default. Ref:
184    "ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.VisualStudio.v80.en/dv_vccrt/html/77a854ae-5b48-4865-89f4-f2dc5cf80f52.htm
185    Calling _set_printf_count_output() stops an invalid parameter crash.
186 */
187     int printf_state;
188     #endif
189 #endif
190     
191     fprintf(stderr,
192             "Usage: smidump [options] [module or path ...]\n"
193             "  -V, --version        show version and license information\n"
194             "  -h, --help           show usage information\n"
195             "  -q, --quiet          do not generate any comments\n"
196             "  -c, --config=file    load a specific configuration file\n"
197             "  -p, --preload=module preload <module>\n"
198             "  -l, --level=level    set maximum level of errors and warnings\n"
199             "  -m, --error-names    print the name of errors in braces\n"
200             "  -s, --severity       print the severity of errors in brackets\n"
201             "  -f, --format=format  use <format> when dumping (default %s)\n"
202             "  -o, --output=name    use <name> when creating names for output files\n"
203             "  -u, --unified        print a single unified output of all modules\n"
204             "  -k, --keep-going     continue after serious parse errors\n\n",
205             defaultDriver ? defaultDriver->name : "none");
206
207     fprintf(stderr, "Supported formats are:\n");
208     formats();
209
210     for (driver = firstDriver; driver; driver = driver->next) {
211         if (! driver->opt) continue;
212         fprintf(stderr, "\nSpecific option for the \"%s\" format:\n",
213                 driver->name);
214         for (i = 0; driver->opt && driver->opt[i].type != OPT_END; i++) {
215             int n;
216             switch (driver->opt[i].type) {
217             case OPT_END:
218             case OPT_FLAG:
219                 value = NULL;
220                 break;
221             case OPT_STRING:
222                 value = "string";
223                 break;
224             case OPT_INT:
225             case OPT_UINT:
226             case OPT_LONG:
227             case OPT_ULONG:
228                 value = "number";
229                 break;
230             }
231 #ifdef _MSC_VER
232     #if _MSC_VER >= 1400
233             printf_state=_set_printf_count_output(1);
234     #endif
235 #endif
236             fprintf(stderr, "  --%s-%s%s%s%n",
237                     driver->name, driver->opt[i].name,
238                     value ? "=" : "",
239                     value ? value : "",
240                     &n);
241 #ifdef _MSC_VER
242     #if _MSC_VER >= 1400
243             (void)_set_printf_count_output(printf_state);
244     #endif
245 #endif
246             fprintf(stderr, "%*s%s\n",
247                     30-n, "",
248                     driver->opt[i].descr ? driver->opt[i].descr : "...");
249         }
250     }
251 }
252
253
254
255 static void help() { usage(); exit(0); }
256 static void version() { printf("smidump " SMI_VERSION_STRING "\n"); exit(0); }
257 static void config(char *filename) { smiReadConfig(filename, "smidump"); }
258 static void level(int lev) { smiSetErrorLevel(lev); }
259 static void quiet() { flags |= SMIDUMP_FLAG_SILENT; }
260 static void preload(char *module) { smiLoadModule(module); }
261 static void unified() { flags |= SMIDUMP_FLAG_UNITE; }
262
263 static void format(char *form)
264 {
265     for (driver = firstDriver; driver; driver = driver->next) {
266         if (strcasecmp(driver->name, form) == 0) {
267             break;
268         }
269     }
270     if (!driver) {
271         fprintf(stderr, "smidump: invalid dump format `%s'"
272                 " - supported formats are:\n", form);
273         formats();
274         exit(1);
275     }
276 }
277
278
279
280 static void
281 errorHandler(char *path, int line, int severity, char *msg, char *tag)
282 {
283     if (path) {
284         fprintf(stderr, "%s:%d: ", path, line);
285     }
286     if (sFlag) {
287         fprintf(stderr, "[%d] ", severity);
288     }
289     if (mFlag) {
290         fprintf(stderr, "{%s} ", tag);
291     }
292     switch (severity) {
293     case 4:
294     case 5:
295         fprintf(stderr, "warning: ");
296         break;
297     case 6:     
298         fprintf(stderr, "info: ");
299         break;
300     }
301     fprintf(stderr, "%s\n", msg);
302
303     if (severity <= 0) {
304         exit(1);
305     }
306 }
307
308
309
310 int main(int argc, char *argv[])
311 {
312     char *modulename;
313     SmiModule *smiModule;
314     int smiflags, i;
315     SmiModule **modv = NULL;
316     int modc = 0;
317
318     output = NULL;
319     firstDriver = lastDriver = defaultDriver = NULL;
320
321     opts = sizeof(genericOpt) / sizeof(optStruct);
322     opt = xmalloc(sizeof(genericOpt));
323     memcpy(opt, genericOpt, sizeof(genericOpt));
324
325     initCm();
326     initCorba();
327 #if 0
328     initFig();
329 #endif
330     initIdentifiers();
331     initImports();
332     initJax();
333     initMetrics();
334     initMosy();
335     initNetsnmp();
336     initPerl();
337     initPython();
338     initSming();
339     initSmi();                defaultDriver = lastDriver;
340     initSppi();
341 #if 0
342     initSql();
343 #endif
344     initScli();
345     initSvg();
346     initTree();
347     initTypes();
348     initSizes();
349     initXml();
350     initXsd();
351     initCompliances();
352     initYang();
353     initBoilerplate();
354     
355     for (i = 1; i < argc; i++)
356         if ((strstr(argv[i], "-c") == argv[i]) ||
357             (strstr(argv[i], "--config") == argv[i])) break;
358     if (i == argc) 
359         smiInit("smidump");
360     else
361         smiInit(NULL);
362
363     flags = 0;
364     driver = defaultDriver;
365
366     optParseOptions(&argc, argv, opt, 0);
367
368     if (!driver) {
369         fprintf(stderr, "smidump: no dump formats registered\n");
370         smiExit();
371         exit(1);
372     }
373     
374     if (sFlag || mFlag) {
375         smiSetErrorHandler(errorHandler);
376     }
377
378     smiflags = smiGetFlags();
379     smiflags |= SMI_FLAG_ERRORS;
380     smiflags |= driver->smiflags;
381     smiSetFlags(smiflags);
382
383     if (flags & SMIDUMP_FLAG_UNITE && driver->ignflags & SMIDUMP_DRIVER_CANT_UNITE) {
384         fprintf(stderr, "smidump: %s format does not support united output:"
385                 " ignoring -u\n", driver->name);
386         flags = (flags & ~SMIDUMP_FLAG_UNITE);
387     }
388
389     if (output && driver->ignflags & SMIDUMP_DRIVER_CANT_OUTPUT) {
390         fprintf(stderr, "smidump: %s format does not support output option:"
391                 " ignoring -o %s\n", driver->name, output);
392         output = NULL;
393     }
394
395     modv = (SmiModule **) xmalloc((argc) * sizeof(SmiModule *));
396     modc = 0;
397     
398     for (i = 1; i < argc; i++) {
399         modulename = smiLoadModule(argv[i]);
400         smiModule = modulename ? smiGetModule(modulename) : NULL;
401         if (smiModule) {
402             if ((smiModule->conformance) && (smiModule->conformance < 3)) {
403                 flags |= SMIDUMP_FLAG_ERROR;
404                 if (! (flags & SMIDUMP_FLAG_SILENT)) {
405                     fprintf(stderr,
406                             "smidump: module `%s' contains errors, "
407                             "expect flawed output\n",
408                             argv[i]);
409                 }
410             }
411             modv[modc++] = smiModule;
412         } else {
413             fprintf(stderr, "smidump: cannot locate module `%s'\n",
414                     argv[i]);
415         }
416     }
417
418     if (! (flags & SMIDUMP_FLAG_ERROR) || kFlag) {
419         (driver->func)(modc, modv, flags, output);
420     } else {
421         if (! (flags & SMIDUMP_FLAG_SILENT)) {
422             fprintf(stderr,
423                     "smidump: aborting due to severe parsing errors\n"
424                     "smidump: use the -k option to force continuation\n");
425         }
426     }
427
428     smiExit();
429
430     if (modv) xfree(modv);
431     
432     return 0;
433 }