Annotation of embedaddon/libxml2/xmlcatalog.c, revision 1.1.1.1
1.1 misho 1: /*
2: * xmlcatalog.c : a small utility program to handle XML catalogs
3: *
4: * See Copyright for the status of this software.
5: *
6: * daniel@veillard.com
7: */
8:
9: #include "libxml.h"
10:
11: #include <string.h>
12: #include <stdio.h>
13: #include <stdarg.h>
14:
15: #ifdef HAVE_STDLIB_H
16: #include <stdlib.h>
17: #endif
18:
19: #ifdef HAVE_LIBREADLINE
20: #include <readline/readline.h>
21: #ifdef HAVE_LIBHISTORY
22: #include <readline/history.h>
23: #endif
24: #endif
25:
26: #include <libxml/xmlmemory.h>
27: #include <libxml/uri.h>
28: #include <libxml/catalog.h>
29: #include <libxml/parser.h>
30: #include <libxml/globals.h>
31:
32: #if defined(LIBXML_CATALOG_ENABLED) && defined(LIBXML_OUTPUT_ENABLED)
33: static int shell = 0;
34: static int sgml = 0;
35: static int noout = 0;
36: static int create = 0;
37: static int add = 0;
38: static int del = 0;
39: static int convert = 0;
40: static int no_super_update = 0;
41: static int verbose = 0;
42: static char *filename = NULL;
43:
44:
45: #ifndef XML_SGML_DEFAULT_CATALOG
46: #define XML_SGML_DEFAULT_CATALOG "/etc/sgml/catalog"
47: #endif
48:
49: /************************************************************************
50: * *
51: * Shell Interface *
52: * *
53: ************************************************************************/
54: /**
55: * xmlShellReadline:
56: * @prompt: the prompt value
57: *
58: * Read a string
59: *
60: * Returns a pointer to it or NULL on EOF the caller is expected to
61: * free the returned string.
62: */
63: static char *
64: xmlShellReadline(const char *prompt) {
65: #ifdef HAVE_LIBREADLINE
66: char *line_read;
67:
68: /* Get a line from the user. */
69: line_read = readline (prompt);
70:
71: /* If the line has any text in it, save it on the history. */
72: if (line_read && *line_read)
73: add_history (line_read);
74:
75: return (line_read);
76: #else
77: char line_read[501];
78: char *ret;
79: int len;
80:
81: if (prompt != NULL)
82: fprintf(stdout, "%s", prompt);
83: if (!fgets(line_read, 500, stdin))
84: return(NULL);
85: line_read[500] = 0;
86: len = strlen(line_read);
87: ret = (char *) malloc(len + 1);
88: if (ret != NULL) {
89: memcpy (ret, line_read, len + 1);
90: }
91: return(ret);
92: #endif
93: }
94:
95: static void usershell(void) {
96: char *cmdline = NULL, *cur;
97: int nbargs;
98: char command[100];
99: char arg[400];
100: char *argv[20];
101: int i, ret;
102: xmlChar *ans;
103:
104: while (1) {
105: cmdline = xmlShellReadline("> ");
106: if (cmdline == NULL)
107: return;
108:
109: /*
110: * Parse the command itself
111: */
112: cur = cmdline;
113: nbargs = 0;
114: while ((*cur == ' ') || (*cur == '\t')) cur++;
115: i = 0;
116: while ((*cur != ' ') && (*cur != '\t') &&
117: (*cur != '\n') && (*cur != '\r')) {
118: if (*cur == 0)
119: break;
120: command[i++] = *cur++;
121: }
122: command[i] = 0;
123: if (i == 0) {
124: free(cmdline);
125: continue;
126: }
127:
128: /*
129: * Parse the argument string
130: */
131: memset(arg, 0, sizeof(arg));
132: while ((*cur == ' ') || (*cur == '\t')) cur++;
133: i = 0;
134: while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
135: if (*cur == 0)
136: break;
137: arg[i++] = *cur++;
138: }
139: arg[i] = 0;
140:
141: /*
142: * Parse the arguments
143: */
144: i = 0;
145: nbargs = 0;
146: cur = arg;
147: memset(argv, 0, sizeof(argv));
148: while (*cur != 0) {
149: while ((*cur == ' ') || (*cur == '\t')) cur++;
150: if (*cur == '\'') {
151: cur++;
152: argv[i] = cur;
153: while ((*cur != 0) && (*cur != '\'')) cur++;
154: if (*cur == '\'') {
155: *cur = 0;
156: nbargs++;
157: i++;
158: cur++;
159: }
160: } else if (*cur == '"') {
161: cur++;
162: argv[i] = cur;
163: while ((*cur != 0) && (*cur != '"')) cur++;
164: if (*cur == '"') {
165: *cur = 0;
166: nbargs++;
167: i++;
168: cur++;
169: }
170: } else {
171: argv[i] = cur;
172: while ((*cur != 0) && (*cur != ' ') && (*cur != '\t'))
173: cur++;
174: *cur = 0;
175: nbargs++;
176: i++;
177: cur++;
178: }
179: }
180:
181: /*
182: * start interpreting the command
183: */
184: if (!strcmp(command, "exit"))
185: break;
186: if (!strcmp(command, "quit"))
187: break;
188: if (!strcmp(command, "bye"))
189: break;
190: if (!strcmp(command, "public")) {
191: if (nbargs != 1) {
192: printf("public requires 1 arguments\n");
193: } else {
194: ans = xmlCatalogResolvePublic((const xmlChar *) argv[0]);
195: if (ans == NULL) {
196: printf("No entry for PUBLIC %s\n", argv[0]);
197: } else {
198: printf("%s\n", (char *) ans);
199: xmlFree(ans);
200: }
201: }
202: } else if (!strcmp(command, "system")) {
203: if (nbargs != 1) {
204: printf("system requires 1 arguments\n");
205: } else {
206: ans = xmlCatalogResolveSystem((const xmlChar *) argv[0]);
207: if (ans == NULL) {
208: printf("No entry for SYSTEM %s\n", argv[0]);
209: } else {
210: printf("%s\n", (char *) ans);
211: xmlFree(ans);
212: }
213: }
214: } else if (!strcmp(command, "add")) {
215: if (sgml) {
216: if ((nbargs != 3) && (nbargs != 2)) {
217: printf("add requires 2 or 3 arguments\n");
218: } else {
219: if (argv[2] == NULL)
220: ret = xmlCatalogAdd(BAD_CAST argv[0], NULL,
221: BAD_CAST argv[1]);
222: else
223: ret = xmlCatalogAdd(BAD_CAST argv[0], BAD_CAST argv[1],
224: BAD_CAST argv[2]);
225: if (ret != 0)
226: printf("add command failed\n");
227: }
228: } else {
229: if ((nbargs != 3) && (nbargs != 2)) {
230: printf("add requires 2 or 3 arguments\n");
231: } else {
232: if (argv[2] == NULL)
233: ret = xmlCatalogAdd(BAD_CAST argv[0], NULL,
234: BAD_CAST argv[1]);
235: else
236: ret = xmlCatalogAdd(BAD_CAST argv[0], BAD_CAST argv[1],
237: BAD_CAST argv[2]);
238: if (ret != 0)
239: printf("add command failed\n");
240: }
241: }
242: } else if (!strcmp(command, "del")) {
243: if (nbargs != 1) {
244: printf("del requires 1\n");
245: } else {
246: ret = xmlCatalogRemove(BAD_CAST argv[0]);
247: if (ret <= 0)
248: printf("del command failed\n");
249:
250: }
251: } else if (!strcmp(command, "resolve")) {
252: if (nbargs != 2) {
253: printf("resolve requires 2 arguments\n");
254: } else {
255: ans = xmlCatalogResolve(BAD_CAST argv[0],
256: BAD_CAST argv[1]);
257: if (ans == NULL) {
258: printf("Resolver failed to find an answer\n");
259: } else {
260: printf("%s\n", (char *) ans);
261: xmlFree(ans);
262: }
263: }
264: } else if (!strcmp(command, "dump")) {
265: if (nbargs != 0) {
266: printf("dump has no arguments\n");
267: } else {
268: xmlCatalogDump(stdout);
269: }
270: } else if (!strcmp(command, "debug")) {
271: if (nbargs != 0) {
272: printf("debug has no arguments\n");
273: } else {
274: verbose++;
275: xmlCatalogSetDebug(verbose);
276: }
277: } else if (!strcmp(command, "quiet")) {
278: if (nbargs != 0) {
279: printf("quiet has no arguments\n");
280: } else {
281: if (verbose > 0)
282: verbose--;
283: xmlCatalogSetDebug(verbose);
284: }
285: } else {
286: if (strcmp(command, "help")) {
287: printf("Unrecognized command %s\n", command);
288: }
289: printf("Commands available:\n");
290: printf("\tpublic PublicID: make a PUBLIC identifier lookup\n");
291: printf("\tsystem SystemID: make a SYSTEM identifier lookup\n");
292: printf("\tresolve PublicID SystemID: do a full resolver lookup\n");
293: printf("\tadd 'type' 'orig' 'replace' : add an entry\n");
294: printf("\tdel 'values' : remove values\n");
295: printf("\tdump: print the current catalog state\n");
296: printf("\tdebug: increase the verbosity level\n");
297: printf("\tquiet: decrease the verbosity level\n");
298: printf("\texit: quit the shell\n");
299: }
300: free(cmdline); /* not xmlFree here ! */
301: }
302: }
303:
304: /************************************************************************
305: * *
306: * Main *
307: * *
308: ************************************************************************/
309: static void usage(const char *name) {
310: /* split into 2 printf's to avoid overly long string (gcc warning) */
311: printf("\
312: Usage : %s [options] catalogfile entities...\n\
313: \tParse the catalog file and query it for the entities\n\
314: \t--sgml : handle SGML Super catalogs for --add and --del\n\
315: \t--shell : run a shell allowing interactive queries\n\
316: \t--create : create a new catalog\n\
317: \t--add 'type' 'orig' 'replace' : add an XML entry\n\
318: \t--add 'entry' : add an SGML entry\n", name);
319: printf("\
320: \t--del 'values' : remove values\n\
321: \t--noout: avoid dumping the result on stdout\n\
322: \t used with --add or --del, it saves the catalog changes\n\
323: \t and with --sgml it automatically updates the super catalog\n\
324: \t--no-super-update: do not update the SGML super catalog\n\
325: \t-v --verbose : provide debug informations\n");
326: }
327: int main(int argc, char **argv) {
328: int i;
329: int ret;
330: int exit_value = 0;
331:
332:
333: if (argc <= 1) {
334: usage(argv[0]);
335: return(1);
336: }
337:
338: LIBXML_TEST_VERSION
339: for (i = 1; i < argc ; i++) {
340: if (!strcmp(argv[i], "-"))
341: break;
342:
343: if (argv[i][0] != '-')
344: break;
345: if ((!strcmp(argv[i], "-verbose")) ||
346: (!strcmp(argv[i], "-v")) ||
347: (!strcmp(argv[i], "--verbose"))) {
348: verbose++;
349: xmlCatalogSetDebug(verbose);
350: } else if ((!strcmp(argv[i], "-noout")) ||
351: (!strcmp(argv[i], "--noout"))) {
352: noout = 1;
353: } else if ((!strcmp(argv[i], "-shell")) ||
354: (!strcmp(argv[i], "--shell"))) {
355: shell++;
356: noout = 1;
357: } else if ((!strcmp(argv[i], "-sgml")) ||
358: (!strcmp(argv[i], "--sgml"))) {
359: sgml++;
360: } else if ((!strcmp(argv[i], "-create")) ||
361: (!strcmp(argv[i], "--create"))) {
362: create++;
363: } else if ((!strcmp(argv[i], "-convert")) ||
364: (!strcmp(argv[i], "--convert"))) {
365: convert++;
366: } else if ((!strcmp(argv[i], "-no-super-update")) ||
367: (!strcmp(argv[i], "--no-super-update"))) {
368: no_super_update++;
369: } else if ((!strcmp(argv[i], "-add")) ||
370: (!strcmp(argv[i], "--add"))) {
371: if (sgml)
372: i += 2;
373: else
374: i += 3;
375: add++;
376: } else if ((!strcmp(argv[i], "-del")) ||
377: (!strcmp(argv[i], "--del"))) {
378: i += 1;
379: del++;
380: } else {
381: fprintf(stderr, "Unknown option %s\n", argv[i]);
382: usage(argv[0]);
383: return(1);
384: }
385: }
386:
387: for (i = 1; i < argc; i++) {
388: if ((!strcmp(argv[i], "-add")) ||
389: (!strcmp(argv[i], "--add"))) {
390: if (sgml)
391: i += 2;
392: else
393: i += 3;
394: continue;
395: } else if ((!strcmp(argv[i], "-del")) ||
396: (!strcmp(argv[i], "--del"))) {
397: i += 1;
398:
399: /* No catalog entry specified */
400: if (i == argc || (sgml && i + 1 == argc)) {
401: fprintf(stderr, "No catalog entry specified to remove from\n");
402: usage (argv[0]);
403: return(1);
404: }
405:
406: continue;
407: } else if (argv[i][0] == '-')
408: continue;
409: filename = argv[i];
410: ret = xmlLoadCatalog(argv[i]);
411: if ((ret < 0) && (create)) {
412: xmlCatalogAdd(BAD_CAST "catalog", BAD_CAST argv[i], NULL);
413: }
414: break;
415: }
416:
417: if (convert)
418: ret = xmlCatalogConvert();
419:
420: if ((add) || (del)) {
421: for (i = 1; i < argc ; i++) {
422: if (!strcmp(argv[i], "-"))
423: break;
424:
425: if (argv[i][0] != '-')
426: continue;
427: if (strcmp(argv[i], "-add") && strcmp(argv[i], "--add") &&
428: strcmp(argv[i], "-del") && strcmp(argv[i], "--del"))
429: continue;
430:
431: if (sgml) {
432: /*
433: * Maintenance of SGML catalogs.
434: */
435: xmlCatalogPtr catal = NULL;
436: xmlCatalogPtr super = NULL;
437:
438: catal = xmlLoadSGMLSuperCatalog(argv[i + 1]);
439:
440: if ((!strcmp(argv[i], "-add")) ||
441: (!strcmp(argv[i], "--add"))) {
442: if (catal == NULL)
443: catal = xmlNewCatalog(1);
444: xmlACatalogAdd(catal, BAD_CAST "CATALOG",
445: BAD_CAST argv[i + 2], NULL);
446:
447: if (!no_super_update) {
448: super = xmlLoadSGMLSuperCatalog(XML_SGML_DEFAULT_CATALOG);
449: if (super == NULL)
450: super = xmlNewCatalog(1);
451:
452: xmlACatalogAdd(super, BAD_CAST "CATALOG",
453: BAD_CAST argv[i + 1], NULL);
454: }
455: } else {
456: if (catal != NULL)
457: ret = xmlACatalogRemove(catal, BAD_CAST argv[i + 2]);
458: else
459: ret = -1;
460: if (ret < 0) {
461: fprintf(stderr, "Failed to remove entry from %s\n",
462: argv[i + 1]);
463: exit_value = 1;
464: }
465: if ((!no_super_update) && (noout) && (catal != NULL) &&
466: (xmlCatalogIsEmpty(catal))) {
467: super = xmlLoadSGMLSuperCatalog(
468: XML_SGML_DEFAULT_CATALOG);
469: if (super != NULL) {
470: ret = xmlACatalogRemove(super,
471: BAD_CAST argv[i + 1]);
472: if (ret < 0) {
473: fprintf(stderr,
474: "Failed to remove entry from %s\n",
475: XML_SGML_DEFAULT_CATALOG);
476: exit_value = 1;
477: }
478: }
479: }
480: }
481: if (noout) {
482: FILE *out;
483:
484: if (xmlCatalogIsEmpty(catal)) {
485: remove(argv[i + 1]);
486: } else {
487: out = fopen(argv[i + 1], "w");
488: if (out == NULL) {
489: fprintf(stderr, "could not open %s for saving\n",
490: argv[i + 1]);
491: exit_value = 2;
492: noout = 0;
493: } else {
494: xmlACatalogDump(catal, out);
495: fclose(out);
496: }
497: }
498: if (!no_super_update && super != NULL) {
499: if (xmlCatalogIsEmpty(super)) {
500: remove(XML_SGML_DEFAULT_CATALOG);
501: } else {
502: out = fopen(XML_SGML_DEFAULT_CATALOG, "w");
503: if (out == NULL) {
504: fprintf(stderr,
505: "could not open %s for saving\n",
506: XML_SGML_DEFAULT_CATALOG);
507: exit_value = 2;
508: noout = 0;
509: } else {
510:
511: xmlACatalogDump(super, out);
512: fclose(out);
513: }
514: }
515: }
516: } else {
517: xmlACatalogDump(catal, stdout);
518: }
519: i += 2;
520: } else {
521: if ((!strcmp(argv[i], "-add")) ||
522: (!strcmp(argv[i], "--add"))) {
523: if ((argv[i + 3] == NULL) || (argv[i + 3][0] == 0))
524: ret = xmlCatalogAdd(BAD_CAST argv[i + 1], NULL,
525: BAD_CAST argv[i + 2]);
526: else
527: ret = xmlCatalogAdd(BAD_CAST argv[i + 1],
528: BAD_CAST argv[i + 2],
529: BAD_CAST argv[i + 3]);
530: if (ret != 0) {
531: printf("add command failed\n");
532: exit_value = 3;
533: }
534: i += 3;
535: } else if ((!strcmp(argv[i], "-del")) ||
536: (!strcmp(argv[i], "--del"))) {
537: ret = xmlCatalogRemove(BAD_CAST argv[i + 1]);
538: if (ret < 0) {
539: fprintf(stderr, "Failed to remove entry %s\n",
540: argv[i + 1]);
541: exit_value = 1;
542: }
543: i += 1;
544: }
545: }
546: }
547:
548: } else if (shell) {
549: usershell();
550: } else {
551: for (i++; i < argc; i++) {
552: xmlURIPtr uri;
553: xmlChar *ans;
554:
555: uri = xmlParseURI(argv[i]);
556: if (uri == NULL) {
557: ans = xmlCatalogResolvePublic((const xmlChar *) argv[i]);
558: if (ans == NULL) {
559: printf("No entry for PUBLIC %s\n", argv[i]);
560: exit_value = 4;
561: } else {
562: printf("%s\n", (char *) ans);
563: xmlFree(ans);
564: }
565: } else {
566: xmlFreeURI(uri);
567: ans = xmlCatalogResolveSystem((const xmlChar *) argv[i]);
568: if (ans == NULL) {
569: printf("No entry for SYSTEM %s\n", argv[i]);
570: ans = xmlCatalogResolveURI ((const xmlChar *) argv[i]);
571: if (ans == NULL) {
572: printf ("No entry for URI %s\n", argv[i]);
573: exit_value = 4;
574: } else {
575: printf("%s\n", (char *) ans);
576: xmlFree (ans);
577: }
578: } else {
579: printf("%s\n", (char *) ans);
580: xmlFree(ans);
581: }
582: }
583: }
584: }
585: if ((!sgml) && ((add) || (del) || (create) || (convert))) {
586: if (noout && filename && *filename) {
587: FILE *out;
588:
589: out = fopen(filename, "w");
590: if (out == NULL) {
591: fprintf(stderr, "could not open %s for saving\n", filename);
592: exit_value = 2;
593: noout = 0;
594: } else {
595: xmlCatalogDump(out);
596: }
597: } else {
598: xmlCatalogDump(stdout);
599: }
600: }
601:
602: /*
603: * Cleanup and check for memory leaks
604: */
605: xmlCleanupParser();
606: xmlMemoryDump();
607: return(exit_value);
608: }
609: #else
610: int main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
611: fprintf(stderr, "libxml was not compiled with catalog and output support\n");
612: return(1);
613: }
614: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>