summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS9
-rw-r--r--doc/envfile.html40
-rw-r--r--doc/index.html2
-rw-r--r--doc/upgrade.html10
-rw-r--r--package/info2
-rw-r--r--src/execline/envfile.c94
-rw-r--r--src/execline/envfile.txt60
7 files changed, 186 insertions, 31 deletions
diff --git a/NEWS b/NEWS
index d966ede..07f4fef 100644
--- a/NEWS
+++ b/NEWS
@@ -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