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

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