summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/os_unix.c61
-rw-r--r--src/testdir/test_channel.vim91
-rw-r--r--src/testdir/test_channel_pipe.py11
-rw-r--r--src/version.c2
4 files changed, 145 insertions, 20 deletions
diff --git a/src/os_unix.c b/src/os_unix.c
index 565dbd089d..b4921e3f38 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -5046,13 +5046,18 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
int fd_err[2]; /* for stderr */
channel_T *channel = NULL;
int use_file_for_in = options->jo_io[PART_IN] == JIO_FILE;
+ int use_file_for_out = options->jo_io[PART_OUT] == JIO_FILE;
+ int use_file_for_err = options->jo_io[PART_ERR] == JIO_FILE;
int use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT;
/* default is to fail */
job->jv_status = JOB_FAILED;
fd_in[0] = -1;
+ fd_in[1] = -1;
fd_out[0] = -1;
+ fd_out[1] = -1;
fd_err[0] = -1;
+ fd_err[1] = -1;
/* TODO: without the channel feature connect the child to /dev/null? */
/* Open pipes for stdin, stdout, stderr. */
@@ -5069,9 +5074,33 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
}
else if (pipe(fd_in) < 0)
goto failed;
- if (pipe(fd_out) < 0)
+
+ if (use_file_for_out)
+ {
+ char_u *fname = options->jo_io_name[PART_OUT];
+
+ fd_out[1] = mch_open((char *)fname, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (fd_out[1] < 0)
+ {
+ EMSG2(_(e_notopen), fname);
+ goto failed;
+ }
+ }
+ else if (pipe(fd_out) < 0)
goto failed;
- if (!use_out_for_err && pipe(fd_err) < 0)
+
+ if (use_file_for_err)
+ {
+ char_u *fname = options->jo_io_name[PART_ERR];
+
+ fd_err[1] = mch_open((char *)fname, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+ if (fd_err[1] < 0)
+ {
+ EMSG2(_(e_notopen), fname);
+ goto failed;
+ }
+ }
+ else if (!use_out_for_err && pipe(fd_err) < 0)
goto failed;
channel = add_channel();
@@ -5117,14 +5146,16 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
}
else
{
- close(fd_err[0]);
+ if (!use_file_for_err)
+ close(fd_err[0]);
close(2);
ignored = dup(fd_err[1]);
close(fd_err[1]);
}
/* set up stdout for the child */
- close(fd_out[0]);
+ if (!use_file_for_out)
+ close(fd_out[0]);
close(1);
ignored = dup(fd_out[1]);
close(fd_out[1]);
@@ -5148,13 +5179,15 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
/* child stdin, stdout and stderr */
if (!use_file_for_in)
close(fd_in[0]);
- close(fd_out[1]);
- if (!use_out_for_err)
+ if (!use_file_for_out)
+ close(fd_out[1]);
+ if (!use_out_for_err && !use_file_for_err)
close(fd_err[1]);
channel_set_pipes(channel,
use_file_for_in ? INVALID_FD : fd_in[1],
- fd_out[0],
- use_out_for_err ? INVALID_FD : fd_err[0]);
+ use_file_for_out ? INVALID_FD : fd_out[0],
+ use_out_for_err || use_file_for_err
+ ? INVALID_FD : fd_err[0]);
channel_set_job(channel, job, options);
# ifdef FEAT_GUI
channel_gui_register(channel);
@@ -5168,21 +5201,17 @@ failed: ;
if (channel != NULL)
channel_free(channel);
if (fd_in[0] >= 0)
- {
close(fd_in[0]);
- if (!use_file_for_in)
- close(fd_in[1]);
- }
+ if (fd_in[1] >= 0)
+ close(fd_in[1]);
if (fd_out[0] >= 0)
- {
close(fd_out[0]);
+ if (fd_out[1] >= 0)
close(fd_out[1]);
- }
if (fd_err[0] >= 0)
- {
close(fd_err[0]);
+ if (fd_err[1] >= 0)
close(fd_err[1]);
- }
# endif
}
diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim
index dd7ef4ec40..08855005c5 100644
--- a/src/testdir/test_channel.vim
+++ b/src/testdir/test_channel.vim
@@ -555,6 +555,97 @@ func Test_nl_read_file()
endtry
endfunc
+func Test_nl_write_out_file()
+ if !has('job')
+ return
+ endif
+ " TODO: make this work for MS-Windows
+ if !has('unix')
+ return
+ endif
+ call ch_log('Test_nl_write_out_file()')
+ let job = job_start(s:python . " test_channel_pipe.py",
+ \ {'out-io': 'file', 'out-name': 'Xoutput'})
+ call assert_equal("run", job_status(job))
+ try
+ let handle = job_getchannel(job)
+ call ch_sendraw(handle, "echo line one\n")
+ call ch_sendraw(handle, "echo line two\n")
+ call ch_sendraw(handle, "double this\n")
+ for i in range(50)
+ sleep 10m
+ if len(readfile('Xoutput')) > 2
+ break
+ endif
+ endfor
+ call assert_equal(['line one', 'line two', 'this', 'AND this'], readfile('Xoutput'))
+ finally
+ call job_stop(job)
+ call delete('Xoutput')
+ endtry
+endfunc
+
+func Test_nl_write_err_file()
+ if !has('job')
+ return
+ endif
+ " TODO: make this work for MS-Windows
+ if !has('unix')
+ return
+ endif
+ call ch_log('Test_nl_write_err_file()')
+ let job = job_start(s:python . " test_channel_pipe.py",
+ \ {'err-io': 'file', 'err-name': 'Xoutput'})
+ call assert_equal("run", job_status(job))
+ try
+ let handle = job_getchannel(job)
+ call ch_sendraw(handle, "echoerr line one\n")
+ call ch_sendraw(handle, "echoerr line two\n")
+ call ch_sendraw(handle, "doubleerr this\n")
+ for i in range(50)
+ sleep 10m
+ if len(readfile('Xoutput')) > 2
+ break
+ endif
+ endfor
+ call assert_equal(['line one', 'line two', 'this', 'AND this'], readfile('Xoutput'))
+ finally
+ call job_stop(job)
+ call delete('Xoutput')
+ endtry
+endfunc
+
+func Test_nl_write_both_file()
+ if !has('job')
+ return
+ endif
+ " TODO: make this work for MS-Windows
+ if !has('unix')
+ return
+ endif
+ call ch_log('Test_nl_write_both_file()')
+ let job = job_start(s:python . " test_channel_pipe.py",
+ \ {'out-io': 'file', 'out-name': 'Xoutput', 'err-io': 'out'})
+ call assert_equal("run", job_status(job))
+ try
+ let handle = job_getchannel(job)
+ call ch_sendraw(handle, "echoerr line one\n")
+ call ch_sendraw(handle, "echo line two\n")
+ call ch_sendraw(handle, "double this\n")
+ call ch_sendraw(handle, "doubleerr that\n")
+ for i in range(50)
+ sleep 10m
+ if len(readfile('Xoutput')) > 5
+ break
+ endif
+ endfor
+ call assert_equal(['line one', 'line two', 'this', 'AND this', 'that', 'AND that'], readfile('Xoutput'))
+ finally
+ call job_stop(job)
+ call delete('Xoutput')
+ endtry
+endfunc
+
func Test_pipe_to_buffer()
if !has('job')
return
diff --git a/src/testdir/test_channel_pipe.py b/src/testdir/test_channel_pipe.py
index 2097d3ebca..d5da687309 100644
--- a/src/testdir/test_channel_pipe.py
+++ b/src/testdir/test_channel_pipe.py
@@ -21,10 +21,13 @@ if __name__ == "__main__":
if typed.startswith("echo "):
print(typed[5:-1])
sys.stdout.flush()
- if typed.startswith("echoerr"):
- print(typed[8:-1], file=sys.stderr)
- sys.stderr.flush()
- if typed.startswith("double"):
+ if typed.startswith("double "):
print(typed[7:-1] + "\nAND " + typed[7:-1])
sys.stdout.flush()
+ if typed.startswith("echoerr "):
+ print(typed[8:-1], file=sys.stderr)
+ sys.stderr.flush()
+ if typed.startswith("doubleerr "):
+ print(typed[10:-1] + "\nAND " + typed[10:-1], file=sys.stderr)
+ sys.stderr.flush()
diff --git a/src/version.c b/src/version.c
index 2a233131fa..b98ff538c6 100644
--- a/src/version.c
+++ b/src/version.c
@@ -744,6 +744,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1514,
+/**/
1513,
/**/
1512,