Commit f160ca75 f160ca75991d5bf994afe3cb5bc549b113b14bbd by Sergey Poznyakoff

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.
1 parent cd2126be
...@@ -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)));
......
...@@ -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);
......