1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * UNIX shell 32 */ 33 34 #include "defs.h" 35 #include "sym.h" 36 37 static struct ionod * inout(); 38 static void chkword(void); 39 static void chksym(int); 40 static struct trenod * term(); 41 static struct trenod * makelist(); 42 static struct trenod * list(); 43 static struct regnod * syncase(); 44 static struct trenod * item(); 45 static int skipnl(); 46 static void prsym(int); 47 static void synbad(void); 48 49 50 /* ======== storage allocation for functions ======== */ 51 52 unsigned char * 53 getstor(asize) 54 int asize; 55 { 56 if (fndef) 57 return((unsigned char *)alloc(asize)); 58 else 59 return(getstak(asize)); 60 } 61 62 63 /* ======== command line decoding ========*/ 64 65 66 67 68 struct trenod * 69 makefork(flgs, i) 70 int flgs; 71 struct trenod *i; 72 { 73 struct forknod *t; 74 75 t = (struct forknod *)getstor(sizeof(struct forknod)); 76 t->forktyp = flgs|TFORK; 77 t->forktre = i; 78 t->forkio = 0; 79 return((struct trenod *)t); 80 } 81 82 static struct trenod * 83 makelist(type, i, r) 84 int type; 85 struct trenod *i, *r; 86 { 87 struct lstnod *t; 88 89 if (i == 0 || r == 0) 90 synbad(); 91 else 92 { 93 t = (struct lstnod *)getstor(sizeof(struct lstnod)); 94 t->lsttyp = type; 95 t->lstlef = i; 96 t->lstrit = r; 97 } 98 return((struct trenod *)t); 99 } 100 101 /* 102 * cmd 103 * empty 104 * list 105 * list & [ cmd ] 106 * list [ ; cmd ] 107 */ 108 struct trenod * 109 cmd(sym, flg) 110 int sym; 111 int flg; 112 { 113 struct trenod *i, *e; 114 i = list(flg); 115 if (wdval == NL) 116 { 117 if (flg & NLFLG) 118 { 119 wdval = ';'; 120 chkpr(); 121 } 122 } 123 else if (i == 0 && (flg & MTFLG) == 0) 124 synbad(); 125 126 switch (wdval) 127 { 128 case '&': 129 if (i) 130 i = makefork(FAMP, i); 131 else 132 synbad(); 133 134 case ';': 135 if (e = cmd(sym, flg | MTFLG)) 136 i = makelist(TLST, i, e); 137 else if (i == 0) 138 synbad(); 139 break; 140 141 case EOFSYM: 142 if (sym == NL) 143 break; 144 145 default: 146 if (sym) 147 chksym(sym); 148 } 149 return(i); 150 } 151 152 /* 153 * list 154 * term 155 * list && term 156 * list || term 157 */ 158 static struct trenod * 159 list(int flg) 160 { 161 struct trenod *r; 162 int b; 163 r = term(flg); 164 while (r && ((b = (wdval == ANDFSYM)) || wdval == ORFSYM)) 165 r = makelist((b ? TAND : TORF), r, term(NLFLG)); 166 return(r); 167 } 168 169 /* 170 * term 171 * item 172 * item |^ term 173 */ 174 static struct trenod * 175 term(int flg) 176 { 177 struct trenod *t; 178 179 reserv++; 180 if (flg & NLFLG) 181 skipnl(); 182 else 183 word(); 184 if ((t = item(TRUE)) && (wdval == '^' || wdval == '|')) 185 { 186 struct trenod *left; 187 struct trenod *right; 188 189 left = makefork(FPOU, t); 190 right = makefork(FPIN, term(NLFLG)); 191 return(makefork(0, makelist(TFIL, left, right))); 192 } 193 else 194 return(t); 195 } 196 197 198 static struct regnod * 199 syncase(esym) 200 int esym; 201 { 202 skipnl(); 203 if (wdval == esym) 204 return(0); 205 else 206 { 207 struct regnod *r = 208 (struct regnod *)getstor(sizeof (struct regnod)); 209 struct argnod *argp; 210 211 r->regptr = 0; 212 for (;;) 213 { 214 if (fndef) 215 { 216 argp= wdarg; 217 wdarg = (struct argnod *)alloc(length(argp->argval) + BYTESPERWORD); 218 movstr(argp->argval, wdarg->argval); 219 } 220 221 wdarg->argnxt = r->regptr; 222 r->regptr = wdarg; 223 224 /* 'in' is not a reserved word in this case */ 225 if (wdval == INSYM){ 226 wdval = 0; 227 } 228 if (wdval || (word() != ')' && wdval != '|')) 229 synbad(); 230 if (wdval == '|') 231 word(); 232 else 233 break; 234 } 235 r->regcom = cmd(0, NLFLG | MTFLG); 236 if (wdval == ECSYM) 237 r->regnxt = syncase(esym); 238 else 239 { 240 chksym(esym); 241 r->regnxt = 0; 242 } 243 return(r); 244 } 245 } 246 247 /* 248 * item 249 * 250 * ( cmd ) [ < in ] [ > out ] 251 * word word* [ < in ] [ > out ] 252 * if ... then ... else ... fi 253 * for ... while ... do ... done 254 * case ... in ... esac 255 * begin ... end 256 */ 257 static struct trenod * 258 item(flag) 259 BOOL flag; 260 { 261 struct trenod *r; 262 struct ionod *io; 263 264 if (flag) 265 io = inout((struct ionod *)0); 266 else 267 io = 0; 268 switch (wdval) 269 { 270 case CASYM: 271 { 272 struct swnod *t; 273 274 t = (struct swnod *)getstor(sizeof(struct swnod)); 275 r = (struct trenod *)t; 276 277 chkword(); 278 if (fndef) 279 t->swarg = make(wdarg->argval); 280 else 281 t->swarg = wdarg->argval; 282 skipnl(); 283 chksym(INSYM | BRSYM); 284 t->swlst = syncase(wdval == INSYM ? ESSYM : KTSYM); 285 t->swtyp = TSW; 286 break; 287 } 288 289 case IFSYM: 290 { 291 int w; 292 struct ifnod *t; 293 294 t = (struct ifnod *)getstor(sizeof(struct ifnod)); 295 r = (struct trenod *)t; 296 297 t->iftyp = TIF; 298 t->iftre = cmd(THSYM, NLFLG); 299 t->thtre = cmd(ELSYM | FISYM | EFSYM, NLFLG); 300 t->eltre = ((w = wdval) == ELSYM ? cmd(FISYM, NLFLG) : (w == EFSYM ? (wdval = IFSYM, item(0)) : 0)); 301 if (w == EFSYM) 302 return(r); 303 break; 304 } 305 306 case FORSYM: 307 { 308 struct fornod *t; 309 310 t = (struct fornod *)getstor(sizeof(struct fornod)); 311 r = (struct trenod *)t; 312 313 t->fortyp = TFOR; 314 t->forlst = 0; 315 chkword(); 316 if (fndef) 317 t->fornam = make(wdarg->argval); 318 else 319 t->fornam = wdarg->argval; 320 if (skipnl() == INSYM) 321 { 322 chkword(); 323 324 nohash++; 325 t->forlst = (struct comnod *)item(0); 326 nohash--; 327 328 if (wdval != NL && wdval != ';') 329 synbad(); 330 if (wdval == NL) 331 chkpr(); 332 skipnl(); 333 } 334 chksym(DOSYM | BRSYM); 335 t->fortre = cmd(wdval == DOSYM ? ODSYM : KTSYM, NLFLG); 336 break; 337 } 338 339 case WHSYM: 340 case UNSYM: 341 { 342 struct whnod *t; 343 344 t = (struct whnod *)getstor(sizeof(struct whnod)); 345 r = (struct trenod *)t; 346 347 t->whtyp = (wdval == WHSYM ? TWH : TUN); 348 t->whtre = cmd(DOSYM, NLFLG); 349 t->dotre = cmd(ODSYM, NLFLG); 350 break; 351 } 352 353 case BRSYM: 354 r = cmd(KTSYM, NLFLG); 355 break; 356 357 case '(': 358 { 359 struct parnod *p; 360 361 p = (struct parnod *)getstor(sizeof(struct parnod)); 362 p->partre = cmd(')', NLFLG); 363 p->partyp = TPAR; 364 r = makefork(0, p); 365 break; 366 } 367 368 default: 369 if (io == 0) 370 return(0); 371 372 case 0: 373 { 374 struct comnod *t; 375 struct argnod *argp; 376 struct argnod **argtail; 377 struct argnod **argset = 0; 378 int keywd = 1; 379 unsigned char *com; 380 381 if ((wdval != NL) && ((peekn = skipwc()) == '(')) 382 { 383 struct fndnod *f; 384 struct ionod *saveio; 385 386 saveio = iotemp; 387 peekn = 0; 388 if (skipwc() != ')') 389 synbad(); 390 391 /* 392 * We increase fndef before calling getstor(), 393 * so that getstor() uses malloc to allocate 394 * memory instead of stack. This is necessary 395 * since fndnod will be hung on np->namenv, 396 * which persists over command executions. 397 */ 398 fndef++; 399 f = (struct fndnod *)getstor(sizeof(struct fndnod)); 400 r = (struct trenod *)f; 401 402 f->fndtyp = TFND; 403 f->fndnam = make(wdarg->argval); 404 f->fndref = 0; 405 reserv++; 406 skipnl(); 407 f->fndval = (struct trenod *)item(0); 408 fndef--; 409 410 if (iotemp != saveio) 411 { 412 struct ionod *ioptr = iotemp; 413 414 while (ioptr->iolst != saveio) 415 ioptr = ioptr->iolst; 416 417 ioptr->iolst = fiotemp; 418 fiotemp = iotemp; 419 iotemp = saveio; 420 } 421 return(r); 422 } 423 else 424 { 425 t = (struct comnod *)getstor(sizeof(struct comnod)); 426 r = (struct trenod *)t; 427 428 t->comio = io; /*initial io chain*/ 429 argtail = &(t->comarg); 430 431 while (wdval == 0) 432 { 433 if (fndef) 434 { 435 argp = wdarg; 436 wdarg = (struct argnod *)alloc(length(argp->argval) + BYTESPERWORD); 437 movstr(argp->argval, wdarg->argval); 438 } 439 440 argp = wdarg; 441 if (wdset && keywd) 442 { 443 argp->argnxt = (struct argnod *)argset; 444 argset = (struct argnod **)argp; 445 } 446 else 447 { 448 *argtail = argp; 449 argtail = &(argp->argnxt); 450 keywd = flags & keyflg; 451 } 452 word(); 453 if (flag) 454 { 455 if (io) 456 { 457 while(io->ionxt) 458 io = io->ionxt; 459 io->ionxt = inout((struct ionod *)0); 460 } 461 else 462 t->comio = io = inout((struct ionod *)0); 463 } 464 } 465 466 t->comtyp = TCOM; 467 t->comset = (struct argnod *)argset; 468 *argtail = 0; 469 470 if (nohash == 0 && (fndef == 0 || (flags & hashflg))) 471 { 472 if (t->comarg) 473 { 474 com = t->comarg->argval; 475 if (*com && *com != DOLLAR) 476 pathlook(com, 0, t->comset); 477 } 478 } 479 480 return(r); 481 } 482 } 483 484 } 485 reserv++; 486 word(); 487 if (io = inout(io)) 488 { 489 r = makefork(0,r); 490 r->treio = io; 491 } 492 return(r); 493 } 494 495 496 static int 497 skipnl() 498 { 499 while ((reserv++, word() == NL)) 500 chkpr(); 501 return(wdval); 502 } 503 504 static struct ionod * 505 inout(lastio) 506 struct ionod *lastio; 507 { 508 int iof; 509 struct ionod *iop; 510 unsigned int c; 511 512 iof = wdnum; 513 switch (wdval) 514 { 515 case DOCSYM: /* << */ 516 iof |= IODOC|IODOC_SUBST; 517 break; 518 519 case APPSYM: /* >> */ 520 case '>': 521 if (wdnum == 0) 522 iof |= 1; 523 iof |= IOPUT; 524 if (wdval == APPSYM) 525 { 526 iof |= IOAPP; 527 break; 528 } 529 530 case '<': 531 if ((c = nextwc()) == '&') 532 iof |= IOMOV; 533 else if (c == '>') 534 iof |= IORDW; 535 else 536 peekn = c | MARK; 537 break; 538 539 default: 540 return(lastio); 541 } 542 543 chkword(); 544 iop = (struct ionod *)getstor(sizeof(struct ionod)); 545 546 if (fndef) 547 iop->ioname = (char *) make(wdarg->argval); 548 else 549 iop->ioname = (char *) (wdarg->argval); 550 551 iop->iolink = 0; 552 iop->iofile = iof; 553 if (iof & IODOC) 554 { 555 iop->iolst = iopend; 556 iopend = iop; 557 } 558 word(); 559 iop->ionxt = inout(lastio); 560 return(iop); 561 } 562 563 static void 564 chkword(void) 565 { 566 if (word()) 567 synbad(); 568 } 569 570 static void 571 chksym(int sym) 572 { 573 int x = sym & wdval; 574 575 if (((x & SYMFLG) ? x : sym) != wdval) 576 synbad(); 577 } 578 579 static void 580 prsym(int sym) 581 { 582 if (sym & SYMFLG) 583 { 584 const struct sysnod *sp = reserved; 585 586 while (sp->sysval && sp->sysval != sym) 587 sp++; 588 prs(sp->sysnam); 589 } 590 else if (sym == EOFSYM) 591 prs(_gettext(endoffile)); 592 else 593 { 594 if (sym & SYMREP) 595 prc(sym); 596 if (sym == NL) 597 prs(_gettext(nlorsemi)); 598 else 599 prc(sym); 600 } 601 } 602 603 static void 604 synbad(void) 605 { 606 prp(); 607 prs(_gettext(synmsg)); 608 if ((flags & ttyflg) == 0) 609 { 610 prs(_gettext(atline)); 611 prn(standin->flin); 612 } 613 prs(colon); 614 prc(LQ); 615 if (wdval) 616 prsym(wdval); 617 else 618 prs_cntl(wdarg->argval); 619 prc(RQ); 620 prs(_gettext(unexpected)); 621 newline(); 622 exitsh(SYNBAD); 623 } 624