Thu, 04 Oct 2012 20:30:05 +0200
Correct out of date build configuration, porting to Solaris 11 network
link infrastructure and new libpcap logic. This additionally allows for
device drivers in subdirectories of /dev. Correct packaged nmap
personalities and signatures to work out of the box. Finally, hack
arpd logic to properly close sockets and quit on TERM by repeating
signaling in the run command script. Sadly, all this fails to correct
the run time behaviour of honeyd which fails to bind to the IP layer.
1 Index: assoc.c
2 --- assoc.c.orig 2009-08-06 02:19:40.000000000 +0200
3 +++ assoc.c 2012-06-27 10:31:02.000000000 +0200
4 @@ -77,6 +77,11 @@
5 b = hash_search (key, hash, HASH_CREATE);
6 if (b == 0)
7 return -1;
8 + /* If we are overwriting an existing element's value, we're not going to
9 + use the key. Nothing in the array assignment code path frees the key
10 + string, so we can free it here to avoid a memory leak. */
11 + if (b->key != key)
12 + free (key);
13 FREE (b->data);
14 b->data = value ? savestring (value) : (char *)0;
15 return (0);
16 Index: bashline.c
17 --- bashline.c.orig 2011-01-16 21:32:47.000000000 +0100
18 +++ bashline.c 2012-06-27 10:31:03.000000000 +0200
19 @@ -121,6 +121,9 @@
20 static int filename_completion_ignore __P((char **));
21 static int bash_push_line __P((void));
23 +static rl_icppfunc_t *save_directory_hook __P((void));
24 +static void reset_directory_hook __P((rl_icppfunc_t *));
25 +
26 static void cleanup_expansion_error __P((void));
27 static void maybe_make_readline_line __P((char *));
28 static void set_up_new_line __P((char *));
29 @@ -243,10 +246,17 @@
30 /* Perform spelling correction on directory names during word completion */
31 int dircomplete_spelling = 0;
33 +/* Expand directory names during word/filename completion. */
34 +int dircomplete_expand = 0;
35 +int dircomplete_expand_relpath = 0;
36 +
37 static char *bash_completer_word_break_characters = " \t\n\"'@><=;|&(:";
38 static char *bash_nohostname_word_break_characters = " \t\n\"'><=;|&(:";
39 /* )) */
41 +static const char *default_filename_quote_characters = " \t\n\\\"'@<>=;|&()#$`?*[!:{~"; /*}*/
42 +static char *custom_filename_quote_characters = 0;
43 +
44 static rl_hook_func_t *old_rl_startup_hook = (rl_hook_func_t *)NULL;
46 static int dot_in_path = 0;
47 @@ -501,7 +511,7 @@
49 /* Tell the completer that we might want to follow symbolic links or
50 do other expansion on directory names. */
51 - rl_directory_rewrite_hook = bash_directory_completion_hook;
52 + set_directory_hook ();
54 rl_filename_rewrite_hook = bash_filename_rewrite_hook;
56 @@ -529,7 +539,7 @@
57 enable_hostname_completion (perform_hostname_completion);
59 /* characters that need to be quoted when appearing in filenames. */
60 - rl_filename_quote_characters = " \t\n\\\"'@<>=;|&()#$`?*[!:{~"; /*}*/
61 + rl_filename_quote_characters = default_filename_quote_characters;
63 rl_filename_quoting_function = bash_quote_filename;
64 rl_filename_dequoting_function = bash_dequote_filename;
65 @@ -564,8 +574,10 @@
66 tilde_initialize ();
67 rl_attempted_completion_function = attempt_shell_completion;
68 rl_completion_entry_function = NULL;
69 - rl_directory_rewrite_hook = bash_directory_completion_hook;
70 rl_ignore_some_completions_function = filename_completion_ignore;
71 + rl_filename_quote_characters = default_filename_quote_characters;
72 +
73 + set_directory_hook ();
74 }
76 /* Contains the line to push into readline. */
77 @@ -1279,6 +1291,9 @@
78 matches = (char **)NULL;
79 rl_ignore_some_completions_function = filename_completion_ignore;
81 + rl_filename_quote_characters = default_filename_quote_characters;
82 + set_directory_hook ();
83 +
84 /* Determine if this could be a command word. It is if it appears at
85 the start of the line (ignoring preceding whitespace), or if it
86 appears after a character that separates commands. It cannot be a
87 @@ -1591,6 +1606,12 @@
88 }
89 else
90 {
91 + if (dircomplete_expand && dot_or_dotdot (filename_hint))
92 + {
93 + dircomplete_expand = 0;
94 + set_directory_hook ();
95 + dircomplete_expand = 1;
96 + }
97 mapping_over = 4;
98 goto inner;
99 }
100 @@ -1791,6 +1812,9 @@
102 inner:
103 val = rl_filename_completion_function (filename_hint, istate);
104 + if (mapping_over == 4 && dircomplete_expand)
105 + set_directory_hook ();
106 +
107 istate = 1;
109 if (val == 0)
110 @@ -2693,6 +2717,52 @@
111 return conv;
112 }
114 +/* Functions to save and restore the appropriate directory hook */
115 +/* This is not static so the shopt code can call it */
116 +void
117 +set_directory_hook ()
118 +{
119 + if (dircomplete_expand)
120 + {
121 + rl_directory_completion_hook = bash_directory_completion_hook;
122 + rl_directory_rewrite_hook = (rl_icppfunc_t *)0;
123 + }
124 + else
125 + {
126 + rl_directory_rewrite_hook = bash_directory_completion_hook;
127 + rl_directory_completion_hook = (rl_icppfunc_t *)0;
128 + }
129 +}
130 +
131 +static rl_icppfunc_t *
132 +save_directory_hook ()
133 +{
134 + rl_icppfunc_t *ret;
135 +
136 + if (dircomplete_expand)
137 + {
138 + ret = rl_directory_completion_hook;
139 + rl_directory_completion_hook = (rl_icppfunc_t *)NULL;
140 + }
141 + else
142 + {
143 + ret = rl_directory_rewrite_hook;
144 + rl_directory_rewrite_hook = (rl_icppfunc_t *)NULL;
145 + }
146 +
147 + return ret;
148 +}
149 +
150 +static void
151 +restore_directory_hook (hookf)
152 + rl_icppfunc_t *hookf;
153 +{
154 + if (dircomplete_expand)
155 + rl_directory_completion_hook = hookf;
156 + else
157 + rl_directory_rewrite_hook = hookf;
158 +}
159 +
160 /* Handle symbolic link references and other directory name
161 expansions while hacking completion. This should return 1 if it modifies
162 the DIRNAME argument, 0 otherwise. It should make sure not to modify
163 @@ -2702,20 +2772,31 @@
164 char **dirname;
165 {
166 char *local_dirname, *new_dirname, *t;
167 - int return_value, should_expand_dirname;
168 + int return_value, should_expand_dirname, nextch, closer;
169 WORD_LIST *wl;
170 struct stat sb;
172 - return_value = should_expand_dirname = 0;
173 + return_value = should_expand_dirname = nextch = closer = 0;
174 local_dirname = *dirname;
176 - if (mbschr (local_dirname, '$'))
177 - should_expand_dirname = 1;
178 + if (t = mbschr (local_dirname, '$'))
179 + {
180 + should_expand_dirname = '$';
181 + nextch = t[1];
182 + /* Deliberately does not handle the deprecated $[...] arithmetic
183 + expansion syntax */
184 + if (nextch == '(')
185 + closer = ')';
186 + else if (nextch == '{')
187 + closer = '}';
188 + else
189 + nextch = 0;
190 + }
191 else
192 {
193 t = mbschr (local_dirname, '`');
194 if (t && unclosed_pair (local_dirname, strlen (local_dirname), "`") == 0)
195 - should_expand_dirname = 1;
196 + should_expand_dirname = '`';
197 }
199 #if defined (HAVE_LSTAT)
200 @@ -2739,6 +2820,23 @@
201 free (new_dirname);
202 dispose_words (wl);
203 local_dirname = *dirname;
204 + /* XXX - change rl_filename_quote_characters here based on
205 + should_expand_dirname/nextch/closer. This is the only place
206 + custom_filename_quote_characters is modified. */
207 + if (rl_filename_quote_characters && *rl_filename_quote_characters)
208 + {
209 + int i, j, c;
210 + i = strlen (default_filename_quote_characters);
211 + custom_filename_quote_characters = xrealloc (custom_filename_quote_characters, i+1);
212 + for (i = j = 0; c = default_filename_quote_characters[i]; i++)
213 + {
214 + if (c == should_expand_dirname || c == nextch || c == closer)
215 + continue;
216 + custom_filename_quote_characters[j++] = c;
217 + }
218 + custom_filename_quote_characters[j] = '\0';
219 + rl_filename_quote_characters = custom_filename_quote_characters;
220 + }
221 }
222 else
223 {
224 @@ -2758,11 +2856,31 @@
225 local_dirname = *dirname = new_dirname;
226 }
228 + /* no_symbolic_links == 0 -> use (default) logical view of the file system.
229 + local_dirname[0] == '.' && local_dirname[1] == '/' means files in the
230 + current directory (./).
231 + local_dirname[0] == '.' && local_dirname[1] == 0 means relative pathnames
232 + in the current directory (e.g., lib/sh).
233 + XXX - should we do spelling correction on these? */
234 +
235 + /* This is test as it was in bash-4.2: skip relative pathnames in current
236 + directory. Change test to
237 + (local_dirname[0] != '.' || (local_dirname[1] && local_dirname[1] != '/'))
238 + if we want to skip paths beginning with ./ also. */
239 if (no_symbolic_links == 0 && (local_dirname[0] != '.' || local_dirname[1]))
240 {
241 char *temp1, *temp2;
242 int len1, len2;
244 + /* If we have a relative path
245 + (local_dirname[0] != '/' && local_dirname[0] != '.')
246 + that is canonical after appending it to the current directory, then
247 + temp1 = temp2+'/'
248 + That is,
249 + strcmp (temp1, temp2) == 0
250 + after adding a slash to temp2 below. It should be safe to not
251 + change those.
252 + */
253 t = get_working_directory ("symlink-hook");
254 temp1 = make_absolute (local_dirname, t);
255 free (t);
256 @@ -2797,7 +2915,15 @@
257 temp2[len2 + 1] = '\0';
258 }
259 }
260 - return_value |= STREQ (local_dirname, temp2) == 0;
261 +
262 + /* dircomplete_expand_relpath == 0 means we want to leave relative
263 + pathnames that are unchanged by canonicalization alone.
264 + *local_dirname != '/' && *local_dirname != '.' == relative pathname
265 + (consistent with general.c:absolute_pathname())
266 + temp1 == temp2 (after appending a slash to temp2) means the pathname
267 + is not changed by canonicalization as described above. */
268 + if (dircomplete_expand_relpath || ((local_dirname[0] != '/' && local_dirname[0] != '.') && STREQ (temp1, temp2) == 0))
269 + return_value |= STREQ (local_dirname, temp2) == 0;
270 free (local_dirname);
271 *dirname = temp2;
272 free (temp1);
273 @@ -3002,12 +3128,13 @@
275 orig_func = rl_completion_entry_function;
276 orig_attempt_func = rl_attempted_completion_function;
277 - orig_dir_func = rl_directory_rewrite_hook;
278 orig_ignore_func = rl_ignore_some_completions_function;
279 orig_rl_completer_word_break_characters = rl_completer_word_break_characters;
280 +
281 + orig_dir_func = save_directory_hook ();
282 +
283 rl_completion_entry_function = rl_filename_completion_function;
284 rl_attempted_completion_function = (rl_completion_func_t *)NULL;
285 - rl_directory_rewrite_hook = (rl_icppfunc_t *)NULL;
286 rl_ignore_some_completions_function = filename_completion_ignore;
287 rl_completer_word_break_characters = " \t\n\"\'";
289 @@ -3015,10 +3142,11 @@
291 rl_completion_entry_function = orig_func;
292 rl_attempted_completion_function = orig_attempt_func;
293 - rl_directory_rewrite_hook = orig_dir_func;
294 rl_ignore_some_completions_function = orig_ignore_func;
295 rl_completer_word_break_characters = orig_rl_completer_word_break_characters;
297 + restore_directory_hook (orig_dir_func);
298 +
299 return r;
300 }
302 Index: bashline.h
303 --- bashline.h.orig 2009-01-04 20:32:22.000000000 +0100
304 +++ bashline.h 2012-06-27 10:31:03.000000000 +0200
305 @@ -33,10 +33,15 @@
306 extern void bashline_reinitialize __P((void));
307 extern int bash_re_edit __P((char *));
309 +extern void bashline_set_event_hook __P((void));
310 +extern void bashline_reset_event_hook __P((void));
311 +
312 extern int bind_keyseq_to_unix_command __P((char *));
314 extern char **bash_default_completion __P((const char *, int, int, int, int));
316 +void set_directory_hook __P((void));
317 +
318 /* Used by programmable completion code. */
319 extern char *command_word_completion_function __P((const char *, int));
320 extern char *bash_groupname_completion_function __P((const char *, int));
321 Index: builtins/declare.def
322 --- builtins/declare.def.orig 2010-05-31 00:25:21.000000000 +0200
323 +++ builtins/declare.def 2012-06-27 10:31:02.000000000 +0200
324 @@ -513,6 +513,11 @@
325 *subscript_start = '['; /* ] */
326 var = assign_array_element (name, value, 0); /* XXX - not aflags */
327 *subscript_start = '\0';
328 + if (var == 0) /* some kind of assignment error */
329 + {
330 + assign_error++;
331 + NEXT_VARIABLE ();
332 + }
333 }
334 else if (simple_array_assign)
335 {
336 Index: builtins/fc.def
337 --- builtins/fc.def.orig 2010-05-31 00:25:38.000000000 +0200
338 +++ builtins/fc.def 2012-06-27 10:31:02.000000000 +0200
339 @@ -304,7 +304,7 @@
340 last_hist = i - rh - hist_last_line_added;
342 /* XXX */
343 - if (saved_command_line_count > 0 && i == last_hist && hlist[last_hist] == 0)
344 + if (i == last_hist && hlist[last_hist] == 0)
345 while (last_hist >= 0 && hlist[last_hist] == 0)
346 last_hist--;
347 if (last_hist < 0)
348 @@ -475,7 +475,7 @@
349 HIST_ENTRY **hlist;
350 {
351 int sign, n, clen, rh;
352 - register int i, j;
353 + register int i, j, last_hist;
354 register char *s;
356 sign = 1;
357 @@ -495,7 +495,15 @@
358 has been enabled (interactive or not) should use it in the last_hist
359 calculation as if it were on. */
360 rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list);
361 - i -= rh + hist_last_line_added;
362 + last_hist = i - rh - hist_last_line_added;
363 +
364 + if (i == last_hist && hlist[last_hist] == 0)
365 + while (last_hist >= 0 && hlist[last_hist] == 0)
366 + last_hist--;
367 + if (last_hist < 0)
368 + return (-1);
369 +
370 + i = last_hist;
372 /* No specification defaults to most recent command. */
373 if (command == NULL)
374 Index: builtins/printf.def
375 --- builtins/printf.def.orig 2010-11-23 16:02:55.000000000 +0100
376 +++ builtins/printf.def 2012-06-27 10:31:02.000000000 +0200
377 @@ -255,6 +255,8 @@
378 #endif
379 {
380 vflag = 1;
381 + if (vbsize == 0)
382 + vbuf = xmalloc (vbsize = 16);
383 vblen = 0;
384 if (vbuf)
385 vbuf[0] = 0;
386 @@ -465,6 +467,9 @@
387 secs = shell_start_time; /* roughly $SECONDS */
388 else
389 secs = arg;
390 +#if defined (HAVE_TZSET)
391 + sv_tz ("TZ"); /* XXX -- just make sure */
392 +#endif
393 tm = localtime (&secs);
394 n = strftime (timebuf, sizeof (timebuf), timefmt, tm);
395 free (timefmt);
396 Index: builtins/read.def
397 --- builtins/read.def.orig 2011-01-04 17:43:36.000000000 +0100
398 +++ builtins/read.def 2012-06-27 10:31:02.000000000 +0200
399 @@ -642,6 +642,12 @@
400 xfree (input_string);
401 return EXECUTION_FAILURE; /* readonly or noassign */
402 }
403 + if (assoc_p (var))
404 + {
405 + builtin_error (_("%s: cannot convert associative to indexed array"), arrayname);
406 + xfree (input_string);
407 + return EXECUTION_FAILURE; /* existing associative array */
408 + }
409 array_flush (array_cell (var));
411 alist = list_string (input_string, ifs_chars, 0);
412 @@ -731,7 +737,7 @@
413 xfree (t1);
414 }
415 else
416 - var = bind_read_variable (varname, t);
417 + var = bind_read_variable (varname, t ? t : "");
418 }
419 else
420 {
421 @@ -792,7 +798,7 @@
422 xfree (t);
423 }
424 else
425 - var = bind_read_variable (list->word->word, input_string);
426 + var = bind_read_variable (list->word->word, input_string ? input_string : "");
428 if (var)
429 {
430 Index: builtins/shopt.def
431 --- builtins/shopt.def.orig 2010-07-03 04:42:44.000000000 +0200
432 +++ builtins/shopt.def 2012-06-27 10:31:03.000000000 +0200
433 @@ -61,6 +61,10 @@
434 #include "common.h"
435 #include "bashgetopt.h"
437 +#if defined (READLINE)
438 +# include "../bashline.h"
439 +#endif
440 +
441 #if defined (HISTORY)
442 # include "../bashhist.h"
443 #endif
444 @@ -94,7 +98,7 @@
445 extern int hist_verify, history_reediting, perform_hostname_completion;
446 extern int no_empty_command_completion;
447 extern int force_fignore;
448 -extern int dircomplete_spelling;
449 +extern int dircomplete_spelling, dircomplete_expand;
451 extern int enable_hostname_completion __P((int));
452 #endif
453 @@ -121,6 +125,10 @@
454 static int set_restricted_shell __P((char *, int));
455 #endif
457 +#if defined (READLINE)
458 +static int shopt_set_complete_direxpand __P((char *, int));
459 +#endif
460 +
461 static int shopt_login_shell;
462 static int shopt_compat31;
463 static int shopt_compat32;
464 @@ -150,6 +158,7 @@
465 { "compat40", &shopt_compat40, set_compatibility_level },
466 { "compat41", &shopt_compat41, set_compatibility_level },
467 #if defined (READLINE)
468 + { "direxpand", &dircomplete_expand, shopt_set_complete_direxpand },
469 { "dirspell", &dircomplete_spelling, (shopt_set_func_t *)NULL },
470 #endif
471 { "dotglob", &glob_dot_filenames, (shopt_set_func_t *)NULL },
472 @@ -535,6 +544,17 @@
473 return 0;
474 }
476 +#if defined (READLINE)
477 +static int
478 +shopt_set_complete_direxpand (option_name, mode)
479 + char *option_name;
480 + int mode;
481 +{
482 + set_directory_hook ();
483 + return 0;
484 +}
485 +#endif
486 +
487 #if defined (RESTRICTED_SHELL)
488 /* Don't allow the value of restricted_shell to be modified. */
490 Index: command.h
491 --- command.h.orig 2010-08-03 01:36:51.000000000 +0200
492 +++ command.h 2012-06-27 10:31:02.000000000 +0200
493 @@ -97,6 +97,7 @@
494 #define W_HASCTLESC 0x200000 /* word contains literal CTLESC characters */
495 #define W_ASSIGNASSOC 0x400000 /* word looks like associative array assignment */
496 #define W_ARRAYIND 0x800000 /* word is an array index being expanded */
497 +#define W_ASSNGLOBAL 0x1000000 /* word is a global assignment to declare (declare/typeset -g) */
499 /* Possible values for subshell_environment */
500 #define SUBSHELL_ASYNC 0x01 /* subshell caused by `command &' */
501 Index: doc/bash.1
502 --- doc/bash.1.orig 2011-01-16 21:31:39.000000000 +0100
503 +++ doc/bash.1 2012-06-27 10:31:03.000000000 +0200
504 @@ -8954,6 +8954,16 @@
505 quoted. This is the behavior of posix mode through version 4.1.
506 The default bash behavior remains as in previous versions.
507 .TP 8
508 +.B direxpand
509 +If set,
510 +.B bash
511 +replaces directory names with the results of word expansion when performing
512 +filename completion. This changes the contents of the readline editing
513 +buffer.
514 +If not set,
515 +.B bash
516 +attempts to preserve what the user typed.
517 +.TP 8
518 .B dirspell
519 If set,
520 .B bash
521 Index: doc/bashref.texi
522 --- doc/bashref.texi.orig 2011-01-16 21:31:57.000000000 +0100
523 +++ doc/bashref.texi 2012-06-27 10:31:03.000000000 +0200
524 @@ -4535,6 +4535,13 @@
525 quoted. This is the behavior of @sc{posix} mode through version 4.1.
526 The default Bash behavior remains as in previous versions.
528 +@item direxpand
529 +If set, Bash
530 +replaces directory names with the results of word expansion when performing
531 +filename completion. This changes the contents of the readline editing
532 +buffer.
533 +If not set, Bash attempts to preserve what the user typed.
534 +
535 @item dirspell
536 If set, Bash
537 attempts spelling correction on directory names during word completion
538 Index: error.c
539 --- error.c.orig 2009-08-22 04:31:31.000000000 +0200
540 +++ error.c 2012-06-27 10:31:02.000000000 +0200
541 @@ -200,7 +200,11 @@
543 va_end (args);
544 if (exit_immediately_on_error)
545 - exit_shell (1);
546 + {
547 + if (last_command_exit_value == 0)
548 + last_command_exit_value = 1;
549 + exit_shell (last_command_exit_value);
550 + }
551 }
553 void
554 Index: execute_cmd.c
555 --- execute_cmd.c.orig 2011-02-09 23:32:25.000000000 +0100
556 +++ execute_cmd.c 2012-06-27 10:31:03.000000000 +0200
557 @@ -2196,6 +2196,7 @@
558 if (ignore_return && cmd)
559 cmd->flags |= CMD_IGNORE_RETURN;
561 +#if defined (JOB_CONTROL)
562 lastpipe_flag = 0;
563 begin_unwind_frame ("lastpipe-exec");
564 lstdin = -1;
565 @@ -2204,7 +2205,7 @@
566 current shell environment. */
567 if (lastpipe_opt && job_control == 0 && asynchronous == 0 && pipe_out == NO_PIPE && prev > 0)
568 {
569 - lstdin = move_to_high_fd (0, 0, 255);
570 + lstdin = move_to_high_fd (0, 1, -1);
571 if (lstdin > 0)
572 {
573 do_piping (prev, pipe_out);
574 @@ -2215,15 +2216,19 @@
575 lastpipe_jid = stop_pipeline (0, (COMMAND *)NULL); /* XXX */
576 add_unwind_protect (lastpipe_cleanup, lastpipe_jid);
577 }
578 - cmd->flags |= CMD_LASTPIPE;
579 + if (cmd)
580 + cmd->flags |= CMD_LASTPIPE;
581 }
582 if (prev >= 0)
583 add_unwind_protect (close, prev);
584 +#endif
586 exec_result = execute_command_internal (cmd, asynchronous, prev, pipe_out, fds_to_close);
588 +#if defined (JOB_CONTROL)
589 if (lstdin > 0)
590 restore_stdin (lstdin);
591 +#endif
593 if (prev >= 0)
594 close (prev);
595 @@ -2246,7 +2251,9 @@
596 unfreeze_jobs_list ();
597 }
599 +#if defined (JOB_CONTROL)
600 discard_unwind_frame ("lastpipe-exec");
601 +#endif
603 return (exec_result);
604 }
605 @@ -3575,13 +3582,13 @@
606 {
607 WORD_LIST *w;
608 struct builtin *b;
609 - int assoc;
610 + int assoc, global;
612 if (words == 0)
613 return;
615 b = 0;
616 - assoc = 0;
617 + assoc = global = 0;
619 for (w = words; w; w = w->next)
620 if (w->word->flags & W_ASSIGNMENT)
621 @@ -3598,12 +3605,17 @@
622 #if defined (ARRAY_VARS)
623 if (assoc)
624 w->word->flags |= W_ASSIGNASSOC;
625 + if (global)
626 + w->word->flags |= W_ASSNGLOBAL;
627 #endif
628 }
629 #if defined (ARRAY_VARS)
630 /* Note that we saw an associative array option to a builtin that takes
631 assignment statements. This is a bit of a kludge. */
632 - else if (w->word->word[0] == '-' && strchr (w->word->word, 'A'))
633 + else if (w->word->word[0] == '-' && (strchr (w->word->word+1, 'A') || strchr (w->word->word+1, 'g')))
634 +#else
635 + else if (w->word->word[0] == '-' && strchr (w->word->word+1, 'g'))
636 +#endif
637 {
638 if (b == 0)
639 {
640 @@ -3613,10 +3625,11 @@
641 else if (b && (b->flags & ASSIGNMENT_BUILTIN))
642 words->word->flags |= W_ASSNBLTIN;
643 }
644 - if (words->word->flags & W_ASSNBLTIN)
645 + if ((words->word->flags & W_ASSNBLTIN) && strchr (w->word->word+1, 'A'))
646 assoc = 1;
647 + if ((words->word->flags & W_ASSNBLTIN) && strchr (w->word->word+1, 'g'))
648 + global = 1;
649 }
650 -#endif
651 }
653 /* Return 1 if the file found by searching $PATH for PATHNAME, defaulting
654 Index: expr.c
655 --- expr.c.orig 2010-12-21 17:12:13.000000000 +0100
656 +++ expr.c 2012-06-27 10:31:02.000000000 +0200
657 @@ -476,19 +476,23 @@
659 if (special)
660 {
661 + if ((op == DIV || op == MOD) && value == 0)
662 + {
663 + if (noeval == 0)
664 + evalerror (_("division by 0"));
665 + else
666 + value = 1;
667 + }
668 +
669 switch (op)
670 {
671 case MUL:
672 lvalue *= value;
673 break;
674 case DIV:
675 - if (value == 0)
676 - evalerror (_("division by 0"));
677 lvalue /= value;
678 break;
679 case MOD:
680 - if (value == 0)
681 - evalerror (_("division by 0"));
682 lvalue %= value;
683 break;
684 case PLUS:
685 @@ -804,7 +808,12 @@
686 val2 = exppower ();
688 if (((op == DIV) || (op == MOD)) && (val2 == 0))
689 - evalerror (_("division by 0"));
690 + {
691 + if (noeval == 0)
692 + evalerror (_("division by 0"));
693 + else
694 + val2 = 1;
695 + }
697 if (op == MUL)
698 val1 *= val2;
699 Index: lib/glob/gmisc.c
700 --- lib/glob/gmisc.c.orig 2011-02-05 22:11:17.000000000 +0100
701 +++ lib/glob/gmisc.c 2012-06-27 10:31:02.000000000 +0200
702 @@ -77,8 +77,8 @@
703 wchar_t *wpat;
704 size_t wmax;
705 {
706 - wchar_t wc, *wbrack;
707 - int matlen, t, in_cclass, in_collsym, in_equiv;
708 + wchar_t wc;
709 + int matlen, bracklen, t, in_cclass, in_collsym, in_equiv;
711 if (*wpat == 0)
712 return (0);
713 @@ -118,58 +118,80 @@
714 break;
715 case L'[':
716 /* scan for ending `]', skipping over embedded [:...:] */
717 - wbrack = wpat;
718 + bracklen = 1;
719 wc = *wpat++;
720 do
721 {
722 if (wc == 0)
723 {
724 - matlen += wpat - wbrack - 1; /* incremented below */
725 - break;
726 + wpat--; /* back up to NUL */
727 + matlen += bracklen;
728 + goto bad_bracket;
729 }
730 else if (wc == L'\\')
731 {
732 - wc = *wpat++;
733 - if (*wpat == 0)
734 - break;
735 + /* *wpat == backslash-escaped character */
736 + bracklen++;
737 + /* If the backslash or backslash-escape ends the string,
738 + bail. The ++wpat skips over the backslash escape */
739 + if (*wpat == 0 || *++wpat == 0)
740 + {
741 + matlen += bracklen;
742 + goto bad_bracket;
743 + }
744 }
745 else if (wc == L'[' && *wpat == L':') /* character class */
746 {
747 wpat++;
748 + bracklen++;
749 in_cclass = 1;
750 }
751 else if (in_cclass && wc == L':' && *wpat == L']')
752 {
753 wpat++;
754 + bracklen++;
755 in_cclass = 0;
756 }
757 else if (wc == L'[' && *wpat == L'.') /* collating symbol */
758 {
759 wpat++;
760 + bracklen++;
761 if (*wpat == L']') /* right bracket can appear as collating symbol */
762 - wpat++;
763 + {
764 + wpat++;
765 + bracklen++;
766 + }
767 in_collsym = 1;
768 }
769 else if (in_collsym && wc == L'.' && *wpat == L']')
770 {
771 wpat++;
772 + bracklen++;
773 in_collsym = 0;
774 }
775 else if (wc == L'[' && *wpat == L'=') /* equivalence class */
776 {
777 wpat++;
778 + bracklen++;
779 if (*wpat == L']') /* right bracket can appear as equivalence class */
780 - wpat++;
781 + {
782 + wpat++;
783 + bracklen++;
784 + }
785 in_equiv = 1;
786 }
787 else if (in_equiv && wc == L'=' && *wpat == L']')
788 {
789 wpat++;
790 + bracklen++;
791 in_equiv = 0;
792 }
793 + else
794 + bracklen++;
795 }
796 while ((wc = *wpat++) != L']');
797 matlen++; /* bracket expression can only match one char */
798 +bad_bracket:
799 break;
800 }
801 }
802 @@ -213,8 +235,8 @@
803 char *pat;
804 size_t max;
805 {
806 - char c, *brack;
807 - int matlen, t, in_cclass, in_collsym, in_equiv;
808 + char c;
809 + int matlen, bracklen, t, in_cclass, in_collsym, in_equiv;
811 if (*pat == 0)
812 return (0);
813 @@ -254,58 +276,80 @@
814 break;
815 case '[':
816 /* scan for ending `]', skipping over embedded [:...:] */
817 - brack = pat;
818 + bracklen = 1;
819 c = *pat++;
820 do
821 {
822 if (c == 0)
823 {
824 - matlen += pat - brack - 1; /* incremented below */
825 - break;
826 + pat--; /* back up to NUL */
827 + matlen += bracklen;
828 + goto bad_bracket;
829 }
830 else if (c == '\\')
831 {
832 - c = *pat++;
833 - if (*pat == 0)
834 - break;
835 + /* *pat == backslash-escaped character */
836 + bracklen++;
837 + /* If the backslash or backslash-escape ends the string,
838 + bail. The ++pat skips over the backslash escape */
839 + if (*pat == 0 || *++pat == 0)
840 + {
841 + matlen += bracklen;
842 + goto bad_bracket;
843 + }
844 }
845 else if (c == '[' && *pat == ':') /* character class */
846 {
847 pat++;
848 + bracklen++;
849 in_cclass = 1;
850 }
851 else if (in_cclass && c == ':' && *pat == ']')
852 {
853 pat++;
854 + bracklen++;
855 in_cclass = 0;
856 }
857 else if (c == '[' && *pat == '.') /* collating symbol */
858 {
859 pat++;
860 + bracklen++;
861 if (*pat == ']') /* right bracket can appear as collating symbol */
862 - pat++;
863 + {
864 + pat++;
865 + bracklen++;
866 + }
867 in_collsym = 1;
868 }
869 else if (in_collsym && c == '.' && *pat == ']')
870 {
871 pat++;
872 + bracklen++;
873 in_collsym = 0;
874 }
875 else if (c == '[' && *pat == '=') /* equivalence class */
876 {
877 pat++;
878 + bracklen++;
879 if (*pat == ']') /* right bracket can appear as equivalence class */
880 - pat++;
881 + {
882 + pat++;
883 + bracklen++;
884 + }
885 in_equiv = 1;
886 }
887 else if (in_equiv && c == '=' && *pat == ']')
888 {
889 pat++;
890 + bracklen++;
891 in_equiv = 0;
892 }
893 + else
894 + bracklen++;
895 }
896 while ((c = *pat++) != ']');
897 matlen++; /* bracket expression can only match one char */
898 +bad_bracket:
899 break;
900 }
901 }
902 Index: lib/readline/callback.c
903 --- lib/readline/callback.c.orig 2010-06-06 18:18:58.000000000 +0200
904 +++ lib/readline/callback.c 2012-06-27 10:31:02.000000000 +0200
905 @@ -148,6 +148,9 @@
906 eof = _rl_vi_domove_callback (_rl_vimvcxt);
907 /* Should handle everything, including cleanup, numeric arguments,
908 and turning off RL_STATE_VIMOTION */
909 + if (RL_ISSTATE (RL_STATE_NUMERICARG) == 0)
910 + _rl_internal_char_cleanup ();
911 +
912 return;
913 }
914 #endif
915 Index: lib/readline/vi_mode.c
916 --- lib/readline/vi_mode.c.orig 2010-11-21 01:51:39.000000000 +0100
917 +++ lib/readline/vi_mode.c 2012-06-27 10:31:02.000000000 +0200
918 @@ -1114,7 +1114,7 @@
919 rl_beg_of_line (1, c);
920 _rl_vi_last_motion = c;
921 RL_UNSETSTATE (RL_STATE_VIMOTION);
922 - return (0);
923 + return (vidomove_dispatch (m));
924 }
925 #if defined (READLINE_CALLBACKS)
926 /* XXX - these need to handle rl_universal_argument bindings */
927 Index: lib/sh/zread.c
928 --- lib/sh/zread.c.orig 2009-03-02 14:54:45.000000000 +0100
929 +++ lib/sh/zread.c 2012-06-27 10:31:02.000000000 +0200
930 @@ -160,14 +160,13 @@
931 zsyncfd (fd)
932 int fd;
933 {
934 - off_t off;
935 - int r;
936 + off_t off, r;
938 off = lused - lind;
939 r = 0;
940 if (off > 0)
941 r = lseek (fd, -off, SEEK_CUR);
943 - if (r >= 0)
944 + if (r != -1)
945 lused = lind = 0;
946 }
947 Index: parse.y
948 --- parse.y.orig 2011-01-02 21:48:11.000000000 +0100
949 +++ parse.y 2012-06-27 10:31:02.000000000 +0200
950 @@ -2499,7 +2499,7 @@
951 We do this only if it is time to do so. Notice that only here
952 is the mail alarm reset; nothing takes place in check_mail ()
953 except the checking of mail. Please don't change this. */
954 - if (prompt_is_ps1 && time_to_check_mail ())
955 + if (prompt_is_ps1 && parse_and_execute_level == 0 && time_to_check_mail ())
956 {
957 check_mail ();
958 reset_mail_timer ();
959 @@ -3842,6 +3842,7 @@
960 int flags;
961 {
962 sh_parser_state_t ps;
963 + sh_input_line_state_t ls;
964 int orig_ind, nc, sflags;
965 char *ret, *s, *ep, *ostring;
967 @@ -3849,10 +3850,12 @@
968 orig_ind = *indp;
969 ostring = string;
971 +/*itrace("xparse_dolparen: size = %d shell_input_line = `%s'", shell_input_line_size, shell_input_line);*/
972 sflags = SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOFREE;
973 if (flags & SX_NOLONGJMP)
974 sflags |= SEVAL_NOLONGJMP;
975 save_parser_state (&ps);
976 + save_input_line_state (&ls);
978 /*(*/
979 parser_state |= PST_CMDSUBST|PST_EOFTOKEN; /* allow instant ')' */ /*(*/
980 @@ -3861,6 +3864,8 @@
982 restore_parser_state (&ps);
983 reset_parser ();
984 + /* reset_parser clears shell_input_line and associated variables */
985 + restore_input_line_state (&ls);
986 if (interactive)
987 token_to_read = 0;
989 @@ -5135,6 +5140,9 @@
990 case 'A':
991 /* Make the current time/date into a string. */
992 (void) time (&the_time);
993 +#if defined (HAVE_TZSET)
994 + sv_tz ("TZ"); /* XXX -- just make sure */
995 +#endif
996 tm = localtime (&the_time);
998 if (c == 'd')
999 @@ -5905,6 +5913,12 @@
1000 ps->expand_aliases = expand_aliases;
1001 ps->echo_input_at_read = echo_input_at_read;
1003 + ps->token = token;
1004 + ps->token_buffer_size = token_buffer_size;
1005 + /* Force reallocation on next call to read_token_word */
1006 + token = 0;
1007 + token_buffer_size = 0;
1008 +
1009 return (ps);
1010 }
1012 @@ -5946,6 +5960,42 @@
1014 expand_aliases = ps->expand_aliases;
1015 echo_input_at_read = ps->echo_input_at_read;
1016 +
1017 + FREE (token);
1018 + token = ps->token;
1019 + token_buffer_size = ps->token_buffer_size;
1020 +}
1021 +
1022 +sh_input_line_state_t *
1023 +save_input_line_state (ls)
1024 + sh_input_line_state_t *ls;
1025 +{
1026 + if (ls == 0)
1027 + ls = (sh_input_line_state_t *)xmalloc (sizeof (sh_input_line_state_t));
1028 + if (ls == 0)
1029 + return ((sh_input_line_state_t *)NULL);
1030 +
1031 + ls->input_line = shell_input_line;
1032 + ls->input_line_size = shell_input_line_size;
1033 + ls->input_line_len = shell_input_line_len;
1034 + ls->input_line_index = shell_input_line_index;
1035 +
1036 + /* force reallocation */
1037 + shell_input_line = 0;
1038 + shell_input_line_size = shell_input_line_len = shell_input_line_index = 0;
1039 +}
1040 +
1041 +void
1042 +restore_input_line_state (ls)
1043 + sh_input_line_state_t *ls;
1044 +{
1045 + FREE (shell_input_line);
1046 + shell_input_line = ls->input_line;
1047 + shell_input_line_size = ls->input_line_size;
1048 + shell_input_line_len = ls->input_line_len;
1049 + shell_input_line_index = ls->input_line_index;
1050 +
1051 + set_line_mbstate ();
1052 }
1054 /************************************************
1055 Index: patchlevel.h
1056 --- patchlevel.h.orig 2010-06-13 02:14:48.000000000 +0200
1057 +++ patchlevel.h 2012-06-27 10:31:03.000000000 +0200
1058 @@ -25,6 +25,6 @@
1059 regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
1060 looks for to find the patch level (for the sccs version string). */
1062 -#define PATCHLEVEL 0
1063 +#define PATCHLEVEL 29
1065 #endif /* _PATCHLEVEL_H_ */
1066 Index: pathexp.c
1067 --- pathexp.c.orig 2010-08-14 05:21:57.000000000 +0200
1068 +++ pathexp.c 2012-06-27 10:31:02.000000000 +0200
1069 @@ -196,7 +196,7 @@
1070 {
1071 if ((qflags & QGLOB_FILENAME) && pathname[i+1] == '/')
1072 continue;
1073 - if ((qflags & QGLOB_REGEXP) && ere_char (pathname[i+1]) == 0)
1074 + if (pathname[i+1] != CTLESC && (qflags & QGLOB_REGEXP) && ere_char (pathname[i+1]) == 0)
1075 continue;
1076 temp[j++] = '\\';
1077 i++;
1078 Index: print_cmd.c
1079 --- print_cmd.c.orig 2010-05-31 00:34:08.000000000 +0200
1080 +++ print_cmd.c 2012-06-27 10:31:02.000000000 +0200
1081 @@ -315,6 +315,7 @@
1082 cprintf ("( ");
1083 skip_this_indent++;
1084 make_command_string_internal (command->value.Subshell->command);
1085 + PRINT_DEFERRED_HEREDOCS ("");
1086 cprintf (" )");
1087 break;
1089 @@ -592,6 +593,7 @@
1090 newline ("do\n");
1091 indentation += indentation_amount;
1092 make_command_string_internal (arith_for_command->action);
1093 + PRINT_DEFERRED_HEREDOCS ("");
1094 semicolon ();
1095 indentation -= indentation_amount;
1096 newline ("done");
1097 @@ -653,6 +655,7 @@
1098 }
1100 make_command_string_internal (group_command->command);
1101 + PRINT_DEFERRED_HEREDOCS ("");
1103 if (inside_function_def)
1104 {
1105 Index: shell.h
1106 --- shell.h.orig 2011-01-07 04:16:55.000000000 +0100
1107 +++ shell.h 2012-06-27 10:31:02.000000000 +0200
1108 @@ -136,6 +136,9 @@
1109 int parser_state;
1110 int *token_state;
1112 + char *token;
1113 + int token_buffer_size;
1114 +
1115 /* input line state -- line number saved elsewhere */
1116 int input_line_terminator;
1117 int eof_encountered;
1118 @@ -166,6 +169,16 @@
1120 } sh_parser_state_t;
1122 +typedef struct _sh_input_line_state_t {
1123 + char *input_line;
1124 + int input_line_index;
1125 + int input_line_size;
1126 + int input_line_len;
1127 +} sh_input_line_state_t;
1128 +
1129 /* Let's try declaring these here. */
1130 extern sh_parser_state_t *save_parser_state __P((sh_parser_state_t *));
1131 extern void restore_parser_state __P((sh_parser_state_t *));
1132 +
1133 +extern sh_input_line_state_t *save_input_line_state __P((sh_input_line_state_t *));
1134 +extern void restore_input_line_state __P((sh_input_line_state_t *));
1135 Index: sig.c
1136 --- sig.c.orig 2010-11-23 14:21:22.000000000 +0100
1137 +++ sig.c 2012-06-27 10:31:02.000000000 +0200
1138 @@ -46,6 +46,7 @@
1140 #if defined (READLINE)
1141 # include "bashline.h"
1142 +# include <readline/readline.h>
1143 #endif
1145 #if defined (HISTORY)
1146 @@ -62,6 +63,7 @@
1147 #if defined (HISTORY)
1148 extern int history_lines_this_session;
1149 #endif
1150 +extern int no_line_editing;
1152 extern void initialize_siglist ();
1154 @@ -505,7 +507,10 @@
1155 {
1156 #if defined (HISTORY)
1157 /* XXX - will inhibit history file being written */
1158 - history_lines_this_session = 0;
1159 +# if defined (READLINE)
1160 + if (interactive_shell == 0 || interactive == 0 || (sig != SIGHUP && sig != SIGTERM) || no_line_editing || (RL_ISSTATE (RL_STATE_READCMD) == 0))
1161 +# endif
1162 + history_lines_this_session = 0;
1163 #endif
1164 terminate_immediately = 0;
1165 termsig_handler (sig);
1166 Index: subst.c
1167 --- subst.c.orig 2011-01-02 22:12:51.000000000 +0100
1168 +++ subst.c 2012-06-27 10:31:03.000000000 +0200
1169 @@ -366,6 +366,11 @@
1170 f &= ~W_ASSNBLTIN;
1171 fprintf (stderr, "W_ASSNBLTIN%s", f ? "|" : "");
1172 }
1173 + if (f & W_ASSNGLOBAL)
1174 + {
1175 + f &= ~W_ASSNGLOBAL;
1176 + fprintf (stderr, "W_ASSNGLOBAL%s", f ? "|" : "");
1177 + }
1178 if (f & W_COMPASSIGN)
1179 {
1180 f &= ~W_COMPASSIGN;
1181 @@ -1379,10 +1384,12 @@
1182 slen = strlen (string + *sindex) + *sindex;
1184 /* The handling of dolbrace_state needs to agree with the code in parse.y:
1185 - parse_matched_pair() */
1186 - dolbrace_state = 0;
1187 - if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
1188 - dolbrace_state = (flags & SX_POSIXEXP) ? DOLBRACE_QUOTE : DOLBRACE_PARAM;
1189 + parse_matched_pair(). The different initial value is to handle the
1190 + case where this function is called to parse the word in
1191 + ${param op word} (SX_WORD). */
1192 + dolbrace_state = (flags & SX_WORD) ? DOLBRACE_WORD : DOLBRACE_PARAM;
1193 + if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && (flags & SX_POSIXEXP))
1194 + dolbrace_state = DOLBRACE_QUOTE;
1196 i = *sindex;
1197 while (c = string[i])
1198 @@ -2801,7 +2808,7 @@
1199 }
1200 else if (assign_list)
1201 {
1202 - if (word->flags & W_ASSIGNARG)
1203 + if ((word->flags & W_ASSIGNARG) && (word->flags & W_ASSNGLOBAL) == 0)
1204 aflags |= ASS_MKLOCAL;
1205 if (word->flags & W_ASSIGNASSOC)
1206 aflags |= ASS_MKASSOC;
1207 @@ -3371,7 +3378,7 @@
1208 if (string == 0 || *string == '\0')
1209 return (WORD_LIST *)NULL;
1211 - td.flags = 0;
1212 + td.flags = W_NOSPLIT2; /* no splitting, remove "" and '' */
1213 td.word = string;
1214 tresult = call_expand_word_internal (&td, quoted, 1, dollar_at_p, has_dollar_at);
1215 return (tresult);
1216 @@ -3704,7 +3711,10 @@
1217 break;
1218 }
1219 else if (string[i] == CTLNUL)
1220 - i++;
1221 + {
1222 + i++;
1223 + continue;
1224 + }
1226 prev_i = i;
1227 ADVANCE_CHAR (string, slen, i);
1228 @@ -4156,7 +4166,7 @@
1229 simple = (wpat[0] != L'\\' && wpat[0] != L'*' && wpat[0] != L'?' && wpat[0] != L'[');
1230 #if defined (EXTENDED_GLOB)
1231 if (extended_glob)
1232 - simple |= (wpat[1] != L'(' || (wpat[0] != L'*' && wpat[0] != L'?' && wpat[0] != L'+' && wpat[0] != L'!' && wpat[0] != L'@')); /*)*/
1233 + simple &= (wpat[1] != L'(' || (wpat[0] != L'*' && wpat[0] != L'?' && wpat[0] != L'+' && wpat[0] != L'!' && wpat[0] != L'@')); /*)*/
1234 #endif
1236 /* If the pattern doesn't match anywhere in the string, go ahead and
1237 @@ -4607,6 +4617,7 @@
1238 if (ifs_firstc == 0)
1239 #endif
1240 word->flags |= W_NOSPLIT;
1241 + word->flags |= W_NOSPLIT2;
1242 result = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
1243 expand_no_split_dollar_star = 0;
1245 @@ -5798,6 +5809,16 @@
1246 is the only expansion that creates more than one word. */
1247 if (qdollaratp && ((hasdol && quoted) || l->next))
1248 *qdollaratp = 1;
1249 + /* If we have a quoted null result (QUOTED_NULL(temp)) and the word is
1250 + a quoted null (l->next == 0 && QUOTED_NULL(l->word->word)), the
1251 + flags indicate it (l->word->flags & W_HASQUOTEDNULL), and the
1252 + expansion is quoted (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
1253 + (which is more paranoia than anything else), we need to return the
1254 + quoted null string and set the flags to indicate it. */
1255 + if (l->next == 0 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && QUOTED_NULL(temp) && QUOTED_NULL(l->word->word) && (l->word->flags & W_HASQUOTEDNULL))
1256 + {
1257 + w->flags |= W_HASQUOTEDNULL;
1258 + }
1259 dispose_words (l);
1260 }
1261 else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && hasdol)
1262 @@ -7176,7 +7197,7 @@
1263 {
1264 /* Extract the contents of the ${ ... } expansion
1265 according to the Posix.2 rules. */
1266 - value = extract_dollar_brace_string (string, &sindex, quoted, (c == '%' || c == '#') ? SX_POSIXEXP : 0);
1267 + value = extract_dollar_brace_string (string, &sindex, quoted, (c == '%' || c == '#' || c =='/' || c == '^' || c == ',' || c ==':') ? SX_POSIXEXP|SX_WORD : SX_WORD);
1268 if (string[sindex] == RBRACE)
1269 sindex++;
1270 else
1271 @@ -7268,6 +7289,7 @@
1272 default:
1273 case '\0':
1274 bad_substitution:
1275 + last_command_exit_value = EXECUTION_FAILURE;
1276 report_error (_("%s: bad substitution"), string ? string : "??");
1277 FREE (value);
1278 FREE (temp);
1279 Index: subst.h
1280 --- subst.h.orig 2010-12-03 02:21:29.000000000 +0100
1281 +++ subst.h 2012-06-27 10:31:02.000000000 +0200
1282 @@ -56,6 +56,7 @@
1283 #define SX_NOLONGJMP 0x0040 /* don't longjmp on fatal error */
1284 #define SX_ARITHSUB 0x0080 /* extracting $(( ... )) (currently unused) */
1285 #define SX_POSIXEXP 0x0100 /* extracting new Posix pattern removal expansions in extract_dollar_brace_string */
1286 +#define SX_WORD 0x0200 /* extracting word in ${param op word} */
1288 /* Remove backslashes which are quoting backquotes from STRING. Modifies
1289 STRING, and returns a pointer to it. */
1290 Index: support/shobj-conf
1291 --- support/shobj-conf.orig 2009-10-28 14:20:21.000000000 +0100
1292 +++ support/shobj-conf 2012-06-27 10:31:02.000000000 +0200
1293 @@ -157,7 +157,7 @@
1294 ;;
1296 # Darwin/MacOS X
1297 -darwin[89]*|darwin10*)
1298 +darwin[89]*|darwin1[012]*)
1299 SHOBJ_STATUS=supported
1300 SHLIB_STATUS=supported
1302 @@ -186,7 +186,7 @@
1303 SHLIB_LIBSUFF='dylib'
1305 case "${host_os}" in
1306 - darwin[789]*|darwin10*) SHOBJ_LDFLAGS=''
1307 + darwin[789]*|darwin1[012]*) SHOBJ_LDFLAGS=''
1308 SHLIB_XLDFLAGS='-dynamiclib -arch_only `/usr/bin/arch` -install_name $(libdir)/$@ -current_version $(SHLIB_MAJOR)$(SHLIB_MINOR) -compatibility_version $(SHLIB_MAJOR) -v'
1309 ;;
1310 *) SHOBJ_LDFLAGS='-dynamic'
1311 Index: tests/shopt.right
1312 --- tests/shopt.right.orig 2010-07-03 05:36:30.000000000 +0200
1313 +++ tests/shopt.right 2012-06-27 10:31:03.000000000 +0200
1314 @@ -12,6 +12,7 @@
1315 shopt -u compat32
1316 shopt -u compat40
1317 shopt -u compat41
1318 +shopt -u direxpand
1319 shopt -u dirspell
1320 shopt -u dotglob
1321 shopt -u execfail
1322 @@ -68,6 +69,7 @@
1323 shopt -u compat32
1324 shopt -u compat40
1325 shopt -u compat41
1326 +shopt -u direxpand
1327 shopt -u dirspell
1328 shopt -u dotglob
1329 shopt -u execfail
1330 @@ -101,6 +103,7 @@
1331 compat32 off
1332 compat40 off
1333 compat41 off
1334 +direxpand off
1335 dirspell off
1336 dotglob off
1337 execfail off
1338 Index: variables.c
1339 --- variables.c.orig 2011-01-25 02:07:48.000000000 +0100
1340 +++ variables.c 2012-06-27 10:31:02.000000000 +0200
1341 @@ -3653,6 +3653,22 @@
1342 return n;
1343 }
1345 +int
1346 +chkexport (name)
1347 + char *name;
1348 +{
1349 + SHELL_VAR *v;
1350 +
1351 + v = find_variable (name);
1352 + if (v && exported_p (v))
1353 + {
1354 + array_needs_making = 1;
1355 + maybe_make_export_env ();
1356 + return 1;
1357 + }
1358 + return 0;
1359 +}
1360 +
1361 void
1362 maybe_make_export_env ()
1363 {
1364 @@ -4214,7 +4230,7 @@
1365 { "TEXTDOMAIN", sv_locale },
1366 { "TEXTDOMAINDIR", sv_locale },
1368 -#if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
1369 +#if defined (HAVE_TZSET)
1370 { "TZ", sv_tz },
1371 #endif
1373 @@ -4558,12 +4574,13 @@
1374 }
1375 #endif /* HISTORY */
1377 -#if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
1378 +#if defined (HAVE_TZSET)
1379 void
1380 sv_tz (name)
1381 char *name;
1382 {
1383 - tzset ();
1384 + if (chkexport (name))
1385 + tzset ();
1386 }
1387 #endif
1389 Index: variables.h
1390 --- variables.h.orig 2010-12-03 02:22:01.000000000 +0100
1391 +++ variables.h 2012-06-27 10:31:02.000000000 +0200
1392 @@ -313,6 +313,7 @@
1394 extern void sort_variables __P((SHELL_VAR **));
1396 +extern int chkexport __P((char *));
1397 extern void maybe_make_export_env __P((void));
1398 extern void update_export_env_inplace __P((char *, int, char *));
1399 extern void put_command_name_into_env __P((char *));
1400 Index: y.tab.c
1401 --- y.tab.c.orig 2011-01-04 15:57:56.000000000 +0100
1402 +++ y.tab.c 2012-06-27 10:31:03.000000000 +0200
1403 @@ -4811,7 +4811,7 @@
1404 We do this only if it is time to do so. Notice that only here
1405 is the mail alarm reset; nothing takes place in check_mail ()
1406 except the checking of mail. Please don't change this. */
1407 - if (prompt_is_ps1 && time_to_check_mail ())
1408 + if (prompt_is_ps1 && parse_and_execute_level == 0 && time_to_check_mail ())
1409 {
1410 check_mail ();
1411 reset_mail_timer ();
1412 @@ -6154,6 +6154,7 @@
1413 int flags;
1414 {
1415 sh_parser_state_t ps;
1416 + sh_input_line_state_t ls;
1417 int orig_ind, nc, sflags;
1418 char *ret, *s, *ep, *ostring;
1420 @@ -6161,10 +6162,12 @@
1421 orig_ind = *indp;
1422 ostring = string;
1424 +/*itrace("xparse_dolparen: size = %d shell_input_line = `%s'", shell_input_line_size, shell_input_line);*/
1425 sflags = SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOFREE;
1426 if (flags & SX_NOLONGJMP)
1427 sflags |= SEVAL_NOLONGJMP;
1428 save_parser_state (&ps);
1429 + save_input_line_state (&ls);
1431 /*(*/
1432 parser_state |= PST_CMDSUBST|PST_EOFTOKEN; /* allow instant ')' */ /*(*/
1433 @@ -6173,6 +6176,8 @@
1435 restore_parser_state (&ps);
1436 reset_parser ();
1437 + /* reset_parser clears shell_input_line and associated variables */
1438 + restore_input_line_state (&ls);
1439 if (interactive)
1440 token_to_read = 0;
1442 @@ -7447,6 +7452,9 @@
1443 case 'A':
1444 /* Make the current time/date into a string. */
1445 (void) time (&the_time);
1446 +#if defined (HAVE_TZSET)
1447 + sv_tz ("TZ"); /* XXX -- just make sure */
1448 +#endif
1449 tm = localtime (&the_time);
1451 if (c == 'd')
1452 @@ -8217,6 +8225,12 @@
1453 ps->expand_aliases = expand_aliases;
1454 ps->echo_input_at_read = echo_input_at_read;
1456 + ps->token = token;
1457 + ps->token_buffer_size = token_buffer_size;
1458 + /* Force reallocation on next call to read_token_word */
1459 + token = 0;
1460 + token_buffer_size = 0;
1461 +
1462 return (ps);
1463 }
1465 @@ -8258,6 +8272,42 @@
1467 expand_aliases = ps->expand_aliases;
1468 echo_input_at_read = ps->echo_input_at_read;
1469 +
1470 + FREE (token);
1471 + token = ps->token;
1472 + token_buffer_size = ps->token_buffer_size;
1473 +}
1474 +
1475 +sh_input_line_state_t *
1476 +save_input_line_state (ls)
1477 + sh_input_line_state_t *ls;
1478 +{
1479 + if (ls == 0)
1480 + ls = (sh_input_line_state_t *)xmalloc (sizeof (sh_input_line_state_t));
1481 + if (ls == 0)
1482 + return ((sh_input_line_state_t *)NULL);
1483 +
1484 + ls->input_line = shell_input_line;
1485 + ls->input_line_size = shell_input_line_size;
1486 + ls->input_line_len = shell_input_line_len;
1487 + ls->input_line_index = shell_input_line_index;
1488 +
1489 + /* force reallocation */
1490 + shell_input_line = 0;
1491 + shell_input_line_size = shell_input_line_len = shell_input_line_index = 0;
1492 +}
1493 +
1494 +void
1495 +restore_input_line_state (ls)
1496 + sh_input_line_state_t *ls;
1497 +{
1498 + FREE (shell_input_line);
1499 + shell_input_line = ls->input_line;
1500 + shell_input_line_size = ls->input_line_size;
1501 + shell_input_line_len = ls->input_line_len;
1502 + shell_input_line_index = ls->input_line_index;
1503 +
1504 + set_line_mbstate ();
1505 }
1507 /************************************************