aboutsummaryrefslogtreecommitdiffhomepage
path: root/exec.c
diff options
context:
space:
mode:
authorGravatar axel <axel@liljencrantz.se>2006-01-12 00:40:20 +1000
committerGravatar axel <axel@liljencrantz.se>2006-01-12 00:40:20 +1000
commit67333a23f1f84bc1de5d7d90185c621264f259b7 (patch)
treedab595e11049f7c5fefdd3972ff7a357fc8e10fa /exec.c
parent72bb5ae06f05fc9a8c237a318a34343ade25c1b9 (diff)
Recover instead of quiting when a redirection error occurs for a shellscript function
darcs-hash:20060111144020-ac50b-a5c7449276730c21949324abd8ba49b91b186e8c.gz
Diffstat (limited to 'exec.c')
-rw-r--r--exec.c77
1 files changed, 48 insertions, 29 deletions
diff --git a/exec.c b/exec.c
index ecd66947..6e7f2df4 100644
--- a/exec.c
+++ b/exec.c
@@ -440,10 +440,32 @@ static int has_fd( io_data_t *d, int fd )
/**
+ Free a transmogrified io chain. Only the chain itself and resources
+ used by a transmogrified IO_FILE redirection are freed, since the
+ original chain may still be needed.
+*/
+static void io_untransmogrify( io_data_t * in, io_data_t *out )
+{
+ if( !out )
+ return;
+ io_untransmogrify( in->next, out->next );
+ switch( in->io_mode )
+ {
+ case IO_FILE:
+ exec_close( out->param1.old_fd );
+ break;
+ }
+ free(out);
+}
+
+
+/**
Make a copy of the specified io redirection chain, but change file
redirection into fd redirection. This makes the redirection chain
suitable for use as block-level io, since the file won't be
repeatedly reopened for every command in the block.
+
+ \return the transmogrified chain on sucess, or 0 on failiure
*/
static io_data_t *io_transmogrify( io_data_t * in )
{
@@ -459,7 +481,8 @@ static io_data_t *io_transmogrify( io_data_t * in )
out->fd = in->fd;
out->io_mode = IO_FD;
out->param2.close_old = 1;
-
+ out->next=0;
+
switch( in->io_mode )
{
/*
@@ -488,7 +511,8 @@ static io_data_t *io_transmogrify( io_data_t * in )
in->param1.filename );
wperror( L"open" );
- exit(1);
+ free( out );
+ return 0;
}
out->param1.old_fd = fd;
@@ -496,32 +520,20 @@ static io_data_t *io_transmogrify( io_data_t * in )
}
}
- out->next = io_transmogrify( in->next );
+ if( in->next)
+ {
+ out->next = io_transmogrify( in->next );
+ if( !out->next )
+ {
+ io_untransmogrify( in, out );
+ return 0;
+ }
+ }
return out;
}
/**
- Free a transmogrified io chain. Only the chain itself and resources
- used by a transmogrified IO_FILE redirection are freed, since the
- original chain may still be needed.
-*/
-static void io_untransmogrify( io_data_t * in, io_data_t *out )
-{
- if( !in )
- return;
- io_untransmogrify( in->next, out->next );
- switch( in->io_mode )
- {
- case IO_FILE:
- exec_close( out->param1.old_fd );
- break;
- }
- free(out);
-}
-
-
-/**
Morph an io redirection chain into redirections suitable for
passing to eval, call eval, and clean up morphed redirections.
@@ -530,21 +542,29 @@ static void io_untransmogrify( io_data_t * in, io_data_t *out )
\param io the io redirections to be performed on this block
*/
-static int internal_exec_helper( const wchar_t *def,
+static void internal_exec_helper( const wchar_t *def,
int block_type,
io_data_t *io )
{
- int res=0;
io_data_t *io_internal = io_transmogrify( io );
int is_block_old=is_block;
is_block=1;
- signal_unblock();
+ /*
+ Did the transmogrification fail - if so, set error status and return
+ */
+ if( io && !io_internal )
+ {
+ proc_set_last_status( 1 );
+ return;
+ }
+ signal_unblock();
+
eval( def, io_internal, block_type );
-
+
signal_block();
-
+
/*
io_data_t *buff = io_get( io, 1 );
if( buff && buff->io_mode == IO_BUFFER )
@@ -555,7 +575,6 @@ static int internal_exec_helper( const wchar_t *def,
io_untransmogrify( io, io_internal );
job_reap( 0 );
is_block=is_block_old;
- return res;
}
/**