[systemd-commits] 10 commits - man/systemd.service.xml man/systemd.socket.xml man/systemd.unit.xml src/conf-parser.c src/dbus.c src/device.c src/load-fragment.c src/main.c src/service.c src/strv.c src/util.c src/util.h units/fedora units/gentoo units/getty at .service.m4 units/graphical.target.m4 units/multi-user.target.m4 units/suse
Lennart Poettering
lennart at kemper.freedesktop.org
Wed Jul 7 13:29:58 PDT 2010
man/systemd.service.xml | 49 +++++++++++------
man/systemd.socket.xml | 25 +++++----
man/systemd.unit.xml | 5 +
src/conf-parser.c | 48 +++++++++++++++--
src/dbus.c | 8 +-
src/device.c | 2
src/load-fragment.c | 125 ++++++++++++++++++++++++++-------------------
src/main.c | 2
src/service.c | 4 -
src/strv.c | 2
src/util.c | 64 ++++++++++++++++-------
src/util.h | 11 ++-
units/fedora/halt.service | 3 -
units/gentoo/halt.service | 3 -
units/getty at .service.m4 | 7 --
units/graphical.target.m4 | 5 -
units/multi-user.target.m4 | 7 --
units/suse/halt.service | 3 -
18 files changed, 234 insertions(+), 139 deletions(-)
New commits:
commit 07405e90968c39f04bc00e1af5b1671940482b19
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Jul 7 22:29:41 2010 +0200
units: in order to make the default services parseable by GKeyFile, merge repeated lines
diff --git a/units/fedora/halt.service b/units/fedora/halt.service
index 815c8fb..106ac6b 100644
--- a/units/fedora/halt.service
+++ b/units/fedora/halt.service
@@ -15,6 +15,5 @@ Conflicts=dev-hugepages.automount dev-mqueue.automount proc-sys-fs-binfmt_misc.a
[Service]
Type=finish
ValidNoProcess=yes
-Environment=INIT_HALT=HALT
-Environment=RUNLEVEL=0
+Environment=INIT_HALT=HALT RUNLEVEL=0
ExecStart=/etc/init.d/halt start
diff --git a/units/gentoo/halt.service b/units/gentoo/halt.service
index ecf4cff..56ac493 100644
--- a/units/gentoo/halt.service
+++ b/units/gentoo/halt.service
@@ -15,6 +15,5 @@ Conflicts=dev-hugepages.automount dev-mqueue.automount proc-sys-fs-binfmt_misc.a
[Service]
Type=finish
ValidNoProcess=yes
-Environment=INIT_HALT=HALT
-Environment=RC_DOWN_HARDDISK=yes
+Environment=INIT_HALT=HALT RC_DOWN_HARDDISK=yes
ExecStart=/etc/init.d/shutdown.sh
diff --git a/units/getty at .service.m4 b/units/getty at .service.m4
index f1f7f32..b82f5aa 100644
--- a/units/getty at .service.m4
+++ b/units/getty at .service.m4
@@ -29,9 +29,4 @@ RestartSec=0
KillMode=process-group
[Install]
-Alias=getty.target.wants/getty at tty1.service
-Alias=getty.target.wants/getty at tty2.service
-Alias=getty.target.wants/getty at tty3.service
-Alias=getty.target.wants/getty at tty4.service
-Alias=getty.target.wants/getty at tty5.service
-Alias=getty.target.wants/getty at tty6.service
+Alias=getty.target.wants/getty at tty1.service getty.target.wants/getty at tty2.service getty.target.wants/getty at tty3.service getty.target.wants/getty at tty4.service getty.target.wants/getty at tty5.service getty.target.wants/getty at tty6.service
diff --git a/units/graphical.target.m4 b/units/graphical.target.m4
index 6228026..468770a 100644
--- a/units/graphical.target.m4
+++ b/units/graphical.target.m4
@@ -22,7 +22,4 @@ Names=runlevel5.target
)m4_dnl
[Install]
-Alias=default.target
-m4_ifdef(`TARGET_FEDORA',
-Alias=runlevel5.target
-)m4_dnl
+Alias=default.target m4_ifdef(`TARGET_FEDORA', runlevel5.target)
diff --git a/units/multi-user.target.m4 b/units/multi-user.target.m4
index eb46b2b..010e7d8 100644
--- a/units/multi-user.target.m4
+++ b/units/multi-user.target.m4
@@ -22,9 +22,4 @@ Names=runlevel3.target
)m4_dnl
[Install]
-Alias=default.target
-m4_ifdef(`TARGET_FEDORA',
-Alias=runlevel2.target
-Alias=runlevel3.target
-Alias=runlevel4.target
-)m4_dnl
+Alias=default.target m4_ifdef(`TARGET_FEDORA', runlevel2.target runlevel3.target runlevel4.target)
diff --git a/units/suse/halt.service b/units/suse/halt.service
index fbcf154..40d58b3 100644
--- a/units/suse/halt.service
+++ b/units/suse/halt.service
@@ -15,6 +15,5 @@ Conflicts=dev-hugepages.automount dev-mqueue.automount proc-sys-fs-binfmt_misc.a
[Service]
Type=finish
ValidNoProcess=yes
-Environment=INIT_HALT=HALT
-Environment=RUNLEVEL=0
+Environment=INIT_HALT=HALT RUNLEVEL=0
ExecStart=/etc/init.d/halt start
commit e167fb86f6935c0fe989d6ccfbbc0acadba245a2
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Jul 7 22:28:51 2010 +0200
util: handle \s escape as defined in the XDG spec properly in cunescape()
diff --git a/src/util.c b/src/util.c
index 5103cc6..a01229e 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1182,6 +1182,11 @@ char *cunescape_length(const char *s, size_t length) {
*(t++) = '\'';
break;
+ case 's':
+ /* This is an extension of the XDG syntax files */
+ *(t++) = ' ';
+ break;
+
case 'x': {
/* hexadecimal encoding */
int a, b;
commit 923f8d76dc1e14be0d8c969b1661d0279ddd97ba
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Jul 7 22:28:02 2010 +0200
dbus: shut down bus connection cleanly and fully when a direct client disconnects
diff --git a/src/dbus.c b/src/dbus.c
index 8172197..0008cfd 100644
--- a/src/dbus.c
+++ b/src/dbus.c
@@ -71,6 +71,7 @@ static const char *error_to_dbus(int error);
static void bus_done_api(Manager *m);
static void bus_done_system(Manager *m);
static void bus_done_private(Manager *m);
+static void shutdown_connection(Manager *m, DBusConnection *c);
static void bus_dispatch_status(DBusConnection *bus, DBusDispatchStatus status, void *data) {
Manager *m = data;
@@ -477,11 +478,8 @@ static DBusHandlerResult private_bus_message_filter(DBusConnection *connection,
dbus_message_get_member(message),
dbus_message_get_path(message));
- if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
- set_remove(m->bus_connections, connection);
- set_remove(m->bus_connections_for_dispatch, connection);
- dbus_connection_unref(connection);
- }
+ if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected"))
+ shutdown_connection(m, connection);
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
commit b3eaa6288107210a84d6d121036fb4b2f7283ee2
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Jul 7 21:22:56 2010 +0200
man: update man pages for recent syntax changes
diff --git a/man/systemd.service.xml b/man/systemd.service.xml
index bceb5aa..7eaf9cb 100644
--- a/man/systemd.service.xml
+++ b/man/systemd.service.xml
@@ -270,10 +270,21 @@
<listitem><para>Additional commands
that are executed before (resp. after)
the command in
- <varname>ExecStart=</varname>. If
- specified more than once, all commands
- are executed one after the other,
- serially. Use of these settings is
+ <varname>ExecStart=</varname>. Multiple
+ command lines may be concatenated in a
+ single directive, by seperating them
+ by semicolons (these semicolons must
+ be passed as seperate words). In that
+ case, the commands are executed one
+ after the other,
+ serially. Alternatively, these
+ directives may be specified more than
+ once whith the same effect. However,
+ the latter syntax is not recommended
+ for compatibility with parsers
+ suitable for XDG
+ <filename>.desktop</filename> files.
+ Use of these settings is
optional.</para></listitem>
</varlistentry>
@@ -281,20 +292,24 @@
<term><varname>ExecReload=</varname></term>
<listitem><para>Commands to execute to
trigger a configuration reload in the
- service. If used more than once, all
- commands are executed one after the
- other, serially. Use of this setting is optional.
- </para></listitem>
+ service. This argument takes multiple
+ command lines, following the same
+ scheme as pointed out for
+ <varname>ExecStartPre=</varname>
+ above. Use of this setting is
+ optional. </para></listitem>
</varlistentry>
<varlistentry>
<term><varname>ExecStop=</varname></term>
<listitem><para>Commands to execute to
stop the service started via
- <varname>ExecStart=</varname>. If used
- more than once, all commands are
- executed one after the other,
- serially. Use of this setting is
+ <varname>ExecStart=</varname>. This
+ argument takes multiple command lines,
+ following the same scheme as pointed
+ out for
+ <varname>ExecStartPre=</varname>
+ above. Use of this setting is
optional. All processes remaining for
a service after the commands
configured in this option are run are
@@ -312,10 +327,12 @@
that are executed after the service
was stopped using the commands
configured in
- <varname>ExecStop=</varname>. If
- specified more than once, all commands
- are executed one after the other,
- serially. Use of these settings is
+ <varname>ExecStop=</varname>. This
+ argument takes multiple command lines,
+ following the same scheme as pointed
+ out for
+ <varname>ExecStartPre</varname>. Use
+ of these settings is
optional.</para></listitem>
</varlistentry>
diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml
index 32102fa..20dc00e 100644
--- a/man/systemd.socket.xml
+++ b/man/systemd.socket.xml
@@ -440,16 +440,18 @@
<varlistentry>
<term><varname>ExecStartPre=</varname></term>
<term><varname>ExecStartPost=</varname></term>
- <listitem><para>Takes a command line,
- which is executed before (resp. after)
- the listening sockets/FIFOs are created and
+ <listitem><para>Takes one or more
+ command lines, which are executed
+ before (resp. after) the listening
+ sockets/FIFOs are created and
bound. The first token of the command
line must be an absolute file name,
then followed by arguments for the
- process. If specified more than once,
- all commands are executed one after
- the other, fully serialized. The use of
- these settings is optional.</para></listitem>
+ process. Multiple command lines may be
+ specified following the same scheme as
+ used for
+ <varname>ExecStartPre=</varname> of
+ service unit files.</para></listitem>
</varlistentry>
<varlistentry>
@@ -458,10 +460,11 @@
<listitem><para>Additional commands
that are executed before (resp. after)
the listening sockets/FIFOs are closed
- and removed. If specified more than
- once, all commands are executed one
- after the other, fully serialized. The use of
- these settings is optional.</para></listitem>
+ and removed. Multiple command lines
+ may be specified following the same
+ scheme as used for
+ <varname>ExecStartPre=</varname> of
+ service unit files.</para></listitem>
</varlistentry>
<varlistentry>
diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index 26272c4..a06eed5 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -114,7 +114,10 @@
are understood: s, min, h, d, w, ms, us.</para>
<para>Empty lines and lines starting with # or ; are
- ignored. This may be used for commenting.</para>
+ ignored. This may be used for commenting. Lines ending
+ in a backslash are concatenated with the following
+ line while reading and the backslash is replaced by a
+ space character. This may be used to wrap long lines.</para>
<para>If a line starts with <option>.include</option>
followed by a file name the specified file will be
commit 61e5d8ed877b6389ea94c05e0e2f646f8b66d8bd
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Jul 7 20:59:20 2010 +0200
service: allow configuration of more than one Exec command in one line
diff --git a/src/load-fragment.c b/src/load-fragment.c
index 43b8093..c3909e9 100644
--- a/src/load-fragment.c
+++ b/src/load-fragment.c
@@ -364,73 +364,94 @@ static int config_parse_exec(
void *data,
void *userdata) {
- ExecCommand **e = data, *nce = NULL;
- char **n;
- char *w;
+ ExecCommand **e = data, *nce;
+ char *path, **n;
unsigned k;
- size_t l;
- char *state, *path = NULL;
- bool honour_argv0, write_to_path;
assert(filename);
assert(lvalue);
assert(rvalue);
- assert(data);
+ assert(e);
/* We accept an absolute path as first argument, or
* alternatively an absolute prefixed with @ to allow
* overriding of argv[0]. */
- honour_argv0 = rvalue[0] == '@';
+ for (;;) {
+ char *w;
+ size_t l;
+ char *state;
+ bool honour_argv0, write_to_path;
- if (rvalue[honour_argv0 ? 1 : 0] != '/') {
- log_error("[%s:%u] Invalid executable path in command line: %s", filename, line, rvalue);
- return -EINVAL;
- }
+ path = NULL;
+ nce = NULL;
+ n = NULL;
- k = 0;
- FOREACH_WORD_QUOTED(w, l, rvalue, state)
- k++;
+ rvalue += strspn(rvalue, WHITESPACE);
- if (!(n = new(char*, k + (honour_argv0 ? 0 : 1))))
- return -ENOMEM;
+ if (rvalue[0] == 0)
+ break;
- k = 0;
- write_to_path = honour_argv0;
- FOREACH_WORD_QUOTED(w, l, rvalue, state) {
- if (write_to_path) {
- if (!(path = strndup(w+1, l-1)))
- goto fail;
- write_to_path = false;
- } else {
- if (!(n[k++] = strndup(w, l)))
- goto fail;
+ honour_argv0 = rvalue[0] == '@';
+
+ if (rvalue[honour_argv0 ? 1 : 0] != '/') {
+ log_error("[%s:%u] Invalid executable path in command line: %s", filename, line, rvalue);
+ return -EINVAL;
}
- }
- n[k] = NULL;
+ k = 0;
+ FOREACH_WORD_QUOTED(w, l, rvalue, state) {
+ if (strncmp(w, ";", l) == 0)
+ break;
- if (!n[0]) {
- log_error("[%s:%u] Invalid command line: %s", filename, line, rvalue);
- strv_free(n);
- return -EINVAL;
- }
+ k++;
+ }
- if (!path)
- if (!(path = strdup(n[0])))
- goto fail;
+ if (!(n = new(char*, k + (honour_argv0 ? 0 : 1))))
+ return -ENOMEM;
+
+ k = 0;
+ write_to_path = honour_argv0;
+ FOREACH_WORD_QUOTED(w, l, rvalue, state) {
+ if (strncmp(w, ";", l) == 0)
+ break;
+
+ if (write_to_path) {
+ if (!(path = cunescape_length(w+1, l-1)))
+ goto fail;
+ write_to_path = false;
+ } else {
+ if (!(n[k++] = cunescape_length(w, l)))
+ goto fail;
+ }
+ }
- assert(path_is_absolute(path));
+ n[k] = NULL;
- if (!(nce = new0(ExecCommand, 1)))
- goto fail;
+ if (!n[0]) {
+ log_error("[%s:%u] Invalid command line: %s", filename, line, rvalue);
+ strv_free(n);
+ return -EINVAL;
+ }
- nce->argv = n;
- nce->path = path;
+ if (!path)
+ if (!(path = strdup(n[0])))
+ goto fail;
- path_kill_slashes(nce->path);
+ assert(path_is_absolute(path));
+
+ if (!(nce = new0(ExecCommand, 1)))
+ goto fail;
- exec_command_append_list(e, nce);
+ nce->argv = n;
+ nce->path = path;
+
+ path_kill_slashes(nce->path);
+
+ exec_command_append_list(e, nce);
+
+ rvalue = state;
+ }
return 0;
commit f60f22dfbb8cfa0eb55d1896db0e4c3f7d3cfacb
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Jul 7 20:58:41 2010 +0200
util: use quoted word parsing where applicable
diff --git a/src/conf-parser.c b/src/conf-parser.c
index df3584d..1cabc0d 100644
--- a/src/conf-parser.c
+++ b/src/conf-parser.c
@@ -423,7 +423,7 @@ int config_parse_strv(
k = 0;
FOREACH_WORD_QUOTED(w, l, rvalue, state)
- if (!(n[k++] = strndup(w, l)))
+ if (!(n[k++] = cunescape_length(w, l)))
goto fail;
n[k] = NULL;
@@ -475,7 +475,7 @@ int config_parse_path_strv(
n[k] = (*sv)[k];
FOREACH_WORD_QUOTED(w, l, rvalue, state) {
- if (!(n[k] = strndup(w, l))) {
+ if (!(n[k] = cunescape_length(w, l))) {
r = -ENOMEM;
goto fail;
}
diff --git a/src/device.c b/src/device.c
index a0349c4..2079f1c 100644
--- a/src/device.c
+++ b/src/device.c
@@ -244,7 +244,7 @@ static int device_process_new_device(Manager *m, struct udev_device *dev, bool u
goto fail;
if (wants) {
- FOREACH_WORD(w, l, wants, state) {
+ FOREACH_WORD_QUOTED(w, l, wants, state) {
char *e;
if (!(e = strndup(w, l))) {
diff --git a/src/load-fragment.c b/src/load-fragment.c
index 1cc7c5c..43b8093 100644
--- a/src/load-fragment.c
+++ b/src/load-fragment.c
@@ -61,7 +61,7 @@ static int config_parse_deps(
assert(lvalue);
assert(rvalue);
- FOREACH_WORD(w, l, rvalue, state) {
+ FOREACH_WORD_QUOTED(w, l, rvalue, state) {
char *t, *k;
int r;
@@ -103,7 +103,7 @@ static int config_parse_names(
assert(rvalue);
assert(data);
- FOREACH_WORD(w, l, rvalue, state) {
+ FOREACH_WORD_QUOTED(w, l, rvalue, state) {
char *t, *k;
int r;
@@ -689,7 +689,7 @@ static int config_parse_cpu_affinity(
assert(rvalue);
assert(data);
- FOREACH_WORD(w, l, rvalue, state) {
+ FOREACH_WORD_QUOTED(w, l, rvalue, state) {
char *t;
int r;
unsigned cpu;
@@ -766,7 +766,7 @@ static int config_parse_secure_bits(
assert(rvalue);
assert(data);
- FOREACH_WORD(w, l, rvalue, state) {
+ FOREACH_WORD_QUOTED(w, l, rvalue, state) {
if (first_word(w, "keep-caps"))
c->secure_bits |= SECURE_KEEP_CAPS;
else if (first_word(w, "keep-caps-locked"))
@@ -807,7 +807,7 @@ static int config_parse_bounding_set(
assert(rvalue);
assert(data);
- FOREACH_WORD(w, l, rvalue, state) {
+ FOREACH_WORD_QUOTED(w, l, rvalue, state) {
char *t;
int r;
cap_value_t cap;
@@ -902,11 +902,11 @@ static int config_parse_cgroup(
size_t l;
char *state;
- FOREACH_WORD(w, l, rvalue, state) {
+ FOREACH_WORD_QUOTED(w, l, rvalue, state) {
char *t;
int r;
- if (!(t = strndup(w, l)))
+ if (!(t = cunescape_length(w, l)))
return -ENOMEM;
r = unit_add_cgroup_from_text(u, t);
@@ -967,7 +967,7 @@ static int config_parse_mount_flags(
assert(rvalue);
assert(data);
- FOREACH_WORD(w, l, rvalue, state) {
+ FOREACH_WORD_QUOTED(w, l, rvalue, state) {
if (strncmp(w, "shared", l) == 0)
flags |= MS_SHARED;
else if (strncmp(w, "slave", l) == 0)
diff --git a/src/main.c b/src/main.c
index 592edbe..d5902b3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -426,7 +426,7 @@ static int config_parse_cpu_affinity(
assert(lvalue);
assert(rvalue);
- FOREACH_WORD(w, l, rvalue, state) {
+ FOREACH_WORD_QUOTED(w, l, rvalue, state) {
char *t;
int r;
unsigned cpu;
diff --git a/src/service.c b/src/service.c
index ccc8312..fed8227 100644
--- a/src/service.c
+++ b/src/service.c
@@ -526,7 +526,7 @@ static int service_load_sysv_path(Service *s, const char *path) {
state = LSB;
- FOREACH_WORD(w, z, t+9, i) {
+ FOREACH_WORD_QUOTED(w, z, t+9, i) {
char *n, *m;
if (!(n = strndup(w, z))) {
@@ -563,7 +563,7 @@ static int service_load_sysv_path(Service *s, const char *path) {
state = LSB;
- FOREACH_WORD(w, z, strchr(t, ':')+1, i) {
+ FOREACH_WORD_QUOTED(w, z, strchr(t, ':')+1, i) {
char *n, *m;
if (!(n = strndup(w, z))) {
diff --git a/src/strv.c b/src/strv.c
index 01464e1..a663696 100644
--- a/src/strv.c
+++ b/src/strv.c
@@ -264,7 +264,7 @@ char **strv_split_quoted(const char *s) {
i = 0;
FOREACH_WORD_QUOTED(w, l, s, state)
- if (!(r[i++] = strndup(w, l))) {
+ if (!(r[i++] = cunescape_length(w, l))) {
strv_free(r);
return NULL;
}
commit 6febfd0d4bdf7519e119149b8d8ec03c210aed1d
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Jul 7 20:58:02 2010 +0200
util: introduce cunescape_length()
diff --git a/src/util.c b/src/util.c
index 58b96ae..5103cc6 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1129,7 +1129,7 @@ char *cescape(const char *s) {
return r;
}
-char *cunescape(const char *s) {
+char *cunescape_length(const char *s, size_t length) {
char *r, *t;
const char *f;
@@ -1137,10 +1137,10 @@ char *cunescape(const char *s) {
/* Undoes C style string escaping */
- if (!(r = new(char, strlen(s)+1)))
+ if (!(r = new(char, length+1)))
return r;
- for (f = s, t = r; *f; f++) {
+ for (f = s, t = r; f < s + length; f++) {
if (*f != '\\') {
*(t++) = *f;
@@ -1242,6 +1242,9 @@ finish:
return r;
}
+char *cunescape(const char *s) {
+ return cunescape_length(s, strlen(s));
+}
char *xescape(const char *s, const char *bad) {
char *r, *t;
diff --git a/src/util.h b/src/util.h
index fed0e67..ff79583 100644
--- a/src/util.h
+++ b/src/util.h
@@ -222,6 +222,12 @@ int undecchar(char c);
char *cescape(const char *s);
char *cunescape(const char *s);
+char *cunescape_length(const char *s, size_t length);
+
+char *xescape(const char *s, const char *bad);
+
+char *bus_path_escape(const char *s);
+char *bus_path_unescape(const char *s);
char *path_kill_slashes(char *path);
@@ -230,11 +236,6 @@ bool path_equal(const char *a, const char *b);
char *ascii_strlower(char *path);
-char *xescape(const char *s, const char *bad);
-
-char *bus_path_escape(const char *s);
-char *bus_path_unescape(const char *s);
-
bool ignore_file(const char *filename);
bool chars_intersect(const char *a, const char *b);
commit 0bab36f250cc79776954fd6066c1e2a33f64c016
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Jul 7 20:57:47 2010 +0200
util: properly handle escaped quotes in words in split_quoted()
diff --git a/src/util.c b/src/util.c
index 78eb728..58b96ae 100644
--- a/src/util.c
+++ b/src/util.c
@@ -360,7 +360,8 @@ char *split(const char *c, size_t *l, const char *separator, char **state) {
/* Split a string into words, but consider strings enclosed in '' and
* "" as words even if they include spaces. */
char *split_quoted(const char *c, size_t *l, char **state) {
- char *current;
+ char *current, *e;
+ bool escaped = false;
current = *state ? *state : (char*) c;
@@ -371,26 +372,45 @@ char *split_quoted(const char *c, size_t *l, char **state) {
if (*current == '\'') {
current ++;
- *l = strcspn(current, "'");
- *state = current+*l;
- if (**state == '\'')
- (*state)++;
+ for (e = current; *e; e++) {
+ if (escaped)
+ escaped = false;
+ else if (*e == '\\')
+ escaped = true;
+ else if (*e == '\'')
+ break;
+ }
+
+ *l = e-current;
+ *state = *e == 0 ? e : e+1;
} else if (*current == '\"') {
current ++;
- *l = strcspn(current, "\"");
- *state = current+*l;
- if (**state == '\"')
- (*state)++;
+ for (e = current; *e; e++) {
+ if (escaped)
+ escaped = false;
+ else if (*e == '\\')
+ escaped = true;
+ else if (*e == '\"')
+ break;
+ }
+
+ *l = e-current;
+ *state = *e == 0 ? e : e+1;
} else {
- *l = strcspn(current, WHITESPACE);
- *state = current+*l;
+ for (e = current; *e; e++) {
+ if (escaped)
+ escaped = false;
+ else if (*e == '\\')
+ escaped = true;
+ else if (strchr(WHITESPACE, *e))
+ break;
+ }
+ *l = e-current;
+ *state = e;
}
- /* FIXME: Cannot deal with strings that have spaces AND ticks
- * in them */
-
return (char*) current;
}
commit f3d4cc01488e4b7acf05da02b487f93ae9744337
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Jul 7 20:57:10 2010 +0200
util: fix handling of unknown escapes in cunescape()
diff --git a/src/util.c b/src/util.c
index 8360eb6..78eb728 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1212,7 +1212,7 @@ char *cunescape(const char *s) {
default:
/* Invalid escape code, let's take it literal then */
*(t++) = '\\';
- *(t++) = 'f';
+ *(t++) = *f;
break;
}
}
commit 3dab29438c431f8e068c079af13ed26a81e563d3
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Jul 7 18:20:42 2010 +0200
conf-parser: support continuation lines with trailing backslashes in lines
diff --git a/src/conf-parser.c b/src/conf-parser.c
index a220453..df3584d 100644
--- a/src/conf-parser.c
+++ b/src/conf-parser.c
@@ -142,6 +142,7 @@ int config_parse(const char *filename, FILE *f, const char* const * sections, co
char *section = NULL;
int r;
bool ours = false;
+ char *continuation = NULL;
assert(filename);
assert(t);
@@ -157,7 +158,8 @@ int config_parse(const char *filename, FILE *f, const char* const * sections, co
}
while (!feof(f)) {
- char l[LINE_MAX];
+ char l[LINE_MAX], *p, *c = NULL, *e;
+ bool escaped = false;
if (!fgets(l, sizeof(l), f)) {
if (feof(f))
@@ -168,7 +170,44 @@ int config_parse(const char *filename, FILE *f, const char* const * sections, co
goto finish;
}
- if ((r = parse_line(filename, ++line, §ion, sections, t, relaxed, l, userdata)) < 0)
+ truncate_nl(l);
+
+ if (continuation) {
+ if (!(c = strappend(continuation, l))) {
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ free(continuation);
+ continuation = NULL;
+ p = c;
+ } else
+ p = l;
+
+ for (e = p; *e; e++) {
+ if (escaped)
+ escaped = false;
+ else if (*e == '\\')
+ escaped = true;
+ }
+
+ if (escaped) {
+ *(e-1) = ' ';
+
+ if (c)
+ continuation = c;
+ else if (!(continuation = strdup(l))) {
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ continue;
+ }
+
+ r = parse_line(filename, ++line, §ion, sections, t, relaxed, p, userdata);
+ free(c);
+
+ if (r < 0)
goto finish;
}
@@ -176,6 +215,7 @@ int config_parse(const char *filename, FILE *f, const char* const * sections, co
finish:
free(section);
+ free(continuation);
if (f && ours)
fclose(f);
More information about the systemd-commits
mailing list