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