123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- #define _POSIX_C_SOURCE 200809L
- #include <stdlib.h>
- #include <stdio.h>
- #include <dirent.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <pwd.h>
- #include "error.h"
- #include "color.h"
- #include "constante.h"
- typedef struct{
- char* path; //Chemin vers le dossier du processus /./proc/[pid]/
- int pid; //Le pid
- int uid; //Le uid du proprietaire
- char state; //L'etat
- char* cmd; //La commande
- }processus;
- /**
- * Indique si une string est un nombre
- * @param char* Le string
- * @return Vrai/Faux
- */
- boolean is_numeric(const char* str){
- while(*str){
- if(*str < '0' || *str > '9'){
- return false;
- }
- str++;
- }
- return true;
- }
- /**
- * Tri les processus par pid croissant
- * @param processus** Le tableau de processus
- */
- void sort_pid(processus** proc, int size){
- processus* tmp;
- int index;
- for(int i = 1; i < size; i++){
- index = i;
- while(index > 0 && proc[index]->pid < proc[index - 1]->pid){
- tmp = proc[index];
- proc[index] = proc[index - 1];
- proc[index - 1] = tmp;
- index--;
- }
- }
- }
- /**
- * Liste les processus actifs
- * @param int* Le nombre de processus actif
- * @return processus** La liste
- */
- processus** list_process(int* nb){
- struct dirent** dir;
- struct stat info;
- int nbRes;
- int length, compteur = 0;
- char* path;
- processus** result;
- //Recup les dossiers
- if((nbRes = scandir("/./proc/", &dir, 0, alphasort)) == ERR){
- addperror("Impossible de scanner le dossier");
- return NULL;
- }
- //Compte le nombre de resultat
- for(int i = 0; i < nbRes; i++){
- //Création chemin
- length = strlen(dir[i]->d_name) + 10;
- path = malloc(sizeof(char) * length);
- memset(path, 0, length);
- snprintf(path, length, "/./proc/%s/", dir[i]->d_name);
- //Recup info
- if(stat(path, &info) == ERR){
- //Pas un dossier
- continue;
- }
- //Ne regarde que les dossiers dont le nom est un nombre
- if(S_ISDIR(info.st_mode) && is_numeric(dir[i]->d_name)){
- compteur++;
- }
- free(path);
- }
- //Allocation resultat
- result = malloc(sizeof(processus*) * compteur);
- //Ajout des resultats
- compteur = 0;
- for(int i = 0; i < nbRes; i++){
- //Création chemin
- length = strlen(dir[i]->d_name) + 10;
- path = malloc(sizeof(char) * length);
- memset(path, 0, length);
- snprintf(path, length, "/./proc/%s/", dir[i]->d_name);
- //Recup info
- if(stat(path, &info) == ERR){
- //Pas un dossier
- continue;
- }
- //Ne regarde que les dossiers dont le nom est un nombre
- if(S_ISDIR(info.st_mode) && is_numeric(dir[i]->d_name)){
- result[compteur] = malloc(sizeof(processus));
- result[compteur]->path = path;
- result[compteur]->pid = atoi(dir[i]->d_name);
- result[compteur]->uid = info.st_uid;
- compteur++;
- continue;
- }
- free(path);
- }
- //Libere memoire
- while(nbRes--){
- free(dir[nbRes]);
- }
- free(dir);
- //Retour
- if(nb != NULL){
- *nb = compteur;
- }
- return result;
- }
- /**
- * Lecture du fichier status d'un processus
- * @param processus* Le processus
- * @return Reussite
- */
- boolean read_status(processus* proc){
- char* file;
- int length, fd;
- char buffer;
- //Recup nom du fichier
- length = strlen(proc->path) + 7;
- file = malloc(sizeof(char) * length);
- memset(file, 0, length);
- snprintf(file, length, "%sstatus", proc->path);
- //Ouverture fichier
- fd = open(file, O_RDONLY);
- if(fd == ERR){
- free(file);
- return false;
- }
- free(file);
- //Lecture jusqu'a l'etat
- int i = 0;
- while(i < 2){
- if(read(fd, &buffer, sizeof(char)) == ERR){
- return false;
- }
- if(buffer == '\n'){
- i++;
- }
- }
- while(buffer != ' '){
- if(read(fd, &buffer, sizeof(char)) == ERR){
- return false;
- }
- }
- while(buffer == ' '){
- if(read(fd, &buffer, sizeof(char)) == ERR){
- return false;
- }
- }
- if(read(fd, &buffer, sizeof(char)) == ERR){
- return false;
- }
- proc->state = buffer;
- //Fermeture
- if(close(fd) == ERR){
- //Rien de particulier
- }
- return true;
- }
- /**
- * Lecture du fichier comm d'un processus
- * @param processus* Le processus
- * @return Reussite
- */
- boolean read_comm(processus* proc){
- char* file;
- int length, fd;
- int size = 0;
- char buf = ' ';
- char* buffer;
- boolean first = true;
- //Recup nom du fichier
- length = strlen(proc->path) + 5;
- file = malloc(sizeof(char) * length);
- memset(file, 0, length);
- snprintf(file, length, "%scomm", proc->path);
- //Ouverture fichier
- fd = open(file, O_RDONLY);
- if(fd == ERR){
- free(file);
- return false;
- }
- free(file);
- //Compte la taille du mot
- while(buf != '\n' && buf != '\0' && buf != EOF){
- if(read(fd, &buf, sizeof(char)) == ERR){
- return false;
- }
- //Au 1er tour
- if(first){
- //Si fichier vide
- if(buf == ' '){
- if(close(fd) == ERR){
- //Rien de particulier
- }
- return false;
- }
- first = false;
- }
- size++;
- }
- size--;
- //Revient au debut
- if(lseek(fd, 0L, SEEK_SET) == ERR){
- return false;
- }
- //Lecture commande
- buffer = malloc(sizeof(char) * (size + 3));
- memset(buffer, 0, size + 3);
- buffer[0] = '[';
- if(read(fd, buffer + 1, size) == ERR){
- return false;
- }
- buffer[strlen(buffer)] = ']';
- proc->cmd = buffer;
- //Fermeture
- if(close(fd) == ERR){
- //Rien de particulier
- }
- return true;
- }
- /**
- * Lecture du fichier cmdline d'un processus
- * @param processus* Le processus
- * @return Reussite
- */
- boolean read_cmd(processus* proc){
- char* file;
- int length, fd;
- int size = 0;
- char buf = ' ';
- char* buffer;
- boolean first = true;
- //Recup nom du fichier
- length = strlen(proc->path) + 8;
- file = malloc(sizeof(char) * length);
- memset(file, 0, length);
- snprintf(file, length, "%scmdline", proc->path);
- //Ouverture fichier
- fd = open(file, O_RDONLY);
- if(fd == ERR){
- free(file);
- return false;
- }
- free(file);
- //Compte la taille du mot
- while(buf != '\n' && buf != '\0' && buf != EOF){
- if(read(fd, &buf, sizeof(char)) == ERR){
- return false;
- }
- //Au 1er tour
- if(first){
- //Si fichier vide
- if(buf == ' '){
- if(close(fd) == ERR){
- //Rien de particulier
- }
- return read_comm(proc);
- }
- first = false;
- }
- size++;
- //On evite les boucles infini
- if(size > 50){
- break;
- }
- }
- size--;
- //Revient au debut
- if(lseek(fd, 0L, SEEK_SET) == ERR){
- return false;
- }
- //Lecture commande
- buffer = malloc(sizeof(char) * (size + 1));
- memset(buffer, 0, size + 1);
- if(read(fd, buffer, size) == ERR){
- return false;
- }
- proc->cmd = buffer;
- //Fermeture
- if(close(fd) == ERR){
- //Rien de particulier
- }
- return true;
- }
- /**
- * Affiche les infos d'un processus
- * @param processus* Le processus
- */
- void printps(processus* proc){
- struct passwd* user;
- //Recup le nom de l'utilisateur
- user = getpwuid(proc->uid);
- if(user == NULL){
- addperror("Impossible de récupérer le nom de l'utilisateur");
- return;
- }
- //Affiche
- if(proc->state == 's'){
- printf(RED);
- }
- if(proc->state == 'r'){
- printf(MAGENTA);
- }
- printf("%s %d %c %s\n", user->pw_name, proc->pid, proc->state, proc->cmd);
- if(proc->state == 's' || proc->state == 'r'){
- printf(RESET);
- }
- }
- int main(){
- int total;
- processus** proc = list_process(&total);
- //Tri des processus par rapport à leur pid
- sort_pid(proc, total);
- for(int i = 0; i < total; i++){
- //Recup info manquante
- if(!read_status(proc[i])){
- free(proc[i]->path);
- free(proc[i]);
- continue;
- }
- if(!read_cmd(proc[i])){
- free(proc[i]->path);
- free(proc[i]);
- continue;
- }
- //Affiche
- printps(proc[i]);
- //Supprime
- free(proc[i]->path);
- free(proc[i]->cmd);
- free(proc[i]);
- }
- free(proc);
- return EXIT_SUCCESS;
- }
|