diff options
Diffstat (limited to 'env_universal_common.c')
-rw-r--r-- | env_universal_common.c | 152 |
1 files changed, 135 insertions, 17 deletions
diff --git a/env_universal_common.c b/env_universal_common.c index de81f197..6aa42810 100644 --- a/env_universal_common.c +++ b/env_universal_common.c @@ -36,11 +36,23 @@ #define SET_MBS "SET" /** + Non-wide version of the set_export command +*/ +#define SET_EXPORT_MBS "SET_EXPORT" + +/** Non-wide version of the erase command */ #define ERASE_MBS "ERASE" +/** + Non-wide version of the barrier command +*/ #define BARRIER_MBS "BARRIER" + +/** + Non-wide version of the barrier_reply command +*/ #define BARRIER_REPLY_MBS "BARRIER_REPLY" /** @@ -48,6 +60,19 @@ */ #define PARSE_ERR L"Unable to parse universal variable message: '%ls'" +/** + A variable entry. Stores the value of a variable and whether it + should be exported. Obviously, it needs to be allocated large + enough to fit the value string. +*/ +typedef struct var_entry +{ + int export; /**< Whether the variable should be exported */ + wchar_t val[0]; /**< The value of the variable */ +} +var_entry_t; + + static void parse_message( wchar_t *msg, connection_t *src ); @@ -61,6 +86,17 @@ void (*callback)( int type, const wchar_t *val ); +/** + Variable used by env_get_names to communicate auxiliary information + to add_key_to_hash +*/ +static int get_names_show_exported; +/** + Variable used by env_get_names to communicate auxiliary information + to add_key_to_hash +*/ +static int get_names_show_unexported; + void env_universal_common_init( void (*cb)(int type, const wchar_t *key, const wchar_t *val ) ) { @@ -155,6 +191,7 @@ static int match( const wchar_t *msg, const wchar_t *cmd ) size_t len = wcslen( cmd ); if( wcsncasecmp( msg, cmd, len ) != 0 ) return 0; + if( msg[len] && msg[len]!= L' ' && msg[len] != L'\t' ) return 0; @@ -169,12 +206,13 @@ static void parse_message( wchar_t *msg, if( msg[0] == L'#' ) return; - - if( match( msg, SET_STR ) ) + + if( match( msg, SET_STR ) || match( msg, SET_EXPORT_STR )) { wchar_t *name, *val, *tmp; - - name = msg+wcslen(SET_STR); + int export = match( msg, SET_EXPORT_STR ); + + name = msg+(export?wcslen(SET_EXPORT_STR):wcslen(SET_STR)); while( wcschr( L"\t ", *name ) ) name++; @@ -189,14 +227,22 @@ static void parse_message( wchar_t *msg, val = unescape( wcsdup(val), 0 ); + var_entry_t *entry = + malloc( sizeof(var_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, val ); + hash_put( &env_universal_var, key, entry ); if( callback ) { - callback( SET, key, val ); + callback( export?SET_EXPORT:SET, key, val ); } + free(val ); } else { @@ -205,7 +251,7 @@ static void parse_message( wchar_t *msg, } else if( match( msg, ERASE_STR ) ) { - wchar_t *name, *val, *tmp; + wchar_t *name, *tmp; name = msg+wcslen(ERASE_STR); while( wcschr( L"\t ", *name ) ) @@ -253,8 +299,11 @@ int try_send( message_t *msg, int fd ) { + debug( 3, + L"before write of %d chars to fd %d", strlen(msg->body), fd ); + int res = write( fd, msg->body, strlen(msg->body) ); - + if( res == -1 ) { switch( errno ) @@ -282,12 +331,11 @@ int try_send( message_t *msg, void try_send_all( connection_t *c ) { - debug( 2, + debug( 3, L"Send all updates to connection on fd %d", c->fd ); while( !q_empty( &c->unsent) ) { - switch( try_send( (message_t *)q_peek( &c->unsent), c->fd ) ) { case 1: @@ -295,9 +343,13 @@ void try_send_all( connection_t *c ) break; case 0: + debug( 1, + L"Socket full, send rest later" ); return; case -1: + debug( 1, + L"Socket dead!!!" ); c->killme = 1; return; } @@ -329,6 +381,7 @@ message_t *create_message( int type, switch( type ) { case SET: + case SET_EXPORT: { if( !val_in ) { @@ -341,20 +394,20 @@ message_t *create_message( int type, char *val = wcs2str(esc ); free(esc); - - - sz = strlen(SET_MBS) + strlen(key) + strlen(val) + 4; + + sz = strlen(type==SET?SET_MBS:SET_EXPORT_MBS) + strlen(key) + strlen(val) + 4; msg = malloc( sizeof( message_t ) + sz ); - + if( !msg ) die_mem(); - - strcpy( msg->body, SET_MBS " " ); + + strcpy( msg->body, (type==SET?SET_MBS:SET_EXPORT_MBS) ); + strcat( msg->body, " " ); strcat( msg->body, key ); strcat( msg->body, ":" ); strcat( msg->body, val ); strcat( msg->body, "\n" ); - + free( val ); break; @@ -406,3 +459,68 @@ message_t *create_message( int type, msg->count=0; return msg; } + +/** + Function used with hash_foreach to insert keys of one table into + another +*/ +static void add_key_to_hash( const void *key, + const void *data, + void *aux ) +{ + var_entry_t *e = (var_entry_t *)data; + if( ( e->export && get_names_show_exported) || + ( !e->export && get_names_show_unexported) ) + al_push( (array_list_t *)aux, key ); +} + +void env_universal_common_get_names( array_list_t *l, + int show_exported, + int show_unexported ) +{ + get_names_show_exported = show_exported; + get_names_show_unexported = show_unexported; + + hash_foreach2( &env_universal_var, + add_key_to_hash, + l ); +} + +wchar_t *env_universal_common_get( const wchar_t *name ) +{ + var_entry_t *e = (var_entry_t *)hash_get( &env_universal_var, name ); + if( e ) + return e->val; + return 0; +} + +int env_universal_common_get_export( const wchar_t *name ) +{ + var_entry_t *e = (var_entry_t *)hash_get( &env_universal_var, name ); + if( e ) + return e->export; + return 0; +} + +static void enqueue( const void *k, + const void *v, + void *q) +{ + const wchar_t *key = (const wchar_t *)k; + const var_entry_t *val = (const var_entry_t *)v; + queue_t *queue = (queue_t *)q; + + message_t *msg = create_message( val->export?SET_EXPORT:SET, key, val->val ); + msg->count=1; + + q_put( queue, msg ); +} + +void enqueue_all( connection_t *c ) +{ + hash_foreach2( &env_universal_var, + &enqueue, + (void *)&c->unsent ); + try_send_all( c ); +} + |