/* $OpenBSD$ */
/*
* Copyright (c) 2011 Nicholas Marriott <nicm@users.sourceforge.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <sys/wait.h>
#include <ctype.h>
#include <errno.h>
#include <netdb.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "tmux.h"
/*
* Build a list of key-value pairs and use them to expand #{key} entries in a
* string.
*/
void format_job_callback(struct job *);
const char *format_job_get(struct format_tree *, const char *);
int format_replace(struct format_tree *, const char *, size_t, char **,
size_t *, size_t *);
char *format_time_string(time_t);
char *format_get_command(struct window_pane *);
void format_defaults_pane_tabs(struct format_tree *, struct window_pane *);
void format_defaults_session(struct format_tree *, struct session *);
void format_defaults_client(struct format_tree *, struct client *);
void format_defaults_winlink(struct format_tree *, struct session *,
struct winlink *);
/* Entry in format job tree. */
struct format_job {
const char *cmd;
time_t last;
char *out;
struct job *job;
int status;
RB_ENTRY(format_job) entry;
};
/* Format job tree. */
int format_job_cmp(struct format_job *, struct format_job *);
RB_HEAD(format_job_tree, format_job) format_jobs = RB_INITIALIZER();
RB_PROTOTYPE(format_job_tree, format_job, entry, format_job_cmp);
RB_GENERATE(format_job_tree, format_job, entry, format_job_cmp);
/* Format job tree comparison function. */
int
format_job_cmp(struct format_job *fj1, struct format_job *fj2)
{
return (strcmp(fj1->cmd, fj2->cmd));
}
/* Entry in format tree. */
struct format_entry {
char *key;
char *value;
RB_ENTRY(format_entry) entry;
};
/* Format entry tree. */
struct format_tree {
struct window *w;
struct session *s;
int status;
RB_HEAD(format_entry_tree, format_entry) tree;
};
int format_entry_cmp(struct format_entry *, struct format_entry *);
RB_PROTOTYPE(format_entry_tree, format_entry, entry, format_entry_cmp);
RB_GENERATE(format_entry_tree, format_entry, entry, format_entry_cmp);
/* Format entry tree comparison function. */
int
format_entry_cmp(struct format_entry *fe1, struct format_entry *fe2)
{
return (strcmp(fe1->key, fe2->key));
}
/* Single-character uppercase aliases. */
const char *format_upper[] = {
NULL, /* A */
NULL, /* B */
NULL, /* C */
"pane_id", /* D */
NULL, /* E */
"window_flags", /* F */
NULL, /* G */
"host", /* H */
"window_index", /* I */
NULL, /* J */
NULL, /* K */
NULL, /* L */
NULL, /* M */
NULL, /* N */
NULL, /* O */
"pane_index", /* P */
NULL, /* Q */
NULL, /* R */
"session_name", /* S */
"pane_title", /* T */
NULL, /* U */
NULL, /* V */
"window_name", /* W */
NULL, /* X */
NULL, /* Y */
NULL /* Z */
};
/* Single-character lowercase aliases. */
const char *format_lower[] = {
NULL, /* a */
NULL, /* b */
NULL, /* c */
NULL, /* d */
NULL, /* e */
NULL, /* f */
NULL, /* g */
"host_short", /* h */
NULL, /* i */
NULL, /* j */
NULL, /* k */
NULL, /* l */
NULL, /* m */
NULL, /* n */
NULL, /* o */
NULL, /* p */
NULL, /* q */
NULL, /* r */
NULL, /* s */
NULL, /* t */
NULL, /* u */
NULL, /* v */
NULL, /* w */
NULL, /* x */
NULL, /* y */
NULL /* z */
};
/* Format job callback. */
void
format_job_callback(struct job *job)
{
struct format_job *fj = job->data;
char *line, *buf;
size_t len;
struct client *c;
fj->job = NULL;
free(fj->out);
buf = NULL;
if ((line = evbuffer_readline(job->event->input)) == NULL) {
len = EVBUFFER_LENGTH(job->event->input);
buf = xmalloc(len + 1);
if (len