From 51de26960c35ef707713d5c02568290d66578db3 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 8 Oct 2012 14:47:25 -0700 Subject: [PATCH] Make escaping consistent for fish <-> fishd protocol Fix fork guards to work in fishd https://github.com/fish-shell/fish-shell/issues/339 --- env.cpp | 5 ++++- env_universal.cpp | 6 +++--- env_universal.h | 2 +- env_universal_common.cpp | 39 +++++++++++++++++++++++++-------------- env_universal_common.h | 9 ++++----- fish.cpp | 29 +++++++++++++++++++++++++++-- fishd.cpp | 6 +++++- 7 files changed, 69 insertions(+), 27 deletions(-) diff --git a/env.cpp b/env.cpp index 387d50c24..56c4d79ff 100644 --- a/env.cpp +++ b/env.cpp @@ -375,7 +375,7 @@ static void react_to_variable_change(const wcstring &key) { Universal variable callback function. This function makes sure the proper events are triggered when an event occurs. */ -static void universal_callback( int type, +static void universal_callback( fish_message_type_t type, const wchar_t *name, const wchar_t *val ) { @@ -395,6 +395,9 @@ static void universal_callback( int type, str=L"ERASE"; break; } + + default: + break; } if( str ) diff --git a/env_universal.cpp b/env_universal.cpp index 3d12a222f..7a1564ed5 100644 --- a/env_universal.cpp +++ b/env_universal.cpp @@ -61,7 +61,7 @@ static int get_socket_count = 0; static wchar_t * path; static wchar_t *user; static void (*start_fishd)(); -static void (*external_callback)( int type, const wchar_t *name, const wchar_t *val ); +static void (*external_callback)( fish_message_type_t type, const wchar_t *name, const wchar_t *val ); /** Flag set to 1 when a barrier reply is recieved @@ -165,7 +165,7 @@ static int get_socket( int fork_ok ) /** Callback function used whenever a new fishd message is recieved */ -static void callback( int type, const wchar_t *name, const wchar_t *val ) +static void callback( fish_message_type_t type, const wchar_t *name, const wchar_t *val ) { if( type == BARRIER_REPLY ) { @@ -250,7 +250,7 @@ static void reconnect() void env_universal_init( wchar_t * p, wchar_t *u, void (*sf)(), - void (*cb)( int type, const wchar_t *name, const wchar_t *val )) + void (*cb)( fish_message_type_t type, const wchar_t *name, const wchar_t *val )) { path=p; user=u; diff --git a/env_universal.h b/env_universal.h index ec2fae19f..bfc456350 100644 --- a/env_universal.h +++ b/env_universal.h @@ -20,7 +20,7 @@ extern connection_t env_universal_server; void env_universal_init( wchar_t * p, wchar_t *u, void (*sf)(), - void (*cb)( int type, const wchar_t *name, const wchar_t *val )); + void (*cb)( fish_message_type_t type, const wchar_t *name, const wchar_t *val )); /** Free memory used by envuni */ diff --git a/env_universal_common.cpp b/env_universal_common.cpp index f476e1ba8..5ed554be6 100644 --- a/env_universal_common.cpp +++ b/env_universal_common.cpp @@ -112,7 +112,7 @@ env_var_table_t env_universal_var; /** Callback function, should be called on all events */ -void (*callback)( int type, +static void (*callback)( fish_message_type_t type, const wchar_t *key, const wchar_t *val ); @@ -405,7 +405,7 @@ static char *wcs2utf( const wchar_t *in ) -void env_universal_common_init( void (*cb)(int type, const wchar_t *key, const wchar_t *val ) ) +void env_universal_common_init( void (*cb)(fish_message_type_t type, const wchar_t *key, const wchar_t *val ) ) { callback = cb; } @@ -592,7 +592,7 @@ void env_universal_common_set( const wchar_t *key, const wchar_t *val, int expor /** Parse message msg */ -static void parse_message( wchar_t *msg, +static void parse_message( wchar_t *msg, connection_t *src ) { // debug( 3, L"parse_message( %ls );", msg ); @@ -622,7 +622,8 @@ static void parse_message( wchar_t *msg, val = tmp+1; val = unescape( val, 0 ); - env_universal_common_set( key, val, exportv ); + if (key && val) + env_universal_common_set( key, val, exportv ); free( val ); free( key ); @@ -752,6 +753,15 @@ void try_send_all( connection_t *c ) } } +/* The universal variable format has some funny escaping requirements; here we try to be safe */ +static bool is_universal_safe_to_encode_directly(wchar_t c) +{ + if (c < 32 || c > 128) + return false; + + return iswalnum(c) || wcschr(L"/", c); +} + /** Escape specified string */ @@ -760,21 +770,22 @@ static wcstring full_escape( const wchar_t *in ) wcstring out; for( ; *in; in++ ) { - if( *in < 32 ) + wchar_t c = *in; + if (is_universal_safe_to_encode_directly(c)) + { + out.push_back(c); + } + else if (c < 256) { - append_format( out, L"\\x%.2x", *in ); + append_format(out, L"\\x%.2x", c); } - else if( *in < 128 ) + else if (c < 65536) { - out.push_back(*in); - } - else if( *in < 65536 ) - { - append_format( out, L"\\u%.4x", *in ); + append_format(out, L"\\u%.4x", c); } else { - append_format( out, L"\\U%.8x", *in ); + append_format(out, L"\\U%.8x", c); } } return out; @@ -803,7 +814,7 @@ void set_body(message_t *msg, ...) } /* Returns an instance of message_t allocated via new */ -message_t *create_message( int type, +message_t *create_message( fish_message_type_t type, const wchar_t *key_in, const wchar_t *val_in ) { diff --git a/env_universal_common.h b/env_universal_common.h index 11991dcd4..7da8cd63a 100644 --- a/env_universal_common.h +++ b/env_universal_common.h @@ -40,15 +40,14 @@ /** The different types of commands that can be sent between client/server */ -enum +typedef enum { SET, SET_EXPORT, ERASE, BARRIER, BARRIER_REPLY, -} - ; +} fish_message_type_t; /** The size of the buffer used for reading from the socket @@ -133,12 +132,12 @@ void try_send_all( connection_t *c ); /** Create a messge with the specified properties */ -message_t *create_message( int type, const wchar_t *key, const wchar_t *val ); +message_t *create_message( fish_message_type_t type, const wchar_t *key, const wchar_t *val ); /** Init the library */ -void env_universal_common_init(void (*cb)(int type, const wchar_t *key, const wchar_t *val ) ); +void env_universal_common_init(void (*cb)(fish_message_type_t type, const wchar_t *key, const wchar_t *val ) ); /** Destroy library data diff --git a/fish.cpp b/fish.cpp index baf8a7741..d1699d584 100644 --- a/fish.cpp +++ b/fish.cpp @@ -410,10 +410,34 @@ static int fish_parse_opt( int argc, char **argv, const char **cmd_ptr ) parses commands from stdin or files, depending on arguments */ +static wcstring full_escape( const wchar_t *in ) +{ + wcstring out; + for( ; *in; in++ ) + { + if( *in < 32 ) + { + append_format( out, L"\\x%.2x", *in ); + } + else if( *in < 128 ) + { + out.push_back(*in); + } + else if( *in < 65536 ) + { + append_format( out, L"\\u%.4x", *in ); + } + else + { + append_format( out, L"\\U%.8x", *in ); + } + } + return out; +} + extern int g_fork_count; int main( int argc, char **argv ) { - struct stat tmp; int res=1; const char *cmd=0; int my_optind=0; @@ -425,7 +449,8 @@ int main( int argc, char **argv ) is_interactive_session=1; program_name=L"fish"; - stat("----------FISH_HIT_MAIN----------", &tmp); + //struct stat tmp; + //stat("----------FISH_HIT_MAIN----------", &tmp); my_optind = fish_parse_opt( argc, argv, &cmd ); diff --git a/fishd.cpp b/fishd.cpp index be69ac417..86c17373d 100644 --- a/fishd.cpp +++ b/fishd.cpp @@ -496,7 +496,7 @@ unlock: /** Event handler. Broadcasts updates to all clients. */ -static void broadcast( int type, const wchar_t *key, const wchar_t *val ) +static void broadcast( fish_message_type_t type, const wchar_t *key, const wchar_t *val ) { connection_t *c; message_t *msg; @@ -540,6 +540,9 @@ static void daemonize() case 0: { + /* Ordinarily there's very limited things we will do after fork, due to multithreading. But fishd is safe because it's single threaded. So don't die in is_forked_child. */ + setup_fork_guards(); + /* Make fishd ignore the HUP signal. */ @@ -557,6 +560,7 @@ static void daemonize() act.sa_handler=&handle_term; sigaction( SIGTERM, &act, 0); break; + } default: