📄 test.c
字号:
}static intbinary_operator (){ int value; char *w; w = argv[pos + 1]; if ((w[0] == '=' && (w[1] == '\0' || (w[1] == '=' && w[2] == '\0'))) || /* =, == */ ((w[0] == '>' || w[0] == '<') && w[1] == '\0') || /* <, > */ (w[0] == '!' && w[1] == '=' && w[2] == '\0')) /* != */ { value = binary_test (w, argv[pos], argv[pos + 2], 0); pos += 3; return (value); }#if defined (PATTERN_MATCHING) if ((w[0] == '=' || w[0] == '!') && w[1] == '~' && w[2] == '\0') { value = patcomp (argv[pos], argv[pos + 2], w[0] == '=' ? EQ : NE); pos += 3; return (value); }#endif if ((w[0] != '-' || w[3] != '\0') || test_binop (w) == 0) { test_syntax_error (_("%s: binary operator expected"), w); /* NOTREACHED */ return (FALSE); } value = binary_test (w, argv[pos], argv[pos + 2], 0); pos += 3; return value;}static intunary_operator (){ char *op; intmax_t r; op = argv[pos]; if (test_unop (op) == 0) return (FALSE); /* the only tricky case is `-t', which may or may not take an argument. */ if (op[1] == 't') { advance (0); if (pos < argc) { if (legal_number (argv[pos], &r)) { advance (0); return (unary_test (op, argv[pos - 1])); } else return (FALSE); } else return (unary_test (op, "1")); } /* All of the unary operators take an argument, so we first call unary_advance (), which checks to make sure that there is an argument, and then advances pos right past it. This means that pos - 1 is the location of the argument. */ unary_advance (); return (unary_test (op, argv[pos - 1]));}intunary_test (op, arg) char *op, *arg;{ intmax_t r; struct stat stat_buf; SHELL_VAR *v; switch (op[1]) { case 'a': /* file exists in the file system? */ case 'e': return (sh_stat (arg, &stat_buf) == 0); case 'r': /* file is readable? */ return (sh_eaccess (arg, R_OK) == 0); case 'w': /* File is writeable? */ return (sh_eaccess (arg, W_OK) == 0); case 'x': /* File is executable? */ return (sh_eaccess (arg, X_OK) == 0); case 'O': /* File is owned by you? */ return (sh_stat (arg, &stat_buf) == 0 && (uid_t) current_user.euid == (uid_t) stat_buf.st_uid); case 'G': /* File is owned by your group? */ return (sh_stat (arg, &stat_buf) == 0 && (gid_t) current_user.egid == (gid_t) stat_buf.st_gid); case 'N': return (sh_stat (arg, &stat_buf) == 0 && stat_buf.st_atime <= stat_buf.st_mtime); case 'f': /* File is a file? */ if (sh_stat (arg, &stat_buf) < 0) return (FALSE); /* -f is true if the given file exists and is a regular file. */#if defined (S_IFMT) return (S_ISREG (stat_buf.st_mode) || (stat_buf.st_mode & S_IFMT) == 0);#else return (S_ISREG (stat_buf.st_mode));#endif /* !S_IFMT */ case 'd': /* File is a directory? */ return (sh_stat (arg, &stat_buf) == 0 && (S_ISDIR (stat_buf.st_mode))); case 's': /* File has something in it? */ return (sh_stat (arg, &stat_buf) == 0 && stat_buf.st_size > (off_t) 0); case 'S': /* File is a socket? */#if !defined (S_ISSOCK) return (FALSE);#else return (sh_stat (arg, &stat_buf) == 0 && S_ISSOCK (stat_buf.st_mode));#endif /* S_ISSOCK */ case 'c': /* File is character special? */ return (sh_stat (arg, &stat_buf) == 0 && S_ISCHR (stat_buf.st_mode)); case 'b': /* File is block special? */ return (sh_stat (arg, &stat_buf) == 0 && S_ISBLK (stat_buf.st_mode)); case 'p': /* File is a named pipe? */#ifndef S_ISFIFO return (FALSE);#else return (sh_stat (arg, &stat_buf) == 0 && S_ISFIFO (stat_buf.st_mode));#endif /* S_ISFIFO */ case 'L': /* Same as -h */ case 'h': /* File is a symbolic link? */#if !defined (S_ISLNK) || !defined (HAVE_LSTAT) return (FALSE);#else return ((arg[0] != '\0') && (lstat (arg, &stat_buf) == 0) && S_ISLNK (stat_buf.st_mode));#endif /* S_IFLNK && HAVE_LSTAT */ case 'u': /* File is setuid? */ return (sh_stat (arg, &stat_buf) == 0 && (stat_buf.st_mode & S_ISUID) != 0); case 'g': /* File is setgid? */ return (sh_stat (arg, &stat_buf) == 0 && (stat_buf.st_mode & S_ISGID) != 0); case 'k': /* File has sticky bit set? */#if !defined (S_ISVTX) /* This is not Posix, and is not defined on some Posix systems. */ return (FALSE);#else return (sh_stat (arg, &stat_buf) == 0 && (stat_buf.st_mode & S_ISVTX) != 0);#endif case 't': /* File fd is a terminal? */ if (legal_number (arg, &r) == 0) return (FALSE); return ((r == (int)r) && isatty ((int)r)); case 'n': /* True if arg has some length. */ return (arg[0] != '\0'); case 'z': /* True if arg has no length. */ return (arg[0] == '\0'); case 'o': /* True if option `arg' is set. */ return (minus_o_option_value (arg) == 1); case 'v': v = find_variable (arg); return (v && var_isset (v) ? TRUE : FALSE); } /* We can't actually get here, but this shuts up gcc. */ return (FALSE);}/* Return TRUE if OP is one of the test command's binary operators. */inttest_binop (op) char *op;{ if (op[0] == '=' && op[1] == '\0') return (1); /* '=' */ else if ((op[0] == '<' || op[0] == '>') && op[1] == '\0') /* string <, > */ return (1); else if ((op[0] == '=' || op[0] == '!') && op[1] == '=' && op[2] == '\0') return (1); /* `==' and `!=' */#if defined (PATTERN_MATCHING) else if (op[2] == '\0' && op[1] == '~' && (op[0] == '=' || op[0] == '!')) return (1);#endif else if (op[0] != '-' || op[2] == '\0' || op[3] != '\0') return (0); else { if (op[2] == 't') switch (op[1]) { case 'n': /* -nt */ case 'o': /* -ot */ case 'l': /* -lt */ case 'g': /* -gt */ return (1); default: return (0); } else if (op[1] == 'e') switch (op[2]) { case 'q': /* -eq */ case 'f': /* -ef */ return (1); default: return (0); } else if (op[2] == 'e') switch (op[1]) { case 'n': /* -ne */ case 'g': /* -ge */ case 'l': /* -le */ return (1); default: return (0); } else return (0); }}/* Return non-zero if OP is one of the test command's unary operators. */inttest_unop (op) char *op;{ if (op[0] != '-' || op[2] != 0) return (0); switch (op[1]) { case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'k': case 'n': case 'o': case 'p': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'z': case 'G': case 'L': case 'O': case 'S': case 'N': return (1); } return (0);}static inttwo_arguments (){ if (argv[pos][0] == '!' && argv[pos][1] == '\0') return (argv[pos + 1][0] == '\0'); else if (argv[pos][0] == '-' && argv[pos][2] == '\0') { if (test_unop (argv[pos])) return (unary_operator ()); else test_syntax_error (_("%s: unary operator expected"), argv[pos]); } else test_syntax_error (_("%s: unary operator expected"), argv[pos]); return (0);}#define ANDOR(s) (s[0] == '-' && !s[2] && (s[1] == 'a' || s[1] == 'o'))/* This could be augmented to handle `-t' as equivalent to `-t 1', but POSIX requires that `-t' be given an argument. */#define ONE_ARG_TEST(s) ((s)[0] != '\0')static intthree_arguments (){ int value; if (test_binop (argv[pos+1])) { value = binary_operator (); pos = argc; } else if (ANDOR (argv[pos+1])) { if (argv[pos+1][1] == 'a') value = ONE_ARG_TEST(argv[pos]) && ONE_ARG_TEST(argv[pos+2]); else value = ONE_ARG_TEST(argv[pos]) || ONE_ARG_TEST(argv[pos+2]); pos = argc; } else if (argv[pos][0] == '!' && argv[pos][1] == '\0') { advance (1); value = !two_arguments (); } else if (argv[pos][0] == '(' && argv[pos+2][0] == ')') { value = ONE_ARG_TEST(argv[pos+1]); pos = argc; } else test_syntax_error (_("%s: binary operator expected"), argv[pos+1]); return (value);}/* This is an implementation of a Posix.2 proposal by David Korn. */static intposixtest (){ int value; switch (argc - 1) /* one extra passed in */ { case 0: value = FALSE; pos = argc; break; case 1: value = ONE_ARG_TEST(argv[1]); pos = argc; break; case 2: value = two_arguments (); pos = argc; break; case 3: value = three_arguments (); break; case 4: if (argv[pos][0] == '!' && argv[pos][1] == '\0') { advance (1); value = !three_arguments (); break; } /* FALLTHROUGH */ default: value = expr (); } return (value);}/* * [: * '[' expr ']' * test: * test expr */inttest_command (margc, margv) int margc; char **margv;{ int value; int code; USE_VAR(margc); code = setjmp (test_exit_buf); if (code) return (test_error_return); argv = margv; if (margv[0] && margv[0][0] == '[' && margv[0][1] == '\0') { --margc; if (margv[margc] && (margv[margc][0] != ']' || margv[margc][1])) test_syntax_error (_("missing `]'"), (char *)NULL); if (margc < 2) test_exit (SHELL_BOOLEAN (FALSE)); } argc = margc; pos = 1; if (pos >= argc) test_exit (SHELL_BOOLEAN (FALSE)); noeval = 0; value = posixtest (); if (pos != argc) test_syntax_error (_("too many arguments"), (char *)NULL); test_exit (SHELL_BOOLEAN (value));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -