diff options
Diffstat (limited to 'pathexec_run.c')
-rw-r--r-- | pathexec_run.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/pathexec_run.c b/pathexec_run.c new file mode 100644 index 0000000..1770ac7 --- /dev/null +++ b/pathexec_run.c | |||
@@ -0,0 +1,48 @@ | |||
1 | /* Public domain. */ | ||
2 | |||
3 | #include "error.h" | ||
4 | #include "stralloc.h" | ||
5 | #include "str.h" | ||
6 | #include "env.h" | ||
7 | #include "pathexec.h" | ||
8 | |||
9 | static stralloc tmp; | ||
10 | |||
11 | void pathexec_run(const char *file,const char * const *argv,const char * const *envp) | ||
12 | { | ||
13 | const char *path; | ||
14 | unsigned int split; | ||
15 | int savederrno; | ||
16 | |||
17 | if (file[str_chr(file,'/')]) { | ||
18 | execve(file,argv,envp); | ||
19 | return; | ||
20 | } | ||
21 | |||
22 | path = env_get("PATH"); | ||
23 | if (!path) path = "/bin:/usr/bin"; | ||
24 | |||
25 | savederrno = 0; | ||
26 | for (;;) { | ||
27 | split = str_chr(path,':'); | ||
28 | if (!stralloc_copyb(&tmp,path,split)) return; | ||
29 | if (!split) | ||
30 | if (!stralloc_cats(&tmp,".")) return; | ||
31 | if (!stralloc_cats(&tmp,"/")) return; | ||
32 | if (!stralloc_cats(&tmp,file)) return; | ||
33 | if (!stralloc_0(&tmp)) return; | ||
34 | |||
35 | execve(tmp.s,argv,envp); | ||
36 | if (errno != error_noent) { | ||
37 | savederrno = errno; | ||
38 | if ((errno != error_acces) && (errno != error_perm) && (errno != error_isdir)) return; | ||
39 | } | ||
40 | |||
41 | if (!path[split]) { | ||
42 | if (savederrno) errno = savederrno; | ||
43 | return; | ||
44 | } | ||
45 | path += split; | ||
46 | path += 1; | ||
47 | } | ||
48 | } | ||