ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/hook.c
Revision: 2358
Committed: Thu Jul 4 20:16:08 2013 UTC (12 years, 1 month ago) by michael
Content type: text/x-csrc
File size: 5863 byte(s)
Log Message:
- hook.c: constification/style corrections

File Contents

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

Properties

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