ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/vendor/ircservices-5.1.24/docs/tech/7.html
Revision: 3389
Committed: Fri Apr 25 14:12:15 2014 UTC (11 years, 4 months ago) by michael
Content type: text/html
File size: 202921 byte(s)
Log Message:
- Imported ircservices-5.1.24

File Contents

# User Rev Content
1 michael 3389 <?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">, as in 2.html -->
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 - 7. Services pseudoclients</title>
9     </head>
10    
11     <body>
12     <h1 class="title" id="top">IRC Services Technical Reference Manual</h1>
13    
14     <h2 class="section-title">7. Services pseudoclients</h2>
15    
16     <p class="section-toc">
17     7-1. <a href="#s1">Basic features of a pseudoclient</a>
18     <br/>7-2. <a href="#s2">OperServ</a>
19     <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-2-1. <a href="#s2-1">OperServ core functionality</a>
20     <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-2-2. <a href="#s2-2">Usermask-related functions</a>
21     <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-2-2-1. <a href="#s2-2-1">Common mask data support</a>
22     <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-2-2-2. <a href="#s2-2-2">Autokills</a>
23     <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-2-2-3. <a href="#s2-2-3">S-lines</a>
24     <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-2-3. <a href="#s2-3">Session limiting</a>
25     <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-2-4. <a href="#s2-4">News</a>
26     <br/>7-3. <a href="#s3">NickServ</a>
27     <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-3-1. <a href="#s3-1">NickServ core functionality</a>
28     <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-3-1-1. <a href="#s3-1-1">Nickname data structures and utility macros</a>
29     <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-3-1-2. <a href="#s3-1-2">Overall module structure</a>
30     <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-3-1-3. <a href="#s3-1-3">The <tt>SET</tt> and <tt>UNSET</tt> commands</a>
31     <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-3-1-4. <a href="#s3-1-4">NickServ utility routines</a>
32     <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-3-1-5. <a href="#s3-1-5">Nickname colliding</a>
33     <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-3-2. <a href="#s3-2">Nickname access lists</a>
34     <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-3-3. <a href="#s3-3">Nickname auto-join lists</a>
35     <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-3-4. <a href="#s3-4">Linking and nickname groups</a>
36     <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-3-5. <a href="#s3-5">E-mail address authentication</a>
37     <br/>7-4. <a href="#s4">ChanServ</a>
38     <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-4-1. <a href="#s4-1">ChanServ core functionality</a>
39     <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-4-1-1. <a href="#s4-1-1">Channel data structures</a>
40     <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-4-1-2. <a href="#s4-1-2">Overall module structure</a>
41     <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-4-1-3. <a href="#s4-1-3">Channel status checking and modification</a>
42     <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-4-1-4. <a href="#s4-1-4">The <tt>SET</tt> and <tt>UNSET</tt> commands</a>
43     <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-4-1-5. <a href="#s4-1-5">ChanServ utility routines</a>
44     <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-4-2. <a href="#s4-2">Channel access list handling</a>
45     <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-4-2-1. <a href="#s4-2-1">Access list basics</a>
46     <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-4-2-2. <a href="#s4-2-2">Manipulation via <tt>ACCESS</tt> and <tt>LEVELS</tt></a>
47     <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-4-2-3. <a href="#s4-2-3">Manipulation via <tt>XOP</tt></a>
48     <br/>7-5. <a href="#s5">MemoServ</a>
49     <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-5-1. <a href="#s5-1">MemoServ core functionality</a>
50     <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-5-1-1. <a href="#s5-1-1">Memo data structures</a>
51     <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-5-1-2. <a href="#s5-1-2">The <tt>memoserv/main</tt> module</a>
52     <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-5-2. <a href="#s5-2">Memo ignore lists</a>
53     <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-5-3. <a href="#s5-3">Memo forwarding</a>
54     <br/>7-6. <a href="#s6">StatServ</a>
55     <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-6-1. <a href="#s6-1">StatServ data structures</a>
56     <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-6-2. <a href="#s6-2">The StatServ module</a>
57     <br/>7-7. <a href="#s7">Miscellaneous pseudoclients</a>
58     <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-7-1. <a href="#s7-1">HelpServ</a>
59     <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-7-2. <a href="#s7-2">DevNull</a>
60     </p>
61    
62     <p class="backlink"><a href="6.html">Previous section: Database handling</a> |
63     <a href="index.html">Table of Contents</a> |
64     <a href="8.html">Next section: Other modules</a></p>
65    
66     <!------------------------------------------------------------------------>
67     <hr/>
68    
69     <h3 class="subsection-title" id="s1">7-1. Basic features of a pseudoclient</h3>
70    
71     <p>Pseudoclients are the user-visible part of Services, providing the
72     actual service functions which IRC users take advantage of. While the
73     details of each pseudoclient differ greatly, all pseudoclients share some
74     common features:</p>
75    
76     <ul>
77     <li class="spaced">Register one or more nicknames via the
78     "<tt>introduce_user</tt>" callback, through which the pseudoclient
79     communicates with IRC clients; see below for details.</li>
80     <li class="spaced">Receive commands from IRC clients via <tt>PRIVMSG</tt>
81     messages. (According to RFC 1459, pseudoclients <i>must not</i>
82     respond to <tt>NOTICE</tt> messages, in order to prevent infinite
83     loops in which two pseudoclients repeatedly respond to each others'
84     notices.)</li>
85     <li class="spaced">Communicate to IRC clients via <tt>NOTICE</tt> messages.
86     (While not explicitly mandated by the RFC, this is in order to
87     avoid potential message loops with other pseudoclients. Occasional
88     requests have been made for Services to allow using
89     <tt>PRIVMSG</tt> for communication with users, apparently because
90     some IRC programs do not show <tt>NOTICE</tt> messages to users,
91     but such requests have been intentionally disregarded for the above
92     reason.)</li>
93     <li class="spaced">Provide a set of commands which users can use to invoke
94     the pseudoclient's functions. (The miscellaneous modules described
95     in <a href="#s7">section 7-7</a> are an exception; the HelpServ
96     pseudoclient has only one function with no associated command name,
97     and the DevNull pseudoclient has none.) Each message to a
98     pseudoclient is interpreted as a command name and parameters, each
99     separated by one or more space characters (ASCII 0x20&mdash;note
100     that the tab character is <i>not</i> treated as a separator).</li>
101     </ul>
102    
103     <p>The "<tt>introduce_user</tt>" callback mentioned above is called by the
104     same-named function, <tt>introduce_user()</tt>, to request that each module
105     introduce its nickname(s) to the IRC network by calling
106     <tt>send_pseudo_nick()</tt> (in <tt>send.c</tt>). The callback takes a
107     single <tt>const char&nbsp;*</tt> parameter, which is <tt>NULL</tt> when
108     the callback is called at startup, or the nickname seen in a <tt>KILL</tt>
109     message when one is received; accordingly, pseudoclients should introduce
110     their nicknames only when the parameter either is <tt>NULL</tt> or matches
111     (case-insensitively, as determined by <tt>irc_stricmp()</tt>) the nickname
112     to be introduced. <tt>send_pseudo_nick()</tt> takes three parameters: the
113     nickname of the pseudoclient to be introduced, the pseudoclient's "real
114     name" string (usually a description of the pseudoclient), and a flag value,
115     composed of zero or more of the following flags:</p>
116     <ul>
117     <li><tt><b>PSEUDO_OPER</b></tt>: The client requires IRC operator
118     privileges. (This does not necessarily guarantee that the client
119     will be given the <tt>+o</tt> user mode; some IRC servers allow any
120     Services pseudoclient to use IRC operator functions, and
121     <tt>+o</tt> is omitted with such servers.)</li>
122     <li><tt><b>PSEUDO_INVIS</b></tt>: The client should be marked invisible
123     (user mode <tt>+i</tt>).</li>
124     </ul>
125    
126     <p>Command processing is typically performed by hooking into the core's
127     "<tt>m_privmsg</tt>" callback, which is intended specifically for this
128     purpose. Depending on the pseudoclient, it may also be necessary to
129     respond to other events on the IRC network, such as channel joins or mode
130     changes; these can typically be handled by hooking into the relevant
131     callback. In extreme cases, it may be necessary to make use of the
132     low-level "<tt>receive message</tt>" callback as well; this should be
133     avoided when possible, however, as it circumvents the standard message
134     processing and can result in network desynchronization.</p>
135    
136     <p>For databases maintained by pseudoclients, the following six functions
137     are typically provided by the pseudoclient for other code that needs direct
138     access to the database (<tt><span style="text-decoration: underline"><i>type</i></span></tt> is the record data
139     type, <tt><span style="text-decoration: underline"><i>name</i></span></tt> is a distinguishing name generally
140     derived from <tt><span style="text-decoration: underline"><i>type</i></span></tt>, and <tt><span style="text-decoration: underline"><i>keytype</i></span></tt>
141     is the data type of the key field):</p>
142    
143     <dl>
144     <dt><tt><span style="text-decoration: underline"><i>type</i></span> *<b>add_<span style="text-decoration: underline"><i>name</i></span></b>(<span style="text-decoration: underline"><i>type</i></span> *<i>record</i>)</tt></dt>
145     <dd>Adds the given record to the database, returning a pointer to the
146     record structure as stored (which may be different from the pointer
147     passed into the function).</dd>
148    
149     <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>record</i>)</tt></dt>
150     <dd>Deletes the given record from the database. <tt><i>record</i></tt>
151     is assumed to be valid, <i>i.e.</i> a pointer returned by a
152     previous call to another database function.</dd>
153    
154     <dt><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>
155     <dd>Returns the record for the given key, or <tt>NULL</tt> if the key
156     is not found in the database.</dd>
157    
158     <dt><tt>void <b>put_<span style="text-decoration: underline"><i>name</i></span></b>(<span style="text-decoration: underline"><i>type</i></span> *<i>record</i>)</tt></dt>
159     <dd>Indicates that the given record is no longer in use. Each call to
160     a database's <tt>get()</tt> function must be followed by a
161     <tt>put()</tt> call for the same record, unless the record is
162     deleted first. <i>Implementation note: A <tt>put()</tt> function
163     was first introduced in 5.0 with the intention that it be used for
164     indicating when a record had been updated, for the purpose of
165     storing the updated data into persistent storage such as an
166     SQL-based database. DBMS support never materialized, and the
167     function's purpose was redefined for version 5.1 to keep track of
168     which records are actively in use, but I have no confidence that
169     the code does <tt>put()</tt> calls in all necessary cases and no
170     others; in fact, it appears that <tt>put_nickgroupinfo()</tt> (at
171     least) is called more often than it should be. It may have been
172     better to drop <tt>put()</tt> entirely and use other methods of
173     checking whether records are in use before expiring them.</i></dd>
174    
175     <dt><tt><span style="text-decoration: underline"><i>type</i></span> *<b>first_<span style="text-decoration: underline"><i>name</i></span></b>()</tt>
176     <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>
177     <dd>Iterates through the database. <tt>first()</tt> returns the first
178     record in the database, and subsequent <tt>next()</tt> calls return
179     each successive record, finally returning <tt>NULL</tt> when all
180     records have been iterated through (if there are no records at all,
181     both <tt>first()</tt> and <tt>next()</tt> return <tt>NULL</tt>).
182     The order is database-dependent, but no record will be returned
183     more than once from the time <tt>first()</tt> is called to the time
184     <tt>next()</tt> returns <tt>NULL</tt>. It is unspecified whether
185     records added while iterating through the database will be
186     included in the iteration. Note that these functions are
187     <i>not</i> considered a "get" for the purposes of the
188     <tt>put()</tt> function; thus a call to <tt>put()</tt> is not
189     required for simple iteration, but if any other database function
190     is to be called before the following <tt>next()</tt>, then an
191     explicit call to <tt>get()</tt> (and a matching call to
192     <tt>put()</tt>) must be made to prevent the record in use from
193     being deleted.</dd>
194     </dl>
195    
196     <p>The following sections describe each of the Services pseudoclients in
197     detail. The reader is assumed to be familiar with the functions of each
198     pseudoclient from a user's point of view, as described in
199     <a href="../3.html">section 3 of the user's manual</a>.</p>
200    
201     <p class="backlink"><a href="#top">Back to top</a></p>
202    
203     <!------------------------------------------------------------------------>
204     <hr/>
205    
206     <h3 class="subsection-title" id="s2">7-2. OperServ</h3>
207    
208     <p>The OperServ pseudoclient provides services to IRC operators allowing
209     control of the network and of Services itself. While not seen by most IRC
210     users, this pseudoclient is discussed first since it provides functionality
211     used by most other pseudoclients.</p>
212    
213     <p>As with most of the Services pseudoclients, OperServ is composed of one
214     core or "main" module, <tt>operserv/main</tt>, and several optional modules
215     providing additional functionality. These are each discussed in separate
216     sections below.</p>
217    
218     <p class="backlink"><a href="#top">Back to top</a></p>
219    
220    
221     <h4 class="subsubsection-title" id="s2-1">7-2-1. OperServ core functionality</h4>
222    
223     <p>The core functionality of OperServ is contained in the
224     <tt>modules/operserv/main.c</tt> source file, compiled into the
225     <tt>operserv/main</tt> module. In addition to the implementation of the
226     core OperServ commands, this file also defines several utility functions
227     used by several other pseudoclient modules; external declarations of these
228     functions and associated constants are located in
229     <tt>modules/operserv/operserv.h</tt>.</p>
230    
231     <p><tt>main.c</tt> is written using the same general structure as most
232     module source files. At the top of the file are variable definitions,
233     including configuration variables, which are given the same names as their
234     corresponding configuration directives; these are followed by forward
235     declarations of individual command routines and the command list. Next
236     come database-related structures and routines, followed by the top-level
237     pseudoclient routines (the "<tt>introduce_user</tt>", "<tt>m_privmsg</tt>",
238     and "<tt>m_whois</tt>" callback functions), and finally the actual command
239     routines, along with any utility routines needed.</p>
240    
241     <p>For OperServ, the first item of note is the list of several commands and
242     command routines inside <tt>#ifdef DEBUG_COMMANDS</tt>. These are, as the
243     conditional name suggests, commands used for debugging Services, and are
244     only available to the Services super-user; the commands are described in
245     detail below.</p>
246    
247     <p>OperServ stores several values to persistent storage, including the
248     maximum client count, the time at which that maximum was reached, and the
249     super-user (<tt>SU</tt> command) password. This data is stored by
250     aggregating the data into a single structure, <tt>operserv_data</tt>, and
251     storing that structure as a single database "record" in a table named
252     "<tt>oper</tt>". Two exported functions, <tt>get_operserv_data()</tt> and
253     <tt>put_operserv_data()</tt>, are also provided to allow external modules,
254     in particular the XML import and export modules (see
255     <a href="8.html#s4">section 8-4</a>), to access the data as well.</p>
256    
257     <p>In order to check a client's Services privilege level (Services
258     operator, Services administrator, or Services super-user), OperServ requires
259     access to the nickname data, in which each registered nickname group's
260     privilege level is stored (the <tt>os_priv</tt> member). However, since
261     NickServ requires that OperServ be loaded first, OperServ must look up the
262     symbols for these routines during its normal operation. Six local functions
263     are defined, one for each of the imported routines (<tt>get_nickinfo()</tt>,
264     <tt>put_nickinfo()</tt>, <tt>_get_ngi()</tt>, <tt>put_nickgroupinfo()</tt>,
265     <tt>first_nickgroupinfo()</tt>, and <tt>next_nickgroupinfo()</tt>), taking
266     the same parameters and returning the same values as the real routines; the
267     local versions look up the symbol for each routine and then call the
268     corresponding address, returning an appropriate error value if the symbol
269     cannot be resolved (or NickServ is not loaded).</p>
270    
271     <p>The main processing routine itself, <tt>operserv()</tt>, is registered
272     as a callback function for the "<tt>m_privmsg</tt>" callback, called for
273     each <tt>PRIVMSG</tt> received by Services. The routine first checks that
274     the message is intended for OperServ; then it ensures that the client that
275     sent the message is an IRC operator, to avoid any possibility of
276     non-operator clients exploiting a bug in the OperServ code. The message
277     received is then logged in the log file, except that parameters to the
278     <tt>SU</tt> and <tt>SET SUPASS</tt> commands are replaced with a dummy
279     string to avoid leaving the super-user password in the log file. (OperServ
280     has no way to detect if one of these commands is misspelled, so for
281     example, a mistaken <tt>SET SUPSAS</tt> will be logged in full, including
282     the password.) Next, the command name is extracted from the message
283     using the <tt>strtok()</tt> function; this also prepares <tt>strtok()</tt>
284     for the command handler to use in extracting the command parameters (see
285     below). After handling CTCP <tt>PING</tt> messages separately, OperServ
286     calls a "<tt>command</tt>" callback, allowing other modules a chance to
287     process the command first. Finally, if no callback function responds to
288     the command, it is looked up in the command table and the command's handler
289     function is called (if the command is not found, an error message is sent
290     instead).</p>
291    
292     <p>Following this and other callback functions are the privilege check
293     functions; <tt>is_services_root()</tt>, <tt>is_services_admin()</tt>, and
294     <tt>is_services_oper()</tt>, which check whether a client has Services
295     super-user, Services administrator, and Services operator privileges
296     respectively (any client with a higher privilege level is treated as
297     having all lower privilege levels as well). The <tt>is_services_root()</tt>
298     function relies on the <tt>ServicesRoot</tt> configuration setting, along
299     with the <tt>UF_SERVROOT</tt> flag in the <tt>User</tt> structure
300     indicating clients which have successfully used the <tt>SU</tt> command;
301     lower privilege levels check the <tt>os_priv</tt> field of the nickname
302     group data structure (see <a href="#s3-1">section 7-3-1</a>) for privilege
303     determination. These routines are exported, and used widely throughout the
304     other pseudoclient modules to perform privilege checks on clients; in
305     particular, they can be used as privilege check functions in the
306     <tt>has_priv</tt> member of a <tt>Command</tt> structure. There is another
307     routine, <tt>nick_is_services_admin()</tt>, which checks if a particular
308     nickname can potentially can Services administrator access, ignoring
309     whether the nickname is actually in use at the time; this is used by
310     NickServ to prevent certain operations from being performed on such
311     nicknames by clients without Services administrator privilege.</p>
312    
313     <p>The command routines themselves are fairly straightforward. One thing
314     to note is that the routines all obtain parameters via
315     <tt>strtok(NULL,...)</tt> and <tt>strtok_remaining()</tt>; this relies on
316     the fact that <tt>operserv()</tt> leaves the message string in the
317     <tt>strtok()</tt> buffer after stripping the command name, so that each
318     routine can parse the command's parameters as appropriate for that command.
319     <tt>strtok_remaining()</tt> is used when the full remaining string is
320     desired, such as when sending a global message; this function is preferred
321     to <tt>strtok(NULL,"")</tt> because the latter can leave leading or
322     trailing whitespace in the result.</p>
323    
324     <p>The processing for the <tt>HELP</tt> command, in <tt>do_help()</tt>, is
325     somewhat tortuous (although still simpler than in other pseudoclients) in
326     order to give proper help responses depending on how Services is
327     configured. In the case of OperServ, some commands may or may not be
328     available depending on what submodules are loaded; the <tt>COMMANDS</tt>
329     help text, which lists the available commands, is combined from several
330     language strings depending on whether the appropriate modules are available
331     to provide a list of the commands which are actually usable at that
332     particular time. Other modules include more complex processing, such as
333     checking the configuration variable values or protocol features. For
334     commands that do not need such special-casing, the <tt>help_cmd()</tt>
335     routine in the Services core (see <a href="2.html#s10">section 2-10</a>)
336     sends a help message as defined by the <tt>Command</tt> structure.</p>
337    
338     <p>The debug commands, defined toward the bottom of <tt>main.c</tt>, are as
339     follows:</p>
340    
341     <dl>
342     <dt><tt><b>LISTSERVERS</b></tt> (<tt>send_server_list()</tt>)</dt>
343     <dd>Sends a <tt>NOTICE</tt> for each server in the server list giving
344     the contents of the <tt>Server</tt> structure.</dd>
345    
346     <dt><tt><b>LISTCHANS</b></tt> (<tt>send_channel_list()</tt>)</dt>
347     <dd>Sends two <tt>NOTICE</tt>s for each channel in the channel list.
348     The first <tt>NOTICE</tt> gives the channel name, creation time,
349     modes (as a string), limit, key ("<tt>-</tt>") if none, and
350     topic; the second contains each client on the channel along with
351     that client's channel user modes on the channel. Any messages
352     which exceed the maximum length of an IRC line are silently
353     truncated.</dd>
354    
355     <dt><tt><b>LISTCHAN</b> <i>channel</i></tt> (<tt>send_channel_info()</tt>)</dt>
356     <dd>Sends a <tt>NOTICE</tt> for each client on the given channel with
357     the client's channel user modes (as a hexadecimal value) and
358     nickname.</dd>
359    
360     <dt><tt><b>LISTUSERS</b></tt> (<tt>send_user_list()</tt>)</dt>
361     <dd>Sends a <tt>NOTICE</tt> for each client on the network, giving
362     the client's nickname and usermask, the "fake host" or "<tt>-</tt>"
363     if none, the IP address or "<tt>-</tt>" if none, user modes as a
364     string, signon timestamp (from the remote server), servicestamp,
365     server name, nickname status flags or "<tt>-</tt>" if the nickname
366     is not registered, ignore value, and real name field.</dd>
367    
368     <dt><tt><b>LISTUSER</b> <i>nickname</i></tt> (<tt>send_user_info()</tt>)</dt>
369     <dd>Sends three <tt>NOTICE</tt>s describing the state of the given
370     client. The first is identical to the line that <tt>LISTUSERS</tt>
371     would output for the client; the second gives the channels which
372     the client has currently joined; and the third gives the channels
373     which the client has identified to ChanServ for.</dd>
374    
375     <dt><tt><b>LISTTIMERS</b></tt> (<tt>send_timeout_list()</tt>, in
376     <tt>timeout.c</tt>)</dt>
377     <dd>Sends a <tt>NOTICE</tt> giving the current time, followed by a
378     <tt>NOTICE</tt> for each timeout currently in the list giving the
379     timeout pointer, timestamp, function pointer, and function
380     argument. This routine is defined in <tt>timeout.c</tt> because
381     the internal timeout fields are hidden from other source
382     files.</dd>
383    
384     <dt><tt><b>MATCHWILD</b> <i>pattern</i> <i>string</i> </tt> (<tt>do_matchwild()</tt>)</dt>
385     <dd>Sends a <tt>NOTICE</tt> giving the result of calling
386     <tt>match_wild</tt> with the given parameters.</dd>
387    
388     <dt><tt><b>SETCMODE [<i>channel</i> <i>modes</i> <i>mode-params</i>...]</b></tt> (<tt>do_setcmode()</tt>)</dt>
389     <dd>Calls <tt>set_cmode()</tt> with the given parameters, using
390     <tt>ServerName</tt> as the message sender. If no parameters are
391     given, calls <tt>set_cmode(NULL,NULL)</tt> to flush out all
392     pending mode changes. Note that the number of mode parameters
393     (including the mode string itself) is limited by the
394     <tt>SETCMODE_NPARAMS</tt> macro, defined to 10 in the source
395     code.</dd>
396    
397     <dt><tt><b>MONITOR-IGNORE</b> [<i>nickname</i>]</tt> (<tt>do_monitor_ignore()</tt>)</dt>
398     <dd>If a nickname is given, starts recording that nickname's ignore
399     value to the log file at 100ms intervals; if no nickname is given,
400     cancels any previous monitoring. Note that in order to ensure
401     sub-second resolution, the <tt>TimeoutCheck</tt> configuration
402     variable is set to 10 (milliseconds) when a nickname is given,
403     potentially causing a reduction in performance; the old value is
404     <i>not</i> restored when the command is given without a
405     nickname.</dd>
406    
407     <dt><tt><b>GETSTRING</b> <i>language</i> <i>string</i></tt> (<tt>do_getstring()</tt>)</dt>
408     <dd>Sends a <tt>NOTICE</tt> containing the text corresponding to the
409     given string in the given language. Both <tt><i>language</i></tt>
410     and <tt><i>string</i></tt> can be given as either names or raw
411     numbers.</dd>
412    
413     <dt><tt><b>SETSTRING</b> <i>language</i> <i>string</i> [<i>text</i>]</tt> (<tt>do_setstring()</tt>)</dt>
414     <dd>Calls <tt>setstring()</tt> to set the given string in the given
415     language to the given text. If no text is given, the string
416     becomes empty.</dd>
417    
418     <dt><tt><b>MAPSTRING</b> <i>old</i> <i>new</i></tt> (<tt>do_mapstring()</tt>)</dt>
419     <dd>Calls <tt>mapstring()</tt> to map one string to another.
420     <tt><i>old</i></tt> and <tt><i>new</i></tt> are string names or
421     numbers.</dd>
422    
423     <dt><tt><b>ADDSTRING</b> <i>name</i></tt> (<tt>do_addstring()</tt>)</dt>
424     <dd>Calls <tt>addstring()</tt> to add a string with the given name to
425     the language table. On success, sends a <tt>NOTICE</tt> with the
426     new string number.</dd>
427     </dl>
428    
429     <p class="backlink"><a href="#top">Back to top</a></p>
430    
431    
432     <h4 class="subsubsection-title" id="s2-2">7-2-2. Usermask-related functions</h4>
433    
434     <h5 class="subsubsubsection-title" id="s2-2-1">7-2-2-1. Common mask data support</h5>
435    
436     <p>One of the major features of OperServ not included in the core module
437     is the autokill and S-line functionality. While these are in fact defined
438     in separate modules, most of the processing for both sets of functions is
439     subsumed under the <tt>MaskData</tt> structure and its generic processing
440     routines included in the core OperServ module, located in
441     <tt>maskdata.c</tt> and <tt>maskdata.h</tt>. This structure contains the
442     elements common to all of these features: a mask string (whose
443     interpretation is left to the particular module), an associated reason
444     string, the nickname of the client that added the mask, the time the mask
445     was added, the time it expires, and the last time the mask was applied to a
446     client; these are stored in the <tt>mask</tt>, <tt>reason</tt>,
447     <tt>who</tt>, <tt>time</tt>, <tt>expires</tt>, and <tt>lastused</tt>
448     fields of the structure, respectively. The remaining fields (other than
449     the record management fields <tt>next</tt>, <tt>prev</tt>, and
450     <tt>usecount</tt>) are: <tt>type</tt>, containing an 8-bit value
451     identifying the type of mask; <tt>num</tt>, giving the user-visible index
452     number for session exception records (see <a href="#s2-3">section
453     7-2-3</a>); and <tt>limit</tt>, used for the session limit in session
454     exception records.</p>
455    
456     <p>As mentioned above, each <tt>MaskData</tt> record has an associated
457     type; more accurately, there are multiple sets of <tt>MaskData</tt>
458     records, one set for each type (the <tt>type</tt> field is only used
459     internally for loading and saving data from or to persistent storage, and
460     does not need to be set by the caller). The available types, defined by
461     the <tt>MD_*</tt> constants in <tt>maskdata.h</tt>, are:</p>
462     <ul>
463     <li><b><tt>MD_AKILL</tt>:</b> An autokill record.</li>
464     <li><b><tt>MD_EXCLUDE</tt>:</b> An autokill exclusion record.</li>
465     <li><b><tt>MD_EXCEPTION</tt>:</b> A session exception record.</li>
466     <li><b><tt>MD_SGLINE</tt>:</b> An SGline record.</li>
467     <li><b><tt>MD_SQLINE</tt>:</b> An SQline record.</li>
468     <li><b><tt>MD_SZLINE</tt>:</b> An SZline record.</li>
469     </ul>
470     <p>It is worth noting that (as also mentioned in <a href="#s2-2-3">section
471     7-2-2-3</a> below) the values chosen for <tt>MD_SGLINE</tt>,
472     <tt>MD_SQLINE</tt>, and <tt>MD_SZLINE</tt> are the ASCII values of the
473     characters <tt>G</tt>, <tt>Q</tt>, and <tt>Z</tt> respectively; this was
474     done in order to simplify common code for all three types of S-lines, so
475     that the type value could be used as is in messages sent to clients rather
476     than having to make separate tests to determine the appropriate text to
477     send. (For example, most of the language file messages for S-line actions
478     use "<tt>S%cLINE</tt>" in the format string, where the <tt>%c</tt> is
479     replaced by the type value.)</p>
480    
481     <p>One other structure, <tt>MaskDataCmdInfo</tt>, can be found in
482     <tt>maskdata.h</tt>; this structure collects information particular to a
483     single <tt>MaskData</tt> type for use by the common command processing.
484     The bulk of the structure consists of language string indices, which are
485     used in sending responses to commands procesed by the common code. These
486     are preceded by: <tt>name</tt>, the command name (such as "<tt>AKILL</tt>"
487     or "<tt>SGLINE</tt>"); <tt>type</tt>, the record type to be used; and
488     <tt>def_expiry_ptr</tt>, a pointer to a variable containing the default
489     expiration period in seconds (a pointer is used so that any changes to the
490     value can be recognized immediately without having to modify this structure
491     as well). There are also five function pointers, all of which are optional
492     (and should be set to <tt>NULL</tt> if not needed):</p>
493    
494     <dl>
495     <dt><tt>void (*<b>mangle_mask</b>)(char *<i>mask</i>)</tt></dt>
496     <dd>Makes any necessary changes to a mask before it is operated on.
497     Any modifications may be made to the mask as long as they do not
498     lengthen it beyond the original string length. Currently, this
499     is used to force case-insensitive masks to lowercase, to avoid the
500     possibility of multiple matching masks with differing case from
501     being added to the database.</dd>
502    
503     <dt><tt>int (*<b>check_add_mask</b>)(const User *<i>u</i>, uint8 <i>type</i>, char *<i>mask</i>, time_t *<i>expiry_ptr</i>)</tt></dt>
504     <dd>Checks whether the given mask of the given type is allowed to be
505     added with the given expiration time (in seconds from the present
506     time, passed as a pointer); returns nonzero to allow the mask to be
507     added, zero to deny it. The mask and expiration time may be
508     modified by the function, provided that the mask is not lengthened
509     beyond the original string length.</dd>
510    
511     <dt><tt>void (*<b>do_add_mask</b>)(const User *<i>u</i>, uint8 <i>type</i>, MaskData *<i>md</i>)</tt></dt>
512     <dd>Performs any extra actions necessary when a mask is added to the
513     database, such as sending that mask to the network.</dd>
514    
515     <dt><tt>void (*<b>do_del_mask</b>)(const User *<i>u</i>, uint8 <i>type</i>, MaskData *<i>md</i>)</tt></dt>
516     <dd>Performs any extra actions necessary when a mask is removed from
517     the database.</dd>
518    
519     <dt><tt>int (*<b>do_unknown_cmd</b>)(const User *<i>u</i>, const char *<i>cmd</i>, char *<i>mask</i>)</tt></dt>
520     <dd>Processes an unknown subcommand for the associated command,
521     returning nonzero if the subcommand was handled, zero otherwise.</dd>
522     </dl>
523    
524     <p>The function which implements the mask-related command support is
525     <tt>do_maskdata_cmd()</tt>, defined below the database support functions in
526     <tt>maskdata.c</tt>. This function behaves in the same way as a standard
527     pseudoclient command handler, taking a single <tt>User&nbsp;*</tt>
528     parameter giving the client that sent the command, and retrieving command
529     parameters via <tt>strtok(NULL,...)</tt>. After obtaining the subcommand
530     name and its parameters (with double-quote processing for masks), the
531     routine checks for the known subcommands <tt>ADD</tt>, <tt>DEL</tt>,
532     <tt>CLEAR</tt>, <tt>LIST</tt>, <tt>VIEW</tt>, <tt>CHECK</tt>, and
533     <tt>COUNT</tt>, processing each appropriately. If the subcommand is not
534     one of these, it is passed to the command's <tt>do_unknown_cmd()</tt>
535     function; if that function returns zero or does not exist, an error is
536     sent to the client.</p>
537    
538     <p>The subcommands themselves are implemented by local routines:
539     <tt>do_maskdata_add()</tt>, <tt>do_maskdata_del()</tt>, and so on. These
540     check the validity of the parameters for the particular subcommand and
541     perform the appropriate action, using the language string indices in the
542     <tt>MaskDataCmdInfo</tt> structure to send replies to the client that
543     issued the command.</p>
544    
545     <p>There are also three utility functions defined after the command
546     handler routines:</p>
547    
548     <dl>
549     <dt><tt>void *<b>new_maskdata</b>()</tt></dt>
550     <dd>Allocates, initializes, and returns a new <tt>MaskData</tt>
551     structure. (The return value is <tt>void&nbsp;*</tt> to avoid a
552     type warning in the database table declaration.)</dd>
553    
554     <dt><tt>void <b>free_maskdata</b>(void *<i>record</i>)</tt></dt>
555     <dd>Frees the <tt>MaskData</tt> structure pointed to by
556     <tt><i>record</i></tt>, Does nothing if <tt><i>record</i></tt> is
557     <tt>NULL</tt>.</dd>
558    
559     <dt><tt>char *<b>make_reason</b>(const char *<i>format</i>, const MaskData *<i>data</i>)</tt></dt>
560     <dd>Returns the reason string for the given mask and format string.
561     If <tt><i>format</i></tt> contains a "<tt>%s</tt>", it will be
562     replaced by the mask's reason string in the return value;
563     otherwise, the returned string is identical to
564     <tt><i>format</i></tt>. The result string is stored in a static
565     buffer, which is overwritten by subsequent calls to
566     <tt>make_reason()</tt>.</dd>
567     </dl>
568    
569     <p>With respect to the database management routines, <tt>MaskData</tt>
570     records are stored in variable-length arrays, one array for each of the 256
571     possible mask types. (Arrays were chosen over hash tables for simplicity;
572     since the most common use of these records is searching all records of a
573     particular type for one that matches a given string, there would be little
574     benefit to the use of a hash table.) The <tt>next</tt> and <tt>prev</tt>
575     fields are not ordinarily required for array handling, but the code stores
576     the (integer) array index value in the <tt>next</tt> field via a cast to
577     <tt>void&nbsp;*</tt>, allowing the code to know where in the array a given
578     record is located without having to search through the array every time
579     (note that the <tt>num</tt> field is used for a different
580     purpose&mdash;index numbers for session exceptions&mdash;and is not
581     available). Aside from the standard database operations, which take a
582     <tt>uint8 <i>type</i></tt> parameter in addition to the mask record itself,
583     the following functions are included:</p>
584    
585     <dl>
586     <dt><tt>MaskData *<b>get_matching_maskdata</b>(uint8 <i>type</i>, const char *<i>str</i>)</tt></dt>
587     <dd>Searches for and returns (in the same manner as
588     <tt>get_maskdata()</tt>, including expiration checks) a mask which
589     matches the wildcard pattern given by <tt><i>str</i></tt>. If more
590     than one mask matches, an arbitrary one is returned.</dd>
591    
592     <dt><tt>MaskData *<b>get_exception_by_num</b>(int <i>num</i>)</tt></dt>
593     <dd>Retrieves a mask of the <tt>MD_EXCEPTION</tt> (session exception)
594     type by its index number.</dd>
595    
596     <dt><tt>MaskData *<b>move_exception</b>(MaskData *<i>except</i>, int <i>newnum</i>)</tt></dt>
597     <dd>Changes the index number of the given <tt>MD_EXCEPTION</tt> mask.
598     (Internally, this reorders the mask array so that entries remain in
599     order by index number.)</dd>
600     </dl>
601    
602     <p class="backlink"><a href="#top">Back to top</a></p>
603    
604    
605     <h5 class="subsubsubsection-title" id="s2-2-2">7-2-2-2. Autokills</h5>
606    
607     <p>As mentioned above, one of the main uses of this mask data code is the
608     autokill module, <tt>operserv/akill</tt>, defined in <tt>akill.c</tt> and
609     <tt>akill.h</tt>. While support for the OperServ <tt>AKILL</tt> and
610     <tt>EXCLUDE</tt> commands simply makes use of the aforementioned
611     <tt>do_maskdata_cmd()</tt> function, handling for the actual autokills and
612     autokill exclusions themselves is defined within the autokill module. This
613     includes:</p>
614    
615     <ul>
616     <li class="spaced"><tt>send_akill()</tt> and <tt>cancel_akill()</tt>, and
617     their autokill exclusion companions <tt>send_exclude()</tt> and
618     <tt>cancel_exclude()</tt>, which (via callbacks hooked into by
619     protocol modules) take care of adding and removing autokills and
620     exclusions on the network. Note that <tt>cancel_akill()</tt> and
621     <tt>cancel_exclude()</tt> destroy their <tt>char&nbsp;*</tt>
622     parameters, but as they are only called when deleting a record,
623     this is not a problem.</li>
624    
625     <li class="spaced"><tt>do_user_check()</tt>, which hooks into the
626     "<tt>user check</tt>" callback to check whether a newly connecting
627     client matches any active autokills or exclusions and take
628     appropriate action.</li>
629    
630     <li class="spaced"><tt>create_akill()</tt>, an exported function which
631     creates a new autokill record given the usermask, reason, setter
632     nickname, and time to expiration. (There is currently no
633     equivalent function for autokill exclusions.)</li>
634    
635     <li class="spaced">The data structure and helper functions for
636     <tt>do_maskdata_cmd()</tt>. In particular, <tt>check_add_akill</tt>
637     uses simple heuristics to check for masks that are so general that
638     they would match any conceivable combination of username and
639     hostname (for example, "<tt>*@*</tt>" or "<tt>?*@*?.*?*</tt>") and
640     disallow such masks, in order to avoid situations where no one
641     could connect to the network because every client matched the
642     autokill.</li>
643    
644     <li class="spaced">The <tt>AKILLCHAN</tt> command implementation,
645     <tt>do_akillchan()</tt>. It is worth noting that (as commented in
646     the code) there is a race condition that can allow the client to
647     reconnect in the miniscule interval between disconnecting the
648     client with a <tt>KILL</tt> command and adding an autokill for that
649     client; this negligible risk was taken in light of the fact that
650     doing it the other way (sending the autokill first) causes some IRC
651     servers to automatically kill the client, and OperServ's
652     <tt>KILL</tt> would cause a "user not found" message to be logged
653     (which did in fact generate some complaints from users). However,
654     once the client is killed, the username and hostname from the
655     <tt>User</tt> structure are no longer available, so they must be
656     saved ahead of time (the code at one point failed to do this,
657     predictably resulting in crashes&mdash;hence the vitriolic comment
658     about that mistake).</li>
659    
660     <li class="spaced">The "<tt>connect</tt>" callback function, which sends
661     all autokills to the network on initial connection.</li>
662    
663     <li class="spaced">The "<tt>expire_maskdata</tt>" timeout function, which
664     checks for autokill expiration. In order to prevent flooding of
665     IRC operators, for example when autokills set by an
666     <tt>AKILLCHAN</tt> command expire, expiration announcements via
667     <tt>WALLOPS</tt> are (if enabled) only sent at the rate of one per
668     second, and any further expirations are merged into a single
669     "<i>nnn</i> more autokills have expired" message sent after all
670     expirations are complete.</li>
671    
672     <li class="spaced">The OperServ "<tt>HELP</tt>" callback function, which
673     is required to display the <tt>AKILL</tt> help message correctly.</li>
674    
675     <li class="spaced">The OperServ "<tt>STATS ALL</tt>" callback function,
676     used to calculate and display autokill memory usage in response to
677     a <tt>STATS ALL</tt> command.</li>
678     </ul>
679    
680     <p>One item of interest in the module setup code at the bottom of the
681     source file is the handling of the <tt>EXCLUDE</tt> command.
682     <tt>EXCLUDE</tt> can be enabled or disabled via a configuration file
683     option (<tt>EnableExclude</tt>), for reasons discussed below. Rather than
684     create two command tables, one with <tt>EXCLUDE</tt> and one without, the
685     code simply modifies the <tt>EXCLUDE</tt> entry to have an empty command
686     name if the command is disabled; since command names parsed by OperServ
687     cannot be empty, the command will never be found. (In order to locate the
688     entry again once the name has been cleared, a static variable is used, set
689     during module initialization to point to the proper element of the command
690     array. The name is restored during module cleanup so that a subsequent
691     initialization will likewise be able to find it.)</p>
692    
693     <p>The handling of autokill exclusions is trickier than it may seem at
694     first glance, due to protocols which support network-wide autokill masks
695     but not exclusion masks. If one takes the naive approach of simply adding
696     autokill masks as usual, one will find that the effectiveness of the
697     autokill exclusions is severely limited. For example, consider a network
698     with an autokill for <tt>*@*.example.com</tt> and an exclusion for
699     <tt>*@oper.example.com</tt>. As long as the only users in the
700     <tt>example.com</tt> domain to connect are from the
701     <tt>oper.example.com</tt> host, the exclusion will function as expected.
702     However, as soon as a user from another <tt>example.com</tt> host connects,
703     the autokill will be triggered and sent out to the network&mdash;with the
704     unintended result that even users from <tt>oper.example.com</tt> are
705     prevented from connecting, since Services has no way to inform other
706     servers on the network about the autokill exclusion.</p>
707    
708     <p>In order to avoid this problem, the <tt>operserv/akill</tt> module will
709     not make use of a protocol's autokill features if that protocol does not
710     also support autokill exclusions, and will simply send out a <tt>KILL</tt>
711     message for each user to be disconnected from the network. However, this
712     may not be desirable for networks that have no intention of using the
713     autokill exclusion functionality. For this reason, the
714     <tt>EnableExclude</tt> configuration option was added, allowing such
715     networks to choose between taking advantage of the protocol's autokill
716     feature and using exclusions with autokills.</p>
717    
718     <p class="backlink"><a href="#top">Back to top</a></p>
719    
720    
721     <h5 class="subsubsubsection-title" id="s2-2-3">7-2-2-3. S-lines</h5>
722    
723     <p>S-lines are the other primary user of the mask data code. These sets of
724     client restriction masks (SGlines, SQlines, and SZlines) are implemented by
725     the <tt>operserv/sline</tt> module, defined in <tt>sline.c</tt> and
726     <tt>sline.h</tt>.</p>
727    
728     <p>The S-line module is very similar to the autokill module, both
729     functionally and internally (in fact, <tt>sline.c</tt> started out as a
730     copy of <tt>akill.c</tt>). The primary difference is in the sharing of
731     data and code between the three mask types. Since the command names differ
732     only in a single character, the code takes the shortcut of using that
733     character as the mask type for use with the <tt>MaskData</tt> support
734     functions&mdash;this is the reason for the warning comment in
735     <tt>maskdata.h</tt> about changing the type values&mdash;and including a
736     <tt>%c</tt> token in relevant messages which is replaced by the mask type.
737     This enables a single message, such as "<tt>%d masks on the S%cLINE
738     list.</tt>", to be shared by code for all three sets of masks. Several
739     functions are likewise shared by the three mask types, taking a type
740     parameter to select which data set to operate on.</p>
741    
742     <p>Naturally, each type of mask is interpreted differently, so the actual
743     processing for each type is handled separately. SQlines, in particular,
744     are checked by the utility routine <tt>check_sqline()</tt>, called from the
745     callback functions <tt>do_user_check()</tt> and
746     <tt>do_user_nickchange_after()</tt>, because there are several possible
747     ways of handling a match:</p>
748    
749     <ul>
750     <li class="spaced">If the client is an IRC operator and the
751     <tt>SQlineIgnoreOpers</tt> configuration option is enabled, then
752     SQlines are not checked at all. (The <tt><i>new_oper</i></tt>
753     parameter is required because, when called from
754     <tt>do_user_check()</tt>, the <tt>User</tt> record will not yet
755     have been created.)</li>
756    
757     <li class="spaced">If the SQline is for a guest nick, the client is left
758     alone, though the SQline itself is sent to the network.</li>
759    
760     <li class="spaced">If the <tt>SQlineKill</tt> configuration option is
761     <i>not</i> set and the protocol in use supports forced nickname
762     changing, the client's nickname is changed to a guest nickname, and
763     the SQline is sent to the network.</li>
764    
765     <li class="spaced">Otherwise, the client is killed, and the SQline is sent
766     to the network.</li>
767     </ul>
768    
769     <p class="backlink"><a href="#top">Back to top</a></p>
770    
771    
772     <h4 class="subsubsection-title" id="s2-3">7-2-3. Session limiting</h4>
773    
774     <p>The last method of client control, session limiting, is implemented by
775     the <tt>operserv/sessions</tt> module, defined in <tt>sessions.c</tt>. The
776     module consists of two major parts: the actual session maintenance and
777     limiting code, and session exception mask management via the
778     <tt>EXCEPTION</tt> command.</p>
779    
780     <p>The session maintenance functionality is contained within the
781     <tt>add_session()</tt> and <tt>del_session()</tt> routines, called from
782     callback functions when clients join or leave the network, respectively.
783     These routines keep track of each host with one or more clients on the
784     network by means of a hash table containing <tt>Session</tt> structures,
785     one per host. When <tt>add_session</tt> is called, it looks up the
786     <tt>Session</tt> record for the new client's hostname, creating a new
787     record with a count of zero if no record for that host already exists, then
788     increments the host's client count by one; conversely,
789     <tt>del_session()</tt> decrements the host's client count, deleting the
790     <tt>Session</tt> structure when the count reaches zero.</p>
791    
792     <p>The "limiting" part of session limiting is a check in
793     <tt>add_session()</tt> to determine whether the host has "too many"
794     clients on the network. Here, "too many" is defined by either the limit
795     given in an exception record (see below) or the default limit given in the
796     <tt>DefSessionLimit</tt> configuration directive; if adding the new client
797     would cause the host's client count to exceed the relevant limit, then the
798     client is killed (any clients already connected are left alone). An
799     autokill can also be added for thte host depending on the configuration
800     settings.</p>
801    
802     <p>The module also provides a <tt>SESSION</tt> command to allow Services
803     operators to view the contents of the session list; this can be used to
804     find hosts from which a large number of clients are connecting. The
805     <tt>SESSION</tt> command is available even if actual limiting of sessions
806     is disabled (by setting <tt>DefSessionLimit</tt> to zero).</p>
807    
808     <p>The second part of the module, session exceptions, allows fine-tuning of
809     the default limit on client connections. For example, it may be desirable
810     to allow extra connections from a particular host known to be used by IRC
811     operators. Such exceptions to the default session limit are stored using
812     <tt>MaskData</tt> structures with the <tt>MD_EXCEPTION</tt> type; each
813     record is treated as a wildcard pattern against which a connecting client's
814     hostname is matched, and if a match is found, that limit is used instead of
815     the default, as described above. If more than one matching session
816     exception exists, the first one in the list (from a user's point of view,
817     the one with the lowest index number) is used.</p>
818    
819     <p>Session exceptions are maintained using the <tt>EXCEPTION</tt> command.
820     The processing for this command, in <tt>do_exception()</tt> and its
821     subroutines, is very similar to other mask-type commands like
822     <tt>AKILL</tt>; however, session exceptions require a limit value in
823     addition to the mask, and it was considered simpler to keep the handling
824     for <tt>EXCEPTION</tt> separate rather than modify
825     <tt>do_maskdata_cmd()</tt> to handle both command formats. The
826     <tt>EXCEPTION</tt> command also includes a <tt>MOVE</tt> subcommand,
827     allowing one record to be moved relative to another within the list (so,
828     for example, a newly-added exception can be moved earlier in the list to
829     take precedence over other exceptions).</p>
830    
831     <p>A careful look at the initialization code will show that the
832     "<tt>user check</tt>" callback function, <tt>check_sessions()</tt> (which
833     in turn calls <tt>add_session()</tt>), is added at a priority of -10. This
834     is in order to ensure that the function is called after all other checks
835     have been performed, as described in <a href="4.html#s5-2">section
836     4-5-2</a> (and is a poor design choice for the reasons described there).</p>
837    
838     <p class="backlink"><a href="#top">Back to top</a></p>
839    
840    
841     <h4 class="subsubsection-title" id="s2-4">7-2-4. News</h4>
842    
843     <p>The last OperServ submodule is the <tt>operserv/news</tt> module,
844     defined in <tt>news.c</tt> and <tt>news.h</tt>. This is a fairly simple
845     module, containing routines to handle news item storage and implement the
846     <tt>LOGONNEWS</tt> and <tt>OPERNEWS</tt> commands.</p>
847    
848     <p>News items are stored in a single variable-length array of
849     <tt>News</tt> structures, <tt>newslist</tt>. The <tt>News</tt> structure
850     contains, aside from the text of the news item itself, the news type
851     (<tt>NEWS_LOGON</tt> or <tt>NEWS_OPER</tt>), an index number used when
852     deleting the item, the nickname of the client that added the item, and the
853     time the item was added. As with <tt>MaskData</tt> structures,
854     <tt>next</tt> and <tt>prev</tt> fields are included only to mirror other
855     structures, and the array index is stored in the <tt>next</tt> field.</p>
856    
857     <p>The two news commands, <tt>LOGONNEWS</tt> and <tt>OPERNEWS</tt>, share
858     the same code, <tt>do_news()</tt>; this routine is called by the actual
859     command handlers with one of the news type codes, either
860     <tt>NEWS_LOGON</tt> or <tt>NEWS_OPER</tt>, and accesses an array of
861     language string indices (<tt>msgarray[]</tt>) to return proper messages
862     for each command, similar to <tt>do_maskdata_cmd()</tt>. Unlike most other
863     commands (but like the <tt>OPER</tt> and <tt>ADMIN</tt> commands in the
864     OperServ core), the news commands include a <tt>LIST</tt> command available
865     to all IRC operators, and other subcommands (<tt>ADD</tt> and <tt>DEL</tt>)
866     restricted to Services operators; thus, the command handler must perform
867     privilege checks on its own rather than specifying a privilege check
868     routine in the command table.</p>
869    
870     <p class="backlink"><a href="#top">Back to top</a></p>
871    
872     <!------------------------------------------------------------------------>
873     <hr/>
874    
875     <h3 class="subsection-title" id="s3">7-3. NickServ</h3>
876    
877     <p>NickServ is typically the first pseudoclient IRC users interact with.
878     It was also the first pseudoclient created during Services' initial design,
879     on which all other pseudoclients were based. The current NickServ is
880     divided into a core module and four submodules implementing additional
881     features; each module is described in its own section below.</p>
882    
883     <p class="backlink"><a href="#top">Back to top</a></p>
884    
885    
886     <h4 class="subsubsection-title" id="s3-1">7-3-1. NickServ core functionality</h4>
887    
888     <p>The core NickServ functionality is implemented by the
889     <tt>nickserv/main</tt> module. Alongside the primary module source file,
890     <tt>main.c</tt>, the module makes use of three additional source files:
891     <tt>collide.c</tt>, handling the disconnection or forced removal of clients
892     using unauthorized nicknames; <tt>set.c</tt>, implementing the <tt>SET</tt>
893     command and its subcommands; and <tt>util.c</tt>, containing various
894     utility routines used by NickServ.</p>
895    
896     <p>NickServ makes use of two distinct header files. One,
897     <tt>nickserv.h</tt>, defines the data structures used for storing nickname
898     information (<tt>NickInfo</tt> and <tt>NickGroupInfo</tt>, described below)
899     along with declarations of exported routines and macros used with nickname
900     records. The other, <tt>ns-local.h</tt>, contains declarations of routines
901     used within NickServ, necessarily declared <tt>extern</tt> because they
902     reside in separate source files but not intended to be used outside the
903     NickServ modules.</p>
904    
905     <p class="backlink"><a href="#top">Back to top</a></p>
906    
907    
908     <h5 class="subsubsubsection-title" id="s3-1-1">7-3-1-1. Nickname data structures and utility macros</h5>
909    
910     <p>Two separate structures are used to store nickname data; this is to
911     facilitate the implementation of nickname links, as described in
912     <a href="#s3-4">section 7-3-4</a>. One structure, <tt>NickInfo</tt>,
913     contains data that is distinct for each individual nickname; the other,
914     <tt>NickGroupInfo</tt>, contains data that is shared among each group of
915     linked nicknames.</p>
916    
917     <p>The <tt>NickInfo</tt> structure includes the following data:</p>
918    
919     <dl>
920     <dt><tt>NickInfo *<b>next</b>, *<b>prev</b></tt></dt>
921     <dd>Used to link records together in the internal hash table.</dd>
922    
923     <dt><tt>int <b>usecount</b></tt></dt>
924     <dd>The record's usage count (number of gets minus number of puts).
925     <i>(Implementation note: As noted in <a href="#s1">section 7-1</a>,
926     this field currently serves no actual purpose.)</i></dd>
927    
928     <dt><tt>char <b>nick</b>[NICKMAX]</tt></dt>
929     <dd>The actual nickname. Capitalization is as used when the nickname
930     was registered, and does not change due to later actions. The
931     buffer size, <tt>NICKMAX</tt>, is defined in the global header
932     file <tt>defs.h</tt>.</dd>
933    
934     <dt><tt>int16 <b>status</b></tt></dt>
935     <dd>The nickname's status. This is a combination of zero or more of
936     the following flags:
937     <ul>
938     <li><b><tt>NS_VERBOTEN</tt>:</b> The nickname is a forbidden
939     nickname set with the <tt>FORBID</tt> command. ("Verboten"
940     is German for "forbidden", but there is no particular
941     meaning behind this choice other than a whim of the
942     developer as he was writing the code.)</li>
943     <li><b><tt>NS_NOEXPIRE</tt>:</b> The nickname is not to be expired
944     regardless of how long it remains unused (<tt>SET
945     NOEXPIRE</tt>).</li>
946     <li><b><tt>NS_KILL_HELD</tt>:</b> The nickname is currently being
947     held by an "enforcer" pseudoclient after killing (or
948     changing the nickname of) a client that was using the
949     nickname without permission.</li>
950     <li><b><tt>NS_GUESTED</tt>:</b> An IRC message has been sent to
951     change the nickname of the client using the nickname, but
952     the nickname change has not yet occurred.</li>
953     </ul>
954     Of these flags, <tt>NS_VERBOTEN</tt> and <tt>NS_NOEXPIRE</tt> are
955     "permanent" flags (collected in the <tt>NS_PERMANENT</tt> mask),
956     which are retained across restarts of Services, while
957     <tt>NS_KILL_HELD</tt> and <tt>NS_GUESTED</tt> are "temporary" flags
958     (collected in the <tt>NS_TEMPORARY</tt> mask), which are cleared
959     each time the database is loaded from persistent storage. Note
960     that the value 0x0001 (bit 0) is not used because it served a
961     separate purpose in previous versions of Services.</dd>
962    
963     <dt><tt>char *<b>last_usermask</b></tt></dt>
964     <dd>The last <tt><i>user</i>@<i>host</i></tt> mask used by the owner
965     of the nickname (<i>i.e.,</i> a client authorized to use the
966     nickname). If the owner is currently online, that client's
967     <tt><i>user</i>@<i>host</i></tt> mask is used. On IRC networks
968     where a "fake hostname" is available, that hostname is used
969     instead of the client's actual hostname.</dd>
970    
971     <dt><tt>char *<b>last_realmask</b></tt></dt>
972     <dd>Like <tt>last_usermask</tt>, but uses the real hostname instead of
973     any "fake hostname". On networks without such a fake hostname,
974     this field is identical to <tt>last_usermask</tt>.</dd>
975    
976     <dt><tt>char *<b>last_realname</b></tt></dt>
977     <dd>The last "real name" string used by the owner of the nickname.</dd>
978    
979     <dt><tt>char *<b>last_quit</b></tt></dt>
980     <dd>The message used the last time the owner quit IRC. <tt>NULL</tt>
981     if not available, such as for newly-registered nicknames.</dd>
982    
983     <dt><tt>time_t <b>time_registered</b></tt></dt>
984     <dd>The timestamp when the nickname was registered.</dd>
985    
986     <dt><tt>time_t <b>last_seen</b></tt></dt>
987     <dd>The timestamp at which the owner most recently used the nickname.
988     Only updated when the owner stops using the nickname; if the
989     nickname is currently in use, this field should not be relied on.</dd>
990    
991     <dt><tt>uint32 <b>nickgroup</b></tt></dt>
992     <dd>The ID of the nickname group with which this nickname is associated
993     (see below).</dd>
994    
995     <dt><tt>uint32 <b>id_stamp</b></tt></dt>
996     <dd>The servicestamp of the client that last identified for the
997     nickname. Used to retain identification status across Services
998     restarts.</dd>
999    
1000     <dt><tt>User *<b>user</b></tt></dt>
1001     <dd><i>Not saved to persistent storage.</i> A pointer to the
1002     <tt>User</tt> structure for the client currently using the
1003     nickname, or <tt>NULL</tt> if the nickname is not currently in
1004     used.</dd>
1005    
1006     <dt><tt>int16 <b>authstat</b></tt></dt>
1007     <dd><i>Not saved to persistent storage.</i> Zero or more of the
1008     following flags, indicating the nickname's authentication status:
1009     <ul>
1010     <li><b><tt>NA_IDENTIFIED</tt>:</b> The current user of the nickname
1011     has identified by password as the nickname's owner.
1012     Mutually exclusive with <tt>NA_IDENT_NOEMAIL</tt>.</li>
1013     <li><b><tt>NA_IDENT_NOMAIL</tt>:</b> The current user of the
1014     nickname has identified by password as the nickname's
1015     owner, but has not registered an E-mail address with the
1016     nickname when one is required. Mutually exclusive with
1017     <tt>NA_IDENTIFIED</tt>.</li>
1018     <li><b><tt>NA_RECOGNIZED</tt>:</b> The current user of the nickname
1019     is recognized via the nickname access list (see
1020     <a href="#s3-2">section 7-3-2</a>).</li>
1021     </ul></dd>
1022    
1023     <dt><tt>int <b>bad_passwords</b></tt></dt>
1024     <dd><i>Not saved to persistent storage.</i> The number of consecutive
1025     failed password identification attempts for the nickname. Used to
1026     determine whether or not to kill a client for attempted password
1027     cracking.</dd>
1028     </dl>
1029    
1030     <p>The <tt>NickGroupInfo</tt> structure includes the following data:</p>
1031    
1032     <dl>
1033     <dt><tt>NickGroupInfo *<b>next</b>, *<b>prev</b></tt></dt>
1034     <dd>Used to link records together in the internal hash table.</dd>
1035    
1036     <dt><tt>int <b>usecount</b></tt></dt>
1037     <dd>The record's usage count (number of gets minus number of puts).
1038     <i>(Implementation note: As noted in <a href="#s1">section 7-1</a>,
1039     this field currently serves no actual purpose.)</i></dd>
1040    
1041     <dt><tt>uint32 <b>id</b></tt></dt>
1042     <dd>The nickname group's ID, a unique 32-bit value. Typically, this
1043     value is randomly assigned. The value zero is not allowed (it is
1044     used in <tt>NickInfo</tt> records to indicate the lack of an
1045     associated nickname group, as for forbidden nicknames).</dd>
1046    
1047     <dt><tt>nickname_t *<b>nicks</b></tt>
1048     <br/><tt>uint16 <b>nicks_count</b></tt></dt>
1049     <dd><i>Not saved to persistent storage.</i> A variable-length array
1050     containing the nicknames associated with this nickname group. Used
1051     for convenience, to avoid having to search through the nickname
1052     database every time a list of nicknames is needed.</dd>
1053    
1054     <dt><tt>uint16 <b>mainnick</b></tt></dt>
1055     <dd>The "main nickname" for the group, used to represent the nickname
1056     group in things such as channel access lists. Specified as an
1057     index into the <tt>nicks[]</tt> array.</dd>
1058    
1059     <dt><tt>Password <b>pass</b></tt></dt>
1060     <dd>The password used for identification for the nickname group.</dd>
1061    
1062     <dt><tt>char *<b>url</b></tt></dt>
1063     <dd>A URL associated with the nickname group. Can be arbitrarily set
1064     by the owner.</dd>
1065    
1066     <dt><tt>char *<b>email</b></tt></dt>
1067     <dd>An E-mail address associated with the nickname group. Can be
1068     arbitrarily set by the owner, and may be required at registration
1069     time by setting the <tt>NSRequireEmail</tt> configuration option.</dd>
1070    
1071     <dt><tt>char *<b>last_email</b></tt></dt>
1072     <dd>When mail-based authentication (see <a href="#s3-5">section
1073     7-3-5</a>) is in use, this field is set to the previous contents
1074     of the <tt>email</tt> field when the owner changes the E-mail
1075     address, and is cleared when the new address is authenticated; this
1076     allows the <tt>RESTOREMAIL</tt> command to function.</dd>
1077    
1078     <dt><tt>char *<b>info</b></tt></dt>
1079     <dd>A free-form text string associated with the nickname group. Can be
1080     arbitrarily set by the owner.</dd>
1081    
1082     <dt><tt>int32 <b>flags</b></tt></dt>
1083     <dd>A bitmask containing zero or more of the following nickname group
1084     flags:
1085     <ul>
1086     <li><b><tt>NF_KILLPROTECT</tt>:</b> NickServ should prevent other
1087     clients from using the nickname by either killing them or
1088     changing their nicknames, depending on the IRC protocol in
1089     use (<tt>SET KILL ON/QUICK/IMMED</tt>).</li>
1090     <li><b><tt>NF_SECURE</tt>:</b> NickServ should require password
1091     identification for the nickname even if the client is on
1092     the nickname's access list (<tt>SET SECURE</tt>).</li>
1093     <li><b><tt>NF_MEMO_HARDMAX</tt>:</b> The client is not permitted to
1094     change the nickname's memo limit (MemoServ <tt>SET LIMIT
1095     HARD</tt>).</li>
1096     <li><b><tt>NF_MEMO_SIGNON</tt>:</b> MemoServ should inform the
1097     client of new memos at signon (MemoServ <tt>SET NOTIFY
1098     ON/LOGON</tt>).</li>
1099     <li><b><tt>NF_MEMO_RECEIVE</tt>:</b> MemoServ should inform the
1100     client of new memos when they are sent (MemoServ <tt>SET
1101     NOTIFY ON/NEW</tt>).</li>
1102     <li><b><tt>NF_PRIVATE</tt>:</b> The nickname is hidden from the
1103     <tt>LIST</tt> and <tt>LISTEMAIL</tt> command output, except
1104     when used by Services administrators (<tt>SET
1105     PRIVATE</tt>).</li>
1106     <li><b><tt>NF_HIDE_EMAIL</tt>:</b> The nickname's E-mail address is
1107     hidden from the <tt>INFO</tt> and <tt>LISTEMAIL</tt>
1108     command output, except when used by Services administrators
1109     (<tt>SET HIDE EMAIL</tt>).</li>
1110     <li><b><tt>NF_HIDE_MASK</tt>:</b> The nickname's
1111     <tt><i>user</i>@<i>host</i></tt> mask is hidden from the
1112     <tt>INFO</tt> and <tt>LIST</tt> command output, except when
1113     used by Services administrators (<tt>SET HIDE
1114     USERMASK</tt>).</li>
1115     <li><b><tt>NF_HIDE_QUIT</tt>:</b> The nickname's last quit message
1116     is hidden from the <tt>INFO</tt> command output, except
1117     when used by Services administrators (<tt>SET HIDE
1118     QUIT</tt>).</li>
1119     <li><b><tt>NF_KILL_QUICK</tt>:</b> NickServ should allow only 20
1120     seconds instead of 60 for an unauthorized client to change
1121     nickname (<tt>SET KILL QUICK/IMMED</tt>).</li>
1122     <li><b><tt>NF_KILL_IMMED</tt>:</b> NickServ should kill or
1123     nickchange unauthorized clients immediately with no grace
1124     period (<tt>SET KILL IMMED</tt>).</li>
1125     <li><b><tt>NF_MEMO_FWD</tt>:</b> MemoServ should forward received
1126     memos to the nickname's E-mail address (MemoServ <tt>SET
1127     FORWARD ON/COPY</tt>).</li>
1128     <li><b><tt>NF_MEMO_FWDCOPY</tt>:</b> MemoServ should save copies of
1129     forwarded memos (MemoServ <tt>SET FORWARD COPY</tt>).</li>
1130     <li><b><tt>NF_SUSPENDED</tt>:</b> The nickname group is suspended
1131     (<tt>SUSPEND</tt>).</li>
1132     <li><b><tt>NF_NOOP</tt>:</b> ChanServ should prevent the nickname
1133     from being added to channel access lists (<tt>SET
1134     NOOP</tt>).</li>
1135     </ul>
1136     Note that the value 0x00000004 (bit 2) is not included in the above
1137     flags because it served a separate purpose in previous versions of
1138     Services. Instead, this value is used as a temporary flag
1139     (<tt>NF_NOGROUP</tt>) when loading databases from earlier versions
1140     of Services, to indicate that a nickname group does not yet have an
1141     ID value assigned.</dd>
1142    
1143     <dt><tt>int16 <b>os_priv</b></tt></dt>
1144     <dd>The nickname group's privilege level with respect to OperServ.
1145     Can be any value, but typically either zero (no special
1146     privileges) or one of the following values:
1147     <ul>
1148     <li><b><tt>NP_SERVOPER</tt>:</b> Services operator privilege.</li>
1149     <li><b><tt>NP_SERVADMIN</tt>:</b> Services administrator
1150     privilege.</li>
1151     </ul>
1152     Other values are treated by the OperServ privilege checking code
1153     (see <a href="#s2-1">section 7-2-1</a>) as having the next lowest
1154     recognized value.</dd>
1155    
1156     <dt><tt>int32 <b>authcode</b></tt></dt>
1157     <dd>The authentication code set for the nickname group, or zero if no
1158     code is set. See <a href="#s3-5">section 7-3-5</a>.</dd>
1159    
1160     <dt><tt>time_t <b>authset</b></tt></dt>
1161     <dd>The timestamp when the nickname group's authentication code was
1162     set (meaningless if no code is set).</dd>
1163    
1164     <dt><tt>int16 <b>authreason</b></tt></dt>
1165     <dd>The reason the nickname group's current authentication code was
1166     set (meaningless if no code is set). One of the following
1167     constants:
1168     <ul>
1169     <li><b><tt>NICKAUTH_REGISTER</tt>:</b> The nickname was newly
1170     registered, and the E-mail address provided in the
1171     <tt>REGISTER</tt> command requires authentication.</li>
1172     <li><b><tt>NICKAUTH_SET_EMAIL</tt>:</b> The nickname group's
1173     E-mail address was changed with the <tt>SET EMAIL</tt>
1174     command, and the new address requires authentication.</li>
1175     <li><b><tt>NICKAUTH_SETAUTH</tt>:</b> Authentication is required as
1176     the result of a Services administrator using the
1177     <tt>SETAUTH</tt> command.</li>
1178     <li><b><tt>NICKAUTH_REAUTH</tt>:</b> Authentication is required as
1179     the result of the nickname owner using the <tt>REAUTH</tt>
1180     command.</li>
1181     </ul></dd>
1182    
1183     <dt><tt>char <b>suspend_who</b>[NICKMAX]</tt></dt>
1184     <dd>The nickname of the client that suspended the nickname group
1185     (meaningless if the <tt>NF_SUSPENDED</tt> flag is not set).</dd>
1186    
1187     <dt><tt>char *<b>suspend_reason</b></tt></dt>
1188     <dd>The reason the nickname group was suspended (meaningless if the
1189     <tt>NF_SUSPENDED</tt> flag is not set).</dd>
1190    
1191     <dt><tt>time_t <b>suspend_time</b></tt></dt>
1192     <dd>The timestamp when the nickname group was suspended (meaningless if
1193     the <tt>NF_SUSPENDED</tt> flag is not set).</dd>
1194    
1195     <dt><tt>time_t <b>suspend_expires</b></tt></dt>
1196     <dd>The timestamp at which the nickname group's suspension expires
1197     (meaningless if the <tt>NF_SUSPENDED</tt> flag is not set).</dd>
1198    
1199     <dt><tt>int16 <b>language</b></tt></dt>
1200     <dd>The language preferred for messages sent to the nickname group.
1201     One of the <tt>LANG_*</tt> constants in the Services core's
1202     <tt>language.h</tt>.</dd>
1203    
1204     <dt><tt>int16 <b>timezone</b></tt></dt>
1205     <dd>The time zone offset specified by the nickname group's owner for
1206     use in displaying times. A number of minutes (possibly negative)
1207     to be added to the UTC timestamps, or <tt>TIMEZONE_DEFAULT</tt> to
1208     use the Services process' default.</dd>
1209    
1210     <dt><tt>int16 <b>channelmax</b></tt></dt>
1211     <dd>The maximum number of channels the nickname group is allowed to
1212     register, <tt>CHANMAX_UNLIMITED</tt> for no limit, or
1213     <tt>CHANMAX_DEFAULT</tt> for the default limit (set by the
1214     ChanServ <tt>CSMaxReg</tt> configuration setting).</dd>
1215    
1216     <dt><tt>char **<b>access</b></tt>
1217     <br/><tt>int <b>access_count</b></tt></dt>
1218     <dd>The nickname group's access list (see <a href="#s3-2">section
1219     7-3-2</a>).</dd>
1220    
1221     <dt><tt>char **<b>ajoin</b></tt>
1222     <br/><tt>int <b>ajoin_count</b></tt></dt>
1223     <dd>The nickname group's auto-join list (see <a href="#s3-3">section
1224     7-3-3</a>).</dd>
1225    
1226     <dt><tt>char **<b>ignore</b></tt>
1227     <br/><tt>int <b>ignore_count</b></tt></dt>
1228     <dd>The nickname group's memo ignore list (see <a href="#s5-2">section
1229     7-5-2</a>).</dd>
1230    
1231     <dt><tt>MemoInfo <b>memos</b></tt></dt>
1232     <dd>The nickname group's stored memos (see <a href="#s5-1">section
1233     7-5-1</a>).</dd>
1234    
1235     <dt><tt>channame_t *<b>channels</b></tt>
1236     <br/><tt>int <b>channels_count</b></tt></dt>
1237     <dd><i>Not saved to persistent storage.</i> The names of the channels
1238     currently registered by this nickname group.</dd>
1239    
1240     <dt><tt>User **<b>id_users</b></tt>
1241     <br/><tt>int <b>id_users_count</b></tt></dt>
1242     <dd><i>Not saved to persistent storage.</i> Pointers to <tt>User</tt>
1243     structures for clients which have identified for this nickname
1244     group.</dd>
1245    
1246     <dt><tt>time_t <b>last_sendauth</b></tt></dt>
1247     <dd><i>Not saved to persistent storage.</i> The timestamp when the
1248     <tt>SENDAUTH</tt> command was last used for this nickname group
1249     (see <a href="#s3-5">section 7-3-5</a>).</dd>
1250    
1251     <dt><tt>int <b>bad_auths</b></tt></dt>
1252     <dd><i>Not saved to persistent storage.</i> The number of times the
1253     <tt>AUTH</tt> command has been used with a bad authentication code
1254     for this nickname group (see <a href="#s3-5">section 7-3-5</a>).</dd>
1255     </dl>
1256    
1257     <p>In addition, <tt>nickserv.h</tt> declares the following convenience
1258     functions and macros:</p>
1259    
1260     <dl>
1261     <dt><tt>int <b>nick_recognized</b>(const NickInfo *<i>ni</i>)</tt>
1262     <br/><tt>int <b>user_recognized</b>(const User *<i>u</i>)</tt></dt>
1263     <dd>Returns whether the given client is recognized via an access list
1264     entry, regardless of whether the client has identified for the
1265     nickname group or not. The client can be specified by either
1266     <tt>NickInfo</tt> or <tt>User</tt> structure. (Nickname
1267     authorization flags are always cleared when a client disconnects
1268     from the network, so the <tt>NickInfo</tt> form will always return
1269     false if used on a nickname not currently in use.)</dd>
1270    
1271     <dt><tt>int <b>nick_identified</b>(const NickInfo *<i>ni</i>)</tt>
1272     <br/><tt>int <b>user_identified</b>(const User *<i>u</i>)</tt></dt>
1273     <dd>Returns whether the given client has identified for its nickname.
1274     The client can be specified by either <tt>NickInfo</tt> or
1275     <tt>User</tt> structure.</dd>
1276    
1277     <dt><tt>int <b>nick_id_or_rec</b>(const NickInfo *<i>ni</i>)</tt>
1278     <br/><tt>int <b>user_id_or_rec</b>(const User *<i>u</i>)</tt></dt>
1279     <dd>Returns whether the given client is recognized via access list or
1280     has identified for its nickname (or both). The client can be
1281     specified by either <tt>NickInfo</tt> or <tt>User</tt> structure.</dd>
1282    
1283     <dt><tt>int <b>nick_ident_nomail</b>(const NickInfo *<i>ni</i>)</tt>
1284     <br/><tt>int <b>user_ident_nomail</b>(const User *<i>u</i>)</tt></dt>
1285     <dd>Returns whether the <tt>NA_IDENT_NOMAIL</tt> flag is set for the
1286     given client; <i>i.e.,</i> evaluates to true when has identified
1287     for its nickname but the nickname lacks a required E-mail address.
1288     The client can be specified by either <tt>NickInfo</tt> or
1289     <tt>User</tt> structure.</dd>
1290    
1291     <dt><tt>int <b>ngi_unauthed</b>(const NickGroupInfo *<i>ngi</i>)</tt></dt>
1292     <dd>Returns whether the given nickname group (more accurately, the
1293     nickname group's E-mail address) is unauthenticated. Note that use
1294     of the <tt>REAUTH</tt> command does not cause the nickname group to
1295     lose its authenticated status.</dd>
1296    
1297     <dt><tt>int <b>valid_ngi</b>(const NickGroupInfo *<i>ngi</i>)</tt></dt>
1298     <dd>Returns whether the given <tt>NickGroupInfo</tt> structure pointer
1299     is valid; <i>i.e.,</i> evaluates to true when <tt><i>ngi</i></tt>
1300     is neither <tt>NULL</tt> nor <tt>NICKGROUPINFO_INVALID</tt>. (The
1301     latter value is used in <tt>User</tt> structures to indicate that
1302     the client has an associated <tt>NickInfo</tt> structure but no
1303     <tt>NickGroupInfo</tt> structure, as is the case for forbidden
1304     nicknames.)</dd>
1305    
1306     <dt><tt>const char *<b>ngi_mainnick</b>(const NickGroupInfo *<i>ngi</i>)</tt></dt>
1307     <dd>Returns the given nickname group's main nickname.</dd>
1308    
1309     <dt><tt>NickGroupInfo *<b>get_ngi</b>(const NickInfo *<i>ni</i>)</tt>
1310     <br/><tt>NickGroupInfo *<b>get_ngi_id</b>(uint32 <i>id</i>)</tt></dt>
1311     <dd>Retrieves the <tt>NickGroupInfo</tt> record corresponding to the
1312     given <tt>NickInfo</tt> or ID value; if there is no corresponding
1313     record, a warning message is logged and <tt>NULL</tt> is returned.
1314     (Like any other database "get" routine, the structure must be "put"
1315     with <tt>put_nickgroupinfo()</tt> when no longer needed.)</dd>
1316    
1317     <dt><tt>int <b>check_ngi</b>(const NickInfo *<i>ni</i>)</tt>
1318     <br/><tt>int <b>check_ngi_id</b>(uint32 <i>id</i>)</tt></dt>
1319     <dd>Returns whether there is a corresponding <tt>NickGroupInfo</tt>
1320     record for the given <tt>NickInfo</tt> or ID value, logging a
1321     warning message if not. (The
1322     <tt>put_<i>xxx</i>(get_<i>xxx</i>(...))</tt> is a common way of
1323     checking for the existence of a record, since the
1324     <tt>put_<i>xxx</i>()</tt> explicitly allow a <tt>NULL</tt>
1325     parameter.)</dd>
1326     </dl>
1327    
1328     <p>The <tt>STANDALONE_NICKSERV</tt> define and (non-macro) utility
1329     functions are discussed in <a href="#s3-1-4">section 7-3-1-4</a>.</p>
1330    
1331     <p class="backlink"><a href="#top">Back to top</a></p>
1332    
1333    
1334     <h5 class="subsubsubsection-title" id="s3-1-2">7-3-1-2. Overall module structure</h5>
1335    
1336     <p>The overall structure of the NickServ module generally follows the same
1337     pattern as the OperServ module: variable and command declarations, database
1338     handling, <tt>PRIVMSG</tt> and other callbacks, and command routines.</p>
1339    
1340     <p>The <tt>nickserv/main</tt> module uses two separate databases, one for
1341     <tt>NickInfo</tt> records and one for <tt>NickGroupInfo</tt> records. The
1342     database handling code is more or less straightforward, using <tt>hash.h</tt>
1343     to maintain the in-memory tables; however, since most of the record
1344     management routines take additional actions (for example, the "add" and
1345     "get" functions update the record's use count), the base hash functions are
1346     defined with a trailing underscore, like <tt>add_nickinfo_()</tt>, and the
1347     actual functions (like <tt>add_nickinfo()</tt>) are wrapped around these.
1348     NickServ exports all of the <tt>NickInfo</tt> and <tt>NickGroupInfo</tt>
1349     database functions, as well as a "put" function for each record type.</p>
1350    
1351     <p>When saving the databases to persistent storage, the <tt>nicks[]</tt>
1352     array and <tt>mainnick</tt> field of <tt>NickGroupInfo</tt> records are not
1353     saved directly; rather, the main nickname itself is saved as a
1354     <tt>NICKMAX</tt>-sized buffer, and the nickname group is initialized with
1355     this nickname when first loaded (the array is subsequently filled in when
1356     the relevant <tt>NickInfo</tt> records are loaded).</p>
1357    
1358     <p>NickServ keeps track of clients' status using callback functions for
1359     new clients, clients changing nickname, and disconnecting clients. The
1360     routines that do the actual processing, <tt>validate_user()</tt> (for a
1361     client starting to use a nickname) and <tt>cancel_user()</tt> (for a client
1362     no longer using a nickname), are located in <tt>util.c</tt>, discussed in
1363     <a href="#s3-1-4">section 7-3-1-4</a>.</p>
1364    
1365     <p>The NickServ commands themselves tend to be fairly complex, especially
1366     when compared to the OperServ command handlers. This is in part due to the
1367     wide range of features available in NickServ, and in part due to the fact
1368     that NickServ and its system of registered nicknames are the primary way by
1369     which clients authenticate themselves, and as such must handle a variety of
1370     circumstances to maintain security, while other pseudoclients simply rely
1371     on the authorization flags set by NickServ. The following command handlers
1372     are particularly worthy of note:</p>
1373    
1374     <dl>
1375     <dt><b><tt>do_help()</tt></b></dt>
1376     <dd>NickServ's commands include a number whose help text changes based
1377     on factors such as the requesting client's IRC operator status,
1378     features available in the IRC protocol in use, and NickServ
1379     configuration settings. The code to handle help requests is
1380     accordingly complex, with many commands unable to rely on the
1381     <tt>help_cmd()</tt> routine.</dd>
1382    
1383     <dt><b><tt>do_register()</tt></b></dt>
1384     <dd>Just as NickServ is the gateway to the rest of Services' functions,
1385     the <tt>REGISTER</tt> command is the gateway to NickServ, providing
1386     one of the two methods by which a client can gain access to
1387     Services (the other being authentication to a previously registered
1388     nickname). The <tt>REGISTER</tt> handler must therefore be
1389     particularly careful to guard against abuse, both to prevent
1390     improper access to other Services commands and to prevent the
1391     <tt>REGISTER</tt> command itself from being abused by arbitrary
1392     clients. The command handler takes the following precautions
1393     before allowing a nickname to be registered:
1394     <ul>
1395     <li class="spaced">Prevents the command from being used by any
1396     particular client more than once every <tt>NSRegDelay</tt>
1397     seconds. This stops mass-registration of nicknames by
1398     automated clients, avoiding both the accompanying load on
1399     Services itself (more memory usage, more time spent looking
1400     up nicknames) and any undesirable side effects, such as the
1401     sending of automated E-mail to arbitrary address when mail
1402     authentication is in use (see <a href="#s3-5">section
1403     7-3-5</a>).</li>
1404     <li class="spaced">Prevents the command from being used by a client
1405     within <tt>NSInitialRegDelay</tt> seconds of connecting to
1406     the network. This prevents automated clients from getting
1407     around the <tt>NSRegDelay</tt> limitation by repeatedly
1408     connecting, issuing a <tt>REGISTER</tt> command, and
1409     disconnecting in rapid succession. (It is still possible
1410     to avoid the limitation by connecting a large number of
1411     clients at once, but as a practical matter it is impossible
1412     for NickServ to distinguish such attempts from ordinary
1413     registration requests, and the sudden presence of a large
1414     number of clients on the network should itself be an
1415     indication of trouble.)</li>
1416     <li class="spaced">Prevents "guest" nicknames from being
1417     registered, which could result in unauthenticated clients
1418     suddenly gaining Services access after a forced nickname
1419     change. (The check itself is performed by the
1420     <tt>do_reglink_check()</tt> earlier in <tt>main.c</tt>,
1421     a callback function attached to the "<tt>REGISTER/LINK
1422     check</tt>" callback; <tt>do_register()</tt> calls this
1423     callback via the <tt>reglink_check()</tt> function in
1424     <tt>util.c</tt>.)</li>
1425     <li class="spaced">Ensures that the nickname is not already
1426     registered. Ordinarily, if a nickname is registered then
1427     the client's <tt>User</tt> structure will have a pointer to
1428     the record in its <tt>ni</tt> field, but if the nickname is
1429     missing a corresponding nickname group (a database error
1430     unless the nickname is forbidden), the <tt>ni</tt> field
1431     will be <tt>NULL</tt> and the <tt>ngi</tt> field will be
1432     set to the constant <tt>NICKGROUPINFO_INVALID</tt>, so that
1433     combination is checked for as well. Also, just in case,
1434     <tt>do_register()</tt> performs a final check by accessing
1435     the database directly, to ensure that the nickname is not
1436     registered in duplicate.</li>
1437     <li class="spaced">Checks that the E-mail address, if given, is (1)
1438     syntactically valid and (2) not disallowed due to a
1439     <tt>RejectEmail</tt> configuration directive.</li>
1440     <li class="spaced">Prevents more than <tt>NSRegEmailMax</tt>
1441     nicknames from being registered to the same address, again
1442     to avoid undue load on Services from a registration flood.
1443     This check calls <tt>count_nicks_with_email()</tt> to
1444     actually count nicknames; this routine has to search the
1445     entire nickname database, which can take a significant
1446     amount of time if many nicknames are registered, so this
1447     check is performed last.</li>
1448     <li class="spaced">As an adjunct to the previous check (and
1449     regardless of the setting of <tt>NSRegEmailMax</tt>), also
1450     prevents a nickname from being registered if the E-mail
1451     address given is already in use by another nickname which
1452     is awaiting mail authentication; this acts as a further
1453     guard to prevent a particular mail address from getting
1454     "mailbombed" by multiple registration requests that make it
1455     through the previous checks.</li>
1456     </ul></dd>
1457    
1458     <dt><b><tt>do_dropemail()</tt></b>
1459     <br/><b><tt>do_dropemail_confirm()</tt></b></dt>
1460     <dd>The <tt>DROPEMAIL</tt> and <tt>DROPEMAIL-CONFIRM</tt> commands are
1461     the only two commands in Services that require state to be kept
1462     specifically for those commands. Due to the potential for data
1463     loss through an erroneous <tt>DROPEMAIL</tt> command, some form of
1464     confirmation was desired, such as an "Are you sure?" requester in
1465     response to a user deleting a file in a GUI. Since Services'
1466     interface is limited to single-line commands, however, this can
1467     only be accomplished through two commands, the second of which
1468     (<tt>DROPEMAIL-CONFIRM</tt>) serves to confirm the action requested
1469     by the first (<tt>DROPEMAIL</tt>). In order for this to be
1470     effective, the <tt>DROPEMAIL-CONFIRM</tt> handler must know which
1471     commands have been sent by whom, so that clients cannot send
1472     arbitrary <tt>DROPEMAIL-CONFIRM</tt> commands to get around the
1473     confirmation check. This is accomplished through the file-local
1474     <tt>dropemail_buffer[]</tt> array, which holds the most recently
1475     issued, unconfirmed <tt>DROPEMAIL</tt> commands. (A single state
1476     record stored in the <tt>User</tt> structure was another
1477     possibility, but one that was discarded to avoid bloat in that
1478     structure, particularly since the vast majority of clients would
1479     never use the command anyway.) When a valid <tt>DROPEMAIL</tt>
1480     command is given, the client is told the number of nicknames that
1481     would be deleted, and the given mask is stored in the buffer array,
1482     with the oldest unconfirmed mask removed if no slots are empty. A
1483     <tt>DROPEMAIL-CONFIRM</tt> for the same mask will then locate the
1484     appropriate buffer slot, ensure that the same client sent both
1485     commands and that the elapsed time between the two commands is not
1486     too long (as defined by the <tt>NSDropEmailExpire</tt> option), and
1487     performs the actual nickname deletion.</dd>
1488    
1489     <dt><tt><b>do_info()</b></tt></dt>
1490     <dd>The <tt>INFO</tt> command has the ability to show extended
1491     information about a nickname with the option <tt>ALL</tt> (only
1492     available to the nickname owner or Services administrators).
1493     However, not all nicknames have any additional information to be
1494     displayed. To prevent the "use <tt>ALL</tt> for more information"
1495     message from being appended if there is not actually anything else
1496     to show, the <tt>INFO</tt> command handler uses a method inspired
1497     by super-user privilege checks in the Linux kernel, which keeps
1498     track of whether a process has taken advantage of those privileges.
1499     When the macro <tt>CHECK_SHOW_ALL</tt> is included in a conditional
1500     test, it will evaluate to true when the <tt>ALL</tt> option is
1501     present (and the client has permission to use it), but a separate
1502     flag variable, <tt>used_all</tt>, will also be set regardless of
1503     the presence of <tt>ALL</tt>; the routine can then determine
1504     whether there were any items that would have been displayed if
1505     <tt>ALL</tt> was given. As noted in the source code comments, the
1506     macro should be the last test in any conditional expression which
1507     uses it, to prevent <tt>used_all</tt> from being set for an item
1508     that will not actually be displayed due to a subsequent test.</dd>
1509    
1510     <dt><tt><b>do_set()</b></tt>
1511     <br/><tt><b>do_unset()</b></tt></dt>
1512     <dd>As the <tt>SET</tt> and <tt>UNSET</tt> commands (<tt>SET</tt> in
1513     particular) have a large number of options, they are defined in a
1514     separate source file, <tt>set.c</tt>. See
1515     <a href="#s3-1-3">section 7-3-1-3</a> for details.</dd>
1516     </dl>
1517    
1518     <p>NickServ also includes a debug command enabled by the
1519     <tt>DEBUG_COMMANDS</tt> preprocessor symbol: <tt>LISTNICK</tt>, which
1520     displays the <tt>NickInfo</tt> and (if present) <tt>NickGroupInfo</tt> data
1521     for a given nickname.</p>
1522    
1523     <p>In addition to the ordinary module setup code, the
1524     <tt>nickserv/main</tt> module supports two command-line options. One,
1525     <tt>-encrypt-all</tt>, is recognized by the Services core; NickServ's
1526     <tt>init_module()</tt> routine checks the corresponding global flag,
1527     <tt>encrypt_all</tt> and, if it is set, encrypts all nicknames using the
1528     encryption type specified by the core's <tt>EncryptionType</tt> setting.
1529     The other option, <tt>-clear-nick-email</tt>, is NickServ-specific, and is
1530     handled by <tt>do_command_line()</tt>, a callback function for the core's
1531     "<tt>command line</tt>" callback; when the option is encountered, the
1532     callback function clears the E-mail address from all nickname groups.</p>
1533    
1534     <p>As several messages used by NickServ can change based on configuration
1535     options or the features available in the IRC server, the initialization and
1536     cleanup code (as well as the reconfiguration handler,
1537     <tt>do_reconfigure()</tt>) call <tt>mapstring()</tt> to adjust the messages
1538     appropriately. The commands <tt>REGISTER</tt>,
1539     <tt>DROPEMAIL</tt>/<tt>DROPEMAIL-CONFIRM</tt>, and <tt>GETPASS</tt> can
1540     also be disabled by configuration options; the commands are disabled by
1541     setting the <tt>name</tt> field of the corresponding <tt>Command</tt>
1542     structure to the empty string, so that it will not be found when the
1543     command table is searched. Pointers to the structures are saved in
1544     file-local variables so that the names can be restored at reconfiguration
1545     or module cleanup time.</p>
1546    
1547     <p class="backlink"><a href="#top">Back to top</a></p>
1548    
1549    
1550     <h5 class="subsubsubsection-title" id="s3-1-3">7-3-1-3. The <tt>SET</tt> and <tt>UNSET</tt> commands</h5>
1551    
1552     <p>The handlers for the <tt>SET</tt> and <tt>UNSET</tt> commands,
1553     <tt>do_set()</tt> and <tt>do_unset()</tt> in <tt>set.c</tt>, work much like
1554     miniature versions of the top-level NickServ message handler
1555     <tt>nickserv()</tt>, in that they check which option name was used with the
1556     command and call an appropriate subroutine to do the actual work. However,
1557     the <tt>do_set()</tt> routine parses the option parameters itself, rather
1558     than leave such parsing to the individual routines (<tt>UNSET</tt> does not
1559     take any additional parameters, so no such parsing is needed); for this
1560     reason, the setup code in <tt>do_set()</tt> is more complex than that in
1561     <tt>nickserv()</tt>, since the <tt>INFO</tt> option treats the entire line
1562     as a single parameter, <tt>HIDE</tt> takes two single-word parameters
1563     separated by a space, and the other options take a single one-word
1564     parameter.</p>
1565    
1566     <p>Additionally, both <tt>SET</tt> and <tt>UNSET</tt> can be used by
1567     Services administrators to set options for other users' nicknames. For
1568     this reason, the individual option-setting routines take both a
1569     <tt>User&nbsp;*</tt> and a <tt>NickInfo&nbsp;*</tt> parameter, where the
1570     <tt>NickInfo&nbsp;*</tt> parameter is the nickname whose options are to be
1571     changed (if the client giving the command is not a Services administrator
1572     or does not give a target nickname, this will simply be equal to the
1573     <tt>ni</tt> field of the <tt>User</tt> structure). <i>Implementation note:
1574     This raises an interesting problem&mdash;how does an option's handler
1575     routine tell the difference between <tt>SET <i>option</i></tt>, <tt>SET
1576     !MyNick <i>option</i></tt>, and <tt>SET !OtherNick <i>option</i></tt> when
1577     sending result messages? The simple answer is that it doesn't: all option
1578     handlers use the "your nick" message style, as mentioned in
1579     <a href="../d.html">Appendix D of the user's manual</a>. If implemented,
1580     it would probably be reasonable to ignore the distinction between the
1581     <tt>SET <i>option</i></tt> and <tt>SET !MyNick <i>option</i></tt> cases,
1582     and simply judge which message to use by comparing the <tt>NickInfo</tt>
1583     parameter with the <tt>ni</tt> field of the client's <tt>User</tt>
1584     structure.</i></p>
1585    
1586     <p>The option handlers themselves are simple for the most part, checking
1587     the option value given and setting or clearing the relevant flag or field
1588     in the <tt>NickInfo</tt> structure or its associated <tt>NickGroupInfo</tt>
1589     structure. Routines which deserve special mention are:</p>
1590    
1591     <dl>
1592     <dt><b><tt>do_set_password()</tt></b></dt>
1593     <dd>The password setting itself is straightforward (note that the
1594     memory containing the cleartext password and the temporary copy of
1595     the encrypted password is cleared as soon as it is no longer
1596     needed); however, the routine first checks the
1597     <tt>NSSecureAdmins</tt> option, and disallows the change if the
1598     target is a (different) Services administrator and the command
1599     sender is not the Services super-user.</dd>
1600    
1601     <dt><b><tt>do_set_email()</tt></b></dt>
1602     <dd>This routine makes several checks mostly related to mail
1603     authentication before allowing the E-mail address to be changed:
1604     <ul>
1605     <li>The address must be a valid E-mail address.</li>
1606     <li>The address must not be rejected by a <tt>RejectEmail</tt>
1607     configuration directive.</li>
1608     <li>The address must not be in use by a nickname awaiting mail
1609     authentication (as with <tt>REGISTER</tt>).</li>
1610     <li>The number of nicknames currently using the address must be
1611     less than <tt>NSRegEmailMax</tt>, if set. (Note that if
1612     the current nickname's group contains other linked
1613     nicknames, the E-mail address change can cause the nickname
1614     total to exceed <tt>NSRegEmailMax</tt>. This is not seen as
1615     a significant problem, and it avoids the opposite problem in
1616     which a user who somehow exceeded the limit would no longer
1617     be able to change their E-mail address at all.)</li>
1618     <li>The time since the last successful <tt>SET EMAIL</tt> must be
1619     at least <tt>NSSetEmailDelay</tt> seconds, if set.</li>
1620     </ul>
1621     If the above checks all pass, the change is performed, and if the
1622     client used to have the <tt>NA_IDENT_NOMAIL</tt> status and an
1623     E-mail address was set, the status is changed to
1624     <tt>NA_IDENTIFIED</tt>. The routine also features its own
1625     callback, "<tt>SET EMAIL</tt>", used by the mail authentication
1626     code. Note that this routine does <i>not</i> check the
1627     <tt>NSRequireEmail</tt> configuration option, and assumes that if
1628     it is passed a <tt>NULL</tt> value, indicating that the address
1629     should be unset, then that is valid. (In fact, <tt>do_unset()</tt>
1630     checks <tt>NSRequireEmail</tt> before calling
1631     <tt>do_set_email()</tt>.)</dd>
1632    
1633     <dt><b><tt>do_set_timezone()</tt></b></dt>
1634     <dd><tt>SET TIMEZONE</tt> allows the time zone to be specified as
1635     either a literal time offset (-5, +6:30, etc.) or a time zone
1636     name. Time zone names (other than "GMT+/-<i>n</i>" and
1637     "UTC+/-<i>n</i>", which are treated as literal offsets) are parsed
1638     using the <tt>timezones[]</tt> table defined just above the
1639     <tt>do_set_timezone()</tt> routine itself, which (hopefully)
1640     includes most common time zones; the table can of course be
1641     modified to include other time zones as particular networks
1642     desire. Once the the time zone has been set, a message is sent to
1643     the calling client giving the current time in the resulting time
1644     zone; however, this is tricky if the calling client is a Services
1645     administrator changing the setting for another nickname, because
1646     <tt>strftime_lang()</tt> always uses the time zone setting of the
1647     nickname used to select the language. To get around this, the
1648     routine determines the difference between the calling nickname's
1649     time zone and the target nickname's time zone, adjusting the
1650     timestamp passed to <tt>strftime_lang()</tt> by that amount
1651     (multiplied by 60, since the <tt>timezone</tt> field is specified
1652     in minutes). Incidentally, support for "daylight saving time"
1653     as used in some countries was deliberately omitted, partly due to
1654     the difficulty of supporting the various systems used in different
1655     countries, and partly because the details of such systems are
1656     highly dependent upon each country's political landscape and can
1657     change at any time (witness the abrupt extension to DST proposed,
1658     and eventually implemented, in the United States of America in
1659     2006).</dd>
1660     </dl>
1661    
1662     <p class="backlink"><a href="#top">Back to top</a></p>
1663    
1664    
1665     <h5 class="subsubsubsection-title" id="s3-1-4">7-3-1-4. NickServ utility routines</h5>
1666    
1667     <p>Most of the utility routines used by NickServ are collected in the file
1668     <tt>util.c</tt>. This file has two functions: aside from providing utility
1669     functions to NickServ itself (several of which are exported for use by
1670     other modules), it can also be <tt>#include</tt>'d in an external source
1671     file to provide definitions of the four routines <tt>new_nickinfo()</tt>,
1672     <tt>free_nickinfo()</tt>, <tt>new_nickgroupinfo()</tt>, and
1673     <tt>free_nickgroupinfo()</tt>, so that such files do not have to define
1674     similar routines themselves. This latter mode is activated by defining
1675     the <tt>STANDALONE_NICKSERV</tt> preprocessor symbol, as documented in the
1676     comments at the top of <tt>util.c</tt>. In this case, only the four
1677     routines mentioned above are defined, with the rest of the file commented
1678     out using <tt>#ifndef</tt>; additionally, the <tt>new_nickgroupinfo()</tt>
1679     routine does not check for the presence of the nickname group IDs it
1680     generates, as it cannot assume that <tt>get_nickgroupinfo()</tt> is
1681     available.</p>
1682    
1683     <p>With respect to its primary use as part of NickServ, <tt>util.c</tt>
1684     defines the following routines:</p>
1685    
1686     <dl>
1687     <dt><tt>NickInfo *<b>new_nickinfo</b>()</tt></dt>
1688     <dd>Returns a pointer to a newly-allocated and initialized
1689     <tt>NickInfo</tt> structure. (For creating a new record in the
1690     database, <tt>makenick()</tt> is preferred; see below.)</dd>
1691    
1692     <dt><tt>void <b>free_nickinfo</b>(NickInfo *<i>ni</i>)</tt></dt>
1693     <dd>Frees the given <tt>NickInfo</tt> structure and all associated
1694     data. (See <tt>delnick()</tt> below for removing a nickname
1695     record from the database.)</dd>
1696    
1697     <dt><tt>NickGroupInfo *<b>new_nickgroupinfo</b>(const char *<i>seed</i>)</tt></dt>
1698     <dd>Returns a pointer to a newly-allocated and initialized
1699     <tt>NickGroupInfo</tt> structure. If <tt><i>seed</i></tt> is not
1700     <tt>NULL</tt>, then it is used to generate an initial ID value for
1701     the nickname group; if that ID value is used, new values are
1702     randomly generated until an unused one is found. (If the code
1703     loops <tt>NEWNICKGROUP_TRIES</tt> times without finding an unused
1704     value, an error is returned; assuming a good random number
1705     generator, the default value of 1000 should ensure success on
1706     typical databases. <tt>NEWNICKGROUP_TRIES</tt> is defined in
1707     <tt>ns-local.h</tt>.) If <tt><i>seed</i></tt> is <tt>NULL</tt>,
1708     then the new nickname group's ID is left at zero.</dd>
1709    
1710     <dt><tt>void <b>free_nickgroupinfo</b>(NickGroupInfo *<i>ngi</i>)</tt></dt>
1711     <dd>Frees the given <tt>NickGroupInfo</tt> structure and all associated
1712     data. (See <tt>delgroup()</tt> below for removing a nickname group
1713     and all its nicknames from the database.)</dd>
1714    
1715     <dt><tt>NickGroupInfo *<b>_get_ngi</b>(NickInfo *<i>ni</i>,
1716     const char *<i>file</i>, int <i>line</i>)</tt>
1717     <br/><tt>NickGroupInfo *<b>_get_ngi_id</b>(uint32 <i>id</i>,
1718     const char *<i>file</i>, int <i>line</i>)</tt></dt>
1719     <dd>Implement the <tt>get_ngi()</tt> and <tt>get_ngi_id()</tt> macros,
1720     respectively. <tt><i>file</i></tt> and <tt><i>line</i></tt> are
1721     the source file and line from which the function was called, and
1722     are filled in by the corresponding macro with <tt>__FILE__</tt> and
1723     <tt>__LINE__</tt>.</dd>
1724    
1725     <dt><tt>int <b>has_identified_nick</b>(const User *<i>u</i>, uint32 <i>group</i>)</tt></dt>
1726     <dd>Returns whether the given client has identified for the nickname
1727     group indicated by <tt><i>group</i></tt>.</dd>
1728    
1729     <dt><tt>int <b>reglink_check</b>(User *<i>u</i>, const char *<i>nick</i>,
1730     char *<i>password</i>, char *<i>email</i>)</tt></dt>
1731     <dd>Calls the "<tt>REGISTER/LINK check</tt>" callback and returns its
1732     result. (A utility function is used rather than directly calling
1733     <tt>call_callback_4()</tt> because the <tt>nickserv/link</tt>
1734     module needs to make use of the callback as well, and the module
1735     system does not allow one module to call another's callbacks (which
1736     would be bad design in any case).</dd>
1737    
1738     <dt><tt>void <b>update_userinfo</b>(const User *<i>u</i>)</tt></dt>
1739     <dd>Updates the user information for the client's nickname. The
1740     <tt>NickInfo</tt> fields <tt>last_usermask</tt>,
1741     <tt>last_realmask</tt>, and <tt>last_realname</tt> are set from
1742     the corresponding fields of the <tt>User</tt> structure, and the
1743     <tt>last_seen</tt> field is set to the current time.
1744     <tt><i>u</i>-&gt;ni</tt> is assumed to be non-<tt>NULL</tt>.</dd>
1745    
1746     <dt><tt>int <b>validate_user</b>(User *<i>u</i>)</tt></dt>
1747     <dd>Sets the <tt>ni</tt> and <tt>ngi</tt> fields of the <tt>User</tt>
1748     structure to point to the <tt>NickInfo</tt> and associated
1749     <tt>NickGroupInfo</tt>, if any, for the client's nickname (if an
1750     error occurs looking up the nickname group, <tt><i>u</i>-&gt;ni</tt>
1751     is set to <tt>NULL</tt> and <tt><i>u</i>-&gt;ngi</tt> is set to
1752     <tt>NICKGROUP_INVALID</tt>); then compares the client's information
1753     with the nickname data and determines what level of access for the
1754     nickname should be granted to the client. Returns 1 if the client
1755     is granted either <tt>NA_IDENTIFIED</tt> or <tt>NA_RECOGNIZED</tt>
1756     access, otherwise zero.
1757    
1758     <p>This routine, along with the <tt>REGISTER</tt> command handler,
1759     is one of the two "points of entry" into Services, and as such is a
1760     critical point for Services security. This is particularly
1761     relevant for the section of code conditionally granting full
1762     (<tt>NA_IDENTIFIED</tt>) nickname access; while
1763     <tt>has_identified_nick()</tt>, mentioned above, operates purely on
1764     data which has been seen since Services started (specifically, the
1765     list of nicknames the client is known to have become identified
1766     for, maintained by <tt>set_identified()</tt>) and is comparatively
1767     safe, the second check, which matches the servicestamp, username,
1768     and hostname of the last client to identify with those of the
1769     current client, needs special attention to ensure that it does not
1770     allow clients to gain improper access. As noted in the comments in
1771     that section of code, the servicestamp provides a fairly high level
1772     of protection on servers which support it natively, while that
1773     level is reduced for servers which do not (such servers are rare
1774     nowadays). The entire section of code can be disabled with the
1775     <tt>NoSplitRecovery</tt> configuration option for added security.</p>
1776    
1777     <p>If the client is determined not to have identified for the
1778     nickname previously, the routine continues, determining whether to
1779     give <tt>NA_RECOGNIZED</tt> access. "Recognized" status is only
1780     implemented by access lists (see <a href="#s3-2">section 7-3-2</a>),
1781     and if the corresponding module is not loaded, the
1782     <tt>NA_RECOGNIZED</tt> flag will never be set on any nickname,
1783     except when set along with <tt>NA_IDENTIFIED</tt>. Likewise, if a
1784     nickname's <tt>NF_SECURE</tt> flag is set, then
1785     <tt>NA_RECOGNIZED</tt> will not be set (and zero will be returned
1786     from the routine) even if the client is in fact recognized.</p>
1787    
1788     <p>If the client is not identified or recognized for the nickname,
1789     <tt>validate_user()</tt> checks whether the client should be
1790     killed or nick-changed, setting an appropriate timeout or calling
1791     the collide routines (see <a href="#s3-1-5">section 7-3-1-5</a>
1792     below) depending on the nickname group settings. However, if the
1793     client was recognized (which will only be true if the nickname has
1794     the <tt>SECURE</tt> option set and thus <tt>NA_RECOGNIZED</tt> was
1795     not set), the kill checks are not performed, allowing the client to
1796     identify at its leisure.</p>
1797    
1798     <p>Finally, the routine checks the nickname's expiration time, and
1799     if it is due to expire "soon" (as defined by the
1800     <tt>NSExpireWarning</tt> configuration option), a warning notice is
1801     sent to the client.</p></dd>
1802    
1803     <dt><tt>void <b>cancel_user</b>(User *<i>u</i>)</tt></dt>
1804     <dd>Updates a client's nickname data when the client stops using the
1805     nickname. The <tt>last_seen</tt> field is updated if the client
1806     was either identified or recognized; the <tt>authstat</tt> field
1807     is cleared along with temporary status flags in the <tt>status</tt>
1808     field; an enforcer is introduced if the client was killed or
1809     nick-changed (see <a href="#s3-1-5">section 7-3-1-5</a>); the
1810     <tt>cancel user</tt>" callback is called; and any active nick
1811     collide timeouts are removed. The <tt>ni</tt> and <tt>ngi</tt>
1812     fields of the client's <tt>User</tt> structure are also reset to
1813     <tt>NULL</tt>.</dd>
1814    
1815     <dt><tt>void <b>set_identified</b>(User *<i>u</i>)</tt></dt>
1816     <dd>Marks the given client as having identified for the nickname it is
1817     currently using. In addition to setting the authentication status
1818     to <tt>NA_IDENTIFIED&nbsp;| NA_RECOGNIZED</tt> and updating the
1819     nickname's <tt>id_stamp</tt> field, the routine adds the nickname
1820     group ID to the list of nickname groups for which the client has
1821     identified, stored in the <tt>User</tt> structure and checked by
1822     <tt>has_identified_nick()</tt>.</dd>
1823    
1824     <dt><tt>NickInfo *<b>makenick</b>(const char *<i>nick</i>,
1825     NickGroupInfo **<i>nickgroup_ret</i>)</tt></dt>
1826     <dd>Creates a new <tt>NickInfo</tt> record with the given nickname,
1827     adds it to the database, and returns a pointer to the new record.
1828     If <tt><i>nickgroup_ret</i></tt> is not <tt>NULL</tt>, then a new
1829     <tt>NickGroupInfo</tt> record is also created for the nickname,
1830     the nickname's <tt>nickgroup</tt> field is set accordingly, and a
1831     pointer to the <tt>NickGroupInfo</tt> record (which is also added
1832     to the database) is stored in the variable pointed to by
1833     <tt><i>nickgroup_ret</i></tt>. Returns <tt>NULL</tt> on error.</dd>
1834    
1835     <dt><tt>int <b>delnick</b>(NickInfo *<i>ni</i>)</tt></dt>
1836     <dd>Removes the given nickname from the database and frees all
1837     resources used by the <tt>NickInfo</tt> structure. If the nickname
1838     was the last of its group, then the nickname group is deleted as
1839     well. Returns nonzero on success, zero on error.</dd>
1840    
1841     <dt><tt>int <b>delgroup</b>(NickGroupInfo *<i>ngi</i>)</tt></dt>
1842     <dd>Removes the given nickname group from the database, along with all
1843     associated nicknames. Returns nonzero on success, zero on error.</dd>
1844    
1845     <dt><tt>int <b>drop_nickgroup</b>(NickGroupInfo *<i>ngi</i>,
1846     const User *<i>u</i>, const char *<i>dropemail</i>)</tt></dt>
1847     <dd>Removes the given nickname group from the database, like
1848     <tt>delgroup()</tt>, but first log information about the nicknames
1849     to be deleted. <tt><i>u</i></tt> is the <tt>User</tt> structure
1850     for the client that sent the command resulting in the deletion.
1851     <tt><i>dropemail</i></tt> should be:
1852     <ul>
1853     <li><tt>NULL</tt> if the call is because of a <tt>DROP</tt> command
1854     from the nickname owner;</li>
1855     <li><tt>PTR_INVALID</tt> if the call is because of a <tt>DROPNICK</tt>
1856     command from a Services administrator;</li>
1857     <li>for a <tt>DROPEMAIL</tt> command, the parameter (address
1858     wildcard) used with the command.</li>
1859     </ul></dd>
1860    
1861     <dt><tt>void <b>suspend_nick</b>(NickGroupInfo *<i>ngi</i>,
1862     const char *<i>reason</i>, const char *<i>who</i>,
1863     const time_t <i>expires</i>)</tt></dt>
1864     <dd>Suspends the given nickname group, copying the parameters
1865     <tt><i>reason</i></tt>, <tt><i>who</i></tt>, and
1866     <tt><i>expires</i></tt> into the suspension data fields. (If
1867     <tt><i>expires</i></tt> is zero, then the suspension will not
1868     expire.)</dd>
1869    
1870     <dt><tt>void <b>unsuspend_nick</b>(NickGroupInfo *<i>ngi</i>, int <i>set_time</i>)</tt></dt>
1871     <dd>Cancels the suspension on the given nickname group. If
1872     <tt><i>set_time</i></tt> is nonzero, the last-seen time of each
1873     nickname in the group will be updated according to
1874     <tt>NSSuspendGrace</tt> to prevent the nickname from expiring for
1875     that length of time (if <tt>NSSuspendGrace</tt> or <tt>NSExpire</tt>
1876     are not set, or if the nickname already has enough time before
1877     expiration, the last-seen time will not be changed).</dd>
1878    
1879     <dt><tt>int <b>nick_check_password</b>(User *<i>u</i>, NickInfo *<i>ni</i>,
1880     const char *<i>password</i>, const char *<i>command</i>,
1881     int <i>failure_msg</i>)</tt></dt>
1882     <dd>Performs a password check for a nickname as part of a NickServ
1883     command. If the password is incorrect or an error occurs when
1884     checking, a notice will be sent to the client; a <tt>WALLOPS</tt>
1885     will also be sent for repeated bad password attempts on the same
1886     nickname. <tt><i>u</i></tt> is the <tt>User</tt> structure for
1887     the client that issued the command; <tt><i>ni</i></tt> is the
1888     <tt>NickInfo</tt> structure for the nickname whose password is
1889     being checked; <tt><i>password</i></tt> is the password given by
1890     the client, <tt><i>command</i></tt> is the name of the command
1891     being executed; and <tt><i>failure_msg</i></tt> is the index of the
1892     message (language string) to be sent if an error occurs when
1893     checking the password.</dd>
1894    
1895     <dt><tt>int <b>count_nicks_with_email</b>(const char *<i>email</i>)</tt></dt>
1896     <dd>Counts and returns the number of registered nicknames with the
1897     given E-mail address. If a nickname has the given address but it
1898     is awaiting mail authentication, the value returned is negative;
1899     for example, if there are five nicknames using a given address but
1900     the address is not authenticated, -5 would be returned. Note that
1901     this function must scan through the entire nickname database, so
1902     care should be taken not to call it too frequently.</dd>
1903     </dl>
1904    
1905     <p><tt>util.c</tt> also defines initialization and cleanup routines,
1906     <tt>init_util()</tt> and <tt>exit_util()</tt>, which take care of
1907     registering and unregistering the callbacks used by various utility
1908     functions. The routines are called as part of the <tt>nickserv/main</tt>
1909     module iniitialization and cleanup.</p>
1910    
1911     <p class="backlink"><a href="#top">Back to top</a></p>
1912    
1913    
1914     <h5 class="subsubsubsection-title" id="s3-1-5">7-3-1-5. Nickname colliding</h5>
1915    
1916     <p>In the general sense, a "nickname collision" is what happens when a
1917     client on an IRC network attempts to use a nickname that is already in use
1918     by another client. The original (RFC 1459) solution to this was to kill
1919     both clients, but with the advent of timestamps, most modern servers only
1920     kill one or the other depending on the timestamps of the two colliding
1921     clients. Early versions of Services took advantage of this behavior to
1922     implement kill protection: by introducing an "enforcer" pseudoclient with
1923     an appropriate timestamp, the old client would be killed and would not be
1924     able to reconnect with the same nickname.</p>
1925    
1926     <p>With respect to Services, then, "nickname colliding" is the act of
1927     forcing a client to stop using a particular nickname. While the nickname
1928     collision method itself has been abandoned, both to avoid depending on
1929     particular collision semantics and to provide a more meaningful disconnect
1930     message to the client ("Nick kill enforced" rather than an arbitrary server
1931     collision message), and although many modern IRC servers allow Services to
1932     forcibly change a client's nickname without going as far as disconnecting
1933     the client altogether, the term "colliding" is still used to refer to this
1934     set of actions.</p>
1935    
1936     <p>Nickname colliding functionality is provided by the file
1937     <tt>collide.c</tt>. This file provides two methods of colliding nicknames:
1938     directly, or via timeouts. The nickname colliding code also has its own
1939     initialization and cleanup functions (<tt>init_collide()</tt> and
1940     <tt>exit_collide()</tt>), which are called from the <tt>nickserv/main</tt>
1941     module initialization and cleanup routines.</p>
1942    
1943     <p>The following routines are used when colliding nicknames directly:</p>
1944    
1945     <dl>
1946     <dt><tt>void <b>collide_nick</b>(NickInfo *<i>ni</i>, int <i>from_timeout</i>)</tt></dt>
1947     <dd>Collides the given nickname, either killing the client using the
1948     nickname or forcibly changing the client's nickname to a "guest"
1949     nickname depending on configuration settings.
1950     <tt><i>from_timeout</i></tt> is used internally with collide
1951     timeouts, and should always be zero when called externally. This
1952     routine automatically calls <tt>introduce_enforcer()</tt> after
1953     the client has been killed or nick-changed (in the case of a
1954     forced nickname change, the enforcer is introduced by
1955     <tt>cancel_user()</tt> upon receipt of the <tt>NICK</tt> message
1956     indicating that the client's nickname has been changed). Any
1957     pending nickname collide or "433" timeouts (see below) on the
1958     nickname are cancelled by thie routine.</dd>
1959    
1960     <dt><tt>void <b>introduce_enforcer</b>(NickInfo *<i>ni</i>)</tt></dt>
1961     <dd>Introduces an enforcer pseudoclient for the given nickname, to
1962     prevent other clients from using the nickname. This routine
1963     automatically adds a timeout to call <tt>release_nick()</tt> after
1964     <tt>NSReleaseTimeout</tt> seconds have passed.</dd>
1965    
1966     <dt><tt>void <b>release_nick</b>(NickInfo *<i>ni</i>, int <i>from_timeout</i>)</tt></dt>
1967     <dd>Removes the enforcer pseudoclient for the given nickname, allowing
1968     other clients to use it again. As with <tt>collide_nick()</tt>,
1969     <tt><i>from_timeout</i></tt> is used internally with collide
1970     timeouts, and should always be zero when called externally. Any
1971     pending release timeouts on the nickname are cancelled by this
1972     routine.</dd>
1973     </dl>
1974    
1975     <p>Callers can also establish timeouts to collide or release a nick after
1976     a certain time. To avoid each caller having to include its own timeout
1977     handlers, <tt>collide.c</tt> provides two wrapper routines around the
1978     generic timeout functions:</p>
1979    
1980     <dl>
1981     <dt><tt>void <b>add_ns_timeout</b>(NickInfo *<i>ni</i>, int <i>type</i>,
1982     time_t <i>delay</i>)</tt></dt>
1983     <dd>Adds a timeout of the given type on the given nickname to occur in
1984     <tt><i>delay</i></tt> seconds. <tt><i>type</i></tt> can be any of
1985     the following:
1986     <ul>
1987     <li><b><tt>TO_COLLIDE</tt>:</b> A timeout for colliding a nickname
1988     (<tt>collide_nick()</tt> will be called).</li>
1989     <li><b><tt>TO_RELEASE</tt>:</b> A timeout for releasing the hold on
1990     a nickname (<tt>release_nick()</tt> will be called).</li>
1991     <li><b><tt>TO_SEND_433</tt>:</b> A timeout for sending the client
1992     using the nickname a "433" error message. (433 is the code
1993     for the <tt>ERR_NICKCOLLISION</tt> reply to a <tt>NICK</tt>
1994     message, and will cause most interactive client software to
1995     request a new nickname from the user. However, some server
1996     software has been known to disallow servers from sending
1997     433 replies to remote clients.)</li>
1998     </ul></dd>
1999    
2000     <dt><tt>void <b>rem_ns_timeout</b>(NickInfo *<i>ni</i>, int <i>type</i>,
2001     int <i>del_to</i>)</tt></dt>
2002     <dd>Removes any timeout of the given type on the given nickname;
2003     <tt><i>ni</i></tt> can be <tt>NULL</tt> to cause timeouts on all
2004     nicknames (of the given type) to be removed. <tt><i>type</i></tt>
2005     can be any of the type values used with <tt>add_ns_timeout()</tt>,
2006     or -1 to remove timeouts of all types. <tt><i>del_to</i></tt>
2007     should always be nonzero when called externally (the parameter is
2008     used for calling from within a timeout function, where it is not
2009     necessary to delete the <tt>Timeout</tt> structure as well).</dd>
2010     </dl>
2011    
2012     <p>Each of the three timeout types has its own timeout function:
2013     <tt>timeout_collide()</tt>, <tt>timeout_release()</tt>, and
2014     <tt>timeout_send_433()</tt>. The timeout functions check for any change
2015     in status (such as identification for the nickname) before performing
2016     their respective functions.</p>
2017    
2018     <p class="backlink"><a href="#top">Back to top</a></p>
2019    
2020    
2021     <h4 class="subsubsection-title" id="s3-2">7-3-2. Nickname access lists</h4>
2022    
2023     <p>Nickname access lists are managed by the <tt>nickserv/access</tt>
2024     module, defined in <tt>access.c</tt>. The module is quite simple,
2025     consisting of a database table, two callback functions, and a NickServ
2026     command (<tt>ACCESS</tt>). For simplicity, the module (along with other
2027     NickServ submodules) assumes the presence of the <tt>nickserv/main</tt>
2028     module rather than explicitly importing every required NickServ symbol,
2029     although the module's initialization does look up the
2030     <tt>nickserv/main</tt> module handle for use in adding the requisite
2031     callbacks and the <tt>ACCESS</tt> command.</p>
2032    
2033     <p>One unusual feature is the use of a static buffer for reading and
2034     writing database records. Since the access list itself is stored in the
2035     corresponding nickname group's <tt>NickGroupInfo</tt> structure as an
2036     array, the entries must be extracted and made available to the database
2037     subsystem in an independent (normalized) format. This is done by using a
2038     <tt>{<i>nickgroup-ID</i>,<i>access-mask</i>}</tt> record format, and
2039     providing a single record buffer. When loading data from persistent
2040     storage, the table's <tt>newrec()</tt> function returns a pointer to this
2041     buffer, taking advantage of the fact that only one record is loaded at a
2042     time (see <a href="6.html#s2-1">section 6-2-1</a>); the <tt>insert()</tt>
2043     routine then looks up the nickname group stored in the buffer and appends
2044     the given access mask to that nickname group's access list, while the
2045     <tt>freerec()</tt> routine frees the access mask string. When saving data,
2046     the <tt>first()</tt> and <tt>next()</tt> routines call
2047     <tt>first_nickgroupinfo()</tt> and <tt>next_nickgroupinfo()</tt> in turn,
2048     looping through each access mask of each nickname group.</p>
2049    
2050     <p>Ideally, the access lists would be stored in memory in the same fashion,
2051     as a distinct table using the nickname group ID as a key. However, since
2052     the current database implementation does not provide an efficient way to
2053     look up records matching arbitrary criteria (like a <tt>SELECT</tt>
2054     statement in SQL), and since problems would ensue when trying to save the
2055     data using the (deprecated, but still available) <tt>database/version4</tt>
2056     module, the in-memory data structures were left as is. See the comments in
2057     the <tt>autojoin.c</tt> source file for a more complete description.</p>
2058    
2059     <p>Other than this, there is little of note in the module; the
2060     <tt>do_access()</tt> command handler simply adds or removes the requested
2061     mask to or from the access list, and the callback functions take care of
2062     setting an initial access mask on registration and determining whether the
2063     user should be treated as recognized by <tt>validate_user()</tt>.</p>
2064    
2065     <p class="backlink"><a href="#top">Back to top</a></p>
2066    
2067    
2068     <h4 class="subsubsection-title" id="s3-3">7-3-3. Nickname auto-join lists</h4>
2069    
2070     <p>Nickname auto-join lists are managed by the <tt>nickserv/autojoin</tt>
2071     module, defined in <tt>autojoin.c</tt>. Aside from the details of its
2072     operation, this module is nearly identical to the <tt>nickserv/access</tt>
2073     module, including the hack used for database loading and saving; see the
2074     discussion of that module above (<a href="#s3-2">section 7-3-2</a>) for
2075     details.</p>
2076    
2077     <p class="backlink"><a href="#top">Back to top</a></p>
2078    
2079    
2080     <h4 class="subsubsection-title" id="s3-4">7-3-4. Linking and nickname groups</h4>
2081    
2082     <p>The distinction between "nicknames" and "nickname groups" has been made
2083     several times above. Ordinarily, this is only of importance as far as
2084     which structure is accessed (<tt>NickInfo</tt> or <tt>NickGroupInfo</tt>);
2085     however, the <tt>nickserv/link</tt> module, defined in <tt>link.c</tt>,
2086     allows nicknames to be linked together by assigning the same nickname group
2087     to both nicknames. This results in all information in the
2088     <tt>NickGroupInfo</tt> structure being shared among all linked nicknames,
2089     with only the data in the <tt>NickInfo</tt> structure kept separately for
2090     each nickname.</p>
2091    
2092     <p>The <tt>nickserv/link</tt> includes three commands: <tt>LINK</tt>,
2093     <tt>UNLINK</tt>, and <tt>LISTLINKS</tt>, as well as one additional
2094     <tt>SET</tt> option, <tt>SET MAINNICK</tt> (linked in through NickServ's
2095     "<tt>SET</tt>" callback). Of these, <tt>LISTLINKS</tt> and <tt>SET
2096     MAINNICK</tt> are straightforward: <tt>do_listlinks()</tt> simply echoes
2097     the contents of the <tt>nicks[]</tt> array for the calling client's
2098     nickname group (or the specified nickname's group for Services
2099     operators), and <tt>do_set_mainnick()</tt> modifies the nickname
2100     group's <tt>mainnick</tt> field based on the given nickname.</p>
2101    
2102     <p>When the <tt>LINK</tt> command is given to link a new nickname to the
2103     caller's nickname group, <tt>do_link()</tt> first ensures that the new
2104     nickname is not already in use and that creating the link would not cause
2105     the caller's total number of nicknames to exceed the <tt>NSRegEmailMax</tt>
2106     limit, if set. (Note that <tt>LINK</tt> does <i>not</i> abort if the mail
2107     address is not authenticated, simply checking the absolute value of the
2108     return from <tt>count_nicks_with_email()</tt> against the limit; creating
2109     the link does not in itself grant any additional privileges to the user,
2110     and can at most be used to "hide" from other users while maintaining
2111     current privileges.) If these checks pass, a new <tt>NickInfo</tt>
2112     structure is created, passing <tt>NULL</tt> as the
2113     <tt><i>nickgroup_ret</i></tt> parameter to <tt>makenick()</tt> to indicate
2114     that a new nickname group is not required; updates the <tt>NickInfo</tt>
2115     structure with the calling user's data; stores the nickname group ID in the
2116     new nickname's <tt>nickgroup</tt> field; and appends the new nickname to
2117     the nickname group's <tt>nicks[]</tt> array.</p>
2118    
2119     <p><tt>UNLINK</tt> acts similarly to the Services administrator command
2120     <tt>DROPNICK</tt> for a single nickname in a group. However, since
2121     <tt>UNLINK</tt> is not limited to Services administrators, care must be
2122     taken that an unprivileged client is not allowed to delete nicknames from
2123     other nickname groups; this check is made by ensuring that (1) the target
2124     nickname has a valid associated <tt>NickGroupInfo</tt> structure and (2)
2125     the nickname group IDs of the two nickname groups are equal, and
2126     disallowing the command otherwise if the <tt>FORCE</tt> option is not
2127     given. (The check is made on the <tt>FORCE</tt> option, disallowed for
2128     unprivileged clients, rather than on the client's privilege level in order
2129     to prevent accidental deletion of others' nicknames by Services
2130     administrators.) If the command is allowed, the routine then deletes the
2131     nickname by calling <tt>delnick()</tt>; if the nickname group's main
2132     nickname is the one being unlinked, <tt>delnick()</tt> automatically
2133     adjusts the <tt>mainnick</tt> field to the next nickname in the
2134     <tt>nicks[]</tt> array (or the previous nickname, if the deleted nickname
2135     was the last one in the array).</p>
2136    
2137     <p class="backlink"><a href="#top">Back to top</a></p>
2138    
2139    
2140     <h4 class="subsubsection-title" id="s3-5">7-3-5. E-mail address authentication</h4>
2141    
2142     <p>While it has long been possible to associate an E-mail address with a
2143     registered nickname, there was traditionally no way to ensure that the
2144     address given was in fact a valid one belonging to the nickname owner.
2145     Since Services 5.0, such functionality has been provided by the
2146     <tt>nickserv/mail-auth</tt> module, defined in <tt>mail-auth.c</tt>. As
2147     described in the user's manual, E-mail address authentication works by
2148     assigning a random "authentication code" to the nickname, then sending an
2149     E-mail message to the registered address containing that code; the owner is
2150     not allowed to identify to the nickname until the code has been entered,
2151     ensuring that the address is one which the owner has (or at least had, at
2152     the time the message was sent) access to.</p>
2153    
2154     <p>Internally, this processing is managed with the <tt>authcode</tt>,
2155     <tt>authset</tt>, and <tt>authreason</tt> fields of the
2156     <tt>NickGroupInfo</tt> structure. When an event occurs requiring E-mail
2157     address authentication, the module generates a random 9-digit numeric code
2158     (100000000 through 999999999 inclusive&mdash;codes with leading zeroes are
2159     not used in order to avoid confusion), stores the code in the nickname
2160     group's <tt>authcode</tt> field, and calls the mail subsystem's
2161     <tt>sendmail()</tt> routine to send a message to the nickname group's
2162     registered E-mail address (see <a href="8.html#s3">section 8-3</a> for
2163     information about how mail is sent). Additionally, the current timestamp
2164     is stored in the <tt>authset</tt> field, and the reason for setting the
2165     code (one of the <tt>NICKAUTH_*</tt> constants) is stored in the
2166     <tt>authreason</tt> field. (In early versions of the module, the reason
2167     was stored in two bits of the authentication code; this method was later
2168     rejected, however, as being too kludgey and inflexible as well as leaking
2169     information.) The presence of a nonzero value in the <tt>authcode</tt>
2170     field indicates that the nickname group is awaiting authentication, and a
2171     nickname identification callback function ensures that clients are not
2172     allowed to identify for such nicknames (nor does <tt>validate_user()</tt>
2173     allow automatic identification if an authentication code is present), thus
2174     effectively preventing their use. By issuing an AUTH command with the
2175     correct code, a nickname owner can clear the nickname group's
2176     <tt>authcode</tt> field, allowing identification to the nickname(s) once
2177     more.</p>
2178    
2179     <p>The module begins with several utility functions:</p>
2180    
2181     <dl>
2182     <dt><tt>void <b>make_auth</b>(NickGroupInfo *<i>ngi</i>, int16 <i>reason</i>)</tt></dt>
2183     <dd>Generates a random authentication code, and sets the nickname
2184     group's <tt>authcode</tt>, <tt>authset</tt>, and <tt>authreason</tt>
2185     fields appropriately. The <tt><i>reason</i></tt> parameter is
2186     copied directly into the <tt>authreason</tt> field, without checks
2187     on its value.</dd>
2188    
2189     <dt><tt>void <b>clear_auth</b>(NickGroupInfo *<i>ngi</i>)</tt></dt>
2190     <dd>Clears the given nickname group's authentication code (if any), as
2191     well as all related nickname group data fields (including the
2192     previous E-mail address).</dd>
2193    
2194     <dt><tt>int <b>send_auth</b>(User *<i>u</i>, NickGroupInfo *<i>ngi</i>,
2195     const char *<i>nick</i>, int <i>what</i>)</tt></dt>
2196     <dd>Sends an E-mail to the given nickname group's owner containing the
2197     nickname's current authentication code. <tt><i>u</i></tt> is the
2198     <tt>User</tt> structure for the client whose command caused the
2199     message to be sent; <tt><i>nick</i></tt> is the specific nickname
2200     for which the command was issued; and <tt><i>what</i></tt> is
2201     one of the <tt>IS_*</tt> constants defined for the routine
2202     (internally a language string index for the mail body or -1 for the
2203     special case of <tt>SETAUTH</tt>). The routine itself is defined
2204     as <tt>send_auth_</tt>, taking a <tt><i>line</i></tt> parameter
2205     indicating where in the source the routine was called from; this is
2206     filled in automatically by the <tt>send_auth()</tt> macro. In
2207     order to inform the calling client of the success or failure of
2208     sending the message, <tt>send_auth()</tt> creates a
2209     <tt>sendauth_data</tt> structure for each message sent, used in the
2210     two routines listed below.</dd>
2211    
2212     <dt><tt>void <b>send_auth_callback</b>(int <i>status</i>, void *<i>data</i>)</tt></dt>
2213     <dd>The callback function used for <tt>sendmail()</tt> when called from
2214     <tt>send_auth()</tt>. This routine uses the <tt>sendauth_data</tt>
2215     structure for the sent message (passed as the <tt><i>data</i></tt>
2216     parameter) to send a reply to the client that issued the original
2217     command, and also to clear the nickname group's
2218     <tt>last_sendauth</tt> field if the command used was
2219     <tt>SENDAUTH</tt> and the message could not be sent. The structure
2220     is then removed from the global list and freed.</dd>
2221    
2222     <dt><tt>int <b>sendauth_userdel</b>(User *<i>user</i>,
2223     const char *<i>reason</i>, int <i>is_kill</i>)</tt></dt>
2224     <dd>Used as a callback function for the core's "<tt>user delete</tt>"
2225     callback. Iterates through the <tt>sendauth_data</tt> list,
2226     clearing the <tt>User</tt> pointer of any entries for the user
2227     being removed; this causes <tt>send_auth_callback()</tt> to skip
2228     sending a reply when the mail sending completes.</dd>
2229     </dl>
2230    
2231     <p>These routines are followed by the command handlers for the commands
2232     supported by the module: <tt>AUTH</tt>, <tt>SENDAUTH</tt>, <tt>REAUTH</tt>,
2233     <tt>RESTOREMAIL</tt>, and the Services administrator commands
2234     <tt>SETAUTH</tt>, <tt>GETAUTH</tt>, and <tt>CLEARAUTH</tt>. Of these, the
2235     only fairly complex one is the <tt>AUTH</tt> handler, <tt>do_auth()</tt>,
2236     as it must watch for attempts to guess the authentication code. (Invalid
2237     <tt>AUTH</tt> commands are treated the same as bad passwords to
2238     <tt>IDENTIFY</tt> or other commands, by calling <tt>bad_password()</tt> and
2239     incrementing the nickname group's <tt>bad_auths</tt> field, which itself
2240     can generate a warning via <tt>WALLOPS</tt>.)</p>
2241    
2242     <p>Finally, the module includes four callback functions. Two of these,
2243     <tt>do_registered()</tt> and <tt>do_set_email()</tt>, hook into the
2244     NickServ callbacks for the <tt>REGISTER</tt> and <tt>SET EMAIL</tt>
2245     commands, respectively, dropping the client's identified status and
2246     generating and sending an authentication code. (Changes to the E-mail
2247     address made by Services administrators are not subject to authentication,
2248     however.) These are followed by the <tt>IDENTIFY</tt> command callback
2249     function <tt>do_identify()</tt>, which disallows <tt>IDENTIFY</tt> for
2250     nicknames with pending authentication codes, and the expiration check
2251     callback function <tt>do_check_expire()</tt>, which drops a
2252     newly-registered nickname after <tt>NSNoAuthExpire</tt> seconds (if set) if
2253     not authenticated, and also clears any pending <tt>REAUTH</tt> after the
2254     same amount of time (the user can subsequently use a second <tt>REAUTH</tt>
2255     if necessary).</p>
2256    
2257     <p>Since the ability to send E-mail is essential for this module to work,
2258     the <tt>init_module()</tt> function checks for the presence of the
2259     <tt>mail/main</tt> module, refusing to load if it is not available.</p>
2260    
2261     <p class="backlink"><a href="#top">Back to top</a></p>
2262    
2263     <!------------------------------------------------------------------------>
2264     <hr/>
2265    
2266     <h3 class="subsection-title" id="s4">7-4. ChanServ</h3>
2267    
2268     <p>ChanServ is the most complex of the standard Services pseudoclients,
2269     owing to the variety of operations that can be performed on channels.
2270     There is no easy way to split those operations up into separate modules
2271     (except by individual command, an avenue which has not been pursued), and
2272     as a result, the core ChanServ module is itself the largest module in
2273     Services.</p>
2274    
2275     <p>As with NickServ, the core ChanServ module, <tt>chanserv/main</tt>, is
2276     split up over several source files. These are discussed in
2277     <a href="#s4-1">section 7-4-1</a> and its subsections, with the exception
2278     of the <tt>access.c</tt> source file, which is discussed in
2279     <a href="#s4-2">section 7-4-2</a> along with the access list manipulation
2280     submodules, <tt>chanserv/access-levels</tt> and
2281     <tt>chanserv/access-xop</tt>.</p>
2282    
2283     <p class="backlink"><a href="#top">Back to top</a></p>
2284    
2285    
2286     <h4 class="subsubsection-title" id="s4-1">7-4-1. ChanServ core functionality</h4>
2287    
2288     <p>The core ChanServ module, <tt>chanserv/main</tt>, is built from several
2289     source files, along much the same lines as the core NickServ module:
2290     <tt>main.c</tt>, containing the central module code and most command
2291     handlers; <tt>access.c</tt>, for handling channel access lists;
2292     <tt>check.c</tt>, for checking the status of a channel against registered
2293     data and making appropriate changes; <tt>set.c</tt>, implementing the
2294     <tt>SET</tt> command; and <tt>util.c</tt>, defining various ChanServ
2295     utility functions.</p>
2296    
2297     <p class="backlink"><a href="#top">Back to top</a></p>
2298    
2299    
2300     <h5 class="subsubsubsection-title" id="s4-1-1">7-4-1-1. Channel data structures</h5>
2301    
2302     <p>As with NickServ, ChanServ splits its declarations into two header
2303     files: <tt>chanserv.h</tt>, containing structures and routine declarations
2304     intended to be exported to other modules, and <tt>cs-local.h</tt>, for
2305     internal use by ChanServ only. (There is also a separate header file,
2306     <tt>access.h</tt>, specifically for channel access list definitions; this
2307     is discussed in <a href="#s4-2-1">section 7-4-2-1</a>.)</p>
2308    
2309     <p>The channel data structure, <tt>ChannelInfo</tt>, is naturally exported.
2310     As ChanServ does not have the concept of "links" or "channel groups" that
2311     NickServ uses with nicknames, all data for a channel is stored in this
2312     single structure. <tt>ChannelInfo</tt> does, however, include three
2313     substructures, defined before it in <tt>chanserv.h</tt>:</p>
2314    
2315     <dl>
2316     <dt><tt>ChanAccess</tt></dt>
2317     <dd>Contains the data for an entry on a channel's access list. Access
2318     list entries are stored by nickname group ID, rather than by
2319     nickname, both to optimize checking an access list for a particular
2320     client and to eliminate the possibility of two or more entries
2321     matching a single client. (This is why only registered nicknames
2322     are allowed on channel access lists, and why channel access list
2323     entries are always displayed using the nickname group's main
2324     nickname, regardless of the nickname actually added to the list.)
2325     Rather than resizing the array every time a change is made to the
2326     list, deleted entries are left in memory with a nickname group ID
2327     of zero, and subsequent adds reuse these entries before attempting
2328     to expand the array. The <tt>channel</tt> field is used to link
2329     the record with its associated channel when loading and saving
2330     data. There are also a number of access-level related constants
2331     declared below this structure, such as the maximum and minimum
2332     access levels and the equivalent access levels for the <tt>XOP</tt>
2333     commands.</dd>
2334    
2335     <dt><tt>AutoKick</tt></dt>
2336     <dd>Contains the data for an entry on a channel's autokick list. As
2337     with access list entries, deleted entries are left in the list
2338     rather than resizing the array (a <tt>NULL</tt> value for the mask
2339     string indicates an unused entry), and the <tt>channel</tt> field
2340     is used when loading and saving data to link the record with its
2341     associated channel.</dd>
2342    
2343     <dt><tt>ModeLock</tt></dt>
2344     <dd>Contains a channel's mode lock data, including the set of modes
2345     locked on and off along with parameters for modes that require
2346     them; with the exception of the presence of two mode sets rather
2347     than one (modes can be locked on, locked off, or neither), the
2348     structure's contents are the same as the fields used in channel
2349     data structures (<tt>Channel</tt> records) to record the channel's
2350     current mode. The mode sets are normally maintained as bitmasks,
2351     but when used in the <tt>convert-db</tt> tool, they are defined as
2352     strings instead to allow lossless conversion to XML without needing
2353     to know the specific set of modes supported by the program that
2354     created the database. Unlike the <tt>ChanAccess</tt> and
2355     <tt>AutoKick</tt> structures, there is only one <tt>ModeLock</tt>
2356     structure per channel, and the data in the structure is saved along
2357     with the channel record itself, so there is no need for a separate
2358     channel field.</dd>
2359     </dl>
2360    
2361     <p><tt>chanserv.h</tt> also defines constants for each of the channel
2362     privilege levels (indices into the <tt>levels[]</tt> array of the
2363     <tt>ChannelInfo</tt> structure). As noted in the comment above the list
2364     of definitions, changing the values of any of the constants will cause
2365     malfunctions when using the <tt>database/version4</tt> module, since that
2366     module simply reads in the list of levels as a block. (This is why the
2367     index 18, formerly used for <tt>CA_AUTOOWNER</tt>, is unused&mdash;to avoid
2368     problems with databases in which that index is used.)</p>
2369    
2370     <p>The <tt>ChannelInfo</tt> structure itself contains the following
2371     fields:</p>
2372    
2373     <dl>
2374     <dt><tt>ChannelInfo *<b>next</b>, *<b>prev</b></tt></dt>
2375     <dd>Used to link records together in the internal hash table.</dd>
2376    
2377     <dt><tt>int <b>usecount</b></tt></dt>
2378     <dd>The record's usage count (number of gets minus number of puts).
2379     <i>(Implementation note: As noted in <a href="#s1">section 7-1</a>,
2380     this field currently serves no actual purpose.)</i></dd>
2381    
2382     <dt><tt>char <b>name</b>[CHANMAX]</tt></dt>
2383     <dd>The channel's name. Capitalization is as used when the channel was
2384     registered, and does not change due to later actions. The buffer
2385     size, <tt>CHANMAX</tt>, is defined in the global header file
2386     <tt>defs.h</tt>.</dd>
2387    
2388     <dt><tt>uint32 <b>founder</b></tt>
2389     <br/><tt>uint32 <b>successor</b></tt></dt>
2390     <dd>The nickname group ID of the channel's founder and successor,
2391     respectively. If the channel does not have a successor set, the
2392     <tt>successor</tt> field will be zero.</dd>
2393    
2394     <dt><tt>Password <b>founderpass</b></tt></dt>
2395     <dd>The founder password for the channel.</dd>
2396    
2397     <dt><tt>char *<b>desc</b></tt></dt>
2398     <dd>The channel's description, as specified at registration time or
2399     with a later <tt>SET DESC</tt> command.</dd>
2400    
2401     <dt><tt>char *<b>url</b></tt></dt>
2402     <dd>The URL associated with the channel, as set with the <tt>SET
2403     URL</tt> command. <tt>NULL</tt> if no URL has been set.</dd>
2404    
2405     <dt><tt>char *<b>email</b></tt></dt>
2406     <dd>The E-mail address associated with the channel, as set with the
2407     <tt>SET EMAIL</tt> command. <tt>NULL</tt> if no E-mail address
2408     has been set.</dd>
2409    
2410     <dt><tt>char *<b>entry_message</b></tt></dt>
2411     <dd>The channel's entry message (the message sent as a <tt>NOTICE</tt>
2412     to clients entering the channel), as set with the <tt>SET
2413     ENTRYMSG</tt> command. <tt>NULL</tt> if no entry message has been
2414     set.</dd>
2415    
2416     <dt><tt>time_t <b>time_registered</b></tt></dt>
2417     <dd>The timestamp at which the channel was registered.</dd>
2418    
2419     <dt><tt>time_t <b>last_used</b></tt></dt>
2420     <dd>The timestamp at which the channel was last used (see
2421     <a href="../3.html#2-3">section 3-2-3 of the user's manual</a> for
2422     details of how the last-used time is set).</dd>
2423    
2424     <dt><tt>char *<b>last_topic</b></tt>
2425     <br/><tt>char <b>last_topic_setter</b>[NICKMAX]</tt>
2426     <br/><tt>time_t <b>last_topic_time</b></tt></dt>
2427     <dd>The topic most recently set on the channel, along with the nickname
2428     of the client that set the topic and the timestamp at which it was
2429     set. If no topic has been set on the channel, <tt>last_topic</tt>
2430     will be <tt>NULL</tt>, and the other two fields will be
2431     undefined.</dd>
2432    
2433     <dt><tt>int32 <b>flags</b></tt></dt>
2434     <dd>A bitmask containing zero or more of the following channel flags:
2435     <ul>
2436     <li><b><tt>CF_KEEPTOPIC</tt>:</b> ChanServ should restore the
2437     channel's previous topic each time the channel is created
2438     on the IRC network (<tt>SET KEEPTOPIC</tt>).</li>
2439     <li><b><tt>CF_SECUREOPS</tt>:</b> Clients without a positive access
2440     level on the channel should be prevented from getting ops
2441     (<tt>SET SECUREOPS</tt>).</li>
2442     <li><b><tt>CF_PRIVATE</tt>:</b> The channel is hidden from the
2443     <tt>LIST</tt> command output, except when used by Services
2444     administrators (<tt>SET PRIVATE</tt>).</li>
2445     <li><b><tt>CF_TOPICLOCK</tt>:</b> ChanServ should prevent the topic
2446     from being changed except by the <tt>SET TOPIC</tt> command
2447     (<tt>SET TOPICLOCK</tt>).</li>
2448     <li><b><tt>CF_RESTRICTED</tt>:</b> ChanServ should automatically
2449     kick and ban any clients without a positive access level
2450     that attempt to join the channel (<tt>SET
2451     RESTRICTED</tt>).</li>
2452     <li><b><tt>CF_LEAVEOPS</tt>:</b> ChanServ should not remove
2453     server-generated ops for the first client to join a
2454     channel, even if that client would not normally be
2455     auto-opped (<tt>SET LEAVEOPS</tt>).</li>
2456     <li><b><tt>CF_SECURE</tt>:</b> When checking a client's channel
2457     access level, require the client to have identified to
2458     NickServ regardless of the setting of the nickname's
2459     <tt>SECURE</tt> option (<tt>SET SECURE</tt>).</li>
2460     <li><b><tt>CF_VERBOTEN</tt>:</b> The channel is forbidden
2461     (<tt>FORBID</tt>).</li>
2462     <li><b><tt>CF_NOEXPIRE</tt>:</b> The channel does not expire
2463     (<tt>SET NOEXPIRE</tt>).</li>
2464     <li><b><tt>CF_OPNOTICE</tt>:</b> ChanServ should send a notice to
2465     the channel whenever any of the <tt>OP</tt>, <tt>VOICE</tt>,
2466     or related commands are used (<tt>SET OPNOTICE</tt>).</li>
2467     <li><b><tt>CF_ENFORCE</tt>:</b> ChanServ should prevent clients
2468     from removing automatically-set channel user modes such as
2469     auto-ops (<tt>SET ENFORCE</tt>).</li>
2470     <li><b><tt>CF_HIDE_EMAIL</tt>:</b> The channel's E-mail address is
2471     hidden from the <tt>INFO</tt> command output, except when
2472     used by Services administrators (<tt>SET HIDE
2473     EMAIL</tt>).</li>
2474     <li><b><tt>CF_HIDE_TOPIC</tt>:</b> The channel's current or last
2475     topic is hidden from the <tt>INFO</tt> command output,
2476     except when used by Services administrators (<tt>SET HIDE
2477     TOPIC</tt>).</li>
2478     <li><b><tt>CF_HIDE_MLOCK</tt>:</b> The channel's mode lock is
2479     hidden from the <tt>INFO</tt> command output, except when
2480     used by Services administrators (<tt>SET HIDE
2481     MLOCK</tt>).</li>
2482     <li><b><tt>CF_SUSPENDED</tt>:</b> The channel is suspended
2483     (<tt>SUSPEND</tt>).</li>
2484     <li><b><tt>CF_MEMO_RESTRICTED</tt>:</b> Only users with the
2485     <tt>MEMO</tt> privilege are permitted to send memos to the
2486     channel (<tt>SET MEMO-RESTRICTED</tt>).</li>
2487     </ul>
2488     The flag values 0x00000100 and 0x00000400 are unused to avoid
2489     difficulties with databases from earlier versions of Services
2490     which used these values.</dd>
2491    
2492     <dt><tt>char <b>suspend_who</b>[NICKMAX]</tt>
2493     <br/><tt>char *<b>suspend_reason</b></tt>
2494     <br/><tt>time_t <b>suspend_time</b></tt>
2495     <br/><tt>time_t <b>suspend_expires</b></tt></dt>
2496     <dd>Suspension data for the channel, if the <tt>CF_SUSPENDED</tt> flag
2497     is set. Used in the same fashion as the same-named fields in the
2498     <tt>NickGroupInfo</tt> structure (see <a href="#s3-1-1">section
2499     7-3-1-1</a>).</dd>
2500    
2501     <dt><tt>int16 <b>levels</b>[CA_SIZE]</tt></dt>
2502     <dd>The channel access levels corresponding to each of the channel
2503     privileges (<tt>CA_INVITE</tt>, <tt>CA_AKICK</tt>, and so on).
2504     A value of <tt>ACCLEV_DEFAULT</tt> indicates that the corresponding
2505     privilege should use the default access level defined in
2506     <tt>access.c</tt>; a value of <tt>ACCLEV_INVALID</tt> indicates
2507     that the corresponding privilege is disabled entirely, except with
2508     respect to the channel founder.</dd>
2509    
2510     <dt><tt>ChanAccess *<b>access</b></tt>
2511     <br/><tt>int16 <b>access_count</b></tt></dt>
2512     <dd>A variable-length array containing the channel's access list.</dd>
2513    
2514     <dt><tt>AutoKick *<b>akick</b></tt>
2515     <br/><tt>int16 <b>akick_count</b></tt></dt>
2516     <dd>A variable-length array containing the channel's autokick list.</dd>
2517    
2518     <dt><tt>ModeLock <b>mlock</b></tt></dt>
2519     <dd>The channel's mode lock data.</dd>
2520    
2521     <dt><tt>Channel *<b>c</b></tt></dt>
2522     <dd><i>Not saved to persistent storage.</i> Points to the
2523     <tt>Channel</tt> structure for the channel if it is currently in
2524     use.</dd>
2525    
2526     <dt><tt>int <b>bad_passwords</b></tt></dt>
2527     <dd><i>Not saved to persistent storage.</i> The number of times an
2528     incorrect password has been given for a channel command (such as
2529     <tt>IDENTIFY</tt>) since the last correct password. Used to warn
2530     about attempts to crack the password.</dd>
2531     </dl>
2532    
2533     <p>The <tt>cs-local.h</tt> header file includes three definitions used
2534     internally by ChanServ:</p>
2535    
2536     <dl>
2537     <dt><tt>MAX_MLOCK_PARAMS</tt> (constant)</dt>
2538     <dd>Sets the maximum number of command parameters that the <tt>SET
2539     MLOCK</tt> command will process. This constant is used to avoid
2540     the overhead of dynamically allocating an argument array for every
2541     invocation of the command; any parameters passed beyond this limit
2542     will be silently ignored. The default value, 256, is more
2543     parameters than are can be passed in an RFC-standard 512-byte line
2544     (even if every parameter is one character, subtracting out the
2545     "<tt>SET MLOCK</tt>" leaves space for only 251 parameters, not
2546     considering the trailing CR/LF and other IRC protocol overhead).</dd>
2547    
2548     <dt><tt>ChanOpt</tt> (structure)</dt>
2549     <dd>Used to define channel option data, for use by the <tt>SET</tt> and
2550     <tt>INFO</tt> commands. The structure has the following fields:
2551     <ul>
2552     <li><b><tt>name</tt>:</b> The name of the option, as a string.</li>
2553     <li><b><tt>flag</tt>:</b> The corresponding <tt>ChannelInfo.flags</tt>
2554     flag value.</li>
2555     <li><b><tt>namestr</tt>:</b> The option's descriptive name (for use
2556     in <tt>INFO</tt> output), as a language string index. If
2557     -1, the option will not be included in <tt>INFO</tt>
2558     output.</li>
2559     <li><b><tt>onstr</tt>, <tt>offstr</tt></b>: Response messages for
2560     turning the option on and off via <tt>SET</tt>, as language
2561     string indices.</li>
2562     <li><b><tt>syntaxstr</tt></b>: The syntax message for setting the
2563     option, as a language string index.</li>
2564     </ul></dd>
2565    
2566     <dt><tt>RET_*</tt> (constants)</dt>
2567     <dd>Return values from access list modification routines. See
2568     <a href="#s4-2-1">section 7-4-2-1</a> for details.</dd>
2569     </dl>
2570    
2571     <p id="s4-1-1-rename">One other point of note in <tt>cs-local.h</tt> is the
2572     renaming of several functions in <tt>set.c</tt> and <tt>util.c</tt> using
2573     <tt>#define</tt> directives, such as renaming <tt>init_set()</tt> to
2574     <tt>init_set_cs()</tt>. This is to avoid conflicts with NickServ, which
2575     includes functions of the same name in its own <tt>set.c</tt> and
2576     <tt>util.c</tt>. While the functions involved are not used outside of
2577     ChanServ, they must be declared external for the multi-file link to
2578     succeed; as a result, if the functions are not renamed, linking the final
2579     program when using static modules will result in a symbol name clash when
2580     the symbols from both modules are processed. This problem does not occur
2581     when using dynamic modules, since the presence of conflicting symbols in
2582     dynamic modules is not itself an error, and no attempt is made to reference
2583     either set of symbols from any other module (the references within the
2584     respective modules are resolved at module link time).</p>
2585    
2586     <p class="backlink"><a href="#top">Back to top</a></p>
2587    
2588    
2589     <h5 class="subsubsubsection-title" id="s4-1-2">7-4-1-2. Overall module structure</h5>
2590    
2591     <p>The main source file for ChanServ, <tt>main.c</tt>, follows the same
2592     pattern as its NickServ counterpart; see <a href="#s3-1-2">section
2593     7-3-1-2</a> for a more extensive description.</p>
2594    
2595     <p>One of the first things defined in <tt>main.c</tt> is the
2596     <tt>chanopts[]</tt> table, an array of <tt>ChanOpt</tt> structures (see
2597     above) describing on/off options available on channels from a user's
2598     perspective. This table is used primarily for the <tt>SET</tt> command
2599     (thus only flags which have a corresponding <tt>SET</tt> command are
2600     listed), and secondarily for outputting the channel's option set in
2601     response to the <tt>INFO</tt> command. Note that the three <tt>HIDE</tt>
2602     options are not listed here, as they are handled specially for the
2603     <tt>SET</tt> command and not listed in the <tt>INFO</tt> output.</p>
2604    
2605     <p>In addition to the standard command list in the <tt>cmds[]</tt> array,
2606     two separate arrays are defined, for the <tt>HALFOP</tt>/<tt>DEHALFOP</tt>
2607     and <tt>PROTECT</tt>/<tt>DEPROTECT</tt> command pairs. These commands can
2608     only be used if the IRC server protocol supports the corresponding feature,
2609     so the module initialization routine checks the protocol's feature flags
2610     and conditionally registers these two pairs of commands.</p>
2611    
2612     <p>ChanServ includes a significant number of callback functions for various
2613     IRC events: in addition to watching for newly-created channels and users
2614     joining channels, it must also monitor changes of status such as channel
2615     modes and channel topics to ensure that they remain consistent with the
2616     registered settings and to record changes, as well as take notice of
2617     nickname-related events that can affect channels. Of these, the
2618     <tt>do_nickgroup_delete()</tt> callback function, called when a nickname
2619     group is deleted, is easily the most complex. Since channel founders must
2620     be registered nicknames, the disappearance of a nickname group means that
2621     any channels with that group as founder will no longer have a valid founder
2622     group ID. If the channel has a successor set, the successor may be able to
2623     assume foundership of the channel&mdash;but the code must be careful that
2624     this does not cause the successor to exceed his registered channel limit,
2625     or users could circumvent the limit by registering multiple nicknames,
2626     setting one as founder and another as successor, and deliberately dropping
2627     the founder nickname. In addition, if the channel was suspended, it is
2628     changed to a forbidden channel to prevent users from getting around a
2629     suspension by dropping and re-registering their nickname. Because of these
2630     various potentialities, the callback function always logs any actions it
2631     takes in response to the deletion of a nickname group.</p>
2632    
2633     <p>Of the command routines, the basic commands (<tt>HELP</tt>,
2634     <tt>REGISTER</tt>, <tt>IDENTIFY</tt>, <tt>DROP</tt>, <tt>DROPCHAN</tt>,
2635     <tt>INFO</tt>, <tt>LIST</tt>) are very similar to their NickServ
2636     counterparts, and are not discussed in detail here. The two
2637     ChanServ-specific commands whose handlers are fairly complex are
2638     <tt>AKICK</tt> and the <tt>OP</tt>/<tt>VOICE</tt> command set.</p>
2639    
2640     <p>The <tt>AKICK</tt> command handler <tt>do_akick()</tt>, despite its
2641     length (including a separate helper routine used with <tt>LIST</tt> and
2642     <tt>VIEW</tt>), is not dissimilar to the OperServ autokill and S-line
2643     commands, or the NickServ <tt>ACCESS</tt> and <tt>AJOIN</tt> handlers. The
2644     only significant difference is the presence of the <tt>ENFORCE</tt>
2645     subcommand; this is implemented by calling <tt>check_kick()</tt>, the
2646     routine used to check whether newly-joined clients are allowed to join a
2647     channel (see <a href="#s4-1-3">section 7-4-1-3</a>) for each client on the
2648     channel, causing clients which match an entry on the autokill list to be
2649     kickbanned.</p>
2650    
2651     <p>The <tt>OP</tt> and <tt>VOICE</tt> family of commands all perform a
2652     common function&mdash;adding or removing a channel user mode&mdash;and for
2653     this reason, all eight commands are handled by a single routine,
2654     <tt>do_opvoice()</tt>, with handlers for each command that call the common
2655     routine with the appropriate command name to indicate the mode of
2656     operation. The data used by the common routine is stored in
2657     <tt>opvoice_data[]</tt>, an array of structures with the following
2658     fields:</p>
2659    
2660     <ul>
2661     <li><b><tt>cmd</tt>:</b> The command name.</li>
2662     <li><b><tt>add</tt>:</b> Nonzero if the command adds a mode, zero if it
2663     removes a mode.</li>
2664     <li><b><tt>mode</tt>:</b> The mode character added or removed.</li>
2665     <li><b><tt>target_acc</tt>:</b> A channel privilege index (<tt>CA_*</tt>
2666     constant); if the target client is in this privilege class, the
2667     command will be refused.</li>
2668     <li><b><tt>success_msg</tt>:</b> The language string index for the message
2669     to be sent when the command succeeds.</li>
2670     <li><b><tt>already_msg</tt>:</b> The language string index for the message
2671     to be sent when the client already has the mode added (or lacks the
2672     mode removed) by the command.</li>
2673     <li><b><tt>failure_msg</tt>:</b> The language string index for the message
2674     to be sent when the command is rejected.</li>
2675     </ul>
2676    
2677     <p>When called, <tt>do_opvoice()</tt> first extracts the data for the
2678     command from the <tt>opvoice_data[]</tt> table, and sets an additional
2679     variable, <tt>target_nextacc</tt>, used for mode-removal commands to set an
2680     upper bound on the target client access level check; this is used to, for
2681     example, allow <tt>DEVOICE</tt> on an auto-op client (since the client can
2682     just give themselves voice status again if necessary). The routine then
2683     loops through all target nicknames given with the command; a
2684     <tt>do/while</tt> loop is used so that if no nicknames are given at all,
2685     the code will still be run once (in this case the client that gave the
2686     command is used as the target). For each target client, the standard
2687     permission and channel status checks are performed, and then the routine
2688     determines whether to allow the command:</p>
2689     <ol>
2690     <li>If the target client is the client giving the command, the command is
2691     allowed.</li>
2692     <li>If the command removes a mode (<tt>DEOP</tt>, <tt>DEVOICE</tt>, etc.)
2693     and the channel does not have the <tt>ENFORCE</tt> option set, the
2694     command is allowed.</li>
2695     <li>If a channel privilege check (<tt>target_acc</tt>) is not specified for
2696     the command, the command is allowed.</li>
2697     <li>If the the target client is not in the privilege class specified for
2698     the command's privilege check, the command is allowed.</li>
2699     <li>If an upper limit for the privilege check (<tt>target_nextacc</tt>) is
2700     set for the command and the target client is in that privilege
2701     class, the command is allowed.</li>
2702     <li>Otherwise, the command is refused.</li>
2703     </ol>
2704    
2705     <p>Once the command has been allowed, the routine determines which mode
2706     flags need to be set or cleared for the target client. (For extensibility,
2707     the code allows for more than one flag to be set or cleared for a single
2708     command, though the data table only allows one mode character.) If there
2709     are no modes to be set or cleared, a notice to that effect is sent to the
2710     caller; otherwise, the necessary mode changes are performed, a notice of
2711     the mode change is sent to the channel if the <tt>OPNOTICE</tt> option is
2712     enabled, and a success notice is sent to the caller. In addition, if the
2713     command was an <tt>OP</tt> command, the channel's last-used time is updated
2714     as for auto-ops.</p>
2715    
2716     <p class="backlink"><a href="#top">Back to top</a></p>
2717    
2718    
2719     <h5 class="subsubsubsection-title" id="s4-1-3">7-4-1-3. Channel status checking and modification</h5>
2720    
2721     <p>ChanServ's routines for checking and adjusting channel status are
2722     located in the source file <tt>check.c</tt>. There are six routines
2723     exported from this file; two, <tt>init_check()</tt> and <tt>exit_check()</tt>,
2724     are initialization and cleanup routines called by the module initialization
2725     and cleanup code, respectively. The remaining routines are:</p>
2726    
2727     <dl>
2728     <dt><tt>void <b>check_modes</b>(Channel *<i>c</i>)</tt></dt>
2729     <dd>Checks the given channel's modes, making any changes necessary.
2730     For registered channels, the "registered" mode (if any) is always
2731     added, and other modes are set or cleared according to the mode
2732     lock; for unregistered channels, the "registered" mode is always
2733     cleared. This routine also checks for the "bouncy modes"
2734     phenomenon in tandem with the channel <tt>MODE</tt> message
2735     handle (see <a href="2.html#s6-3">section 2-6-3</a>).</dd>
2736    
2737     <dt><tt>void <b>check_chan_user_modes</b>(const char *<i>source</i>,
2738     struct c_userlist *<i>u</i>, Channel *<i>c</i>, int32 <i>oldmodes</i>)</tt></dt>
2739     <dd>Checks the channel user modes of the given client (<tt><i>u</i></tt>)
2740     on the given channel, making any changes necessary. The set of
2741     "necessary" changes depends not only on the client's current modes,
2742     but also on the source of the <tt>MODE</tt> message that caused the
2743     change (passing an empty string for the <tt><i>source</i></tt>
2744     parameter will cause such checks to be skipped).
2745     <tt><i>oldmodes</i></tt> is the client's previous set of modes, or
2746     -1 for a client joining a channel. The sequence of operations is
2747     fairly complicated:
2748     <ul>
2749     <li class="spaced">If the channel is not registered (or forbidden),
2750     no changes are made.</li>
2751     <li class="spaced">If <tt><i>source</i></tt> is Services' server
2752     name or the ChanServ or OperServ pseudoclient nickname,
2753     no changes are made (under the assumption that anything
2754     done by Services has been otherwise checked).</li>
2755     <li class="spaced">If <tt><i>source</i></tt> is the client whose
2756     modes are being checked, then no changes are made
2757     <i>unless</i> the user is either not opped or is about to
2758     be deopped, in which case the mode changes made by the
2759     client are reversed. However, this check is not performed
2760     for IRC operators (since some IRC servers allow operators
2761     to set arbitrary modes regardless of chanop status), and on
2762     servers supporting halfops, the mode change is not reversed
2763     if the user has halfops and is only changing the halfop or
2764     voice modes.</li>
2765     <li class="spaced">If the mode change is the opping by a server of
2766     the first client to join a channel and the channel does not
2767     have the <tt>LEAVEOPS</tt> option set, the client's channel
2768     access level is checked against the auto-op privilege
2769     level. If the client has auto-op privileges, then the
2770     channel's last-used time is updated as for ordinary auto-op
2771     processing (see below); otherwise, a "channel is
2772     registered" notice is sent to the client and the client is
2773     deopped (in that order, so that a human user will see the
2774     reason for the deop before the mode change itself).</li>
2775     <li class="spaced">The "<tt>check_chan_user_modes</tt>" callback is
2776     called, allowing protocol modules to handle modes not
2777     recognized by the standard processing.</li>
2778     <li class="spaced">The client's new modes, based on channel
2779     privilege level, are calculated by calling
2780     <tt>check_access_cumode()</tt> (see
2781     <a href="#s4-2-1">section 7-4-2-1</a>).</li>
2782     <li class="spaced">If the client just joined the channel, the mode
2783     change was done by a server, or the <tt>ENFORCE</tt> option
2784     is set on the channel, all missing automatic modes are
2785     added. (This has the effect of allowing automatic modes to
2786     be removed from clients if <tt>ENFORCE</tt> is not set.)
2787     In addition, if the mode change included a <tt>+o</tt>, the
2788     channel's last-used time is updated.</li>
2789     <li class="spaced">If the client is not an IRC operator, any
2790     necessary mode removals are performed.</li>
2791     </ul>
2792     <p>The mode changes in these last two steps are performed by a
2793     helper routine, <tt>local_set_cumodes()</tt>, which in turn calls
2794     <tt>set_cmode()</tt> for each mode in the given set.</p></dd>
2795    
2796     <dt><tt>int <b>check_kick</b>(User *<i>user</i>, const char *<i>chan</i>,
2797     int <i>on_join</i>)</tt></dt>
2798     <dd>Checks whether a client is permitted to be on a channel; if so,
2799     returns zero, otherwise kickbans the client and returns nonzero.
2800     This routine is normally called when a client joins a channel,
2801     before the actual join processing, but setting the
2802     <tt><i>on_join</i></tt> parameter to zero allows this routine to be
2803     called for clients already in the channel as well, such as for the
2804     <tt>AKICK ENFORCE</tt> command. A client can be denied access to a
2805     channel for any number of reasons, checked in the following order:
2806     <ul>
2807     <li class="spaced">If the channel name is the single character
2808     "<tt>#"</tt>" and the <tt>CSForbidShortChannel</tt>
2809     configuration option is set, the client is kickbanned.</li>
2810     <li class="spaced">If the client is a Services administrator, the
2811     client is allowed.</li>
2812     <li class="spaced">If the "<tt>check_kick</tt>" callback returns 1,
2813     the client is kickbanned; if it returns 2, the client is
2814     allowed.</li>
2815     <li class="spaced">If the client is an IRC operator, the client is
2816     allowed.</li>
2817     <li class="spaced">If the channel already exists with an
2818     IRC-operators-only mode, the client is kickbanned.
2819     (Ordinarily, the IRC server takes care of such processing,
2820     but this code is included to handle desynchs and other
2821     network problems.)</li>
2822     <li class="spaced">If the channel is not registered, then the
2823     client is kickbanned if the <tt>CSRegisteredOnly</tt>
2824     configuration option is set, and allowed otherwise.</li>
2825     <li class="spaced">If the channel is forbidden or suspended, the
2826     client is kickbanned.</li>
2827     <li class="spaced">If the channel's mode lock has an
2828     IRC-operators-only mode set, the client is kickbanned.</li>
2829     <li class="spaced">If the channel's mode lock includes a
2830     registered-nicknames-only mode and the client's nickname is
2831     not registered, the client is kickbanned. (However, this
2832     check is skipped if the <tt>CSSkipModeRCeck</tt>
2833     configuration option is set.)</li>
2834     <li class="spaced">If the client's
2835     <tt><i>nick</i>!<i>user</i>@<i>host</i></tt> string
2836     matches an autokick mask, the client is kickbanned.</li>
2837     <li class="spaced">If the client matches the <tt>NOJOIN</tt>
2838     privilege on the channel, the client is kickbanned.
2839     The client is also kickbanned if it would match the
2840     <tt>NOJOIN</tt> privilege when identified to its nickname;
2841     however, this check is skipped if less time than specified
2842     in the <tt>CSRestrictDelay</tt> configuration option has
2843     passed since Services startup.</li>
2844     <li class="spaced">Otherwise, the client is allowed.</li>
2845     </ul>
2846     <p>If the client is to be kickbanned, the routine first checks
2847     whether kicking the client would cause the channel to become empty
2848     (and thus be deleted, nullifying the effecet of any ban); if so, a
2849     <tt>JOIN</tt> message is sent to the network to cause ChanServ to
2850     join the channel, and a timeout for <tt>CSInhabit</tt> seconds is
2851     added to cause ChanServ to leave the channel after that time.
2852     Following this, the routine ensures that the ban mask is properly
2853     formatted (containing a nickname as well as user and host), then
2854     clears any ban exceptions matching the user and adds the ban mask
2855     if it is not already present. Once the ban is present, the client
2856     is then kicked from the channel, and removed from the internal data
2857     structures if necessary.</p>
2858     <p><i>Implementation note: As mentioned in
2859     <a href="../d.html">Appendix D of the user manual</a>, when
2860     ChanServ temporarily enters a channel for a kickban, it is not
2861     added to the internal channel data; as a result, a subsequent
2862     <tt>UNBAN</tt> or <tt>INVITE</tt> on the channel will return a
2863     "channel does not exist" error. It would probably be better to
2864     add ChanServ to the channel's client list like any ordinary
2865     client.</i></p>
2866     </dd>
2867    
2868     <dt><tt>int <b>check_topiclock</b>(Channel *<i>c</i>, time_t <i>topic_time</i>)</tt></dt>
2869     <dd>Called on a channel topic change (<tt><i>topic_time</i></tt> is the
2870     timestamp associated with the topic change) to restore the topic to
2871     its previous value if the channel's <tt>TOPICLOCK</tt> option is
2872     set. Returns nonzero if the topic is changed by the routine,
2873     otherwise zero.</dd>
2874     </dl>
2875    
2876     <p class="backlink"><a href="#top">Back to top</a></p>
2877    
2878    
2879     <h5 class="subsubsubsection-title" id="s4-1-4">7-4-1-4. The <tt>SET</tt> and <tt>UNSET</tt> commands</h5>
2880    
2881     <p>The handlers for the <tt>SET</tt> and <tt>UNSET</tt> commands are
2882     located in the <tt>set.c</tt> source file; as for NickServ, they function
2883     like miniature versions of the main <tt>chanserv()</tt> routine. One
2884     noteworthy difference is that the on/off options (other than the three
2885     <tt>HIDE</tt> options) are all handled by a single routine,
2886     <tt>do_set_boolean()</tt>; the main <tt>SET</tt> handler, <tt>do_set()</tt>,
2887     looks up the option name in the <tt>chanopts[]</tt> table defined in
2888     <tt>main.c</tt> (checking privileges for the <tt>NOEXPIRE</tt> option),
2889     then calls <tt>do_set_boolean()</tt>, which uses the data from the
2890     <tt>ChanOpt</tt> structure to set channel flags and send responses to the
2891     calling client.</p>
2892    
2893     <p>Other noteworthy option handlers are:</p>
2894    
2895     <dl>
2896     <dt><tt><b>do_set_founder()</b></tt>
2897     <br/><tt><b>do_set_successor()</b></tt></dt>
2898     <dd>Both <tt>SET FOUNDER</tt> and <tt>SET SUCCESSOR</tt> follow the
2899     same general pattern: the given nickname is looked up to retrieve
2900     its nickname group ID, the ID is checked to ensure that both
2901     founder and successor are not set to the same nickname group, and
2902     an informational message is logged to record the change. The major
2903     difference is that <tt>SET FOUNDER</tt> checks to ensure that the
2904     new founder has not reached the channel registration limit, while
2905     <tt>SET SUCCESSOR</tt> makes no such check. (Even if it did, the
2906     check would only make sense at the time the <tt>SET SUCCESSOR</tt>
2907     command was given, and would not reflect any future channel
2908     registrations or drops by the successor. An alternative
2909     possibility would be to have successor channels count against the
2910     channel limit as well, as mentioned in <a href="11.html#s1">section
2911     11-1</a>.)</dd>
2912    
2913     <dt><tt><b>do_set_mlock()</b></tt></dt>
2914     <dd>The <tt>SET MLOCK</tt> handler is fairly complex, as it must parse
2915     the mode string and parameters to ensure that users cannot
2916     inadvertently (or maliciously) cause an invalid <tt>MODE</tt>
2917     message to be sent to the IRC network. The routine parses the mode
2918     string character by character; if a mode is found that conflicts
2919     with an earlier setting in the string, the later occurrence takes
2920     precedence. Additionally, in order to simplify cleanup in case a
2921     problem is found, the new mode lock is accumulated in a temporary
2922     <tt>ModeLock</tt> structure, which is copied into the channel's
2923     data when the routine successfully completes.
2924     <p>In order to support additional modes provided by particular IRC
2925     protocols, <tt>do_set_mlock()</tt> defines a callback, "<tt>SET
2926     MLOCK</tt>", which is called once for every mode in the mode
2927     string; it is also called once after all modes have been processed,
2928     to allow for a final validity check (for example, to check for
2929     modes that require other modes to be set, as the Unreal protocol
2930     module does).</p></dd>
2931     </dl>
2932    
2933     <p class="backlink"><a href="#top">Back to top</a></p>
2934    
2935    
2936     <h5 class="subsubsubsection-title" id="s4-1-5">7-4-1-5. ChanServ utility routines</h5>
2937    
2938     <p>ChanServ's utility functions are defined in <tt>util.c</tt>. As with
2939     NickServ, the preprocessor symbol <tt>STANDALONE_CHANSERV</tt> can be
2940     defined before including <tt>util.c</tt> in another file; this causes the
2941     routines <tt>new_channelinfo()</tt>, <tt>free_channelinfo()</tt>, and
2942     <tt>reset_levels</tt> to be defined as <tt>static</tt>, and eliminates all
2943     other code. <tt>new_channelinfo()</tt> and <tt>free_channelinfo()</tt> are
2944     used to allocate and free resources for a <tt>ChannelInfo</tt> structure,
2945     like their nickname counterparts; <tt>reset_levels()</tt> resets the
2946     privilege levels for a channel (the <tt>levels[]</tt> array) to default
2947     values.</p>
2948    
2949     <p>Aside from these three functions (all exported from ChanServ),
2950     <tt>util.c</tt> defines the following routines, along with the
2951     initialization and cleanup routines <tt>init_util()</tt> and
2952     <tt>exit_util()</tt>:</p>
2953    
2954     <dl>
2955     <dt><tt>int <b>check_channel_limit</b>(const NickGroupInfo *<i>ngi</i>, int *<i>max_ret</i>)</tt></dt>
2956     <dd>Compares the given nickname group's registered channel count with
2957     the limit applied to that nickname, returning -1 if the limit has
2958     yet to be reached, 0 if the limit has been reached, and 1 if the
2959     limit has been exceeded (much like string comparison functions).
2960     Also stores the registered channel limit in the variable pointed to
2961     by <tt><i>max_ret</i></tt> if <tt><i>max_ret</i></tt> is not
2962     <tt>NULL</tt>. This routine is exported.</dd>
2963    
2964     <dt><tt>ChannelInfo *<b>makechan</b>(const char *<i>chan</i>)</tt></dt>
2965     <dd>Creates a new <tt>ChannelInfo</tt> structure for the given channel
2966     name, adds it to the database, and returns it.</dd>
2967    
2968     <dt><tt>int <b>delchan</b>(ChannelInfo *<i>ci</i>)</tt></dt>
2969     <dd>Removes the given channel from the database, returning nonzero on
2970     success, zero on failure.</dd>
2971    
2972     <dt><tt>void <b>count_chan</b>(ChannelInfo *<i>ci</i>)</tt></dt>
2973     <dd>Updates the <tt>NickGroupInfo</tt> record for the given channel's
2974     founder to indicate that that nickname group owns the channel,
2975     incrementing the owned-channel count.</dd>
2976    
2977     <dt><tt>void <b>uncount_chan</b>(ChannelInfo *<i>ci</i>)</tt></dt>
2978     <dd>Removes the given channel from its founder's owned-channel list
2979     and decrements the owned-channel count.</dd>
2980    
2981     <dt><tt>int <b>is_founder</b>(const User *<i>user</i>, const ChannelInfo *<i>ci</i>)</tt></dt>
2982     <dd>Returns whether the given user has founder access to the given
2983     channel, whether due to being the actual channel founder or to
2984     identifying for the channel with its founder password.</dd>
2985    
2986     <dt><tt>int <b>is_identified</b>(const User *<i>user</i>, const ChannelInfo *<i>ci</i>)</tt></dt>
2987     <dd>Returns whether the given user has identified for the channel with
2988     its founder password. A subset of <tt>is_founder()</tt>.</dd>
2989    
2990     <dt><tt>void <b>restore_topic</b>(Channel *<i>c</i>)</tt></dt>
2991     <dd>Restores the saved topic on a newly-created channel if the
2992     channel is registered and its <tt>KEEPTOPIC</tt> option is set.</dd>
2993    
2994     <dt><tt>void <b>record_topic</b>(ChannelInfo *<i>ci</i>, const char *<i>topic</i>, const char *<i>setter</i>, time_t <i>topic_time</i>)</tt></dt>
2995     <dd>Records the given topic in the given channel's data structure.</dd>
2996    
2997     <dt><tt>void <b>suspend_channel</b>(ChannelInfo *<i>ci</i>, const char *<i>reason</i>, const char *<i>who</i>, const time_t <i>expires</i>)</tt></dt>
2998     <dd>Suspends the given channel, copying the parameters
2999     <tt><i>reason</i></tt>, <tt><i>who</i></tt>, and
3000     <tt><i>expires</i></tt> into the suspension data fields. (If
3001     <tt><i>expires</i></tt> is zero, then the suspension will not
3002     expire.)</dd>
3003    
3004     <dt><tt>void <b>unsuspend_channel</b>(ChannelInfo *<i>ci</i>, int <i>set_time</i>)</tt></dt>
3005     <dd>Cancels the suspension on the given channel. If
3006     <tt><i>set_time</i></tt> is nonzero, the last-used time of the
3007     channel will be updated according to <tt>CSSuspendGrace</tt> to
3008     prevent the channel from expiring for that length of time (if
3009     <tt>CSSuspendGrace</tt> or <tt>CSExpire</tt> are not set, or if the
3010     channel already has enough time before expiration, the last-used
3011     time will not be changed).</dd>
3012    
3013     <dt><tt>void <b>chan_bad_password</b>(User *<i>u</i>, ChannelInfo *<i>ci</i>)</tt></dt>
3014     <dd>Records a bad password attempt for the given channel, sending out a
3015     <tt>WALLOPS</tt> if the number of consecutive bad password attempts
3016     for the channel reaches the limit specified by the
3017     <tt>BadPassWarning</tt> configuration option (if set).</dd>
3018    
3019     <dt><tt>ChanOpt *<b>chanopt_from_name</b>(const char *<i>optname</i>)</tt></dt>
3020     <dd>Returns the <tt>ChanOpt</tt> corresponding to the given
3021     (case-insensitive) option name, or <tt>NULL</tt> if no matching
3022     option is found.</dd>
3023    
3024     <dt><tt>char *<b>chanopts_to_string</b>(const ChannelInfo *<i>ci</i>, const NickGroupInfo *<i>ngi</i>)</tt></dt>
3025     <dd>Returns a string describing the set of options active on the given
3026     channel in human-readable form. <tt>ngi</tt> indicates the client
3027     to which the string will be sent and is used in <tt>getstring()</tt>
3028     calls. The returned string is stored in a static buffer, which
3029     will be overwritten by the next call to this routine.</dd>
3030     </dl>
3031    
3032     <p class="backlink"><a href="#top">Back to top</a></p>
3033    
3034    
3035     <h4 class="subsubsection-title" id="s4-2">7-4-2. Channel access list handling</h4>
3036    
3037     <p>As discussed in the user's manual, user privileges on channels are
3038     maintained via channel access lists. Channel access list handling in
3039     ChanServ is split into three files. One, <tt>access.c</tt>, contains
3040     common routines and privilege level definitions, and is included in the
3041     <tt>chanserv/main</tt> module; the other two, <tt>access-levels.c</tt> and
3042     <tt>access-xop.c</tt>, are independent modules which provide two different
3043     ways of manipulating access lists. A separate header file,
3044     <tt>access.h</tt>, contains definitions related to channel access lists.</p>
3045    
3046     <p class="backlink"><a href="#top">Back to top</a></p>
3047    
3048    
3049     <h5 class="subsubsubsection-title" id="s4-2-1">7-4-2-1. Access list basics</h5>
3050    
3051     <p>The <tt>access.c</tt> source file, included as part of the main ChanServ
3052     module, serves two main purposes; to define the set of privileges
3053     associated with channels, and to provide utility routines for performing
3054     common operations related to channel access lists. It also makes use of
3055     the <tt>access.h</tt> header file for certain structure and constant
3056     definitions.</p>
3057    
3058     <p>The list of channel privileges is defined in the <tt>levelinfo[]</tt>
3059     array at the top of the file; each element in the array is a
3060     <tt>LevelInfo</tt> structure that describes one privilege. (The word
3061     "level" in the identifiers comes from the command, <tt>LEVELS</tt>, used
3062     to modify the settings on a per-channel basis; that command name was
3063     originally used for the meaning of "setting the <i>levels</i> at which
3064     privileges are given".)</p>
3065    
3066     <p>The word "privilege" itself is something of a misnomer, as it includes
3067     two "negative privileges", <tt>CA_AUTODEOP</tt> and <tt>CA_NOJOIN</tt>.
3068     While these can be used in the same manner as ordinary privileges, their
3069     primary function is in conjunction with the <tt>SECUREOPS</tt> and
3070     <tt>RESTRICTED</tt> channel options; these cause the respective privilege
3071     levels to be treated as zero, preventing users not on the channel access
3072     list to be auto-deopped or blocked from entering the channel. However,
3073     these two privileges are not visible to users, so "privilege" is considered
3074     clear enough to use in the documentation</p>
3075    
3076     <p>The <tt>LevelInfo</tt> structure, defined in <tt>access.h</tt>, contains
3077     the following fields:</p>
3078    
3079     <dl>
3080     <dt><tt>int <b>what</b></tt></dt>
3081     <dd>The <tt>CA_*</tt> constant used for this privilege.</dd>
3082    
3083     <dt><tt>int <b>defval</b></tt></dt>
3084     <dd>The default channel access level corresponding to this
3085     privilege.</dd>
3086    
3087     <dt><tt>const char *<b>name</b></tt></dt>
3088     <dd>The user-visible name for this privilege, used in the
3089     <tt>LEVELS</tt> command. An empty string makes the privilege
3090     invisible to users.</dd>
3091    
3092     <dt><tt>int <b>desc</b></tt></dt>
3093     <dd>The message string index giving the privilege's description.</dd>
3094    
3095     <dt><tt>int <b>action</b></tt></dt>
3096     <dd>The "meaning" of the privilege: the action to be performed for
3097     clients with the appropriate access level. One of the following
3098     flags, any of which may be combined (OR'd) with
3099     <tt>CL_LESSEQUAL</tt> to make the privilege's associated level a
3100     maximum rather than a minimum:
3101     <ul>
3102     <li><b><tt>CL_SET_MODE</tt>:</b> Sets channel user modes on the
3103     corresponding client.</li>
3104     <li><b><tt>CL_CLEAR_MODE</tt>:</b> Clears channel user modes from
3105     the corresponding client.</li>
3106     <li><b><tt>CL_ALLOW_CMD</tt>:</b> Allows a command or set of
3107     commands to be used.</li>
3108     <li><b><tt>CL_OTHER</tt>:</b> Handled separately (or a no-op).</li>
3109     </ul></dd>
3110    
3111     <dt><tt>union {...} <b>target</b></tt></dt>
3112     <dd>Data used in implementing the privilege. The union has two
3113     members:
3114     <ul>
3115     <li class="spaced"><tt>struct {...} <b>cumode</b></tt>: Used for
3116     <tt>CL_SET_MODE</tt> and <tt>CL_CLEAR_MODE</tt>. Includes
3117     three fields:
3118     <ul>
3119     <li><tt>const char *<b>modes</b></tt>: The string of
3120     mode(s) to set on the client.</li>
3121     <li><tt>int <b>cont</b></tt>: Used to "chain" privileges
3122     together, so that only the first applicable mode
3123     set is used (used for <tt>AUTOOP</tt>,
3124     <tt>AUTOHALFOP</tt>, and <tt>AUTOVOICE</tt>).</li>
3125     <li><tt>int32 <b>flags</b></tt>: The mode flags equivalent
3126     to <tt>modes</tt>. Set at module initialization
3127     time (this field can be left uninitialized).</li>
3128     </ul></li>
3129     <li class="spaced"><tt>struct {...} <b>cmd</b></tt>: Used for
3130     <tt>CL_ALLOW_CMD</tt>. Includes two string fields:
3131     <ul>
3132     <li><tt>const char *<b>main</b></tt>: The relevant command
3133     name.</li>
3134     <li><tt>const char *<b>sub</b></tt>: The relevant subcommand
3135     for the given command, or <tt>NULL</tt> if none.</li>
3136     </ul></li>
3137     </ul></dd>
3138     </dl>
3139    
3140     <p>In addition to the <tt>levelinfo[]</tt> table itself, exported for use
3141     by other modules (particularly the <tt>http/dbaccess</tt> module, described
3142     in <a href="8.html#s2-7">section 8-2-7</a>), the file's initialization
3143     routine <tt>init_access()</tt> copies relevant parts of the table into two
3144     local arrays indexed by privilege (<tt>CA_*</tt> value):
3145     <tt>def_levels[]</tt>, containing each entry's default access level (the
3146     <tt>defval</tt> field), and <tt>lev_is_max[]</tt>, containing a boolean
3147     indication of whether the privilege's access level is a maximum (whether
3148     the <tt>action</tt> field has <tt>CL_LESSEQUAL</tt> set).</p>
3149    
3150     <p>The main portion of <tt>access.c</tt> defines the following utility
3151     functions for use by the main ChanServ module and the two access list
3152     manipulation modules. Several of the routines are exported for use by
3153     external modules as well.</p>
3154    
3155     <dl>
3156     <dt><tt>int <b>get_ci_level</b>(const ChannelInfo *<i>ci</i>, int <i>what</i>)</tt></dt>
3157     <dd><i>Exported routine.</i> Returns the given channel's level for the
3158     given privilege, translating <tt>ACCLEV_DEFAULT</tt> in the
3159     channel's <tt>levels[]</tt> into the appropriate default value.
3160     Returns <tt>ACCLEV_INVALID</tt> (and logs an error message) on
3161     invalid parameters.</dd>
3162    
3163     <dt><tt>int <b>check_access</b>(const User *<i>user</i>, const ChannelInfo *<i>ci</i>, int <i>what</i>)</tt></dt>
3164     <dd><i>Exported routine.</i> Returns whether the given client has the
3165     given privilege (<tt><i>what</i></tt>) on the given channel. Due
3166     to an unfortunate coincidence of terms, this routine can seem
3167     confusing to call for the <tt>CA_NOJOIN</tt> "privilege": the
3168     return value will be 1 if the client does <i>not</i> "have access
3169     to" the channel, <i>i.e.</i> matches the <tt>CA_NOJOIN</tt>
3170     privilege.</dd>
3171    
3172     <dt><tt>int check_access_if_idented(const User *user, const ChannelInfo *ci, int what)</tt></dt>
3173     <dd><i>Exported routine.</i> Like <tt>check_access()</tt>, but returns
3174     what the result would be if the client was identified for its
3175     nickname. (If the nickname is not registered, the return value
3176     will be the same as for <tt>check_access()</tt>.</dd>
3177    
3178     <dt><tt>int check_access_cmd(const User *user, const ChannelInfo *ci, const char *command, const char *subcommand)</tt></dt>
3179     <dd><i>Exported routine.</i> Returns whether the client is allowed to
3180     use the given command on the given channel. If the check is being
3181     made for a specific subcommand, that subcommand is specified in
3182     <tt><i>subcommand</i></tt>; otherwise, <tt><i>subcommand</i></tt>
3183     is <tt>NULL</tt>.</dd>
3184    
3185     <dt><tt>int <b>get_access</b>(const User *<i>user</i>, const ChannelInfo *<i>ci</i>)</tt></dt>
3186     <dd>Returns the given client's access level on the given channel,
3187     taking into account whether the client has identified for its
3188     nickname with respect to the nickname and channel <tt>SECURE</tt>
3189     options.</dd>
3190    
3191     <dt><tt>static int get_access_if_idented(const User *user, const ChannelInfo *ci)</tt></dt>
3192     <dd>Like <tt>get_access()</tt>, but returns the access level associated
3193     with the client's nickname regardless of whether the client has
3194     identified or not.</dd>
3195    
3196     <dt><tt>int check_access_cumode(const User *user, const ChannelInfo *ci, int32 newmodes, int32 changemask)</tt></dt>
3197     <dd>Checks the channel user modes of a client on a channel, returning a
3198     bitmask of modes that are to be changed (in other words, the
3199     bitwise exclusive-or of the current and resulting mode sets).
3200     <tt><i>newmodes</i></tt> is the client's current set of modes on
3201     the channel; <tt><i>changemask</i></tt> indicates which modes
3202     changed due to the action that caused this function to be called.</dd>
3203    
3204     <dt><tt>int access_add(ChannelInfo *ci, const char *nick, int level, int uacc)</tt>
3205     <br/><tt>int access_del(ChannelInfo *ci, const char *nick, int uacc)</tt></dt>
3206     <dd>Adds (<tt>access_add()</tt>) or deletes (<tt>access_del()</tt>) an
3207     entry to or from the given channel's access list for the nickname
3208     group to which <tt><i>nick</i></tt> belongs. <tt><i>level</i></tt>
3209     is the access level for the new entry, and <tt><i>uacc</i></tt> is
3210     the access level of the client making the change. Both routines
3211     return one of the following result codes, defined in
3212     <tt>cs-local.h</tt>:
3213     <ul>
3214     <li><b><tt>RET_ADDED</tt></b> (<tt>access_add()</tt> only): The
3215     target nickname did not previously exist on the channel's
3216     access list, and was successfully added.</li>
3217     <li><b><tt>RET_CHANGED</tt></b> (<tt>access_add()</tt> only): The
3218     target nickname previously had a different access level on
3219     the channel, and the access level was successfully
3220     changed.</li>
3221     <li><b><tt>RET_UNCHANGED</tt></b> (<tt>access_add()</tt> only): The
3222     target nickname already had the desired access level on the
3223     channel.</li>
3224     <li><b><tt>RET_DELETED</tt></b> (<tt>access_del()</tt> only): The
3225     target nickname was successfully deleted from the channel's
3226     access list.</li>
3227     <li><b><tt>RET_LISTED</tt></b> (used by other modules): The target
3228     nickname was listed.</li>
3229     <li><b><tt>RET_PERMISSION</tt>:</b> The calling user does not have
3230     permission to make the requested change.</li>
3231     <li><b><tt>RET_NOSUCHNICK</tt>:</b> The given nickname is not
3232     registered.</li>
3233     <li><b><tt>RET_NICKFORBID</tt>:</b> The given nickname is
3234     forbidden.</li>
3235     <li><b><tt>RET_LISTFULL</tt></b> (<tt>access_add()</tt> only): The
3236     channel's access list is full and the given nickname is not
3237     already on the list.</li>
3238     <li><b><tt>RET_NOENTRY</tt></b> (<tt>access_del()</tt> only): The
3239     given nickname does not exist on the channel's access
3240     list.</li>
3241     <li><b><tt>RET_INTERR</tt></b>: An internal error occurred.</li>
3242     </ul>
3243     Note that successful return codes are positive, while failure
3244     return codes are negative (zero is not used as a return code).</dd>
3245     </dl>
3246    
3247     <p><tt>access.c</tt> also includes initialization code in the
3248     <tt>init_access()</tt> routine, called from the <tt>chanserv/main</tt>
3249     module's <tt>init_module()</tt>. This routine initializes the
3250     <tt>def_levels[]</tt> and <tt>lev_is_max[]</tt> arrays, as well as the
3251     <tt>flags</tt> field of the <tt>target.cumode</tt> structure for privileges
3252     that set or clear modes; it also disables (by removing from the table) any
3253     privileges for features not supported by the IRC protocol in use.
3254     <i>Implementation note: This relies on the current design of Services, in
3255     which the protocol module will never be changed while the program is
3256     running. If this design is changed, the code will need to be updated to
3257     leave the appropriate entries in the table, perhaps by adding a "disabled"
3258     flag or field to each entry.</i></p>
3259    
3260     <p>There is also a corresponding <tt>exit_access()</tt> routine; it does
3261     nothing, but is included for completeness.</p>
3262    
3263     <p class="backlink"><a href="#top">Back to top</a></p>
3264    
3265    
3266     <h5 class="subsubsubsection-title" id="s4-2-2">7-4-2-2. Manipulation via <tt>ACCESS</tt> and <tt>LEVELS</tt></h5>
3267    
3268     <p>The <tt>chanserv/access-levels</tt> module is one of two modules for
3269     manipulating channel access lists. It provides direct access to both the
3270     channel access list itself, via the <tt>ACCESS</tt> command, and channels'
3271     privilege level settings, via the <tt>LEVELS</tt> command.</p>
3272    
3273     <p>Since the functions available in both commands change depending on
3274     runtime parameters, their help messages are handled by a "<tt>HELP</tt>"
3275     callback function, <tt>do_help()</tt>. In addition to description of the
3276     two commands, a third help option, <tt>LEVELS DESC</tt> provides
3277     descriptions of the available channel privileges; unlike most other help
3278     messages, the text is generated on the fly from the <tt>levelinfo[]</tt>
3279     array and corresponding description strings.</p>
3280    
3281     <p>The <tt>ACCESS</tt> command handler, <tt>do_access()</tt>, calls one of
3282     several subroutines to perform each of the available actions, depending on
3283     the subcommand given. Two of these, <tt>do_access_add()</tt> and
3284     <tt>do_access_del()</tt>, simply call the <tt>access_add()</tt> and
3285     <tt>access_del()</tt> routines mentioned in <a href="#s4-2-1">section
3286     7-4-2-1</a>, sending appropriate result messages to the calling client
3287     depending on the return codes from those functions.
3288     <tt>do_access_list()</tt> and <tt>do_access_listlevel()</tt> select access
3289     entries for listing based on the given parameters, then call
3290     <tt>access_list()</tt>, defined below the <tt>ACCESS</tt> subcommand
3291     handlers, to actually send the list text to the calling client. (The
3292     <tt><i>sent_header</i></tt> parameter to <tt>access_list()</tt> is used to
3293     to record whether a list header message has been sent.) The final
3294     subcommand handler, <tt>do_access_count()</tt>, simply counts up the number
3295     of (active) access entries in the list and sends that in a response message
3296     to the calling client.</p>
3297    
3298     <p>The <tt>LEVELS</tt> command also has several subcommands, though these
3299     are all handled within the command handler <tt>do_levels()</tt>. The
3300     command implementation itself is fairly straightforward, with <tt>SET</tt>
3301     and <tt>DISABLE</tt> searching the <tt>levelinfo[]</tt> array for the named
3302     privilege, and <tt>LIST</tt> iterating through that array to display the
3303     current level for each privilege.</p>
3304    
3305     <p class="backlink"><a href="#top">Back to top</a></p>
3306    
3307    
3308     <h5 class="subsubsubsection-title" id="s4-2-3">7-4-2-3. Manipulation via <tt>XOP</tt></h5>
3309    
3310     <p>The <tt>chanserv/access-xop</tt> module, defined in <tt>access-xop.c</tt>,
3311     provides the <tt>XOP</tt> command set for managing channel access lists.
3312     While these commands present the access list as several distinct lists
3313     (SOP, AOP, and so on), they are in fact only different views of the same
3314     channel access list, each containing nicknames with a particular predefined
3315     access level. This has the following side effects:</p>
3316    
3317     <ul>
3318     <li class="spaced">A particular nickname cannot be present on two or more
3319     lists simultaneously (this would require having two entries on the
3320     access list for the same nickname). Attempting to add a nickname
3321     that is already on a different list is treated as an access level
3322     change.</li>
3323    
3324     <li class="spaced">Changes to the access list made by the <tt>ACCESS</tt>
3325     command will also be reflected in the relevant XOP lists. If the
3326     <tt>ACCESS</tt> command is used to add a nickname at a level not
3327     associated with any <tt>XOP</tt> command, that nickname will be
3328     invisible from every <tt>XOP</tt> list, even if it would have
3329     privileges associated with one or more of the lists.
3330     <i>Implementation note: One could conceivably change the <tt>XOP
3331     LIST</tt> commands to list all entriess in intermediate or extreme
3332     ranges; for example, nicknames with an access level between
3333     <tt>ACCLEV_AOP</tt> and <tt>ACCLEV_SOP</tt> could be shown on the
3334     AOP list, and nicknames with an access level below
3335     <tt>ACCLEV_NOP</tt> could be shown on the NOP list.</i></li>
3336    
3337     <li class="spaced">If the channel's privilege levels are changed (such as
3338     with the <tt>LEVELS</tt> command), the <tt>XOP</tt> commands may no
3339     longer perform as their help messages describe, because the XOP
3340     lists are associated with hardcoded access levels rather than
3341     specific privileges. <i>Implementation note: Attempting to base
3342     the lists on privilege levels could have unusual results if, for
3343     example, the auto-op privilege was lowered below auto-voice.</i></li>
3344     </ul>
3345    
3346     <p>The commands themselves are handled by a single central routine,
3347     <tt>handle_xop()</tt>, which is called from each command's particular
3348     handler with the appropriate access level. <tt>handle_xop()</tt> works
3349     much like <tt>do_access()</tt> from <tt>access-levels.c</tt> (in fact, it
3350     is a modified copy of <tt>do_access()</tt>, and its subroutines are
3351     likewise derived from the handlers for the <tt>ACCESS</tt> subcommands).
3352     Response messages include the list name (SOP, AOP, etc.) as a parameter in
3353     the message, and this name is determined based on the command's access
3354     level using the <tt>XOP_LISTNAME</tt> macro at the top of the file.</p>
3355    
3356     <p class="backlink"><a href="#top">Back to top</a></p>
3357    
3358     <!------------------------------------------------------------------------>
3359     <hr/>
3360    
3361     <h3 class="subsection-title" id="s5">7-5. MemoServ</h3>
3362    
3363     <p>The MemoServ pseudoclient serves as an adjunct to NickServ, allowing
3364     short messages (memos) to be sent between users and storing those messages
3365     for the recipient. Like other pseudoclients, the majority of MemoServ's
3366     functionality is implemented in the <tt>memoserv/main</tt> module,
3367     described below in <a href="#s5-1">section 7-5-1</a>; additional modules
3368     allow users to maintain "ignore" lists (<tt>memoserv/ignore</tt>,
3369     <a href="#s5-2">section 7-5-2</a>) and have memos forwarded via E-mail
3370     (<tt>memoserv/forward</tt>, <a href="#s5-3">section 7-5-3</a>).</p>
3371    
3372     <p class="backlink"><a href="#top">Back to top</a></p>
3373    
3374    
3375     <h4 class="subsubsection-title" id="s5-1">7-5-1. MemoServ core functionality</h4>
3376    
3377     <p>Unlike OperServ, NickServ, and ChanServ, MemoServ only provides
3378     additional functionality to users (nicknames and, to an extent, channels)
3379     already registered with Services. For this reason, the main MemoServ
3380     code is comparatively simple, and the <tt>memoserv/main</tt> module is
3381     implemented by a single source file, <tt>main.c</tt>. There is also a
3382     header file, <tt>memoserv.h</tt>, containing structures and definitions
3383     used by MemoServ.</p>
3384    
3385     <p class="backlink"><a href="#top">Back to top</a></p>
3386    
3387    
3388     <h5 class="subsubsubsection-title" id="s5-1-1">7-5-1-1. Memo data structures</h5>
3389    
3390     <p>The structure used to store memos are defined in the header file
3391     <tt>memoserv.h</tt>. Each memo is stored in a structure called
3392     (appropriately enough) <tt>Memo</tt>, and the set of memos belonging to a
3393     particular nickname group is stored in a <tt>MemoInfo</tt> structure. The
3394     <tt>Memo</tt> structure contains the following fields:</p>
3395    
3396     <dl>
3397     <dt><tt>uint32 <b>number</b></tt></dt>
3398     <dd>The index number associated with this memo, for use with MemoServ
3399     commands such as <tt>READ</tt> and <tt>DEL</tt>. Note that while
3400     the array of memos in a <tt>MemoInfo</tt> structure is kept free of
3401     holes caused by memo deletions, memo index numbers do not change
3402     except as a result of the <tt>RENUMBER</tt> command, so there is
3403     not a one-to-one mapping between the two.</dd>
3404    
3405     <dt><tt>int16 <b>flags</b></tt></dt>
3406     <dd>Flags associated with the memo. Zero or more of the following
3407     constants, OR'd together:
3408     <ul>
3409     <li><b><tt>MF_UNREAD</tt>:</b> The memo has not yet been read.</li>
3410     <li><b><tt>MF_EXPIREOK</tt>:</b> The memo is allowed to expire.
3411     <i>Implementation note: The sense of this flag is opposite
3412     that of MemoServ's design, which expires any memos except
3413     those explicitly locked with the <tt>SAVE</tt> command.
3414     This was done to keep compatibility with memos sent using
3415     old versions of Services, in which memos did not expire;
3416     rather than explicitly adding a "locked" flag to every memo
3417     when loading databases from such a version, the flag takes
3418     advantage of the fact that the corresponding bit in such
3419     memos is zero. This way, for a memo to expire, the flag
3420     must be explicitly enabled by the new version when the memo
3421     is sent.</i></li>
3422     </ul></dd>
3423    
3424     <dt><tt>time_t <b>time</b></tt></dt>
3425     <dd>The timestamp when the memo was sent.</dd>
3426    
3427     <dt><tt>time_t <b>firstread</b></tt></dt>
3428     <dd>The time at which the memo was first read by its recipient. This
3429     is stored to ensure that an unread memo does not expire immediately
3430     after it is first read (the <tt>MSExpireDelay</tt> configuration
3431     option controls how long MemoServ will wait after this timestamp
3432     before expiring the memo).</dd>
3433    
3434     <dt><tt>char <b>sender</b>[NICKMAX]</tt></dt>
3435     <dd>The nickname of the client that sent the memo.</dd>
3436    
3437     <dt><tt>char *<b>channel</b></tt></dt>
3438     <dd>For memos sent to channels, the name of the channel to which the
3439     memo was sent. <tt>NULL</tt> for other memos.</dd>
3440    
3441     <dt><tt>char *<b>text</b></tt></dt>
3442     <dd>The text of the memo.</dd>
3443     </dl>
3444    
3445     <p>The <tt>MemoInfo</tt> structure contains:</p>
3446    
3447     <dl>
3448     <dt><tt>Memo *<b>memos</b></tt>
3449     <br/><tt>int16 <b>memos_count</b></tt></dt>
3450     <dd>A variable-length array containing the memos associated with this
3451     structure.</dd>
3452    
3453     <dt><tt>int16 <b>memomax</b></tt></dt>
3454     <dd>The maximum number of memos this nickname group is allowed to have
3455     stored. Either a nonnegative literal value (zero is allowed, and
3456     means that the nickname group cannot receive any memos at all), or
3457     one of the following constants:
3458     <ul>
3459     <li><b><tt>MEMOMAX_UNLIMITED</tt>:</b> There is no limit on the
3460     number of nicknames that can be stored.</li>
3461     <li><b><tt>MEMOMAX_DEFAULT</tt>:</b> The default limit, set by the
3462     <tt>MSMaxMemos</tt> configuration option, is used. (If
3463     <tt>MSMaxMemos</tt> is changed, the new limit will be
3464     automatically applied.)</li>
3465     </ul>
3466     The constant <tt>MEMOMAX_MAX</tt> is also provided to give the
3467     largest possible maximum value (a side-effect of storing the value
3468     in 16 bits).</dd>
3469     </dl>
3470    
3471     <p>Each <tt>MemoInfo</tt> structure is stored as part of the corresponding
3472     nickname group's <tt>NickGroupInfo</tt> structure (see
3473     <a href="#s3-1-1">section 7-3-1-1</a>). In previous versions, channels had
3474     associated memo lists as well, but this feature was removed for version 5.1
3475     in favor of the current system of distributing channel memos to privileged
3476     users.</p>
3477    
3478     <p>There are two more constants in <tt>memoserv.h</tt>:
3479     <tt>MS_RECEIVE_PRI_CHECK</tt> and <tt>MS_RECEIVE_PRI_DELIVER</tt>. These
3480     are callback priorities that can be used with <tt>add_callback_pri()</tt>
3481     to allow a "<tt>receive memo</tt>" callback function to ensure it is called
3482     before functions which try to deliver the memo. Both the
3483     <tt>memoserv/ignore</tt> and <tt>memoserv/forward</tt> modules take
3484     advantage of these constants.</p>
3485    
3486     <p class="backlink"><a href="#top">Back to top</a></p>
3487    
3488    
3489     <h5 class="subsubsubsection-title" id="s5-1-2">7-5-1-2. The <tt>memoserv/main</tt> module</h5>
3490    
3491     <p>The <tt>memoserv/main</tt> module is defined in the file <tt>main.c</tt>,
3492     and aside from the lack of any auxiliary source files, its structure is
3493     more or less the same as that of the other pseudoclients' core modules.</p>
3494    
3495     <p>Since, as mentioned above, the <tt>MemoInfo</tt> structures containing
3496     memo data are stored as part of the corresponding <tt>NickGroupInfo</tt>
3497     structures, special handling is required when moving the data to or from
3498     persistent storage. MemoServ uses iterator functions for the
3499     <tt>MemoInfo</tt> table that in turn iterate through <tt>NickGroupInfo</tt>
3500     structures, and sets up a dummy record containing each record's associated
3501     nickname group ID, much like the <tt>nickserv/access</tt> module (see
3502     <a href="#s3-2">section 7-3-2</a>). For individial <tt>Memo</tt> records,
3503     an additional iterator is used to loop through each memo in every
3504     <tt>MemoInfo</tt> structure.</p>
3505    
3506     <p>Most MemoServ actions are implemented by separate routines in the
3507     "MemoServ private routines" section of the file, rather than directly in
3508     the command handlers. These functions are:</p>
3509     <ul>
3510     <li><b><tt>send_memo()</tt></b> and <b><tt>send_chan_memo()</tt></b>,
3511     which send memos to users and channels respectively;</li>
3512     <li><b><tt>list_memo()</tt></b>, which sends the calling client a one-line
3513     description of a memo, and <b><tt>list_memo_callback()</tt></b>, a
3514     callback function to do the same thing;</li>
3515     <li><b><tt>read_memo()</tt></b> and <b><tt>read_memo_callback</tt></b>,
3516     which display the text of a memo;</li>
3517     <li><b><tt>save_memo()</tt></b> and <b><tt>save_memo_callback</tt></b>,
3518     which mark memos as non-expiring; and</li>
3519     <li><b><tt>del_memo()</tt></b> and <b><tt>del_memo_callback()</tt></b>,
3520     which delete memos.</li>
3521     </ul>
3522    
3523     <p>Other utility routines include:</p>
3524    
3525     <dl>
3526     <dt><tt>void <b>check_memos</b>(User *<i>u</i>)</tt></dt>
3527     <dd>Checks whether the given client's nickname group has any unread
3528     memos, sending an appropriate message to the client if so (and if
3529     the <tt>NF_MEMO_SIGNON</tt> flag is set for the nickname group).
3530     Called by the "<tt>user create</tt>" callback function
3531     <tt>do_user_create()</tt> if the client is recognized.</dd>
3532    
3533     <dt><tt>void <b>expire_memos</b>(MemoInfo *<i>mi</i>)</tt></dt>
3534     <dd>Deletes all memos in the given <tt>MemoInfo</tt> structure that
3535     are eligible for expiration.</dd>
3536    
3537     <dt><tt>MemoInfo *<b>get_memoinfo</b>(const char *<i>name</i>, NickGroupInfo **<i>owner_ret</i>, int *<i>error_ret</i></tt></dt>
3538     <dd>Returns the <tt>MemoInfo</tt> structure corresponding to the given
3539     nickname, or <tt>NULL</tt> on error. On success,
3540     <tt>*<i>owner_ret</i></tt> is set to point to the
3541     <tt>NickGroupInfo</tt> structure for the corresponding nickname
3542     group; on error, <tt>*<i>error_ret</i></tt> is set to one of the
3543     following error codes:
3544     <ul>
3545     <li><b>GMI_INTERR</b>: An internal error occurred.</li>
3546     <li><b>GMI_FORBIDDEN</b>: The given nickname is forbidden.</li>
3547     <li><b>GMI_SUSPENDED</b>: The given nickname is suspended.</li>
3548     <li><b>GMI_NOTFOUND</b>: The given nickname is not registered.</li>
3549     </ul>
3550     <i>Implementation note: This function's primary purpose of handling
3551     both nicknames and channel names transparently was obsoleted with
3552     the redesign of channel memo handling; however, the function still
3553     serves the purpose of checking for unregistered, forbidden, or
3554     suspended nicknames, eliminating the necessity to include such
3555     checks directly in every command handler.</i></dd>
3556     </dl>
3557    
3558     <p>The command handlers are for the most part simple, only needing to parse
3559     parameters and call the appropriate utility routine. The two commands
3560     which are implemented directly, <tt>SET</tt> and <tt>INFO</tt>, are mostly
3561     branching trees for the various nickname options and statuses.</p>
3562    
3563     <p class="backlink"><a href="#top">Back to top</a></p>
3564    
3565    
3566     <h4 class="subsubsection-title" id="s5-2">7-5-2. Memo ignore lists</h4>
3567    
3568     <p>The <tt>memoserv/ignore</tt> module was added to allow users a way to
3569     block memos from unwanted senders such as spammers. The module is
3570     implemented by the source file <tt>ignore.c</tt>.</p>
3571    
3572     <p>For the most part, <tt>ignore.c</tt> works in the same way as the
3573     <tt>nickserv/access</tt> and <tt>nickserv/autojoin</tt> modules. The
3574     one routine unique to <tt>memoserv/ignore</tt> is the
3575     <tt>check_if_ignored()</tt> routine, added as a callback function to the
3576     core MemoServ module's "<tt>receive memo</tt>" callback at priority
3577     <tt>MS_RECEIVE_PRI_CHECK</tt>. The routine runs through the nickname
3578     group's ignore list twoce: the first time, it treats each entry as a
3579     <tt><i>Nick</i>!<i>user</i>@<i>host</i></tt> mask which is compared against
3580     that of the memo sender, while the second time, it treats each entry as a
3581     nickname, and the memo is blocked if that nickname's nickname group ID
3582     matches that of the sender (thus proventing malicious clients from evading
3583     the block by simply changing to another linked nick). If thd memo is
3584     blocked, the routine returns the language string index
3585     <tt>MEMO_C_GETS_NO_MEMOS</tt> (the same as is used if the target has a
3586     memo limit of zero), to prevent leaking information about the ignore list
3587     contents.</p>
3588    
3589     <p class="backlink"><a href="#top">Back to top</a></p>
3590    
3591    
3592     <h4 class="subsubsection-title" id="s5-3">7-5-3. Memo forwarding</h4>
3593    
3594     <p>The <tt>memoserv/forward</tt> module, defined in the source file
3595     <tt>forward.c</tt>, provides an interface between memos in Services and an
3596     external mail system. As such, one of its prerequisite modules (other than
3597     <tt>memoserv/main</tt>, of course) is <tt>nickserv/mail-auth</tt>, to
3598     reduce the possibility of Services being abused to send mail to arbitrary
3599     addresses.</p>
3600    
3601     <p>The module includes two methods of forwarding memos: manual and
3602     automatic. The former, manual forwarding, is done through the
3603     <tt>FORWARD</tt> command, implemented by the <tt>do_forward()</tt> routine
3604     and its subroutines <tt>fwd_memo()</tt> and <tt>fwd_memo_callback()</tt>.
3605     As with other commands that allow users to send mail via Services, the
3606     command handler includes a check that the command is not used more
3607     frequently than the configuration option <tt>MSForwardDelay</tt> specifies.
3608     If this and the other checks pass, the command handler takes one of two
3609     actions, depending on its parameter. If "<tt>ALL</tt>" was given, then
3610     <tt>fwd_memo()</tt> is called for each memo in the calling client's
3611     <tt>MemoInfo</tt> structure; otherwise, the parameter is passed to
3612     <tt>process_numlist()</tt> to call the <tt>fwd_memo_callback()</tt>
3613     callback function (which in turn calls <tt>fwd_memo()</tt>) for each memo
3614     specified in the index list.</p>
3615    
3616     <p><tt>fwd_memo()</tt> itself does not perform the actual sending of the
3617     mail message; rather, it accumulates message body text in its parameters
3618     <tt>char **<i>p_body</i></tt> and <tt>int *<i>p_bodylen</i></tt> (both of
3619     which are modified as a result of the routine). This allows the caller to
3620     combine multiple memos into a single message without knowing ahead of time
3621     how many or which memos are to be sent.</p>
3622    
3623     <p>The second method of forwarding, automatic forwarding on receipt, is
3624     implemented by the <tt>do_receive_memo()</tt> function, attached to the
3625     MemoServ "<tt>receive memo</tt>" callback, along with the
3626     <tt>do_set_forward()</tt> option handler (attached to the "<tt>SET</tt>"
3627     callback) to set forwarding options for a nickname group. Of the
3628     forwarding options, <tt>ON</tt> (flag <tt>NF_MEMO_FWD</tt>) and
3629     <tt>OFF</tt> (no flags set) are fairly obvious. For <tt>COPY</tt> (flags
3630     <tt>NF_MEMO_FWD</tt> and <tt>NF_MEMO_FWDCOPY</tt>), however, it is worth
3631     noting that (as also mentioned in the user's manual and help messages)
3632     memos will be rejected when the recipient has a full list of memos. This
3633     is partly a result of the callback implementation, in the sense that the
3634     check for a full memo list is made before the callback is ever called; but
3635     it also ensures that every memo received by the user is either processed
3636     completely (both forwarded and saved) or not at all. This can be important
3637     if, for example, a user uses <tt>SET FORWARD COPY</tt> to save copies of
3638     memos to an archival E-mail address, but only uses Services to actually
3639     read the memos. If a memo that would overflow the list was nonetheless
3640     forwarded and treated as "sent", the sender would be left wondering why the
3641     recipient was not responding to the purportedly delivered memo.</p>
3642    
3643     <p class="backlink"><a href="#top">Back to top</a></p>
3644    
3645     <!------------------------------------------------------------------------>
3646     <hr/>
3647    
3648     <h3 class="subsection-title" id="s6">7-6. StatServ</h3>
3649    
3650     <p>The StatServ pseudoclient is intended to record and provide network
3651     statistics; however, mostly due to lack of developer interest, it has
3652     floundered. The module is defined in the <tt>modules/statserv</tt>
3653     directory by a single source file, <tt>main.c</tt>, and an accompanying
3654     header file, <tt>statserv.h</tt>.</p>
3655    
3656     <p class="backlink"><a href="#top">Back to top</a></p>
3657    
3658    
3659     <h4 class="subsubsection-title" id="s6-1">7-6-1. StatServ data structures</h4>
3660    
3661     <p>The current implementation of StatServ only records data for servers.
3662     This data is stored in a <tt>ServerStats</tt> structure, defined in
3663     <tt>statserv.h</tt> and containing the following fields:</p>
3664    
3665     <dl>
3666     <dt><tt>ServerStats *<b>next</b>, *<b>prev</b></tt></dt>
3667     <dd>Used to maintain the linked list of <tt>ServerStats</tt>
3668     structures.</dd>
3669    
3670     <dt><tt>char *<b>name</b></tt></dt>
3671     <dd>The name of the server to which this structure applies.</dd>
3672    
3673     <dt><tt>time_t <b>t_join</b></tt></dt>
3674     <dd>The timestamp at which the server most recently joined the network.
3675     Zero if the server is not currently connected.</dd>
3676    
3677     <dt><tt>time_t <b>t_quit</b></tt></dt>
3678     <dd>The timestamp at which the server last disconnected. Zero if
3679     Services has never seen the server disconnect.</dd>
3680    
3681     <dt><tt>char *<b>quit_message</b></tt></dt>
3682     <dd>The quit message used the last time the server disconnected.
3683     <tt>NULL</tt> if Services has never seen the server disconnect.</dd>
3684    
3685     <dt><tt>int <b>usercnt</b>, <b>opercnt</b></tt></dt>
3686     <dd>The current number of clients and IRC operators on the server.</dd>
3687     </dl>
3688    
3689     <p>As the data has no direct references to other data stored persistently,
3690     saving the <tt>ServerStats</tt> records is straightforward.</p>
3691    
3692     <p>There are also commented-out definitions for <tt>MinMax</tt> and
3693     <tt>MinMaxHistory</tt> structures, and <tt>MinMaxHistory</tt> fields in
3694     <tt>ServerStats</tt>; these were originally intended for keeping a history
3695     of client and operator counts on each server, but this functionality was
3696     never implemented.</p>
3697    
3698     <p class="backlink"><a href="#top">Back to top</a></p>
3699    
3700    
3701     <h4 class="subsubsection-title" id="s6-2">7-6-2. The StatServ module</h4>
3702    
3703     <p>The module itself, defined in <tt>main.c</tt>, is likewise quite simple.
3704     It follows the general layout of other pseudoclient core modules, though it
3705     only has two commands (other than <tt>HELP</tt>) and a few callback
3706     routines.</p>
3707    
3708     <p>The two commands, <tt>SERVERS</tt> and <tt>USERS</tt>, are handled by
3709     <tt>do_servers()</tt> and <tt>do_users()</tt> respectively. The latter
3710     needs no additional explanation, as it only sends the calling client the
3711     user and operator counts it maintains internally (via the client-related
3712     callbacks mentioned below). <tt>do_servers()</tt> is only slightly more
3713     complex, handling four distinct subcommands. Three of these
3714     (<tt>STATS</tt>, <tt>LIST</tt>, and <tt>VIEW</tt>) extract information from
3715     the <tt>ServerStats</tt> structures and send them to the calling client;
3716     the last, <tt>DELETE</tt>, allows a structure to be deleted, and is
3717     protected by an <tt>is_services_admin()</tt> check in the <tt>if</tt>
3718     chain.</p>
3719    
3720     <p>In order to keep track of statistics, StatServ naturally relies on
3721     callbacks. To watch for connecting and disconnecting servers, StatServ
3722     adds callback functions to the core's "<tt>server create</tt>" and
3723     "<tt>server delete</tt>" callbacks; these functions update the relevant
3724     <tt>ServerStats</tt> structures as servers join and leave the network, with
3725     <tt>stats_do_server()</tt> (the "<tt>server create</tt>" handler) creating
3726     a new <tt>ServerStats</tt> structure if it sees a server connect that is
3727     not recorded in the <tt>ServerStats</tt> structure table.</p>
3728    
3729     <p>StatServ also uses the "<tt>user create</tt>", "<tt>user delete</tt>",
3730     and "<tt>user MODE</tt>" callbacks to keep track of the number of clients
3731     and IRC operators on the network, stored in the file-scope variables
3732     <tt>usercnt</tt> and <tt>opcnt</tt> respectively. Note that this overlaps
3733     slightly with the maximum client count maintained by OperServ; a good
3734     argument could be made for moving this functionality to StatServ as well,
3735     but it has been left in OperServ for historical reasons (the maximum client
3736     count monitoring functionality has been part of OperServ since the earliest
3737     versions of Services, long before StatServ existed).</p>
3738    
3739     <p class="backlink"><a href="#top">Back to top</a></p>
3740    
3741     <!------------------------------------------------------------------------>
3742     <hr/>
3743    
3744     <h3 class="subsection-title" id="s7">7-7. Miscellaneous pseudoclients</h3>
3745    
3746     <p>Aside from the standard pseudoclients listed above, there are two
3747     additional pseudoclients, HelpServ and DevNull, provided in case they can
3748     be of use. These pseudoclients are disabled in the default Services
3749     configuration. These modules are so simple as to not warrant their own
3750     subdirectories, and are stored in the <tt>modules/misc</tt> directory.</p>
3751    
3752     <p class="backlink"><a href="#top">Back to top</a></p>
3753    
3754    
3755     <h4 class="subsubsection-title" id="s7-1">7-7-1. HelpServ</h4>
3756    
3757     <p>The HelpServ pseudoclient, defined in <tt>modules/misc/helpserv.c</tt>,
3758     uses the parameters given in each <tt>PRIVMSG</tt> it receives to form a
3759     pathname for a text file, which (if it exists) is then sent to the calling
3760     client as <tt>NOTICE</tt>s. The pathname is formed by concatenating the
3761     path given by the <tt>HelpDir</tt> module configuration setting (the
3762     example configuration file uses <tt>helpfiles</tt>, relative to the
3763     Services data directory) with each of its space-separated parameters,
3764     inserting a path separator ("<tt>/</tt>") between each element. To allow
3765     the parameter to be case-insensitive even when using case-sensitive
3766     filesystems, all uppercase characters in the parameters are lowercased.</p>
3767    
3768     <p>Since this involves access to a file specified by an arbitrary
3769     user-specified string, the routine must take care not to allow access to
3770     inappropriate files. This is done by replacing all slashes and periods in
3771     the string with underscores, to prevent a malicious user from specifying
3772     a parameter like "<tt>../../../../../etc/passwd</tt>". (If there are
3773     explicit symbolic links to parent directories, of course, HelpServ will
3774     happily follow them.) <i>Implementation note: As a general rule, when
3775     sanitizing user input like this it is better to make a set of explicitly
3776     allowed characters and delete or convert anything outside that set.
3777     However, pathnames on Unix systems are simple and well defined:
3778     disregarding the effects of symbolic links, only a slash can allow access
3779     to file entries outside of the current directory, and "<tt>.</tt>" and
3780     "<tt>..</tt>" are the only entries that are automatically created within
3781     each directory, so the set of allowed characters is essentially "everything
3782     except <tt>/</tt> and <tt>.</tt>".</i></p>
3783    
3784     <p>In the earliest versions of Services, HelpServ was a standard
3785     pseudoclient, and other pseudoclients made use of its functionality to
3786     display their own help messages, which were stored as text files under the
3787     <tt>data/helpfiles</tt> directory. However, the help messages were later
3788     moved to string data stored directly in the executable file, and then to
3789     the current model of language files, diluting the usefulness of HelpServ
3790     itself. The module has nonetheless been left in Services in case it is
3791     useful for things such as providing network information.</p>
3792    
3793     <p class="backlink"><a href="#top">Back to top</a></p>
3794    
3795    
3796     <h4 class="subsubsection-title" id="s7-2">7-7-2. DevNull</h4>
3797    
3798     <p>The DevNull pseudoclient, defined in <tt>modules/misc/devnull.c</tt>, is
3799     an extremely simple pseudoclient which, like its Unix namesake
3800     <tt>/dev/null</tt>, simply discards any <tt>PRIVMSG</tt>s sent to it. It
3801     is not particularly useful in the ordinary course of events, but the author
3802     has made use of it as a default <tt>/query</tt> target to prevent messages
3803     from going to unintended users.</p>
3804    
3805     <p class="backlink"><a href="#top">Back to top</a></p>
3806    
3807     <!------------------------------------------------------------------------>
3808     <hr/>
3809    
3810     <p class="backlink"><a href="6.html">Previous section: Database handling</a> |
3811     <a href="index.html">Table of Contents</a> |
3812     <a href="8.html">Next section: Other modules</a></p>
3813    
3814     </body>
3815     </html>