Annotation of embedaddon/libxml2/xmlcatalog.c, revision 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>