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