Hi,<br><br>I prefer this implementation than the older one, because it check on executable(Maybe we add a attribute for that or check on shebang) file and call found with the full path.<br>I was thinking about to put this as RFC..., because I don't have really a usecase for this.<br>
Some commands can do a autocompletion for files that are in $PATH, when this is needed.<br><br>The naming things, I don't like the name, too. I was doing the naming like the others functions.<br>I will send a v2 with a better name and functionheader<br>
<br>Regards<br>Alexander Aring<br><br><div class="gmail_quote">2012/9/11 Sascha Hauer <span dir="ltr"><<a href="mailto:s.hauer@pengutronix.de" target="_blank">s.hauer@pengutronix.de</a>></span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="im">On Tue, Sep 11, 2012 at 07:31:58AM +0200, Alexander Aring wrote:<br>
> Rewritten path complete, to use it maybe<br>
> in another functions.<br>
<br>
</div>Do you have a usecase for this?<br>
<div><div class="h5"><br>
><br>
> Signed-off-by: Alexander Aring <<a href="mailto:alex.aring@gmail.com">alex.aring@gmail.com</a>><br>
> ---<br>
>  common/complete.c | 73 +++++++++++++------------------------------------------<br>
>  include/libbb.h   |  2 ++<br>
>  lib/libbb.c       | 64 +++++++++++++++++++++++++++++++++++++++++++++++-<br>
>  3 files changed, 82 insertions(+), 57 deletions(-)<br>
><br>
> diff --git a/common/complete.c b/common/complete.c<br>
> index 6a871ef..a06c070 100644<br>
> --- a/common/complete.c<br>
> +++ b/common/complete.c<br>
> @@ -25,6 +25,8 @@<br>
>  #include <libgen.h><br>
>  #include <command.h><br>
>  #include <environment.h><br>
> +#include <errno.h><br>
> +#include <libbb.h><br>
><br>
>  static int file_complete(struct string_list *sl, char *instr, int exec)<br>
>  {<br>
> @@ -70,65 +72,24 @@ out:<br>
>       return 0;<br>
>  }<br>
><br>
> -static int path_command_complete(struct string_list *sl, char *instr)<br>
> +static int path_command_complete(char *name, void *priv)<br>
>  {<br>
> -     struct stat s;<br>
> -     DIR *dir;<br>
> -     struct dirent *d;<br>
> -     char tmp[PATH_MAX];<br>
> -     char *path, *p, *n;<br>
> -<br>
> -     p = path = strdup(getenv("PATH"));<br>
> -<br>
> -     if (!path)<br>
> -             return -1;<br>
> -<br>
> -     while (p) {<br>
> -             n = strchr(p, ':');<br>
> -             if (n)<br>
> -                     *n++ = '\0';<br>
> -             if (*p == '\0') {<br>
> -                     p = n;<br>
> -                     continue;<br>
> -             }<br>
> -             dir = opendir(p);<br>
> +     struct string_list *sl = priv;<br>
> +     char *filename;<br>
><br>
> -             /* We need to check all PATH dirs, so if one failed,<br>
> -              * try next */<br>
> -             if (!dir) {<br>
> -                     p = n;<br>
> -                     continue;<br>
> -             }<br>
> +     filename = strrchr(name, '/') + 1;<br>
> +     if (!filename)<br>
> +             return -EINVAL;<br>
><br>
> -             while ((d = readdir(dir))) {<br>
> -                     if (!strcmp(d->d_name, ".") ||<br>
> -                                     !strcmp(d->d_name, ".."))<br>
> -                             continue;<br>
> +     strcat(filename, " ");<br>
><br>
> -                     if (!strncmp(instr, d->d_name, strlen(instr))) {<br>
> -                             strcpy(tmp, d->d_name);<br>
> -                             if (!stat(tmp, &s) &&<br>
> -                                             S_ISDIR(s.st_mode))<br>
> -                                     continue;<br>
> -                             else<br>
> -                                     strcat(tmp, " ");<br>
> -<br>
> -                             /* This function is called<br>
> -                              * after command_complete,<br>
> -                              * so we check if a double<br>
> -                              * entry exist */<br>
> -                             if (string_list_contains<br>
> -                                             (sl, tmp) == 0) {<br>
> -                                     string_list_add_sorted(sl, tmp);<br>
> -                             }<br>
> -                     }<br>
> -             }<br>
> -<br>
> -             closedir(dir);<br>
> -             p = n;<br>
> -     }<br>
> -<br>
> -     free(path);<br>
> +     /* This function is called<br>
> +      * after command_complete,<br>
> +      * so we check if a double<br>
> +      * entry exist */<br>
> +     if (!string_list_contains<br>
> +             (sl, filename))<br>
> +             string_list_add_sorted(sl, filename);<br>
><br>
>       return 0;<br>
>  }<br>
> @@ -334,7 +295,7 @@ int complete(char *instr, char **outstr)<br>
>                       instr = t;<br>
>               } else {<br>
>                       command_complete(&sl, instr);<br>
> -                     path_command_complete(&sl, instr);<br>
> +                     find_execable_like(path_command_complete, instr, &sl);<br>
>                       env_param_complete(&sl, instr, 0);<br>
>               }<br>
>               if (*instr == '$')<br>
> diff --git a/include/libbb.h b/include/libbb.h<br>
> index 47b2e08..0ef702b 100644<br>
> --- a/include/libbb.h<br>
> +++ b/include/libbb.h<br>
> @@ -11,6 +11,8 @@ char *concat_subpath_file(const char *path, const char *f);<br>
>  int execable_file(const char *name);<br>
>  char *find_execable(const char *filename);<br>
>  char* last_char_is(const char *s, int c);<br>
> +int find_execable_like(int found(char *name, void *priv),<br>
> +             const char *likelyname, void *priv);<br>
><br>
>  enum {<br>
>       ACTION_RECURSE     = (1 << 0),<br>
> diff --git a/lib/libbb.c b/lib/libbb.c<br>
> index e0d7481..daf77c7 100644<br>
> --- a/lib/libbb.c<br>
> +++ b/lib/libbb.c<br>
> @@ -14,6 +14,7 @@<br>
>  #include <xfuncs.h><br>
>  #include <malloc.h><br>
>  #include <environment.h><br>
> +#include <errno.h><br>
><br>
>  /* concatenate path and file name to new allocation buffer,<br>
>   * not adding '/' if path name already has '/'<br>
> @@ -60,7 +61,6 @@ int execable_file(const char *name)<br>
>  }<br>
>  EXPORT_SYMBOL(execable_file);<br>
><br>
> -<br>
>  /* search $PATH for an executable file;<br>
>   * return allocated string containing full path if found;<br>
>   * return NULL otherwise;<br>
> @@ -89,6 +89,68 @@ char *find_execable(const char *filename)<br>
>  }<br>
>  EXPORT_SYMBOL(find_execable);<br>
><br>
> +/* search $PATH for an executable file which is<br>
> + * like the filename specified in likelyname;<br>
> + * A likelyname on match will call the found function;<br>
> + * Caller need to duplicate the name string in<br>
> + * found functionpointer, if he want to save it;<br>
> + * return 0 on success and <0 on error;<br>
> + */<br>
> +int find_execable_like(int found(char *name, void *priv),<br>
> +             const char *likelyname, void *priv)<br>
<br>
</div></div>I don't like the name very much. Can we name it execable_complete?<br>
Also I would use the likelyname argument as first argument, because<br>
then it would read "on 'name' do call 'found'"<br>
<br>
(I always stumble over 'execable', it should rather be 'executable', but<br>
we have the former everywhere, so either change them all keep it here<br>
aswell)<br>
<span class="HOEnZb"><font color="#888888"><br>
Sascha<br>
<br>
--<br>
Pengutronix e.K.                           |                             |<br>
Industrial Linux Solutions                 | <a href="http://www.pengutronix.de/" target="_blank">http://www.pengutronix.de/</a>  |<br>
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: <a href="tel:%2B49-5121-206917-0" value="+4951212069170">+49-5121-206917-0</a>    |<br>
Amtsgericht Hildesheim, HRA 2686           | Fax:   <a href="tel:%2B49-5121-206917-5555" value="+4951212069175555">+49-5121-206917-5555</a> |<br>
</font></span></blockquote></div><br>