summaryrefslogtreecommitdiff
path: root/usr.bin/ftp/complete.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/ftp/complete.c')
-rw-r--r--usr.bin/ftp/complete.c113
1 files changed, 63 insertions, 50 deletions
diff --git a/usr.bin/ftp/complete.c b/usr.bin/ftp/complete.c
index aee1b1868b1..a80b3125aff 100644
--- a/usr.bin/ftp/complete.c
+++ b/usr.bin/ftp/complete.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: complete.c,v 1.3 1997/02/05 04:55:14 millert Exp $ */
-/* $NetBSD: complete.c,v 1.2 1997/02/01 10:44:57 lukem Exp $ */
+/* $OpenBSD: complete.c,v 1.4 1997/03/14 04:32:13 millert Exp $ */
+/* $NetBSD: complete.c,v 1.3 1997/03/13 06:23:13 lukem Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
*/
#ifndef lint
-static char rcsid[] = "$OpenBSD: complete.c,v 1.3 1997/02/05 04:55:14 millert Exp $";
+static char rcsid[] = "$OpenBSD: complete.c,v 1.4 1997/03/14 04:32:13 millert Exp $";
#endif /* not lint */
/*
@@ -58,7 +58,7 @@ static int
comparstr(a, b)
const void *a, *b;
{
- return strcmp(*(char **)a, *(char **)b);
+ return (strcmp(*(char **)a, *(char **)b));
}
/*
@@ -83,14 +83,14 @@ complete_ambiguous(word, list, words)
wordlen = strlen(word);
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 */
strcpy(insertstr, words->sl_str[0]);
if (el_insertstr(el, insertstr + wordlen) == -1)
- return CC_ERROR;
+ return (CC_ERROR);
else
- return CC_REFRESH;
+ return (CC_REFRESH);
}
if (!list) {
@@ -108,19 +108,19 @@ complete_ambiguous(word, list, words)
strncpy(insertstr, lastmatch, matchlen);
insertstr[matchlen] = '\0';
if (el_insertstr(el, insertstr + wordlen) == -1)
- return CC_ERROR;
+ return (CC_ERROR);
else
/*
* XXX: really want CC_REFRESH_BEEP
*/
- return CC_REFRESH;
+ return (CC_REFRESH);
}
}
putchar('\n');
qsort(words->sl_str, words->sl_cur, sizeof(char *), comparstr);
list_vertical(words);
- return CC_REDISPLAY;
+ return (CC_REDISPLAY);
}
/*
@@ -148,7 +148,7 @@ complete_command(word, list)
rv = complete_ambiguous(word, list, words);
sl_free(words, 0);
- return rv;
+ return (rv);
}
/*
@@ -180,7 +180,7 @@ complete_local(word, list)
}
if ((dd = opendir(dir)) == NULL)
- return CC_ERROR;
+ return (CC_ERROR);
words = sl_init();
@@ -202,7 +202,7 @@ complete_local(word, list)
rv = complete_ambiguous(file, list, words);
sl_free(words, 1);
- return rv;
+ return (rv);
}
/*
@@ -215,39 +215,50 @@ complete_remote(word, list)
{
static StringList *dirlist;
static char lastdir[MAXPATHLEN];
- static int ftpdslashbug;
StringList *words;
char dir[MAXPATHLEN];
char *file, *cp;
- int i, offset;
+ int i;
unsigned char rv;
char *dummyargv[] = { "complete", dir, NULL };
- offset = 0;
if ((file = strrchr(word, '/')) == NULL) {
- strcpy(dir, ".");
+ (void)strcpy(dir, ".");
file = word;
} else {
- if (file == word)
- strcpy(dir, "/");
- else {
- offset = file - word;
- strncpy(dir, word, offset);
- dir[offset] = '\0';
- offset++;
+ cp = file;
+ while (*cp == '/' && cp > word)
+ cp--;
+ if (cp == word) {
+ dir[0] = '/';
+ dir[1] = '\0';
+ } else {
+ (void)strncpy(dir, word, cp - word + 1);
+ dir[cp - word + 1] = '\0';
}
file++;
}
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)
sl_free(dirlist, 1);
dirlist = sl_init();
- ftpdslashbug = 0;
mflag = 1;
- while ((cp = remglob(dummyargv, 0)) != NULL) {
+ emesg = NULL;
+ while ((cp = remglob(dummyargv, 0, &emesg)) != NULL) {
char *tcp;
if (!mflag)
@@ -259,33 +270,35 @@ complete_remote(word, list)
/*
* Work around ftpd(1) bug, which puts a // instead
* 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' &&
- cp[0] == '/' && cp[1] == '/') {
- cp++;
- ftpdslashbug = 1;
- }
- tcp = strdup(cp);
+ if (ftpdslashbug && (cp[dirlen] != '/'))
+ ftpdslashbug = 0;
+ tcp = strdup(cp + dirlen + ftpdslashbug);
if (tcp == NULL)
errx(1, "Can't allocate memory for remote dir");
sl_add(dirlist, tcp);
}
- strcpy(lastdir, dir);
+ if (emesg != NULL) {
+ printf("\n%s\n", emesg);
+ return (CC_REDISPLAY);
+ }
+ (void)strcpy(lastdir, dir);
dirchange = 0;
}
words = sl_init();
for (i = 0; i < dirlist->sl_cur; i++) {
cp = dirlist->sl_str[i];
- if (strlen(word) > strlen(cp))
+ if (strlen(file) > strlen(cp))
continue;
- if (strncmp(word, cp, strlen(word)) == 0)
- sl_add(words, cp + offset + ftpdslashbug);
+ if (strncmp(file, cp, strlen(file)) == 0)
+ sl_add(words, cp);
}
rv = complete_ambiguous(file, list, words);
sl_free(words, 0);
- return rv;
+ return (rv);
}
/*
@@ -306,7 +319,7 @@ complete(el, ch)
lf = el_line(el);
len = lf->lastchar - lf->buffer;
if (len >= sizeof(line))
- return CC_ERROR;
+ return (CC_ERROR);
strncpy(line, lf->buffer, len);
line[len] = '\0';
cursor_pos = line + (lf->cursor - lf->buffer);
@@ -315,7 +328,7 @@ complete(el, ch)
makeargv(); /* build argc/argv of current line */
if (cursor_argo >= sizeof(word))
- return CC_ERROR;
+ return (CC_ERROR);
dolist = 0;
/* if cursor and word is same, list alternatives */
@@ -327,11 +340,11 @@ complete(el, ch)
word[cursor_argo] = '\0';
if (cursor_argc == 0)
- return complete_command(word, dolist);
+ return (complete_command(word, dolist));
c = getcmd(margv[0]);
if (c == (struct cmd *)-1 || c == 0)
- return CC_ERROR;
+ return (CC_ERROR);
celems = strlen(c->c_complete);
/* check for 'continuation' completes (which are uppercase) */
@@ -340,26 +353,26 @@ complete(el, ch)
cursor_argc = celems;
if (cursor_argc > celems)
- return CC_ERROR;
+ return (CC_ERROR);
switch (c->c_complete[cursor_argc - 1]) {
case 'l': /* local complete */
case 'L':
- return complete_local(word, dolist);
+ return (complete_local(word, dolist));
case 'r': /* remote complete */
case 'R':
if (!connected) {
- puts("\nMust be connected to complete");
- return CC_REDISPLAY;
+ puts("\nMust be connected to complete.");
+ return (CC_REDISPLAY);
}
- return complete_remote(word, dolist);
+ return (complete_remote(word, dolist));
case 'c': /* command complete */
case 'C':
- return complete_command(word, dolist);
+ return (complete_command(word, dolist));
case 'n': /* no complete */
default:
- return CC_ERROR;
+ return (CC_ERROR);
}
- return CC_ERROR;
+ return (CC_ERROR);
}