1 /* $OpenBSD: file.c,v 1.40 2020/10/06 01:40:43 deraadt Exp $ */
2 /* $NetBSD: file.c,v 1.11 1996/11/08 19:34:37 christos Exp $ */
3
4 /*-
5 * Copyright (c) 1980, 1991, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #include <sys/ioctl.h>
34 #include <sys/stat.h>
35 #include <sys/types.h>
36
37 #include <dirent.h>
38 #include <errno.h>
39 #include <limits.h>
40 #include <pwd.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <termios.h>
44 #include <unistd.h>
45
46 #include "csh.h"
47 #include "extern.h"
48
49 /*
50 * Tenex style file name recognition, .. and more.
51 * History:
52 * Author: Ken Greer, Sept. 1975, CMU.
53 * Finally got around to adding to the Cshell., Ken Greer, Dec. 1981.
54 */
55
56 #ifndef TRUE
57 #define TRUE 1
58 #endif
59 #ifndef FALSE
60 #define FALSE 0
61 #endif
62
63 #define ESC '\033'
64 #define TABWIDTH 8
65
66 typedef enum {
67 LIST,
68 RECOGNIZE
69 } COMMAND;
70
71 struct cmdline {
72 int fdin;
73 int fdout;
74 int istty;
75 int flags;
76 #define CL_ALTWERASE 0x1
77 #define CL_PROMPT 0x2
78 char *buf;
79 size_t len;
80 size_t size;
81 size_t cursor;
82 };
83
84 /* Command line auxiliary functions. */
85 static void cl_beep(struct cmdline *);
86 static void cl_flush(struct cmdline *);
87 static int cl_getc(struct cmdline *);
88 static Char *cl_lastw(struct cmdline *);
89 static void cl_putc(struct cmdline *, int);
90 static void cl_visc(struct cmdline *, int);
91
92 /* Command line editing functions. */
93 static int cl_abort(struct cmdline *, int);
94 static int cl_erasec(struct cmdline *, int);
95 static int cl_erasew(struct cmdline *, int);
96 static int cl_insert(struct cmdline *, int);
97 static int cl_kill(struct cmdline *, int);
98 static int cl_list(struct cmdline *, int);
99 static int cl_literal(struct cmdline *, int);
100 static int cl_recognize(struct cmdline *, int);
101 static int cl_reprint(struct cmdline *, int);
102 static int cl_status(struct cmdline *, int);
103
104 static const struct termios *setup_tty(int);
105
106 static void catn(Char *, Char *, int);
107 static void copyn(Char *, Char *, int);
108 static Char filetype(Char *, Char *);
109 static void print_by_column(Char *, Char *[], int);
110 static Char *tilde(Char *, Char *);
111 static void extract_dir_and_name(Char *, Char *, Char *);
112 static Char *getentry(DIR *, int);
113 static void free_items(Char **, int);
114 static int tsearch(Char *, COMMAND, int);
115 static int recognize(Char *, Char *, int, int);
116 static int is_prefix(Char *, Char *);
117 static int is_suffix(Char *, Char *);
118 static int ignored(Char *);
119
120 /*
121 * Put this here so the binary can be patched with adb to enable file
122 * completion by default. Filec controls completion, nobeep controls
123 * ringing the terminal bell on incomplete expansions.
124 */
125 bool filec = 0;
126
127 static void
cl_flush(struct cmdline * cl)128 cl_flush(struct cmdline *cl)
129 {
130 size_t i, len;
131 int c;
132
133 if (cl->flags & CL_PROMPT) {
134 cl->flags &= ~CL_PROMPT;
135 printprompt();
136 }
137
138 if (cl->cursor < cl->len) {
139 for (; cl->cursor < cl->len; cl->cursor++)
140 cl_visc(cl, cl->buf[cl->cursor]);
141 } else if (cl->cursor > cl->len) {
142 len = cl->cursor - cl->len;
143 for (i = len; i > 0; i--) {
144 c = cl->buf[--cl->cursor];
145 if (c == '\t')
146 len += TABWIDTH - 1;
147 else if (iscntrl(c))
148 len++; /* account for leading ^ */
149 }
150 for (i = 0; i < len; i++)
151 cl_putc(cl, '\b');
152 for (i = 0; i < len; i++)
153 cl_putc(cl, ' ');
154 for (i = 0; i < len; i++)
155 cl_putc(cl, '\b');
156 cl->cursor = cl->len;
157 }
158 }
159
160 static int
cl_getc(struct cmdline * cl)161 cl_getc(struct cmdline *cl)
162 {
163 ssize_t n;
164 unsigned char c;
165
166 for (;;) {
167 n = read(cl->fdin, &c, 1);
168 switch (n) {
169 case -1:
170 if (errno == EINTR)
171 continue;
172 /* FALLTHROUGH */
173 case 0:
174 return 0;
175 default:
176 return c & 0x7F;
177 }
178 }
179 }
180
181 static Char *
cl_lastw(struct cmdline * cl)182 cl_lastw(struct cmdline *cl)
183 {
184 static Char word[BUFSIZ];
185 const unsigned char *delimiters = " '\"\t;&<>()|^%";
186 Char *cp;
187 size_t i;
188
189 for (i = cl->len; i > 0; i--)
190 if (strchr(delimiters, cl->buf[i - 1]) != NULL)
191 break;
192
193 cp = word;
194 for (; i < cl->len; i++)
195 *cp++ = cl->buf[i];
196 *cp = '\0';
197
198 return word;
199 }
200
201 static void
cl_putc(struct cmdline * cl,int c)202 cl_putc(struct cmdline *cl, int c)
203 {
204 unsigned char cc = c;
205
206 write(cl->fdout, &cc, 1);
207 }
208
209 static void
cl_visc(struct cmdline * cl,int c)210 cl_visc(struct cmdline *cl, int c)
211 {
212 #define UNCNTRL(x) ((x) == 0x7F ? '?' : ((x) | 0x40))
213 int i;
214
215 if (c == '\t') {
216 for (i = 0; i < TABWIDTH; i++)
217 cl_putc(cl, ' ');
218 } else if (c != '\n' && iscntrl(c)) {
219 cl_putc(cl, '^');
220 cl_putc(cl, UNCNTRL(c));
221 } else {
222 cl_putc(cl, c);
223 }
224 }
225
226 static int
cl_abort(struct cmdline * cl,int c)227 cl_abort(struct cmdline *cl, int c)
228 {
229 cl_visc(cl, c);
230
231 /* Abort while/foreach loop prematurely. */
232 if (whyles) {
233 if (cl->istty)
234 setup_tty(0);
235 kill(getpid(), SIGINT);
236 }
237
238 cl_putc(cl, '\n');
239 cl->len = cl->cursor = 0;
240 cl->flags |= CL_PROMPT;
241
242 return 0;
243 }
244
245 static int
cl_erasec(struct cmdline * cl,int c)246 cl_erasec(struct cmdline *cl, int c)
247 {
248 if (cl->len > 0)
249 cl->len--;
250
251 return 0;
252 }
253
254 static int
cl_erasew(struct cmdline * cl,int c)255 cl_erasew(struct cmdline *cl, int c)
256 {
257 const unsigned char *ws = " \t";
258
259 for (; cl->len > 0; cl->len--)
260 if (strchr(ws, cl->buf[cl->len - 1]) == NULL &&
261 ((cl->flags & CL_ALTWERASE) == 0 ||
262 isalpha(cl->buf[cl->len - 1])))
263 break;
264 for (; cl->len > 0; cl->len--)
265 if (strchr(ws, cl->buf[cl->len - 1]) != NULL ||
266 ((cl->flags & CL_ALTWERASE) &&
267 !isalpha(cl->buf[cl->len - 1])))
268 break;
269
270 return 0;
271 }
272
273 static void
cl_beep(struct cmdline * cl)274 cl_beep(struct cmdline *cl)
275 {
276 if (adrof(STRnobeep) == 0)
277 cl_putc(cl, '\007');
278 }
279
280 static int
cl_insert(struct cmdline * cl,int c)281 cl_insert(struct cmdline *cl, int c)
282 {
283 if (cl->len == cl->size)
284 return 1;
285
286 cl->buf[cl->len++] = c;
287
288 if (c == '\n')
289 return 1;
290
291 return 0;
292 }
293
294 static int
cl_kill(struct cmdline * cl,int c)295 cl_kill(struct cmdline *cl, int c)
296 {
297 cl->len = 0;
298
299 return 0;
300 }
301
302 static int
cl_list(struct cmdline * cl,int c)303 cl_list(struct cmdline *cl, int c)
304 {
305 Char *word;
306 size_t len;
307
308 if (adrof(STRignoreeof) || cl->len > 0)
309 cl_visc(cl, c);
310
311 if (cl->len == 0)
312 return 1;
313
314 cl_putc(cl, '\n');
315 cl->cursor = 0;
316 cl->flags |= CL_PROMPT;
317
318 word = cl_lastw(cl);
319 len = Strlen(word);
320 tsearch(word, LIST, BUFSIZ - len - 1); /* NUL */
321
322 return 0;
323 }
324
325 static int
cl_literal(struct cmdline * cl,int c)326 cl_literal(struct cmdline *cl, int c)
327 {
328 int literal;
329
330 literal = cl_getc(cl);
331 if (literal == '\n')
332 literal = '\r';
333 cl_insert(cl, literal);
334
335 return 0;
336 }
337
338 static int
cl_recognize(struct cmdline * cl,int c)339 cl_recognize(struct cmdline *cl, int c)
340 {
341 Char *word;
342 size_t len;
343 int nitems;
344
345 if (cl->len == 0) {
346 cl_beep(cl);
347 return 0;
348 }
349
350 word = cl_lastw(cl);
351 len = Strlen(word);
352 nitems = tsearch(word, RECOGNIZE, BUFSIZ - len - 1); /* NUL */
353 for (word += len; *word != '\0'; word++)
354 cl_insert(cl, *word);
355 if (nitems != 1)
356 cl_beep(cl);
357
358 return 0;
359 }
360
361 static int
cl_reprint(struct cmdline * cl,int c)362 cl_reprint(struct cmdline *cl, int c)
363 {
364 cl_visc(cl, c);
365 cl_putc(cl, '\n');
366 cl->cursor = 0;
367
368 return 0;
369 }
370
371 static int
cl_status(struct cmdline * cl,int c)372 cl_status(struct cmdline *cl, int c)
373 {
374 cl->cursor = 0;
375 if (cl->istty)
376 ioctl(cl->fdin, TIOCSTAT);
377
378 return 0;
379 }
380
381 const struct termios *
setup_tty(int on)382 setup_tty(int on)
383 {
384 static struct termios newtio, oldtio;
385
386 if (on) {
387 tcgetattr(SHIN, &oldtio);
388
389 newtio = oldtio;
390 newtio.c_lflag &= ~(ECHO | ICANON | ISIG);
391 newtio.c_cc[VEOL] = ESC;
392 newtio.c_cc[VLNEXT] = _POSIX_VDISABLE;
393 newtio.c_cc[VMIN] = 1;
394 newtio.c_cc[VTIME] = 0;
395 } else {
396 newtio = oldtio;
397 }
398
399 tcsetattr(SHIN, TCSADRAIN, &newtio);
400
401 /*
402 * Since VLNEXT is disabled, restore its previous value in order to make
403 * the key detectable.
404 */
405 newtio.c_cc[VLNEXT] = oldtio.c_cc[VLNEXT];
406
407 return &newtio;
408 }
409
410 /*
411 * Concatenate src onto tail of des.
412 * Des is a string whose maximum length is count.
413 * Always null terminate.
414 */
415 static void
catn(Char * des,Char * src,int count)416 catn(Char *des, Char *src, int count)
417 {
418 while (--count >= 0 && *des)
419 des++;
420 while (--count >= 0)
421 if ((*des++ = *src++) == 0)
422 return;
423 *des = '\0';
424 }
425
426 /*
427 * Places Char's like strlcpy, but no special return value.
428 */
429 static void
copyn(Char * des,Char * src,int count)430 copyn(Char *des, Char *src, int count)
431 {
432 while (--count >= 0)
433 if ((*des++ = *src++) == 0)
434 return;
435 *des = '\0';
436 }
437
438 static Char
filetype(Char * dir,Char * file)439 filetype(Char *dir, Char *file)
440 {
441 Char path[PATH_MAX];
442 struct stat statb;
443
444 Strlcpy(path, dir, sizeof path/sizeof(Char));
445 catn(path, file, sizeof(path) / sizeof(Char));
446 if (lstat(short2str(path), &statb) == 0) {
447 switch (statb.st_mode & S_IFMT) {
448 case S_IFDIR:
449 return ('/');
450
451 case S_IFLNK:
452 if (stat(short2str(path), &statb) == 0 && /* follow it out */
453 S_ISDIR(statb.st_mode))
454 return ('>');
455 else
456 return ('@');
457
458 case S_IFSOCK:
459 return ('=');
460
461 default:
462 if (statb.st_mode & 0111)
463 return ('*');
464 }
465 }
466 return (' ');
467 }
468
469 /*
470 * Print sorted down columns
471 */
472 static void
print_by_column(Char * dir,Char * items[],int count)473 print_by_column(Char *dir, Char *items[], int count)
474 {
475 struct winsize win;
476 int i, rows, r, c, maxwidth = 0, columns;
477
478 if (ioctl(SHOUT, TIOCGWINSZ, (ioctl_t) & win) == -1 || win.ws_col == 0)
479 win.ws_col = 80;
480 for (i = 0; i < count; i++)
481 maxwidth = maxwidth > (r = Strlen(items[i])) ? maxwidth : r;
482 maxwidth += 2; /* for the file tag and space */
483 columns = win.ws_col / maxwidth;
484 if (columns == 0)
485 columns = 1;
486 rows = (count + (columns - 1)) / columns;
487 for (r = 0; r < rows; r++) {
488 for (c = 0; c < columns; c++) {
489 i = c * rows + r;
490 if (i < count) {
491 int w;
492
493 (void) fprintf(cshout, "%s", vis_str(items[i]));
494 (void) fputc(dir ? filetype(dir, items[i]) : ' ', cshout);
495 if (c < columns - 1) { /* last column? */
496 w = Strlen(items[i]) + 1;
497 for (; w < maxwidth; w++)
498 (void) fputc(' ', cshout);
499 }
500 }
501 }
502 (void) fputc('\r', cshout);
503 (void) fputc('\n', cshout);
504 }
505 }
506
507 /*
508 * Expand file name with possible tilde usage
509 * ~person/mumble
510 * expands to
511 * home_directory_of_person/mumble
512 */
513 static Char *
tilde(Char * new,Char * old)514 tilde(Char *new, Char *old)
515 {
516 Char *o, *p;
517 struct passwd *pw;
518 static Char person[40];
519
520 if (old[0] != '~') {
521 Strlcpy(new, old, PATH_MAX);
522 return new;
523 }
524
525 for (p = person, o = &old[1]; *o && *o != '/'; *p++ = *o++)
526 continue;
527 *p = '\0';
528 if (person[0] == '\0')
529 (void) Strlcpy(new, value(STRhome), PATH_MAX);
530 else {
531 pw = getpwnam(short2str(person));
532 if (pw == NULL)
533 return (NULL);
534 (void) Strlcpy(new, str2short(pw->pw_dir), PATH_MAX);
535 }
536 (void) Strlcat(new, o, PATH_MAX);
537 return (new);
538 }
539
540 /*
541 * Parse full path in file into 2 parts: directory and file names
542 * Should leave final slash (/) at end of dir.
543 */
544 static void
extract_dir_and_name(Char * path,Char * dir,Char * name)545 extract_dir_and_name(Char *path, Char *dir, Char *name)
546 {
547 Char *p;
548
549 p = Strrchr(path, '/');
550 if (p == NULL) {
551 copyn(name, path, MAXNAMLEN);
552 dir[0] = '\0';
553 }
554 else {
555 copyn(name, ++p, MAXNAMLEN);
556 copyn(dir, path, p - path);
557 }
558 }
559
560 static Char *
getentry(DIR * dir_fd,int looking_for_lognames)561 getentry(DIR *dir_fd, int looking_for_lognames)
562 {
563 struct passwd *pw;
564 struct dirent *dirp;
565
566 if (looking_for_lognames) {
567 if ((pw = getpwent()) == NULL)
568 return (NULL);
569 return (str2short(pw->pw_name));
570 }
571 if ((dirp = readdir(dir_fd)) != NULL)
572 return (str2short(dirp->d_name));
573 return (NULL);
574 }
575
576 static void
free_items(Char ** items,int numitems)577 free_items(Char **items, int numitems)
578 {
579 int i;
580
581 for (i = 0; i < numitems; i++)
582 free(items[i]);
583 free(items);
584 }
585
586 #define FREE_ITEMS(items) { \
587 sigset_t sigset, osigset;\
588 \
589 sigemptyset(&sigset);\
590 sigaddset(&sigset, SIGINT);\
591 sigprocmask(SIG_BLOCK, &sigset, &osigset);\
592 free_items(items, numitems);\
593 sigprocmask(SIG_SETMASK, &osigset, NULL);\
594 }
595
596 /*
597 * Perform a RECOGNIZE or LIST command on string "word".
598 */
599 static int
tsearch(Char * word,COMMAND command,int max_word_length)600 tsearch(Char *word, COMMAND command, int max_word_length)
601 {
602 DIR *dir_fd;
603 int numitems = 0, ignoring = TRUE, nignored = 0;
604 int name_length, looking_for_lognames;
605 Char tilded_dir[PATH_MAX], dir[PATH_MAX];
606 Char name[MAXNAMLEN + 1], extended_name[MAXNAMLEN + 1];
607 Char *entry;
608 Char **items = NULL;
609 size_t maxitems = 0;
610
611 looking_for_lognames = (*word == '~') && (Strchr(word, '/') == NULL);
612 if (looking_for_lognames) {
613 (void) setpwent();
614 copyn(name, &word[1], MAXNAMLEN); /* name sans ~ */
615 dir_fd = NULL;
616 }
617 else {
618 extract_dir_and_name(word, dir, name);
619 if (tilde(tilded_dir, dir) == 0)
620 return (0);
621 dir_fd = opendir(*tilded_dir ? short2str(tilded_dir) : ".");
622 if (dir_fd == NULL)
623 return (0);
624 }
625
626 again: /* search for matches */
627 name_length = Strlen(name);
628 for (numitems = 0; (entry = getentry(dir_fd, looking_for_lognames)) != NULL;) {
629 if (!is_prefix(name, entry))
630 continue;
631 /* Don't match . files on null prefix match */
632 if (name_length == 0 && entry[0] == '.' &&
633 !looking_for_lognames)
634 continue;
635 if (command == LIST) {
636 if (numitems >= maxitems) {
637 maxitems += 1024;
638 items = xreallocarray(items, maxitems, sizeof(*items));
639 }
640 items[numitems] = xreallocarray(NULL, (Strlen(entry) + 1), sizeof(Char));
641 copyn(items[numitems], entry, MAXNAMLEN);
642 numitems++;
643 }
644 else { /* RECOGNIZE command */
645 if (ignoring && ignored(entry))
646 nignored++;
647 else if (recognize(extended_name,
648 entry, name_length, ++numitems))
649 break;
650 }
651 }
652 if (ignoring && numitems == 0 && nignored > 0) {
653 ignoring = FALSE;
654 nignored = 0;
655 if (looking_for_lognames)
656 (void) setpwent();
657 else
658 rewinddir(dir_fd);
659 goto again;
660 }
661
662 if (looking_for_lognames)
663 (void) endpwent();
664 else
665 (void) closedir(dir_fd);
666 if (numitems == 0)
667 return (0);
668 if (command == RECOGNIZE) {
669 if (looking_for_lognames)
670 copyn(word, STRtilde, 1);
671 else
672 /* put back dir part */
673 copyn(word, dir, max_word_length);
674 /* add extended name */
675 catn(word, extended_name, max_word_length);
676 return (numitems);
677 }
678 else { /* LIST */
679 qsort(items, numitems, sizeof(*items), sortscmp);
680 print_by_column(looking_for_lognames ? NULL : tilded_dir,
681 items, numitems);
682 if (items != NULL)
683 FREE_ITEMS(items);
684 }
685 return (0);
686 }
687
688 /*
689 * Object: extend what user typed up to an ambiguity.
690 * Algorithm:
691 * On first match, copy full entry (assume it'll be the only match)
692 * On subsequent matches, shorten extended_name to the first
693 * Character mismatch between extended_name and entry.
694 * If we shorten it back to the prefix length, stop searching.
695 */
696 static int
recognize(Char * extended_name,Char * entry,int name_length,int numitems)697 recognize(Char *extended_name, Char *entry, int name_length, int numitems)
698 {
699 if (numitems == 1) /* 1st match */
700 copyn(extended_name, entry, MAXNAMLEN);
701 else { /* 2nd & subsequent matches */
702 Char *x, *ent;
703 int len = 0;
704
705 x = extended_name;
706 for (ent = entry; *x && *x == *ent++; x++, len++)
707 continue;
708 *x = '\0'; /* Shorten at 1st Char diff */
709 if (len == name_length) /* Ambiguous to prefix? */
710 return (-1); /* So stop now and save time */
711 }
712 return (0);
713 }
714
715 /*
716 * Return true if check matches initial Chars in template.
717 * This differs from PWB imatch in that if check is null
718 * it matches anything.
719 */
720 static int
is_prefix(Char * check,Char * template)721 is_prefix(Char *check, Char *template)
722 {
723 do
724 if (*check == 0)
725 return (TRUE);
726 while (*check++ == *template++);
727 return (FALSE);
728 }
729
730 /*
731 * Return true if the Chars in template appear at the
732 * end of check, I.e., are its suffix.
733 */
734 static int
is_suffix(Char * check,Char * template)735 is_suffix(Char *check, Char *template)
736 {
737 Char *c, *t;
738
739 for (c = check; *c++;)
740 continue;
741 for (t = template; *t++;)
742 continue;
743 for (;;) {
744 if (t == template)
745 return 1;
746 if (c == check || *--t != *--c)
747 return 0;
748 }
749 }
750
751 int
tenex(Char * inputline,int inputline_size)752 tenex(Char *inputline, int inputline_size)
753 {
754 static struct {
755 int (*fn)(struct cmdline *, int);
756 int idx;
757 } keys[] = {
758 { cl_abort, VINTR },
759 { cl_erasec, VERASE },
760 { cl_erasew, VWERASE },
761 { cl_kill, VKILL },
762 { cl_list, VEOF },
763 { cl_literal, VLNEXT },
764 { cl_recognize, VEOL },
765 { cl_reprint, VREPRINT },
766 { cl_status, VSTATUS },
767 { cl_insert, -1 }
768 };
769 unsigned char buf[BUFSIZ];
770 const struct termios *tio;
771 struct cmdline cl;
772 size_t i;
773 int c, ret;
774
775 memset(&cl, 0, sizeof(cl));
776 cl.fdin = SHIN;
777 cl.fdout = SHOUT;
778 cl.istty = isatty(SHIN);
779
780 if (cl.istty)
781 tio = setup_tty(1);
782
783 cl.buf = buf;
784 cl.size = sizeof(buf);
785 if (inputline_size < cl.size)
786 cl.size = inputline_size;
787 if (cl.istty && tio->c_lflag & ALTWERASE)
788 cl.flags |= CL_ALTWERASE;
789 if (needprompt) {
790 needprompt = 0;
791 cl.flags |= CL_PROMPT;
792 cl_flush(&cl);
793 }
794
795 for (;;) {
796 if ((c = cl_getc(&cl)) == 0)
797 break;
798
799 for (i = 0; keys[i].idx >= 0; i++)
800 if (cl.istty && CCEQ(tio->c_cc[keys[i].idx], c))
801 break;
802 ret = keys[i].fn(&cl, c);
803 cl_flush(&cl);
804 if (ret)
805 break;
806 }
807
808 if (cl.istty)
809 setup_tty(0);
810
811 for (i = 0; i < cl.len; i++)
812 inputline[i] = cl.buf[i];
813 /*
814 * NUL-terminating the buffer implies that it contains a complete
815 * command ready to be executed. Therefore, don't terminate if the
816 * buffer is full since more characters must be read in order to form a
817 * complete command.
818 */
819 if (i < cl.size)
820 inputline[i] = '\0';
821
822 return cl.len;
823 }
824
825 static int
ignored(Char * entry)826 ignored(Char *entry)
827 {
828 struct varent *vp;
829 Char **cp;
830
831 if ((vp = adrof(STRfignore)) == NULL || (cp = vp->vec) == NULL)
832 return (FALSE);
833 for (; *cp != NULL; cp++)
834 if (is_suffix(entry, *cp))
835 return (TRUE);
836 return (FALSE);
837 }
838