A bunch of work to move towards a sane memory model in job_t

This commit is contained in:
ridiculousfish 2012-01-29 22:06:58 -08:00
parent 966cd6a8ca
commit 3b8a4e56b0
16 changed files with 195 additions and 130 deletions

View File

@ -3014,7 +3014,7 @@ static int builtin_fg( parser_t &parser, wchar_t **argv )
_( L"%ls: Can't put job %d, '%ls' to foreground because it is not under job control\n" ),
argv[0],
pid,
j->command );
j->command_cstr() );
builtin_print_help( parser, argv[0], sb_err );
j=0;
}
@ -3028,7 +3028,7 @@ static int builtin_fg( parser_t &parser, wchar_t **argv )
sb_printf( sb_err,
FG_MSG,
j->job_id,
j->command );
j->command_cstr() );
}
else
{
@ -3040,10 +3040,10 @@ static int builtin_fg( parser_t &parser, wchar_t **argv )
fwprintf( stderr,
FG_MSG,
j->job_id,
j->command );
j->command_cstr() );
}
wchar_t *ft = tok_first( j->command );
wchar_t *ft = tok_first( j->command_cstr() );
if( ft != 0 )
env_set( L"_", ft, ENV_EXPORT );
free(ft);
@ -3077,7 +3077,7 @@ static int send_to_bg( parser_t &parser, job_t *j, const wchar_t *name )
_( L"%ls: Can't put job %d, '%ls' to background because it is not under job control\n" ),
L"bg",
j->job_id,
j->command );
j->command_cstr() );
builtin_print_help( parser, L"bg", sb_err );
return STATUS_BUILTIN_ERROR;
}
@ -3086,7 +3086,7 @@ static int send_to_bg( parser_t &parser, job_t *j, const wchar_t *name )
sb_printf( sb_err,
_(L"Send job %d '%ls' to background\n"),
j->job_id,
j->command );
j->command_cstr() );
}
make_first( j );
job_set_flag( j, JOB_FOREGROUND, 0 );
@ -3821,7 +3821,7 @@ int builtin_exists( wchar_t *cmd )
Return true if the specified builtin should handle it's own help,
false otherwise.
*/
static int internal_help( wchar_t *cmd )
static int internal_help( const wchar_t *cmd )
{
CHECK( cmd, 0 );
return contains( cmd, L"for", L"while", L"function",
@ -3829,15 +3829,15 @@ static int internal_help( wchar_t *cmd )
}
int builtin_run( parser_t &parser, wchar_t **argv, io_data_t *io )
int builtin_run( parser_t &parser, const wchar_t * const *argv, io_data_t *io )
{
int (*cmd)(parser_t &parser, wchar_t **argv)=0;
int (*cmd)(parser_t &parser, const wchar_t * const *argv)=0;
real_io = io;
CHECK( argv, STATUS_BUILTIN_ERROR );
CHECK( argv[0], STATUS_BUILTIN_ERROR );
cmd = (int (*)(parser_t &parser, wchar_t **))hash_get( &builtin, argv[0] );
cmd = (int (*)(parser_t &parser, const wchar_t * const*))hash_get( &builtin, argv[0] );
if( argv[1] != 0 && !internal_help(argv[0]) )
{

View File

@ -137,7 +137,7 @@ int builtin_exists( wchar_t *cmd );
\return the exit status of the builtin command
*/
int builtin_run( parser_t &parser, wchar_t **argv, io_data_t *io );
int builtin_run( parser_t &parser, const wchar_t * const *argv, io_data_t *io );
/**
Insert all builtin names into l. These are not copies of the strings and should not be freed after use.

View File

@ -542,7 +542,6 @@ static int builtin_complete( parser_t &parser, wchar_t **argv )
if( do_complete )
{
std::vector<completion_t> comp;
int i;
const wchar_t *prev_temporary_buffer = temporary_buffer;
@ -560,7 +559,7 @@ static int builtin_complete( parser_t &parser, wchar_t **argv )
complete2( do_complete, comp );
for( i=0; i< comp.size() ; i++ )
for( size_t i=0; i< comp.size() ; i++ )
{
const completion_t &next = comp.at( i );

View File

@ -99,7 +99,7 @@ static void builtin_jobs_print( job_t *j, int mode, int header )
sb_append( sb_out,
job_is_stopped(j)?_(L"stopped"):_(L"running"),
L"\t",
j->command,
j->command_cstr(),
L"\n",
NULL );
break;
@ -147,7 +147,7 @@ static void builtin_jobs_print( job_t *j, int mode, int header )
for( p=j->first_process; p; p=p->next )
{
sb_printf( sb_out, L"%ls\n", p->argv[0] );
sb_printf( sb_out, L"%ls\n", p->argv0() );
}
break;
}

View File

@ -159,14 +159,14 @@ wchar_t **list_to_char_arr( array_list_t *l )
wchar_t **completions_to_char_arr( std::vector<completion_t> &l )
{
wchar_t ** res = (wchar_t **)malloc( sizeof(wchar_t *)*( l.size() + 1) );
int i;
size_t i;
if( res == 0 )
{
DIE_MEM();
}
for( i=0; i< l.size(); i++ )
{
res[i] = const_cast<wchar_t*>(l.at(i).completion.c_str());
res[i] = wcsdup(l.at(i).completion.c_str());
}
res[i]='\0';
return res;
@ -414,7 +414,7 @@ char *wcs2str_internal( const wchar_t *in, char *out )
return out;
}
char **wcsv2strv( const wchar_t **in )
char **wcsv2strv( const wchar_t * const *in )
{
int count =0;
int i;

View File

@ -356,7 +356,7 @@ wcstring format_string(const wchar_t *format, ...);
Returns a newly allocated wide character string array equivalent of
the specified multibyte character string array
*/
char **wcsv2strv( const wchar_t **in );
char **wcsv2strv( const wchar_t * const *in );
/**
Returns a newly allocated multibyte character string array equivalent of the specified wide character string array

View File

@ -907,7 +907,6 @@ static void complete_strings( std::vector<completion_t> &comp_out,
std::vector<completion_t> &possible_comp,
int flags )
{
int i;
wchar_t *wc, *tmp;
tmp = expand_one( 0,
@ -918,7 +917,7 @@ static void complete_strings( std::vector<completion_t> &comp_out,
wc = parse_util_unescape_wildcards( tmp );
free(tmp);
for( i=0; i< possible_comp.size(); i++ )
for( size_t i=0; i< possible_comp.size(); i++ )
{
wcstring temp = possible_comp.at( i ).completion;
const wchar_t *next_str = temp.empty()?NULL:temp.c_str();

View File

@ -236,7 +236,7 @@ const wchar_t *event_get_desc( event_t *e )
{
job_t *j = job_get_from_pid( -e->param1.pid );
if( j )
sb_printf( get_desc_buff, _(L"exit handler for job %d, '%ls'"), j->job_id, j->command );
sb_printf( get_desc_buff, _(L"exit handler for job %d, '%ls'"), j->job_id, j->command_cstr() );
else
sb_printf( get_desc_buff, _(L"exit handler for job with process group %d"), -e->param1.pid );
}
@ -247,7 +247,7 @@ const wchar_t *event_get_desc( event_t *e )
{
job_t *j = job_get( e->param1.job_id );
if( j )
sb_printf( get_desc_buff, _(L"exit handler for job %d, '%ls'"), j->job_id, j->command );
sb_printf( get_desc_buff, _(L"exit handler for job %d, '%ls'"), j->job_id, j->command_cstr() );
else
sb_printf( get_desc_buff, _(L"exit handler for job with job id %d"), j->job_id );

View File

@ -467,7 +467,7 @@ static int setup_child_process( job_t *j, process_t *p )
call. Only use it in the execve error handler which calls exit
right afterwards, anyway.
*/
static wchar_t *get_interpreter( wchar_t *file )
static wchar_t *get_interpreter( const wchar_t *file )
{
string_buffer_t sb;
FILE *fp = wfopen( file, "r" );
@ -509,7 +509,7 @@ static void launch_process( process_t *p )
// debug( 1, L"exec '%ls'", p->argv[0] );
char **argv = wcsv2strv( (const wchar_t **) p->argv);
char **argv = wcsv2strv(p->get_argv());
char **envv = env_export_arr( 0 );
execve ( wcs2str(p->actual_cmd),
@ -539,21 +539,21 @@ static void launch_process( process_t *p )
wchar_t **res;
char **res_real;
while( p->argv[count] != 0 )
while( p->argv(count) != 0 )
count++;
res = (wchar_t **)malloc( sizeof(wchar_t*)*(count+2));
wchar_t sh_command[] = L"/bin/sh";
res = (wchar_t **)malloc( sizeof(wchar_t*)*(count+3));
const wchar_t *sh_command = L"/bin/sh";
res[0] = sh_command;
res[1] = p->actual_cmd;
res[0] = wcsdup(sh_command);
res[1] = wcsdup(p->actual_cmd);
for( i=1; p->argv[i]; i++ ){
res[i+1] = p->argv[i];
for( i=1; p->argv(i) != NULL; i++ ){
res[i+1] = wcsdup(p->argv(i));
}
res[i+1] = 0;
p->argv = res;
p->set_argv(res);
p->actual_cmd = sh_command;
res_real = wcsv2strv( (const wchar_t **) res);
@ -841,9 +841,9 @@ static int set_child_group( job_t *j, process_t *p, int print_errors )
debug( 1,
_( L"Could not send process %d, '%ls' in job %d, '%ls' from group %d to group %d" ),
p->pid,
p->argv[0],
p->argv0(),
j->job_id,
j->command,
j->command_cstr(),
getpgid( p->pid),
j->pgid );
@ -863,7 +863,7 @@ static int set_child_group( job_t *j, process_t *p, int print_errors )
{
debug( 1, _( L"Could not send job %d ('%ls') to foreground" ),
j->job_id,
j->command );
j->command_cstr() );
wperror( L"tcsetpgrp" );
res = -1;
}
@ -978,7 +978,7 @@ void exec( parser_t &parser, job_t *j )
sigemptyset( &chldset );
sigaddset( &chldset, SIGCHLD );
debug( 4, L"Exec job '%ls' with id %d", j->command, j->job_id );
debug( 4, L"Exec job '%ls' with id %d", j->command_cstr(), j->job_id );
if( parser.block_io )
{
@ -1004,8 +1004,8 @@ void exec( parser_t &parser, job_t *j )
Input redirection - create a new gobetween process to take
care of buffering
*/
process_t *fake = (process_t *)halloc( j, sizeof(process_t) );
fake->type = INTERNAL_BUFFER;
process_t *fake = new process_t();
fake->type = INTERNAL_BUFFER;
fake->pipe_write_fd = 1;
j->first_process->pipe_read_fd = input_redirect->fd;
fake->next = j->first_process;
@ -1187,31 +1187,33 @@ void exec( parser_t &parser, job_t *j )
*/
signal_unblock();
orig_def = function_get_definition( p->argv[0] );
orig_def = function_get_definition( p->argv0() );
// 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)
orig_def = wcsdup(orig_def);
wcstring_list_t named_arguments = function_get_named_arguments( p->argv[0] );
shadows = function_get_shadows( p->argv[0] );
wcstring_list_t named_arguments = function_get_named_arguments( p->argv0() );
shadows = function_get_shadows( p->argv0() );
signal_block();
if( orig_def )
{
def = (wchar_t *)halloc_register( j, const_cast<wchar_t *>(orig_def) );
//def = (wchar_t *)halloc_register( j, const_cast<wchar_t *>(orig_def) );
// PCA LEAKS
def = (wchar_t *)orig_def;
}
if( def == 0 )
{
debug( 0, _( L"Unknown function '%ls'" ), p->argv[0] );
debug( 0, _( L"Unknown function '%ls'" ), p->argv0() );
break;
}
parser.push_block( shadows?FUNCTION_CALL:FUNCTION_CALL_NO_SHADOW );
parser.current_block->param2.function_call_process = p;
parser.current_block->param1.function_call_name = (wchar_t *)halloc_register( parser.current_block, wcsdup( p->argv[0] ) );
parser.current_block->param1.function_call_name = (wchar_t *)halloc_register( parser.current_block, wcsdup( p->argv0() ) );
/*
@ -1220,10 +1222,10 @@ void exec( parser_t &parser, job_t *j )
signals.
*/
signal_unblock();
parse_util_set_argv( p->argv+1, named_arguments );
parse_util_set_argv( p->get_argv()+1, named_arguments );
signal_block();
parser.forbid_function( p->argv[0] );
parser.forbid_function( p->argv0() );
if( p->next )
{
@ -1247,7 +1249,7 @@ void exec( parser_t &parser, job_t *j )
j->io = io_add( j->io, io_buffer );
}
internal_exec_helper( parser, p->argv[0], TOP, j->io );
internal_exec_helper( parser, p->argv0(), TOP, j->io );
break;
}
@ -1380,7 +1382,7 @@ void exec( parser_t &parser, job_t *j )
signal_unblock();
p->status = builtin_run( parser, p->argv, j->io );
p->status = builtin_run( parser, p->get_argv(), j->io );
builtin_out_redirect=old_out;
builtin_err_redirect=old_err;
@ -1580,7 +1582,7 @@ void exec( parser_t &parser, job_t *j )
p->completed=1;
if( p->next == 0 )
{
debug( 3, L"Set status of %ls to %d using short circut", j->command, p->status );
debug( 3, L"Set status of %ls to %d using short circut", j->command_cstr(), p->status );
int status = p->status;
proc_set_last_status( job_get_flag( j, JOB_NEGATE )?(!status):status );

View File

@ -401,7 +401,7 @@ static int find_process( const wchar_t *proc,
while ((j = jobs.next()))
{
wchar_t jid[16];
if( j->command == 0 )
if( j->command.size() == 0 )
continue;
swprintf( jid, 16, L"%d", j->job_id );
@ -414,7 +414,7 @@ static int find_process( const wchar_t *proc,
sb_printf( &desc_buff,
COMPLETE_JOB_DESC_VAL,
j->command );
j->command_cstr() );
completion_allocate( out,
jid+wcslen(proc),
@ -437,7 +437,7 @@ static int find_process( const wchar_t *proc,
if( jid > 0 && !errno && !*end )
{
j = job_get( jid );
if( (j != 0) && (j->command != 0 ) )
if( (j != 0) && (j->command_cstr() != 0 ) )
{
{
@ -460,15 +460,15 @@ static int find_process( const wchar_t *proc,
{
int offset;
if( j->command == 0 )
if( j->command_cstr() == 0 )
continue;
if( match_pid( j->command, proc, flags, &offset ) )
if( match_pid( j->command_cstr(), proc, flags, &offset ) )
{
if( flags & ACCEPT_INCOMPLETE )
{
completion_allocate( out,
j->command + offset + wcslen(proc),
j->command_cstr() + offset + wcslen(proc),
COMPLETE_JOB_DESC,
0 );
}
@ -493,7 +493,7 @@ static int find_process( const wchar_t *proc,
while ((j = jobs.next()))
{
process_t *p;
if( j->command == 0 )
if( j->command.size() == 0 )
continue;
for( p=j->first_process; p; p=p->next )
{
@ -2621,7 +2621,8 @@ wchar_t *expand_one( void *context, wchar_t *string, int flags )
// al_foreach( &l, &free );
// al_destroy( &l );
halloc_register( context, one );
if (context)
halloc_register( context, one );
return one;
}

View File

@ -600,11 +600,11 @@ void parse_util_token_extent( const wchar_t *buff,
}
void parse_util_set_argv( wchar_t **argv, const wcstring_list_t &named_arguments )
void parse_util_set_argv( const wchar_t * const *argv, const wcstring_list_t &named_arguments )
{
if( *argv )
{
wchar_t **arg;
const wchar_t * const *arg;
string_buffer_t sb;
sb_init( &sb );
@ -627,7 +627,7 @@ void parse_util_set_argv( wchar_t **argv, const wcstring_list_t &named_arguments
if( named_arguments.size() )
{
wchar_t **arg;
const wchar_t * const *arg;
size_t i;
for( i=0, arg=argv; i < named_arguments.size(); i++ )

View File

@ -116,7 +116,7 @@ int parse_util_get_offset( wchar_t *buff, int line, int line_offset );
Set the argv environment variable to the specified null-terminated
array of strings.
*/
void parse_util_set_argv( wchar_t **argv, const wcstring_list_t &named_arguments );
void parse_util_set_argv( const wchar_t * const *argv, const wcstring_list_t &named_arguments );
/**
Make a duplicate of the specified string, unescape wildcard

View File

@ -574,14 +574,9 @@ static const wchar_t *parser_find_end( const wchar_t * buff )
}
void parser_t::forbid_function( wchar_t *function )
void parser_t::forbid_function( const wcstring &function )
{
/*
if( function )
debug( 2, L"Forbid %ls\n", function );
*/
CHECK( function, );
forbidden_function.push_back(wcstring(function));
forbidden_function.push_back(function);
}
void parser_t::allow_function()
@ -937,14 +932,14 @@ void parser_t::stack_trace( block_t *b, string_buffer_t *buff)
if( b->type == FUNCTION_CALL )
{
if( b->param2.function_call_process->argv[1] )
if( b->param2.function_call_process->argv(1) )
{
string_buffer_t tmp;
sb_init( &tmp );
for( i=1; b->param2.function_call_process->argv[i]; i++ )
for( i=1; b->param2.function_call_process->argv(i); i++ )
{
sb_append( &tmp, i>1?L" ":L"", b->param2.function_call_process->argv[i], NULL );
sb_append( &tmp, i>1?L" ":L"", b->param2.function_call_process->argv(i), NULL );
}
sb_printf( buff, _(L"\twith parameter list '%ls'\n"), (wchar_t *)tmp.buff );
@ -1202,7 +1197,7 @@ const wchar_t *parser_t::get_buffer() const
}
int parser_t::is_help( wchar_t *s, int min_match ) const
int parser_t::is_help( const wchar_t *s, int min_match ) const
{
int len;
@ -1275,9 +1270,8 @@ void parser_t::parse_job_argument_list( process_t *p,
return;
}
if( !p->argv )
halloc_register( j, p->argv = completions_to_char_arr( args ) );
p->next = (process_t *)halloc( j, sizeof( process_t ) );
p->set_argv(completions_to_char_arr(args));
p->next = new process_t();
tok_next( tok );
@ -1298,8 +1292,8 @@ void parser_t::parse_job_argument_list( process_t *p,
case TOK_END:
{
if( !p->argv )
halloc_register( j, p->argv = completions_to_char_arr( args ) );
if( !p->get_argv() )
p->set_argv(completions_to_char_arr(args));
if( tok_has_next(tok))
tok_next(tok);
@ -1447,7 +1441,7 @@ void parser_t::parse_job_argument_list( process_t *p,
{
case TOK_STRING:
{
target = (wchar_t *)expand_one( j,
target = expand_one( j,
wcsdup( tok_last( tok ) ),
no_exec ? EXPAND_SKIP_VARIABLES : 0);
@ -2047,7 +2041,7 @@ int parser_t::parse_job( process_t *p,
error( SYNTAX_ERROR,
tok_get_pos( tok ),
UNKNOWN_BUILTIN_ERR_MSG,
args->at( args->size() -1 ) );
args->back().completion.c_str() );
}
}
@ -2147,8 +2141,8 @@ int parser_t::parse_job( process_t *p,
{
if( p->type == INTERNAL_BUILTIN && parser_keywords_skip_arguments( (wchar_t *)args->at( 0 ).completion.c_str() ) )
{
if( !p->argv )
halloc_register( j, p->argv = completions_to_char_arr( *args ) );
if( !p->get_argv() )
p->set_argv(completions_to_char_arr( *args ));
}
else
{
@ -2194,14 +2188,14 @@ void parser_t::skipped_exec( job_t * j )
{
if( p->type == INTERNAL_BUILTIN )
{
if(( wcscmp( p->argv[0], L"for" )==0) ||
( wcscmp( p->argv[0], L"switch" )==0) ||
( wcscmp( p->argv[0], L"begin" )==0) ||
( wcscmp( p->argv[0], L"function" )==0))
if(( wcscmp( p->argv0(), L"for" )==0) ||
( wcscmp( p->argv0(), L"switch" )==0) ||
( wcscmp( p->argv0(), L"begin" )==0) ||
( wcscmp( p->argv0(), L"function" )==0))
{
this->push_block( FAKE );
}
else if( wcscmp( p->argv[0], L"end" )==0)
else if( wcscmp( p->argv0(), L"end" )==0)
{
if(!current_block->outer->skip )
{
@ -2210,7 +2204,7 @@ void parser_t::skipped_exec( job_t * j )
}
parser_t::pop_block();
}
else if( wcscmp( p->argv[0], L"else" )==0)
else if( wcscmp( p->argv0(), L"else" )==0)
{
if( (current_block->type == IF ) &&
(current_block->param1.if_state != 0))
@ -2219,7 +2213,7 @@ void parser_t::skipped_exec( job_t * j )
return;
}
}
else if( wcscmp( p->argv[0], L"case" )==0)
else if( wcscmp( p->argv0(), L"case" )==0)
{
if( (current_block->type == SWITCH ) )
{
@ -2287,12 +2281,12 @@ void parser_t::eval_job( tokenizer *tok )
}
}
j->first_process = (process_t *)halloc( j, sizeof( process_t ) );
j->first_process = new process_t();
job_begin_pos = tok_get_pos( tok );
if( parse_job( j->first_process, j, tok ) &&
j->first_process->argv )
j->first_process->get_argv() )
{
if( job_start_pos < tok_get_pos( tok ) )
{
@ -2302,9 +2296,7 @@ void parser_t::eval_job( tokenizer *tok )
if( newline )
stop_pos = mini( stop_pos, newline - tok_string(tok) );
j->command = halloc_wcsndup( j,
tok_string(tok)+start_pos,
stop_pos-start_pos );
j->command = wcstring(tok_string(tok)+start_pos, stop_pos-start_pos);
}
else
j->command = L"";
@ -2312,7 +2304,7 @@ void parser_t::eval_job( tokenizer *tok )
if( profile )
{
t2 = get_time();
profile_item->cmd = wcsdup( j->command );
profile_item->cmd = wcsdup( j->command_cstr() );
profile_item->skipped=current_block->skip;
}

View File

@ -236,7 +236,7 @@ class parser_t {
int current_tokenizer_pos;
/** List of called functions, used to help prevent infinite recursion */
std::vector<wcstring> forbidden_function;
wcstring_list_t forbidden_function;
/** String index where the current job started. */
int job_start_pos;
@ -395,7 +395,7 @@ class parser_t {
inside of a conditional block. This is to remove some possibilities
of infinite recursion.
*/
void forbid_function( wchar_t *function );
void forbid_function( const wcstring &function );
/**
Undo last call to parser_forbid_function().
*/
@ -417,7 +417,7 @@ class parser_t {
\param s the string to test
\param min_match is the minimum number of characters that must match in a long style option, i.e. the longest common prefix between --help and any other option. If less than 3, 3 will be assumed.
*/
int is_help( wchar_t *s, int min_match ) const;
int is_help( const wchar_t *s, int min_match ) const;
/**
Returns the file currently evaluated by the parser. This can be

View File

@ -178,7 +178,8 @@ void job_promote(job_t *job)
void job_free( job_t * j )
{
job_remove( j );
halloc_free( j );
j->~job_t();
halloc_free( j );
}
void proc_destroy()
@ -191,7 +192,7 @@ void proc_destroy()
while( ! jobs.empty() )
{
job_t *job = jobs.front();
debug( 2, L"freeing leaked job %ls", job->command );
debug( 2, L"freeing leaked job %ls", job->command_cstr() );
job_free( job );
}
}
@ -209,11 +210,12 @@ int proc_get_last_status()
job_t *job_create()
{
int free_id=1;
job_t *res;
while( job_get( free_id ) != 0 )
free_id++;
res = new job_t(free_id);
void *buff = halloc( 0, sizeof(job_t) );
job_t *res = new (buff) job_t(free_id);
job_list().push_front(res);
job_set_flag( res,
@ -524,7 +526,7 @@ void job_handle_signal ( int signal, siginfo_t *info, void *con )
static void format_job_info( const job_t *j, const wchar_t *status )
{
fwprintf (stdout, L"\r" );
fwprintf (stdout, _( L"Job %d, \'%ls\' has %ls" ), j->job_id, j->command, status);
fwprintf (stdout, _( L"Job %d, \'%ls\' has %ls" ), j->job_id, j->command_cstr(), status);
fflush( stdout );
tputs(clr_eol,1,&writeb);
fwprintf (stdout, L"\n" );
@ -608,7 +610,7 @@ int job_reap( int interactive )
_( L"%ls: Job %d, \'%ls\' terminated by signal %ls (%ls)" ),
program_name,
j->job_id,
j->command,
j->command_cstr(),
sig2wcs(WTERMSIG(p->status)),
signal_get_desc( WTERMSIG(p->status) ) );
else
@ -616,9 +618,9 @@ int job_reap( int interactive )
_( L"%ls: Process %d, \'%ls\' from job %d, \'%ls\' terminated by signal %ls (%ls)" ),
program_name,
p->pid,
p->argv[0],
p->argv0(),
j->job_id,
j->command,
j->command_cstr(),
sig2wcs(WTERMSIG(p->status)),
signal_get_desc( WTERMSIG(p->status) ) );
tputs(clr_eol,1,&writeb);
@ -851,7 +853,7 @@ static void read_try( job_t *j )
if( buff )
{
debug( 3, L"proc::read_try('%ls')\n", j->command );
debug( 3, L"proc::read_try('%ls')\n", j->command_cstr() );
while(1)
{
char b[BUFFER_SIZE];
@ -899,7 +901,7 @@ static int terminal_give_to_job( job_t *j, int cont )
debug( 1,
_( L"Could not send job %d ('%ls') to foreground" ),
j->job_id,
j->command );
j->command_cstr() );
wperror( L"tcsetpgrp" );
return 0;
}
@ -911,7 +913,7 @@ static int terminal_give_to_job( job_t *j, int cont )
debug( 1,
_( L"Could not send job %d ('%ls') to foreground" ),
j->job_id,
j->command );
j->command_cstr() );
wperror( L"tcsetattr" );
return 0;
}
@ -971,7 +973,7 @@ void job_continue (job_t *j, int cont)
L"Continue job %d, gid %d (%ls), %ls, %ls",
j->job_id,
j->pgid,
j->command,
j->command_cstr(),
job_is_completed( j )?L"COMPLETED":L"UNCOMPLETED",
is_interactive?L"INTERACTIVE":L"NON-INTERACTIVE" );
@ -1169,9 +1171,6 @@ void proc_sanity_check()
continue;
validate_pointer( j->command,
_( L"Job command" ),
0 );
validate_pointer( j->first_process,
_( L"Process list pointer" ),
0 );
@ -1185,8 +1184,8 @@ void proc_sanity_check()
{
debug( 0,
_( L"More than one job in foreground: job 1: '%ls' job 2: '%ls'"),
fg_job->command,
j->command );
fg_job->command_cstr(),
j->command_cstr() );
sanity_lose();
}
fg_job = j;
@ -1195,8 +1194,8 @@ void proc_sanity_check()
p = j->first_process;
while( p )
{
validate_pointer( p->argv, _( L"Process argument list" ), 0 );
validate_pointer( p->argv[0], _( L"Process name" ), 0 );
validate_pointer( p->get_argv(), _( L"Process argument list" ), 0 );
validate_pointer( p->argv0(), _( L"Process name" ), 0 );
validate_pointer( p->next, _( L"Process list pointer" ), 1 );
validate_pointer( p->actual_cmd, _( L"Process command" ), 1 );
@ -1204,8 +1203,8 @@ void proc_sanity_check()
{
debug( 0,
_( L"Job '%ls', process '%ls' has inconsistent state \'stopped\'=%d" ),
j->command,
p->argv[0],
j->command_cstr(),
p->argv0(),
p->stopped );
sanity_lose();
}
@ -1214,8 +1213,8 @@ void proc_sanity_check()
{
debug( 0,
_( L"Job '%ls', process '%ls' has inconsistent state \'completed\'=%d" ),
j->command,
p->argv[0],
j->command_cstr(),
p->argv0(),
p->completed );
sanity_lose();
}

89
proc.h
View File

@ -19,6 +19,7 @@
#include "util.h"
#include "io.h"
#include "common.h"
/**
The status code use when a command was not found
@ -126,19 +127,84 @@ enum
*/
class process_t
{
private:
/** argv parameter for for execv, builtin_run, etc. This is allocated via malloc, and furthermore, each string within it is allocated via malloc as well . Null terminated. */
wchar_t **argv_array;
void free_argv(void) {
if (argv_array != NULL) {
for (size_t i = 0; argv_array[i] != NULL; i++) {
free(argv_array[i]);
}
free(argv_array);
}
}
public:
process_t() :
argv_array(NULL),
type(0),
actual_cmd(NULL),
pid(0),
pipe_write_fd(0),
pipe_read_fd(0),
completed(0),
stopped(0),
status(0),
count_help_magic(0),
next(NULL)
#ifdef HAVE__PROC_SELF_STAT
,last_time(),
unsigned long last_jiffies(0)
#endif
{
}
~process_t()
{
if (this->next != NULL)
delete this->next;
this->free_argv();
}
/**
Type of process. Can be one of \c EXTERNAL, \c
INTERNAL_BUILTIN, \c INTERNAL_FUNCTION, \c INTERNAL_BLOCK,
INTERNAL_EXEC, or INTERNAL_BUFFER
*/
int type;
/** Sets argv */
void set_argv(wchar_t **argv) {
free_argv();
/** argv parameter for for execv, builtin_run, etc. */
wchar_t **argv;
#if 0
// argv must be a malloc'd array of malloc'd strings. This bit of nonsense below can help catch if someone doesn't pass us something from malloc.
if (argv) {
for (size_t i=0; argv[i]; i++) {
wchar_t *tmp = wcsdup(argv[i]);
free(argv[i]);
argv[i] = tmp;
}
}
#endif
this->argv_array = argv;
}
/** Returns argv */
const wchar_t * const *get_argv(void) const { return argv_array; }
/** Returns argv[0] */
const wchar_t *argv0(void) const { return argv_array[0]; }
/** Returns argv[idx] */
const wchar_t *argv(size_t idx) const { return argv_array[idx]; }
/** actual command to pass to exec in case of EXTERNAL or INTERNAL_EXEC */
wchar_t *actual_cmd;
const wchar_t *actual_cmd;
/** process ID */
pid_t pid;
@ -161,8 +227,8 @@ class process_t
/** Special flag to tell the evaluation function for count to print the help information */
int count_help_magic;
/** next process in pipeline */
struct process_t *next;
/** Next process in pipeline. We own this and we are responsible for deleting it. */
struct process_t *next;
#ifdef HAVE__PROC_SELF_STAT
/** Last time of cpu time check */
struct timeval last_time;
@ -239,7 +305,7 @@ class job_t
public:
job_t(int jobid) :
command(NULL),
command(),
first_process(NULL),
pgid(0),
tmodes(),
@ -248,6 +314,11 @@ class job_t
flags(0)
{
}
~job_t() {
if (first_process != NULL)
delete first_process;
}
/**
@ -255,10 +326,12 @@ class job_t
job. It is used for displaying messages about job status
on the terminal.
*/
const wchar_t *command;
wcstring command;
const wchar_t *command_cstr() const { return command.c_str(); }
/**
A linked list of all the processes in this job.
A linked list of all the processes in this job. We are responsible for deleting this when we are deallocated.
*/
process_t *first_process;