From 72025a6a38e3aed4dadab5013dc64e0a432ba992 Mon Sep 17 00:00:00 2001 From: axel Date: Tue, 3 Feb 2009 08:46:45 +1000 Subject: [PATCH] Make fish avoid iterating through user list when completing file part of directory starting with tilde. Also add a timeout to the directory iteration, to protect against humongously large user databases. darcs-hash:20090202224645-ac50b-353047a73e4d6f494f470fe2ea6c4a34b486d302.gz --- common.c | 15 ++++ common.h | 10 +++ complete.c | 229 +++++++++++++++++++++++------------------------------ fallback.h | 4 + 4 files changed, 127 insertions(+), 131 deletions(-) diff --git a/common.c b/common.c index ed7b92a..4a21dbb 100644 --- a/common.c +++ b/common.c @@ -1805,3 +1805,18 @@ void sb_format_size( string_buffer_t *sb, } } } + +double timef() +{ + int time_res; + struct timeval tv; + + time_res = gettimeofday(&tv, 0); + + if( time_res ) + { + return NAN; + } + + return (double)tv.tv_sec + 0.000001*tv.tv_usec; +} diff --git a/common.h b/common.h index dd66492..7831c7e 100644 --- a/common.h +++ b/common.h @@ -447,5 +447,15 @@ void bugreport(); void sb_format_size( string_buffer_t *sb, long long sz ); +/** + Return the number of seconds from the UNIX epoch, with subsecond + precision. This function uses the gettimeofday function, and will + have the same precision as that function. + + If an error occurs, NAN is returned. + */ +double timef(); + + #endif diff --git a/complete.c b/complete.c index 466db2e..9193be1 100644 --- a/complete.c +++ b/complete.c @@ -1,6 +1,6 @@ /** \file complete.c Functions related to tab-completion. -These functions are used for storing and retrieving tab-completion data, as well as for performing tab-completion. + These functions are used for storing and retrieving tab-completion data, as well as for performing tab-completion. */ #include "config.h" @@ -107,6 +107,14 @@ These functions are used for storing and retrieving tab-completion data, as well #endif +/** + The maximum amount of time that we're willing to spend doing + username tilde completion. This special limit has been coded in + because user lookup can be extremely slow in cases of a humongous + LDAP database. (Google, I'm looking at you) + */ +#define MAX_USER_LOOKUP_TIME 0.2 + /** Struct describing a completion option entry. @@ -180,9 +188,9 @@ static void complete_free_entry( complete_entry_t *c ); */ void completion_allocate( array_list_t *context, - const wchar_t *comp, - const wchar_t *desc, - int flags ) + const wchar_t *comp, + const wchar_t *desc, + int flags ) { completion_t *res = halloc( context, sizeof( completion_t) ); res->completion = halloc_wcsdup( context, comp ); @@ -378,8 +386,8 @@ static complete_entry_t *complete_get_exact_entry( const wchar_t *cmd, void complete_set_authoritative( const wchar_t *cmd, - int cmd_type, - int authoritative ) + int cmd_type, + int authoritative ) { complete_entry_t *c; @@ -473,9 +481,9 @@ static complete_entry_t *complete_remove_entry( complete_entry_t *e, { wchar_t *pos; /* fwprintf( stderr, - L"remove option -%lc --%ls\n", - o->short_opt?o->short_opt:L' ', - o->long_opt ); + L"remove option -%lc --%ls\n", + o->short_opt?o->short_opt:L' ', + o->long_opt ); */ if( o->short_opt ) { @@ -1067,10 +1075,10 @@ static const wchar_t *complete_function_desc( const wchar_t *fn ) \param comp the list to add all completions to */ static void complete_cmd( const wchar_t *cmd, - array_list_t *comp, - int use_function, - int use_builtin, - int use_command ) + array_list_t *comp, + int use_function, + int use_builtin, + int use_command ) { wchar_t *path; wchar_t *path_cpy; @@ -1124,18 +1132,18 @@ static void complete_cmd( const wchar_t *cmd, add_slash = nxt_path[path_len-1]!=L'/'; nxt_completion = wcsdupcat( nxt_path, - add_slash?L"/":L"", - cmd ); + add_slash?L"/":L"", + cmd ); if( ! nxt_completion ) continue; prev_count = al_get_count( comp ); if( expand_string( 0, - nxt_completion, - comp, - ACCEPT_INCOMPLETE | - EXECUTABLES_ONLY ) != EXPAND_ERROR ) + nxt_completion, + comp, + ACCEPT_INCOMPLETE | + EXECUTABLES_ONLY ) != EXPAND_ERROR ) { for( i=prev_count; i 0.2 ) + { + return 1; + } + + pw_name = str2wcs( pw->pw_name ); - while((pw=getpwent()) != 0) + if( pw_name ) { - wchar_t *pw_name = str2wcs( pw->pw_name ); - if( pw_name ) + if( wcsncmp( user_name, pw_name, name_len )==0 ) { - if( wcsncmp( user_name, pw_name, name_len )==0 ) - { - string_buffer_t desc; - - sb_init( &desc ); - sb_printf( &desc, - COMPLETE_USER_DESC, - pw_name ); - - completion_allocate( comp, - &pw_name[name_len], - (wchar_t *)desc.buff, - COMPLETE_NO_SPACE ); - - res=1; - - sb_destroy( &desc ); - } - else if( wcsncasecmp( user_name, pw_name, name_len )==0 ) - { - string_buffer_t name; - string_buffer_t desc; - - sb_init( &name ); - sb_init( &desc ); - sb_printf( &name, - L"~%ls", - pw_name ); - sb_printf( &desc, - COMPLETE_USER_DESC, - pw_name ); + string_buffer_t desc; + + sb_init( &desc ); + sb_printf( &desc, + COMPLETE_USER_DESC, + pw_name ); + + completion_allocate( comp, + &pw_name[name_len], + (wchar_t *)desc.buff, + COMPLETE_NO_SPACE ); + + res=1; + + sb_destroy( &desc ); + } + else if( wcsncasecmp( user_name, pw_name, name_len )==0 ) + { + string_buffer_t name; + string_buffer_t desc; + + sb_init( &name ); + sb_init( &desc ); + sb_printf( &name, + L"~%ls", + pw_name ); + sb_printf( &desc, + COMPLETE_USER_DESC, + pw_name ); - completion_allocate( comp, - (wchar_t *)name.buff, - (wchar_t *)desc.buff, - COMPLETE_NO_CASE | COMPLETE_DONT_ESCAPE | COMPLETE_NO_SPACE ); - res=1; + completion_allocate( comp, + (wchar_t *)name.buff, + (wchar_t *)desc.buff, + COMPLETE_NO_CASE | COMPLETE_DONT_ESCAPE | COMPLETE_NO_SPACE ); + res=1; - sb_destroy( &desc ); - sb_destroy( &name ); + sb_destroy( &desc ); + sb_destroy( &name ); - } - free( pw_name ); } + free( pw_name ); } - endpwent(); } + endpwent(); } } - return res;} + return res; +} diff --git a/fallback.h b/fallback.h index 77154ae..68bbcff 100644 --- a/fallback.h +++ b/fallback.h @@ -469,4 +469,8 @@ long sysconf(int name); #endif +#ifndef NAN +#define NAN (0.0/0.0) +#endif + #endif