Allow filename completion on zero-length modules, remove a memory leak, remove

a file descriptor leak, and make filename completion thread-safe.
Patched and tested by tilghman.
(Closes issue #11681)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@97350 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Tilghman Lesher
2008-01-09 00:44:14 +00:00
parent 34f994f017
commit 1f14e0cf39
2 changed files with 51 additions and 49 deletions

View File

@@ -1248,7 +1248,7 @@ static char *complete_mod_4(const char *line, const char *word, int pos, int sta
static char *complete_fn_2(const char *line, const char *word, int pos, int state)
{
char *c;
char *c, *d;
char filename[256];
if (pos != 1)
@@ -1259,17 +1259,20 @@ static char *complete_fn_2(const char *line, const char *word, int pos, int stat
else
snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_MODULE_DIR, word);
c = filename_completion_function(filename, state);
c = d = filename_completion_function(filename, state);
if (c && word[0] != '/')
c += (strlen(ast_config_AST_MODULE_DIR) + 1);
if (c)
c = strdup(c);
free(d);
return c ? strdup(c) : c;
return c;
}
static char *complete_fn_3(const char *line, const char *word, int pos, int state)
{
char *c;
char *c, *d;
char filename[256];
if (pos != 2)
@@ -1280,12 +1283,15 @@ static char *complete_fn_3(const char *line, const char *word, int pos, int stat
else
snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_MODULE_DIR, word);
c = filename_completion_function(filename, state);
c = d = filename_completion_function(filename, state);
if (c && word[0] != '/')
c += (strlen(ast_config_AST_MODULE_DIR) + 1);
if (c)
c = strdup(c);
free(d);
return c ? strdup(c) : c;
return c;
}
static int group_show_channels(int fd, int argc, char *argv[])

View File

@@ -1189,68 +1189,63 @@ tilde_expand(char *txt)
/*
* return first found file name starting by the ``text'' or NULL if no
* such file can be found
* value of ``state'' is ignored
* such file can be found.
* The first ``state'' matches are ignored.
*
* it's caller's responsibility to free returned string
*/
char *
filename_completion_function(const char *text, int state)
{
static DIR *dir = NULL;
static char *filename = NULL, *dirname = NULL;
static size_t filename_len = 0;
DIR *dir = NULL;
char *filename = NULL, *dirname = NULL;
size_t filename_len = 0;
struct dirent *entry;
char *temp;
size_t len;
int count = 0;
if (state == 0 || dir == NULL) {
if (dir != NULL) {
closedir(dir);
dir = NULL;
}
temp = strrchr(text, '/');
if (temp) {
temp++;
filename = realloc(filename, strlen(temp) + 1);
(void) strcpy(filename, temp);
len = temp - text; /* including last slash */
dirname = realloc(dirname, len + 1);
(void) strncpy(dirname, text, len);
dirname[len] = '\0';
} else {
filename = strdup(text);
dirname = NULL;
}
/* support for ``~user'' syntax */
if (dirname && *dirname == '~') {
temp = tilde_expand(dirname);
dirname = realloc(dirname, strlen(temp) + 1);
(void) strcpy(dirname, temp); /* safe */
free(temp); /* no longer needed */
}
/* will be used in cycle */
filename_len = strlen(filename);
if (filename_len == 0)
return (NULL); /* no expansion possible */
dir = opendir(dirname ? dirname : ".");
if (!dir)
return (NULL); /* cannot open the directory */
temp = strrchr(text, '/');
if (temp) {
temp++;
filename = realloc(filename, strlen(temp) + 1);
(void) strcpy(filename, temp);
len = temp - text; /* including last slash */
dirname = realloc(dirname, len + 1);
(void) strncpy(dirname, text, len);
dirname[len] = '\0';
} else {
filename = strdup(text);
dirname = NULL;
}
/* support for ``~user'' syntax */
if (dirname && *dirname == '~') {
temp = tilde_expand(dirname);
dirname = realloc(dirname, strlen(temp) + 1);
(void) strcpy(dirname, temp); /* safe */
free(temp); /* no longer needed */
}
/* will be used in cycle */
filename_len = strlen(filename);
dir = opendir(dirname ? dirname : ".");
if (!dir)
return (NULL); /* cannot open the directory */
/* find the match */
while ((entry = readdir(dir)) != NULL) {
/* otherwise, get first entry where first */
/* filename_len characters are equal */
if (entry->d_name[0] == filename[0]
if (
#if defined(__SVR4) || defined(__linux__)
&& strlen(entry->d_name) >= filename_len
strlen(entry->d_name) >= filename_len
#else
&& entry->d_namlen >= filename_len
entry->d_namlen >= filename_len
#endif
&& strncmp(entry->d_name, filename,
filename_len) == 0)
filename_len) == 0
&& (state-- == 0))
break;
}
@@ -1272,6 +1267,7 @@ filename_completion_function(const char *text, int state)
strcat(temp, "/"); /* safe */
} else
temp = NULL;
closedir(dir);
return (temp);
}