Port wordsplit from grecs 20616b88
The updated version supports tilde and pathname expansion, command substitution and standard shell-like replacement constructs in variable substitution, such as ${X:-V} etc. * include/mailutils/wordsplit.h: Update. * libmailutils/string/wordsplit.c: Update. * libmailutils/tests/wsp.c: Update. * libmailutils/tests/wordsplit.at: Update unescape test. * libmailutils/imapio/create.c (mu_imapio_create): Initialize ws_escape array. * libmailutils/mime/mimehdr.c (_mime_header_parse): Likewise. * libmailutils/tests/modmesg.c: Use mu_wordsplit with MU_WRDSF_NOSPLIT to run expansions on the string. * mu/shell.c (shell_prompt): Likewise.
Showing
8 changed files
with
328 additions
and
70 deletions
This diff is collapsed.
Click to expand it.
... | @@ -29,7 +29,10 @@ mu_imapio_create (mu_imapio_t *iop, mu_stream_t str, int server) | ... | @@ -29,7 +29,10 @@ mu_imapio_create (mu_imapio_t *iop, mu_stream_t str, int server) |
29 | io->_imap_stream = str; | 29 | io->_imap_stream = str; |
30 | mu_stream_ref (str); | 30 | mu_stream_ref (str); |
31 | io->_imap_ws.ws_delim = " \t()[]"; | 31 | io->_imap_ws.ws_delim = " \t()[]"; |
32 | io->_imap_ws.ws_escape = "\\\""; | 32 | io->_imap_ws.ws_escape[0] = NULL; |
33 | io->_imap_ws.ws_escape[1] = "\\\\\"\""; | ||
34 | MU_WRDSO_ESC_SET (&io->_imap_ws, 0, MU_WRDSO_BSKEEP); | ||
35 | MU_WRDSO_ESC_SET (&io->_imap_ws, 1, MU_WRDSO_BSKEEP); | ||
33 | io->_imap_ws_flags = MU_WRDSF_DELIM | | 36 | io->_imap_ws_flags = MU_WRDSF_DELIM | |
34 | MU_WRDSF_ESCAPE | | 37 | MU_WRDSF_ESCAPE | |
35 | MU_WRDSF_NOVAR | | 38 | MU_WRDSF_NOVAR | |
... | @@ -37,7 +40,8 @@ mu_imapio_create (mu_imapio_t *iop, mu_stream_t str, int server) | ... | @@ -37,7 +40,8 @@ mu_imapio_create (mu_imapio_t *iop, mu_stream_t str, int server) |
37 | MU_WRDSF_DQUOTE | | 40 | MU_WRDSF_DQUOTE | |
38 | MU_WRDSF_RETURN_DELIMS | | 41 | MU_WRDSF_RETURN_DELIMS | |
39 | MU_WRDSF_WS | | 42 | MU_WRDSF_WS | |
40 | MU_WRDSF_APPEND; | 43 | MU_WRDSF_APPEND | |
44 | MU_WRDSF_OPTIONS; | ||
41 | io->_imap_server = server; | 45 | io->_imap_server = server; |
42 | *iop = io; | 46 | *iop = io; |
43 | return 0; | 47 | return 0; | ... | ... |
... | @@ -293,12 +293,14 @@ _mime_header_parse (const char *text, char **pvalue, | ... | @@ -293,12 +293,14 @@ _mime_header_parse (const char *text, char **pvalue, |
293 | size_t i; | 293 | size_t i; |
294 | 294 | ||
295 | ws.ws_delim = " \t\r\n;"; | 295 | ws.ws_delim = " \t\r\n;"; |
296 | ws.ws_escape = "\\\""; | 296 | ws.ws_escape[0] = ws.ws_escape[1] = "\\\\\"\""; |
297 | MU_WRDSO_ESC_SET (&ws, 0, MU_WRDSO_BSKEEP); | ||
298 | MU_WRDSO_ESC_SET (&ws, 1, MU_WRDSO_BSKEEP); | ||
297 | if (mu_wordsplit (text, &ws, | 299 | if (mu_wordsplit (text, &ws, |
298 | MU_WRDSF_DELIM | MU_WRDSF_ESCAPE | | 300 | MU_WRDSF_DELIM | MU_WRDSF_ESCAPE | |
299 | MU_WRDSF_NOVAR | MU_WRDSF_NOCMD | | 301 | MU_WRDSF_NOVAR | MU_WRDSF_NOCMD | |
300 | MU_WRDSF_DQUOTE | MU_WRDSF_SQUEEZE_DELIMS | | 302 | MU_WRDSF_DQUOTE | MU_WRDSF_SQUEEZE_DELIMS | |
301 | MU_WRDSF_RETURN_DELIMS | MU_WRDSF_WS)) | 303 | MU_WRDSF_RETURN_DELIMS | MU_WRDSF_WS | MU_WRDSF_OPTIONS)) |
302 | { | 304 | { |
303 | mu_debug (MU_DEBCAT_MIME, MU_DEBUG_ERROR, | 305 | mu_debug (MU_DEBCAT_MIME, MU_DEBUG_ERROR, |
304 | (_("wordsplit: %s"), mu_wordsplit_strerror (&ws))); | 306 | (_("wordsplit: %s"), mu_wordsplit_strerror (&ws))); | ... | ... |
This diff is collapsed.
Click to expand it.
... | @@ -32,7 +32,6 @@ main (int argc, char **argv) | ... | @@ -32,7 +32,6 @@ main (int argc, char **argv) |
32 | mu_stream_t stream = NULL; | 32 | mu_stream_t stream = NULL; |
33 | mu_header_t hdr; | 33 | mu_header_t hdr; |
34 | mu_body_t body; | 34 | mu_body_t body; |
35 | char *buf = NULL; | ||
36 | 35 | ||
37 | mu_set_program_name (argv[0]); | 36 | mu_set_program_name (argv[0]); |
38 | 37 | ||
... | @@ -78,15 +77,20 @@ main (int argc, char **argv) | ... | @@ -78,15 +77,20 @@ main (int argc, char **argv) |
78 | } | 77 | } |
79 | else if (strcmp (argv[i], "-t") == 0) | 78 | else if (strcmp (argv[i], "-t") == 0) |
80 | { | 79 | { |
81 | size_t len; | 80 | mu_wordsplit_t ws; |
82 | i++; | 81 | i++; |
83 | assert (argv[i] != NULL); | 82 | assert (argv[i] != NULL); |
84 | len = strlen (argv[i]); | 83 | |
85 | buf = realloc (buf, len + 1); | 84 | if (mu_wordsplit (argv[i], &ws, |
86 | mu_wordsplit_c_unquote_copy (buf, argv[i], len); | 85 | MU_WRDSF_NOSPLIT | MU_WRDSF_DEFFLAGS)) |
87 | assert (buf != NULL); | 86 | { |
88 | assert (mu_stream_write (stream, buf, | 87 | mu_error ("mu_wordsplit: %s", mu_wordsplit_strerror (&ws)); |
89 | strlen (buf), NULL) == 0); | 88 | exit (1); |
89 | } | ||
90 | else | ||
91 | assert (mu_stream_write (stream, ws.ws_wordv[0], | ||
92 | strlen (ws.ws_wordv[0]), NULL) == 0); | ||
93 | mu_wordsplit_free (&ws); | ||
90 | } | 94 | } |
91 | else | 95 | else |
92 | mu_error ("ignoring unknown argument %s", argv[i]); | 96 | mu_error ("ignoring unknown argument %s", argv[i]); | ... | ... |
... | @@ -347,7 +347,7 @@ TESTWSP([suppress ws trimming within quotes],[], | ... | @@ -347,7 +347,7 @@ TESTWSP([suppress ws trimming within quotes],[], |
347 | 4: "formatfield=In message %{text}, " | 347 | 4: "formatfield=In message %{text}, " |
348 | ]) | 348 | ]) |
349 | 349 | ||
350 | TESTWSP([unescape],[],[-default novar nocmd quote escape '\"'], | 350 | TESTWSP([unescape],[],[-default novar nocmd quote escape :+:'\\""'], |
351 | [\Seen "quote \"" "bs \\"], | 351 | [\Seen "quote \"" "bs \\"], |
352 | [NF: 3 | 352 | [NF: 3 |
353 | 0: \\Seen | 353 | 0: \\Seen | ... | ... |
... | @@ -22,6 +22,7 @@ | ... | @@ -22,6 +22,7 @@ |
22 | #include <stdio.h> | 22 | #include <stdio.h> |
23 | #include <string.h> | 23 | #include <string.h> |
24 | #include <mailutils/wordsplit.h> | 24 | #include <mailutils/wordsplit.h> |
25 | #include <mailutils/alloc.h> | ||
25 | #include <mailutils/kwd.h> | 26 | #include <mailutils/kwd.h> |
26 | #include <mailutils/errno.h> | 27 | #include <mailutils/errno.h> |
27 | #include <mailutils/error.h> | 28 | #include <mailutils/error.h> |
... | @@ -29,6 +30,8 @@ | ... | @@ -29,6 +30,8 @@ |
29 | 30 | ||
30 | extern char **environ; | 31 | extern char **environ; |
31 | 32 | ||
33 | char *progname; | ||
34 | |||
32 | struct mu_kwd bool_keytab[] = { | 35 | struct mu_kwd bool_keytab[] = { |
33 | { "append", MU_WRDSF_APPEND }, | 36 | { "append", MU_WRDSF_APPEND }, |
34 | /*{ "reuse", MU_WRDSF_REUSE },*/ | 37 | /*{ "reuse", MU_WRDSF_REUSE },*/ |
... | @@ -50,6 +53,14 @@ struct mu_kwd bool_keytab[] = { | ... | @@ -50,6 +53,14 @@ struct mu_kwd bool_keytab[] = { |
50 | { "default", MU_WRDSF_DEFFLAGS }, | 53 | { "default", MU_WRDSF_DEFFLAGS }, |
51 | { "env_kv", MU_WRDSF_ENV_KV }, | 54 | { "env_kv", MU_WRDSF_ENV_KV }, |
52 | { "incremental", MU_WRDSF_INCREMENTAL }, | 55 | { "incremental", MU_WRDSF_INCREMENTAL }, |
56 | { "pathexpand", MU_WRDSF_PATHEXPAND }, | ||
57 | { NULL, 0 } | ||
58 | }; | ||
59 | |||
60 | struct mu_kwd opt_keytab[] = { | ||
61 | { "nullglob", MU_WRDSO_NULLGLOB }, | ||
62 | { "failglob", MU_WRDSO_FAILGLOB }, | ||
63 | { "dotglob", MU_WRDSO_DOTGLOB }, | ||
53 | { NULL, 0 } | 64 | { NULL, 0 } |
54 | }; | 65 | }; |
55 | 66 | ||
... | @@ -65,18 +76,27 @@ help () | ... | @@ -65,18 +76,27 @@ help () |
65 | { | 76 | { |
66 | size_t i; | 77 | size_t i; |
67 | 78 | ||
68 | printf ("usage: wsp [options]\n"); | 79 | printf ("usage: %s [options] [VAR=VALUE...]\n", progname); |
69 | printf ("options are:\n"); | 80 | printf ("options are:\n"); |
70 | printf (" [-]trimnl\n"); | 81 | printf (" [-]trimnl\n"); |
71 | printf (" [-]plaintext\n"); | 82 | printf (" [-]plaintext\n"); |
83 | printf (" -env\n"); | ||
84 | printf (" env sys|none|null\n"); | ||
72 | putchar ('\n'); | 85 | putchar ('\n'); |
73 | for (i = 0; bool_keytab[i].name; i++) | 86 | for (i = 0; bool_keytab[i].name; i++) |
74 | printf (" [-]%s\n", bool_keytab[i].name); | 87 | printf (" [-]%s\n", bool_keytab[i].name); |
75 | putchar ('\n'); | 88 | putchar ('\n'); |
76 | for (i = 0; string_keytab[i].name; i++) | 89 | for (i = 0; string_keytab[i].name; i++) |
77 | { | 90 | { |
78 | printf (" -%s\n", bool_keytab[i].name); | 91 | printf (" -%s\n", string_keytab[i].name); |
79 | printf (" %s ARG\n", bool_keytab[i].name); | 92 | printf (" %s ARG\n", string_keytab[i].name); |
93 | } | ||
94 | printf (" escape-word ARG\n"); | ||
95 | printf (" escape-quote ARG\n"); | ||
96 | putchar ('\n'); | ||
97 | for (i = 0; opt_keytab[i].name; i++) | ||
98 | { | ||
99 | printf (" [-]%s\n", opt_keytab[i].name); | ||
80 | } | 100 | } |
81 | putchar ('\n'); | 101 | putchar ('\n'); |
82 | printf (" -dooffs\n"); | 102 | printf (" -dooffs\n"); |
... | @@ -104,12 +124,7 @@ print_qword (const char *word, int plaintext) | ... | @@ -104,12 +124,7 @@ print_qword (const char *word, int plaintext) |
104 | if (size >= qlen) | 124 | if (size >= qlen) |
105 | { | 125 | { |
106 | qlen = size + 1; | 126 | qlen = size + 1; |
107 | qbuf = realloc (qbuf, qlen); | 127 | qbuf = mu_realloc (qbuf, qlen); |
108 | if (!qbuf) | ||
109 | { | ||
110 | mu_error ("not enough memory"); | ||
111 | abort (); | ||
112 | } | ||
113 | } | 128 | } |
114 | mu_wordsplit_c_quote_copy (qbuf, word, 0); | 129 | mu_wordsplit_c_quote_copy (qbuf, word, 0); |
115 | qbuf[size] = 0; | 130 | qbuf[size] = 0; |
... | @@ -131,50 +146,179 @@ make_env_kv () | ... | @@ -131,50 +146,179 @@ make_env_kv () |
131 | ; | 146 | ; |
132 | 147 | ||
133 | size = (i - 1) * 2 + 1; | 148 | size = (i - 1) * 2 + 1; |
134 | newenv = calloc (size, sizeof (newenv[0])); | 149 | newenv = mu_calloc (size, sizeof (newenv[0])); |
135 | if (!newenv) | ||
136 | { | ||
137 | mu_error ("not enough memory"); | ||
138 | exit (1); | ||
139 | } | ||
140 | 150 | ||
141 | for (i = j = 0; environ[i]; i++) | 151 | for (i = j = 0; environ[i]; i++) |
142 | { | 152 | { |
143 | size_t len = strcspn (environ[i], "="); | 153 | size_t len = strcspn (environ[i], "="); |
144 | char *p = malloc (len+1); | 154 | char *p = mu_alloc (len+1); |
145 | if (!p) | ||
146 | { | ||
147 | mu_error ("not enough memory"); | ||
148 | exit (1); | ||
149 | } | ||
150 | memcpy (p, environ[i], len); | 155 | memcpy (p, environ[i], len); |
151 | p[len] = 0; | 156 | p[len] = 0; |
152 | newenv[j++] = p; | 157 | newenv[j++] = p; |
153 | p = strdup (environ[i] + len + 1); | 158 | p = mu_strdup (environ[i] + len + 1); |
154 | if (!p) | ||
155 | { | ||
156 | mu_error ("not enough memory"); | ||
157 | exit (1); | ||
158 | } | ||
159 | newenv[j++] = p; | 159 | newenv[j++] = p; |
160 | } | 160 | } |
161 | newenv[j] = NULL; | 161 | newenv[j] = NULL; |
162 | return newenv; | 162 | return newenv; |
163 | } | 163 | } |
164 | 164 | ||
165 | static int | ||
166 | wsp_getvar (char **ret, const char *vptr, size_t vlen, void *data) | ||
167 | { | ||
168 | char **base = data; | ||
169 | int i; | ||
170 | |||
171 | for (i = 0; base[i]; i++) | ||
172 | { | ||
173 | size_t l = strcspn (base[i], "="); | ||
174 | if (l == vlen && memcmp (base[i], vptr, vlen) == 0) | ||
175 | { | ||
176 | char *p = strdup (base[i] + vlen + 1); | ||
177 | if (p == NULL) | ||
178 | return MU_WRDSE_NOSPACE; | ||
179 | *ret = p; | ||
180 | return MU_WRDSE_OK; | ||
181 | } | ||
182 | } | ||
183 | return MU_WRDSE_UNDEF; | ||
184 | } | ||
185 | |||
186 | static int | ||
187 | wsp_runcmd (char **ret, const char *str, size_t len, char **argv, void *closure) | ||
188 | { | ||
189 | FILE *fp; | ||
190 | char *cmd; | ||
191 | int c, lastc; | ||
192 | char *buffer = NULL; | ||
193 | size_t bufsize = 0; | ||
194 | size_t buflen = 0; | ||
195 | |||
196 | cmd = malloc (len + 1); | ||
197 | if (!cmd) | ||
198 | return MU_WRDSE_NOSPACE; | ||
199 | memcpy (cmd, str, len); | ||
200 | cmd[len] = 0; | ||
201 | |||
202 | fp = popen(cmd, "r"); | ||
203 | if (!fp) | ||
204 | { | ||
205 | size_t size = 0; | ||
206 | ret = NULL; | ||
207 | if (mu_asprintf (ret, &size, "can't run %s: %s", | ||
208 | cmd, strerror (errno))) | ||
209 | return MU_WRDSE_NOSPACE; | ||
210 | else | ||
211 | return MU_WRDSE_USERERR; | ||
212 | } | ||
213 | |||
214 | while ((c = fgetc (fp)) != EOF) | ||
215 | { | ||
216 | lastc = c; | ||
217 | if (c == '\n') | ||
218 | c = ' '; | ||
219 | if (buflen == bufsize) | ||
220 | { | ||
221 | char *p; | ||
222 | |||
223 | if (bufsize == 0) | ||
224 | bufsize = 80; | ||
225 | else | ||
226 | bufsize *= 2; | ||
227 | p = realloc (buffer, bufsize); | ||
228 | if (!p) | ||
229 | { | ||
230 | free (buffer); | ||
231 | free (cmd); | ||
232 | return MU_WRDSE_NOSPACE; | ||
233 | } | ||
234 | buffer = p; | ||
235 | } | ||
236 | buffer[buflen++] = c; | ||
237 | } | ||
238 | |||
239 | if (buffer) | ||
240 | { | ||
241 | if (lastc == '\n') | ||
242 | --buflen; | ||
243 | buffer[buflen] = 0; | ||
244 | } | ||
245 | |||
246 | pclose (fp); | ||
247 | free (cmd); | ||
248 | |||
249 | *ret = buffer; | ||
250 | return MU_WRDSE_OK; | ||
251 | } | ||
252 | |||
253 | enum env_type | ||
254 | { | ||
255 | env_none, | ||
256 | env_null, | ||
257 | env_sys | ||
258 | }; | ||
259 | |||
260 | struct mu_kwd env_keytab[] = { | ||
261 | { "none", env_none }, | ||
262 | { "null", env_null }, | ||
263 | { "sys", env_sys }, | ||
264 | { NULL } | ||
265 | }; | ||
266 | |||
267 | static void | ||
268 | set_escape_string (mu_wordsplit_t *ws, int *wsflags, int q, const char *str) | ||
269 | { | ||
270 | if (*str == ':') | ||
271 | { | ||
272 | while (*++str != ':') | ||
273 | { | ||
274 | int f; | ||
275 | switch (*str) | ||
276 | { | ||
277 | case '+': | ||
278 | f = MU_WRDSO_BSKEEP; | ||
279 | break; | ||
280 | |||
281 | case '0': | ||
282 | f = MU_WRDSO_OESC; | ||
283 | break; | ||
284 | |||
285 | case 'x': | ||
286 | f = MU_WRDSO_XESC; | ||
287 | break; | ||
288 | |||
289 | default: | ||
290 | fprintf (stderr, "%s: invalid escape flag near %s\n", | ||
291 | progname, str); | ||
292 | abort (); | ||
293 | } | ||
294 | MU_WRDSO_ESC_SET (ws, q, f); | ||
295 | } | ||
296 | *wsflags |= MU_WRDSF_OPTIONS; | ||
297 | ++str; | ||
298 | } | ||
299 | ws->ws_escape[q] = str; | ||
300 | } | ||
301 | |||
165 | int | 302 | int |
166 | main (int argc, char **argv) | 303 | main (int argc, char **argv) |
167 | { | 304 | { |
168 | char buf[1024], *ptr; | 305 | char buf[1024], *ptr, *saved_ptr; |
169 | int i, offarg = 0; | 306 | int i, offarg = 0; |
170 | int trimnl_option = 0; | 307 | int trimnl_option = 0; |
171 | int plaintext_option = 0; | 308 | int plaintext_option = 0; |
172 | int wsflags = (MU_WRDSF_DEFFLAGS & ~MU_WRDSF_NOVAR) | | 309 | int wsflags = (MU_WRDSF_DEFFLAGS & ~MU_WRDSF_NOVAR) | |
173 | MU_WRDSF_ENOMEMABRT | | 310 | MU_WRDSF_ENOMEMABRT | |
174 | MU_WRDSF_ENV | MU_WRDSF_SHOWERR; | 311 | MU_WRDSF_SHOWERR; |
175 | struct mu_wordsplit ws; | 312 | mu_wordsplit_t ws; |
176 | int next_call = 0; | 313 | int next_call = 0; |
314 | char *fenvbase[128]; | ||
315 | size_t fenvidx = 0; | ||
316 | size_t fenvmax = sizeof (fenvbase) / sizeof (fenvbase[0]); | ||
317 | int use_env = env_sys; | ||
318 | |||
319 | progname = argv[0]; | ||
177 | 320 | ||
321 | ws.ws_options = 0; | ||
178 | for (i = 1; i < argc; i++) | 322 | for (i = 1; i < argc; i++) |
179 | { | 323 | { |
180 | char *opt = argv[i]; | 324 | char *opt = argv[i]; |
... | @@ -212,7 +356,31 @@ main (int argc, char **argv) | ... | @@ -212,7 +356,31 @@ main (int argc, char **argv) |
212 | plaintext_option = !negate; | 356 | plaintext_option = !negate; |
213 | continue; | 357 | continue; |
214 | } | 358 | } |
215 | 359 | ||
360 | if (strcmp (opt, "env") == 0) | ||
361 | { | ||
362 | if (negate) | ||
363 | use_env = env_none; | ||
364 | else | ||
365 | { | ||
366 | i++; | ||
367 | if (i == argc) | ||
368 | { | ||
369 | fprintf (stderr, "%s: missing argument for env\n", | ||
370 | progname); | ||
371 | exit (1); | ||
372 | } | ||
373 | |||
374 | if (mu_kwd_xlat_name (env_keytab, argv[i], &use_env)) | ||
375 | { | ||
376 | fprintf (stderr, "%s: invalid argument for env\n", | ||
377 | progname); | ||
378 | exit (1); | ||
379 | } | ||
380 | } | ||
381 | continue; | ||
382 | } | ||
383 | |||
216 | if (mu_kwd_xlat_name (bool_keytab, opt, &flag) == 0) | 384 | if (mu_kwd_xlat_name (bool_keytab, opt, &flag) == 0) |
217 | { | 385 | { |
218 | if (negate) | 386 | if (negate) |
... | @@ -231,7 +399,8 @@ main (int argc, char **argv) | ... | @@ -231,7 +399,8 @@ main (int argc, char **argv) |
231 | i++; | 399 | i++; |
232 | if (i == argc) | 400 | if (i == argc) |
233 | { | 401 | { |
234 | mu_error ("%s missing argument", opt); | 402 | fprintf (stderr, "%s: missing argument for %s\n", |
403 | progname, opt); | ||
235 | exit (1); | 404 | exit (1); |
236 | } | 405 | } |
237 | 406 | ||
... | @@ -246,7 +415,8 @@ main (int argc, char **argv) | ... | @@ -246,7 +415,8 @@ main (int argc, char **argv) |
246 | break; | 415 | break; |
247 | 416 | ||
248 | case MU_WRDSF_ESCAPE: | 417 | case MU_WRDSF_ESCAPE: |
249 | ws.ws_escape = argv[i]; | 418 | set_escape_string (&ws, &wsflags, 0, argv[i]); |
419 | set_escape_string (&ws, &wsflags, 1, argv[i]); | ||
250 | break; | 420 | break; |
251 | } | 421 | } |
252 | 422 | ||
... | @@ -255,6 +425,27 @@ main (int argc, char **argv) | ... | @@ -255,6 +425,27 @@ main (int argc, char **argv) |
255 | continue; | 425 | continue; |
256 | } | 426 | } |
257 | 427 | ||
428 | if (strcmp (opt, "escape-word") == 0 | ||
429 | || strcmp (opt, "escape-quote") == 0) | ||
430 | { | ||
431 | int q = opt[7] == 'q'; | ||
432 | |||
433 | i++; | ||
434 | if (i == argc) | ||
435 | { | ||
436 | fprintf (stderr, "%s: missing argument for %s\n", | ||
437 | progname, opt); | ||
438 | exit (1); | ||
439 | } | ||
440 | if (!(wsflags & MU_WRDSF_ESCAPE)) | ||
441 | { | ||
442 | wsflags |= MU_WRDSF_ESCAPE; | ||
443 | ws.ws_escape[!q] = NULL; | ||
444 | } | ||
445 | set_escape_string (&ws, &wsflags, q, argv[i]); | ||
446 | continue; | ||
447 | } | ||
448 | |||
258 | if (strcmp (opt, "dooffs") == 0) | 449 | if (strcmp (opt, "dooffs") == 0) |
259 | { | 450 | { |
260 | if (negate) | 451 | if (negate) |
... | @@ -267,20 +458,23 @@ main (int argc, char **argv) | ... | @@ -267,20 +458,23 @@ main (int argc, char **argv) |
267 | 458 | ||
268 | if (i == argc) | 459 | if (i == argc) |
269 | { | 460 | { |
270 | mu_error ("%s missing arguments", opt); | 461 | fprintf (stderr, "%s: missing arguments for %s\n", |
462 | progname, opt); | ||
271 | exit (1); | 463 | exit (1); |
272 | } | 464 | } |
273 | ws.ws_offs = strtoul (argv[i], &p, 10); | 465 | ws.ws_offs = strtoul (argv[i], &p, 10); |
274 | if (*p) | 466 | if (*p) |
275 | { | 467 | { |
276 | mu_error ("invalid number: %s", argv[i]); | 468 | fprintf (stderr, "%s: invalid number: %s\n", |
469 | progname, argv[i]); | ||
277 | exit (1); | 470 | exit (1); |
278 | } | 471 | } |
279 | 472 | ||
280 | i++; | 473 | i++; |
281 | if (i + ws.ws_offs > argc) | 474 | if (i + ws.ws_offs > argc) |
282 | { | 475 | { |
283 | mu_error ("%s: not enough arguments", opt); | 476 | fprintf (stderr, "%s: not enough arguments for %s\n", |
477 | progname, opt); | ||
284 | exit (1); | 478 | exit (1); |
285 | } | 479 | } |
286 | offarg = i; | 480 | offarg = i; |
... | @@ -290,15 +484,65 @@ main (int argc, char **argv) | ... | @@ -290,15 +484,65 @@ main (int argc, char **argv) |
290 | continue; | 484 | continue; |
291 | } | 485 | } |
292 | 486 | ||
293 | mu_error ("%s: unrecognized argument", opt); | 487 | if (mu_kwd_xlat_name (opt_keytab, opt, &flag) == 0) |
488 | { | ||
489 | wsflags |= MU_WRDSF_OPTIONS; | ||
490 | if (negate) | ||
491 | ws.ws_options &= ~flag; | ||
492 | else | ||
493 | ws.ws_options |= flag; | ||
494 | continue; | ||
495 | } | ||
496 | |||
497 | if (strchr (opt, '=')) | ||
498 | { | ||
499 | if (fenvidx < fenvmax - 1) | ||
500 | { | ||
501 | fenvbase[fenvidx++] = opt; | ||
502 | continue; | ||
503 | } | ||
504 | else | ||
505 | { | ||
506 | fprintf (stderr, "%s: environment too big\n", progname); | ||
507 | exit (1); | ||
508 | } | ||
509 | } | ||
510 | |||
511 | fprintf (stderr, "%s: unrecognized argument: %s\n", | ||
512 | progname, opt); | ||
294 | exit (1); | 513 | exit (1); |
295 | } | 514 | } |
296 | 515 | ||
297 | if (wsflags & MU_WRDSF_ENV_KV) | 516 | if (fenvidx) |
298 | ws.ws_env = (const char **) make_env_kv (); | 517 | { |
299 | else | 518 | fenvbase[fenvidx] = NULL; |
300 | ws.ws_env = (const char **) environ; | 519 | wsflags |= MU_WRDSF_GETVAR | MU_WRDSF_CLOSURE; |
520 | ws.ws_getvar = wsp_getvar; | ||
521 | ws.ws_closure = fenvbase; | ||
522 | } | ||
523 | |||
524 | switch (use_env) | ||
525 | { | ||
526 | case env_null: | ||
527 | wsflags |= MU_WRDSF_ENV; | ||
528 | ws.ws_env = NULL; | ||
529 | break; | ||
301 | 530 | ||
531 | case env_none: | ||
532 | break; | ||
533 | |||
534 | case env_sys: | ||
535 | wsflags |= MU_WRDSF_ENV; | ||
536 | if (wsflags & MU_WRDSF_ENV_KV) | ||
537 | ws.ws_env = (const char **) make_env_kv (); | ||
538 | else | ||
539 | ws.ws_env = (const char **) environ; | ||
540 | break; | ||
541 | } | ||
542 | |||
543 | if (!(wsflags & MU_WRDSF_NOCMD)) | ||
544 | ws.ws_command = wsp_runcmd; | ||
545 | |||
302 | if (wsflags & MU_WRDSF_INCREMENTAL) | 546 | if (wsflags & MU_WRDSF_INCREMENTAL) |
303 | trimnl_option = 1; | 547 | trimnl_option = 1; |
304 | 548 | ||
... | @@ -309,7 +553,11 @@ main (int argc, char **argv) | ... | @@ -309,7 +553,11 @@ main (int argc, char **argv) |
309 | size_t i; | 553 | size_t i; |
310 | 554 | ||
311 | if (trimnl_option) | 555 | if (trimnl_option) |
312 | mu_rtrim_cset (ptr, "\n"); | 556 | { |
557 | size_t len = strlen (ptr); | ||
558 | if (len && ptr[len-1] == '\n') | ||
559 | ptr[len-1] = 0; | ||
560 | } | ||
313 | 561 | ||
314 | if (wsflags & MU_WRDSF_INCREMENTAL) | 562 | if (wsflags & MU_WRDSF_INCREMENTAL) |
315 | { | 563 | { |
... | @@ -318,16 +566,12 @@ main (int argc, char **argv) | ... | @@ -318,16 +566,12 @@ main (int argc, char **argv) |
318 | if (*ptr == 0) | 566 | if (*ptr == 0) |
319 | ptr = NULL; | 567 | ptr = NULL; |
320 | else | 568 | else |
321 | free ((void*)ws.ws_input); | 569 | free (saved_ptr); |
322 | } | 570 | } |
323 | else | 571 | else |
324 | next_call = 1; | 572 | next_call = 1; |
325 | if (ptr) | 573 | if (ptr) |
326 | { | 574 | ptr = saved_ptr = mu_strdup (ptr); |
327 | ptr = strdup (ptr); | ||
328 | if (!ptr) | ||
329 | abort (); | ||
330 | } | ||
331 | } | 575 | } |
332 | 576 | ||
333 | rc = mu_wordsplit (ptr, &ws, wsflags); | 577 | rc = mu_wordsplit (ptr, &ws, wsflags); |
... | @@ -344,8 +588,8 @@ main (int argc, char **argv) | ... | @@ -344,8 +588,8 @@ main (int argc, char **argv) |
344 | ws.ws_wordv[i] = argv[offarg + i]; | 588 | ws.ws_wordv[i] = argv[offarg + i]; |
345 | offarg = 0; | 589 | offarg = 0; |
346 | } | 590 | } |
347 | 591 | ||
348 | wsflags |= MU_WRDSF_REUSE; | 592 | wsflags |= MU_WRDSF_REUSE | (ws.ws_flags & MU_WRDSF_ENV); |
349 | printf ("NF: %lu", (unsigned long) ws.ws_wordc); | 593 | printf ("NF: %lu", (unsigned long) ws.ws_wordc); |
350 | if (wsflags & MU_WRDSF_DOOFFS) | 594 | if (wsflags & MU_WRDSF_DOOFFS) |
351 | printf (" (%lu)", (unsigned long) ws.ws_offs); | 595 | printf (" (%lu)", (unsigned long) ws.ws_offs); | ... | ... |
... | @@ -252,12 +252,16 @@ shell_help (int argc, char **argv) | ... | @@ -252,12 +252,16 @@ shell_help (int argc, char **argv) |
252 | static int | 252 | static int |
253 | shell_prompt (int argc, char **argv) | 253 | shell_prompt (int argc, char **argv) |
254 | { | 254 | { |
255 | size_t size; | 255 | mu_wordsplit_t ws; |
256 | 256 | ||
257 | free (mutool_shell_prompt); | 257 | if (mu_wordsplit (argv[1], &ws, MU_WRDSF_NOSPLIT | MU_WRDSF_DEFFLAGS)) |
258 | size = strlen (argv[1]); | 258 | mu_error ("mu_wordsplit: %s", mu_wordsplit_strerror (&ws)); |
259 | mutool_shell_prompt = mu_alloc (size + 1); | 259 | else |
260 | mu_wordsplit_c_unquote_copy (mutool_shell_prompt, argv[1], size); | 260 | { |
261 | free (mutool_shell_prompt); | ||
262 | mutool_shell_prompt = mu_strdup (ws.ws_wordv[0]); | ||
263 | } | ||
264 | mu_wordsplit_free (&ws); | ||
261 | return 0; | 265 | return 0; |
262 | } | 266 | } |
263 | 267 | ||
... | @@ -521,7 +525,7 @@ execute_line (char *line) | ... | @@ -521,7 +525,7 @@ execute_line (char *line) |
521 | int status = 0; | 525 | int status = 0; |
522 | 526 | ||
523 | ws.ws_comment = "#"; | 527 | ws.ws_comment = "#"; |
524 | ws.ws_escape = "\\\""; | 528 | ws.ws_escape[0] = ws.ws_escape[1] = "\\\\\"\""; |
525 | rc = mu_wordsplit (line, &ws, | 529 | rc = mu_wordsplit (line, &ws, |
526 | MU_WRDSF_DEFFLAGS|MU_WRDSF_COMMENT|MU_WRDSF_ESCAPE| | 530 | MU_WRDSF_DEFFLAGS|MU_WRDSF_COMMENT|MU_WRDSF_ESCAPE| |
527 | MU_WRDSF_INCREMENTAL|MU_WRDSF_APPEND); | 531 | MU_WRDSF_INCREMENTAL|MU_WRDSF_APPEND); | ... | ... |
-
Please register or sign in to post a comment