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 #pragma ident "%Z%%M% %I% %E% SMI"
167c478bd9Sstevel@tonic-gate
177c478bd9Sstevel@tonic-gate #ifdef FILEC
187c478bd9Sstevel@tonic-gate /*
197c478bd9Sstevel@tonic-gate * Tenex style file name recognition, .. and more.
207c478bd9Sstevel@tonic-gate * History:
217c478bd9Sstevel@tonic-gate * Author: Ken Greer, Sept. 1975, CMU.
227c478bd9Sstevel@tonic-gate * Finally got around to adding to the Cshell., Ken Greer, Dec. 1981.
237c478bd9Sstevel@tonic-gate */
247c478bd9Sstevel@tonic-gate
257c478bd9Sstevel@tonic-gate #include "sh.h"
267c478bd9Sstevel@tonic-gate #include <sys/types.h>
277c478bd9Sstevel@tonic-gate #include <dirent.h>
287c478bd9Sstevel@tonic-gate #include <pwd.h>
297c478bd9Sstevel@tonic-gate #include "sh.tconst.h"
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate #define TRUE 1
327c478bd9Sstevel@tonic-gate #define FALSE 0
337c478bd9Sstevel@tonic-gate #define ON 1
347c478bd9Sstevel@tonic-gate #define OFF 0
357c478bd9Sstevel@tonic-gate
367c478bd9Sstevel@tonic-gate #define ESC '\033'
377c478bd9Sstevel@tonic-gate
386c02b4a4Smuffin extern DIR *opendir_(tchar *);
397c478bd9Sstevel@tonic-gate
407c478bd9Sstevel@tonic-gate static char *BELL = "\07";
417c478bd9Sstevel@tonic-gate static char *CTRLR = "^R\n";
427c478bd9Sstevel@tonic-gate
437c478bd9Sstevel@tonic-gate typedef enum {LIST, RECOGNIZE} COMMAND;
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate static jmp_buf osetexit; /* saved setexit() state */
467c478bd9Sstevel@tonic-gate static struct termios tty_save; /* saved terminal state */
477c478bd9Sstevel@tonic-gate static struct termios tty_new; /* new terminal state */
487c478bd9Sstevel@tonic-gate
496c02b4a4Smuffin static int is_prefix(tchar *, tchar *);
506c02b4a4Smuffin static int is_suffix(tchar *, tchar *);
516c02b4a4Smuffin static int ignored(tchar *);
526c02b4a4Smuffin
537c478bd9Sstevel@tonic-gate /*
547c478bd9Sstevel@tonic-gate * Put this here so the binary can be patched with adb to enable file
557c478bd9Sstevel@tonic-gate * completion by default. Filec controls completion, nobeep controls
567c478bd9Sstevel@tonic-gate * ringing the terminal bell on incomplete expansions.
577c478bd9Sstevel@tonic-gate */
587c478bd9Sstevel@tonic-gate bool filec = 0;
597c478bd9Sstevel@tonic-gate
606c02b4a4Smuffin static void
setup_tty(int on)616c02b4a4Smuffin setup_tty(int on)
627c478bd9Sstevel@tonic-gate {
637c478bd9Sstevel@tonic-gate int omask;
647c478bd9Sstevel@tonic-gate #ifdef TRACE
657c478bd9Sstevel@tonic-gate tprintf("TRACE- setup_tty()\n");
667c478bd9Sstevel@tonic-gate #endif
677c478bd9Sstevel@tonic-gate
687c478bd9Sstevel@tonic-gate omask = sigblock(sigmask(SIGINT));
697c478bd9Sstevel@tonic-gate if (on) {
707c478bd9Sstevel@tonic-gate /*
717c478bd9Sstevel@tonic-gate * The shell makes sure that the tty is not in some weird state
727c478bd9Sstevel@tonic-gate * and fixes it if it is. But it should be noted that the
737c478bd9Sstevel@tonic-gate * tenex routine will not work correctly in CBREAK or RAW mode
747c478bd9Sstevel@tonic-gate * so this code below is, therefore, mandatory.
757c478bd9Sstevel@tonic-gate *
767c478bd9Sstevel@tonic-gate * Also, in order to recognize the ESC (filename-completion)
777c478bd9Sstevel@tonic-gate * character, set EOL to ESC. This way, ESC will terminate
787c478bd9Sstevel@tonic-gate * the line, but still be in the input stream.
797c478bd9Sstevel@tonic-gate * EOT (filename list) will also terminate the line,
807c478bd9Sstevel@tonic-gate * but will not appear in the input stream.
817c478bd9Sstevel@tonic-gate *
827c478bd9Sstevel@tonic-gate * The getexit/setexit contortions ensure that the
837c478bd9Sstevel@tonic-gate * tty state will be restored if the user types ^C.
847c478bd9Sstevel@tonic-gate */
857c478bd9Sstevel@tonic-gate (void) ioctl(SHIN, TCGETS, (char *)&tty_save);
867c478bd9Sstevel@tonic-gate getexit(osetexit);
877c478bd9Sstevel@tonic-gate if (setjmp(reslab)) {
887c478bd9Sstevel@tonic-gate (void) ioctl(SHIN, TCSETSW, (char *)&tty_save);
897c478bd9Sstevel@tonic-gate resexit(osetexit);
907c478bd9Sstevel@tonic-gate reset();
917c478bd9Sstevel@tonic-gate }
927c478bd9Sstevel@tonic-gate tty_new = tty_save;
937c478bd9Sstevel@tonic-gate tty_new.c_cc[VEOL] = ESC;
947c478bd9Sstevel@tonic-gate tty_new.c_iflag |= IMAXBEL | BRKINT | IGNPAR;
957c478bd9Sstevel@tonic-gate tty_new.c_lflag |= ICANON;
967c478bd9Sstevel@tonic-gate tty_new.c_lflag |= ECHOCTL;
977c478bd9Sstevel@tonic-gate tty_new.c_oflag &= ~OCRNL;
987c478bd9Sstevel@tonic-gate (void) ioctl(SHIN, TCSETSW, (char *)&tty_new);
997c478bd9Sstevel@tonic-gate } else {
1007c478bd9Sstevel@tonic-gate /*
1017c478bd9Sstevel@tonic-gate * Reset terminal state to what user had when invoked
1027c478bd9Sstevel@tonic-gate */
1037c478bd9Sstevel@tonic-gate (void) ioctl(SHIN, TCSETSW, (char *)&tty_save);
1047c478bd9Sstevel@tonic-gate resexit(osetexit);
1057c478bd9Sstevel@tonic-gate }
1067c478bd9Sstevel@tonic-gate (void) sigsetmask(omask);
1077c478bd9Sstevel@tonic-gate }
1087c478bd9Sstevel@tonic-gate
1096c02b4a4Smuffin static void
termchars(void)1106c02b4a4Smuffin termchars(void)
1117c478bd9Sstevel@tonic-gate {
1127c478bd9Sstevel@tonic-gate extern char *tgetstr();
1137c478bd9Sstevel@tonic-gate char bp[1024];
1147c478bd9Sstevel@tonic-gate static char area[256];
1157c478bd9Sstevel@tonic-gate static int been_here = 0;
1167c478bd9Sstevel@tonic-gate char *ap = area;
1176c02b4a4Smuffin char *s;
1187c478bd9Sstevel@tonic-gate char *term;
1197c478bd9Sstevel@tonic-gate
1207c478bd9Sstevel@tonic-gate #ifdef TRACE
1217c478bd9Sstevel@tonic-gate tprintf("TRACE- termchars()\n");
1227c478bd9Sstevel@tonic-gate #endif
1237c478bd9Sstevel@tonic-gate if (been_here)
1247c478bd9Sstevel@tonic-gate return;
1257c478bd9Sstevel@tonic-gate been_here = TRUE;
1267c478bd9Sstevel@tonic-gate
1277c478bd9Sstevel@tonic-gate if ((term = getenv("TERM")) == NULL)
1287c478bd9Sstevel@tonic-gate return;
1297c478bd9Sstevel@tonic-gate if (tgetent(bp, term) != 1)
1307c478bd9Sstevel@tonic-gate return;
1317c478bd9Sstevel@tonic-gate if (s = tgetstr("vb", &ap)) /* Visible Bell */
1327c478bd9Sstevel@tonic-gate BELL = s;
1337c478bd9Sstevel@tonic-gate }
1347c478bd9Sstevel@tonic-gate
1357c478bd9Sstevel@tonic-gate /*
1367c478bd9Sstevel@tonic-gate * Move back to beginning of current line
1377c478bd9Sstevel@tonic-gate */
1386c02b4a4Smuffin static void
back_to_col_1(void)1396c02b4a4Smuffin back_to_col_1(void)
1407c478bd9Sstevel@tonic-gate {
1417c478bd9Sstevel@tonic-gate int omask;
1427c478bd9Sstevel@tonic-gate
1437c478bd9Sstevel@tonic-gate #ifdef TRACE
1447c478bd9Sstevel@tonic-gate tprintf("TRACE- back_to_col_1()\n");
1457c478bd9Sstevel@tonic-gate #endif
1467c478bd9Sstevel@tonic-gate omask = sigblock(sigmask(SIGINT));
1477c478bd9Sstevel@tonic-gate (void) write(SHOUT, "\r", 1);
1487c478bd9Sstevel@tonic-gate (void) sigsetmask(omask);
1497c478bd9Sstevel@tonic-gate }
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate /*
1527c478bd9Sstevel@tonic-gate * Push string contents back into tty queue
1537c478bd9Sstevel@tonic-gate */
1546c02b4a4Smuffin static void
pushback(tchar * string,int echoflag)1556c02b4a4Smuffin pushback(tchar *string, int echoflag)
1567c478bd9Sstevel@tonic-gate {
1576c02b4a4Smuffin tchar *p;
1587c478bd9Sstevel@tonic-gate struct termios tty;
159*65b0c20eSnakanon int omask, retry = 0;
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate #ifdef TRACE
1627c478bd9Sstevel@tonic-gate tprintf("TRACE- pushback()\n");
1637c478bd9Sstevel@tonic-gate #endif
1647c478bd9Sstevel@tonic-gate omask = sigblock(sigmask(SIGINT));
1657c478bd9Sstevel@tonic-gate tty = tty_new;
1667c478bd9Sstevel@tonic-gate if (!echoflag)
1677c478bd9Sstevel@tonic-gate tty.c_lflag &= ~ECHO;
168*65b0c20eSnakanon
169*65b0c20eSnakanon again:
1707c478bd9Sstevel@tonic-gate (void) ioctl(SHIN, TCSETSF, (char *)&tty);
1717c478bd9Sstevel@tonic-gate
1727c478bd9Sstevel@tonic-gate for (p = string; *p; p++) {
1737c478bd9Sstevel@tonic-gate char mbc[MB_LEN_MAX];
1747c478bd9Sstevel@tonic-gate int i, j = wctomb(mbc, (wchar_t)*p);
1757c478bd9Sstevel@tonic-gate
1767c478bd9Sstevel@tonic-gate if (j < 0) {
1777c478bd9Sstevel@tonic-gate /* Error! But else what can we do? */
1787c478bd9Sstevel@tonic-gate continue;
1797c478bd9Sstevel@tonic-gate }
1807c478bd9Sstevel@tonic-gate for (i = 0; i < j; ++i) {
181*65b0c20eSnakanon if (ioctl(SHIN, TIOCSTI, mbc + i) != 0 &&
182*65b0c20eSnakanon errno == EAGAIN) {
183*65b0c20eSnakanon if (retry++ < 5)
184*65b0c20eSnakanon goto again;
185*65b0c20eSnakanon /* probably no worth retrying any more */
186*65b0c20eSnakanon }
1877c478bd9Sstevel@tonic-gate }
1887c478bd9Sstevel@tonic-gate }
1897c478bd9Sstevel@tonic-gate
1907c478bd9Sstevel@tonic-gate if (tty.c_lflag != tty_new.c_lflag)
1917c478bd9Sstevel@tonic-gate (void) ioctl(SHIN, TCSETS, (char *)&tty_new);
1927c478bd9Sstevel@tonic-gate (void) sigsetmask(omask);
1937c478bd9Sstevel@tonic-gate }
1947c478bd9Sstevel@tonic-gate
1957c478bd9Sstevel@tonic-gate /*
1967c478bd9Sstevel@tonic-gate * Concatenate src onto tail of des.
1977c478bd9Sstevel@tonic-gate * Des is a string whose maximum length is count.
1987c478bd9Sstevel@tonic-gate * Always null terminate.
1997c478bd9Sstevel@tonic-gate */
2006c02b4a4Smuffin void
catn(tchar * des,tchar * src,int count)2016c02b4a4Smuffin catn(tchar *des, tchar *src, int count)
2027c478bd9Sstevel@tonic-gate {
2037c478bd9Sstevel@tonic-gate #ifdef TRACE
2047c478bd9Sstevel@tonic-gate tprintf("TRACE- catn()\n");
2057c478bd9Sstevel@tonic-gate #endif
2067c478bd9Sstevel@tonic-gate
2077c478bd9Sstevel@tonic-gate while (--count >= 0 && *des)
2087c478bd9Sstevel@tonic-gate des++;
2097c478bd9Sstevel@tonic-gate while (--count >= 0)
2107c478bd9Sstevel@tonic-gate if ((*des++ = *src++) == '\0')
2117c478bd9Sstevel@tonic-gate return;
2127c478bd9Sstevel@tonic-gate *des = '\0';
2137c478bd9Sstevel@tonic-gate }
2147c478bd9Sstevel@tonic-gate
2156c02b4a4Smuffin static int
max(a,b)2167c478bd9Sstevel@tonic-gate max(a, b)
2177c478bd9Sstevel@tonic-gate {
2187c478bd9Sstevel@tonic-gate
2197c478bd9Sstevel@tonic-gate return (a > b ? a : b);
2207c478bd9Sstevel@tonic-gate }
2217c478bd9Sstevel@tonic-gate
2227c478bd9Sstevel@tonic-gate /*
2237c478bd9Sstevel@tonic-gate * Like strncpy but always leave room for trailing \0
2247c478bd9Sstevel@tonic-gate * and always null terminate.
2257c478bd9Sstevel@tonic-gate */
2266c02b4a4Smuffin void
copyn(tchar * des,tchar * src,int count)2276c02b4a4Smuffin copyn(tchar *des, tchar *src, int count)
2287c478bd9Sstevel@tonic-gate {
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate #ifdef TRACE
2317c478bd9Sstevel@tonic-gate tprintf("TRACE- copyn()\n");
2327c478bd9Sstevel@tonic-gate #endif
2337c478bd9Sstevel@tonic-gate while (--count >= 0)
2347c478bd9Sstevel@tonic-gate if ((*des++ = *src++) == '\0')
2357c478bd9Sstevel@tonic-gate return;
2367c478bd9Sstevel@tonic-gate *des = '\0';
2377c478bd9Sstevel@tonic-gate }
2387c478bd9Sstevel@tonic-gate
2397c478bd9Sstevel@tonic-gate /*
2407c478bd9Sstevel@tonic-gate * For qsort()
2417c478bd9Sstevel@tonic-gate */
2426c02b4a4Smuffin static int
fcompare(tchar ** file1,tchar ** file2)2436c02b4a4Smuffin fcompare(tchar **file1, tchar **file2)
2447c478bd9Sstevel@tonic-gate {
2457c478bd9Sstevel@tonic-gate
2467c478bd9Sstevel@tonic-gate #ifdef TRACE
2477c478bd9Sstevel@tonic-gate tprintf("TRACE- fcompare()\n");
2487c478bd9Sstevel@tonic-gate #endif
2497c478bd9Sstevel@tonic-gate return (strcoll_(*file1, *file2));
2507c478bd9Sstevel@tonic-gate }
2517c478bd9Sstevel@tonic-gate
2527c478bd9Sstevel@tonic-gate static char
filetype(tchar * dir,tchar * file,int nosym)2536c02b4a4Smuffin filetype(tchar *dir, tchar *file, int nosym)
2547c478bd9Sstevel@tonic-gate {
2557c478bd9Sstevel@tonic-gate tchar path[MAXPATHLEN + 1];
2567c478bd9Sstevel@tonic-gate struct stat statb;
2577c478bd9Sstevel@tonic-gate
2587c478bd9Sstevel@tonic-gate #ifdef TRACE
2597c478bd9Sstevel@tonic-gate tprintf("TRACE- filetype()\n");
2607c478bd9Sstevel@tonic-gate #endif
2617c478bd9Sstevel@tonic-gate if (dir) {
2627c478bd9Sstevel@tonic-gate catn(strcpy_(path, dir), file, MAXPATHLEN);
2637c478bd9Sstevel@tonic-gate if (nosym) {
2647c478bd9Sstevel@tonic-gate if (stat_(path, &statb) < 0)
2657c478bd9Sstevel@tonic-gate return (' ');
2667c478bd9Sstevel@tonic-gate } else {
2677c478bd9Sstevel@tonic-gate if (lstat_(path, &statb) < 0)
2687c478bd9Sstevel@tonic-gate return (' ');
2697c478bd9Sstevel@tonic-gate }
2707c478bd9Sstevel@tonic-gate if ((statb.st_mode & S_IFMT) == S_IFLNK)
2717c478bd9Sstevel@tonic-gate return ('@');
2727c478bd9Sstevel@tonic-gate if ((statb.st_mode & S_IFMT) == S_IFDIR)
2737c478bd9Sstevel@tonic-gate return ('/');
2747c478bd9Sstevel@tonic-gate if (((statb.st_mode & S_IFMT) == S_IFREG) &&
2757c478bd9Sstevel@tonic-gate (statb.st_mode & 011))
2767c478bd9Sstevel@tonic-gate return ('*');
2777c478bd9Sstevel@tonic-gate }
2787c478bd9Sstevel@tonic-gate return (' ');
2797c478bd9Sstevel@tonic-gate }
2807c478bd9Sstevel@tonic-gate
2817c478bd9Sstevel@tonic-gate /*
2827c478bd9Sstevel@tonic-gate * Print sorted down columns
2837c478bd9Sstevel@tonic-gate */
2846c02b4a4Smuffin static void
print_by_column(tchar * dir,tchar * items[],int count,int looking_for_command)2856c02b4a4Smuffin print_by_column(tchar *dir, tchar *items[], int count, int looking_for_command)
2867c478bd9Sstevel@tonic-gate {
2876c02b4a4Smuffin int i, rows, r, c, maxwidth = 0, columns;
2887c478bd9Sstevel@tonic-gate
2897c478bd9Sstevel@tonic-gate #ifdef TRACE
2907c478bd9Sstevel@tonic-gate tprintf("TRACE- print_by_column()\n");
2917c478bd9Sstevel@tonic-gate #endif
2927c478bd9Sstevel@tonic-gate for (i = 0; i < count; i++)
2937c478bd9Sstevel@tonic-gate maxwidth = max(maxwidth, tswidth(items[i]));
2947c478bd9Sstevel@tonic-gate
2957c478bd9Sstevel@tonic-gate /* for the file tag and space */
2967c478bd9Sstevel@tonic-gate maxwidth += looking_for_command ? 1 : 2;
2977c478bd9Sstevel@tonic-gate columns = max(78 / maxwidth, 1);
2987c478bd9Sstevel@tonic-gate rows = (count + (columns - 1)) / columns;
2997c478bd9Sstevel@tonic-gate
3007c478bd9Sstevel@tonic-gate for (r = 0; r < rows; r++) {
3017c478bd9Sstevel@tonic-gate for (c = 0; c < columns; c++) {
3027c478bd9Sstevel@tonic-gate i = c * rows + r;
3037c478bd9Sstevel@tonic-gate if (i < count) {
3046c02b4a4Smuffin int w;
3057c478bd9Sstevel@tonic-gate
3067c478bd9Sstevel@tonic-gate /*
3077c478bd9Sstevel@tonic-gate * Print filename followed by
3087c478bd9Sstevel@tonic-gate * '@' or '/' or '*' or ' '
3097c478bd9Sstevel@tonic-gate */
3107c478bd9Sstevel@tonic-gate printf("%t", items[i]);
3117c478bd9Sstevel@tonic-gate w = tswidth(items[i]);
3127c478bd9Sstevel@tonic-gate if (!looking_for_command) {
3137c478bd9Sstevel@tonic-gate printf("%c",
3147c478bd9Sstevel@tonic-gate (tchar) filetype(dir, items[i], 0));
3157c478bd9Sstevel@tonic-gate w++;
3167c478bd9Sstevel@tonic-gate }
3177c478bd9Sstevel@tonic-gate if (c < columns - 1) /* last column? */
3187c478bd9Sstevel@tonic-gate for (; w < maxwidth; w++)
3197c478bd9Sstevel@tonic-gate printf(" ");
3207c478bd9Sstevel@tonic-gate }
3217c478bd9Sstevel@tonic-gate }
3227c478bd9Sstevel@tonic-gate printf("\n");
3237c478bd9Sstevel@tonic-gate }
3247c478bd9Sstevel@tonic-gate }
3257c478bd9Sstevel@tonic-gate
3267c478bd9Sstevel@tonic-gate /*
3277c478bd9Sstevel@tonic-gate * Expand file name with possible tilde usage
3287c478bd9Sstevel@tonic-gate * ~person/mumble
3297c478bd9Sstevel@tonic-gate * expands to
3307c478bd9Sstevel@tonic-gate * home_directory_of_person/mumble
3317c478bd9Sstevel@tonic-gate */
3327c478bd9Sstevel@tonic-gate tchar *
tilde(tchar * new,tchar * old)3336c02b4a4Smuffin tilde(tchar *new, tchar *old)
3347c478bd9Sstevel@tonic-gate {
3356c02b4a4Smuffin tchar *o, *p;
3366c02b4a4Smuffin struct passwd *pw;
3377c478bd9Sstevel@tonic-gate static tchar person[40];
3387c478bd9Sstevel@tonic-gate char person_[40]; /* work */
3397c478bd9Sstevel@tonic-gate tchar *pw_dir; /* work */
3407c478bd9Sstevel@tonic-gate
3417c478bd9Sstevel@tonic-gate #ifdef TRACE
3427c478bd9Sstevel@tonic-gate tprintf("TRACE- tilde()\n");
3437c478bd9Sstevel@tonic-gate #endif
3447c478bd9Sstevel@tonic-gate if (old[0] != '~')
3457c478bd9Sstevel@tonic-gate return (strcpy_(new, old));
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate for (p = person, o = &old[1]; *o && *o != '/'; *p++ = *o++)
3487c478bd9Sstevel@tonic-gate ;
3497c478bd9Sstevel@tonic-gate *p = '\0';
3507c478bd9Sstevel@tonic-gate if (person[0] == '\0')
3517c478bd9Sstevel@tonic-gate (void) strcpy_(new, value(S_home /* "home" */));
3527c478bd9Sstevel@tonic-gate else {
3537c478bd9Sstevel@tonic-gate pw = getpwnam(tstostr(person_, person));
3547c478bd9Sstevel@tonic-gate if (pw == NULL)
3557c478bd9Sstevel@tonic-gate return (NULL);
3567c478bd9Sstevel@tonic-gate pw_dir = strtots((tchar *)NULL, pw->pw_dir); /* allocate */
3577c478bd9Sstevel@tonic-gate (void) strcpy_(new, pw_dir);
3587c478bd9Sstevel@tonic-gate xfree(pw_dir); /* free it */
3597c478bd9Sstevel@tonic-gate }
3607c478bd9Sstevel@tonic-gate (void) strcat_(new, o);
3617c478bd9Sstevel@tonic-gate return (new);
3627c478bd9Sstevel@tonic-gate }
3637c478bd9Sstevel@tonic-gate
3647c478bd9Sstevel@tonic-gate /*
3657c478bd9Sstevel@tonic-gate * Cause pending line to be printed
3667c478bd9Sstevel@tonic-gate */
3676c02b4a4Smuffin static void
sim_retype(void)3686c02b4a4Smuffin sim_retype(void)
3697c478bd9Sstevel@tonic-gate {
3707c478bd9Sstevel@tonic-gate #ifdef notdef
3717c478bd9Sstevel@tonic-gate struct termios tty_pending;
3727c478bd9Sstevel@tonic-gate
3737c478bd9Sstevel@tonic-gate #ifdef TRACE
3747c478bd9Sstevel@tonic-gate tprintf("TRACE- sim_retypr()\n");
3757c478bd9Sstevel@tonic-gate #endif
3767c478bd9Sstevel@tonic-gate tty_pending = tty_new;
3777c478bd9Sstevel@tonic-gate tty_pending.c_lflag |= PENDIN;
3787c478bd9Sstevel@tonic-gate
3797c478bd9Sstevel@tonic-gate (void) ioctl(SHIN, TCSETS, (char *)&tty_pending);
3807c478bd9Sstevel@tonic-gate #else
3817c478bd9Sstevel@tonic-gate #ifdef TRACE
3827c478bd9Sstevel@tonic-gate tprintf("TRACE- sim_retype()\n");
3837c478bd9Sstevel@tonic-gate #endif
3847c478bd9Sstevel@tonic-gate (void) write(SHOUT, CTRLR, strlen(CTRLR));
3857c478bd9Sstevel@tonic-gate printprompt();
3867c478bd9Sstevel@tonic-gate #endif
3877c478bd9Sstevel@tonic-gate }
3887c478bd9Sstevel@tonic-gate
3896c02b4a4Smuffin static int
beep_outc(int c)3906c02b4a4Smuffin beep_outc(int c)
3916c02b4a4Smuffin {
3927c478bd9Sstevel@tonic-gate char buf[1];
3937c478bd9Sstevel@tonic-gate
3947c478bd9Sstevel@tonic-gate buf[0] = c;
3957c478bd9Sstevel@tonic-gate
3967c478bd9Sstevel@tonic-gate (void) write(SHOUT, buf, 1);
3977c478bd9Sstevel@tonic-gate
3987c478bd9Sstevel@tonic-gate return 0;
3997c478bd9Sstevel@tonic-gate }
4007c478bd9Sstevel@tonic-gate
4016c02b4a4Smuffin static void
beep(void)4026c02b4a4Smuffin beep(void)
4037c478bd9Sstevel@tonic-gate {
4047c478bd9Sstevel@tonic-gate
4057c478bd9Sstevel@tonic-gate #ifdef TRACE
4067c478bd9Sstevel@tonic-gate tprintf("TRACE- beep()\n");
4077c478bd9Sstevel@tonic-gate #endif
4087c478bd9Sstevel@tonic-gate if (adrof(S_nobeep /* "nobeep" */) == 0)
4097c478bd9Sstevel@tonic-gate (void) tputs(BELL, 0, beep_outc);
4107c478bd9Sstevel@tonic-gate }
4117c478bd9Sstevel@tonic-gate
4127c478bd9Sstevel@tonic-gate /*
4137c478bd9Sstevel@tonic-gate * Erase that silly ^[ and print the recognized part of the string.
4147c478bd9Sstevel@tonic-gate */
4156c02b4a4Smuffin static void
print_recognized_stuff(tchar * recognized_part)4166c02b4a4Smuffin print_recognized_stuff(tchar *recognized_part)
4177c478bd9Sstevel@tonic-gate {
4187c478bd9Sstevel@tonic-gate int unit = didfds ? 1 : SHOUT;
4197c478bd9Sstevel@tonic-gate
4207c478bd9Sstevel@tonic-gate #ifdef TRACE
4217c478bd9Sstevel@tonic-gate tprintf("TRACE- print_recognized_stuff()\n");
4227c478bd9Sstevel@tonic-gate #endif
4237c478bd9Sstevel@tonic-gate
4247c478bd9Sstevel@tonic-gate /*
4257c478bd9Sstevel@tonic-gate * An optimized erasing of that silly ^[
4267c478bd9Sstevel@tonic-gate *
4277c478bd9Sstevel@tonic-gate * One would think that line speeds have become fast enough that this
4287c478bd9Sstevel@tonic-gate * isn't necessary, but it turns out that the visual difference is
4297c478bd9Sstevel@tonic-gate * quite noticeable.
4307c478bd9Sstevel@tonic-gate */
4317c478bd9Sstevel@tonic-gate flush();
4327c478bd9Sstevel@tonic-gate switch (tswidth(recognized_part)) {
4337c478bd9Sstevel@tonic-gate case 0:
4347c478bd9Sstevel@tonic-gate /* erase two characters: ^[ */
4357c478bd9Sstevel@tonic-gate write(unit, "\b\b \b\b", sizeof "\b\b \b\b" - 1);
4367c478bd9Sstevel@tonic-gate break;
4377c478bd9Sstevel@tonic-gate
4387c478bd9Sstevel@tonic-gate case 1:
4397c478bd9Sstevel@tonic-gate /* overstrike the ^, erase the [ */
4407c478bd9Sstevel@tonic-gate write(unit, "\b\b", 2);
4417c478bd9Sstevel@tonic-gate printf("%t", recognized_part);
4427c478bd9Sstevel@tonic-gate write(unit, " \b\b", 4);
4437c478bd9Sstevel@tonic-gate break;
4447c478bd9Sstevel@tonic-gate
4457c478bd9Sstevel@tonic-gate default:
4467c478bd9Sstevel@tonic-gate /* overstrike both characters ^[ */
4477c478bd9Sstevel@tonic-gate write(unit, "\b\b", 2);
4487c478bd9Sstevel@tonic-gate printf("%t", recognized_part);
4497c478bd9Sstevel@tonic-gate break;
4507c478bd9Sstevel@tonic-gate }
4517c478bd9Sstevel@tonic-gate flush();
4527c478bd9Sstevel@tonic-gate }
4537c478bd9Sstevel@tonic-gate
4547c478bd9Sstevel@tonic-gate /*
4557c478bd9Sstevel@tonic-gate * Parse full path in file into 2 parts: directory and file names
4567c478bd9Sstevel@tonic-gate * Should leave final slash (/) at end of dir.
4577c478bd9Sstevel@tonic-gate */
4586c02b4a4Smuffin static void
extract_dir_and_name(tchar * path,tchar * dir,tchar * name)4596c02b4a4Smuffin extract_dir_and_name(tchar *path, tchar *dir, tchar *name)
4607c478bd9Sstevel@tonic-gate {
4616c02b4a4Smuffin tchar *p;
4627c478bd9Sstevel@tonic-gate
4637c478bd9Sstevel@tonic-gate #ifdef TRACE
4647c478bd9Sstevel@tonic-gate tprintf("TRACE- extract_dir_and_name()\n");
4657c478bd9Sstevel@tonic-gate #endif
4667c478bd9Sstevel@tonic-gate p = rindex_(path, '/');
4677c478bd9Sstevel@tonic-gate if (p == NOSTR) {
4687c478bd9Sstevel@tonic-gate copyn(name, path, MAXNAMLEN);
4697c478bd9Sstevel@tonic-gate dir[0] = '\0';
4707c478bd9Sstevel@tonic-gate } else {
4717c478bd9Sstevel@tonic-gate copyn(name, ++p, MAXNAMLEN);
4727c478bd9Sstevel@tonic-gate copyn(dir, path, p - path);
4737c478bd9Sstevel@tonic-gate }
4747c478bd9Sstevel@tonic-gate }
4757c478bd9Sstevel@tonic-gate
4767c478bd9Sstevel@tonic-gate tchar *
getentry(DIR * dir_fd,int looking_for_lognames)4776c02b4a4Smuffin getentry(DIR *dir_fd, int looking_for_lognames)
4787c478bd9Sstevel@tonic-gate {
4796c02b4a4Smuffin struct passwd *pw;
4806c02b4a4Smuffin struct dirent *dirp;
4817c478bd9Sstevel@tonic-gate /*
4827c478bd9Sstevel@tonic-gate * For char * -> tchar * Conversion
4837c478bd9Sstevel@tonic-gate */
4847c478bd9Sstevel@tonic-gate static tchar strbuf[MAXNAMLEN+1];
4857c478bd9Sstevel@tonic-gate
4867c478bd9Sstevel@tonic-gate #ifdef TRACE
4877c478bd9Sstevel@tonic-gate tprintf("TRACE- getentry()\n");
4887c478bd9Sstevel@tonic-gate #endif
4897c478bd9Sstevel@tonic-gate if (looking_for_lognames) {
4907c478bd9Sstevel@tonic-gate if ((pw = getpwent()) == NULL)
4917c478bd9Sstevel@tonic-gate return (NULL);
4927c478bd9Sstevel@tonic-gate return (strtots(strbuf, pw->pw_name));
4937c478bd9Sstevel@tonic-gate }
4947c478bd9Sstevel@tonic-gate if (dirp = readdir(dir_fd))
4957c478bd9Sstevel@tonic-gate return (strtots(strbuf, dirp->d_name));
4967c478bd9Sstevel@tonic-gate return (NULL);
4977c478bd9Sstevel@tonic-gate }
4987c478bd9Sstevel@tonic-gate
4996c02b4a4Smuffin static void
free_items(tchar ** items)5006c02b4a4Smuffin free_items(tchar **items)
5017c478bd9Sstevel@tonic-gate {
5026c02b4a4Smuffin int i;
5037c478bd9Sstevel@tonic-gate
5047c478bd9Sstevel@tonic-gate #ifdef TRACE
5057c478bd9Sstevel@tonic-gate tprintf("TRACE- free_items()\n");
5067c478bd9Sstevel@tonic-gate #endif
5077c478bd9Sstevel@tonic-gate for (i = 0; items[i]; i++)
508*65b0c20eSnakanon xfree(items[i]);
509*65b0c20eSnakanon xfree((char *)items);
5107c478bd9Sstevel@tonic-gate }
5117c478bd9Sstevel@tonic-gate
5127c478bd9Sstevel@tonic-gate #define FREE_ITEMS(items) { \
5137c478bd9Sstevel@tonic-gate int omask;\
5147c478bd9Sstevel@tonic-gate \
5157c478bd9Sstevel@tonic-gate omask = sigblock(sigmask(SIGINT));\
5167c478bd9Sstevel@tonic-gate free_items(items);\
5177c478bd9Sstevel@tonic-gate items = NULL;\
5187c478bd9Sstevel@tonic-gate (void) sigsetmask(omask);\
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate
5217c478bd9Sstevel@tonic-gate /*
5227c478bd9Sstevel@tonic-gate * Perform a RECOGNIZE or LIST command on string "word".
5237c478bd9Sstevel@tonic-gate */
5246c02b4a4Smuffin static int
search2(tchar * word,COMMAND command,int max_word_length)5256c02b4a4Smuffin search2(tchar *word, COMMAND command, int max_word_length)
5267c478bd9Sstevel@tonic-gate {
5277c478bd9Sstevel@tonic-gate static tchar **items = NULL;
5286c02b4a4Smuffin DIR *dir_fd;
5296c02b4a4Smuffin int numitems = 0, ignoring = TRUE, nignored = 0;
5306c02b4a4Smuffin int name_length, looking_for_lognames;
5317c478bd9Sstevel@tonic-gate tchar tilded_dir[MAXPATHLEN + 1], dir[MAXPATHLEN + 1];
5327c478bd9Sstevel@tonic-gate tchar name[MAXNAMLEN + 1], extended_name[MAXNAMLEN+1];
5337c478bd9Sstevel@tonic-gate tchar *entry;
5347c478bd9Sstevel@tonic-gate #define MAXITEMS 1024
5357c478bd9Sstevel@tonic-gate #ifdef TRACE
5367c478bd9Sstevel@tonic-gate tprintf("TRACE- search2()\n");
5377c478bd9Sstevel@tonic-gate #endif
5387c478bd9Sstevel@tonic-gate
5397c478bd9Sstevel@tonic-gate if (items != NULL)
5407c478bd9Sstevel@tonic-gate FREE_ITEMS(items);
5417c478bd9Sstevel@tonic-gate
5427c478bd9Sstevel@tonic-gate looking_for_lognames = (*word == '~') && (index_(word, '/') == NULL);
5437c478bd9Sstevel@tonic-gate if (looking_for_lognames) {
5447c478bd9Sstevel@tonic-gate (void) setpwent();
5457c478bd9Sstevel@tonic-gate copyn(name, &word[1], MAXNAMLEN); /* name sans ~ */
5467c478bd9Sstevel@tonic-gate } else {
5477c478bd9Sstevel@tonic-gate extract_dir_and_name(word, dir, name);
5487c478bd9Sstevel@tonic-gate if (tilde(tilded_dir, dir) == 0)
5497c478bd9Sstevel@tonic-gate return (0);
5507c478bd9Sstevel@tonic-gate dir_fd = opendir_(*tilded_dir ? tilded_dir : S_DOT /* "." */);
5517c478bd9Sstevel@tonic-gate if (dir_fd == NULL)
5527c478bd9Sstevel@tonic-gate return (0);
5537c478bd9Sstevel@tonic-gate }
5547c478bd9Sstevel@tonic-gate
5557c478bd9Sstevel@tonic-gate again: /* search for matches */
5567c478bd9Sstevel@tonic-gate name_length = strlen_(name);
5577c478bd9Sstevel@tonic-gate for (numitems = 0; entry = getentry(dir_fd, looking_for_lognames); ) {
5587c478bd9Sstevel@tonic-gate if (!is_prefix(name, entry))
5597c478bd9Sstevel@tonic-gate continue;
5607c478bd9Sstevel@tonic-gate /* Don't match . files on null prefix match */
5617c478bd9Sstevel@tonic-gate if (name_length == 0 && entry[0] == '.' &&
5627c478bd9Sstevel@tonic-gate !looking_for_lognames)
5637c478bd9Sstevel@tonic-gate continue;
5647c478bd9Sstevel@tonic-gate if (command == LIST) {
5657c478bd9Sstevel@tonic-gate if (numitems >= MAXITEMS) {
5667c478bd9Sstevel@tonic-gate printf("\nYikes!! Too many %s!!\n",
5677c478bd9Sstevel@tonic-gate looking_for_lognames ?
5687c478bd9Sstevel@tonic-gate "names in password file":"files");
5697c478bd9Sstevel@tonic-gate break;
5707c478bd9Sstevel@tonic-gate }
5717c478bd9Sstevel@tonic-gate if (items == NULL)
572*65b0c20eSnakanon items = (tchar **)xcalloc(sizeof (items[1]),
5737c478bd9Sstevel@tonic-gate MAXITEMS+1);
5747c478bd9Sstevel@tonic-gate items[numitems] = (tchar *)xalloc((unsigned)(strlen_(entry) + 1) * sizeof (tchar));
5757c478bd9Sstevel@tonic-gate copyn(items[numitems], entry, MAXNAMLEN);
5767c478bd9Sstevel@tonic-gate numitems++;
5777c478bd9Sstevel@tonic-gate } else { /* RECOGNIZE command */
5787c478bd9Sstevel@tonic-gate if (ignoring && ignored(entry))
5797c478bd9Sstevel@tonic-gate nignored++;
5807c478bd9Sstevel@tonic-gate else if (recognize(extended_name,
5817c478bd9Sstevel@tonic-gate entry, name_length, ++numitems))
5827c478bd9Sstevel@tonic-gate break;
5837c478bd9Sstevel@tonic-gate }
5847c478bd9Sstevel@tonic-gate }
5857c478bd9Sstevel@tonic-gate if (ignoring && numitems == 0 && nignored > 0) {
5867c478bd9Sstevel@tonic-gate ignoring = FALSE;
5877c478bd9Sstevel@tonic-gate nignored = 0;
5887c478bd9Sstevel@tonic-gate if (looking_for_lognames)
5897c478bd9Sstevel@tonic-gate (void) setpwent();
5907c478bd9Sstevel@tonic-gate else
5917c478bd9Sstevel@tonic-gate rewinddir(dir_fd);
5927c478bd9Sstevel@tonic-gate goto again;
5937c478bd9Sstevel@tonic-gate }
5947c478bd9Sstevel@tonic-gate
5957c478bd9Sstevel@tonic-gate if (looking_for_lognames)
5967c478bd9Sstevel@tonic-gate (void) endpwent();
5977c478bd9Sstevel@tonic-gate else {
5987c478bd9Sstevel@tonic-gate unsetfd(dir_fd->dd_fd);
5997c478bd9Sstevel@tonic-gate closedir_(dir_fd);
6007c478bd9Sstevel@tonic-gate }
6017c478bd9Sstevel@tonic-gate if (command == RECOGNIZE && numitems > 0) {
6027c478bd9Sstevel@tonic-gate if (looking_for_lognames)
6037c478bd9Sstevel@tonic-gate copyn(word, S_TIL /* "~" */, 1);
6047c478bd9Sstevel@tonic-gate else
6057c478bd9Sstevel@tonic-gate /* put back dir part */
6067c478bd9Sstevel@tonic-gate copyn(word, dir, max_word_length);
6077c478bd9Sstevel@tonic-gate /* add extended name */
6087c478bd9Sstevel@tonic-gate catn(word, extended_name, max_word_length);
6097c478bd9Sstevel@tonic-gate return (numitems);
6107c478bd9Sstevel@tonic-gate }
6117c478bd9Sstevel@tonic-gate if (command == LIST) {
6127c478bd9Sstevel@tonic-gate qsort((char *)items, numitems, sizeof (items[1]),
6137c478bd9Sstevel@tonic-gate (int (*)(const void *, const void *))fcompare);
6147c478bd9Sstevel@tonic-gate /*
6157c478bd9Sstevel@tonic-gate * Never looking for commands in this version, so final
6167c478bd9Sstevel@tonic-gate * argument forced to 0. If command name completion is
6177c478bd9Sstevel@tonic-gate * reinstated, this must change.
6187c478bd9Sstevel@tonic-gate */
6197c478bd9Sstevel@tonic-gate print_by_column(looking_for_lognames ? NULL : tilded_dir,
6207c478bd9Sstevel@tonic-gate items, numitems, 0);
6217c478bd9Sstevel@tonic-gate if (items != NULL)
6227c478bd9Sstevel@tonic-gate FREE_ITEMS(items);
6237c478bd9Sstevel@tonic-gate }
6247c478bd9Sstevel@tonic-gate return (0);
6257c478bd9Sstevel@tonic-gate }
6267c478bd9Sstevel@tonic-gate
6277c478bd9Sstevel@tonic-gate /*
6287c478bd9Sstevel@tonic-gate * Object: extend what user typed up to an ambiguity.
6297c478bd9Sstevel@tonic-gate * Algorithm:
6307c478bd9Sstevel@tonic-gate * On first match, copy full entry (assume it'll be the only match)
6317c478bd9Sstevel@tonic-gate * On subsequent matches, shorten extended_name to the first
6327c478bd9Sstevel@tonic-gate * character mismatch between extended_name and entry.
6337c478bd9Sstevel@tonic-gate * If we shorten it back to the prefix length, stop searching.
6347c478bd9Sstevel@tonic-gate */
6356c02b4a4Smuffin int
recognize(tchar * extended_name,tchar * entry,int name_length,int numitems)6366c02b4a4Smuffin recognize(tchar *extended_name, tchar *entry, int name_length, int numitems)
6377c478bd9Sstevel@tonic-gate {
6387c478bd9Sstevel@tonic-gate
6397c478bd9Sstevel@tonic-gate #ifdef TRACE
6407c478bd9Sstevel@tonic-gate tprintf("TRACE- recognize()\n");
6417c478bd9Sstevel@tonic-gate #endif
6427c478bd9Sstevel@tonic-gate if (numitems == 1) /* 1st match */
6437c478bd9Sstevel@tonic-gate copyn(extended_name, entry, MAXNAMLEN);
6447c478bd9Sstevel@tonic-gate else { /* 2nd and subsequent matches */
6456c02b4a4Smuffin tchar *x, *ent;
6466c02b4a4Smuffin int len = 0;
6477c478bd9Sstevel@tonic-gate
6487c478bd9Sstevel@tonic-gate x = extended_name;
6497c478bd9Sstevel@tonic-gate for (ent = entry; *x && *x == *ent++; x++, len++)
6507c478bd9Sstevel@tonic-gate ;
6517c478bd9Sstevel@tonic-gate *x = '\0'; /* Shorten at 1st char diff */
6527c478bd9Sstevel@tonic-gate if (len == name_length) /* Ambiguous to prefix? */
6537c478bd9Sstevel@tonic-gate return (-1); /* So stop now and save time */
6547c478bd9Sstevel@tonic-gate }
6557c478bd9Sstevel@tonic-gate return (0);
6567c478bd9Sstevel@tonic-gate }
6577c478bd9Sstevel@tonic-gate
6587c478bd9Sstevel@tonic-gate /*
6597c478bd9Sstevel@tonic-gate * Return true if check items initial chars in template
6607c478bd9Sstevel@tonic-gate * This differs from PWB imatch in that if check is null
6617c478bd9Sstevel@tonic-gate * it items anything
6627c478bd9Sstevel@tonic-gate */
6636c02b4a4Smuffin static int
is_prefix(tchar * check,tchar * template)6646c02b4a4Smuffin is_prefix(tchar *check, tchar *template)
6657c478bd9Sstevel@tonic-gate {
6667c478bd9Sstevel@tonic-gate #ifdef TRACE
6677c478bd9Sstevel@tonic-gate tprintf("TRACE- is_prefix()\n");
6687c478bd9Sstevel@tonic-gate #endif
6697c478bd9Sstevel@tonic-gate
6707c478bd9Sstevel@tonic-gate do
6717c478bd9Sstevel@tonic-gate if (*check == 0)
6727c478bd9Sstevel@tonic-gate return (TRUE);
6737c478bd9Sstevel@tonic-gate while (*check++ == *template++);
6747c478bd9Sstevel@tonic-gate return (FALSE);
6757c478bd9Sstevel@tonic-gate }
6767c478bd9Sstevel@tonic-gate
6777c478bd9Sstevel@tonic-gate /*
6787c478bd9Sstevel@tonic-gate * Return true if the chars in template appear at the
6797c478bd9Sstevel@tonic-gate * end of check, i.e., are its suffix.
6807c478bd9Sstevel@tonic-gate */
6816c02b4a4Smuffin static int
is_suffix(tchar * check,tchar * template)6826c02b4a4Smuffin is_suffix(tchar *check, tchar *template)
6837c478bd9Sstevel@tonic-gate {
6846c02b4a4Smuffin tchar *c, *t;
6857c478bd9Sstevel@tonic-gate
6867c478bd9Sstevel@tonic-gate #ifdef TRACE
6877c478bd9Sstevel@tonic-gate tprintf("TRACE- is_suffix()\n");
6887c478bd9Sstevel@tonic-gate #endif
6897c478bd9Sstevel@tonic-gate for (c = check; *c++; )
6907c478bd9Sstevel@tonic-gate ;
6917c478bd9Sstevel@tonic-gate for (t = template; *t++; )
6927c478bd9Sstevel@tonic-gate ;
6937c478bd9Sstevel@tonic-gate for (;;) {
6947c478bd9Sstevel@tonic-gate if (t == template)
6957c478bd9Sstevel@tonic-gate return (TRUE);
6967c478bd9Sstevel@tonic-gate if (c == check || *--t != *--c)
6977c478bd9Sstevel@tonic-gate return (FALSE);
6987c478bd9Sstevel@tonic-gate }
6997c478bd9Sstevel@tonic-gate }
7007c478bd9Sstevel@tonic-gate
7016c02b4a4Smuffin int
tenex(tchar * inputline,int inputline_size)7026c02b4a4Smuffin tenex(tchar *inputline, int inputline_size)
7037c478bd9Sstevel@tonic-gate {
7046c02b4a4Smuffin int numitems, num_read, should_retype;
7057c478bd9Sstevel@tonic-gate int i;
7067c478bd9Sstevel@tonic-gate
7077c478bd9Sstevel@tonic-gate #ifdef TRACE
7087c478bd9Sstevel@tonic-gate tprintf("TRACE- tenex()\n");
7097c478bd9Sstevel@tonic-gate #endif
7107c478bd9Sstevel@tonic-gate setup_tty(ON);
7117c478bd9Sstevel@tonic-gate termchars();
7127c478bd9Sstevel@tonic-gate num_read = 0;
7137c478bd9Sstevel@tonic-gate should_retype = FALSE;
7147c478bd9Sstevel@tonic-gate while ((i = read_(SHIN, inputline+num_read, inputline_size-num_read))
7157c478bd9Sstevel@tonic-gate > 0) {
7167c478bd9Sstevel@tonic-gate static tchar *delims = S_DELIM /* " '\"\t;&<>()|`" */;
7176c02b4a4Smuffin tchar *str_end, *word_start, last_char;
7186c02b4a4Smuffin int space_left;
7197c478bd9Sstevel@tonic-gate struct termios tty;
7207c478bd9Sstevel@tonic-gate COMMAND command;
7217c478bd9Sstevel@tonic-gate
7227c478bd9Sstevel@tonic-gate num_read += i;
7237c478bd9Sstevel@tonic-gate inputline[num_read] = '\0';
7247c478bd9Sstevel@tonic-gate last_char = inputline[num_read - 1] & TRIM;
7257c478bd9Sstevel@tonic-gate
726*65b0c20eSnakanon /*
727*65b0c20eSnakanon * read_() can return more than requested size if there
728*65b0c20eSnakanon * is multibyte character at the end.
729*65b0c20eSnakanon */
730*65b0c20eSnakanon if ((num_read >= inputline_size) || (last_char == '\n'))
7317c478bd9Sstevel@tonic-gate break;
7327c478bd9Sstevel@tonic-gate
7337c478bd9Sstevel@tonic-gate str_end = &inputline[num_read];
7347c478bd9Sstevel@tonic-gate if (last_char == ESC) {
7357c478bd9Sstevel@tonic-gate command = RECOGNIZE;
7367c478bd9Sstevel@tonic-gate *--str_end = '\0'; /* wipe out trailing ESC */
7377c478bd9Sstevel@tonic-gate } else
7387c478bd9Sstevel@tonic-gate command = LIST;
7397c478bd9Sstevel@tonic-gate
7407c478bd9Sstevel@tonic-gate tty = tty_new;
7417c478bd9Sstevel@tonic-gate tty.c_lflag &= ~ECHO;
7427c478bd9Sstevel@tonic-gate (void) ioctl(SHIN, TCSETSF, (char *)&tty);
7437c478bd9Sstevel@tonic-gate
7447c478bd9Sstevel@tonic-gate if (command == LIST)
7457c478bd9Sstevel@tonic-gate printf("\n");
7467c478bd9Sstevel@tonic-gate /*
7477c478bd9Sstevel@tonic-gate * Find LAST occurence of a delimiter in the inputline.
7487c478bd9Sstevel@tonic-gate * The word start is one character past it.
7497c478bd9Sstevel@tonic-gate */
7507c478bd9Sstevel@tonic-gate for (word_start = str_end; word_start > inputline;
7517c478bd9Sstevel@tonic-gate --word_start) {
7527c478bd9Sstevel@tonic-gate if (index_(delims, word_start[-1]) ||
7537c478bd9Sstevel@tonic-gate isauxsp(word_start[-1]))
7547c478bd9Sstevel@tonic-gate break;
7557c478bd9Sstevel@tonic-gate }
7567c478bd9Sstevel@tonic-gate space_left = inputline_size - (word_start - inputline) - 1;
7577c478bd9Sstevel@tonic-gate numitems = search2(word_start, command, space_left);
7587c478bd9Sstevel@tonic-gate
7597c478bd9Sstevel@tonic-gate /*
7607c478bd9Sstevel@tonic-gate * Tabs in the input line cause trouble after a pushback.
7617c478bd9Sstevel@tonic-gate * tty driver won't backspace over them because column
7627c478bd9Sstevel@tonic-gate * positions are now incorrect. This is solved by retyping
7637c478bd9Sstevel@tonic-gate * over current line.
7647c478bd9Sstevel@tonic-gate */
7657c478bd9Sstevel@tonic-gate if (index_(inputline, '\t')) { /* tab tchar in input line? */
7667c478bd9Sstevel@tonic-gate back_to_col_1();
7677c478bd9Sstevel@tonic-gate should_retype = TRUE;
7687c478bd9Sstevel@tonic-gate }
7697c478bd9Sstevel@tonic-gate if (command == LIST) /* Always retype after a LIST */
7707c478bd9Sstevel@tonic-gate should_retype = TRUE;
7717c478bd9Sstevel@tonic-gate if (should_retype)
7727c478bd9Sstevel@tonic-gate printprompt();
7737c478bd9Sstevel@tonic-gate pushback(inputline, should_retype);
7747c478bd9Sstevel@tonic-gate num_read = 0; /* chars will be reread */
7757c478bd9Sstevel@tonic-gate should_retype = FALSE;
7767c478bd9Sstevel@tonic-gate
7777c478bd9Sstevel@tonic-gate /*
7787c478bd9Sstevel@tonic-gate * Avoid a race condition by echoing what we're recognized
7797c478bd9Sstevel@tonic-gate * _after_ pushing back the command line. This way, if the
7807c478bd9Sstevel@tonic-gate * user waits until seeing this output before typing more
7817c478bd9Sstevel@tonic-gate * stuff, the resulting keystrokes won't race with the STIed
7827c478bd9Sstevel@tonic-gate * input we've pushed back. (Of course, if the user types
7837c478bd9Sstevel@tonic-gate * ahead, the race still exists and it's quite possible that
7847c478bd9Sstevel@tonic-gate * the pushed back input line will interleave with the
7857c478bd9Sstevel@tonic-gate * keystrokes in unexpected ways.)
7867c478bd9Sstevel@tonic-gate */
7877c478bd9Sstevel@tonic-gate if (command == RECOGNIZE) {
7887c478bd9Sstevel@tonic-gate /* print from str_end on */
7897c478bd9Sstevel@tonic-gate print_recognized_stuff(str_end);
7907c478bd9Sstevel@tonic-gate if (numitems != 1) /* Beep = No match/ambiguous */
7917c478bd9Sstevel@tonic-gate beep();
7927c478bd9Sstevel@tonic-gate }
7937c478bd9Sstevel@tonic-gate }
7947c478bd9Sstevel@tonic-gate setup_tty(OFF);
7957c478bd9Sstevel@tonic-gate return (num_read);
7967c478bd9Sstevel@tonic-gate }
7977c478bd9Sstevel@tonic-gate
7986c02b4a4Smuffin static int
ignored(tchar * entry)7996c02b4a4Smuffin ignored(tchar *entry)
8007c478bd9Sstevel@tonic-gate {
8017c478bd9Sstevel@tonic-gate struct varent *vp;
8026c02b4a4Smuffin tchar **cp;
8037c478bd9Sstevel@tonic-gate
8047c478bd9Sstevel@tonic-gate #ifdef TRACE
8057c478bd9Sstevel@tonic-gate tprintf("TRACE- ignored()\n");
8067c478bd9Sstevel@tonic-gate #endif
8077c478bd9Sstevel@tonic-gate if ((vp = adrof(S_fignore /* "fignore" */)) == NULL ||
8087c478bd9Sstevel@tonic-gate (cp = vp->vec) == NULL)
8097c478bd9Sstevel@tonic-gate return (FALSE);
8107c478bd9Sstevel@tonic-gate for (; *cp != NULL; cp++)
8117c478bd9Sstevel@tonic-gate if (is_suffix(entry, *cp))
8127c478bd9Sstevel@tonic-gate return (TRUE);
8137c478bd9Sstevel@tonic-gate return (FALSE);
8147c478bd9Sstevel@tonic-gate }
8156c02b4a4Smuffin #endif /* FILEC */
816