ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/libio/misc/hook.c
Revision: 61
Committed: Mon Oct 3 21:20:41 2005 UTC (20 years, 10 months ago) by adx
Content type: text/x-csrc
File size: 6170 byte(s)
Log Message:
- split libio Makefiles for easier maintenance
- moved pcre.h to main include/ as it is currently a part
  of libio interface (in the future all such headers should
  be moved to libio/ and integrated...)

Now, libio components like comm, misc etc. should be as independent
as possible (from the rest of ircd and from each other), to allow
easy reuse in other software and to keep the interface clean.


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 "ircd.h"
29     #include "list.h"
30     #include "memory.h"
31     #include "numeric.h"
32     #include "tools.h"
33     #include "irc_string.h"
34     #include "send.h"
35    
36     dlink_list callback_list = {NULL, NULL, 0};
37    
38     /*
39     * register_callback()
40     *
41     * Creates a new callback.
42     *
43     * inputs:
44     * name - name used to identify the callback
45     * (can be NULL for anonymous callbacks)
46     * func - initial function attached to the chain
47     * (can be NULL to create an empty chain)
48     * output: pointer to Callback structure or NULL if already exists
49     *
50     * NOTE: Once registered, a callback should never be freed!
51     * That's because there may be modules which depend on it
52     * (even if no functions are attached). That's also why
53     * we dynamically allocate the struct here -- we don't want
54     * to allow anyone to place it in module data, which can be
55     * unloaded at any time.
56     */
57     struct Callback *
58     register_callback(const char *name, CBFUNC *func)
59     {
60     struct Callback *cb;
61    
62     if (name != NULL)
63     if ((cb = find_callback(name)) != NULL)
64     {
65     /* re-attaching an empty hook chain? */
66     if (!is_callback_present(cb))
67     {
68     dlinkAdd(func, MyMalloc(sizeof(dlink_node)), &cb->chain);
69     return (cb);
70     }
71     return (NULL);
72     }
73    
74     cb = MyMalloc(sizeof(struct Callback));
75     if (func != NULL)
76     dlinkAdd(func, MyMalloc(sizeof(dlink_node)), &cb->chain);
77     if (name != NULL)
78     {
79     DupString(cb->name, name);
80     dlinkAdd(cb, &cb->node, &callback_list);
81     }
82     return (cb);
83     }
84    
85     /*
86     * execute_callback()
87     *
88     * Passes control down the callback hook chain.
89     *
90     * inputs:
91     * callback - pointer to Callback structure
92     * param - argument to pass
93     * output: function return value
94     */
95     void *
96     execute_callback(struct Callback *cb, ...)
97     {
98     void *res;
99     va_list args;
100    
101     cb->called++;
102     cb->last = CurrentTime;
103    
104     if (!is_callback_present(cb))
105     return (NULL);
106    
107     va_start(args, cb);
108     res = ((CBFUNC *) cb->chain.head->data)(args);
109     va_end(args);
110     return (res);
111     }
112    
113     /*
114     * pass_callback()
115     *
116     * Called by a hook function to pass code flow further
117     * in the hook chain.
118     *
119     * inputs:
120     * this_hook - pointer to dlink_node of the current hook function
121     * ... - (original or modified) arguments to be passed
122     * output: callback return value
123     */
124     void *
125     pass_callback(dlink_node *this_hook, ...)
126     {
127     void *res;
128     va_list args;
129    
130     if (this_hook->next == NULL)
131     return (NULL); /* reached the last one */
132    
133     va_start(args, this_hook);
134     res = ((CBFUNC *) this_hook->next->data)(args);
135     va_end(args);
136     return (res);
137     }
138    
139     /*
140     * find_callback()
141     *
142     * Finds a named callback.
143     *
144     * inputs:
145     * name - name of the callback
146     * output: pointer to Callback structure or NULL if not found
147     */
148     struct Callback *
149     find_callback(const char *name)
150     {
151     struct Callback *cb;
152     dlink_node *ptr;
153    
154     DLINK_FOREACH(ptr, callback_list.head)
155     {
156     cb = ptr->data;
157     if (!irccmp(cb->name, name))
158     return (cb);
159     }
160    
161     return (NULL);
162     }
163    
164     /*
165     * install_hook()
166     *
167     * Installs a hook for the given callback.
168     *
169     * inputs:
170     * cb - pointer to Callback structure
171     * hook - address of hook function
172     * output: pointer to dlink_node of the hook (used when
173     * passing control to the next hook in the chain);
174     * valid till uninstall_hook() is called
175     *
176     * NOTE: The new hook is installed at the beginning of the chain,
177     * so it has full control over functions installed earlier.
178     */
179     dlink_node *
180     install_hook(struct Callback *cb, CBFUNC *hook)
181     {
182     dlink_node *node = MyMalloc(sizeof(dlink_node));
183    
184     dlinkAdd(hook, node, &cb->chain);
185     return (node);
186     }
187    
188     /*
189     * uninstall_hook()
190     *
191     * Removes a specific hook for the given callback.
192     *
193     * inputs:
194     * cb - pointer to Callback structure
195     * hook - address of hook function
196     * output: none
197     */
198     void
199     uninstall_hook(struct Callback *cb, CBFUNC *hook)
200     {
201     /* let it core if not found */
202     dlink_node *ptr = dlinkFind(&cb->chain, hook);
203    
204     dlinkDelete(ptr, &cb->chain);
205     MyFree(ptr);
206     }
207    
208     /*
209     * stats_hooks()
210     *
211     * Displays registered callbacks and lengths of their hook chains.
212     * (This is the handler of /stats h)
213     *
214     * inputs:
215     * source_p - pointer to struct Client
216     * output: none
217     */
218     void
219     stats_hooks(struct Client *source_p)
220     {
221     dlink_node *ptr;
222     struct Callback *cb;
223     char lastused[32];
224    
225     sendto_one(source_p, ":%s %d %s : %-20s %-20s Used Hooks", me.name,
226     RPL_STATSDEBUG, source_p->name, "Callback", "Last Execution");
227     sendto_one(source_p, ":%s %d %s : ------------------------------------"
228     "--------------------", me.name, RPL_STATSDEBUG, source_p->name);
229    
230     DLINK_FOREACH(ptr, callback_list.head)
231     {
232     cb = ptr->data;
233    
234     if (cb->last != 0)
235     snprintf(lastused, sizeof(lastused), "%d seconds ago",
236     (int) (CurrentTime - cb->last));
237     else
238     strcpy(lastused, "NEVER");
239    
240     sendto_one(source_p, ":%s %d %s : %-20s %-20s %-8u %d", me.name,
241     RPL_STATSDEBUG, source_p->name, cb->name, lastused, cb->called,
242     dlink_list_length(&cb->chain));
243     }
244    
245     sendto_one(source_p, ":%s %d %s : ", me.name, RPL_STATSDEBUG,
246     source_p->name);
247     }

Properties

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