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