33 #if defined (_AIX) && !defined (__GNUC__)
42 # define alloca(n) __builtin_alloca (n)
48 extern char *alloca ();
53 #if !defined(lint) && !defined(SCCSID)
56 #include <sys/types.h>
79 #include "filecomplete.h"
81 static const Char break_chars[] = {
' ',
'\t',
'\n',
'"',
'\\',
'\'',
'`',
'@',
82 '$',
'>',
'<',
'=',
';',
'|',
'&',
'{',
'(',
'\0' };
96 fn_tilde_expand(
const char *txt)
98 #if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT)
109 temp = strchr(txt + 1,
'/');
111 temp = strdup(txt + 1);
116 len = (size_t)(temp - txt + 1);
117 temp = el_malloc(len *
sizeof(*temp));
120 (void)strncpy(temp, txt + 1, len - 2);
121 temp[len - 2] =
'\0';
124 #ifdef HAVE_GETPW_R_POSIX
125 if (getpwuid_r(getuid(), &pwres, pwbuf,
sizeof(pwbuf),
128 #elif HAVE_GETPW_R_DRAFT
129 pass = getpwuid_r(getuid(), &pwres, pwbuf,
sizeof(pwbuf));
131 pass = getpwuid(getuid());
134 #ifdef HAVE_GETPW_R_POSIX
135 if (getpwnam_r(temp, &pwres, pwbuf,
sizeof(pwbuf), &pass) != 0)
137 #elif HAVE_GETPW_R_DRAFT
138 pass = getpwnam_r(temp, &pwres, pwbuf,
sizeof(pwbuf));
140 pass = getpwnam(temp);
151 len = strlen(pass->pw_dir) + 1 + strlen(txt) + 1;
152 temp = el_malloc(len *
sizeof(*temp));
155 (void)snprintf(temp, len,
"%s/%s", pass->pw_dir, txt);
169 fn_filename_completion_function(
const char *text,
int state)
171 static DIR *dir = NULL;
172 static char *filename = NULL, *dirname = NULL, *dirpath = NULL;
173 static size_t filename_len = 0;
174 struct dirent *
entry;
178 if (state == 0 || dir == NULL) {
179 temp = strrchr(text,
'/');
183 nptr = el_realloc(filename, (strlen(temp) + 1) *
191 (void)strcpy(filename, temp);
192 len = (size_t)(temp - text);
194 nptr = el_realloc(dirname, (len + 1) *
202 (void)strncpy(dirname, text, len);
209 filename = strdup(text);
210 if (filename == NULL)
226 if (dirname == NULL) {
227 if ((dirname = strdup(
"")) == NULL)
229 dirpath = strdup(
"./");
230 }
else if (*dirname ==
'~')
231 dirpath = fn_tilde_expand(dirname);
233 dirpath = strdup(dirname);
238 dir = opendir(dirpath);
243 filename_len = filename ? strlen(filename) : 0;
247 while ((entry = readdir(dir)) != NULL) {
249 if (entry->d_name[0] ==
'.' && (!entry->d_name[1]
250 || (entry->d_name[1] ==
'.' && !entry->d_name[2])))
252 if (filename_len == 0)
256 if (entry->d_name[0] == filename[0]
257 #
if HAVE_STRUCT_DIRENT_D_NAMLEN
258 && entry->d_namlen >= filename_len
260 && strlen(entry->d_name) >= filename_len
262 && strncmp(entry->d_name, filename,
269 #if HAVE_STRUCT_DIRENT_D_NAMLEN
270 len = entry->d_namlen;
272 len = strlen(entry->d_name);
275 len = strlen(dirname) + len + 1;
276 temp = el_malloc(len *
sizeof(*temp));
279 (void)snprintf(temp, len,
"%s%s", dirname, entry->d_name);
291 append_char_function(
const char *
name)
294 char *expname = *name ==
'~' ? fn_tilde_expand(name) : NULL;
295 const char *rs =
" ";
297 if (stat(expname ? expname : name, &stbuf) == -1)
299 if (S_ISDIR(stbuf.st_mode))
310 char ** completion_matches(
const char *,
char *(*)(
const char *,
int));
312 completion_matches(
const char *text,
char *(*genfunc)(
const char *,
int))
314 char **match_list = NULL, *retstr, *prevstr;
315 size_t match_list_len, max_equal, which,
i;
320 while ((retstr = (*genfunc) (text, (
int)matches)) != NULL) {
322 if (matches + 3 >= match_list_len) {
324 while (matches + 3 >= match_list_len)
325 match_list_len <<= 1;
326 nmatch_list = el_realloc(match_list,
327 match_list_len *
sizeof(*nmatch_list));
328 if (nmatch_list == NULL) {
332 match_list = nmatch_list;
335 match_list[++matches] = retstr;
343 prevstr = match_list[1];
344 max_equal = strlen(prevstr);
345 for (; which <= matches; which++) {
346 for (i = 0; i < max_equal &&
347 prevstr[
i] == match_list[which][
i]; i++)
352 retstr = el_malloc((max_equal + 1) *
sizeof(*retstr));
353 if (retstr == NULL) {
357 (void)strncpy(retstr, match_list[1], max_equal);
358 retstr[max_equal] =
'\0';
359 match_list[0] = retstr;
362 match_list[matches + 1] = NULL;
371 _fn_qsort_string_compare(
const void *i1,
const void *i2)
373 const char *s1 = ((
const char *
const *)i1)[0];
374 const char *s2 = ((
const char *
const *)i2)[0];
376 return strcasecmp(s1, s2);
388 fn_display_match_list (
EditLine *el,
char **matches,
size_t num,
size_t width)
390 size_t line, lines, col, cols, thisguy;
391 int screenwidth = el->el_terminal.t_size.h;
401 cols = (size_t)screenwidth / (width + 1);
406 lines = (num + cols - 1) / cols;
409 qsort(matches, num,
sizeof(
char *), _fn_qsort_string_compare);
414 for (line = 0; line < lines; line++) {
415 for (col = 0; col < cols; col++) {
416 thisguy = line + col * lines;
419 (void)fprintf(el->el_outfile,
"%s%-*s",
420 col == 0 ?
"" :
" ", (
int)width, matches[thisguy]);
422 (void)fprintf(el->el_outfile,
"\n");
440 char *(*complet_func)(
const char *,
int),
441 char **(*attempted_completion_function)(
const char *,
int,
int),
442 const Char *word_break,
const Char *special_prefixes,
443 const char *(*app_func)(
const char *),
size_t query_items,
444 int *completion_type,
int *over,
int *point,
int *end)
451 int what_to_do =
'\t';
452 int retval = CC_NORM;
454 if (el->el_state.lastcmd == el->el_state.thiscmd)
458 if (completion_type != NULL)
459 *completion_type = what_to_do;
462 complet_func = fn_filename_completion_function;
464 app_func = append_char_function;
467 li = FUN(el,line)(el);
469 while (ctemp > li->buffer
470 && !Strchr(word_break, ctemp[-1])
471 && (!special_prefixes || !Strchr(special_prefixes, ctemp[-1]) ) )
474 len = (size_t)(li->cursor - ctemp);
475 #if defined(__SSP__) || defined(__SSP_ALL__)
476 temp = el_malloc((len + 1) *
sizeof(*temp));
478 temp = alloca((len + 1) *
sizeof(*temp));
480 (void)Strncpy(temp, ctemp, len);
486 *point = (int)(li->cursor - li->buffer);
488 *end = (int)(li->lastchar - li->buffer);
490 if (attempted_completion_function) {
491 int cur_off = (int)(li->cursor - li->buffer);
492 matches = (*attempted_completion_function)(
493 ct_encode_string(temp, &el->el_scratch),
494 cur_off - (int)len, cur_off);
497 if (!attempted_completion_function ||
498 (over != NULL && !*over && !matches))
499 matches = completion_matches(
500 ct_encode_string(temp, &el->el_scratch), complet_func);
507 size_t matches_num, maxlen, match_len, match_display=1;
514 if (matches[0][0] !=
'\0') {
515 el_deletestr(el, (
int) len);
516 FUN(el,insertstr)(el,
517 ct_decode_string(matches[0], &el->el_scratch));
520 if (what_to_do ==
'?')
521 goto display_matches;
523 if (matches[2] == NULL && strcmp(matches[0], matches[1]) == 0) {
529 FUN(el,insertstr)(el,
530 ct_decode_string((*app_func)(matches[0]),
532 }
else if (what_to_do ==
'!') {
539 for(i = 1, maxlen = 0; matches[
i]; i++) {
540 match_len = strlen(matches[i]);
541 if (match_len > maxlen)
545 matches_num = (size_t)(i - 1);
548 (void)fprintf(el->el_outfile,
"\n");
554 if (matches_num > query_items) {
555 (void)fprintf(el->el_outfile,
556 "Display all %zu possibilities? (y or n) ",
558 (void)fflush(el->el_outfile);
559 if (getc(stdin) !=
'y')
561 (void)fprintf(el->el_outfile,
"\n");
572 fn_display_match_list(el, matches,
573 matches_num+1, maxlen);
575 retval = CC_REDISPLAY;
576 }
else if (matches[0][0]) {
591 for (i = 0; matches[
i]; i++)
596 #if defined(__SSP__) || defined(__SSP_ALL__)
607 _el_fn_complete(
EditLine *el,
int ch __attribute__((__unused__)))
609 return (
unsigned char)fn_complete(el, NULL, NULL,
610 break_chars, NULL, NULL, (
size_t)100,
611 NULL, NULL, NULL, NULL);