pstree.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /* vim: tabstop=4 shiftwidth=4 noexpandtab
  2. * This file is part of ToaruOS and is released under the terms
  3. * of the NCSA / University of Illinois License - see LICENSE.md
  4. * Copyright (C) 2014-2018 K. Lange
  5. *
  6. * pstree - Display a tree of running process
  7. *
  8. */
  9. #include <sys/stat.h>
  10. #include <fcntl.h>
  11. #include <stdint.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <unistd.h>
  16. #include <dirent.h>
  17. #include <toaru/list.h>
  18. #include <toaru/tree.h>
  19. typedef struct process {
  20. int pid;
  21. int ppid;
  22. int tgid;
  23. char name[100];
  24. char path[200];
  25. } p_t;
  26. #define LINE_LEN 4096
  27. p_t * build_entry(struct dirent * dent) {
  28. char tmp[256];
  29. FILE * f;
  30. char line[LINE_LEN];
  31. sprintf(tmp, "/proc/%s/status", dent->d_name);
  32. f = fopen(tmp, "r");
  33. p_t * proc = malloc(sizeof(p_t));
  34. while (fgets(line, LINE_LEN, f) != NULL) {
  35. char * n = strstr(line,"\n");
  36. if (n) { *n = '\0'; }
  37. char * tab = strstr(line,"\t");
  38. if (tab) {
  39. *tab = '\0';
  40. tab++;
  41. }
  42. if (strstr(line, "Pid:") == line) {
  43. proc->pid = atoi(tab);
  44. } else if (strstr(line, "PPid:") == line) {
  45. proc->ppid = atoi(tab);
  46. } else if (strstr(line, "Tgid:") == line) {
  47. proc->tgid = atoi(tab);
  48. } else if (strstr(line, "Name:") == line) {
  49. strcpy(proc->name, tab);
  50. } else if (strstr(line, "Path:") == line) {
  51. strcpy(proc->path, tab);
  52. }
  53. }
  54. if (strstr(proc->name,"python") == proc->name) {
  55. char * name = proc->path + strlen(proc->path) - 1;
  56. while (1) {
  57. if (*name == '/') {
  58. name++;
  59. break;
  60. }
  61. if (name == proc->name) break;
  62. name--;
  63. }
  64. memcpy(proc->name, name, strlen(name)+1);
  65. }
  66. if (proc->tgid != proc->pid) {
  67. char tmp[100] = {0};
  68. sprintf(tmp, "{%s}", proc->name);
  69. memcpy(proc->name, tmp, strlen(tmp)+1);
  70. }
  71. fclose(f);
  72. return proc;
  73. }
  74. uint8_t find_pid(void * proc_v, void * pid_v) {
  75. p_t * p = proc_v;
  76. pid_t i = (pid_t)pid_v;
  77. return (uint8_t)(p->pid == i);
  78. }
  79. void print_process_tree_node(tree_node_t * node, size_t depth, int indented, int more, char lines[]) {
  80. p_t * proc = node->value;
  81. for (int i = 0; i < (int)strlen(proc->name)+3; ++i) {
  82. lines[depth+i] = 0;
  83. }
  84. if (!indented && depth) {
  85. if (more) {
  86. printf("─┬─");
  87. lines[depth+1] = 1;
  88. } else {
  89. printf("───");
  90. }
  91. depth += 3;
  92. } else if (depth) {
  93. for (int i = 0; i < (int)depth; ++i) {
  94. if (lines[i]) {
  95. printf("│");
  96. } else {
  97. printf(" ");
  98. }
  99. }
  100. if (more) {
  101. printf(" ├─");
  102. lines[depth+1] = 1;
  103. } else {
  104. printf(" └─");
  105. }
  106. depth += 3;
  107. }
  108. printf(proc->name);
  109. if (!node->children->length) {
  110. printf("\n");
  111. } else {
  112. depth += strlen(proc->name);
  113. int t = 0;
  114. foreach(child, node->children) {
  115. /* Recursively print the children */
  116. print_process_tree_node(child->value, depth, !!(t), ((t+1)!=(int)node->children->length), lines);
  117. t++;
  118. }
  119. }
  120. for (int i = 0; i < (int)strlen(proc->name)+3; ++i) {
  121. lines[depth+i] = 0;
  122. }
  123. }
  124. int main (int argc, char * argv[]) {
  125. /* Open the directory */
  126. DIR * dirp = opendir("/proc");
  127. /* Read the entries in the directory */
  128. tree_t * procs = tree_create();
  129. struct dirent * ent = readdir(dirp);
  130. while (ent != NULL) {
  131. if (ent->d_name[0] >= '0' && ent->d_name[0] <= '9') {
  132. p_t * proc = build_entry(ent);
  133. if (proc->ppid == 0 && proc->pid == 1) {
  134. tree_set_root(procs, proc);
  135. } else {
  136. tree_node_t * parent = tree_find(procs,(void *)proc->ppid,find_pid);
  137. if (parent) {
  138. tree_node_insert_child(procs, parent, proc);
  139. }
  140. }
  141. }
  142. ent = readdir(dirp);
  143. }
  144. closedir(dirp);
  145. char lines[500] = {0};
  146. print_process_tree_node(procs->root, 0, 0, 0, lines);
  147. return 0;
  148. }
  149. /*
  150. * vim: tabstop=4
  151. * vim: shiftwidth=4
  152. * vim: noexpandtab
  153. */