ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/libio/misc/hook.c
Revision: 65
Committed: Mon Oct 3 23:33:16 2005 UTC (20 years, 10 months ago) by adx
Content type: text/x-csrc
File size: 4986 byte(s)
Log Message:
- removed external references from libio/misc
- imported s_misc.c to libio, moved CurrentTime there

File Contents

# User Rev Content
1 adx 61 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * hook.c: Provides a generic event hooking interface.
4     *
5     * Copyright (C) 2003 Piotr Nizynski, Advanced IRC Services Project Team
6     * Copyright (C) 2005 Hybrid Development Team
7     *
8     * This program is free software; you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License as published by
10     * the Free Software Foundation; either version 2 of the License, or
11     * (at your option) any later version.
12     *
13     * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17     *
18     * You should have received a copy of the GNU General Public License
19     * along with this program; if not, write to the Free Software
20     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21     * USA
22     *
23     * $Id: hook.c 33 2005-10-02 20:50:00Z knight $
24     */
25    
26     #include "stdinc.h"
27     #include "hook.h"
28     #include "list.h"
29     #include "memory.h"
30     #include "tools.h"
31     #include "irc_string.h"
32 adx 65 #include "s_misc.h"
33 adx 61
34     dlink_list callback_list = {NULL, NULL, 0};
35    
36     /*
37     * register_callback()
38     *
39     * Creates a new callback.
40     *
41     * inputs:
42     * name - name used to identify the callback
43     * (can be NULL for anonymous callbacks)
44     * func - initial function attached to the chain
45     * (can be NULL to create an empty chain)
46     * output: pointer to Callback structure or NULL if already exists
47     *
48     * NOTE: Once registered, a callback should never be freed!
49     * That's because there may be modules which depend on it
50     * (even if no functions are attached). That's also why
51     * we dynamically allocate the struct here -- we don't want
52     * to allow anyone to place it in module data, which can be
53     * unloaded at any time.
54     */
55     struct Callback *
56     register_callback(const char *name, CBFUNC *func)
57     {
58     struct Callback *cb;
59    
60     if (name != NULL)
61     if ((cb = find_callback(name)) != NULL)
62     {
63     /* re-attaching an empty hook chain? */
64     if (!is_callback_present(cb))
65     {
66     dlinkAdd(func, MyMalloc(sizeof(dlink_node)), &cb->chain);
67     return (cb);
68     }
69     return (NULL);
70     }
71    
72     cb = MyMalloc(sizeof(struct Callback));
73     if (func != NULL)
74     dlinkAdd(func, MyMalloc(sizeof(dlink_node)), &cb->chain);
75     if (name != NULL)
76     {
77     DupString(cb->name, name);
78     dlinkAdd(cb, &cb->node, &callback_list);
79     }
80     return (cb);
81     }
82    
83     /*
84     * execute_callback()
85     *
86     * Passes control down the callback hook chain.
87     *
88     * inputs:
89     * callback - pointer to Callback structure
90     * param - argument to pass
91     * output: function return value
92     */
93     void *
94     execute_callback(struct Callback *cb, ...)
95     {
96     void *res;
97     va_list args;
98    
99     cb->called++;
100     cb->last = CurrentTime;
101    
102     if (!is_callback_present(cb))
103     return (NULL);
104    
105     va_start(args, cb);
106     res = ((CBFUNC *) cb->chain.head->data)(args);
107     va_end(args);
108     return (res);
109     }
110    
111     /*
112     * pass_callback()
113     *
114     * Called by a hook function to pass code flow further
115     * in the hook chain.
116     *
117     * inputs:
118     * this_hook - pointer to dlink_node of the current hook function
119     * ... - (original or modified) arguments to be passed
120     * output: callback return value
121     */
122     void *
123     pass_callback(dlink_node *this_hook, ...)
124     {
125     void *res;
126     va_list args;
127    
128     if (this_hook->next == NULL)
129     return (NULL); /* reached the last one */
130    
131     va_start(args, this_hook);
132     res = ((CBFUNC *) this_hook->next->data)(args);
133     va_end(args);
134     return (res);
135     }
136    
137     /*
138     * find_callback()
139     *
140     * Finds a named callback.
141     *
142     * inputs:
143     * name - name of the callback
144     * output: pointer to Callback structure or NULL if not found
145     */
146     struct Callback *
147     find_callback(const char *name)
148     {
149     struct Callback *cb;
150     dlink_node *ptr;
151    
152     DLINK_FOREACH(ptr, callback_list.head)
153     {
154     cb = ptr->data;
155     if (!irccmp(cb->name, name))
156     return (cb);
157     }
158    
159     return (NULL);
160     }
161    
162     /*
163     * install_hook()
164     *
165     * Installs a hook for the given callback.
166     *
167     * inputs:
168     * cb - pointer to Callback structure
169     * hook - address of hook function
170     * output: pointer to dlink_node of the hook (used when
171     * passing control to the next hook in the chain);
172     * valid till uninstall_hook() is called
173     *
174     * NOTE: The new hook is installed at the beginning of the chain,
175     * so it has full control over functions installed earlier.
176     */
177     dlink_node *
178     install_hook(struct Callback *cb, CBFUNC *hook)
179     {
180     dlink_node *node = MyMalloc(sizeof(dlink_node));
181    
182     dlinkAdd(hook, node, &cb->chain);
183     return (node);
184     }
185    
186     /*
187     * uninstall_hook()
188     *
189     * Removes a specific hook for the given callback.
190     *
191     * inputs:
192     * cb - pointer to Callback structure
193     * hook - address of hook function
194     * output: none
195     */
196     void
197     uninstall_hook(struct Callback *cb, CBFUNC *hook)
198     {
199     /* let it core if not found */
200     dlink_node *ptr = dlinkFind(&cb->chain, hook);
201    
202     dlinkDelete(ptr, &cb->chain);
203     MyFree(ptr);
204     }

Properties

Name Value
svn:eol-style native
svn:keywords "Id Revision"