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

@@ -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

@@ -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 )

@@ -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 */

@@ -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);
}

@@ -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 */

@@ -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

@@ -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

@@ -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

@@ -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;