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