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