mirror of
https://github.com/tmux/tmux.git
synced 2025-09-02 05:21:10 +00:00
Add a flag to run a background process in a pty as well, not used for
anything yet.
This commit is contained in:
80
job.c
80
job.c
@ -25,6 +25,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <util.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
@ -69,18 +70,15 @@ static LIST_HEAD(joblist, job) all_jobs = LIST_HEAD_INITIALIZER(all_jobs);
|
||||
struct job *
|
||||
job_run(const char *cmd, struct session *s, const char *cwd,
|
||||
job_update_cb updatecb, job_complete_cb completecb, job_free_cb freecb,
|
||||
void *data, int flags)
|
||||
void *data, int flags, int sx, int sy)
|
||||
{
|
||||
struct job *job;
|
||||
struct environ *env;
|
||||
pid_t pid;
|
||||
int nullfd, out[2];
|
||||
int nullfd, out[2], master;
|
||||
const char *home;
|
||||
sigset_t set, oldset;
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, out) != 0)
|
||||
return (NULL);
|
||||
log_debug("%s: cmd=%s, cwd=%s", __func__, cmd, cwd == NULL ? "" : cwd);
|
||||
struct winsize ws;
|
||||
|
||||
/*
|
||||
* Do not set TERM during .tmux.conf, it is nice to be able to use
|
||||
@ -90,13 +88,26 @@ job_run(const char *cmd, struct session *s, const char *cwd,
|
||||
|
||||
sigfillset(&set);
|
||||
sigprocmask(SIG_BLOCK, &set, &oldset);
|
||||
switch (pid = fork()) {
|
||||
|
||||
if (flags & JOB_PTY) {
|
||||
memset(&ws, 0, sizeof ws);
|
||||
ws.ws_col = sx;
|
||||
ws.ws_row = sy;
|
||||
pid = fdforkpty(ptm_fd, &master, NULL, NULL, &ws);
|
||||
} else {
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, out) != 0)
|
||||
goto fail;
|
||||
pid = fork();
|
||||
}
|
||||
log_debug("%s: cmd=%s, cwd=%s", __func__, cmd, cwd == NULL ? "" : cwd);
|
||||
|
||||
switch (pid) {
|
||||
case -1:
|
||||
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||
environ_free(env);
|
||||
close(out[0]);
|
||||
close(out[1]);
|
||||
return (NULL);
|
||||
if (~flags & JOB_PTY) {
|
||||
close(out[0]);
|
||||
close(out[1]);
|
||||
}
|
||||
goto fail;
|
||||
case 0:
|
||||
proc_clear_signals(server_proc, 1);
|
||||
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||
@ -109,22 +120,23 @@ job_run(const char *cmd, struct session *s, const char *cwd,
|
||||
environ_push(env);
|
||||
environ_free(env);
|
||||
|
||||
if (dup2(out[1], STDIN_FILENO) == -1)
|
||||
fatal("dup2 failed");
|
||||
if (dup2(out[1], STDOUT_FILENO) == -1)
|
||||
fatal("dup2 failed");
|
||||
if (out[1] != STDIN_FILENO && out[1] != STDOUT_FILENO)
|
||||
close(out[1]);
|
||||
close(out[0]);
|
||||
|
||||
nullfd = open(_PATH_DEVNULL, O_RDWR, 0);
|
||||
if (nullfd == -1)
|
||||
fatal("open failed");
|
||||
if (dup2(nullfd, STDERR_FILENO) == -1)
|
||||
fatal("dup2 failed");
|
||||
if (nullfd != STDERR_FILENO)
|
||||
close(nullfd);
|
||||
if (~flags & JOB_PTY) {
|
||||
if (dup2(out[1], STDIN_FILENO) == -1)
|
||||
fatal("dup2 failed");
|
||||
if (dup2(out[1], STDOUT_FILENO) == -1)
|
||||
fatal("dup2 failed");
|
||||
if (out[1] != STDIN_FILENO && out[1] != STDOUT_FILENO)
|
||||
close(out[1]);
|
||||
close(out[0]);
|
||||
|
||||
nullfd = open(_PATH_DEVNULL, O_RDWR, 0);
|
||||
if (nullfd == -1)
|
||||
fatal("open failed");
|
||||
if (dup2(nullfd, STDERR_FILENO) == -1)
|
||||
fatal("dup2 failed");
|
||||
if (nullfd != STDERR_FILENO)
|
||||
close(nullfd);
|
||||
}
|
||||
closefrom(STDERR_FILENO + 1);
|
||||
|
||||
execl(_PATH_BSHELL, "sh", "-c", cmd, (char *) NULL);
|
||||
@ -133,7 +145,6 @@ job_run(const char *cmd, struct session *s, const char *cwd,
|
||||
|
||||
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||
environ_free(env);
|
||||
close(out[1]);
|
||||
|
||||
job = xmalloc(sizeof *job);
|
||||
job->state = JOB_RUNNING;
|
||||
@ -150,7 +161,11 @@ job_run(const char *cmd, struct session *s, const char *cwd,
|
||||
job->freecb = freecb;
|
||||
job->data = data;
|
||||
|
||||
job->fd = out[0];
|
||||
if (~flags & JOB_PTY) {
|
||||
close(out[1]);
|
||||
job->fd = out[0];
|
||||
} else
|
||||
job->fd = master;
|
||||
setblocking(job->fd, 0);
|
||||
|
||||
job->event = bufferevent_new(job->fd, job_read_callback,
|
||||
@ -161,6 +176,11 @@ job_run(const char *cmd, struct session *s, const char *cwd,
|
||||
|
||||
log_debug("run job %p: %s, pid %ld", job, job->cmd, (long) job->pid);
|
||||
return (job);
|
||||
|
||||
fail:
|
||||
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||
environ_free(env);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Kill and free an individual job. */
|
||||
@ -209,7 +229,7 @@ job_write_callback(__unused struct bufferevent *bufev, void *data)
|
||||
log_debug("job write %p: %s, pid %ld, output left %zu", job, job->cmd,
|
||||
(long) job->pid, len);
|
||||
|
||||
if (len == 0) {
|
||||
if (len == 0 && (~job->flags & JOB_KEEPWRITE)) {
|
||||
shutdown(job->fd, SHUT_WR);
|
||||
bufferevent_disable(job->event, EV_WRITE);
|
||||
}
|
||||
|
Reference in New Issue
Block a user