1 /* GNU test program (ksb and mjb) */
3 /* Modified to run with the GNU shell by bfox. */
5 /* Copyright (C) 1987-1999 Free Software Foundation, Inc.
7 This file is part of GNU Bash, the Bourne Again SHell.
9 Bash is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 2, or (at your option) any later
14 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software Foundation,
21 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23 /* Define TEST_STANDALONE to get the /bin/test version. Otherwise, you get
24 the shell builtin version. */
25 /* #define TEST_STANDALONE */
29 #include <sys/types.h>
31 /* The official name of this program (e.g., no `g' prefix). */
32 #define PROGRAM_NAME "test"
34 #define TEST_STANDALONE 1
36 #if !defined (TEST_STANDALONE)
38 # include "posixstat.h"
39 # include "filecntl.h"
40 #else /* TEST_STANDALONE */
42 # include "group-member.h"
44 # if !defined (S_IXUGO)
47 # if defined (_POSIX_VERSION)
49 # else /* !_POSIX_VERSION */
50 # include <sys/param.h>
51 # endif /* _POSIX_VERSION */
52 # define whitespace(c) (((c) == ' ') || ((c) == '\t'))
53 # define digit(c) ((c) >= '0' && (c) <= '9')
54 # define digit_value(c) ((c) - '0')
56 #endif /* TEST_STANDALONE */
58 #if !defined (_POSIX_VERSION)
59 # include <sys/file.h>
60 #endif /* !_POSIX_VERSION */
68 #define STREQ(a, b) ((a)[0] == (b)[0] && strcmp (a, b) == 0)
71 # define member(c, s) ((c) ? (strchr ((s), (c)) ? 1 : 0) : 0)
74 extern gid_t
getegid ();
75 extern uid_t
geteuid ();
84 /* This name is used solely when printing --version information. */
85 #define PROGRAM_NAME "test"
87 /* The following few defines control the truth and false output of each stage.
88 TRUE and FALSE are what we use to compute the final output value.
89 SHELL_BOOLEAN is the form which returns truth or falseness in shell terms.
90 TRUTH_OR is how to do logical or with TRUE and FALSE.
91 TRUTH_AND is how to do logical and with TRUE and FALSE..
92 Default is TRUE = 1, FALSE = 0, TRUTH_OR = a | b, TRUTH_AND = a & b,
93 SHELL_BOOLEAN = (!value). */
96 #define SHELL_BOOLEAN(value) (!(value))
97 #define TRUTH_OR(a, b) ((a) | (b))
98 #define TRUTH_AND(a, b) ((a) & (b))
100 #if defined (TEST_STANDALONE)
101 # define test_exit(val) exit (val)
103 static jmp_buf test_exit_buf
;
104 static int test_error_return
= 0;
105 # define test_exit(val) test_error_return = val, longjmp (test_exit_buf, 1)
106 #endif /* !TEST_STANDALONE */
108 static int pos
; /* The offset of the current argument in ARGV. */
109 static int argc
; /* The number of arguments present in ARGV. */
110 static char **argv
; /* The argument list. */
112 static int unop
PARAMS ((int op
));
113 static int binop
PARAMS ((char *s
));
114 static int unary_operator
PARAMS ((void));
115 static int binary_operator
PARAMS ((void));
116 static int two_arguments
PARAMS ((void));
117 static int three_arguments
PARAMS ((void));
118 static int posixtest
PARAMS ((void));
120 static int expr
PARAMS ((void));
121 static int term
PARAMS ((void));
122 static int and PARAMS ((void));
123 static int or PARAMS ((void));
125 #if __GNUC__ >= 2 && defined (__GNUC_MINOR__) \
126 && __GNUC_MINOR__ >= 5 && !defined (__STRICT_ANSI__)
127 # define NO_RETURN_ATTRIBUTE __attribute__ ((noreturn))
129 # define NO_RETURN_ATTRIBUTE /* empty */
132 static void test_syntax_error
PARAMS ((char *format
, char *arg
)) NO_RETURN_ATTRIBUTE
;
133 static void beyond
PARAMS ((void)) NO_RETURN_ATTRIBUTE
;
136 test_syntax_error (char *format
, char *arg
)
138 fprintf (stderr
, "%s: ", argv
[0]);
139 fprintf (stderr
, format
, arg
);
141 test_exit (SHELL_BOOLEAN (FALSE
));
144 /* A wrapper for stat () which disallows pathnames that are empty strings. */
146 test_stat (char *path
, struct stat
*finfo
)
153 return (stat (path
, finfo
));
156 /* Do the same thing access(2) does, but use the effective uid and gid,
157 and don't make the mistake of telling root that any file is executable.
158 But this loses when the containing filesystem is mounted e.g. read-only. */
160 eaccess (char *path
, int mode
)
163 static int euid
= -1;
165 if (test_stat (path
, &st
) < 0)
173 /* Root can read or write any file. */
177 /* Root can execute any file that has any one of the execute
179 if (st
.st_mode
& S_IXUGO
)
183 if (st
.st_uid
== euid
) /* owner */
185 else if (group_member (st
.st_gid
))
188 if (st
.st_mode
& mode
)
194 /* Increment our position in the argument list. Check that we're not
195 past the end of the argument list. This check is supressed if the
196 argument is FALSE. Made a macro for efficiency. */
201 if ((f) && pos >= argc) \
206 #if !defined (advance)
212 if (f
&& pos
>= argc
)
217 #define unary_advance() \
226 * beyond - call when we're beyond the end of the argument list (an
232 test_syntax_error (_("argument expected\n"), NULL
);
235 /* Syntax error for when an integer argument was expected, but
236 something else was found. */
238 integer_expected_error (char *pch
)
240 test_syntax_error (_("integer expression expected %s\n"), pch
);
243 /* Return nonzero if the characters pointed to by STRING constitute a
244 valid number. Stuff the converted number into RESULT if RESULT is
245 a non-null pointer to a long. */
247 isint (register char *string
, long int *result
)
258 /* Skip leading whitespace characters. */
259 while (whitespace (*string
))
265 /* We allow leading `-' or `+'. */
266 if (*string
== '-' || *string
== '+')
268 if (!digit (string
[1]))
277 while (digit (*string
))
280 value
= (value
* 10) + digit_value (*string
);
284 /* Skip trailing whitespace, if any. */
285 while (whitespace (*string
))
288 /* Error if not at end of string. */
301 /* Find the modification time of FILE, and stuff it into AGE, a pointer
302 to a long. Return nonzero if successful, else zero. */
304 age_of (char *filename
, long int *age
)
308 if (test_stat (filename
, &finfo
) < 0)
312 *age
= finfo
.st_mtime
;
318 * term - parse a term and return 1 or 0 depending on whether the term
319 * evaluates to true or false, respectively.
322 * '-'('h'|'d'|'f'|'r'|'s'|'w'|'c'|'b'|'p'|'u'|'g'|'k') filename
323 * '-'('L'|'x') filename
325 * '-'('z'|'n') string
327 * string ('!='|'=') string
328 * <int> '-'(eq|ne|le|lt|ge|gt) <int>
329 * file '-'(nt|ot|ef) file
333 * positive and negative integers
343 /* Deal with leading "not"'s. */
344 if ('!' == argv
[pos
][0] && '\000' == argv
[pos
][1])
347 while (pos
< argc
&& '!' == argv
[pos
][0] && '\000' == argv
[pos
][1])
353 return (value
^ (term ()));
356 /* A paren-bracketed argument. */
357 if (argv
[pos
][0] == '(' && !argv
[pos
][1])
362 test_syntax_error (_("')' expected\n"), NULL
);
364 if (argv
[pos
][0] != ')' || argv
[pos
][1])
365 test_syntax_error (_("')' expected, found %s\n"), argv
[pos
]);
367 return (TRUE
== (value
));
370 /* are there enough arguments left that this could be dyadic? */
371 if (((pos
+ 3 <= argc
) && binop (argv
[pos
+ 1])) ||
372 ((pos
+ 4 <= argc
&& STREQ (argv
[pos
], "-l") && binop (argv
[pos
+ 2]))))
373 value
= binary_operator ();
375 /* Might be a switch type argument */
376 else if ('-' == argv
[pos
][0] && argv
[pos
][1] && 0 == argv
[pos
][2])
378 if (unop (argv
[pos
][1]))
379 value
= unary_operator ();
381 test_syntax_error (_("%s: unary operator expected\n"), argv
[pos
]);
385 value
= (argv
[pos
][0] != '\0');
393 binary_operator (void)
396 struct stat stat_buf
, stat_spare
;
397 long int l
, r
, value
;
398 /* Are the left and right integer expressions of the form '-l string'? */
401 if (strcmp (argv
[pos
], "-l") == 0)
406 /* Make sure that OP is still a valid binary operator. */
407 if ((op
>= argc
- 1) || (binop (argv
[op
]) == 0))
408 test_syntax_error (_("%s: binary operator expected\n"), argv
[op
]);
418 if ((op
< argc
- 2) && (strcmp (argv
[op
+ 1], "-l") == 0))
426 if (argv
[op
][0] == '-')
428 /* check for eq, nt, and stuff */
435 if (argv
[op
][2] == 't' && !argv
[op
][3])
439 l
= strlen (argv
[op
- 1]);
442 if (!isint (argv
[op
- 1], &l
))
443 integer_expected_error (_("before -lt"));
447 r
= strlen (argv
[op
+ 2]);
450 if (!isint (argv
[op
+ 1], &r
))
451 integer_expected_error (_("after -lt"));
454 return (TRUE
== (l
< r
));
457 if (argv
[op
][2] == 'e' && !argv
[op
][3])
461 l
= strlen (argv
[op
- 1]);
464 if (!isint (argv
[op
- 1], &l
))
465 integer_expected_error (_("before -le"));
468 r
= strlen (argv
[op
+ 2]);
471 if (!isint (argv
[op
+ 1], &r
))
472 integer_expected_error (_("after -le"));
475 return (TRUE
== (l
<= r
));
480 if (argv
[op
][2] == 't' && !argv
[op
][3])
482 /* gt integer greater than */
484 l
= strlen (argv
[op
- 1]);
487 if (!isint (argv
[op
- 1], &l
))
488 integer_expected_error (_("before -gt"));
491 r
= strlen (argv
[op
+ 2]);
494 if (!isint (argv
[op
+ 1], &r
))
495 integer_expected_error (_("after -gt"));
498 return (TRUE
== (l
> r
));
501 if (argv
[op
][2] == 'e' && !argv
[op
][3])
503 /* ge - integer greater than or equal to */
505 l
= strlen (argv
[op
- 1]);
508 if (!isint (argv
[op
- 1], &l
))
509 integer_expected_error (_("before -ge"));
512 r
= strlen (argv
[op
+ 2]);
515 if (!isint (argv
[op
+ 1], &r
))
516 integer_expected_error (_("after -ge"));
519 return (TRUE
== (l
>= r
));
524 if (argv
[op
][2] == 't' && !argv
[op
][3])
526 /* nt - newer than */
528 if (l_is_l
|| r_is_l
)
529 test_syntax_error (_("-nt does not accept -l\n"), NULL
);
530 if (age_of (argv
[op
- 1], &l
) && age_of (argv
[op
+ 1], &r
))
531 return (TRUE
== (l
> r
));
536 if (argv
[op
][2] == 'e' && !argv
[op
][3])
538 /* ne - integer not equal */
540 l
= strlen (argv
[op
- 1]);
543 if (!isint (argv
[op
- 1], &l
))
544 integer_expected_error (_("before -ne"));
547 r
= strlen (argv
[op
+ 2]);
550 if (!isint (argv
[op
+ 1], &r
))
551 integer_expected_error (_("after -ne"));
554 return (TRUE
== (l
!= r
));
559 if (argv
[op
][2] == 'q' && !argv
[op
][3])
561 /* eq - integer equal */
563 l
= strlen (argv
[op
- 1]);
566 if (!isint (argv
[op
- 1], &l
))
567 integer_expected_error (_("before -eq"));
570 r
= strlen (argv
[op
+ 2]);
573 if (!isint (argv
[op
+ 1], &r
))
574 integer_expected_error (_("after -eq"));
577 return (TRUE
== (l
== r
));
580 if (argv
[op
][2] == 'f' && !argv
[op
][3])
582 /* ef - hard link? */
584 if (l_is_l
|| r_is_l
)
585 test_syntax_error (_("-ef does not accept -l\n"), NULL
);
586 if (stat (argv
[op
- 1], &stat_buf
) < 0)
588 if (stat (argv
[op
+ 1], &stat_spare
) < 0)
591 (stat_buf
.st_dev
== stat_spare
.st_dev
&&
592 stat_buf
.st_ino
== stat_spare
.st_ino
));
597 if ('t' == argv
[op
][2] && '\000' == argv
[op
][3])
599 /* ot - older than */
601 if (l_is_l
|| r_is_l
)
602 test_syntax_error (_("-nt does not accept -l\n"), NULL
);
603 if (age_of (argv
[op
- 1], &l
) && age_of (argv
[op
+ 1], &r
))
604 return (TRUE
== (l
< r
));
609 test_syntax_error (_("unknown binary operator"), argv
[op
]);
612 if (argv
[op
][0] == '=' && !argv
[op
][1])
614 value
= (strcmp (argv
[pos
], argv
[pos
+ 2]) == 0);
616 return (TRUE
== value
);
619 if (strcmp (argv
[op
], "!=") == 0)
621 value
= (strcmp (argv
[pos
], argv
[pos
+ 2]) != 0);
623 return (TRUE
== value
);
631 unary_operator (void)
634 struct stat stat_buf
;
636 switch (argv
[pos
][1])
641 /* All of the following unary operators use unary_advance (), which
642 checks to make sure that there is an argument, and then advances
643 pos right past it. This means that pos - 1 is the location of the
646 case 'a': /* file exists in the file system? */
649 value
= -1 != test_stat (argv
[pos
- 1], &stat_buf
);
650 return (TRUE
== value
);
652 case 'r': /* file is readable? */
654 value
= -1 != eaccess (argv
[pos
- 1], R_OK
);
655 return (TRUE
== value
);
657 case 'w': /* File is writable? */
659 value
= -1 != eaccess (argv
[pos
- 1], W_OK
);
660 return (TRUE
== value
);
662 case 'x': /* File is executable? */
664 value
= -1 != eaccess (argv
[pos
- 1], X_OK
);
665 return (TRUE
== value
);
667 case 'O': /* File is owned by you? */
669 if (test_stat (argv
[pos
- 1], &stat_buf
) < 0)
672 return (TRUE
== (geteuid () == stat_buf
.st_uid
));
674 case 'G': /* File is owned by your group? */
676 if (test_stat (argv
[pos
- 1], &stat_buf
) < 0)
679 return (TRUE
== (getegid () == stat_buf
.st_gid
));
681 case 'f': /* File is a file? */
683 if (test_stat (argv
[pos
- 1], &stat_buf
) < 0)
686 /* Under POSIX, -f is true if the given file exists
687 and is a regular file. */
688 return (TRUE
== ((S_ISREG (stat_buf
.st_mode
)) ||
689 (0 == (stat_buf
.st_mode
& S_IFMT
))));
691 case 'd': /* File is a directory? */
693 if (test_stat (argv
[pos
- 1], &stat_buf
) < 0)
696 return (TRUE
== (S_ISDIR (stat_buf
.st_mode
)));
698 case 's': /* File has something in it? */
700 if (test_stat (argv
[pos
- 1], &stat_buf
) < 0)
703 return (TRUE
== (stat_buf
.st_size
> (off_t
) 0));
705 case 'S': /* File is a socket? */
706 #if !defined (S_ISSOCK)
711 if (test_stat (argv
[pos
- 1], &stat_buf
) < 0)
714 return (TRUE
== (S_ISSOCK (stat_buf
.st_mode
)));
715 #endif /* S_ISSOCK */
717 case 'c': /* File is character special? */
719 if (test_stat (argv
[pos
- 1], &stat_buf
) < 0)
722 return (TRUE
== (S_ISCHR (stat_buf
.st_mode
)));
724 case 'b': /* File is block special? */
726 if (test_stat (argv
[pos
- 1], &stat_buf
) < 0)
729 return (TRUE
== (S_ISBLK (stat_buf
.st_mode
)));
731 case 'p': /* File is a named pipe? */
736 if (test_stat (argv
[pos
- 1], &stat_buf
) < 0)
738 return (TRUE
== (S_ISFIFO (stat_buf
.st_mode
)));
739 #endif /* S_ISFIFO */
741 case 'L': /* Same as -h */
744 case 'h': /* File is a symbolic link? */
749 /* An empty filename is not a valid pathname. */
750 if ((argv
[pos
- 1][0] == '\0') ||
751 (lstat (argv
[pos
- 1], &stat_buf
) < 0))
754 return (TRUE
== (S_ISLNK (stat_buf
.st_mode
)));
757 case 'u': /* File is setuid? */
762 if (test_stat (argv
[pos
- 1], &stat_buf
) < 0)
765 return (TRUE
== (0 != (stat_buf
.st_mode
& S_ISUID
)));
768 case 'g': /* File is setgid? */
773 if (test_stat (argv
[pos
- 1], &stat_buf
) < 0)
776 return (TRUE
== (0 != (stat_buf
.st_mode
& S_ISGID
)));
779 case 'k': /* File has sticky bit set? */
781 if (test_stat (argv
[pos
- 1], &stat_buf
) < 0)
784 /* This is not Posix, and is not defined on some Posix systems. */
787 return (TRUE
== (0 != (stat_buf
.st_mode
& S_ISVTX
)));
790 case 't': /* File (fd) is a terminal? */
794 if (!isint (argv
[pos
], &fd
))
795 integer_expected_error (_("after -t"));
802 return (TRUE
== (isatty ((int) fd
)));
804 case 'n': /* True if arg has some length. */
806 return (TRUE
== (argv
[pos
- 1][0] != 0));
808 case 'z': /* True if arg has no length. */
810 return (TRUE
== (argv
[pos
- 1][0] == '\0'));
825 while ((pos
< argc
) && strcmp (argv
[pos
], "-a") == 0)
828 value
= TRUTH_AND (value
, and ());
830 return (TRUE
== value
);
845 while ((pos
< argc
) && strcmp (argv
[pos
], "-o") == 0)
848 value
= TRUTH_OR (value
, or ());
851 return (TRUE
== value
);
864 return (FALSE
^ (or ())); /* Same with this. */
867 /* Return TRUE if S is one of the test command's binary operators. */
871 return ((STREQ (s
, "=")) || (STREQ (s
, "!=")) || (STREQ (s
, "-nt")) ||
872 (STREQ (s
, "-ot")) || (STREQ (s
, "-ef")) || (STREQ (s
, "-eq")) ||
873 (STREQ (s
, "-ne")) || (STREQ (s
, "-lt")) || (STREQ (s
, "-le")) ||
874 (STREQ (s
, "-gt")) || (STREQ (s
, "-ge")));
877 /* Return nonzero if OP is one of the test command's unary operators. */
881 return (member (op
, "abcdefgkLhprsStuwxOGnz"));
885 one_argument (const char *s
)
888 return (TRUE
== (isatty (1)));
890 return strlen (s
) != 0;
898 if (STREQ (argv
[pos
], "!"))
899 value
= ! one_argument (argv
[pos
+1]);
900 else if (argv
[pos
][0] == '-'
901 && argv
[pos
][1] != '\0'
902 && argv
[pos
][2] == '\0')
904 if (unop (argv
[pos
][1]))
905 value
= unary_operator ();
907 test_syntax_error (_("%s: unary operator expected\n"), argv
[pos
]);
915 three_arguments (void)
919 if (STREQ (argv
[pos
], "!"))
922 value
= !two_arguments ();
924 else if (binop (argv
[pos
+1]))
926 value
= binary_operator ();
929 else if ((STREQ (argv
[pos
+1], "-a")) || (STREQ (argv
[pos
+1], "-o")) ||
930 (argv
[pos
][0] == '('))
933 test_syntax_error (_("%s: binary operator expected\n"), argv
[pos
+1]);
937 /* This is an implementation of a Posix.2 proposal by David Korn. */
943 switch (argc
- 1) /* one extra passed in */
951 value
= one_argument (argv
[1]);
956 value
= two_arguments ();
961 value
= three_arguments ();
965 if (STREQ (argv
[pos
], "!"))
968 value
= !three_arguments ();
980 #if defined (TEST_STANDALONE)
981 # include "long-options.h"
987 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
992 Usage: %s EXPRESSION\n\
993 or: [ EXPRESSION ]\n\
996 program_name
, program_name
);
998 Exit with the status determined by EXPRESSION.\n\
1000 --help display this help and exit\n\
1001 --version output version information and exit\n\
1003 EXPRESSION is true or false and sets exit status. It is one of:\n\
1007 ( EXPRESSION ) EXPRESSION is true\n\
1008 ! EXPRESSION EXPRESSION is false\n\
1009 EXPRESSION1 -a EXPRESSION2 both EXPRESSION1 and EXPRESSION2 are true\n\
1010 EXPRESSION1 -o EXPRESSION2 either EXPRESSION1 or EXPRESSION2 is true\n\
1012 [-n] STRING the length of STRING is nonzero\n\
1013 -z STRING the length of STRING is zero\n\
1014 STRING1 = STRING2 the strings are equal\n\
1015 STRING1 != STRING2 the strings are not equal\n\
1017 INTEGER1 -eq INTEGER2 INTEGER1 is equal to INTEGER2\n\
1018 INTEGER1 -ge INTEGER2 INTEGER1 is greater than or equal to INTEGER2\n\
1019 INTEGER1 -gt INTEGER2 INTEGER1 is greater than INTEGER2\n\
1020 INTEGER1 -le INTEGER2 INTEGER1 is less than or equal to INTEGER2\n\
1021 INTEGER1 -lt INTEGER2 INTEGER1 is less than INTEGER2\n\
1022 INTEGER1 -ne INTEGER2 INTEGER1 is not equal to INTEGER2\n\
1026 FILE1 -ef FILE2 FILE1 and FILE2 have the same device and inode numbers\n\
1027 FILE1 -nt FILE2 FILE1 is newer (modification date) than FILE2\n\
1028 FILE1 -ot FILE2 FILE1 is older than FILE2\n\
1030 -b FILE FILE exists and is block special\n\
1031 -c FILE FILE exists and is character special\n\
1032 -d FILE FILE exists and is a directory\n\
1033 -e FILE FILE exists\n\
1034 -f FILE FILE exists and is a regular file\n\
1035 -g FILE FILE exists and is set-group-ID\n\
1036 -G FILE FILE exists and is owned by the effective group ID\n\
1037 -k FILE FILE exists and has its sticky bit set\n\
1038 -L FILE FILE exists and is a symbolic link\n\
1039 -O FILE FILE exists and is owned by the effective user ID\n\
1040 -p FILE FILE exists and is a named pipe\n\
1041 -r FILE FILE exists and is readable\n\
1042 -s FILE FILE exists and has a size greater than zero\n\
1043 -S FILE FILE exists and is a socket\n\
1044 -t [FD] file descriptor FD (stdout by default) is opened on a terminal\n\
1045 -u FILE FILE exists and its set-user-ID bit is set\n\
1046 -w FILE FILE exists and is writable\n\
1047 -x FILE FILE exists and is executable\n\
1051 Beware that parentheses need to be escaped (e.g., by backslashes) for shells.\n\
1052 INTEGER may also be -l STRING, which evaluates to the length of STRING.\n\
1054 puts (_("\nReport bugs to <bug-sh-utils@gnu.org>."));
1058 #endif /* TEST_STANDALONE */
1060 #if !defined (TEST_STANDALONE)
1061 # define main test_command
1064 #define AUTHORS "FIXME: ksb and mjb"
1073 main (int margc
, char **margv
)
1077 #if !defined (TEST_STANDALONE)
1080 code
= setjmp (test_exit_buf
);
1083 return (test_error_return
);
1084 #else /* TEST_STANDALONE */
1085 program_name
= margv
[0];
1086 setlocale (LC_ALL
, "");
1087 bindtextdomain (PACKAGE
, LOCALEDIR
);
1088 textdomain (PACKAGE
);
1089 #endif /* TEST_STANDALONE */
1093 if (margv
[0] && strcmp (margv
[0], "[") == 0)
1095 /* Don't recognize --help or --version if POSIXLY_CORRECT is set. */
1096 if (getenv ("POSIXLY_CORRECT") == NULL
)
1097 parse_long_options (argc
, argv
, PROGRAM_NAME
, GNU_PACKAGE
, VERSION
,
1103 test_exit (SHELL_BOOLEAN (FALSE
));
1105 if (margv
[margc
] && strcmp (margv
[margc
], "]") != 0)
1106 test_syntax_error (_("missing `]'\n"), NULL
);
1113 test_exit (SHELL_BOOLEAN (FALSE
));
1115 parse_long_options (argc
, argv
, PROGRAM_NAME
, GNU_PACKAGE
, VERSION
,
1117 value
= posixtest ();
1120 test_syntax_error (_("too many arguments\n"), NULL
);
1122 test_exit (SHELL_BOOLEAN (value
));