17d8fb588SMatthias Schmidt /*
27d8fb588SMatthias Schmidt * sh.exp.c: Expression evaluations
37d8fb588SMatthias Schmidt */
47d8fb588SMatthias Schmidt /*-
57d8fb588SMatthias Schmidt * Copyright (c) 1980, 1991 The Regents of the University of California.
67d8fb588SMatthias Schmidt * All rights reserved.
77d8fb588SMatthias Schmidt *
87d8fb588SMatthias Schmidt * Redistribution and use in source and binary forms, with or without
97d8fb588SMatthias Schmidt * modification, are permitted provided that the following conditions
107d8fb588SMatthias Schmidt * are met:
117d8fb588SMatthias Schmidt * 1. Redistributions of source code must retain the above copyright
127d8fb588SMatthias Schmidt * notice, this list of conditions and the following disclaimer.
137d8fb588SMatthias Schmidt * 2. Redistributions in binary form must reproduce the above copyright
147d8fb588SMatthias Schmidt * notice, this list of conditions and the following disclaimer in the
157d8fb588SMatthias Schmidt * documentation and/or other materials provided with the distribution.
167d8fb588SMatthias Schmidt * 3. Neither the name of the University nor the names of its contributors
177d8fb588SMatthias Schmidt * may be used to endorse or promote products derived from this software
187d8fb588SMatthias Schmidt * without specific prior written permission.
197d8fb588SMatthias Schmidt *
207d8fb588SMatthias Schmidt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
217d8fb588SMatthias Schmidt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
227d8fb588SMatthias Schmidt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
237d8fb588SMatthias Schmidt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
247d8fb588SMatthias Schmidt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
257d8fb588SMatthias Schmidt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
267d8fb588SMatthias Schmidt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
277d8fb588SMatthias Schmidt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
287d8fb588SMatthias Schmidt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
297d8fb588SMatthias Schmidt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
307d8fb588SMatthias Schmidt * SUCH DAMAGE.
317d8fb588SMatthias Schmidt */
327d8fb588SMatthias Schmidt #include "sh.h"
337d8fb588SMatthias Schmidt #include "tw.h"
347d8fb588SMatthias Schmidt
357d8fb588SMatthias Schmidt /*
367d8fb588SMatthias Schmidt * C shell
377d8fb588SMatthias Schmidt */
387d8fb588SMatthias Schmidt
397d8fb588SMatthias Schmidt #define ADDOP 1
407d8fb588SMatthias Schmidt #define MULOP 2
417d8fb588SMatthias Schmidt #define EQOP 4
427d8fb588SMatthias Schmidt #define RELOP 8
437d8fb588SMatthias Schmidt #define RESTOP 16
447d8fb588SMatthias Schmidt #define ANYOP 31
457d8fb588SMatthias Schmidt
467d8fb588SMatthias Schmidt #define EQEQ 1
477d8fb588SMatthias Schmidt #define GTR 2
487d8fb588SMatthias Schmidt #define LSS 4
497d8fb588SMatthias Schmidt #define NOTEQ 6
507d8fb588SMatthias Schmidt #define EQMATCH 7
517d8fb588SMatthias Schmidt #define NOTEQMATCH 8
527d8fb588SMatthias Schmidt
537d8fb588SMatthias Schmidt static int sh_access (const Char *, int);
5494afa86dSJohn Marino static tcsh_number_t exp1 (Char ***, int);
5594afa86dSJohn Marino static tcsh_number_t exp2x (Char ***, int);
5694afa86dSJohn Marino static tcsh_number_t exp2a (Char ***, int);
5794afa86dSJohn Marino static tcsh_number_t exp2b (Char ***, int);
5894afa86dSJohn Marino static tcsh_number_t exp2c (Char ***, int);
597d8fb588SMatthias Schmidt static Char *exp3 (Char ***, int);
607d8fb588SMatthias Schmidt static Char *exp3a (Char ***, int);
617d8fb588SMatthias Schmidt static Char *exp4 (Char ***, int);
627d8fb588SMatthias Schmidt static Char *exp5 (Char ***, int);
637d8fb588SMatthias Schmidt static Char *exp6 (Char ***, int);
647d8fb588SMatthias Schmidt static void evalav (Char **);
657d8fb588SMatthias Schmidt static int isa (Char *, int);
6694afa86dSJohn Marino static tcsh_number_t egetn (const Char *);
677d8fb588SMatthias Schmidt
687d8fb588SMatthias Schmidt #ifdef EDEBUG
6957e3f2b5SSimon 'corecode' Schubert static void etracc (const char *, const Char *, Char ***);
7094afa86dSJohn Marino static void etraci (const char *, tcsh_number_t, Char ***);
717d8fb588SMatthias Schmidt #else /* !EDEBUG */
727d8fb588SMatthias Schmidt #define etracc(A, B, C) ((void)0)
737d8fb588SMatthias Schmidt #define etraci(A, B, C) ((void)0)
747d8fb588SMatthias Schmidt #endif /* !EDEBUG */
757d8fb588SMatthias Schmidt
767d8fb588SMatthias Schmidt /*
777d8fb588SMatthias Schmidt * shell access function according to POSIX and non POSIX
787d8fb588SMatthias Schmidt * From Beto Appleton (beto@aixwiz.aix.ibm.com)
797d8fb588SMatthias Schmidt */
807d8fb588SMatthias Schmidt static int
sh_access(const Char * fname,int mode)817d8fb588SMatthias Schmidt sh_access(const Char *fname, int mode)
827d8fb588SMatthias Schmidt {
837d8fb588SMatthias Schmidt #if defined(POSIX) && !defined(USE_ACCESS)
847d8fb588SMatthias Schmidt struct stat statb;
857d8fb588SMatthias Schmidt #endif /* POSIX */
867d8fb588SMatthias Schmidt char *name = short2str(fname);
877d8fb588SMatthias Schmidt
887d8fb588SMatthias Schmidt if (*name == '\0')
897d8fb588SMatthias Schmidt return 1;
907d8fb588SMatthias Schmidt
917d8fb588SMatthias Schmidt #if !defined(POSIX) || defined(USE_ACCESS)
927d8fb588SMatthias Schmidt return access(name, mode);
937d8fb588SMatthias Schmidt #else /* POSIX */
947d8fb588SMatthias Schmidt
957d8fb588SMatthias Schmidt /*
967d8fb588SMatthias Schmidt * POSIX 1003.2-d11.2
977d8fb588SMatthias Schmidt * -r file True if file exists and is readable.
987d8fb588SMatthias Schmidt * -w file True if file exists and is writable.
997d8fb588SMatthias Schmidt * True shall indicate only that the write flag is on.
1007d8fb588SMatthias Schmidt * The file shall not be writable on a read-only file
1017d8fb588SMatthias Schmidt * system even if this test indicates true.
1027d8fb588SMatthias Schmidt * -x file True if file exists and is executable.
1037d8fb588SMatthias Schmidt * True shall indicate only that the execute flag is on.
1047d8fb588SMatthias Schmidt * If file is a directory, true indicates that the file
1057d8fb588SMatthias Schmidt * can be searched.
1067d8fb588SMatthias Schmidt */
1077d8fb588SMatthias Schmidt if (mode != W_OK && mode != X_OK)
1087d8fb588SMatthias Schmidt return access(name, mode);
1097d8fb588SMatthias Schmidt
1107d8fb588SMatthias Schmidt if (stat(name, &statb) == -1)
1117d8fb588SMatthias Schmidt return 1;
1127d8fb588SMatthias Schmidt
1137d8fb588SMatthias Schmidt if (access(name, mode) == 0) {
1147d8fb588SMatthias Schmidt #ifdef S_ISDIR
1157d8fb588SMatthias Schmidt if (S_ISDIR(statb.st_mode) && mode == X_OK)
1167d8fb588SMatthias Schmidt return 0;
1177d8fb588SMatthias Schmidt #endif /* S_ISDIR */
1187d8fb588SMatthias Schmidt
1197d8fb588SMatthias Schmidt /* root needs permission for someone */
1207d8fb588SMatthias Schmidt switch (mode) {
1217d8fb588SMatthias Schmidt case W_OK:
1227d8fb588SMatthias Schmidt mode = S_IWUSR | S_IWGRP | S_IWOTH;
1237d8fb588SMatthias Schmidt break;
1247d8fb588SMatthias Schmidt case X_OK:
1257d8fb588SMatthias Schmidt mode = S_IXUSR | S_IXGRP | S_IXOTH;
1267d8fb588SMatthias Schmidt break;
1277d8fb588SMatthias Schmidt default:
1287d8fb588SMatthias Schmidt abort();
1297d8fb588SMatthias Schmidt break;
1307d8fb588SMatthias Schmidt }
1317d8fb588SMatthias Schmidt
1327d8fb588SMatthias Schmidt }
1337d8fb588SMatthias Schmidt
1347d8fb588SMatthias Schmidt else if (euid == statb.st_uid)
1357d8fb588SMatthias Schmidt mode <<= 6;
1367d8fb588SMatthias Schmidt
1377d8fb588SMatthias Schmidt else if (egid == statb.st_gid)
1387d8fb588SMatthias Schmidt mode <<= 3;
1397d8fb588SMatthias Schmidt
1407d8fb588SMatthias Schmidt # ifdef NGROUPS_MAX
1417d8fb588SMatthias Schmidt else {
1427d8fb588SMatthias Schmidt /* you can be in several groups */
1437d8fb588SMatthias Schmidt long n;
1447d8fb588SMatthias Schmidt GETGROUPS_T *groups;
1457d8fb588SMatthias Schmidt
1467d8fb588SMatthias Schmidt /*
1477d8fb588SMatthias Schmidt * Try these things to find a positive maximum groups value:
1487d8fb588SMatthias Schmidt * 1) sysconf(_SC_NGROUPS_MAX)
1497d8fb588SMatthias Schmidt * 2) NGROUPS_MAX
1507d8fb588SMatthias Schmidt * 3) getgroups(0, unused)
1517d8fb588SMatthias Schmidt * Then allocate and scan the groups array if one of these worked.
1527d8fb588SMatthias Schmidt */
1537d8fb588SMatthias Schmidt # if defined (HAVE_SYSCONF) && defined (_SC_NGROUPS_MAX)
1547d8fb588SMatthias Schmidt if ((n = sysconf(_SC_NGROUPS_MAX)) == -1)
1557d8fb588SMatthias Schmidt # endif /* _SC_NGROUPS_MAX */
1567d8fb588SMatthias Schmidt n = NGROUPS_MAX;
1577d8fb588SMatthias Schmidt if (n <= 0)
1587d8fb588SMatthias Schmidt n = getgroups(0, (GETGROUPS_T *) NULL);
1597d8fb588SMatthias Schmidt
1607d8fb588SMatthias Schmidt if (n > 0) {
1617d8fb588SMatthias Schmidt groups = xmalloc(n * sizeof(*groups));
1627d8fb588SMatthias Schmidt n = getgroups((int) n, groups);
1637d8fb588SMatthias Schmidt while (--n >= 0)
1647d8fb588SMatthias Schmidt if (groups[n] == statb.st_gid) {
1657d8fb588SMatthias Schmidt mode <<= 3;
1667d8fb588SMatthias Schmidt break;
1677d8fb588SMatthias Schmidt }
16860962bbcSJohn Marino xfree(groups);
1697d8fb588SMatthias Schmidt }
1707d8fb588SMatthias Schmidt }
1717d8fb588SMatthias Schmidt # endif /* NGROUPS_MAX */
1727d8fb588SMatthias Schmidt
1737d8fb588SMatthias Schmidt if (statb.st_mode & mode)
1747d8fb588SMatthias Schmidt return 0;
1757d8fb588SMatthias Schmidt else
1767d8fb588SMatthias Schmidt return 1;
1777d8fb588SMatthias Schmidt #endif /* !POSIX */
1787d8fb588SMatthias Schmidt }
1797d8fb588SMatthias Schmidt
18094afa86dSJohn Marino tcsh_number_t
expr(Char *** vp)1817d8fb588SMatthias Schmidt expr(Char ***vp)
1827d8fb588SMatthias Schmidt {
1837d8fb588SMatthias Schmidt return (exp0(vp, 0));
1847d8fb588SMatthias Schmidt }
1857d8fb588SMatthias Schmidt
18694afa86dSJohn Marino tcsh_number_t
exp0(Char *** vp,int ignore)1877d8fb588SMatthias Schmidt exp0(Char ***vp, int ignore)
1887d8fb588SMatthias Schmidt {
18994afa86dSJohn Marino tcsh_number_t p1 = exp1(vp, ignore);
1907d8fb588SMatthias Schmidt
1917d8fb588SMatthias Schmidt etraci("exp0 p1", p1, vp);
19257e3f2b5SSimon 'corecode' Schubert while (**vp && eq(**vp, STRor2)) {
1937d8fb588SMatthias Schmidt int p2;
1947d8fb588SMatthias Schmidt
1957d8fb588SMatthias Schmidt (*vp)++;
19657e3f2b5SSimon 'corecode' Schubert
19757e3f2b5SSimon 'corecode' Schubert p2 = compat_expr ?
19857e3f2b5SSimon 'corecode' Schubert exp0(vp, (ignore & TEXP_IGNORE) || p1) :
19957e3f2b5SSimon 'corecode' Schubert exp1(vp, (ignore & TEXP_IGNORE) || p1);
20057e3f2b5SSimon 'corecode' Schubert if (compat_expr || !(ignore & TEXP_IGNORE))
20157e3f2b5SSimon 'corecode' Schubert p1 = (p1 || p2);
20257e3f2b5SSimon 'corecode' Schubert etraci("exp0 p1", p1, vp);
20357e3f2b5SSimon 'corecode' Schubert if (compat_expr)
20457e3f2b5SSimon 'corecode' Schubert break;
2057d8fb588SMatthias Schmidt }
2067d8fb588SMatthias Schmidt return (p1);
2077d8fb588SMatthias Schmidt }
2087d8fb588SMatthias Schmidt
20994afa86dSJohn Marino static tcsh_number_t
exp1(Char *** vp,int ignore)2107d8fb588SMatthias Schmidt exp1(Char ***vp, int ignore)
2117d8fb588SMatthias Schmidt {
21294afa86dSJohn Marino tcsh_number_t p1 = exp2x(vp, ignore);
2137d8fb588SMatthias Schmidt
2147d8fb588SMatthias Schmidt etraci("exp1 p1", p1, vp);
21557e3f2b5SSimon 'corecode' Schubert while (**vp && eq(**vp, STRand2)) {
21694afa86dSJohn Marino tcsh_number_t p2;
2177d8fb588SMatthias Schmidt
2187d8fb588SMatthias Schmidt (*vp)++;
21957e3f2b5SSimon 'corecode' Schubert p2 = compat_expr ?
22057e3f2b5SSimon 'corecode' Schubert exp1(vp, (ignore & TEXP_IGNORE) || !p1) :
22157e3f2b5SSimon 'corecode' Schubert exp2x(vp, (ignore & TEXP_IGNORE) || !p1);
22257e3f2b5SSimon 'corecode' Schubert
2237d8fb588SMatthias Schmidt etraci("exp1 p2", p2, vp);
22457e3f2b5SSimon 'corecode' Schubert if (compat_expr || !(ignore & TEXP_IGNORE))
22557e3f2b5SSimon 'corecode' Schubert p1 = (p1 && p2);
22657e3f2b5SSimon 'corecode' Schubert etraci("exp1 p1", p1, vp);
22757e3f2b5SSimon 'corecode' Schubert if (compat_expr)
22857e3f2b5SSimon 'corecode' Schubert break;
2297d8fb588SMatthias Schmidt }
2307d8fb588SMatthias Schmidt return (p1);
2317d8fb588SMatthias Schmidt }
2327d8fb588SMatthias Schmidt
23394afa86dSJohn Marino static tcsh_number_t
exp2x(Char *** vp,int ignore)2347d8fb588SMatthias Schmidt exp2x(Char ***vp, int ignore)
2357d8fb588SMatthias Schmidt {
23694afa86dSJohn Marino tcsh_number_t p1 = exp2a(vp, ignore);
2377d8fb588SMatthias Schmidt
23857e3f2b5SSimon 'corecode' Schubert etraci("exp2x p1", p1, vp);
23957e3f2b5SSimon 'corecode' Schubert while (**vp && eq(**vp, STRor)) {
24094afa86dSJohn Marino tcsh_number_t p2;
2417d8fb588SMatthias Schmidt
2427d8fb588SMatthias Schmidt (*vp)++;
24357e3f2b5SSimon 'corecode' Schubert p2 = compat_expr ?
24457e3f2b5SSimon 'corecode' Schubert exp2x(vp, ignore) :
24557e3f2b5SSimon 'corecode' Schubert exp2a(vp, ignore);
24657e3f2b5SSimon 'corecode' Schubert etraci("exp2x p2", p2, vp);
24757e3f2b5SSimon 'corecode' Schubert if (compat_expr || !(ignore & TEXP_IGNORE))
24857e3f2b5SSimon 'corecode' Schubert p1 = (p1 | p2);
24957e3f2b5SSimon 'corecode' Schubert etraci("exp2x p1", p1, vp);
25057e3f2b5SSimon 'corecode' Schubert if (compat_expr)
25157e3f2b5SSimon 'corecode' Schubert break;
2527d8fb588SMatthias Schmidt }
2537d8fb588SMatthias Schmidt return (p1);
2547d8fb588SMatthias Schmidt }
2557d8fb588SMatthias Schmidt
25694afa86dSJohn Marino static tcsh_number_t
exp2a(Char *** vp,int ignore)2577d8fb588SMatthias Schmidt exp2a(Char ***vp, int ignore)
2587d8fb588SMatthias Schmidt {
25994afa86dSJohn Marino tcsh_number_t p1 = exp2b(vp, ignore);
2607d8fb588SMatthias Schmidt
2617d8fb588SMatthias Schmidt etraci("exp2a p1", p1, vp);
26257e3f2b5SSimon 'corecode' Schubert while (**vp && eq(**vp, STRcaret)) {
26394afa86dSJohn Marino tcsh_number_t p2;
2647d8fb588SMatthias Schmidt
2657d8fb588SMatthias Schmidt (*vp)++;
26657e3f2b5SSimon 'corecode' Schubert p2 = compat_expr ?
26757e3f2b5SSimon 'corecode' Schubert exp2a(vp, ignore) :
26857e3f2b5SSimon 'corecode' Schubert exp2b(vp, ignore);
2697d8fb588SMatthias Schmidt etraci("exp2a p2", p2, vp);
27057e3f2b5SSimon 'corecode' Schubert if (compat_expr || !(ignore & TEXP_IGNORE))
27157e3f2b5SSimon 'corecode' Schubert p1 = (p1 ^ p2);
27257e3f2b5SSimon 'corecode' Schubert etraci("exp2a p1", p1, vp);
27357e3f2b5SSimon 'corecode' Schubert if (compat_expr)
27457e3f2b5SSimon 'corecode' Schubert break;
2757d8fb588SMatthias Schmidt }
2767d8fb588SMatthias Schmidt return (p1);
2777d8fb588SMatthias Schmidt }
2787d8fb588SMatthias Schmidt
27994afa86dSJohn Marino static tcsh_number_t
exp2b(Char *** vp,int ignore)2807d8fb588SMatthias Schmidt exp2b(Char ***vp, int ignore)
2817d8fb588SMatthias Schmidt {
28294afa86dSJohn Marino tcsh_number_t p1 = exp2c(vp, ignore);
2837d8fb588SMatthias Schmidt
2847d8fb588SMatthias Schmidt etraci("exp2b p1", p1, vp);
28557e3f2b5SSimon 'corecode' Schubert while (**vp && eq(**vp, STRand)) {
28694afa86dSJohn Marino tcsh_number_t p2;
2877d8fb588SMatthias Schmidt
2887d8fb588SMatthias Schmidt (*vp)++;
28957e3f2b5SSimon 'corecode' Schubert p2 = compat_expr ?
29057e3f2b5SSimon 'corecode' Schubert exp2b(vp, ignore) :
29157e3f2b5SSimon 'corecode' Schubert exp2c(vp, ignore);
2927d8fb588SMatthias Schmidt etraci("exp2b p2", p2, vp);
29357e3f2b5SSimon 'corecode' Schubert if (compat_expr || !(ignore & TEXP_IGNORE))
29457e3f2b5SSimon 'corecode' Schubert p1 = (p1 & p2);
29557e3f2b5SSimon 'corecode' Schubert etraci("exp2b p1", p1, vp);
29657e3f2b5SSimon 'corecode' Schubert if (compat_expr)
29757e3f2b5SSimon 'corecode' Schubert break;
2987d8fb588SMatthias Schmidt }
2997d8fb588SMatthias Schmidt return (p1);
3007d8fb588SMatthias Schmidt }
3017d8fb588SMatthias Schmidt
30294afa86dSJohn Marino static tcsh_number_t
exp2c(Char *** vp,int ignore)3037d8fb588SMatthias Schmidt exp2c(Char ***vp, int ignore)
3047d8fb588SMatthias Schmidt {
3057d8fb588SMatthias Schmidt Char *p1 = exp3(vp, ignore);
3067d8fb588SMatthias Schmidt Char *p2;
30794afa86dSJohn Marino tcsh_number_t i;
3087d8fb588SMatthias Schmidt
3097d8fb588SMatthias Schmidt cleanup_push(p1, xfree);
3107d8fb588SMatthias Schmidt etracc("exp2c p1", p1, vp);
3117d8fb588SMatthias Schmidt if ((i = isa(**vp, EQOP)) != 0) {
3127d8fb588SMatthias Schmidt (*vp)++;
3137d8fb588SMatthias Schmidt if (i == EQMATCH || i == NOTEQMATCH)
3147d8fb588SMatthias Schmidt ignore |= TEXP_NOGLOB;
3157d8fb588SMatthias Schmidt p2 = exp3(vp, ignore);
3167d8fb588SMatthias Schmidt cleanup_push(p2, xfree);
3177d8fb588SMatthias Schmidt etracc("exp2c p2", p2, vp);
3187d8fb588SMatthias Schmidt if (!(ignore & TEXP_IGNORE))
31960962bbcSJohn Marino switch ((int)i) {
3207d8fb588SMatthias Schmidt
3217d8fb588SMatthias Schmidt case EQEQ:
3227d8fb588SMatthias Schmidt i = eq(p1, p2);
3237d8fb588SMatthias Schmidt break;
3247d8fb588SMatthias Schmidt
3257d8fb588SMatthias Schmidt case NOTEQ:
3267d8fb588SMatthias Schmidt i = !eq(p1, p2);
3277d8fb588SMatthias Schmidt break;
3287d8fb588SMatthias Schmidt
3297d8fb588SMatthias Schmidt case EQMATCH:
3307d8fb588SMatthias Schmidt i = Gmatch(p1, p2);
3317d8fb588SMatthias Schmidt break;
3327d8fb588SMatthias Schmidt
3337d8fb588SMatthias Schmidt case NOTEQMATCH:
3347d8fb588SMatthias Schmidt i = !Gmatch(p1, p2);
3357d8fb588SMatthias Schmidt break;
3367d8fb588SMatthias Schmidt }
3377d8fb588SMatthias Schmidt cleanup_until(p1);
3387d8fb588SMatthias Schmidt return (i);
3397d8fb588SMatthias Schmidt }
3407d8fb588SMatthias Schmidt i = egetn(p1);
3417d8fb588SMatthias Schmidt cleanup_until(p1);
3427d8fb588SMatthias Schmidt return (i);
3437d8fb588SMatthias Schmidt }
3447d8fb588SMatthias Schmidt
3457d8fb588SMatthias Schmidt static Char *
exp3(Char *** vp,int ignore)3467d8fb588SMatthias Schmidt exp3(Char ***vp, int ignore)
3477d8fb588SMatthias Schmidt {
3487d8fb588SMatthias Schmidt Char *p1, *p2;
34994afa86dSJohn Marino tcsh_number_t i;
3507d8fb588SMatthias Schmidt
3517d8fb588SMatthias Schmidt p1 = exp3a(vp, ignore);
3527d8fb588SMatthias Schmidt etracc("exp3 p1", p1, vp);
35357e3f2b5SSimon 'corecode' Schubert while ((i = isa(**vp, RELOP)) != 0) {
3547d8fb588SMatthias Schmidt (*vp)++;
3557d8fb588SMatthias Schmidt if (**vp && eq(**vp, STRequal))
3567d8fb588SMatthias Schmidt i |= 1, (*vp)++;
3577d8fb588SMatthias Schmidt cleanup_push(p1, xfree);
35857e3f2b5SSimon 'corecode' Schubert p2 = compat_expr ?
35957e3f2b5SSimon 'corecode' Schubert exp3(vp, ignore) :
36057e3f2b5SSimon 'corecode' Schubert exp3a(vp, ignore);
3617d8fb588SMatthias Schmidt cleanup_push(p2, xfree);
3627d8fb588SMatthias Schmidt etracc("exp3 p2", p2, vp);
3637d8fb588SMatthias Schmidt if (!(ignore & TEXP_IGNORE))
36460962bbcSJohn Marino switch ((int)i) {
3657d8fb588SMatthias Schmidt
3667d8fb588SMatthias Schmidt case GTR:
3677d8fb588SMatthias Schmidt i = egetn(p1) > egetn(p2);
3687d8fb588SMatthias Schmidt break;
3697d8fb588SMatthias Schmidt
3707d8fb588SMatthias Schmidt case GTR | 1:
3717d8fb588SMatthias Schmidt i = egetn(p1) >= egetn(p2);
3727d8fb588SMatthias Schmidt break;
3737d8fb588SMatthias Schmidt
3747d8fb588SMatthias Schmidt case LSS:
3757d8fb588SMatthias Schmidt i = egetn(p1) < egetn(p2);
3767d8fb588SMatthias Schmidt break;
3777d8fb588SMatthias Schmidt
3787d8fb588SMatthias Schmidt case LSS | 1:
3797d8fb588SMatthias Schmidt i = egetn(p1) <= egetn(p2);
3807d8fb588SMatthias Schmidt break;
3817d8fb588SMatthias Schmidt }
3827d8fb588SMatthias Schmidt cleanup_until(p1);
38357e3f2b5SSimon 'corecode' Schubert p1 = putn(i);
38457e3f2b5SSimon 'corecode' Schubert etracc("exp3 p1", p1, vp);
38557e3f2b5SSimon 'corecode' Schubert if (compat_expr)
38657e3f2b5SSimon 'corecode' Schubert break;
3877d8fb588SMatthias Schmidt }
3887d8fb588SMatthias Schmidt return (p1);
3897d8fb588SMatthias Schmidt }
3907d8fb588SMatthias Schmidt
3917d8fb588SMatthias Schmidt static Char *
exp3a(Char *** vp,int ignore)3927d8fb588SMatthias Schmidt exp3a(Char ***vp, int ignore)
3937d8fb588SMatthias Schmidt {
3947d8fb588SMatthias Schmidt Char *p1, *p2;
3957d8fb588SMatthias Schmidt const Char *op;
39694afa86dSJohn Marino tcsh_number_t i;
3977d8fb588SMatthias Schmidt
3987d8fb588SMatthias Schmidt p1 = exp4(vp, ignore);
3997d8fb588SMatthias Schmidt etracc("exp3a p1", p1, vp);
4007d8fb588SMatthias Schmidt op = **vp;
4017d8fb588SMatthias Schmidt if (op && any("<>", op[0]) && op[0] == op[1]) {
4027d8fb588SMatthias Schmidt (*vp)++;
4037d8fb588SMatthias Schmidt cleanup_push(p1, xfree);
40457e3f2b5SSimon 'corecode' Schubert p2 = compat_expr ?
40557e3f2b5SSimon 'corecode' Schubert exp3a(vp, ignore) :
40657e3f2b5SSimon 'corecode' Schubert exp4(vp, ignore);
4077d8fb588SMatthias Schmidt cleanup_push(p2, xfree);
4087d8fb588SMatthias Schmidt etracc("exp3a p2", p2, vp);
4097d8fb588SMatthias Schmidt if (op[0] == '<')
4107d8fb588SMatthias Schmidt i = egetn(p1) << egetn(p2);
4117d8fb588SMatthias Schmidt else
4127d8fb588SMatthias Schmidt i = egetn(p1) >> egetn(p2);
4137d8fb588SMatthias Schmidt cleanup_until(p1);
41457e3f2b5SSimon 'corecode' Schubert p1 = putn(i);
41557e3f2b5SSimon 'corecode' Schubert etracc("exp3a p1", p1, vp);
4167d8fb588SMatthias Schmidt }
4177d8fb588SMatthias Schmidt return (p1);
4187d8fb588SMatthias Schmidt }
4197d8fb588SMatthias Schmidt
4207d8fb588SMatthias Schmidt static Char *
exp4(Char *** vp,int ignore)4217d8fb588SMatthias Schmidt exp4(Char ***vp, int ignore)
4227d8fb588SMatthias Schmidt {
4237d8fb588SMatthias Schmidt Char *p1, *p2;
42494afa86dSJohn Marino tcsh_number_t i = 0;
4257d8fb588SMatthias Schmidt
4267d8fb588SMatthias Schmidt p1 = exp5(vp, ignore);
4277d8fb588SMatthias Schmidt etracc("exp4 p1", p1, vp);
42857e3f2b5SSimon 'corecode' Schubert while (isa(**vp, ADDOP)) {
4297d8fb588SMatthias Schmidt const Char *op = *(*vp)++;
4307d8fb588SMatthias Schmidt
4317d8fb588SMatthias Schmidt cleanup_push(p1, xfree);
43257e3f2b5SSimon 'corecode' Schubert p2 = compat_expr ?
43357e3f2b5SSimon 'corecode' Schubert exp4(vp, ignore) :
43457e3f2b5SSimon 'corecode' Schubert exp5(vp, ignore);
4357d8fb588SMatthias Schmidt cleanup_push(p2, xfree);
4367d8fb588SMatthias Schmidt etracc("exp4 p2", p2, vp);
4377d8fb588SMatthias Schmidt if (!(ignore & TEXP_IGNORE))
4387d8fb588SMatthias Schmidt switch (op[0]) {
4397d8fb588SMatthias Schmidt
4407d8fb588SMatthias Schmidt case '+':
4417d8fb588SMatthias Schmidt i = egetn(p1) + egetn(p2);
4427d8fb588SMatthias Schmidt break;
4437d8fb588SMatthias Schmidt
4447d8fb588SMatthias Schmidt case '-':
4457d8fb588SMatthias Schmidt i = egetn(p1) - egetn(p2);
4467d8fb588SMatthias Schmidt break;
4477d8fb588SMatthias Schmidt }
4487d8fb588SMatthias Schmidt cleanup_until(p1);
44957e3f2b5SSimon 'corecode' Schubert p1 = putn(i);
45057e3f2b5SSimon 'corecode' Schubert etracc("exp4 p1", p1, vp);
45157e3f2b5SSimon 'corecode' Schubert if (compat_expr)
45257e3f2b5SSimon 'corecode' Schubert break;
4537d8fb588SMatthias Schmidt }
4547d8fb588SMatthias Schmidt return (p1);
4557d8fb588SMatthias Schmidt }
4567d8fb588SMatthias Schmidt
4577d8fb588SMatthias Schmidt static Char *
exp5(Char *** vp,int ignore)4587d8fb588SMatthias Schmidt exp5(Char ***vp, int ignore)
4597d8fb588SMatthias Schmidt {
4607d8fb588SMatthias Schmidt Char *p1, *p2;
46194afa86dSJohn Marino tcsh_number_t i = 0;
4627d8fb588SMatthias Schmidt
4637d8fb588SMatthias Schmidt p1 = exp6(vp, ignore);
4647d8fb588SMatthias Schmidt etracc("exp5 p1", p1, vp);
4657d8fb588SMatthias Schmidt
46657e3f2b5SSimon 'corecode' Schubert while (isa(**vp, MULOP)) {
4677d8fb588SMatthias Schmidt const Char *op = *(*vp)++;
4687d8fb588SMatthias Schmidt if ((ignore & TEXP_NOGLOB) != 0) {
4697d8fb588SMatthias Schmidt /*
4707d8fb588SMatthias Schmidt * We are just trying to get the right side of
4717d8fb588SMatthias Schmidt * a =~ or !~ operator
4727d8fb588SMatthias Schmidt */
4737d8fb588SMatthias Schmidt xfree(p1);
4747d8fb588SMatthias Schmidt return Strsave(op);
4757d8fb588SMatthias Schmidt }
4767d8fb588SMatthias Schmidt
4777d8fb588SMatthias Schmidt cleanup_push(p1, xfree);
47857e3f2b5SSimon 'corecode' Schubert p2 = compat_expr ?
47957e3f2b5SSimon 'corecode' Schubert exp5(vp, ignore) :
48057e3f2b5SSimon 'corecode' Schubert exp6(vp, ignore);
4817d8fb588SMatthias Schmidt cleanup_push(p2, xfree);
4827d8fb588SMatthias Schmidt etracc("exp5 p2", p2, vp);
4837d8fb588SMatthias Schmidt if (!(ignore & TEXP_IGNORE))
4847d8fb588SMatthias Schmidt switch (op[0]) {
4857d8fb588SMatthias Schmidt
4867d8fb588SMatthias Schmidt case '*':
4877d8fb588SMatthias Schmidt i = egetn(p1) * egetn(p2);
4887d8fb588SMatthias Schmidt break;
4897d8fb588SMatthias Schmidt
4907d8fb588SMatthias Schmidt case '/':
4917d8fb588SMatthias Schmidt i = egetn(p2);
4927d8fb588SMatthias Schmidt if (i == 0)
4937d8fb588SMatthias Schmidt stderror(ERR_DIV0);
4947d8fb588SMatthias Schmidt i = egetn(p1) / i;
4957d8fb588SMatthias Schmidt break;
4967d8fb588SMatthias Schmidt
4977d8fb588SMatthias Schmidt case '%':
4987d8fb588SMatthias Schmidt i = egetn(p2);
4997d8fb588SMatthias Schmidt if (i == 0)
5007d8fb588SMatthias Schmidt stderror(ERR_MOD0);
5017d8fb588SMatthias Schmidt i = egetn(p1) % i;
5027d8fb588SMatthias Schmidt break;
5037d8fb588SMatthias Schmidt }
5047d8fb588SMatthias Schmidt cleanup_until(p1);
50557e3f2b5SSimon 'corecode' Schubert p1 = putn(i);
50657e3f2b5SSimon 'corecode' Schubert etracc("exp5 p1", p1, vp);
50757e3f2b5SSimon 'corecode' Schubert if (compat_expr)
50857e3f2b5SSimon 'corecode' Schubert break;
5097d8fb588SMatthias Schmidt }
5107d8fb588SMatthias Schmidt return (p1);
5117d8fb588SMatthias Schmidt }
5127d8fb588SMatthias Schmidt
5137d8fb588SMatthias Schmidt static Char *
exp6(Char *** vp,int ignore)5147d8fb588SMatthias Schmidt exp6(Char ***vp, int ignore)
5157d8fb588SMatthias Schmidt {
51694afa86dSJohn Marino tcsh_number_t ccode;
51794afa86dSJohn Marino tcsh_number_t i = 0;
5187d8fb588SMatthias Schmidt Char *cp;
5197d8fb588SMatthias Schmidt
5207d8fb588SMatthias Schmidt if (**vp == 0)
5217d8fb588SMatthias Schmidt stderror(ERR_NAME | ERR_EXPRESSION);
5227d8fb588SMatthias Schmidt if (eq(**vp, STRbang)) {
5237d8fb588SMatthias Schmidt (*vp)++;
5247d8fb588SMatthias Schmidt cp = exp6(vp, ignore);
5257d8fb588SMatthias Schmidt cleanup_push(cp, xfree);
5267d8fb588SMatthias Schmidt etracc("exp6 ! cp", cp, vp);
5277d8fb588SMatthias Schmidt i = egetn(cp);
5287d8fb588SMatthias Schmidt cleanup_until(cp);
5297d8fb588SMatthias Schmidt return (putn(!i));
5307d8fb588SMatthias Schmidt }
5317d8fb588SMatthias Schmidt if (eq(**vp, STRtilde)) {
5327d8fb588SMatthias Schmidt (*vp)++;
5337d8fb588SMatthias Schmidt cp = exp6(vp, ignore);
5347d8fb588SMatthias Schmidt cleanup_push(cp, xfree);
5357d8fb588SMatthias Schmidt etracc("exp6 ~ cp", cp, vp);
5367d8fb588SMatthias Schmidt i = egetn(cp);
5377d8fb588SMatthias Schmidt cleanup_until(cp);
5387d8fb588SMatthias Schmidt return (putn(~i));
5397d8fb588SMatthias Schmidt }
5407d8fb588SMatthias Schmidt if (eq(**vp, STRLparen)) {
5417d8fb588SMatthias Schmidt (*vp)++;
5427d8fb588SMatthias Schmidt ccode = exp0(vp, ignore);
5437d8fb588SMatthias Schmidt etraci("exp6 () ccode", ccode, vp);
5447d8fb588SMatthias Schmidt if (**vp == 0 || ***vp != ')')
5457d8fb588SMatthias Schmidt stderror(ERR_NAME | ERR_EXPRESSION);
5467d8fb588SMatthias Schmidt (*vp)++;
5477d8fb588SMatthias Schmidt return (putn(ccode));
5487d8fb588SMatthias Schmidt }
5497d8fb588SMatthias Schmidt if (eq(**vp, STRLbrace)) {
5507d8fb588SMatthias Schmidt Char **v;
5517d8fb588SMatthias Schmidt struct command faket;
5527d8fb588SMatthias Schmidt Char *fakecom[2];
5537d8fb588SMatthias Schmidt
5547d8fb588SMatthias Schmidt faket.t_dtyp = NODE_COMMAND;
5557d8fb588SMatthias Schmidt faket.t_dflg = F_BACKQ;
5567d8fb588SMatthias Schmidt faket.t_dcar = faket.t_dcdr = faket.t_dspr = NULL;
5577d8fb588SMatthias Schmidt faket.t_dcom = fakecom;
5587d8fb588SMatthias Schmidt fakecom[0] = STRfakecom;
5597d8fb588SMatthias Schmidt fakecom[1] = NULL;
5607d8fb588SMatthias Schmidt (*vp)++;
5617d8fb588SMatthias Schmidt v = *vp;
5627d8fb588SMatthias Schmidt for (;;) {
5637d8fb588SMatthias Schmidt if (!**vp)
5647d8fb588SMatthias Schmidt stderror(ERR_NAME | ERR_MISSING, '}');
5657d8fb588SMatthias Schmidt if (eq(*(*vp)++, STRRbrace))
5667d8fb588SMatthias Schmidt break;
5677d8fb588SMatthias Schmidt }
5687d8fb588SMatthias Schmidt if (ignore & TEXP_IGNORE)
5697d8fb588SMatthias Schmidt return (Strsave(STRNULL));
5707d8fb588SMatthias Schmidt psavejob();
5717d8fb588SMatthias Schmidt cleanup_push(&faket, psavejob_cleanup); /* faket is only a marker */
5727d8fb588SMatthias Schmidt if (pfork(&faket, -1) == 0) {
5737d8fb588SMatthias Schmidt *--(*vp) = 0;
5747d8fb588SMatthias Schmidt evalav(v);
5757d8fb588SMatthias Schmidt exitstat();
5767d8fb588SMatthias Schmidt }
5777d8fb588SMatthias Schmidt pwait();
5787d8fb588SMatthias Schmidt cleanup_until(&faket);
579*d6ab524cSAntonio Huete Jimenez etraci("exp6 {} status", getstatus(), vp);
580*d6ab524cSAntonio Huete Jimenez return putn(getstatus() == 0);
5817d8fb588SMatthias Schmidt }
5827d8fb588SMatthias Schmidt if (isa(**vp, ANYOP))
5837d8fb588SMatthias Schmidt return (Strsave(STRNULL));
5847d8fb588SMatthias Schmidt cp = *(*vp)++;
5857d8fb588SMatthias Schmidt #ifdef convex
5867d8fb588SMatthias Schmidt # define FILETESTS "erwxfdzoplstSXLbcugkmKR"
5877d8fb588SMatthias Schmidt #else
5887d8fb588SMatthias Schmidt # define FILETESTS "erwxfdzoplstSXLbcugkmK"
5897d8fb588SMatthias Schmidt #endif /* convex */
5907d8fb588SMatthias Schmidt #define FILEVALS "ZAMCDIUGNFPL"
5917d8fb588SMatthias Schmidt if (*cp == '-' && (any(FILETESTS, cp[1]) || any(FILEVALS, cp[1])))
5927d8fb588SMatthias Schmidt return(filetest(cp, vp, ignore));
5937d8fb588SMatthias Schmidt etracc("exp6 default", cp, vp);
5947d8fb588SMatthias Schmidt return (ignore & TEXP_NOGLOB ? Strsave(cp) : globone(cp, G_APPEND));
5957d8fb588SMatthias Schmidt }
5967d8fb588SMatthias Schmidt
5977d8fb588SMatthias Schmidt
5987d8fb588SMatthias Schmidt /*
5997d8fb588SMatthias Schmidt * Extended file tests
6007d8fb588SMatthias Schmidt * From: John Rowe <rowe@excc.exeter.ac.uk>
6017d8fb588SMatthias Schmidt */
6027d8fb588SMatthias Schmidt Char *
filetest(Char * cp,Char *** vp,int ignore)6037d8fb588SMatthias Schmidt filetest(Char *cp, Char ***vp, int ignore)
6047d8fb588SMatthias Schmidt {
6057d8fb588SMatthias Schmidt #ifdef convex
6067d8fb588SMatthias Schmidt struct cvxstat stb, *st = NULL;
6077d8fb588SMatthias Schmidt # define TCSH_STAT stat64
6087d8fb588SMatthias Schmidt #else
6097d8fb588SMatthias Schmidt # define TCSH_STAT stat
6107d8fb588SMatthias Schmidt struct stat stb, *st = NULL;
6117d8fb588SMatthias Schmidt #endif /* convex */
6127d8fb588SMatthias Schmidt
6137d8fb588SMatthias Schmidt #ifdef S_IFLNK
6147d8fb588SMatthias Schmidt # ifdef convex
6157d8fb588SMatthias Schmidt struct cvxstat lstb, *lst = NULL;
6167d8fb588SMatthias Schmidt # define TCSH_LSTAT lstat64
6177d8fb588SMatthias Schmidt # else
6187d8fb588SMatthias Schmidt # define TCSH_LSTAT lstat
6197d8fb588SMatthias Schmidt struct stat lstb, *lst = NULL;
6207d8fb588SMatthias Schmidt # endif /* convex */
6217d8fb588SMatthias Schmidt char *filnam;
6227d8fb588SMatthias Schmidt #endif /* S_IFLNK */
6237d8fb588SMatthias Schmidt
62494afa86dSJohn Marino tcsh_number_t i = 0;
6257d8fb588SMatthias Schmidt unsigned pmask = 0xffff;
6267d8fb588SMatthias Schmidt int altout = 0;
6277d8fb588SMatthias Schmidt Char *ft = cp, *dp, *ep, *strdev, *strino, *strF, *str, valtest = '\0',
6287d8fb588SMatthias Schmidt *errval = STR0;
62960962bbcSJohn Marino char *string, string0[22 + MB_LEN_MAX + 1]; /* space for 64 bit octal */
6307d8fb588SMatthias Schmidt time_t footime;
6317d8fb588SMatthias Schmidt struct passwd *pw;
6327d8fb588SMatthias Schmidt struct group *gr;
6337d8fb588SMatthias Schmidt
6347d8fb588SMatthias Schmidt while (any(FILETESTS, *++ft))
6357d8fb588SMatthias Schmidt continue;
6367d8fb588SMatthias Schmidt
6377d8fb588SMatthias Schmidt if (!*ft && *(ft - 1) == 'L')
6387d8fb588SMatthias Schmidt --ft;
6397d8fb588SMatthias Schmidt
6407d8fb588SMatthias Schmidt if (any(FILEVALS, *ft)) {
6417d8fb588SMatthias Schmidt valtest = *ft++;
6427d8fb588SMatthias Schmidt /*
6437d8fb588SMatthias Schmidt * Value tests return '-1' on failure as 0 is
6447d8fb588SMatthias Schmidt * a legitimate value for many of them.
6457d8fb588SMatthias Schmidt * 'F' returns ':' for compatibility.
6467d8fb588SMatthias Schmidt */
6477d8fb588SMatthias Schmidt errval = valtest == 'F' ? STRcolon : STRminus1;
6487d8fb588SMatthias Schmidt
6497d8fb588SMatthias Schmidt if (valtest == 'P' && *ft >= '0' && *ft <= '7') {
6507d8fb588SMatthias Schmidt pmask = (char) *ft - '0';
6517d8fb588SMatthias Schmidt while ( *++ft >= '0' && *ft <= '7' )
6527d8fb588SMatthias Schmidt pmask = 8 * pmask + ((char) *ft - '0');
6537d8fb588SMatthias Schmidt }
6547d8fb588SMatthias Schmidt if (Strcmp(ft, STRcolon) == 0 && any("AMCUGP", valtest)) {
6557d8fb588SMatthias Schmidt altout = 1;
6567d8fb588SMatthias Schmidt ++ft;
6577d8fb588SMatthias Schmidt }
6587d8fb588SMatthias Schmidt }
6597d8fb588SMatthias Schmidt
6607d8fb588SMatthias Schmidt if (*ft || ft == cp + 1)
6617d8fb588SMatthias Schmidt stderror(ERR_NAME | ERR_FILEINQ);
6627d8fb588SMatthias Schmidt
6637d8fb588SMatthias Schmidt /*
6647d8fb588SMatthias Schmidt * Detect missing file names by checking for operator in the file name
6657d8fb588SMatthias Schmidt * position. However, if an operator name appears there, we must make
6667d8fb588SMatthias Schmidt * sure that there's no file by that name (e.g., "/") before announcing
6677d8fb588SMatthias Schmidt * an error. Even this check isn't quite right, since it doesn't take
6687d8fb588SMatthias Schmidt * globbing into account.
6697d8fb588SMatthias Schmidt */
6707d8fb588SMatthias Schmidt
6717d8fb588SMatthias Schmidt if (isa(**vp, ANYOP) && TCSH_STAT(short2str(**vp), &stb))
6727d8fb588SMatthias Schmidt stderror(ERR_NAME | ERR_FILENAME);
6737d8fb588SMatthias Schmidt
6747d8fb588SMatthias Schmidt dp = *(*vp)++;
6757d8fb588SMatthias Schmidt if (ignore & TEXP_IGNORE)
6767d8fb588SMatthias Schmidt return (Strsave(STRNULL));
677*d6ab524cSAntonio Huete Jimenez if ((ignore & TEXP_NOGLOB) == 0) {
6787d8fb588SMatthias Schmidt ep = globone(dp, G_APPEND);
679*d6ab524cSAntonio Huete Jimenez } else {
680*d6ab524cSAntonio Huete Jimenez ep = Strsave(dp);
681*d6ab524cSAntonio Huete Jimenez }
6827d8fb588SMatthias Schmidt cleanup_push(ep, xfree);
6837d8fb588SMatthias Schmidt ft = &cp[1];
6847d8fb588SMatthias Schmidt do
6857d8fb588SMatthias Schmidt switch (*ft) {
6867d8fb588SMatthias Schmidt
6877d8fb588SMatthias Schmidt case 'r':
6887d8fb588SMatthias Schmidt i = !sh_access(ep, R_OK);
6897d8fb588SMatthias Schmidt break;
6907d8fb588SMatthias Schmidt
6917d8fb588SMatthias Schmidt case 'w':
6927d8fb588SMatthias Schmidt i = !sh_access(ep, W_OK);
6937d8fb588SMatthias Schmidt break;
6947d8fb588SMatthias Schmidt
6957d8fb588SMatthias Schmidt case 'x':
6967d8fb588SMatthias Schmidt i = !sh_access(ep, X_OK);
6977d8fb588SMatthias Schmidt break;
6987d8fb588SMatthias Schmidt
6997d8fb588SMatthias Schmidt case 'X': /* tcsh extension, name is an executable in the path
7007d8fb588SMatthias Schmidt * or a tcsh builtin command
7017d8fb588SMatthias Schmidt */
7027d8fb588SMatthias Schmidt i = find_cmd(ep, 0);
7037d8fb588SMatthias Schmidt break;
7047d8fb588SMatthias Schmidt
7057d8fb588SMatthias Schmidt case 't': /* SGI extension, true when file is a tty */
7067d8fb588SMatthias Schmidt i = isatty(atoi(short2str(ep)));
7077d8fb588SMatthias Schmidt break;
7087d8fb588SMatthias Schmidt
7097d8fb588SMatthias Schmidt default:
7107d8fb588SMatthias Schmidt
7117d8fb588SMatthias Schmidt #ifdef S_IFLNK
7127d8fb588SMatthias Schmidt if (tolower(*ft) == 'l') {
7137d8fb588SMatthias Schmidt /*
7147d8fb588SMatthias Schmidt * avoid convex compiler bug.
7157d8fb588SMatthias Schmidt */
7167d8fb588SMatthias Schmidt if (!lst) {
7177d8fb588SMatthias Schmidt lst = &lstb;
7187d8fb588SMatthias Schmidt if (TCSH_LSTAT(short2str(ep), lst) == -1) {
7197d8fb588SMatthias Schmidt cleanup_until(ep);
7207d8fb588SMatthias Schmidt return (Strsave(errval));
7217d8fb588SMatthias Schmidt }
7227d8fb588SMatthias Schmidt }
7237d8fb588SMatthias Schmidt if (*ft == 'L')
7247d8fb588SMatthias Schmidt st = lst;
7257d8fb588SMatthias Schmidt }
7267d8fb588SMatthias Schmidt else
7277d8fb588SMatthias Schmidt #endif /* S_IFLNK */
7287d8fb588SMatthias Schmidt /*
7297d8fb588SMatthias Schmidt * avoid convex compiler bug.
7307d8fb588SMatthias Schmidt */
7317d8fb588SMatthias Schmidt if (!st) {
7327d8fb588SMatthias Schmidt st = &stb;
7337d8fb588SMatthias Schmidt if (TCSH_STAT(short2str(ep), st) == -1) {
7347d8fb588SMatthias Schmidt cleanup_until(ep);
7357d8fb588SMatthias Schmidt return (Strsave(errval));
7367d8fb588SMatthias Schmidt }
7377d8fb588SMatthias Schmidt }
7387d8fb588SMatthias Schmidt
7397d8fb588SMatthias Schmidt switch (*ft) {
7407d8fb588SMatthias Schmidt
7417d8fb588SMatthias Schmidt case 'f':
7427d8fb588SMatthias Schmidt #ifdef S_ISREG
7437d8fb588SMatthias Schmidt i = S_ISREG(st->st_mode);
7447d8fb588SMatthias Schmidt #else /* !S_ISREG */
7457d8fb588SMatthias Schmidt i = 0;
7467d8fb588SMatthias Schmidt #endif /* S_ISREG */
7477d8fb588SMatthias Schmidt break;
7487d8fb588SMatthias Schmidt
7497d8fb588SMatthias Schmidt case 'd':
7507d8fb588SMatthias Schmidt #ifdef S_ISDIR
7517d8fb588SMatthias Schmidt i = S_ISDIR(st->st_mode);
7527d8fb588SMatthias Schmidt #else /* !S_ISDIR */
7537d8fb588SMatthias Schmidt i = 0;
7547d8fb588SMatthias Schmidt #endif /* S_ISDIR */
7557d8fb588SMatthias Schmidt break;
7567d8fb588SMatthias Schmidt
7577d8fb588SMatthias Schmidt case 'p':
7587d8fb588SMatthias Schmidt #ifdef S_ISFIFO
7597d8fb588SMatthias Schmidt i = S_ISFIFO(st->st_mode);
7607d8fb588SMatthias Schmidt #else /* !S_ISFIFO */
7617d8fb588SMatthias Schmidt i = 0;
7627d8fb588SMatthias Schmidt #endif /* S_ISFIFO */
7637d8fb588SMatthias Schmidt break;
7647d8fb588SMatthias Schmidt
7657d8fb588SMatthias Schmidt case 'm' :
7667d8fb588SMatthias Schmidt #ifdef S_ISOFL
7677d8fb588SMatthias Schmidt i = S_ISOFL(st->st_dm_mode);
7687d8fb588SMatthias Schmidt #else /* !S_ISOFL */
7697d8fb588SMatthias Schmidt i = 0;
7707d8fb588SMatthias Schmidt #endif /* S_ISOFL */
7717d8fb588SMatthias Schmidt break ;
7727d8fb588SMatthias Schmidt
7737d8fb588SMatthias Schmidt case 'K' :
7747d8fb588SMatthias Schmidt #ifdef S_ISOFL
7757d8fb588SMatthias Schmidt i = stb.st_dm_key;
7767d8fb588SMatthias Schmidt #else /* !S_ISOFL */
7777d8fb588SMatthias Schmidt i = 0;
7787d8fb588SMatthias Schmidt #endif /* S_ISOFL */
7797d8fb588SMatthias Schmidt break ;
7807d8fb588SMatthias Schmidt
7817d8fb588SMatthias Schmidt
7827d8fb588SMatthias Schmidt case 'l':
7837d8fb588SMatthias Schmidt #ifdef S_ISLNK
7847d8fb588SMatthias Schmidt i = S_ISLNK(lst->st_mode);
7857d8fb588SMatthias Schmidt #else /* !S_ISLNK */
7867d8fb588SMatthias Schmidt i = 0;
7877d8fb588SMatthias Schmidt #endif /* S_ISLNK */
7887d8fb588SMatthias Schmidt break;
7897d8fb588SMatthias Schmidt
7907d8fb588SMatthias Schmidt case 'S':
7917d8fb588SMatthias Schmidt # ifdef S_ISSOCK
7927d8fb588SMatthias Schmidt i = S_ISSOCK(st->st_mode);
7937d8fb588SMatthias Schmidt # else /* !S_ISSOCK */
7947d8fb588SMatthias Schmidt i = 0;
7957d8fb588SMatthias Schmidt # endif /* S_ISSOCK */
7967d8fb588SMatthias Schmidt break;
7977d8fb588SMatthias Schmidt
7987d8fb588SMatthias Schmidt case 'b':
7997d8fb588SMatthias Schmidt #ifdef S_ISBLK
8007d8fb588SMatthias Schmidt i = S_ISBLK(st->st_mode);
8017d8fb588SMatthias Schmidt #else /* !S_ISBLK */
8027d8fb588SMatthias Schmidt i = 0;
8037d8fb588SMatthias Schmidt #endif /* S_ISBLK */
8047d8fb588SMatthias Schmidt break;
8057d8fb588SMatthias Schmidt
8067d8fb588SMatthias Schmidt case 'c':
8077d8fb588SMatthias Schmidt #ifdef S_ISCHR
8087d8fb588SMatthias Schmidt i = S_ISCHR(st->st_mode);
8097d8fb588SMatthias Schmidt #else /* !S_ISCHR */
8107d8fb588SMatthias Schmidt i = 0;
8117d8fb588SMatthias Schmidt #endif /* S_ISCHR */
8127d8fb588SMatthias Schmidt break;
8137d8fb588SMatthias Schmidt
8147d8fb588SMatthias Schmidt case 'u':
8157d8fb588SMatthias Schmidt i = (S_ISUID & st->st_mode) != 0;
8167d8fb588SMatthias Schmidt break;
8177d8fb588SMatthias Schmidt
8187d8fb588SMatthias Schmidt case 'g':
8197d8fb588SMatthias Schmidt i = (S_ISGID & st->st_mode) != 0;
8207d8fb588SMatthias Schmidt break;
8217d8fb588SMatthias Schmidt
8227d8fb588SMatthias Schmidt case 'k':
8237d8fb588SMatthias Schmidt i = (S_ISVTX & st->st_mode) != 0;
8247d8fb588SMatthias Schmidt break;
8257d8fb588SMatthias Schmidt
8267d8fb588SMatthias Schmidt case 'z':
8277d8fb588SMatthias Schmidt i = st->st_size == 0;
8287d8fb588SMatthias Schmidt break;
8297d8fb588SMatthias Schmidt
8307d8fb588SMatthias Schmidt #ifdef convex
8317d8fb588SMatthias Schmidt case 'R':
8327d8fb588SMatthias Schmidt i = (stb.st_dmonflags & IMIGRATED) == IMIGRATED;
8337d8fb588SMatthias Schmidt break;
8347d8fb588SMatthias Schmidt #endif /* convex */
8357d8fb588SMatthias Schmidt
8367d8fb588SMatthias Schmidt case 's':
8377d8fb588SMatthias Schmidt i = stb.st_size != 0;
8387d8fb588SMatthias Schmidt break;
8397d8fb588SMatthias Schmidt
8407d8fb588SMatthias Schmidt case 'e':
8417d8fb588SMatthias Schmidt i = 1;
8427d8fb588SMatthias Schmidt break;
8437d8fb588SMatthias Schmidt
8447d8fb588SMatthias Schmidt case 'o':
8457d8fb588SMatthias Schmidt i = st->st_uid == uid;
8467d8fb588SMatthias Schmidt break;
8477d8fb588SMatthias Schmidt
8487d8fb588SMatthias Schmidt /*
8497d8fb588SMatthias Schmidt * Value operators are a tcsh extension.
8507d8fb588SMatthias Schmidt */
8517d8fb588SMatthias Schmidt
8527d8fb588SMatthias Schmidt case 'D':
85394afa86dSJohn Marino i = (tcsh_number_t) st->st_dev;
8547d8fb588SMatthias Schmidt break;
8557d8fb588SMatthias Schmidt
8567d8fb588SMatthias Schmidt case 'I':
85794afa86dSJohn Marino i = (tcsh_number_t) st->st_ino;
8587d8fb588SMatthias Schmidt break;
8597d8fb588SMatthias Schmidt
8607d8fb588SMatthias Schmidt case 'F':
8617d8fb588SMatthias Schmidt strdev = putn( (int) st->st_dev);
8627d8fb588SMatthias Schmidt strino = putn( (int) st->st_ino);
8637d8fb588SMatthias Schmidt strF = xmalloc((2 + Strlen(strdev) + Strlen(strino))
8647d8fb588SMatthias Schmidt * sizeof(Char));
8657d8fb588SMatthias Schmidt (void) Strcat(Strcat(Strcpy(strF, strdev), STRcolon), strino);
8667d8fb588SMatthias Schmidt xfree(strdev);
8677d8fb588SMatthias Schmidt xfree(strino);
8687d8fb588SMatthias Schmidt cleanup_until(ep);
8697d8fb588SMatthias Schmidt return(strF);
8707d8fb588SMatthias Schmidt
8717d8fb588SMatthias Schmidt case 'L':
8727d8fb588SMatthias Schmidt if ( *(ft + 1) ) {
8737d8fb588SMatthias Schmidt i = 1;
8747d8fb588SMatthias Schmidt break;
8757d8fb588SMatthias Schmidt }
8767d8fb588SMatthias Schmidt #ifdef S_ISLNK
8777d8fb588SMatthias Schmidt filnam = short2str(ep);
8787d8fb588SMatthias Schmidt string = areadlink(filnam);
8797d8fb588SMatthias Schmidt strF = string == NULL ? errval : str2short(string);
8807d8fb588SMatthias Schmidt xfree(string);
8817d8fb588SMatthias Schmidt cleanup_until(ep);
8827d8fb588SMatthias Schmidt return(Strsave(strF));
8837d8fb588SMatthias Schmidt
8847d8fb588SMatthias Schmidt #else /* !S_ISLNK */
8857d8fb588SMatthias Schmidt i = 0;
8867d8fb588SMatthias Schmidt break;
8877d8fb588SMatthias Schmidt #endif /* S_ISLNK */
8887d8fb588SMatthias Schmidt
8897d8fb588SMatthias Schmidt
8907d8fb588SMatthias Schmidt case 'N':
89194afa86dSJohn Marino i = (tcsh_number_t) st->st_nlink;
8927d8fb588SMatthias Schmidt break;
8937d8fb588SMatthias Schmidt
8947d8fb588SMatthias Schmidt case 'P':
8957d8fb588SMatthias Schmidt string = string0 + 1;
8967d8fb588SMatthias Schmidt (void) xsnprintf(string, sizeof(string0) - 1, "%o",
8977d8fb588SMatthias Schmidt pmask & (unsigned int)
8987d8fb588SMatthias Schmidt ((S_IRWXU|S_IRWXG|S_IRWXO|S_ISUID|S_ISGID) & st->st_mode));
8997d8fb588SMatthias Schmidt if (altout && *string != '0')
9007d8fb588SMatthias Schmidt *--string = '0';
9017d8fb588SMatthias Schmidt cleanup_until(ep);
9027d8fb588SMatthias Schmidt return(Strsave(str2short(string)));
9037d8fb588SMatthias Schmidt
9047d8fb588SMatthias Schmidt case 'U':
9057d8fb588SMatthias Schmidt if (altout && (pw = xgetpwuid(st->st_uid))) {
9067d8fb588SMatthias Schmidt cleanup_until(ep);
9077d8fb588SMatthias Schmidt return(Strsave(str2short(pw->pw_name)));
9087d8fb588SMatthias Schmidt }
90994afa86dSJohn Marino i = (tcsh_number_t) st->st_uid;
9107d8fb588SMatthias Schmidt break;
9117d8fb588SMatthias Schmidt
9127d8fb588SMatthias Schmidt case 'G':
9137d8fb588SMatthias Schmidt if (altout && (gr = xgetgrgid(st->st_gid))) {
9147d8fb588SMatthias Schmidt cleanup_until(ep);
9157d8fb588SMatthias Schmidt return(Strsave(str2short(gr->gr_name)));
9167d8fb588SMatthias Schmidt }
91794afa86dSJohn Marino i = (tcsh_number_t) st->st_gid;
9187d8fb588SMatthias Schmidt break;
9197d8fb588SMatthias Schmidt
9207d8fb588SMatthias Schmidt case 'Z':
92194afa86dSJohn Marino i = (tcsh_number_t) st->st_size;
9227d8fb588SMatthias Schmidt break;
9237d8fb588SMatthias Schmidt
9247d8fb588SMatthias Schmidt case 'A': case 'M': case 'C':
9257d8fb588SMatthias Schmidt footime = *ft == 'A' ? st->st_atime :
9267d8fb588SMatthias Schmidt *ft == 'M' ? st->st_mtime : st->st_ctime;
9277d8fb588SMatthias Schmidt if (altout) {
9287d8fb588SMatthias Schmidt strF = str2short(ctime(&footime));
9297d8fb588SMatthias Schmidt if ((str = Strchr(strF, '\n')) != NULL)
9307d8fb588SMatthias Schmidt *str = (Char) '\0';
9317d8fb588SMatthias Schmidt cleanup_until(ep);
9327d8fb588SMatthias Schmidt return(Strsave(strF));
9337d8fb588SMatthias Schmidt }
93494afa86dSJohn Marino i = (tcsh_number_t) footime;
9357d8fb588SMatthias Schmidt break;
9367d8fb588SMatthias Schmidt
9377d8fb588SMatthias Schmidt }
9387d8fb588SMatthias Schmidt }
9397d8fb588SMatthias Schmidt while (*++ft && i);
9407d8fb588SMatthias Schmidt etraci("exp6 -? i", i, vp);
9417d8fb588SMatthias Schmidt cleanup_until(ep);
9427d8fb588SMatthias Schmidt return (putn(i));
9437d8fb588SMatthias Schmidt }
9447d8fb588SMatthias Schmidt
9457d8fb588SMatthias Schmidt
9467d8fb588SMatthias Schmidt static void
evalav(Char ** v)9477d8fb588SMatthias Schmidt evalav(Char **v)
9487d8fb588SMatthias Schmidt {
9497d8fb588SMatthias Schmidt struct wordent paraml1;
9507d8fb588SMatthias Schmidt struct wordent *hp = ¶ml1;
9517d8fb588SMatthias Schmidt struct command *t;
9527d8fb588SMatthias Schmidt struct wordent *wdp = hp;
9537d8fb588SMatthias Schmidt
954*d6ab524cSAntonio Huete Jimenez setstatus(0);
955653fab9eSSascha Wildner initlex(hp);
9567d8fb588SMatthias Schmidt while (*v) {
9577d8fb588SMatthias Schmidt struct wordent *new = xcalloc(1, sizeof *wdp);
9587d8fb588SMatthias Schmidt
9597d8fb588SMatthias Schmidt new->prev = wdp;
9607d8fb588SMatthias Schmidt new->next = hp;
9617d8fb588SMatthias Schmidt wdp->next = new;
9627d8fb588SMatthias Schmidt wdp = new;
9637d8fb588SMatthias Schmidt wdp->word = Strsave(*v++);
9647d8fb588SMatthias Schmidt }
9657d8fb588SMatthias Schmidt hp->prev = wdp;
9667d8fb588SMatthias Schmidt cleanup_push(¶ml1, lex_cleanup);
9677d8fb588SMatthias Schmidt alias(¶ml1);
9687d8fb588SMatthias Schmidt t = syntax(paraml1.next, ¶ml1, 0);
9697d8fb588SMatthias Schmidt cleanup_push(t, syntax_cleanup);
9707d8fb588SMatthias Schmidt if (seterr)
9717d8fb588SMatthias Schmidt stderror(ERR_OLD);
9727d8fb588SMatthias Schmidt execute(t, -1, NULL, NULL, TRUE);
9737d8fb588SMatthias Schmidt cleanup_until(¶ml1);
9747d8fb588SMatthias Schmidt }
9757d8fb588SMatthias Schmidt
9767d8fb588SMatthias Schmidt static int
isa(Char * cp,int what)9777d8fb588SMatthias Schmidt isa(Char *cp, int what)
9787d8fb588SMatthias Schmidt {
9797d8fb588SMatthias Schmidt if (cp == 0)
9807d8fb588SMatthias Schmidt return ((what & RESTOP) != 0);
9817d8fb588SMatthias Schmidt if (*cp == '\0')
9827d8fb588SMatthias Schmidt return 0;
9837d8fb588SMatthias Schmidt if (cp[1] == 0) {
9847d8fb588SMatthias Schmidt if (what & ADDOP && (*cp == '+' || *cp == '-'))
9857d8fb588SMatthias Schmidt return (1);
9867d8fb588SMatthias Schmidt if (what & MULOP && (*cp == '*' || *cp == '/' || *cp == '%'))
9877d8fb588SMatthias Schmidt return (1);
9887d8fb588SMatthias Schmidt if (what & RESTOP && (*cp == '(' || *cp == ')' || *cp == '!' ||
9897d8fb588SMatthias Schmidt *cp == '~' || *cp == '^' || *cp == '"'))
9907d8fb588SMatthias Schmidt return (1);
9917d8fb588SMatthias Schmidt }
9927d8fb588SMatthias Schmidt else if (cp[2] == 0) {
9937d8fb588SMatthias Schmidt if (what & RESTOP) {
9947d8fb588SMatthias Schmidt if (cp[0] == '|' && cp[1] == '&')
9957d8fb588SMatthias Schmidt return (1);
9967d8fb588SMatthias Schmidt if (cp[0] == '<' && cp[1] == '<')
9977d8fb588SMatthias Schmidt return (1);
9987d8fb588SMatthias Schmidt if (cp[0] == '>' && cp[1] == '>')
9997d8fb588SMatthias Schmidt return (1);
10007d8fb588SMatthias Schmidt }
10017d8fb588SMatthias Schmidt if (what & EQOP) {
10027d8fb588SMatthias Schmidt if (cp[0] == '=') {
10037d8fb588SMatthias Schmidt if (cp[1] == '=')
10047d8fb588SMatthias Schmidt return (EQEQ);
10057d8fb588SMatthias Schmidt if (cp[1] == '~')
10067d8fb588SMatthias Schmidt return (EQMATCH);
10077d8fb588SMatthias Schmidt }
10087d8fb588SMatthias Schmidt else if (cp[0] == '!') {
10097d8fb588SMatthias Schmidt if (cp[1] == '=')
10107d8fb588SMatthias Schmidt return (NOTEQ);
10117d8fb588SMatthias Schmidt if (cp[1] == '~')
10127d8fb588SMatthias Schmidt return (NOTEQMATCH);
10137d8fb588SMatthias Schmidt }
10147d8fb588SMatthias Schmidt }
10157d8fb588SMatthias Schmidt }
10167d8fb588SMatthias Schmidt if (what & RELOP) {
10177d8fb588SMatthias Schmidt if (*cp == '<')
10187d8fb588SMatthias Schmidt return (LSS);
10197d8fb588SMatthias Schmidt if (*cp == '>')
10207d8fb588SMatthias Schmidt return (GTR);
10217d8fb588SMatthias Schmidt }
10227d8fb588SMatthias Schmidt return (0);
10237d8fb588SMatthias Schmidt }
10247d8fb588SMatthias Schmidt
102594afa86dSJohn Marino static tcsh_number_t
egetn(const Char * cp)102694afa86dSJohn Marino egetn(const Char *cp)
10277d8fb588SMatthias Schmidt {
10287d8fb588SMatthias Schmidt if (*cp && *cp != '-' && !Isdigit(*cp))
10297d8fb588SMatthias Schmidt stderror(ERR_NAME | ERR_EXPRESSION);
10307d8fb588SMatthias Schmidt return (getn(cp));
10317d8fb588SMatthias Schmidt }
10327d8fb588SMatthias Schmidt
10337d8fb588SMatthias Schmidt /* Phew! */
10347d8fb588SMatthias Schmidt
10357d8fb588SMatthias Schmidt #ifdef EDEBUG
10367d8fb588SMatthias Schmidt static void
etraci(const char * str,tcsh_number_t i,Char *** vp)103794afa86dSJohn Marino etraci(const char *str, tcsh_number_t i, Char ***vp)
10387d8fb588SMatthias Schmidt {
103994afa86dSJohn Marino #ifdef HAVE_LONG_LONG
104094afa86dSJohn Marino xprintf("%s=%lld\t", str, i);
104194afa86dSJohn Marino #else
104294afa86dSJohn Marino xprintf("%s=%ld\t", str, i);
104394afa86dSJohn Marino #endif
10447d8fb588SMatthias Schmidt blkpr(*vp);
10457d8fb588SMatthias Schmidt xputchar('\n');
10467d8fb588SMatthias Schmidt }
10477d8fb588SMatthias Schmidt static void
etracc(const char * str,const Char * cp,Char *** vp)104857e3f2b5SSimon 'corecode' Schubert etracc(const char *str, const Char *cp, Char ***vp)
10497d8fb588SMatthias Schmidt {
105057e3f2b5SSimon 'corecode' Schubert xprintf("%s=%S\t", str, cp);
10517d8fb588SMatthias Schmidt blkpr(*vp);
10527d8fb588SMatthias Schmidt xputchar('\n');
10537d8fb588SMatthias Schmidt }
10547d8fb588SMatthias Schmidt #endif /* EDEBUG */
1055