summaryrefslogtreecommitdiff
path: root/sftp-int.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2003-01-10 21:40:00 +1100
committerDamien Miller <djm@mindrot.org>2003-01-10 21:40:00 +1100
commit956f3fb28b93420e87a51d1611029accebb2e43b (patch)
treed1f304e1bf833cef147bec2335b75187a93f9e98 /sftp-int.c
parenta8ed44b79e6dd78d7871b0fb8149951b54662ef5 (diff)
- (djm) OpenBSD CVS Sync
- djm@cvs.openbsd.org 2003/01/08 23:53:26 [sftp.1 sftp.c sftp-int.c sftp-int.h] Cleanup error handling for batchmode Allow blank lines and comments in input Ability to suppress abort on error in batchmode ("-put blah") Fixes mindrot bug #452; markus@ ok
Diffstat (limited to 'sftp-int.c')
-rw-r--r--sftp-int.c132
1 files changed, 80 insertions, 52 deletions
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