To: vim-dev@vim.org Subject: Patch 7.1.223 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit ------------ Patch 7.1.223 Problem: glob() doesn't work properly when 'shell' is "sh" or "bash" and the expanded name contains spaces, '~', single quotes and other special characters. (Adri Verhoef, Charles Campbell) Solution: For Posix shells define a vimglob() function to list the matches instead of using "echo" directly. Files: src/os_unix.c *** ../vim-7.1.222/src/os_unix.c Thu Jan 3 18:55:21 2008 --- src/os_unix.c Sun Jan 13 13:52:53 2008 *************** *** 4946,4951 **** --- 4946,4954 ---- char_u *p; int dir; #ifdef __EMX__ + /* + * This is the OS/2 implementation. + */ # define EXPL_ALLOC_INC 16 char_u **expl_files; size_t files_alloced, files_free; *************** *** 5056,5075 **** return OK; #else /* __EMX__ */ ! int j; char_u *tempname; char_u *command; FILE *fd; char_u *buffer; ! #define STYLE_ECHO 0 /* use "echo" to expand */ ! #define STYLE_GLOB 1 /* use "glob" to expand, for csh */ ! #define STYLE_PRINT 2 /* use "print -N" to expand, for zsh */ ! #define STYLE_BT 3 /* `cmd` expansion, execute the pattern directly */ int shell_style = STYLE_ECHO; int check_spaces; static int did_find_nul = FALSE; int ampersent = FALSE; *num_file = 0; /* default: no files found */ *file = NULL; --- 5059,5084 ---- return OK; #else /* __EMX__ */ ! /* ! * This is the non-OS/2 implementation (really Unix). ! */ int j; char_u *tempname; char_u *command; FILE *fd; char_u *buffer; ! #define STYLE_ECHO 0 /* use "echo", the default */ ! #define STYLE_GLOB 1 /* use "glob", for csh */ ! #define STYLE_VIMGLOB 2 /* use "vimglob", for Posix sh */ ! #define STYLE_PRINT 3 /* use "print -N", for zsh */ ! #define STYLE_BT 4 /* `cmd` expansion, execute the pattern ! * directly */ int shell_style = STYLE_ECHO; int check_spaces; static int did_find_nul = FALSE; int ampersent = FALSE; + /* vimglob() function to define for Posix shell */ + static char *sh_vimglob_func = "vimglob() { while [ $# -ge 1 ]; do echo -n \"$1\"; echo; shift; done }; vimglob >"; *num_file = 0; /* default: no files found */ *file = NULL; *************** *** 5107,5115 **** /* * Let the shell expand the patterns and write the result into the temp ! * file. if expanding `cmd` execute it directly. ! * If we use csh, glob will work better than echo. ! * If we use zsh, print -N will work better than glob. */ if (num_pat == 1 && *pat[0] == '`' && (len = STRLEN(pat[0])) > 2 --- 5116,5132 ---- /* * Let the shell expand the patterns and write the result into the temp ! * file. ! * STYLE_BT: NL separated ! * If expanding `cmd` execute it directly. ! * STYLE_GLOB: NUL separated ! * If we use *csh, "glob" will work better than "echo". ! * STYLE_PRINT: NL or NUL separated ! * If we use *zsh, "print -N" will work better than "glob". ! * STYLE_VIMGLOB: NL separated ! * If we use *sh*, we define "vimglob()". ! * STYLE_ECHO: space separated. ! * A shell we don't know, stay safe and use "echo". */ if (num_pat == 1 && *pat[0] == '`' && (len = STRLEN(pat[0])) > 2 *************** *** 5122,5130 **** else if (STRCMP(p_sh + len - 3, "zsh") == 0) shell_style = STYLE_PRINT; } ! ! /* "unset nonomatch; print -N >" plus two is 29 */ len = STRLEN(tempname) + 29; for (i = 0; i < num_pat; ++i) { /* Count the length of the patterns in the same way as they are put in --- 5139,5155 ---- else if (STRCMP(p_sh + len - 3, "zsh") == 0) shell_style = STYLE_PRINT; } ! if (shell_style == STYLE_ECHO && strstr((char *)gettail(p_sh), ! "sh") != NULL) ! shell_style = STYLE_VIMGLOB; ! ! /* Compute the length of the command. We need 2 extra bytes: for the ! * optional '&' and for the NUL. ! * Worst case: "unset nonomatch; print -N >" plus two is 29 */ len = STRLEN(tempname) + 29; + if (shell_style == STYLE_VIMGLOB) + len += STRLEN(sh_vimglob_func); + for (i = 0; i < num_pat; ++i) { /* Count the length of the patterns in the same way as they are put in *************** *** 5183,5192 **** --- 5208,5221 ---- STRCAT(command, "glob >"); else if (shell_style == STYLE_PRINT) STRCAT(command, "print -N >"); + else if (shell_style == STYLE_VIMGLOB) + STRCAT(command, sh_vimglob_func); else STRCAT(command, "echo >"); } + STRCAT(command, tempname); + if (shell_style != STYLE_BT) for (i = 0; i < num_pat; ++i) { *************** *** 5232,5239 **** if (flags & EW_SILENT) show_shell_mess = FALSE; if (ampersent) ! STRCAT(command, "&"); /* put the '&' back after the ! redirection */ /* * Using zsh -G: If a pattern has no matches, it is just deleted from --- 5261,5267 ---- if (flags & EW_SILENT) show_shell_mess = FALSE; if (ampersent) ! STRCAT(command, "&"); /* put the '&' after the redirection */ /* * Using zsh -G: If a pattern has no matches, it is just deleted from *************** *** 5265,5271 **** show_shell_mess = TRUE; vim_free(command); ! if (i) /* mch_call_shell() failed */ { mch_remove(tempname); vim_free(tempname); --- 5293,5299 ---- show_shell_mess = TRUE; vim_free(command); ! if (i != 0) /* mch_call_shell() failed */ { mch_remove(tempname); vim_free(tempname); *************** *** 5336,5342 **** } vim_free(tempname); ! #if defined(__CYGWIN__) || defined(__CYGWIN32__) /* Translate into . Caution, buffer may contain NUL. */ p = buffer; for (i = 0; i < len; ++i) --- 5364,5370 ---- } vim_free(tempname); ! # if defined(__CYGWIN__) || defined(__CYGWIN32__) /* Translate into . Caution, buffer may contain NUL. */ p = buffer; for (i = 0; i < len; ++i) *************** *** 5359,5365 **** } } /* file names are separated with NL */ ! else if (shell_style == STYLE_BT) { buffer[len] = NUL; /* make sure the buffer ends in NUL */ p = buffer; --- 5387,5393 ---- } } /* file names are separated with NL */ ! else if (shell_style == STYLE_BT || shell_style == STYLE_VIMGLOB) { buffer[len] = NUL; /* make sure the buffer ends in NUL */ p = buffer; *************** *** 5438,5444 **** { (*file)[i] = p; /* Space or NL separates */ ! if (shell_style == STYLE_ECHO || shell_style == STYLE_BT) { while (!(shell_style == STYLE_ECHO && *p == ' ') && *p != '\n' && *p != NUL) --- 5466,5473 ---- { (*file)[i] = p; /* Space or NL separates */ ! if (shell_style == STYLE_ECHO || shell_style == STYLE_BT ! || shell_style == STYLE_VIMGLOB) { while (!(shell_style == STYLE_ECHO && *p == ' ') && *p != '\n' && *p != NUL) *** ../vim-7.1.222/src/version.c Sun Jan 13 13:30:34 2008 --- src/version.c Sun Jan 13 13:45:04 2008 *************** *** 668,669 **** --- 668,671 ---- { /* Add new patch number below this line */ + /**/ + 223, /**/ -- User: I'm having problems with my text editor. Help desk: Which editor are you using? User: I don't know, but it's version VI (pronounced: 6). Help desk: Oh, then you should upgrade to version VIM (pronounced: 994). /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ download, build and distribute -- http://www.A-A-P.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///