diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | sftp-client.c | 81 | ||||
-rw-r--r-- | sftp-client.h | 13 | ||||
-rw-r--r-- | sftp-int.c | 29 | ||||
-rw-r--r-- | sftp-server.c | 75 | ||||
-rw-r--r-- | sftp.1 | 18 | ||||
-rw-r--r-- | sftp.c | 4 | ||||
-rw-r--r-- | sftp.h | 9 |
8 files changed, 216 insertions, 22 deletions
@@ -1,3 +1,10 @@ | |||
1 | 20010308 | ||
2 | - OpenBSD CVS Sync | ||
3 | - djm@cvs.openbsd.org 2001/03/07 10:11:23 | ||
4 | [sftp-client.c sftp-client.h sftp-int.c sftp-server.c sftp.1 sftp.c sftp.h] | ||
5 | Support for new draft (draft-ietf-secsh-filexfer-01). New symlink handling | ||
6 | functions and small protocol change. | ||
7 | |||
1 | 20010307 | 8 | 20010307 |
2 | - (bal) OpenBSD CVS Sync | 9 | - (bal) OpenBSD CVS Sync |
3 | - deraadt@cvs.openbsd.org 2001/03/06 06:11:18 | 10 | - deraadt@cvs.openbsd.org 2001/03/06 06:11:18 |
@@ -4430,4 +4437,4 @@ | |||
4430 | - Wrote replacements for strlcpy and mkdtemp | 4437 | - Wrote replacements for strlcpy and mkdtemp |
4431 | - Released 1.0pre1 | 4438 | - Released 1.0pre1 |
4432 | 4439 | ||
4433 | $Id: ChangeLog,v 1.924 2001/03/07 10:38:19 djm Exp $ | 4440 | $Id: ChangeLog,v 1.925 2001/03/07 23:08:49 djm Exp $ |
diff --git a/sftp-client.c b/sftp-client.c index 5242cab03..d1e4ebacc 100644 --- a/sftp-client.c +++ b/sftp-client.c | |||
@@ -29,7 +29,7 @@ | |||
29 | /* XXX: copy between two remote sites */ | 29 | /* XXX: copy between two remote sites */ |
30 | 30 | ||
31 | #include "includes.h" | 31 | #include "includes.h" |
32 | RCSID("$OpenBSD: sftp-client.c,v 1.10 2001/02/14 09:46:03 djm Exp $"); | 32 | RCSID("$OpenBSD: sftp-client.c,v 1.11 2001/03/07 10:11:22 djm Exp $"); |
33 | 33 | ||
34 | #include "ssh.h" | 34 | #include "ssh.h" |
35 | #include "buffer.h" | 35 | #include "buffer.h" |
@@ -247,7 +247,8 @@ do_init(int fd_in, int fd_out) | |||
247 | } | 247 | } |
248 | 248 | ||
249 | buffer_free(&msg); | 249 | buffer_free(&msg); |
250 | return(0); | 250 | |
251 | return(version); | ||
251 | } | 252 | } |
252 | 253 | ||
253 | int | 254 | int |
@@ -483,8 +484,7 @@ do_realpath(int fd_in, int fd_out, char *path) | |||
483 | Attrib *a; | 484 | Attrib *a; |
484 | 485 | ||
485 | expected_id = id = msg_id++; | 486 | expected_id = id = msg_id++; |
486 | send_string_request(fd_out, id, SSH2_FXP_REALPATH, path, | 487 | send_string_request(fd_out, id, SSH2_FXP_REALPATH, path, strlen(path)); |
487 | strlen(path)); | ||
488 | 488 | ||
489 | buffer_init(&msg); | 489 | buffer_init(&msg); |
490 | 490 | ||
@@ -549,6 +549,79 @@ do_rename(int fd_in, int fd_out, char *oldpath, char *newpath) | |||
549 | } | 549 | } |
550 | 550 | ||
551 | int | 551 | int |
552 | do_symlink(int fd_in, int fd_out, char *oldpath, char *newpath) | ||
553 | { | ||
554 | Buffer msg; | ||
555 | u_int status, id; | ||
556 | |||
557 | buffer_init(&msg); | ||
558 | |||
559 | /* Send rename request */ | ||
560 | id = msg_id++; | ||
561 | buffer_put_char(&msg, SSH2_FXP_SYMLINK); | ||
562 | buffer_put_int(&msg, id); | ||
563 | buffer_put_cstring(&msg, oldpath); | ||
564 | buffer_put_cstring(&msg, newpath); | ||
565 | send_msg(fd_out, &msg); | ||
566 | debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath, | ||
567 | newpath); | ||
568 | buffer_free(&msg); | ||
569 | |||
570 | status = get_status(fd_in, id); | ||
571 | if (status != SSH2_FX_OK) | ||
572 | error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, newpath, | ||
573 | fx2txt(status)); | ||
574 | |||
575 | return(status); | ||
576 | } | ||
577 | |||
578 | char * | ||
579 | do_readlink(int fd_in, int fd_out, char *path) | ||
580 | { | ||
581 | Buffer msg; | ||
582 | u_int type, expected_id, count, id; | ||
583 | char *filename, *longname; | ||
584 | Attrib *a; | ||
585 | |||
586 | expected_id = id = msg_id++; | ||
587 | send_string_request(fd_out, id, SSH2_FXP_READLINK, path, strlen(path)); | ||
588 | |||
589 | buffer_init(&msg); | ||
590 | |||
591 | get_msg(fd_in, &msg); | ||
592 | type = buffer_get_char(&msg); | ||
593 | id = buffer_get_int(&msg); | ||
594 | |||
595 | if (id != expected_id) | ||
596 | fatal("ID mismatch (%d != %d)", id, expected_id); | ||
597 | |||
598 | if (type == SSH2_FXP_STATUS) { | ||
599 | u_int status = buffer_get_int(&msg); | ||
600 | |||
601 | error("Couldn't readlink: %s", fx2txt(status)); | ||
602 | return(NULL); | ||
603 | } else if (type != SSH2_FXP_NAME) | ||
604 | fatal("Expected SSH2_FXP_NAME(%d) packet, got %d", | ||
605 | SSH2_FXP_NAME, type); | ||
606 | |||
607 | count = buffer_get_int(&msg); | ||
608 | if (count != 1) | ||
609 | fatal("Got multiple names (%d) from SSH_FXP_READLINK", count); | ||
610 | |||
611 | filename = buffer_get_string(&msg, NULL); | ||
612 | longname = buffer_get_string(&msg, NULL); | ||
613 | a = decode_attrib(&msg); | ||
614 | |||
615 | debug3("SSH_FXP_READLINK %s -> %s", path, filename); | ||
616 | |||
617 | xfree(longname); | ||
618 | |||
619 | buffer_free(&msg); | ||
620 | |||
621 | return(filename); | ||
622 | } | ||
623 | |||
624 | int | ||
552 | do_download(int fd_in, int fd_out, char *remote_path, char *local_path, | 625 | do_download(int fd_in, int fd_out, char *remote_path, char *local_path, |
553 | int pflag) | 626 | int pflag) |
554 | { | 627 | { |
diff --git a/sftp-client.h b/sftp-client.h index 838b46b0b..e836c0d66 100644 --- a/sftp-client.h +++ b/sftp-client.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sftp-client.h,v 1.1 2001/02/04 11:11:54 djm Exp $ */ | 1 | /* $OpenBSD: sftp-client.h,v 1.2 2001/03/07 10:11:23 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2001 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2001 Damien Miller. All rights reserved. |
@@ -26,7 +26,10 @@ | |||
26 | 26 | ||
27 | /* Client side of SSH2 filexfer protocol */ | 27 | /* Client side of SSH2 filexfer protocol */ |
28 | 28 | ||
29 | /* Initialiase a SSH filexfer connection */ | 29 | /* |
30 | * Initialiase a SSH filexfer connection. Returns -1 on error or | ||
31 | * protocol version on success. | ||
32 | */ | ||
30 | int do_init(int fd_in, int fd_out); | 33 | int do_init(int fd_in, int fd_out); |
31 | 34 | ||
32 | /* Close file referred to by 'handle' */ | 35 | /* Close file referred to by 'handle' */ |
@@ -67,6 +70,12 @@ char *do_realpath(int fd_in, int fd_out, char *path); | |||
67 | /* Rename 'oldpath' to 'newpath' */ | 70 | /* Rename 'oldpath' to 'newpath' */ |
68 | int do_rename(int fd_in, int fd_out, char *oldpath, char *newpath); | 71 | int do_rename(int fd_in, int fd_out, char *oldpath, char *newpath); |
69 | 72 | ||
73 | /* Rename 'oldpath' to 'newpath' */ | ||
74 | int do_symlink(int fd_in, int fd_out, char *oldpath, char *newpath); | ||
75 | |||
76 | /* Return target of symlink 'path' - caller must free result */ | ||
77 | char *do_readlink(int fd_in, int fd_out, char *path); | ||
78 | |||
70 | /* XXX: add callbacks to do_download/do_upload so we can do progress meter */ | 79 | /* XXX: add callbacks to do_download/do_upload so we can do progress meter */ |
71 | 80 | ||
72 | /* | 81 | /* |
diff --git a/sftp-int.c b/sftp-int.c index 7aa7abdb9..6f5b3677a 100644 --- a/sftp-int.c +++ b/sftp-int.c | |||
@@ -28,7 +28,7 @@ | |||
28 | /* XXX: recursive operations */ | 28 | /* XXX: recursive operations */ |
29 | 29 | ||
30 | #include "includes.h" | 30 | #include "includes.h" |
31 | RCSID("$OpenBSD: sftp-int.c,v 1.25 2001/03/06 06:11:44 deraadt Exp $"); | 31 | RCSID("$OpenBSD: sftp-int.c,v 1.26 2001/03/07 10:11:23 djm Exp $"); |
32 | 32 | ||
33 | #include "buffer.h" | 33 | #include "buffer.h" |
34 | #include "xmalloc.h" | 34 | #include "xmalloc.h" |
@@ -40,7 +40,11 @@ RCSID("$OpenBSD: sftp-int.c,v 1.25 2001/03/06 06:11:44 deraadt Exp $"); | |||
40 | #include "sftp-client.h" | 40 | #include "sftp-client.h" |
41 | #include "sftp-int.h" | 41 | #include "sftp-int.h" |
42 | 42 | ||
43 | extern FILE* infile; | 43 | /* File to read commands from */ |
44 | extern FILE *infile; | ||
45 | |||
46 | /* Version of server we are speaking to */ | ||
47 | int version; | ||
44 | 48 | ||
45 | /* Seperators for interactive commands */ | 49 | /* Seperators for interactive commands */ |
46 | #define WHITESPACE " \t\r\n" | 50 | #define WHITESPACE " \t\r\n" |
@@ -66,6 +70,7 @@ extern FILE* infile; | |||
66 | #define I_RM 18 | 70 | #define I_RM 18 |
67 | #define I_RMDIR 19 | 71 | #define I_RMDIR 19 |
68 | #define I_SHELL 20 | 72 | #define I_SHELL 20 |
73 | #define I_SYMLINK 21 | ||
69 | 74 | ||
70 | struct CMD { | 75 | struct CMD { |
71 | const char *c; | 76 | const char *c; |
@@ -86,6 +91,7 @@ const struct CMD cmds[] = { | |||
86 | { "lchdir", I_LCHDIR }, | 91 | { "lchdir", I_LCHDIR }, |
87 | { "lls", I_LLS }, | 92 | { "lls", I_LLS }, |
88 | { "lmkdir", I_LMKDIR }, | 93 | { "lmkdir", I_LMKDIR }, |
94 | { "ln", I_SYMLINK }, | ||
89 | { "lpwd", I_LPWD }, | 95 | { "lpwd", I_LPWD }, |
90 | { "ls", I_LS }, | 96 | { "ls", I_LS }, |
91 | { "lumask", I_LUMASK }, | 97 | { "lumask", I_LUMASK }, |
@@ -96,6 +102,7 @@ const struct CMD cmds[] = { | |||
96 | { "rename", I_RENAME }, | 102 | { "rename", I_RENAME }, |
97 | { "rm", I_RM }, | 103 | { "rm", I_RM }, |
98 | { "rmdir", I_RMDIR }, | 104 | { "rmdir", I_RMDIR }, |
105 | { "symlink", I_SYMLINK }, | ||
99 | { "!", I_SHELL }, | 106 | { "!", I_SHELL }, |
100 | { "?", I_HELP }, | 107 | { "?", I_HELP }, |
101 | { NULL, -1} | 108 | { NULL, -1} |
@@ -113,6 +120,7 @@ help(void) | |||
113 | printf("help Display this help text\n"); | 120 | printf("help Display this help text\n"); |
114 | printf("get remote-path [local-path] Download file\n"); | 121 | printf("get remote-path [local-path] Download file\n"); |
115 | printf("lls [ls-options [path]] Display local directory listing\n"); | 122 | printf("lls [ls-options [path]] Display local directory listing\n"); |
123 | printf("ln oldpath newpath Symlink remote file\n"); | ||
116 | printf("lmkdir path Create local directory\n"); | 124 | printf("lmkdir path Create local directory\n"); |
117 | printf("lpwd Print local working directory\n"); | 125 | printf("lpwd Print local working directory\n"); |
118 | printf("ls [path] Display remote directory listing\n"); | 126 | printf("ls [path] Display remote directory listing\n"); |
@@ -125,6 +133,7 @@ help(void) | |||
125 | printf("rename oldpath newpath Rename remote file\n"); | 133 | printf("rename oldpath newpath Rename remote file\n"); |
126 | printf("rmdir path Remove remote directory\n"); | 134 | printf("rmdir path Remove remote directory\n"); |
127 | printf("rm path Delete remote file\n"); | 135 | printf("rm path Delete remote file\n"); |
136 | printf("symlink oldpath newpath Symlink remote file\n"); | ||
128 | printf("!command Execute 'command' in local shell\n"); | 137 | printf("!command Execute 'command' in local shell\n"); |
129 | printf("! Escape to local shell\n"); | 138 | printf("! Escape to local shell\n"); |
130 | printf("? Synonym for help\n"); | 139 | printf("? Synonym for help\n"); |
@@ -356,7 +365,7 @@ parse_args(const char **cpp, int *pflag, unsigned long *n_arg, | |||
356 | return(-1); | 365 | return(-1); |
357 | break; | 366 | break; |
358 | case I_RENAME: | 367 | case I_RENAME: |
359 | /* Get first pathname (mandatory) */ | 368 | case I_SYMLINK: |
360 | if (get_pathname(&cp, path1)) | 369 | if (get_pathname(&cp, path1)) |
361 | return(-1); | 370 | return(-1); |
362 | if (get_pathname(&cp, path2)) | 371 | if (get_pathname(&cp, path2)) |
@@ -468,6 +477,16 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) | |||
468 | path2 = make_absolute(path2, *pwd); | 477 | path2 = make_absolute(path2, *pwd); |
469 | err = do_rename(in, out, path1, path2); | 478 | err = do_rename(in, out, path1, path2); |
470 | break; | 479 | break; |
480 | case I_SYMLINK: | ||
481 | if (version < 3) { | ||
482 | error("The server (version %d) does not support " | ||
483 | "this operation", version); | ||
484 | err = -1; | ||
485 | } else { | ||
486 | path2 = make_absolute(path2, *pwd); | ||
487 | err = do_symlink(in, out, path1, path2); | ||
488 | } | ||
489 | break; | ||
471 | case I_RM: | 490 | case I_RM: |
472 | path1 = make_absolute(path1, *pwd); | 491 | path1 = make_absolute(path1, *pwd); |
473 | err = do_rm(in, out, path1); | 492 | err = do_rm(in, out, path1); |
@@ -624,6 +643,10 @@ interactive_loop(int fd_in, int fd_out) | |||
624 | char *pwd; | 643 | char *pwd; |
625 | char cmd[2048]; | 644 | char cmd[2048]; |
626 | 645 | ||
646 | version = do_init(fd_in, fd_out); | ||
647 | if (version == -1) | ||
648 | fatal("Couldn't initialise connection to server"); | ||
649 | |||
627 | pwd = do_realpath(fd_in, fd_out, "."); | 650 | pwd = do_realpath(fd_in, fd_out, "."); |
628 | if (pwd == NULL) | 651 | if (pwd == NULL) |
629 | fatal("Need cwd"); | 652 | fatal("Need cwd"); |
diff --git a/sftp-server.c b/sftp-server.c index 6575eb941..178084577 100644 --- a/sftp-server.c +++ b/sftp-server.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 22 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
23 | */ | 23 | */ |
24 | #include "includes.h" | 24 | #include "includes.h" |
25 | RCSID("$OpenBSD: sftp-server.c,v 1.22 2001/03/03 22:07:50 deraadt Exp $"); | 25 | RCSID("$OpenBSD: sftp-server.c,v 1.23 2001/03/07 10:11:23 djm Exp $"); |
26 | 26 | ||
27 | #include "buffer.h" | 27 | #include "buffer.h" |
28 | #include "bufaux.h" | 28 | #include "bufaux.h" |
@@ -49,6 +49,9 @@ char *__progname; | |||
49 | Buffer iqueue; | 49 | Buffer iqueue; |
50 | Buffer oqueue; | 50 | Buffer oqueue; |
51 | 51 | ||
52 | /* Version of client */ | ||
53 | int version; | ||
54 | |||
52 | /* portable attibutes, etc. */ | 55 | /* portable attibutes, etc. */ |
53 | 56 | ||
54 | typedef struct Stat Stat; | 57 | typedef struct Stat Stat; |
@@ -266,12 +269,29 @@ void | |||
266 | send_status(u_int32_t id, u_int32_t error) | 269 | send_status(u_int32_t id, u_int32_t error) |
267 | { | 270 | { |
268 | Buffer msg; | 271 | Buffer msg; |
272 | const char *status_messages[] = { | ||
273 | "Success", /* SSH_FX_OK */ | ||
274 | "End of file", /* SSH_FX_EOF */ | ||
275 | "No such file", /* SSH_FX_NO_SUCH_FILE */ | ||
276 | "Permission denied", /* SSH_FX_PERMISSION_DENIED */ | ||
277 | "Failure", /* SSH_FX_FAILURE */ | ||
278 | "Bad message", /* SSH_FX_BAD_MESSAGE */ | ||
279 | "No connection", /* SSH_FX_NO_CONNECTION */ | ||
280 | "Connection lost", /* SSH_FX_CONNECTION_LOST */ | ||
281 | "Operation unsupported", /* SSH_FX_OP_UNSUPPORTED */ | ||
282 | "Unknown error" /* Others */ | ||
283 | }; | ||
269 | 284 | ||
270 | TRACE("sent status id %d error %d", id, error); | 285 | TRACE("sent status id %d error %d", id, error); |
271 | buffer_init(&msg); | 286 | buffer_init(&msg); |
272 | buffer_put_char(&msg, SSH2_FXP_STATUS); | 287 | buffer_put_char(&msg, SSH2_FXP_STATUS); |
273 | buffer_put_int(&msg, id); | 288 | buffer_put_int(&msg, id); |
274 | buffer_put_int(&msg, error); | 289 | buffer_put_int(&msg, error); |
290 | if (version >= 3) { | ||
291 | buffer_put_cstring(&msg, | ||
292 | status_messages[MIN(error,SSH2_FX_MAX)]); | ||
293 | buffer_put_cstring(&msg, ""); | ||
294 | } | ||
275 | send_msg(&msg); | 295 | send_msg(&msg); |
276 | buffer_free(&msg); | 296 | buffer_free(&msg); |
277 | } | 297 | } |
@@ -347,8 +367,8 @@ void | |||
347 | process_init(void) | 367 | process_init(void) |
348 | { | 368 | { |
349 | Buffer msg; | 369 | Buffer msg; |
350 | int version = buffer_get_int(&iqueue); | ||
351 | 370 | ||
371 | version = buffer_get_int(&iqueue); | ||
352 | TRACE("client version %d", version); | 372 | TRACE("client version %d", version); |
353 | buffer_init(&msg); | 373 | buffer_init(&msg); |
354 | buffer_put_char(&msg, SSH2_FXP_VERSION); | 374 | buffer_put_char(&msg, SSH2_FXP_VERSION); |
@@ -860,6 +880,51 @@ process_rename(void) | |||
860 | } | 880 | } |
861 | 881 | ||
862 | void | 882 | void |
883 | process_readlink(void) | ||
884 | { | ||
885 | u_int32_t id; | ||
886 | char link[MAXPATHLEN]; | ||
887 | char *path; | ||
888 | |||
889 | id = get_int(); | ||
890 | path = get_string(NULL); | ||
891 | TRACE("readlink id %d path %s", id, path); | ||
892 | if (readlink(path, link, sizeof(link) - 1) == -1) | ||
893 | send_status(id, errno_to_portable(errno)); | ||
894 | else { | ||
895 | Stat s; | ||
896 | |||
897 | link[sizeof(link) - 1] = '\0'; | ||
898 | attrib_clear(&s.attrib); | ||
899 | s.name = s.long_name = link; | ||
900 | send_names(id, 1, &s); | ||
901 | } | ||
902 | xfree(path); | ||
903 | } | ||
904 | |||
905 | void | ||
906 | process_symlink(void) | ||
907 | { | ||
908 | u_int32_t id; | ||
909 | struct stat st; | ||
910 | char *oldpath, *newpath; | ||
911 | int ret, status = SSH2_FX_FAILURE; | ||
912 | |||
913 | id = get_int(); | ||
914 | oldpath = get_string(NULL); | ||
915 | newpath = get_string(NULL); | ||
916 | TRACE("symlink id %d old %s new %s", id, oldpath, newpath); | ||
917 | /* fail if 'newpath' exists */ | ||
918 | if (stat(newpath, &st) == -1) { | ||
919 | ret = symlink(oldpath, newpath); | ||
920 | status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; | ||
921 | } | ||
922 | send_status(id, status); | ||
923 | xfree(oldpath); | ||
924 | xfree(newpath); | ||
925 | } | ||
926 | |||
927 | void | ||
863 | process_extended(void) | 928 | process_extended(void) |
864 | { | 929 | { |
865 | u_int32_t id; | 930 | u_int32_t id; |
@@ -944,6 +1009,12 @@ process(void) | |||
944 | case SSH2_FXP_RENAME: | 1009 | case SSH2_FXP_RENAME: |
945 | process_rename(); | 1010 | process_rename(); |
946 | break; | 1011 | break; |
1012 | case SSH2_FXP_READLINK: | ||
1013 | process_readlink(); | ||
1014 | break; | ||
1015 | case SSH2_FXP_SYMLINK: | ||
1016 | process_symlink(); | ||
1017 | break; | ||
947 | case SSH2_FXP_EXTENDED: | 1018 | case SSH2_FXP_EXTENDED: |
948 | process_extended(); | 1019 | process_extended(); |
949 | break; | 1020 | break; |
@@ -1,4 +1,4 @@ | |||
1 | .\" $OpenBSD: sftp.1,v 1.11 2001/03/06 15:10:42 deraadt Exp $ | 1 | .\" $OpenBSD: sftp.1,v 1.12 2001/03/07 10:11:23 djm Exp $ |
2 | .\" | 2 | .\" |
3 | .\" Copyright (c) 2001 Damien Miller. All rights reserved. | 3 | .\" Copyright (c) 2001 Damien Miller. All rights reserved. |
4 | .\" | 4 | .\" |
@@ -58,7 +58,7 @@ instead of | |||
58 | Since it lacks user interaction it should be used in conjuction with a | 58 | Since it lacks user interaction it should be used in conjuction with a |
59 | non-interactive authentication. Sftp will abort if any of the following | 59 | non-interactive authentication. Sftp will abort if any of the following |
60 | commands fail: | 60 | commands fail: |
61 | .Pa get, put, rename, rm, mkdir, chdir, lchdir | 61 | .Pa get, put, rename, ln, rm, mkdir, chdir, lchdir |
62 | and | 62 | and |
63 | .Pa lmkdir. | 63 | .Pa lmkdir. |
64 | .It Fl C | 64 | .It Fl C |
@@ -131,6 +131,11 @@ is not specified. | |||
131 | .It Ic lmkdir Ar path | 131 | .It Ic lmkdir Ar path |
132 | Create local directory specified by | 132 | Create local directory specified by |
133 | .Ar path . | 133 | .Ar path . |
134 | .It Ic ln Ar oldpath Ar newpath | ||
135 | Create a symbolic link from | ||
136 | .Ar oldpath | ||
137 | to | ||
138 | .Ar newpath . | ||
134 | .It Ic lpwd | 139 | .It Ic lpwd |
135 | Print local working directory. | 140 | Print local working directory. |
136 | .It Ic ls Op Ar path | 141 | .It Ic ls Op Ar path |
@@ -152,8 +157,8 @@ Create remote directory specified by | |||
152 | .Xc | 157 | .Xc |
153 | Upload | 158 | Upload |
154 | .Ar local-path | 159 | .Ar local-path |
155 | and store it on the remote machine. If the remote path name is not specified, | 160 | and store it on the remote machine. If the remote path name is not |
156 | it is given the same name it has on the local machine. If the | 161 | specified, it is given the same name it has on the local machine. If the |
157 | .Fl P | 162 | .Fl P |
158 | flag is specified, then the file's full permission and access time are | 163 | flag is specified, then the file's full permission and access time are |
159 | copied too. | 164 | copied too. |
@@ -172,6 +177,11 @@ Remove remote directory specified by | |||
172 | .It Ic rm Ar path | 177 | .It Ic rm Ar path |
173 | Delete remote file specified by | 178 | Delete remote file specified by |
174 | .Ar path . | 179 | .Ar path . |
180 | .It Ic symlink Ar oldpath Ar newpath | ||
181 | Create a symbolic link from | ||
182 | .Ar oldpath | ||
183 | to | ||
184 | .Ar newpath . | ||
175 | .It Ic ! Ar command | 185 | .It Ic ! Ar command |
176 | Execute | 186 | Execute |
177 | .Ar command | 187 | .Ar command |
@@ -24,7 +24,7 @@ | |||
24 | 24 | ||
25 | #include "includes.h" | 25 | #include "includes.h" |
26 | 26 | ||
27 | RCSID("$OpenBSD: sftp.c,v 1.10 2001/03/06 06:11:44 deraadt Exp $"); | 27 | RCSID("$OpenBSD: sftp.c,v 1.11 2001/03/07 10:11:23 djm Exp $"); |
28 | 28 | ||
29 | /* XXX: commandline mode */ | 29 | /* XXX: commandline mode */ |
30 | /* XXX: copy between two remote hosts (commandline) */ | 30 | /* XXX: copy between two remote hosts (commandline) */ |
@@ -256,8 +256,6 @@ main(int argc, char **argv) | |||
256 | 256 | ||
257 | connect_to_server(make_ssh_args(NULL), &in, &out, &sshpid); | 257 | connect_to_server(make_ssh_args(NULL), &in, &out, &sshpid); |
258 | 258 | ||
259 | do_init(in, out); | ||
260 | |||
261 | interactive_loop(in, out); | 259 | interactive_loop(in, out); |
262 | 260 | ||
263 | #if !defined(USE_PIPES) | 261 | #if !defined(USE_PIPES) |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sftp.h,v 1.2 2001/01/29 01:58:18 niklas Exp $ */ | 1 | /* $OpenBSD: sftp.h,v 1.3 2001/03/07 10:11:23 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2001 Markus Friedl. All rights reserved. |
@@ -25,11 +25,11 @@ | |||
25 | */ | 25 | */ |
26 | 26 | ||
27 | /* | 27 | /* |
28 | * draft-ietf-secsh-filexfer-00.txt | 28 | * draft-ietf-secsh-filexfer-01.txt |
29 | */ | 29 | */ |
30 | 30 | ||
31 | /* version */ | 31 | /* version */ |
32 | #define SSH2_FILEXFER_VERSION 2 | 32 | #define SSH2_FILEXFER_VERSION 3 |
33 | 33 | ||
34 | /* client to server */ | 34 | /* client to server */ |
35 | #define SSH2_FXP_INIT 1 | 35 | #define SSH2_FXP_INIT 1 |
@@ -49,6 +49,8 @@ | |||
49 | #define SSH2_FXP_REALPATH 16 | 49 | #define SSH2_FXP_REALPATH 16 |
50 | #define SSH2_FXP_STAT 17 | 50 | #define SSH2_FXP_STAT 17 |
51 | #define SSH2_FXP_RENAME 18 | 51 | #define SSH2_FXP_RENAME 18 |
52 | #define SSH2_FXP_READLINK 19 | ||
53 | #define SSH2_FXP_SYMLINK 20 | ||
52 | 54 | ||
53 | /* server to client */ | 55 | /* server to client */ |
54 | #define SSH2_FXP_VERSION 2 | 56 | #define SSH2_FXP_VERSION 2 |
@@ -86,3 +88,4 @@ | |||
86 | #define SSH2_FX_NO_CONNECTION 6 | 88 | #define SSH2_FX_NO_CONNECTION 6 |
87 | #define SSH2_FX_CONNECTION_LOST 7 | 89 | #define SSH2_FX_CONNECTION_LOST 7 |
88 | #define SSH2_FX_OP_UNSUPPORTED 8 | 90 | #define SSH2_FX_OP_UNSUPPORTED 8 |
91 | #define SSH2_FX_MAX 8 | ||