auto import from //depot/cupcake/@135843
diff --git a/toolbox/ps.c b/toolbox/ps.c
new file mode 100644
index 0000000..3b86fa2
--- /dev/null
+++ b/toolbox/ps.c
@@ -0,0 +1,214 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <fcntl.h>
+
+#include <string.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <dirent.h>
+
+#include <pwd.h>
+
+
+static char *nexttoksep(char **strp, char *sep)
+{
+    char *p = strsep(strp,sep);
+    return (p == 0) ? "" : p;
+}
+static char *nexttok(char **strp)
+{
+    return nexttoksep(strp, " ");
+}
+
+#define SHOW_PRIO 1
+#define SHOW_TIME 2
+
+static int display_flags = 0;
+
+static int ps_line(int pid, int tid, char *namefilter)
+{
+    char statline[1024];
+    char cmdline[1024];
+    char user[32];
+    struct stat stats;
+    int fd, r;
+    char *ptr, *name, *state;
+    int ppid, tty;
+    unsigned wchan, rss, vss, eip;
+    unsigned utime, stime;
+    int prio, nice, rtprio, sched;
+    struct passwd *pw;
+    
+    sprintf(statline, "/proc/%d", pid);
+    stat(statline, &stats);
+
+    if(tid) {
+        sprintf(statline, "/proc/%d/task/%d/stat", pid, tid);
+        cmdline[0] = 0;
+    } else {
+        sprintf(statline, "/proc/%d/stat", pid);
+        sprintf(cmdline, "/proc/%d/cmdline", pid);    
+        fd = open(cmdline, O_RDONLY);
+        if(fd == 0) {
+            r = 0;
+        } else {
+            r = read(fd, cmdline, 1023);
+            close(fd);
+            if(r < 0) r = 0;
+        }
+        cmdline[r] = 0;
+    }
+    
+    fd = open(statline, O_RDONLY);
+    if(fd == 0) return -1;
+    r = read(fd, statline, 1023);
+    close(fd);
+    if(r < 0) return -1;
+    statline[r] = 0;
+
+    ptr = statline;
+    nexttok(&ptr); // skip pid
+    ptr++;          // skip "("
+
+    name = ptr;
+    ptr = strrchr(ptr, ')'); // Skip to *last* occurence of ')',
+    *ptr++ = '\0';           // and null-terminate name.
+
+    ptr++;          // skip " "
+    state = nexttok(&ptr);
+    ppid = atoi(nexttok(&ptr));
+    nexttok(&ptr); // pgrp
+    nexttok(&ptr); // sid
+    tty = atoi(nexttok(&ptr));
+    
+    nexttok(&ptr); // tpgid
+    nexttok(&ptr); // flags
+    nexttok(&ptr); // minflt
+    nexttok(&ptr); // cminflt
+    nexttok(&ptr); // majflt
+    nexttok(&ptr); // cmajflt
+#if 1
+    utime = atoi(nexttok(&ptr));
+    stime = atoi(nexttok(&ptr));
+#else
+    nexttok(&ptr); // utime
+    nexttok(&ptr); // stime
+#endif
+    nexttok(&ptr); // cutime
+    nexttok(&ptr); // cstime
+    prio = atoi(nexttok(&ptr));
+    nice = atoi(nexttok(&ptr));
+    nexttok(&ptr); // threads
+    nexttok(&ptr); // itrealvalue
+    nexttok(&ptr); // starttime
+    vss = strtoul(nexttok(&ptr), 0, 10); // vsize
+    rss = strtoul(nexttok(&ptr), 0, 10); // rss
+    nexttok(&ptr); // rlim
+    nexttok(&ptr); // startcode
+    nexttok(&ptr); // endcode
+    nexttok(&ptr); // startstack
+    nexttok(&ptr); // kstkesp
+    eip = strtoul(nexttok(&ptr), 0, 10); // kstkeip
+    nexttok(&ptr); // signal
+    nexttok(&ptr); // blocked
+    nexttok(&ptr); // sigignore
+    nexttok(&ptr); // sigcatch
+    wchan = strtoul(nexttok(&ptr), 0, 10); // wchan
+    nexttok(&ptr); // nswap
+    nexttok(&ptr); // cnswap
+    nexttok(&ptr); // exit signal
+    nexttok(&ptr); // processor
+    rtprio = atoi(nexttok(&ptr)); // rt_priority
+    sched = atoi(nexttok(&ptr)); // scheduling policy
+    
+    tty = atoi(nexttok(&ptr));
+    
+    if(tid != 0) {
+        ppid = pid;
+        pid = tid;
+    }
+
+    pw = getpwuid(stats.st_uid);
+    if(pw == 0) {
+        sprintf(user,"%d",(int)stats.st_uid);
+    } else {
+        strcpy(user,pw->pw_name);
+    }
+    
+    if(!namefilter || !strncmp(name, namefilter, strlen(namefilter))) {
+        printf("%-8s %-5d %-5d %-5d %-5d", user, pid, ppid, vss / 1024, rss * 4);
+        if(display_flags&SHOW_PRIO)
+            printf(" %-5d %-5d %-5d %-5d", prio, nice, rtprio, sched);
+        printf(" %08x %08x %s %s", wchan, eip, state, cmdline[0] ? cmdline : name);
+        if(display_flags&SHOW_TIME)
+            printf(" (u:%d, s:%d)", utime, stime);
+        printf("\n");
+    }
+    return 0;
+}
+
+
+void ps_threads(int pid, char *namefilter)
+{
+    char tmp[128];
+    DIR *d;
+    struct dirent *de;
+
+    sprintf(tmp,"/proc/%d/task",pid);
+    d = opendir(tmp);
+    if(d == 0) return;
+    
+    while((de = readdir(d)) != 0){
+        if(isdigit(de->d_name[0])){
+            int tid = atoi(de->d_name);
+            if(tid == pid) continue;
+            ps_line(pid, tid, namefilter);
+        }
+    }
+    closedir(d);    
+}
+
+int ps_main(int argc, char **argv)
+{
+    DIR *d;
+    struct dirent *de;
+    char *namefilter = 0;
+    int pidfilter = 0;
+    int threads = 0;
+    
+    d = opendir("/proc");
+    if(d == 0) return -1;
+
+    while(argc > 1){
+        if(!strcmp(argv[1],"-t")) {
+            threads = 1;
+        } else if(!strcmp(argv[1],"-x")) {
+            display_flags |= SHOW_TIME;
+        } else if(!strcmp(argv[1],"-p")) {
+            display_flags |= SHOW_PRIO;
+        }  else if(isdigit(argv[1][0])){
+            pidfilter = atoi(argv[1]);
+        } else {
+            namefilter = argv[1];
+        }
+        argc--;
+        argv++;
+    }
+
+    printf("USER     PID   PPID  VSIZE RSS   %sWCHAN    PC         NAME\n", 
+           (display_flags&SHOW_PRIO)?"PRIO  NICE  RTPRI SCHED ":"");
+    while((de = readdir(d)) != 0){
+        if(isdigit(de->d_name[0])){
+            int pid = atoi(de->d_name);
+            if(!pidfilter || (pidfilter == pid)) {
+                ps_line(pid, 0, namefilter);
+                if(threads) ps_threads(pid, namefilter);
+            }
+        }
+    }
+    closedir(d);
+    return 0;
+}
+