myps.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. #define _POSIX_C_SOURCE 200809L
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <dirent.h>
  5. #include <string.h>
  6. #include <sys/types.h>
  7. #include <sys/stat.h>
  8. #include <unistd.h>
  9. #include <fcntl.h>
  10. #include <pwd.h>
  11. #include "error.h"
  12. #include "color.h"
  13. #include "constante.h"
  14. typedef struct{
  15. char* path; //Chemin vers le dossier du processus /./proc/[pid]/
  16. int pid; //Le pid
  17. int uid; //Le uid du proprietaire
  18. char state; //L'etat
  19. char* cmd; //La commande
  20. }processus;
  21. /**
  22. * Indique si une string est un nombre
  23. * @param char* Le string
  24. * @return Vrai/Faux
  25. */
  26. boolean is_numeric(const char* str){
  27. while(*str){
  28. if(*str < '0' || *str > '9'){
  29. return false;
  30. }
  31. str++;
  32. }
  33. return true;
  34. }
  35. /**
  36. * Tri les processus par pid croissant
  37. * @param processus** Le tableau de processus
  38. */
  39. void sort_pid(processus** proc, int size){
  40. processus* tmp;
  41. int index;
  42. for(int i = 1; i < size; i++){
  43. index = i;
  44. while(index > 0 && proc[index]->pid < proc[index - 1]->pid){
  45. tmp = proc[index];
  46. proc[index] = proc[index - 1];
  47. proc[index - 1] = tmp;
  48. index--;
  49. }
  50. }
  51. }
  52. /**
  53. * Liste les processus actifs
  54. * @param int* Le nombre de processus actif
  55. * @return processus** La liste
  56. */
  57. processus** list_process(int* nb){
  58. struct dirent** dir;
  59. struct stat info;
  60. int nbRes;
  61. int length, compteur = 0;
  62. char* path;
  63. processus** result;
  64. //Recup les dossiers
  65. if((nbRes = scandir("/./proc/", &dir, 0, alphasort)) == ERR){
  66. addperror("Impossible de scanner le dossier");
  67. return NULL;
  68. }
  69. //Compte le nombre de resultat
  70. for(int i = 0; i < nbRes; i++){
  71. //Création chemin
  72. length = strlen(dir[i]->d_name) + 10;
  73. path = malloc(sizeof(char) * length);
  74. memset(path, 0, length);
  75. snprintf(path, length, "/./proc/%s/", dir[i]->d_name);
  76. //Recup info
  77. if(stat(path, &info) == ERR){
  78. //Pas un dossier
  79. continue;
  80. }
  81. //Ne regarde que les dossiers dont le nom est un nombre
  82. if(S_ISDIR(info.st_mode) && is_numeric(dir[i]->d_name)){
  83. compteur++;
  84. }
  85. free(path);
  86. }
  87. //Allocation resultat
  88. result = malloc(sizeof(processus*) * compteur);
  89. //Ajout des resultats
  90. compteur = 0;
  91. for(int i = 0; i < nbRes; i++){
  92. //Création chemin
  93. length = strlen(dir[i]->d_name) + 10;
  94. path = malloc(sizeof(char) * length);
  95. memset(path, 0, length);
  96. snprintf(path, length, "/./proc/%s/", dir[i]->d_name);
  97. //Recup info
  98. if(stat(path, &info) == ERR){
  99. //Pas un dossier
  100. continue;
  101. }
  102. //Ne regarde que les dossiers dont le nom est un nombre
  103. if(S_ISDIR(info.st_mode) && is_numeric(dir[i]->d_name)){
  104. result[compteur] = malloc(sizeof(processus));
  105. result[compteur]->path = path;
  106. result[compteur]->pid = atoi(dir[i]->d_name);
  107. result[compteur]->uid = info.st_uid;
  108. compteur++;
  109. continue;
  110. }
  111. free(path);
  112. }
  113. //Libere memoire
  114. while(nbRes--){
  115. free(dir[nbRes]);
  116. }
  117. free(dir);
  118. //Retour
  119. if(nb != NULL){
  120. *nb = compteur;
  121. }
  122. return result;
  123. }
  124. /**
  125. * Lecture du fichier status d'un processus
  126. * @param processus* Le processus
  127. * @return Reussite
  128. */
  129. boolean read_status(processus* proc){
  130. char* file;
  131. int length, fd;
  132. char buffer;
  133. //Recup nom du fichier
  134. length = strlen(proc->path) + 7;
  135. file = malloc(sizeof(char) * length);
  136. memset(file, 0, length);
  137. snprintf(file, length, "%sstatus", proc->path);
  138. //Ouverture fichier
  139. fd = open(file, O_RDONLY);
  140. if(fd == ERR){
  141. free(file);
  142. return false;
  143. }
  144. free(file);
  145. //Lecture jusqu'a l'etat
  146. int i = 0;
  147. while(i < 2){
  148. if(read(fd, &buffer, sizeof(char)) == ERR){
  149. return false;
  150. }
  151. if(buffer == '\n'){
  152. i++;
  153. }
  154. }
  155. while(buffer != ' '){
  156. if(read(fd, &buffer, sizeof(char)) == ERR){
  157. return false;
  158. }
  159. }
  160. while(buffer == ' '){
  161. if(read(fd, &buffer, sizeof(char)) == ERR){
  162. return false;
  163. }
  164. }
  165. if(read(fd, &buffer, sizeof(char)) == ERR){
  166. return false;
  167. }
  168. proc->state = buffer;
  169. //Fermeture
  170. if(close(fd) == ERR){
  171. //Rien de particulier
  172. }
  173. return true;
  174. }
  175. /**
  176. * Lecture du fichier comm d'un processus
  177. * @param processus* Le processus
  178. * @return Reussite
  179. */
  180. boolean read_comm(processus* proc){
  181. char* file;
  182. int length, fd;
  183. int size = 0;
  184. char buf = ' ';
  185. char* buffer;
  186. boolean first = true;
  187. //Recup nom du fichier
  188. length = strlen(proc->path) + 5;
  189. file = malloc(sizeof(char) * length);
  190. memset(file, 0, length);
  191. snprintf(file, length, "%scomm", proc->path);
  192. //Ouverture fichier
  193. fd = open(file, O_RDONLY);
  194. if(fd == ERR){
  195. free(file);
  196. return false;
  197. }
  198. free(file);
  199. //Compte la taille du mot
  200. while(buf != '\n' && buf != '\0' && buf != EOF){
  201. if(read(fd, &buf, sizeof(char)) == ERR){
  202. return false;
  203. }
  204. //Au 1er tour
  205. if(first){
  206. //Si fichier vide
  207. if(buf == ' '){
  208. if(close(fd) == ERR){
  209. //Rien de particulier
  210. }
  211. return false;
  212. }
  213. first = false;
  214. }
  215. size++;
  216. }
  217. size--;
  218. //Revient au debut
  219. if(lseek(fd, 0L, SEEK_SET) == ERR){
  220. return false;
  221. }
  222. //Lecture commande
  223. buffer = malloc(sizeof(char) * (size + 3));
  224. memset(buffer, 0, size + 3);
  225. buffer[0] = '[';
  226. if(read(fd, buffer + 1, size) == ERR){
  227. return false;
  228. }
  229. buffer[strlen(buffer)] = ']';
  230. proc->cmd = buffer;
  231. //Fermeture
  232. if(close(fd) == ERR){
  233. //Rien de particulier
  234. }
  235. return true;
  236. }
  237. /**
  238. * Lecture du fichier cmdline d'un processus
  239. * @param processus* Le processus
  240. * @return Reussite
  241. */
  242. boolean read_cmd(processus* proc){
  243. char* file;
  244. int length, fd;
  245. int size = 0;
  246. char buf = ' ';
  247. char* buffer;
  248. boolean first = true;
  249. //Recup nom du fichier
  250. length = strlen(proc->path) + 8;
  251. file = malloc(sizeof(char) * length);
  252. memset(file, 0, length);
  253. snprintf(file, length, "%scmdline", proc->path);
  254. //Ouverture fichier
  255. fd = open(file, O_RDONLY);
  256. if(fd == ERR){
  257. free(file);
  258. return false;
  259. }
  260. free(file);
  261. //Compte la taille du mot
  262. while(buf != '\n' && buf != '\0' && buf != EOF){
  263. if(read(fd, &buf, sizeof(char)) == ERR){
  264. return false;
  265. }
  266. //Au 1er tour
  267. if(first){
  268. //Si fichier vide
  269. if(buf == ' '){
  270. if(close(fd) == ERR){
  271. //Rien de particulier
  272. }
  273. return read_comm(proc);
  274. }
  275. first = false;
  276. }
  277. size++;
  278. //On evite les boucles infini
  279. if(size > 50){
  280. break;
  281. }
  282. }
  283. size--;
  284. //Revient au debut
  285. if(lseek(fd, 0L, SEEK_SET) == ERR){
  286. return false;
  287. }
  288. //Lecture commande
  289. buffer = malloc(sizeof(char) * (size + 1));
  290. memset(buffer, 0, size + 1);
  291. if(read(fd, buffer, size) == ERR){
  292. return false;
  293. }
  294. proc->cmd = buffer;
  295. //Fermeture
  296. if(close(fd) == ERR){
  297. //Rien de particulier
  298. }
  299. return true;
  300. }
  301. /**
  302. * Affiche les infos d'un processus
  303. * @param processus* Le processus
  304. */
  305. void printps(processus* proc){
  306. struct passwd* user;
  307. //Recup le nom de l'utilisateur
  308. user = getpwuid(proc->uid);
  309. if(user == NULL){
  310. addperror("Impossible de récupérer le nom de l'utilisateur");
  311. return;
  312. }
  313. //Affiche
  314. if(proc->state == 's'){
  315. printf(RED);
  316. }
  317. if(proc->state == 'r'){
  318. printf(MAGENTA);
  319. }
  320. printf("%s %d %c %s\n", user->pw_name, proc->pid, proc->state, proc->cmd);
  321. if(proc->state == 's' || proc->state == 'r'){
  322. printf(RESET);
  323. }
  324. }
  325. int main(){
  326. int total;
  327. processus** proc = list_process(&total);
  328. //Tri des processus par rapport à leur pid
  329. sort_pid(proc, total);
  330. for(int i = 0; i < total; i++){
  331. //Recup info manquante
  332. if(!read_status(proc[i])){
  333. free(proc[i]->path);
  334. free(proc[i]);
  335. continue;
  336. }
  337. if(!read_cmd(proc[i])){
  338. free(proc[i]->path);
  339. free(proc[i]);
  340. continue;
  341. }
  342. //Affiche
  343. printps(proc[i]);
  344. //Supprime
  345. free(proc[i]->path);
  346. free(proc[i]->cmd);
  347. free(proc[i]);
  348. }
  349. free(proc);
  350. return EXIT_SUCCESS;
  351. }