nfs-ganesha 1.4

log_functions.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=8:tabstop=8:
00003  *
00004  * Copyright CEA/DAM/DIF  (2008)
00005  * contributeur : Philippe DENIEL   philippe.deniel@cea.fr
00006  *                Thomas LEIBOVICI  thomas.leibovici@cea.fr
00007  *
00008  *
00009  * This program is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 3 of the License, or (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  * ---------------------------------------
00024  *
00025  * ensemble des fonctions d'affichage et de gestion des erreurs
00026  *
00027  */
00028 #ifdef HAVE_CONFIG_H
00029 #include "config.h"
00030 #endif
00031 
00032 #include <stdlib.h>             /* for malloc */
00033 #include <ctype.h>              /* for isdigit */
00034 #include <pthread.h>
00035 #include <stdio.h>
00036 #include <stdarg.h>
00037 #include <unistd.h>
00038 #include <fcntl.h>
00039 #include <time.h>
00040 #include <sys/types.h>
00041 #include <sys/param.h>
00042 #include <sys/stat.h>
00043 #include <errno.h>
00044 #include <string.h>
00045 #include <signal.h>
00046 #include <libgen.h>
00047 
00048 #include "log.h"
00049 //#include "nfs_core.h"
00050 
00051 /* La longueur d'une chaine */
00052 #define STR_LEN_TXT      2048
00053 #define PATH_LEN         1024
00054 #define MAX_STR_LEN      1024
00055 #define MAX_NUM_FAMILY  50
00056 #define UNUSED_SLOT -1
00057 
00058 log_level_t tabLogLevel[] =
00059 {
00060   {NIV_NULL,       "NIV_NULL",       "NULL",       LOG_NOTICE},
00061   {NIV_FATAL,      "NIV_FATAL",      "FATAL",      LOG_CRIT},
00062   {NIV_MAJ,        "NIV_MAJ",        "MAJ",        LOG_CRIT},
00063   {NIV_CRIT,       "NIV_CRIT",       "CRIT",       LOG_ERR},
00064   {NIV_WARN,       "NIV_WARN",       "WARN",       LOG_WARNING},
00065   {NIV_EVENT,      "NIV_EVENT",      "EVENT",      LOG_NOTICE},
00066   {NIV_INFO,       "NIV_INFO",       "INFO",       LOG_INFO},
00067   {NIV_DEBUG,      "NIV_DEBUG",      "DEBUG",      LOG_DEBUG},
00068   {NIV_MID_DEBUG,  "NIV_MID_DEBUG",  "MID_DEBUG",  LOG_DEBUG},
00069   {NIV_FULL_DEBUG, "NIV_FULL_DEBUG", "FULL_DEBUG", LOG_DEBUG}
00070 };
00071 
00072 #ifndef ARRAY_SIZE
00073 #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
00074 #endif
00075 
00076 /* les code d'error */
00077 errctx_t __attribute__ ((__unused__)) tab_systeme_err[] =
00078 {
00079   {SUCCES, "SUCCES", "No Error"},
00080   {ERR_FAILURE, "FAILURE", "Une error est survenue"},
00081   {ERR_EVNT, "EVNT", "Evennement survenu"},
00082   {ERR_PTHREAD_KEY_CREATE, "ERR_PTHREAD_KEY_CREATE", "Error in creation of pthread_keys"},
00083   {ERR_MALLOC, "ERR_MALLOC", "malloc impossible"},
00084   {ERR_SIGACTION, "ERR_SIGACTION", "sigaction impossible"},
00085   {ERR_PTHREAD_ONCE, "ERR_PTHREAD_ONCE", "pthread_once impossible"},
00086   {ERR_FICHIER_LOG, "ERR_FICHIER_LOG", "impossible d'acceder au fichier de log"},
00087   {ERR_GETHOSTBYNAME, "ERR_GETHOSTBYNAME", "gethostbyname impossible"},
00088   {ERR_MMAP, "ERR_MMAP", "mmap impossible"},
00089   {ERR_SOCKET, "ERR_SOCKET", "socket impossible"},
00090   {ERR_BIND, "ERR_BIND", "bind impossible"},
00091   {ERR_CONNECT, "ERR_CONNECT", "connect impossible"},
00092   {ERR_LISTEN, "ERR_LISTEN", "listen impossible"},
00093   {ERR_ACCEPT, "ERR_ACCEPT", "accept impossible"},
00094   {ERR_RRESVPORT, "ERR_RRESVPORT", "rresvport impossible"},
00095   {ERR_GETHOSTNAME, "ERR_GETHOSTNAME", "gethostname impossible"},
00096   {ERR_GETSOCKNAME, "ERR_GETSOCKNAME", "getsockname impossible"},
00097   {ERR_IOCTL, "ERR_IOCTL", "ioctl impossible"},
00098   {ERR_UTIME, "ERR_UTIME", "utime impossible"},
00099   {ERR_XDR, "ERR_XDR", "Un appel XDR a echoue"},
00100   {ERR_CHMOD, "ERR_CHMOD", "chmod impossible"},
00101   {ERR_SEND, "ERR_SEND", "send impossible"},
00102   {ERR_GETHOSTBYADDR, "ERR_GETHOSTBYADDR", "gethostbyaddr impossible"},
00103   {ERR_PREAD, "ERR_PREAD", "pread impossible"},
00104   {ERR_PWRITE, "ERR_PWRITE", "pwrite impossible"},
00105   {ERR_STAT, "ERR_STAT", "stat impossible"},
00106   {ERR_GETPEERNAME, "ERR_GETPEERNAME", "getpeername impossible"},
00107   {ERR_FORK, "ERR_FORK", "fork impossible"},
00108   {ERR_GETSERVBYNAME, "ERR_GETSERVBYNAME", "getservbyname impossible"},
00109   {ERR_MUNMAP, "ERR_MUNMAP", "munmap impossible"},
00110   {ERR_STATVFS, "ERR_STATVFS", "statvfs impossible"},
00111   {ERR_OPENDIR, "ERR_OPENDIR", "opendir impossible"},
00112   {ERR_READDIR, "ERR_READDIR", "readdir impossible"},
00113   {ERR_CLOSEDIR, "ERR_CLOSEDIR", "closedir impossible"},
00114   {ERR_LSTAT, "ERR_LSTAT", "lstat impossible"},
00115   {ERR_GETWD, "ERR_GETWD", "getwd impossible"},
00116   {ERR_CHDIR, "ERR_CHDIR", "chdir impossible"},
00117   {ERR_CHOWN, "ERR_CHOWN", "chown impossible"},
00118   {ERR_MKDIR, "ERR_MKDIR", "mkdir impossible"},
00119   {ERR_OPEN, "ERR_OPEN", "open impossible"},
00120   {ERR_READ, "ERR_READ", "read impossible"},
00121   {ERR_WRITE, "ERR_WRITE", "write impossible"},
00122   {ERR_UTIMES, "ERR_UTIMES", "utimes impossible"},
00123   {ERR_READLINK, "ERR_READLINK", "readlink impossible"},
00124   {ERR_SYMLINK, "ERR_SYMLINK", "symlink impossible"},
00125   {ERR_SYSTEM, "ERR_SYSTEM", "system impossible"},
00126   {ERR_POPEN, "ERR_POPEN", "popen impossible"},
00127   {ERR_LSEEK, "ERR_LSEEK", "lseek impossible"},
00128   {ERR_PTHREAD_CREATE, "ERR_PTHREAD_CREATE", "pthread_create impossible"},
00129   {ERR_RECV, "ERR_RECV", "recv impossible"},
00130   {ERR_FOPEN, "ERR_FOPEN", "fopen impossible"},
00131   {ERR_GETCWD, "ERR_GETCWD", "getcwd impossible"},
00132   {ERR_SETUID, "ERR_SETUID", "setuid impossible"},
00133   {ERR_RENAME, "ERR_RENAME", "rename impossible"},
00134   {ERR_UNLINK, "ERR_UNLINK", "unlink impossible"},
00135   {ERR_SELECT, "ERR_SELECT", "select impossible"},
00136   {ERR_WAIT, "ERR_WAIT", "wait impossible"},
00137   {ERR_SETSID, "ERR_SETSID", "setsid impossible"},
00138   {ERR_SETGID, "ERR_SETGID", "setgid impossible"},
00139   {ERR_GETGROUPS, "ERR_GETGROUPS", "getgroups impossible"},
00140   {ERR_SETGROUPS, "ERR_SETGROUPS", "setgroups impossible"},
00141   {ERR_UMASK, "ERR_UMASK", "umask impossible"},
00142   {ERR_CREAT, "ERR_CREAT", "creat impossible"},
00143   {ERR_SETSOCKOPT, "ERR_SETSOCKOPT", "setsockopt impossible"},
00144   {ERR_DIRECTIO, "ERR_DIRECTIO", "appel a directio impossible"},
00145   {ERR_GETRLIMIT, "ERR_GETRLIMIT", "appel a getrlimit impossible"},
00146   {ERR_SETRLIMIT, "ERR_SETRLIMIT", "appel a setrlimit"},
00147   {ERR_TRUNCATE, "ERR_TRUNCATE", "appel a truncate impossible"},
00148   {ERR_PTHREAD_MUTEX_INIT, "ERR_PTHREAD_MUTEX_INIT", "init d'un mutex"},
00149   {ERR_PTHREAD_COND_INIT, "ERR_PTHREAD_COND_INIT", "init d'une variable de condition"},
00150   {ERR_FCNTL, "ERR_FCNTL", "call to fcntl is impossible"},
00151   {ERR_NULL, "ERR_NULL", ""}
00152 };
00153 
00154 /* constants */
00155 static int masque_log = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
00156 
00157 /* Array of error families */
00158 
00159 static family_t tab_family[MAX_NUM_FAMILY];
00160 
00161 /* Global variables */
00162 
00163 static char nom_programme[1024];
00164 static char nom_host[256];
00165 static int syslog_opened = 0 ;
00166 
00167 //extern nfs_parameter_t nfs_param;
00168 
00169 /*
00170  * Variables specifiques aux threads.
00171  */
00172 
00173 typedef struct ThreadLogContext_t
00174 {
00175 
00176   char nom_fonction[STR_LEN];
00177 
00178 } ThreadLogContext_t;
00179 
00180 /* threads keys */
00181 static pthread_key_t thread_key;
00182 static pthread_once_t once_key = PTHREAD_ONCE_INIT;
00183 
00184 #define LogChanges(format, args...) \
00185   do { \
00186     if (LogComponents[COMPONENT_LOG].comp_log_type != TESTLOG || \
00187         LogComponents[COMPONENT_LOG].comp_log_level == NIV_FULL_DEBUG) \
00188       DisplayLogComponentLevel(COMPONENT_LOG, (char *)__FUNCTION__, \
00189                                NIV_NULL, "LOG: " format, ## args ); \
00190   } while (0)
00191 
00192 cleanup_list_element *cleanup_list = NULL;
00193 
00194 void RegisterCleanup(cleanup_list_element *clean)
00195 {
00196   clean->next = cleanup_list;
00197   cleanup_list = clean;
00198 }
00199 
00200 void Cleanup(void)
00201 {
00202   cleanup_list_element *c = cleanup_list;
00203   while(c != NULL)
00204     {
00205       c->clean();
00206       c = c->next;
00207     }
00208 }
00209 
00210 void Fatal(void)
00211 {
00212   Cleanup();
00213   exit(1);
00214 }
00215 
00216 #ifdef _DONT_HAVE_LOCALTIME_R
00217 
00218 /* Localtime is not reentrant...
00219  * So we are obliged to have a mutex for calling it.
00220  * pffff....
00221  */
00222 static pthread_mutex_t mutex_localtime = PTHREAD_MUTEX_INITIALIZER;
00223 
00224 /* thread-safe and PORTABLE version of localtime */
00225 
00226 static struct tm *Localtime_r(const time_t * p_time, struct tm *p_tm)
00227 {
00228   struct tm *p_tmp_tm;
00229 
00230   if(!p_tm)
00231     {
00232       errno = EFAULT;
00233       return NULL;
00234     }
00235 
00236   pthread_mutex_lock(&mutex_localtime);
00237 
00238   p_tmp_tm = localtime(p_time);
00239 
00240   /* copy the result */
00241   (*p_tm) = (*p_tmp_tm);
00242 
00243   pthread_mutex_unlock(&mutex_localtime);
00244 
00245   return p_tm;
00246 }
00247 #else
00248 # define Localtime_r localtime_r
00249 #endif
00250 
00251 /* Init of pthread_keys */
00252 static void init_keys(void)
00253 {
00254   if(pthread_key_create(&thread_key, NULL) == -1)
00255     LogCrit(COMPONENT_LOG,
00256             "init_keys - pthread_key_create returned %d (%s)",
00257             errno, strerror(errno));
00258 }                               /* init_keys */
00259 
00260 
00261 const char *emergency = "* log emergency *";
00262 
00267 static ThreadLogContext_t *Log_GetThreadContext(int ok_errors)
00268 {
00269   ThreadLogContext_t *p_current_thread_vars;
00270 
00271   /* first, we init the keys if this is the first time */
00272   if(pthread_once(&once_key, init_keys) != 0)
00273     {
00274       if (ok_errors)
00275         LogCrit(COMPONENT_LOG_EMERG,
00276                 "Log_GetThreadContext - pthread_once returned %d (%s)",
00277                 errno, strerror(errno));
00278       return NULL;
00279     }
00280 
00281   p_current_thread_vars = (ThreadLogContext_t *) pthread_getspecific(thread_key);
00282 
00283   /* we allocate the thread key if this is the first time */
00284   if(p_current_thread_vars == NULL)
00285     {
00286       /* allocates thread structure */
00287       p_current_thread_vars = (ThreadLogContext_t *) malloc(sizeof(ThreadLogContext_t));
00288 
00289       if(p_current_thread_vars == NULL)
00290         {
00291           if (ok_errors)
00292             LogCrit(COMPONENT_LOG_EMERG,
00293                     "Log_GetThreadContext - malloc returned %d (%s)",
00294                     errno, strerror(errno));
00295           return NULL;
00296         }
00297 
00298       /* inits thread structures */
00299       p_current_thread_vars->nom_fonction[0] = '\0';
00300 
00301       /* set the specific value */
00302       pthread_setspecific(thread_key, (void *)p_current_thread_vars);
00303 
00304       if (ok_errors)
00305         LogFullDebug(COMPONENT_LOG_EMERG, "malloc => %p",
00306                      p_current_thread_vars);
00307     }
00308 
00309   return p_current_thread_vars;
00310 
00311 }                               /* Log_GetThreadContext */
00312 
00313 static inline const char *Log_GetThreadFunction(int ok_errors)
00314 {
00315   ThreadLogContext_t *context = Log_GetThreadContext(ok_errors);
00316 
00317   if (context == NULL)
00318     return emergency;
00319   else
00320     return context->nom_fonction;
00321 }
00322 
00323 void GetNameFunction(char *name, int len)
00324 {
00325   const char *s = Log_GetThreadFunction(0);
00326 
00327   if (s != emergency && s != NULL)
00328     strncpy(name, s, len);
00329   else
00330     snprintf(name, len, "Thread %p", (caddr_t)pthread_self());
00331 }
00332 
00333 /*
00334  * Fait la conversion nom du niveau de log
00335  * en ascii vers valeur numerique du niveau
00336  *
00337  */
00338 
00339 int ReturnLevelAscii(const char *LevelEnAscii)
00340 {
00341   int i = 0;
00342 
00343   for(i = 0; i < ARRAY_SIZE(tabLogLevel); i++)
00344     if(!strcmp(tabLogLevel[i].str, LevelEnAscii))
00345       return tabLogLevel[i].value;
00346 
00347   /* Si rien n'est trouve on retourne -1 */
00348   return -1;
00349 }                               /* ReturnLevelAscii */
00350 
00351 char *ReturnLevelInt(int level)
00352 {
00353   int i = 0;
00354 
00355   for(i = 0; i < ARRAY_SIZE(tabLogLevel); i++)
00356     if(tabLogLevel[i].value == level)
00357       return tabLogLevel[i].str;
00358 
00359   /* Si on n'a rien trouve on retourne NULL */
00360   return NULL;
00361 }                               /* ReturnLevelInt */
00362 
00363 /*
00364  * Set le nom du programme en cours.
00365  */
00366 void SetNamePgm(char *nom)
00367 {
00368 
00369   /* Cette fonction n'est pas thread-safe car le nom du programme
00370    * est commun a tous les threads */
00371   strcpy(nom_programme, nom);
00372 }                               /* SetNamePgm */
00373 
00374 /*
00375  * Set le nom d'host en cours
00376  */
00377 void SetNameHost(char *nom)
00378 {
00379   strcpy(nom_host, nom);
00380 }                               /* SetNameHost */
00381 
00382 /*
00383  *
00384  * Set le nom de la fonction en cours
00385  *
00386  */
00387 void SetNameFunction(char *nom)
00388 {
00389   ThreadLogContext_t *context = Log_GetThreadContext(0);
00390 
00391   if (context != NULL)
00392     strcpy(context->nom_fonction, nom);
00393 }                               /* SetNameFunction */
00394 
00395 /*
00396  * Cette fonction permet d'installer un handler de signal
00397  */
00398 
00399 static void ArmeSignal(int signal, void (*action) ())
00400 {
00401   struct sigaction act;         /* Soyons POSIX et puis signal() c'est pas joli */
00402 
00403   /* Mise en place des champs du struct sigaction */
00404   act.sa_flags = 0;
00405   act.sa_handler = action;
00406   sigemptyset(&act.sa_mask);
00407 
00408   if(sigaction(signal, &act, NULL) == -1)
00409     LogCrit(COMPONENT_LOG,
00410             "Impossible to arm signal %d, error %d (%s)",
00411             signal, errno, strerror(errno));
00412 }                               /* ArmeSignal */
00413 
00414 /*
00415  *
00416  * Cinq fonctions pour gerer le niveau de debug et le controler
00417  * a distance au travers de handlers de signaux
00418  *
00419  * InitDebug
00420  * IncrementeLevelDebug
00421  * DecrementeLevelDebug
00422  * SetLevelDebug
00423  * ReturnLevelDebug
00424  *
00425  */
00426 
00427 void SetComponentLogLevel(log_components_t component, int level_to_set)
00428 {
00429   if (component == COMPONENT_ALL)
00430     {
00431       SetLevelDebug(level_to_set);
00432       return;
00433     }
00434 
00435   if(level_to_set < NIV_NULL)
00436     level_to_set = NIV_NULL;
00437 
00438   if(level_to_set >= NB_LOG_LEVEL)
00439     level_to_set = NB_LOG_LEVEL - 1;
00440 
00441   if (LogComponents[component].comp_log_level != level_to_set)
00442     {
00443       LogChanges("Changing log level of %s from %s to %s",
00444                  LogComponents[component].comp_name,
00445                  ReturnLevelInt(LogComponents[component].comp_log_level),
00446                  ReturnLevelInt(level_to_set));
00447       LogComponents[component].comp_log_level = level_to_set;
00448     }
00449 }
00450 
00451 inline int ReturnLevelDebug()
00452 {
00453   return LogComponents[COMPONENT_ALL].comp_log_level;
00454 }                               /* ReturnLevelDebug */
00455 
00456 void _SetLevelDebug(int level_to_set)
00457 {
00458   int i;
00459 
00460   if(level_to_set < NIV_NULL)
00461     level_to_set = NIV_NULL;
00462 
00463   if(level_to_set >= NB_LOG_LEVEL)
00464     level_to_set = NB_LOG_LEVEL - 1;
00465 
00466   for (i = COMPONENT_ALL; i < COMPONENT_COUNT; i++)
00467       LogComponents[i].comp_log_level = level_to_set;
00468 }                               /* SetLevelDebug */
00469 
00470 void SetLevelDebug(int level_to_set)
00471 {
00472   _SetLevelDebug(level_to_set);
00473 
00474   LogChanges("Setting log level for all components to %s",
00475              ReturnLevelInt(LogComponents[COMPONENT_ALL].comp_log_level));
00476 }
00477 
00478 static void IncrementeLevelDebug()
00479 {
00480   _SetLevelDebug(ReturnLevelDebug() + 1);
00481 
00482   LogChanges("SIGUSR1 Increasing log level for all components to %s",
00483              ReturnLevelInt(LogComponents[COMPONENT_ALL].comp_log_level));
00484 }                               /* IncrementeLevelDebug */
00485 
00486 static void DecrementeLevelDebug()
00487 {
00488   _SetLevelDebug(ReturnLevelDebug() - 1);
00489 
00490   LogChanges("SIGUSR2 Decreasing log level for all components to %s",
00491              ReturnLevelInt(LogComponents[COMPONENT_ALL].comp_log_level));
00492 }                               /* DecrementeLevelDebug */
00493 
00494 void InitLogging()
00495 {
00496   int i;
00497   char *env_value;
00498   int newlevel, component, oldlevel;
00499 
00500   /* Initialisation du tableau des familys */
00501   tab_family[0].num_family = 0;
00502   tab_family[0].tab_err = (family_error_t *) tab_systeme_err;
00503   strcpy(tab_family[0].name_family, "Errors Systeme UNIX");
00504 
00505   for(i = 1; i < MAX_NUM_FAMILY; i++)
00506     tab_family[i].num_family = UNUSED_SLOT;
00507 
00508   ArmeSignal(SIGUSR1, IncrementeLevelDebug);
00509   ArmeSignal(SIGUSR2, DecrementeLevelDebug);
00510 
00511   for(component = COMPONENT_ALL; component < COMPONENT_COUNT; component++)
00512     {
00513       env_value = getenv(LogComponents[component].comp_name);
00514       if (env_value == NULL)
00515         continue;
00516       newlevel = ReturnLevelAscii(env_value);
00517       if (newlevel == -1) {
00518         LogMajor(COMPONENT_LOG,
00519                  "Environment variable %s exists, but the value %s is not a valid log level.",
00520                  LogComponents[component].comp_name, env_value);
00521         continue;
00522       }
00523       oldlevel = LogComponents[component].comp_log_level;
00524       LogComponents[component].comp_log_level = newlevel;
00525       LogChanges("Using environment variable to switch log level for %s from %s to %s",
00526                  LogComponents[component].comp_name, ReturnLevelInt(oldlevel),
00527                  ReturnLevelInt(newlevel));
00528     }
00529 
00530 }                               /* InitLevelDebug */
00531 
00532 /*
00533  * Une fonction d'affichage tout a fait generique
00534  */
00535 
00536 static void DisplayLogString_valist(char *buff_dest, char * function, log_components_t component, char *format, va_list arguments)
00537 {
00538   char texte[STR_LEN_TXT];
00539   struct tm the_date;
00540   time_t tm;
00541   const char *threadname = Log_GetThreadFunction(component != COMPONENT_LOG_EMERG);
00542 
00543   tm = time(NULL);
00544   Localtime_r(&tm, &the_date);
00545 
00546   /* Ecriture sur le fichier choisi */
00547   log_vsnprintf(texte, STR_LEN_TXT, format, arguments);
00548 
00549   if(LogComponents[component].comp_log_level < LogComponents[LOG_MESSAGE_VERBOSITY].comp_log_level)
00550     snprintf(buff_dest, STR_LEN_TXT,
00551              "%.2d/%.2d/%.4d %.2d:%.2d:%.2d epoch=%ld : %s : %s-%d[%s] :%s\n",
00552              the_date.tm_mday, the_date.tm_mon + 1, 1900 + the_date.tm_year,
00553              the_date.tm_hour, the_date.tm_min, the_date.tm_sec, tm, nom_host,
00554              nom_programme, getpid(), threadname,
00555              texte);
00556   else
00557     snprintf(buff_dest, STR_LEN_TXT,
00558              "%.2d/%.2d/%.4d %.2d:%.2d:%.2d epoch=%ld : %s : %s-%d[%s] :%s :%s\n",
00559              the_date.tm_mday, the_date.tm_mon + 1, 1900 + the_date.tm_year,
00560              the_date.tm_hour, the_date.tm_min, the_date.tm_sec, tm, nom_host,
00561              nom_programme, getpid(), threadname, function,
00562              texte);
00563 }                               /* DisplayLogString_valist */
00564 
00565 static int DisplayLogSyslog_valist(log_components_t component, char * function,
00566                                    int level, char * format, va_list arguments)
00567 {
00568   char texte[STR_LEN_TXT];
00569   const char *threadname = Log_GetThreadFunction(component != COMPONENT_LOG_EMERG);
00570 
00571   if( !syslog_opened )
00572    {
00573      openlog("nfs-ganesha", LOG_PID, LOG_USER);
00574      syslog_opened = 1;
00575    }
00576 
00577   /* Ecriture sur le fichier choisi */
00578   log_vsnprintf(texte, STR_LEN_TXT, format, arguments);
00579 
00580   if(LogComponents[component].comp_log_level < LogComponents[LOG_MESSAGE_VERBOSITY].comp_log_level)
00581     syslog(tabLogLevel[level].syslog_level, "[%s] :%s", threadname, texte);
00582   else
00583     syslog(tabLogLevel[level].syslog_level, "[%s] :%s :%s", threadname, function, texte);
00584 
00585   return 1 ;
00586 } /* DisplayLogSyslog_valist */
00587 
00588 static int DisplayLogFlux_valist(FILE * flux, char * function,
00589                                  log_components_t component, char *format,
00590                                  va_list arguments)
00591 {
00592   char tampon[STR_LEN_TXT];
00593 
00594   DisplayLogString_valist(tampon, function, component, format, arguments);
00595 
00596   fprintf(flux, "%s", tampon);
00597   return fflush(flux);
00598 }                               /* DisplayLogFlux_valist */
00599 
00600 static int DisplayTest_valist(log_components_t component, char *format,
00601                               va_list arguments)
00602 {
00603   char text[STR_LEN_TXT];
00604 
00605   log_vsnprintf(text, STR_LEN_TXT, format, arguments);
00606 
00607   fprintf(stdout, "%s\n", text);
00608   return fflush(stdout);
00609 }
00610 
00611 static int DisplayBuffer_valist(char *buffer, log_components_t component,
00612                                 char *format, va_list arguments)
00613 {
00614   return log_vsnprintf(buffer, STR_LEN_TXT, format, arguments);
00615 }
00616 
00617 static int DisplayLogPath_valist(char *path, char * function,
00618                                  log_components_t component, char *format,
00619                                  va_list arguments)
00620 {
00621   char tampon[STR_LEN_TXT];
00622   int fd, my_status;
00623 
00624   DisplayLogString_valist(tampon, function, component, format, arguments);
00625 
00626   if(path[0] != '\0')
00627     {
00628 #ifdef _LOCK_LOG
00629       if((fd = open(path, O_WRONLY | O_SYNC | O_APPEND | O_CREAT, masque_log)) != -1)
00630         {
00631           /* un verrou sur fichier */
00632           struct flock lock_file;
00633 
00634           /* mise en place de la structure de verrou sur fichier */
00635           lock_file.l_type = F_WRLCK;
00636           lock_file.l_whence = SEEK_SET;
00637           lock_file.l_start = 0;
00638           lock_file.l_len = 0;
00639 
00640           if(fcntl(fd, F_SETLKW, (char *)&lock_file) != -1)
00641             {
00642               /* Si la prise du verrou est OK */
00643               write(fd, tampon, strlen(tampon));
00644 
00645               /* Relache du verrou sur fichier */
00646               lock_file.l_type = F_UNLCK;
00647 
00648               fcntl(fd, F_SETLKW, (char *)&lock_file);
00649 
00650               /* fermeture du fichier */
00651               close(fd);
00652               return SUCCES;
00653             }                   /* if fcntl */
00654           else
00655             {
00656               /* Si la prise du verrou a fait un probleme */
00657               my_status = errno;
00658               close(fd);
00659             }
00660         }
00661 
00662 #else
00663       if((fd = open(path, O_WRONLY | O_NONBLOCK | O_APPEND | O_CREAT, masque_log)) != -1)
00664         {
00665           if(write(fd, tampon, strlen(tampon)) < strlen(tampon))
00666           {
00667             fprintf(stderr, "Error: couldn't complete write to the log file, ensure disk has not filled up");
00668             close(fd);
00669             return ERR_FICHIER_LOG;
00670           }
00671 
00672           /* fermeture du fichier */
00673           close(fd);
00674           return SUCCES;
00675         }
00676 #endif
00677       else
00678         {
00679           /* Si l'ouverture du fichier s'est mal passee */
00680           my_status = errno;
00681         }
00682       fprintf(stderr, "Error %s : %s : status %d on file %s message was:\n%s\n",
00683               tab_systeme_err[ERR_FICHIER_LOG].label,
00684               tab_systeme_err[ERR_FICHIER_LOG].msg, my_status, path, tampon);
00685 
00686       return ERR_FICHIER_LOG;
00687     }
00688   /* if path */
00689   return SUCCES;
00690 }                               /* DisplayLogPath_valist */
00691 
00692 /*
00693  *
00694  * Les routines de gestions des messages d'erreur
00695  *
00696  */
00697 
00698 int AddFamilyError(int num_family, char *name_family, family_error_t * tab_err)
00699 {
00700   int i = 0;
00701 
00702   /* Le numero de la family est entre -1 et MAX_NUM_FAMILY */
00703   if((num_family < -1) || (num_family >= MAX_NUM_FAMILY))
00704     return -1;
00705 
00706   /* On n'occupe pas 0 car ce sont les erreurs du systeme */
00707   if(num_family == 0)
00708     return -1;
00709 
00710   /* On cherche une entree vacante */
00711   for(i = 0; i < MAX_NUM_FAMILY; i++)
00712     if(tab_family[i].num_family == UNUSED_SLOT)
00713       break;
00714 
00715   /* On verifie que la table n'est pas pleine */
00716   if(i == MAX_NUM_FAMILY)
00717     return -1;
00718 
00719   tab_family[i].num_family = (num_family != -1) ? num_family : i;
00720   tab_family[i].tab_err = tab_err;
00721   strcpy(tab_family[i].name_family, name_family);
00722 
00723   return tab_family[i].num_family;
00724 }                               /* AddFamilyError */
00725 
00726 char *ReturnNameFamilyError(int num_family)
00727 {
00728   int i = 0;
00729 
00730   for(i = 0; i < MAX_NUM_FAMILY; i++)
00731     if(tab_family[i].num_family == num_family)
00732       {
00733         /* A quoi sert cette ligne ??????!!!!!! */
00734         /* tab_family[i].num_family = UNUSED_SLOT ; */
00735         return tab_family[i].name_family;
00736       }
00737 
00738   /* Sinon on retourne NULL */
00739   return NULL;
00740 }                               /* ReturnFamilyError */
00741 
00742 /* Cette fonction trouve une family dans le tabelau des familys d'erreurs */
00743 static family_error_t *TrouveTabErr(int num_family)
00744 {
00745   int i = 0;
00746 
00747   for(i = 0; i < MAX_NUM_FAMILY; i++)
00748     {
00749       if(tab_family[i].num_family == num_family)
00750         {
00751           return tab_family[i].tab_err;
00752         }
00753     }
00754 
00755   /* Sinon on retourne NULL */
00756   return NULL;
00757 }                               /* TrouveTabErr */
00758 
00759 static family_error_t TrouveErr(family_error_t * tab_err, int num)
00760 {
00761   int i = 0;
00762   family_error_t returned_err;
00763 
00764   do
00765     {
00766 
00767       if(tab_err[i].numero == num || tab_err[i].numero == ERR_NULL)
00768         {
00769           returned_err = tab_err[i];
00770           break;
00771         }
00772 
00773       i += 1;
00774     }
00775   while(1);
00776 
00777   return returned_err;
00778 }                               /* TrouveErr */
00779 
00780 int MakeLogError(char *buffer, int num_family, int num_error, int status,
00781                   int ma_ligne)
00782 {
00783   family_error_t *tab_err = NULL;
00784   family_error_t the_error;
00785 
00786   /* Find the family */
00787   if((tab_err = TrouveTabErr(num_family)) == NULL)
00788     return -1;
00789 
00790   /* find the error */
00791   the_error = TrouveErr(tab_err, num_error);
00792 
00793   if(status == 0)
00794     {
00795       return sprintf(buffer, "Error %s : %s : status %d : Line %d",
00796                      the_error.label, the_error.msg, status, ma_ligne);
00797     }
00798   else
00799     {
00800       char tempstr[1024];
00801       char *errstr;
00802       errstr = strerror_r(status, tempstr, 1024);
00803 
00804       return sprintf(buffer, "Error %s : %s : status %d : %s : Line %d",
00805                      the_error.label, the_error.msg, status, errstr, ma_ligne);
00806     }
00807 }                               /* MakeLogError */
00808 
00809 /* Un sprintf personnalisé */
00810 /* Cette macro est utilisee a chaque fois que l'on avance d'un pas dans le parsing */
00811 #define ONE_STEP  do { iterformat +=1 ; len += 1; } while(0)
00812 
00813 #define NO_TYPE       0
00814 #define INT_TYPE      1
00815 #define LONG_TYPE     2
00816 #define CHAR_TYPE     3
00817 #define STRING_TYPE   4
00818 #define FLOAT_TYPE    5
00819 #define DOUBLE_TYPE   6
00820 #define POINTEUR_TYPE 7
00821 
00822 /* Type specifiques a la log */
00823 #define EXTENDED_TYPE 8
00824 
00825 #define STATUS_SHORT       1
00826 #define STATUS_LONG        2
00827 #define CONTEXTE_SHORT     3
00828 #define CONTEXTE_LONG      4
00829 #define ERREUR_SHORT       5
00830 #define ERREUR_LONG        6
00831 #define ERRNUM_SHORT       7
00832 #define ERRNUM_LONG        8
00833 #define ERRCTX_SHORT       9
00834 #define ERRCTX_LONG        10
00835 #define CHANGE_ERR_FAMILY  11
00836 #define CHANGE_CTX_FAMILY  12
00837 #define ERRNO_SHORT        13
00838 #define ERRNO_LONG         14
00839 
00840 #define NO_LONG 0
00841 #define SHORT_LG 1
00842 #define LONG_LG 2
00843 #define LONG_LONG_LG 3
00844 
00845 #define MAX_STR_TOK LOG_MAX_STRLEN
00846 
00847 int log_vsnprintf(char *out, size_t taille, char *format, va_list arguments)
00848 {
00849   /* TODO: eventually remove this entirely, but this makes the code
00850    * work for now */
00851   return vsnprintf(out, taille, format, arguments);
00852 }
00853 
00854 int log_snprintf(char *out, size_t n, char *format, ...)
00855 {
00856   va_list arguments;
00857   int rc;
00858 
00859   va_start(arguments, format);
00860   rc = log_vsnprintf(out, n, format, arguments);
00861   va_end(arguments);
00862 
00863   return rc;
00864 }
00865 
00866 int log_fprintf(FILE * file, char *format, ...)
00867 {
00868   va_list arguments;
00869   char tmpstr[LOG_MAX_STRLEN];
00870   int rc;
00871 
00872   va_start(arguments, format);
00873   memset(tmpstr, 0, LOG_MAX_STRLEN);
00874   rc = log_vsnprintf(tmpstr, LOG_MAX_STRLEN, format, arguments);
00875   va_end(arguments);
00876   fputs(tmpstr, file);
00877   return rc;
00878 }
00879 
00880 log_component_info __attribute__ ((__unused__)) LogComponents[COMPONENT_COUNT] =
00881 {
00882   { COMPONENT_ALL,               "COMPONENT_ALL", "",
00883     NIV_EVENT,
00884   },
00885   { COMPONENT_LOG,               "COMPONENT_LOG", "LOG",
00886     NIV_EVENT,
00887     SYSLOG,
00888     "SYSLOG"
00889   },
00890   { COMPONENT_LOG_EMERG,         "COMPONENT_LOG_EMERG", "LOG",
00891     NIV_EVENT,
00892     SYSLOG,
00893     "SYSLOG"
00894   },
00895   { COMPONENT_MEMALLOC,          "COMPONENT_MEMALLOC", "MEM ALLOC",
00896     NIV_EVENT,
00897     SYSLOG,
00898     "SYSLOG"
00899   },
00900   { COMPONENT_MEMLEAKS,          "COMPONENT_MEMLEAKS", "MEM LEAKS",
00901     NIV_EVENT,
00902     SYSLOG,
00903     "SYSLOG"
00904   },
00905   { COMPONENT_FSAL,              "COMPONENT_FSAL", "FSAL",
00906     NIV_EVENT,
00907     SYSLOG,
00908     "SYSLOG"
00909   },
00910   { COMPONENT_NFSPROTO,          "COMPONENT_NFSPROTO", "NFS PROTO",
00911     NIV_EVENT,
00912     SYSLOG,
00913     "SYSLOG"
00914   },
00915   { COMPONENT_NFS_V4,            "COMPONENT_NFS_V4", "NFS V4",
00916     NIV_EVENT,
00917     SYSLOG,
00918     "SYSLOG"
00919   },
00920   { COMPONENT_NFS_V4_PSEUDO,     "COMPONENT_NFS_V4_PSEUDO", "NFS V4 PSEUDO",
00921     NIV_EVENT,
00922     SYSLOG,
00923     "SYSLOG"
00924   },
00925   { COMPONENT_FILEHANDLE,        "COMPONENT_FILEHANDLE", "FILE HANDLE",
00926     NIV_EVENT,
00927     SYSLOG,
00928     "SYSLOG"
00929   },
00930   { COMPONENT_NFS_SHELL,         "COMPONENT_NFS_SHELL", "NFS SHELL",
00931 #ifdef _DEBUG_NFS_SHELL
00932     NIV_FULL_DEBUG,
00933 #else
00934     NIV_EVENT,
00935 #endif
00936     SYSLOG,
00937     "SYSLOG"
00938   },
00939   { COMPONENT_DISPATCH,          "COMPONENT_DISPATCH", "DISPATCH",
00940     NIV_EVENT,
00941     SYSLOG,
00942     "SYSLOG"
00943   },
00944   { COMPONENT_CACHE_CONTENT,     "COMPONENT_CACHE_CONTENT", "CACHE CONTENT",
00945     NIV_EVENT,
00946     SYSLOG,
00947     "SYSLOG"
00948   },
00949   { COMPONENT_CACHE_INODE,       "COMPONENT_CACHE_INODE", "CACHE INODE",
00950     NIV_EVENT,
00951     SYSLOG,
00952     "SYSLOG"
00953   },
00954   { COMPONENT_CACHE_INODE_GC,    "COMPONENT_CACHE_INODE_GC", "CACHE INODE GC",
00955     NIV_EVENT,
00956     SYSLOG,
00957     "SYSLOG"
00958   },
00959   { COMPONENT_CACHE_INODE_LRU,    "COMPONENT_CACHE_INODE_LRU", "CACHE INODE LRU",
00960     NIV_EVENT,
00961     SYSLOG,
00962     "SYSLOG"
00963   },
00964   { COMPONENT_HASHTABLE,         "COMPONENT_HASHTABLE", "HASH TABLE",
00965     NIV_EVENT,
00966     SYSLOG,
00967     "SYSLOG"
00968   },
00969   { COMPONENT_HASHTABLE_CACHE,   "COMPONENT_HASHTABLE_CACHE", "HASH TABLE CACHE",
00970     NIV_EVENT,
00971     SYSLOG,
00972     "SYSLOG"
00973   },
00974   { COMPONENT_LRU,               "COMPONENT_LRU", "LRU",
00975     NIV_EVENT,
00976     SYSLOG,
00977     "SYSLOG"
00978   },
00979   { COMPONENT_DUPREQ,            "COMPONENT_DUPREQ", "DUPREQ",
00980     NIV_EVENT,
00981     SYSLOG,
00982     "SYSLOG"
00983   },
00984   { COMPONENT_RPCSEC_GSS,        "COMPONENT_RPCSEC_GSS", "RPCSEC GSS",
00985     NIV_EVENT,
00986     SYSLOG,
00987     "SYSLOG"
00988   },
00989   { COMPONENT_INIT,              "COMPONENT_INIT", "NFS STARTUP",
00990     NIV_EVENT,
00991     SYSLOG,
00992     "SYSLOG"
00993   },
00994   { COMPONENT_MAIN,              "COMPONENT_MAIN", "MAIN",
00995     NIV_EVENT,
00996     SYSLOG,
00997     "SYSLOG"
00998   },
00999   { COMPONENT_IDMAPPER,          "COMPONENT_IDMAPPER", "ID MAPPER",
01000     NIV_EVENT,
01001     SYSLOG,
01002     "SYSLOG"
01003   },
01004   { COMPONENT_NFS_READDIR,       "COMPONENT_NFS_READDIR", "NFS READDIR",
01005     NIV_EVENT,
01006     SYSLOG,
01007     "SYSLOG"
01008   },
01009 
01010   { COMPONENT_NFS_V4_LOCK,       "COMPONENT_NFS_V4_LOCK", "NFS V4 LOCK",
01011     NIV_EVENT,
01012     SYSLOG,
01013     "SYSLOG"
01014   },
01015   { COMPONENT_NFS_V4_XATTR,      "COMPONENT_NFS_V4_XATTR", "NFS V4 XATTR",
01016     NIV_EVENT,
01017     SYSLOG,
01018     "SYSLOG"
01019   },
01020   { COMPONENT_NFS_V4_REFERRAL,   "COMPONENT_NFS_V4_REFERRAL", "NFS V4 REFERRAL",
01021     NIV_EVENT,
01022     SYSLOG,
01023     "SYSLOG"
01024   },
01025   { COMPONENT_MEMCORRUPT,        "COMPONENT_MEMCORRUPT", "MEM CORRUPT",
01026     NIV_EVENT,
01027     SYSLOG,
01028     "SYSLOG"
01029   },
01030   { COMPONENT_CONFIG,            "COMPONENT_CONFIG", "CONFIG",
01031     NIV_EVENT,
01032     SYSLOG,
01033     "SYSLOG"
01034   },
01035   { COMPONENT_CLIENTID,          "COMPONENT_CLIENTID", "CLIENT ID",
01036     NIV_EVENT,
01037     SYSLOG,
01038     "SYSLOG"
01039   },
01040   { COMPONENT_STDOUT,            "COMPONENT_STDOUT", "STDOUT",
01041     NIV_EVENT,
01042     SYSLOG,
01043     "SYSLOG"
01044   },
01045   { COMPONENT_SESSIONS,          "COMPONENT_SESSIONS", "SESSIONS",
01046     NIV_EVENT,
01047     SYSLOG,
01048     "SYSLOG"
01049   },
01050   { COMPONENT_PNFS,              "COMPONENT_PNFS", "PNFS",
01051     NIV_EVENT,
01052     SYSLOG,
01053     "SYSLOG"
01054   },
01055   { COMPONENT_RPC_CACHE,         "COMPONENT_RPC_CACHE", "RPC CACHE",
01056     NIV_EVENT,
01057     SYSLOG,
01058     "SYSLOG"
01059   },
01060   { COMPONENT_RW_LOCK,           "COMPONENT_RW_LOCK", "RW LOCK",
01061     NIV_EVENT,
01062     SYSLOG,
01063     "SYSLOG"
01064   },
01065   { COMPONENT_NLM,               "COMPONENT_NLM", "NLM",
01066     NIV_EVENT,
01067     SYSLOG,
01068     "SYSLOG"
01069   },
01070   { COMPONENT_RPC,               "COMPONENT_RPC", "RPC",
01071     NIV_EVENT,
01072     SYSLOG,
01073     "SYSLOG"
01074   },
01075   { COMPONENT_NFS_CB,            "COMPONENT_NFS_CB", "NFS CB",
01076     NIV_EVENT,
01077     SYSLOG,
01078     "SYSLOG"
01079   },
01080   { COMPONENT_THREAD,            "COMPONENT_THREAD", "THREAD",
01081     NIV_EVENT,
01082     SYSLOG,
01083     "SYSLOG"
01084   },
01085   { COMPONENT_NFS_V4_ACL,        "COMPONENT_NFS_V4_ACL", "NFS V4 ACL",
01086     NIV_EVENT,
01087     SYSLOG,
01088     "SYSLOG"
01089   },
01090   { COMPONENT_STATE,             "COMPONENT_STATE", "STATE",
01091     NIV_EVENT,
01092     SYSLOG,
01093     "SYSLOG"
01094   },
01095   { COMPONENT_9P,                "COMPONENT_9P", "9P",
01096     NIV_EVENT,
01097     SYSLOG,
01098     "SYSLOG"
01099   },
01100   { COMPONENT_9P_DISPATCH,       "COMPONENT_9P_DISPATCH", "9P DISPATCH",
01101     NIV_EVENT,
01102     SYSLOG,
01103     "SYSLOG"
01104   },
01105   { COMPONENT_FSAL_UP,             "COMPONENT_FSAL_UP", "FSAL_UP",
01106     NIV_EVENT,
01107     SYSLOG,
01108     "SYSLOG"
01109   },
01110   { COMPONENT_DBUS,                "COMPONENT_DBUS", "DBUS",
01111     NIV_EVENT,
01112     SYSLOG,
01113     "SYSLOG"
01114   },
01115   { LOG_MESSAGE_VERBOSITY,        "LOG_MESSAGE_VERBOSITY",
01116                                   "LOG MESSAGE VERBOSITY",
01117     NIV_NULL,
01118     SYSLOG,
01119     "SYSLOG"
01120   },
01121 };
01122 
01123 int DisplayLogComponentLevel(log_components_t component,
01124                              char * function,
01125                              log_levels_t level,
01126                              char *format, ...)
01127 {
01128   va_list arguments;
01129   int rc;
01130   va_start(arguments, format);
01131 
01132   switch(LogComponents[component].comp_log_type)
01133     {
01134     case SYSLOG:
01135       rc = DisplayLogSyslog_valist(component, function, level, format, arguments);
01136       break;
01137     case FILELOG:
01138       rc = DisplayLogPath_valist(LogComponents[component].comp_log_file, function, component, format, arguments);
01139       break;
01140     case STDERRLOG:
01141       rc = DisplayLogFlux_valist(stderr, function, component, format, arguments);
01142       break;
01143     case STDOUTLOG:
01144       rc = DisplayLogFlux_valist(stdout, function, component, format, arguments);
01145       break;
01146     case TESTLOG:
01147       rc = DisplayTest_valist(component, format, arguments);
01148       break;
01149     case BUFFLOG:
01150       rc = DisplayBuffer_valist(LogComponents[component].comp_buffer, component, format, arguments);
01151       break;
01152     default:
01153       rc = ERR_FAILURE;
01154     }
01155 
01156   va_end(arguments);
01157 
01158   if(level == NIV_FATAL)
01159     Fatal();
01160 
01161   return rc;
01162 }
01163 
01164 int DisplayErrorComponentLogLine(log_components_t component,
01165                                  char * function,
01166                                  int num_family,
01167                                  int num_error,
01168                                  int status,
01169                                  int ma_ligne)
01170 {
01171   char buffer[STR_LEN_TXT];
01172 
01173   if(MakeLogError(buffer, num_family, num_error, status, ma_ligne) == -1)
01174     return -1;
01175   return DisplayLogComponentLevel(component, function, NIV_CRIT, "%s: %s",
01176                                   LogComponents[component].comp_str, buffer);
01177 }                               /* DisplayErrorLogLine */
01178 
01179 static int isValidLogPath(char *pathname)
01180 {
01181   char tempname[MAXPATHLEN];
01182 
01183   char *directory_name;
01184   int rc;
01185 
01186   strncpy(tempname, pathname, MAXPATHLEN);
01187 
01188   directory_name = dirname(tempname);
01189   if (directory_name == NULL)
01190       return 0;
01191 
01192   rc = access(directory_name, W_OK);
01193   switch(rc)
01194     {
01195     case 0:
01196       break; /* success !! */
01197     case EACCES:
01198       LogCrit(COMPONENT_LOG,
01199               "Either access is denied to the file or denied to one of the directories in %s",
01200               directory_name);
01201       break;
01202     case ELOOP:
01203       LogCrit(COMPONENT_LOG,
01204               "Too many symbolic links were encountered in resolving %s",
01205               directory_name);
01206       break;
01207     case ENAMETOOLONG:
01208       LogCrit(COMPONENT_LOG,
01209               "%s is too long of a pathname.",
01210               directory_name);
01211       break;
01212     case ENOENT:
01213       LogCrit(COMPONENT_LOG,
01214               "A component of %s does not exist.",
01215               directory_name);
01216       break;
01217     case ENOTDIR:
01218       LogCrit(COMPONENT_LOG,
01219               "%s is not a directory.",
01220               directory_name);
01221       break;
01222     case EROFS:
01223       LogCrit(COMPONENT_LOG,
01224               "Write permission was requested for a file on a read-only file system.");
01225       break;
01226     case EFAULT:
01227       LogCrit(COMPONENT_LOG,
01228               "%s points outside your accessible address space.",
01229               directory_name);
01230       break;
01231 
01232     default:
01233         break ;
01234     }
01235 
01236   return 1;
01237 }
01238 
01239 /*
01240  * Sets the default logging method (whether to a specific filepath or syslog.
01241  * During initialization this is used and separate layer logging defaults to
01242  * this destination.
01243  */
01244 void SetDefaultLogging(char *name)
01245 {
01246   int component;
01247 
01248   SetComponentLogFile(COMPONENT_LOG, name);
01249 
01250   LogChanges("Setting log destination for ALL components to %s", name);
01251   for(component = COMPONENT_ALL; component < COMPONENT_COUNT; component++)
01252     {
01253       if (component == COMPONENT_STDOUT)
01254         continue;
01255       SetComponentLogFile(component, name);
01256     }
01257 }                               /* SetDefaultLogging */
01258 
01259 int SetComponentLogFile(log_components_t component, char *name)
01260 {
01261   int newtype, changed;
01262 
01263   if (strcmp(name, "SYSLOG") == 0)
01264     newtype = SYSLOG;
01265   else if (strcmp(name, "STDERR") == 0)
01266     newtype = STDERRLOG;
01267   else if (strcmp(name, "STDOUT") == 0)
01268     newtype = STDOUTLOG;
01269   else if (strcmp(name, "TEST") == 0)
01270     newtype = TESTLOG;
01271   else
01272     newtype = FILELOG;
01273 
01274   if (newtype == FILELOG)
01275     {
01276       if (!isValidLogPath(name))
01277         {
01278           LogMajor(COMPONENT_LOG, "Could not set default logging to %s", name);
01279           errno = EINVAL;
01280           return -1;
01281         }
01282       }
01283 
01284   changed = (newtype != LogComponents[component].comp_log_type) ||
01285             (newtype == FILELOG && strcmp(name, LogComponents[component].comp_log_file) != 0);
01286 
01287   if (component != COMPONENT_LOG && changed)
01288     LogChanges("Changing log destination for %s from %s to %s",
01289                LogComponents[component].comp_name,
01290                LogComponents[component].comp_log_file,
01291                name);
01292 
01293   LogComponents[component].comp_log_type = newtype;
01294   strncpy(LogComponents[component].comp_log_file, name, MAXPATHLEN);
01295 
01296   if (component == COMPONENT_LOG && changed)
01297     LogChanges("Changing log destination for %s from %s to %s",
01298                LogComponents[component].comp_name,
01299                LogComponents[component].comp_log_file,
01300                name);
01301 
01302   return 0;
01303 }                               /* SetComponentLogFile */
01304 
01305 void SetComponentLogBuffer(log_components_t component, char *buffer)
01306 {
01307   LogComponents[component].comp_log_type = BUFFLOG;
01308   LogComponents[component].comp_buffer   = buffer;
01309 }
01310 
01311 /*
01312  *  Re-export component logging to TI-RPC internal logging
01313  */
01314 void
01315 rpc_warnx(/* const */ char *fmt, ...)
01316 {
01317     va_list ap;
01318     log_components_t comp = COMPONENT_RPC;
01319     int level;
01320 
01321     level = LogComponents[comp].comp_log_level;
01322     if (level < NIV_DEBUG)
01323         goto out;
01324 
01325     va_start(ap, fmt);
01326 
01327     switch(LogComponents[comp].comp_log_type) {
01328     case SYSLOG:
01329       DisplayLogSyslog_valist(comp, "rpc", level, fmt, ap);
01330       break;
01331     case FILELOG:
01332       DisplayLogPath_valist(LogComponents[comp].comp_log_file, "rpc",
01333                             comp, fmt, ap);
01334       break;
01335     case STDERRLOG:
01336       DisplayLogFlux_valist(stderr, "rpc", comp, fmt, ap);
01337       break;
01338     case STDOUTLOG:
01339       DisplayLogFlux_valist(stdout, "rpc", comp, fmt, ap);
01340       break;
01341     case TESTLOG:
01342       DisplayTest_valist(comp, fmt, ap);
01343       break;
01344     case BUFFLOG:
01345       DisplayBuffer_valist(LogComponents[comp].comp_buffer, comp, fmt, ap);
01346     } /* switch */
01347 
01348     va_end(ap);
01349 
01350 out:
01351     return;
01352 
01353 } /* rpc_warnx */
01354 
01355 /*
01356  * Pour info : Les tags de printf dont on peut se servir:
01357  * w DMNOPQTUWX
01358  */
01359 
01360 #ifdef _SNMP_ADM_ACTIVE
01361 
01362 int getComponentLogLevel(snmp_adm_type_union * param, void *opt)
01363 {
01364   long component = (long)opt;
01365 
01366   strcpy(param->string, ReturnLevelInt(LogComponents[component].comp_log_level));
01367   return 0;
01368 }
01369 
01370 int setComponentLogLevel(const snmp_adm_type_union * param, void *opt)
01371 {
01372   long component = (long)opt;
01373   int level_to_set = ReturnLevelAscii(param->string);
01374 
01375   if (level_to_set == -1)
01376     return -1;
01377 
01378   if (component == COMPONENT_ALL)
01379     {
01380       _SetLevelDebug(level_to_set);
01381 
01382       LogChanges("SNMP request changing log level for all components to %s",
01383                  ReturnLevelInt(level_to_set));
01384     }
01385   else
01386     {
01387       LogChanges("SNMP request changing log level of %s from %s to %s.",
01388                  LogComponents[component].comp_name,
01389                  ReturnLevelInt(LogComponents[component].comp_log_level),
01390                  ReturnLevelInt(level_to_set));
01391       LogComponents[component].comp_log_level = level_to_set;
01392     }
01393 
01394   return 0;
01395 }
01396 
01397 #endif /* _SNMP_ADM_ACTIVE */