#include <net/if.h>
#include <time.h>
#include <dirent.h>
+#include <syslog.h>
#include "parse.h"
#include "config.h"
static int config_rebootsignal(const char *, const char *, struct lxc_conf *);
static int config_stopsignal(const char *, const char *, struct lxc_conf *);
static int config_start(const char *, const char *, struct lxc_conf *);
+static int config_syslog(const char *, const char *, struct lxc_conf *);
static int config_monitor(const char *, const char *, struct lxc_conf *);
static int config_group(const char *, const char *, struct lxc_conf *);
static int config_environment(const char *, const char *, struct lxc_conf *);
{ "lxc.init_uid", config_init_uid },
{ "lxc.init_gid", config_init_gid },
{ "lxc.ephemeral", config_ephemeral },
+ { "lxc.syslog", config_syslog },
};
struct signame {
#endif
};
+struct syslog_facility {
+ const char *name;
+ int facility;
+};
+
+static const struct syslog_facility syslog_facilities[] = {
+ { "daemon", LOG_DAEMON },
+ { "local0", LOG_LOCAL0 },
+ { "local1", LOG_LOCAL1 },
+ { "local2", LOG_LOCAL2 },
+ { "local3", LOG_LOCAL3 },
+ { "local4", LOG_LOCAL4 },
+ { "local5", LOG_LOCAL5 },
+ { "local6", LOG_LOCAL6 },
+ { "local7", LOG_LOCAL7 },
+};
+
static const size_t config_size = sizeof(config)/sizeof(struct lxc_config_t);
extern struct lxc_config_t *lxc_getconfig(const char *key)
return 0;
}
+static int config_syslog(const char *key, const char *value,
+ struct lxc_conf *lxc_conf)
+{
+ int n;
+ int facility = -1;
+
+ for (n = 0; n < sizeof(syslog_facilities) / sizeof((syslog_facilities)[0]); n++) {
+ if (strcasecmp(syslog_facilities[n].name, value) == 0) {
+ facility = syslog_facilities[n].facility;
+ lxc_log_syslog(facility);
+ return 0;
+ }
+ }
+
+ ERROR("Wrong value for lxc.syslog");
+ return -1;
+}
#define __USE_GNU /* for *_CLOEXEC */
+#include <syslog.h>
+#include <stdio.h>
+
#include <fcntl.h>
#include <stdlib.h>
#define LXC_LOG_DATEFOMAT_SIZE 15
int lxc_log_fd = -1;
+static int syslog_enable = 0;
int lxc_quiet_specified;
int lxc_log_use_global_fd;
static int lxc_loglevel_specified;
static char log_prefix[LXC_LOG_PREFIX_SIZE] = "lxc";
static char *log_fname = NULL;
+static char *log_vmname = NULL;
lxc_log_define(lxc_log, lxc);
+static int lxc_log_priority_to_syslog(int priority)
+{
+ switch (priority) {
+ case LXC_LOG_PRIORITY_FATAL:
+ return LOG_EMERG;
+ case LXC_LOG_PRIORITY_ALERT:
+ return LOG_ALERT;
+ case LXC_LOG_PRIORITY_CRIT:
+ return LOG_CRIT;
+ case LXC_LOG_PRIORITY_ERROR:
+ return LOG_ERR;
+ case LXC_LOG_PRIORITY_WARN:
+ return LOG_WARNING;
+ case LXC_LOG_PRIORITY_NOTICE:
+ case LXC_LOG_PRIORITY_NOTSET:
+ return LOG_NOTICE;
+ case LXC_LOG_PRIORITY_INFO:
+ return LOG_INFO;
+ case LXC_LOG_PRIORITY_TRACE:
+ case LXC_LOG_PRIORITY_DEBUG:
+ return LOG_DEBUG;
+ }
+
+ /* Not reached */
+ return LOG_NOTICE;
+}
+
+/*---------------------------------------------------------------------------*/
+static int log_append_syslog(const struct lxc_log_appender *appender,
+ struct lxc_log_event *event)
+{
+ char *msg;
+ int rc, len;
+ va_list args;
+
+ if (!syslog_enable)
+ return 0;
+
+ va_copy(args, *event->vap);
+ len = vsnprintf(NULL, 0, event->fmt, args) + 1;
+ va_end(args);
+ msg = malloc(len * sizeof(char));
+ if (msg == NULL)
+ return 0;
+ rc = vsnprintf(msg, len, event->fmt, *event->vap);
+ if (rc == -1 || rc >= len) {
+ free(msg);
+ return 0;
+ }
+
+ syslog(lxc_log_priority_to_syslog(event->priority),
+ "%s %s - %s:%s:%d - %s" ,
+ log_vmname ? log_vmname : "",
+ event->category,
+ event->locinfo->file, event->locinfo->func,
+ event->locinfo->line,
+ msg);
+ free(msg);
+ return 0;
+}
+
/*---------------------------------------------------------------------------*/
static int log_append_stderr(const struct lxc_log_appender *appender,
struct lxc_log_event *event)
if (event->priority < LXC_LOG_PRIORITY_ERROR)
return 0;
- fprintf(stderr, "%s: ", log_prefix);
+ fprintf(stderr, "%s: %s", log_prefix, log_vmname ? log_vmname : "");
fprintf(stderr, "%s: %s: %d ", event->locinfo->file, event->locinfo->func, event->locinfo->line);
vfprintf(stderr, event->fmt, *event->vap);
fprintf(stderr, "\n");
strftime(date, sizeof(date), "%Y%m%d%H%M%S", t);
ms = event->timestamp.tv_usec / 1000;
n = snprintf(buffer, sizeof(buffer),
- "%15s %10s.%03d %-8s %s - %s:%s:%d - ",
+ "%15s%s%s %10s.%03d %-8s %s - %s:%s:%d - ",
log_prefix,
+ log_vmname ? " " : "",
+ log_vmname ? log_vmname : "",
date,
ms,
lxc_log_priority_to_string(event->priority),
return write(fd_to_use, buffer, n + 1);
}
+static struct lxc_log_appender log_appender_syslog = {
+ .name = "syslog",
+ .append = log_append_syslog,
+ .next = NULL,
+};
+
static struct lxc_log_appender log_appender_stderr = {
.name = "stderr",
.append = log_append_stderr,
extern void lxc_log_close(void)
{
+ closelog();
+ free(log_vmname);
+ log_vmname = NULL;
if (lxc_log_fd == -1)
return;
close(lxc_log_fd);
return ret;
}
+extern int lxc_log_syslog(int facility)
+{
+ struct lxc_log_appender *appender;
+
+ openlog(log_prefix, LOG_PID, facility);
+ if (!lxc_log_category_lxc.appender) {
+ lxc_log_category_lxc.appender = &log_appender_syslog;
+ return 0;
+ }
+ appender = lxc_log_category_lxc.appender;
+ while (appender->next != NULL)
+ appender = appender->next;
+ appender->next = &log_appender_syslog;
+
+ return 0;
+}
+
+extern void lxc_log_enable_syslog(void)
+{
+ syslog_enable = 1;
+}
+
/*
* lxc_log_init:
* Called from lxc front-end programs (like lxc-create, lxc-start) to
if (prefix)
lxc_log_set_prefix(prefix);
+ if (name)
+ log_vmname = strdup(name);
+
if (file) {
if (strcmp(file, "none") == 0)
return 0;