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