RDK Documentation (Open Sourced RDK Components)
rdk_debug_priv.c
Go to the documentation of this file.
1 /*
2  * If not stated otherwise in this file or this component's Licenses.txt file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2016 RDK Management
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18 */
19 
20 /**
21  * @file rdk_debug_priv.c
22  */
23 
24 
25 /**
26 * @defgroup rdk_logger
27 * @{
28 * @defgroup src
29 * @{
30 **/
31 
32 
33 #include <assert.h>
34 #include <stdio.h>
35 /*lint -e(451)*/
36 #include <stdarg.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <ctype.h>
40 #include <limits.h>
41 #include <unistd.h>
42 #include <sys/syscall.h> /* For SYS_xxx definitions */
43 #include <errno.h>
44 #include <fcntl.h>
45 #include <sys/ioctl.h>
46 #include <arpa/inet.h>
47 #include <netdb.h>
48 
49 
50 #include "rdk_logger_types.h"
51 #include "rdk_error.h"
52 #define RDK_DEBUG_DEFINE_STRINGS
53 #include "rdk_debug_priv.h"
54 #include "rdk_dynamic_logger.h"
55 #include "log4c.h"
56 #include <rdk_utils.h>
57 
58 #ifdef SYSTEMD_JOURNAL
59 #include <systemd/sd-journal.h>
60 #endif //SYSTEMD_JOURNAL
61 
62 
63 #ifdef SYSTEMD_SYSLOG_HELPER
64 #include "syslog_helper_ifc.h"
65 #endif
66 
67 /// Debugging messages are enabled. Default is enabled (1) and 0 for off.
68 static int g_debugEnabled = 1;
69 
70 extern int global_count;
71 
72 /**
73  * Returns 1 if logging has been requested for the corresponding module (mod)
74  * and level (lvl) combination. To be used in rdk_dbg_priv_* files ONLY.
75  */
76 #define WANT_LOG(mod, lvl) ( ( ((mod) >= 0) && ((mod) < RDK_MAX_MOD_COUNT) ) ? (rdk_g_logControlTbl[(mod)] & (1 << (lvl))) : 0 )
77 
78 
79 /** Skip whitespace in a c-style string. */
80 #define SKIPWHITE(cptr) while ((*cptr != '\0') && isspace(*cptr)) cptr++
81 
82 /** Bit mask for trace (TRACE1 thru TRACE9) logging levels. */
83 #define LOG_TRACE ( (1 << RDK_LOG_TRACE1) | (1 << RDK_LOG_TRACE2) | (1 << RDK_LOG_TRACE3) \
84  | (1 << RDK_LOG_TRACE4) | (1 << RDK_LOG_TRACE5) | (1 << RDK_LOG_TRACE6) \
85  | (1 << RDK_LOG_TRACE7) | (1 << RDK_LOG_TRACE8) | (1 << RDK_LOG_TRACE9) )
86 
87 /** Turns on FATAL, ERROR, WARN NOTICE & INFO. */
88 #define LOG_ALL ( (1 << RDK_LOG_FATAL) | (1 << RDK_LOG_ERROR) | \
89  (1 << RDK_LOG_WARN) | (1 << RDK_LOG_INFO) | \
90  (1 << RDK_LOG_NOTICE))
91 
92 /** All logging 'off'. */
93 #define LOG_NONE 0
94 
95 #define HOSTADDR_STR_MAX 255
96 
97 
98 #define MAX_LOGLINE_LENGTH 4096
99 
100 static int initLogger(char *category);
101 
102 static const char* dated_format_nocr(const log4c_layout_t* a_layout,
103  const log4c_logging_event_t*a_event);
104 static const char* basic_format_nocr(const log4c_layout_t* a_layout,
105  const log4c_logging_event_t*a_event);
106 static const char* comcast_dated_format_nocr(const log4c_layout_t* a_layout,
107  log4c_logging_event_t*a_event);
108 static int stream_env_overwrite_open(log4c_appender_t * appender);
109 static int stream_env_append_open(log4c_appender_t * appender);
110 static int stream_env_append(log4c_appender_t* appender, const log4c_logging_event_t* event);
111 static int stream_env_plus_stdout_append(log4c_appender_t* appender, const log4c_logging_event_t* event);
112 static int stream_env_close(log4c_appender_t * appender);
113 
114 /* GLOBALS */
115 
116 static rdk_logger_Bool g_initialized = FALSE;
117 
118 
119 /** Global variable used to control logging. */
120 uint32_t rdk_g_logControlTbl[RDK_MAX_MOD_COUNT];
121 
122 /** UDP logging variables. */
123 rdk_logger_Bool dbg_logViaUDP = FALSE;
124 int dbg_udpSocket;
125 struct sockaddr_in dbg_logHostAddr;
126 
127 log4c_category_t* stackCat = NULL;
128 
129 enum
130 {
131  /** Used as an array index. */
132  ERR_INVALID_MOD_NAME = 0, ERR_INVALID_LOG_NAME
133 };
134 
135 enum
136 {
137  RC_ERROR, RC_OK
138 };
139 
140 static const char *errorMsgs[] =
141 { "Error: Invalid module name.", "Warning: Ignoring invalid log name(s)." };
142 
143 
144 /**
145  * Initialize Debug API.
146  */
147 static log4c_category_t* defaultCategory = NULL;
148 static log4c_category_t* glibCategory = NULL;
149 
150 static const log4c_layout_type_t log4c_layout_type_dated_nocr =
151 { "dated_nocr", dated_format_nocr, };
152 
153 static const log4c_layout_type_t log4c_layout_type_basic_nocr =
154 { "basic_nocr", basic_format_nocr, };
155 
156 static const log4c_layout_type_t log4c_layout_type_comcast_dated_nocr =
157 { "comcast_dated_nocr", comcast_dated_format_nocr, };
158 
159 static const log4c_appender_type_t
160  log4c_appender_type_stream_env =
161  { "stream_env", stream_env_overwrite_open, stream_env_append,
162  stream_env_close, };
163 
164 static const log4c_appender_type_t log4c_appender_type_stream_env_append =
165 { "stream_env_append", stream_env_append_open, stream_env_append,
166  stream_env_close, };
167 
168 static const log4c_appender_type_t log4c_appender_type_stream_env_plus_stdout =
169 { "stream_env_plus_stdout", stream_env_overwrite_open,
170  stream_env_plus_stdout_append, stream_env_close, };
171 
172 static const log4c_appender_type_t log4c_appender_type_stream_env_append_plus_stdout =
173 { "stream_env_append_plus_stdout", stream_env_append_open,
174  stream_env_plus_stdout_append, stream_env_close, };
175 
176 void rdk_dbg_priv_Init()
177 {
178  const char* envVar;
179 
180  if (initLogger("RI"))
181  {
182  fprintf(stderr, "%s -- initLogger failure?!\n", __FUNCTION__);
183  }
184 
185  stackCat = log4c_category_get("RI.Stack");
186 
188 
189  /* Try to get logging option. */
190  envVar = rdk_logger_envGet("EnableMPELog");
191  if (NULL != envVar)
192  {
193  g_debugEnabled = (strcasecmp(envVar, "TRUE") == 0);
194  }
195 }
196 
197 /**
198  * Safely force a string to uppercase. I hate this mundane rubbish.
199  *
200  * @param token String to be forced to uppercase.
201  */
202 static void forceUpperCase(char *token)
203 {
204  while (*token)
205  {
206  if (islower(*token))
207  {
208  *token = (char) toupper(*token);
209  }
210  token++;
211  }
212 }
213 
214 /**
215  * Convert a log level name to the correspodning log level enum value.
216  *
217  * @param name Log level name, which must be uppercase.
218  * @param Corresponding enumeration value or -1 on error.
219  */
220 static int logNameToEnum(const char *name)
221 {
222  int i = 0;
223  while (i < ENUM_RDK_LOG_COUNT)
224  {
225  if (strcmp(name, rdk_logLevelStrings[i]) == 0)
226  {
227  return i;
228  }
229  i++;
230  }
231 
232  return -1;
233 }
234 
235 /**
236  * Extract a whitespace delimited token from a string.
237  *
238  * @param srcStr Pointer to the source string, this will be modified
239  * to point to the first character after the token extracted.
240  *
241  * @param tokBuf This is a string that will be filled with the
242  * token. Note: this buffer is assumed to be large enough to hold the
243  * largest possible token.
244  */
245 static void extractToken(const char **srcStr, char *tokBuf)
246 {
247  const char *src = *srcStr;
248  while (*src && !isspace(*src))
249  {
250  *tokBuf++ = *src++;
251  }
252  *tokBuf = '\0';
253  *srcStr = src;
254 }
255 
256 /**
257  * Parse a whitespace delimited list of log types and log type meta names.
258  *
259  * @param cfgStr String containing one more log types. (Right hand
260  * side of INI file entry.)
261  *
262  * @param defConfig Default configuration to base the return value on.
263  *
264  * @return Returns a bit mask that can be used as an entry in
265  * #rdk_g_logControlTbl.
266  */
267 static int parseLogConfig(const char *cfgStr, uint32_t *configEntry,
268  const char **msg)
269 {
270  uint32_t config = *configEntry;
271  char logTypeName[128] =
272  { 0 };
273  int rc = RC_OK;
274 
275  *msg = "";
276 
277  SKIPWHITE(cfgStr)
278  ;
279  if (*cfgStr == '\0')
280  {
281  *msg = "Warning: Empty log level confguration.";
282  return RC_ERROR;
283  }
284 
285  while (*cfgStr != '\0')
286  {
287  /* Extract and normalise log type name token. */
288 
289  memset(logTypeName, 0, sizeof(logTypeName));
290  extractToken(&cfgStr, logTypeName);
291  forceUpperCase(logTypeName);
292 
293  /* Handle special meta names. */
294 
295  if (strcmp(logTypeName, "ALL") == 0)
296  {
297  config |= LOG_ALL;
298  }
299  else if (strcmp(logTypeName, "NONE") == 0)
300  {
301  config = LOG_NONE;
302  }
303  else if (strcmp(logTypeName, "TRACE") == 0)
304  {
305  config |= LOG_TRACE;
306  }
307  else if (strcmp(logTypeName, "!TRACE") == 0)
308  {
309  config &= ~LOG_TRACE;
310  }
311  else
312  {
313  /* Determine the corresponding bit for the log name. */
314  int invert = 0;
315  const char *name = logTypeName;
316  int logLevel = -1;
317 
318  if (logTypeName[0] == '!')
319  {
320  invert = 1;
321  name = &logTypeName[1];
322  }
323 
324  logLevel = logNameToEnum(name);
325  if (logLevel != -1)
326  {
327  if (invert)
328  {
329  config &= ~(1 << logLevel);
330  }
331  else
332  {
333  config |= (1 << logLevel);
334  }
335  }
336  else
337  {
338  *msg = errorMsgs[ERR_INVALID_LOG_NAME];
339  rc = RC_ERROR;
340  }
341  }
342 
343  SKIPWHITE(cfgStr)
344  ;
345  }
346 
347  *configEntry = config;
348  return rc;
349 }
350 
351 static void printTime(const struct tm *pTm, char *pBuff)
352 {
353  sprintf(pBuff,"%02d%02d%02d-%02d:%02d:%02d",pTm->tm_year + 1900 - 2000, pTm->tm_mon + 1, pTm->tm_mday, pTm->tm_hour, pTm->tm_min, pTm->tm_sec);
354 }
355 
356 /*****************************************************************************
357  *
358  * EXPORTED FUNCTIONS
359  *
360  ****************************************************************************/
361 
362 /**
363  * Initialize the debug log control table. This should be called from
364  * the initialization routine of the debug manager.
365  */
367 {
368  char envVarName[128] =
369  { 0 };
370  const char *envVarValue = NULL;
371  uint32_t defaultConfig = 0;
372  int mod = 0;
373  const char *msg = "";
374 
375  /** Pre-condition the control table to disable all logging. This
376  * means that if no logging control statements are present in the
377  * debug.ini file all logging will be suppressed. */
378  memset(rdk_g_logControlTbl, 0, sizeof(rdk_g_logControlTbl));
379 
380  /** Intialize to the default configuration for all modules. */
381  strcpy(envVarName, "LOG.RDK.DEFAULT");
382  envVarValue = rdk_logger_envGet(envVarName);
383  if ((envVarValue != NULL) && (envVarValue[0] != 0))
384  {
385  (void) parseLogConfig(envVarValue, &defaultConfig, &msg);
386  for (mod = 1; mod <= global_count; mod++)
387  {
388  rdk_g_logControlTbl[mod] = defaultConfig;
389  }
390  }
391 
392  /** Configure each module from the ini file. Note: It is not an
393  * error to have no entry in the ini file for a module - we simply
394  * leave it at the default logging. */
395  for (mod = 1; mod <= global_count; mod++)
396  {
397  /** Get the logging level */
398  envVarValue = rdk_logger_envGetValueFromNum(mod);
399  if ((envVarValue != NULL) && (envVarValue[0] != '\0'))
400  {
401  (void) parseLogConfig(envVarValue, &rdk_g_logControlTbl[mod],
402  &msg);
403  }
404  }
405 }
406 
407 /**
408  * @brief Function to check if a specific log level of a module is enabled.
409  *
410  * @param[in] module The module name or category for for which the log level shall be checked (as mentioned in debug.ini).
411  * @param[in] level The debug logging level.
412  *
413  * @return Returns true, if debug log level enabled successfully else returns false.
414  */
415 rdk_logger_Bool rdk_dbg_enabled(const char *module, rdk_LogLevel level)
416 {
417  int number = rdk_logger_envGetNum(module);
418  if (WANT_LOG(number, level))
419  {
420  return TRUE;
421  }
422  else
423  {
424  return FALSE;
425  }
426 }
427 
428 /**
429  * Modify the debug log control table.
430  */
431 void rdk_dbg_priv_SetLogLevelString(const char* pszModuleName, const char* pszLogLevels)
432 {
433  const char *envVarName;
434  uint32_t defaultConfig = 0;
435  int mod = 0;
436  const char *msg = "";
437 
438  if ((pszModuleName != NULL) && (pszLogLevels != NULL))
439  {
440  /* Intialize to the default configuration for all modules. */
441  if(0 == strcmp(pszModuleName, "LOG.RDK.DEFAULT"))
442  {
443  (void) parseLogConfig(pszLogLevels, &defaultConfig, &msg);
444  for (mod = 1; mod <= global_count; mod++)
445  {
446  rdk_g_logControlTbl[mod] = defaultConfig;
447  }
448  printf("rdk_dbg_priv_SetLogLevelString: Set Logging Level for '%s' to '%s'\n", pszModuleName, pszLogLevels);
449  return;
450  }
451 
452  /* Configure each module from the ini file. Note: It is not an
453  * error to have no entry in the ini file for a module - we simply
454  * leave it at the default logging. */
455  for (mod = 1; mod <= global_count; mod++)
456  {
457  envVarName = rdk_logger_envGetModFromNum(mod);
458  if(0 == strcmp(pszModuleName, envVarName))
459  {
460  if ((pszLogLevels != NULL) && (pszLogLevels[0] != '\0'))
461  {
462  (void) parseLogConfig(pszLogLevels, &rdk_g_logControlTbl[mod], &msg);
463  printf("rdk_dbg_priv_SetLogLevelString: Set Logging Level for '%s' to '%s'\n", pszModuleName, pszLogLevels);
464  return;
465  }
466  }
467  }
468  }
469  printf("rdk_dbg_priv_SetLogLevelString: Failed to set Logging Level for '%s' to '%s'\n", pszModuleName, pszLogLevels);
470 }
471 
472 
473 
474 /**
475  * Provides an interface to query the configuration of logging in a
476  * specific module as a user readable string. Note: the mimimum
477  * acceptable length of the supplied configuration buffer is 32 bytes.
478  *
479  * @param modName Name of the module.
480  *
481  * @param cfgStr The configuration strng: which should be space
482  * separated module names.
483  *
484  * @param cfgStrMaxLen The maximum length of the configuration string
485  * to be returned including the NUL character.
486  *
487  * @return A string containing a user readable error message if an
488  * error occured; or "OK" upon success.
489  */
490 const char * rdk_dbg_priv_LogQueryOpSysIntf(char *modName, char *cfgStr,
491  int cfgStrMaxLen)
492 {
493  char *name = modName;
494  int mod = -1;
495  uint32_t modCfg = 0;
496  int level = -1;
497 
498  assert(modName);
499  assert(cfgStr);
500  assert(cfgStrMaxLen > 32);
501 
502  cfgStrMaxLen -= 1; /**< Ensure there is space for NUL. */
503  strcpy(cfgStr, "");
504 
505  /** Get the module configuration. Note: DEFAULT is not valid as it
506  * is an alias.
507  */
508  forceUpperCase(name);
509  mod = rdk_logger_envGetNum(modName);
510  if (mod < 0)
511  {
512  return "Unknown module specified.";
513  }
514  modCfg = rdk_g_logControlTbl[mod];
515 
516  /** Try and find a succinct way of describing the configuration. */
517 
518  if (modCfg == 0)
519  {
520  strcpy(cfgStr, "NONE");
521  return "OK"; /* This is a canonical response. */
522  }
523 
524 #if 0 /* BAT: print out the level details instead of just these abbreviations */
525 
526  /* Look for appropriate abberviations. */
527 
528  if ((modCfg & LOG_ALL) == LOG_ALL)
529  {
530  strcpy(cfgStr, " ALL");
531  modCfg &= ~LOG_ALL;
532  }
533 
534  if ((modCfg & LOG_TRACE) == LOG_TRACE)
535  {
536  strcat(cfgStr, " TRACE");
537  modCfg &= ~LOG_TRACE;
538  }
539 #endif /* BAT */
540 
541  /** Loop through the control word and print out the enabled levels. */
542 
543  for (level = 0; level < ENUM_RDK_LOG_COUNT; level++)
544  {
545  if (modCfg & (1 << level))
546  {
547  /** Stop building out the config string if it would exceed
548  * the buffer length.
549  */
550  if (strlen(cfgStr) + strlen(rdk_logLevelStrings[level])
551  > (size_t) cfgStrMaxLen)
552  {
553  return "Warning: Config string too long, config concatenated.";
554  }
555 
556  strcat(cfgStr, " "); /* Not efficient - rah rah. */
557  strcat(cfgStr, rdk_logLevelStrings[level]);
558  }
559  }
560 
561  return "OK";
562 }
563 
564 void rdk_debug_priv_log_msg( rdk_LogLevel level,
565  int module, const char *module_name, const char* format, va_list args)
566 {
567  /** Get the category from module name */
568  static log4c_category_t *cat_cache[RDK_MAX_MOD_COUNT] = {NULL};
569  char cat_name[64] = {'\0'};
570  log4c_category_t* cat = NULL;
571 
572  /* Handling process request here. This is not a blocking call and it shall return immediately */
573  rdk_dyn_log_processPendingRequest();
574 
575  if (!g_debugEnabled || !WANT_LOG(module, level))
576  {
577  return;
578  }
579 
580  char *parent_cat_name = (char *)log4c_category_get_name(stackCat);
581  snprintf(cat_name, sizeof(cat_name)-1, "%s.%s", parent_cat_name == NULL ? "" : parent_cat_name, module_name);
582 
583  if((module >= 0) && (module < RDK_MAX_MOD_COUNT))
584  {
585  if (cat_cache[module] == NULL) {
586  /** Only doing a read here, lock not needed */
587  cat_cache[module] = log4c_category_get(cat_name);
588  }
589 
590  cat = cat_cache[module];
591  }
592  else
593  {
594  cat = log4c_category_get(cat_name);
595  }
596 
597  switch (level)
598  {
599  case RDK_LOG_FATAL:
600  log4c_category_vlog(cat, LOG4C_PRIORITY_FATAL, format, args);
601  break;
602  case RDK_LOG_ERROR:
603  log4c_category_vlog(cat, LOG4C_PRIORITY_ERROR, format, args);
604  break;
605  case RDK_LOG_WARN:
606  log4c_category_vlog(cat, LOG4C_PRIORITY_WARN, format, args);
607  break;
608  case RDK_LOG_NOTICE:
609  log4c_category_vlog(cat, LOG4C_PRIORITY_NOTICE, format, args);
610  break;
611  case RDK_LOG_INFO:
612  log4c_category_vlog(cat, LOG4C_PRIORITY_INFO, format, args);
613  break;
614  case RDK_LOG_DEBUG:
615  log4c_category_vlog(cat, LOG4C_PRIORITY_DEBUG, format, args);
616  break;
617  case RDK_LOG_TRACE1:
618  case RDK_LOG_TRACE2:
619  case RDK_LOG_TRACE3:
620  case RDK_LOG_TRACE4:
621  case RDK_LOG_TRACE5:
622  case RDK_LOG_TRACE6:
623  case RDK_LOG_TRACE7:
624  case RDK_LOG_TRACE8:
625  case RDK_LOG_TRACE9:
626  log4c_category_vlog(cat, LOG4C_PRIORITY_TRACE, format, args);
627  break;
628  default:
629  log4c_category_vlog(cat, LOG4C_PRIORITY_DEBUG, format, args);
630  break;
631  }
632 }
633 
634 
635 void RDK_LOG_ControlCB(const char *moduleName, const char *subComponentName, const char *loggingLevel, int log_status)
636 {
637  char logTypeName[20] = {0};
638 
639  if ((NULL == moduleName) || (NULL == loggingLevel))
640  {
641  return;
642  }
643 
644  strncpy(logTypeName, loggingLevel, sizeof(logTypeName));
645  if (logTypeName[0] == '~')
646  {
647  logTypeName[0] = '!';
648  }
649 
650  rdk_dbg_priv_SetLogLevelString(moduleName, (const char *)logTypeName);
651 }
652 
653 
654 /*************************Copied from ri_log.c******************/
655 
656 /**
657  * Instantiate the logger...
658  * @param cat The category string for this instance logging/filtering
659  * @return the result of the instantiation
660  */
661 static int initLogger(char *category)
662 {
663 
664  ///> These must be set before calling log4c_init so that the log4crc file
665  ///> will configure them
666  (void) log4c_appender_type_set(&log4c_appender_type_stream_env);
667  (void) log4c_appender_type_set(&log4c_appender_type_stream_env_append);
668  (void) log4c_appender_type_set(&log4c_appender_type_stream_env_plus_stdout);
669  (void) log4c_appender_type_set(
670  &log4c_appender_type_stream_env_append_plus_stdout);
671  (void) log4c_layout_type_set(&log4c_layout_type_dated_nocr);
672  (void) log4c_layout_type_set(&log4c_layout_type_basic_nocr);
673  (void) log4c_layout_type_set(&log4c_layout_type_comcast_dated_nocr);
674 
675  if (log4c_init())
676  {
677  fprintf(stderr, "log4c_init() failed?!");
678  return -1;
679  }
680  else
681  {
682  defaultCategory = log4c_category_get(category);
683  glibCategory = log4c_category_get("RI.GLib");
684  }
685 
686  return 0;
687 }
688 
689 
690 /****************************************************************
691  * Dated layout with no ending carriage return / line feed
692  */
693 static const char* dated_format_nocr(const log4c_layout_t* layout,
694  const log4c_logging_event_t* event)
695 {
696  struct tm tm;
697  char timeBuff[40];
698  //localtime_r(&event->evt_timestamp.tv_sec, &tm); /* Use the UTC Time for logging */
699  gmtime_r(&event->evt_timestamp.tv_sec, &tm);
700 
701  memset(&timeBuff,0,40);
702 
703  printTime(&tm,timeBuff);
704 
705  (void) snprintf(event->evt_buffer.buf_data, event->evt_buffer.buf_size,
706  "%s.%03ld %-8s %s- %s", timeBuff,
707  event->evt_timestamp.tv_usec / 1000, log4c_priority_to_string(
708  event->evt_priority), event->evt_category,
709  event->evt_msg);
710  if (event->evt_buffer.buf_size > 0 && event->evt_buffer.buf_data != NULL)
711  {
712  event->evt_buffer.buf_data[event->evt_buffer.buf_size - 1] = 0;
713  }
714  return event->evt_buffer.buf_data;
715 }
716 
717 /****************************************************************
718  * Basic layout with no ending carriage return / line feed
719  */
720 static const char* basic_format_nocr(const log4c_layout_t* layout,
721  const log4c_logging_event_t* event)
722 {
723  (void) snprintf(event->evt_buffer.buf_data, event->evt_buffer.buf_size, "%-8s %s - %s",
724  log4c_priority_to_string(event->evt_priority),
725  event->evt_category, event->evt_msg);
726 
727  if (event->evt_buffer.buf_size > 0 && event->evt_buffer.buf_data != NULL)
728  {
729  event->evt_buffer.buf_data[event->evt_buffer.buf_size - 1] = 0;
730  }
731 
732  return event->evt_buffer.buf_data;
733 }
734 
735 #define COMCAST_DATAED_BUFF_SIZE 40
736 
737 static const char* comcast_dated_format_nocr(const log4c_layout_t* layout,
738  log4c_logging_event_t*event)
739 {
740  struct tm tm;
741  int n = -1;
742  char timeBuff[COMCAST_DATAED_BUFF_SIZE] = {0};
743  //localtime_r(&event->evt_timestamp.tv_sec, &tm); /* Use the UTC Time for logging */
744  gmtime_r(&event->evt_timestamp.tv_sec, &tm);
745 
746  printTime(&tm,timeBuff);
747 
748  /** Get the last part of the cagetory as "module" */
749  char *p= (char *)(event->evt_category);
750  if (NULL == p)
751  {
752  p = (char*)"UNKNOWN";
753  }
754  else
755  {
756  int len = strlen(p);
757  if ( len > 0 && *p != '.' && *(p+len-1) !='.')
758  {
759  p = p + len - 1;
760  while (p != (char *)(event->evt_category) && *p != '.') p--;
761  if (*p == '.') p+=1;
762 
763  }
764  else
765  {
766  p = (char*)"UNKNOWN";
767  }
768  }
769 
770  n = snprintf(event->evt_buffer.buf_data, event->evt_buffer.buf_size,
771  "%s.%06ld [mod=%s, lvl=%s] [tid=%ld] %s",timeBuff,
772  event->evt_timestamp.tv_usec,
773  p, log4c_priority_to_string(event->evt_priority), syscall(SYS_gettid),
774  event->evt_msg);
775  if (n > -1 && n > event->evt_buffer.buf_size && event->evt_buffer.buf_maxsize == 0) {
776  event->evt_buffer.buf_size = n + COMCAST_DATAED_BUFF_SIZE + 1;
777  event->evt_buffer.buf_data = (char *) realloc (event->evt_buffer.buf_data, event->evt_buffer.buf_size);
778  //TODO realloc error check
779  n = snprintf(event->evt_buffer.buf_data, event->evt_buffer.buf_size,
780  "%s.%06ld [mod=%s, lvl=%s] [tid=%ld] %s",timeBuff,
781  event->evt_timestamp.tv_usec,
782  p, log4c_priority_to_string(event->evt_priority), syscall(SYS_gettid),
783  event->evt_msg);
784  }
785  if (event->evt_buffer.buf_size > 0 && event->evt_buffer.buf_data != NULL)
786  {
787  event->evt_buffer.buf_data[event->evt_buffer.buf_size - 1] = 0;
788  }
789  return event->evt_buffer.buf_data;
790 }
791 /****************************************************************
792  * Stream layout that will parse environment variables from the
793  * stream name (env vars have a leading "$(" and end with )"
794  */
795 static int stream_env_open(log4c_appender_t* appender, int append)
796 {
797  FILE* fp = (FILE*)log4c_appender_get_udata(appender);
798  char* name = strdup(log4c_appender_get_name(appender));
799  int nameLen = strlen(name);
800  char* temp = name;
801  char *varBegin, *varEnd;
802  char* envVar;
803  const int MAX_VAR_LEN = 1024;
804  char newName[MAX_VAR_LEN+1];
805  int newNameLen = 0;
806 
807  if (fp)
808  {
809  free(name); /*RDKB-7467, CID-24968, free unused resources*/
810  return 0;
811  }
812 
813  newName[0] = '\0';
814 
815  ///> Parse any environment variables
816  while ((varBegin = strchr(temp,'$')) != NULL)
817  {
818  ///> Search for opening and closing parens
819  if (((varBegin - name + 1) >= nameLen) || (*(varBegin+1) != '('))
820  goto parse_error;
821 
822  ///> Append characters up to this point to the new name
823  strncat(newName, temp, varBegin-temp);
824  newNameLen += varBegin-temp;
825  if (newNameLen > MAX_VAR_LEN)
826  goto length_error;
827 
828  varBegin += 2; ///> start of env var name
829 
830  if ((varEnd = strchr(varBegin,')')) == NULL)
831  goto parse_error;
832 
833  *varEnd = '\0';
834  if ((envVar = getenv(varBegin)) == NULL)
835  goto parse_error;
836 
837  ///> Append env var value to the new name
838  strncat(newName, envVar, strlen(envVar));
839  newNameLen += strlen(envVar);
840  if (newNameLen >MAX_VAR_LEN)
841  goto length_error;
842 
843  temp = varEnd + 1;
844  }
845 
846  ///> Append remaining characters
847  strncat(newName, temp, (name + nameLen) - temp);
848  newNameLen += (name + nameLen) - temp;
849  if (newNameLen >MAX_VAR_LEN)
850  goto length_error;
851 
852  free(name);
853 
854  if (!strcmp(newName,"stderr"))
855  fp = stderr;
856  else if (!strcmp(newName,"stdout"))
857  fp = stdout;
858  else if (append)
859  {
860  printf("****Opening %s in append mode\n", newName);
861  if ((fp = fopen(newName, "a")) == NULL)
862  return -1;
863  }
864  else
865  {
866  printf("****Opening %s in write mode\n", newName);
867  if ((fp = fopen(newName, "w")) == NULL)
868  return -1;
869  }
870 
871  /**> unbuffered mode */
872  setbuf(fp, NULL);
873 
874  (void)log4c_appender_set_udata(appender, fp);
875  return 0;
876 
877  parse_error:
878  fprintf(stderr, "*(*(*(*( log4c appender stream_env, %s -- Illegal env var name or format! %s\n",
879  __FUNCTION__, name);
880  (void)fflush(stderr);
881  free(name);
882  return -1;
883 
884  length_error:
885  fprintf(stderr, "*(*(*(*( log4c appender stream_env, %s -- Path is too long! %s\n",
886  __FUNCTION__, name);
887  (void)fflush(stderr);
888  free(name);
889  return -1;
890 }
891 
892 static int stream_env_overwrite_open(log4c_appender_t* appender)
893 {
894  return stream_env_open(appender, 0);
895 }
896 
897 static int stream_env_append_open(log4c_appender_t* appender)
898 {
899  return stream_env_open(appender, 1);
900 }
901 
902 #ifdef SYSTEMD_JOURNAL
903 static int stream_env_append_get_priority(int log4c_pr)
904 {
905  int priority;
906  switch(log4c_pr)
907  {
908  case LOG4C_PRIORITY_FATAL:
909  priority = LOG_EMERG;
910  break;
911  case LOG4C_PRIORITY_ERROR:
912  priority = LOG_ERR;
913  break;
914  case LOG4C_PRIORITY_WARN:
915  priority = LOG_WARNING;
916  break;
917  case LOG4C_PRIORITY_NOTICE:
918  priority = LOG_NOTICE;
919  break;
920  case LOG4C_PRIORITY_INFO:
921  priority = LOG_INFO;
922  break;
923  case LOG4C_PRIORITY_DEBUG:
924  case LOG4C_PRIORITY_TRACE:
925  default:
926  priority = LOG_DEBUG;
927  break;
928  }
929  return priority;
930 }
931 #endif
932 
933 static int stream_env_append(log4c_appender_t* appender,
934  const log4c_logging_event_t* event)
935 {
936  int retval=0;
937  FILE* fp = (FILE*)log4c_appender_get_udata(appender);
938 
939 #if defined(SYSTEMD_SYSLOG_HELPER)
940  send_logs_to_syslog(event->evt_rendered_msg);
941 #elif defined(SYSTEMD_JOURNAL)
942  if (fp == stdout || fp == stderr)
943  {
944  retval = sd_journal_print(stream_env_append_get_priority(event->evt_priority), "%s",event->evt_rendered_msg);
945  }
946  else
947  {
948  retval = fprintf(fp, "%s", event->evt_rendered_msg);
949  (void)fflush(fp);
950  }
951 #else
952  retval = fprintf(fp, "%s", event->evt_rendered_msg);
953  (void)fflush(fp);
954 #endif
955 
956  //free((void *)event->evt_rendered_msg);
957 
958  return retval;
959 }
960 
961 static int stream_env_plus_stdout_append(log4c_appender_t* appender,
962  const log4c_logging_event_t* event)
963 {
964  int retval=0;
965  FILE* fp = (FILE*)log4c_appender_get_udata(appender);
966 
967 #if defined(SYSTEMD_SYSLOG_HELPER)
968  send_logs_to_syslog(event->evt_rendered_msg);
969 #elif defined(SYSTEMD_JOURNAL)
970  if (fp != stdout || fp != stderr)
971  {
972  retval = fprintf(fp, "%s", event->evt_rendered_msg);
973  }
974  else
975  {
976  retval = sd_journal_print(stream_env_append_get_priority(event->evt_priority), "%s",event->evt_rendered_msg);
977  }
978  (void)fflush(fp);
979 #else
980  retval = fprintf(fp, "%s", event->evt_rendered_msg);
981  fprintf(stdout, "%s", event->evt_rendered_msg);
982  (void)fflush(fp);
983  (void)fflush(stdout);
984 #endif
985  //free((void *)event->evt_rendered_msg);
986 
987  return retval;
988 }
989 
990 
991 static int stream_env_close(log4c_appender_t* appender)
992 {
993  FILE* fp = (FILE*)log4c_appender_get_udata(appender);
994 
995  if (!fp || fp == stdout || fp == stderr)
996  return 0;
997 
998  return fclose(fp);
999 }
1000 
1001 
1002 /*************************End Copied from ri_log.c******************/
1003 
g_debugEnabled
static int g_debugEnabled
Debugging messages are enabled. Default is enabled (1) and 0 for off.
Definition: rdk_debug_priv.c:68
parseLogConfig
static int parseLogConfig(const char *cfgStr, uint32_t *configEntry, const char **msg)
Definition: rdk_debug_priv.c:267
SKIPWHITE
#define SKIPWHITE(cptr)
Definition: rdk_debug_priv.c:80
dbg_logViaUDP
rdk_logger_Bool dbg_logViaUDP
Definition: rdk_debug_priv.c:123
rdk_logger_envGetModFromNum
const char * rdk_logger_envGetModFromNum(int Num)
This function is used to get the name of the specified environment variable based on its registered n...
Definition: rdk_logger_util.c:285
rdk_g_logControlTbl
uint32_t rdk_g_logControlTbl[RDK_MAX_MOD_COUNT]
Definition: rdk_debug_priv.c:120
logNameToEnum
static int logNameToEnum(const char *name)
Definition: rdk_debug_priv.c:220
extractToken
static void extractToken(const char **srcStr, char *tokBuf)
Definition: rdk_debug_priv.c:245
defaultCategory
static log4c_category_t * defaultCategory
Definition: rdk_debug_priv.c:147
rdk_utils.h
rdk_logger_envGetNum
int rdk_logger_envGetNum(const char *mod)
Function will give the registered number of the specified environment variable.
Definition: rdk_logger_util.c:257
ERR_INVALID_MOD_NAME
@ ERR_INVALID_MOD_NAME
Definition: rdk_debug_priv.c:132
rdk_logLevelStrings
const char * rdk_logLevelStrings[ENUM_RDK_LOG_COUNT]
initLogger
static int initLogger(char *category)
Definition: rdk_debug_priv.c:661
rdk_logger_envGetValueFromNum
const char * rdk_logger_envGetValueFromNum(int number)
This function is used to get the value of the specified environment variable based on its registered ...
Definition: rdk_logger_util.c:231
rdk_logger_envGet
const char * rdk_logger_envGet(const char *name)
This function will get value of the specified environment variable.
Definition: rdk_logger_util.c:203
rdk_dbg_enabled
rdk_logger_Bool rdk_dbg_enabled(const char *module, rdk_LogLevel level)
Function to check if a specific log level of a module is enabled.
Definition: rdk_debug_priv.c:415
rdk_LogLevel
rdk_LogLevel
These values represent the logging 'levels' or 'types', they are each independent.
Definition: rdk_debug.h:157
forceUpperCase
static void forceUpperCase(char *token)
Definition: rdk_debug_priv.c:202
global_count
int global_count
Definition: rdk_logger_util.c:55
LOG_ALL
#define LOG_ALL
Definition: rdk_debug_priv.c:88
rdk_dbg_priv_LogControlInit
void rdk_dbg_priv_LogControlInit(void)
Definition: rdk_debug_priv.c:366
LOG_INFO
#define LOG_INFO(AAMP_JS_OBJECT, FORMAT,...)
Definition: jsutils.h:39
rdk_dbg_priv_SetLogLevelString
void rdk_dbg_priv_SetLogLevelString(const char *pszModuleName, const char *pszLogLevels)
Definition: rdk_debug_priv.c:431
rdk_dbg_priv_LogQueryOpSysIntf
const char * rdk_dbg_priv_LogQueryOpSysIntf(char *modName, char *cfgStr, int cfgStrMaxLen)
Definition: rdk_debug_priv.c:490
WANT_LOG
#define WANT_LOG(mod, lvl)
Definition: rdk_debug_priv.c:76
TRUE
#define TRUE
Defines for TRUE/FALSE/ENABLE flags.
Definition: wifi_common_hal.h:199
LOG_TRACE
#define LOG_TRACE
Definition: rdk_debug_priv.c:83
LOG_NONE
#define LOG_NONE
Definition: rdk_debug_priv.c:93