diff options
Diffstat (limited to 'toys')
-rw-r--r-- | toys/posix/ps.c | 62 |
1 files changed, 35 insertions, 27 deletions
diff --git a/toys/posix/ps.c b/toys/posix/ps.c index f5e080c7..fef9c908 100644 --- a/toys/posix/ps.c +++ b/toys/posix/ps.c @@ -234,7 +234,7 @@ struct ofields { * struct procpid contains a slot[] array of 64 bit values, with the following * data at each position in the array. Most is read from /proc/$PID/stat (see * https://kernel.org/doc/Documentation/filesystems/proc.txt table 1-4) but - * we we replace several fields with don't use with other data. */ + * we replace several fields with don't use with other data. */ enum { SLOT_pid, /*process id*/ SLOT_ppid, // parent process id @@ -297,7 +297,7 @@ struct procpid { * get the overflow back). * * slot: which slot[] out of procpid. Negative means it's a string field. - * Setting bit |64 requests extra display/sort processing. + * value|XX requests extra display/sort processing. * * The TAGGED_ARRAY plumbing produces an enum of indexes, the "tag" is the * first string argument and the prefix is the first argument to TAGGED_ARRAY @@ -308,8 +308,9 @@ struct procpid { * if (TT.bits & _PS_NAME) printf("-o included PS_NAME"); */ +#define XX 64 // force string representation for sorting, etc + // TODO: Android uses -30 for LABEL, but ideally it would auto-size. -// 64|slot means compare as string when sorting struct typography { char *name, *help; signed char width, slot; @@ -349,13 +350,13 @@ struct typography { // user/group (may call getpwuid() or similar) {"UID", "User id", 5, SLOT_uid}, - {"USER", "User name", -12, 64|SLOT_uid}, + {"USER", "User name", -12, XX|SLOT_uid}, {"RUID", "Real (before suid) user ID", 4, SLOT_ruid}, - {"RUSER", "Real (before suid) user name", -8, 64|SLOT_ruid}, + {"RUSER", "Real (before suid) user name", -8, XX|SLOT_ruid}, {"GID", "Group ID", 8, SLOT_gid}, - {"GROUP", "Group name", -8, 64|SLOT_gid}, + {"GROUP", "Group name", -8, XX|SLOT_gid}, {"RGID", "Real (before sgid) Group ID", 4, SLOT_rgid}, - {"RGROUP", "Real (before sgid) group name", -8, 64|SLOT_rgid}, + {"RGROUP", "Real (before sgid) group name", -8, XX|SLOT_rgid}, // clock displays (00:00:00) {"TIME", "CPU time consumed", 8, SLOT_utime}, @@ -382,20 +383,19 @@ struct typography { // Misc (special cases) {"STIME", "Start time (ISO 8601)", 5, SLOT_starttime}, - {"F", "Flags 1=FORKNOEXEC 4=SUPERPRIV", 1, 64|SLOT_flags}, + {"F", "Flags 1=FORKNOEXEC 4=SUPERPRIV", 1, XX|SLOT_flags}, {"S", "Process state:\n" "\t R (running) S (sleeping) D (device I/O) T (stopped) t (traced)\n" "\t Z (zombie) X (deader) x (dead) K (wakekill) W (waking)", - -1, 64}, + -1, XX}, {"STAT", "Process state (S) plus:\n" "\t < high priority N low priority L locked memory\n" "\t s session leader + foreground l multithreaded", - -5, 64}, - {"PCY", "Android scheduling policy", 3, 64|SLOT_pcy}, + -5, XX}, + {"PCY", "Android scheduling policy", 3, XX|SLOT_pcy}, ); // Show sorted "-o help" text for fields listed in toybuf[len] - static void help_fields(int len, int multi) { int i, j, k, left = 0; @@ -429,7 +429,7 @@ static void help_fields(int len, int multi) if (!multi && left) xputc('\n'); } -// Print help text for all -o field, with categories. +// Print help text for each -o field, with categories. static void help_help(void) { int i, jump = PS_CMD+1-PS_COMM; @@ -454,7 +454,7 @@ static void help_help(void) xexit(); } -// Return 0 to discard, nonzero to keep +// process match filter for top/ps/pgrep: Return 0 to discard, nonzero to keep static int shared_match_process(long long *slot) { struct ptr_len match[] = { @@ -478,8 +478,7 @@ static int shared_match_process(long long *slot) return ll ? 0 : -1; } - -// Return 0 to discard, nonzero to keep +// process match filter for ps: Return 0 to discard, nonzero to keep static int ps_match_process(long long *slot) { int i = shared_match_process(slot); @@ -497,12 +496,12 @@ static int ps_match_process(long long *slot) return 1; } -// Convert field to string representation +// Generate display string (260 bytes at end of toybuf) from struct ofield static char *string_field(struct procpid *tb, struct ofields *field) { char *buf = toybuf+sizeof(toybuf)-260, *out = buf, *s; int which = field->which, sl = typos[which].slot; - long long *slot = tb->slot, ll = (sl >= 0) ? slot[sl&63] : 0; + long long *slot = tb->slot, ll = (sl >= 0) ? slot[sl&(XX-1)] : 0; // numbers, mostly from /proc/$PID/stat if (which <= PS_BIT) { @@ -536,7 +535,7 @@ static char *string_field(struct procpid *tb, struct ofields *field) // user/group } else if (which <= PS_RGROUP) { sprintf(out, "%lld", ll); - if (sl&64) { + if (sl&XX) { if (which > PS_RUSER) { struct group *gr = bufgetgrgid(ll); @@ -576,7 +575,7 @@ static char *string_field(struct procpid *tb, struct ofields *field) // Percentage displays } else if (which <= PS__CPU) { - ll = slot[sl&63]*1000; + ll = slot[sl&(XX-1)]*1000; if (which==PS__VSZ || which==PS__MEM) ll /= slot[SLOT_totalram]/((which==PS__VSZ) ? 1024 : 4096); else if (slot[SLOT_upticks]) ll /= slot[SLOT_upticks]; @@ -624,7 +623,7 @@ static char *string_field(struct procpid *tb, struct ofields *field) return out; } -// Display process data that get_ps() read from /proc, formatting with TT.fields +// Display process data that get_ps() read from /proc, formatting via TT.fields static void show_ps(void *p) { struct procpid *tb = p; @@ -687,7 +686,7 @@ static void show_ps(void *p) putchar(TT.time ? '\r' : '\n'); } -// dirtree callback: read data about process, then display or store it. +// dirtree callback: read data about a process, then display or store it. // Fills toybuf with struct procpid and either DIRTREE_SAVEs a copy to ->extra // (in -k mode) or calls show_ps directly on toybuf (for low memory systems). static int get_ps(struct dirtree *new) @@ -982,6 +981,7 @@ static int get_ps(struct dirtree *new) return DIRTREE_SAVE; } +// wrapper for get_ps() that also collects threads under each processes static int get_threads(struct dirtree *new) { struct dirtree *dt; @@ -1033,6 +1033,7 @@ static int get_threads(struct dirtree *new) return 0; } +// Parse one FIELD argument (with optional =name :width) into struct ofields static char *parse_ko(void *data, char *type, int length) { struct ofields *field; @@ -1100,6 +1101,8 @@ static char *parse_ko(void *data, char *type, int length) return 0; } +// Write FIELD list into display header string (truncating at blen), +// and return bitfield of which FIELDs are used. static long long get_headers(struct ofields *field, char *buf, int blen) { long long bits = 0; @@ -1114,7 +1117,7 @@ static long long get_headers(struct ofields *field, char *buf, int blen) return bits; } -// Parse -p -s -t -u -U -g -G +// Parse command line options -p -s -t -u -U -g -G static char *parse_rest(void *data, char *str, int len) { struct ptr_len *pl = (struct ptr_len *)data; @@ -1192,7 +1195,7 @@ static char *parse_rest(void *data, char *str, int len) return str; } -// sort for -k +// sort processes by FIELD(s) listed in option -k static int ksort(void *aa, void *bb) { struct ofields *field; @@ -1203,7 +1206,7 @@ static int ksort(void *aa, void *bb) slot = typos[field->which].slot; // Can we do numeric sort? - if (!(slot&64)) { + if (!(slot&XX)) { if (ta->slot[slot]<tb->slot[slot]) ret = -1; if (ta->slot[slot]>tb->slot[slot]) ret = 1; } @@ -1220,6 +1223,8 @@ static int ksort(void *aa, void *bb) return ret; } +// Collect ->extra field from leaf nodes DIRTREE_SAVEd by get_ps() into array +// (recursion because tree from get_thread() isn't flat list of siblings) static struct procpid **collate_leaves(struct procpid **tb, struct dirtree *dt) { while (dt) { @@ -1234,6 +1239,8 @@ static struct procpid **collate_leaves(struct procpid **tb, struct dirtree *dt) return tb; } +// Allocate struct procpid array of length count and populate it with ->extra +// fields from dirtree leaf nodes. (top diffs old & new array to show changes) static struct procpid **collate(int count, struct dirtree *dt) { struct procpid **tbsort = xmalloc(count*sizeof(struct procpid *)); @@ -1243,6 +1250,7 @@ static struct procpid **collate(int count, struct dirtree *dt) return tbsort; } +// parse command line arguments (ala -k -o) with a comma separated FIELD list static void default_ko(char *s, void *fields, char *err, struct arg_list *arg) { struct arg_list def; @@ -1320,7 +1328,7 @@ void ps_main(void) for (field = TT.fields; field; field = field->next) { if (FLAG(n) && field->which>=PS_UID - && field->which<=PS_RGROUP && (typos[field->which].slot&64)) + && field->which<=PS_RGROUP && (typos[field->which].slot&XX)) field->which--; } } @@ -1585,7 +1593,7 @@ static void top_common( pos = stpcpy(toybuf, "Totals:"); for (field = TT.fields; field; field = field->next) { long long ll, bits = 0; - int slot = typos[field->which].slot&63; + int slot = typos[field->which].slot&(XX-1); if (field->which<PS_C || field->which>PS_DIO) continue; ll = 1LL<<field->which; |