mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	In order that people can use formats like #D in #() in the status line
and not have to wait for an update when they change pane, we allow commands to run more than once a second if the expanded form changes. Unfortunately this can mean them being run far too often (pretty much continually) when multiple clients exist, because some formats (including #D) will always differ between clients. To avoid this, give each client its own tree of jobs which means that the same command will be different instances for each client - similar to how we have the tag to separate commands for different panes. GitHub issue 889; test case reported by Paul Johnson.
This commit is contained in:
		
							
								
								
									
										3
									
								
								cfg.c
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								cfg.c
									
									
									
									
									
								
							@@ -148,7 +148,8 @@ load_cfg(const char *path, struct client *c, struct cmdq_item *item, int quiet)
 | 
			
		||||
				    line);
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			ft = format_create(NULL, FORMAT_NONE, FORMAT_NOJOBS);
 | 
			
		||||
			ft = format_create(NULL, NULL, FORMAT_NONE,
 | 
			
		||||
			    FORMAT_NOJOBS);
 | 
			
		||||
 | 
			
		||||
			s = p + 3;
 | 
			
		||||
			while (isspace((u_char)*s))
 | 
			
		||||
 
 | 
			
		||||
@@ -73,7 +73,7 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item)
 | 
			
		||||
	if (template == NULL)
 | 
			
		||||
		template = DISPLAY_MESSAGE_TEMPLATE;
 | 
			
		||||
 | 
			
		||||
	ft = format_create(item, FORMAT_NONE, 0);
 | 
			
		||||
	ft = format_create(item->client, item, FORMAT_NONE, 0);
 | 
			
		||||
	format_defaults(ft, c, s, wl, wp);
 | 
			
		||||
 | 
			
		||||
	msg = format_expand_time(ft, template, time(NULL));
 | 
			
		||||
 
 | 
			
		||||
@@ -57,7 +57,7 @@ cmd_list_buffers_exec(struct cmd *self, struct cmdq_item *item)
 | 
			
		||||
 | 
			
		||||
	pb = NULL;
 | 
			
		||||
	while ((pb = paste_walk(pb)) != NULL) {
 | 
			
		||||
		ft = format_create(item, FORMAT_NONE, 0);
 | 
			
		||||
		ft = format_create(item->client, item, FORMAT_NONE, 0);
 | 
			
		||||
		format_defaults_paste_buffer(ft, pb);
 | 
			
		||||
 | 
			
		||||
		line = format_expand(ft, template);
 | 
			
		||||
 
 | 
			
		||||
@@ -72,7 +72,7 @@ cmd_list_clients_exec(struct cmd *self, struct cmdq_item *item)
 | 
			
		||||
		if (c->session == NULL || (s != NULL && s != c->session))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		ft = format_create(item, FORMAT_NONE, 0);
 | 
			
		||||
		ft = format_create(item->client, item, FORMAT_NONE, 0);
 | 
			
		||||
		format_add(ft, "line", "%u", idx);
 | 
			
		||||
		format_defaults(ft, c, NULL, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -144,7 +144,7 @@ cmd_list_keys_commands(struct cmd *self, struct cmdq_item *item)
 | 
			
		||||
		    "#{command_list_usage}";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ft = format_create(item, FORMAT_NONE, 0);
 | 
			
		||||
	ft = format_create(item->client, item, FORMAT_NONE, 0);
 | 
			
		||||
	format_defaults(ft, NULL, NULL, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
	for (entryp = cmd_table; *entryp != NULL; entryp++) {
 | 
			
		||||
 
 | 
			
		||||
@@ -123,7 +123,7 @@ cmd_list_panes_window(struct cmd *self, struct session *s, struct winlink *wl,
 | 
			
		||||
 | 
			
		||||
	n = 0;
 | 
			
		||||
	TAILQ_FOREACH(wp, &wl->window->panes, entry) {
 | 
			
		||||
		ft = format_create(item, FORMAT_NONE, 0);
 | 
			
		||||
		ft = format_create(item->client, item, FORMAT_NONE, 0);
 | 
			
		||||
		format_add(ft, "line", "%u", n);
 | 
			
		||||
		format_defaults(ft, NULL, s, wl, wp);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -65,7 +65,7 @@ cmd_list_sessions_exec(struct cmd *self, struct cmdq_item *item)
 | 
			
		||||
 | 
			
		||||
	n = 0;
 | 
			
		||||
	RB_FOREACH(s, sessions, &sessions) {
 | 
			
		||||
		ft = format_create(item, FORMAT_NONE, 0);
 | 
			
		||||
		ft = format_create(item->client, item, FORMAT_NONE, 0);
 | 
			
		||||
		format_add(ft, "line", "%u", n);
 | 
			
		||||
		format_defaults(ft, NULL, s, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -86,7 +86,7 @@ cmd_list_windows_session(struct cmd *self, struct session *s,
 | 
			
		||||
{
 | 
			
		||||
	struct args		*args = self->args;
 | 
			
		||||
	struct winlink		*wl;
 | 
			
		||||
	u_int			n;
 | 
			
		||||
	u_int			 n;
 | 
			
		||||
	struct format_tree	*ft;
 | 
			
		||||
	const char		*template;
 | 
			
		||||
	char			*line;
 | 
			
		||||
@@ -105,7 +105,7 @@ cmd_list_windows_session(struct cmd *self, struct session *s,
 | 
			
		||||
 | 
			
		||||
	n = 0;
 | 
			
		||||
	RB_FOREACH(wl, winlinks, &s->windows) {
 | 
			
		||||
		ft = format_create(item, FORMAT_NONE, 0);
 | 
			
		||||
		ft = format_create(item->client, item, FORMAT_NONE, 0);
 | 
			
		||||
		format_add(ft, "line", "%u", n);
 | 
			
		||||
		format_defaults(ft, NULL, s, wl, NULL);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -90,7 +90,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Expand the command. */
 | 
			
		||||
	ft = format_create(item, FORMAT_NONE, 0);
 | 
			
		||||
	ft = format_create(item->client, item, FORMAT_NONE, 0);
 | 
			
		||||
	format_defaults(ft, c, s, wl, wp);
 | 
			
		||||
	cmd = format_expand_time(ft, args->argv[0], time(NULL));
 | 
			
		||||
	format_free(ft);
 | 
			
		||||
 
 | 
			
		||||
@@ -299,7 +299,7 @@ cmdq_format(struct cmdq_item *item, const char *key, const char *fmt, ...)
 | 
			
		||||
	va_end(ap);
 | 
			
		||||
 | 
			
		||||
	if (shared->formats == NULL)
 | 
			
		||||
		shared->formats = format_create(NULL, FORMAT_NONE, 0);
 | 
			
		||||
		shared->formats = format_create(NULL, NULL, FORMAT_NONE, 0);
 | 
			
		||||
	format_add(shared->formats, key, "%s", value);
 | 
			
		||||
 | 
			
		||||
	free(value);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										68
									
								
								format.c
									
									
									
									
									
								
							
							
						
						
									
										68
									
								
								format.c
									
									
									
									
									
								
							@@ -76,6 +76,7 @@ static void	 format_defaults_winlink(struct format_tree *,
 | 
			
		||||
 | 
			
		||||
/* Entry in format job tree. */
 | 
			
		||||
struct format_job {
 | 
			
		||||
	struct client		*client;
 | 
			
		||||
	u_int			 tag;
 | 
			
		||||
	const char		*cmd;
 | 
			
		||||
	const char		*expanded;
 | 
			
		||||
@@ -128,6 +129,7 @@ struct format_tree {
 | 
			
		||||
	struct session		*s;
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
 | 
			
		||||
	struct client		*client;
 | 
			
		||||
	u_int			 tag;
 | 
			
		||||
	int			 flags;
 | 
			
		||||
 | 
			
		||||
@@ -236,7 +238,6 @@ format_job_complete(struct job *job)
 | 
			
		||||
	struct format_job	*fj = job->data;
 | 
			
		||||
	char			*line, *buf;
 | 
			
		||||
	size_t			 len;
 | 
			
		||||
	struct client		*c;
 | 
			
		||||
 | 
			
		||||
	fj->job = NULL;
 | 
			
		||||
 | 
			
		||||
@@ -258,8 +259,8 @@ format_job_complete(struct job *job)
 | 
			
		||||
		free(buf);
 | 
			
		||||
 | 
			
		||||
	if (fj->status) {
 | 
			
		||||
		TAILQ_FOREACH(c, &clients, entry)
 | 
			
		||||
		    server_status_client(c);
 | 
			
		||||
		if (fj->client != NULL)
 | 
			
		||||
			server_status_client(fj->client);
 | 
			
		||||
		fj->status = 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -268,22 +269,33 @@ format_job_complete(struct job *job)
 | 
			
		||||
static char *
 | 
			
		||||
format_job_get(struct format_tree *ft, const char *cmd)
 | 
			
		||||
{
 | 
			
		||||
	struct format_job_tree	*jobs;
 | 
			
		||||
	struct format_job	 fj0, *fj;
 | 
			
		||||
	time_t			 t;
 | 
			
		||||
	char			*expanded;
 | 
			
		||||
	int			 force;
 | 
			
		||||
 | 
			
		||||
	if (ft->client == NULL)
 | 
			
		||||
		jobs = &format_jobs;
 | 
			
		||||
	else if (ft->client->jobs != NULL)
 | 
			
		||||
		jobs = ft->client->jobs;
 | 
			
		||||
	else {
 | 
			
		||||
		jobs = ft->client->jobs = xmalloc(sizeof *ft->client->jobs);
 | 
			
		||||
		RB_INIT(jobs);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fj0.tag = ft->tag;
 | 
			
		||||
	fj0.cmd = cmd;
 | 
			
		||||
	if ((fj = RB_FIND(format_job_tree, &format_jobs, &fj0)) == NULL) {
 | 
			
		||||
	if ((fj = RB_FIND(format_job_tree, jobs, &fj0)) == NULL) {
 | 
			
		||||
		fj = xcalloc(1, sizeof *fj);
 | 
			
		||||
		fj->client = ft->client;
 | 
			
		||||
		fj->tag = ft->tag;
 | 
			
		||||
		fj->cmd = xstrdup(cmd);
 | 
			
		||||
		fj->expanded = NULL;
 | 
			
		||||
 | 
			
		||||
		xasprintf(&fj->out, "<'%s' not ready>", fj->cmd);
 | 
			
		||||
 | 
			
		||||
		RB_INSERT(format_job_tree, &format_jobs, fj);
 | 
			
		||||
		RB_INSERT(format_job_tree, jobs, fj);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	expanded = format_expand(ft, cmd);
 | 
			
		||||
@@ -314,17 +326,16 @@ format_job_get(struct format_tree *ft, const char *cmd)
 | 
			
		||||
 | 
			
		||||
/* Remove old jobs. */
 | 
			
		||||
static void
 | 
			
		||||
format_job_timer(__unused int fd, __unused short events, __unused void *arg)
 | 
			
		||||
format_job_tidy(struct format_job_tree *jobs, int force)
 | 
			
		||||
{
 | 
			
		||||
	struct format_job	*fj, *fj1;
 | 
			
		||||
	time_t			 now;
 | 
			
		||||
	struct timeval		 tv = { .tv_sec = 60 };
 | 
			
		||||
 | 
			
		||||
	now = time(NULL);
 | 
			
		||||
	RB_FOREACH_SAFE(fj, format_job_tree, &format_jobs, fj1) {
 | 
			
		||||
		if (fj->last > now || now - fj->last < 3600)
 | 
			
		||||
	RB_FOREACH_SAFE(fj, format_job_tree, jobs, fj1) {
 | 
			
		||||
		if (!force && (fj->last > now || now - fj->last < 3600))
 | 
			
		||||
			continue;
 | 
			
		||||
		RB_REMOVE(format_job_tree, &format_jobs, fj);
 | 
			
		||||
		RB_REMOVE(format_job_tree, jobs, fj);
 | 
			
		||||
 | 
			
		||||
		log_debug("%s: %s", __func__, fj->cmd);
 | 
			
		||||
 | 
			
		||||
@@ -337,6 +348,29 @@ format_job_timer(__unused int fd, __unused short events, __unused void *arg)
 | 
			
		||||
 | 
			
		||||
		free(fj);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Remove old jobs for client. */
 | 
			
		||||
void
 | 
			
		||||
format_lost_client(struct client *c)
 | 
			
		||||
{
 | 
			
		||||
	if (c->jobs != NULL)
 | 
			
		||||
		format_job_tidy(c->jobs, 1);
 | 
			
		||||
	free(c->jobs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Remove old jobs periodically. */
 | 
			
		||||
static void
 | 
			
		||||
format_job_timer(__unused int fd, __unused short events, __unused void *arg)
 | 
			
		||||
{
 | 
			
		||||
	struct client	*c;
 | 
			
		||||
	struct timeval	 tv = { .tv_sec = 60 };
 | 
			
		||||
 | 
			
		||||
	format_job_tidy(&format_jobs, 0);
 | 
			
		||||
	TAILQ_FOREACH(c, &clients, entry) {
 | 
			
		||||
		if (c->jobs != NULL)
 | 
			
		||||
			format_job_tidy(c->jobs, 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	evtimer_del(&format_job_event);
 | 
			
		||||
	evtimer_add(&format_job_event, &tv);
 | 
			
		||||
@@ -533,7 +567,7 @@ format_merge(struct format_tree *ft, struct format_tree *from)
 | 
			
		||||
 | 
			
		||||
/* Create a new tree. */
 | 
			
		||||
struct format_tree *
 | 
			
		||||
format_create(struct cmdq_item *item, int tag, int flags)
 | 
			
		||||
format_create(struct client *c, struct cmdq_item *item, int tag, int flags)
 | 
			
		||||
{
 | 
			
		||||
	struct format_tree	*ft;
 | 
			
		||||
 | 
			
		||||
@@ -545,6 +579,11 @@ format_create(struct cmdq_item *item, int tag, int flags)
 | 
			
		||||
	ft = xcalloc(1, sizeof *ft);
 | 
			
		||||
	RB_INIT(&ft->tree);
 | 
			
		||||
 | 
			
		||||
	if (c != NULL) {
 | 
			
		||||
		ft->client = c;
 | 
			
		||||
		ft->client->references++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ft->tag = tag;
 | 
			
		||||
	ft->flags = flags;
 | 
			
		||||
 | 
			
		||||
@@ -577,6 +616,8 @@ format_free(struct format_tree *ft)
 | 
			
		||||
		free(fe);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (ft->client != NULL)
 | 
			
		||||
		server_client_unref(ft->client);
 | 
			
		||||
	free(ft);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1099,7 +1140,10 @@ format_single(struct cmdq_item *item, const char *fmt, struct client *c,
 | 
			
		||||
	struct format_tree	*ft;
 | 
			
		||||
	char			*expanded;
 | 
			
		||||
 | 
			
		||||
	ft = format_create(item, FORMAT_NONE, 0);
 | 
			
		||||
	if (item != NULL)
 | 
			
		||||
		ft = format_create(item->client, item, FORMAT_NONE, 0);
 | 
			
		||||
	else
 | 
			
		||||
		ft = format_create(NULL, item, FORMAT_NONE, 0);
 | 
			
		||||
	format_defaults(ft, c, s, wl, wp);
 | 
			
		||||
 | 
			
		||||
	expanded = format_expand(ft, fmt);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								names.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								names.c
									
									
									
									
									
								
							@@ -124,7 +124,7 @@ format_window_name(struct window *w)
 | 
			
		||||
	const char		*fmt;
 | 
			
		||||
	char			*name;
 | 
			
		||||
 | 
			
		||||
	ft = format_create(NULL, FORMAT_WINDOW|w->id, 0);
 | 
			
		||||
	ft = format_create(NULL, NULL, FORMAT_WINDOW|w->id, 0);
 | 
			
		||||
	format_defaults_window(ft, w);
 | 
			
		||||
	format_defaults_pane(ft, w->active);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -280,7 +280,7 @@ screen_redraw_make_pane_status(struct client *c, struct window *w,
 | 
			
		||||
 | 
			
		||||
	fmt = options_get_string(w->options, "pane-border-format");
 | 
			
		||||
 | 
			
		||||
	ft = format_create(NULL, FORMAT_PANE|wp->id, 0);
 | 
			
		||||
	ft = format_create(c, NULL, FORMAT_PANE|wp->id, 0);
 | 
			
		||||
	format_defaults(ft, c, NULL, NULL, wp);
 | 
			
		||||
 | 
			
		||||
	memcpy(&old, &wp->status_screen, sizeof old);
 | 
			
		||||
 
 | 
			
		||||
@@ -283,6 +283,7 @@ server_client_lost(struct client *c)
 | 
			
		||||
	free(c->prompt_string);
 | 
			
		||||
	free(c->prompt_buffer);
 | 
			
		||||
 | 
			
		||||
	format_lost_client(c);
 | 
			
		||||
	environ_free(c->environ);
 | 
			
		||||
 | 
			
		||||
	proc_remove_peer(c->peer);
 | 
			
		||||
@@ -1326,7 +1327,7 @@ server_client_set_title(struct client *c)
 | 
			
		||||
 | 
			
		||||
	template = options_get_string(s->options, "set-titles-string");
 | 
			
		||||
 | 
			
		||||
	ft = format_create(NULL, FORMAT_NONE, 0);
 | 
			
		||||
	ft = format_create(c, NULL, FORMAT_NONE, 0);
 | 
			
		||||
	format_defaults(ft, c, NULL, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
	title = format_expand_time(ft, template, time(NULL));
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								status.c
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								status.c
									
									
									
									
									
								
							@@ -519,9 +519,9 @@ status_replace(struct client *c, struct winlink *wl, const char *fmt, time_t t)
 | 
			
		||||
	else
 | 
			
		||||
		tag = FORMAT_NONE;
 | 
			
		||||
	if (c->flags & CLIENT_STATUSFORCE)
 | 
			
		||||
		ft = format_create(NULL, tag, FORMAT_STATUS|FORMAT_FORCE);
 | 
			
		||||
		ft = format_create(c, NULL, tag, FORMAT_STATUS|FORMAT_FORCE);
 | 
			
		||||
	else
 | 
			
		||||
		ft = format_create(NULL, tag, FORMAT_STATUS);
 | 
			
		||||
		ft = format_create(c, NULL, tag, FORMAT_STATUS);
 | 
			
		||||
	format_defaults(ft, c, NULL, wl, NULL);
 | 
			
		||||
 | 
			
		||||
	expanded = format_expand_time(ft, fmt, t);
 | 
			
		||||
@@ -663,7 +663,7 @@ status_prompt_set(struct client *c, const char *msg, const char *input,
 | 
			
		||||
	time_t			 t;
 | 
			
		||||
	char			*tmp;
 | 
			
		||||
 | 
			
		||||
	ft = format_create(NULL, FORMAT_NONE, 0);
 | 
			
		||||
	ft = format_create(c, NULL, FORMAT_NONE, 0);
 | 
			
		||||
	format_defaults(ft, c, NULL, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
	t = time(NULL);
 | 
			
		||||
@@ -724,7 +724,7 @@ status_prompt_update(struct client *c, const char *msg, const char *input)
 | 
			
		||||
	time_t			 t;
 | 
			
		||||
	char			*tmp;
 | 
			
		||||
 | 
			
		||||
	ft = format_create(NULL, FORMAT_NONE, 0);
 | 
			
		||||
	ft = format_create(c, NULL, FORMAT_NONE, 0);
 | 
			
		||||
	format_defaults(ft, c, NULL, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
	t = time(NULL);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								tmux.h
									
									
									
									
									
								
							@@ -43,6 +43,7 @@ struct client;
 | 
			
		||||
struct cmdq_item;
 | 
			
		||||
struct cmdq_list;
 | 
			
		||||
struct environ;
 | 
			
		||||
struct format_job_tree;
 | 
			
		||||
struct input_ctx;
 | 
			
		||||
struct mode_key_cmdstr;
 | 
			
		||||
struct mouse_event;
 | 
			
		||||
@@ -1290,6 +1291,7 @@ struct client {
 | 
			
		||||
	struct timeval	 activity_time;
 | 
			
		||||
 | 
			
		||||
	struct environ	*environ;
 | 
			
		||||
	struct format_job_tree	*jobs;
 | 
			
		||||
 | 
			
		||||
	char		*title;
 | 
			
		||||
	const char	*cwd;
 | 
			
		||||
@@ -1501,7 +1503,8 @@ char		*paste_make_sample(struct paste_buffer *);
 | 
			
		||||
#define FORMAT_PANE 0x80000000U
 | 
			
		||||
#define FORMAT_WINDOW 0x40000000U
 | 
			
		||||
struct format_tree;
 | 
			
		||||
struct format_tree *format_create(struct cmdq_item *, int, int);
 | 
			
		||||
struct format_tree *format_create(struct client *, struct cmdq_item *, int,
 | 
			
		||||
		     int);
 | 
			
		||||
void		 format_free(struct format_tree *);
 | 
			
		||||
void printflike(3, 4) format_add(struct format_tree *, const char *,
 | 
			
		||||
		     const char *, ...);
 | 
			
		||||
@@ -1517,6 +1520,7 @@ void		 format_defaults_pane(struct format_tree *,
 | 
			
		||||
		     struct window_pane *);
 | 
			
		||||
void		 format_defaults_paste_buffer(struct format_tree *,
 | 
			
		||||
		     struct paste_buffer *);
 | 
			
		||||
void		 format_lost_client(struct client *);
 | 
			
		||||
 | 
			
		||||
/* hooks.c */
 | 
			
		||||
struct hook;
 | 
			
		||||
 
 | 
			
		||||
@@ -202,7 +202,7 @@ window_choose_data_create(int type, struct client *c, struct session *s)
 | 
			
		||||
	wcd = xmalloc(sizeof *wcd);
 | 
			
		||||
	wcd->type = type;
 | 
			
		||||
 | 
			
		||||
	wcd->ft = format_create(NULL, FORMAT_NONE, 0);
 | 
			
		||||
	wcd->ft = format_create(c, NULL, FORMAT_NONE, 0);
 | 
			
		||||
	wcd->ft_template = NULL;
 | 
			
		||||
 | 
			
		||||
	wcd->command = NULL;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user