ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/libio/misc/hook.c
Revision: 69
Committed: Tue Oct 4 16:09:51 2005 UTC (20 years, 10 months ago) by adx
Content type: text/x-csrc
File size: 4867 byte(s)
Log Message:
- splitted ircd/libio, all headers connected with libio sources have been
  moved for internal use only. To use libio interface, include "libio.h"
  (which is already done in "stdinc.h")


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    
28     dlink_list callback_list = {NULL, NULL, 0};
29    
30     /*
31     * register_callback()
32     *
33     * Creates a new callback.
34     *
35     * inputs:
36     * name - name used to identify the callback
37     * (can be NULL for anonymous callbacks)
38     * func - initial function attached to the chain
39     * (can be NULL to create an empty chain)
40     * output: pointer to Callback structure or NULL if already exists
41     *
42     * NOTE: Once registered, a callback should never be freed!
43     * That's because there may be modules which depend on it
44     * (even if no functions are attached). That's also why
45     * we dynamically allocate the struct here -- we don't want
46     * to allow anyone to place it in module data, which can be
47     * unloaded at any time.
48     */
49     struct Callback *
50     register_callback(const char *name, CBFUNC *func)
51     {
52     struct Callback *cb;
53    
54     if (name != NULL)
55     if ((cb = find_callback(name)) != NULL)
56     {
57     /* re-attaching an empty hook chain? */
58     if (!is_callback_present(cb))
59     {
60     dlinkAdd(func, MyMalloc(sizeof(dlink_node)), &cb->chain);
61     return (cb);
62     }
63     return (NULL);
64     }
65    
66     cb = MyMalloc(sizeof(struct Callback));
67     if (func != NULL)
68     dlinkAdd(func, MyMalloc(sizeof(dlink_node)), &cb->chain);
69     if (name != NULL)
70     {
71     DupString(cb->name, name);
72     dlinkAdd(cb, &cb->node, &callback_list);
73     }
74     return (cb);
75     }
76    
77     /*
78     * execute_callback()
79     *
80     * Passes control down the callback hook chain.
81     *
82     * inputs:
83     * callback - pointer to Callback structure
84     * param - argument to pass
85     * output: function return value
86     */
87     void *
88     execute_callback(struct Callback *cb, ...)
89     {
90     void *res;
91     va_list args;
92    
93     cb->called++;
94     cb->last = CurrentTime;
95    
96     if (!is_callback_present(cb))
97     return (NULL);
98    
99     va_start(args, cb);
100     res = ((CBFUNC *) cb->chain.head->data)(args);
101     va_end(args);
102     return (res);
103     }
104    
105     /*
106     * pass_callback()
107     *
108     * Called by a hook function to pass code flow further
109     * in the hook chain.
110     *
111     * inputs:
112     * this_hook - pointer to dlink_node of the current hook function
113     * ... - (original or modified) arguments to be passed
114     * output: callback return value
115     */
116     void *
117     pass_callback(dlink_node *this_hook, ...)
118     {
119     void *res;
120     va_list args;
121    
122     if (this_hook->next == NULL)
123     return (NULL); /* reached the last one */
124    
125     va_start(args, this_hook);
126     res = ((CBFUNC *) this_hook->next->data)(args);
127     va_end(args);
128     return (res);
129     }
130    
131     /*
132     * find_callback()
133     *
134     * Finds a named callback.
135     *
136     * inputs:
137     * name - name of the callback
138     * output: pointer to Callback structure or NULL if not found
139     */
140     struct Callback *
141     find_callback(const char *name)
142     {
143     struct Callback *cb;
144     dlink_node *ptr;
145    
146     DLINK_FOREACH(ptr, callback_list.head)
147     {
148     cb = ptr->data;
149     if (!irccmp(cb->name, name))
150     return (cb);
151     }
152    
153     return (NULL);
154     }
155    
156     /*
157     * install_hook()
158     *
159     * Installs a hook for the given callback.
160     *
161     * inputs:
162     * cb - pointer to Callback structure
163     * hook - address of hook function
164     * output: pointer to dlink_node of the hook (used when
165     * passing control to the next hook in the chain);
166     * valid till uninstall_hook() is called
167     *
168     * NOTE: The new hook is installed at the beginning of the chain,
169     * so it has full control over functions installed earlier.
170     */
171     dlink_node *
172     install_hook(struct Callback *cb, CBFUNC *hook)
173     {
174     dlink_node *node = MyMalloc(sizeof(dlink_node));
175    
176     dlinkAdd(hook, node, &cb->chain);
177     return (node);
178     }
179    
180     /*
181     * uninstall_hook()
182     *
183     * Removes a specific hook for the given callback.
184     *
185     * inputs:
186     * cb - pointer to Callback structure
187     * hook - address of hook function
188     * output: none
189     */
190     void
191     uninstall_hook(struct Callback *cb, CBFUNC *hook)
192     {
193     /* let it core if not found */
194     dlink_node *ptr = dlinkFind(&cb->chain, hook);
195    
196     dlinkDelete(ptr, &cb->chain);
197     MyFree(ptr);
198     }

Properties

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