# HG changeset patch # User Bram Moolenaar # Date 1396716946 -7200 # Node ID 76863b4b48a3684905527dcc688e5a8c4c5e23d9 # Parent 2db11543541add8963c12135394630d086352628 updated for version 7.4.247 Problem: When passing input to system() there is no way to keep NUL and NL characters separate. Solution: Optionally use a list for the system() input. (ZyX) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -5964,10 +5964,17 @@ synstack({lnum}, {col}) *synstack()* system({expr} [, {input}]) *system()* *E677* Get the output of the shell command {expr}. - When {input} is given, this string is written to a file and - passed as stdin to the command. The string is written as-is, - you need to take care of using the correct line separators - yourself. Pipes are not used. + + When {input} is given and is a string this string is written + to a file and passed as stdin to the command. The string is + written as-is, you need to take care of using the correct line + separators yourself. + If {input} is given and is a |List| it is written to the file + in a way |writefile()| does with {binary} set to "b" (i.e. + with a newline between each list item with newlines inside + list items converted to NULs). + Pipes are not used. + Note: Use |shellescape()| or |::S| with |expand()| or |fnamemodify()| to escape special characters in a command argument. Newlines in {expr} may cause the command to fail. diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -836,6 +836,7 @@ static void getwinvar __ARGS((typval_T * static int searchpair_cmn __ARGS((typval_T *argvars, pos_T *match_pos)); static int search_cmn __ARGS((typval_T *argvars, pos_T *match_pos, int *flagsp)); static void setwinvar __ARGS((typval_T *argvars, typval_T *rettv, int off)); +static int write_list __ARGS((FILE *fd, list_T *list, int binary)); #ifdef EBCDIC @@ -18267,14 +18268,22 @@ f_system(argvars, rettv) EMSG2(_(e_notopen), infile); goto done; } - p = get_tv_string_buf_chk(&argvars[1], buf); - if (p == NULL) - { - fclose(fd); - goto done; /* type error; errmsg already given */ - } - if (fwrite(p, STRLEN(p), 1, fd) != 1) - err = TRUE; + if (argvars[1].v_type == VAR_LIST) + { + if (write_list(fd, argvars[1].vval.v_list, TRUE) == FAIL) + err = TRUE; + } + else + { + p = get_tv_string_buf_chk(&argvars[1], buf); + if (p == NULL) + { + fclose(fd); + goto done; /* type error; errmsg already given */ + } + if (fwrite(p, STRLEN(p), 1, fd) != 1) + err = TRUE; + } if (fclose(fd) != 0) err = TRUE; if (err) @@ -19173,6 +19182,49 @@ f_winwidth(argvars, rettv) } /* + * Write list of strings to file + */ + static int +write_list(fd, list, binary) + FILE *fd; + list_T *list; + int binary; +{ + listitem_T *li; + int c; + int ret = OK; + char_u *s; + + for (li = list->lv_first; li != NULL; li = li->li_next) + { + for (s = get_tv_string(&li->li_tv); *s != NUL; ++s) + { + if (*s == '\n') + c = putc(NUL, fd); + else + c = putc(*s, fd); + if (c == EOF) + { + ret = FAIL; + break; + } + } + if (!binary || li->li_next != NULL) + if (putc('\n', fd) == EOF) + { + ret = FAIL; + break; + } + if (ret == FAIL) + { + EMSG(_(e_write)); + break; + } + } + return ret; +} + +/* * "writefile()" function */ static void @@ -19183,10 +19235,7 @@ f_writefile(argvars, rettv) int binary = FALSE; char_u *fname; FILE *fd; - listitem_T *li; - char_u *s; int ret = 0; - int c; if (check_restricted() || check_secure()) return; @@ -19213,33 +19262,8 @@ f_writefile(argvars, rettv) } else { - for (li = argvars[0].vval.v_list->lv_first; li != NULL; - li = li->li_next) - { - for (s = get_tv_string(&li->li_tv); *s != NUL; ++s) - { - if (*s == '\n') - c = putc(NUL, fd); - else - c = putc(*s, fd); - if (c == EOF) - { - ret = -1; - break; - } - } - if (!binary || li->li_next != NULL) - if (putc('\n', fd) == EOF) - { - ret = -1; - break; - } - if (ret < 0) - { - EMSG(_(e_write)); - break; - } - } + if (write_list(fd, argvars[0].vval.v_list, binary) == FAIL) + ret = -1; fclose(fd); } diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -735,6 +735,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 247, +/**/ 246, /**/ 245,