/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <libintl.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
#include <getopt.h>
#include <cmdparse.h>
/* Usage types */
/* printable ascii character set len */
/*
* MAXOPTIONSTRING is the max length of the options string used in getopt and
* will be the printable character set + ':' for each character,
* providing for options with arguments. e.g. "t:Cs:hglr:"
*/
/* standard command options table to support -?, -V */
};
/* standard subcommand options table to support -? */
};
/* forward declarations */
static int getSubcommandProps(char *, subCommandProps_t **);
static char *getExecBasename(char *);
static char *getLongOption(int);
static char *getOptionArgDesc(int);
/* global data */
static char *commandName;
/*
* input:
* subCommand - subcommand value
* output:
* subCommandProps - pointer to subCommandProps_t structure allocated by caller
*
* On successful return, subCommandProps contains the properties for the value
* in subCommand. On failure, the contents of subCommandProps is unspecified.
*
* Returns:
* zero on success
* non-zero on failure
*
*/
static int
{
int len;
*subCommandProps = sp;
return (0);
}
}
return (1);
}
/*
* input:
* shortOption - short option character for which to return the
* associated long option string
*
* Returns:
* on success, long option name
* on failure, NULL
*/
static char *
{
}
}
return (NULL);
}
/*
* input
* shortOption - short option character for which to return the
* option argument
* Returns:
* on success, argument string
* on failure, NULL
*/
static char *
{
}
}
return (NULL);
}
/*
* Print usage for a subcommand.
*
* input:
* usage type - GENERAL_USAGE, DETAIL_USAGE
* subcommand - pointer to subCommandProps_t structure
*
* Returns:
* none
*
*/
static void
{
int i;
char *optionArgDesc;
char *longOpt;
if (usageType == GENERAL_USAGE) {
subcommand->name);
for (i = 0; standardSubCmdOptions[i].name; i++) {
(void) printf(",");
}
return;
}
/* print subcommand usage */
subcommand->name);
/* print options if applicable */
if (subcommand->required) {
} else {
}
if (subcommand->required) {
} else {
}
}
/* print operand requirements */
}
}
}
}
}
}
/* print options for subcommand */
(void) printf("\n\t\t-%c, --%s ",
subcommand->optionString[i],
longOpt);
if (optionArgDesc != NULL) {
}
if (subcommand->exclusive &&
subcommand->optionString[i])) {
}
}
}
if (subcommand->helpText) {
}
}
/*
* input:
* type of usage statement to print
*
* Returns:
* return value of subUsage
*/
static void
{
int i;
/* print general command usage */
for (i = 0; standardCmdOptions[i].name; i++) {
(void) printf(",");
}
if (usageType == GENERAL_USAGE) {
for (i = 0; standardSubCmdOptions[i].name; i++) {
(void) printf(",");
}
}
/* print all subcommand usage */
}
}
/*
* input:
* execFullName - exec name of program (argv[0])
*
* Returns:
* command name portion of execFullName
*/
static char *
{
/* guard against '/' at end of command invocation */
for (;;) {
break;
} else {
if (*execBasename == '\0') {
*lastSlash = '\0';
continue;
}
break;
}
}
return (execBasename);
}
/*
* cmdParse is a parser that checks syntax of the input command against
* various rules tables.
*
* It provides usage feedback based upon the passed rules tables by calling
* two usage functions, usage, subUsage
*
* When syntax is successfully validated, the associated function is called
* using the subcommands table functions.
*
* Syntax is as follows:
* command subcommand [<options>] [<operand>]
*
* There are two standard short and long options assumed:
* -?, --help Provides usage on a command or subcommand
* and stops further processing of the arguments
*
* -V, --version Provides version information on the command
* and stops further processing of the arguments
*
* These options are loaded by this function.
*
* input:
* argc, argv from main
* syntax rules tables (synTables_t structure)
* callArgs - void * passed by caller to be passed to subcommand function
*
* output:
* funcRet - pointer to int that holds subcommand function return value
*
* Returns:
*
* zero on successful syntax parse and function call
*
* 1 on unsuccessful syntax parse (no function has been called)
* This could be due to a version or help call or simply a
* general usage call.
*
* -1 check errno, call failed
*
* This module is not MT-safe.
*
*/
int
int *funcRet)
{
int getoptargc;
char **getoptargv;
int opt;
int operInd;
int i, j;
int len;
char *availOptions;
char *versionString;
/*
* Check for NULLs on mandatory input arguments
*
* Note: longOptionTbl can be NULL in the case
* where there is no caller defined options
*
*/
/* set global command name */
/* Set unbuffered output */
/* load globals */
/* There must be at least two arguments */
if (argc < 2) {
return (1);
}
/*
* load standard subcommand options to internal long options table
* Two separate getopt_long(3C) tables are used.
*/
for (i = 0; standardSubCmdOptions[i].name; i++) {
}
/*
* copy caller's long options into internal long options table
* We do this for two reasons:
* 1) We need to use the getopt_long option structure internally
* 2) We need to prepend the table with the standard option
* for all subcommands (currently -?)
*/
if (i > MAXOPTIONS - 1) {
/* option table too long */
assert(0);
}
}
/* set option table global */
_longOptions = &intLongOpt[0];
/*
* '+' in option string ensures POSIX compliance in getopt_long()
* which means that processing will stop at first non-option
* argument.
*/
switch (opt) {
case '?':
/*
* getopt can return a '?' when no
* option letters match string. Check for
* the 'real' '?' in optopt.
*/
if (optopt == '?') {
exit(0);
} else {
return (1);
}
break;
case 'V':
exit(0);
break;
default:
break;
}
}
/*
* subcommand is always in the second argument. If there is no
* recognized subcommand in the second argument, print error,
* general usage and then return.
*/
gettext("invalid subcommand"));
return (1);
}
getoptargv = argv;
getoptargv++;
getoptargc = argc;
getoptargc -= 1;
j = 0;
/*
* Build optionStringAll from long options table
*/
/* sanity check on string length */
if (j + 1 >= sizeof (optionStringAll)) {
/* option table too long */
assert(0);
}
optionStringAll[++j] = ':';
}
}
i = 0;
/*
* Run getopt for all arguments against all possible options
* later.
*
* Once all options are retrieved, a validity check against
* subcommand table is performed.
*/
switch (opt) {
case '?':
/*
* getopt can return a '?' when no
* option letters match string. Check for
* the 'real' '?' in optopt.
*/
if (optopt == '?') {
exit(0);
} else {
exit(1);
}
default:
if (optarg) {
- 1) {
(void) printf("%s: %s\n",
gettext("option too long"));
return (-1);
}
}
i++;
break;
}
}
/*
* increment past last option
*/
/*
* Check validity of given options, if any were given
*/
/* get option string for this subcommand */
/* Get count of required options */
if (subcommand->required) {
}
gettext("no options permitted"));
return (1);
}
for (i = 0; cmdOptions[i].optval; i++) {
/* is the option in the available option string? */
cmdOptions[i].optval,
gettext("invalid option"));
return (1);
/* increment required options entered */
} else if (subcommand->required &&
cmdOptions[i].optval))) {
/* Check for exclusive options */
subcommand->exclusive &&
cmdOptions[i].optval)) {
(void) printf("%s: '-%c': %s\n",
gettext("is an exclusive option"));
return (1);
}
}
} else { /* no options were input */
gettext("at least one option required"));
return (1);
}
}
/* Were all required options entered? */
if (requiredOptionEntered != requiredOptionCnt) {
gettext("Following option(s) required"),
return (1);
}
/*
* If there are no operands,
* check to see if this is okay
*/
gettext("requires an operand"));
return (1);
}
/*
* If there are more operands,
* check to see if this is okay
*/
return (1);
}
/*
* If there is more than one more operand,
* check to see if this is okay
*/
return (1);
}
/* Finished syntax checks */
/* Call appropriate function */
&cmdOptions[0], callArgs);
return (0);
}