diff --git a/Makefile b/Makefile index d2b9f065..1e180dbd 100644 --- a/Makefile +++ b/Makefile @@ -77,20 +77,23 @@ CPPFLAGS := -I/usr/include/ncurses ALL_CPPFLAGS := $(PKG_CPPFLAGS) $(CPPFLAGS) # Left out -Wconversion due to noise in glibc headers. -# Left out a number of things that older compilers lack: -# -Wpadded -Wunreachable-code -Wdisabled-optimization +# Left out -Wunreachable-code and -Wdisabled-optimization +# because gcc spews many useless warnings with them. # # Since none of the PKG_CFLAGS things are truly required # to compile procps, they might best be moved to CFLAGS. # On the other hand, they aren't normal -O -g things either. # -# TODO: determine why -fomit-frame-pointer is missing +# Note that -O2 includes -fomit-frame-pointer only if the arch +# doesn't lose some debugging ability. # PKG_CFLAGS := -fno-common -ffast-math \ -W -Wall -Wshadow -Wcast-align -Wredundant-decls \ -Wbad-function-cast -Wcast-qual -Wwrite-strings -Waggregate-return \ -Wstrict-prototypes -Wmissing-prototypes -CFLAGS := -O2 -g3 +# Note that some stuff below is conditional on CFLAGS containing +# an option that starts with "-g". (-g, -g2, -g3, -ggdb, etc.) +CFLAGS := -O2 -s ALL_CFLAGS := $(PKG_CFLAGS) $(CFLAGS) PKG_LDFLAGS := -Wl,-warn-common @@ -116,10 +119,15 @@ ALL_CFLAGS += $(call check_gcc,-Wstrict-aliasing=2,) # use computed goto. #ALL_CFLAGS += $(call check_gcc,-fno-gcse,) -# These are part of -O3 but we dislike -finline-functions. -# Using -fno-inline-functions with -O3 would work too. +# if not debugging, enable things that could confuse gdb +ifeq (,$(findstring -g,$(filter -g%,$(CFLAGS)))) ALL_CFLAGS += $(call check_gcc,-fweb,) ALL_CFLAGS += $(call check_gcc,-frename-registers,) +ALL_CFLAGS += $(call check_gcc,-fomit-frame-pointer,) +endif + +# in case -O3 is enabled, avoid bloat +ALL_CFLAGS += $(call check_gcc,-fno-inline-functions,) # Be 64-bit if at all possible. In a cross-compiling situation, one may # do "make m64=-m32 lib64=lib" to produce 32-bit executables. DO NOT @@ -197,7 +205,7 @@ clean: ###### install $(BINFILES) : all - $(install) --mode a=rx --strip $(notdir $@) $@ + $(install) --mode a=rx $(notdir $@) $@ $(MANFILES) : all $(install) --mode a=r $(notdir $@) $@ diff --git a/NEWS b/NEWS index d0bacbdd..d3dc30df 100644 --- a/NEWS +++ b/NEWS @@ -1,11 +1,14 @@ procps-3.2.1 --> procps-3.2.2 +move striping from install command to CFLAGS now using gcc -fweb and -frename-registers options avoid warning about -lncurses when not linking -- thanks FLWM +watch: allow sub-second intervals -- thanks Thomas Stewart ps: personality-specific -x support (HP-UX and SVR4-MP) ps: k option, same as --sort vmstat: fixed -d top: try to handle terminals lacking rmam and smam #235003 +top: xterm dislikes clear-to-eol at eol (char lost) top: tolerate sparse CPU numbering procps-3.2.0 --> procps-3.2.1 diff --git a/proc/escape.c b/proc/escape.c index 060e0a31..83aee9db 100644 --- a/proc/escape.c +++ b/proc/escape.c @@ -131,7 +131,7 @@ int escape_strlist(char *restrict dst, const char *restrict const *restrict src, /////////////////////////////////////////////////// int escape_command(char *restrict const outbuf, const proc_t *restrict const pp, int bytes, int glyphs, unsigned flags){ - int overhead = 1; // the trailing NUL + int overhead = 0; int end = 0; if(bytes > glyphs+1) bytes=glyphs+1; // FIXME: assumes 8-bit locale @@ -147,7 +147,7 @@ int escape_command(char *restrict const outbuf, const proc_t *restrict const pp, if(pp->state=='Z') overhead += 10; // chars in " " else flags &= ~ESC_DEFUNCT; } - if(overhead >= bytes){ // if no room for even one byte of the command name + if(overhead + 1 >= bytes){ // if no room for even one byte of the command name // you'd damn well better have _some_ space outbuf[0] = '-'; outbuf[1] = '\0'; @@ -156,7 +156,7 @@ int escape_command(char *restrict const outbuf, const proc_t *restrict const pp, if(flags & ESC_BRACKETS){ outbuf[end++] = '['; } - end += escape_str(outbuf+end, pp->cmd, bytes-overhead, glyphs-overhead+1); + end += escape_str(outbuf+end, pp->cmd, bytes-overhead, glyphs-overhead); // Hmmm, do we want "[foo] " or "[foo ]"? if(flags & ESC_BRACKETS){ diff --git a/proc/module.mk b/proc/module.mk index 4155ced5..3afe56f5 100644 --- a/proc/module.mk +++ b/proc/module.mk @@ -64,12 +64,12 @@ endif $(lib)/$(SONAME) : proc/$(SONAME) - $(install) --mode a=rx --strip $< $@ + $(install) --mode a=rx $< $@ cd $(lib) && $(ln_sf) $(SONAME) lib$(NAME).so $(ldconfig) #$(usr/lib)/lib$(NAME).a : proc/lib$(NAME).a -# $(install) --mode a=r --strip $< $@ +# $(install) --mode a=r $< $@ # Junk anyway... supposed to go in /usr/include/$(NAME) #$(HDRFILES) ??? : $(addprefix proc/,$(HDRFILES)) ??? diff --git a/ps/module.mk b/ps/module.mk index c4a986d6..258fef67 100755 --- a/ps/module.mk +++ b/ps/module.mk @@ -33,7 +33,7 @@ ps/stacktrace.o: ps/stacktrace.c $(bin)ps: ps/ps - $(install) --mode a=rx --strip $< $@ + $(install) --mode a=rx $< $@ $(man1)ps.1 : ps/ps.1 $(install) --mode a=r $< $@ diff --git a/top.c b/top.c index b743a8d0..e3a34c92 100644 --- a/top.c +++ b/top.c @@ -674,11 +674,10 @@ static void show_special (int interact, const char *glob) if (*glob) PUTT("%.*s", Screen_cols, glob); } - + /*###### Small Utility routines ########################################*/ - /* - * Get a string from the user */ +// Get a string from the user static char *ask4str (const char *prompt) { static char buf[GETBUFSIZ]; @@ -691,8 +690,7 @@ static char *ask4str (const char *prompt) } - /* - * Get a float from the user */ +// Get a float from the user static float get_float (const char *prompt) { char *line; @@ -709,8 +707,7 @@ static float get_float (const char *prompt) } - /* - * Get an integer from the user */ +// Get an integer from the user static int get_int (const char *prompt) { char *line; @@ -1151,51 +1148,47 @@ static FLD_t Fieldstab[] = { L_EITHER - must L_status, else 64-bit math, __udivdi3 on 32-bit ! keys head fmts width scale sort desc lflg ------ ----------- ------- ------ ----- ----- ---------------------- -------- */ - { "AaAa", " PID ", "%5u ", -1, -1, SF(PID), "Process Id", L_NONE }, - { "BbBb", " PPID ", "%5u ", -1, -1, SF(PPD), "Parent Process Pid", L_EITHER }, - { "CcQq", "RUSER ", "%-8.8s ", -1, -1, SF(URR), "Real user name", L_RUSER }, - { "DdCc", " UID ", "%4u ", -1, -1, SF(UID), "User Id", L_NONE }, - { "EeDd", "USER ", "%-8.8s ", -1, -1, SF(URE), "User Name", L_EUSER }, - { "FfNn", "GROUP ", "%-8.8s ", -1, -1, SF(GRP), "Group Name", L_GROUP }, - { "GgGg", "TTY ", "%-8.8s ", 8, -1, SF(TTY), "Controlling Tty", L_stat }, - { "HhHh", " PR ", "%3d ", -1, -1, SF(PRI), "Priority", L_stat }, - { "IiIi", " NI ", "%3d ", -1, -1, SF(NCE), "Nice value", L_stat }, - { "JjYy", "#C ", "%2u ", -1, -1, SF(CPN), "Last used cpu (SMP)", L_stat }, - { "KkEe", "%CPU ", "%#4.1f ", -1, -1, SF(CPU), "CPU usage", L_stat }, - { "LlWw", " TIME ", "%6.6s ", 6, -1, SF(TME), "CPU Time", L_stat }, - { "MmRr", " TIME+ ", "%9.9s ", 9, -1, SF(TME), "CPU Time, hundredths", L_stat }, - { "NnFf", "%MEM ", "%#4.1f ", -1, -1, SF(RES), "Memory usage (RES)", L_statm }, - { "OoMm", " VIRT ", "%5.5s ", 5, SK_Kb, SF(VRT), "Virtual Image (kb)", L_statm }, - { "PpOo", "SWAP ", "%4.4s ", 4, SK_Kb, SF(SWP), "Swapped size (kb)", L_statm }, - { "QqTt", " RES ", "%4.4s ", 4, SK_Kb, SF(RES), "Resident size (kb)", L_statm }, - { "RrKk", "CODE ", "%4.4s ", 4, SK_Kb, SF(COD), "Code size (kb)", L_statm }, - { "SsLl", "DATA ", "%4.4s ", 4, SK_Kb, SF(DAT), "Data+Stack size (kb)", L_statm }, - { "TtPp", " SHR ", "%4.4s ", 4, SK_Kb, SF(SHR), "Shared Mem size (kb)", L_statm }, - { "UuJj", "nFLT ", "%4.4s ", 4, SK_no, SF(FLT), "Page Fault count", L_stat }, - { "VvSs", "nDRT ", "%4.4s ", 4, SK_no, SF(DRT), "Dirty Pages count", L_statm }, + { "AaAa", " PID", " %5u", -1, -1, SF(PID), "Process Id", L_NONE }, + { "BbBb", " PPID", " %5u", -1, -1, SF(PPD), "Parent Process Pid", L_EITHER }, + { "CcQq", " RUSER ", " %-8.8s", -1, -1, SF(URR), "Real user name", L_RUSER }, + { "DdCc", " UID", " %4u", -1, -1, SF(UID), "User Id", L_NONE }, + { "EeDd", " USER ", " %-8.8s", -1, -1, SF(URE), "User Name", L_EUSER }, + { "FfNn", " GROUP ", " %-8.8s", -1, -1, SF(GRP), "Group Name", L_GROUP }, + { "GgGg", " TTY ", " %-8.8s", 8, -1, SF(TTY), "Controlling Tty", L_stat }, + { "HhHh", " PR", " %3d", -1, -1, SF(PRI), "Priority", L_stat }, + { "IiIi", " NI", " %3d", -1, -1, SF(NCE), "Nice value", L_stat }, + { "JjYy", " #C", " %2u", -1, -1, SF(CPN), "Last used cpu (SMP)", L_stat }, + { "KkEe", " %CPU", " %#4.1f", -1, -1, SF(CPU), "CPU usage", L_stat }, + { "LlWw", " TIME", " %6.6s", 6, -1, SF(TME), "CPU Time", L_stat }, + { "MmRr", " TIME+ ", " %9.9s", 9, -1, SF(TME), "CPU Time, hundredths", L_stat }, + { "NnFf", " %MEM", " %#4.1f", -1, -1, SF(RES), "Memory usage (RES)", L_statm }, + { "OoMm", " VIRT", " %5.5s", 5, SK_Kb, SF(VRT), "Virtual Image (kb)", L_statm }, + { "PpOo", " SWAP", " %4.4s", 4, SK_Kb, SF(SWP), "Swapped size (kb)", L_statm }, + { "QqTt", " RES", " %4.4s", 4, SK_Kb, SF(RES), "Resident size (kb)", L_statm }, + { "RrKk", " CODE", " %4.4s", 4, SK_Kb, SF(COD), "Code size (kb)", L_statm }, + { "SsLl", " DATA", " %4.4s", 4, SK_Kb, SF(DAT), "Data+Stack size (kb)", L_statm }, + { "TtPp", " SHR", " %4.4s", 4, SK_Kb, SF(SHR), "Shared Mem size (kb)", L_statm }, + { "UuJj", " nFLT", " %4.4s", 4, SK_no, SF(FLT), "Page Fault count", L_stat }, + { "VvSs", " nDRT", " %4.4s", 4, SK_no, SF(DRT), "Dirty Pages count", L_statm }, #ifdef USE_LIB_STA3 - { "WwVv", "STA ", "%3.3s ", -1, -1, SF(STA), "Process Status", L_stat }, + { "WwVv", " STA", " %3.3s", -1, -1, SF(STA), "Process Status", L_stat }, #else - { "WwVv", "S ", "%c ", -1, -1, SF(STA), "Process Status", L_EITHER }, + { "WwVv", " S", " %c", -1, -1, SF(STA), "Process Status", L_EITHER }, #endif // next entry's special: '.head' will be formatted using table entry's own // '.fmts' plus runtime supplied conversion args! - { "XxXx", "COMMAND ", "%-*.*s ", -1, -1, SF(CMD), "Command name/line", L_EITHER }, - { "YyUu", "WCHAN ", "%-9.9s ", -1, -1, SF(WCH), "Sleeping in Function", L_stat }, + { "XxXx", " COMMAND", " %-*.*s", -1, -1, SF(CMD), "Command name/line", L_EITHER }, + { "YyUu", " WCHAN ", " %-9.9s", -1, -1, SF(WCH), "Sleeping in Function", L_stat }, // next entry's special: the 0's will be replaced with '.'! -#ifdef CASEUP_HEXES - { "ZzZz", "Flags ", "%08lX ", -1, -1, SF(FLG), "Task Flags ", L_stat }, -#else - { "ZzZz", "Flags ", "%08lx ", -1, -1, SF(FLG), "Task Flags ", L_stat }, -#endif + { "ZzZz", " Flags ", " %08lx", -1, -1, SF(FLG), "Task Flags ", L_stat }, #if 0 - { "..Qq", " A ", "%4.4s ", 4, SK_no, SF(PID), "Accessed Page count", L_stat }, - { "..Nn", " TRS ", "%4.4s ", 4, SK_Kb, SF(PID), "Code in memory (kb)", L_stat }, - { "..Rr", " WP ", "%4.4s ", 4, SK_no, SF(PID), "Unwritable Pages", L_stat }, - { "Jj[{", "#C ", "%2u ", -1, -1, SF(CPN), "Last used cpu (SMP)", L_stat }, - { "..\\|","Bad ", "%2u ", -1, -1, SF(CPN), "-- must ignore | --", 0 }, - { "..]}", "Bad ", "%2u ", -1, -1, SF(CPN), "-- not used --", 0 }, - { "..^~", "Bad ", "%2u ", -1, -1, SF(CPN), "-- not used --", 0 }, + { "..Qq", " A", " %4.4s", 4, SK_no, SF(PID), "Accessed Page count", L_stat }, + { "..Nn", " TRS", " %4.4s", 4, SK_Kb, SF(PID), "Code in memory (kb)", L_stat }, + { "..Rr", " WP", " %4.4s", 4, SK_no, SF(PID), "Unwritable Pages", L_stat }, + { "Jj[{", " #C", " %2u", -1, -1, SF(CPN), "Last used cpu (SMP)", L_stat }, + { "..\\|"," Bad", " %2u", -1, -1, SF(CPN), "-- must ignore | --", 0 }, + { "..]}", " Bad", " %2u", -1, -1, SF(CPN), "-- not used --", 0 }, + { "..^~", " Bad", " %2u", -1, -1, SF(CPN), "-- not used --", 0 }, #endif }; #undef SF @@ -2022,7 +2015,7 @@ static void reframewins (void) for (i = 0; i < w->maxpflgs; i++) { h = Fieldstab[w->procflags[i]].head; // oops, won't fit -- we're outta here... - if (Screen_cols < (int)((s - w->columnhdr) + strlen(h))) break; + if (Screen_cols+1 < (int)((s - w->columnhdr) + strlen(h))) break; s = scat(s, h); } @@ -2030,28 +2023,29 @@ static void reframewins (void) // heading via maxcmdln - it may be a fib if P_CMD wasn't encountered, // but that's ok because it won't be displayed anyway w->maxpflgs = i; - w->maxcmdln = Screen_cols - - (strlen(w->columnhdr) - strlen(Fieldstab[P_CMD].head)) - 1; + w->maxcmdln = Screen_cols - (strlen(w->columnhdr) - strlen(Fieldstab[P_CMD].head)); // finally, we can build the true run-time columns header, format the // command column heading, if P_CMD is really being displayed, and // rebuild the all-important PROC_FILLxxx flags that will be used // until/if we're we're called again *(s = w->columnhdr) = '\0'; - if (Rc.mode_altscr) s = scat(s, fmtmk("%d", w->winnum)); +// if (Rc.mode_altscr) s = scat(s, fmtmk("%d", w->winnum)); for (i = 0; i < w->maxpflgs; i++) { + int advance = (i==0) && !Rc.mode_altscr; h = Fieldstab[w->procflags[i]].head; if (P_WCH == w->procflags[i]) needpsdb = 1; if (P_CMD == w->procflags[i]) { - s = scat(s, fmtmk(Fieldstab[P_CMD].fmts, w->maxcmdln, w->maxcmdln, h)); + s = scat(s, fmtmk(Fieldstab[P_CMD].fmts+advance, w->maxcmdln, w->maxcmdln, "COMMAND"/*h*/ )); if (CHKw(w, Show_CMDLIN)) { Frames_libflags |= L_CMDLINE; // if (w->maxcmdln > Frames_maxcmdln) Frames_maxcmdln = w->maxcmdln; } } else - s = scat(s, h); + s = scat(s, h+advance); Frames_libflags |= Fieldstab[w->procflags[i]].lflg; } + if (Rc.mode_altscr) w->columnhdr[0] = w->winnum + '0'; } if (Rc.mode_altscr) w = w->next; } while (w != Curwin); @@ -2904,12 +2898,14 @@ static proc_t **summary_show (void) // Display information for a single task row. static void task_show (const WIN_t *q, const proc_t *p) { - char rbuf[ROWBUFSIZ], *rp; + char rbuf[ROWBUFSIZ]; + char *rp = rbuf; int j, x, pad; - // we must begin a row with a possible window number in mind... - *(rp = rbuf) = '\0'; - if ((pad = Rc.mode_altscr)) rp = scat(rp, " "); + *rp = '\0'; + + pad = Rc.mode_altscr; +// if (pad) rp = scat(rp, " "); for (x = 0; x < q->maxpflgs; x++) { char cbuf[ROWBUFSIZ], _z[ROWBUFSIZ]; @@ -2918,6 +2914,8 @@ static void task_show (const WIN_t *q, const proc_t *p) unsigned s = Fieldstab[i].scale; // string must be altered ! unsigned w = Fieldstab[i].width; + int advance = (x==0) && !Rc.mode_altscr; + switch (i) { case P_CMD: { char tmp[ROWBUFSIZ]; @@ -2974,7 +2972,7 @@ static void task_show (const WIN_t *q, const proc_t *p) break; case P_PRI: if (unlikely(-99 > p->priority) || unlikely(999 < p->priority)) { - f = " RT "; + f = " RT"; MKCOL(""); } else MKCOL((int)p->priority); @@ -3023,11 +3021,7 @@ static void task_show (const WIN_t *q, const proc_t *p) break; case P_WCH: if (No_ksyms) { -#ifdef CASEUP_HEXES - f = "%08lX "; -#else - f = "%08lx "; -#endif + f = " %08lx "; MKCOL((long)p->wchan); } else { MKCOL(wchan(p->wchan, p->XXXID)); @@ -3036,7 +3030,7 @@ static void task_show (const WIN_t *q, const proc_t *p) } /* end: switch 'procflag' */ - rp = scat(rp, cbuf); + rp = scat(rp, cbuf+advance); } /* end: for 'maxpflgs' */ PUFF( @@ -3045,7 +3039,7 @@ static void task_show (const WIN_t *q, const proc_t *p) Screen_cols + pad, rbuf, Caps_off, - Cap_clr_eol + "" /*Cap_clr_eol*/ ); #undef MKCOL diff --git a/top.h b/top.h index c035b713..77bbee6d 100644 --- a/top.h +++ b/top.h @@ -128,19 +128,37 @@ // - may NOT contain cursor motion terminfo escapes // - assumed to represent a complete screen ROW // - subject to optimization, thus MAY be discarded -#define PUFF(fmt,arg...) do { \ - char _str[ROWBUFSIZ]; \ - char *_ptr = &Pseudo_scrn[Pseudo_row++ * Pseudo_cols]; \ - int _len = 1 + snprintf(_str, sizeof(_str), fmt, ## arg); \ - if (Batch) putp(_str); \ - else { \ - if (!memcmp(_ptr, _str, _len)) \ - putp("\n"); \ - else { \ - memcpy(_ptr, _str, _len); \ - putp(_ptr); \ - } } \ - } while (0) + +// The evil version (53892 byte stripped top, oddly enough) +#define _PUFF(fmt,arg...) \ +do { \ + char _str[ROWBUFSIZ]; \ + int _len = 1 + snprintf(_str, sizeof(_str), fmt, ## arg); \ + putp ( Batch ? _str : \ + ({ \ + char *restrict const _pse = &Pseudo_scrn[Pseudo_row++ * Pseudo_cols]; \ + memcmp(_pse, _str, _len) ? memcpy(_pse, _str, _len) : "\n"; \ + }) \ + ); \ +} while (0) + +// The good version (53876 byte stripped top) +#define PUFF(fmt,arg...) \ +do { \ + char _str[ROWBUFSIZ]; \ + char *_ptr; \ + int _len = 1 + snprintf(_str, sizeof(_str), fmt, ## arg); \ + if (Batch) _ptr = _str; \ + else { \ + _ptr = &Pseudo_scrn[Pseudo_row++ * Pseudo_cols]; \ + if (memcmp(_ptr, _str, _len)) { \ + memcpy(_ptr, _str, _len); \ + } else { \ + _ptr = "\n"; \ + } \ + } \ + putp(_ptr); \ +} while (0) /*------ Special Macros (debug and/or informative) ---------------------*/ diff --git a/watch.c b/watch.c index deec4623..66dde649 100644 --- a/watch.c +++ b/watch.c @@ -96,7 +96,7 @@ main(int argc, char *argv[]) int option_differences = 0, option_differences_cumulative = 0, option_help = 0, option_version = 0; - int interval = 2; + float interval = 2; char *command; int command_length = 0; /* not including final \0 */ @@ -120,9 +120,11 @@ main(int argc, char *argv[]) case 'n': { char *str; - interval = strtol(optarg, &str, 10); + interval = strtof(optarg, &str); if (!*optarg || *str) do_usage(); + if(interval < 0.1) + interval = 0.1; } break; case 'v': @@ -203,8 +205,8 @@ main(int argc, char *argv[]) if (show_title) { // left justify interval and command, // right justify time, clipping all to fit window width - asprintf(&header, "Every %ds: %.*s", - interval, min(width - 1, command_length), command); + asprintf(&header, "Every %.1fs: %.*s", + interval, min(width - 1, command_length), command); mvaddstr(0, 0, header); if (strlen(header) > (size_t) (width - tsl - 1)) mvaddstr(0, width - tsl - 4, "... "); @@ -268,7 +270,7 @@ main(int argc, char *argv[]) first_screen = 0; refresh(); - sleep(interval); + usleep(interval * 1000000); } endwin();