summaryrefslogtreecommitdiff
path: root/sftp-int.c
diff options
context:
space:
mode:
Diffstat (limited to 'sftp-int.c')
-rw-r--r--sftp-int.c217
1 files changed, 87 insertions, 130 deletions
diff --git a/sftp-int.c b/sftp-int.c
index 94299aa43..6987de9a3 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.62 2003/08/25 08:13:09 fgsch Exp $"); 28RCSID("$OpenBSD: sftp-int.c,v 1.57 2003/03/05 22:33:43 markus Exp $");
29 29
30#include "buffer.h" 30#include "buffer.h"
31#include "xmalloc.h" 31#include "xmalloc.h"
@@ -53,10 +53,6 @@ int showprogress = 1;
53/* Seperators for interactive commands */ 53/* Seperators for interactive commands */
54#define WHITESPACE " \t\r\n" 54#define WHITESPACE " \t\r\n"
55 55
56/* Define what type of ls view (0 - multi-column) */
57#define LONG_VIEW 1 /* Full view ala ls -l */
58#define SHORT_VIEW 2 /* Single row view ala ls -1 */
59
60/* Commands for interactive mode */ 56/* Commands for interactive mode */
61#define I_CHDIR 1 57#define I_CHDIR 1
62#define I_CHGRP 2 58#define I_CHGRP 2
@@ -311,10 +307,7 @@ parse_ls_flags(const char **cpp, int *lflag)
311 for(; strchr(WHITESPACE, *cp) == NULL; cp++) { 307 for(; strchr(WHITESPACE, *cp) == NULL; cp++) {
312 switch (*cp) { 308 switch (*cp) {
313 case 'l': 309 case 'l':
314 *lflag = LONG_VIEW; 310 *lflag = 1;
315 break;
316 case '1':
317 *lflag = SHORT_VIEW;
318 break; 311 break;
319 default: 312 default:
320 error("Invalid flag -%c", *cp); 313 error("Invalid flag -%c", *cp);
@@ -332,7 +325,7 @@ get_pathname(const char **cpp, char **path)
332{ 325{
333 const char *cp = *cpp, *end; 326 const char *cp = *cpp, *end;
334 char quot; 327 char quot;
335 int i, j; 328 int i;
336 329
337 cp += strspn(cp, WHITESPACE); 330 cp += strspn(cp, WHITESPACE);
338 if (!*cp) { 331 if (!*cp) {
@@ -341,54 +334,37 @@ get_pathname(const char **cpp, char **path)
341 return (0); 334 return (0);
342 } 335 }
343 336
344 *path = xmalloc(strlen(cp) + 1);
345
346 /* Check for quoted filenames */ 337 /* Check for quoted filenames */
347 if (*cp == '\"' || *cp == '\'') { 338 if (*cp == '\"' || *cp == '\'') {
348 quot = *cp++; 339 quot = *cp++;
349 340
350 /* Search for terminating quote, unescape some chars */ 341 end = strchr(cp, quot);
351 for (i = j = 0; i <= strlen(cp); i++) { 342 if (end == NULL) {
352 if (cp[i] == quot) { /* Found quote */ 343 error("Unterminated quote");
353 (*path)[j] = '\0'; 344 goto fail;
354 break;
355 }
356 if (cp[i] == '\0') { /* End of string */
357 error("Unterminated quote");
358 goto fail;
359 }
360 if (cp[i] == '\\') { /* Escaped characters */
361 i++;
362 if (cp[i] != '\'' && cp[i] != '\"' &&
363 cp[i] != '\\') {
364 error("Bad escaped character '\%c'",
365 cp[i]);
366 goto fail;
367 }
368 }
369 (*path)[j++] = cp[i];
370 } 345 }
371 346 if (cp == end) {
372 if (j == 0) {
373 error("Empty quotes"); 347 error("Empty quotes");
374 goto fail; 348 goto fail;
375 } 349 }
376 *cpp = cp + i + strspn(cp + i, WHITESPACE); 350 *cpp = end + 1 + strspn(end + 1, WHITESPACE);
377 } else { 351 } else {
378 /* Read to end of filename */ 352 /* Read to end of filename */
379 end = strpbrk(cp, WHITESPACE); 353 end = strpbrk(cp, WHITESPACE);
380 if (end == NULL) 354 if (end == NULL)
381 end = strchr(cp, '\0'); 355 end = strchr(cp, '\0');
382 *cpp = end + strspn(end, WHITESPACE); 356 *cpp = end + strspn(end, WHITESPACE);
383
384 memcpy(*path, cp, end - cp);
385 (*path)[end - cp] = '\0';
386 } 357 }
387 return (0); 358
359 i = end - cp;
360
361 *path = xmalloc(i + 1);
362 memcpy(*path, cp, i);
363 (*path)[i] = '\0';
364 return(0);
388 365
389 fail: 366 fail:
390 xfree(*path); 367 *path = NULL;
391 *path = NULL;
392 return (-1); 368 return (-1);
393} 369}
394 370
@@ -449,8 +425,29 @@ process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag)
449 goto out; 425 goto out;
450 } 426 }
451 427
452 /* If multiple matches, dst must be a directory or unspecified */ 428 /* Only one match, dst may be file, directory or unspecified */
453 if (g.gl_matchc > 1 && dst && !is_dir(dst)) { 429 if (g.gl_pathv[0] && g.gl_matchc == 1) {
430 if (dst) {
431 /* If directory specified, append filename */
432 if (is_dir(dst)) {
433 if (infer_path(g.gl_pathv[0], &tmp)) {
434 err = 1;
435 goto out;
436 }
437 abs_dst = path_append(dst, tmp);
438 xfree(tmp);
439 } else
440 abs_dst = xstrdup(dst);
441 } else if (infer_path(g.gl_pathv[0], &abs_dst)) {
442 err = -1;
443 goto out;
444 }
445 err = do_download(conn, g.gl_pathv[0], abs_dst, pflag);
446 goto out;
447 }
448
449 /* Multiple matches, dst may be directory or unspecified */
450 if (dst && !is_dir(dst)) {
454 error("Multiple files match, but \"%s\" is not a directory", 451 error("Multiple files match, but \"%s\" is not a directory",
455 dst); 452 dst);
456 err = -1; 453 err = -1;
@@ -462,19 +459,7 @@ process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag)
462 err = -1; 459 err = -1;
463 goto out; 460 goto out;
464 } 461 }
465 462 if (dst) {
466 if (g.gl_matchc == 1 && dst) {
467 /* If directory specified, append filename */
468 if (is_dir(dst)) {
469 if (infer_path(g.gl_pathv[0], &tmp)) {
470 err = 1;
471 goto out;
472 }
473 abs_dst = path_append(dst, tmp);
474 xfree(tmp);
475 } else
476 abs_dst = xstrdup(dst);
477 } else if (dst) {
478 abs_dst = path_append(dst, tmp); 463 abs_dst = path_append(dst, tmp);
479 xfree(tmp); 464 xfree(tmp);
480 } else 465 } else
@@ -518,8 +503,38 @@ process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag)
518 goto out; 503 goto out;
519 } 504 }
520 505
521 /* If multiple matches, dst may be directory or unspecified */ 506 /* Only one match, dst may be file, directory or unspecified */
522 if (g.gl_matchc > 1 && tmp_dst && !remote_is_dir(conn, tmp_dst)) { 507 if (g.gl_pathv[0] && g.gl_matchc == 1) {
508 if (!is_reg(g.gl_pathv[0])) {
509 error("Can't upload %s: not a regular file",
510 g.gl_pathv[0]);
511 err = 1;
512 goto out;
513 }
514 if (tmp_dst) {
515 /* If directory specified, append filename */
516 if (remote_is_dir(conn, tmp_dst)) {
517 if (infer_path(g.gl_pathv[0], &tmp)) {
518 err = 1;
519 goto out;
520 }
521 abs_dst = path_append(tmp_dst, tmp);
522 xfree(tmp);
523 } else
524 abs_dst = xstrdup(tmp_dst);
525 } else {
526 if (infer_path(g.gl_pathv[0], &abs_dst)) {
527 err = -1;
528 goto out;
529 }
530 abs_dst = make_absolute(abs_dst, pwd);
531 }
532 err = do_upload(conn, g.gl_pathv[0], abs_dst, pflag);
533 goto out;
534 }
535
536 /* Multiple matches, dst may be directory or unspecified */
537 if (tmp_dst && !remote_is_dir(conn, tmp_dst)) {
523 error("Multiple files match, but \"%s\" is not a directory", 538 error("Multiple files match, but \"%s\" is not a directory",
524 tmp_dst); 539 tmp_dst);
525 err = -1; 540 err = -1;
@@ -536,20 +551,7 @@ process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag)
536 err = -1; 551 err = -1;
537 goto out; 552 goto out;
538 } 553 }
539 554 if (tmp_dst) {
540 if (g.gl_matchc == 1 && tmp_dst) {
541 /* If directory specified, append filename */
542 if (remote_is_dir(conn, tmp_dst)) {
543 if (infer_path(g.gl_pathv[0], &tmp)) {
544 err = 1;
545 goto out;
546 }
547 abs_dst = path_append(tmp_dst, tmp);
548 xfree(tmp);
549 } else
550 abs_dst = xstrdup(tmp_dst);
551
552 } else if (tmp_dst) {
553 abs_dst = path_append(tmp_dst, tmp); 555 abs_dst = path_append(tmp_dst, tmp);
554 xfree(tmp); 556 xfree(tmp);
555 } else 557 } else
@@ -565,7 +567,6 @@ out:
565 xfree(abs_dst); 567 xfree(abs_dst);
566 if (tmp_dst) 568 if (tmp_dst)
567 xfree(tmp_dst); 569 xfree(tmp_dst);
568 globfree(&g);
569 return(err); 570 return(err);
570} 571}
571 572
@@ -582,27 +583,15 @@ sdirent_comp(const void *aa, const void *bb)
582static int 583static int
583do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag) 584do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag)
584{ 585{
585 int n, c = 1, colspace = 0, columns = 1; 586 int n;
586 SFTP_DIRENT **d; 587 SFTP_DIRENT **d;
587 588
588 if ((n = do_readdir(conn, path, &d)) != 0) 589 if ((n = do_readdir(conn, path, &d)) != 0)
589 return (n); 590 return (n);
590 591
591 if (!(lflag & SHORT_VIEW)) { 592 /* Count entries for sort */
592 int m = 0, width = 80; 593 for (n = 0; d[n] != NULL; n++)
593 struct winsize ws; 594 ;
594
595 /* Count entries for sort and find longest filename */
596 for (n = 0; d[n] != NULL; n++)
597 m = MAX(m, strlen(d[n]->filename));
598
599 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1)
600 width = ws.ws_col;
601
602 columns = width / (m + 2);
603 columns = MAX(columns, 1);
604 colspace = width / columns;
605 }
606 595
607 qsort(d, n, sizeof(*d), sdirent_comp); 596 qsort(d, n, sizeof(*d), sdirent_comp);
608 597
@@ -613,7 +602,7 @@ do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag)
613 fname = path_strip(tmp, strip_path); 602 fname = path_strip(tmp, strip_path);
614 xfree(tmp); 603 xfree(tmp);
615 604
616 if (lflag & LONG_VIEW) { 605 if (lflag) {
617 char *lname; 606 char *lname;
618 struct stat sb; 607 struct stat sb;
619 608
@@ -623,20 +612,13 @@ do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag)
623 printf("%s\n", lname); 612 printf("%s\n", lname);
624 xfree(lname); 613 xfree(lname);
625 } else { 614 } else {
626 printf("%-*s", colspace, fname); 615 /* XXX - multicolumn display would be nice here */
627 if (c >= columns) { 616 printf("%s\n", fname);
628 printf("\n");
629 c = 1;
630 } else
631 c++;
632 } 617 }
633 618
634 xfree(fname); 619 xfree(fname);
635 } 620 }
636 621
637 if (!(lflag & LONG_VIEW) && (c != 1))
638 printf("\n");
639
640 free_sftp_dirents(d); 622 free_sftp_dirents(d);
641 return (0); 623 return (0);
642} 624}
@@ -647,8 +629,9 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
647 int lflag) 629 int lflag)
648{ 630{
649 glob_t g; 631 glob_t g;
650 int i, c = 1, colspace = 0, columns = 1; 632 int i;
651 Attrib *a; 633 Attrib *a;
634 struct stat sb;
652 635
653 memset(&g, 0, sizeof(g)); 636 memset(&g, 0, sizeof(g));
654 637
@@ -675,31 +658,12 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
675 } 658 }
676 } 659 }
677 660
678 if (!(lflag & SHORT_VIEW)) {
679 int m = 0, width = 80;
680 struct winsize ws;
681
682 /* Count entries for sort and find longest filename */
683 for (i = 0; g.gl_pathv[i]; i++)
684 m = MAX(m, strlen(g.gl_pathv[i]));
685
686 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1)
687 width = ws.ws_col;
688
689 columns = width / (m + 2);
690 columns = MAX(columns, 1);
691 colspace = width / columns;
692 }
693
694 for (i = 0; g.gl_pathv[i]; i++) { 661 for (i = 0; g.gl_pathv[i]; i++) {
695 char *fname; 662 char *fname, *lname;
696 663
697 fname = path_strip(g.gl_pathv[i], strip_path); 664 fname = path_strip(g.gl_pathv[i], strip_path);
698 665
699 if (lflag & LONG_VIEW) { 666 if (lflag) {
700 char *lname;
701 struct stat sb;
702
703 /* 667 /*
704 * XXX: this is slow - 1 roundtrip per path 668 * XXX: this is slow - 1 roundtrip per path
705 * A solution to this is to fork glob() and 669 * A solution to this is to fork glob() and
@@ -715,19 +679,12 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
715 printf("%s\n", lname); 679 printf("%s\n", lname);
716 xfree(lname); 680 xfree(lname);
717 } else { 681 } else {
718 printf("%-*s", colspace, fname); 682 /* XXX - multicolumn display would be nice here */
719 if (c >= columns) { 683 printf("%s\n", fname);
720 printf("\n");
721 c = 1;
722 } else
723 c++;
724 } 684 }
725 xfree(fname); 685 xfree(fname);
726 } 686 }
727 687
728 if (!(lflag & LONG_VIEW) && (c != 1))
729 printf("\n");
730
731 if (g.gl_pathc) 688 if (g.gl_pathc)
732 globfree(&g); 689 globfree(&g);
733 690