|  | @@ -0,0 +1,194 @@
 | 
	
		
			
				|  |  | +/* 
 | 
	
		
			
				|  |  | + * File:   error.c
 | 
	
		
			
				|  |  | + * Author: Arthur Brandao
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * Created on 8 novembre 2018
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +#define _POSIX_C_SOURCE 200809L
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#include <stdio.h>
 | 
	
		
			
				|  |  | +#include <stdlib.h>
 | 
	
		
			
				|  |  | +#include <stdarg.h>
 | 
	
		
			
				|  |  | +#include <unistd.h>
 | 
	
		
			
				|  |  | +#include <fcntl.h>
 | 
	
		
			
				|  |  | +#include <sys/types.h>
 | 
	
		
			
				|  |  | +#include <sys/stat.h>
 | 
	
		
			
				|  |  | +#include "str.h"
 | 
	
		
			
				|  |  | +#include "error.h"
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/* --- Extern --- */
 | 
	
		
			
				|  |  | +int serrno = 0;
 | 
	
		
			
				|  |  | +char* serrlib[] = {
 | 
	
		
			
				|  |  | +    "Reussite"
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +Error error;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/* --- Fonctions de la structure --- */
 | 
	
		
			
				|  |  | +void end(){
 | 
	
		
			
				|  |  | +    time_t temps;
 | 
	
		
			
				|  |  | +    int fd;
 | 
	
		
			
				|  |  | +    //Ecriture derniere ligne
 | 
	
		
			
				|  |  | +    temps = time(NULL) - error.start;
 | 
	
		
			
				|  |  | +    fprintf(stderr, "----- Fin log processus %d (temps en seconde : %ld) -----\n", getpid(), temps);
 | 
	
		
			
				|  |  | +    //On remet la sortie standard des erreurs
 | 
	
		
			
				|  |  | +    fd = redirect_fd(STDERR_FILENO, error.errfd);
 | 
	
		
			
				|  |  | +    if(fd == ERR){
 | 
	
		
			
				|  |  | +        adderror("Impossible de rediriger la sortie d'erreur standard");
 | 
	
		
			
				|  |  | +        return;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    //Fermeture du fichier
 | 
	
		
			
				|  |  | +    if(close(fd) == ERR){
 | 
	
		
			
				|  |  | +        addperror("Erreur pendant la fermeture du fichier de log");
 | 
	
		
			
				|  |  | +        return;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    //Nettoyage memoire
 | 
	
		
			
				|  |  | +    free(error.filename);
 | 
	
		
			
				|  |  | +    error.start = 0;
 | 
	
		
			
				|  |  | +    error.end = NULL;
 | 
	
		
			
				|  |  | +    error.exit = NULL;
 | 
	
		
			
				|  |  | +    error.exit_err = NULL;
 | 
	
		
			
				|  |  | +    error.exit_status = NULL;
 | 
	
		
			
				|  |  | +    error.exit_msg = NULL;
 | 
	
		
			
				|  |  | +    error.add = NULL;
 | 
	
		
			
				|  |  | +    error.print = NULL;
 | 
	
		
			
				|  |  | +    error.printadd = NULL;
 | 
	
		
			
				|  |  | +    //On indique que la structure est non inialisée
 | 
	
		
			
				|  |  | +    error.init = 0;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void exit_status(int status){
 | 
	
		
			
				|  |  | +    error.end();
 | 
	
		
			
				|  |  | +    exit(status);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void exit_ok(){
 | 
	
		
			
				|  |  | +    error.exit_status(EXIT_SUCCESS);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void exit_err(){
 | 
	
		
			
				|  |  | +    error.exit_status(EXIT_FAILURE);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void exit_msg(int status, const char* format, ...){
 | 
	
		
			
				|  |  | +    va_list arg;
 | 
	
		
			
				|  |  | +    va_start(arg, format);
 | 
	
		
			
				|  |  | +    vfprintf(stdout, format, arg);
 | 
	
		
			
				|  |  | +    va_end(arg);
 | 
	
		
			
				|  |  | +    error.exit_status(status);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void add(const char* format, ...){
 | 
	
		
			
				|  |  | +    va_list arg;
 | 
	
		
			
				|  |  | +    va_start(arg, format);
 | 
	
		
			
				|  |  | +    vfprintf(stderr, format, arg);
 | 
	
		
			
				|  |  | +    va_end(arg);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void printerr(const char* format, ...){
 | 
	
		
			
				|  |  | +    va_list arg;
 | 
	
		
			
				|  |  | +    va_start(arg, format);
 | 
	
		
			
				|  |  | +    vdprintf(error.errfd, format, arg);
 | 
	
		
			
				|  |  | +    va_end(arg);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void printadd(const char* format, ...){
 | 
	
		
			
				|  |  | +    va_list arg;
 | 
	
		
			
				|  |  | +    va_start(arg, format);
 | 
	
		
			
				|  |  | +    vdprintf(error.errfd, format, arg);
 | 
	
		
			
				|  |  | +    vfprintf(stderr, format, arg);
 | 
	
		
			
				|  |  | +    va_end(arg);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/* --- Fonctions publiques --- */
 | 
	
		
			
				|  |  | +int redirect_fd(int fd1, int fd2){
 | 
	
		
			
				|  |  | +    int tmpfd;
 | 
	
		
			
				|  |  | +    //On duplique le 1er fd
 | 
	
		
			
				|  |  | +    tmpfd = dup(fd1);
 | 
	
		
			
				|  |  | +    if(tmpfd == ERR){
 | 
	
		
			
				|  |  | +        addperror("Erreur pendant la duplication");
 | 
	
		
			
				|  |  | +        return ERR;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    //On fait en sorte que fd1 soit lié au fichier de fd2
 | 
	
		
			
				|  |  | +    if(dup2(fd2, fd1) == ERR){
 | 
	
		
			
				|  |  | +        addperror("Erreur pendant le changement de fd");
 | 
	
		
			
				|  |  | +        return ERR;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    //On ferme l'ancien fd2
 | 
	
		
			
				|  |  | +    if(close(fd2) == ERR){
 | 
	
		
			
				|  |  | +        addperror("Erreur pendant la fermeture de fd2");
 | 
	
		
			
				|  |  | +        return ERR;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    //On retourne le nouveau fd de fd1
 | 
	
		
			
				|  |  | +    return tmpfd;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +int redirect_fd2(int fd1, int fd2){
 | 
	
		
			
				|  |  | +    int tmpfd;
 | 
	
		
			
				|  |  | +    //On duplique le 1er fd
 | 
	
		
			
				|  |  | +    tmpfd = dup(fd1);
 | 
	
		
			
				|  |  | +    if(tmpfd == ERR){
 | 
	
		
			
				|  |  | +        addperror("Erreur pendant la duplication");
 | 
	
		
			
				|  |  | +        return ERR;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    //On fait en sorte que fd1 soit lié au fichier de fd2
 | 
	
		
			
				|  |  | +    if(dup2(fd2, fd1) == ERR){
 | 
	
		
			
				|  |  | +        addperror("Erreur pendant le changement de fd");
 | 
	
		
			
				|  |  | +        return ERR;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    //On retourne le nouveau fd de fd1
 | 
	
		
			
				|  |  | +    return tmpfd;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void error_init(){
 | 
	
		
			
				|  |  | +    //Creation nom fichier puis initialisation
 | 
	
		
			
				|  |  | +    char filename[19];
 | 
	
		
			
				|  |  | +    sprintf(filename, "err-%ld.log", time(NULL));
 | 
	
		
			
				|  |  | +    error_finit(filename);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void error_finit(const char* filename){
 | 
	
		
			
				|  |  | +    extern Error error;
 | 
	
		
			
				|  |  | +    int fd, length;
 | 
	
		
			
				|  |  | +    //Si il y a deja un log
 | 
	
		
			
				|  |  | +    if(error.init){
 | 
	
		
			
				|  |  | +        //On le ferme
 | 
	
		
			
				|  |  | +        error.end();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    //Ouverture fichier
 | 
	
		
			
				|  |  | +    fd = open(filename, O_CREAT | O_RDWR, S_IRWXU);
 | 
	
		
			
				|  |  | +    if(fd == ERR){
 | 
	
		
			
				|  |  | +        addperror("Erreur lors de l'ouverture du fichier de log");
 | 
	
		
			
				|  |  | +        return;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    //On se place à la fin du fichier
 | 
	
		
			
				|  |  | +    if(lseek(fd, 0L, SEEK_END) == ERR){
 | 
	
		
			
				|  |  | +        addperror("Erreur lors du deplacement dans le fichier");
 | 
	
		
			
				|  |  | +        return;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    //Changement de la sortie d'erreur standard
 | 
	
		
			
				|  |  | +    error.errfd = redirect_fd(STDERR_FILENO, fd);
 | 
	
		
			
				|  |  | +    if(error.errfd == ERR){
 | 
	
		
			
				|  |  | +        adderror("Impossible de rediriger la sortie d'erreur standard");
 | 
	
		
			
				|  |  | +        return;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    //Copie nom du fichier
 | 
	
		
			
				|  |  | +    length = strlen(filename);
 | 
	
		
			
				|  |  | +    error.filename = malloc(sizeof(char) * (length + 1));
 | 
	
		
			
				|  |  | +    memset(error.filename, 0, length + 1);
 | 
	
		
			
				|  |  | +    strncpy(error.filename, filename, length);
 | 
	
		
			
				|  |  | +    //Timestamp de debut
 | 
	
		
			
				|  |  | +    error.start = time(NULL);
 | 
	
		
			
				|  |  | +    //Ajout fonctions
 | 
	
		
			
				|  |  | +    error.end = end;
 | 
	
		
			
				|  |  | +    error.exit = exit_ok;
 | 
	
		
			
				|  |  | +    error.exit_err = exit_err;
 | 
	
		
			
				|  |  | +    error.exit_status = exit_status;
 | 
	
		
			
				|  |  | +    error.exit_msg = exit_msg;
 | 
	
		
			
				|  |  | +    error.add = add;
 | 
	
		
			
				|  |  | +    error.print = printerr;
 | 
	
		
			
				|  |  | +    error.printadd = printadd;
 | 
	
		
			
				|  |  | +    //Ecriture 1er ligne
 | 
	
		
			
				|  |  | +    fprintf(stderr, "----- Log processus %d (timestamp : %ld) -----\n", getpid(), error.start);
 | 
	
		
			
				|  |  | +    //On indique que l'inialisation a eu lieu
 | 
	
		
			
				|  |  | +    error.init = 1;
 | 
	
		
			
				|  |  | +}
 |