summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2016-03-06 23:06:25 +0100
committerBram Moolenaar <Bram@vim.org>2016-03-06 23:06:25 +0100
commitb69fccf377f43544b86817b0de6cc1498a4ff9ec (patch)
tree16fe5187c9273a82f735ee1e4f2b50dcc345771f
parentd0b6502a7ace39d6cd30874110a572371d10beae (diff)
downloadvim-git-7.4.1506.tar.gz
patch 7.4.1506v7.4.1506
Problem: Job cannot read from a file. Solution: Implement reading from a file for Unix.
-rw-r--r--src/eval.c12
-rw-r--r--src/os_unix.c34
-rw-r--r--src/os_win32.c25
-rw-r--r--src/testdir/test_channel.vim27
-rw-r--r--src/version.c2
5 files changed, 85 insertions, 15 deletions
diff --git a/src/eval.c b/src/eval.c
index 510dd128d..77638d561 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -15118,6 +15118,7 @@ f_job_start(typval_T *argvars UNUSED, typval_T *rettv)
garray_T ga;
#endif
jobopt_T opt;
+ int part;
rettv->v_type = VAR_JOB;
job = job_alloc();
@@ -15135,6 +15136,17 @@ f_job_start(typval_T *argvars UNUSED, typval_T *rettv)
+ JO_STOPONEXIT + JO_EXIT_CB + JO_OUT_IO) == FAIL)
return;
+ /* Check that when io is "file" that there is a file name. */
+ for (part = PART_OUT; part <= PART_IN; ++part)
+ if ((opt.jo_set & (JO_OUT_IO << (part - PART_OUT)))
+ && opt.jo_io[part] == JIO_FILE
+ && (!(opt.jo_set & (JO_OUT_NAME << (part - PART_OUT)))
+ || *opt.jo_io_name[part] == NUL))
+ {
+ EMSG(_("E920: -io file requires -name to be set"));
+ return;
+ }
+
if ((opt.jo_set & JO_IN_IO) && opt.jo_io[PART_IN] == JIO_BUFFER)
{
buf_T *buf;
diff --git a/src/os_unix.c b/src/os_unix.c
index ed2b1298c..565dbd089 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -5045,6 +5045,7 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
int fd_out[2]; /* for stdout */
int fd_err[2]; /* for stderr */
channel_T *channel = NULL;
+ int use_file_for_in = options->jo_io[PART_IN] == JIO_FILE;
int use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT;
/* default is to fail */
@@ -5055,8 +5056,22 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
/* TODO: without the channel feature connect the child to /dev/null? */
/* Open pipes for stdin, stdout, stderr. */
- if (pipe(fd_in) < 0 || pipe(fd_out) < 0
- || (!use_out_for_err && pipe(fd_err) < 0))
+ if (use_file_for_in)
+ {
+ char_u *fname = options->jo_io_name[PART_IN];
+
+ fd_in[0] = mch_open((char *)fname, O_RDONLY, 0);
+ if (fd_in[0] < 0)
+ {
+ EMSG2(_(e_notopen), fname);
+ goto failed;
+ }
+ }
+ else if (pipe(fd_in) < 0)
+ goto failed;
+ if (pipe(fd_out) < 0)
+ goto failed;
+ if (!use_out_for_err && pipe(fd_err) < 0)
goto failed;
channel = add_channel();
@@ -5088,7 +5103,8 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
/* TODO: re-enable this when pipes connect without a channel */
# ifdef FEAT_CHANNEL
/* set up stdin for the child */
- close(fd_in[1]);
+ if (!use_file_for_in)
+ close(fd_in[1]);
close(0);
ignored = dup(fd_in[0]);
close(fd_in[0]);
@@ -5130,12 +5146,15 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
# ifdef FEAT_CHANNEL
/* child stdin, stdout and stderr */
- close(fd_in[0]);
+ if (!use_file_for_in)
+ close(fd_in[0]);
close(fd_out[1]);
if (!use_out_for_err)
close(fd_err[1]);
- channel_set_pipes(channel, fd_in[1], fd_out[0],
- use_out_for_err ? INVALID_FD : fd_err[0]);
+ 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]);
channel_set_job(channel, job, options);
# ifdef FEAT_GUI
channel_gui_register(channel);
@@ -5151,7 +5170,8 @@ failed: ;
if (fd_in[0] >= 0)
{
close(fd_in[0]);
- close(fd_in[1]);
+ if (!use_file_for_in)
+ close(fd_in[1]);
}
if (fd_out[0] >= 0)
{
diff --git a/src/os_win32.c b/src/os_win32.c
index 42e867246..9201b3497 100644
--- a/src/os_win32.c
+++ b/src/os_win32.c
@@ -5000,6 +5000,7 @@ mch_start_job(char *cmd, job_T *job, jobopt_T *options)
HANDLE jo;
# ifdef FEAT_CHANNEL
channel_T *channel;
+ int use_file_for_in = options->jo_io[PART_IN] == JIO_FILE;
int use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT;
HANDLE ifd[2];
HANDLE ofd[2];
@@ -5035,13 +5036,25 @@ mch_start_job(char *cmd, job_T *job, jobopt_T *options)
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
- if (!CreatePipe(&ifd[0], &ifd[1], &saAttr, 0)
- || !pSetHandleInformation(ifd[1], HANDLE_FLAG_INHERIT, 0)
- || !CreatePipe(&ofd[0], &ofd[1], &saAttr, 0)
- || !pSetHandleInformation(ofd[0], HANDLE_FLAG_INHERIT, 0)
- || (!use_out_for_err
+ if (use_file_for_in)
+ {
+ char_u *fname = options->jo_io_name[PART_IN];
+
+ // TODO
+ EMSG2(_(e_notopen), fname);
+ goto failed;
+ }
+ else if (!CreatePipe(&ifd[0], &ifd[1], &saAttr, 0)
+ || !pSetHandleInformation(ifd[1], HANDLE_FLAG_INHERIT, 0))
+ goto failed;
+
+ if (!CreatePipe(&ofd[0], &ofd[1], &saAttr, 0)
+ || !pSetHandleInformation(ofd[0], HANDLE_FLAG_INHERIT, 0))
+ goto failed;
+
+ if (!use_out_for_err
&& (!CreatePipe(&efd[0], &efd[1], &saAttr, 0)
- || !pSetHandleInformation(efd[0], HANDLE_FLAG_INHERIT, 0))))
+ || !pSetHandleInformation(efd[0], HANDLE_FLAG_INHERIT, 0)))
goto failed;
si.dwFlags |= STARTF_USESTDHANDLES;
si.hStdInput = ifd[0];
diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim
index 5321cce23..299bb2ba7 100644
--- a/src/testdir/test_channel.vim
+++ b/src/testdir/test_channel.vim
@@ -524,6 +524,31 @@ func Test_nl_err_to_out_pipe()
endtry
endfunc
+func Test_nl_read_file()
+ if !has('job')
+ return
+ endif
+ " TODO: make this work for MS-Windows.
+ if !has('unix')
+ return
+ endif
+ call ch_log('Test_nl_read_file()')
+ call writefile(['echo something', 'echoerr wrong', 'double this'], 'Xinput')
+ let job = job_start(s:python . " test_channel_pipe.py",
+ \ {'in-io': 'file', 'in-name': 'Xinput'})
+ call assert_equal("run", job_status(job))
+ try
+ let handle = job_getchannel(job)
+ call assert_equal("something", ch_readraw(handle))
+ call assert_equal("wrong", ch_readraw(handle, {'part': 'err'}))
+ call assert_equal("this", ch_readraw(handle))
+ call assert_equal("AND this", ch_readraw(handle))
+ finally
+ call job_stop(job)
+ call delete('Xinput')
+ endtry
+endfunc
+
func Test_pipe_to_buffer()
if !has('job')
return
@@ -556,7 +581,6 @@ func Test_pipe_from_buffer()
if !has('job')
return
endif
-call ch_logfile('channellog', 'w')
call ch_log('Test_pipe_from_buffer()')
sp pipe-input
@@ -574,7 +598,6 @@ call ch_logfile('channellog', 'w')
finally
call job_stop(job)
endtry
-call ch_logfile('')
endfunc
func Test_pipe_to_nameless_buffer()
diff --git a/src/version.c b/src/version.c
index 9c94df8b3..7e86ba6a3 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 */
/**/
+ 1506,
+/**/
1505,
/**/
1504,