da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner* Copyright (c) 1982-2010 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* http://www.opensource.org/licenses/cpl1.0.txt *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#pragma prototyped
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * test expression
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * [ expression ]
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * David Korn
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Labs
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "defs.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <error.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <ls.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "io.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "terminal.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "test.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "builtins.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "FEATURE/externs"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "FEATURE/poll"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <tmx.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if !_lib_setregid
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# undef _lib_setreuid
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* _lib_setregid */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef S_ISSOCK
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# if _pipe_socketpair
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# if _socketpair_shutdown_mode
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define isapipe(f,p) (test_stat(f,p)>=0&&S_ISFIFO((p)->st_mode)||S_ISSOCK((p)->st_mode)&&(p)->st_ino&&((p)->st_mode&(S_IRUSR|S_IWUSR))!=(S_IRUSR|S_IWUSR))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define isapipe(f,p) (test_stat(f,p)>=0&&S_ISFIFO((p)->st_mode)||S_ISSOCK((p)->st_mode)&&(p)->st_ino)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define isapipe(f,p) (test_stat(f,p)>=0&&S_ISFIFO((p)->st_mode)||S_ISSOCK((p)->st_mode)&&(p)->st_ino)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define isasock(f,p) (test_stat(f,p)>=0&&S_ISSOCK((p)->st_mode))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define isapipe(f,p) (test_stat(f,p)>=0&&S_ISFIFO((p)->st_mode))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define isasock(f,p) (0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define permission(a,f) (sh_access(a,f)==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic time_t test_time(const char*, const char*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int test_stat(const char*, struct stat*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int test_mode(const char*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* single char string compare */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define c_eq(a,c) (*a==c && *(a+1)==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* two character string compare */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define c2_eq(a,c1,c2) (*a==c1 && *(a+1)==c2 && *(a+2)==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstruct test
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Shell_t *sh;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int ap;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int ac;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char **av;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin};
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic char *nxtarg(struct test*,int);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int expr(struct test*,int);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int e3(struct test*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int test_strmatch(const char *str, const char *pat)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int match[2*(MATCH_MAX+1)],n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c, m=0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register const char *cp=pat;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(c = *cp++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(c=='(')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin m++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(c=='\\' && *cp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(m)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin m++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin match[0] = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(m > elementsof(match)/2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin m = elementsof(match)/2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = strgrpmatch(str, pat, match, m, STR_MAXIMAL|STR_LEFT|STR_RIGHT);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(m==0 && n==1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin match[1] = strlen(str);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_setmatch(str, -1, n, match);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint b_test(int argc, char *argv[],void *extra)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct test tdata;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *cp = argv[0];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int not;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin tdata.sh = ((Shbltin_t*)extra)->shp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tdata.av = argv;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tdata.ap = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(c_eq(cp,'['))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp = argv[--argc];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!c_eq(cp, ']'))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_exit(2),e_missing,"']'");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(argc <= 1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp = argv[1];
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(c_eq(cp,'(') && argc<=6 && c_eq(argv[argc-1],')'))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin /* special case ( binop ) to conform with standard */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!(argc==4 && (not=sh_lookup(cp=argv[2],shtab_testops))))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin cp = (++argv)[1];
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin argc -= 2;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin not = c_eq(cp,'!');
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* posix portion for test */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch(argc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 5:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!not)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin argv++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* fall through */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 4:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int op = sh_lookup(cp=argv[2],shtab_testops);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(op&TEST_BINOP)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!op)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(argc==5)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(not && cp[0]=='-' && cp[2]==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(test_unop(cp[1],argv[3])!=0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(argv[1][0]=='-' && argv[1][2]==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(!test_unop(argv[1][1],cp));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_exit(2),e_badop,cp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(test_binop(op,argv[1],argv[3])^(argc!=5));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 3:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(not)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(*argv[2]!=0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(cp[0] != '-' || cp[2] || cp[1]=='?')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(cp[0]=='-' && (cp[1]=='-' || cp[1]=='?') &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin strcmp(argv[2],"--")==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char *av[3];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin av[0] = argv[0];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin av[1] = argv[1];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin av[2] = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin optget(av,sh_opttest);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_usage(2), "%s",opt_info.arg);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(2);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(!test_unop(cp[1],argv[2]));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 2:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(*cp==0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tdata.ac = argc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(!expr(&tdata,0));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * evaluate a test expression.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * flag is 0 on outer level
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * flag is 1 when in parenthesis
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * flag is 2 when evaluating -a
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int expr(struct test *tp,register int flag)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int r;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *p;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r = e3(tp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(tp->ap < tp->ac)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p = nxtarg(tp,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check for -o and -a */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(flag && c_eq(p,')'))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tp->ap--;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(*p=='-' && *(p+2)==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(*++p == 'o')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(flag==2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tp->ap--;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r |= expr(tp,3);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(*p == 'a')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r &= expr(tp,2);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(flag==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_exit(2),e_badsyntax);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(r);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic char *nxtarg(struct test *tp,int mt)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(tp->ap >= tp->ac)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(mt)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tp->ap++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_exit(2),e_argument);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(tp->av[tp->ap++]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int e3(struct test *tp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *arg, *cp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int op;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char *binop;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin arg=nxtarg(tp,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(arg && c_eq(arg, '!'))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(!e3(tp));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(c_eq(arg, '('))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin op = expr(tp,1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp = nxtarg(tp,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!cp || !c_eq(cp, ')'))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_exit(2),e_missing,"')'");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(op);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp = nxtarg(tp,1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(cp!=0 && (c_eq(cp,'=') || c2_eq(cp,'!','=')))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto skip;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(c2_eq(arg,'-','t'))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(cp)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz {
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz op = strtol(cp,&binop, 10);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz return(*binop?0:tty_check(op));
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* test -t with no arguments */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tp->ap--;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(tty_check(1));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(*arg=='-' && arg[2]==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin op = arg[1];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!cp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* for backward compatibility with new flags */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(op==0 || !strchr(test_opchars+10,op))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_exit(2),e_argument);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(strchr(test_opchars,op))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(test_unop(op,cp));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!cp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tp->ap--;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(*arg!=0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinskip:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin op = sh_lookup(binop=cp,shtab_testops);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(op&TEST_BINOP))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp = nxtarg(tp,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!op)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_exit(2),e_badop,binop);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(op==TEST_AND || op==TEST_OR)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tp->ap--;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(test_binop(op,arg,cp));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint test_unop(register int op,register const char *arg)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct stat statb;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch(op)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'r':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(permission(arg, R_OK));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'w':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(permission(arg, W_OK));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'x':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(permission(arg, X_OK));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'V':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if SHOPT_FS_3D
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int offset = staktell();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(stat(arg,&statb)<0 || !S_ISREG(statb.st_mode))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* add trailing / */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stakputs(arg);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stakputc('/');
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stakputc(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin arg = (const char*)stakptr(offset);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stakseek(offset);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* FALL THRU */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_FS_3D */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'd':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(test_stat(arg,&statb)>=0 && S_ISDIR(statb.st_mode));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'c':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(test_stat(arg,&statb)>=0 && S_ISCHR(statb.st_mode));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'b':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(test_stat(arg,&statb)>=0 && S_ISBLK(statb.st_mode));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'f':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(test_stat(arg,&statb)>=0 && S_ISREG(statb.st_mode));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'u':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(test_mode(arg)&S_ISUID);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'g':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(test_mode(arg)&S_ISGID);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'k':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef S_ISVTX
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(test_mode(arg)&S_ISVTX);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* S_ISVTX */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if SHOPT_TEST_L
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'l':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'L':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'h': /* undocumented, and hopefully will disappear */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(*arg==0 || arg[strlen(arg)-1]=='/' || lstat(arg,&statb)<0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(S_ISLNK(statb.st_mode));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'C':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef S_ISCTG
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(test_stat(arg,&statb)>=0 && S_ISCTG(statb.st_mode));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* S_ISCTG */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'H':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef S_ISCDF
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int offset = staktell();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(test_stat(arg,&statb)>=0 && S_ISCDF(statb.st_mode))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stakputs(arg);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stakputc('+');
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stakputc(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin arg = (const char*)stakptr(offset);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stakseek(offset);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(test_stat(arg,&statb)>=0 && S_ISCDF(statb.st_mode));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* S_ISCDF */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'S':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(isasock(arg,&statb));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'N':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(test_stat(arg,&statb)>=0 && tmxgetmtime(&statb) > tmxgetatime(&statb));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'p':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(isapipe(arg,&statb));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'n':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(*arg != 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'z':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(*arg == 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 's':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfsync(sfstdout);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'O':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'G':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(*arg==0 || test_stat(arg,&statb)<0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(op=='s')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(statb.st_size>0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(op=='O')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(statb.st_uid==sh.userid);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(statb.st_gid==sh.groupid);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'a':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'e':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(permission(arg, F_OK));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'o':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f=1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(*arg=='?')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(sh_lookopt(arg+1,&f)>0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin op = sh_lookopt(arg,&f);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(op && (f==(sh_isoption(op)!=0)));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 't':
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz {
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz char *last;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz op = strtol(arg,&last, 10);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz return(*last?0:tty_check(op));
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz }
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz case 'v':
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz case 'R':
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz {
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz Namval_t *np;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz Namarr_t *ap;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz int isref;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(!(np = nv_open(arg,sh.var_tree,NV_VARNAME|NV_NOFAIL|NV_NOADD|NV_NOREF)))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz return(0);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz isref = nv_isref(np);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(op=='R')
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz return(isref);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(isref)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz {
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(np->nvalue.cp)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz np = nv_refnode(np);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz else
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz return(0);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz }
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(ap = nv_arrayptr(np))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz return(nv_arrayisset(np,ap));
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz return(!nv_isnull(np) || nv_isattr(np,NV_INTEGER));
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static char a[3] = "-?";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin a[1]= op;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_exit(2),e_badop,a);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* NOTREACHED */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint test_binop(register int op,const char *left,const char *right)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register double lnum,rnum;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(op&TEST_ARITH)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(*left=='0')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin left++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(*right=='0')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin right++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin lnum = sh_arith(left);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rnum = sh_arith(right);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch(op)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* op must be one of the following values */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case TEST_AND:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case TEST_OR:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(*left!=0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case TEST_PEQ:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(test_strmatch(left, right));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case TEST_PNE:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(!test_strmatch(left, right));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case TEST_SGT:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(strcoll(left, right)>0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case TEST_SLT:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(strcoll(left, right)<0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case TEST_SEQ:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(strcmp(left, right)==0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case TEST_SNE:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(strcmp(left, right)!=0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case TEST_EF:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(test_inode(left,right));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case TEST_NT:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(test_time(left,right)>0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case TEST_OT:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(test_time(left,right)<0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case TEST_EQ:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(lnum==rnum);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case TEST_NE:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(lnum!=rnum);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case TEST_GT:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(lnum>rnum);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case TEST_LT:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(lnum<rnum);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case TEST_GE:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(lnum>=rnum);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case TEST_LE:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(lnum<=rnum);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* NOTREACHED */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * returns the modification time of f1 - modification time of f2
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic time_t test_time(const char *file1,const char *file2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Time_t t1, t2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct stat statb1,statb2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int r=test_stat(file2,&statb2);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(test_stat(file1,&statb1)<0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(r<0?0:-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(r<0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin t1 = tmxgetmtime(&statb1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin t2 = tmxgetmtime(&statb2);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (t1 > t2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (t1 < t2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * return true if inode of two files are the same
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint test_inode(const char *file1,const char *file2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct stat stat1,stat2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(test_stat(file1,&stat1)>=0 && test_stat(file2,&stat2)>=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(stat1.st_dev == stat2.st_dev && stat1.st_ino == stat2.st_ino)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This version of access checks against effective uid/gid
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The static buffer statb is shared with test_mode.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint sh_access(register const char *name, register int mode)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct stat statb;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(*name==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(strmatch(name,(char*)e_devfdNN))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(sh_ioaccess((int)strtol(name+8, (char**)0, 10),mode));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* can't use access function for execute permission with root */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(mode==X_OK && sh.euserid==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto skip;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh.userid==sh.euserid && sh.groupid==sh.egroupid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(access(name,mode));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef _lib_setreuid
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* swap the real uid to effective, check access then restore */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* first swap real and effective gid, if different */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh.groupid==sh.euserid || setregid(sh.egroupid,sh.groupid)==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* next swap real and effective uid, if needed */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh.userid==sh.euserid || setreuid(sh.euserid,sh.userid)==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin mode = access(name,mode);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* restore ids */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh.userid!=sh.euserid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin setreuid(sh.userid,sh.euserid);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh.groupid!=sh.egroupid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin setregid(sh.groupid,sh.egroupid);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(mode);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(sh.groupid!=sh.egroupid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin setregid(sh.groupid,sh.egroupid);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* _lib_setreuid */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinskip:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(test_stat(name, &statb) == 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(mode == F_OK)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(mode);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(sh.euserid == 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!S_ISREG(statb.st_mode) || mode!=X_OK)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* root needs execute permission for someone */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin mode = (S_IXUSR|S_IXGRP|S_IXOTH);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(sh.euserid == statb.st_uid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin mode <<= 6;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(sh.egroupid == statb.st_gid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin mode <<= 3;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef _lib_getgroups
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* on some systems you can be in several groups */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static int maxgroups;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin gid_t *groups;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(maxgroups==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* first time */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((maxgroups=getgroups(0,(gid_t*)0)) <= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* pre-POSIX system */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin maxgroups=NGROUPS_MAX;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin groups = (gid_t*)stakalloc((maxgroups+1)*sizeof(gid_t));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = getgroups(maxgroups,groups);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(--n >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(groups[n] == statb.st_gid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin mode <<= 3;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* _lib_getgroups */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(statb.st_mode & mode)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Return the mode bits of file <file>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * If <file> is null, then the previous stat buffer is used.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The mode bits are zero if the file doesn't exist.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int test_mode(register const char *file)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct stat statb;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(file && (*file==0 || test_stat(file,&statb)<0))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(statb.st_mode);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * do an fstat() for /dev/fd/n, otherwise stat()
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int test_stat(const char *name,struct stat *buff)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(*name==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errno = ENOENT;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(strmatch(name,(char*)e_devfdNN))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(fstat((int)strtol(name+8, (char**)0, 10),buff));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(stat(name,buff));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}