diff options
-rw-r--r-- | coreutils/ls.c | 196 | ||||
-rw-r--r-- | shell/cmdedit.c | 58 |
2 files changed, 121 insertions, 133 deletions
diff --git a/coreutils/ls.c b/coreutils/ls.c index 853a18059..8a2b5e138 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c | |||
@@ -43,11 +43,9 @@ | |||
43 | 43 | ||
44 | enum { | 44 | enum { |
45 | TERMINAL_WIDTH = 80, /* use 79 if terminal has linefold bug */ | 45 | TERMINAL_WIDTH = 80, /* use 79 if terminal has linefold bug */ |
46 | COLUMN_WIDTH = 14, /* default if AUTOWIDTH not defined */ | ||
47 | COLUMN_GAP = 2, /* includes the file type char */ | 46 | COLUMN_GAP = 2, /* includes the file type char */ |
48 | }; | 47 | }; |
49 | 48 | ||
50 | |||
51 | /************************************************************************/ | 49 | /************************************************************************/ |
52 | 50 | ||
53 | #include <sys/types.h> | 51 | #include <sys/types.h> |
@@ -167,7 +165,7 @@ struct dnode { /* the basic node */ | |||
167 | }; | 165 | }; |
168 | typedef struct dnode dnode_t; | 166 | typedef struct dnode dnode_t; |
169 | 167 | ||
170 | static struct dnode **list_dir(char *); | 168 | static struct dnode **list_dir(const char *); |
171 | static struct dnode **dnalloc(int); | 169 | static struct dnode **dnalloc(int); |
172 | static int list_single(struct dnode *); | 170 | static int list_single(struct dnode *); |
173 | 171 | ||
@@ -186,14 +184,12 @@ static unsigned int time_fmt; | |||
186 | static unsigned int follow_links = FALSE; | 184 | static unsigned int follow_links = FALSE; |
187 | #endif | 185 | #endif |
188 | 186 | ||
189 | static unsigned short column = 0; | ||
190 | |||
191 | #ifdef CONFIG_FEATURE_AUTOWIDTH | 187 | #ifdef CONFIG_FEATURE_AUTOWIDTH |
192 | static unsigned short terminal_width = TERMINAL_WIDTH; | 188 | static unsigned short terminal_width = TERMINAL_WIDTH; |
193 | static unsigned short column_width = COLUMN_WIDTH; | ||
194 | static unsigned short tabstops = COLUMN_GAP; | 189 | static unsigned short tabstops = COLUMN_GAP; |
195 | #else | 190 | #else |
196 | static unsigned short column_width = COLUMN_WIDTH; | 191 | #define tabstops COLUMN_GAP |
192 | #define terminal_width TERMINAL_WIDTH | ||
197 | #endif | 193 | #endif |
198 | 194 | ||
199 | static int status = EXIT_SUCCESS; | 195 | static int status = EXIT_SUCCESS; |
@@ -202,35 +198,31 @@ static int status = EXIT_SUCCESS; | |||
202 | static unsigned long ls_disp_hr = 0; | 198 | static unsigned long ls_disp_hr = 0; |
203 | #endif | 199 | #endif |
204 | 200 | ||
205 | static int my_stat(struct dnode *cur) | 201 | static struct dnode *my_stat(char *fullname, char *name) |
206 | { | 202 | { |
203 | struct stat dstat; | ||
204 | struct dnode *cur; | ||
205 | |||
207 | #ifdef CONFIG_FEATURE_LS_FOLLOWLINKS | 206 | #ifdef CONFIG_FEATURE_LS_FOLLOWLINKS |
208 | if (follow_links) { | 207 | if (follow_links) { |
209 | if (stat(cur->fullname, &cur->dstat)) { | 208 | if (stat(fullname, &dstat)) { |
210 | perror_msg("%s", cur->fullname); | 209 | perror_msg("%s", fullname); |
211 | status = EXIT_FAILURE; | 210 | status = EXIT_FAILURE; |
212 | free(cur->fullname); | 211 | return 0; |
213 | free(cur); | ||
214 | return -1; | ||
215 | } | 212 | } |
216 | } else | 213 | } else |
217 | #endif | 214 | #endif |
218 | if (lstat(cur->fullname, &cur->dstat)) { | 215 | if (lstat(fullname, &dstat)) { |
219 | perror_msg("%s", cur->fullname); | 216 | perror_msg("%s", fullname); |
220 | status = EXIT_FAILURE; | 217 | status = EXIT_FAILURE; |
221 | free(cur->fullname); | ||
222 | free(cur); | ||
223 | return -1; | ||
224 | } | ||
225 | return 0; | 218 | return 0; |
226 | } | ||
227 | |||
228 | static void newline(void) | ||
229 | { | ||
230 | if (column > 0) { | ||
231 | putchar('\n'); | ||
232 | column = 0; | ||
233 | } | 219 | } |
220 | |||
221 | cur = (struct dnode *) xmalloc(sizeof(struct dnode)); | ||
222 | cur->fullname = fullname; | ||
223 | cur->name = name; | ||
224 | cur->dstat = dstat; | ||
225 | return cur; | ||
234 | } | 226 | } |
235 | 227 | ||
236 | /*----------------------------------------------------------------------*/ | 228 | /*----------------------------------------------------------------------*/ |
@@ -239,7 +231,6 @@ static char fgcolor(mode_t mode) | |||
239 | { | 231 | { |
240 | /* Check wheter the file is existing (if so, color it red!) */ | 232 | /* Check wheter the file is existing (if so, color it red!) */ |
241 | if (errno == ENOENT) { | 233 | if (errno == ENOENT) { |
242 | errno = 0; | ||
243 | return '\037'; | 234 | return '\037'; |
244 | } | 235 | } |
245 | if (LIST_EXEC && S_ISREG(mode) | 236 | if (LIST_EXEC && S_ISREG(mode) |
@@ -272,24 +263,6 @@ static char append_char(mode_t mode) | |||
272 | #endif | 263 | #endif |
273 | 264 | ||
274 | /*----------------------------------------------------------------------*/ | 265 | /*----------------------------------------------------------------------*/ |
275 | static void nexttabstop(void) | ||
276 | { | ||
277 | static short nexttab = 0; | ||
278 | int n = 0; | ||
279 | |||
280 | if (column > 0) { | ||
281 | n = nexttab - column; | ||
282 | if (n < 1) | ||
283 | n = 1; | ||
284 | while (n--) { | ||
285 | putchar(' '); | ||
286 | column++; | ||
287 | } | ||
288 | } | ||
289 | nexttab = column + column_width + COLUMN_GAP; | ||
290 | } | ||
291 | |||
292 | /*----------------------------------------------------------------------*/ | ||
293 | static int is_subdir(struct dnode *dn) | 266 | static int is_subdir(struct dnode *dn) |
294 | { | 267 | { |
295 | return (S_ISDIR(dn->dstat.st_mode) && strcmp(dn->name, ".") != 0 && | 268 | return (S_ISDIR(dn->dstat.st_mode) && strcmp(dn->name, ".") != 0 && |
@@ -437,7 +410,11 @@ static int sortcmp(struct dnode *d1, struct dnode *d2) | |||
437 | cmp = 1; | 410 | cmp = 1; |
438 | if (dif == 0) { | 411 | if (dif == 0) { |
439 | /* sort by name- may be a tie_breaker for time or size cmp */ | 412 | /* sort by name- may be a tie_breaker for time or size cmp */ |
413 | #ifdef CONFIG_LOCALE_SUPPORT | ||
414 | dif = strcoll(d1->name, d2->name); | ||
415 | #else | ||
440 | dif = strcmp(d1->name, d2->name); | 416 | dif = strcmp(d1->name, d2->name); |
417 | #endif | ||
441 | if (dif > 0) | 418 | if (dif > 0) |
442 | cmp = 1; | 419 | cmp = 1; |
443 | if (dif < 0) | 420 | if (dif < 0) |
@@ -479,46 +456,40 @@ static void shellsort(struct dnode **dn, int size) | |||
479 | static void showfiles(struct dnode **dn, int nfiles) | 456 | static void showfiles(struct dnode **dn, int nfiles) |
480 | { | 457 | { |
481 | int i, ncols, nrows, row, nc; | 458 | int i, ncols, nrows, row, nc; |
482 | 459 | int column = 0; | |
483 | #ifdef CONFIG_FEATURE_AUTOWIDTH | 460 | int nexttab = 0; |
484 | int len; | 461 | int column_width = 0; /* for STYLE_LONG and STYLE_SINGLE not used */ |
485 | #endif | ||
486 | 462 | ||
487 | if (dn == NULL || nfiles < 1) | 463 | if (dn == NULL || nfiles < 1) |
488 | return; | 464 | return; |
489 | 465 | ||
490 | #ifdef CONFIG_FEATURE_AUTOWIDTH | 466 | switch (style_fmt) { |
467 | case STYLE_LONG: /* one record per line, extended info */ | ||
468 | case STYLE_SINGLE: /* one record per line */ | ||
469 | ncols = 1; | ||
470 | break; | ||
471 | default: | ||
491 | /* find the longest file name- use that as the column width */ | 472 | /* find the longest file name- use that as the column width */ |
492 | column_width = 0; | ||
493 | for (i = 0; i < nfiles; i++) { | 473 | for (i = 0; i < nfiles; i++) { |
494 | len = strlen(dn[i]->name) + | 474 | int len = strlen(dn[i]->name) + |
495 | ((list_fmt & LIST_INO) ? 8 : 0) + | 475 | ((list_fmt & LIST_INO) ? 8 : 0) + |
496 | ((list_fmt & LIST_BLOCKS) ? 5 : 0); | 476 | ((list_fmt & LIST_BLOCKS) ? 5 : 0); |
497 | if (column_width < len) | 477 | if (column_width < len) |
498 | column_width = len; | 478 | column_width = len; |
499 | } | 479 | } |
500 | ncols = (int) (terminal_width / (column_width + COLUMN_GAP)); | 480 | column_width += tabstops; |
501 | #else | 481 | ncols = (int) (terminal_width / column_width); |
502 | ncols = TERMINAL_WIDTH; | ||
503 | #endif | ||
504 | switch (style_fmt) { | ||
505 | case STYLE_LONG: /* one record per line, extended info */ | ||
506 | case STYLE_SINGLE: /* one record per line */ | ||
507 | ncols = 1; | ||
508 | break; | ||
509 | } | 482 | } |
510 | 483 | ||
511 | if (ncols > 1) { | 484 | if (ncols > 1) { |
512 | nrows = nfiles / ncols; | 485 | nrows = nfiles / ncols; |
486 | if ((nrows * ncols) < nfiles) | ||
487 | nrows++; /* round up fractionals */ | ||
513 | } else { | 488 | } else { |
514 | nrows = nfiles; | 489 | nrows = nfiles; |
515 | ncols = 1; | 490 | ncols = 1; |
516 | } | 491 | } |
517 | if ((nrows * ncols) < nfiles) | ||
518 | nrows++; /* round up fractionals */ | ||
519 | 492 | ||
520 | if (nrows > nfiles) | ||
521 | nrows = nfiles; | ||
522 | for (row = 0; row < nrows; row++) { | 493 | for (row = 0; row < nrows; row++) { |
523 | for (nc = 0; nc < ncols; nc++) { | 494 | for (nc = 0; nc < ncols; nc++) { |
524 | /* reach into the array based on the column and row */ | 495 | /* reach into the array based on the column and row */ |
@@ -526,11 +497,19 @@ static void showfiles(struct dnode **dn, int nfiles) | |||
526 | if (disp_opts & DISP_ROWS) | 497 | if (disp_opts & DISP_ROWS) |
527 | i = (row * ncols) + nc; /* display across row */ | 498 | i = (row * ncols) + nc; /* display across row */ |
528 | if (i < nfiles) { | 499 | if (i < nfiles) { |
529 | nexttabstop(); | 500 | if (column > 0) { |
530 | list_single(dn[i]); | 501 | nexttab -= column; |
502 | while (nexttab--) { | ||
503 | putchar(' '); | ||
504 | column++; | ||
505 | } | ||
531 | } | 506 | } |
507 | nexttab = column + column_width; | ||
508 | column += list_single(dn[i]); | ||
532 | } | 509 | } |
533 | newline(); | 510 | } |
511 | putchar('\n'); | ||
512 | column = 0; | ||
534 | } | 513 | } |
535 | } | 514 | } |
536 | 515 | ||
@@ -580,7 +559,7 @@ static void showdirs(struct dnode **dn, int ndirs) | |||
580 | } | 559 | } |
581 | 560 | ||
582 | /*----------------------------------------------------------------------*/ | 561 | /*----------------------------------------------------------------------*/ |
583 | static struct dnode **list_dir(char *path) | 562 | static struct dnode **list_dir(const char *path) |
584 | { | 563 | { |
585 | struct dnode *dn, *cur, **dnp; | 564 | struct dnode *dn, *cur, **dnp; |
586 | struct dirent *entry; | 565 | struct dirent *entry; |
@@ -599,18 +578,21 @@ static struct dnode **list_dir(char *path) | |||
599 | return (NULL); /* could not open the dir */ | 578 | return (NULL); /* could not open the dir */ |
600 | } | 579 | } |
601 | while ((entry = readdir(dir)) != NULL) { | 580 | while ((entry = readdir(dir)) != NULL) { |
581 | char *fullname; | ||
582 | |||
602 | /* are we going to list the file- it may be . or .. or a hidden file */ | 583 | /* are we going to list the file- it may be . or .. or a hidden file */ |
603 | if ((strcmp(entry->d_name, ".") == 0) && !(disp_opts & DISP_DOT)) | 584 | if (entry->d_name[0] == '.') { |
604 | continue; | 585 | if ((entry->d_name[1] == 0 || ( |
605 | if ((strcmp(entry->d_name, "..") == 0) && !(disp_opts & DISP_DOT)) | 586 | entry->d_name[1] == '.' |
587 | && entry->d_name[2] == 0)) | ||
588 | && !(disp_opts & DISP_DOT)) | ||
606 | continue; | 589 | continue; |
607 | if ((entry->d_name[0] == '.') && !(disp_opts & DISP_HIDDEN)) | 590 | if (!(disp_opts & DISP_HIDDEN)) |
608 | continue; | 591 | continue; |
609 | cur = (struct dnode *) xmalloc(sizeof(struct dnode)); | 592 | } |
610 | cur->fullname = concat_path_file(path, entry->d_name); | 593 | fullname = concat_path_file(path, entry->d_name); |
611 | cur->name = cur->fullname + | 594 | cur = my_stat(fullname, strrchr(fullname, '/') + 1); |
612 | (strlen(cur->fullname) - strlen(entry->d_name)); | 595 | if (!cur) |
613 | if (my_stat(cur)) | ||
614 | continue; | 596 | continue; |
615 | cur->next = dn; | 597 | cur->next = dn; |
616 | dn = cur; | 598 | dn = cur; |
@@ -621,7 +603,7 @@ static struct dnode **list_dir(char *path) | |||
621 | /* now that we know how many files there are | 603 | /* now that we know how many files there are |
622 | ** allocate memory for an array to hold dnode pointers | 604 | ** allocate memory for an array to hold dnode pointers |
623 | */ | 605 | */ |
624 | if (nfiles < 1) | 606 | if (dn == NULL) |
625 | return (NULL); | 607 | return (NULL); |
626 | dnp = dnalloc(nfiles); | 608 | dnp = dnalloc(nfiles); |
627 | for (i = 0, cur = dn; i < nfiles; i++) { | 609 | for (i = 0, cur = dn; i < nfiles; i++) { |
@@ -635,10 +617,10 @@ static struct dnode **list_dir(char *path) | |||
635 | /*----------------------------------------------------------------------*/ | 617 | /*----------------------------------------------------------------------*/ |
636 | static int list_single(struct dnode *dn) | 618 | static int list_single(struct dnode *dn) |
637 | { | 619 | { |
638 | int i; | 620 | int i, column = 0; |
639 | 621 | ||
640 | #ifdef CONFIG_FEATURE_LS_USERNAME | 622 | #ifdef CONFIG_FEATURE_LS_USERNAME |
641 | char scratch[BUFSIZ + 1]; | 623 | char scratch[16]; |
642 | #endif | 624 | #endif |
643 | #ifdef CONFIG_FEATURE_LS_TIMESTAMPS | 625 | #ifdef CONFIG_FEATURE_LS_TIMESTAMPS |
644 | char *filetime; | 626 | char *filetime; |
@@ -649,7 +631,7 @@ static int list_single(struct dnode *dn) | |||
649 | char append; | 631 | char append; |
650 | #endif | 632 | #endif |
651 | 633 | ||
652 | if (dn == NULL || dn->fullname == NULL) | 634 | if (dn->fullname == NULL) |
653 | return (0); | 635 | return (0); |
654 | 636 | ||
655 | #ifdef CONFIG_FEATURE_LS_TIMESTAMPS | 637 | #ifdef CONFIG_FEATURE_LS_TIMESTAMPS |
@@ -667,29 +649,20 @@ static int list_single(struct dnode *dn) | |||
667 | for (i = 0; i <= 31; i++) { | 649 | for (i = 0; i <= 31; i++) { |
668 | switch (list_fmt & (1 << i)) { | 650 | switch (list_fmt & (1 << i)) { |
669 | case LIST_INO: | 651 | case LIST_INO: |
670 | printf("%7ld ", (long int) dn->dstat.st_ino); | 652 | column += printf("%7ld ", (long int) dn->dstat.st_ino); |
671 | column += 8; | ||
672 | break; | 653 | break; |
673 | case LIST_BLOCKS: | 654 | case LIST_BLOCKS: |
674 | #ifdef CONFIG_FEATURE_HUMAN_READABLE | ||
675 | printf("%6s ", make_human_readable_str(dn->dstat.st_blocks >> 1, | ||
676 | KILOBYTE, (ls_disp_hr == TRUE) ? 0 : KILOBYTE)); | ||
677 | #else | ||
678 | #if _FILE_OFFSET_BITS == 64 | 655 | #if _FILE_OFFSET_BITS == 64 |
679 | printf("%4lld ", dn->dstat.st_blocks >> 1); | 656 | column += printf("%4lld ", dn->dstat.st_blocks >> 1); |
680 | #else | 657 | #else |
681 | printf("%4ld ", dn->dstat.st_blocks >> 1); | 658 | column += printf("%4ld ", dn->dstat.st_blocks >> 1); |
682 | #endif | ||
683 | #endif | 659 | #endif |
684 | column += 5; | ||
685 | break; | 660 | break; |
686 | case LIST_MODEBITS: | 661 | case LIST_MODEBITS: |
687 | printf("%-10s ", (char *) mode_string(dn->dstat.st_mode)); | 662 | column += printf("%-10s ", (char *) mode_string(dn->dstat.st_mode)); |
688 | column += 10; | ||
689 | break; | 663 | break; |
690 | case LIST_NLINKS: | 664 | case LIST_NLINKS: |
691 | printf("%4ld ", (long) dn->dstat.st_nlink); | 665 | column += printf("%4ld ", (long) dn->dstat.st_nlink); |
692 | column += 10; | ||
693 | break; | 666 | break; |
694 | case LIST_ID_NAME: | 667 | case LIST_ID_NAME: |
695 | #ifdef CONFIG_FEATURE_LS_USERNAME | 668 | #ifdef CONFIG_FEATURE_LS_USERNAME |
@@ -701,29 +674,28 @@ static int list_single(struct dnode *dn) | |||
701 | break; | 674 | break; |
702 | #endif | 675 | #endif |
703 | case LIST_ID_NUMERIC: | 676 | case LIST_ID_NUMERIC: |
704 | printf("%-8d %-8d", dn->dstat.st_uid, dn->dstat.st_gid); | 677 | column += printf("%-8d %-8d", dn->dstat.st_uid, dn->dstat.st_gid); |
705 | column += 17; | ||
706 | break; | 678 | break; |
707 | case LIST_SIZE: | 679 | case LIST_SIZE: |
708 | case LIST_DEV: | 680 | case LIST_DEV: |
709 | if (S_ISBLK(dn->dstat.st_mode) || S_ISCHR(dn->dstat.st_mode)) { | 681 | if (S_ISBLK(dn->dstat.st_mode) || S_ISCHR(dn->dstat.st_mode)) { |
710 | printf("%4d, %3d ", (int) MAJOR(dn->dstat.st_rdev), | 682 | column += printf("%4d, %3d ", (int) MAJOR(dn->dstat.st_rdev), |
711 | (int) MINOR(dn->dstat.st_rdev)); | 683 | (int) MINOR(dn->dstat.st_rdev)); |
712 | } else { | 684 | } else { |
713 | #ifdef CONFIG_FEATURE_HUMAN_READABLE | 685 | #ifdef CONFIG_FEATURE_HUMAN_READABLE |
714 | if (ls_disp_hr == TRUE) { | 686 | if (ls_disp_hr == TRUE) { |
715 | printf("%8s ", make_human_readable_str(dn->dstat.st_size, 1, 0)); | 687 | column += printf("%9s ", |
688 | make_human_readable_str(dn->dstat.st_size, 1, 0)); | ||
716 | } else | 689 | } else |
717 | #endif | 690 | #endif |
718 | { | 691 | { |
719 | #if _FILE_OFFSET_BITS == 64 | 692 | #if _FILE_OFFSET_BITS == 64 |
720 | printf("%9lld ", (long long) dn->dstat.st_size); | 693 | column += printf("%9lld ", (long long) dn->dstat.st_size); |
721 | #else | 694 | #else |
722 | printf("%9ld ", dn->dstat.st_size); | 695 | column += printf("%9ld ", dn->dstat.st_size); |
723 | #endif | 696 | #endif |
724 | } | 697 | } |
725 | } | 698 | } |
726 | column += 10; | ||
727 | break; | 699 | break; |
728 | #ifdef CONFIG_FEATURE_LS_TIMESTAMPS | 700 | #ifdef CONFIG_FEATURE_LS_TIMESTAMPS |
729 | case LIST_FULLTIME: | 701 | case LIST_FULLTIME: |
@@ -752,13 +724,12 @@ static int list_single(struct dnode *dn) | |||
752 | fgcolor(info.st_mode)); | 724 | fgcolor(info.st_mode)); |
753 | } | 725 | } |
754 | #endif | 726 | #endif |
755 | printf("%s", dn->name); | 727 | column += printf("%s", dn->name); |
756 | #ifdef CONFIG_FEATURE_LS_COLOR | 728 | #ifdef CONFIG_FEATURE_LS_COLOR |
757 | if (show_color) { | 729 | if (show_color) { |
758 | printf("\033[0m"); | 730 | printf("\033[0m"); |
759 | } | 731 | } |
760 | #endif | 732 | #endif |
761 | column += strlen(dn->name); | ||
762 | break; | 733 | break; |
763 | case LIST_SYMLINK: | 734 | case LIST_SYMLINK: |
764 | if (S_ISLNK(dn->dstat.st_mode)) { | 735 | if (S_ISLNK(dn->dstat.st_mode)) { |
@@ -778,13 +749,12 @@ static int list_single(struct dnode *dn) | |||
778 | fgcolor(info.st_mode)); | 749 | fgcolor(info.st_mode)); |
779 | } | 750 | } |
780 | #endif | 751 | #endif |
781 | printf("%s", lpath); | 752 | column += printf("%s", lpath) + 4; |
782 | #ifdef CONFIG_FEATURE_LS_COLOR | 753 | #ifdef CONFIG_FEATURE_LS_COLOR |
783 | if (show_color) { | 754 | if (show_color) { |
784 | printf("\033[0m"); | 755 | printf("\033[0m"); |
785 | } | 756 | } |
786 | #endif | 757 | #endif |
787 | column += strlen(lpath) + 4; | ||
788 | free(lpath); | 758 | free(lpath); |
789 | } | 759 | } |
790 | } | 760 | } |
@@ -800,7 +770,7 @@ static int list_single(struct dnode *dn) | |||
800 | } | 770 | } |
801 | } | 771 | } |
802 | 772 | ||
803 | return (0); | 773 | return column; |
804 | } | 774 | } |
805 | 775 | ||
806 | /*----------------------------------------------------------------------*/ | 776 | /*----------------------------------------------------------------------*/ |
@@ -830,8 +800,6 @@ extern int ls_main(int argc, char **argv) | |||
830 | #endif | 800 | #endif |
831 | #ifdef CONFIG_FEATURE_AUTOWIDTH | 801 | #ifdef CONFIG_FEATURE_AUTOWIDTH |
832 | ioctl(fileno(stdout), TIOCGWINSZ, &win); | 802 | ioctl(fileno(stdout), TIOCGWINSZ, &win); |
833 | if (win.ws_row > 4) | ||
834 | column_width = win.ws_row - 2; | ||
835 | if (win.ws_col > 0) | 803 | if (win.ws_col > 0) |
836 | terminal_width = win.ws_col - 1; | 804 | terminal_width = win.ws_col - 1; |
837 | #endif | 805 | #endif |
@@ -1025,10 +993,10 @@ extern int ls_main(int argc, char **argv) | |||
1025 | /* stuff the command line file names into an dnode array */ | 993 | /* stuff the command line file names into an dnode array */ |
1026 | dn = NULL; | 994 | dn = NULL; |
1027 | for (oi = 0; oi < ac; oi++) { | 995 | for (oi = 0; oi < ac; oi++) { |
1028 | cur = (struct dnode *) xmalloc(sizeof(struct dnode)); | 996 | char *fullname = xstrdup(av[oi]); |
1029 | cur->fullname = xstrdup(av[oi]); | 997 | |
1030 | cur->name = cur->fullname; | 998 | cur = my_stat(fullname, fullname); |
1031 | if (my_stat(cur)) | 999 | if (!cur) |
1032 | continue; | 1000 | continue; |
1033 | cur->next = dn; | 1001 | cur->next = dn; |
1034 | dn = cur; | 1002 | dn = cur; |
diff --git a/shell/cmdedit.c b/shell/cmdedit.c index da2b017e1..2ea61614d 100644 --- a/shell/cmdedit.c +++ b/shell/cmdedit.c | |||
@@ -951,6 +951,44 @@ static int find_match(char *matchBuf, int *len_with_quotes) | |||
951 | return command_mode; | 951 | return command_mode; |
952 | } | 952 | } |
953 | 953 | ||
954 | /* | ||
955 | display by column original ideas from ls applet, | ||
956 | very optimize by my :) | ||
957 | */ | ||
958 | static void showfiles(char **matches, int nfiles) | ||
959 | { | ||
960 | int ncols, row; | ||
961 | int column_width = 0; | ||
962 | int nrows = nfiles; | ||
963 | |||
964 | /* find the longest file name- use that as the column width */ | ||
965 | for (row = 0; row < nrows; row++) { | ||
966 | int l = strlen(matches[row]); | ||
967 | |||
968 | if (column_width < l) | ||
969 | column_width = l; | ||
970 | } | ||
971 | column_width += 2; /* min space for columns */ | ||
972 | ncols = cmdedit_termw / column_width; | ||
973 | |||
974 | if (ncols > 1) { | ||
975 | nrows /= ncols; | ||
976 | if(nfiles % ncols) | ||
977 | nrows++; /* round up fractionals */ | ||
978 | column_width = -column_width; /* for printf("%-Ns", ...); */ | ||
979 | } else { | ||
980 | ncols = 1; | ||
981 | } | ||
982 | for (row = 0; row < nrows; row++) { | ||
983 | int n = row; | ||
984 | int nc; | ||
985 | |||
986 | for(nc = 1; nc < ncols && n+nrows < nfiles; n += nrows, nc++) | ||
987 | printf("%*s", column_width, matches[n]); | ||
988 | printf("%s\n", matches[n]); | ||
989 | } | ||
990 | } | ||
991 | |||
954 | 992 | ||
955 | static void input_tab(int *lastWasTab) | 993 | static void input_tab(int *lastWasTab) |
956 | { | 994 | { |
@@ -1078,29 +1116,11 @@ static void input_tab(int *lastWasTab) | |||
1078 | * just hit TAB again, print a list of all the | 1116 | * just hit TAB again, print a list of all the |
1079 | * available choices... */ | 1117 | * available choices... */ |
1080 | if (matches && num_matches > 0) { | 1118 | if (matches && num_matches > 0) { |
1081 | int i, col, l; | ||
1082 | int sav_cursor = cursor; /* change goto_new_line() */ | 1119 | int sav_cursor = cursor; /* change goto_new_line() */ |
1083 | 1120 | ||
1084 | /* Go to the next line */ | 1121 | /* Go to the next line */ |
1085 | goto_new_line(); | 1122 | goto_new_line(); |
1086 | for (i = 0, col = 0; i < num_matches; i++) { | 1123 | showfiles(matches, num_matches); |
1087 | l = strlen(matches[i]); | ||
1088 | if (l < 14) | ||
1089 | l = 14; | ||
1090 | printf("%-14s ", matches[i]); | ||
1091 | col+=l; | ||
1092 | if ((l += 2) > 16) | ||
1093 | while (l % 16) { | ||
1094 | putchar(' '); | ||
1095 | l++; | ||
1096 | } | ||
1097 | if (col > (cmdedit_termw-l-l) && matches[i + 1] != NULL) { | ||
1098 | putchar('\n'); | ||
1099 | col = 0; | ||
1100 | } | ||
1101 | } | ||
1102 | /* Go to the next line and rewrite */ | ||
1103 | putchar('\n'); | ||
1104 | redraw(0, len - sav_cursor); | 1124 | redraw(0, len - sav_cursor); |
1105 | } | 1125 | } |
1106 | } | 1126 | } |