2005-09-20 21:26:39 +08:00
/** \file exec.c
Functions for executing a program .
Some of the code in this file is based on code from the Glibc
manual , though I the changes performed have been massive .
*/
2006-08-11 09:18:35 +08:00
# include "config.h"
2005-09-20 21:26:39 +08:00
# include <stdlib.h>
# include <stdio.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <termios.h>
# include <unistd.h>
# include <fcntl.h>
# include <errno.h>
# include <wchar.h>
# include <string.h>
# include <limits.h>
# include <signal.h>
# include <sys/wait.h>
# include <assert.h>
# include <dirent.h>
2006-11-15 21:30:46 +08:00
# include <time.h>
2011-12-27 11:18:46 +08:00
# include <vector>
2012-02-09 14:56:42 +08:00
# include <deque>
2012-02-10 23:55:06 +08:00
# include <algorithm>
2012-02-22 11:33:11 +08:00
# include <memory>
2005-09-20 21:26:39 +08:00
2006-07-31 04:26:59 +08:00
# ifdef HAVE_SIGINFO_H
# include <siginfo.h>
# endif
2006-02-28 21:17:16 +08:00
# include "fallback.h"
2005-09-20 21:26:39 +08:00
# include "util.h"
2006-02-28 21:17:16 +08:00
2005-09-20 21:26:39 +08:00
# include "common.h"
# include "wutil.h"
# include "proc.h"
# include "exec.h"
# include "parser.h"
# include "builtin.h"
# include "function.h"
# include "env.h"
# include "wildcard.h"
# include "sanity.h"
# include "expand.h"
2005-10-08 19:20:51 +08:00
# include "signal.h"
2006-07-20 06:55:49 +08:00
2006-02-15 03:56:36 +08:00
# include "parse_util.h"
2005-09-20 21:26:39 +08:00
/**
file descriptor redirection error message
*/
2006-01-04 20:51:02 +08:00
# define FD_ERROR _( L"An error occurred while redirecting file descriptor %d" )
2007-10-27 02:42:32 +08:00
2009-02-23 04:28:52 +08:00
/**
file descriptor redirection error message
*/
# define WRITE_ERROR _( L"An error occurred while writing output" )
2005-09-20 21:26:39 +08:00
/**
file redirection error message
*/
2006-01-04 20:51:02 +08:00
# define FILE_ERROR _( L"An error occurred while redirecting file '%ls'" )
2007-10-27 02:42:32 +08:00
/**
file redirection clobbering error message
*/
# define NOCLOB_ERROR _( L"The file '%ls' already exists" )
2005-09-20 21:26:39 +08:00
/**
fork error message
*/
2006-01-04 20:51:02 +08:00
# define FORK_ERROR _( L"Could not create child process - exiting" )
2005-09-20 21:26:39 +08:00
2006-11-15 21:30:46 +08:00
/**
The number of times to try to call fork ( ) before giving up
*/
# define FORK_LAPS 5
2007-01-21 23:20:26 +08:00
/**
The number of nanoseconds to sleep between attempts to call fork ( )
*/
# define FORK_SLEEP_TIME 1000000
2006-10-26 23:19:46 +08:00
/**
Base open mode to pass to calls to open
*/
2006-11-15 21:30:46 +08:00
# define OPEN_MASK 0666
2005-10-17 21:24:12 +08:00
2005-10-03 21:09:37 +08:00
/**
List of all pipes used by internal pipes . These must be closed in
many situations in order to make sure that stray fds aren ' t lying
around .
*/
2012-02-09 14:56:42 +08:00
static std : : vector < int > open_fds ;
2005-10-17 21:24:12 +08:00
2006-02-04 19:33:20 +08:00
static int set_child_group ( job_t * j , process_t * p , int print_errors ) ;
2006-02-04 05:50:31 +08:00
2009-02-23 04:28:52 +08:00
static void exec_write_and_exit ( int fd , char * buff , size_t count , int status )
{
2011-12-27 11:18:46 +08:00
if ( write_loop ( fd , buff , count ) = = - 1 )
2009-02-23 04:28:52 +08:00
{
debug ( 0 , WRITE_ERROR ) ;
wperror ( L " write " ) ;
exit ( status ) ;
}
exit ( status ) ;
}
2005-10-08 19:20:51 +08:00
void exec_close ( int fd )
2005-09-23 21:10:31 +08:00
{
2006-11-15 21:30:46 +08:00
if ( fd < 0 )
{
debug ( 0 , L " Called close on invalid file descriptor " ) ;
return ;
}
2011-12-27 11:18:46 +08:00
2005-09-23 21:10:31 +08:00
while ( close ( fd ) = = - 1 )
{
if ( errno ! = EINTR )
{
debug ( 1 , FD_ERROR , fd ) ;
wperror ( L " close " ) ;
2006-06-21 17:54:30 +08:00
break ;
2005-09-23 21:10:31 +08:00
}
}
2011-12-27 11:18:46 +08:00
2012-02-09 14:56:42 +08:00
/* Maybe remove this form our set of open fds */
2012-02-10 23:55:06 +08:00
open_fds . erase ( std : : remove ( open_fds . begin ( ) , open_fds . end ( ) , fd ) , open_fds . end ( ) ) ;
2005-10-03 21:09:37 +08:00
}
2005-10-08 19:20:51 +08:00
int exec_pipe ( int fd [ 2 ] )
2005-10-03 21:09:37 +08:00
{
2005-10-08 19:20:51 +08:00
int res ;
2011-12-27 11:18:46 +08:00
2005-10-08 19:20:51 +08:00
while ( ( res = pipe ( fd ) ) )
{
if ( errno ! = EINTR )
{
wperror ( L " pipe " ) ;
return res ;
}
2011-12-27 11:18:46 +08:00
}
2005-11-02 23:41:59 +08:00
debug ( 4 , L " Created pipe using fds %d and %d " , fd [ 0 ] , fd [ 1 ] ) ;
2011-12-27 11:18:46 +08:00
2012-02-09 14:56:42 +08:00
open_fds . push_back ( fd [ 0 ] ) ;
open_fds . push_back ( fd [ 1 ] ) ;
2011-12-27 11:18:46 +08:00
2005-10-03 21:09:37 +08:00
return res ;
}
/**
Check if the specified fd is used as a part of a pipeline in the
specidied set of IO redirections .
\ param fd the fd to search for
\ param io the set of io redirections to search in
*/
static int use_fd_in_pipe ( int fd , io_data_t * io )
2011-12-27 11:18:46 +08:00
{
2005-10-03 21:09:37 +08:00
if ( ! io )
return 0 ;
2011-12-27 11:18:46 +08:00
if ( ( io - > io_mode = = IO_BUFFER ) | |
2005-10-07 22:08:57 +08:00
( io - > io_mode = = IO_PIPE ) )
2005-10-03 21:09:37 +08:00
{
2005-10-12 03:31:16 +08:00
if ( io - > param1 . pipe_fd [ 0 ] = = fd | |
io - > param1 . pipe_fd [ 1 ] = = fd )
2005-10-03 21:09:37 +08:00
return 1 ;
}
2011-12-27 11:18:46 +08:00
2005-10-03 21:09:37 +08:00
return use_fd_in_pipe ( fd , io - > next ) ;
}
/**
Close all fds in open_fds , except for those that are mentioned in
2005-10-21 19:59:45 +08:00
the redirection list io . This should make sure that there are no
stray opened file descriptors in the child .
2011-12-27 11:18:46 +08:00
2006-05-18 21:00:39 +08:00
\ param io the list of io redirections for this job . Pipes mentioned
here should not be closed .
2005-10-03 21:09:37 +08:00
*/
static void close_unused_internal_pipes ( io_data_t * io )
{
2012-02-09 14:56:42 +08:00
/* A call to exec_close will modify open_fds, so be careful how we walk */
for ( size_t i = 0 ; i < open_fds . size ( ) ; i + + ) {
int fd = open_fds . at ( i ) ;
if ( ! use_fd_in_pipe ( fd , io ) )
{
debug ( 4 , L " Close fd %d, used in other context " , fd ) ;
exec_close ( fd ) ;
i - - ;
}
}
2005-10-03 21:09:37 +08:00
}
2005-09-20 21:26:39 +08:00
/**
2011-12-27 11:18:46 +08:00
Make sure the fd used by this redirection is not used by i . e . a pipe .
2005-09-20 21:26:39 +08:00
*/
void free_fd ( io_data_t * io , int fd )
{
if ( ! io )
return ;
2011-12-27 11:18:46 +08:00
2007-01-07 22:06:46 +08:00
if ( ( io - > io_mode = = IO_PIPE ) | | ( io - > io_mode = = IO_BUFFER ) )
2005-09-20 21:26:39 +08:00
{
int i ;
for ( i = 0 ; i < 2 ; i + + )
{
2005-10-12 03:31:16 +08:00
if ( io - > param1 . pipe_fd [ i ] = = fd )
2005-09-20 21:26:39 +08:00
{
while ( 1 )
{
2005-10-12 03:31:16 +08:00
if ( ( io - > param1 . pipe_fd [ i ] = dup ( fd ) ) = = - 1 )
2005-09-20 21:26:39 +08:00
{
2007-01-07 22:06:46 +08:00
if ( errno ! = EINTR )
2005-09-20 21:26:39 +08:00
{
2011-12-27 11:18:46 +08:00
debug ( 1 ,
2005-09-20 21:26:39 +08:00
FD_ERROR ,
2011-12-27 11:18:46 +08:00
fd ) ;
2005-09-20 21:26:39 +08:00
wperror ( L " dup " ) ;
2007-01-21 23:03:41 +08:00
FATAL_EXIT ( ) ;
2005-09-20 21:26:39 +08:00
}
}
else
2007-01-07 22:06:46 +08:00
{
2005-09-20 21:26:39 +08:00
break ;
2007-01-07 22:06:46 +08:00
}
2005-09-20 21:26:39 +08:00
}
}
}
}
2007-01-07 22:06:46 +08:00
free_fd ( io - > next , fd ) ;
2005-09-20 21:26:39 +08:00
}
2005-10-21 19:59:45 +08:00
/**
Set up a childs io redirections . Should only be called by
setup_child_process ( ) . Does the following : First it closes any open
file descriptors not related to the child by calling
close_unused_internal_pipes ( ) and closing the universal variable
server file descriptor . It then goes on to perform all the
redirections described by \ c io .
\ param io the list of IO redirections for the child
2006-01-16 06:41:48 +08:00
2006-02-04 05:50:31 +08:00
\ return 0 on sucess , - 1 on failiure
2005-10-21 19:59:45 +08:00
*/
2007-01-21 23:19:43 +08:00
static int handle_child_io ( io_data_t * io )
2005-09-20 21:26:39 +08:00
{
2005-10-03 21:09:37 +08:00
close_unused_internal_pipes ( io ) ;
2005-09-20 21:26:39 +08:00
for ( ; io ; io = io - > next )
{
int tmp ;
2005-10-12 03:31:16 +08:00
if ( io - > io_mode = = IO_FD & & io - > fd = = io - > param1 . old_fd )
2005-09-20 21:26:39 +08:00
{
continue ;
}
if ( io - > fd > 2 )
{
/*
2011-12-27 11:18:46 +08:00
Make sure the fd used by this redirection is not used by e . g . a pipe .
2005-09-20 21:26:39 +08:00
*/
free_fd ( io , io - > fd ) ;
}
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
switch ( io - > io_mode )
{
case IO_CLOSE :
2007-01-21 23:01:14 +08:00
{
2006-06-21 17:54:30 +08:00
if ( close ( io - > fd ) )
{
debug ( 0 , _ ( L " Failed to close file descriptor %d " ) , io - > fd ) ;
wperror ( L " close " ) ;
}
2005-09-20 21:26:39 +08:00
break ;
2007-01-21 23:01:14 +08:00
}
2005-09-20 21:26:39 +08:00
case IO_FILE :
2005-11-29 18:12:06 +08:00
{
2012-02-22 11:33:11 +08:00
if ( ( tmp = wopen ( io - > filename ,
2007-10-27 02:42:32 +08:00
io - > param2 . flags , OPEN_MASK ) ) = = - 1 )
2005-09-20 21:26:39 +08:00
{
2007-10-27 02:42:32 +08:00
if ( ( io - > param2 . flags & O_EXCL ) & &
( errno = = EEXIST ) )
{
2011-12-27 11:18:46 +08:00
debug ( 1 ,
2007-10-27 02:42:32 +08:00
NOCLOB_ERROR ,
2012-02-22 11:33:11 +08:00
io - > filename . c_str ( ) ) ;
2007-10-27 02:42:32 +08:00
}
else
{
2011-12-27 11:18:46 +08:00
debug ( 1 ,
2007-10-27 02:42:32 +08:00
FILE_ERROR ,
2012-02-22 11:33:11 +08:00
io - > filename . c_str ( ) ) ;
2011-12-27 11:18:46 +08:00
2007-10-27 02:42:32 +08:00
wperror ( L " open " ) ;
}
2011-12-27 11:18:46 +08:00
2007-01-21 23:19:43 +08:00
return - 1 ;
}
2005-09-20 21:26:39 +08:00
else if ( tmp ! = io - > fd )
{
2006-06-21 17:54:30 +08:00
/*
This call will sometimes fail , but that is ok ,
this is just a precausion .
*/
2005-11-29 18:12:06 +08:00
close ( io - > fd ) ;
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
if ( dup2 ( tmp , io - > fd ) = = - 1 )
{
2011-12-27 11:18:46 +08:00
debug ( 1 ,
2005-09-20 21:26:39 +08:00
FD_ERROR ,
io - > fd ) ;
wperror ( L " dup2 " ) ;
2007-01-21 23:19:43 +08:00
return - 1 ;
2005-09-20 21:26:39 +08:00
}
2005-10-08 19:20:51 +08:00
exec_close ( tmp ) ;
2011-12-27 11:18:46 +08:00
}
2005-09-20 21:26:39 +08:00
break ;
2005-11-29 18:12:06 +08:00
}
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
case IO_FD :
2005-11-29 18:12:06 +08:00
{
2006-06-21 17:54:30 +08:00
/*
This call will sometimes fail , but that is ok ,
this is just a precausion .
*/
2005-11-29 18:12:06 +08:00
close ( io - > fd ) ;
2006-01-16 06:41:48 +08:00
2005-10-12 03:31:16 +08:00
if ( dup2 ( io - > param1 . old_fd , io - > fd ) = = - 1 )
2005-09-20 21:26:39 +08:00
{
2011-12-27 11:18:46 +08:00
debug ( 1 ,
2005-09-20 21:26:39 +08:00
FD_ERROR ,
io - > fd ) ;
wperror ( L " dup2 " ) ;
2007-01-21 23:19:43 +08:00
return - 1 ;
2005-09-20 21:26:39 +08:00
}
break ;
2005-11-29 18:12:06 +08:00
}
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
case IO_BUFFER :
case IO_PIPE :
{
2007-01-07 22:10:52 +08:00
int write_pipe ;
2011-12-27 11:18:46 +08:00
2007-01-07 22:10:52 +08:00
write_pipe = ! io - > is_input ;
/*
debug ( 0 ,
2011-12-27 11:18:46 +08:00
L " %ls %ls on fd %d (%d %d) " ,
write_pipe ? L " write " : L " read " ,
2007-01-07 22:10:52 +08:00
( io - > io_mode = = IO_BUFFER ) ? L " buffer " : L " pipe " ,
io - > fd ,
io - > param1 . pipe_fd [ 0 ] ,
io - > param1 . pipe_fd [ 1 ] ) ;
*/
if ( dup2 ( io - > param1 . pipe_fd [ write_pipe ] , io - > fd ) ! = io - > fd )
2005-09-20 21:26:39 +08:00
{
debug ( 1 , PIPE_ERROR ) ;
wperror ( L " dup2 " ) ;
2007-01-21 23:19:43 +08:00
return - 1 ;
2005-09-20 21:26:39 +08:00
}
2011-12-27 11:18:46 +08:00
if ( write_pipe )
2005-09-20 21:26:39 +08:00
{
2005-10-12 03:31:16 +08:00
exec_close ( io - > param1 . pipe_fd [ 0 ] ) ;
exec_close ( io - > param1 . pipe_fd [ 1 ] ) ;
2005-09-20 21:26:39 +08:00
}
else
2006-01-16 06:41:48 +08:00
{
2005-10-12 03:31:16 +08:00
exec_close ( io - > param1 . pipe_fd [ 0 ] ) ;
2006-01-16 06:41:48 +08:00
}
2005-09-20 21:26:39 +08:00
break ;
}
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
}
}
2006-01-16 06:41:48 +08:00
2006-02-04 05:50:31 +08:00
return 0 ;
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
}
2005-10-09 19:48:16 +08:00
/**
Initialize a new child process . This should be called right away
2006-11-15 21:30:46 +08:00
after forking in the child process . If job control is enabled for
this job , the process is put in the process group of the job , all
signal handlers are reset , signals are unblocked ( this function may
only be called inside the exec function , which blocks all signals ) ,
and all IO redirections and other file descriptor actions are
performed .
2006-01-16 06:41:48 +08:00
\ param j the job to set up the IO for
2006-01-24 04:40:14 +08:00
\ param p the child process to set up
2006-01-16 06:41:48 +08:00
2006-11-15 21:30:46 +08:00
\ return 0 on sucess , - 1 on failiure . When this function returns ,
signals are always unblocked . On failiure , signal handlers , io
redirections and process group of the process is undefined .
2005-10-09 19:48:16 +08:00
*/
2006-01-16 08:15:56 +08:00
static int setup_child_process ( job_t * j , process_t * p )
2005-09-20 21:26:39 +08:00
{
2006-02-04 05:50:31 +08:00
int res = 0 ;
2011-12-27 11:18:46 +08:00
2006-02-04 05:50:31 +08:00
if ( p )
{
2006-02-04 19:33:20 +08:00
res = set_child_group ( j , p , 1 ) ;
2006-02-01 20:27:15 +08:00
}
2011-12-27 11:18:46 +08:00
if ( ! res )
2006-02-01 20:27:15 +08:00
{
2007-01-21 23:19:43 +08:00
res = handle_child_io ( j - > io ) ;
if ( p ! = 0 & & res )
{
exit ( 1 ) ;
}
2005-09-20 21:26:39 +08:00
}
2011-12-27 11:18:46 +08:00
2006-01-16 06:41:48 +08:00
/* Set the handling for job control signals back to the default. */
2006-02-04 05:50:31 +08:00
if ( ! res )
2006-01-16 06:41:48 +08:00
{
signal_reset_handlers ( ) ;
}
2011-12-27 11:18:46 +08:00
2005-10-14 19:40:33 +08:00
/* Remove all signal blocks */
2011-12-27 11:18:46 +08:00
signal_unblock ( ) ;
2006-01-16 06:41:48 +08:00
return res ;
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
}
2008-01-16 09:04:54 +08:00
/**
2012-02-23 04:00:02 +08:00
Returns the interpreter for the specified script . Returns false if file
is not a script with a shebang .
2008-01-16 09:04:54 +08:00
*/
2012-02-23 04:00:02 +08:00
static bool get_interpreter ( const wcstring & file , wcstring & interpreter )
2008-01-16 09:04:54 +08:00
{
2012-02-23 04:00:02 +08:00
wcstring res ;
2008-01-16 09:04:54 +08:00
FILE * fp = wfopen ( file , " r " ) ;
if ( fp )
{
while ( 1 )
{
wint_t ch = getwc ( fp ) ;
if ( ch = = WEOF )
break ;
if ( ch = = L ' \n ' )
break ;
2012-02-23 04:00:02 +08:00
res . push_back ( ch ) ;
2008-01-16 09:04:54 +08:00
}
2012-02-23 04:00:02 +08:00
fclose ( fp ) ;
2008-01-16 09:04:54 +08:00
}
2011-12-27 11:18:46 +08:00
2012-02-23 04:00:02 +08:00
if ( string_prefixes_string ( L " #! / " , res ) ) {
interpreter = 3 + res . c_str ( ) ;
return true ;
} else if ( string_prefixes_string ( L " #!/ " , res ) ) {
interpreter = 2 + res . c_str ( ) ;
return true ;
} else {
return false ;
}
2008-01-16 09:04:54 +08:00
}
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
/**
This function is executed by the child process created by a call to
2005-10-09 19:48:16 +08:00
fork ( ) . It should be called after \ c setup_child_process . It calls
execve to replace the fish process image with the command specified
in \ c p . It never returns .
2005-09-20 21:26:39 +08:00
*/
static void launch_process ( process_t * p )
{
2006-12-12 03:03:08 +08:00
FILE * f ;
2007-01-07 22:09:18 +08:00
int err ;
2011-12-27 11:18:46 +08:00
2006-12-12 03:03:08 +08:00
// debug( 1, L"exec '%ls'", p->argv[0] );
2006-12-09 06:04:28 +08:00
2012-01-30 14:06:58 +08:00
char * * argv = wcsv2strv ( p - > get_argv ( ) ) ;
2007-10-15 17:36:15 +08:00
char * * envv = env_export_arr ( 0 ) ;
2011-12-27 11:18:46 +08:00
execve ( wcs2str ( p - > actual_cmd ) ,
2007-10-15 17:36:15 +08:00
argv ,
envv ) ;
2011-12-27 11:18:46 +08:00
2007-10-15 17:36:15 +08:00
err = errno ;
2011-12-27 11:18:46 +08:00
/*
2007-10-15 17:36:15 +08:00
Something went wrong with execve , check for a " : " , and run
/ bin / sh if encountered . This is a weird predecessor to the shebang
that is still sometimes used since it is supported on Windows .
2006-12-12 03:03:08 +08:00
*/
f = wfopen ( p - > actual_cmd , " r " ) ;
2007-10-15 17:36:15 +08:00
if ( f )
{
char begin [ 1 ] = { 0 } ;
2006-12-12 03:03:08 +08:00
size_t read ;
2011-12-27 11:18:46 +08:00
2006-12-12 03:03:08 +08:00
read = fread ( begin , 1 , 1 , f ) ;
fclose ( f ) ;
2011-12-27 11:18:46 +08:00
2007-10-15 17:36:15 +08:00
if ( ( read = = 1 ) & & ( begin [ 0 ] = = ' : ' ) )
{
2012-01-15 14:32:45 +08:00
2012-02-01 10:06:20 +08:00
wcstring_list_t argv ;
const wchar_t * sh_command = L " /bin/sh " ;
argv . push_back ( sh_command ) ;
argv . push_back ( p - > actual_cmd ) ;
for ( size_t i = 1 ; p - > argv ( i ) ! = NULL ; i + + ) {
argv . push_back ( p - > argv ( i ) ) ;
2007-10-15 17:36:15 +08:00
}
2011-12-27 11:18:46 +08:00
2012-02-01 10:06:20 +08:00
p - > set_argv ( argv ) ;
2012-01-30 15:22:42 +08:00
p - > actual_cmd = wcsdup ( sh_command ) ;
2008-01-04 09:56:31 +08:00
2012-02-01 10:06:20 +08:00
char * * res_real = wcsv2strv ( p - > get_argv ( ) ) ;
2011-12-27 11:18:46 +08:00
execve ( wcs2str ( p - > actual_cmd ) ,
2008-01-04 09:56:31 +08:00
res_real ,
2007-10-15 17:36:15 +08:00
envv ) ;
}
}
2011-12-27 11:18:46 +08:00
2007-10-15 17:36:15 +08:00
errno = err ;
2011-12-27 11:18:46 +08:00
debug ( 0 ,
2007-10-15 17:36:15 +08:00
_ ( L " Failed to execute process '%ls'. Reason: " ) ,
p - > actual_cmd ) ;
2011-12-27 11:18:46 +08:00
2007-10-15 17:36:15 +08:00
switch ( errno )
{
2011-12-27 11:18:46 +08:00
2007-10-15 17:36:15 +08:00
case E2BIG :
{
size_t sz = 0 ;
char * * p ;
2007-10-15 17:51:08 +08:00
2012-02-23 04:00:02 +08:00
wcstring sz1 , sz2 ;
2011-12-27 11:18:46 +08:00
2007-10-15 19:39:36 +08:00
long arg_max = - 1 ;
2012-02-23 04:00:02 +08:00
2007-10-15 17:36:15 +08:00
for ( p = argv ; * p ; p + + )
{
sz + = strlen ( * p ) + 1 ;
}
2011-12-27 11:18:46 +08:00
2007-10-15 17:36:15 +08:00
for ( p = envv ; * p ; p + + )
{
sz + = strlen ( * p ) + 1 ;
}
2011-12-27 11:18:46 +08:00
2012-02-23 04:00:02 +08:00
sz1 = format_size ( sz ) ;
2007-10-15 19:39:36 +08:00
arg_max = sysconf ( _SC_ARG_MAX ) ;
2011-12-27 11:18:46 +08:00
2007-10-15 19:39:36 +08:00
if ( arg_max > 0 )
{
2012-02-23 04:00:02 +08:00
sz2 = format_size ( arg_max ) ;
2011-12-27 11:18:46 +08:00
2007-10-15 19:39:36 +08:00
debug ( 0 ,
2008-01-16 09:04:54 +08:00
L " The total size of the argument and environment lists (%ls) exceeds the operating system limit of %ls. " ,
2012-02-23 04:00:02 +08:00
sz1 . c_str ( ) ,
sz2 . c_str ( ) ) ;
2007-10-15 19:39:36 +08:00
}
else
{
debug ( 0 ,
2008-01-16 09:04:54 +08:00
L " The total size of the argument and environment lists (%ls) exceeds the operating system limit. " ,
2012-02-23 04:00:02 +08:00
sz1 . c_str ( ) ) ;
2007-10-15 19:39:36 +08:00
}
2011-12-27 11:18:46 +08:00
debug ( 0 ,
2012-02-23 04:00:02 +08:00
L " Try running the command again with fewer arguments. " ) ;
2008-01-09 03:31:45 +08:00
exit ( STATUS_EXEC_FAIL ) ;
2011-12-27 11:18:46 +08:00
2007-10-15 17:36:15 +08:00
break ;
}
2007-01-07 22:09:18 +08:00
2008-01-16 09:04:54 +08:00
case ENOEXEC :
{
wperror ( L " exec " ) ;
2011-12-27 11:18:46 +08:00
2008-01-16 09:04:54 +08:00
debug ( 0 , L " The file '%ls' is marked as an executable but could not be run by the operating system. " , p - > actual_cmd ) ;
exit ( STATUS_EXEC_FAIL ) ;
}
case ENOENT :
{
2012-02-23 04:00:02 +08:00
wcstring interpreter ;
if ( get_interpreter ( p - > actual_cmd , interpreter ) & & waccess ( interpreter , X_OK ) )
2008-01-16 09:04:54 +08:00
{
2012-02-23 04:00:02 +08:00
debug ( 0 , L " The file '%ls' specified the interpreter '%ls', which is not an executable command. " , p - > actual_cmd , interpreter . c_str ( ) ) ;
2008-01-16 09:04:54 +08:00
}
else
{
debug ( 0 , L " The file '%ls' or a script or ELF interpreter does not exist, or a shared library needed for file or interpreter cannot be found. " , p - > actual_cmd ) ;
}
2011-12-27 11:18:46 +08:00
2008-01-16 09:04:54 +08:00
exit ( STATUS_EXEC_FAIL ) ;
}
case ENOMEM :
{
debug ( 0 , L " Out of memory " ) ;
exit ( STATUS_EXEC_FAIL ) ;
}
2007-10-15 17:36:15 +08:00
default :
{
2008-01-16 09:04:54 +08:00
wperror ( L " exec " ) ;
2011-12-27 11:18:46 +08:00
2008-01-16 09:04:54 +08:00
// debug(0, L"The file '%ls' is marked as an executable but could not be run by the operating system.", p->actual_cmd);
exit ( STATUS_EXEC_FAIL ) ;
2007-10-15 17:36:15 +08:00
}
}
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
}
/**
2005-10-03 21:09:37 +08:00
Check if the IO redirection chains contains redirections for the
specified file descriptor
2005-09-20 21:26:39 +08:00
*/
static int has_fd ( io_data_t * d , int fd )
{
return io_get ( d , fd ) ! = 0 ;
}
2006-01-11 22:40:20 +08:00
/**
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 ;
2011-12-27 11:18:46 +08:00
}
2012-02-22 11:33:11 +08:00
delete out ;
2006-01-11 22:40:20 +08:00
}
2005-09-20 21:26:39 +08:00
/**
2005-10-09 19:48:16 +08:00
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
2006-11-15 21:30:46 +08:00
repeatedly reopened for every command in the block , which would
reset the cursor position .
2006-01-11 22:40:20 +08:00
\ return the transmogrified chain on sucess , or 0 on failiure
2005-09-20 21:26:39 +08:00
*/
static io_data_t * io_transmogrify ( io_data_t * in )
{
if ( ! in )
return 0 ;
2011-12-27 11:18:46 +08:00
2012-02-22 11:33:11 +08:00
std : : auto_ptr < io_data_t > out ( new io_data_t ( ) ) ;
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
out - > fd = in - > fd ;
out - > io_mode = IO_FD ;
2005-10-12 03:31:16 +08:00
out - > param2 . close_old = 1 ;
2006-01-11 22:40:20 +08:00
out - > next = 0 ;
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
switch ( in - > io_mode )
{
/*
These redirections don ' t need transmogrification . They can be passed through .
*/
case IO_FD :
case IO_CLOSE :
case IO_BUFFER :
case IO_PIPE :
{
2012-02-22 11:33:11 +08:00
* out = * in ;
2005-09-20 21:26:39 +08:00
break ;
}
/*
Transmogrify file redirections
*/
case IO_FILE :
{
int fd ;
2011-12-27 11:18:46 +08:00
2012-02-22 11:33:11 +08:00
if ( ( fd = wopen ( in - > filename , in - > param2 . flags , OPEN_MASK ) ) = = - 1 )
2005-09-20 21:26:39 +08:00
{
2011-12-27 11:18:46 +08:00
debug ( 1 ,
2005-09-20 21:26:39 +08:00
FILE_ERROR ,
2012-02-22 11:33:11 +08:00
in - > filename . c_str ( ) ) ;
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
wperror ( L " open " ) ;
2012-02-22 11:33:11 +08:00
return NULL ;
2011-12-27 11:18:46 +08:00
}
2005-09-20 21:26:39 +08:00
2005-10-12 03:31:16 +08:00
out - > param1 . old_fd = fd ;
2005-09-20 21:26:39 +08:00
break ;
}
}
2011-12-27 11:18:46 +08:00
2006-01-11 22:40:20 +08:00
if ( in - > next )
{
out - > next = io_transmogrify ( in - > next ) ;
if ( ! out - > next )
{
2012-02-22 11:33:11 +08:00
io_untransmogrify ( in , out . release ( ) ) ;
return NULL ;
2006-01-11 22:40:20 +08:00
}
}
2011-12-27 11:18:46 +08:00
2012-02-22 11:33:11 +08:00
return out . release ( ) ;
2005-09-20 21:26:39 +08:00
}
/**
Morph an io redirection chain into redirections suitable for
passing to eval , call eval , and clean up morphed redirections .
\ param def the code to evaluate
\ param block_type the type of block to push on evaluation
\ param io the io redirections to be performed on this block
*/
2012-01-23 12:47:13 +08:00
static void internal_exec_helper ( parser_t & parser ,
const wchar_t * def ,
enum block_type_t block_type ,
io_data_t * io )
2005-09-20 21:26:39 +08:00
{
io_data_t * io_internal = io_transmogrify ( io ) ;
int is_block_old = is_block ;
is_block = 1 ;
2011-12-27 11:18:46 +08:00
2006-01-11 22:40:20 +08:00
/*
Did the transmogrification fail - if so , set error status and return
*/
if ( io & & ! io_internal )
{
2006-10-09 09:21:02 +08:00
proc_set_last_status ( STATUS_EXEC_FAIL ) ;
2006-01-11 22:40:20 +08:00
return ;
}
2011-12-27 11:18:46 +08:00
2006-01-11 22:40:20 +08:00
signal_unblock ( ) ;
2011-12-27 11:18:46 +08:00
2012-01-23 12:47:13 +08:00
parser . eval ( def , io_internal , block_type ) ;
2011-12-27 11:18:46 +08:00
2005-10-14 19:40:33 +08:00
signal_block ( ) ;
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
io_untransmogrify ( io , io_internal ) ;
2005-10-12 03:23:43 +08:00
job_reap ( 0 ) ;
2005-09-20 21:26:39 +08:00
is_block = is_block_old ;
}
2005-10-09 19:48:16 +08:00
/**
2006-02-04 19:33:20 +08:00
This function should be called by both the parent process and the
child right after fork ( ) has been called . If job control is
enabled , the child is put in the jobs group , and if the child is
also in the foreground , it is also given control of the
terminal . When called in the parent process , this function may
fail , since the child might have already finished and called
exit . The parent process may safely ignore the exit status of this
call .
2011-12-27 11:18:46 +08:00
Returns 0 on sucess , - 1 on failiure .
2005-09-20 21:26:39 +08:00
*/
2006-02-04 19:33:20 +08:00
static int set_child_group ( job_t * j , process_t * p , int print_errors )
2005-09-20 21:26:39 +08:00
{
2006-02-04 05:50:31 +08:00
int res = 0 ;
2011-12-27 11:18:46 +08:00
2006-10-26 04:47:59 +08:00
if ( job_get_flag ( j , JOB_CONTROL ) )
2005-09-20 21:26:39 +08:00
{
if ( ! j - > pgid )
{
j - > pgid = p - > pid ;
}
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
if ( setpgid ( p - > pid , j - > pgid ) )
2006-08-27 08:52:52 +08:00
{
2006-02-04 19:33:20 +08:00
if ( getpgid ( p - > pid ) ! = j - > pgid & & print_errors )
2005-09-20 21:26:39 +08:00
{
2011-12-27 11:18:46 +08:00
debug ( 1 ,
2007-09-09 06:24:53 +08:00
_ ( L " Could not send process %d, '%ls' in job %d, '%ls' from group %d to group %d " ) ,
p - > pid ,
2012-01-30 14:06:58 +08:00
p - > argv0 ( ) ,
2007-09-09 06:24:53 +08:00
j - > job_id ,
2012-01-30 14:06:58 +08:00
j - > command_cstr ( ) ,
2007-09-09 06:24:53 +08:00
getpgid ( p - > pid ) ,
j - > pgid ) ;
2005-09-20 21:26:39 +08:00
wperror ( L " setpgid " ) ;
2006-02-04 05:50:31 +08:00
res = - 1 ;
2005-09-20 21:26:39 +08:00
}
}
}
else
{
j - > pgid = getpid ( ) ;
}
2006-02-04 19:33:20 +08:00
2006-10-26 04:47:59 +08:00
if ( job_get_flag ( j , JOB_TERMINAL ) & & job_get_flag ( j , JOB_FOREGROUND ) )
2006-02-01 20:27:15 +08:00
{
2006-02-04 19:33:20 +08:00
if ( tcsetpgrp ( 0 , j - > pgid ) & & print_errors )
2006-02-01 20:27:15 +08:00
{
2011-12-27 11:18:46 +08:00
debug ( 1 , _ ( L " Could not send job %d ('%ls') to foreground " ) ,
j - > job_id ,
2012-01-30 14:06:58 +08:00
j - > command_cstr ( ) ) ;
2006-02-01 20:27:15 +08:00
wperror ( L " tcsetpgrp " ) ;
2006-02-04 05:50:31 +08:00
res = - 1 ;
2006-02-01 20:27:15 +08:00
}
}
2006-02-04 05:50:31 +08:00
return res ;
2005-09-20 21:26:39 +08:00
}
2006-11-15 21:30:46 +08:00
/**
This function is a wrapper around fork . If the fork calls fails
with EAGAIN , it is retried FORK_LAPS times , with a very slight
delay between each lap . If fork fails even then , the process will
exit with an error message .
*/
static pid_t exec_fork ( )
{
pid_t pid ;
struct timespec pollint ;
int i ;
2011-12-27 11:18:46 +08:00
2006-11-15 21:30:46 +08:00
for ( i = 0 ; i < FORK_LAPS ; i + + )
{
pid = fork ( ) ;
if ( pid > = 0 )
{
return pid ;
}
2011-12-27 11:18:46 +08:00
2006-11-15 21:30:46 +08:00
if ( errno ! = EAGAIN )
{
break ;
}
pollint . tv_sec = 0 ;
2007-01-21 23:20:26 +08:00
pollint . tv_nsec = FORK_SLEEP_TIME ;
2006-11-15 21:30:46 +08:00
/*
Don ' t sleep on the final lap - sleeping might change the
value of errno , which will break the error reporting below .
*/
if ( i ! = FORK_LAPS - 1 )
{
nanosleep ( & pollint , NULL ) ;
}
}
2011-12-27 11:18:46 +08:00
2006-11-15 21:30:46 +08:00
debug ( 0 , FORK_ERROR ) ;
wperror ( L " fork " ) ;
2007-01-21 23:03:41 +08:00
FATAL_EXIT ( ) ;
2006-11-15 21:30:46 +08:00
}
2005-09-20 21:26:39 +08:00
2008-01-14 00:47:47 +08:00
/**
Perform output from builtins
*/
2012-02-23 02:51:06 +08:00
static void do_builtin_io ( const wchar_t * out , const wchar_t * err )
2007-01-21 22:58:10 +08:00
{
if ( out )
{
if ( fwprintf ( stdout , L " %ls " , out ) = = - 1 | | fflush ( stdout ) = = EOF )
{
debug ( 0 , L " Error while writing to stdout " ) ;
wperror ( L " fwprintf " ) ;
show_stackframe ( ) ;
}
}
2011-12-27 11:18:46 +08:00
2007-01-21 22:58:10 +08:00
if ( err )
{
if ( fwprintf ( stderr , L " %ls " , err ) = = - 1 | | fflush ( stderr ) = = EOF )
{
/*
Can ' t really show any error message here , since stderr is
2007-01-21 23:22:42 +08:00
dead .
2007-01-21 22:58:10 +08:00
*/
}
}
2011-12-27 11:18:46 +08:00
}
2007-01-21 22:58:10 +08:00
2012-01-23 12:47:13 +08:00
void exec ( parser_t & parser , job_t * j )
2005-09-20 21:26:39 +08:00
{
process_t * p ;
pid_t pid ;
int mypipe [ 2 ] ;
2011-12-27 11:18:46 +08:00
sigset_t chldset ;
2005-09-20 21:26:39 +08:00
int skip_fork ;
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
io_data_t pipe_read , pipe_write ;
io_data_t * tmp ;
io_data_t * io_buffer = 0 ;
2005-10-17 21:24:12 +08:00
2005-10-21 07:56:51 +08:00
/*
2006-11-15 21:30:46 +08:00
Set to 1 if something goes wrong while exec : ing the job , in
which case the cleanup code will kick in .
2005-10-21 07:56:51 +08:00
*/
int exec_error = 0 ;
2006-08-27 08:52:52 +08:00
int needs_keepalive = 0 ;
process_t keepalive ;
2011-12-27 11:18:46 +08:00
2006-08-27 08:52:52 +08:00
2006-06-21 08:48:36 +08:00
CHECK ( j , ) ;
2006-10-30 05:09:11 +08:00
CHECK_BLOCK ( ) ;
2011-12-27 11:18:46 +08:00
2006-03-18 09:04:59 +08:00
if ( no_exec )
return ;
2011-12-27 11:18:46 +08:00
2006-03-18 09:04:59 +08:00
sigemptyset ( & chldset ) ;
sigaddset ( & chldset , SIGCHLD ) ;
2011-12-27 11:18:46 +08:00
2012-01-30 14:06:58 +08:00
debug ( 4 , L " Exec job '%ls' with id %d " , j - > command_cstr ( ) , j - > job_id ) ;
2011-12-27 11:18:46 +08:00
2012-01-23 12:47:13 +08:00
if ( parser . block_io )
2006-08-13 09:38:03 +08:00
{
if ( j - > io )
2007-01-21 23:01:14 +08:00
{
2012-02-10 10:43:36 +08:00
j - > io = io_add ( io_duplicate ( parser . block_io ) , j - > io ) ;
2007-01-21 23:01:14 +08:00
}
2006-08-13 09:38:03 +08:00
else
2007-01-21 23:01:14 +08:00
{
2012-02-10 10:43:36 +08:00
j - > io = io_duplicate ( parser . block_io ) ;
2007-01-21 23:01:14 +08:00
}
2006-08-13 09:38:03 +08:00
}
2011-12-27 11:18:46 +08:00
2007-01-07 22:10:52 +08:00
io_data_t * input_redirect ;
for ( input_redirect = j - > io ; input_redirect ; input_redirect = input_redirect - > next )
2006-08-13 09:38:03 +08:00
{
2011-12-27 11:18:46 +08:00
if ( ( input_redirect - > io_mode = = IO_BUFFER ) & &
2007-01-07 22:10:52 +08:00
input_redirect - > is_input )
{
/*
Input redirection - create a new gobetween process to take
care of buffering
*/
2012-01-30 14:06:58 +08:00
process_t * fake = new process_t ( ) ;
fake - > type = INTERNAL_BUFFER ;
2007-01-07 22:10:52 +08:00
fake - > pipe_write_fd = 1 ;
j - > first_process - > pipe_read_fd = input_redirect - > fd ;
fake - > next = j - > first_process ;
j - > first_process = fake ;
break ;
}
2006-08-13 09:38:03 +08:00
}
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
if ( j - > first_process - > type = = INTERNAL_EXEC )
{
/*
Do a regular launch - but without forking first . . .
*/
2005-10-14 19:40:33 +08:00
signal_block ( ) ;
/*
2006-06-04 06:35:33 +08:00
setup_child_process makes sure signals are properly set
2006-02-05 21:12:53 +08:00
up . It will also call signal_unblock
2005-10-14 19:40:33 +08:00
*/
2006-02-04 05:50:31 +08:00
if ( ! setup_child_process ( j , 0 ) )
2006-01-16 06:41:48 +08:00
{
/*
2007-01-21 23:01:14 +08:00
launch_process _never_ returns
2006-01-16 06:41:48 +08:00
*/
launch_process ( j - > first_process ) ;
}
else
{
2006-10-26 04:47:59 +08:00
job_set_flag ( j , JOB_CONSTRUCTED , 1 ) ;
2006-01-16 06:41:48 +08:00
j - > first_process - > completed = 1 ;
return ;
}
2006-08-13 09:38:03 +08:00
2011-12-27 11:18:46 +08:00
}
2005-09-20 21:26:39 +08:00
pipe_read . fd = 0 ;
pipe_write . fd = 1 ;
pipe_read . io_mode = IO_PIPE ;
2005-10-12 03:31:16 +08:00
pipe_read . param1 . pipe_fd [ 0 ] = - 1 ;
pipe_read . param1 . pipe_fd [ 1 ] = - 1 ;
2007-01-07 22:10:52 +08:00
pipe_read . is_input = 1 ;
2005-09-20 21:26:39 +08:00
pipe_write . io_mode = IO_PIPE ;
2007-01-07 22:10:52 +08:00
pipe_write . is_input = 0 ;
2005-09-20 21:26:39 +08:00
pipe_read . next = 0 ;
pipe_write . next = 0 ;
2006-11-18 00:24:38 +08:00
pipe_write . param1 . pipe_fd [ 0 ] = pipe_write . param1 . pipe_fd [ 1 ] = - 1 ;
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
j - > io = io_add ( j - > io , & pipe_write ) ;
2011-12-27 11:18:46 +08:00
2005-10-14 19:40:33 +08:00
signal_block ( ) ;
2006-08-27 08:52:52 +08:00
/*
2007-09-24 16:18:23 +08:00
See if we need to create a group keepalive process . This is
a process that we create to make sure that the process group
doesn ' t die accidentally , and is often needed when a
builtin / block / function is inside a pipeline , since that
usually means we have to wait for one program to exit before
continuing in the pipeline , causing the group leader to
exit .
2006-08-27 08:52:52 +08:00
*/
2011-12-27 11:18:46 +08:00
2006-10-26 04:47:59 +08:00
if ( job_get_flag ( j , JOB_CONTROL ) )
2006-08-27 08:52:52 +08:00
{
for ( p = j - > first_process ; p ; p = p - > next )
{
2007-09-24 16:21:44 +08:00
if ( p - > type ! = EXTERNAL )
2006-08-27 08:52:52 +08:00
{
if ( p - > next )
{
needs_keepalive = 1 ;
break ;
}
2007-09-24 16:21:44 +08:00
if ( p ! = j - > first_process )
{
needs_keepalive = 1 ;
break ;
}
2011-12-27 11:18:46 +08:00
2006-08-27 08:52:52 +08:00
}
2011-12-27 11:18:46 +08:00
2006-08-27 08:52:52 +08:00
}
}
2011-12-27 11:18:46 +08:00
2006-08-27 08:52:52 +08:00
if ( needs_keepalive )
{
2006-11-15 21:30:46 +08:00
keepalive . pid = exec_fork ( ) ;
2006-08-27 08:52:52 +08:00
if ( keepalive . pid = = 0 )
{
keepalive . pid = getpid ( ) ;
set_child_group ( j , & keepalive , 1 ) ;
2011-12-27 11:18:46 +08:00
pause ( ) ;
2006-08-27 08:52:52 +08:00
exit ( 0 ) ;
}
else
{
2011-12-27 11:18:46 +08:00
set_child_group ( j , & keepalive , 0 ) ;
2006-08-27 08:52:52 +08:00
}
}
2011-12-27 11:18:46 +08:00
2005-10-21 19:59:45 +08:00
/*
This loop loops over every process_t in the job , starting it as
appropriate . This turns out to be rather complex , since a
process_t can be one of many rather different things .
2005-10-21 07:56:51 +08:00
2005-10-21 19:59:45 +08:00
The loop also has to handle pipelining between the jobs .
*/
2006-08-27 08:52:52 +08:00
2005-11-02 23:41:59 +08:00
for ( p = j - > first_process ; p ; p = p - > next )
2005-09-20 21:26:39 +08:00
{
mypipe [ 1 ] = - 1 ;
skip_fork = 0 ;
2011-12-27 11:18:46 +08:00
2007-01-07 22:10:52 +08:00
pipe_write . fd = p - > pipe_write_fd ;
pipe_read . fd = p - > pipe_read_fd ;
// debug( 0, L"Pipe created from fd %d to fd %d", pipe_write.fd, pipe_read.fd );
2011-12-27 11:18:46 +08:00
2005-10-07 22:08:57 +08:00
2011-12-27 11:18:46 +08:00
/*
2006-11-15 21:30:46 +08:00
This call is used so the global environment variable array
is regenerated , if needed , before the fork . That way , we
avoid a lot of duplicate work where EVERY child would need
to generate it , since that result would not get written
back to the parent . This call could be safely removed , but
it would result in slightly lower performance - at least on
uniprocessor systems .
2005-10-03 21:09:37 +08:00
*/
2005-09-23 04:16:52 +08:00
if ( p - > type = = EXTERNAL )
env_export_arr ( 1 ) ;
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
/*
2011-12-27 11:18:46 +08:00
Set up fd : s that will be used in the pipe
2005-09-20 21:26:39 +08:00
*/
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
if ( p = = j - > first_process - > next )
{
j - > io = io_add ( j - > io , & pipe_read ) ;
}
2011-12-27 11:18:46 +08:00
2005-11-02 23:41:59 +08:00
if ( p - > next )
2005-09-20 21:26:39 +08:00
{
2005-11-02 23:41:59 +08:00
// debug( 1, L"%ls|%ls" , p->argv[0], p->next->argv[0]);
2011-12-27 11:18:46 +08:00
2005-11-02 23:41:59 +08:00
if ( exec_pipe ( mypipe ) = = - 1 )
2005-09-20 21:26:39 +08:00
{
debug ( 1 , PIPE_ERROR ) ;
wperror ( L " pipe " ) ;
2005-10-21 07:56:51 +08:00
exec_error = 1 ;
break ;
2005-09-20 21:26:39 +08:00
}
2005-10-12 03:31:16 +08:00
memcpy ( pipe_write . param1 . pipe_fd , mypipe , sizeof ( int ) * 2 ) ;
2005-09-20 21:26:39 +08:00
}
else
{
/*
This is the last element of the pipeline .
Remove the io redirection for pipe output .
*/
j - > io = io_remove ( j - > io , & pipe_write ) ;
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
}
switch ( p - > type )
{
case INTERNAL_FUNCTION :
{
2006-10-30 05:09:11 +08:00
wchar_t * def = 0 ;
2007-04-23 06:10:33 +08:00
int shadows ;
2011-12-27 11:18:46 +08:00
2006-10-30 05:09:11 +08:00
2006-11-18 00:24:38 +08:00
/*
Calls to function_get_definition might need to
source a file as a part of autoloading , hence there
must be no blocks .
*/
2006-10-30 05:09:11 +08:00
signal_unblock ( ) ;
2012-01-31 03:15:06 +08:00
const wchar_t * orig_def = function_get_definition ( p - > argv0 ( ) ) ;
2012-01-14 15:44:18 +08:00
// function_get_named_arguments may trigger autoload, which deallocates the orig_def.
// We should make function_get_definition return a wcstring (but how to handle NULL...)
if ( orig_def )
2012-01-31 03:15:06 +08:00
def = wcsdup ( orig_def ) ;
2012-01-14 15:44:18 +08:00
2012-01-30 14:06:58 +08:00
wcstring_list_t named_arguments = function_get_named_arguments ( p - > argv0 ( ) ) ;
shadows = function_get_shadows ( p - > argv0 ( ) ) ;
2007-04-17 04:06:11 +08:00
2006-10-30 05:09:11 +08:00
signal_block ( ) ;
2011-12-27 11:18:46 +08:00
2012-01-31 03:15:06 +08:00
if ( def = = NULL )
2005-09-20 21:26:39 +08:00
{
2012-01-30 14:06:58 +08:00
debug ( 0 , _ ( L " Unknown function '%ls' " ) , p - > argv0 ( ) ) ;
2005-09-20 21:26:39 +08:00
break ;
}
2012-01-17 04:10:08 +08:00
parser . push_block ( shadows ? FUNCTION_CALL : FUNCTION_CALL_NO_SHADOW ) ;
2011-12-27 11:18:46 +08:00
2012-02-08 09:06:45 +08:00
parser . current_block - > state2 < process_t * > ( ) = p ;
parser . current_block - > state1 < wcstring > ( ) = p - > argv0 ( ) ;
2011-12-27 11:18:46 +08:00
2007-10-15 21:20:06 +08:00
/*
set_argv might trigger an event
handler , hence we need to unblock
signals .
*/
signal_unblock ( ) ;
2012-01-30 14:06:58 +08:00
parse_util_set_argv ( p - > get_argv ( ) + 1 , named_arguments ) ;
2007-10-15 21:20:06 +08:00
signal_block ( ) ;
2011-12-27 11:18:46 +08:00
2012-01-30 14:06:58 +08:00
parser . forbid_function ( p - > argv0 ( ) ) ;
2005-09-20 21:26:39 +08:00
if ( p - > next )
{
2011-12-27 11:18:46 +08:00
io_buffer = io_buffer_create ( 0 ) ;
2005-09-20 21:26:39 +08:00
j - > io = io_add ( j - > io , io_buffer ) ;
}
2011-12-27 11:18:46 +08:00
2012-01-23 12:47:13 +08:00
internal_exec_helper ( parser , def , TOP , j - > io ) ;
2011-12-27 11:18:46 +08:00
2012-01-23 12:47:13 +08:00
parser . allow_function ( ) ;
2012-01-17 04:10:08 +08:00
parser . pop_block ( ) ;
2012-01-31 03:15:06 +08:00
free ( def ) ;
2011-12-27 11:18:46 +08:00
break ;
2005-09-20 21:26:39 +08:00
}
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
case INTERNAL_BLOCK :
{
if ( p - > next )
{
2011-12-27 11:18:46 +08:00
io_buffer = io_buffer_create ( 0 ) ;
2005-09-20 21:26:39 +08:00
j - > io = io_add ( j - > io , io_buffer ) ;
}
2012-01-23 12:47:13 +08:00
2012-01-30 14:06:58 +08:00
internal_exec_helper ( parser , p - > argv0 ( ) , TOP , j - > io ) ;
2005-09-20 21:26:39 +08:00
break ;
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
}
2006-08-13 09:38:03 +08:00
2005-09-20 21:26:39 +08:00
case INTERNAL_BUILTIN :
{
int builtin_stdin = 0 ;
int fg ;
int close_stdin = 0 ;
2006-11-15 21:30:46 +08:00
/*
If this is the first process , check the io
redirections and see where we should be reading
from .
*/
2005-09-20 21:26:39 +08:00
if ( p = = j - > first_process )
{
io_data_t * in = io_get ( j - > io , 0 ) ;
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
if ( in )
{
switch ( in - > io_mode )
{
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
case IO_FD :
{
2005-10-12 03:31:16 +08:00
builtin_stdin = in - > param1 . old_fd ;
2005-09-20 21:26:39 +08:00
break ;
}
case IO_PIPE :
{
2005-10-12 03:31:16 +08:00
builtin_stdin = in - > param1 . pipe_fd [ 0 ] ;
2005-09-20 21:26:39 +08:00
break ;
}
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
case IO_FILE :
{
2012-02-22 11:33:11 +08:00
builtin_stdin = wopen ( in - > filename ,
2006-11-15 21:30:46 +08:00
in - > param2 . flags , OPEN_MASK ) ;
2005-10-21 07:56:51 +08:00
if ( builtin_stdin = = - 1 )
2005-09-20 21:26:39 +08:00
{
2011-12-27 11:18:46 +08:00
debug ( 1 ,
2005-10-21 07:56:51 +08:00
FILE_ERROR ,
2012-02-22 11:33:11 +08:00
in - > filename . c_str ( ) ) ;
2005-10-21 07:56:51 +08:00
wperror ( L " open " ) ;
2005-09-20 21:26:39 +08:00
}
else
{
close_stdin = 1 ;
}
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
break ;
}
2011-12-27 11:18:46 +08:00
2007-10-05 23:01:06 +08:00
case IO_CLOSE :
{
/*
FIXME :
When
requesting
that
stdin
be
closed ,
we
really
don ' t
do
anything . How
should
this
be
handled ?
*/
builtin_stdin = - 1 ;
2011-12-27 11:18:46 +08:00
2007-10-05 23:01:06 +08:00
break ;
}
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
default :
{
2005-10-21 07:56:51 +08:00
builtin_stdin = - 1 ;
2011-12-27 11:18:46 +08:00
debug ( 1 ,
2006-01-04 20:51:02 +08:00
_ ( L " Unknown input redirection type %d " ) ,
2005-09-20 21:26:39 +08:00
in - > io_mode ) ;
break ;
}
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
}
}
}
else
{
2005-10-12 03:31:16 +08:00
builtin_stdin = pipe_read . param1 . pipe_fd [ 0 ] ;
2005-09-20 21:26:39 +08:00
}
2005-10-21 07:56:51 +08:00
if ( builtin_stdin = = - 1 )
{
exec_error = 1 ;
break ;
}
2006-06-04 06:35:33 +08:00
else
{
2006-11-18 00:24:38 +08:00
int old_out = builtin_out_redirect ;
int old_err = builtin_err_redirect ;
2011-12-27 11:18:46 +08:00
/*
2006-11-15 21:30:46 +08:00
Since this may be the foreground job , and since
a builtin may execute another foreground job ,
we need to pretend to suspend this job while
running the builtin , in order to avoid a
situation where two jobs are running at once .
The reason this is done here , and not by the
relevant builtins , is that this way , the
builtin does not need to know what job it is
part of . It could probably figure that out by
walking the job list , but it seems more robust
to make exec handle things .
2006-06-04 06:35:33 +08:00
*/
2011-12-27 11:18:46 +08:00
2012-01-23 12:47:13 +08:00
builtin_push_io ( parser , builtin_stdin ) ;
2011-12-27 11:18:46 +08:00
2006-06-04 06:35:33 +08:00
builtin_out_redirect = has_fd ( j - > io , 1 ) ;
2011-12-27 11:18:46 +08:00
builtin_err_redirect = has_fd ( j - > io , 2 ) ;
2006-11-18 00:24:38 +08:00
2006-10-26 04:47:59 +08:00
fg = job_get_flag ( j , JOB_FOREGROUND ) ;
job_set_flag ( j , JOB_FOREGROUND , 0 ) ;
2011-12-27 11:18:46 +08:00
2006-06-04 06:35:33 +08:00
signal_unblock ( ) ;
2011-12-27 11:18:46 +08:00
2012-01-30 14:06:58 +08:00
p - > status = builtin_run ( parser , p - > get_argv ( ) , j - > io ) ;
2011-12-27 11:18:46 +08:00
2006-11-18 00:24:38 +08:00
builtin_out_redirect = old_out ;
builtin_err_redirect = old_err ;
2011-12-27 11:18:46 +08:00
2006-06-04 06:35:33 +08:00
signal_block ( ) ;
2011-12-27 11:18:46 +08:00
2006-06-04 06:35:33 +08:00
/*
Restore the fg flag , which is temporarily set to
false during builtin execution so as not to confuse
some job - handling builtins .
*/
2006-10-26 04:47:59 +08:00
job_set_flag ( j , JOB_FOREGROUND , fg ) ;
2006-06-04 06:35:33 +08:00
}
2011-12-27 11:18:46 +08:00
2006-11-15 21:30:46 +08:00
/*
If stdin has been redirected , close the redirection
stream .
*/
2005-09-20 21:26:39 +08:00
if ( close_stdin )
{
2005-10-08 19:20:51 +08:00
exec_close ( builtin_stdin ) ;
2011-12-27 11:18:46 +08:00
}
break ;
2005-09-20 21:26:39 +08:00
}
}
2011-12-27 11:18:46 +08:00
2005-10-21 07:56:51 +08:00
if ( exec_error )
2007-01-21 23:01:14 +08:00
{
2005-10-21 07:56:51 +08:00
break ;
2007-01-21 23:01:14 +08:00
}
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
switch ( p - > type )
{
2006-08-13 09:38:03 +08:00
2005-09-20 21:26:39 +08:00
case INTERNAL_BLOCK :
case INTERNAL_FUNCTION :
{
int status = proc_get_last_status ( ) ;
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
/*
Handle output from a block or function . This usually
means do nothing , but in the case of pipes , we have
2005-11-30 03:50:30 +08:00
to buffer such io , since otherwise the internal pipe
2005-09-20 21:26:39 +08:00
buffer might overflow .
*/
2005-11-02 23:41:59 +08:00
if ( ! io_buffer )
2005-09-20 21:26:39 +08:00
{
2005-11-30 03:50:30 +08:00
/*
2006-01-30 06:04:14 +08:00
No buffer , so we exit directly . This means we
2005-11-30 03:50:30 +08:00
have to manually set the exit status .
*/
if ( p - > next = = 0 )
{
2006-10-26 04:47:59 +08:00
proc_set_last_status ( job_get_flag ( j , JOB_NEGATE ) ? ( ! status ) : status ) ;
2005-11-30 03:50:30 +08:00
}
2005-09-20 21:26:39 +08:00
p - > completed = 1 ;
break ;
}
j - > io = io_remove ( j - > io , io_buffer ) ;
2011-12-27 11:18:46 +08:00
2005-10-08 19:20:51 +08:00
io_buffer_read ( io_buffer ) ;
2011-12-27 11:18:46 +08:00
2005-10-12 03:31:16 +08:00
if ( io_buffer - > param2 . out_buffer - > used ! = 0 )
2005-09-20 21:26:39 +08:00
{
2006-11-15 21:30:46 +08:00
pid = exec_fork ( ) ;
2006-01-18 20:42:48 +08:00
2005-11-02 23:41:59 +08:00
if ( pid = = 0 )
2005-09-20 21:26:39 +08:00
{
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
/*
This is the child process . Write out the contents of the pipeline .
*/
p - > pid = getpid ( ) ;
2006-01-16 08:15:56 +08:00
setup_child_process ( j , p ) ;
2009-02-23 04:28:52 +08:00
2011-12-27 11:18:46 +08:00
exec_write_and_exit ( io_buffer - > fd ,
2009-02-23 04:28:52 +08:00
io_buffer - > param2 . out_buffer - > buff ,
io_buffer - > param2 . out_buffer - > used ,
status ) ;
2005-09-20 21:26:39 +08:00
}
else
{
2011-12-27 11:18:46 +08:00
/*
2005-09-20 21:26:39 +08:00
This is the parent process . Store away
2005-10-14 19:40:33 +08:00
information on the child , and possibly give
2005-09-20 21:26:39 +08:00
it control over the terminal .
*/
2011-12-27 11:18:46 +08:00
p - > pid = pid ;
2006-02-04 19:33:20 +08:00
set_child_group ( j , p , 0 ) ;
2011-12-27 11:18:46 +08:00
}
2005-09-20 21:26:39 +08:00
}
2006-01-30 06:04:14 +08:00
else
{
if ( p - > next = = 0 )
{
2006-10-26 04:47:59 +08:00
proc_set_last_status ( job_get_flag ( j , JOB_NEGATE ) ? ( ! status ) : status ) ;
2006-01-30 06:04:14 +08:00
}
p - > completed = 1 ;
}
2011-12-27 11:18:46 +08:00
2005-10-08 19:20:51 +08:00
io_buffer_destroy ( io_buffer ) ;
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
io_buffer = 0 ;
break ;
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
}
2006-08-13 09:38:03 +08:00
case INTERNAL_BUFFER :
{
2011-12-27 11:18:46 +08:00
2006-11-15 21:30:46 +08:00
pid = exec_fork ( ) ;
2011-12-27 11:18:46 +08:00
2006-08-13 09:38:03 +08:00
if ( pid = = 0 )
{
/*
2007-01-07 22:10:52 +08:00
This is the child process . Write out the
contents of the pipeline .
2006-08-13 09:38:03 +08:00
*/
p - > pid = getpid ( ) ;
setup_child_process ( j , p ) ;
2011-12-27 11:18:46 +08:00
2009-02-23 04:28:52 +08:00
exec_write_and_exit ( 1 ,
2011-12-27 11:18:46 +08:00
input_redirect - > param2 . out_buffer - > buff ,
2009-02-23 04:28:52 +08:00
input_redirect - > param2 . out_buffer - > used ,
0 ) ;
2006-08-13 09:38:03 +08:00
}
else
{
2011-12-27 11:18:46 +08:00
/*
2006-08-13 09:38:03 +08:00
This is the parent process . Store away
information on the child , and possibly give
it control over the terminal .
*/
2011-12-27 11:18:46 +08:00
p - > pid = pid ;
set_child_group ( j , p , 0 ) ;
}
2006-08-13 09:38:03 +08:00
2011-12-27 11:18:46 +08:00
break ;
2006-08-13 09:38:03 +08:00
}
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
case INTERNAL_BUILTIN :
{
2007-09-23 06:20:41 +08:00
int skip_fork ;
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
/*
2006-11-15 21:30:46 +08:00
Handle output from builtin commands . In the general
case , this means forking of a worker process , that
will write out the contents of the stdout and stderr
buffers to the correct file descriptor . Since
forking is expensive , fish tries to avoid it wehn
possible .
*/
/*
If a builtin didn ' t produce any output , and it is
not inside a pipeline , there is no need to fork
2005-09-20 21:26:39 +08:00
*/
skip_fork =
2012-02-23 02:51:06 +08:00
get_stdout_buffer ( ) . empty ( ) & &
get_stderr_buffer ( ) . empty ( ) & &
! p - > next ;
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
/*
2007-01-21 23:01:14 +08:00
If the output of a builtin is to be sent to an internal
2005-09-20 21:26:39 +08:00
buffer , there is no need to fork . This helps out the
performance quite a bit in complex completion code .
*/
2007-09-23 06:20:41 +08:00
io_data_t * io = io_get ( j - > io , 1 ) ;
2005-09-20 21:26:39 +08:00
int buffer_stdout = io & & io - > io_mode = = IO_BUFFER ;
2011-12-27 11:18:46 +08:00
2012-02-23 02:51:06 +08:00
if ( ( get_stderr_buffer ( ) . empty ( ) ) & &
2005-09-20 21:26:39 +08:00
( ! p - > next ) & &
2012-02-23 02:51:06 +08:00
( ! get_stdout_buffer ( ) . empty ( ) ) & &
2005-09-20 21:26:39 +08:00
( buffer_stdout ) )
{
2012-02-23 02:51:06 +08:00
std : : string res = wcs2string ( get_stdout_buffer ( ) ) ;
b_append ( io - > param2 . out_buffer , res . c_str ( ) , res . size ( ) ) ;
2005-09-20 21:26:39 +08:00
skip_fork = 1 ;
}
2007-03-25 06:34:30 +08:00
for ( io = j - > io ; io ; io = io - > next )
{
2012-02-22 11:33:11 +08:00
if ( io - > io_mode = = IO_FILE & & io - > filename ! = L " /dev/null " )
2007-03-25 06:34:30 +08:00
{
skip_fork = 0 ;
}
}
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
if ( skip_fork )
{
p - > completed = 1 ;
if ( p - > next = = 0 )
{
2012-01-30 14:06:58 +08:00
debug ( 3 , L " Set status of %ls to %d using short circut " , j - > command_cstr ( ) , p - > status ) ;
2011-12-27 11:18:46 +08:00
2010-11-24 00:27:16 +08:00
int status = p - > status ;
2009-02-22 00:46:56 +08:00
proc_set_last_status ( job_get_flag ( j , JOB_NEGATE ) ? ( ! status ) : status ) ;
2005-09-20 21:26:39 +08:00
}
break ;
}
2006-11-15 21:30:46 +08:00
/*
Ok , unfortunatly , we have to do a real fork . Bummer .
*/
2011-12-27 11:18:46 +08:00
2006-11-15 21:30:46 +08:00
pid = exec_fork ( ) ;
2005-11-02 23:41:59 +08:00
if ( pid = = 0 )
2005-09-20 21:26:39 +08:00
{
2006-06-04 06:35:33 +08:00
2005-09-20 21:26:39 +08:00
/*
2006-06-04 06:35:33 +08:00
This is the child process . Setup redirections ,
print correct output to stdout and stderr , and
then exit .
2005-09-20 21:26:39 +08:00
*/
p - > pid = getpid ( ) ;
2006-01-16 08:15:56 +08:00
setup_child_process ( j , p ) ;
2012-02-23 02:51:06 +08:00
const wcstring & out = get_stdout_buffer ( ) , & err = get_stderr_buffer ( ) ;
do_builtin_io ( out . empty ( ) ? NULL : out . c_str ( ) , err . empty ( ) ? NULL : err . c_str ( ) ) ;
2005-09-20 21:26:39 +08:00
exit ( p - > status ) ;
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
}
else
{
2011-12-27 11:18:46 +08:00
/*
2005-09-20 21:26:39 +08:00
This is the parent process . Store away
2006-06-04 06:35:33 +08:00
information on the child , and possibly give
2005-09-20 21:26:39 +08:00
it control over the terminal .
*/
p - > pid = pid ;
2011-12-27 11:18:46 +08:00
2006-02-04 19:33:20 +08:00
set_child_group ( j , p , 0 ) ;
2011-12-27 11:18:46 +08:00
}
2005-09-20 21:26:39 +08:00
break ;
}
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
case EXTERNAL :
{
2006-11-15 21:30:46 +08:00
pid = exec_fork ( ) ;
2005-11-02 23:41:59 +08:00
if ( pid = = 0 )
2005-09-20 21:26:39 +08:00
{
/*
2011-12-27 11:18:46 +08:00
This is the child process .
2005-09-20 21:26:39 +08:00
*/
p - > pid = getpid ( ) ;
2006-01-16 08:15:56 +08:00
setup_child_process ( j , p ) ;
2005-09-20 21:26:39 +08:00
launch_process ( p ) ;
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
/*
launch_process _never_ returns . . .
*/
}
else
{
2011-12-27 11:18:46 +08:00
/*
2005-09-20 21:26:39 +08:00
This is the parent process . Store away
information on the child , and possibly fice
it control over the terminal .
*/
p - > pid = pid ;
2006-02-04 19:33:20 +08:00
set_child_group ( j , p , 0 ) ;
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
}
break ;
}
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
}
2005-11-02 23:41:59 +08:00
if ( p - > type = = INTERNAL_BUILTIN )
2012-01-23 12:47:13 +08:00
builtin_pop_io ( parser ) ;
2011-12-27 11:18:46 +08:00
/*
2006-11-15 21:30:46 +08:00
Close the pipe the current process uses to read from the
previous process_t
2005-09-20 21:26:39 +08:00
*/
2005-10-12 03:31:16 +08:00
if ( pipe_read . param1 . pipe_fd [ 0 ] > = 0 )
exec_close ( pipe_read . param1 . pipe_fd [ 0 ] ) ;
2011-12-27 11:18:46 +08:00
/*
2006-11-15 21:30:46 +08:00
Set up the pipe the next process uses to read from the
current process_t
2005-09-20 21:26:39 +08:00
*/
if ( p - > next )
2005-10-12 03:31:16 +08:00
pipe_read . param1 . pipe_fd [ 0 ] = mypipe [ 0 ] ;
2011-12-27 11:18:46 +08:00
/*
2006-06-04 06:35:33 +08:00
If there is a next process in the pipeline , close the
output end of the current pipe ( the surrent child
subprocess already has a copy of the pipe - this makes sure
we don ' t leak file descriptors either in the shell or in
the children ) .
2005-09-20 21:26:39 +08:00
*/
if ( p - > next )
{
2005-10-08 19:20:51 +08:00
exec_close ( mypipe [ 1 ] ) ;
2011-12-27 11:18:46 +08:00
}
2005-09-20 21:26:39 +08:00
}
2006-08-27 08:52:52 +08:00
/*
The keepalive process is no longer needed , so we terminate it
with extreme prejudice
*/
if ( needs_keepalive )
{
kill ( keepalive . pid , SIGKILL ) ;
}
2011-12-27 11:18:46 +08:00
signal_unblock ( ) ;
2005-10-21 07:56:51 +08:00
2005-09-23 21:10:31 +08:00
debug ( 3 , L " Job is constructed " ) ;
2005-09-20 21:26:39 +08:00
j - > io = io_remove ( j - > io , & pipe_read ) ;
2012-01-23 12:47:13 +08:00
for ( tmp = parser . block_io ; tmp ; tmp = tmp - > next )
2005-09-20 21:26:39 +08:00
j - > io = io_remove ( j - > io , tmp ) ;
2011-12-27 11:18:46 +08:00
2006-10-26 04:47:59 +08:00
job_set_flag ( j , JOB_CONSTRUCTED , 1 ) ;
2005-09-20 21:26:39 +08:00
2006-10-26 04:47:59 +08:00
if ( ! job_get_flag ( j , JOB_FOREGROUND ) )
2005-09-20 21:26:39 +08:00
{
proc_last_bg_pid = j - > pgid ;
}
2006-04-04 19:27:22 +08:00
2005-10-21 07:56:51 +08:00
if ( ! exec_error )
{
job_continue ( j , 0 ) ;
}
2011-12-27 11:18:46 +08:00
}
2010-09-18 09:51:16 +08:00
2005-09-20 21:26:39 +08:00
2012-02-08 15:35:41 +08:00
static int exec_subshell_internal ( const wcstring & cmd , wcstring_list_t * lst )
2005-09-20 21:26:39 +08:00
{
char * begin , * end ;
char z = 0 ;
int prev_subshell = is_subshell ;
int status , prev_status ;
io_data_t * io_buffer ;
2007-04-23 02:49:56 +08:00
char sep = 0 ;
2011-12-27 11:18:46 +08:00
2012-01-17 01:43:34 +08:00
const env_var_t ifs = env_get_string ( L " IFS " ) ;
2007-04-23 02:49:56 +08:00
2012-01-14 18:42:17 +08:00
if ( ! ifs . missing_or_empty ( ) )
2007-04-23 02:49:56 +08:00
{
2012-01-14 18:42:17 +08:00
if ( ifs . at ( 0 ) < 128 )
2007-04-23 02:49:56 +08:00
{
sep = ' \n ' ; //ifs[0];
}
else
{
sep = 0 ;
debug ( 0 , L " Warning - invalid command substitution separator '%lc'. Please change the firsta character of IFS " , ifs [ 0 ] ) ;
}
2011-12-27 11:18:46 +08:00
2007-04-23 02:49:56 +08:00
}
2011-12-27 11:18:46 +08:00
is_subshell = 1 ;
2006-08-13 09:38:03 +08:00
io_buffer = io_buffer_create ( 0 ) ;
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
prev_status = proc_get_last_status ( ) ;
2011-12-27 11:18:46 +08:00
2012-01-23 13:57:30 +08:00
parser_t & parser = parser_t : : principal_parser ( ) ;
2012-01-23 12:47:13 +08:00
if ( parser . eval ( cmd , io_buffer , SUBST ) )
2006-10-19 23:36:03 +08:00
{
status = - 1 ;
}
else
{
status = proc_get_last_status ( ) ;
}
2011-12-27 11:18:46 +08:00
2005-10-08 19:20:51 +08:00
io_buffer_read ( io_buffer ) ;
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
proc_set_last_status ( prev_status ) ;
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
is_subshell = prev_subshell ;
2011-12-27 11:18:46 +08:00
2005-10-12 03:31:16 +08:00
b_append ( io_buffer - > param2 . out_buffer , & z , 1 ) ;
2011-12-27 11:18:46 +08:00
begin = end = io_buffer - > param2 . out_buffer - > buff ;
2005-11-02 23:41:59 +08:00
2006-11-15 21:30:46 +08:00
if ( lst )
2005-09-20 21:26:39 +08:00
{
while ( 1 )
{
2007-04-23 02:49:56 +08:00
if ( * end = = 0 )
2005-09-20 21:26:39 +08:00
{
2007-04-23 02:49:56 +08:00
if ( begin ! = end )
2005-09-20 21:26:39 +08:00
{
2007-04-23 02:49:56 +08:00
wchar_t * el = str2wcs ( begin ) ;
2006-02-22 23:41:52 +08:00
if ( el )
{
2012-02-08 15:35:41 +08:00
lst - > push_back ( el ) ;
2012-02-18 02:52:30 +08:00
free ( el ) ;
2006-02-22 23:41:52 +08:00
}
else
{
debug ( 2 , L " Got null string on line %d of file %s " , __LINE__ , __FILE__ ) ;
}
2011-12-27 11:18:46 +08:00
}
2007-04-23 02:49:56 +08:00
io_buffer_destroy ( io_buffer ) ;
2011-12-27 11:18:46 +08:00
2007-04-23 02:49:56 +08:00
return status ;
}
else if ( * end = = sep )
{
wchar_t * el ;
* end = 0 ;
el = str2wcs ( begin ) ;
if ( el )
{
2012-02-08 15:35:41 +08:00
lst - > push_back ( el ) ;
2012-02-18 02:52:30 +08:00
free ( el ) ;
2007-04-23 02:49:56 +08:00
}
else
{
debug ( 2 , L " Got null string on line %d of file %s " , __LINE__ , __FILE__ ) ;
2005-09-20 21:26:39 +08:00
}
2007-04-23 02:49:56 +08:00
begin = end + 1 ;
2005-09-20 21:26:39 +08:00
}
end + + ;
}
}
2011-12-27 11:18:46 +08:00
2005-10-08 19:20:51 +08:00
io_buffer_destroy ( io_buffer ) ;
2006-01-18 20:42:48 +08:00
2011-12-27 11:18:46 +08:00
return status ;
2005-09-20 21:26:39 +08:00
}
2012-02-08 15:35:41 +08:00
int exec_subshell ( const wcstring & cmd , std : : vector < wcstring > & outputs )
{
return exec_subshell_internal ( cmd , & outputs ) ;
}
__warn_unused int exec_subshell ( const wcstring & cmd )
{
return exec_subshell_internal ( cmd , NULL ) ;
}