Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/security/nss/cmd/multinit/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 24 kB image not shown  

Quelle  multinit.c   Sprache: C

 
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "nss.h"
#include "secutil.h"
#include "pk11pub.h"
#include "cert.h"

typedef struct commandDescriptStr {
    int required;
    char *arg;
    char *des;
} commandDescript;

enum optionNames {
    opt_liborder = 0,
    opt_mainDB,
    opt_lib1DB,
    opt_lib2DB,
    opt_mainRO,
    opt_lib1RO,
    opt_lib2RO,
    opt_mainCMD,
    opt_lib1CMD,
    opt_lib2CMD,
    opt_mainTokNam,
    opt_lib1TokNam,
    opt_lib2TokNam,
    opt_oldStyle,
    opt_verbose,
    opt_summary,
    opt_help,
    opt_last
};

static const secuCommandFlag options_init[] = {
    { /* opt_liborder */ 'o', PR_TRUE, "1M2zmi", PR_TRUE, "order" },
    { /* opt_mainDB */ 'd', PR_TRUE, 0, PR_FALSE, "main_db" },
    { /* opt_lib1DB */ '1', PR_TRUE, 0, PR_FALSE, "lib1_db" },
    { /* opt_lib2DB */ '2', PR_TRUE, 0, PR_FALSE, "lib2_db" },
    { /* opt_mainRO */ 'r', PR_FALSE, 0, PR_FALSE, "main_readonly" },
    { /* opt_lib1RO */ 0, PR_FALSE, 0, PR_FALSE, "lib1_readonly" },
    { /* opt_lib2RO */ 0, PR_FALSE, 0, PR_FALSE, "lib2_readonly" },
    { /* opt_mainCMD */ 'c', PR_TRUE, 0, PR_FALSE, "main_command" },
    { /* opt_lib1CMD */ 0, PR_TRUE, 0, PR_FALSE, "lib1_command" },
    { /* opt_lib2CMD */ 0, PR_TRUE, 0, PR_FALSE, "lib2_command" },
    { /* opt_mainTokNam */ 't', PR_TRUE, 0, PR_FALSE, "main_token_name" },
    { /* opt_lib1TokNam */ 0, PR_TRUE, 0, PR_FALSE, "lib1_token_name" },
    { /* opt_lib2TokNam */ 0, PR_TRUE, 0, PR_FALSE, "lib2_token_name" },
    { /* opt_oldStype */ 's', PR_FALSE, 0, PR_FALSE, "oldStype" },
    { /* opt_verbose */ 'v', PR_FALSE, 0, PR_FALSE, "verbose" },
    { /* opt_summary */ 'z', PR_FALSE, 0, PR_FALSE, "summary" },
    { /* opt_help */ 'h', PR_FALSE, 0, PR_FALSE, "help" }
};

static const commandDescript options_des[] = {
    { /* opt_liborder */ PR_FALSE, "initOrder",
      " Specifies the order of NSS initialization and shutdown. Order is\n"
      " given as a string where each character represents either an init or\n"
      " a shutdown of the main program or one of the 2 test libraries\n"
      " (library 1 and library 2). The valid characters are as follows:\n"
      " M Init the main program\n 1 Init library 1\n"
      " 2 Init library 2\n"
      " m Shutdown the main program\n i Shutdown library 1\n"
      " z Shutdown library 2\n" },
    { /* opt_mainDB */ PR_TRUE, "nss_db",
      " Specified the directory to open the nss database for the main\n"
      " program. Must be specified if \"M\" is given in the order string\n" },
    { /* opt_lib1DB */ PR_FALSE, "nss_db",
      " Specified the directory to open the nss database for library 1.\n"
      " Must be specified if \"1\" is given in the order string\n" },
    { /* opt_lib2DB */ PR_FALSE, "nss_db",
      " Specified the directory to open the nss database for library 2.\n"
      " Must be specified if \"2\" is given in the order string\n" },
    { /* opt_mainRO */ PR_FALSE, NULL,
      " Open the main program's database read only.\n" },
    { /* opt_lib1RO */ PR_FALSE, NULL,
      " Open library 1's database read only.\n" },
    { /* opt_lib2RO */ PR_FALSE, NULL,
      " Open library 2's database read only.\n" },
    { /* opt_mainCMD */ PR_FALSE, "nss_command",
      " Specifies the NSS command to execute in the main program.\n"
      " Valid commands are: \n"
      " key_slot, list_slots, list_certs, add_cert, none.\n"
      " Default is \"none\".\n" },
    { /* opt_lib1CMD */ PR_FALSE, "nss_command",
      " Specifies the NSS command to execute in library 1.\n" },
    { /* opt_lib2CMD */ PR_FALSE, "nss_command",
      " Specifies the NSS command to execute in library 2.\n" },
    { /* opt_mainTokNam */ PR_FALSE, "token_name",
      " Specifies the name of PKCS11 token for the main program's "
      "database.\n" },
    { /* opt_lib1TokNam */ PR_FALSE, "token_name",
      " Specifies the name of PKCS11 token for library 1's database.\n" },
    { /* opt_lib2TokNam */ PR_FALSE, "token_name",
      " Specifies the name of PKCS11 token for library 2's database.\n" },
    { /* opt_oldStype */ PR_FALSE, NULL,
      " Use NSS_Shutdown rather than NSS_ShutdownContext in the main\n"
      " program.\n" },
    { /* opt_verbose */ PR_FALSE, NULL,
      " Noisily output status to standard error\n" },
    { /* opt_summarize */ PR_FALSE, NULL,
      "report a summary of the test results\n" },
    { /* opt_help */ PR_FALSE, NULL, " give this message\n" }
};

/*
 * output our short help (table driven). (does not exit).
 */

static void
short_help(const char *prog)
{
    int count = opt_last;
    int i, words_found;

    /* make sure all the tables are up to date before we allow compiles to
     * succeed */

    PR_STATIC_ASSERT(sizeof(options_init) / sizeof(secuCommandFlag) == opt_last);
    PR_STATIC_ASSERT(sizeof(options_init) / sizeof(secuCommandFlag) ==
                     sizeof(options_des) / sizeof(commandDescript));

    /* print the base usage */
    fprintf(stderr, "usage: %s ", prog);
    for (i = 0, words_found = 0; i < count; i++) {
        if (!options_des[i].required) {
            fprintf(stderr, "[");
        }
        if (options_init[i].longform) {
            fprintf(stderr, "--%s", options_init[i].longform);
            words_found++;
        } else {
            fprintf(stderr, "-%c", options_init[i].flag);
        }
        if (options_init[i].needsArg) {
            if (options_des[i].arg) {
                fprintf(stderr, " %s", options_des[i].arg);
            } else {
                fprintf(stderr, " arg");
            }
            words_found++;
        }
        if (!options_des[i].required) {
            fprintf(stderr, "]");
        }
        if (i < count - 1) {
            if (words_found >= 5) {
                fprintf(stderr, "\n ");
                words_found = 0;
            } else {
                fprintf(stderr, " ");
            }
        }
    }
    fprintf(stderr, "\n");
}

/*
 * print out long help. like short_help, this does not exit
 */

static void
long_help(const char *prog)
{
    int i;
    int count = opt_last;

    short_help(prog);
    /* print the option descriptions */
    fprintf(stderr, "\n");
    for (i = 0; i < count; i++) {
        fprintf(stderr, " ");
        if (options_init[i].flag) {
            fprintf(stderr, "-%c", options_init[i].flag);
            if (options_init[i].longform) {
                fprintf(stderr, ",");
            }
        }
        if (options_init[i].longform) {
            fprintf(stderr, "--%s", options_init[i].longform);
        }
        if (options_init[i].needsArg) {
            if (options_des[i].arg) {
                fprintf(stderr, " %s", options_des[i].arg);
            } else {
                fprintf(stderr, " arg");
            }
            if (options_init[i].arg) {
                fprintf(stderr, " (default = \"%s\")", options_init[i].arg);
            }
        }
        fprintf(stderr, "\n%s", options_des[i].des);
    }
}

/*
 * record summary data
 */

struct bufferData {
    char *data; /* lowest address of the buffer */
    char *next; /* pointer to the next element on the buffer */
    int len;    /* length of the buffer */
};

/* our actual buffer. If data is NULL, then all append ops
 * except are noops */

static struct bufferData buffer = { NULL, NULL, 0 };

#define CHUNK_SIZE 1000

/*
 * get our initial data. and set the buffer variables up. on failure,
 * just don't initialize the buffer.
 */

static void
initBuffer(void)
{
    buffer.data = PORT_Alloc(CHUNK_SIZE);
    if (!buffer.data) {
        return;
    }
    buffer.next = buffer.data;
    buffer.len = CHUNK_SIZE;
}

/*
 * grow the buffer. If we can't get more data, record a 'D' in the second
 * to last record and allow the rest of the data to overwrite the last
 * element.
 */

static void
growBuffer(void)
{
    char *new = PORT_Realloc(buffer.data, buffer.len + CHUNK_SIZE);
    if (!new) {
        buffer.data[buffer.len - 2] = 'D'/* signal malloc failure in summary */
        /* buffer must always point to good memory if it exists */
        buffer.next = buffer.data + (buffer.len - 1);
        return;
    }
    buffer.next = new + (buffer.next - buffer.data);
    buffer.data = new;
    buffer.len += CHUNK_SIZE;
}

/*
 * append a label, doubles as appending a single character.
 */

static void
appendLabel(char label)
{
    if (!buffer.data) {
        return;
    }

    *buffer.next++ = label;
    if (buffer.data + buffer.len >= buffer.next) {
        growBuffer();
    }
}

/*
 * append a string onto the buffer. The result will be <string>
 */

static void
appendString(char *string)
{
    if (!buffer.data) {
        return;
    }

    appendLabel('<');
    while (*string) {
        appendLabel(*string++);
    }
    appendLabel('>');
}

/*
 * append a bool, T= true, F=false
 */

static void
appendBool(PRBool bool)
{
    if (!buffer.data) {
        return;
    }

    if (bool) {
        appendLabel('t');
    } else {
        appendLabel('f');
    }
}

/*
 * append a single hex nibble.
 */

static void
appendHex(unsigned char nibble)
{
    if (nibble <= 9) {
        appendLabel('0' + nibble);
    } else {
        appendLabel('a' + nibble - 10);
    }
}

/*
 * append a 32 bit integer (even on a 64 bit platform).
 * for simplicity append it as a hex value, full extension with 0x prefix.
 */

static void
appendInt(unsigned int value)
{
    int i;

    if (!buffer.data) {
        return;
    }

    appendLabel('0');
    appendLabel('x');
    value = value & 0xffffffff; /* only look at the buttom 8 bytes */
    for (i = 0; i < 8; i++) {
        appendHex(value >> 28);
        value = value << 4;
    }
}

/* append a trust flag */
static void
appendFlags(unsigned int flag)
{
    char trust[10];
    char *cp = trust;

    trust[0] = 0;
    printflags(trust, flag);
    while (*cp) {
        appendLabel(*cp++);
    }
}

/*
 * dump our buffer out with a result= flag so we can find it easily.
 * free the buffer as a side effect.
 */

static void
dumpBuffer(void)
{
    if (!buffer.data) {
        return;
    }

    appendLabel(0); /* terminate */
    printf("\nresult=%s\n", buffer.data);
    PORT_Free(buffer.data);
    buffer.data = buffer.next = NULL;
    buffer.len = 0;
}

/*
 * usage, like traditional usage, automatically exit
 */

static void
usage(const char *prog)
{
    short_help(prog);
    dumpBuffer();
    exit(1);
}

/*
 * like usage, except prints the long version of help
 */

static void
usage_long(const char *prog)
{
    long_help(prog);
    dumpBuffer();
    exit(1);
}

static const char *
bool2String(PRBool bool)
{
    return bool ? "true" : "false";
}

/*
 * print out interesting info about the given slot
 */

void
print_slot(PK11SlotInfo *slot, int log)
{
    if (log) {
        fprintf(stderr, "* Name=%s Token_Name=%s present=%s, ro=%s *\n",
                PK11_GetSlotName(slot), PK11_GetTokenName(slot),
                bool2String(PK11_IsPresent(slot)),
                bool2String(PK11_IsReadOnly(slot)));
    }
    appendLabel('S');
    appendString(PK11_GetTokenName(slot));
    appendBool(PK11_IsPresent(slot));
    appendBool(PK11_IsReadOnly(slot));
}

/*
 * list all our slots
 */

void
do_list_slots(const char *progName, int log)
{
    PK11SlotList *list;
    PK11SlotListElement *le;

    list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, NULL);
    if (list == NULL) {
        fprintf(stderr, "ERROR: no tokens found %s\n",
                SECU_Strerror(PORT_GetError()));
        appendLabel('S');
        appendString("none");
        return;
    }

    for (le = PK11_GetFirstSafe(list); le;
         le = PK11_GetNextSafe(list, le, PR_TRUE)) {
        print_slot(le->slot, log);
    }
    PK11_FreeSlotList(list);
}

static PRBool
sort_CN(CERTCertificate *certa, CERTCertificate *certb, void *arg)
{
    char *commonNameA, *commonNameB;
    int ret;

    commonNameA = CERT_GetCommonName(&certa->subject);
    commonNameB = CERT_GetCommonName(&certb->subject);

    if (commonNameA == NULL) {
        PORT_Free(commonNameB);
        return PR_TRUE;
    }
    if (commonNameB == NULL) {
        PORT_Free(commonNameA);
        return PR_FALSE;
    }
    ret = PORT_Strcmp(commonNameA, commonNameB);
    PORT_Free(commonNameA);
    PORT_Free(commonNameB);
    return (ret < 0) ? PR_TRUE : PR_FALSE;
}

/*
 * list all the certs
 */

void
do_list_certs(const char *progName, int log)
{
    CERTCertList *list;
    CERTCertList *sorted;
    CERTCertListNode *node;
    CERTCertTrust trust;
    unsigned int i;

    list = PK11_ListCerts(PK11CertListUnique, NULL);
    if (list == NULL) {
        fprintf(stderr, "ERROR: no certs found %s\n",
                SECU_Strerror(PORT_GetError()));
        appendLabel('C');
        appendString("none");
        return;
    }

    sorted = CERT_NewCertList();
    if (sorted == NULL) {
        fprintf(stderr, "ERROR: no certs found %s\n",
                SECU_Strerror(PORT_GetError()));
        appendLabel('C');
        appendLabel('E');
        appendInt(PORT_GetError());
        return;
    }

    /* sort the list */
    for (node = CERT_LIST_HEAD(list); !CERT_LIST_END(node, list);
         node = CERT_LIST_NEXT(node)) {
        CERT_AddCertToListSorted(sorted, node->cert, sort_CN, NULL);
    }

    for (node = CERT_LIST_HEAD(sorted); !CERT_LIST_END(node, sorted);
         node = CERT_LIST_NEXT(node)) {
        CERTCertificate *cert = node->cert;
        char *commonName;

        SECU_PrintCertNickname(node, stderr);
        if (log) {
            fprintf(stderr, "* Slot=%s*\n", cert->slot ? PK11_GetTokenName(cert->slot) : "none");
            fprintf(stderr, "* Nickname=%s*\n", cert->nickname);
            fprintf(stderr, "* Subject=<%s>*\n", cert->subjectName);
            fprintf(stderr, "* Issuer=<%s>*\n", cert->issuerName);
            fprintf(stderr, "* SN=");
            for (i = 0; i < cert->serialNumber.len; i++) {
                if (i != 0)
                    fprintf(stderr, ":");
                fprintf(stderr, "%02x", cert->serialNumber.data[0]);
            }
            fprintf(stderr, " *\n");
        }
        appendLabel('C');
        commonName = CERT_GetCommonName(&cert->subject);
        appendString(commonName ? commonName : "*NoName*");
        PORT_Free(commonName);
        if (CERT_GetCertTrust(cert, &trust) == SECSuccess) {
            appendFlags(trust.sslFlags);
            appendFlags(trust.emailFlags);
            appendFlags(trust.objectSigningFlags);
        }
    }
    CERT_DestroyCertList(list);
}

/*
 * need to implement yet... try to add a new certificate
 */

void
do_add_cert(const char *progName, int log)
{
    PORT_Assert(/* do_add_cert not implemented */ 0);
}

/*
 * display the current key slot
 */

void
do_key_slot(const char *progName, int log)
{
    PK11SlotInfo *slot = PK11_GetInternalKeySlot();
    if (!slot) {
        fprintf(stderr, "ERROR: no internal key slot found %s\n",
                SECU_Strerror(PORT_GetError()));
        appendLabel('K');
        appendLabel('S');
        appendString("none");
    }
    print_slot(slot, log);
    PK11_FreeSlot(slot);
}

/*
 * execute some NSS command.
 */

void
do_command(const char *label, int initialized, secuCommandFlag *command,
           const char *progName, int log)
{
    char *command_string;
    if (!initialized) {
        return;
    }

    if (command->activated) {
        command_string = command->arg;
    } else {
        command_string = "none";
    }

    if (log) {
        fprintf(stderr, "*Executing nss command \"%s\" for %s*\n",
                command_string, label);
    }

    /* do something */
    if (PORT_Strcasecmp(command_string, "list_slots") == 0) {
        do_list_slots(progName, log);
    } else if (PORT_Strcasecmp(command_string, "list_certs") == 0) {
        do_list_certs(progName, log);
    } else if (PORT_Strcasecmp(command_string, "add_cert") == 0) {
        do_add_cert(progName, log);
    } else if (PORT_Strcasecmp(command_string, "key_slot") == 0) {
        do_key_slot(progName, log);
    } else if (PORT_Strcasecmp(command_string, "none") != 0) {
        fprintf(stderr, ">> Unknown command (%s)\n", command_string);
        appendLabel('E');
        appendString("bc");
        usage_long(progName);
    }
}

/*
 * functions do handle
 * different library initializations.
 */

static int main_initialized;
static int lib1_initialized;
static int lib2_initialized;

void
main_Init(secuCommandFlag *db, secuCommandFlag *tokNam,
          int readOnly, const char *progName, int log)
{
    SECStatus rv;
    if (log) {
        fprintf(stderr, "*NSS_Init for the main program*\n");
    }
    appendLabel('M');
    if (!db->activated) {
        fprintf(stderr, ">> No main_db has been specified\n");
        usage(progName);
    }
    if (main_initialized) {
        fprintf(stderr, "Warning: Second initialization of Main\n");
        appendLabel('E');
        appendString("2M");
    }
    if (tokNam->activated) {
        PK11_ConfigurePKCS11(NULL, NULL, NULL, tokNam->arg,
                             NULL, NULL, NULL, NULL, 0, 0);
    }
    rv = NSS_Initialize(db->arg, """""",
                        NSS_INIT_NOROOTINIT |
                            (readOnly ? NSS_INIT_READONLY : 0));
    if (rv != SECSuccess) {
        appendLabel('E');
        appendInt(PORT_GetError());
        fprintf(stderr, ">> %s\n", SECU_Strerror(PORT_GetError()));
        dumpBuffer();
        exit(1);
    }
    main_initialized = 1;
}

void
main_Do(secuCommandFlag *command, const char *progName, int log)
{
    do_command("main", main_initialized, command, progName, log);
}

void
main_Shutdown(int old_style, const char *progName, int log)
{
    SECStatus rv;
    appendLabel('N');
    if (log) {
        fprintf(stderr, "*NSS_Shutdown for the main program*\n");
    }
    if (!main_initialized) {
        fprintf(stderr, "Warning: Main shutdown without corresponding init\n");
    }
    if (old_style) {
        rv = NSS_Shutdown();
    } else {
        rv = NSS_ShutdownContext(NULL);
    }
    fprintf(stderr, "Shutdown main state = %d\n", rv);
    if (rv != SECSuccess) {
        appendLabel('E');
        appendInt(PORT_GetError());
        fprintf(stderr, "ERROR: %s\n", SECU_Strerror(PORT_GetError()));
    }
    main_initialized = 0;
}

/* common library init */
NSSInitContext *
lib_Init(const char *lableString, char label, int initialized,
         secuCommandFlag *db, secuCommandFlag *tokNam, int readonly,
         const char *progName, int log)
{
    NSSInitContext *ctxt;
    NSSInitParameters initStrings;
    NSSInitParameters *initStringPtr = NULL;

    appendLabel(label);
    if (log) {
        fprintf(stderr, "*NSS_Init for %s*\n", lableString);
    }

    if (!db->activated) {
        fprintf(stderr, ">> No %s_db has been specified\n", lableString);
        usage(progName);
    }
    if (initialized) {
        fprintf(stderr, "Warning: Second initialization of %s\n", lableString);
    }
    if (tokNam->activated) {
        PORT_Memset(&initStrings, 0, sizeof(initStrings));
        initStrings.length = sizeof(initStrings);
        initStrings.dbTokenDescription = tokNam->arg;
        initStringPtr = &initStrings;
    }
    ctxt = NSS_InitContext(db->arg, """""", initStringPtr,
                           NSS_INIT_NOROOTINIT |
                               (readonly ? NSS_INIT_READONLY : 0));
    if (ctxt == NULL) {
        appendLabel('E');
        appendInt(PORT_GetError());
        fprintf(stderr, ">> %s\n", SECU_Strerror(PORT_GetError()));
        dumpBuffer();
        exit(1);
    }
    return ctxt;
}

/* common library shutdown */
void
lib_Shutdown(const char *labelString, char label, NSSInitContext *ctx,
             int initialize, const char *progName, int log)
{
    SECStatus rv;
    appendLabel(label);
    if (log) {
        fprintf(stderr, "*NSS_Shutdown for %s\n*", labelString);
    }
    if (!initialize) {
        fprintf(stderr, "Warning: %s shutdown without corresponding init\n",
                labelString);
    }
    rv = NSS_ShutdownContext(ctx);
    fprintf(stderr, "Shutdown %s state = %d\n", labelString, rv);
    if (rv != SECSuccess) {
        appendLabel('E');
        appendInt(PORT_GetError());
        fprintf(stderr, "ERROR: %s\n", SECU_Strerror(PORT_GetError()));
    }
}

static NSSInitContext *lib1_context;
static NSSInitContext *lib2_context;
void
lib1_Init(secuCommandFlag *db, secuCommandFlag *tokNam,
          int readOnly, const char *progName, int log)
{
    lib1_context = lib_Init("lib1"'1', lib1_initialized, db, tokNam,
                            readOnly, progName, log);
    lib1_initialized = 1;
}

void
lib2_Init(secuCommandFlag *db, secuCommandFlag *tokNam,
          int readOnly, const char *progName, int log)
{
    lib2_context = lib_Init("lib2"'2', lib2_initialized,
                            db, tokNam, readOnly, progName, log);
    lib2_initialized = 1;
}

void
lib1_Do(secuCommandFlag *command, const char *progName, int log)
{
    do_command("lib1", lib1_initialized, command, progName, log);
}

void
lib2_Do(secuCommandFlag *command, const char *progName, int log)
{
    do_command("lib2", lib2_initialized, command, progName, log);
}

void
lib1_Shutdown(const char *progName, int log)
{
    lib_Shutdown("lib1"'I', lib1_context, lib1_initialized, progName, log);
    lib1_initialized = 0;
    /* don't clear lib1_Context, so we can test multiple attempts to close
     * the same context produces correct errors*/

}

void
lib2_Shutdown(const char *progName, int log)
{
    lib_Shutdown("lib2"'Z', lib2_context, lib2_initialized, progName, log);
    lib2_initialized = 0;
    /* don't clear lib2_Context, so we can test multiple attempts to close
     * the same context produces correct errors*/

}

int
main(int argc, char **argv)
{
    SECStatus rv;
    secuCommand libinit;
    char *progName;
    char *order;
    secuCommandFlag *options;
    int log = 0;

    progName = strrchr(argv[0], '/');
    progName = progName ? progName + 1 : argv[0];

    libinit.numCommands = 0;
    libinit.commands = 0;
    libinit.numOptions = opt_last;
    options = (secuCommandFlag *)PORT_Alloc(sizeof(options_init));
    if (options == NULL) {
        fprintf(stderr, ">> %s:Not enough free memory to run command\n",
                progName);
        exit(1);
    }
    PORT_Memcpy(options, options_init, sizeof(options_init));
    libinit.options = options;

    rv = SECU_ParseCommandLine(argc, argv, progName, &libinit);
    if (rv != SECSuccess) {
        usage(progName);
    }

    if (libinit.options[opt_help].activated) {
        long_help(progName);
        exit(0);
    }

    log = libinit.options[opt_verbose].activated;
    if (libinit.options[opt_summary].activated) {
        initBuffer();
    }

    order = libinit.options[opt_liborder].arg;
    if (!order) {
        usage(progName);
    }

    if (log) {
        fprintf(stderr, "* initializing with order \"%s\"*\n", order);
    }

    for (; *order; order++) {
        switch (*order) {
            case 'M':
                main_Init(&libinit.options[opt_mainDB],
                          &libinit.options[opt_mainTokNam],
                          libinit.options[opt_mainRO].activated,
                          progName, log);
                break;
            case '1':
                lib1_Init(&libinit.options[opt_lib1DB],
                          &libinit.options[opt_lib1TokNam],
                          libinit.options[opt_lib1RO].activated,
                          progName, log);
                break;
            case '2':
                lib2_Init(&libinit.options[opt_lib2DB],
                          &libinit.options[opt_lib2TokNam],
                          libinit.options[opt_lib2RO].activated,
                          progName, log);
                break;
            case 'm':
                main_Shutdown(libinit.options[opt_oldStyle].activated,
                              progName, log);
                break;
            case 'i':
                lib1_Shutdown(progName, log);
                break;
            case 'z':
                lib2_Shutdown(progName, log);
                break;
            default:
                fprintf(stderr, ">> Unknown init/shutdown command \"%c\"", *order);
                usage_long(progName);
        }
        main_Do(&libinit.options[opt_mainCMD], progName, log);
        lib1_Do(&libinit.options[opt_lib1CMD], progName, log);
        lib2_Do(&libinit.options[opt_lib2CMD], progName, log);
    }

    if (NSS_IsInitialized()) {
        appendLabel('X');
        fprintf(stderr, "Warning: NSS is initialized\n");
    }
    dumpBuffer();

    exit(0);
}

Messung V0.5
C=92 H=94 G=92

¤ Dauer der Verarbeitung: 0.20 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.