Patch 8.0.0744
Problem:    A terminal window uses pipes instead of a pty.
Solution:   Add pty support.
Files:      src/structs.h, src/os_unix.c, src/terminal.c, src/channel.c,
            src/proto/os_unix.pro, src/os_win32.c, src/proto/os_win32.pro


*** ../vim-8.0.0743/src/structs.h       2017-07-20 23:04:42.967282191 +0200
--- src/structs.h       2017-07-22 17:58:36.776232195 +0200
***************
*** 1705,1710 ****
--- 1705,1711 ----
      char_u    jo_io_name_buf[4][NUMBUFLEN];
      char_u    *jo_io_name[4]; /* not allocated! */
      int               jo_io_buf[4];
+     int               jo_pty;
      int               jo_modifiable[4];
      int               jo_message[4];
      channel_T *jo_channel;
*** ../vim-8.0.0743/src/os_unix.c       2017-07-22 14:08:39.082860834 +0200
--- src/os_unix.c       2017-07-22 18:01:24.335023832 +0200
***************
*** 4098,4103 ****
--- 4098,4129 ----
  }
  #endif
  
+ #if defined(FEAT_GUI) || defined(FEAT_JOB_CHANNEL)
+     static void
+ open_pty(int *pty_master_fd, int *pty_slave_fd)
+ {
+     char      *tty_name;
+ 
+     *pty_master_fd = OpenPTY(&tty_name);          /* open pty */
+     if (*pty_master_fd >= 0)
+     {
+       /* Leaving out O_NOCTTY may lead to waitpid() always returning
+        * 0 on Mac OS X 10.7 thereby causing freezes. Let's assume
+        * adding O_NOCTTY always works when defined. */
+ #ifdef O_NOCTTY
+       *pty_slave_fd = open(tty_name, O_RDWR | O_NOCTTY | O_EXTRA, 0);
+ #else
+       *pty_slave_fd = open(tty_name, O_RDWR | O_EXTRA, 0);
+ #endif
+       if (*pty_slave_fd < 0)
+       {
+           close(*pty_master_fd);
+           *pty_master_fd = -1;
+       }
+     }
+ }
+ #endif
+ 
      int
  mch_call_shell(
      char_u    *cmd,
***************
*** 4206,4212 ****
      int               pty_master_fd = -1;         /* for pty's */
  # ifdef FEAT_GUI
      int               pty_slave_fd = -1;
-     char      *tty_name;
  # endif
      int               fd_toshell[2];          /* for pipes */
      int               fd_fromshell[2];
--- 4232,4237 ----
***************
*** 4269,4293 ****
         * If the slave can't be opened, close the master pty.
         */
        if (p_guipty && !(options & (SHELL_READ|SHELL_WRITE)))
!       {
!           pty_master_fd = OpenPTY(&tty_name);     /* open pty */
!           if (pty_master_fd >= 0)
!           {
!               /* Leaving out O_NOCTTY may lead to waitpid() always returning
!                * 0 on Mac OS X 10.7 thereby causing freezes. Let's assume
!                * adding O_NOCTTY always works when defined. */
! #ifdef O_NOCTTY
!               pty_slave_fd = open(tty_name, O_RDWR | O_NOCTTY | O_EXTRA, 0);
! #else
!               pty_slave_fd = open(tty_name, O_RDWR | O_EXTRA, 0);
! #endif
!               if (pty_slave_fd < 0)
!               {
!                   close(pty_master_fd);
!                   pty_master_fd = -1;
!               }
!           }
!       }
        /*
         * If not opening a pty or it didn't work, try using pipes.
         */
--- 4294,4300 ----
         * If the slave can't be opened, close the master pty.
         */
        if (p_guipty && !(options & (SHELL_READ|SHELL_WRITE)))
!           open_pty(&pty_master_fd, &pty_slave_fd);
        /*
         * If not opening a pty or it didn't work, try using pipes.
         */
***************
*** 5100,5111 ****
  
  #if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
      void
! mch_start_job(char **argv, job_T *job, jobopt_T *options)
  {
      pid_t     pid;
      int               fd_in[2];       /* for stdin */
      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;
--- 5107,5120 ----
  
  #if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
      void
! mch_job_start(char **argv, job_T *job, jobopt_T *options)
  {
      pid_t     pid;
      int               fd_in[2];       /* for stdin */
      int               fd_out[2];      /* for stdout */
      int               fd_err[2];      /* for stderr */
+     int               pty_master_fd = -1;
+     int               pty_slave_fd = -1;
      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;
***************
*** 5128,5133 ****
--- 5137,5145 ----
      fd_err[0] = -1;
      fd_err[1] = -1;
  
+     if (options->jo_pty)
+       open_pty(&pty_master_fd, &pty_slave_fd);
+ 
      /* TODO: without the channel feature connect the child to /dev/null? */
      /* Open pipes for stdin, stdout, stderr. */
      if (use_file_for_in)
***************
*** 5141,5147 ****
            goto failed;
        }
      }
!     else if (!use_null_for_in && pipe(fd_in) < 0)
        goto failed;
  
      if (use_file_for_out)
--- 5153,5159 ----
            goto failed;
        }
      }
!     else if (!use_null_for_in && pty_master_fd < 0 && pipe(fd_in) < 0)
        goto failed;
  
      if (use_file_for_out)
***************
*** 5155,5161 ****
            goto failed;
        }
      }
!     else if (!use_null_for_out && pipe(fd_out) < 0)
        goto failed;
  
      if (use_file_for_err)
--- 5167,5173 ----
            goto failed;
        }
      }
!     else if (!use_null_for_out && pty_master_fd < 0 && pipe(fd_out) < 0)
        goto failed;
  
      if (use_file_for_err)
***************
*** 5169,5175 ****
            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)
--- 5181,5188 ----
            goto failed;
        }
      }
!     else if (!use_out_for_err && !use_null_for_err
!                                     && pty_master_fd < 0 && pipe(fd_err) < 0)
        goto failed;
  
      if (!use_null_for_in || !use_null_for_out || !use_null_for_err)
***************
*** 5224,5277 ****
            null_fd = open("/dev/null", O_RDWR | O_EXTRA, 0);
  
        /* set up stdin for the child */
        if (use_null_for_in && null_fd >= 0)
-       {
-           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 && null_fd >= 0)
        {
-           close(2);
            ignored = dup(null_fd);
            stderr_works = FALSE;
        }
        else if (use_out_for_err)
-       {
-           close(2);
            ignored = dup(fd_out[1]);
!       }
        else
-       {
-           if (!use_file_for_err)
-               close(fd_err[0]);
-           close(2);
            ignored = dup(fd_err[1]);
-           close(fd_err[1]);
-       }
  
        /* set up stdout for the child */
        if (use_null_for_out && null_fd >= 0)
-       {
-           close(1);
            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)
--- 5237,5289 ----
            null_fd = open("/dev/null", O_RDWR | O_EXTRA, 0);
  
        /* set up stdin for the child */
+       close(0);
        if (use_null_for_in && null_fd >= 0)
            ignored = dup(null_fd);
!       else if (fd_in[0] < 0)
!           ignored = dup(pty_slave_fd);
        else
            ignored = dup(fd_in[0]);
  
        /* set up stderr for the child */
+       close(2);
        if (use_null_for_err && null_fd >= 0)
        {
            ignored = dup(null_fd);
            stderr_works = FALSE;
        }
        else if (use_out_for_err)
            ignored = dup(fd_out[1]);
!       else if (fd_err[1] < 0)
!           ignored = dup(pty_slave_fd);
        else
            ignored = dup(fd_err[1]);
  
        /* set up stdout for the child */
+       close(1);
        if (use_null_for_out && null_fd >= 0)
            ignored = dup(null_fd);
!       else if (fd_out[1] < 0)
!           ignored = dup(pty_slave_fd);
        else
            ignored = dup(fd_out[1]);
+ 
+       if (fd_in[0] >= 0)
+           close(fd_in[0]);
+       if (fd_in[1] >= 0)
+           close(fd_in[1]);
+       if (fd_out[0] >= 0)
+           close(fd_out[0]);
+       if (fd_out[1] >= 0)
            close(fd_out[1]);
+       if (fd_err[0] >= 0)
+           close(fd_err[0]);
+       if (fd_err[1] >= 0)
+           close(fd_err[1]);
+       if (pty_master_fd >= 0)
+       {
+           close(pty_master_fd); /* not used */
+           close(pty_slave_fd); /* duped above */
        }
  
        if (null_fd >= 0)
***************
*** 5296,5302 ****
      job->jv_status = JOB_STARTED;
      job->jv_channel = channel;  /* ch_refcount was set above */
  
!     /* child stdin, stdout and stderr */
      if (!use_file_for_in && fd_in[0] >= 0)
        close(fd_in[0]);
      if (!use_file_for_out && fd_out[1] >= 0)
--- 5308,5316 ----
      job->jv_status = JOB_STARTED;
      job->jv_channel = channel;  /* ch_refcount was set above */
  
!     if (pty_master_fd >= 0)
!       close(pty_slave_fd); /* duped above */
!     /* close child stdin, stdout and stderr */
      if (!use_file_for_in && fd_in[0] >= 0)
        close(fd_in[0]);
      if (!use_file_for_out && fd_out[1] >= 0)
***************
*** 5306,5317 ****
      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);
      }
  
--- 5320,5331 ----
      if (channel != NULL)
      {
        channel_set_pipes(channel,
!               use_file_for_in || use_null_for_in
!                       ? INVALID_FD : fd_in[1] < 0 ? pty_master_fd : fd_in[1],
!               use_file_for_out || use_null_for_out
!                     ? INVALID_FD : fd_out[0] < 0 ? pty_master_fd : fd_out[0],
!               use_out_for_err || use_file_for_err || use_null_for_err
!                    ? INVALID_FD : fd_err[0] < 0 ? pty_master_fd : fd_err[0]);
        channel_set_job(channel, job, options);
      }
  
***************
*** 5332,5337 ****
--- 5346,5355 ----
        close(fd_err[0]);
      if (fd_err[1] >= 0)
        close(fd_err[1]);
+     if (pty_master_fd >= 0)
+       close(pty_master_fd);
+     if (pty_slave_fd >= 0)
+       close(pty_slave_fd);
  }
  
      char *
*** ../vim-8.0.0743/src/terminal.c      2017-07-22 16:14:39.276915783 +0200
--- src/terminal.c      2017-07-22 17:55:38.433509231 +0200
***************
*** 34,40 ****
   * TODO:
   * - When 'termsize' is set and dragging the separator the terminal gets 
messed
   *   up.
-  * - Use a pty for I/O with the job.
   * - set buffer options to be scratch, hidden, nomodifiable, etc.
   * - set buffer name to command, add (1) to avoid duplicates.
   * - If [command] is not given the 'shell' option is used.
--- 34,39 ----
***************
*** 52,57 ****
--- 51,58 ----
   * - add test for giving error for invalid 'termsize' value.
   * - support minimal size when 'termsize' is "rows*cols".
   * - support minimal size when 'termsize' is empty?
+  * - implement "term" for job_start(): more job options when starting a
+  *   terminal.
   * - implement ":buf {term-buf-name}"
   * - implement term_list()                    list of buffers with a terminal
   * - implement term_getsize(buf)
***************
*** 673,678 ****
--- 674,680 ----
      opt->jo_set |= JO_OUT_IO + (JO_OUT_IO << (PART_ERR - PART_OUT));
      opt->jo_io_buf[PART_OUT] = curbuf->b_fnum;
      opt->jo_io_buf[PART_ERR] = curbuf->b_fnum;
+     opt->jo_pty = TRUE;
      opt->jo_set |= JO_OUT_BUF + (JO_OUT_BUF << (PART_ERR - PART_OUT));
      opt->jo_term_rows = rows;
      opt->jo_term_cols = cols;
*** ../vim-8.0.0743/src/channel.c       2017-07-22 16:14:39.272915812 +0200
--- src/channel.c       2017-07-22 17:50:26.123745598 +0200
***************
*** 1013,1019 ****
        if (part == PART_SOCK)
            sock_close(*fd);
        else
!           fd_close(*fd);
        *fd = INVALID_FD;
  
        channel->ch_to_be_closed &= ~(1 << part);
--- 1013,1028 ----
        if (part == PART_SOCK)
            sock_close(*fd);
        else
!       {
!           /* When using a pty the same FD is set on multiple parts, only
!            * close it when the last reference is closed. */
!           if ((part == PART_IN || channel->ch_part[PART_IN].ch_fd != *fd)
!                   && (part == PART_OUT
!                                   || channel->ch_part[PART_OUT].ch_fd != *fd)
!                   && (part == PART_ERR
!                                  || channel->ch_part[PART_ERR].ch_fd != *fd))
!               fd_close(*fd);
!       }
        *fd = INVALID_FD;
  
        channel->ch_to_be_closed &= ~(1 << part);
***************
*** 4280,4285 ****
--- 4289,4300 ----
                opt->jo_io_name[part] =
                       get_tv_string_buf_chk(item, opt->jo_io_name_buf[part]);
            }
+           else if (STRCMP(hi->hi_key, "pty") == 0)
+           {
+               if (!(supported & JO_MODE))
+                   break;
+               opt->jo_pty = get_tv_number(item);
+           }
            else if (STRCMP(hi->hi_key, "in_buf") == 0
                    || STRCMP(hi->hi_key, "out_buf") == 0
                    || STRCMP(hi->hi_key, "err_buf") == 0)
***************
*** 5074,5083 ****
        ch_logs(NULL, "Starting job: %s", (char *)ga.ga_data);
        ga_clear(&ga);
      }
!     mch_start_job(argv, job, &opt);
  #else
      ch_logs(NULL, "Starting job: %s", (char *)cmd);
!     mch_start_job((char *)cmd, job, &opt);
  #endif
  
      /* If the channel is reading from a buffer, write lines now. */
--- 5089,5098 ----
        ch_logs(NULL, "Starting job: %s", (char *)ga.ga_data);
        ga_clear(&ga);
      }
!     mch_job_start(argv, job, &opt);
  #else
      ch_logs(NULL, "Starting job: %s", (char *)cmd);
!     mch_job_start((char *)cmd, job, &opt);
  #endif
  
      /* If the channel is reading from a buffer, write lines now. */
*** ../vim-8.0.0743/src/proto/os_unix.pro       2016-10-15 18:36:45.353910276 
+0200
--- src/proto/os_unix.pro       2017-07-22 17:51:31.695276052 +0200
***************
*** 57,63 ****
  void mch_new_shellsize(void);
  int mch_parse_cmd(char_u *cmd, int use_shcf, char ***argv, int *argc);
  int mch_call_shell(char_u *cmd, int options);
! void mch_start_job(char **argv, job_T *job, jobopt_T *options);
  char *mch_job_status(job_T *job);
  job_T *mch_detect_ended_job(job_T *job_list);
  int mch_stop_job(job_T *job, char_u *how);
--- 57,63 ----
  void mch_new_shellsize(void);
  int mch_parse_cmd(char_u *cmd, int use_shcf, char ***argv, int *argc);
  int mch_call_shell(char_u *cmd, int options);
! void mch_job_start(char **argv, job_T *job, jobopt_T *options);
  char *mch_job_status(job_T *job);
  job_T *mch_detect_ended_job(job_T *job_list);
  int mch_stop_job(job_T *job, char_u *how);
*** ../vim-8.0.0743/src/os_win32.c      2017-03-21 19:29:22.053338817 +0100
--- src/os_win32.c      2017-07-22 17:51:13.007409872 +0200
***************
*** 4964,4970 ****
  }
  
      void
! mch_start_job(char *cmd, job_T *job, jobopt_T *options)
  {
      STARTUPINFO               si;
      PROCESS_INFORMATION       pi;
--- 4964,4970 ----
  }
  
      void
! mch_job_start(char *cmd, job_T *job, jobopt_T *options)
  {
      STARTUPINFO               si;
      PROCESS_INFORMATION       pi;
*** ../vim-8.0.0743/src/proto/os_win32.pro      2017-02-01 13:14:11.026177020 
+0100
--- src/proto/os_win32.pro      2017-07-22 17:51:23.691333367 +0200
***************
*** 41,47 ****
  void mch_new_shellsize(void);
  void mch_set_winsize_now(void);
  int mch_call_shell(char_u *cmd, int options);
! void mch_start_job(char *cmd, job_T *job, jobopt_T *options);
  char *mch_job_status(job_T *job);
  job_T *mch_detect_ended_job(job_T *job_list);
  int mch_stop_job(job_T *job, char_u *how);
--- 41,47 ----
  void mch_new_shellsize(void);
  void mch_set_winsize_now(void);
  int mch_call_shell(char_u *cmd, int options);
! void mch_job_start(char *cmd, job_T *job, jobopt_T *options);
  char *mch_job_status(job_T *job);
  job_T *mch_detect_ended_job(job_T *job_list);
  int mch_stop_job(job_T *job, char_u *how);
*** ../vim-8.0.0743/src/version.c       2017-07-22 17:03:57.371802012 +0200
--- src/version.c       2017-07-22 17:55:21.141633051 +0200
***************
*** 771,772 ****
--- 771,774 ----
  {   /* Add new patch number below this line */
+ /**/
+     744,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
203. You're an active member of more than 20 newsgroups.

 /// 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