#define _POSIX_C_SOURCE 200809L #include #include #include #include #include #include #include #include #include #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; }