File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libxml2 / xmlcatalog.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 19:53:30 2014 UTC (9 years, 11 months ago) by misho
Branches: libxml2, MAIN
CVS tags: v2_9_1p0, v2_9_1, HEAD
libxml2 2.9.1

    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>