diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | sftp-int.c | 132 | ||||
-rw-r--r-- | sftp-int.h | 4 | ||||
-rw-r--r-- | sftp.1 | 11 | ||||
-rw-r--r-- | sftp.c | 8 |
5 files changed, 103 insertions, 61 deletions
@@ -1,6 +1,13 @@ | |||
1 | 20030110 | 1 | 20030110 |
2 | - (djm) Enable new setproctitle emulation for Linux, AIX and HP/UX. More | 2 | - (djm) Enable new setproctitle emulation for Linux, AIX and HP/UX. More |
3 | systems may be added later. | 3 | systems may be added later. |
4 | - (djm) OpenBSD CVS Sync | ||
5 | - djm@cvs.openbsd.org 2003/01/08 23:53:26 | ||
6 | [sftp.1 sftp.c sftp-int.c sftp-int.h] | ||
7 | Cleanup error handling for batchmode | ||
8 | Allow blank lines and comments in input | ||
9 | Ability to suppress abort on error in batchmode ("-put blah") | ||
10 | Fixes mindrot bug #452; markus@ ok | ||
4 | 11 | ||
5 | 20030108 | 12 | 20030108 |
6 | - (djm) Sync openbsd-compat/ with OpenBSD -current | 13 | - (djm) Sync openbsd-compat/ with OpenBSD -current |
@@ -969,4 +976,4 @@ | |||
969 | save auth method before monitor_reset_key_state(); bugzilla bug #284; | 976 | save auth method before monitor_reset_key_state(); bugzilla bug #284; |
970 | ok provos@ | 977 | ok provos@ |
971 | 978 | ||
972 | $Id: ChangeLog,v 1.2558 2003/01/09 22:53:12 djm Exp $ | 979 | $Id: ChangeLog,v 1.2559 2003/01/10 10:40:00 djm Exp $ |
diff --git a/sftp-int.c b/sftp-int.c index 04b67c969..f2c8fa6dc 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" |
28 | RCSID("$OpenBSD: sftp-int.c,v 1.50 2002/11/21 23:03:51 deraadt Exp $"); | 28 | RCSID("$OpenBSD: sftp-int.c,v 1.51 2003/01/08 23:53:26 djm Exp $"); |
29 | 29 | ||
30 | #include "buffer.h" | 30 | #include "buffer.h" |
31 | #include "xmalloc.h" | 31 | #include "xmalloc.h" |
@@ -666,7 +666,7 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path, | |||
666 | } | 666 | } |
667 | 667 | ||
668 | static int | 668 | static int |
669 | parse_args(const char **cpp, int *pflag, int *lflag, | 669 | parse_args(const char **cpp, int *pflag, int *lflag, int *iflag, |
670 | unsigned long *n_arg, char **path1, char **path2) | 670 | unsigned long *n_arg, char **path1, char **path2) |
671 | { | 671 | { |
672 | const char *cmd, *cp = *cpp; | 672 | const char *cmd, *cp = *cpp; |
@@ -678,10 +678,17 @@ parse_args(const char **cpp, int *pflag, int *lflag, | |||
678 | /* Skip leading whitespace */ | 678 | /* Skip leading whitespace */ |
679 | cp = cp + strspn(cp, WHITESPACE); | 679 | cp = cp + strspn(cp, WHITESPACE); |
680 | 680 | ||
681 | /* Ignore blank lines */ | 681 | /* Ignore blank lines and lines which begin with comment '#' char */ |
682 | if (!*cp) | 682 | if (*cp == '\0' || *cp == '#') |
683 | return(-1); | 683 | return (0); |
684 | 684 | ||
685 | /* Check for leading '-' (disable error processing) */ | ||
686 | *iflag = 0; | ||
687 | if (*cp == '-') { | ||
688 | *iflag = 1; | ||
689 | cp++; | ||
690 | } | ||
691 | |||
685 | /* Figure out which command we have */ | 692 | /* Figure out which command we have */ |
686 | for (i = 0; cmds[i].c; i++) { | 693 | for (i = 0; cmds[i].c; i++) { |
687 | int cmdlen = strlen(cmds[i].c); | 694 | int cmdlen = strlen(cmds[i].c); |
@@ -703,7 +710,7 @@ parse_args(const char **cpp, int *pflag, int *lflag, | |||
703 | cmdnum = I_SHELL; | 710 | cmdnum = I_SHELL; |
704 | } else if (cmdnum == -1) { | 711 | } else if (cmdnum == -1) { |
705 | error("Invalid command."); | 712 | error("Invalid command."); |
706 | return(-1); | 713 | return (-1); |
707 | } | 714 | } |
708 | 715 | ||
709 | /* Get arguments and parse flags */ | 716 | /* Get arguments and parse flags */ |
@@ -813,10 +820,11 @@ parse_args(const char **cpp, int *pflag, int *lflag, | |||
813 | } | 820 | } |
814 | 821 | ||
815 | static int | 822 | static int |
816 | parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd) | 823 | parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, |
824 | int err_abort) | ||
817 | { | 825 | { |
818 | char *path1, *path2, *tmp; | 826 | char *path1, *path2, *tmp; |
819 | int pflag, lflag, cmdnum, i; | 827 | int pflag, lflag, iflag, cmdnum, i; |
820 | unsigned long n_arg; | 828 | unsigned long n_arg; |
821 | Attrib a, *aa; | 829 | Attrib a, *aa; |
822 | char path_buf[MAXPATHLEN]; | 830 | char path_buf[MAXPATHLEN]; |
@@ -824,14 +832,22 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd) | |||
824 | glob_t g; | 832 | glob_t g; |
825 | 833 | ||
826 | path1 = path2 = NULL; | 834 | path1 = path2 = NULL; |
827 | cmdnum = parse_args(&cmd, &pflag, &lflag, &n_arg, | 835 | cmdnum = parse_args(&cmd, &pflag, &lflag, &iflag, &n_arg, |
828 | &path1, &path2); | 836 | &path1, &path2); |
829 | 837 | ||
838 | if (iflag != 0) | ||
839 | err_abort = 0; | ||
840 | |||
830 | memset(&g, 0, sizeof(g)); | 841 | memset(&g, 0, sizeof(g)); |
831 | 842 | ||
832 | /* Perform command */ | 843 | /* Perform command */ |
833 | switch (cmdnum) { | 844 | switch (cmdnum) { |
845 | case 0: | ||
846 | /* Blank line */ | ||
847 | break; | ||
834 | case -1: | 848 | case -1: |
849 | /* Unrecognized command */ | ||
850 | err = -1; | ||
835 | break; | 851 | break; |
836 | case I_GET: | 852 | case I_GET: |
837 | err = process_get(conn, path1, path2, *pwd, pflag); | 853 | err = process_get(conn, path1, path2, *pwd, pflag); |
@@ -853,8 +869,9 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd) | |||
853 | remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); | 869 | remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); |
854 | for (i = 0; g.gl_pathv[i]; i++) { | 870 | for (i = 0; g.gl_pathv[i]; i++) { |
855 | printf("Removing %s\n", g.gl_pathv[i]); | 871 | printf("Removing %s\n", g.gl_pathv[i]); |
856 | if (do_rm(conn, g.gl_pathv[i]) == -1) | 872 | err = do_rm(conn, g.gl_pathv[i]); |
857 | err = -1; | 873 | if (err != 0 && err_abort) |
874 | break; | ||
858 | } | 875 | } |
859 | break; | 876 | break; |
860 | case I_MKDIR: | 877 | case I_MKDIR: |
@@ -907,8 +924,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd) | |||
907 | tmp = *pwd; | 924 | tmp = *pwd; |
908 | 925 | ||
909 | path1 = make_absolute(path1, *pwd); | 926 | path1 = make_absolute(path1, *pwd); |
910 | 927 | err = do_globbed_ls(conn, path1, tmp, lflag); | |
911 | do_globbed_ls(conn, path1, tmp, lflag); | ||
912 | break; | 928 | break; |
913 | case I_LCHDIR: | 929 | case I_LCHDIR: |
914 | if (chdir(path1) == -1) { | 930 | if (chdir(path1) == -1) { |
@@ -942,56 +958,57 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd) | |||
942 | remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); | 958 | remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); |
943 | for (i = 0; g.gl_pathv[i]; i++) { | 959 | for (i = 0; g.gl_pathv[i]; i++) { |
944 | printf("Changing mode on %s\n", g.gl_pathv[i]); | 960 | printf("Changing mode on %s\n", g.gl_pathv[i]); |
945 | do_setstat(conn, g.gl_pathv[i], &a); | 961 | err = do_setstat(conn, g.gl_pathv[i], &a); |
962 | if (err != 0 && err_abort) | ||
963 | break; | ||
946 | } | 964 | } |
947 | break; | 965 | break; |
948 | case I_CHOWN: | 966 | 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: | 967 | case I_CHGRP: |
966 | path1 = make_absolute(path1, *pwd); | 968 | path1 = make_absolute(path1, *pwd); |
967 | remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); | 969 | remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); |
968 | for (i = 0; g.gl_pathv[i]; i++) { | 970 | for (i = 0; g.gl_pathv[i]; i++) { |
969 | if (!(aa = do_stat(conn, g.gl_pathv[i], 0))) | 971 | if (!(aa = do_stat(conn, g.gl_pathv[i], 0))) { |
970 | continue; | 972 | if (err != 0 && err_abort) |
973 | break; | ||
974 | else | ||
975 | continue; | ||
976 | } | ||
971 | if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { | 977 | if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { |
972 | error("Can't get current ownership of " | 978 | error("Can't get current ownership of " |
973 | "remote file \"%s\"", g.gl_pathv[i]); | 979 | "remote file \"%s\"", g.gl_pathv[i]); |
974 | continue; | 980 | if (err != 0 && err_abort) |
981 | break; | ||
982 | else | ||
983 | continue; | ||
975 | } | 984 | } |
976 | printf("Changing group on %s\n", g.gl_pathv[i]); | ||
977 | aa->flags &= SSH2_FILEXFER_ATTR_UIDGID; | 985 | aa->flags &= SSH2_FILEXFER_ATTR_UIDGID; |
978 | aa->gid = n_arg; | 986 | if (cmdnum == I_CHOWN) { |
979 | do_setstat(conn, g.gl_pathv[i], aa); | 987 | printf("Changing owner on %s\n", g.gl_pathv[i]); |
988 | aa->uid = n_arg; | ||
989 | } else { | ||
990 | printf("Changing group on %s\n", g.gl_pathv[i]); | ||
991 | aa->gid = n_arg; | ||
992 | } | ||
993 | err = do_setstat(conn, g.gl_pathv[i], aa); | ||
994 | if (err != 0 && err_abort) | ||
995 | break; | ||
980 | } | 996 | } |
981 | break; | 997 | break; |
982 | case I_PWD: | 998 | case I_PWD: |
983 | printf("Remote working directory: %s\n", *pwd); | 999 | printf("Remote working directory: %s\n", *pwd); |
984 | break; | 1000 | break; |
985 | case I_LPWD: | 1001 | case I_LPWD: |
986 | if (!getcwd(path_buf, sizeof(path_buf))) | 1002 | if (!getcwd(path_buf, sizeof(path_buf))) { |
987 | error("Couldn't get local cwd: %s", | 1003 | error("Couldn't get local cwd: %s", strerror(errno)); |
988 | strerror(errno)); | 1004 | err = -1; |
989 | else | 1005 | break; |
990 | printf("Local working directory: %s\n", | 1006 | } |
991 | path_buf); | 1007 | printf("Local working directory: %s\n", path_buf); |
992 | break; | 1008 | break; |
993 | case I_QUIT: | 1009 | case I_QUIT: |
994 | return(-1); | 1010 | /* Processed below */ |
1011 | break; | ||
995 | case I_HELP: | 1012 | case I_HELP: |
996 | help(); | 1013 | help(); |
997 | break; | 1014 | break; |
@@ -1009,20 +1026,23 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd) | |||
1009 | if (path2) | 1026 | if (path2) |
1010 | xfree(path2); | 1027 | xfree(path2); |
1011 | 1028 | ||
1012 | /* If an error occurs in batch mode we should abort. */ | 1029 | /* If an unignored error occurs in batch mode we should abort. */ |
1013 | if (infile != stdin && err > 0) | 1030 | if (err_abort && err != 0) |
1014 | return -1; | 1031 | return (-1); |
1032 | else if (cmdnum == I_QUIT) | ||
1033 | return (1); | ||
1015 | 1034 | ||
1016 | return(0); | 1035 | return (0); |
1017 | } | 1036 | } |
1018 | 1037 | ||
1019 | void | 1038 | int |
1020 | interactive_loop(int fd_in, int fd_out, char *file1, char *file2) | 1039 | interactive_loop(int fd_in, int fd_out, char *file1, char *file2) |
1021 | { | 1040 | { |
1022 | char *pwd; | 1041 | char *pwd; |
1023 | char *dir = NULL; | 1042 | char *dir = NULL; |
1024 | char cmd[2048]; | 1043 | char cmd[2048]; |
1025 | struct sftp_conn *conn; | 1044 | struct sftp_conn *conn; |
1045 | int err; | ||
1026 | 1046 | ||
1027 | conn = do_init(fd_in, fd_out, copy_buffer_len, num_requests); | 1047 | conn = do_init(fd_in, fd_out, copy_buffer_len, num_requests); |
1028 | if (conn == NULL) | 1048 | if (conn == NULL) |
@@ -1039,7 +1059,8 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2) | |||
1039 | if (remote_is_dir(conn, dir) && file2 == NULL) { | 1059 | if (remote_is_dir(conn, dir) && file2 == NULL) { |
1040 | printf("Changing to: %s\n", dir); | 1060 | printf("Changing to: %s\n", dir); |
1041 | snprintf(cmd, sizeof cmd, "cd \"%s\"", dir); | 1061 | snprintf(cmd, sizeof cmd, "cd \"%s\"", dir); |
1042 | parse_dispatch_command(conn, cmd, &pwd); | 1062 | if (parse_dispatch_command(conn, cmd, &pwd, 1) != 0) |
1063 | return (-1); | ||
1043 | } else { | 1064 | } else { |
1044 | if (file2 == NULL) | 1065 | if (file2 == NULL) |
1045 | snprintf(cmd, sizeof cmd, "get %s", dir); | 1066 | snprintf(cmd, sizeof cmd, "get %s", dir); |
@@ -1047,12 +1068,13 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2) | |||
1047 | snprintf(cmd, sizeof cmd, "get %s %s", dir, | 1068 | snprintf(cmd, sizeof cmd, "get %s %s", dir, |
1048 | file2); | 1069 | file2); |
1049 | 1070 | ||
1050 | parse_dispatch_command(conn, cmd, &pwd); | 1071 | err = parse_dispatch_command(conn, cmd, &pwd, 1); |
1051 | xfree(dir); | 1072 | xfree(dir); |
1052 | return; | 1073 | return (err); |
1053 | } | 1074 | } |
1054 | xfree(dir); | 1075 | xfree(dir); |
1055 | } | 1076 | } |
1077 | |||
1056 | #if HAVE_SETVBUF | 1078 | #if HAVE_SETVBUF |
1057 | setvbuf(stdout, NULL, _IOLBF, 0); | 1079 | setvbuf(stdout, NULL, _IOLBF, 0); |
1058 | setvbuf(infile, NULL, _IOLBF, 0); | 1080 | setvbuf(infile, NULL, _IOLBF, 0); |
@@ -1061,6 +1083,7 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2) | |||
1061 | setlinebuf(infile); | 1083 | setlinebuf(infile); |
1062 | #endif | 1084 | #endif |
1063 | 1085 | ||
1086 | err = 0; | ||
1064 | for (;;) { | 1087 | for (;;) { |
1065 | char *cp; | 1088 | char *cp; |
1066 | 1089 | ||
@@ -1077,8 +1100,13 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2) | |||
1077 | if (cp) | 1100 | if (cp) |
1078 | *cp = '\0'; | 1101 | *cp = '\0'; |
1079 | 1102 | ||
1080 | if (parse_dispatch_command(conn, cmd, &pwd)) | 1103 | err = parse_dispatch_command(conn, cmd, &pwd, infile != stdin); |
1104 | if (err != 0) | ||
1081 | break; | 1105 | break; |
1082 | } | 1106 | } |
1083 | xfree(pwd); | 1107 | xfree(pwd); |
1108 | |||
1109 | /* err == 1 signifies normal "quit" exit */ | ||
1110 | return (err >= 0 ? 0 : -1); | ||
1084 | } | 1111 | } |
1112 | |||
diff --git a/sftp-int.h b/sftp-int.h index 976875812..8a04a03f6 100644 --- a/sftp-int.h +++ b/sftp-int.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sftp-int.h,v 1.5 2002/02/13 00:59:23 djm Exp $ */ | 1 | /* $OpenBSD: sftp-int.h,v 1.6 2003/01/08 23:53:26 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2001,2002 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2001,2002 Damien Miller. All rights reserved. |
@@ -24,4 +24,4 @@ | |||
24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 | */ | 25 | */ |
26 | 26 | ||
27 | void interactive_loop(int, int, char *, char *); | 27 | int interactive_loop(int, int, char *, char *); |
@@ -1,4 +1,4 @@ | |||
1 | .\" $OpenBSD: sftp.1,v 1.38 2003/01/07 23:42:54 fgsch Exp $ | 1 | .\" $OpenBSD: sftp.1,v 1.39 2003/01/08 23:53:26 djm Exp $ |
2 | .\" | 2 | .\" |
3 | .\" Copyright (c) 2001 Damien Miller. All rights reserved. | 3 | .\" Copyright (c) 2001 Damien Miller. All rights reserved. |
4 | .\" | 4 | .\" |
@@ -77,9 +77,16 @@ non-interactive authentication. | |||
77 | will abort if any of the following | 77 | will abort if any of the following |
78 | commands fail: | 78 | commands fail: |
79 | .Ic get , put , rename , ln , | 79 | .Ic get , put , rename , ln , |
80 | .Ic rm , mkdir , chdir , lchdir | 80 | .Ic rm , mkdir , chdir , ls , |
81 | .Ic lchdir , chmod , chown , chgrp , lpwd | ||
81 | and | 82 | and |
82 | .Ic lmkdir . | 83 | .Ic lmkdir . |
84 | Termination on error can be suppressed on a command by command basis by | ||
85 | prefixing the command with a | ||
86 | .Ic '-' | ||
87 | character (For example, | ||
88 | .Ic -rm /tmp/blah* | ||
89 | ). | ||
83 | .It Fl o Ar ssh_option | 90 | .It Fl o Ar ssh_option |
84 | Can be used to pass options to | 91 | Can be used to pass options to |
85 | .Nm ssh | 92 | .Nm ssh |
@@ -24,7 +24,7 @@ | |||
24 | 24 | ||
25 | #include "includes.h" | 25 | #include "includes.h" |
26 | 26 | ||
27 | RCSID("$OpenBSD: sftp.c,v 1.32 2002/11/27 17:53:35 markus Exp $"); | 27 | RCSID("$OpenBSD: sftp.c,v 1.33 2003/01/08 23:53:26 djm Exp $"); |
28 | 28 | ||
29 | /* XXX: short-form remote directory listings (like 'ls -C') */ | 29 | /* XXX: short-form remote directory listings (like 'ls -C') */ |
30 | 30 | ||
@@ -108,7 +108,7 @@ usage(void) | |||
108 | int | 108 | int |
109 | main(int argc, char **argv) | 109 | main(int argc, char **argv) |
110 | { | 110 | { |
111 | int in, out, ch; | 111 | int in, out, ch, err; |
112 | pid_t sshpid; | 112 | pid_t sshpid; |
113 | char *host, *userhost, *cp, *file2; | 113 | char *host, *userhost, *cp, *file2; |
114 | int debug_level = 0, sshver = 2; | 114 | int debug_level = 0, sshver = 2; |
@@ -237,7 +237,7 @@ main(int argc, char **argv) | |||
237 | &sshpid); | 237 | &sshpid); |
238 | } | 238 | } |
239 | 239 | ||
240 | interactive_loop(in, out, file1, file2); | 240 | err = interactive_loop(in, out, file1, file2); |
241 | 241 | ||
242 | #if !defined(USE_PIPES) | 242 | #if !defined(USE_PIPES) |
243 | shutdown(in, SHUT_RDWR); | 243 | shutdown(in, SHUT_RDWR); |
@@ -254,5 +254,5 @@ main(int argc, char **argv) | |||
254 | fatal("Couldn't wait for ssh process: %s", | 254 | fatal("Couldn't wait for ssh process: %s", |
255 | strerror(errno)); | 255 | strerror(errno)); |
256 | 256 | ||
257 | exit(0); | 257 | exit(err == 0 ? 0 : 1); |
258 | } | 258 | } |