[PATCH 2/2] complete: abstract path complete
Alexander Aring
alex.aring at googlemail.com
Tue Sep 11 01:31:58 EDT 2012
Rewritten path complete, to use it maybe
in another functions.
Signed-off-by: Alexander Aring <alex.aring at gmail.com>
---
common/complete.c | 73 +++++++++++++------------------------------------------
include/libbb.h | 2 ++
lib/libbb.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 82 insertions(+), 57 deletions(-)
diff --git a/common/complete.c b/common/complete.c
index 6a871ef..a06c070 100644
--- a/common/complete.c
+++ b/common/complete.c
@@ -25,6 +25,8 @@
#include <libgen.h>
#include <command.h>
#include <environment.h>
+#include <errno.h>
+#include <libbb.h>
static int file_complete(struct string_list *sl, char *instr, int exec)
{
@@ -70,65 +72,24 @@ out:
return 0;
}
-static int path_command_complete(struct string_list *sl, char *instr)
+static int path_command_complete(char *name, void *priv)
{
- struct stat s;
- DIR *dir;
- struct dirent *d;
- char tmp[PATH_MAX];
- char *path, *p, *n;
-
- p = path = strdup(getenv("PATH"));
-
- if (!path)
- return -1;
-
- while (p) {
- n = strchr(p, ':');
- if (n)
- *n++ = '\0';
- if (*p == '\0') {
- p = n;
- continue;
- }
- dir = opendir(p);
+ struct string_list *sl = priv;
+ char *filename;
- /* We need to check all PATH dirs, so if one failed,
- * try next */
- if (!dir) {
- p = n;
- continue;
- }
+ filename = strrchr(name, '/') + 1;
+ if (!filename)
+ return -EINVAL;
- while ((d = readdir(dir))) {
- if (!strcmp(d->d_name, ".") ||
- !strcmp(d->d_name, ".."))
- continue;
+ strcat(filename, " ");
- if (!strncmp(instr, d->d_name, strlen(instr))) {
- strcpy(tmp, d->d_name);
- if (!stat(tmp, &s) &&
- S_ISDIR(s.st_mode))
- continue;
- else
- strcat(tmp, " ");
-
- /* This function is called
- * after command_complete,
- * so we check if a double
- * entry exist */
- if (string_list_contains
- (sl, tmp) == 0) {
- string_list_add_sorted(sl, tmp);
- }
- }
- }
-
- closedir(dir);
- p = n;
- }
-
- free(path);
+ /* This function is called
+ * after command_complete,
+ * so we check if a double
+ * entry exist */
+ if (!string_list_contains
+ (sl, filename))
+ string_list_add_sorted(sl, filename);
return 0;
}
@@ -334,7 +295,7 @@ int complete(char *instr, char **outstr)
instr = t;
} else {
command_complete(&sl, instr);
- path_command_complete(&sl, instr);
+ find_execable_like(path_command_complete, instr, &sl);
env_param_complete(&sl, instr, 0);
}
if (*instr == '$')
diff --git a/include/libbb.h b/include/libbb.h
index 47b2e08..0ef702b 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -11,6 +11,8 @@ char *concat_subpath_file(const char *path, const char *f);
int execable_file(const char *name);
char *find_execable(const char *filename);
char* last_char_is(const char *s, int c);
+int find_execable_like(int found(char *name, void *priv),
+ const char *likelyname, void *priv);
enum {
ACTION_RECURSE = (1 << 0),
diff --git a/lib/libbb.c b/lib/libbb.c
index e0d7481..daf77c7 100644
--- a/lib/libbb.c
+++ b/lib/libbb.c
@@ -14,6 +14,7 @@
#include <xfuncs.h>
#include <malloc.h>
#include <environment.h>
+#include <errno.h>
/* concatenate path and file name to new allocation buffer,
* not adding '/' if path name already has '/'
@@ -60,7 +61,6 @@ int execable_file(const char *name)
}
EXPORT_SYMBOL(execable_file);
-
/* search $PATH for an executable file;
* return allocated string containing full path if found;
* return NULL otherwise;
@@ -89,6 +89,68 @@ char *find_execable(const char *filename)
}
EXPORT_SYMBOL(find_execable);
+/* search $PATH for an executable file which is
+ * like the filename specified in likelyname;
+ * A likelyname on match will call the found function;
+ * Caller need to duplicate the name string in
+ * found functionpointer, if he want to save it;
+ * return 0 on success and <0 on error;
+ */
+int find_execable_like(int found(char *name, void *priv),
+ const char *likelyname, void *priv)
+{
+ int ret;
+ DIR *dir;
+ struct dirent *d;
+ char *path, *p, *dirname, *n;
+
+ if (!likelyname)
+ return -EINVAL;
+
+ p = path = strdup(getenv("PATH"));
+ while (p) {
+ n = strchr(p, ':');
+ if (n)
+ *n++ = '\0';
+ if (*p != '\0') { /* it's not a PATH="foo::bar" situation */
+ dir = opendir(p);
+ if (!dir) {
+ p = n;
+ continue;
+ }
+
+ dirname = p;
+ while ((d = readdir(dir))) {
+ if (!strcmp(d->d_name, ".") ||
+ !strcmp(d->d_name, ".."))
+ continue;
+ if (!strncmp(likelyname, d->d_name,
+ strlen(likelyname))) {
+ p = concat_path_file(dirname,
+ d->d_name);
+ if (execable_file(p)) {
+ ret = found(p, priv);
+ if (ret < 0)
+ goto err;
+ }
+ free(p);
+ }
+ }
+ closedir(dir);
+ }
+ p = n;
+ }
+
+ free(path);
+ return 0;
+err:
+ closedir(dir);
+ free(p);
+ free(path);
+ return ret;
+}
+EXPORT_SYMBOL(find_execable_like);
+
/* Find out if the last character of a string matches the one given.
* Don't underrun the buffer if the string length is 0.
*/
--
1.7.12
More information about the barebox
mailing list