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
This commit is contained in:
axel 2006-11-15 22:34:47 +10:00
parent d00bc973fe
commit 3b2670532a
3 changed files with 156 additions and 45 deletions

View file

@ -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;
}
@ -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<al_get_count( &lst ); i++ )
{
wchar_t *key = (wchar_t *)al_get( &lst, i );
env_universal_common_remove( key );
}
al_destroy( &lst );
}
/**
Try to establish a new connection to fishd. If successfull, end
with call to env_universal_barrier(), to make sure everything is in
@ -216,6 +246,7 @@ static void reconnect()
init = 1;
if( env_universal_server.fd >= 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;
@ -385,6 +416,12 @@ void env_universal_set( const wchar_t *name, const wchar_t *value, int export )
debug( 3, L"env_universal_set( \"%ls\", \"%ls\" )", name, value );
if( is_dead() )
{
env_universal_common_set( name, value, export );
}
else
{
msg = create_message( export?SET_EXPORT:SET,
name,
value);
@ -398,6 +435,7 @@ void env_universal_set( const wchar_t *name, const wchar_t *value, int export )
msg->count=1;
q_put( &env_universal_server.unsent, msg );
env_universal_barrier();
}
}
int env_universal_remove( const wchar_t *name )
@ -411,15 +449,21 @@ 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 );
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;
}
@ -431,6 +475,8 @@ void env_universal_get_names( array_list_t *l,
if( !init )
return;
CHECK( l, );
env_universal_common_get_names( l,
show_exported,
show_unexported );

View file

@ -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;
env_universal_common_set( key, val, export );
wcscpy( entry->val, val );
remove_entry( key );
hash_put( &env_universal_var, key, entry );
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 );
/*
A connection need not always be open - we only try to close it
if it is open.
*/
if( c->fd >= 0 )
{
if( close( c->fd ) )
{
wperror( L"close" );
}
}
}

View file

@ -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 );
/**
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