summaryrefslogtreecommitdiff
path: root/src/libenvexec
diff options
context:
space:
mode:
Diffstat (limited to 'src/libenvexec')
-rw-r--r--src/libenvexec/envdir-internal.h11
-rw-r--r--src/libenvexec/envdir.c82
-rw-r--r--src/libenvexec/envdir_clamp.c85
-rw-r--r--src/libenvexec/envdir_noclamp.c103
4 files changed, 204 insertions, 77 deletions
diff --git a/src/libenvexec/envdir-internal.h b/src/libenvexec/envdir-internal.h
new file mode 100644
index 0000000..7b86b1c
--- /dev/null
+++ b/src/libenvexec/envdir-internal.h
@@ -0,0 +1,11 @@
+/* ISC license. */
+
+#ifndef ENVDIR_INTERNAL_H
+#define ENVDIR_INTERNAL_H
+
+#include <skalibs/stralloc.h>
+
+extern int envdir_internal_clamp (char const *, stralloc *, unsigned int, char) ;
+extern int envdir_internal_noclamp (char const *, stralloc *, unsigned int, char) ;
+
+#endif
diff --git a/src/libenvexec/envdir.c b/src/libenvexec/envdir.c
index 6992654..be8867a 100644
--- a/src/libenvexec/envdir.c
+++ b/src/libenvexec/envdir.c
@@ -1,85 +1,13 @@
/* 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
+#include <skalibs/env.h>
+#include "envdir-internal.h"
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 ;
- }
+ return nullis ? options & SKALIBS_ENVDIR_NOCLAMP ?
+ envdir_internal_noclamp(path, modifs, options & ~SKALIBS_ENVDIR_NOCLAMP, nullis) :
+ envdir_internal_clamp(path, modifs, options, nullis) : (errno = EINVAL, -1) ;
}
diff --git a/src/libenvexec/envdir_clamp.c b/src/libenvexec/envdir_clamp.c
new file mode 100644
index 0000000..b63ed97
--- /dev/null
+++ b/src/libenvexec/envdir_clamp.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>
+#include "envdir-internal.h"
+
+#define MAXVARSIZE 4095
+
+int envdir_internal_clamp (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 = 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/envdir_noclamp.c b/src/libenvexec/envdir_noclamp.c
new file mode 100644
index 0000000..b87291a
--- /dev/null
+++ b/src/libenvexec/envdir_noclamp.c
@@ -0,0 +1,103 @@
+/* ISC license. */
+
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <skalibs/bytestr.h>
+#include <skalibs/buffer.h>
+#include <skalibs/env.h>
+#include <skalibs/direntry.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/djbunix.h>
+#include <skalibs/skamisc.h>
+#include "envdir-internal.h"
+
+#define N 4096
+
+int envdir_internal_noclamp (char const *path, stralloc *modifs, unsigned int options, char nullis)
+{
+ unsigned int n = 0 ;
+ size_t pathlen = strlen(path) ;
+ size_t modifbase = modifs->len ;
+ int wasnull = !modifs->s ;
+ int fd ;
+ DIR *dir = opendir(path) ;
+ if (!dir) return -1 ;
+ for (;;)
+ {
+ direntry *d ;
+ size_t len, pos ;
+ 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) ;
+ fd = openc_readb(tmp) ;
+ }
+ if (fd < 0)
+ {
+ if (errno == ENOENT) errno = EIDRM ;
+ goto err ;
+ }
+ if (!stralloc_catb(modifs, d->d_name, len) || !stralloc_catb(modifs, "=", 1)) goto errfd ;
+ pos = modifs->len ;
+ if (options & SKALIBS_ENVDIR_VERBATIM)
+ {
+ if (!slurp(modifs, fd)) goto errfd ;
+ if (modifs->len == pos) modifs->len = pos - 1 ;
+ if (!(options & SKALIBS_ENVDIR_NOCHOMP) && (modifs->s[modifs->len - 1] == '\n')) modifs->len-- ;
+ }
+ else
+ {
+ int r ;
+ char buf[N] ;
+ buffer b = BUFFER_INIT(&buffer_read, fd, buf, N) ;
+ r = skagetln(&b, modifs, '\n') ;
+ if (r == -1)
+ {
+ if (errno != EPIPE) goto errfd ;
+ if (!(options & SKALIBS_ENVDIR_NOCHOMP)) modifs->len = pos ;
+ if (!stralloc_catb(modifs, "\n", 1)) goto errfd ;
+ }
+ if (!r) modifs->len = pos - 1 ;
+ else
+ {
+ size_t i = pos ;
+ if (!(options & SKALIBS_ENVDIR_NOCHOMP))
+ {
+ while (modifs->len-- > pos)
+ {
+ char c = modifs->s[modifs->len] ;
+ if ((c != ' ') && (c != '\t') && (c != '\r')) break ;
+ }
+ modifs->len++ ;
+ for (; i < modifs->len ; i++) if (!modifs->s[i]) modifs->s[i] = nullis ;
+ }
+ }
+ }
+ fd_close(fd) ;
+ if (!stralloc_0(modifs)) goto err ;
+ n++ ;
+ }
+ if (errno) goto err ;
+ dir_close(dir) ;
+ return n ;
+
+ errfd:
+ fd_close(fd) ;
+ err:
+ {
+ int e = errno ;
+ dir_close(dir) ;
+ if (wasnull) stralloc_free(modifs) ; else modifs->len = modifbase ;
+ errno = e ;
+ return -1 ;
+ }
+}