error.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /*
  2. * File: error.c
  3. * Author: Arthur Brandao
  4. *
  5. * Created on 8 novembre 2018
  6. */
  7. #define _POSIX_C_SOURCE 200809L
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <stdarg.h>
  11. #include <unistd.h>
  12. #include <fcntl.h>
  13. #include <sys/types.h>
  14. #include <sys/stat.h>
  15. #include "str.h"
  16. #include "error.h"
  17. /* --- Extern --- */
  18. int serrno = 0;
  19. char* serrlib[] = {
  20. "Reussite"
  21. };
  22. Error error;
  23. /* --- Fonctions de la structure --- */
  24. void end(){
  25. time_t temps;
  26. int fd;
  27. //Ecriture derniere ligne
  28. temps = time(NULL) - error.start;
  29. fprintf(stderr, "----- Fin log processus %d (temps en seconde : %ld) -----\n", getpid(), temps);
  30. //On remet la sortie standard des erreurs
  31. fd = redirect_fd(STDERR_FILENO, error.errfd);
  32. if(fd == ERR){
  33. adderror("Impossible de rediriger la sortie d'erreur standard");
  34. return;
  35. }
  36. //Fermeture du fichier
  37. if(close(fd) == ERR){
  38. addperror("Erreur pendant la fermeture du fichier de log");
  39. return;
  40. }
  41. //Nettoyage memoire
  42. free(error.filename);
  43. error.start = 0;
  44. error.end = NULL;
  45. error.exit = NULL;
  46. error.exit_err = NULL;
  47. error.exit_status = NULL;
  48. error.exit_msg = NULL;
  49. error.add = NULL;
  50. error.print = NULL;
  51. error.printadd = NULL;
  52. //On indique que la structure est non inialisée
  53. error.init = 0;
  54. }
  55. void exit_status(int status){
  56. error.end();
  57. exit(status);
  58. }
  59. void exit_ok(){
  60. error.exit_status(EXIT_SUCCESS);
  61. }
  62. void exit_err(){
  63. error.exit_status(EXIT_FAILURE);
  64. }
  65. void exit_msg(int status, const char* format, ...){
  66. va_list arg;
  67. va_start(arg, format);
  68. vfprintf(stdout, format, arg);
  69. va_end(arg);
  70. error.exit_status(status);
  71. }
  72. void add(const char* format, ...){
  73. va_list arg;
  74. va_start(arg, format);
  75. vfprintf(stderr, format, arg);
  76. va_end(arg);
  77. }
  78. void printerr(const char* format, ...){
  79. va_list arg;
  80. va_start(arg, format);
  81. vdprintf(error.errfd, format, arg);
  82. va_end(arg);
  83. }
  84. void printadd(const char* format, ...){
  85. va_list arg;
  86. va_start(arg, format);
  87. vdprintf(error.errfd, format, arg);
  88. vfprintf(stderr, format, arg);
  89. va_end(arg);
  90. }
  91. /* --- Fonctions publiques --- */
  92. int redirect_fd(int fd1, int fd2){
  93. int tmpfd;
  94. //On duplique le 1er fd
  95. tmpfd = dup(fd1);
  96. if(tmpfd == ERR){
  97. addperror("Erreur pendant la duplication");
  98. return ERR;
  99. }
  100. //On fait en sorte que fd1 soit lié au fichier de fd2
  101. if(dup2(fd2, fd1) == ERR){
  102. addperror("Erreur pendant le changement de fd");
  103. return ERR;
  104. }
  105. //On ferme l'ancien fd2
  106. if(close(fd2) == ERR){
  107. addperror("Erreur pendant la fermeture de fd2");
  108. return ERR;
  109. }
  110. //On retourne le nouveau fd de fd1
  111. return tmpfd;
  112. }
  113. int redirect_fd2(int fd1, int fd2){
  114. int tmpfd;
  115. //On duplique le 1er fd
  116. tmpfd = dup(fd1);
  117. if(tmpfd == ERR){
  118. addperror("Erreur pendant la duplication");
  119. return ERR;
  120. }
  121. //On fait en sorte que fd1 soit lié au fichier de fd2
  122. if(dup2(fd2, fd1) == ERR){
  123. addperror("Erreur pendant le changement de fd");
  124. return ERR;
  125. }
  126. //On retourne le nouveau fd de fd1
  127. return tmpfd;
  128. }
  129. void error_init(){
  130. //Creation nom fichier puis initialisation
  131. char filename[19];
  132. sprintf(filename, "err-%ld.log", time(NULL));
  133. error_finit(filename);
  134. }
  135. void error_finit(const char* filename){
  136. extern Error error;
  137. int fd, length;
  138. //Si il y a deja un log
  139. if(error.init){
  140. //On le ferme
  141. error.end();
  142. }
  143. //Ouverture fichier
  144. fd = open(filename, O_CREAT | O_RDWR, S_IRWXU);
  145. if(fd == ERR){
  146. addperror("Erreur lors de l'ouverture du fichier de log");
  147. return;
  148. }
  149. //On se place à la fin du fichier
  150. if(lseek(fd, 0L, SEEK_END) == ERR){
  151. addperror("Erreur lors du deplacement dans le fichier");
  152. return;
  153. }
  154. //Changement de la sortie d'erreur standard
  155. error.errfd = redirect_fd(STDERR_FILENO, fd);
  156. if(error.errfd == ERR){
  157. adderror("Impossible de rediriger la sortie d'erreur standard");
  158. return;
  159. }
  160. //Copie nom du fichier
  161. length = strlen(filename);
  162. error.filename = malloc(sizeof(char) * (length + 1));
  163. memset(error.filename, 0, length + 1);
  164. strncpy(error.filename, filename, length);
  165. //Timestamp de debut
  166. error.start = time(NULL);
  167. //Ajout fonctions
  168. error.end = end;
  169. error.exit = exit_ok;
  170. error.exit_err = exit_err;
  171. error.exit_status = exit_status;
  172. error.exit_msg = exit_msg;
  173. error.add = add;
  174. error.print = printerr;
  175. error.printadd = printadd;
  176. //Ecriture 1er ligne
  177. fprintf(stderr, "----- Log processus %d (timestamp : %ld) -----\n", getpid(), error.start);
  178. //On indique que l'inialisation a eu lieu
  179. error.init = 1;
  180. }