nfs-ganesha 1.4
|
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 */