aboutsummaryrefslogtreecommitdiff
path: root/lib/wildmatch.c
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2019-06-02 07:40:11 +0300
committerSergey Poznyakoff <gray@gnu.org>2019-06-02 08:03:16 +0300
commitcc298a11a131b162f291d6ee27ba1d7598a1b6c4 (patch)
tree4d82a9a5da05fbfdce0c9bf03e605ecf00baa07a /lib/wildmatch.c
parent1f28935841a69aa8be7eb2e88f580df9c95206d2 (diff)
downloadpies-cc298a11a131b162f291d6ee27ba1d7598a1b6c4.tar.gz
pies-cc298a11a131b162f291d6ee27ba1d7598a1b6c4.tar.bz2
New configuration statement for manipulating the environment.
The "env" statement is now a compound statement. It can contain four substatements: "clear" to clear the environment, "keep" to retain certain variable while clearing it, "set" to set a variable, and "unset" to unset a variable or variables. Both "keep" and "unset" can take globbing pattern as their argument, in which case they affect all variable matching that pattern. The value part in the "set" statement is subject to variable expansion, e.g. set "MANPATH=$MANPATH${MANPATH:+:}/usr/local/man" The support for the old one-line syntax of "env" is retained for backward compatibility. This commit also fixes redirection to a file: new data are appended to the file, instead of overwriting it. * lib/Makefile.am: Add new files. * lib/envop.c: New file. * lib/envop.h: New file. * lib/wildmatch.c: New file. * src/comp.c (component_free): Update. * src/pies.c (argv_free): New function. (parse_legacy_env): New function. (_cb_env): Remove. (cb_env_section_parser): New function. (cb_env_keywords): New keywords for the "env" block statement: clear, keep, set, unset. (component_keywords): New compount statement: env. Old usage retained for backward compatibility. * src/pies.h: Include "envop.h" (component)<env>: Remove. <envop>: New field. * src/prog.h (prog)<env>: New field. * src/progman.c (redirect_to_file): Position to the end of file. (DEBUG_ENVIRON): Remove macro. (debug_environ): New function. (environ_setup): Remove. (prog_sockenv): Use environ_set to modify local copy of environment. (prog_start_prologue): Use environ_create + envop_exec to create and modify the environment. (prog_execute): Set environment to prog-local copy. * tests/.gitignore: Build envtest * tests/Makefile.am: Add new tests. * tests/testsuite.at: Add environment tests. * tests/envop.at: New file. * tests/envtest.c: New file. * tests/env.at: New file. * tests/redirect.at: Check first two lines of the output file.
Diffstat (limited to 'lib/wildmatch.c')
-rw-r--r--lib/wildmatch.c140
1 files changed, 140 insertions, 0 deletions
diff --git a/lib/wildmatch.c b/lib/wildmatch.c
new file mode 100644
index 0000000..2b4d7c8
--- /dev/null
+++ b/lib/wildmatch.c
@@ -0,0 +1,140 @@
+/* Environment-specific globbing pattern matching for GNU Pies.
+ Copyright (C) 2019 Sergey Poznyakoff
+
+ GNU Pies is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GNU Pies is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Pies. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdlib.h>
+
+enum
+ {
+ WILD_FALSE = 0,
+ WILD_TRUE,
+ WILD_ABORT
+ };
+
+static int
+match_char_class (char const **pexpr, char c)
+{
+ int res;
+ int rc;
+ char const *expr = *pexpr;
+
+ expr++;
+ if (*expr == '^')
+ {
+ res = 0;
+ expr++;
+ }
+ else
+ res = 1;
+
+ if (*expr == '-' || *expr == ']')
+ rc = c == *expr++;
+ else
+ rc = !res;
+
+ for (; *expr && *expr != ']'; expr++)
+ {
+ if (rc == res)
+ {
+ if (*expr == '\\' && expr[1] == ']')
+ expr++;
+ }
+ else if (expr[1] == '-')
+ {
+ if (*expr == '\\')
+ rc = *++expr == c;
+ else
+ {
+ rc = *expr <= c && c <= expr[2];
+ expr += 2;
+ }
+ }
+ else if (*expr == '\\' && expr[1] == ']')
+ rc = *++expr == c;
+ else
+ rc = *expr == c;
+ }
+ *pexpr = *expr ? expr + 1 : expr;
+ return rc == res;
+}
+
+#define END_OF_NAME(s,l) ((l) == 0 || *(s) == 0)
+#define NEXT_CHAR(s,l) (s++, l--)
+
+int
+wilder_match (char const *expr, char const *name, size_t len)
+{
+ int c;
+
+ while (expr && *expr)
+ {
+ if (END_OF_NAME (name, len) && *expr != '*')
+ return WILD_ABORT;
+ switch (*expr)
+ {
+ case '*':
+ while (*++expr == '*')
+ ;
+ if (*expr == 0)
+ return WILD_TRUE;
+ while (!END_OF_NAME (name, len))
+ {
+ int res = wilder_match (expr, name, len);
+ if (res != WILD_FALSE)
+ return res;
+ NEXT_CHAR (name, len);
+ }
+ return WILD_ABORT;
+
+ case '?':
+ expr++;
+ NEXT_CHAR (name, len);
+ break;
+
+ case '[':
+ if (!match_char_class (&expr, *name))
+ return WILD_FALSE;
+ NEXT_CHAR (name, len);
+ break;
+
+ case '\\':
+ if (expr[1])
+ {
+ c = *++expr; expr++;
+ if (*name != wordsplit_c_unquote_char (c))
+ return WILD_FALSE;
+ NEXT_CHAR (name, len);
+ break;
+ }
+ /* fall through */
+ default:
+ if (*expr != *name)
+ return WILD_FALSE;
+ expr++;
+ NEXT_CHAR (name, len);
+ }
+ }
+ return END_OF_NAME (name, len) ? WILD_TRUE : WILD_FALSE;
+}
+
+/* Return 0 if first LEN bytes of NAME match globbing pattern EXPR. */
+int
+wildmatch (char const *expr, char const *name, size_t len)
+{
+ return wilder_match (expr, name, len) != WILD_TRUE;
+}

Return to:

Send suggestions and report system problems to the System administrator.