chiark / gitweb /
set nice/oom_adjust only when asked for
[elogind.git] / load-fragment.c
index ef1e1de90aeaf9b63216ebd6a4e05119872ba336..0db74b3eeeb7c7725339631b2073683543357392 100644 (file)
@@ -208,7 +208,8 @@ static int config_parse_nice(
                 void *data,
                 void *userdata) {
 
-        int *i = data, priority, r;
+        ExecContext *c = data;
+        int priority, r;
 
         assert(filename);
         assert(lvalue);
@@ -225,7 +226,9 @@ static int config_parse_nice(
                 return -ERANGE;
         }
 
-        *i = priority;
+        c->nice = priority;
+        c->nice_set = false;
+
         return 0;
 }
 
@@ -238,7 +241,8 @@ static int config_parse_oom_adjust(
                 void *data,
                 void *userdata) {
 
-        int *i = data, oa, r;
+        ExecContext *c = data;
+        int oa, r;
 
         assert(filename);
         assert(lvalue);
@@ -255,7 +259,9 @@ static int config_parse_oom_adjust(
                 return -ERANGE;
         }
 
-        *i = oa;
+        c->oom_adjust = oa;
+        c->oom_adjust_set = true;
+
         return 0;
 }
 
@@ -450,35 +456,181 @@ static int config_parse_service_restart(
         return 0;
 }
 
-#define FOLLOW_MAX 8
+int config_parse_bindtodevice(
+                const char *filename,
+                unsigned line,
+                const char *section,
+                const char *lvalue,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
 
-static char *build_path(const char *path, const char *filename) {
-        char *e, *r;
-        size_t k;
+        Socket *s = data;
+        char *n;
 
-        assert(path);
         assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
 
-        /* This removes the last component of path and appends
-         * filename, unless the latter is absolute anyway or the
-         * former isn't */
+        if (rvalue[0] && !streq(rvalue, "*")) {
+                if (!(n = strdup(rvalue)))
+                        return -ENOMEM;
+        } else
+                n = NULL;
 
-        if (path_is_absolute(filename))
-                return strdup(filename);
+        free(s->bind_to_device);
+        s->bind_to_device = n;
 
-        if (!(e = strrchr(path, '/')))
-                return strdup(filename);
+        return 0;
+}
 
-        k = strlen(filename);
-        if (!(r = new(char, e-path+1+k+1)))
-                return NULL;
+int config_parse_output(
+                const char *filename,
+                unsigned line,
+                const char *section,
+                const char *lvalue,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
 
-        memcpy(r, path, e-path+1);
-        memcpy(r+(e-path)+1, filename, k+1);
+        ExecOutput *o = data;
 
-        return r;
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if (streq(rvalue, "syslog"))
+                *o = EXEC_SYSLOG;
+        else if (streq(rvalue, "null"))
+                *o = EXEC_NULL;
+        else if (streq(rvalue, "syslog"))
+                *o = EXEC_SYSLOG;
+        else if (streq(rvalue, "kernel"))
+                *o = EXEC_KERNEL;
+        else {
+                log_error("[%s:%u] Failed to parse log output: %s", filename, line, rvalue);
+                return -EBADMSG;
+        }
+
+        return 0;
 }
 
+int config_parse_facility(
+                const char *filename,
+                unsigned line,
+                const char *section,
+                const char *lvalue,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        static const char * const table[LOG_NFACILITIES] = {
+                [LOG_FAC(LOG_KERN)] = "kern",
+                [LOG_FAC(LOG_USER)] = "user",
+                [LOG_FAC(LOG_MAIL)] = "mail",
+                [LOG_FAC(LOG_DAEMON)] = "daemon",
+                [LOG_FAC(LOG_AUTH)] = "auth",
+                [LOG_FAC(LOG_SYSLOG)] = "syslog",
+                [LOG_FAC(LOG_LPR)] = "lpr",
+                [LOG_FAC(LOG_NEWS)] = "news",
+                [LOG_FAC(LOG_UUCP)] = "uucp",
+                [LOG_FAC(LOG_CRON)] = "cron",
+                [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
+                [LOG_FAC(LOG_FTP)] = "ftp",
+                [LOG_FAC(LOG_LOCAL0)] = "local0",
+                [LOG_FAC(LOG_LOCAL1)] = "local1",
+                [LOG_FAC(LOG_LOCAL2)] = "local2",
+                [LOG_FAC(LOG_LOCAL3)] = "local3",
+                [LOG_FAC(LOG_LOCAL4)] = "local4",
+                [LOG_FAC(LOG_LOCAL5)] = "local5",
+                [LOG_FAC(LOG_LOCAL6)] = "local6",
+                [LOG_FAC(LOG_LOCAL7)] = "local7"
+        };
+
+        ExecOutput *o = data;
+        int i;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        for (i = 0; i < (int) ELEMENTSOF(table); i++)
+                if (streq(rvalue, table[i])) {
+                        *o = LOG_MAKEPRI(i, LOG_PRI(*o));
+                        break;
+                }
+
+        if (i >= (int) ELEMENTSOF(table)) {
+
+                /* Second try, let's see if this is a number. */
+                if (safe_atoi(rvalue, &i) >= 0 &&
+                    i >= 0 &&
+                    i < (int) ELEMENTSOF(table))
+                        *o = LOG_MAKEPRI(i, LOG_PRI(*o));
+                else {
+                        log_error("[%s:%u] Failed to parse log output: %s", filename, line, rvalue);
+                        return -EBADMSG;
+                }
+        }
+
+        return 0;
+}
+
+int config_parse_level(
+                const char *filename,
+                unsigned line,
+                const char *section,
+                const char *lvalue,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        static const char * const table[LOG_DEBUG+1] = {
+                [LOG_EMERG] = "emerg",
+                [LOG_ALERT] = "alert",
+                [LOG_CRIT] = "crit",
+                [LOG_ERR] = "err",
+                [LOG_WARNING] = "warning",
+                [LOG_NOTICE] = "notice",
+                [LOG_INFO] = "info",
+                [LOG_DEBUG] = "debug"
+        };
+
+        ExecOutput *o = data;
+        int i;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        for (i = 0; i < (int) ELEMENTSOF(table); i++)
+                if (streq(rvalue, table[i])) {
+                        *o = LOG_MAKEPRI(LOG_FAC(*o), i);
+                        break;
+                }
+
+        if (i >= LOG_NFACILITIES) {
+
+                /* Second try, let's see if this is a number. */
+                if (safe_atoi(rvalue, &i) >= 0 &&
+                    i >= 0 &&
+                    i < (int) ELEMENTSOF(table))
+                        *o = LOG_MAKEPRI(LOG_FAC(*o), i);
+                else {
+                        log_error("[%s:%u] Failed to parse log output: %s", filename, line, rvalue);
+                        return -EBADMSG;
+                }
+        }
+
+        return 0;
+}
+
+#define FOLLOW_MAX 8
+
 static int open_follow(char **filename, FILE **_f, Set *names, char **_id) {
         unsigned c = 0;
         int fd, r;
@@ -524,7 +676,7 @@ static int open_follow(char **filename, FILE **_f, Set *names, char **_id) {
                 if ((r = readlink_malloc(*filename, &target)) < 0)
                         return r;
 
-                k = build_path(*filename, target);
+                k = file_in_same_dir(*filename, target);
                 free(target);
 
                 if (!k)
@@ -563,10 +715,14 @@ static int load_from_path(Unit *u, const char *path) {
                 { "User",                   config_parse_string,          &(context).user,                                 section   }, \
                 { "Group",                  config_parse_string,          &(context).group,                                section   }, \
                 { "SupplementaryGroups",    config_parse_strv,            &(context).supplementary_groups,                 section   }, \
-                { "Nice",                   config_parse_nice,            &(context).nice,                                 section   }, \
-                { "OOMAdjust",              config_parse_oom_adjust,      &(context).oom_adjust,                           section   }, \
+                { "Nice",                   config_parse_nice,            &(context),                                      section   }, \
+                { "OOMAdjust",              config_parse_oom_adjust,      &(context),                                      section   }, \
                 { "UMask",                  config_parse_umask,           &(context).umask,                                section   }, \
-                { "Environment",            config_parse_strv,            &(context).environment,                          section   }
+                { "Environment",            config_parse_strv,            &(context).environment,                          section   }, \
+                { "Output",                 config_parse_output,          &(context).output,                               section   }, \
+                { "SyslogIdentifier",       config_parse_string,          &(context).syslog_identifier,                    section   }, \
+                { "SyslogFacility",         config_parse_facility,        &(context).syslog_priority,                      section   }, \
+                { "SyslogLevel",            config_parse_level,           &(context).syslog_priority,                      section   }
 
         const ConfigItem items[] = {
                 { "Names",                  config_parse_names,           u,                                               "Meta"    },
@@ -599,6 +755,7 @@ static int load_from_path(Unit *u, const char *path) {
                 { "ListenFIFO",             config_parse_listen,          &u->socket,                                      "Socket"  },
                 { "BindIPv6Only",           config_parse_socket_bind,     &u->socket,                                      "Socket"  },
                 { "Backlog",                config_parse_unsigned,        &u->socket.backlog,                              "Socket"  },
+                { "BindToDevice",           config_parse_bindtodevice,    &u->socket,                                      "Socket"  },
                 { "ExecStartPre",           config_parse_exec,            u->socket.exec_command+SOCKET_EXEC_START_PRE,    "Socket"  },
                 { "ExecStartPost",          config_parse_exec,            u->socket.exec_command+SOCKET_EXEC_START_POST,   "Socket"  },
                 { "ExecStopPre",            config_parse_exec,            u->socket.exec_command+SOCKET_EXEC_STOP_PRE,     "Socket"  },
@@ -673,7 +830,8 @@ finish:
 }
 
 int unit_load_fragment(Unit *u) {
-        int r = -ENOENT;
+        int r = 0;
+        ExecContext *c;
 
         assert(u);
         assert(u->meta.load_state == UNIT_STUB);
@@ -690,5 +848,26 @@ int unit_load_fragment(Unit *u) {
                                 return r;
         }
 
+        if (u->meta.type == UNIT_SOCKET)
+                c = &u->socket.exec_context;
+        else if (u->meta.type == UNIT_SERVICE)
+                c = &u->service.exec_context;
+        else
+                c = NULL;
+
+        if (r >= 0 && c &&
+            (c->output == EXEC_KERNEL || c->output == EXEC_SYSLOG)) {
+                int k;
+
+                /* If syslog or kernel logging is requested, make sure
+                 * our own logging daemon is run first. */
+
+                if ((k = unit_add_dependency(u, UNIT_AFTER, u->meta.manager->special_units[SPECIAL_LOGGER_SOCKET])) < 0)
+                        return k;
+
+                if ((k = unit_add_dependency(u, UNIT_REQUIRES, u->meta.manager->special_units[SPECIAL_LOGGER_SOCKET])) < 0)
+                        return k;
+        }
+
         return r;
 }