1 /* 2 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 7 /* All Rights Reserved */ 8 9 /* 10 * Copyright (c) 1980 Regents of the University of California. 11 * All rights reserved. The Berkeley Software License Agreement 12 * specifies the terms and conditions for redistribution. 13 */ 14 15 #include "sh.h" 16 #include "sh.tconst.h" 17 18 /* 19 * C shell 20 */ 21 22 #define IGNORE 1 /* in ignore, it means to ignore value, just parse */ 23 #define NOGLOB 2 /* in ignore, it means not to globone */ 24 25 #define ADDOP 1 26 #define MULOP 2 27 #define EQOP 4 28 #define RELOP 8 29 #define RESTOP 16 30 #define ANYOP 31 31 32 #define EQEQ 1 33 #define GTR 2 34 #define LSS 4 35 #define NOTEQ 6 36 #define EQMATCH 7 37 #define NOTEQMATCH 8 38 39 int uid; 40 41 int exp0(tchar ***, bool); 42 int exp1(tchar ***, bool); 43 int exp2(tchar ***, bool); 44 int exp2a(tchar ***, bool); 45 int exp2b(tchar ***, bool); 46 int exp2c(tchar ***, bool); 47 tchar *exp3(tchar ***, bool); 48 tchar *exp3a(tchar ***, bool); 49 tchar *exp4(tchar ***, bool); 50 tchar *exp5(tchar ***, bool); 51 tchar *exp6(tchar ***, bool); 52 void evalav(tchar **); 53 54 /* 55 * Determine if file given by name is accessible with permissions 56 * given by mode. 57 * 58 * Borrowed from the Bourne sh, and modified a bit 59 * 60 * If the requested access is permitted, a value of 0 is 61 * returned. Otherwise, a value of -1 is returned and errno is 62 * set to indicate the error 63 */ 64 65 int 66 chk_access(tchar *path, mode_t mode) 67 { 68 static int flag; 69 static uid_t euid; 70 struct stat statb; 71 mode_t ftype; 72 unsigned char name[MAXPATHLEN*MB_LEN_MAX]; /* General use buffer. */ 73 74 /* convert tchar * to char * */ 75 tstostr((char *)name, path); 76 77 if (flag == 0) { 78 euid = geteuid(); 79 flag = 1; 80 } 81 if (stat((char *)name, &statb) == 0) { 82 ftype = statb.st_mode & S_IFMT; 83 if (access((char *)name, 010|(mode>>6)) == 0) { 84 if (euid == 0) { 85 if (ftype != S_IFREG || mode != S_IEXEC) 86 return (0); 87 /* root can execute file as long as it has execute 88 permission for someone */ 89 if (statb.st_mode & (S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6))) 90 return (0); 91 return (-1); 92 } 93 return (0); 94 } 95 } 96 return (-1); 97 } 98 99 int 100 exp(tchar ***vp) 101 { 102 #ifdef TRACE 103 tprintf("TRACE- exp()\n"); 104 #endif 105 106 return (exp0(vp, 0)); 107 } 108 109 int 110 exp0(tchar ***vp, bool ignore) 111 { 112 int p1 = exp1(vp, ignore); 113 #ifdef TRACE 114 tprintf("TRACE- exp0()\n"); 115 #endif 116 117 #ifdef EDEBUG 118 etraci("exp0 p1", p1, vp); 119 #endif 120 if (**vp && eq(**vp, S_BARBAR /* "||" */)) { 121 int p2; 122 123 (*vp)++; 124 p2 = exp0(vp, (ignore&IGNORE) || p1); 125 #ifdef EDEBUG 126 etraci("exp0 p2", p2, vp); 127 #endif 128 return (p1 || p2); 129 } 130 return (p1); 131 } 132 133 int 134 exp1(tchar ***vp, bool ignore) 135 { 136 int p1 = exp2(vp, ignore); 137 138 #ifdef TRACE 139 tprintf("TRACE- exp1()\n"); 140 #endif 141 #ifdef EDEBUG 142 etraci("exp1 p1", p1, vp); 143 #endif 144 if (**vp && eq(**vp, S_ANDAND /* "&&" */)) { 145 int p2; 146 147 (*vp)++; 148 p2 = exp1(vp, (ignore&IGNORE) || !p1); 149 #ifdef EDEBUG 150 etraci("exp1 p2", p2, vp); 151 #endif 152 return (p1 && p2); 153 } 154 return (p1); 155 } 156 157 int 158 exp2(tchar ***vp, bool ignore) 159 { 160 int p1 = exp2a(vp, ignore); 161 162 #ifdef TRACE 163 tprintf("TRACE- exp2()\n"); 164 #endif 165 #ifdef EDEBUG 166 etraci("exp3 p1", p1, vp); 167 #endif 168 if (**vp && eq(**vp, S_BAR /* "|" */)) { 169 int p2; 170 171 (*vp)++; 172 p2 = exp2(vp, ignore); 173 #ifdef EDEBUG 174 etraci("exp3 p2", p2, vp); 175 #endif 176 return (p1 | p2); 177 } 178 return (p1); 179 } 180 181 int 182 exp2a(tchar ***vp, bool ignore) 183 { 184 int p1 = exp2b(vp, ignore); 185 186 #ifdef TRACE 187 tprintf("TRACE- exp2a()\n"); 188 #endif 189 #ifdef EDEBUG 190 etraci("exp2a p1", p1, vp); 191 #endif 192 if (**vp && eq(**vp, S_HAT /* "^" */)) { 193 int p2; 194 195 (*vp)++; 196 p2 = exp2a(vp, ignore); 197 #ifdef EDEBUG 198 etraci("exp2a p2", p2, vp); 199 #endif 200 return (p1 ^ p2); 201 } 202 return (p1); 203 } 204 205 int 206 exp2b(tchar ***vp, bool ignore) 207 { 208 int p1 = exp2c(vp, ignore); 209 210 #ifdef TRACE 211 tprintf("TRACE- exp2b()\n"); 212 #endif 213 #ifdef EDEBUG 214 etraci("exp2b p1", p1, vp); 215 #endif 216 if (**vp && eq(**vp, S_AND /* "&" */)) { 217 int p2; 218 219 (*vp)++; 220 p2 = exp2b(vp, ignore); 221 #ifdef EDEBUG 222 etraci("exp2b p2", p2, vp); 223 #endif 224 return (p1 & p2); 225 } 226 return (p1); 227 } 228 229 int 230 exp2c(tchar ***vp, bool ignore) 231 { 232 tchar *p1 = exp3(vp, ignore); 233 tchar *p2; 234 int i; 235 236 #ifdef TRACE 237 tprintf("TRACE- exp2c()\n"); 238 #endif 239 #ifdef EDEBUG 240 etracc("exp2c p1", p1, vp); 241 #endif 242 if (i = isa(**vp, EQOP)) { 243 (*vp)++; 244 if (i == EQMATCH || i == NOTEQMATCH) 245 ignore |= NOGLOB; 246 p2 = exp3(vp, ignore); 247 #ifdef EDEBUG 248 etracc("exp2c p2", p2, vp); 249 #endif 250 if (!(ignore&IGNORE)) switch (i) { 251 252 case EQEQ: 253 i = eq(p1, p2); 254 break; 255 256 case NOTEQ: 257 i = !eq(p1, p2); 258 break; 259 260 case EQMATCH: 261 i = Gmatch(p1, p2); 262 break; 263 264 case NOTEQMATCH: 265 i = !Gmatch(p1, p2); 266 break; 267 } 268 xfree(p1), xfree(p2); 269 return (i); 270 } 271 i = egetn(p1); 272 xfree(p1); 273 return (i); 274 } 275 276 tchar * 277 exp3(tchar ***vp, bool ignore) 278 { 279 tchar *p1, *p2; 280 int i; 281 282 #ifdef TRACE 283 tprintf("TRACE- exp3()\n"); 284 #endif 285 p1 = exp3a(vp, ignore); 286 #ifdef EDEBUG 287 etracc("exp3 p1", p1, vp); 288 #endif 289 if (i = isa(**vp, RELOP)) { 290 (*vp)++; 291 if (**vp && eq(**vp, S_EQ /* "=" */)) 292 i |= 1, (*vp)++; 293 p2 = exp3(vp, ignore); 294 #ifdef EDEBUG 295 etracc("exp3 p2", p2, vp); 296 #endif 297 if (!(ignore&IGNORE)) switch (i) { 298 299 case GTR: 300 i = egetn(p1) > egetn(p2); 301 break; 302 303 case GTR|1: 304 i = egetn(p1) >= egetn(p2); 305 break; 306 307 case LSS: 308 i = egetn(p1) < egetn(p2); 309 break; 310 311 case LSS|1: 312 i = egetn(p1) <= egetn(p2); 313 break; 314 } 315 xfree(p1), xfree(p2); 316 return (putn(i)); 317 } 318 return (p1); 319 } 320 321 tchar * 322 exp3a(tchar ***vp, bool ignore) 323 { 324 tchar *p1, *p2, *op; 325 int i; 326 327 #ifdef TRACE 328 tprintf("TRACE- exp3a()\n"); 329 #endif 330 p1 = exp4(vp, ignore); 331 #ifdef EDEBUG 332 etracc("exp3a p1", p1, vp); 333 #endif 334 op = **vp; 335 /* if (op && any(op[0], "<>") && op[0] == op[1]) { */ 336 if (op && (op[0] == '<' || op[0] == '>') && op[0] == op[1]) { 337 (*vp)++; 338 p2 = exp3a(vp, ignore); 339 #ifdef EDEBUG 340 etracc("exp3a p2", p2, vp); 341 #endif 342 if (op[0] == '<') 343 i = egetn(p1) << egetn(p2); 344 else 345 i = egetn(p1) >> egetn(p2); 346 xfree(p1), xfree(p2); 347 return (putn(i)); 348 } 349 return (p1); 350 } 351 352 tchar * 353 exp4(tchar ***vp, bool ignore) 354 { 355 tchar *p1, *p2; 356 int i = 0; 357 358 #ifdef TRACE 359 tprintf("TRACE- exp4()\n"); 360 #endif 361 p1 = exp5(vp, ignore); 362 #ifdef EDEBUG 363 etracc("exp4 p1", p1, vp); 364 #endif 365 if (isa(**vp, ADDOP)) { 366 tchar *op = *(*vp)++; 367 368 p2 = exp4(vp, ignore); 369 #ifdef EDEBUG 370 etracc("exp4 p2", p2, vp); 371 #endif 372 if (!(ignore&IGNORE)) switch (op[0]) { 373 374 case '+': 375 i = egetn(p1) + egetn(p2); 376 break; 377 378 case '-': 379 i = egetn(p1) - egetn(p2); 380 break; 381 } 382 xfree(p1), xfree(p2); 383 return (putn(i)); 384 } 385 return (p1); 386 } 387 388 tchar * 389 exp5(tchar ***vp, bool ignore) 390 { 391 tchar *p1, *p2; 392 int i = 0; 393 394 #ifdef TRACE 395 tprintf("TRACE- exp5()\n"); 396 #endif 397 p1 = exp6(vp, ignore); 398 #ifdef EDEBUG 399 etracc("exp5 p1", p1, vp); 400 #endif 401 if (isa(**vp, MULOP)) { 402 tchar *op = *(*vp)++; 403 404 p2 = exp5(vp, ignore); 405 #ifdef EDEBUG 406 etracc("exp5 p2", p2, vp); 407 #endif 408 if (!(ignore&IGNORE)) switch (op[0]) { 409 410 case '*': 411 i = egetn(p1) * egetn(p2); 412 break; 413 414 case '/': 415 i = egetn(p2); 416 if (i == 0) 417 error("Divide by 0"); 418 i = egetn(p1) / i; 419 break; 420 421 case '%': 422 i = egetn(p2); 423 if (i == 0) 424 error("Mod by 0"); 425 i = egetn(p1) % i; 426 break; 427 } 428 xfree(p1), xfree(p2); 429 return (putn(i)); 430 } 431 return (p1); 432 } 433 434 tchar * 435 exp6(tchar ***vp, bool ignore) 436 { 437 int ccode, i; 438 tchar *cp, *dp, *ep; 439 440 #ifdef TRACE 441 tprintf("TRACE- exp6()\n"); 442 #endif 443 if (**vp == 0) 444 bferr("Expression syntax"); 445 if (eq(**vp, S_EXAS /* "!" */)) { 446 (*vp)++; 447 cp = exp6(vp, ignore); 448 #ifdef EDEBUG 449 etracc("exp6 ! cp", cp, vp); 450 #endif 451 i = egetn(cp); 452 xfree(cp); 453 return (putn(!i)); 454 } 455 if (eq(**vp, S_TIL /* "~" */)) { 456 (*vp)++; 457 cp = exp6(vp, ignore); 458 #ifdef EDEBUG 459 etracc("exp6 ~ cp", cp, vp); 460 #endif 461 i = egetn(cp); 462 xfree(cp); 463 return (putn(~i)); 464 } 465 if (eq(**vp, S_LPAR /* "(" */)) { 466 (*vp)++; 467 ccode = exp0(vp, ignore); 468 #ifdef EDEBUG 469 etraci("exp6 () ccode", ccode, vp); 470 #endif 471 if (*vp == 0 || **vp == 0 || ***vp != ')') 472 bferr("Expression syntax"); 473 (*vp)++; 474 return (putn(ccode)); 475 } 476 if (eq(**vp, S_LBRA /* "{" */)) { 477 tchar **v; 478 struct command faket; 479 tchar *fakecom[2]; 480 481 faket.t_dtyp = TCOM; 482 faket.t_dflg = 0; 483 faket.t_dcar = faket.t_dcdr = faket.t_dspr = (struct command *)0; 484 faket.t_dcom = fakecom; 485 fakecom[0] = S_BRAPPPBRA /* "{ ... }" */; 486 fakecom[1] = NOSTR; 487 (*vp)++; 488 v = *vp; 489 for (;;) { 490 if (!**vp) 491 bferr("Missing }"); 492 if (eq(*(*vp)++, S_RBRA /* "}" */)) 493 break; 494 } 495 if (ignore&IGNORE) 496 return (S_ /* "" */); 497 psavejob(); 498 if (pfork(&faket, -1) == 0) { 499 *--(*vp) = 0; 500 evalav(v); 501 exitstat(); 502 } 503 pwait(); 504 prestjob(); 505 #ifdef EDEBUG 506 etraci("exp6 {} status", egetn(value("status")), vp); 507 #endif 508 return (putn(egetn(value(S_status /* "status" */)) == 0)); 509 } 510 if (isa(**vp, ANYOP)) 511 return (S_ /* "" */); 512 cp = *(*vp)++; 513 if (*cp == '-' && any(cp[1], S_erwxfdzo /* "erwxfdzo" */)) { 514 struct stat stb; 515 516 if (cp[2] != '\0') 517 bferr("Malformed file inquiry"); 518 519 /* 520 * Detect missing file names by checking for operator 521 * in the file name position. However, if an operator 522 * name appears there, we must make sure that there's 523 * no file by that name (e.g., "/") before announcing 524 * an error. Even this check isn't quite right, since 525 * it doesn't take globbing into account. 526 */ 527 if ((**vp == NULL) || isa(**vp, ANYOP) && stat_(**vp, &stb)) 528 bferr("Missing file name"); 529 dp = *(*vp)++; 530 531 if (ignore&IGNORE) 532 return (S_ /* "" */); 533 ep = globone(dp); 534 switch (cp[1]) { 535 536 case 'r': 537 i = !chk_access(ep, S_IREAD); 538 break; 539 540 case 'w': 541 i = !chk_access(ep, S_IWRITE); 542 break; 543 544 case 'x': 545 i = !chk_access(ep, S_IEXEC); 546 break; 547 548 default: 549 if (stat_(ep, &stb)) { 550 xfree(ep); 551 return (S_0 /* "0" */); 552 } 553 switch (cp[1]) { 554 555 case 'f': 556 i = (stb.st_mode & S_IFMT) == S_IFREG; 557 break; 558 559 case 'd': 560 i = (stb.st_mode & S_IFMT) == S_IFDIR; 561 break; 562 563 case 'z': 564 i = stb.st_size == 0; 565 break; 566 567 case 'e': 568 i = 1; 569 break; 570 571 case 'o': 572 i = stb.st_uid == uid; 573 break; 574 } 575 } 576 #ifdef EDEBUG 577 etraci("exp6 -? i", i, vp); 578 #endif 579 xfree(ep); 580 return (putn(i)); 581 } 582 #ifdef EDEBUG 583 etracc("exp6 default", cp, vp); 584 #endif 585 return (ignore&NOGLOB ? savestr(cp) : globone(cp)); 586 } 587 588 void 589 evalav(tchar **v) 590 { 591 struct wordent paraml; 592 struct wordent *hp = ¶ml; 593 struct command *t; 594 struct wordent *wdp = hp; 595 596 #ifdef TRACE 597 tprintf("TRACE- evalav()\n"); 598 #endif 599 set(S_status /* "status" */, S_0 /* "0" */); 600 hp->prev = hp->next = hp; 601 hp->word = S_ /* "" */; 602 while (*v) { 603 struct wordent *new = (struct wordent *)xcalloc(1, sizeof *wdp); 604 605 new->prev = wdp; 606 new->next = hp; 607 wdp->next = new; 608 wdp = new; 609 wdp->word = savestr(*v++); 610 } 611 hp->prev = wdp; 612 alias(¶ml); 613 t = syntax(paraml.next, ¶ml, 0); 614 if (err_msg) 615 error("%s", gettext(err_msg)); 616 execute(t, -1); 617 freelex(¶ml), freesyn(t); 618 } 619 620 int 621 isa(tchar *cp, int what) 622 { 623 624 #ifdef TRACE 625 tprintf("TRACE- isa()\n"); 626 #endif 627 if (cp == 0) 628 return ((what & RESTOP) != 0); 629 if (cp[1] == 0) { 630 if (what & ADDOP && (*cp == '+' || *cp == '-')) 631 return (1); 632 if (what & MULOP && (*cp == '*' || *cp == '/' || *cp == '%')) 633 return (1); 634 if (what & RESTOP && (*cp == '(' || *cp == ')' || *cp == '!' || 635 *cp == '~' || *cp == '^' || *cp == '"')) 636 return (1); 637 } else if (cp[2] == 0) { 638 if (what & RESTOP) { 639 if (cp[0] == '|' && cp[1] == '&') 640 return (1); 641 if (cp[0] == '<' && cp[1] == '<') 642 return (1); 643 if (cp[0] == '>' && cp[1] == '>') 644 return (1); 645 } 646 if (what & EQOP) { 647 if (cp[0] == '=') { 648 if (cp[1] == '=') 649 return (EQEQ); 650 if (cp[1] == '~') 651 return (EQMATCH); 652 } else if (cp[0] == '!') { 653 if (cp[1] == '=') 654 return (NOTEQ); 655 if (cp[1] == '~') 656 return (NOTEQMATCH); 657 } 658 } 659 } 660 if (what & RELOP) { 661 if (*cp == '<') 662 return (LSS); 663 if (*cp == '>') 664 return (GTR); 665 } 666 return (0); 667 } 668 669 int 670 egetn(tchar *cp) 671 { 672 673 #ifdef TRACE 674 tprintf("TRACE- egetn()\n"); 675 #endif 676 if (*cp && *cp != '-' && !digit(*cp)) 677 bferr("Expression syntax"); 678 return (getn(cp)); 679 } 680 681 /* Phew! */ 682 683 #ifdef EDEBUG 684 void 685 etraci(tchar *str, int i, tchar ***vp) 686 { 687 688 printf("%s=%d\t", str, i); 689 blkpr(*vp); 690 printf("\n"); 691 } 692 693 void 694 etracc(tchar *str, tchar *cp, tchar ***vp) 695 { 696 697 printf("%s=%s\t", str, cp); 698 blkpr(*vp); 699 printf("\n"); 700 } 701 #endif 702