summaryrefslogtreecommitdiff
path: root/src/libenvexec
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2020-11-24 21:45:56 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2020-11-24 21:45:56 +0000
commit18e43565574b700befc832ed4d25d25e40951f68 (patch)
tree2c97774819e99132b10dc60403f43e2034e395f9 /src/libenvexec
parent265092c55d40f362a521eee97676e0d51ef17800 (diff)
downloadskalibs-18e43565574b700befc832ed4d25d25e40951f68.tar.xz
Complete revamp of the pathexec functions
- pathexec_run is now called exec_ae a for provided file name (default: argv[0]) e for provided envp (default: environ) - pathexec is now called mexec. m for merge environment. Option letters are: a for provided file name (default: argv[0]) e for provided envp (default: environ) f for provided envp *and* length of the envp m for provided modif string plus its length (the length is always needed because the modifs are null-terminated) n for provided modif string, length *and* number of modifs - functions have a foo0 version for _exit(0) when argv[0] is null - functions have a xfoo version to die if the exec fails - and a xfoo0 - Compatibility #defines and #includes are there until the next major bump
Diffstat (limited to 'src/libenvexec')
-rw-r--r--src/libenvexec/env_addmodif.c19
-rw-r--r--src/libenvexec/env_dump.c54
-rw-r--r--src/libenvexec/env_get.c9
-rw-r--r--src/libenvexec/env_get2.c17
-rw-r--r--src/libenvexec/env_len.c10
-rw-r--r--src/libenvexec/env_make.c16
-rw-r--r--src/libenvexec/env_merg.c8
-rw-r--r--src/libenvexec/env_merge.c9
-rw-r--r--src/libenvexec/env_mergen.c26
-rw-r--r--src/libenvexec/env_mergn.c8
-rw-r--r--src/libenvexec/env_string.c19
-rw-r--r--src/libenvexec/envalloc_0.c10
-rw-r--r--src/libenvexec/envalloc_make.c18
-rw-r--r--src/libenvexec/envalloc_merge.c15
-rw-r--r--src/libenvexec/envalloc_uniq.c32
-rw-r--r--src/libenvexec/envdir.c85
-rw-r--r--src/libenvexec/exec0_ae.c11
-rw-r--r--src/libenvexec/exec_ae.c14
-rw-r--r--src/libenvexec/mexec0_af.c11
-rw-r--r--src/libenvexec/mexec0_afm.c11
-rw-r--r--src/libenvexec/mexec0_afn.c11
-rw-r--r--src/libenvexec/mexec_af.c17
-rw-r--r--src/libenvexec/mexec_afm.c9
-rw-r--r--src/libenvexec/mexec_afn.c11
-rw-r--r--src/libenvexec/xexec0_ae.c11
-rw-r--r--src/libenvexec/xexec_ae.c12
-rw-r--r--src/libenvexec/xexecvep.c13
-rw-r--r--src/libenvexec/xexecvep_loose.c13
-rw-r--r--src/libenvexec/xmexec0_af.c12
-rw-r--r--src/libenvexec/xmexec0_afm.c12
-rw-r--r--src/libenvexec/xmexec0_afn.c12
-rw-r--r--src/libenvexec/xmexec_af.c12
-rw-r--r--src/libenvexec/xmexec_afm.c12
-rw-r--r--src/libenvexec/xmexec_afn.c12
34 files changed, 571 insertions, 0 deletions
diff --git a/src/libenvexec/env_addmodif.c b/src/libenvexec/env_addmodif.c
new file mode 100644
index 0000000..ddd1be3
--- /dev/null
+++ b/src/libenvexec/env_addmodif.c
@@ -0,0 +1,19 @@
+/* ISC license. */
+
+#include <sys/types.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/env.h>
+
+int env_addmodif (stralloc *sa, char const *s, char const *t)
+{
+ size_t oldlen = sa->len ;
+ if (!s) return 1 ;
+ if (!stralloc_cats(sa, s)) return 0 ;
+ if ((t && (!stralloc_catb(sa, "=", 1) || !stralloc_cats(sa, t)))
+ || !stralloc_0(sa))
+ {
+ sa->len = oldlen ;
+ return 0 ;
+ }
+ return 1 ;
+}
diff --git a/src/libenvexec/env_dump.c b/src/libenvexec/env_dump.c
new file mode 100644
index 0000000..10f5913
--- /dev/null
+++ b/src/libenvexec/env_dump.c
@@ -0,0 +1,54 @@
+/* ISC license. */
+
+#include <skalibs/nonposix.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <skalibs/bytestr.h>
+#include <skalibs/env.h>
+#include <skalibs/djbunix.h>
+
+ /* XXX: breaks layering, but really openat() should be supported everywhere */
+#include <skalibs/unix-transactional.h>
+
+#define SUFFIX ":envdump:XXXXXX"
+
+int env_dump (char const *dir, mode_t mode, char const *const *envp)
+{
+ int fd ;
+ size_t dirlen = strlen(dir) ;
+ char tmpdir[dirlen + sizeof(SUFFIX)] ;
+ memcpy(tmpdir, dir, dirlen) ;
+ memcpy(tmpdir + dirlen, SUFFIX, sizeof(SUFFIX)) ;
+ if (!mkdtemp(tmpdir)) return 0 ;
+ fd = open_read(tmpdir) ;
+ if (fd == -1) goto err ;
+ for (; *envp ; envp++)
+ {
+ size_t len = str_chr(*envp, '=') ;
+ size_t vallen = strlen(*envp + len + 1) ;
+ char fn[len + 1] ;
+ memcpy(fn, *envp, len) ;
+ fn[len] = 0 ;
+ len = openwritenclose_at(fd, fn, *envp + len + 1, vallen) ;
+ if (len < vallen) goto cerr ;
+ }
+ fd_close(fd) ;
+ if (chmod(tmpdir, mode) == -1) goto err ;
+ if (rename(tmpdir, dir) == -1) goto err ;
+ return 1 ;
+
+ cerr:
+ fd_close(fd) ;
+ err:
+ {
+ int e = errno ;
+ rm_rf(tmpdir) ;
+ errno = e ;
+ }
+ return 0 ;
+}
diff --git a/src/libenvexec/env_get.c b/src/libenvexec/env_get.c
new file mode 100644
index 0000000..d809461
--- /dev/null
+++ b/src/libenvexec/env_get.c
@@ -0,0 +1,9 @@
+/* ISC license. */
+
+#include <stdlib.h>
+#include <skalibs/posixplz.h>
+
+char const *env_get (char const *s)
+{
+ return getenv(s) ;
+}
diff --git a/src/libenvexec/env_get2.c b/src/libenvexec/env_get2.c
new file mode 100644
index 0000000..5909ea6
--- /dev/null
+++ b/src/libenvexec/env_get2.c
@@ -0,0 +1,17 @@
+/* ISC license. */
+
+#include <string.h>
+#include <skalibs/bytestr.h>
+#include <skalibs/env.h>
+
+char const *env_get2 (char const *const *envp, char const *s)
+{
+ size_t len, i ;
+ if (!s) return 0 ;
+ len = strlen(s) ;
+ for (i = 0 ; envp[i] ; ++i)
+ if (str_start(envp[i], s)
+ && (envp[i][len] == '='))
+ return envp[i] + len + 1 ;
+ return 0 ;
+}
diff --git a/src/libenvexec/env_len.c b/src/libenvexec/env_len.c
new file mode 100644
index 0000000..eef30c4
--- /dev/null
+++ b/src/libenvexec/env_len.c
@@ -0,0 +1,10 @@
+/* ISC license. */
+
+#include <skalibs/env.h>
+
+size_t env_len (char const *const *e)
+{
+ size_t i = 0 ;
+ while (*e++) i++ ;
+ return i ;
+}
diff --git a/src/libenvexec/env_make.c b/src/libenvexec/env_make.c
new file mode 100644
index 0000000..60148f8
--- /dev/null
+++ b/src/libenvexec/env_make.c
@@ -0,0 +1,16 @@
+/* ISC license. */
+
+#include <string.h>
+#include <errno.h>
+#include <skalibs/env.h>
+
+int env_make (char const **v, size_t argc, char const *s, size_t len)
+{
+ while (argc--)
+ {
+ size_t n = strlen(s) + 1 ;
+ if (n > len) return (errno = EINVAL, 0) ;
+ *v++ = s ; s += n ; len -= n ;
+ }
+ return 1 ;
+}
diff --git a/src/libenvexec/env_merg.c b/src/libenvexec/env_merg.c
new file mode 100644
index 0000000..3c403ae
--- /dev/null
+++ b/src/libenvexec/env_merg.c
@@ -0,0 +1,8 @@
+/* ISC license. */
+
+#include <skalibs/env.h>
+
+size_t env_merg (char const **v, size_t vmax, char const *const *envp, char const *modifs, size_t modiflen)
+{
+ return env_merge(v, vmax, envp, env_len(envp), modifs, modiflen) ;
+}
diff --git a/src/libenvexec/env_merge.c b/src/libenvexec/env_merge.c
new file mode 100644
index 0000000..ac3e17c
--- /dev/null
+++ b/src/libenvexec/env_merge.c
@@ -0,0 +1,9 @@
+/* ISC license. */
+
+#include <skalibs/bytestr.h>
+#include <skalibs/env.h>
+
+size_t env_merge (char const **v, size_t vmax, char const *const *envp, size_t envlen, char const *modifs, size_t modiflen)
+{
+ return env_mergen(v, vmax, envp, envlen, modifs, modiflen, byte_count(modifs, modiflen, '\0')) ;
+}
diff --git a/src/libenvexec/env_mergen.c b/src/libenvexec/env_mergen.c
new file mode 100644
index 0000000..acc7c39
--- /dev/null
+++ b/src/libenvexec/env_mergen.c
@@ -0,0 +1,26 @@
+/* ISC license. */
+
+#include <string.h>
+#include <errno.h>
+
+#include <skalibs/bytestr.h>
+#include <skalibs/env.h>
+
+size_t env_mergen (char const **v, size_t vmax, char const *const *envp, size_t envlen, char const *modifs, size_t modiflen, size_t n)
+{
+ size_t vlen = envlen ;
+ size_t i = 0 ;
+ if (envlen + n + 1 > vmax) return (errno = ENAMETOOLONG, 0) ;
+ for (; i < envlen ; i++) v[i] = envp[i] ;
+ for (i = 0 ; i < modiflen ; i += strlen(modifs + i) + 1)
+ {
+ size_t split = str_chr(modifs + i, '=') ;
+ size_t j = 0 ;
+ for (; j < vlen ; j++)
+ if (!strncmp(modifs + i, v[j], split) && (v[j][split] == '=')) break ;
+ if (j < vlen) v[j] = v[--vlen] ;
+ if (modifs[i + split]) v[vlen++] = modifs + i ;
+ }
+ v[vlen++] = 0 ;
+ return vlen ;
+}
diff --git a/src/libenvexec/env_mergn.c b/src/libenvexec/env_mergn.c
new file mode 100644
index 0000000..a8a93c1
--- /dev/null
+++ b/src/libenvexec/env_mergn.c
@@ -0,0 +1,8 @@
+/* ISC license. */
+
+#include <skalibs/env.h>
+
+size_t env_mergn (char const **v, size_t vmax, char const *const *envp, char const *modifs, size_t modiflen, size_t modifn)
+{
+ return env_mergen(v, vmax, envp, env_len(envp), modifs, modiflen, modifn) ;
+}
diff --git a/src/libenvexec/env_string.c b/src/libenvexec/env_string.c
new file mode 100644
index 0000000..e30f095
--- /dev/null
+++ b/src/libenvexec/env_string.c
@@ -0,0 +1,19 @@
+/* ISC license. */
+
+#include <skalibs/stralloc.h>
+#include <skalibs/env.h>
+
+int env_string (stralloc *sa, char const *const *envp, size_t envlen)
+{
+ size_t salen = sa->len ;
+ size_t i = 0 ;
+ for (; i < envlen ; i++)
+ {
+ if (!stralloc_cats(sa, envp[i]) || !stralloc_0(sa))
+ {
+ sa->len = salen ;
+ return 0 ;
+ }
+ }
+ return 1 ;
+}
diff --git a/src/libenvexec/envalloc_0.c b/src/libenvexec/envalloc_0.c
new file mode 100644
index 0000000..114f69e
--- /dev/null
+++ b/src/libenvexec/envalloc_0.c
@@ -0,0 +1,10 @@
+/* ISC license. */
+
+#include <skalibs/genalloc.h>
+#include <skalibs/envalloc.h>
+
+int envalloc_0 (genalloc *v)
+{
+ char const *z = 0 ;
+ return genalloc_append(char const *, v, &z) ;
+}
diff --git a/src/libenvexec/envalloc_make.c b/src/libenvexec/envalloc_make.c
new file mode 100644
index 0000000..f8c459a
--- /dev/null
+++ b/src/libenvexec/envalloc_make.c
@@ -0,0 +1,18 @@
+/* ISC license. */
+
+#include <skalibs/env.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/envalloc.h>
+
+int envalloc_make (genalloc *v, size_t argc, char const *s, size_t len)
+{
+ int wasnull = !v->s ;
+ if (!genalloc_readyplus(char const *, v, argc+1)) return 0 ;
+ if (!env_make(genalloc_s(char const *, v) + genalloc_len(char const *, v), argc, s, len))
+ {
+ if (wasnull) genalloc_free(char const *, v) ;
+ return 0 ;
+ }
+ genalloc_setlen(char const *, v, genalloc_len(char const *, v) + argc) ;
+ return 1 ;
+}
diff --git a/src/libenvexec/envalloc_merge.c b/src/libenvexec/envalloc_merge.c
new file mode 100644
index 0000000..84716e4
--- /dev/null
+++ b/src/libenvexec/envalloc_merge.c
@@ -0,0 +1,15 @@
+/* ISC license. */
+
+#include <skalibs/bytestr.h>
+#include <skalibs/env.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/envalloc.h>
+
+int envalloc_merge (genalloc *v, char const *const *envp, size_t envlen, char const *modifs, size_t modiflen)
+{
+ size_t n = envlen + 1 + byte_count(modifs, modiflen, '\0') ;
+ if (!genalloc_readyplus(char const *, v, n)) return 0 ;
+ n = env_mergen(genalloc_s(char const *, v) + genalloc_len(char const *, v), n, envp, envlen, modifs, modiflen, n) ;
+ genalloc_setlen(char const *, v, genalloc_len(char const *, v) + n) ;
+ return 1 ;
+}
diff --git a/src/libenvexec/envalloc_uniq.c b/src/libenvexec/envalloc_uniq.c
new file mode 100644
index 0000000..cf60b44
--- /dev/null
+++ b/src/libenvexec/envalloc_uniq.c
@@ -0,0 +1,32 @@
+/* ISC license. */
+
+#include <string.h>
+#include <errno.h>
+#include <skalibs/bytestr.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/envalloc.h>
+
+int envalloc_uniq (genalloc *v, char delim)
+{
+ unsigned int m = 0 ;
+ size_t i = 0 ;
+ for (; i < genalloc_len(char const *, v) ; i++)
+ {
+ size_t j = i+1 ;
+ char const *s = genalloc_s(char const *, v)[i] ;
+ size_t n = str_chr(s, delim) ;
+ if (delim && !s[n]) return (errno = EINVAL, -1) ;
+ for (; j < genalloc_len(char const *, v) ; j++)
+ {
+ char const **p = genalloc_s(char const *, v) ;
+ if (!strncmp(s, p[j], n))
+ {
+ size_t len = genalloc_len(char const *, v) - 1 ;
+ genalloc_setlen(char const *, v, len) ;
+ p[j] = p[len] ;
+ m++ ;
+ }
+ }
+ }
+ return m ;
+}
diff --git a/src/libenvexec/envdir.c b/src/libenvexec/envdir.c
new file mode 100644
index 0000000..6992654
--- /dev/null
+++ b/src/libenvexec/envdir.c
@@ -0,0 +1,85 @@
+/* ISC license. */
+
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <skalibs/bytestr.h>
+#include <skalibs/env.h>
+#include <skalibs/direntry.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/djbunix.h>
+
+#define MAXVARSIZE 4095
+
+int envdir_internal (char const *path, stralloc *modifs, unsigned int options, char nullis)
+{
+ char buf[MAXVARSIZE + 1] ;
+ unsigned int n = 0 ;
+ size_t pathlen = strlen(path) ;
+ size_t modifbase = modifs->len ;
+ int wasnull = !modifs->s ;
+ DIR *dir ;
+ if (!nullis) return (errno = EINVAL, -1) ;
+ dir = opendir(path) ;
+ if (!dir) return -1 ;
+ for (;;)
+ {
+ direntry *d ;
+ size_t len ;
+ ssize_t r ;
+ errno = 0 ;
+ d = readdir(dir) ;
+ if (!d) break ;
+ if (d->d_name[0] == '.') continue ;
+ len = strlen(d->d_name) ;
+ if (str_chr(d->d_name, '=') < len) continue ;
+ {
+ char tmp[pathlen + len + 2] ;
+ memcpy(tmp, path, pathlen) ;
+ tmp[pathlen] = '/' ;
+ memcpy(tmp + pathlen + 1, d->d_name, len + 1) ;
+ r = openreadnclose(tmp, buf, MAXVARSIZE) ;
+ }
+ if (r < 0)
+ {
+ if (errno == ENOENT) errno = EIDRM ;
+ goto err ;
+ }
+ else if (r > 0)
+ {
+ if (options & SKALIBS_ENVDIR_VERBATIM)
+ {
+ if (!(options & SKALIBS_ENVDIR_NOCHOMP) && (buf[r-1] == '\n')) r-- ;
+ }
+ else
+ {
+ r = byte_chr(buf, r, '\n') ;
+ if (!(options & SKALIBS_ENVDIR_NOCHOMP))
+ {
+ while (r--) if ((buf[r] != ' ') && (buf[r] != '\t') && (buf[r] != '\r')) break ;
+ r++ ;
+ }
+ }
+ {
+ size_t i = 0 ;
+ for (; i < (size_t)r ; i++) if (!buf[i]) buf[i] = nullis ;
+ }
+ buf[r++] = 0 ;
+ if (!env_addmodif(modifs, d->d_name, buf)) goto err ;
+ }
+ else if (!env_addmodif(modifs, d->d_name, 0)) goto err ;
+ n++ ;
+ }
+ if (errno) goto err ;
+ dir_close(dir) ;
+ return n ;
+
+ err:
+ {
+ int e = errno ;
+ dir_close(dir) ;
+ if (wasnull) stralloc_free(modifs) ; else modifs->len = modifbase ;
+ errno = e ;
+ return -1 ;
+ }
+}
diff --git a/src/libenvexec/exec0_ae.c b/src/libenvexec/exec0_ae.c
new file mode 100644
index 0000000..14aac8b
--- /dev/null
+++ b/src/libenvexec/exec0_ae.c
@@ -0,0 +1,11 @@
+/* ISC license. */
+
+#include <unistd.h>
+
+#include <skalibs/exec.h>
+
+void exec0_ae (char const *file, char const *const *argv, char const *const *envp)
+{
+ if (!argv[0]) _exit(0) ;
+ exec_ae(file, argv, envp) ;
+}
diff --git a/src/libenvexec/exec_ae.c b/src/libenvexec/exec_ae.c
new file mode 100644
index 0000000..3c28722
--- /dev/null
+++ b/src/libenvexec/exec_ae.c
@@ -0,0 +1,14 @@
+/* ISC license. */
+
+#include <stdlib.h>
+
+#include <skalibs/config.h>
+#include <skalibs/posixplz.h>
+#include <skalibs/exec.h>
+
+void exec_ae (char const *file, char const *const *argv, char const *const *envp)
+{
+ char const *path = getenv("PATH") ;
+ if (!path) path = SKALIBS_DEFAULTPATH ;
+ execvep(file, argv, envp, path) ;
+}
diff --git a/src/libenvexec/mexec0_af.c b/src/libenvexec/mexec0_af.c
new file mode 100644
index 0000000..97e228d
--- /dev/null
+++ b/src/libenvexec/mexec0_af.c
@@ -0,0 +1,11 @@
+/* ISC license. */
+
+#include <unistd.h>
+
+#include <skalibs/exec.h>
+
+void mexec0_af (char const *file, char const *const *argv, char const *const *envp, size_t envlen)
+{
+ if (!argv[0]) _exit(0) ;
+ mexec_af(file, argv, envp, envlen) ;
+}
diff --git a/src/libenvexec/mexec0_afm.c b/src/libenvexec/mexec0_afm.c
new file mode 100644
index 0000000..1ece07e
--- /dev/null
+++ b/src/libenvexec/mexec0_afm.c
@@ -0,0 +1,11 @@
+/* ISC license. */
+
+#include <unistd.h>
+
+#include <skalibs/exec.h>
+
+void mexec0_afm (char const *file, char const *const *argv, char const *const *envp, size_t envlen, char const *modif, size_t modiflen)
+{
+ if (!argv[0]) _exit(0) ;
+ mexec_afm(file, argv, envp, envlen, modif, modiflen) ;
+}
diff --git a/src/libenvexec/mexec0_afn.c b/src/libenvexec/mexec0_afn.c
new file mode 100644
index 0000000..160a509
--- /dev/null
+++ b/src/libenvexec/mexec0_afn.c
@@ -0,0 +1,11 @@
+/* ISC license. */
+
+#include <unistd.h>
+
+#include <skalibs/exec.h>
+
+void mexec0_afn (char const *file, char const *const *argv, char const *const *envp, size_t envlen, char const *modif, size_t modiflen, size_t modifn)
+{
+ if (!argv[0]) _exit(0) ;
+ mexec_afn(file, argv, envp, envlen, modif, modiflen, modifn) ;
+}
diff --git a/src/libenvexec/mexec_af.c b/src/libenvexec/mexec_af.c
new file mode 100644
index 0000000..34c266a
--- /dev/null
+++ b/src/libenvexec/mexec_af.c
@@ -0,0 +1,17 @@
+/* ISC license. */
+
+#include <skalibs/stralloc.h>
+#include <skalibs/env.h>
+#include <skalibs/exec.h>
+
+static stralloc modifsa = STRALLOC_ZERO ;
+
+int env_mexec (char const *key, char const *value)
+{
+ return env_addmodif(&modifsa, key, value) ;
+}
+
+void mexec_af (char const *file, char const *const *argv, char const *const *envp, size_t envlen)
+{
+ mexec_afm(file, argv, envp, envlen, modifsa.s, modifsa.len) ;
+}
diff --git a/src/libenvexec/mexec_afm.c b/src/libenvexec/mexec_afm.c
new file mode 100644
index 0000000..01571a1
--- /dev/null
+++ b/src/libenvexec/mexec_afm.c
@@ -0,0 +1,9 @@
+/* ISC license. */
+
+#include <skalibs/bytestr.h>
+#include <skalibs/exec.h>
+
+void mexec_afm (char const *file, char const *const *argv, char const *const *envp, size_t envlen, char const *modif, size_t modiflen)
+{
+ mexec_afn(file, argv, envp, envlen, modif, modiflen, byte_count(modif, modiflen, '\0')) ;
+}
diff --git a/src/libenvexec/mexec_afn.c b/src/libenvexec/mexec_afn.c
new file mode 100644
index 0000000..278be11
--- /dev/null
+++ b/src/libenvexec/mexec_afn.c
@@ -0,0 +1,11 @@
+/* ISC license. */
+
+#include <skalibs/env.h>
+#include <skalibs/exec.h>
+
+void mexec_afn (char const *file, char const *const *argv, char const *const *envp, size_t envlen, char const *modif, size_t modiflen, size_t modifn)
+{
+ char const *newenvp[envlen + modifn + 1] ;
+ env_mergen(newenvp, envlen + modifn + 1, envp, envlen, modif, modiflen, modifn) ;
+ exec_ae(file, argv, newenvp) ;
+}
diff --git a/src/libenvexec/xexec0_ae.c b/src/libenvexec/xexec0_ae.c
new file mode 100644
index 0000000..f0bd39c
--- /dev/null
+++ b/src/libenvexec/xexec0_ae.c
@@ -0,0 +1,11 @@
+/* ISC license. */
+
+#include <unistd.h>
+
+#include <skalibs/exec.h>
+
+void xexec0_ae (char const *file, char const *const *argv, char const *const *envp)
+{
+ if (!argv[0]) _exit(0) ;
+ xexec_ae(file, argv, envp) ;
+}
diff --git a/src/libenvexec/xexec_ae.c b/src/libenvexec/xexec_ae.c
new file mode 100644
index 0000000..55b7c70
--- /dev/null
+++ b/src/libenvexec/xexec_ae.c
@@ -0,0 +1,12 @@
+/* ISC license. */
+
+#include <errno.h>
+
+#include <skalibs/exec.h>
+#include <skalibs/strerr2.h>
+
+void xexec_ae (char const *file, char const *const *argv, char const *const *envp)
+{
+ exec_ae(file, argv, envp) ;
+ strerr_dieexec(errno == ENOENT ? 127 : 126, file) ;
+}
diff --git a/src/libenvexec/xexecvep.c b/src/libenvexec/xexecvep.c
new file mode 100644
index 0000000..c272401
--- /dev/null
+++ b/src/libenvexec/xexecvep.c
@@ -0,0 +1,13 @@
+/* ISC license. */
+
+#include <errno.h>
+
+#include <skalibs/posixplz.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/exec.h>
+
+void xexecvep (char const *file, char const *const *argv, char const *const *envp, char const *path)
+{
+ execvep(file, argv, envp, path) ;
+ strerr_dieexec(errno == ENOENT ? 127 : 126, file) ;
+}
diff --git a/src/libenvexec/xexecvep_loose.c b/src/libenvexec/xexecvep_loose.c
new file mode 100644
index 0000000..a9935a6
--- /dev/null
+++ b/src/libenvexec/xexecvep_loose.c
@@ -0,0 +1,13 @@
+/* ISC license. */
+
+#include <errno.h>
+
+#include <skalibs/posixplz.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/exec.h>
+
+void xexecvep_loose (char const *file, char const *const *argv, char const *const *envp, char const *path)
+{
+ xexecvep_loose(file, argv, envp, path) ;
+ strerr_dieexec(errno == ENOENT ? 127 : 126, file) ;
+}
diff --git a/src/libenvexec/xmexec0_af.c b/src/libenvexec/xmexec0_af.c
new file mode 100644
index 0000000..a0bf84d
--- /dev/null
+++ b/src/libenvexec/xmexec0_af.c
@@ -0,0 +1,12 @@
+/* ISC license. */
+
+#include <errno.h>
+
+#include <skalibs/exec.h>
+#include <skalibs/strerr2.h>
+
+void xmexec0_af (char const *file, char const *const *argv, char const *const *envp, size_t envlen)
+{
+ xmexec0_af(file, argv, envp, envlen) ;
+ strerr_dieexec(errno == ENOENT ? 127 : 126, file) ;
+}
diff --git a/src/libenvexec/xmexec0_afm.c b/src/libenvexec/xmexec0_afm.c
new file mode 100644
index 0000000..a43cb49
--- /dev/null
+++ b/src/libenvexec/xmexec0_afm.c
@@ -0,0 +1,12 @@
+/* ISC license. */
+
+#include <errno.h>
+
+#include <skalibs/exec.h>
+#include <skalibs/strerr2.h>
+
+void xmexec0_afm (char const *file, char const *const *argv, char const *const *envp, size_t envlen, char const *modif, size_t modiflen)
+{
+ mexec0_afm(file, argv, envp, envlen, modif, modiflen) ;
+ strerr_dieexec(errno == ENOENT ? 127 : 126, file) ;
+}
diff --git a/src/libenvexec/xmexec0_afn.c b/src/libenvexec/xmexec0_afn.c
new file mode 100644
index 0000000..73eeb04
--- /dev/null
+++ b/src/libenvexec/xmexec0_afn.c
@@ -0,0 +1,12 @@
+/* ISC license. */
+
+#include <errno.h>
+
+#include <skalibs/exec.h>
+#include <skalibs/strerr2.h>
+
+void xmexec0_afn (char const *file, char const *const *argv, char const *const *envp, size_t envlen, char const *modif, size_t modiflen, size_t modifn)
+{
+ mexec0_afn(file, argv, envp, envlen, modif, modiflen, modifn) ;
+ strerr_dieexec(errno == ENOENT ? 127 : 126, file) ;
+}
diff --git a/src/libenvexec/xmexec_af.c b/src/libenvexec/xmexec_af.c
new file mode 100644
index 0000000..240220b
--- /dev/null
+++ b/src/libenvexec/xmexec_af.c
@@ -0,0 +1,12 @@
+/* ISC license. */
+
+#include <errno.h>
+
+#include <skalibs/exec.h>
+#include <skalibs/strerr2.h>
+
+void xmexec_af (char const *file, char const *const *argv, char const *const *envp, size_t envlen)
+{
+ xmexec_af(file, argv, envp, envlen) ;
+ strerr_dieexec(errno == ENOENT ? 127 : 126, file) ;
+}
diff --git a/src/libenvexec/xmexec_afm.c b/src/libenvexec/xmexec_afm.c
new file mode 100644
index 0000000..ac86c3a
--- /dev/null
+++ b/src/libenvexec/xmexec_afm.c
@@ -0,0 +1,12 @@
+/* ISC license. */
+
+#include <errno.h>
+
+#include <skalibs/exec.h>
+#include <skalibs/strerr2.h>
+
+void xmexec_afm (char const *file, char const *const *argv, char const *const *envp, size_t envlen, char const *modif, size_t modiflen)
+{
+ mexec_afm(file, argv, envp, envlen, modif, modiflen) ;
+ strerr_dieexec(errno == ENOENT ? 127 : 126, file) ;
+}
diff --git a/src/libenvexec/xmexec_afn.c b/src/libenvexec/xmexec_afn.c
new file mode 100644
index 0000000..93f0c33
--- /dev/null
+++ b/src/libenvexec/xmexec_afn.c
@@ -0,0 +1,12 @@
+/* ISC license. */
+
+#include <errno.h>
+
+#include <skalibs/exec.h>
+#include <skalibs/strerr2.h>
+
+void xmexec_afn (char const *file, char const *const *argv, char const *const *envp, size_t envlen, char const *modif, size_t modiflen, size_t modifn)
+{
+ mexec_afn(file, argv, envp, envlen, modif, modiflen, modifn) ;
+ strerr_dieexec(errno == ENOENT ? 127 : 126, file) ;
+}