media/mtransport/third_party/nrappkit/src/log/r_log.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /**
michael@0 2 r_log.c
michael@0 3
michael@0 4
michael@0 5 Copyright (C) 2001, RTFM, Inc.
michael@0 6 Copyright (C) 2006, Network Resonance, Inc.
michael@0 7 All Rights Reserved
michael@0 8
michael@0 9 Redistribution and use in source and binary forms, with or without
michael@0 10 modification, are permitted provided that the following conditions
michael@0 11 are met:
michael@0 12
michael@0 13 1. Redistributions of source code must retain the above copyright
michael@0 14 notice, this list of conditions and the following disclaimer.
michael@0 15 2. Redistributions in binary form must reproduce the above copyright
michael@0 16 notice, this list of conditions and the following disclaimer in the
michael@0 17 documentation and/or other materials provided with the distribution.
michael@0 18 3. Neither the name of Network Resonance, Inc. nor the name of any
michael@0 19 contributors to this software may be used to endorse or promote
michael@0 20 products derived from this software without specific prior written
michael@0 21 permission.
michael@0 22
michael@0 23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
michael@0 24 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
michael@0 25 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
michael@0 26 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
michael@0 27 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
michael@0 28 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
michael@0 29 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
michael@0 30 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
michael@0 31 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
michael@0 32 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
michael@0 33 POSSIBILITY OF SUCH DAMAGE.
michael@0 34
michael@0 35
michael@0 36 ekr@rtfm.com Mon Dec 3 15:24:38 2001
michael@0 37 */
michael@0 38
michael@0 39
michael@0 40 static char *RCSSTRING __UNUSED__ ="$Id: r_log.c,v 1.10 2008/11/25 22:25:18 adamcain Exp $";
michael@0 41
michael@0 42
michael@0 43 #ifdef LINUX
michael@0 44 #define _BSD_SOURCE
michael@0 45 #endif
michael@0 46
michael@0 47 #include "r_log.h"
michael@0 48 #include "hex.h"
michael@0 49
michael@0 50 #include <string.h>
michael@0 51 #include <errno.h>
michael@0 52 #ifndef _MSC_VER
michael@0 53 #include <strings.h>
michael@0 54 #include <syslog.h>
michael@0 55 #endif
michael@0 56 #include <registry.h>
michael@0 57 #include <time.h>
michael@0 58
michael@0 59
michael@0 60 #include "nr_common.h"
michael@0 61 #include "nr_reg_keys.h"
michael@0 62
michael@0 63
michael@0 64 #define LOGGING_DEFAULT_LEVEL 5
michael@0 65
michael@0 66 int NR_LOG_LOGGING = 0;
michael@0 67
michael@0 68 static char *log_level_strings[]={
michael@0 69 "EMERG",
michael@0 70 "ALERT",
michael@0 71 "CRIT",
michael@0 72 "ERR",
michael@0 73 "WARNING",
michael@0 74 "NOTICE",
michael@0 75 "INFO",
michael@0 76 "DEBUG"
michael@0 77 };
michael@0 78
michael@0 79 static char *log_level_reg_strings[]={
michael@0 80 "emergency",
michael@0 81 "alert",
michael@0 82 "critical",
michael@0 83 "error",
michael@0 84 "warning",
michael@0 85 "notice",
michael@0 86 "info",
michael@0 87 "debug"
michael@0 88 };
michael@0 89
michael@0 90 #define LOGGING_REG_PREFIX "logging"
michael@0 91
michael@0 92 #define MAX_ERROR_STRING_SIZE 512
michael@0 93
michael@0 94 #define R_LOG_INITTED1 1
michael@0 95 #define R_LOG_INITTED2 2
michael@0 96
michael@0 97 #define LOG_NUM_DESTINATIONS 3
michael@0 98
michael@0 99 typedef struct log_type_ {
michael@0 100 char *facility_name;
michael@0 101 int level[LOG_NUM_DESTINATIONS];
michael@0 102 NR_registry dest_facility_key[LOG_NUM_DESTINATIONS];
michael@0 103 } log_type;
michael@0 104
michael@0 105 #define MAX_LOG_TYPES 1024
michael@0 106
michael@0 107 static log_type log_types[MAX_LOG_TYPES];
michael@0 108 static int log_type_ct;
michael@0 109
michael@0 110
michael@0 111 typedef struct log_destination_ {
michael@0 112 char *dest_name;
michael@0 113 int enabled;
michael@0 114 int default_level;
michael@0 115 r_dest_vlog *dest_vlog;
michael@0 116 } log_destination;
michael@0 117
michael@0 118
michael@0 119 #define LOG_LEVEL_UNDEFINED -1
michael@0 120 #define LOG_LEVEL_NONE -2
michael@0 121 #define LOG_LEVEL_USE_DEST_DEFAULT -3
michael@0 122
michael@0 123 static int stderr_vlog(int facility,int level,const char *format,va_list ap);
michael@0 124 static int syslog_vlog(int facility,int level,const char *format,va_list ap);
michael@0 125 static int noop_vlog(int facility,int level,const char *format,va_list ap);
michael@0 126
michael@0 127 static log_destination log_destinations[LOG_NUM_DESTINATIONS]={
michael@0 128 {
michael@0 129 "stderr",
michael@0 130 0,
michael@0 131 LOGGING_DEFAULT_LEVEL,
michael@0 132 stderr_vlog,
michael@0 133 },
michael@0 134 {
michael@0 135 "syslog",
michael@0 136 #ifndef WIN32
michael@0 137 1,
michael@0 138 #else
michael@0 139 0,
michael@0 140 #endif
michael@0 141 LOGGING_DEFAULT_LEVEL,
michael@0 142 syslog_vlog,
michael@0 143 },
michael@0 144 {
michael@0 145 "extra",
michael@0 146 0,
michael@0 147 LOGGING_DEFAULT_LEVEL,
michael@0 148 noop_vlog,
michael@0 149 },
michael@0 150 };
michael@0 151
michael@0 152 static int r_log_level=LOGGING_DEFAULT_LEVEL;
michael@0 153 static int r_log_level_environment=0;
michael@0 154 static int r_log_initted=0;
michael@0 155 static int r_log_env_verbose=0;
michael@0 156
michael@0 157 static void r_log_facility_change_cb(void *cb_arg, char action, NR_registry name);
michael@0 158 static void r_log_facility_delete_cb(void *cb_arg, char action, NR_registry name);
michael@0 159 static void r_log_destination_change_cb(void *cb_arg, char action, NR_registry name);
michael@0 160 static void r_log_default_level_change_cb(void *cb_arg, char action, NR_registry name);
michael@0 161 static int r_log_get_default_level(void);
michael@0 162 static int r_log_get_destinations(int usereg);
michael@0 163 static int r_logging_dest(int dest_index, int facility, int level);
michael@0 164 static int _r_log_init(int usereg);
michael@0 165 static int r_log_get_reg_level(NR_registry name, int *level);
michael@0 166
michael@0 167 int r_log_register(char *facility_name,int *log_facility)
michael@0 168 {
michael@0 169 int i,j;
michael@0 170 int level;
michael@0 171 int r,_status;
michael@0 172 char *buf=0;
michael@0 173 NR_registry dest_prefix, dest_facility_prefix;
michael@0 174
michael@0 175 for(i=0;i<log_type_ct;i++){
michael@0 176 if(!strcmp(facility_name,log_types[i].facility_name)){
michael@0 177 *log_facility=i;
michael@0 178 return(0);
michael@0 179 }
michael@0 180 }
michael@0 181
michael@0 182 if(log_type_ct==MAX_LOG_TYPES){
michael@0 183 ABORT(R_INTERNAL);
michael@0 184 }
michael@0 185
michael@0 186 i=log_type_ct;
michael@0 187
michael@0 188 /* Initial registration completed, increment log_type_ct */
michael@0 189 log_types[i].facility_name=r_strdup(facility_name);
michael@0 190 *log_facility=log_type_ct;
michael@0 191 log_type_ct++;
michael@0 192
michael@0 193 for(j=0; j<LOG_NUM_DESTINATIONS; j++){
michael@0 194 log_types[i].level[j]=LOG_LEVEL_UNDEFINED;
michael@0 195
michael@0 196 if(NR_reg_initted()){
michael@0 197
michael@0 198 if(snprintf(dest_prefix,sizeof(NR_registry),
michael@0 199 "logging.%s.facility",log_destinations[j].dest_name)>=sizeof(NR_registry))
michael@0 200 ABORT(R_INTERNAL);
michael@0 201
michael@0 202 if (r=NR_reg_make_registry(dest_prefix,facility_name,dest_facility_prefix))
michael@0 203 ABORT(r);
michael@0 204
michael@0 205 if(snprintf(log_types[i].dest_facility_key[j],sizeof(NR_registry),
michael@0 206 "%s.level",dest_facility_prefix)>=sizeof(NR_registry))
michael@0 207 ABORT(R_INTERNAL);
michael@0 208
michael@0 209 if(!r_log_get_reg_level(log_types[i].dest_facility_key[j],&level)){
michael@0 210 log_types[i].level[j]=level;
michael@0 211 }
michael@0 212
michael@0 213 /* Set a callback for the facility's level */
michael@0 214 if(r=NR_reg_register_callback(log_types[i].dest_facility_key[j],
michael@0 215 NR_REG_CB_ACTION_ADD|NR_REG_CB_ACTION_CHANGE,
michael@0 216 r_log_facility_change_cb,(void *)&(log_types[i].level[j])))
michael@0 217 ABORT(r);
michael@0 218 if(r=NR_reg_register_callback(log_types[i].dest_facility_key[j],
michael@0 219 NR_REG_CB_ACTION_DELETE,
michael@0 220 r_log_facility_delete_cb,(void *)&(log_types[i].level[j])))
michael@0 221 ABORT(r);
michael@0 222
michael@0 223 }
michael@0 224 }
michael@0 225
michael@0 226 _status=0;
michael@0 227 abort:
michael@0 228 if(_status)
michael@0 229 RFREE(buf);
michael@0 230 return(_status);
michael@0 231 }
michael@0 232
michael@0 233 int r_log_facility(int facility,char **typename)
michael@0 234 {
michael@0 235 if(facility >= 0 && facility < log_type_ct){
michael@0 236 *typename=log_types[facility].facility_name;
michael@0 237 return(0);
michael@0 238 }
michael@0 239 return(R_NOT_FOUND);
michael@0 240 }
michael@0 241
michael@0 242 static int r_log_get_reg_level(NR_registry name, int *out)
michael@0 243 {
michael@0 244 char level[32];
michael@0 245 int r,_status;
michael@0 246 int i;
michael@0 247
michael@0 248 if(r=NR_reg_get_string(name,level,sizeof(level)))
michael@0 249 ABORT(r);
michael@0 250
michael@0 251 if(!strcasecmp(level,"none")){
michael@0 252 *out=LOG_LEVEL_NONE;
michael@0 253 return(0);
michael@0 254 }
michael@0 255
michael@0 256 for(i=0;i<=LOG_DEBUG;i++){
michael@0 257 if(!strcasecmp(level,log_level_reg_strings[i])){
michael@0 258 *out=(int)i;
michael@0 259 return(0);
michael@0 260 }
michael@0 261 }
michael@0 262
michael@0 263 if(i>LOG_DEBUG){
michael@0 264 *out=LOG_LEVEL_UNDEFINED;
michael@0 265 }
michael@0 266
michael@0 267 _status=0;
michael@0 268 abort:
michael@0 269 return(_status);
michael@0 270 }
michael@0 271
michael@0 272 /* Handle the case where a value changes */
michael@0 273 static void r_log_facility_change_cb(void *cb_arg, char action, NR_registry name)
michael@0 274 {
michael@0 275 int *lt_level=(int *)cb_arg;
michael@0 276 int level;
michael@0 277 int r,_status;
michael@0 278
michael@0 279 if(r=r_log_get_reg_level(name,&level))
michael@0 280 ABORT(r);
michael@0 281
michael@0 282 *lt_level=level;
michael@0 283
michael@0 284 _status=0;
michael@0 285 abort:
michael@0 286 return;
michael@0 287 }
michael@0 288
michael@0 289 /* Handle the case where a value is deleted */
michael@0 290 static void r_log_facility_delete_cb(void *cb_arg, char action, NR_registry name)
michael@0 291 {
michael@0 292 int *lt_level=(int *)cb_arg;
michael@0 293
michael@0 294 *lt_level=LOG_LEVEL_UNDEFINED;
michael@0 295 }
michael@0 296
michael@0 297 int r_log(int facility,int level,const char *format,...)
michael@0 298 {
michael@0 299 va_list ap;
michael@0 300
michael@0 301 va_start(ap,format);
michael@0 302
michael@0 303 r_vlog(facility,level,format,ap);
michael@0 304 va_end(ap);
michael@0 305
michael@0 306 return(0);
michael@0 307 }
michael@0 308
michael@0 309 int r_dump(int facility,int level,char *name,char *data,int len)
michael@0 310 {
michael@0 311 char *hex = 0;
michael@0 312 int unused;
michael@0 313
michael@0 314 if(!r_logging(facility,level))
michael@0 315 return(0);
michael@0 316
michael@0 317 hex=RMALLOC((len*2)+1);
michael@0 318 if (!hex)
michael@0 319 return(R_FAILED);
michael@0 320
michael@0 321 if (nr_nbin2hex((UCHAR*)data, len, hex, len*2+1, &unused))
michael@0 322 strcpy(hex, "?");
michael@0 323
michael@0 324 if(name)
michael@0 325 r_log(facility,level,"%s[%d]=%s",name,len,hex);
michael@0 326 else
michael@0 327 r_log(facility,level,"%s",hex);
michael@0 328
michael@0 329 RFREE(hex);
michael@0 330 return(0);
michael@0 331 }
michael@0 332
michael@0 333 // Some platforms (notably WIN32) do not have this
michael@0 334 #ifndef va_copy
michael@0 335 #ifdef WIN32
michael@0 336 #define va_copy(dest, src) ( (dest) = (src) )
michael@0 337 #else // WIN32
michael@0 338 #error va_copy undefined, and semantics of assignment on va_list unknown
michael@0 339 #endif //WIN32
michael@0 340 #endif //va_copy
michael@0 341
michael@0 342 int r_vlog(int facility,int level,const char *format,va_list ap)
michael@0 343 {
michael@0 344 char log_fmt_buf[MAX_ERROR_STRING_SIZE];
michael@0 345 char *level_str="unknown";
michael@0 346 char *facility_str="unknown";
michael@0 347 char *fmt_str=(char *)format;
michael@0 348 int i;
michael@0 349
michael@0 350 if(r_log_env_verbose){
michael@0 351 if((level>=LOG_EMERG) && (level<=LOG_DEBUG))
michael@0 352 level_str=log_level_strings[level];
michael@0 353
michael@0 354 if(facility >= 0 && facility < log_type_ct)
michael@0 355 facility_str=log_types[facility].facility_name;
michael@0 356
michael@0 357 snprintf(log_fmt_buf, MAX_ERROR_STRING_SIZE, "(%s/%s) %s",
michael@0 358 facility_str,level_str,format);
michael@0 359
michael@0 360 log_fmt_buf[MAX_ERROR_STRING_SIZE-1]=0;
michael@0 361 fmt_str=log_fmt_buf;
michael@0 362 }
michael@0 363
michael@0 364 for(i=0; i<LOG_NUM_DESTINATIONS; i++){
michael@0 365 if(r_logging_dest(i,facility,level)){
michael@0 366 // Some platforms do not react well when you use a va_list more than
michael@0 367 // once
michael@0 368 va_list copy;
michael@0 369 va_copy(copy, ap);
michael@0 370 log_destinations[i].dest_vlog(facility,level,fmt_str,copy);
michael@0 371 va_end(copy);
michael@0 372 }
michael@0 373 }
michael@0 374 return(0);
michael@0 375 }
michael@0 376
michael@0 377 int stderr_vlog(int facility,int level,const char *format,va_list ap)
michael@0 378 {
michael@0 379 #if 0 /* remove time stamping, for now */
michael@0 380 char cbuf[30];
michael@0 381 time_t tt;
michael@0 382
michael@0 383 tt=time(0);
michael@0 384
michael@0 385 ctime_r(&tt,cbuf);
michael@0 386 cbuf[strlen(cbuf)-1]=0;
michael@0 387
michael@0 388 fprintf(stderr,"%s: ",cbuf);
michael@0 389 #endif
michael@0 390
michael@0 391 vfprintf(stderr,format,ap);
michael@0 392 fprintf(stderr,"\n");
michael@0 393 return(0);
michael@0 394 }
michael@0 395
michael@0 396 int syslog_vlog(int facility,int level,const char *format,va_list ap)
michael@0 397 {
michael@0 398 #ifndef WIN32
michael@0 399 vsyslog(level|LOG_LOCAL0,format,ap);
michael@0 400 #endif
michael@0 401 return(0);
michael@0 402 }
michael@0 403
michael@0 404 int noop_vlog(int facility,int level,const char *format,va_list ap)
michael@0 405 {
michael@0 406 return(0);
michael@0 407 }
michael@0 408
michael@0 409 int r_log_e(int facility,int level,const char *format,...)
michael@0 410 {
michael@0 411 va_list ap;
michael@0 412
michael@0 413 va_start(ap,format);
michael@0 414 r_vlog_e(facility,level,format,ap);
michael@0 415 va_end(ap);
michael@0 416
michael@0 417 return(0);
michael@0 418 }
michael@0 419
michael@0 420 int r_vlog_e(int facility,int level,const char *format,va_list ap)
michael@0 421 {
michael@0 422 char log_fmt_buf[MAX_ERROR_STRING_SIZE];
michael@0 423 if(r_logging(facility,level)) {
michael@0 424 int formatlen = strlen(format);
michael@0 425
michael@0 426 if(formatlen+2 > MAX_ERROR_STRING_SIZE)
michael@0 427 return(1);
michael@0 428
michael@0 429 strncpy(log_fmt_buf, format, formatlen);
michael@0 430 strcpy(&log_fmt_buf[formatlen], ": ");
michael@0 431 snprintf(&log_fmt_buf[formatlen+2], MAX_ERROR_STRING_SIZE - formatlen - 2, "%s",
michael@0 432 #ifdef WIN32
michael@0 433 strerror(WSAGetLastError()));
michael@0 434 #else
michael@0 435 strerror(errno));
michael@0 436 #endif
michael@0 437 log_fmt_buf[MAX_ERROR_STRING_SIZE-1]=0;
michael@0 438
michael@0 439 r_vlog(facility,level,log_fmt_buf,ap);
michael@0 440 }
michael@0 441 return(0);
michael@0 442 }
michael@0 443
michael@0 444 int r_log_nr(int facility,int level,int r,const char *format,...)
michael@0 445 {
michael@0 446 va_list ap;
michael@0 447
michael@0 448 va_start(ap,format);
michael@0 449 r_vlog_nr(facility,level,r,format,ap);
michael@0 450 va_end(ap);
michael@0 451
michael@0 452 return(0);
michael@0 453 }
michael@0 454
michael@0 455 int r_vlog_nr(int facility,int level,int r,const char *format,va_list ap)
michael@0 456 {
michael@0 457 char log_fmt_buf[MAX_ERROR_STRING_SIZE];
michael@0 458 if(r_logging(facility,level)) {
michael@0 459 int formatlen = strlen(format);
michael@0 460
michael@0 461 if(formatlen+2 > MAX_ERROR_STRING_SIZE)
michael@0 462 return(1);
michael@0 463 strncpy(log_fmt_buf, format, formatlen);
michael@0 464 strcpy(&log_fmt_buf[formatlen], ": ");
michael@0 465 snprintf(&log_fmt_buf[formatlen+2], MAX_ERROR_STRING_SIZE - formatlen - 2, "%s",
michael@0 466 nr_strerror(r));
michael@0 467
michael@0 468 log_fmt_buf[MAX_ERROR_STRING_SIZE-1]=0;
michael@0 469
michael@0 470 r_vlog(facility,level,log_fmt_buf,ap);
michael@0 471 }
michael@0 472 return(0);
michael@0 473 }
michael@0 474
michael@0 475 static int r_logging_dest(int dest_index, int facility, int level)
michael@0 476 {
michael@0 477 int thresh;
michael@0 478
michael@0 479 _r_log_init(0);
michael@0 480
michael@0 481 if(!log_destinations[dest_index].enabled)
michael@0 482 return(0);
michael@0 483
michael@0 484 if(level <= r_log_level_environment)
michael@0 485 return(1);
michael@0 486
michael@0 487 if(r_log_initted<R_LOG_INITTED2)
michael@0 488 return(level<=r_log_level);
michael@0 489
michael@0 490 if(facility < 0 || facility > log_type_ct)
michael@0 491 thresh=r_log_level;
michael@0 492 else{
michael@0 493 if(log_types[facility].level[dest_index]==LOG_LEVEL_NONE)
michael@0 494 return(0);
michael@0 495
michael@0 496 if(log_types[facility].level[dest_index]>=0)
michael@0 497 thresh=log_types[facility].level[dest_index];
michael@0 498 else if(log_destinations[dest_index].default_level!=LOG_LEVEL_UNDEFINED)
michael@0 499 thresh=log_destinations[dest_index].default_level;
michael@0 500 else
michael@0 501 thresh=r_log_level;
michael@0 502 }
michael@0 503
michael@0 504 if(level<=thresh)
michael@0 505 return(1);
michael@0 506
michael@0 507 return(0);
michael@0 508 }
michael@0 509
michael@0 510 int r_logging(int facility, int level)
michael@0 511 {
michael@0 512 int i;
michael@0 513
michael@0 514 _r_log_init(0);
michael@0 515
michael@0 516 /* return 1 if logging is on for any dest */
michael@0 517
michael@0 518 for(i=0; i<LOG_NUM_DESTINATIONS; i++){
michael@0 519 if(r_logging_dest(i,facility,level))
michael@0 520 return(1);
michael@0 521 }
michael@0 522
michael@0 523 return(0);
michael@0 524 }
michael@0 525
michael@0 526
michael@0 527 static int r_log_get_default_level(void)
michael@0 528 {
michael@0 529 char *log;
michael@0 530 int _status;
michael@0 531
michael@0 532 log=getenv("R_LOG_LEVEL");
michael@0 533
michael@0 534 if(log){
michael@0 535 r_log_level=atoi(log);
michael@0 536 r_log_level_environment=atoi(log);
michael@0 537 }
michael@0 538 else{
michael@0 539 r_log_level=LOGGING_DEFAULT_LEVEL;
michael@0 540 }
michael@0 541
michael@0 542 _status=0;
michael@0 543 //abort:
michael@0 544 return(_status);
michael@0 545 }
michael@0 546
michael@0 547
michael@0 548 static int r_log_get_destinations(int usereg)
michael@0 549 {
michael@0 550 char *log;
michael@0 551 int i;
michael@0 552 int r,_status;
michael@0 553
michael@0 554 log=getenv("R_LOG_DESTINATION");
michael@0 555 if(log){
michael@0 556 for(i=0; i<LOG_NUM_DESTINATIONS; i++)
michael@0 557 log_destinations[i].enabled=!strcmp(log,log_destinations[i].dest_name);
michael@0 558 }
michael@0 559 else if(usereg){
michael@0 560 NR_registry reg_key;
michael@0 561 int i;
michael@0 562 int value;
michael@0 563 char c;
michael@0 564
michael@0 565 /* Get the data out of the registry */
michael@0 566 for(i=0; i<LOG_NUM_DESTINATIONS; i++){
michael@0 567 /* set callback for default level */
michael@0 568 if(snprintf(reg_key,sizeof(reg_key),"%s.%s.level",LOGGING_REG_PREFIX,
michael@0 569 log_destinations[i].dest_name)>=sizeof(reg_key))
michael@0 570 ABORT(R_INTERNAL);
michael@0 571
michael@0 572 NR_reg_register_callback(reg_key,
michael@0 573 NR_REG_CB_ACTION_ADD|NR_REG_CB_ACTION_CHANGE|NR_REG_CB_ACTION_DELETE,
michael@0 574 r_log_default_level_change_cb,0);
michael@0 575
michael@0 576 if(r=r_log_get_reg_level(reg_key,&value)){
michael@0 577 if(r==R_NOT_FOUND)
michael@0 578 log_destinations[i].default_level=LOG_LEVEL_UNDEFINED;
michael@0 579 else
michael@0 580 ABORT(R_INTERNAL);
michael@0 581 }
michael@0 582 else
michael@0 583 log_destinations[i].default_level=value;
michael@0 584
michael@0 585 /* set callback for the enabled key for this logging dest */
michael@0 586 if(snprintf(reg_key,sizeof(reg_key),"%s.%s.enabled",LOGGING_REG_PREFIX,
michael@0 587 log_destinations[i].dest_name)>=sizeof(reg_key))
michael@0 588 ABORT(R_INTERNAL);
michael@0 589
michael@0 590 NR_reg_register_callback(reg_key,
michael@0 591 NR_REG_CB_ACTION_ADD|NR_REG_CB_ACTION_CHANGE|NR_REG_CB_ACTION_DELETE,
michael@0 592 r_log_destination_change_cb,0);
michael@0 593
michael@0 594 if(r=NR_reg_get_char(reg_key,&c)){
michael@0 595 if(r==R_NOT_FOUND)
michael@0 596 log_destinations[i].enabled=0;
michael@0 597 else
michael@0 598 ABORT(r);
michael@0 599 }
michael@0 600 else
michael@0 601 log_destinations[i].enabled=c;
michael@0 602 }
michael@0 603 }
michael@0 604
michael@0 605 _status=0;
michael@0 606 abort:
michael@0 607 return(_status);
michael@0 608 }
michael@0 609
michael@0 610 static void r_log_destination_change_cb(void *cb_arg, char action, NR_registry name)
michael@0 611 {
michael@0 612 r_log_get_destinations(1);
michael@0 613 }
michael@0 614
michael@0 615 static void r_log_default_level_change_cb(void *cb_arg, char action, NR_registry name)
michael@0 616 {
michael@0 617 r_log_get_destinations(1);
michael@0 618 }
michael@0 619
michael@0 620
michael@0 621 int r_log_init()
michael@0 622 {
michael@0 623 _r_log_init(1);
michael@0 624
michael@0 625 return 0;
michael@0 626 }
michael@0 627
michael@0 628 int _r_log_init(int use_reg)
michael@0 629 {
michael@0 630 #ifndef WIN32
michael@0 631 char *log;
michael@0 632 #endif
michael@0 633
michael@0 634 if(!use_reg){
michael@0 635 if(r_log_initted<R_LOG_INITTED1){
michael@0 636 r_log_get_default_level();
michael@0 637 r_log_get_destinations(0);
michael@0 638
michael@0 639 r_log_initted=R_LOG_INITTED1;
michael@0 640 }
michael@0 641 }
michael@0 642 else{
michael@0 643 if(r_log_initted<R_LOG_INITTED2){
michael@0 644 int facility;
michael@0 645
michael@0 646 r_log_get_default_level();
michael@0 647 r_log_get_destinations(1);
michael@0 648
michael@0 649 r_log_register("generic",&facility);
michael@0 650 r_log_register("logging",&NR_LOG_LOGGING);
michael@0 651
michael@0 652 r_log_initted=R_LOG_INITTED2;
michael@0 653 }
michael@0 654 }
michael@0 655
michael@0 656 #ifdef WIN32
michael@0 657 r_log_env_verbose=1;
michael@0 658 #else
michael@0 659 log=getenv("R_LOG_VERBOSE");
michael@0 660 if(log)
michael@0 661 r_log_env_verbose=atoi(log);
michael@0 662 #endif
michael@0 663
michael@0 664 return(0);
michael@0 665 }
michael@0 666
michael@0 667 int r_log_set_extra_destination(int default_level, r_dest_vlog *dest_vlog)
michael@0 668 {
michael@0 669 int i;
michael@0 670 log_destination *dest = 0;
michael@0 671
michael@0 672 for(i=0; i<LOG_NUM_DESTINATIONS; i++){
michael@0 673 if(!strcmp("extra",log_destinations[i].dest_name)){
michael@0 674 dest=&log_destinations[i];
michael@0 675 break;
michael@0 676 }
michael@0 677 }
michael@0 678
michael@0 679 if(!dest)
michael@0 680 return(R_INTERNAL);
michael@0 681
michael@0 682 if (dest_vlog==0){
michael@0 683 dest->enabled=0;
michael@0 684 dest->dest_vlog=noop_vlog;
michael@0 685 }
michael@0 686 else{
michael@0 687 dest->enabled=1;
michael@0 688 dest->default_level=default_level;
michael@0 689 dest->dest_vlog=dest_vlog;
michael@0 690 }
michael@0 691
michael@0 692 return(0);
michael@0 693 }
michael@0 694

mercurial