summaryrefslogtreecommitdiff
path: root/sftp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sftp.c')
-rw-r--r--sftp.c242
1 files changed, 162 insertions, 80 deletions
diff --git a/sftp.c b/sftp.c
index 969328de4..ad1f8c84d 100644
--- a/sftp.c
+++ b/sftp.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sftp.c,v 1.148 2013/07/25 00:56:52 djm Exp $ */ 1/* $OpenBSD: sftp.c,v 1.158 2013/11/20 20:54:10 deraadt Exp $ */
2/* 2/*
3 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> 3 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
4 * 4 *
@@ -94,6 +94,9 @@ int global_aflag = 0;
94/* When this option is set, the file transfers will always preserve times */ 94/* When this option is set, the file transfers will always preserve times */
95int global_pflag = 0; 95int global_pflag = 0;
96 96
97/* When this option is set, transfers will have fsync() called on each file */
98int global_fflag = 0;
99
97/* SIGINT received during command processing */ 100/* SIGINT received during command processing */
98volatile sig_atomic_t interrupted = 0; 101volatile sig_atomic_t interrupted = 0;
99 102
@@ -129,32 +132,34 @@ extern char *__progname;
129#define SORT_FLAGS (LS_NAME_SORT|LS_TIME_SORT|LS_SIZE_SORT) 132#define SORT_FLAGS (LS_NAME_SORT|LS_TIME_SORT|LS_SIZE_SORT)
130 133
131/* Commands for interactive mode */ 134/* Commands for interactive mode */
132#define I_CHDIR 1 135enum sftp_command {
133#define I_CHGRP 2 136 I_CHDIR = 1,
134#define I_CHMOD 3 137 I_CHGRP,
135#define I_CHOWN 4 138 I_CHMOD,
136#define I_DF 24 139 I_CHOWN,
137#define I_GET 5 140 I_DF,
138#define I_HELP 6 141 I_GET,
139#define I_LCHDIR 7 142 I_HELP,
140#define I_LINK 25 143 I_LCHDIR,
141#define I_LLS 8 144 I_LINK,
142#define I_LMKDIR 9 145 I_LLS,
143#define I_LPWD 10 146 I_LMKDIR,
144#define I_LS 11 147 I_LPWD,
145#define I_LUMASK 12 148 I_LS,
146#define I_MKDIR 13 149 I_LUMASK,
147#define I_PUT 14 150 I_MKDIR,
148#define I_PWD 15 151 I_PUT,
149#define I_QUIT 16 152 I_PWD,
150#define I_RENAME 17 153 I_QUIT,
151#define I_RM 18 154 I_RENAME,
152#define I_RMDIR 19 155 I_RM,
153#define I_SHELL 20 156 I_RMDIR,
154#define I_SYMLINK 21 157 I_SHELL,
155#define I_VERSION 22 158 I_SYMLINK,
156#define I_PROGRESS 23 159 I_VERSION,
157#define I_REGET 26 160 I_PROGRESS,
161 I_REGET,
162};
158 163
159struct CMD { 164struct CMD {
160 const char *c; 165 const char *c;
@@ -357,7 +362,7 @@ make_absolute(char *p, char *pwd)
357 362
358static int 363static int
359parse_getput_flags(const char *cmd, char **argv, int argc, 364parse_getput_flags(const char *cmd, char **argv, int argc,
360 int *aflag, int *pflag, int *rflag) 365 int *aflag, int *fflag, int *pflag, int *rflag)
361{ 366{
362 extern int opterr, optind, optopt, optreset; 367 extern int opterr, optind, optopt, optreset;
363 int ch; 368 int ch;
@@ -365,12 +370,15 @@ parse_getput_flags(const char *cmd, char **argv, int argc,
365 optind = optreset = 1; 370 optind = optreset = 1;
366 opterr = 0; 371 opterr = 0;
367 372
368 *aflag = *rflag = *pflag = 0; 373 *aflag = *fflag = *rflag = *pflag = 0;
369 while ((ch = getopt(argc, argv, "aPpRr")) != -1) { 374 while ((ch = getopt(argc, argv, "afPpRr")) != -1) {
370 switch (ch) { 375 switch (ch) {
371 case 'a': 376 case 'a':
372 *aflag = 1; 377 *aflag = 1;
373 break; 378 break;
379 case 'f':
380 *fflag = 1;
381 break;
374 case 'p': 382 case 'p':
375 case 'P': 383 case 'P':
376 *pflag = 1; 384 *pflag = 1;
@@ -413,6 +421,30 @@ parse_link_flags(const char *cmd, char **argv, int argc, int *sflag)
413} 421}
414 422
415static int 423static int
424parse_rename_flags(const char *cmd, char **argv, int argc, int *lflag)
425{
426 extern int opterr, optind, optopt, optreset;
427 int ch;
428
429 optind = optreset = 1;
430 opterr = 0;
431
432 *lflag = 0;
433 while ((ch = getopt(argc, argv, "l")) != -1) {
434 switch (ch) {
435 case 'l':
436 *lflag = 1;
437 break;
438 default:
439 error("%s: Invalid flag -%c", cmd, optopt);
440 return -1;
441 }
442 }
443
444 return optind;
445}
446
447static int
416parse_ls_flags(char **argv, int argc, int *lflag) 448parse_ls_flags(char **argv, int argc, int *lflag)
417{ 449{
418 extern int opterr, optind, optopt, optreset; 450 extern int opterr, optind, optopt, optreset;
@@ -493,6 +525,26 @@ parse_df_flags(const char *cmd, char **argv, int argc, int *hflag, int *iflag)
493} 525}
494 526
495static int 527static int
528parse_no_flags(const char *cmd, char **argv, int argc)
529{
530 extern int opterr, optind, optopt, optreset;
531 int ch;
532
533 optind = optreset = 1;
534 opterr = 0;
535
536 while ((ch = getopt(argc, argv, "")) != -1) {
537 switch (ch) {
538 default:
539 error("%s: Invalid flag -%c", cmd, optopt);
540 return -1;
541 }
542 }
543
544 return optind;
545}
546
547static int
496is_dir(char *path) 548is_dir(char *path)
497{ 549{
498 struct stat sb; 550 struct stat sb;
@@ -528,7 +580,7 @@ pathname_is_dir(char *pathname)
528 580
529static int 581static int
530process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, 582process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd,
531 int pflag, int rflag, int resume) 583 int pflag, int rflag, int resume, int fflag)
532{ 584{
533 char *abs_src = NULL; 585 char *abs_src = NULL;
534 char *abs_dst = NULL; 586 char *abs_dst = NULL;
@@ -587,11 +639,13 @@ process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd,
587 printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); 639 printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
588 if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { 640 if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
589 if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL, 641 if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL,
590 pflag || global_pflag, 1, resume) == -1) 642 pflag || global_pflag, 1, resume,
643 fflag || global_fflag) == -1)
591 err = -1; 644 err = -1;
592 } else { 645 } else {
593 if (do_download(conn, g.gl_pathv[i], abs_dst, NULL, 646 if (do_download(conn, g.gl_pathv[i], abs_dst, NULL,
594 pflag || global_pflag, resume) == -1) 647 pflag || global_pflag, resume,
648 fflag || global_fflag) == -1)
595 err = -1; 649 err = -1;
596 } 650 }
597 free(abs_dst); 651 free(abs_dst);
@@ -606,7 +660,7 @@ out:
606 660
607static int 661static int
608process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, 662process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd,
609 int pflag, int rflag) 663 int pflag, int rflag, int fflag)
610{ 664{
611 char *tmp_dst = NULL; 665 char *tmp_dst = NULL;
612 char *abs_dst = NULL; 666 char *abs_dst = NULL;
@@ -647,7 +701,7 @@ process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd,
647 error("stat %s: %s", g.gl_pathv[i], strerror(errno)); 701 error("stat %s: %s", g.gl_pathv[i], strerror(errno));
648 continue; 702 continue;
649 } 703 }
650 704
651 tmp = xstrdup(g.gl_pathv[i]); 705 tmp = xstrdup(g.gl_pathv[i]);
652 if ((filename = basename(tmp)) == NULL) { 706 if ((filename = basename(tmp)) == NULL) {
653 error("basename %s: %s", tmp, strerror(errno)); 707 error("basename %s: %s", tmp, strerror(errno));
@@ -673,11 +727,13 @@ process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd,
673 printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst); 727 printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst);
674 if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { 728 if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
675 if (upload_dir(conn, g.gl_pathv[i], abs_dst, 729 if (upload_dir(conn, g.gl_pathv[i], abs_dst,
676 pflag || global_pflag, 1) == -1) 730 pflag || global_pflag, 1,
731 fflag || global_fflag) == -1)
677 err = -1; 732 err = -1;
678 } else { 733 } else {
679 if (do_upload(conn, g.gl_pathv[i], abs_dst, 734 if (do_upload(conn, g.gl_pathv[i], abs_dst,
680 pflag || global_pflag) == -1) 735 pflag || global_pflag,
736 fflag || global_fflag) == -1)
681 err = -1; 737 err = -1;
682 } 738 }
683 } 739 }
@@ -975,7 +1031,7 @@ undo_glob_escape(char *s)
975 * 1031 *
976 * If "lastquote" is not NULL, the quoting character used for the last 1032 * If "lastquote" is not NULL, the quoting character used for the last
977 * argument is placed in *lastquote ("\0", "'" or "\""). 1033 * argument is placed in *lastquote ("\0", "'" or "\"").
978 * 1034 *
979 * If "terminated" is not NULL, *terminated will be set to 1 when the 1035 * If "terminated" is not NULL, *terminated will be set to 1 when the
980 * last argument's quote has been properly terminated or 0 otherwise. 1036 * last argument's quote has been properly terminated or 0 otherwise.
981 * This parameter is only of use if "sloppy" is set. 1037 * This parameter is only of use if "sloppy" is set.
@@ -1009,7 +1065,7 @@ makeargv(const char *arg, int *argcp, int sloppy, char *lastquote,
1009 error("Too many arguments."); 1065 error("Too many arguments.");
1010 return NULL; 1066 return NULL;
1011 } 1067 }
1012 if (isspace(arg[i])) { 1068 if (isspace((unsigned char)arg[i])) {
1013 if (state == MA_UNQUOTED) { 1069 if (state == MA_UNQUOTED) {
1014 /* Terminate current argument */ 1070 /* Terminate current argument */
1015 argvs[j++] = '\0'; 1071 argvs[j++] = '\0';
@@ -1024,7 +1080,7 @@ makeargv(const char *arg, int *argcp, int sloppy, char *lastquote,
1024 state = q; 1080 state = q;
1025 if (lastquote != NULL) 1081 if (lastquote != NULL)
1026 *lastquote = arg[i]; 1082 *lastquote = arg[i];
1027 } else if (state == MA_UNQUOTED) 1083 } else if (state == MA_UNQUOTED)
1028 state = q; 1084 state = q;
1029 else if (state == q) 1085 else if (state == q)
1030 state = MA_UNQUOTED; 1086 state = MA_UNQUOTED;
@@ -1130,9 +1186,9 @@ makeargv(const char *arg, int *argcp, int sloppy, char *lastquote,
1130} 1186}
1131 1187
1132static int 1188static int
1133parse_args(const char **cpp, int *aflag, int *hflag, int *iflag, int *lflag, 1189parse_args(const char **cpp, int *ignore_errors, int *aflag, int *fflag,
1134 int *pflag, int *rflag, int *sflag, unsigned long *n_arg, 1190 int *hflag, int *iflag, int *lflag, int *pflag, int *rflag, int *sflag,
1135 char **path1, char **path2) 1191 unsigned long *n_arg, char **path1, char **path2)
1136{ 1192{
1137 const char *cmd, *cp = *cpp; 1193 const char *cmd, *cp = *cpp;
1138 char *cp2, **argv; 1194 char *cp2, **argv;
@@ -1144,9 +1200,9 @@ parse_args(const char **cpp, int *aflag, int *hflag, int *iflag, int *lflag,
1144 cp = cp + strspn(cp, WHITESPACE); 1200 cp = cp + strspn(cp, WHITESPACE);
1145 1201
1146 /* Check for leading '-' (disable error processing) */ 1202 /* Check for leading '-' (disable error processing) */
1147 *iflag = 0; 1203 *ignore_errors = 0;
1148 if (*cp == '-') { 1204 if (*cp == '-') {
1149 *iflag = 1; 1205 *ignore_errors = 1;
1150 cp++; 1206 cp++;
1151 cp = cp + strspn(cp, WHITESPACE); 1207 cp = cp + strspn(cp, WHITESPACE);
1152 } 1208 }
@@ -1176,7 +1232,8 @@ parse_args(const char **cpp, int *aflag, int *hflag, int *iflag, int *lflag,
1176 } 1232 }
1177 1233
1178 /* Get arguments and parse flags */ 1234 /* Get arguments and parse flags */
1179 *aflag = *lflag = *pflag = *rflag = *hflag = *n_arg = 0; 1235 *aflag = *fflag = *hflag = *iflag = *lflag = *pflag = 0;
1236 *rflag = *sflag = 0;
1180 *path1 = *path2 = NULL; 1237 *path1 = *path2 = NULL;
1181 optidx = 1; 1238 optidx = 1;
1182 switch (cmdnum) { 1239 switch (cmdnum) {
@@ -1184,7 +1241,7 @@ parse_args(const char **cpp, int *aflag, int *hflag, int *iflag, int *lflag,
1184 case I_REGET: 1241 case I_REGET:
1185 case I_PUT: 1242 case I_PUT:
1186 if ((optidx = parse_getput_flags(cmd, argv, argc, 1243 if ((optidx = parse_getput_flags(cmd, argv, argc,
1187 aflag, pflag, rflag)) == -1) 1244 aflag, fflag, pflag, rflag)) == -1)
1188 return -1; 1245 return -1;
1189 /* Get first pathname (mandatory) */ 1246 /* Get first pathname (mandatory) */
1190 if (argc - optidx < 1) { 1247 if (argc - optidx < 1) {
@@ -1208,8 +1265,15 @@ parse_args(const char **cpp, int *aflag, int *hflag, int *iflag, int *lflag,
1208 case I_LINK: 1265 case I_LINK:
1209 if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1) 1266 if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1)
1210 return -1; 1267 return -1;
1211 case I_SYMLINK: 1268 goto parse_two_paths;
1212 case I_RENAME: 1269 case I_RENAME:
1270 if ((optidx = parse_rename_flags(cmd, argv, argc, lflag)) == -1)
1271 return -1;
1272 goto parse_two_paths;
1273 case I_SYMLINK:
1274 if ((optidx = parse_no_flags(cmd, argv, argc)) == -1)
1275 return -1;
1276 parse_two_paths:
1213 if (argc - optidx < 2) { 1277 if (argc - optidx < 2) {
1214 error("You must specify two paths after a %s " 1278 error("You must specify two paths after a %s "
1215 "command.", cmd); 1279 "command.", cmd);
@@ -1227,6 +1291,8 @@ parse_args(const char **cpp, int *aflag, int *hflag, int *iflag, int *lflag,
1227 case I_CHDIR: 1291 case I_CHDIR:
1228 case I_LCHDIR: 1292 case I_LCHDIR:
1229 case I_LMKDIR: 1293 case I_LMKDIR:
1294 if ((optidx = parse_no_flags(cmd, argv, argc)) == -1)
1295 return -1;
1230 /* Get pathname (mandatory) */ 1296 /* Get pathname (mandatory) */
1231 if (argc - optidx < 1) { 1297 if (argc - optidx < 1) {
1232 error("You must specify a path after a %s command.", 1298 error("You must specify a path after a %s command.",
@@ -1268,6 +1334,8 @@ parse_args(const char **cpp, int *aflag, int *hflag, int *iflag, int *lflag,
1268 base = 8; 1334 base = 8;
1269 case I_CHOWN: 1335 case I_CHOWN:
1270 case I_CHGRP: 1336 case I_CHGRP:
1337 if ((optidx = parse_no_flags(cmd, argv, argc)) == -1)
1338 return -1;
1271 /* Get numeric arg (mandatory) */ 1339 /* Get numeric arg (mandatory) */
1272 if (argc - optidx < 1) 1340 if (argc - optidx < 1)
1273 goto need_num_arg; 1341 goto need_num_arg;
@@ -1298,6 +1366,8 @@ parse_args(const char **cpp, int *aflag, int *hflag, int *iflag, int *lflag,
1298 case I_HELP: 1366 case I_HELP:
1299 case I_VERSION: 1367 case I_VERSION:
1300 case I_PROGRESS: 1368 case I_PROGRESS:
1369 if ((optidx = parse_no_flags(cmd, argv, argc)) == -1)
1370 return -1;
1301 break; 1371 break;
1302 default: 1372 default:
1303 fatal("Command not implemented"); 1373 fatal("Command not implemented");
@@ -1312,8 +1382,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1312 int err_abort) 1382 int err_abort)
1313{ 1383{
1314 char *path1, *path2, *tmp; 1384 char *path1, *path2, *tmp;
1315 int aflag = 0, hflag = 0, iflag = 0, lflag = 0, pflag = 0; 1385 int ignore_errors = 0, aflag = 0, fflag = 0, hflag = 0, iflag = 0;
1316 int rflag = 0, sflag = 0; 1386 int lflag = 0, pflag = 0, rflag = 0, sflag = 0;
1317 int cmdnum, i; 1387 int cmdnum, i;
1318 unsigned long n_arg = 0; 1388 unsigned long n_arg = 0;
1319 Attrib a, *aa; 1389 Attrib a, *aa;
@@ -1322,9 +1392,9 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1322 glob_t g; 1392 glob_t g;
1323 1393
1324 path1 = path2 = NULL; 1394 path1 = path2 = NULL;
1325 cmdnum = parse_args(&cmd, &aflag, &hflag, &iflag, &lflag, &pflag, 1395 cmdnum = parse_args(&cmd, &ignore_errors, &aflag, &fflag, &hflag,
1326 &rflag, &sflag, &n_arg, &path1, &path2); 1396 &iflag, &lflag, &pflag, &rflag, &sflag, &n_arg, &path1, &path2);
1327 if (iflag != 0) 1397 if (ignore_errors != 0)
1328 err_abort = 0; 1398 err_abort = 0;
1329 1399
1330 memset(&g, 0, sizeof(g)); 1400 memset(&g, 0, sizeof(g));
@@ -1343,20 +1413,22 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1343 /* FALLTHROUGH */ 1413 /* FALLTHROUGH */
1344 case I_GET: 1414 case I_GET:
1345 err = process_get(conn, path1, path2, *pwd, pflag, 1415 err = process_get(conn, path1, path2, *pwd, pflag,
1346 rflag, aflag); 1416 rflag, aflag, fflag);
1347 break; 1417 break;
1348 case I_PUT: 1418 case I_PUT:
1349 err = process_put(conn, path1, path2, *pwd, pflag, rflag); 1419 err = process_put(conn, path1, path2, *pwd, pflag,
1420 rflag, fflag);
1350 break; 1421 break;
1351 case I_RENAME: 1422 case I_RENAME:
1352 path1 = make_absolute(path1, *pwd); 1423 path1 = make_absolute(path1, *pwd);
1353 path2 = make_absolute(path2, *pwd); 1424 path2 = make_absolute(path2, *pwd);
1354 err = do_rename(conn, path1, path2); 1425 err = do_rename(conn, path1, path2, lflag);
1355 break; 1426 break;
1356 case I_SYMLINK: 1427 case I_SYMLINK:
1357 sflag = 1; 1428 sflag = 1;
1358 case I_LINK: 1429 case I_LINK:
1359 path1 = make_absolute(path1, *pwd); 1430 if (!sflag)
1431 path1 = make_absolute(path1, *pwd);
1360 path2 = make_absolute(path2, *pwd); 1432 path2 = make_absolute(path2, *pwd);
1361 err = (sflag ? do_symlink : do_hardlink)(conn, path1, path2); 1433 err = (sflag ? do_symlink : do_hardlink)(conn, path1, path2);
1362 break; 1434 break;
@@ -1567,7 +1639,7 @@ complete_display(char **list, u_int len)
1567 char *tmp; 1639 char *tmp;
1568 1640
1569 /* Count entries for sort and find longest */ 1641 /* Count entries for sort and find longest */
1570 for (y = 0; list[y]; y++) 1642 for (y = 0; list[y]; y++)
1571 m = MAX(m, strlen(list[y])); 1643 m = MAX(m, strlen(list[y]));
1572 1644
1573 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1) 1645 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1)
@@ -1612,8 +1684,8 @@ complete_ambiguous(const char *word, char **list, size_t count)
1612 for (y = 1; list[y]; y++) { 1684 for (y = 1; list[y]; y++) {
1613 u_int x; 1685 u_int x;
1614 1686
1615 for (x = 0; x < matchlen; x++) 1687 for (x = 0; x < matchlen; x++)
1616 if (list[0][x] != list[y][x]) 1688 if (list[0][x] != list[y][x])
1617 break; 1689 break;
1618 1690
1619 matchlen = x; 1691 matchlen = x;
@@ -1625,7 +1697,7 @@ complete_ambiguous(const char *word, char **list, size_t count)
1625 tmp[matchlen] = '\0'; 1697 tmp[matchlen] = '\0';
1626 return tmp; 1698 return tmp;
1627 } 1699 }
1628 } 1700 }
1629 1701
1630 return xstrdup(word); 1702 return xstrdup(word);
1631} 1703}
@@ -1645,12 +1717,12 @@ complete_cmd_parse(EditLine *el, char *cmd, int lastarg, char quote,
1645 if (cmd == NULL) { 1717 if (cmd == NULL) {
1646 for (y = 0; cmds[y].c; y++) 1718 for (y = 0; cmds[y].c; y++)
1647 list[count++] = xstrdup(cmds[y].c); 1719 list[count++] = xstrdup(cmds[y].c);
1648 1720
1649 list[count] = NULL; 1721 list[count] = NULL;
1650 complete_display(list, 0); 1722 complete_display(list, 0);
1651 1723
1652 for (y = 0; list[y] != NULL; y++) 1724 for (y = 0; list[y] != NULL; y++)
1653 free(list[y]); 1725 free(list[y]);
1654 free(list); 1726 free(list);
1655 return count; 1727 return count;
1656 } 1728 }
@@ -1658,7 +1730,7 @@ complete_cmd_parse(EditLine *el, char *cmd, int lastarg, char quote,
1658 /* Prepare subset of commands that start with "cmd" */ 1730 /* Prepare subset of commands that start with "cmd" */
1659 cmdlen = strlen(cmd); 1731 cmdlen = strlen(cmd);
1660 for (y = 0; cmds[y].c; y++) { 1732 for (y = 0; cmds[y].c; y++) {
1661 if (!strncasecmp(cmd, cmds[y].c, cmdlen)) 1733 if (!strncasecmp(cmd, cmds[y].c, cmdlen))
1662 list[count++] = xstrdup(cmds[y].c); 1734 list[count++] = xstrdup(cmds[y].c);
1663 } 1735 }
1664 list[count] = NULL; 1736 list[count] = NULL;
@@ -1673,8 +1745,8 @@ complete_cmd_parse(EditLine *el, char *cmd, int lastarg, char quote,
1673 if (count > 1) 1745 if (count > 1)
1674 complete_display(list, 0); 1746 complete_display(list, 0);
1675 1747
1676 for (y = 0; list[y]; y++) 1748 for (y = 0; list[y]; y++)
1677 free(list[y]); 1749 free(list[y]);
1678 free(list); 1750 free(list);
1679 1751
1680 if (tmp != NULL) { 1752 if (tmp != NULL) {
@@ -1714,7 +1786,7 @@ complete_is_remote(char *cmd) {
1714 return -1; 1786 return -1;
1715 1787
1716 for (i = 0; cmds[i].c; i++) { 1788 for (i = 0; cmds[i].c; i++) {
1717 if (!strncasecmp(cmd, cmds[i].c, strlen(cmds[i].c))) 1789 if (!strncasecmp(cmd, cmds[i].c, strlen(cmds[i].c)))
1718 return cmds[i].t; 1790 return cmds[i].t;
1719 } 1791 }
1720 1792
@@ -1731,7 +1803,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
1731 u_int i, hadglob, pwdlen, len, tmplen, filelen, cesc, isesc, isabs; 1803 u_int i, hadglob, pwdlen, len, tmplen, filelen, cesc, isesc, isabs;
1732 int clen; 1804 int clen;
1733 const LineInfo *lf; 1805 const LineInfo *lf;
1734 1806
1735 /* Glob from "file" location */ 1807 /* Glob from "file" location */
1736 if (file == NULL) 1808 if (file == NULL)
1737 tmp = xstrdup("*"); 1809 tmp = xstrdup("*");
@@ -1745,9 +1817,9 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
1745 if (remote != LOCAL) { 1817 if (remote != LOCAL) {
1746 tmp = make_absolute(tmp, remote_path); 1818 tmp = make_absolute(tmp, remote_path);
1747 remote_glob(conn, tmp, GLOB_DOOFFS|GLOB_MARK, NULL, &g); 1819 remote_glob(conn, tmp, GLOB_DOOFFS|GLOB_MARK, NULL, &g);
1748 } else 1820 } else
1749 glob(tmp, GLOB_DOOFFS|GLOB_MARK, NULL, &g); 1821 glob(tmp, GLOB_DOOFFS|GLOB_MARK, NULL, &g);
1750 1822
1751 /* Determine length of pwd so we can trim completion display */ 1823 /* Determine length of pwd so we can trim completion display */
1752 for (hadglob = tmplen = pwdlen = 0; tmp[tmplen] != 0; tmplen++) { 1824 for (hadglob = tmplen = pwdlen = 0; tmp[tmplen] != 0; tmplen++) {
1753 /* Terminate counting on first unescaped glob metacharacter */ 1825 /* Terminate counting on first unescaped glob metacharacter */
@@ -1763,7 +1835,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
1763 } 1835 }
1764 free(tmp); 1836 free(tmp);
1765 1837
1766 if (g.gl_matchc == 0) 1838 if (g.gl_matchc == 0)
1767 goto out; 1839 goto out;
1768 1840
1769 if (g.gl_matchc > 1) 1841 if (g.gl_matchc > 1)
@@ -1796,7 +1868,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
1796 1868
1797 if (tmplen > (filelen - cesc)) { 1869 if (tmplen > (filelen - cesc)) {
1798 tmp2 = tmp + filelen - cesc; 1870 tmp2 = tmp + filelen - cesc;
1799 len = strlen(tmp2); 1871 len = strlen(tmp2);
1800 /* quote argument on way out */ 1872 /* quote argument on way out */
1801 for (i = 0; i < len; i += clen) { 1873 for (i = 0; i < len; i += clen) {
1802 if ((clen = mblen(tmp2 + i, len - i)) < 0 || 1874 if ((clen = mblen(tmp2 + i, len - i)) < 0 ||
@@ -1852,7 +1924,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
1852static unsigned char 1924static unsigned char
1853complete(EditLine *el, int ch) 1925complete(EditLine *el, int ch)
1854{ 1926{
1855 char **argv, *line, quote; 1927 char **argv, *line, quote;
1856 int argc, carg; 1928 int argc, carg;
1857 u_int cursor, len, terminated, ret = CC_ERROR; 1929 u_int cursor, len, terminated, ret = CC_ERROR;
1858 const LineInfo *lf; 1930 const LineInfo *lf;
@@ -1891,7 +1963,7 @@ complete(EditLine *el, int ch)
1891 } else if (carg == 1 && cursor > 0 && line[cursor - 1] != ' ') { 1963 } else if (carg == 1 && cursor > 0 && line[cursor - 1] != ' ') {
1892 /* Handle the command parsing */ 1964 /* Handle the command parsing */
1893 if (complete_cmd_parse(el, argv[0], argc == carg, 1965 if (complete_cmd_parse(el, argv[0], argc == carg,
1894 quote, terminated) != 0) 1966 quote, terminated) != 0)
1895 ret = CC_REDISPLAY; 1967 ret = CC_REDISPLAY;
1896 } else if (carg >= 1) { 1968 } else if (carg >= 1) {
1897 /* Handle file parsing */ 1969 /* Handle file parsing */
@@ -1904,11 +1976,11 @@ complete(EditLine *el, int ch)
1904 if (remote != 0 && 1976 if (remote != 0 &&
1905 complete_match(el, complete_ctx->conn, 1977 complete_match(el, complete_ctx->conn,
1906 *complete_ctx->remote_pathp, filematch, 1978 *complete_ctx->remote_pathp, filematch,
1907 remote, carg == argc, quote, terminated) != 0) 1979 remote, carg == argc, quote, terminated) != 0)
1908 ret = CC_REDISPLAY; 1980 ret = CC_REDISPLAY;
1909 } 1981 }
1910 1982
1911 free(line); 1983 free(line);
1912 return ret; 1984 return ret;
1913} 1985}
1914#endif /* USE_LIBEDIT */ 1986#endif /* USE_LIBEDIT */
@@ -1942,12 +2014,19 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
1942 el_source(el, NULL); 2014 el_source(el, NULL);
1943 2015
1944 /* Tab Completion */ 2016 /* Tab Completion */
1945 el_set(el, EL_ADDFN, "ftp-complete", 2017 el_set(el, EL_ADDFN, "ftp-complete",
1946 "Context sensitive argument completion", complete); 2018 "Context sensitive argument completion", complete);
1947 complete_ctx.conn = conn; 2019 complete_ctx.conn = conn;
1948 complete_ctx.remote_pathp = &remote_path; 2020 complete_ctx.remote_pathp = &remote_path;
1949 el_set(el, EL_CLIENTDATA, (void*)&complete_ctx); 2021 el_set(el, EL_CLIENTDATA, (void*)&complete_ctx);
1950 el_set(el, EL_BIND, "^I", "ftp-complete", NULL); 2022 el_set(el, EL_BIND, "^I", "ftp-complete", NULL);
2023 /* enable ctrl-left-arrow and ctrl-right-arrow */
2024 el_set(el, EL_BIND, "\\e[1;5C", "em-next-word", NULL);
2025 el_set(el, EL_BIND, "\\e[5C", "em-next-word", NULL);
2026 el_set(el, EL_BIND, "\\e[1;5D", "ed-prev-word", NULL);
2027 el_set(el, EL_BIND, "\\e\\e[D", "ed-prev-word", NULL);
2028 /* make ^w match ksh behaviour */
2029 el_set(el, EL_BIND, "^w", "ed-delete-prev-word", NULL);
1951 } 2030 }
1952#endif /* USE_LIBEDIT */ 2031#endif /* USE_LIBEDIT */
1953 2032
@@ -2116,7 +2195,7 @@ usage(void)
2116 extern char *__progname; 2195 extern char *__progname;
2117 2196
2118 fprintf(stderr, 2197 fprintf(stderr,
2119 "usage: %s [-1246Cpqrv] [-B buffer_size] [-b batchfile] [-c cipher]\n" 2198 "usage: %s [-1246aCfpqrv] [-B buffer_size] [-b batchfile] [-c cipher]\n"
2120 " [-D sftp_server_path] [-F ssh_config] " 2199 " [-D sftp_server_path] [-F ssh_config] "
2121 "[-i identity_file] [-l limit]\n" 2200 "[-i identity_file] [-l limit]\n"
2122 " [-o ssh_option] [-P port] [-R num_requests] " 2201 " [-o ssh_option] [-P port] [-R num_requests] "
@@ -2164,7 +2243,7 @@ main(int argc, char **argv)
2164 infile = stdin; 2243 infile = stdin;
2165 2244
2166 while ((ch = getopt(argc, argv, 2245 while ((ch = getopt(argc, argv,
2167 "1246ahpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) { 2246 "1246afhpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) {
2168 switch (ch) { 2247 switch (ch) {
2169 /* Passed through to ssh(1) */ 2248 /* Passed through to ssh(1) */
2170 case '4': 2249 case '4':
@@ -2224,6 +2303,9 @@ main(int argc, char **argv)
2224 quiet = batchmode = 1; 2303 quiet = batchmode = 1;
2225 addargs(&args, "-obatchmode yes"); 2304 addargs(&args, "-obatchmode yes");
2226 break; 2305 break;
2306 case 'f':
2307 global_fflag = 1;
2308 break;
2227 case 'p': 2309 case 'p':
2228 global_pflag = 1; 2310 global_pflag = 1;
2229 break; 2311 break;