summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--sftp-int.c132
-rw-r--r--sftp-int.h4
-rw-r--r--sftp.111
-rw-r--r--sftp.c8
5 files changed, 103 insertions, 61 deletions
diff --git a/ChangeLog b/ChangeLog
index 492eadab3..3c38dbb10 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,13 @@
120030110 120030110
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
520030108 1220030108
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"
28RCSID("$OpenBSD: sftp-int.c,v 1.50 2002/11/21 23:03:51 deraadt Exp $"); 28RCSID("$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
668static int 668static int
669parse_args(const char **cpp, int *pflag, int *lflag, 669parse_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
815static int 822static int
816parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd) 823parse_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
1019void 1038int
1020interactive_loop(int fd_in, int fd_out, char *file1, char *file2) 1039interactive_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
27void interactive_loop(int, int, char *, char *); 27int interactive_loop(int, int, char *, char *);
diff --git a/sftp.1 b/sftp.1
index 60d46b1c2..67086bdaa 100644
--- a/sftp.1
+++ b/sftp.1
@@ -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.
77will abort if any of the following 77will abort if any of the following
78commands fail: 78commands 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
81and 82and
82.Ic lmkdir . 83.Ic lmkdir .
84Termination on error can be suppressed on a command by command basis by
85prefixing the command with a
86.Ic '-'
87character (For example,
88.Ic -rm /tmp/blah*
89).
83.It Fl o Ar ssh_option 90.It Fl o Ar ssh_option
84Can be used to pass options to 91Can be used to pass options to
85.Nm ssh 92.Nm ssh
diff --git a/sftp.c b/sftp.c
index c173e58cb..d62e9e42c 100644
--- a/sftp.c
+++ b/sftp.c
@@ -24,7 +24,7 @@
24 24
25#include "includes.h" 25#include "includes.h"
26 26
27RCSID("$OpenBSD: sftp.c,v 1.32 2002/11/27 17:53:35 markus Exp $"); 27RCSID("$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)
108int 108int
109main(int argc, char **argv) 109main(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}