summaryrefslogtreecommitdiff
path: root/sftp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sftp.c')
-rw-r--r--sftp.c217
1 files changed, 130 insertions, 87 deletions
diff --git a/sftp.c b/sftp.c
index 342ae7efc..969328de4 100644
--- a/sftp.c
+++ b/sftp.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sftp.c,v 1.142 2013/02/08 00:41:12 djm Exp $ */ 1/* $OpenBSD: sftp.c,v 1.148 2013/07/25 00:56:52 djm 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 *
@@ -38,6 +38,9 @@
38#ifdef HAVE_LIBGEN_H 38#ifdef HAVE_LIBGEN_H
39#include <libgen.h> 39#include <libgen.h>
40#endif 40#endif
41#ifdef HAVE_LOCALE_H
42# include <locale.h>
43#endif
41#ifdef USE_LIBEDIT 44#ifdef USE_LIBEDIT
42#include <histedit.h> 45#include <histedit.h>
43#else 46#else
@@ -76,12 +79,18 @@ int batchmode = 0;
76/* PID of ssh transport process */ 79/* PID of ssh transport process */
77static pid_t sshpid = -1; 80static pid_t sshpid = -1;
78 81
82/* Suppress diagnositic messages */
83int quiet = 0;
84
79/* This is set to 0 if the progressmeter is not desired. */ 85/* This is set to 0 if the progressmeter is not desired. */
80int showprogress = 1; 86int showprogress = 1;
81 87
82/* When this option is set, we always recursively download/upload directories */ 88/* When this option is set, we always recursively download/upload directories */
83int global_rflag = 0; 89int global_rflag = 0;
84 90
91/* When this option is set, we resume download if possible */
92int global_aflag = 0;
93
85/* 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 */
86int global_pflag = 0; 95int global_pflag = 0;
87 96
@@ -145,6 +154,7 @@ extern char *__progname;
145#define I_SYMLINK 21 154#define I_SYMLINK 21
146#define I_VERSION 22 155#define I_VERSION 22
147#define I_PROGRESS 23 156#define I_PROGRESS 23
157#define I_REGET 26
148 158
149struct CMD { 159struct CMD {
150 const char *c; 160 const char *c;
@@ -184,6 +194,7 @@ static const struct CMD cmds[] = {
184 { "put", I_PUT, LOCAL }, 194 { "put", I_PUT, LOCAL },
185 { "pwd", I_PWD, REMOTE }, 195 { "pwd", I_PWD, REMOTE },
186 { "quit", I_QUIT, NOARGS }, 196 { "quit", I_QUIT, NOARGS },
197 { "reget", I_REGET, REMOTE },
187 { "rename", I_RENAME, REMOTE }, 198 { "rename", I_RENAME, REMOTE },
188 { "rm", I_RM, REMOTE }, 199 { "rm", I_RM, REMOTE },
189 { "rmdir", I_RMDIR, REMOTE }, 200 { "rmdir", I_RMDIR, REMOTE },
@@ -215,7 +226,7 @@ cmd_interrupt(int signo)
215 const char msg[] = "\rInterrupt \n"; 226 const char msg[] = "\rInterrupt \n";
216 int olderrno = errno; 227 int olderrno = errno;
217 228
218 write(STDERR_FILENO, msg, sizeof(msg) - 1); 229 (void)write(STDERR_FILENO, msg, sizeof(msg) - 1);
219 interrupted = 1; 230 interrupted = 1;
220 errno = olderrno; 231 errno = olderrno;
221} 232}
@@ -233,6 +244,7 @@ help(void)
233 " filesystem containing 'path'\n" 244 " filesystem containing 'path'\n"
234 "exit Quit sftp\n" 245 "exit Quit sftp\n"
235 "get [-Ppr] remote [local] Download file\n" 246 "get [-Ppr] remote [local] Download file\n"
247 "reget remote [local] Resume download file\n"
236 "help Display this help text\n" 248 "help Display this help text\n"
237 "lcd path Change local directory to 'path'\n" 249 "lcd path Change local directory to 'path'\n"
238 "lls [ls-options [path]] Display local directory listing\n" 250 "lls [ls-options [path]] Display local directory listing\n"
@@ -306,7 +318,7 @@ local_do_ls(const char *args)
306 /* XXX: quoting - rip quoting code from ftp? */ 318 /* XXX: quoting - rip quoting code from ftp? */
307 snprintf(buf, len, _PATH_LS " %s", args); 319 snprintf(buf, len, _PATH_LS " %s", args);
308 local_do_shell(buf); 320 local_do_shell(buf);
309 xfree(buf); 321 free(buf);
310 } 322 }
311} 323}
312 324
@@ -337,15 +349,15 @@ make_absolute(char *p, char *pwd)
337 /* Derelativise */ 349 /* Derelativise */
338 if (p && p[0] != '/') { 350 if (p && p[0] != '/') {
339 abs_str = path_append(pwd, p); 351 abs_str = path_append(pwd, p);
340 xfree(p); 352 free(p);
341 return(abs_str); 353 return(abs_str);
342 } else 354 } else
343 return(p); 355 return(p);
344} 356}
345 357
346static int 358static int
347parse_getput_flags(const char *cmd, char **argv, int argc, int *pflag, 359parse_getput_flags(const char *cmd, char **argv, int argc,
348 int *rflag) 360 int *aflag, int *pflag, int *rflag)
349{ 361{
350 extern int opterr, optind, optopt, optreset; 362 extern int opterr, optind, optopt, optreset;
351 int ch; 363 int ch;
@@ -353,9 +365,12 @@ parse_getput_flags(const char *cmd, char **argv, int argc, int *pflag,
353 optind = optreset = 1; 365 optind = optreset = 1;
354 opterr = 0; 366 opterr = 0;
355 367
356 *rflag = *pflag = 0; 368 *aflag = *rflag = *pflag = 0;
357 while ((ch = getopt(argc, argv, "PpRr")) != -1) { 369 while ((ch = getopt(argc, argv, "aPpRr")) != -1) {
358 switch (ch) { 370 switch (ch) {
371 case 'a':
372 *aflag = 1;
373 break;
359 case 'p': 374 case 'p':
360 case 'P': 375 case 'P':
361 *pflag = 1; 376 *pflag = 1;
@@ -513,7 +528,7 @@ pathname_is_dir(char *pathname)
513 528
514static int 529static int
515process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, 530process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd,
516 int pflag, int rflag) 531 int pflag, int rflag, int resume)
517{ 532{
518 char *abs_src = NULL; 533 char *abs_src = NULL;
519 char *abs_dst = NULL; 534 char *abs_dst = NULL;
@@ -547,7 +562,7 @@ process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd,
547 tmp = xstrdup(g.gl_pathv[i]); 562 tmp = xstrdup(g.gl_pathv[i]);
548 if ((filename = basename(tmp)) == NULL) { 563 if ((filename = basename(tmp)) == NULL) {
549 error("basename %s: %s", tmp, strerror(errno)); 564 error("basename %s: %s", tmp, strerror(errno));
550 xfree(tmp); 565 free(tmp);
551 err = -1; 566 err = -1;
552 goto out; 567 goto out;
553 } 568 }
@@ -563,24 +578,28 @@ process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd,
563 } else { 578 } else {
564 abs_dst = xstrdup(filename); 579 abs_dst = xstrdup(filename);
565 } 580 }
566 xfree(tmp); 581 free(tmp);
567 582
568 printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); 583 resume |= global_aflag;
584 if (!quiet && resume)
585 printf("Resuming %s to %s\n", g.gl_pathv[i], abs_dst);
586 else if (!quiet && !resume)
587 printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
569 if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { 588 if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
570 if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL, 589 if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL,
571 pflag || global_pflag, 1) == -1) 590 pflag || global_pflag, 1, resume) == -1)
572 err = -1; 591 err = -1;
573 } else { 592 } else {
574 if (do_download(conn, g.gl_pathv[i], abs_dst, NULL, 593 if (do_download(conn, g.gl_pathv[i], abs_dst, NULL,
575 pflag || global_pflag) == -1) 594 pflag || global_pflag, resume) == -1)
576 err = -1; 595 err = -1;
577 } 596 }
578 xfree(abs_dst); 597 free(abs_dst);
579 abs_dst = NULL; 598 abs_dst = NULL;
580 } 599 }
581 600
582out: 601out:
583 xfree(abs_src); 602 free(abs_src);
584 globfree(&g); 603 globfree(&g);
585 return(err); 604 return(err);
586} 605}
@@ -632,7 +651,7 @@ process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd,
632 tmp = xstrdup(g.gl_pathv[i]); 651 tmp = xstrdup(g.gl_pathv[i]);
633 if ((filename = basename(tmp)) == NULL) { 652 if ((filename = basename(tmp)) == NULL) {
634 error("basename %s: %s", tmp, strerror(errno)); 653 error("basename %s: %s", tmp, strerror(errno));
635 xfree(tmp); 654 free(tmp);
636 err = -1; 655 err = -1;
637 goto out; 656 goto out;
638 } 657 }
@@ -648,9 +667,10 @@ process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd,
648 } else { 667 } else {
649 abs_dst = make_absolute(xstrdup(filename), pwd); 668 abs_dst = make_absolute(xstrdup(filename), pwd);
650 } 669 }
651 xfree(tmp); 670 free(tmp);
652 671
653 printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst); 672 if (!quiet)
673 printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst);
654 if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { 674 if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
655 if (upload_dir(conn, g.gl_pathv[i], abs_dst, 675 if (upload_dir(conn, g.gl_pathv[i], abs_dst,
656 pflag || global_pflag, 1) == -1) 676 pflag || global_pflag, 1) == -1)
@@ -663,10 +683,8 @@ process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd,
663 } 683 }
664 684
665out: 685out:
666 if (abs_dst) 686 free(abs_dst);
667 xfree(abs_dst); 687 free(tmp_dst);
668 if (tmp_dst)
669 xfree(tmp_dst);
670 globfree(&g); 688 globfree(&g);
671 return(err); 689 return(err);
672} 690}
@@ -714,7 +732,7 @@ do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag)
714 /* Add any subpath that also needs to be counted */ 732 /* Add any subpath that also needs to be counted */
715 tmp = path_strip(path, strip_path); 733 tmp = path_strip(path, strip_path);
716 m += strlen(tmp); 734 m += strlen(tmp);
717 xfree(tmp); 735 free(tmp);
718 736
719 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1) 737 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1)
720 width = ws.ws_col; 738 width = ws.ws_col;
@@ -740,7 +758,7 @@ do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag)
740 758
741 tmp = path_append(path, d[n]->filename); 759 tmp = path_append(path, d[n]->filename);
742 fname = path_strip(tmp, strip_path); 760 fname = path_strip(tmp, strip_path);
743 xfree(tmp); 761 free(tmp);
744 762
745 if (lflag & LS_LONG_VIEW) { 763 if (lflag & LS_LONG_VIEW) {
746 if (lflag & (LS_NUMERIC_VIEW|LS_SI_UNITS)) { 764 if (lflag & (LS_NUMERIC_VIEW|LS_SI_UNITS)) {
@@ -752,7 +770,7 @@ do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag)
752 lname = ls_file(fname, &sb, 1, 770 lname = ls_file(fname, &sb, 1,
753 (lflag & LS_SI_UNITS)); 771 (lflag & LS_SI_UNITS));
754 printf("%s\n", lname); 772 printf("%s\n", lname);
755 xfree(lname); 773 free(lname);
756 } else 774 } else
757 printf("%s\n", d[n]->longname); 775 printf("%s\n", d[n]->longname);
758 } else { 776 } else {
@@ -764,7 +782,7 @@ do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag)
764 c++; 782 c++;
765 } 783 }
766 784
767 xfree(fname); 785 free(fname);
768 } 786 }
769 787
770 if (!(lflag & LS_LONG_VIEW) && (c != 1)) 788 if (!(lflag & LS_LONG_VIEW) && (c != 1))
@@ -834,7 +852,7 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
834 lname = ls_file(fname, g.gl_statv[i], 1, 852 lname = ls_file(fname, g.gl_statv[i], 1,
835 (lflag & LS_SI_UNITS)); 853 (lflag & LS_SI_UNITS));
836 printf("%s\n", lname); 854 printf("%s\n", lname);
837 xfree(lname); 855 free(lname);
838 } else { 856 } else {
839 printf("%-*s", colspace, fname); 857 printf("%-*s", colspace, fname);
840 if (c >= columns) { 858 if (c >= columns) {
@@ -843,7 +861,7 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
843 } else 861 } else
844 c++; 862 c++;
845 } 863 }
846 xfree(fname); 864 free(fname);
847 } 865 }
848 866
849 if (!(lflag & LS_LONG_VIEW) && (c != 1)) 867 if (!(lflag & LS_LONG_VIEW) && (c != 1))
@@ -1112,8 +1130,9 @@ makeargv(const char *arg, int *argcp, int sloppy, char *lastquote,
1112} 1130}
1113 1131
1114static int 1132static int
1115parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag, 1133parse_args(const char **cpp, int *aflag, int *hflag, int *iflag, int *lflag,
1116 int *hflag, int *sflag, unsigned long *n_arg, char **path1, char **path2) 1134 int *pflag, int *rflag, int *sflag, unsigned long *n_arg,
1135 char **path1, char **path2)
1117{ 1136{
1118 const char *cmd, *cp = *cpp; 1137 const char *cmd, *cp = *cpp;
1119 char *cp2, **argv; 1138 char *cp2, **argv;
@@ -1157,14 +1176,15 @@ parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag,
1157 } 1176 }
1158 1177
1159 /* Get arguments and parse flags */ 1178 /* Get arguments and parse flags */
1160 *lflag = *pflag = *rflag = *hflag = *n_arg = 0; 1179 *aflag = *lflag = *pflag = *rflag = *hflag = *n_arg = 0;
1161 *path1 = *path2 = NULL; 1180 *path1 = *path2 = NULL;
1162 optidx = 1; 1181 optidx = 1;
1163 switch (cmdnum) { 1182 switch (cmdnum) {
1164 case I_GET: 1183 case I_GET:
1184 case I_REGET:
1165 case I_PUT: 1185 case I_PUT:
1166 if ((optidx = parse_getput_flags(cmd, argv, argc, 1186 if ((optidx = parse_getput_flags(cmd, argv, argc,
1167 pflag, rflag)) == -1) 1187 aflag, pflag, rflag)) == -1)
1168 return -1; 1188 return -1;
1169 /* Get first pathname (mandatory) */ 1189 /* Get first pathname (mandatory) */
1170 if (argc - optidx < 1) { 1190 if (argc - optidx < 1) {
@@ -1179,6 +1199,11 @@ parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag,
1179 /* Destination is not globbed */ 1199 /* Destination is not globbed */
1180 undo_glob_escape(*path2); 1200 undo_glob_escape(*path2);
1181 } 1201 }
1202 if (*aflag && cmdnum == I_PUT) {
1203 /* XXX implement resume for uploads */
1204 error("Resume is not supported for uploads");
1205 return -1;
1206 }
1182 break; 1207 break;
1183 case I_LINK: 1208 case I_LINK:
1184 if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1) 1209 if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1)
@@ -1287,7 +1312,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1287 int err_abort) 1312 int err_abort)
1288{ 1313{
1289 char *path1, *path2, *tmp; 1314 char *path1, *path2, *tmp;
1290 int pflag = 0, rflag = 0, lflag = 0, iflag = 0, hflag = 0, sflag = 0; 1315 int aflag = 0, hflag = 0, iflag = 0, lflag = 0, pflag = 0;
1316 int rflag = 0, sflag = 0;
1291 int cmdnum, i; 1317 int cmdnum, i;
1292 unsigned long n_arg = 0; 1318 unsigned long n_arg = 0;
1293 Attrib a, *aa; 1319 Attrib a, *aa;
@@ -1296,9 +1322,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1296 glob_t g; 1322 glob_t g;
1297 1323
1298 path1 = path2 = NULL; 1324 path1 = path2 = NULL;
1299 cmdnum = parse_args(&cmd, &pflag, &rflag, &lflag, &iflag, &hflag, 1325 cmdnum = parse_args(&cmd, &aflag, &hflag, &iflag, &lflag, &pflag,
1300 &sflag, &n_arg, &path1, &path2); 1326 &rflag, &sflag, &n_arg, &path1, &path2);
1301
1302 if (iflag != 0) 1327 if (iflag != 0)
1303 err_abort = 0; 1328 err_abort = 0;
1304 1329
@@ -1313,8 +1338,12 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1313 /* Unrecognized command */ 1338 /* Unrecognized command */
1314 err = -1; 1339 err = -1;
1315 break; 1340 break;
1341 case I_REGET:
1342 aflag = 1;
1343 /* FALLTHROUGH */
1316 case I_GET: 1344 case I_GET:
1317 err = process_get(conn, path1, path2, *pwd, pflag, rflag); 1345 err = process_get(conn, path1, path2, *pwd, pflag,
1346 rflag, aflag);
1318 break; 1347 break;
1319 case I_PUT: 1348 case I_PUT:
1320 err = process_put(conn, path1, path2, *pwd, pflag, rflag); 1349 err = process_put(conn, path1, path2, *pwd, pflag, rflag);
@@ -1335,7 +1364,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1335 path1 = make_absolute(path1, *pwd); 1364 path1 = make_absolute(path1, *pwd);
1336 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); 1365 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
1337 for (i = 0; g.gl_pathv[i] && !interrupted; i++) { 1366 for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
1338 printf("Removing %s\n", g.gl_pathv[i]); 1367 if (!quiet)
1368 printf("Removing %s\n", g.gl_pathv[i]);
1339 err = do_rm(conn, g.gl_pathv[i]); 1369 err = do_rm(conn, g.gl_pathv[i]);
1340 if (err != 0 && err_abort) 1370 if (err != 0 && err_abort)
1341 break; 1371 break;
@@ -1359,24 +1389,24 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1359 break; 1389 break;
1360 } 1390 }
1361 if ((aa = do_stat(conn, tmp, 0)) == NULL) { 1391 if ((aa = do_stat(conn, tmp, 0)) == NULL) {
1362 xfree(tmp); 1392 free(tmp);
1363 err = 1; 1393 err = 1;
1364 break; 1394 break;
1365 } 1395 }
1366 if (!(aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) { 1396 if (!(aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) {
1367 error("Can't change directory: Can't check target"); 1397 error("Can't change directory: Can't check target");
1368 xfree(tmp); 1398 free(tmp);
1369 err = 1; 1399 err = 1;
1370 break; 1400 break;
1371 } 1401 }
1372 if (!S_ISDIR(aa->perm)) { 1402 if (!S_ISDIR(aa->perm)) {
1373 error("Can't change directory: \"%s\" is not " 1403 error("Can't change directory: \"%s\" is not "
1374 "a directory", tmp); 1404 "a directory", tmp);
1375 xfree(tmp); 1405 free(tmp);
1376 err = 1; 1406 err = 1;
1377 break; 1407 break;
1378 } 1408 }
1379 xfree(*pwd); 1409 free(*pwd);
1380 *pwd = tmp; 1410 *pwd = tmp;
1381 break; 1411 break;
1382 case I_LS: 1412 case I_LS:
@@ -1431,7 +1461,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1431 a.perm = n_arg; 1461 a.perm = n_arg;
1432 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); 1462 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
1433 for (i = 0; g.gl_pathv[i] && !interrupted; i++) { 1463 for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
1434 printf("Changing mode on %s\n", g.gl_pathv[i]); 1464 if (!quiet)
1465 printf("Changing mode on %s\n", g.gl_pathv[i]);
1435 err = do_setstat(conn, g.gl_pathv[i], &a); 1466 err = do_setstat(conn, g.gl_pathv[i], &a);
1436 if (err != 0 && err_abort) 1467 if (err != 0 && err_abort)
1437 break; 1468 break;
@@ -1460,10 +1491,14 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1460 } 1491 }
1461 aa->flags &= SSH2_FILEXFER_ATTR_UIDGID; 1492 aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;
1462 if (cmdnum == I_CHOWN) { 1493 if (cmdnum == I_CHOWN) {
1463 printf("Changing owner on %s\n", g.gl_pathv[i]); 1494 if (!quiet)
1495 printf("Changing owner on %s\n",
1496 g.gl_pathv[i]);
1464 aa->uid = n_arg; 1497 aa->uid = n_arg;
1465 } else { 1498 } else {
1466 printf("Changing group on %s\n", g.gl_pathv[i]); 1499 if (!quiet)
1500 printf("Changing group on %s\n",
1501 g.gl_pathv[i]);
1467 aa->gid = n_arg; 1502 aa->gid = n_arg;
1468 } 1503 }
1469 err = do_setstat(conn, g.gl_pathv[i], aa); 1504 err = do_setstat(conn, g.gl_pathv[i], aa);
@@ -1504,10 +1539,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1504 1539
1505 if (g.gl_pathc) 1540 if (g.gl_pathc)
1506 globfree(&g); 1541 globfree(&g);
1507 if (path1) 1542 free(path1);
1508 xfree(path1); 1543 free(path2);
1509 if (path2)
1510 xfree(path2);
1511 1544
1512 /* If an unignored error occurs in batch mode we should abort. */ 1545 /* If an unignored error occurs in batch mode we should abort. */
1513 if (err_abort && err != 0) 1546 if (err_abort && err != 0)
@@ -1617,8 +1650,8 @@ complete_cmd_parse(EditLine *el, char *cmd, int lastarg, char quote,
1617 complete_display(list, 0); 1650 complete_display(list, 0);
1618 1651
1619 for (y = 0; list[y] != NULL; y++) 1652 for (y = 0; list[y] != NULL; y++)
1620 xfree(list[y]); 1653 free(list[y]);
1621 xfree(list); 1654 free(list);
1622 return count; 1655 return count;
1623 } 1656 }
1624 1657
@@ -1631,7 +1664,7 @@ complete_cmd_parse(EditLine *el, char *cmd, int lastarg, char quote,
1631 list[count] = NULL; 1664 list[count] = NULL;
1632 1665
1633 if (count == 0) { 1666 if (count == 0) {
1634 xfree(list); 1667 free(list);
1635 return 0; 1668 return 0;
1636 } 1669 }
1637 1670
@@ -1641,8 +1674,8 @@ complete_cmd_parse(EditLine *el, char *cmd, int lastarg, char quote,
1641 complete_display(list, 0); 1674 complete_display(list, 0);
1642 1675
1643 for (y = 0; list[y]; y++) 1676 for (y = 0; list[y]; y++)
1644 xfree(list[y]); 1677 free(list[y]);
1645 xfree(list); 1678 free(list);
1646 1679
1647 if (tmp != NULL) { 1680 if (tmp != NULL) {
1648 tmplen = strlen(tmp); 1681 tmplen = strlen(tmp);
@@ -1663,7 +1696,7 @@ complete_cmd_parse(EditLine *el, char *cmd, int lastarg, char quote,
1663 if (y > 0 && el_insertstr(el, argterm) == -1) 1696 if (y > 0 && el_insertstr(el, argterm) == -1)
1664 fatal("el_insertstr failed."); 1697 fatal("el_insertstr failed.");
1665 } 1698 }
1666 xfree(tmp); 1699 free(tmp);
1667 } 1700 }
1668 1701
1669 return count; 1702 return count;
@@ -1694,8 +1727,9 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
1694 char *file, int remote, int lastarg, char quote, int terminated) 1727 char *file, int remote, int lastarg, char quote, int terminated)
1695{ 1728{
1696 glob_t g; 1729 glob_t g;
1697 char *tmp, *tmp2, ins[3]; 1730 char *tmp, *tmp2, ins[8];
1698 u_int i, hadglob, pwdlen, len, tmplen, filelen, cesc, isesc, isabs; 1731 u_int i, hadglob, pwdlen, len, tmplen, filelen, cesc, isesc, isabs;
1732 int clen;
1699 const LineInfo *lf; 1733 const LineInfo *lf;
1700 1734
1701 /* Glob from "file" location */ 1735 /* Glob from "file" location */
@@ -1727,7 +1761,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
1727 if (tmp[tmplen] == '/') 1761 if (tmp[tmplen] == '/')
1728 pwdlen = tmplen + 1; /* track last seen '/' */ 1762 pwdlen = tmplen + 1; /* track last seen '/' */
1729 } 1763 }
1730 xfree(tmp); 1764 free(tmp);
1731 1765
1732 if (g.gl_matchc == 0) 1766 if (g.gl_matchc == 0)
1733 goto out; 1767 goto out;
@@ -1742,7 +1776,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
1742 1776
1743 tmp2 = complete_ambiguous(file, g.gl_pathv, g.gl_matchc); 1777 tmp2 = complete_ambiguous(file, g.gl_pathv, g.gl_matchc);
1744 tmp = path_strip(tmp2, isabs ? NULL : remote_path); 1778 tmp = path_strip(tmp2, isabs ? NULL : remote_path);
1745 xfree(tmp2); 1779 free(tmp2);
1746 1780
1747 if (tmp == NULL) 1781 if (tmp == NULL)
1748 goto out; 1782 goto out;
@@ -1764,10 +1798,13 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
1764 tmp2 = tmp + filelen - cesc; 1798 tmp2 = tmp + filelen - cesc;
1765 len = strlen(tmp2); 1799 len = strlen(tmp2);
1766 /* quote argument on way out */ 1800 /* quote argument on way out */
1767 for (i = 0; i < len; i++) { 1801 for (i = 0; i < len; i += clen) {
1802 if ((clen = mblen(tmp2 + i, len - i)) < 0 ||
1803 (size_t)clen > sizeof(ins) - 2)
1804 fatal("invalid multibyte character");
1768 ins[0] = '\\'; 1805 ins[0] = '\\';
1769 ins[1] = tmp2[i]; 1806 memcpy(ins + 1, tmp2 + i, clen);
1770 ins[2] = '\0'; 1807 ins[clen + 1] = '\0';
1771 switch (tmp2[i]) { 1808 switch (tmp2[i]) {
1772 case '\'': 1809 case '\'':
1773 case '"': 1810 case '"':
@@ -1804,7 +1841,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
1804 if (i > 0 && el_insertstr(el, ins) == -1) 1841 if (i > 0 && el_insertstr(el, ins) == -1)
1805 fatal("el_insertstr failed."); 1842 fatal("el_insertstr failed.");
1806 } 1843 }
1807 xfree(tmp); 1844 free(tmp);
1808 1845
1809 out: 1846 out:
1810 globfree(&g); 1847 globfree(&g);
@@ -1816,7 +1853,8 @@ static unsigned char
1816complete(EditLine *el, int ch) 1853complete(EditLine *el, int ch)
1817{ 1854{
1818 char **argv, *line, quote; 1855 char **argv, *line, quote;
1819 u_int argc, carg, cursor, len, terminated, ret = CC_ERROR; 1856 int argc, carg;
1857 u_int cursor, len, terminated, ret = CC_ERROR;
1820 const LineInfo *lf; 1858 const LineInfo *lf;
1821 struct complete_ctx *complete_ctx; 1859 struct complete_ctx *complete_ctx;
1822 1860
@@ -1830,7 +1868,7 @@ complete(EditLine *el, int ch)
1830 memcpy(line, lf->buffer, cursor); 1868 memcpy(line, lf->buffer, cursor);
1831 line[cursor] = '\0'; 1869 line[cursor] = '\0';
1832 argv = makeargv(line, &carg, 1, &quote, &terminated); 1870 argv = makeargv(line, &carg, 1, &quote, &terminated);
1833 xfree(line); 1871 free(line);
1834 1872
1835 /* Get all the arguments on the line */ 1873 /* Get all the arguments on the line */
1836 len = lf->lastchar - lf->buffer; 1874 len = lf->lastchar - lf->buffer;
@@ -1842,7 +1880,7 @@ complete(EditLine *el, int ch)
1842 /* Ensure cursor is at EOL or a argument boundary */ 1880 /* Ensure cursor is at EOL or a argument boundary */
1843 if (line[cursor] != ' ' && line[cursor] != '\0' && 1881 if (line[cursor] != ' ' && line[cursor] != '\0' &&
1844 line[cursor] != '\n') { 1882 line[cursor] != '\n') {
1845 xfree(line); 1883 free(line);
1846 return ret; 1884 return ret;
1847 } 1885 }
1848 1886
@@ -1870,7 +1908,7 @@ complete(EditLine *el, int ch)
1870 ret = CC_REDISPLAY; 1908 ret = CC_REDISPLAY;
1871 } 1909 }
1872 1910
1873 xfree(line); 1911 free(line);
1874 return ret; 1912 return ret;
1875} 1913}
1876#endif /* USE_LIBEDIT */ 1914#endif /* USE_LIBEDIT */
@@ -1922,31 +1960,30 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
1922 dir = make_absolute(dir, remote_path); 1960 dir = make_absolute(dir, remote_path);
1923 1961
1924 if (remote_is_dir(conn, dir) && file2 == NULL) { 1962 if (remote_is_dir(conn, dir) && file2 == NULL) {
1925 printf("Changing to: %s\n", dir); 1963 if (!quiet)
1964 printf("Changing to: %s\n", dir);
1926 snprintf(cmd, sizeof cmd, "cd \"%s\"", dir); 1965 snprintf(cmd, sizeof cmd, "cd \"%s\"", dir);
1927 if (parse_dispatch_command(conn, cmd, 1966 if (parse_dispatch_command(conn, cmd,
1928 &remote_path, 1) != 0) { 1967 &remote_path, 1) != 0) {
1929 xfree(dir); 1968 free(dir);
1930 xfree(remote_path); 1969 free(remote_path);
1931 xfree(conn); 1970 free(conn);
1932 return (-1); 1971 return (-1);
1933 } 1972 }
1934 } else { 1973 } else {
1935 /* XXX this is wrong wrt quoting */ 1974 /* XXX this is wrong wrt quoting */
1936 if (file2 == NULL) 1975 snprintf(cmd, sizeof cmd, "get%s %s%s%s",
1937 snprintf(cmd, sizeof cmd, "get %s", dir); 1976 global_aflag ? " -a" : "", dir,
1938 else 1977 file2 == NULL ? "" : " ",
1939 snprintf(cmd, sizeof cmd, "get %s %s", dir, 1978 file2 == NULL ? "" : file2);
1940 file2);
1941
1942 err = parse_dispatch_command(conn, cmd, 1979 err = parse_dispatch_command(conn, cmd,
1943 &remote_path, 1); 1980 &remote_path, 1);
1944 xfree(dir); 1981 free(dir);
1945 xfree(remote_path); 1982 free(remote_path);
1946 xfree(conn); 1983 free(conn);
1947 return (err); 1984 return (err);
1948 } 1985 }
1949 xfree(dir); 1986 free(dir);
1950 } 1987 }
1951 1988
1952 setlinebuf(stdout); 1989 setlinebuf(stdout);
@@ -2004,8 +2041,8 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
2004 if (err != 0) 2041 if (err != 0)
2005 break; 2042 break;
2006 } 2043 }
2007 xfree(remote_path); 2044 free(remote_path);
2008 xfree(conn); 2045 free(conn);
2009 2046
2010#ifdef USE_LIBEDIT 2047#ifdef USE_LIBEDIT
2011 if (el != NULL) 2048 if (el != NULL)
@@ -2112,6 +2149,7 @@ main(int argc, char **argv)
2112 2149
2113 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ 2150 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
2114 sanitise_stdfd(); 2151 sanitise_stdfd();
2152 setlocale(LC_CTYPE, "");
2115 2153
2116 __progname = ssh_get_progname(argv[0]); 2154 __progname = ssh_get_progname(argv[0]);
2117 memset(&args, '\0', sizeof(args)); 2155 memset(&args, '\0', sizeof(args));
@@ -2126,7 +2164,7 @@ main(int argc, char **argv)
2126 infile = stdin; 2164 infile = stdin;
2127 2165
2128 while ((ch = getopt(argc, argv, 2166 while ((ch = getopt(argc, argv,
2129 "1246hpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) { 2167 "1246ahpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) {
2130 switch (ch) { 2168 switch (ch) {
2131 /* Passed through to ssh(1) */ 2169 /* Passed through to ssh(1) */
2132 case '4': 2170 case '4':
@@ -2143,6 +2181,8 @@ main(int argc, char **argv)
2143 addargs(&args, "%s", optarg); 2181 addargs(&args, "%s", optarg);
2144 break; 2182 break;
2145 case 'q': 2183 case 'q':
2184 ll = SYSLOG_LEVEL_ERROR;
2185 quiet = 1;
2146 showprogress = 0; 2186 showprogress = 0;
2147 addargs(&args, "-%c", ch); 2187 addargs(&args, "-%c", ch);
2148 break; 2188 break;
@@ -2164,6 +2204,9 @@ main(int argc, char **argv)
2164 case '2': 2204 case '2':
2165 sshver = 2; 2205 sshver = 2;
2166 break; 2206 break;
2207 case 'a':
2208 global_aflag = 1;
2209 break;
2167 case 'B': 2210 case 'B':
2168 copy_buffer_len = strtol(optarg, &cp, 10); 2211 copy_buffer_len = strtol(optarg, &cp, 10);
2169 if (copy_buffer_len == 0 || *cp != '\0') 2212 if (copy_buffer_len == 0 || *cp != '\0')
@@ -2178,7 +2221,7 @@ main(int argc, char **argv)
2178 (infile = fopen(optarg, "r")) == NULL) 2221 (infile = fopen(optarg, "r")) == NULL)
2179 fatal("%s (%s).", strerror(errno), optarg); 2222 fatal("%s (%s).", strerror(errno), optarg);
2180 showprogress = 0; 2223 showprogress = 0;
2181 batchmode = 1; 2224 quiet = batchmode = 1;
2182 addargs(&args, "-obatchmode yes"); 2225 addargs(&args, "-obatchmode yes");
2183 break; 2226 break;
2184 case 'p': 2227 case 'p':
@@ -2275,7 +2318,7 @@ main(int argc, char **argv)
2275 if (conn == NULL) 2318 if (conn == NULL)
2276 fatal("Couldn't initialise connection to server"); 2319 fatal("Couldn't initialise connection to server");
2277 2320
2278 if (!batchmode) { 2321 if (!quiet) {
2279 if (sftp_direct == NULL) 2322 if (sftp_direct == NULL)
2280 fprintf(stderr, "Connected to %s.\n", host); 2323 fprintf(stderr, "Connected to %s.\n", host);
2281 else 2324 else