mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-05 04:11:08 +00:00
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:
18
main/cli.c
18
main/cli.c
@@ -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)
|
static char *complete_fn_2(const char *line, const char *word, int pos, int state)
|
||||||
{
|
{
|
||||||
char *c;
|
char *c, *d;
|
||||||
char filename[256];
|
char filename[256];
|
||||||
|
|
||||||
if (pos != 1)
|
if (pos != 1)
|
||||||
@@ -1259,17 +1259,20 @@ static char *complete_fn_2(const char *line, const char *word, int pos, int stat
|
|||||||
else
|
else
|
||||||
snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_MODULE_DIR, word);
|
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] != '/')
|
if (c && word[0] != '/')
|
||||||
c += (strlen(ast_config_AST_MODULE_DIR) + 1);
|
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)
|
static char *complete_fn_3(const char *line, const char *word, int pos, int state)
|
||||||
{
|
{
|
||||||
char *c;
|
char *c, *d;
|
||||||
char filename[256];
|
char filename[256];
|
||||||
|
|
||||||
if (pos != 2)
|
if (pos != 2)
|
||||||
@@ -1280,12 +1283,15 @@ static char *complete_fn_3(const char *line, const char *word, int pos, int stat
|
|||||||
else
|
else
|
||||||
snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_MODULE_DIR, word);
|
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] != '/')
|
if (c && word[0] != '/')
|
||||||
c += (strlen(ast_config_AST_MODULE_DIR) + 1);
|
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[])
|
static int group_show_channels(int fd, int argc, char *argv[])
|
||||||
|
@@ -1189,68 +1189,63 @@ tilde_expand(char *txt)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* return first found file name starting by the ``text'' or NULL if no
|
* return first found file name starting by the ``text'' or NULL if no
|
||||||
* such file can be found
|
* such file can be found.
|
||||||
* value of ``state'' is ignored
|
* The first ``state'' matches are ignored.
|
||||||
*
|
*
|
||||||
* it's caller's responsibility to free returned string
|
* it's caller's responsibility to free returned string
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
filename_completion_function(const char *text, int state)
|
filename_completion_function(const char *text, int state)
|
||||||
{
|
{
|
||||||
static DIR *dir = NULL;
|
DIR *dir = NULL;
|
||||||
static char *filename = NULL, *dirname = NULL;
|
char *filename = NULL, *dirname = NULL;
|
||||||
static size_t filename_len = 0;
|
size_t filename_len = 0;
|
||||||
struct dirent *entry;
|
struct dirent *entry;
|
||||||
char *temp;
|
char *temp;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
if (state == 0 || dir == NULL) {
|
temp = strrchr(text, '/');
|
||||||
if (dir != NULL) {
|
if (temp) {
|
||||||
closedir(dir);
|
temp++;
|
||||||
dir = NULL;
|
filename = realloc(filename, strlen(temp) + 1);
|
||||||
}
|
(void) strcpy(filename, temp);
|
||||||
temp = strrchr(text, '/');
|
len = temp - text; /* including last slash */
|
||||||
if (temp) {
|
dirname = realloc(dirname, len + 1);
|
||||||
temp++;
|
(void) strncpy(dirname, text, len);
|
||||||
filename = realloc(filename, strlen(temp) + 1);
|
dirname[len] = '\0';
|
||||||
(void) strcpy(filename, temp);
|
} else {
|
||||||
len = temp - text; /* including last slash */
|
filename = strdup(text);
|
||||||
dirname = realloc(dirname, len + 1);
|
dirname = NULL;
|
||||||
(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 */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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 */
|
/* find the match */
|
||||||
while ((entry = readdir(dir)) != NULL) {
|
while ((entry = readdir(dir)) != NULL) {
|
||||||
/* otherwise, get first entry where first */
|
/* otherwise, get first entry where first */
|
||||||
/* filename_len characters are equal */
|
/* filename_len characters are equal */
|
||||||
if (entry->d_name[0] == filename[0]
|
if (
|
||||||
#if defined(__SVR4) || defined(__linux__)
|
#if defined(__SVR4) || defined(__linux__)
|
||||||
&& strlen(entry->d_name) >= filename_len
|
strlen(entry->d_name) >= filename_len
|
||||||
#else
|
#else
|
||||||
&& entry->d_namlen >= filename_len
|
entry->d_namlen >= filename_len
|
||||||
#endif
|
#endif
|
||||||
&& strncmp(entry->d_name, filename,
|
&& strncmp(entry->d_name, filename,
|
||||||
filename_len) == 0)
|
filename_len) == 0
|
||||||
|
&& (state-- == 0))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1272,6 +1267,7 @@ filename_completion_function(const char *text, int state)
|
|||||||
strcat(temp, "/"); /* safe */
|
strcat(temp, "/"); /* safe */
|
||||||
} else
|
} else
|
||||||
temp = NULL;
|
temp = NULL;
|
||||||
|
closedir(dir);
|
||||||
|
|
||||||
return (temp);
|
return (temp);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user