aboutsummaryrefslogtreecommitdiff
path: root/toys/posix
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2015-11-28 14:39:29 -0600
committerRob Landley <rob@landley.net>2015-11-28 14:39:29 -0600
commit463c56b4fb5c63ffa294b126b41d26942d37f9dc (patch)
tree88e833f6fb77905aba26ee6e2589c5478ced7945 /toys/posix
parent12a487b61f809aa4794578e14efe32d717f22bdb (diff)
downloadtoybox-463c56b4fb5c63ffa294b126b41d26942d37f9dc.tar.gz
Save string offsets rather than recalculating them each time, and use struct
instead of carving up toybuf by hand. This makes breaking out the field conversion logic into its own function less expensive.
Diffstat (limited to 'toys/posix')
-rw-r--r--toys/posix/ps.c60
1 files changed, 35 insertions, 25 deletions
diff --git a/toys/posix/ps.c b/toys/posix/ps.c
index e5fcc5c5..984a1b3a 100644
--- a/toys/posix/ps.c
+++ b/toys/posix/ps.c
@@ -174,24 +174,23 @@ static int match_process(long long *slot)
return 1;
}
+// Data layout in toybuf
+struct carveup {
+ long long slot[50]; // data from /proc, skippint #2 and #3
+ unsigned short offset[4]; // offset of fields in str[] (skip name, always 0)
+ char state;
+ char str[]; // name, tty, wchan, attr, cmdline
+};
+
// Display process data that get_ps() read from /proc, formatting with TT.fields
static void show_ps(long long *slot)
{
- char state, *s, *buf, *strslot[5]; // name, tty, wchan, attr, cmdline
+ char *s, *buf = toybuf+sizeof(toybuf)-64;
+ struct carveup *tb = (void *)slot;
struct strawberry *field;
long long ll;
int i, len, width = TT.width;
- // Carve toybuf up into chunks to extract our incoming data
- s = (char *)(slot+50);
- state = *s++;
- for (i=0; i<5; i++) {
- strslot[i] = s;
- s += strlen(s)+1;
- }
- // 64 byte sscratch space reserved for sprintf to output data to
- buf = toybuf+sizeof(toybuf)-64;
-
// Loop through fields to display
for (field = TT.fields; field; field = field->next) {
char *out = buf;
@@ -229,18 +228,19 @@ static void show_ps(long long *slot)
if (pw) out = pw->pw_name;
}
}
- // strslot: CMD TTY WCHAN LABEL (plus CMDLINE handled elsewhere)
- } else if (-1!=(i = stridx((char[]){15,12,10,31}, field->which)))
- out = strslot[i];
+ // CMD TTY WCHAN LABEL (CMDLINE handled elsewhere)
+ } else if (-1!=(i = stridx((char[]){15,12,10,31}, field->which))) {
+ out = tb->str;
+ if (i) out += tb->offset[i-1];
// F (also assignment of i used by later tests)
// Posix doesn't specify what flags should say. Man page says
// 1 for PF_FORKNOEXEC and 4 for PF_SUPERPRIV from linux/sched.h
- else if (!(i = field->which)) sprintf(out, "%llo", (slot[6]>>6)&5);
+ } else if (!(i = field->which)) sprintf(out, "%llo", (slot[6]>>6)&5);
// S STAT
else if (i==1 || i==27) {
s = out;
- *s++ = state;
+ *s++ = tb->state;
if (i==27) {
// TODO l = multithreaded
if (slot[16]<0) *s++ = '<';
@@ -284,9 +284,9 @@ static void show_ps(long long *slot)
} else if (i==14 || i==32) {
if (slot[47]<1) {
out = toybuf+sizeof(toybuf)-300;
- sprintf(out, "[%s]", *strslot); // kernel thread, use real name
+ sprintf(out, "[%s]", tb->str); // kernel thread, use real name
} else {
- out = strslot[4];
+ out = tb->str+tb->offset[3];
if (slot[47]!=INT_MAX) out[slot[47]] = ' '*(i==14);
}
@@ -321,8 +321,9 @@ static int get_ps(struct dirtree *new)
long long bits;
} fetch[] = {{"fd/", 1<<12}, {"wchan", 1<<10}, {"attr/current", 1<<31},
{"cmdline", (1<<14)|(1LL<<32)}};
+ struct carveup *tb = (void *)toybuf;
long long *slot = (void *)toybuf;
- char *name, *s, *buf = (char *)(slot+50), *end = 0;
+ char *name, *s, *buf = tb->str, *end = 0;
int i, j, fd, ksave = DIRTREE_SAVE*!!(toys.optflags&FLAG_k);
off_t len;
@@ -342,16 +343,24 @@ static int get_ps(struct dirtree *new)
for (s = ++name; *s; s++) if (*s == ')') end = s;
if (!end || end-name>255) return 0;
- // Put status in first byte, and copy name after with low chars spaced.
- if (1>sscanf(s = end, ") %c%n", buf++, &i)) return 0;
- for (i = 0; i<end-name; i++) if ((buf[i] = name[i]) < ' ') buf[i] = ' ';
- buf += i;
+ // Move name right after slot[] array (pid already set, so stomping it's ok)
+ // and convert low chars to spaces while we're at it.
+ for (i = 0; i<end-name; i++)
+ if ((tb->str[i] = name[i]) < ' ') tb->str[i] = ' ';
+ buf = tb->str+i;
*buf++ = 0;
- i = 3;
- // parse numeric fields (PID = 0, skip 2, then 4th field goes in slot[1])
+ // Parse numeric fields (starting at 4th field in slot[1])
+ if (1>sscanf(s = end, ") %c%n", &tb->state, &i)) return 0;
for (j = 1; j<50; j++) if (1>sscanf(s += i, " %lld%n", slot+j, &i)) break;
+ // Now we've read the data, move status and name right after slot[] array,
+ // and convert low chars to spaces while we're at it.
+ for (i = 0; i<end-name; i++)
+ if ((tb->str[i] = name[i]) < ' ') tb->str[i] = ' ';
+ buf = tb->str+i;
+ *buf++ = 0;
+
// save uid, ruid, gid, gid, and rgid int slots 31-34 (we don't use sigcatch
// or numeric wchan, and the remaining two are always zero), and vmlck into
// 18 (which is "obsolete, always 0")
@@ -386,6 +395,7 @@ static int get_ps(struct dirtree *new)
// it'd almost never get used, querying length of a proc file is awkward,
// fixed buffer is nommu friendly... Wait for somebody to complain. :)
for (j = 0; j<ARRAY_LEN(fetch); j++) {
+ tb->offset[j] = buf-(tb->str);
if (!(TT.bits&fetch[j].bits)) {
*buf++ = 0;
continue;