/*
 * XML Catalog Manager (xmlcatmgr)
 * $Id: main.c,v 1.12 2004/05/01 21:07:41 jmmv Exp $
 *
 * Copyright (c) 2003, 2004 Julio M. Merino Vidal.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name of the author nor the names of contributors may
 *    be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * The main program.
 */

#include "system.h"

#ifndef lint
__RCSID("$Id: main.c,v 1.12 2004/05/01 21:07:41 jmmv Exp $");
#endif

#include "generic.h"
#include "mem.h"
#include "sgml.h"
#include "xml.h"

static void usage(int);
static void version(void);
int main(int, char **);

/* --------------------------------------------------------------------- */

/*
 * Shows an usage message and exits with the given error code.
 *
 * If exitstat's value is EXIT_SUCCESS, we assume the user invoked us
 * with the '-h' flag, so we want a descriptive usage message.
 */
static void
usage(int exitstat)
{
    if (exitstat == EXIT_SUCCESS)
        (void)fprintf(stderr, "%s version %s\n", PKGNAME, PKGVERSION);

    (void)fprintf(stderr,
                  "Usage: %s [-hpsv] [-c catalog] action [action_args]\n",
                  getprogname());

    if (exitstat == EXIT_SUCCESS) {
        (void)fprintf(stderr,
                      "\nCopyright (c) 2003, 2004 Julio M. Merino Vidal.\n"
                      "This program is licensed under the terms of the BSD "
                      "license.\n"
                      "\nAvailable options:\n"
                      "    -c catalog    Use `catalog' as the catalog file.\n"
                      "    -h            Show this help message.\n"
                      "    -p            Prepend new entries instead of append"
                      " (add mode only).\n"
                      "    -s            Switch to SGML mode.\n"
                      "    -v            Show version information and exit.\n"
                      "\nAvailable actions:\n"
                      "    add, create, destroy, lookup, remove.\n"
                      "\nDefault SGML catalog: %s\n"
                      "Default XML catalog: %s\n"
                      "\nSee xmlcatmgr(1) for more information.\n",
                      DEFAULT_CATALOG_SGML, DEFAULT_CATALOG_XML);
    }

    exit(exitstat);
}

/* --------------------------------------------------------------------- */

/*
 * Shows a string containing the program's version and exits.
 */
static void
version(void)
{
    (void)fprintf(stderr, "%s %s\n", PKGNAME, PKGVERSION);
    exit(EXIT_SUCCESS);
}

/* --------------------------------------------------------------------- */

/*
 * Program entry point.  This parses options and selects the run action
 * based on the first non-option parameter.  It then invokes the right
 * function (from generic) with a pointer to the mode (XML or SGML)
 * action.
 */
int
main(int argc, char **argv)
{
    bool res, pflag, sflag;
    const char *catname;
    char *const *argvorig;
    int argcorig, ch;
    bool (*ptr_add)(int, char *const *, FILE *, bool);
    bool (*ptr_create)(FILE *);
    bool (*ptr_lookup)(int, char *const *, FILE *);
    bool (*ptr_remove)(int, char *const *, FILE *);

    argcorig = argc;
    argvorig = argv;

    setprogname(argv[0]);

    catname = DEFAULT_CATALOG_XML;
    pflag = false;
    sflag = false;

    while ((ch = getopt(argc, argv, "+c:hpsv")) != -1) {
        switch (ch) {
        case 'c':
            catname = optarg;
            break;
        case 'h':
            usage(EXIT_SUCCESS);
            /* NOTREACHED */
        case 'p':
            pflag = true;
            break;
        case 's':
            if (catname == DEFAULT_CATALOG_XML)
                catname = DEFAULT_CATALOG_SGML;
            sflag = true;
            break;
        case 'v':
            version();
            /* NOTREACHED */
        case '?':
        default:
            usage(EXIT_FAILURE);
            /* NOTREACHED */
        }
    }
    argc -= optind;
    argv += optind;

    if (argc == 0)
        usage(EXIT_FAILURE);

    if (sflag) {
        ptr_add = sgml_add;
        ptr_create = sgml_create;
        ptr_lookup = sgml_lookup;
        ptr_remove = sgml_remove;
    } else {
        ptr_add = xml_add;
        ptr_create = xml_create;
        ptr_lookup = xml_lookup;
        ptr_remove = xml_remove;
    }

    if (pflag && strcmp(argv[0], "add") != 0)
        warnx("the `-p' flag is only useful in `add' mode");

    res = true;
    if (strcmp(argv[0], "add") == 0) {
        res = generic_add(argc - 1, argv + 1, catname, ptr_add, pflag);
    } else if (strcmp(argv[0], "create") == 0) {
        res = generic_create(catname, ptr_create);
    } else if (strcmp(argv[0], "destroy") == 0) {
        res = generic_destroy(catname);
    } else if (strcmp(argv[0], "lookup") == 0) {
        res = generic_lookup(argc - 1, argv + 1, catname, ptr_lookup);
    } else if (strcmp(argv[0], "remove") == 0) {
        res = generic_remove(argc - 1, argv + 1, catname, ptr_remove);
    } else {
        warnx("unknown action `%s'", argv[0]);
        res = false;
    }

    mem_status(catname, argcorig, argvorig);

    return res ? EXIT_SUCCESS : EXIT_FAILURE;
}

/*
 * Local Variables: ***
 * mode: c ***
 * c-file-style: "stroustrup" ***
 * End: ***
 * vim: syntax=c:expandtab:shiftwidth=4:softtabstop=4
 */
