mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	Move job struct into job.c.
This commit is contained in:
		@@ -132,14 +132,16 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item)
 | 
			
		||||
static void
 | 
			
		||||
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 cmd_list			*cmdlist;
 | 
			
		||||
	struct cmdq_item		*new_item;
 | 
			
		||||
	char				*cause, *cmd, *file = cdata->file;
 | 
			
		||||
	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;
 | 
			
		||||
	else
 | 
			
		||||
		cmd = cdata->cmd_if;
 | 
			
		||||
 
 | 
			
		||||
@@ -57,7 +57,7 @@ struct cmd_run_shell_data {
 | 
			
		||||
static void
 | 
			
		||||
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 cmd_find_state		 fs;
 | 
			
		||||
 | 
			
		||||
@@ -113,22 +113,23 @@ cmd_run_shell_exec(struct cmd *self, struct cmdq_item *item)
 | 
			
		||||
static void
 | 
			
		||||
cmd_run_shell_callback(struct job *job)
 | 
			
		||||
{
 | 
			
		||||
	struct cmd_run_shell_data	*cdata = job->data;
 | 
			
		||||
	char				*cmd = cdata->cmd, *msg, *line;
 | 
			
		||||
	struct cmd_run_shell_data	*cdata = job_get_data(job);
 | 
			
		||||
	struct bufferevent		*event = job_get_event(job);
 | 
			
		||||
	char				*cmd = cdata->cmd, *msg = NULL, *line;
 | 
			
		||||
	size_t				 size;
 | 
			
		||||
	int				 retcode;
 | 
			
		||||
	int				 retcode, status;
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		if ((line = evbuffer_readline(job->event->input)) != NULL) {
 | 
			
		||||
		if ((line = evbuffer_readline(event->input)) != NULL) {
 | 
			
		||||
			cmd_run_shell_print(job, line);
 | 
			
		||||
			free(line);
 | 
			
		||||
		}
 | 
			
		||||
	} while (line != NULL);
 | 
			
		||||
 | 
			
		||||
	size = EVBUFFER_LENGTH(job->event->input);
 | 
			
		||||
	size = EVBUFFER_LENGTH(event->input);
 | 
			
		||||
	if (size != 0) {
 | 
			
		||||
		line = xmalloc(size + 1);
 | 
			
		||||
		memcpy(line, EVBUFFER_DATA(job->event->input), size);
 | 
			
		||||
		memcpy(line, EVBUFFER_DATA(event->input), size);
 | 
			
		||||
		line[size] = '\0';
 | 
			
		||||
 | 
			
		||||
		cmd_run_shell_print(job, line);
 | 
			
		||||
@@ -136,12 +137,12 @@ cmd_run_shell_callback(struct job *job)
 | 
			
		||||
		free(line);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	msg = NULL;
 | 
			
		||||
	if (WIFEXITED(job->status)) {
 | 
			
		||||
		if ((retcode = WEXITSTATUS(job->status)) != 0)
 | 
			
		||||
	status = job_get_status(job);
 | 
			
		||||
	if (WIFEXITED(status)) {
 | 
			
		||||
		if ((retcode = WEXITSTATUS(status)) != 0)
 | 
			
		||||
			xasprintf(&msg, "'%s' returned %d", cmd, retcode);
 | 
			
		||||
	} else if (WIFSIGNALED(job->status)) {
 | 
			
		||||
		retcode = WTERMSIG(job->status);
 | 
			
		||||
	} else if (WIFSIGNALED(status)) {
 | 
			
		||||
		retcode = WTERMSIG(status);
 | 
			
		||||
		xasprintf(&msg, "'%s' terminated by signal %d", cmd, retcode);
 | 
			
		||||
	}
 | 
			
		||||
	if (msg != NULL)
 | 
			
		||||
 
 | 
			
		||||
@@ -44,7 +44,6 @@ const struct cmd_entry cmd_show_messages_entry = {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int	cmd_show_messages_terminals(struct cmdq_item *, int);
 | 
			
		||||
static int	cmd_show_messages_jobs(struct cmdq_item *, int);
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
cmd_show_messages_terminals(struct cmdq_item *item, int blank)
 | 
			
		||||
@@ -67,25 +66,6 @@ cmd_show_messages_terminals(struct cmdq_item *item, int blank)
 | 
			
		||||
	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
 | 
			
		||||
cmd_show_messages_exec(struct cmd *self, struct cmdq_item *item)
 | 
			
		||||
{
 | 
			
		||||
@@ -104,7 +84,7 @@ cmd_show_messages_exec(struct cmd *self, struct cmdq_item *item)
 | 
			
		||||
		done = 1;
 | 
			
		||||
	}
 | 
			
		||||
	if (args_has(args, 'J')) {
 | 
			
		||||
		cmd_show_messages_jobs(item, blank);
 | 
			
		||||
		job_print_summary(item, blank);
 | 
			
		||||
		done = 1;
 | 
			
		||||
	}
 | 
			
		||||
	if (done)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								format.c
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								format.c
									
									
									
									
									
								
							@@ -191,8 +191,8 @@ static const char *format_lower[] = {
 | 
			
		||||
static void
 | 
			
		||||
format_job_update(struct job *job)
 | 
			
		||||
{
 | 
			
		||||
	struct format_job	*fj = job->data;
 | 
			
		||||
	struct evbuffer		*evb = job->event->input;
 | 
			
		||||
	struct format_job	*fj = job_get_data(job);
 | 
			
		||||
	struct evbuffer		*evb = job_get_event(job)->input;
 | 
			
		||||
	char			*line = NULL, *next;
 | 
			
		||||
	time_t			 t;
 | 
			
		||||
 | 
			
		||||
@@ -221,18 +221,19 @@ format_job_update(struct job *job)
 | 
			
		||||
static void
 | 
			
		||||
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;
 | 
			
		||||
	size_t			 len;
 | 
			
		||||
 | 
			
		||||
	fj->job = NULL;
 | 
			
		||||
 | 
			
		||||
	buf = NULL;
 | 
			
		||||
	if ((line = evbuffer_readline(job->event->input)) == NULL) {
 | 
			
		||||
		len = EVBUFFER_LENGTH(job->event->input);
 | 
			
		||||
	if ((line = evbuffer_readline(evb)) == NULL) {
 | 
			
		||||
		len = EVBUFFER_LENGTH(evb);
 | 
			
		||||
		buf = xmalloc(len + 1);
 | 
			
		||||
		if (len != 0)
 | 
			
		||||
			memcpy(buf, EVBUFFER_DATA(job->event->input), len);
 | 
			
		||||
			memcpy(buf, EVBUFFER_DATA(evb), len);
 | 
			
		||||
		buf[len] = '\0';
 | 
			
		||||
	} else
 | 
			
		||||
		buf = line;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										100
									
								
								job.c
									
									
									
									
									
								
							
							
						
						
									
										100
									
								
								job.c
									
									
									
									
									
								
							@@ -37,8 +37,32 @@ static void	job_read_callback(struct bufferevent *, void *);
 | 
			
		||||
static void	job_write_callback(struct bufferevent *, 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. */
 | 
			
		||||
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. */
 | 
			
		||||
struct job *
 | 
			
		||||
@@ -208,8 +232,16 @@ job_error_callback(__unused struct bufferevent *bufev, __unused short events,
 | 
			
		||||
 | 
			
		||||
/* Job died (waitpid() returned its pid). */
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
	job->status = status;
 | 
			
		||||
@@ -223,3 +255,67 @@ job_died(struct job *job, int status)
 | 
			
		||||
		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++;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										23
									
								
								server.c
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								server.c
									
									
									
									
									
								
							@@ -162,7 +162,6 @@ server_start(struct tmuxproc *client, struct event_base *base, int lockfd,
 | 
			
		||||
    char *lockfile)
 | 
			
		||||
{
 | 
			
		||||
	int		 pair[2];
 | 
			
		||||
	struct job	*job;
 | 
			
		||||
	sigset_t	 set, oldset;
 | 
			
		||||
	struct client	*c;
 | 
			
		||||
	char		*cause = NULL;
 | 
			
		||||
@@ -223,17 +222,13 @@ server_start(struct tmuxproc *client, struct event_base *base, int lockfd,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	start_cfg();
 | 
			
		||||
 | 
			
		||||
	server_add_accept(0);
 | 
			
		||||
 | 
			
		||||
	proc_loop(server_proc, server_loop);
 | 
			
		||||
 | 
			
		||||
	LIST_FOREACH(job, &all_jobs, entry) {
 | 
			
		||||
		if (job->pid != -1)
 | 
			
		||||
			kill(job->pid, SIGTERM);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	job_kill_all();
 | 
			
		||||
	status_prompt_save_history();
 | 
			
		||||
 | 
			
		||||
	exit(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -243,7 +238,6 @@ server_loop(void)
 | 
			
		||||
{
 | 
			
		||||
	struct client	*c;
 | 
			
		||||
	u_int		 items;
 | 
			
		||||
	struct job	*job;
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		items = cmdq_next(NULL);
 | 
			
		||||
@@ -276,10 +270,8 @@ server_loop(void)
 | 
			
		||||
	if (!TAILQ_EMPTY(&clients))
 | 
			
		||||
		return (0);
 | 
			
		||||
 | 
			
		||||
	LIST_FOREACH(job, &all_jobs, entry) {
 | 
			
		||||
		if ((~job->flags & JOB_NOWAIT) && job->state == JOB_RUNNING)
 | 
			
		||||
	if (job_still_running())
 | 
			
		||||
		return (0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return (1);
 | 
			
		||||
}
 | 
			
		||||
@@ -457,7 +449,6 @@ server_child_exited(pid_t pid, int status)
 | 
			
		||||
{
 | 
			
		||||
	struct window		*w, *w1;
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
	struct job		*job;
 | 
			
		||||
 | 
			
		||||
	RB_FOREACH_SAFE(w, windows, &windows, w1) {
 | 
			
		||||
		TAILQ_FOREACH(wp, &w->panes, entry) {
 | 
			
		||||
@@ -474,13 +465,7 @@ server_child_exited(pid_t pid, int status)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	LIST_FOREACH(job, &all_jobs, entry) {
 | 
			
		||||
		if (pid == job->pid) {
 | 
			
		||||
			job_died(job, status);	/* might free job */
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	job_check_died(pid, status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Handle stopped children. */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										45
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										45
									
								
								tmux.h
									
									
									
									
									
								
							@@ -44,6 +44,7 @@ struct cmdq_list;
 | 
			
		||||
struct environ;
 | 
			
		||||
struct format_job_tree;
 | 
			
		||||
struct input_ctx;
 | 
			
		||||
struct job;
 | 
			
		||||
struct mode_tree_data;
 | 
			
		||||
struct mouse_event;
 | 
			
		||||
struct options;
 | 
			
		||||
@@ -619,37 +620,6 @@ struct hook {
 | 
			
		||||
	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. */
 | 
			
		||||
struct screen_sel;
 | 
			
		||||
struct screen_titles;
 | 
			
		||||
@@ -1628,11 +1598,20 @@ void		 options_style_update_old(struct options *,
 | 
			
		||||
extern const struct options_table_entry options_table[];
 | 
			
		||||
 | 
			
		||||
/* 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 *,
 | 
			
		||||
		     job_update_cb, job_complete_cb, job_free_cb, void *, int);
 | 
			
		||||
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 */
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
	window_copy_copy_buffer(wp, bufname, buf, len);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user