2006-05-26 21:38:11 +10:00
/** \file builtin_jobs.c
2012-11-18 11:23:22 +01:00
Functions for executing the jobs builtin .
2006-05-26 21:38:11 +10:00
*/
2006-08-11 11:18:35 +10:00
# include "config.h"
2006-05-26 21:38:11 +10:00
# include <stdlib.h>
# include <stdio.h>
# include <wchar.h>
# include <unistd.h>
# include <termios.h>
# include <errno.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <string.h>
# include <wctype.h>
# include "fallback.h"
# include "util.h"
# include "wutil.h"
# include "builtin.h"
# include "proc.h"
# include "parser.h"
# include "common.h"
# include "wgetopt.h"
2006-07-20 08:55:49 +10:00
2006-05-26 21:38:11 +10:00
/**
Print modes for the jobs builtin
*/
enum
{
2012-11-18 16:30:30 -08:00
JOBS_DEFAULT , /**< Print lots of general info */
JOBS_PRINT_PID , /**< Print pid of each process in job */
JOBS_PRINT_COMMAND , /**< Print command name of each process in job */
JOBS_PRINT_GROUP , /**< Print group id of job */
2006-05-26 21:38:11 +10:00
}
2012-11-18 16:30:30 -08:00
;
2006-05-26 21:38:11 +10:00
# ifdef HAVE__PROC_SELF_STAT
/**
Calculates the cpu usage ( in percent ) of the specified job .
*/
2012-11-18 16:30:30 -08:00
static int cpu_use ( const job_t * j )
2006-05-26 21:38:11 +10:00
{
2012-11-18 16:30:30 -08:00
double u = 0 ;
process_t * p ;
2006-05-26 21:38:11 +10:00
2012-11-18 16:30:30 -08:00
for ( p = j - > first_process ; p ; p = p - > next )
{
struct timeval t ;
int jiffies ;
gettimeofday ( & t , 0 ) ;
jiffies = proc_get_jiffies ( p ) ;
2006-05-26 21:38:11 +10:00
2012-11-18 16:30:30 -08:00
double t1 = 1000000.0 * p - > last_time . tv_sec + p - > last_time . tv_usec ;
double t2 = 1000000.0 * t . tv_sec + t . tv_usec ;
2006-05-26 21:38:11 +10:00
2012-11-18 16:30:30 -08:00
/* fwprintf( stderr, L"t1 %f t2 %f p1 %d p2 %d\n",
t1 , t2 , jiffies , p - > last_jiffies ) ;
*/
2006-05-26 21:38:11 +10:00
2012-11-18 16:30:30 -08:00
u + = ( ( double ) ( jiffies - p - > last_jiffies ) ) / ( t2 - t1 ) ;
}
return u * 1000000 ;
2006-05-26 21:38:11 +10:00
}
# endif
/**
Print information about the specified job
*/
2012-11-18 16:30:30 -08:00
static void builtin_jobs_print ( const job_t * j , int mode , int header )
2006-05-26 21:38:11 +10:00
{
2012-11-18 16:30:30 -08:00
process_t * p ;
switch ( mode )
{
2012-11-19 00:31:03 -08:00
case JOBS_DEFAULT :
2012-11-18 16:30:30 -08:00
{
2012-11-19 00:31:03 -08:00
if ( header )
{
/*
Print table header before first job
*/
stdout_buffer . append ( _ ( L " Job \t Group \t " ) ) ;
2006-05-26 21:38:11 +10:00
# ifdef HAVE__PROC_SELF_STAT
2012-11-19 00:31:03 -08:00
stdout_buffer . append ( _ ( L " CPU \t " ) ) ;
2006-05-26 21:38:11 +10:00
# endif
2012-11-19 00:31:03 -08:00
stdout_buffer . append ( _ ( L " State \t Command \n " ) ) ;
}
2006-05-26 21:38:11 +10:00
2012-11-19 00:31:03 -08:00
append_format ( stdout_buffer , L " %d \t %d \t " , j - > job_id , j - > pgid ) ;
2006-05-26 21:38:11 +10:00
# ifdef HAVE__PROC_SELF_STAT
2012-11-19 00:31:03 -08:00
append_format ( stdout_buffer , L " %d%% \t " , cpu_use ( j ) ) ;
2006-05-26 21:38:11 +10:00
# endif
2012-11-19 00:31:03 -08:00
stdout_buffer . append ( job_is_stopped ( j ) ? _ ( L " stopped " ) : _ ( L " running " ) ) ;
stdout_buffer . append ( L " \t " ) ;
stdout_buffer . append ( j - > command_wcstr ( ) ) ;
stdout_buffer . append ( L " \n " ) ;
break ;
2012-11-18 16:30:30 -08:00
}
2012-11-18 11:23:22 +01:00
2012-11-19 00:31:03 -08:00
case JOBS_PRINT_GROUP :
2012-11-18 16:30:30 -08:00
{
2012-11-19 00:31:03 -08:00
if ( header )
{
/*
Print table header before first job
*/
stdout_buffer . append ( _ ( L " Group \n " ) ) ;
}
append_format ( stdout_buffer , L " %d \n " , j - > pgid ) ;
break ;
2012-11-18 16:30:30 -08:00
}
2012-11-19 00:31:03 -08:00
case JOBS_PRINT_PID :
2012-11-18 16:30:30 -08:00
{
2012-11-19 00:31:03 -08:00
if ( header )
{
/*
Print table header before first job
*/
stdout_buffer . append ( _ ( L " Procces \n " ) ) ;
}
2012-11-18 11:23:22 +01:00
2012-11-19 00:31:03 -08:00
for ( p = j - > first_process ; p ; p = p - > next )
{
append_format ( stdout_buffer , L " %d \n " , p - > pid ) ;
}
break ;
2012-11-18 16:30:30 -08:00
}
2012-11-19 00:31:03 -08:00
case JOBS_PRINT_COMMAND :
2012-11-18 16:30:30 -08:00
{
2012-11-19 00:31:03 -08:00
if ( header )
{
/*
Print table header before first job
*/
stdout_buffer . append ( _ ( L " Command \n " ) ) ;
}
for ( p = j - > first_process ; p ; p = p - > next )
{
append_format ( stdout_buffer , L " %ls \n " , p - > argv0 ( ) ) ;
}
break ;
2012-11-18 16:30:30 -08:00
}
2012-11-18 11:23:22 +01:00
}
2006-05-26 21:38:11 +10:00
}
2006-06-13 23:43:28 +10:00
/**
The jobs builtin . Used fopr printing running jobs . Defined in builtin_jobs . c .
*/
2012-11-18 16:30:30 -08:00
static int builtin_jobs ( parser_t & parser , wchar_t * * argv )
2006-05-26 21:38:11 +10:00
{
2012-11-18 16:30:30 -08:00
int argc = 0 ;
int found = 0 ;
int mode = JOBS_DEFAULT ;
int print_last = 0 ;
const job_t * j ;
argc = builtin_count_args ( argv ) ;
woptind = 0 ;
while ( 1 )
{
static const struct woption
long_options [ ] =
2012-11-18 11:23:22 +01:00
{
2012-11-18 16:30:30 -08:00
{
L " pid " , no_argument , 0 , ' p '
}
,
{
L " command " , no_argument , 0 , ' c '
}
,
{
L " group " , no_argument , 0 , ' g '
}
,
{
L " last " , no_argument , 0 , ' l '
}
,
{
L " help " , no_argument , 0 , ' h '
}
,
{
0 , 0 , 0 , 0
}
2012-11-18 11:23:22 +01:00
}
2012-11-18 16:30:30 -08:00
;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
int opt_index = 0 ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
int opt = wgetopt_long ( argc ,
argv ,
L " pclgh " ,
long_options ,
& opt_index ) ;
if ( opt = = - 1 )
break ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
switch ( opt )
{
2012-11-19 00:31:03 -08:00
case 0 :
if ( long_options [ opt_index ] . flag ! = 0 )
break ;
append_format ( stderr_buffer ,
BUILTIN_ERR_UNKNOWN ,
argv [ 0 ] ,
long_options [ opt_index ] . name ) ;
2006-05-26 21:38:11 +10:00
2012-11-19 00:31:03 -08:00
builtin_print_help ( parser , argv [ 0 ] , stderr_buffer ) ;
2006-05-26 21:38:11 +10:00
2012-11-19 00:31:03 -08:00
return 1 ;
2006-05-26 21:38:11 +10:00
2012-11-19 00:31:03 -08:00
case ' p ' :
mode = JOBS_PRINT_PID ;
break ;
2006-05-26 21:38:11 +10:00
2012-11-19 00:31:03 -08:00
case ' c ' :
mode = JOBS_PRINT_COMMAND ;
break ;
2006-05-26 21:38:11 +10:00
2012-11-19 00:31:03 -08:00
case ' g ' :
mode = JOBS_PRINT_GROUP ;
break ;
2006-05-26 21:38:11 +10:00
2012-11-19 00:31:03 -08:00
case ' l ' :
{
print_last = 1 ;
break ;
}
2006-05-26 21:38:11 +10:00
2012-11-19 00:31:03 -08:00
case ' h ' :
builtin_print_help ( parser , argv [ 0 ] , stdout_buffer ) ;
return 0 ;
2006-05-26 21:38:11 +10:00
2012-11-19 00:31:03 -08:00
case ' ? ' :
builtin_unknown_option ( parser , argv [ 0 ] , argv [ woptind - 1 ] ) ;
return 1 ;
2006-05-26 21:38:11 +10:00
2012-11-18 16:30:30 -08:00
}
2012-11-18 11:23:22 +01:00
}
2006-05-26 21:38:11 +10:00
2012-11-18 11:23:22 +01:00
/*
2012-11-18 16:30:30 -08:00
Do not babble if not interactive
2012-11-18 11:23:22 +01:00
*/
2012-11-18 16:30:30 -08:00
if ( builtin_out_redirect )
2012-11-18 11:23:22 +01:00
{
2012-11-18 16:30:30 -08:00
found = 1 ;
2012-11-18 11:23:22 +01:00
}
2012-11-18 16:30:30 -08:00
if ( print_last )
2012-11-18 11:23:22 +01:00
{
2012-11-18 16:30:30 -08:00
/*
Ignore unconstructed jobs , i . e . ourself .
*/
job_iterator_t jobs ;
const job_t * j ;
while ( ( j = jobs . next ( ) ) )
{
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
if ( ( j - > flags & JOB_CONSTRUCTED ) & & ! job_is_completed ( j ) )
{
builtin_jobs_print ( j , mode , ! found ) ;
return 0 ;
}
}
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
}
else
{
if ( woptind < argc )
2012-11-18 11:23:22 +01:00
{
2012-11-18 16:30:30 -08:00
int i ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
found = 1 ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
for ( i = woptind ; i < argc ; i + + )
{
int pid ;
wchar_t * end ;
errno = 0 ;
pid = fish_wcstoi ( argv [ i ] , & end , 10 ) ;
if ( errno | | * end )
{
append_format ( stderr_buffer ,
_ ( L " %ls: '%ls' is not a job \n " ) ,
argv [ 0 ] ,
argv [ i ] ) ;
return 1 ;
}
j = job_get_from_pid ( pid ) ;
if ( j & & ! job_is_completed ( j ) )
{
builtin_jobs_print ( j , mode , ! found ) ;
}
else
{
append_format ( stderr_buffer ,
_ ( L " %ls: No suitable job: %d \n " ) ,
argv [ 0 ] ,
pid ) ;
return 1 ;
}
}
2012-11-18 11:23:22 +01:00
}
else
{
2012-01-29 16:36:21 -08:00
job_iterator_t jobs ;
2012-02-27 18:43:24 -08:00
const job_t * j ;
2012-01-29 16:36:21 -08:00
while ( ( j = jobs . next ( ) ) )
{
2012-11-18 16:30:30 -08:00
/*
Ignore unconstructed jobs , i . e . ourself .
*/
if ( ( j - > flags & JOB_CONSTRUCTED ) & & ! job_is_completed ( j ) )
{
builtin_jobs_print ( j , mode , ! found ) ;
found = 1 ;
}
}
2012-11-18 11:23:22 +01:00
}
}
2012-11-18 16:30:30 -08:00
if ( ! found )
{
append_format ( stdout_buffer ,
_ ( L " %ls: There are no jobs \n " ) ,
argv [ 0 ] ) ;
}
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
return 0 ;
2006-05-26 21:38:11 +10:00
}