summaryrefslogtreecommitdiff
path: root/src/execline/runblock.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/execline/runblock.c')
-rw-r--r--src/execline/runblock.c149
1 files changed, 149 insertions, 0 deletions
diff --git a/src/execline/runblock.c b/src/execline/runblock.c
new file mode 100644
index 0000000..a654023
--- /dev/null
+++ b/src/execline/runblock.c
@@ -0,0 +1,149 @@
+/* ISC license. */
+
+#include <skalibs/sgetopt.h>
+#include <skalibs/uint.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/env.h>
+#include <skalibs/djbunix.h>
+#include <skalibs/skamisc.h>
+#include <execline/execline.h>
+
+#define USAGE "runblock [ -P ] [ -n argshift ] [ -r ] n"
+#define dieusage() strerr_dieusage(100, USAGE)
+
+int main (int argc, char const *const *argv, char const *const *envp)
+{
+ genalloc v = GENALLOC_ZERO ; /* array of char const * */
+ unsigned int n, sharp ;
+ unsigned int m = 0 ;
+ unsigned int strict = el_getstrict() ;
+ int flagnopop = 0, flagr = 0 ;
+ PROG = "runblock" ;
+ {
+ subgetopt_t l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ register int opt = subgetopt_r(argc, argv, "Prn:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'P' : flagnopop = 1 ; break ;
+ case 'r' : flagr = 1 ; break ;
+ case 'n' : if (!uint0_scan(l.arg, &m)) dieusage() ; break ;
+ default : dieusage() ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+ if (argc != 1) dieusage() ;
+ if (!uint0_scan(argv[0], &n) || (!n && !flagr)) dieusage() ;
+
+ {
+ char const *x = env_get2(envp, "#") ;
+ if (!x) strerr_dienotset(100, "#") ;
+ if (!uint0_scan(x, &sharp)) strerr_dieinvalid(100, "#") ;
+ }
+
+ /* Skip n-1 blocks (n if flagr) */
+ {
+ register unsigned int i = 1 ;
+ for (; i < n + flagr ; i++)
+ {
+ unsigned int base = m ;
+ for (;;)
+ {
+ char const *x ;
+ char fmt[UINT_FMT] ;
+ if (++m > sharp) strerr_dief1x(100, "too few arguments") ;
+ fmt[uint_fmt(fmt, m)] = 0 ;
+ x = env_get2(envp, fmt) ;
+ if (!x) strerr_dienotset(100, fmt) ;
+ if ((x[0] == EXECLINE_BLOCK_END_CHAR) && (!EXECLINE_BLOCK_END_CHAR || !x[1])) break ;
+ if ((x[0] != EXECLINE_BLOCK_QUOTE_CHAR) && strict)
+ {
+ char fmtb[UINT_FMT] ;
+ char fmti[UINT_FMT] ;
+ fmti[uint_fmt(fmti, i)] = 0 ;
+ fmtb[uint_fmt(fmtb, m - base)] = 0 ;
+ if (strict == 1)
+ strerr_warnw6x("unquoted positional ", x, " at block ", fmti, " position ", fmtb) ;
+ else
+ strerr_dief6x(100, "unquoted positional ", x, " at block ", fmti, " position ", fmtb) ;
+ }
+ }
+ }
+ }
+
+ if (flagr) /* put remainder envvars into v */
+ {
+ if (++m == sharp) return 0 ;
+ if (!genalloc_ready(char const *, &v, sharp - m + 2))
+ strerr_diefu1sys(111, "genalloc_ready") ;
+ for (; m <= sharp ; m++)
+ {
+ char const *x ;
+ char fmt[UINT_FMT] ;
+ fmt[uint_fmt(fmt, m)] = 0 ;
+ x = env_get2(envp, fmt) ;
+ if (!x) strerr_dienotset(100, fmt) ;
+ genalloc_append(char const *, &v, &x) ;
+ }
+ }
+ else /* put envvars from nth block into v */
+ {
+ unsigned int base = m ;
+ for (;;)
+ {
+ char const *x ;
+ char fmt[UINT_FMT] ;
+ if (++m > sharp) strerr_dief1x(100, "too few arguments") ;
+ fmt[uint_fmt(fmt, m)] = 0 ;
+ x = env_get2(envp, fmt) ;
+ if (!x) strerr_dienotset(100, fmt) ;
+ if ((x[0] == EXECLINE_BLOCK_END_CHAR) && (!EXECLINE_BLOCK_END_CHAR || !x[1])) break ;
+ if (x[0] != EXECLINE_BLOCK_QUOTE_CHAR)
+ {
+ if (strict)
+ {
+ char fmtb[UINT_FMT] ;
+ char fmtn[UINT_FMT] ;
+ fmtn[uint_fmt(fmtn, n)] = 0 ;
+ fmtb[uint_fmt(fmtb, m - base)] = 0 ;
+ if (strict == 1)
+ strerr_warnw6x("unquoted positional ", x, " at block ", fmtn, " position ", fmtb) ;
+ else
+ strerr_dief6x(100, "unquoted positional ", x, " at block ", fmtn, " position ", fmtb) ;
+ }
+ }
+ else x++ ;
+ if (!genalloc_append(char const *, &v, &x)) strerr_diefu1sys(111, "envalloc_catb") ;
+ }
+ }
+
+ {
+ char const *z = 0 ;
+ if (!genalloc_append(char const *, &v, &z))
+ strerr_diefu1sys(111, "genalloc_append") ;
+ }
+
+ if (flagnopop) /* exec now */
+ pathexec_run(genalloc_s(char const *, &v)[0], genalloc_s(char const *, &v), envp) ;
+ else /* popenv, then exec */
+ {
+ char const *list[11] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "#" } ;
+ unsigned int envlen = env_len(envp) ;
+ register int popped = el_popenv(&satmp, envp, envlen, list, 11) ;
+ if (popped < 0) strerr_diefu1sys(111, "pop environment") ;
+ else
+ {
+ char const *w[envlen - popped + 1] ;
+ if (!env_make(w, envlen - popped, satmp.s, satmp.len))
+ strerr_diefu1sys(111, "env_make") ;
+ w[envlen - popped] = 0 ;
+ pathexec_run(genalloc_s(char const *, &v)[0], genalloc_s(char const *, &v), w) ;
+ stralloc_free(&satmp) ;
+ }
+ }
+ strerr_dieexec(111, genalloc_s(char const *, &v)[0]) ;
+}