diff --git a/builtin.c b/builtin.c index 281b1e70a..bdd5a6cb2 100644 --- a/builtin.c +++ b/builtin.c @@ -2216,8 +2216,8 @@ static int builtin_fg( wchar_t **argv ) */ for( j=first_job; j; j=j->next ) { - if( j->constructed && (!job_is_completed(j)) && - ( (job_is_stopped(j) || !j->fg) && (j->job_control) ) ) + if( job_get_flag( j, JOB_CONSTRUCTED ) && (!job_is_completed(j)) && + ( (job_is_stopped(j) || (!job_get_flag(j, JOB_FOREGROUND)) ) && job_get_flag( j, JOB_CONTROL) ) ) { break; } @@ -2288,7 +2288,7 @@ static int builtin_fg( wchar_t **argv ) else { j = job_get_from_pid( pid ); - if( !j || !j->constructed || job_is_completed( j )) + if( !j || !job_get_flag( j, JOB_CONSTRUCTED ) || job_is_completed( j )) { sb_printf( sb_err, _( L"%ls: No suitable job: %d\n" ), @@ -2297,7 +2297,7 @@ static int builtin_fg( wchar_t **argv ) builtin_print_help( argv[0], sb_err ); j=0; } - else if( !j->job_control ) + else if( !job_get_flag( j, JOB_CONTROL) ) { sb_printf( sb_err, _( L"%ls: Can't put job %d, '%ls' to foreground because it is not under job control\n" ), @@ -2339,7 +2339,7 @@ static int builtin_fg( wchar_t **argv ) reader_write_title(); make_first( j ); - j->fg=1; + job_set_flag( j, JOB_FOREGROUND, 1 ); job_continue( j, job_is_stopped(j) ); } @@ -2360,7 +2360,7 @@ static int send_to_bg( job_t *j, const wchar_t *name ) builtin_print_help( L"bg", sb_err ); return STATUS_BUILTIN_ERROR; } - else if( !j->job_control ) + else if( !job_get_flag( j, JOB_CONTROL ) ) { sb_printf( sb_err, _( L"%ls: Can't put job %d, '%ls' to background because it is not under job control\n" ), @@ -2378,7 +2378,7 @@ static int send_to_bg( job_t *j, const wchar_t *name ) j->command ); } make_first( j ); - j->fg=0; + job_set_flag( j, JOB_FOREGROUND, 0 ); job_continue( j, job_is_stopped(j) ); return 0; } @@ -2396,7 +2396,7 @@ static int builtin_bg( wchar_t **argv ) job_t *j; for( j=first_job; j; j=j->next ) { - if( job_is_stopped(j) && j->job_control && (!job_is_completed(j)) ) + if( job_is_stopped(j) && job_get_flag( j, JOB_CONTROL ) && (!job_is_completed(j)) ) { break; } @@ -2519,7 +2519,6 @@ static void builtin_end_add_function_def( function_data_t *d ) wchar_t *def = wcsndup( parser_get_buffer()+current_block->tok_pos, parser_get_job_pos()-current_block->tok_pos ); - function_add( d->name, def, d->description, diff --git a/builtin_jobs.c b/builtin_jobs.c index 361f4a196..8b0791399 100644 --- a/builtin_jobs.c +++ b/builtin_jobs.c @@ -276,7 +276,7 @@ static int builtin_jobs( wchar_t **argv ) */ for( j=first_job; j; j=j->next ) { - if( j->constructed && !job_is_completed(j) ) + if( (j->flags & JOB_CONSTRUCTED) && !job_is_completed(j) ) { builtin_jobs_print( j, mode, !found ); return 0; @@ -330,7 +330,7 @@ static int builtin_jobs( wchar_t **argv ) /* Ignore unconstructed jobs, i.e. ourself. */ - if( j->constructed && !job_is_completed(j) ) + if( (j->flags & JOB_CONSTRUCTED) && !job_is_completed(j) ) { builtin_jobs_print( j, mode, !found ); found = 1; diff --git a/exec.c b/exec.c index 501369b32..5a53e91c9 100644 --- a/exec.c +++ b/exec.c @@ -609,7 +609,7 @@ static int set_child_group( job_t *j, process_t *p, int print_errors ) { int res = 0; - if( j->job_control ) + if( job_get_flag( j, JOB_CONTROL ) ) { if (!j->pgid) { @@ -638,7 +638,7 @@ static int set_child_group( job_t *j, process_t *p, int print_errors ) j->pgid = getpid(); } - if( j->terminal && j->fg ) + if( job_get_flag( j, JOB_TERMINAL ) && job_get_flag( j, JOB_FOREGROUND ) ) { if( tcsetpgrp (0, j->pgid) && print_errors ) { @@ -735,7 +735,7 @@ void exec( job_t *j ) } else { - j->constructed=1; + job_set_flag( j, JOB_CONSTRUCTED, 1 ); j->first_process->completed=1; return; } @@ -767,7 +767,7 @@ void exec( job_t *j ) inside a pipeline. */ - if( j->job_control ) + if( job_get_flag( j, JOB_CONTROL ) ) { for( p=j->first_process; p; p = p->next ) { @@ -991,8 +991,8 @@ void exec( job_t *j ) builtin_out_redirect = has_fd( j->io, 1 ); builtin_err_redirect = has_fd( j->io, 2 ); - fg = j->fg; - j->fg = 0; + fg = job_get_flag( j, JOB_FOREGROUND ); + job_set_flag( j, JOB_FOREGROUND, 0 ); signal_unblock(); @@ -1005,7 +1005,7 @@ void exec( job_t *j ) false during builtin execution so as not to confuse some job-handling builtins. */ - j->fg = fg; + job_set_flag( j, JOB_FOREGROUND, fg ); } if( close_stdin ) @@ -1041,7 +1041,7 @@ void exec( job_t *j ) */ if( p->next == 0 ) { - proc_set_last_status( j->negate?(!status):status); + proc_set_last_status( job_get_flag( j, JOB_NEGATE )?(!status):status); } p->completed = 1; break; @@ -1091,7 +1091,7 @@ void exec( job_t *j ) { if( p->next == 0 ) { - proc_set_last_status( j->negate?(!status):status); + proc_set_last_status( job_get_flag( j, JOB_NEGATE )?(!status):status); } p->completed = 1; } @@ -1182,7 +1182,7 @@ void exec( job_t *j ) { debug( 3, L"Set status of %ls to %d using short circut", j->command, p->status ); - proc_set_last_status( j->negate?(!p->status):p->status ); + proc_set_last_status( job_get_flag( j, JOB_NEGATE )?(!p->status):p->status ); } break; @@ -1316,9 +1316,9 @@ void exec( job_t *j ) for( tmp = block_io; tmp; tmp=tmp->next ) j->io = io_remove( j->io, tmp ); - j->constructed = 1; + job_set_flag( j, JOB_CONSTRUCTED, 1 ); - if( !j->fg ) + if( !job_get_flag( j, JOB_FOREGROUND ) ) { proc_last_bg_pid = j->pgid; } diff --git a/parser.c b/parser.c index 588ca4644..93f676e19 100644 --- a/parser.c +++ b/parser.c @@ -1362,7 +1362,7 @@ static void parse_job_main_loop( process_t *p, case TOK_BACKGROUND: { - j->fg = 0; + job_set_flag( j, JOB_FOREGROUND, 0 ); } case TOK_END: @@ -1381,7 +1381,7 @@ static void parse_job_main_loop( process_t *p, { int skip=0; - if( j->skip ) + if( job_get_flag( j, JOB_SKIP ) ) { skip = 1; } @@ -1622,7 +1622,7 @@ static void parse_job_main_loop( process_t *p, { if( unmatched_wildcard && !matched_wildcard ) { - j->wildcard_error = 1; + job_set_flag( j, JOB_WILDCARD_ERROR, 1 ); proc_set_last_status( STATUS_UNMATCHED_WILDCARD ); if( is_interactive && !is_block ) { @@ -1783,7 +1783,7 @@ static int parse_job( process_t *p, } else { - j->negate=1-j->negate; + job_set_flag( j, JOB_NEGATE, !job_get_flag( j, JOB_NEGATE ) ); consumed=1; } } @@ -1796,7 +1796,7 @@ static int parse_job( process_t *p, } else { - j->skip = proc_get_last_status(); + job_set_flag( j, JOB_SKIP, proc_get_last_status()); consumed=1; } } @@ -1809,7 +1809,7 @@ static int parse_job( process_t *p, } else { - j->skip = !proc_get_last_status(); + job_set_flag( j, JOB_SKIP, !proc_get_last_status()); consumed=1; } } @@ -2053,7 +2053,8 @@ static int parse_job( process_t *p, fwprintf( stderr, L"%ls", parser_current_line() ); current_tokenizer_pos=tmp; - j->skip=1; + + job_set_flag( j, JOB_SKIP, 1 ); proc_set_last_status( STATUS_UNKNOWN_COMMAND ); } } @@ -2258,9 +2259,10 @@ static void eval_job( tokenizer *tok ) case TOK_STRING: { j = job_create(); - j->fg=1; - j->terminal = j->job_control && (!is_subshell && !is_event); - j->skip_notification = is_subshell || is_block || is_event || (!is_interactive); + job_set_flag( j, JOB_FOREGROUND, 1 ); + job_set_flag( j, JOB_TERMINAL, job_get_flag( j, JOB_CONTROL ) ); + job_set_flag( j, JOB_TERMINAL, job_get_flag( j, JOB_CONTROL ) && (!is_subshell && !is_event)); + job_set_flag( j, JOB_SKIP_NOTIFICATION, is_subshell || is_block || is_event || (!is_interactive)); current_block->job = j; @@ -2303,11 +2305,11 @@ static void eval_job( tokenizer *tok ) p->cmd = wcsdup( j->command ); p->skipped=current_block->skip; } - + skip |= current_block->skip; - skip |= j->wildcard_error; - skip |= j->skip; - + skip |= job_get_flag( j, JOB_WILDCARD_ERROR ); + skip |= job_get_flag( j, JOB_SKIP ); + if(!skip ) { int was_builtin = 0; diff --git a/proc.c b/proc.c index a0f535db0..e13f8a7c6 100644 --- a/proc.c +++ b/proc.c @@ -211,8 +211,10 @@ job_t *job_create() res->job_id = free_id; first_job = res; - res->job_control = (job_control_mode==JOB_CONTROL_ALL) || - ((job_control_mode == JOB_CONTROL_INTERACTIVE) && (is_interactive)); + job_set_flag( res, + JOB_CONTROL, + (job_control_mode==JOB_CONTROL_ALL) || + ((job_control_mode == JOB_CONTROL_INTERACTIVE) && (is_interactive)) ); // if( res->job_id > 2 ) // fwprintf( stderr, L"Create job %d\n", res->job_id ); @@ -287,6 +289,20 @@ int job_is_completed( const job_t *j ) } +void job_set_flag( job_t *j, int flag, int set ) +{ + if( set ) + j->flags |= flag; + else + j->flags = j->flags & (0xffffffff ^ flag); +} + +int job_get_flag( job_t *j, int flag ) +{ + return j->flags&flag?1:0; +} + + /** Store the status of the process pid that was returned by waitpid. Return 0 if all went well, nonzero otherwise. @@ -521,7 +537,7 @@ int job_reap( int interactive ) sent to the console, do not consider reaping jobs that need status messages */ - if( (!j->skip_notification) && (!interactive) && (!j->fg)) + if( (!job_get_flag( j, JOB_SKIP_NOTIFICATION ) ) && (!interactive) && (!job_get_flag( j, JOB_FOREGROUND ))) { continue; } @@ -549,8 +565,8 @@ int job_reap( int interactive ) { int proc_is_job = ((p==j->first_process) && (p->next == 0)); if( proc_is_job ) - j->notified = 1; - if( !j->skip_notification ) + job_set_flag( j, JOB_NOTIFIED, 1 ); + if( !job_get_flag( j, JOB_SKIP_NOTIFICATION ) ) { if( proc_is_job ) fwprintf( stdout, @@ -589,30 +605,27 @@ int job_reap( int interactive ) */ if( job_is_completed( j ) ) { - if( !j->fg && !j->notified ) + if( !job_get_flag( j, JOB_FOREGROUND) && !job_get_flag( j, JOB_NOTIFIED ) && !job_get_flag( j, JOB_SKIP_NOTIFICATION ) ) { - if( !j->skip_notification ) - { - format_job_info( j, _( L"ended" ) ); - found=1; - } + format_job_info( j, _( L"ended" ) ); + found=1; } proc_fire_event( L"JOB_EXIT", EVENT_EXIT, -j->pgid, 0 ); proc_fire_event( L"JOB_EXIT", EVENT_JOB_ID, j->job_id, 0 ); job_free(j); } - else if( job_is_stopped( j ) && !j->notified ) + else if( job_is_stopped( j ) && !job_get_flag( j, JOB_NOTIFIED ) ) { /* Notify the user about newly stopped jobs. */ - if( !j->skip_notification ) + if( !job_get_flag( j, JOB_SKIP_NOTIFICATION ) ) { format_job_info( j, _( L"stopped" ) ); found=1; } - j->notified = 1; + job_set_flag( j, JOB_NOTIFIED, 1 ); } } @@ -843,7 +856,7 @@ void job_continue (job_t *j, int cont) job_remove( j ); j->next = first_job; first_job = j; - j->notified = 0; + job_set_flag( j, JOB_NOTIFIED, 0 ); debug( 4, L"Continue job %d (%ls), %ls, %ls", @@ -854,7 +867,7 @@ void job_continue (job_t *j, int cont) if( !job_is_completed( j ) ) { - if( j->terminal && j->fg ) + if( job_get_flag( j, JOB_TERMINAL ) && job_get_flag( j, JOB_FOREGROUND ) ) { /* Put the job into the foreground. */ signal_block(); @@ -893,7 +906,7 @@ void job_continue (job_t *j, int cont) for( p=j->first_process; p; p=p->next ) p->stopped=0; - if( j->job_control ) + if( job_get_flag( j, JOB_CONTROL ) ) { if( killpg( j->pgid, SIGCONT ) ) { @@ -914,7 +927,7 @@ void job_continue (job_t *j, int cont) } } - if( j->fg ) + if( job_get_flag( j, JOB_FOREGROUND ) ) { int quit = 0; @@ -968,7 +981,7 @@ void job_continue (job_t *j, int cont) } } - if( j->fg ) + if( job_get_flag( j, JOB_FOREGROUND ) ) { if( job_is_completed( j )) @@ -986,14 +999,14 @@ void job_continue (job_t *j, int cont) if( p->pid ) { debug( 3, L"Set status of %ls to %d", j->command, WEXITSTATUS(p->status) ); - proc_set_last_status( j->negate?(WEXITSTATUS(p->status)?0:1):WEXITSTATUS(p->status) ); + proc_set_last_status( job_get_flag( j, JOB_NEGATE )?(WEXITSTATUS(p->status)?0:1):WEXITSTATUS(p->status) ); } } } /* Put the shell back in the foreground. */ - if( j->terminal && j->fg ) + if( job_get_flag( j, JOB_TERMINAL ) && job_get_flag( j, JOB_FOREGROUND ) ) { signal_block(); if( tcsetpgrp (0, getpid()) ) @@ -1037,7 +1050,7 @@ void proc_sanity_check() { process_t *p; - if( !j->constructed ) + if( !job_get_flag( j, JOB_CONSTRUCTED ) ) continue; @@ -1054,7 +1067,7 @@ void proc_sanity_check() /* More than one foreground job? */ - if( j->fg && !(job_is_stopped(j) || job_is_completed(j) ) ) + if( job_get_flag( j, JOB_FOREGROUND ) && !(job_is_stopped(j) || job_is_completed(j) ) ) { if( fg_job != 0 ) { diff --git a/proc.h b/proc.h index baf7af536..cfed6acc6 100644 --- a/proc.h +++ b/proc.h @@ -146,6 +146,64 @@ typedef struct process } process_t; +/** + Constant for the flag variable in the job struct + + true if user was told about stopped job +*/ +#define JOB_NOTIFIED 1 +/** + Constant for the flag variable in the job struct + + Whether this job is in the foreground +*/ +#define JOB_FOREGROUND 2 +/** + Constant for the flag variable in the job struct + + Whether the specified job is completely constructed, + i.e. completely parsed, and every process in the job has been + forked, etc. +*/ +#define JOB_CONSTRUCTED 4 +/** + Constant for the flag variable in the job struct + + Whether the specified job is a part of a subshell, event handler or some other form of special job that should not be reported +*/ +#define JOB_SKIP_NOTIFICATION 8 +/** + Constant for the flag variable in the job struct + + Should the exit status be negated? This flag can only be set by the not builtin. +*/ +#define JOB_NEGATE 16 +/** + Constant for the flag variable in the job struct + + This flag is set to one on wildcard expansion errors. It means that the current command should not be executed +*/ +#define JOB_WILDCARD_ERROR 32 + +/** + Constant for the flag variable in the job struct + + Skip executing this job. This flag is set by the short-circut builtins, i.e. and and or +*/ +#define JOB_SKIP 64 + +/** + Constant for the flag variable in the job struct + + Whether the job is under job control +*/ +#define JOB_CONTROL 128 +/** + Constant for the flag variable in the job struct + + Whether the job wants to own the terminal when in the foreground +*/ +#define JOB_TERMINAL 256 /** A pipeline of one or more processes. */ typedef struct job @@ -156,45 +214,22 @@ typedef struct job process_t *first_process; /** process group ID */ pid_t pgid; - /** true if user was told about stopped job */ - int notified; /** saved terminal modes */ struct termios tmodes; /** The job id of the job*/ int job_id; - /** Whether this job is in the foreground */ - int fg; - /** - Whether the specified job is completely constructed, - i.e. completely parsed, and every process in the job has been - forked, etc. - */ - int constructed; - /** - Whether the specified job is a part of a subshell, event handler or some other form of special job that should not be reported - */ - int skip_notification; /** List of IO redrections for the job */ io_data_t *io; - - /** Should the exit status be negated? This flag can only be set by the not builtin. */ - int negate; - - /** This flag is set to one on wildcard expansion errors. It means that the current command should not be executed */ - int wildcard_error; - - /** Skip executing this job. This flag is set by the short-circut builtins, i.e. and and or */ - int skip; - - /** Whether the job is under job control */ - int job_control; - - /** Whether the job wants to own the terminal when in the foreground */ - int terminal; /** Pointer to the next job */ struct job *next; + + /** + Bitset containing information about the job. A combination of the JOB_* constants. + */ + int flags; + } job_t; @@ -260,6 +295,9 @@ extern int job_control_mode; */ extern int no_exec; +void job_set_flag( job_t *j, int flag, int set ); + +int job_get_flag( job_t *j, int flag ); /** Sets the status of the last process to exit