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