top on wyse60, whitespace doc, thread fixes

This commit is contained in:
albert 2003-10-07 03:12:50 +00:00
parent 620b861bd5
commit 3a16c12ce3
9 changed files with 181 additions and 101 deletions

1
NEWS
View File

@ -1,5 +1,6 @@
procps-3.1.13 --> procps-3.1.14
top: displays on more genuine serial terminals
handle 32-bit dev_t of Linux 2.6
ps: finally, m and -m satisfy the original design
ps: distinct per-thread and whole-process pending signals

View File

@ -220,6 +220,8 @@ extern void freeproc(proc_t* p);
#define PROC_FILLWCHAN 0x0080 // look up WCHAN name
#define PROC_FILLARG 0x0100 // alloc and fill in `cmdline'
#define PROC_LOOSE_TASKS 0x0200 // threat threads as if they were processes
// Obsolete, consider only processes with one of the passed:
#define PROC_PID 0x1000 // process id numbers ( 0 terminated)
#define PROC_UID 0x4000 // user id numbers ( length needed )

View File

@ -101,6 +101,11 @@
#define TF_U_L 0x0010
#define TF_show_proc 0x0100 // show the summary line
#define TF_show_task 0x0200 // show the per-thread lines
#define TF_show_both 0x0400 // distinct proc/task format lists
#define TF_loose_tasks 0x0800 // let sorting break up task groups (BSDish)
#define TF_no_sort 0x1000 // don't know if thread-grouping should survive a sort
#define TF_no_forest 0x2000 // don't see how to do threads w/ forest option
#define TF_must_use 0x4000 // options only make sense if LWP/SPID column added
/* personality control flags */
#define PER_BROKEN_o 0x0001
@ -140,10 +145,10 @@
#define FM_c 0x0001 /* -c */
#define FM_j 0x0002 /* -j */ /* only set when !sysv_j_format */
#define FM_y 0x0004 /* -y */
#define FM_L 0x0008 /* -L */
//#define FM_L 0x0008 /* -L */
#define FM_P 0x0010 /* -P */
#define FM_M 0x0020 /* -M */
#define FM_T 0x0040 /* -T */
//#define FM_T 0x0040 /* -T */
#define FM_F 0x0080 /* -F */ /* -F also sets the regular -f flags */
/* sorting & formatting */

View File

@ -212,6 +212,7 @@ static unsigned collect_format_needs(format_node *walk){
static format_node *proc_format_list;
static format_node *task_format_list;
static unsigned needs_for_threads;
static unsigned needs_for_sort;
static unsigned proc_format_needs;
static unsigned task_format_needs;
@ -225,7 +226,7 @@ static void lists_and_needs(void){
check_headers();
// only care about the difference when showing both
if( (thread_flags & (TF_show_proc|TF_show_task)) == (TF_show_proc|TF_show_task) ){
if(thread_flags & TF_show_both){
format_node pfn, tfn; // junk, to handle special case at begin of list
format_node *walk = format_list;
format_node *p_end = &pfn;
@ -293,6 +294,8 @@ static void lists_and_needs(void){
/* FIXME broken filthy hack -- got to unify some stuff here */
if( ( (proc_format_needs|task_format_needs|needs_for_sort) & PROC_FILLWCHAN) && !wchan_is_number)
if (open_psdb(namelist_file)) wchan_is_number = 1;
if(thread_flags&TF_loose_tasks) needs_for_threads |= PROC_LOOSE_TASKS;
}
//////////////////////////////////////////////////////////////////////////
@ -317,12 +320,11 @@ static void fill_pcpu(proc_t *buf){
static void simple_spew(void){
proc_t buf;
PROCTAB* ptp;
ptp = openproc(needs_for_format | needs_for_sort | needs_for_select);
ptp = openproc(needs_for_format | needs_for_sort | needs_for_select | needs_for_threads);
if(!ptp) {
fprintf(stderr, "Error: can not access /proc.\n");
exit(1);
}
if(!thread_flags) thread_flags=TF_show_proc;
memset(&buf, '#', sizeof(proc_t));
while(readproc(ptp,&buf)){
if(want_this_proc(&buf)){
@ -385,10 +387,16 @@ static int compare_two_procs(const void *a, const void *b){
}
/***** show pre-sorted array of process pointers */
static void show_proc_array(int n){
static void show_proc_array(PROCTAB *restrict ptp, int n){
proc_t **p = processes;
while(n--){
show_one_proc(*p,format_list);
if(thread_flags & TF_show_proc) show_one_proc(*p, proc_format_list);
if(thread_flags & TF_show_task){
proc_t buf2;
// must still have the process allocated
while(readtask(ptp,*p,&buf2)) show_one_proc(&buf2, task_format_list);
// must not attempt to free cmdline and environ
}
/* no point freeing any of this -- won't need more mem */
// if((*p)->cmdline) free((void*)*(*p)->cmdline);
// if((*p)->environ) free((void*)*(*p)->environ);
@ -469,7 +477,7 @@ static void fancy_spew(void){
fprintf(stderr, "can't have threads with sorting or forest output\n");
exit(49);
}
ptp = openproc(needs_for_format | needs_for_sort | needs_for_select);
ptp = openproc(needs_for_format | needs_for_sort | needs_for_select | needs_for_threads);
if(!ptp) {
fprintf(stderr, "Error: can not access /proc.\n");
exit(1);
@ -487,7 +495,7 @@ static void fancy_spew(void){
if(forest_type) prep_forest_sort();
qsort(processes, n, sizeof(proc_t*), compare_two_procs);
if(forest_type) show_forest(n);
else show_proc_array(n);
else show_proc_array(ptp,n);
}

View File

@ -1323,11 +1323,11 @@ static const format_struct format_array[] = {
{"timeout", "TMOUT", pr_timeout, sr_timeout, 5, 0, LNX, AN|RIGHT},
{"tmout", "TMOUT", pr_timeout, sr_timeout, 5, 0, LNX, AN|RIGHT},
{"tname", "TTY", pr_tty8, sr_tty, 8, 0, DEC, PO|LEFT},
{"tpgid", "TPGID", pr_tpgid, sr_tpgid, 5, 0, XXX, AN|PIDMAX|RIGHT},
{"tpgid", "TPGID", pr_tpgid, sr_tpgid, 5, 0, XXX, PO|PIDMAX|RIGHT},
{"trs", "TRS", pr_trs, sr_trs, 4, MEM, AIX, PO|RIGHT},
{"trss", "TRSS", pr_trs, sr_trs, 4, MEM, BSD, PO|RIGHT}, /* 4.3BSD NET/2 */
{"tsess", "TSESS", pr_nop, sr_nop, 5, 0, BSD, AN|PIDMAX|RIGHT},
{"tsession", "TSESS", pr_nop, sr_nop, 5, 0, DEC, AN|PIDMAX|RIGHT},
{"tsess", "TSESS", pr_nop, sr_nop, 5, 0, BSD, PO|PIDMAX|RIGHT},
{"tsession", "TSESS", pr_nop, sr_nop, 5, 0, DEC, PO|PIDMAX|RIGHT},
{"tsiz", "TSIZ", pr_tsiz, sr_nop, 4, 0, BSD, PO|RIGHT},
{"tt", "TT", pr_tty8, sr_tty, 8, 0, BSD, PO|LEFT},
{"tty", "TT", pr_tty8, sr_tty, 8, 0, U98, PO|LEFT}, /* Unix98 requires "TT" but has "TTY" too. :-( */ /* was 3 wide */

View File

@ -265,8 +265,7 @@ static const char *parse_sysv_option(void){
*/
trace("-L Print LWP (thread) info.\n");
thread_flags |= TF_U_L;
thread_flags |= TF_show_task;
format_modifiers |= FM_L;
// format_modifiers |= FM_L;
break;
case 'M': /* someday, maybe, we will have MAC like SGI's Irix */
trace("-M Print security label for Mandatory Access Control.\n");
@ -301,8 +300,7 @@ static const char *parse_sysv_option(void){
*/
trace("-T adds strange SPID column (old sproc() threads?)\n");
thread_flags |= TF_U_T;
thread_flags |= TF_show_task;
format_modifiers |= FM_T;
// format_modifiers |= FM_T;
break;
case 'U': /* end */
trace("-U select by RUID (supports names).\n");
@ -362,7 +360,7 @@ static const char *parse_sysv_option(void){
return "List of session leaders OR effective group IDs was invalid.";
case 'j':
trace("-j jobs format.\n");
/* Debian uses RD_j and Digital uses JFMT */
/* old Debian used RD_j and Digital uses JFMT */
if(sysv_j_format) format_flags |= FF_Uj;
else format_modifiers |= FM_j;
break;
@ -374,8 +372,6 @@ static const char *parse_sysv_option(void){
trace("-m shows threads.\n");
/* note that AIX shows 2 lines for a normal process */
thread_flags |= TF_U_m;
thread_flags |= TF_show_proc;
thread_flags |= TF_show_task;
break;
case 'n': /* end */
trace("-n sets namelist file.\n");
@ -507,7 +503,6 @@ static const char *parse_bsd_option(void){
case 'H': // The FreeBSD way (NetBSD:s OpenBSD:k FreeBSD:H -- NIH???)
trace("H Print LWP (thread) info.\n"); // was: Use /vmcore as c-dumpfile\n");
thread_flags |= TF_B_H;
thread_flags |= TF_show_task; // FIXME: determine if TF_show_proc is needed
//format_modifiers |= FM_L; // FIXME: determine if we need something like this
break;
case 'L': /* single */
@ -606,8 +601,6 @@ static const char *parse_bsd_option(void){
#if 0
case 'k': // OpenBSD: don't hide "kernel threads" -- like the swapper?
trace("k Print LWP (thread) info.\n"); // was: Use /vmcore as c-dumpfile\n");
thread_flags |= TF_show_task; // FIXME: determine if TF_show_proc is needed
//format_modifiers |= FM_L; // FIXME: determine if we need something like this
break;
#endif
case 'l':
@ -625,8 +618,6 @@ static const char *parse_bsd_option(void){
break;
}
thread_flags |= TF_B_m;
thread_flags |= TF_show_proc;
thread_flags |= TF_show_task;
break;
case 'n':
trace("n Numeric output for WCHAN, and USER replaced by UID\n");
@ -1101,7 +1092,15 @@ static void choose_dimensions(void){
}
static const char *thread_option_check(void){
if(!thread_flags) return NULL;
if(!thread_flags){
thread_flags = TF_show_proc;
return NULL;
}
if(forest_type){
return "Thread display conflicts with forest display.";
}
//thread_flags |= TF_no_forest;
if((thread_flags&TF_B_H) && (thread_flags&(TF_B_m|TF_U_m)))
return "Thread flags conflict; can't use H with m or -m.";
@ -1110,6 +1109,22 @@ static const char *thread_option_check(void){
if((thread_flags&TF_U_L) && (thread_flags&TF_U_T))
return "Thread flags conflict; can't use both -L and -T.";
if(thread_flags&TF_B_H) thread_flags |= (TF_show_proc|TF_loose_tasks);
if(thread_flags&(TF_B_m|TF_U_m)) thread_flags |= (TF_show_proc|TF_show_task|TF_show_both);
if(thread_flags&(TF_U_T|TF_U_L)){
if(thread_flags&(TF_B_m|TF_U_m|TF_B_H)){
// Got a thread style, so format modification is a requirement?
// Maybe -T/-L has H thread style though. (sorting interaction?)
//return "Huh? Tell procps-feedback@lists.sf.net what you expected.";
thread_flags |= TF_must_use;
}else{
// using -L/-T thread style, so format from elsewhere is OK
thread_flags |= TF_show_task; // or like the H option?
//thread_flags |= TF_no_sort;
}
}
return NULL;
}
@ -1124,10 +1139,10 @@ int arg_parse(int argc, char *argv[]){
err = parse_all_options();
if(err) goto try_bsd;
err = process_sf_options(!not_pure_unix);
if(err) goto try_bsd;
err = thread_option_check();
if(err) goto try_bsd;
err = process_sf_options(!not_pure_unix);
if(err) goto try_bsd;
err = select_bits_setup();
if(err) goto try_bsd;
@ -1154,10 +1169,10 @@ try_bsd:
err2 = parse_all_options();
if(err2) goto total_failure;
err2 = process_sf_options(!not_pure_unix);
if(err2) goto total_failure;
err2 = thread_option_check();
if(err2) goto total_failure;
err2 = process_sf_options(!not_pure_unix);
if(err2) goto total_failure;
err2 = select_bits_setup();
if(err2) goto total_failure;

13
ps/ps.1
View File

@ -102,7 +102,6 @@ v display virtual memory format
OUTPUT MODIFIERS
-H show process hierarchy (forest)
-m show threads
-n set namelist file
-w wide output
C use raw CPU time for %CPU instead of decaying average
@ -113,7 +112,6 @@ c true command name
e show environment after the command
f ASCII-art process hierarchy (forest)
h no header (or, one header per screen in the BSD personality)
m all threads
n numeric output for WCHAN and USER
w wide output
--cols set screen width
@ -127,6 +125,13 @@ w wide output
--sort specify sorting order
--width set screen width
THREAD DISPLAY
-L show threads, possibly with LWP and NLWP columns
-T show threads, possibly with SPID column
-m show threads after processes
H show threads as if they were processes
m show threads after processes
INFORMATION
-V print version
L list all format specifiers
@ -160,6 +165,10 @@ Use the $PS_FORMAT environment variable to specify a default
as desired; DefSysV and DefBSD are macros that may be used to
choose the default UNIX or BSD columns.
The following user-defined format specifiers may contain
spaces: comm, args, cmd, comm, command, fname, ucmd, ucomm,
lstart, bsdstart, start
The "-g" option can select by session leader OR by group name.
Selection by session leader is specified by many standards,
but selection by group is the logical behavior that several other

View File

@ -276,7 +276,7 @@ out:
if(colon_loc){ /* if width override */
*colon_loc = '\0';
colon_loc++;
if(strspn(colon_loc,"0123456789") != strlen(colon_loc) || *colon_loc=='0'){
if(strspn(colon_loc,"0123456789") != strlen(colon_loc) || *colon_loc=='0' || !*colon_loc){
free(buf);
goto badwidth;
}
@ -351,7 +351,6 @@ static const char *long_sort_parse(sf_node *sfn){
char *buf; /* temp copy of arg to hack on */
char *sep_loc; /* separator location: " \t,\n" */
char *walk;
const char *err; /* error code that could or did happen */
sort_node *snode;
int items;
int need_item;
@ -364,7 +363,6 @@ static const char *long_sort_parse(sf_node *sfn){
need_item = 1; /* true */
items = 0;
walk = buf;
err = "Improper sort specifier list.";
do{
switch(*walk){
case ' ': case ',': case '\t': case '\n': case '\0':
@ -713,16 +711,16 @@ static const char *generate_sysv_list(void){
}else if(format_flags & FF_Ul){
PUSH("ni"); PUSH("opri");
}
if((format_modifiers & FM_L) && (format_flags & FF_Uf)) PUSH("nlwp");
if((thread_flags & TF_U_L) && (format_flags & FF_Uf)) PUSH("nlwp");
if( (format_flags & (FF_Uf|FF_Ul)) && !(format_modifiers & FM_c) ) PUSH("c");
if(format_modifiers & FM_P) PUSH("psr");
if(format_modifiers & FM_L) PUSH("lwp");
if(thread_flags & TF_U_L) PUSH("lwp");
if(format_modifiers & FM_j){
PUSH("sid");
PUSH("pgid");
}
if(format_flags & (FF_Uf|FF_Ul)) PUSH("ppid");
if(format_modifiers & FM_T) PUSH("spid");
if(thread_flags & TF_U_T) PUSH("spid");
PUSH("pid");
if(format_flags & FF_Uf){
if(personality & PER_SANE_USER) PUSH("user");
@ -737,7 +735,6 @@ static const char *generate_sysv_list(void){
if(format_modifiers & FM_M){
PUSH("label"); /* Mandatory Access Control */
}
format_modifiers = 0;
return NULL;
}
@ -749,7 +746,6 @@ static const char *generate_sysv_list(void){
*/
const char *process_sf_options(int localbroken){
sf_node *sf_walk;
int option_source; /* true if user-defined */
if(personality & PER_BROKEN_o) localbroken = 1;
if(personality & PER_GOOD_o) localbroken = 0;
@ -794,10 +790,49 @@ const char *process_sf_options(int localbroken){
sf_walk = sf_walk->next;
}
// Get somebody to explain how -L/-T is supposed to interact
// with sorting. Do the threads remain grouped, with sorting
// by process, or do the threads get sorted by themselves?
if(sort_list && (thread_flags&TF_no_sort)){
return "Tell procps-feedback@lists.sf.net what you expected.";
}
// If nothing else, try to use $PS_FORMAT before the default.
if(!format_flags && !format_modifiers && !format_list){
char *tmp;
if(thread_flags&TF_must_use) return "Tell procps-feedback@sf.net what you want. (-L/-T, -m/m/H, and $PS_FORMAT)";
tmp = getenv("PS_FORMAT"); /* user override kills default */
if(tmp && *tmp){
const char *err;
sf_node sfn;
sfn.sf = tmp;
sfn.f_cooked = NULL;
err = format_parse(&sfn);
if(!err){
format_node *fmt_walk;
fmt_walk = sfn.f_cooked;
while(fmt_walk){ /* put any nodes onto format_list in opposite way */
format_node *travler;
travler = fmt_walk;
fmt_walk = fmt_walk->next;
travler->next = format_list;
format_list = travler;
}
return NULL;
}
// FIXME: prove that this won't be hit on valid bogus-BSD options
fprintf(stderr, "Warning: $PS_FORMAT ignored. (%s)\n", err);
}
}
if(format_list){
if(format_flags) return "Conflicting format options.";
option_source = 1;
}else{
if(format_modifiers) return "Can't use output modifiers with user-defined output";
if(thread_flags&TF_must_use) return "-L/-T with H/m/-m and -o/-O/o/O is nonsense";
return NULL;
}
do{
const char *spec;
switch(format_flags){
@ -831,35 +866,10 @@ const char *process_sf_options(int localbroken){
} /* end switch(format_flags) */
option_source = 0;
if(!format_flags && !format_modifiers){ /* was default */
char *tmp;
tmp = getenv("PS_FORMAT"); /* user override kills default */
if(tmp && *tmp){
const char *err;
sf_node sfn;
// spec = tmp;
// option_source = 2;
sfn.sf = tmp;
sfn.f_cooked = NULL;
err = format_parse(&sfn);
if(!err){
format_node *fmt_walk;
fmt_walk = sfn.f_cooked;
while(fmt_walk){ /* put any nodes onto format_list in opposite way */
format_node *travler;
travler = fmt_walk;
fmt_walk = fmt_walk->next;
travler->next = format_list;
format_list = travler;
}
return NULL;
}
fprintf(stderr, "Warning: $PS_FORMAT ignored. (%s)\n", err);
}
}
// not just for case 0, since sysv_l_format and such may be NULL
if(!spec) return generate_sysv_list();
if(spec){
do{
format_node *fmt_walk;
fmt_walk = do_one_spec(spec, NULL); /* use override "" for no headers */
while(fmt_walk){ /* put any nodes onto format_list in opposite way */
@ -869,16 +879,11 @@ const char *process_sf_options(int localbroken){
travler->next = format_list;
format_list = travler;
}
}else{
const char *err;
err = generate_sysv_list();
if(err) return err;
option_source = 3;
}
}
if(format_modifiers){ /* generate_sysv_list() may have cleared some bits */
}while(0);
}while(0);
do{
format_node *fn;
if(option_source) return "Can't use output modifiers with user-defined output";
if(format_modifiers & FM_j){
fn = do_one_spec("pgid", NULL);
if(!fmt_add_after("PPID", fn)) if(!fmt_add_after("PID", fn))
@ -902,9 +907,25 @@ const char *process_sf_options(int localbroken){
fn = do_one_spec("pri", NULL);
if(!fmt_add_after("CLS", fn)) return "Lost my CLS!";
}
if(thread_flags & TF_U_T){
fn = do_one_spec("spid", NULL);
if(!fmt_add_after("PID", fn) && (thread_flags&TF_must_use))
return "-T with H/-m/m but no PID for SPID to follow";
}
if(thread_flags & TF_U_L){
fn = do_one_spec("lwp", NULL);
if(fmt_add_after("SID", fn)) goto did_lwp;
if(fmt_add_after("SESS", fn)) goto did_lwp;
if(fmt_add_after("PGID", fn)) goto did_lwp;
if(fmt_add_after("PGRP", fn)) goto did_lwp;
if(fmt_add_after("PPID", fn)) goto did_lwp;
if(fmt_add_after("PID", fn)) goto did_lwp;
if(thread_flags&TF_must_use)
return "-L with H/-m/m but no PID/PGID/SID/SESS for NLWP to follow";
did_lwp:
fn = do_one_spec("nlwp", NULL);
fmt_add_after("%CPU", fn);
}
if(!option_source){ /* OK to really muck with stuff */
format_node *fn;
/* Do personality-specific translations not covered by format_flags.
* Generally, these only get hit when personality overrides unix output.
* That (mostly?) means the Digital and Debian personalities.
@ -917,9 +938,8 @@ const char *process_sf_options(int localbroken){
fn = do_one_spec("user", NULL);
if(fmt_add_after("UID", fn)) fmt_delete("UID");
}
}
}while(0);
/* Could scan for duplicates (format and sort) here. Digital does. */
return NULL;
}

26
top.c
View File

@ -2302,16 +2302,36 @@ static void wins_reflag (int what, int flg)
static void wins_resize (int dont_care_sig)
{
struct winsize wz;
char *env_columns; // Unix98 environment variable COLUMNS
char *env_lines; // Unix98 environment variable LINES
(void)dont_care_sig;
Screen_cols = columns;
Screen_rows = lines;
if (-1 != (ioctl(STDOUT_FILENO, TIOCGWINSZ, &wz))) {
Screen_cols = columns; // <term.h>
Screen_rows = lines; // <term.h>
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &wz) != -1 && wz.ws_col>0 && wz.ws_row>0) {
Screen_cols = wz.ws_col;
Screen_rows = wz.ws_row;
}
if (Batch) Screen_rows = MAXINT;
env_columns = getenv("COLUMNS");
if(env_columns && *env_columns){
long t;
char *endptr;
t = strtol(env_columns, &endptr, 0);
if(!*endptr && (t>0) && (t<=0x7fffffffL)) Screen_cols = (int)t;
}
env_lines = getenv("LINES");
if(env_lines && *env_lines){
long t;
char *endptr;
t = strtol(env_lines, &endptr, 0);
if(!*endptr && (t>0) && (t<=0x7fffffffL)) Screen_rows = (int)t;
}
// we might disappoint some folks (but they'll deserve it)
if (SCREENMAX < Screen_cols) Screen_cols = SCREENMAX;