123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416 |
- #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 <time.h>
- #include "error.h"
- #include "color.h"
- #include "constante.h"
- #define MAX_CMD_SIZE 50
- typedef long long int llint;
- typedef unsigned long long ull;
- 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
- llint tty;
- llint cpu;
- ull start;
- llint vsz;
- llint rss;
- }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--;
- }
- }
- }
- int get_uptime() {
- FILE* procUptime;
- int sec, ssec;
- procUptime = fopen("/proc/uptime", "r");
- int tmp = fscanf(procUptime, "%d.%ds", &sec, &ssec);
- tmp++; //Pour ne pas avoir de warning
- fclose(procUptime);
- return (sec * sysconf(_SC_CLK_TCK)) + ssec;
- }
- /**
- * 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;
- FILE* f;
- int length, tmp;
- char buffer[BUFFER_SIZE];
- llint trash;
- //Recup nom du fichier
- length = strlen(proc->path) + 5;
- file = malloc(sizeof(char) * length);
- memset(file, 0, length);
- snprintf(file, length, "%sstat", proc->path);
- //Ouverture fichier
- f = fopen(file, "r");;
- if(!f){
- free(file);
- return false;
- }
- free(file);
- //Lecture des informations
- tmp = fscanf(f, "%lld ", &trash);
- tmp = fscanf(f, "%s ", buffer);
- tmp = fscanf(f, "%c ", &proc->state);
- for (int i = 0; i < 3; i++){
- tmp = fscanf(f, "%lld ", &trash);
- }
- tmp = fscanf(f, "%lld ", &proc->tty);
- for (int i = 0; i < 6; i++){
- tmp = fscanf(f, "%lld ", &trash);
- }
- tmp = fscanf(f, "%lld ", &proc->cpu);
- for (int i = 0; i < 7; i++){
- tmp = fscanf(f, "%lld ", &trash);
- }
- tmp = fscanf(f, "%llu ", &proc->start);
- tmp = fscanf(f, "%lld ", &proc->vsz);
- tmp = fscanf(f, "%lld ", &proc->rss);
- tmp++; //Pour ne pas avoir de warning
- fclose(f);
- 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 > MAX_CMD_SIZE){
- 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;
- boolean color = false;
- llint vsize;
- char start[BUFFER_SIZE];
- //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;
- }
- //VSZ
- vsize = proc->vsz / 1024;
- //Debut
- int uptime = get_uptime();
- int running = uptime - proc->start;
- time_t runningTime = time(NULL) - (running / sysconf(_SC_CLK_TCK));
- strftime(start, sizeof(start), "%H:%M", localtime(&runningTime));
- //Couleur
- if(proc->state == 's'){
- printf(RED);
- }
- if(proc->state == 'r'){
- printf(MAGENTA);
- }
- switch(proc->state){
- case 'S':
- printf(RED);
- color = true;
- break;
- case 'R':
- printf(YELLOW);
- color = true;
- break;
- case 'N':
- printf(BLUE);
- color = true;
- break;
- case 'Z':
- printf(GREEN);
- color = true;
- break;
- case 'T':
- printf(MAGENTA);
- color = true;
- break;
- case 'D':
- printf(CYAN);
- color = true;
- break;
- }
- //Affiche (Manque %CPU, %MEM, TIME)
- printf("%s %d %lld %lld %lld %c %s %s\n", user->pw_name, proc->pid, vsize, proc->rss, proc->tty, proc->state, start, proc->cmd);
- if(color){
- printf(RESET);
- }
- }
- int main(){
- int total;
- processus** proc = list_process(&total);
- //Tri des processus par rapport à leur pid
- sort_pid(proc, total);
- if(total > 0){
- printf("USER PID VSZ RSS TTY STAT START COMMAND \n");
- }
- 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;
- }
|