summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org>2018-11-15 07:58:01 (GMT)
committer Sergey Poznyakoff <gray@gnu.org>2018-11-15 07:58:01 (GMT)
commit6e4ef4c272a23ffde227689bc4e65a0523f18b4d (patch) (side-by-side diff)
tree9c47e8915e0a11ff5df86ee7849cbc54eeff3882
parent82a4e4b019194d60080c1b9f34de841485f3b9e3 (diff)
downloadgrecs-6e4ef4c272a23ffde227689bc4e65a0523f18b4d.tar.gz
grecs-6e4ef4c272a23ffde227689bc4e65a0523f18b4d.tar.bz2
Port mailutils commit 2c2e3c50d6
* include/wordsplit.h (WRDSO_ARGV): Remove. * src/wordsplit.c (expcmd): Always split command line into arguments. This fixes https://savannah.gnu.org/bugs/?54830 * tests/wsp.c: Implement internal commands, instead of calling shell ones. This fixes https://savannah.gnu.org/bugs/?54829. * tests/wordsplit.at: Rewrite command expansion tests.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--include/wordsplit.h8
-rw-r--r--src/wordsplit.c20
-rw-r--r--tests/wordsplit.at138
-rw-r--r--tests/wsp.c131
4 files changed, 122 insertions, 175 deletions
diff --git a/include/wordsplit.h b/include/wordsplit.h
index 7229df3..1a047f7 100644
--- a/include/wordsplit.h
+++ b/include/wordsplit.h
@@ -88,9 +88,8 @@ struct wordsplit
void *clos);
/* [Input] (!WRDSF_NOCMD) Returns in the memory
location pointed to by RET the expansion of
- the command CMD (LEN bytes long). If WRDSO_ARGV
- option is set, ARGV contains CMD split out to
- words. Otherwise ARGV is NULL.
+ the command CMD (LEN bytes long). On input,
+ ARGV contains CMD split out to words.
See ws_getvar for a discussion of possible
return values. */
@@ -196,9 +195,10 @@ struct wordsplit
#define WRDSO_FAILGLOB 0x00000002
/* Allow a leading period to be matched by metacharacters. */
#define WRDSO_DOTGLOB 0x00000004
-/* ws_command needs argv parameter */
+#if 0 /* Unused value */
#define WRDSO_ARGV 0x00000008
/* Keep backslash in unrecognized escape sequences in words */
+#endif
#define WRDSO_BSKEEP_WORD 0x00000010
/* Handle octal escapes in words */
#define WRDSO_OESC_WORD 0x00000020
diff --git a/src/wordsplit.c b/src/wordsplit.c
index b4baeb3..bad59b1 100644
--- a/src/wordsplit.c
+++ b/src/wordsplit.c
@@ -1527,6 +1527,7 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len,
size_t j;
char *value;
struct wordsplit_node *newnode;
+ struct wordsplit ws;
str++;
len--;
@@ -1538,22 +1539,15 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len,
}
*pend = str + j;
- if (wsp->ws_options & WRDSO_ARGV)
+ rc = _wsplt_subsplit (wsp, &ws, str, j, WRDSF_WS | WRDSF_QUOTE, 1);
+ if (rc)
{
- struct wordsplit ws;
-
- rc = _wsplt_subsplit (wsp, &ws, str, j, WRDSF_WS | WRDSF_QUOTE, 1);
- if (rc)
- {
- _wsplt_seterr_sub (wsp, &ws);
- wordsplit_free (&ws);
- return 1;
- }
- rc = wsp->ws_command (&value, str, j, ws.ws_wordv, wsp->ws_closure);
+ _wsplt_seterr_sub (wsp, &ws);
wordsplit_free (&ws);
+ return 1;
}
- else
- rc = wsp->ws_command (&value, str, j, NULL, wsp->ws_closure);
+ rc = wsp->ws_command (&value, str, j, ws.ws_wordv, wsp->ws_closure);
+ wordsplit_free (&ws);
if (rc == WRDSE_NOSPACE)
return _wsplt_nomem (wsp);
diff --git a/tests/wordsplit.at b/tests/wordsplit.at
index 75dde85..631d939 100644
--- a/tests/wordsplit.at
+++ b/tests/wordsplit.at
@@ -711,142 +711,70 @@ TOTAL: 1
],
[input exhausted
])
-
-dnl Something that doesn't fit into TESTWSP
-
-AT_SETUP([simple command substitution])
-AT_KEYWORDS([wordsplit wsp wsp-cmd wsp-cmd-1])
-AT_CHECK([
-mkdir dir
-> dir/file
-
-wsp -nocmd <<'EOT'
-begin $(find dir) end
-EOT
-],
-[0],
+
+TESTWSP([simple command substitution],[],[-nocmd],
+[begin $(words a b) end],
[NF: 4
0: begin
-1: dir
-2: dir/file
+1: a
+2: b
3: end
TOTAL: 4
])
-AT_CLEANUP
-AT_SETUP([quoted command substitution])
-AT_KEYWORDS([wordsplit wsp wsp-cmd wsp-cmd-2])
-AT_CHECK([
-mkdir dir
-> dir/file
-
-wsp -nocmd <<'EOT'
-begin "$(find dir)" end
-EOT
-],
-[0],
+TESTWSP([quoted command substitution],[],[-nocmd],
+[begin "$(words a b)" end],
[NF: 3
0: begin
-1: "dir dir/file"
+1: "a b"
2: end
TOTAL: 3
])
-AT_CLEANUP
-
-AT_SETUP([coalesced command substitution])
-AT_KEYWORDS([wordsplit wsp wsp-cmd wsp-cmd-3])
-AT_CHECK([
-mkdir dir
-> dir/file
-wsp -nocmd <<'EOT'
-begin($(find dir))end
-EOT
-],
-[0],
+TESTWSP([coalesced command substitution],[],[-nocmd],
+[begin($(words a b))end],
[NF: 2
-0: begin(dir
-1: dir/file)end
+0: begin(a
+1: b)end
TOTAL: 2
])
-AT_CLEANUP
-AT_SETUP([quoted coalesced command substitution])
-AT_KEYWORDS([wordsplit wsp wsp-cmd wsp-cmd-4])
-AT_CHECK([
-mkdir dir
-> dir/file
-
-wsp -nocmd <<'EOT'
-"begin($(find dir))end"
-EOT
-],
-[0],
+TESTWSP([quoted coalesced command substitution],[],[-nocmd],
+["begin($(words a b))end"],
[NF: 1
-0: "begin(dir dir/file)end"
+0: "begin(a b)end"
TOTAL: 1
])
-AT_CLEANUP
-
-AT_SETUP([variable and command substitution])
-AT_KEYWORDS([wordsplit wsp wsp-var wsp-var24 wsp-cmd wsp-cmd-5])
-AT_CHECK([
-mkdir dir
-> dir/file
-DIR=dir wsp -nocmd -novar<<'EOT'
-begin $DIR $(find $DIR) end
-EOT
-],
-[0],
+TESTWSP([variable and command substitution],[],[-nocmd -novar],
+[begin $X $(words $X $Y) end],
[NF: 5
0: begin
-1: dir
-2: dir
-3: dir/file
+1: a
+2: a
+3: b
4: end
TOTAL: 5
-])
-AT_CLEANUP
+],[],[X=a Y=b])
-AT_SETUP([variable expansion and command substitution in quotes])
-AT_KEYWORDS([wordsplit wsp wsp-var wsp-var25 wsp-cmd wsp-cmd-6])
-AT_CHECK([
-mkdir dir
-> dir/file
-
-DIR=dir BEGIN=begin wsp -nocmd -novar<<'EOT'
-"${BEGIN}($(find $DIR))end"
-EOT
-],
-[0],
+TESTWSP([variable expansion and command substitution in quotes],[],[-nocmd -novar],
+["${BEGIN}($(words $X $Y))end"],
[NF: 1
-0: "begin(dir dir/file)end"
+0: "begin(a b)end"
TOTAL: 1
-])
-AT_CLEANUP
-
-AT_SETUP([nested commands])
-AT_KEYWORDS([wordsplit wsp wsp-cmd])
-AT_CHECK([
-AT_DATA([input],[foo
-bar
-baz
-])
-SUFFIX=put wsp -nocmd -novar <<'EOT'
-$(echo output $(cat in$SUFFIX))
-EOT
-],
-[0],
+],[],[X=a Y=b BEGIN=begin])
+
+TESTWSP([nested commands],[],[-nocmd -novar],
+[$(words output $(words in$SUFFIX text) end)],
[NF: 4
0: output
-1: foo
-2: bar
-3: baz
+1: input
+2: text
+3: end
TOTAL: 4
-])
-AT_CLEANUP
+],[],[SUFFIX=put])
+dnl Something that doesn't fit into TESTWSP
AT_SETUP([pathname expansion])
AT_KEYWORDS([wordsplit wsp wsp-path wsp-path-1])
AT_CHECK([
diff --git a/tests/wsp.c b/tests/wsp.c
index a96fb7f..cca3a36 100644
--- a/tests/wsp.c
+++ b/tests/wsp.c
@@ -201,72 +201,97 @@ wsp_getvar (char **ret, const char *vptr, size_t vlen, void *data)
}
return WRDSE_UNDEF;
}
-
+
static int
-wsp_runcmd (char **ret, const char *str, size_t len, char **argv, void *closure)
+cmd_quote (char **ret, const char *str, size_t len, char **argv)
{
- FILE *fp;
- char *cmd;
- int c, lastc;
- char *buffer = NULL;
- size_t bufsize = 0;
- size_t buflen = 0;
+ int alen;
+ for (alen = 0; alen < len && !(str[alen] == ' ' || str[alen] == '\t'); alen++)
+ ;
+ for (; alen < len && (str[alen] == ' ' || str[alen] == '\t'); alen++)
+ ;
+ len -= alen;
+ *ret = malloc (len + 1);
+ if (!*ret)
+ return WRDSE_NOSPACE;
+ memcpy (*ret, str + alen, len);
+ (*ret)[len] = 0;
+ return WRDSE_OK;
+}
+
+static int
+cmd_words (char **ret, const char *str, size_t len, char **argv)
+{
+ char *p;
+ int i;
- cmd = malloc (len + 1);
- if (!cmd)
+ p = malloc (len + 1);
+ if (!p)
return WRDSE_NOSPACE;
- memcpy (cmd, str, len);
- cmd[len] = 0;
-
- fp = popen(cmd, "r");
- if (!fp)
+ *ret = p;
+ for (i = 1; argv[i]; i++)
{
- size_t size = 0;
- ret = NULL;
- if (grecs_asprintf (ret, &size, "can't run %s: %s",
- cmd, strerror (errno)))
- return WRDSE_NOSPACE;
- else
- return WRDSE_USERERR;
+ size_t s = strlen (argv[i]);
+ if (i > 1)
+ *p++ = ' ';
+ memcpy (p, argv[i], s);
+ p += s;
}
+ *p = 0;
+ return WRDSE_OK;
+}
- while ((c = fgetc (fp)) != EOF)
+static int
+cmd_lines (char **ret, const char *str, size_t len, char **argv)
+{
+ char *p;
+ int i;
+
+ p = malloc (len + 1);
+ if (!p)
+ return WRDSE_NOSPACE;
+ *ret = p;
+ for (i = 1; argv[i]; i++)
{
- lastc = c;
- if (c == '\n')
- c = ' ';
- if (buflen == bufsize)
- {
- char *p;
-
- if (bufsize == 0)
- bufsize = 80;
- else
- bufsize *= 2;
- p = realloc (buffer, bufsize);
- if (!p)
- {
- free (buffer);
- free (cmd);
- return WRDSE_NOSPACE;
- }
- buffer = p;
- }
- buffer[buflen++] = c;
+ size_t s = strlen (argv[i]);
+ if (i > 1)
+ *p++ = '\n';
+ memcpy (p, argv[i], s);
+ p += s;
}
+ *p = 0;
+ return WRDSE_OK;
+}
+
+static struct command
+{
+ char const *name;
+ int (*cmd)(char **ret, const char *str, size_t len, char **argv);
+} comtab[] = {
+ { "quote", cmd_quote },
+ { "words", cmd_words },
+ { "lines", cmd_lines }
+};
- if (buffer)
+static int
+wsp_runcmd (char **ret, const char *str, size_t len, char **argv, void *closure)
+{
+ int i;
+ size_t s = 0;
+
+ for (i = 0; ; i++)
{
- if (lastc == '\n')
- --buflen;
- buffer[buflen] = 0;
+ if (i == sizeof (comtab) / sizeof (comtab[0]))
+ break;
+ if (strcmp (comtab[i].name, argv[0]) == 0)
+ return comtab[i].cmd (ret, str, len, argv);
}
-
- pclose (fp);
- free (cmd);
- *ret = buffer;
- return WRDSE_OK;
+ *ret = NULL;
+ if (grecs_asprintf (ret, &s, "unknown command: %s", argv[0]))
+ return WRDSE_NOSPACE;
+ else
+ return WRDSE_USERERR;
}
enum env_type

Return to:

Send suggestions and report system problems to the System administrator.