summaryrefslogtreecommitdiff
path: root/sftp.c
diff options
context:
space:
mode:
authorDarren Tucker <dtucker@zip.com.au>2004-05-24 10:12:19 +1000
committerDarren Tucker <dtucker@zip.com.au>2004-05-24 10:12:19 +1000
commitcdf547afe4f7b6ad9b3143bb79163fa7a00f6721 (patch)
tree96deb3c736492199988f4e0632cb56619586fad5 /sftp.c
parentefec7c23b1d646578ddc47685496bdb9f1e9187f (diff)
- djm@cvs.openbsd.org 2004/05/19 12:17:33
[sftp-client.c sftp.c] gracefully abort transfers on receipt of SIGINT, also ignore SIGINT while waiting for a command; ok markus@
Diffstat (limited to 'sftp.c')
-rw-r--r--sftp.c64
1 files changed, 47 insertions, 17 deletions
diff --git a/sftp.c b/sftp.c
index a47ccf5a2..0bc68f058 100644
--- a/sftp.c
+++ b/sftp.c
@@ -16,7 +16,7 @@
16 16
17#include "includes.h" 17#include "includes.h"
18 18
19RCSID("$OpenBSD: sftp.c,v 1.45 2004/03/03 09:31:20 djm Exp $"); 19RCSID("$OpenBSD: sftp.c,v 1.46 2004/05/19 12:17:33 djm Exp $");
20 20
21#include "buffer.h" 21#include "buffer.h"
22#include "xmalloc.h" 22#include "xmalloc.h"
@@ -46,6 +46,9 @@ static pid_t sshpid = -1;
46/* This is set to 0 if the progressmeter is not desired. */ 46/* This is set to 0 if the progressmeter is not desired. */
47int showprogress = 1; 47int showprogress = 1;
48 48
49/* SIGINT received during command processing */
50volatile sig_atomic_t interrupted = 0;
51
49int remote_glob(struct sftp_conn *, const char *, int, 52int remote_glob(struct sftp_conn *, const char *, int,
50 int (*)(const char *, int), glob_t *); /* proto for sftp-glob.c */ 53 int (*)(const char *, int), glob_t *); /* proto for sftp-glob.c */
51 54
@@ -131,6 +134,24 @@ static const struct CMD cmds[] = {
131int interactive_loop(int fd_in, int fd_out, char *file1, char *file2); 134int interactive_loop(int fd_in, int fd_out, char *file1, char *file2);
132 135
133static void 136static void
137killchild(int signo)
138{
139 if (sshpid > 1)
140 kill(sshpid, SIGTERM);
141
142 _exit(1);
143}
144
145static void
146cmd_interrupt(int signo)
147{
148 const char msg[] = "\rInterrupt \n";
149
150 write(STDERR_FILENO, msg, sizeof(msg) - 1);
151 interrupted = 1;
152}
153
154static void
134help(void) 155help(void)
135{ 156{
136 printf("Available commands:\n"); 157 printf("Available commands:\n");
@@ -465,7 +486,7 @@ process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag)
465 goto out; 486 goto out;
466 } 487 }
467 488
468 for (i = 0; g.gl_pathv[i]; i++) { 489 for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
469 if (infer_path(g.gl_pathv[i], &tmp)) { 490 if (infer_path(g.gl_pathv[i], &tmp)) {
470 err = -1; 491 err = -1;
471 goto out; 492 goto out;
@@ -534,7 +555,7 @@ process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag)
534 goto out; 555 goto out;
535 } 556 }
536 557
537 for (i = 0; g.gl_pathv[i]; i++) { 558 for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
538 if (!is_reg(g.gl_pathv[i])) { 559 if (!is_reg(g.gl_pathv[i])) {
539 error("skipping non-regular file %s", 560 error("skipping non-regular file %s",
540 g.gl_pathv[i]); 561 g.gl_pathv[i]);
@@ -621,7 +642,7 @@ do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag)
621 642
622 qsort(d, n, sizeof(*d), sdirent_comp); 643 qsort(d, n, sizeof(*d), sdirent_comp);
623 644
624 for (n = 0; d[n] != NULL; n++) { 645 for (n = 0; d[n] != NULL && !interrupted; n++) {
625 char *tmp, *fname; 646 char *tmp, *fname;
626 647
627 tmp = path_append(path, d[n]->filename); 648 tmp = path_append(path, d[n]->filename);
@@ -673,6 +694,9 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
673 return (-1); 694 return (-1);
674 } 695 }
675 696
697 if (interrupted)
698 goto out;
699
676 /* 700 /*
677 * If the glob returns a single match, which is the same as the 701 * If the glob returns a single match, which is the same as the
678 * input glob, and it is a directory, then just list its contents 702 * input glob, and it is a directory, then just list its contents
@@ -706,7 +730,7 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
706 colspace = width / columns; 730 colspace = width / columns;
707 } 731 }
708 732
709 for (i = 0; g.gl_pathv[i]; i++) { 733 for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
710 char *fname; 734 char *fname;
711 735
712 fname = path_strip(g.gl_pathv[i], strip_path); 736 fname = path_strip(g.gl_pathv[i], strip_path);
@@ -743,6 +767,7 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
743 if (!(lflag & LONG_VIEW) && (c != 1)) 767 if (!(lflag & LONG_VIEW) && (c != 1))
744 printf("\n"); 768 printf("\n");
745 769
770 out:
746 if (g.gl_pathc) 771 if (g.gl_pathc)
747 globfree(&g); 772 globfree(&g);
748 773
@@ -952,7 +977,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
952 case I_RM: 977 case I_RM:
953 path1 = make_absolute(path1, *pwd); 978 path1 = make_absolute(path1, *pwd);
954 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); 979 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
955 for (i = 0; g.gl_pathv[i]; i++) { 980 for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
956 printf("Removing %s\n", g.gl_pathv[i]); 981 printf("Removing %s\n", g.gl_pathv[i]);
957 err = do_rm(conn, g.gl_pathv[i]); 982 err = do_rm(conn, g.gl_pathv[i]);
958 if (err != 0 && err_abort) 983 if (err != 0 && err_abort)
@@ -1041,7 +1066,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1041 a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; 1066 a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
1042 a.perm = n_arg; 1067 a.perm = n_arg;
1043 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); 1068 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
1044 for (i = 0; g.gl_pathv[i]; i++) { 1069 for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
1045 printf("Changing mode on %s\n", g.gl_pathv[i]); 1070 printf("Changing mode on %s\n", g.gl_pathv[i]);
1046 err = do_setstat(conn, g.gl_pathv[i], &a); 1071 err = do_setstat(conn, g.gl_pathv[i], &a);
1047 if (err != 0 && err_abort) 1072 if (err != 0 && err_abort)
@@ -1052,7 +1077,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1052 case I_CHGRP: 1077 case I_CHGRP:
1053 path1 = make_absolute(path1, *pwd); 1078 path1 = make_absolute(path1, *pwd);
1054 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); 1079 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
1055 for (i = 0; g.gl_pathv[i]; i++) { 1080 for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
1056 if (!(aa = do_stat(conn, g.gl_pathv[i], 0))) { 1081 if (!(aa = do_stat(conn, g.gl_pathv[i], 0))) {
1057 if (err != 0 && err_abort) 1082 if (err != 0 && err_abort)
1058 break; 1083 break;
@@ -1180,6 +1205,8 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
1180 for (;;) { 1205 for (;;) {
1181 char *cp; 1206 char *cp;
1182 1207
1208 signal(SIGINT, SIG_IGN);
1209
1183 printf("sftp> "); 1210 printf("sftp> ");
1184 1211
1185 /* XXX: use libedit */ 1212 /* XXX: use libedit */
@@ -1195,6 +1222,10 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
1195 if (cp) 1222 if (cp)
1196 *cp = '\0'; 1223 *cp = '\0';
1197 1224
1225 /* Handle user interrupts gracefully during commands */
1226 interrupted = 0;
1227 signal(SIGINT, cmd_interrupt);
1228
1198 err = parse_dispatch_command(conn, cmd, &pwd, batchmode); 1229 err = parse_dispatch_command(conn, cmd, &pwd, batchmode);
1199 if (err != 0) 1230 if (err != 0)
1200 break; 1231 break;
@@ -1206,15 +1237,6 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
1206} 1237}
1207 1238
1208static void 1239static void
1209killchild(int signo)
1210{
1211 if (sshpid > 1)
1212 kill(sshpid, signo);
1213
1214 _exit(1);
1215}
1216
1217static void
1218connect_to_server(char *path, char **args, int *in, int *out) 1240connect_to_server(char *path, char **args, int *in, int *out)
1219{ 1241{
1220 int c_in, c_out; 1242 int c_in, c_out;
@@ -1249,6 +1271,14 @@ connect_to_server(char *path, char **args, int *in, int *out)
1249 close(*out); 1271 close(*out);
1250 close(c_in); 1272 close(c_in);
1251 close(c_out); 1273 close(c_out);
1274
1275 /*
1276 * The underlying ssh is in the same process group, so we must
1277 * ignore SIGINT if we want to gracefully abort commands,
1278 * otherwise the signal will make it to the ssh process and
1279 * kill it too
1280 */
1281 signal(SIGINT, SIG_IGN);
1252 execv(path, args); 1282 execv(path, args);
1253 fprintf(stderr, "exec: %s: %s\n", path, strerror(errno)); 1283 fprintf(stderr, "exec: %s: %s\n", path, strerror(errno));
1254 exit(1); 1284 exit(1);