Annotation of src/usr.bin/tmux/hooks.c, Revision 1.6
1.6 ! nicm 1: /* $OpenBSD: hooks.c,v 1.5 2016/10/10 21:29:23 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.3 nicm 36: static void hooks_emptyfn(struct cmd_q *);
1.1 nicm 37:
38: static int
39: hooks_cmp(struct hook *hook1, struct hook *hook2)
40: {
41: return (strcmp(hook1->name, hook2->name));
42: }
43:
44: struct hooks *
1.4 nicm 45: hooks_get(struct session *s)
46: {
47: if (s != NULL)
48: return (s->hooks);
49: return (global_hooks);
50: }
51:
52: struct hooks *
1.1 nicm 53: hooks_create(struct hooks *parent)
54: {
55: struct hooks *hooks;
56:
57: hooks = xcalloc(1, sizeof *hooks);
58: RB_INIT(&hooks->tree);
59: hooks->parent = parent;
60: return (hooks);
61: }
62:
1.2 nicm 63: static void
64: hooks_free1(struct hooks *hooks, struct hook *hook)
65: {
66: RB_REMOVE(hooks_tree, &hooks->tree, hook);
67: cmd_list_free(hook->cmdlist);
68: free((char *)hook->name);
69: free(hook);
70: }
71:
1.1 nicm 72: void
73: hooks_free(struct hooks *hooks)
74: {
75: struct hook *hook, *hook1;
76:
77: RB_FOREACH_SAFE(hook, hooks_tree, &hooks->tree, hook1)
1.2 nicm 78: hooks_free1(hooks, hook);
1.1 nicm 79: free(hooks);
80: }
81:
82: struct hook *
83: hooks_first(struct hooks *hooks)
84: {
85: return (RB_MIN(hooks_tree, &hooks->tree));
86: }
87:
88: struct hook *
89: hooks_next(struct hook *hook)
90: {
91: return (RB_NEXT(hooks_tree, &hooks->tree, hook));
92: }
93:
94: void
95: hooks_add(struct hooks *hooks, const char *name, struct cmd_list *cmdlist)
96: {
97: struct hook *hook;
98:
99: if ((hook = hooks_find1(hooks, name)) != NULL)
1.2 nicm 100: hooks_free1(hooks, hook);
1.1 nicm 101:
102: hook = xcalloc(1, sizeof *hook);
103: hook->name = xstrdup(name);
104: hook->cmdlist = cmdlist;
105: hook->cmdlist->references++;
106: RB_INSERT(hooks_tree, &hooks->tree, hook);
107: }
108:
109: void
1.2 nicm 110: hooks_remove(struct hooks *hooks, const char *name)
1.1 nicm 111: {
1.2 nicm 112: struct hook *hook;
113:
114: if ((hook = hooks_find1(hooks, name)) != NULL)
115: hooks_free1(hooks, hook);
1.1 nicm 116: }
117:
1.2 nicm 118: static struct hook *
1.1 nicm 119: hooks_find1(struct hooks *hooks, const char *name)
120: {
121: struct hook hook;
122:
123: hook.name = name;
124: return (RB_FIND(hooks_tree, &hooks->tree, &hook));
125: }
126:
127: struct hook *
128: hooks_find(struct hooks *hooks, const char *name)
129: {
130: struct hook hook0, *hook;
131:
132: hook0.name = name;
133: hook = RB_FIND(hooks_tree, &hooks->tree, &hook0);
134: while (hook == NULL) {
135: hooks = hooks->parent;
136: if (hooks == NULL)
137: break;
138: hook = RB_FIND(hooks_tree, &hooks->tree, &hook0);
139: }
140: return (hook);
141: }
142:
1.3 nicm 143: static void
144: hooks_emptyfn(struct cmd_q *hooks_cmdq)
145: {
146: struct cmd_q *cmdq = hooks_cmdq->data;
147:
148: if (cmdq != NULL) {
149: if (hooks_cmdq->client_exit >= 0)
150: cmdq->client_exit = hooks_cmdq->client_exit;
151: if (!cmdq_free(cmdq))
152: cmdq_continue(cmdq);
153: }
154: cmdq_free(hooks_cmdq);
155: }
156:
157: int
1.4 nicm 158: hooks_run(struct hooks *hooks, struct client *c, struct cmd_find_state *fs,
159: const char *fmt, ...)
1.1 nicm 160: {
161: struct hook *hook;
1.3 nicm 162: struct cmd_q *hooks_cmdq;
163: va_list ap;
164: char *name;
165:
166: va_start(ap, fmt);
167: xvasprintf(&name, fmt, ap);
168: va_end(ap);
1.1 nicm 169:
170: hook = hooks_find(hooks, name);
1.3 nicm 171: if (hook == NULL) {
172: free(name);
173: return (-1);
174: }
1.1 nicm 175: log_debug("running hook %s", name);
1.3 nicm 176: free(name);
177:
178: hooks_cmdq = cmdq_new(c);
179: hooks_cmdq->flags |= CMD_Q_NOHOOKS;
1.4 nicm 180:
181: if (fs != NULL)
182: cmd_find_copy_state(&hooks_cmdq->current, fs);
1.3 nicm 183: hooks_cmdq->parent = NULL;
184:
185: cmdq_run(hooks_cmdq, hook->cmdlist, NULL);
186: cmdq_free(hooks_cmdq);
187: return (0);
188: }
189:
190: int
1.4 nicm 191: hooks_wait(struct hooks *hooks, struct cmd_q *cmdq, struct cmd_find_state *fs,
192: const char *fmt, ...)
1.3 nicm 193: {
194: struct hook *hook;
195: struct cmd_q *hooks_cmdq;
196: va_list ap;
197: char *name;
1.6 ! nicm 198:
! 199: if (cmdq->flags & CMD_Q_NOHOOKS)
! 200: return (-1);
1.3 nicm 201:
202: va_start(ap, fmt);
203: xvasprintf(&name, fmt, ap);
204: va_end(ap);
205:
206: hook = hooks_find(hooks, name);
207: if (hook == NULL) {
208: free(name);
209: return (-1);
210: }
211: log_debug("running hook %s (parent %p)", name, cmdq);
212: free(name);
1.1 nicm 213:
1.3 nicm 214: hooks_cmdq = cmdq_new(cmdq->client);
215: hooks_cmdq->flags |= CMD_Q_NOHOOKS;
1.4 nicm 216:
217: if (fs != NULL)
218: cmd_find_copy_state(&hooks_cmdq->current, fs);
1.3 nicm 219: hooks_cmdq->parent = cmdq;
220:
221: hooks_cmdq->emptyfn = hooks_emptyfn;
222: hooks_cmdq->data = cmdq;
223:
224: if (cmdq != NULL)
225: cmdq->references++;
226: cmdq_run(hooks_cmdq, hook->cmdlist, NULL);
227: return (0);
1.1 nicm 228: }