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 
10 static stralloc plus;
11 static stralloc tmp;
12 
pathexec_env(const char * s,const char * t)13 int 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 
pathexec_env_run(const char * file,const char * const * argv)25 void 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 
pathexec(const char * const * argv)71 void pathexec(const char *const *argv)
72 {
73   return pathexec_env_run(*argv, argv);
74 }
75