Author: Kev <klmitch@mit.edu>
authorKevin L. Mitchell <klmitch@mit.edu>
Fri, 15 Jun 2001 20:53:40 +0000 (20:53 +0000)
committerKevin L. Mitchell <klmitch@mit.edu>
Fri, 15 Jun 2001 20:53:40 +0000 (20:53 +0000)
Log message:

Finished up the events API documentation; wrote documentation for gline,
ircd_snprintf, motd, msgq, privileges, and the send functions.  Still to
document: modebuf, mode_parse(), joinbuf, and jupe.

git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@504 c9e4aea6-c8fd-4c43-8297-357d70d61c8c

doc/api/events.txt
doc/api/gline.txt [new file with mode: 0644]
doc/api/ircd_snprintf.txt [new file with mode: 0644]
doc/api/motd.txt [new file with mode: 0644]
doc/api/msgq.txt [new file with mode: 0644]
doc/api/privileges.txt [new file with mode: 0644]
doc/api/send.txt [new file with mode: 0644]

index 9e8303682178dc8dca59fef3d9aef7c6a6d4b91e..cadfa705d84b94159bc7867b012ee3a508a47ecd 100644 (file)
@@ -535,10 +535,282 @@ but may only be called once, since it uses function static storage to
 store the flag strings.
 </function>
 
+<function>
+int sig_signal(struct Signal* sig);
+
+This macro returns the signal number for the given struct Signal.
+</function>
+
+<function>
+void* sig_data(struct Signal* sig);
+
+When a struct Signal is initialized, data that the call-back function
+may find useful is stored in the struct Signal.  This macro returns
+that pointer.
+</function>
+
+<function>
+int sig_ed_int(struct Signal* sig);
+
+Engines may find it convenient to associate an integer with a struct
+Signal.  This macro may be used to retrieve that integer or, when used
+as an lvalue, to assign a value to it.  Engine data must be either an
+int or a void*; use of both is prohibited.
+</function>
+
+<function>
+void* sig_ed_ptr(struct Signal* sig);
+
+Engines may find it convenient to associate a void* pointer with a
+struct Signal.  This macro may be used to retrieve that pointer or,
+when used as an lvalue, to assign a value to it.  Engine data must be
+either an int or a void*; use of both is prohibited.
+</function>
+
+<function>
+int sig_active(struct Signal* sig);
+
+A signal's active flag is set when initialized by signal_add().  This
+may be used by the application to determine whether or not the signal
+has been initialized yet.  If it is, sig_active() returns a non-zero
+value; otherwise, its value is 0.
+</function>
+
+<function>
+void signal_add(struct Signal* signal, EventCallBack call, void* data,
+               int sig);
+
+This function is called to add a signal to the list of signals to be
+monitored.  The _signal_ parameter is a pointer is a pointer to a
+struct Signal that is allocated by the application.  The _call_
+parameter is a pointer to a function to process any signal events.
+The _data_ parameter is for use of the signal call-back and may be
+zero.  The _sig_ parameter is the integer value of the signal to be
+monitored.
+</function>
+
+<function>
+enum TimerType t_type(struct Timer* tim);
+
+This macro returns the type of the given timer.
+</function>
+
+<function>
+time_t t_value(struct Timer* tim);
+
+This macro returns the value that was used when the given timer was
+initialized by the events subsystem.  It will contain an absolute time
+if the timer type is TT_ABSOLUTE, and a relative time otherwise.
+</function>
+
+<function>
+time_t t_expire(struct Timer* tim);
+
+This macro returns the absolute time at which the timer will next
+expire.
+</function>
+
+<function>
+void* t_data(struct Timer* tim);
+
+When a struct Timer is initialized, data that the call-back function
+may find useful is stored in the struct Socket.  This macro returns
+that pointer.
+</function>
+
+<function>
+int t_ed_int(struct Timer *tim);
+
+Engines may find it convenient to associate an integer with a struct
+Timer.  This macro may be used to retrieve that integer or, when used
+as an lvalue, to assign a value to it.  Engine data must be either an
+int or a void*; use of both is prohibited.
+</function>
+
+<function>
+void* t_ed_ptr(struct Timer *tim);
+
+Engines may find it convenient to associate a void* pointer with a
+struct Timer.  This macro may be used to retrieve that pointer or,
+when used as an lvalue, to assign a value to it.  Engine data must be
+either an int or a void*; use of both is prohibited.
+</function>
+
+<function>
+int t_active(struct Timer *tim);
+
+A timer's active flag is set when initialized by timer_add(), and is
+cleared immediately prior to generating an event of type ET_DESTROY.
+This may be used by the application to determine whether or not the
+timer is still in use by the events subsystem.  If it is, s_active()
+returns a non-zero value; otherwise, its value is 0.
+</function>
+
+<function>
+void timer_add(struct Timer* timer, EventCallBack call, void* data,
+              enum TimerType type, time_t value);
+
+This function is called to initialize and queue a timer.  The _timer_
+parameter is a pointer to a struct Timer that is allocated by the
+application.  The _call_ parameter is a pointer to a function to
+process the timer's expiration.  The _data_ parameter is for use of
+the timer call-back and may be zero.  The _type_ parameter must be one
+of the valid timer types--TT_ABSOLUTE, TT_RELATIVE, or TT_PERIODIC.
+Finally, _value_ is the value for the timer's expiration.
+</function>
+
+<function>
+void timer_del(struct Timer* timer);
+
+When the application no longer needs a TT_PERIODIC timer, or when it
+wishes to stop a TT_ABSOLUTE or TT_RELATIVE timer before its
+expiration, it should call the timer_del() function.
+</function>
+
+<function>
+void timer_chg(struct Timer* timer, enum TimerType type, time_t value);
+
+Occasionally, an application may wish to delay an existing TT_ABSOLUTE
+or TT_RELATIVE timer; this may be done with the timer_chg() function.
+The _type_ parameter must be one of TT_ABSOLUTE or
+TT_RELATIVE--changing the values of TT_PERIODIC timers is not
+supported.  The _value_ parameter is the same as would be given to
+timer_add() for that particular type of timer.
+</function>
+
+<function>
+void timer_run(void);
+
+When an engine has finished processing the results of its socket and
+signal checks--just before it loops around to test for more events--it
+should call the timer_run() function to expire any waiting timers.
+</function>
+
+<function>
+time_t timer_next(struct Generators* gen);
+
+Most engines will use a blocking call with a timeout to check for
+socket activity.  To determine when the next timer needs to be run,
+and thus to calculate how long the call should block, the engine
+should call timer_next() with the _gen_ parameter passed to the
+_EngineLoop_ function.  The timer_next() function returns an absolute
+time, which may have to be massaged into a relative time before the
+engine may use it.
+</function>
+
+<function>
+const char* timer_to_name(enum TimerType type);
+
+This function is defined only when DEBUGMODE is #define'd.  It takes
+the given _type_ and returns a string giving that type's name.  This
+function may safely be called from Debug() macros.
+</function>
+
+<function>
+enum EventType ev_type(struct Event* ev);
+
+This macro simply returns the type of the event _ev_.
+</function>
+
+<function>
+int ev_data(struct Event* ev);
+
+When an event is generated, a single integer can be passed along as a
+piece of extra information.  This can be used, for instance, to carry
+an errno value when an ET_ERROR is generated.  This macro simply
+returns that integer.
+</function>
+
+<function>
+struct Socket* ev_socket(struct Event* ev);
+
+If the event was generated by a socket, this macro returns a pointer
+to the struct Socket that generated the event.  The results are
+undefined if the event was not generated by a socket.
+</function>
+
+<function>
+struct Signal* ev_signal(struct Event* ev);
+
+If the event was generated by a signal, this macro returns a pointer
+to the struct Signal that generated the event.  The results are
+undefined if the event was not generated by a signal.
+</function>
+
+<function>
+struct Timer* ev_timer(struct Event* ev);
+
+If the event was generated by a timer, this macro returns a pointer to
+the struct Timer that generated the event.  The results are undefined
+if the event was not generated by a timer.
+</function>
+
+<function>
+void event_init(int max_sockets);
+
+Before any of the functions or macros described here can be called,
+the events subsystem must be initialized by calling event_init().  The
+_max_sockets_ parameter specifies to the events subsystem how many
+sockets it must be able to support; this figure may be used for memory
+allocation by the engines.
+</function>
+
+<function>
+void event_loop(void);
+
+Once the initial sockets are open, signals added, and timers queued,
+the application must call the event_loop() function in order to
+actually begin monitoring those sockets, signals, and timers.
+</function>
+
+<function>
+void event_generate(enum EventType type, void* arg, int data);
+
+This is the function called by the events subsystem to generate
+particular events.  The _type_ parameter specifies the type of event
+to generate, and the _arg_ parameter must be a pointer to the event's
+generator.  The _data_ parameter may be used for passing such things
+as signal numbers or errno values.
+</function>
+
+<function>
+const char* event_to_name(enum EventType type);
+
+This function is defined only when DEBUGMODE is #define'd.  It takes
+the given _type_ and returns a string giving that event type's name.
+This function may safely be called from Debug() macros.
+</function>
+
+<function>
+const char* engine_name(void);
+
+This function is used to retrieve the name of the engine presently
+being used by the events subsystem.
+</function>
+
+<function>
+void gen_ref_inc(void* gen);
+
+This macro increments the reference count of the generator _gen_,
+preventing it from simply disappearing without warning.
+</function>
+
+<function>
+void gen_ref_dec(void* gen);
+
+This macro decrements the reference count of the generator _gen_, and
+releases the memory associated with it by generating at ET_DESTROY
+event if the reference count falls to zero and the generator is marked
+for destruction.  No references should be made to the generator after
+calling this macro.
+</function>
+
 <authors>
 Kev <klmitch@mit.edu>
 </authors>
 
 <changelog>
+[2001-6-14 Kev] Finished initial description of the events subsystem.
+
 [2001-6-13 Kev] Initial description of the events subsystem.
 </changelog>
diff --git a/doc/api/gline.txt b/doc/api/gline.txt
new file mode 100644 (file)
index 0000000..4da9eb5
--- /dev/null
@@ -0,0 +1,283 @@
+Some users can be very annoying, as any IRC operator can attest.  Some
+can in fact be downright abusive.  Sometimes the best way of dealing
+with these users is to ban them from the entire network.  The G-line
+system permits this.
+
+G-lines are fairly complicated.  A G-line can be active or inactive,
+either locally or globally.  It can be a purely local G-line, or
+global.  It could be based on IP address or on host name.  In short,
+there are many variations on the basic G-line.  Worse, there is also
+the concept of a "bad channel," or BADCHAN, that has been tacked onto
+the G-line subsystem, when it should have been a separate command in
+the first place.
+
+Different types of G-lines are differentiated from each other through
+the use of various flags.  Some of these flags are maintained solely
+by the G-line subsystem, where as others are passed to various
+functions in the API.
+
+<macro>
+#define GLINE_MAX_EXPIRE 604800        /* max expire: 7 days */
+
+This macro lists the maximum expire time a G-line is permitted to
+have.  This value is limited to 7 days to prevent abuse of the system.
+</macro>
+
+<macro>
+#define GLINE_ACTIVE   0x0001
+
+This flag is used to indicate that a given G-line is globally active.
+</macro>
+
+<macro>
+#define GLINE_IPMASK   0x0002
+
+This flag is used to indicate that a given G-line is an IP mask.  This
+flag is maintained internally by the G-line subsystem.
+</macro>
+
+<macro>
+#define GLINE_BADCHAN  0x0004
+
+This flag is used to indicate that a given G-line specifies a BADCHAN,
+a channel that users are not permitted to join.  This flag is
+maintained internally, but is also used in gline_find() to search for
+a BADCHAN for a particular channel.
+</macro>
+
+<macro>
+#define GLINE_LOCAL    0x0008
+
+This flag is used to indicate that a given G-line is a local G-line.
+Local G-lines do not affect users on other servers.
+</macro>
+
+<macro>
+#define GLINE_ANY      0x0010
+
+This flag is passed to gline_find() to signal that function to return
+any G-line or BADCHAN that matches the passed mask string.  It is
+never set on a real G-line.
+</macro>
+
+<macro>
+#define GLINE_FORCE    0x0020
+
+This flag is passed to gline_add() to force the server to accept an
+expire time that might be out of bounds.  It is never set on a real
+G-line.
+</macro>
+
+<macro>
+#define GLINE_EXACT    0x0040
+
+This flag is passed to gline_find() to signal that function to return
+only G-lines that exactly match the passed mask string.  That is, the
+ircd_strcmp() function is called to compare the G-line to the mask,
+rather than the match() function.  This flag is never set on a real
+G-line.
+</macro>
+
+<macro>
+#define GLINE_LDEACT   0x0080  /* locally deactivated */
+
+This flag is set on global G-lines that have been locally
+deactivated.  This flag is maintained internally by the G-line
+subsystem.
+</macro>
+
+<macro>
+#define GLINE_GLOBAL   0x0100  /* find only global glines */
+
+This flag is passed to gline_find() or gline_lookup() to specify that
+the caller is only interested in global G-lines.  This flag is never
+set on a real G-line.
+</macro>
+
+<macro>
+#define GLINE_LASTMOD  0x0200  /* find only glines with non-zero lastmod */
+
+This flag is passed to gline_find() or gline_lookup() to specify that
+the caller is only interested in G-lines with a non-zero lastmod time,
+that is, G-lines that were not set by a U-lined service.  This flag is
+never set on a real G-line.
+</macro>
+
+<struct>
+struct Gline;
+
+The struct Gline describes everything about a given G-line.  None of
+its fields may be directly accessed by the application; use the
+functions and macros described below instead.
+</struct>
+
+<function>
+int GlineIsActive(struct Gline* g);
+
+This macro returns a non-zero value if the G-line is active, or 0
+otherwise.  If a G-line is locally deactivated, this macro will always
+return 0.
+</function>
+
+<function>
+int GlineIsRemActive(struct Gline* g);
+
+This macro returns a non-zero value if the G-line is active, ignoring
+whether or not it is locally deactivated.
+</function>
+
+<function>
+int GlineIsIpMask(struct Gline* g);
+
+This macro returns a non-zero value if the G-line is an IP mask.
+</function>
+
+<function>
+int GlineIsBadChan(struct Gline* g);
+
+This macro returns a non-zero value if a G-line actually represents a
+BADCHAN.
+</function>
+
+<function>
+int GlineIsLocal(struct Gline* g);
+
+This macro returns a non-zero value if a G-line is local only.
+</function>
+
+<function>
+char* GlineUser(struct Gline* g);
+
+This macro returns the user name associated with the G-line.  If the
+G-line represents a BADCHAN, this will contain the channel name.
+</function>
+
+<function>
+char* GlineHost(struct Gline* g);
+
+This macro returns the host name associated with the G-line.  If the
+G-line represents a BADCHAN, this will be a NULL pointer.
+</function>
+
+<function>
+char* GlineReason(struct Gline* g);
+
+This macro returns the reason that was given when the G-line was set.
+</function>
+
+<function>
+time_t GlineLastMod(struct Gline* g);
+
+G-lines that were not set by a U-lined service have a modification
+time that must be monotonically increasing.  This macro simply returns
+that modification time.
+</function>
+
+<function>
+int gline_propagate(struct Client *cptr, struct Client *sptr,
+                   struct Gline *gline);
+
+When a global G-line is set or modified, all other servers must be
+notified of the new G-line.  This function takes care of propagating
+the G-line specified by _gline_, originated by the client _sptr_, to
+all servers except _cptr_ (which may be a NULL pointer).
+</function>
+
+<function>
+int gline_add(struct Client *cptr, struct Client *sptr, char *userhost,
+             char *reason, time_t expire, time_t lastmod, unsigned int flags);
+
+This function simply adds a G-line, set by _sptr_ and with a
+_userhost_, _reason_, _expire_, and _lastmod_ as specified.  The
+_flags_ parameter is a bit mask consisting of the binary OR of
+GLINE_FORCE, GLINE_LOCAL, or GLINE_ACTIVE, as appropriate.  The
+gline_add() function also calls gline_propagate() to propagate the
+G-line, and kills off any local users matching the G-line if it is
+active.
+</function>
+
+<function>
+int gline_activate(struct Client *cptr, struct Client *sptr,
+                  struct Gline *gline, time_t lastmod, unsigned int flags);
+
+This function activates the G-line specified by _gline_, setting its
+_lastmod_ time as specified.  If _flags_ is GLINE_LOCAL and if the
+G-line is locally deactivated, this function will turn off the local
+deactivation flag, but will not modify _lastmod_.  If the G-line is
+globally deactivated, passing this function the GLINE_LOCAL flag will
+have no effect.
+</function>
+
+<function>
+int gline_deactivate(struct Client *cptr, struct Client *sptr,
+                    struct Gline *gline, time_t lastmod, unsigned int flags);
+
+This function is similar to gline_activate() except that it
+deactivates the G-line.  If the given G-line is local, or if it was
+set by a U-lined service (and GLINE_LOCAL was not passed via _flags_),
+then the G-line is deleted from memory.  In all other cases, the
+G-line is simply deactivated, either locally (if GLINE_LOCAL was
+passed via _flags_) or globally.  Global deactivation will update the
+_lastmod_ time.
+</function>
+
+<function>
+struct Gline *gline_find(char *userhost, unsigned int flags);
+
+This function looks up a G-line matching the given _userhost_ value,
+under control of the _flags_ parameter.  Valid _flags_ that may be
+passed are: GLINE_BADCHAN, GLINE_ANY, GLINE_GLOBAL, GLINE_LASTMOD, or
+GLINE_EXACT, each described above.
+</function>
+
+<function>
+struct Gline *gline_lookup(struct Client *cptr, unsigned int flags);
+
+This function looks up a G-line matching the given client, specified
+by _cptr_, under the control of the _flags_.  Valid values for _flags_
+are GLINE_GLOBAL and GLINE_LASTMOD, as described above.
+</function>
+
+<function>
+void gline_free(struct Gline *gline);
+
+This function releases all storage associated with a given G-line.
+</function>
+
+<function>
+void gline_burst(struct Client *cptr);
+
+This function generates a burst of all existing global G-lines and
+BADCHANs and sends them to the server specified by _cptr_.
+</function>
+
+<function>
+int gline_resend(struct Client *cptr, struct Gline *gline);
+
+This function resends the _gline_ to a server specified by _cptr_.
+This may be used if, for instance, it is discovered that a server is
+not synchronized with respect to a particular G-line.
+</function>
+
+<function>
+int gline_list(struct Client *sptr, char *userhost);
+
+This function sends the information about a G-line matching _userhost_
+to the client specified by _sptr_.  If _userhost_ is a NULL pointer, a
+list of all G-lines is sent.
+</function>
+
+<function>
+void gline_stats(struct Client *sptr);
+
+This function generates a list of all G-lines, sending them to the
+user _sptr_ by a /STATS G response.
+</function>
+
+<authors>
+Kev <klmitch@mit.edu>
+</authors>
+
+<changelog>
+[2001-6-15 Kev] Initial documentation for the G-line API.
+</changelog>
diff --git a/doc/api/ircd_snprintf.txt b/doc/api/ircd_snprintf.txt
new file mode 100644 (file)
index 0000000..ee9b7f2
--- /dev/null
@@ -0,0 +1,268 @@
+These functions are intended to be a complete replacement for sprintf
+and sprintf_irc.  They are a (nearly) complete reimplementation, and
+of course they're snprintf clones, making it more difficult for
+accidental buffer overflows to crop up.
+
+First off, what's missing?  These functions support all ANSI C
+conversion specifiers and selected ones from ISO 9x, with the
+exception of all floating-point conversions.  The floating-point
+conversions are tricky, and will likely be dependent on the
+representation of a floating-point number on a particular
+architecture.  While that representation is likely to conform to some
+standard, it is not currently used in ircu, so seemed like a good
+thing to omit, given the difficulty of implementing it.
+
+There are two more things missing from this implementation that would
+be required by ANSI; the first is support for multibyte character
+strings, and the second is support for locales, neither of which have
+any relevance for ircu, so again omission seemed to be a good policy.
+Additionally, %#x always causes '0x' (or '0X') to be printed, even if
+the number is zero.
+
+These functions also have some extensions not seen in a
+standards-compliant implementation; technically, the ISO 9x extensions
+fall into this category, for instance.  The ISO 9x extensions
+supported are type extensions--%ju, %tu, and %zu, for instance; %qu
+and %hhu are also supported.  The extensions added for use in ircu are
+%Tu, which takes a time_t, and the new %C conversion, which inserts
+either a numeric or a nick, dependent on the <dest> parameter.  The
+GNU %m extension, which inserts the strerror() string corresponding to
+the current value of errno, is also supported, as is a special %v
+extension, which essentially does a recursive call to ircd_snprintf.
+
+The following description is descended from the Linux man page for the
+printf family of functions.
+
+The format string is composed of zero or more directives: ordinary
+characters (not %), which are copied unchanged to the output stream;
+and conversion specifications, each of which results in fetching zero
+or more subsequent arguments.  Each conversion specification is
+introduced by the character %.  The arguments must correspond properly
+(after type promotion) with the conversion specifier.  After the %,
+the following appear in sequence:
+
+* Zero or more of the following flags:
+
+  #    specifying that the value should be converted to an "alternate
+       form."  For c, d, i, n, p, s, and u conversions, this option
+       has no effect.  For o conversions, the precision of the number
+       is increased to force the first character of the output string
+       to a zero (except if a zero value is printed with an explicit
+       precision of zero).  For x and X conversions, the string '0x'
+       (or '0X' for X conversions) is prepended to it.  For e, E, f,
+       g, and G conversions, the result will always contain a decimal
+       point, even if no digits follow it (normally, a decimal point
+       appears in the results of those conversions only if a digit
+       follows).  For g and G conversions, trailing zeros are not
+       removed from the result as they would otherwise be.  For C
+       conversions, if the destination is local and the origin is a
+       user, the nick!user@host form is used.
+
+  0    specifying zero padding.  For all conversions except n, the
+       converted value is padded on the left with zeros rather than
+       blanks.  If a precision is given with a numeric conversion (d,
+       i, o, u, i, x, and X), the 0 flag is ignored.
+
+  -    (a negative field width flag) indicates the converted value is
+       to be left adjusted on the field boundary.  Except for n
+       conversions, the converted value is padded on the right with
+       blanks, rather than on the left with blanks or zeros.  A -
+       overrides a 0 if both are given.
+
+ ' '   (a space) specifying that a blank should be left before a
+       positive number produced by a signed conversion (d, e, E, f,
+       g, G, or i).
+
+  +    specifying that a sign always be placed before a number
+       produced by a signed conversion.  A + overrides a space if
+       both are used.
+
+  :    specifying that a struct Client name should be preceded by a
+       ':' character if the destination is a user
+
+* An optional decimal digit string specifying a minimum field width.
+  If the converted value has fewer characters than the field width, it
+  will be padded with spaces on the left (or right, if the
+  left-adjustment flag has been given) to fill out the field width.
+
+* An optional precision, in the form of a period (`.') followed by an
+  optional digit string.  If the digit string is omitted, the
+  precision is taken as zero.  This gives the minimum number of digits
+  to appear for d, i, o, u, x, and X conversions, the number of digits
+  to appear after the decimal-point for e, E, and f conversions, the
+  maximum number of significant digits for g and G conversions, or the
+  maximum number of characters to be printed from a string for s
+  conversions.
+
+* The optional character h, specifying that a following d, i, o, u, x,
+  or X conversion corresponds to a short int or unsigned short int
+  argument, or that a following n conversion corresponds to a pointer
+  to a short int argument.  If the h character is given again, char is
+  used instead of short int.
+
+* The optional character l (ell) specifying that a following d, i, o,
+  u, x, or X conversion applies to a pointer to a long int or unsigned
+  long int argument, or that a following n conversion corresponds to a
+  pointer to a long int argument.
+
+* The character L specifying that a following e, E, f, g, or G
+  conversion corresponds to a long double argument, or a following d,
+  i, o, u, x, or X conversion corresponds to a long long argument.
+  Note that long long is not specified in ANSI C and therefore not
+  portable to all architectures.
+
+* The optional character q.  This is equivalent to L.
+
+* A j character specifying that the following integer (d, i, o, u, x,
+  or X) conversion corresponds to an intmax_t argument.
+
+* A t character specifying that the following integer (d, i, o, u, x,
+  or X) conversion corresponds to a ptrdiff_t argument.
+
+* A z character specifying that the following integer (d, i, o, u, x,
+  or X) conversion corresponds to a size_t argument.
+
+* A T character specifying that the following integer (d, i, o, u, x,
+  or X) conversion corresponds to a time_t argument.
+
+* A character that specifies the type of conversion to be applied.
+
+A field width or precision, or both, may be indicated by an asterisk
+`*' instead of a digit string.  In this case, an int argument supplies
+the field width or precision.  A negative field width is treated as a
+left adjustment flag followed by a positive field width; a negative
+precision is treated as though it were missing.
+
+The conversion specifiers and their meanings are:
+
+  diouxX       The int (or appropriate variant) argument is converted
+               to signed decimal (d and i), unsigned octal (o),
+               unsigned decimal (u), or unsigned hexadecimal (x and
+               X) notation.  The letters abcdef are used for x
+               conversions; the letters ABCDEF are used for X
+               conversions.  The precision, if any, gives the minimum
+               number of digits that must appear; if the converted
+               value requires fewer digits, it is padded on the left
+               with zeros.
+
+  eE           [NOT IMPLEMENTED] The double argument is rounded and
+               converted in the style [-]d.dddedd where there is one
+               digit before the decimal-point character and the
+               number of digits after it is equal to the precision;
+               if the precision is missing, it is taken as 6; if the
+               precision is zero, no decimal-point character
+               appears.  An E conversion uses the letter E (rather
+               than e) to introduce the exponent.  The exponent
+               always contains at least two digits; if the value is
+               zero, the exponent is 00.
+
+  f            [NOT IMPLEMENTED] The double argument is rounded and
+               converted to  decimal notation in the style
+               [-]ddd.ddd, where the number of digits after the
+               decimal-point character is equal to the precision
+               specification.  If the precision is missing, it is
+               taken as 6; if the precision is explicitly zero, no
+               decimal-point character appears.  If a decimal point
+               appears, at least one digit appears before it.
+
+  g            [NOT IMPLEMENTED] The double argument is converted in
+               style f or e (or E for G conversions).  The precision
+               specifies the number of significant digits.  If the
+               precision is missing, 6 digits are given; if the
+               precision is zero, it is treated as 1.  Style e is
+               used if the exponent from its conversion is less than
+               -4 or greater than or equal to the precision.
+               Trailing zeros are removed from the fractional part of
+               the result; a decimal point appears only if it is
+               followed by at least one digit.
+
+  c            The int argument is converted to an unsigned char, and
+               the resulting character is written.
+
+  s            The "char *" argument is expected to be a pointer to
+               an array of character type (pointer to a string).
+               Characters from the array are written up to (but not
+               including) a terminating NUL character; if a precision
+               is specified, no more than the number specified are
+               written.  If a precision is given, no null character
+               need be present; if the precision is not specified, or
+               is greater than the size of the array, the array must
+               contain a terminating NUL character.
+
+  p            The "void *" pointer argument is printed in
+               hexadecimal (as if by %#x or %#lx).
+
+  n            The number of characters written so far is stored into
+               the integer indicated by the ``int *'' (or variant)
+               pointer argument.  No argument is converted.
+
+  m            The error message associated with the current value of
+               errno is printed as if by %s.
+
+  C            The client argument identifier is printed under the
+               control of the <dest> argument; if <dest> is NULL or
+               is a user, the client's name (nickname or server name)
+               is printed; otherwise, the client's network numeric is
+               printed.
+
+  H            The channel argument identifier (channel name) is
+               printed.
+
+  v            The argument given must be a pointer to a struct
+               VarData with vd_format and vd_args must be initialized
+               appropriately.  On return, vd_chars will contain the
+               number of characters added to the buffer, and
+               vd_overflow will contain the number of characters that
+               could not be added due to buffer overflow or due to a
+               precision.
+
+  %            A `%' is written.  No argument is converted.  The
+               complete conversion specification is `%%'.
+
+In no case does a non-existent or small field width cause truncation
+of a field; if the result of a conversion is wider than the field
+width, the field is expanded to contain the conversion result.
+
+<struct>
+struct VarData {
+  size_t       vd_chars;       /* number of characters inserted */
+  size_t       vd_overflow;    /* number of characters that couldn't be */
+  const char   *vd_format;     /* format string */
+  va_list      vd_args;        /* arguments for %v */
+};
+
+This structure is used by the %v conversion specification.  The
+_vd_format_ element must contain a format string, and the _vd_args_
+element must be a variable argument list.  Upon return from
+ircd_snprintf() or ircd_vsnprintf(), the _vd_chars_ element will
+contain the number of characters that were able to be inserted, and
+the _vd_overflow_ element will contain the number of characters that
+could not be inserted.
+</struct>
+
+<function>
+int ircd_snprintf(struct Client *dest, char *buf, size_t buf_len,
+                 const char *format, ...);
+
+This formats the argument list, under control of the _format_, into
+the buffer specified by _buf_, the size of which is specified by
+_buf_len_.  The _dest_ parameter is used to determine whether to use a
+numeric or a nickname for %C conversions.
+</function>
+
+<function>
+int ircd_vsnprintf(struct Client *dest, char *buf, size_t buf_len,
+                  const char *format, va_list args);
+
+This function is identical to the ircd_snprintf() function except for
+the variable argument list given by _args_.
+</function>
+
+<authors>
+Kev <klmitch@mit.edu>
+</authors>
+
+<changelog>
+[2001-6-15 Kev] Initial documentation of the ircd_snprintf family of
+functions.
+</changelog>
diff --git a/doc/api/motd.txt b/doc/api/motd.txt
new file mode 100644 (file)
index 0000000..5d54cf4
--- /dev/null
@@ -0,0 +1,74 @@
+The server has a Message of the Day (MOTD) which is often used for
+describing the Acceptable Usage Policy, where to get help if you have
+problems, and so on.  Older versions of ircd had a lot of duplicated
+code, as well as some inefficiencies, all related to sending the
+MOTD.  As of u2.10.11, there is an API specifically for MOTDs.  This
+API caches the MOTDs in memory for efficiency.  Sending a MOTD to a
+client is as simple as calling a single function.
+
+<function>
+void motd_init(void);
+
+This function initializes the MOTD subsystem.  It will also read in
+the default MOTD (usually ircd.motd) and the remote MOTD (usually
+remote.motd) files.
+</function>
+
+<function>
+int motd_send(struct Client* cptr);
+
+This function sends an appropriate MOTD to the client specified by
+_cptr_.  If _cptr_ is not a local client, the remote MOTD will be
+sent; otherwise, an attempt will be made to find a T-line in the
+configuration file that matches the client.  If no T-line can be
+found, the default MOTD will be sent to the client.  This function
+returns 0 for the convenience of other functions that must have an
+integer return value.
+</function>
+
+<function>
+void motd_signon(struct Client* cptr);
+
+This function is similar to motd_send(), described above, except that
+it will only send a message to the client indicating when the MOTD was
+last modified if the FEAT_NODEFAULTMOTD feature is set to TRUE.
+</function>
+
+<function>
+void motd_recache(void);
+
+The MOTD system will not automatically detect when MOTD files have
+been modified.  This function causes the MOTD system to clear the MOTD
+cache and re-read the files.
+</function>
+
+<function>
+void motd_add(const char *hostmask, const char *path);
+
+This function is used to add a MOTD to be sent to clients possessing a
+given _hostmask_.  If _hostmask_ is a numerical string, it is
+interpreted as a connection class.
+</function>
+
+<function>
+void motd_clear(void);
+
+This function clears the list of special MOTDs.  Only the default MOTD
+and remote MOTD are not affected by this function.
+</function>
+
+<function>
+void motd_report(struct Client *to);
+
+The motd_report() function sends a list of the T-lines stored in
+memory to the client specified by _to_.  Access control should be
+handled by the caller.
+</function>
+
+<authors>
+Kev <klmitch@mit.edu>
+</authors>
+
+<changelog>
+[2001-6-15 Kev] Initial documentation of the MOTD interface.
+</changelog>
diff --git a/doc/api/msgq.txt b/doc/api/msgq.txt
new file mode 100644 (file)
index 0000000..cfa6ef6
--- /dev/null
@@ -0,0 +1,195 @@
+Many messages generated by an IRC server are sent to multiple
+recipients.  Previous versions of ircd used DBuf to store these
+messages until they could actually be sent.  The problem with using a
+DBuf for this, though, is that there are multiple copies of the same
+message hanging around.  Another problem is that there is at least one
+strcpy() or equivalent call for each destination the message is sent
+to.  A simple solution to this problem is to use messages queues.
+This file documents the MsgQ interface for ircd.
+
+The MsgQ interface is loosely based on the API for DBuf.  Although the
+structures are vastly different, most calls, including several of the
+macros, are similar to certain pieces of the DBuf API.  This made
+retrofitting ircd with MsgQ support much simpler.
+
+<struct>
+struct MsgCounts {
+  int alloc;
+  int used;
+};
+
+The MsgCounts structure may be used for determining how much memory is
+in use by the MsgQ system.  The _alloc_ element is a count of the
+total number of structures (of whatever type) that have been
+allocated; the _used_ element is a count of how many are actually in
+use.  MsgQ never releases any of its allocated memory; instead, it
+places unused structures onto a free list.
+</struct>
+
+<struct>
+struct MsgBuf;
+
+The MsgBuf structure contains the actual message, along with a
+reference count and the message's length.  None of its fields are
+directly accessible by the application.
+</struct>
+
+<struct>
+struct MsgQ;
+
+The MsgQ structure is a structure allocated by the application that is
+used by the MsgQ system to describe an entire message queue, including
+both normal and priority queues.  None of its fields are directly
+accessible by the application.
+</struct>
+
+<global>
+struct MsgCounts msgBufCounts; /* resource count for struct MsgBuf */
+
+This global variable counts the number of MsgBuf structures that have
+been allocated.  This may be used to determine how much memory is in
+use by the MsgQ system.
+</global>
+
+<global>
+struct MsgCounts msgCounts;    /* resource count for struct Msg */
+
+This global variable counts the number of Msg structures that have
+been allocated.  The Msg structure describes the link between a queue
+and a message.  It is not accessible to the application, and so not
+further documented here.
+</global>
+
+<function>
+unsigned int MsgQLength(struct MsgQ* mq);
+
+This macro returns the number of bytes in a particular user's message
+queue.
+</function>
+
+<function>
+unsigned int MsgQCount(struct MsgQ* mq);
+
+This macro returns the number of messages in a particular user's
+message queue.
+</function>
+
+<function>
+void MsgQClear(struct MsgQ* mq);
+
+This macro simply clears the content of a particular message queue.
+NOTE: This macro evaluates its argument twice.
+</function>
+
+<function>
+void msgq_init(struct MsgQ *mq);
+
+This function initializes a caller-allocated message queue to be
+empty.  Calling this function on a message queue with messages in it
+WILL RESULT IN A MEMORY LEAK.
+</function>
+
+<function>
+void msgq_delete(struct MsgQ *mq, unsigned int length);
+
+This function removes the given number of bytes from the message
+queue.  If entire messages have been sent, they will be unlinked from
+the queue.  The _length_ parameter does not need to correspond to a
+given message's length; the MsgQ system is able to deal with messages
+that have only partially been sent.
+</function>
+
+<function>
+int msgq_mapiov(const struct MsgQ *mq, struct iovec *iov, int count,
+               unsigned int *len);
+
+The msgq_mapiov() function takes a struct MsgQ (specified by the _mq_
+parameter) and a caller allocated struct iovec array (specified by the
+_iov_ parameter) and maps the contents of the message into the struct
+iovec array.  The _count_ parameter must indicate the total number of
+elements available for msgq_mapiov() to use.  The _len_ parameter must
+be a pointer to an unsigned int, and upon return from the function
+will contain the total number of bytes that have been mapped into the
+struct iovec array.  This function returns the number of struct iovec
+elements that have been filled.  For more information about the
+purpose of struct iovec, see your system's man page for the writev()
+function.
+</function>
+
+<function>
+struct MsgBuf *msgq_make(struct Client *dest, const char *format, ...);
+
+This function allocates a struct MsgBuf and calls ircd_vsnprintf()
+with the _dest_ and _format_ parameters to fill it in.  Most callers
+should use the send_buffer() function (declared in send.h) to attach
+the struct MsgBuf to a client's message queue.
+</function>
+
+<function>
+struct MsgBuf *msgq_vmake(struct Client *dest, const char *format, va_list vl);
+
+This function is identical to msgq_make() except that it takes a
+va_list (given by the _vl_ parameter) and calls ircd_vsnprintf() to
+format the message.
+</function>
+
+<function>
+void msgq_append(struct Client *dest, struct MsgBuf *mb, const char *format,
+                ...);
+
+Occasionally a caller is not able to completely compute a message
+before calling msgq_make().  When this happens, the msgq_append()
+function may be called to append more text onto the struct MsgBuf
+specified by the _mb_ parameter.  As with msgq_make(), the _dest_ and
+_format_ parameters are passed to ircd_vsnprintf(), along with the
+additional arguments.
+</function>
+
+<function>
+void msgq_clean(struct MsgBuf *mb);
+
+As mentioned above, struct MsgBuf includes a reference count.  When
+that reference count reaches zero, the structure is released.  The
+reference count is set to 1 by msgq_make() and msgq_vmake().  Once a
+given message has been attached to all the queues it needs to be, the
+caller should call the msgq_clean() function to decrement this
+reference count.  This function will place the struct MsgBuf back onto
+the free list if it did not get attached to any message queues.  The
+msgq_delete() function calls msgq_clean() internally, so the
+application need not call msgq_clean() explicitly afterwards.
+</function>
+
+<function>
+void msgq_add(struct MsgQ *mq, struct MsgBuf *mb, int prio);
+
+This function is used to attach a given struct MsgBuf, as specified by
+the _mb_ parameter, to a given message queue.  The _prio_ parameter,
+if non-zero, specifies that the message should be placed on the
+priority queue.  This function is called by send_buffer(), defined in
+send.h; most applications should call that function, rather than this
+one.
+</function>
+
+<function>
+void msgq_count_memory(size_t *msg_alloc, size_t *msg_used,
+                      size_t *msgbuf_alloc, size_t *msgbuf_used);
+
+This function simply takes the counts kept in msgBufCounts and
+msgCounts and multiplies them by the appropriate structure sizes,
+storing the resulting sizes into its parameters.
+</function>
+
+<function>
+unsigned int msgq_bufleft(struct MsgBuf *mb);
+
+This function is for use in conjunction with msgq_append().  It
+returns the total number of bytes of free storage in the given _mb_.
+</function>
+
+<authors>
+Kev <klmitch@mit.edu>
+</authors>
+
+<changelog>
+[2001-6-15 Kev] Initial documentation for the MsgQ functions.
+</changelog>
diff --git a/doc/api/privileges.txt b/doc/api/privileges.txt
new file mode 100644 (file)
index 0000000..dd8697a
--- /dev/null
@@ -0,0 +1,91 @@
+Access control becomes more of a problem as you have more and more
+users that need to access certain features.  As it stands, ircu has
+only 3 access levels: ordinary user, local operator, and global
+operator.  This is hardly enough control, especially over some of the
+more advanced and powerful features, such as G-lines.
+
+Since u2.10.11, ircu includes the concept of privileges.  Privileges
+are basically an arbitrarily long bit string.  Access to particular
+features is governed by the value of a particular bit of that bit
+string--in other words, privileges are a form of Access Control List.
+This document covers the basic structures and macros used by the
+privileges system.
+
+<struct>
+struct Privs;
+
+The Privs structure stores a privileges bit string and represents a
+user's entire privilege set.  This is implemented as a structure,
+rather than as an array of integers, in order to leverage C's
+structure copy.
+</struct>
+
+<function>
+void PrivSet(struct Privs pset, int priv);
+
+This macro sets the privilege specified by _priv_ in the privileges
+structure.  This macro evaluates the _priv_ argument twice.
+</function>
+
+<function>
+void PrivClr(struct Privs pset, int priv);
+
+This macro clears the privilege specified by _priv_ in the privileges
+structure.  This macro evaluates the _priv_ argument twice.
+</function>
+
+<function>
+int PrivHas(struct Privs pset, int priv);
+
+This macro tests whether the privilege specified by _priv_ is set in
+the privileges structure, returning non-zero if it is.  This macro
+evaluates the _priv_ argument twice.
+</function>
+
+<function>
+void GrantPriv(struct Client* cli, int priv);
+
+This macro grants a particular client, specified by _cli_, the
+privilege specified by _priv_.  This macro evaluates the _priv_
+argument twice.
+</function>
+
+<function>
+void RevokePriv(struct Client* cli, int priv);
+
+This macro revokes the privilege specified by _priv_ from the client.
+This macro evaluates the _priv_ argument twice.
+</function>
+
+<function>
+int HasPriv(struct Client* cli, int priv);
+
+This macro tests whether the client specified by _cli_ has the
+privilege specified by _priv_, returning non-zero if so.  This macro
+evaluates the _priv_ argument twice.
+</function>
+
+<function>
+void client_set_privs(struct Client* client);
+
+The ircu configuration file does not yet support privileges.  This
+function thus sets the appropriate privileges for an operator, based
+upon various feature settings.  It should be called whenever there is
+a change in a user's IRC operator status.
+</function>
+
+<function>
+int client_report_privs(struct Client *to, struct Client *client);
+
+This function sends the client specified by _to_ a list of the
+privileges that another client has.  It returns a value of 0 for the
+convenience of other functions that must return an integer value.
+</function>
+
+<authors>
+Kev <klmitch@mit.edu>
+</authors>
+
+<changelog>
+[2001-6-15 Kev] Initial documentation of the privileges system.
+</changelog>
diff --git a/doc/api/send.txt b/doc/api/send.txt
new file mode 100644 (file)
index 0000000..ebf09e8
--- /dev/null
@@ -0,0 +1,231 @@
+The send functions are perhaps the most important API in all of ircd;
+without them, communications would not be possible.  Most of these
+functions are pretty much stand-alone, although one or two are
+intended for use in conjunction with the MsgQ interface.  The send
+functions use the MsgQ interface internally, but for the most part,
+this fact is hidden from the caller.
+
+Command tokenization provides the greatest complication.  The
+functions do use ircd_snprintf() internally, so the use of numerics
+doesn't increase that complication.  The tokenization issue is dealt
+with by making each function accept two char* pointers, _cmd_ and
+_tok_, in that order, and then defining a CMD_* macro in msg.h that
+contains the message string and the token string in that order.  When
+one of these functions is called, it determines whether the
+destination will be a server or a user, then selects the correct one,
+either _cmd_ or _tok_, for that message.
+
+The MsgQ interface provides the concept of a priority queue; messages
+which must be sent as soon as possible, regardless of what other
+messages may already be in the queue.  The sendcmdto_prio_one() and
+sendcmdto_flag_butone() functions make use of this priority queue.
+The function send_buffer() also takes a _prio_ argument that should be
+non-zero if the message passed to it should be placed in the priority
+queue.
+
+<macro>
+#define SKIP_DEAF      0x01    /* skip users that are +d */
+
+This flag may be passed to sendcmdto_channel_butone() to cause a
+message passed by that function to skip users that are +d.  See the
+documentation for sendcmdto_channel_butone() for more information.
+</macro>
+
+<macro>
+#define SKIP_BURST     0x02    /* skip users that are bursting */
+
+This is another flag that may be passed to
+sendcmdto_channel_butone().  Its purpose is to cause the server to not
+send the message across a link that is still in the "burst" stage of
+network junction.  See the documentation for
+sendcmdto_channel_butone() for more information.
+</macro>
+
+<macro>
+#define SKIP_NONOPS    0x04    /* skip users that aren't chanops */
+
+Some messages may need to be passed only to channel operators.  This
+flag is passed to sendcmdto_channel_butone() when that is the case.
+See the documentation for sendcmdto_channel_butone() for more
+information.
+</macro>
+
+<function>
+void send_buffer(struct Client* to, struct MsgBuf* buf, int prio);
+
+Some applications may need to build a message piece by piece, directly
+utilizing the MsgQ interface.  The function send_buffer() is used when
+that message has been completed to place the message on a client's
+queue.  See the documentation for the MsgQ interface for more
+information about struct MsgBuf and the _buf_ parameter.
+</function>
+
+<function>
+void flush_connections(struct Client* cptr);
+
+This function attempts to send all queued data to a client specified
+by _cptr_.  If _cptr_ is 0, all clients with non-empty send queues
+will have their queues flushed.
+</function>
+
+<function>
+void send_queued(struct Client *to);
+
+This function attempts to send all queued data to a client specified
+by _to_.  The _to_ parameter is not permitted to be 0.  This is the
+function called by flush_connections().
+</function>
+
+<function>
+void sendrawto_one(struct Client *to, const char *pattern, ...);
+
+Most of the actual send functions in this API send their data with a
+prefix--the numeric of the origin.  This function is used when a
+message should be sent _without_ that prefix.  The caller must specify
+the complete message, including the exact command, with the _pattern_
+argument and the variable argument list following it.
+</function>
+
+<function>
+void sendcmdto_one(struct Client *from, const char *cmd, const char *tok,
+                  struct Client *to, const char *pattern, ...);
+
+This function is used for sending messages to specific clients.  The
+origin of the message is specified using the _from_ parameter; this
+will be used to formulate the origin.  As mentioned above, _cmd_ and
+_tok_ are used to determine the command and token to be used.  The
+_to_ parameter specifies which client the message should be sent to.
+The origin and command will be formatted and followed by a space; the
+given _pattern_ and the following arguments are passed to
+ircd_snprintf() for formatting.
+</function>
+
+<function>
+void sendcmdto_prio_one(struct Client *from, const char *cmd, const char *tok,
+                       struct Client *to, const char *pattern, ...);
+
+This function is identical to sendcmdto_one() except that messages
+formatted using it will be placed onto the priority queue.
+</function>
+
+<function>
+void sendcmdto_serv_butone(struct Client *from, const char *cmd,
+                          const char *tok, struct Client *one,
+                          const char *pattern, ...);
+
+This function treats its arguments similar to sendcmdto_one() does.
+Messages passed created with this function are sent to all directly
+linked servers except for the _one_ passed.  If _one_ is 0, the
+message is sent to all linked servers.
+</function>
+
+<function>
+void sendcmdto_common_channels(struct Client *from, const char *cmd,
+                              const char *tok, const char *pattern, ...);
+
+When a user quits IRC, all of the other users on the channels that the
+user is on must receive a single QUIT message.  This function formats
+the message, under control of _from_ (for the origin prefix), _cmd_
+and _tok_, and _pattern_ and the variable argument list, and sends
+that message to all local users on the same channels as the user
+specified by _from_.  This function does not send any messages across
+server<->server links.
+</function>
+
+<function>
+void sendcmdto_channel_butserv(struct Client *from, const char *cmd,
+                              const char *tok, struct Channel *to,
+                              const char *pattern, ...);
+
+This function is used to send a command to every local user on a
+particular channel, specified by _to_.  No messages are sent across
+the server<->server links.
+</function>
+
+<function>
+void sendcmdto_channel_butone(struct Client *from, const char *cmd,
+                             const char *tok, struct Channel *to,
+                             struct Client *one, unsigned int skip,
+                             const char *pattern, ...);
+
+This function is used mostly for sending PRIVMSG commands to
+particular channels.  The users that receive the message are under the
+control of the _skip_ parameter, which is a binary OR of the
+SKIP_DEAF, SKIP_BURST, and SKIP_NONOPS flags, depending on what
+channel users should see the message.  This function sends messages
+across both client<->server and server<->server links, as needed.  The
+client specified by _one_ will not receive a copy of the message.
+</function>
+
+<function>
+void sendcmdto_flag_butone(struct Client *from, const char *cmd,
+                          const char *tok, struct Client *one,
+                          unsigned int flag, const char *pattern, ...);
+
+This function is used for sending messages to clients with specific
+user modes set (specified by the _flag_ parameter).  Three flags make
+sense for this function: FLAGS_WALLOP (user mode +w), FLAGS_DEBUG
+(user mode +g), and FLAGS_OPER.  FLAGS_OPER has a special meaning that
+further restricts distribution of the message only to IRC operators.
+For the purposes of this function, no distinction is made between
+global operators and local operators.
+</function>
+
+<function>
+void sendcmdto_match_butone(struct Client *from, const char *cmd,
+                           const char *tok, const char *to,
+                           struct Client *one, unsigned int who,
+                           const char *pattern, ...);
+
+Certain kinds of global messages may be sent by IRC operators.  This
+function implements those global messages.  The _to_ parameter is used
+to specify a pattern by which to filter users, while _who_ specifies
+whether that pattern is to be applied to the user's server name or to
+the user's host name.  The _who_ parameter may be one of MATCH_SERVER
+or MATCH_HOST; these two macros are defined in s_user.h.  The _one_
+parameter will not receive a copy of the message.
+</function>
+
+<function>
+void sendto_opmask_butone(struct Client *one, unsigned int mask,
+                         const char *pattern, ...);
+
+The sendto_opmask_butone() function sends a server notice to all
+subscribing users except for _one_.  The _mask_ parameter is one of
+the SNO_* values defined in client.h and is used for selection of
+subscribing users.
+</function>
+
+<function>
+void vsendto_opmask_butone(struct Client *one, unsigned int mask,
+                          const char *pattern, va_list vl);
+
+The vsendto_opmask_butone() function is identical to the
+sendto_opmask_butone() function except that instead of a variable
+argument list, it takes a va_list, specified by _vl_.
+</function>
+
+<macro>
+#define SND_EXPLICIT   0x40000000      /* first arg is a pattern to use */
+
+When this flag, defined in ircd_reply.h, is combined with the _reply_
+argument to the send_reply() function, the format string send_reply()
+uses is obtained from the first argument in the variable argument list
+passed to that function, rather than from the table of replies.
+</macro>
+
+<function>
+int send_reply(struct Client* to, int reply, ...);
+
+The send_reply() function, declared in ircd_reply.h, is used to send
+clients numeric replies.  Unless SND_EXPLICIT is used, the pattern
+will be extracted from a table of replies.
+</function>
+
+<authors>
+Kev <klmitch@mit.edu>
+</authors>
+
+<changelog>
+[2001-6-15 Kev] Initial documentation for the send functions.
+</changelog>