initial checkin of the new command library.

This commit is contained in:
mcgreer%netscape.com 2001-09-14 18:37:37 +00:00
Родитель 9e69f4ae7f
Коммит b076ea1c68
5 изменённых файлов: 756 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,75 @@
#! gmake
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Netscape security libraries.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1994-2000 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the
# terms of the GNU General Public License Version 2 or later (the
# "GPL"), in which case the provisions of the GPL are applicable
# instead of those above. If you wish to allow use of your
# version of this file only under the terms of the GPL and not to
# allow others to use your version of this file under the MPL,
# indicate your decision by deleting the provisions above and
# replace them with the notice and other provisions required by
# the GPL. If you do not delete the provisions above, a recipient
# may use your version of this file under either the MPL or the
# GPL.
#
#######################################################################
# (1) Include initial platform-independent assignments (MANDATORY). #
#######################################################################
include manifest.mn
#######################################################################
# (2) Include "global" configuration information. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/config.mk
#######################################################################
# (3) Include "component" configuration information. (OPTIONAL) #
#######################################################################
#######################################################################
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
#######################################################################
include config.mk
#######################################################################
# (5) Execute "global" rules. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/rules.mk
#######################################################################
# (6) Execute "component" rules. (OPTIONAL) #
#######################################################################
#######################################################################
# (7) Execute "local" rules. (OPTIONAL). #
#######################################################################

Просмотреть файл

@ -0,0 +1,474 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include <string.h>
#include <ctype.h>
#include "cmdutil.h"
static int s_indent_size = 4;
void
CMD_SetIndentSize(int size)
{
s_indent_size = size;
}
#if 0
static void
indent(PRFileDesc *out, int level)
{
int i, j;
for (i=0; i<level; i++)
for (j=0; j<s_indent_size; j++)
PR_fprintf(out, " ");
}
#endif
struct cmdPrintStateStr {
PRFileDesc *file;
int width;
int indent;
int linepos;
};
static void
init_print_ps(cmdPrintState *ps, PRFileDesc *outfile, int width, int indent)
{
ps->file = (outfile) ? outfile : PR_STDOUT;
ps->width = (width > 0) ? width : 80;
ps->indent = (indent > 0) ? indent : 0;
ps->linepos = 0;
}
static void
print_ps_indent(cmdPrintState *ps)
{
int j;
if (ps->linepos != 0) {
PR_fprintf(ps->file, "\n");
ps->linepos = 0;
}
for (j=0; j<=ps->indent; j++) PR_fprintf(ps->file, " ");
ps->linepos = ps->indent;
}
static void
print_ps_to_indent(cmdPrintState *ps)
{
if (ps->linepos > ps->indent)
PR_fprintf(ps->file, "\n");
while (ps->linepos <= ps->indent) {
PR_fprintf(ps->file, " ");
ps->linepos++;
}
}
static void
nprintbuf(cmdPrintState *ps, char *buf, int start, int len)
{
int j;
for (j=start; j<start + len; j++) {
if (buf[j] == '\n') {
PR_fprintf(ps->file, "\n");
ps->linepos = 0;
print_ps_indent(ps);
} else {
PR_fprintf(ps->file, "%c", buf[j]);
ps->linepos++;
}
}
}
static void
nprintf(cmdPrintState *ps, char *msg, ...)
{
char buf[256];
int i, len, grouplen;
PRBool openquote, openbracket, openparen, openangle, itsaword;
va_list args;
va_start(args, msg);
vsprintf(buf, msg, args);
len = strlen(buf);
/* print_ps_indent(ps); */
if (len < ps->width - ps->linepos) {
nprintbuf(ps, buf, 0, len + 1);
return;
}
/* group in this order: " [ ( < word > ) ] " */
i=0;
openquote=openbracket=openparen=openangle=itsaword=PR_FALSE;
while (i<len) {
grouplen = 0;
if (buf[i] == '\"') { openquote = PR_TRUE; grouplen = 1; }
else if (buf[i] == '[') { openbracket = PR_TRUE; grouplen = 1; }
else if (buf[i] == '(') { openparen = PR_TRUE; grouplen = 1; }
else if (buf[i] == '<') { openangle = PR_TRUE; grouplen = 1; }
else itsaword = PR_TRUE;
while (grouplen < len && buf[i+grouplen] != '\0' &&
((openquote && buf[i+grouplen] != '\"') ||
(openbracket && buf[i+grouplen] != ']') ||
(openparen && buf[i+grouplen] != ')') ||
(openangle && buf[i+grouplen] != '>') ||
(itsaword && !isspace(buf[i+grouplen]))))
grouplen++;
grouplen++; /* grab the terminator (whitespace for word) */
if (!itsaword && isspace(buf[i+grouplen])) grouplen++;
if (grouplen < ps->width - ps->linepos) {
nprintbuf(ps, buf, i, grouplen);
} else if (grouplen < ps->width - ps->indent) {
print_ps_indent(ps);
nprintbuf(ps, buf, i, grouplen);
} else {
/* it's just too darn long. what to do? */
}
i += grouplen;
openquote=openbracket=openparen=openangle=itsaword=PR_FALSE;
}
va_end(args);
}
void
CMD_PrintUsageString(cmdPrintState *ps, char *str)
{
nprintf(ps, "%s", str);
}
/* void because it exits with Usage() if failure */
static void
command_line_okay(cmdCommand *cmd, char *progName)
{
int i, c = -1;
/* user asked for help. hope somebody gives it to them. */
if (cmd->opt[0].on) return;
/* check that the command got all of its needed options */
for (i=0; i<cmd->ncmd; i++) {
if (cmd->cmd[i].on) {
if (c > 0) {
fprintf(stderr,
"%s: only one command can be given at a time.\n",
progName);
CMD_Usage(progName, cmd);
} else {
c = i;
}
}
}
if (cmd->cmd[c].argUse == CMDArgReq && cmd->cmd[c].arg == NULL) {
/* where's the arg when you need it... */
fprintf(stderr, "%s: command --%s requires an argument.\n",
progName, cmd->cmd[c].s);
fprintf(stderr, "type \"%s --%s --help\" for help.\n",
progName, cmd->cmd[c].s);
CMD_Usage(progName, cmd);
}
for (i=0; i<cmd->nopt; i++) {
if (cmd->cmd[c].req & CMDBIT(i)) {
/* command requires this option */
if (!cmd->opt[i].on) {
/* but it ain't there */
fprintf(stderr, "%s: command --%s requires option --%s.\n",
progName, cmd->cmd[c].s, cmd->opt[i].s);
} else {
/* okay, its there, but does it have an arg? */
if (cmd->opt[i].argUse == CMDArgReq && !cmd->opt[i].arg) {
fprintf(stderr, "%s: option --%s requires an argument.\n",
progName, cmd->opt[i].s);
}
}
} else if (cmd->cmd[c].opt & CMDBIT(i)) {
/* this option is optional */
if (cmd->opt[i].on) {
/* okay, its there, but does it have an arg? */
if (cmd->opt[i].argUse == CMDArgReq && !cmd->opt[i].arg) {
fprintf(stderr, "%s: option --%s requires an argument.\n",
progName, cmd->opt[i].s);
}
}
} else {
/* command knows nothing about it */
if (cmd->opt[i].on) {
/* so why the h--- is it on? */
fprintf(stderr, "%s: option --%s not used with command --%s.\n",
progName, cmd->opt[i].s, cmd->cmd[c].s);
}
}
}
}
static char *
get_arg(char *curopt, char **nextopt, int argc, int *index)
{
char *str;
if (curopt) {
str = curopt;
} else {
if (*index + 1 >= argc) return NULL;
/* not really an argument but another flag */
if (nextopt[*index+1][0] == '-') return NULL;
str = nextopt[++(*index)];
}
/* parse the option */
return strdup(str);
}
int
CMD_ParseCommandLine(int argc, char **argv, char *progName, cmdCommand *cmd)
{
int i, j, k;
int cmdToRun = -1;
char *flag;
i=1;
if (argc <= 1) return -2; /* gross hack for cmdless things like atob */
do {
flag = argv[i];
if (strlen(flag) < 2) /* huh? */
return -1;
if (flag[0] != '-')
return -1;
/* ignore everything after lone "--" (app-specific weirdness there) */
if (strcmp(flag, "--") == 0)
return cmdToRun;
/* single hyphen means short alias (single-char) */
if (flag[1] != '-') {
j=1;
/* collect a set of opts, ex. -abc */
while (flag[j] != '\0') {
PRBool found = PR_FALSE;
/* walk the command set looking for match */
for (k=0; k<cmd->ncmd; k++) {
if (flag[j] == cmd->cmd[k].c) {
/* done - only take one command at a time */
if (j > 1) return -1;
cmd->cmd[k].on = found = PR_TRUE;
cmdToRun = k;
if (cmd->cmd[k].argUse != CMDNoArg)
cmd->cmd[k].arg = get_arg(NULL, argv, argc, &i);
goto next_flag;
}
}
/* wasn't found in commands, try options */
for (k=0; k<cmd->nopt; k++) {
if (flag[j] == cmd->opt[k].c) {
/* collect this option and keep going */
cmd->opt[k].on = found = PR_TRUE;
if (flag[j+1] == '\0') {
if (cmd->opt[k].argUse != CMDNoArg)
cmd->opt[k].arg = get_arg(NULL, argv, argc, &i);
goto next_flag;
}
}
}
j++;
if (!found) return -1;
}
} else { /* long alias, ex. --list */
char *fl = NULL, *arg = NULL;
PRBool hyphened = PR_FALSE;
fl = &flag[2];
arg = strchr(fl, '=');
if (arg) {
*arg++ = '\0';
} else {
arg = strchr(fl, '-');
if (arg) {
hyphened = PR_TRUE; /* watch this, see below */
*arg++ = '\0';
}
}
for (k=0; k<cmd->ncmd; k++) {
if (strcmp(fl, cmd->cmd[k].s) == 0) {
cmd->cmd[k].on = PR_TRUE;
cmdToRun = k;
if (cmd->cmd[k].argUse != CMDNoArg || hyphened) {
cmd->cmd[k].arg = get_arg(arg, argv, argc, &i);
}
if (arg) arg[-1] = '=';
goto next_flag;
}
}
for (k=0; k<cmd->nopt; k++) {
if (strcmp(fl, cmd->opt[k].s) == 0) {
cmd->opt[k].on = PR_TRUE;
if (cmd->opt[k].argUse != CMDNoArg || hyphened) {
cmd->opt[k].arg = get_arg(arg, argv, argc, &i);
}
if (arg) arg[-1] = '=';
goto next_flag;
}
}
return -1;
}
next_flag:
i++;
} while (i < argc);
command_line_okay(cmd, progName);
return cmdToRun;
}
void
CMD_LongUsage(char *progName, cmdCommand *cmd, cmdUsageCallback usage)
{
int i, j;
PRBool oneCommand = PR_FALSE;
cmdPrintState ps;
init_print_ps(&ps, PR_STDERR, 80, 0);
nprintf(&ps, "\n%s: ", progName);
/* prints app-specific header */
ps.indent = strlen(progName) + 4;
usage(&ps, 0, PR_FALSE, PR_TRUE, PR_FALSE);
for (i=0; i<cmd->ncmd; i++) if (cmd->cmd[i].on) oneCommand = PR_TRUE;
for (i=0; i<cmd->ncmd; i++) {
if ((oneCommand && cmd->cmd[i].on) || !oneCommand) {
ps.indent = 0;
print_ps_indent(&ps);
if (cmd->cmd[i].c != 0) {
nprintf(&ps, "-%c, ", cmd->cmd[i].c);
nprintf(&ps, "--%-16s ", cmd->cmd[i].s);
} else {
nprintf(&ps, "--%-20s ", cmd->cmd[i].s);
}
ps.indent += 20;
usage(&ps, i, PR_TRUE, PR_FALSE, PR_FALSE);
for (j=0; j<cmd->nopt; j++) {
if (cmd->cmd[i].req & CMDBIT(j)) {
ps.indent = 0;
print_ps_indent(&ps);
nprintf(&ps, "%3s* ", "");
if (cmd->opt[j].c != 0) {
nprintf(&ps, "-%c, ", cmd->opt[j].c);
nprintf(&ps, "--%-16s ", cmd->opt[j].s);
} else {
nprintf(&ps, "--%-20s ", cmd->opt[j].s);
}
ps.indent += 29;
usage(&ps, j, PR_FALSE, PR_FALSE, PR_FALSE);
}
}
for (j=0; j<cmd->nopt; j++) {
if (cmd->cmd[i].opt & CMDBIT(j)) {
ps.indent = 0;
print_ps_indent(&ps);
nprintf(&ps, "%5s", "");
if (cmd->opt[j].c != 0) {
nprintf(&ps, "-%c, ", cmd->opt[j].c);
nprintf(&ps, "--%-16s ", cmd->opt[j].s);
} else {
nprintf(&ps, "--%-20s ", cmd->opt[j].s);
}
ps.indent += 29;
usage(&ps, j, PR_FALSE, PR_FALSE, PR_FALSE);
}
}
}
nprintf(&ps, "\n");
}
ps.indent = 0;
nprintf(&ps, "\n* - required flag for command\n\n");
/* prints app-specific footer */
usage(&ps, 0, PR_FALSE, PR_FALSE, PR_TRUE);
/*nprintf(&ps, "\n\n");*/
exit(1);
}
void
CMD_Usage(char *progName, cmdCommand *cmd)
{
int i, j, inc;
PRBool first;
cmdPrintState ps;
init_print_ps(&ps, PR_STDERR, 80, 0);
nprintf(&ps, "%s", progName);
ps.indent = strlen(progName) + 1;
print_ps_to_indent(&ps);
for (i=0; i<cmd->ncmd; i++) {
if (cmd->cmd[i].c != 0) {
nprintf(&ps, "-%c", cmd->cmd[i].c);
inc = 4;
} else {
nprintf(&ps, "--%s", cmd->cmd[i].s);
inc = 4 + strlen(cmd->cmd[i].s);
}
first = PR_TRUE;
ps.indent += inc;
print_ps_to_indent(&ps);
for (j=0; j<cmd->nopt; j++) {
if (cmd->cmd[i].req & CMDBIT(j)) {
if (cmd->opt[j].c != 0 && cmd->opt[j].argUse == CMDNoArg) {
if (first) {
nprintf(&ps, "-");
first = !first;
}
nprintf(&ps, "%c", cmd->opt[j].c);
}
}
}
for (j=0; j<cmd->nopt; j++) {
if (cmd->cmd[i].req & CMDBIT(j)) {
if (cmd->opt[j].c != 0)
nprintf(&ps, "-%c ", cmd->opt[j].c);
else
nprintf(&ps, "--%s ", cmd->opt[j].s);
if (cmd->opt[j].argUse != CMDNoArg)
nprintf(&ps, "%s ", cmd->opt[j].s);
}
}
first = PR_TRUE;
for (j=0; j<cmd->nopt; j++) {
if (cmd->cmd[i].opt & CMDBIT(j)) {
if (cmd->opt[j].c != 0 && cmd->opt[j].argUse == CMDNoArg) {
if (first) {
nprintf(&ps, "[-");
first = !first;
}
nprintf(&ps, "%c", cmd->opt[j].c);
}
}
}
if (!first) nprintf(&ps, "] ");
for (j=0; j<cmd->nopt; j++) {
if (cmd->cmd[i].opt & CMDBIT(j) &&
cmd->opt[j].argUse != CMDNoArg) {
if (cmd->opt[j].c != 0)
nprintf(&ps, "[-%c %s] ", cmd->opt[j].c, cmd->opt[j].s);
else
nprintf(&ps, "[--%s %s] ", cmd->opt[j].s, cmd->opt[j].s);
}
}
ps.indent -= inc;
print_ps_indent(&ps);
}
ps.indent = 0;
nprintf(&ps, "\n");
exit(1);
}

Просмотреть файл

@ -0,0 +1,115 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef _CMDUTIL_H_
#define _CMDUTIL_H_
#include <stdio.h>
#include "nspr.h"
#include "nssbase.h"
typedef int
(* CMD_PPFunc)(PRFileDesc *out, NSSItem *item, char *msg, int level);
/*
* Command Line Parsing routines
*
* The attempt here is to provide common functionality for command line
* parsing across an array of tools. The tools should obey the historical
* rules of:
*
* (1) one command per line,
* (2) the command should be uppercase,
* (3) options should be lowercase,
* (4) a short usage statement is presented in case of error,
* (5) a long usage statement is given by -? or --help
*/
/* To aid in formatting usage output. XXX Uh, why exposed? */
typedef struct cmdPrintStateStr cmdPrintState;
typedef enum {
CMDArgReq = 0,
CMDArgOpt,
CMDNoArg
} CMDArg;
struct cmdCommandLineArgStr {
char c; /* one-character alias for flag */
char *s; /* string alias for flag */
CMDArg argUse; /* flag takes an argument */
char *arg; /* argument given for flag */
PRBool on; /* flag was issued at command-line */
int req; /* required arguments for commands */
int opt; /* optional arguments for commands */
};
struct cmdCommandLineOptStr {
char c; /* one-character alias for flag */
char *s; /* string alias for flag */
CMDArg argUse; /* flag takes an argument */
char *arg; /* argument given for flag */
PRBool on; /* flag was issued at command-line */
};
typedef struct cmdCommandLineArgStr cmdCommandLineArg;
typedef struct cmdCommandLineOptStr cmdCommandLineOpt;
struct cmdCommandStr {
int ncmd;
int nopt;
cmdCommandLineArg *cmd;
cmdCommandLineOpt *opt;
};
typedef struct cmdCommandStr cmdCommand;
int
CMD_ParseCommandLine(int argc, char **argv, char *progName, cmdCommand *cmd);
typedef void
(* cmdUsageCallback)(cmdPrintState *, int, PRBool, PRBool, PRBool);
#define CMDBIT(n) (1<<n)
void
CMD_Usage(char *progName, cmdCommand *cmd);
void
CMD_LongUsage(char *progName, cmdCommand *cmd, cmdUsageCallback use);
void
CMD_PrintUsageString(cmdPrintState *ps, char *str);
#endif /* _CMDUTIL_H_ */

Просмотреть файл

@ -0,0 +1,43 @@
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Netscape security libraries.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1994-2000 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the
# terms of the GNU General Public License Version 2 or later (the
# "GPL"), in which case the provisions of the GPL are applicable
# instead of those above. If you wish to allow use of your
# version of this file only under the terms of the GPL and not to
# allow others to use your version of this file under the MPL,
# indicate your decision by deleting the provisions above and
# replace them with the notice and other provisions required by
# the GPL. If you do not delete the provisions above, a recipient
# may use your version of this file under either the MPL or the
# GPL.
#
#
# Override TARGETS variable so that only static libraries
# are specifed as dependencies within rules.mk.
#
TARGETS = $(LIBRARY)
SHARED_LIBRARY =
IMPORT_LIBRARY =
PROGRAM =

Просмотреть файл

@ -0,0 +1,49 @@
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Netscape security libraries.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1994-2000 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the
# terms of the GNU General Public License Version 2 or later (the
# "GPL"), in which case the provisions of the GPL are applicable
# instead of those above. If you wish to allow use of your
# version of this file only under the terms of the GPL and not to
# allow others to use your version of this file under the MPL,
# indicate your decision by deleting the provisions above and
# replace them with the notice and other provisions required by
# the GPL. If you do not delete the provisions above, a recipient
# may use your version of this file under either the MPL or the
# GPL.
#
CORE_DEPTH = ../../..
LIBRARY_NAME = cmdutil
# MODULE public and private header directories are implicitly REQUIRED.
MODULE = seccmd
DEFINES = -DNSPR20
EXPORTS = cmdutil.h \
$(NULL)
CSRCS = cmdline.c \
$(NULL)
REQUIRES = security nspr dbm