]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/pstree.c
Add Erik Quanstrom's smart tool for ATA SMART.
[plan9front.git] / sys / src / cmd / pstree.c
1 #include <u.h>
2 #include <libc.h>
3
4 enum { NBUCKETS = 1024 };
5
6 typedef struct Proc Proc;
7 typedef struct Bucket Bucket;
8
9 struct Proc {
10         int pid;
11         Proc *first, *last, *parent, *next;
12         Proc *bnext;
13 };
14
15 struct Bucket {
16         Proc *first, *last;
17 } buck[NBUCKETS];
18
19 Proc *
20 getproc(int pid)
21 {
22         Proc *p;
23         
24         for(p = buck[pid % NBUCKETS].first; p; p = p->bnext)
25                 if(p->pid == pid)
26                         return p;
27
28         return nil;
29 }
30
31 void
32 addproc(int pid)
33 {
34         Proc *p;
35         Bucket *b;
36         
37         p = mallocz(sizeof(*p), 1);
38         if(p == nil)
39                 sysfatal("malloc: %r");
40         p->pid = pid;
41         b = buck + pid % NBUCKETS;
42         if(b->first != nil)
43                 b->last->bnext = p;
44         else
45                 b->first = p;
46         b->last = p;
47 }
48
49 int
50 theppid(int pid)
51 {
52         char *file;
53         int fd;
54         char buf[12];
55         int ppid;
56         
57         file = smprint("/proc/%d/ppid", pid);
58         fd = open(file, OREAD);
59         free(file);
60         if(fd < 0)
61                 return 0;
62         ppid = 0;
63         if(read(fd, buf, sizeof buf) >= 0)
64                 ppid = atoi(buf);
65         close(fd);
66         return ppid;
67 }
68
69 void
70 addppid(int pid)
71 {
72         int ppid;
73         Proc *p, *par;
74         
75         p = getproc(pid);
76         ppid = theppid(pid);
77         par = getproc(ppid);
78         if(par == nil)
79                 par = getproc(0);
80         p->parent = par;
81         if(par->first != nil)
82                 par->last->next = p;
83         else
84                 par->first = p;
85         par->last = p;
86 }
87
88 void
89 addprocs(void)
90 {
91         int fd, rc, i;
92         Dir *d;
93         
94         fd = open("/proc", OREAD);
95         if(fd < 0)
96                 sysfatal("open: %r");
97         rc = dirreadall(fd, &d);
98         if(rc < 0)
99                 sysfatal("dirreadall: %r");
100         close(fd);
101         for(i = 0; i < rc; i++)
102                 if(d[i].mode & DMDIR)
103                         addproc(atoi(d[i].name));
104         for(i = 0; i < rc; i++)
105                 if(d[i].mode & DMDIR)
106                         addppid(atoi(d[i].name));
107         free(d);
108 }
109
110 Rune buf[512];
111
112 int
113 readout(char *file)
114 {
115         int fd, rc, n;
116         char b[512];
117
118         fd = open(file, OREAD);
119         free(file);
120         if(fd < 0)
121                 return -1;
122         n = 0;
123         while(rc = read(fd, b, 512), rc > 0) {
124                 write(1, b, rc);
125                 n += rc;
126         }
127         close(fd);
128         return n;
129 }
130
131 void
132 printargs(int pid)
133 {
134         char *file;
135         char b[28], *p;
136         int fd;
137
138         if(pid == 0)
139                 return;
140         if(readout(smprint("/proc/%d/args", pid)) > 0)
141                 return;
142         file = smprint("/proc/%d/status", pid);
143         fd = open(file, OREAD);
144         free(file);
145         if(fd < 0)
146                 return;
147         memset(b, 0, sizeof b);
148         if(read(fd, b, 27) <= 0)
149                 return;
150         p = b + strlen(b) - 1;
151         while(*p == ' ')
152                 *p-- = 0;
153         print("%s", b);
154         close(fd);
155 }
156
157 void
158 descend(Proc *p, Rune *r)
159 {
160         Rune last;
161         Proc *q;
162         
163         last = *--r;
164         *r = last == L' ' ? L'└' : L'├';
165         print("%S", buf);
166         printargs(p->pid);
167         print(" [%d]\n", p->pid);
168         *r = last;
169         *++r = L'│';
170         for(q = p->first; q; q = q->next) {
171                 if(q->next == nil)
172                         *r = L' ';
173                 descend(q, r + 1);
174         }
175         *r = 0;
176 }
177
178 void
179 printprocs(void)
180 {
181         descend(getproc(0), buf);
182 }
183
184 void
185 main()
186 {
187         addproc(0);
188         addprocs();
189         printprocs();
190 }