ps.c revision 4f6e8d7a00cbeda1e70cc15be9c4af1018bdad53
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
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
215