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