Annotation of src/usr.bin/tmux/hooks.c, Revision 1.7
1.7 ! nicm 1: /* $OpenBSD: hooks.c,v 1.6 2016/10/13 22:48:51 nicm Exp $ */
1.1 nicm 2:
3: /*
4: * Copyright (c) 2012 Thomas Adam <thomas@xteddy.org>
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:
21: #include <stdlib.h>
22: #include <string.h>
23:
24: #include "tmux.h"
25:
26: struct hooks {
27: RB_HEAD(hooks_tree, hook) tree;
28: struct hooks *parent;
29: };
30:
31: static int hooks_cmp(struct hook *, struct hook *);
1.5 nicm 32: RB_GENERATE_STATIC(hooks_tree, hook, entry, hooks_cmp);
1.1 nicm 33:
1.2 nicm 34: static struct hook *hooks_find1(struct hooks *, const char *);
35: static void hooks_free1(struct hooks *, struct hook *);
1.1 nicm 36:
37: static int
38: hooks_cmp(struct hook *hook1, struct hook *hook2)
39: {
40: return (strcmp(hook1->name, hook2->name));
41: }
42:
43: struct hooks *
1.4 nicm 44: hooks_get(struct session *s)
45: {
46: if (s != NULL)
47: return (s->hooks);
48: return (global_hooks);
49: }
50:
51: struct hooks *
1.1 nicm 52: hooks_create(struct hooks *parent)
53: {
54: struct hooks *hooks;
55:
56: hooks = xcalloc(1, sizeof *hooks);
57: RB_INIT(&hooks->tree);
58: hooks->parent = parent;
59: return (hooks);
60: }
61:
1.2 nicm 62: static void
63: hooks_free1(struct hooks *hooks, struct hook *hook)
64: {
65: RB_REMOVE(hooks_tree, &hooks->tree, hook);
66: cmd_list_free(hook->cmdlist);
67: free((char *)hook->name);
68: free(hook);
69: }
70:
1.1 nicm 71: void
72: hooks_free(struct hooks *hooks)
73: {
74: struct hook *hook, *hook1;
75:
76: RB_FOREACH_SAFE(hook, hooks_tree, &hooks->tree, hook1)
1.2 nicm 77: hooks_free1(hooks, hook);
1.1 nicm 78: free(hooks);
79: }
80:
81: struct hook *
82: hooks_first(struct hooks *hooks)
83: {
84: return (RB_MIN(hooks_tree, &hooks->tree));
85: }
86:
87: struct hook *
88: hooks_next(struct hook *hook)
89: {
90: return (RB_NEXT(hooks_tree, &hooks->tree, hook));
91: }
92:
93: void
94: hooks_add(struct hooks *hooks, const char *name, struct cmd_list *cmdlist)
95: {
96: struct hook *hook;
97:
98: if ((hook = hooks_find1(hooks, name)) != NULL)
1.2 nicm 99: hooks_free1(hooks, hook);
1.1 nicm 100:
101: hook = xcalloc(1, sizeof *hook);
102: hook->name = xstrdup(name);
103: hook->cmdlist = cmdlist;
104: hook->cmdlist->references++;
105: RB_INSERT(hooks_tree, &hooks->tree, hook);
106: }
107:
108: void
1.2 nicm 109: hooks_remove(struct hooks *hooks, const char *name)
1.1 nicm 110: {
1.2 nicm 111: struct hook *hook;
112:
113: if ((hook = hooks_find1(hooks, name)) != NULL)
114: hooks_free1(hooks, hook);
1.1 nicm 115: }
116:
1.2 nicm 117: static struct hook *
1.1 nicm 118: hooks_find1(struct hooks *hooks, const char *name)
119: {
120: struct hook hook;
121:
122: hook.name = name;
123: return (RB_FIND(hooks_tree, &hooks->tree, &hook));
124: }
125:
126: struct hook *
127: hooks_find(struct hooks *hooks, const char *name)
128: {
129: struct hook hook0, *hook;
130:
131: hook0.name = name;
132: hook = RB_FIND(hooks_tree, &hooks->tree, &hook0);
133: while (hook == NULL) {
134: hooks = hooks->parent;
135: if (hooks == NULL)
136: break;
137: hook = RB_FIND(hooks_tree, &hooks->tree, &hook0);
138: }
139: return (hook);
140: }
141:
1.7 ! nicm 142: void
1.4 nicm 143: hooks_run(struct hooks *hooks, struct client *c, struct cmd_find_state *fs,
144: const char *fmt, ...)
1.1 nicm 145: {
146: struct hook *hook;
1.3 nicm 147: va_list ap;
148: char *name;
1.7 ! nicm 149: struct cmd_q *new_cmdq, *loop;
1.3 nicm 150:
151: va_start(ap, fmt);
152: xvasprintf(&name, fmt, ap);
153: va_end(ap);
1.1 nicm 154:
155: hook = hooks_find(hooks, name);
1.3 nicm 156: if (hook == NULL) {
157: free(name);
1.7 ! nicm 158: return;
1.3 nicm 159: }
1.1 nicm 160: log_debug("running hook %s", name);
1.3 nicm 161:
1.7 ! nicm 162: new_cmdq = cmdq_get_command(hook->cmdlist, fs, NULL, CMD_Q_NOHOOKS);
1.4 nicm 163:
1.7 ! nicm 164: for (loop = new_cmdq; loop != NULL; loop = loop->next)
! 165: loop->hook = xstrdup(name);
! 166: free(name);
1.3 nicm 167:
1.7 ! nicm 168: cmdq_append(c, new_cmdq);
1.3 nicm 169: }
170:
1.7 ! nicm 171: void
! 172: hooks_insert(struct hooks *hooks, struct cmd_q *cmdq, struct cmd_find_state *fs,
1.4 nicm 173: const char *fmt, ...)
1.3 nicm 174: {
175: struct hook *hook;
176: va_list ap;
177: char *name;
1.7 ! nicm 178: struct cmd_q *new_cmdq, *loop;
1.6 nicm 179:
180: if (cmdq->flags & CMD_Q_NOHOOKS)
1.7 ! nicm 181: return;
1.3 nicm 182:
183: va_start(ap, fmt);
184: xvasprintf(&name, fmt, ap);
185: va_end(ap);
186:
187: hook = hooks_find(hooks, name);
188: if (hook == NULL) {
189: free(name);
1.7 ! nicm 190: return;
1.3 nicm 191: }
192: log_debug("running hook %s (parent %p)", name, cmdq);
1.1 nicm 193:
1.7 ! nicm 194: new_cmdq = cmdq_get_command(hook->cmdlist, fs, NULL, CMD_Q_NOHOOKS);
1.4 nicm 195:
1.7 ! nicm 196: for (loop = new_cmdq; loop != NULL; loop = loop->next)
! 197: loop->hook = xstrdup(name);
! 198: free(name);
1.3 nicm 199:
200: if (cmdq != NULL)
1.7 ! nicm 201: cmdq_insert_after(cmdq, new_cmdq);
! 202: else
! 203: cmdq_append(NULL, new_cmdq);
1.1 nicm 204: }