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