Home | History | Annotate | Download | only in toolbox
      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <ctype.h>
      4 #include <fcntl.h>
      5 
      6 #include <string.h>
      7 
      8 #include <sys/stat.h>
      9 #include <sys/types.h>
     10 #include <dirent.h>
     11 
     12 #include <pwd.h>
     13 
     14 #include <cutils/sched_policy.h>
     15 
     16 
     17 static char *nexttoksep(char **strp, char *sep)
     18 {
     19     char *p = strsep(strp,sep);
     20     return (p == 0) ? "" : p;
     21 }
     22 static char *nexttok(char **strp)
     23 {
     24     return nexttoksep(strp, " ");
     25 }
     26 
     27 #define SHOW_PRIO 1
     28 #define SHOW_TIME 2
     29 #define SHOW_POLICY 4
     30 
     31 static int display_flags = 0;
     32 
     33 static int ps_line(int pid, int tid, char *namefilter)
     34 {
     35     char statline[1024];
     36     char cmdline[1024];
     37     char user[32];
     38     struct stat stats;
     39     int fd, r;
     40     char *ptr, *name, *state;
     41     int ppid, tty;
     42     unsigned wchan, rss, vss, eip;
     43     unsigned utime, stime;
     44     int prio, nice, rtprio, sched;
     45     struct passwd *pw;
     46 
     47     sprintf(statline, "/proc/%d", pid);
     48     stat(statline, &stats);
     49 
     50     if(tid) {
     51         sprintf(statline, "/proc/%d/task/%d/stat", pid, tid);
     52         cmdline[0] = 0;
     53     } else {
     54         sprintf(statline, "/proc/%d/stat", pid);
     55         sprintf(cmdline, "/proc/%d/cmdline", pid);
     56         fd = open(cmdline, O_RDONLY);
     57         if(fd == 0) {
     58             r = 0;
     59         } else {
     60             r = read(fd, cmdline, 1023);
     61             close(fd);
     62             if(r < 0) r = 0;
     63         }
     64         cmdline[r] = 0;
     65     }
     66 
     67     fd = open(statline, O_RDONLY);
     68     if(fd == 0) return -1;
     69     r = read(fd, statline, 1023);
     70     close(fd);
     71     if(r < 0) return -1;
     72     statline[r] = 0;
     73 
     74     ptr = statline;
     75     nexttok(&ptr); // skip pid
     76     ptr++;          // skip "("
     77 
     78     name = ptr;
     79     ptr = strrchr(ptr, ')'); // Skip to *last* occurence of ')',
     80     *ptr++ = '\0';           // and null-terminate name.
     81 
     82     ptr++;          // skip " "
     83     state = nexttok(&ptr);
     84     ppid = atoi(nexttok(&ptr));
     85     nexttok(&ptr); // pgrp
     86     nexttok(&ptr); // sid
     87     tty = atoi(nexttok(&ptr));
     88 
     89     nexttok(&ptr); // tpgid
     90     nexttok(&ptr); // flags
     91     nexttok(&ptr); // minflt
     92     nexttok(&ptr); // cminflt
     93     nexttok(&ptr); // majflt
     94     nexttok(&ptr); // cmajflt
     95 #if 1
     96     utime = atoi(nexttok(&ptr));
     97     stime = atoi(nexttok(&ptr));
     98 #else
     99     nexttok(&ptr); // utime
    100     nexttok(&ptr); // stime
    101 #endif
    102     nexttok(&ptr); // cutime
    103     nexttok(&ptr); // cstime
    104     prio = atoi(nexttok(&ptr));
    105     nice = atoi(nexttok(&ptr));
    106     nexttok(&ptr); // threads
    107     nexttok(&ptr); // itrealvalue
    108     nexttok(&ptr); // starttime
    109     vss = strtoul(nexttok(&ptr), 0, 10); // vsize
    110     rss = strtoul(nexttok(&ptr), 0, 10); // rss
    111     nexttok(&ptr); // rlim
    112     nexttok(&ptr); // startcode
    113     nexttok(&ptr); // endcode
    114     nexttok(&ptr); // startstack
    115     nexttok(&ptr); // kstkesp
    116     eip = strtoul(nexttok(&ptr), 0, 10); // kstkeip
    117     nexttok(&ptr); // signal
    118     nexttok(&ptr); // blocked
    119     nexttok(&ptr); // sigignore
    120     nexttok(&ptr); // sigcatch
    121     wchan = strtoul(nexttok(&ptr), 0, 10); // wchan
    122     nexttok(&ptr); // nswap
    123     nexttok(&ptr); // cnswap
    124     nexttok(&ptr); // exit signal
    125     nexttok(&ptr); // processor
    126     rtprio = atoi(nexttok(&ptr)); // rt_priority
    127     sched = atoi(nexttok(&ptr)); // scheduling policy
    128 
    129     tty = atoi(nexttok(&ptr));
    130 
    131     if(tid != 0) {
    132         ppid = pid;
    133         pid = tid;
    134     }
    135 
    136     pw = getpwuid(stats.st_uid);
    137     if(pw == 0) {
    138         sprintf(user,"%d",(int)stats.st_uid);
    139     } else {
    140         strcpy(user,pw->pw_name);
    141     }
    142 
    143     if(!namefilter || !strncmp(name, namefilter, strlen(namefilter))) {
    144         printf("%-9s %-5d %-5d %-6d %-5d", user, pid, ppid, vss / 1024, rss * 4);
    145         if(display_flags&SHOW_PRIO)
    146             printf(" %-5d %-5d %-5d %-5d", prio, nice, rtprio, sched);
    147         if (display_flags & SHOW_POLICY) {
    148             SchedPolicy p;
    149             if (get_sched_policy(pid, &p) < 0)
    150                 printf(" un ");
    151             else {
    152                 if (p == SP_BACKGROUND)
    153                     printf(" bg ");
    154                 else if (p == SP_FOREGROUND)
    155                     printf(" fg ");
    156                 else
    157                     printf(" er ");
    158             }
    159         }
    160         printf(" %08x %08x %s %s", wchan, eip, state, cmdline[0] ? cmdline : name);
    161         if(display_flags&SHOW_TIME)
    162             printf(" (u:%d, s:%d)", utime, stime);
    163 
    164         printf("\n");
    165     }
    166     return 0;
    167 }
    168 
    169 
    170 void ps_threads(int pid, char *namefilter)
    171 {
    172     char tmp[128];
    173     DIR *d;
    174     struct dirent *de;
    175 
    176     sprintf(tmp,"/proc/%d/task",pid);
    177     d = opendir(tmp);
    178     if(d == 0) return;
    179 
    180     while((de = readdir(d)) != 0){
    181         if(isdigit(de->d_name[0])){
    182             int tid = atoi(de->d_name);
    183             if(tid == pid) continue;
    184             ps_line(pid, tid, namefilter);
    185         }
    186     }
    187     closedir(d);
    188 }
    189 
    190 int ps_main(int argc, char **argv)
    191 {
    192     DIR *d;
    193     struct dirent *de;
    194     char *namefilter = 0;
    195     int pidfilter = 0;
    196     int threads = 0;
    197 
    198     d = opendir("/proc");
    199     if(d == 0) return -1;
    200 
    201     while(argc > 1){
    202         if(!strcmp(argv[1],"-t")) {
    203             threads = 1;
    204         } else if(!strcmp(argv[1],"-x")) {
    205             display_flags |= SHOW_TIME;
    206         } else if(!strcmp(argv[1],"-P")) {
    207             display_flags |= SHOW_POLICY;
    208         } else if(!strcmp(argv[1],"-p")) {
    209             display_flags |= SHOW_PRIO;
    210         }  else if(isdigit(argv[1][0])){
    211             pidfilter = atoi(argv[1]);
    212         } else {
    213             namefilter = argv[1];
    214         }
    215         argc--;
    216         argv++;
    217     }
    218 
    219     printf("USER     PID   PPID  VSIZE  RSS   %s %s WCHAN    PC         NAME\n",
    220            (display_flags&SHOW_PRIO)?"PRIO  NICE  RTPRI SCHED ":"",
    221            (display_flags&SHOW_POLICY)?"PCY " : "");
    222     while((de = readdir(d)) != 0){
    223         if(isdigit(de->d_name[0])){
    224             int pid = atoi(de->d_name);
    225             if(!pidfilter || (pidfilter == pid)) {
    226                 ps_line(pid, 0, namefilter);
    227                 if(threads) ps_threads(pid, namefilter);
    228             }
    229         }
    230     }
    231     closedir(d);
    232     return 0;
    233 }
    234 
    235