chiark / gitweb /
exec: extend variable substitution to support splitting variable values into seperate...
authorLennart Poettering <lennart@poettering.net>
Wed, 21 Jul 2010 00:57:35 +0000 (02:57 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 21 Jul 2010 00:57:35 +0000 (02:57 +0200)
Makefile.am
fixme
man/systemd.service.xml
src/test-env-replace.c [new file with mode: 0644]
src/util.c
units/.gitignore
units/emergency.service
units/fedora/single.service

index 94ae6af..4dcecc5 100644 (file)
@@ -77,7 +77,8 @@ noinst_PROGRAMS = \
        test-ns \
        test-loopback \
        test-daemon \
-       test-cgroup
+       test-cgroup \
+       test-env-replace
 
 if HAVE_PAM
 pamlib_LTLIBRARIES = \
@@ -446,6 +447,15 @@ test_cgroup_CFLAGS = \
 test_cgroup_LDADD = \
        libsystemd-basic.la
 
+test_env_replace_SOURCES = \
+       src/test-env-replace.c
+
+test_env_replace_CFLAGS = \
+       $(AM_CFLAGS)
+
+test_env_replace_LDADD = \
+       libsystemd-basic.la
+
 systemd_logger_SOURCES = \
        src/logger.c \
        src/sd-daemon.c \
diff --git a/fixme b/fixme
index 5737863..29a6db4 100644 (file)
--- a/fixme
+++ b/fixme
@@ -35,9 +35,9 @@
 
 * systemctl status $PID, systemctl stop $PID!
 
-* place /etc/inittab with explaining blurb.
+/dev/null symlinks supporten
 
-* In command lines, support both "$FOO" and $FOO
+* place /etc/inittab with explaining blurb.
 
 * /etc must always take precedence even if we follow symlinks!
 
index 9623883..94a21d3 100644 (file)
                                 <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>. On
                                 top of that basic environment variable
                                 substitution is supported, where
-                                <literal>$(FOO)</literal> is replaced
-                                by the value of the environment
-                                variable of the same
-                                name.</para></listitem>
+                                <literal>${FOO}</literal> is replaced
+                                by the string value of the environment
+                                variable of the same name. Also
+                                <literal>$FOO</literal> may appear as
+                                seperate word on the command line in
+                                which case the variable is replaced by
+                                its value split at
+                                whitespaces.</para></listitem>
                         </varlistentry>
 
                         <varlistentry>
diff --git a/src/test-env-replace.c b/src/test-env-replace.c
new file mode 100644 (file)
index 0000000..df101fd
--- /dev/null
@@ -0,0 +1,59 @@
+/*-*- Mode: C; c-basic-offset: 8 -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <unistd.h>
+#include <string.h>
+
+#include "util.h"
+#include "log.h"
+#include "strv.h"
+
+int main(int argc, char *argv[]) {
+
+        const char *env[] = {
+                "FOO=BAR BAR",
+                "BAR=waldo",
+                NULL
+        };
+
+        const char *line[] = {
+                "FOO$FOO",
+                "FOO$FOOFOO",
+                "FOO${FOO}$FOO",
+                "FOO${FOO}",
+                "${FOO}",
+                "$FOO",
+                "$FOO$FOO",
+                "${FOO}${BAR}",
+                "${FOO",
+                NULL
+        };
+
+        char **i, **r;
+
+        r = replace_env_argv((char**) line, (char**) env);
+
+        STRV_FOREACH(i, r)
+                printf("%s\n", *i);
+
+        strv_free(r);
+
+}
index 45de609..da8a6c3 100644 (file)
@@ -2778,7 +2778,7 @@ void status_welcome(void) {
 char *replace_env(const char *format, char **env) {
         enum {
                 WORD,
-                DOLLAR,
+                CURLY,
                 VARIABLE
         } state = WORD;
 
@@ -2793,11 +2793,11 @@ char *replace_env(const char *format, char **env) {
 
                 case WORD:
                         if (*e == '$')
-                                state = DOLLAR;
+                                state = CURLY;
                         break;
 
-                case DOLLAR:
-                        if (*e == '(') {
+                case CURLY:
+                        if (*e == '{') {
                                 if (!(k = strnappend(r, word, e-word-1)))
                                         goto fail;
 
@@ -2821,7 +2821,7 @@ char *replace_env(const char *format, char **env) {
                         break;
 
                 case VARIABLE:
-                        if (*e == ')') {
+                        if (*e == '}') {
                                 char *t;
 
                                 if ((t = strv_env_get_with_length(env, word+2, e-word-2))) {
@@ -2853,12 +2853,49 @@ fail:
 
 char **replace_env_argv(char **argv, char **env) {
         char **r, **i;
-        unsigned k = 0;
+        unsigned k = 0, l = 0;
+
+        l = strv_length(argv);
 
-        if (!(r = new(char*, strv_length(argv)+1)))
+        if (!(r = new(char*, l+1)))
                 return NULL;
 
         STRV_FOREACH(i, argv) {
+
+                /* If $FOO appears as single word, replace it by the split up variable */
+                if ((*i)[0] == '$') {
+                        char *e = strv_env_get(env, *i+1);
+
+                        if (e) {
+                                char **w, **m;
+                                unsigned q;
+
+                                if (!(m = strv_split_quoted(e))) {
+                                        r[k] = NULL;
+                                        strv_free(r);
+                                        return NULL;
+                                }
+
+                                q = strv_length(m);
+                                l = l + q - 1;
+
+                                if (!(w = realloc(r, sizeof(char*) * (l+1)))) {
+                                        r[k] = NULL;
+                                        strv_free(r);
+                                        strv_free(m);
+                                        return NULL;
+                                }
+
+                                r = w;
+                                memcpy(r + k, m, q * sizeof(char*));
+                                free(m);
+
+                                k += q;
+                                continue;
+                        }
+                }
+
+                /* If ${FOO} appears as part of a word, replace it by the variable as-is */
                 if (!(r[k++] = replace_env(*i, env))) {
                         strv_free(r);
                         return NULL;
index ea85dc0..5de1b5c 100644 (file)
@@ -6,3 +6,4 @@ graphical.target
 multi-user.target
 getty@.service
 remote-fs.target
+test-env-replace
index dd4a070..7a1f81a 100644 (file)
@@ -22,4 +22,4 @@ KillMode=process-group
 
 # Bash ignores SIGTERM, so we send SIGHUP first, to ensure that bash
 # terminates cleanly.
-ExecStop=-/bin/kill -HUP $(MAINPID)
+ExecStop=-/bin/kill -HUP ${MAINPID}
index f4af539..93a70cf 100644 (file)
@@ -25,4 +25,4 @@ KillMode=process-group
 
 # Bash ignores SIGTERM, so we send SIGHUP first, to ensure that bash
 # terminates cleanly.
-ExecStop=-/bin/kill -HUP $(MAINPID)
+ExecStop=-/bin/kill -HUP ${MAINPID}