]> granicus.if.org Git - vim/commitdiff
patch 7.4.1506 v7.4.1506
authorBram Moolenaar <Bram@vim.org>
Sun, 6 Mar 2016 22:06:25 +0000 (23:06 +0100)
committerBram Moolenaar <Bram@vim.org>
Sun, 6 Mar 2016 22:06:25 +0000 (23:06 +0100)
Problem:    Job cannot read from a file.
Solution:   Implement reading from a file for Unix.

src/eval.c
src/os_unix.c
src/os_win32.c
src/testdir/test_channel.vim
src/version.c

index 510dd128da7e5b0d7c5b6e2f0ec1d06d3da1e67e..77638d561288d6c8952619162108c92f7331fc7c 100644 (file)
@@ -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;
index ed2b1298cdcbb005090e0dc76c094ea1135f148e..565dbd089ddc993f520bac9a489d597bb2a3cd73 100644 (file)
@@ -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)
     {
index 42e8672468492b26dec27ca0e02e20cc04b6aeba..9201b349727f57e6d57febe8575a5d5ae89e7e24 100644 (file)
@@ -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];
index 5321cce23f3ba62a5ee3df84c1ab845ae7065d64..299bb2ba7b53f49965ab9db1acabf1d75d949d6f 100644 (file)
@@ -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()
index 9c94df8b37b93da9147770a315446ae408da4aa2..7e86ba6a391bcadd618cc6a873ed8360ae847d7a 100644 (file)
@@ -743,6 +743,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1506,
 /**/
     1505,
 /**/