Bug Summary

File:src/bin/csh/dol.c
Warning:line 683, column 5
Value stored to 'dp' is never read

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 dol.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/dol.c
1/* $OpenBSD: dol.c,v 1.26 2019/06/28 05:35:34 deraadt Exp $ */
2/* $NetBSD: dol.c,v 1.8 1995/09/27 00:38:38 jtc 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/types.h>
34#include <fcntl.h>
35#include <errno(*__errno()).h>
36#include <stdlib.h>
37#include <string.h>
38#include <unistd.h>
39#include <stdarg.h>
40
41#include "csh.h"
42#include "extern.h"
43
44/*
45 * These routines perform variable substitution and quoting via ' and ".
46 * To this point these constructs have been preserved in the divided
47 * input words. Here we expand variables and turn quoting via ' and " into
48 * QUOTE bits on characters (which prevent further interpretation).
49 * If the `:q' modifier was applied during history expansion, then
50 * some QUOTEing may have occurred already, so we dont "trim()" here.
51 */
52
53static int Dpeekc, Dpeekrd; /* Peeks for DgetC and Dreadc */
54static Char *Dcp, **Dvp; /* Input vector for Dreadc */
55
56#define DEOF-1 -1
57
58#define unDgetC(c)Dpeekc = c Dpeekc = c
59
60#define QUOTES(0x0001|0x0002|0x0040) (_QF0x0001|_QB0x0002|_ESC0x0040) /* \ ' " ` */
61
62/*
63 * The following variables give the information about the current
64 * $ expansion, recording the current word position, the remaining
65 * words within this expansion, the count of remaining words, and the
66 * information about any : modifier which is being applied.
67 */
68#define MAXWLEN(1024 - 4) (BUFSIZ1024 - 4)
69#define MAXMOD(1024 - 4) MAXWLEN(1024 - 4) /* This cannot overflow */
70static Char *dolp; /* Remaining chars from this word */
71static Char **dolnxt; /* Further words */
72static int dolcnt; /* Count of further words */
73static Char dolmod[MAXMOD(1024 - 4)]; /* : modifier character */
74static int dolnmod; /* Number of modifiers */
75static int dolmcnt; /* :gx -> 10000, else 1 */
76static int dolwcnt; /* :wx -> 10000, else 1 */
77
78static void Dfix2(Char **);
79static Char *Dpack(Char *, Char *);
80static int Dword(void);
81static void dolerror(Char *);
82static int DgetC(int);
83static void Dgetdol(void);
84static void fixDolMod(void);
85static void setDolp(Char *);
86static void unDredc(int);
87static int Dredc(void);
88static void Dtestq(int);
89
90
91/*
92 * Fix up the $ expansions and quotations in the
93 * argument list to command t.
94 */
95void
96Dfix(struct command *t)
97{
98 Char **pp;
99 Char *p;
100
101 if (noexec)
102 return;
103 /* Note that t_dcom isn't trimmed thus !...:q's aren't lost */
104 for (pp = t->t_dcom; (p = *pp++) != NULL((void *)0);)
105 for (; *p; p++) {
106 if (cmap(*p, _DOL | QUOTES)(((*p) & 0100000U) ? 0 : (_cmap[(unsigned char)(*p)] &
(0x0080 | (0x0001|0x0002|0x0040))))
) { /* $, \, ', ", ` */
107 Dfix2(t->t_dcom); /* found one */
108 blkfree(t->t_dcom);
109 t->t_dcom = gargv;
110 gargv = 0;
111 return;
112 }
113 }
114}
115
116/*
117 * $ substitute one word, for i/o redirection
118 */
119Char *
120Dfix1(Char *cp)
121{
122 Char *Dv[2];
123
124 if (noexec)
125 return (0);
126 Dv[0] = cp;
127 Dv[1] = NULL((void *)0);
128 Dfix2(Dv);
129 if (gargc != 1) {
130 setname(vis_str(cp))(bname = (vis_str(cp)));
131 stderror(ERR_NAME0x10000000 | ERR_AMBIG40);
132 }
133 cp = Strsave(gargv[0]);
134 blkfree(gargv), gargv = 0;
135 return (cp);
136}
137
138/*
139 * Subroutine to do actual fixing after state initialization.
140 */
141static void
142Dfix2(Char **v)
143{
144 ginit(); /* Initialize glob's area pointers */
145 Dvp = v;
146 Dcp = STRNULL; /* Setup input vector for Dreadc */
147 unDgetC(0)Dpeekc = 0;
148 unDredc(0); /* Clear out any old peeks (at error) */
149 dolp = 0;
150 dolcnt = 0; /* Clear out residual $ expands (...) */
151 while (Dword())
152 continue;
153}
154
155/*
156 * Pack up more characters in this word
157 */
158static Char *
159Dpack(Char *wbuf, Char *wp)
160{
161 int c;
162 int i = MAXWLEN(1024 - 4) - (wp - wbuf);
163
164 for (;;) {
165 c = DgetC(DODOL1);
166 if (c == '\\') {
167 c = DgetC(0);
168 if (c == DEOF-1) {
169 unDredc(c);
170 *wp = 0;
171 Gcat(STRNULL, wbuf);
172 return (NULL((void *)0));
173 }
174 if (c == '\n')
175 c = ' ';
176 else
177 c |= QUOTE0100000U;
178 }
179 if (c == DEOF-1) {
180 unDredc(c);
181 *wp = 0;
182 Gcat(STRNULL, wbuf);
183 return (NULL((void *)0));
184 }
185 if (cmap(c, _SP | _NL | _QF | _QB)(((c) & 0100000U) ? 0 : (_cmap[(unsigned char)(c)] & (
0x0004 | 0x0008 | 0x0001 | 0x0002)))
) { /* sp \t\n'"` */
186 unDgetC(c)Dpeekc = c;
187 if (cmap(c, QUOTES)(((c) & 0100000U) ? 0 : (_cmap[(unsigned char)(c)] & (
(0x0001|0x0002|0x0040))))
)
188 return (wp);
189 *wp++ = 0;
190 Gcat(STRNULL, wbuf);
191 return (NULL((void *)0));
192 }
193 if (--i <= 0)
194 stderror(ERR_WTOOLONG2);
195 *wp++ = c;
196 }
197}
198
199/*
200 * Get a word. This routine is analogous to the routine
201 * word() in sh.lex.c for the main lexical input. One difference
202 * here is that we don't get a newline to terminate our expansion.
203 * Rather, DgetC will return a DEOF when we hit the end-of-input.
204 */
205static int
206Dword(void)
207{
208 int c, c1;
209 Char wbuf[BUFSIZ1024];
210 Char *wp = wbuf;
211 int i = MAXWLEN(1024 - 4);
212 bool dolflg;
213 bool sofar = 0, done = 0;
214
215 while (!done) {
216 done = 1;
217 c = DgetC(DODOL1);
218 switch (c) {
219
220 case DEOF-1:
221 if (sofar == 0)
222 return (0);
223 /* finish this word and catch the code above the next time */
224 unDredc(c);
225 /* fall into ... */
226
227 case '\n':
228 *wp = 0;
229 Gcat(STRNULL, wbuf);
230 return (1);
231
232 case ' ':
233 case '\t':
234 done = 0;
235 break;
236
237 case '`':
238 /* We preserve ` quotations which are done yet later */
239 *wp++ = c, --i;
240 case '\'':
241 case '"':
242 /*
243 * Note that DgetC never returns a QUOTES character from an
244 * expansion, so only true input quotes will get us here or out.
245 */
246 c1 = c;
247 dolflg = c1 == '"' ? DODOL1 : 0;
248 for (;;) {
249 c = DgetC(dolflg);
250 if (c == c1)
251 break;
252 if (c == '\n' || c == DEOF-1)
253 stderror(ERR_UNMATCHED52, c1);
254 if ((c & (QUOTE0100000U | TRIM0077777)) == ('\n' | QUOTE0100000U))
255 --wp, ++i;
256 if (--i <= 0)
257 stderror(ERR_WTOOLONG2);
258 switch (c1) {
259
260 case '"':
261 /*
262 * Leave any `s alone for later. Other chars are all
263 * quoted, thus `...` can tell it was within "...".
264 */
265 *wp++ = c == '`' ? '`' : c | QUOTE0100000U;
266 break;
267
268 case '\'':
269 /* Prevent all further interpretation */
270 *wp++ = c | QUOTE0100000U;
271 break;
272
273 case '`':
274 /* Leave all text alone for later */
275 *wp++ = c;
276 break;
277
278 default:
279 break;
280 }
281 }
282 if (c1 == '`')
283 *wp++ = '`' /* i--; eliminated */;
284 sofar = 1;
285 if ((wp = Dpack(wbuf, wp)) == NULL((void *)0))
286 return (1);
287 else {
288 i = MAXWLEN(1024 - 4) - (wp - wbuf);
289 done = 0;
290 }
291 break;
292
293 case '\\':
294 c = DgetC(0); /* No $ subst! */
295 if (c == '\n' || c == DEOF-1) {
296 done = 0;
297 break;
298 }
299 c |= QUOTE0100000U;
300 break;
301
302 default:
303 break;
304 }
305 if (done) {
306 unDgetC(c)Dpeekc = c;
307 sofar = 1;
308 if ((wp = Dpack(wbuf, wp)) == NULL((void *)0))
309 return (1);
310 else {
311 i = MAXWLEN(1024 - 4) - (wp - wbuf);
312 done = 0;
313 }
314 }
315 }
316 /* Really NOTREACHED */
317 return (0);
318}
319
320
321/*
322 * Get a character, performing $ substitution unless flag is 0.
323 * Any QUOTES character which is returned from a $ expansion is
324 * QUOTEd so that it will not be recognized above.
325 */
326static int
327DgetC(int flag)
328{
329 int c;
330
331top:
332 if ((c = Dpeekc) != '\0') {
333 Dpeekc = 0;
334 return (c);
335 }
336 if (lap) {
337 c = *lap++ & (QUOTE0100000U | TRIM0077777);
338 if (c == 0) {
339 lap = 0;
340 goto top;
341 }
342quotspec:
343 if (cmap(c, QUOTES)(((c) & 0100000U) ? 0 : (_cmap[(unsigned char)(c)] & (
(0x0001|0x0002|0x0040))))
)
344 return (c | QUOTE0100000U);
345 return (c);
346 }
347 if (dolp) {
348 if ((c = *dolp++ & (QUOTE0100000U | TRIM0077777)) != '\0')
349 goto quotspec;
350 if (dolcnt > 0) {
351 setDolp(*dolnxt++);
352 --dolcnt;
353 return (' ');
354 }
355 dolp = 0;
356 }
357 if (dolcnt > 0) {
358 setDolp(*dolnxt++);
359 --dolcnt;
360 goto top;
361 }
362 c = Dredc();
363 if (c == '$' && flag) {
364 Dgetdol();
365 goto top;
366 }
367 return (c);
368}
369
370static Char *nulvec[] = {0};
371static struct varent nulargv = {nulvec, STRargv, { NULL((void *)0), NULL((void *)0), NULL((void *)0) }, 0};
372
373static void
374dolerror(Char *s)
375{
376 setname(vis_str(s))(bname = (vis_str(s)));
377 stderror(ERR_NAME0x10000000 | ERR_RANGE43);
378}
379
380/*
381 * Handle the multitudinous $ expansion forms.
382 * Ugh.
383 */
384static void
385Dgetdol(void)
386{
387 Char *np;
388 struct varent *vp = NULL((void *)0);
389 Char name[4 * MAXVARLEN30 + 1];
390 int c, sc;
391 int subscr = 0, lwb = 1, upb = 0;
392 bool dimen = 0, bitset = 0;
393 char tnp;
394 Char wbuf[BUFSIZ1024];
395 static Char *dolbang = NULL((void *)0);
396
397 dolnmod = dolmcnt = dolwcnt = 0;
398 c = sc = DgetC(0);
399 if (c == '{')
400 c = DgetC(0); /* sc is { to take } later */
401 if ((c & TRIM0077777) == '#')
402 dimen++, c = DgetC(0); /* $# takes dimension */
403 else if (c == '?')
404 bitset++, c = DgetC(0); /* $? tests existence */
405 switch (c) {
406
407 case '!':
408 if (dimen || bitset)
409 stderror(ERR_SYNTAX0);
410 if (backpid != 0) {
411 free(dolbang);
412 setDolp(dolbang = putn(backpid));
413 }
414 goto eatbrac;
415
416 case '$':
417 if (dimen || bitset)
418 stderror(ERR_SYNTAX0);
419 setDolp(doldol);
420 goto eatbrac;
421
422 case '<' | QUOTE0100000U:
423 if (bitset)
424 stderror(ERR_NOTALLOWED1, "$?<");
425 if (dimen)
426 stderror(ERR_NOTALLOWED1, "$?#");
427 for (np = wbuf; read(OLDSTD, &tnp, 1) == 1; np++) {
428 *np = (unsigned char) tnp;
429 if (np >= &wbuf[BUFSIZ1024 - 1])
430 stderror(ERR_LTOOLONG3);
431 if (tnp == '\n')
432 break;
433 }
434 *np = 0;
435 /*
436 * KLUDGE: dolmod is set here because it will cause setDolp to call
437 * domod and thus to copy wbuf. Otherwise setDolp would use it
438 * directly. If we saved it ourselves, no one would know when to free
439 * it. The actual function of the 'q' causes filename expansion not to
440 * be done on the interpolated value.
441 */
442 dolmod[dolnmod++] = 'q';
443 dolmcnt = 10000;
444 setDolp(wbuf);
445 goto eatbrac;
446
447 case DEOF-1:
448 case '\n':
449 stderror(ERR_SYNTAX0);
450 /* NOTREACHED */
451 break;
452
453 case '*':
454 (void) Strlcpy(name, STRargv, sizeof name/sizeof(Char));
455 vp = adrof(STRargv)adrof1(STRargv, &shvhed);
456 subscr = -1; /* Prevent eating [...] */
457 break;
458
459 default:
460 np = name;
461 if (Isdigit(c)(((c) & 0100000U) ? 0 : isdigit((unsigned char) (c)))) {
462 if (dimen)
463 stderror(ERR_NOTALLOWED1, "$#<num>");
464 subscr = 0;
465 do {
466 subscr = subscr * 10 + c - '0';
467 c = DgetC(0);
468 } while (Isdigit(c)(((c) & 0100000U) ? 0 : isdigit((unsigned char) (c))));
469 unDredc(c);
470 if (subscr < 0)
471 stderror(ERR_RANGE43);
472 if (subscr == 0) {
473 if (bitset) {
474 dolp = ffile ? STR1 : STR0;
475 goto eatbrac;
476 }
477 if (ffile == 0)
478 stderror(ERR_DOLZERO4);
479 fixDolMod();
480 setDolp(ffile);
481 goto eatbrac;
482 }
483 if (bitset)
484 stderror(ERR_DOLQUEST5);
485 vp = adrof(STRargv)adrof1(STRargv, &shvhed);
486 if (vp == 0) {
487 vp = &nulargv;
488 goto eatmod;
489 }
490 break;
491 }
492 if (!alnum(c)(((c) & 0100000U) ? 0 : (isalnum((unsigned char) (c)) || (
c) == '_'))
)
493 stderror(ERR_VARALNUM32);
494 for (;;) {
495 *np++ = c;
496 c = DgetC(0);
497 if (!alnum(c)(((c) & 0100000U) ? 0 : (isalnum((unsigned char) (c)) || (
c) == '_'))
)
498 break;
499 if (np >= &name[MAXVARLEN30])
500 stderror(ERR_VARTOOLONG31);
501 }
502 *np++ = 0;
503 unDredc(c);
504 vp = adrof(name)adrof1(name, &shvhed);
505 }
506 if (bitset) {
507 dolp = (vp || getenv(short2str(name))) ? STR1 : STR0;
508 goto eatbrac;
509 }
510 if (vp == 0) {
511 np = str2short(getenv(short2str(name)));
512 if (np) {
513 fixDolMod();
514 setDolp(np);
515 goto eatbrac;
516 }
517 udvar(name);
518 /* NOTREACHED */
519 }
520 c = DgetC(0);
521 upb = blklen(vp->vec);
522 if (dimen == 0 && subscr == 0 && c == '[') {
523 np = name;
524 for (;;) {
525 c = DgetC(DODOL1); /* Allow $ expand within [ ] */
526 if (c == ']')
527 break;
528 if (c == '\n' || c == DEOF-1)
529 stderror(ERR_INCBR6);
530 if (np >= &name[sizeof(name) / sizeof(Char) - 2])
531 stderror(ERR_VARTOOLONG31);
532 *np++ = c;
533 }
534 *np = 0, np = name;
535 if (dolp || dolcnt) /* $ exp must end before ] */
536 stderror(ERR_EXPORD7);
537 if (!*np)
538 stderror(ERR_SYNTAX0);
539 if (Isdigit(*np)(((*np) & 0100000U) ? 0 : isdigit((unsigned char) (*np)))) {
540 int i;
541
542 for (i = 0; Isdigit(*np)(((*np) & 0100000U) ? 0 : isdigit((unsigned char) (*np))); i = i * 10 + *np++ - '0')
543 continue;
544 if ((i < 0 || i > upb) && !any("-*", *np)) {
545 dolerror(vp->v_name);
546 return;
547 }
548 lwb = i;
549 if (!*np)
550 upb = lwb, np = STRstar;
551 }
552 if (*np == '*')
553 np++;
554 else if (*np != '-')
555 stderror(ERR_MISSING51, '-');
556 else {
557 int i = upb;
558
559 np++;
560 if (Isdigit(*np)(((*np) & 0100000U) ? 0 : isdigit((unsigned char) (*np)))) {
561 i = 0;
562 while (Isdigit(*np)(((*np) & 0100000U) ? 0 : isdigit((unsigned char) (*np))))
563 i = i * 10 + *np++ - '0';
564 if (i < 0 || i > upb) {
565 dolerror(vp->v_name);
566 return;
567 }
568 }
569 if (i < lwb)
570 upb = lwb - 1;
571 else
572 upb = i;
573 }
574 if (lwb == 0) {
575 if (upb != 0) {
576 dolerror(vp->v_name);
577 return;
578 }
579 upb = -1;
580 }
581 if (*np)
582 stderror(ERR_SYNTAX0);
583 }
584 else {
585 if (subscr > 0) {
586 if (subscr > upb)
587 lwb = 1, upb = 0;
588 else
589 lwb = upb = subscr;
590 }
591 unDredc(c);
592 }
593 if (dimen) {
594 Char *cp = putn(upb - lwb + 1);
595
596 addla(cp);
597 free(cp);
598 }
599 else {
600eatmod:
601 fixDolMod();
602 dolnxt = &vp->vec[lwb - 1];
603 dolcnt = upb - lwb + 1;
604 }
605eatbrac:
606 if (sc == '{') {
607 c = Dredc();
608 if (c != '}')
609 stderror(ERR_MISSING51, '}');
610 }
611}
612
613static void
614fixDolMod(void)
615{
616 int c;
617
618 c = DgetC(0);
619 if (c == ':') {
620 do {
621 c = DgetC(0), dolmcnt = 1, dolwcnt = 1;
622 if (c == 'g' || c == 'a') {
623 if (c == 'g')
624 dolmcnt = 10000;
625 else
626 dolwcnt = 10000;
627 c = DgetC(0);
628 }
629 if ((c == 'g' && dolmcnt != 10000) ||
630 (c == 'a' && dolwcnt != 10000)) {
631 if (c == 'g')
632 dolmcnt = 10000;
633 else
634 dolwcnt = 10000;
635 c = DgetC(0);
636 }
637
638 if (c == 's') { /* [eichin:19910926.0755EST] */
639 int delimcnt = 2;
640 int delim = DgetC(0);
641 dolmod[dolnmod++] = c;
642 dolmod[dolnmod++] = delim;
643
644 if (!delim || letter(delim)(((delim) & 0100000U) ? 0 : (isalpha((unsigned char) (delim
)) || (delim) == '_'))
645 || Isdigit(delim)(((delim) & 0100000U) ? 0 : isdigit((unsigned char) (delim
)))
|| any(" \t\n", delim)) {
646 seterror(ERR_BADSUBST89);
647 break;
648 }
649 while ((c = DgetC(0)) != (-1)) {
650 dolmod[dolnmod++] = c;
651 if(c == delim) delimcnt--;
652 if(!delimcnt) break;
653 }
654 if(delimcnt) {
655 seterror(ERR_BADSUBST89);
656 break;
657 }
658 continue;
659 }
660 if (!any("htrqxes", c))
661 stderror(ERR_BADMOD8, c);
662 dolmod[dolnmod++] = c;
663 if (c == 'q')
664 dolmcnt = 10000;
665 }
666 while ((c = DgetC(0)) == ':');
667 unDredc(c);
668 }
669 else
670 unDredc(c);
671}
672
673static void
674setDolp(Char *cp)
675{
676 Char *dp;
677 int i;
678
679 if (dolnmod == 0 || dolmcnt == 0) {
680 dolp = cp;
681 return;
682 }
683 dp = cp = Strsave(cp);
Value stored to 'dp' is never read
684 for (i = 0; i < dolnmod; i++) {
685 /* handle s// [eichin:19910926.0510EST] */
686 if(dolmod[i] == 's') {
687 int delim;
688 Char *lhsub, *rhsub, *np;
689 size_t lhlen = 0, rhlen = 0;
690 int didmod = 0;
691
692 delim = dolmod[++i];
693 if (!delim || letter(delim)(((delim) & 0100000U) ? 0 : (isalpha((unsigned char) (delim
)) || (delim) == '_'))
694 || Isdigit(delim)(((delim) & 0100000U) ? 0 : isdigit((unsigned char) (delim
)))
|| any(" \t\n", delim)) {
695 seterror(ERR_BADSUBST89);
696 break;
697 }
698 lhsub = &dolmod[++i];
699 while(dolmod[i] != delim && dolmod[++i]) {
700 lhlen++;
701 }
702 dolmod[i] = 0;
703 rhsub = &dolmod[++i];
704 while(dolmod[i] != delim && dolmod[++i]) {
705 rhlen++;
706 }
707 dolmod[i] = 0;
708
709 do {
710 dp = Strstr(cp, lhsub);
711 if (dp) {
712 size_t len = Strlen(cp) + 1 - lhlen + rhlen;
713
714 np = xreallocarray(NULL((void *)0), len, sizeof(Char));
715 *dp = 0;
716 (void) Strlcpy(np, cp, len);
717 (void) Strlcat(np, rhsub, len);
718 (void) Strlcat(np, dp + lhlen, len);
719
720 free(cp);
721 dp = cp = np;
722 didmod = 1;
723 } else {
724 /* should this do a seterror? */
725 break;
726 }
727 }
728 while (dolwcnt == 10000);
729 /*
730 * restore dolmod for additional words
731 */
732 dolmod[i] = rhsub[-1] = delim;
733 if (didmod)
734 dolmcnt--;
735 else
736 break;
737 } else {
738 int didmod = 0;
739
740 do {
741 if ((dp = domod(cp, dolmod[i]))) {
742 didmod = 1;
743 if (Strcmp(cp, dp) == 0) {
744 free(cp);
745 cp = dp;
746 break;
747 }
748 else {
749 free(cp);
750 cp = dp;
751 }
752 }
753 else
754 break;
755 }
756 while (dolwcnt == 10000);
757 dp = cp;
758 if (didmod)
759 dolmcnt--;
760 else
761 break;
762 }
763 }
764
765 addla(cp);
766 free(cp);
767
768 dolp = STRNULL;
769 if (seterr)
770 stderror(ERR_OLD0x40000000);
771}
772
773static void
774unDredc(int c)
775{
776
777 Dpeekrd = c;
778}
779
780static int
781Dredc(void)
782{
783 int c;
784
785 if ((c = Dpeekrd) != '\0') {
786 Dpeekrd = 0;
787 return (c);
788 }
789 if (Dcp && (c = *Dcp++))
790 return (c & (QUOTE0100000U | TRIM0077777));
791 if (*Dvp == 0) {
792 Dcp = 0;
793 return (DEOF-1);
794 }
795 Dcp = *Dvp++;
796 return (' ');
797}
798
799static void
800Dtestq(int c)
801{
802
803 if (cmap(c, QUOTES)(((c) & 0100000U) ? 0 : (_cmap[(unsigned char)(c)] & (
(0x0001|0x0002|0x0040))))
)
804 gflag = 1;
805}
806
807/*
808 * Form a shell temporary file (in unit 0) from the words
809 * of the shell input up to EOF or a line the same as "term".
810 * Unit 0 should have been closed before this call.
811 */
812void
813/*ARGSUSED*/
814heredoc(Char *term)
815{
816 int c;
817 Char *Dv[2];
818 Char obuf[BUFSIZ1024], lbuf[BUFSIZ1024], mbuf[BUFSIZ1024];
819 int ocnt, lcnt, mcnt;
820 Char *lbp, *obp, *mbp;
821 Char **vp;
822 bool quoted;
823 char tmp[] = "/tmp/sh.XXXXXXXX";
824
825 if (mkstemp(tmp) == -1)
826 stderror(ERR_SYSTEM55, tmp, strerror(errno(*__errno())));
827 (void) unlink(tmp); /* 0 0 inode! */
828 Dv[0] = term;
829 Dv[1] = NULL((void *)0);
830 gflag = 0;
831 trim(Dv);
832 rscan(Dv, Dtestq);
833 quoted = gflag;
834 ocnt = BUFSIZ1024;
835 obp = obuf;
836 for (;;) {
837 /*
838 * Read up a line
839 */
840 lbp = lbuf;
841 lcnt = BUFSIZ1024 - 4;
842 for (;;) {
843 c = readc(1); /* 1 -> Want EOF returns */
844 if (c < 0 || c == '\n')
845 break;
846 if ((c &= TRIM0077777) != '\0') {
847 *lbp++ = c;
848 if (--lcnt < 0) {
849 setname("<<")(bname = ("<<"));
850 stderror(ERR_NAME0x10000000 | ERR_OVERFLOW44);
851 }
852 }
853 }
854 *lbp = 0;
855
856 /*
857 * Check for EOF or compare to terminator -- before expansion
858 */
859 if (c < 0 || eq(lbuf, term)(Strcmp(lbuf, term) == 0)) {
860 (void) write(STDIN_FILENO0, short2str(obuf),
861 (size_t) (BUFSIZ1024 - ocnt));
862 (void) lseek(STDIN_FILENO0, (off_t) 0, SEEK_SET0);
863 return;
864 }
865
866 /*
867 * If term was quoted or -n just pass it on
868 */
869 if (quoted || noexec) {
870 *lbp++ = '\n';
871 *lbp = 0;
872 for (lbp = lbuf; (c = *lbp++) != '\0';) {
873 *obp++ = c;
874 if (--ocnt == 0) {
875 (void) write(STDIN_FILENO0, short2str(obuf), BUFSIZ1024);
876 obp = obuf;
877 ocnt = BUFSIZ1024;
878 }
879 }
880 continue;
881 }
882
883 /*
884 * Term wasn't quoted so variable and then command expand the input
885 * line
886 */
887 Dcp = lbuf;
888 Dvp = Dv + 1;
889 mbp = mbuf;
890 mcnt = BUFSIZ1024 - 4;
891 for (;;) {
892 c = DgetC(DODOL1);
893 if (c == DEOF-1)
894 break;
895 if ((c &= TRIM0077777) == 0)
896 continue;
897 /* \ quotes \ $ ` here */
898 if (c == '\\') {
899 c = DgetC(0);
900 if (!any("$\\`", c))
901 unDgetC(c | QUOTE)Dpeekc = c | 0100000U, c = '\\';
902 else
903 c |= QUOTE0100000U;
904 }
905 *mbp++ = c;
906 if (--mcnt == 0) {
907 setname("<<")(bname = ("<<"));
908 stderror(ERR_NAME0x10000000 | ERR_OVERFLOW44);
909 }
910 }
911 *mbp++ = 0;
912
913 /*
914 * If any ` in line do command substitution
915 */
916 mbp = mbuf;
917 if (any(short2str(mbp), '`')) {
918 /*
919 * 1 arg to dobackp causes substitution to be literal. Words are
920 * broken only at newlines so that all blanks and tabs are
921 * preserved. Blank lines (null words) are not discarded.
922 */
923 vp = dobackp(mbuf, 1);
924 }
925 else
926 /* Setup trivial vector similar to return of dobackp */
927 Dv[0] = mbp, Dv[1] = NULL((void *)0), vp = Dv;
928
929 /*
930 * Resurrect the words from the command substitution each separated by
931 * a newline. Note that the last newline of a command substitution
932 * will have been discarded, but we put a newline after the last word
933 * because this represents the newline after the last input line!
934 */
935 for (; *vp; vp++) {
936 for (mbp = *vp; *mbp; mbp++) {
937 *obp++ = *mbp & TRIM0077777;
938 if (--ocnt == 0) {
939 (void) write(STDIN_FILENO0, short2str(obuf), BUFSIZ1024);
940 obp = obuf;
941 ocnt = BUFSIZ1024;
942 }
943 }
944 *obp++ = '\n';
945 if (--ocnt == 0) {
946 (void) write(STDIN_FILENO0, short2str(obuf), BUFSIZ1024);
947 obp = obuf;
948 ocnt = BUFSIZ1024;
949 }
950 }
951 blkfree(pargv);
952 pargv = NULL((void *)0);
953 }
954}