2 * xmlcatalog.c : a small utility program to handle XML catalogs
4 * See Copyright for the status of this software.
19 #ifdef HAVE_LIBREADLINE
20 #include <readline/readline.h>
21 #ifdef HAVE_LIBHISTORY
22 #include <readline/history.h>
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>
35 static int create
= 0;
38 static int convert
= 0;
39 static int verbose
= 0;
40 static char *filename
;
42 #ifdef LIBXML_CATALOG_ENABLED
44 #define XML_SGML_DEFAULT_CATALOG "/etc/sgml/catalog"
46 /************************************************************************
50 ************************************************************************/
53 * @prompt: the prompt value
57 * Returns a pointer to it or NULL on EOF the caller is expected to
58 * free the returned string.
61 xmlShellReadline(const char *prompt
) {
62 #ifdef HAVE_LIBREADLINE
65 /* Get a line from the user. */
66 line_read
= readline (prompt
);
68 /* If the line has any text in it, save it on the history. */
69 if (line_read
&& *line_read
)
70 add_history (line_read
);
79 fprintf(stdout
, "%s", prompt
);
80 if (!fgets(line_read
, 500, stdin
))
83 len
= strlen(line_read
);
84 ret
= (char *) malloc(len
+ 1);
86 memcpy (ret
, line_read
, len
+ 1);
92 static void usershell(void) {
93 char *cmdline
= NULL
, *cur
;
102 cmdline
= xmlShellReadline("> ");
107 * Parse the command itself
111 while ((*cur
== ' ') || (*cur
== '\t')) cur
++;
113 while ((*cur
!= ' ') && (*cur
!= '\t') &&
114 (*cur
!= '\n') && (*cur
!= '\r')) {
117 command
[i
++] = *cur
++;
120 if (i
== 0) continue;
124 * Parse the argument string
126 memset(arg
, 0, sizeof(arg
));
127 while ((*cur
== ' ') || (*cur
== '\t')) cur
++;
129 while ((*cur
!= '\n') && (*cur
!= '\r') && (*cur
!= 0)) {
139 * Parse the arguments
144 memset(argv
, 0, sizeof(argv
));
146 while ((*cur
== ' ') || (*cur
== '\t')) cur
++;
150 while ((*cur
!= 0) && (*cur
!= '\'')) cur
++;
157 } else if (*cur
== '"') {
160 while ((*cur
!= 0) && (*cur
!= '"')) cur
++;
169 while ((*cur
!= 0) && (*cur
!= ' ') && (*cur
!= '\t'))
179 * start interpreting the command
181 if (!strcmp(command
, "exit"))
183 if (!strcmp(command
, "quit"))
185 if (!strcmp(command
, "bye"))
187 if (!strcmp(command
, "public")) {
189 printf("public requires 1 arguments\n");
191 ans
= xmlCatalogResolvePublic((const xmlChar
*) argv
[0]);
193 printf("No entry for PUBLIC %s\n", argv
[0]);
199 } else if (!strcmp(command
, "system")) {
201 printf("system requires 1 arguments\n");
203 ans
= xmlCatalogResolveSystem((const xmlChar
*) argv
[0]);
205 printf("No entry for SYSTEM %s\n", argv
[0]);
211 } else if (!strcmp(command
, "add")) {
213 if ((nbargs
!= 3) && (nbargs
!= 2)) {
214 printf("add requires 2 or 3 arguments\n");
217 ret
= xmlCatalogAdd(BAD_CAST argv
[0], NULL
,
220 ret
= xmlCatalogAdd(BAD_CAST argv
[0], BAD_CAST argv
[1],
223 printf("add command failed\n");
226 if ((nbargs
!= 3) && (nbargs
!= 2)) {
227 printf("add requires 2 or 3 arguments\n");
230 ret
= xmlCatalogAdd(BAD_CAST argv
[0], NULL
,
233 ret
= xmlCatalogAdd(BAD_CAST argv
[0], BAD_CAST argv
[1],
236 printf("add command failed\n");
239 } else if (!strcmp(command
, "del")) {
241 printf("del requires 1\n");
243 ret
= xmlCatalogRemove(BAD_CAST argv
[0]);
245 printf("del command failed\n");
248 } else if (!strcmp(command
, "resolve")) {
250 printf("resolve requires 2 arguments\n");
252 ans
= xmlCatalogResolve(BAD_CAST argv
[0],
255 printf("Resolver failed to find an answer\n");
261 } else if (!strcmp(command
, "dump")) {
263 printf("dump has no arguments\n");
265 xmlCatalogDump(stdout
);
267 } else if (!strcmp(command
, "debug")) {
269 printf("debug has no arguments\n");
272 xmlCatalogSetDebug(verbose
);
274 } else if (!strcmp(command
, "quiet")) {
276 printf("quiet has no arguments\n");
280 xmlCatalogSetDebug(verbose
);
283 if (strcmp(command
, "help")) {
284 printf("Unrecognized command %s\n", command
);
286 printf("Commands available:\n");
287 printf("\tpublic PublicID: make a PUBLIC identifier lookup\n");
288 printf("\tsystem SystemID: make a SYSTEM identifier lookup\n");
289 printf("\tresolve PublicID SystemID: do a full resolver lookup\n");
290 printf("\tadd 'type' 'orig' 'replace' : add an entry\n");
291 printf("\tdel 'values' : remove values\n");
292 printf("\tdump: print the current catalog state\n");
293 printf("\tdebug: increase the verbosity level\n");
294 printf("\tquiet: decrease the verbosity level\n");
295 printf("\texit: quit the shell\n");
297 free(cmdline
); /* not xmlFree here ! */
301 /************************************************************************
305 ************************************************************************/
306 static void usage(const char *name
) {
307 printf("Usage : %s [options] catalogfile entities...\n", name
);
308 printf("\tParse the catalog file and query it for the entities\n");
309 printf("\t--sgml : handle SGML Super catalogs for --add and --del\n");
310 printf("\t--shell : run a shell allowing interactive queries\n");
311 printf("\t--create : create a new catalog\n");
312 printf("\t--add 'type' 'orig' 'replace' : add an entry\n");
313 printf("\t--del 'values' : remove values\n");
314 printf("\t--noout: avoid dumping the result on stdout\n");
315 printf("\t used with add or del, it saves the catalog changes\n");
316 printf("\t and with --sgml it also updates the super catalog\n");
317 printf("\t-v --verbose : provide debug informations\n");
319 int main(int argc
, char **argv
) {
331 for (i
= 1; i
< argc
; i
++) {
332 if (!strcmp(argv
[i
], "-"))
335 if (argv
[i
][0] != '-')
337 if ((!strcmp(argv
[i
], "-verbose")) ||
338 (!strcmp(argv
[i
], "-v")) ||
339 (!strcmp(argv
[i
], "--verbose"))) {
341 xmlCatalogSetDebug(verbose
);
342 } else if ((!strcmp(argv
[i
], "-noout")) ||
343 (!strcmp(argv
[i
], "--noout"))) {
345 } else if ((!strcmp(argv
[i
], "-shell")) ||
346 (!strcmp(argv
[i
], "--shell"))) {
349 } else if ((!strcmp(argv
[i
], "-sgml")) ||
350 (!strcmp(argv
[i
], "--sgml"))) {
352 } else if ((!strcmp(argv
[i
], "-create")) ||
353 (!strcmp(argv
[i
], "--create"))) {
355 } else if ((!strcmp(argv
[i
], "-convert")) ||
356 (!strcmp(argv
[i
], "--convert"))) {
358 } else if ((!strcmp(argv
[i
], "-add")) ||
359 (!strcmp(argv
[i
], "--add"))) {
365 } else if ((!strcmp(argv
[i
], "-del")) ||
366 (!strcmp(argv
[i
], "--del"))) {
370 fprintf(stderr
, "Unknown option %s\n", argv
[i
]);
376 for (i
= 1; i
< argc
; i
++) {
377 if ((!strcmp(argv
[i
], "-add")) ||
378 (!strcmp(argv
[i
], "--add"))) {
384 } else if ((!strcmp(argv
[i
], "-del")) ||
385 (!strcmp(argv
[i
], "--del"))) {
388 } else if (argv
[i
][0] == '-')
391 ret
= xmlLoadCatalog(argv
[i
]);
392 if ((ret
< 0) && (create
)) {
393 xmlCatalogAdd(BAD_CAST
"catalog", BAD_CAST argv
[i
], NULL
);
399 ret
= xmlCatalogConvert();
401 if ((add
) || (del
)) {
402 for (i
= 1; i
< argc
; i
++) {
403 if (!strcmp(argv
[i
], "-"))
406 if (argv
[i
][0] != '-')
408 if (strcmp(argv
[i
], "-add") && strcmp(argv
[i
], "--add") &&
409 strcmp(argv
[i
], "-del") && strcmp(argv
[i
], "--del"))
414 * Maintenance of SGML catalogs.
416 xmlCatalogPtr catal
= NULL
;
417 xmlCatalogPtr super
= NULL
;
419 catal
= xmlLoadSGMLSuperCatalog(argv
[i
+ 1]);
421 if ((!strcmp(argv
[i
], "-add")) ||
422 (!strcmp(argv
[i
], "--add"))) {
424 catal
= xmlNewCatalog(1);
425 super
= xmlLoadSGMLSuperCatalog(XML_SGML_DEFAULT_CATALOG
);
427 super
= xmlNewCatalog(1);
429 xmlACatalogAdd(catal
, BAD_CAST
"CATALOG",
430 BAD_CAST argv
[i
+ 2], NULL
);
431 xmlACatalogAdd(super
, BAD_CAST
"CATALOG",
432 BAD_CAST argv
[i
+ 1], NULL
);
435 ret
= xmlACatalogRemove(catal
, BAD_CAST argv
[i
+ 2]);
439 fprintf(stderr
, "Failed to remove entry from %s\n",
443 if ((noout
) && (catal
!= NULL
) &&
444 (xmlCatalogIsEmpty(catal
))) {
445 super
= xmlLoadSGMLSuperCatalog(
446 XML_SGML_DEFAULT_CATALOG
);
448 ret
= xmlACatalogRemove(super
,
449 BAD_CAST argv
[i
+ 1]);
452 "Failed to remove entry from %s\n",
453 XML_SGML_DEFAULT_CATALOG
);
462 if (xmlCatalogIsEmpty(catal
)) {
465 out
= fopen(argv
[i
+ 1], "w");
467 fprintf(stderr
, "could not open %s for saving\n",
472 xmlACatalogDump(catal
, out
);
477 if (xmlCatalogIsEmpty(super
)) {
478 remove(XML_SGML_DEFAULT_CATALOG
);
480 out
= fopen(XML_SGML_DEFAULT_CATALOG
, "w");
483 "could not open %s for saving\n",
484 XML_SGML_DEFAULT_CATALOG
);
489 xmlACatalogDump(super
, out
);
495 xmlACatalogDump(catal
, stdout
);
499 if ((!strcmp(argv
[i
], "-add")) ||
500 (!strcmp(argv
[i
], "--add"))) {
501 if ((argv
[i
+ 3] == NULL
) || (argv
[i
+ 3][0] == 0))
502 ret
= xmlCatalogAdd(BAD_CAST argv
[i
+ 1], NULL
,
503 BAD_CAST argv
[i
+ 2]);
505 ret
= xmlCatalogAdd(BAD_CAST argv
[i
+ 1],
506 BAD_CAST argv
[i
+ 2],
507 BAD_CAST argv
[i
+ 3]);
509 printf("add command failed\n");
513 } else if ((!strcmp(argv
[i
], "-del")) ||
514 (!strcmp(argv
[i
], "--del"))) {
515 ret
= xmlCatalogRemove(BAD_CAST argv
[i
+ 1]);
517 fprintf(stderr
, "Failed to remove entry %s\n",
529 for (i
++; i
< argc
; i
++) {
533 uri
= xmlParseURI(argv
[i
]);
535 ans
= xmlCatalogResolvePublic((const xmlChar
*) argv
[i
]);
537 printf("No entry for PUBLIC %s\n", argv
[i
]);
545 ans
= xmlCatalogResolveSystem((const xmlChar
*) argv
[i
]);
547 printf("No entry for SYSTEM %s\n", argv
[i
]);
556 if ((!sgml
) && ((add
) || (del
) || (create
) || (convert
))) {
560 out
= fopen(filename
, "w");
562 fprintf(stderr
, "could not open %s for saving\n", filename
);
569 xmlCatalogDump(stdout
);
574 * Cleanup and check for memory leaks
581 int main(int argc
, char **argv
) {
582 fprintf(stderr
, "libxml was not compiled with catalog support\n");