logger.c 17.8 KB
Newer Older
1 2 3 4 5
/*****************************************************************************
 * logger.c
 * Print a log to a file or to screen
 *****************************************************************************
 * Copyright (C) 1998, 1999, 2000, 2001 VideoLAN
6
 * $Id: logger.c,v 1.23 2001/11/12 17:30:42 marcari Exp $
7 8
 *
 * Authors: Damien Lucas <nitrox@via.ecp.fr>
9 10
 *          Marc Ariberti <marcari@via.ecp.fr>
 * 
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

26 27 28 29
#include <pthread.h>                                   /* pthread_mutex_lock */
#include <stdarg.h>                                                /* va_arg */
#include <time.h>                                                    /* time */
#include <stdio.h>                                           /* fflush , ... */
30
#include <stdlib.h>
Damien Lucas's avatar
Damien Lucas committed
31

32 33 34
#include "types.h"
#include "logger.h"

Damien Lucas's avatar
Damien Lucas committed
35

36 37
#define FALSE   0
#define TRUE    1
Damien Lucas's avatar
Damien Lucas committed
38

39
/* Local Functions prototypes */
Damien Lucas's avatar
Damien Lucas committed
40 41


42 43 44
static struct LOG_stream * ls_none;
static pthread_mutex_t ptm_log_available;
static int is_log_available=FALSE;
Damien Lucas's avatar
Damien Lucas committed
45

46
/*****************************************************************************
47
 * VS_log_File : Write a log inside a file
48
 *****************************************************************************/
49 50
static void VS_log_File(LOG_LEVELS level,
                        LOG_MODULES module,
51
                        struct LOG_stream * output_stream,
52
                        char* format,
53
                        va_list ap)
54
{
55 56 57 58 59 60 61 62 63 64
 
  char MsgBuff[LOGBUFF_MAXSIZE];   /* buffer which will contain 
                                      the message wanted to be displayed */
  char LineBuff[LOGBUFF_LINESIZE]; /* line currently displayed */
  char HeaderBuff[34+20];          /* header of the message + color */
  char FooterBuff[20];             /* footer of the message + end color */

  int MessagePosition;
  int MessageLength;
  
Damien Lucas's avatar
Damien Lucas committed
65 66 67 68 69
  time_t MsgTime;
  struct tm * ptmTime;

#ifndef DEBUG
  if(level!=LOGDEBUG)
70
  {
Damien Lucas's avatar
Damien Lucas committed
71 72 73 74
#endif
  /* Record the time */
  time(&MsgTime);
  ptmTime=localtime(&MsgTime);
75
  sprintf(HeaderBuff, "%02i/%02i %02i:%02i:%02i ", ptmTime->tm_mday,
Damien Lucas's avatar
Damien Lucas committed
76 77 78 79 80 81 82 83 84
          ptmTime->tm_mon+1, ptmTime->tm_hour, 
          ptmTime->tm_min, ptmTime->tm_sec);



  /* Determinate in which module it happened */
  switch (module)
  {
    case SNMP:
85
      sprintf(HeaderBuff+strlen(HeaderBuff), "[SNMP  : ");
Damien Lucas's avatar
Damien Lucas committed
86 87 88
      break;
    
    case SERVER:
89
      sprintf(HeaderBuff+strlen(HeaderBuff), "[SERVER: ");
Damien Lucas's avatar
Damien Lucas committed
90 91 92
      break;
      
    case DB:
93
      sprintf(HeaderBuff+strlen(HeaderBuff), "[DB    : ");
Damien Lucas's avatar
Damien Lucas committed
94 95 96
      break;

    case CFG:
97
      sprintf(HeaderBuff+strlen(HeaderBuff), "[CFG   : ");
Damien Lucas's avatar
Damien Lucas committed
98 99 100
      break;
      
    case IF:
101
      sprintf(HeaderBuff+strlen(HeaderBuff), "[IF    : ");
Damien Lucas's avatar
Damien Lucas committed
102 103 104
      break;
    
    case TELNET:
105
      sprintf(HeaderBuff+strlen(HeaderBuff), "[TELNET: ");
Damien Lucas's avatar
Damien Lucas committed
106 107
      break;
    case LOGGER:
108
      sprintf(HeaderBuff+strlen(HeaderBuff), "[LOGGER: ");
Damien Lucas's avatar
Damien Lucas committed
109 110 111 112 113 114 115
      break;
  }

  /* Determinate the error level */
  switch (level)
  {
    case LOGDEBUG:
116
      sprintf(HeaderBuff+strlen(HeaderBuff), "debug   ] ");
Damien Lucas's avatar
Damien Lucas committed
117 118
      break;
    case LOGINFO:
119
      sprintf(HeaderBuff+strlen(HeaderBuff), "info    ] ");
Damien Lucas's avatar
Damien Lucas committed
120 121
      break;
    case LOGWARNING:
122
      sprintf(HeaderBuff+strlen(HeaderBuff), "Warning ] ");
Damien Lucas's avatar
Damien Lucas committed
123 124
      break;
    case LOGFATAL:
125 126
      {
        sprintf(HeaderBuff+strlen(HeaderBuff), "FATAL   ] ");
Damien Lucas's avatar
Damien Lucas committed
127
        break;
128
      }
Damien Lucas's avatar
Damien Lucas committed
129
    case LOGERROR:
130 131
      {
        sprintf(HeaderBuff+strlen(HeaderBuff), "ERROR   ] ");
Damien Lucas's avatar
Damien Lucas committed
132
        break;
133
      }
Damien Lucas's avatar
Damien Lucas committed
134 135 136
  }
 
  /* XXX No error checking ! What length is the message ? */
137
  vsnprintf(MsgBuff, LOGBUFF_MAXSIZE, format, ap);
Damien Lucas's avatar
Damien Lucas committed
138

139 140
  sprintf(FooterBuff,"\n");
        
141 142
  pthread_mutex_lock(&output_stream->ptm_log);
  fputs(HeaderBuff, output_stream->fd_output);
143 144 145 146 147 148

  MessageLength = strlen(MsgBuff);
  MessagePosition = 0;
  while ( (MessageLength-MessagePosition) > LOGBUFF_LINESIZE )
  {
    snprintf( LineBuff, LOGBUFF_LINESIZE+1, MsgBuff + MessagePosition );
149 150
    fputs( LineBuff, output_stream->fd_output );
    fputs( "\n                                  ", output_stream->fd_output );
151 152
    MessagePosition += LOGBUFF_LINESIZE;
  }
153
  fputs( MsgBuff + MessagePosition, output_stream->fd_output);
154
  
155 156 157
  fputs(FooterBuff, output_stream->fd_output);
  fflush(output_stream->fd_output);
  pthread_mutex_unlock(&output_stream->ptm_log);
Damien Lucas's avatar
Damien Lucas committed
158 159 160 161

#ifndef DEBUG
  }
#endif
162
}
163

164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
                  
/*****************************************************************************
 * VS_log_Telnet : formats the ouput to be printed on a telnet intf
 *****************************************************************************/
static void VS_log_Telnet(LOG_LEVELS level,
                        LOG_MODULES module,
                        struct LOG_stream * output_stream,
                        char* format,
                        va_list ap)
{
 
  char MsgBuff[LOGBUFF_MAXSIZE];   /* buffer which will contain 
                                      the message wanted to be displayed */
  char LineBuff[LOGBUFF_LINESIZE]; /* line currently displayed */
  char HeaderBuff[34+20];          /* header of the message + color */
  char FooterBuff[20];             /* footer of the message + end color */

  int MessagePosition;
  int MessageLength;
  
  time_t MsgTime;
  struct tm * ptmTime;

#ifndef DEBUG
  if(level!=LOGDEBUG)
  {
#endif
  /* Record the time */
  time(&MsgTime);
  ptmTime=localtime(&MsgTime);
  sprintf(HeaderBuff, "%02i/%02i %02i:%02i:%02i ", ptmTime->tm_mday,
          ptmTime->tm_mon+1, ptmTime->tm_hour, 
          ptmTime->tm_min, ptmTime->tm_sec);



  /* Determinate in which module it happened */
  switch (module)
  {
    case SNMP:
      sprintf(HeaderBuff+strlen(HeaderBuff), "[SNMP  : ");
      break;
    
    case SERVER:
      sprintf(HeaderBuff+strlen(HeaderBuff), "[SERVER: ");
      break;
      
    case DB:
      sprintf(HeaderBuff+strlen(HeaderBuff), "[DB    : ");
      break;

    case CFG:
      sprintf(HeaderBuff+strlen(HeaderBuff), "[CFG   : ");
      break;
      
    case IF:
      sprintf(HeaderBuff+strlen(HeaderBuff), "[IF    : ");
      break;
    
    case TELNET:
      sprintf(HeaderBuff+strlen(HeaderBuff), "[TELNET: ");
      break;
    case LOGGER:
      sprintf(HeaderBuff+strlen(HeaderBuff), "[LOGGER: ");
      break;
  }

  /* Determinate the error level */
  switch (level)
  {
    case LOGDEBUG:
      sprintf(HeaderBuff+strlen(HeaderBuff), "debug   ] ");
      break;
    case LOGINFO:
      sprintf(HeaderBuff+strlen(HeaderBuff), "info    ] ");
      break;
    case LOGWARNING:
      sprintf(HeaderBuff+strlen(HeaderBuff), "Warning ] ");
      break;
    case LOGFATAL:
      {
        sprintf(HeaderBuff+strlen(HeaderBuff), "FATAL   ] ");
        break;
      }
    case LOGERROR:
      {
        sprintf(HeaderBuff+strlen(HeaderBuff), "ERROR   ] ");
        break;
      }
  }
 
  /* XXX No error checking ! What length is the message ? */
  vsnprintf(MsgBuff, LOGBUFF_MAXSIZE, format, ap);

  sprintf(FooterBuff,"\r\n");
        
  pthread_mutex_lock(&output_stream->ptm_log);
  fputs(HeaderBuff, output_stream->fd_output);

  MessageLength = strlen(MsgBuff);
  MessagePosition = 0;
  while ( (MessageLength-MessagePosition) > LOGBUFF_LINESIZE )
  {
    snprintf( LineBuff, LOGBUFF_LINESIZE+1, MsgBuff + MessagePosition );
    fputs( LineBuff, output_stream->fd_output );
    fputs( "\r\n                                  ", output_stream->fd_output );
    MessagePosition += LOGBUFF_LINESIZE;
  }
  fputs( MsgBuff + MessagePosition, output_stream->fd_output);
  
  fputs(FooterBuff, output_stream->fd_output);
  fflush(output_stream->fd_output);
  pthread_mutex_unlock(&output_stream->ptm_log);

#ifndef DEBUG
  }
#endif
}

283 284 285


/*****************************************************************************
286
 * Write a log to a screen(-like) output
287
 *****************************************************************************/
288 289
static void VS_log_Screen(LOG_LEVELS level,
                          LOG_MODULES module,
290
                          struct LOG_stream * output_stream,
291 292
                          char* format,
                          va_list ap)
293
{
294 295 296 297 298 299 300 301 302
  char MsgBuff[LOGBUFF_MAXSIZE];   /* buffer which will contain 
                                      the message wanted to be displayed */
  char LineBuff[LOGBUFF_LINESIZE]; /* line currently displayed */
  char HeaderBuff[34+20];          /* header of the message + color */
  char FooterBuff[20];             /* footer of the message + end color */

  int MessagePosition;
  int MessageLength;
  
303
  time_t MsgTime;
304
  struct tm * ptmTime;
305

306 307 308 309
#ifndef DEBUG
  if(level!=LOGDEBUG)
  {
#endif
310 311 312
  /* Record the time */
  time(&MsgTime);
  ptmTime=localtime(&MsgTime);
313
  sprintf(HeaderBuff, "%02i/%02i %02i:%02i:%02i ", ptmTime->tm_mday,
314 315 316
          ptmTime->tm_mon+1, ptmTime->tm_hour, 
          ptmTime->tm_min, ptmTime->tm_sec);

Damien Lucas's avatar
Damien Lucas committed
317 318


319 320 321 322
  /* Determinate in which module it happened */
  switch (module)
  {
    case SNMP:
323
      sprintf(HeaderBuff+strlen(HeaderBuff), "[SNMP  : ");
324 325 326
      break;
    
    case SERVER:
327
      sprintf(HeaderBuff+strlen(HeaderBuff), "[SERVER: ");
328 329 330
      break;
      
    case DB:
331
      sprintf(HeaderBuff+strlen(HeaderBuff), "[DB    : ");
332 333 334
      break;

    case CFG:
335
      sprintf(HeaderBuff+strlen(HeaderBuff), "[CFG   : ");
336
      break;
337 338
      
    case IF:
339
      sprintf(HeaderBuff+strlen(HeaderBuff), "[IF    : ");
340 341 342
      break;
    
    case TELNET:
343
      sprintf(HeaderBuff+strlen(HeaderBuff), "[TELNET: ");
344
      break;
Damien Lucas's avatar
Damien Lucas committed
345
    case LOGGER:
346
      sprintf(HeaderBuff+strlen(HeaderBuff), "[LOGGER: ");
Damien Lucas's avatar
Damien Lucas committed
347
      break;
348 349 350 351 352 353
  }

  /* Determinate the error level */
  switch (level)
  {
    case LOGDEBUG:
354
      sprintf(HeaderBuff+strlen(HeaderBuff), "debug   ] ");
355 356
      break;
    case LOGINFO:
357
      sprintf(HeaderBuff+strlen(HeaderBuff), "info    ] ");
358 359
      break;
    case LOGWARNING:
360 361 362
#ifdef LINUX_COLOR
      sprintf(HeaderBuff+strlen(HeaderBuff), "\033[40;32;1m");
#endif
363
      sprintf(HeaderBuff+strlen(HeaderBuff), "Warning ] ");
364 365
      break;
    case LOGFATAL:
366 367
      {
#ifdef LINUX_COLOR
368
        sprintf(HeaderBuff+strlen(HeaderBuff), "\033[40;31;1m");
369
#endif        
370
        sprintf(HeaderBuff+strlen(HeaderBuff), "FATAL   ] ");
371 372 373 374 375
        break;
      }
    case LOGERROR:
      {
#ifdef LINUX_COLOR
376
        sprintf(HeaderBuff+strlen(HeaderBuff), "\033[40;31;1m");
377
#endif 
378
        sprintf(HeaderBuff+strlen(HeaderBuff), "ERROR   ] ");
379 380
        break;
      }
381
  }
382
 
383
  /* XXX No error checking ! What length is the message ? */
384 385 386 387 388 389 390 391
  vsnprintf(MsgBuff, LOGBUFF_MAXSIZE, format, ap);

#ifdef LINUX_COLOR
  sprintf(FooterBuff, "\033[0m\n");
#else
  sprintf(FooterBuff,"\n");
#endif

392 393
  pthread_mutex_lock(&output_stream->ptm_log);
  fputs(HeaderBuff, output_stream->fd_output);
394 395 396 397 398 399

  MessageLength = strlen(MsgBuff);
  MessagePosition = 0;
  while ( (MessageLength-MessagePosition) > LOGBUFF_LINESIZE )
  {
    snprintf( LineBuff, LOGBUFF_LINESIZE+1, MsgBuff + MessagePosition );
400 401
    fputs( LineBuff, output_stream->fd_output );
    fputs( "\n                                  ", output_stream->fd_output );
402 403
    MessagePosition += LOGBUFF_LINESIZE;
  }
404
  fputs( MsgBuff + MessagePosition, output_stream->fd_output);
405
  
406 407 408 409
  fputs(FooterBuff, output_stream->fd_output);
  fflush(output_stream->fd_output);
  pthread_mutex_unlock(&output_stream->ptm_log);
       
410 411 412
#ifndef DEBUG
  }
#endif
Damien Lucas's avatar
Damien Lucas committed
413 414 415
}


416 417 418 419 420


/*****************************************************************************
 * Main log function 
 *****************************************************************************/
Damien Lucas's avatar
Damien Lucas committed
421 422
void VS_log(LOG_LEVELS level, LOG_MODULES module, char* format, ...)
{
423 424
   struct LOG_stream * ls_current=ls_none->next_stream;
 va_list ap;
Damien Lucas's avatar
Damien Lucas committed
425
  va_start(ap,format);
426 427 428 429

  /* check whether the logging system is available or not */
  pthread_mutex_lock(&ptm_log_available);
  if (is_log_available==FALSE)
Damien Lucas's avatar
Damien Lucas committed
430
  {
431
    return;
Damien Lucas's avatar
Damien Lucas committed
432
  }
433
  pthread_mutex_unlock(&ptm_log_available);
434
  
435
  while(ls_current != NULL)
Damien Lucas's avatar
Damien Lucas committed
436
  {
437 438 439 440 441 442 443 444
    switch(ls_current->type)
    {
      case LOGTYPE_FILE:
        VS_log_File(level, module, ls_current, format, ap);
        break;
      case LOGTYPE_SCREEN:
        VS_log_Screen(level, module, ls_current, format, ap);
        break;
445 446 447
      case LOGTYPE_TELNET:
        VS_log_Telnet(level, module, ls_current, format, ap);
        break;
448 449 450
      default:
    }
    ls_current=ls_current->next_stream;
Damien Lucas's avatar
Damien Lucas committed
451 452
  }
  
453
  va_end(ap);
Damien Lucas's avatar
Damien Lucas committed
454 455 456
}


457 458

/*****************************************************************************
459 460 461 462
 * Open a log file 
 ******************
 * opens a new file for logging and returns if no error the file descriptor
 * in order to be able to close it later
463
 *****************************************************************************/
464
FILE * LOG_file (char * sLogName)
Damien Lucas's avatar
Damien Lucas committed
465 466
{
  int iRc;
467 468
  FILE * fdLogFile;
 
Damien Lucas's avatar
Damien Lucas committed
469 470 471 472 473 474 475 476
  iRc=0;
  if( !(fdLogFile = fopen (sLogName, "w+")))
  {
    iRc=1;
    VS_log(LOGFATAL, LOGGER, "Unable to open %s log file ", sLogName);
  }
  else
  {
477 478 479 480 481 482 483 484 485 486
    LOG_create(fdLogFile, LOGTYPE_FILE);
  }
  
  if (iRc==1)
  {
    return NULL;
  }
  else
  {
    return fdLogFile;
Damien Lucas's avatar
Damien Lucas committed
487 488 489 490
  }
}


491

492
#if 0
493 494 495
/*****************************************************************************
 * Close the LogFile
 *****************************************************************************/
Damien Lucas's avatar
Damien Lucas committed
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518
int CloseLogFile ()
{
  int iRc;
  iRc=0;

  if(fdLogFile)
  {
    iRc=fclose(fdLogFile);
    if(iRc)
    {
      VS_log(LOGERROR, LOGGER, "Unable to close file");
    }
    iRc=pthread_mutex_destroy(&ptmLogFile);
  }
  else
  {
    iRc=1;
    VS_log(LOGERROR, LOGGER, "Unable to close log file: file not open");
  }
  return iRc;
        
}

519
#endif
520 521 522


/*****************************************************************************
Damien Lucas's avatar
Damien Lucas committed
523
 * LOG_init() : Initialize the log process
524 525 526
 *****************************************************************************
 * TODO Gestion d'erreurs
 *****************************************************************************/
527
int LOG_init()
Damien Lucas's avatar
Damien Lucas committed
528
{
529 530 531
  /* initialization of the logs chain */
  ls_none = malloc(sizeof(struct LOG_stream));
  if(ls_none==NULL)
Damien Lucas's avatar
Damien Lucas committed
532
  {
533
    return(-1);
Damien Lucas's avatar
Damien Lucas committed
534
  }
535 536 537 538 539 540 541
  
  ls_none->fd_output=NULL;
  ls_none->type=LOGTYPE_NONE;
  ls_none->next_stream=NULL;

  pthread_mutex_init(&ptm_log_available, NULL);
  is_log_available=TRUE;
542 543
  return 0;
}
Damien Lucas's avatar
Damien Lucas committed
544 545


546
/*****************************************************************************
547
 * LOG_create : add a new log output to the list
548
 *****************************************************************************
549
 * 
550
 *****************************************************************************/
551 552

int LOG_create(FILE * output_stream, int type)
553
{
554 555
  struct LOG_stream * ls_new;
  struct LOG_stream * ls_current;
Damien Lucas's avatar
Damien Lucas committed
556

557 558
  ls_new = malloc(sizeof(struct LOG_stream));
  if (ls_new==NULL)
559
  {
560
    return(-1);
561
  }
562 563 564 565 566 567 568 569
  ls_new->fd_output=output_stream;
  ls_new->type=type;
  pthread_mutex_init( &(ls_new->ptm_log), NULL );
  ls_new->next_stream=NULL;
  
  /* inserts the new log stream et the end of the queue */
  ls_current=ls_none;
  while(ls_current->next_stream!=NULL)
570
  {
571
    ls_current=ls_current->next_stream;
572
  }
573 574
  ls_current->next_stream = ls_new;
  
575 576
  return 0;
}
Damien Lucas's avatar
Damien Lucas committed
577 578


579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609
/**********
 * LOG_delete : removes a log output from the list
 ************
 * 
 ************/

int LOG_delete(FILE * output_stream)
{
  struct LOG_stream * ls_current;
  struct LOG_stream * ls_previous;

  /* searches for the log stream */
  ls_previous=NULL;
  ls_current=ls_none;
  while (ls_current->fd_output!=output_stream)
  {

    ls_previous=ls_current;
    ls_current=ls_current->next_stream;
    if (ls_current==NULL)
    { /* error : log stream not found */
      return -1;
    }
  }
  ls_previous->next_stream=ls_current->next_stream;
  
  pthread_mutex_destroy(&ls_current->ptm_log);
  free(ls_current);
  
  return 0;
}
Damien Lucas's avatar
Damien Lucas committed
610

611
/****************************************************************************
612
 * LOG_close() : terminates le the log system 
613
 ****************************************************************************
614
 * DONE 
615
 ****************************************************************************/
Damien Lucas's avatar
Damien Lucas committed
616

617 618
int LOG_close()
{
619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637
  struct LOG_stream * ls_current;
  struct LOG_stream * ls_next;
 
  VS_log(LOGINFO, SERVER, "Terminating log system");
 
  pthread_mutex_lock(&ptm_log_available);
  is_log_available=FALSE;
  pthread_mutex_unlock(&ptm_log_available);
  
  ls_current=ls_none;
  while (ls_current != NULL)
  {
    ls_next=ls_current->next_stream;
    pthread_mutex_destroy(&ls_current->ptm_log);
    free(ls_current);
    ls_current=ls_next;
  }
  
  return 0;
638
}
Damien Lucas's avatar
Damien Lucas committed
639

640 641 642
/****************************************************************************
 * VS_log_errstr() : Returns a string corresponding to an ERR_CODE
 ****************************************************************************/
Damien Lucas's avatar
Damien Lucas committed
643 644 645 646 647 648
char * VS_log_errstr(ERR_CODE err)
{
  static char * str[]=
  {
    "no error",
    "object not found",
649
    "trying to do a walk on a switch is currently walked by an other thread",
650
    "the authentification failed",
651
    "bad configuration file",
652 653
    "unable to bind a socket",
    "unable to connect to remote host",
654
    "unable to stop the database",
655 656
    "unable to resolve the dns",
    "initiatization of the switch failed",
Damien Lucas's avatar
Damien Lucas committed
657
    "unable to open, read or write a file",
658
    "unable to allocate memory",
659
    "pb with the number",
Damien Lucas's avatar
Damien Lucas committed
660 661 662
    "parse error",
    "pipe creation error",
    "unable to write to a pipe",
663 664 665 666 667
    "unable to spawn a thread",
    "unable to receive data from remote host",
    "unable to send data to remote host",
    "unable to execute a select() operation",
    "snmp error",
668
    "unable to stop the snmp",
669 670 671
    "unable to open a socket",
    "time error",
    "timeout"
Damien Lucas's avatar
Damien Lucas committed
672 673 674
  };
  return str[err];
}