Skip to content

Commit

Permalink
Make fish store universal variables locally if fishd can't be started…
Browse files Browse the repository at this point in the history
… - local changes are lost of the fishd connection is restored

darcs-hash:20061115123447-ac50b-bf17c55079e1196205cc3a4fd0ca22d9f539836c.gz
  • Loading branch information
liljencrantz committed Nov 15, 2006
1 parent d00bc97 commit 3b26705
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 45 deletions.
88 changes: 67 additions & 21 deletions env_universal.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
}

Expand All @@ -151,7 +156,7 @@ static int get_socket( int fork_ok )

return -1;
}

debug( 3, L"Connected to fd %d", s );

return s;
Expand Down Expand Up @@ -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
Expand All @@ -216,6 +246,7 @@ static void reconnect()
init = 1;
if( env_universal_server.fd >= 0 )
{
env_universal_remove_all();
env_universal_barrier();
}
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 )
Expand All @@ -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;
}

Expand All @@ -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,
Expand Down
71 changes: 48 additions & 23 deletions env_universal_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
*/
Expand All @@ -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));
Expand All @@ -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
{
Expand All @@ -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 )
{
Expand Down Expand Up @@ -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" );
}
}
}
42 changes: 41 additions & 1 deletion env_universal_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 );

Expand All @@ -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

0 comments on commit 3b26705

Please sign in to comment.