diff --git a/Makefile b/Makefile index 858e3fce..93e49350 100644 --- a/Makefile +++ b/Makefile @@ -155,8 +155,10 @@ install: $(filter-out $(SKIP) $(addprefix $(DESTDIR),$(SKIP)),$(INSTALL)) ############ prog.c --> prog.o +top.o : top.h + %.o : %.c - $(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -c -o $@ $^ + $(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -c -o $@ $< w.o: w.c $(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) $(W_SHOWFROM) -c $< diff --git a/NEWS b/NEWS index e9ccf804..284fcfb3 100644 --- a/NEWS +++ b/NEWS @@ -1,9 +1,11 @@ procps-3.1.11 --> procps-3.1.12 +ps: explicit width ("ps -o pid,wchan:42,args") +ps: $PS_FORMAT works properly #201575 top: new Linux 2.6.0-test4 CPU stats shown top: multiple -p options work again top: fixed 4 GB wrap-around -ps: comes with tests +ps: has a set of tests to ensure correctness man page: /var/run/utmp, not /etc/utmp #206583 required flags moved out of CFLAGS #205429 RPM generation handles /lib64 diff --git a/ps/ps.1 b/ps/ps.1 index b22288a6..c99cd2d4 100644 --- a/ps/ps.1 +++ b/ps/ps.1 @@ -152,9 +152,13 @@ If all column headers are empty ("ps -o pid= -o comm=") then the header line will not be output. Column width will increase as needed for wide headers; this may be used to widen up columns such as WCHAN ("ps -o pid,wchan=WIDE-WCHAN-COLUMN -o comm"). +Explicit width control ("ps opid,wchan:42,cmd") is offered too. The behavior of "ps -o pid=X,comm=Y" varies with personality; output may be one column named "X,comm=Y" or two columns named "X" and "Y". Use multiple -o options when in doubt. +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 "-g" option can select by session leader OR by group name. Selection by session leader is specified by many standards, @@ -186,7 +190,7 @@ Heuristics are used to determine the behavior of this option. To ensure that the desired behavior is obtained, specify the other option (sorting or formatting) in some other way. -For sorting, BSD "O" option syntax is O[+|-]k1[,[+|-]k2[,...]] +For sorting, obsolete BSD "O" option syntax is O[+|-]k1[,[+|-]k2[,...]] Order the process listing according to the multilevel sort specified by the sequence of short keys from SORT KEYS, k1, k2, ... The `+' is quite optional, merely re-iterating the default direction on a key. `-' reverses diff --git a/ps/sortformat.c b/ps/sortformat.c index 06181c5f..8750590a 100644 --- a/ps/sortformat.c +++ b/ps/sortformat.c @@ -268,6 +268,7 @@ out: while(items--){ format_node *endp; char *equal_loc; + char *colon_loc; sep_loc = strpbrk(walk," ,\t\n"); /* if items left, then sep_loc is not in header override */ if(items && sep_loc) *sep_loc = '\0'; @@ -276,6 +277,15 @@ out: *equal_loc = '\0'; equal_loc++; } + colon_loc = strpbrk(walk,":"); + if(colon_loc){ /* if width override */ + *colon_loc = '\0'; + colon_loc++; + if(strspn(colon_loc,"0123456789") != strlen(colon_loc) || *colon_loc=='0'){ + free(buf); + goto badwidth; + } + } fnode = do_one_spec(walk,equal_loc); if(!fnode){ if(!*errbuf){ /* if didn't already create an error string */ @@ -289,6 +299,14 @@ out: free(buf); goto unknown; } + if(colon_loc){ + if(fnode->next){ + free(buf); + goto notmacro; + } + // FIXME: enforce signal width to 8, 9, or 16 (grep: SIGNAL wide_signals) + fnode->width = atoi(colon_loc); // already verified to be a number + } endp = fnode; while(endp->next) endp = endp->next; /* find end */ endp->next = sfn->f_cooked; sfn->f_cooked = fnode; @@ -302,6 +320,8 @@ out: if(0) unknown: err=errbuf; if(0) empty: err="Empty format list."; if(0) improper: err="Improper format list."; + if(0) badwidth: err="Column widths must be unsigned decimal numbers."; + if(0) notmacro: err="Can't set width for a macro (multi-column) format specifier."; if(strchr(sfn->sf,'%')) err = aix_format_parse(sfn); return err; } @@ -733,13 +753,14 @@ static const char *generate_sysv_list(void){ * The "broken" flag enables a really bad Unix98 misfeature. */ const char *process_sf_options(int localbroken){ - const char *err; 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; broken = localbroken; if(sf_list){ + const char *err; err = parse_O_option(sf_list); if(err) return err; } @@ -782,8 +803,6 @@ const char *process_sf_options(int localbroken){ if(format_flags) return "Conflicting format options."; option_source = 1; }else{ - format_node *fmt_walk; - format_node *fn; const char *spec; switch(format_flags){ @@ -822,14 +841,32 @@ const char *process_sf_options(int localbroken){ char *tmp; tmp = getenv("PS_FORMAT"); /* user override kills default */ if(tmp && *tmp){ - spec = tmp; - option_source = 2; + 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); } } if(spec){ - fn = do_one_spec(spec, NULL); /* use override "" for no headers */ - fmt_walk = fn; + 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 */ format_node *travler; travler = fmt_walk; @@ -838,6 +875,7 @@ const char *process_sf_options(int localbroken){ format_list = travler; } }else{ + const char *err; err = generate_sysv_list(); if(err) return err; option_source = 3; diff --git a/top.c b/top.c index 5428d204..5a6d1efb 100644 --- a/top.c +++ b/top.c @@ -1434,8 +1434,8 @@ static void rc_write_new (FILE *fp) { fprintf(fp, RCF_EYECATCHER "\"%s with windows\"\t\t# shameless braggin'\n" , Myname); fprintf(fp, RCF_DEPRECATED - "Mode_altscr=%d, Mode_irixps=%d, Delay_time=%.3f, Curwin=%d\n" - , Rc.mode_altscr, Rc.mode_irixps, Rc.delay_time, Curwin - Winstk); + "Mode_altscr=%d, Mode_irixps=%d, Delay_time=%.3f, Curwin=%u\n" + , Rc.mode_altscr, Rc.mode_irixps, Rc.delay_time, (unsigned)(Curwin - Winstk)); for (i = 0; i < GROUPSMAX; i++) { char buf[40]; char *cp = Winstk[i].rc.fieldscur; diff --git a/top.h b/top.h index ee1c320e..95014d36 100644 --- a/top.h +++ b/top.h @@ -368,7 +368,7 @@ typedef struct WIN_t { #define STATES_line2x5 "%s\03" \ " %#5.1f%% \02user,\03 %#5.1f%% \02system,\03 %#5.1f%% \02nice,\03 %#5.1f%% \02idle,\03 %#5.1f%% \02IO-wait\03\n" #define STATES_line2x6 "%s\03" \ - " %#4.1f%% \02us,\03 %#4.1f%% \02sy,\03 %#4.1f%% \02ni,\03 %#4.1f%% \02id,\03 %#4.1f%% \02wa,\03 %#4.1f%% \02hi,\03 %#4.1f%% \02si,\03\n" + " %#4.1f%% \02us,\03 %#4.1f%% \02sy,\03 %#4.1f%% \02ni,\03 %#4.1f%% \02id,\03 %#4.1f%% \02wa,\03 %#4.1f%% \02hi,\03 %#4.1f%% \02si\03\n" #ifdef CASEUP_SUMMK #define MEMORY_line1 "Mem: \03" \ " %8uK \02total,\03 %8uK \02used,\03 %8uK \02free,\03 %8uK \02buffers\03\n"