summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlastair Poole <netstar@gmail.com>2021-05-17 16:30:30 +0100
committerAlastair Poole <netstar@gmail.com>2021-05-17 16:30:30 +0100
commita6e45b02b7edb075342f5db063dd4182d122c718 (patch)
treec03baf369b133c8a4a6a07d91521566898797902
parent2568058a446822cdb2005b4ddba2b68403e52edc (diff)
wip: wip wip wip wip wip wip wip
wip?
-rw-r--r--src/bin/next/filesystems.c129
-rw-r--r--src/bin/next/filesystems.h28
-rw-r--r--src/bin/next/machine.h2
-rw-r--r--src/bin/next/meson.build4
-rw-r--r--src/bin/next/process.c1499
-rw-r--r--src/bin/next/process.h119
6 files changed, 1780 insertions, 1 deletions
diff --git a/src/bin/next/filesystems.c b/src/bin/next/filesystems.c
new file mode 100644
index 0000000..35b6499
--- /dev/null
+++ b/src/bin/next/filesystems.c
@@ -0,0 +1,129 @@
1#include "filesystems.h"
2
3#include <stdio.h>
4#include <limits.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8
9#if defined(__linux__)
10 #include <sys/vfs.h>
11#endif
12
13#if defined(__APPLE__) && defined(__MACH__)
14# define __MacOS__
15#endif
16
17#if defined (__MacOS__) || defined(__FreeBSD__) || defined(__DragonFly__)
18# include <sys/types.h>
19# include <sys/sysctl.h>
20# include <sys/param.h>
21# include <sys/ucred.h>
22# include <sys/mount.h>
23#endif
24
25#if defined(__OpenBSD__) || defined(__NetBSD__)
26# include <sys/param.h>
27# include <sys/sysctl.h>
28# include <sys/mount.h>
29#endif
30
31Eina_List *
32file_system_info_all_get(void)
33{
34 Eina_List *list = NULL;
35# if defined(__linux__)
36 FILE *f;
37 char *dev, *mount, *type_name, *cp, *end;
38 struct statfs stats;
39 char buf[4096];
40
41 f = fopen("/proc/mounts", "r");
42 if (!f) return NULL;
43
44 while ((fgets(buf, sizeof(buf), f)) != NULL)
45 {
46 mount = strchr(buf, ' ') + 1;
47 if (!mount) continue;
48 dev = strndup(buf, mount - buf);
49 cp = strchr(mount, ' ');
50 if (!cp) continue;
51 end = cp;
52 *end = '\0';
53 cp++;
54 end = strchr(cp, ' ');
55 if (!end) continue;
56 type_name = strndup(cp, end - cp);
57
58 if ((strstr(cp, "nodev")) || (statfs(mount, &stats) < 0) ||
59 (stats.f_blocks == 0 && stats.f_bfree == 0))
60 {
61 free(dev);
62 free(type_name);
63 continue;
64 }
65
66 File_System *fs = calloc(1, sizeof(File_System));
67 fs->mount = strdup(mount);
68 fs->path = dev;
69 fs->type_name = type_name;
70 fs->usage.total = stats.f_bsize * stats.f_blocks;
71 fs->usage.used = fs->usage.total - (stats.f_bsize * stats.f_bfree);
72 list = eina_list_append(list, fs);
73 }
74 fclose(f);
75# else
76 struct statfs *mounts;
77 int i, count;
78
79 count = getmntinfo(&mounts, MNT_WAIT);
80 for (i = 0; i < count; i++)
81 {
82 File_System *fs = calloc(1, sizeof(File_System));
83 fs->mount = strdup(mounts[i].f_mntonname);
84 fs->path = strdup(mounts[i].f_mntfromname);
85#if defined(__OpenBSD__)
86#else
87 fs->type = mounts[i].f_type;
88#endif
89 fs->type_name = strdup(mounts[i].f_fstypename);
90 fs->usage.total = mounts[i].f_bsize * mounts[i].f_blocks;
91 fs->usage.used = fs->usage.total - (mounts[i].f_bsize * mounts[i].f_bfree);
92
93 list = eina_list_append(list, fs);
94 }
95# endif
96 return list;
97}
98
99void
100file_system_info_free(File_System *fs)
101{
102 free(fs->mount);
103 free(fs->path);
104 if (fs->type_name)
105 free(fs->type_name);
106 free(fs);
107}
108
109Eina_Bool
110file_system_in_use(const char *name)
111{
112 Eina_List *list;
113 File_System *fs;
114 Eina_Bool mounted = 0;
115
116 if (!name) return 0;
117
118 list = file_system_info_all_get();
119 EINA_LIST_FREE(list, fs)
120 {
121 if (fs->type_name && (!strcasecmp(fs->type_name, name)))
122 mounted = 1;
123
124 file_system_info_free(fs);
125 }
126
127 return mounted;
128}
129
diff --git a/src/bin/next/filesystems.h b/src/bin/next/filesystems.h
new file mode 100644
index 0000000..897c10b
--- /dev/null
+++ b/src/bin/next/filesystems.h
@@ -0,0 +1,28 @@
1#ifndef __FILESYSTEMS_H__
2#define __FILESYSTEMS_H__
3
4#include <Eina.h>
5
6typedef struct {
7 unsigned long long total;
8 unsigned long long used;
9} _Usage;
10
11typedef struct _File_System {
12 char *path;
13 char *mount;
14 char *type_name;
15 unsigned int type;
16 _Usage usage;
17} File_System;
18
19Eina_List *
20file_system_info_all_get(void);
21
22void
23file_system_info_free(File_System *fs);
24
25Eina_Bool
26file_system_in_use(const char *name);
27
28#endif
diff --git a/src/bin/next/machine.h b/src/bin/next/machine.h
index 597ad58..d43166a 100644
--- a/src/bin/next/machine.h
+++ b/src/bin/next/machine.h
@@ -136,7 +136,7 @@ int
136cores_frequency(void); 136cores_frequency(void);
137 137
138int 138int
139core_id_frequency(int d); 139core_id_frequency(int id);
140 140
141int 141int
142core_id_temperature(int id); 142core_id_temperature(int id);
diff --git a/src/bin/next/meson.build b/src/bin/next/meson.build
index 6c0b60f..c0db5f0 100644
--- a/src/bin/next/meson.build
+++ b/src/bin/next/meson.build
@@ -1,4 +1,8 @@
1src_watch += files([ 1src_watch += files([
2 'machine.c', 2 'machine.c',
3 'machine.h', 3 'machine.h',
4 'process.c',
5 'process.h',
6 'filesystems.c',
7 'filesystems.h',
4]) 8])
diff --git a/src/bin/next/process.c b/src/bin/next/process.c
new file mode 100644
index 0000000..4d0ec14
--- /dev/null
+++ b/src/bin/next/process.c
@@ -0,0 +1,1499 @@
1#if defined(__MACH__) && defined(__APPLE__)
2# define __MacOS__
3#endif
4
5#include "ui/gettext.h"
6#define _(STR) gettext(STR)
7
8#if defined(__MacOS__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
9# include <sys/types.h>
10# include <sys/sysctl.h>
11# include <sys/user.h>
12# include <sys/proc.h>
13# include <libgen.h>
14#endif
15
16#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
17# include <libgen.h>
18# include <unistd.h>
19# include <fcntl.h>
20# include <kvm.h>
21# include <limits.h>
22# include <sys/proc.h>
23# include <sys/param.h>
24# include <sys/resource.h>
25#endif
26
27#if defined(__FreeBSD__)
28# define _WANT_FILE
29# include <sys/file.h>
30# include <sys/filedesc.h>
31#endif
32
33#if defined(__MacOS__)
34# include <libproc.h>
35# include <sys/proc_info.h>
36#endif
37
38#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41#include <ctype.h>
42#include <unistd.h>
43#include <limits.h>
44
45#include "process.h"
46#include <Eina.h>
47#include <Ecore.h>
48#include <Ecore_File.h>
49
50#if defined(__linux__) && !defined(PF_KTHREAD)
51# define PF_KTHREAD 0x00200000
52#endif
53
54#include "macros.h"
55
56static Eina_Bool _show_kthreads = 1;
57
58void
59proc_info_kthreads_show_set(Eina_Bool enabled)
60{
61 _show_kthreads = enabled;
62}
63
64Eina_Bool
65proc_info_kthreads_show_get(void)
66{
67 return _show_kthreads;
68}
69
70static const char * _states[128];
71
72static void
73_states_init(void)
74{
75#if defined(__linux__)
76 _states['D'] = _("dsleep");
77 _states['I'] = _("idle");
78 _states['R'] = _("running");
79 _states['S'] = _("sleeping");
80 _states['T'] = _("stopped");
81 _states['X'] = _("dead");
82 _states['Z'] = _("zombie");
83#else
84 _states[SIDL] = _("idle");
85 _states[SRUN] = _("running");
86 _states[SSLEEP] = _("sleeping");
87 _states[SSTOP] = _("stopped");
88#if !defined(__MacOS__)
89#if !defined(__OpenBSD__)
90 _states[SWAIT] = _("wait");
91 _states[SLOCK] = _("lock");
92 _states[SZOMB] = _("zombie");
93#endif
94#if defined(__OpenBSD__)
95 _states[SDEAD] = _("zombie");
96 _states[SONPROC] = _("running");
97#endif
98#endif
99#endif
100}
101
102static const char *
103_process_state_name(char state)
104{
105 static int init = 0;
106 if (!init)
107 {
108 _states_init();
109 init = 1;
110 }
111 return _states[toupper(state)];
112}
113
114#if defined(__linux__)
115
116static unsigned long
117_parse_line(const char *line)
118{
119 char *p, *tok;
120
121 p = strchr(line, ':') + 1;
122 while (isspace(*p))
123 p++;
124 tok = strtok(p, " ");
125
126 return atol(tok);
127}
128
129static void
130_mem_size(Proc_Info *proc)
131{
132 FILE *f;
133 char buf[4096];
134 unsigned int dummy, size, shared, resident, data, text;
135 static int pagesize = 0;
136
137 if (!pagesize) pagesize = getpagesize();
138
139 snprintf(buf, sizeof(buf), "/proc/%d/statm", proc->pid);
140 f = fopen(buf, "r");
141 if (!f) return;
142
143 if (fgets(buf, sizeof(buf), f))
144 {
145 if (sscanf(buf, "%u %u %u %u %u %u %u",
146 &size, &resident, &shared, &text,
147 &dummy, &data, &dummy) == 7)
148 {
149 proc->mem_rss = MEMSIZE(resident) * MEMSIZE(pagesize);
150 proc->mem_shared = MEMSIZE(shared) * MEMSIZE(pagesize);
151 proc->mem_size = proc->mem_rss - proc->mem_shared;
152 proc->mem_virt = MEMSIZE(size) * MEMSIZE(pagesize);
153 }
154 }
155
156 fclose(f);
157}
158
159static void
160_cmd_args(Proc_Info *p, char *name, size_t len)
161{
162 char buf[8192];
163 int pid = p->pid;
164
165 snprintf(buf, sizeof(buf), "/proc/%d/exe", pid);
166 char *link = ecore_file_readlink(buf);
167 if (link)
168 {
169 snprintf(name, len, "%s", ecore_file_file_get(link));
170 free(link);
171 }
172
173 snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
174 FILE *f = fopen(buf, "r");
175 if (f)
176 {
177 if (fgets(buf, sizeof(buf), f))
178 {
179 Eina_Strbuf *b = eina_strbuf_new();
180 const char *n;
181
182 if (ecore_file_exists(buf))
183 snprintf(name, len, "%s", ecore_file_file_get(buf));
184
185 n = buf;
186 while (n && *n && (*n + 1))
187 {
188 eina_strbuf_append(b, n);
189 n = strchr(n, '\0') + 1;
190 if (n && *n && (*n + 1)) eina_strbuf_append(b, " ");
191 }
192 p->arguments = eina_strbuf_release(b);
193 }
194 fclose(f);
195 }
196
197 char *end = strchr(name, ' ');
198 if (end) *end = '\0';
199
200 p->command = strdup(name);
201}
202
203static int
204_uid(int pid)
205{
206 FILE *f;
207 char buf[4096];
208 int uid = 0;
209
210 snprintf(buf, sizeof(buf),"/proc/%d/status", pid);
211 f = fopen(buf, "r");
212 if (!f) return -1;
213
214 while ((fgets(buf, sizeof(buf), f)) != NULL)
215 {
216 if (!strncmp(buf, "Uid:", 4))
217 {
218 uid = _parse_line(buf);
219 break;
220 }
221 }
222
223 fclose(f);
224
225 return uid;
226}
227
228static int64_t
229_boot_time(void)
230{
231 FILE *f;
232 int64_t boot_time;
233 char buf[4096];
234 double uptime = 0.0;
235
236 f = fopen("/proc/uptime", "r");
237 if (!f) return 0;
238
239 if (fgets(buf, sizeof(buf), f))
240 sscanf(buf, "%lf", &uptime);
241 else boot_time = 0;
242
243 fclose(f);
244
245 if (uptime > 0.0)
246 boot_time = time(NULL) - (time_t) uptime;
247
248 return boot_time;
249}
250
251typedef struct
252{
253 int pid, ppid, utime, stime, cutime, cstime;
254 int psr, pri, nice, numthreads;
255 long long int start_time, run_time;
256 char state;
257 unsigned int mem_rss, flags;
258 unsigned long mem_virt;
259 char name[1024];
260} Stat;
261
262static Eina_Bool
263_stat(const char *path, Stat *st)
264{
265 FILE *f;
266 char line[4096];
267 char name[1024];
268 int dummy, len = 0;
269 static long tck = 0;
270 static int64_t boot_time = 0;
271
272 if (!boot_time) boot_time = _boot_time();
273
274 memset(st, 0, sizeof(Stat));
275
276 f = fopen(path, "r");
277 if (!f) return 0;
278
279 if (fgets(line, sizeof(line), f))
280 {
281
282 len = sscanf(line, "%d %s %c %d %d %d %d %d %u %u %u %u %u %d %d %d"
283 " %d %d %d %u %u %lld %lu %u %u %u %u %u %u %u %d %d %d %d %u"
284 " %d %d %d %d %d %d %d %d %d", &dummy, name,
285 &st->state, &st->ppid, &dummy, &dummy, &dummy, &dummy, &st->flags,
286 &dummy, &dummy, &dummy, &dummy, &st->utime, &st->stime, &st->cutime,
287 &st->cstime, &st->pri, &st->nice, &st->numthreads, &dummy, &st->start_time,
288 &st->mem_virt, &st->mem_rss, &dummy, &dummy, &dummy, &dummy, &dummy,
289 &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy,
290 &dummy, &dummy, &st->psr, &dummy, &dummy, &dummy, &dummy, &dummy);
291 }
292 fclose(f);
293
294 if (len != 44) return 0;
295
296 len = strlen(name);
297 if (len)
298 {
299 name[len-1] = '\0';
300 snprintf(st->name, sizeof(st->name), "%s", &name[1]);
301 }
302
303 if (!tck) tck = sysconf(_SC_CLK_TCK);
304
305 st->start_time /= tck;
306 st->start_time += boot_time;
307 st->run_time = (st->utime + st->stime) / tck;
308
309 return 1;
310}
311
312static int
313_n_files(Proc_Info *p)
314{
315 char buf[256];
316 Eina_List *files;
317 char *f;
318
319 snprintf(buf, sizeof(buf), "/proc/%d/fd", p->pid);
320
321 files = ecore_file_ls(buf);
322 EINA_LIST_FREE(files, f)
323 {
324 p->numfiles++;
325 free(f);
326 }
327 return p->numfiles;
328}
329
330static Eina_List *
331_process_list_linux_get(void)
332{
333 Eina_List *files, *list;
334 const char *state;
335 char *n;
336 char buf[4096];
337 Stat st;
338
339 list = NULL;
340
341 files = ecore_file_ls("/proc");
342 EINA_LIST_FREE(files, n)
343 {
344 int pid = atoi(n);
345 free(n);
346
347 if (!pid) continue;
348
349 snprintf(buf, sizeof(buf), "/proc/%d/stat", pid);
350 if (!_stat(buf, &st))
351 continue;
352
353 if (st.flags & PF_KTHREAD && !proc_info_kthreads_show_get())
354 continue;
355
356 Proc_Info *p = calloc(1, sizeof(Proc_Info));
357 if (!p) return NULL;
358
359 p->pid = pid;
360 p->ppid = st.ppid;
361 p->uid = _uid(pid);
362 p->cpu_id = st.psr;
363 p->start = st.start_time;
364 p->run_time = st.run_time;
365 state = _process_state_name(st.state);
366 snprintf(p->state, sizeof(p->state), "%s", state);
367 p->cpu_time = st.utime + st.stime;
368 p->nice = st.nice;
369 p->priority = st.pri;
370 p->numthreads = st.numthreads;
371 p->numfiles = _n_files(p);
372 if (st.flags & PF_KTHREAD)
373 p->is_kernel = 1;
374 _mem_size(p);
375 _cmd_args(p, st.name, sizeof(st.name));
376
377 list = eina_list_append(list, p);
378 }
379
380 return list;
381}
382
383static void
384_proc_thread_info(Proc_Info *p)
385{
386 Eina_List *files;
387 const char *state;
388 char *n;
389 char buf[4096];
390 Stat st;
391
392 snprintf(buf, sizeof(buf), "/proc/%d/task", p->pid);
393 files = ecore_file_ls(buf);
394 EINA_LIST_FREE(files, n)
395 {
396 int tid = atoi(n);
397 free(n);
398 snprintf(buf, sizeof(buf), "/proc/%d/task/%d/stat", p->pid, tid);
399 if (!_stat(buf, &st))
400 continue;
401
402 Proc_Info *t = calloc(1, sizeof(Proc_Info));
403 if (!t) continue;
404 t->cpu_id = st.psr;
405 state = _process_state_name(st.state);
406 snprintf(t->state, sizeof(t->state), "%s", state);
407 t->cpu_time = st.utime + st.stime;
408 t->nice = st.nice;
409 t->priority = st.pri;
410 t->numthreads = st.numthreads;
411 t->mem_virt = st.mem_virt;
412 t->mem_rss = st.mem_rss;
413
414 t->tid = tid;
415 t->thread_name = strdup(st.name);
416
417 p->threads = eina_list_append(p->threads, t);
418 }
419}
420
421Proc_Info *
422proc_info_by_pid(int pid)
423{
424 const char *state;
425 Stat st;
426 char buf[4096];
427
428 snprintf(buf, sizeof(buf), "/proc/%d/stat", pid);
429 if (!_stat(buf, &st))
430 return NULL;
431
432 Proc_Info *p = calloc(1, sizeof(Proc_Info));
433 if (!p) return NULL;
434
435 p->pid = pid;
436 p->ppid = st.ppid;
437 p->uid = _uid(pid);
438 p->cpu_id = st.psr;
439 p->start = st.start_time;
440 p->run_time = st.run_time;
441 state = _process_state_name(st.state);
442 snprintf(p->state, sizeof(p->state), "%s", state);
443 p->cpu_time = st.utime + st.stime;
444 p->priority = st.pri;
445 p->nice = st.nice;
446 p->numthreads = st.numthreads;
447 p->numfiles = _n_files(p);
448 if (st.flags & PF_KTHREAD) p->is_kernel = 1;
449 _mem_size(p);
450 _cmd_args(p, st.name, sizeof(st.name));
451
452 _proc_thread_info(p);
453
454 return p;
455}
456
457#endif
458
459#if defined(__OpenBSD__)
460
461static void
462_proc_get(Proc_Info *p, struct kinfo_proc *kp)
463{
464 static int pagesize = 0;
465 const char *state;
466
467 if (!pagesize) pagesize = getpagesize();
468
469 p->pid = kp->p_pid;
470 p->ppid = kp->p_ppid;
471 p->uid = kp->p_uid;
472 p->cpu_id = kp->p_cpuid;
473 p->start = kp->p_ustart_sec;
474 p->run_time = kp->p_uutime_sec + kp->p_ustime_sec +
475 (kp->p_uutime_usec / 1000000) + (kp->p_ustime_usec / 1000000);
476
477 state = _process_state_name(kp->p_stat);
478 snprintf(p->state, sizeof(p->state), "%s", state);
479 snprintf(p->wchan, sizeof(p->wchan), "%s", kp->p_wmesg);
480 p->cpu_time = kp->p_uticks + kp->p_sticks + kp->p_iticks;
481 p->mem_virt = p->mem_size = (MEMSIZE(kp->p_vm_tsize) * MEMSIZE(pagesize)) +
482 (MEMSIZE(kp->p_vm_dsize) * MEMSIZE(pagesize)) + (MEMSIZE(kp->p_vm_ssize) * MEMSIZE(pagesize));
483 p->mem_rss = MEMSIZE(kp->p_vm_rssize) * MEMSIZE(pagesize);
484 p->priority = kp->p_priority - PZERO;
485 p->nice = kp->p_nice - NZERO;
486 p->tid = kp->p_tid;
487}
488
489static void
490_kvm_get(Proc_Info *p, kvm_t *kern, struct kinfo_proc *kp)
491{
492 char **args;
493 char name[4096];
494
495 if ((args = kvm_getargv(kern, kp, sizeof(name)-1)))
496 {
497 Eina_Strbuf *buf = eina_strbuf_new();
498 for (int i = 0; args[i]; i++)
499 {
500 eina_strbuf_append(buf, args[i]);
501 if (args[i + 1])
502 eina_strbuf_append(buf, " ");
503 }
504 p->arguments = eina_strbuf_string_steal(buf);
505 eina_strbuf_free(buf);
506
507 if (args[0] && ecore_file_exists(args[0]))
508 p->command = strdup(ecore_file_file_get(args[0]));
509 }
510 struct kinfo_file *kf;
511 int n;
512
513 if ((kf = kvm_getfiles(kern, KERN_FILE_BYPID, -1, sizeof(struct kinfo_file), &n)))
514 {
515 for (int i = 0; i < n; i++)
516 {
517 if (kf[i].p_pid == kp->p_pid)
518 {
519 if (kf[i].fd_fd >= 0) p->numfiles++;
520 }
521 }
522 }
523
524 if (!p->command)
525 p->command = strdup(kp->p_comm);
526}
527
528Proc_Info *
529proc_info_by_pid(int pid)
530{
531 struct kinfo_proc *kp, *kpt;
532 kvm_t *kern;
533 char errbuf[_POSIX2_LINE_MAX];
534 int count, pid_count;
535
536 kern = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf);
537 if (!kern) return NULL;
538
539 kp = kvm_getprocs(kern, KERN_PROC_PID, pid, sizeof(*kp), &count);
540 if (!kp) return NULL;
541
542 if (count == 0) return NULL;
543
544 Proc_Info *p = calloc(1, sizeof(Proc_Info));
545 if (!p) return NULL;
546
547 _proc_get(p, kp);
548 _kvm_get(p, kern, kp);
549
550 kp = kvm_getprocs(kern, KERN_PROC_SHOW_THREADS, 0, sizeof(*kp), &pid_count);
551
552 for (int i = 0; i < pid_count; i++)
553 {
554 if (kp[i].p_pid != p->pid) continue;
555
556 kpt = &kp[i];
557
558 if (kpt->p_tid <= 0) continue;
559
560 Proc_Info *t = calloc(1, sizeof(Proc_Info));
561 if (!t) continue;
562
563 _proc_get(t, kpt);
564
565 t->tid = kpt->p_tid;
566 t->thread_name = strdup(kpt->p_comm);
567
568 p->threads = eina_list_append(p->threads, t);
569 }
570
571 p->numthreads = eina_list_count(p->threads);
572
573 kvm_close(kern);
574
575 return p;
576}
577
578static Eina_List *
579_process_list_openbsd_get(void)
580{
581 struct kinfo_proc *kps, *kp;
582 Proc_Info *p;
583 char errbuf[4096];
584 kvm_t *kern;
585 int pid_count;
586 Eina_List *list = NULL;
587
588 kern = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf);
589 if (!kern) return NULL;
590
591 kps = kvm_getprocs(kern, KERN_PROC_ALL, 0, sizeof(*kps), &pid_count);
592 if (!kps) return NULL;
593
594 for (int i = 0; i < pid_count; i++)
595 {
596 p = calloc(1, sizeof(Proc_Info));
597 if (!p) return NULL;
598
599 kp = &kps[i];
600
601 Proc_Info *p = proc_info_by_pid(kp->p_pid);
602 if (p)
603 list = eina_list_append(list, p);
604 }
605
606 kvm_close(kern);
607
608 return list;
609}
610
611#endif
612
613#if defined(__MacOS__)
614static void
615_cmd_get(Proc_Info *p, int pid)
616{
617 char *cp, *args, **argv;
618 int mib[3], argmax, argc;
619 size_t size;
620
621 mib[0] = CTL_KERN;
622 mib[1] = KERN_ARGMAX;
623
624 size = sizeof(argmax);
625
626 if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1) return;
627
628 mib[0] = CTL_KERN;
629 mib[1] = KERN_PROCARGS2;
630 mib[2] = pid;
631
632 size = (size_t) argmax;
633 args = malloc(argmax);
634 if (!args) return;
635
636 /* See libtop.c (top) for the origin of this comment, which is necessary as
637 * there is little other documentation...thanks Apple.
638 *
639 * Make a sysctl() call to get the raw argument space of the process.
640 * The layout is documented in start.s, which is part of the Csu
641 * project. In summary, it looks like:
642 *
643 * /---------------\ 0x00000000
644 * : :
645 * : :
646 * |---------------|
647 * | argc |
648 * |---------------|
649 * | arg[0] |
650 * |---------------|
651 * : :
652 * : :
653 * |---------------|
654 * | arg[argc - 1] |
655 * |---------------|
656 * | 0 |
657 * |---------------|
658 * | env[0] |
659 * |---------------|
660 * : :
661 * : :
662 * |---------------|
663 * | env[n] |
664 * |---------------|
665 * | 0 |
666 * |---------------| <-- Beginning of data returned by sysctl() is here.
667 * | argc |
668 * |---------------|
669 * | exec_path |
670 * |:::::::::::::::|
671 * | |
672 * | String area. |
673 * | |
674 * |---------------| <-- Top of stack.
675 * : :
676 * : :
677 * \---------------/ 0xffffffff
678 */
679
680 if (sysctl(mib, 3, args, &size, NULL, 0) == -1) return;
681
682 memcpy(&argc, args, sizeof(argc));
683 cp = args + sizeof(argc);
684
685 /* Skip exec path */
686 for (;cp < &args[size]; cp++)
687 {
688 if (*cp == '\0') break;
689 }
690
691 if (cp == &args[size]) return;
692
693 /* Skip any padded NULLs. */
694 for (;cp < &args[size]; cp++)
695 {
696 if (*cp == '\0') break;
697 }
698
699 if (cp == &args[size]) return;
700
701 argv = malloc(1 + argc * sizeof(char *));
702 if (!argv) return;
703
704 int i = 0;
705 argv[i] = cp;
706
707 for (cp = args + sizeof(int); cp < &args[size] && i < argc; cp++)
708 {
709 if (*cp == '\0')
710 {
711 while (*cp == '\0') cp++;
712 argv[i++] = cp;
713 }
714 }
715
716 if (i == 0) i++;
717
718 argv[i] = NULL;
719
720 p->command = strdup(basename(argv[0]));
721
722 Eina_Strbuf *buf = eina_strbuf_new();
723
724 for (i = 0; i < argc; i++)
725 eina_strbuf_append_printf(buf, "%s ", argv[i]);
726
727 if (argc > 0)
728 p->arguments = eina_strbuf_release(buf);
729 else
730 eina_strbuf_free(buf);
731
732 free(args);
733 free(argv);
734}
735
736static Proc_Info *
737_proc_pidinfo(size_t pid)
738{
739 const char *state;
740 struct proc_taskallinfo taskinfo;
741 int size = proc_pidinfo(pid, PROC_PIDTASKALLINFO, 0, &taskinfo, sizeof(taskinfo));
742 if (size != sizeof(taskinfo)) return NULL;
743
744 Proc_Info *p = calloc(1, sizeof(Proc_Info));
745 if (!p) return NULL;
746
747 p->pid = pid;
748 p->ppid = taskinfo.pbsd.pbi_ppid;
749 p->uid = taskinfo.pbsd.pbi_uid;
750 p->cpu_id = -1;
751 p->cpu_time = taskinfo.ptinfo.pti_total_user +
752 taskinfo.ptinfo.pti_total_system;
753 p->cpu_time /= 10000000;
754 p->start = taskinfo.pbsd.pbi_start_tvsec;
755 state = _process_state_name(taskinfo.pbsd.pbi_status);
756 snprintf(p->state, sizeof(p->state), "%s", state);
757 p->mem_size = p->mem_virt = taskinfo.ptinfo.pti_virtual_size;
758 p->mem_rss = taskinfo.ptinfo.pti_resident_size;
759 p->priority = taskinfo.ptinfo.pti_priority;
760 p->nice = taskinfo.pbsd.pbi_nice;
761 p->numthreads = taskinfo.ptinfo.pti_threadnum;
762 _cmd_get(p, pid);
763
764 return p;
765}
766
767static Eina_List *
768_process_list_macos_fallback_get(void)
769{
770 Eina_List *list = NULL;
771
772 for (int i = 1; i <= PID_MAX; i++)
773 {
774 Proc_Info *p = _proc_pidinfo(i);
775 if (p)
776 list = eina_list_append(list, p);
777 }
778
779 return list;
780}
781
782static Eina_List *
783_process_list_macos_get(void)
784{
785 Eina_List *list = NULL;
786 pid_t *pids = NULL;
787 int size, pid_count;
788
789 size = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0);
790 if (size == -1)
791 return _process_list_macos_fallback_get();
792
793 pids = malloc(size * sizeof(pid_t));
794 if (!pids) return NULL;
795
796 size = proc_listpids(PROC_ALL_PIDS, 0, pids, size * sizeof(pid_t));
797 if (size == -1)
798 {
799 free(pids);
800 return _process_list_macos_fallback_get();
801 }
802
803 pid_count = size / sizeof(pid_t);
804 for (int i = 0; i < pid_count; i++)
805 {
806 pid_t pid = pids[i];
807 Proc_Info *p = _proc_pidinfo(pid);
808 if (p)
809 list = eina_list_append(list, p);
810 }
811
812 free(pids);
813
814 return list;
815}
816
817Proc_Info *
818proc_info_by_pid(int pid)
819{
820 const char *state;
821 struct proc_taskallinfo taskinfo;
822 struct proc_workqueueinfo workqueue;
823 size_t size;
824
825 size = proc_pidinfo(pid, PROC_PIDTASKALLINFO, 0, &taskinfo, sizeof(taskinfo));
826 if (size != sizeof(taskinfo))
827 return NULL;
828
829 size = proc_pidinfo(pid, PROC_PIDWORKQUEUEINFO, 0, &workqueue, sizeof(workqueue));
830 if (size != sizeof(workqueue))
831 memset(&workqueue, 0, sizeof(struct proc_workqueueinfo));
832
833 Proc_Info *p = calloc(1, sizeof(Proc_Info));
834 if (!p) return NULL;
835
836 p->pid = pid;
837 p->uid = taskinfo.pbsd.pbi_uid;
838 p->ppid = taskinfo.pbsd.pbi_ppid;
839 p->cpu_id = workqueue.pwq_nthreads;
840 p->cpu_time = taskinfo.ptinfo.pti_total_user +
841 taskinfo.ptinfo.pti_total_system;
842 p->cpu_time /= 10000000;
843 p->start = taskinfo.pbsd.pbi_start_tvsec;
844 state = _process_state_name(taskinfo.pbsd.pbi_status);
845 snprintf(p->state, sizeof(p->state), "%s", state);
846 p->mem_size = p->mem_virt = taskinfo.ptinfo.pti_virtual_size;
847 p->mem_rss = taskinfo.ptinfo.pti_resident_size;
848 p->priority = taskinfo.ptinfo.pti_priority;
849 p->nice = taskinfo.pbsd.pbi_nice;
850 p->numthreads = taskinfo.ptinfo.pti_threadnum;
851 _cmd_get(p, pid);
852
853 return p;
854}
855
856#endif
857
858#if defined(__FreeBSD__) || defined(__DragonFly__)
859
860static int
861_pid_max(void)
862{
863 size_t len;
864 static int pid_max = 0;
865
866 if (pid_max != 0) return pid_max;
867
868 len = sizeof(pid_max);
869 if (sysctlbyname("kern.pid_max", &pid_max, &len, NULL, 0) == -1)
870 {
871#if defined(__FreeBSD__)
872 pid_max = 99999;
873#elif defined(__DragonFly__)
874 pid_max = 999999;
875#else
876 pid_max = PID_MAX;
877#endif
878 }
879
880 return pid_max;
881}
882
883static void
884_kvm_get(Proc_Info *p, struct kinfo_proc *kp)
885{
886 kvm_t * kern;
887 char name[4096];
888 Eina_Bool have_command = 0;
889
890 kern = kvm_open(NULL, "/dev/mem", NULL, O_RDONLY, "kvm_open");
891 if (!kern) goto nokvm;
892 char **args;
893 if ((args = kvm_getargv(kern, kp, sizeof(name)-1)) && (args[0]))
894 {
895 char *base = strdup(args[0]);
896 if (base)
897 {
898 char *spc = strchr(base, ' ');
899 if (spc) *spc = '\0';
900
901 if (ecore_file_exists(base))
902 {
903 snprintf(name, sizeof(name), "%s", basename(base));
904 have_command = 1;
905 }
906 free(base);
907 }
908 Eina_Strbuf *buf = eina_strbuf_new();
909 for (int i = 0; args[i] != NULL; i++)
910 {
911 eina_strbuf_append(buf, args[i]);
912 if (args[i + 1])
913 eina_strbuf_append(buf, " ");
914 }
915 p->arguments = eina_strbuf_string_steal(buf);
916 eina_strbuf_free(buf);
917 }
918
919 struct filedesc filed;
920 struct fdescenttbl *fdt;
921 unsigned int n;
922
923 if (!kvm_read(kern, (unsigned long)kp->ki_fd, &filed, sizeof(filed)))
924 goto kvmerror;
925
926 if (!kvm_read(kern, (unsigned long)filed.fd_files, &n, sizeof(n)))
927 goto kvmerror;
928
929 unsigned int size = sizeof(*fdt) + n * sizeof(struct filedescent);
930 fdt = malloc(size);
931 if (fdt)
932 {
933 if (kvm_read(kern, (unsigned long)filed.fd_files, fdt, size))
934 {
935 for (int i = 0; i < n; i++)
936 {
937 if (!fdt->fdt_ofiles[i].fde_file) continue;
938 p->numfiles++;
939 }
940 }
941 free(fdt);
942 }
943
944kvmerror:
945 if (kern)
946 kvm_close(kern);
947nokvm:
948 if (!have_command)
949 snprintf(name, sizeof(name), "%s", kp->ki_comm);
950
951 p->command = strdup(name);
952}
953
954static Proc_Info *
955_proc_thread_info(struct kinfo_proc *kp, Eina_Bool is_thread)
956{
957 struct rusage *usage;
958 const char *state;
959 Proc_Info *p;
960 static int pagesize = 0;
961
962 if (!pagesize) pagesize = getpagesize();
963
964 p = calloc(1, sizeof(Proc_Info));
965 if (!p) return NULL;
966
967 p->pid = kp->ki_pid;
968 p->ppid = kp->ki_ppid;
969 p->uid = kp->ki_uid;
970
971 if (!is_thread)
972 _kvm_get(p, kp);
973
974 p->cpu_id = kp->ki_oncpu;
975 if (p->cpu_id == -1)
976 p->cpu_id = kp->ki_lastcpu;
977
978 usage = &kp->ki_rusage;
979
980 p->cpu_time = ((usage->ru_utime.tv_sec * 1000000) + usage->ru_utime.tv_usec +
981 (usage->ru_stime.tv_sec * 1000000) + usage->ru_stime.tv_usec) / 10000;
982 p->run_time = (kp->ki_runtime + 500000) / 1000000;
983 state = _process_state_name(kp->ki_stat);
984 snprintf(p->state, sizeof(p->state), "%s", state);
985 snprintf(p->wchan, sizeof(p->wchan), "%s", kp->ki_wmesg);
986 p->mem_virt = kp->ki_size;
987 p->mem_rss = MEMSIZE(kp->ki_rssize) * MEMSIZE(pagesize);
988 p->start = kp->ki_start.tv_sec;
989 p->mem_size = p->mem_virt;
990 p->nice = kp->ki_nice - NZERO;
991 p->priority = kp->ki_pri.pri_level - PZERO;
992 p->numthreads = kp->ki_numthreads;
993
994 p->tid = kp->ki_tid;
995 p->thread_name = strdup(kp->ki_tdname);
996 if (kp->ki_flag & P_KPROC) p->is_kernel = 1;
997
998 return p;
999}
1000
1001static Eina_List *
1002_process_list_freebsd_fallback_get(void)
1003{
1004 Eina_List *list;
1005 struct kinfo_proc kp;
1006 int mib[4];
1007 size_t len;
1008 static int pid_max;
1009
1010 pid_max = _pid_max();
1011
1012 list = NULL;
1013
1014 len = sizeof(int);
1015 if (sysctlnametomib("kern.proc.pid", mib, &len) == -1)
1016 return NULL;
1017
1018 for (int i = 1; i <= pid_max; i++)
1019 {
1020 mib[3] = i;
1021 len = sizeof(kp);
1022 if (sysctl(mib, 4, &kp, &len, NULL, 0) == -1)
1023 continue;
1024
1025 if (kp.ki_flag & P_KPROC && !proc_info_kthreads_show_get())
1026 continue;
1027
1028 Proc_Info *p = _proc_thread_info(&kp, 0);
1029 if (p)
1030 list = eina_list_append(list, p);
1031 }
1032
1033 return list;
1034}
1035
1036static Eina_List *
1037_process_list_freebsd_get(void)
1038{
1039 kvm_t *kern;
1040 Eina_List *list = NULL;
1041 struct kinfo_proc *kps, *kp;
1042 char errbuf[_POSIX2_LINE_MAX];
1043 int pid_count;
1044
1045 kern = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
1046 if (!kern)
1047 return _process_list_freebsd_fallback_get();
1048
1049 kps = kvm_getprocs(kern, KERN_PROC_PROC, 0, &pid_count);
1050 if (!kps)
1051 {
1052 kvm_close(kern);
1053 return _process_list_freebsd_fallback_get();
1054 }
1055
1056 for (int i = 0; i < pid_count; i++)
1057 {
1058 if (kps[i].ki_flag & P_KPROC && !proc_info_kthreads_show_get())
1059 continue;
1060
1061 kp = &kps[i];
1062
1063 Proc_Info *p = _proc_thread_info(kp, 0);
1064 if (p)
1065 list = eina_list_append(list, p);
1066 }
1067
1068 kvm_close(kern);
1069
1070 return list;
1071}
1072
1073static Proc_Info *
1074_proc_info_by_pid_fallback(int pid)
1075{
1076 struct kinfo_proc kp;
1077 int mib[4];
1078 size_t len;
1079
1080 len = sizeof(int);
1081 if (sysctlnametomib("kern.proc.pid", mib, &len) == -1)
1082 return NULL;
1083
1084 mib[3] = pid;
1085
1086 len = sizeof(kp);
1087 if (sysctl(mib, 4, &kp, &len, NULL, 0) == -1)
1088 return NULL;
1089
1090 Proc_Info *p = _proc_thread_info(&kp, 0);
1091
1092 return p;
1093}
1094
1095Proc_Info *
1096proc_info_by_pid(int pid)
1097{
1098 kvm_t *kern;
1099 struct kinfo_proc *kps, *kp;
1100 char errbuf[_POSIX2_LINE_MAX];
1101 int pid_count;
1102
1103 kern = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
1104 if (!kern)
1105 return _proc_info_by_pid_fallback(pid);
1106
1107 kps = kvm_getprocs(kern, KERN_PROC_ALL, 0, &pid_count);
1108 if (!kps)
1109 {
1110 kvm_close(kern);
1111 return _proc_info_by_pid_fallback(pid);
1112 }
1113
1114 Proc_Info *p = NULL;
1115
1116 // XXX: run_time does not include interrupts.
1117
1118 for (int i = 0; i < pid_count; i++)
1119 {
1120 if (kps[i].ki_flag & P_KPROC && !proc_info_kthreads_show_get())
1121 continue;
1122 if (kps[i].ki_pid != pid)
1123 continue;
1124
1125 kp = &kps[i];
1126 Proc_Info *t = _proc_thread_info(kp, 1);
1127 if (!p)
1128 {
1129 p = _proc_thread_info(kp, 0);
1130 p->cpu_time = 0;
1131 }
1132
1133 p->cpu_time += t->cpu_time;
1134 p->threads = eina_list_append(p->threads, t);
1135 }
1136
1137 kvm_close(kern);
1138
1139 if (!p) return _proc_info_by_pid_fallback(pid);
1140
1141 return p;
1142}
1143#endif
1144
1145void
1146proc_info_free(Proc_Info *proc)
1147{
1148 Proc_Info *t;
1149
1150 if (!proc) return;
1151
1152 EINA_LIST_FREE(proc->threads, t)
1153 proc_info_free(t);
1154
1155 if (proc->command)
1156 free(proc->command);
1157 if (proc->arguments)
1158 free(proc->arguments);
1159 if (proc->thread_name)
1160 free(proc->thread_name);
1161
1162 free(proc);
1163}
1164
1165Eina_List *
1166proc_info_all_get(void)
1167{
1168 Eina_List *processes;
1169
1170#if defined(__linux__)
1171 processes = _process_list_linux_get();
1172#elif defined(__FreeBSD__) || defined(__DragonFly__)
1173 processes = _process_list_freebsd_get();
1174#elif defined(__MacOS__)
1175 processes = _process_list_macos_get();
1176#elif defined(__OpenBSD__)
1177 processes = _process_list_openbsd_get();
1178#else
1179 processes = NULL;
1180#endif
1181
1182 return processes;
1183}
1184
1185static Eina_Bool
1186_child_add(Eina_List *parents, Proc_Info *child)
1187{
1188 Eina_List *l;
1189 Proc_Info *parent;
1190
1191 EINA_LIST_FOREACH(parents, l, parent)
1192 {
1193 if (parent->pid == child->ppid)
1194 {
1195 parent->children = eina_list_append(parent->children, child);
1196 return 1;
1197 }
1198 }
1199
1200 return 0;
1201}
1202
1203Eina_List *
1204proc_info_all_children_get()
1205{
1206 Proc_Info *proc;
1207 Eina_List *l;
1208 Eina_List *procs;
1209
1210 procs = proc_info_all_get();
1211
1212 EINA_LIST_FOREACH(procs, l, proc)
1213 {
1214 int ok =_child_add(procs, proc);
1215 (void) ok;
1216 }
1217
1218 return procs;
1219}
1220
1221Eina_List *
1222_append_wanted(Eina_List *wanted, Eina_List *tree)
1223{
1224 Eina_List *l;
1225 Proc_Info *parent;
1226
1227 EINA_LIST_FOREACH(tree, l, parent)
1228 {
1229 wanted = eina_list_append(wanted, parent);
1230 if (parent->children)
1231 wanted = _append_wanted(wanted, parent->children);
1232 }
1233 return wanted;
1234}
1235
1236Eina_List *
1237proc_info_pid_children_get(pid_t pid)
1238{
1239 Proc_Info *proc;
1240 Eina_List *l, *procs, *wanted = NULL;
1241
1242 procs = proc_info_all_children_get();
1243
1244 EINA_LIST_FOREACH(procs, l, proc)
1245 {
1246 if (!wanted && proc->pid == pid)
1247 {
1248 wanted = eina_list_append(wanted, proc);
1249 if (proc->children)
1250 wanted = _append_wanted(wanted, proc->children);
1251 }
1252 }
1253
1254 EINA_LIST_FREE(procs, proc)
1255 {
1256 if (!eina_list_data_find(wanted, proc))
1257 {
1258 proc_info_free(proc);
1259 }
1260 }
1261
1262 return wanted;
1263}
1264
1265void
1266proc_info_all_children_free(Eina_List *pstree)
1267{
1268 Proc_Info *parent, *child;
1269
1270 EINA_LIST_FREE(pstree, parent)
1271 {
1272 EINA_LIST_FREE(parent->children, child)
1273 proc_info_pid_children_free(child);
1274 proc_info_free(parent);
1275 }
1276}
1277
1278void
1279proc_info_pid_children_free(Proc_Info *proc)
1280{
1281 Proc_Info *child;
1282
1283 EINA_LIST_FREE(proc->children, child)
1284 proc_info_free(child);
1285
1286 proc_info_free(proc);
1287}
1288
1289int
1290proc_sort_by_pid(const void *p1, const void *p2)
1291{
1292 const Proc_Info *inf1, *inf2;
1293
1294 inf1 = p1; inf2 = p2;
1295
1296 return inf1->pid - inf2->pid;
1297}
1298
1299int
1300proc_sort_by_uid(const void *p1, const void *p2)
1301{
1302 const Proc_Info *inf1, *inf2;
1303
1304 inf1 = p1; inf2 = p2;
1305
1306 return inf1->uid - inf2->uid;
1307}
1308
1309int
1310proc_sort_by_nice(const void *p1, const void *p2)
1311{
1312 const Proc_Info *inf1, *inf2;
1313
1314 inf1 = p1; inf2 = p2;
1315
1316 return inf1->nice - inf2->nice;
1317}
1318
1319int
1320proc_sort_by_pri(const void *p1, const void *p2)
1321{
1322 const Proc_Info *inf1, *inf2;
1323
1324 inf1 = p1; inf2 = p2;
1325
1326 return inf1->priority - inf2->priority;
1327}
1328
1329int
1330proc_sort_by_cpu(const void *p1, const void *p2)
1331{
1332 const Proc_Info *inf1, *inf2;
1333
1334 inf1 = p1; inf2 = p2;
1335
1336 return inf1->cpu_id - inf2->cpu_id;
1337}
1338
1339int
1340proc_sort_by_threads(const void *p1, const void *p2)
1341{
1342 const Proc_Info *inf1, *inf2;
1343
1344 inf1 = p1; inf2 = p2;
1345
1346 return inf1->numthreads - inf2->numthreads;
1347}
1348
1349int
1350proc_sort_by_files(const void *p1, const void *p2)
1351{
1352 const Proc_Info *inf1, *inf2;
1353
1354 inf1 = p1; inf2 = p2;
1355
1356 return inf1->numfiles - inf2->numfiles;
1357}
1358
1359int
1360proc_sort_by_size(const void *p1, const void *p2)
1361{
1362 const Proc_Info *inf1, *inf2;
1363 int64_t size1, size2;
1364
1365 inf1 = p1; inf2 = p2;
1366
1367 size1 = inf1->mem_size;
1368 size2 = inf2->mem_size;
1369
1370 if (size1 > size2)
1371 return 1;
1372 if (size1 < size2)
1373 return -1;
1374
1375 return 0;
1376}
1377
1378int
1379proc_sort_by_virt(const void *p1, const void *p2)
1380{
1381 const Proc_Info *inf1, *inf2;
1382 int64_t size1, size2;
1383
1384 inf1 = p1; inf2 = p2;
1385
1386 size1 = inf1->mem_virt;
1387 size2 = inf2->mem_virt;
1388
1389 if (size1 > size2)
1390 return 1;
1391 if (size1 < size2)
1392 return -1;
1393
1394 return 0;
1395}
1396
1397int
1398proc_sort_by_rss(const void *p1, const void *p2)
1399{
1400 const Proc_Info *inf1, *inf2;
1401 int64_t size1, size2;
1402
1403 inf1 = p1; inf2 = p2;
1404
1405 size1 = inf1->mem_rss;
1406 size2 = inf2->mem_rss;
1407
1408 if (size1 > size2)
1409 return 1;
1410 if (size1 < size2)
1411 return -1;
1412
1413 return 0;
1414}
1415
1416int
1417proc_sort_by_shared(const void *p1, const void *p2)
1418{
1419 const Proc_Info *inf1, *inf2;
1420 int64_t size1, size2;
1421
1422 inf1 = p1; inf2 = p2;
1423
1424 size1 = inf1->mem_shared;
1425 size2 = inf2->mem_shared;
1426
1427 if (size1 > size2)
1428 return 1;
1429 if (size1 < size2)
1430 return -1;
1431
1432 return 0;
1433}
1434
1435int
1436proc_sort_by_time(const void *p1, const void *p2)
1437{
1438 const Proc_Info *inf1, *inf2;
1439 int64_t t1, t2;
1440
1441 inf1 = p1; inf2 = p2;
1442
1443 t1 = inf1->run_time;
1444 t2 = inf2->run_time;
1445
1446 if (t1 > t2)
1447 return 1;
1448 if (t1 < t2)
1449 return -1;
1450
1451 return 0;
1452}
1453
1454int
1455proc_sort_by_cpu_usage(const void *p1, const void *p2)
1456{
1457 const Proc_Info *inf1, *inf2;
1458 double one, two;
1459
1460 inf1 = p1; inf2 = p2;
1461
1462 one = inf1->cpu_usage;
1463 two = inf2->cpu_usage;
1464
1465 if (one > two)
1466 return 1;
1467 else if (one < two)
1468 return -1;
1469 else return 0;
1470}
1471
1472int
1473proc_sort_by_cmd(const void *p1, const void *p2)
1474{
1475 const Proc_Info *inf1, *inf2;
1476
1477 inf1 = p1; inf2 = p2;
1478
1479 return strcasecmp(inf1->command, inf2->command);
1480}
1481
1482int
1483proc_sort_by_state(const void *p1, const void *p2)
1484{
1485 const Proc_Info *inf1, *inf2;
1486
1487 inf1 = p1; inf2 = p2;
1488
1489 return strcmp(inf1->state, inf2->state);
1490}
1491
1492int
1493proc_sort_by_age(const void *p1, const void *p2)
1494{
1495 const Proc_Info *c1 = p1, *c2 = p2;
1496
1497 return c1->start - c2->start;
1498}
1499
diff --git a/src/bin/next/process.h b/src/bin/next/process.h
new file mode 100644
index 0000000..9f3f795
--- /dev/null
+++ b/src/bin/next/process.h
@@ -0,0 +1,119 @@
1#ifndef __PROC_H__
2#define __PROC_H__
3
4#include <Eina.h>
5#include <stdint.h>
6#include <unistd.h>
7
8#if !defined(PID_MAX)
9# define PID_MAX 99999
10#endif
11
12typedef struct _Proc_Info
13{
14 pid_t pid;
15 pid_t ppid;
16 uid_t uid;
17 int8_t nice;
18 int8_t priority;
19 int cpu_id;
20 int32_t numthreads;
21 int64_t cpu_time;
22 double cpu_usage;
23 int64_t run_time;
24 int64_t start;
25
26 uint64_t mem_size;
27 uint64_t mem_virt;
28 uint64_t mem_rss;
29 uint64_t mem_shared;
30
31 char *command;
32 char *arguments;
33 char state[32];
34 char wchan[32];
35
36 Eina_List *fds;
37 int numfiles;
38
39 short is_kernel;
40 int tid;
41 char *thread_name;
42
43 Eina_List *threads;
44 Eina_List *children;
45} Proc_Info;
46
47Eina_List *
48proc_info_all_get(void);
49
50Proc_Info *
51proc_info_by_pid(int pid);
52
53void
54proc_info_free(Proc_Info *proc);
55
56void
57proc_info_kthreads_show_set(Eina_Bool enabled);
58
59Eina_Bool
60proc_info_kthreads_show_get(void);
61
62Eina_List *
63proc_info_all_children_get(void);
64
65Eina_List *
66proc_info_pid_children_get(pid_t pid);
67
68void
69proc_info_pid_children_free(Proc_Info *procs);
70
71int
72proc_sort_by_pid(const void *p1, const void *p2);
73
74int
75proc_sort_by_uid(const void *p1, const void *p2);
76
77int
78proc_sort_by_nice(const void *p1, const void *p2);
79
80int
81proc_sort_by_pri(const void *p1, const void *p2);
82
83int
84proc_sort_by_cpu(const void *p1, const void *p2);
85
86int
87proc_sort_by_threads(const void *p1, const void *p2);
88
89int
90proc_sort_by_files(const void *p1, const void *p2);
91
92int
93proc_sort_by_size(const void *p1, const void *p2);
94
95int
96proc_sort_by_virt(const void *p1, const void *p2);
97
98int
99proc_sort_by_rss(const void *p1, const void *p2);
100
101int
102proc_sort_by_shared(const void *p1, const void *p2);
103
104int
105proc_sort_by_time(const void *p1, const void *p2);
106
107int
108proc_sort_by_cpu_usage(const void *p1, const void *p2);
109
110int
111proc_sort_by_cmd(const void *p1, const void *p2);
112
113int
114proc_sort_by_state(const void *p1, const void *p2);
115
116int
117proc_sort_by_age(const void *p1, const void *p2);
118
119#endif