Mercurial > vim
diff src/os_unix.c @ 8031:ece323e2b57f v7.4.1310
commit https://github.com/vim/vim/commit/6463ca229cb9412581419497924c85fcbfc854ab
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Feb 13 17:04:46 2016 +0100
patch 7.4.1310
Problem: Jobs don't open a channel.
Solution: Create pipes and add them to the channel. Add ch_logfile().
Only Unix for now.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sat, 13 Feb 2016 17:15:05 +0100 |
parents | 75e0831549f1 |
children | c6443e78cf2d |
line wrap: on
line diff
--- a/src/os_unix.c +++ b/src/os_unix.c @@ -3984,6 +3984,42 @@ mch_parse_cmd(char_u *cmd, int use_shcf, } #endif +#if !defined(USE_SYSTEM) || defined(FEAT_JOB) + static void +set_child_environment(void) +{ +# ifdef HAVE_SETENV + char envbuf[50]; +# else + static char envbuf_Rows[20]; + static char envbuf_Columns[20]; +# endif + + /* Simulate to have a dumb terminal (for now) */ +# ifdef HAVE_SETENV + setenv("TERM", "dumb", 1); + sprintf((char *)envbuf, "%ld", Rows); + setenv("ROWS", (char *)envbuf, 1); + sprintf((char *)envbuf, "%ld", Rows); + setenv("LINES", (char *)envbuf, 1); + sprintf((char *)envbuf, "%ld", Columns); + setenv("COLUMNS", (char *)envbuf, 1); +# else + /* + * Putenv does not copy the string, it has to remain valid. + * Use a static array to avoid losing allocated memory. + */ + putenv("TERM=dumb"); + sprintf(envbuf_Rows, "ROWS=%ld", Rows); + putenv(envbuf_Rows); + sprintf(envbuf_Rows, "LINES=%ld", Rows); + putenv(envbuf_Rows); + sprintf(envbuf_Columns, "COLUMNS=%ld", Columns); + putenv(envbuf_Columns); +# endif +} +#endif + int mch_call_shell( char_u *cmd, @@ -4134,12 +4170,6 @@ mch_call_shell( int fd_toshell[2]; /* for pipes */ int fd_fromshell[2]; int pipe_error = FALSE; -# ifdef HAVE_SETENV - char envbuf[50]; -# else - static char envbuf_Rows[20]; - static char envbuf_Columns[20]; -# endif int did_settmode = FALSE; /* settmode(TMODE_RAW) called */ newcmd = vim_strsave(p_sh); @@ -4349,28 +4379,7 @@ mch_call_shell( # endif } # endif - /* Simulate to have a dumb terminal (for now) */ -# ifdef HAVE_SETENV - setenv("TERM", "dumb", 1); - sprintf((char *)envbuf, "%ld", Rows); - setenv("ROWS", (char *)envbuf, 1); - sprintf((char *)envbuf, "%ld", Rows); - setenv("LINES", (char *)envbuf, 1); - sprintf((char *)envbuf, "%ld", Columns); - setenv("COLUMNS", (char *)envbuf, 1); -# else - /* - * Putenv does not copy the string, it has to remain valid. - * Use a static array to avoid losing allocated memory. - */ - putenv("TERM=dumb"); - sprintf(envbuf_Rows, "ROWS=%ld", Rows); - putenv(envbuf_Rows); - sprintf(envbuf_Rows, "LINES=%ld", Rows); - putenv(envbuf_Rows); - sprintf(envbuf_Columns, "COLUMNS=%ld", Columns); - putenv(envbuf_Columns); -# endif + set_child_environment(); /* * stderr is only redirected when using the GUI, so that a @@ -5030,13 +5039,34 @@ error: void mch_start_job(char **argv, job_T *job) { - pid_t pid = fork(); - - if (pid == -1) /* maybe we should use vfork() */ - { - job->jv_status = JOB_FAILED; - } - else if (pid == 0) + pid_t pid; + int fd_in[2]; /* for stdin */ + int fd_out[2]; /* for stdout */ + int fd_err[2]; /* for stderr */ + int ch_idx; + + /* default is to fail */ + job->jv_status = JOB_FAILED; + fd_in[0] = -1; + fd_out[0] = -1; + fd_err[0] = -1; + + /* Open pipes for stdin, stdout, stderr. */ + if ((pipe(fd_in) < 0) || (pipe(fd_out) < 0) ||(pipe(fd_err) < 0)) + goto failed; + + ch_idx = add_channel(); + if (ch_idx < 0) + goto failed; + + pid = fork(); /* maybe we should use vfork() */ + if (pid == -1) + { + /* failed to fork */ + goto failed; + } + + if (pid == 0) { /* child */ reset_signals(); /* handle signals normally */ @@ -5048,17 +5078,62 @@ mch_start_job(char **argv, job_T *job) (void)setsid(); # endif + set_child_environment(); + + /* set up stdin for the child */ + close(fd_in[1]); + close(0); + ignored = dup(fd_in[0]); + close(fd_in[0]); + + /* set up stdout for the child */ + close(fd_out[0]); + close(1); + ignored = dup(fd_out[1]); + close(fd_out[1]); + + /* set up stderr for the child */ + close(fd_err[0]); + close(2); + ignored = dup(fd_err[1]); + close(fd_err[1]); + /* See above for type of argv. */ execvp(argv[0], argv); perror("executing job failed"); _exit(EXEC_FAILED); /* exec failed, return failure code */ } - else - { - /* parent */ - job->jv_pid = pid; - job->jv_status = JOB_STARTED; + + /* parent */ + job->jv_pid = pid; + job->jv_status = JOB_STARTED; + job->jv_channel = ch_idx; + + /* child stdin, stdout and stderr */ + close(fd_in[0]); + close(fd_out[1]); + close(fd_err[1]); + channel_set_pipes(ch_idx, fd_in[1], fd_out[0], fd_err[0]); + channel_set_job(ch_idx, job); + + return; + +failed: + if (fd_in[0] >= 0) + { + close(fd_in[0]); + close(fd_in[1]); + } + if (fd_out[0] >= 0) + { + close(fd_out[0]); + close(fd_out[1]); + } + if (fd_err[0] >= 0) + { + close(fd_err[0]); + close(fd_err[1]); } } @@ -5104,8 +5179,8 @@ mch_job_status(job_T *job) int mch_stop_job(job_T *job, char_u *how) { - int sig = -1; - pid_t job_pid; + int sig = -1; + pid_t job_pid; if (STRCMP(how, "hup") == 0) sig = SIGHUP;