Magellan Linux

Diff of /trunk/mkinitrd-magellan/klibc/usr/dash/bltin/test.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1121 by niro, Fri Apr 24 18:32:46 2009 UTC revision 1122 by niro, Wed Aug 18 21:11:40 2010 UTC
# Line 11  Line 11 
11  #include <sys/stat.h>  #include <sys/stat.h>
12  #include <sys/types.h>  #include <sys/types.h>
13    
14  #include <ctype.h>  #include <fcntl.h>
15  #include <errno.h>  #include <stdint.h>
16  #include <stdlib.h>  #include <stdlib.h>
17  #include <string.h>  #include <string.h>
18  #include <unistd.h>  #include <unistd.h>
# Line 143  static int nexpr(enum token); Line 143  static int nexpr(enum token);
143  static int primary(enum token);  static int primary(enum token);
144  static int binop(void);  static int binop(void);
145  static int filstat(char *, enum token);  static int filstat(char *, enum token);
146  static enum token t_lex(char *);  static enum token t_lex(char **);
147  static int isoperand(void);  static int isoperand(char **);
 static int getn(const char *);  
148  static int newerf(const char *, const char *);  static int newerf(const char *, const char *);
149  static int olderf(const char *, const char *);  static int olderf(const char *, const char *);
150  static int equalf(const char *, const char *);  static int equalf(const char *, const char *);
151    #ifdef HAVE_FACCESSAT
152    static int test_file_access(const char *, int);
153    #else
154  static int test_st_mode(const struct stat64 *, int);  static int test_st_mode(const struct stat64 *, int);
155  static int bash_group_member(gid_t);  static int bash_group_member(gid_t);
156    #endif
157    
158    static inline intmax_t getn(const char *s)
159    {
160     return atomax10(s);
161    }
162    
163    static const struct t_op *getop(const char *s)
164    {
165     const struct t_op *op;
166    
167     for (op = ops; op->op_text; op++) {
168     if (strcmp(s, op->op_text) == 0)
169     return op;
170     }
171    
172     return NULL;
173    }
174    
175  int  int
176  testcmd(int argc, char **argv)  testcmd(int argc, char **argv)
177  {  {
178     const struct t_op *op;
179     enum token n;
180   int res;   int res;
181    
182   if (strcmp(argv[0], "[") == 0) {   if (*argv[0] == '[') {
183   if (strcmp(argv[--argc], "]"))   if (*argv[--argc] != ']')
184   error("missing ]");   error("missing ]");
185   argv[argc] = NULL;   argv[argc] = NULL;
186   }   }
187    
188   if (argc < 2)   argv++;
189     argc--;
190    
191     if (argc < 1)
192   return 1;   return 1;
193    
194   t_wp = &argv[1];   /*
195   res = !oexpr(t_lex(*t_wp));   * POSIX prescriptions: he who wrote this deserves the Nobel
196     * peace prize.
197     */
198     switch (argc) {
199     case 3:
200     op = getop(argv[1]);
201     if (op && op->op_type == BINOP) {
202     n = OPERAND;
203     goto eval;
204     }
205     /* fall through */
206    
207     case 4:
208     if (!strcmp(argv[0], "(") && !strcmp(argv[argc - 1], ")")) {
209     argv[--argc] = NULL;
210     argv++;
211     argc--;
212     }
213     }
214    
215     n = t_lex(argv);
216    
217    eval:
218     t_wp = argv;
219     res = !oexpr(n);
220     argv = t_wp;
221    
222   if (*t_wp != NULL && *++t_wp != NULL)   if (argv[0] != NULL && argv[1] != NULL)
223   syntax(*t_wp, "unexpected operator");   syntax(argv[0], "unexpected operator");
224    
225   return res;   return res;
226  }  }
# Line 187  syntax(const char *op, const char *msg) Line 237  syntax(const char *op, const char *msg)
237  static int  static int
238  oexpr(enum token n)  oexpr(enum token n)
239  {  {
240   int res;   int res = 0;
241    
242   res = aexpr(n);   for (;;) {
243   if (t_lex(*++t_wp) == BOR)   res |= aexpr(n);
244   return oexpr(t_lex(*++t_wp)) || res;   n = t_lex(t_wp + 1);
245   t_wp--;   if (n != BOR)
246     break;
247     n = t_lex(t_wp += 2);
248     }
249   return res;   return res;
250  }  }
251    
252  static int  static int
253  aexpr(enum token n)  aexpr(enum token n)
254  {  {
255   int res;   int res = 1;
256    
257   res = nexpr(n);   for (;;) {
258   if (t_lex(*++t_wp) == BAND)   if (!nexpr(n))
259   return aexpr(t_lex(*++t_wp)) && res;   res = 0;
260   t_wp--;   n = t_lex(t_wp + 1);
261     if (n != BAND)
262     break;
263     n = t_lex(t_wp += 2);
264     }
265   return res;   return res;
266  }  }
267    
# Line 212  static int Line 269  static int
269  nexpr(enum token n)  nexpr(enum token n)
270  {  {
271   if (n == UNOT)   if (n == UNOT)
272   return !nexpr(t_lex(*++t_wp));   return !nexpr(t_lex(++t_wp));
273   return primary(n);   return primary(n);
274  }  }
275    
# Line 225  primary(enum token n) Line 282  primary(enum token n)
282   if (n == EOI)   if (n == EOI)
283   return 0; /* missing expression */   return 0; /* missing expression */
284   if (n == LPAREN) {   if (n == LPAREN) {
285   if ((nn = t_lex(*++t_wp)) == RPAREN)   if ((nn = t_lex(++t_wp)) == RPAREN)
286   return 0; /* missing expression */   return 0; /* missing expression */
287   res = oexpr(nn);   res = oexpr(nn);
288   if (t_lex(*++t_wp) != RPAREN)   if (t_lex(++t_wp) != RPAREN)
289   syntax(NULL, "closing paren expected");   syntax(NULL, "closing paren expected");
290   return res;   return res;
291   }   }
# Line 243  primary(enum token n) Line 300  primary(enum token n)
300   return strlen(*t_wp) != 0;   return strlen(*t_wp) != 0;
301   case FILTT:   case FILTT:
302   return isatty(getn(*t_wp));   return isatty(getn(*t_wp));
303    #ifdef HAVE_FACCESSAT
304     case FILRD:
305     return test_file_access(*t_wp, R_OK);
306     case FILWR:
307     return test_file_access(*t_wp, W_OK);
308     case FILEX:
309     return test_file_access(*t_wp, X_OK);
310    #endif
311   default:   default:
312   return filstat(*t_wp, n);   return filstat(*t_wp, n);
313   }   }
314   }   }
315    
316   if (t_lex(t_wp[1]), t_wp_op && t_wp_op->op_type == BINOP) {   if (t_lex(t_wp + 1), t_wp_op && t_wp_op->op_type == BINOP) {
317   return binop();   return binop();
318   }   }
319    
# Line 262  binop(void) Line 327  binop(void)
327   struct t_op const *op;   struct t_op const *op;
328    
329   opnd1 = *t_wp;   opnd1 = *t_wp;
330   (void) t_lex(*++t_wp);   (void) t_lex(++t_wp);
331   op = t_wp_op;   op = t_wp_op;
332    
333   if ((opnd2 = *++t_wp) == (char *)0)   if ((opnd2 = *++t_wp) == (char *)0)
# Line 312  filstat(char *nm, enum token mode) Line 377  filstat(char *nm, enum token mode)
377   return 0;   return 0;
378    
379   switch (mode) {   switch (mode) {
380    #ifndef HAVE_FACCESSAT
381   case FILRD:   case FILRD:
382   return test_st_mode(&s, R_OK);   return test_st_mode(&s, R_OK);
383   case FILWR:   case FILWR:
384   return test_st_mode(&s, W_OK);   return test_st_mode(&s, W_OK);
385   case FILEX:   case FILEX:
386   return test_st_mode(&s, X_OK);   return test_st_mode(&s, X_OK);
387    #endif
388   case FILEXIST:   case FILEXIST:
389   return 1;   return 1;
390   case FILREG:   case FILREG:
# Line 351  filstat(char *nm, enum token mode) Line 418  filstat(char *nm, enum token mode)
418   }   }
419  }  }
420    
421  static enum token  static enum token t_lex(char **tp)
 t_lex(char *s)  
422  {  {
423   struct t_op const *op;   struct t_op const *op;
424     char *s = *tp;
  op = ops;  
425    
426   if (s == 0) {   if (s == 0) {
427   t_wp_op = (struct t_op *)0;   t_wp_op = (struct t_op *)0;
428   return EOI;   return EOI;
429   }   }
430   while (op->op_text) {  
431   if (strcmp(s, op->op_text) == 0) {   op = getop(s);
432   if ((op->op_type == UNOP && isoperand()) ||   if (op && !(op->op_type == UNOP && isoperand(tp)) &&
433      (op->op_num == LPAREN && *(t_wp+1) == 0))      !(op->op_num == LPAREN && !tp[1])) {
434   break;   t_wp_op = op;
435   t_wp_op = op;   return op->op_num;
  return op->op_num;  
  }  
  op++;  
436   }   }
437    
438   t_wp_op = (struct t_op *)0;   t_wp_op = (struct t_op *)0;
439   return OPERAND;   return OPERAND;
440  }  }
441    
442  static int  static int isoperand(char **tp)
 isoperand(void)  
443  {  {
444   struct t_op const *op;   struct t_op const *op;
445   char *s, *t;   char *s;
446    
447   op = ops;   if (!(s = tp[1]))
  if ((s  = *(t_wp+1)) == 0)  
448   return 1;   return 1;
449   if ((t = *(t_wp+2)) == 0)   if (!tp[2])
450   return 0;   return 0;
  while (op->op_text) {  
  if (strcmp(s, op->op_text) == 0)  
      return op->op_type == BINOP &&  
         (t[0] != ')' || t[1] != '\0');  
  op++;  
  }  
  return 0;  
 }  
   
 /* atoi with error detection */  
 static int  
 getn(const char *s)  
 {  
  char *p;  
  long r;  
   
  errno = 0;  
  r = strtol(s, &p, 10);  
451    
452   if (errno != 0)   op = getop(s);
453        error("%s: out of range", s);   return op && op->op_type == BINOP;
   
  while (isspace((unsigned char)*p))  
       p++;  
   
  if (*p)  
       error("%s: bad number", s);  
   
  return (int) r;  
454  }  }
455    
456  static int  static int
# Line 449  equalf (const char *f1, const char *f2) Line 484  equalf (const char *f1, const char *f2)
484   b1.st_ino == b2.st_ino);   b1.st_ino == b2.st_ino);
485  }  }
486    
487    #ifdef HAVE_FACCESSAT
488    static int test_file_access(const char *path, int mode)
489    {
490     return !faccessat(AT_FDCWD, path, mode, AT_EACCESS);
491    }
492    #else /* HAVE_FACCESSAT */
493  /*  /*
494   * Similar to what access(2) does, but uses the effective uid and gid.   * Similar to what access(2) does, but uses the effective uid and gid.
495   * Doesn't make the mistake of telling root that any file is executable.   * Doesn't make the mistake of telling root that any file is executable.
# Line 499  bash_group_member(gid_t gid) Line 540  bash_group_member(gid_t gid)
540    
541   return (0);   return (0);
542  }  }
543    #endif /* HAVE_FACCESSAT */

Legend:
Removed from v.1121  
changed lines
  Added in v.1122