format.c revision 1.7
1/* $OpenBSD$ */
2
3/*
4 * Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/types.h>
20#include <sys/wait.h>
21
22#include <errno.h>
23#include <fnmatch.h>
24#include <libgen.h>
25#include <stdarg.h>
26#include <stdlib.h>
27#include <string.h>
28#include <time.h>
29#include <unistd.h>
30
31#include "tmux.h"
32
33/*
34 * Build a list of key-value pairs and use them to expand #{key} entries in a
35 * string.
36 */
37
38struct format_entry;
39typedef void (*format_cb)(struct format_tree *, struct format_entry *);
40
41static char	*format_job_get(struct format_tree *, const char *);
42static void	 format_job_timer(int, short, void *);
43
44static char	*format_find(struct format_tree *, const char *, int);
45static void	 format_add_cb(struct format_tree *, const char *, format_cb);
46static void	 format_add_tv(struct format_tree *, const char *,
47		     struct timeval *);
48static int	 format_replace(struct format_tree *, const char *, size_t,
49		     char **, size_t *, size_t *);
50
51static void	 format_defaults_session(struct format_tree *,
52		     struct session *);
53static void	 format_defaults_client(struct format_tree *, struct client *);
54static void	 format_defaults_winlink(struct format_tree *,
55		     struct winlink *);
56
57/* Entry in format job tree. */
58struct format_job {
59	struct client		*client;
60	u_int			 tag;
61	const char		*cmd;
62	const char		*expanded;
63
64	time_t			 last;
65	char			*out;
66	int			 updated;
67
68	struct job		*job;
69	int			 status;
70
71	RB_ENTRY(format_job)	 entry;
72};
73
74/* Format job tree. */
75static struct event format_job_event;
76static int format_job_cmp(struct format_job *, struct format_job *);
77static RB_HEAD(format_job_tree, format_job) format_jobs = RB_INITIALIZER();
78RB_GENERATE_STATIC(format_job_tree, format_job, entry, format_job_cmp);
79
80/* Format job tree comparison function. */
81static int
82format_job_cmp(struct format_job *fj1, struct format_job *fj2)
83{
84	if (fj1->tag < fj2->tag)
85		return (-1);
86	if (fj1->tag > fj2->tag)
87		return (1);
88	return (strcmp(fj1->cmd, fj2->cmd));
89}
90
91/* Format modifiers. */
92#define FORMAT_TIMESTRING 0x1
93#define FORMAT_BASENAME 0x2
94#define FORMAT_DIRNAME 0x4
95#define FORMAT_SUBSTITUTE 0x8
96
97/* Entry in format tree. */
98struct format_entry {
99	char			*key;
100	char			*value;
101	time_t			 t;
102	format_cb		 cb;
103	RB_ENTRY(format_entry)	 entry;
104};
105
106/* Format entry tree. */
107struct format_tree {
108	struct window		*w;
109	struct winlink		*wl;
110	struct session		*s;
111	struct window_pane	*wp;
112
113	struct client		*client;
114	u_int			 tag;
115	int			 flags;
116
117	RB_HEAD(format_entry_tree, format_entry) tree;
118};
119static int format_entry_cmp(struct format_entry *, struct format_entry *);
120RB_GENERATE_STATIC(format_entry_tree, format_entry, entry, format_entry_cmp);
121
122/* Format entry tree comparison function. */
123static int
124format_entry_cmp(struct format_entry *fe1, struct format_entry *fe2)
125{
126	return (strcmp(fe1->key, fe2->key));
127}
128
129/* Single-character uppercase aliases. */
130static const char *format_upper[] = {
131	NULL,		/* A */
132	NULL,		/* B */
133	NULL,		/* C */
134	"pane_id",	/* D */
135	NULL,		/* E */
136	"window_flags",	/* F */
137	NULL,		/* G */
138	"host",		/* H */
139	"window_index",	/* I */
140	NULL,		/* J */
141	NULL,		/* K */
142	NULL,		/* L */
143	NULL,		/* M */
144	NULL,		/* N */
145	NULL,		/* O */
146	"pane_index",	/* P */
147	NULL,		/* Q */
148	NULL,		/* R */
149	"session_name",	/* S */
150	"pane_title",	/* T */
151	NULL,		/* U */
152	NULL,		/* V */
153	"window_name",	/* W */
154	NULL,		/* X */
155	NULL,		/* Y */
156	NULL 		/* Z */
157};
158
159/* Single-character lowercase aliases. */
160static const char *format_lower[] = {
161	NULL,		/* a */
162	NULL,		/* b */
163	NULL,		/* c */
164	NULL,		/* d */
165	NULL,		/* e */
166	NULL,		/* f */
167	NULL,		/* g */
168	"host_short",	/* h */
169	NULL,		/* i */
170	NULL,		/* j */
171	NULL,		/* k */
172	NULL,		/* l */
173	NULL,		/* m */
174	NULL,		/* n */
175	NULL,		/* o */
176	NULL,		/* p */
177	NULL,		/* q */
178	NULL,		/* r */
179	NULL,		/* s */
180	NULL,		/* t */
181	NULL,		/* u */
182	NULL,		/* v */
183	NULL,		/* w */
184	NULL,		/* x */
185	NULL,		/* y */
186	NULL		/* z */
187};
188
189/* Format job update callback. */
190static void
191format_job_update(struct job *job)
192{
193	struct format_job	*fj = job->data;
194	char			*line;
195	time_t			 t;
196
197	if ((line = evbuffer_readline(job->event->input)) == NULL)
198		return;
199	fj->updated = 1;
200
201	free(fj->out);
202	fj->out = line;
203
204	log_debug("%s: %p %s: %s", __func__, fj, fj->cmd, fj->out);
205
206	t = time(NULL);
207	if (fj->status && fj->last != t) {
208		if (fj->client != NULL)
209			server_status_client(fj->client);
210		fj->last = t;
211	}
212}
213
214/* Format job complete callback. */
215static void
216format_job_complete(struct job *job)
217{
218	struct format_job	*fj = job->data;
219	char			*line, *buf;
220	size_t			 len;
221
222	fj->job = NULL;
223
224	buf = NULL;
225	if ((line = evbuffer_readline(job->event->input)) == NULL) {
226		len = EVBUFFER_LENGTH(job->event->input);
227		buf = xmalloc(len + 1);
228		if (len != 0)
229			memcpy(buf, EVBUFFER_DATA(job->event->input), len);
230		buf[len] = '\0';
231	} else
232		buf = line;
233
234	log_debug("%s: %p %s: %s", __func__, fj, fj->cmd, buf);
235
236	if (*buf != '\0' || !fj->updated) {
237		free(fj->out);
238		fj->out = buf;
239	} else
240		free(buf);
241
242	if (fj->status) {
243		if (fj->client != NULL)
244			server_status_client(fj->client);
245		fj->status = 0;
246	}
247}
248
249/* Find a job. */
250static char *
251format_job_get(struct format_tree *ft, const char *cmd)
252{
253	struct format_job_tree	*jobs;
254	struct format_job	 fj0, *fj;
255	time_t			 t;
256	char			*expanded;
257	int			 force;
258
259	if (ft->client == NULL)
260		jobs = &format_jobs;
261	else if (ft->client->jobs != NULL)
262		jobs = ft->client->jobs;
263	else {
264		jobs = ft->client->jobs = xmalloc(sizeof *ft->client->jobs);
265		RB_INIT(jobs);
266	}
267
268	fj0.tag = ft->tag;
269	fj0.cmd = cmd;
270	if ((fj = RB_FIND(format_job_tree, jobs, &fj0)) == NULL) {
271		fj = xcalloc(1, sizeof *fj);
272		fj->client = ft->client;
273		fj->tag = ft->tag;
274		fj->cmd = xstrdup(cmd);
275		fj->expanded = NULL;
276
277		xasprintf(&fj->out, "<'%s' not ready>", fj->cmd);
278
279		RB_INSERT(format_job_tree, jobs, fj);
280	}
281
282	expanded = format_expand(ft, cmd);
283	if (fj->expanded == NULL || strcmp(expanded, fj->expanded) != 0) {
284		free(__UNCONST(fj->expanded));
285		fj->expanded = xstrdup(expanded);
286		force = 1;
287	} else
288		force = (ft->flags & FORMAT_FORCE);
289
290	t = time(NULL);
291	if (fj->job == NULL && (force || fj->last != t)) {
292		fj->job = job_run(expanded, NULL, NULL, format_job_update,
293		    format_job_complete, NULL, fj);
294		if (fj->job == NULL) {
295			free(fj->out);
296			xasprintf(&fj->out, "<'%s' didn't start>", fj->cmd);
297		}
298		fj->last = t;
299		fj->updated = 0;
300	}
301
302	if (ft->flags & FORMAT_STATUS)
303		fj->status = 1;
304
305	free(expanded);
306	return (format_expand(ft, fj->out));
307}
308
309/* Remove old jobs. */
310static void
311format_job_tidy(struct format_job_tree *jobs, int force)
312{
313	struct format_job	*fj, *fj1;
314	time_t			 now;
315
316	now = time(NULL);
317	RB_FOREACH_SAFE(fj, format_job_tree, jobs, fj1) {
318		if (!force && (fj->last > now || now - fj->last < 3600))
319			continue;
320		RB_REMOVE(format_job_tree, jobs, fj);
321
322		log_debug("%s: %s", __func__, fj->cmd);
323
324		if (fj->job != NULL)
325			job_free(fj->job);
326
327		free(__UNCONST(fj->expanded));
328		free(__UNCONST(fj->cmd));
329		free(fj->out);
330
331		free(fj);
332	}
333}
334
335/* Remove old jobs for client. */
336void
337format_lost_client(struct client *c)
338{
339	if (c->jobs != NULL)
340		format_job_tidy(c->jobs, 1);
341	free(c->jobs);
342}
343
344/* Remove old jobs periodically. */
345static void
346format_job_timer(__unused int fd, __unused short events, __unused void *arg)
347{
348	struct client	*c;
349	struct timeval	 tv = { .tv_sec = 60 };
350
351	format_job_tidy(&format_jobs, 0);
352	TAILQ_FOREACH(c, &clients, entry) {
353		if (c->jobs != NULL)
354			format_job_tidy(c->jobs, 0);
355	}
356
357	evtimer_del(&format_job_event);
358	evtimer_add(&format_job_event, &tv);
359}
360
361/* Callback for host. */
362static void
363format_cb_host(__unused struct format_tree *ft, struct format_entry *fe)
364{
365	char host[HOST_NAME_MAX + 1];
366
367	if (gethostname(host, sizeof host) != 0)
368		fe->value = xstrdup("");
369	else
370		fe->value = xstrdup(host);
371}
372
373/* Callback for host_short. */
374static void
375format_cb_host_short(__unused struct format_tree *ft, struct format_entry *fe)
376{
377	char host[HOST_NAME_MAX + 1], *cp;
378
379	if (gethostname(host, sizeof host) != 0)
380		fe->value = xstrdup("");
381	else {
382		if ((cp = strchr(host, '.')) != NULL)
383			*cp = '\0';
384		fe->value = xstrdup(host);
385	}
386}
387
388/* Callback for pid. */
389static void
390format_cb_pid(__unused struct format_tree *ft, struct format_entry *fe)
391{
392	xasprintf(&fe->value, "%ld", (long)getpid());
393}
394
395/* Callback for session_alerts. */
396static void
397format_cb_session_alerts(struct format_tree *ft, struct format_entry *fe)
398{
399	struct session	*s = ft->s;
400	struct winlink	*wl;
401	char		 alerts[1024], tmp[16];
402
403	if (s == NULL)
404		return;
405
406	*alerts = '\0';
407	RB_FOREACH(wl, winlinks, &s->windows) {
408		if ((wl->flags & WINLINK_ALERTFLAGS) == 0)
409			continue;
410		xsnprintf(tmp, sizeof tmp, "%u", wl->idx);
411
412		if (*alerts != '\0')
413			strlcat(alerts, ",", sizeof alerts);
414		strlcat(alerts, tmp, sizeof alerts);
415		if (wl->flags & WINLINK_ACTIVITY)
416			strlcat(alerts, "#", sizeof alerts);
417		if (wl->flags & WINLINK_BELL)
418			strlcat(alerts, "!", sizeof alerts);
419		if (wl->flags & WINLINK_SILENCE)
420			strlcat(alerts, "~", sizeof alerts);
421	}
422	fe->value = xstrdup(alerts);
423}
424
425/* Callback for session_stack. */
426static void
427format_cb_session_stack(struct format_tree *ft, struct format_entry *fe)
428{
429	struct session	*s = ft->s;
430	struct winlink	*wl;
431	char		 result[1024], tmp[16];
432
433	if (s == NULL)
434		return;
435
436	xsnprintf(result, sizeof result, "%u", s->curw->idx);
437	TAILQ_FOREACH(wl, &s->lastw, sentry) {
438		xsnprintf(tmp, sizeof tmp, "%u", wl->idx);
439
440		if (*result != '\0')
441			strlcat(result, ",", sizeof result);
442		strlcat(result, tmp, sizeof result);
443	}
444	fe->value = xstrdup(result);
445}
446
447/* Callback for window_stack_index. */
448static void
449format_cb_window_stack_index(struct format_tree *ft, struct format_entry *fe)
450{
451	struct session	*s = ft->wl->session;
452	struct winlink	*wl;
453	u_int		 idx;
454
455	idx = 0;
456	TAILQ_FOREACH(wl, &s->lastw, sentry) {
457		idx++;
458		if (wl == ft->wl)
459			break;
460	}
461	if (wl != NULL)
462		xasprintf(&fe->value, "%u", idx);
463	else
464		fe->value = xstrdup("0");
465}
466
467/* Callback for window_layout. */
468static void
469format_cb_window_layout(struct format_tree *ft, struct format_entry *fe)
470{
471	struct window	*w = ft->w;
472
473	if (w == NULL)
474		return;
475
476	if (w->saved_layout_root != NULL)
477		fe->value = layout_dump(w->saved_layout_root);
478	else
479		fe->value = layout_dump(w->layout_root);
480}
481
482/* Callback for window_visible_layout. */
483static void
484format_cb_window_visible_layout(struct format_tree *ft, struct format_entry *fe)
485{
486	struct window	*w = ft->w;
487
488	if (w == NULL)
489		return;
490
491	fe->value = layout_dump(w->layout_root);
492}
493
494/* Callback for pane_start_command. */
495static void
496format_cb_start_command(struct format_tree *ft, struct format_entry *fe)
497{
498	struct window_pane	*wp = ft->wp;
499
500	if (wp == NULL)
501		return;
502
503	fe->value = cmd_stringify_argv(wp->argc, wp->argv);
504}
505
506/* Callback for pane_current_command. */
507static void
508format_cb_current_command(struct format_tree *ft, struct format_entry *fe)
509{
510	struct window_pane	*wp = ft->wp;
511	char			*cmd;
512
513	if (wp == NULL)
514		return;
515
516	cmd = osdep_get_name(wp->fd, wp->tty);
517	if (cmd == NULL || *cmd == '\0') {
518		free(cmd);
519		cmd = cmd_stringify_argv(wp->argc, wp->argv);
520		if (cmd == NULL || *cmd == '\0') {
521			free(cmd);
522			cmd = xstrdup(wp->shell);
523		}
524	}
525	fe->value = parse_window_name(cmd);
526	free(cmd);
527}
528
529/* Callback for pane_current_path. */
530static void
531format_cb_current_path(struct format_tree *ft, struct format_entry *fe)
532{
533	struct window_pane	*wp = ft->wp;
534	char			*cwd;
535
536	if (wp == NULL)
537		return;
538
539	cwd = osdep_get_cwd(wp->fd);
540	if (cwd != NULL)
541		fe->value = xstrdup(cwd);
542}
543
544/* Callback for history_bytes. */
545static void
546format_cb_history_bytes(struct format_tree *ft, struct format_entry *fe)
547{
548	struct window_pane	*wp = ft->wp;
549	struct grid		*gd;
550	struct grid_line	*gl;
551	unsigned long long	 size;
552	u_int			 i;
553
554	if (wp == NULL)
555		return;
556	gd = wp->base.grid;
557
558	size = 0;
559	for (i = 0; i < gd->hsize; i++) {
560		gl = &gd->linedata[i];
561		size += gl->cellsize * sizeof *gl->celldata;
562		size += gl->extdsize * sizeof *gl->extddata;
563	}
564	size += gd->hsize * sizeof *gd->linedata;
565
566	xasprintf(&fe->value, "%llu", size);
567}
568
569/* Callback for pane_tabs. */
570static void
571format_cb_pane_tabs(struct format_tree *ft, struct format_entry *fe)
572{
573	struct window_pane	*wp = ft->wp;
574	struct evbuffer		*buffer;
575	u_int			 i;
576	int			 size;
577
578	if (wp == NULL)
579		return;
580
581	buffer = evbuffer_new();
582	for (i = 0; i < wp->base.grid->sx; i++) {
583		if (!bit_test(wp->base.tabs, i))
584			continue;
585
586		if (EVBUFFER_LENGTH(buffer) > 0)
587			evbuffer_add(buffer, ",", 1);
588		evbuffer_add_printf(buffer, "%u", i);
589	}
590	size = EVBUFFER_LENGTH(buffer);
591	xasprintf(&fe->value, "%.*s", size, EVBUFFER_DATA(buffer));
592	evbuffer_free(buffer);
593}
594
595/* Merge a format tree. */
596static void
597format_merge(struct format_tree *ft, struct format_tree *from)
598{
599	struct format_entry	*fe;
600
601	RB_FOREACH(fe, format_entry_tree, &from->tree) {
602		if (fe->value != NULL)
603			format_add(ft, fe->key, "%s", fe->value);
604	}
605}
606
607/* Create a new tree. */
608struct format_tree *
609format_create(struct client *c, struct cmdq_item *item, int tag, int flags)
610{
611	struct format_tree	*ft;
612
613	if (!event_initialized(&format_job_event)) {
614		evtimer_set(&format_job_event, format_job_timer, NULL);
615		format_job_timer(-1, 0, NULL);
616	}
617
618	ft = xcalloc(1, sizeof *ft);
619	RB_INIT(&ft->tree);
620
621	if (c != NULL) {
622		ft->client = c;
623		ft->client->references++;
624	}
625
626	ft->tag = tag;
627	ft->flags = flags;
628
629	format_add(ft, "version", "%s", VERSION);
630	format_add_cb(ft, "host", format_cb_host);
631	format_add_cb(ft, "host_short", format_cb_host_short);
632	format_add_cb(ft, "pid", format_cb_pid);
633	format_add(ft, "socket_path", "%s", socket_path);
634	format_add_tv(ft, "start_time", &start_time);
635
636	if (item != NULL) {
637		if (item->cmd != NULL)
638			format_add(ft, "command", "%s", item->cmd->entry->name);
639		if (item->shared != NULL && item->shared->formats != NULL)
640			format_merge(ft, item->shared->formats);
641	}
642
643	return (ft);
644}
645
646/* Free a tree. */
647void
648format_free(struct format_tree *ft)
649{
650	struct format_entry	*fe, *fe1;
651
652	RB_FOREACH_SAFE(fe, format_entry_tree, &ft->tree, fe1) {
653		RB_REMOVE(format_entry_tree, &ft->tree, fe);
654		free(fe->value);
655		free(fe->key);
656		free(fe);
657	}
658
659	if (ft->client != NULL)
660		server_client_unref(ft->client);
661	free(ft);
662}
663
664/* Add a key-value pair. */
665void
666format_add(struct format_tree *ft, const char *key, const char *fmt, ...)
667{
668	struct format_entry	*fe;
669	struct format_entry	*fe_now;
670	va_list			 ap;
671
672	fe = xmalloc(sizeof *fe);
673	fe->key = xstrdup(key);
674
675	fe_now = RB_INSERT(format_entry_tree, &ft->tree, fe);
676	if (fe_now != NULL) {
677		free(fe->key);
678		free(fe);
679		free(fe_now->value);
680		fe = fe_now;
681	}
682
683	fe->cb = NULL;
684	fe->t = 0;
685
686	va_start(ap, fmt);
687	xvasprintf(&fe->value, fmt, ap);
688	va_end(ap);
689}
690
691/* Add a key and time. */
692static void
693format_add_tv(struct format_tree *ft, const char *key, struct timeval *tv)
694{
695	struct format_entry	*fe;
696	struct format_entry	*fe_now;
697
698	fe = xmalloc(sizeof *fe);
699	fe->key = xstrdup(key);
700
701	fe_now = RB_INSERT(format_entry_tree, &ft->tree, fe);
702	if (fe_now != NULL) {
703		free(fe->key);
704		free(fe);
705		free(fe_now->value);
706		fe = fe_now;
707	}
708
709	fe->cb = NULL;
710	fe->t = tv->tv_sec;
711
712	fe->value = NULL;
713}
714
715/* Add a key and function. */
716static void
717format_add_cb(struct format_tree *ft, const char *key, format_cb cb)
718{
719	struct format_entry	*fe;
720	struct format_entry	*fe_now;
721
722	fe = xmalloc(sizeof *fe);
723	fe->key = xstrdup(key);
724
725	fe_now = RB_INSERT(format_entry_tree, &ft->tree, fe);
726	if (fe_now != NULL) {
727		free(fe->key);
728		free(fe);
729		free(fe_now->value);
730		fe = fe_now;
731	}
732
733	fe->cb = cb;
734	fe->t = 0;
735
736	fe->value = NULL;
737}
738
739/* Find a format entry. */
740static char *
741format_find(struct format_tree *ft, const char *key, int modifiers)
742{
743	struct format_entry	*fe, fe_find;
744	struct environ_entry	*envent;
745	static char		 s[64];
746	struct options_entry	*o;
747	const char		*found;
748	int			 idx;
749	char			*copy, *saved;
750
751	if (~modifiers & FORMAT_TIMESTRING) {
752		o = options_parse_get(global_options, key, &idx, 0);
753		if (o == NULL && ft->w != NULL)
754			o = options_parse_get(ft->w->options, key, &idx, 0);
755		if (o == NULL)
756			o = options_parse_get(global_w_options, key, &idx, 0);
757		if (o == NULL && ft->s != NULL)
758			o = options_parse_get(ft->s->options, key, &idx, 0);
759		if (o == NULL)
760			o = options_parse_get(global_s_options, key, &idx, 0);
761		if (o != NULL) {
762			found = options_tostring(o, idx, 1);
763			goto found;
764		}
765	}
766	found = NULL;
767
768	fe_find.key = __UNCONST(key);
769	fe = RB_FIND(format_entry_tree, &ft->tree, &fe_find);
770	if (fe != NULL) {
771		if (modifiers & FORMAT_TIMESTRING) {
772			if (fe->t == 0)
773				return (NULL);
774			ctime_r(&fe->t, s);
775			s[strcspn(s, "\n")] = '\0';
776			found = s;
777			goto found;
778		}
779		if (fe->t != 0) {
780			xsnprintf(s, sizeof s, "%lld", (long long)fe->t);
781			found = s;
782			goto found;
783		}
784		if (fe->value == NULL && fe->cb != NULL)
785			fe->cb(ft, fe);
786		found = fe->value;
787		goto found;
788	}
789
790	if (~modifiers & FORMAT_TIMESTRING) {
791		envent = NULL;
792		if (ft->s != NULL)
793			envent = environ_find(ft->s->environ, key);
794		if (envent == NULL)
795			envent = environ_find(global_environ, key);
796		if (envent != NULL) {
797			found = envent->value;
798			goto found;
799		}
800	}
801
802	return (NULL);
803
804found:
805	if (found == NULL)
806		return (NULL);
807	copy = xstrdup(found);
808	if (modifiers & FORMAT_BASENAME) {
809		saved = copy;
810		copy = xstrdup(basename(saved));
811		free(saved);
812	}
813	if (modifiers & FORMAT_DIRNAME) {
814		saved = copy;
815		copy = xstrdup(dirname(saved));
816		free(saved);
817	}
818	return (copy);
819}
820
821/* Skip until comma. */
822static char *
823format_skip(char *s)
824{
825	int	brackets = 0;
826
827	for (; *s != '\0'; s++) {
828		if (*s == '{')
829			brackets++;
830		if (*s == '}')
831			brackets--;
832		if (*s == ',' && brackets == 0)
833			break;
834	}
835	if (*s == '\0')
836		return (NULL);
837	return (s);
838}
839
840/* Return left and right alternatives separated by commas. */
841static int
842format_choose(char *s, char **left, char **right)
843{
844	char	*cp;
845
846	cp = format_skip(s);
847	if (cp == NULL)
848		return (-1);
849	*cp = '\0';
850
851	*left = s;
852	*right = cp + 1;
853	return (0);
854}
855
856/* Is this true? */
857int
858format_true(const char *s)
859{
860	if (s != NULL && *s != '\0' && (s[0] != '0' || s[1] != '\0'))
861		return (1);
862	return (0);
863}
864
865/* Replace a key. */
866static int
867format_replace(struct format_tree *ft, const char *key, size_t keylen,
868    char **buf, size_t *len, size_t *off)
869{
870	struct window_pane	*wp = ft->wp;
871	char			*copy, *copy0, *endptr, *ptr, *found, *new;
872	char			*value, *from = NULL, *to = NULL, *left, *right;
873	size_t			 valuelen, newlen, fromlen, tolen, used;
874	long			 limit = 0;
875	int			 modifiers = 0, compare = 0, search = 0;
876
877	/* Make a copy of the key. */
878	copy0 = copy = xmalloc(keylen + 1);
879	memcpy(copy, key, keylen);
880	copy[keylen] = '\0';
881
882	/* Is there a length limit or whatnot? */
883	switch (copy[0]) {
884	case 'm':
885		if (copy[1] != ':')
886			break;
887		compare = -2;
888		copy += 2;
889		break;
890	case 'C':
891		if (copy[1] != ':')
892			break;
893		search = 1;
894		copy += 2;
895		break;
896	case '|':
897		if (copy[1] != '|' || copy[2] != ':')
898			break;
899		compare = -3;
900		copy += 3;
901		break;
902	case '&':
903		if (copy[1] != '&' || copy[2] != ':')
904			break;
905		compare = -4;
906		copy += 3;
907		break;
908	case '!':
909		if (copy[1] == '=' && copy[2] == ':') {
910			compare = -1;
911			copy += 3;
912			break;
913		}
914		break;
915	case '=':
916		if (copy[1] == '=' && copy[2] == ':') {
917			compare = 1;
918			copy += 3;
919			break;
920		}
921		errno = 0;
922		limit = strtol(copy + 1, &endptr, 10);
923		if (errno == ERANGE && (limit == LONG_MIN || limit == LONG_MAX))
924			break;
925		if (*endptr != ':')
926			break;
927		copy = endptr + 1;
928		break;
929	case 'b':
930		if (copy[1] != ':')
931			break;
932		modifiers |= FORMAT_BASENAME;
933		copy += 2;
934		break;
935	case 'd':
936		if (copy[1] != ':')
937			break;
938		modifiers |= FORMAT_DIRNAME;
939		copy += 2;
940		break;
941	case 't':
942		if (copy[1] != ':')
943			break;
944		modifiers |= FORMAT_TIMESTRING;
945		copy += 2;
946		break;
947	case 's':
948		if (copy[1] != '/')
949			break;
950		from = copy + 2;
951		for (copy = from; *copy != '\0' && *copy != '/'; copy++)
952			/* nothing */;
953		if (copy[0] != '/' || copy == from) {
954			copy = copy0;
955			break;
956		}
957		copy[0] = '\0';
958		to = copy + 1;
959		for (copy = to; *copy != '\0' && *copy != '/'; copy++)
960			/* nothing */;
961		if (copy[0] != '/' || copy[1] != ':') {
962			copy = copy0;
963			break;
964		}
965		copy[0] = '\0';
966
967		modifiers |= FORMAT_SUBSTITUTE;
968		copy += 2;
969		break;
970	}
971
972	/* Is this a comparison or a conditional? */
973	if (search) {
974		/* Search in pane. */
975		if (wp == NULL)
976			value = xstrdup("0");
977		else
978			xasprintf(&value, "%u", window_pane_search(wp, copy));
979	} else if (compare != 0) {
980		/* Comparison: compare comma-separated left and right. */
981		if (format_choose(copy, &left, &right) != 0)
982			goto fail;
983		left = format_expand(ft, left);
984		right = format_expand(ft, right);
985		if (compare == -3 &&
986		    (format_true(left) || format_true(right)))
987			value = xstrdup("1");
988		else if (compare == -4 &&
989		    (format_true(left) && format_true(right)))
990			value = xstrdup("1");
991		else if (compare == 1 && strcmp(left, right) == 0)
992			value = xstrdup("1");
993		else if (compare == -1 && strcmp(left, right) != 0)
994			value = xstrdup("1");
995		else if (compare == -2 && fnmatch(left, right, 0) == 0)
996			value = xstrdup("1");
997		else
998			value = xstrdup("0");
999		free(right);
1000		free(left);
1001	} else if (*copy == '?') {
1002		/* Conditional: check first and choose second or third. */
1003		ptr = format_skip(copy);
1004		if (ptr == NULL)
1005			goto fail;
1006		*ptr = '\0';
1007
1008		found = format_find(ft, copy + 1, modifiers);
1009		if (found == NULL)
1010			found = format_expand(ft, copy + 1);
1011		if (format_choose(ptr + 1, &left, &right) != 0)
1012			goto fail;
1013
1014		if (format_true(found))
1015			value = format_expand(ft, left);
1016		else
1017			value = format_expand(ft, right);
1018		free(found);
1019	} else {
1020		/* Neither: look up directly. */
1021		value = format_find(ft, copy, modifiers);
1022		if (value == NULL)
1023			value = xstrdup("");
1024	}
1025
1026	/* Perform substitution if any. */
1027	if (modifiers & FORMAT_SUBSTITUTE) {
1028		fromlen = strlen(from);
1029		tolen = strlen(to);
1030
1031		newlen = strlen(value) + 1;
1032		copy = new = xmalloc(newlen);
1033		for (ptr = value; *ptr != '\0'; /* nothing */) {
1034			if (strncmp(ptr, from, fromlen) != 0) {
1035				*new++ = *ptr++;
1036				continue;
1037			}
1038			used = new - copy;
1039
1040			newlen += tolen;
1041			copy = xrealloc(copy, newlen);
1042
1043			new = copy + used;
1044			memcpy(new, to, tolen);
1045
1046			new += tolen;
1047			ptr += fromlen;
1048		}
1049		*new = '\0';
1050		free(value);
1051		value = copy;
1052	}
1053
1054	/* Truncate the value if needed. */
1055	if (limit > 0) {
1056		new = utf8_trimcstr(value, limit);
1057		free(value);
1058		value = new;
1059	} else if (limit < 0) {
1060		new = utf8_rtrimcstr(value, -limit);
1061		free(value);
1062		value = new;
1063	}
1064
1065	/* Expand the buffer and copy in the value. */
1066	valuelen = strlen(value);
1067	while (*len - *off < valuelen + 1) {
1068		*buf = xreallocarray(*buf, 2, *len);
1069		*len *= 2;
1070	}
1071	memcpy(*buf + *off, value, valuelen);
1072	*off += valuelen;
1073
1074	free(value);
1075	free(copy0);
1076	return (0);
1077
1078fail:
1079	free(copy0);
1080	return (-1);
1081}
1082
1083/* Expand keys in a template, passing through strftime first. */
1084char *
1085format_expand_time(struct format_tree *ft, const char *fmt, time_t t)
1086{
1087	struct tm	*tm;
1088	char		 s[2048];
1089
1090	if (fmt == NULL || *fmt == '\0')
1091		return (xstrdup(""));
1092
1093	tm = localtime(&t);
1094
1095	if (strftime(s, sizeof s, fmt, tm) == 0)
1096		return (xstrdup(""));
1097
1098	return (format_expand(ft, s));
1099}
1100
1101/* Expand keys in a template. */
1102char *
1103format_expand(struct format_tree *ft, const char *fmt)
1104{
1105	char		*buf, *out;
1106	const char	*ptr, *s, *saved = fmt;
1107	size_t		 off, len, n, outlen;
1108	int     	 ch, brackets;
1109
1110	if (fmt == NULL)
1111		return (xstrdup(""));
1112
1113	len = 64;
1114	buf = xmalloc(len);
1115	off = 0;
1116
1117	while (*fmt != '\0') {
1118		if (*fmt != '#') {
1119			while (len - off < 2) {
1120				buf = xreallocarray(buf, 2, len);
1121				len *= 2;
1122			}
1123			buf[off++] = *fmt++;
1124			continue;
1125		}
1126		fmt++;
1127
1128		ch = (u_char) *fmt++;
1129		switch (ch) {
1130		case '(':
1131			brackets = 1;
1132			for (ptr = fmt; *ptr != '\0'; ptr++) {
1133				if (*ptr == '(')
1134					brackets++;
1135				if (*ptr == ')' && --brackets == 0)
1136					break;
1137			}
1138			if (*ptr != ')' || brackets != 0)
1139				break;
1140			n = ptr - fmt;
1141
1142			if (ft->flags & FORMAT_NOJOBS)
1143				out = xstrdup("");
1144			else
1145				out = format_job_get(ft, xstrndup(fmt, n));
1146			outlen = strlen(out);
1147
1148			while (len - off < outlen + 1) {
1149				buf = xreallocarray(buf, 2, len);
1150				len *= 2;
1151			}
1152			memcpy(buf + off, out, outlen);
1153			off += outlen;
1154
1155			free(out);
1156
1157			fmt += n + 1;
1158			continue;
1159		case '{':
1160			brackets = 1;
1161			for (ptr = fmt; *ptr != '\0'; ptr++) {
1162				if (*ptr == '{')
1163					brackets++;
1164				if (*ptr == '}' && --brackets == 0)
1165					break;
1166			}
1167			if (*ptr != '}' || brackets != 0)
1168				break;
1169			n = ptr - fmt;
1170
1171			if (format_replace(ft, fmt, n, &buf, &len, &off) != 0)
1172				break;
1173			fmt += n + 1;
1174			continue;
1175		case '#':
1176			while (len - off < 2) {
1177				buf = xreallocarray(buf, 2, len);
1178				len *= 2;
1179			}
1180			buf[off++] = '#';
1181			continue;
1182		default:
1183			s = NULL;
1184			if (ch >= 'A' && ch <= 'Z')
1185				s = format_upper[ch - 'A'];
1186			else if (ch >= 'a' && ch <= 'z')
1187				s = format_lower[ch - 'a'];
1188			if (s == NULL) {
1189				while (len - off < 3) {
1190					buf = xreallocarray(buf, 2, len);
1191					len *= 2;
1192				}
1193				buf[off++] = '#';
1194				buf[off++] = ch;
1195				continue;
1196			}
1197			n = strlen(s);
1198			if (format_replace(ft, s, n, &buf, &len, &off) != 0)
1199				break;
1200			continue;
1201		}
1202
1203		break;
1204	}
1205	buf[off] = '\0';
1206
1207	log_debug("format '%s' -> '%s'", saved, buf);
1208	return (buf);
1209}
1210
1211/* Expand a single string. */
1212char *
1213format_single(struct cmdq_item *item, const char *fmt, struct client *c,
1214    struct session *s, struct winlink *wl, struct window_pane *wp)
1215{
1216	struct format_tree	*ft;
1217	char			*expanded;
1218
1219	if (item != NULL)
1220		ft = format_create(item->client, item, FORMAT_NONE, 0);
1221	else
1222		ft = format_create(NULL, item, FORMAT_NONE, 0);
1223	format_defaults(ft, c, s, wl, wp);
1224
1225	expanded = format_expand(ft, fmt);
1226	format_free(ft);
1227	return (expanded);
1228}
1229
1230/* Set defaults for any of arguments that are not NULL. */
1231void
1232format_defaults(struct format_tree *ft, struct client *c, struct session *s,
1233    struct winlink *wl, struct window_pane *wp)
1234{
1235	format_add(ft, "session_format", "%d", s != NULL);
1236	format_add(ft, "window_format", "%d", wl != NULL);
1237	format_add(ft, "pane_format", "%d", wp != NULL);
1238
1239	if (s == NULL && c != NULL)
1240		s = c->session;
1241	if (wl == NULL && s != NULL)
1242		wl = s->curw;
1243	if (wp == NULL && wl != NULL)
1244		wp = wl->window->active;
1245
1246	if (c != NULL)
1247		format_defaults_client(ft, c);
1248	if (s != NULL)
1249		format_defaults_session(ft, s);
1250	if (wl != NULL)
1251		format_defaults_winlink(ft, wl);
1252	if (wp != NULL)
1253		format_defaults_pane(ft, wp);
1254}
1255
1256/* Set default format keys for a session. */
1257static void
1258format_defaults_session(struct format_tree *ft, struct session *s)
1259{
1260	struct session_group	*sg;
1261
1262	ft->s = s;
1263
1264	format_add(ft, "session_name", "%s", s->name);
1265	format_add(ft, "session_windows", "%u", winlink_count(&s->windows));
1266	format_add(ft, "session_width", "%u", s->sx);
1267	format_add(ft, "session_height", "%u", s->sy);
1268	format_add(ft, "session_id", "$%u", s->id);
1269
1270	sg = session_group_contains(s);
1271	format_add(ft, "session_grouped", "%d", sg != NULL);
1272	if (sg != NULL)
1273		format_add(ft, "session_group", "%s", sg->name);
1274
1275	format_add_tv(ft, "session_created", &s->creation_time);
1276	format_add_tv(ft, "session_last_attached", &s->last_attached_time);
1277	format_add_tv(ft, "session_activity", &s->activity_time);
1278
1279	format_add(ft, "session_attached", "%u", s->attached);
1280	format_add(ft, "session_many_attached", "%d", s->attached > 1);
1281
1282	format_add_cb(ft, "session_alerts", format_cb_session_alerts);
1283	format_add_cb(ft, "session_stack", format_cb_session_stack);
1284}
1285
1286/* Set default format keys for a client. */
1287static void
1288format_defaults_client(struct format_tree *ft, struct client *c)
1289{
1290	struct session	*s;
1291	const char	*name;
1292	struct tty	*tty = &c->tty;
1293	const char	*types[] = TTY_TYPES;
1294
1295	if (ft->s == NULL)
1296		ft->s = c->session;
1297
1298	format_add(ft, "client_name", "%s", c->name);
1299	format_add(ft, "client_pid", "%ld", (long) c->pid);
1300	format_add(ft, "client_height", "%u", tty->sy);
1301	format_add(ft, "client_width", "%u", tty->sx);
1302	format_add(ft, "client_tty", "%s", c->ttyname);
1303	format_add(ft, "client_control_mode", "%d",
1304		!!(c->flags & CLIENT_CONTROL));
1305
1306	if (tty->term_name != NULL)
1307		format_add(ft, "client_termname", "%s", tty->term_name);
1308	if (tty->term_name != NULL)
1309		format_add(ft, "client_termtype", "%s", types[tty->term_type]);
1310
1311	format_add_tv(ft, "client_created", &c->creation_time);
1312	format_add_tv(ft, "client_activity", &c->activity_time);
1313
1314	format_add(ft, "client_written", "%zu", c->written);
1315	format_add(ft, "client_discarded", "%zu", c->discarded);
1316
1317	name = server_client_get_key_table(c);
1318	if (strcmp(c->keytable->name, name) == 0)
1319		format_add(ft, "client_prefix", "%d", 0);
1320	else
1321		format_add(ft, "client_prefix", "%d", 1);
1322	format_add(ft, "client_key_table", "%s", c->keytable->name);
1323
1324	if (tty->flags & TTY_UTF8)
1325		format_add(ft, "client_utf8", "%d", 1);
1326	else
1327		format_add(ft, "client_utf8", "%d", 0);
1328
1329	if (c->flags & CLIENT_READONLY)
1330		format_add(ft, "client_readonly", "%d", 1);
1331	else
1332		format_add(ft, "client_readonly", "%d", 0);
1333
1334	s = c->session;
1335	if (s != NULL)
1336		format_add(ft, "client_session", "%s", s->name);
1337	s = c->last_session;
1338	if (s != NULL && session_alive(s))
1339		format_add(ft, "client_last_session", "%s", s->name);
1340}
1341
1342/* Set default format keys for a window. */
1343void
1344format_defaults_window(struct format_tree *ft, struct window *w)
1345{
1346	ft->w = w;
1347
1348	format_add_tv(ft, "window_activity", &w->activity_time);
1349	format_add(ft, "window_id", "@%u", w->id);
1350	format_add(ft, "window_name", "%s", w->name);
1351	format_add(ft, "window_width", "%u", w->sx);
1352	format_add(ft, "window_height", "%u", w->sy);
1353	format_add_cb(ft, "window_layout", format_cb_window_layout);
1354	format_add_cb(ft, "window_visible_layout",
1355	    format_cb_window_visible_layout);
1356	format_add(ft, "window_panes", "%u", window_count_panes(w));
1357	format_add(ft, "window_zoomed_flag", "%d",
1358	    !!(w->flags & WINDOW_ZOOMED));
1359}
1360
1361/* Set default format keys for a winlink. */
1362static void
1363format_defaults_winlink(struct format_tree *ft, struct winlink *wl)
1364{
1365	struct session	*s = wl->session;
1366	struct window	*w = wl->window;
1367
1368	if (ft->w == NULL)
1369		ft->w = wl->window;
1370	ft->wl = wl;
1371
1372	format_defaults_window(ft, w);
1373
1374	format_add(ft, "window_index", "%d", wl->idx);
1375	format_add_cb(ft, "window_stack_index", format_cb_window_stack_index);
1376	format_add(ft, "window_flags", "%s", window_printable_flags(wl));
1377	format_add(ft, "window_active", "%d", wl == s->curw);
1378
1379	format_add(ft, "window_bell_flag", "%d",
1380	    !!(wl->flags & WINLINK_BELL));
1381	format_add(ft, "window_activity_flag", "%d",
1382	    !!(wl->flags & WINLINK_ACTIVITY));
1383	format_add(ft, "window_silence_flag", "%d",
1384	    !!(wl->flags & WINLINK_SILENCE));
1385	format_add(ft, "window_last_flag", "%d",
1386	    !!(wl == TAILQ_FIRST(&s->lastw)));
1387	format_add(ft, "window_linked", "%d", session_is_linked(s, wl->window));
1388}
1389
1390/* Set default format keys for a window pane. */
1391void
1392format_defaults_pane(struct format_tree *ft, struct window_pane *wp)
1393{
1394	struct grid	*gd = wp->base.grid;
1395	u_int		 idx;
1396	int  		 status;
1397
1398	if (ft->w == NULL)
1399		ft->w = wp->window;
1400	ft->wp = wp;
1401
1402	format_add(ft, "history_size", "%u", gd->hsize);
1403	format_add(ft, "history_limit", "%u", gd->hlimit);
1404	format_add_cb(ft, "history_bytes", format_cb_history_bytes);
1405
1406	if (window_pane_index(wp, &idx) != 0)
1407		fatalx("index not found");
1408	format_add(ft, "pane_index", "%u", idx);
1409
1410	format_add(ft, "pane_width", "%u", wp->sx);
1411	format_add(ft, "pane_height", "%u", wp->sy);
1412	format_add(ft, "pane_title", "%s", wp->base.title);
1413	format_add(ft, "pane_id", "%%%u", wp->id);
1414	format_add(ft, "pane_active", "%d", wp == wp->window->active);
1415	format_add(ft, "pane_input_off", "%d", !!(wp->flags & PANE_INPUTOFF));
1416	format_add(ft, "pane_pipe", "%d", wp->pipe_fd != -1);
1417
1418	status = wp->status;
1419	if (wp->fd == -1 && WIFEXITED(status))
1420		format_add(ft, "pane_dead_status", "%d", WEXITSTATUS(status));
1421	format_add(ft, "pane_dead", "%d", wp->fd == -1);
1422
1423	if (window_pane_visible(wp)) {
1424		format_add(ft, "pane_left", "%u", wp->xoff);
1425		format_add(ft, "pane_top", "%u", wp->yoff);
1426		format_add(ft, "pane_right", "%u", wp->xoff + wp->sx - 1);
1427		format_add(ft, "pane_bottom", "%u", wp->yoff + wp->sy - 1);
1428		format_add(ft, "pane_at_left", "%d", wp->xoff == 0);
1429		format_add(ft, "pane_at_top", "%d", wp->yoff == 0);
1430		format_add(ft, "pane_at_right", "%d", wp->xoff + wp->sx == wp->window->sx);
1431		format_add(ft, "pane_at_bottom", "%d", wp->yoff + wp->sy == wp->window->sy);
1432	}
1433
1434	format_add(ft, "pane_in_mode", "%d", wp->screen != &wp->base);
1435	if (wp->mode != NULL)
1436		format_add(ft, "pane_mode", "%s", wp->mode->name);
1437
1438	format_add(ft, "pane_synchronized", "%d",
1439	    !!options_get_number(wp->window->options, "synchronize-panes"));
1440	if (wp->searchstr != NULL)
1441		format_add(ft, "pane_search_string", "%s", wp->searchstr);
1442
1443	format_add(ft, "pane_tty", "%s", wp->tty);
1444	format_add(ft, "pane_pid", "%ld", (long) wp->pid);
1445	format_add_cb(ft, "pane_start_command", format_cb_start_command);
1446	format_add_cb(ft, "pane_current_command", format_cb_current_command);
1447	format_add_cb(ft, "pane_current_path", format_cb_current_path);
1448
1449	format_add(ft, "cursor_x", "%u", wp->base.cx);
1450	format_add(ft, "cursor_y", "%u", wp->base.cy);
1451	format_add(ft, "scroll_region_upper", "%u", wp->base.rupper);
1452	format_add(ft, "scroll_region_lower", "%u", wp->base.rlower);
1453
1454	window_copy_add_formats(wp, ft);
1455
1456	format_add(ft, "alternate_on", "%d", wp->saved_grid ? 1 : 0);
1457	format_add(ft, "alternate_saved_x", "%u", wp->saved_cx);
1458	format_add(ft, "alternate_saved_y", "%u", wp->saved_cy);
1459
1460	format_add(ft, "cursor_flag", "%d",
1461	    !!(wp->base.mode & MODE_CURSOR));
1462	format_add(ft, "insert_flag", "%d",
1463	    !!(wp->base.mode & MODE_INSERT));
1464	format_add(ft, "keypad_cursor_flag", "%d",
1465	    !!(wp->base.mode & MODE_KCURSOR));
1466	format_add(ft, "keypad_flag", "%d",
1467	    !!(wp->base.mode & MODE_KKEYPAD));
1468	format_add(ft, "wrap_flag", "%d",
1469	    !!(wp->base.mode & MODE_WRAP));
1470
1471	format_add(ft, "mouse_any_flag", "%d",
1472	    !!(wp->base.mode & ALL_MOUSE_MODES));
1473	format_add(ft, "mouse_standard_flag", "%d",
1474	    !!(wp->base.mode & MODE_MOUSE_STANDARD));
1475	format_add(ft, "mouse_button_flag", "%d",
1476	    !!(wp->base.mode & MODE_MOUSE_BUTTON));
1477	format_add(ft, "mouse_all_flag", "%d",
1478	    !!(wp->base.mode & MODE_MOUSE_ALL));
1479
1480	format_add_cb(ft, "pane_tabs", format_cb_pane_tabs);
1481}
1482
1483/* Set default format keys for paste buffer. */
1484void
1485format_defaults_paste_buffer(struct format_tree *ft, struct paste_buffer *pb)
1486{
1487	struct timeval	 tv;
1488	size_t		 size;
1489	char		*s;
1490
1491	timerclear(&tv);
1492	tv.tv_sec = paste_buffer_created(pb);
1493	paste_buffer_data(pb, &size);
1494
1495	format_add(ft, "buffer_size", "%zu", size);
1496	format_add(ft, "buffer_name", "%s", paste_buffer_name(pb));
1497	format_add_tv(ft, "buffer_created", &tv);
1498
1499	s = paste_make_sample(pb);
1500	format_add(ft, "buffer_sample", "%s", s);
1501	free(s);
1502}
1503