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
This commit is contained in:
axel 2005-10-15 10:51:26 +10:00
parent 638df31ca4
commit 9298f610f6
14 changed files with 178 additions and 52 deletions

132
builtin.c
View File

@ -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; i<argc; i++ )
sb_append2( sb_out,
L"function ",
argv[i],
L"\n\t",
function_get_definition(argv[i]),
L"\nend\n\n",
(void *)0);
{
if( !function_exists( argv[i] ) )
res++;
else
{
sb_append2( sb_out,
L"function ",
argv[i],
L"\n\t",
function_get_definition(argv[i]),
L"\nend\n\n",
(void *)0);
}
}
break;
}
}
return 0;
return res;
}
@ -714,6 +724,17 @@ static int wcsbindingname( wchar_t *str )
return 1;
}
static void print_block_stack( block_t *b )
{
if( !b )
return;
wprintf( L"%ls (%d)\n", parser_get_block_desc( b->type ), 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: " );

View File

@ -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;

View File

@ -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()
{

View File

@ -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;

View File

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

1
main.c
View File

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

View File

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

View File

@ -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;

View File

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

11
proc.c
View File

@ -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);
}

View File

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

View File

@ -656,5 +656,4 @@ int main( int argc, char **argv )
}
}
#endif

8
util.c
View File

@ -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 )

View File

@ -12,6 +12,7 @@
#include <errno.h>
#include <fcntl.h>
#include <wchar.h>
#include <wctype.h>
#include <string.h>
#include <dirent.h>
#include <stdarg.h>
@ -240,7 +241,6 @@ static int vgwprintf( void (*writer)(wchar_t),
{
if(*filter == L'%')
{
int i;
int is_long=0;
int width = -1;
filter++;