diff options
-rw-r--r-- | NEWS | 9 | ||||
-rw-r--r-- | doc/envfile.html | 40 | ||||
-rw-r--r-- | doc/index.html | 2 | ||||
-rw-r--r-- | doc/upgrade.html | 10 | ||||
-rw-r--r-- | package/info | 2 | ||||
-rw-r--r-- | src/execline/envfile.c | 94 | ||||
-rw-r--r-- | src/execline/envfile.txt | 60 |
7 files changed, 186 insertions, 31 deletions
@@ -1,5 +1,14 @@ Changelog for execline. +In 2.6.1.0 +---------- + + - The envfile format has changed; it is now more expressive and +largely compatible with systemd's EnvironmentFile format. The +new format is a superset of the old one, so old envfiles should +still be understood by the new binary. + + In 2.6.0.2 ---------- diff --git a/doc/envfile.html b/doc/envfile.html index 5c0523c..713b6ae 100644 --- a/doc/envfile.html +++ b/doc/envfile.html @@ -55,19 +55,32 @@ it execs into <em>prog</em>. <p> <em>file</em> is a text file containing lines of the form <tt>key = value</tt>. -Whitespace is permitted before and after <em>key</em>, and before or after <em>value</em>, -but <em>key</em> or <em>value</em> can never contain whitespace. No quoting -is possible. +Whitespace is permitted before and after <em>key</em>, and before or after <em>value</em>. </p> <p> Empty lines, or lines containing only whitespace, are ignored. Lines beginning with <tt>#</tt> (possibly after some whitespace) are ignored (and typically used for comments). -Comments are also possible at the end of lines: -<tt>key = value # comment</tt> is a valid line. Note that there -<em>must</em> be whitespace between <em>value</em> and <tt>#</tt> -in this case (else <tt>#</tt> is just read as a part of <em>value</em>). +Leading and trailing whitespace is stripped from values; but a +value can be double-quoted, which allows for inclusion of leading +and trailing whitespace. +</p> + +<p> + A non-commented line that ends with a backslash ("<tt>\</tt>") is +concatenated with the following one, and the newline character is +ignored. If a backslashed newline happens before the start of a +value, then the whitespace at the beginning of the new line will be +part of the value (i.e. leading whitespace on a new line is not +stripped). +</p> + +<p> + C escapes, including hexadecimal and octal sequences, are supported +in quoted values. Unicode codepoint sequences are not supported. It +is possible to include a newline in a quoted value by using <tt>\n</tt>; +but including newlines in environment variables is not recommended. </p> <p> @@ -78,16 +91,21 @@ added to the environment, with an empty value. If you do not want the environment. </p> +<p> + The envfile format is largely compatible with systemd's +<a href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#EnvironmentFile=">EnvironmentFile</a> +format, which allows for the reuse of such files outside of systemd. +</p> + <h2> Notes </h2> <ul> <li> If <em>file</em> is <tt>-</tt> then <tt>envfile</tt> reads and parses its standard input instead. To read a file literally named <tt>-</tt>, you can use <tt>./-</tt> for instance. </li> - <li> The variables and values that can be defined with <tt>envfile</tt> -are purposefully restricted in order to keep the parsing extremely simple. -If you need fancy values, for instance values that contain whitespace or -a newline, you should use an envdir instead: see + <li> The variables that can be defined with <tt>envfile</tt> +are purposefully restricted. If you need more expressive power for your +variable names, or for your values, you should use an envdir instead: see <a href="//skarnet.org/software/s6/s6-envdir.html">s6-envdir</a>. </li> </ul> diff --git a/doc/index.html b/doc/index.html index 0b41cea..0437fd5 100644 --- a/doc/index.html +++ b/doc/index.html @@ -66,7 +66,7 @@ library. </li> <h3> Download </h3> <ul> - <li> The current released version of execline is <a href="execline-2.6.0.2.tar.gz">2.6.0.2</a>. </li> + <li> The current released version of execline is <a href="execline-2.6.1.0.tar.gz">2.6.1.0</a>. </li> <li> Alternatively, you can checkout a copy of the <a href="//git.skarnet.org/cgi-bin/cgit.cgi/execline/">execline git repository</a>: diff --git a/doc/upgrade.html b/doc/upgrade.html index e1ae3a3..3038dcf 100644 --- a/doc/upgrade.html +++ b/doc/upgrade.html @@ -18,6 +18,16 @@ <h1> What has changed in execline </h1> +<h2> in 2.6.1.0 </h2> + +<ul> + <li> The <a href="envfile.html">envfile</a> format has changed. +It is now more expressive and largely compatible with systemd's +<a href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#EnvironmentFile=">EnvironmentFile</a> +format. The new format is a superset of the old one, so old +envfiles should still be understood by the new binary. </li> +</ul> + <h2> in 2.6.0.2 </h2> <ul> diff --git a/package/info b/package/info index 22fb0b7..dcded8e 100644 --- a/package/info +++ b/package/info @@ -1,4 +1,4 @@ package=execline -version=2.6.0.2 +version=2.6.1.0 category=admin package_macro_name=EXECLINE diff --git a/src/execline/envfile.c b/src/execline/envfile.c index 638b182..18a175b 100644 --- a/src/execline/envfile.c +++ b/src/execline/envfile.c @@ -3,9 +3,11 @@ #include <stdint.h> #include <string.h> +#include <skalibs/bytestr.h> #include <skalibs/types.h> #include <skalibs/buffer.h> #include <skalibs/strerr2.h> +#include <skalibs/fmtscan.h> #include <skalibs/env.h> #include <skalibs/stralloc.h> #include <skalibs/djbunix.h> @@ -14,6 +16,15 @@ #define dieusage() strerr_dieusage(100, USAGE) #define dienomem() strerr_diefu1sys(111, "stralloc_catb") +static void scanoct (stralloc *sa, size_t pos) +{ + unsigned int u ; + if (!stralloc_0(sa)) dienomem() ; + uint_oscan(sa->s + pos, &u) ; + sa->s[pos] = u ; + sa->len = pos+1 ; +} + static inline uint8_t cclass (char c) { switch (c) @@ -26,7 +37,38 @@ static inline uint8_t cclass (char c) case '\t' : case '\f' : case '\r' : return 4 ; - default : return 5 ; + case '\\' : return 5 ; + case '\"' : return 6 ; + case 'a' : + case 'b' : + case 'f' : return 7 ; + case 'n' : + case 'r' : + case 't' : + case 'v' : return 8 ; + case '\'' : + case '?' : return 9 ; + case 'x' : return 10 ; + case '0' : + case '1' : + case '2' : + case '3' : + case '4' : + case '5' : + case '6' : + case '7' : return 11 ; + case '8' : + case '9' : + case 'A' : + case 'B' : + case 'c' : + case 'C' : + case 'd' : + case 'D' : + case 'e' : + case 'E' : + case 'F' : return 12 ; + default : return 13 ; } } @@ -39,32 +81,48 @@ static inline char next (char const *file, buffer *b) return c ; } -static inline void parse_config (char const *file, buffer *b, stralloc *modif) +static inline void parse_config (char const *file, buffer *b, stralloc *sa) { - static uint8_t const table[7][6] = + static uint16_t const table[14][14] = { - { 0x07, 0x01, 0x80, 0x08, 0x00, 0x22 }, - { 0x07, 0x01, 0x80, 0x01, 0x01, 0x01 }, - { 0x08, 0x08, 0x08, 0x24, 0x03, 0x22 }, - { 0x08, 0x08, 0x08, 0x24, 0x03, 0x08 }, - { 0x47, 0x41, 0xc0, 0x25, 0x04, 0x25 }, - { 0x47, 0x41, 0xc0, 0x25, 0x46, 0x25 }, - { 0x07, 0x01, 0x80, 0x08, 0x06, 0x08 } + { 0x000e, 0x0001, 0x0020, 0x000f, 0x0000, 0x000f, 0x000f, 0x0012, 0x0012, 0x000f, 0x0012, 0x0012, 0x0012, 0x0012 }, + { 0x000e, 0x0001, 0x0020, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001 }, + { 0x000f, 0x0012, 0x000f, 0x0014, 0x0003, 0x000f, 0x000f, 0x0012, 0x0012, 0x000f, 0x0012, 0x0012, 0x0012, 0x0012 }, + { 0x000f, 0x000f, 0x000f, 0x0014, 0x0003, 0x000f, 0x000f, 0x000f, 0x000f, 0x000f, 0x000f, 0x000f, 0x000f, 0x000f }, + { 0x004e, 0x0015, 0x0060, 0x0015, 0x0004, 0x0008, 0x0007, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015 }, + { 0x004e, 0x0015, 0x0060, 0x0015, 0x0116, 0x0008, 0x0007, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015 }, + { 0x00ce, 0x0015, 0x00d0, 0x0015, 0x0016, 0x0008, 0x0007, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015 }, + { 0x000f, 0x0017, 0x000f, 0x0017, 0x0017, 0x0009, 0x0005, 0x0017, 0x0017, 0x0017, 0x0017, 0x0017, 0x0017, 0x0017 }, + { 0x000f, 0x000f, 0x0025, 0x000f, 0x0015, 0x0015, 0x0015, 0x000f, 0x000f, 0x000f, 0x000f, 0x000f, 0x000f, 0x000f }, + { 0x000f, 0x0017, 0x0027, 0x0017, 0x0017, 0x0017, 0x0017, 0x1017, 0x1017, 0x0017, 0x000a, 0x011c, 0x0017, 0x0017 }, + { 0x000f, 0x000f, 0x000f, 0x000f, 0x000f, 0x000f, 0x000f, 0x001b, 0x000f, 0x000f, 0x000f, 0x001b, 0x001b, 0x000f }, + { 0x000f, 0x000f, 0x000f, 0x000f, 0x000f, 0x000f, 0x000f, 0x0217, 0x000f, 0x000f, 0x000f, 0x0217, 0x0217, 0x000f }, + { 0x000f, 0x0417, 0x000f, 0x0417, 0x0417, 0x0409, 0x0405, 0x0417, 0x0417, 0x0417, 0x0417, 0x001d, 0x0417, 0x0417 }, + { 0x000f, 0x0417, 0x000f, 0x0417, 0x0417, 0x0409, 0x0405, 0x0417, 0x0417, 0x0417, 0x0417, 0x0817, 0x0417, 0x0417 } } ; unsigned int line = 1 ; + size_t mark = 0 ; uint8_t state = 0 ; - while (state < 7) + while (state < 14) { char c = next(file, b) ; - uint8_t what = table[state][cclass(c)] ; + uint16_t what = table[state][cclass(c)] ; state = what & 0x0f ; - if (what & 0x20) - if (!stralloc_catb(modif, &c, 1)) dienomem() ; - if (what & 0x40) - if (!stralloc_0(modif)) dienomem() ; - if (what & 0x80) line++ ; + if (what & 0x0400) scanoct(sa, mark) ; + if (what & 0x0100) mark = sa->len ; + if (what & 0x1000) c = 7 + byte_chr("abtnvfr", 7, c) ; + if (what & 0x0010) if (!stralloc_catb(sa, &c, 1)) dienomem() ; + if (what & 0x0020) line++ ; + if (what & 0x0080) sa->len = mark ; + if (what & 0x0040) if (!stralloc_0(sa)) dienomem() ; + if (what & 0x0200) + { + sa->s[sa->len-2] = (fmtscan_num(sa->s[sa->len-2], 16) << 4) + fmtscan_num(sa->s[sa->len-1], 16) ; + sa->len-- ; + } + if (what & 0x0800) scanoct(sa, mark) ; } - if (state > 7) + if (state > 14) { char fmt[UINT_FMT] ; fmt[uint_fmt(fmt, line)] = 0 ; diff --git a/src/execline/envfile.txt b/src/execline/envfile.txt new file mode 100644 index 0000000..81ed02e --- /dev/null +++ b/src/execline/envfile.txt @@ -0,0 +1,60 @@ +envfile parser: + +class | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 +st\ev | \0 # \n = space \ " abf nrtv '? x 0-7 89cde other + +START | n a a a a a a +0 | END COMMENT START X START X X VAR VAR X VAR VAR VAR VAR + +COMMENT | n +1 | END COMMENT START COMMENT COMMENT COMMENT COMMENT COMMENT COMMENT COMMENT COMMENT COMMENT COMMENT COMMENT + +VAR | a a a a a a a a +2 | X VAR X EQ WAITEQ X X VAR VAR X VAR VAR VAR VAR + +WAITEQ | a +3 | X X X EQ WAITEQ X X X X X X X X X + +EQ | + a + n a a a a a a a a +4 | END VAL START VAL EQ ESC Q VAL VAL VAL VAL VAL VAL VAL + +VAL | + a + n a m a a a a a a a a +5 | END VAL START VAL SPACE ESC Q VAL VAL VAL VAL VAL VAL VAL + +SPACE | b + a b + n a a a a a a a a a +6 | END VAL START VAL SPACE ESC Q VAL VAL VAL VAL VAL VAL VAL + +Q | a a a a a a a a a a +7 | X Q X Q Q QESC VAL Q Q Q Q Q Q Q + +ESC | n a a a +8 | X X VAL X VAL VAL VAL X X X X X X X + +QESC | a n a a a a s a s a a m a a a +9 | X Q Q Q Q Q Q Q Q Q HEX0 OCT1 Q Q + +HEX0 | a a a +a | X X X X X X X HEX1 X X X HEX1 HEX1 X + +HEX1 | a h a h a h +b | X X X X X X X Q X X X Q Q X + +OCT1 | o a o a o a o o o a o a o a o a a o a o a +c | X Q X Q Q QESC VAL Q Q Q Q OCT2 Q Q + +OCT2 | o a o a o a o o o a o a o a o a a O o a o a +d | X Q X Q Q QESC VAL Q Q Q Q Q Q Q + +END = e, X = f + +16 states, 9 actions -> 13 bits + +a 0x0010 add cur +n 0x0020 line++ ++ 0x0040 add \0 (definition complete) +b 0x0080 go back to mark +m 0x0100 set mark +h 0x0200 calc hex +o 0x0400 calc oct before a +O 0x0800 calc oct after a +s 0x1000 turn cur special before a |