mirror of
https://github.com/tmux/tmux.git
synced 2025-09-02 05:21:10 +00:00
Merge branch 'obsd-master'
This commit is contained in:
@ -132,14 +132,16 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
static void
|
static void
|
||||||
cmd_if_shell_callback(struct job *job)
|
cmd_if_shell_callback(struct job *job)
|
||||||
{
|
{
|
||||||
struct cmd_if_shell_data *cdata = job->data;
|
struct cmd_if_shell_data *cdata = job_get_data(job);
|
||||||
struct client *c = cdata->client;
|
struct client *c = cdata->client;
|
||||||
struct cmd_list *cmdlist;
|
struct cmd_list *cmdlist;
|
||||||
struct cmdq_item *new_item;
|
struct cmdq_item *new_item;
|
||||||
char *cause, *cmd, *file = cdata->file;
|
char *cause, *cmd, *file = cdata->file;
|
||||||
u_int line = cdata->line;
|
u_int line = cdata->line;
|
||||||
|
int status;
|
||||||
|
|
||||||
if (!WIFEXITED(job->status) || WEXITSTATUS(job->status) != 0)
|
status = job_get_status(job);
|
||||||
|
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
|
||||||
cmd = cdata->cmd_else;
|
cmd = cdata->cmd_else;
|
||||||
else
|
else
|
||||||
cmd = cdata->cmd_if;
|
cmd = cdata->cmd_if;
|
||||||
|
@ -57,7 +57,7 @@ struct cmd_run_shell_data {
|
|||||||
static void
|
static void
|
||||||
cmd_run_shell_print(struct job *job, const char *msg)
|
cmd_run_shell_print(struct job *job, const char *msg)
|
||||||
{
|
{
|
||||||
struct cmd_run_shell_data *cdata = job->data;
|
struct cmd_run_shell_data *cdata = job_get_data(job);
|
||||||
struct window_pane *wp = NULL;
|
struct window_pane *wp = NULL;
|
||||||
struct cmd_find_state fs;
|
struct cmd_find_state fs;
|
||||||
|
|
||||||
@ -113,22 +113,23 @@ cmd_run_shell_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
static void
|
static void
|
||||||
cmd_run_shell_callback(struct job *job)
|
cmd_run_shell_callback(struct job *job)
|
||||||
{
|
{
|
||||||
struct cmd_run_shell_data *cdata = job->data;
|
struct cmd_run_shell_data *cdata = job_get_data(job);
|
||||||
char *cmd = cdata->cmd, *msg, *line;
|
struct bufferevent *event = job_get_event(job);
|
||||||
|
char *cmd = cdata->cmd, *msg = NULL, *line;
|
||||||
size_t size;
|
size_t size;
|
||||||
int retcode;
|
int retcode, status;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if ((line = evbuffer_readline(job->event->input)) != NULL) {
|
if ((line = evbuffer_readline(event->input)) != NULL) {
|
||||||
cmd_run_shell_print(job, line);
|
cmd_run_shell_print(job, line);
|
||||||
free(line);
|
free(line);
|
||||||
}
|
}
|
||||||
} while (line != NULL);
|
} while (line != NULL);
|
||||||
|
|
||||||
size = EVBUFFER_LENGTH(job->event->input);
|
size = EVBUFFER_LENGTH(event->input);
|
||||||
if (size != 0) {
|
if (size != 0) {
|
||||||
line = xmalloc(size + 1);
|
line = xmalloc(size + 1);
|
||||||
memcpy(line, EVBUFFER_DATA(job->event->input), size);
|
memcpy(line, EVBUFFER_DATA(event->input), size);
|
||||||
line[size] = '\0';
|
line[size] = '\0';
|
||||||
|
|
||||||
cmd_run_shell_print(job, line);
|
cmd_run_shell_print(job, line);
|
||||||
@ -136,12 +137,12 @@ cmd_run_shell_callback(struct job *job)
|
|||||||
free(line);
|
free(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
msg = NULL;
|
status = job_get_status(job);
|
||||||
if (WIFEXITED(job->status)) {
|
if (WIFEXITED(status)) {
|
||||||
if ((retcode = WEXITSTATUS(job->status)) != 0)
|
if ((retcode = WEXITSTATUS(status)) != 0)
|
||||||
xasprintf(&msg, "'%s' returned %d", cmd, retcode);
|
xasprintf(&msg, "'%s' returned %d", cmd, retcode);
|
||||||
} else if (WIFSIGNALED(job->status)) {
|
} else if (WIFSIGNALED(status)) {
|
||||||
retcode = WTERMSIG(job->status);
|
retcode = WTERMSIG(status);
|
||||||
xasprintf(&msg, "'%s' terminated by signal %d", cmd, retcode);
|
xasprintf(&msg, "'%s' terminated by signal %d", cmd, retcode);
|
||||||
}
|
}
|
||||||
if (msg != NULL)
|
if (msg != NULL)
|
||||||
|
@ -43,7 +43,6 @@ const struct cmd_entry cmd_show_messages_entry = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static int cmd_show_messages_terminals(struct cmdq_item *, int);
|
static int cmd_show_messages_terminals(struct cmdq_item *, int);
|
||||||
static int cmd_show_messages_jobs(struct cmdq_item *, int);
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cmd_show_messages_terminals(struct cmdq_item *item, int blank)
|
cmd_show_messages_terminals(struct cmdq_item *item, int blank)
|
||||||
@ -66,25 +65,6 @@ cmd_show_messages_terminals(struct cmdq_item *item, int blank)
|
|||||||
return (n != 0);
|
return (n != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
cmd_show_messages_jobs(struct cmdq_item *item, int blank)
|
|
||||||
{
|
|
||||||
struct job *job;
|
|
||||||
u_int n;
|
|
||||||
|
|
||||||
n = 0;
|
|
||||||
LIST_FOREACH(job, &all_jobs, entry) {
|
|
||||||
if (blank) {
|
|
||||||
cmdq_print(item, "%s", "");
|
|
||||||
blank = 0;
|
|
||||||
}
|
|
||||||
cmdq_print(item, "Job %u: %s [fd=%d, pid=%ld, status=%d]",
|
|
||||||
n, job->cmd, job->fd, (long)job->pid, job->status);
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
return (n != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cmd_show_messages_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_show_messages_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
@ -103,7 +83,7 @@ cmd_show_messages_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
done = 1;
|
done = 1;
|
||||||
}
|
}
|
||||||
if (args_has(args, 'J')) {
|
if (args_has(args, 'J')) {
|
||||||
cmd_show_messages_jobs(item, blank);
|
job_print_summary(item, blank);
|
||||||
done = 1;
|
done = 1;
|
||||||
}
|
}
|
||||||
if (done)
|
if (done)
|
||||||
|
13
format.c
13
format.c
@ -191,8 +191,8 @@ static const char *format_lower[] = {
|
|||||||
static void
|
static void
|
||||||
format_job_update(struct job *job)
|
format_job_update(struct job *job)
|
||||||
{
|
{
|
||||||
struct format_job *fj = job->data;
|
struct format_job *fj = job_get_data(job);
|
||||||
struct evbuffer *evb = job->event->input;
|
struct evbuffer *evb = job_get_event(job)->input;
|
||||||
char *line = NULL, *next;
|
char *line = NULL, *next;
|
||||||
time_t t;
|
time_t t;
|
||||||
|
|
||||||
@ -221,18 +221,19 @@ format_job_update(struct job *job)
|
|||||||
static void
|
static void
|
||||||
format_job_complete(struct job *job)
|
format_job_complete(struct job *job)
|
||||||
{
|
{
|
||||||
struct format_job *fj = job->data;
|
struct format_job *fj = job_get_data(job);
|
||||||
|
struct evbuffer *evb = job_get_event(job)->input;
|
||||||
char *line, *buf;
|
char *line, *buf;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
fj->job = NULL;
|
fj->job = NULL;
|
||||||
|
|
||||||
buf = NULL;
|
buf = NULL;
|
||||||
if ((line = evbuffer_readline(job->event->input)) == NULL) {
|
if ((line = evbuffer_readline(evb)) == NULL) {
|
||||||
len = EVBUFFER_LENGTH(job->event->input);
|
len = EVBUFFER_LENGTH(evb);
|
||||||
buf = xmalloc(len + 1);
|
buf = xmalloc(len + 1);
|
||||||
if (len != 0)
|
if (len != 0)
|
||||||
memcpy(buf, EVBUFFER_DATA(job->event->input), len);
|
memcpy(buf, EVBUFFER_DATA(evb), len);
|
||||||
buf[len] = '\0';
|
buf[len] = '\0';
|
||||||
} else
|
} else
|
||||||
buf = line;
|
buf = line;
|
||||||
|
100
job.c
100
job.c
@ -36,8 +36,32 @@ static void job_read_callback(struct bufferevent *, void *);
|
|||||||
static void job_write_callback(struct bufferevent *, void *);
|
static void job_write_callback(struct bufferevent *, void *);
|
||||||
static void job_error_callback(struct bufferevent *, short, void *);
|
static void job_error_callback(struct bufferevent *, short, void *);
|
||||||
|
|
||||||
|
struct job {
|
||||||
|
enum {
|
||||||
|
JOB_RUNNING,
|
||||||
|
JOB_DEAD,
|
||||||
|
JOB_CLOSED
|
||||||
|
} state;
|
||||||
|
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
char *cmd;
|
||||||
|
pid_t pid;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
int fd;
|
||||||
|
struct bufferevent *event;
|
||||||
|
|
||||||
|
job_update_cb updatecb;
|
||||||
|
job_complete_cb completecb;
|
||||||
|
job_free_cb freecb;
|
||||||
|
void *data;
|
||||||
|
|
||||||
|
LIST_ENTRY(job) entry;
|
||||||
|
};
|
||||||
|
|
||||||
/* All jobs list. */
|
/* All jobs list. */
|
||||||
struct joblist all_jobs = LIST_HEAD_INITIALIZER(all_jobs);
|
LIST_HEAD(joblist, job) all_jobs = LIST_HEAD_INITIALIZER(all_jobs);
|
||||||
|
|
||||||
/* Start a job running, if it isn't already. */
|
/* Start a job running, if it isn't already. */
|
||||||
struct job *
|
struct job *
|
||||||
@ -207,8 +231,16 @@ job_error_callback(__unused struct bufferevent *bufev, __unused short events,
|
|||||||
|
|
||||||
/* Job died (waitpid() returned its pid). */
|
/* Job died (waitpid() returned its pid). */
|
||||||
void
|
void
|
||||||
job_died(struct job *job, int status)
|
job_check_died(pid_t pid, int status)
|
||||||
{
|
{
|
||||||
|
struct job *job;
|
||||||
|
|
||||||
|
LIST_FOREACH(job, &all_jobs, entry) {
|
||||||
|
if (pid == job->pid)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (job == NULL)
|
||||||
|
return;
|
||||||
log_debug("job died %p: %s, pid %ld", job, job->cmd, (long) job->pid);
|
log_debug("job died %p: %s, pid %ld", job, job->cmd, (long) job->pid);
|
||||||
|
|
||||||
job->status = status;
|
job->status = status;
|
||||||
@ -222,3 +254,67 @@ job_died(struct job *job, int status)
|
|||||||
job->state = JOB_DEAD;
|
job->state = JOB_DEAD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get job status. */
|
||||||
|
int
|
||||||
|
job_get_status(struct job *job)
|
||||||
|
{
|
||||||
|
return (job->status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get job data. */
|
||||||
|
void *
|
||||||
|
job_get_data(struct job *job)
|
||||||
|
{
|
||||||
|
return (job->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get job event. */
|
||||||
|
struct bufferevent *
|
||||||
|
job_get_event(struct job *job)
|
||||||
|
{
|
||||||
|
return (job->event);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Kill all jobs. */
|
||||||
|
void
|
||||||
|
job_kill_all(void)
|
||||||
|
{
|
||||||
|
struct job *job;
|
||||||
|
|
||||||
|
LIST_FOREACH(job, &all_jobs, entry) {
|
||||||
|
if (job->pid != -1)
|
||||||
|
kill(job->pid, SIGTERM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Are any jobs still running? */
|
||||||
|
int
|
||||||
|
job_still_running(void)
|
||||||
|
{
|
||||||
|
struct job *job;
|
||||||
|
|
||||||
|
LIST_FOREACH(job, &all_jobs, entry) {
|
||||||
|
if ((~job->flags & JOB_NOWAIT) && job->state == JOB_RUNNING)
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print job summary. */
|
||||||
|
void
|
||||||
|
job_print_summary(struct cmdq_item *item, int blank)
|
||||||
|
{
|
||||||
|
struct job *job;
|
||||||
|
u_int n = 0;
|
||||||
|
|
||||||
|
LIST_FOREACH(job, &all_jobs, entry) {
|
||||||
|
if (blank) {
|
||||||
|
cmdq_print(item, "%s", "");
|
||||||
|
blank = 0;
|
||||||
|
}
|
||||||
|
cmdq_print(item, "Job %u: %s [fd=%d, pid=%ld, status=%d]",
|
||||||
|
n, job->cmd, job->fd, (long)job->pid, job->status);
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
25
server.c
25
server.c
@ -161,7 +161,6 @@ server_start(struct tmuxproc *client, struct event_base *base, int lockfd,
|
|||||||
char *lockfile)
|
char *lockfile)
|
||||||
{
|
{
|
||||||
int pair[2];
|
int pair[2];
|
||||||
struct job *job;
|
|
||||||
sigset_t set, oldset;
|
sigset_t set, oldset;
|
||||||
struct client *c;
|
struct client *c;
|
||||||
char *cause = NULL;
|
char *cause = NULL;
|
||||||
@ -222,17 +221,13 @@ server_start(struct tmuxproc *client, struct event_base *base, int lockfd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
start_cfg();
|
start_cfg();
|
||||||
|
|
||||||
server_add_accept(0);
|
server_add_accept(0);
|
||||||
|
|
||||||
proc_loop(server_proc, server_loop);
|
proc_loop(server_proc, server_loop);
|
||||||
|
|
||||||
LIST_FOREACH(job, &all_jobs, entry) {
|
job_kill_all();
|
||||||
if (job->pid != -1)
|
|
||||||
kill(job->pid, SIGTERM);
|
|
||||||
}
|
|
||||||
|
|
||||||
status_prompt_save_history();
|
status_prompt_save_history();
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,7 +237,6 @@ server_loop(void)
|
|||||||
{
|
{
|
||||||
struct client *c;
|
struct client *c;
|
||||||
u_int items;
|
u_int items;
|
||||||
struct job *job;
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
items = cmdq_next(NULL);
|
items = cmdq_next(NULL);
|
||||||
@ -275,10 +269,8 @@ server_loop(void)
|
|||||||
if (!TAILQ_EMPTY(&clients))
|
if (!TAILQ_EMPTY(&clients))
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
LIST_FOREACH(job, &all_jobs, entry) {
|
if (job_still_running())
|
||||||
if ((~job->flags & JOB_NOWAIT) && job->state == JOB_RUNNING)
|
return (0);
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
@ -456,7 +448,6 @@ server_child_exited(pid_t pid, int status)
|
|||||||
{
|
{
|
||||||
struct window *w, *w1;
|
struct window *w, *w1;
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
struct job *job;
|
|
||||||
|
|
||||||
RB_FOREACH_SAFE(w, windows, &windows, w1) {
|
RB_FOREACH_SAFE(w, windows, &windows, w1) {
|
||||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||||
@ -473,13 +464,7 @@ server_child_exited(pid_t pid, int status)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
job_check_died(pid, status);
|
||||||
LIST_FOREACH(job, &all_jobs, entry) {
|
|
||||||
if (pid == job->pid) {
|
|
||||||
job_died(job, status); /* might free job */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle stopped children. */
|
/* Handle stopped children. */
|
||||||
|
45
tmux.h
45
tmux.h
@ -46,6 +46,7 @@ struct cmdq_list;
|
|||||||
struct environ;
|
struct environ;
|
||||||
struct format_job_tree;
|
struct format_job_tree;
|
||||||
struct input_ctx;
|
struct input_ctx;
|
||||||
|
struct job;
|
||||||
struct mode_tree_data;
|
struct mode_tree_data;
|
||||||
struct mouse_event;
|
struct mouse_event;
|
||||||
struct options;
|
struct options;
|
||||||
@ -627,37 +628,6 @@ struct hook {
|
|||||||
RB_ENTRY(hook) entry;
|
RB_ENTRY(hook) entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Scheduled job. */
|
|
||||||
struct job;
|
|
||||||
typedef void (*job_update_cb) (struct job *);
|
|
||||||
typedef void (*job_complete_cb) (struct job *);
|
|
||||||
typedef void (*job_free_cb) (void *);
|
|
||||||
struct job {
|
|
||||||
enum {
|
|
||||||
JOB_RUNNING,
|
|
||||||
JOB_DEAD,
|
|
||||||
JOB_CLOSED
|
|
||||||
} state;
|
|
||||||
|
|
||||||
int flags;
|
|
||||||
#define JOB_NOWAIT 0x1
|
|
||||||
|
|
||||||
char *cmd;
|
|
||||||
pid_t pid;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
int fd;
|
|
||||||
struct bufferevent *event;
|
|
||||||
|
|
||||||
job_update_cb updatecb;
|
|
||||||
job_complete_cb completecb;
|
|
||||||
job_free_cb freecb;
|
|
||||||
void *data;
|
|
||||||
|
|
||||||
LIST_ENTRY(job) entry;
|
|
||||||
};
|
|
||||||
LIST_HEAD(joblist, job);
|
|
||||||
|
|
||||||
/* Virtual screen. */
|
/* Virtual screen. */
|
||||||
struct screen_sel;
|
struct screen_sel;
|
||||||
struct screen_titles;
|
struct screen_titles;
|
||||||
@ -1659,11 +1629,20 @@ void options_style_update_old(struct options *,
|
|||||||
extern const struct options_table_entry options_table[];
|
extern const struct options_table_entry options_table[];
|
||||||
|
|
||||||
/* job.c */
|
/* job.c */
|
||||||
extern struct joblist all_jobs;
|
typedef void (*job_update_cb) (struct job *);
|
||||||
|
typedef void (*job_complete_cb) (struct job *);
|
||||||
|
typedef void (*job_free_cb) (void *);
|
||||||
|
#define JOB_NOWAIT 0x1
|
||||||
struct job *job_run(const char *, struct session *, const char *,
|
struct job *job_run(const char *, struct session *, const char *,
|
||||||
job_update_cb, job_complete_cb, job_free_cb, void *, int);
|
job_update_cb, job_complete_cb, job_free_cb, void *, int);
|
||||||
void job_free(struct job *);
|
void job_free(struct job *);
|
||||||
void job_died(struct job *, int);
|
void job_check_died(pid_t, int);
|
||||||
|
int job_get_status(struct job *);
|
||||||
|
void *job_get_data(struct job *);
|
||||||
|
struct bufferevent *job_get_event(struct job *);
|
||||||
|
void job_kill_all(void);
|
||||||
|
int job_still_running(void);
|
||||||
|
void job_print_summary(struct cmdq_item *, int);
|
||||||
|
|
||||||
/* environ.c */
|
/* environ.c */
|
||||||
struct environ *environ_create(void);
|
struct environ *environ_create(void);
|
||||||
|
@ -1687,7 +1687,7 @@ window_copy_copy_pipe(struct window_pane *wp, struct session *s,
|
|||||||
expanded = format_single(NULL, arg, NULL, s, NULL, wp);
|
expanded = format_single(NULL, arg, NULL, s, NULL, wp);
|
||||||
|
|
||||||
job = job_run(expanded, s, NULL, NULL, NULL, NULL, NULL, JOB_NOWAIT);
|
job = job_run(expanded, s, NULL, NULL, NULL, NULL, NULL, JOB_NOWAIT);
|
||||||
bufferevent_write(job->event, buf, len);
|
bufferevent_write(job_get_event(job), buf, len);
|
||||||
|
|
||||||
free(expanded);
|
free(expanded);
|
||||||
window_copy_copy_buffer(wp, bufname, buf, len);
|
window_copy_copy_buffer(wp, bufname, buf, len);
|
||||||
|
Reference in New Issue
Block a user