/* XXX: finish implementation of all commands */
/* XXX: do fnmatch() instead of using raw pathname */
+/* XXX: globbed ls */
/* XXX: recursive operations */
#include "includes.h"
-RCSID("$OpenBSD: sftp-int.c,v 1.7 2001/02/05 00:02:32 deraadt Exp $");
+RCSID("$OpenBSD: sftp-int.c,v 1.19 2001/02/09 11:46:24 djm Exp $");
#include "buffer.h"
#include "xmalloc.h"
};
const struct CMD cmds[] = {
- { "CD", I_CHDIR },
- { "CHDIR", I_CHDIR },
- { "CHGRP", I_CHGRP },
- { "CHMOD", I_CHMOD },
- { "CHOWN", I_CHOWN },
- { "EXIT", I_QUIT },
- { "GET", I_GET },
- { "HELP", I_HELP },
- { "LCD", I_LCHDIR },
- { "LCHDIR", I_LCHDIR },
- { "LLS", I_LLS },
- { "LMKDIR", I_LMKDIR },
- { "LPWD", I_LPWD },
- { "LS", I_LS },
- { "LUMASK", I_LUMASK },
- { "MKDIR", I_MKDIR },
- { "PUT", I_PUT },
- { "PWD", I_PWD },
- { "QUIT", I_QUIT },
- { "RENAME", I_RENAME },
- { "RM", I_RM },
- { "RMDIR", I_RMDIR },
+ { "cd", I_CHDIR },
+ { "chdir", I_CHDIR },
+ { "chgrp", I_CHGRP },
+ { "chmod", I_CHMOD },
+ { "chown", I_CHOWN },
+ { "dir", I_LS },
+ { "exit", I_QUIT },
+ { "get", I_GET },
+ { "help", I_HELP },
+ { "lcd", I_LCHDIR },
+ { "lchdir", I_LCHDIR },
+ { "lls", I_LLS },
+ { "lmkdir", I_LMKDIR },
+ { "lpwd", I_LPWD },
+ { "ls", I_LS },
+ { "lumask", I_LUMASK },
+ { "mkdir", I_MKDIR },
+ { "put", I_PUT },
+ { "pwd", I_PWD },
+ { "quit", I_QUIT },
+ { "rename", I_RENAME },
+ { "rm", I_RM },
+ { "rmdir", I_RMDIR },
{ "!", I_SHELL },
{ "?", I_HELP },
{ NULL, -1}
help(void)
{
printf("Available commands:\n");
- printf("CD path Change remote directory to 'path'\n");
- printf("LCD path Change local directory to 'path'\n");
- printf("CHGRP grp path Change group of file 'path' to 'grp'\n");
- printf("CHMOD mode path Change permissions of file 'path' to 'mode'\n");
- printf("CHOWN own path Change owner of file 'path' to 'own'\n");
- printf("HELP Display this help text\n");
- printf("GET remote-path [local-path] Download file\n");
- printf("LLS [ls options] [path] Display local directory listing\n");
- printf("LMKDIR path Create local directory\n");
- printf("LPWD Print local working directory\n");
- printf("LS [path] Display remote directory listing\n");
- printf("LUMASK umask Set local umask to 'umask'\n");
- printf("MKDIR path Create remote directory\n");
- printf("PUT local-path [remote-path] Upload file\n");
- printf("PWD Display remote working directory\n");
- printf("EXIT Quit sftp\n");
- printf("QUIT Quit sftp\n");
- printf("RENAME oldpath newpath Rename remote file\n");
- printf("RMDIR path Remove remote directory\n");
- printf("RM path Delete remote file\n");
+ printf("cd path Change remote directory to 'path'\n");
+ printf("lcd path Change local directory to 'path'\n");
+ printf("chgrp grp path Change group of file 'path' to 'grp'\n");
+ printf("chmod mode path Change permissions of file 'path' to 'mode'\n");
+ printf("chown own path Change owner of file 'path' to 'own'\n");
+ printf("help Display this help text\n");
+ printf("get remote-path [local-path] Download file\n");
+ printf("lls [ls-options [path]] Display local directory listing\n");
+ printf("lmkdir path Create local directory\n");
+ printf("lpwd Print local working directory\n");
+ printf("ls [path] Display remote directory listing\n");
+ printf("lumask umask Set local umask to 'umask'\n");
+ printf("mkdir path Create remote directory\n");
+ printf("put local-path [remote-path] Upload file\n");
+ printf("pwd Display remote working directory\n");
+ printf("exit Quit sftp\n");
+ printf("quit Quit sftp\n");
+ printf("rename oldpath newpath Rename remote file\n");
+ printf("rmdir path Remove remote directory\n");
+ printf("rm path Delete remote file\n");
printf("!command Execute 'command' in local shell\n");
printf("! Escape to local shell\n");
+ printf("? Synonym for help\n");
}
void
local_do_ls(const char *args)
{
if (!args || !*args)
- local_do_shell("ls");
+ local_do_shell(_PATH_LS);
else {
- char *buf = xmalloc(8 + strlen(args) + 1);
+ int len = strlen(_PATH_LS " ") + strlen(args) + 1;
+ char *buf = xmalloc(len);
/* XXX: quoting - rip quoting code from ftp? */
- sprintf(buf, "/bin/ls %s", args);
+ snprintf(buf, len, _PATH_LS " %s", args);
local_do_shell(buf);
+ xfree(buf);
}
}
/* Check for flags */
if (cp[0] == '-' && cp[1] && strchr(WHITESPACE, cp[2])) {
- switch (*cp) {
+ switch (cp[1]) {
case 'P':
*pflag = 1;
break;
int
get_pathname(const char **cpp, char **path)
{
- const char *quot, *cp = *cpp;
+ const char *cp = *cpp, *end;
+ char quot;
int i;
cp += strspn(cp, WHITESPACE);
if (!*cp) {
*cpp = cp;
*path = NULL;
- return(0);
+ return (0);
}
/* Check for quoted filenames */
if (*cp == '\"' || *cp == '\'') {
- quot = cp++;
- for(i = 0; cp[i] && cp[i] != *quot; i++)
- ;
- if (!cp[i]) {
+ quot = *cp++;
+
+ end = strchr(cp, quot);
+ if (end == NULL) {
error("Unterminated quote");
- *path = NULL;
- return(-1);
+ goto fail;
}
- if (i == 0) {
+ if (cp == end) {
error("Empty quotes");
- *path = NULL;
- return(-1);
+ goto fail;
}
- *path = xmalloc(i + 1);
- memcpy(*path, cp, i);
- (*path)[i] = '\0';
- cp += i + 1;
- *cpp = cp + strspn(cp, WHITESPACE);
- return(0);
+ *cpp = end + 1 + strspn(end + 1, WHITESPACE);
+ } else {
+ /* Read to end of filename */
+ end = strpbrk(cp, WHITESPACE);
+ if (end == NULL)
+ end = strchr(cp, '\0');
+ *cpp = end + strspn(end, WHITESPACE);
}
- /* Read to end of filename */
- for(i = 0; cp[i] && cp[i] != ' '; i++)
- ;
+ i = end - cp;
*path = xmalloc(i + 1);
memcpy(*path, cp, i);
(*path)[i] = '\0';
- cp += i;
- *cpp = cp + strspn(cp, WHITESPACE);
-
return(0);
+
+ fail:
+ *path = NULL;
+ return (-1);
}
int
debug("XXX: P = \"%s\"", p);
cp = strrchr(p, '/');
-
if (cp == NULL) {
*ifp = xstrdup(p);
return(0);
}
*cpp = cp;
-
return(cmdnum);
}
int
parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
{
- char *path1, *path2;
+ char *path1, *path2, *tmp;
int pflag, cmdnum;
unsigned long n_arg;
Attrib a, *aa;
break;
case I_CHDIR:
path1 = make_absolute(path1, *pwd);
+ if ((tmp = do_realpath(in, out, path1)) == NULL)
+ break;
+ if ((aa = do_stat(in, out, tmp)) == NULL) {
+ xfree(tmp);
+ break;
+ }
+ if (!(aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) {
+ error("Can't change directory: Can't check target");
+ xfree(tmp);
+ break;
+ }
+ if (!S_ISDIR(aa->perm)) {
+ error("Can't change directory: \"%s\" is not "
+ "a directory", tmp);
+ xfree(tmp);
+ break;
+ }
xfree(*pwd);
- *pwd = do_realpath(in, out, path1);
+ *pwd = tmp;
break;
case I_LS:
+ if (!path1) {
+ do_ls(in, out, *pwd);
+ break;
+ }
path1 = make_absolute(path1, *pwd);
- do_ls(in, out, path1?path1:*pwd);
+ if ((tmp = do_realpath(in, out, path1)) == NULL)
+ break;
+ xfree(path1);
+ path1 = tmp;
+ if ((aa = do_stat(in, out, path1)) == NULL)
+ break;
+ if ((aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
+ !S_ISDIR(aa->perm)) {
+ error("Can't ls: \"%s\" is not a directory", path1);
+ break;
+ }
+ do_ls(in, out, path1);
break;
case I_LCHDIR:
if (chdir(path1) == -1)
break;
case I_LMKDIR:
if (mkdir(path1, 0777) == -1)
- error("Couldn't create local directory to "
+ error("Couldn't create local directory "
"\"%s\": %s", path1, strerror(errno));
break;
case I_LLS:
break;
case I_CHOWN:
path1 = make_absolute(path1, *pwd);
- aa = do_stat(in, out, path1);
+ if (!(aa = do_stat(in, out, path1)))
+ break;
if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) {
error("Can't get current ownership of "
"remote file \"%s\"", path1);
break;
}
+ aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;
aa->uid = n_arg;
do_setstat(in, out, path1, aa);
break;
case I_CHGRP:
path1 = make_absolute(path1, *pwd);
- aa = do_stat(in, out, path1);
+ if (!(aa = do_stat(in, out, path1)))
+ break;
if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) {
error("Can't get current ownership of "
"remote file \"%s\"", path1);
break;
}
+ aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;
aa->gid = n_arg;
do_setstat(in, out, path1, aa);
break;
xfree(path1);
if (path2)
xfree(path2);
-
return(0);
}
if (pwd == NULL)
fatal("Need cwd");
- setvbuf(stdout, (char *)NULL, _IOLBF, 0);
- setvbuf(stdin, (char *)NULL, _IOLBF, 0);
+ setvbuf(stdout, NULL, _IOLBF, 0);
+ setvbuf(stdin, NULL, _IOLBF, 0);
for(;;) {
char *cp;