Fix getopt_long(3) not handling invalid options and long options properly.

This commit is contained in:
Jonas 'Sortie' Termansen 2014-04-23 19:39:51 +02:00
parent bcf72f71e4
commit 8591bcef7b
1 changed files with 12 additions and 4 deletions

View File

@ -73,7 +73,7 @@ const struct option* find_long_option(char* arg,
char** option_arg) char** option_arg)
{ {
char* argname = arg + 2; char* argname = arg + 2;
size_t argname_length = strcspn(arg, "="); size_t argname_length = strcspn(argname, "=");
for ( int i = 0; longopts && longopts[i].name; i++ ) for ( int i = 0; longopts && longopts[i].name; i++ )
{ {
@ -147,7 +147,14 @@ int getopt_long(int argc, char* const* argv, const char* shortopts,
// Verify the long option is allowed. // Verify the long option is allowed.
if ( !option ) if ( !option )
{
if ( !caller_handles_missing_argument && opterr )
error(0, 0, "unrecognized option `%s'", arg);
return '?'; return '?';
}
if ( longindex )
*longindex = option_index;
// Check whether the next argument is the parameter to this option. // Check whether the next argument is the parameter to this option.
if ( !option_arg && option->has_arg != no_argument ) if ( !option_arg && option->has_arg != no_argument )
@ -161,14 +168,13 @@ int getopt_long(int argc, char* const* argv, const char* shortopts,
if ( !option_arg && option->has_arg == required_argument ) if ( !option_arg && option->has_arg == required_argument )
{ {
if ( caller_handles_missing_argument ) if ( caller_handles_missing_argument )
return *longindex = option_index, ':'; return ':';
if ( opterr ) if ( opterr )
error(0, 0, "option requires an argument `--%s'", option->name); error(0, 0, "option requires an argument `--%s'", option->name);
return '?'; return '?';
} }
return optarg = option_arg, return optarg = option_arg,
*longindex = option_index,
option->flag ? (*option->flag = option->val, 0) : option->val; option->flag ? (*option->flag = option->val, 0) : option->val;
} }
@ -198,12 +204,14 @@ int getopt_long(int argc, char* const* argv, const char* shortopts,
char* opt_decl = strchr(shortopts, short_option); char* opt_decl = strchr(shortopts, short_option);
if ( !opt_decl ) if ( !opt_decl )
{ {
if ( !caller_handles_missing_argument && opterr )
error(0, 0, "invalid option -- '%c'", short_option);
optopt = short_option; optopt = short_option;
short_option = '?'; short_option = '?';
} }
// Check whether the short option requires an parameter. // Check whether the short option requires an parameter.
if ( opt_decl[1] == ':' ) if ( opt_decl && opt_decl[1] == ':' )
{ {
// This argument cannot contain more short options after this. // This argument cannot contain more short options after this.
optcurvalid = false; optcurvalid = false;