ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/hook.c
Revision: 3334
Committed: Wed Apr 16 16:42:54 2014 UTC (11 years, 4 months ago) by michael
Content type: text/x-csrc
File size: 5752 byte(s)
Log Message:
- Replaced strcpy() with strlcpy() in some places

File Contents

# User Rev Content
1 adx 30 /*
2 michael 2846 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 adx 30 *
4 michael 2846 * Copyright (c) 2003 Piotr Nizynski, Advanced IRC Services Project Team
5     * Copyright (c) 2005-2014 ircd-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    
23 michael 1149 /*! \file hook.c
24     * \brief Provides a generic event hooking interface.
25     * \version $Id$
26     */
27    
28 adx 30 #include "stdinc.h"
29 michael 1011 #include "list.h"
30 adx 30 #include "hook.h"
31     #include "ircd.h"
32     #include "memory.h"
33     #include "numeric.h"
34     #include "irc_string.h"
35     #include "send.h"
36 michael 1011 #include "client.h"
37 adx 30
38 michael 2846
39 michael 2358 static dlink_list callback_list;
40 adx 30
41 michael 2358
42 michael 1149 /*! \brief Creates a new callback.
43 michael 2846 * \param name Name used to identify the callback
44 adx 30 * (can be NULL for anonymous callbacks)
45 michael 2846 * \param func Initial function attached to the chain
46 adx 30 * (can be NULL to create an empty chain)
47 michael 2846 * \return Pointer to Callback structure or NULL if already exists
48 michael 1149 * \note Once registered, a callback should never be freed!
49 adx 30 * 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 michael 1149 struct Callback *cb = NULL;
59 adx 30
60 michael 3218 if (name)
61 michael 1149 {
62 michael 3218 if ((cb = find_callback(name)))
63 adx 30 {
64 michael 3218 if (func)
65 michael 713 dlinkAddTail(func, MyMalloc(sizeof(dlink_node)), &cb->chain);
66 michael 1149
67     return cb;
68 adx 30 }
69 michael 1149 }
70 adx 30
71     cb = MyMalloc(sizeof(struct Callback));
72 michael 2358
73 michael 3218 if (func)
74 adx 30 dlinkAdd(func, MyMalloc(sizeof(dlink_node)), &cb->chain);
75 michael 1149
76 michael 3218 if (name)
77 adx 30 {
78 michael 1646 cb->name = xstrdup(name);
79 adx 30 dlinkAdd(cb, &cb->node, &callback_list);
80     }
81 michael 1149
82     return cb;
83 adx 30 }
84    
85 michael 1149 /*! \brief Passes control down the callback hook chain.
86 michael 2846 * \param cb Pointer to Callback structure
87     * \param ... Argument to pass
88     * \return function Return value
89 adx 30 */
90     void *
91     execute_callback(struct Callback *cb, ...)
92     {
93 michael 2358 void *res = NULL;
94 adx 30 va_list args;
95    
96     cb->called++;
97     cb->last = CurrentTime;
98    
99     if (!is_callback_present(cb))
100 michael 1149 return NULL;
101 adx 30
102     va_start(args, cb);
103 michael 2358 res = ((CBFUNC *)cb->chain.head->data)(args);
104 adx 30 va_end(args);
105 michael 1149
106     return res;
107 adx 30 }
108    
109 michael 1149 /*! \brief Called by a hook function to pass code flow further
110     * in the hook chain.
111 michael 2846 * \param this_hook Pointer to dlink_node of the current hook function
112 michael 1149 * \param ... (original or modified) arguments to be passed
113 michael 2846 * \return callback Return value
114 adx 30 */
115     void *
116     pass_callback(dlink_node *this_hook, ...)
117     {
118 michael 2358 void *res = NULL;
119 adx 30 va_list args;
120    
121     if (this_hook->next == NULL)
122 michael 2846 return NULL; /* Reached the last one */
123 adx 30
124     va_start(args, this_hook);
125 michael 2358 res = ((CBFUNC *)this_hook->next->data)(args);
126 adx 30 va_end(args);
127 michael 1149
128     return res;
129 adx 30 }
130    
131 michael 1149 /*! \brief Finds a named callback.
132 michael 2846 * \param name Name of the callback
133     * \return Pointer to Callback structure or NULL if not found
134 adx 30 */
135     struct Callback *
136     find_callback(const char *name)
137     {
138 michael 2358 dlink_node *ptr = NULL;
139 adx 30
140     DLINK_FOREACH(ptr, callback_list.head)
141 michael 3218 if (!irccmp(((struct Callback *)ptr->data)->name, name))
142     return ptr->data;
143 michael 1149
144     return NULL;
145 adx 30 }
146    
147 michael 1149 /*! \brief Installs a hook for the given callback.
148 adx 30 *
149 michael 1149 * The new hook is installed at the beginning of the chain,
150     * so it has full control over functions installed earlier.
151 adx 30 *
152 michael 2846 * \param cb Pointer to Callback structure
153     * \param hook Address of hook function
154     * \return Pointer to dlink_node of the hook (used when passing
155 michael 1149 * control to the next hook in the chain);
156 adx 30 * valid till uninstall_hook() is called
157     */
158     dlink_node *
159     install_hook(struct Callback *cb, CBFUNC *hook)
160     {
161     dlink_node *node = MyMalloc(sizeof(dlink_node));
162    
163     dlinkAdd(hook, node, &cb->chain);
164 michael 1149 return node;
165 adx 30 }
166    
167 michael 1149 /*! \brief Removes a specific hook for the given callback.
168 michael 2846 * \param cb Pointer to Callback structure
169     * \param hook Address of hook function
170 adx 30 */
171     void
172     uninstall_hook(struct Callback *cb, CBFUNC *hook)
173     {
174 michael 2358 /* Let it core if not found */
175 adx 30 dlink_node *ptr = dlinkFind(&cb->chain, hook);
176    
177     dlinkDelete(ptr, &cb->chain);
178     MyFree(ptr);
179     }
180    
181 michael 1149 /*! \brief Displays registered callbacks and lengths of their hook chains.
182     * (This is the handler of /stats h)
183 michael 2846 * \param source_p Pointer to struct Client
184 adx 30 */
185     void
186     stats_hooks(struct Client *source_p)
187     {
188 michael 3218 char lastused[IRCD_BUFSIZE] = "";
189 michael 2358 const dlink_node *ptr = NULL;
190 adx 30
191     sendto_one(source_p, ":%s %d %s : %-20s %-20s Used Hooks", me.name,
192     RPL_STATSDEBUG, source_p->name, "Callback", "Last Execution");
193     sendto_one(source_p, ":%s %d %s : ------------------------------------"
194     "--------------------", me.name, RPL_STATSDEBUG, source_p->name);
195    
196     DLINK_FOREACH(ptr, callback_list.head)
197     {
198 michael 2358 const struct Callback *cb = ptr->data;
199 adx 30
200 michael 3218 if (cb->last)
201 adx 30 snprintf(lastused, sizeof(lastused), "%d seconds ago",
202 michael 3218 (int)(CurrentTime - cb->last));
203 adx 30 else
204 michael 3334 strlcpy(lastused, "NEVER", sizeof(lastused));
205 adx 30
206     sendto_one(source_p, ":%s %d %s : %-20s %-20s %-8u %d", me.name,
207     RPL_STATSDEBUG, source_p->name, cb->name, lastused, cb->called,
208 michael 2358 dlink_list_length(&cb->chain));
209 adx 30 }
210     }

Properties

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