upstream: sftp: Be a bit more clever about completions
There are commands (e.g. "get" or "put") that accept two arguments, a local path and a remote path. However, the way current completion is written doesn't take this distinction into account and always completes remote or local paths. By expanding CMD struct and "cmds" array this distinction can be reflected and with small adjustment to completer code the correct path can be completed. By Michal Privoznik, ok dtucker@ OpenBSD-Commit-ID: 1396d921c4eb1befd531f5c4a8ab47e7a74b610b
This commit is contained in:
parent
590db83384
commit
ac1ec95459
115
sftp.c
115
sftp.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: sftp.c,v 1.219 2022/09/16 03:13:34 djm Exp $ */
|
||||
/* $OpenBSD: sftp.c,v 1.220 2022/09/16 03:33:14 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
|
||||
*
|
||||
|
@ -166,7 +166,8 @@ enum sftp_command {
|
|||
struct CMD {
|
||||
const char *c;
|
||||
const int n;
|
||||
const int t;
|
||||
const int t; /* Completion type for the first argument */
|
||||
const int t2; /* completion type for the optional second argument */
|
||||
};
|
||||
|
||||
/* Type of completion */
|
||||
|
@ -175,44 +176,44 @@ struct CMD {
|
|||
#define LOCAL 2
|
||||
|
||||
static const struct CMD cmds[] = {
|
||||
{ "bye", I_QUIT, NOARGS },
|
||||
{ "cd", I_CHDIR, REMOTE },
|
||||
{ "chdir", I_CHDIR, REMOTE },
|
||||
{ "chgrp", I_CHGRP, REMOTE },
|
||||
{ "chmod", I_CHMOD, REMOTE },
|
||||
{ "chown", I_CHOWN, REMOTE },
|
||||
{ "copy", I_COPY, REMOTE },
|
||||
{ "cp", I_COPY, REMOTE },
|
||||
{ "df", I_DF, REMOTE },
|
||||
{ "dir", I_LS, REMOTE },
|
||||
{ "exit", I_QUIT, NOARGS },
|
||||
{ "get", I_GET, REMOTE },
|
||||
{ "help", I_HELP, NOARGS },
|
||||
{ "lcd", I_LCHDIR, LOCAL },
|
||||
{ "lchdir", I_LCHDIR, LOCAL },
|
||||
{ "lls", I_LLS, LOCAL },
|
||||
{ "lmkdir", I_LMKDIR, LOCAL },
|
||||
{ "ln", I_LINK, REMOTE },
|
||||
{ "lpwd", I_LPWD, LOCAL },
|
||||
{ "ls", I_LS, REMOTE },
|
||||
{ "lumask", I_LUMASK, NOARGS },
|
||||
{ "mkdir", I_MKDIR, REMOTE },
|
||||
{ "mget", I_GET, REMOTE },
|
||||
{ "mput", I_PUT, LOCAL },
|
||||
{ "progress", I_PROGRESS, NOARGS },
|
||||
{ "put", I_PUT, LOCAL },
|
||||
{ "pwd", I_PWD, REMOTE },
|
||||
{ "quit", I_QUIT, NOARGS },
|
||||
{ "reget", I_REGET, REMOTE },
|
||||
{ "rename", I_RENAME, REMOTE },
|
||||
{ "reput", I_REPUT, LOCAL },
|
||||
{ "rm", I_RM, REMOTE },
|
||||
{ "rmdir", I_RMDIR, REMOTE },
|
||||
{ "symlink", I_SYMLINK, REMOTE },
|
||||
{ "version", I_VERSION, NOARGS },
|
||||
{ "!", I_SHELL, NOARGS },
|
||||
{ "?", I_HELP, NOARGS },
|
||||
{ NULL, -1, -1 }
|
||||
{ "bye", I_QUIT, NOARGS, NOARGS },
|
||||
{ "cd", I_CHDIR, REMOTE, NOARGS },
|
||||
{ "chdir", I_CHDIR, REMOTE, NOARGS },
|
||||
{ "chgrp", I_CHGRP, REMOTE, NOARGS },
|
||||
{ "chmod", I_CHMOD, REMOTE, NOARGS },
|
||||
{ "chown", I_CHOWN, REMOTE, NOARGS },
|
||||
{ "copy", I_COPY, REMOTE, LOCAL },
|
||||
{ "cp", I_COPY, REMOTE, LOCAL },
|
||||
{ "df", I_DF, REMOTE, NOARGS },
|
||||
{ "dir", I_LS, REMOTE, NOARGS },
|
||||
{ "exit", I_QUIT, NOARGS, NOARGS },
|
||||
{ "get", I_GET, REMOTE, LOCAL },
|
||||
{ "help", I_HELP, NOARGS, NOARGS },
|
||||
{ "lcd", I_LCHDIR, LOCAL, NOARGS },
|
||||
{ "lchdir", I_LCHDIR, LOCAL, NOARGS },
|
||||
{ "lls", I_LLS, LOCAL, NOARGS },
|
||||
{ "lmkdir", I_LMKDIR, LOCAL, NOARGS },
|
||||
{ "ln", I_LINK, REMOTE, REMOTE },
|
||||
{ "lpwd", I_LPWD, LOCAL, NOARGS },
|
||||
{ "ls", I_LS, REMOTE, NOARGS },
|
||||
{ "lumask", I_LUMASK, NOARGS, NOARGS },
|
||||
{ "mkdir", I_MKDIR, REMOTE, NOARGS },
|
||||
{ "mget", I_GET, REMOTE, LOCAL },
|
||||
{ "mput", I_PUT, LOCAL, REMOTE },
|
||||
{ "progress", I_PROGRESS, NOARGS, NOARGS },
|
||||
{ "put", I_PUT, LOCAL, REMOTE },
|
||||
{ "pwd", I_PWD, REMOTE, NOARGS },
|
||||
{ "quit", I_QUIT, NOARGS, NOARGS },
|
||||
{ "reget", I_REGET, REMOTE, LOCAL },
|
||||
{ "rename", I_RENAME, REMOTE, REMOTE },
|
||||
{ "reput", I_REPUT, LOCAL, REMOTE },
|
||||
{ "rm", I_RM, REMOTE, NOARGS },
|
||||
{ "rmdir", I_RMDIR, REMOTE, NOARGS },
|
||||
{ "symlink", I_SYMLINK, REMOTE, REMOTE },
|
||||
{ "version", I_VERSION, NOARGS, NOARGS },
|
||||
{ "!", I_SHELL, NOARGS, NOARGS },
|
||||
{ "?", I_HELP, NOARGS, NOARGS },
|
||||
{ NULL, -1, -1, -1 }
|
||||
};
|
||||
|
||||
/* ARGSUSED */
|
||||
|
@ -1945,19 +1946,25 @@ complete_cmd_parse(EditLine *el, char *cmd, int lastarg, char quote,
|
|||
}
|
||||
|
||||
/*
|
||||
* Determine whether a particular sftp command's arguments (if any)
|
||||
* represent local or remote files.
|
||||
* Determine whether a particular sftp command's arguments (if any) represent
|
||||
* local or remote files. The "cmdarg" argument specifies the actual argument
|
||||
* and accepts values 1 or 2.
|
||||
*/
|
||||
static int
|
||||
complete_is_remote(char *cmd) {
|
||||
complete_is_remote(char *cmd, int cmdarg) {
|
||||
int i;
|
||||
|
||||
if (cmd == NULL)
|
||||
return -1;
|
||||
|
||||
for (i = 0; cmds[i].c; i++) {
|
||||
if (!strncasecmp(cmd, cmds[i].c, strlen(cmds[i].c)))
|
||||
return cmds[i].t;
|
||||
if (!strncasecmp(cmd, cmds[i].c, strlen(cmds[i].c))) {
|
||||
if (cmdarg == 1)
|
||||
return cmds[i].t;
|
||||
else if (cmdarg == 2)
|
||||
return cmds[i].t2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
@ -2137,12 +2144,28 @@ complete(EditLine *el, int ch)
|
|||
ret = CC_REDISPLAY;
|
||||
} else if (carg >= 1) {
|
||||
/* Handle file parsing */
|
||||
int remote = complete_is_remote(argv[0]);
|
||||
int remote = 0;
|
||||
int i = 0, cmdarg = 0;
|
||||
char *filematch = NULL;
|
||||
|
||||
if (carg > 1 && line[cursor-1] != ' ')
|
||||
filematch = argv[carg - 1];
|
||||
|
||||
for (i = 1; i < carg; i++) {
|
||||
/* Skip flags */
|
||||
if (argv[i][0] != '-')
|
||||
cmdarg++;
|
||||
}
|
||||
|
||||
/*
|
||||
* If previous argument is complete, then offer completion
|
||||
* on the next one.
|
||||
*/
|
||||
if (line[cursor - 1] == ' ')
|
||||
cmdarg++;
|
||||
|
||||
remote = complete_is_remote(argv[0], cmdarg);
|
||||
|
||||
if ((remote == REMOTE || remote == LOCAL) &&
|
||||
complete_match(el, complete_ctx->conn,
|
||||
*complete_ctx->remote_pathp, filematch,
|
||||
|
|
Loading…
Reference in New Issue