From 3b2670532ae9327de16082d1814589658b7c8519 Mon Sep 17 00:00:00 2001 From: axel Date: Wed, 15 Nov 2006 22:34:47 +1000 Subject: [PATCH] Make fish store universal variables locally if fishd can't be started - local changes are lost of the fishd connection is restored darcs-hash:20061115123447-ac50b-bf17c55079e1196205cc3a4fd0ca22d9f539836c.gz --- env_universal.c | 88 ++++++++++++++++++++++++++++++++---------- env_universal_common.c | 71 +++++++++++++++++++++++----------- env_universal_common.h | 42 +++++++++++++++++++- 3 files changed, 156 insertions(+), 45 deletions(-) diff --git a/env_universal.c b/env_universal.c index a069be9..13665f0 100644 --- a/env_universal.c +++ b/env_universal.c @@ -70,6 +70,11 @@ static int barrier_reply = 0; void env_universal_barrier(); +static int is_dead() +{ + return env_universal_server.fd < 0; +} + /** Get a socket for reading from the server @@ -140,7 +145,7 @@ static int get_socket( int fork_ok ) return get_socket( 0 ); } - debug( 2, L"Could not connect to socket %d, already tried manual restart (or no command supplied), giving up", s ); + debug( 1, L"Could not connect to universal variable server, already tried manual restart (or no command supplied). You will not be able to share variable values between fish sessions. Is fish properly installed?" ); return -1; } @@ -151,7 +156,7 @@ static int get_socket( int fork_ok ) return -1; } - + debug( 3, L"Connected to fd %d", s ); return s; @@ -198,6 +203,31 @@ static void check_connection() } } +/** + Remove all universal variables. +*/ +static void env_universal_remove_all() +{ + array_list_t lst; + int i; + + al_init( &lst ); + + env_universal_common_get_names( &lst, + 1, + 1 ); + + for( i=0; i= 0 ) { + env_universal_remove_all(); env_universal_barrier(); } } @@ -317,7 +348,7 @@ void env_universal_barrier() message_t *msg; fd_set fds; - if( !init || ( env_universal_server.fd == -1 )) + if( !init || is_dead() ) return; barrier_reply = 0; @@ -384,20 +415,27 @@ void env_universal_set( const wchar_t *name, const wchar_t *value, int export ) CHECK( name, ); debug( 3, L"env_universal_set( \"%ls\", \"%ls\" )", name, value ); - - msg = create_message( export?SET_EXPORT:SET, - name, - value); - if( !msg ) + if( is_dead() ) { - debug( 1, L"Could not create universal variable message" ); - return; + env_universal_common_set( name, value, export ); + } + else + { + msg = create_message( export?SET_EXPORT:SET, + name, + value); + + if( !msg ) + { + debug( 1, L"Could not create universal variable message" ); + return; + } + + msg->count=1; + q_put( &env_universal_server.unsent, msg ); + env_universal_barrier(); } - - msg->count=1; - q_put( &env_universal_server.unsent, msg ); - env_universal_barrier(); } int env_universal_remove( const wchar_t *name ) @@ -411,16 +449,22 @@ int env_universal_remove( const wchar_t *name ) CHECK( name, 1 ); res = !env_universal_common_get( name ); - debug( 3, L"env_universal_remove( \"%ls\" )", name ); - - msg= create_message( ERASE, name, 0); - msg->count=1; - q_put( &env_universal_server.unsent, msg ); - env_universal_barrier(); - + + if( is_dead() ) + { + env_universal_common_remove( name ); + } + else + { + msg= create_message( ERASE, name, 0); + msg->count=1; + q_put( &env_universal_server.unsent, msg ); + env_universal_barrier(); + } + return res; } @@ -430,6 +474,8 @@ void env_universal_get_names( array_list_t *l, { if( !init ) return; + + CHECK( l, ); env_universal_common_get_names( l, show_exported, diff --git a/env_universal_common.c b/env_universal_common.c index ab0ac49..5a6c49f 100644 --- a/env_universal_common.c +++ b/env_universal_common.c @@ -423,7 +423,7 @@ void read_message( connection_t *src ) /** Remove variable with specified name */ -static void remove_entry( wchar_t *name ) +void env_universal_common_remove( const wchar_t *name ) { void *k, *v; hash_remove( &env_universal_var, @@ -449,6 +449,34 @@ static int match( const wchar_t *msg, const wchar_t *cmd ) return 1; } +void env_universal_common_set( const wchar_t *key, const wchar_t *val, int export ) +{ + var_uni_entry_t *entry; + wchar_t *name; + + CHECK( key, ); + CHECK( val, ); + + entry = malloc( sizeof(var_uni_entry_t) + sizeof(wchar_t)*(wcslen(val)+1) ); + name = wcsdup(key); + + if( !entry || !name ) + DIE_MEM(); + + entry->export=export; + + wcscpy( entry->val, val ); + env_universal_common_remove( name ); + + hash_put( &env_universal_var, name, entry ); + + if( callback ) + { + callback( export?SET_EXPORT:SET, name, val ); + } +} + + /** Parse message msg */ @@ -462,7 +490,7 @@ static void parse_message( wchar_t *msg, if( match( msg, SET_STR ) || match( msg, SET_EXPORT_STR )) { - wchar_t *name, *val, *tmp; + wchar_t *name, *tmp; int export = match( msg, SET_EXPORT_STR ); name = msg+(export?wcslen(SET_EXPORT_STR):wcslen(SET_STR)); @@ -472,31 +500,20 @@ static void parse_message( wchar_t *msg, tmp = wcschr( name, L':' ); if( tmp ) { - wchar_t *key =malloc( sizeof( wchar_t)*(tmp-name+1)); + wchar_t *key; + wchar_t *val; + + key = malloc( sizeof( wchar_t)*(tmp-name+1)); memcpy( key, name, sizeof( wchar_t)*(tmp-name)); key[tmp-name]=0; val = tmp+1; - - val = unescape( val, 0 ); - var_uni_entry_t *entry = - malloc( sizeof(var_uni_entry_t) + sizeof(wchar_t)*(wcslen(val)+1) ); - if( !entry ) - DIE_MEM(); - entry->export=export; - - wcscpy( entry->val, val ); - remove_entry( key ); - - hash_put( &env_universal_var, key, entry ); + env_universal_common_set( key, val, export ); - if( callback ) - { - callback( export?SET_EXPORT:SET, key, val ); - } - free(val ); + free( val ); + free( key ); } else { @@ -522,7 +539,7 @@ static void parse_message( wchar_t *msg, debug( 1, PARSE_ERR, msg ); } - remove_entry( name ); + env_universal_common_remove( name ); if( callback ) { @@ -853,8 +870,16 @@ void connection_destroy( connection_t *c) { q_destroy( &c->unsent ); b_destroy( &c->input ); - if( close( c->fd ) ) + + /* + A connection need not always be open - we only try to close it + if it is open. + */ + if( c->fd >= 0 ) { - wperror( L"close" ); + if( close( c->fd ) ) + { + wperror( L"close" ); + } } } diff --git a/env_universal_common.h b/env_universal_common.h index 21550a0..166fb6b 100644 --- a/env_universal_common.h +++ b/env_universal_common.h @@ -143,19 +143,50 @@ void env_universal_common_destroy(); /** Add all variable names to the specified list + + This function operate agains the local copy of all universal + variables, it does not communicate with any other process. */ void env_universal_common_get_names( array_list_t *l, int show_exported, int show_unexported ); +/** + Perform the specified variable assignment. + + This function operate agains the local copy of all universal + variables, it does not communicate with any other process. + + Do not call this function. Create a message to do it. This function + is only to be used when fishd is dead. +*/ +void env_universal_common_set( const wchar_t *key, const wchar_t *val, int export ); + +/** + Remove the specified variable. + + This function operate agains the local copy of all universal + variables, it does not communicate with any other process. + + Do not call this function. Create a message to do it. This function + is only to be used when fishd is dead. +*/ +void env_universal_common_remove( const wchar_t *key ); + /** Get the value of the variable with the specified name + + This function operate agains the local copy of all universal + variables, it does not communicate with any other process. */ wchar_t *env_universal_common_get( const wchar_t *name ); /** Get the export flag of the variable with the specified name. Returns 0 if the variable doesn't exist. + + This function operate agains the local copy of all universal + variables, it does not communicate with any other process. */ int env_universal_common_get_export( const wchar_t *name ); @@ -164,8 +195,17 @@ int env_universal_common_get_export( const wchar_t *name ); */ void enqueue_all( connection_t *c ); +/** + Fill in the specified connection_t struct. Use the specified file + descriptor for communication. +*/ void connection_init( connection_t *c, int fd ); -void connection_destroy( connection_t *c); +/** + Close and destroy the specified connection struct. This frees + allstructures allocated by the connection, such as ques of unsent + messages. +*/ +void connection_destroy( connection_t *c); #endif