LIRC libraries
LinuxInfraredRemoteControl
 All Data Structures Files Functions Variables Typedefs Enumerations Macros Modules Pages
lirc_log.c
Go to the documentation of this file.
1 /****************************************************************************
2  ** lircd.c *****************************************************************
3  ****************************************************************************
4  *
5  * lirc_log - simple logging module.
6  *
7  *
8  */
9 
16 #ifdef HAVE_CONFIG_H
17 # include <config.h>
18 #endif
19 
20 
21 #include <errno.h>
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <sys/stat.h>
27 #include <time.h>
28 #include <unistd.h>
29 #include <limits.h>
30 #include <ctype.h>
31 
32 #include "lirc/lirc_log.h"
33 
34 #define HOSTNAME_LEN 128
35 char hostname[HOSTNAME_LEN + 1];
36 FILE *lf = NULL;
37 
38 loglevel_t loglevel = LIRC_NOLOG;
39 
40 static int use_syslog = 1;
41 
42 const char *syslogident = "lircd-" VERSION;
43 const char *logfile = "syslog";
44 
45 char progname[128] = {'?','\0'};
46 static int nodaemon = 0;
47 
48 static const int PRIO_LEN = 16;
51 static const char* prio2text(int prio)
52 {
53  switch (prio) {
54  case LIRC_DEBUG: return "Debug";
55  case LIRC_NOTICE: return "Notice";
56  case LIRC_INFO: return "Info";
57  case LIRC_WARNING: return "Warning";
58  case LIRC_ERROR: return "Error";
59  case LIRC_TRACE: return "Trace";
60  case LIRC_TRACE1: return "Trace1";
61  case LIRC_TRACE2: return "Trace2";
62  default: return "(Bad prio)";
63  }
64 }
65 
66 
68 {
69  return use_syslog;
70 }
71 
72 
73 void lirc_log_set_file(const char* s)
74 {
75  if (strcmp(s, "syslog") == 0) {
76  use_syslog = 1;
77  } else {
78  logfile = s;
79  use_syslog = 0;
80  }
81 }
82 
83 
84 int lirc_log_open(const char* _progname, int _nodaemon, loglevel_t level)
85 {
86  strncpy(progname, _progname, sizeof(progname));
87  nodaemon = _nodaemon;
88  loglevel = level;
89 
90  if (use_syslog) {
91  if (nodaemon) {
92  openlog(syslogident, LOG_CONS | LOG_PID | LOG_PERROR, LOG_LOCAL0);
93  } else {
94  openlog(syslogident, LOG_CONS | LOG_PID, LOG_LOCAL0);
95  }
96  } else {
97  lf = fopen(logfile, "a");
98  if (lf == NULL) {
99  fprintf(stderr, "%s: could not open logfile \"%s\"\n",
100  progname, logfile);
101  perror(progname);
102  return 1;
103  }
104  gethostname(hostname, HOSTNAME_LEN);
105  }
106  return 0;
107 }
108 
109 
111 {
112  if (use_syslog){
113  closelog();
114  return(0);
115  }
116  else if (lf)
117  return( fclose(lf));
118  else
119  return(0);
120 }
121 
122 
123 int lirc_log_reopen(void)
124 {
125  struct stat s;
126 
127  if (use_syslog)
128  /* Don't need to do anything; this is syslogd's task */
129  return(0);
130 
131  logprintf(LIRC_INFO, "closing logfile");
132  if (-1 == fstat(fileno(lf), &s)) {
133  perror("Invalid logfile!");
134  return -1;
135  }
136  fclose(lf);
137  lf = fopen(logfile, "a");
138  if (lf == NULL) {
139  /* can't print any error messagees */
140  perror("Can't open logfile");
141  return -1;
142  }
143  logprintf(LIRC_INFO, "reopened logfile");
144  if (-1 == fchmod(fileno(lf), s.st_mode)) {
145  logprintf(LIRC_WARNING, "could not set file permissions");
146  logperror(LIRC_WARNING, NULL);
147  }
148  return 0;
149 }
150 
151 
153 {
154  if (level >= LIRC_MIN_LOGLEVEL && level <= LIRC_MAX_LOGLEVEL){
155  loglevel = level;
156  return 1;
157  }
158  else
159  return 0;
160 }
161 
162 
163 static loglevel_t symbol2loglevel(const char* levelstring)
164 {
165  static const struct {const char* label; int value;} options[] = {
166  {"TRACE2" , LIRC_TRACE2},
167  {"TRACE1" , LIRC_TRACE1},
168  {"TRACE" , LIRC_TRACE},
169  {"DEBUG" , LIRC_DEBUG},
170  {"INFO" , LIRC_INFO},
171  {"NOTICE" , LIRC_NOTICE},
172  {"WARNING" , LIRC_WARNING},
173  {"ERROR" , LIRC_ERROR},
174  {0,0}
175  };
176 
177  char label[128];
178  int i;
179 
180  if (levelstring == NULL || ! *levelstring)
181  return LIRC_BADLEVEL;
182  for (i = 0; i < sizeof(label) && levelstring[i]; i += 1)
183  label[i] = toupper(levelstring[i]);
184  label[i] = '\0';
185  i = 0;
186  while (options[i].label && strcmp(options[i].label, label) != 0)
187  i += 1;
188  return options[i].label ? options[i].value : -1;
189 }
190 
191 
193 // Try to parse LIRC_LOGLEVEL in environment, fall back to DEFAULT_LOGLEVEL.
194 {
195  loglevel_t try;
196  const char* const level = getenv("LIRC_LOGLEVEL");
197 
198  if (level != NULL) {
199  try = string2loglevel(level);
200  return try == LIRC_BADLEVEL ? DEFAULT_LOGLEVEL : try;
201  } else {
202  return DEFAULT_LOGLEVEL;
203  }
204 }
205 
206 
208 {
209  long level = LONG_MAX;
210 
211  if (s == NULL || *s == '\0')
212  return LIRC_BADLEVEL;
213  while (isspace(*s) && *s)
214  s++;
215  if (isdigit(*s)) {
216  level = strtol(s, NULL, 10);
217  if (level > LIRC_MAX_LOGLEVEL || level < LIRC_MIN_LOGLEVEL)
218  return LIRC_BADLEVEL;
219  else
220  return level;
221  } else {
222  return symbol2loglevel(s);
223  }
224 }
225 
226 
233 void logprintf(loglevel_t prio, const char *format_str, ...)
234 {
235  int save_errno = errno;
236  va_list ap;
237  char buff[PRIO_LEN + strlen(format_str)];
238 
239 #ifdef SYSTEMD_LOGPERROR_FIX
240  if (nodaemon && prio <= loglevel) {
241  fprintf(stderr, "%s: %s ", progname, prio2text(prio));
242  va_start(ap, format_str);
243  vfprintf(stderr, format_str, ap);
244  va_end(ap);
245  fputc('\n', stderr);
246  fflush(stderr);
247  }
248 #endif
249  if (use_syslog) {
250  snprintf(buff, sizeof(buff),
251  "%s: %s", prio2text(prio), format_str);
252  va_start(ap, format_str);
253  vsyslog(prio, buff, ap);
254  va_end(ap);
255  } else if (lf && prio <= loglevel) {
256  time_t current;
257  char *currents;
258 
259  current = time(&current);
260  currents = ctime(&current);
261 
262  fprintf(lf, "%15.15s %s %s: ",
263  currents + 4, hostname, progname);
264  fprintf(lf, "%s: ", prio2text(prio));
265  va_start(ap, format_str);
266  vfprintf(lf, format_str, ap);
267  va_end(ap);
268  fputc('\n', lf);
269  fflush(lf);
270  }
271  errno = save_errno;
272 }
273 
279 void logperror(loglevel_t prio, const char *fmt, ...)
280 {
281  char s[256];
282  va_list ap;
283 
284  va_start(ap, fmt);
285  vsnprintf(s, sizeof(s), fmt, ap);
286  va_end(ap);
287  if (use_syslog){
288  if ((s) != NULL)
289  syslog(prio, "%s: %m\n", s);
290  else
291  syslog(prio, "%m\n");
292  } else {
293  if (s != NULL) {
294  logprintf(prio, "%s: %s", s, strerror(errno));
295  } else {
296  logprintf(prio, "%s", strerror(errno));
297  }
298  }
299 }
300 
301 
302 int lirc_log_get_clientlog(const char* basename, char* buffer, ssize_t size)
303 {
304  const char* home;
305 
306  if (getenv("XDG_CACHE_HOME") != NULL ) {
307  strncpy(buffer, getenv("XDG_CACHE_HOME"), size);
308  buffer[size - 1] = '\0';
309  strncat(buffer, "/", size - strlen(buffer) - 1);
310  } else {
311  home = getenv("HOME");
312  home = home != NULL ? home : "/";
313  strncpy(buffer, home, size);
314  buffer[size - 1] = '\0';
315  strncat(buffer, "/.cache/", size - strlen(buffer) - 1);
316  }
317  strncat(buffer, basename, size - strlen(buffer) - 1);
318  strncat(buffer, ".log", size - strlen(buffer) - 1);
319  return 0;
320 }
321 
322 
323 void hexdump(char *prefix, unsigned char* buf, int len)
324 // Dump a byte array as hex code, adding a prefix.
325 {
326  int i;
327  char str[1024];
328  int pos = 0;
329  if (prefix != NULL) {
330  strncpy(str, prefix, sizeof(str));
331  pos = strnlen(str, sizeof(str));
332  }
333  if (len > 0) {
334  for (i = 0; i < len; i++) {
335  if (pos + 3 >= sizeof(str)) {
336  break;
337  }
338 
339  if (!(i % 8)) {
340  str[pos++] = ' ';
341  }
342 
343  sprintf(str + pos, "%02x ", buf[i]);
344 
345  pos += 3;
346  }
347  } else {
348  strncpy(str + pos, "NO DATA", sizeof(str));
349  }
350  LOGPRINTF(1, "%s", str);
351 }
#define LIRC_MAX_LOGLEVEL
Definition: lirc_log.h:51
loglevel_t loglevel
Definition: lirc_log.c:38
int lirc_log_open(const char *_progname, int _nodaemon, loglevel_t level)
Definition: lirc_log.c:84
loglevel_t
Definition: lirc_log.h:37
void lirc_log_set_file(const char *s)
Definition: lirc_log.c:73
int lirc_log_close()
Definition: lirc_log.c:110
#define LIRC_MIN_LOGLEVEL
Definition: lirc_log.h:54
#define DEFAULT_LOGLEVEL
Definition: lirc_log.h:63
int lirc_log_setlevel(loglevel_t level)
Definition: lirc_log.c:152
#define LOGPRINTF(level, fmt, args...)
Definition: lirc_log.h:76
void hexdump(char *prefix, unsigned char *buf, int len)
Definition: lirc_log.c:323
loglevel_t lirc_log_defaultlevel(void)
Definition: lirc_log.c:192
int lirc_log_use_syslog()
Definition: lirc_log.c:67
void logperror(loglevel_t prio, const char *fmt,...)
Definition: lirc_log.c:279
int lirc_log_get_clientlog(const char *basename, char *buffer, ssize_t size)
Definition: lirc_log.c:302
loglevel_t string2loglevel(const char *s)
Definition: lirc_log.c:207
void logprintf(loglevel_t prio, const char *format_str,...)
Definition: lirc_log.c:233