ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/hook.c
(Generate patch)

Comparing:
ircd-hybrid-7.2/src/hook.c (file contents), Revision 713 by michael, Wed Jul 12 12:37:35 2006 UTC vs.
ircd-hybrid/trunk/src/hook.c (file contents), Revision 2358 by michael, Thu Jul 4 20:16:08 2013 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)