Patch 7.4.1518
Problem:    Channel with disconnected in/out/err is not supported.
Solution:   Implement it for Unix.
Files:      src/eval.c, src/os_unix.c, src/structs.h,
            src/testdir/test_channel.vim, src/testdir/test_channel_pipe.py


*** ../vim-7.4.1517/src/eval.c  2016-03-08 17:08:38.558223138 +0100
--- src/eval.c  2016-03-08 18:18:34.206760505 +0100
***************
*** 10285,10291 ****
   * Returns NULL if the handle is invalid.
   */
      static channel_T *
! get_channel_arg(typval_T *tv)
  {
      channel_T *channel = NULL;
  
--- 10285,10291 ----
   * Returns NULL if the handle is invalid.
   */
      static channel_T *
! get_channel_arg(typval_T *tv, int check_open)
  {
      channel_T *channel = NULL;
  
***************
*** 10304,10310 ****
        return NULL;
      }
  
!     if (channel == NULL || !channel_is_open(channel))
      {
        EMSG(_("E906: not an open channel"));
        return NULL;
--- 10304,10310 ----
        return NULL;
      }
  
!     if (check_open && (channel == NULL || !channel_is_open(channel)))
      {
        EMSG(_("E906: not an open channel"));
        return NULL;
***************
*** 10318,10324 ****
      static void
  f_ch_close(typval_T *argvars, typval_T *rettv UNUSED)
  {
!     channel_T *channel = get_channel_arg(&argvars[0]);
  
      if (channel != NULL)
      {
--- 10318,10324 ----
      static void
  f_ch_close(typval_T *argvars, typval_T *rettv UNUSED)
  {
!     channel_T *channel = get_channel_arg(&argvars[0], TRUE);
  
      if (channel != NULL)
      {
***************
*** 10333,10339 ****
      static void
  f_ch_getbufnr(typval_T *argvars, typval_T *rettv)
  {
!     channel_T *channel = get_channel_arg(&argvars[0]);
  
      rettv->vval.v_number = -1;
      if (channel != NULL)
--- 10333,10339 ----
      static void
  f_ch_getbufnr(typval_T *argvars, typval_T *rettv)
  {
!     channel_T *channel = get_channel_arg(&argvars[0], TRUE);
  
      rettv->vval.v_number = -1;
      if (channel != NULL)
***************
*** 10361,10367 ****
      static void
  f_ch_getjob(typval_T *argvars, typval_T *rettv)
  {
!     channel_T *channel = get_channel_arg(&argvars[0]);
  
      if (channel != NULL)
      {
--- 10361,10367 ----
      static void
  f_ch_getjob(typval_T *argvars, typval_T *rettv)
  {
!     channel_T *channel = get_channel_arg(&argvars[0], TRUE);
  
      if (channel != NULL)
      {
***************
*** 10383,10389 ****
      channel_T *channel = NULL;
  
      if (argvars[1].v_type != VAR_UNKNOWN)
!       channel = get_channel_arg(&argvars[1]);
  
      ch_log(channel, (char *)msg);
  }
--- 10383,10389 ----
      channel_T *channel = NULL;
  
      if (argvars[1].v_type != VAR_UNKNOWN)
!       channel = get_channel_arg(&argvars[1], TRUE);
  
      ch_log(channel, (char *)msg);
  }
***************
*** 10500,10506 ****
                                                                      == FAIL)
        return;
  
!     channel = get_channel_arg(&argvars[0]);
      if (channel != NULL)
      {
        if (opt.jo_set & JO_PART)
--- 10500,10506 ----
                                                                      == FAIL)
        return;
  
!     channel = get_channel_arg(&argvars[0], TRUE);
      if (channel != NULL)
      {
        if (opt.jo_set & JO_PART)
***************
*** 10570,10576 ****
      channel_T *channel;
      int               part_send;
  
!     channel = get_channel_arg(&argvars[0]);
      if (channel == NULL)
        return NULL;
      part_send = channel_part_send(channel);
--- 10570,10576 ----
      channel_T *channel;
      int               part_send;
  
!     channel = get_channel_arg(&argvars[0], TRUE);
      if (channel == NULL)
        return NULL;
      part_send = channel_part_send(channel);
***************
*** 10619,10625 ****
      rettv->v_type = VAR_STRING;
      rettv->vval.v_string = NULL;
  
!     channel = get_channel_arg(&argvars[0]);
      if (channel == NULL)
        return;
      part_send = channel_part_send(channel);
--- 10619,10625 ----
      rettv->v_type = VAR_STRING;
      rettv->vval.v_string = NULL;
  
!     channel = get_channel_arg(&argvars[0], TRUE);
      if (channel == NULL)
        return;
      part_send = channel_part_send(channel);
***************
*** 10736,10742 ****
      channel_T *channel;
      jobopt_T  opt;
  
!     channel = get_channel_arg(&argvars[0]);
      if (channel == NULL)
        return;
      clear_job_options(&opt);
--- 10736,10742 ----
      channel_T *channel;
      jobopt_T  opt;
  
!     channel = get_channel_arg(&argvars[0], TRUE);
      if (channel == NULL)
        return;
      clear_job_options(&opt);
***************
*** 10752,10768 ****
      static void
  f_ch_status(typval_T *argvars, typval_T *rettv)
  {
      /* return an empty string by default */
      rettv->v_type = VAR_STRING;
  
!     if (argvars[0].v_type != VAR_CHANNEL)
!     {
!       EMSG2(_(e_invarg2), get_tv_string(&argvars[0]));
!       rettv->vval.v_string = NULL;
!     }
!     else
!       rettv->vval.v_string = vim_strsave(
!                        (char_u *)channel_status(argvars[0].vval.v_channel));
  }
  #endif
  
--- 10752,10765 ----
      static void
  f_ch_status(typval_T *argvars, typval_T *rettv)
  {
+     channel_T *channel;
+ 
      /* return an empty string by default */
      rettv->v_type = VAR_STRING;
+     rettv->vval.v_string = NULL;
  
!     channel = get_channel_arg(&argvars[0], FALSE);
!     rettv->vval.v_string = vim_strsave((char_u *)channel_status(channel));
  }
  #endif
  
*** ../vim-7.4.1517/src/os_unix.c       2016-03-08 15:37:36.734963213 +0100
--- src/os_unix.c       2016-03-08 18:00:02.826270515 +0100
***************
*** 5045,5055 ****
--- 5045,5061 ----
      int               fd_out[2];      /* for stdout */
      int               fd_err[2];      /* for stderr */
      channel_T *channel = NULL;
+     int               use_null_for_in = options->jo_io[PART_IN] == JIO_NULL;
+     int               use_null_for_out = options->jo_io[PART_OUT] == JIO_NULL;
+     int               use_null_for_err = options->jo_io[PART_ERR] == JIO_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;
  
+     if (use_out_for_err && use_null_for_out)
+       use_null_for_err = TRUE;
+ 
      /* default is to fail */
      job->jv_status = JOB_FAILED;
      fd_in[0] = -1;
***************
*** 5072,5078 ****
            goto failed;
        }
      }
!     else if (pipe(fd_in) < 0)
        goto failed;
  
      if (use_file_for_out)
--- 5078,5084 ----
            goto failed;
        }
      }
!     else if (!use_null_for_in && pipe(fd_in) < 0)
        goto failed;
  
      if (use_file_for_out)
***************
*** 5086,5092 ****
            goto failed;
        }
      }
!     else if (pipe(fd_out) < 0)
        goto failed;
  
      if (use_file_for_err)
--- 5092,5098 ----
            goto failed;
        }
      }
!     else if (!use_null_for_out && pipe(fd_out) < 0)
        goto failed;
  
      if (use_file_for_err)
***************
*** 5100,5111 ****
            goto failed;
        }
      }
!     else if (!use_out_for_err && pipe(fd_err) < 0)
        goto failed;
  
!     channel = add_channel();
!     if (channel == NULL)
!       goto failed;
  # endif
  
      pid = fork();     /* maybe we should use vfork() */
--- 5106,5120 ----
            goto failed;
        }
      }
!     else if (!use_out_for_err && !use_null_for_err && pipe(fd_err) < 0)
        goto failed;
  
!     if (!use_null_for_in || !use_null_for_out || !use_null_for_err)
!     {
!       channel = add_channel();
!       if (channel == NULL)
!           goto failed;
!     }
  # endif
  
      pid = fork();     /* maybe we should use vfork() */
***************
*** 5117,5122 ****
--- 5126,5135 ----
  
      if (pid == 0)
      {
+ # ifdef FEAT_CHANNEL
+       int             null_fd = -1;
+ # endif
+ 
        /* child */
        reset_signals();                /* handle signals normally */
  
***************
*** 5131,5145 ****
  
        /* TODO: re-enable this when pipes connect without a channel */
  # ifdef FEAT_CHANNEL
        /* set up stdin for the child */
!       if (!use_file_for_in)
!           close(fd_in[1]);
!       close(0);
!       ignored = dup(fd_in[0]);
!       close(fd_in[0]);
  
        /* set up stderr for the child */
!       if (use_out_for_err)
        {
            close(2);
            ignored = dup(fd_out[1]);
--- 5144,5174 ----
  
        /* TODO: re-enable this when pipes connect without a channel */
  # ifdef FEAT_CHANNEL
+       if (use_null_for_in || use_null_for_out || use_null_for_err)
+           null_fd = open("/dev/null", O_RDWR | O_EXTRA, 0);
+ 
        /* set up stdin for the child */
!       if (use_null_for_in)
!       {
!           close(0);
!           ignored = dup(null_fd);
!       }
!       else
!       {
!           if (!use_file_for_in)
!               close(fd_in[1]);
!           close(0);
!           ignored = dup(fd_in[0]);
!           close(fd_in[0]);
!       }
  
        /* set up stderr for the child */
!       if (use_null_for_err)
!       {
!           close(2);
!           ignored = dup(null_fd);
!       }
!       else if (use_out_for_err)
        {
            close(2);
            ignored = dup(fd_out[1]);
***************
*** 5154,5164 ****
        }
  
        /* set up stdout for the child */
!       if (!use_file_for_out)
!           close(fd_out[0]);
!       close(1);
!       ignored = dup(fd_out[1]);
!       close(fd_out[1]);
  # endif
  
        /* See above for type of argv. */
--- 5183,5203 ----
        }
  
        /* set up stdout for the child */
!       if (use_null_for_out)
!       {
!           close(0);
!           ignored = dup(null_fd);
!       }
!       else
!       {
!           if (!use_file_for_out)
!               close(fd_out[0]);
!           close(1);
!           ignored = dup(fd_out[1]);
!           close(fd_out[1]);
!       }
!       if (null_fd >= 0)
!           close(null_fd);
  # endif
  
        /* See above for type of argv. */
***************
*** 5183,5199 ****
        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],
!                     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);
  #  endif
  # endif
  
      return;
  
  failed: ;
--- 5222,5244 ----
        close(fd_out[1]);
      if (!use_out_for_err && !use_file_for_err)
        close(fd_err[1]);
!     if (channel != NULL)
!     {
!       channel_set_pipes(channel,
!                     use_file_for_in || use_null_for_in
!                                                     ? INVALID_FD : fd_in[1],
!                     use_file_for_out || use_null_for_out
!                                                    ? INVALID_FD : fd_out[0],
!                     use_out_for_err || use_file_for_err || use_null_for_err
                                                    ? INVALID_FD : fd_err[0]);
!       channel_set_job(channel, job, options);
  #  ifdef FEAT_GUI
!       channel_gui_register(channel);
  #  endif
+     }
  # endif
  
+     /* success! */
      return;
  
  failed: ;
*** ../vim-7.4.1517/src/structs.h       2016-03-06 20:22:20.352165976 +0100
--- src/structs.h       2016-03-08 17:53:21.790418035 +0100
***************
*** 1417,1424 ****
  #define JO_TIMEOUT_ALL        (JO_TIMEOUT + JO_OUT_TIMEOUT + JO_ERR_TIMEOUT)
  
  typedef enum {
      JIO_NULL,
-     JIO_PIPE,
      JIO_FILE,
      JIO_BUFFER,
      JIO_OUT
--- 1417,1424 ----
  #define JO_TIMEOUT_ALL        (JO_TIMEOUT + JO_OUT_TIMEOUT + JO_ERR_TIMEOUT)
  
  typedef enum {
+     JIO_PIPE,     /* default */
      JIO_NULL,
      JIO_FILE,
      JIO_BUFFER,
      JIO_OUT
*** ../vim-7.4.1517/src/testdir/test_channel.vim        2016-03-08 
16:06:51.048733393 +0100
--- src/testdir/test_channel.vim        2016-03-08 18:19:39.738081447 +0100
***************
*** 784,789 ****
--- 784,841 ----
    endtry
  endfunc
  
+ func Test_pipe_null()
+   if !has('job')
+     return
+   endif
+   " TODO: implement this for MS-Windows
+   if !has('unix')
+     return
+   endif
+   call ch_log('Test_pipe_null()')
+ 
+   " We cannot check that no I/O works, we only check that the job starts
+   " properly.
+   let job = job_start(s:python . " test_channel_pipe.py something",
+       \ {'in-io': 'null'})
+   call assert_equal("run", job_status(job))
+   try
+     call assert_equal('something', ch_read(job))
+   finally
+     call job_stop(job)
+   endtry
+ 
+   let job = job_start(s:python . " test_channel_pipe.py err-out",
+       \ {'out-io': 'null'})
+   call assert_equal("run", job_status(job))
+   try
+     call assert_equal('err-out', ch_read(job, {"part": "err"}))
+   finally
+     call job_stop(job)
+   endtry
+ 
+   let job = job_start(s:python . " test_channel_pipe.py something",
+       \ {'err-io': 'null'})
+   call assert_equal("run", job_status(job))
+   try
+     call assert_equal('something', ch_read(job))
+   finally
+     call job_stop(job)
+   endtry
+ 
+   let job = job_start(s:python . " test_channel_pipe.py something",
+       \ {'out-io': 'null', 'err-io': 'out'})
+   call assert_equal("run", job_status(job))
+   call job_stop(job)
+ 
+   let job = job_start(s:python . " test_channel_pipe.py something",
+       \ {'in-io': 'null', 'out-io': 'null', 'err-io': 'null'})
+   call assert_equal("run", job_status(job))
+   call assert_equal('channel fail', string(job_getchannel(job)))
+   call assert_equal('fail', ch_status(job))
+   call job_stop(job)
+ endfunc
+ 
  """"""""""
  
  let s:unletResponse = ''
*** ../vim-7.4.1517/src/testdir/test_channel_pipe.py    2016-03-08 
15:37:36.734963213 +0100
--- src/testdir/test_channel_pipe.py    2016-03-08 17:31:19.792095528 +0100
***************
*** 10,16 ****
  if __name__ == "__main__":
  
      if len(sys.argv) > 1:
!         print(sys.argv[1])
  
      while True:
          typed = sys.stdin.readline()
--- 10,21 ----
  if __name__ == "__main__":
  
      if len(sys.argv) > 1:
!         if sys.argv[1].startswith("err"):
!             print(sys.argv[1], file=sys.stderr)
!             sys.stderr.flush()
!         else:
!             print(sys.argv[1])
!             sys.stdout.flush()
  
      while True:
          typed = sys.stdin.readline()
*** ../vim-7.4.1517/src/version.c       2016-03-08 17:13:02.063486804 +0100
--- src/version.c       2016-03-08 17:26:56.018826202 +0100
***************
*** 745,746 ****
--- 745,748 ----
  {   /* Add new patch number below this line */
+ /**/
+     1518,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
12. You turn off your modem and get this awful empty feeling, like you just
    pulled the plug on a loved one.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui