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