error.c 5.0 KB

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