34 #include "lirc/lirc_log.h"
37 #define min(a, b) (a < b ? a : b)
40 #define HOSTNAME_LEN 128
44 char hostname[HOSTNAME_LEN + 1];
51 static int use_syslog = 1;
53 const char* syslogident =
"lircd-" VERSION;
54 const char* logfile =
"syslog";
56 char progname[128] = {
'?',
'\0' };
57 static int nodaemon = 0;
59 static const int PRIO_LEN = 16;
62 static const char* prio2text(
int prio)
65 case LIRC_DEBUG:
return "Debug";
66 case LIRC_NOTICE:
return "Notice";
67 case LIRC_INFO:
return "Info";
68 case LIRC_WARNING:
return "Warning";
69 case LIRC_ERROR:
return "Error";
70 case LIRC_TRACE:
return "Trace";
71 case LIRC_TRACE1:
return "Trace1";
72 case LIRC_TRACE2:
return "Trace2";
73 default:
return "(Bad prio)";
86 if (strcmp(s,
"syslog") == 0) {
97 strncpy(progname, _progname,
sizeof(progname));
105 openlog(syslogident, LOG_CONS | LOG_PID | LOG_PERROR, LOG_LOCAL0);
107 openlog(syslogident, LOG_CONS | LOG_PID, LOG_LOCAL0);
109 lf = fopen(logfile,
"a");
111 fprintf(stderr,
"%s: could not open logfile \"%s\"\n",
116 if (getenv(
"SUDO_USER") != NULL && geteuid() == 0) {
117 user = getenv(
"SUDO_USER");
118 user = user == NULL ?
"root" : user;
120 if (chown(logfile, pw->pw_uid, pw->pw_gid) == -1)
121 perror(
"Cannot reset log file owner.");
123 gethostname(hostname, HOSTNAME_LEN);
124 log_warn(
"------------------------ Log re-opened ----------------------------");
126 if (getenv(
"LIRC_LOGCHANNEL") != NULL) {
129 if (level != LIRC_NOLOG) {
130 logprintf(level,
"%s: Opening log, level: %s",
131 _progname, prio2text(level));
150 int lirc_log_reopen(
void)
159 if (-1 == fstat(fileno(lf), &s)) {
160 perror(
"Invalid logfile!");
164 lf = fopen(logfile,
"a");
167 perror(
"Can't open logfile");
171 if (-1 == fchmod(fileno(lf), s.st_mode)) {
172 log_warn(
"could not set file permissions");
190 static loglevel_t symbol2loglevel(
const char* levelstring)
192 static const struct {
const char* label;
int value; } options[] = {
193 {
"TRACE2", LIRC_TRACE2 },
194 {
"TRACE1", LIRC_TRACE1 },
195 {
"TRACE", LIRC_TRACE },
196 {
"DEBUG", LIRC_DEBUG },
197 {
"INFO", LIRC_INFO },
198 {
"NOTICE", LIRC_NOTICE },
199 {
"WARNING", LIRC_WARNING },
200 {
"ERROR", LIRC_ERROR },
207 if (levelstring == NULL || !*levelstring)
208 return LIRC_BADLEVEL;
209 for (i = 0; i <
sizeof(label) && levelstring[i]; i += 1)
210 label[i] = toupper(levelstring[i]);
213 while (options[i].label && strcmp(options[i].label, label) != 0)
215 return options[i].label ? options[i].value : -1;
223 const char*
const level = getenv(
"LIRC_LOGLEVEL");
236 long level = LONG_MAX;
238 if (s == NULL || *s ==
'\0')
239 return LIRC_BADLEVEL;
240 while (isspace(*s) && *s)
243 level = strtol(s, NULL, 10);
245 return LIRC_BADLEVEL;
249 return symbol2loglevel(s);
259 va_start(ap, format);
260 vsnprintf(buff,
sizeof(buff), format, ap);
275 int save_errno = errno;
277 char buff[PRIO_LEN + strlen(format_str)];
280 snprintf(buff,
sizeof(buff),
281 "%s: %s", prio2text(prio), format_str);
282 va_start(ap, format_str);
283 vsyslog(min(7, prio), buff, ap);
290 gettimeofday(&tv, &tz);
291 currents = ctime(&tv.tv_sec);
293 fprintf(lf,
"%15.15s.%06ld %s %s: ",
294 currents + 4, (
long) tv.tv_usec, hostname, progname);
295 fprintf(lf,
"%s: ", prio2text(prio));
296 va_start(ap, format_str);
297 vfprintf(lf, format_str, ap);
316 vsnprintf(s,
sizeof(s), fmt, ap);
320 syslog(min(7, prio),
"%s: %m\n", s);
322 syslog(min(7, prio),
"%m\n");
325 logprintf(prio,
"%s: %s", s, strerror(errno));
339 if (getenv(
"XDG_CACHE_HOME") != NULL) {
340 strncpy(buffer, getenv(
"XDG_CACHE_HOME"), size);
341 buffer[size - 1] =
'\0';
342 }
else if (getenv(
"SUDO_USER") != NULL && geteuid() == 0) {
343 user = getenv(
"SUDO_USER");
347 snprintf(buffer, size,
"%s/.cache", pw->pw_dir);
349 home = getenv(
"HOME");
350 home = home != NULL ? home :
"/tmp";
351 snprintf(buffer, size,
"%s/.cache", home);
353 if (access(buffer, F_OK) != 0) {
354 r = mkdir(buffer, 0777);
357 "Cannot create log directory %s", buffer);
358 syslog(LOG_WARNING,
"Falling back to using /tmp");
359 strcpy(buffer,
"/tmp");
362 strncat(buffer,
"/", size - strlen(buffer) - 1);
363 strncat(buffer, basename, size - strlen(buffer) - 1);
364 strncat(buffer,
".log", size - strlen(buffer) - 1);
369 void hexdump(
char* prefix,
unsigned char* buf,
int len)
376 if (prefix != NULL) {
377 strncpy(str, prefix,
sizeof(str));
378 pos = strnlen(str,
sizeof(str));
381 for (i = 0; i < len; i++) {
382 if (pos + 3 >=
sizeof(str))
388 sprintf(str + pos,
"%02x ", buf[i]);
393 strncpy(str + pos,
"NO DATA",
sizeof(str));
#define LIRC_MAX_LOGLEVEL
Max loglevel (for validation).
loglevel_t loglevel
The actual loglevel.
int lirc_log_open(const char *_progname, int _nodaemon, loglevel_t level)
Open the log for upcoming logging.
#define log_warn(fmt,...)
Log a warning message.
logchannel_t
Log channels used to filter messages.
int lirc_log_close(void)
Close the log previosly opened with lirc_log_open().
loglevel_t
The defined loglevels.
void lirc_log_set_file(const char *s)
Set logfile.
int lirc_log_use_syslog(void)
Check if log is set up to use syslog or not.
#define log_trace(fmt,...)
Log a trace message.
logchannel_t logged_channels
The actual logchannel.
#define LIRC_MIN_LOGLEVEL
Mix loglevel (for validation).
#define DEFAULT_LOGLEVEL
Default loglevel (last resort).
int lirc_log_setlevel(loglevel_t level)
Set the level.
void hexdump(char *prefix, unsigned char *buf, int len)
Print prefix + a hex dump of len bytes starting at *buf.
loglevel_t lirc_log_defaultlevel(void)
Get the default level, from environment or hardcoded.
void logperror(loglevel_t prio, const char *fmt,...)
Prints a description of the last error to the log.
int lirc_log_get_clientlog(const char *basename, char *buffer, ssize_t size)
Retrieve a client path for logging according to freedesktop specs.
loglevel_t string2loglevel(const char *s)
Convert a string, either a number or 'info', 'trace1', error etc.
#define log_info(fmt,...)
Log an info message.
void logprintf(loglevel_t prio, const char *format_str,...)
Write a message to the log.
void perrorf(const char *format,...)
Adds printf-style arguments to perror(3).