470 lines
7 KiB
C
470 lines
7 KiB
C
/******************************************************************************
|
|
* Copyright (c) 2004, 2008 IBM Corporation
|
|
* All rights reserved.
|
|
* This program and the accompanying materials
|
|
* are made available under the terms of the BSD License
|
|
* which accompanies this distribution, and is available at
|
|
* http://www.opensource.org/licenses/bsd-license.php
|
|
*
|
|
* Contributors:
|
|
* IBM Corporation - initial implementation
|
|
*****************************************************************************/
|
|
|
|
/*
|
|
* includes
|
|
*******************************************************************************
|
|
*/
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <getopt.h>
|
|
|
|
/*
|
|
* global variables, types & constants
|
|
* may be removed if already defined
|
|
*******************************************************************************
|
|
*/
|
|
int opterr = 1;
|
|
int optopt = 0;
|
|
int optind = 1;
|
|
char *optarg = NULL;
|
|
|
|
/*
|
|
* internal values needed by getopt
|
|
* DO NOT CHANGE or REMOVE
|
|
*/
|
|
enum {
|
|
OPTIONAL_ARG = 0,
|
|
MANDATORY_ARG = 1,
|
|
NO_ARG = 2
|
|
};
|
|
|
|
/*
|
|
* variables needed by getopt & getopt_long!
|
|
* DO NOT REMOVE
|
|
*/
|
|
static char *optstart = NULL;
|
|
|
|
int
|
|
getopt(int argc, char **argv, const char *options)
|
|
{
|
|
char *optptr;
|
|
char *argptr;
|
|
int optman;
|
|
int idx;
|
|
int ret = 0;
|
|
int argpresent;
|
|
|
|
/*
|
|
* reset used global values
|
|
*/
|
|
optopt = 0;
|
|
optarg = NULL;
|
|
|
|
/*
|
|
* reset getopt if a new argv pointer is passed
|
|
*/
|
|
if (optstart != argv[0]) {
|
|
optopt = 0;
|
|
optind = 1;
|
|
optarg = NULL;
|
|
optstart = argv[0];
|
|
}
|
|
|
|
/*
|
|
* return if no more arguments are available
|
|
*/
|
|
if (optind >= argc) {
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* start parsing argv[optind]
|
|
*/
|
|
idx = 0;
|
|
|
|
/*
|
|
* return if the option does not begin with a '-' or has more than 2 characters
|
|
*/
|
|
if (argv[optind][idx] != '-') {
|
|
|
|
if (opterr != 0) {
|
|
printf("unknown option \'%s\', expecting \'-\'\n",
|
|
argv[optind]);
|
|
}
|
|
|
|
optopt = (int) argv[optind][idx];
|
|
optind++;
|
|
|
|
return '?';
|
|
}
|
|
|
|
/*
|
|
* continue to the next character in argv[optind]
|
|
*/
|
|
idx++;
|
|
|
|
/*
|
|
* identify the option
|
|
* make sure if an option contains a ':' to invalidate the option
|
|
*/
|
|
optptr = strchr(argv[optind], ':');
|
|
|
|
if (optptr == NULL) {
|
|
optptr = strchr(options, (int) argv[optind][idx]);
|
|
} else {
|
|
optptr = NULL;
|
|
}
|
|
|
|
/*
|
|
* check whether the option is present
|
|
*/
|
|
if (optptr == NULL) {
|
|
/*
|
|
* unknown option detected
|
|
*/
|
|
if (opterr != 0) {
|
|
printf("unknown option \'%s\'\n", argv[optind]);
|
|
}
|
|
|
|
optopt = (int) argv[optind][idx];
|
|
optind++;
|
|
|
|
return '?';
|
|
}
|
|
|
|
/*
|
|
* the option is present in the option string
|
|
* setup return value
|
|
*/
|
|
ret = (int) *optptr;
|
|
|
|
/*
|
|
* get option argument if needed
|
|
*/
|
|
optptr++;
|
|
|
|
/*
|
|
* determine between mandatory and optional argument
|
|
*/
|
|
optman = NO_ARG;
|
|
|
|
if (*optptr == ':') {
|
|
optman--; // now set to MANDATORY_ARG
|
|
}
|
|
|
|
if (optman == MANDATORY_ARG) {
|
|
optptr++;
|
|
|
|
if (*optptr == ':') {
|
|
optman--; // now set to OPTIONAL_ARG
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* if strlen( argv[optind ) is greater than 2,
|
|
* the argument is in the same argv
|
|
*/
|
|
if (strlen(argv[optind]) > 2) {
|
|
argptr = &argv[optind][2];
|
|
|
|
/*
|
|
* do not allow '-' in an argument
|
|
*/
|
|
if (strchr(argptr, '-') != NULL) {
|
|
|
|
if (opterr != 0) {
|
|
printf
|
|
("illegal argument value \'%s\' for option \'-%c\'\n",
|
|
argptr, ret);
|
|
}
|
|
|
|
optopt = ret;
|
|
|
|
return '?';
|
|
}
|
|
|
|
} else {
|
|
/*
|
|
* move on to the next argv
|
|
* it now either contains an argument or the next option
|
|
*/
|
|
optind++;
|
|
|
|
/*
|
|
* make sure not to overflow
|
|
*/
|
|
if (optind < argc) {
|
|
argptr = argv[optind];
|
|
} else {
|
|
argptr = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* do the needed actions for the argument state
|
|
*/
|
|
switch (optman) {
|
|
case OPTIONAL_ARG:
|
|
|
|
if (argptr == NULL) {
|
|
break;
|
|
}
|
|
|
|
if (*argptr != '-') {
|
|
/*
|
|
* argument present
|
|
*/
|
|
optarg = argptr;
|
|
optind++;
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
case MANDATORY_ARG:
|
|
argpresent = (argptr != NULL);
|
|
|
|
if (argpresent) {
|
|
argpresent = (*argptr != '-');
|
|
}
|
|
|
|
if (argpresent) {
|
|
/*
|
|
* argument present
|
|
*/
|
|
optarg = argptr;
|
|
optind++;
|
|
} else {
|
|
/*
|
|
* mandatory argument missing
|
|
*/
|
|
if (opterr != 0) {
|
|
printf
|
|
("missing argument for option \'-%c\'\n",
|
|
ret);
|
|
}
|
|
|
|
optopt = ret;
|
|
|
|
/*
|
|
* if the first character of options is a ':'
|
|
* return a ':' instead of a '?' in case of
|
|
* a missing argument
|
|
*/
|
|
if (*options == ':') {
|
|
ret = ':';
|
|
} else {
|
|
ret = '?';
|
|
}
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
case NO_ARG:
|
|
|
|
if (strlen(argv[optind - 1]) > 2) {
|
|
|
|
if (opterr != 0) {
|
|
printf
|
|
("too many arguments for option \'-%c\'\n",
|
|
ret);
|
|
}
|
|
|
|
optopt = ret;
|
|
ret = '?';
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int
|
|
getopt_long(int argc, char **argv, const char *shortopts,
|
|
const struct option *longopts, int *indexptr)
|
|
{
|
|
struct option *optptr = (struct option *) longopts;
|
|
int optidx = 0;
|
|
int idx;
|
|
int ret = 0;
|
|
int argpresent;
|
|
|
|
/*
|
|
* reset used global values
|
|
*/
|
|
optopt = 0;
|
|
optarg = NULL;
|
|
|
|
/*
|
|
* reset indexptr
|
|
*/
|
|
*indexptr = -1;
|
|
|
|
/*
|
|
* reset getopt if a new argv pointer is passed
|
|
*/
|
|
if (optstart != argv[0]) {
|
|
optopt = 0;
|
|
optind = 1;
|
|
optarg = NULL;
|
|
optstart = argv[0];
|
|
}
|
|
|
|
/*
|
|
* return if no more arguments are available
|
|
*/
|
|
if (optind >= argc) {
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* start parsing argv[optind]
|
|
*/
|
|
idx = 0;
|
|
|
|
/*
|
|
* return if the option does not begin with a '-'
|
|
*/
|
|
if (argv[optind][idx] != '-') {
|
|
printf("unknown option \'%s\', expecting \'-\'\n",
|
|
argv[optind]);
|
|
|
|
optind++;
|
|
|
|
return '?';
|
|
}
|
|
|
|
/*
|
|
* move on to the next character in argv[optind]
|
|
*/
|
|
idx++;
|
|
|
|
/*
|
|
* return getopt() in case of a short option
|
|
*/
|
|
if (argv[optind][idx] != '-') {
|
|
return getopt(argc, argv, shortopts);
|
|
}
|
|
|
|
/*
|
|
* handle a long option
|
|
*/
|
|
idx++;
|
|
|
|
while (optptr->name != NULL) {
|
|
|
|
if (strcmp(&argv[optind][idx], optptr->name) == 0) {
|
|
break;
|
|
}
|
|
|
|
optptr++;
|
|
optidx++;
|
|
}
|
|
|
|
/*
|
|
* no matching option found
|
|
*/
|
|
if (optptr->name == NULL) {
|
|
printf("unknown option \'%s\'\n", argv[optind]);
|
|
|
|
optind++;
|
|
|
|
return '?';
|
|
}
|
|
|
|
/*
|
|
* option was found, set up index pointer
|
|
*/
|
|
*indexptr = optidx;
|
|
|
|
/*
|
|
* get argument
|
|
*/
|
|
optind++;
|
|
|
|
switch (optptr->has_arg) {
|
|
case no_argument:
|
|
/*
|
|
* nothing to do
|
|
*/
|
|
|
|
break;
|
|
|
|
case required_argument:
|
|
argpresent = (optind != argc);
|
|
|
|
if (argpresent) {
|
|
argpresent = (argv[optind][0] != '-');
|
|
}
|
|
|
|
if (argpresent) {
|
|
/*
|
|
* argument present
|
|
*/
|
|
optarg = argv[optind];
|
|
optind++;
|
|
} else {
|
|
/*
|
|
* mandatory argument missing
|
|
*/
|
|
printf("missing argument for option \'%s\'\n",
|
|
argv[optind - 1]);
|
|
|
|
ret = '?';
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
case optional_argument:
|
|
|
|
if (optind == argc) {
|
|
break;
|
|
}
|
|
|
|
if (argv[optind][0] != '-') {
|
|
/*
|
|
* argument present
|
|
*/
|
|
optarg = argv[optind];
|
|
optind++;
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
default:
|
|
printf("unknown argument option for option \'%s\'\n",
|
|
argv[optind - 1]);
|
|
|
|
ret = '?';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*
|
|
* setup return values
|
|
*/
|
|
if (ret != '?') {
|
|
|
|
if (optptr->flag == NULL) {
|
|
ret = optptr->val;
|
|
} else {
|
|
*optptr->flag = optptr->val;
|
|
ret = 0;
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
}
|