From 9298f610f6f26425db36d8727ad533d660a6c5d6 Mon Sep 17 00:00:00 2001 From: axel Date: Sat, 15 Oct 2005 10:51:26 +1000 Subject: [PATCH] Add support for specifying event handler for calling job in command supstitution. Add psub shellscript function for process substitution darcs-hash:20051015005126-ac50b-d2aedca3a50a78362502f3fa9dd8bf25cb7dc6e1.gz --- builtin.c | 132 ++++++++++++++++++++++++++++++++-------- env_universal_common.c | 2 - event.c | 8 ++- event.h | 6 ++ init/fish_function.fish | 30 +++++++++ main.c | 1 + output.c | 8 +-- parser.c | 12 ++-- parser.h | 5 ++ proc.c | 11 ++-- reader.c | 4 +- tokenizer.c | 1 - util.c | 8 ++- wutil.c | 2 +- 14 files changed, 178 insertions(+), 52 deletions(-) diff --git a/builtin.c b/builtin.c index e8c4af254..8197b6006 100644 --- a/builtin.c +++ b/builtin.c @@ -492,7 +492,8 @@ static int builtin_functions( wchar_t **argv ) int argc=builtin_count_args( argv ); int list=0; int show_hidden=0; - + int res = 0; + woptind=0; const static struct woption @@ -679,19 +680,28 @@ static int builtin_functions( wchar_t **argv ) default: { + for( i=woptind; itype ), b->job?b->job->job_id:-1 ); + print_block_stack( b->outer ); + +} + + /** The function builtin, used for providing subroutines. It calls various functions from function.c to perform any heavy lifting. @@ -855,25 +876,82 @@ static int builtin_function( wchar_t **argv ) wchar_t *end; event_t *e; - errno = 0; - pid = wcstol( woptarg, &end, 10 ); - if( errno || !end || *end ) - { - sb_printf( sb_err, - L"%ls: Invalid process id %ls\n", - argv[0], - woptarg ); - res=1; - break; - } - e = malloc( sizeof(event_t)); if( !e ) die_mem(); - e->type = EVENT_EXIT; - e->param1.pid = (opt=='j'?-1:1)*abs(pid); - e->function_name=0; - al_push( events, e ); + + if( ( opt == 'j' ) && + ( wcscasecmp( woptarg, L"caller" ) == 0 ) ) + { + int job_id = -1; + + if( is_subshell ) + { + block_t *b = current_block; + +// print_block_stack( b ); + + while( b && (b->type != SUBST) ) + b = b->outer; + + if( b ) + { + b=b->outer; + } + if( b->job ) + { +// debug( 1, L"Found block, type is %ls", parser_get_block_desc( b->type ) ); + + job_id = b->job->job_id; + } + else + { +// debug( 1, L"Calling block is null" ); + } + + } + + if( job_id == -1 ) + { + sb_printf( sb_err, + L"%ls: Cannot find calling job for event handler\n", + argv[0] ); + res=1; + } + else + { + e->type = EVENT_JOB_ID; + e->param1.job_id = job_id; + } + + } + else + { + errno = 0; + pid = wcstol( woptarg, &end, 10 ); + if( errno || !end || *end ) + { + sb_printf( sb_err, + L"%ls: Invalid process id %ls\n", + argv[0], + woptarg ); + res=1; + break; + } + + + e->type = EVENT_EXIT; + e->param1.pid = (opt=='j'?-1:1)*abs(pid); + } + if( res ) + { + free( e ); + } + else + { + e->function_name=0; + al_push( events, e ); + } break; } @@ -927,7 +1005,7 @@ static int builtin_function( wchar_t **argv ) wchar_t **names_arr; int chars=0; - builtin_print_help( argv[0], sb_err ); +// builtin_print_help( argv[0], sb_err ); sb_append( sb_err, L"Current functions are: " ); chars += wcslen( L"Current functions are: " ); diff --git a/env_universal_common.c b/env_universal_common.c index 226859f18..29ef08ab4 100644 --- a/env_universal_common.c +++ b/env_universal_common.c @@ -230,8 +230,6 @@ static void parse_message( wchar_t *msg, tmp = wcschr( name, L':' ); if( tmp ) { - wchar_t *val_unescaped; - wchar_t *key =malloc( sizeof( wchar_t)*(tmp-name+1)); memcpy( key, name, sizeof( wchar_t)*(tmp-name)); key[tmp-name]=0; diff --git a/event.c b/event.c index 669f6beb8..2ccaf619c 100644 --- a/event.c +++ b/event.c @@ -95,6 +95,9 @@ static int event_match( event_t *class, event_t *instance ) if( class->param1.pid == EVENT_ANY_PID ) return 1; return class->param1.pid == instance->param1.pid; + + case EVENT_JOB_ID: + return class->param1.job_id == instance->param1.job_id; } /** @@ -180,7 +183,6 @@ void event_remove( event_t *criterion ) signal_handle( e.param1.signal, 0 ); } } - } else { @@ -292,7 +294,7 @@ static void event_fire_internal( event_t *event, array_list_t *arguments ) al_push( fire, criterion ); } } - + /* No matches. Time to return. */ @@ -362,7 +364,7 @@ static void event_fire_internal( event_t *event, array_list_t *arguments ) } /** - Perform all pending signal events + Handle all pending signal events */ static void event_fire_signal_events() { diff --git a/event.h b/event.h index c691e6bdf..9700e331d 100644 --- a/event.h +++ b/event.h @@ -23,6 +23,7 @@ enum EVENT_SIGNAL, /**< An event triggered by a signal */ EVENT_VARIABLE, /**< An event triggered by a variable update */ EVENT_EXIT, /**< An event triggered by a job or process exit */ + EVENT_JOB_ID, /**< An event triggered by a job exit */ } ; @@ -53,6 +54,11 @@ typedef struct Process id for process-type events. Use EVENT_ANY_PID to match any pid. */ pid_t pid; + /** + Job id for EVENT_JOB_ID type events + */ + int job_id; + } param1; const wchar_t *function_name; diff --git a/init/fish_function.fish b/init/fish_function.fish index de57042d7..aaa44565c 100644 --- a/init/fish_function.fish +++ b/init/fish_function.fish @@ -711,6 +711,36 @@ function type -d "Print the type of a command" return $status end +function psub -d "Read from stdin into a file and output the filename. Remove the file when the command that calles psub exits." + + if not status --is-command-substitution + echo psub: Not inside of command substitution + end + + # Find unique file name + while true + set filename /tmp/.psub.(echo %self).(random); + if not test -e $filename + break; + end + end + + cat >$filename + + # Find unique function name + while true + set funcname __fish_psub_(random); + if not functions $funcname >/dev/null ^/dev/null + break; + end + end + + eval function $funcname --on-job-exit caller\; rm $filename\; functions -e $funcname\; end + + echo $filename + +end + if status --is-interactive diff --git a/main.c b/main.c index 98737f358..dbcff92ed 100644 --- a/main.c +++ b/main.c @@ -55,6 +55,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "intern.h" #include "exec.h" #include "event.h" +#include "output.h" /** Parse init files diff --git a/output.c b/output.c index 856586844..34e8819b7 100644 --- a/output.c +++ b/output.c @@ -258,9 +258,9 @@ int writech( wint_t ch ) */ void writestr( const wchar_t *str ) { - while( *str ) - writech( *str++ ); -/* +// while( *str ) +// writech( *str++ ); + size_t len = MAX_UTF8_BYTES*wcslen(str)+1; if( writestr_buff_sz < len ) @@ -276,7 +276,7 @@ void writestr( const wchar_t *str ) writestr_buff_sz ); write( 1, writestr_buff, strlen( writestr_buff ) ); -*/ + } diff --git a/parser.c b/parser.c index b3d063dde..32192ceb4 100644 --- a/parser.c +++ b/parser.c @@ -176,7 +176,8 @@ void parser_push_block( int type ) if( type == TOP || type == SUBST ) new->skip = 0; - + new->job = 0; + new->loop_status=LOOP_NORMAL; current_block = new; @@ -1681,7 +1682,9 @@ static void eval_job( tokenizer *tok ) j->fg=1; j->constructed=0; j->skip_notification = is_subshell || is_block || is_event || (!is_interactive); - + + current_block->job = j; + proc_had_barrier=0; if( is_interactive ) @@ -1733,7 +1736,7 @@ static void eval_job( tokenizer *tok ) p->cmd = wcsdup( j->command ); p->skipped=current_block->skip; } - + skip |= current_block->skip; if(!skip ) @@ -1785,6 +1788,7 @@ static void eval_job( tokenizer *tok ) */ job_free( j ); } + current_block->job = 0; break; } @@ -1889,7 +1893,7 @@ int eval( const wchar_t *cmd, io_data_t *io, int block_type ) exit(1); break; } - + if( (!error_code) && (!exit_status()) && (!proc_get_last_status()) ) { char *h; diff --git a/parser.h b/parser.h index d02edf130..cb6170476 100644 --- a/parser.h +++ b/parser.h @@ -25,6 +25,11 @@ typedef struct block */ int loop_status; + /** + The log that is currently evaluated in the specified block. + */ + job_t *job; + /** First block type specific variable */ diff --git a/proc.c b/proc.c index 3f188ad85..bc27a2147 100644 --- a/proc.c +++ b/proc.c @@ -482,7 +482,7 @@ static void format_job_info( const job_t *j, const wchar_t *status ) fwprintf (stdout, L"\n" ); } -static void fire_process_event( const wchar_t *msg, pid_t pid, int status ) +static void fire_process_event( const wchar_t *msg, int type, pid_t pid, int status ) { static event_t ev; event_t e; @@ -490,7 +490,7 @@ static void fire_process_event( const wchar_t *msg, pid_t pid, int status ) e.function_name=0; - ev.type=EVENT_EXIT; + ev.type=type; ev.param1.pid = pid; al_push( &event_arg, msg ); @@ -516,7 +516,7 @@ int job_reap( int interactive ) locked++; if( locked>1 ) - return; + return 0; for( j=first_job; j; j=jnext) { @@ -539,7 +539,7 @@ int job_reap( int interactive ) s = p->status; - fire_process_event( L"PROCESS_EXIT", p->pid, ( WIFSIGNALED(s)?-1:WEXITSTATUS( s )) ); + fire_process_event( L"PROCESS_EXIT", EVENT_EXIT, p->pid, ( WIFSIGNALED(s)?-1:WEXITSTATUS( s )) ); if( WIFSIGNALED(s) ) { @@ -597,7 +597,8 @@ int job_reap( int interactive ) found=1; } } - fire_process_event( L"JOB_EXIT", -j->pgid, 0 ); + fire_process_event( L"JOB_EXIT", EVENT_EXIT, -j->pgid, 0 ); + fire_process_event( L"JOB_EXIT", EVENT_JOB_ID, j->job_id, 0 ); job_free(j); } diff --git a/reader.c b/reader.c index b74805e6d..b585ea481 100644 --- a/reader.c +++ b/reader.c @@ -71,6 +71,7 @@ commence. #include "input.h" #include "function.h" #include "output.h" +#include "signal.h" /** Maximum length of prefix string when printing completion @@ -238,9 +239,6 @@ static reader_data_t *data=0; */ static int end_loop = 0; - -static int new_size=0; - /** The list containing names of files that are being parsed */ diff --git a/tokenizer.c b/tokenizer.c index 6f861b87e..6e4c6c928 100644 --- a/tokenizer.c +++ b/tokenizer.c @@ -656,5 +656,4 @@ int main( int argc, char **argv ) } } - #endif diff --git a/util.c b/util.c index 7eb73ec31..a03d7fc4d 100644 --- a/util.c +++ b/util.c @@ -872,9 +872,13 @@ void sb_append2( string_buffer_t *b, ... ) int sb_printf( string_buffer_t *buffer, const wchar_t *format, ... ) { va_list va; + int res; + va_start( va, format ); - sb_vprintf( buffer, format, va ); - va_end( va ); + res = sb_vprintf( buffer, format, va ); + va_end( va ); + + return res; } int sb_vprintf( string_buffer_t *buffer, const wchar_t *format, va_list va_orig ) diff --git a/wutil.c b/wutil.c index 4256ba605..23a53d441 100644 --- a/wutil.c +++ b/wutil.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -240,7 +241,6 @@ static int vgwprintf( void (*writer)(wchar_t), { if(*filter == L'%') { - int i; int is_long=0; int width = -1; filter++;