summaryrefslogtreecommitdiff
path: root/pathexec_env.c
diff options
context:
space:
mode:
Diffstat (limited to 'pathexec_env.c')
-rw-r--r--pathexec_env.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/pathexec_env.c b/pathexec_env.c
new file mode 100644
index 0000000..1305469
--- /dev/null
+++ b/pathexec_env.c
@@ -0,0 +1,74 @@
1/* Public domain. */
2
3#include "stralloc.h"
4#include "alloc.h"
5#include "str.h"
6#include "byte.h"
7#include "env.h"
8#include "pathexec.h"
9
10static stralloc plus;
11static stralloc tmp;
12
13int pathexec_env(const char *s,const char *t)
14{
15 if (!s) return 1;
16 if (!stralloc_copys(&tmp,s)) return 0;
17 if (t) {
18 if (!stralloc_cats(&tmp,"=")) return 0;
19 if (!stralloc_cats(&tmp,t)) return 0;
20 }
21 if (!stralloc_0(&tmp)) return 0;
22 return stralloc_cat(&plus,&tmp);
23}
24
25void pathexec_env_run(const char *file, const char *const *argv)
26{
27 const char **e;
28 unsigned int elen;
29 unsigned int i;
30 unsigned int j;
31 unsigned int split;
32 unsigned int t;
33
34 if (!stralloc_cats(&plus,"")) return;
35
36 elen = 0;
37 for (i = 0;environ[i];++i)
38 ++elen;
39 for (i = 0;i < plus.len;++i)
40 if (!plus.s[i])
41 ++elen;
42
43 e = (const char **) alloc((elen + 1) * sizeof(char *));
44 if (!e) return;
45
46 elen = 0;
47 for (i = 0;environ[i];++i)
48 e[elen++] = environ[i];
49
50 j = 0;
51 for (i = 0;i < plus.len;++i)
52 if (!plus.s[i]) {
53 split = str_chr(plus.s + j,'=');
54 for (t = 0;t < elen;++t)
55 if (byte_equal(plus.s + j,split,e[t]))
56 if (e[t][split] == '=') {
57 --elen;
58 e[t] = e[elen];
59 break;
60 }
61 if (plus.s[j + split])
62 e[elen++] = plus.s + j;
63 j = i + 1;
64 }
65 e[elen] = 0;
66
67 pathexec_run(file,argv,e);
68 alloc_free(e);
69}
70
71void pathexec(const char *const *argv)
72{
73 return pathexec_env_run(*argv, argv);
74}