bash-4.2-029.patch 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. BASH PATCH REPORT
  2. =================
  3. Bash-Release: 4.2
  4. Patch-ID: bash42-029
  5. Bug-Reported-by: "Michael Kalisz" <michael@kalisz.homelinux.net>
  6. Bug-Reference-ID: <50241.78.69.11.112.1298585641.squirrel@kalisz.homelinux.net>
  7. Bug-Reference-URL: http://lists.gnu.org/archive/html/bug-bash/2011-02/msg00274.html
  8. Bug-Description:
  9. Bash-4.2 tries to leave completed directory names as the user typed them,
  10. without expanding them to a full pathname. One effect of this is that
  11. shell variables used in pathnames being completed (e.g., $HOME) are left
  12. unchanged, but the `$' is quoted by readline because it is a special
  13. character to the shell.
  14. This patch introduces two things:
  15. 1. A new shell option, `direxpand', which, if set, attempts to emulate the
  16. bash-4.1 behavior of expanding words to full pathnames during
  17. completion;
  18. 2. A set of heuristics that reduce the number of times special characters
  19. such as `$' are quoted when the directory name is not expanded.
  20. Patch (apply with `patch -p0'):
  21. diff -NrC 2 ../bash-4.2-patched/bashline.c ./bashline.c
  22. *** ../bash-4.2-patched/bashline.c 2011-01-16 15:32:47.000000000 -0500
  23. --- ./bashline.c 2012-05-07 16:27:18.000000000 -0400
  24. ***************
  25. *** 122,125 ****
  26. --- 122,128 ----
  27. static int bash_push_line __P((void));
  28. + static rl_icppfunc_t *save_directory_hook __P((void));
  29. + static void reset_directory_hook __P((rl_icppfunc_t *));
  30. +
  31. static void cleanup_expansion_error __P((void));
  32. static void maybe_make_readline_line __P((char *));
  33. ***************
  34. *** 244,251 ****
  35. --- 247,261 ----
  36. int dircomplete_spelling = 0;
  37. + /* Expand directory names during word/filename completion. */
  38. + int dircomplete_expand = 0;
  39. + int dircomplete_expand_relpath = 0;
  40. +
  41. static char *bash_completer_word_break_characters = " \t\n\"'@><=;|&(:";
  42. static char *bash_nohostname_word_break_characters = " \t\n\"'><=;|&(:";
  43. /* )) */
  44. + static const char *default_filename_quote_characters = " \t\n\\\"'@<>=;|&()#$`?*[!:{~"; /*}*/
  45. + static char *custom_filename_quote_characters = 0;
  46. +
  47. static rl_hook_func_t *old_rl_startup_hook = (rl_hook_func_t *)NULL;
  48. ***************
  49. *** 502,506 ****
  50. /* Tell the completer that we might want to follow symbolic links or
  51. do other expansion on directory names. */
  52. ! rl_directory_rewrite_hook = bash_directory_completion_hook;
  53. rl_filename_rewrite_hook = bash_filename_rewrite_hook;
  54. --- 512,516 ----
  55. /* Tell the completer that we might want to follow symbolic links or
  56. do other expansion on directory names. */
  57. ! set_directory_hook ();
  58. rl_filename_rewrite_hook = bash_filename_rewrite_hook;
  59. ***************
  60. *** 530,534 ****
  61. /* characters that need to be quoted when appearing in filenames. */
  62. ! rl_filename_quote_characters = " \t\n\\\"'@<>=;|&()#$`?*[!:{~"; /*}*/
  63. rl_filename_quoting_function = bash_quote_filename;
  64. --- 540,544 ----
  65. /* characters that need to be quoted when appearing in filenames. */
  66. ! rl_filename_quote_characters = default_filename_quote_characters;
  67. rl_filename_quoting_function = bash_quote_filename;
  68. ***************
  69. *** 565,570 ****
  70. rl_attempted_completion_function = attempt_shell_completion;
  71. rl_completion_entry_function = NULL;
  72. - rl_directory_rewrite_hook = bash_directory_completion_hook;
  73. rl_ignore_some_completions_function = filename_completion_ignore;
  74. }
  75. --- 575,582 ----
  76. rl_attempted_completion_function = attempt_shell_completion;
  77. rl_completion_entry_function = NULL;
  78. rl_ignore_some_completions_function = filename_completion_ignore;
  79. + rl_filename_quote_characters = default_filename_quote_characters;
  80. +
  81. + set_directory_hook ();
  82. }
  83. ***************
  84. *** 1280,1283 ****
  85. --- 1292,1298 ----
  86. rl_ignore_some_completions_function = filename_completion_ignore;
  87. + rl_filename_quote_characters = default_filename_quote_characters;
  88. + set_directory_hook ();
  89. +
  90. /* Determine if this could be a command word. It is if it appears at
  91. the start of the line (ignoring preceding whitespace), or if it
  92. ***************
  93. *** 1592,1595 ****
  94. --- 1607,1616 ----
  95. else
  96. {
  97. + if (dircomplete_expand && dot_or_dotdot (filename_hint))
  98. + {
  99. + dircomplete_expand = 0;
  100. + set_directory_hook ();
  101. + dircomplete_expand = 1;
  102. + }
  103. mapping_over = 4;
  104. goto inner;
  105. ***************
  106. *** 1792,1795 ****
  107. --- 1813,1819 ----
  108. inner:
  109. val = rl_filename_completion_function (filename_hint, istate);
  110. + if (mapping_over == 4 && dircomplete_expand)
  111. + set_directory_hook ();
  112. +
  113. istate = 1;
  114. ***************
  115. *** 2694,2697 ****
  116. --- 2718,2767 ----
  117. }
  118. + /* Functions to save and restore the appropriate directory hook */
  119. + /* This is not static so the shopt code can call it */
  120. + void
  121. + set_directory_hook ()
  122. + {
  123. + if (dircomplete_expand)
  124. + {
  125. + rl_directory_completion_hook = bash_directory_completion_hook;
  126. + rl_directory_rewrite_hook = (rl_icppfunc_t *)0;
  127. + }
  128. + else
  129. + {
  130. + rl_directory_rewrite_hook = bash_directory_completion_hook;
  131. + rl_directory_completion_hook = (rl_icppfunc_t *)0;
  132. + }
  133. + }
  134. +
  135. + static rl_icppfunc_t *
  136. + save_directory_hook ()
  137. + {
  138. + rl_icppfunc_t *ret;
  139. +
  140. + if (dircomplete_expand)
  141. + {
  142. + ret = rl_directory_completion_hook;
  143. + rl_directory_completion_hook = (rl_icppfunc_t *)NULL;
  144. + }
  145. + else
  146. + {
  147. + ret = rl_directory_rewrite_hook;
  148. + rl_directory_rewrite_hook = (rl_icppfunc_t *)NULL;
  149. + }
  150. +
  151. + return ret;
  152. + }
  153. +
  154. + static void
  155. + restore_directory_hook (hookf)
  156. + rl_icppfunc_t *hookf;
  157. + {
  158. + if (dircomplete_expand)
  159. + rl_directory_completion_hook = hookf;
  160. + else
  161. + rl_directory_rewrite_hook = hookf;
  162. + }
  163. +
  164. /* Handle symbolic link references and other directory name
  165. expansions while hacking completion. This should return 1 if it modifies
  166. ***************
  167. *** 2703,2720 ****
  168. {
  169. char *local_dirname, *new_dirname, *t;
  170. ! int return_value, should_expand_dirname;
  171. WORD_LIST *wl;
  172. struct stat sb;
  173. ! return_value = should_expand_dirname = 0;
  174. local_dirname = *dirname;
  175. ! if (mbschr (local_dirname, '$'))
  176. ! should_expand_dirname = 1;
  177. else
  178. {
  179. t = mbschr (local_dirname, '`');
  180. if (t && unclosed_pair (local_dirname, strlen (local_dirname), "`") == 0)
  181. ! should_expand_dirname = 1;
  182. }
  183. --- 2773,2801 ----
  184. {
  185. char *local_dirname, *new_dirname, *t;
  186. ! int return_value, should_expand_dirname, nextch, closer;
  187. WORD_LIST *wl;
  188. struct stat sb;
  189. ! return_value = should_expand_dirname = nextch = closer = 0;
  190. local_dirname = *dirname;
  191. ! if (t = mbschr (local_dirname, '$'))
  192. ! {
  193. ! should_expand_dirname = '$';
  194. ! nextch = t[1];
  195. ! /* Deliberately does not handle the deprecated $[...] arithmetic
  196. ! expansion syntax */
  197. ! if (nextch == '(')
  198. ! closer = ')';
  199. ! else if (nextch == '{')
  200. ! closer = '}';
  201. ! else
  202. ! nextch = 0;
  203. ! }
  204. else
  205. {
  206. t = mbschr (local_dirname, '`');
  207. if (t && unclosed_pair (local_dirname, strlen (local_dirname), "`") == 0)
  208. ! should_expand_dirname = '`';
  209. }
  210. ***************
  211. *** 2740,2743 ****
  212. --- 2821,2841 ----
  213. dispose_words (wl);
  214. local_dirname = *dirname;
  215. + /* XXX - change rl_filename_quote_characters here based on
  216. + should_expand_dirname/nextch/closer. This is the only place
  217. + custom_filename_quote_characters is modified. */
  218. + if (rl_filename_quote_characters && *rl_filename_quote_characters)
  219. + {
  220. + int i, j, c;
  221. + i = strlen (default_filename_quote_characters);
  222. + custom_filename_quote_characters = xrealloc (custom_filename_quote_characters, i+1);
  223. + for (i = j = 0; c = default_filename_quote_characters[i]; i++)
  224. + {
  225. + if (c == should_expand_dirname || c == nextch || c == closer)
  226. + continue;
  227. + custom_filename_quote_characters[j++] = c;
  228. + }
  229. + custom_filename_quote_characters[j] = '\0';
  230. + rl_filename_quote_characters = custom_filename_quote_characters;
  231. + }
  232. }
  233. else
  234. ***************
  235. *** 2759,2762 ****
  236. --- 2857,2871 ----
  237. }
  238. + /* no_symbolic_links == 0 -> use (default) logical view of the file system.
  239. + local_dirname[0] == '.' && local_dirname[1] == '/' means files in the
  240. + current directory (./).
  241. + local_dirname[0] == '.' && local_dirname[1] == 0 means relative pathnames
  242. + in the current directory (e.g., lib/sh).
  243. + XXX - should we do spelling correction on these? */
  244. +
  245. + /* This is test as it was in bash-4.2: skip relative pathnames in current
  246. + directory. Change test to
  247. + (local_dirname[0] != '.' || (local_dirname[1] && local_dirname[1] != '/'))
  248. + if we want to skip paths beginning with ./ also. */
  249. if (no_symbolic_links == 0 && (local_dirname[0] != '.' || local_dirname[1]))
  250. {
  251. ***************
  252. *** 2764,2767 ****
  253. --- 2873,2885 ----
  254. int len1, len2;
  255. + /* If we have a relative path
  256. + (local_dirname[0] != '/' && local_dirname[0] != '.')
  257. + that is canonical after appending it to the current directory, then
  258. + temp1 = temp2+'/'
  259. + That is,
  260. + strcmp (temp1, temp2) == 0
  261. + after adding a slash to temp2 below. It should be safe to not
  262. + change those.
  263. + */
  264. t = get_working_directory ("symlink-hook");
  265. temp1 = make_absolute (local_dirname, t);
  266. ***************
  267. *** 2798,2802 ****
  268. }
  269. }
  270. ! return_value |= STREQ (local_dirname, temp2) == 0;
  271. free (local_dirname);
  272. *dirname = temp2;
  273. --- 2916,2928 ----
  274. }
  275. }
  276. !
  277. ! /* dircomplete_expand_relpath == 0 means we want to leave relative
  278. ! pathnames that are unchanged by canonicalization alone.
  279. ! *local_dirname != '/' && *local_dirname != '.' == relative pathname
  280. ! (consistent with general.c:absolute_pathname())
  281. ! temp1 == temp2 (after appending a slash to temp2) means the pathname
  282. ! is not changed by canonicalization as described above. */
  283. ! if (dircomplete_expand_relpath || ((local_dirname[0] != '/' && local_dirname[0] != '.') && STREQ (temp1, temp2) == 0))
  284. ! return_value |= STREQ (local_dirname, temp2) == 0;
  285. free (local_dirname);
  286. *dirname = temp2;
  287. ***************
  288. *** 3003,3012 ****
  289. orig_func = rl_completion_entry_function;
  290. orig_attempt_func = rl_attempted_completion_function;
  291. - orig_dir_func = rl_directory_rewrite_hook;
  292. orig_ignore_func = rl_ignore_some_completions_function;
  293. orig_rl_completer_word_break_characters = rl_completer_word_break_characters;
  294. rl_completion_entry_function = rl_filename_completion_function;
  295. rl_attempted_completion_function = (rl_completion_func_t *)NULL;
  296. - rl_directory_rewrite_hook = (rl_icppfunc_t *)NULL;
  297. rl_ignore_some_completions_function = filename_completion_ignore;
  298. rl_completer_word_break_characters = " \t\n\"\'";
  299. --- 3129,3139 ----
  300. orig_func = rl_completion_entry_function;
  301. orig_attempt_func = rl_attempted_completion_function;
  302. orig_ignore_func = rl_ignore_some_completions_function;
  303. orig_rl_completer_word_break_characters = rl_completer_word_break_characters;
  304. +
  305. + orig_dir_func = save_directory_hook ();
  306. +
  307. rl_completion_entry_function = rl_filename_completion_function;
  308. rl_attempted_completion_function = (rl_completion_func_t *)NULL;
  309. rl_ignore_some_completions_function = filename_completion_ignore;
  310. rl_completer_word_break_characters = " \t\n\"\'";
  311. ***************
  312. *** 3016,3023 ****
  313. rl_completion_entry_function = orig_func;
  314. rl_attempted_completion_function = orig_attempt_func;
  315. - rl_directory_rewrite_hook = orig_dir_func;
  316. rl_ignore_some_completions_function = orig_ignore_func;
  317. rl_completer_word_break_characters = orig_rl_completer_word_break_characters;
  318. return r;
  319. }
  320. --- 3143,3151 ----
  321. rl_completion_entry_function = orig_func;
  322. rl_attempted_completion_function = orig_attempt_func;
  323. rl_ignore_some_completions_function = orig_ignore_func;
  324. rl_completer_word_break_characters = orig_rl_completer_word_break_characters;
  325. + restore_directory_hook (orig_dir_func);
  326. +
  327. return r;
  328. }
  329. diff -NrC 2 ../bash-4.2-patched/bashline.h ./bashline.h
  330. *** ../bash-4.2-patched/bashline.h 2009-01-04 14:32:22.000000000 -0500
  331. --- ./bashline.h 2012-05-07 16:27:18.000000000 -0400
  332. ***************
  333. *** 34,41 ****
  334. --- 34,46 ----
  335. extern int bash_re_edit __P((char *));
  336. + extern void bashline_set_event_hook __P((void));
  337. + extern void bashline_reset_event_hook __P((void));
  338. +
  339. extern int bind_keyseq_to_unix_command __P((char *));
  340. extern char **bash_default_completion __P((const char *, int, int, int, int));
  341. + void set_directory_hook __P((void));
  342. +
  343. /* Used by programmable completion code. */
  344. extern char *command_word_completion_function __P((const char *, int));
  345. diff -NrC 2 ../bash-4.2-patched/builtins/shopt.def ./builtins/shopt.def
  346. *** ../bash-4.2-patched/builtins/shopt.def 2010-07-02 22:42:44.000000000 -0400
  347. --- ./builtins/shopt.def 2012-05-07 16:27:18.000000000 -0400
  348. ***************
  349. *** 62,65 ****
  350. --- 62,69 ----
  351. #include "bashgetopt.h"
  352. + #if defined (READLINE)
  353. + # include "../bashline.h"
  354. + #endif
  355. +
  356. #if defined (HISTORY)
  357. # include "../bashhist.h"
  358. ***************
  359. *** 95,99 ****
  360. extern int no_empty_command_completion;
  361. extern int force_fignore;
  362. ! extern int dircomplete_spelling;
  363. extern int enable_hostname_completion __P((int));
  364. --- 99,103 ----
  365. extern int no_empty_command_completion;
  366. extern int force_fignore;
  367. ! extern int dircomplete_spelling, dircomplete_expand;
  368. extern int enable_hostname_completion __P((int));
  369. ***************
  370. *** 122,125 ****
  371. --- 126,133 ----
  372. #endif
  373. + #if defined (READLINE)
  374. + static int shopt_set_complete_direxpand __P((char *, int));
  375. + #endif
  376. +
  377. static int shopt_login_shell;
  378. static int shopt_compat31;
  379. ***************
  380. *** 151,154 ****
  381. --- 159,163 ----
  382. { "compat41", &shopt_compat41, set_compatibility_level },
  383. #if defined (READLINE)
  384. + { "direxpand", &dircomplete_expand, shopt_set_complete_direxpand },
  385. { "dirspell", &dircomplete_spelling, (shopt_set_func_t *)NULL },
  386. #endif
  387. ***************
  388. *** 536,539 ****
  389. --- 545,559 ----
  390. }
  391. + #if defined (READLINE)
  392. + static int
  393. + shopt_set_complete_direxpand (option_name, mode)
  394. + char *option_name;
  395. + int mode;
  396. + {
  397. + set_directory_hook ();
  398. + return 0;
  399. + }
  400. + #endif
  401. +
  402. #if defined (RESTRICTED_SHELL)
  403. /* Don't allow the value of restricted_shell to be modified. */
  404. Binary files ../bash-4.2-patched/doc/._bashref.pdf and ./doc/._bashref.pdf differ
  405. diff -NrC 2 ../bash-4.2-patched/doc/bash.1 ./doc/bash.1
  406. *** ../bash-4.2-patched/doc/bash.1 2011-01-16 15:31:39.000000000 -0500
  407. --- ./doc/bash.1 2012-05-07 16:27:18.000000000 -0400
  408. ***************
  409. *** 8949,8952 ****
  410. --- 8949,8962 ----
  411. The default bash behavior remains as in previous versions.
  412. .TP 8
  413. + .B direxpand
  414. + If set,
  415. + .B bash
  416. + replaces directory names with the results of word expansion when performing
  417. + filename completion. This changes the contents of the readline editing
  418. + buffer.
  419. + If not set,
  420. + .B bash
  421. + attempts to preserve what the user typed.
  422. + .TP 8
  423. .B dirspell
  424. If set,
  425. diff -NrC 2 ../bash-4.2-patched/doc/bashref.texi ./doc/bashref.texi
  426. *** ../bash-4.2-patched/doc/bashref.texi 2011-01-16 15:31:57.000000000 -0500
  427. --- ./doc/bashref.texi 2012-05-07 16:27:18.000000000 -0400
  428. ***************
  429. *** 4536,4539 ****
  430. --- 4536,4546 ----
  431. The default Bash behavior remains as in previous versions.
  432. + @item direxpand
  433. + If set, Bash
  434. + replaces directory names with the results of word expansion when performing
  435. + filename completion. This changes the contents of the readline editing
  436. + buffer.
  437. + If not set, Bash attempts to preserve what the user typed.
  438. +
  439. @item dirspell
  440. If set, Bash
  441. diff -NrC 2 ../bash-4.2-patched/tests/shopt.right ./tests/shopt.right
  442. *** ../bash-4.2-patched/tests/shopt.right 2010-07-02 23:36:30.000000000 -0400
  443. --- ./tests/shopt.right 2012-05-07 16:27:18.000000000 -0400
  444. ***************
  445. *** 13,16 ****
  446. --- 13,17 ----
  447. shopt -u compat40
  448. shopt -u compat41
  449. + shopt -u direxpand
  450. shopt -u dirspell
  451. shopt -u dotglob
  452. ***************
  453. *** 69,72 ****
  454. --- 70,74 ----
  455. shopt -u compat40
  456. shopt -u compat41
  457. + shopt -u direxpand
  458. shopt -u dirspell
  459. shopt -u dotglob
  460. ***************
  461. *** 102,105 ****
  462. --- 104,108 ----
  463. compat40 off
  464. compat41 off
  465. + direxpand off
  466. dirspell off
  467. dotglob off
  468. *** ../bash-4.2-patched/patchlevel.h Sat Jun 12 20:14:48 2010
  469. --- ./patchlevel.h Thu Feb 24 21:41:34 2011
  470. ***************
  471. *** 26,30 ****
  472. looks for to find the patch level (for the sccs version string). */
  473. ! #define PATCHLEVEL 28
  474. #endif /* _PATCHLEVEL_H_ */
  475. --- 26,30 ----
  476. looks for to find the patch level (for the sccs version string). */
  477. ! #define PATCHLEVEL 29
  478. #endif /* _PATCHLEVEL_H_ */