aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libc.h1
-rw-r--r--src/lib9/mkfile1
-rw-r--r--src/lib9/searchpath.c62
3 files changed, 64 insertions, 0 deletions
diff --git a/include/libc.h b/include/libc.h
index 653606a1..6e1aa957 100644
--- a/include/libc.h
+++ b/include/libc.h
@@ -390,6 +390,7 @@ extern int postnote(int, int, char *);
extern double p9pow10(int);
/* extern int putenv(char*, char*); <stdlib.h. */
/* extern void qsort(void*, long, long, int (*)(void*, void*)); <stdlib.h> */
+extern char* searchpath(char*);
/* extern int p9setjmp(p9jmp_buf); */
#define p9setjmp(b) sigsetjmp((void*)(b), 1)
/*
diff --git a/src/lib9/mkfile b/src/lib9/mkfile
index 34faf95c..361ab5b7 100644
--- a/src/lib9/mkfile
+++ b/src/lib9/mkfile
@@ -131,6 +131,7 @@ LIB9OFILES=\
read9pmsg.$O\
readn.$O\
rfork.$O\
+ searchpath.$O\
seek.$O\
sendfd.$O\
sleep.$O\
diff --git a/src/lib9/searchpath.c b/src/lib9/searchpath.c
new file mode 100644
index 00000000..3b8e7daa
--- /dev/null
+++ b/src/lib9/searchpath.c
@@ -0,0 +1,62 @@
+#include <u.h>
+#include <libc.h>
+
+/*
+ * Search $PATH for an executable with the given name.
+ * Like in rc, mid-name slashes do not disable search.
+ * Should probably handle escaped colons,
+ * but I don't know what the syntax is.
+ */
+char*
+searchpath(char *name)
+{
+ char *path, *p, *next;
+ char *s, *ss;
+ int ns, l;
+
+ s = nil;
+ ns = 0;
+ if((name[0] == '.' && name[1] == '/')
+ || (name[0] == '.' && name[1] == '.' && name[2] == '/')
+ || (name[0] == '/')){
+ if(access(name, AEXEC) >= 0)
+ return strdup(name);
+ return nil;
+ }
+
+ path = getenv("PATH");
+ for(p=path; p && *p; p=next){
+ if((next = strchr(p, ':')) != nil)
+ *next++ = 0;
+ if(*p == 0){
+ if(access(name, AEXEC) >= 0){
+ free(s);
+ free(path);
+ return strdup(name);
+ }
+ }else{
+ l = strlen(p)+1+strlen(name)+1;
+ if(l > ns){
+ ss = realloc(s, l);
+ if(ss == nil){
+ free(s);
+ free(path);
+ return nil;
+ }
+ s = ss;
+ ns = l;
+ }
+ strcpy(s, p);
+ strcat(s, "/");
+ strcat(s, name);
+ if(access(s, AEXEC) >= 0){
+ free(path);
+ return s;
+ }
+ }
+ }
+ free(s);
+ free(path);
+ return nil;
+}
+