summaryrefslogtreecommitdiff
path: root/sftp-int.c
diff options
context:
space:
mode:
Diffstat (limited to 'sftp-int.c')
-rw-r--r--sftp-int.c197
1 files changed, 130 insertions, 67 deletions
diff --git a/sftp-int.c b/sftp-int.c
index 6a2012910..6987de9a3 100644
--- a/sftp-int.c
+++ b/sftp-int.c
@@ -25,7 +25,7 @@
25/* XXX: recursive operations */ 25/* XXX: recursive operations */
26 26
27#include "includes.h" 27#include "includes.h"
28RCSID("$OpenBSD: sftp-int.c,v 1.49 2002/09/12 00:13:06 djm Exp $"); 28RCSID("$OpenBSD: sftp-int.c,v 1.57 2003/03/05 22:33:43 markus Exp $");
29 29
30#include "buffer.h" 30#include "buffer.h"
31#include "xmalloc.h" 31#include "xmalloc.h"
@@ -47,6 +47,9 @@ extern size_t copy_buffer_len;
47/* Number of concurrent outstanding requests */ 47/* Number of concurrent outstanding requests */
48extern int num_requests; 48extern int num_requests;
49 49
50/* This is set to 0 if the progressmeter is not desired. */
51int showprogress = 1;
52
50/* Seperators for interactive commands */ 53/* Seperators for interactive commands */
51#define WHITESPACE " \t\r\n" 54#define WHITESPACE " \t\r\n"
52 55
@@ -73,13 +76,14 @@ extern int num_requests;
73#define I_SHELL 20 76#define I_SHELL 20
74#define I_SYMLINK 21 77#define I_SYMLINK 21
75#define I_VERSION 22 78#define I_VERSION 22
79#define I_PROGRESS 23
76 80
77struct CMD { 81struct CMD {
78 const char *c; 82 const char *c;
79 const int n; 83 const int n;
80}; 84};
81 85
82const struct CMD cmds[] = { 86static const struct CMD cmds[] = {
83 { "bye", I_QUIT }, 87 { "bye", I_QUIT },
84 { "cd", I_CHDIR }, 88 { "cd", I_CHDIR },
85 { "chdir", I_CHDIR }, 89 { "chdir", I_CHDIR },
@@ -100,6 +104,7 @@ const struct CMD cmds[] = {
100 { "ls", I_LS }, 104 { "ls", I_LS },
101 { "lumask", I_LUMASK }, 105 { "lumask", I_LUMASK },
102 { "mkdir", I_MKDIR }, 106 { "mkdir", I_MKDIR },
107 { "progress", I_PROGRESS },
103 { "put", I_PUT }, 108 { "put", I_PUT },
104 { "mput", I_PUT }, 109 { "mput", I_PUT },
105 { "pwd", I_PWD }, 110 { "pwd", I_PWD },
@@ -132,6 +137,7 @@ help(void)
132 printf("ls [path] Display remote directory listing\n"); 137 printf("ls [path] Display remote directory listing\n");
133 printf("lumask umask Set local umask to 'umask'\n"); 138 printf("lumask umask Set local umask to 'umask'\n");
134 printf("mkdir path Create remote directory\n"); 139 printf("mkdir path Create remote directory\n");
140 printf("progress Toggle display of progress meter\n");
135 printf("put local-path [remote-path] Upload file\n"); 141 printf("put local-path [remote-path] Upload file\n");
136 printf("pwd Display remote working directory\n"); 142 printf("pwd Display remote working directory\n");
137 printf("exit Quit sftp\n"); 143 printf("exit Quit sftp\n");
@@ -375,6 +381,17 @@ is_dir(char *path)
375} 381}
376 382
377static int 383static int
384is_reg(char *path)
385{
386 struct stat sb;
387
388 if (stat(path, &sb) == -1)
389 fatal("stat %s: %s", path, strerror(errno));
390
391 return(S_ISREG(sb.st_mode));
392}
393
394static int
378remote_is_dir(struct sftp_conn *conn, char *path) 395remote_is_dir(struct sftp_conn *conn, char *path)
379{ 396{
380 Attrib *a; 397 Attrib *a;
@@ -425,7 +442,6 @@ process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag)
425 err = -1; 442 err = -1;
426 goto out; 443 goto out;
427 } 444 }
428 printf("Fetching %s to %s\n", g.gl_pathv[0], abs_dst);
429 err = do_download(conn, g.gl_pathv[0], abs_dst, pflag); 445 err = do_download(conn, g.gl_pathv[0], abs_dst, pflag);
430 goto out; 446 goto out;
431 } 447 }
@@ -489,6 +505,12 @@ process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag)
489 505
490 /* Only one match, dst may be file, directory or unspecified */ 506 /* Only one match, dst may be file, directory or unspecified */
491 if (g.gl_pathv[0] && g.gl_matchc == 1) { 507 if (g.gl_pathv[0] && g.gl_matchc == 1) {
508 if (!is_reg(g.gl_pathv[0])) {
509 error("Can't upload %s: not a regular file",
510 g.gl_pathv[0]);
511 err = 1;
512 goto out;
513 }
492 if (tmp_dst) { 514 if (tmp_dst) {
493 /* If directory specified, append filename */ 515 /* If directory specified, append filename */
494 if (remote_is_dir(conn, tmp_dst)) { 516 if (remote_is_dir(conn, tmp_dst)) {
@@ -507,7 +529,6 @@ process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag)
507 } 529 }
508 abs_dst = make_absolute(abs_dst, pwd); 530 abs_dst = make_absolute(abs_dst, pwd);
509 } 531 }
510 printf("Uploading %s to %s\n", g.gl_pathv[0], abs_dst);
511 err = do_upload(conn, g.gl_pathv[0], abs_dst, pflag); 532 err = do_upload(conn, g.gl_pathv[0], abs_dst, pflag);
512 goto out; 533 goto out;
513 } 534 }
@@ -521,6 +542,11 @@ process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag)
521 } 542 }
522 543
523 for (i = 0; g.gl_pathv[i]; i++) { 544 for (i = 0; g.gl_pathv[i]; i++) {
545 if (!is_reg(g.gl_pathv[i])) {
546 error("skipping non-regular file %s",
547 g.gl_pathv[i]);
548 continue;
549 }
524 if (infer_path(g.gl_pathv[i], &tmp)) { 550 if (infer_path(g.gl_pathv[i], &tmp)) {
525 err = -1; 551 err = -1;
526 goto out; 552 goto out;
@@ -550,7 +576,7 @@ sdirent_comp(const void *aa, const void *bb)
550 SFTP_DIRENT *a = *(SFTP_DIRENT **)aa; 576 SFTP_DIRENT *a = *(SFTP_DIRENT **)aa;
551 SFTP_DIRENT *b = *(SFTP_DIRENT **)bb; 577 SFTP_DIRENT *b = *(SFTP_DIRENT **)bb;
552 578
553 return (strcmp(a->filename, b->filename)); 579 return (strcmp(a->filename, b->filename));
554} 580}
555 581
556/* sftp ls.1 replacement for directories */ 582/* sftp ls.1 replacement for directories */
@@ -563,7 +589,7 @@ do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag)
563 if ((n = do_readdir(conn, path, &d)) != 0) 589 if ((n = do_readdir(conn, path, &d)) != 0)
564 return (n); 590 return (n);
565 591
566 /* Count entries for sort */ 592 /* Count entries for sort */
567 for (n = 0; d[n] != NULL; n++) 593 for (n = 0; d[n] != NULL; n++)
568 ; 594 ;
569 595
@@ -571,7 +597,7 @@ do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag)
571 597
572 for (n = 0; d[n] != NULL; n++) { 598 for (n = 0; d[n] != NULL; n++) {
573 char *tmp, *fname; 599 char *tmp, *fname;
574 600
575 tmp = path_append(path, d[n]->filename); 601 tmp = path_append(path, d[n]->filename);
576 fname = path_strip(tmp, strip_path); 602 fname = path_strip(tmp, strip_path);
577 xfree(tmp); 603 xfree(tmp);
@@ -589,7 +615,7 @@ do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag)
589 /* XXX - multicolumn display would be nice here */ 615 /* XXX - multicolumn display would be nice here */
590 printf("%s\n", fname); 616 printf("%s\n", fname);
591 } 617 }
592 618
593 xfree(fname); 619 xfree(fname);
594 } 620 }
595 621
@@ -599,7 +625,7 @@ do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag)
599 625
600/* sftp ls.1 replacement which handles path globs */ 626/* sftp ls.1 replacement which handles path globs */
601static int 627static int
602do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path, 628do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
603 int lflag) 629 int lflag)
604{ 630{
605 glob_t g; 631 glob_t g;
@@ -609,23 +635,23 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
609 635
610 memset(&g, 0, sizeof(g)); 636 memset(&g, 0, sizeof(g));
611 637
612 if (remote_glob(conn, path, GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE, 638 if (remote_glob(conn, path, GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE,
613 NULL, &g)) { 639 NULL, &g)) {
614 error("Can't ls: \"%s\" not found", path); 640 error("Can't ls: \"%s\" not found", path);
615 return (-1); 641 return (-1);
616 } 642 }
617 643
618 /* 644 /*
619 * If the glob returns a single match, which is the same as the 645 * If the glob returns a single match, which is the same as the
620 * input glob, and it is a directory, then just list its contents 646 * input glob, and it is a directory, then just list its contents
621 */ 647 */
622 if (g.gl_pathc == 1 && 648 if (g.gl_pathc == 1 &&
623 strncmp(path, g.gl_pathv[0], strlen(g.gl_pathv[0]) - 1) == 0) { 649 strncmp(path, g.gl_pathv[0], strlen(g.gl_pathv[0]) - 1) == 0) {
624 if ((a = do_lstat(conn, path, 1)) == NULL) { 650 if ((a = do_lstat(conn, path, 1)) == NULL) {
625 globfree(&g); 651 globfree(&g);
626 return (-1); 652 return (-1);
627 } 653 }
628 if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && 654 if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
629 S_ISDIR(a->perm)) { 655 S_ISDIR(a->perm)) {
630 globfree(&g); 656 globfree(&g);
631 return (do_ls_dir(conn, path, strip_path, lflag)); 657 return (do_ls_dir(conn, path, strip_path, lflag));
@@ -640,8 +666,8 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
640 if (lflag) { 666 if (lflag) {
641 /* 667 /*
642 * XXX: this is slow - 1 roundtrip per path 668 * XXX: this is slow - 1 roundtrip per path
643 * A solution to this is to fork glob() and 669 * A solution to this is to fork glob() and
644 * build a sftp specific version which keeps the 670 * build a sftp specific version which keeps the
645 * attribs (which currently get thrown away) 671 * attribs (which currently get thrown away)
646 * that the server returns as well as the filenames. 672 * that the server returns as well as the filenames.
647 */ 673 */
@@ -666,7 +692,7 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
666} 692}
667 693
668static int 694static int
669parse_args(const char **cpp, int *pflag, int *lflag, 695parse_args(const char **cpp, int *pflag, int *lflag, int *iflag,
670 unsigned long *n_arg, char **path1, char **path2) 696 unsigned long *n_arg, char **path1, char **path2)
671{ 697{
672 const char *cmd, *cp = *cpp; 698 const char *cmd, *cp = *cpp;
@@ -678,10 +704,17 @@ parse_args(const char **cpp, int *pflag, int *lflag,
678 /* Skip leading whitespace */ 704 /* Skip leading whitespace */
679 cp = cp + strspn(cp, WHITESPACE); 705 cp = cp + strspn(cp, WHITESPACE);
680 706
681 /* Ignore blank lines */ 707 /* Ignore blank lines and lines which begin with comment '#' char */
682 if (!*cp) 708 if (*cp == '\0' || *cp == '#')
683 return(-1); 709 return (0);
684 710
711 /* Check for leading '-' (disable error processing) */
712 *iflag = 0;
713 if (*cp == '-') {
714 *iflag = 1;
715 cp++;
716 }
717
685 /* Figure out which command we have */ 718 /* Figure out which command we have */
686 for (i = 0; cmds[i].c; i++) { 719 for (i = 0; cmds[i].c; i++) {
687 int cmdlen = strlen(cmds[i].c); 720 int cmdlen = strlen(cmds[i].c);
@@ -703,7 +736,7 @@ parse_args(const char **cpp, int *pflag, int *lflag,
703 cmdnum = I_SHELL; 736 cmdnum = I_SHELL;
704 } else if (cmdnum == -1) { 737 } else if (cmdnum == -1) {
705 error("Invalid command."); 738 error("Invalid command.");
706 return(-1); 739 return (-1);
707 } 740 }
708 741
709 /* Get arguments and parse flags */ 742 /* Get arguments and parse flags */
@@ -803,6 +836,7 @@ parse_args(const char **cpp, int *pflag, int *lflag,
803 case I_LPWD: 836 case I_LPWD:
804 case I_HELP: 837 case I_HELP:
805 case I_VERSION: 838 case I_VERSION:
839 case I_PROGRESS:
806 break; 840 break;
807 default: 841 default:
808 fatal("Command not implemented"); 842 fatal("Command not implemented");
@@ -813,10 +847,11 @@ parse_args(const char **cpp, int *pflag, int *lflag,
813} 847}
814 848
815static int 849static int
816parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd) 850parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
851 int err_abort)
817{ 852{
818 char *path1, *path2, *tmp; 853 char *path1, *path2, *tmp;
819 int pflag, lflag, cmdnum, i; 854 int pflag, lflag, iflag, cmdnum, i;
820 unsigned long n_arg; 855 unsigned long n_arg;
821 Attrib a, *aa; 856 Attrib a, *aa;
822 char path_buf[MAXPATHLEN]; 857 char path_buf[MAXPATHLEN];
@@ -824,14 +859,22 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd)
824 glob_t g; 859 glob_t g;
825 860
826 path1 = path2 = NULL; 861 path1 = path2 = NULL;
827 cmdnum = parse_args(&cmd, &pflag, &lflag, &n_arg, 862 cmdnum = parse_args(&cmd, &pflag, &lflag, &iflag, &n_arg,
828 &path1, &path2); 863 &path1, &path2);
829 864
865 if (iflag != 0)
866 err_abort = 0;
867
830 memset(&g, 0, sizeof(g)); 868 memset(&g, 0, sizeof(g));
831 869
832 /* Perform command */ 870 /* Perform command */
833 switch (cmdnum) { 871 switch (cmdnum) {
872 case 0:
873 /* Blank line */
874 break;
834 case -1: 875 case -1:
876 /* Unrecognized command */
877 err = -1;
835 break; 878 break;
836 case I_GET: 879 case I_GET:
837 err = process_get(conn, path1, path2, *pwd, pflag); 880 err = process_get(conn, path1, path2, *pwd, pflag);
@@ -853,8 +896,9 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd)
853 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); 896 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
854 for (i = 0; g.gl_pathv[i]; i++) { 897 for (i = 0; g.gl_pathv[i]; i++) {
855 printf("Removing %s\n", g.gl_pathv[i]); 898 printf("Removing %s\n", g.gl_pathv[i]);
856 if (do_rm(conn, g.gl_pathv[i]) == -1) 899 err = do_rm(conn, g.gl_pathv[i]);
857 err = -1; 900 if (err != 0 && err_abort)
901 break;
858 } 902 }
859 break; 903 break;
860 case I_MKDIR: 904 case I_MKDIR:
@@ -900,15 +944,14 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd)
900 do_globbed_ls(conn, *pwd, *pwd, lflag); 944 do_globbed_ls(conn, *pwd, *pwd, lflag);
901 break; 945 break;
902 } 946 }
903 947
904 /* Strip pwd off beginning of non-absolute paths */ 948 /* Strip pwd off beginning of non-absolute paths */
905 tmp = NULL; 949 tmp = NULL;
906 if (*path1 != '/') 950 if (*path1 != '/')
907 tmp = *pwd; 951 tmp = *pwd;
908 952
909 path1 = make_absolute(path1, *pwd); 953 path1 = make_absolute(path1, *pwd);
910 954 err = do_globbed_ls(conn, path1, tmp, lflag);
911 do_globbed_ls(conn, path1, tmp, lflag);
912 break; 955 break;
913 case I_LCHDIR: 956 case I_LCHDIR:
914 if (chdir(path1) == -1) { 957 if (chdir(path1) == -1) {
@@ -942,62 +985,70 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd)
942 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); 985 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
943 for (i = 0; g.gl_pathv[i]; i++) { 986 for (i = 0; g.gl_pathv[i]; i++) {
944 printf("Changing mode on %s\n", g.gl_pathv[i]); 987 printf("Changing mode on %s\n", g.gl_pathv[i]);
945 do_setstat(conn, g.gl_pathv[i], &a); 988 err = do_setstat(conn, g.gl_pathv[i], &a);
989 if (err != 0 && err_abort)
990 break;
946 } 991 }
947 break; 992 break;
948 case I_CHOWN: 993 case I_CHOWN:
949 path1 = make_absolute(path1, *pwd);
950 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
951 for (i = 0; g.gl_pathv[i]; i++) {
952 if (!(aa = do_stat(conn, g.gl_pathv[i], 0)))
953 continue;
954 if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) {
955 error("Can't get current ownership of "
956 "remote file \"%s\"", g.gl_pathv[i]);
957 continue;
958 }
959 printf("Changing owner on %s\n", g.gl_pathv[i]);
960 aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;
961 aa->uid = n_arg;
962 do_setstat(conn, g.gl_pathv[i], aa);
963 }
964 break;
965 case I_CHGRP: 994 case I_CHGRP:
966 path1 = make_absolute(path1, *pwd); 995 path1 = make_absolute(path1, *pwd);
967 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); 996 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
968 for (i = 0; g.gl_pathv[i]; i++) { 997 for (i = 0; g.gl_pathv[i]; i++) {
969 if (!(aa = do_stat(conn, g.gl_pathv[i], 0))) 998 if (!(aa = do_stat(conn, g.gl_pathv[i], 0))) {
970 continue; 999 if (err != 0 && err_abort)
1000 break;
1001 else
1002 continue;
1003 }
971 if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { 1004 if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) {
972 error("Can't get current ownership of " 1005 error("Can't get current ownership of "
973 "remote file \"%s\"", g.gl_pathv[i]); 1006 "remote file \"%s\"", g.gl_pathv[i]);
974 continue; 1007 if (err != 0 && err_abort)
1008 break;
1009 else
1010 continue;
975 } 1011 }
976 printf("Changing group on %s\n", g.gl_pathv[i]);
977 aa->flags &= SSH2_FILEXFER_ATTR_UIDGID; 1012 aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;
978 aa->gid = n_arg; 1013 if (cmdnum == I_CHOWN) {
979 do_setstat(conn, g.gl_pathv[i], aa); 1014 printf("Changing owner on %s\n", g.gl_pathv[i]);
1015 aa->uid = n_arg;
1016 } else {
1017 printf("Changing group on %s\n", g.gl_pathv[i]);
1018 aa->gid = n_arg;
1019 }
1020 err = do_setstat(conn, g.gl_pathv[i], aa);
1021 if (err != 0 && err_abort)
1022 break;
980 } 1023 }
981 break; 1024 break;
982 case I_PWD: 1025 case I_PWD:
983 printf("Remote working directory: %s\n", *pwd); 1026 printf("Remote working directory: %s\n", *pwd);
984 break; 1027 break;
985 case I_LPWD: 1028 case I_LPWD:
986 if (!getcwd(path_buf, sizeof(path_buf))) 1029 if (!getcwd(path_buf, sizeof(path_buf))) {
987 error("Couldn't get local cwd: %s", 1030 error("Couldn't get local cwd: %s", strerror(errno));
988 strerror(errno)); 1031 err = -1;
989 else 1032 break;
990 printf("Local working directory: %s\n", 1033 }
991 path_buf); 1034 printf("Local working directory: %s\n", path_buf);
992 break; 1035 break;
993 case I_QUIT: 1036 case I_QUIT:
994 return(-1); 1037 /* Processed below */
1038 break;
995 case I_HELP: 1039 case I_HELP:
996 help(); 1040 help();
997 break; 1041 break;
998 case I_VERSION: 1042 case I_VERSION:
999 printf("SFTP protocol version %u\n", sftp_proto_version(conn)); 1043 printf("SFTP protocol version %u\n", sftp_proto_version(conn));
1000 break; 1044 break;
1045 case I_PROGRESS:
1046 showprogress = !showprogress;
1047 if (showprogress)
1048 printf("Progress meter enabled\n");
1049 else
1050 printf("Progress meter disabled\n");
1051 break;
1001 default: 1052 default:
1002 fatal("%d is not implemented", cmdnum); 1053 fatal("%d is not implemented", cmdnum);
1003 } 1054 }
@@ -1009,20 +1060,23 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd)
1009 if (path2) 1060 if (path2)
1010 xfree(path2); 1061 xfree(path2);
1011 1062
1012 /* If an error occurs in batch mode we should abort. */ 1063 /* If an unignored error occurs in batch mode we should abort. */
1013 if (infile != stdin && err > 0) 1064 if (err_abort && err != 0)
1014 return -1; 1065 return (-1);
1066 else if (cmdnum == I_QUIT)
1067 return (1);
1015 1068
1016 return(0); 1069 return (0);
1017} 1070}
1018 1071
1019void 1072int
1020interactive_loop(int fd_in, int fd_out, char *file1, char *file2) 1073interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
1021{ 1074{
1022 char *pwd; 1075 char *pwd;
1023 char *dir = NULL; 1076 char *dir = NULL;
1024 char cmd[2048]; 1077 char cmd[2048];
1025 struct sftp_conn *conn; 1078 struct sftp_conn *conn;
1079 int err;
1026 1080
1027 conn = do_init(fd_in, fd_out, copy_buffer_len, num_requests); 1081 conn = do_init(fd_in, fd_out, copy_buffer_len, num_requests);
1028 if (conn == NULL) 1082 if (conn == NULL)
@@ -1039,7 +1093,8 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
1039 if (remote_is_dir(conn, dir) && file2 == NULL) { 1093 if (remote_is_dir(conn, dir) && file2 == NULL) {
1040 printf("Changing to: %s\n", dir); 1094 printf("Changing to: %s\n", dir);
1041 snprintf(cmd, sizeof cmd, "cd \"%s\"", dir); 1095 snprintf(cmd, sizeof cmd, "cd \"%s\"", dir);
1042 parse_dispatch_command(conn, cmd, &pwd); 1096 if (parse_dispatch_command(conn, cmd, &pwd, 1) != 0)
1097 return (-1);
1043 } else { 1098 } else {
1044 if (file2 == NULL) 1099 if (file2 == NULL)
1045 snprintf(cmd, sizeof cmd, "get %s", dir); 1100 snprintf(cmd, sizeof cmd, "get %s", dir);
@@ -1047,12 +1102,14 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
1047 snprintf(cmd, sizeof cmd, "get %s %s", dir, 1102 snprintf(cmd, sizeof cmd, "get %s %s", dir,
1048 file2); 1103 file2);
1049 1104
1050 parse_dispatch_command(conn, cmd, &pwd); 1105 err = parse_dispatch_command(conn, cmd, &pwd, 1);
1051 xfree(dir); 1106 xfree(dir);
1052 return; 1107 xfree(pwd);
1108 return (err);
1053 } 1109 }
1054 xfree(dir); 1110 xfree(dir);
1055 } 1111 }
1112
1056#if HAVE_SETVBUF 1113#if HAVE_SETVBUF
1057 setvbuf(stdout, NULL, _IOLBF, 0); 1114 setvbuf(stdout, NULL, _IOLBF, 0);
1058 setvbuf(infile, NULL, _IOLBF, 0); 1115 setvbuf(infile, NULL, _IOLBF, 0);
@@ -1061,6 +1118,7 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
1061 setlinebuf(infile); 1118 setlinebuf(infile);
1062#endif 1119#endif
1063 1120
1121 err = 0;
1064 for (;;) { 1122 for (;;) {
1065 char *cp; 1123 char *cp;
1066 1124
@@ -1077,8 +1135,13 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
1077 if (cp) 1135 if (cp)
1078 *cp = '\0'; 1136 *cp = '\0';
1079 1137
1080 if (parse_dispatch_command(conn, cmd, &pwd)) 1138 err = parse_dispatch_command(conn, cmd, &pwd, infile != stdin);
1139 if (err != 0)
1081 break; 1140 break;
1082 } 1141 }
1083 xfree(pwd); 1142 xfree(pwd);
1143
1144 /* err == 1 signifies normal "quit" exit */
1145 return (err >= 0 ? 0 : -1);
1084} 1146}
1147