version 1.3, 1997/02/05 04:55:14 |
version 1.4, 1997/03/14 04:32:13 |
|
|
/* $OpenBSD$ */ |
/* $OpenBSD$ */ |
/* $NetBSD: complete.c,v 1.2 1997/02/01 10:44:57 lukem Exp $ */ |
/* $NetBSD: complete.c,v 1.3 1997/03/13 06:23:13 lukem Exp $ */ |
|
|
/*- |
/*- |
* Copyright (c) 1997 The NetBSD Foundation, Inc. |
* Copyright (c) 1997 The NetBSD Foundation, Inc. |
|
|
comparstr(a, b) |
comparstr(a, b) |
const void *a, *b; |
const void *a, *b; |
{ |
{ |
return strcmp(*(char **)a, *(char **)b); |
return (strcmp(*(char **)a, *(char **)b)); |
} |
} |
|
|
/* |
/* |
|
|
|
|
wordlen = strlen(word); |
wordlen = strlen(word); |
if (words->sl_cur == 0) |
if (words->sl_cur == 0) |
return CC_ERROR; /* no choices available */ |
return (CC_ERROR); /* no choices available */ |
|
|
if (words->sl_cur == 1) { /* only once choice available */ |
if (words->sl_cur == 1) { /* only once choice available */ |
strcpy(insertstr, words->sl_str[0]); |
strcpy(insertstr, words->sl_str[0]); |
if (el_insertstr(el, insertstr + wordlen) == -1) |
if (el_insertstr(el, insertstr + wordlen) == -1) |
return CC_ERROR; |
return (CC_ERROR); |
else |
else |
return CC_REFRESH; |
return (CC_REFRESH); |
} |
} |
|
|
if (!list) { |
if (!list) { |
|
|
strncpy(insertstr, lastmatch, matchlen); |
strncpy(insertstr, lastmatch, matchlen); |
insertstr[matchlen] = '\0'; |
insertstr[matchlen] = '\0'; |
if (el_insertstr(el, insertstr + wordlen) == -1) |
if (el_insertstr(el, insertstr + wordlen) == -1) |
return CC_ERROR; |
return (CC_ERROR); |
else |
else |
/* |
/* |
* XXX: really want CC_REFRESH_BEEP |
* XXX: really want CC_REFRESH_BEEP |
*/ |
*/ |
return CC_REFRESH; |
return (CC_REFRESH); |
} |
} |
} |
} |
|
|
putchar('\n'); |
putchar('\n'); |
qsort(words->sl_str, words->sl_cur, sizeof(char *), comparstr); |
qsort(words->sl_str, words->sl_cur, sizeof(char *), comparstr); |
list_vertical(words); |
list_vertical(words); |
return CC_REDISPLAY; |
return (CC_REDISPLAY); |
} |
} |
|
|
/* |
/* |
|
|
|
|
rv = complete_ambiguous(word, list, words); |
rv = complete_ambiguous(word, list, words); |
sl_free(words, 0); |
sl_free(words, 0); |
return rv; |
return (rv); |
} |
} |
|
|
/* |
/* |
|
|
} |
} |
|
|
if ((dd = opendir(dir)) == NULL) |
if ((dd = opendir(dir)) == NULL) |
return CC_ERROR; |
return (CC_ERROR); |
|
|
words = sl_init(); |
words = sl_init(); |
|
|
|
|
|
|
rv = complete_ambiguous(file, list, words); |
rv = complete_ambiguous(file, list, words); |
sl_free(words, 1); |
sl_free(words, 1); |
return rv; |
return (rv); |
} |
} |
|
|
/* |
/* |
|
|
{ |
{ |
static StringList *dirlist; |
static StringList *dirlist; |
static char lastdir[MAXPATHLEN]; |
static char lastdir[MAXPATHLEN]; |
static int ftpdslashbug; |
|
StringList *words; |
StringList *words; |
char dir[MAXPATHLEN]; |
char dir[MAXPATHLEN]; |
char *file, *cp; |
char *file, *cp; |
int i, offset; |
int i; |
unsigned char rv; |
unsigned char rv; |
|
|
char *dummyargv[] = { "complete", dir, NULL }; |
char *dummyargv[] = { "complete", dir, NULL }; |
|
|
offset = 0; |
|
if ((file = strrchr(word, '/')) == NULL) { |
if ((file = strrchr(word, '/')) == NULL) { |
strcpy(dir, "."); |
(void)strcpy(dir, "."); |
file = word; |
file = word; |
} else { |
} else { |
if (file == word) |
cp = file; |
strcpy(dir, "/"); |
while (*cp == '/' && cp > word) |
else { |
cp--; |
offset = file - word; |
if (cp == word) { |
strncpy(dir, word, offset); |
dir[0] = '/'; |
dir[offset] = '\0'; |
dir[1] = '\0'; |
offset++; |
} else { |
|
(void)strncpy(dir, word, cp - word + 1); |
|
dir[cp - word + 1] = '\0'; |
} |
} |
file++; |
file++; |
} |
} |
|
|
if (dirchange || strcmp(dir, lastdir) != 0) { /* dir not cached */ |
if (dirchange || strcmp(dir, lastdir) != 0) { /* dir not cached */ |
|
char *emesg; |
|
int dirlen, ftpdslashbug; |
|
|
|
dirlen = strlen(dir); |
|
ftpdslashbug = 0; |
|
if (strcmp(dir, "/") == 0) |
|
ftpdslashbug = 1; |
|
else if (strcmp(dir, ".") == 0) |
|
dirlen = 0; |
|
else |
|
dirlen++; |
if (dirlist != NULL) |
if (dirlist != NULL) |
sl_free(dirlist, 1); |
sl_free(dirlist, 1); |
dirlist = sl_init(); |
dirlist = sl_init(); |
|
|
ftpdslashbug = 0; |
|
mflag = 1; |
mflag = 1; |
while ((cp = remglob(dummyargv, 0)) != NULL) { |
emesg = NULL; |
|
while ((cp = remglob(dummyargv, 0, &emesg)) != NULL) { |
char *tcp; |
char *tcp; |
|
|
if (!mflag) |
if (!mflag) |
|
|
/* |
/* |
* Work around ftpd(1) bug, which puts a // instead |
* Work around ftpd(1) bug, which puts a // instead |
* of / in front of each filename returned by "NLST /". |
* of / in front of each filename returned by "NLST /". |
* Without this, remote completes of / look ugly. |
* Without this, remote completes of / don't work. |
|
* However, only do this if the bug is present. |
*/ |
*/ |
if (dir[0] == '/' && dir[1] == '\0' && |
if (ftpdslashbug && (cp[dirlen] != '/')) |
cp[0] == '/' && cp[1] == '/') { |
ftpdslashbug = 0; |
cp++; |
tcp = strdup(cp + dirlen + ftpdslashbug); |
ftpdslashbug = 1; |
|
} |
|
tcp = strdup(cp); |
|
if (tcp == NULL) |
if (tcp == NULL) |
errx(1, "Can't allocate memory for remote dir"); |
errx(1, "Can't allocate memory for remote dir"); |
sl_add(dirlist, tcp); |
sl_add(dirlist, tcp); |
} |
} |
strcpy(lastdir, dir); |
if (emesg != NULL) { |
|
printf("\n%s\n", emesg); |
|
return (CC_REDISPLAY); |
|
} |
|
(void)strcpy(lastdir, dir); |
dirchange = 0; |
dirchange = 0; |
} |
} |
|
|
words = sl_init(); |
words = sl_init(); |
for (i = 0; i < dirlist->sl_cur; i++) { |
for (i = 0; i < dirlist->sl_cur; i++) { |
cp = dirlist->sl_str[i]; |
cp = dirlist->sl_str[i]; |
if (strlen(word) > strlen(cp)) |
if (strlen(file) > strlen(cp)) |
continue; |
continue; |
if (strncmp(word, cp, strlen(word)) == 0) |
if (strncmp(file, cp, strlen(file)) == 0) |
sl_add(words, cp + offset + ftpdslashbug); |
sl_add(words, cp); |
} |
} |
rv = complete_ambiguous(file, list, words); |
rv = complete_ambiguous(file, list, words); |
sl_free(words, 0); |
sl_free(words, 0); |
return rv; |
return (rv); |
} |
} |
|
|
/* |
/* |
|
|
lf = el_line(el); |
lf = el_line(el); |
len = lf->lastchar - lf->buffer; |
len = lf->lastchar - lf->buffer; |
if (len >= sizeof(line)) |
if (len >= sizeof(line)) |
return CC_ERROR; |
return (CC_ERROR); |
strncpy(line, lf->buffer, len); |
strncpy(line, lf->buffer, len); |
line[len] = '\0'; |
line[len] = '\0'; |
cursor_pos = line + (lf->cursor - lf->buffer); |
cursor_pos = line + (lf->cursor - lf->buffer); |
|
|
makeargv(); /* build argc/argv of current line */ |
makeargv(); /* build argc/argv of current line */ |
|
|
if (cursor_argo >= sizeof(word)) |
if (cursor_argo >= sizeof(word)) |
return CC_ERROR; |
return (CC_ERROR); |
|
|
dolist = 0; |
dolist = 0; |
/* if cursor and word is same, list alternatives */ |
/* if cursor and word is same, list alternatives */ |
|
|
word[cursor_argo] = '\0'; |
word[cursor_argo] = '\0'; |
|
|
if (cursor_argc == 0) |
if (cursor_argc == 0) |
return complete_command(word, dolist); |
return (complete_command(word, dolist)); |
|
|
c = getcmd(margv[0]); |
c = getcmd(margv[0]); |
if (c == (struct cmd *)-1 || c == 0) |
if (c == (struct cmd *)-1 || c == 0) |
return CC_ERROR; |
return (CC_ERROR); |
celems = strlen(c->c_complete); |
celems = strlen(c->c_complete); |
|
|
/* check for 'continuation' completes (which are uppercase) */ |
/* check for 'continuation' completes (which are uppercase) */ |
|
|
cursor_argc = celems; |
cursor_argc = celems; |
|
|
if (cursor_argc > celems) |
if (cursor_argc > celems) |
return CC_ERROR; |
return (CC_ERROR); |
|
|
switch (c->c_complete[cursor_argc - 1]) { |
switch (c->c_complete[cursor_argc - 1]) { |
case 'l': /* local complete */ |
case 'l': /* local complete */ |
case 'L': |
case 'L': |
return complete_local(word, dolist); |
return (complete_local(word, dolist)); |
case 'r': /* remote complete */ |
case 'r': /* remote complete */ |
case 'R': |
case 'R': |
if (!connected) { |
if (!connected) { |
puts("\nMust be connected to complete"); |
puts("\nMust be connected to complete."); |
return CC_REDISPLAY; |
return (CC_REDISPLAY); |
} |
} |
return complete_remote(word, dolist); |
return (complete_remote(word, dolist)); |
case 'c': /* command complete */ |
case 'c': /* command complete */ |
case 'C': |
case 'C': |
return complete_command(word, dolist); |
return (complete_command(word, dolist)); |
case 'n': /* no complete */ |
case 'n': /* no complete */ |
default: |
default: |
return CC_ERROR; |
return (CC_ERROR); |
} |
} |
|
|
return CC_ERROR; |
return (CC_ERROR); |
} |
} |