Bug Summary

File:src/bin/csh/file.c
Warning:line 800, column 20
Array access (via field 'c_cc') results in an undefined pointer dereference

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name file.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/bin/csh/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/bin/csh -I . -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/bin/csh/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/bin/csh/file.c
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(*__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 TRUE1
57#define TRUE1 1
58#endif
59#ifndef FALSE0
60#define FALSE0 0
61#endif
62
63#define ESC'\033' '\033'
64#define TABWIDTH8 8
65
66typedef enum {
67 LIST,
68 RECOGNIZE
69} COMMAND;
70
71struct cmdline {
72 int fdin;
73 int fdout;
74 int istty;
75 int flags;
76#define CL_ALTWERASE0x1 0x1
77#define CL_PROMPT0x2 0x2
78 char *buf;
79 size_t len;
80 size_t size;
81 size_t cursor;
82};
83
84/* Command line auxiliary functions. */
85static void cl_beep(struct cmdline *);
86static void cl_flush(struct cmdline *);
87static int cl_getc(struct cmdline *);
88static Char *cl_lastw(struct cmdline *);
89static void cl_putc(struct cmdline *, int);
90static void cl_visc(struct cmdline *, int);
91
92/* Command line editing functions. */
93static int cl_abort(struct cmdline *, int);
94static int cl_erasec(struct cmdline *, int);
95static int cl_erasew(struct cmdline *, int);
96static int cl_insert(struct cmdline *, int);
97static int cl_kill(struct cmdline *, int);
98static int cl_list(struct cmdline *, int);
99static int cl_literal(struct cmdline *, int);
100static int cl_recognize(struct cmdline *, int);
101static int cl_reprint(struct cmdline *, int);
102static int cl_status(struct cmdline *, int);
103
104static const struct termios *setup_tty(int);
105
106static void catn(Char *, Char *, int);
107static void copyn(Char *, Char *, int);
108static Char filetype(Char *, Char *);
109static void print_by_column(Char *, Char *[], int);
110static Char *tilde(Char *, Char *);
111static void extract_dir_and_name(Char *, Char *, Char *);
112static Char *getentry(DIR *, int);
113static void free_items(Char **, int);
114static int tsearch(Char *, COMMAND, int);
115static int recognize(Char *, Char *, int, int);
116static int is_prefix(Char *, Char *);
117static int is_suffix(Char *, Char *);
118static 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 */
125bool filec = 0;
126
127static void
128cl_flush(struct cmdline *cl)
129{
130 size_t i, len;
131 int c;
132
133 if (cl->flags & CL_PROMPT0x2) {
134 cl->flags &= ~CL_PROMPT0x2;
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 += TABWIDTH8 - 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
160static int
161cl_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(*__errno()) == EINTR4)
171 continue;
172 /* FALLTHROUGH */
173 case 0:
174 return 0;
175 default:
176 return c & 0x7F;
177 }
178 }
179}
180
181static Char *
182cl_lastw(struct cmdline *cl)
183{
184 static Char word[BUFSIZ1024];
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((void *)0))
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
201static void
202cl_putc(struct cmdline *cl, int c)
203{
204 unsigned char cc = c;
205
206 write(cl->fdout, &cc, 1);
207}
208
209static void
210cl_visc(struct cmdline *cl, int c)
211{
212#define UNCNTRL(x)((x) == 0x7F ? '?' : ((x) | 0x40)) ((x) == 0x7F ? '?' : ((x) | 0x40))
213 int i;
214
215 if (c == '\t') {
216 for (i = 0; i < TABWIDTH8; i++)
217 cl_putc(cl, ' ');
218 } else if (c != '\n' && iscntrl(c)) {
219 cl_putc(cl, '^');
220 cl_putc(cl, UNCNTRL(c)((c) == 0x7F ? '?' : ((c) | 0x40)));
221 } else {
222 cl_putc(cl, c);
223 }
224}
225
226static int
227cl_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(), SIGINT2);
236 }
237
238 cl_putc(cl, '\n');
239 cl->len = cl->cursor = 0;
240 cl->flags |= CL_PROMPT0x2;
241
242 return 0;
243}
244
245static int
246cl_erasec(struct cmdline *cl, int c)
247{
248 if (cl->len > 0)
249 cl->len--;
250
251 return 0;
252}
253
254static int
255cl_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((void *)0) &&
261 ((cl->flags & CL_ALTWERASE0x1) == 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((void *)0) ||
266 ((cl->flags & CL_ALTWERASE0x1) &&
267 !isalpha(cl->buf[cl->len - 1])))
268 break;
269
270 return 0;
271}
272
273static void
274cl_beep(struct cmdline *cl)
275{
276 if (adrof(STRnobeep)adrof1(STRnobeep, &shvhed) == 0)
277 cl_putc(cl, '\007');
278}
279
280static int
281cl_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
294static int
295cl_kill(struct cmdline *cl, int c)
296{
297 cl->len = 0;
298
299 return 0;
300}
301
302static int
303cl_list(struct cmdline *cl, int c)
304{
305 Char *word;
306 size_t len;
307
308 if (adrof(STRignoreeof)adrof1(STRignoreeof, &shvhed) || 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_PROMPT0x2;
317
318 word = cl_lastw(cl);
319 len = Strlen(word);
320 tsearch(word, LIST, BUFSIZ1024 - len - 1); /* NUL */
321
322 return 0;
323}
324
325static int
326cl_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
338static int
339cl_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, BUFSIZ1024 - 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
361static int
362cl_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
371static int
372cl_status(struct cmdline *cl, int c)
373{
374 cl->cursor = 0;
375 if (cl->istty)
376 ioctl(cl->fdin, TIOCSTAT((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) |
((('t')) << 8) | ((101)))
);
377
378 return 0;
379}
380
381const struct termios *
382setup_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 &= ~(ECHO0x00000008 | ICANON0x00000100 | ISIG0x00000080);
391 newtio.c_cc[VEOL1] = ESC'\033';
392 newtio.c_cc[VLNEXT14] = _POSIX_VDISABLE(0377);
393 newtio.c_cc[VMIN16] = 1;
394 newtio.c_cc[VTIME17] = 0;
395 } else {
396 newtio = oldtio;
397 }
398
399 tcsetattr(SHIN, TCSADRAIN1, &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[VLNEXT14] = oldtio.c_cc[VLNEXT14];
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 */
415static void
416catn(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 */
429static void
430copyn(Char *des, Char *src, int count)
431{
432 while (--count >= 0)
433 if ((*des++ = *src++) == 0)
434 return;
435 *des = '\0';
436}
437
438static Char
439filetype(Char *dir, Char *file)
440{
441 Char path[PATH_MAX1024];
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_IFMT0170000) {
448 case S_IFDIR0040000:
449 return ('/');
450
451 case S_IFLNK0120000:
452 if (stat(short2str(path), &statb) == 0 && /* follow it out */
453 S_ISDIR(statb.st_mode)((statb.st_mode & 0170000) == 0040000))
454 return ('>');
455 else
456 return ('@');
457
458 case S_IFSOCK0140000:
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 */
472static void
473print_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((unsigned long)0x40000000 | ((sizeof(struct winsize) & 0x1fff
) << 16) | ((('t')) << 8) | ((104)))
, (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 */
513static Char *
514tilde(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_MAX1024);
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)value1(STRhome, &shvhed), PATH_MAX1024);
530 else {
531 pw = getpwnam(short2str(person));
532 if (pw == NULL((void *)0))
533 return (NULL((void *)0));
534 (void) Strlcpy(new, str2short(pw->pw_dir), PATH_MAX1024);
535 }
536 (void) Strlcat(new, o, PATH_MAX1024);
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 */
544static void
545extract_dir_and_name(Char *path, Char *dir, Char *name)
546{
547 Char *p;
548
549 p = Strrchr(path, '/');
550 if (p == NULL((void *)0)) {
551 copyn(name, path, MAXNAMLEN255);
552 dir[0] = '\0';
553 }
554 else {
555 copyn(name, ++p, MAXNAMLEN255);
556 copyn(dir, path, p - path);
557 }
558}
559
560static Char *
561getentry(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((void *)0))
568 return (NULL((void *)0));
569 return (str2short(pw->pw_name));
570 }
571 if ((dirp = readdir(dir_fd)) != NULL((void *)0))
572 return (str2short(dirp->d_name));
573 return (NULL((void *)0));
574}
575
576static void
577free_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){ sigset_t sigset, osigset; sigemptyset(&sigset); sigaddset
(&sigset, 2); sigprocmask(1, &sigset, &osigset); free_items
(items, numitems); sigprocmask(3, &osigset, ((void *)0));
}
{ \
587 sigset_t sigset, osigset;\
588\
589 sigemptyset(&sigset);\
590 sigaddset(&sigset, SIGINT2);\
591 sigprocmask(SIG_BLOCK1, &sigset, &osigset);\
592 free_items(items, numitems);\
593 sigprocmask(SIG_SETMASK3, &osigset, NULL((void *)0));\
594}
595
596/*
597 * Perform a RECOGNIZE or LIST command on string "word".
598 */
599static int
600tsearch(Char *word, COMMAND command, int max_word_length)
601{
602 DIR *dir_fd;
603 int numitems = 0, ignoring = TRUE1, nignored = 0;
604 int name_length, looking_for_lognames;
605 Char tilded_dir[PATH_MAX1024], dir[PATH_MAX1024];
606 Char name[MAXNAMLEN255 + 1], extended_name[MAXNAMLEN255 + 1];
607 Char *entry;
608 Char **items = NULL((void *)0);
609 size_t maxitems = 0;
610
611 looking_for_lognames = (*word == '~') && (Strchr(word, '/') == NULL((void *)0));
612 if (looking_for_lognames) {
613 (void) setpwent();
614 copyn(name, &word[1], MAXNAMLEN255); /* name sans ~ */
615 dir_fd = NULL((void *)0);
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((void *)0))
623 return (0);
624 }
625
626again: /* search for matches */
627 name_length = Strlen(name);
628 for (numitems = 0; (entry = getentry(dir_fd, looking_for_lognames)) != NULL((void *)0);) {
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((void *)0), (Strlen(entry) + 1), sizeof(Char));
641 copyn(items[numitems], entry, MAXNAMLEN255);
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 = FALSE0;
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((void *)0) : tilded_dir,
681 items, numitems);
682 if (items != NULL((void *)0))
683 FREE_ITEMS(items){ sigset_t sigset, osigset; sigemptyset(&sigset); sigaddset
(&sigset, 2); sigprocmask(1, &sigset, &osigset); free_items
(items, numitems); sigprocmask(3, &osigset, ((void *)0));
}
;
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 */
696static int
697recognize(Char *extended_name, Char *entry, int name_length, int numitems)
698{
699 if (numitems == 1) /* 1st match */
700 copyn(extended_name, entry, MAXNAMLEN255);
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 */
720static int
721is_prefix(Char *check, Char *template)
722{
723 do
724 if (*check == 0)
725 return (TRUE1);
726 while (*check++ == *template++);
727 return (FALSE0);
728}
729
730/*
731 * Return true if the Chars in template appear at the
732 * end of check, I.e., are its suffix.
733 */
734static int
735is_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
751int
752tenex(Char *inputline, int inputline_size)
753{
754 static struct {
755 int (*fn)(struct cmdline *, int);
756 int idx;
757 } keys[] = {
758 { cl_abort, VINTR8 },
759 { cl_erasec, VERASE3 },
760 { cl_erasew, VWERASE4 },
761 { cl_kill, VKILL5 },
762 { cl_list, VEOF0 },
763 { cl_literal, VLNEXT14 },
764 { cl_recognize, VEOL1 },
765 { cl_reprint, VREPRINT6 },
766 { cl_status, VSTATUS18 },
767 { cl_insert, -1 }
768 };
769 unsigned char buf[BUFSIZ1024];
770 const struct termios *tio;
1
'tio' declared without an initial value
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)
2
Assuming field 'istty' is 0
3
Taking false branch
781 tio = setup_tty(1);
782
783 cl.buf = buf;
784 cl.size = sizeof(buf);
785 if (inputline_size < cl.size)
4
Assuming 'inputline_size' is >= field 'size'
5
Taking false branch
786 cl.size = inputline_size;
787 if (cl.istty
5.1
Field 'istty' is 0
&& tio->c_lflag & ALTWERASE0x00000200)
788 cl.flags |= CL_ALTWERASE0x1;
789 if (needprompt) {
6
Assuming 'needprompt' is 0
7
Taking false branch
790 needprompt = 0;
791 cl.flags |= CL_PROMPT0x2;
792 cl_flush(&cl);
793 }
794
795 for (;;) {
8
Loop condition is true. Entering loop body
796 if ((c = cl_getc(&cl)) == 0)
9
Assuming the condition is false
10
Taking false branch
797 break;
798
799 for (i = 0; keys[i].idx >= 0; i++)
11
Loop condition is true. Entering loop body
800 if (cl.istty && CCEQ(tio->c_cc[keys[i].idx], c)(c == tio->c_cc[keys[i].idx] ? tio->c_cc[keys[i].idx] !=
(0377) : 0)
)
12
Assuming field 'istty' is not equal to 0
13
Array access (via field 'c_cc') results in an undefined pointer dereference
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
825static int
826ignored(Char *entry)
827{
828 struct varent *vp;
829 Char **cp;
830
831 if ((vp = adrof(STRfignore)adrof1(STRfignore, &shvhed)) == NULL((void *)0) || (cp = vp->vec) == NULL((void *)0))
832 return (FALSE0);
833 for (; *cp != NULL((void *)0); cp++)
834 if (is_suffix(entry, *cp))
835 return (TRUE1);
836 return (FALSE0);
837}