1 |
<?xml version="1.0" encoding="ISO-8859-1"?> |
2 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11-strict.dtd"> |
3 |
<!-- Annoyingly, <u> has been removed, so replacing it with <span style="text-decoration: underline"> --> |
4 |
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> |
5 |
<head> |
6 |
<meta http-equiv="Content-Style-Type" content="text/css"/> |
7 |
<style type="text/css">@import "style.css";</style> |
8 |
<title>IRC Services Technical Reference Manual - 2. Core Services functionality</title> |
9 |
</head> |
10 |
|
11 |
<body> |
12 |
<h1 class="title" id="top">IRC Services Technical Reference Manual</h1> |
13 |
|
14 |
<h2 class="section-title">2. Core Services functionality</h2> |
15 |
|
16 |
<p class="section-toc"> |
17 |
2-1. <a href="#s1">How does Services work?</a> |
18 |
<br/>2-2. <a href="#s2">Utility headers and functions</a> |
19 |
<br/> 2-2-1. <a href="#s2-1">Header file overview</a> |
20 |
<br/> 2-2-2. <a href="#s2-2">Compatibility functions</a> |
21 |
<br/> 2-2-3. <a href="#s2-3">Memory allocation</a> |
22 |
<br/> 2-2-4. <a href="#s2-4">List and array macros</a> |
23 |
<br/> 2-2-5. <a href="#s2-5">Generic hash tables</a> |
24 |
<br/> 2-2-6. <a href="#s2-6">Other utility functions</a> |
25 |
<br/>2-3. <a href="#s3">Program startup and termination</a> |
26 |
<br/> 2-3-1. <a href="#s3-1">Initialization</a> |
27 |
<br/> 2-3-2. <a href="#s3-2">Configuration files</a> |
28 |
<br/> 2-3-3. <a href="#s3-3">The main loop</a> |
29 |
<br/> 2-3-4. <a href="#s3-4">Signals</a> |
30 |
<br/> 2-3-5. <a href="#s3-5">Termination</a> |
31 |
<br/>2-4. <a href="#s4">Logging</a> |
32 |
<br/>2-5. <a href="#s5">Message sending and receiving</a> |
33 |
<br/> 2-5-1. <a href="#s5-1">Sending messages</a> |
34 |
<br/> 2-5-2. <a href="#s5-2">Receiving messages</a> |
35 |
<br/> 2-5-3. <a href="#s5-3">Processing messages</a> |
36 |
<br/> 2-5-4. <a href="#s5-4">The ignore list</a> |
37 |
<br/>2-6. <a href="#s6">Servers, clients, and channels</a> |
38 |
<br/> 2-6-1. <a href="#s6-1">Servers</a> |
39 |
<br/> 2-6-2. <a href="#s6-2">Clients</a> |
40 |
<br/> 2-6-3. <a href="#s6-3">Channels</a> |
41 |
<br/> 2-6-4. <a href="#s6-4">Client and channel modes</a> |
42 |
<br/> 2-6-5. <a href="#s6-5">High-level actions</a> |
43 |
<br/>2-7. <a href="#s7">Timed events</a> |
44 |
<br/>2-8. <a href="#s8">Multilingual support</a> |
45 |
<br/> 2-8-1. <a href="#s8-1">Overview</a> |
46 |
<br/> 2-8-2. <a href="#s8-2">Using multilingual strings</a> |
47 |
<br/> 2-8-3. <a href="#s8-3">Modifying the string table at runtime</a> |
48 |
<br/> 2-8-4. <a href="#s8-4">The language file compiler</a> |
49 |
<br/>2-9. <a href="#s9">Module interfaces</a> |
50 |
<br/> 2-9-1. <a href="#s9-1">Encryption</a> |
51 |
<br/> 2-9-2. <a href="#s9-2">Database storage</a> |
52 |
<br/>2-10. <a href="#s10">Module command list maintenance</a> |
53 |
</p> |
54 |
|
55 |
<p class="backlink"><a href="1.html">Previous section: About this manual</a> | |
56 |
<a href="index.html">Table of Contents</a> | |
57 |
<a href="3.html">Next section: Communication (socket) handling</a></p> |
58 |
|
59 |
<!------------------------------------------------------------------------> |
60 |
<hr/> |
61 |
|
62 |
<h3 class="subsection-title" id="s1">2-1. How does Services work?</h3> |
63 |
|
64 |
<p>Services is, at its simplest, simply an IRC server with built-in "bots" |
65 |
("pseudoclients"—fake clients—in this documentation). The core |
66 |
of Services consists of code to connect to a given IRC server and register |
67 |
in the same way as an ordinary IRC server would, then process IRC messages |
68 |
that arrive from the remote server; instead of listening for client |
69 |
connections and mediating client-to-client conversation, however, Services |
70 |
instead passes received messages to its pseudoclients, which take |
71 |
appropriate action based on the message (for example, sending a |
72 |
<tt>/msg</tt> containing "<tt>REGISTER mypassword</tt>" to NickServ, the |
73 |
nickname registration pseudoclient, causes NickServ to register the |
74 |
nickname of the user who sent the message). In this sense, Services can be |
75 |
considered an extension of the traditional IRC bot, but since its many |
76 |
capabilities require knowledge of the state of the entire IRC |
77 |
network—information not available to clients—it is implemented |
78 |
as a server instead.</p> |
79 |
|
80 |
<p>Services is composed of a core set of functionality, discussed in this |
81 |
section and in sections 3 and 4, on top of which sit modules implementing |
82 |
features such as pseudoclients and database storage, discussed in sections |
83 |
5 through 8. This section discusses the overall flow of execution, and |
84 |
the implementation details of each set of core functions.</p> |
85 |
|
86 |
<p>The source code for the core functionality is located in the top source |
87 |
directory. The style guidelines used in writing the Services code can be |
88 |
found in <a href="d.html">Appendix D</a>; one point that should be noted in |
89 |
particular is that each source file contains a trailer instructing the |
90 |
Emacs and Vim text editors to indent properly and not use tab characters, |
91 |
and this trailer should be appended to any new source files created:</p> |
92 |
|
93 |
<div class="code">/* |
94 |
* Local variables: |
95 |
* c-file-style: "stroustrup" |
96 |
* c-file-offsets: ((case-label . *) (statement-case-intro . *)) |
97 |
* indent-tabs-mode: nil |
98 |
* End: |
99 |
* |
100 |
* vim: expandtab shiftwidth=4: |
101 |
*/</div> |
102 |
|
103 |
<p class="backlink"><a href="#top">Back to top</a></p> |
104 |
|
105 |
<!------------------------------------------------------------------------> |
106 |
<hr/> |
107 |
|
108 |
<h3 class="subsection-title" id="s2">2-2. Utility headers and functions</h3> |
109 |
|
110 |
<p>Before beginning a discussion of the code itself, it is worth noting the |
111 |
common header files used by most of the source code. The various utility |
112 |
routines implemented in Services, are also mentioned, as these are often |
113 |
used in place of traditional C library functions.</p> |
114 |
|
115 |
<p class="backlink"><a href="#top">Back to top</a></p> |
116 |
|
117 |
|
118 |
<h4 class="subsubsection-title" id="s2-1">2-2-1. Header file overview</h4> |
119 |
|
120 |
<p>While many of the core function groups have their own header files, as |
121 |
noted below, some of the more common routines and structure definitions are |
122 |
collected into a few main header files to reduce file clutter. These files |
123 |
are:</p> |
124 |
|
125 |
<ul> |
126 |
|
127 |
<li class="spaced"><b><tt>services.h</tt>:</b> The main Services header |
128 |
file, included by every source file. This file includes the following |
129 |
header files automatically: |
130 |
<ul style="margin-top: 0; margin-bottom: 0"> |
131 |
<li><tt>config.h</tt></li> |
132 |
<li><tt>defs.h</tt></li> |
133 |
<li><tt>memory.h</tt></li> |
134 |
<li><tt>list-array.h</tt></li> |
135 |
<li><tt>log.h</tt></li> |
136 |
<li><tt>sockets.h</tt></li> |
137 |
<li><tt>send.h</tt></li> |
138 |
<li><tt>modes.h</tt></li> |
139 |
<li><tt>users.h</tt></li> |
140 |
<li><tt>channels.h</tt></li> |
141 |
<li><tt>servers.h</tt></li> |
142 |
<li><tt>extern.h</tt></li> |
143 |
</ul> |
144 |
<tt>services.h</tt> also declares type names for several common data |
145 |
structures, as well as constants for the <tt>clear_channel()</tt> function |
146 |
(see <a href="#s6-5">section 2-6-5</a>).</li> |
147 |
|
148 |
<li class="spaced"><b><tt>config.h</tt>:</b> Contains basic information |
149 |
about the compilation and execution environment, along with compilation |
150 |
options selected by the user. Generated automatically by the |
151 |
<tt>configure</tt> script (see <a href="10.html#s2">section 10-2</a>). |
152 |
Among the definitions in this file are types for integers of specific |
153 |
sizes: <tt>int8</tt>, <tt>int16</tt>, and <tt>int32</tt> for signed 8-bit, |
154 |
16-bit, and 32-bit integers respectively, and <tt>uint8</tt>, |
155 |
<tt>uint16</tt>, and <tt>uint32</tt> for unsigned integers. (See |
156 |
<a href="11.html#s1">section 11-1</a> for why the standard <tt>int8_t</tt> |
157 |
and similar types were not used.)</li> |
158 |
|
159 |
<li class="spaced"><b><tt>defs.h</tt>:</b> Contains basic constants and |
160 |
macros used by Services. The top part of this file, through the line that |
161 |
reads "<tt>There should be no need to modify anything below this |
162 |
line.</tt>", contains settings that can be edited by users with special |
163 |
needs but are considered esoteric enough that they do not warrant an extra |
164 |
option to the <tt>configure</tt> script. The <tt>NICKMAX</tt>, |
165 |
<tt>CHANMAX</tt>, and <tt>PASSMAX</tt> constants, in particular, set the |
166 |
size of buffers (including the trailing null on strings) used for |
167 |
nicknames, channels, and passwords; the databases rely on these remaining |
168 |
constant for a given set of data, and changing them will result in the |
169 |
data files becoming unusable. For the <tt>convert-db</tt> utility (see |
170 |
<a href="9.html">section 9</a>), they are defined to values large enough |
171 |
to handle any data found in other programs' data files, and should never be |
172 |
changed. The latter half of this file consists of including proper system |
173 |
header files, based on the contents of <tt>config.h</tt>, and ensuring that |
174 |
some basic system constants are defined. A few other simple macros are |
175 |
defined as well: |
176 |
<ul style="margin-top: 0; margin-bottom: 0"> |
177 |
<li><tt>sizeof(<i>v</i>)</tt> is redefined to return a signed |
178 |
<tt>int</tt> value, to avoid unnecessary warnings about |
179 |
signed/unsigned conversion.</li> |
180 |
<li><tt>lenof(<i>a</i>)</tt> gives the length of an array in |
181 |
elements (this must be a C array, not a pointer).</li> |
182 |
<li><tt>sgn(<i>n</i>)</tt> returns -1 if its parameter is negative, |
183 |
1 if positive, and 0 if zero; note that <tt><i>n</i></tt> |
184 |
may be evaluated twice.</li> |
185 |
<li><tt>FORMAT(<i>type</i>,<i>fmt</i>,<i>start</i>)</tt> |
186 |
encapsulates GCC's "format" attribute, used for checking |
187 |
arguments to functions that take format strings, without |
188 |
causing errors on other compilers.</li> |
189 |
<li><tt>FUNCPTR</tt> and <tt>E_FUNCPTR</tt> are used to get around |
190 |
an apparent GCC problem in attributes on function |
191 |
pointers.</li> |
192 |
<li><tt>PTR_INVALID</tt> is a pointer value that can be used when |
193 |
an invalid pointer value other than <tt>NULL</tt> is |
194 |
required.</li> |
195 |
</ul> |
196 |
</li> |
197 |
|
198 |
<li class="spaced"><b><tt>extern.h</tt>:</b> Contains <tt>extern</tt> |
199 |
declarations for core source files which do not have their own separate |
200 |
header files. Also defines <tt>E</tt> as an abbreviation for |
201 |
<tt>extern</tt>.</li> |
202 |
|
203 |
</ul> |
204 |
|
205 |
<p class="backlink"><a href="#top">Back to top</a></p> |
206 |
|
207 |
|
208 |
<h4 class="subsubsection-title" id="s2-2">2-2-2. Compatibility functions</h4> |
209 |
|
210 |
<p>While most modern compilation environments have a fairly wide range of |
211 |
standard functions included, such functions may not be available on some |
212 |
platforms, or their implementations may contain bugs. To work around such |
213 |
problems, Services includes local versions of several common functions in |
214 |
<tt>compat.c</tt>, and enables them as necessary based on the configuration |
215 |
results stored in <tt>config.h</tt>. These functions are:</p> |
216 |
<ul> |
217 |
<li><tt>hstrerror()</tt> (<tt>strerror()</tt> for hostname resolution)</li> |
218 |
<li><tt>snprintf()</tt> / <tt>vsnprintf()</tt> (defined in <tt>vsnprintf.c</tt>)</li> |
219 |
<li><tt>strtok()</tt></li> |
220 |
<li><tt>stricmp()</tt> / <tt>strnicmp()</tt></li> |
221 |
<li><tt>strdup()</tt></li> |
222 |
<li><tt>strspn()</tt> / <tt>strcspn()</tt></li> |
223 |
<li><tt>strerror()</tt></li> |
224 |
<li><tt>strsignal()</tt></li> |
225 |
</ul> |
226 |
<p><tt>strtok()</tt>, in particular, bears mentioning as its behavior in |
227 |
certain cases does not seem to be well-defined by the standard (see, for |
228 |
example, the definition in |
229 |
<a href="http://www.opengroup.org/onlinepubs/009695399/functions/strtok.html">IEEE Std 1003.1-2001</a> |
230 |
<span class="remotehost">[www.opengroup.org]</span>). The Services |
231 |
pseudoclients use <tt>strtok()</tt> to parse commands from clients; in some |
232 |
cases, where a final parameter may contain space characters, this results |
233 |
in the following sequence of calls:</p> |
234 |
<div class="code">char *param1 = strtok(NULL, " "); |
235 |
char *param2 = strtok(NULL, "");</div> |
236 |
<p>For conciseness, Services does not check the value of each |
237 |
<tt>strtok()</tt> call, assuming that if at some point the end of the |
238 |
string is reached, all subsequent calls will return <tt>NULL</tt>. |
239 |
However, if the remainder of the string contains multiple space characters, |
240 |
some implementations will return the remaining whitespace for the second |
241 |
call despite returning <tt>NULL</tt> for the first (others, such as old |
242 |
versions of glibc, have been known to crash on the second call). I have |
243 |
not confirmed whether this difference in behavior still has an effect on |
244 |
Services, but it did cause problems at one point; hence this behavior is |
245 |
checked for, and the compatibility <tt>strtok()</tt> is enabled if the |
246 |
system <tt>strtok()</tt> does not behave as Services expects.</p> |
247 |
|
248 |
<p>Also, the <tt>stricmp()</tt> and <tt>strnicmp()</tt> functions are |
249 |
alternate names for the POSIX <tt>strcasecmp()</tt> and |
250 |
<tt>strncasecmp()</tt> functions (the "i" is for "case-insensitive"). I |
251 |
prefer the former pair of names because I find them to be both concise and |
252 |
clearer about the function's purpose—to me, "case" says |
253 |
"case-<i>sensitive</i>", and I have to recall that <tt>strcmp()</tt> itself |
254 |
is case-sensitive to avoid confusion. Some compilation environments do in |
255 |
fact provide <tt>stricmp()</tt> and <tt>strnicmp()</tt> functions, and they |
256 |
are used if present; if the <tt>strcasecmp()</tt> pair is instead found, |
257 |
<tt>stricmp</tt> and <tt>strnicmp</tt> are defined to be aliases for them.</p> |
258 |
|
259 |
<p class="backlink"><a href="#top">Back to top</a></p> |
260 |
|
261 |
|
262 |
<h4 class="subsubsection-title" id="s2-3">2-2-3. Memory allocation</h4> |
263 |
|
264 |
<p>Services implements wrappers for the four primary memory allocation |
265 |
functions:</p> |
266 |
<ul> |
267 |
<li><tt><b>smalloc</b>(long <i>size</i>)</tt></li> |
268 |
<li><tt><b>scalloc</b>(long <i>els</i>, long <i>elsize</i>)</tt></li> |
269 |
<li><tt><b>srealloc</b>(void *<i>oldptr</i>, long <i>newsize</i>)</tt></li> |
270 |
<li><tt><b>sstrdup</b>(const char *<i>s</i>)</tt></li> |
271 |
</ul> |
272 |
<p>The "s" prefix in these function names is short for "safe": if one of |
273 |
these functions fails to allocate memory, it will abort the program by |
274 |
generating a <tt>SIGUSR1</tt> signal (see <a href="#s3-4">section 2-3-4</a>) |
275 |
rather than returning <tt>NULL</tt>, so the caller can safely assume that |
276 |
if the memory size requested was not zero, the return value will not be |
277 |
<tt>NULL</tt>. (This concept is carried over from the earliest days of |
278 |
Services development, when it was known that memory allocation would never |
279 |
fail barring a program bug; however, it is arguably a bad design and could |
280 |
be improved. See <a href="11.html#s1">section 11-1</a>.) These functions |
281 |
are implemented in the file <tt>memory.c</tt>, with declarations in |
282 |
<tt>memory.h</tt> (included by <tt>services.h</tt>).</p> |
283 |
|
284 |
<p>Services also has a simple memory misuse checker, activated by the |
285 |
<tt>-memchecks</tt> option to <tt>configure</tt>; this code is not very |
286 |
thorough, but can detect some cases of access to unallocated memory, such |
287 |
as trying to free an already-free block of memory, and report the source |
288 |
code file and line where the problem occurred via macros in |
289 |
<tt>memory.h</tt>. In addition, if the <tt>-showallocs</tt> option is |
290 |
given to <tt>configure</tt>, these functions will log every memory |
291 |
allocation and release to the log file, again with the relevant source code |
292 |
file and line, and report on exit whether any memory was leaked. If a leak |
293 |
is found, the log file can be parsed to find allocations which were not |
294 |
reallocated or freed.</p> |
295 |
|
296 |
<p>The <tt>FILELINE</tt> macro used in the definitions of |
297 |
<tt>smalloc()</tt> and related functions is used to add filename and line |
298 |
number parameters only when memory checking is enabled; if so, the actual |
299 |
functions receive an extra two parameters, <tt>const char *<i>file</i></tt> |
300 |
and <tt>int <i>line</i></tt>, which are passed to the corresponding |
301 |
allocation function (<tt>MCmalloc()</tt>, etc.). Macros are used in |
302 |
<tt>memory.h</tt> to pass the current file and line (<tt>__FILE__</tt>, |
303 |
<tt>__LINE__</tt>) in these parameters, so that the external interface does |
304 |
not change.</p> |
305 |
|
306 |
<p class="backlink"><a href="#top">Back to top</a></p> |
307 |
|
308 |
|
309 |
<h4 class="subsubsection-title" id="s2-4">2-2-4. List and array macros</h4> |
310 |
|
311 |
<p>The header file <tt>list-array.h</tt> defines several macros useful in |
312 |
handling lists and variable-length arrays, with macros for adding and |
313 |
removing elements, iterating over lists and arrays, and searching for an |
314 |
element with a given key (either scalar or complex).</p> |
315 |
|
316 |
<p>The list-related macros implement a doubly-linked list. The |
317 |
<tt>list</tt> parameter to each of these macros is assumed to be an lvalue |
318 |
(that is, a variable, structure field, pointer indirection, etc.) with no |
319 |
side effects of the same type as the individual list nodes; this parameter |
320 |
is modified by the insertion and removal macros. The nodes are assumed to |
321 |
be (pointers to) structures containing at least <tt>next</tt> and |
322 |
<tt>prev</tt> fields, which are used by these macros to implement the list. |
323 |
The macros are:</p> |
324 |
|
325 |
<dl> |
326 |
<dt><tt><b>LIST_INSERT</b>(<i>node</i>, <i>list</i>)</tt></dt> |
327 |
<dd>Inserts <tt><i>node</i></tt> into the beginning of |
328 |
<tt><i>list</i></tt>. Insertion is performed in constant time.</dd> |
329 |
|
330 |
<dt><tt><b>LIST_APPEND</b>(<i>node</i>, <i>list</i>)</tt></dt> |
331 |
<dd>Appends <tt><i>node</i></tt> to the end of of <tt><i>list</i></tt>. |
332 |
Insertion is performed in linear time with the length of the list.</dd> |
333 |
|
334 |
<dt><tt><b>LIST_INSERT_ORDERED</b>(<i>node</i>, <i>list</i>, <i>compare</i>, |
335 |
<i>field</i>)</tt></dt> |
336 |
<dd>Inserts <tt><i>node</i></tt> into <tt><i>list</i></tt> so that |
337 |
<tt><i>list</i></tt> maintains its order as determined by the |
338 |
function <tt><i>compare</i></tt> called on the field |
339 |
<tt><i>field</i></tt> of each node. <tt><i>field</i></tt> must be |
340 |
a field of <tt><i>node</i></tt>, and <tt><i>compare</i></tt> must |
341 |
be a function that takes two <tt><i>field</i></tt> values and |
342 |
returns -1, 0, or 1 indicating whether the first argument is |
343 |
ordered before, equal to, or after the second (<tt>strcmp()</tt>, |
344 |
for example). If an equal node is found, <tt><i>node</i></tt> is |
345 |
inserted after it. Insertion is performed in linear time with the |
346 |
length of the list, disregarding the execution time of the |
347 |
comparison function.</dd> |
348 |
|
349 |
<dt><tt><b>LIST_REMOVE</b>(<i>node</i>, <i>list</i>)</tt></dt> |
350 |
<dd>Removes <tt><i>node</i></tt> from <tt><i>list</i></tt>. |
351 |
<tt><i>node</i></tt> is assumed to already be a part of |
352 |
<tt><i>list</i></tt>. Removal is performed in constant time.</dd> |
353 |
|
354 |
<dt><tt><b>LIST_FOREACH</b>(<i>iter</i>, <i>list</i>)</tt></dt> |
355 |
<dd>Iterates over every element in <tt><i>list</i></tt>, using |
356 |
<tt><i>iter</i></tt> as the iterator. The macro has the same |
357 |
properties as a <tt>for()</tt> loop; see the implementation of |
358 |
<tt>LIST_SEARCH</tt> for an example of usage. <tt><i>iter</i></tt> |
359 |
must be an lvalue.</dd> |
360 |
|
361 |
<dt><tt><b>LIST_FOREACH_SAFE</b>(<i>iter</i>, <i>list</i>, <i>temp</i>)</tt></dt> |
362 |
<dd>Iterates over <tt><i>list</i></tt> using an extra variable |
363 |
(<tt><i>temp</i></tt>) to hold the next element, ensuring proper |
364 |
operation even when the current element is deleted. |
365 |
<tt><i>iter</i></tt> and <tt><i>temp</i></tt> must be lvalues.</dd> |
366 |
|
367 |
<dt><tt><b>LIST_SEARCH</b>(<i>list</i>, <i>field</i>, <i>target</i>, |
368 |
<i>compare</i>, <i>result</i>)</tt></dt> |
369 |
<dd>Searches <tt><i>list</i></tt> for a node with <tt><i>field</i></tt> |
370 |
equal to <tt><i>target</i></tt> (as evaluated by |
371 |
<tt><i>compare</i></tt>) and places a pointer to the node found, or |
372 |
<tt>NULL</tt> if none found, in <tt><i>result</i></tt>. |
373 |
<tt><i>field</i></tt> must be a field of the nodes in |
374 |
<tt><i>list</i></tt>; <tt><i>target</i></tt> must be an expression |
375 |
of the type of <tt><i>field</i></tt> with no side effects; |
376 |
<tt><i>result</i></tt> must be an lvalue; and |
377 |
<tt><i>compare</i></tt> must be a <tt>strcmp()</tt>-like functio |
378 |
(see <tt>LIST_INSERT_ORDERED</tt>). The search is performed in |
379 |
linear time, disregarding the execution time of the comparison |
380 |
function.</dd> |
381 |
|
382 |
<dt><tt><b>LIST_SEARCH_SCALAR</b>(<i>list</i>, <i>field</i>, <i>target</i>, |
383 |
<i>result</i>)</tt></dt> |
384 |
<dd>Searches <tt><i>list</i></tt> as <tt>LIST_SEARCH</tt> does, but for |
385 |
a scalar value. The search is performed in linear time.</dd> |
386 |
|
387 |
<dt><tt><b>LIST_SEARCH_ORDERED</b>(<i>list</i>, <i>field</i>, <i>target</i>, |
388 |
<i>compare</i>, <i>result</i>)</tt></dt> |
389 |
<dd>Searches <tt><i>list</i></tt> as <tt>LIST_SEARCH</tt> does, but for |
390 |
a list known to be ordered. The search is performed in linear |
391 |
time, disregarding the execution time of the comparison function.</dd> |
392 |
|
393 |
<dt><tt><b>LIST_SEARCH_ORDERED_SCALAR</b>(<i>list</i>, <i>field</i>, |
394 |
<i>target</i>, <i>result</i>)</tt></dt> |
395 |
<dd>Searches <tt><i>list</i></tt> as <tt>LIST_SEARCH_ORDERED</tt> does, |
396 |
but for a scalar value. The search is performed in linear time.</dd> |
397 |
</dl> |
398 |
|
399 |
<p>The variable-length array macros are similar in nature; however, since |
400 |
arrays require both a pointer and an element count, the base macros take |
401 |
two arguments designating the array, <tt><i>array</i></tt> (the pointer) |
402 |
and <tt><i>count</i></tt> (the count of elements), both of which must be |
403 |
lvalues. These macros are named <tt>ARRAY2_*</tt>, indicating that the |
404 |
array to be operated on is specified by two arguments. A shorthand form of |
405 |
each macro, named <tt>ARRAY_*</tt>, is also available; this form assumes |
406 |
that the element count is stored in a variable (or field, etc.) named with |
407 |
the name of the array suffixed with "<tt>_count</tt>". Thus, for example, |
408 |
<tt>ARRAY_EXTEND(mystruct->some_array)</tt> is exactly equivalent to |
409 |
<tt>ARRAY2_EXTEND(mystruct->some_array, mystruct->some_array_count)</tt>. |
410 |
Note that this implies that if the array pointer is itself an array |
411 |
element (with the element counts presumably stored in a separate array), |
412 |
then the two-argument forms of the macros must be used. As with lists, the |
413 |
array pointer and element count must be lvalues. The macros (only the |
414 |
one-argument forms are shown for conciseness) are as follows:</p> |
415 |
|
416 |
<dl> |
417 |
<dt><tt><b>ARRAY_EXTEND</b>(<i>array</i>)</tt></dt> |
418 |
<dd>Extends a variable-length array by one entry. Execution time is no |
419 |
greater than linear with the length of the array (depending on |
420 |
whether <tt>realloc()</tt> has to move the array data).</dd> |
421 |
|
422 |
<dt><tt><b>ARRAY_INSERT</b>(<i>array</i>, <i>index</i>)</tt></dt> |
423 |
<dd>Inserts a slot at position <tt><i>index</i></tt> in a |
424 |
variable-length array. Execution time is linear with the length of |
425 |
the array.</dd> |
426 |
|
427 |
<dt><tt><b>ARRAY_REMOVE</b>(<i>array</i>, <i>index</i>)</tt></dt> |
428 |
<dd>Deletes entry number <tt><i>index</i></tt> from a variable-length |
429 |
array. Execution time is linear with the length of the array.</dd> |
430 |
|
431 |
<dt><tt><b>ARRAY_FOREACH</b>(<i>array</i>, <i>iter</i>)</tt></dt> |
432 |
<dd>Iterates over every element in a variable-length array.</dd> |
433 |
|
434 |
<dt><tt><b>ARRAY_SEARCH</b>(<i>array</i>, <i>field</i>, <i>target</i>, |
435 |
<i>compare</i>, <i>result</i>)</tt></dt> |
436 |
<dd>Searches a variable-length array for a value. Operates like |
437 |
<tt>LIST_SEARCH</tt>. <tt><i>result</i></tt> must be an integer |
438 |
lvalue. If nothing is found, <tt><i>result</i></tt> will be set |
439 |
equal to the array's element count (<tt><i>array</i>_count</tt>). |
440 |
The search is performed in linear time, disregarding the execution |
441 |
time of the comparison function.</dd> |
442 |
|
443 |
<dt><tt><b>ARRAY_SEARCH_PLAIN</b>(<i>array</i>, <i>target</i>, |
444 |
<i>compare</i>, <i>result</i>)</tt></dt> |
445 |
<dd>Searches a variable-length array for a value, when the array |
446 |
elements do not have fields. The search is performed in linear |
447 |
time, disregarding the execution time of the comparison function.</dd> |
448 |
|
449 |
<dt><tt><b>ARRAY_SEARCH_SCALAR</b>(<i>array</i>, <i>field</i>, <i>target</i>, |
450 |
<i>result</i>)</tt></dt> |
451 |
<dd>Searches a variable-length array for a scalar value. The search is |
452 |
performed in linear time.</dd> |
453 |
|
454 |
<dt><tt><b>ARRAY_SEARCH_PLAIN_SCALAR</b>(<i>array</i>, <i>target</i>, |
455 |
<i>result</i>)</tt></dt> |
456 |
<dd>Searches a variable-length array for a scalar value, when the array |
457 |
elements do not have fields. The search is performed in linear |
458 |
time.</dd> |
459 |
</dl> |
460 |
|
461 |
<p class="backlink"><a href="#top">Back to top</a></p> |
462 |
|
463 |
|
464 |
<h4 class="subsubsection-title" id="s2-5">2-2-5. Generic hash tables</h4> |
465 |
|
466 |
<p>The header file <tt>hash.h</tt> defines macros that can be used to |
467 |
implement a simple hash table, and is used by the core code to maintain the |
468 |
network client, channel, and server lists, as well as by modules such as |
469 |
NickServ and ChanServ for in-memory databases. The file is set up so that |
470 |
a hash table can be defined with a single macro, <tt>DEFINE_HASH</tt> (for |
471 |
a string key) or <tt>DEFINE_HASH_SCALAR</tt> (for a scalar key), using |
472 |
these formats:</p> |
473 |
|
474 |
<div class="code"><b>DEFINE_HASH</b>(<i>name</i>, <i>type</i>, <i>keyfield</i>) |
475 |
<b>DEFINE_HASH_SCALAR</b>(<i>name</i>, <i>type</i>, <i>keyfield</i>, <i>keytype</i>)</div> |
476 |
|
477 |
<p>The <tt><i>name</i></tt> parameter to the macros gives the name to be |
478 |
used in the hash table's access functions (see below). <tt><i>type</i></tt> |
479 |
gives the data type of the nodes to be stored in the hash table, which must |
480 |
be a structured type containing at least <tt><i>next</i></tt> and |
481 |
<tt><i>prev</i></tt> fields (for maintaining the hash table's collision |
482 |
lists), and <tt><i>keyfield</i></tt> specifies which field of |
483 |
<tt><i>type</i></tt> contains each node's key value. For scalar keys, the |
484 |
additional parameter <tt><i>keytype</i></tt> gives the type of |
485 |
<tt><i>keyfield</i></tt> (string keys are always of type |
486 |
<tt>char *</tt>).</p> |
487 |
|
488 |
<p>These macros each define the following functions (parameters to the |
489 |
<tt>DEFINE_HASH</tt> or <tt>DEFINE_HASH_SCALAR</tt> macros are given in <tt><span style="text-decoration: underline"><i>underlined italic</i></span></tt> |
490 |
to differentiate them from the function parameters):</p> |
491 |
|
492 |
<dl> |
493 |
<dt><tt>void <b>add_<span style="text-decoration: underline"><i>name</i></span></b>(<span style="text-decoration: underline"><i>type</i></span> *<i>node</i>)</tt></dt> |
494 |
<dd>Adds the given node to the hash table.</dd> |
495 |
|
496 |
<dt><tt>void <b>del_<span style="text-decoration: underline"><i>name</i></span></b>(<span style="text-decoration: underline"><i>type</i></span> *<i>node</i>)</tt></dt> |
497 |
<dd>Removes the given node from the hash table.</dd> |
498 |
|
499 |
<dt><tt><span style="text-decoration: underline"><i>type</i></span> *<b>get_<span style="text-decoration: underline"><i>name</i></span></b>(const char *<i>key</i>)</tt> |
500 |
<br/><tt><span style="text-decoration: underline"><i>type</i></span> *<b>get_<span style="text-decoration: underline"><i>name</i></span></b>(<span style="text-decoration: underline"><i>keytype</i></span> *<i>key</i>)</tt></dt> |
501 |
<dd>If an element with the given key is stored in the hash table, |
502 |
returns a pointer to that element; otherwise, returns |
503 |
<tt>NULL</tt>. The first format is used for hashes with string |
504 |
keys, while the second is used for hashes with scalar keys.</dd> |
505 |
|
506 |
<dt><tt><span style="text-decoration: underline"><i>type</i></span> *<b>first_<span style="text-decoration: underline"><i>name</i></span></b>()</tt> |
507 |
<br/><tt><span style="text-decoration: underline"><i>type</i></span> *<b>next_<span style="text-decoration: underline"><i>name</i></span></b>()</tt></dt> |
508 |
<dd>Iterate over all elements in the hash table. For hashes with |
509 |
string keys, elements are returned in lexical order by key if |
510 |
<tt>HASH_SORTED</tt> is defined (see below). |
511 |
<tt>first_<span style="text-decoration: underline"><i>name</i></span>()</tt> |
512 |
initializes the iterator to the first element in the hash table and |
513 |
returns it; <tt>next_<span style="text-decoration: underline"><i>name</i></span>()</tt> |
514 |
returns subsequent elements, one at a time, until all elements have |
515 |
been returned, at which point it returns <tt>NULL</tt> until |
516 |
<tt>first_<span style="text-decoration: underline"><i>name</i></span>()</tt> |
517 |
is called again. If there are no elements in the hash table, |
518 |
<tt>first_<span style="text-decoration: underline"><i>name</i></span>()</tt> |
519 |
will return <tt>NULL</tt> (as will <tt>next_<span style="text-decoration: underline"><i>name</i></span>()</tt>). |
520 |
It is safe to delete elements, including the current element, while |
521 |
iterating. If an element is added while iterating, it is undefined |
522 |
whether that element will be returned by |
523 |
<tt>next_<span style="text-decoration: underline"><i>name</i></span>()</tt> |
524 |
before the end of the hash table is reached.</dd> |
525 |
</dl> |
526 |
|
527 |
<p>The following preprocessor macros can be defined to modify the behavior |
528 |
of the hash table functions. Except as otherwise noted, these macros take |
529 |
effect when the <tt>DEFINE_HASH</tt> and <tt>DEFINE_HASH_SCALAR</tt> macros |
530 |
are invoked.</p> |
531 |
|
532 |
<dl> |
533 |
<dt><tt><b>EXPIRE_CHECK</b>(<i>node</i>)</tt></dt> |
534 |
<dd>Returns a boolean value (zero if false, nonzero if true) indicating |
535 |
whether the given node has expired. If the macro evaluates to a |
536 |
true (nonzero) value, the <tt>get_<span style="text-decoration: underline"><i>name</i></span>()</tt>, |
537 |
<tt>first_<span style="text-decoration: underline"><i>name</i></span>()</tt>, and <tt>next_<span style="text-decoration: underline"><i>name</i></span>()</tt> |
538 |
macros will ignore the corresponding node when processing. (This |
539 |
is used, for example, by NickServ and ChanServ to automatically |
540 |
delete nicknames and channels which have expired; in these cases, |
541 |
<tt>EXPIRE_CHECK</tt> is set to a function which deletes the record |
542 |
and returns nonzero if the record has expired.) Defaults to 0, |
543 |
<i>i.e.</i>, no expiration.</dd> |
544 |
|
545 |
<dt><tt><b>HASH_STATIC</b></tt></dt> |
546 |
<dd>Controls whether the hash table functions are defined as static or |
547 |
global functions. This macro is prefixed directly to the function |
548 |
definitions, so it should be defined to either <tt>static</tt> or |
549 |
an empty value (not an empty string). Defaults to nothing, making |
550 |
the functions globally visible.</dd> |
551 |
|
552 |
<dt><tt><b>HASHFUNC</b>(<i>key</i>)</tt></dt> |
553 |
<dd>Hashes the given key to a value used as an index into the hash |
554 |
table. Defaults to <tt>DEFAULT_HASHFUNC(<i>key</i>)</tt>, defined |
555 |
by <tt>hash.h</tt>.</dd> |
556 |
|
557 |
<dt><tt><b>HASHSIZE</b></tt></dt> |
558 |
<dd>Sets the size of the hash table. Should be set to the range of |
559 |
values returned by <tt>HASHFUNC()</tt>. Defaults to |
560 |
<tt>DEFAULT_HASHSIZE</tt>, defined by <tt>hash.h</tt>.</dd> |
561 |
|
562 |
<dt><tt><b>HASH_SORTED</b></tt></dt> |
563 |
<dd>Controls whether the |
564 |
<tt>first_<span style="text-decoration: underline"><i>name</i></span>()</tt> and <tt>next_<span style="text-decoration: underline"><i>name</i></span>()</tt> |
565 |
functions return elements in lexical order, as described above; if |
566 |
defined to a nonzero value, lexical sorting for hash tables with |
567 |
string keys is enabled. This macro affects the |
568 |
<tt>DEFAULT_HASHFUNC()</tt> and <tt>DEFAULT_HASHSIZE</tt> macros, |
569 |
and must be defined before <tt>hash.h</tt> is included. |
570 |
Ordinarily, this is set in <tt>config.h</tt> by the |
571 |
<tt>-sorted-lists</tt> option to the <tt>configure</tt> script (see |
572 |
<a href="10.html#s2">section 10-2</a>).</dd> |
573 |
</dl> |
574 |
|
575 |
<p>Internally, the hash table itself is stored in an array defined as |
576 |
<tt><span style="text-decoration: underline"><i>type</i></span> *hashtable_<span style="text-decoration: underline"><i>name</i></span>[HASHSIZE]</tt>, with |
577 |
each element pointing to list of elements that hash to the value of the |
578 |
array index. This array is defined by the <tt>DEFINE_HASHTABLE</tt> macro, |
579 |
invoked via <tt>DEFINE_HASH</tt> or <tt>DEFINE_HASH_SCALAR</tt>. The |
580 |
<tt>add</tt>, <tt>del</tt>, <tt>get</tt>, and <tt>first</tt>/<tt>last</tt> |
581 |
functions are likewise defined by the <tt>DEFINE_HASH_ADD</tt> (or |
582 |
<tt>DEFINE_HASH_ADD_SCALAR</tt>), <tt>DEFINE_HASH_DEL</tt>, |
583 |
<tt>DEFINE_HASH_GET</tt> (or <tt>DEFINE_HASH_GET_SCALAR</tt>), and |
584 |
<tt>DEFINE_HASH_ITER</tt>; the iterator functions |
585 |
(<tt>first</tt>/<tt>next</tt>) are defined first, so that the <tt>del</tt> |
586 |
function can advance the iterator if the element pointed to by the iterator |
587 |
is removed.</p> |
588 |
|
589 |
<p>The <tt>add</tt>, <tt>del</tt>, and <tt>get</tt> functions are fairly |
590 |
straightforward, adding to, removing from, or searching the appropriate |
591 |
list as given by the hash value of the relevant element's key. The |
592 |
<tt>first</tt> and <tt>next</tt> functions are implemented in terms of a |
593 |
common iterator subfunction, <tt>_next_<span style="text-decoration: underline"><i>name</i></span>()</tt>, which |
594 |
advances the iterator (stored as a hash value in |
595 |
<tt>hashpos_<span style="text-decoration: underline"><i>name</i></span></tt> and a pointer within that hash value's |
596 |
list in <tt>hashiter_<span style="text-decoration: underline"><i>name</i></span></tt>) to the next element in the |
597 |
hash, leaving the pointer to that element in |
598 |
<tt>hashiter_<span style="text-decoration: underline"><i>name</i></span></tt>. The <tt>first</tt> function |
599 |
initializes the iterator's hash value to -1 and pointer to <tt>NULL</tt> |
600 |
(a <tt>NULL</tt> pointer triggers the iterator to advance to the next hash |
601 |
value), calls the iterator function once to load the first element into the |
602 |
iterator, then returns the return value of the <tt>next</tt> function. The |
603 |
<tt>next</tt> function saves the current pointer value of the iterator, |
604 |
advances the iterator, then returns the saved pointer value.</p> |
605 |
|
606 |
<p>The default hash function works only for string keys, and varies |
607 |
depending on whether <tt>HASH_SORTED</tt> is set. If it is, the hash |
608 |
function uses an internal lookup table (<tt>__hashlookup[]</tt>) to convert |
609 |
the first two characters of the key to 5-bit values and concatenates those |
610 |
to form a 10-bit value, with the first character's hash value in the upper |
611 |
five bits. The lookup table uses values that increase from 0 to 31 in |
612 |
lexical order, as modified by the RFC 1459 case-treatment rules; since the |
613 |
string-key <tt>add</tt> function keeps the hash table lists in order, this |
614 |
ensures that the iterator returns all elements in lexical order. The hash |
615 |
table size in this case is 1024, the range of the 10-bit hash value. If |
616 |
<tt>HASH_SORTED</tt> is not set, the function instead uses a hash table of |
617 |
65537 (2<sup>16</sup>+1) entries, and computes a hash value over all |
618 |
characters of the key string using an internal lookup table |
619 |
(<tt>__hashlookup_unsorted[]</tt>) based on the <tt>irc_lowertable[]</tt> |
620 |
array in <tt>misc.c</tt> (the same table used by the <tt>irc_tolower()</tt> |
621 |
function, as described in <a href="#s2-6">section 2-2-6</a>). This |
622 |
provides more balanced usage of hash table entries, but loses the ability |
623 |
to iterate through the elements in lexical order.</p> |
624 |
|
625 |
<p class="backlink"><a href="#top">Back to top</a></p> |
626 |
|
627 |
|
628 |
<h4 class="subsubsection-title" id="s2-6">2-2-6. Other utility functions</h4> |
629 |
|
630 |
<p>The remainder of the utility functions are defined in <tt>misc.c</tt>, |
631 |
and can be broken down into several groups:</p> |
632 |
|
633 |
<p><b>String functions</b></p> |
634 |
|
635 |
<dl> |
636 |
<dt><tt>unsigned char <b>irc_tolower</b>(char <i>c</i>)</tt></dt> |
637 |
<dd>Returns the lower-case version of the given character, like |
638 |
<tt>tolower()</tt>, but follows IRC protocol rules; unless |
639 |
modified by the protocol module, the three characters |
640 |
<tt>[ \ ]</tt> are translated to <tt>{ | }</tt>, |
641 |
as required by RFC 1459.</dd> |
642 |
|
643 |
<dt><tt>int <b>irc_stricmp</b>(const char *<i>s1</i>, const char *<i>s2</i>)</tt> |
644 |
<br/><tt>int <b>irc_strnicmp</b>(const char *<i>s1</i>, const char *<i>s2</i>, int <i>max</i>)</tt></dt> |
645 |
<dd>Versions of <tt>stricmp()</tt> and <tt>strnicmp()</tt> that use IRC |
646 |
protocol rules for upper/lower case conversion.</dd> |
647 |
|
648 |
<dt><tt>char *<b>strscpy</b>(char *<i>d</i>, const char *<i>s</i>, size_t <i>len</i>)</tt></dt> |
649 |
<dd>Copies a string safely (the "<tt><b>s</b></tt>" in |
650 |
<tt>str<b>s</b>cpy</tt>) into a buffer. Similar to |
651 |
<tt>strncpy()</tt>, except that the string is always |
652 |
null-terminated (so that at most <tt><i>len</i>-1</tt> characters |
653 |
of <tt><i>s</i></tt> are copied to <tt><i>d</i></tt>), and if |
654 |
<tt><i>s</i></tt> is shorter than <tt><i>len</i>-1</tt> characters, |
655 |
<tt><i>d</i></tt> is not padded with nulls. Returns |
656 |
<tt><i>d</i></tt>.</dd> |
657 |
|
658 |
<dt><tt>char *<b>strbcpy</b>(char *<i>d</i>, const char *<i>s</i>)</tt></dt> |
659 |
<dd>A shortcut macro for using <tt>strscpy()</tt> with a buffer |
660 |
declared as a character array (<tt>char <i>buffer</i>[<i>N</i>]</tt>), |
661 |
intended to reduce the potential for buffer overflows due to size |
662 |
mismatches. Equivalent to <tt>strscpy(<i>d</i>, <i>s</i>, |
663 |
sizeof(<i>d</i>))</tt>.</dd> |
664 |
|
665 |
<dt><tt>char *<b>strmove</b>(char *<i>d</i>, const char *<i>s</i>)</tt></dt> |
666 |
<dd>A version of <tt>strcpy()</tt> that can handle overlapping memory |
667 |
regions (for example, deleting characters from the beginning of a |
668 |
string). Returns <tt><i>d</i></tt>.</dd> |
669 |
|
670 |
<dt><tt>char *<b>stristr</b>(const char *<i>s1</i>, const char *<i>s2</i>)</tt></dt> |
671 |
<dd>A case-insensitive version of <tt>strstr()</tt>. Searches |
672 |
case-insensitively for <tt><i>s2</i></tt> inside <tt><i>s1</i></tt>, |
673 |
returning the first match found or <tt>NULL</tt> if no match is |
674 |
found.</dd> |
675 |
|
676 |
<dt><tt>char *<b>strupper</b>(char *<i>s</i>)</tt></dt> |
677 |
<dd>Converts the given string to upper case. Returns <tt><i>s</i></tt>.</dd> |
678 |
|
679 |
<dt><tt>char *<b>strlower</b>(char *<i>s</i>)</tt></dt> |
680 |
<dd>Converts the given string to lower case. Returns <tt><i>s</i></tt>.</dd> |
681 |
|
682 |
<dt><tt>char *<b>strnrepl</b>(char *<i>s</i>, int32 <i>size</i>, const char *<i>old</i>, const char *<i>new</i>)</tt></dt> |
683 |
<dd>Replaces all occurrences of <tt><i>old</i></tt> with |
684 |
<tt><i>new</i></tt> within <tt><i>s</i></tt>. Stops replacing if |
685 |
the result would exceed <tt><i>size</i>-1</tt> bytes. Returns |
686 |
<tt><i>s</i></tt>.</dd> |
687 |
|
688 |
<dt><tt>char *<b>strtok_remaining</b>()</tt></dt> |
689 |
<dd>Returns any remaining text in the string currently being processed |
690 |
by <tt>strtok()</tt>, like <tt>strtok(NULL,"")</tt>, with any |
691 |
leading or trailing whitespace stripped.</dd> |
692 |
|
693 |
<dt><tt>char *<b>merge_args</b>(int <i>argc</i>, char **<i>argv</i>)</tt></dt> |
694 |
<dd>Joins the arguments in the given argument array with spaces, and |
695 |
returns the result in a static buffer.</dd> |
696 |
|
697 |
<dt><tt>int <b>match_wild</b>(const char *<i>pattern</i>, const char *<i>str</i>)</tt> |
698 |
<br/><tt>int <b>match_wild_nocase</b>(const char *<i>pattern</i>, const char *<i>str</i>)</tt></dt> |
699 |
<dd>Returns whether the given string <tt><i>str</i></tt> matches the |
700 |
wildcard <tt><i>pattern</i></tt> (case-sensitively or |
701 |
case-insensitively, respectively). The <tt>*</tt> (match zero or |
702 |
more characters) and <tt>?</tt> (match one character) wildcards are |
703 |
recognized.</dd> |
704 |
|
705 |
<dt><tt>int <b>valid_nick</b>(const char *<i>str</i>)</tt> |
706 |
<br/><tt>int <b>valid_chan</b>(const char *<i>str</i>)</tt> |
707 |
<br/><tt>int <b>valid_domain</b>(const char *<i>str</i>)</tt> |
708 |
<br/><tt>int <b>valid_email</b>(const char *<i>str</i>)</tt> |
709 |
<br/><tt>int <b>valid_url</b>(const char *<i>str</i>)</tt></dt> |
710 |
<dd>Checks whether the given string is a valid nickname, channel name, |
711 |
domain name, E-mail address, or URL, respectively. Nickname and |
712 |
channel checking behavior default to the behavior defined by the |
713 |
reference IRC server implementation (note that this differs |
714 |
slightly from RFC 1459 for nicknames; the reference implementation |
715 |
is treated as canonical), but may be modified by protocol modules.</dd> |
716 |
<dt><tt>int <b>rejected_email</b>(const char *<i>email</i>)</tt></dt> |
717 |
<dd>Checks whether the given E-mail address matches any address masks |
718 |
given with the <tt>RejectEmail</tt> configuration directive.</dd> |
719 |
</dl> |
720 |
|
721 |
<p><b>Time-related functions</b></p> |
722 |
|
723 |
<dl> |
724 |
<dt><tt>uint32 <b>time_msec</b>()</tt></dt> |
725 |
<dd>Returns the current time to millisecond resolution. The epoch is |
726 |
arbitrary, so returned values can only be used to measure time |
727 |
differences.</dd> |
728 |
|
729 |
<dt><tt>time_t <b>strtotime</b>(const char *<i>str</i>, char **<i>endptr</i>)</tt></dt> |
730 |
<dd>Converts a string to a <tt>time_t</tt> value, assuming base 10, and |
731 |
sets <tt>*<i>endptr</i></tt> to the first character after the |
732 |
parsed time value, as for <tt>strtol()</tt> and similar functions. |
733 |
Sets <tt>errno</tt> to <tt>ERANGE</tt> if the parsed value cannot |
734 |
be represented in a <tt>time_t</tt>.</dd> |
735 |
|
736 |
<dt><tt>int <b>dotime</b>(const char *s)</tt></dt> |
737 |
<dd>Returns the number of seconds represented by the given time string, |
738 |
which is an integer followed by a unit specifier: "<tt>s</tt>" for |
739 |
seconds, "<tt>m</tt>" for minutes, "<tt>h</tt>" for hours, or |
740 |
"<tt>d</tt>" for days. Multiple time strings can be concatenated, |
741 |
such as "<tt>1h30m</tt>". Returns -1 if the string is not a valid |
742 |
time string.</dd> |
743 |
</dl> |
744 |
|
745 |
<p><b>IP address-related functions</b></p> |
746 |
|
747 |
<dl> |
748 |
<dt><tt>uint8 *<b>pack_ip</b>(const char *<i>ipaddr</i>)</tt></dt> |
749 |
<dd>Converts an IPv4 address string into a 4-byte binary address, and |
750 |
returns a pointer to the packed address (stored in a static |
751 |
buffer), or <tt>NULL</tt> if the given string does not represent a |
752 |
valid IPv4 address.</dd> |
753 |
|
754 |
<dt><tt>char *<b>unpack_ip</b>(const uint8 *<i>ip</i>)</tt></dt> |
755 |
<dd>Converts a packed IPv4 address into an address string, and returns |
756 |
a pointer to that string (stored in a static buffer).</dd> |
757 |
|
758 |
<dt><tt>uint8 *<b>pack_ip6</b>(const char *<i>ipaddr</i>)</tt> |
759 |
<br/><tt>char *<b>unpack_ip6</b>(const uint8 *<i>ip</i>)</tt></dt> |
760 |
<dd>IPv6 versions of <tt>pack_ip()</tt> and <tt>unpack_ip()</tt>.</dd> |
761 |
</dl> |
762 |
|
763 |
<p><b>Base64 encoding and decoding</b></p> |
764 |
|
765 |
<dl> |
766 |
<dt><tt>int <b>encode_base64</b>(const void *<i>in</i>, int <i>insize</i>, char *<i>out</i>, int <i>outsize</i>)</tt></dt> |
767 |
<dd>Encodes the buffer <tt><i>in</i></tt> of size <tt><i>insize</i></tt> |
768 |
bytes into the buffer <tt><i>out</i></tt> as a base64 string, |
769 |
truncating the result at <tt><i>outsize</i>-1</tt> bytes and |
770 |
appending a null terminator. Returns the number of bytes needed to |
771 |
encode the entire input buffer. The required output buffer size |
772 |
can be determined with <tt>encode_base64(<i>in</i>, <i>insize</i>, |
773 |
NULL, 0)</tt>.</dd> |
774 |
|
775 |
<dt><tt>int <b>decode_base64</b>(const char *<i>in</i>, void *<i>out</i>, int <i>outsize</i>)</tt></dt> |
776 |
<dd>Decodes the base64 string <tt><i>in</i></tt> into the buffer |
777 |
<tt><i>out</i></tt> of size <tt><i>outsize</i></tt>, truncating the |
778 |
output if necessary. Returns the number of bytes needed to store |
779 |
the entire decoded output. The required output buffer size can be |
780 |
determined with <tt>decode_base64(<i>in</i>, NULL, 0)</tt>.</dd> |
781 |
</dl> |
782 |
|
783 |
<p><b>Other functions</b></p> |
784 |
|
785 |
<dl> |
786 |
<dt><tt>int <b>process_numlist</b>(const char *<i>numstr</i>, int *<i>count_ret</i>, range_callback_t <i>callback</i>, ...)</tt></dt> |
787 |
<dd>Processes a number list of the form |
788 |
"<tt><i>n1</i>[-<i>n2</i>][,<i>n3</i>[-<i>n4</i>]...]</tt>", |
789 |
calling the given callback function once for each number contained |
790 |
in the list. Returns the sum of all values returned from the |
791 |
callback function, and stores the number of times the callback |
792 |
function was called in <tt><i>count_ret</i></tt> if it is not |
793 |
<tt>NULL</tt>. If the callback routine returns -1, |
794 |
<tt>process_numlist()</tt> aborts processing and returns |
795 |
immediately (the -1 is not included in the sum of the callback |
796 |
return values). The list is sorted so that the values passed to the |
797 |
callback function for a particular list are in strictly increasing |
798 |
order, with no duplicates. Values outside the range 0 through |
799 |
65536 are discarded to avoid excessive consumption of resources. |
800 |
The callback function type is defined in <tt>extern.h</tt> as: |
801 |
<div class="code">int (*<b>range_callback_t</b>)(int <i>num</i>, va_list <i>args</i>)</div> |
802 |
where <tt><i>num</i></tt> is the number currently being processed |
803 |
and <tt><i>args</i></tt> are the additional arguments passed to |
804 |
<tt>process_numlist()</tt>.</dd> |
805 |
|
806 |
<dt><tt>long <b>atolsafe</b>(const char *<i>s</i>, long <i>min</i>, long <i>max</i>)</tt></dt> |
807 |
<dd>Converts a string in base 10 to a <tt>long</tt> value, ensuring |
808 |
that the string contains no invalid characters and that it is |
809 |
within the inclusive range <tt><i>min</i></tt> through |
810 |
<tt><i>max</i></tt>. On error, sets <tt>errno</tt> to |
811 |
<tt>EINVAL</tt> if the string contains invalid characters or |
812 |
<tt>ERANGE</tt> if the value is outside of the specified range, and |
813 |
returns <tt><i>min</i>-1</tt>.</dd> |
814 |
</dl> |
815 |
|
816 |
<p class="backlink"><a href="#top">Back to top</a></p> |
817 |
|
818 |
<!------------------------------------------------------------------------> |
819 |
<hr/> |
820 |
|
821 |
<h3 class="subsection-title" id="s3">2-3. Program startup and termination</h3> |
822 |
|
823 |
<p>As with most C programs, Services starts execution at the <tt>main()</tt> |
824 |
routine, in <tt>main.c</tt>. This routine performs program initialization |
825 |
(see <a href="#s3-1">section 2-3-1</a>), executes the main program loop |
826 |
(see <a href="#s3-3">section 2-3-3</a>), and performs cleanup when the |
827 |
main loop terminates (see <a href="#s3-5">section 2-3-5</a>). |
828 |
<tt>main()</tt> takes three parameters from the operating system: |
829 |
<tt><i>ac</i></tt>, the command-line argument count (called <tt>argc</tt> |
830 |
by some programs); <tt><i>av</i></tt>, the command-line argument vector |
831 |
(called <tt>argv</tt> by some programs); and <tt>envp</tt>, the environment |
832 |
pointer.</p> |
833 |
|
834 |
<p class="backlink"><a href="#top">Back to top</a></p> |
835 |
|
836 |
|
837 |
<h4 class="subsubsection-title" id="s3-1">2-3-1. Initialization</h4> |
838 |
|
839 |
<p>The bulk of initialization is performed by the <tt>init()</tt> routine, |
840 |
located in <tt>init.c</tt>. This routine:</p> |
841 |
|
842 |
<ul> |
843 |
<li class="spaced">Initializes the logging subsystem, by calling |
844 |
<tt>open_memory_log()</tt> (the log file itself is not opened at this time; |
845 |
any log messages are saved in a memory buffer until a log file is |
846 |
available).</li> |
847 |
|
848 |
<li class="spaced">Initializes the memory subsystem (see |
849 |
<a href="#s2-3">section 2-2-3</a>).</li> |
850 |
|
851 |
<li class="spaced">Parses basic command-line options by calling |
852 |
<tt>parse_options(ac,av,0)</tt>, exiting if an error occurs.</li> |
853 |
|
854 |
<li class="spaced">Changes the current directory to the Services data |
855 |
directory, as specified by the <tt>-dir</tt> command-line option or set by |
856 |
the <tt>configure</tt> script.</li> |
857 |
|
858 |
<li class="spaced">Reads the primary configuration file, |
859 |
<tt>ircservices.conf</tt> in the data directory (see |
860 |
<a href="#s3-2">section 2-3-2</a>).</li> |
861 |
|
862 |
<li class="spaced">Re-parses basic command-line options, to override |
863 |
configuration file settings.</li> |
864 |
|
865 |
<li class="spaced">Opens the log file, as specified in the configuration |
866 |
file or by the <tt>-log</tt> command-line option, writing a warning to |
867 |
standard error if the file cannot be opened.</li> |
868 |
|
869 |
<li class="spaced">Writes a greeting message to the log file.</li> |
870 |
|
871 |
<li class="spaced">Records the current time in the <tt>start_time</tt> |
872 |
variable (this variable is used in responding to IRC <tt>INFO</tt> and |
873 |
<tt>STATS</tt> requests).</li> |
874 |
|
875 |
<li class="spaced">If Services was started in read-only mode (with the |
876 |
<tt>-readonly</tt> option), closes the log file again.</li> |
877 |
|
878 |
<li class="spaced">If configured to (with <tt>configure -dumpcore</tt>), |
879 |
attempts to remove any core dump size limits to ensure that a core dump is |
880 |
written when a segmentation fault occurs.</li> |
881 |
|
882 |
<li class="spaced">Initializes the system pseudo-random number generator, |
883 |
using a seed value based on the current time and the process IDs of the |
884 |
Services process and its parent process.</li> |
885 |
|
886 |
<li class="spaced">Initializes the socket subsystem (see |
887 |
<a href="3.html">section 3</a>).</li> |
888 |
|
889 |
<li class="spaced">Initializes the module subsystem (see |
890 |
<a href="4.html">section 4</a>).</li> |
891 |
|
892 |
<li class="spaced">Registers callbacks used in <tt>init.c</tt> and |
893 |
<tt>main.c</tt> (callbacks are described in <a href="4.html#s5">section |
894 |
4-5</a>): |
895 |
<ul> |
896 |
<li><tt>command line</tt></li> |
897 |
<li><tt>introduce_user</tt></li> |
898 |
<li><tt>connect</tt></li> |
899 |
<li><tt>save data complete</tt></li> |
900 |
</ul></li> |
901 |
|
902 |
<li class="spaced">Calls other subsystems' initialization routines.</li> |
903 |
|
904 |
<li class="spaced">Initializes multilingual support (see |
905 |
<a href="#s8">section 2-8</a>), and loads any external language files |
906 |
specified by the <tt>LoadLanguageText</tt> configuration directive, in |
907 |
the order they were encountered in the configuration file.</li> |
908 |
|
909 |
<li class="spaced">Loads all modules specified by the <tt>LoadModule</tt> |
910 |
configuration directive, in the order they were encountered in the |
911 |
configuration file.</li> |
912 |
|
913 |
<li class="spaced">Checks for unrecognized command-line options and passes |
914 |
them to modules via the "<tt>command line</tt>" callback.</li> |
915 |
|
916 |
<li class="spaced">Checks that a protocol module has been loaded, writing |
917 |
an error message to standard error and exiting if not.</li> |
918 |
|
919 |
<li class="spaced">If the <tt>-nofork</tt> option was not specified, writes |
920 |
a message to standard error indicating that initialization succeeded.</li> |
921 |
|
922 |
<li class="spaced">If the <tt>-nofork</tt> option was not specified, calls |
923 |
the system's <tt>fork()</tt> function to spawn a new process; if successful, |
924 |
the parent process immediately exits with code 0 (success), while execution |
925 |
continues in the child process. <i>Note that from here on down, no fatal |
926 |
errors can occur; any unexpected conditions are reported to the log |
927 |
file.</i></li> |
928 |
|
929 |
<li class="spaced">Writes the process ID of the Services process to the |
930 |
file specified in the <tt>PIDFilename</tt> configuration directive.</li> |
931 |
|
932 |
<li class="spaced">Initializes signal handling (see <a href="#s3-4">section |
933 |
2-3-4</a>).</li> |
934 |
|
935 |
<li class="spaced">Creates a socket for communication with the remote |
936 |
server, and initiates the server connection (the connection is performed |
937 |
asynchronously, with the <tt>connect_callback()</tt> and |
938 |
<tt>disconnect_callback()</tt> functions in <tt>main.c</tt> handling |
939 |
connection success and failure, respectively).</li> |
940 |
|
941 |
</ul> |
942 |
|
943 |
<p>Once <tt>init()</tt> has successfully completed its work, <tt>main()</tt> |
944 |
initializes three timestamp variables used as second-resolution timers: |
945 |
<tt>last_send</tt> (defined in <tt>send.c</tt>), indicating when data was |
946 |
last sent to the server; <tt>last_update</tt>, indicating when the |
947 |
databases were last written to persistent storage; and <tt>last_check</tt>, |
948 |
indicating when timed events (see <a href="#s7">section 2-7</a>) were last |
949 |
checked for timeouts.</p> |
950 |
|
951 |
<p>Finally, <tt>main()</tt> initializes an error trap via |
952 |
<tt>sigsetjmp()</tt>, to which signal handlers can return (via |
953 |
<tt>siglongjmp()</tt>) when a signal causing program termination is |
954 |
received. Ideally, this call would be located in the |
955 |
<tt>do_sigsetjmp()</tt> function in <tt>signals.c</tt>, along with the rest |
956 |
of the signal handling code. However, since <tt>sigsetjmp()</tt> is not |
957 |
guaranteed to work if the function that called it returns, <tt>main()</tt> |
958 |
instead invokes the <tt>DO_SIGSETJMP</tt> macro, also located in |
959 |
<tt>main.c</tt>; this macro sets up a context buffer, calls |
960 |
<tt>sigsetjmp()</tt>, then calls <tt>do_sigsetjmp()</tt> to pass the |
961 |
context buffer pointer to the signal code.</p> |
962 |
|
963 |
<p class="backlink"><a href="#top">Back to top</a></p> |
964 |
|
965 |
|
966 |
<h4 class="subsubsection-title" id="s3-2">2-3-2. Configuration files</h4> |
967 |
|
968 |
<p>Configuration files are handled by code in <tt>conffile.c</tt>. This |
969 |
file has two external interfaces: <tt>configure()</tt>, which reads in |
970 |
settings from a configuration file, and <tt>deconfigure()</tt>, which |
971 |
restores the settings to their default values. (A third exported function, |
972 |
<tt>config_error()</tt>, is available for configuration directive handlers, |
973 |
described below, to call in order to print warning or error messages.)</p> |
974 |
|
975 |
<p>In order to avoid leaving configuration variables in an inconsistent |
976 |
state if an error is found, configuration files are processed in two |
977 |
passes: first all settings are read into temporary storage, then, if no |
978 |
errors were found, the new values are assigned to the appropriate |
979 |
configuration variables. These two steps are both performed by |
980 |
<tt>configure()</tt>, with the third parameter (<tt>action</tt>) indicating |
981 |
which step is to be performed: <tt>CONFIGURE_READ</tt> to read in the |
982 |
configuration file, <tt>CONFIGURE_SET</tt> to store the new values in the |
983 |
configuration variables, or both (<tt>CONFIGURE_READ|CONFIGURE_SET</tt>) to |
984 |
perform both steps in one call. Additionally, when configuring settings |
985 |
for the first time, the original value of each configuration variable is |
986 |
saved, allowing <tt>deconfigure()</tt> to restore those values later.</p> |
987 |
|
988 |
<p>Configuration information is stored in one of two text files: |
989 |
<tt>ircservices.conf</tt> for core configuration and <tt>modules.conf</tt> |
990 |
for module configuration (these filenames cannot be changed at runtime, but |
991 |
can be changed at compilation time via the <tt>IRCSERVICES_CONF</tt> and |
992 |
<tt>MODULES_CONF</tt> constants in <tt>defs.h</tt>). The file to be used |
993 |
implied by the <tt><i>modulename</i></tt> parameter passed to |
994 |
<tt>configure()</tt>; if a non-<tt>NULL</tt> name is given, |
995 |
<tt>modules.conf</tt> is used, otherwise <tt>ircservices.conf</tt> is |
996 |
used.</p> |
997 |
|
998 |
<p>Both files use the same format: one configuration directive per line, |
999 |
with comments delimited by <tt>#</tt> (blank and comment-only lines are |
1000 |
permitted). The configuration directive and its parameters are each |
1001 |
separated by a nonzero amount of whitespace. If whitespace is needed |
1002 |
inside a string parameter, the parameter can be enclosed in double quotes; |
1003 |
in this case, double quotes must be used around the entire |
1004 |
parameter—they are treated as ordinary characters in the middle of a |
1005 |
parameter. Configuration directives are treated case-insensitively.</p> |
1006 |
|
1007 |
<p>Aside from caller-specified configuration directives, three |
1008 |
meta-directives are recognized in configuration files. The |
1009 |
<tt>IncludeFile</tt> directive allows nesting of configuration files, |
1010 |
taking a single parameter which specifies the file to insert. (Nesting |
1011 |
is internally limited to 100 levels to avoid recursion loops.) The |
1012 |
<tt>Module</tt> directive is only recognized in <tt>modules.conf</tt>, and |
1013 |
specifies the beginning of a particular module's section, with the module |
1014 |
name given as a parameter to the directive; it must be matched by an |
1015 |
<tt>EndModule</tt> directive (taking no parameters). When the |
1016 |
<tt><i>modulename</i></tt> parameter to <tt>configure()</tt> is not |
1017 |
<tt>NULL</tt>, only the configuration directives in the section matching |
1018 |
the given module name are processed.</p> |
1019 |
|
1020 |
<p>Configuration directives to be processed are specified by an array of |
1021 |
<tt>ConfigDirective</tt> structures, passed as the <tt><i>directives</i></tt> |
1022 |
parameter to <tt>configure()</tt>. This structure is defined in |
1023 |
<tt>conffile.h</tt>, and consists of a name parameter |
1024 |
(<tt>const char *<b>name</b></tt>) followed by an fixed-size array of |
1025 |
parameter substructures (the array is 8 elements long by default, which can |
1026 |
be changed via the <tt>CONFIG_MAXPARAMS</tt> constant in <tt>defs.h</tt>).</p> |
1027 |
|
1028 |
<p>The string in the <tt>name</tt> field gives the name of the directive, |
1029 |
which should consist of only alphanumeric characters, no punctuation or |
1030 |
spaces. Directives are treated case-insensitively, and if more than one |
1031 |
entry has the same name, only the first will be used. A value of |
1032 |
<tt>NULL</tt> for the <tt><i>name</i></tt> field is used to terminate the |
1033 |
array.</p> |
1034 |
|
1035 |
<p>The parameter substructure of <tt>ConfigDirective</tt> contains the |
1036 |
following fields:</p> |
1037 |
|
1038 |
<dl> |
1039 |
<dt><tt>int <b>type</b></tt></dt> |
1040 |
<dd>Specifies both the data type of the variable which holds the |
1041 |
parameter value and the format in which it is expressed in the |
1042 |
configuration file, using one of the <tt>CD_*</tt> constants |
1043 |
defined in <tt>conffile.h</tt>: |
1044 |
<ul> |
1045 |
<li><b><tt>CD_NONE</tt>:</b> No parameter present (processing of the |
1046 |
directive is terminated). This constant is not used in |
1047 |
actual parameter definitions, but as it has a value of zero, |
1048 |
any parameters not specified in the <tt>ConfigDirective</tt> |
1049 |
structure will automatically end the parameter list, so no |
1050 |
explicit fencepost is required.</li> |
1051 |
<li><b><tt>CD_INT</tt>:</b> An integer parameter. Any 32-bit |
1052 |
integer value is accepted, and the value is stored as type |
1053 |
<tt>int32</tt>.</li> |
1054 |
<li><b><tt>CD_POSINT</tt>:</b> A positive integer parameter. As |
1055 |
for <tt>CD_INT</tt>, but zero and negative values are not |
1056 |
accepted.</li> |
1057 |
<li><b><tt>CD_PORT</tt>:</b> A TCP/UDP port number. Integers from |
1058 |
1 through 65535 inclusive are accepted, and the value is |
1059 |
stored as type <tt>int32</tt>.</li> |
1060 |
<li><b><tt>CD_STRING</tt>:</b> A string parameter. A pointer to |
1061 |
the string value is stored in the <tt>char *</tt> |
1062 |
configuration variable. Strings are internally allocated |
1063 |
with <tt>malloc()</tt> and freed when necessary by |
1064 |
<tt>configure()</tt> and <tt>deconfigure()</tt>; they |
1065 |
should be treated as read-only by the caller.</li> |
1066 |
<li><b><tt>CD_TIME</tt>:</b> A time parameter, stored as type |
1067 |
<tt>time_t</tt>. The parameter can be either an integer |
1068 |
number of seconds or a string of one or more value-unit |
1069 |
pairs, where units are "<tt>d</tt>" (days), "<tt>h</tt>" |
1070 |
(hours), "<tt>m</tt>" (minutes), or "<tt>s</tt>" (seconds). |
1071 |
For example, a time of 1 hour and 30 minutes could be |
1072 |
specified as "<tt>1h30m</tt>", "<tt>90m</tt>", or |
1073 |
"<tt>5400</tt>".</li> |
1074 |
<li><b><tt>CD_TIMEMSEC</tt>:</b> A time parameter, parsed as a |
1075 |
decimal number of seconds and converted to milliseconds. |
1076 |
The value is stored as type <tt>int32</tt>.</li> |
1077 |
<li><b><tt>CD_FUNC</tt>:</b> A parameter which is handled by an |
1078 |
external function (see below).</li> |
1079 |
<li><b><tt>CD_SET</tt>:</b> A pseudo-parameter (does not use up an |
1080 |
actual parameter to the directive), which sets a variable |
1081 |
of type <tt>int</tt> to 1 if the directive is seen.</li> |
1082 |
<li><b><tt>CD_DEPRECATED</tt>:</b> A pseudo-parameter, which causes |
1083 |
a warning to be written to the log that the directive is |
1084 |
deprecated if it is encountered in a configuration file.</li> |
1085 |
</ul></dd> |
1086 |
|
1087 |
<dt><tt>int <b>flags</b></tt></dt> |
1088 |
<dd>Specifies zero or more flags for the parameter: |
1089 |
<ul> |
1090 |
<li><b><tt>CF_OPTIONAL</tt>:</b> Indicates that the parameter is |
1091 |
optional, not required. If the parameter is missing from |
1092 |
the configuration file, the variable's value is not |
1093 |
changed.</li> |
1094 |
<li><b><tt>CF_DIRREQ</tt>:</b> Indicates that the directive is |
1095 |
required; if the directive is not found when reading the |
1096 |
configuration file, an error will be generated. This flag |
1097 |
is only valid when used with the first parameter.</li> |
1098 |
<li><b><tt>CF_SAVED</tt>:</b> <i>Used internally.</i> Indicates |
1099 |
that the original value of the variable has been saved in |
1100 |
the <tt><i>prev</i></tt> field.</li> |
1101 |
<li><b><tt>CF_WASSET</tt>:</b> <i>Used internally.</i> Indicates |
1102 |
that the <tt><i>new</i></tt> field has been set.</li> |
1103 |
<li><b><tt>CF_ALLOCED</tt>:</b> <i>Used internally.</i> Indicates |
1104 |
that the current value of the string variable was allocated |
1105 |
by the configuration file parser.</li> |
1106 |
<li><b><tt>CF_ALLOCED_NEW</tt>:</b> <i>Used internally.</i> |
1107 |
Indicates that the string value in the <tt><i>new</i></tt> |
1108 |
field was allocated by the configuration file parser.</li> |
1109 |
</ul></dd> |
1110 |
|
1111 |
<dt><tt>void *<b>ptr</b></tt></dt> |
1112 |
<dd>Points to the variable into which the value read from the |
1113 |
configuration file is to be written (except for types |
1114 |
<tt>CD_FUNC</tt>, described below, and <tt>CD_DEPRECATED</tt>, |
1115 |
which does not set a value). Note that for string variables, this |
1116 |
is a pointer to the <tt>char *</tt> variable that will receive |
1117 |
the new string pointer, so the effective type is |
1118 |
<tt>char **</tt>.</dd> |
1119 |
|
1120 |
<dt><tt>CDValue <b>prev</b></tt> |
1121 |
<br/><tt>CDValue <b>new</b></tt></dt> |
1122 |
<dd>Used internally to hold the variable's original value and the new |
1123 |
value read in from the configuration file, respectively. Callers |
1124 |
should not attempt to access these fields.</dd> |
1125 |
</dl> |
1126 |
|
1127 |
<p>If the processing required for a parameter is more complex than the |
1128 |
basic types listed above, an external function can be specified to process |
1129 |
the parameter. To do this. set the parameter's type to <tt>CD_FUNC</tt>, |
1130 |
and in the <tt>ptr</tt> field, place a pointer to a handler function that |
1131 |
takes three parameters and returns an <tt>int</tt>:</p> |
1132 |
|
1133 |
<div class="code">int <i>function</i>(const char *<i>filename</i>, int <i>linenum</i>, char *<i>param</i>);</div> |
1134 |
|
1135 |
<p>The first two parameters, <tt><i>filename</i></tt> and |
1136 |
<tt><i>linenum</i></tt>, serve two purposes. One is provide the filename |
1137 |
and line number currently being processed, when reading the file; these can |
1138 |
then be passed to <tt>config_error()</tt> if a warning or error message |
1139 |
needs to be printed. The other is to indicate the action requested of the |
1140 |
function. <i>(Note: This is poor design. Ideally, the action requested |
1141 |
should be specified by a separate parameter to the function.)</i> If |
1142 |
<tt><i>filename</i></tt> is not <tt>NULL</tt>, then the function is being |
1143 |
called to process the parameter string and store any resulting values in a |
1144 |
temporary location; if it is <tt>NULL</tt>, then the function should |
1145 |
perform some other action as specified by <tt>linenum</tt>:</p> |
1146 |
|
1147 |
<ul> |
1148 |
<li><b><tt>CDFUNC_INIT</tt>:</b> Prepare for processing a new value |
1149 |
(<i>e.g.</i>, save variables' original values and clear any variables used |
1150 |
for temporary value storage).</li> |
1151 |
<li><b><tt>CDFUNC_SET</tt>:</b> Copy any temporary values to their final |
1152 |
locations.</li> |
1153 |
<li><b><tt>CDFUNC_DECONFIG</tt>:</b> Restore configuration variables' |
1154 |
original values.</li> |
1155 |
</ul> |
1156 |
|
1157 |
<p>The final parameter, <tt><i>param</i></tt>, is the parameter string read |
1158 |
from the configuration file, and may be modified or destroyed (the parser |
1159 |
will not make any further use of it).</p> |
1160 |
|
1161 |
<p>The function should return nonzero on success, zero on error. However, |
1162 |
errors are only checked for when reading/processing the parameter; the |
1163 |
<tt>CDFUNC_INIT</tt>, <tt>CDFUNC_SET</tt>, and <tt>CDFUNC_DECONFIG</tt> |
1164 |
operations are assumed to succeed.</p> |
1165 |
|
1166 |
<p><b>Configuration file processing details</b></p> |
1167 |
|
1168 |
<p>The calling pattern of <tt>configure()</tt> and <tt>deconfigure()</tt> |
1169 |
looks roughly like the following:</p> |
1170 |
|
1171 |
<div class="code">configure(..., CONFIGURE_READ) |
1172 |
-> read_config_file() |
1173 |
-> do_read_config_file() |
1174 |
[ -> do_read_config_file()... ] |
1175 |
-> parse_config_line() |
1176 |
configure(..., CONFIGURE_SET) |
1177 |
-> do_all_directives(ACTION_COPYNEW) |
1178 |
deconfigure() |
1179 |
-> do_all_directives(ACTION_RESTORESAVED)</div> |
1180 |
|
1181 |
<p><tt>configure()</tt> with the <tt>CONFIGURE_SET</tt> flag and |
1182 |
<tt>deconfigure()</tt> have basically the same function: to store a value |
1183 |
into each configuration variable. This is handled by the internal function |
1184 |
<tt>do_all_directives</tt>, which uses the <tt><i>action</i></tt> parameter |
1185 |
to select whether to copy the new value read in from the configuration file |
1186 |
(<tt>ACTION_COPYNEW</tt>) or the saved original value |
1187 |
(<tt>ACTION_RESTORESAVED</tt>).</p> |
1188 |
|
1189 |
<p><tt>configure()</tt> with the <tt>CONFIGURE_READ</tt> flag calls |
1190 |
<tt>read_config_file()</tt>, which opens the proper configuration file, |
1191 |
initializes all configuration parameters for reading, calls |
1192 |
<tt>do_read_config_file()</tt> to actually process the file, and checks |
1193 |
that all required directives were seen; the function returns nonzero on |
1194 |
success, zero if an error was detected.</p> |
1195 |
|
1196 |
<p><tt>do_read_config_file()</tt> iterates through each line of the given |
1197 |
file, calling <tt>parse_config_line()</tt> for each non-empty line (except |
1198 |
that the meta-directives <tt>IncludeFile</tt>, <tt>Module</tt>, and |
1199 |
<tt>EndModule</tt> are processed directly by <tt>do_read_config_file()</tt>). |
1200 |
<tt>parse_config_line()</tt>, in turn, splits the given line into directive |
1201 |
and parameters, locates the entry in the <tt>ConfigDirective</tt> array |
1202 |
corresponding to the directive (generating an error if none is found), and |
1203 |
processes each of the directive's parameters, returning success (nonzero) |
1204 |
or failure (zero) to <tt>do_read_config_file()</tt>.</p> |
1205 |
|
1206 |
<p class="backlink"><a href="#top">Back to top</a></p> |
1207 |
|
1208 |
|
1209 |
<h4 class="subsubsection-title" id="s3-3">2-3-3. The main loop</h4> |
1210 |
|
1211 |
<p>Once initialization has completed, Services enters the main loop. This |
1212 |
fairly simple loop performs the following functions:</p> |
1213 |
|
1214 |
<ul> |
1215 |
<li class="spaced">Saves the current databases to persistent storage, if the |
1216 |
<tt>save_data</tt> global flag has been set to a nonzero value or the time |
1217 |
specified by the <tt>UpdateTimeout</tt> configuration directive has passed |
1218 |
since the last time the databases were saved. After saving, the |
1219 |
<tt>save_data</tt> flag is cleared and the last database save time is |
1220 |
stored in <tt>last_update</tt>.</li> |
1221 |
|
1222 |
<li class="spaced">Exits the loop if the <tt>delayed_quit</tt> global flag |
1223 |
has been set to a nonzero value. (This flag is used to cause Services to |
1224 |
save its databases before exiting, and can be set by the <tt>SIGTERM</tt> |
1225 |
signal, as described below in <a href="#s3-4">section 2-3-4</a>, or by the |
1226 |
OperServ <tt>SHUTDOWN</tt> and <tt>RESTART</tt> commands, as described in |
1227 |
<a href="../4.html">section 4 of the user's manual</a>.)</li> |
1228 |
|
1229 |
<li class="spaced">Sends a <tt>PING</tt> message to the remote server if |
1230 |
the connection to the server is active and periodic pinging has been |
1231 |
enabled via the the <tt>PingFrequency</tt> configuration directive.</li> |
1232 |
|
1233 |
<li class="spaced">Checks active timers for timeout events (see |
1234 |
<a href="#s7">section 2-7</a>), if the time specified by the |
1235 |
<tt>TimeoutCheck</tt> configuration directive has passed since the last |
1236 |
such check.</li> |
1237 |
|
1238 |
<li class="spaced">Checks sockets for activity (see |
1239 |
<a href="3.html#s6">section 3-6</a>).</li> |
1240 |
|
1241 |
<li class="spaced">Flushes out all accumulated channel mode changes, if |
1242 |
channel mode merging has not been enabled by the <tt>MergeChannelModes</tt> |
1243 |
configuration directive (see <tt>set_cmode()</tt> in |
1244 |
<a href="#s6-5">section 2-6-5</a>).</li> |
1245 |
</ul> |
1246 |
|
1247 |
<p>The main loop terminates when the <tt>quitting</tt> global flag becomes |
1248 |
nonzero, and can also abort via the <tt>delayed_quit</tt> flag as described |
1249 |
above.</p> |
1250 |
|
1251 |
<p class="backlink"><a href="#top">Back to top</a></p> |
1252 |
|
1253 |
|
1254 |
<h4 class="subsubsection-title" id="s3-4">2-3-4. Signals</h4> |
1255 |
|
1256 |
<p>Services makes use of the following signals to perform certain actions:</p> |
1257 |
|
1258 |
<ul> |
1259 |
<li><b><tt>SIGTERM</tt>:</b> Causes Services to save its databases and |
1260 |
terminate, as if the OperServ <tt>SHUTDOWN</tt> command had been given.</li> |
1261 |
<li><b><tt>SIGINT</tt>, <tt>SIGQUIT</tt>:</b> Causes Services to terminate |
1262 |
immediately without saving its databases, as if the OperServ <tt>QUIT</tt> |
1263 |
command had been given.</li> |
1264 |
<li><b><tt>SIGHUP</tt>:</b> Causes Services to save its databases and |
1265 |
reread the configuration file, as if the OperServ <tt>UPDATE</tt> and |
1266 |
<tt>REHASH</tt> commands had been given. Rehashing is done via the |
1267 |
<tt>reconfigure()</tt> function provided by <tt>init.c</tt>.</li> |
1268 |
<li><b><tt>SIGUSR2</tt>:</b> Causes Services to close the log file and |
1269 |
reopen it immediately; this can be useful if the log file has been moved.</li> |
1270 |
</ul> |
1271 |
|
1272 |
<p>To catch program or system faults, the <tt>SIGSEGV</tt>, <tt>SIGBUS</tt>, |
1273 |
<tt>SIGILL</tt>, <tt>SIGTRAP</tt>, <tt>SIGFPE</tt>, and (if defined) |
1274 |
<tt>SIGIOT</tt> signals are directed to a generic termination handler |
1275 |
(<tt>weirdsig_handler()</tt>, also used for <tt>SIGINT</tt> and |
1276 |
<tt>SIGQUIT</tt>). However, if the <tt>-dumpcore</tt> option was given to |
1277 |
<tt>configure</tt>, <tt>SIGSEGV</tt> is instead left alone, causing the |
1278 |
operating system to abort the program and dump a core file if a |
1279 |
segmentation fault occurs.</p> |
1280 |
|
1281 |
<p>In addition, <tt>SIGUSR1</tt> is used by the memory subsystem to cause |
1282 |
the program to abort if an out-of-memory condition is detected by the |
1283 |
<tt>smalloc()</tt>, <tt>scalloc()</tt>, or <tt>srealloc()</tt> functions.</p> |
1284 |
|
1285 |
<p>All signals not mentioned above are set to "ignore" by the |
1286 |
<tt>init_signals()</tt> function. (However, the <tt>SIGPROF</tt> and |
1287 |
<tt>SIGCHLD</tt> signals are left alone: <tt>SIGPROF</tt> so that |
1288 |
profiling can be performed, and <tt>SIGCHLD</tt> so that any child |
1289 |
processes can be properly reaped.)</p> |
1290 |
|
1291 |
<p>The handlers for each of these signals, as well as the |
1292 |
<tt>init_signals()</tt> function which sets them up, are in |
1293 |
<tt>signals.c</tt>. This source file has two additional external |
1294 |
interfaces, <tt>enable_signals()</tt> and <tt>disable_signals()</tt>, |
1295 |
which enable and disable, respectively, processing of the <tt>SIGTERM</tt>, |
1296 |
<tt>SIGHUP</tt>, and <tt>SIGUSR2</tt> signals, to prevent any action being |
1297 |
taken when Services' internal data may be in an inconsistent state. The |
1298 |
signals are not ignored, only blocked, so if one of these signals is |
1299 |
received between a <tt>disable_signals()</tt> call and the corresponding |
1300 |
<tt>enable_signals()</tt> call, it will be processed immediately when |
1301 |
<tt>enable_signals()</tt> is called.</p> |
1302 |
|
1303 |
<p class="backlink"><a href="#top">Back to top</a></p> |
1304 |
|
1305 |
|
1306 |
<h4 class="subsubsection-title" id="s3-5">2-3-5. Termination</h4> |
1307 |
|
1308 |
<p>Once the main loop terminates, Services calls the <tt>cleanup()</tt> |
1309 |
function (defined in <tt>init.c</tt>), which performs the following |
1310 |
actions—more or less the reverse of <tt>init()</tt>:</p> |
1311 |
|
1312 |
<ul> |
1313 |
<li class="spaced">Writes a log entry with the quit message (stored in |
1314 |
the global variable <tt>quitmsg</tt>); a default message is written if none |
1315 |
has been provided, but any code that causes Services to exit should provide |
1316 |
an appropriate quit message.</li> |
1317 |
|
1318 |
<li class="spaced">Flushes out any unsent mode changes.</li> |
1319 |
|
1320 |
<li class="spaced">Unloads all modules.</li> |
1321 |
|
1322 |
<li class="spaced">If the remote server socket has been opened, sends an |
1323 |
<tt>SQUIT</tt> to the remote server (if connected) and closes the socket.</li> |
1324 |
|
1325 |
<li class="spaced">Calls <tt>lang_cleanup()</tt> to free all memory used |
1326 |
by multilingual support.</li> |
1327 |
|
1328 |
<li class="spaced">Calls other subsystems' cleanup routines.</li> |
1329 |
|
1330 |
<li class="spaced">Unregisters callbacks registered by <tt>init()</tt>.</li> |
1331 |
|
1332 |
<li class="spaced">Calls the module subsystem's cleanup routine.</li> |
1333 |
|
1334 |
<li class="spaced">Calls <tt>deconfigure()</tt> to reset all configuration |
1335 |
variables to their original values and free any strings allocated by the |
1336 |
configuration file parser. However, the value of <tt>LogFilename</tt> is |
1337 |
preserved in a static buffer, in case the log needs to be reopened (as can |
1338 |
happen when restarting; see below).</li> |
1339 |
|
1340 |
<li class="spaced">Closes the log file.</li> |
1341 |
</ul> |
1342 |
|
1343 |
<p>Finally, Services terminates by returning from <tt>main()</tt>; however, |
1344 |
if a restart has been requested (by setting the <tt>restart</tt> global |
1345 |
flag to a nonzero value), Services first attempts to re-execute itself via |
1346 |
the <tt>execve</tt> system call. If this fails, the log file is reopened |
1347 |
and an error message is written (regardless of whether read-only mode was |
1348 |
enabled or not).</p> |
1349 |
|
1350 |
|
1351 |
<p class="backlink"><a href="#top">Back to top</a></p> |
1352 |
|
1353 |
<!------------------------------------------------------------------------> |
1354 |
<hr/> |
1355 |
|
1356 |
<h3 class="subsection-title" id="s4">2-4. Logging</h3> |
1357 |
|
1358 |
<p>Logging functionality is provided by the functions in <tt>log.c</tt> |
1359 |
(and the corresponding <tt>log.h</tt> header file, included by |
1360 |
<tt>services.h</tt>).</p> |
1361 |
|
1362 |
<p>The logging subsystem does not include explicit initialization or |
1363 |
cleanup routines; all necessary processing is carried out in the |
1364 |
<tt>open_log()</tt> and <tt>close_log()</tt> functions, which are (as the |
1365 |
names imply) used to open and close the log file; <tt>open_log()</tt> in |
1366 |
particular relies on the <tt>LogFilename</tt> global variable (which |
1367 |
reflects the same-named configuration directive) for the name of the file |
1368 |
to open (see below). There is also an <tt>open_memory_log()</tt> function, |
1369 |
which can be used to set up a memory buffer to hold log messages when the |
1370 |
log filename is not yet known; a <tt>reopen_log()</tt> function, to close |
1371 |
and reopen the log file (in case the file has been moved and needs to be |
1372 |
recreated, or if <tt>LogFilename</tt> has changed, for example); and a |
1373 |
<tt>log_is_open()</tt> function, which returns whether a log file or buffer |
1374 |
is currently open.</p> |
1375 |
|
1376 |
<p>The log filename specified in the <tt>LogFilename</tt> configuration is |
1377 |
taken to be a template containing one or more of the following tokens:</p> |
1378 |
|
1379 |
<ul> |
1380 |
<li><b><tt>%y</tt>:</b> The current year (4 digits).</li> |
1381 |
<li><b><tt>%m</tt>:</b> The current month, 01-12 (2 digits).</li> |
1382 |
<li><b><tt>%d</tt>:</b> The current day of the month, 01-31 (2 digits).</li> |
1383 |
<li><b><tt>%%</tt>:</b> A literal "<tt>%</tt>" character.</li> |
1384 |
</ul> |
1385 |
|
1386 |
<p>The template is processed by the <tt>gen_log_filename()</tt> function, |
1387 |
called by <tt>open_log()</tt> and <tt>reopen_log()</tt>; the function |
1388 |
replaces the tokens with their appropriate values and returns the resulting |
1389 |
filename.</p> |
1390 |
|
1391 |
<p>Actual logging of messages is done via a set of ten functions, depending |
1392 |
on the particulars of the message:</p> |
1393 |
|
1394 |
<div class="code"> log(<i>format</i>, ...) |
1395 |
log_debug(<i>debuglevel</i>, <i>format</i>, ...) |
1396 |
log_perror(<i>format</i>, ...) |
1397 |
log_perror_debug(<i>debuglevel</i>, <i>format</i>, ...) |
1398 |
module_log(<i>format</i>, ...) |
1399 |
module_log_debug(<i>debuglevel</i>, <i>format</i>, ...) |
1400 |
module_log_perror(<i>format</i>, ...) |
1401 |
module_log_perror_debug(<i>debuglevel</i>, <i>format</i>, ...) |
1402 |
fatal(<i>format</i>, ...) |
1403 |
fatal_perror(<i>format</i>, ...) |
1404 |
</div> |
1405 |
|
1406 |
<p>Of these, the first eight (all but <tt>fatal()</tt> and |
1407 |
<tt>fatal_perror()</tt>) are implemented as macros defined in |
1408 |
<tt>log.h</tt> which call the <tt>do_log()</tt> function. The |
1409 |
<tt>module_</tt> functions are intended for use in modules, and insert the |
1410 |
module name before the log message (using the <tt>MODULE_NAME</tt> macro, |
1411 |
as described in <a href="4.html#s2-2">section 4-2-2</a>); the |
1412 |
<tt>_perror</tt> functions append a system error string to the end of the |
1413 |
message, like <tt>perror()</tt>; and the <tt>_debug</tt> functions allow a |
1414 |
minimum debug level for the message to be specified (and also cause the |
1415 |
string "debug:" to be inserted at the beginning of the message if the given |
1416 |
level is greater than zero). To illustrate the format of messages written |
1417 |
by these functions, a sample message from <tt>module_log_perror_debug(1,"message")</tt> might be:</p> |
1418 |
|
1419 |
<div class="code">[Jan 01 12:34:56 2000] debug: (module_name) message: System error</div> |
1420 |
|
1421 |
<p>When running in debug mode, the time is printed to microsecond |
1422 |
resolution.</p> |
1423 |
|
1424 |
<p><i>Implementation note: One reason these are implemented as |
1425 |
macros is to avoid GCC warning about <tt>log()</tt> conflicting with the |
1426 |
built-in mathematical function <tt>log()</tt>; another is to make it |
1427 |
unnecessary for modules to have to manually specify <tt>MODULE_NAME</tt> |
1428 |
when calling the module logging functions.</i></p> |
1429 |
|
1430 |
<p>The last two logging functions, <tt>fatal()</tt> and |
1431 |
<tt>fatal_perror()</tt>, are intended for conditions under which a |
1432 |
catastrophic failure cannot be avoided; they write the given message to the |
1433 |
log file (prefixed by a timestamp and the string "FATAL:"), send a |
1434 |
<tt>WALLOPS</tt> message to the remote server if connected, and call |
1435 |
<tt>exit(1)</tt> to abort the program, without performing any of the |
1436 |
ordinary cleanup procedure.</p> |
1437 |
|
1438 |
<p>All of the logging functions above first check whether the log file |
1439 |
needs to be rotated, by calling <tt>check_log_rotate()</tt> if the log file |
1440 |
is open. This function calls <tt>gen_log_filename()</tt> and compares the |
1441 |
result against the name of the currently open log file; if the filenames |
1442 |
differ, then the current log file is closed, and a new one is opened with |
1443 |
the new name.</p> |
1444 |
|
1445 |
<p>Actual writing to the log file is performed by the <tt>vlogprintf()</tt> |
1446 |
function, which can be thought of as a <tt>vfprintf()</tt> with an implied |
1447 |
file parameter (the log file). There are also <tt>logprintf()</tt> and |
1448 |
<tt>logputs()</tt> functions, which similarly function as <tt>fprintf()</tt> |
1449 |
and <tt>fputs()</tt> do. (Note that <tt>logputs()</tt> does <i>not</i> |
1450 |
output a trailing newline, like <tt>fputs()</tt> and unlike <tt>puts()</tt>.) |
1451 |
These functions first write the given string to standard error if the |
1452 |
program is running in no-fork mode (from the <tt>-nofork</tt> command-line |
1453 |
option). The string is then written to the currently open log file; if no |
1454 |
log file is open but the memory buffer is available (and not full), the |
1455 |
string is written to the buffer instead.</p> |
1456 |
|
1457 |
<p class="backlink"><a href="#top">Back to top</a></p> |
1458 |
|
1459 |
<!------------------------------------------------------------------------> |
1460 |
<hr/> |
1461 |
|
1462 |
<h3 class="subsection-title" id="s5">2-5. Message sending and receiving</h3> |
1463 |
|
1464 |
<p>In order to operate, Services must be able to send messages to and |
1465 |
receive messages from the remote IRC server. While each IRC server has its |
1466 |
own idiosyncrasies (which are handled by IRC protocol modules, as described |
1467 |
in <a href="5.html">section 5</a>), all share the same text-based, |
1468 |
line-oriented format described in RFC 1459, and the Services core includes |
1469 |
several functions for handling basic message sending and receiving.</p> |
1470 |
|
1471 |
<p class="backlink"><a href="#top">Back to top</a></p> |
1472 |
|
1473 |
|
1474 |
<h4 class="subsubsection-title" id="s5-1">2-5-1. Sending messages</h4> |
1475 |
|
1476 |
<p>Message sending routines are located in <tt>send.c</tt> and |
1477 |
<tt>send.h</tt>. The most basic of these is <tt>vsend_cmd()</tt> (and its |
1478 |
companion <tt>send_cmd()</tt>), which takes an optional message source, a |
1479 |
message format string, and format arguments, and formats them into an IRC |
1480 |
message which it then sends to the remote server. (These functions would |
1481 |
have been better named <tt>[v]send_msg()</tt>, but <i>c'est la vie</i>.) |
1482 |
For example, a <tt>PING</tt> message could be sent to the remote server |
1483 |
with:</p> |
1484 |
|
1485 |
<div class="code">send_cmd(NULL, "PING :%s", ServerName);</div> |
1486 |
|
1487 |
<p>Since it would be overly repetitive to write out the entire message |
1488 |
format every time a message was to be sent, and since some protocols use |
1489 |
different message formats for some messages, there are a number of |
1490 |
shortcut routines which send a certain type of message to the remote |
1491 |
server. For example, <tt>PRIVMSG</tt>, <tt>NOTICE</tt>, and |
1492 |
<tt>WALLOPS</tt> messages can be sent using the routines of the same |
1493 |
names:</p> |
1494 |
|
1495 |
<dl> |
1496 |
<dt><tt>void <b>privmsg</b>(const char *<i>source</i>, const char *<i>dest</i>, |
1497 |
const char *<i>fmt</i>, ...)</tt></dt> |
1498 |
<dd>Sends a <tt>PRIVMSG</tt> message from <tt><i>source</i></tt> to |
1499 |
<tt><i>dest</i></tt>.</dd> |
1500 |
<dt><tt>void <b>notice</b>(const char *<i>source</i>, const char *<i>dest</i>, |
1501 |
const char *<i>fmt</i>, ...)</tt></dt> |
1502 |
<dd>Sends a <tt>NOTICE</tt> message from <tt><i>source</i></tt> to |
1503 |
<tt><i>dest</i></tt>.</dd> |
1504 |
<dt><tt>void <b>wallops</b>(const char *<i>source</i>, |
1505 |
const char *<i>fmt</i>, ...)</tt></dt> |
1506 |
<dd>Sends a <tt>WALLOPS</tt> message (or an equivalent message for the |
1507 |
protocol in use) to the network.</dd> |
1508 |
</dl> |
1509 |
|
1510 |
<p>Of these, <tt>NOTICE</tt> is used most commonly by far, and it has |
1511 |
several variations of its own:</p> |
1512 |
|
1513 |
<dl> |
1514 |
<dt><tt>void <b>notice_list</b>(const char *<i>source</i>, |
1515 |
const char *<i>dest</i>, const char **<i>text</i>)</tt></dt> |
1516 |
<dd>Sends each string in the <tt>NULL</tt>-terminated array |
1517 |
<tt><i>text</i></tt> as a <tt>NOTICE</tt> message from |
1518 |
<tt><i>source</i></tt> to <tt><i>dest</i></tt>.</dd> |
1519 |
<dt><tt>void <b>notice_all</b>(const char *<i>source</i>, |
1520 |
const char *<i>fmt</i>, ...)</tt></dt> |
1521 |
<dd>Sends a <tt>NOTICE</tt> message from <tt><i>source</i></tt> to |
1522 |
all clients on the network.</dd> |
1523 |
<dt><tt>void <b>notice_lang</b>(const char *<i>source</i>, |
1524 |
const User *<i>dest</i>, int *<i>index</i>, ...)</tt></dt> |
1525 |
<dd>Sends a <tt>NOTICE</tt> message from <tt><i>source</i></tt> to |
1526 |
<tt><i>dest</i></tt>, taking into account the language preference |
1527 |
of the target client and splitting the text into separate messages |
1528 |
at newline boundaries.</dd> |
1529 |
<dt><tt>void <b>notice_help</b>(const char *<i>source</i>, |
1530 |
const User *<i>dest</i>, int *<i>index</i>, ...)</tt></dt> |
1531 |
<dd>Sends a <tt>NOTICE</tt> message from <tt><i>source</i></tt> to |
1532 |
<tt><i>dest</i></tt> like <tt>notice_lang()</tt>, but also replaces |
1533 |
each occurrence of <tt>%S</tt> (with an upper-case "S") in the |
1534 |
format string with the value of <tt><i>source</i></tt>.</dd> |
1535 |
</dl> |
1536 |
|
1537 |
<p>The latter two functions, <tt>notice_lang()</tt> and |
1538 |
<tt>notice_help()</tt>, take advantage of multilingual support (see |
1539 |
<a href="#s8-2">section 2-8-2</a>) to send messages in the user's selected |
1540 |
language; in this case the destination is passed as a <tt>User</tt> |
1541 |
structure (see <a href="#s6-2">section 2-6-2</a>) rather than a string. |
1542 |
These functions also process <tt>printf()</tt>-style formatting tokens in |
1543 |
the specified message.</p> |
1544 |
|
1545 |
<p>Other sending functions include:</p> |
1546 |
|
1547 |
<dl> |
1548 |
<dt><tt>void <b>send_channel_cmd</b>(const char *<i>source</i>, |
1549 |
const char *<i>fmt</i>, ...)</tt></dt> |
1550 |
<dd>Sends a message that changes a channel's status. Some protocols |
1551 |
do not allow pseudoclients to change channel status directly, and |
1552 |
substitute the server name for the nickname given in the |
1553 |
<tt><i>source</i></tt> parameter.</dd> |
1554 |
<dt><tt>void <b>send_cmode_cmd</b>(const char *<i>source</i>, |
1555 |
const char *<i>channel</i>, const char *<i>fmt</i>, ...)</tt></dt> |
1556 |
<dd>Sends a <tt>MODE</tt> message for a channel. The format string |
1557 |
should start with the mode parameter ("<tt>+...</tt>" or |
1558 |
"<tt>-...</tt>").</dd> |
1559 |
<dt><tt>void <b>send_error</b>(const char *<i>fmt</i>, ...)</tt></dt> |
1560 |
<dd>Sends an <tt>ERROR</tt> message to the remote server, and |
1561 |
disconnects.</dd> |
1562 |
<dt><tt>void <b>send_namechange</b>(const char *<i>nick</i>, |
1563 |
const char *<i>newname</i>)</tt></dt> |
1564 |
<dd>Sends a message to change the "real name" of a pseudoclient. |
1565 |
<i>Not supported by some protocols.</i></dd> |
1566 |
<dt><tt>void <b>send_nick</b>(const char *<i>nick</i>, const char *<i>user</i>, |
1567 |
const char *<i>host</i>, const char *<i>server</i>, |
1568 |
const char *<i>name</i>, const char *<i>modes</i>)</tt></dt> |
1569 |
<dd>Sends messages to introduce a client to the network.</dd> |
1570 |
<dt><tt>void <b>send_nickchange</b>(const char *<i>nick</i>, |
1571 |
const char *<i>newnick</i>)</tt></dt> |
1572 |
<dd>Sends a message to change the nickname of a pseudoclient.</dd> |
1573 |
<dt><tt>send_nickchange_remote(const char *<i>nick</i>, |
1574 |
const char *<i>newnick</i>)</tt></dt> |
1575 |
<dd>Sends a message to change the nickname of a client on another |
1576 |
server. <i>Not supported by some protocols.</i></dd> |
1577 |
<dt><tt>void <b>send_pseudo_nick</b>(const char *<i>nick</i>, |
1578 |
const char *<i>realname</i>, int <i>flags</i>)</tt></dt> |
1579 |
<dd>Introduces a pseudoclient to the network.</dd> |
1580 |
<dt><tt>void <b>send_server</b>()</tt></dt> |
1581 |
<dd>Sends the initial messages required upon connection to the remote |
1582 |
server.</dd> |
1583 |
<dt><tt>void <b>send_server_remote</b>(const char *<i>server</i>, |
1584 |
const char *<i>desc</i>)</tt></dt> |
1585 |
<dd>Sends a message to introduce a new (fake) server to the network.</dd> |
1586 |
</dl> |
1587 |
|
1588 |
<p>Note that some of these functions are actually implemented by protocol |
1589 |
modules, as described in <a href="5.html">section 5</a>. This means that |
1590 |
they may not have exactly the same result on different protocols (for |
1591 |
example, <tt>send_nickchange_remote()</tt> won't do anything if the |
1592 |
protocol doesn't support remote nickname changing), and that the functions |
1593 |
cannot be used before a protocol module is loaded (any attempt to do so |
1594 |
will cause the program to abort).</p> |
1595 |
|
1596 |
<p><tt>send.c</tt> also defines several variables used to indicate |
1597 |
characteristics of the protocol in use:</p> |
1598 |
|
1599 |
<ul> |
1600 |
<li><b><tt>protocol_name</tt>:</b> A string describing the protocol.</li> |
1601 |
<li><b><tt>protocol_version</tt>:</b> A string describing the versions of |
1602 |
the protocol supported by the module.</li> |
1603 |
<li><b><tt>protocol_features</tt>:</b> A bitmask of features supported by |
1604 |
the protocol.</li> |
1605 |
<li><b><tt>protocol_nickmax</tt>:</b> The maximum nickname length supported |
1606 |
by the protocol.</li> |
1607 |
</ul> |
1608 |
|
1609 |
<p>These variables are set by the protocol module in its initialization |
1610 |
routine; see <a href="5.html#s2">section 5-2</a> for details. |
1611 |
<tt>send.c</tt> hooks into the "<tt>load module</tt>" callback to watch |
1612 |
for a protocol module being loaded, and ensures that the protocol has set |
1613 |
all protocol variables and functions properly. <i>Implementation note: |
1614 |
since there is nothing to specify that a particular module is a protocol |
1615 |
module, the function simply assumes that the first module loaded is a |
1616 |
protocol module.</i></p> |
1617 |
|
1618 |
<p class="backlink"><a href="#top">Back to top</a></p> |
1619 |
|
1620 |
|
1621 |
<h4 class="subsubsection-title" id="s5-2">2-5-2. Receiving messages</h4> |
1622 |
|
1623 |
<p>Message reception is handled by the socket callbacks |
1624 |
<tt>readfirstline_callback()</tt> and <tt>readline_callback()</tt>, which |
1625 |
are called when a line of text is available to be read from the network |
1626 |
(see <a href="3.html">section 3</a> for a description of how socket |
1627 |
processing works). When the socket is created, its <tt>READLINE</tt> |
1628 |
callback is set to <tt>readfirstline_callback()</tt>; this routine reads |
1629 |
the first line of data from the network, sets the <tt>linked</tt> global |
1630 |
flag (if the first line was not an <tt>ERROR</tt> message) to indicate |
1631 |
that Services has connected to the network, introduces all pseudoclients |
1632 |
(using the <tt>introduce_user()</tt> function in <tt>init.c</tt>—see |
1633 |
<a href="7.html#s1">section 7-1</a> for details), calls the |
1634 |
"<tt>connect</tt>" callback, and changes the socket's callback function to |
1635 |
<tt>readline_callback()</tt> to read subsequent messages.</p> |
1636 |
|
1637 |
<p>Each line of data read in this way is sent to the <tt>process()</tt> |
1638 |
function, discussed in <a href="#s5-3">section 2-5-3</a> below, for parsing |
1639 |
and processing.</p> |
1640 |
|
1641 |
<p class="backlink"><a href="#top">Back to top</a></p> |
1642 |
|
1643 |
|
1644 |
<h4 class="subsubsection-title" id="s5-3">2-5-3. Processing messages</h4> |
1645 |
|
1646 |
<p>Once a message has been received from the remote server, it is passed to |
1647 |
the <tt>process()</tt> function, defined in <tt>process.c</tt>, for |
1648 |
processing. (Technically, <tt>process()</tt> takes no arguments, and reads |
1649 |
the message from the global <tt>inbuf</tt> variable; this approach is taken |
1650 |
to allow signal handlers to log the current buffer in case the program |
1651 |
crashes during processing of a message.) <tt>process()</tt> first extracts |
1652 |
the sender, if any, from the beginning of the buffer and splits the rest of |
1653 |
the buffer into fields in the RFC 1459 style—note that there is no |
1654 |
facility for handling protocols which do not use RFC 1459-style messages. |
1655 |
<tt>process()</tt> then calls the "<tt>receive message</tt>" callback, |
1656 |
which is the lowest-level method of hooking into input messages; if no |
1657 |
callback function handles the message, it is then processed in the ordinary |
1658 |
manner, which involves looking up the message name using |
1659 |
<tt>find_message()</tt> and calling the message's handler function if one |
1660 |
exists. The handler receives the message's source as a string, and the |
1661 |
message's parameters as a count/vector pair (the command itself is not |
1662 |
passed to the function).</p> |
1663 |
|
1664 |
<p><tt>find_message()</tt> is located in <tt>messages.c</tt>, along with |
1665 |
other routines for managing messages. Message handlers are organized into |
1666 |
tables of <tt>Message</tt> structures, each of which is a pair of a message |
1667 |
name and a handler for that message. These tables can be registered with |
1668 |
the message processing code using the <tt>register_messages()</tt> |
1669 |
function, and removed again with the <tt>unregister_messages()</tt> |
1670 |
function (the default handlers are installed by the |
1671 |
<tt>messages_init()</tt> function). This is the method by which protocol |
1672 |
modules (see <a href="5.html">section 5</a>) typically handle |
1673 |
protocol-specific messages, though in some cases it is necessary to hook |
1674 |
into the "<tt>receive message</tt>" callback instead.</p> |
1675 |
|
1676 |
<p>When called, <tt>find_message()</tt> searches all registered tables for |
1677 |
a handler for the given message (case-insensitive), and returns it if |
1678 |
found. If two or more tables have handlers for the same message, the one |
1679 |
in the most recently registered table is used, allowing previously-installed |
1680 |
handlers to be overridden (however, there is no facility for calling the |
1681 |
overridden handler).</p> |
1682 |
|
1683 |
<p>Internally, <tt>find_message()</tt> uses a doubly-linked list of message |
1684 |
names and associated <tt>Message</tt> structures to locate messages; this |
1685 |
list is created by <tt>init_message_list()</tt> called each time a message |
1686 |
table is registered or unregistered. When a message is found, it is |
1687 |
shifted one element toward the head of the list (if it is not already at |
1688 |
the head), so that subsequent searches can find that message faster. This |
1689 |
allows frequently-seen messages to "bubble" up to the top of the list, |
1690 |
reducing the time spent looking up each message. (A decent hash table |
1691 |
would probably be more efficient still, if more complex.)</p> |
1692 |
|
1693 |
<p>The default message handlers are also defined in <tt>messages.c</tt>, |
1694 |
and cover the basic set of IRC messages, such as <tt>PRIVMSG</tt> (which |
1695 |
calls the "<tt>m_privmsg</tt>" callback for processing), <tt>JOIN</tt>, and |
1696 |
<tt>SERVER</tt>. There are also entries in the table for ignored messages, |
1697 |
such as <tt>NOTICE</tt> and <tt>PONG</tt>, with no handler specified; these |
1698 |
are present to prevent <tt>process()</tt> from logging an "unknown message" |
1699 |
warning.</p> |
1700 |
|
1701 |
<p>Noticeably absent from the message table are <tt>NICK</tt> and |
1702 |
<tt>USER</tt>. Client registration is one of the greatest points of |
1703 |
difference between IRC protocols, and attempting to use the default RFC |
1704 |
1459 method does not work on most modern protocols, so handling of these |
1705 |
messages is left entirely to the protocol module. As a corollary, if the |
1706 |
protocol module does not handle these (or whatever other message may be |
1707 |
used for introducing clients to the network), Services will not be able to |
1708 |
recognize any clients.</p> |
1709 |
|
1710 |
<p class="backlink"><a href="#top">Back to top</a></p> |
1711 |
|
1712 |
|
1713 |
<h4 class="subsubsection-title" id="s5-4">2-5-4. The ignore list</h4> |
1714 |
|
1715 |
<p>In order to provide some measure of protection against users "spamming" |
1716 |
Services with messages in order to cause a denial of service, the default |
1717 |
<tt>PRIVMSG</tt> handler includes logic which keeps track of how much load |
1718 |
each client is placing on Services, and ignores <tt>PRIVMSG</tt> messages |
1719 |
from clients who exceed a certain threshold. The ignore data is not kept |
1720 |
in a "list" per se, but is instead stored as part of each <tt>User</tt> |
1721 |
structure (see <a href="#s6-2">section 2-6-2</a>); the |
1722 |
<tt>ignore_init()</tt> routine initializes the fields in this structure |
1723 |
used for ignore data, and the <tt>ignore_update()</tt> routine updates the |
1724 |
fields after work has been done on behalf of the client. Both of these |
1725 |
routines are contained in <tt>ignore.c</tt>.</p> |
1726 |
|
1727 |
<p>The "ignore value" for a client, stored in the <tt>ignore</tt> field of |
1728 |
the <tt>User</tt> structure, is calculated roughly as the average over |
1729 |
time of a function whose value is 1 when Services is executing code on |
1730 |
behalf ot the client and 0 at all other times, with recent values given |
1731 |
more weight. Rather than keep track of the exact time values, however, a |
1732 |
decaying average is computed, with the value decaying by half every time |
1733 |
interval specified by the <tt>IgnoreDecay</tt> configuration directive. If |
1734 |
this average value exceeds the threshold specified by |
1735 |
<tt>IgnoreThreshold</tt>, the <tt>PRIVMSG</tt> handler will ignore the |
1736 |
client's message.</p> |
1737 |
|
1738 |
<p>This approach is obviously limited in its effectiveness—for |
1739 |
example, it cannot deal with a botnet or other large group of clients |
1740 |
attacking Services if each client stays below the ignore threshold—but |
1741 |
it can serve as a first line of defense against malicious users.</p> |
1742 |
|
1743 |
|
1744 |
<p class="backlink"><a href="#top">Back to top</a></p> |
1745 |
|
1746 |
<!------------------------------------------------------------------------> |
1747 |
<hr/> |
1748 |
|
1749 |
<h3 class="subsection-title" id="s6">2-6. Servers, clients, and channels</h3> |
1750 |
|
1751 |
<p>Since Services connects to the IRC network as a server, it must keep |
1752 |
track of the IRC network's state—the servers, clients, and channels |
1753 |
on the network—just as other servers do. This section discusses the |
1754 |
way in which this state is stored and the routines used for managing it.</p> |
1755 |
|
1756 |
<p class="backlink"><a href="#top">Back to top</a></p> |
1757 |
|
1758 |
|
1759 |
<h4 class="subsubsection-title" id="s6-1">2-6-1. Servers</h4> |
1760 |
|
1761 |
<p>Server management routines are contained in <tt>servers.c</tt> and |
1762 |
<tt>servers.h</tt>. The important routines (other than initialization |
1763 |
and cleanup) are <tt>do_server()</tt> and <tt>do_squit()</tt>, which are |
1764 |
called from their respective message handlers to add and remove servers. |
1765 |
The server records themselves are stored in a hash table, created using |
1766 |
the <tt>hash.h</tt> header file. Each record is a <tt>Server</tt> |
1767 |
structure, containing the server's name, network join time, and client list |
1768 |
(see <a href="#s6-2">section 2-6-2</a> below); there is also a flag |
1769 |
indicating whether the record represents a real server on the network or a |
1770 |
fake server created by Services (such as with the OperServ <tt>JUPE</tt> |
1771 |
command). Services also creates a fake server record for itself, using the |
1772 |
empty string for the server name.</p> |
1773 |
|
1774 |
<p>When adding a server, parent/child links are established between the |
1775 |
originating server and the new server. This allows easy removal of an |
1776 |
entire subtree of servers when an <tt>SQUIT</tt> message is received: |
1777 |
<tt>do_squit()</tt> calls <tt>squit_server()</tt> on the quitting server, |
1778 |
which calls <tt>recursive_squit()</tt> to delete any child servers (from |
1779 |
Services' point of view) before deleting the quitting server itself. In |
1780 |
turn, <tt>recursive_squit()</tt>, as its name suggests, recursively calls |
1781 |
<tt>squit_server()</tt> for each child server. Since the IRC protocol |
1782 |
mandates a tree structure for the network—cycles are not |
1783 |
permitted—there is no danger of infinite recursion.</p> |
1784 |
|
1785 |
<p>In addition, there are some protocols which do not explicitly send |
1786 |
<tt>QUIT</tt> messages for clients on disconnecting servers, a |
1787 |
bandwidth-saving feature commonly known as "NOQUIT" from the token used in |
1788 |
protocol negotiation to indicate that the feature is available. If the |
1789 |
protocol module signals, via the <tt>PF_NOQUIT</tt> protocol feature flag |
1790 |
(see <a href="5.html#s2">section 5-2</a>), that it supports this feature, |
1791 |
<tt>squit_server()</tt> will take care of removing all clients on each |
1792 |
deleted server before deleting the server itself.</p> |
1793 |
|
1794 |
<p class="backlink"><a href="#top">Back to top</a></p> |
1795 |
|
1796 |
|
1797 |
<h4 class="subsubsection-title" id="s6-2">2-6-2. Clients</h4> |
1798 |
|
1799 |
<p>Clients are also called "users" in IRC. It is common to use the term |
1800 |
"client" to refer to any program which connects to an IRC server and "user" |
1801 |
to refer in particular to a human operating a client (or a client operated |
1802 |
by a human), but through an unfortunate choice of terminology, clients are |
1803 |
called "users" in the Services source code. (In this documentation, the |
1804 |
term "client" is used to refer to an IRC client on the network, while |
1805 |
"user" refers more generally to the human controlling a client.)</p> |
1806 |
|
1807 |
<p>Be that as it may, each client (user) that connects to the network is |
1808 |
given a <tt>User</tt> record, as defined in <tt>users.h</tt>, which is |
1809 |
managed by code in <tt>users.c</tt>; as with server management, |
1810 |
<tt>users.c</tt> uses a hash table to hold the client records. Each client |
1811 |
record contains:</p> |
1812 |
|
1813 |
<ul> |
1814 |
<li class="spaced">The client's nickname, username, hostname, and "real |
1815 |
name" strings. "Fake hostname" (the hostname shown to non-operator |
1816 |
clients) and IP address are also recorded for protocols which |
1817 |
support them.</li> |
1818 |
|
1819 |
<li class="spaced">Next/previous links for linking all clients on the same |
1820 |
server (the <tt>snext</tt> and <tt>sprev</tt> fields).</li> |
1821 |
|
1822 |
<li class="spaced">Nickname registration data (see |
1823 |
<a href="7.html#s3-1-1">section 7-3-1-1</a>).</li> |
1824 |
|
1825 |
<li class="spaced">The client's connection timestamp as passed from the |
1826 |
remote server, as well as the local timestamp when Services |
1827 |
received the client registration message. There is also a |
1828 |
"Services stamp" field, a unique integer assigned by Services and |
1829 |
maintained by the IRC servers (if supported) to identify clients |
1830 |
across netsplits; this is used by the NickServ pseudoclient in |
1831 |
nickname authentication.</li> |
1832 |
|
1833 |
<li class="spaced">The client's IRC modes, and flags used by Services.</li> |
1834 |
|
1835 |
<li class="spaced">The client's ignore data (see <a href="#s5-4">section |
1836 |
2-5-4</a>).</li> |
1837 |
|
1838 |
<li class="spaced">Various counters and timers, such as for counting bad |
1839 |
passwords.</li> |
1840 |
|
1841 |
<li class="spaced">An array of registered nickname group IDs for which the |
1842 |
client has identified (used by NickServ).</li> |
1843 |
|
1844 |
<li class="spaced">A list of channels the client is currently in.</li> |
1845 |
|
1846 |
<li class="spaced">A list of channels the client has identified for (used |
1847 |
by ChanServ).</li> |
1848 |
</ul> |
1849 |
|
1850 |
<p>As can be seen above, the <tt>User</tt> structure contains a few fields |
1851 |
which are used only by modules. From a design standpoint, these fields |
1852 |
would be ideally stored in separate tables set up by those modules, but |
1853 |
they are aggregated into the <tt>User</tt> structure for the sake of |
1854 |
convenience. The core code does not access any of the module-based data, |
1855 |
with the exception of the multilingual code, which uses the language |
1856 |
setting stored in the nickname's registration data, if any (see |
1857 |
<a href="#s8-2">section 2-8-2</a>).</p> |
1858 |
|
1859 |
<p>The primary interface into the client management code is through the IRC |
1860 |
message processing functions, as with servers. In the case of clients, |
1861 |
there are several messages that need to be handled: <tt>NICK</tt>, |
1862 |
<tt>MODE</tt> (for a client target), <tt>KILL</tt>, <tt>QUIT</tt>, |
1863 |
<tt>JOIN</tt>, <tt>PART</tt>, and <tt>KICK</tt>. (The latter three are |
1864 |
technically channel-related messages, but as they also operate on client |
1865 |
data, they are handled here and call functions from the channel management |
1866 |
subsystem to do their work.) As some of these messages have large parts in |
1867 |
common, they often call local subroutines to perform their work: |
1868 |
<tt>QUIT</tt> and <tt>KILL</tt> both use <tt>quit_user()</tt> to clean up |
1869 |
after the departing client, and <tt>PART</tt> and <tt>KICK</tt> call |
1870 |
<tt>part_channel()</tt> to remove the client from the specified channel. |
1871 |
(The infamous "<tt>JOIN 0</tt>" message, which causes a client to |
1872 |
leave all channels it is currently in, is similarly implemented.)</p> |
1873 |
|
1874 |
<p>In addition to the processing functions, <tt>users.c</tt> provides a |
1875 |
number of client-related utility functions. These include informational |
1876 |
functions that return a client's status on the network or on a particular |
1877 |
channel:</p> |
1878 |
|
1879 |
<dl> |
1880 |
<dt><tt>int <b>is_oper</b>(const User *<i>user</i>)</tt></dt> |
1881 |
<dd>Returns whether the client is an IRC operator.</dd> |
1882 |
<dt><tt>int <b>is_on_chan</b>(const User *<i>user</i>, const char *<i>chan</i>)</tt></dt> |
1883 |
<dd>Returns whether the client is on the specified channel.</dd> |
1884 |
<dt><tt>int <b>is_chanop</b>(const User *<i>user</i>, const char *<i>chan</i>)</tt></dt> |
1885 |
<dd>Returns whether the client is a channel operator on the specified |
1886 |
channel.</dd> |
1887 |
<dt><tt>int <b>is_voiced</b>(const User *<i>user</i>, const char *<i>chan</i>)</tt></dt> |
1888 |
<dd>Returns whether the client is voiced on the specified channel.</dd> |
1889 |
</dl> |
1890 |
|
1891 |
<p>Functions for handling user/host masks:</p> |
1892 |
|
1893 |
<dl> |
1894 |
<dt><tt>int <b>match_usermask</b>(const char *<i>mask</i>, const User *<i>user</i>)</tt></dt> |
1895 |
<dd>Returns whether the client's username and hostname information |
1896 |
match the given <tt><i>user</i>@<i>host</i></tt> mask.</dd> |
1897 |
<dt><tt>void <b>split_usermask</b>(const char *<i>mask</i>, |
1898 |
char **<i>nick</i>, char **<i>user</i>, char **<i>host</i>)</tt></dt> |
1899 |
<dd>Returns the nickname, username, and hostname parts of a mask as |
1900 |
separate strings.</dd> |
1901 |
<dt><tt>char *<b>create_mask</b>(const User *<i>user</i>, int <i>use_fakehost</i>)</tt></dt> |
1902 |
<dd>Creates a new mask based on the client's username and hostname |
1903 |
information, returning it as a <tt>malloc()</tt>'d string.</dd> |
1904 |
</dl> |
1905 |
|
1906 |
<p>And functions related to guest nicknames:</p> |
1907 |
|
1908 |
<dl> |
1909 |
<dt><tt>char *<b>make_guest_nick</b>()</tt></dt> |
1910 |
<dd>Creates a new guest nickname. The returned nickname is stored in |
1911 |
a static buffer.</dd> |
1912 |
<dt><tt>int <b>is_guest_nick</b>(const char *<i>nick</i>)</tt></dt> |
1913 |
<dd>Returns whether the given nickname is a guest nickname.</dd> |
1914 |
</dl> |
1915 |
|
1916 |
<p class="backlink"><a href="#top">Back to top</a></p> |
1917 |
|
1918 |
|
1919 |
<h4 class="subsubsection-title" id="s6-3">2-6-3. Channels</h4> |
1920 |
|
1921 |
<p>Channels are managed by the <tt>channels.c</tt> and <tt>channels.h</tt> |
1922 |
files, which, like servers and clients, store records for each channel in a |
1923 |
hash table. Channel records contain:</p> |
1924 |
|
1925 |
<ul> |
1926 |
<li class="spaced">The channel's name.</li> |
1927 |
|
1928 |
<li class="spaced">Channel registration data (see |
1929 |
<a href="7.html#s4-1-1">section 7-4-1-1</a>).</li> |
1930 |
|
1931 |
<li class="spaced">The channel's creation timestamp.</li> |
1932 |
|
1933 |
<li class="spaced">The channel's topic, along with the nickname of the |
1934 |
client which set the topic and the time the topic was set.</li> |
1935 |
|
1936 |
<li class="spaced">Mode information for the channel, including a bitmask of |
1937 |
binary modes and fields for non-binary modes and ban/exception/invite lists. |
1938 |
Not all fields are used by all protocols; also, the meaning of the bits in |
1939 |
the <tt>modes</tt> field changes with the protocol (see |
1940 |
<a href="#s6-4">section 2-6-4</a> below).</li> |
1941 |
|
1942 |
<li class="spaced">A list of clients on the channel, with channel user |
1943 |
modes (such as <tt>+o</tt> and <tt>+v</tt>) and local flags for each |
1944 |
client.</li> |
1945 |
|
1946 |
<li class="spaced">Fields used to check for "bouncy modes" (see below).</li> |
1947 |
</ul> |
1948 |
|
1949 |
<p>As discussed in <a href="#s6-2">section 2-6-2</a>, the channel messages |
1950 |
<tt>JOIN</tt>, <tt>PART</tt>, and <tt>KICK</tt> are processed by the client |
1951 |
management subsystem; the handlers for those messages call |
1952 |
<tt>chan_adduser()</tt> and <tt>chan_deluser()</tt> for the channel side of |
1953 |
the processing. The only messages processed entirely by <tt>channels.c</tt> |
1954 |
are the pure channel messages <tt>MODE</tt> (for a channel target) and |
1955 |
<tt>TOPIC</tt>.</p> |
1956 |
|
1957 |
<p>One problem that can occur with channels is that, possibly due to a |
1958 |
misconfiguration, the remote server (or another server on the network) does |
1959 |
not allow Services to change the channel's modes; this can result in an |
1960 |
infinite loop of channel mode changes taking place. For example, ChanServ |
1961 |
might request that the mode <tt>+s</tt> be set on a channel, but when |
1962 |
Services sends that mode change out, the remote server immediately counters |
1963 |
it with a <tt>-s</tt>. ChanServ, believing that its <tt>+s</tt> actually |
1964 |
took effect before the <tt>-s</tt> was sent, sends out a new <tt>+s</tt>, |
1965 |
and the cycle continues. This can result in flooding of the link between |
1966 |
Services and its remote server and make the channel unusable due to the |
1967 |
neverending mode changes.</p> |
1968 |
|
1969 |
<p>To avoid this problem, the <tt>MODE</tt> message handler watches for |
1970 |
identical mode changes from any server, and counts the number of changes |
1971 |
that occur per second. ChanServ uses this in its mode-setting routine |
1972 |
(<tt>check_modes()</tt>, described in <a href="7.html#s4-1-3">section |
1973 |
7-4-1-3</a>) to decide whether to attempt to change modes on the channel. |
1974 |
<i>Implementation note: While the count of mode changes per second and the |
1975 |
"bouncy modes" flag is kept on a per-channel basis, the mode string itself |
1976 |
is stored in a single static variable, so bouncy modes may not be detected |
1977 |
if they occur on multiple channels at the same time.</i></p> |
1978 |
|
1979 |
<p>The <tt>MODE</tt> message handler also keeps track of multiple channel |
1980 |
user mode changes for the same client within the same <tt>MODE</tt> |
1981 |
message, and aggregates them so that the "<tt>channel umode change</tt>" |
1982 |
callback is only called once per client per message.</p> |
1983 |
|
1984 |
<p>Aside from message processing, <tt>channels.c</tt> also provides the |
1985 |
function <tt>chan_has_ban()</tt>, which returns whether a given ban mask |
1986 |
(case-insensitive) exists on a particular channel.</p> |
1987 |
|
1988 |
<p class="backlink"><a href="#top">Back to top</a></p> |
1989 |
|
1990 |
|
1991 |
<h4 class="subsubsection-title" id="s6-4">2-6-4. Client and channel modes</h4> |
1992 |
|
1993 |
<p>Services keeps track of binary modes for clients and channels using flag |
1994 |
bitmasks rather than strings, for efficiency. In order to convert between |
1995 |
the mode characters used by the IRC protocol and these flag values, the |
1996 |
<tt>modes.c</tt> source file (along with its companion header, |
1997 |
<tt>modes.h</tt>) provides several utility routines for handling client and |
1998 |
channel modes:</p> |
1999 |
|
2000 |
<dl> |
2001 |
<dt><tt>void <b>mode_setup</b>()</tt></dt> |
2002 |
<dd>Initializes internal tables (see below).</dd> |
2003 |
<dt><tt>int32 <b>mode_char_to_flag</b>(char <i>c</i>, int <i>which</i>)</tt></dt> |
2004 |
<dd>Converts a mode character to the corresponding flag value.</dd> |
2005 |
<dt><tt>char <b>mode_flag_to_char</b>(int32 <i>f</i>, int <i>which</i>)</tt></dt> |
2006 |
<dd>Converts a single mode flag to the corresponding character.</dd> |
2007 |
<dt><tt>int32 <b>mode_string_to_flags</b>(const char *<i>s</i>, int <i>which</i>)</tt></dt> |
2008 |
<dd>Converts a string of mode characters to a set of flags.</dd> |
2009 |
<dt><tt>char *<b>mode_flags_to_string</b>(int32 <i>flags</i>, int <i>which</i>)</tt></dt> |
2010 |
<dd>Converts a set of mode flags to a string of mode characters (the |
2011 |
returned string is stored in a static buffer).</dd> |
2012 |
<dt><tt>int <b>mode_char_to_params</b>(char <i>c</i>, int <i>which</i>)</tt></dt> |
2013 |
<dd>Returns the number of parameters used when setting or unsetting a |
2014 |
mode, as <tt>plus_params<<8 | minus_params</tt> (see the |
2015 |
<tt>ModeData</tt> structure description below).</dd> |
2016 |
<dt><tt>int32 <b>cumode_prefix_to_flag</b>(char <i>c</i>)</tt></dt> |
2017 |
<dd>Converts a nickname prefix character to the corresponding channel |
2018 |
user mode flag.</dd> |
2019 |
</dl> |
2020 |
|
2021 |
<p>The <tt><i>which</i></tt> parameter passed to most of these functions |
2022 |
indicates what type of mode is being used: <tt>MODE_USER</tt> for client |
2023 |
modes (such as <tt>+o</tt> for IRC operator status), <tt>MODE_CHANNEL</tt> |
2024 |
for channel modes (such as <tt>+s</tt> for secret channels), and |
2025 |
<tt>MODE_CHANUSER</tt> for "channel user modes"—channel modes that |
2026 |
are applied to clients on the channel rather than the channel itself, such |
2027 |
as <tt>+o</tt> for channel operator privileges. (Channel modes and channel |
2028 |
user modes share the same set of mode characters in the IRC protocol, but |
2029 |
Services treats them separately, hence there is a separate mode selection |
2030 |
constant for them.)</p> |
2031 |
|
2032 |
<p>In the case of channel modes, not every mode is a simple binary on/off |
2033 |
flag; for example, <tt>+l</tt> (limit) takes an integer parameter that |
2034 |
specifies the client limit on the channel, and <tt>+b</tt> can be specified |
2035 |
multiple times. These are handled by additional fields in the channel |
2036 |
record for each of these "special" modes. When there is a distinction |
2037 |
between "set" and "unset" for the mode (such as <tt>+l</tt>/<tt>-l</tt>), |
2038 |
it is also given a flag value, but modes such as <tt>+b</tt> that can be |
2039 |
set multiple times are not given a flag at all.</p> |
2040 |
|
2041 |
<p>While these functions are able to handle the standard IRC mode |
2042 |
characters (client modes <tt>oiw</tt>, channel modes <tt>biklmnpst</tt>, |
2043 |
and channel user modes <tt>ov</tt>) by default, many IRC protocols |
2044 |
introduce additional modes specific to that protocol. In order to support |
2045 |
these modes as well, <tt>modes.c</tt> exports three arrays into which mode |
2046 |
information can be written: <tt>usermodes[]</tt>, <tt>chanmodes[]</tt>, |
2047 |
and <tt>chanusermodes[]</tt>, for user (client), channel, and channel user |
2048 |
modes, respectively. These are each arrays of 256 elements, where each |
2049 |
element of the array contains information about the character with the |
2050 |
value of the corresponding array index (for example, the element with index |
2051 |
65 has information about the mode character "<tt>A</tt>"). The type of |
2052 |
each element is a <tt>ModeData</tt> structure, containing:</p> |
2053 |
|
2054 |
<dl> |
2055 |
<dt><tt>int32 <b>flag</b></tt></dt> |
2056 |
<dd>The flag value assigned to the mode (must be unique among all modes |
2057 |
of the same type). Can be 0x80000000 (<tt>MODE_INVALID</tt>) if no |
2058 |
flag is to be used for the mode, as is generally the case for modes |
2059 |
like the channel mode <tt>+b</tt> which can be set multiple times.</dd> |
2060 |
<dt><tt>uint8 <b>plus_params</b></tt></dt> |
2061 |
<dd>The number of parameters used when adding the mode.</dd> |
2062 |
<dt><tt>uint8 <b>minus_params</b></tt></dt> |
2063 |
<dd>The number of parameters used when removing the mode.</dd> |
2064 |
<dt><tt>char <b>prefix</b></tt></dt> |
2065 |
<dd>For channel user modes, the nickname prefix character for the mode |
2066 |
(such as "<tt>@</tt>" for "<tt>+o</tt>").</dd> |
2067 |
<dt><tt>uint32 <b>info</b></tt></dt> |
2068 |
<dd>Zero or more informational flags about the mode: |
2069 |
<ul> |
2070 |
<li><b><tt>MI_MULTIPLE</tt>:</b> The mode can be set multiple times |
2071 |
(like <tt>+b</tt> on channels).</li> |
2072 |
<li><b><tt>MI_REGISTERED</tt>:</b> The mode should be set on |
2073 |
clients with registered nicknames, or on registered |
2074 |
channels.</li> |
2075 |
<li><b><tt>MI_OPERS_ONLY</tt>:</b> The mode causes a channel to be |
2076 |
limited to operators only.</li> |
2077 |
<li><b><tt>MI_REGNICKS_ONLY</tt>:</b> The mode causes a channel to |
2078 |
be limited to clients with registered nicknames only.</li> |
2079 |
</ul></dd> |
2080 |
</dl> |
2081 |
|
2082 |
<p>The upper eight bits of the <tt>info</tt> field are reserved for local |
2083 |
use by modules, which can take advantage of this to decouple behavioral |
2084 |
logic from actual mode characters. See the description of the Unreal |
2085 |
protocol module in <a href="5.html#s6-14">section 5-6-14</a> for an example |
2086 |
of using such local information flags.</p> |
2087 |
|
2088 |
<p>Whenever any changes are made to the mode arrays, the |
2089 |
<tt>mode_setup()</tt> routine must be called to update the internal lookup |
2090 |
tables used by the conversion functions. (<tt>mode_setup()</tt> must also |
2091 |
be called once before using any of the functions, even when the arrays are |
2092 |
not modified; but since <tt>init()</tt> takes care of this call, it is not |
2093 |
a concern in practice.)</p> |
2094 |
|
2095 |
<p class="backlink"><a href="#top">Back to top</a></p> |
2096 |
|
2097 |
|
2098 |
<h4 class="subsubsection-title" id="s6-5">2-6-5. High-level actions</h4> |
2099 |
|
2100 |
<p>The <tt>actions.c</tt> source file provides several routines which |
2101 |
implement common operations on clients and channels. While the core code |
2102 |
does not make use of these routines, they are provided to simplify |
2103 |
pseudoclient code and reduce redundancy. The routines are:</p> |
2104 |
|
2105 |
<dl> |
2106 |
<dt><tt>int <b>bad_password</b>(const char *<i>service</i>, User *<i>u</i>, |
2107 |
const char *<i>what</i>)</tt></dt> |
2108 |
<dd>Logs a bad password attempt for a client. The client is sent a |
2109 |
"password incorrect" message, and the bad password count is |
2110 |
incremented, first being cleared if at least the interval specified |
2111 |
by <tt>BadPassTimeout</tt> has passed. If the bad password count |
2112 |
reaches the limit specified by <tt>BadPassLimit</tt>, the client |
2113 |
will be killed (disconnected from the network), and a warning will |
2114 |
be sent when the count reaches one less than the limit. Returns |
2115 |
1 if the client was warned, 2 if killed, 0 otherwise.</dd> |
2116 |
|
2117 |
<dt><tt>void <b>clear_channel</b>(Channel *<i>chan</i>, int <i>what</i>, |
2118 |
const void *<i>param</i>)</tt></dt> |
2119 |
<dd>Clears modes and/or clients from a channel, depending on the |
2120 |
<tt><i>what</i></tt> and <tt><i>param</i></tt> parameters. |
2121 |
<tt><i>what</i></tt> can be any of the following flags: |
2122 |
<ul> |
2123 |
<li><b><tt>CLEAR_MODES</tt></b>: Remove all regular channel modes, |
2124 |
like <tt>+s</tt> and <tt>+l</tt>. <tt><i>param</i></tt> is |
2125 |
ignored.</li> |
2126 |
<li><b><tt>CLEAR_BANS</tt></b>: Remove all channel bans. If |
2127 |
<tt><i>param</i></tt> is not <tt>NULL</tt>, it is treated |
2128 |
as a <tt>User *</tt>, and only bans matching that |
2129 |
client are cleared.</li> |
2130 |
<li><b><tt>CLEAR_EXCEPTS</tt></b>: Remove all channel ban |
2131 |
exceptions. <tt><i>param</i></tt> is treated as for |
2132 |
<tt>CLEAR_BANS</tt>.</li> |
2133 |
<li><b><tt>CLEAR_UMODES</tt></b>: Remove channel user modes. |
2134 |
<tt><i>param</i></tt> is cast to <tt>uint32</tt> and |
2135 |
treated as the set of mode flags to clear.</li> |
2136 |
<li><b><tt>CLEAR_USERS</tt></b>: Kick all clients from the channel. |
2137 |
<tt><i>param</i></tt> is treated as a <tt>char *</tt> |
2138 |
containing the reason to use in the kick message, and must |
2139 |
not be <tt>NULL</tt>.</li> |
2140 |
</ul> |
2141 |
More than one of these flags can be combined, but for obvious |
2142 |
reasons, this only works when the same <tt><i>param</i></tt> value |
2143 |
can be used for all flags; <tt>CLEAR_UMODES</tt> cannot be used |
2144 |
with <tt>CLEAR_BANS</tt> or <tt>CLEAR_EXCEPTS</tt>, for example. |
2145 |
There is also a callback provided by this function, named |
2146 |
"<tt>clear channel</tt>", which takes precedence over the |
2147 |
standard processing (<tt>CLEAR_EXCEPTS</tt> in particular must be |
2148 |
implemented via callback since it is not an RFC-standard feature).</dd> |
2149 |
|
2150 |
<dt><tt>const char *<b>set_clear_channel_sender</b>(const char *<i>newsender</i>)</tt></dt> |
2151 |
<dd>Sets the name (typically a pseudoclient nickname) used as the |
2152 |
sender in messages generated by <tt>clear_channel()</tt>, and |
2153 |
returns the old sender name. If <tt><i>newsender</i></tt> is |
2154 |
<tt>NULL</tt>, the server name is used as the sender, which is the |
2155 |
default behavior. <tt><i>newsender</i></tt> can also be specified |
2156 |
as <tt>PTR_INVALID</tt> to retrieve the current sender name without |
2157 |
changing it.</dd> |
2158 |
|
2159 |
<dt><tt>void <b>kill_user</b>(const char *<i>source</i>, |
2160 |
const char *<i>user</i>, const char *<i>reason</i>)</tt></dt> |
2161 |
<dd>Kills the specified client from the IRC network. |
2162 |
<tt><i>source</i></tt> is used as the message sender, and |
2163 |
<tt><i>reason</i></tt> is the reason string for the <tt>KILL</tt> |
2164 |
message.</dd> |
2165 |
|
2166 |
<dt><tt>void <b>set_topic</b>(const char *<i>source</i>, Channel *<i>c</i>, |
2167 |
const char *<i>topic</i>, const char *<i>setter</i>, time_t <i>t</i>)</tt></dt> |
2168 |
<dd>Sets the topic on the specified channel. This function calls a |
2169 |
callback ("<tt>set topic</tt>") to perform its work, since |
2170 |
different protocols have different methods for setting channel |
2171 |
topics; in particular, some protocols ignore channel topic changes |
2172 |
depending on the timestamp used in the <tt>TOPIC</tt> message.</dd> |
2173 |
|
2174 |
<dt><tt>void <b>set_cmode</b>(const char *<i>sender</i>, Channel *<i>channel</i>, ...)</tt></dt> |
2175 |
<dd>Sets modes on a channel, including channel user modes. This |
2176 |
function accumulates multiple mode changes for the same channel in |
2177 |
a buffer, only sending out a <tt>MODE</tt> message when instructed |
2178 |
to or when necessary (when the number of parameters to the message |
2179 |
exceeds the maximum of 6, or when the number of channels with |
2180 |
cached mode changes exceeds the limit set by |
2181 |
<tt>MERGE_CHANMODES_MAX</tt> in <tt>defs.h</tt>). The routine also |
2182 |
tries to be "smart" about multiple changes for the same mode, and |
2183 |
if it sees a mode change that renders a previous change meaningless, |
2184 |
it will remove that previous change without ever sending it to the |
2185 |
network. There are two ways to call the function: |
2186 |
<ul> |
2187 |
<li><b><tt>set_cmode(<i>sender</i>, <i>channel</i>, <i>modes</i>, |
2188 |
<i>param0</i>, <i>param1</i>, ...)</tt>:</b> Ordinary |
2189 |
operation, with a non-<tt>NULL</tt> value for |
2190 |
<tt><i>sender</i></tt>. <tt><i>modes</i></tt> is passed |
2191 |
as an ordinary mode change string, such as |
2192 |
"<tt>+nst-il+k</tt>", and any parameters for the modes are |
2193 |
passed in the order the mode characters appear in |
2194 |
<tt><i>modes</i></tt>, as for an IRC <tt>MODE</tt> message. |
2195 |
Note that all parameters, including numeric parameters, |
2196 |
must be passed as strings.</li> |
2197 |
<li><b><tt>set_cmode(NULL, <i>channel</i>)</tt>:</b> Flush out |
2198 |
accumulated mode changes for the given channel. If |
2199 |
<tt><i>channel</i></tt> is also <tt>NULL</tt>, accumulated |
2200 |
mode changes for all channels are flushed out.</li> |
2201 |
</ul> |
2202 |
|
2203 |
<p>Internally, <tt>set_cmode()</tt> uses a <tt>modedata</tt> |
2204 |
structure to keep track of each set of mode changes for a channel. |
2205 |
Simple binary modes are stored as sets of flags to add and remove |
2206 |
(<tt>binmodes_on</tt> and <tt>binmodes_off</tt>), while modes that |
2207 |
take parameters are accumulated in two arrays: <tt>opmodes[]</tt>, |
2208 |
containing each mode character prefixed by a <tt>+</tt> or |
2209 |
<tt>-</tt>, and <tt>params[]</tt>, containing the parameters for |
2210 |
each mode (space-separated if the mode takes two or more |
2211 |
parameters). For mode-with-parameters number <tt><i>n</i></tt>, |
2212 |
<tt>opmodes[2*<i>n</i>]</tt> is either "<tt>+</tt>" or |
2213 |
"<tt>-</tt>", <tt>opmodes[2*<i>n</i>+1]</tt> is the mode character |
2214 |
itself, and <tt>params[<i>n</i>]</tt> is the string holding the |
2215 |
mode's parameters.</p> |
2216 |
|
2217 |
<p><tt>set_cmode()</tt> processes each mode character in turn, |
2218 |
watching for "<tt>+</tt>" or "<tt>-</tt>" to indicate whether the |
2219 |
modes are being added or removed. Binary modes are simply added |
2220 |
to the appropriate <tt>binmodes</tt> field; modes with parameters |
2221 |
are appended to the <tt>opmodes[]</tt> and <tt>params[]</tt> |
2222 |
arrays, with a flush being performed if the number of mode |
2223 |
parameters exceeds the RFC-defined limit of 6 or the total length |
2224 |
of the parameters exceeds a maximum derived as the RFC line length |
2225 |
limit of 510 characters less the maximum length of the other parts |
2226 |
of the <tt>MODE</tt> message.</p> |
2227 |
|
2228 |
<p>If the <tt>MergeChannelModes</tt> option is set, |
2229 |
<tt>set_cmode</tt> will also set a timeout for flushing the modes |
2230 |
out to the network (see <a href="#s7">section 2-7</a> for details |
2231 |
on timeouts).</p> |
2232 |
|
2233 |
<p>When modes need to be flushed out, whether due to a full |
2234 |
message, a timeout, or a manual flush with |
2235 |
<tt><i>sender</i>==NULL</tt>, the <tt>flush_cmode()</tt> routine is |
2236 |
called. This routine collects all accumulated modes into a string: |
2237 |
binary modes are written first (with mode removals before mode |
2238 |
additions, since at least some IRC server software ignores a |
2239 |
<tt>+s</tt> when sent after a <tt>-p</tt>), followed by modes with |
2240 |
parameters in the order they were accumulated. The generated |
2241 |
<tt>MODE</tt> message is then sent out to the network, and the |
2242 |
<tt>modedata</tt> structure is cleared so that it can be reused.</p></dd> |
2243 |
</dl> |
2244 |
|
2245 |
<p class="backlink"><a href="#top">Back to top</a></p> |
2246 |
|
2247 |
<!------------------------------------------------------------------------> |
2248 |
<hr/> |
2249 |
|
2250 |
<h3 class="subsection-title" id="s7">2-7. Timed events</h3> |
2251 |
|
2252 |
<p>While most events in Services happen synchronously, such as in response |
2253 |
to a message from the IRC network, it is sometimes necessary to schedule |
2254 |
actions to occur at a later time. This is accomplished through the use of |
2255 |
timed events, called <i>timeouts</i>. Timeouts are implemented by the |
2256 |
source files <tt>timeout.c</tt> and <tt>timeout.h</tt>.</p> |
2257 |
|
2258 |
<p>To create a new timeout, call <tt>add_timeout()</tt> or |
2259 |
<tt>add_timeout_ms()</tt>, both of which function identically except that |
2260 |
the former uses units of seconds while the latter uses milliseconds (in |
2261 |
fact, <tt>add_timeout()</tt> is implemented in terms of |
2262 |
<tt>add_timeout_ms()</tt>). These functions take a pointer to the routine |
2263 |
to be called when the timeout expires, and a <tt><i>repeat</i></tt> flag |
2264 |
which, if nonzero, causes the timeout to restart at the given delay value |
2265 |
when it expires (normally, the timeout is removed after it expires and the |
2266 |
timeout routine is called). The functions return a pointer to a |
2267 |
<tt>Timeout</tt> structure, which is also passed to the timeout routine |
2268 |
when it is called. If the caller needs to pass extra data to the timeout |
2269 |
routine, the <tt>data</tt> field can be set to an arbitrary value; this |
2270 |
must be done before the routine that added the timeout returns (more |
2271 |
precisely, before the next time <tt>check_timeouts()</tt> is |
2272 |
called) in order to avoid a race condition. <i>Implementation note: The |
2273 |
maximum delay on a timeout is 2^31-1 milliseconds, or about 25 days. This |
2274 |
is due to the 32-bit width of the <tt>time_msec()</tt> return value; any |
2275 |
time 2^31 milliseconds or more in the future will be treated as in the past |
2276 |
due to signed difference comparison.</i></p> |
2277 |
|
2278 |
<p>Since Services is a single-threaded program, timeouts have to be checked |
2279 |
for manually at periodic intervals. This is done by calling the |
2280 |
<tt>check_timeouts()</tt> function; the main loop of Services calls this |
2281 |
at intervals specified by the <tt>TimeoutCheck</tt> configuration |
2282 |
directive. (As a consequence, timeouts will only have a resolution equal |
2283 |
to <tt>TimeoutCheck</tt>—if <tt>TimeoutCheck</tt> is specified as 3 |
2284 |
seconds, for example, a timeout specified for 1 millisecond can still take |
2285 |
up to 3 seconds to be executed.) Upon being called, |
2286 |
<tt>check_timeouts()</tt> iterates through the linked list of timeouts, |
2287 |
checking for any that have expired. For such timeouts, the timeout's |
2288 |
expiration routine is called, passing a pointer to the <tt>Timeout</tt> |
2289 |
structure as a parameter, then the timeout is either restarted (if it is |
2290 |
specified as a repeating timeout) or deleted.</p> |
2291 |
|
2292 |
<p>The timeout routines guarantee that a new timeout added from a timeout |
2293 |
routine will not be checked during that run of <tt>check_timeouts()</tt>. |
2294 |
Internally, this is ensured by always adding new timeouts at the head of |
2295 |
the timeout list.</p> |
2296 |
|
2297 |
<p>If a timeout needs to be deleted before it expires, the |
2298 |
<tt>del_timeout()</tt> function can be used. This function can also be |
2299 |
used to delete a repeating timeout from the timeout's own expiration |
2300 |
routine (or even a non-repeating timeout, though since the timeout would |
2301 |
be deleted anyway it would serve no purpose). To avoid dangling |
2302 |
pointers, <tt>del_timeout()</tt> does not actually delete any timeouts |
2303 |
during a <tt>check_timeouts()</tt> run; instead, it clears the timeout's |
2304 |
internal <tt>timeout</tt> field (which holds the time in milliseconds when |
2305 |
the timeout is set to expire) to zero, causing <tt>check_timeouts()</tt> to |
2306 |
delete the timeout when it is reached during list iteration.</p> |
2307 |
|
2308 |
<p>There is also a function <tt>send_timeout_list()</tt>, intended for |
2309 |
debugging (and only available if <tt>DEBUG_COMMANDS</tt> is defined), which |
2310 |
sends the current timeout list to the given client as <tt>NOTICE</tt> |
2311 |
messages.</p> |
2312 |
|
2313 |
<p class="backlink"><a href="#top">Back to top</a></p> |
2314 |
|
2315 |
<!------------------------------------------------------------------------> |
2316 |
<hr/> |
2317 |
|
2318 |
<h3 class="subsection-title" id="s8">2-8. Multilingual support</h3> |
2319 |
|
2320 |
<p>In order to provide a more natural interface for users who speak |
2321 |
different languages, Services includes the ability to send messages in any |
2322 |
of several languages. This functionality is implemented in the |
2323 |
<tt>language.c</tt> and <tt>language.h</tt> source files, and the actual |
2324 |
text used for each language is stored in the <tt>lang</tt> subdirectory.</p> |
2325 |
|
2326 |
<p class="backlink"><a href="#top">Back to top</a></p> |
2327 |
|
2328 |
|
2329 |
<h4 class="subsubsection-title" id="s8-1">2-8-1. Overview</h4> |
2330 |
|
2331 |
<p>The multilingual support system in Services uses tables of strings to |
2332 |
accomplish "translation" of messages. These tables are indexed by named |
2333 |
constants, listed in the automatically-generated <tt>langstrs.h</tt> header |
2334 |
file (see <a href="10.html#s3-3">section 10-3-3</a> for details on how this |
2335 |
file is generated); a routine that wants to take advantage of multilingual |
2336 |
support can then use the appropriate message index to obtain a translated |
2337 |
message.</p> |
2338 |
|
2339 |
<p>There is no on-the-fly translation, of course; all messages used with |
2340 |
multilingual support must be prepared ahead of time. These messages are |
2341 |
stored in data files in the <tt>lang</tt> subdirectory, which are |
2342 |
precompiled for efficiency and loaded into Services at runtime. It is also |
2343 |
possible to add new strings to the string tables, or modify the precompiled |
2344 |
strings, on the fly; however, all such strings must likewise be prepared |
2345 |
ahead of time (or otherwise generated by the code calling the multilingual |
2346 |
routines).</p> |
2347 |
|
2348 |
<p class="backlink"><a href="#top">Back to top</a></p> |
2349 |
|
2350 |
|
2351 |
<h4 class="subsubsection-title" id="s8-2">2-8-2. Using multilingual strings</h4> |
2352 |
|
2353 |
<p>Before being used, the multilingual support subsystem must first be |
2354 |
initialized by calling <tt>lang_init()</tt>. This routine sets up the |
2355 |
internal string tables, then loads each language's precompiled data file |
2356 |
from the <tt>languages</tt> subdirectory of the data directory; the |
2357 |
filenames are hardcoded in the <tt>filenames[]</tt> array. The |
2358 |
<tt>lang_cleanup()</tt> function takes care of freeing these resources.</p> |
2359 |
|
2360 |
<p>The precompiled data files consist of a string count, a table of offsets |
2361 |
to the strings, and the strings themselves separated by null bytes. For |
2362 |
the sake of efficiency, the entire string data is loaded into a single |
2363 |
block of memory, a pointer to which is stored at index 0 of each language's |
2364 |
string table; pointers to individual strings are then calculated from the |
2365 |
string offset table in the file, and the pointer to the text for string |
2366 |
index <i>n</i> is stored at array index <i>n</i>+1. <i>Implementation |
2367 |
note: This is admittedly a rather confusing approach, and probably came |
2368 |
about from reluctance to introduce yet another file-scope array.</i></p> |
2369 |
|
2370 |
<p>Once the language data has been loaded, several functions are available |
2371 |
to make use of multilingual strings. The simplest of these is |
2372 |
<tt>getstring()</tt> and its companion <tt>getstring_lang()</tt>, which |
2373 |
simply return the text associated with the selected string index. The |
2374 |
<tt>getstring()</tt> routine uses a nickname group record, |
2375 |
<tt>NickGroupInfo *</tt>, to select the language, while |
2376 |
<tt>getstring_lang()</tt> uses the language index directly. (Language |
2377 |
index values can be obtained with the <tt>lookup_language()</tt> function, |
2378 |
using the name of a language—the same as the precompiled data file |
2379 |
name; see also <a href="#s8-4">section 2-8-4</a>—to retrieve the |
2380 |
index, or the <tt>LANG_*</tt> constants in <tt>language.h</tt> can be used |
2381 |
directly.)</p> |
2382 |
|
2383 |
<p><i>Implementation note: With the exception of <tt>getstring_lang()</tt>, |
2384 |
all of the string retrieval functions use nickname group records rather |
2385 |
than language index values to select the language. This stems from the |
2386 |
fact that users' language preferences are recorded as part of the nickname |
2387 |
group record for the user's registered nickname, but is arguably poor |
2388 |
design, with core code relying on the internal data structure of a |
2389 |
module.</i></p> |
2390 |
|
2391 |
<p>For obvious reasons, the strings returned by <tt>getstring()</tt> are |
2392 |
generally used in messages sent to users. For this reason, the routines |
2393 |
<tt>notice_lang()</tt> and <tt>notice_help()</tt> are provided by the |
2394 |
<tt>send.c</tt> source file to simplify the operation of retrieving a |
2395 |
string in the user's selected language and sending it as a <tt>NOTICE</tt>. |
2396 |
The routines can handle newlines in the strings as well, breaking the |
2397 |
strings up into separate <tt>NOTICE</tt> messages at the newlines. The |
2398 |
difference between the functions is that <tt>notice_help()</tt> replaces |
2399 |
the "<tt>%S</tt>" token in the string (a capital <tt>S</tt>, not a |
2400 |
lowercase <tt>s</tt>) by the nickname used to send the messages; this makes |
2401 |
it easy to refer to a pseudoclient's own nickname in help messages.</p> |
2402 |
|
2403 |
<p>Both <tt>notice_lang()</tt> and <tt>notice_help()</tt> treat the |
2404 |
strings returned by <tt>getstring()</tt> as <tt>printf()</tt>-style format |
2405 |
strings, and accept variadic argument lists in the same style as the basic |
2406 |
<tt>notice()</tt> function. This does, however, present a problem for |
2407 |
multilingual support: different languages have different word orders, while |
2408 |
the order of format parameters cannot be changed around to match the |
2409 |
language. Translators must therefore be careful to maintain the same token |
2410 |
order when translating strings, though this may result in slightly |
2411 |
unnatural text.</p> |
2412 |
|
2413 |
<p>One other shortcut function for sending messages to users is the |
2414 |
<tt>syntax_error()</tt> function. This function takes a command name |
2415 |
and a string index containing a syntax message, and sends a two-line |
2416 |
<tt>NOTICE</tt> of the form:</p> |
2417 |
|
2418 |
<div class="code">-Service- Syntax: <b>COMMAND <span style="text-decoration: underline">parameter-1</span> <span style="text-decoration: underline">parameter-2</span>...</b> |
2419 |
-Service- Type <b>/msg Service HELP COMMAND</b> for more information.</div> |
2420 |
|
2421 |
<p>The first line uses the <tt>SYNTAX_ERROR</tt> string, inserting the |
2422 |
syntax string passed to the routine, and the second uses <tt>MORE_HELP</tt>, |
2423 |
inserting the pseudoclient nickname and command name.</p> |
2424 |
|
2425 |
<p>In addition, there are three functions which operate on time values. |
2426 |
<tt>strftime_lang()</tt> is a multilingual version of the standard |
2427 |
<tt>strftime()</tt> function, generating a string describing a specific |
2428 |
date and time using the language specified by the nickname group record |
2429 |
passed in; the format string, of course, is specified by a string index |
2430 |
rather than a literal string pointer. The <tt>%a</tt>, <tt>%A</tt>, |
2431 |
<tt>%b</tt>, and <tt>%B</tt> tokens are treated specially: rather than |
2432 |
passing them directly to <tt>strftime()</tt> (which would always return |
2433 |
the same weekday and month names), they are translated by |
2434 |
<tt>strftime_lang()</tt>, using the <tt>STRFTIME_DAYS_SHORT</tt>, |
2435 |
<tt>STRFTIME_DAYS_LONG</tt>, <tt>STRFTIME_MONTHS_SHORT</tt>, and |
2436 |
<tt>STRFTIME_MONTHS_LONG</tt> strings, respectively. Each of these |
2437 |
strings is assumed to be a newline-separated list of weekday or month |
2438 |
names, and the appropriate name is selected based on the time passed to the |
2439 |
function.</p> |
2440 |
|
2441 |
<p><tt>maketime()</tt> takes a time interval (the parameter type is |
2442 |
<tt>time_t</tt>, but it is simply a count of seconds, not a timestamp) and |
2443 |
and generates a "human-readable" string describing that time interval: for |
2444 |
example, a value of 3716 seconds might be described simply as "1 hour", or |
2445 |
as "1 hour, 2 minutes" (using the relevant language strings, as listed |
2446 |
below). By default, <tt>maketime()</tt> does not display seconds, so an |
2447 |
interval of less than 60 seconds will be rounded up to "1 minute"; this |
2448 |
behavior can be changed by specifying the <tt>MT_SECONDS</tt> flag when |
2449 |
calling the function. Also, <tt>maketime()</tt> normally only describes |
2450 |
the interval using the largest relevant unit (days, hours, minutes, or |
2451 |
seconds), but a second unit can be added, as in the "1 hour, 2 minutes" |
2452 |
example above, by specifying the <tt>MT_DUALUNIT</tt> flag. The following |
2453 |
strings are used by this function—note in particular the inclusion |
2454 |
of spaces before the unit names, since some languages do not use them:</p> |
2455 |
<ul> |
2456 |
<li><b><tt>STR_SECOND</tt>:</b> "<tt> second</tt>" (for exactly 1 second)</li> |
2457 |
<li><b><tt>STR_SECONDS</tt>:</b> "<tt> seconds</tt>" (for other numbers of seconds)</li> |
2458 |
<li><b><tt>STR_MINUTE</tt>:</b> "<tt> minute</tt>" (for exactly 1 minute)</li> |
2459 |
<li><b><tt>STR_MINUTES</tt>:</b> "<tt> minutes</tt>" (for other numbers of minutes)</li> |
2460 |
<li><b><tt>STR_HOUR</tt>:</b> "<tt> hour</tt>" (for exactly 1 hour)</li> |
2461 |
<li><b><tt>STR_HOURS</tt>:</b> "<tt> hours</tt>" (for other numbers of hours)</li> |
2462 |
<li><b><tt>STR_DAY</tt>:</b> "<tt> day</tt>" (for exactly 1 day)</li> |
2463 |
<li><b><tt>STR_DAYS</tt>:</b> "<tt> days</tt>" (for other numbers of days)</li> |
2464 |
<li><b><tt>STR_TIMESEP</tt>:</b> the separator between units, such as "<tt>, </tt>" (comma and space)</li> |
2465 |
</ul> |
2466 |
|
2467 |
<p><tt>maketime()</tt> returns its result in a static buffer, so the string |
2468 |
should be copied elsewhere if it will be needed at a later time, or if two |
2469 |
or more consecutive calls are made.</p> |
2470 |
|
2471 |
<p>The last function, <tt>expires_in_lang()</tt>, takes an expiration |
2472 |
timestamp and returns a string describing how long it will be before that |
2473 |
expiration time arrives. Generally, this is just the result of |
2474 |
<tt>maketime()</tt> called with <tt>MT_DUALUNIT</tt> on the difference |
2475 |
between the current time and the given expiration time, but if the |
2476 |
timestamp is zero (meaning no expiration), then the <tt>EXPIRES_NONE</tt> |
2477 |
string ("never expires") is returned instead. If the given time has |
2478 |
already passed, it is treated as an interval of 1 second, unless expiration |
2479 |
has been disabled via the <tt>-noexpire</tt> command-line option, in which |
2480 |
case the <tt>EXPIRES_NOW</tt> string ("expired") is returned.</p> |
2481 |
|
2482 |
<p class="backlink"><a href="#top">Back to top</a></p> |
2483 |
|
2484 |
|
2485 |
<h4 class="subsubsection-title" id="s8-3">2-8-3. Modifying the string table at runtime</h4> |
2486 |
|
2487 |
<p>There are three ways to modify the string table while Services is |
2488 |
running: string mapping, explicit string setting, and external language |
2489 |
files.</p> |
2490 |
|
2491 |
<p>The simplest way to change multilingual strings is through string |
2492 |
mapping, which causes requests for one string index to return a different |
2493 |
string. The advantage of string mapping is that a single operation changes |
2494 |
the contents of the string for all languages; however, mapping only works |
2495 |
with strings which are already present in the string tables.</p> |
2496 |
|
2497 |
<p>String mapping is performed with the <tt>mapstring()</tt> routine. |
2498 |
After calling this routine with the string index to modify |
2499 |
(<tt><i>old</i></tt>) and the new string to return for that index |
2500 |
(<tt><i>new</i></tt>), all requests to <tt>getstring()</tt> or other |
2501 |
text retrieval functions for <tt><i>old</i></tt> will instead return the |
2502 |
text of <tt><i>new</i></tt> in the same language. <tt>mapstring()</tt> |
2503 |
returns the previous mapping of <tt><i>old</i></tt> (which will be equal |
2504 |
to <tt><i>old</i></tt> if no previous mapping had been performed), which |
2505 |
can be used to cancel the mapping:</p> |
2506 |
|
2507 |
<div class="code">static int old_STRING1 = -1; |
2508 |
int my_init() { |
2509 |
// ... |
2510 |
old_STRING1 = mapstring(STRING1, STRING2); |
2511 |
return 1; |
2512 |
} |
2513 |
void my_cleanup() { |
2514 |
if (old_STRING1 >= 0) { |
2515 |
mapstring(STRING1, old_STRING1); |
2516 |
old_STRING1 = -1; |
2517 |
} |
2518 |
// ... |
2519 |
}</div> |
2520 |
|
2521 |
<p>Mapping is used most often to change the text of pseudoclient replies or |
2522 |
help messages based on configuration settings or protocol features, by |
2523 |
writing two or more versions of the message ahead of time and mapping the |
2524 |
appropriate one to the base string as necessary; this allows a single |
2525 |
string index to be used without having to check the relevant options or |
2526 |
protocol features every time.</p> |
2527 |
|
2528 |
<p><i>Implementation note: Unexpected results can occur if unmaps are not |
2529 |
performed in the proper order. A solution might be to have |
2530 |
<tt>mapstring()</tt> keep track of all maps internally and return a |
2531 |
"mapping ID" to the caller; calling a new function <tt>unmapstring()</tt> |
2532 |
with the mapping ID would then remove that particular mapping from the |
2533 |
mapping stack.</i></p> |
2534 |
|
2535 |
<p>When more versatility with the replacement strings is needed, and |
2536 |
particularly when a module wants to add new strings to the string tables, |
2537 |
the <tt>setstring()</tt> and <tt>addstring()</tt> routines can be used. |
2538 |
<tt>setstring()</tt> allows the contents of a string in a specific language |
2539 |
to be set to any arbitrary text, while <tt>addstring()</tt> creates a new, |
2540 |
initially empty, string in the string table, returning the new string's |
2541 |
index (which can then be used with <tt>setstring()</tt> and the other |
2542 |
multilingual support functions, just as with the built-in strings).</p> |
2543 |
|
2544 |
<p>However, a problem crops up when using <tt>addstring()</tt> to add new |
2545 |
strings: the string's index is not constant. It is, of course, possible to |
2546 |
export a variable containing the index to any source file that needs it, |
2547 |
but a cleaner approach is to call the <tt>lookup_string()</tt> function |
2548 |
with the same name given to the <tt>addstring()</tt> function, which |
2549 |
returns the index corresponding to the given string name. |
2550 |
<tt>lookup_string()</tt> also works with built-in strings, using the |
2551 |
constant name as the string (so, for example, the result of |
2552 |
<tt>lookup_string("SYNTAX_ERROR")</tt> would be the value of the constant |
2553 |
<tt>SYNTAX_ERROR</tt>).</p> |
2554 |
|
2555 |
<p>When a module adds many new strings to the string table, it can be |
2556 |
inconvenient to call <tt>addstring()</tt> and <tt>setstring()</tt> for |
2557 |
every string. To avoid this hassle, the <tt>load_ext_lang()</tt> function |
2558 |
is provided to load "external language files", text files containing |
2559 |
language string data. The format of these files is essentially the same as |
2560 |
the base language source flies (see <a href="#s8-4">section 2-8-4</a> |
2561 |
below), with the exception that the language name is also included on the |
2562 |
line containing the string name, separated from the string name by |
2563 |
whitespace. This function is called to load external language files |
2564 |
specified with the <tt>LoadLanguageText</tt> configuration directive.</p> |
2565 |
|
2566 |
<p>There is also a <tt>reset_ext_lang()</tt> routine, which clears out all |
2567 |
changes made with <tt>setstring()</tt> and <tt>load_ext_lang()</tt>; |
2568 |
strings added to the string table with <tt>addstring()</tt> are left in, |
2569 |
with their contents cleared to empty strings. However, outside of the |
2570 |
<tt>lang_init()</tt> and <tt>lang_cleanup()</tt> functions, this is only |
2571 |
called by the reconfiguration code in <tt>init.c</tt>, and should not be |
2572 |
called by modules.</p> |
2573 |
|
2574 |
<p><i>Implementation note: It probably shouldn't be called during |
2575 |
reconfiguration, either, since it blows away anything modules may have |
2576 |
changed in their initialization routines. As a consequence, third-party |
2577 |
modules should not use <tt>setstring()</tt> or <tt>load_ext_lang()</tt> at |
2578 |
all, and should instead rely on the <tt>LoadLanguageText</tt> directive to |
2579 |
load text for any strings that they add.</i></p> |
2580 |
|
2581 |
<p class="backlink"><a href="#top">Back to top</a></p> |
2582 |
|
2583 |
|
2584 |
<h4 class="subsubsection-title" id="s8-4">2-8-4. The language file compiler</h4> |
2585 |
|
2586 |
<p>The text files which define the base language strings are stored in the |
2587 |
<tt>lang</tt> subdirectory of the top source code directory, one for each |
2588 |
language: <tt>en_us.l</tt>, <tt>de.l</tt>, and so on. The format of these |
2589 |
files is fairly simple, consisting of a series of string names followed by |
2590 |
their contents (blank lines, and lines beginning with the "<tt>#</tt>" |
2591 |
character, are ignored). For each string, the string name is placed alone |
2592 |
on a line, followed by one or more lines of message text; each line of |
2593 |
message text must begin with the tab character (ASCII code 9)—spaces |
2594 |
are not permitted. If two or more lines are given, they are joined by |
2595 |
linefeed (ASCII code 10, standard Unix newline) characters.</p> |
2596 |
|
2597 |
<p>Rather than manually parsing these files each time Services is loaded, |
2598 |
however, they are precompiled into binary data files by the |
2599 |
<tt>langcomp</tt> program, compiled from <tt>langcomp.c</tt> in the |
2600 |
<tt>lang</tt> subdirectory. This program reads in a language source file |
2601 |
specified as a command-line argument, and (if no errors are encountered) |
2602 |
writes out the precompiled binary data for that file to the same filename |
2603 |
with the extension stripped; for example, <tt>langcomp en_us.l</tt> |
2604 |
creates the file <tt>en_us</tt>, and so forth.</p> |
2605 |
|
2606 |
<p>In order to ensure that the strings are written in the correct order |
2607 |
regardless of the order in which they appear in the source file, |
2608 |
<tt>langcomp</tt> relies on a file named <tt>index</tt>, which contains a |
2609 |
list of all string names in the order they should be stored. (As described |
2610 |
in <a href="10.html#s3-3">section 10-3-3</a>, this file is generated |
2611 |
automatically from <tt>en_us.l</tt>, which is treated as the canonical |
2612 |
language file.) If <tt>langcomp</tt> encounters a string name which is not |
2613 |
listed in this file, it reports an error and does not generate an output |
2614 |
file. It is also possible to get warnings on strings listed in |
2615 |
<tt>index</tt> but missing from the language file, by passing the |
2616 |
<tt>-w</tt> option to <tt>langcomp</tt>. <i>Implementation note: One |
2617 |
problem that has occurred frequently is forgetting to insert a tab at the |
2618 |
beginning of a blank line intended to be part of a message. It might be a |
2619 |
good idea to have <tt>langcomp -w</tt> warn about such cases as well.</i></p> |
2620 |
|
2621 |
<p>To make certain that the core source code and modules also use the same |
2622 |
string order and index values, the <tt>index</tt> file is also used to |
2623 |
generate a header file, <tt>langstrs.h</tt>, which is included by |
2624 |
<tt>language.h</tt>. This file contains <tt>#define</tt> directives to |
2625 |
define the string index constants; if the preprocessor macro |
2626 |
<tt>LANGSTR_ARRAY</tt> is defined when the file is included, then it also |
2627 |
defines an array containing the string names as C strings |
2628 |
(<tt>language.c</tt> uses this to implement the <tt>lookup_string()</tt> |
2629 |
function).</p> |
2630 |
|
2631 |
|
2632 |
<p class="backlink"><a href="#top">Back to top</a></p> |
2633 |
|
2634 |
<!------------------------------------------------------------------------> |
2635 |
<hr/> |
2636 |
|
2637 |
<h3 class="subsection-title" id="s9">2-9. Module interfaces</h3> |
2638 |
|
2639 |
<p>While many modules in Services perform their own independent functions, |
2640 |
there are some sets of modules which implement the same functionality in |
2641 |
alternative ways. Protocol methods are the most obvious example of this, |
2642 |
and the core code provides an interface to these modules, as described in |
2643 |
section <a href="#s5-1">2-5-1</a>. This section covers the core interfaces |
2644 |
to two more such sets of modules: encryption modules and database modules. |
2645 |
Unlike protocol modules, encryption and databases are not used by the core |
2646 |
code, but interfaces are supplied to simplify the design of modules which |
2647 |
do make use of them.</p> |
2648 |
|
2649 |
<p class="backlink"><a href="#top">Back to top</a></p> |
2650 |
|
2651 |
|
2652 |
<h4 class="subsubsection-title" id="s9-1">2-9-1. Encryption</h4> |
2653 |
|
2654 |
<p>Encryption modules are used by the Services pseudoclients to encrypt |
2655 |
passwords, reducing the danger of passwords leaking as a result of improper |
2656 |
access to the databases. While the encryption modules themselves can |
2657 |
encrypt any arbitrary data, the core interface explicitly uses the context |
2658 |
of passwords. The interface is implemented by <tt>encrypt.c</tt> and |
2659 |
<tt>encrypt.h</tt>.</p> |
2660 |
|
2661 |
<p>At the center of the interface is the <tt>Password</tt> structure, |
2662 |
defined in <tt>encrypt.h</tt>. This structure contains a buffer for the |
2663 |
encrypted password itself, along with a string pointer identifying the |
2664 |
cipher used to encrypt the password; this allows passwords using different |
2665 |
ciphers to be mixed in the same set of data and still be decrypted/checked, |
2666 |
assuming a module implementing the cipher is available. The cipher may be |
2667 |
<tt>NULL</tt>, indicating that the password is not encrypted.</p> |
2668 |
|
2669 |
<p><tt>Password</tt> structures can be allocated either dynamically or |
2670 |
statically. Dynamic <tt>Password</tt> structures can be obtained with the |
2671 |
<tt>new_password()</tt> function and freed with the <tt>free_password()</tt> |
2672 |
function; static variables can be initialized with <tt>init_password()</tt> |
2673 |
and cleared with <tt>clear_password()</tt>. <tt>clear_password()</tt> can |
2674 |
also be used at any time to clear the contents of a <tt>Password</tt> |
2675 |
structure when they are no longer needed.</p> |
2676 |
|
2677 |
<p>Encryption of plaintext password strings into <tt>Password</tt> |
2678 |
structures is done with the <tt>encrypt_password</tt> function. This |
2679 |
function uses the cipher named by the <tt>EncryptionType</tt> configuration |
2680 |
directive to encrypt the password, returning an error if no module has |
2681 |
registered that cipher (see below). The inverse function, |
2682 |
<tt>decrypt_password()</tt>, is also available, but should only be used |
2683 |
when there is a need to view the plaintext password itself (for example, |
2684 |
the NickServ and ChanServ <tt>GETPASS</tt> commands use this function). |
2685 |
Checking whether a user-entered password is correct can be accomplished |
2686 |
through the <tt>check_password()</tt> function without decrypting the |
2687 |
encrypted password.</p> |
2688 |
|
2689 |
<p>To set the contents of a <tt>Password</tt> structure to particular |
2690 |
values, such as when reading them from an external source, call |
2691 |
<tt>set_password()</tt>. (Make sure to zero out the original data |
2692 |
afterwards if it will no longer be used, so a copy of the password data |
2693 |
does not remain in memory.) When writing or storing the contents of a |
2694 |
<tt>Password</tt> structure elsewhere, the structure members may be |
2695 |
accessed directly; however, make certain you treat the <tt>password[]</tt> |
2696 |
field as a binary buffer, not a string (<i>e.g.,</i> use <tt>memcpy()</tt> |
2697 |
rather than <tt>strcpy()</tt> to copy it), and remember to check whether |
2698 |
the <tt>cipher</tt> field is <tt>NULL</tt> before accessing it. The |
2699 |
<tt>copy_password()</tt> function is also available for copying data from |
2700 |
one <tt>Password</tt> structure to another.</p> |
2701 |
|
2702 |
<p>When a module implementing an encryption cipher is loaded, it should |
2703 |
call <tt>register_cipher()</tt> with a pointer to a <tt>CipherInfo</tt> |
2704 |
structure that gives the cipher's name (a string identifying the cipher |
2705 |
for use in passwords' cipher fields and the <tt>EncryptionType</tt> |
2706 |
directive) and the functions which implement encryption, decryption, |
2707 |
and password checking. The module must also be certain to call |
2708 |
<tt>unregister_cipher()</tt> with the same <tt>CipherInfo</tt> structure |
2709 |
before being unloaded, or the encryption interface may attempt to call |
2710 |
routines which are no longer present in memory.</p> |
2711 |
|
2712 |
<p><i>Implementation note: It might be cleverer and more foolproof to |
2713 |
define a particular identifier to be used/exported for the CipherInfo |
2714 |
structure, then add a load-module hook and automatically register the |
2715 |
cipher if the identifier is found, unregistering it when the module is |
2716 |
unloaded.</i></p> |
2717 |
|
2718 |
<p class="backlink"><a href="#top">Back to top</a></p> |
2719 |
|
2720 |
|
2721 |
<h4 class="subsubsection-title" id="s9-2">2-9-2. Database storage</h4> |
2722 |
|
2723 |
<p>The files <tt>databases.c</tt> and <tt>databases.h</tt> define a common |
2724 |
interface for storing persistent data. Modules that want to use this |
2725 |
interface do so by defining data tables describing the data to be stored |
2726 |
and how to access it; see <a href="6.html#s2">section 6-2</a> for details.</p> |
2727 |
|
2728 |
<p>The database interface itself is quite simple. A module wishing to |
2729 |
have a data table stored in persistent storage calls the |
2730 |
<tt>register_dbtable()</tt> function (and must, of course, call |
2731 |
<tt>unregister_dbtable()</tt> for the same table before being unloaded). |
2732 |
Registering a table will cause the table's contents to be automatically |
2733 |
loaded from persistent storage (if no database module is available, the |
2734 |
table load will occur when a database module is registered). This is all |
2735 |
that the calling module needs to do; the database subsystem will take care |
2736 |
of the rest. It is, however, important to note that unregistering a |
2737 |
database table will <i>not</i> cause it to be written out; if a write |
2738 |
before close is desired, it must be done manually as described below.</p> |
2739 |
|
2740 |
<p>Actual writing of the registered database tables to persistent storage |
2741 |
is accomplished by calling the <tt>save_all_dbtables()</tt> function. The |
2742 |
main loop of Services calls this function periodically, as dictated by the |
2743 |
<tt>UpdateTimeout</tt> configuration setting; it is also called directly by |
2744 |
the OperServ <tt>UPDATE</tt> command.</p> |
2745 |
|
2746 |
<p>Database modules register themselves with the core database interface |
2747 |
by calling <tt>register_dbmodule()</tt>, providing a <tt>DBModule</tt> |
2748 |
structure giving the various routines that implement the database |
2749 |
opreations. Unlike encryption modules, only one database module can be |
2750 |
active at a time; if a second database module tries to register itself, |
2751 |
<tt>register_dbmodule()</tt> will return failure. As usual, the companion |
2752 |
function <tt>unregister_dbmodule()</tt> must be called upon module |
2753 |
unload.</p> |
2754 |
|
2755 |
<p class="backlink"><a href="#top">Back to top</a></p> |
2756 |
|
2757 |
<!------------------------------------------------------------------------> |
2758 |
<hr/> |
2759 |
|
2760 |
<h3 class="subsection-title" id="s10">2-10. Module command list maintenance</h3> |
2761 |
|
2762 |
<p>There is one other facility provided by the core code for the use of |
2763 |
modules: a command lookup system, implemented by <tt>commands.c</tt> and |
2764 |
<tt>commands.h</tt>, which pseudoclients can use to execute user commands.</p> |
2765 |
|
2766 |
<p>Each command to be handled by this facility must have a <tt>Command</tt> |
2767 |
record defined for it. This is a structure that contains the command name |
2768 |
(command names are treated case-insensitively); a function pointer for the |
2769 |
routine to call to run the command, which is passed the <tt>User</tt> |
2770 |
structure for the user giving the command; an optional function pointer to |
2771 |
a function which returns a boolean value indicating whether the user is |
2772 |
allowed to execute the command, such as <tt>is_oper()</tt>; help message |
2773 |
numbers and parameters; and a <tt>next</tt> field, used to link multiple |
2774 |
records for the same command name together (this will be set when the |
2775 |
command is registered, and need not be set by the caller).</p> |
2776 |
|
2777 |
<p>To allow multiple modules to utilize this facility without their command |
2778 |
lists interfering, a <i>command list ID</i> is passed to each function to |
2779 |
identify which set of commands to look at. The type of this ID is |
2780 |
<tt>Module *</tt> (the type of a module handle, as described in |
2781 |
<a href="4.html">section 4</a>), and typically each module will pass in its |
2782 |
own module handle, or possibly the handle of its "parent" module, for |
2783 |
example in the case of the NickServ submodules like <tt>nickserv/access</tt> |
2784 |
which add to the main NickServ command set.</p> |
2785 |
|
2786 |
<p>In order to use these functions, the command list must first be |
2787 |
initialized; this is done by calling <tt>new_commandlist()</tt> with the |
2788 |
desired command list ID. The ID must be unique, and the function will fail |
2789 |
if another command list with the same ID already exists. Once the command |
2790 |
list has been successfully created, commands can be registered with the |
2791 |
<tt>register_commands()</tt> function. This function takes an array of |
2792 |
commands to register, terminated by an entry with the <tt>name</tt> field |
2793 |
set to <tt>NULL</tt>.</p> |
2794 |
|
2795 |
<p>If a module needs to remove commands, such as when cleaning up, it can |
2796 |
use the <tt>unregister_commands()</tt> function; the same array pointer as |
2797 |
was passed to <tt>register_commands()</tt> must be used here as well (it is |
2798 |
not possible to unregister only part of a command array). Likewise, the |
2799 |
entire command list can be deleted with <tt>del_commandlist()</tt>; before |
2800 |
the command list can be deleted, however, all commands must have been |
2801 |
removed from it, or the function will fail.</p> |
2802 |
|
2803 |
<p>There are three functions that make use of these command lists. The |
2804 |
simplest is <tt>lookup_cmd()</tt>, which simply looks up a command by name |
2805 |
and returns a pointer to the <tt>Command</tt> structure, or <tt>NULL</tt> |
2806 |
if the command is not found. This can be used, for example, if a command |
2807 |
record needs to be modified at runtime (many of the built-in pseudoclients |
2808 |
use this to change help messages depending on the runtime and IRC network |
2809 |
environment). If there are multiple commands with the same name registered |
2810 |
in the same command list, this function will return a pointer to the one |
2811 |
most recently registered; the <tt>next</tt> field can be used to examine |
2812 |
other records for the same command name.</p> |
2813 |
|
2814 |
<p>A more useful function is <tt>run_cmd()</tt>; this looks up the given |
2815 |
command name in the same manner as <tt>lookup_cmd()</tt>, then calls the |
2816 |
command's processing routine with the calling user's <tt>User</tt> record |
2817 |
passed as a parameter. However, if the command has a privilege-checking |
2818 |
routine (<tt>has_priv</tt>) defined, <tt>run_cmd()</tt> first calls that |
2819 |
routine, and if it returns false (zero), a "permission denied" error is |
2820 |
sent to the user and the command is not executed. If the given command |
2821 |
name is not found, a <tt>NOTICE</tt> to that effect is sent to the user |
2822 |
instead. <i>Implementation note: The reason additional parameters to the |
2823 |
processing routine are not supported is because all current command |
2824 |
routines extract their parameters using <tt>strtok(NULL,...)</tt>. This |
2825 |
is clearly poor design, and could be improved by, for example, making |
2826 |
<tt>run_cmd()</tt> into a variadic function and passing the |
2827 |
<tt>va_list</tt> to the command routine, or even just by adding a |
2828 |
<tt>void *</tt> parameter to <tt>run_cmd()</tt> and the command |
2829 |
routine prototype.</i></p> |
2830 |
|
2831 |
<p>The last command-related function is <tt>help_cmd()</tt>. It takes the |
2832 |
same parameters as <tt>run_cmd()</tt>, but rather than executing the |
2833 |
command's processing routine, it uses the help message fields of the |
2834 |
command record to send a help message to the user (again, informing the |
2835 |
user if the command name is not found in the command list). Three help |
2836 |
messages can be specified for each command: <tt>helpmsg_all</tt>, which is |
2837 |
displayed to all users; <tt>helpmsg_reg</tt>, which is displayed after |
2838 |
<tt>helpmsg_all</tt> to users who are not IRC operators; and |
2839 |
<tt>helpmsg_oper</tt>, which is displayed after <tt>helpmsg_all</tt> to IRC |
2840 |
operators. These fields are all message index numbers for use with the |
2841 |
multilingual routines, not literal strings. If any field is -1, the |
2842 |
corresponding help message is not displayed, so (for example) a command |
2843 |
that does not have any special help for IRC operators can use -1 in both |
2844 |
the <tt>helpmsg_reg</tt> and <tt>helpmsg_oper</tt> fields.</p> |
2845 |
|
2846 |
<p>It is also possible to specify format parameters for the help messages, |
2847 |
as long as they are strings; the four string values <tt>help_param1</tt> |
2848 |
through <tt>help_param4</tt> will be passed to <tt>notice_help()</tt> to |
2849 |
fill in "<tt>%s</tt>" tokens in the help message. If more complex |
2850 |
processing or other parameter types are required, <tt>help_cmd()</tt> |
2851 |
cannot be used; the module will have to send the proper help text out |
2852 |
itself.</p> |
2853 |
|
2854 |
<p class="backlink"><a href="#top">Back to top</a></p> |
2855 |
|
2856 |
<!------------------------------------------------------------------------> |
2857 |
<hr/> |
2858 |
|
2859 |
<p class="backlink"><a href="1.html">Previous section: About this manual</a> | |
2860 |
<a href="index.html">Table of Contents</a> | |
2861 |
<a href="3.html">Next section: Communication (socket) handling</a></p> |
2862 |
|
2863 |
</body> |
2864 |
</html> |