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