Problem: Job cannot read from a file.
Solution: Implement reading from a file for Unix.
garray_T ga;
#endif
jobopt_T opt;
+ int part;
rettv->v_type = VAR_JOB;
job = job_alloc();
+ 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;
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 */
/* 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();
/* 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]);
# 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);
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)
{
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];
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];
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
if !has('job')
return
endif
-call ch_logfile('channellog', 'w')
call ch_log('Test_pipe_from_buffer()')
sp pipe-input
finally
call job_stop(job)
endtry
-call ch_logfile('')
endfunc
func Test_pipe_to_nameless_buffer()
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 1506,
/**/
1505,
/**/