diff options
Diffstat (limited to 'sftp-int.c')
-rw-r--r-- | sftp-int.c | 132 |
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" |
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 | |||