summaryrefslogtreecommitdiffstats
path: root/lib/libedit/filecomplete.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libedit/filecomplete.c')
-rw-r--r--lib/libedit/filecomplete.c305
1 files changed, 169 insertions, 136 deletions
diff --git a/lib/libedit/filecomplete.c b/lib/libedit/filecomplete.c
index bf0d759..10d44e4 100644
--- a/lib/libedit/filecomplete.c
+++ b/lib/libedit/filecomplete.c
@@ -1,3 +1,5 @@
+/* $NetBSD: filecomplete.c,v 1.34 2014/10/18 15:07:02 riz Exp $ */
+
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -25,10 +27,12 @@
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
- *
- * $NetBSD: filecomplete.c,v 1.19 2010/06/01 18:20:26 christos Exp $
*/
+#include "config.h"
+#if !defined(lint) && !defined(SCCSID)
+__RCSID("$NetBSD: filecomplete.c,v 1.34 2014/10/18 15:07:02 riz Exp $");
+#endif /* not lint && not SCCSID */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -44,16 +48,16 @@ __FBSDID("$FreeBSD$");
#include <limits.h>
#include <errno.h>
#include <fcntl.h>
-#include <vis.h>
+
#include "el.h"
#include "fcns.h" /* for EL_NUM_FCNS */
#include "histedit.h"
#include "filecomplete.h"
-static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`',
- '>', '<', '=', ';', '|', '&', '{', '(', '\0' };
+static const Char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@',
+ '$', '>', '<', '=', ';', '|', '&', '{', '(', '\0' };
/* Tilde is deliberately omitted here, we treat it specially. */
-static char extra_quote_chars[] = { ')', '}', '*', '?', '[', '$', '\0' };
+static const Char extra_quote_chars[] = { ')', '}', '*', '?', '[', '$', '\0' };
/********************************/
@@ -64,18 +68,21 @@ static char extra_quote_chars[] = { ')', '}', '*', '?', '[', '$', '\0' };
* if ``user'' isn't valid user name or ``txt'' doesn't start
* w/ '~', returns pointer to strdup()ed copy of ``txt''
*
- * it's callers's responsibility to free() returned string
+ * it's the caller's responsibility to free() the returned string
*/
char *
fn_tilde_expand(const char *txt)
{
- struct passwd pwres, *pass;
+#if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT)
+ struct passwd pwres;
+ char pwbuf[1024];
+#endif
+ struct passwd *pass;
char *temp;
size_t len = 0;
- char pwbuf[1024];
if (txt[0] != '~')
- return (strdup(txt));
+ return strdup(txt);
temp = strchr(txt + 1, '/');
if (temp == NULL) {
@@ -83,34 +90,49 @@ fn_tilde_expand(const char *txt)
if (temp == NULL)
return NULL;
} else {
- len = temp - txt + 1; /* text until string after slash */
- temp = malloc(len);
+ /* text until string after slash */
+ len = (size_t)(temp - txt + 1);
+ temp = el_malloc(len * sizeof(*temp));
if (temp == NULL)
return NULL;
(void)strncpy(temp, txt + 1, len - 2);
temp[len - 2] = '\0';
}
if (temp[0] == 0) {
- if (getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf), &pass) != 0)
- pass = NULL;
+#ifdef HAVE_GETPW_R_POSIX
+ if (getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf),
+ &pass) != 0)
+ pass = NULL;
+#elif HAVE_GETPW_R_DRAFT
+ pass = getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf));
+#else
+ pass = getpwuid(getuid());
+#endif
} else {
+#ifdef HAVE_GETPW_R_POSIX
if (getpwnam_r(temp, &pwres, pwbuf, sizeof(pwbuf), &pass) != 0)
pass = NULL;
+#elif HAVE_GETPW_R_DRAFT
+ pass = getpwnam_r(temp, &pwres, pwbuf, sizeof(pwbuf));
+#else
+ pass = getpwnam(temp);
+#endif
}
- free(temp); /* value no more needed */
+ el_free(temp); /* value no more needed */
if (pass == NULL)
- return (strdup(txt));
+ return strdup(txt);
- /* update pointer txt to point at string immediately following */
+ /* update pointer txt to point at string immedially following */
/* first slash */
txt += len;
- temp = malloc(strlen(pass->pw_dir) + 1 + strlen(txt) + 1);
+ len = strlen(pass->pw_dir) + 1 + strlen(txt) + 1;
+ temp = el_malloc(len * sizeof(*temp));
if (temp == NULL)
return NULL;
- (void)sprintf(temp, "%s/%s", pass->pw_dir, txt);
+ (void)snprintf(temp, len, "%s/%s", pass->pw_dir, txt);
- return (temp);
+ return temp;
}
@@ -119,7 +141,7 @@ fn_tilde_expand(const char *txt)
* such file can be found
* value of ``state'' is ignored
*
- * it's caller's responsibility to free returned string
+ * it's the caller's responsibility to free the returned string
*/
char *
fn_filename_completion_function(const char *text, int state)
@@ -136,19 +158,21 @@ fn_filename_completion_function(const char *text, int state)
if (temp) {
char *nptr;
temp++;
- nptr = realloc(filename, strlen(temp) + 1);
+ nptr = el_realloc(filename, (strlen(temp) + 1) *
+ sizeof(*nptr));
if (nptr == NULL) {
- free(filename);
+ el_free(filename);
filename = NULL;
return NULL;
}
filename = nptr;
(void)strcpy(filename, temp);
- len = temp - text; /* including last slash */
+ len = (size_t)(temp - text); /* including last slash */
- nptr = realloc(dirname, len + 1);
+ nptr = el_realloc(dirname, (len + 1) *
+ sizeof(*nptr));
if (nptr == NULL) {
- free(dirname);
+ el_free(dirname);
dirname = NULL;
return NULL;
}
@@ -156,7 +180,7 @@ fn_filename_completion_function(const char *text, int state)
(void)strncpy(dirname, text, len);
dirname[len] = '\0';
} else {
- free(filename);
+ el_free(filename);
if (*text == 0)
filename = NULL;
else {
@@ -164,7 +188,7 @@ fn_filename_completion_function(const char *text, int state)
if (filename == NULL)
return NULL;
}
- free(dirname);
+ el_free(dirname);
dirname = NULL;
}
@@ -175,7 +199,7 @@ fn_filename_completion_function(const char *text, int state)
/* support for ``~user'' syntax */
- free(dirpath);
+ el_free(dirpath);
dirpath = NULL;
if (dirname == NULL) {
if ((dirname = strdup("")) == NULL)
@@ -191,7 +215,7 @@ fn_filename_completion_function(const char *text, int state)
dir = opendir(dirpath);
if (!dir)
- return (NULL); /* cannot open the directory */
+ return NULL; /* cannot open the directory */
/* will be used in cycle */
filename_len = filename ? strlen(filename) : 0;
@@ -208,26 +232,36 @@ fn_filename_completion_function(const char *text, int state)
/* otherwise, get first entry where first */
/* filename_len characters are equal */
if (entry->d_name[0] == filename[0]
+#if HAVE_STRUCT_DIRENT_D_NAMLEN
&& entry->d_namlen >= filename_len
+#else
+ && strlen(entry->d_name) >= filename_len
+#endif
&& strncmp(entry->d_name, filename,
filename_len) == 0)
break;
}
if (entry) { /* match found */
+
+#if HAVE_STRUCT_DIRENT_D_NAMLEN
len = entry->d_namlen;
+#else
+ len = strlen(entry->d_name);
+#endif
- temp = malloc(strlen(dirname) + len + 1);
+ len = strlen(dirname) + len + 1;
+ temp = el_malloc(len * sizeof(*temp));
if (temp == NULL)
return NULL;
- (void)sprintf(temp, "%s%s", dirname, entry->d_name);
+ (void)snprintf(temp, len, "%s%s", dirname, entry->d_name);
} else {
(void)closedir(dir);
dir = NULL;
temp = NULL;
}
- return (temp);
+ return temp;
}
@@ -244,11 +278,9 @@ append_char_function(const char *name)
rs = "/";
out:
if (expname)
- free(expname);
+ el_free(expname);
return rs;
}
-
-
/*
* returns list of completions for text given
* non-static for readline.
@@ -269,10 +301,10 @@ completion_matches(const char *text, char *(*genfunc)(const char *, int))
char **nmatch_list;
while (matches + 3 >= match_list_len)
match_list_len <<= 1;
- nmatch_list = realloc(match_list,
- match_list_len * sizeof(char *));
+ nmatch_list = el_realloc(match_list,
+ match_list_len * sizeof(*nmatch_list));
if (nmatch_list == NULL) {
- free(match_list);
+ el_free(match_list);
return NULL;
}
match_list = nmatch_list;
@@ -295,9 +327,9 @@ completion_matches(const char *text, char *(*genfunc)(const char *, int))
max_equal = i;
}
- retstr = malloc(max_equal + 1);
+ retstr = el_malloc((max_equal + 1) * sizeof(*retstr));
if (retstr == NULL) {
- free(match_list);
+ el_free(match_list);
return NULL;
}
(void)strncpy(retstr, match_list[1], max_equal);
@@ -305,12 +337,11 @@ completion_matches(const char *text, char *(*genfunc)(const char *, int))
match_list[0] = retstr;
/* add NULL as last pointer to the array */
- match_list[matches + 1] = (char *) NULL;
+ match_list[matches + 1] = NULL;
- return (match_list);
+ return match_list;
}
-
/*
* Sort function for qsort(). Just wrapper around strcasecmp().
*/
@@ -323,47 +354,53 @@ _fn_qsort_string_compare(const void *i1, const void *i2)
return strcasecmp(s1, s2);
}
-
/*
* Display list of strings in columnar format on readline's output stream.
- * 'matches' is list of strings, 'len' is number of strings in 'matches',
- * 'max' is maximum length of string in 'matches'.
+ * 'matches' is list of strings, 'num' is number of strings in 'matches',
+ * 'width' is maximum length of string in 'matches'.
+ *
+ * matches[0] is not one of the match strings, but it is counted in
+ * num, so the strings are matches[1] *through* matches[num-1].
*/
void
-fn_display_match_list(EditLine *el, char **matches, size_t len, size_t max)
+fn_display_match_list (EditLine *el, char **matches, size_t num, size_t width)
{
- size_t i, idx, limit, count;
- int screenwidth = el->el_term.t_size.h;
+ size_t line, lines, col, cols, thisguy;
+ int screenwidth = el->el_terminal.t_size.h;
+
+ /* Ignore matches[0]. Avoid 1-based array logic below. */
+ matches++;
+ num--;
+
+ /*
+ * Find out how many entries can be put on one line; count
+ * with one space between strings the same way it's printed.
+ */
+ cols = (size_t)screenwidth / (width + 1);
+ if (cols == 0)
+ cols = 1;
+
+ /* how many lines of output, rounded up */
+ lines = (num + cols - 1) / cols;
+
+ /* Sort the items. */
+ qsort(matches, num, sizeof(char *), _fn_qsort_string_compare);
/*
- * Find out how many entries can be put on one line, count
- * with two spaces between strings.
+ * On the ith line print elements i, i+lines, i+lines*2, etc.
*/
- limit = screenwidth / (max + 2);
- if (limit == 0)
- limit = 1;
-
- /* how many lines of output */
- count = len / limit;
- if (count * limit < len)
- count++;
-
- /* Sort the items if they are not already sorted. */
- qsort(&matches[1], len, sizeof(char *), _fn_qsort_string_compare);
-
- idx = 1;
- for(; count > 0; count--) {
- int more = limit > 0 && matches[0];
- for(i = 0; more; idx++) {
- more = ++i < limit && matches[idx + 1];
- (void)fprintf(el->el_outfile, "%-*s%s", (int)max,
- matches[idx], more ? " " : "");
+ for (line = 0; line < lines; line++) {
+ for (col = 0; col < cols; col++) {
+ thisguy = line + col * lines;
+ if (thisguy >= num)
+ break;
+ (void)fprintf(el->el_outfile, "%s%-*s",
+ col == 0 ? "" : " ", (int)width, matches[thisguy]);
}
(void)fprintf(el->el_outfile, "\n");
}
}
-
/*
* Complete the word at or before point,
* 'what_to_do' says what to do with the completion.
@@ -380,18 +417,18 @@ int
fn_complete(EditLine *el,
char *(*complet_func)(const char *, int),
char **(*attempted_completion_function)(const char *, int, int),
- const char *word_break, const char *special_prefixes,
+ const Char *word_break, const Char *special_prefixes,
const char *(*app_func)(const char *), size_t query_items,
int *completion_type, int *over, int *point, int *end,
- const char *(*find_word_start_func)(const char *, const char *),
- char *(*dequoting_func)(const char *),
+ const Char *(*find_word_start_func)(const Char *, const Char *),
+ Char *(*dequoting_func)(const Char *),
char *(*quoting_func)(const char *))
{
- const LineInfo *li;
- char *temp;
- char *dequoted_temp;
- char **matches;
- const char *ctemp;
+ const TYPE(LineInfo) *li;
+ Char *temp;
+ Char *dequoted_temp;
+ char **matches;
+ const Char *ctemp;
size_t len;
int what_to_do = '\t';
int retval = CC_NORM;
@@ -409,26 +446,20 @@ fn_complete(EditLine *el,
app_func = append_char_function;
/* We now look backwards for the start of a filename/variable word */
- li = el_line(el);
+ li = FUN(el,line)(el);
if (find_word_start_func)
ctemp = find_word_start_func(li->buffer, li->cursor);
else {
ctemp = li->cursor;
while (ctemp > li->buffer
- && !strchr(word_break, ctemp[-1])
- && (!special_prefixes || !strchr(special_prefixes, ctemp[-1]) ) )
+ && !Strchr(word_break, ctemp[-1])
+ && (!special_prefixes || !Strchr(special_prefixes, ctemp[-1]) ) )
ctemp--;
}
- len = li->cursor - ctemp;
-#if defined(__SSP__) || defined(__SSP_ALL__)
- temp = malloc(sizeof(*temp) * (len + 1));
- if (temp == NULL)
- return retval;
-#else
- temp = alloca(sizeof(*temp) * (len + 1));
-#endif
- (void)strncpy(temp, ctemp, len);
+ len = (size_t)(li->cursor - ctemp);
+ temp = el_malloc((len + 1) * sizeof(*temp));
+ (void)Strncpy(temp, ctemp, len);
temp[len] = '\0';
if (dequoting_func) {
@@ -447,13 +478,17 @@ fn_complete(EditLine *el,
if (attempted_completion_function) {
int cur_off = (int)(li->cursor - li->buffer);
- matches = (*attempted_completion_function) (dequoted_temp ? dequoted_temp : temp,
- (int)(cur_off - len), cur_off);
+ matches = (*attempted_completion_function)(
+ ct_encode_string(dequoted_temp ? dequoted_temp : temp,
+ &el->el_scratch),
+ cur_off - (int)len, cur_off);
} else
matches = 0;
if (!attempted_completion_function ||
(over != NULL && !*over && !matches))
- matches = completion_matches(dequoted_temp ? dequoted_temp : temp, complet_func);
+ matches = completion_matches(
+ ct_encode_string(dequoted_temp ? dequoted_temp : temp,
+ &el->el_scratch), complet_func);
if (over != NULL)
*over = 0;
@@ -475,23 +510,25 @@ fn_complete(EditLine *el,
goto free_matches;
} else
quoted_match = NULL;
-
el_deletestr(el, (int) len);
- el_insertstr(el, quoted_match ? quoted_match : matches[0]);
-
- free(quoted_match);
+ FUN(el,insertstr)(el,
+ ct_decode_string(quoted_match ? quoted_match :
+ matches[0] , &el->el_scratch));
}
if (what_to_do == '?')
goto display_matches;
- if (matches[2] == NULL && strcmp(matches[0], matches[1]) == 0) {
+ if (matches[2] == NULL &&
+ (matches[1] == NULL || strcmp(matches[0], matches[1]) == 0)) {
/*
* We found exact match. Add a space after
* it, unless we do filename completion and the
* object is a directory.
*/
- el_insertstr(el, (*app_func)(matches[0]));
+ FUN(el,insertstr)(el,
+ ct_decode_string((*app_func)(matches[0]),
+ &el->el_scratch));
} else if (what_to_do == '!') {
display_matches:
/*
@@ -504,7 +541,8 @@ fn_complete(EditLine *el,
if (match_len > maxlen)
maxlen = match_len;
}
- matches_num = i - 1;
+ /* matches[1] through matches[i-1] are available */
+ matches_num = (size_t)(i - 1);
/* newline to get on next line from command line */
(void)fprintf(el->el_outfile, "\n");
@@ -523,9 +561,17 @@ fn_complete(EditLine *el,
(void)fprintf(el->el_outfile, "\n");
}
- if (match_display)
- fn_display_match_list(el, matches, matches_num,
- maxlen);
+ if (match_display) {
+ /*
+ * Interface of this function requires the
+ * strings be matches[1..num-1] for compat.
+ * We have matches_num strings not counting
+ * the prefix in matches[0], so we need to
+ * add 1 to matches_num for the call.
+ */
+ fn_display_match_list(el, matches,
+ matches_num+1, maxlen);
+ }
retval = CC_REDISPLAY;
} else if (matches[0][0]) {
/*
@@ -544,18 +590,15 @@ fn_complete(EditLine *el,
free_matches:
/* free elements of array and the array itself */
for (i = 0; matches[i]; i++)
- free(matches[i]);
- free(matches);
+ el_free(matches[i]);
+ el_free(matches);
matches = NULL;
}
free(dequoted_temp);
-#if defined(__SSP__) || defined(__SSP_ALL__)
- free(temp);
-#endif
+ el_free(temp);
return retval;
}
-
/*
* el-compatible wrapper around rl_complete; needed for key binding
*/
@@ -564,30 +607,26 @@ unsigned char
_el_fn_complete(EditLine *el, int ch __attribute__((__unused__)))
{
return (unsigned char)fn_complete(el, NULL, NULL,
- break_chars, NULL, NULL, 100,
+ break_chars, NULL, NULL, (size_t)100,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL);
}
-
-static const char *
-sh_find_word_start(const char *buffer, const char *cursor)
+static const Char *
+sh_find_word_start(const Char *buffer, const Char *cursor)
{
- const char *word_start = buffer;
+ const Char *word_start = buffer;
while (buffer < cursor) {
if (*buffer == '\\')
buffer++;
- else if (strchr(break_chars, *buffer))
+ else if (Strchr(break_chars, *buffer))
word_start = buffer + 1;
-
buffer++;
}
-
return word_start;
}
-
static char *
sh_quote(const char *str)
{
@@ -595,24 +634,20 @@ sh_quote(const char *str)
int extra_len = 0;
char *quoted_str, *dst;
- if (*str == '-' || *str == '+')
- extra_len += 2;
- for (src = str; *src != '\0'; src++)
- if (strchr(break_chars, *src) ||
- strchr(extra_quote_chars, *src))
+ for (src = str; *src != '\0'; src++)
+ if (Strchr(break_chars, *src) ||
+ Strchr(extra_quote_chars, *src))
extra_len++;
quoted_str = malloc(sizeof(*quoted_str) *
- (strlen(str) + extra_len + 1));
+ (strlen(str) + extra_len + 1));
if (quoted_str == NULL)
return NULL;
dst = quoted_str;
- if (*str == '-' || *str == '+')
- *dst++ = '.', *dst++ = '/';
for (src = str; *src != '\0'; src++) {
- if (strchr(break_chars, *src) ||
- strchr(extra_quote_chars, *src))
+ if (Strchr(break_chars, *src) ||
+ Strchr(extra_quote_chars, *src))
*dst++ = '\\';
*dst++ = *src;
}
@@ -621,14 +656,13 @@ sh_quote(const char *str)
return quoted_str;
}
-
-static char *
-sh_dequote(const char *str)
+static Char *
+sh_dequote(const Char *str)
{
- char *dequoted_str, *dst;
+ Char *dequoted_str, *dst;
/* save extra space to replace \~ with ./~ */
- dequoted_str = malloc(sizeof(*dequoted_str) * (strlen(str) + 1 + 1));
+ dequoted_str = malloc(sizeof(*dequoted_str) * (Strlen(str) + 1 + 1));
if (dequoted_str == NULL)
return NULL;
@@ -652,7 +686,6 @@ sh_dequote(const char *str)
return dequoted_str;
}
-
/*
* completion function using sh quoting rules; for key binding
*/
OpenPOWER on IntegriCloud