Skip to content

Commit b69fccf

Browse files
committed
patch 7.4.1506
Problem: Job cannot read from a file. Solution: Implement reading from a file for Unix.
1 parent d0b6502 commit b69fccf

5 files changed

Lines changed: 85 additions & 15 deletions

File tree

src/eval.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15118,6 +15118,7 @@ f_job_start(typval_T *argvars UNUSED, typval_T *rettv)
1511815118
garray_T ga;
1511915119
#endif
1512015120
jobopt_T opt;
15121+
int part;
1512115122

1512215123
rettv->v_type = VAR_JOB;
1512315124
job = job_alloc();
@@ -15135,6 +15136,17 @@ f_job_start(typval_T *argvars UNUSED, typval_T *rettv)
1513515136
+ JO_STOPONEXIT + JO_EXIT_CB + JO_OUT_IO) == FAIL)
1513615137
return;
1513715138

15139+
/* Check that when io is "file" that there is a file name. */
15140+
for (part = PART_OUT; part <= PART_IN; ++part)
15141+
if ((opt.jo_set & (JO_OUT_IO << (part - PART_OUT)))
15142+
&& opt.jo_io[part] == JIO_FILE
15143+
&& (!(opt.jo_set & (JO_OUT_NAME << (part - PART_OUT)))
15144+
|| *opt.jo_io_name[part] == NUL))
15145+
{
15146+
EMSG(_("E920: -io file requires -name to be set"));
15147+
return;
15148+
}
15149+
1513815150
if ((opt.jo_set & JO_IN_IO) && opt.jo_io[PART_IN] == JIO_BUFFER)
1513915151
{
1514015152
buf_T *buf;

src/os_unix.c

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5045,6 +5045,7 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
50455045
int fd_out[2]; /* for stdout */
50465046
int fd_err[2]; /* for stderr */
50475047
channel_T *channel = NULL;
5048+
int use_file_for_in = options->jo_io[PART_IN] == JIO_FILE;
50485049
int use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT;
50495050

50505051
/* default is to fail */
@@ -5055,8 +5056,22 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
50555056

50565057
/* TODO: without the channel feature connect the child to /dev/null? */
50575058
/* Open pipes for stdin, stdout, stderr. */
5058-
if (pipe(fd_in) < 0 || pipe(fd_out) < 0
5059-
|| (!use_out_for_err && pipe(fd_err) < 0))
5059+
if (use_file_for_in)
5060+
{
5061+
char_u *fname = options->jo_io_name[PART_IN];
5062+
5063+
fd_in[0] = mch_open((char *)fname, O_RDONLY, 0);
5064+
if (fd_in[0] < 0)
5065+
{
5066+
EMSG2(_(e_notopen), fname);
5067+
goto failed;
5068+
}
5069+
}
5070+
else if (pipe(fd_in) < 0)
5071+
goto failed;
5072+
if (pipe(fd_out) < 0)
5073+
goto failed;
5074+
if (!use_out_for_err && pipe(fd_err) < 0)
50605075
goto failed;
50615076

50625077
channel = add_channel();
@@ -5088,7 +5103,8 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
50885103
/* TODO: re-enable this when pipes connect without a channel */
50895104
# ifdef FEAT_CHANNEL
50905105
/* set up stdin for the child */
5091-
close(fd_in[1]);
5106+
if (!use_file_for_in)
5107+
close(fd_in[1]);
50925108
close(0);
50935109
ignored = dup(fd_in[0]);
50945110
close(fd_in[0]);
@@ -5130,12 +5146,15 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
51305146

51315147
# ifdef FEAT_CHANNEL
51325148
/* child stdin, stdout and stderr */
5133-
close(fd_in[0]);
5149+
if (!use_file_for_in)
5150+
close(fd_in[0]);
51345151
close(fd_out[1]);
51355152
if (!use_out_for_err)
51365153
close(fd_err[1]);
5137-
channel_set_pipes(channel, fd_in[1], fd_out[0],
5138-
use_out_for_err ? INVALID_FD : fd_err[0]);
5154+
channel_set_pipes(channel,
5155+
use_file_for_in ? INVALID_FD : fd_in[1],
5156+
fd_out[0],
5157+
use_out_for_err ? INVALID_FD : fd_err[0]);
51395158
channel_set_job(channel, job, options);
51405159
# ifdef FEAT_GUI
51415160
channel_gui_register(channel);
@@ -5151,7 +5170,8 @@ failed: ;
51515170
if (fd_in[0] >= 0)
51525171
{
51535172
close(fd_in[0]);
5154-
close(fd_in[1]);
5173+
if (!use_file_for_in)
5174+
close(fd_in[1]);
51555175
}
51565176
if (fd_out[0] >= 0)
51575177
{

src/os_win32.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5000,6 +5000,7 @@ mch_start_job(char *cmd, job_T *job, jobopt_T *options)
50005000
HANDLE jo;
50015001
# ifdef FEAT_CHANNEL
50025002
channel_T *channel;
5003+
int use_file_for_in = options->jo_io[PART_IN] == JIO_FILE;
50035004
int use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT;
50045005
HANDLE ifd[2];
50055006
HANDLE ofd[2];
@@ -5035,13 +5036,25 @@ mch_start_job(char *cmd, job_T *job, jobopt_T *options)
50355036
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
50365037
saAttr.bInheritHandle = TRUE;
50375038
saAttr.lpSecurityDescriptor = NULL;
5038-
if (!CreatePipe(&ifd[0], &ifd[1], &saAttr, 0)
5039-
|| !pSetHandleInformation(ifd[1], HANDLE_FLAG_INHERIT, 0)
5040-
|| !CreatePipe(&ofd[0], &ofd[1], &saAttr, 0)
5041-
|| !pSetHandleInformation(ofd[0], HANDLE_FLAG_INHERIT, 0)
5042-
|| (!use_out_for_err
5039+
if (use_file_for_in)
5040+
{
5041+
char_u *fname = options->jo_io_name[PART_IN];
5042+
5043+
// TODO
5044+
EMSG2(_(e_notopen), fname);
5045+
goto failed;
5046+
}
5047+
else if (!CreatePipe(&ifd[0], &ifd[1], &saAttr, 0)
5048+
|| !pSetHandleInformation(ifd[1], HANDLE_FLAG_INHERIT, 0))
5049+
goto failed;
5050+
5051+
if (!CreatePipe(&ofd[0], &ofd[1], &saAttr, 0)
5052+
|| !pSetHandleInformation(ofd[0], HANDLE_FLAG_INHERIT, 0))
5053+
goto failed;
5054+
5055+
if (!use_out_for_err
50435056
&& (!CreatePipe(&efd[0], &efd[1], &saAttr, 0)
5044-
|| !pSetHandleInformation(efd[0], HANDLE_FLAG_INHERIT, 0))))
5057+
|| !pSetHandleInformation(efd[0], HANDLE_FLAG_INHERIT, 0)))
50455058
goto failed;
50465059
si.dwFlags |= STARTF_USESTDHANDLES;
50475060
si.hStdInput = ifd[0];

src/testdir/test_channel.vim

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,31 @@ func Test_nl_err_to_out_pipe()
524524
endtry
525525
endfunc
526526

527+
func Test_nl_read_file()
528+
if !has('job')
529+
return
530+
endif
531+
" TODO: make this work for MS-Windows.
532+
if !has('unix')
533+
return
534+
endif
535+
call ch_log('Test_nl_read_file()')
536+
call writefile(['echo something', 'echoerr wrong', 'double this'], 'Xinput')
537+
let job = job_start(s:python . " test_channel_pipe.py",
538+
\ {'in-io': 'file', 'in-name': 'Xinput'})
539+
call assert_equal("run", job_status(job))
540+
try
541+
let handle = job_getchannel(job)
542+
call assert_equal("something", ch_readraw(handle))
543+
call assert_equal("wrong", ch_readraw(handle, {'part': 'err'}))
544+
call assert_equal("this", ch_readraw(handle))
545+
call assert_equal("AND this", ch_readraw(handle))
546+
finally
547+
call job_stop(job)
548+
call delete('Xinput')
549+
endtry
550+
endfunc
551+
527552
func Test_pipe_to_buffer()
528553
if !has('job')
529554
return
@@ -556,7 +581,6 @@ func Test_pipe_from_buffer()
556581
if !has('job')
557582
return
558583
endif
559-
call ch_logfile('channellog', 'w')
560584
call ch_log('Test_pipe_from_buffer()')
561585

562586
sp pipe-input
@@ -574,7 +598,6 @@ call ch_logfile('channellog', 'w')
574598
finally
575599
call job_stop(job)
576600
endtry
577-
call ch_logfile('')
578601
endfunc
579602

580603
func Test_pipe_to_nameless_buffer()

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,8 @@ static char *(features[]) =
743743

744744
static int included_patches[] =
745745
{ /* Add new patch number below this line */
746+
/**/
747+
1506,
746748
/**/
747749
1505,
748750
/**/

0 commit comments

Comments
 (0)