Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

logging.c

Go to the documentation of this file.
00001 /*! \file logging.c
00002           This file implements the logging facility.
00003  */
00004 
00005 #include "logging.h"
00006 
00007 /*! \brief Maximum number of characters for a date.
00008  */
00009 
00010 #define MAX_TIME_SIZE   512
00011 
00012 /*! \brief Maximum size (in bytes) fir the log file.
00013     \remark 2147381248 bytes = 2Go - 100ko
00014  */
00015 
00016 #define MAXLOGFILESIZE  2147381248
00017 
00018 /*! \brief Maximum number of characters (including the final zero) for a MAC address written
00019            with ':' separators.
00020            Example: "00:11:22:33:44:55".
00021  */
00022 
00023 #define MAC_ADDRESS_DOTED_SIZE 18
00024 
00025 /*! \brief Maximum number of characters (including the final zero) for the gateway IP address.
00026  */
00027 
00028 #define GATEWAY_IP_MAX_SIZE 16
00029 
00030 /*! \brief Maximum number of characters (including the final zero) for a node ID.
00031  */
00032 
00033 #define NODE_ID_MAX_SIZE 20
00034 
00035 /*! \brief Current MAC address.
00036  */
00037 
00038 static char current_mac_address[MAC_ADDRESS_DOTED_SIZE];
00039 
00040 /*! \brief Current gateway.
00041  */
00042 
00043 static char gateway[GATEWAY_IP_MAX_SIZE];
00044 
00045 /*! \brief Current node ID.
00046  */
00047 
00048 static char node_id[NODE_ID_MAX_SIZE];
00049 
00050 /*! \brief Current shelf number.
00051  */
00052 
00053 static unsigned long int shelf = 0;
00054 
00055 /*! \brief Current slot number.
00056  */
00057 
00058 static unsigned long int slot = 0;
00059 
00060 /*! \brief Current port number.
00061  */
00062 
00063 static unsigned long int port = 0;
00064 
00065 /*! \brief Current VCI.
00066  */
00067 
00068 unsigned short int vci = 0;
00069 
00070 /*! \brief Current VLAN id.
00071  */
00072 
00073 unsigned short int vlan_id = 0;
00074 
00075 /*! \brief Numerical value of the current tag.
00076  */
00077 
00078 static unsigned int current_tag = 0;
00079 
00080 /*! \brief This flag defines if the server should manage the size of the log file.
00081  */
00082 
00083 static int logsize = 0;
00084 
00085 /*! \brief Activate the log size management.
00086  */
00087 
00088 void activate_log_size_management() { logsize = 1; }
00089 
00090 /*! \brief Maximum number of characters for the error message.
00091  */
00092 
00093 #define ERROR_SIZE   2048
00094 
00095 /*! \brief Last error for this module.
00096  */
00097 
00098 static char last_error[ERROR_SIZE];
00099 
00100 /*! \brief Return the last error message.
00101     \return The function returns a pointer to a statically alocated string of characters
00102             that represents the last error.
00103  */
00104 
00105 char* logger_last_error() { return last_error; }
00106 
00107 /*! \brief Set the last error message.
00108     \param error Pointer to a string that represents the last error message.
00109  */
00110 
00111 static void logger_set_last_error (const char * fmt,...)
00112 {
00113   va_list   list;
00114 
00115   memset ((void*)last_error, 0, ERROR_SIZE);
00116   va_start (list, fmt);
00117   vsnprintf (last_error, ERROR_SIZE - 1, fmt, list);
00118   va_end (list);
00119 }
00120 
00121 /*! \brief Clear the last error (set all zeros).
00122  */
00123 
00124 static void clear_last_error()
00125 { memset ((void*)last_error, 0, ERROR_SIZE); }
00126 
00127 /*! \brief Increment the value of the current tag.
00128     \author Denis BEURIVE
00129  */
00130 
00131 void logging_new_tag()
00132 {
00133   current_tag++;
00134   memset ((void*)current_mac_address, 0, MAC_ADDRESS_DOTED_SIZE);
00135   memset ((void*)node_id,             0, NODE_ID_MAX_SIZE);
00136   memset ((void*)gateway,             0, GATEWAY_IP_MAX_SIZE);
00137 
00138   snprintf (current_mac_address, MAC_ADDRESS_DOTED_SIZE, "--:--:--:--:--:--");
00139   snprintf (node_id,             NODE_ID_MAX_SIZE,       "--");
00140   snprintf (gateway,             GATEWAY_IP_MAX_SIZE,    "-.-.-.-");
00141   shelf   = 0;
00142   slot    = 0;
00143   port    = 0;
00144   vci     = 0;
00145   vlan_id = 0;
00146 }
00147 
00148 /*! \brief Initialize the client's identifier.
00149     \author Denis BEURIVE
00150     \param mac pointer to a zero terminated string of characters that represents the current MAC
00151            address.
00152     \param vnode_id Current node ID.
00153     \param vshelf Current shelf.
00154     \param vslot Current slot.
00155     \param vport Current port.
00156     \param vvci Current VCI.
00157     \param vvlan_id Current vlan_id.
00158  */
00159 
00160 void init_client_ids (char*               mac,
00161                       char*               vnode_id,
00162                       unsigned long int   vshelf,
00163                       unsigned long int   vslot,
00164                       unsigned long int   vport,
00165                       unsigned short int  vvci,
00166                       unsigned short int  vvlan_id)
00167 {
00168   strncpy (current_mac_address, mac,        MAC_ADDRESS_DOTED_SIZE-1);
00169   strncpy (node_id,             vnode_id,   NODE_ID_MAX_SIZE-1);
00170   strncpy (gateway,             "-.-.-.-",  GATEWAY_IP_MAX_SIZE-1);
00171   shelf   = vshelf;
00172   slot    = vslot;
00173   port    = vport;
00174   vci     = vvci;
00175   vlan_id = vvlan_id;
00176 }
00177 
00178 /*! \brief Initialize the logging system.
00179     \author Denis BEURIVE
00180  */
00181 
00182 void init_syslogger()
00183 {
00184   snprintf (current_mac_address, MAC_ADDRESS_DOTED_SIZE, "--:--:--:--:--:--");
00185   snprintf (node_id,             NODE_ID_MAX_SIZE,       "--");
00186   snprintf (gateway,             GATEWAY_IP_MAX_SIZE,    "-.-.-.-");
00187 }
00188 
00189 /*! \brief Return the current tag.
00190     \author Denis BEURIVE
00191     \return The function returns a pointer to a statically allocated,
00192             zero terminated string of characters that represents the current tag. 
00193  */
00194 
00195 static char* log_tag()
00196 {
00197   static char t[13];
00198   int         p;
00199 
00200   memset (t, 0, 13);
00201   snprintf (t, 13, "%12u", current_tag);
00202   for (p=0; p<13; p++) { if (t[p] == ' ') { t[p] = '0'; } }
00203   return t;
00204 }
00205 
00206 /*! \brief Return the current date as Apache's standard.
00207     \author Denis BEURIVE
00208     \return The function returns a pointer to a string of characters that contains the current date.
00209     \warning The string is returned in a statically allocated buffer, which subsequent calls
00210              will overwrite.
00211  */
00212 
00213 char* dater()
00214 {
00215   static char  strtime[MAX_TIME_SIZE];
00216   time_t       tt;
00217 
00218   tt = time(NULL);
00219   strftime (strtime, 256, "%Y-%m-%d %k:%M:%S", localtime(&tt));
00220 
00221   return strtime;
00222 }
00223 
00224 /*! \brief Return a timestamp usable for file name.
00225     \author Denis BEURIVE
00226     \return The function returns a timestamp that can be used for file names.
00227     \warning The string is returned in a statically allocated buffer, which subsequent calls will overwrite.
00228  */
00229 
00230 static char* filetimestamp()
00231 {
00232   static char  strtime[MAX_TIME_SIZE];
00233   time_t       tt;
00234 
00235   tt = time(NULL);
00236   strftime (strtime, 256, "%Y%m%d-%k:%M:%S", localtime(&tt));
00237 
00238   return strtime;
00239 }
00240 
00241 /*! \brief Get the size of a given file (in bytes).
00242     \param file Path to the file.
00243     \return Upon successful completion, the function returns the size of the file (in bytes).
00244             The value 0 can mean that:
00245             <ul>
00246               <li>The file is empty.
00247               <li>The file does not exist.
00248             </ul>
00249             If an error occures, the function returns the value (unsigned long int)(-1).
00250  */
00251 
00252 static unsigned long int get_file_size (const char *file)
00253 {
00254   struct stat s;
00255 
00256   clear_last_error();
00257 
00258   if (stat(file, &s) == -1)
00259   {
00260     int e = errno;
00261     if (e == ENOENT) { return 0; }
00262     logger_set_last_error ("stat(%s) : %s (%s,%d)", file, strerror(e), __FILE__, __LINE__);
00263     return (unsigned long int)(-1);
00264   }
00265 
00266   return (unsigned long int)(s.st_size);
00267 }
00268 
00269 /*! \brief Log one line in a given log file.
00270     \author Denis BEURIVE
00271     \param file Pointer to a zero terminated string of characters that represents the path to the log file.
00272     \param ftm Pointer to a zero terminated string of characters that defines the output formats (same as printf()).
00273     \return Upon successful completion, the function returns the value 0. Otherwize, the function returns the value 1.
00274     \remark This function behaves just like the function printf().
00275  */
00276 
00277 int my_syslog (const char *file, const char * fmt,...)
00278 {
00279         va_list            list;
00280         static char        mbuf[4097];
00281         FILE               *fd;
00282         unsigned long int  filesize;
00283         int                ifd;
00284 
00285         memset ((void*)mbuf, 0, 4097);
00286         clear_last_error();
00287 
00288         va_start (list, fmt);
00289         vsnprintf (mbuf, (sizeof mbuf) - 1, fmt, list);
00290         va_end (list);
00291 
00292         /* ---------------------------------- */
00293         /* Check the size of the file         */
00294         /* Rename it if necessary             */
00295         /* ---------------------------------- */
00296 
00297         if (logsize)
00298         {
00299           filesize = get_file_size (file);
00300           if (filesize != (unsigned long int)(-1))
00301           {
00302             if (filesize > MAXLOGFILESIZE)
00303             {
00304               char newpath[256];
00305               memset((void*)newpath, 0, 256);
00306               snprintf (newpath, 256, "%s.%s", file, filetimestamp());
00307               if (rename (file, newpath) == -1)
00308               {
00309                 int e = errno;
00310                 logger_set_last_error ("rename(%s,%s) : %s (%s,%d)",
00311                                        file, newpath ,strerror(e), __FILE__, __LINE__);
00312                 return 1;
00313               }
00314             }
00315           }
00316           else { return 1; }
00317         }
00318 
00319         ifd = open (file, O_CREAT | O_WRONLY | O_APPEND | O_LARGEFILE, S_IRWXU | S_IRWXG | S_IRWXO);
00320         if (ifd == -1)
00321         {
00322           int e = errno;
00323           logger_set_last_error ("open(%s) : %s (%s,%d)", file, strerror(e), __FILE__, __LINE__);
00324           return 1;
00325         }
00326 
00327         fd = fdopen (ifd, "a");
00328         if (fd == NULL)
00329         {
00330           int e = errno;
00331           logger_set_last_error ("fdopen(%d) : %s (%s,%d)", ifd, strerror(e), __FILE__, __LINE__);
00332           return 1;
00333         }
00334 
00335         fprintf (fd, "[%s] [%s] [%s/%lu/%lu/%lu/%d/%d/%s] %s %s\n",
00336                      log_tag(),
00337                      current_mac_address,
00338                      node_id,
00339                      shelf,
00340                      slot,
00341                      port,
00342                      vci,
00343                      vlan_id,
00344                      gateway,
00345                      dater(),
00346                      mbuf);
00347 
00348         fclose (fd);
00349         return 0;
00350 }
00351 
00352 /*! \brief Set the gateway for tag.
00353     \param g Pointer to a zero terminated string of characters that represents the gateway.
00354  */
00355 
00356 void logger_set_gateway (const char *g)
00357 {
00358   memset ((void*)gateway, 0, GATEWAY_IP_MAX_SIZE);
00359   strncpy (gateway, g, GATEWAY_IP_MAX_SIZE);
00360 }
00361 
00362 /*! \brief Log 2 empty lines in a given log file.
00363     \author Denis BEURIVE
00364     \param file Pointer to a zero terminated string of characters that represents the path to the log file.
00365     \return Upon successful completion, the function returns the value 0. Otherwize, the function returns the value 1.
00366  */
00367 
00368 int my_syslog_skip_line (const char *file)
00369 {
00370   FILE  *fd;
00371   int   ifd;
00372 
00373   clear_last_error(); 
00374 
00375   ifd = open (file, O_CREAT | O_WRONLY | O_APPEND | O_LARGEFILE, S_IRWXU | S_IRWXG | S_IRWXO);
00376   if (ifd == -1)
00377   {
00378      int e = errno;
00379      logger_set_last_error ("open(%s) : %s (%s,%d)", file, strerror(e), __FILE__, __LINE__);
00380      return 1;
00381   }
00382 
00383   fd = fdopen (ifd, "a");
00384   if (fd == NULL)
00385   {
00386      int e = errno;
00387      logger_set_last_error ("fdopen(%s) : %s (%s,%d)", file, strerror(e), __FILE__, __LINE__);
00388      return 1;
00389   }
00390  
00391   fprintf (fd, "\n\n");
00392   fclose (fd);
00393   return 0;
00394 }
00395 
00396 
00397 
00398 

Generated on Mon Jun 19 12:31:05 2006 for MyDhcp_V2 by doxygen1.2.15