ps.c revision 8b37c91b934bf22d8ae52bebad7f1f22f16d1132
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
17static char *nexttoksep(char **strp, char *sep)
18{
19    char *p = strsep(strp,sep);
20    return (p == 0) ? "" : p;
21}
22static 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
32static int display_flags = 0;
33
34static 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
173void 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
193int 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