1c80476e4SDavid E. O'Brien /* $Header: /src/pub/tcsh/sh.file.c,v 3.15 1997/10/02 16:36:29 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. 17c80476e4SDavid E. O'Brien * 3. All advertising materials mentioning features or use of this software 18c80476e4SDavid E. O'Brien * must display the following acknowledgement: 19c80476e4SDavid E. O'Brien * This product includes software developed by the University of 20c80476e4SDavid E. O'Brien * California, Berkeley and its contributors. 21c80476e4SDavid E. O'Brien * 4. Neither the name of the University nor the names of its contributors 22c80476e4SDavid E. O'Brien * may be used to endorse or promote products derived from this software 23c80476e4SDavid E. O'Brien * without specific prior written permission. 24c80476e4SDavid E. O'Brien * 25c80476e4SDavid E. O'Brien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26c80476e4SDavid E. O'Brien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27c80476e4SDavid E. O'Brien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28c80476e4SDavid E. O'Brien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29c80476e4SDavid E. O'Brien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30c80476e4SDavid E. O'Brien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31c80476e4SDavid E. O'Brien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32c80476e4SDavid E. O'Brien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33c80476e4SDavid E. O'Brien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34c80476e4SDavid E. O'Brien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35c80476e4SDavid E. O'Brien * SUCH DAMAGE. 36c80476e4SDavid E. O'Brien */ 37c80476e4SDavid E. O'Brien #include "sh.h" 38c80476e4SDavid E. O'Brien 39c80476e4SDavid E. O'Brien RCSID("$Id: sh.file.c,v 3.15 1997/10/02 16:36:29 christos Exp $") 40c80476e4SDavid E. O'Brien 41c80476e4SDavid E. O'Brien #ifdef FILEC 42c80476e4SDavid E. O'Brien 43c80476e4SDavid E. O'Brien /* 44c80476e4SDavid E. O'Brien * Tenex style file name recognition, .. and more. 45c80476e4SDavid E. O'Brien * History: 46c80476e4SDavid E. O'Brien * Author: Ken Greer, Sept. 1975, CMU. 47c80476e4SDavid E. O'Brien * Finally got around to adding to the Cshell., Ken Greer, Dec. 1981. 48c80476e4SDavid E. O'Brien */ 49c80476e4SDavid E. O'Brien 50c80476e4SDavid E. O'Brien #define ON 1 51c80476e4SDavid E. O'Brien #define OFF 0 52c80476e4SDavid E. O'Brien #ifndef TRUE 53c80476e4SDavid E. O'Brien #define TRUE 1 54c80476e4SDavid E. O'Brien #endif 55c80476e4SDavid E. O'Brien #ifndef FALSE 56c80476e4SDavid E. O'Brien #define FALSE 0 57c80476e4SDavid E. O'Brien #endif 58c80476e4SDavid E. O'Brien 59c80476e4SDavid E. O'Brien #define ESC CTL_ESC('\033') 60c80476e4SDavid E. O'Brien 61c80476e4SDavid E. O'Brien typedef enum { 62c80476e4SDavid E. O'Brien LIST, RECOGNIZE 63c80476e4SDavid E. O'Brien } COMMAND; 64c80476e4SDavid E. O'Brien 65c80476e4SDavid E. O'Brien static void setup_tty __P((int)); 66c80476e4SDavid E. O'Brien static void back_to_col_1 __P((void)); 67c80476e4SDavid E. O'Brien static void pushback __P((Char *)); 68c80476e4SDavid E. O'Brien static void catn __P((Char *, Char *, int)); 69c80476e4SDavid E. O'Brien static void copyn __P((Char *, Char *, int)); 70c80476e4SDavid E. O'Brien static Char filetype __P((Char *, Char *)); 71c80476e4SDavid E. O'Brien static void print_by_column __P((Char *, Char *[], int)); 72c80476e4SDavid E. O'Brien static Char *tilde __P((Char *, Char *)); 73c80476e4SDavid E. O'Brien static void retype __P((void)); 74c80476e4SDavid E. O'Brien static void beep __P((void)); 75c80476e4SDavid E. O'Brien static void print_recognized_stuff __P((Char *)); 76c80476e4SDavid E. O'Brien static void extract_dir_and_name __P((Char *, Char *, Char *)); 77c80476e4SDavid E. O'Brien static Char *getitem __P((DIR *, int)); 78c80476e4SDavid E. O'Brien static void free_items __P((Char **)); 79c80476e4SDavid E. O'Brien static int tsearch __P((Char *, COMMAND, int)); 80c80476e4SDavid E. O'Brien static int recognize __P((Char *, Char *, int, int)); 81c80476e4SDavid E. O'Brien static int is_prefix __P((Char *, Char *)); 82c80476e4SDavid E. O'Brien static int is_suffix __P((Char *, Char *)); 83c80476e4SDavid E. O'Brien static int ignored __P((Char *)); 84c80476e4SDavid E. O'Brien 85c80476e4SDavid E. O'Brien 86c80476e4SDavid E. O'Brien /* 87c80476e4SDavid E. O'Brien * Put this here so the binary can be patched with adb to enable file 88c80476e4SDavid E. O'Brien * completion by default. Filec controls completion, nobeep controls 89c80476e4SDavid E. O'Brien * ringing the terminal bell on incomplete expansions. 90c80476e4SDavid E. O'Brien */ 91c80476e4SDavid E. O'Brien bool filec = 0; 92c80476e4SDavid E. O'Brien 93c80476e4SDavid E. O'Brien static void 94c80476e4SDavid E. O'Brien setup_tty(on) 95c80476e4SDavid E. O'Brien int on; 96c80476e4SDavid E. O'Brien { 97c80476e4SDavid E. O'Brien #ifdef TERMIO 98c80476e4SDavid E. O'Brien # ifdef POSIX 99c80476e4SDavid E. O'Brien struct termios tchars; 100c80476e4SDavid E. O'Brien # else 101c80476e4SDavid E. O'Brien struct termio tchars; 102c80476e4SDavid E. O'Brien # endif /* POSIX */ 103c80476e4SDavid E. O'Brien 104c80476e4SDavid E. O'Brien # ifdef POSIX 105c80476e4SDavid E. O'Brien (void) tcgetattr(SHIN, &tchars); 106c80476e4SDavid E. O'Brien # else 107c80476e4SDavid E. O'Brien (void) ioctl(SHIN, TCGETA, (ioctl_t) &tchars); 108c80476e4SDavid E. O'Brien # endif /* POSIX */ 109c80476e4SDavid E. O'Brien if (on) { 110c80476e4SDavid E. O'Brien tchars.c_cc[VEOL] = ESC; 111c80476e4SDavid E. O'Brien if (tchars.c_lflag & ICANON) 112c80476e4SDavid E. O'Brien # ifdef POSIX 113c80476e4SDavid E. O'Brien on = TCSADRAIN; 114c80476e4SDavid E. O'Brien # else 115c80476e4SDavid E. O'Brien on = TCSETA; 116c80476e4SDavid E. O'Brien # endif /* POSIX */ 117c80476e4SDavid E. O'Brien else { 118c80476e4SDavid E. O'Brien # ifdef POSIX 119c80476e4SDavid E. O'Brien on = TCSAFLUSH; 120c80476e4SDavid E. O'Brien # else 121c80476e4SDavid E. O'Brien on = TCSETAF; 122c80476e4SDavid E. O'Brien # endif /* POSIX */ 123c80476e4SDavid E. O'Brien tchars.c_lflag |= ICANON; 124c80476e4SDavid E. O'Brien 125c80476e4SDavid E. O'Brien } 126c80476e4SDavid E. O'Brien } 127c80476e4SDavid E. O'Brien else { 128c80476e4SDavid E. O'Brien tchars.c_cc[VEOL] = _POSIX_VDISABLE; 129c80476e4SDavid E. O'Brien # ifdef POSIX 130c80476e4SDavid E. O'Brien on = TCSADRAIN; 131c80476e4SDavid E. O'Brien # else 132c80476e4SDavid E. O'Brien on = TCSETA; 133c80476e4SDavid E. O'Brien # endif /* POSIX */ 134c80476e4SDavid E. O'Brien } 135c80476e4SDavid E. O'Brien # ifdef POSIX 136c80476e4SDavid E. O'Brien (void) tcsetattr(SHIN, on, &tchars); 137c80476e4SDavid E. O'Brien # else 138c80476e4SDavid E. O'Brien (void) ioctl(SHIN, on, (ioctl_t) &tchars); 139c80476e4SDavid E. O'Brien # endif /* POSIX */ 140c80476e4SDavid E. O'Brien #else 141c80476e4SDavid E. O'Brien struct sgttyb sgtty; 142c80476e4SDavid E. O'Brien static struct tchars tchars;/* INT, QUIT, XON, XOFF, EOF, BRK */ 143c80476e4SDavid E. O'Brien 144c80476e4SDavid E. O'Brien if (on) { 145c80476e4SDavid E. O'Brien (void) ioctl(SHIN, TIOCGETC, (ioctl_t) & tchars); 146c80476e4SDavid E. O'Brien tchars.t_brkc = ESC; 147c80476e4SDavid E. O'Brien (void) ioctl(SHIN, TIOCSETC, (ioctl_t) & tchars); 148c80476e4SDavid E. O'Brien /* 149c80476e4SDavid E. O'Brien * This must be done after every command: if the tty gets into raw or 150c80476e4SDavid E. O'Brien * cbreak mode the user can't even type 'reset'. 151c80476e4SDavid E. O'Brien */ 152c80476e4SDavid E. O'Brien (void) ioctl(SHIN, TIOCGETP, (ioctl_t) & sgtty); 153c80476e4SDavid E. O'Brien if (sgtty.sg_flags & (RAW | CBREAK)) { 154c80476e4SDavid E. O'Brien sgtty.sg_flags &= ~(RAW | CBREAK); 155c80476e4SDavid E. O'Brien (void) ioctl(SHIN, TIOCSETP, (ioctl_t) & sgtty); 156c80476e4SDavid E. O'Brien } 157c80476e4SDavid E. O'Brien } 158c80476e4SDavid E. O'Brien else { 159c80476e4SDavid E. O'Brien tchars.t_brkc = -1; 160c80476e4SDavid E. O'Brien (void) ioctl(SHIN, TIOCSETC, (ioctl_t) & tchars); 161c80476e4SDavid E. O'Brien } 162c80476e4SDavid E. O'Brien #endif /* TERMIO */ 163c80476e4SDavid E. O'Brien } 164c80476e4SDavid E. O'Brien 165c80476e4SDavid E. O'Brien /* 166c80476e4SDavid E. O'Brien * Move back to beginning of current line 167c80476e4SDavid E. O'Brien */ 168c80476e4SDavid E. O'Brien static void 169c80476e4SDavid E. O'Brien back_to_col_1() 170c80476e4SDavid E. O'Brien { 171c80476e4SDavid E. O'Brien #ifdef TERMIO 172c80476e4SDavid E. O'Brien # ifdef POSIX 173c80476e4SDavid E. O'Brien struct termios tty, tty_normal; 174c80476e4SDavid E. O'Brien # else 175c80476e4SDavid E. O'Brien struct termio tty, tty_normal; 176c80476e4SDavid E. O'Brien # endif /* POSIX */ 177c80476e4SDavid E. O'Brien #else 178c80476e4SDavid E. O'Brien struct sgttyb tty, tty_normal; 179c80476e4SDavid E. O'Brien #endif /* TERMIO */ 180c80476e4SDavid E. O'Brien 181c80476e4SDavid E. O'Brien # ifdef BSDSIGS 182c80476e4SDavid E. O'Brien sigmask_t omask = sigblock(sigmask(SIGINT)); 183c80476e4SDavid E. O'Brien # else 184c80476e4SDavid E. O'Brien (void) sighold(SIGINT); 185c80476e4SDavid E. O'Brien # endif /* BSDSIGS */ 186c80476e4SDavid E. O'Brien 187c80476e4SDavid E. O'Brien #ifdef TERMIO 188c80476e4SDavid E. O'Brien # ifdef POSIX 189c80476e4SDavid E. O'Brien (void) tcgetattr(SHOUT, &tty); 190c80476e4SDavid E. O'Brien # else 191c80476e4SDavid E. O'Brien (void) ioctl(SHOUT, TCGETA, (ioctl_t) &tty_normal); 192c80476e4SDavid E. O'Brien # endif /* POSIX */ 193c80476e4SDavid E. O'Brien tty_normal = tty; 194c80476e4SDavid E. O'Brien tty.c_iflag &= ~INLCR; 195c80476e4SDavid E. O'Brien tty.c_oflag &= ~ONLCR; 196c80476e4SDavid E. O'Brien # ifdef POSIX 197c80476e4SDavid E. O'Brien (void) tcsetattr(SHOUT, TCSANOW, &tty); 198c80476e4SDavid E. O'Brien # else 199c80476e4SDavid E. O'Brien (void) ioctl(SHOUT, TCSETAW, (ioctl_t) &tty); 200c80476e4SDavid E. O'Brien # endif /* POSIX */ 201c80476e4SDavid E. O'Brien (void) write(SHOUT, "\r", 1); 202c80476e4SDavid E. O'Brien # ifdef POSIX 203c80476e4SDavid E. O'Brien (void) tcsetattr(SHOUT, TCSANOW, &tty_normal); 204c80476e4SDavid E. O'Brien # else 205c80476e4SDavid E. O'Brien (void) ioctl(SHOUT, TCSETAW, (ioctl_t) &tty_normal); 206c80476e4SDavid E. O'Brien # endif /* POSIX */ 207c80476e4SDavid E. O'Brien #else 208c80476e4SDavid E. O'Brien (void) ioctl(SHIN, TIOCGETP, (ioctl_t) & tty); 209c80476e4SDavid E. O'Brien tty_normal = tty; 210c80476e4SDavid E. O'Brien tty.sg_flags &= ~CRMOD; 211c80476e4SDavid E. O'Brien (void) ioctl(SHIN, TIOCSETN, (ioctl_t) & tty); 212c80476e4SDavid E. O'Brien (void) write(SHOUT, "\r", 1); 213c80476e4SDavid E. O'Brien (void) ioctl(SHIN, TIOCSETN, (ioctl_t) & tty_normal); 214c80476e4SDavid E. O'Brien #endif /* TERMIO */ 215c80476e4SDavid E. O'Brien 216c80476e4SDavid E. O'Brien # ifdef BSDSIGS 217c80476e4SDavid E. O'Brien (void) sigsetmask(omask); 218c80476e4SDavid E. O'Brien # else 219c80476e4SDavid E. O'Brien (void) sigrelse(SIGINT); 220c80476e4SDavid E. O'Brien # endif /* BSDISGS */ 221c80476e4SDavid E. O'Brien } 222c80476e4SDavid E. O'Brien 223c80476e4SDavid E. O'Brien /* 224c80476e4SDavid E. O'Brien * Push string contents back into tty queue 225c80476e4SDavid E. O'Brien */ 226c80476e4SDavid E. O'Brien static void 227c80476e4SDavid E. O'Brien pushback(string) 228c80476e4SDavid E. O'Brien Char *string; 229c80476e4SDavid E. O'Brien { 230c80476e4SDavid E. O'Brien register Char *p; 231c80476e4SDavid E. O'Brien char c; 232c80476e4SDavid E. O'Brien #ifdef TERMIO 233c80476e4SDavid E. O'Brien # ifdef POSIX 234c80476e4SDavid E. O'Brien struct termios tty, tty_normal; 235c80476e4SDavid E. O'Brien # else 236c80476e4SDavid E. O'Brien struct termio tty, tty_normal; 237c80476e4SDavid E. O'Brien # endif /* POSIX */ 238c80476e4SDavid E. O'Brien #else 239c80476e4SDavid E. O'Brien struct sgttyb tty, tty_normal; 240c80476e4SDavid E. O'Brien #endif /* TERMIO */ 241c80476e4SDavid E. O'Brien 242c80476e4SDavid E. O'Brien #ifdef BSDSIGS 243c80476e4SDavid E. O'Brien sigmask_t omask = sigblock(sigmask(SIGINT)); 244c80476e4SDavid E. O'Brien #else 245c80476e4SDavid E. O'Brien (void) sighold(SIGINT); 246c80476e4SDavid E. O'Brien #endif /* BSDSIGS */ 247c80476e4SDavid E. O'Brien 248c80476e4SDavid E. O'Brien #ifdef TERMIO 249c80476e4SDavid E. O'Brien # ifdef POSIX 250c80476e4SDavid E. O'Brien (void) tcgetattr(SHOUT, &tty); 251c80476e4SDavid E. O'Brien # else 252c80476e4SDavid E. O'Brien (void) ioctl(SHOUT, TCSETAW, (ioctl_t) &tty); 253c80476e4SDavid E. O'Brien # endif /* POSIX */ 254c80476e4SDavid E. O'Brien tty_normal = tty; 255c80476e4SDavid E. O'Brien tty.c_lflag &= ~(ECHOKE | ECHO | ECHOE | ECHOK | ECHONL | ECHOPRT | ECHOCTL); 256c80476e4SDavid E. O'Brien # ifdef POSIX 257c80476e4SDavid E. O'Brien (void) tcsetattr(SHOUT, TCSANOW, &tty); 258c80476e4SDavid E. O'Brien # else 259c80476e4SDavid E. O'Brien (void) ioctl(SHOUT, TCSETAW, (ioctl_t) &tty); 260c80476e4SDavid E. O'Brien # endif /* POSIX */ 261c80476e4SDavid E. O'Brien 262c80476e4SDavid E. O'Brien for (p = string; c = *p; p++) 263c80476e4SDavid E. O'Brien (void) ioctl(SHOUT, TIOCSTI, (ioctl_t) & c); 264c80476e4SDavid E. O'Brien # ifdef POSIX 265c80476e4SDavid E. O'Brien (void) tcsetattr(SHOUT, TCSANOW, &tty_normal); 266c80476e4SDavid E. O'Brien # else 267c80476e4SDavid E. O'Brien (void) ioctl(SHOUT, TCSETAW, (ioctl_t) &tty_normal); 268c80476e4SDavid E. O'Brien # endif /* POSIX */ 269c80476e4SDavid E. O'Brien (void) sigsetmask(omask); 270c80476e4SDavid E. O'Brien #else 271c80476e4SDavid E. O'Brien (void) ioctl(SHOUT, TIOCGETP, (ioctl_t) & tty); 272c80476e4SDavid E. O'Brien tty_normal = tty; 273c80476e4SDavid E. O'Brien tty.sg_flags &= ~ECHO; 274c80476e4SDavid E. O'Brien (void) ioctl(SHOUT, TIOCSETN, (ioctl_t) & tty); 275c80476e4SDavid E. O'Brien 276c80476e4SDavid E. O'Brien for (p = string; c = *p; p++) 277c80476e4SDavid E. O'Brien (void) ioctl(SHOUT, TIOCSTI, (ioctl_t) & c); 278c80476e4SDavid E. O'Brien (void) ioctl(SHOUT, TIOCSETN, (ioctl_t) & tty_normal); 279c80476e4SDavid E. O'Brien #endif /* TERMIO */ 280c80476e4SDavid E. O'Brien 281c80476e4SDavid E. O'Brien # ifdef BSDSIGS 282c80476e4SDavid E. O'Brien (void) sigsetmask(omask); 283c80476e4SDavid E. O'Brien # else 284c80476e4SDavid E. O'Brien (void) sigrelse(SIGINT); 285c80476e4SDavid E. O'Brien # endif /* BSDISGS */ 286c80476e4SDavid E. O'Brien } 287c80476e4SDavid E. O'Brien 288c80476e4SDavid E. O'Brien /* 289c80476e4SDavid E. O'Brien * Concatenate src onto tail of des. 290c80476e4SDavid E. O'Brien * Des is a string whose maximum length is count. 291c80476e4SDavid E. O'Brien * Always null terminate. 292c80476e4SDavid E. O'Brien */ 293c80476e4SDavid E. O'Brien static void 294c80476e4SDavid E. O'Brien catn(des, src, count) 295c80476e4SDavid E. O'Brien register Char *des, *src; 296c80476e4SDavid E. O'Brien register count; 297c80476e4SDavid E. O'Brien { 298c80476e4SDavid E. O'Brien while (--count >= 0 && *des) 299c80476e4SDavid E. O'Brien des++; 300c80476e4SDavid E. O'Brien while (--count >= 0) 301c80476e4SDavid E. O'Brien if ((*des++ = *src++) == 0) 302c80476e4SDavid E. O'Brien return; 303c80476e4SDavid E. O'Brien *des = '\0'; 304c80476e4SDavid E. O'Brien } 305c80476e4SDavid E. O'Brien 306c80476e4SDavid E. O'Brien /* 307c80476e4SDavid E. O'Brien * Like strncpy but always leave room for trailing \0 308c80476e4SDavid E. O'Brien * and always null terminate. 309c80476e4SDavid E. O'Brien */ 310c80476e4SDavid E. O'Brien static void 311c80476e4SDavid E. O'Brien copyn(des, src, count) 312c80476e4SDavid E. O'Brien register Char *des, *src; 313c80476e4SDavid E. O'Brien register count; 314c80476e4SDavid E. O'Brien { 315c80476e4SDavid E. O'Brien while (--count >= 0) 316c80476e4SDavid E. O'Brien if ((*des++ = *src++) == 0) 317c80476e4SDavid E. O'Brien return; 318c80476e4SDavid E. O'Brien *des = '\0'; 319c80476e4SDavid E. O'Brien } 320c80476e4SDavid E. O'Brien 321c80476e4SDavid E. O'Brien static Char 322c80476e4SDavid E. O'Brien filetype(dir, file) 323c80476e4SDavid E. O'Brien Char *dir, *file; 324c80476e4SDavid E. O'Brien { 325c80476e4SDavid E. O'Brien Char path[MAXPATHLEN]; 326c80476e4SDavid E. O'Brien struct stat statb; 327c80476e4SDavid E. O'Brien 328c80476e4SDavid E. O'Brien catn(Strcpy(path, dir), file, sizeof(path) / sizeof(Char)); 329c80476e4SDavid E. O'Brien if (lstat(short2str(path), &statb) == 0) { 330c80476e4SDavid E. O'Brien switch (statb.st_mode & S_IFMT) { 331c80476e4SDavid E. O'Brien case S_IFDIR: 332c80476e4SDavid E. O'Brien return ('/'); 333c80476e4SDavid E. O'Brien 334c80476e4SDavid E. O'Brien case S_IFLNK: 335c80476e4SDavid E. O'Brien if (stat(short2str(path), &statb) == 0 && /* follow it out */ 336c80476e4SDavid E. O'Brien S_ISDIR(statb.st_mode)) 337c80476e4SDavid E. O'Brien return ('>'); 338c80476e4SDavid E. O'Brien else 339c80476e4SDavid E. O'Brien return ('@'); 340c80476e4SDavid E. O'Brien 341c80476e4SDavid E. O'Brien case S_IFSOCK: 342c80476e4SDavid E. O'Brien return ('='); 343c80476e4SDavid E. O'Brien 344c80476e4SDavid E. O'Brien default: 345c80476e4SDavid E. O'Brien if (statb.st_mode & 0111) 346c80476e4SDavid E. O'Brien return ('*'); 347c80476e4SDavid E. O'Brien } 348c80476e4SDavid E. O'Brien } 349c80476e4SDavid E. O'Brien return (' '); 350c80476e4SDavid E. O'Brien } 351c80476e4SDavid E. O'Brien 352c80476e4SDavid E. O'Brien static struct winsize win; 353c80476e4SDavid E. O'Brien 354c80476e4SDavid E. O'Brien /* 355c80476e4SDavid E. O'Brien * Print sorted down columns 356c80476e4SDavid E. O'Brien */ 357c80476e4SDavid E. O'Brien static void 358c80476e4SDavid E. O'Brien print_by_column(dir, items, count) 359c80476e4SDavid E. O'Brien Char *dir, *items[]; 360c80476e4SDavid E. O'Brien int count; 361c80476e4SDavid E. O'Brien { 362c80476e4SDavid E. O'Brien register int i, rows, r, c, maxwidth = 0, columns; 363c80476e4SDavid E. O'Brien 364c80476e4SDavid E. O'Brien if (ioctl(SHOUT, TIOCGWINSZ, (ioctl_t) & win) < 0 || win.ws_col == 0) 365c80476e4SDavid E. O'Brien win.ws_col = 80; 366c80476e4SDavid E. O'Brien for (i = 0; i < count; i++) 367c80476e4SDavid E. O'Brien maxwidth = maxwidth > (r = Strlen(items[i])) ? maxwidth : r; 368c80476e4SDavid E. O'Brien maxwidth += 2; /* for the file tag and space */ 369c80476e4SDavid E. O'Brien columns = win.ws_col / maxwidth; 370c80476e4SDavid E. O'Brien if (columns == 0) 371c80476e4SDavid E. O'Brien columns = 1; 372c80476e4SDavid E. O'Brien rows = (count + (columns - 1)) / columns; 373c80476e4SDavid E. O'Brien for (r = 0; r < rows; r++) { 374c80476e4SDavid E. O'Brien for (c = 0; c < columns; c++) { 375c80476e4SDavid E. O'Brien i = c * rows + r; 376c80476e4SDavid E. O'Brien if (i < count) { 377c80476e4SDavid E. O'Brien register int w; 378c80476e4SDavid E. O'Brien 379c80476e4SDavid E. O'Brien xprintf("%S", items[i]); 380c80476e4SDavid E. O'Brien xputchar(dir ? filetype(dir, items[i]) : ' '); 381c80476e4SDavid E. O'Brien if (c < columns - 1) { /* last column? */ 382c80476e4SDavid E. O'Brien w = Strlen(items[i]) + 1; 383c80476e4SDavid E. O'Brien for (; w < maxwidth; w++) 384c80476e4SDavid E. O'Brien xputchar(' '); 385c80476e4SDavid E. O'Brien } 386c80476e4SDavid E. O'Brien } 387c80476e4SDavid E. O'Brien } 388c80476e4SDavid E. O'Brien xputchar('\r'); 389c80476e4SDavid E. O'Brien xputchar('\n'); 390c80476e4SDavid E. O'Brien } 391c80476e4SDavid E. O'Brien } 392c80476e4SDavid E. O'Brien 393c80476e4SDavid E. O'Brien /* 394c80476e4SDavid E. O'Brien * Expand file name with possible tilde usage 395c80476e4SDavid E. O'Brien * ~person/mumble 396c80476e4SDavid E. O'Brien * expands to 397c80476e4SDavid E. O'Brien * home_directory_of_person/mumble 398c80476e4SDavid E. O'Brien */ 399c80476e4SDavid E. O'Brien static Char * 400c80476e4SDavid E. O'Brien tilde(new, old) 401c80476e4SDavid E. O'Brien Char *new, *old; 402c80476e4SDavid E. O'Brien { 403c80476e4SDavid E. O'Brien register Char *o, *p; 404c80476e4SDavid E. O'Brien register struct passwd *pw; 405c80476e4SDavid E. O'Brien static Char person[40]; 406c80476e4SDavid E. O'Brien 407c80476e4SDavid E. O'Brien if (old[0] != '~') 408c80476e4SDavid E. O'Brien return (Strcpy(new, old)); 409c80476e4SDavid E. O'Brien 410c80476e4SDavid E. O'Brien for (p = person, o = &old[1]; *o && *o != '/'; *p++ = *o++); 411c80476e4SDavid E. O'Brien *p = '\0'; 412c80476e4SDavid E. O'Brien if (person[0] == '\0') 413c80476e4SDavid E. O'Brien (void) Strcpy(new, varval(STRhome)); 414c80476e4SDavid E. O'Brien else { 415c80476e4SDavid E. O'Brien pw = getpwnam(short2str(person)); 416c80476e4SDavid E. O'Brien if (pw == NULL) 417c80476e4SDavid E. O'Brien return (NULL); 418c80476e4SDavid E. O'Brien (void) Strcpy(new, str2short(pw->pw_dir)); 419c80476e4SDavid E. O'Brien } 420c80476e4SDavid E. O'Brien (void) Strcat(new, o); 421c80476e4SDavid E. O'Brien return (new); 422c80476e4SDavid E. O'Brien } 423c80476e4SDavid E. O'Brien 424c80476e4SDavid E. O'Brien /* 425c80476e4SDavid E. O'Brien * Cause pending line to be printed 426c80476e4SDavid E. O'Brien */ 427c80476e4SDavid E. O'Brien static void 428c80476e4SDavid E. O'Brien retype() 429c80476e4SDavid E. O'Brien { 430c80476e4SDavid E. O'Brien #ifdef TERMIO 431c80476e4SDavid E. O'Brien # ifdef POSIX 432c80476e4SDavid E. O'Brien struct termios tty; 433c80476e4SDavid E. O'Brien 434c80476e4SDavid E. O'Brien (void) tcgetattr(SHOUT, &tty); 435c80476e4SDavid E. O'Brien # else 436c80476e4SDavid E. O'Brien struct termio tty; 437c80476e4SDavid E. O'Brien 438c80476e4SDavid E. O'Brien (void) ioctl(SHOUT, TCGETA, (ioctl_t) &tty); 439c80476e4SDavid E. O'Brien # endif /* POSIX */ 440c80476e4SDavid E. O'Brien 441c80476e4SDavid E. O'Brien tty.c_lflag |= PENDIN; 442c80476e4SDavid E. O'Brien 443c80476e4SDavid E. O'Brien # ifdef POSIX 444c80476e4SDavid E. O'Brien (void) tcsetattr(SHOUT, TCSANOW, &tty); 445c80476e4SDavid E. O'Brien # else 446c80476e4SDavid E. O'Brien (void) ioctl(SHOUT, TCSETAW, (ioctl_t) &tty); 447c80476e4SDavid E. O'Brien # endif /* POSIX */ 448c80476e4SDavid E. O'Brien #else 449c80476e4SDavid E. O'Brien int pending_input = LPENDIN; 450c80476e4SDavid E. O'Brien 451c80476e4SDavid E. O'Brien (void) ioctl(SHOUT, TIOCLBIS, (ioctl_t) & pending_input); 452c80476e4SDavid E. O'Brien #endif /* TERMIO */ 453c80476e4SDavid E. O'Brien } 454c80476e4SDavid E. O'Brien 455c80476e4SDavid E. O'Brien static void 456c80476e4SDavid E. O'Brien beep() 457c80476e4SDavid E. O'Brien { 458c80476e4SDavid E. O'Brien if (adrof(STRnobeep) == 0) 459c80476e4SDavid E. O'Brien #ifndef _OSD_POSIX 460c80476e4SDavid E. O'Brien (void) write(SHOUT, "\007", 1); 461c80476e4SDavid E. O'Brien #else /*_OSD_POSIX*/ 462c80476e4SDavid E. O'Brien { 463c80476e4SDavid E. O'Brien unsigned char beep_ch = CTL_ESC('\007'); 464c80476e4SDavid E. O'Brien (void) write(SHOUT, &beep_ch, 1); 465c80476e4SDavid E. O'Brien } 466c80476e4SDavid E. O'Brien #endif /*_OSD_POSIX*/ 467c80476e4SDavid E. O'Brien } 468c80476e4SDavid E. O'Brien 469c80476e4SDavid E. O'Brien /* 470c80476e4SDavid E. O'Brien * Erase that silly ^[ and 471c80476e4SDavid E. O'Brien * print the recognized part of the string 472c80476e4SDavid E. O'Brien */ 473c80476e4SDavid E. O'Brien static void 474c80476e4SDavid E. O'Brien print_recognized_stuff(recognized_part) 475c80476e4SDavid E. O'Brien Char *recognized_part; 476c80476e4SDavid E. O'Brien { 477c80476e4SDavid E. O'Brien /* An optimized erasing of that silly ^[ */ 478c80476e4SDavid E. O'Brien (void) putraw('\b'); 479c80476e4SDavid E. O'Brien (void) putraw('\b'); 480c80476e4SDavid E. O'Brien switch (Strlen(recognized_part)) { 481c80476e4SDavid E. O'Brien 482c80476e4SDavid E. O'Brien case 0: /* erase two Characters: ^[ */ 483c80476e4SDavid E. O'Brien (void) putraw(' '); 484c80476e4SDavid E. O'Brien (void) putraw(' '); 485c80476e4SDavid E. O'Brien (void) putraw('\b'); 486c80476e4SDavid E. O'Brien (void) putraw('\b'); 487c80476e4SDavid E. O'Brien break; 488c80476e4SDavid E. O'Brien 489c80476e4SDavid E. O'Brien case 1: /* overstrike the ^, erase the [ */ 490c80476e4SDavid E. O'Brien xprintf("%S", recognized_part); 491c80476e4SDavid E. O'Brien (void) putraw(' '); 492c80476e4SDavid E. O'Brien (void) putraw('\b'); 493c80476e4SDavid E. O'Brien break; 494c80476e4SDavid E. O'Brien 495c80476e4SDavid E. O'Brien default: /* overstrike both Characters ^[ */ 496c80476e4SDavid E. O'Brien xprintf("%S", recognized_part); 497c80476e4SDavid E. O'Brien break; 498c80476e4SDavid E. O'Brien } 499c80476e4SDavid E. O'Brien flush(); 500c80476e4SDavid E. O'Brien } 501c80476e4SDavid E. O'Brien 502c80476e4SDavid E. O'Brien /* 503c80476e4SDavid E. O'Brien * Parse full path in file into 2 parts: directory and file names 504c80476e4SDavid E. O'Brien * Should leave final slash (/) at end of dir. 505c80476e4SDavid E. O'Brien */ 506c80476e4SDavid E. O'Brien static void 507c80476e4SDavid E. O'Brien extract_dir_and_name(path, dir, name) 508c80476e4SDavid E. O'Brien Char *path, *dir, *name; 509c80476e4SDavid E. O'Brien { 510c80476e4SDavid E. O'Brien register Char *p; 511c80476e4SDavid E. O'Brien 512c80476e4SDavid E. O'Brien p = Strrchr(path, '/'); 513c80476e4SDavid E. O'Brien if (p == NULL) { 514c80476e4SDavid E. O'Brien copyn(name, path, MAXNAMLEN); 515c80476e4SDavid E. O'Brien dir[0] = '\0'; 516c80476e4SDavid E. O'Brien } 517c80476e4SDavid E. O'Brien else { 518c80476e4SDavid E. O'Brien copyn(name, ++p, MAXNAMLEN); 519c80476e4SDavid E. O'Brien copyn(dir, path, p - path); 520c80476e4SDavid E. O'Brien } 521c80476e4SDavid E. O'Brien } 522c80476e4SDavid E. O'Brien /* atp vmsposix - I need to remove all the setpwent 523c80476e4SDavid E. O'Brien * getpwent endpwent stuff. VMS_POSIX has getpwnam getpwuid 524c80476e4SDavid E. O'Brien * and getlogin. This needs fixing. (There is no access to 525c80476e4SDavid E. O'Brien * pw->passwd in VMS - a secure system benefit :-| ) 526c80476e4SDavid E. O'Brien */ 527c80476e4SDavid E. O'Brien static Char * 528c80476e4SDavid E. O'Brien getitem(dir_fd, looking_for_lognames) 529c80476e4SDavid E. O'Brien DIR *dir_fd; 530c80476e4SDavid E. O'Brien int looking_for_lognames; 531c80476e4SDavid E. O'Brien { 532c80476e4SDavid E. O'Brien register struct passwd *pw; 533c80476e4SDavid E. O'Brien register struct dirent *dirp; 534c80476e4SDavid E. O'Brien 535c80476e4SDavid E. O'Brien if (looking_for_lognames) { 536c80476e4SDavid E. O'Brien #ifdef _VMS_POSIX 537c80476e4SDavid E. O'Brien return (NULL); 538c80476e4SDavid E. O'Brien #else 539c80476e4SDavid E. O'Brien if ((pw = getpwent()) == NULL) 540c80476e4SDavid E. O'Brien return (NULL); 541c80476e4SDavid E. O'Brien return (str2short(pw->pw_name)); 542c80476e4SDavid E. O'Brien #endif /* atp vmsposix */ 543c80476e4SDavid E. O'Brien } 544c80476e4SDavid E. O'Brien if (dirp = readdir(dir_fd)) 545c80476e4SDavid E. O'Brien return (str2short(dirp->d_name)); 546c80476e4SDavid E. O'Brien return (NULL); 547c80476e4SDavid E. O'Brien } 548c80476e4SDavid E. O'Brien 549c80476e4SDavid E. O'Brien static void 550c80476e4SDavid E. O'Brien free_items(items) 551c80476e4SDavid E. O'Brien register Char **items; 552c80476e4SDavid E. O'Brien { 553c80476e4SDavid E. O'Brien register int i; 554c80476e4SDavid E. O'Brien 555c80476e4SDavid E. O'Brien for (i = 0; items[i]; i++) 556c80476e4SDavid E. O'Brien xfree((ptr_t) items[i]); 557c80476e4SDavid E. O'Brien xfree((ptr_t) items); 558c80476e4SDavid E. O'Brien } 559c80476e4SDavid E. O'Brien 560c80476e4SDavid E. O'Brien #ifdef BSDSIGS 561c80476e4SDavid E. O'Brien # define FREE_ITEMS(items) { \ 562c80476e4SDavid E. O'Brien sigmask_t omask;\ 563c80476e4SDavid E. O'Brien \ 564c80476e4SDavid E. O'Brien omask = sigblock(sigmask(SIGINT));\ 565c80476e4SDavid E. O'Brien free_items(items);\ 566c80476e4SDavid E. O'Brien items = NULL;\ 567c80476e4SDavid E. O'Brien (void) sigsetmask(omask);\ 568c80476e4SDavid E. O'Brien } 569c80476e4SDavid E. O'Brien #else 570c80476e4SDavid E. O'Brien # define FREE_ITEMS(items) { \ 571c80476e4SDavid E. O'Brien (void) sighold(SIGINT);\ 572c80476e4SDavid E. O'Brien free_items(items);\ 573c80476e4SDavid E. O'Brien items = NULL;\ 574c80476e4SDavid E. O'Brien (void) sigrelse(SIGINT);\ 575c80476e4SDavid E. O'Brien } 576c80476e4SDavid E. O'Brien #endif /* BSDSIGS */ 577c80476e4SDavid E. O'Brien 578c80476e4SDavid E. O'Brien /* 579c80476e4SDavid E. O'Brien * Perform a RECOGNIZE or LIST command on string "word". 580c80476e4SDavid E. O'Brien */ 581c80476e4SDavid E. O'Brien static int 582c80476e4SDavid E. O'Brien tsearch(word, command, max_word_length) 583c80476e4SDavid E. O'Brien Char *word; 584c80476e4SDavid E. O'Brien int max_word_length; 585c80476e4SDavid E. O'Brien COMMAND command; 586c80476e4SDavid E. O'Brien { 587c80476e4SDavid E. O'Brien static Char **items = NULL; 588c80476e4SDavid E. O'Brien register DIR *dir_fd; 589c80476e4SDavid E. O'Brien register numitems = 0, ignoring = TRUE, nignored = 0; 590c80476e4SDavid E. O'Brien register name_length, looking_for_lognames; 591c80476e4SDavid E. O'Brien Char tilded_dir[MAXPATHLEN + 1], dir[MAXPATHLEN + 1]; 592c80476e4SDavid E. O'Brien Char name[MAXNAMLEN + 1], extended_name[MAXNAMLEN + 1]; 593c80476e4SDavid E. O'Brien Char *item; 594c80476e4SDavid E. O'Brien 595c80476e4SDavid E. O'Brien #define MAXITEMS 1024 596c80476e4SDavid E. O'Brien 597c80476e4SDavid E. O'Brien if (items != NULL) 598c80476e4SDavid E. O'Brien FREE_ITEMS(items); 599c80476e4SDavid E. O'Brien 600c80476e4SDavid E. O'Brien looking_for_lognames = (*word == '~') && (Strchr(word, '/') == NULL); 601c80476e4SDavid E. O'Brien if (looking_for_lognames) { 602c80476e4SDavid E. O'Brien #ifndef _VMS_POSIX 603c80476e4SDavid E. O'Brien (void) setpwent(); 604c80476e4SDavid E. O'Brien #endif /*atp vmsposix */ 605c80476e4SDavid E. O'Brien copyn(name, &word[1], MAXNAMLEN); /* name sans ~ */ 606c80476e4SDavid E. O'Brien dir_fd = NULL; 607c80476e4SDavid E. O'Brien } 608c80476e4SDavid E. O'Brien else { 609c80476e4SDavid E. O'Brien extract_dir_and_name(word, dir, name); 610c80476e4SDavid E. O'Brien if (tilde(tilded_dir, dir) == 0) 611c80476e4SDavid E. O'Brien return (0); 612c80476e4SDavid E. O'Brien dir_fd = opendir(*tilded_dir ? short2str(tilded_dir) : "."); 613c80476e4SDavid E. O'Brien if (dir_fd == NULL) 614c80476e4SDavid E. O'Brien return (0); 615c80476e4SDavid E. O'Brien } 616c80476e4SDavid E. O'Brien 617c80476e4SDavid E. O'Brien again: /* search for matches */ 618c80476e4SDavid E. O'Brien name_length = Strlen(name); 619c80476e4SDavid E. O'Brien for (numitems = 0; item = getitem(dir_fd, looking_for_lognames);) { 620c80476e4SDavid E. O'Brien if (!is_prefix(name, item)) 621c80476e4SDavid E. O'Brien continue; 622c80476e4SDavid E. O'Brien /* Don't match . files on null prefix match */ 623c80476e4SDavid E. O'Brien if (name_length == 0 && item[0] == '.' && 624c80476e4SDavid E. O'Brien !looking_for_lognames) 625c80476e4SDavid E. O'Brien continue; 626c80476e4SDavid E. O'Brien if (command == LIST) { 627c80476e4SDavid E. O'Brien if (numitems >= MAXITEMS) { 628c80476e4SDavid E. O'Brien xprintf(CGETS(14, 1, "\nYikes!! Too many %s!!\n"), 629c80476e4SDavid E. O'Brien looking_for_lognames ? 630c80476e4SDavid E. O'Brien CGETS(14, 2, "names in password file") : 631c80476e4SDavid E. O'Brien CGETS(14, 3, "files"); 632c80476e4SDavid E. O'Brien break; 633c80476e4SDavid E. O'Brien } 634c80476e4SDavid E. O'Brien /* 635c80476e4SDavid E. O'Brien * From Beto Appleton (beto@aixwiz.austin.ibm.com) 636c80476e4SDavid E. O'Brien * typing "./control-d" will cause the csh to core-dump. 637c80476e4SDavid E. O'Brien * the problem can be reproduce as following: 638c80476e4SDavid E. O'Brien * 1. set ignoreeof 639c80476e4SDavid E. O'Brien * 2. set filec 640c80476e4SDavid E. O'Brien * 3. create a directory with 1050 files 641c80476e4SDavid E. O'Brien * 4. typing "./control-d" will cause the csh to core-dump 642c80476e4SDavid E. O'Brien * Solution: Add + 1 to MAXITEMS 643c80476e4SDavid E. O'Brien */ 644c80476e4SDavid E. O'Brien if (items == NULL) 645c80476e4SDavid E. O'Brien items = (Char **) xcalloc(sizeof(items[0]), MAXITEMS + 1); 646c80476e4SDavid E. O'Brien items[numitems] = (Char *) xmalloc((size_t) (Strlen(item) + 1) * 647c80476e4SDavid E. O'Brien sizeof(Char)); 648c80476e4SDavid E. O'Brien copyn(items[numitems], item, MAXNAMLEN); 649c80476e4SDavid E. O'Brien numitems++; 650c80476e4SDavid E. O'Brien } 651c80476e4SDavid E. O'Brien else { /* RECOGNIZE command */ 652c80476e4SDavid E. O'Brien if (ignoring && ignored(item)) 653c80476e4SDavid E. O'Brien nignored++; 654c80476e4SDavid E. O'Brien else if (recognize(extended_name, 655c80476e4SDavid E. O'Brien item, name_length, ++numitems)) 656c80476e4SDavid E. O'Brien break; 657c80476e4SDavid E. O'Brien } 658c80476e4SDavid E. O'Brien } 659c80476e4SDavid E. O'Brien if (ignoring && numitems == 0 && nignored > 0) { 660c80476e4SDavid E. O'Brien ignoring = FALSE; 661c80476e4SDavid E. O'Brien nignored = 0; 662c80476e4SDavid E. O'Brien if (looking_for_lognames) 663c80476e4SDavid E. O'Brien #ifndef _VMS_POSIX 664c80476e4SDavid E. O'Brien (void) setpwent(); 665c80476e4SDavid E. O'Brien #endif /* atp vmsposix */ 666c80476e4SDavid E. O'Brien else 667c80476e4SDavid E. O'Brien rewinddir(dir_fd); 668c80476e4SDavid E. O'Brien goto again; 669c80476e4SDavid E. O'Brien } 670c80476e4SDavid E. O'Brien 671c80476e4SDavid E. O'Brien if (looking_for_lognames) 672c80476e4SDavid E. O'Brien #ifndef _VMS_POSIX 673c80476e4SDavid E. O'Brien (void) endpwent(); 674c80476e4SDavid E. O'Brien #endif /*atp vmsposix */ 675c80476e4SDavid E. O'Brien else 676c80476e4SDavid E. O'Brien (void) closedir(dir_fd); 677c80476e4SDavid E. O'Brien if (numitems == 0) 678c80476e4SDavid E. O'Brien return (0); 679c80476e4SDavid E. O'Brien if (command == RECOGNIZE) { 680c80476e4SDavid E. O'Brien if (looking_for_lognames) 681c80476e4SDavid E. O'Brien copyn(word, STRtilde, 1); 682c80476e4SDavid E. O'Brien else 683c80476e4SDavid E. O'Brien /* put back dir part */ 684c80476e4SDavid E. O'Brien copyn(word, dir, max_word_length); 685c80476e4SDavid E. O'Brien /* add extended name */ 686c80476e4SDavid E. O'Brien catn(word, extended_name, max_word_length); 687c80476e4SDavid E. O'Brien return (numitems); 688c80476e4SDavid E. O'Brien } 689c80476e4SDavid E. O'Brien else { /* LIST */ 690c80476e4SDavid E. O'Brien qsort((ptr_t) items, (size_t) numitems, sizeof(items[0]), sortscmp); 691c80476e4SDavid E. O'Brien print_by_column(looking_for_lognames ? NULL : tilded_dir, 692c80476e4SDavid E. O'Brien items, numitems); 693c80476e4SDavid E. O'Brien if (items != NULL) 694c80476e4SDavid E. O'Brien FREE_ITEMS(items); 695c80476e4SDavid E. O'Brien } 696c80476e4SDavid E. O'Brien return (0); 697c80476e4SDavid E. O'Brien } 698c80476e4SDavid E. O'Brien 699c80476e4SDavid E. O'Brien /* 700c80476e4SDavid E. O'Brien * Object: extend what user typed up to an ambiguity. 701c80476e4SDavid E. O'Brien * Algorithm: 702c80476e4SDavid E. O'Brien * On first match, copy full item (assume it'll be the only match) 703c80476e4SDavid E. O'Brien * On subsequent matches, shorten extended_name to the first 704c80476e4SDavid E. O'Brien * Character mismatch between extended_name and item. 705c80476e4SDavid E. O'Brien * If we shorten it back to the prefix length, stop searching. 706c80476e4SDavid E. O'Brien */ 707c80476e4SDavid E. O'Brien static int 708c80476e4SDavid E. O'Brien recognize(extended_name, item, name_length, numitems) 709c80476e4SDavid E. O'Brien Char *extended_name, *item; 710c80476e4SDavid E. O'Brien int name_length, numitems; 711c80476e4SDavid E. O'Brien { 712c80476e4SDavid E. O'Brien if (numitems == 1) /* 1st match */ 713c80476e4SDavid E. O'Brien copyn(extended_name, item, MAXNAMLEN); 714c80476e4SDavid E. O'Brien else { /* 2nd & subsequent matches */ 715c80476e4SDavid E. O'Brien register Char *x, *ent; 716c80476e4SDavid E. O'Brien register int len = 0; 717c80476e4SDavid E. O'Brien 718c80476e4SDavid E. O'Brien x = extended_name; 719c80476e4SDavid E. O'Brien for (ent = item; *x && *x == *ent++; x++, len++); 720c80476e4SDavid E. O'Brien *x = '\0'; /* Shorten at 1st Char diff */ 721c80476e4SDavid E. O'Brien if (len == name_length) /* Ambiguous to prefix? */ 722c80476e4SDavid E. O'Brien return (-1); /* So stop now and save time */ 723c80476e4SDavid E. O'Brien } 724c80476e4SDavid E. O'Brien return (0); 725c80476e4SDavid E. O'Brien } 726c80476e4SDavid E. O'Brien 727c80476e4SDavid E. O'Brien /* 728c80476e4SDavid E. O'Brien * Return true if check matches initial Chars in template. 729c80476e4SDavid E. O'Brien * This differs from PWB imatch in that if check is null 730c80476e4SDavid E. O'Brien * it matches anything. 731c80476e4SDavid E. O'Brien */ 732c80476e4SDavid E. O'Brien static int 733c80476e4SDavid E. O'Brien is_prefix(check, template) 734c80476e4SDavid E. O'Brien register Char *check, *template; 735c80476e4SDavid E. O'Brien { 736c80476e4SDavid E. O'Brien do 737c80476e4SDavid E. O'Brien if (*check == 0) 738c80476e4SDavid E. O'Brien return (TRUE); 739c80476e4SDavid E. O'Brien while (*check++ == *template++); 740c80476e4SDavid E. O'Brien return (FALSE); 741c80476e4SDavid E. O'Brien } 742c80476e4SDavid E. O'Brien 743c80476e4SDavid E. O'Brien /* 744c80476e4SDavid E. O'Brien * Return true if the Chars in template appear at the 745c80476e4SDavid E. O'Brien * end of check, I.e., are it's suffix. 746c80476e4SDavid E. O'Brien */ 747c80476e4SDavid E. O'Brien static int 748c80476e4SDavid E. O'Brien is_suffix(check, template) 749c80476e4SDavid E. O'Brien Char *check, *template; 750c80476e4SDavid E. O'Brien { 751c80476e4SDavid E. O'Brien register Char *c, *t; 752c80476e4SDavid E. O'Brien 753c80476e4SDavid E. O'Brien for (c = check; *c++;); 754c80476e4SDavid E. O'Brien for (t = template; *t++;); 755c80476e4SDavid E. O'Brien for (;;) { 756c80476e4SDavid E. O'Brien if (t == template) 757c80476e4SDavid E. O'Brien return 1; 758c80476e4SDavid E. O'Brien if (c == check || *--t != *--c) 759c80476e4SDavid E. O'Brien return 0; 760c80476e4SDavid E. O'Brien } 761c80476e4SDavid E. O'Brien } 762c80476e4SDavid E. O'Brien 763c80476e4SDavid E. O'Brien int 764c80476e4SDavid E. O'Brien tenex(inputline, inputline_size) 765c80476e4SDavid E. O'Brien Char *inputline; 766c80476e4SDavid E. O'Brien int inputline_size; 767c80476e4SDavid E. O'Brien { 768c80476e4SDavid E. O'Brien register int numitems, num_read; 769c80476e4SDavid E. O'Brien char tinputline[BUFSIZE]; 770c80476e4SDavid E. O'Brien 771c80476e4SDavid E. O'Brien 772c80476e4SDavid E. O'Brien setup_tty(ON); 773c80476e4SDavid E. O'Brien 774c80476e4SDavid E. O'Brien while ((num_read = read(SHIN, tinputline, BUFSIZE)) > 0) { 775c80476e4SDavid E. O'Brien int i; 776c80476e4SDavid E. O'Brien static Char delims[] = {' ', '\'', '"', '\t', ';', '&', '<', 777c80476e4SDavid E. O'Brien '>', '(', ')', '|', '^', '%', '\0'}; 778c80476e4SDavid E. O'Brien register Char *str_end, *word_start, last_Char, should_retype; 779c80476e4SDavid E. O'Brien register int space_left; 780c80476e4SDavid E. O'Brien COMMAND command; 781c80476e4SDavid E. O'Brien 782c80476e4SDavid E. O'Brien for (i = 0; i < num_read; i++) 783c80476e4SDavid E. O'Brien inputline[i] = (unsigned char) tinputline[i]; 784c80476e4SDavid E. O'Brien last_Char = inputline[num_read - 1] & ASCII; 785c80476e4SDavid E. O'Brien 786c80476e4SDavid E. O'Brien if (last_Char == '\n' || num_read == inputline_size) 787c80476e4SDavid E. O'Brien break; 788c80476e4SDavid E. O'Brien command = (last_Char == ESC) ? RECOGNIZE : LIST; 789c80476e4SDavid E. O'Brien if (command == LIST) 790c80476e4SDavid E. O'Brien xputchar('\n'); 791c80476e4SDavid E. O'Brien str_end = &inputline[num_read]; 792c80476e4SDavid E. O'Brien if (last_Char == ESC) 793c80476e4SDavid E. O'Brien --str_end; /* wipeout trailing cmd Char */ 794c80476e4SDavid E. O'Brien *str_end = '\0'; 795c80476e4SDavid E. O'Brien /* 796c80476e4SDavid E. O'Brien * Find LAST occurence of a delimiter in the inputline. The word start 797c80476e4SDavid E. O'Brien * is one Character past it. 798c80476e4SDavid E. O'Brien */ 799c80476e4SDavid E. O'Brien for (word_start = str_end; word_start > inputline; --word_start) 800c80476e4SDavid E. O'Brien if (Strchr(delims, word_start[-1])) 801c80476e4SDavid E. O'Brien break; 802c80476e4SDavid E. O'Brien space_left = inputline_size - (word_start - inputline) - 1; 803c80476e4SDavid E. O'Brien numitems = tsearch(word_start, command, space_left); 804c80476e4SDavid E. O'Brien 805c80476e4SDavid E. O'Brien if (command == RECOGNIZE) { 806c80476e4SDavid E. O'Brien /* print from str_end on */ 807c80476e4SDavid E. O'Brien print_recognized_stuff(str_end); 808c80476e4SDavid E. O'Brien if (numitems != 1) /* Beep = No match/ambiguous */ 809c80476e4SDavid E. O'Brien beep(); 810c80476e4SDavid E. O'Brien } 811c80476e4SDavid E. O'Brien 812c80476e4SDavid E. O'Brien /* 813c80476e4SDavid E. O'Brien * Tabs in the input line cause trouble after a pushback. tty driver 814c80476e4SDavid E. O'Brien * won't backspace over them because column positions are now 815c80476e4SDavid E. O'Brien * incorrect. This is solved by retyping over current line. 816c80476e4SDavid E. O'Brien */ 817c80476e4SDavid E. O'Brien should_retype = FALSE; 818c80476e4SDavid E. O'Brien if (Strchr(inputline, '\t')) { /* tab Char in input line? */ 819c80476e4SDavid E. O'Brien back_to_col_1(); 820c80476e4SDavid E. O'Brien should_retype = TRUE; 821c80476e4SDavid E. O'Brien } 822c80476e4SDavid E. O'Brien if (command == LIST) /* Always retype after a LIST */ 823c80476e4SDavid E. O'Brien should_retype = TRUE; 824c80476e4SDavid E. O'Brien if (should_retype) 825c80476e4SDavid E. O'Brien printprompt(0, NULL); 826c80476e4SDavid E. O'Brien pushback(inputline); 827c80476e4SDavid E. O'Brien if (should_retype) 828c80476e4SDavid E. O'Brien retype(); 829c80476e4SDavid E. O'Brien } 830c80476e4SDavid E. O'Brien setup_tty(OFF); 831c80476e4SDavid E. O'Brien return (num_read); 832c80476e4SDavid E. O'Brien } 833c80476e4SDavid E. O'Brien 834c80476e4SDavid E. O'Brien static int 835c80476e4SDavid E. O'Brien ignored(item) 836c80476e4SDavid E. O'Brien register Char *item; 837c80476e4SDavid E. O'Brien { 838c80476e4SDavid E. O'Brien struct varent *vp; 839c80476e4SDavid E. O'Brien register Char **cp; 840c80476e4SDavid E. O'Brien 841c80476e4SDavid E. O'Brien if ((vp = adrof(STRfignore)) == NULL || (cp = vp->vec) == NULL) 842c80476e4SDavid E. O'Brien return (FALSE); 843c80476e4SDavid E. O'Brien for (; *cp != NULL; cp++) 844c80476e4SDavid E. O'Brien if (is_suffix(item, *cp)) 845c80476e4SDavid E. O'Brien return (TRUE); 846c80476e4SDavid E. O'Brien return (FALSE); 847c80476e4SDavid E. O'Brien } 848c80476e4SDavid E. O'Brien #endif /* FILEC */ 849