diff options
Diffstat (limited to 'toys/pending/ps.c')
-rw-r--r-- | toys/pending/ps.c | 101 |
1 files changed, 66 insertions, 35 deletions
diff --git a/toys/pending/ps.c b/toys/pending/ps.c index 43818ee8..22cf9beb 100644 --- a/toys/pending/ps.c +++ b/toys/pending/ps.c @@ -6,9 +6,9 @@ * And http://kernel.org/doc/Documentation/filesystems/proc.txt Table 1-4 * And linux kernel source fs/proc/array.c function do_task_stat() * - * Deviation from posix: no -n + * Deviation from posix: no -n, "-o tty" called "TTY" not "TT", -USE_PS(NEWTOY(ps, "aAdeo*", TOYFLAG_USR|TOYFLAG_BIN)) +USE_PS(NEWTOY(ps, "aAdeflo*", TOYFLAG_USR|TOYFLAG_BIN)) config PS bool "ps" @@ -22,12 +22,11 @@ config PS -a Processes with terminals, except session leaders -d Processes that aren't session leaders -e Same as -A - - -f Full listing + -l Long listing + -g Processes belonging to these session leaders -G Processes with these real group IDs - -l Long listing -o Show FIELDS for each process -p select by PID -t select by TTY @@ -56,7 +55,7 @@ GLOBALS( unsigned width; dev_t tty; - void *oo; + void *fields; ) /* @@ -68,18 +67,23 @@ GLOBALS( man page: F flags mean... */ +struct strawberry { + struct strawberry *next, *prev; + short which, len; + char title[]; +}; + // dirtree callback. // toybuf used as: 1024 /proc/$PID/stat, 1024 slot[], 2048 /proc/$PID/cmdline static int do_ps(struct dirtree *new) { + struct strawberry *fields; long long *slot = (void *)(toybuf+1024); char *name, *s, state; - int nlen, slots, i, field, width = TT.width, idxes[] = {0, -1, -2, -3}; + int nlen, slots, i, width = TT.width, idxes[] = {0, -1, -2, -3}; struct passwd *pw; struct group *gr; -width=18; - if (!new->parent) return DIRTREE_RECURSE; if (!(*slot = atol(new->name))) return 0; @@ -104,40 +108,49 @@ width=18; if (!(toys.optflags*(FLAG_a|FLAG_d|FLAG_A|FLAG_e)) && TT.tty!=slot[4]) return 0; - // default: pidi=1 user time args + // 0 "F", "S", "UID", "PID", "PPID", "C", "PRI", + // 7 "NI", "ADDR", "SZ", "WCHAN", "STIME", "TTY", "TIME", "CMD", + //15 "COMMAND", "ELAPSED", "GROUP", "%CPU", "PGID", "RGROUP", + //21 "RUSER", "USER", "VSZ" - for (field = 0; field<ARRAY_LEN(idxes); field++) { + for (fields = TT.fields; field = 0; field<ARRAY_LEN(idxes); field++) { char *out = toybuf+2048; - int idx = idxes[field]; - // Default: unsupported - sprintf(out, "-"); + i = fields->which; - // Our tests here are in octal to match \123 character escapes in typos[] + unsigned idx = idxes[field]; - // Print a raw stat field? - if (idx<0300) - sprintf(out, (char *[]){"%lld","%llx","%llo"}[idx>>6], slot[idx&63]); + // Default: unsupported + sprintf(out, "-"); - else if (idx == 0300) sprintf(out, "%c", state); // S - else if (idx == 0301 || idx == 0302) { // UID and USER + // does strchr() find NUL if you look for it? No idea, test that first. + // F + if (!fields->which) sprintf(out, "%llo", slot[7]); + // PID, PPID, PRI, NI, ADDR, SZ + else if (-1 != (i = stridx((char[]){3,4,6,7,8,9}, fields->which) + sprintf(out, ((1<<i)&0x10) ? "%llx" : "%lld", + slot[((char[]){0,2,16,17,22})[i]]>>(((1<<i)&0x20) ? 12 : 0)); + // S + else if ((i = fields->which) == 1) + sprintf(out, "%c", state); + else if (i == 2 || i == 22) { // UID and USER sprintf(out, "%d", new->st.st_uid); - if (idx == 302 || (toys.optflags&FLAG_f)) { + if (i == 2 || (toys.optflags&FLAG_f)) { struct passwd *pw = getpwuid(new->st.st_uid); if (pw) out = pw->pw_name; } - } else if (idx == 0303); // C (unsupported for now) - else if (idx == 0304) // SZ - sprintf(out, "%lld", slot[22]/4096); - else if (idx == 0305) { // WCHAN - sprintf(toybuf+512, "%lld/wchan"); + // C (unsupported for now) +// else if (idx == 5); + // WCHAN + } else if (idx == 10) { // WCHAN + sprintf(toybuf+512, "%lld/wchan", *slot); readfileat(dirtree_parentfd(new), toybuf+512, out, 2047); + // SZ - // time - } else if (idx == -2) { - long seconds = (slot[11]+(idx==-3)*slot[12])/sysconf(_SC_CLK_TCK), - ll = 60*60*24; + // STIME and TIME + } else if (idx == 13) { + long seconds = (slot[11]+slot[12])/sysconf(_SC_CLK_TCK), ll = 60*60*24; for (s = out, i = 0; i<4; i++) { if (i>1 || seconds > ll) @@ -173,12 +186,15 @@ width=18; void ps_main(void) { - int i, fd = -1; + struct strawberry *field; // Octal output code followed by header name char *typos[] = { - "\207F", "\300S", "\301UID", "\0PID", "\02PPID", "\303C", "\20PRI", - "\21NI", "\34ADDR", "\304SZ", "\305WCHAN", "STIME", "TTY", "TIME", "CMD" + "F", "S", "UID", "PID", "PPID", "C", "PRI", + "NI", "ADDR", "SZ", "WCHAN", "STIME", "TTY", "TIME", "CMD", + "COMMAND", "ELAPSED", "GROUP", "%CPU", "PGID", "RGROUP", + "RUSER", "USER", "VSZ" }; + int i, fd = -1; // l l fl a fl fl l l l l l f a a a // F S UID PID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD @@ -200,18 +216,33 @@ void ps_main(void) } if (fd != -1) close(fd); + // Select fields if (FLAG_o) { printf("todo\n"); } else { - short def = 0x0807; + unsigned short def = 0x0807; if (toys.optflags&FLAG_f) def = 0x1e0f; if (toys.optflags&FLAG_l) def = 0x7ff7; // order of fields[] matches posix STDOUT section, so add enabled XSI // defaults according to bitmask + + for (i=0; def>>i; i++) { + int len = strlen(typos[i]); + + if (!((def>>i)&1)) continue; + + field = xmalloc(sizeof(struct strawberry)+len+1); + field->which = i; + field->len = len; + strcpy(field->title, typos[i]); + dlist_add_nomalloc(&TT.fields, fields); + } } + dlist_terminate(TT.fields); - printf("pid user time args\n"); + for (field = TT.fields; *field; field = field->next) + printf(" %*s", field->len, title); dirtree_read("/proc", do_ps); } |