modules/er/er.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. NOERR
  2. er_getsev
  3. er_getfacsym
  4. er_getmsg_parts
  5. ER_setpath
  6. er_logit
  7. ER_is_traced
  8. ER_anybody_wants
  9. er_get_printmode
  10. ER_perror
  11. ER_asp_va
  12. ER_inf_va
  13. ER_dbg_va
  14. ER_init

   1 /***************************************
   2   $Revision: 1.13 $
   3 
   4   Error reporting (er) er.c - library of functions to uniformly report errors.
   5 
   6   Status: NOT REVUED, TESTED, PROVISIONAL 
   7 
   8   Design and implementation by: Marek Bukowy
   9 
  10   ******************/ /******************
  11   Copyright (c) 1999                              RIPE NCC
  12  
  13   All Rights Reserved
  14   
  15   Permission to use, copy, modify, and distribute this software and its
  16   documentation for any purpose and without fee is hereby granted,
  17   provided that the above copyright notice appear in all copies and that
  18   both that copyright notice and this permission notice appear in
  19   supporting documentation, and that the name of the author not be
  20   used in advertising or publicity pertaining to distribution of the
  21   software without specific, written prior permission.
  22   
  23   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  24   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  25   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  26   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  27   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  28   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  29   ***************************************/
  30 
  31 #define ER_IMPL
  32 #include "erroutines.h"
  33 #include <pthread.h>
  34 #include <time.h>
  35 
  36 
  37 int NOERR(er_ret_t a) 
     /* [<][>][^][v][top][bottom][index][help] */
  38 {
  39   return (    ((a & 0xFFFF) == 0 )          /* the error part is 0 */
  40               && ((a & 0xFFFF0000) != 0) ); /* the facility is non-zero */
  41 }
  42 
  43 char *er_getsev( int sev, int mode )
     /* [<][>][^][v][top][bottom][index][help] */
  44 {
  45 int i;
  46 
  47   for(i=0; er_level_a[i].sev != 0; i++) {
  48         if (er_level_a[i].sev == sev)  {
  49             break;
  50         }
  51   }
  52 
  53   switch( mode & 0x03 ) {
  54   case ER_M_SEVCHAR:    /* one-letter severity indication */
  55     return er_level_a[i].chr;
  56   case ER_M_SEVLONG:    /* long severity indication */
  57     return er_level_a[i].txt;
  58   }
  59   
  60   /* no severity indication */
  61   return "";    /* "" goes to program text, so returning a
  62                    pointer to it is OK */
  63 }
  64 
  65 char *er_getfacsym(int faccode)
     /* [<][>][^][v][top][bottom][index][help] */
  66 {
  67 int facidx;
  68 
  69   if( faccode != FAC_NONE  )  {
  70     for (facidx=0; facidx<FAC_LAST; facidx++) {
  71       if( er_main_err[facidx].code == faccode ) {
  72         break;
  73       }
  74     }
  75     return  er_main_err[facidx].name;
  76   } 
  77   else  return "";
  78 }
  79 
  80 /* TWO CONSTANTS DEFINE THE LENGTH OF STRINGS HERE:
  81    ER_MSGLEN - max length of the line to be logged
  82    ER_ERRLEN - max length of the error message
  83 */
  84 char *er_getmsg_parts(int facwhere, int errcode, int mode, 
     /* [<][>][^][v][top][bottom][index][help] */
  85                         char *buf, char *fmttxt, va_list args)
  86 {
  87 int fac, err, sev;
  88 int facidx, erridx;
  89 char erbuf[ER_ERRLEN], thr_str[10], *ermne, *txtlong="";
  90 
  91 /* init to "" */
  92 erbuf[0] = 0;
  93 ermne = "";
  94 
  95 sev = ( errcode & 0xff000000 );         /* not shifted */
  96 fac = ( errcode & 0x00ff0000 ) >> 16;
  97 err = ( errcode & 0x0000ffff );         /* not shifted */
  98 
  99   for (facidx=0; facidx<FAC_LAST; facidx++) {
 100     if( er_main_err[facidx].code == fac ) {
 101       break;
 102     }
 103   }
 104 
 105   /* now, if we got to the last one and it's not the right one, 
 106      the system is not configured properly */
 107   if(facidx==FAC_LAST) {
 108      assert( er_main_err[facidx].code == fac ); /* just bail out. */
 109   }
 110 
 111   /* still alive ? OK, build the message ...*/
 112 
 113   /* ... using facidx/erridx if it's not a DEBUG or INFO */
 114   switch( sev ) {
 115     case ER_SEV_D:
 116         ermne = "DEBUG";
 117         break;
 118     case ER_SEV_I:
 119         ermne = "INFO";
 120         break;
 121     default:
 122     /* OK, go to the module table. bail out if not initialized */
 123     assert( er_main_err[facidx].errs != NULL );
 124 
 125     for(erridx=0; er_main_err[facidx].errs[erridx].code != -1; erridx++) {
 126       if( er_main_err[facidx].errs[erridx].code == errcode ) {
 127         /* FOUND! now set the error message format using facidx and erridx */
 128 
 129         /* long error message without arguments */
 130         txtlong = er_main_err[facidx].errs[erridx].text;
 131         
 132         /* set the mnemonic pointer if necessary */ 
 133         if( mode & ER_M_MNEMONIC ) {
 134           ermne = er_main_err[facidx].errs[erridx].mnem;
 135         }
 136         break;
 137       }
 138     }
 139     /*  return ""; */
 140     /* no, do not return: bail out if the code is not defined */
 141     assert( er_main_err[facidx].errs[erridx].code != -1 );
 142   }
 143 
 144   /* build the error message using vsnprintf */  
 145   vsnprintf(erbuf, ER_ERRLEN, fmttxt, args);
 146   
 147   sprintf(thr_str, "%d", pthread_self() );
 148 
 149   /* build the actual log message */
 150   snprintf(buf, ER_MSGLEN, "%s-%s/%s %s-%s-%s %s %s",
 151            (mode & ER_M_PROGNAME) ? er_progname : "",
 152            (mode & ER_M_PIDFULL)  ? er_pid : "",
 153            (mode & ER_M_THR_ID )  ? thr_str : "",
 154            (mode & ER_M_FACSYMB)  ? er_getfacsym(facwhere) : "",
 155            er_getsev(sev, mode),
 156            (mode & ER_M_MNEMONIC) ? ermne : "",
 157            (mode & ER_M_TEXTLONG) ? txtlong : "",
 158            erbuf
 159            );   
 160   return buf;
 161 }
 162 
 163 void ER_setpath(er_path_t *newset)
     /* [<][>][^][v][top][bottom][index][help] */
 164 {
 165   /* initialise the mutex if not yet initialised */
 166 
 167   if( er_pathlist_mutex_initialised == 0 ) {
 168     pthread_mutex_init( &er_pathlist_mutex, NULL );
 169   }
 170   
 171   pthread_mutex_lock( &er_pathlist_mutex );
 172   memcpy( & er_provisional_struct, newset, sizeof(er_path_t));  
 173   pthread_mutex_unlock( &er_pathlist_mutex );
 174 }
 175 
 176 void er_logit(int facwhere, er_mask_t asp, int mode, int errcode, char *msg)
     /* [<][>][^][v][top][bottom][index][help] */
 177 {
 178   char  buf[ER_MSGLEN], tmbuf[32];
 179   struct timeval tval;
 180   struct tm tmstr;
 181 
 182   if ( mode & ER_M_DATETIME ) {
 183     gettimeofday(&tval, NULL);
 184     
 185     ctime_r(& tval.tv_sec, tmbuf);
 186     /* truncate before 2000 */
 187     tmbuf[19]=0;
 188     /* localtime_r( & tval.tv_sec, & tmstr);
 189        sprintf(tmbuf, "%02d:%02d:%02d", 
 190        tmstr.tm_hour, tmstr.tm_min, tmstr.tm_sec); */
 191     
 192   } else {
 193     tmbuf[0]=0;
 194   }
 195 
 196   snprintf(buf, ER_MSGLEN, "%s %s\n", tmbuf, msg );
 197   /* OK, now dispatch the message to all different paths */
 198   
 199   /* MUTEX :
 200 
 201      So, while the most of the work is done composing the message
 202      according to the format set in the path descriptor (mode),
 203      the output should also be locked.
 204 
 205      here the mutex associated with the path should be set.
 206      However, another mutex should be already used to protect other threads 
 207      from reading the path description while it is modified by the master
 208      thread. An RW lock can be used for this.
 209           
 210      Fortunately, fputs is MT-Safe in Solaris.
 211   */
 212  
 213 
 214   /* for now we have at most one :-) */ 
 215   if(  er_provisional_struct.fdes == NULL ) {
 216     fputs(buf,stderr);
 217   }
 218   else {
 219     /* someone has really set something! */
 220     if( errcode >= er_provisional_struct.sev
 221         || ER_is_traced(facwhere, asp) ) {
 222 
 223         fputs(buf, er_provisional_struct.fdes);
 224       }
 225   }
 226   
 227   
 228   
 229 }
 230 
 231 
 232 int ER_is_traced(int facwhere, er_mask_t asp) 
     /* [<][>][^][v][top][bottom][index][help] */
 233 {
 234 int ik = 0;
 235 
 236  if( er_provisional_struct.fac == 0 
 237      || er_provisional_struct.fac == facwhere ) {
 238   /* pthread_mutex_lock( &er_pathlist_mutex ); */
 239      ik =  er_provisional_struct.asp & asp;
 240   /* pthread_mutex_unlock( &er_pathlist_mutex ); */
 241  }
 242  
 243   return (ik);
 244 }
 245 
 246 int ER_anybody_wants( int facwhere, int errcode, er_mask_t asp )
     /* [<][>][^][v][top][bottom][index][help] */
 247 {
 248 int i;
 249 
 250   pthread_mutex_lock( &er_pathlist_mutex );
 251   i = ( errcode >= er_provisional_struct.sev );
 252   pthread_mutex_unlock( &er_pathlist_mutex );
 253 
 254   return i;
 255 }
 256 
 257 int er_get_printmode(er_path_t *pathstruct) 
     /* [<][>][^][v][top][bottom][index][help] */
 258 {
 259 int i;
 260 
 261   pthread_mutex_lock( &er_pathlist_mutex );
 262   if(  pathstruct->fdes == NULL ) {
 263     /* default mode */
 264     i = ER_M_DEFAULT;
 265   }
 266   else {
 267     i = pathstruct->mode;
 268   }
 269   pthread_mutex_unlock( &er_pathlist_mutex );
 270 
 271   return i;
 272 }
 273 
 274 void ER_perror(int facwhere, int errcode, char *format, ...)
     /* [<][>][^][v][top][bottom][index][help] */
 275 {
 276   char  erbuf[ER_MSGLEN];
 277   int     pmode;
 278   va_list ap;
 279 
 280   if( ER_anybody_wants( facwhere, errcode, 0 ) ) {      /* uses pathlist mutex */
 281 
 282     pmode = er_get_printmode( & er_provisional_struct );/* uses pathlist mutex */
 283 
 284     /* now, this takes most time: */
 285     va_start(ap, format);
 286     er_getmsg_parts(facwhere, errcode, pmode, erbuf, format, ap );
 287     va_end(ap);
 288     
 289     /* actually, here will be a loop once there are more paths possible. */
 290     er_logit(facwhere, 
 291            0,                          /* empty aspect mask for errors */
 292            pmode,
 293            errcode, 
 294            erbuf);                              /* empty debug message */
 295   }
 296 }
 297 
 298 
 299 void ER_asp_va( int facwhere, int sev,  er_mask_t asp, char *txt, 
     /* [<][>][^][v][top][bottom][index][help] */
 300                 va_list args)
 301 {
 302     int pmode;
 303     char    erbuf[ER_MSGLEN];
 304 
 305     pmode = er_get_printmode( & er_provisional_struct );
 306     er_getmsg_parts(facwhere, sev, pmode, erbuf, txt, args );
 307     er_logit(facwhere, asp, pmode, sev, erbuf);
 308 }
 309 
 310 void ER_inf_va( int facwhere, er_mask_t asp, char *txt, ...)
     /* [<][>][^][v][top][bottom][index][help] */
 311 {
 312     va_list   ap;
 313     va_start(ap, txt);
 314     ER_asp_va( facwhere, ER_SEV_I, asp, txt, ap );
 315     va_end(ap);
 316 }
 317 
 318 
 319 void ER_dbg_va( int facwhere, er_mask_t asp, char *txt, ...)
     /* [<][>][^][v][top][bottom][index][help] */
 320 {
 321   char    erbuf[ER_MSGLEN];
 322   int pmode;
 323   va_list   ap;
 324 
 325   if( ER_is_traced( facwhere, asp ) ) {
 326     
 327     pmode = er_get_printmode( & er_provisional_struct );
 328     
 329     va_start(ap, txt);
 330     er_getmsg_parts(facwhere, ER_SEV_D, pmode, erbuf, txt, ap );
 331     va_end(ap);
 332     
 333     er_logit(facwhere, asp, pmode, ER_SEV_D, erbuf);
 334   }
 335 }
 336 
 337 
 338 /* Set GLOBAL VARIABLES == can be done only by the master thread */
 339 void ER_init(int argc, char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 340 {
 341 char *er_slash; 
 342 
 343   er_slash = rindex(argv[0],'/');                              
 344   strncpy(er_progname, (er_slash != NULL) ? er_slash+1 : argv[0], 31);
 345   er_progname[31] = 0;
 346 
 347   snprintf(er_pid, 10, "%d", getpid());
 348 
 349 }

/* [<][>][^][v][top][bottom][index][help] */