mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 04:43:10 +00:00
Add some input validation code to various functions
darcs-hash:20060222154152-ac50b-608032284165f099beecd1cd4f7c6bb2b45df432.gz
This commit is contained in:
parent
3afead1827
commit
ca04fc745d
11 changed files with 225 additions and 84 deletions
12
common.c
12
common.c
|
@ -212,8 +212,13 @@ wchar_t *str2wcs( const char *in )
|
|||
size_t len = strlen(in);
|
||||
|
||||
out = malloc( sizeof(wchar_t)*(len+1) );
|
||||
|
||||
if( !out )
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
|
||||
return str2wcs_internal( in, out );
|
||||
|
||||
}
|
||||
|
||||
wchar_t *str2wcs_internal( const char *in, wchar_t *out )
|
||||
|
@ -226,11 +231,6 @@ wchar_t *str2wcs_internal( const char *in, wchar_t *out )
|
|||
|
||||
memset( &state, 0, sizeof(state) );
|
||||
|
||||
if( !out )
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
|
||||
while( in[in_pos] )
|
||||
{
|
||||
res = mbrtowc( &out[out_pos], &in[in_pos], len-in_pos, &state );
|
||||
|
|
85
complete.c
85
complete.c
|
@ -481,8 +481,10 @@ void complete_remove( const wchar_t *cmd,
|
|||
{
|
||||
wchar_t *pos2 = pos+1;
|
||||
while( *pos2 == L':' )
|
||||
{
|
||||
pos2++;
|
||||
|
||||
}
|
||||
|
||||
memmove( pos,
|
||||
pos2,
|
||||
sizeof(wchar_t)*wcslen(pos2) );
|
||||
|
@ -500,7 +502,9 @@ void complete_remove( const wchar_t *cmd,
|
|||
free( o );
|
||||
}
|
||||
else
|
||||
{
|
||||
oprev = o;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -523,7 +527,9 @@ void complete_remove( const wchar_t *cmd,
|
|||
}
|
||||
|
||||
if( e )
|
||||
{
|
||||
eprev = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -541,8 +547,14 @@ static void parse_cmd_string( const wchar_t *str,
|
|||
/* Get the path of the command */
|
||||
path = get_filename( str );
|
||||
if( path == 0 )
|
||||
{
|
||||
/**
|
||||
Use the empty string as the 'path' for commands that can
|
||||
not be found.
|
||||
*/
|
||||
path = wcsdup(L"");
|
||||
|
||||
}
|
||||
|
||||
/* Make sure the path is not included in the command */
|
||||
cmd = wcsrchr( str, L'/' );
|
||||
if( cmd != 0 )
|
||||
|
@ -611,11 +623,11 @@ int complete_is_valid_option( const wchar_t *str,
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if( !(short_validated = malloc( wcslen( opt ) )))
|
||||
{
|
||||
die_mem();
|
||||
|
||||
}
|
||||
|
||||
memset( short_validated, 0, wcslen( opt ) );
|
||||
|
||||
hash_init( &gnu_match_hash,
|
||||
|
@ -649,8 +661,10 @@ int complete_is_valid_option( const wchar_t *str,
|
|||
const wchar_t *a;
|
||||
|
||||
if( !wildcard_match( match, i->cmd ) )
|
||||
{
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
found_match = 1;
|
||||
|
||||
if( !i->authorative )
|
||||
|
@ -666,15 +680,19 @@ int complete_is_valid_option( const wchar_t *str,
|
|||
for( o = i->first_option; o; o=o->next )
|
||||
{
|
||||
if( o->old_mode )
|
||||
{
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
if( wcsncmp( &opt[2], o->long_opt, gnu_opt_len )==0)
|
||||
{
|
||||
hash_put( &gnu_match_hash, o->long_opt, L"" );
|
||||
if( (wcsncmp( &opt[2],
|
||||
o->long_opt,
|
||||
wcslen( o->long_opt) )==0) )
|
||||
{
|
||||
is_gnu_exact=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -926,24 +944,30 @@ const wchar_t *complete_get_desc( const wchar_t *filename )
|
|||
switch( errno )
|
||||
{
|
||||
case ENOENT:
|
||||
{
|
||||
sb_printf( get_desc_buff, L"%lc%ls", COMPLETE_SEP, COMPLETE_ROTTEN_SYMLINK_DESC );
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case EACCES:
|
||||
{
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
if( errno == ELOOP )
|
||||
{
|
||||
sb_printf( get_desc_buff, L"%lc%ls", COMPLETE_SEP, COMPLETE_LOOP_SYMLINK_DESC );
|
||||
}
|
||||
|
||||
/*
|
||||
Some kind of broken symlink. We ignore it
|
||||
here, and it will get a 'file' description,
|
||||
or one based on suffix.
|
||||
Some kind of unknown broken symlink. We
|
||||
ignore it here, and it will get a 'file'
|
||||
description, or one based on suffix.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1013,19 +1037,14 @@ static void copy_strings_with_prefix( array_list_t *comp_out,
|
|||
if(!tmp)
|
||||
return;
|
||||
|
||||
if( tmp[0] == L'~' )
|
||||
{
|
||||
tmp=expand_tilde(wc);
|
||||
}
|
||||
|
||||
wc = parse_util_unescape_wildcards( tmp );
|
||||
free(tmp);
|
||||
|
||||
for( i=0; i<al_get_count( possible_comp ); i++ )
|
||||
{
|
||||
wchar_t *next_str = (wchar_t *)al_get( possible_comp, i );
|
||||
|
||||
wildcard_complete( next_str, wc, desc, desc_func, comp_out );
|
||||
if( next_str )
|
||||
wildcard_complete( next_str, wc, desc, desc_func, comp_out );
|
||||
}
|
||||
|
||||
free( wc );
|
||||
|
@ -1358,10 +1377,26 @@ static void complete_from_args( const wchar_t *str,
|
|||
for( i=0; i< al_get_count( &possible_comp ); i++ )
|
||||
{
|
||||
wchar_t *next = (wchar_t *)al_get( &possible_comp, i );
|
||||
al_set( &possible_comp , i, unescape( next, 0 ) );
|
||||
free( next );
|
||||
wchar_t *next_unescaped;
|
||||
if( next )
|
||||
{
|
||||
next_unescaped = unescape( next, 0 );
|
||||
if( next_unescaped )
|
||||
{
|
||||
al_set( &possible_comp , i, next_unescaped );
|
||||
}
|
||||
else
|
||||
{
|
||||
debug( 2, L"Could not expand string %ls on line %d of file %s", next, __LINE__, __FILE__ );
|
||||
}
|
||||
free( next );
|
||||
}
|
||||
else
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
copy_strings_with_prefix( comp_out, str, desc, 0, &possible_comp );
|
||||
|
||||
al_foreach( &possible_comp, (void (*)(const void *))&free );
|
||||
|
@ -1674,11 +1709,11 @@ static void complete_param_expand( wchar_t *str,
|
|||
comp_str = str;
|
||||
}
|
||||
|
||||
debug( 2,
|
||||
debug( 3,
|
||||
L"expand_string( \"%ls\", comp_out, EXPAND_SKIP_SUBSHELL | ACCEPT_INCOMPLETE | %ls );",
|
||||
comp_str,
|
||||
do_file?L"0":L"EXPAND_SKIP_WILDCARDS" );
|
||||
|
||||
|
||||
expand_string( 0,
|
||||
wcsdup(comp_str),
|
||||
comp_out,
|
||||
|
@ -1753,10 +1788,8 @@ static int try_complete_variable( const wchar_t *cmd,
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -214,7 +214,7 @@ void env_universal_init( wchar_t * p,
|
|||
void (*sf)(),
|
||||
void (*cb)( int type, const wchar_t *name, const wchar_t *val ))
|
||||
{
|
||||
debug( 2, L"env_universal_init()" );
|
||||
debug( 3, L"env_universal_init()" );
|
||||
path=p;
|
||||
user=u;
|
||||
start_fishd=sf;
|
||||
|
@ -233,7 +233,7 @@ void env_universal_init( wchar_t * p,
|
|||
{
|
||||
env_universal_barrier();
|
||||
}
|
||||
debug( 2, L"end env_universal_init()" );
|
||||
debug( 3, L"end env_universal_init()" );
|
||||
}
|
||||
|
||||
void env_universal_destroy()
|
||||
|
|
|
@ -105,7 +105,7 @@ static int get_names_show_unexported;
|
|||
|
||||
void env_universal_common_init( void (*cb)(int type, const wchar_t *key, const wchar_t *val ) )
|
||||
{
|
||||
debug( 2, L"Init env_universal_common" );
|
||||
debug( 3, L"Init env_universal_common" );
|
||||
callback = cb;
|
||||
hash_init( &env_universal_var, &hash_wcs_func, &hash_wcs_cmp );
|
||||
}
|
||||
|
@ -229,7 +229,7 @@ static int match( const wchar_t *msg, const wchar_t *cmd )
|
|||
static void parse_message( wchar_t *msg,
|
||||
connection_t *src )
|
||||
{
|
||||
debug( 2, L"parse_message( %ls );", msg );
|
||||
debug( 3, L"parse_message( %ls );", msg );
|
||||
|
||||
if( msg[0] == L'#' )
|
||||
return;
|
||||
|
|
17
exec.c
17
exec.c
|
@ -1260,10 +1260,16 @@ int exec_subshell( const wchar_t *cmd,
|
|||
{
|
||||
wchar_t *el = str2wcs( begin );
|
||||
if( el )
|
||||
{
|
||||
al_push( l, el );
|
||||
}
|
||||
else
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
}
|
||||
}
|
||||
io_buffer_destroy( io_buffer );
|
||||
|
||||
|
||||
return status;
|
||||
|
||||
case '\n':
|
||||
|
@ -1271,7 +1277,14 @@ int exec_subshell( const wchar_t *cmd,
|
|||
wchar_t *el;
|
||||
*end=0;
|
||||
el = str2wcs( begin );
|
||||
al_push( l, el );
|
||||
if( el )
|
||||
{
|
||||
al_push( l, el );
|
||||
}
|
||||
else
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
}
|
||||
begin = end+1;
|
||||
break;
|
||||
}
|
||||
|
|
95
expand.c
95
expand.c
|
@ -1189,6 +1189,18 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
|
|||
int i, j;
|
||||
const wchar_t *item_begin;
|
||||
|
||||
if( !in )
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !out )
|
||||
{
|
||||
debug( 2, L"Got null pointer on line %d of file %s", __LINE__, __FILE__ );
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch( parse_util_locate_cmdsubst(in,
|
||||
¶n_begin,
|
||||
¶n_end,
|
||||
|
@ -1205,7 +1217,6 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
|
|||
case 1:
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
len1 = (paran_begin-in);
|
||||
|
@ -1254,10 +1265,10 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
|
|||
sb_append_substring( &whole_item, sub_item2, item_len );
|
||||
sb_append_char( &whole_item, INTERNAL_SEPARATOR );
|
||||
sb_append( &whole_item, tail_item );
|
||||
|
||||
al_push( out, whole_item.buff );
|
||||
|
||||
al_push( out, whole_item.buff );
|
||||
}
|
||||
|
||||
|
||||
free( sub_item2 );
|
||||
}
|
||||
free(in);
|
||||
|
@ -1438,23 +1449,18 @@ int expand_string( void *context,
|
|||
|
||||
if( EXPAND_SKIP_SUBSHELL & flags )
|
||||
{
|
||||
wchar_t *pos = str;
|
||||
|
||||
while( 1 )
|
||||
const wchar_t *begin, *end;
|
||||
|
||||
if( parse_util_locate_cmdsubst( str,
|
||||
&begin,
|
||||
&end,
|
||||
1 ) != 0 )
|
||||
{
|
||||
pos = wcschr( pos, L'(' );
|
||||
if( pos == 0 )
|
||||
break;
|
||||
|
||||
if( (pos == str) || ( *(pos-1) != L'\\' ) )
|
||||
{
|
||||
error( SUBSHELL_ERROR, -1, L"Subshells not allowed" );
|
||||
free( str );
|
||||
al_destroy( &list1 );
|
||||
al_destroy( &list2 );
|
||||
return EXPAND_ERROR;
|
||||
}
|
||||
pos++;
|
||||
error( SUBSHELL_ERROR, -1, L"Subshells not allowed" );
|
||||
free( str );
|
||||
al_destroy( &list1 );
|
||||
al_destroy( &list2 );
|
||||
return EXPAND_ERROR;
|
||||
}
|
||||
al_push( &list1, str );
|
||||
}
|
||||
|
@ -1483,7 +1489,10 @@ int expand_string( void *context,
|
|||
free( (void *)al_get( in, i ) );
|
||||
|
||||
if( !next )
|
||||
continue;
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( EXPAND_SKIP_VARIABLES & flags )
|
||||
{
|
||||
|
@ -1492,7 +1501,6 @@ int expand_string( void *context,
|
|||
if( *tmp == VARIABLE_EXPAND )
|
||||
*tmp = L'$';
|
||||
al_push( out, next );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1513,6 +1521,13 @@ int expand_string( void *context,
|
|||
for( i=0; i<al_get_count( in ); i++ )
|
||||
{
|
||||
wchar_t *next = (wchar_t *)al_get( in, i );
|
||||
|
||||
if( !next )
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !expand_brackets( next, flags, out ))
|
||||
{
|
||||
al_destroy( in );
|
||||
|
@ -1528,6 +1543,13 @@ int expand_string( void *context,
|
|||
for( i=0; i<al_get_count( in ); i++ )
|
||||
{
|
||||
wchar_t *next = (wchar_t *)al_get( in, i );
|
||||
|
||||
if( !next )
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !(next=expand_tilde_internal( next ) ) )
|
||||
{
|
||||
al_destroy( in );
|
||||
|
@ -1572,6 +1594,12 @@ int expand_string( void *context,
|
|||
wchar_t *next = (wchar_t *)al_get( in, i );
|
||||
int wc_res;
|
||||
|
||||
if( !next )
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
continue;
|
||||
}
|
||||
|
||||
remove_internal_separator( next, EXPAND_SKIP_WILDCARDS & flags );
|
||||
|
||||
if( ((flags & ACCEPT_INCOMPLETE) && (!(flags & EXPAND_SKIP_WILDCARDS))) ||
|
||||
|
@ -1590,27 +1618,46 @@ int expand_string( void *context,
|
|||
switch( wc_res )
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
if( !(flags & ACCEPT_INCOMPLETE) )
|
||||
{
|
||||
if( res == EXPAND_OK )
|
||||
res = EXPAND_WILDCARD_NO_MATCH;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
case 1:
|
||||
{
|
||||
int j;
|
||||
res = EXPAND_WILDCARD_MATCH;
|
||||
sort_list( out );
|
||||
al_push_all( end_out, out );
|
||||
|
||||
for( j=0; j<al_get_count( out ); j++ )
|
||||
{
|
||||
wchar_t *next = (wchar_t *)al_get( out, j );
|
||||
if( !next )
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
continue;
|
||||
}
|
||||
al_push( end_out, next );
|
||||
}
|
||||
al_truncate( out, 0 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( flags & ACCEPT_INCOMPLETE)
|
||||
{
|
||||
free( next );
|
||||
}
|
||||
else
|
||||
{
|
||||
al_push( end_out, next );
|
||||
}
|
||||
}
|
||||
}
|
||||
al_destroy( in );
|
||||
|
|
26
main.c
26
main.c
|
@ -122,6 +122,10 @@ int main( int argc, char **argv )
|
|||
"command", required_argument, 0, 'c'
|
||||
}
|
||||
,
|
||||
{
|
||||
"debug-level", required_argument, 0, 'd'
|
||||
}
|
||||
,
|
||||
{
|
||||
"interactive", no_argument, 0, 'i'
|
||||
}
|
||||
|
@ -152,14 +156,14 @@ int main( int argc, char **argv )
|
|||
|
||||
int opt = getopt_long( argc,
|
||||
argv,
|
||||
"hilvc:p:",
|
||||
"hilvc:p:d:",
|
||||
long_options,
|
||||
&opt_index );
|
||||
|
||||
#else
|
||||
int opt = getopt( argc,
|
||||
argv,
|
||||
"hilvc:p:" );
|
||||
"hilvc:p:d:" );
|
||||
#endif
|
||||
if( opt == -1 )
|
||||
break;
|
||||
|
@ -174,6 +178,22 @@ int main( int argc, char **argv )
|
|||
is_interactive_session = 0;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
{
|
||||
char *end;
|
||||
int tmp = strtol(optarg, &end, 10);
|
||||
if( tmp >= 0 && tmp <=10 && !*end )
|
||||
{
|
||||
debug_level=tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug( 0, _(L"Invalid value '%s' for debug level switch"), optarg );
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'h':
|
||||
cmd = "help";
|
||||
break;
|
||||
|
@ -233,7 +253,7 @@ int main( int argc, char **argv )
|
|||
wchar_t *cmd_wcs = str2wcs( cmd );
|
||||
res = eval( cmd_wcs, 0, TOP );
|
||||
free(cmd_wcs);
|
||||
reader_exit(0);
|
||||
reader_exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
12
parse_util.c
12
parse_util.c
|
@ -155,16 +155,12 @@ int parse_util_locate_cmdsubst( const wchar_t *in,
|
|||
return 0;
|
||||
}
|
||||
|
||||
*begin = paran_begin;
|
||||
*end = paran_count?in+wcslen(in):paran_end;
|
||||
if( begin )
|
||||
*begin = paran_begin;
|
||||
if( end )
|
||||
*end = paran_count?in+wcslen(in):paran_end;
|
||||
|
||||
/* assert( *begin >= in );
|
||||
assert( *begin < (in+wcslen(in) ) );
|
||||
assert( *end >= *begin );
|
||||
assert( *end < (in+wcslen(in) ) );
|
||||
*/
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
11
parser.c
11
parser.c
|
@ -708,7 +708,7 @@ wchar_t *get_filename( const wchar_t *cmd )
|
|||
{
|
||||
wchar_t *path;
|
||||
|
||||
debug( 2, L"get_filename( '%ls' )", cmd );
|
||||
debug( 3, L"get_filename( '%ls' )", cmd );
|
||||
|
||||
if(wcschr( cmd, L'/' ) != 0 )
|
||||
{
|
||||
|
@ -948,7 +948,14 @@ int eval_args( const wchar_t *line, array_list_t *args )
|
|||
{
|
||||
case TOK_STRING:
|
||||
{
|
||||
if( expand_string( 0, wcsdup(tok_last( &tok )), args, 0 ) == EXPAND_ERROR )
|
||||
wchar_t *tmp = wcsdup(tok_last( &tok ));
|
||||
|
||||
if( !tmp )
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
|
||||
if( expand_string( 0, tmp, args, 0 ) == EXPAND_ERROR )
|
||||
{
|
||||
err_pos=tok_get_pos( &tok );
|
||||
do_loop=0;
|
||||
|
|
6
reader.c
6
reader.c
|
@ -567,11 +567,12 @@ static void remove_duplicates( array_list_t *l )
|
|||
|
||||
prev = (wchar_t *)al_get( l, 0 );
|
||||
for( in=1, out=1; in < al_get_count( l ); in++ )
|
||||
{
|
||||
{
|
||||
wchar_t *curr = (wchar_t *)al_get( l, in );
|
||||
|
||||
if( fldcmp( prev, curr )==0 )
|
||||
{
|
||||
free( curr );
|
||||
free( curr );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2036,7 +2037,6 @@ void reader_set_buffer( wchar_t *b, int p )
|
|||
else
|
||||
{
|
||||
data->buff_pos=l;
|
||||
// fwprintf( stderr, L"Pos %d\n", l );
|
||||
}
|
||||
|
||||
reader_super_highlight_me_plenty( data->buff,
|
||||
|
|
37
wildcard.c
37
wildcard.c
|
@ -151,13 +151,32 @@ static int wildcard_complete_internal( const wchar_t *orig,
|
|||
const wchar_t *(*desc_func)(const wchar_t *),
|
||||
array_list_t *out )
|
||||
{
|
||||
if( !wc )
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !str )
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !orig )
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( *wc == 0 &&
|
||||
( ( *str != L'.') || (!is_first)) )
|
||||
{
|
||||
if( !out )
|
||||
return 1;
|
||||
|
||||
wchar_t *new;
|
||||
if( !out )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( wcschr( str, PROG_COMPLETE_SEP ) )
|
||||
{
|
||||
|
@ -165,7 +184,7 @@ static int wildcard_complete_internal( const wchar_t *orig,
|
|||
This completion has an embedded description, du not use the generic description
|
||||
*/
|
||||
wchar_t *sep;
|
||||
|
||||
|
||||
new = wcsdup( str );
|
||||
sep = wcschr(new, PROG_COMPLETE_SEP );
|
||||
*sep = COMPLETE_SEP;
|
||||
|
@ -661,15 +680,19 @@ int wildcard_expand( const wchar_t *wc,
|
|||
if( wc_end )
|
||||
{
|
||||
new_wc=wc_end+1;
|
||||
/*
|
||||
Accept multiple '/' as a single direcotry separator
|
||||
*/
|
||||
while(*new_wc==L'/')
|
||||
{
|
||||
new_wc++;
|
||||
}
|
||||
}
|
||||
|
||||
res |= wildcard_expand( new_wc,
|
||||
new_dir,
|
||||
flags,
|
||||
out );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -694,8 +717,10 @@ int wildcard_expand( const wchar_t *wc,
|
|||
closedir( dir );
|
||||
|
||||
if( flags & ACCEPT_INCOMPLETE )
|
||||
{
|
||||
sb_destroy( &sb_desc );
|
||||
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue