source: trunk/third/libxml2/xmlcatalog.c @ 19097

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