1*9ccc37e3SMark Peek /* $Header: /p/tcsh/cvsroot/tcsh/sh.file.c,v 3.37 2010/02/09 20:21:49 christos Exp $ */ 2c80476e4SDavid E. O'Brien /* 3c80476e4SDavid E. O'Brien * sh.file.c: File completion for csh. This file is not used in tcsh. 4c80476e4SDavid E. O'Brien */ 5c80476e4SDavid E. O'Brien /*- 6c80476e4SDavid E. O'Brien * Copyright (c) 1980, 1991 The Regents of the University of California. 7c80476e4SDavid E. O'Brien * All rights reserved. 8c80476e4SDavid E. O'Brien * 9c80476e4SDavid E. O'Brien * Redistribution and use in source and binary forms, with or without 10c80476e4SDavid E. O'Brien * modification, are permitted provided that the following conditions 11c80476e4SDavid E. O'Brien * are met: 12c80476e4SDavid E. O'Brien * 1. Redistributions of source code must retain the above copyright 13c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer. 14c80476e4SDavid E. O'Brien * 2. Redistributions in binary form must reproduce the above copyright 15c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer in the 16c80476e4SDavid E. O'Brien * documentation and/or other materials provided with the distribution. 1729301572SMark Peek * 3. Neither the name of the University nor the names of its contributors 18c80476e4SDavid E. O'Brien * may be used to endorse or promote products derived from this software 19c80476e4SDavid E. O'Brien * without specific prior written permission. 20c80476e4SDavid E. O'Brien * 21c80476e4SDavid E. O'Brien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22c80476e4SDavid E. O'Brien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23c80476e4SDavid E. O'Brien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24c80476e4SDavid E. O'Brien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25c80476e4SDavid E. O'Brien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26c80476e4SDavid E. O'Brien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27c80476e4SDavid E. O'Brien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28c80476e4SDavid E. O'Brien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29c80476e4SDavid E. O'Brien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30c80476e4SDavid E. O'Brien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31c80476e4SDavid E. O'Brien * SUCH DAMAGE. 32c80476e4SDavid E. O'Brien */ 33c80476e4SDavid E. O'Brien #include "sh.h" 3429301572SMark Peek #include "ed.h" 35c80476e4SDavid E. O'Brien 36*9ccc37e3SMark Peek RCSID("$tcsh: sh.file.c,v 3.37 2010/02/09 20:21:49 christos Exp $") 37c80476e4SDavid E. O'Brien 3829301572SMark Peek #if defined(FILEC) && defined(TIOCSTI) 39c80476e4SDavid E. O'Brien 40c80476e4SDavid E. O'Brien /* 41c80476e4SDavid E. O'Brien * Tenex style file name recognition, .. and more. 42c80476e4SDavid E. O'Brien * History: 43c80476e4SDavid E. O'Brien * Author: Ken Greer, Sept. 1975, CMU. 44c80476e4SDavid E. O'Brien * Finally got around to adding to the Cshell., Ken Greer, Dec. 1981. 45c80476e4SDavid E. O'Brien */ 46c80476e4SDavid E. O'Brien 47c80476e4SDavid E. O'Brien #define ON 1 48c80476e4SDavid E. O'Brien #define OFF 0 49c80476e4SDavid E. O'Brien #ifndef TRUE 50c80476e4SDavid E. O'Brien #define TRUE 1 51c80476e4SDavid E. O'Brien #endif 52c80476e4SDavid E. O'Brien #ifndef FALSE 53c80476e4SDavid E. O'Brien #define FALSE 0 54c80476e4SDavid E. O'Brien #endif 55c80476e4SDavid E. O'Brien 56c80476e4SDavid E. O'Brien #define ESC CTL_ESC('\033') 57c80476e4SDavid E. O'Brien 58c80476e4SDavid E. O'Brien typedef enum { 59c80476e4SDavid E. O'Brien LIST, RECOGNIZE 60c80476e4SDavid E. O'Brien } COMMAND; 61c80476e4SDavid E. O'Brien 6245e5710bSMark Peek static void setup_tty (int); 6345e5710bSMark Peek static void back_to_col_1 (void); 6445e5710bSMark Peek static void pushback (const Char *); 6545e5710bSMark Peek static int filetype (const Char *, const Char *); 6645e5710bSMark Peek static void print_by_column (const Char *, Char *[], size_t); 6745e5710bSMark Peek static Char *tilde (const Char *); 6845e5710bSMark Peek static void retype (void); 6945e5710bSMark Peek static void beep (void); 7045e5710bSMark Peek static void print_recognized_stuff (const Char *); 7145e5710bSMark Peek static void extract_dir_and_name (const Char *, Char **, const Char **); 7245e5710bSMark Peek static Char *getitem (DIR *, int); 7345e5710bSMark Peek static size_t tsearch (Char *, COMMAND, size_t); 7445e5710bSMark Peek static int compare (const void *, const void *); 7545e5710bSMark Peek static int recognize (Char **, Char *, size_t, size_t); 7645e5710bSMark Peek static int is_prefix (const Char *, const Char *); 7745e5710bSMark Peek static int is_suffix (const Char *, const Char *); 7845e5710bSMark Peek static int ignored (const Char *); 79c80476e4SDavid E. O'Brien 80c80476e4SDavid E. O'Brien 81c80476e4SDavid E. O'Brien /* 82c80476e4SDavid E. O'Brien * Put this here so the binary can be patched with adb to enable file 83c80476e4SDavid E. O'Brien * completion by default. Filec controls completion, nobeep controls 84c80476e4SDavid E. O'Brien * ringing the terminal bell on incomplete expansions. 85c80476e4SDavid E. O'Brien */ 8623338178SMark Peek int filec = 0; 87c80476e4SDavid E. O'Brien 88c80476e4SDavid E. O'Brien static void 8945e5710bSMark Peek setup_tty(int on) 90c80476e4SDavid E. O'Brien { 91c80476e4SDavid E. O'Brien #ifdef TERMIO 92c80476e4SDavid E. O'Brien # ifdef POSIX 93c80476e4SDavid E. O'Brien struct termios tchars; 94c80476e4SDavid E. O'Brien # else 95c80476e4SDavid E. O'Brien struct termio tchars; 96c80476e4SDavid E. O'Brien # endif /* POSIX */ 97c80476e4SDavid E. O'Brien 98c80476e4SDavid E. O'Brien # ifdef POSIX 99c80476e4SDavid E. O'Brien (void) tcgetattr(SHIN, &tchars); 100c80476e4SDavid E. O'Brien # else 101c80476e4SDavid E. O'Brien (void) ioctl(SHIN, TCGETA, (ioctl_t) &tchars); 102c80476e4SDavid E. O'Brien # endif /* POSIX */ 103c80476e4SDavid E. O'Brien if (on) { 104c80476e4SDavid E. O'Brien tchars.c_cc[VEOL] = ESC; 105c80476e4SDavid E. O'Brien if (tchars.c_lflag & ICANON) 106c80476e4SDavid E. O'Brien # ifdef POSIX 107c80476e4SDavid E. O'Brien on = TCSADRAIN; 108c80476e4SDavid E. O'Brien # else 109c80476e4SDavid E. O'Brien on = TCSETA; 110c80476e4SDavid E. O'Brien # endif /* POSIX */ 111c80476e4SDavid E. O'Brien else { 112c80476e4SDavid E. O'Brien # ifdef POSIX 113c80476e4SDavid E. O'Brien on = TCSAFLUSH; 114c80476e4SDavid E. O'Brien # else 115c80476e4SDavid E. O'Brien on = TCSETAF; 116c80476e4SDavid E. O'Brien # endif /* POSIX */ 117c80476e4SDavid E. O'Brien tchars.c_lflag |= ICANON; 118c80476e4SDavid E. O'Brien 119c80476e4SDavid E. O'Brien } 120c80476e4SDavid E. O'Brien } 121c80476e4SDavid E. O'Brien else { 122c80476e4SDavid E. O'Brien tchars.c_cc[VEOL] = _POSIX_VDISABLE; 123c80476e4SDavid E. O'Brien # ifdef POSIX 124c80476e4SDavid E. O'Brien on = TCSADRAIN; 125c80476e4SDavid E. O'Brien # else 126c80476e4SDavid E. O'Brien on = TCSETA; 127c80476e4SDavid E. O'Brien # endif /* POSIX */ 128c80476e4SDavid E. O'Brien } 129c80476e4SDavid E. O'Brien # ifdef POSIX 13045e5710bSMark Peek (void) xtcsetattr(SHIN, on, &tchars); 131c80476e4SDavid E. O'Brien # else 132c80476e4SDavid E. O'Brien (void) ioctl(SHIN, on, (ioctl_t) &tchars); 133c80476e4SDavid E. O'Brien # endif /* POSIX */ 134c80476e4SDavid E. O'Brien #else 135c80476e4SDavid E. O'Brien struct sgttyb sgtty; 136c80476e4SDavid E. O'Brien static struct tchars tchars;/* INT, QUIT, XON, XOFF, EOF, BRK */ 137c80476e4SDavid E. O'Brien 138c80476e4SDavid E. O'Brien if (on) { 139c80476e4SDavid E. O'Brien (void) ioctl(SHIN, TIOCGETC, (ioctl_t) & tchars); 140c80476e4SDavid E. O'Brien tchars.t_brkc = ESC; 141c80476e4SDavid E. O'Brien (void) ioctl(SHIN, TIOCSETC, (ioctl_t) & tchars); 142c80476e4SDavid E. O'Brien /* 143c80476e4SDavid E. O'Brien * This must be done after every command: if the tty gets into raw or 144c80476e4SDavid E. O'Brien * cbreak mode the user can't even type 'reset'. 145c80476e4SDavid E. O'Brien */ 146c80476e4SDavid E. O'Brien (void) ioctl(SHIN, TIOCGETP, (ioctl_t) & sgtty); 147c80476e4SDavid E. O'Brien if (sgtty.sg_flags & (RAW | CBREAK)) { 148c80476e4SDavid E. O'Brien sgtty.sg_flags &= ~(RAW | CBREAK); 149c80476e4SDavid E. O'Brien (void) ioctl(SHIN, TIOCSETP, (ioctl_t) & sgtty); 150c80476e4SDavid E. O'Brien } 151c80476e4SDavid E. O'Brien } 152c80476e4SDavid E. O'Brien else { 153c80476e4SDavid E. O'Brien tchars.t_brkc = -1; 154c80476e4SDavid E. O'Brien (void) ioctl(SHIN, TIOCSETC, (ioctl_t) & tchars); 155c80476e4SDavid E. O'Brien } 156c80476e4SDavid E. O'Brien #endif /* TERMIO */ 157c80476e4SDavid E. O'Brien } 158c80476e4SDavid E. O'Brien 159c80476e4SDavid E. O'Brien /* 160c80476e4SDavid E. O'Brien * Move back to beginning of current line 161c80476e4SDavid E. O'Brien */ 162c80476e4SDavid E. O'Brien static void 16345e5710bSMark Peek back_to_col_1(void) 164c80476e4SDavid E. O'Brien { 165c80476e4SDavid E. O'Brien #ifdef TERMIO 166c80476e4SDavid E. O'Brien # ifdef POSIX 167c80476e4SDavid E. O'Brien struct termios tty, tty_normal; 168c80476e4SDavid E. O'Brien # else 169c80476e4SDavid E. O'Brien struct termio tty, tty_normal; 170c80476e4SDavid E. O'Brien # endif /* POSIX */ 171c80476e4SDavid E. O'Brien #else 172c80476e4SDavid E. O'Brien struct sgttyb tty, tty_normal; 173c80476e4SDavid E. O'Brien #endif /* TERMIO */ 174c80476e4SDavid E. O'Brien 17545e5710bSMark Peek pintr_disabled++; 17645e5710bSMark Peek cleanup_push(&pintr_disabled, disabled_cleanup); 177c80476e4SDavid E. O'Brien 178c80476e4SDavid E. O'Brien #ifdef TERMIO 179c80476e4SDavid E. O'Brien # ifdef POSIX 180c80476e4SDavid E. O'Brien (void) tcgetattr(SHOUT, &tty); 181c80476e4SDavid E. O'Brien # else 182c80476e4SDavid E. O'Brien (void) ioctl(SHOUT, TCGETA, (ioctl_t) &tty_normal); 183c80476e4SDavid E. O'Brien # endif /* POSIX */ 184c80476e4SDavid E. O'Brien tty_normal = tty; 185c80476e4SDavid E. O'Brien tty.c_iflag &= ~INLCR; 186c80476e4SDavid E. O'Brien tty.c_oflag &= ~ONLCR; 187c80476e4SDavid E. O'Brien # ifdef POSIX 18845e5710bSMark Peek (void) xtcsetattr(SHOUT, TCSANOW, &tty); 189c80476e4SDavid E. O'Brien # else 190c80476e4SDavid E. O'Brien (void) ioctl(SHOUT, TCSETAW, (ioctl_t) &tty); 191c80476e4SDavid E. O'Brien # endif /* POSIX */ 19245e5710bSMark Peek (void) xwrite(SHOUT, "\r", 1); 193c80476e4SDavid E. O'Brien # ifdef POSIX 19445e5710bSMark Peek (void) xtcsetattr(SHOUT, TCSANOW, &tty_normal); 195c80476e4SDavid E. O'Brien # else 196c80476e4SDavid E. O'Brien (void) ioctl(SHOUT, TCSETAW, (ioctl_t) &tty_normal); 197c80476e4SDavid E. O'Brien # endif /* POSIX */ 198c80476e4SDavid E. O'Brien #else 199c80476e4SDavid E. O'Brien (void) ioctl(SHIN, TIOCGETP, (ioctl_t) & tty); 200c80476e4SDavid E. O'Brien tty_normal = tty; 201c80476e4SDavid E. O'Brien tty.sg_flags &= ~CRMOD; 202c80476e4SDavid E. O'Brien (void) ioctl(SHIN, TIOCSETN, (ioctl_t) & tty); 20345e5710bSMark Peek (void) xwrite(SHOUT, "\r", 1); 204c80476e4SDavid E. O'Brien (void) ioctl(SHIN, TIOCSETN, (ioctl_t) & tty_normal); 205c80476e4SDavid E. O'Brien #endif /* TERMIO */ 206c80476e4SDavid E. O'Brien 20745e5710bSMark Peek cleanup_until(&pintr_disabled); 208c80476e4SDavid E. O'Brien } 209c80476e4SDavid E. O'Brien 210c80476e4SDavid E. O'Brien /* 211c80476e4SDavid E. O'Brien * Push string contents back into tty queue 212c80476e4SDavid E. O'Brien */ 213c80476e4SDavid E. O'Brien static void 21445e5710bSMark Peek pushback(const Char *string) 215c80476e4SDavid E. O'Brien { 21645e5710bSMark Peek const Char *p; 217c80476e4SDavid E. O'Brien #ifdef TERMIO 218c80476e4SDavid E. O'Brien # ifdef POSIX 219c80476e4SDavid E. O'Brien struct termios tty, tty_normal; 220c80476e4SDavid E. O'Brien # else 221c80476e4SDavid E. O'Brien struct termio tty, tty_normal; 222c80476e4SDavid E. O'Brien # endif /* POSIX */ 223c80476e4SDavid E. O'Brien #else 224c80476e4SDavid E. O'Brien struct sgttyb tty, tty_normal; 225c80476e4SDavid E. O'Brien #endif /* TERMIO */ 226c80476e4SDavid E. O'Brien 22745e5710bSMark Peek pintr_disabled++; 22845e5710bSMark Peek cleanup_push(&pintr_disabled, disabled_cleanup); 229c80476e4SDavid E. O'Brien 230c80476e4SDavid E. O'Brien #ifdef TERMIO 231c80476e4SDavid E. O'Brien # ifdef POSIX 232c80476e4SDavid E. O'Brien (void) tcgetattr(SHOUT, &tty); 233c80476e4SDavid E. O'Brien # else 234c80476e4SDavid E. O'Brien (void) ioctl(SHOUT, TCSETAW, (ioctl_t) &tty); 235c80476e4SDavid E. O'Brien # endif /* POSIX */ 236c80476e4SDavid E. O'Brien tty_normal = tty; 237a15e6f9aSMark Peek tty.c_lflag &= ~(ECHOKE | ECHO | ECHOE | ECHOK | ECHONL | 238a15e6f9aSMark Peek #ifndef __QNXNTO__ 239a15e6f9aSMark Peek ECHOPRT | 240a15e6f9aSMark Peek #endif 241a15e6f9aSMark Peek ECHOCTL); 242c80476e4SDavid E. O'Brien # ifdef POSIX 24345e5710bSMark Peek (void) xtcsetattr(SHOUT, TCSANOW, &tty); 244c80476e4SDavid E. O'Brien # else 245c80476e4SDavid E. O'Brien (void) ioctl(SHOUT, TCSETAW, (ioctl_t) &tty); 246c80476e4SDavid E. O'Brien # endif /* POSIX */ 247c80476e4SDavid E. O'Brien 24823338178SMark Peek for (p = string; *p != '\0'; p++) { 24923338178SMark Peek char buf[MB_LEN_MAX]; 25023338178SMark Peek size_t i, len; 25123338178SMark Peek 25223338178SMark Peek len = one_wctomb(buf, *p & CHAR); 25323338178SMark Peek for (i = 0; i < len; i++) 25423338178SMark Peek (void) ioctl(SHOUT, TIOCSTI, (ioctl_t) &buf[i]); 25523338178SMark Peek } 256c80476e4SDavid E. O'Brien # ifdef POSIX 25745e5710bSMark Peek (void) xtcsetattr(SHOUT, TCSANOW, &tty_normal); 258c80476e4SDavid E. O'Brien # else 259c80476e4SDavid E. O'Brien (void) ioctl(SHOUT, TCSETAW, (ioctl_t) &tty_normal); 260c80476e4SDavid E. O'Brien # endif /* POSIX */ 261c80476e4SDavid E. O'Brien #else 262c80476e4SDavid E. O'Brien (void) ioctl(SHOUT, TIOCGETP, (ioctl_t) & tty); 263c80476e4SDavid E. O'Brien tty_normal = tty; 264c80476e4SDavid E. O'Brien tty.sg_flags &= ~ECHO; 265c80476e4SDavid E. O'Brien (void) ioctl(SHOUT, TIOCSETN, (ioctl_t) & tty); 266c80476e4SDavid E. O'Brien 267c80476e4SDavid E. O'Brien for (p = string; c = *p; p++) 268c80476e4SDavid E. O'Brien (void) ioctl(SHOUT, TIOCSTI, (ioctl_t) & c); 269c80476e4SDavid E. O'Brien (void) ioctl(SHOUT, TIOCSETN, (ioctl_t) & tty_normal); 270c80476e4SDavid E. O'Brien #endif /* TERMIO */ 271c80476e4SDavid E. O'Brien 27245e5710bSMark Peek cleanup_until(&pintr_disabled); 273c80476e4SDavid E. O'Brien } 274c80476e4SDavid E. O'Brien 27523338178SMark Peek static int 27645e5710bSMark Peek filetype(const Char *dir, const Char *file) 277c80476e4SDavid E. O'Brien { 27845e5710bSMark Peek Char *path; 27945e5710bSMark Peek char *spath; 280c80476e4SDavid E. O'Brien struct stat statb; 281c80476e4SDavid E. O'Brien 28245e5710bSMark Peek path = Strspl(dir, file); 28345e5710bSMark Peek spath = short2str(path); 28445e5710bSMark Peek xfree(path); 28545e5710bSMark Peek if (lstat(spath, &statb) == 0) { 286c80476e4SDavid E. O'Brien switch (statb.st_mode & S_IFMT) { 287c80476e4SDavid E. O'Brien case S_IFDIR: 288c80476e4SDavid E. O'Brien return ('/'); 289c80476e4SDavid E. O'Brien 290c80476e4SDavid E. O'Brien case S_IFLNK: 29145e5710bSMark Peek if (stat(spath, &statb) == 0 && /* follow it out */ 292c80476e4SDavid E. O'Brien S_ISDIR(statb.st_mode)) 293c80476e4SDavid E. O'Brien return ('>'); 294c80476e4SDavid E. O'Brien else 295c80476e4SDavid E. O'Brien return ('@'); 296c80476e4SDavid E. O'Brien 297c80476e4SDavid E. O'Brien case S_IFSOCK: 298c80476e4SDavid E. O'Brien return ('='); 299c80476e4SDavid E. O'Brien 300c80476e4SDavid E. O'Brien default: 301c80476e4SDavid E. O'Brien if (statb.st_mode & 0111) 302c80476e4SDavid E. O'Brien return ('*'); 303c80476e4SDavid E. O'Brien } 304c80476e4SDavid E. O'Brien } 305c80476e4SDavid E. O'Brien return (' '); 306c80476e4SDavid E. O'Brien } 307c80476e4SDavid E. O'Brien 308c80476e4SDavid E. O'Brien /* 309c80476e4SDavid E. O'Brien * Print sorted down columns 310c80476e4SDavid E. O'Brien */ 311c80476e4SDavid E. O'Brien static void 31245e5710bSMark Peek print_by_column(const Char *dir, Char *items[], size_t count) 313c80476e4SDavid E. O'Brien { 31445e5710bSMark Peek struct winsize win; 31523338178SMark Peek size_t i; 31623338178SMark Peek int rows, r, c, maxwidth = 0, columns; 317c80476e4SDavid E. O'Brien 318c80476e4SDavid E. O'Brien if (ioctl(SHOUT, TIOCGWINSZ, (ioctl_t) & win) < 0 || win.ws_col == 0) 319c80476e4SDavid E. O'Brien win.ws_col = 80; 320c80476e4SDavid E. O'Brien for (i = 0; i < count; i++) 321c80476e4SDavid E. O'Brien maxwidth = maxwidth > (r = Strlen(items[i])) ? maxwidth : r; 322c80476e4SDavid E. O'Brien maxwidth += 2; /* for the file tag and space */ 323c80476e4SDavid E. O'Brien columns = win.ws_col / maxwidth; 324c80476e4SDavid E. O'Brien if (columns == 0) 325c80476e4SDavid E. O'Brien columns = 1; 326c80476e4SDavid E. O'Brien rows = (count + (columns - 1)) / columns; 327c80476e4SDavid E. O'Brien for (r = 0; r < rows; r++) { 328c80476e4SDavid E. O'Brien for (c = 0; c < columns; c++) { 329c80476e4SDavid E. O'Brien i = c * rows + r; 330c80476e4SDavid E. O'Brien if (i < count) { 33129301572SMark Peek int w; 332c80476e4SDavid E. O'Brien 333c80476e4SDavid E. O'Brien xprintf("%S", items[i]); 334c80476e4SDavid E. O'Brien xputchar(dir ? filetype(dir, items[i]) : ' '); 335c80476e4SDavid E. O'Brien if (c < columns - 1) { /* last column? */ 336c80476e4SDavid E. O'Brien w = Strlen(items[i]) + 1; 337c80476e4SDavid E. O'Brien for (; w < maxwidth; w++) 338c80476e4SDavid E. O'Brien xputchar(' '); 339c80476e4SDavid E. O'Brien } 340c80476e4SDavid E. O'Brien } 341c80476e4SDavid E. O'Brien } 342c80476e4SDavid E. O'Brien xputchar('\r'); 343c80476e4SDavid E. O'Brien xputchar('\n'); 344c80476e4SDavid E. O'Brien } 345c80476e4SDavid E. O'Brien } 346c80476e4SDavid E. O'Brien 347c80476e4SDavid E. O'Brien /* 348c80476e4SDavid E. O'Brien * Expand file name with possible tilde usage 349c80476e4SDavid E. O'Brien * ~person/mumble 350c80476e4SDavid E. O'Brien * expands to 351c80476e4SDavid E. O'Brien * home_directory_of_person/mumble 352c80476e4SDavid E. O'Brien */ 353c80476e4SDavid E. O'Brien static Char * 35445e5710bSMark Peek tilde(const Char *old) 355c80476e4SDavid E. O'Brien { 35645e5710bSMark Peek const Char *o, *home; 35729301572SMark Peek struct passwd *pw; 358c80476e4SDavid E. O'Brien 359c80476e4SDavid E. O'Brien if (old[0] != '~') 36045e5710bSMark Peek return (Strsave(old)); 36145e5710bSMark Peek old++; 362c80476e4SDavid E. O'Brien 36345e5710bSMark Peek for (o = old; *o != '\0' && *o != '/'; o++) 36445e5710bSMark Peek ; 36545e5710bSMark Peek if (o == old) 36645e5710bSMark Peek home = varval(STRhome); 367c80476e4SDavid E. O'Brien else { 36845e5710bSMark Peek Char *person; 36945e5710bSMark Peek 37045e5710bSMark Peek person = Strnsave(old, o - old); 37145e5710bSMark Peek pw = xgetpwnam(short2str(person)); 37245e5710bSMark Peek xfree(person); 373c80476e4SDavid E. O'Brien if (pw == NULL) 374c80476e4SDavid E. O'Brien return (NULL); 37545e5710bSMark Peek home = str2short(pw->pw_dir); 376c80476e4SDavid E. O'Brien } 37745e5710bSMark Peek return Strspl(home, o); 378c80476e4SDavid E. O'Brien } 379c80476e4SDavid E. O'Brien 380c80476e4SDavid E. O'Brien /* 381c80476e4SDavid E. O'Brien * Cause pending line to be printed 382c80476e4SDavid E. O'Brien */ 383c80476e4SDavid E. O'Brien static void 38445e5710bSMark Peek retype(void) 385c80476e4SDavid E. O'Brien { 386c80476e4SDavid E. O'Brien #ifdef TERMIO 387c80476e4SDavid E. O'Brien # ifdef POSIX 388c80476e4SDavid E. O'Brien struct termios tty; 389c80476e4SDavid E. O'Brien 390c80476e4SDavid E. O'Brien (void) tcgetattr(SHOUT, &tty); 391c80476e4SDavid E. O'Brien # else 392c80476e4SDavid E. O'Brien struct termio tty; 393c80476e4SDavid E. O'Brien 394c80476e4SDavid E. O'Brien (void) ioctl(SHOUT, TCGETA, (ioctl_t) &tty); 395c80476e4SDavid E. O'Brien # endif /* POSIX */ 396c80476e4SDavid E. O'Brien 397a15e6f9aSMark Peek #ifndef __QNXNTO__ 398c80476e4SDavid E. O'Brien tty.c_lflag |= PENDIN; 399a15e6f9aSMark Peek #endif 400c80476e4SDavid E. O'Brien 401c80476e4SDavid E. O'Brien # ifdef POSIX 40245e5710bSMark Peek (void) xtcsetattr(SHOUT, TCSANOW, &tty); 403c80476e4SDavid E. O'Brien # else 404c80476e4SDavid E. O'Brien (void) ioctl(SHOUT, TCSETAW, (ioctl_t) &tty); 405c80476e4SDavid E. O'Brien # endif /* POSIX */ 406c80476e4SDavid E. O'Brien #else 407c80476e4SDavid E. O'Brien int pending_input = LPENDIN; 408c80476e4SDavid E. O'Brien 409c80476e4SDavid E. O'Brien (void) ioctl(SHOUT, TIOCLBIS, (ioctl_t) & pending_input); 410c80476e4SDavid E. O'Brien #endif /* TERMIO */ 411c80476e4SDavid E. O'Brien } 412c80476e4SDavid E. O'Brien 413c80476e4SDavid E. O'Brien static void 41445e5710bSMark Peek beep(void) 415c80476e4SDavid E. O'Brien { 416c80476e4SDavid E. O'Brien if (adrof(STRnobeep) == 0) 4173b6eaa7bSAndrey A. Chernov #ifdef IS_ASCII 41845e5710bSMark Peek (void) xwrite(SHOUT, "\007", 1); 4193b6eaa7bSAndrey A. Chernov #else 420c80476e4SDavid E. O'Brien { 421c80476e4SDavid E. O'Brien unsigned char beep_ch = CTL_ESC('\007'); 42245e5710bSMark Peek (void) xwrite(SHOUT, &beep_ch, 1); 423c80476e4SDavid E. O'Brien } 4243b6eaa7bSAndrey A. Chernov #endif 425c80476e4SDavid E. O'Brien } 426c80476e4SDavid E. O'Brien 427c80476e4SDavid E. O'Brien /* 428c80476e4SDavid E. O'Brien * Erase that silly ^[ and 429c80476e4SDavid E. O'Brien * print the recognized part of the string 430c80476e4SDavid E. O'Brien */ 431c80476e4SDavid E. O'Brien static void 43245e5710bSMark Peek print_recognized_stuff(const Char *recognized_part) 433c80476e4SDavid E. O'Brien { 434c80476e4SDavid E. O'Brien /* An optimized erasing of that silly ^[ */ 435c80476e4SDavid E. O'Brien (void) putraw('\b'); 436c80476e4SDavid E. O'Brien (void) putraw('\b'); 437c80476e4SDavid E. O'Brien switch (Strlen(recognized_part)) { 438c80476e4SDavid E. O'Brien 439c80476e4SDavid E. O'Brien case 0: /* erase two Characters: ^[ */ 440c80476e4SDavid E. O'Brien (void) putraw(' '); 441c80476e4SDavid E. O'Brien (void) putraw(' '); 442c80476e4SDavid E. O'Brien (void) putraw('\b'); 443c80476e4SDavid E. O'Brien (void) putraw('\b'); 444c80476e4SDavid E. O'Brien break; 445c80476e4SDavid E. O'Brien 446c80476e4SDavid E. O'Brien case 1: /* overstrike the ^, erase the [ */ 447c80476e4SDavid E. O'Brien xprintf("%S", recognized_part); 448c80476e4SDavid E. O'Brien (void) putraw(' '); 449c80476e4SDavid E. O'Brien (void) putraw('\b'); 450c80476e4SDavid E. O'Brien break; 451c80476e4SDavid E. O'Brien 452c80476e4SDavid E. O'Brien default: /* overstrike both Characters ^[ */ 453c80476e4SDavid E. O'Brien xprintf("%S", recognized_part); 454c80476e4SDavid E. O'Brien break; 455c80476e4SDavid E. O'Brien } 456c80476e4SDavid E. O'Brien flush(); 457c80476e4SDavid E. O'Brien } 458c80476e4SDavid E. O'Brien 459c80476e4SDavid E. O'Brien /* 460c80476e4SDavid E. O'Brien * Parse full path in file into 2 parts: directory and file names 461c80476e4SDavid E. O'Brien * Should leave final slash (/) at end of dir. 462c80476e4SDavid E. O'Brien */ 463c80476e4SDavid E. O'Brien static void 46445e5710bSMark Peek extract_dir_and_name(const Char *path, Char **dir, const Char **name) 465c80476e4SDavid E. O'Brien { 46645e5710bSMark Peek const Char *p; 467c80476e4SDavid E. O'Brien 468c80476e4SDavid E. O'Brien p = Strrchr(path, '/'); 46945e5710bSMark Peek if (p == NULL) 47045e5710bSMark Peek p = path; 47145e5710bSMark Peek else 47245e5710bSMark Peek p++; 47345e5710bSMark Peek *name = p; 47445e5710bSMark Peek *dir = Strnsave(path, p - path); 475c80476e4SDavid E. O'Brien } 47623338178SMark Peek 477c80476e4SDavid E. O'Brien static Char * 47845e5710bSMark Peek getitem(DIR *dir_fd, int looking_for_lognames) 479c80476e4SDavid E. O'Brien { 48029301572SMark Peek struct passwd *pw; 48129301572SMark Peek struct dirent *dirp; 482c80476e4SDavid E. O'Brien 483c80476e4SDavid E. O'Brien if (looking_for_lognames) { 48423338178SMark Peek #ifndef HAVE_GETPWENT 485c80476e4SDavid E. O'Brien return (NULL); 486c80476e4SDavid E. O'Brien #else 487c80476e4SDavid E. O'Brien if ((pw = getpwent()) == NULL) 488c80476e4SDavid E. O'Brien return (NULL); 489c80476e4SDavid E. O'Brien return (str2short(pw->pw_name)); 490c80476e4SDavid E. O'Brien #endif /* atp vmsposix */ 491c80476e4SDavid E. O'Brien } 49229301572SMark Peek if ((dirp = readdir(dir_fd)) != NULL) 493c80476e4SDavid E. O'Brien return (str2short(dirp->d_name)); 494c80476e4SDavid E. O'Brien return (NULL); 495c80476e4SDavid E. O'Brien } 496c80476e4SDavid E. O'Brien 497c80476e4SDavid E. O'Brien /* 498c80476e4SDavid E. O'Brien * Perform a RECOGNIZE or LIST command on string "word". 499c80476e4SDavid E. O'Brien */ 50045e5710bSMark Peek static size_t 50145e5710bSMark Peek tsearch(Char *word, COMMAND command, size_t max_word_length) 502c80476e4SDavid E. O'Brien { 50329301572SMark Peek DIR *dir_fd; 50423338178SMark Peek int ignoring = TRUE, nignored = 0; 50545e5710bSMark Peek int looking_for_lognames; 50645e5710bSMark Peek Char *tilded_dir = NULL, *dir = NULL; 50745e5710bSMark Peek Char *extended_name = NULL; 50845e5710bSMark Peek const Char *name; 509c80476e4SDavid E. O'Brien Char *item; 51045e5710bSMark Peek struct blk_buf items = BLK_BUF_INIT; 51145e5710bSMark Peek size_t name_length; 512c80476e4SDavid E. O'Brien 513c80476e4SDavid E. O'Brien looking_for_lognames = (*word == '~') && (Strchr(word, '/') == NULL); 514c80476e4SDavid E. O'Brien if (looking_for_lognames) { 51523338178SMark Peek #ifdef HAVE_GETPWENT 516c80476e4SDavid E. O'Brien (void) setpwent(); 51723338178SMark Peek #endif 51845e5710bSMark Peek name = word + 1; /* name sans ~ */ 519c80476e4SDavid E. O'Brien dir_fd = NULL; 52045e5710bSMark Peek cleanup_push(dir, xfree); 521c80476e4SDavid E. O'Brien } 522c80476e4SDavid E. O'Brien else { 52345e5710bSMark Peek extract_dir_and_name(word, &dir, &name); 52445e5710bSMark Peek cleanup_push(dir, xfree); 52545e5710bSMark Peek tilded_dir = tilde(dir); 52645e5710bSMark Peek if (tilded_dir == NULL) 52745e5710bSMark Peek goto end; 52845e5710bSMark Peek cleanup_push(tilded_dir, xfree); 529c80476e4SDavid E. O'Brien dir_fd = opendir(*tilded_dir ? short2str(tilded_dir) : "."); 530c80476e4SDavid E. O'Brien if (dir_fd == NULL) 53145e5710bSMark Peek goto end; 532c80476e4SDavid E. O'Brien } 533c80476e4SDavid E. O'Brien 534c80476e4SDavid E. O'Brien name_length = Strlen(name); 53545e5710bSMark Peek cleanup_push(&extended_name, xfree_indirect); 53645e5710bSMark Peek cleanup_push(&items, bb_cleanup); 53745e5710bSMark Peek again: /* search for matches */ 53845e5710bSMark Peek while ((item = getitem(dir_fd, looking_for_lognames)) != NULL) { 539c80476e4SDavid E. O'Brien if (!is_prefix(name, item)) 540c80476e4SDavid E. O'Brien continue; 541c80476e4SDavid E. O'Brien /* Don't match . files on null prefix match */ 542c80476e4SDavid E. O'Brien if (name_length == 0 && item[0] == '.' && 543c80476e4SDavid E. O'Brien !looking_for_lognames) 544c80476e4SDavid E. O'Brien continue; 54545e5710bSMark Peek if (command == LIST) 54645e5710bSMark Peek bb_append(&items, Strsave(item)); 547c80476e4SDavid E. O'Brien else { /* RECOGNIZE command */ 548c80476e4SDavid E. O'Brien if (ignoring && ignored(item)) 549c80476e4SDavid E. O'Brien nignored++; 55045e5710bSMark Peek else if (recognize(&extended_name, item, name_length, ++items.len)) 551c80476e4SDavid E. O'Brien break; 552c80476e4SDavid E. O'Brien } 553c80476e4SDavid E. O'Brien } 55445e5710bSMark Peek if (ignoring && items.len == 0 && nignored > 0) { 555c80476e4SDavid E. O'Brien ignoring = FALSE; 556c80476e4SDavid E. O'Brien nignored = 0; 55723338178SMark Peek if (looking_for_lognames) { 55823338178SMark Peek #ifdef HAVE_GETPWENT 559c80476e4SDavid E. O'Brien (void) setpwent(); 560c80476e4SDavid E. O'Brien #endif /* atp vmsposix */ 56123338178SMark Peek } else 562c80476e4SDavid E. O'Brien rewinddir(dir_fd); 563c80476e4SDavid E. O'Brien goto again; 564c80476e4SDavid E. O'Brien } 565c80476e4SDavid E. O'Brien 56623338178SMark Peek if (looking_for_lognames) { 56723338178SMark Peek #ifndef HAVE_GETPWENT 568c80476e4SDavid E. O'Brien (void) endpwent(); 56923338178SMark Peek #endif 57023338178SMark Peek } else 57145e5710bSMark Peek xclosedir(dir_fd); 57245e5710bSMark Peek if (items.len != 0) { 573c80476e4SDavid E. O'Brien if (command == RECOGNIZE) { 574c80476e4SDavid E. O'Brien if (looking_for_lognames) 57545e5710bSMark Peek copyn(word, STRtilde, 2);/*FIXBUF, sort of */ 576c80476e4SDavid E. O'Brien else 577c80476e4SDavid E. O'Brien /* put back dir part */ 57845e5710bSMark Peek copyn(word, dir, max_word_length);/*FIXBUF*/ 579c80476e4SDavid E. O'Brien /* add extended name */ 58045e5710bSMark Peek catn(word, extended_name, max_word_length);/*FIXBUF*/ 581c80476e4SDavid E. O'Brien } 582c80476e4SDavid E. O'Brien else { /* LIST */ 58345e5710bSMark Peek qsort(items.vec, items.len, sizeof(items.vec[0]), compare); 584c80476e4SDavid E. O'Brien print_by_column(looking_for_lognames ? NULL : tilded_dir, 58545e5710bSMark Peek items.vec, items.len); 586c80476e4SDavid E. O'Brien } 58745e5710bSMark Peek } 58845e5710bSMark Peek end: 58945e5710bSMark Peek cleanup_until(dir); 59045e5710bSMark Peek return items.len; 591c80476e4SDavid E. O'Brien } 592c80476e4SDavid E. O'Brien 59329301572SMark Peek 59429301572SMark Peek static int 59545e5710bSMark Peek compare(const void *p, const void *q) 59629301572SMark Peek { 597*9ccc37e3SMark Peek #if defined (WIDE_STRINGS) && !defined (UTF16_STRING) 59823338178SMark Peek errno = 0; 59923338178SMark Peek 60045e5710bSMark Peek return (wcscoll(*(Char *const *) p, *(Char *const *) q)); 60123338178SMark Peek #else 60223338178SMark Peek char *p1, *q1; 60323338178SMark Peek int res; 60423338178SMark Peek 60545e5710bSMark Peek p1 = strsave(short2str(*(Char *const *) p)); 60645e5710bSMark Peek q1 = strsave(short2str(*(Char *const *) q)); 60745e5710bSMark Peek # if defined(NLS) && defined(HAVE_STRCOLL) 60823338178SMark Peek res = strcoll(p1, q1); 60929301572SMark Peek # else 61023338178SMark Peek res = strcmp(p1, q1); 61145e5710bSMark Peek # endif /* NLS && HAVE_STRCOLL */ 61223338178SMark Peek xfree (p1); 61323338178SMark Peek xfree (q1); 61423338178SMark Peek return res; 61523338178SMark Peek #endif /* not WIDE_STRINGS */ 61629301572SMark Peek } 61729301572SMark Peek 618c80476e4SDavid E. O'Brien /* 619c80476e4SDavid E. O'Brien * Object: extend what user typed up to an ambiguity. 620c80476e4SDavid E. O'Brien * Algorithm: 621c80476e4SDavid E. O'Brien * On first match, copy full item (assume it'll be the only match) 622c80476e4SDavid E. O'Brien * On subsequent matches, shorten extended_name to the first 623c80476e4SDavid E. O'Brien * Character mismatch between extended_name and item. 624c80476e4SDavid E. O'Brien * If we shorten it back to the prefix length, stop searching. 625c80476e4SDavid E. O'Brien */ 626c80476e4SDavid E. O'Brien static int 62745e5710bSMark Peek recognize(Char **extended_name, Char *item, size_t name_length, 62845e5710bSMark Peek size_t numitems) 629c80476e4SDavid E. O'Brien { 630c80476e4SDavid E. O'Brien if (numitems == 1) /* 1st match */ 63145e5710bSMark Peek *extended_name = Strsave(item); 632c80476e4SDavid E. O'Brien else { /* 2nd & subsequent matches */ 63329301572SMark Peek Char *x, *ent; 63445e5710bSMark Peek size_t len = 0; 635c80476e4SDavid E. O'Brien 63645e5710bSMark Peek x = *extended_name; 637c80476e4SDavid E. O'Brien for (ent = item; *x && *x == *ent++; x++, len++); 638c80476e4SDavid E. O'Brien *x = '\0'; /* Shorten at 1st Char diff */ 639c80476e4SDavid E. O'Brien if (len == name_length) /* Ambiguous to prefix? */ 640c80476e4SDavid E. O'Brien return (-1); /* So stop now and save time */ 641c80476e4SDavid E. O'Brien } 642c80476e4SDavid E. O'Brien return (0); 643c80476e4SDavid E. O'Brien } 644c80476e4SDavid E. O'Brien 645c80476e4SDavid E. O'Brien /* 646c80476e4SDavid E. O'Brien * Return true if check matches initial Chars in template. 647c80476e4SDavid E. O'Brien * This differs from PWB imatch in that if check is null 648c80476e4SDavid E. O'Brien * it matches anything. 649c80476e4SDavid E. O'Brien */ 650c80476e4SDavid E. O'Brien static int 65145e5710bSMark Peek is_prefix(const Char *check, const Char *template) 652c80476e4SDavid E. O'Brien { 653c80476e4SDavid E. O'Brien do 654c80476e4SDavid E. O'Brien if (*check == 0) 655c80476e4SDavid E. O'Brien return (TRUE); 656c80476e4SDavid E. O'Brien while (*check++ == *template++); 657c80476e4SDavid E. O'Brien return (FALSE); 658c80476e4SDavid E. O'Brien } 659c80476e4SDavid E. O'Brien 660c80476e4SDavid E. O'Brien /* 661c80476e4SDavid E. O'Brien * Return true if the Chars in template appear at the 662c80476e4SDavid E. O'Brien * end of check, I.e., are it's suffix. 663c80476e4SDavid E. O'Brien */ 664c80476e4SDavid E. O'Brien static int 66545e5710bSMark Peek is_suffix(const Char *check, const Char *template) 666c80476e4SDavid E. O'Brien { 66745e5710bSMark Peek const Char *c, *t; 668c80476e4SDavid E. O'Brien 669c80476e4SDavid E. O'Brien for (c = check; *c++;); 670c80476e4SDavid E. O'Brien for (t = template; *t++;); 671c80476e4SDavid E. O'Brien for (;;) { 672c80476e4SDavid E. O'Brien if (t == template) 673c80476e4SDavid E. O'Brien return 1; 674c80476e4SDavid E. O'Brien if (c == check || *--t != *--c) 675c80476e4SDavid E. O'Brien return 0; 676c80476e4SDavid E. O'Brien } 677c80476e4SDavid E. O'Brien } 678c80476e4SDavid E. O'Brien 67945e5710bSMark Peek static void 68045e5710bSMark Peek setup_tty_cleanup(void *dummy) 681c80476e4SDavid E. O'Brien { 68245e5710bSMark Peek USE(dummy); 68345e5710bSMark Peek setup_tty(OFF); 68445e5710bSMark Peek } 685c80476e4SDavid E. O'Brien 68645e5710bSMark Peek size_t 68745e5710bSMark Peek tenex(Char *inputline, size_t inputline_size) 68845e5710bSMark Peek { 68945e5710bSMark Peek size_t numitems; 69045e5710bSMark Peek ssize_t num_read; 69145e5710bSMark Peek char tinputline[BUFSIZE + 1];/*FIXBUF*/ 692c80476e4SDavid E. O'Brien 693c80476e4SDavid E. O'Brien setup_tty(ON); 69445e5710bSMark Peek cleanup_push(&num_read, setup_tty_cleanup); /* num_read is only a marker */ 695c80476e4SDavid E. O'Brien 69645e5710bSMark Peek while ((num_read = xread(SHIN, tinputline, BUFSIZE)) > 0) {/*FIXBUF*/ 69745e5710bSMark Peek static const Char delims[] = {' ', '\'', '"', '\t', ';', '&', '<', 698c80476e4SDavid E. O'Brien '>', '(', ')', '|', '^', '%', '\0'}; 69929301572SMark Peek Char *str_end, *word_start, last_Char, should_retype; 70045e5710bSMark Peek size_t space_left; 701c80476e4SDavid E. O'Brien COMMAND command; 702c80476e4SDavid E. O'Brien 70323338178SMark Peek tinputline[num_read] = 0; 70445e5710bSMark Peek Strcpy(inputline, str2short(tinputline));/*FIXBUF*/ 70523338178SMark Peek num_read = Strlen(inputline); 70645e5710bSMark Peek last_Char = CTL_ESC(ASC(inputline[num_read - 1]) & ASCII); 707c80476e4SDavid E. O'Brien 70845e5710bSMark Peek if (last_Char == '\n' || (size_t)num_read == inputline_size) 709c80476e4SDavid E. O'Brien break; 710c80476e4SDavid E. O'Brien command = (last_Char == ESC) ? RECOGNIZE : LIST; 711c80476e4SDavid E. O'Brien if (command == LIST) 712c80476e4SDavid E. O'Brien xputchar('\n'); 713c80476e4SDavid E. O'Brien str_end = &inputline[num_read]; 714c80476e4SDavid E. O'Brien if (last_Char == ESC) 715c80476e4SDavid E. O'Brien --str_end; /* wipeout trailing cmd Char */ 716c80476e4SDavid E. O'Brien *str_end = '\0'; 717c80476e4SDavid E. O'Brien /* 718c80476e4SDavid E. O'Brien * Find LAST occurence of a delimiter in the inputline. The word start 719c80476e4SDavid E. O'Brien * is one Character past it. 720c80476e4SDavid E. O'Brien */ 721c80476e4SDavid E. O'Brien for (word_start = str_end; word_start > inputline; --word_start) 722c80476e4SDavid E. O'Brien if (Strchr(delims, word_start[-1])) 723c80476e4SDavid E. O'Brien break; 724c80476e4SDavid E. O'Brien space_left = inputline_size - (word_start - inputline) - 1; 725c80476e4SDavid E. O'Brien numitems = tsearch(word_start, command, space_left); 726c80476e4SDavid E. O'Brien 727c80476e4SDavid E. O'Brien if (command == RECOGNIZE) { 728c80476e4SDavid E. O'Brien /* print from str_end on */ 729c80476e4SDavid E. O'Brien print_recognized_stuff(str_end); 730c80476e4SDavid E. O'Brien if (numitems != 1) /* Beep = No match/ambiguous */ 731c80476e4SDavid E. O'Brien beep(); 732c80476e4SDavid E. O'Brien } 733c80476e4SDavid E. O'Brien 734c80476e4SDavid E. O'Brien /* 735c80476e4SDavid E. O'Brien * Tabs in the input line cause trouble after a pushback. tty driver 736c80476e4SDavid E. O'Brien * won't backspace over them because column positions are now 737c80476e4SDavid E. O'Brien * incorrect. This is solved by retyping over current line. 738c80476e4SDavid E. O'Brien */ 739c80476e4SDavid E. O'Brien should_retype = FALSE; 740c80476e4SDavid E. O'Brien if (Strchr(inputline, '\t')) { /* tab Char in input line? */ 741c80476e4SDavid E. O'Brien back_to_col_1(); 742c80476e4SDavid E. O'Brien should_retype = TRUE; 743c80476e4SDavid E. O'Brien } 744c80476e4SDavid E. O'Brien if (command == LIST) /* Always retype after a LIST */ 745c80476e4SDavid E. O'Brien should_retype = TRUE; 746c80476e4SDavid E. O'Brien if (should_retype) 747c80476e4SDavid E. O'Brien printprompt(0, NULL); 748c80476e4SDavid E. O'Brien pushback(inputline); 749c80476e4SDavid E. O'Brien if (should_retype) 750c80476e4SDavid E. O'Brien retype(); 751c80476e4SDavid E. O'Brien } 75245e5710bSMark Peek cleanup_until(&num_read); 753c80476e4SDavid E. O'Brien return (num_read); 754c80476e4SDavid E. O'Brien } 755c80476e4SDavid E. O'Brien 756c80476e4SDavid E. O'Brien static int 75745e5710bSMark Peek ignored(const Char *item) 758c80476e4SDavid E. O'Brien { 759c80476e4SDavid E. O'Brien struct varent *vp; 76029301572SMark Peek Char **cp; 761c80476e4SDavid E. O'Brien 762c80476e4SDavid E. O'Brien if ((vp = adrof(STRfignore)) == NULL || (cp = vp->vec) == NULL) 763c80476e4SDavid E. O'Brien return (FALSE); 764c80476e4SDavid E. O'Brien for (; *cp != NULL; cp++) 765c80476e4SDavid E. O'Brien if (is_suffix(item, *cp)) 766c80476e4SDavid E. O'Brien return (TRUE); 767c80476e4SDavid E. O'Brien return (FALSE); 768c80476e4SDavid E. O'Brien } 76929301572SMark Peek #endif /* FILEC && TIOCSTI */ 770