2 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
7 /* All Rights Reserved */
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.
15 #pragma ident "%Z%%M% %I% %E% SMI"
18 #include "sh.tconst.h"
24 #define IGNORE 1 /* in ignore, it means to ignore value, just parse */
25 #define NOGLOB 2 /* in ignore, it means not to globone */
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
**);
55 * Determine if file given by name is accessible with permissions
58 * Borrowed from the Bourne sh, and modified a bit
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
66 chk_access(tchar
*path
, mode_t mode
)
72 unsigned char name
[MAXPATHLEN
*MB_LEN_MAX
]; /* General use buffer. */
74 /* convert tchar * to char * */
81 if (stat((char *)name
, &statb
) == 0) {
82 ftype
= statb
.st_mode
& S_IFMT
;
83 if (access((char *)name
, 010|(mode
>>6)) == 0) {
85 if (ftype
!= S_IFREG
|| mode
!= S_IEXEC
)
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)))
103 tprintf("TRACE- exp()\n");
106 return (exp0(vp
, 0));
110 exp0(tchar
***vp
, bool ignore
)
112 int p1
= exp1(vp
, ignore
);
114 tprintf("TRACE- exp0()\n");
118 etraci("exp0 p1", p1
, vp
);
120 if (**vp
&& eq(**vp
, S_BARBAR
/* "||" */)) {
124 p2
= exp0(vp
, (ignore
&IGNORE
) || p1
);
126 etraci("exp0 p2", p2
, vp
);
134 exp1(tchar
***vp
, bool ignore
)
136 int p1
= exp2(vp
, ignore
);
139 tprintf("TRACE- exp1()\n");
142 etraci("exp1 p1", p1
, vp
);
144 if (**vp
&& eq(**vp
, S_ANDAND
/* "&&" */)) {
148 p2
= exp1(vp
, (ignore
&IGNORE
) || !p1
);
150 etraci("exp1 p2", p2
, vp
);
158 exp2(tchar
***vp
, bool ignore
)
160 int p1
= exp2a(vp
, ignore
);
163 tprintf("TRACE- exp2()\n");
166 etraci("exp3 p1", p1
, vp
);
168 if (**vp
&& eq(**vp
, S_BAR
/* "|" */)) {
172 p2
= exp2(vp
, ignore
);
174 etraci("exp3 p2", p2
, vp
);
182 exp2a(tchar
***vp
, bool ignore
)
184 int p1
= exp2b(vp
, ignore
);
187 tprintf("TRACE- exp2a()\n");
190 etraci("exp2a p1", p1
, vp
);
192 if (**vp
&& eq(**vp
, S_HAT
/* "^" */)) {
196 p2
= exp2a(vp
, ignore
);
198 etraci("exp2a p2", p2
, vp
);
206 exp2b(tchar
***vp
, bool ignore
)
208 int p1
= exp2c(vp
, ignore
);
211 tprintf("TRACE- exp2b()\n");
214 etraci("exp2b p1", p1
, vp
);
216 if (**vp
&& eq(**vp
, S_AND
/* "&" */)) {
220 p2
= exp2b(vp
, ignore
);
222 etraci("exp2b p2", p2
, vp
);
230 exp2c(tchar
***vp
, bool ignore
)
232 tchar
*p1
= exp3(vp
, ignore
);
237 tprintf("TRACE- exp2c()\n");
240 etracc("exp2c p1", p1
, vp
);
242 if (i
= isa(**vp
, EQOP
)) {
244 if (i
== EQMATCH
|| i
== NOTEQMATCH
)
246 p2
= exp3(vp
, ignore
);
248 etracc("exp2c p2", p2
, vp
);
250 if (!(ignore
&IGNORE
)) switch (i
) {
268 xfree(p1
), xfree(p2
);
277 exp3(tchar
***vp
, bool ignore
)
283 tprintf("TRACE- exp3()\n");
285 p1
= exp3a(vp
, ignore
);
287 etracc("exp3 p1", p1
, vp
);
289 if (i
= isa(**vp
, RELOP
)) {
291 if (**vp
&& eq(**vp
, S_EQ
/* "=" */))
293 p2
= exp3(vp
, ignore
);
295 etracc("exp3 p2", p2
, vp
);
297 if (!(ignore
&IGNORE
)) switch (i
) {
300 i
= egetn(p1
) > egetn(p2
);
304 i
= egetn(p1
) >= egetn(p2
);
308 i
= egetn(p1
) < egetn(p2
);
312 i
= egetn(p1
) <= egetn(p2
);
315 xfree(p1
), xfree(p2
);
322 exp3a(tchar
***vp
, bool ignore
)
328 tprintf("TRACE- exp3a()\n");
330 p1
= exp4(vp
, ignore
);
332 etracc("exp3a p1", p1
, vp
);
335 /* if (op && any(op[0], "<>") && op[0] == op[1]) { */
336 if (op
&& (op
[0] == '<' || op
[0] == '>') && op
[0] == op
[1]) {
338 p2
= exp3a(vp
, ignore
);
340 etracc("exp3a p2", p2
, vp
);
343 i
= egetn(p1
) << egetn(p2
);
345 i
= egetn(p1
) >> egetn(p2
);
346 xfree(p1
), xfree(p2
);
353 exp4(tchar
***vp
, bool ignore
)
359 tprintf("TRACE- exp4()\n");
361 p1
= exp5(vp
, ignore
);
363 etracc("exp4 p1", p1
, vp
);
365 if (isa(**vp
, ADDOP
)) {
366 tchar
*op
= *(*vp
)++;
368 p2
= exp4(vp
, ignore
);
370 etracc("exp4 p2", p2
, vp
);
372 if (!(ignore
&IGNORE
)) switch (op
[0]) {
375 i
= egetn(p1
) + egetn(p2
);
379 i
= egetn(p1
) - egetn(p2
);
382 xfree(p1
), xfree(p2
);
389 exp5(tchar
***vp
, bool ignore
)
395 tprintf("TRACE- exp5()\n");
397 p1
= exp6(vp
, ignore
);
399 etracc("exp5 p1", p1
, vp
);
401 if (isa(**vp
, MULOP
)) {
402 tchar
*op
= *(*vp
)++;
404 p2
= exp5(vp
, ignore
);
406 etracc("exp5 p2", p2
, vp
);
408 if (!(ignore
&IGNORE
)) switch (op
[0]) {
411 i
= egetn(p1
) * egetn(p2
);
417 error("Divide by 0");
428 xfree(p1
), xfree(p2
);
435 exp6(tchar
***vp
, bool ignore
)
441 tprintf("TRACE- exp6()\n");
444 bferr("Expression syntax");
445 if (eq(**vp
, S_EXAS
/* "!" */)) {
447 cp
= exp6(vp
, ignore
);
449 etracc("exp6 ! cp", cp
, vp
);
455 if (eq(**vp
, S_TIL
/* "~" */)) {
457 cp
= exp6(vp
, ignore
);
459 etracc("exp6 ~ cp", cp
, vp
);
465 if (eq(**vp
, S_LPAR
/* "(" */)) {
467 ccode
= exp0(vp
, ignore
);
469 etraci("exp6 () ccode", ccode
, vp
);
471 if (*vp
== 0 || **vp
== 0 || ***vp
!= ')')
472 bferr("Expression syntax");
474 return (putn(ccode
));
476 if (eq(**vp
, S_LBRA
/* "{" */)) {
478 struct command faket
;
483 faket
.t_dcar
= faket
.t_dcdr
= faket
.t_dspr
= NULL
;
484 faket
.t_dcom
= fakecom
;
485 fakecom
[0] = S_BRAPPPBRA
/* "{ ... }" */;
492 if (eq(*(*vp
)++, S_RBRA
/* "}" */))
496 return (S_
/* "" */);
498 if (pfork(&faket
, -1) == 0) {
506 etraci("exp6 {} status", egetn(value("status")), vp
);
508 return (putn(egetn(value(S_status
/* "status" */)) == 0));
510 if (isa(**vp
, ANYOP
))
511 return (S_
/* "" */);
513 if (*cp
== '-' && any(cp
[1], S_erwxfdzo
/* "erwxfdzo" */)) {
517 bferr("Malformed file inquiry");
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.
527 if ((**vp
== NULL
) || isa(**vp
, ANYOP
) && stat_(**vp
, &stb
))
528 bferr("Missing file name");
532 return (S_
/* "" */);
537 i
= !chk_access(ep
, S_IREAD
);
541 i
= !chk_access(ep
, S_IWRITE
);
545 i
= !chk_access(ep
, S_IEXEC
);
549 if (stat_(ep
, &stb
)) {
551 return (S_0
/* "0" */);
556 i
= (stb
.st_mode
& S_IFMT
) == S_IFREG
;
560 i
= (stb
.st_mode
& S_IFMT
) == S_IFDIR
;
564 i
= stb
.st_size
== 0;
572 i
= stb
.st_uid
== uid
;
577 etraci("exp6 -? i", i
, vp
);
583 etracc("exp6 default", cp
, vp
);
585 return (ignore
&NOGLOB
? savestr(cp
) : globone(cp
));
591 struct wordent paraml
;
592 struct wordent
*hp
= ¶ml
;
594 struct wordent
*wdp
= hp
;
597 tprintf("TRACE- evalav()\n");
599 set(S_status
/* "status" */, S_0
/* "0" */);
600 hp
->prev
= hp
->next
= hp
;
601 hp
->word
= S_
/* "" */;
603 struct wordent
*new = (struct wordent
*)xcalloc(1, sizeof *wdp
);
609 wdp
->word
= savestr(*v
++);
613 t
= syntax(paraml
.next
, ¶ml
, 0);
615 error("%s", gettext(err
));
617 freelex(¶ml
), freesyn(t
);
621 isa(tchar
*cp
, int what
)
625 tprintf("TRACE- isa()\n");
628 return ((what
& RESTOP
) != 0);
630 if (what
& ADDOP
&& (*cp
== '+' || *cp
== '-'))
632 if (what
& MULOP
&& (*cp
== '*' || *cp
== '/' || *cp
== '%'))
634 if (what
& RESTOP
&& (*cp
== '(' || *cp
== ')' || *cp
== '!' ||
635 *cp
== '~' || *cp
== '^' || *cp
== '"'))
637 } else if (cp
[2] == 0) {
639 if (cp
[0] == '|' && cp
[1] == '&')
641 if (cp
[0] == '<' && cp
[1] == '<')
643 if (cp
[0] == '>' && cp
[1] == '>')
652 } else if (cp
[0] == '!') {
674 tprintf("TRACE- egetn()\n");
676 if (*cp
&& *cp
!= '-' && !digit(*cp
))
677 bferr("Expression syntax");
685 etraci(tchar
*str
, int i
, tchar
***vp
)
688 printf("%s=%d\t", str
, i
);
694 etracc(tchar
*str
, tchar
*cp
, tchar
***vp
)
697 printf("%s=%s\t", str
, cp
);