diff options
77 files changed, 671 insertions, 331 deletions
diff --git a/CODING_STYLE b/CODING_STYLE index 8b945cd3c1..0064303203 100644 --- a/CODING_STYLE +++ b/CODING_STYLE @@ -145,11 +145,15 @@ - Think about the types you use. If a value cannot sensibly be negative, do not use "int", but use "unsigned". -- Do not use types like "short". They *never* make sense. Use ints, - longs, long longs, all in unsigned+signed fashion, and the fixed - size types uint32_t and so on, as well as size_t, but nothing - else. Do not use kernel types like u32 and so on, leave that to the - kernel. +- Use "char" only for actual characters. Use "uint8_t" or "int8_t" + when you actually mean a byte-sized signed or unsigned + integers. When referring to a generic byte, we generally prefer the + unsigned variant "uint8_t". Do not use types based on "short". They + *never* make sense. Use ints, longs, long longs, all in + unsigned+signed fashion, and the fixed size types + uint8_t/uint16_t/uint32_t/uint64_t/int8_t/int16_t/int32_t and so on, + as well as size_t, but nothing else. Do not use kernel types like + u32 and so on, leave that to the kernel. - Public API calls (i.e. functions exported by our shared libraries) must be marked "_public_" and need to be prefixed with "sd_". No diff --git a/Makefile.am b/Makefile.am index 51548bb289..cec07fac27 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1506,7 +1506,7 @@ EXTRA_DIST += \ test/c.service \ test/daughter.service \ test/d.service \ - test/end.service.in \ + test/end.service \ test/e.service \ test/f.service \ test/grandchild.service \ @@ -33,6 +33,12 @@ Janitorial Clean-ups: Features: +* add an explicit parser for LimitNICE= and LimitRTPRIO= that verifies + the specified range and generates sane error messages for incorrect + specifications. Also, for LimitNICE= maybe introduce a syntax such + as "+5" or "-7" in order to make the limits more readable as they + are otherwise shifted by 20. + * do something about "/control" subcgroups in the unified cgroup hierarchy * when we detect that there are waiting jobs but no running jobs, do something @@ -912,8 +918,6 @@ External: * dbus: in fedora, make /var/lib/dbus/machine-id a symlink to /etc/machine-id -* add "# export SYSTEMD_PAGER=" to bash login - * /usr/bin/service should actually show the new command line * fedora: suggest auto-restart on failure, but not on success and not on coredump. also, ask people to think about changing the start limit logic. Also point people to RestartPreventExitStatus=, SuccessExitStatus= diff --git a/man/systemd-detect-virt.xml b/man/systemd-detect-virt.xml index 3997e10c43..5d19322cdc 100644 --- a/man/systemd-detect-virt.xml +++ b/man/systemd-detect-virt.xml @@ -22,7 +22,7 @@ --> <refentry id="systemd-detect-virt" - xmlns:xi="http://www.w3.org/2001/XInclude"> + xmlns:xi="http://www.w3.org/2001/XInclude"> <refentryinfo> <title>systemd-detect-virt</title> @@ -81,92 +81,92 @@ <colspec colname="product" /> <thead> <row> - <entry>Type</entry> - <entry>ID</entry> - <entry>Product</entry> + <entry>Type</entry> + <entry>ID</entry> + <entry>Product</entry> </row> </thead> <tbody> <row> - <entry morerows="9">VM</entry> - <entry><varname>qemu</varname></entry> - <entry>QEMU software virtualization</entry> + <entry morerows="9">VM</entry> + <entry><varname>qemu</varname></entry> + <entry>QEMU software virtualization</entry> </row> <row> - <entry><varname>kvm</varname></entry> - <entry>Linux KVM kernel virtual machine</entry> + <entry><varname>kvm</varname></entry> + <entry>Linux KVM kernel virtual machine</entry> </row> <row> - <entry><varname>zvm</varname></entry> - <entry>s390 z/VM</entry> + <entry><varname>zvm</varname></entry> + <entry>s390 z/VM</entry> </row> <row> - <entry><varname>vmware</varname></entry> - <entry>VMware Workstation or Server, and related products</entry> + <entry><varname>vmware</varname></entry> + <entry>VMware Workstation or Server, and related products</entry> </row> <row> - <entry><varname>microsoft</varname></entry> - <entry>Hyper-V, also known as Viridian or Windows Server Virtualization</entry> + <entry><varname>microsoft</varname></entry> + <entry>Hyper-V, also known as Viridian or Windows Server Virtualization</entry> </row> <row> - <entry><varname>oracle</varname></entry> - <entry>Oracle VM VirtualBox (historically marketed by innotek and Sun Microsystems)</entry> + <entry><varname>oracle</varname></entry> + <entry>Oracle VM VirtualBox (historically marketed by innotek and Sun Microsystems)</entry> </row> <row> - <entry><varname>xen</varname></entry> - <entry>Xen hypervisor (only domU, not dom0)</entry> + <entry><varname>xen</varname></entry> + <entry>Xen hypervisor (only domU, not dom0)</entry> </row> <row> - <entry><varname>bochs</varname></entry> - <entry>Bochs Emulator</entry> + <entry><varname>bochs</varname></entry> + <entry>Bochs Emulator</entry> </row> <row> - <entry><varname>uml</varname></entry> - <entry>User-mode Linux</entry> + <entry><varname>uml</varname></entry> + <entry>User-mode Linux</entry> </row> <row> - <entry><varname>parallels</varname></entry> - <entry>Parallels Desktop, Parallels Server</entry> + <entry><varname>parallels</varname></entry> + <entry>Parallels Desktop, Parallels Server</entry> </row> <row> - <entry morerows="5">Container</entry> - <entry><varname>openvz</varname></entry> - <entry>OpenVZ/Virtuozzo</entry> + <entry morerows="5">Container</entry> + <entry><varname>openvz</varname></entry> + <entry>OpenVZ/Virtuozzo</entry> </row> <row> - <entry><varname>lxc</varname></entry> - <entry>Linux container implementation by LXC</entry> + <entry><varname>lxc</varname></entry> + <entry>Linux container implementation by LXC</entry> </row> <row> - <entry><varname>lxc-libvirt</varname></entry> - <entry>Linux container implementation by libvirt</entry> + <entry><varname>lxc-libvirt</varname></entry> + <entry>Linux container implementation by libvirt</entry> </row> <row> - <entry><varname>systemd-nspawn</varname></entry> - <entry>systemd's minimal container implementation, see <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry></entry> + <entry><varname>systemd-nspawn</varname></entry> + <entry>systemd's minimal container implementation, see <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry></entry> </row> <row> - <entry><varname>docker</varname></entry> - <entry>Docker container manager</entry> + <entry><varname>docker</varname></entry> + <entry>Docker container manager</entry> </row> <row> - <entry><varname>rkt</varname></entry> - <entry>rkt app container runtime</entry> + <entry><varname>rkt</varname></entry> + <entry>rkt app container runtime</entry> </row> </tbody> </tgroup> diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 96298f11ed..2b090871ff 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -568,90 +568,133 @@ of various resources for executed processes. See <citerefentry><refentrytitle>setrlimit</refentrytitle><manvolnum>2</manvolnum></citerefentry> for details. Use the string <varname>infinity</varname> to - configure no limit on a specific resource. The multiplicative suffixes - K (=1024), M (=1024*1024) and so on for G, T, P and E may be used for - resource limits measured in bytes (e.g. LimitAS=16G).</para></listitem> + configure no limit on a specific resource. The multiplicative + suffixes K (=1024), M (=1024*1024) and so on for G, T, P and E + may be used for resource limits measured in bytes + (e.g. LimitAS=16G). For the limits referring to time values, + the usual time units ms, s, min, h and so on may be used (see + <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry> + for details). Note that if no time unit is specified for + <varname>LimitCPU=</varname> the default unit of seconds is + implied, while for <varname>LimitRTTIME=</varname> the default + unit of microseconds is implied. Also, note that the effective + granularity of the limits might influence their + enforcement. For example, time limits specified for + <varname>LimitCPU=</varname> will be rounded up implicitly to + multiples of 1s.</para> + + <para>Note that most process resource limits configured with + these options are per-process, and processes may fork in order + to acquire a new set of resources that are accounted + independently of the original process, and may thus escape + limits set. Also note that <varname>LimitRSS=</varname> is not + implemented on Linux, and setting it has no effect. Often it + is advisable to prefer the resource controls listed in + <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry> + over these per-process limits, as they apply to services as a + whole, may be altered dynamically at runtime, and are + generally more expressive. For example, + <varname>MemoryLimit=</varname> is a more powerful (and + working) replacement for <varname>LimitRSS=</varname>.</para> <table> <title>Limit directives and their equivalent with ulimit</title> - <tgroup cols='2'> + <tgroup cols='3'> <colspec colname='directive' /> <colspec colname='equivalent' /> + <colspec colname='unit' /> <thead> <row> <entry>Directive</entry> <entry>ulimit equivalent</entry> + <entry>Unit</entry> </row> </thead> <tbody> <row> - <entry>LimitCPU</entry> + <entry>LimitCPU=</entry> <entry>ulimit -t</entry> + <entry>Seconds</entry> </row> <row> - <entry>LimitFSIZE</entry> + <entry>LimitFSIZE=</entry> <entry>ulimit -f</entry> + <entry>Bytes</entry> </row> <row> - <entry>LimitDATA</entry> + <entry>LimitDATA=</entry> <entry>ulimit -d</entry> + <entry>Bytes</entry> </row> <row> - <entry>LimitSTACK</entry> + <entry>LimitSTACK=</entry> <entry>ulimit -s</entry> + <entry>Bytes</entry> </row> <row> - <entry>LimitCORE</entry> + <entry>LimitCORE=</entry> <entry>ulimit -c</entry> + <entry>Bytes</entry> </row> <row> - <entry>LimitRSS</entry> + <entry>LimitRSS=</entry> <entry>ulimit -m</entry> + <entry>Bytes</entry> </row> <row> - <entry>LimitNOFILE</entry> + <entry>LimitNOFILE=</entry> <entry>ulimit -n</entry> + <entry>Number of File Descriptors</entry> </row> <row> - <entry>LimitAS</entry> + <entry>LimitAS=</entry> <entry>ulimit -v</entry> + <entry>Bytes</entry> </row> <row> - <entry>LimitNPROC</entry> + <entry>LimitNPROC=</entry> <entry>ulimit -u</entry> + <entry>Number of Processes</entry> </row> <row> - <entry>LimitMEMLOCK</entry> + <entry>LimitMEMLOCK=</entry> <entry>ulimit -l</entry> + <entry>Bytes</entry> </row> <row> - <entry>LimitLOCKS</entry> + <entry>LimitLOCKS=</entry> <entry>ulimit -x</entry> + <entry>Number of Locks</entry> </row> <row> - <entry>LimitSIGPENDING</entry> + <entry>LimitSIGPENDING=</entry> <entry>ulimit -i</entry> + <entry>Number of Queued Signals</entry> </row> <row> - <entry>LimitMSGQUEUE</entry> + <entry>LimitMSGQUEUE=</entry> <entry>ulimit -q</entry> + <entry>Bytes</entry> </row> <row> - <entry>LimitNICE</entry> + <entry>LimitNICE=</entry> <entry>ulimit -e</entry> + <entry>Nice Level</entry> </row> <row> - <entry>LimitRTPRIO</entry> + <entry>LimitRTPRIO=</entry> <entry>ulimit -r</entry> + <entry>Realtime Priority</entry> </row> <row> - <entry>LimitRTTIME</entry> + <entry>LimitRTTIME=</entry> <entry>No equivalent</entry> + <entry>Microseconds</entry> </row> </tbody> </tgroup> - </table> + </table></listitem> </varlistentry> <varlistentry> @@ -1320,6 +1363,7 @@ <citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>, + <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>, <citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>, <citerefentry project='man-pages'><refentrytitle>exec</refentrytitle><manvolnum>3</manvolnum></citerefentry> diff --git a/man/systemd.timer.xml b/man/systemd.timer.xml index 20890f2270..c98258a0d7 100644 --- a/man/systemd.timer.xml +++ b/man/systemd.timer.xml @@ -127,7 +127,7 @@ boot-up. The argument may also include time units. Example: "OnBootSec=5h 30min" means 5 hours and 30 minutes after boot-up. For details about the syntax of time spans, see - <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para> + <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para> <para>If a timer configured with <varname>OnBootSec=</varname> or <varname>OnStartupSec=</varname> is already in the past diff --git a/src/basic/calendarspec.c b/src/basic/calendarspec.c index a6a906f453..7151fc3d0c 100644 --- a/src/basic/calendarspec.c +++ b/src/basic/calendarspec.c @@ -562,7 +562,7 @@ static int parse_date(const char **p, CalendarSpec *c) { return -EINVAL; } -static int parse_time(const char **p, CalendarSpec *c) { +static int parse_calendar_time(const char **p, CalendarSpec *c) { CalendarComponent *h = NULL, *m = NULL, *s = NULL; const char *t; int r; @@ -802,7 +802,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) { if (r < 0) goto fail; - r = parse_time(&p, c); + r = parse_calendar_time(&p, c); if (r < 0) goto fail; diff --git a/src/basic/def.h b/src/basic/def.h index 950f693899..0657ac7367 100644 --- a/src/basic/def.h +++ b/src/basic/def.h @@ -76,17 +76,19 @@ #define NOTIFY_FD_MAX 768 #define NOTIFY_BUFFER_MAX PIPE_BUF -/* Return a nulstr for a standard cascade of configuration directories, - * suitable to pass to conf_files_list_nulstr or config_parse_many. */ -#define CONF_DIRS_NULSTR(n) \ - "/etc/" n ".d\0" \ - "/run/" n ".d\0" \ - "/usr/local/lib/" n ".d\0" \ - "/usr/lib/" n ".d\0" \ - CONF_DIR_SPLIT_USR(n) - #ifdef HAVE_SPLIT_USR -#define CONF_DIR_SPLIT_USR(n) "/lib/" n ".d\0" +#define _CONF_PATHS_SPLIT_USR(n) "/lib/" n "\0" #else -#define CONF_DIR_SPLIT_USR(n) +#define _CONF_PATHS_SPLIT_USR(n) #endif + +/* Return a nulstr for a standard cascade of configuration paths, + * suitable to pass to conf_files_list_nulstr() or config_parse_many() + * to implement drop-in directories for extending configuration + * files. */ +#define CONF_PATHS_NULSTR(n) \ + "/etc/" n "\0" \ + "/run/" n "\0" \ + "/usr/local/lib/" n "\0" \ + "/usr/lib/" n "\0" \ + _CONF_PATHS_SPLIT_USR(n) diff --git a/src/basic/extract-word.c b/src/basic/extract-word.c index 6721b85c0a..ff6d211ef4 100644 --- a/src/basic/extract-word.c +++ b/src/basic/extract-word.c @@ -29,54 +29,51 @@ int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags) { _cleanup_free_ char *s = NULL; size_t allocated = 0, sz = 0; + char c; int r; char quote = 0; /* 0 or ' or " */ bool backslash = false; /* whether we've just seen a backslash */ - bool separator = false; /* whether we've just seen a separator */ - bool start = true; /* false means we're looking at a value */ assert(p); assert(ret); - if (!separators) - separators = WHITESPACE; - /* Bail early if called after last value or with no input */ if (!*p) goto finish_force_terminate; + c = **p; + + if (!separators) + separators = WHITESPACE; /* Parses the first word of a string, and returns it in * *ret. Removes all quotes in the process. When parsing fails * (because of an uneven number of quotes or similar), leaves * the pointer *p at the first invalid character. */ - for (;;) { - char c = **p; - - if (start) { - if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) - if (!GREEDY_REALLOC(s, allocated, sz+1)) - return -ENOMEM; + if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) + if (!GREEDY_REALLOC(s, allocated, sz+1)) + return -ENOMEM; - if (c == 0) - goto finish_force_terminate; - else if (strchr(separators, c)) { + for (;; (*p) ++, c = **p) { + if (c == 0) + goto finish_force_terminate; + else if (strchr(separators, c)) { + if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) { (*p) ++; - if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) - goto finish_force_next; - continue; + goto finish_force_next; } - + } else { /* We found a non-blank character, so we will always * want to return a string (even if it is empty), * allocate it here. */ if (!GREEDY_REALLOC(s, allocated, sz+1)) return -ENOMEM; - - start = false; + break; } + } + for (;; (*p) ++, c = **p) { if (backslash) { if (!GREEDY_REALLOC(s, allocated, sz+7)) return -ENOMEM; @@ -107,67 +104,73 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra if (flags & EXTRACT_CUNESCAPE_RELAX) { s[sz++] = '\\'; s[sz++] = c; - goto end_escape; - } - return -EINVAL; + } else + return -EINVAL; + } else { + (*p) += r - 1; + + if (c != 0) + s[sz++] = c; /* normal explicit char */ + else + sz += utf8_encode_unichar(s + sz, u); /* unicode chars we'll encode as utf8 */ } - - (*p) += r - 1; - - if (c != 0) - s[sz++] = c; /* normal explicit char */ - else - sz += utf8_encode_unichar(s + sz, u); /* unicode chars we'll encode as utf8 */ } else s[sz++] = c; -end_escape: backslash = false; } else if (quote) { /* inside either single or double quotes */ - if (c == 0) { - if (flags & EXTRACT_RELAX) - goto finish_force_terminate; - return -EINVAL; - } else if (c == quote) /* found the end quote */ - quote = 0; - else if (c == '\\') - backslash = true; - else { - if (!GREEDY_REALLOC(s, allocated, sz+2)) - return -ENOMEM; - - s[sz++] = c; + for (;; (*p) ++, c = **p) { + if (c == 0) { + if (flags & EXTRACT_RELAX) + goto finish_force_terminate; + return -EINVAL; + } else if (c == quote) { /* found the end quote */ + quote = 0; + break; + } else if (c == '\\') { + backslash = true; + break; + } else { + if (!GREEDY_REALLOC(s, allocated, sz+2)) + return -ENOMEM; + + s[sz++] = c; + } } - } else if (separator) { - if (c == 0) - goto finish_force_terminate; - if (!strchr(separators, c)) - goto finish; - } else { - if (c == 0) - goto finish_force_terminate; - else if ((c == '\'' || c == '"') && (flags & EXTRACT_QUOTES)) - quote = c; - else if (c == '\\') - backslash = true; - else if (strchr(separators, c)) { - if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) { - (*p) ++; - goto finish_force_next; - } - separator = true; - } else { - if (!GREEDY_REALLOC(s, allocated, sz+2)) - return -ENOMEM; + for (;; (*p) ++, c = **p) { + if (c == 0) + goto finish_force_terminate; + else if ((c == '\'' || c == '"') && (flags & EXTRACT_QUOTES)) { + quote = c; + break; + } else if (c == '\\') { + backslash = true; + break; + } else if (strchr(separators, c)) { + if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) { + (*p) ++; + goto finish_force_next; + } + /* Skip additional coalesced separators. */ + for (;; (*p) ++, c = **p) { + if (c == 0) + goto finish_force_terminate; + if (!strchr(separators, c)) + break; + } + goto finish; - s[sz++] = c; + } else { + if (!GREEDY_REALLOC(s, allocated, sz+2)) + return -ENOMEM; + + s[sz++] = c; + } } } - - (*p) ++; } finish_force_terminate: diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c index b6358c459a..151067e916 100644 --- a/src/basic/parse-util.c +++ b/src/basic/parse-util.c @@ -67,11 +67,14 @@ int parse_mode(const char *s, mode_t *ret) { assert(s); assert(ret); + s += strspn(s, WHITESPACE); + if (s[0] == '-') + return -ERANGE; + errno = 0; l = strtol(s, &x, 8); if (errno != 0) return -errno; - if (!x || x == s || *x) return -EINVAL; if (l < 0 || l > 07777) @@ -162,15 +165,15 @@ int parse_size(const char *t, uint64_t base, uint64_t *size) { unsigned i; p += strspn(p, WHITESPACE); - if (*p == '-') - return -ERANGE; errno = 0; l = strtoull(p, &e, 10); - if (errno > 0) + if (errno != 0) return -errno; if (e == p) return -EINVAL; + if (*p == '-') + return -ERANGE; if (*e == '.') { e++; @@ -181,7 +184,7 @@ int parse_size(const char *t, uint64_t base, uint64_t *size) { char *e2; l2 = strtoull(e, &e2, 10); - if (errno > 0) + if (errno != 0) return -errno; /* Ignore failure. E.g. 10.M is valid */ @@ -307,12 +310,24 @@ int safe_atou(const char *s, unsigned *ret_u) { assert(s); assert(ret_u); - errno = 0; - l = strtoul(s, &x, 0); + /* strtoul() is happy to parse negative values, and silently + * converts them to unsigned values without generating an + * error. We want a clean error, hence let's look for the "-" + * prefix on our own, and generate an error. But let's do so + * only after strtoul() validated that the string is clean + * otherwise, so that we return EINVAL preferably over + * ERANGE. */ - if (!x || x == s || *x || errno) - return errno > 0 ? -errno : -EINVAL; + s += strspn(s, WHITESPACE); + errno = 0; + l = strtoul(s, &x, 0); + if (errno != 0) + return -errno; + if (!x || x == s || *x) + return -EINVAL; + if (s[0] == '-') + return -ERANGE; if ((unsigned long) (unsigned) l != l) return -ERANGE; @@ -329,10 +344,10 @@ int safe_atoi(const char *s, int *ret_i) { errno = 0; l = strtol(s, &x, 0); - - if (!x || x == s || *x || errno) - return errno > 0 ? -errno : -EINVAL; - + if (errno != 0) + return -errno; + if (!x || x == s || *x) + return -EINVAL; if ((long) (int) l != l) return -ERANGE; @@ -347,11 +362,16 @@ int safe_atollu(const char *s, long long unsigned *ret_llu) { assert(s); assert(ret_llu); + s += strspn(s, WHITESPACE); + errno = 0; l = strtoull(s, &x, 0); - - if (!x || x == s || *x || errno) - return errno ? -errno : -EINVAL; + if (errno != 0) + return -errno; + if (!x || x == s || *x) + return -EINVAL; + if (*s == '-') + return -ERANGE; *ret_llu = l; return 0; @@ -366,9 +386,10 @@ int safe_atolli(const char *s, long long int *ret_lli) { errno = 0; l = strtoll(s, &x, 0); - - if (!x || x == s || *x || errno) - return errno ? -errno : -EINVAL; + if (errno != 0) + return -errno; + if (!x || x == s || *x) + return -EINVAL; *ret_lli = l; return 0; @@ -381,12 +402,16 @@ int safe_atou8(const char *s, uint8_t *ret) { assert(s); assert(ret); + s += strspn(s, WHITESPACE); + errno = 0; l = strtoul(s, &x, 0); - - if (!x || x == s || *x || errno) - return errno > 0 ? -errno : -EINVAL; - + if (errno != 0) + return -errno; + if (!x || x == s || *x) + return -EINVAL; + if (s[0] == '-') + return -ERANGE; if ((unsigned long) (uint8_t) l != l) return -ERANGE; @@ -401,12 +426,16 @@ int safe_atou16(const char *s, uint16_t *ret) { assert(s); assert(ret); + s += strspn(s, WHITESPACE); + errno = 0; l = strtoul(s, &x, 0); - - if (!x || x == s || *x || errno) - return errno > 0 ? -errno : -EINVAL; - + if (errno != 0) + return -errno; + if (!x || x == s || *x) + return -EINVAL; + if (s[0] == '-') + return -ERANGE; if ((unsigned long) (uint16_t) l != l) return -ERANGE; @@ -423,10 +452,10 @@ int safe_atoi16(const char *s, int16_t *ret) { errno = 0; l = strtol(s, &x, 0); - - if (!x || x == s || *x || errno) - return errno > 0 ? -errno : -EINVAL; - + if (errno != 0) + return -errno; + if (!x || x == s || *x) + return -EINVAL; if ((long) (int16_t) l != l) return -ERANGE; @@ -448,10 +477,13 @@ int safe_atod(const char *s, double *ret_d) { errno = 0; d = strtod_l(s, &x, loc); - - if (!x || x == s || *x || errno) { + if (errno != 0) { freelocale(loc); - return errno ? -errno : -EINVAL; + return -errno; + } + if (!x || x == s || *x) { + freelocale(loc); + return -EINVAL; } freelocale(loc); diff --git a/src/basic/time-util.c b/src/basic/time-util.c index e629d91cb2..b36fbe4f09 100644 --- a/src/basic/time-util.c +++ b/src/basic/time-util.c @@ -705,7 +705,8 @@ finish: return 0; } -int parse_sec(const char *t, usec_t *usec) { +int parse_time(const char *t, usec_t *usec, usec_t default_unit) { + static const struct { const char *suffix; usec_t usec; @@ -737,7 +738,6 @@ int parse_sec(const char *t, usec_t *usec) { { "y", USEC_PER_YEAR }, { "usec", 1ULL }, { "us", 1ULL }, - { "", USEC_PER_SEC }, /* default is sec */ }; const char *p, *s; @@ -746,6 +746,7 @@ int parse_sec(const char *t, usec_t *usec) { assert(t); assert(usec); + assert(default_unit > 0); p = t; @@ -764,6 +765,7 @@ int parse_sec(const char *t, usec_t *usec) { long long l, z = 0; char *e; unsigned i, n = 0; + usec_t multiplier, k; p += strspn(p, WHITESPACE); @@ -806,21 +808,24 @@ int parse_sec(const char *t, usec_t *usec) { for (i = 0; i < ELEMENTSOF(table); i++) if (startswith(e, table[i].suffix)) { - usec_t k = (usec_t) z * table[i].usec; - - for (; n > 0; n--) - k /= 10; - - r += (usec_t) l * table[i].usec + k; + multiplier = table[i].usec; p = e + strlen(table[i].suffix); - - something = true; break; } - if (i >= ELEMENTSOF(table)) - return -EINVAL; + if (i >= ELEMENTSOF(table)) { + multiplier = default_unit; + p = e; + } + + something = true; + + k = (usec_t) z * multiplier; + for (; n > 0; n--) + k /= 10; + + r += (usec_t) l * multiplier + k; } *usec = r; @@ -828,6 +833,10 @@ int parse_sec(const char *t, usec_t *usec) { return 0; } +int parse_sec(const char *t, usec_t *usec) { + return parse_time(t, usec, USEC_PER_SEC); +} + int parse_nsec(const char *t, nsec_t *nsec) { static const struct { const char *suffix; diff --git a/src/basic/time-util.h b/src/basic/time-util.h index 925bf18eb2..0417c29cdd 100644 --- a/src/basic/time-util.h +++ b/src/basic/time-util.h @@ -104,6 +104,7 @@ int dual_timestamp_deserialize(const char *value, dual_timestamp *t); int parse_timestamp(const char *t, usec_t *usec); int parse_sec(const char *t, usec_t *usec); +int parse_time(const char *t, usec_t *usec, usec_t default_unit); int parse_nsec(const char *t, nsec_t *nsec); bool ntp_synced(void); diff --git a/src/basic/virt.c b/src/basic/virt.c index ff006e96c6..d088b7a804 100644 --- a/src/basic/virt.c +++ b/src/basic/virt.c @@ -400,7 +400,7 @@ int detect_container(void) { goto finish; } - r = VIRTUALIZATION_NONE; + r = VIRTUALIZATION_CONTAINER_OTHER; finish: cached_found = r; diff --git a/src/binfmt/binfmt.c b/src/binfmt/binfmt.c index 42ad0adb02..03fb413fe5 100644 --- a/src/binfmt/binfmt.c +++ b/src/binfmt/binfmt.c @@ -37,7 +37,7 @@ #include "strv.h" #include "util.h" -static const char conf_file_dirs[] = CONF_DIRS_NULSTR("binfmt"); +static const char conf_file_dirs[] = CONF_PATHS_NULSTR("binfmt.d"); static int delete_rule(const char *rule) { _cleanup_free_ char *x = NULL, *fn = NULL; diff --git a/src/bootchart/bootchart.c b/src/bootchart/bootchart.c index 852febb225..6a0e1d6b14 100644 --- a/src/bootchart/bootchart.c +++ b/src/bootchart/bootchart.c @@ -95,8 +95,6 @@ static void signal_handler(int sig) { exiting = 1; } -#define BOOTCHART_CONF "/etc/systemd/bootchart.conf" - #define BOOTCHART_MAX (16*1024*1024) static void parse_conf(void) { @@ -117,8 +115,8 @@ static void parse_conf(void) { { NULL, NULL, NULL, 0, NULL } }; - config_parse_many(BOOTCHART_CONF, - CONF_DIRS_NULSTR("systemd/bootchart.conf"), + config_parse_many(PKGSYSCONFDIR "/bootchart.conf", + CONF_PATHS_NULSTR("systemd/bootchart.conf.d"), NULL, config_item_table_lookup, items, true, NULL); if (init != NULL) diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c index 4e9a76a100..22efc58ac9 100644 --- a/src/cgls/cgls.c +++ b/src/cgls/cgls.c @@ -165,8 +165,10 @@ static int get_cgroup_root(char **ret) { } static void show_cg_info(const char *controller, const char *path) { - if (cg_unified() <= 0) + + if (cg_unified() <= 0 && controller && !streq(controller, SYSTEMD_CGROUP_CONTROLLER)) printf("Controller %s; ", controller); + printf("Control group %s:\n", isempty(path) ? "/" : path); fflush(stdout); } @@ -270,6 +272,7 @@ int main(int argc, char *argv[]) { show_cg_info(SYSTEMD_CGROUP_CONTROLLER, root); + printf("-.slice\n"); r = show_cgroup(SYSTEMD_CGROUP_CONTROLLER, root, NULL, 0, arg_kernel_threads, output_flags); } } diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 5b7954dbf9..75388659e3 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -58,7 +58,7 @@ $1.RestrictAddressFamilies, config_parse_address_families, 0, $1.SystemCallArchitectures, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 $1.SystemCallErrorNumber, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 $1.RestrictAddressFamilies, config_parse_warn_compat, DISABLED_CONFIGURATION, 0') -$1.LimitCPU, config_parse_limit, RLIMIT_CPU, offsetof($1, exec_context.rlimit) +$1.LimitCPU, config_parse_sec_limit, RLIMIT_CPU, offsetof($1, exec_context.rlimit) $1.LimitFSIZE, config_parse_bytes_limit, RLIMIT_FSIZE, offsetof($1, exec_context.rlimit) $1.LimitDATA, config_parse_bytes_limit, RLIMIT_DATA, offsetof($1, exec_context.rlimit) $1.LimitSTACK, config_parse_bytes_limit, RLIMIT_STACK, offsetof($1, exec_context.rlimit) @@ -73,7 +73,7 @@ $1.LimitSIGPENDING, config_parse_limit, RLIMIT_SIGP $1.LimitMSGQUEUE, config_parse_bytes_limit, RLIMIT_MSGQUEUE, offsetof($1, exec_context.rlimit) $1.LimitNICE, config_parse_limit, RLIMIT_NICE, offsetof($1, exec_context.rlimit) $1.LimitRTPRIO, config_parse_limit, RLIMIT_RTPRIO, offsetof($1, exec_context.rlimit) -$1.LimitRTTIME, config_parse_limit, RLIMIT_RTTIME, offsetof($1, exec_context.rlimit) +$1.LimitRTTIME, config_parse_usec_limit, RLIMIT_RTTIME, offsetof($1, exec_context.rlimit) $1.ReadWriteDirectories, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.read_write_dirs) $1.ReadOnlyDirectories, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.read_only_dirs) $1.InaccessibleDirectories, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.inaccessible_dirs) diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 7f12f26b08..79cabd26e7 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -111,22 +111,28 @@ int config_parse_unit_deps(const char *unit, UnitDependency d = ltype; Unit *u = userdata; - const char *word, *state; - size_t l; + const char *p; assert(filename); assert(lvalue); assert(rvalue); - FOREACH_WORD_QUOTED(word, l, rvalue, state) { - _cleanup_free_ char *t = NULL, *k = NULL; + p = rvalue; + for(;;) { + _cleanup_free_ char *word = NULL, *k = NULL; int r; - t = strndup(word, l); - if (!t) + r = extract_first_word(&p, &word, NULL, 0); + if (r == 0) + break; + if (r == -ENOMEM) return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); + break; + } - r = unit_name_printf(u, t, &k); + r = unit_name_printf(u, word, &k); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m"); continue; @@ -136,8 +142,6 @@ int config_parse_unit_deps(const char *unit, if (r < 0) log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add dependency on %s, ignoring: %m", k); } - if (!isempty(state)) - log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid syntax, ignoring."); return 0; } @@ -970,23 +974,22 @@ int config_parse_exec_secure_bits(const char *unit, return 0; } -int config_parse_bounding_set(const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_bounding_set( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { uint64_t *capability_bounding_set_drop = data; - uint64_t capability_bounding_set; + uint64_t capability_bounding_set, sum = 0; bool invert = false; - uint64_t sum = 0; - const char *prev; - const char *cur; + const char *p; assert(filename); assert(lvalue); @@ -1003,35 +1006,32 @@ int config_parse_bounding_set(const char *unit, * non-inverted everywhere to have a fully normalized * interface. */ - prev = cur = rvalue; + p = rvalue; for (;;) { _cleanup_free_ char *word = NULL; - int cap; - int r; + int cap, r; - r = extract_first_word(&cur, &word, NULL, EXTRACT_QUOTES); + r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES); if (r == 0) break; if (r == -ENOMEM) return log_oom(); if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Trailing garbage in bounding set, ignoring: %s", prev); + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse word, ignoring: %s", rvalue); break; } cap = capability_from_name(word); if (cap < 0) { log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse capability in bounding set, ignoring: %s", word); - prev = cur; continue; } - sum |= ((uint64_t) 1ULL) << (uint64_t) cap; - prev = cur; + sum |= ((uint64_t) UINT64_C(1)) << (uint64_t) cap; } capability_bounding_set = invert ? ~sum : sum; - if (*capability_bounding_set_drop && capability_bounding_set) + if (*capability_bounding_set_drop != 0 && capability_bounding_set != 0) *capability_bounding_set_drop = ~(~*capability_bounding_set_drop | capability_bounding_set); else *capability_bounding_set_drop = ~capability_bounding_set; @@ -1039,19 +1039,21 @@ int config_parse_bounding_set(const char *unit, return 0; } -int config_parse_limit(const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_limit( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { struct rlimit **rl = data; - unsigned long long u; + rlim_t v; + int r; assert(filename); assert(lvalue); @@ -1061,15 +1063,22 @@ int config_parse_limit(const char *unit, rl += ltype; if (streq(rvalue, "infinity")) - u = (unsigned long long) RLIM_INFINITY; + v = RLIM_INFINITY; else { - int r; + uint64_t u; - r = safe_atollu(rvalue, &u); + /* setrlimit(2) suggests rlim_t is always 64bit on Linux. */ + assert_cc(sizeof(rlim_t) == sizeof(uint64_t)); + + r = safe_atou64(rvalue, &u); + if (r >= 0 && u >= (uint64_t) RLIM_INFINITY) + r = -ERANGE; if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue); return 0; } + + v = (rlim_t) u; } if (!*rl) { @@ -1078,23 +1087,25 @@ int config_parse_limit(const char *unit, return log_oom(); } - (*rl)->rlim_cur = (*rl)->rlim_max = (rlim_t) u; + (*rl)->rlim_cur = (*rl)->rlim_max = v; return 0; } -int config_parse_bytes_limit(const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_bytes_limit( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { struct rlimit **rl = data; - uint64_t bytes; + rlim_t bytes; + int r; assert(filename); assert(lvalue); @@ -1104,15 +1115,120 @@ int config_parse_bytes_limit(const char *unit, rl += ltype; if (streq(rvalue, "infinity")) - bytes = (uint64_t) RLIM_INFINITY; + bytes = RLIM_INFINITY; else { - int r; + uint64_t u; + + r = parse_size(rvalue, 1024, &u); + if (r >= 0 && u >= (uint64_t) RLIM_INFINITY) + r = -ERANGE; + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue); + return 0; + } + + bytes = (rlim_t) u; + } + + if (!*rl) { + *rl = new(struct rlimit, 1); + if (!*rl) + return log_oom(); + } + + (*rl)->rlim_cur = (*rl)->rlim_max = bytes; + return 0; +} + +int config_parse_sec_limit( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { - r = parse_size(rvalue, 1024, &bytes); + struct rlimit **rl = data; + rlim_t seconds; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + rl += ltype; + + if (streq(rvalue, "infinity")) + seconds = RLIM_INFINITY; + else { + usec_t t; + + r = parse_sec(rvalue, &t); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue); return 0; } + + if (t == USEC_INFINITY) + seconds = RLIM_INFINITY; + else + seconds = (rlim_t) (DIV_ROUND_UP(t, USEC_PER_SEC)); + } + + if (!*rl) { + *rl = new(struct rlimit, 1); + if (!*rl) + return log_oom(); + } + + (*rl)->rlim_cur = (*rl)->rlim_max = seconds; + return 0; +} + + +int config_parse_usec_limit( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + struct rlimit **rl = data; + rlim_t useconds; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + rl += ltype; + + if (streq(rvalue, "infinity")) + useconds = RLIM_INFINITY; + else { + usec_t t; + + r = parse_time(rvalue, &t, 1); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue); + return 0; + } + + if (t == USEC_INFINITY) + useconds = RLIM_INFINITY; + else + useconds = (rlim_t) t; } if (!*rl) { @@ -1121,7 +1237,7 @@ int config_parse_bytes_limit(const char *unit, return log_oom(); } - (*rl)->rlim_cur = (*rl)->rlim_max = (rlim_t) bytes; + (*rl)->rlim_cur = (*rl)->rlim_max = useconds; return 0; } diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h index 029775bb46..0cf821289c 100644 --- a/src/core/load-fragment.h +++ b/src/core/load-fragment.h @@ -57,6 +57,8 @@ int config_parse_exec_secure_bits(const char *unit, const char *filename, unsign int config_parse_bounding_set(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_limit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_bytes_limit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_sec_limit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_usec_limit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_sysv_priority(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_kill_signal(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_exec_mount_flags(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); diff --git a/src/core/main.c b/src/core/main.c index 950315e857..a86080642d 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -682,8 +682,14 @@ static int parse_config_file(void) { const char *fn, *conf_dirs_nulstr; - fn = arg_running_as == MANAGER_SYSTEM ? PKGSYSCONFDIR "/system.conf" : PKGSYSCONFDIR "/user.conf"; - conf_dirs_nulstr = arg_running_as == MANAGER_SYSTEM ? CONF_DIRS_NULSTR("systemd/system.conf") : CONF_DIRS_NULSTR("systemd/user.conf"); + fn = arg_running_as == MANAGER_SYSTEM ? + PKGSYSCONFDIR "/system.conf" : + PKGSYSCONFDIR "/user.conf"; + + conf_dirs_nulstr = arg_running_as == MANAGER_SYSTEM ? + CONF_PATHS_NULSTR("systemd/system.conf.d") : + CONF_PATHS_NULSTR("systemd/user.conf.d"); + config_parse_many(fn, conf_dirs_nulstr, "Manager\0", config_item_table_lookup, items, false, NULL); diff --git a/src/core/manager.c b/src/core/manager.c index b13663e702..7c3a020c4a 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -2024,7 +2024,6 @@ int manager_loop(Manager *m) { /* Yay, something is going seriously wrong, pause a little */ log_warning("Looping too fast. Throttling execution a little."); sleep(1); - continue; } if (manager_dispatch_load_queue(m) > 0) diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c index 6eb0ee9d9e..b2f5fbf6b4 100644 --- a/src/journal-remote/journal-remote.c +++ b/src/journal-remote/journal-remote.c @@ -1188,7 +1188,7 @@ static int parse_config(void) { {}}; return config_parse_many(PKGSYSCONFDIR "/journal-remote.conf", - CONF_DIRS_NULSTR("systemd/journal-remote.conf"), + CONF_PATHS_NULSTR("systemd/journal-remote.conf.d"), "Remote\0", config_item_table_lookup, items, false, NULL); } diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c index 42d14dc7c4..6302266ccb 100644 --- a/src/journal-remote/journal-upload.c +++ b/src/journal-remote/journal-upload.c @@ -542,7 +542,7 @@ static int parse_config(void) { {}}; return config_parse_many(PKGSYSCONFDIR "/journal-upload.conf", - CONF_DIRS_NULSTR("systemd/journal-upload.conf"), + CONF_PATHS_NULSTR("systemd/journal-upload.conf.d"), "Upload\0", config_item_table_lookup, items, false, NULL); } diff --git a/src/journal/coredump.c b/src/journal/coredump.c index 4c83e311db..f750ddfcbd 100644 --- a/src/journal/coredump.c +++ b/src/journal/coredump.c @@ -126,8 +126,8 @@ static int parse_config(void) { {} }; - return config_parse_many("/etc/systemd/coredump.conf", - CONF_DIRS_NULSTR("systemd/coredump.conf"), + return config_parse_many(PKGSYSCONFDIR "/coredump.conf", + CONF_PATHS_NULSTR("systemd/coredump.conf.d"), "Coredump\0", config_item_table_lookup, items, false, NULL); diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 7a70dcbc57..36fe739073 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -1296,10 +1296,22 @@ static int setup_signals(Server *s) { if (r < 0) return r; + /* Let's process SIGTERM late, so that we flush all queued + * messages to disk before we exit */ + r = sd_event_source_set_priority(s->sigterm_event_source, SD_EVENT_PRIORITY_NORMAL+20); + if (r < 0) + return r; + + /* When journald is invoked on the terminal (when debugging), + * it's useful if C-c is handled equivalent to SIGTERM. */ r = sd_event_add_signal(s->event, &s->sigint_event_source, SIGINT, dispatch_sigterm, s); if (r < 0) return r; + r = sd_event_source_set_priority(s->sigint_event_source, SD_EVENT_PRIORITY_NORMAL+20); + if (r < 0) + return r; + return 0; } @@ -1360,8 +1372,8 @@ static int server_parse_proc_cmdline(Server *s) { static int server_parse_config_file(Server *s) { assert(s); - return config_parse_many("/etc/systemd/journald.conf", - CONF_DIRS_NULSTR("systemd/journald.conf"), + return config_parse_many(PKGSYSCONFDIR "/journald.conf", + CONF_PATHS_NULSTR("systemd/journald.conf.d"), "Journal\0", config_item_perf_lookup, journald_gperf_lookup, false, s); diff --git a/src/login/logind.c b/src/login/logind.c index 83896ea627..be6bbe5b5c 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -1102,8 +1102,8 @@ static int manager_run(Manager *m) { static int manager_parse_config_file(Manager *m) { assert(m); - return config_parse_many("/etc/systemd/logind.conf", - CONF_DIRS_NULSTR("systemd/logind.conf"), + return config_parse_many(PKGSYSCONFDIR "/logind.conf", + CONF_PATHS_NULSTR("systemd/logind.conf.d"), "Login\0", config_item_perf_lookup, logind_gperf_lookup, false, m); diff --git a/src/modules-load/modules-load.c b/src/modules-load/modules-load.c index 13784763f1..a7fdcb09cf 100644 --- a/src/modules-load/modules-load.c +++ b/src/modules-load/modules-load.c @@ -38,7 +38,7 @@ static char **arg_proc_cmdline_modules = NULL; -static const char conf_file_dirs[] = CONF_DIRS_NULSTR("modules-load"); +static const char conf_file_dirs[] = CONF_PATHS_NULSTR("modules-load.d"); static void systemd_kmod_log(void *data, int priority, const char *file, int line, const char *fn, const char *format, va_list args) { diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c index de1bd26174..9207719551 100644 --- a/src/resolve/resolved-conf.c +++ b/src/resolve/resolved-conf.c @@ -150,8 +150,8 @@ int config_parse_support( int manager_parse_config_file(Manager *m) { assert(m); - return config_parse_many("/etc/systemd/resolved.conf", - CONF_DIRS_NULSTR("systemd/resolved.conf"), + return config_parse_many(PKGSYSCONFDIR "/resolved.conf", + CONF_PATHS_NULSTR("systemd/resolved.conf.d"), "Resolve\0", config_item_perf_lookup, resolved_gperf_lookup, false, m); diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c index 102c5cc992..39b836d053 100644 --- a/src/shared/sleep-config.c +++ b/src/shared/sleep-config.c @@ -54,7 +54,7 @@ int parse_sleep_config(const char *verb, char ***_modes, char ***_states) { }; config_parse_many(PKGSYSCONFDIR "/sleep.conf", - CONF_DIRS_NULSTR("systemd/sleep.conf"), + CONF_PATHS_NULSTR("systemd/sleep.conf.d"), "Sleep\0", config_item_table_lookup, items, false, NULL); diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c index 152c98b348..25b5ff52ea 100644 --- a/src/sysctl/sysctl.c +++ b/src/sysctl/sysctl.c @@ -41,7 +41,7 @@ static char **arg_prefixes = NULL; -static const char conf_file_dirs[] = CONF_DIRS_NULSTR("sysctl"); +static const char conf_file_dirs[] = CONF_PATHS_NULSTR("sysctl.d"); static int apply_all(Hashmap *sysctl_options) { char *property, *value; diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index 008b1bde24..675f94906b 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -72,7 +72,7 @@ typedef struct Item { static char *arg_root = NULL; -static const char conf_file_dirs[] = CONF_DIRS_NULSTR("sysusers"); +static const char conf_file_dirs[] = CONF_PATHS_NULSTR("sysusers.d"); static Hashmap *users = NULL, *groups = NULL; static Hashmap *todo_uids = NULL, *todo_gids = NULL; diff --git a/src/test/test-time.c b/src/test/test-time.c index 3840fff061..820e4aaee2 100644 --- a/src/test/test-time.c +++ b/src/test/test-time.c @@ -57,6 +57,28 @@ static void test_parse_sec(void) { assert_se(parse_sec(".3 infinity", &u) < 0); } +static void test_parse_time(void) { + usec_t u; + + assert_se(parse_time("5", &u, 1) >= 0); + assert_se(u == 5); + + assert_se(parse_time("5", &u, USEC_PER_MSEC) >= 0); + assert_se(u == 5 * USEC_PER_MSEC); + + assert_se(parse_time("5", &u, USEC_PER_SEC) >= 0); + assert_se(u == 5 * USEC_PER_SEC); + + assert_se(parse_time("5s", &u, 1) >= 0); + assert_se(u == 5 * USEC_PER_SEC); + + assert_se(parse_time("5s", &u, USEC_PER_SEC) >= 0); + assert_se(u == 5 * USEC_PER_SEC); + + assert_se(parse_time("5s", &u, USEC_PER_MSEC) >= 0); + assert_se(u == 5 * USEC_PER_SEC); +} + static void test_parse_nsec(void) { nsec_t u; @@ -161,6 +183,7 @@ static void test_get_timezones(void) { int main(int argc, char *argv[]) { test_parse_sec(); + test_parse_time(); test_parse_nsec(); test_format_timespan(1); test_format_timespan(USEC_PER_MSEC); diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c index f9107e0d0d..3648ec9c58 100644 --- a/src/test/test-unit-file.c +++ b/src/test/test-unit-file.c @@ -681,6 +681,66 @@ static void test_config_parse_bounding_set(void) { assert_se(capability_bounding_set_drop == ~(make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN))); } +static void test_config_parse_rlimit(void) { + struct rlimit * rl[_RLIMIT_MAX] = {}; + + assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55", rl, NULL) >= 0); + assert_se(rl[RLIMIT_NOFILE]); + assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55); + assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max); + + assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity", rl, NULL) >= 0); + assert_se(rl[RLIMIT_NOFILE]); + assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY); + assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max); + + rl[RLIMIT_NOFILE] = mfree(rl[RLIMIT_NOFILE]); + + assert_se(config_parse_sec_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "56", rl, NULL) >= 0); + assert_se(rl[RLIMIT_CPU]); + assert_se(rl[RLIMIT_CPU]->rlim_cur == 56); + assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max); + + assert_se(config_parse_sec_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "57s", rl, NULL) >= 0); + assert_se(rl[RLIMIT_CPU]); + assert_se(rl[RLIMIT_CPU]->rlim_cur == 57); + assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max); + + assert_se(config_parse_sec_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "infinity", rl, NULL) >= 0); + assert_se(rl[RLIMIT_CPU]); + assert_se(rl[RLIMIT_CPU]->rlim_cur == RLIM_INFINITY); + assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max); + + assert_se(config_parse_sec_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "1234ms", rl, NULL) >= 0); + assert_se(rl[RLIMIT_CPU]); + assert_se(rl[RLIMIT_CPU]->rlim_cur == 2); + assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max); + + rl[RLIMIT_CPU] = mfree(rl[RLIMIT_CPU]); + + assert_se(config_parse_usec_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58", rl, NULL) >= 0); + assert_se(rl[RLIMIT_RTTIME]); + assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58); + assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max); + + assert_se(config_parse_usec_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s", rl, NULL) >= 0); + assert_se(rl[RLIMIT_RTTIME]); + assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC); + assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max); + + assert_se(config_parse_usec_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity", rl, NULL) >= 0); + assert_se(rl[RLIMIT_RTTIME]); + assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY); + assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max); + + assert_se(config_parse_usec_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "2345ms", rl, NULL) >= 0); + assert_se(rl[RLIMIT_RTTIME]); + assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 2345 * USEC_PER_MSEC); + assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max); + + rl[RLIMIT_RTTIME] = mfree(rl[RLIMIT_RTTIME]); +} + int main(int argc, char *argv[]) { int r; @@ -690,6 +750,7 @@ int main(int argc, char *argv[]) { r = test_unit_file_get_set(); test_config_parse_exec(); test_config_parse_bounding_set(); + test_config_parse_rlimit(); test_load_env_file_1(); test_load_env_file_2(); test_load_env_file_3(); diff --git a/src/timesync/timesyncd-conf.c b/src/timesync/timesyncd-conf.c index 001a0f4d41..5881bc0c45 100644 --- a/src/timesync/timesyncd-conf.c +++ b/src/timesync/timesyncd-conf.c @@ -100,8 +100,8 @@ int config_parse_servers( int manager_parse_config_file(Manager *m) { assert(m); - return config_parse_many("/etc/systemd/timesyncd.conf", - CONF_DIRS_NULSTR("systemd/timesyncd.conf"), + return config_parse_many(PKGSYSCONFDIR "/timesyncd.conf", + CONF_PATHS_NULSTR("systemd/timesyncd.conf.d"), "Time\0", config_item_perf_lookup, timesyncd_gperf_lookup, false, m); diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index ffae91a3ca..64f0c9396c 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -159,7 +159,7 @@ static char **arg_include_prefixes = NULL; static char **arg_exclude_prefixes = NULL; static char *arg_root = NULL; -static const char conf_file_dirs[] = CONF_DIRS_NULSTR("tmpfiles"); +static const char conf_file_dirs[] = CONF_PATHS_NULSTR("tmpfiles.d"); #define MAX_DEPTH 256 diff --git a/test/TEST-01-BASIC/test.sh b/test/TEST-01-BASIC/test.sh index d97fbe24d4..b6b474393d 100755 --- a/test/TEST-01-BASIC/test.sh +++ b/test/TEST-01-BASIC/test.sh @@ -53,7 +53,7 @@ Description=Testsuite service After=multi-user.target [Service] -ExecStart=/bin/bash -c 'set -x; systemctl --failed --no-legend --no-pager > /failed ; echo OK > /testok; while : ;do echo "testsuite service waiting for journal to move to /var/log/journal" > /dev/console ; for i in /var/log/journal/*;do [ -d "\$i" ] && echo "\$i" && break 2; done; sleep 1; done; sleep 1; exit 0;' +ExecStart=/bin/sh -x -c 'systemctl --failed --no-legend --no-pager > /failed ; echo OK > /testok' Type=oneshot EOF diff --git a/test/TEST-02-CRYPTSETUP/test.sh b/test/TEST-02-CRYPTSETUP/test.sh index 4be2365e2f..2997da06ff 100755 --- a/test/TEST-02-CRYPTSETUP/test.sh +++ b/test/TEST-02-CRYPTSETUP/test.sh @@ -59,7 +59,7 @@ Description=Testsuite service After=multi-user.target [Service] -ExecStart=/bin/bash -c 'set -x; systemctl --failed --no-legend --no-pager > /failed ; echo OK > /testok; while : ;do systemd-cat echo "testsuite service waiting for /var/log/journal" ; echo "testsuite service waiting for journal to move to /var/log/journal" > /dev/console ; for i in /var/log/journal/*;do [ -d "\$i" ] && echo "\$i" && break 2; done; sleep 1; done; sleep 1; exit 0;' +ExecStart=/bin/sh -x -c 'systemctl --failed --no-legend --no-pager > /failed ; echo OK > /testok' Type=oneshot EOF diff --git a/test/end.service b/test/end.service new file mode 100644 index 0000000000..6e1996fd02 --- /dev/null +++ b/test/end.service @@ -0,0 +1,10 @@ +[Unit] +Description=End the test +After=testsuite.service +OnFailure=poweroff.target +OnFailureJobMode=replace-irreversibly + +[Service] +Type=oneshot +ExecStart=/bin/sh -x -c 'systemctl poweroff --no-block' +TimeoutStartSec=5m diff --git a/test/end.service.in b/test/end.service.in deleted file mode 100644 index 4857ffe02b..0000000000 --- a/test/end.service.in +++ /dev/null @@ -1,6 +0,0 @@ -[Unit] -Description=End the test -After=testsuite.service - -[Service] -ExecStart=@SYSTEMCTL@ poweroff --no-block diff --git a/test/test-execute/exec-capabilityboundingset-invert.service b/test/test-execute/exec-capabilityboundingset-invert.service index e2b09e1550..fd5d248702 100644 --- a/test/test-execute/exec-capabilityboundingset-invert.service +++ b/test/test-execute/exec-capabilityboundingset-invert.service @@ -2,5 +2,6 @@ Description=Test for CapabilityBoundingSet [Service] -ExecStart=/bin/sh -c 'c=$(capsh --print | grep "Bounding set " | grep "cap_chown"); echo $c; exit $(test -z $c)' +ExecStart=/bin/sh -x -c 'c=$$(capsh --print | grep "^Bounding set .*cap_chown"); test -z "$$c"' +Type=oneshot CapabilityBoundingSet=~CAP_CHOWN diff --git a/test/test-execute/exec-capabilityboundingset-merge.service b/test/test-execute/exec-capabilityboundingset-merge.service index b0f4732529..5c7fcaf437 100644 --- a/test/test-execute/exec-capabilityboundingset-merge.service +++ b/test/test-execute/exec-capabilityboundingset-merge.service @@ -2,6 +2,7 @@ Description=Test for CapabilityBoundingSet [Service] -ExecStart=/bin/sh -c 'c=$(capsh --print | grep "Bounding set " | cut -f 2 -d "="); echo $c; exit $(test $c = "cap_chown,cap_fowner,cap_kill")' +ExecStart=/bin/sh -x -c 'c=$$(capsh --print | grep "Bounding set "); test "$$c" = "Bounding set =cap_chown,cap_fowner,cap_kill"' +Type=oneshot CapabilityBoundingSet=CAP_FOWNER CapabilityBoundingSet=CAP_KILL CAP_CHOWN diff --git a/test/test-execute/exec-capabilityboundingset-reset.service b/test/test-execute/exec-capabilityboundingset-reset.service index 51092ab0d5..d7d3320204 100644 --- a/test/test-execute/exec-capabilityboundingset-reset.service +++ b/test/test-execute/exec-capabilityboundingset-reset.service @@ -2,6 +2,7 @@ Description=Test for CapabilityBoundingSet [Service] -ExecStart=/bin/sh -c 'c=$(capsh --print | grep "Bounding set " | cut -f 2 -d "="); echo $c; exit $(test -z $c)' +ExecStart=/bin/sh -x -c 'c=$$(capsh --print | grep "Bounding set "); test "$$c" = "Bounding set ="' +Type=oneshot CapabilityBoundingSet=CAP_FOWNER CAP_KILL CapabilityBoundingSet= diff --git a/test/test-execute/exec-capabilityboundingset-simple.service b/test/test-execute/exec-capabilityboundingset-simple.service index b9037a0ddf..bf1a7f575a 100644 --- a/test/test-execute/exec-capabilityboundingset-simple.service +++ b/test/test-execute/exec-capabilityboundingset-simple.service @@ -2,5 +2,6 @@ Description=Test for CapabilityBoundingSet [Service] -ExecStart=/bin/sh -c 'c=$(capsh --print | grep "Bounding set " | cut -f 2 -d "="); echo $c; exit $(test $c = "cap_fowner,cap_kill")' +ExecStart=/bin/sh -x -c 'c=$$(capsh --print | grep "Bounding set "); test "$$c" = "Bounding set =cap_fowner,cap_kill"' +Type=oneshot CapabilityBoundingSet=CAP_FOWNER CAP_KILL diff --git a/test/test-execute/exec-environment-empty.service b/test/test-execute/exec-environment-empty.service index 0219ca4fd7..9c92d4bc81 100644 --- a/test/test-execute/exec-environment-empty.service +++ b/test/test-execute/exec-environment-empty.service @@ -2,6 +2,7 @@ Description=Test for Environment [Service] -ExecStart=/bin/sh -c 'exit $(test ! "$VAR1" = "word1 word2") && $(test ! "$VAR2" = word3) && $(test ! "$VAR3" = \'$word 5 6\')' +ExecStart=/bin/sh -x -c 'test "$${VAR1-unset}" = "unset" && test "$${VAR2-unset}" = "unset" && test "$${VAR3-unset}" = "unset"' +Type=oneshot Environment="VAR1=word1 word2" VAR2=word3 "VAR3=$word 5 6" Environment= diff --git a/test/test-execute/exec-environment-multiple.service b/test/test-execute/exec-environment-multiple.service index 479005a5d8..b9bc225635 100644 --- a/test/test-execute/exec-environment-multiple.service +++ b/test/test-execute/exec-environment-multiple.service @@ -2,6 +2,7 @@ Description=Test for Environment [Service] -ExecStart=/bin/sh -c 'exit $(test "$VAR1" = "word1 word2") && $(test "$VAR2" = word3) && $(test "$VAR3" = foobar)' +ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = foobar' +Type=oneshot Environment="VAR1=word1 word2" VAR2=word3 "VAR3=$word 5 6" Environment="VAR3=foobar" diff --git a/test/test-execute/exec-environment.service b/test/test-execute/exec-environment.service index 4586b4c4a9..06e77af220 100644 --- a/test/test-execute/exec-environment.service +++ b/test/test-execute/exec-environment.service @@ -2,5 +2,6 @@ Description=Test for Environment [Service] -ExecStart=/bin/sh -c 'exit $(test "$VAR1" = "word1 word2") && $(test "$VAR2" = word3) && $(test "$VAR3" = \'$word 5 6\')' +ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6"' +Type=oneshot Environment="VAR1=word1 word2" VAR2=word3 "VAR3=$word 5 6" diff --git a/test/test-execute/exec-environmentfile.service b/test/test-execute/exec-environmentfile.service index 848f2a120c..f6b8462719 100644 --- a/test/test-execute/exec-environmentfile.service +++ b/test/test-execute/exec-environmentfile.service @@ -2,6 +2,6 @@ Description=Test for EnvironmentFile [Service] -ExecStart=/bin/sh -c 'exit $(test "$VAR1" = "word1 word2") && $(test "$VAR2" = word3) && $(test "$VAR3" = \'$word 5 6\')' +ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6"' Type=oneshot EnvironmentFile=/tmp/test-exec_environmentfile.conf diff --git a/test/test-execute/exec-group.service b/test/test-execute/exec-group.service index 1aa04b5bd2..be7c796912 100644 --- a/test/test-execute/exec-group.service +++ b/test/test-execute/exec-group.service @@ -2,5 +2,6 @@ Description=Test for Group [Service] -ExecStart=/bin/sh -c 'exit $(test $(id -n -g) = nobody)' +ExecStart=/bin/sh -x -c 'test "$$(id -n -g)" = "nobody"' +Type=oneshot Group=nobody diff --git a/test/test-execute/exec-ignoresigpipe-no.service b/test/test-execute/exec-ignoresigpipe-no.service index 69b2e9d8a8..73addf5f05 100644 --- a/test/test-execute/exec-ignoresigpipe-no.service +++ b/test/test-execute/exec-ignoresigpipe-no.service @@ -2,6 +2,6 @@ Description=Test for IgnoreSIGPIPE=no [Service] -ExecStart=/bin/sh -c 'kill -PIPE 0' +ExecStart=/bin/sh -x -c 'kill -PIPE 0' Type=oneshot IgnoreSIGPIPE=no diff --git a/test/test-execute/exec-ignoresigpipe-yes.service b/test/test-execute/exec-ignoresigpipe-yes.service index 877ec8aed0..f81c01719e 100644 --- a/test/test-execute/exec-ignoresigpipe-yes.service +++ b/test/test-execute/exec-ignoresigpipe-yes.service @@ -2,6 +2,6 @@ Description=Test for IgnoreSIGPIPE=yes [Service] -ExecStart=/bin/sh -c 'kill -PIPE 0' +ExecStart=/bin/sh -x -c 'kill -PIPE 0' Type=oneshot IgnoreSIGPIPE=yes diff --git a/test/test-execute/exec-ioschedulingclass-best-effort.service b/test/test-execute/exec-ioschedulingclass-best-effort.service index 56e2718505..29bb8510b4 100644 --- a/test/test-execute/exec-ioschedulingclass-best-effort.service +++ b/test/test-execute/exec-ioschedulingclass-best-effort.service @@ -2,6 +2,6 @@ Description=Test for IOSchedulingClass=best-effort [Service] -ExecStart=/bin/bash -c 'c=$(ionice); echo $c; [[ "$c" == best-effort* ]]' +ExecStart=/bin/sh -x -c 'c=$$(LC_ALL=C ionice); test "$${c%%:*}" = "best-effort"' Type=oneshot IOSchedulingClass=best-effort diff --git a/test/test-execute/exec-ioschedulingclass-idle.service b/test/test-execute/exec-ioschedulingclass-idle.service index b45795cab7..87dbed14c1 100644 --- a/test/test-execute/exec-ioschedulingclass-idle.service +++ b/test/test-execute/exec-ioschedulingclass-idle.service @@ -2,6 +2,6 @@ Description=Test for IOSchedulingClass=idle [Service] -ExecStart=/bin/bash -c 'c=$(ionice); echo $c; [[ "$c" == idle* ]]' +ExecStart=/bin/sh -x -c 'c=$$(LC_ALL=C ionice); test "$${c%%:*}" = "idle"' Type=oneshot IOSchedulingClass=idle diff --git a/test/test-execute/exec-ioschedulingclass-none.service b/test/test-execute/exec-ioschedulingclass-none.service index 36b546ca01..b6af122a1e 100644 --- a/test/test-execute/exec-ioschedulingclass-none.service +++ b/test/test-execute/exec-ioschedulingclass-none.service @@ -2,6 +2,6 @@ Description=Test for IOSchedulingClass=none [Service] -ExecStart=/bin/bash -c 'c=$(ionice); echo $c; [[ "$c" == none* ]]' +ExecStart=/bin/sh -x -c 'c=$$(LC_ALL=C ionice); test "$${c%%:*}" = "none"' Type=oneshot IOSchedulingClass=none diff --git a/test/test-execute/exec-ioschedulingclass-realtime.service b/test/test-execute/exec-ioschedulingclass-realtime.service index 74936d8079..d920d5c687 100644 --- a/test/test-execute/exec-ioschedulingclass-realtime.service +++ b/test/test-execute/exec-ioschedulingclass-realtime.service @@ -2,6 +2,6 @@ Description=Test for IOSchedulingClass=realtime [Service] -ExecStart=/bin/bash -c 'c=$(ionice); echo $c; [[ "$c" == realtime* ]]' +ExecStart=/bin/sh -x -c 'c=$$(LC_ALL=C ionice); test "$${c%%:*}" = "realtime"' Type=oneshot IOSchedulingClass=realtime diff --git a/test/test-execute/exec-oomscoreadjust-negative.service b/test/test-execute/exec-oomscoreadjust-negative.service index 63ab501c63..2234c53c3f 100644 --- a/test/test-execute/exec-oomscoreadjust-negative.service +++ b/test/test-execute/exec-oomscoreadjust-negative.service @@ -2,6 +2,6 @@ Description=Test for OOMScoreAdjust [Service] -ExecStart=/bin/bash -c 'c=$(cat /proc/self/oom_score_adj); echo $c; exit $(test $c -eq -100)' -OOMScoreAdjust=-100 +ExecStart=/bin/sh -x -c 'c=$$(cat /proc/self/oom_score_adj); test "$$c" -eq -100' Type=oneshot +OOMScoreAdjust=-100 diff --git a/test/test-execute/exec-oomscoreadjust-positive.service b/test/test-execute/exec-oomscoreadjust-positive.service index e47a4f1392..456a8f80cf 100644 --- a/test/test-execute/exec-oomscoreadjust-positive.service +++ b/test/test-execute/exec-oomscoreadjust-positive.service @@ -2,6 +2,6 @@ Description=Test for OOMScoreAdjust [Service] -ExecStart=/bin/bash -c 'c=$(cat /proc/self/oom_score_adj); echo $c; exit $(test $c -eq 100)' -OOMScoreAdjust=100 +ExecStart=/bin/sh -x -c 'c=$$(cat /proc/self/oom_score_adj); test "$$c" -eq 100' Type=oneshot +OOMScoreAdjust=100 diff --git a/test/test-execute/exec-personality-s390.service b/test/test-execute/exec-personality-s390.service index f3c3b03e3d..89f7de89d0 100644 --- a/test/test-execute/exec-personality-s390.service +++ b/test/test-execute/exec-personality-s390.service @@ -2,6 +2,6 @@ Description=Test for Personality=s390 [Service] -ExecStart=/bin/sh -c 'echo $(uname -m); exit $(test $(uname -m) = "s390")' +ExecStart=/bin/sh -x -c 'c=$$(uname -m); test "$$c" = "s390"' Type=oneshot Personality=s390 diff --git a/test/test-execute/exec-personality-x86-64.service b/test/test-execute/exec-personality-x86-64.service index 5bb5d910d0..433e69a6d1 100644 --- a/test/test-execute/exec-personality-x86-64.service +++ b/test/test-execute/exec-personality-x86-64.service @@ -2,6 +2,6 @@ Description=Test for Personality=x86-64 [Service] -ExecStart=/bin/sh -c 'echo $(uname -m); exit $(test $(uname -m) = "x86_64")' +ExecStart=/bin/sh -x -c 'c=$$(uname -m); test "$$c" = "x86_64"' Type=oneshot Personality=x86-64 diff --git a/test/test-execute/exec-personality-x86.service b/test/test-execute/exec-personality-x86.service index 0b370a6480..a623a08cbe 100644 --- a/test/test-execute/exec-personality-x86.service +++ b/test/test-execute/exec-personality-x86.service @@ -2,6 +2,6 @@ Description=Test for Personality=x86 [Service] -ExecStart=/bin/sh -c 'echo $(uname -m); exit $(test $(uname -m) = "i686")' +ExecStart=/bin/sh -x -c 'c=$$(uname -m); test "$$c" = "i686"' Type=oneshot Personality=x86 diff --git a/test/test-execute/exec-privatedevices-no.service b/test/test-execute/exec-privatedevices-no.service index cf4f275fb6..77aeb951b5 100644 --- a/test/test-execute/exec-privatedevices-no.service +++ b/test/test-execute/exec-privatedevices-no.service @@ -2,6 +2,6 @@ Description=Test for PrivateDev=no [Service] -ExecStart=/bin/sh -c 'exit $(test -c /dev/mem)' +ExecStart=/bin/sh -x -c 'test -c /dev/mem' Type=oneshot PrivateDevices=no diff --git a/test/test-execute/exec-privatedevices-yes.service b/test/test-execute/exec-privatedevices-yes.service index 85b3f4f981..ab958b646e 100644 --- a/test/test-execute/exec-privatedevices-yes.service +++ b/test/test-execute/exec-privatedevices-yes.service @@ -2,6 +2,6 @@ Description=Test for PrivateDev=yes [Service] -ExecStart=/bin/sh -c 'exit $(test ! -c /dev/mem)' +ExecStart=/bin/sh -c 'test ! -c /dev/mem' Type=oneshot PrivateDevices=yes diff --git a/test/test-execute/exec-privatenetwork-yes.service b/test/test-execute/exec-privatenetwork-yes.service index 494712e6a7..3df543ec93 100644 --- a/test/test-execute/exec-privatenetwork-yes.service +++ b/test/test-execute/exec-privatenetwork-yes.service @@ -2,5 +2,6 @@ Description=Test for PrivateNetwork [Service] -ExecStart=/bin/sh -c 'i=$(ip link | grep ": " | grep -v lo); echo $i; exit $(test -z $i)' +ExecStart=/bin/sh -x -c 'i=$$(ip link | grep ": " | grep -v ": lo:"); test -z "$$i"' +Type=oneshot PrivateNetwork=yes diff --git a/test/test-execute/exec-privatetmp-no.service b/test/test-execute/exec-privatetmp-no.service index d69e552a63..59f60f4755 100644 --- a/test/test-execute/exec-privatetmp-no.service +++ b/test/test-execute/exec-privatetmp-no.service @@ -2,6 +2,6 @@ Description=Test for PrivateTmp=no [Service] -ExecStart=/bin/sh -c 'exit $(test -f /tmp/test-exec_privatetmp)' +ExecStart=/bin/sh -x -c 'test -f /tmp/test-exec_privatetmp' Type=oneshot PrivateTmp=no diff --git a/test/test-execute/exec-privatetmp-yes.service b/test/test-execute/exec-privatetmp-yes.service index 881a040b87..907c291b81 100644 --- a/test/test-execute/exec-privatetmp-yes.service +++ b/test/test-execute/exec-privatetmp-yes.service @@ -2,6 +2,6 @@ Description=Test for PrivateTmp=yes [Service] -ExecStart=/bin/sh -c 'exit $(test ! -f /tmp/test-exec_privatetmp)' +ExecStart=/bin/sh -x -c 'test ! -f /tmp/test-exec_privatetmp' Type=oneshot PrivateTmp=yes diff --git a/test/test-execute/exec-runtimedirectory-mode.service b/test/test-execute/exec-runtimedirectory-mode.service index ba6d7ee39f..842721d5c2 100644 --- a/test/test-execute/exec-runtimedirectory-mode.service +++ b/test/test-execute/exec-runtimedirectory-mode.service @@ -2,7 +2,7 @@ Description=Test for RuntimeDirectoryMode [Service] -ExecStart=/bin/sh -c 's=$(stat -c %a /tmp/test-exec_runtimedirectory-mode); echo $s; exit $(test $s = "750")' +ExecStart=/bin/sh -x -c 'mode=$$(stat -c %%a /tmp/test-exec_runtimedirectory-mode); test "$$mode" = "750"' Type=oneshot RuntimeDirectory=test-exec_runtimedirectory-mode RuntimeDirectoryMode=0750 diff --git a/test/test-execute/exec-runtimedirectory-owner.service b/test/test-execute/exec-runtimedirectory-owner.service index 077e08d1c5..1f438c182e 100644 --- a/test/test-execute/exec-runtimedirectory-owner.service +++ b/test/test-execute/exec-runtimedirectory-owner.service @@ -2,7 +2,7 @@ Description=Test for RuntimeDirectory owner (must not be the default group of the user if Group is set) [Service] -ExecStart=/bin/sh -c 'f=/tmp/test-exec_runtimedirectory-owner;g=$(stat -c %G $f); echo "$g"; exit $(test $g = "nobody")' +ExecStart=/bin/sh -x -c 'group=$$(stat -c %%G /tmp/test-exec_runtimedirectory-owner); test "$$group" = "nobody"' Type=oneshot Group=nobody User=root diff --git a/test/test-execute/exec-runtimedirectory.service b/test/test-execute/exec-runtimedirectory.service index c12a6c63d6..ec46c9d49b 100644 --- a/test/test-execute/exec-runtimedirectory.service +++ b/test/test-execute/exec-runtimedirectory.service @@ -2,6 +2,6 @@ Description=Test for RuntimeDirectory [Service] -ExecStart=/bin/sh -c 'exit $(test -d /tmp/test-exec_runtimedirectory)' +ExecStart=/bin/sh -x -c 'test -d /tmp/test-exec_runtimedirectory' Type=oneshot RuntimeDirectory=test-exec_runtimedirectory diff --git a/test/test-execute/exec-systemcallerrornumber.service b/test/test-execute/exec-systemcallerrornumber.service index b11a952bd6..ff7da3c1a4 100644 --- a/test/test-execute/exec-systemcallerrornumber.service +++ b/test/test-execute/exec-systemcallerrornumber.service @@ -2,6 +2,7 @@ Description=Test for SystemCallErrorNumber [Service] -ExecStart=/bin/sh -c 'uname -a' +ExecStart=/bin/sh -x -c 'uname -a' +Type=oneshot SystemCallFilter=~uname SystemCallErrorNumber=EACCES diff --git a/test/test-execute/exec-systemcallfilter-failing.service b/test/test-execute/exec-systemcallfilter-failing.service index c6ce9368c9..5c6422f0fd 100644 --- a/test/test-execute/exec-systemcallfilter-failing.service +++ b/test/test-execute/exec-systemcallfilter-failing.service @@ -3,6 +3,7 @@ Description=Test for SystemCallFilter [Service] ExecStart=/bin/echo "This should not be seen" +Type=oneshot SystemCallFilter=ioperm SystemCallFilter=~ioperm SystemCallFilter=ioperm diff --git a/test/test-execute/exec-systemcallfilter-failing2.service b/test/test-execute/exec-systemcallfilter-failing2.service index b7f7c2aff9..3516078e1f 100644 --- a/test/test-execute/exec-systemcallfilter-failing2.service +++ b/test/test-execute/exec-systemcallfilter-failing2.service @@ -3,4 +3,5 @@ Description=Test for SystemCallFilter [Service] ExecStart=/bin/echo "This should not be seen" +Type=oneshot SystemCallFilter=~write open execve exit_group close mmap munmap fstat DONOTEXIST diff --git a/test/test-execute/exec-systemcallfilter-not-failing.service b/test/test-execute/exec-systemcallfilter-not-failing.service index feb206ab6d..c794b67edd 100644 --- a/test/test-execute/exec-systemcallfilter-not-failing.service +++ b/test/test-execute/exec-systemcallfilter-not-failing.service @@ -3,6 +3,7 @@ Description=Test for SystemCallFilter [Service] ExecStart=/bin/echo "Foo bar" +Type=oneshot SystemCallFilter=~read write open execve ioperm SystemCallFilter=ioctl SystemCallFilter=read write open execve diff --git a/test/test-execute/exec-systemcallfilter-not-failing2.service b/test/test-execute/exec-systemcallfilter-not-failing2.service index cca469aa3d..a62c81bd48 100644 --- a/test/test-execute/exec-systemcallfilter-not-failing2.service +++ b/test/test-execute/exec-systemcallfilter-not-failing2.service @@ -3,4 +3,5 @@ Description=Test for SystemCallFilter [Service] ExecStart=/bin/echo "Foo bar" +Type=oneshot SystemCallFilter= diff --git a/test/test-execute/exec-umask-0177.service b/test/test-execute/exec-umask-0177.service index af9295888e..a5e8fc4dbc 100644 --- a/test/test-execute/exec-umask-0177.service +++ b/test/test-execute/exec-umask-0177.service @@ -2,6 +2,7 @@ Description=Test for UMask [Service] -ExecStart=/bin/sh -c 'touch /tmp/test-exec-umask; s=$(stat -c %a /tmp/test-exec-umask); echo $s; exit $(test $s = "600")' +ExecStart=/bin/sh -x -c 'touch /tmp/test-exec-umask; mode=$$(stat -c %%a /tmp/test-exec-umask); test "$$mode" = "600"' +Type=oneshot UMask=0177 PrivateTmp=yes diff --git a/test/test-execute/exec-umask-default.service b/test/test-execute/exec-umask-default.service index 41e20a60a1..487f5e9b94 100644 --- a/test/test-execute/exec-umask-default.service +++ b/test/test-execute/exec-umask-default.service @@ -2,5 +2,6 @@ Description=Test for UMask default [Service] -ExecStart=/bin/sh -c 'touch /tmp/test-exec-umask; s=$(stat -c %a /tmp/test-exec-umask); echo $s; exit $(test $s = "644")' +ExecStart=/bin/sh -x -c 'touch /tmp/test-exec-umask; mode=$$(stat -c %%a /tmp/test-exec-umask); test "$$mode" = "644"' +Type=oneshot PrivateTmp=yes diff --git a/test/test-execute/exec-user.service b/test/test-execute/exec-user.service index 2ca08ebb42..0a00c1abc4 100644 --- a/test/test-execute/exec-user.service +++ b/test/test-execute/exec-user.service @@ -2,5 +2,6 @@ Description=Test for User [Service] -ExecStart=/bin/sh -c 'exit $(test "$USER" = nobody)' +ExecStart=/bin/sh -x -c 'test "$$USER" = "nobody"' +Type=oneshot User=nobody diff --git a/test/test-execute/exec-workingdirectory.service b/test/test-execute/exec-workingdirectory.service index 10855d682a..fe3c420d2d 100644 --- a/test/test-execute/exec-workingdirectory.service +++ b/test/test-execute/exec-workingdirectory.service @@ -2,6 +2,6 @@ Description=Test for WorkingDirectory [Service] -ExecStart=/bin/sh -c 'echo $PWD; exit $(test $PWD = "/tmp/test-exec_workingdirectory")' +ExecStart=/bin/sh -x -c 'test "$$PWD" = "/tmp/test-exec_workingdirectory"' Type=oneshot WorkingDirectory=/tmp/test-exec_workingdirectory diff --git a/test/test-functions b/test/test-functions index ab77576573..2f5ec9b93f 100644 --- a/test/test-functions +++ b/test/test-functions @@ -305,7 +305,7 @@ install_terminfo() { setup_testsuite() { cp $TEST_BASE_DIR/testsuite.target $initdir/etc/systemd/system/ - sed "s#@SYSTEMCTL@#$(type -P systemctl)#g" $TEST_BASE_DIR/end.service.in > $initdir/etc/systemd/system/end.service + cp $TEST_BASE_DIR/end.service $initdir/etc/systemd/system/ mkdir -p $initdir/etc/systemd/system/testsuite.target.wants ln -fs $TEST_BASE_DIR/testsuite.service $initdir/etc/systemd/system/testsuite.target.wants/testsuite.service |