summaryrefslogtreecommitdiff
path: root/sftp-int.c
diff options
context:
space:
mode:
Diffstat (limited to 'sftp-int.c')
-rw-r--r--sftp-int.c199
1 files changed, 118 insertions, 81 deletions
diff --git a/sftp-int.c b/sftp-int.c
index 02e0d38c0..8b5ae3aef 100644
--- a/sftp-int.c
+++ b/sftp-int.c
@@ -24,10 +24,11 @@
24 24
25/* XXX: finish implementation of all commands */ 25/* XXX: finish implementation of all commands */
26/* XXX: do fnmatch() instead of using raw pathname */ 26/* XXX: do fnmatch() instead of using raw pathname */
27/* XXX: globbed ls */
27/* XXX: recursive operations */ 28/* XXX: recursive operations */
28 29
29#include "includes.h" 30#include "includes.h"
30RCSID("$OpenBSD: sftp-int.c,v 1.7 2001/02/05 00:02:32 deraadt Exp $"); 31RCSID("$OpenBSD: sftp-int.c,v 1.19 2001/02/09 11:46:24 djm Exp $");
31 32
32#include "buffer.h" 33#include "buffer.h"
33#include "xmalloc.h" 34#include "xmalloc.h"
@@ -70,28 +71,29 @@ struct CMD {
70}; 71};
71 72
72const struct CMD cmds[] = { 73const struct CMD cmds[] = {
73 { "CD", I_CHDIR }, 74 { "cd", I_CHDIR },
74 { "CHDIR", I_CHDIR }, 75 { "chdir", I_CHDIR },
75 { "CHGRP", I_CHGRP }, 76 { "chgrp", I_CHGRP },
76 { "CHMOD", I_CHMOD }, 77 { "chmod", I_CHMOD },
77 { "CHOWN", I_CHOWN }, 78 { "chown", I_CHOWN },
78 { "EXIT", I_QUIT }, 79 { "dir", I_LS },
79 { "GET", I_GET }, 80 { "exit", I_QUIT },
80 { "HELP", I_HELP }, 81 { "get", I_GET },
81 { "LCD", I_LCHDIR }, 82 { "help", I_HELP },
82 { "LCHDIR", I_LCHDIR }, 83 { "lcd", I_LCHDIR },
83 { "LLS", I_LLS }, 84 { "lchdir", I_LCHDIR },
84 { "LMKDIR", I_LMKDIR }, 85 { "lls", I_LLS },
85 { "LPWD", I_LPWD }, 86 { "lmkdir", I_LMKDIR },
86 { "LS", I_LS }, 87 { "lpwd", I_LPWD },
87 { "LUMASK", I_LUMASK }, 88 { "ls", I_LS },
88 { "MKDIR", I_MKDIR }, 89 { "lumask", I_LUMASK },
89 { "PUT", I_PUT }, 90 { "mkdir", I_MKDIR },
90 { "PWD", I_PWD }, 91 { "put", I_PUT },
91 { "QUIT", I_QUIT }, 92 { "pwd", I_PWD },
92 { "RENAME", I_RENAME }, 93 { "quit", I_QUIT },
93 { "RM", I_RM }, 94 { "rename", I_RENAME },
94 { "RMDIR", I_RMDIR }, 95 { "rm", I_RM },
96 { "rmdir", I_RMDIR },
95 { "!", I_SHELL }, 97 { "!", I_SHELL },
96 { "?", I_HELP }, 98 { "?", I_HELP },
97 { NULL, -1} 99 { NULL, -1}
@@ -101,28 +103,29 @@ void
101help(void) 103help(void)
102{ 104{
103 printf("Available commands:\n"); 105 printf("Available commands:\n");
104 printf("CD path Change remote directory to 'path'\n"); 106 printf("cd path Change remote directory to 'path'\n");
105 printf("LCD path Change local directory to 'path'\n"); 107 printf("lcd path Change local directory to 'path'\n");
106 printf("CHGRP grp path Change group of file 'path' to 'grp'\n"); 108 printf("chgrp grp path Change group of file 'path' to 'grp'\n");
107 printf("CHMOD mode path Change permissions of file 'path' to 'mode'\n"); 109 printf("chmod mode path Change permissions of file 'path' to 'mode'\n");
108 printf("CHOWN own path Change owner of file 'path' to 'own'\n"); 110 printf("chown own path Change owner of file 'path' to 'own'\n");
109 printf("HELP Display this help text\n"); 111 printf("help Display this help text\n");
110 printf("GET remote-path [local-path] Download file\n"); 112 printf("get remote-path [local-path] Download file\n");
111 printf("LLS [ls options] [path] Display local directory listing\n"); 113 printf("lls [ls-options [path]] Display local directory listing\n");
112 printf("LMKDIR path Create local directory\n"); 114 printf("lmkdir path Create local directory\n");
113 printf("LPWD Print local working directory\n"); 115 printf("lpwd Print local working directory\n");
114 printf("LS [path] Display remote directory listing\n"); 116 printf("ls [path] Display remote directory listing\n");
115 printf("LUMASK umask Set local umask to 'umask'\n"); 117 printf("lumask umask Set local umask to 'umask'\n");
116 printf("MKDIR path Create remote directory\n"); 118 printf("mkdir path Create remote directory\n");
117 printf("PUT local-path [remote-path] Upload file\n"); 119 printf("put local-path [remote-path] Upload file\n");
118 printf("PWD Display remote working directory\n"); 120 printf("pwd Display remote working directory\n");
119 printf("EXIT Quit sftp\n"); 121 printf("exit Quit sftp\n");
120 printf("QUIT Quit sftp\n"); 122 printf("quit Quit sftp\n");
121 printf("RENAME oldpath newpath Rename remote file\n"); 123 printf("rename oldpath newpath Rename remote file\n");
122 printf("RMDIR path Remove remote directory\n"); 124 printf("rmdir path Remove remote directory\n");
123 printf("RM path Delete remote file\n"); 125 printf("rm path Delete remote file\n");
124 printf("!command Execute 'command' in local shell\n"); 126 printf("!command Execute 'command' in local shell\n");
125 printf("! Escape to local shell\n"); 127 printf("! Escape to local shell\n");
128 printf("? Synonym for help\n");
126} 129}
127 130
128void 131void
@@ -166,13 +169,15 @@ void
166local_do_ls(const char *args) 169local_do_ls(const char *args)
167{ 170{
168 if (!args || !*args) 171 if (!args || !*args)
169 local_do_shell("ls"); 172 local_do_shell(_PATH_LS);
170 else { 173 else {
171 char *buf = xmalloc(8 + strlen(args) + 1); 174 int len = strlen(_PATH_LS " ") + strlen(args) + 1;
175 char *buf = xmalloc(len);
172 176
173 /* XXX: quoting - rip quoting code from ftp? */ 177 /* XXX: quoting - rip quoting code from ftp? */
174 sprintf(buf, "/bin/ls %s", args); 178 snprintf(buf, len, _PATH_LS " %s", args);
175 local_do_shell(buf); 179 local_do_shell(buf);
180 xfree(buf);
176 } 181 }
177} 182}
178 183
@@ -198,7 +203,7 @@ parse_getput_flags(const char **cpp, int *pflag)
198 203
199 /* Check for flags */ 204 /* Check for flags */
200 if (cp[0] == '-' && cp[1] && strchr(WHITESPACE, cp[2])) { 205 if (cp[0] == '-' && cp[1] && strchr(WHITESPACE, cp[2])) {
201 switch (*cp) { 206 switch (cp[1]) {
202 case 'P': 207 case 'P':
203 *pflag = 1; 208 *pflag = 1;
204 break; 209 break;
@@ -216,50 +221,49 @@ parse_getput_flags(const char **cpp, int *pflag)
216int 221int
217get_pathname(const char **cpp, char **path) 222get_pathname(const char **cpp, char **path)
218{ 223{
219 const char *quot, *cp = *cpp; 224 const char *cp = *cpp, *end;
225 char quot;
220 int i; 226 int i;
221 227
222 cp += strspn(cp, WHITESPACE); 228 cp += strspn(cp, WHITESPACE);
223 if (!*cp) { 229 if (!*cp) {
224 *cpp = cp; 230 *cpp = cp;
225 *path = NULL; 231 *path = NULL;
226 return(0); 232 return (0);
227 } 233 }
228 234
229 /* Check for quoted filenames */ 235 /* Check for quoted filenames */
230 if (*cp == '\"' || *cp == '\'') { 236 if (*cp == '\"' || *cp == '\'') {
231 quot = cp++; 237 quot = *cp++;
232 for(i = 0; cp[i] && cp[i] != *quot; i++) 238
233 ; 239 end = strchr(cp, quot);
234 if (!cp[i]) { 240 if (end == NULL) {
235 error("Unterminated quote"); 241 error("Unterminated quote");
236 *path = NULL; 242 goto fail;
237 return(-1);
238 } 243 }
239 if (i == 0) { 244 if (cp == end) {
240 error("Empty quotes"); 245 error("Empty quotes");
241 *path = NULL; 246 goto fail;
242 return(-1);
243 } 247 }
244 *path = xmalloc(i + 1); 248 *cpp = end + 1 + strspn(end + 1, WHITESPACE);
245 memcpy(*path, cp, i); 249 } else {
246 (*path)[i] = '\0'; 250 /* Read to end of filename */
247 cp += i + 1; 251 end = strpbrk(cp, WHITESPACE);
248 *cpp = cp + strspn(cp, WHITESPACE); 252 if (end == NULL)
249 return(0); 253 end = strchr(cp, '\0');
254 *cpp = end + strspn(end, WHITESPACE);
250 } 255 }
251 256
252 /* Read to end of filename */ 257 i = end - cp;
253 for(i = 0; cp[i] && cp[i] != ' '; i++)
254 ;
255 258
256 *path = xmalloc(i + 1); 259 *path = xmalloc(i + 1);
257 memcpy(*path, cp, i); 260 memcpy(*path, cp, i);
258 (*path)[i] = '\0'; 261 (*path)[i] = '\0';
259 cp += i;
260 *cpp = cp + strspn(cp, WHITESPACE);
261
262 return(0); 262 return(0);
263
264 fail:
265 *path = NULL;
266 return (-1);
263} 267}
264 268
265int 269int
@@ -270,7 +274,6 @@ infer_path(const char *p, char **ifp)
270 debug("XXX: P = \"%s\"", p); 274 debug("XXX: P = \"%s\"", p);
271 275
272 cp = strrchr(p, '/'); 276 cp = strrchr(p, '/');
273
274 if (cp == NULL) { 277 if (cp == NULL) {
275 *ifp = xstrdup(p); 278 *ifp = xstrdup(p);
276 return(0); 279 return(0);
@@ -421,14 +424,13 @@ parse_args(const char **cpp, int *pflag, unsigned long *n_arg,
421 } 424 }
422 425
423 *cpp = cp; 426 *cpp = cp;
424
425 return(cmdnum); 427 return(cmdnum);
426} 428}
427 429
428int 430int
429parse_dispatch_command(int in, int out, const char *cmd, char **pwd) 431parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
430{ 432{
431 char *path1, *path2; 433 char *path1, *path2, *tmp;
432 int pflag, cmdnum; 434 int pflag, cmdnum;
433 unsigned long n_arg; 435 unsigned long n_arg;
434 Attrib a, *aa; 436 Attrib a, *aa;
@@ -471,12 +473,44 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
471 break; 473 break;
472 case I_CHDIR: 474 case I_CHDIR:
473 path1 = make_absolute(path1, *pwd); 475 path1 = make_absolute(path1, *pwd);
476 if ((tmp = do_realpath(in, out, path1)) == NULL)
477 break;
478 if ((aa = do_stat(in, out, tmp)) == NULL) {
479 xfree(tmp);
480 break;
481 }
482 if (!(aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) {
483 error("Can't change directory: Can't check target");
484 xfree(tmp);
485 break;
486 }
487 if (!S_ISDIR(aa->perm)) {
488 error("Can't change directory: \"%s\" is not "
489 "a directory", tmp);
490 xfree(tmp);
491 break;
492 }
474 xfree(*pwd); 493 xfree(*pwd);
475 *pwd = do_realpath(in, out, path1); 494 *pwd = tmp;
476 break; 495 break;
477 case I_LS: 496 case I_LS:
497 if (!path1) {
498 do_ls(in, out, *pwd);
499 break;
500 }
478 path1 = make_absolute(path1, *pwd); 501 path1 = make_absolute(path1, *pwd);
479 do_ls(in, out, path1?path1:*pwd); 502 if ((tmp = do_realpath(in, out, path1)) == NULL)
503 break;
504 xfree(path1);
505 path1 = tmp;
506 if ((aa = do_stat(in, out, path1)) == NULL)
507 break;
508 if ((aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
509 !S_ISDIR(aa->perm)) {
510 error("Can't ls: \"%s\" is not a directory", path1);
511 break;
512 }
513 do_ls(in, out, path1);
480 break; 514 break;
481 case I_LCHDIR: 515 case I_LCHDIR:
482 if (chdir(path1) == -1) 516 if (chdir(path1) == -1)
@@ -485,7 +519,7 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
485 break; 519 break;
486 case I_LMKDIR: 520 case I_LMKDIR:
487 if (mkdir(path1, 0777) == -1) 521 if (mkdir(path1, 0777) == -1)
488 error("Couldn't create local directory to " 522 error("Couldn't create local directory "
489 "\"%s\": %s", path1, strerror(errno)); 523 "\"%s\": %s", path1, strerror(errno));
490 break; 524 break;
491 case I_LLS: 525 case I_LLS:
@@ -506,23 +540,27 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
506 break; 540 break;
507 case I_CHOWN: 541 case I_CHOWN:
508 path1 = make_absolute(path1, *pwd); 542 path1 = make_absolute(path1, *pwd);
509 aa = do_stat(in, out, path1); 543 if (!(aa = do_stat(in, out, path1)))
544 break;
510 if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { 545 if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) {
511 error("Can't get current ownership of " 546 error("Can't get current ownership of "
512 "remote file \"%s\"", path1); 547 "remote file \"%s\"", path1);
513 break; 548 break;
514 } 549 }
550 aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;
515 aa->uid = n_arg; 551 aa->uid = n_arg;
516 do_setstat(in, out, path1, aa); 552 do_setstat(in, out, path1, aa);
517 break; 553 break;
518 case I_CHGRP: 554 case I_CHGRP:
519 path1 = make_absolute(path1, *pwd); 555 path1 = make_absolute(path1, *pwd);
520 aa = do_stat(in, out, path1); 556 if (!(aa = do_stat(in, out, path1)))
557 break;
521 if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { 558 if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) {
522 error("Can't get current ownership of " 559 error("Can't get current ownership of "
523 "remote file \"%s\"", path1); 560 "remote file \"%s\"", path1);
524 break; 561 break;
525 } 562 }
563 aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;
526 aa->gid = n_arg; 564 aa->gid = n_arg;
527 do_setstat(in, out, path1, aa); 565 do_setstat(in, out, path1, aa);
528 break; 566 break;
@@ -550,7 +588,6 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
550 xfree(path1); 588 xfree(path1);
551 if (path2) 589 if (path2)
552 xfree(path2); 590 xfree(path2);
553
554 return(0); 591 return(0);
555} 592}
556 593
@@ -564,8 +601,8 @@ interactive_loop(int fd_in, int fd_out)
564 if (pwd == NULL) 601 if (pwd == NULL)
565 fatal("Need cwd"); 602 fatal("Need cwd");
566 603
567 setvbuf(stdout, (char *)NULL, _IOLBF, 0); 604 setvbuf(stdout, NULL, _IOLBF, 0);
568 setvbuf(stdin, (char *)NULL, _IOLBF, 0); 605 setvbuf(stdin, NULL, _IOLBF, 0);
569 606
570 for(;;) { 607 for(;;) {
571 char *cp; 608 char *cp;