]> andersk Git - openssh.git/blobdiff - sftp-int.c
- (djm) Sync sftp and scp stuff from OpenBSD:
[openssh.git] / sftp-int.c
index 02e0d38c029a8422312cf9d17cb2042d3c0997ba..8b5ae3aefb616492dfd533c92b4fe4438f7723e5 100644 (file)
 
 /* 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"
@@ -70,28 +71,29 @@ struct CMD {
 };
 
 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}
@@ -101,28 +103,29 @@ void
 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
@@ -166,13 +169,15 @@ 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);
        }
 }
 
@@ -198,7 +203,7 @@ parse_getput_flags(const char **cpp, int *pflag)
 
        /* Check for flags */
        if (cp[0] == '-' && cp[1] && strchr(WHITESPACE, cp[2])) {
-               switch (*cp) {
+               switch (cp[1]) {
                case 'P':
                        *pflag = 1;
                        break;
@@ -216,50 +221,49 @@ parse_getput_flags(const char **cpp, int *pflag)
 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
@@ -270,7 +274,6 @@ infer_path(const char *p, char **ifp)
        debug("XXX: P = \"%s\"", p);
 
        cp = strrchr(p, '/');
-
        if (cp == NULL) {
                *ifp = xstrdup(p);
                return(0);
@@ -421,14 +424,13 @@ parse_args(const char **cpp, int *pflag, unsigned long *n_arg,
        }
 
        *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;
@@ -471,12 +473,44 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
                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)
@@ -485,7 +519,7 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
                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:
@@ -506,23 +540,27 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
                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;
@@ -550,7 +588,6 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
                xfree(path1);
        if (path2)
                xfree(path2);
-
        return(0);
 }
 
@@ -564,8 +601,8 @@ interactive_loop(int fd_in, int fd_out)
        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;
This page took 0.054489 seconds and 4 git commands to generate.