sh.file.c (131962) | sh.file.c (145479) |
---|---|
1/* $Header: /src/pub/tcsh/sh.file.c,v 3.23 2003/02/08 20:03:26 christos Exp $ */ | 1/* $Header: /src/pub/tcsh/sh.file.c,v 3.28 2005/01/05 16:06:13 christos Exp $ */ |
2/* 3 * sh.file.c: File completion for csh. This file is not used in tcsh. 4 */ 5/*- 6 * Copyright (c) 1980, 1991 The Regents of the University of California. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without --- 18 unchanged lines hidden (view full) --- 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33#include "sh.h" 34#include "ed.h" 35 | 2/* 3 * sh.file.c: File completion for csh. This file is not used in tcsh. 4 */ 5/*- 6 * Copyright (c) 1980, 1991 The Regents of the University of California. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without --- 18 unchanged lines hidden (view full) --- 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33#include "sh.h" 34#include "ed.h" 35 |
36RCSID("$Id: sh.file.c,v 3.23 2003/02/08 20:03:26 christos Exp $") | 36RCSID("$Id: sh.file.c,v 3.28 2005/01/05 16:06:13 christos Exp $") |
37 38#if defined(FILEC) && defined(TIOCSTI) 39 40/* 41 * Tenex style file name recognition, .. and more. 42 * History: 43 * Author: Ken Greer, Sept. 1975, CMU. 44 * Finally got around to adding to the Cshell., Ken Greer, Dec. 1981. --- 14 unchanged lines hidden (view full) --- 59 LIST, RECOGNIZE 60} COMMAND; 61 62static void setup_tty __P((int)); 63static void back_to_col_1 __P((void)); 64static void pushback __P((Char *)); 65static void catn __P((Char *, Char *, int)); 66static void copyn __P((Char *, Char *, int)); | 37 38#if defined(FILEC) && defined(TIOCSTI) 39 40/* 41 * Tenex style file name recognition, .. and more. 42 * History: 43 * Author: Ken Greer, Sept. 1975, CMU. 44 * Finally got around to adding to the Cshell., Ken Greer, Dec. 1981. --- 14 unchanged lines hidden (view full) --- 59 LIST, RECOGNIZE 60} COMMAND; 61 62static void setup_tty __P((int)); 63static void back_to_col_1 __P((void)); 64static void pushback __P((Char *)); 65static void catn __P((Char *, Char *, int)); 66static void copyn __P((Char *, Char *, int)); |
67static Char filetype __P((Char *, Char *)); 68static void print_by_column __P((Char *, Char *[], int)); | 67static int filetype __P((Char *, Char *)); 68static void print_by_column __P((Char *, Char *[], size_t)); |
69static Char *tilde __P((Char *, Char *)); 70static void retype __P((void)); 71static void beep __P((void)); 72static void print_recognized_stuff __P((Char *)); 73static void extract_dir_and_name __P((Char *, Char *, Char *)); 74static Char *getitem __P((DIR *, int)); 75static void free_items __P((Char **, size_t)); 76static int tsearch __P((Char *, COMMAND, int)); 77static int compare __P((const ptr_t, const ptr_t)); | 69static Char *tilde __P((Char *, Char *)); 70static void retype __P((void)); 71static void beep __P((void)); 72static void print_recognized_stuff __P((Char *)); 73static void extract_dir_and_name __P((Char *, Char *, Char *)); 74static Char *getitem __P((DIR *, int)); 75static void free_items __P((Char **, size_t)); 76static int tsearch __P((Char *, COMMAND, int)); 77static int compare __P((const ptr_t, const ptr_t)); |
78static int recognize __P((Char *, Char *, int, int)); | 78static int recognize __P((Char *, Char *, int, size_t)); |
79static int is_prefix __P((Char *, Char *)); 80static int is_suffix __P((Char *, Char *)); 81static int ignored __P((Char *)); 82 83 84/* 85 * Put this here so the binary can be patched with adb to enable file 86 * completion by default. Filec controls completion, nobeep controls 87 * ringing the terminal bell on incomplete expansions. 88 */ | 79static int is_prefix __P((Char *, Char *)); 80static int is_suffix __P((Char *, Char *)); 81static int ignored __P((Char *)); 82 83 84/* 85 * Put this here so the binary can be patched with adb to enable file 86 * completion by default. Filec controls completion, nobeep controls 87 * ringing the terminal bell on incomplete expansions. 88 */ |
89bool filec = 0; | 89int filec = 0; |
90 91static void 92setup_tty(on) 93 int on; 94{ 95#ifdef TERMIO 96# ifdef POSIX 97 struct termios tchars; --- 123 unchanged lines hidden (view full) --- 221/* 222 * Push string contents back into tty queue 223 */ 224static void 225pushback(string) 226 Char *string; 227{ 228 Char *p; | 90 91static void 92setup_tty(on) 93 int on; 94{ 95#ifdef TERMIO 96# ifdef POSIX 97 struct termios tchars; --- 123 unchanged lines hidden (view full) --- 221/* 222 * Push string contents back into tty queue 223 */ 224static void 225pushback(string) 226 Char *string; 227{ 228 Char *p; |
229 char c; | |
230#ifdef TERMIO 231# ifdef POSIX 232 struct termios tty, tty_normal; 233# else 234 struct termio tty, tty_normal; 235# endif /* POSIX */ 236#else 237 struct sgttyb tty, tty_normal; --- 14 unchanged lines hidden (view full) --- 252 tty_normal = tty; 253 tty.c_lflag &= ~(ECHOKE | ECHO | ECHOE | ECHOK | ECHONL | ECHOPRT | ECHOCTL); 254# ifdef POSIX 255 (void) tcsetattr(SHOUT, TCSANOW, &tty); 256# else 257 (void) ioctl(SHOUT, TCSETAW, (ioctl_t) &tty); 258# endif /* POSIX */ 259 | 229#ifdef TERMIO 230# ifdef POSIX 231 struct termios tty, tty_normal; 232# else 233 struct termio tty, tty_normal; 234# endif /* POSIX */ 235#else 236 struct sgttyb tty, tty_normal; --- 14 unchanged lines hidden (view full) --- 251 tty_normal = tty; 252 tty.c_lflag &= ~(ECHOKE | ECHO | ECHOE | ECHOK | ECHONL | ECHOPRT | ECHOCTL); 253# ifdef POSIX 254 (void) tcsetattr(SHOUT, TCSANOW, &tty); 255# else 256 (void) ioctl(SHOUT, TCSETAW, (ioctl_t) &tty); 257# endif /* POSIX */ 258 |
260 for (p = string; (c = *p) != '\0'; p++) 261 (void) ioctl(SHOUT, TIOCSTI, (ioctl_t) & c); | 259 for (p = string; *p != '\0'; p++) { 260 char buf[MB_LEN_MAX]; 261 size_t i, len; 262 263 len = one_wctomb(buf, *p & CHAR); 264 for (i = 0; i < len; i++) 265 (void) ioctl(SHOUT, TIOCSTI, (ioctl_t) &buf[i]); 266 } |
262# ifdef POSIX 263 (void) tcsetattr(SHOUT, TCSANOW, &tty_normal); 264# else 265 (void) ioctl(SHOUT, TCSETAW, (ioctl_t) &tty_normal); 266# endif /* POSIX */ 267#else 268 (void) ioctl(SHOUT, TIOCGETP, (ioctl_t) & tty); 269 tty_normal = tty; --- 40 unchanged lines hidden (view full) --- 310 int count; 311{ 312 while (--count >= 0) 313 if ((*des++ = *src++) == 0) 314 return; 315 *des = '\0'; 316} 317 | 267# ifdef POSIX 268 (void) tcsetattr(SHOUT, TCSANOW, &tty_normal); 269# else 270 (void) ioctl(SHOUT, TCSETAW, (ioctl_t) &tty_normal); 271# endif /* POSIX */ 272#else 273 (void) ioctl(SHOUT, TIOCGETP, (ioctl_t) & tty); 274 tty_normal = tty; --- 40 unchanged lines hidden (view full) --- 315 int count; 316{ 317 while (--count >= 0) 318 if ((*des++ = *src++) == 0) 319 return; 320 *des = '\0'; 321} 322 |
318static Char | 323static int |
319filetype(dir, file) 320 Char *dir, *file; 321{ 322 Char path[MAXPATHLEN]; 323 struct stat statb; 324 325 catn(Strcpy(path, dir), file, sizeof(path) / sizeof(Char)); 326 if (lstat(short2str(path), &statb) == 0) { --- 22 unchanged lines hidden (view full) --- 349static struct winsize win; 350 351/* 352 * Print sorted down columns 353 */ 354static void 355print_by_column(dir, items, count) 356 Char *dir, *items[]; | 324filetype(dir, file) 325 Char *dir, *file; 326{ 327 Char path[MAXPATHLEN]; 328 struct stat statb; 329 330 catn(Strcpy(path, dir), file, sizeof(path) / sizeof(Char)); 331 if (lstat(short2str(path), &statb) == 0) { --- 22 unchanged lines hidden (view full) --- 354static struct winsize win; 355 356/* 357 * Print sorted down columns 358 */ 359static void 360print_by_column(dir, items, count) 361 Char *dir, *items[]; |
357 int count; | 362 size_t count; |
358{ | 363{ |
359 int i, rows, r, c, maxwidth = 0, columns; | 364 size_t i; 365 int rows, r, c, maxwidth = 0, columns; |
360 361 if (ioctl(SHOUT, TIOCGWINSZ, (ioctl_t) & win) < 0 || win.ws_col == 0) 362 win.ws_col = 80; 363 for (i = 0; i < count; i++) 364 maxwidth = maxwidth > (r = Strlen(items[i])) ? maxwidth : r; 365 maxwidth += 2; /* for the file tag and space */ 366 columns = win.ws_col / maxwidth; 367 if (columns == 0) --- 143 unchanged lines hidden (view full) --- 511 copyn(name, path, MAXNAMLEN); 512 dir[0] = '\0'; 513 } 514 else { 515 copyn(name, ++p, MAXNAMLEN); 516 copyn(dir, path, p - path); 517 } 518} | 366 367 if (ioctl(SHOUT, TIOCGWINSZ, (ioctl_t) & win) < 0 || win.ws_col == 0) 368 win.ws_col = 80; 369 for (i = 0; i < count; i++) 370 maxwidth = maxwidth > (r = Strlen(items[i])) ? maxwidth : r; 371 maxwidth += 2; /* for the file tag and space */ 372 columns = win.ws_col / maxwidth; 373 if (columns == 0) --- 143 unchanged lines hidden (view full) --- 517 copyn(name, path, MAXNAMLEN); 518 dir[0] = '\0'; 519 } 520 else { 521 copyn(name, ++p, MAXNAMLEN); 522 copyn(dir, path, p - path); 523 } 524} |
519/* atp vmsposix - I need to remove all the setpwent 520 * getpwent endpwent stuff. VMS_POSIX has getpwnam getpwuid 521 * and getlogin. This needs fixing. (There is no access to 522 * pw->passwd in VMS - a secure system benefit :-| ) 523 */ | 525 |
524static Char * 525getitem(dir_fd, looking_for_lognames) 526 DIR *dir_fd; 527 int looking_for_lognames; 528{ 529 struct passwd *pw; 530 struct dirent *dirp; 531 532 if (looking_for_lognames) { | 526static Char * 527getitem(dir_fd, looking_for_lognames) 528 DIR *dir_fd; 529 int looking_for_lognames; 530{ 531 struct passwd *pw; 532 struct dirent *dirp; 533 534 if (looking_for_lognames) { |
533#ifdef _VMS_POSIX | 535#ifndef HAVE_GETPWENT |
534 return (NULL); 535#else 536 if ((pw = getpwent()) == NULL) 537 return (NULL); 538 return (str2short(pw->pw_name)); 539#endif /* atp vmsposix */ 540 } 541 if ((dirp = readdir(dir_fd)) != NULL) --- 34 unchanged lines hidden (view full) --- 576 */ 577static int 578tsearch(word, command, max_word_length) 579 Char *word; 580 int max_word_length; 581 COMMAND command; 582{ 583 DIR *dir_fd; | 536 return (NULL); 537#else 538 if ((pw = getpwent()) == NULL) 539 return (NULL); 540 return (str2short(pw->pw_name)); 541#endif /* atp vmsposix */ 542 } 543 if ((dirp = readdir(dir_fd)) != NULL) --- 34 unchanged lines hidden (view full) --- 578 */ 579static int 580tsearch(word, command, max_word_length) 581 Char *word; 582 int max_word_length; 583 COMMAND command; 584{ 585 DIR *dir_fd; |
584 int numitems = 0, ignoring = TRUE, nignored = 0; | 586 int ignoring = TRUE, nignored = 0; |
585 int name_length, looking_for_lognames; 586 Char tilded_dir[MAXPATHLEN + 1], dir[MAXPATHLEN + 1]; 587 Char name[MAXNAMLEN + 1], extended_name[MAXNAMLEN + 1]; 588 Char *item; 589 Char **items = NULL; | 587 int name_length, looking_for_lognames; 588 Char tilded_dir[MAXPATHLEN + 1], dir[MAXPATHLEN + 1]; 589 Char name[MAXNAMLEN + 1], extended_name[MAXNAMLEN + 1]; 590 Char *item; 591 Char **items = NULL; |
590 size_t maxitems = 0; | 592 size_t numitems = 0, maxitems = 0; |
591 592 looking_for_lognames = (*word == '~') && (Strchr(word, '/') == NULL); 593 if (looking_for_lognames) { | 593 594 looking_for_lognames = (*word == '~') && (Strchr(word, '/') == NULL); 595 if (looking_for_lognames) { |
594#ifndef _VMS_POSIX | 596#ifdef HAVE_GETPWENT |
595 (void) setpwent(); | 597 (void) setpwent(); |
596#endif /*atp vmsposix */ | 598#endif |
597 copyn(name, &word[1], MAXNAMLEN); /* name sans ~ */ 598 dir_fd = NULL; 599 } 600 else { 601 extract_dir_and_name(word, dir, name); 602 if (tilde(tilded_dir, dir) == 0) 603 return (0); 604 dir_fd = opendir(*tilded_dir ? short2str(tilded_dir) : "."); --- 31 unchanged lines hidden (view full) --- 636 else if (recognize(extended_name, 637 item, name_length, ++numitems)) 638 break; 639 } 640 } 641 if (ignoring && numitems == 0 && nignored > 0) { 642 ignoring = FALSE; 643 nignored = 0; | 599 copyn(name, &word[1], MAXNAMLEN); /* name sans ~ */ 600 dir_fd = NULL; 601 } 602 else { 603 extract_dir_and_name(word, dir, name); 604 if (tilde(tilded_dir, dir) == 0) 605 return (0); 606 dir_fd = opendir(*tilded_dir ? short2str(tilded_dir) : "."); --- 31 unchanged lines hidden (view full) --- 638 else if (recognize(extended_name, 639 item, name_length, ++numitems)) 640 break; 641 } 642 } 643 if (ignoring && numitems == 0 && nignored > 0) { 644 ignoring = FALSE; 645 nignored = 0; |
644 if (looking_for_lognames) 645#ifndef _VMS_POSIX | 646 if (looking_for_lognames) { 647#ifdef HAVE_GETPWENT |
646 (void) setpwent(); 647#endif /* atp vmsposix */ | 648 (void) setpwent(); 649#endif /* atp vmsposix */ |
648 else | 650 } else |
649 rewinddir(dir_fd); 650 goto again; 651 } 652 | 651 rewinddir(dir_fd); 652 goto again; 653 } 654 |
653 if (looking_for_lognames) 654#ifndef _VMS_POSIX | 655 if (looking_for_lognames) { 656#ifndef HAVE_GETPWENT |
655 (void) endpwent(); | 657 (void) endpwent(); |
656#endif /*atp vmsposix */ 657 else | 658#endif 659 } else |
658 (void) closedir(dir_fd); 659 if (numitems == 0) 660 return (0); 661 if (command == RECOGNIZE) { 662 if (looking_for_lognames) 663 copyn(word, STRtilde, 1); 664 else 665 /* put back dir part */ 666 copyn(word, dir, max_word_length); 667 /* add extended name */ 668 catn(word, extended_name, max_word_length); 669 return (numitems); 670 } 671 else { /* LIST */ | 660 (void) closedir(dir_fd); 661 if (numitems == 0) 662 return (0); 663 if (command == RECOGNIZE) { 664 if (looking_for_lognames) 665 copyn(word, STRtilde, 1); 666 else 667 /* put back dir part */ 668 copyn(word, dir, max_word_length); 669 /* add extended name */ 670 catn(word, extended_name, max_word_length); 671 return (numitems); 672 } 673 else { /* LIST */ |
672 qsort((ptr_t) items, (size_t) numitems, sizeof(items[0]), | 674 qsort((ptr_t) items, numitems, sizeof(items[0]), |
673 (int (*) __P((const void *, const void *))) compare); 674 print_by_column(looking_for_lognames ? NULL : tilded_dir, 675 items, numitems); 676 if (items != NULL) 677 FREE_ITEMS(items, numitems); 678 } 679 return (0); 680} 681 682 683static int 684compare(p, q) 685 const ptr_t p, q; 686{ | 675 (int (*) __P((const void *, const void *))) compare); 676 print_by_column(looking_for_lognames ? NULL : tilded_dir, 677 items, numitems); 678 if (items != NULL) 679 FREE_ITEMS(items, numitems); 680 } 681 return (0); 682} 683 684 685static int 686compare(p, q) 687 const ptr_t p, q; 688{ |
687#if defined(NLS) && !defined(NOSTRCOLL) 688 errno = 0; /* strcoll sets errno, another brain-damage */ 689 690 return (strcoll(*(char **) p, *(char **) q)); | 689#ifdef WIDE_STRINGS 690 errno = 0; 691 692 return (wcscoll(*(Char **) p, *(Char **) q)); |
691#else | 693#else |
692 return (strcmp(*(char **) p, *(char **) q)); 693#endif /* NLS && !NOSTRCOLL */ | 694 char *p1, *q1; 695 int res; 696 697 p1 = strsave(short2str(*(Char **) p)); 698 q1 = strsave(short2str(*(Char **) q)); 699# if defined(NLS) && !defined(NOSTRCOLL) 700 errno = 0; /* strcoll sets errno, another brain-damage */ 701 res = strcoll(p1, q1); 702# else 703 res = strcmp(p1, q1); 704# endif /* NLS && !NOSTRCOLL */ 705 xfree (p1); 706 xfree (q1); 707 return res; 708#endif /* not WIDE_STRINGS */ |
694} 695 696/* 697 * Object: extend what user typed up to an ambiguity. 698 * Algorithm: 699 * On first match, copy full item (assume it'll be the only match) 700 * On subsequent matches, shorten extended_name to the first 701 * Character mismatch between extended_name and item. 702 * If we shorten it back to the prefix length, stop searching. 703 */ 704static int 705recognize(extended_name, item, name_length, numitems) 706 Char *extended_name, *item; | 709} 710 711/* 712 * Object: extend what user typed up to an ambiguity. 713 * Algorithm: 714 * On first match, copy full item (assume it'll be the only match) 715 * On subsequent matches, shorten extended_name to the first 716 * Character mismatch between extended_name and item. 717 * If we shorten it back to the prefix length, stop searching. 718 */ 719static int 720recognize(extended_name, item, name_length, numitems) 721 Char *extended_name, *item; |
707 int name_length, numitems; | 722 int name_length; 723 size_t numitems; |
708{ 709 if (numitems == 1) /* 1st match */ 710 copyn(extended_name, item, MAXNAMLEN); 711 else { /* 2nd & subsequent matches */ 712 Char *x, *ent; 713 int len = 0; 714 715 x = extended_name; --- 42 unchanged lines hidden (view full) --- 758} 759 760int 761tenex(inputline, inputline_size) 762 Char *inputline; 763 int inputline_size; 764{ 765 int numitems, num_read; | 724{ 725 if (numitems == 1) /* 1st match */ 726 copyn(extended_name, item, MAXNAMLEN); 727 else { /* 2nd & subsequent matches */ 728 Char *x, *ent; 729 int len = 0; 730 731 x = extended_name; --- 42 unchanged lines hidden (view full) --- 774} 775 776int 777tenex(inputline, inputline_size) 778 Char *inputline; 779 int inputline_size; 780{ 781 int numitems, num_read; |
766 char tinputline[BUFSIZE]; | 782 char tinputline[BUFSIZE + 1]; |
767 768 769 setup_tty(ON); 770 771 while ((num_read = read(SHIN, tinputline, BUFSIZE)) > 0) { | 783 784 785 setup_tty(ON); 786 787 while ((num_read = read(SHIN, tinputline, BUFSIZE)) > 0) { |
772 int i; | |
773 static Char delims[] = {' ', '\'', '"', '\t', ';', '&', '<', 774 '>', '(', ')', '|', '^', '%', '\0'}; 775 Char *str_end, *word_start, last_Char, should_retype; 776 int space_left; 777 COMMAND command; 778 | 788 static Char delims[] = {' ', '\'', '"', '\t', ';', '&', '<', 789 '>', '(', ')', '|', '^', '%', '\0'}; 790 Char *str_end, *word_start, last_Char, should_retype; 791 int space_left; 792 COMMAND command; 793 |
779 for (i = 0; i < num_read; i++) 780 inputline[i] = (unsigned char) tinputline[i]; | 794 tinputline[num_read] = 0; 795 Strcpy(inputline, str2short(tinputline)); 796 num_read = Strlen(inputline); |
781 last_Char = inputline[num_read - 1] & ASCII; 782 783 if (last_Char == '\n' || num_read == inputline_size) 784 break; 785 command = (last_Char == ESC) ? RECOGNIZE : LIST; 786 if (command == LIST) 787 xputchar('\n'); 788 str_end = &inputline[num_read]; --- 57 unchanged lines hidden --- | 797 last_Char = inputline[num_read - 1] & ASCII; 798 799 if (last_Char == '\n' || num_read == inputline_size) 800 break; 801 command = (last_Char == ESC) ? RECOGNIZE : LIST; 802 if (command == LIST) 803 xputchar('\n'); 804 str_end = &inputline[num_read]; --- 57 unchanged lines hidden --- |