neovim/neovim — pull request #1141 by splinterofchaos (2014-09-06 15:41:18+00:00)
Title: [RFC] vim-patch:7.4.247 + vim-patch:7.4.248 + vim-patch:7.4.256 + f_system() bug fix

The first few commits come from a branch I based this and #1134 off of--some utility functions.

[247](https://code.google.com/p/vim/source/detail?r=v7-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)

Factors `write_list()` out of `f_writefile()`. I think it would do more but we removed `EBCDIC` support.

.
[248](https://code.google.com/p/vim/source/detail?r=v7-4-248):

> Problem: Cannot distinguish between NL and NUL in output of system().

>Solution: Add systemlist(). (ZyX)

It seems we at one point factored `get_cmd_output_as_rettv()` into `f_system()`, but I had to re-add it, this time as `get_system_output_as_rettv()`. Includes some changes to `get_cmd_output()`, even though I didn't use it to implement `systemlist()`.

.
[256](https://code.google.com/p/vim/source/detail?r=v7-4-256):

>Problem: Using systemlist() may cause a crash and does not handle NUL characters properly.

>Solution: Increase the reference count, allocate memory by length. (Yasuhiro Matsumoto)

I tracked down the [original discussion](https://groups.google.com/forum/#!topic/vim_dev/KFfZhNDSXxk) on this to explain why the move from `vim_strnsave` to a manual loop.

> STRCPY/STRNCPY doesn't copy bytes after 0x00.

.
=
Bugfix: None of these patches included a test, and testing with NUL can be kinda tricky, so I wrote a small program:

```c
#include

int main() {
char buf[] = "a\0b\1c\nd\2e\nfg";
return fwrite(buf, sizeof buf, 1, stdout) == 1;
}
```

Running `:echo systemlist('./a.out')` will produce
```
['a
b^Ac', 'd^Be', 'fg
']
```
*(The extra newline is because in writing `sizeof buf`, the ending '\0' is included.)*

And I verified this behaviour with vanilla vim as well. However, `:echo system('./a.out')` should produce
```
a^Ab^Ac
d^Be
fg^A
```
and neovim just prints `a` because it thinks the string ends at the second char. `os_system` has an out-parameter, `nread`, which we don't actually use because we assume all string end in `NUL`. The fix is to convert all `NUL`s that happend *before* `res + nread` to `SOH`.

I wanted to submit the bug fix as a separate PR, but since I had to modify the code around it, it seemed simpler to put it in here.