mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-07 07:11:14 -03:00
Some changes to migrate towards C++ and a multithreaded model
This commit is contained in:
412
proc.cpp
412
proc.cpp
@@ -7,7 +7,7 @@ will call proc to create representations of the running jobs as
|
||||
needed.
|
||||
|
||||
Some of the code in this file is based on code from the Glibc manual.
|
||||
|
||||
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
@@ -76,7 +76,7 @@ Some of the code in this file is based on code from the Glibc manual.
|
||||
#include "output.h"
|
||||
|
||||
/**
|
||||
Size of message buffer
|
||||
Size of message buffer
|
||||
*/
|
||||
#define MESS_SIZE 256
|
||||
|
||||
@@ -85,13 +85,13 @@ Some of the code in this file is based on code from the Glibc manual.
|
||||
*/
|
||||
#define BUFFER_SIZE 4096
|
||||
|
||||
/**
|
||||
Status of last process to exit
|
||||
/**
|
||||
Status of last process to exit
|
||||
*/
|
||||
static int last_status=0;
|
||||
|
||||
/**
|
||||
Signal flag
|
||||
Signal flag
|
||||
*/
|
||||
static sig_atomic_t got_signal=0;
|
||||
|
||||
@@ -139,7 +139,7 @@ void proc_init()
|
||||
|
||||
|
||||
/**
|
||||
Remove job from list of jobs
|
||||
Remove job from list of jobs
|
||||
*/
|
||||
static int job_remove( job_t *j )
|
||||
{
|
||||
@@ -156,7 +156,7 @@ static int job_remove( job_t *j )
|
||||
sanity_lose();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if( prev == 0 )
|
||||
first_job = j->next;
|
||||
else
|
||||
@@ -184,7 +184,7 @@ void proc_destroy()
|
||||
{
|
||||
debug( 2, L"freeing leaked job %ls", first_job->command );
|
||||
job_free( first_job );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void proc_set_last_status( int s )
|
||||
@@ -201,25 +201,25 @@ job_t *job_create()
|
||||
{
|
||||
int free_id=1;
|
||||
job_t *res;
|
||||
|
||||
|
||||
while( job_get( free_id ) != 0 )
|
||||
free_id++;
|
||||
res = halloc( 0, sizeof(job_t) );
|
||||
res = (job_t *)halloc( 0, sizeof(job_t) );
|
||||
res->next = first_job;
|
||||
res->job_id = free_id;
|
||||
first_job = res;
|
||||
|
||||
job_set_flag( res,
|
||||
JOB_CONTROL,
|
||||
(job_control_mode==JOB_CONTROL_ALL) ||
|
||||
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 );
|
||||
// fwprintf( stderr, L"Create job %d\n", res->job_id );
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
job_t *job_get( int id )
|
||||
{
|
||||
job_t *res = first_job;
|
||||
@@ -227,7 +227,7 @@ job_t *job_get( int id )
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
while( res != 0 )
|
||||
{
|
||||
if( res->job_id == id )
|
||||
@@ -240,7 +240,7 @@ job_t *job_get( int id )
|
||||
job_t *job_get_from_pid( int pid )
|
||||
{
|
||||
job_t *res = first_job;
|
||||
|
||||
|
||||
while( res != 0 )
|
||||
{
|
||||
if( res->pgid == pid )
|
||||
@@ -251,8 +251,8 @@ job_t *job_get_from_pid( int pid )
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Return true if all processes in the job have stopped or completed.
|
||||
/*
|
||||
Return true if all processes in the job have stopped or completed.
|
||||
|
||||
\param j the job to test
|
||||
*/
|
||||
@@ -271,20 +271,20 @@ int job_is_stopped( const job_t *j )
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Return true if the last processes in the job has completed.
|
||||
/*
|
||||
Return true if the last processes in the job has completed.
|
||||
|
||||
\param j the job to test
|
||||
*/
|
||||
int job_is_completed( const job_t *j )
|
||||
{
|
||||
process_t *p;
|
||||
|
||||
|
||||
for (p = j->first_process; p->next; p = p->next)
|
||||
;
|
||||
|
||||
|
||||
return p->completed;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void job_set_flag( job_t *j, int flag, int set )
|
||||
@@ -301,10 +301,10 @@ int job_get_flag( job_t *j, int flag )
|
||||
}
|
||||
|
||||
int job_signal( job_t *j, int signal )
|
||||
{
|
||||
{
|
||||
pid_t my_pid = getpid();
|
||||
int res = 0;
|
||||
|
||||
|
||||
if( j->pgid != my_pid )
|
||||
{
|
||||
res = killpg( j->pgid, SIGHUP );
|
||||
@@ -337,7 +337,7 @@ int job_signal( job_t *j, int signal )
|
||||
|
||||
/**
|
||||
Store the status of the process pid that was returned by waitpid.
|
||||
Return 0 if all went well, nonzero otherwise.
|
||||
Return 0 if all went well, nonzero otherwise.
|
||||
*/
|
||||
static void mark_process_status( job_t *j,
|
||||
process_t *p,
|
||||
@@ -345,19 +345,19 @@ static void mark_process_status( job_t *j,
|
||||
{
|
||||
// debug( 0, L"Process %ls %ls", p->argv[0], WIFSTOPPED (status)?L"stopped":(WIFEXITED( status )?L"exited":(WIFSIGNALED( status )?L"signaled to exit":L"BLARGH")) );
|
||||
p->status = status;
|
||||
|
||||
|
||||
if (WIFSTOPPED (status))
|
||||
{
|
||||
p->stopped = 1;
|
||||
}
|
||||
else if (WIFSIGNALED(status) || WIFEXITED(status))
|
||||
else if (WIFSIGNALED(status) || WIFEXITED(status))
|
||||
{
|
||||
p->completed = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ssize_t ignore;
|
||||
|
||||
|
||||
/* This should never be reached */
|
||||
p->completed = 1;
|
||||
|
||||
@@ -388,10 +388,10 @@ static void handle_child_status( pid_t pid, int status )
|
||||
int found_proc = 0;
|
||||
job_t *j=0;
|
||||
process_t *p=0;
|
||||
// char mess[MESS_SIZE];
|
||||
found_proc = 0;
|
||||
// char mess[MESS_SIZE];
|
||||
found_proc = 0;
|
||||
/*
|
||||
snprintf( mess,
|
||||
snprintf( mess,
|
||||
MESS_SIZE,
|
||||
"Process %d\n",
|
||||
(int) pid );
|
||||
@@ -410,8 +410,8 @@ static void handle_child_status( pid_t pid, int status )
|
||||
"Process %d is %ls from job %ls\n",
|
||||
(int) pid, p->actual_cmd, j->command );
|
||||
write( 2, mess, strlen(mess ));
|
||||
*/
|
||||
|
||||
*/
|
||||
|
||||
mark_process_status ( j, p, status);
|
||||
if( p->completed && prev != 0 )
|
||||
{
|
||||
@@ -420,7 +420,7 @@ static void handle_child_status( pid_t pid, int status )
|
||||
/* snprintf( mess,
|
||||
MESS_SIZE,
|
||||
"Kill previously uncompleted process %ls (%d)\n",
|
||||
prev->actual_cmd,
|
||||
prev->actual_cmd,
|
||||
prev->pid );
|
||||
write( 2, mess, strlen(mess ));
|
||||
*/
|
||||
@@ -435,15 +435,15 @@ static void handle_child_status( pid_t pid, int status )
|
||||
}
|
||||
|
||||
|
||||
if( WIFSIGNALED( status ) &&
|
||||
( WTERMSIG(status)==SIGINT ||
|
||||
if( WIFSIGNALED( status ) &&
|
||||
( WTERMSIG(status)==SIGINT ||
|
||||
WTERMSIG(status)==SIGQUIT ) )
|
||||
{
|
||||
if( !is_interactive_session )
|
||||
{
|
||||
{
|
||||
struct sigaction act;
|
||||
sigemptyset( & act.sa_mask );
|
||||
act.sa_flags=0;
|
||||
act.sa_flags=0;
|
||||
act.sa_handler=SIG_DFL;
|
||||
sigaction( SIGINT, &act, 0 );
|
||||
sigaction( SIGQUIT, &act, 0 );
|
||||
@@ -458,34 +458,34 @@ static void handle_child_status( pid_t pid, int status )
|
||||
{
|
||||
c->skip=1;
|
||||
c=c->outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( !found_proc )
|
||||
{
|
||||
/*
|
||||
/*
|
||||
A child we lost track of?
|
||||
|
||||
|
||||
There have been bugs in both subshell handling and in
|
||||
builtin handling that have caused this previously...
|
||||
*/
|
||||
/* snprintf( mess,
|
||||
/* snprintf( mess,
|
||||
MESS_SIZE,
|
||||
"Process %d not found by %d\n",
|
||||
(int) pid, (int)getpid() );
|
||||
|
||||
write( 2, mess, strlen(mess ));
|
||||
*/
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void job_handle_signal ( int signal, siginfo_t *info, void *con )
|
||||
{
|
||||
|
||||
|
||||
int status;
|
||||
pid_t pid;
|
||||
int errno_old = errno;
|
||||
@@ -503,19 +503,19 @@ void job_handle_signal ( int signal, siginfo_t *info, void *con )
|
||||
{
|
||||
errno=errno_old;
|
||||
return;
|
||||
}
|
||||
}
|
||||
default:
|
||||
|
||||
handle_child_status( pid, status );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
kill( 0, SIGIO );
|
||||
errno=errno_old;
|
||||
}
|
||||
|
||||
/**
|
||||
Format information about job status for the user to look at.
|
||||
/**
|
||||
Format information about job status for the user to look at.
|
||||
|
||||
\param j the job to test
|
||||
\param status a string description of the job exit type
|
||||
@@ -531,46 +531,46 @@ static void format_job_info( const job_t *j, const wchar_t *status )
|
||||
|
||||
void proc_fire_event( const wchar_t *msg, int type, pid_t pid, int status )
|
||||
{
|
||||
|
||||
|
||||
event.type=type;
|
||||
event.param1.pid = pid;
|
||||
|
||||
al_push( &event.arguments, msg );
|
||||
|
||||
al_push( &event.arguments, msg );
|
||||
|
||||
sb_printf( &event_pid, L"%d", pid );
|
||||
al_push( &event.arguments, event_pid.buff );
|
||||
|
||||
sb_printf( &event_status, L"%d", status );
|
||||
|
||||
sb_printf( &event_status, L"%d", status );
|
||||
al_push( &event.arguments, event_status.buff );
|
||||
|
||||
event_fire( &event );
|
||||
|
||||
al_truncate( &event.arguments, 0 );
|
||||
sb_clear( &event_pid );
|
||||
sb_clear( &event_status );
|
||||
}
|
||||
sb_clear( &event_pid );
|
||||
sb_clear( &event_status );
|
||||
}
|
||||
|
||||
int job_reap( int interactive )
|
||||
{
|
||||
job_t *j, *jnext;
|
||||
job_t *j, *jnext;
|
||||
int found=0;
|
||||
|
||||
|
||||
static int locked = 0;
|
||||
|
||||
locked++;
|
||||
|
||||
|
||||
locked++;
|
||||
|
||||
/*
|
||||
job_read may fire an event handler, we do not want to call
|
||||
ourselves recursively (to avoid infinite recursion).
|
||||
*/
|
||||
if( locked>1 )
|
||||
return 0;
|
||||
|
||||
|
||||
for( j=first_job; j; j=jnext)
|
||||
{
|
||||
{
|
||||
process_t *p;
|
||||
jnext = j->next;
|
||||
|
||||
|
||||
/*
|
||||
If we are reaping only jobs who do not need status messages
|
||||
sent to the console, do not consider reaping jobs that need
|
||||
@@ -580,28 +580,28 @@ int job_reap( int interactive )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
for( p=j->first_process; p; p=p->next )
|
||||
{
|
||||
int s;
|
||||
if( !p->completed )
|
||||
continue;
|
||||
|
||||
|
||||
if( !p->pid )
|
||||
continue;
|
||||
|
||||
continue;
|
||||
|
||||
s = p->status;
|
||||
|
||||
proc_fire_event( L"PROCESS_EXIT", EVENT_EXIT, p->pid, ( WIFSIGNALED(s)?-1:WEXITSTATUS( s )) );
|
||||
|
||||
|
||||
proc_fire_event( L"PROCESS_EXIT", EVENT_EXIT, p->pid, ( WIFSIGNALED(s)?-1:WEXITSTATUS( s )) );
|
||||
|
||||
if( WIFSIGNALED(s) )
|
||||
{
|
||||
/*
|
||||
/*
|
||||
Ignore signal SIGPIPE.We issue it ourselves to the pipe
|
||||
writer when the pipe reader dies.
|
||||
*/
|
||||
if( WTERMSIG(s) != SIGPIPE )
|
||||
{
|
||||
{
|
||||
int proc_is_job = ((p==j->first_process) && (p->next == 0));
|
||||
if( proc_is_job )
|
||||
job_set_flag( j, JOB_NOTIFIED, 1 );
|
||||
@@ -611,7 +611,7 @@ int job_reap( int interactive )
|
||||
fwprintf( stdout,
|
||||
_( L"%ls: Job %d, \'%ls\' terminated by signal %ls (%ls)" ),
|
||||
program_name,
|
||||
j->job_id,
|
||||
j->job_id,
|
||||
j->command,
|
||||
sig2wcs(WTERMSIG(p->status)),
|
||||
signal_get_desc( WTERMSIG(p->status) ) );
|
||||
@@ -627,43 +627,43 @@ int job_reap( int interactive )
|
||||
signal_get_desc( WTERMSIG(p->status) ) );
|
||||
tputs(clr_eol,1,&writeb);
|
||||
fwprintf (stdout, L"\n" );
|
||||
found=1;
|
||||
found=1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
/*
|
||||
Clear status so it is not reported more than once
|
||||
*/
|
||||
p->status = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
/*
|
||||
If all processes have completed, tell the user the job has
|
||||
completed and delete it from the active job list.
|
||||
completed and delete it from the active job list.
|
||||
*/
|
||||
if( job_is_completed( j ) )
|
||||
if( job_is_completed( j ) )
|
||||
{
|
||||
if( !job_get_flag( j, JOB_FOREGROUND) && !job_get_flag( j, JOB_NOTIFIED ) && !job_get_flag( j, JOB_SKIP_NOTIFICATION ) )
|
||||
{
|
||||
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 );
|
||||
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 ) && !job_get_flag( j, JOB_NOTIFIED ) )
|
||||
}
|
||||
else if( job_is_stopped( j ) && !job_get_flag( j, JOB_NOTIFIED ) )
|
||||
{
|
||||
/*
|
||||
Notify the user about newly stopped jobs.
|
||||
/*
|
||||
Notify the user about newly stopped jobs.
|
||||
*/
|
||||
if( !job_get_flag( j, JOB_SKIP_NOTIFICATION ) )
|
||||
{
|
||||
format_job_info( j, _( L"stopped" ) );
|
||||
found=1;
|
||||
}
|
||||
}
|
||||
job_set_flag( j, JOB_NOTIFIED, 1 );
|
||||
}
|
||||
}
|
||||
@@ -672,8 +672,8 @@ int job_reap( int interactive )
|
||||
fflush( stdout );
|
||||
|
||||
locked = 0;
|
||||
|
||||
return found;
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
@@ -692,36 +692,36 @@ unsigned long proc_get_jiffies( process_t *p )
|
||||
wchar_t fn[FN_SIZE];
|
||||
|
||||
char state;
|
||||
int pid, ppid, pgrp,
|
||||
int pid, ppid, pgrp,
|
||||
session, tty_nr, tpgid,
|
||||
exit_signal, processor;
|
||||
|
||||
long int cutime, cstime, priority,
|
||||
nice, placeholder, itrealvalue,
|
||||
exit_signal, processor;
|
||||
|
||||
long int cutime, cstime, priority,
|
||||
nice, placeholder, itrealvalue,
|
||||
rss;
|
||||
unsigned long int flags, minflt, cminflt,
|
||||
majflt, cmajflt, utime,
|
||||
stime, starttime, vsize,
|
||||
unsigned long int flags, minflt, cminflt,
|
||||
majflt, cmajflt, utime,
|
||||
stime, starttime, vsize,
|
||||
rlim, startcode, endcode,
|
||||
startstack, kstkesp, kstkeip,
|
||||
signal, blocked, sigignore,
|
||||
sigcatch, wchan, nswap, cnswap;
|
||||
char comm[1024];
|
||||
|
||||
|
||||
if( p->pid <= 0 )
|
||||
return 0;
|
||||
|
||||
|
||||
swprintf( fn, FN_SIZE, L"/proc/%d/stat", p->pid );
|
||||
|
||||
|
||||
FILE *f = wfopen( fn, "r" );
|
||||
if( !f )
|
||||
return 0;
|
||||
|
||||
int count = fscanf( f,
|
||||
"%d %s %c "
|
||||
|
||||
int count = fscanf( f,
|
||||
"%d %s %c "
|
||||
"%d %d %d "
|
||||
"%d %d %lu "
|
||||
|
||||
|
||||
"%lu %lu %lu "
|
||||
"%lu %lu %lu "
|
||||
"%ld %ld %ld "
|
||||
@@ -735,15 +735,15 @@ unsigned long proc_get_jiffies( process_t *p )
|
||||
"%lu %lu %lu "
|
||||
|
||||
"%lu %d %d ",
|
||||
|
||||
&pid, comm, &state,
|
||||
&ppid, &pgrp, &session,
|
||||
|
||||
&pid, comm, &state,
|
||||
&ppid, &pgrp, &session,
|
||||
&tty_nr, &tpgid, &flags,
|
||||
|
||||
&minflt, &cminflt, &majflt,
|
||||
&cmajflt, &utime, &stime,
|
||||
&cutime, &cstime, &priority,
|
||||
|
||||
|
||||
&nice, &placeholder, &itrealvalue,
|
||||
&starttime, &vsize, &rss,
|
||||
&rlim, &startcode, &endcode,
|
||||
@@ -765,7 +765,7 @@ unsigned long proc_get_jiffies( process_t *p )
|
||||
*/
|
||||
fclose( f );
|
||||
return utime+stime+cutime+cstime;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -775,14 +775,14 @@ void proc_update_jiffies()
|
||||
{
|
||||
job_t *j;
|
||||
process_t *p;
|
||||
|
||||
|
||||
for( j=first_job; j; j=j->next )
|
||||
{
|
||||
for( p=j->first_process; p; p=p->next )
|
||||
{
|
||||
gettimeofday( &p->last_time, 0 );
|
||||
p->last_jiffies = proc_get_jiffies( p );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -791,8 +791,8 @@ void proc_update_jiffies()
|
||||
|
||||
/**
|
||||
Check if there are buffers associated with the job, and select on
|
||||
them for a while if available.
|
||||
|
||||
them for a while if available.
|
||||
|
||||
\param j the job to test
|
||||
|
||||
\return 1 if buffers were avaialble, zero otherwise
|
||||
@@ -804,7 +804,7 @@ static int select_try( job_t *j )
|
||||
io_data_t *d;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
|
||||
|
||||
for( d = j->io; d; d=d->next )
|
||||
{
|
||||
if( d->io_mode == IO_BUFFER )
|
||||
@@ -816,15 +816,15 @@ static int select_try( job_t *j )
|
||||
debug( 3, L"select_try on %d\n", fd );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( maxfd >= 0 )
|
||||
{
|
||||
int retval;
|
||||
struct timeval tv;
|
||||
|
||||
|
||||
tv.tv_sec=0;
|
||||
tv.tv_usec=10000;
|
||||
|
||||
|
||||
retval =select( maxfd+1, &fds, 0, 0, &tv );
|
||||
return retval > 0;
|
||||
}
|
||||
@@ -833,7 +833,7 @@ static int select_try( job_t *j )
|
||||
}
|
||||
|
||||
/**
|
||||
Read from descriptors until they are empty.
|
||||
Read from descriptors until they are empty.
|
||||
|
||||
\param j the job to test
|
||||
*/
|
||||
@@ -846,13 +846,13 @@ static void read_try( job_t *j )
|
||||
*/
|
||||
for( d = j->io; d; d=d->next )
|
||||
{
|
||||
|
||||
|
||||
if( d->io_mode == IO_BUFFER )
|
||||
{
|
||||
buff=d;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( buff )
|
||||
{
|
||||
debug( 3, L"proc::read_try('%ls')\n", j->command );
|
||||
@@ -860,7 +860,7 @@ static void read_try( job_t *j )
|
||||
{
|
||||
char b[BUFFER_SIZE];
|
||||
int l;
|
||||
|
||||
|
||||
l=read_blocked( buff->param1.pipe_fd[0],
|
||||
b, BUFFER_SIZE );
|
||||
if( l==0 )
|
||||
@@ -871,23 +871,23 @@ static void read_try( job_t *j )
|
||||
{
|
||||
if( errno != EAGAIN )
|
||||
{
|
||||
debug( 1,
|
||||
debug( 1,
|
||||
_( L"An error occured while reading output from code block" ) );
|
||||
wperror( L"read_try" );
|
||||
}
|
||||
wperror( L"read_try" );
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
b_append( buff->param2.out_buffer, b, l );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Give ownership of the terminal to the specified job.
|
||||
Give ownership of the terminal to the specified job.
|
||||
|
||||
\param j The job to give the terminal to.
|
||||
|
||||
@@ -897,19 +897,19 @@ static void read_try( job_t *j )
|
||||
*/
|
||||
static int terminal_give_to_job( job_t *j, int cont )
|
||||
{
|
||||
|
||||
|
||||
if( tcsetpgrp (0, j->pgid) )
|
||||
{
|
||||
debug( 1,
|
||||
_( L"Could not send job %d ('%ls') to foreground" ),
|
||||
j->job_id,
|
||||
debug( 1,
|
||||
_( L"Could not send job %d ('%ls') to foreground" ),
|
||||
j->job_id,
|
||||
j->command );
|
||||
wperror( L"tcsetpgrp" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if( cont )
|
||||
{
|
||||
{
|
||||
if( tcsetattr (0, TCSADRAIN, &j->tmodes))
|
||||
{
|
||||
debug( 1,
|
||||
@@ -926,20 +926,20 @@ static int terminal_give_to_job( job_t *j, int cont )
|
||||
/**
|
||||
Returns contol of the terminal to the shell, and saves the terminal
|
||||
attribute state to the job, so that we can restore the terminal
|
||||
ownership to the job at a later time .
|
||||
ownership to the job at a later time .
|
||||
*/
|
||||
static int terminal_return_from_job( job_t *j)
|
||||
{
|
||||
|
||||
|
||||
if( tcsetpgrp (0, getpgrp()) )
|
||||
{
|
||||
debug( 1, _( L"Could not return shell to foreground" ) );
|
||||
wperror( L"tcsetpgrp" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Save jobs terminal modes.
|
||||
|
||||
/*
|
||||
Save jobs terminal modes.
|
||||
*/
|
||||
if( tcgetattr (0, &j->tmodes) )
|
||||
{
|
||||
@@ -947,9 +947,9 @@ static int terminal_return_from_job( job_t *j)
|
||||
wperror( L"tcgetattr" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Restore the shell's terminal modes.
|
||||
|
||||
/*
|
||||
Restore the shell's terminal modes.
|
||||
*/
|
||||
if( tcsetattr (0, TCSADRAIN, &shell_modes))
|
||||
{
|
||||
@@ -972,35 +972,35 @@ void job_continue (job_t *j, int cont)
|
||||
job_set_flag( j, JOB_NOTIFIED, 0 );
|
||||
|
||||
CHECK_BLOCK();
|
||||
|
||||
|
||||
debug( 4,
|
||||
L"Continue job %d, gid %d (%ls), %ls, %ls",
|
||||
j->job_id,
|
||||
j->job_id,
|
||||
j->pgid,
|
||||
j->command,
|
||||
job_is_completed( j )?L"COMPLETED":L"UNCOMPLETED",
|
||||
j->command,
|
||||
job_is_completed( j )?L"COMPLETED":L"UNCOMPLETED",
|
||||
is_interactive?L"INTERACTIVE":L"NON-INTERACTIVE" );
|
||||
|
||||
|
||||
if( !job_is_completed( j ) )
|
||||
{
|
||||
if( job_get_flag( j, JOB_TERMINAL ) && job_get_flag( j, JOB_FOREGROUND ) )
|
||||
{
|
||||
{
|
||||
/* Put the job into the foreground. */
|
||||
int ok;
|
||||
|
||||
|
||||
signal_block();
|
||||
|
||||
|
||||
ok = terminal_give_to_job( j, cont );
|
||||
|
||||
signal_unblock();
|
||||
|
||||
signal_unblock();
|
||||
|
||||
if( !ok )
|
||||
return;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
Send the job a continue signal, if necessary.
|
||||
|
||||
/*
|
||||
Send the job a continue signal, if necessary.
|
||||
*/
|
||||
if( cont )
|
||||
{
|
||||
@@ -1025,16 +1025,16 @@ void job_continue (job_t *j, int cont)
|
||||
{
|
||||
wperror (L"kill (SIGCONT)");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( job_get_flag( j, JOB_FOREGROUND ) )
|
||||
{
|
||||
int quit = 0;
|
||||
|
||||
/*
|
||||
|
||||
/*
|
||||
Wait for job to report. Looks a bit ugly because it has to
|
||||
handle the possibility that a signal is dispatched while
|
||||
running job_is_stopped().
|
||||
@@ -1052,16 +1052,16 @@ void job_continue (job_t *j, int cont)
|
||||
|
||||
if( !quit )
|
||||
{
|
||||
|
||||
// debug( 1, L"select_try()" );
|
||||
|
||||
// debug( 1, L"select_try()" );
|
||||
switch( select_try(j) )
|
||||
{
|
||||
case 1:
|
||||
case 1:
|
||||
{
|
||||
read_try( j );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case -1:
|
||||
{
|
||||
/*
|
||||
@@ -1072,7 +1072,7 @@ void job_continue (job_t *j, int cont)
|
||||
improvement on my 300 MHz machine) on
|
||||
short-lived jobs.
|
||||
*/
|
||||
int status;
|
||||
int status;
|
||||
pid_t pid = waitpid(-1, &status, WUNTRACED );
|
||||
if( pid > 0 )
|
||||
{
|
||||
@@ -1091,20 +1091,20 @@ void job_continue (job_t *j, int cont)
|
||||
{
|
||||
quit = 1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( job_get_flag( j, JOB_FOREGROUND ) )
|
||||
{
|
||||
|
||||
|
||||
if( job_is_completed( j ))
|
||||
{
|
||||
process_t *p = j->first_process;
|
||||
@@ -1113,51 +1113,51 @@ void job_continue (job_t *j, int cont)
|
||||
|
||||
if( WIFEXITED( p->status ) || WIFSIGNALED(p->status))
|
||||
{
|
||||
/*
|
||||
/*
|
||||
Mark process status only if we are in the foreground
|
||||
and the last process in a pipe, and it is not a short circuted builtin
|
||||
*/
|
||||
if( p->pid )
|
||||
{
|
||||
int status = proc_format_status(p->status);
|
||||
|
||||
|
||||
proc_set_last_status( job_get_flag( j, JOB_NEGATE )?!status:status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
Put the shell back in the foreground.
|
||||
/*
|
||||
Put the shell back in the foreground.
|
||||
*/
|
||||
if( job_get_flag( j, JOB_TERMINAL ) && job_get_flag( j, JOB_FOREGROUND ) )
|
||||
{
|
||||
int ok;
|
||||
|
||||
|
||||
signal_block();
|
||||
|
||||
ok = terminal_return_from_job( j );
|
||||
|
||||
|
||||
signal_unblock();
|
||||
|
||||
|
||||
if( !ok )
|
||||
return;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
int proc_format_status(int status)
|
||||
int proc_format_status(int status)
|
||||
{
|
||||
if( WIFSIGNALED( status ) )
|
||||
if( WIFSIGNALED( status ) )
|
||||
{
|
||||
return 128+WTERMSIG(status);
|
||||
}
|
||||
else if( WIFEXITED( status ) )
|
||||
}
|
||||
else if( WIFEXITED( status ) )
|
||||
{
|
||||
return WEXITSTATUS(status);
|
||||
}
|
||||
return status;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1165,22 +1165,22 @@ void proc_sanity_check()
|
||||
{
|
||||
job_t *j;
|
||||
job_t *fg_job=0;
|
||||
|
||||
|
||||
for( j = first_job; j ; j=j->next )
|
||||
{
|
||||
process_t *p;
|
||||
|
||||
if( !job_get_flag( j, JOB_CONSTRUCTED ) )
|
||||
continue;
|
||||
|
||||
|
||||
validate_pointer( j->command,
|
||||
_( L"Job command" ),
|
||||
|
||||
|
||||
validate_pointer( j->command,
|
||||
_( L"Job command" ),
|
||||
0 );
|
||||
validate_pointer( j->first_process,
|
||||
_( L"Process list pointer" ),
|
||||
0 );
|
||||
validate_pointer( j->next,
|
||||
validate_pointer( j->next,
|
||||
_( L"Job list pointer" ),
|
||||
1 );
|
||||
|
||||
@@ -1191,7 +1191,7 @@ void proc_sanity_check()
|
||||
{
|
||||
if( fg_job != 0 )
|
||||
{
|
||||
debug( 0,
|
||||
debug( 0,
|
||||
_( L"More than one job in foreground: job 1: '%ls' job 2: '%ls'"),
|
||||
fg_job->command,
|
||||
j->command );
|
||||
@@ -1199,39 +1199,39 @@ void proc_sanity_check()
|
||||
}
|
||||
fg_job = j;
|
||||
}
|
||||
|
||||
|
||||
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->next, _( L"Process list pointer" ), 1 );
|
||||
validate_pointer( p->actual_cmd, _( L"Process command" ), 1 );
|
||||
|
||||
|
||||
if ( (p->stopped & (~0x00000001)) != 0 )
|
||||
{
|
||||
debug( 0,
|
||||
_( L"Job '%ls', process '%ls' has inconsistent state \'stopped\'=%d" ),
|
||||
j->command,
|
||||
j->command,
|
||||
p->argv[0],
|
||||
p->stopped );
|
||||
sanity_lose();
|
||||
}
|
||||
|
||||
|
||||
if ( (p->completed & (~0x00000001)) != 0 )
|
||||
{
|
||||
debug( 0,
|
||||
_( L"Job '%ls', process '%ls' has inconsistent state \'completed\'=%d" ),
|
||||
j->command,
|
||||
j->command,
|
||||
p->argv[0],
|
||||
p->completed );
|
||||
sanity_lose();
|
||||
}
|
||||
|
||||
|
||||
p=p->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void proc_push_interactive( int value )
|
||||
|
||||
Reference in New Issue
Block a user