17c478bd9Sstevel@tonic-gate /*
26c02b4a4Smuffin * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
37c478bd9Sstevel@tonic-gate * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate */
57c478bd9Sstevel@tonic-gate
67c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
77c478bd9Sstevel@tonic-gate /* All Rights Reserved */
87c478bd9Sstevel@tonic-gate
97c478bd9Sstevel@tonic-gate /*
107c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California.
117c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley Software License Agreement
127c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution.
137c478bd9Sstevel@tonic-gate */
147c478bd9Sstevel@tonic-gate
157c478bd9Sstevel@tonic-gate #ifdef FILEC
167c478bd9Sstevel@tonic-gate /*
177c478bd9Sstevel@tonic-gate * Tenex style file name recognition, .. and more.
187c478bd9Sstevel@tonic-gate * History:
197c478bd9Sstevel@tonic-gate * Author: Ken Greer, Sept. 1975, CMU.
207c478bd9Sstevel@tonic-gate * Finally got around to adding to the Cshell., Ken Greer, Dec. 1981.
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate
237c478bd9Sstevel@tonic-gate #include "sh.h"
247c478bd9Sstevel@tonic-gate #include <sys/types.h>
257c478bd9Sstevel@tonic-gate #include <dirent.h>
267c478bd9Sstevel@tonic-gate #include <pwd.h>
277c478bd9Sstevel@tonic-gate #include "sh.tconst.h"
287c478bd9Sstevel@tonic-gate
29*65b0c20eSnakanon #define TRUE 1
30*65b0c20eSnakanon #define FALSE 0
31*65b0c20eSnakanon #define ON 1
32*65b0c20eSnakanon #define OFF 0
337c478bd9Sstevel@tonic-gate
34*65b0c20eSnakanon #define ESC '\033'
357c478bd9Sstevel@tonic-gate
366c02b4a4Smuffin extern DIR *opendir_(tchar *);
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate static char *BELL = "\07";
397c478bd9Sstevel@tonic-gate static char *CTRLR = "^R\n";
407c478bd9Sstevel@tonic-gate
417c478bd9Sstevel@tonic-gate typedef enum {LIST, RECOGNIZE} COMMAND;
427c478bd9Sstevel@tonic-gate
437c478bd9Sstevel@tonic-gate static jmp_buf osetexit; /* saved setexit() state */
447c478bd9Sstevel@tonic-gate static struct termios tty_save; /* saved terminal state */
457c478bd9Sstevel@tonic-gate static struct termios tty_new; /* new terminal state */
467c478bd9Sstevel@tonic-gate
476c02b4a4Smuffin static int is_prefix(tchar *, tchar *);
486c02b4a4Smuffin static int is_suffix(tchar *, tchar *);
496c02b4a4Smuffin static int ignored(tchar *);
506c02b4a4Smuffin
517c478bd9Sstevel@tonic-gate /*
527c478bd9Sstevel@tonic-gate * Put this here so the binary can be patched with adb to enable file
537c478bd9Sstevel@tonic-gate * completion by default. Filec controls completion, nobeep controls
547c478bd9Sstevel@tonic-gate * ringing the terminal bell on incomplete expansions.
557c478bd9Sstevel@tonic-gate */
567c478bd9Sstevel@tonic-gate bool filec = 0;
577c478bd9Sstevel@tonic-gate
586c02b4a4Smuffin static void
setup_tty(int on)596c02b4a4Smuffin setup_tty(int on)
607c478bd9Sstevel@tonic-gate {
617c478bd9Sstevel@tonic-gate int omask;
627c478bd9Sstevel@tonic-gate #ifdef TRACE
637c478bd9Sstevel@tonic-gate tprintf("TRACE- setup_tty()\n");
647c478bd9Sstevel@tonic-gate #endif
657c478bd9Sstevel@tonic-gate
667c478bd9Sstevel@tonic-gate omask = sigblock(sigmask(SIGINT));
677c478bd9Sstevel@tonic-gate if (on) {
687c478bd9Sstevel@tonic-gate /*
697c478bd9Sstevel@tonic-gate * The shell makes sure that the tty is not in some weird state
707c478bd9Sstevel@tonic-gate * and fixes it if it is. But it should be noted that the
717c478bd9Sstevel@tonic-gate * tenex routine will not work correctly in CBREAK or RAW mode
727c478bd9Sstevel@tonic-gate * so this code below is, therefore, mandatory.
737c478bd9Sstevel@tonic-gate *
747c478bd9Sstevel@tonic-gate * Also, in order to recognize the ESC (filename-completion)
757c478bd9Sstevel@tonic-gate * character, set EOL to ESC. This way, ESC will terminate
767c478bd9Sstevel@tonic-gate * the line, but still be in the input stream.
777c478bd9Sstevel@tonic-gate * EOT (filename list) will also terminate the line,
787c478bd9Sstevel@tonic-gate * but will not appear in the input stream.
797c478bd9Sstevel@tonic-gate *
807c478bd9Sstevel@tonic-gate * The getexit/setexit contortions ensure that the
817c478bd9Sstevel@tonic-gate * tty state will be restored if the user types ^C.
827c478bd9Sstevel@tonic-gate */
837c478bd9Sstevel@tonic-gate (void) ioctl(SHIN, TCGETS, (char *)&tty_save);
847c478bd9Sstevel@tonic-gate getexit(osetexit);
857c478bd9Sstevel@tonic-gate if (setjmp(reslab)) {
867c478bd9Sstevel@tonic-gate (void) ioctl(SHIN, TCSETSW, (char *)&tty_save);
877c478bd9Sstevel@tonic-gate resexit(osetexit);
887c478bd9Sstevel@tonic-gate reset();
897c478bd9Sstevel@tonic-gate }
907c478bd9Sstevel@tonic-gate tty_new = tty_save;
917c478bd9Sstevel@tonic-gate tty_new.c_cc[VEOL] = ESC;
927c478bd9Sstevel@tonic-gate tty_new.c_iflag |= IMAXBEL | BRKINT | IGNPAR;
937c478bd9Sstevel@tonic-gate tty_new.c_lflag |= ICANON;
947c478bd9Sstevel@tonic-gate tty_new.c_lflag |= ECHOCTL;
957c478bd9Sstevel@tonic-gate tty_new.c_oflag &= ~OCRNL;
967c478bd9Sstevel@tonic-gate (void) ioctl(SHIN, TCSETSW, (char *)&tty_new);
977c478bd9Sstevel@tonic-gate } else {
987c478bd9Sstevel@tonic-gate /*
997c478bd9Sstevel@tonic-gate * Reset terminal state to what user had when invoked
1007c478bd9Sstevel@tonic-gate */
1017c478bd9Sstevel@tonic-gate (void) ioctl(SHIN, TCSETSW, (char *)&tty_save);
1027c478bd9Sstevel@tonic-gate resexit(osetexit);
1037c478bd9Sstevel@tonic-gate }
1047c478bd9Sstevel@tonic-gate (void) sigsetmask(omask);
1057c478bd9Sstevel@tonic-gate }
1067c478bd9Sstevel@tonic-gate
1076c02b4a4Smuffin static void
termchars(void)1086c02b4a4Smuffin termchars(void)
1097c478bd9Sstevel@tonic-gate {
1107c478bd9Sstevel@tonic-gate extern char *tgetstr();
1116c02b4a4Smuffin char bp[1024];
1127c478bd9Sstevel@tonic-gate static char area[256];
1137c478bd9Sstevel@tonic-gate static int been_here = 0;
1146c02b4a4Smuffin char *ap = area;
1156c02b4a4Smuffin char *s;
1166c02b4a4Smuffin char *term;
1177c478bd9Sstevel@tonic-gate
1187c478bd9Sstevel@tonic-gate #ifdef TRACE
1197c478bd9Sstevel@tonic-gate tprintf("TRACE- termchars()\n");
1207c478bd9Sstevel@tonic-gate #endif
1217c478bd9Sstevel@tonic-gate if (been_here)
1227c478bd9Sstevel@tonic-gate return;
1237c478bd9Sstevel@tonic-gate been_here = TRUE;
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gate if ((term = getenv("TERM")) == NULL)
1267c478bd9Sstevel@tonic-gate return;
1277c478bd9Sstevel@tonic-gate if (tgetent(bp, term) != 1)
1287c478bd9Sstevel@tonic-gate return;
1297c478bd9Sstevel@tonic-gate if (s = tgetstr("vb", &ap)) /* Visible Bell */
1307c478bd9Sstevel@tonic-gate BELL = s;
1317c478bd9Sstevel@tonic-gate }
1327c478bd9Sstevel@tonic-gate
1337c478bd9Sstevel@tonic-gate /*
1347c478bd9Sstevel@tonic-gate * Move back to beginning of current line
1357c478bd9Sstevel@tonic-gate */
1366c02b4a4Smuffin static void
back_to_col_1(void)1376c02b4a4Smuffin back_to_col_1(void)
1387c478bd9Sstevel@tonic-gate {
1397c478bd9Sstevel@tonic-gate int omask;
1407c478bd9Sstevel@tonic-gate
1417c478bd9Sstevel@tonic-gate #ifdef TRACE
1427c478bd9Sstevel@tonic-gate tprintf("TRACE- back_to_col_1()\n");
1437c478bd9Sstevel@tonic-gate #endif
1447c478bd9Sstevel@tonic-gate omask = sigblock(sigmask(SIGINT));
1457c478bd9Sstevel@tonic-gate (void) write(SHOUT, "\r", 1);
1467c478bd9Sstevel@tonic-gate (void) sigsetmask(omask);
1477c478bd9Sstevel@tonic-gate }
1487c478bd9Sstevel@tonic-gate
1497c478bd9Sstevel@tonic-gate /*
1507c478bd9Sstevel@tonic-gate * Push string contents back into tty queue
1517c478bd9Sstevel@tonic-gate */
1526c02b4a4Smuffin static void
pushback(tchar * string,int echoflag)1536c02b4a4Smuffin pushback(tchar *string, int echoflag)
1547c478bd9Sstevel@tonic-gate {
1556c02b4a4Smuffin tchar *p;
1567c478bd9Sstevel@tonic-gate struct termios tty;
157*65b0c20eSnakanon int omask, retry = 0;
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate #ifdef TRACE
1607c478bd9Sstevel@tonic-gate tprintf("TRACE- pushback()\n");
1617c478bd9Sstevel@tonic-gate #endif
1627c478bd9Sstevel@tonic-gate omask = sigblock(sigmask(SIGINT));
1637c478bd9Sstevel@tonic-gate tty = tty_new;
1647c478bd9Sstevel@tonic-gate if (!echoflag)
1657c478bd9Sstevel@tonic-gate tty.c_lflag &= ~ECHO;
166*65b0c20eSnakanon
167*65b0c20eSnakanon again:
1687c478bd9Sstevel@tonic-gate (void) ioctl(SHIN, TCSETSF, (char *)&tty);
1697c478bd9Sstevel@tonic-gate
170*65b0c20eSnakanon for (p = string; *p; p++) {
1717c478bd9Sstevel@tonic-gate char mbc[MB_LEN_MAX];
1727c478bd9Sstevel@tonic-gate int i, j = wctomb(mbc, (wchar_t)*p);
173*65b0c20eSnakanon
1747c478bd9Sstevel@tonic-gate if (j < 0) {
1757c478bd9Sstevel@tonic-gate /* Error! But else what can we do? */
1767c478bd9Sstevel@tonic-gate continue;
1777c478bd9Sstevel@tonic-gate }
1787c478bd9Sstevel@tonic-gate for (i = 0; i < j; ++i) {
179*65b0c20eSnakanon if (ioctl(SHIN, TIOCSTI, mbc + i) != 0 &&
180*65b0c20eSnakanon errno == EAGAIN) {
181*65b0c20eSnakanon if (retry++ < 5)
182*65b0c20eSnakanon goto again;
183*65b0c20eSnakanon /* probably no worth retrying any more */
184*65b0c20eSnakanon }
1857c478bd9Sstevel@tonic-gate }
1867c478bd9Sstevel@tonic-gate }
1877c478bd9Sstevel@tonic-gate
1887c478bd9Sstevel@tonic-gate if (tty.c_lflag != tty_new.c_lflag)
1897c478bd9Sstevel@tonic-gate (void) ioctl(SHIN, TCSETS, (char *)&tty_new);
1907c478bd9Sstevel@tonic-gate (void) sigsetmask(omask);
1917c478bd9Sstevel@tonic-gate }
1927c478bd9Sstevel@tonic-gate
1937c478bd9Sstevel@tonic-gate /*
1947c478bd9Sstevel@tonic-gate * Concatenate src onto tail of des.
1957c478bd9Sstevel@tonic-gate * Des is a string whose maximum length is count.
1967c478bd9Sstevel@tonic-gate * Always null terminate.
1977c478bd9Sstevel@tonic-gate */
1986c02b4a4Smuffin void
catn(tchar * des,tchar * src,int count)1996c02b4a4Smuffin catn(tchar *des, tchar *src, int count)
2007c478bd9Sstevel@tonic-gate {
2017c478bd9Sstevel@tonic-gate #ifdef TRACE
2027c478bd9Sstevel@tonic-gate tprintf("TRACE- catn()\n");
2037c478bd9Sstevel@tonic-gate #endif
2047c478bd9Sstevel@tonic-gate
2057c478bd9Sstevel@tonic-gate while (--count >= 0 && *des)
2067c478bd9Sstevel@tonic-gate des++;
2077c478bd9Sstevel@tonic-gate while (--count >= 0)
2087c478bd9Sstevel@tonic-gate if ((*des++ = *src++) == '\0')
2097c478bd9Sstevel@tonic-gate return;
2107c478bd9Sstevel@tonic-gate *des = '\0';
2117c478bd9Sstevel@tonic-gate }
2127c478bd9Sstevel@tonic-gate
2136c02b4a4Smuffin static int
max(a,b)2147c478bd9Sstevel@tonic-gate max(a, b)
2157c478bd9Sstevel@tonic-gate {
2167c478bd9Sstevel@tonic-gate
2177c478bd9Sstevel@tonic-gate return (a > b ? a : b);
2187c478bd9Sstevel@tonic-gate }
2197c478bd9Sstevel@tonic-gate
2207c478bd9Sstevel@tonic-gate /*
2217c478bd9Sstevel@tonic-gate * Like strncpy but always leave room for trailing \0
2227c478bd9Sstevel@tonic-gate * and always null terminate.
2237c478bd9Sstevel@tonic-gate */
2246c02b4a4Smuffin void
copyn(tchar * des,tchar * src,int count)2256c02b4a4Smuffin copyn(tchar *des, tchar *src, int count)
2267c478bd9Sstevel@tonic-gate {
2277c478bd9Sstevel@tonic-gate
2287c478bd9Sstevel@tonic-gate #ifdef TRACE
2297c478bd9Sstevel@tonic-gate tprintf("TRACE- copyn()\n");
2307c478bd9Sstevel@tonic-gate #endif
2317c478bd9Sstevel@tonic-gate while (--count >= 0)
2327c478bd9Sstevel@tonic-gate if ((*des++ = *src++) == '\0')
2337c478bd9Sstevel@tonic-gate return;
2347c478bd9Sstevel@tonic-gate *des = '\0';
2357c478bd9Sstevel@tonic-gate }
2367c478bd9Sstevel@tonic-gate
2377c478bd9Sstevel@tonic-gate /*
2387c478bd9Sstevel@tonic-gate * For qsort()
2397c478bd9Sstevel@tonic-gate */
2406c02b4a4Smuffin static int
fcompare(tchar ** file1,tchar ** file2)2416c02b4a4Smuffin fcompare(tchar **file1, tchar **file2)
2427c478bd9Sstevel@tonic-gate {
2437c478bd9Sstevel@tonic-gate
2447c478bd9Sstevel@tonic-gate #ifdef TRACE
2457c478bd9Sstevel@tonic-gate tprintf("TRACE- fcompare()\n");
2467c478bd9Sstevel@tonic-gate #endif
2477c478bd9Sstevel@tonic-gate return (strcoll_(*file1, *file2));
2487c478bd9Sstevel@tonic-gate }
2497c478bd9Sstevel@tonic-gate
2507c478bd9Sstevel@tonic-gate static char
filetype(tchar * dir,tchar * file,int nosym)2516c02b4a4Smuffin filetype(tchar *dir, tchar *file, int nosym)
2527c478bd9Sstevel@tonic-gate {
2537c478bd9Sstevel@tonic-gate tchar path[MAXPATHLEN + 1];
2547c478bd9Sstevel@tonic-gate struct stat statb;
2557c478bd9Sstevel@tonic-gate
2567c478bd9Sstevel@tonic-gate #ifdef TRACE
2577c478bd9Sstevel@tonic-gate tprintf("TRACE- filetype()\n");
2587c478bd9Sstevel@tonic-gate #endif
2597c478bd9Sstevel@tonic-gate if (dir) {
2607c478bd9Sstevel@tonic-gate catn(strcpy_(path, dir), file, MAXPATHLEN);
2617c478bd9Sstevel@tonic-gate if (nosym) {
2627c478bd9Sstevel@tonic-gate if (stat_(path, &statb) < 0)
2637c478bd9Sstevel@tonic-gate return (' ');
2647c478bd9Sstevel@tonic-gate } else {
2657c478bd9Sstevel@tonic-gate if (lstat_(path, &statb) < 0)
2667c478bd9Sstevel@tonic-gate return (' ');
2677c478bd9Sstevel@tonic-gate }
2687c478bd9Sstevel@tonic-gate if ((statb.st_mode & S_IFMT) == S_IFLNK)
2697c478bd9Sstevel@tonic-gate return ('@');
2707c478bd9Sstevel@tonic-gate if ((statb.st_mode & S_IFMT) == S_IFDIR)
2717c478bd9Sstevel@tonic-gate return ('/');
2727c478bd9Sstevel@tonic-gate if (((statb.st_mode & S_IFMT) == S_IFREG) &&
2737c478bd9Sstevel@tonic-gate (statb.st_mode & 011))
2747c478bd9Sstevel@tonic-gate return ('*');
2757c478bd9Sstevel@tonic-gate }
2767c478bd9Sstevel@tonic-gate return (' ');
2777c478bd9Sstevel@tonic-gate }
2787c478bd9Sstevel@tonic-gate
2797c478bd9Sstevel@tonic-gate /*
2807c478bd9Sstevel@tonic-gate * Print sorted down columns
2817c478bd9Sstevel@tonic-gate */
2826c02b4a4Smuffin static void
print_by_column(tchar * dir,tchar * items[],int count,int looking_for_command)2836c02b4a4Smuffin print_by_column(tchar *dir, tchar *items[], int count, int looking_for_command)
2847c478bd9Sstevel@tonic-gate {
2856c02b4a4Smuffin int i, rows, r, c, maxwidth = 0, columns;
2867c478bd9Sstevel@tonic-gate
2877c478bd9Sstevel@tonic-gate #ifdef TRACE
2887c478bd9Sstevel@tonic-gate tprintf("TRACE- print_by_column()\n");
2897c478bd9Sstevel@tonic-gate #endif
2907c478bd9Sstevel@tonic-gate for (i = 0; i < count; i++)
2917c478bd9Sstevel@tonic-gate maxwidth = max(maxwidth, tswidth(items[i]));
2927c478bd9Sstevel@tonic-gate
2937c478bd9Sstevel@tonic-gate /* for the file tag and space */
2947c478bd9Sstevel@tonic-gate maxwidth += looking_for_command ? 1 : 2;
2957c478bd9Sstevel@tonic-gate columns = max(78 / maxwidth, 1);
2967c478bd9Sstevel@tonic-gate rows = (count + (columns - 1)) / columns;
2977c478bd9Sstevel@tonic-gate
2987c478bd9Sstevel@tonic-gate for (r = 0; r < rows; r++) {
2997c478bd9Sstevel@tonic-gate for (c = 0; c < columns; c++) {
3007c478bd9Sstevel@tonic-gate i = c * rows + r;
3017c478bd9Sstevel@tonic-gate if (i < count) {
3026c02b4a4Smuffin int w;
3037c478bd9Sstevel@tonic-gate
3047c478bd9Sstevel@tonic-gate /*
3057c478bd9Sstevel@tonic-gate * Print filename followed by
3067c478bd9Sstevel@tonic-gate * '@' or '/' or '*' or ' '
3077c478bd9Sstevel@tonic-gate */
3087c478bd9Sstevel@tonic-gate printf("%t", items[i]);
3097c478bd9Sstevel@tonic-gate w = tswidth(items[i]);
3107c478bd9Sstevel@tonic-gate if (!looking_for_command) {
3117c478bd9Sstevel@tonic-gate printf("%c",
3127c478bd9Sstevel@tonic-gate (tchar) filetype(dir, items[i], 0));
3137c478bd9Sstevel@tonic-gate w++;
3147c478bd9Sstevel@tonic-gate }
3157c478bd9Sstevel@tonic-gate if (c < columns - 1) /* last column? */
3167c478bd9Sstevel@tonic-gate for (; w < maxwidth; w++)
3177c478bd9Sstevel@tonic-gate printf(" ");
3187c478bd9Sstevel@tonic-gate }
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate printf("\n");
3217c478bd9Sstevel@tonic-gate }
3227c478bd9Sstevel@tonic-gate }
3237c478bd9Sstevel@tonic-gate
3247c478bd9Sstevel@tonic-gate /*
3257c478bd9Sstevel@tonic-gate * Expand file name with possible tilde usage
3267c478bd9Sstevel@tonic-gate * ~person/mumble
3277c478bd9Sstevel@tonic-gate * expands to
3287c478bd9Sstevel@tonic-gate * home_directory_of_person/mumble
3297c478bd9Sstevel@tonic-gate */
3307c478bd9Sstevel@tonic-gate tchar *
tilde(tchar * new,tchar * old)3316c02b4a4Smuffin tilde(tchar *new, tchar *old)
3327c478bd9Sstevel@tonic-gate {
3336c02b4a4Smuffin tchar *o, *p;
3346c02b4a4Smuffin struct passwd *pw;
3357c478bd9Sstevel@tonic-gate static tchar person[40];
3367c478bd9Sstevel@tonic-gate char person_[40]; /* work */
3377c478bd9Sstevel@tonic-gate tchar *pw_dir; /* work */
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate #ifdef TRACE
3407c478bd9Sstevel@tonic-gate tprintf("TRACE- tilde()\n");
3417c478bd9Sstevel@tonic-gate #endif
3427c478bd9Sstevel@tonic-gate if (old[0] != '~')
3437c478bd9Sstevel@tonic-gate return (strcpy_(new, old));
3447c478bd9Sstevel@tonic-gate
3457c478bd9Sstevel@tonic-gate for (p = person, o = &old[1]; *o && *o != '/'; *p++ = *o++)
3467c478bd9Sstevel@tonic-gate ;
3477c478bd9Sstevel@tonic-gate *p = '\0';
3487c478bd9Sstevel@tonic-gate if (person[0] == '\0')
349*65b0c20eSnakanon (void) strcpy_(new, value(S_home /* "home" */));
3507c478bd9Sstevel@tonic-gate else {
351*65b0c20eSnakanon pw = getpwnam(tstostr(person_, person));
3527c478bd9Sstevel@tonic-gate if (pw == NULL)
3537c478bd9Sstevel@tonic-gate return (NULL);
3547c478bd9Sstevel@tonic-gate pw_dir = strtots((tchar *)NULL, pw->pw_dir); /* allocate */
3557c478bd9Sstevel@tonic-gate (void) strcpy_(new, pw_dir);
3567c478bd9Sstevel@tonic-gate xfree(pw_dir); /* free it */
3577c478bd9Sstevel@tonic-gate }
3587c478bd9Sstevel@tonic-gate (void) strcat_(new, o);
3597c478bd9Sstevel@tonic-gate return (new);
3607c478bd9Sstevel@tonic-gate }
3617c478bd9Sstevel@tonic-gate
3627c478bd9Sstevel@tonic-gate /*
3637c478bd9Sstevel@tonic-gate * Cause pending line to be printed
3647c478bd9Sstevel@tonic-gate */
3656c02b4a4Smuffin static void
sim_retype(void)3666c02b4a4Smuffin sim_retype(void)
3677c478bd9Sstevel@tonic-gate {
3687c478bd9Sstevel@tonic-gate #ifdef notdef
3697c478bd9Sstevel@tonic-gate struct termios tty_pending;
370*65b0c20eSnakanon
3717c478bd9Sstevel@tonic-gate #ifdef TRACE
3727c478bd9Sstevel@tonic-gate tprintf("TRACE- sim_retypr()\n");
3737c478bd9Sstevel@tonic-gate #endif
3747c478bd9Sstevel@tonic-gate tty_pending = tty_new;
3757c478bd9Sstevel@tonic-gate tty_pending.c_lflag |= PENDIN;
3767c478bd9Sstevel@tonic-gate
3777c478bd9Sstevel@tonic-gate (void) ioctl(SHIN, TCSETS, (char *)&tty_pending);
3787c478bd9Sstevel@tonic-gate #else
3797c478bd9Sstevel@tonic-gate #ifdef TRACE
3807c478bd9Sstevel@tonic-gate tprintf("TRACE- sim_retype()\n");
3817c478bd9Sstevel@tonic-gate #endif
3827c478bd9Sstevel@tonic-gate (void) write(SHOUT, CTRLR, strlen(CTRLR));
3837c478bd9Sstevel@tonic-gate printprompt();
3847c478bd9Sstevel@tonic-gate #endif
3857c478bd9Sstevel@tonic-gate }
3867c478bd9Sstevel@tonic-gate
3876c02b4a4Smuffin static int
beep_outc(int c)3886c02b4a4Smuffin beep_outc(int c)
3896c02b4a4Smuffin {
3907c478bd9Sstevel@tonic-gate char buf[1];
3917c478bd9Sstevel@tonic-gate
3927c478bd9Sstevel@tonic-gate buf[0] = c;
3937c478bd9Sstevel@tonic-gate
394*65b0c20eSnakanon (void) write(SHOUT, buf, 1);
3957c478bd9Sstevel@tonic-gate
3967c478bd9Sstevel@tonic-gate return 0;
3977c478bd9Sstevel@tonic-gate }
3987c478bd9Sstevel@tonic-gate
3996c02b4a4Smuffin static void
beep(void)4006c02b4a4Smuffin beep(void)
4017c478bd9Sstevel@tonic-gate {
4027c478bd9Sstevel@tonic-gate
4037c478bd9Sstevel@tonic-gate #ifdef TRACE
4047c478bd9Sstevel@tonic-gate tprintf("TRACE- beep()\n");
4057c478bd9Sstevel@tonic-gate #endif
406*65b0c20eSnakanon if (adrof(S_nobeep /* "nobeep" */) == 0)
407*65b0c20eSnakanon (void) tputs(BELL, 0, beep_outc);
4087c478bd9Sstevel@tonic-gate }
4097c478bd9Sstevel@tonic-gate
4107c478bd9Sstevel@tonic-gate /*
4117c478bd9Sstevel@tonic-gate * Erase that silly ^[ and print the recognized part of the string.
4127c478bd9Sstevel@tonic-gate */
4136c02b4a4Smuffin static void
print_recognized_stuff(tchar * recognized_part)4146c02b4a4Smuffin print_recognized_stuff(tchar *recognized_part)
4157c478bd9Sstevel@tonic-gate {
4167c478bd9Sstevel@tonic-gate int unit = didfds ? 1 : SHOUT;
4177c478bd9Sstevel@tonic-gate
4187c478bd9Sstevel@tonic-gate #ifdef TRACE
4197c478bd9Sstevel@tonic-gate tprintf("TRACE- print_recognized_stuff()\n");
4207c478bd9Sstevel@tonic-gate #endif
4217c478bd9Sstevel@tonic-gate
4227c478bd9Sstevel@tonic-gate /*
4237c478bd9Sstevel@tonic-gate * An optimized erasing of that silly ^[
4247c478bd9Sstevel@tonic-gate *
4257c478bd9Sstevel@tonic-gate * One would think that line speeds have become fast enough that this
4267c478bd9Sstevel@tonic-gate * isn't necessary, but it turns out that the visual difference is
4277c478bd9Sstevel@tonic-gate * quite noticeable.
4287c478bd9Sstevel@tonic-gate */
429*65b0c20eSnakanon flush();
4307c478bd9Sstevel@tonic-gate switch (tswidth(recognized_part)) {
4317c478bd9Sstevel@tonic-gate case 0:
4327c478bd9Sstevel@tonic-gate /* erase two characters: ^[ */
4337c478bd9Sstevel@tonic-gate write(unit, "\b\b \b\b", sizeof "\b\b \b\b" - 1);
4347c478bd9Sstevel@tonic-gate break;
4357c478bd9Sstevel@tonic-gate
4367c478bd9Sstevel@tonic-gate case 1:
4377c478bd9Sstevel@tonic-gate /* overstrike the ^, erase the [ */
4387c478bd9Sstevel@tonic-gate write(unit, "\b\b", 2);
4397c478bd9Sstevel@tonic-gate printf("%t", recognized_part);
4407c478bd9Sstevel@tonic-gate write(unit, " \b\b", 4);
4417c478bd9Sstevel@tonic-gate break;
4427c478bd9Sstevel@tonic-gate
4437c478bd9Sstevel@tonic-gate default:
4447c478bd9Sstevel@tonic-gate /* overstrike both characters ^[ */
4457c478bd9Sstevel@tonic-gate write(unit, "\b\b", 2);
4467c478bd9Sstevel@tonic-gate printf("%t", recognized_part);
4477c478bd9Sstevel@tonic-gate break;
4487c478bd9Sstevel@tonic-gate }
4497c478bd9Sstevel@tonic-gate flush();
4507c478bd9Sstevel@tonic-gate }
4517c478bd9Sstevel@tonic-gate
4527c478bd9Sstevel@tonic-gate /*
4537c478bd9Sstevel@tonic-gate * Parse full path in file into 2 parts: directory and file names
4547c478bd9Sstevel@tonic-gate * Should leave final slash (/) at end of dir.
4557c478bd9Sstevel@tonic-gate */
4566c02b4a4Smuffin static void
extract_dir_and_name(tchar * path,tchar * dir,tchar * name)4576c02b4a4Smuffin extract_dir_and_name(tchar *path, tchar *dir, tchar *name)
4587c478bd9Sstevel@tonic-gate {
4596c02b4a4Smuffin tchar *p;
4607c478bd9Sstevel@tonic-gate
4617c478bd9Sstevel@tonic-gate #ifdef TRACE
4627c478bd9Sstevel@tonic-gate tprintf("TRACE- extract_dir_and_name()\n");
4637c478bd9Sstevel@tonic-gate #endif
4647c478bd9Sstevel@tonic-gate p = rindex_(path, '/');
4657c478bd9Sstevel@tonic-gate if (p == NOSTR) {
4667c478bd9Sstevel@tonic-gate copyn(name, path, MAXNAMLEN);
4677c478bd9Sstevel@tonic-gate dir[0] = '\0';
4687c478bd9Sstevel@tonic-gate } else {
4697c478bd9Sstevel@tonic-gate copyn(name, ++p, MAXNAMLEN);
4707c478bd9Sstevel@tonic-gate copyn(dir, path, p - path);
4717c478bd9Sstevel@tonic-gate }
4727c478bd9Sstevel@tonic-gate }
4737c478bd9Sstevel@tonic-gate
4747c478bd9Sstevel@tonic-gate tchar *
getentry(DIR * dir_fd,int looking_for_lognames)4756c02b4a4Smuffin getentry(DIR *dir_fd, int looking_for_lognames)
4767c478bd9Sstevel@tonic-gate {
4776c02b4a4Smuffin struct passwd *pw;
4786c02b4a4Smuffin struct dirent *dirp;
4797c478bd9Sstevel@tonic-gate /*
4807c478bd9Sstevel@tonic-gate * For char * -> tchar * Conversion
4817c478bd9Sstevel@tonic-gate */
4827c478bd9Sstevel@tonic-gate static tchar strbuf[MAXNAMLEN+1];
4837c478bd9Sstevel@tonic-gate
4847c478bd9Sstevel@tonic-gate #ifdef TRACE
4857c478bd9Sstevel@tonic-gate tprintf("TRACE- getentry()\n");
4867c478bd9Sstevel@tonic-gate #endif
4877c478bd9Sstevel@tonic-gate if (looking_for_lognames) {
488*65b0c20eSnakanon if ((pw = getpwent()) == NULL)
4897c478bd9Sstevel@tonic-gate return (NULL);
490*65b0c20eSnakanon return (strtots(strbuf, pw->pw_name));
4917c478bd9Sstevel@tonic-gate }
4927c478bd9Sstevel@tonic-gate if (dirp = readdir(dir_fd))
493*65b0c20eSnakanon return (strtots(strbuf, dirp->d_name));
4947c478bd9Sstevel@tonic-gate return (NULL);
4957c478bd9Sstevel@tonic-gate }
4967c478bd9Sstevel@tonic-gate
4976c02b4a4Smuffin static void
free_items(tchar ** items)4986c02b4a4Smuffin free_items(tchar **items)
4997c478bd9Sstevel@tonic-gate {
5006c02b4a4Smuffin int i;
5017c478bd9Sstevel@tonic-gate
5027c478bd9Sstevel@tonic-gate #ifdef TRACE
5037c478bd9Sstevel@tonic-gate tprintf("TRACE- free_items()\n");
5047c478bd9Sstevel@tonic-gate #endif
5057c478bd9Sstevel@tonic-gate for (i = 0; items[i]; i++)
506*65b0c20eSnakanon xfree(items[i]);
507*65b0c20eSnakanon xfree((char *)items);
5087c478bd9Sstevel@tonic-gate }
5097c478bd9Sstevel@tonic-gate
510*65b0c20eSnakanon #define FREE_ITEMS(items) { \
5117c478bd9Sstevel@tonic-gate int omask;\
5127c478bd9Sstevel@tonic-gate \
5137c478bd9Sstevel@tonic-gate omask = sigblock(sigmask(SIGINT));\
5147c478bd9Sstevel@tonic-gate free_items(items);\
5157c478bd9Sstevel@tonic-gate items = NULL;\
5167c478bd9Sstevel@tonic-gate (void) sigsetmask(omask);\
5177c478bd9Sstevel@tonic-gate }
5187c478bd9Sstevel@tonic-gate
5197c478bd9Sstevel@tonic-gate /*
5207c478bd9Sstevel@tonic-gate * Perform a RECOGNIZE or LIST command on string "word".
5217c478bd9Sstevel@tonic-gate */
5226c02b4a4Smuffin static int
search2(tchar * word,COMMAND command,int max_word_length)5236c02b4a4Smuffin search2(tchar *word, COMMAND command, int max_word_length)
5247c478bd9Sstevel@tonic-gate {
5257c478bd9Sstevel@tonic-gate static tchar **items = NULL;
5266c02b4a4Smuffin DIR *dir_fd;
5276c02b4a4Smuffin int numitems = 0, ignoring = TRUE, nignored = 0;
5286c02b4a4Smuffin int name_length, looking_for_lognames;
5297c478bd9Sstevel@tonic-gate tchar tilded_dir[MAXPATHLEN + 1], dir[MAXPATHLEN + 1];
5307c478bd9Sstevel@tonic-gate tchar name[MAXNAMLEN + 1], extended_name[MAXNAMLEN+1];
5317c478bd9Sstevel@tonic-gate tchar *entry;
532*65b0c20eSnakanon #define MAXITEMS 1024
5337c478bd9Sstevel@tonic-gate #ifdef TRACE
5347c478bd9Sstevel@tonic-gate tprintf("TRACE- search2()\n");
5357c478bd9Sstevel@tonic-gate #endif
5367c478bd9Sstevel@tonic-gate
5377c478bd9Sstevel@tonic-gate if (items != NULL)
5387c478bd9Sstevel@tonic-gate FREE_ITEMS(items);
5397c478bd9Sstevel@tonic-gate
5407c478bd9Sstevel@tonic-gate looking_for_lognames = (*word == '~') && (index_(word, '/') == NULL);
5417c478bd9Sstevel@tonic-gate if (looking_for_lognames) {
5427c478bd9Sstevel@tonic-gate (void) setpwent();
5437c478bd9Sstevel@tonic-gate copyn(name, &word[1], MAXNAMLEN); /* name sans ~ */
5447c478bd9Sstevel@tonic-gate } else {
5457c478bd9Sstevel@tonic-gate extract_dir_and_name(word, dir, name);
5467c478bd9Sstevel@tonic-gate if (tilde(tilded_dir, dir) == 0)
5477c478bd9Sstevel@tonic-gate return (0);
548*65b0c20eSnakanon dir_fd = opendir_(*tilded_dir ? tilded_dir : S_DOT /* "." */);
5497c478bd9Sstevel@tonic-gate if (dir_fd == NULL)
5507c478bd9Sstevel@tonic-gate return (0);
5517c478bd9Sstevel@tonic-gate }
5527c478bd9Sstevel@tonic-gate
5537c478bd9Sstevel@tonic-gate again: /* search for matches */
5547c478bd9Sstevel@tonic-gate name_length = strlen_(name);
5557c478bd9Sstevel@tonic-gate for (numitems = 0; entry = getentry(dir_fd, looking_for_lognames); ) {
5567c478bd9Sstevel@tonic-gate if (!is_prefix(name, entry))
5577c478bd9Sstevel@tonic-gate continue;
5587c478bd9Sstevel@tonic-gate /* Don't match . files on null prefix match */
5597c478bd9Sstevel@tonic-gate if (name_length == 0 && entry[0] == '.' &&
5607c478bd9Sstevel@tonic-gate !looking_for_lognames)
5617c478bd9Sstevel@tonic-gate continue;
5627c478bd9Sstevel@tonic-gate if (command == LIST) {
5637c478bd9Sstevel@tonic-gate if (numitems >= MAXITEMS) {
564*65b0c20eSnakanon printf("\nYikes!! Too many %s!!\n",
5657c478bd9Sstevel@tonic-gate looking_for_lognames ?
5667c478bd9Sstevel@tonic-gate "names in password file":"files");
5677c478bd9Sstevel@tonic-gate break;
5687c478bd9Sstevel@tonic-gate }
5697c478bd9Sstevel@tonic-gate if (items == NULL)
570*65b0c20eSnakanon items = (tchar **)xcalloc(sizeof (items[1]),
5717c478bd9Sstevel@tonic-gate MAXITEMS+1);
572*65b0c20eSnakanon items[numitems] = (tchar *)xalloc((unsigned)(strlen_(entry) + 1) * sizeof (tchar));
5737c478bd9Sstevel@tonic-gate copyn(items[numitems], entry, MAXNAMLEN);
5747c478bd9Sstevel@tonic-gate numitems++;
5757c478bd9Sstevel@tonic-gate } else { /* RECOGNIZE command */
5767c478bd9Sstevel@tonic-gate if (ignoring && ignored(entry))
5777c478bd9Sstevel@tonic-gate nignored++;
5787c478bd9Sstevel@tonic-gate else if (recognize(extended_name,
5797c478bd9Sstevel@tonic-gate entry, name_length, ++numitems))
5807c478bd9Sstevel@tonic-gate break;
5817c478bd9Sstevel@tonic-gate }
5827c478bd9Sstevel@tonic-gate }
5837c478bd9Sstevel@tonic-gate if (ignoring && numitems == 0 && nignored > 0) {
5847c478bd9Sstevel@tonic-gate ignoring = FALSE;
5857c478bd9Sstevel@tonic-gate nignored = 0;
5867c478bd9Sstevel@tonic-gate if (looking_for_lognames)
587*65b0c20eSnakanon (void) setpwent();
5887c478bd9Sstevel@tonic-gate else
5897c478bd9Sstevel@tonic-gate rewinddir(dir_fd);
5907c478bd9Sstevel@tonic-gate goto again;
5917c478bd9Sstevel@tonic-gate }
5927c478bd9Sstevel@tonic-gate
5937c478bd9Sstevel@tonic-gate if (looking_for_lognames)
5947c478bd9Sstevel@tonic-gate (void) endpwent();
5957c478bd9Sstevel@tonic-gate else {
5967c478bd9Sstevel@tonic-gate unsetfd(dir_fd->dd_fd);
5977c478bd9Sstevel@tonic-gate closedir_(dir_fd);
5987c478bd9Sstevel@tonic-gate }
5997c478bd9Sstevel@tonic-gate if (command == RECOGNIZE && numitems > 0) {
6007c478bd9Sstevel@tonic-gate if (looking_for_lognames)
601*65b0c20eSnakanon copyn(word, S_TIL /* "~" */, 1);
6027c478bd9Sstevel@tonic-gate else
6037c478bd9Sstevel@tonic-gate /* put back dir part */
6047c478bd9Sstevel@tonic-gate copyn(word, dir, max_word_length);
6057c478bd9Sstevel@tonic-gate /* add extended name */
6067c478bd9Sstevel@tonic-gate catn(word, extended_name, max_word_length);
6077c478bd9Sstevel@tonic-gate return (numitems);
6087c478bd9Sstevel@tonic-gate }
6097c478bd9Sstevel@tonic-gate if (command == LIST) {
610*65b0c20eSnakanon qsort((char *)items, numitems, sizeof (items[1]),
611*65b0c20eSnakanon (int (*)(const void *, const void *))fcompare);
6127c478bd9Sstevel@tonic-gate /*
6137c478bd9Sstevel@tonic-gate * Never looking for commands in this version, so final
6147c478bd9Sstevel@tonic-gate * argument forced to 0. If command name completion is
6157c478bd9Sstevel@tonic-gate * reinstated, this must change.
6167c478bd9Sstevel@tonic-gate */
6177c478bd9Sstevel@tonic-gate print_by_column(looking_for_lognames ? NULL : tilded_dir,
6187c478bd9Sstevel@tonic-gate items, numitems, 0);
6197c478bd9Sstevel@tonic-gate if (items != NULL)
6207c478bd9Sstevel@tonic-gate FREE_ITEMS(items);
6217c478bd9Sstevel@tonic-gate }
6227c478bd9Sstevel@tonic-gate return (0);
6237c478bd9Sstevel@tonic-gate }
6247c478bd9Sstevel@tonic-gate
6257c478bd9Sstevel@tonic-gate /*
6267c478bd9Sstevel@tonic-gate * Object: extend what user typed up to an ambiguity.
6277c478bd9Sstevel@tonic-gate * Algorithm:
628*65b0c20eSnakanon * On first match, copy full entry (assume it'll be the only match)
6297c478bd9Sstevel@tonic-gate * On subsequent matches, shorten extended_name to the first
6307c478bd9Sstevel@tonic-gate * character mismatch between extended_name and entry.
6317c478bd9Sstevel@tonic-gate * If we shorten it back to the prefix length, stop searching.
6327c478bd9Sstevel@tonic-gate */
6336c02b4a4Smuffin int
recognize(tchar * extended_name,tchar * entry,int name_length,int numitems)6346c02b4a4Smuffin recognize(tchar *extended_name, tchar *entry, int name_length, int numitems)
6357c478bd9Sstevel@tonic-gate {
6367c478bd9Sstevel@tonic-gate
6377c478bd9Sstevel@tonic-gate #ifdef TRACE
6387c478bd9Sstevel@tonic-gate tprintf("TRACE- recognize()\n");
6397c478bd9Sstevel@tonic-gate #endif
6407c478bd9Sstevel@tonic-gate if (numitems == 1) /* 1st match */
6417c478bd9Sstevel@tonic-gate copyn(extended_name, entry, MAXNAMLEN);
6427c478bd9Sstevel@tonic-gate else { /* 2nd and subsequent matches */
6436c02b4a4Smuffin tchar *x, *ent;
6446c02b4a4Smuffin int len = 0;
6457c478bd9Sstevel@tonic-gate
6467c478bd9Sstevel@tonic-gate x = extended_name;
6477c478bd9Sstevel@tonic-gate for (ent = entry; *x && *x == *ent++; x++, len++)
6487c478bd9Sstevel@tonic-gate ;
6497c478bd9Sstevel@tonic-gate *x = '\0'; /* Shorten at 1st char diff */
6507c478bd9Sstevel@tonic-gate if (len == name_length) /* Ambiguous to prefix? */
6517c478bd9Sstevel@tonic-gate return (-1); /* So stop now and save time */
6527c478bd9Sstevel@tonic-gate }
6537c478bd9Sstevel@tonic-gate return (0);
6547c478bd9Sstevel@tonic-gate }
6557c478bd9Sstevel@tonic-gate
6567c478bd9Sstevel@tonic-gate /*
6577c478bd9Sstevel@tonic-gate * Return true if check items initial chars in template
6587c478bd9Sstevel@tonic-gate * This differs from PWB imatch in that if check is null
6597c478bd9Sstevel@tonic-gate * it items anything
6607c478bd9Sstevel@tonic-gate */
6616c02b4a4Smuffin static int
is_prefix(tchar * check,tchar * template)6626c02b4a4Smuffin is_prefix(tchar *check, tchar *template)
6637c478bd9Sstevel@tonic-gate {
6647c478bd9Sstevel@tonic-gate #ifdef TRACE
6657c478bd9Sstevel@tonic-gate tprintf("TRACE- is_prefix()\n");
6667c478bd9Sstevel@tonic-gate #endif
6677c478bd9Sstevel@tonic-gate
6687c478bd9Sstevel@tonic-gate do
6697c478bd9Sstevel@tonic-gate if (*check == 0)
6707c478bd9Sstevel@tonic-gate return (TRUE);
6717c478bd9Sstevel@tonic-gate while (*check++ == *template++);
6727c478bd9Sstevel@tonic-gate return (FALSE);
6737c478bd9Sstevel@tonic-gate }
6747c478bd9Sstevel@tonic-gate
6757c478bd9Sstevel@tonic-gate /*
6767c478bd9Sstevel@tonic-gate * Return true if the chars in template appear at the
6777c478bd9Sstevel@tonic-gate * end of check, i.e., are its suffix.
6787c478bd9Sstevel@tonic-gate */
6796c02b4a4Smuffin static int
is_suffix(tchar * check,tchar * template)6806c02b4a4Smuffin is_suffix(tchar *check, tchar *template)
6817c478bd9Sstevel@tonic-gate {
6826c02b4a4Smuffin tchar *c, *t;
6837c478bd9Sstevel@tonic-gate
6847c478bd9Sstevel@tonic-gate #ifdef TRACE
6857c478bd9Sstevel@tonic-gate tprintf("TRACE- is_suffix()\n");
6867c478bd9Sstevel@tonic-gate #endif
687*65b0c20eSnakanon for (c = check; *c++; )
6887c478bd9Sstevel@tonic-gate ;
689*65b0c20eSnakanon for (t = template; *t++; )
6907c478bd9Sstevel@tonic-gate ;
6917c478bd9Sstevel@tonic-gate for (;;) {
6927c478bd9Sstevel@tonic-gate if (t == template)
6937c478bd9Sstevel@tonic-gate return (TRUE);
6947c478bd9Sstevel@tonic-gate if (c == check || *--t != *--c)
6957c478bd9Sstevel@tonic-gate return (FALSE);
6967c478bd9Sstevel@tonic-gate }
6977c478bd9Sstevel@tonic-gate }
6987c478bd9Sstevel@tonic-gate
6996c02b4a4Smuffin int
tenex(tchar * inputline,int inputline_size)7006c02b4a4Smuffin tenex(tchar *inputline, int inputline_size)
7017c478bd9Sstevel@tonic-gate {
7026c02b4a4Smuffin int numitems, num_read, should_retype;
7037c478bd9Sstevel@tonic-gate int i;
7047c478bd9Sstevel@tonic-gate
7057c478bd9Sstevel@tonic-gate #ifdef TRACE
7067c478bd9Sstevel@tonic-gate tprintf("TRACE- tenex()\n");
7077c478bd9Sstevel@tonic-gate #endif
7087c478bd9Sstevel@tonic-gate setup_tty(ON);
7097c478bd9Sstevel@tonic-gate termchars();
7107c478bd9Sstevel@tonic-gate num_read = 0;
7117c478bd9Sstevel@tonic-gate should_retype = FALSE;
7127c478bd9Sstevel@tonic-gate while ((i = read_(SHIN, inputline+num_read, inputline_size-num_read))
7137c478bd9Sstevel@tonic-gate > 0) {
714*65b0c20eSnakanon static tchar *delims = S_DELIM /* " '\"\t;&<>()|`" */;
7156c02b4a4Smuffin tchar *str_end, *word_start, last_char;
7166c02b4a4Smuffin int space_left;
7177c478bd9Sstevel@tonic-gate struct termios tty;
7187c478bd9Sstevel@tonic-gate COMMAND command;
7197c478bd9Sstevel@tonic-gate
7207c478bd9Sstevel@tonic-gate num_read += i;
7217c478bd9Sstevel@tonic-gate inputline[num_read] = '\0';
7227c478bd9Sstevel@tonic-gate last_char = inputline[num_read - 1] & TRIM;
7237c478bd9Sstevel@tonic-gate
724*65b0c20eSnakanon /*
725*65b0c20eSnakanon * read_() can return more than requested size if there
726*65b0c20eSnakanon * is multibyte character at the end.
727*65b0c20eSnakanon */
728*65b0c20eSnakanon if ((num_read >= inputline_size) || (last_char == '\n'))
7297c478bd9Sstevel@tonic-gate break;
7307c478bd9Sstevel@tonic-gate
7317c478bd9Sstevel@tonic-gate str_end = &inputline[num_read];
7327c478bd9Sstevel@tonic-gate if (last_char == ESC) {
7337c478bd9Sstevel@tonic-gate command = RECOGNIZE;
7347c478bd9Sstevel@tonic-gate *--str_end = '\0'; /* wipe out trailing ESC */
7357c478bd9Sstevel@tonic-gate } else
7367c478bd9Sstevel@tonic-gate command = LIST;
7377c478bd9Sstevel@tonic-gate
7387c478bd9Sstevel@tonic-gate tty = tty_new;
7397c478bd9Sstevel@tonic-gate tty.c_lflag &= ~ECHO;
7407c478bd9Sstevel@tonic-gate (void) ioctl(SHIN, TCSETSF, (char *)&tty);
7417c478bd9Sstevel@tonic-gate
7427c478bd9Sstevel@tonic-gate if (command == LIST)
7437c478bd9Sstevel@tonic-gate printf("\n");
7447c478bd9Sstevel@tonic-gate /*
7457c478bd9Sstevel@tonic-gate * Find LAST occurence of a delimiter in the inputline.
7467c478bd9Sstevel@tonic-gate * The word start is one character past it.
7477c478bd9Sstevel@tonic-gate */
7487c478bd9Sstevel@tonic-gate for (word_start = str_end; word_start > inputline;
7497c478bd9Sstevel@tonic-gate --word_start) {
7507c478bd9Sstevel@tonic-gate if (index_(delims, word_start[-1]) ||
7517c478bd9Sstevel@tonic-gate isauxsp(word_start[-1]))
7527c478bd9Sstevel@tonic-gate break;
7537c478bd9Sstevel@tonic-gate }
7547c478bd9Sstevel@tonic-gate space_left = inputline_size - (word_start - inputline) - 1;
7557c478bd9Sstevel@tonic-gate numitems = search2(word_start, command, space_left);
7567c478bd9Sstevel@tonic-gate
7577c478bd9Sstevel@tonic-gate /*
7587c478bd9Sstevel@tonic-gate * Tabs in the input line cause trouble after a pushback.
7597c478bd9Sstevel@tonic-gate * tty driver won't backspace over them because column
7607c478bd9Sstevel@tonic-gate * positions are now incorrect. This is solved by retyping
7617c478bd9Sstevel@tonic-gate * over current line.
7627c478bd9Sstevel@tonic-gate */
7637c478bd9Sstevel@tonic-gate if (index_(inputline, '\t')) { /* tab tchar in input line? */
7647c478bd9Sstevel@tonic-gate back_to_col_1();
7657c478bd9Sstevel@tonic-gate should_retype = TRUE;
7667c478bd9Sstevel@tonic-gate }
7677c478bd9Sstevel@tonic-gate if (command == LIST) /* Always retype after a LIST */
7687c478bd9Sstevel@tonic-gate should_retype = TRUE;
7697c478bd9Sstevel@tonic-gate if (should_retype)
7707c478bd9Sstevel@tonic-gate printprompt();
7717c478bd9Sstevel@tonic-gate pushback(inputline, should_retype);
7727c478bd9Sstevel@tonic-gate num_read = 0; /* chars will be reread */
7737c478bd9Sstevel@tonic-gate should_retype = FALSE;
7747c478bd9Sstevel@tonic-gate
7757c478bd9Sstevel@tonic-gate /*
7767c478bd9Sstevel@tonic-gate * Avoid a race condition by echoing what we're recognized
7777c478bd9Sstevel@tonic-gate * _after_ pushing back the command line. This way, if the
7787c478bd9Sstevel@tonic-gate * user waits until seeing this output before typing more
7797c478bd9Sstevel@tonic-gate * stuff, the resulting keystrokes won't race with the STIed
7807c478bd9Sstevel@tonic-gate * input we've pushed back. (Of course, if the user types
7817c478bd9Sstevel@tonic-gate * ahead, the race still exists and it's quite possible that
7827c478bd9Sstevel@tonic-gate * the pushed back input line will interleave with the
7837c478bd9Sstevel@tonic-gate * keystrokes in unexpected ways.)
7847c478bd9Sstevel@tonic-gate */
7857c478bd9Sstevel@tonic-gate if (command == RECOGNIZE) {
7867c478bd9Sstevel@tonic-gate /* print from str_end on */
7877c478bd9Sstevel@tonic-gate print_recognized_stuff(str_end);
7887c478bd9Sstevel@tonic-gate if (numitems != 1) /* Beep = No match/ambiguous */
7897c478bd9Sstevel@tonic-gate beep();
7907c478bd9Sstevel@tonic-gate }
7917c478bd9Sstevel@tonic-gate }
7927c478bd9Sstevel@tonic-gate setup_tty(OFF);
7937c478bd9Sstevel@tonic-gate return (num_read);
7947c478bd9Sstevel@tonic-gate }
7957c478bd9Sstevel@tonic-gate
7966c02b4a4Smuffin static int
ignored(tchar * entry)7976c02b4a4Smuffin ignored(tchar *entry)
7987c478bd9Sstevel@tonic-gate {
7997c478bd9Sstevel@tonic-gate struct varent *vp;
8006c02b4a4Smuffin tchar **cp;
8017c478bd9Sstevel@tonic-gate
8027c478bd9Sstevel@tonic-gate #ifdef TRACE
8037c478bd9Sstevel@tonic-gate tprintf("TRACE- ignored()\n");
8047c478bd9Sstevel@tonic-gate #endif
805*65b0c20eSnakanon if ((vp = adrof(S_fignore /* "fignore" */)) == NULL ||
8067c478bd9Sstevel@tonic-gate (cp = vp->vec) == NULL)
8077c478bd9Sstevel@tonic-gate return (FALSE);
8087c478bd9Sstevel@tonic-gate for (; *cp != NULL; cp++)
8097c478bd9Sstevel@tonic-gate if (is_suffix(entry, *cp))
8107c478bd9Sstevel@tonic-gate return (TRUE);
8117c478bd9Sstevel@tonic-gate return (FALSE);
8127c478bd9Sstevel@tonic-gate }
8136c02b4a4Smuffin #endif /* FILEC */
814