diff options
Diffstat (limited to 'src/execline/envfile.c')
-rw-r--r-- | src/execline/envfile.c | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/src/execline/envfile.c b/src/execline/envfile.c new file mode 100644 index 0000000..638b182 --- /dev/null +++ b/src/execline/envfile.c @@ -0,0 +1,93 @@ +/* ISC license. */ + +#include <stdint.h> +#include <string.h> + +#include <skalibs/types.h> +#include <skalibs/buffer.h> +#include <skalibs/strerr2.h> +#include <skalibs/env.h> +#include <skalibs/stralloc.h> +#include <skalibs/djbunix.h> + +#define USAGE "envfile file prog..." +#define dieusage() strerr_dieusage(100, USAGE) +#define dienomem() strerr_diefu1sys(111, "stralloc_catb") + +static inline uint8_t cclass (char c) +{ + switch (c) + { + case 0 : return 0 ; + case '#' : return 1 ; + case '\n' : return 2 ; + case '=' : return 3 ; + case ' ' : + case '\t' : + case '\f' : + case '\r' : return 4 ; + default : return 5 ; + } +} + +static inline char next (char const *file, buffer *b) +{ + char c ; + ssize_t r = buffer_get(b, &c, 1) ; + if (r < 0) strerr_diefu2sys(111, "read from ", file) ; + if (!r) c = 0 ; + return c ; +} + +static inline void parse_config (char const *file, buffer *b, stralloc *modif) +{ + static uint8_t const table[7][6] = + { + { 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 } + } ; + unsigned int line = 1 ; + uint8_t state = 0 ; + while (state < 7) + { + char c = next(file, b) ; + uint8_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 (state > 7) + { + char fmt[UINT_FMT] ; + fmt[uint_fmt(fmt, line)] = 0 ; + strerr_dief4x(1, "syntax error line ", fmt, " while parsing ", file) ; + } +} + +int main (int argc, char const *const *argv, char const *const *envp) +{ + stralloc modif = STRALLOC_ZERO ; + PROG = "envfile" ; + if (argc < 3) dieusage() ; + if (!strcmp(argv[1], "-")) + parse_config("standard input", buffer_0, &modif) ; + else + { + buffer b ; + char buf[BUFFER_INSIZE] ; + int fd = open_readb(argv[1]) ; + if (fd == -1) strerr_diefu2sys(111, "open ", argv[1]) ; + buffer_init(&b, &buffer_read, fd, buf, BUFFER_INSIZE) ; + parse_config(argv[1], &b, &modif) ; + fd_close(fd) ; + } + xpathexec_r(argv + 2, envp, env_len(envp), modif.s, modif.len) ; +} |