Merge branch 'newtop'
This commit is contained in:
commit
c3b7310149
19
.gitignore
vendored
Normal file
19
.gitignore
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
free
|
||||||
|
kill
|
||||||
|
pgrep
|
||||||
|
pkill
|
||||||
|
pmap
|
||||||
|
proc/.depend
|
||||||
|
proc/libproc-3.2.8.so
|
||||||
|
ps/ps
|
||||||
|
pwdx
|
||||||
|
skill
|
||||||
|
slabtop
|
||||||
|
snice
|
||||||
|
sysctl
|
||||||
|
tload
|
||||||
|
top
|
||||||
|
uptime
|
||||||
|
vmstat
|
||||||
|
w
|
||||||
|
watch
|
871
README.top
871
README.top
@ -1,545 +1,328 @@
|
|||||||
Credit for this belongs to:
|
This file summarizes changes to the top program and supporting documentation
|
||||||
Jim / James C. Warner, <warnerjc@worldnet.att.net>
|
introduced on March 31, 2011.
|
||||||
|
|
||||||
----------------------------------
|
Contents:
|
||||||
|
DOCUMENT Changes
|
||||||
Ok, ok, I yield -- most of what follows has been removed from the manual page
|
INTERNAL Improvements
|
||||||
and packaged separately as this README (hey, it was only TEMPORARY insanity).
|
EXTERNAL Improvements
|
||||||
|
BUGS Previously Fixed and Preserved
|
||||||
Of course, that means that now absolutely nobody will ever read it.
|
BUGS Newly/Nearly Fixed
|
||||||
|
BUGS/WISH-LISTS That Should Go Bye-bye
|
||||||
This is probably a good thing...
|
BUGS FIXED You Didn't Know You Had
|
||||||
|
OTHER Changes, Hopefully They Won't Bite You
|
||||||
|
BENCHMARKS
|
||||||
## Table of Contents ---------------------------------------------------##
|
|
||||||
# the only darn thing that wasn't in the man page
|
|
||||||
CUSTOMIZING the Sources
|
DOCUMENT Changes =========================================================
|
||||||
# the following carry their original topic numbers
|
. The entire file was cleaned up, standardized and expanded to include:
|
||||||
DIFFERENCES / New Features
|
- a new section "2. SUMMARY Display" added for symmetry with Fields
|
||||||
Interface Etiquette
|
- nine new fields were added to section "3a. DESCRIPTIONS of Fields"
|
||||||
Expanded Configurable Display Support
|
- a new section "3b. MANAGING Fields" replaced the obsolete section
|
||||||
Enhanced Field/Column Management
|
"2b. SELECTING and ORDERING Columns"
|
||||||
Customization Flexibility
|
- section "5c. SCROLLING a Window" was added for that new feature
|
||||||
NOTES and Rantings
|
|
||||||
The top Binary
|
. I don't know when the explanations for CODE and DATA were changed to
|
||||||
Comparing Performance
|
show 'virtual' memory, but I think there's a reason their alternate
|
||||||
Cost of Stuff
|
names contain the word 'resident'. Thus they were changed back to
|
||||||
The top Sources
|
say 'physical memory'.
|
||||||
EXAMPLES of Windows
|
|
||||||
The 'A' Mode Command Toggle
|
. And as I indicated in a previous email, the former string identifier
|
||||||
STACKIN' & WHACKIN' Windows
|
'ME' was restored as were the 'h' key/command conventions (vs. <h>).
|
||||||
ALL TOGETHER Now, Window(s)
|
|
||||||
|
Oops, the 'h' key/command conventions remain restored, but subsequent
|
||||||
|
testing revealed problems with the .ME string identifier. Thus, it was
|
||||||
## CUSTOMIZING the Sources ---------------------------------------------##
|
changed to .WE (along with the companion .Me/.We id).
|
||||||
|
|
||||||
Listed below are the conditionals available should you wish to recompile
|
. Also previously mentioned, the 'man2html' program translates top.1 to
|
||||||
this top. The author's favorite is: PRETEND4CPUS.
|
HTML with near perfect fidelity. I take that to mean there should be
|
||||||
|
no problems with the top.1 source on most other platforms.
|
||||||
That's the #define allowing you to simulate an SMP environment, and
|
|
||||||
(perhaps) impress your friends. It's currently set to display four
|
To further improve translation to HTML, several .Bd and .Ed macros
|
||||||
separate CPUs, but could easily be changed.
|
were added to preserve literal (fixed width) spacing.
|
||||||
|
|
||||||
Caution: do NOT use this provision in an effort to impress someone
|
|
||||||
who truly possesses such a machine! The fact that all 4
|
INTERNAL Improvements ====================================================
|
||||||
CPUs show the same dynamic results will likely have the
|
. The old restriction of 26 fields has been lifted. With this new-top
|
||||||
opposite effect.
|
100+ fields are now possible. It currently supports up to 55, of
|
||||||
|
which 35 are in use. Adding a new field is almost too easy.
|
||||||
|
|
||||||
//#define ATEOJ_REPORT /* report a bunch of stuff, at end-of-job */
|
. Task row construction has been considerably improved -- both from
|
||||||
//#define CASEUP_HEXES /* show any hex values in upper case */
|
a programming perspective and a performance perspective.
|
||||||
//#define CASEUP_SCALE /* show scaled time/num suffix upper case */
|
|
||||||
//#define CASEUP_SUMMK /* show memory summary kilobytes with 'K' */
|
. The column highlighting costs for sort field visibility were
|
||||||
//#define POSIX_CMDLIN /* use '[ ]' for kernel threads, not '( )' */
|
virtually eliminated.
|
||||||
//#define PRETEND2_5_X /* pretend we're linux 2.5.x (for IO-wait) */
|
|
||||||
//#define PRETEND4CPUS /* pretend we're smp with 4 ticsers (sic) */
|
An optional define (USE_X_COLHDR) can be enabled to completely
|
||||||
//#define PRETENDNOCAP /* use a terminal without essential caps */
|
eliminate any costs associated with the 'x' command toggle.
|
||||||
//#define SORT_SUPRESS /* *attempt* to reduce qsort overhead */
|
|
||||||
//#define STDOUT_IOLBF /* disable our own stdout _IOFBF override */
|
. The management of the HST_t structures, used for %cpu calculations,
|
||||||
//#define USE_LIB_STA3 /* use lib status (3 ch) vs. proc_t (1 ch) */
|
was optimized with a hashing scheme. Thus the need for a qsort then
|
||||||
//#define WARN_NOT_SMP /* restrict '1' & 'I' commands to true smp */
|
a binary search in each frame was completely eliminated.
|
||||||
|
|
||||||
|
An optional define can restore the former qsort/bsearch approach but
|
||||||
## 6. DIFFERENCES / New Features ---------------------------------------##
|
with an internal inlined binary search function offering substantially
|
||||||
The following summarizes differences between this top and your
|
better performance than the old top.
|
||||||
former top. It was originally based on procps-2.0.7. However,
|
|
||||||
except for the separate/summary CPU toggle, all of these differ-
|
. This far more capable new-top executable is no larger than old top.
|
||||||
ences also apply through procps-2.0.10.
|
|
||||||
|
. The above combine to produce substantially improved performance
|
||||||
6a. Interface Etiquette
|
whose details are documented below under BENCHMARKS.
|
||||||
-*- Input and output are far more carefully implemented in
|
|
||||||
this top. You won't be subjected to 4 - 5 'Unknown command'
|
|
||||||
messages should you press the wrong key.
|
EXTERNAL Improvements ====================================================
|
||||||
|
. Field management has been completely redesigned. It's now embodied
|
||||||
-*- You need suffer a confirmation message only when the results
|
on a single screen where display-ability, position and sort selection
|
||||||
of a command are not obvious by their effects on the display.
|
can be handled in one place -- for all windows at one time!
|
||||||
|
|
||||||
-*- The Help screen will no longer overflow, even when running
|
This function is dependent on cursor motion keys and should a device
|
||||||
with a 24 row xterm (vt100).
|
not have the customary arrow keys, alternatives are provided and
|
||||||
|
documented under "Operation" near the beginning of the man page.
|
||||||
-*- The fields selection/ordering screens do not carelessly
|
|
||||||
destroy important information through unintended line wraps.
|
. The following new fields have been added:
|
||||||
|
Group Id
|
||||||
-*- Should you narrow a xterm window to less than 80 columns
|
Minor Page Faults
|
||||||
while this top is running, you will not be left with an
|
Number of Threads
|
||||||
utterly worthless, embarrassing display.
|
Process Group Id
|
||||||
|
Real User Id
|
||||||
6b. Expanded Configurable Display Support
|
Saved User Id
|
||||||
-*- In an SMP environment, you can choose between a summary dis-
|
Saved User Name
|
||||||
play or you may show each cpu separately. No longer must
|
Session Id
|
||||||
this choice be irrevocably made at startup.
|
Tty Process Group Id
|
||||||
|
|
||||||
-*- There are new fields and with this top, any field is
|
. Scrolling keys now allow one to move the view of any window vertically
|
||||||
selectable for sorting. Plus, your sorted column can be
|
or horizontally to reveal any desired task or column. Previously, only
|
||||||
instantly reversed with just a single keystroke.
|
some tasks were viewable even with reversible, selectable sort columns.
|
||||||
|
|
||||||
-*- You may optionally apply 2 distinct types of highlighting to
|
Each of the four windows is capable of maintaining its own scrolled
|
||||||
running tasks and/or sorted columns. With this top, you'll
|
coordinates and an optional toggle ('C') displays a message aiding
|
||||||
be able to instantly spot running tasks and always know the
|
navigation within the available tasks and displayable fields.
|
||||||
current sort field.
|
|
||||||
|
. User interactive line oriented input now provides for true line
|
||||||
-*- While you could continue to use the more familiar (and
|
editing supported by these new keys:
|
||||||
boring) monochrome display, you might want to try this top's
|
Left/Right arrow keys, Delete key, Backspace and
|
||||||
new color display. You can even create your own unique col-
|
Home/End keys (likely limited to xterm, not terminal)
|
||||||
ors used in summaries, messages, headings and tasks, each of
|
|
||||||
which can be made persistent until you choose to change them.
|
. User filtering via the -u | -U interactive commands is now window
|
||||||
|
based which means that different windows could be used to filter
|
||||||
-*- Up to four separate windows can be displayed simultaneously,
|
different users.
|
||||||
giving you four separate ways to sort and view the tasks cur-
|
|
||||||
rently cluttering up your system. You could have one view by
|
. Signal handling has been normalized and is now consistent regardless
|
||||||
pids, another by cpu usage, yet another showing memory con-
|
of the particular top screen a user may have been using.
|
||||||
sumption. You get the idea...
|
|
||||||
|
. The 'i' toggle now shows any task that has used *some* cpu since the
|
||||||
-*- Each window comes with pre-configured (but user configurable)
|
last screen update. It's no longer limited to just running tasks.
|
||||||
fields and you can size each window individually.
|
|
||||||
|
. The summary area 'task states' line now reflects either 'Threads'
|
||||||
-*- Virtually every one of this top's options (summaries, fields,
|
or 'Tasks' depending on the -H toggle.
|
||||||
colors, sorted column, etc.) is separately configurable for
|
|
||||||
each of those four windows.
|
|
||||||
|
BUGS Previously Fixed and Preserved ======================================
|
||||||
Heck, you can even change a window's name, if you don't care
|
( but not necessarily literally)
|
||||||
for top's choices. Your changes will be reflected not only
|
. 228822, suspending top leaves xterm in slightly messed-up state
|
||||||
when you're in what top calls alternate-display mode but also
|
. 256376, segfaults, if the xterm is to small
|
||||||
on his special new 'Windows' help screen.
|
. 320289, segv on sigwinch
|
||||||
|
. 351065, wrong highlight 1st column (escape characters displayed)
|
||||||
-*- And, [ ** Drum-Roll + Ta-Da ** ] with just one keystroke you
|
. 358724, accepts extra numeric args
|
||||||
can quickly switch between full-screen and multiple window
|
. 378695, seg fault if "/proc" is not mounted
|
||||||
modes! Or, with a different keystroke, toggle a single win-
|
. 426782, UID field is too narrow
|
||||||
dow Off for now, then On again later!!
|
. 458986, should check xterm for EOF/EIO
|
||||||
|
. 459890, Irix mode should use %#4.1f when threads shown
|
||||||
6c. Enhanced Field/Column Management
|
|
||||||
-*- Many Field/Column names have been changed to make them more
|
|
||||||
intuitive, more self-descriptive. And with this top you
|
BUGS Newly/Nearly Fixed ==================================================
|
||||||
won't be fooled with field choices that are "not yet imple-
|
. 225542, 'Unknown command' message blocks further commands
|
||||||
mented".
|
The message is now displayed using usleep for 1.25 seconds, instead
|
||||||
|
of the former full 2 seconds. And while it still blocks further
|
||||||
-*- Task memory statistics are more meaningful and more accurate.
|
commands, the delay is much more tolerable.
|
||||||
|
|
||||||
-*- You'll finally have complete display integrity regardless of
|
Can we consider this bug 'nearly' fixed?
|
||||||
field selections, their order or screen width. And that
|
|
||||||
means the command column no longer need be kept as the right-
|
. 410292, interface error when using backspace
|
||||||
most field, lest your screen turn to <bleep> when all the
|
Full line editing was added but could be disabled via a #define.
|
||||||
following columns get misaligned.
|
And via that define, even under basic termios support, the backspace
|
||||||
|
problem was cured.
|
||||||
6d. Customization Flexibility
|
|
||||||
-*- You have complete program naming freedom with no internal
|
. 567509, top idle command ('i') not working for threaded programs
|
||||||
ties to a specific personal configuration file. Symbolic
|
Since the 'i' command now reflects tasks that have used *some* cpu,
|
||||||
links could be used to establish different configuration
|
and is no longer dependent on an 'R' state, I *believe/hope* this
|
||||||
files reflecting the different personalities of your cus-
|
bug has been swatted.
|
||||||
tomized "tops", under whatever aliases you've used.
|
|
||||||
|
|
||||||
Thus, you could have an alias for running top in 'Batch
|
BUGS/WISH-LISTS That Should Go Bye-bye ===================================
|
||||||
mode', another for when you work from the Linux console and
|
. 340751, wish for hostname to benefit multiple top sessions
|
||||||
maybe a third used with X-Windows. All of that, yet still
|
Craig's suggestion regarding symlinks is the perfect solution.
|
||||||
just a single binary image!
|
How dare Craig say that the solution was "not ideal" !
|
||||||
|
|
||||||
-*- All of your configuration choices can be preserved in a per-
|
. 586497, wish for graceful degradation on small screen sizes
|
||||||
sonal configuration file, including any changes made on a
|
This objective could be accomplished by setting up 2 symlinks for
|
||||||
per-window basis. Thus, once you personalize things they
|
top, personalizing them for the 2 tiny phone displays, then writing
|
||||||
remain personalized until you decide to change them again.
|
the respective configuration files.
|
||||||
This top has been completely cured of:
|
|
||||||
i-cant-remember-so-please-do-that-all-over-again
|
I shudder at the programming effort suggested by Paul. And when it
|
||||||
( and again, and again ... )
|
was done you'd find everybody else would have different criteria.
|
||||||
|
|
||||||
The bottom line is this: if you save your configuration
|
|
||||||
before quitting top, upon restart the display will appear
|
BUGS FIXED You Didn't Know You Had =======================================
|
||||||
exactly as you left it. And that means you no longer have to
|
. Without amplifying the dirty details, the long standing occasionally
|
||||||
keep top running until-the-end-of-time (ok, a long time
|
reported display corruption, and an unreported source of performance
|
||||||
anyway), lest your customizations go bye-bye.
|
degradation, has been eliminated. The cure is in the elimination of
|
||||||
|
the Pseudo_cols variable and the improved PUFF macro.
|
||||||
|
|
||||||
## 7. NOTES and Rantings -----------------------------------------------##
|
. Line oriented input was not sensitive to screen width. Thus a user
|
||||||
7a. The top Binary
|
could hold down any key and ultimately line wrap, overwriting the
|
||||||
To whom it may (should) concern: this top, even with its vastly
|
columns header and the entire screen. New top prevents this.
|
||||||
expanded capabilities, is only slightly larger than the old top.
|
|
||||||
Were it not for extensive help text and additional sort callbacks,
|
. User filtering (-u|-U) via a user ID (not name) now validates that
|
||||||
it would be smaller.
|
number. The old-top just made sure it was numeric, then blindly
|
||||||
Throw source carelessly at objectives, it will
|
displayed no matching users (i.e. an empty window).
|
||||||
produce equally careless machine instructions.
|
|
||||||
example: (num_pages - an_address)/1024 == duh?
|
. The threads toggle ('H') is no longer window based but more properly
|
||||||
kicker: document result as broken, due to elf!
|
applies to all windows. The previous implementation produced the
|
||||||
----------------------------------------------
|
following aberration if multiple windows were being shown:
|
||||||
I know you're out there, are you getting this?
|
. -H would be acknowledged and applied to all visible windows
|
||||||
|
. keying 'a' or 'w' would silently turn it off
|
||||||
Now, as for all those new capabilities like colors and windows and
|
. then keying -H would turn it back on, but the user expected off
|
||||||
highlighting, you'd expect this top to be the "mother of all pigs"
|
|
||||||
compared to old top -- right?
|
. If you hit ^Z on any help or fields screen to suspend old-top, after
|
||||||
|
issuing 'fg' you would then be left with a seemingly hung application
|
||||||
Yea, with this top expect following piglets:
|
inviting ^C. In truth, one could recover with the space bar, but that
|
||||||
. A smaller virtual image and resident footprint
|
was far from intuitive.
|
||||||
. Slightly fewer major page faults
|
|
||||||
. A large reduction in minor page faults for SMP
|
. The old-top consistently writes 1 extra byte for each task row or 1
|
||||||
. The same or better response time
|
byte too few for columns headers, depending on your perspective.
|
||||||
. The same or even less CPU costs
|
The new top writes the same number of bytes for each.
|
||||||
|
|
||||||
Ideally any comparison of the old and new top should be against
|
. By failing to clear to eol, old top left the display in a terrible
|
||||||
the same libproc format (32-bit or 64-bit tics) and run in a true
|
state after exiting a 'fields' screen when only a few columns were
|
||||||
or simulated SMP environment (producing separate CPU stats). This
|
being displayed.
|
||||||
latter requirement will coax old top into handling his own
|
|
||||||
'/proc/stat' access -- something this top always does, but with
|
. The old-top used a zero value for the L_NONE library flag which could
|
||||||
less cost.
|
cause repeated rebuilding of columns headers with each frame. In truth,
|
||||||
|
this was not likely to happen in real life since only two fields actually
|
||||||
7b. Comparing Performance
|
used that flag. However, if it did happen, performance could be degraded
|
||||||
Even with equivalent libraries and '/proc/stat' access, it's dif-
|
by 800%.
|
||||||
ficult to accurately compare tops using their own displays.
|
|
||||||
Results for these cpu-intensive programs (who frequently exceed
|
|
||||||
their time-slice) generally show a wide disparity in %CPU. This
|
OTHER Changes, Hopefully They Won't Bite You =============================
|
||||||
is due to differing call patterns, kernel preemptions and the tim-
|
. The undocumented TOPRC environment variable is no longer supported.
|
||||||
ing of process snapshots. For slightly better results, start each
|
Any similar need can be met through a symlink alias.
|
||||||
program with the following commands:
|
|
||||||
./old-top -d 0.5
|
. The use of environment variables to override terminal size is now
|
||||||
nice -n-10 ./new-top -d 0.4
|
off by default but could be enabled through '#define TTYGETENVYES'.
|
||||||
|
|
||||||
While actually putting this top at a performance disadvantage, the
|
. The global 'bold enable' toggle is active by default and thus agrees
|
||||||
higher scheduling priority and staggered timing will periodically
|
with the documentation. It's been wrong ever since Al's wholesale
|
||||||
yield a somewhat truer picture. You could even reverse those
|
'cosmetic' changes in procps-3.2.2.
|
||||||
roles and get similar results.
|
|
||||||
|
. Task defaults now show bold (not reverse) and row highlighting.
|
||||||
The most consistent performance results will be obtained 'off-
|
This agrees with what was always stated in the documentation.
|
||||||
line', using your shell's time pipe or the time program itself.
|
|
||||||
And even in a single processor environment or without equivalent
|
. The 'H' toggle (thread mode) is not persistent. Persistence can be
|
||||||
libraries, total cpu costs (user time + system time) are similar.
|
achieved with a simple shell script employing the -H switch.
|
||||||
|
|
||||||
However, this top's cpu costs ARE influenced by the capabilities
|
. Then 'g' and 'G' commands were reversed to reflect their likely use.
|
||||||
you choose to exploit, even if they don't SEEM to be reflected in
|
|
||||||
such timings. So let's examine some...
|
|
||||||
|
BENCHMARKS ===============================================================
|
||||||
7c. Cost of Stuff
|
Tested as root with nice -10 and using only common fields
|
||||||
Colors Cost -- Nada (almost).
|
( on a pretty old, slow laptop under Debian Lenny )
|
||||||
Once the terminfo strings are built (at and during a user's
|
but rcfiles specified identical sort fields and identical
|
||||||
behest) they are SAVED with each window's stuff. And while
|
settings for the 'B', 'b', 'x' and 'y' toggles (even though
|
||||||
there will be extra tty escape sequences transmitted because of
|
the defaults are not necessarily identical).
|
||||||
colors, it makes no difference which 'char *' is actually used.
|
|
||||||
|
In every case new-top outperforms old-top, but I've shown %
|
||||||
Highlighting Cost -- Nada (maybe), or blame it on Rio.
|
improvements for only the most significant. Those cases mostly
|
||||||
On second thought, let's blame it on the user.
|
involve colors with both row & column highlighting. I suggested
|
||||||
|
above that the highlighting cost was virtually eliminated in
|
||||||
For row highlighting, there is only the cost of those extra tty
|
new-top, and these tests bare that out.
|
||||||
escape sequences (same as for colors). For column highlight-
|
|
||||||
ing, there is a fairly significant cost associated with column
|
Note the much smaller differences for new-top between the 24x80
|
||||||
transition management combined with even more tty output.
|
window results and full screen (but don't mix apples_terminal
|
||||||
These increased costs are incurred on every task display row.
|
with oranges_xterm). This is a reflection of the simplification
|
||||||
|
of task row construction, also mentioned above.
|
||||||
Sooo... hey USER -- do NOT highlight COLUMNS. You shouldn't
|
|
||||||
need a constant visual reminder of your chosen sort field.
|
It's always been the case that any top in an xterm outperforms
|
||||||
However, if you forget which field top is sorting it can serve
|
that top under the terminal application, even when the xterm
|
||||||
as a quick visual reminder.
|
provides additional rows and columns. It's true below with
|
||||||
|
Gnome and it was true nine years ago under KDE.
|
||||||
Windows Cost -- Nada (if just 1 window).
|
|
||||||
If more than 1 window, almost certainly NOT Nada so blame it on
|
----------------------------------------------------------
|
||||||
reality. Colors are not an issue, but those sort fields are.
|
The following comparisons were run with:
|
||||||
|
100 tasks & 160 threads
|
||||||
If we could trust the user to always select the same 'c' state,
|
-d0 -n5000
|
||||||
'S' state and sort field (hey, why ya got multiple windows then
|
new-top old-top
|
||||||
user, huh?) AND if we can trust someone to recompile top with a
|
xterm 24x80
|
||||||
#define enabled, then we could achieve 'Nada'.
|
a 1 win, lflgs_none 11.2 secs 51.8 secs + 462.6%
|
||||||
|
1 win, default 61.0 secs 66.8 secs
|
||||||
Ok, not likely, so we're gonna' be doing multiple sorts. BUT,
|
1 win, colors w/ x+y 61.3 secs 83.0 secs + 135.4%
|
||||||
it may not be as bad as it sounds. Those sorts involve point-
|
1 win, thread mode 88.3 secs 94.2 secs
|
||||||
ers only. And, that's as good as it gets ! (right Mr. N?)
|
b 1 win, every field on 99.7 secs 106.0 secs
|
||||||
|
1 win, cmdline 71.2 secs 76.6 secs
|
||||||
7d. The top Sources
|
4 wins, defaults 101.3 secs 107.2 secs
|
||||||
top.h
|
4 wins, colors w/ x+y 101.5 secs 122.8 secs + 121.0%
|
||||||
Unlike his predecessor, this top has a proper header file. It
|
|
||||||
contains ONLY declarations, NOT definitions. And there are
|
xterm, full screen (53x170)
|
||||||
several conditionals present to help with further customiza-
|
a 1 win, lflgs_none 15.9 secs 54.2 secs + 340.9%
|
||||||
tions and experimentation. All are Off by default.
|
1 win, default 70.0 secs 73.2 secs
|
||||||
|
1 win, colors w/ x+y 69.4 secs 131.3 secs + 189.2%
|
||||||
top.c
|
1 win, thread mode 97.6 secs 102.6 secs
|
||||||
Hopefully proves that source code needn't be a disorganized,
|
c 1 win, every field on 122.1 secs 128.1 secs
|
||||||
misaligned MESS. And, WHO says a source listing shouldn't
|
1 win, cmdline 80.8 secs 83.7 secs
|
||||||
occasionally make you SMILE? Why, top.c even does a darn good
|
4 wins, defaults 111.4 secs 115.8 secs
|
||||||
job of following the suggestions in a document hardly anybody
|
4 wins, colors w/ x+y 112.0 secs 172.9 secs + 154.4%
|
||||||
seems to observe.
|
|
||||||
|
terminal 24x80
|
||||||
the Linus Torvalds CodingStyle guidelines ...
|
a 1 win, lflgs_none 8.9 secs 58.6 secs + 658.4%
|
||||||
-*- -*- -*- on indentation + etc. -*- -*- -*-
|
1 win, default 70.1 secs 80.3 secs
|
||||||
well almost all, except for those stinkin'...
|
1 win, colors w/ x+y 70.6 secs 157.3 secs + 222.8%
|
||||||
|
1 win, thread mode 104.7 secs 120.5 secs
|
||||||
I suppose even Linus Torvalds is entitled to err now and again.
|
b 1 win, every field on 111.2 secs 134.5 secs
|
||||||
How so you say? Tabs, me' bucko, stinkin' tabs! That, plus the
|
1 win, cmdline 83.8 secs 94.5 secs
|
||||||
simplistic position regarding indentation espoused in that other-
|
4 wins, defaults 125.6 secs 146.7 secs
|
||||||
wise excellent document.
|
4 wins, colors w/ x+y 125.6 secs 206.9 secs + 176.7%
|
||||||
|
|
||||||
-*- Rant On, and on -*-
|
terminal, full screen (39x125)
|
||||||
Let's compare two approaches to the tab/indentation issue with a
|
a 1 win, lflgs_none 9.1 secs 60.6 secs + 665.9%
|
||||||
small code sample using tabs then spaces. This snippet happens to
|
1 win, default 74.3 secs 88.0 secs
|
||||||
be the key to top's use of dynamic colors on many static screens,
|
1 win, colors w/ x+y 73.9 secs 314.5 secs + 425.6%
|
||||||
while also ensuring screen width isn't exceeded so as to avoid
|
1 win, thread mode 113.0 secs 140.9 secs
|
||||||
line wraps. We'll view just the first 40 columns, assuming one
|
b 1 win, every field on 117.7 secs 154.9 secs
|
||||||
wishes to occasionally provide comments to the right of actual
|
1 win, cmdline 87.4 secs 107.2 secs
|
||||||
code (you do, don't you?).
|
4 wins, defaults 139.1 secs 166.7 secs
|
||||||
|
4 wins, colors w/ x+y 157.3 secs 423.2 secs + 269.0%
|
||||||
Then YOU decide which approach makes the most SENSE!
|
|
||||||
|
----------------------------------------------------------
|
||||||
Stinkin' Tabs versus Spaces: the Linus way
|
The following comarisons were run with:
|
||||||
Hey, where'd my +----+----1----+----2----+----3----+----4+
|
300 tasks & 360 threads
|
||||||
many code lines | while (*sub_beg) { :
|
-d0 -n3000
|
||||||
up-and-gone-to? | switch (*sub_end:
|
new-top old-top
|
||||||
| case 0: :
|
xterm, full screen (53x170)
|
||||||
Gosh, wonder if | \ Tabs Induced / :
|
a 1 win, lflgs_none 14.3 secs 79.0 secs + 552.4%
|
||||||
Linus expects a | case 1: :
|
1 win, default 101.1 secs 104.5 secs
|
||||||
fellow to stick | + WASTE-Lands! + case 5: :
|
1 win, colors w/ x+y 101.3 secs 140.0 secs + 138.2%
|
||||||
his comments on | :
|
1 win, thread mode 120.1 secs 123.1 secs
|
||||||
the left side?! | + Not a Living + :
|
c 1 win, every field on 179.8 secs 185.6 secs
|
||||||
| :
|
1 win, cmdline 124.9 secs 132.8 secs
|
||||||
Ever see source | + line-of-code + :
|
4 wins, defaults 174.8 secs 179.2 secs
|
||||||
with not enough | :
|
4 wins, colors w/ x+y 175.0 secs 215.2 secs + 123.0%
|
||||||
whitespace; and | / To Be Found! \ :
|
|
||||||
this is better? | default::
|
terminal, full screen (39x125)
|
||||||
| :
|
a 1 win, lflgs_none 12.3 secs 98.5 secs + 800.8%
|
||||||
Oh lookie here, \ } :
|
1 win, default 117.4 secs 134.0 secs
|
||||||
there's just a hint of REAL code! ----> if (0 >= room) b:
|
1 win, colors w/ x+y 111.6 secs 296.1 secs + 265.3%
|
||||||
/ } /* end: while 'subtrin:
|
1 win, thread mode 141.3 secs 155.3 secs
|
||||||
+----------------------------------------+
|
b 1 win, every field on 197.7 secs 204.8 secs
|
||||||
|
1 win, cmdline 143.9 secs 157.3 secs
|
||||||
Spaces versus Stinkin' Tabs: the other way
|
4 wins, defaults 204.0 secs 226.2 secs
|
||||||
+----+----1----+----2----+----3----+----4+
|
4 wins, colors w/ x+y 216.9 secs 434.5 secs + 200.3%
|
||||||
Wow, now this is | while (*sub_beg) { :
|
|
||||||
Visible hackin'! | switch (*sub_end) { :
|
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||||
| case 0: :
|
|
||||||
Hmmm, wonder how | *(sub_end + 1) = '\0'; :
|
notes:
|
||||||
many programmers | case 1: case 2: case 3: case:
|
a these results represent the library flags L_NONE zero value and
|
||||||
read those lines | case 5: case 6: case 7: case:
|
thus the hidden cost of rebuilding column headers w/ every frame
|
||||||
from the LEFT to | cap = Curwin->captab[(int:
|
b while every common field was turned on, not all fields could be
|
||||||
the RIGHT? This | *sub_end = '\0'; :
|
displayed due to limited screen width
|
||||||
"innovation" may | PUTP("%s%.*s%s", cap, roo:
|
c only in a full screen xterm window could all common fields
|
||||||
possibly benefit | room -= (sub_end - sub_be:
|
actually be displayed
|
||||||
those particular | sub_beg = ++sub_end; :
|
|
||||||
kinds of people, | break; :
|
|
||||||
you agree? Duh! | default: :
|
|
||||||
| ++sub_end; :
|
|
||||||
AND, there might | } :
|
|
||||||
even be room for | if (0 >= room) break; :
|
|
||||||
unseen comments! | } /* end: while 'subtrings' */ :
|
|
||||||
+----------------------------------------+
|
|
||||||
|
|
||||||
Gosh, I just don't KNOW -- it's such a TOUGH choice...
|
|
||||||
|
|
||||||
Oh you Stinkin' Tabs: correspondence, Who-Cares; documentation,
|
|
||||||
Oh-Alright; even scripts, Well-If-You-Must. But you have NO place
|
|
||||||
within the code-space of MY C-source listing! So be gone
|
|
||||||
already!!
|
|
||||||
|
|
||||||
In Summation...
|
|
||||||
- If you want to use tabs to the right of the code, go-for-it.
|
|
||||||
But PLEASE, not ever in the C-source code-space, thank-you-
|
|
||||||
kindly. Just use three little ol' spaces (exactly 3, no-more,
|
|
||||||
no-less) where you WOULD have stuck a stinkin' tab.
|
|
||||||
|
|
||||||
We'll get far more READABLE files, much less WAISTED precious
|
|
||||||
horizontal space, more consistent CURSORS and on, and ON, AND
|
|
||||||
ON! Plus, without those awful *the-devil's-own-handiwork*, the
|
|
||||||
aforementioned document need NEVER speak of their EVILS again.
|
|
||||||
|
|
||||||
- Lastly, since SPACES (not stinkin' tabs) are SO beneficial,
|
|
||||||
maybe we should use just a few more of 'em. Some of those C-
|
|
||||||
thingies are VERY sensitive -- they don't like being TOUCHED
|
|
||||||
by any other syntax element! Which ones? Why these guys:
|
|
||||||
|
|
||||||
braces, reserved words and binary operators
|
|
||||||
( it's the TRUTH, they told me themselves )
|
|
||||||
|
|
||||||
It's so EASY to keep 'em HAPPY! And lo-and-behold, the combi-
|
|
||||||
nation of <sp>thingy<sp> turns out to be a darn effective bug
|
|
||||||
repellent, too. So much so, one can actually code while
|
|
||||||
TOTALLY NUDE yet still avoid them ol' bug-bytes (sic-sic)!
|
|
||||||
step
|
|
||||||
down_from
|
|
||||||
me_punctilious
|
|
||||||
soap-box_once_again
|
|
||||||
[1 +5 +5 +5 = huh?]
|
|
||||||
|
|
||||||
|
|
||||||
## 4c. EXAMPLES of Windows ---------------------------------------------##
|
|
||||||
|
|
||||||
-*- The 'A' Mode Command Toggle -*-
|
|
||||||
Here's what you'll see when you first invoke the alternate-display
|
|
||||||
mode interactive command.
|
|
||||||
|
|
||||||
This particular display was produce on a VT100 xterm, with only 24
|
|
||||||
rows. All four task displays are visible, but they could not be sized
|
|
||||||
the same. Available lines are parceled out in the fairest way possi-
|
|
||||||
ble so the last two task displays have an extra line each.
|
|
||||||
|
|
||||||
Notice the 'current' window name in the summary area -- it's been
|
|
||||||
emphasized because the associated task display is visible. Since
|
|
||||||
1:Def has a task area, the full range of interactive commands would be
|
|
||||||
at your disposal. But remember, many of those commands will apply
|
|
||||||
only to window 1:Def.
|
|
||||||
|
|
||||||
+--------------------------------------+
|
|
||||||
1:Def name is bold, |1:Def - 15:46:37 up 16:25, 9 users, :
|
|
||||||
thus all commands |Tasks: 76 total, 1 running, 75 sle:
|
|
||||||
will be available. |Cpu(s): 0.7% user, 1.3% system, :
|
|
||||||
|Mem: 126588k total, 123688k used,:
|
|
||||||
|Swap: 265032k total, 8232k used,:
|
|
||||||
|______________________________________:
|
|
||||||
Tough luck windows |1__PID_USER______PR__NI_%CPU____TIME+_:
|
|
||||||
#1 & 2 - you lost | 7343 jtwm 16 0 0.9 0:00.59:
|
|
||||||
one line each -- | 7339 jtwm 9 0 0.0 0:00.02:
|
|
||||||
guess you'll just |__7337_root_______9___0__0.0___0:01.30:
|
|
||||||
have to learn how |2__PID__PPID_Command____________TIME+_:
|
|
||||||
to live with it. | 997 952 kdeinit 17:59.59:
|
|
||||||
| 1115 952 kdeinit 2:16.47:
|
|
||||||
|__1803__1116_led_______________1:55.30:
|
|
||||||
|3__PID_%MEM__VIRT_SWAP__RES_CODE_DATA_:
|
|
||||||
The #3 & #4 windows | 4634 12.3 15620 0 15m 860 14m :
|
|
||||||
better not gloat | 7337 11.3 14396 92 13m 36 13m :
|
|
||||||
over 1 extra line. | 923 10.6 30524 16m 13m 1120 12m :
|
|
||||||
That user could yet |___991__7.2__9492__316_9176___12_9164_:
|
|
||||||
sock 'em with the |4_UID_USER_____GROUP____TTY________PID:
|
|
||||||
'n' command and | 43 xfs xfs ? 806:
|
|
||||||
take those lines, | 0 ykde users pts/7 5561:
|
|
||||||
plus others, away! | 0 wgnome users pts/7 5560:
|
|
||||||
| 0 root root pts/7 5325:
|
|
||||||
+--------------------------------------+
|
|
||||||
|
|
||||||
So, what say we start applying some of those "full range of interac-
|
|
||||||
tive commands"?
|
|
||||||
|
|
||||||
Onward + Downward...
|
|
||||||
|
|
||||||
-*- STACKIN' & WHACKIN' Windows -*-
|
|
||||||
Whoa, hold on mate. Someone has already whacked these windows. See,
|
|
||||||
there are no task areas for windows 1:Def and 4:Usr. Well, we can at
|
|
||||||
least retrace their steps...
|
|
||||||
|
|
||||||
Here's what was done, after issuing the 'A' command and entering
|
|
||||||
alternate-display mode.
|
|
||||||
1) When #1 was the 'current' window, '-' was pressed,
|
|
||||||
toggling Off the associated task display
|
|
||||||
( if 'l t m' had been applied to its summary, too )
|
|
||||||
( then there'll be only a msg line when 'current' )
|
|
||||||
2) Then the 'w' key was struck to cycle backward,
|
|
||||||
making 4:Usr the 'current' window
|
|
||||||
(could have used 'a a a', if one likes to type)
|
|
||||||
3) Then step #1 was repeated, and bye-bye window #4
|
|
||||||
4) Finally, window #2 was made the 'current' window
|
|
||||||
( Q. how many keystrokes were used? )
|
|
||||||
( A. minimum of 2: 'a a' or 'w w'. )
|
|
||||||
|
|
||||||
+--------------------------------------+
|
|
||||||
No 'l','t','m','1' |2:Top - 15:48:35 up 16:27, 9 users, :
|
|
||||||
commands have been |Tasks: 75 total, 1 running, 74 sle:
|
|
||||||
issued here, |Cpu(s): 2.0% user, 0.7% system, :
|
|
||||||
but... |Mem: 126588k total, 123712k used,:
|
|
||||||
|Swap: 265032k total, 8232k used,:
|
|
||||||
|______________________________________:
|
|
||||||
#2's been changed; |2__PID__PPID_Command____________TIME+_:
|
|
||||||
user applied a 'c' | 997 952 kdeinit: konsol 18:00.70:
|
|
||||||
command (when it | 1115 952 kdeinit: konsol 2:16.47:
|
|
||||||
was current) - now | 1803 1116 led tiptop.HELP 1:55.30:
|
|
||||||
shows cmd lines vs. | 923 922 X :0 1:09.60:
|
|
||||||
program names; | 973 1 klaptopdaemon 0:59.63:
|
|
||||||
still seems to be | 981 952 /usr/bin/artsd 0:48.63:
|
|
||||||
sorted on TIME+ | 987 1 kdeinit: kdeskt 0:24.34:
|
|
||||||
though |___991_____1_kdeinit:_kicker___0:04.59:
|
|
||||||
|3__PID_%MEM__VIRT_SWAP__RES_CODE_DATA_:
|
|
||||||
This #3 guy appears | 4634 12.3 15620 0 15m 860 14m :
|
|
||||||
to still be running | 7337 11.3 14396 92 13m 36 13m :
|
|
||||||
with the supplied | 923 10.6 30544 16m 13m 1120 12m :
|
|
||||||
defaults, but no | 991 7.2 9492 316 9176 12 9164 :
|
|
||||||
telling what damage | 7329 7.0 9036 140 8896 36 8860 :
|
|
||||||
might have been | 1115 6.9 8956 160 8796 36 8760 :
|
|
||||||
done to it's | 987 6.4 8668 524 8144 20 8124 :
|
|
||||||
summary info stuff | 1131 6.4 8268 144 8124 36 8088 :
|
|
||||||
+--------------------------------------+
|
|
||||||
|
|
||||||
And that's what brought us to this current state. No, wait. Oh
|
|
||||||
lordy, will you look at that -- someone has changed the name of win-
|
|
||||||
dow #2 from 'Job' to 'Top'!
|
|
||||||
|
|
||||||
How'd they do that? Well, they just issued the 'g' interactive com-
|
|
||||||
mand, of course. That command is available whenever alternate-display
|
|
||||||
mode is active and always impacts just the 'current' window. Gosh,
|
|
||||||
you can even issue the 'g' command when 'l' has toggled Off the very
|
|
||||||
summary area line containing the window name!
|
|
||||||
|
|
||||||
Almost Done...
|
|
||||||
|
|
||||||
-*- ALL TOGETHER Now, Window(s) -*-
|
|
||||||
Here, the window 1:Def task display has been toggled Off but it
|
|
||||||
remains the 'current' window. Since there is no task area, many com-
|
|
||||||
mands will be restricted. However, the commands ('l', 't', 'm', '1')
|
|
||||||
affecting the summary area, as well as some other global commands
|
|
||||||
('k', 'Z', etc.), would still be active.
|
|
||||||
|
|
||||||
Notice that the Mem and Swap lines are not shown. This means that the
|
|
||||||
loser (oops, user) has, in fact, issued the 'm' command! Now, if you
|
|
||||||
were to cycle the 'current' window with the 'a' or 'w' commands, the
|
|
||||||
task display would remain the same (except possibly growing/shrinking
|
|
||||||
slightly) but the summary area would change periodically.
|
|
||||||
|
|
||||||
The comments to the left of the image provide additional insights into
|
|
||||||
how things came to be. Note especially the comments for window 4:Usr
|
|
||||||
-- the one with some empty rows...
|
|
||||||
|
|
||||||
1:Def no highlight, +--------------------------------------+
|
|
||||||
thus disabled cmds: |1:Def - 15:50:32 up 16:29, 9 users, :
|
|
||||||
b,i,n,u,x,y, etc. |Tasks: 75 total, 2 running, 73 sle:
|
|
||||||
& m = lost Mem/Swap |Cpu(s): 10.6% user, 0.0% system, :
|
|
||||||
|______________________________________:
|
|
||||||
2:Job was very busy: |2__PID__PPID_Command____________TIME+_:
|
|
||||||
'n' cmd, w/ 7 tasks | 80 1 ( khubd ) 0:00.00:
|
|
||||||
'c' cmd, cmd line | 6 0 ( kreclaimd ) 0:00.00:
|
|
||||||
'O' cmd, sort cmd | 9 1 ( mdrecoveryd ) 0:00.00:
|
|
||||||
'R' cmd, sort bkwd | 11358 1 /bin/bash/ /usr 0:00.00:
|
|
||||||
'x' cmd, hi column | 1297 1 /sbin/mingetty 0:00.00:
|
|
||||||
(when 2 WAS current) | 683 1 xinetd -stayali 0:00.00:
|
|
||||||
|___836_____1_login_--_root_____0:00.00:
|
|
||||||
3:Mem has altered |3__PID_%MEM__VIRT_SWAP__RES_CODE_DATA_:
|
|
||||||
some std defaults: | 4634 12.3 15620 0 15m 860 14m :
|
|
||||||
'y' turned Off | 7337 11.3 14396 92 13m 36 13m :
|
|
||||||
'x' turned On | 923 10.6 30544 16m 13m 1120 12m :
|
|
||||||
(when 3 WAS current) | 991 7.2 9492 316 9176 12 9164 :
|
|
||||||
|__7329__7.0__9036__140_8896___36_8860_:
|
|
||||||
Huh? 4:Usr has some |4_UID_USER_____GROUP____TTY________PID:
|
|
||||||
blank rows! ? ? ? ? | 0 jtwm root pts/2 5561:
|
|
||||||
Aha, the 'i' command | 0 root root ? 5560:
|
|
||||||
applied (when 4 WAS | :
|
|
||||||
current); could be | :
|
|
||||||
reversed with '=', | :
|
|
||||||
when 4 IS current! +--------------------------------------+
|
|
||||||
|
|
||||||
Ok now, how about that 'current' window 1:Def and its unseen tasks?
|
|
||||||
At any time, you can quickly retrieve lost tasks in a number of ways:
|
|
||||||
1) Press '-', toggling just the 'current' window
|
|
||||||
2) Press '_', toggling all visible/invisible windows
|
|
||||||
( 1:Def is the only window currently not shown )
|
|
||||||
( afterward, it'll be the only window showing! )
|
|
||||||
* 3) Press '+', forcing all task displays to become visible
|
|
||||||
4) Press 'A' to return to full-screen mode,
|
|
||||||
with only 1:Def tasks shown and without a window name
|
|
||||||
|
|
||||||
Now that should be enough ways of getting a task area visible again to
|
|
||||||
satisfy almost any user, don't ya think?
|
|
||||||
|
|
||||||
Note: Use #3 above when you've messed up your screen beyond
|
|
||||||
redemption. The four task displays will reappear, nice and even.
|
|
||||||
They will also have retained any customizations you had previously
|
|
||||||
applied, except for the 'i' (idle tasks) and 'n' (max tasks) com-
|
|
||||||
mands.
|
|
||||||
|
|
||||||
That's It ! Piece of Cake !! Enjoy them there windows !!!
|
|
||||||
|
|
||||||
|
@ -50,13 +50,6 @@ static int escape_str_utf8(char *restrict dst, const char *restrict src, int buf
|
|||||||
my_cells++;
|
my_cells++;
|
||||||
my_bytes++;
|
my_bytes++;
|
||||||
|
|
||||||
} else if (len==1) {
|
|
||||||
/* non-multibyte */
|
|
||||||
*(dst++) = isprint(*src) ? *src : '?';
|
|
||||||
src++;
|
|
||||||
my_cells++;
|
|
||||||
my_bytes++;
|
|
||||||
|
|
||||||
} else if (!iswprint(wc)) {
|
} else if (!iswprint(wc)) {
|
||||||
/* multibyte - no printable */
|
/* multibyte - no printable */
|
||||||
*(dst++) = '?';
|
*(dst++) = '?';
|
||||||
@ -98,7 +91,7 @@ static int escape_str_utf8(char *restrict dst, const char *restrict src, int buf
|
|||||||
}
|
}
|
||||||
//fprintf(stdout, "cells: %d\n", my_cells);
|
//fprintf(stdout, "cells: %d\n", my_cells);
|
||||||
}
|
}
|
||||||
*(dst++) = '\0';
|
*dst = '\0';
|
||||||
|
|
||||||
// fprintf(stderr, "maxcells: %d, my_cells; %d\n", *maxcells, my_cells);
|
// fprintf(stderr, "maxcells: %d, my_cells; %d\n", *maxcells, my_cells);
|
||||||
|
|
||||||
@ -114,14 +107,14 @@ int escape_str(char *restrict dst, const char *restrict src, int bufsize, int *m
|
|||||||
int my_cells = 0;
|
int my_cells = 0;
|
||||||
int my_bytes = 0;
|
int my_bytes = 0;
|
||||||
const char codes[] =
|
const char codes[] =
|
||||||
"Z-------------------------------"
|
"Z..............................."
|
||||||
"********************************"
|
"||||||||||||||||||||||||||||||||"
|
||||||
"********************************"
|
"||||||||||||||||||||||||||||||||"
|
||||||
"*******************************-"
|
"|||||||||||||||||||||||||||||||."
|
||||||
"--------------------------------"
|
"????????????????????????????????"
|
||||||
"********************************"
|
"????????????????????????????????"
|
||||||
"********************************"
|
"????????????????????????????????"
|
||||||
"********************************";
|
"????????????????????????????????";
|
||||||
|
|
||||||
#if (__GNU_LIBRARY__ >= 6)
|
#if (__GNU_LIBRARY__ >= 6)
|
||||||
static int utf_init=0;
|
static int utf_init=0;
|
||||||
@ -131,9 +124,10 @@ int escape_str(char *restrict dst, const char *restrict src, int bufsize, int *m
|
|||||||
char *enc = nl_langinfo(CODESET);
|
char *enc = nl_langinfo(CODESET);
|
||||||
utf_init = enc && strcasecmp(enc, "UTF-8")==0 ? 1 : -1;
|
utf_init = enc && strcasecmp(enc, "UTF-8")==0 ? 1 : -1;
|
||||||
}
|
}
|
||||||
if (utf_init==1)
|
if (utf_init==1 && MB_CUR_MAX>1) {
|
||||||
/* UTF8 locales */
|
/* UTF8 locales */
|
||||||
return escape_str_utf8(dst, src, bufsize, maxcells);
|
return escape_str_utf8(dst, src, bufsize, maxcells);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(bufsize > *maxcells+1) bufsize=*maxcells+1; // FIXME: assumes 8-bit locale
|
if(bufsize > *maxcells+1) bufsize=*maxcells+1; // FIXME: assumes 8-bit locale
|
||||||
@ -143,12 +137,12 @@ int escape_str(char *restrict dst, const char *restrict src, int bufsize, int *m
|
|||||||
break;
|
break;
|
||||||
c = (unsigned char) *(src++);
|
c = (unsigned char) *(src++);
|
||||||
if(!c) break;
|
if(!c) break;
|
||||||
if(codes[c]=='-') c='?';
|
if(codes[c]!='|') c=codes[c];
|
||||||
my_cells++;
|
my_cells++;
|
||||||
my_bytes++;
|
my_bytes++;
|
||||||
*(dst++) = c;
|
*(dst++) = c;
|
||||||
}
|
}
|
||||||
*(dst++) = '\0';
|
*dst = '\0';
|
||||||
|
|
||||||
*maxcells -= my_cells;
|
*maxcells -= my_cells;
|
||||||
return my_bytes; // bytes of text, excluding the NUL
|
return my_bytes; // bytes of text, excluding the NUL
|
||||||
@ -214,3 +208,16 @@ int escape_command(char *restrict const outbuf, const proc_t *restrict const pp,
|
|||||||
outbuf[end] = '\0';
|
outbuf[end] = '\0';
|
||||||
return end; // bytes, not including the NUL
|
return end; // bytes, not including the NUL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// copy an already 'escaped' string,
|
||||||
|
// using the traditional escape.h calling conventions
|
||||||
|
int escaped_copy(char *restrict dst, const char *restrict src, int bufsize, int *maxroom){
|
||||||
|
int n;
|
||||||
|
if (bufsize > *maxroom+1) bufsize = *maxroom+1;
|
||||||
|
n = snprintf(dst, bufsize, "%s", src);
|
||||||
|
if (n >= bufsize) n = bufsize-1;
|
||||||
|
*maxroom -= n;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
@ -17,6 +17,7 @@ EXTERN_C_BEGIN
|
|||||||
extern int escape_strlist(char *restrict dst, const char *restrict const *restrict src, size_t n, int *cells);
|
extern int escape_strlist(char *restrict dst, const char *restrict const *restrict src, size_t n, int *cells);
|
||||||
extern int escape_str(char *restrict dst, const char *restrict src, int bufsize, int *maxcells);
|
extern int escape_str(char *restrict dst, const char *restrict src, int bufsize, int *maxcells);
|
||||||
extern int escape_command(char *restrict const outbuf, const proc_t *restrict const pp, int bytes, int *cells, unsigned flags);
|
extern int escape_command(char *restrict const outbuf, const proc_t *restrict const pp, int bytes, int *cells, unsigned flags);
|
||||||
|
extern int escaped_copy(char *restrict dst, const char *restrict src, int bufsize, int *maxroom);
|
||||||
|
|
||||||
EXTERN_C_END
|
EXTERN_C_END
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,7 +6,7 @@ global:
|
|||||||
__cyg_profile_func_enter; __cyg_profile_func_exit; main;
|
__cyg_profile_func_enter; __cyg_profile_func_exit; main;
|
||||||
|
|
||||||
readproc; readtask; readproctab; readproctab2; look_up_our_self; escape_command;
|
readproc; readtask; readproctab; readproctab2; look_up_our_self; escape_command;
|
||||||
escape_str; escape_strlist;
|
escape_str; escape_strlist; escaped_copy; read_cmdline;
|
||||||
openproc; closeproc;
|
openproc; closeproc;
|
||||||
tty_to_dev; dev_to_tty; open_psdb_message; open_psdb; lookup_wchan;
|
tty_to_dev; dev_to_tty; open_psdb_message; open_psdb; lookup_wchan;
|
||||||
display_version; procps_version; linux_version_code;
|
display_version; procps_version; linux_version_code;
|
||||||
|
145
proc/readproc.c
145
proc/readproc.c
@ -12,6 +12,7 @@
|
|||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "readproc.h"
|
#include "readproc.h"
|
||||||
#include "alloc.h"
|
#include "alloc.h"
|
||||||
|
#include "escape.h"
|
||||||
#include "pwcache.h"
|
#include "pwcache.h"
|
||||||
#include "devname.h"
|
#include "devname.h"
|
||||||
#include "procps.h"
|
#include "procps.h"
|
||||||
@ -365,6 +366,19 @@ LEAVE(0x220);
|
|||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
#ifdef OOMEM_ENABLE
|
||||||
|
static void oomscore2proc(const char* S, proc_t *restrict P)
|
||||||
|
{
|
||||||
|
sscanf(S, "%d", &P->oom_score);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void oomadj2proc(const char* S, proc_t *restrict P)
|
||||||
|
{
|
||||||
|
sscanf(S, "%d", &P->oom_adj);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
// Reads /proc/*/stat files, being careful not to trip over processes with
|
// Reads /proc/*/stat files, being careful not to trip over processes with
|
||||||
// names like ":-) 1 2 3 4 5 6".
|
// names like ":-) 1 2 3 4 5 6".
|
||||||
@ -514,13 +528,15 @@ static char** file2strvec(const char* directory, const char* what) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// warning: interface may change
|
// this is the former under utilized 'read_cmdline', which has been
|
||||||
int read_cmdline(char *restrict const dst, unsigned sz, unsigned pid){
|
// generalized in support of these new libproc flags:
|
||||||
|
// PROC_EDITCGRPCVT, PROC_EDITCMDLCVT
|
||||||
|
static int read_unvectored(char *restrict const dst, unsigned sz, unsigned pid, const char *what, char sep) {
|
||||||
char name[32];
|
char name[32];
|
||||||
int fd;
|
int fd;
|
||||||
unsigned n = 0;
|
unsigned n = 0;
|
||||||
dst[0] = '\0';
|
|
||||||
snprintf(name, sizeof name, "/proc/%u/cmdline", pid);
|
snprintf(name, sizeof name, "/proc/%u/%s", pid, what);
|
||||||
fd = open(name, O_RDONLY);
|
fd = open(name, O_RDONLY);
|
||||||
if(fd==-1) return 0;
|
if(fd==-1) return 0;
|
||||||
for(;;){
|
for(;;){
|
||||||
@ -530,23 +546,86 @@ int read_cmdline(char *restrict const dst, unsigned sz, unsigned pid){
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
n += r;
|
n += r;
|
||||||
if(n==sz) break; // filled the buffer
|
if(n==sz) { // filled the buffer
|
||||||
|
--n; // make room for '\0'
|
||||||
|
break;
|
||||||
|
}
|
||||||
if(r==0) break; // EOF
|
if(r==0) break; // EOF
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
if(n){
|
if(n){
|
||||||
int i;
|
int i=n;
|
||||||
if(n==sz) n--;
|
while(i--)
|
||||||
dst[n] = '\0';
|
if(dst[i]=='\n' || dst[i]=='\0') dst[i]=sep;
|
||||||
i=n;
|
|
||||||
while(i--){
|
|
||||||
int c = dst[i];
|
|
||||||
if(c<' ' || c>'~') dst[i]=' ';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
dst[n] = '\0';
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char** vectorize_this_str (const char* src) {
|
||||||
|
#define pSZ (sizeof(char*))
|
||||||
|
char *cpy, **vec;
|
||||||
|
int adj, tot;
|
||||||
|
|
||||||
|
tot = strlen(src) + 1; // prep for our vectors
|
||||||
|
adj = (pSZ-1) - ((tot + pSZ-1) & (pSZ-1)); // calc alignment bytes
|
||||||
|
cpy = xcalloc(NULL, tot + adj + (2 * pSZ)); // get new larger buffer
|
||||||
|
snprintf(cpy, tot, "%s", src); // duplicate their string
|
||||||
|
vec = (char**)(cpy + tot + adj); // prep pointer to pointers
|
||||||
|
*vec = cpy; // point 1st vector to string
|
||||||
|
*(vec+1) = NULL; // null ptr 'list' delimit
|
||||||
|
return vec; // ==> free(*vec) to dealloc
|
||||||
|
#undef pSZ
|
||||||
|
}
|
||||||
|
|
||||||
|
// This routine reads /proc/#/cgroup for a single task.
|
||||||
|
// It is similar to file2strvec except we filter and concatenate
|
||||||
|
// the data into a single string represented as a single vector.
|
||||||
|
static void fill_cgroup_cvt (proc_t *restrict p) {
|
||||||
|
#define vMAX ( sizeof(dbuf) - (int)(dst - dbuf) )
|
||||||
|
char sbuf[1024], dbuf[1024];
|
||||||
|
char *src, *dst, *grp, *eob;
|
||||||
|
int tot, x, whackable_int = sizeof(dbuf);
|
||||||
|
|
||||||
|
*(dst = dbuf) = '\0'; // empty destination
|
||||||
|
tot = read_unvectored(sbuf, sizeof(sbuf), p->tid, "cgroup", '\0');
|
||||||
|
for (src = sbuf, eob = sbuf + tot; src < eob; src += x) {
|
||||||
|
x = 1; // loop assist
|
||||||
|
if (!*src) continue;
|
||||||
|
x = strlen((grp = src));
|
||||||
|
if ('/' == grp[x - 1]) continue; // skip empty root cgroups
|
||||||
|
#if 0
|
||||||
|
grp += strspn(grp, "0123456789:"); // jump past group number
|
||||||
|
#endif
|
||||||
|
dst += snprintf(dst, vMAX, "%s", (dst > dbuf) ? "," : "");
|
||||||
|
dst += escape_str(dst, grp, vMAX, &whackable_int);
|
||||||
|
}
|
||||||
|
p->cgroup = vectorize_this_str(dbuf[0] ? dbuf : "-");
|
||||||
|
#undef vMAX
|
||||||
|
}
|
||||||
|
|
||||||
|
// This routine reads /proc/#/cmdline for the designated task, "escapes"
|
||||||
|
// the result into a single string represented as a single vector and
|
||||||
|
// guarantees the caller a valid proc_t.cmdline pointer.
|
||||||
|
static void fill_cmdline_cvt (proc_t *restrict p) {
|
||||||
|
#define uFLG ( ESC_BRACKETS | ESC_DEFUNCT )
|
||||||
|
char sbuf[2048], dbuf[2048];
|
||||||
|
int whackable_int = sizeof(dbuf);
|
||||||
|
|
||||||
|
if (read_unvectored(sbuf, sizeof(sbuf), p->tid, "cmdline", ' '))
|
||||||
|
escape_str(dbuf, sbuf, sizeof(dbuf), &whackable_int);
|
||||||
|
else
|
||||||
|
escape_command(dbuf, p, sizeof(dbuf), &whackable_int, uFLG);
|
||||||
|
p->cmdline = vectorize_this_str(dbuf);
|
||||||
|
#undef uFLG
|
||||||
|
}
|
||||||
|
|
||||||
|
// warning: interface may change
|
||||||
|
int read_cmdline(char *restrict const dst, unsigned sz, unsigned pid) {
|
||||||
|
return read_unvectored(dst, sz, pid, "cmdline", ' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* These are some nice GNU C expression subscope "inline" functions.
|
/* These are some nice GNU C expression subscope "inline" functions.
|
||||||
* The can be used with arbitrary types and evaluate their arguments
|
* The can be used with arbitrary types and evaluate their arguments
|
||||||
* exactly once.
|
* exactly once.
|
||||||
@ -628,21 +707,37 @@ static proc_t* simple_readproc(PROCTAB *restrict const PT, proc_t *restrict cons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & PROC_FILLCOM) || (flags & PROC_FILLARG)) /* read+parse /proc/#/cmdline */
|
if (unlikely(flags & PROC_FILLENV)) /* read /proc/#/environ */
|
||||||
p->cmdline = file2strvec(path, "cmdline");
|
p->environ = file2strvec(path, "environ");
|
||||||
else
|
|
||||||
p->cmdline = NULL;
|
|
||||||
|
|
||||||
if (unlikely(flags & PROC_FILLENV)) /* read+parse /proc/#/environ */
|
|
||||||
p->environ = file2strvec(path, "environ");
|
|
||||||
else
|
else
|
||||||
p->environ = NULL;
|
p->environ = NULL;
|
||||||
|
|
||||||
if(linux_version_code>=LINUX_VERSION(2,6,24) && (flags & PROC_FILLCGROUP))
|
if (flags & (PROC_FILLCOM|PROC_FILLARG)) { /* read /proc/#/cmdline */
|
||||||
p->cgroup = file2strvec(path, "cgroup"); /* read /proc/#/cgroup */
|
if (flags & PROC_EDITCMDLCVT)
|
||||||
else
|
fill_cmdline_cvt(p);
|
||||||
p->cgroup = NULL;
|
else
|
||||||
|
p->cmdline = file2strvec(path, "cmdline");
|
||||||
|
} else
|
||||||
|
p->cmdline = NULL;
|
||||||
|
|
||||||
|
if ((flags & PROC_FILLCGROUP) /* read /proc/#/cgroup, if possible */
|
||||||
|
&& linux_version_code >= LINUX_VERSION(2,6,24)) {
|
||||||
|
if (flags & PROC_EDITCGRPCVT)
|
||||||
|
fill_cgroup_cvt(p);
|
||||||
|
else
|
||||||
|
p->cgroup = file2strvec(path, "cgroup");
|
||||||
|
} else
|
||||||
|
p->cgroup = NULL;
|
||||||
|
|
||||||
|
#ifdef OOMEM_ENABLE
|
||||||
|
if (unlikely(flags & PROC_FILLOOM)) {
|
||||||
|
if (likely( file2str(path, "oom_score", sbuf, sizeof sbuf) != -1 ))
|
||||||
|
oomscore2proc(sbuf, p);
|
||||||
|
if (likely( file2str(path, "oom_adj", sbuf, sizeof sbuf) != -1 ))
|
||||||
|
oomadj2proc(sbuf, p);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
next_proc:
|
next_proc:
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -111,8 +111,9 @@ typedef struct proc_t {
|
|||||||
cmin_flt, // stat cumulative min_flt of process and child processes
|
cmin_flt, // stat cumulative min_flt of process and child processes
|
||||||
cmaj_flt; // stat cumulative maj_flt of process and child processes
|
cmaj_flt; // stat cumulative maj_flt of process and child processes
|
||||||
char
|
char
|
||||||
**environ, // (special) environment string vector (/proc/#/environ)
|
**environ, // (special) environment string vector (/proc/#/environ)
|
||||||
**cmdline; // (special) command line string vector (/proc/#/cmdline)
|
**cmdline, // (special) command line string vector (/proc/#/cmdline)
|
||||||
|
**cgroup; // (special) cgroup string vector (/proc/#/cgroup)
|
||||||
char
|
char
|
||||||
// Be compatible: Digital allows 16 and NT allows 14 ???
|
// Be compatible: Digital allows 16 and NT allows 14 ???
|
||||||
euser[P_G_SZ], // stat(),status effective user name
|
euser[P_G_SZ], // stat(),status effective user name
|
||||||
@ -140,7 +141,11 @@ typedef struct proc_t {
|
|||||||
tpgid, // stat terminal process group id
|
tpgid, // stat terminal process group id
|
||||||
exit_signal, // stat might not be SIGCHLD
|
exit_signal, // stat might not be SIGCHLD
|
||||||
processor; // stat current (or most recent?) CPU
|
processor; // stat current (or most recent?) CPU
|
||||||
char **cgroup; // cgroup current cgroup, looks like a classic filepath
|
#ifdef OOMEM_ENABLE
|
||||||
|
int
|
||||||
|
oom_score, // oom_score (badness for OOM killer)
|
||||||
|
oom_adj; // oom_adj (adjustment to OOM score)
|
||||||
|
#endif
|
||||||
} proc_t;
|
} proc_t;
|
||||||
|
|
||||||
// PROCTAB: data structure holding the persistent information readproc needs
|
// PROCTAB: data structure holding the persistent information readproc needs
|
||||||
@ -239,6 +244,7 @@ extern proc_t * get_proc_stats(pid_t pid, proc_t *p);
|
|||||||
#define PROC_FILLWCHAN 0x0080 // look up WCHAN name
|
#define PROC_FILLWCHAN 0x0080 // look up WCHAN name
|
||||||
#define PROC_FILLARG 0x0100 // alloc and fill in `cmdline'
|
#define PROC_FILLARG 0x0100 // alloc and fill in `cmdline'
|
||||||
#define PROC_FILLCGROUP 0x0200 // alloc and fill in `cgroup`
|
#define PROC_FILLCGROUP 0x0200 // alloc and fill in `cgroup`
|
||||||
|
#define PROC_FILLOOM 0x0400 // alloc and fill in oom_score, oom_adj
|
||||||
|
|
||||||
#define PROC_LOOSE_TASKS 0x2000 // threat threads as if they were processes
|
#define PROC_LOOSE_TASKS 0x2000 // threat threads as if they were processes
|
||||||
|
|
||||||
@ -246,6 +252,9 @@ extern proc_t * get_proc_stats(pid_t pid, proc_t *p);
|
|||||||
#define PROC_PID 0x1000 // process id numbers ( 0 terminated)
|
#define PROC_PID 0x1000 // process id numbers ( 0 terminated)
|
||||||
#define PROC_UID 0x4000 // user id numbers ( length needed )
|
#define PROC_UID 0x4000 // user id numbers ( length needed )
|
||||||
|
|
||||||
|
#define PROC_EDITCGRPCVT 0x10000 // edit `cgroup' as single vector
|
||||||
|
#define PROC_EDITCMDLCVT 0x20000 // edit `cmdline' as single vector
|
||||||
|
|
||||||
// it helps to give app code a few spare bits
|
// it helps to give app code a few spare bits
|
||||||
#define PROC_SPARE_1 0x01000000
|
#define PROC_SPARE_1 0x01000000
|
||||||
#define PROC_SPARE_2 0x02000000
|
#define PROC_SPARE_2 0x02000000
|
||||||
|
@ -24,7 +24,9 @@
|
|||||||
#include <netinet/in.h> /* htons */
|
#include <netinet/in.h> /* htons */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef OOMEM_ENABLE
|
||||||
long smp_num_cpus; /* number of CPUs */
|
long smp_num_cpus; /* number of CPUs */
|
||||||
|
#endif
|
||||||
|
|
||||||
#define BAD_OPEN_MESSAGE \
|
#define BAD_OPEN_MESSAGE \
|
||||||
"Error: /proc must be mounted\n" \
|
"Error: /proc must be mounted\n" \
|
||||||
@ -180,7 +182,11 @@ static void old_Hertz_hack(void){
|
|||||||
setlocale(LC_NUMERIC, savelocale);
|
setlocale(LC_NUMERIC, savelocale);
|
||||||
jiffies = user_j + nice_j + sys_j + other_j;
|
jiffies = user_j + nice_j + sys_j + other_j;
|
||||||
seconds = (up_1 + up_2) / 2;
|
seconds = (up_1 + up_2) / 2;
|
||||||
|
#ifndef OOMEM_ENABLE
|
||||||
h = (unsigned)( (double)jiffies/seconds/smp_num_cpus );
|
h = (unsigned)( (double)jiffies/seconds/smp_num_cpus );
|
||||||
|
#else
|
||||||
|
h = (unsigned)( (double)jiffies/seconds/smp_num_cpus() );
|
||||||
|
#endif
|
||||||
/* actual values used by 2.4 kernels: 32 64 100 128 1000 1024 1200 */
|
/* actual values used by 2.4 kernels: 32 64 100 128 1000 1024 1200 */
|
||||||
switch(h){
|
switch(h){
|
||||||
case 9 ... 11 : Hertz = 10; break; /* S/390 (sometimes) */
|
case 9 ... 11 : Hertz = 10; break; /* S/390 (sometimes) */
|
||||||
@ -246,10 +252,34 @@ static int check_for_privs(void){
|
|||||||
return !!rc;
|
return !!rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef OOMEM_ENABLE
|
||||||
|
long smp_num_cpus(void)
|
||||||
|
{
|
||||||
|
static long _smp_num_cpus=-1; /* number of CPUs */
|
||||||
|
|
||||||
|
if (_smp_num_cpus != -1)
|
||||||
|
return(_smp_num_cpus);
|
||||||
|
|
||||||
|
// ought to count CPUs in /proc/stat instead of relying
|
||||||
|
// on glibc, which foolishly tries to parse /proc/cpuinfo
|
||||||
|
//
|
||||||
|
// SourceForge has an old Alpha running Linux 2.2.20 that
|
||||||
|
// appears to have a non-SMP kernel on a 2-way SMP box.
|
||||||
|
// _SC_NPROCESSORS_CONF returns 2, resulting in HZ=512
|
||||||
|
// _SC_NPROCESSORS_ONLN returns 1, which should work OK
|
||||||
|
|
||||||
|
_smp_num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
|
if(_smp_num_cpus<1) _smp_num_cpus=1; /* SPARC glibc is buggy */
|
||||||
|
|
||||||
|
return(_smp_num_cpus);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void init_libproc(void) __attribute__((constructor));
|
static void init_libproc(void) __attribute__((constructor));
|
||||||
static void init_libproc(void){
|
static void init_libproc(void){
|
||||||
have_privs = check_for_privs();
|
have_privs = check_for_privs();
|
||||||
init_Linux_version(); /* Must be called before we check code */
|
init_Linux_version(); /* Must be called before we check code */
|
||||||
|
#ifndef OOMEM_ENABLE
|
||||||
// ought to count CPUs in /proc/stat instead of relying
|
// ought to count CPUs in /proc/stat instead of relying
|
||||||
// on glibc, which foolishly tries to parse /proc/cpuinfo
|
// on glibc, which foolishly tries to parse /proc/cpuinfo
|
||||||
//
|
//
|
||||||
@ -259,7 +289,7 @@ static void init_libproc(void){
|
|||||||
// _SC_NPROCESSORS_ONLN returns 1, which should work OK
|
// _SC_NPROCESSORS_ONLN returns 1, which should work OK
|
||||||
smp_num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
|
smp_num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
if(smp_num_cpus<1) smp_num_cpus=1; /* SPARC glibc is buggy */
|
if(smp_num_cpus<1) smp_num_cpus=1; /* SPARC glibc is buggy */
|
||||||
|
#endif
|
||||||
if(linux_version_code > LINUX_VERSION(2, 4, 0)){
|
if(linux_version_code > LINUX_VERSION(2, 4, 0)){
|
||||||
Hertz = find_elf_note(AT_CLKTCK);
|
Hertz = find_elf_note(AT_CLKTCK);
|
||||||
if(Hertz!=NOTE_NOT_FOUND) return;
|
if(Hertz!=NOTE_NOT_FOUND) return;
|
||||||
|
@ -7,7 +7,11 @@
|
|||||||
EXTERN_C_BEGIN
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
extern unsigned long long Hertz; /* clock tick frequency */
|
extern unsigned long long Hertz; /* clock tick frequency */
|
||||||
|
#ifndef OOMEM_ENABLE
|
||||||
extern long smp_num_cpus; /* number of CPUs */
|
extern long smp_num_cpus; /* number of CPUs */
|
||||||
|
#else
|
||||||
|
extern long smp_num_cpus(void); /* number of CPUs */
|
||||||
|
#endif
|
||||||
extern int have_privs; /* boolean, true if setuid or similar */
|
extern int have_privs; /* boolean, true if setuid or similar */
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -224,6 +224,7 @@ static unsigned task_format_needs;
|
|||||||
#define needs_for_format (proc_format_needs|task_format_needs)
|
#define needs_for_format (proc_format_needs|task_format_needs)
|
||||||
|
|
||||||
#define PROC_ONLY_FLAGS (PROC_FILLENV|PROC_FILLARG|PROC_FILLCOM|PROC_FILLMEM|PROC_FILLCGROUP)
|
#define PROC_ONLY_FLAGS (PROC_FILLENV|PROC_FILLARG|PROC_FILLCOM|PROC_FILLMEM|PROC_FILLCGROUP)
|
||||||
|
|
||||||
/***** munge lists and determine openproc() flags */
|
/***** munge lists and determine openproc() flags */
|
||||||
static void lists_and_needs(void){
|
static void lists_and_needs(void){
|
||||||
check_headers();
|
check_headers();
|
||||||
@ -283,11 +284,12 @@ static void lists_and_needs(void){
|
|||||||
}
|
}
|
||||||
if(!unix_f_option){
|
if(!unix_f_option){
|
||||||
proc_format_needs &= ~PROC_FILLCOM;
|
proc_format_needs &= ~PROC_FILLCOM;
|
||||||
|
proc_format_needs |= PROC_EDITCMDLCVT;
|
||||||
needs_for_sort &= ~PROC_FILLCOM;
|
needs_for_sort &= ~PROC_FILLCOM;
|
||||||
}
|
}
|
||||||
// convert ARG to COM as a standard
|
// convert ARG to COM as a standard
|
||||||
if(proc_format_needs & PROC_FILLARG){
|
if(proc_format_needs & PROC_FILLARG){
|
||||||
proc_format_needs |= PROC_FILLCOM;
|
proc_format_needs |= (PROC_FILLCOM | PROC_EDITCMDLCVT);
|
||||||
proc_format_needs &= ~PROC_FILLARG;
|
proc_format_needs &= ~PROC_FILLARG;
|
||||||
}
|
}
|
||||||
if(bsd_e_option){
|
if(bsd_e_option){
|
||||||
|
95
ps/output.c
95
ps/output.c
@ -331,8 +331,11 @@ Modifications to the arguments are not shown.
|
|||||||
|
|
||||||
// FIXME: some of these may hit the guard page in forest mode
|
// FIXME: some of these may hit the guard page in forest mode
|
||||||
|
|
||||||
/* "command" is the same thing: long unless c */
|
/*
|
||||||
static int pr_args(char *restrict const outbuf, const proc_t *restrict const pp){
|
* "args", "cmd", "command" are all the same: long unless c
|
||||||
|
* "comm", "ucmd", "ucomm" are all the same: short unless -f
|
||||||
|
* ( determinations are made in display.c, we just deal with results ) */
|
||||||
|
static int pr_argcom(char *restrict const outbuf, const proc_t *restrict const pp){
|
||||||
char *endp = outbuf;
|
char *endp = outbuf;
|
||||||
unsigned flags;
|
unsigned flags;
|
||||||
int rightward=max_rightward;
|
int rightward=max_rightward;
|
||||||
@ -342,84 +345,30 @@ static int pr_args(char *restrict const outbuf, const proc_t *restrict const pp)
|
|||||||
endp += fh;
|
endp += fh;
|
||||||
rightward -= fh;
|
rightward -= fh;
|
||||||
}
|
}
|
||||||
if(bsd_c_option) flags = ESC_DEFUNCT;
|
if(pp->cmdline)
|
||||||
else flags = ESC_DEFUNCT | ESC_BRACKETS | ESC_ARGS;
|
endp += escaped_copy(endp, *pp->cmdline, OUTBUF_SIZE, &rightward);
|
||||||
endp += escape_command(endp, pp, OUTBUF_SIZE, &rightward, flags);
|
else
|
||||||
|
endp += escape_command(endp, pp, OUTBUF_SIZE, &rightward, ESC_DEFUNCT);
|
||||||
|
|
||||||
if(bsd_e_option && rightward>1){
|
if(bsd_e_option && rightward>1) {
|
||||||
const char **env = (const char**)pp->environ;
|
if(pp->environ && *pp->environ)
|
||||||
if(env && *env){
|
endp += escape_strlist(endp, pp->environ, OUTBUF_SIZE, &rightward);
|
||||||
*endp++ = ' ';
|
|
||||||
rightward--;
|
|
||||||
endp += escape_strlist(endp, env, OUTBUF_SIZE, &rightward);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//return endp - outbuf;
|
//return endp - outbuf;
|
||||||
return max_rightward-rightward;
|
return max_rightward-rightward;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pr_cgroup(char *restrict const outbuf,const proc_t *restrict const pp) {
|
static int pr_cgroup(char *restrict const outbuf,const proc_t *restrict const pp) {
|
||||||
char *endp = outbuf;
|
|
||||||
int rightward = max_rightward;
|
int rightward = max_rightward;
|
||||||
|
|
||||||
if(pp->cgroup) {
|
if(pp->cgroup) {
|
||||||
char **pcgroup = pp->cgroup;
|
escaped_copy(outbuf, *pp->cgroup, OUTBUF_SIZE, &rightward);
|
||||||
|
return max_rightward-rightward;
|
||||||
while(*pcgroup != NULL) {
|
|
||||||
//Skip root cgroups
|
|
||||||
if(!**pcgroup || (*pcgroup)[strlen(*pcgroup)-1] == '/') {
|
|
||||||
pcgroup++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Skip initial cgroup number
|
|
||||||
char *ccgroup = strchr(*pcgroup, ':');
|
|
||||||
if(ccgroup == NULL)
|
|
||||||
ccgroup = *pcgroup;
|
|
||||||
else
|
|
||||||
ccgroup++;
|
|
||||||
|
|
||||||
if(endp != outbuf)
|
|
||||||
endp += escape_str(endp, ";", OUTBUF_SIZE, &rightward);
|
|
||||||
|
|
||||||
endp += escape_str(endp, ccgroup, OUTBUF_SIZE, &rightward);
|
|
||||||
|
|
||||||
pcgroup++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if(endp == outbuf)
|
|
||||||
return pr_nop(outbuf,pp);
|
return pr_nop(outbuf,pp);
|
||||||
|
|
||||||
return (int)(endp-outbuf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* "ucomm" is the same thing: short unless -f */
|
|
||||||
static int pr_comm(char *restrict const outbuf, const proc_t *restrict const pp){
|
|
||||||
char *endp = outbuf;
|
|
||||||
unsigned flags;
|
|
||||||
int rightward=max_rightward;
|
|
||||||
|
|
||||||
if(forest_prefix){
|
|
||||||
int fh = forest_helper(outbuf);
|
|
||||||
endp += fh;
|
|
||||||
rightward -= fh;
|
|
||||||
}
|
|
||||||
if(unix_f_option) flags = ESC_DEFUNCT | ESC_BRACKETS | ESC_ARGS;
|
|
||||||
else flags = ESC_DEFUNCT;
|
|
||||||
endp += escape_command(endp, pp, OUTBUF_SIZE, &rightward, flags);
|
|
||||||
|
|
||||||
if(bsd_e_option && rightward>1){
|
|
||||||
const char **env = (const char**)pp->environ;
|
|
||||||
if(env && *env){
|
|
||||||
*endp++ = ' ';
|
|
||||||
rightward--;
|
|
||||||
endp += escape_strlist(endp, env, OUTBUF_SIZE, &rightward);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//return endp - outbuf;
|
|
||||||
return max_rightward-rightward;
|
|
||||||
}
|
|
||||||
/* Non-standard, from SunOS 5 */
|
/* Non-standard, from SunOS 5 */
|
||||||
static int pr_fname(char *restrict const outbuf, const proc_t *restrict const pp){
|
static int pr_fname(char *restrict const outbuf, const proc_t *restrict const pp){
|
||||||
char *endp = outbuf;
|
char *endp = outbuf;
|
||||||
@ -1292,7 +1241,7 @@ static int pr_t_left2(char *restrict const outbuf, const proc_t *restrict const
|
|||||||
#define GRP PROC_FILLGRP /* gid_t -> group names */
|
#define GRP PROC_FILLGRP /* gid_t -> group names */
|
||||||
#define WCH PROC_FILLWCHAN /* do WCHAN lookup */
|
#define WCH PROC_FILLWCHAN /* do WCHAN lookup */
|
||||||
|
|
||||||
#define CGRP PROC_FILLCGROUP /* read cgroup */
|
#define CGRP PROC_FILLCGROUP | PROC_EDITCGRPCVT /* read cgroup */
|
||||||
/* TODO
|
/* TODO
|
||||||
* pull out annoying BSD aliases into another table (to macro table?)
|
* pull out annoying BSD aliases into another table (to macro table?)
|
||||||
* add sorting functions here (to unify names)
|
* add sorting functions here (to unify names)
|
||||||
@ -1320,7 +1269,7 @@ static const format_struct format_array[] = {
|
|||||||
{"addr_1", "ADDR", pr_nop, sr_nop, 1, 0, LNX, AN|LEFT},
|
{"addr_1", "ADDR", pr_nop, sr_nop, 1, 0, LNX, AN|LEFT},
|
||||||
{"alarm", "ALARM", pr_alarm, sr_alarm, 5, 0, LNX, AN|RIGHT},
|
{"alarm", "ALARM", pr_alarm, sr_alarm, 5, 0, LNX, AN|RIGHT},
|
||||||
{"argc", "ARGC", pr_nop, sr_nop, 4, 0, LNX, PO|RIGHT},
|
{"argc", "ARGC", pr_nop, sr_nop, 4, 0, LNX, PO|RIGHT},
|
||||||
{"args", "COMMAND", pr_args, sr_cmd, 27, ARG, U98, PO|UNLIMITED}, /*command*/
|
{"args", "COMMAND", pr_argcom, sr_cmd, 27, ARG, U98, PO|UNLIMITED}, /*command*/
|
||||||
{"atime", "TIME", pr_time, sr_nop, 8, 0, SOE, ET|RIGHT}, /*cputime*/ /* was 6 wide */
|
{"atime", "TIME", pr_time, sr_nop, 8, 0, SOE, ET|RIGHT}, /*cputime*/ /* was 6 wide */
|
||||||
{"blocked", "BLOCKED", pr_sigmask, sr_nop, 9, 0, BSD, TO|SIGNAL}, /*sigmask*/
|
{"blocked", "BLOCKED", pr_sigmask, sr_nop, 9, 0, BSD, TO|SIGNAL}, /*sigmask*/
|
||||||
{"bnd", "BND", pr_nop, sr_nop, 1, 0, AIX, TO|RIGHT},
|
{"bnd", "BND", pr_nop, sr_nop, 1, 0, AIX, TO|RIGHT},
|
||||||
@ -1332,11 +1281,11 @@ static const format_struct format_array[] = {
|
|||||||
{"class", "CLS", pr_class, sr_sched, 3, 0, XXX, TO|LEFT},
|
{"class", "CLS", pr_class, sr_sched, 3, 0, XXX, TO|LEFT},
|
||||||
{"cls", "CLS", pr_class, sr_sched, 3, 0, HPU, TO|RIGHT}, /*says HPUX or RT*/
|
{"cls", "CLS", pr_class, sr_sched, 3, 0, HPU, TO|RIGHT}, /*says HPUX or RT*/
|
||||||
{"cmaj_flt", "-", pr_nop, sr_cmaj_flt, 1, 0, LNX, AN|RIGHT},
|
{"cmaj_flt", "-", pr_nop, sr_cmaj_flt, 1, 0, LNX, AN|RIGHT},
|
||||||
{"cmd", "CMD", pr_args, sr_cmd, 27, ARG, DEC, PO|UNLIMITED}, /*ucomm*/
|
{"cmd", "CMD", pr_argcom, sr_cmd, 27, ARG, DEC, PO|UNLIMITED}, /*ucomm*/
|
||||||
{"cmin_flt", "-", pr_nop, sr_cmin_flt, 1, 0, LNX, AN|RIGHT},
|
{"cmin_flt", "-", pr_nop, sr_cmin_flt, 1, 0, LNX, AN|RIGHT},
|
||||||
{"cnswap", "-", pr_nop, sr_nop, 1, 0, LNX, AN|RIGHT},
|
{"cnswap", "-", pr_nop, sr_nop, 1, 0, LNX, AN|RIGHT},
|
||||||
{"comm", "COMMAND", pr_comm, sr_cmd, 15, COM, U98, PO|UNLIMITED}, /*ucomm*/
|
{"comm", "COMMAND", pr_argcom, sr_cmd, 15, COM, U98, PO|UNLIMITED}, /*ucomm*/
|
||||||
{"command", "COMMAND", pr_args, sr_cmd, 27, ARG, XXX, PO|UNLIMITED}, /*args*/
|
{"command", "COMMAND", pr_argcom, sr_cmd, 27, ARG, XXX, PO|UNLIMITED}, /*args*/
|
||||||
{"context", "CONTEXT", pr_context, sr_nop, 31, 0, LNX, ET|LEFT},
|
{"context", "CONTEXT", pr_context, sr_nop, 31, 0, LNX, ET|LEFT},
|
||||||
{"cp", "CP", pr_cp, sr_pcpu, 3, 0, DEC, ET|RIGHT}, /*cpu*/
|
{"cp", "CP", pr_cp, sr_pcpu, 3, 0, DEC, ET|RIGHT}, /*cpu*/
|
||||||
{"cpu", "CPU", pr_nop, sr_nop, 3, 0, BSD, AN|RIGHT}, /* FIXME ... HP-UX wants this as the CPU number for SMP? */
|
{"cpu", "CPU", pr_nop, sr_nop, 3, 0, BSD, AN|RIGHT}, /* FIXME ... HP-UX wants this as the CPU number for SMP? */
|
||||||
@ -1516,8 +1465,8 @@ static const format_struct format_array[] = {
|
|||||||
{"tty4", "TTY", pr_tty4, sr_tty, 4, 0, LNX, PO|LEFT},
|
{"tty4", "TTY", pr_tty4, sr_tty, 4, 0, LNX, PO|LEFT},
|
||||||
{"tty8", "TTY", pr_tty8, sr_tty, 8, 0, LNX, PO|LEFT},
|
{"tty8", "TTY", pr_tty8, sr_tty, 8, 0, LNX, PO|LEFT},
|
||||||
{"u_procp", "UPROCP", pr_nop, sr_nop, 6, 0, DEC, AN|RIGHT},
|
{"u_procp", "UPROCP", pr_nop, sr_nop, 6, 0, DEC, AN|RIGHT},
|
||||||
{"ucmd", "CMD", pr_comm, sr_cmd, 15, COM, DEC, PO|UNLIMITED}, /*ucomm*/
|
{"ucmd", "CMD", pr_argcom, sr_cmd, 15, COM, DEC, PO|UNLIMITED}, /*ucomm*/
|
||||||
{"ucomm", "COMMAND", pr_comm, sr_cmd, 15, COM, XXX, PO|UNLIMITED}, /*comm*/
|
{"ucomm", "COMMAND", pr_argcom, sr_cmd, 15, COM, XXX, PO|UNLIMITED}, /*comm*/
|
||||||
{"uid", "UID", pr_euid, sr_euid, 5, 0, XXX, ET|RIGHT},
|
{"uid", "UID", pr_euid, sr_euid, 5, 0, XXX, ET|RIGHT},
|
||||||
{"uid_hack", "UID", pr_euser, sr_euser, 8, USR, XXX, ET|USER},
|
{"uid_hack", "UID", pr_euser, sr_euser, 8, USR, XXX, ET|USER},
|
||||||
{"umask", "UMASK", pr_nop, sr_nop, 5, 0, DEC, AN|RIGHT},
|
{"umask", "UMASK", pr_nop, sr_nop, 5, 0, DEC, AN|RIGHT},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user