Browse Source

Import upstream version 0.9.2

Alexander Barton 18 years ago
commit
4736aa9617
100 changed files with 37293 additions and 0 deletions
  1. 35 0
      AUTHORS
  2. 340 0
      COPYING
  3. 632 0
      ChangeLog
  4. 186 0
      INSTALL
  5. 46 0
      Makefile.am
  6. 555 0
      Makefile.in
  7. 211 0
      NEWS
  8. 87 0
      README
  9. 1010 0
      aclocal.m4
  10. 1466 0
      config.guess
  11. 1579 0
      config.sub
  12. 10130 0
      configure
  13. 418 0
      configure.in
  14. 28 0
      contrib/Debian/Makefile.am
  15. 292 0
      contrib/Debian/Makefile.in
  16. 187 0
      contrib/Debian/changelog
  17. 1 0
      contrib/Debian/compat
  18. 47 0
      contrib/Debian/control
  19. 13 0
      contrib/Debian/copyright
  20. 75 0
      contrib/Debian/ngircd.init
  21. 14 0
      contrib/Debian/ngircd.postinst
  22. 172 0
      contrib/Debian/rules
  23. 20 0
      contrib/MacOSX/Makefile.am
  24. 283 0
      contrib/MacOSX/Makefile.in
  25. 22 0
      contrib/Makefile.am
  26. 433 0
      contrib/Makefile.in
  27. 27 0
      contrib/README
  28. 55 0
      contrib/ngircd.spec
  29. 77 0
      contrib/systrace.policy
  30. 479 0
      depcomp
  31. 56 0
      doc/CVS.txt
  32. 79 0
      doc/FAQ.txt
  33. 42 0
      doc/Makefile.am
  34. 311 0
      doc/Makefile.in
  35. 65 0
      doc/Platforms.txt
  36. 118 0
      doc/Protocol.txt
  37. 67 0
      doc/README-AUX.txt
  38. 53 0
      doc/README-BeOS.txt
  39. 33 0
      doc/RFC.txt
  40. 181 0
      doc/sample-ngircd.conf
  41. 294 0
      install-sh
  42. 22 0
      man/Makefile.am
  43. 386 0
      man/Makefile.in
  44. 80 0
      man/ngircd.8
  45. 250 0
      man/ngircd.conf.5
  46. 336 0
      missing
  47. 111 0
      mkinstalldirs
  48. 24 0
      src/Makefile.am
  49. 453 0
      src/Makefile.in
  50. 308 0
      src/config.h.in
  51. 99 0
      src/ngircd/Makefile.am
  52. 675 0
      src/ngircd/Makefile.in
  53. 896 0
      src/ngircd/channel.c
  54. 111 0
      src/ngircd/channel.h
  55. 1183 0
      src/ngircd/client.c
  56. 161 0
      src/ngircd/client.h
  57. 1075 0
      src/ngircd/conf.c
  58. 148 0
      src/ngircd/conf.h
  59. 264 0
      src/ngircd/conn-func.c
  60. 62 0
      src/ngircd/conn-func.h
  61. 210 0
      src/ngircd/conn-zip.c
  62. 38 0
      src/ngircd/conn-zip.h
  63. 1723 0
      src/ngircd/conn.c
  64. 107 0
      src/ngircd/conn.h
  65. 112 0
      src/ngircd/defines.h
  66. 125 0
      src/ngircd/hash.c
  67. 27 0
      src/ngircd/hash.h
  68. 495 0
      src/ngircd/irc-channel.c
  69. 33 0
      src/ngircd/irc-channel.h
  70. 1021 0
      src/ngircd/irc-info.c
  71. 44 0
      src/ngircd/irc-info.h
  72. 577 0
      src/ngircd/irc-login.c
  73. 32 0
      src/ngircd/irc-login.h
  74. 728 0
      src/ngircd/irc-mode.c
  75. 28 0
      src/ngircd/irc-mode.h
  76. 126 0
      src/ngircd/irc-op.c
  77. 28 0
      src/ngircd/irc-op.h
  78. 216 0
      src/ngircd/irc-oper.c
  79. 32 0
      src/ngircd/irc-oper.h
  80. 427 0
      src/ngircd/irc-server.c
  81. 29 0
      src/ngircd/irc-server.h
  82. 428 0
      src/ngircd/irc-write.c
  83. 39 0
      src/ngircd/irc-write.h
  84. 345 0
      src/ngircd/irc.c
  85. 32 0
      src/ngircd/irc.h
  86. 488 0
      src/ngircd/lists.c
  87. 46 0
      src/ngircd/lists.h
  88. 327 0
      src/ngircd/log.c
  89. 56 0
      src/ngircd/log.h
  90. 253 0
      src/ngircd/match.c
  91. 27 0
      src/ngircd/match.h
  92. 128 0
      src/ngircd/messages.h
  93. 811 0
      src/ngircd/ngircd.c
  94. 57 0
      src/ngircd/ngircd.h
  95. 456 0
      src/ngircd/parse.c
  96. 49 0
      src/ngircd/parse.h
  97. 366 0
      src/ngircd/rendezvous.c
  98. 39 0
      src/ngircd/rendezvous.h
  99. 325 0
      src/ngircd/resolve.c
  100. 0 0
      src/ngircd/resolve.h

+ 35 - 0
AUTHORS

@@ -0,0 +1,35 @@
+
+                     ngIRCd - Next Generation IRC Server
+
+                        (c)2001-2005 Alexander Barton,
+                    alex@barton.de, http://www.barton.de/
+
+               ngIRCd is free software and published under the
+                   terms of the GNU General Public License.
+
+                       -- AUTHORS and CONTRIBUTORS --
+
+
+Main Authors
+~~~~~~~~~~~~
+Alexander Barton, <alex@barton.de> (alex)
+
+
+Contributors
+~~~~~~~~~~~~
+Goetz Hoffart, <goetz@hoffart.de> (goetz)
+Ilja Osthoff, <i.osthoff@gmx.net> (ilja)
+Benjamin Pineau, <ben@zouh.org>
+Sean Reifschneider, <jafo-rpms@tummy.com>
+Florian Westphal, <westphal@foo.fh-furtwangen.de> (fw)
+
+
+Code snippets
+~~~~~~~~~~~~~
+J. Kercheval: pattern matching functions
+Patrick Powell, <papowell@astart.com>: snprintf()-function
+Andrew Tridgell & Martin Pool: strl{cpy|cat}()-functions
+
+
+-- 
+$Id: AUTHORS,v 1.11 2005/03/19 14:24:52 alex Exp $

+ 340 - 0
COPYING

@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.

+ 632 - 0
ChangeLog

@@ -0,0 +1,632 @@
+
+                     ngIRCd - Next Generation IRC Server
+
+                        (c)2001-2005 Alexander Barton,
+                    alex@barton.de, http://www.barton.de/
+
+               ngIRCd is free software and published under the
+                   terms of the GNU General Public License.
+
+                               -- ChangeLog --
+
+
+ngIRCd 0.9.2 (2005-10-15)
+
+  - Fixed a bug that could cause the damon to crash when outgoing server
+    connections can't be established.
+  - Fixed a bug that caused the daemon to leak file descriptors when no
+    resolver subprocesses could be created.
+  - Fixed server NOTICEs to users with "s" mode ("server messages").
+  - Fixed a format string bug in "connection statistics" messages to clients.
+
+ngIRCd 0.9.1 (2005-08-03)
+
+  - The KILL command killed much more than desired (including server links!)
+    when the target user is connected to a remote server. Bug introduced in
+    ngIRCd 0.9.0 ...  Reported by <qssl@fastmail.fm>, Thanks!
+  - Changed some constants to be "signed" (instead of unsigned) to solve
+    problems with old (pre-ANSI) compilers.
+
+ngIRCd 0.9.0 (2005-07-24)
+
+  ngIRCd 0.9.0-pre1 (2005-07-09)
+  - Fixed maximum length of user names, now allow up to 9 characters.
+  - Cut off oversized IRC messages that should be sent to the network instead
+    of shuttding down the (wrong) connection.
+  - Don't generate error messages for unknown commands received before the
+    client is registered with the server (like the original ircd).
+  - Never run with root privileges but always switch the user ID.
+  - Make "netsplit" messages RFC compliant.
+  - Fix handling of QUIT Messages: send only one message, even if the client
+    is member of multiple channels.
+  - Don't exit server if closing of a socket fails; instead ignore it and
+    pray that this will be "the right thing" ...
+  - Implemented the IRC function "WHOWAS".
+  - Don't enable assert() calls when not ./configure'd with --enable-debug.
+  - Fixed ./configure test for TCP Wrappers: now it runs on Mac OS X as well.
+  - Enhanced configure script: now you can pass an (optional) search path
+    to all --with-XXX parameters, e. g. "--with-ident=/opt/ident".
+  - Removed typedefs for the native C datatypes.
+    Use stdbool.h / inttypes.h if available.
+  - New configuration option "OperServerMode" to enable a workaround needed
+    when running an network with ircd2 servers and "OperCanUseMode" enabled
+    to prevent the ircd2 daemon to drop mode changes of IRC operators.
+    Patch by Florian Westphal, <westphal@foo.fh-furtwangen.de>.
+  - Implemented support for "secret channels" (channel mode "s").
+  - New configuration option "Mask" for [Operator] sections to limit OPER
+    commands to users with a specific IRC mask. Patch from Florian Westphal.
+  - Write "error file" (/tmp/ngircd-XXX.err) only if compiled with debug
+    code ("--enable-debug") and running as daemon process.
+  - Don't create version information string each time a client connects
+    but instead on server startup. By Florian Westphal.
+  - New configuration variable "PidFile", section "[Global]": if defined,
+    the server writes its process ID (PID) to this file. Default: off.
+    Idea of Florian Westphal, <westphal@foo.fh-furtwangen.de>.
+  - Code cleanups from Florian Westphal, <westphal@foo.fh-furtwangen.de>.
+  - Raised the maximum length of passwords to 20 characters.
+  - Fixed a memory leak when resizing the connection pool and realloc()
+    failed. Now we don't fall back to malloc(), which should be sane anyway.
+    Patch from Florian Westphal, <westphal@foo.fh-furtwangen.de>.
+  - Added support for the Howl (http://www.porchdogsoft.com/products/howl/)
+    Rendezvous API, in addition to the API of Apple (Mac OS X). The available
+    API will be autodetected when you call "./configure --with-rendezvous".
+  - Made ngIRCd compile on HP/UX 10.20 with native HP pre-ANSI C compiler and
+    most probably other older C compilers on other systems.
+  - When the daemon should switch to another user ID (ServerID is defined in
+    the configuration file) and is not running in a chroot environment, it
+    changes its working directory to the home directory of this user. This
+    should enable the system to write proper core files when not running with
+    root privileges ...
+
+ngIRCd 0.8.3 (2005-02-03)
+
+  - Fixed a bug that could case a root exploit when the daemon is compiled
+    to do IDENT lookups and is logging to syslog. Bug discovered by CoKi,
+    <coki@nosystem.com.ar>, thanks a lot!
+    (http://www.nosystem.com.ar/advisories/advisory-11.txt)
+
+ngIRCd 0.8.2 (2005-01-26)
+
+  - Added doc/SSL.txt to distribution.
+  - Fixed a buffer overflow that could cause the daemon to crash. Bug found
+    by Florian Westphal, <westphal@foo.fh-furtwangen.de>.
+  - Fixed a possible buffer underrun when reading the MOTD file. Thanks
+    to Florian Westphal, <westphal@foo.fh-furtwangen.de>.
+  - Fixed detection of IRC lines which are too long to send. Detected by
+    Florian Westphal, <westphal@foo.fh-furtwangen.de>.
+  - Fixed return values of our own implementation of strlcpy(). The code has
+    been taken from rsync and they fixed it, but we didn't until today :-/
+    It has only been used when the system didn't implement strlcpy by itself,
+    not on "modern" systems. Florian Westphal, <westphal@foo.fh-furtwangen.de>.
+
+ngIRCd 0.8.1 (2004-12-25)
+
+  - Autoconf: Updated config.guess and config.sub
+  - Added some more debug code ...
+  - Fixed wrong variable names in output of "ngircd --configtest".
+  - Debian: Fixed the name of the "default file" in the init script for
+    ngircd-full packages. And do the test if the binary is executable after
+    reading this file.
+  - Enhanced the "test suite": please have a look at src/testsuite/README!
+
+ngIRCd 0.8.0 (2004-06-26)
+
+  - Fixed wrong buffer size calculation for results of the resolver.
+
+  ngircd 0.8.0-pre2 (2004-05-16)
+  - Enhanced logging to console when running in "no-detached mode": added
+    PID and log messages of resolver sub-processes.
+  - Fixed host name lookups when using IDENT user lookups.
+  - "make clean" and "make maintainer-clean" remove more files now.
+
+  ngIRCd 0.8.0-pre1 (2004-05-07)
+  - Two new configuration options: "ChrootDir" and "MotdPhrase", thanks to
+    Benjamin Pineau <ben@zouh.org>. Now you can force the daemon to change
+    its root and working directory to something "safe". MotdPhrase is used
+    to define an "MOTD string" instead of a whole file, useful if the
+    "real" MOTD file would be outside the "jail".
+  - INVITE- and BAN-lists become synchronized between IRC+ servers when
+    establishing new connections, if the peer supports this as well.
+  - Reorganized autogen.sh and configure scripts.
+  - Fixed a wrong assert() which could cause the daemon to exit spuriously
+    when closing down connections.
+  - Better logging of decompression errors returned by zlib.
+  - Servers other than the destination server didn't clean up the invite
+    list of an "invite-only" channel properly when an INVITE'd user joined.
+  - Changed the reply of the MODE command to match the syntax of the
+    original ircd exactly: the unnecessary but missing ":" before the last
+    parameter has been added.
+  - Fixed TRACE: don't output "Serv" lines for ourself; display more info.
+  - Results of the resolver (hostnames and IDENT names) are discarded after
+    the client is successfully registered with the server.
+  - Better logging while establishing and shutting down connections.
+  - The type of service (TOS) of all sockets is set to "interactive" now.
+  - Added short command line option "-t" as alternative to "--configtest".
+  - Added optional support for "IDENT" lookups on incoming connections. You
+    have to enable this function with the ./configure switch "--with-ident".
+    The default is not to do IDENT lookups.
+
+ngIRCd 0.7.7 (2004-02-05)
+
+  - The info text ("real name") of users is set to "-" if none has been
+    specified using the USER command (e. g. "USER user * * :"). Reason:
+    the original ircd doesn't like empty ones and would KILL such users.
+  - Fixed (optional) TCP Wrapper test which was broken and could result in
+    false results. Thanks to Fuminori Tanizaki <tany@mcnet.ad.jp>!
+  - Removed "USE_" prefixes of configuration #defines.
+
+ngIRCd 0.7.6 (2003-12-05)
+
+  - Fixed abort() ("server crash") when INVITE'ing users to nonexistent
+    channels. Bug found by <hiddenx@wp.pl>.
+  - Extended version numbering of CVS versions (added date).
+  - Enhanced/fixed doc/Protocol.txt;
+
+ngIRCd 0.7.5 (2003-11-07)
+
+  - Fixed ban behavior: users which are banned from a channel can't no
+    longer send PRIVMSG's to this channel (fixes Bug #47).
+  - Fixed and enhanced the "penalty handling" of the server: commands that
+    require more resources block the client for a short time.
+  - Changed the internal time resolution to one second.
+  - New configuration variable "MaxConnectionsIP" to limit the number of
+    simultaneous connections from a single IP that the server will accept.
+    This configuration options lowers the risk of denial of service attacks
+    (DoS), the default is 5 connections per client IP.
+  - Fixed build problems under Mac OS X 10.3.
+  - Use "-pipe" when compiling with gcc, speeds things up a little :-)
+  - Added new configuration variable "Listen" to bind all listening
+    sockets of the server to a single IP address.
+  - Suppress misleading error message of diff during make run.
+  - Enhanced test-suite and made it work on GNU/Hurd.
+  - Fixed minor typo in debug output :-)
+
+ngIRCd 0.7.1 (2003-07-18)
+
+  - Included files to build Debian packages (located in "debian/").
+  - Updated config.guess and config.sub to newer upstream versions.
+  - NJOIN propagates user channel modes correctly again ... Upsa.
+  - Made Makefile more compatible with "make -j<n>".
+  - Added support for GNU/Hurd.
+  - Fixed a compiler warning related to an unnecessary assert().
+  - Enhanced VERSION command when using debug versions.
+
+ngIRCd 0.7.0 (2003-05-01)
+
+  - "ServerName" is checked better now: a dot (".") is required.
+  - The KILL command verifies and logs more parameters.
+
+  ngIRCd 0.7.0-pre2 (2003-04-27)
+  - CVS build system fixes (made autogen.sh more portable).
+  - Fixed compilation and test-suite on Solaris (tested with 2.6).
+  - New documentation file "doc/Platforms.txt" describing the status of
+    ngIRCd on the various tested platforms.
+  - Test for broken GCC on Mac OS X and disable "-pedantic" in this case.
+  - Disable "-ansi" on Cygwin: system headers are incompatible.
+  - The server tried to connect to other servers only once when DNS or
+    socket failures occurred.
+  - Fixed --configtest: There is no variable "ServerPwd", it's "Password".
+
+  ngIRCd 0.7.0-pre1 (2003-04-22)
+  - New signal handler (more secure, actions are executed outside).
+  - GCC: the compiler is now called with more warning options enabled.
+  - Replaced a lot of str[n]cpy(), str[n]cat() and sprintf() calls with the
+    more secure functions strlcpy(), strlcat() and snprintf(). On systems
+    that don't support strlcpy() and strlcat(), these functions are included
+    in the libngportab now (with prototypes in portab.h).
+  - If the server can't close a socket, it panics now. This is an error that
+    can't occur during normal operation so there is something broken.
+  - The order of log messages during disconnects is more "natural" now ;-)
+  - Cleaned up handling of server configuration structures: modifying and
+    removing servers during runtime works more reliable now.
+  - Compression code from "conn.[ch]" is now found in new "conn-zip.[ch]"
+  - Moved some connection functions from "conn.[ch]" to "conn-func.[ch]".
+  - New command CONNECT to enable and add server links. The syntax is not
+    RFC-compatible: use "CONNECT <name> <port>" to enable and connect an
+    configured server and "CONNECT <name> <port> <host> <mypwd> <peerpwd>"
+    to add a new server (ngIRCd tries to connect new servers only once!).
+  - Added DISCONNECT command ("DISCONNECT <name>") to disable servers.
+  - Restructured the documentation: Now the main language is English. The
+    german documentation has been removed (until there is a maintainer).
+  - Enhanced killing of users caused by a nickname collision.
+  - Better error detection for status code ("numerics") forwarding.
+  - Moved tool functions to own library: "libngtool".
+  - New command TRACE (you can trace only servers at the moment).
+  - New command HELP that lists all understood commands.
+  - There should no longer remain "unknown connections" (see e.g. LUSERS)
+    if an outgoing server link can't be established.
+  - Added AC_PREREQ(2.50) to configure.in for better autoconf compatibility.
+  - Conn_Close() now handles recursive calls for the same link correctly.
+  - ngIRCd can register itself with Rendezvous: to enable support pass the
+    new switch "--with-rendezvous" to configure.
+  - Added support for TCP Wrappers library: pass "--with-tcp-wrappers" to
+    configure to enable it.
+  - Changed some configure options to use "--with"/"--without" as prefix
+    instead of "--enable"/"--disable": "--without-syslog", "--without-zlib",
+    "--with-tcp-wrappers", and "--with-rendezvous".
+  - Better error reporting to clients on connect.
+  - Enhanced manual pages ngircd(8) and ngircd.conf(5).
+  - Documentation is now installed in $(datadir)/doc/ngircd.
+  - Enhanced hanling of NJOIN in case of nick collisions.
+
+ngIRCd 0.6.1, 2003-01-21
+
+  - Fixed KILL: you can't crash the server by killing yourself any more,
+    ngIRCd no longer sends a QUIT to other servers after the KILL, and you
+    can kill only valid users now.
+  - The server no longer forwards commands to ordinary users, instead it
+    answers with the correct error message ("no such server") now.
+  - WHOIS commands weren't always forwarded as requested.
+  - The server sets a correct default AWAY message now when propagating
+    between servers (bug introduced in 0.6.0).
+  - Fixed up and enhanced CHANINFO command: channel keys and user limits
+    are synchronized between servers now, too.
+  - MODE returns the key and user limit for channel members correctly now.
+  - Non-members of a channel could crash the server when trying to change
+    its modes or modes of its members.
+  - The server didn't validate weather a target user is a valid channel
+    member when changing his channel user modes which could crash ngIRCd.
+
+
+Older changes (sorry, only available in german language):
+
+ngIRCd 0.6.0, 2002-12-24
+
+  ngIRCd 0.6.0-pre2, 2002-12-23
+  - neuer Numeric 005 ("Features") beim Connect.
+  - LUSERS erweitert: nun wird die maximale Anzahl der lokalen und globalen
+    Clients, die dem Server bzw. im Netzwerk seit dem letzten (Re-)Start
+    dem Server gleichzeitig bekannt waren, angezeigt.
+
+  ngIRCd 0.6.0-pre1, 2002-12-18
+  - beim Schliessen einer Verbindung zeigt der Server nun vor dem ERROR
+    noch eine Statistik ueber die empfangene und gesendete Datenmenge an.
+  - der Server wartet bei einer eingehenden Verbindung nun laenger auf den
+    Resolver (4 Sekunden), wenn das Ergebnis eintrifft setzt er aber den
+    Login sofort fort (bisher wurde immer mind. 1 Sekunde gewartet).
+  - Connection-Strukturen werden nun "pool-weise" verwaltet; der Pool wird
+    bei Bedarf bis zu einem konfigurierten Limit vergroessert.
+  - Mit der neuen Konfigurationsvariable "MaxConnections" (Sektion "Global")
+    kann die maximale Anzahl gleichzeitiger Verbindungen begrenzt werden.
+    Der Default ist -1, "unlimitiert".
+  - der Server erkennt nun, ob bereits eine eingehende Verbindung von einem
+    Peer-Server besteht und versucht dann nicht mehr, selber eine eigene
+    ausgehende Verbindung zu diesem auufzubauen. Dadurch kann nun auf beiden
+    Servern in der Konfiguration ein Port fuer den Connect konfiguriert
+    werden (beide Server versuchen sich dann gegenseitig zu connectieren).
+  - Test-Suite und Dokumentation an A/UX angepasst.
+  - unter HP-UX definiert das configure-Script nun _XOPEN_SOURCE_EXTENDED.
+  - Server identifizieren sich nun mit asyncronen Passwoertern, d.h. das
+    Passwort, welches A an B schickt, kann ein anderes sein als das, welches
+    B als Antwort an A sendet. In der Konfig.-Datei, Abschnitt "Server",
+    wurde "Password" dazu durch "MyPassword" und "PeerPassword" ersetzt.
+  - Der Server kann nun zur Laufzeit die Konfiguration neu einlesen: dies
+    macht er nach dem Befehl REHASH oder wenn ein HUP-Signal empfangen wird.
+  - Channel-Mode "P" ("persistent") kann nur noch von IRC-Operatoren gesetzt
+    werden. Grund: User koennen den Server sonst leicht "Channel-Flooden".
+  - MOTD kann nun an andere Server geforwarded werden.
+  - IRC-Befehl "TIME" implementiert.
+  - Server-Server-Links koennen nun komprimiert werden, dazu wird die zlib
+    (www.zlib.org) benoetigt. Unterstuetzt die Gegenseite die Komprimierung
+    nicht, wird automatisch unkomprimiert kommuniziert. Das Verfahren ist
+    kompatibel mit dem Original-ircd 2.10.3, d.h. beide Server koennen
+    miteinander ueber komprimiert Links kommunizieren.
+  - Handling der Schreibpuffer umgestellt: Server sollte schneller arbeiten.
+  - Prefix-Fehler werden besser protokolliert (mit verursachendem Befehl).
+  - SQUIT wird nicht mehr doppelt an andere Server weitergeleitet.
+  - Der Server versucht nun vor dem Schliessen einer Verbindung Daten, die
+    noch im Schreibpuffer stehen, zu senden.
+  - Source in weiteres Modul "irc-info" aufgespalten.
+  - Konfigurationsvariablen werden besser validiert: Laengen, Zahlen, ...
+  - neuen Befehl STATS begonnen: bisher unterstuetzt wird "l" und "m".
+  - bei ISON und USERHOST fehlte im Ergebnis-String der korrekte Absender.
+  - IRC Operatoren koennen nun mit KILL User toeten. Achtung: ein Grund muss
+    zwingend als zweiter Parameter angegeben werden!
+  - neue Konfigurations-Variable "MaxJoins": Hiermit kann die maximale Zahl
+    der Channels, in denen ein User Mitglied sein kann, begrent werden.
+  - neuer, deutlich flexiblerer Parser fuer den MODE Befehl.
+  - neue Channel-Modes l (User-Limit) und k (Channel-Key) implementiert.
+
+ngIRCd 0.5.4, 24.11.2002
+
+  - Fehler-Handling von connect() gefixed: der Server kann sich nun auch   
+    unter A/UX wieder zu anderen verbinden.
+  - in den Konfigurationsvariablen ServerUID und ServerGID kann nun nicht
+    nur die numerische ID, sondern auch der Name des Users bzw. der Gruppe
+    verwendet werden. Beim Start des Daemons wird nun beides angezeigt.
+  - Besseres Logging von Prefix-Fehlern.
+  - angenommene Sockets werden nun korrekt auf "non-blocking" konfiguriert,
+    beim Senden und Empfangen werden Blockierungen besser abgefangen.
+  - RPL_UMODEIS hat Code 221, nicht 211 ... *argl*
+  - select() in Try_Write() hat falschen (keinen!) Timeout verwendet;
+    die "Zeit-Aufloesung" des Servers sind zudem nun 2 Sekunden (TIME_RES).
+    Insgesamt sollte die Reaktionszeit des Server nun besser sein.
+
+ngIRCd 0.5.3, 08.11.2002
+
+  - NOTICE liefert nun wirklich nie mehr einen Fehler, auch dann nicht,
+    wenn der sendende Client noch gar nicht registriert ist.
+  - ein "schneller Server-Reconnect" wird nur noch dann versucht, wenn die
+    Verbindung zuvor ordentlich (="lange genug") in Ordnung war; somit also
+    nicht meht, wenn der Peer-Server gleich beim Connect ein ERROR liefert.
+    Das vermeidet "Connect-Orgien".
+  - einige Datentypen aufgeraumt: z.B. sind viele INT32s nun LONGs. Das ist
+    auf Platformen mit 8-Byte-Integern kompatibler.
+  - RPL_YOURHOST_MSG ist nun ircII- und RFC-kompatibel ;-)
+  - Segfault unter hoher Netzaktivitaet behoben: in Conn_Close() wird die
+    Connection-Struktur nun frueher als "ungueltig" markiert.
+
+ngIRCd 0.5.2, 04.10.2002
+
+  - Buffer Overflow in Read_Resolver_Result() behoben.
+  - Format-String-Bugs, die zum Abbruch des Servers fuehrten, behoben.
+  - Maximale Laenge eines IRC-Prefix wurde falsch berechnet.
+
+ngIRCd 0.5.1, 03.10.2002
+
+  - in RPL_YOURHOST_MSG wurde ein fehlerhafter Versionsstring geliefert.
+  - Test-Suite: start-server.sh, stop-server.sh und stress-server.sh koennen
+    nun "manuell" von der Kommandozeile gestartet werden, stress-server.sh
+    startet per Default nur noch 5 Sessions, eine andere Zahl kann auf der
+    Kommandozeile uebergeben werden (Syntax: "stress-server.sh <count>").
+  - In bestimmten Faellen hat der Server versucht auf einen bereits wieder
+    geschlossenen Socket Daten zu schreiben; das fuehrte zu einem Abbruch des
+    Servers durch ein assert(). Nun wird geprueft, ob der Socket noch ok ist.
+  - im "contrib"-Verzeichnis befindet sich nun eine RPM-Spec-Datei, aus den
+    .tar.gz's koennen nun mit "rpm -ta <archiv>" RPM's erzeugt werden. Danke
+    an Sean Reifschneider <jafo@tummy.com>!
+  - Syntax von RPL_MYINFO_MSG korrigiert: liefert nun vier Parameter.
+
+ngIRCd 0.5.0, 20.09.2002
+
+  - Dokumentation aktualisiert.
+  - Fehler bei Validierung von "AdminInfo2" behoben.
+  - Test der Flags fuer "ps" in der Testsuite verbessert, ist nun zu mehr
+    Plattformen kompatibler.
+
+  ngIRCd 0.5.0-pre2, 17.09.2002
+  - Fix in IRC_WriteStrServersPrefix() war "badly broken" -- behoben.
+
+  ngIRCd 0.5.0-pre1, 16.09.2002
+  - Manual-Pages ngircd.8 und ngircd.conf.5 begonnen.
+  - Wird der Netzwerk-Sniffer aktiviert (--sniffer), so schaltet der
+    ngIRCd nun automatisch in den Debug-Modus.
+  - auf Systemen, die inet_aton() nicht kennen (wie z.B. A/UX), kann der
+    ngIRCd nun dennoch auch aktiv Server-Links aufbauen.
+  - h_errno wird auf Systemen, die das nicht kennen (wie z.B. HP-UX 10.20)
+    nicht mehr verwendet. Somit compiliert der ngIRCd nun auch dort :-)
+  - um auf dem Ziel-System nicht vorhandene Funktionen nachzubilden wird nun
+    die "libngportab" erzeugt; genutzt wird dies bisher fuer vsnprintf().
+    Nun compiliert der ngIRCd auch unter Solaris 2.5.1.
+  - "persistente Channels" (Mode 'P') implementiert: diese koennen in der
+    Konfigurationsdatei definiert werden (Sektion "Channel", vgl. Beispiel-
+    Konfiguration "sample-ngircd.conf") und bleiben auch dann bestehen,
+    wenn kein User mehr im Channel ist. Zu Channel-Operatoren werden bisher
+    nur IRC-Operatoren, die den Channel betreten. Die persistenten Channels
+    werden durch das Flag "P" gelennzeichnet, welches normal durch Channel-
+    Op's gesetzt und geloescht werden kann.
+  - bei "--configtest" werden keine leere Abschnitte mehr ausgegeben.
+  - Source in weitere Module aufgespalten: lists, irc-op und resolve.
+  - #include's aufgeraeumt: Header includieren keine anderen mehr.
+  - KICK implementiert (bisher kann nur ein User aus einem Channel geckicked
+    werden, Listen, wir im RFC vorgesehen, werden bisher nicht unterstuetzt).
+  - INVITE, den Channel-Mode "i" sowie Invite-Lists ueber den MODE-Befehl
+    (setzen, erfragen und loeschen) implementiert.
+  - Source an ansi2knr fuer pre-ANSI-Compiler angepasst; ansi2knr in Source-
+    Tree aufgenommen und in Build-System integriert; der ngIRCd compiliert
+    nun z.B. unter A/UX mit dem nativen Compiler von Apple.
+  - TOPIC lieferte bei unbekanntem Channel einen falschen Fehlercode.
+  - LIST versteht nun Wildcards und kann an andere Server geforwarded werden.
+  - wurde ein KILL fuer nicht-lokale Clients empfangen, so wurden die
+    Verwaltungs-Strukturen nicht korrekt freigegeben.
+  - empfangene NJOIN's wurden "zerhackt" an andere Server weitergegeben.
+  - neue Konfigurationsoption "OperCanUseMode" (Sektion "Global"):
+    ist sie aktiv, koennen IRC-Operatoren immer Channel-Modes setzen.
+  - Dokumentation des neuen IRC+-Protokolls begonnen: doc/Protocol.txt
+  - Protokoll- und Server-ID bei PASS-Befehlen auf neues Format umgestellt;
+    bei empfangenen PASS-Befehlen werden diese zudem nun auch ausgewertet.
+    Die unterstuetzten Flags sind in doc/Protocol.txt beschrieben.
+  - mit dem neuen Befehl CHANINFO syncronisieren Server, die das IRC+-
+    Protokoll unterstuetzen, Channel-Modes und Topics.
+  - neue Option "--disable-ircplus" fuer das configure-Script, um das
+    IRC+-Protokoll abzuschalten (per Default ist es aktiviert).
+  - Ban-Lists (setzen, erfragen und loeschen) implementiert.
+  - wird der Server mit "-n"/"--nodaemon" gestartet, so werden keine Mel-
+    dungen mehr ueber Syslog ausgegeben, sondern nur noch auf der Konsole.
+  - "Test-Suite" begonnen (in "make check" integriert): Dabei wird ein
+    speziell konfigurierter Server auf Port 6789 gestartet, mit dem dann
+    einige Tests durchgefuehrt werden (u.a. "Stress-Test" mit 50 Clients).
+  - zu lange Operator-Namen in der Konfiguration wurden falsch gekuerzt.
+  - kleine Anpassung an AIX 3.2.5: nun laeuft der ngIRCd auch dort :-)
+  - ADMIN-Befehl implementiert. Die Daten hierzu werden in der Konfig-Datei
+    im [Global]-Abschnitt mit den Variablen "AdminInfo1", "AdminInfo2" und
+    "AdminEMail" konfiguriert.
+  
+ngIRCd 0.4.3, 11.06.2002
+
+  - Bei PRIVMSG und NOTICE hat der ngIRCd nicht ueberpruft, ob das Ziel
+    ueberhaupt ein User ist. War es keiner, so fuehrte dies zu einem
+    Abbruch des Servers [es wurde assert() aufgerufen].
+
+ngIRCd 0.4.2, 29.04.2002
+
+  - LUSERS verzaehlt sich bei eigenen Server-Links nicht mehr.
+  - QUIT wird nun auch von noch nicht registrierten Clients akzeptiert.
+  - IRC-Funktion LIST implementiert; bisher werden allerdings noch keine
+    Wildcards (bis auf "*") unterstuetzt.
+
+ngIRCd 0.4.1, 08.04.2002
+
+  - Bei Server-Links wird nicht mehr an Hand der Anzahl der Parameter
+    eines empfangenen SERVER-Befehls, sondern "intern" erkannt, ob es
+    sich um eine ein- oder ausgehende Verbindung handelt und somit das
+    eigene PASS-SERVER-Paar gesendet werden muss oder nicht. Da sich
+    verschiedene Versionen des Original-ircd's anders verhalten, schlug
+    die Anmeldung je nach Gehenseite evtl. fehl.
+  - Bei einem NICK-Befehl eines lokalen Client konnte der Server ab-
+    stuerzen, da ein Format-String einer Log-Meldung fehlerhaft war.
+
+ngIRCd 0.4.0, 01.04.2002
+
+  - IRC-Befehle nochmal auf weitere Source-Dateien aufgespalten.
+  - WHO implementiert (bisher ohne komplette Unterstuetzung von Masks).
+  - Der AWAY-Mode wurde nicht ueber mehrere Server-Links weitergegeben.
+  - stderr wird nun in eine Datei umgelenkt (/tmp/ngircd-<PID>.err).
+    Laeuft der Server nicht im Debug-Modus, so wird diese bei Programm-
+    ende geloescht. Sollte der Server abstuerzen, finden sich hier evtl.
+    zusaetzliche Informationen.
+  - In Nicknames wird das Zeichen "-" nun als zulaessig erkannt.
+  - die Beispiel-Konfigurationsdatei (doc/sample-ngircd.conf) wird als
+    ngircd.conf installiert, wenn noch keine "echte" Konfigurationsdatei
+    vorhanden ist.
+  - bei WHO, WHOIS und NAMES wird nun nur noch der Status "Operator" oder
+    "voiced" geliefert -- nicht mehr beides.
+  - Server-Gruppen implementiert: es wird immer nur zu einem Server in
+    einer Gruppe eine Verbindung aufgebaut, klappt es beim ersten Server
+    nicht, so wird der naechste probiert (Variable "Group" in der Kon-
+    figurationsdatei, Sektion [Server]).
+  - IRC_PING() ist, wenn nicht im "strict RFC"-Mode, toleranter und ak-
+    zeptiert beliebig viele Parameter (z.B. BitchX sendet soetwas).
+  - die "Portab-Header" werden nicht mehr benoetigt, die System-Erkennung
+    wird nun ausschliesslich vom configure-Script durchgefuehrt. System-
+    abhaengige Definitionen finden sich nun unter src/portrab/.
+  - Clients und Channels werden nicht mehr ueber ihren Namen, sondern
+    einen Hash-Wert gesucht: sollte deutlich schneller sein.
+  - neuer Kommandozeilen-Parameter "--configtest": die Konfiguration wird
+    gelesen und dann die verwendeten Werte angezeigt.
+  - Client-Mode "s" (Server Notices) implementiert.
+  - mit dem neuen Kommandozeilen-Parameter "--config"/"-f" kann eine
+    alternative Konfigurationsdatei angegeben werden.
+  - nach dem Start kann der ngIRCd, wenn er mit root-Rechten laeuft,
+    zu einer anderen User-ID und Group-ID wechseln.
+  - URL der Homepage wird u.a. bei "--version" mit angezeigt.
+
+ngIRCd 0.3.0, 02.03.2002
+
+  - bekommt der Server ein HUP-Signal, so startet er neu -- genau so, wie
+    er auf den IRC-Befehl RESTART reagiert.
+  - FAQ um Hinweise auf den Bugtracker erweitert.
+  - neuer Kommandozeilen-Schalter "--passive" (-p): wird er angegeben, so
+    verbindet sich der ngIRCd nicht mehr automatisch zu anderen Servern.
+    Zum Debuggen manchmal ganz praktisch :-)
+  - direkt nach dem Start schreibt der ngIRCd nun die aktiven Kommando-
+    zeilenschalter in's Logfile (Passive, Debug, Sniffer ...).
+  - das Signal-Flag SA_RESTART wird nur noch gesetzt, wenn es auf dem
+    jeweiligen System auch definiert ist.
+  - bei ausgehenden Verbindungen wird nun der Ziel-Port protokolliert.
+  - neue Befehle VERSION und KILL implementiert.
+  - make-Target "check" (und "distcheck") mit Sinn erfuellt :-)
+    (die Tests sind aber bisher nicht all zu tiefgehend ...)
+  - Durch einen Ueberlauf konnte die Idle-Time bei WHOIS negativ werden ...
+  - Anpassungen an A/UX: gehoert nun auch zu den unterstuetzten Platformen.
+  - WHOIS wird nicht mehr automatisch an den "Original-Server" weiterge-
+    leitet: war eh nicht RFC-konform und machte mit Clients Probleme.
+  - an User wird nun immer ein "komplettes" Prefix (mit Host-Mask) ver-
+    schickt, Server bekommen nach wie vor kurze: das "Original" hat bei
+    bestimmten Befehlen (PRIVMSG) ansonsten evtl. Probleme ...
+  - NAMES korrigiert und vollstaendig implementiert.
+  - SQUIT wird auf jeden Fall geforwarded, zudem besseres Logging.
+  - Ist ein Nick bei der User-Registrierung bereits belegt, nimmt der
+    Server nun korrekt weitere NICK-Befehle an und verwendet diese.
+  - PRIVMSG beachtet nun die Channel-Modes "n" und "m".
+  - AWAY implementiert. PRIVMSG, MODE, USERHOST und WHOIS angepasst.
+  - der ngIRCd unterstuetzt nun Channel-Topics (TOPIC-Befehl).
+  - ausgehende Server-Verbindungen werden nun asyncron connectiert und
+    blockieren nicht mehr den ganzen Server, wenn die Gegenseite nicht
+    erreicht werden kann (bis zum Timeout konnten Minuten vergehen!).
+  - Wert der Konfigurations-Variable "ConnectRetry" wird besser beachtet.
+  - Channel- und Nicknames werden nun ordentlich validiert.
+
+ngIRCd 0.2.1, 17.02.2002
+
+  - NICK korrigiert: es werden nun auch alle "betroffenen" User informiert.
+  - configure-Script erweitert, u.a. bessere Anpassung an BeOS: dort wird
+    nun die "libbe" zum ngIRCd gelinkt, somit funktioniert auch syslog.
+  - Fehlerhafte bzw. noch nicht verstandene Modes werden nun ausfuehrlicher
+    an den Client geliefert.
+
+ngIRCd 0.2.0, 15.02.2002
+
+  - Nicknames und Channel-Namen werden etwas besser auf Gueltigkeit ueber-
+    prueft; ist aber nach wie vor noch nicht ausreichend.
+  - NJOINS von Servern wurden nicht an andere Server weitergeleitet.
+  - Begonnen Channel-Modes und User-Channel-Modes zu implementieren: der
+    Server versteht an User-Modes o und v, beachtet letzteres allerdings
+    noch nirgends. Bekannte (aber nicht beachtete!) Channel-Modes sind
+    bisher a, m, n, p, q, s und t. Diese Modes werden von Usern ange-
+    nommen, von anderen Servern werden auch unbekannte Modes uebernommen.
+  - Benutzer von connectierenden Servern wurden nicht in den Channels ange-
+    kuendigt, es wurden nur die internen Strukturen angepasst.
+  - Nach dem Connect eines Users werden LUSERS-Informationen angezeigt.
+
+ngIRCd 0.1.0, 29.01.2002
+
+  - User-Modes bei User-Registrierungen von andere Servern (NICK-Befehl)
+    wurden falsch uebernommen. Zudem wurden die Modes falsch gekuerzt.
+  - Server-Verbindungen werden nun nach dem Start erst nach einer kurzen
+    Pause aufgebaut (zur Zeit drei Sekunden).
+  - Hilfetext korrigiert: --help und --version waren vertauscht, die
+    Option --sniffer wurde gar nicht erwaehnt.
+  - FAQ.txt in doc/ begonnen.
+  - der IRC-Sniffer wird nur noch aktiviert, wenn die Option auf der
+    Kommandozeile angegeben wurde (bei entsprechend compiliertem Server).
+  - Channels implementiert, bisher jedoch noch ohne Channel-Modes, d.h.
+    es gibt keine Channel-Ops, kein Topic, kein "topic lock" etc. pp.
+    Chatten in Channels ist aber natuerlich moeglich ;-)
+  - neue Befehle fuer Channles: JOIN, PART und NJOIN.
+  - durch die Channels einige Aenderungen an PRIVMSG, WHOIS, MODE etc.
+  - neu connectierenden Servern werden nun Channels mit NJOIN angekuendigt.
+  - Signal-Hander geaendert: die Fehlermeldung "interrupted system call"
+    sollte so nicht mehr auftreten.
+  - "spaeter" neu connectierende Server werden nun im Netz angekuendigt.
+  - SERVER-Meldungen an andere Server sind nun korrekt sortiert.
+  - Clients werden nun korrekt sowohl nur ueber den Nickname als auch die
+    komplette "Host Mask" erkannt.
+
+ngIRCd 0.0.3, 16.01.2002
+
+  - Server-Links vollstaendig implementiert: der ngIRCd kann nun auch
+    "Sub-Server" haben, also sowohl als Leaf-Node als auch Hub in einem
+    IRC-Netzwerk arbeiten.
+  - MODE und NICK melden nun die Aenderungen an andere Server, ebenso
+    die Befehle QUIT und SQUIT.
+  - WHOIS wird nun immer an den "Original-Server" weitergeleitet.
+  - Parses handhabt Leerzeichen zw. Parametern nun etwas "lockerer".
+  - Status-Codes an den Server selber werden ignorier.
+  - Log-Meldungen und Log-Level ueberarbeitet und korrigiert.
+  - Kommandozeilen-Parser: Debug- und No-Daemon-Modus, Hilfe.
+  - ngIRCd wandelt sich nun in einen Daemon (Hintergrundprozess) um.
+  - WHOIS korrigiert: Anfrage wurde u.U. an User geforwarded anstatt vom
+    Server beantwortet zu werden.
+  - neue Befehle: LUSERS, LINKS
+  - Client-Modes von Remote-Servern wurden nicht korrekt uerbernommen.
+
+ngIRCd 0.0.2, 06.01.2002
+
+  - Struktur der Konfigurationsdatei geaendert: sie ist nun "Samba like",
+    d.h. sie besteht aus Abschnitten (siehe "doc/sample-ngircd.conf").
+  - Es koennen mehrere IRC-Server-Opertatoren konfiguriert werden.
+  - Zombies der Resolver-Prozesse werden nun ordentlich "getoetet".
+  - NICK kann nun die Gross- und Kleinschreibung eines Nicks aendern.
+  - ein Server-Passwort ist nun konfigurierbar.
+  - neue Befehle: ERROR, SERVER, NJOIN (nur als "Fake"), SQUIT.
+  - Asyncroner Resolver Hostname->IP implementiert.
+  - Server-Links teilweise implementiert: bisher kann der ngIRCd jedoch
+    nur "leafed server" sein, d.h. keine "Client-Server" haben. Einige
+    Befehle sind auch noch nicht (optimal) angepasst: PRIVMSG funktioniert
+    aber bereits, ebenso wie WHOIS (letzterer wird immer an den Server,
+    auf dem der User registriert ist, weitergegeben).
+  - "arpa/inet.h" wird nur noch includiert, wenn vorhanden.
+  - Fehler bei select() fuerhen nun zum Abbruch von ngIRCd, bisher landete
+    der Server zumeist in einer Endlosschleife.
+  - Logmeldungen und Level an vielen Stellen verbessert.
+  - lokalen Usernamen wird nun ein "~" vorangestellt, da bisher noch keine
+    Ident-Anfragen gemacht werden.
+
+ngIRCd 0.0.1, 31.12.2001
+
+  - erste oeffentliche Version von ngIRCd als "public preview" :-)
+
+
+-- 
+$Id: ChangeLog,v 1.276.2.12 2005/10/15 12:44:08 alex Exp $

+ 186 - 0
INSTALL

@@ -0,0 +1,186 @@
+
+                     ngIRCd - Next Generation IRC Server
+
+                      (c)2001-2004 by Alexander Barton,
+                    alex@barton.de, http://www.barton.de/
+
+               ngIRCd is free software and published under the
+                   terms of the GNU General Public License.
+
+                                -- INSTALL --
+
+                         
+
+I. Upgrade Information
+~~~~~~~~~~~~~~~~~~~~~~
+
+Differences to version 0.8.x
+
+- The maximum length of passwords has been raised to 20 characters (instead
+  of 8 characters). If your passwords are longer than 8 characters then they
+  are cut at an other position now.
+
+Differences to version 0.6.x
+
+- Some options of the configure script have been renamed:
+    --disable-syslog  ->  --without-syslog
+    --disable-zlib    ->  --without-zlib
+  Please call "./configure --help" to review the full list of options!
+
+Differences to version 0.5.x
+
+- Starting with version 0.6.0, other servers are identified using asynchronous
+  passwords: therefore the variable "Password" in [Server]-sections has been
+  replaced by "MyPassword" and "PeerPassword".
+
+- New configuration variables, section [Global]: MaxConnections, MaxJoins
+  (see example configuration file "doc/sample-ngircd.conf"!).
+
+
+II. Standard Installation
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ngIRCd is developed for UNIX-based systems, which means that the installation
+on modern UNIX-like systems that are supported by GNU autoconf and GNU
+automake ("configure") should be no problem.
+
+The normal installation procedure after getting (and expanding) the source
+files (using a distribution archive or CVS) is as following:
+
+  1) ./autogen.sh	[only necessary when using CVS]
+  2) ./configure
+  3) make
+  4) make install
+
+(Please see details below!)
+
+Now the newly compiled executable "ngircd" is installed in its standard
+location, /usr/local/sbin/.
+
+The next step is to configure and afterwards starting the daemon. Please
+have a look at the ngircd(8) and ngircd.conf(5) manual pages for details
+and all possible options.
+
+If no previous version of the configuration file exists (the standard name
+is /usr/local/etc/ngircd.conf), a sample configuration file containing all
+possible options will be installed there. You'll find its template in the
+doc/ directory: sample-ngircd.conf.
+
+
+1): "autogen.sh"
+
+The first step, autogen.sh, is only necessary if the configure-script isn't
+already generated. This never happens in official ("stable") releases in
+tar.gz-archives, but when using CVS.
+
+This step is therefore only interesting for developers.
+
+autogen.sh produces the Makefile.in's, which are necessary for the configure
+script itself, and some more files for make. To run autogen.sh you'll need
+GNU autoconf and GNU automake (use recent versions! autoconf 2.53 and
+automake 1.6.1 are known to work).
+
+Again: "end users" do not need this step!
+
+
+2): "./configure"
+
+The configure-script is used to detect local system dependencies.
+
+In the perfect case, configure should recognise all needed libraries, header
+files and so on. If this shouldn't work, "./configure --help" shows all
+possible options.
+
+In addition, you can pass some command line options to "configure" to enable
+and/or disable some features of ngIRCd. All these options are shown using
+"./configure --help", too.
+
+Compiling a static binary will avoid you the hassle of feeding a chroot dir
+(if you want use the chroot feature). Just do something like:
+  CFLAGS=-static ./configure [--your-options ...]
+Then you can use a void directory as ChrootDir (like OpenSSH's /var/empty).
+
+
+3): "make"
+
+The make command uses the Makefiles produced by configure and compiles the
+ngIRCd daemon.
+
+
+4): "make install"
+
+Use "make install" to install the server and a sample configuration file on
+the local system. Normally, root privileges are necessary to complete this
+step. If there is already an older configuration file present, it won't be
+overwritten.
+
+This files will be installed by default:
+
+- /usr/local/sbin/ngircd: executable server
+- /usr/local/etc/ngircd.conf: sample configuration (if not already present)
+- /usr/local/share/doc/ngircd/: documentation
+
+
+II. Useful make-targets
+~~~~~~~~~~~~~~~~~~~~~~~
+
+The Makefile produced by the configure-script contains always these useful
+targets:
+
+ - clean: delete every product from the compiler/linker
+   next step: -> make
+
+ - distclean: the above plus erase all generated Makefiles
+   next step: -> ./configure
+
+ - maintainer-clean: erase all automatic generated files
+   next step: -> ./autogen.sh
+
+
+III. Sample configuration file ngircd.conf
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In the sample configuration file, there are comments beginning with "#" OR
+";" -- this is only for the better understanding of the file.
+
+The file is separated in four blocks: [Global], [Operator], [Server], and
+[Channel].
+
+In the [Global] section, there is the main configuration like the server
+name and the ports, on which the server should be listening. IRC operators
+of this server are defined in [Operator] blocks. [Server] is the section
+where server links are configured. And [Channel] blocks are used to
+configure pre-defined ("persistent") IRC channels.
+
+The meaning of the variables in the configuration file is explained in the 
+"doc/sample-ngircd.conf", which is used as sample configuration file in
+/usr/local/etc after running "make install" (if you don't already have one)
+and in the "ngircd.conf" manual page.
+
+
+IV. Command line options
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+These parameters could be passed to the ngIRCd:
+
+-f, --config <file>
+	The daemon uses the file <file> as configuration file rather than
+	the standard configuration /usr/local/etc/ngircd.conf.
+
+-n, --nodaemon
+	ngIRCd should be running as a foreground process.
+
+-p, --passive
+	Server-links won't be automatically established.
+
+-t, --configtest
+	Reads, validates and dumps the configuration file as interpreted
+	by the server. Then exits.
+
+Use "--help" to see a short help text describing all available parameters
+the server understands, with "--version" the ngIRCd shows its version
+number. In both cases the server exits after the output.
+
+
+-- 
+$Id: INSTALL,v 1.21 2005/02/10 08:20:09 alex Exp $

+ 46 - 0
Makefile.am

@@ -0,0 +1,46 @@
+#
+# ngIRCd -- The Next Generation IRC Daemon
+# Copyright (c)2001-2003 by Alexander Barton (alex@barton.de)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# Please read the file COPYING, README and AUTHORS for more information.
+#
+# $Id: Makefile.am,v 1.16 2005/04/09 12:27:40 alex Exp $
+#
+
+AUTOMAKE_OPTIONS = gnu
+
+SUBDIRS = doc src man contrib
+
+clean-local:
+	rm -f build-stamp*
+
+maintainer-clean-local:
+	rm -rf autom4te.cache
+	rm -f Makefile.in Makefile aclocal.m4 configure
+	rm -f mkinstalldirs missing depcomp install-sh
+	rm -f config.log debian
+
+lint:
+	make -C src/ngircd lint
+
+srcdoc:
+	make -C src srcdoc
+
+xcode:
+	@xcodebuild -project contrib/MacOSX/ngIRCd.xcode -list >/dev/null 2>&1 \
+	 || ( echo; echo "Error: \"xcodebuild\" not found!"; echo; exit 1 )
+	xcodebuild -project contrib/MacOSX/ngIRCd.xcode -alltargets \
+	 -buildstyle Development
+
+rpm: distcheck
+	rpm -ta ngircd-*.tar.gz
+
+deb:
+	[ -f debian/rules ] || ln -s contrib/Debian debian
+	dpkg-buildpackage -rfakeroot
+
+# -eof-

+ 555 - 0
Makefile.in

@@ -0,0 +1,555 @@
+# Makefile.in generated by automake 1.7.9 from Makefile.am.
+# @configure_input@
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# ngIRCd -- The Next Generation IRC Daemon
+# Copyright (c)2001-2003 by Alexander Barton (alex@barton.de)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# Please read the file COPYING, README and AUTHORS for more information.
+#
+# $Id: Makefile.am,v 1.16 2005/04/09 12:27:40 alex Exp $
+#
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = .
+
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_triplet = @host@
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+U = @U@
+VERSION = @VERSION@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+
+AUTOMAKE_OPTIONS = gnu
+
+SUBDIRS = doc src man contrib
+subdir = .
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/src/config.h
+CONFIG_CLEAN_FILES =
+DIST_SOURCES =
+
+RECURSIVE_TARGETS = info-recursive dvi-recursive pdf-recursive \
+	ps-recursive install-info-recursive uninstall-info-recursive \
+	all-recursive install-data-recursive install-exec-recursive \
+	installdirs-recursive install-recursive uninstall-recursive \
+	check-recursive installcheck-recursive
+DIST_COMMON = README $(srcdir)/Makefile.in $(srcdir)/configure AUTHORS \
+	COPYING ChangeLog INSTALL Makefile.am NEWS aclocal.m4 \
+	config.guess config.sub configure.in depcomp install-sh missing \
+	mkinstalldirs
+DIST_SUBDIRS = $(SUBDIRS)
+all: all-recursive
+
+.SUFFIXES:
+
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno
+$(srcdir)/Makefile.in:  Makefile.am  $(top_srcdir)/configure.in $(ACLOCAL_M4)
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  Makefile
+Makefile:  $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)
+
+$(top_builddir)/config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	$(SHELL) ./config.status --recheck
+$(srcdir)/configure:  $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
+	cd $(srcdir) && $(AUTOCONF)
+
+$(ACLOCAL_M4):  configure.in 
+	cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+uninstall-info-am:
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+	@set fnord $$MAKEFLAGS; amf=$$2; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	   || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+	@set fnord $$MAKEFLAGS; amf=$$2; \
+	dot_seen=no; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	rev=''; for subdir in $$list; do \
+	  if test "$$subdir" = "."; then :; else \
+	    rev="$$subdir $$rev"; \
+	  fi; \
+	done; \
+	rev="$$rev ."; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	   || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+ctags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+	done
+
+ETAGS = etags
+ETAGSFLAGS =
+
+CTAGS = ctags
+CTAGSFLAGS =
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	if (etags --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	else \
+	  include_option=--include; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -f $$subdir/TAGS && \
+	      tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(ETAGS_ARGS)$$tags$$unique" \
+	  || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	     $$tags $$unique
+
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = .
+distdir = $(PACKAGE)-$(VERSION)
+
+am__remove_distdir = \
+  { test ! -d $(distdir) \
+    || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
+         && rm -fr $(distdir); }; }
+
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+
+distdir: $(DISTFILES)
+	$(am__remove_distdir)
+	mkdir $(distdir)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkinstalldirs) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -d $(distdir)/$$subdir \
+	    || mkdir $(distdir)/$$subdir \
+	    || exit 1; \
+	    (cd $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$(top_distdir)" \
+	        distdir=../$(distdir)/$$subdir \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+	-find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
+	  ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+	  ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+	  ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \
+	|| chmod -R a+r $(distdir)
+dist-gzip: distdir
+	$(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+	$(am__remove_distdir)
+
+dist dist-all: distdir
+	$(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+	$(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration.  Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+	$(am__remove_distdir)
+	GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(AMTAR) xf -
+	chmod -R a-w $(distdir); chmod a+w $(distdir)
+	mkdir $(distdir)/_build
+	mkdir $(distdir)/_inst
+	chmod a-w $(distdir)
+	dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+	  && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+	  && cd $(distdir)/_build \
+	  && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+	    $(DISTCHECK_CONFIGURE_FLAGS) \
+	  && $(MAKE) $(AM_MAKEFLAGS) \
+	  && $(MAKE) $(AM_MAKEFLAGS) dvi \
+	  && $(MAKE) $(AM_MAKEFLAGS) check \
+	  && $(MAKE) $(AM_MAKEFLAGS) install \
+	  && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+	  && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+	  && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+	        distuninstallcheck \
+	  && chmod -R a-w "$$dc_install_base" \
+	  && ({ \
+	       (cd ../.. && $(mkinstalldirs) "$$dc_destdir") \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+	            distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+	      } || { rm -rf "$$dc_destdir"; exit 1; }) \
+	  && rm -rf "$$dc_destdir" \
+	  && $(MAKE) $(AM_MAKEFLAGS) dist-gzip \
+	  && rm -f $(distdir).tar.gz \
+	  && $(MAKE) $(AM_MAKEFLAGS) distcleancheck
+	$(am__remove_distdir)
+	@echo "$(distdir).tar.gz is ready for distribution" | \
+	  sed 'h;s/./=/g;p;x;p;x'
+distuninstallcheck:
+	@cd $(distuninstallcheck_dir) \
+	&& test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+	   || { echo "ERROR: files left after uninstall:" ; \
+	        if test -n "$(DESTDIR)"; then \
+	          echo "  (check DESTDIR support)"; \
+	        fi ; \
+	        $(distuninstallcheck_listfiles) ; \
+	        exit 1; } >&2
+distcleancheck: distclean
+	@if test '$(srcdir)' = . ; then \
+	  echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+	  exit 1 ; \
+	fi
+	@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+	  || { echo "ERROR: files left in build directory after distclean:" ; \
+	       $(distcleancheck_listfiles) ; \
+	       exit 1; } >&2
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-local mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-recursive
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -rf $(top_srcdir)/autom4te.cache
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic \
+	maintainer-clean-local
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+uninstall-info: uninstall-info-recursive
+
+.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am clean \
+	clean-generic clean-local clean-recursive ctags ctags-recursive \
+	dist dist-all dist-gzip distcheck distclean distclean-generic \
+	distclean-recursive distclean-tags distcleancheck distdir \
+	distuninstallcheck dvi dvi-am dvi-recursive info info-am \
+	info-recursive install install-am install-data install-data-am \
+	install-data-recursive install-exec install-exec-am \
+	install-exec-recursive install-info install-info-am \
+	install-info-recursive install-man install-recursive \
+	install-strip installcheck installcheck-am installdirs \
+	installdirs-am installdirs-recursive maintainer-clean \
+	maintainer-clean-generic maintainer-clean-local \
+	maintainer-clean-recursive mostlyclean mostlyclean-generic \
+	mostlyclean-recursive pdf pdf-am pdf-recursive ps ps-am \
+	ps-recursive tags tags-recursive uninstall uninstall-am \
+	uninstall-info-am uninstall-info-recursive uninstall-recursive
+
+
+clean-local:
+	rm -f build-stamp*
+
+maintainer-clean-local:
+	rm -rf autom4te.cache
+	rm -f Makefile.in Makefile aclocal.m4 configure
+	rm -f mkinstalldirs missing depcomp install-sh
+	rm -f config.log debian
+
+lint:
+	make -C src/ngircd lint
+
+srcdoc:
+	make -C src srcdoc
+
+xcode:
+	@xcodebuild -project contrib/MacOSX/ngIRCd.xcode -list >/dev/null 2>&1 \
+	 || ( echo; echo "Error: \"xcodebuild\" not found!"; echo; exit 1 )
+	xcodebuild -project contrib/MacOSX/ngIRCd.xcode -alltargets \
+	 -buildstyle Development
+
+rpm: distcheck
+	rpm -ta ngircd-*.tar.gz
+
+deb:
+	[ -f debian/rules ] || ln -s contrib/Debian debian
+	dpkg-buildpackage -rfakeroot
+
+# -eof-
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:

+ 211 - 0
NEWS

@@ -0,0 +1,211 @@
+
+                     ngIRCd - Next Generation IRC Server
+
+                        (c)2001-2005 Alexander Barton,
+                    alex@barton.de, http://www.barton.de/
+
+               ngIRCd is free software and published under the
+                   terms of the GNU General Public License.
+
+                                  -- NEWS --
+
+
+ngIRCd 0.9.0 (2005-07-24)
+
+  - Never run with root privileges but always switch the user ID.
+  - Make "netsplit" messages RFC compliant.
+  - Implemented the IRC function "WHOWAS".
+  - New configuration option "OperServerMode" to enable a workaround needed
+    when running an network with ircd2 servers and "OperCanUseMode" enabled
+    to prevent the ircd2 daemon to drop mode changes of IRC operators.
+    Patch by Florian Westphal, <westphal@foo.fh-furtwangen.de>.
+  - Implemented support for "secret channels" (channel mode "s").
+  - New configuration option "Mask" for [Operator] sections to limit OPER
+    commands to users with a specific IRC mask. Patch from Florian Westphal.
+  - New configuration variable "PidFile", section "[Global]": if defined,
+    the server writes its process ID (PID) to this file. Default: off.
+    Idea of Florian Westphal, <westphal@foo.fh-furtwangen.de>.
+  - Added support for the Howl (http://www.porchdogsoft.com/products/howl/)
+    Rendezvous API, in addition to the API of Apple (Mac OS X). The available
+    API will be autodetected when you call "./configure --with-rendezvous".
+
+ngIRCd 0.8.0 (2004-06-26)
+
+  - Two new configuration options: "ChrootDir" and "MotdPhrase", thanks to
+    Benjamin Pineau <ben@zouh.org>. Now you can force the daemon to change
+    its root and working directory to something "safe". MotdPhrase is used
+    to define an "MOTD string" instead of a whole file, useful if the
+    "real" MOTD file would be outside the "jail".
+  - INVITE- and BAN-lists become synchronized between IRC+ servers when
+    establishing new connections, if the peer supports this as well.
+  - The type of service (TOS) of all sockets is set to "interactive" now.
+  - Added short command line option "-t" as alternative to "--configtest".
+  - Added optional support for "IDENT" lookups on incoming connections. You
+    have to enable this function with the ./configure switch "--with-ident".
+    The default is not to do IDENT lookups.
+
+ngIRCd 0.7.5 (2003-07-11)
+
+  - New configuration variable "MaxConnectionsIP" to limit the number of
+    simultaneous connections from a single IP that the server will accept.
+    This configuration options lowers the risk of denial of service attacks
+    (DoS), the default is 5 connections per client IP.
+  - Added new configuration variable "Listen" to bind all listening
+    sockets of the server to a single IP address.
+       
+ngIRCd 0.7.1 (2003-07-18)
+
+  - Added support for GNU/Hurd.
+
+ngIRCd 0.7.0 (2003-05-01)
+
+  - New command CONNECT to enable and add server links. The syntax is not
+    RFC-compatible: use "CONNECT <name> <port>" to enable and connect an
+    configured server and "CONNECT <name> <port> <host> <mypwd> <peerpwd>"
+    to add a new server (ngIRCd tries to connect new servers only once!).
+  - Added DISCONNECT command ("DISCONNECT <name>") to disable servers.
+  - New command TRACE (you can trace only servers at the moment).
+  - New command HELP that lists all understood commands.
+  - ngIRCd can register itself with Rendezvous: to enable support pass the
+    new switch "--with-rendezvous" to configure.
+  - Added support for TCP Wrappers library: pass "--with-tcp-wrappers" to
+    configure to enable it.
+  - Changed some configure options to use "--with"/"--without" as prefix
+    instead of "--enable"/"--disable": "--without-syslog", "--without-zlib",
+    "--with-tcp-wrappers", and "--with-rendezvous".
+  - Enhanced manual pages ngircd(8) and ngircd.conf(5).
+  - Documentation is now installed in $(datadir)/doc/ngircd.
+
+
+Older news (sorry, only available in german language):
+
+ngIRCd 0.6.0, 2002-12-24
+
+  - beim Schliessen einer Verbindung zeigt der Server nun vor dem ERROR
+    noch eine Statistik ueber die empfangene und gesendete Datenmenge an.
+  - Connection-Strukturen werden nun "pool-weise" verwaltet; der Pool wird
+    bei Bedarf bis zu einem konfigurierten Limit vergroessert.
+  - Mit der neuen Konfigurationsvariable "MaxConnections" (Sekion "Global")
+    kann die maximale Anzahl gleichzeitiger Verbindungen begrenzt werden.
+    Der Default ist -1, "unlimitiert".
+  - der Server erkennt nun, ob bereits eine eingehende Verbindung von einem
+    Peer-Server besteht und versucht dann nicht mehr, selber eine eigene
+    ausgehende Verbindung zu diesem auufzubauen. Dadurch kann nun auf beiden
+    Servern in der Konfiguration ein Port fuer den Connect konfiguriert
+    werden (beide Server versuchen sich dann gegenseitig zu connectieren).
+  - Server identifizieren sich nun mit asyncronen Passwoertern, d.h. das
+    Passwort, welches A an B schickt, kann ein anderes sein als das, welches
+    B als Antwort an A sendet. In der Konfig.-Datei, Abschnitt "Server",
+    wurde "Password" dazu durch "MyPassword" und "PeerPassword" ersetzt.
+  - Der Server kann nun zur Laufzeit die Konfiguration neu einlesen: dies
+    macht er nach dem Befehl REHASH oder wenn ein HUP-Signal empfangen wird.
+  - Server-Server-Links koennen nun komprimiert werden, dazu wird die zlib
+    (www.zlib.org) benoetigt. Unterstuetzt die Gegenseite die Komprimierung
+    nicht, wird automatisch unkomprimiert kommuniziert. Das Verfahren ist
+    kompatibel mit dem Original-ircd 2.10.3, d.h. beide Server koennen
+    miteinander ueber komprimiert Links kommunizieren.
+  - neue Konfigurations-Variable "MaxJoins": Hiermit kann die maximale Zahl
+    der Channels, in denen ein User Mitglied sein kann, begrent werden.
+  - neue Channel-Modes l (User-Limit) und k (Channel-Key) implementiert.
+
+ngIRCd 0.5.0, 20.09.2002
+
+  - AIX (3.2.5), HP-UX (10.20), IRIX (6.5), NetBSD (1.5.3/m68k) und Solaris
+    (2.5.1, 2.6) gehoeren nun auch zu den unterstuetzten Platformen.
+  - Unter A/UX (und evtl. weiteren Systemen) kompiliert der ngIRCd nun mit
+    dem "nativen" (ggf. pre-ANSI) Compiler.
+  - "persistente Channels" (Mode 'P') implementiert: diese koennen in der
+    Konfigurationsdatei definiert werden (Sektion "Channel", vgl. Beispiel-
+    Konfiguration "sample-ngircd.conf") und bleiben auch dann bestehen,
+    wenn kein User mehr im Channel ist.
+  - neue IRC-Befehle: KICK, INVITE, ADMIN, CHANINFO; LIST wurde erweitert.
+    Mit dem neuen Befehl CHANINFO syncronisieren Server, die das IRC+-
+    Protokoll unterstuetzen, Channel-Modes und Topics. Fuer den ADMIN-Befehl
+    gibt es neue Konfigurationsoptionen (Sektion "Global"): "AdminInfo1",
+    "AdminInfo2" und "AdminEMail".
+  - Invite- und Ban-Lists implementiert.
+  - neue Konfigurationsoption "OperCanUseMode" (Sektion "Global"):
+    ist sie aktiv, koennen IRC-Operatoren immer Channel-Modes setzen.
+  - "Test-Suite" begonnen: mit "make check" wird sie durchlaufen.
+
+ngIRCd 0.4.2, 29.04.2002
+
+  - IRC-Funktion LIST implementiert; bisher werden allerdings noch keine
+    Regular Expressions (bis auf "*") unterstuetzt.
+
+ngIRCd 0.4.0, 01.04.2002
+
+  - WHO implementiert (bisher ohne komplette Unterstuetzung von Masks).
+  - stderr wird nun in eine Datei umgelenkt (/ngircd-<PID>.err).
+    Laeuft der Server nicht im Debug-Modus, so wird diese bei Programm-
+    ende geloescht. Sollte der Server abstuerzen, finden sich hier evtl.
+    zusaetzliche Informationen.
+  - Server-Gruppen implementiert: es wird immer nur zu einem Server in
+    einer Gruppe eine Verbindung aufgebaut, klappt es beim ersten Server
+    nicht, so wird der naechste probiert.
+  - Clients und Channels werden nicht mehr ueber ihren Namen, sondern
+    einen Hash-Wert gesucht: sollte deutlich schneller sein.
+  - neuer Kommandozeilen-Parameter "--configtest": die Konfiguration wird
+    gelesen und die dann verwendeten Werte angezeigt.
+  - Client-Mode "s" (Server Notices) implementiert.
+  - mit dem neuen Kommandozeilen-Parameter "--config"/"-f" kann eine
+    alternative Konfigurationsdatei angegeben werden.
+  - nach dem Start kann der ngIRCd, wenn er mit root-Rechten laeuft,
+    zu einer anderen User-ID und Group-ID wechseln.
+
+ngIRCd 0.3.0, 02.03.2002
+
+  - bekommt der Server ein HUP-Signal, so startet er neu -- genau so, wie
+    er auf den IRC-Befehl RESTART reagiert.
+  - neuer Kommandozeilen-Schalter "--passive" (-p): wird er angegeben, so
+    verbindet sich der ngIRCd nicht mehr automatisch zu anderen Servern.
+    Zum Debuggen manchmal ganz praktisch :-)
+  - neue Befehle VERSION und KILL implementiert. NAMES korrigiert.
+  - Anpassungen an A/UX: gehoert nun auch zu den unterstuetzten Platformen.
+  - AWAY (und der User-Mode 'a') ist nun implementiert.
+  - der ngIRCd unterstuetzt nun Channel-Topics (TOPIC-Befehl).
+  - Channel- und Nicknames werden nun ordentlich validiert.
+
+ngIRCd 0.2.0, 15.02.2002
+
+  - Begonnen Channel-Modes und User-Channel-Modes zu implementieren: der
+    Server versteht an User-Modes o und v, beachtet letzteres allerdings
+    noch nirgends. Bekannte (aber nicht beachtete!) Channel-Modes sind
+    bisher a, m, n, p, q, s und t. Diese Modes werden von Usern ange-
+    nommen, von anderen Servern werden auch unbekannte Modes uebernommen.
+  - Nach dem Connect eines Users werden LUSERS-Informationen angezeigt.
+
+ngIRCd 0.1.0, 29.01.2002
+
+  - Channels implementiert, bisher jedoch noch ohne Channel-Modes, d.h.
+    es gibt keine Channel-Ops, kein Topic, kein "topic lock" etc. pp.
+    Chatten in Channels ist aber natuerlich moeglich ;-)
+    Dadurch zum Teil groessere Aenderungen an bisherigen Funktionen.
+  - neue Befehle fuer Channles: JOIN, PART und NJOIN.
+  - FAQ.txt in doc/ begonnen.
+
+ngIRCd 0.0.3, 16.01.2002
+
+  - Server-Links vollstaendig implementiert: der ngIRCd kann nun auch
+    "Sub-Server" haben, also sowohl als Leaf-Node als auch Hub in einem
+    IRC-Netzwerk arbeiten.
+  - WHOIS wird nun immer an den "Original-Server" weitergeleitet.
+  - Parser handhabt Leerzeichen zw. Parametern nun etwas "lockerer".
+  - Kommandozeilen-Parser: Debug- und No-Daemon-Modus, Hilfe.
+  - ngIRCd wandelt sich nun in einen Daemon (Hintergrundprozess) um.
+  - neue Befehle: LUSERS, LINKS.
+
+ngIRCd 0.0.2, 06.01.2002
+
+  - neuer Aufbau der Konfigurationsdatei,
+  - mehrere IRC-Operatoren koennen konfiguriert werden,
+  - Server-Links teilweise implementiert. Bisher kann der ngIRCd jedoch
+    nur "leafed server" sein, d.h. keine "Client-Server" haben.
+
+ngIRCd 0.0.1, 31.12.2001
+
+  - erste oeffentliche Version von ngIRCd als "public preview" :-)
+
+
+-- 
+$Id: NEWS,v 1.74.2.1 2005/07/24 21:39:45 alex Exp $

+ 87 - 0
README

@@ -0,0 +1,87 @@
+
+                     ngIRCd - Next Generation IRC Server
+
+                        (c)2001-2005 Alexander Barton,
+                    alex@barton.de, http://www.barton.de/
+
+               ngIRCd is free software and published under the
+                   terms of the GNU General Public License.
+
+                                -- README --
+
+
+I. Introduction
+~~~~~~~~~~~~~~~
+
+ngIRCd is an Open Source server for the Internet Relay Chat (IRC), which
+is developed and published under the terms of the GNU General Public
+Licence (URL: http://www.gnu.org/licenses/gpl.html). ngIRCd means "next
+generation IRC daemon", it's written from scratch and not deduced from the
+"grandfather of IRC daemons", the daemon of the IRCNet.
+
+
+II. Status
+~~~~~~~~~~~
+
+It is not the goal of ngIRCd to implement all the nasty behaviours of the
+original ircd, but to implement most of the useful commands and semantics
+specified by the RFCs.
+
+In the meantime ngIRCd should be quite feature complete and stable to be
+used in real IRC networks.
+
+Implemented IRC-commands are:
+
+ADMIN, AWAY, CHANINFO, CONNECT, DIE, DISCONNECT, ERROR, HELP, INVITE, ISON,
+JOIN, KICK, KILL, LINKS, LIST, LUSERS, MODE, MOTD, NAMES, NICK, NJOIN, NOTICE,
+OPER, PART, PASS, PING, PONG, PRIVMSG, QUIT, REHASH, RESTART, SERVER, SQUIT,
+STATS, TIME, TOPIC, TRACE, USER, USERHOST, VERSION, WHO, WHOIS, WHOWAS.
+
+
+III. Features (or: why use ngIRCd?)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- no problems with servers which have dynamic IP addresses
+- simple, easy understandable configuration file,
+- freely published open-source C source code,
+- ngIRCd will be developed on in the future.
+- wide field of supported platforms, including AIX, A/UX, FreeBSD, HP-UX,
+  IRIX, Linux, Mac OS X, NetBSD, OpenBSD, Solaris, and Windows with Cygwin.
+
+
+IV. Documentation
+~~~~~~~~~~~~~~~~~
+
+More documentation can be found in the "doc/" directory and the homepage of
+the ngIRCd: <http://ngircd.barton.de/>.
+
+
+V. Download
+~~~~~~~~~~~
+
+The homepage of the ngIRCd is: <http://ngircd.barton.de/>; you will find
+the newest information about the ngIRCd and the most recent ("stable")
+releases there.
+
+If you are interested in the latest development versions (which are not
+always stable), then please read the section "CVS" on the homepage and
+the file "doc/CVS.txt" which describes the use of CVS, the "Concurrent
+Versioning System".
+
+
+VI. Bugs
+~~~~~~~~
+
+If you find bugs in the ngIRCd (which might be there :-), please report
+them at the following URL:
+
+<http://ngircd.barton.de/#bugs>
+
+There you can read about known bugs and limitations, too.
+
+If you have critics, patches or something else, please feel free to post a
+mail to <alex@barton.de>.
+
+
+-- 
+$Id: README,v 1.20.2.1 2005/07/09 14:41:39 alex Exp $

File diff suppressed because it is too large
+ 1010 - 0
aclocal.m4


File diff suppressed because it is too large
+ 1466 - 0
config.guess


File diff suppressed because it is too large
+ 1579 - 0
config.sub


File diff suppressed because it is too large
+ 10130 - 0
configure


+ 418 - 0
configure.in

@@ -0,0 +1,418 @@
+#
+# ngIRCd -- The Next Generation IRC Daemon
+# Copyright (c)2001-2005 Alexander Barton <alex@barton.de>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# Please read the file COPYING, README and AUTHORS for more information.
+#
+# $Id: configure.in,v 1.111.2.6 2005/10/15 12:44:08 alex Exp $
+#
+
+# -- Initialisation --
+
+AC_PREREQ(2.50)
+AC_INIT(ngircd, 0.9.2)
+AC_CONFIG_SRCDIR(src/ngircd/ngircd.c)
+AC_CANONICAL_TARGET
+AM_INIT_AUTOMAKE(1.6)
+AM_CONFIG_HEADER(src/config.h)
+
+# -- Templates for config.h --
+
+AH_TEMPLATE([DEBUG], [Define if debug-mode should be enabled])
+AH_TEMPLATE([HAVE_socklen_t], [Define if socklen_t exists])
+AH_TEMPLATE([SNIFFER], [Define if IRC sniffer should be enabled])
+AH_TEMPLATE([STRICT_RFC], [Define if ngIRCd should behave strict RFC compliant])
+AH_TEMPLATE([SYSLOG], [Define if syslog should be used for logging])
+AH_TEMPLATE([ZLIB], [Define if zlib compression should be enabled])
+AH_TEMPLATE([TCPWRAP], [Define if TCP wrappers should be used])
+AH_TEMPLATE([IRCPLUS], [Define if IRC+ protocol should be used])
+AH_TEMPLATE([RENDEZVOUS], [Define if Rendezvous support should be included])
+AH_TEMPLATE([IDENTAUTH], [Define if the server should do IDENT requests])
+
+AH_TEMPLATE([TARGET_OS], [Target operating system name])
+AH_TEMPLATE([TARGET_VENDOR], [Target system vendor])
+AH_TEMPLATE([TARGET_CPU], [Target CPU name])
+
+# -- C Compiler --
+
+AC_PROG_CC
+
+# -- Helper programs --
+
+AC_PROG_AWK
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+AC_PROG_RANLIB
+
+# -- Compiler Features --
+
+AM_C_PROTOTYPES
+AC_C_CONST
+
+# -- Hard coded system and compiler dependencies/features/options ... --
+
+if test "$GCC" = "yes"; then
+	# We are using the GNU C compiler. Good!
+	CFLAGS="$CFLAGS -pipe -W -Wall -Wpointer-arith -Wstrict-prototypes"
+fi
+
+case "$target_os" in
+	hpux*)
+		# This is HP/UX, we need to define _XOPEN_SOURCE_EXTENDED
+		# (tested with HP/UX 11.11)
+		CFLAGS="$CFLAGS -D_XOPEN_SOURCE_EXTENDED"
+		;;
+esac
+
+# Add additional CFLAGS, eventually specified on the command line:
+test -n "$CFLAGS_ADD" && CFLAGS="$CFLAGS $CFLAGS_ADD"
+
+CFLAGS="$CFLAGS -DSYSCONFDIR='\"\$(sysconfdir)\"'"
+
+# -- Headers --
+
+AC_HEADER_STDC
+AC_HEADER_TIME
+AC_HEADER_SYS_WAIT
+
+AC_CHECK_HEADERS([ \
+	ctype.h errno.h fcntl.h netdb.h netinet/in.h stdlib.h string.h \
+	strings.h sys/socket.h sys/time.h unistd.h \
+	],,AC_MSG_ERROR([required C header missing!]))
+
+AC_CHECK_HEADERS([arpa/inet.h ctype.h malloc.h stdbool.h stddef.h varargs.h])
+
+# -- Datatypes --
+
+AC_MSG_CHECKING(whether socklen_t exists)
+AC_TRY_COMPILE([
+#include <sys/types.h>
+#include <sys/socket.h>
+	],[
+	socklen_t a, b;
+	a = 2; b = 4; a += b;
+	],[
+	AC_DEFINE(HAVE_socklen_t) AC_MSG_RESULT(yes)
+	],[
+	AC_MSG_RESULT(no)
+])
+
+AC_TYPE_SIGNAL
+AC_TYPE_SIZE_T
+
+# -- Libraries --
+
+AC_CHECK_LIB(UTIL,memmove)
+AC_CHECK_LIB(socket,bind)
+AC_CHECK_LIB(nsl,gethostent)
+
+# -- Functions --
+
+AC_FUNC_FORK
+AC_FUNC_STRFTIME
+
+AC_CHECK_FUNCS([ \
+	bind gethostbyaddr gethostbyname gethostname inet_ntoa malloc memmove \
+	memset realloc setsid setsockopt socket strcasecmp strchr strerror \
+	strstr waitpid],,AC_MSG_ERROR([required function missing!]))
+
+AC_CHECK_FUNCS(inet_aton isdigit sigaction snprintf vsnprintf strdup strlcpy strlcat)
+
+AC_CHECK_FUNCS(select,[AC_CHECK_HEADERS(sys/select.h)],
+	AC_MSG_ERROR([required function select() is missing!])
+)
+
+# -- Configuration options --
+
+x_syslog_on=no
+AC_ARG_WITH(syslog,
+	[  --without-syslog        disable syslog (autodetected by default)],
+	[	if test "$withval" != "no"; then
+			if test "$withval" != "yes"; then
+				CFLAGS="-I$withval/include $CFLAGS"
+				CPPFLAGS="-I$withval/include $CPPFLAGS"
+				LDFLAGS="-L$withval/lib $LDFLAGS"
+			fi
+			AC_CHECK_LIB(be, syslog)
+			AC_CHECK_FUNCS(syslog, x_syslog_on=yes,
+				AC_MSG_ERROR([Can't enable syslog!])
+			)
+		fi
+	],
+	[
+		AC_CHECK_LIB(be, syslog)
+		AC_CHECK_FUNCS(syslog, x_syslog_on=yes)
+	]
+)
+if test "$x_syslog_on" = "yes"; then
+	AC_DEFINE(SYSLOG, 1)
+	AC_CHECK_HEADERS(syslog.h,,AC_MSG_ERROR([required C header missing!]))
+fi
+
+x_zlib_on=no
+AC_ARG_WITH(zlib,
+	[  --without-zlib          disable zlib compression (autodetected by default)],
+	[	if test "$withval" != "no"; then
+			if test "$withval" != "yes"; then
+				CFLAGS="-I$withval/include $CFLAGS"
+				CPPFLAGS="-I$withval/include $CPPFLAGS"
+				LDFLAGS="-L$withval/lib $LDFLAGS"
+			fi
+			AC_CHECK_LIB(z, deflate)
+			AC_CHECK_FUNCS(deflate, x_zlib_on=yes,
+				AC_MSG_ERROR([Can't enable zlib!])
+			)
+		fi
+	],
+	[	AC_CHECK_LIB(z, deflate)
+		AC_CHECK_FUNCS(deflate, x_zlib_on=yes)
+	]
+)
+if test "$x_zlib_on" = "yes"; then
+	AC_DEFINE(ZLIB, 1)
+	AC_CHECK_HEADERS(zlib.h,,AC_MSG_ERROR([required C header missing!]))
+fi
+
+x_tcpwrap_on=no
+AC_ARG_WITH(tcp-wrappers,
+	[  --with-tcp-wrappers     enable TCP wrappers support],
+	[	if test "$withval" != "no"; then
+			if test "$withval" != "yes"; then
+				CFLAGS="-I$withval/include $CFLAGS"
+				CPPFLAGS="-I$withval/include $CPPFLAGS"
+				LDFLAGS="-L$withval/lib $LDFLAGS"
+			fi
+			AC_MSG_CHECKING(for hosts_access)
+			LIBS="-lwrap $LIBS"
+			AC_TRY_LINK([
+#include <tcpd.h>
+int allow_severity = 0;
+int deny_severity = 0;
+				],[
+				tcpd_warn("link test");
+				],[
+				AC_MSG_RESULT(yes)
+				AC_DEFINE(TCPWRAP, 1)
+				x_tcpwrap_on=yes
+				],[
+				AC_MSG_RESULT(no)
+				AC_MSG_ERROR([Can't enable TCP wrappers!])
+			])
+		fi
+	]
+)
+
+x_rendezvous_on=no
+AC_ARG_WITH(rendezvous,
+	[  --with-rendezvous       enable support for "Rendezvous"],
+	[	if test "$withval" != "no"; then
+			if test "$withval" != "yes"; then
+				CFLAGS="-I$withval/include $CFLAGS"
+				CPPFLAGS="-I$withval/include $CPPFLAGS"
+				LDFLAGS="-L$withval/lib $LDFLAGS"
+			fi
+			AC_CHECK_FUNCS(DNSServiceRegistrationCreate, x_rendezvous_on=osx,
+			[
+				AC_CHECK_LIB(pthread, pthread_mutexattr_init)
+				AC_CHECK_LIB(howl, sw_discovery_init)
+				AC_CHECK_FUNCS(sw_discovery_init, \
+				 x_rendezvous_on=howl, \
+				 AC_MSG_ERROR([Can't enable Rendezvous!]))
+			])
+		fi
+	]
+)
+if test "$x_rendezvous_on" = "osx"; then
+	AC_CHECK_HEADERS([DNSServiceDiscovery/DNSServiceDiscovery.h \
+	 mach/port.h],,AC_MSG_ERROR([required C header missing!]))
+	AC_DEFINE(RENDEZVOUS, 1)
+fi
+if test "$x_rendezvous_on" = "howl"; then
+	for dir in /usr/local/include /usr/local/include/howl* \
+	 /usr/include /usr/include/howl*; do
+	 	test -d "$dir" || continue
+		AC_MSG_CHECKING([for Howl headers in $dir])
+		if test -f "$dir/rendezvous/rendezvous.h"; then
+			if test "$dir" != "/usr/local/include" -a \
+			 "$dir" != "/usr/include"; then
+				CFLAGS="-I$dir $CFLAGS"
+				CPPFLAGS="-I$dir $CPPFLAGS"
+			fi
+			AC_MSG_RESULT(yes)
+			break
+		else
+			AC_MSG_RESULT(no)
+		fi
+	done
+	AC_CHECK_HEADERS([rendezvous/rendezvous.h],, \
+	 AC_MSG_ERROR([required C header missing!]))
+	AC_DEFINE(RENDEZVOUS, 1)
+fi
+
+x_identauth_on=no
+AC_ARG_WITH(ident,
+	[  --with-ident            enable "IDENT" ("AUTH") protocol support],
+	[	if test "$withval" != "no"; then
+			if test "$withval" != "yes"; then
+				CFLAGS="-I$withval/include $CFLAGS"
+				CPPFLAGS="-I$withval/include $CPPFLAGS"
+				LDFLAGS="-L$withval/lib $LDFLAGS"
+			fi
+			AC_CHECK_LIB(ident, ident_id)
+			AC_CHECK_FUNCS(ident_id, x_identauth_on=yes,
+				AC_MSG_ERROR([Can't enable IDENT support!])
+			)
+		fi
+	]
+)
+if test "$x_identauth_on" = "yes"; then
+	AC_DEFINE(IDENTAUTH, 1)
+	AC_CHECK_HEADERS(ident.h,,AC_MSG_ERROR([required C header missing!]))
+fi
+
+x_ircplus_on=yes
+AC_ARG_ENABLE(ircplus,
+	[  --disable-ircplus       disable IRC+ protocol],
+	if test "$enableval" = "no"; then x_ircplus_on=no; fi
+)
+if test "$x_ircplus_on" = "yes"; then
+	AC_DEFINE(IRCPLUS, 1)
+fi
+
+x_sniffer_on=no; x_debug_on=no
+AC_ARG_ENABLE(sniffer,
+	[  --enable-sniffer        enable IRC traffic sniffer (enables debug mode)],
+	if test "$enableval" = "yes"; then
+		AC_DEFINE(SNIFFER, 1)
+		x_sniffer_on=yes; x_debug_on=yes
+	fi
+)
+
+AC_ARG_ENABLE(debug,
+	[  --enable-debug          show additional debug output],
+	if test "$enableval" = "yes"; then x_debug_on=yes; fi
+)
+if test "$x_debug_on" = "yes"; then
+	AC_DEFINE(DEBUG, 1)
+	test "$GCC" = "yes" && CFLAGS="-pedantic $CFLAGS"
+fi
+
+x_strict_rfc_on=no
+AC_ARG_ENABLE(strict-rfc,
+	[  --enable-strict-rfc     strict RFC conformance -- may break clients!],
+	if test "$enableval" = "yes"; then
+		AC_DEFINE(STRICT_RFC, 1)
+		x_strict_rfc_on=yes
+	fi
+)
+
+# -- Definitions --
+
+AC_DEFINE_UNQUOTED(TARGET_CPU, "$target_cpu" )
+AC_DEFINE_UNQUOTED(TARGET_VENDOR, "$target_vendor" )
+AC_DEFINE_UNQUOTED(TARGET_OS, "$target_os" )
+
+# Add additional CFLAGS, eventually specified on the command line, but after
+# running this configure script. Useful for "-Werror" for example.
+test -n "$CFLAGS_END" && CFLAGS="$CFLAGS $CFLAGS_END"
+
+# -- Generate files --
+
+AC_OUTPUT([ \
+	Makefile \
+	doc/Makefile \
+	src/Makefile \
+	src/portab/Makefile \
+	src/tool/Makefile \
+	src/ngircd/Makefile \
+	src/testsuite/Makefile \
+	man/Makefile \
+	contrib/Makefile \
+	contrib/Debian/Makefile \
+	contrib/MacOSX/Makefile \
+])
+
+type dpkg >/dev/null 2>&1
+if test $? -eq 0; then
+	# Generate debian/ link if the dpkg command exists
+	# (read: if we are running on a debian compatible system)
+	echo "creating Debian-specific links ..."
+	test -f debian/rules || ln -s contrib/Debian debian
+fi
+
+# -- Result --
+
+echo
+echo "ngIRCd $PACKAGE_VERSION has been configured with the following options:"
+echo
+
+# Someone please show me a better way :)  [borrowed by OpenSSH]
+B=`eval echo ${bindir}` ; B=`eval echo ${B}`
+S=`eval echo ${sbindir}` ; S=`eval echo ${S}`
+C=`eval echo ${sysconfdir}` ; C=`eval echo ${C}`
+M=`eval echo ${mandir}` ; M=`eval echo ${M}`
+D=`eval echo ${datadir}/doc/${PACKAGE}` ; D=`eval echo ${D}`
+
+echo "             Target: ${target}"
+test "$target" != "$host" && echo "               Host: ${host}"
+echo "           Compiler: ${CC}"
+test -n "$CFLAGS"	&& echo "     Compiler flags: ${CFLAGS}"
+test -n "$CPPFLAGS"	&& echo " Preprocessor flags: ${CPPFLAGS}"
+test -n "$LDFLAGS"	&& echo "       Linker flags: ${LDFLAGS}"
+test -n "$LIBS"		&& echo "          Libraries: ${LIBS}"
+echo
+echo "    'ngircd' binary: $S"
+echo " Configuration file: $C"
+echo "       Manual pages: $M"
+echo "      Documentation: $D"
+echo
+
+echo $ECHO_N "     Syslog support: $ECHO_C"
+test "$x_syslog_on" = "yes" \
+	&& echo $ECHO_N "yes $ECHO_C" \
+	|| echo $ECHO_N "no  $ECHO_C"
+echo $ECHO_N "  Enable debug code: $ECHO_C"
+test "$x_debug_on" = "yes" \
+	&& echo "yes" \
+	|| echo "no"
+
+echo $ECHO_N "   zlib compression: $ECHO_C"
+test "$x_zlib_on" = "yes" \
+	&& echo $ECHO_N "yes $ECHO_C" \
+	|| echo $ECHO_N "no  $ECHO_C"
+echo $ECHO_N "        IRC sniffer: $ECHO_C"
+test "$x_sniffer_on" = "yes" \
+	&& echo "yes" \
+	|| echo "no"
+
+echo $ECHO_N "   Use TCP Wrappers: $ECHO_C"
+test "$x_tcpwrap_on" = "yes" \
+	&& echo $ECHO_N "yes $ECHO_C" \
+	|| echo $ECHO_N "no  $ECHO_C"
+echo $ECHO_N "    Strict RFC mode: $ECHO_C"
+test "$x_strict_rfc_on" = "yes" \
+	&& echo "yes" \
+	|| echo "no"
+
+echo $ECHO_N " Rendezvous support: $ECHO_C"
+test "$x_rendezvous_on" = "osx" -o "$x_rendezvous_on" = "howl" \
+	&& echo $ECHO_N "yes $ECHO_C" \
+	|| echo $ECHO_N "no  $ECHO_C"
+echo $ECHO_N "      IRC+ protocol: $ECHO_C"
+test "$x_ircplus_on" = "yes" \
+	&& echo "yes" \
+	|| echo "no"
+
+echo $ECHO_N "      IDENT support: $ECHO_C"
+test "$x_identauth_on" = "yes" \
+	&& echo $ECHO_N "yes $ECHO_C" \
+	|| echo $ECHO_N "no  $ECHO_C"
+
+echo; echo
+
+# -eof-

+ 28 - 0
contrib/Debian/Makefile.am

@@ -0,0 +1,28 @@
+#
+# ngIRCd -- The Next Generation IRC Daemon
+# Copyright (c)2001-2003 by Alexander Barton (alex@barton.de)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# Please read the file COPYING, README and AUTHORS for more information.
+#
+# $Id: Makefile.am,v 1.4 2004/05/11 00:32:31 alex Exp $
+#
+
+EXTRA_DIST = rules changelog compat control copyright \
+	ngircd.init ngircd.postinst
+
+maintainer-clean-local:
+	rm -f Makefile Makefile.in
+
+clean-local:
+	rm -f ngircd.postinst.debhelper ngircd.postrm.debhelper \
+	 ngircd.prerm.debhelper ngircd.substvars
+	rm -f ngircd-full.postinst.debhelper ngircd-full.postrm.debhelper \
+	 ngircd-full.prerm.debhelper ngircd-full.substvars
+	rm -rf ngircd ngircd-full
+	rm -f files
+
+# -eof-

+ 292 - 0
contrib/Debian/Makefile.in

@@ -0,0 +1,292 @@
+# Makefile.in generated by automake 1.7.9 from Makefile.am.
+# @configure_input@
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# ngIRCd -- The Next Generation IRC Daemon
+# Copyright (c)2001-2003 by Alexander Barton (alex@barton.de)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# Please read the file COPYING, README and AUTHORS for more information.
+#
+# $Id: Makefile.am,v 1.4 2004/05/11 00:32:31 alex Exp $
+#
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../..
+
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_triplet = @host@
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+U = @U@
+VERSION = @VERSION@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+
+EXTRA_DIST = rules changelog compat control copyright \
+	ngircd.init ngircd.postinst
+
+subdir = contrib/Debian
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/src/config.h
+CONFIG_CLEAN_FILES =
+DIST_SOURCES =
+DIST_COMMON = $(srcdir)/Makefile.in Makefile.am
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  Makefile.am  $(top_srcdir)/configure.in $(ACLOCAL_M4)
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  contrib/Debian/Makefile
+Makefile:  $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
+uninstall-info-am:
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ../..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkinstalldirs) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile
+
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-local mostlyclean-am
+
+distclean: distclean-am
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic \
+	maintainer-clean-local
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+.PHONY: all all-am check check-am clean clean-generic clean-local \
+	distclean distclean-generic distdir dvi dvi-am info info-am \
+	install install-am install-data install-data-am install-exec \
+	install-exec-am install-info install-info-am install-man \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic \
+	maintainer-clean-local mostlyclean mostlyclean-generic pdf \
+	pdf-am ps ps-am uninstall uninstall-am uninstall-info-am
+
+
+maintainer-clean-local:
+	rm -f Makefile Makefile.in
+
+clean-local:
+	rm -f ngircd.postinst.debhelper ngircd.postrm.debhelper \
+	 ngircd.prerm.debhelper ngircd.substvars
+	rm -f ngircd-full.postinst.debhelper ngircd-full.postrm.debhelper \
+	 ngircd-full.prerm.debhelper ngircd-full.substvars
+	rm -rf ngircd ngircd-full
+	rm -f files
+
+# -eof-
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:

+ 187 - 0
contrib/Debian/changelog

@@ -0,0 +1,187 @@
+ngircd (0.9.2-0ab1) unstable; urgency=low
+
+  * New "upstream release" fixing a few bugs in 0.9.1.
+
+ -- Alexander Barton <alex@barton.de>  Sat, 15 Oct 2005 14:10:34 +0200
+
+ngircd (0.9.1-0ab1) unstable; urgency=medium
+
+  * New "upstream release" addressing two problems in ngIRCd 0.9.0.
+
+ -- Alexander Barton <alex@barton.de>  Wed,  3 Aug 2005 15:10:41 +0200
+
+ngircd (0.9.0-0ab2) unstable; urgency=medium
+
+  * Init script: fixed a problem with symbolic links in runlevel directories
+    that could prevent the init script from working correctly.
+
+ -- Alexander Barton <alex@barton.de>  Tue, 26 Jul 2005 21:31:18 +0200
+
+ngircd (0.9.0-0ab1) unstable; urgency=low
+
+  * New "upstream release".
+
+ -- Alexander Barton <alex@Arthur.Ath.CX>  Sat,  24 Jul 2005 23:30:00 +0200
+
+ngircd (0.8.3-0ab1) unstable; urgency=high
+
+  * New "upstream release", including security fixes.
+
+ -- Alexander Barton <alex@Arthur.Ath.CX>  Thu,  3 Feb 2005 10:41:55 +0100
+
+ngircd (0.8.2-0ab1) unstable; urgency=high
+
+  * New "upstream release", including security fixes.
+
+ -- Alexander Barton <alex@Arthur.Ath.CX>  Wed, 26 Jan 2005 23:14:12 +0100
+
+ngircd (0.8.1-0ab1) unstable; urgency=low
+
+  * New "upstream release".
+
+ -- Alexander Barton <alex@Arthur.Ath.CX>  Sat, 25 Dec 2004 01:18:32 +0100
+
+ngircd (0.8.0-0ab2) unstable; urgency=low
+
+  * Added missing commas to debian control file, fixes bug #56.
+    Thanks to Kevin Otte.
+
+ -- Alexander Barton <alex@Arthur.Ath.CX>  Thu, 15 Jul 2004 10:53:39 +0200
+
+ngircd (0.8.0-0ab1) unstable; urgency=low
+
+  * New upstream version.
+
+ -- Alexander Barton <alex@Arthur.Ath.CX>  Sat, 26 Jun 2004 11:25:59 +0200
+
+ngircd (0.7.7+HEAD-0ab6) unstable; urgency=low
+
+  * Incorporated actual CVS HEAD version which includes all features of
+    version 0.8.0-pre1 and patches for the resolver and logger.
+
+ -- Alexander Barton <alex@Arthur.Ath.CX>  Tue, 11 May 2004 02:18:50 +0200
+
+ngircd (0.7.7+HEAD-0ab5) unstable; urgency=low
+
+  * Updates from CVS HEAD branch, most notably: "INVITE- and BAN-lists
+    become synchronized between IRC+ servers when establishing new
+    connections, if the peer supports this as well."
+
+ -- Alexander Barton <alex@Arthur.Ath.CX>  Mon, 26 Apr 2004 01:53:15 +0200
+
+ngircd (0.7.7+HEAD-0ab4) unstable; urgency=low
+
+  * This version includes fixes for INVITE command and the handling of the
+    invite and ban lists from CVS-HEAD.
+
+ -- Alexander Barton <alex@Arthur.Ath.CX>  Fri,  9 Apr 2004 23:55:13 +0200
+
+ngircd (0.7.7+HEAD-0ab3) unstable; urgency=low
+
+  * Included MODE fix from CVS-HEAD branch.
+
+ -- Alexander Barton <alex@Arthur.Ath.CX>  Mon,  5 Apr 2004 13:09:24 +0200
+
+ngircd (0.7.7+HEAD-0ab2) unstable; urgency=low
+
+  * Incorporated more fixes and enhancements of CVS-HEAD version,
+    e. g. better connection logging and fixed TRACE command.
+
+ -- Alexander Barton <alex@Arthur.Ath.CX>  Sat, 28 Feb 2004 03:20:32 +0100
+
+ngircd (0.7.7+HEAD-0ab1) unstable; urgency=low
+
+  * New upstream version. This debian package includes all features of
+    ngIRCd 0.7.7 and changes of the CVS-HEAD development tree.
+
+ -- Alexander Barton <alex@Arthur.Ath.CX>  Thu,  5 Feb 2004 15:23:22 +0100
+
+ngircd (0.7.6+HEAD-0ab2) unstable; urgency=low
+
+  * Included new fixes and additions from the CVS-HEAD upstream branch,
+    e. g. the setting of type of service (TOS) on sockets.
+
+ -- Alexander Barton <alex@Arthur.Ath.CX>  Mon, 26 Jan 2004 04:05:41 +0100
+
+ngircd (0.7.6+HEAD-0ab1) unstable; urgency=low
+
+  * Included all changes from the CVS-HEAD upstream version.
+  * Restructured debian packaging system: now there are two packages, a
+    "standard" version that includes all the default options and a "full"
+    version that additionally includes support for TCP wrappers and IDENT
+    lookups.
+
+ -- Alexander Barton <alex@Arthur.Ath.CX>  Thu,  1 Jan 2004 23:12:11 +0100
+
+ngircd (0.7.6-0ab1) unstable; urgency=medium
+
+  * New upstream version.
+  * Changed version numvering scheme of debian package.
+
+ -- Alexander Barton <alex@Arthur.Ath.CX>  Fri,  5 Dec 2003 14:26:41 +0100
+
+ngircd (0.7.5-0.2ab) unstable; urgency=low
+
+  * Updated RPM and Debian package description and configuration.
+
+ -- Alexander Barton <alex@Arthur.Ath.CX>  Sat, 29 Nov 2003 21:24:32 +0100
+
+ngircd (0.7.5-0.1ab) unstable; urgency=low
+
+  * New upstream version.
+
+ -- Alexander Barton <alex@Arthur.Ath.CX>  Fri,  7 Nov 2003 21:59:58 +0100
+
+ngircd (0.7.1-0.1ab) unstable; urgency=low
+
+  * New upstream version :-)
+
+ -- Alexander Barton <alex@Arthur.Ath.CX>  Fri, 18 Jul 2003 22:53:02 +0200
+
+ngircd (0.7.0-0.7ab) unstable; urgency=low
+
+  * Fixed up post installation script (added interpreter, fixed chmod call).
+
+ -- Alexander Barton <alex@Arthur.Ath.CX>  Sun, 13 Jul 2003 00:52:38 +0200
+
+ngircd (0.7.0-0.6ab) unstable; urgency=low
+
+  * Added /etc/default/ngircd.
+  * Included own post installation script.
+
+ -- Alexander Barton <alex@Arthur.Ath.CX>  Sat, 12 Jul 2003 20:31:09 +0200
+
+ngircd (0.7.0-0.5ab) unstable; urgency=low
+
+  * Enhanced init script.
+  * Included NJOIN fix from actual CVS "HEAD" branch.
+
+ -- Alexander Barton <alex@Arthur.Ath.CX>  Wed,  9 Jul 2003 22:40:49 +0200
+
+ngircd (0.7.0-0.4ab) unstable; urgency=low
+
+  * Reverted use of dh_installexamples.
+
+ -- Alexander Barton <alex@Arthur.Ath.CX>  Thu, 22 May 2003 00:15:03 +0200
+
+ngircd (0.7.0-0.3ab) unstable; urgency=low
+
+  * Removed "debian/docs" and "debian/conffiles"; debhelper takes care of
+    this for us automagically.
+  * Excluded "etc/ngircd.conf" from dh_fixperms.
+
+ -- Alexander Barton <alex@Arthur.Ath.CX>  Wed, 21 May 2003 23:25:05 +0200
+
+ngircd (0.7.0-0.2ab) unstable; urgency=low
+
+  * Fixed wrong variable substitution in init script.
+  * Added some CVS "Id-Tags" (but not checked in, yet).
+  * Removed own "Provides:" from control file.
+
+ -- Alexander Barton <alex@barton.de>  Wed, 21 May 2003 12:32:34 +0200
+
+ngircd (0.7.0-0.1ab) unstable; urgency=low
+
+  * Initial Release.
+
+ -- Alexander Barton <alex@barton.de>  Wed, 21 May 2003 02:36:52 +0200

+ 1 - 0
contrib/Debian/compat

@@ -0,0 +1 @@
+4

+ 47 - 0
contrib/Debian/control

@@ -0,0 +1,47 @@
+Source: ngircd
+Section: net
+Priority: optional
+Maintainer: Alexander Barton <alex@barton.de>
+Build-Depends: debhelper (>> 4.0.0), libz-dev, libwrap-dev, libident-dev
+Standards-Version: 3.5.8
+
+Package: ngircd
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: A lightweight daemon for the Internet Relay Chat (IRC)
+ ngIRCd is a free open source daemon for the Internet Relay Chat (IRC)
+ network. It is written from scratch and is not based upon the original
+ IRCd like many others.
+ .
+ This package contains the "standard distribution", including support for
+ syslog logging and compressed server-links using zlib.
+ .
+ Advantages of ngIRCd:
+  - no problems with servers using changing/non-static IP addresses.
+  - small and lean configuration file.
+  - free, modern and open source C code.
+  - still under active development.
+ .
+ ngIRCd is compatible to the "original" ircd 2.10.3p3, so you can run
+ mixed networks.
+
+Package: ngircd-full
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Conflicts: ngircd
+Description: A lightweight daemon for the Internet Relay Chat (IRC)
+ ngIRCd is a free open source daemon for the Internet Relay Chat (IRC)
+ network. It is written from scratch and is not based upon the original
+ IRCd like many others.
+ .
+ This package includes support for TCP wrappers and IDENT requests in
+ addition to the features of the "standard package".
+ .
+ Advantages of ngIRCd:
+  - no problems with servers using changing/non-static IP addresses.
+  - small and lean configuration file.
+  - free, modern and open source C code.
+  - still under active development.
+ .
+ ngIRCd is compatible to the "original" ircd 2.10.3p3, so you can run
+ mixed networks.

+ 13 - 0
contrib/Debian/copyright

@@ -0,0 +1,13 @@
+This package was debianized by Alexander Barton <alex@barton.de> on
+Tue, 20 May 2003 15:47:40 +0200.
+
+It was downloaded from ftp://Arthur.Ath.CX/pub/Users/alex/ngircd/
+
+Upstream Author: Alexander Barton <alex@barton.de>
+
+This software is copyright (c) 1999-2003 by Alexander Barton.
+
+You are free to distribute this software under the terms of the
+GNU General Public License.
+On Debian systems, the complete text of the GNU General Public
+License can be found in /usr/share/common-licenses/GPL file.

+ 75 - 0
contrib/Debian/ngircd.init

@@ -0,0 +1,75 @@
+#!/bin/sh
+#
+# ngIRCd start and stop script for Debian-based systems
+#
+# $Id: ngircd.init,v 1.5.2.1 2005/07/26 19:30:54 alex Exp $
+#
+
+PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+DAEMON=/usr/sbin/ngircd
+NAME=ngIRCd
+DESC="IRC daemon"
+PARAMS=""
+
+test -h "$0" && me=`readlink $0` || me="$0"
+BASENAME=`basename $me`
+
+test -f /etc/default/$BASENAME && . /etc/default/$BASENAME
+
+test -x $DAEMON || exit 0
+
+Check_Config()
+{
+	$DAEMON --configtest >/dev/null 2>&1
+	if [ $? -ne 0 ]; then
+		echo "Configuration of $NAME is not valide, won't (re)start!"
+		echo "Please run \"$DAEMON --configtest\" manually and fix it up ..."
+		exit 1
+	fi
+}
+
+Try_Start()
+{
+	[ ! -d /var/run/ircd ] || chown irc:irc /var/run/ircd
+	start-stop-daemon --start --quiet --exec $DAEMON -- $PARAMS
+	if [ $? -ne 0 ]; then
+		echo "$NAME failed!"
+		exit 1
+	fi
+	echo "$NAME."
+}
+
+case "$1" in
+  start)
+	Check_Config
+	echo -n "Starting $DESC: "
+	Try_Start
+	;;
+  stop)
+	echo -n "Stopping $DESC: "
+	start-stop-daemon --stop --quiet --pidfile /var/run/ircd/ngircd.pid --exec $DAEMON \
+	  && echo "$NAME." \
+	  || echo "(none running)"
+	;;
+  reload|force-reload)
+	Check_Config
+	echo "Reloading $DESC configuration files."
+	start-stop-daemon --stop --signal 1 --quiet --exec $DAEMON
+	;;
+  restart)
+	Check_Config
+	echo -n "Restarting $DESC: "
+	start-stop-daemon --stop --quiet --oknodo --exec $DAEMON
+	sleep 1
+	Try_Start
+	;;
+  *)
+	N=/etc/init.d/$NAME
+	echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2
+	exit 1
+	;;
+esac
+
+exit 0
+
+# -eof-

+ 14 - 0
contrib/Debian/ngircd.postinst

@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# Debian post-installation script
+# $Id: ngircd.postinst,v 1.1 2003/12/31 17:20:11 alex Exp $
+#
+
+if [ -f /etc/ngircd/ngircd.conf ]; then
+	# make sure that configuration file is not world readable
+	chmod o= /etc/ngircd/ngircd.conf
+fi
+
+#DEBHELPER#
+
+# -eof-

+ 172 - 0
contrib/Debian/rules

@@ -0,0 +1,172 @@
+#!/usr/bin/make -f
+#
+# ngIRCd -- The Next Generation IRC Daemon
+# Copyright (c)2001-2003 by Alexander Barton (alex@barton.de)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# Please read the file COPYING, README and AUTHORS for more information.
+#
+# debian/rules for ngIRCd
+#
+# $Id: rules,v 1.3 2005/02/07 23:09:31 alex Exp $
+#
+# Based on the sample debian/rules that uses debhelper,
+# GNU copyright 1997 to 1999 by Joey Hess.
+#
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+# These are used for cross-compiling and for saving the configure script
+# from having to guess our platform (since we know it already)
+DEB_HOST_GNU_TYPE  ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
+DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
+
+CFLAGS = -Wall -g
+
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+	CFLAGS += -O0
+else
+	CFLAGS += -O2
+endif
+ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
+	INSTALL_PROGRAM += -s
+endif
+
+configure-ngircd: configure
+	dh_testdir
+	
+	# configure "standard" variant:
+	./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) \
+	  --prefix=/usr \
+	  --sysconfdir=/etc/ngircd \
+	  --mandir=\$${prefix}/share/man \
+	  --with-syslog --with-zlib
+
+configure-ngircd-full: configure
+	dh_testdir
+	
+	# configure "full" variant:
+	./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) \
+	  --prefix=/usr \
+	  --sysconfdir=/etc/ngircd \
+	  --mandir=\$${prefix}/share/man \
+	  --with-syslog --with-zlib --with-tcp-wrappers --with-ident
+
+build:
+	dh_clean -k
+
+build-ngircd: build-stamp-ngircd
+build-stamp-ngircd: configure-ngircd
+	dh_testdir
+	rm -f build-stamp-*
+	
+	# Add here commands to compile the "standard" package:
+	$(MAKE)
+	
+	touch build-stamp-ngircd
+
+build-ngircd-full: build-stamp-ngircd-full
+build-stamp-ngircd-full: configure-ngircd-full
+	dh_testdir
+	rm -f build-stamp-*
+	
+	# Add here commands to compile the "full" package:
+	$(MAKE)
+	
+	touch build-stamp-ngircd-full
+
+clean:
+	dh_testdir
+	dh_testroot
+	rm -f build-stamp*
+	rm -f $(CURDIR)/debian/ngircd-full.default
+	rm -f $(CURDIR)/debian/ngircd-full.init
+	rm -f $(CURDIR)/debian/ngircd-full.postinst
+	
+	# Add here commands to clean up after the build process:
+	-$(MAKE) clean
+	
+ifneq "$(wildcard /usr/share/misc/config.sub)" ""
+	cp -f /usr/share/misc/config.sub config.sub
+endif
+ifneq "$(wildcard /usr/share/misc/config.guess)" ""
+	cp -f /usr/share/misc/config.guess config.guess
+endif
+	dh_clean
+
+install: install-ngircd install-ngircd-full
+
+install-ngircd: build-ngircd
+	dh_testdir
+	dh_testroot
+	dh_installdirs
+	
+	# Add here commands to install the "standard" package into debian/ngircd:
+	$(MAKE) install DESTDIR=$(CURDIR)/debian/ngircd
+	rm $(CURDIR)/debian/ngircd/usr/share/doc/ngircd/INSTALL*
+	rm $(CURDIR)/debian/ngircd/usr/share/doc/ngircd/COPYING*
+	mkdir -p $(CURDIR)/debian/ngircd/var/run/ircd
+	cat $(CURDIR)/debian/ngircd/usr/share/doc/ngircd/sample-ngircd.conf | \
+	 sed -e "s/;ServerUID = 65534/ServerUID = irc/g" | \
+	 sed -e "s/;ServerGID = 65534/ServerGID = irc/g" | \
+	 sed -e "s/;MotdFile = \/usr\/local\/etc\/ngircd.motd/MotdFile = \/etc\/ngircd\/ngircd.motd/g" | \
+	 sed -e "s/;PidFile = \/var\/run\/ngircd\/ngircd.pid/PidFile = \/var\/run\/ircd\/ngircd.pid/g" \
+	 >$(CURDIR)/debian/ngircd/etc/ngircd/ngircd.conf
+	touch $(CURDIR)/debian/ngircd/etc/ngircd/ngircd.motd
+
+install-ngircd-full: build-ngircd-full
+	dh_testdir
+	dh_testroot
+	dh_installdirs
+	
+	# Add here commands to install the "full" package into debian/ngircd-full:
+	$(MAKE) install DESTDIR=$(CURDIR)/debian/ngircd-full
+	rm $(CURDIR)/debian/ngircd-full/usr/share/doc/ngircd/INSTALL*
+	rm $(CURDIR)/debian/ngircd-full/usr/share/doc/ngircd/COPYING*
+	mv $(CURDIR)/debian/ngircd-full/usr/share/doc/ngircd \
+	 $(CURDIR)/debian/ngircd-full/usr/share/doc/ngircd-full
+	mkdir -p $(CURDIR)/debian/ngircd-full/var/run/ircd
+	cat $(CURDIR)/debian/ngircd-full/usr/share/doc/ngircd-full/sample-ngircd.conf | \
+	 sed -e "s/;ServerUID = 65534/ServerUID = irc/g" | \
+	 sed -e "s/;ServerGID = 65534/ServerGID = irc/g" | \
+	 sed -e "s/;MotdFile = \/usr\/local\/etc\/ngircd.motd/MotdFile = \/etc\/ngircd\/ngircd.motd/g" | \
+	 sed -e "s/;PidFile = \/var\/run\/ngircd\/ngircd.pid/PidFile = \/var\/run\/ircd\/ngircd.pid/g" \
+	 >$(CURDIR)/debian/ngircd-full/etc/ngircd/ngircd.conf
+	touch $(CURDIR)/debian/ngircd-full/etc/ngircd/ngircd.motd
+
+# Build architecture-independent files here.
+binary-indep:
+	# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+	ln -s $(CURDIR)/debian/ngircd.default \
+	 $(CURDIR)/debian/ngircd-full.default
+	ln -s $(CURDIR)/debian/ngircd.init \
+	 $(CURDIR)/debian/ngircd-full.init
+	ln -s $(CURDIR)/debian/ngircd.postinst \
+	 $(CURDIR)/debian/ngircd-full.postinst
+	
+	dh_testdir
+	dh_testroot
+	dh_installchangelogs -a -A ChangeLog
+	dh_installdocs -a
+	dh_installinit -a
+	dh_strip -a
+	dh_compress -a
+	dh_fixperms -a
+	dh_installdeb -a
+	dh_shlibdeps -a
+	dh_gencontrol -a
+	dh_md5sums -a
+	dh_builddeb -a
+
+binary: binary-indep binary-arch
+
+.PHONY: build clean binary-indep binary-arch binary install 
+
+# -eof-

+ 20 - 0
contrib/MacOSX/Makefile.am

@@ -0,0 +1,20 @@
+#
+# ngIRCd -- The Next Generation IRC Daemon
+# Copyright (c)2001-2004 Alexander Barton <alex@barton.de>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# Please read the file COPYING, README and AUTHORS for more information.
+#
+# $Id: Makefile.am,v 1.2 2004/05/11 00:34:26 alex Exp $
+#
+
+clean-local:
+	rm -rf build
+
+maintainer-clean-local:
+	rm -f Makefile Makefile.in
+
+# -eof-

+ 283 - 0
contrib/MacOSX/Makefile.in

@@ -0,0 +1,283 @@
+# Makefile.in generated by automake 1.7.9 from Makefile.am.
+# @configure_input@
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# ngIRCd -- The Next Generation IRC Daemon
+# Copyright (c)2001-2004 Alexander Barton <alex@barton.de>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# Please read the file COPYING, README and AUTHORS for more information.
+#
+# $Id: Makefile.am,v 1.2 2004/05/11 00:34:26 alex Exp $
+#
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../..
+
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_triplet = @host@
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+U = @U@
+VERSION = @VERSION@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+subdir = contrib/MacOSX
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/src/config.h
+CONFIG_CLEAN_FILES =
+DIST_SOURCES =
+DIST_COMMON = $(srcdir)/Makefile.in Makefile.am
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  Makefile.am  $(top_srcdir)/configure.in $(ACLOCAL_M4)
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  contrib/MacOSX/Makefile
+Makefile:  $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
+uninstall-info-am:
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ../..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkinstalldirs) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile
+
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-local mostlyclean-am
+
+distclean: distclean-am
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic \
+	maintainer-clean-local
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+.PHONY: all all-am check check-am clean clean-generic clean-local \
+	distclean distclean-generic distdir dvi dvi-am info info-am \
+	install install-am install-data install-data-am install-exec \
+	install-exec-am install-info install-info-am install-man \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic \
+	maintainer-clean-local mostlyclean mostlyclean-generic pdf \
+	pdf-am ps ps-am uninstall uninstall-am uninstall-info-am
+
+
+clean-local:
+	rm -rf build
+
+maintainer-clean-local:
+	rm -f Makefile Makefile.in
+
+# -eof-
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:

+ 22 - 0
contrib/Makefile.am

@@ -0,0 +1,22 @@
+#
+# ngIRCd -- The Next Generation IRC Daemon
+# Copyright (c)2001-2004 Alexander Barton <alex@barton.de>
+#
+# Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen
+# der GNU General Public License (GPL), wie von der Free Software Foundation
+# herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2
+# der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version.
+# Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
+# der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
+#
+# $Id: Makefile.am,v 1.4 2004/04/28 12:18:02 alex Exp $
+#
+
+SUBDIRS = Debian MacOSX
+
+EXTRA_DIST = README ngircd.spec systrace.policy
+
+maintainer-clean-local:
+	rm -f Makefile Makefile.in
+
+# -eof-

+ 433 - 0
contrib/Makefile.in

@@ -0,0 +1,433 @@
+# Makefile.in generated by automake 1.7.9 from Makefile.am.
+# @configure_input@
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# ngIRCd -- The Next Generation IRC Daemon
+# Copyright (c)2001-2004 Alexander Barton <alex@barton.de>
+#
+# Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen
+# der GNU General Public License (GPL), wie von der Free Software Foundation
+# herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2
+# der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version.
+# Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
+# der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
+#
+# $Id: Makefile.am,v 1.4 2004/04/28 12:18:02 alex Exp $
+#
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_triplet = @host@
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+U = @U@
+VERSION = @VERSION@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+
+SUBDIRS = Debian MacOSX
+
+EXTRA_DIST = README ngircd.spec systrace.policy
+subdir = contrib
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/src/config.h
+CONFIG_CLEAN_FILES =
+DIST_SOURCES =
+
+RECURSIVE_TARGETS = info-recursive dvi-recursive pdf-recursive \
+	ps-recursive install-info-recursive uninstall-info-recursive \
+	all-recursive install-data-recursive install-exec-recursive \
+	installdirs-recursive install-recursive uninstall-recursive \
+	check-recursive installcheck-recursive
+DIST_COMMON = README $(srcdir)/Makefile.in Makefile.am
+DIST_SUBDIRS = $(SUBDIRS)
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  Makefile.am  $(top_srcdir)/configure.in $(ACLOCAL_M4)
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  contrib/Makefile
+Makefile:  $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
+uninstall-info-am:
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+	@set fnord $$MAKEFLAGS; amf=$$2; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	   || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+	@set fnord $$MAKEFLAGS; amf=$$2; \
+	dot_seen=no; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	rev=''; for subdir in $$list; do \
+	  if test "$$subdir" = "."; then :; else \
+	    rev="$$subdir $$rev"; \
+	  fi; \
+	done; \
+	rev="$$rev ."; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	   || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+ctags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+	done
+
+ETAGS = etags
+ETAGSFLAGS =
+
+CTAGS = ctags
+CTAGSFLAGS =
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	if (etags --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	else \
+	  include_option=--include; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -f $$subdir/TAGS && \
+	      tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(ETAGS_ARGS)$$tags$$unique" \
+	  || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	     $$tags $$unique
+
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkinstalldirs) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -d $(distdir)/$$subdir \
+	    || mkdir $(distdir)/$$subdir \
+	    || exit 1; \
+	    (cd $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$(top_distdir)" \
+	        distdir=../$(distdir)/$$subdir \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-recursive
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic \
+	maintainer-clean-local
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+uninstall-info: uninstall-info-recursive
+
+.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am clean \
+	clean-generic clean-recursive ctags ctags-recursive distclean \
+	distclean-generic distclean-recursive distclean-tags distdir \
+	dvi dvi-am dvi-recursive info info-am info-recursive install \
+	install-am install-data install-data-am install-data-recursive \
+	install-exec install-exec-am install-exec-recursive \
+	install-info install-info-am install-info-recursive install-man \
+	install-recursive install-strip installcheck installcheck-am \
+	installdirs installdirs-am installdirs-recursive \
+	maintainer-clean maintainer-clean-generic \
+	maintainer-clean-local maintainer-clean-recursive mostlyclean \
+	mostlyclean-generic mostlyclean-recursive pdf pdf-am \
+	pdf-recursive ps ps-am ps-recursive tags tags-recursive \
+	uninstall uninstall-am uninstall-info-am \
+	uninstall-info-recursive uninstall-recursive
+
+
+maintainer-clean-local:
+	rm -f Makefile Makefile.in
+
+# -eof-
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:

+ 27 - 0
contrib/README

@@ -0,0 +1,27 @@
+
+                     ngIRCd - Next Generation IRC Server
+
+                      (c)2001-2004 by Alexander Barton,
+                    alex@barton.de, http://www.barton.de/
+
+               ngIRCd is free software and published under the
+                   terms of the GNU General Public License.
+
+                            -- Contributions --
+
+
+MacOSX/
+ - Project file for XCode "project builder" of Mac OS X.
+
+Debian/
+ - Various files for building Debian packages.
+
+ngircd.spec
+ - RPM "spec" file.
+
+systrace.policy
+ - Systrace policy file for OpenBSD (and probably NetBSD).
+
+
+--
+$Id: README,v 1.1 2004/04/28 12:18:50 alex Exp $

+ 55 - 0
contrib/ngircd.spec

@@ -0,0 +1,55 @@
+%define name    ngircd
+%define version 0.9.2
+%define release 1
+%define prefix  %{_prefix}
+
+Summary:      A lightweight daemon for the Internet Relay Chat (IRC)
+Name:         %{name}
+Version:      %{version}
+Release:      %{release}
+Copyright:    GPL
+Group:        Networking/Daemons
+URL:          http://arthur.ath.cx/~alex/ngircd/
+Source:       %{name}-%{version}.tar.gz
+Packager:     Sean Reifschneider <jafo-rpms@tummy.com>
+BuildRoot:    /var/tmp/%{name}-root
+
+%description
+ngIRCd is a free open source daemon for the Internet Relay Chat (IRC),
+developed under the GNU General Public License (GPL). It's written from
+scratch and is not based upon the original IRCd like many others.
+
+Advantages:
+ - no problems with servers using changing/non-static IP addresses.
+ - small and lean configuration file.
+ - free, modern and open source C code.
+ - still under active development.
+
+ngIRCd is compatible to the "original" ircd 2.10.3p3, so you can run
+mixed networks.
+
+%prep
+%setup
+%build
+%configure
+make
+
+%install
+[ -n "$RPM_BUILD_ROOT" -a "$RPM_BUILD_ROOT" != / ] && rm -rf "$RPM_BUILD_ROOT"
+%makeinstall
+(
+   cd "$RPM_BUILD_ROOT"
+   ( cd usr/sbin; mv *-ngircd ngircd )
+   ( cd usr/share/man/man5; mv *-ngircd.conf.5 ngircd.conf.5 )
+   ( cd usr/share/man/man8; mv *-ngircd.8 ngircd.8 )
+)
+
+%clean
+[ -n "$RPM_BUILD_ROOT" -a "$RPM_BUILD_ROOT" != / ] && rm -rf "$RPM_BUILD_ROOT"
+
+%files
+%defattr(755,root,root)
+%doc AUTHORS  COPYING  ChangeLog  INSTALL NEWS  README
+%config(noreplace) /etc
+%{_prefix}/sbin
+%{_prefix}/share/man/

+ 77 - 0
contrib/systrace.policy

@@ -0,0 +1,77 @@
+#
+# Sample systrace policy for ngIRCd on OpenBSD
+# Author: Benjamin Pineau <ben@zouh.org>
+#
+# $Id: systrace.policy,v 1.1 2004/04/28 12:16:59 alex Exp $
+#
+# Tune me, put me in /etc/systrace/usr_local_bin_ngircd and start ngIRCd
+# (with root privileges) as:
+#
+#   systrace -a /usr/local/bin/ngircd
+#
+# I didn't tried this on NetBSD, but it should work as is.
+#
+# On systems with pf, it can be supplemented by strict firewall rules:
+# for a ngircd running as '$ircuser', binding on '$ircport' and accepting
+# 30 connections:
+#
+#   block out log quick proto tcp from any port $ircport to any \
+#    user != $ircuser
+#   pass in inet proto tcp from any to any port $ircport user $ircuser \
+#    keep state (max 30) flags S/SA
+#
+
+Policy: /usr/local/bin/ngircd, Emulation: native
+	native-__sysctl: permit
+	native-fsread: filename eq "/etc/malloc.conf" then permit
+	native-fsread: filename sub "/usr/share/zoneinfo/" then permit
+	native-fsread: filename eq "/usr/local/etc/ngircd.conf" then permit
+	native-fsread: filename eq "/usr/local/etc/ngircd.motd" then permit
+	native-fsread: filename eq "/etc/ngircd.conf" then permit
+	native-fsread: filename eq "/etc/ngircd.motd" then permit
+	native-fsread: filename eq "/etc/spwd.db" then deny[eperm]
+	native-fsread: filename eq "/etc/group" then permit
+	native-fsread: filename eq "/etc/resolv.conf" then permit
+	native-fsread: filename eq "/etc/localtime" then permit
+	native-fsread: filename eq "/etc/hosts" then permit
+	native-fsread: filename sub "<non-existent filename>" then deny[enoent]
+	native-socket: sockdom eq "AF_UNIX" and socktype eq "SOCK_DGRAM" then permit
+	native-socket: sockdom eq "AF_INET" and socktype eq "SOCK_STREAM" then permit
+	native-bind: sockaddr match "inet-*:6667" then permit, if user != root
+	native-connect: sockaddr eq "/dev/log" then permit, if user != root
+	native-connect: sockaddr match "inet-*:53" then permit, if user != root
+	native-setsockopt: permit, if user != root
+	native-listen: permit, if user != root
+	native-accept: permit, if user != root
+	native-sendto: true then permit, if user != root
+	native-recvfrom: permit, if user != root
+	native-read: permit
+	native-pread: permit
+	native-write: permit, if user != root
+	native-mmap: permit
+	native-munmap: permit
+	native-mprotect: permit
+	native-break: permit
+	native-umask: permit
+	native-fork: permit
+	native-setsid: permit
+	native-chdir: permit
+	native-chroot: permit
+	native-setgid: gid neq "0" then permit
+	native-setuid: uid neq "0" and uname neq "root" then permit
+	native-getuid: permit
+	native-getgid: permit
+	native-gettimeofday: permit
+	native-getpid: permit
+	native-select: permit
+	native-fcntl: permit
+	native-fstat: permit
+	native-issetugid: permit
+	native-sigaction: permit
+	native-pipe: permit
+	native-sigreturn: permit
+	native-close: permit
+	native-exit: permit
+	native-fswrite: deny[eperm]
+
+# -eof-

+ 479 - 0
depcomp

@@ -0,0 +1,479 @@
+#! /bin/sh
+
+# depcomp - compile a program generating dependencies as side-effects
+# Copyright 1999, 2000, 2003 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+  echo "depcomp: Variables source, object and depmode must be set" 1>&2
+  exit 1
+fi
+# `libtool' can also be set to `yes' or `no'.
+
+if test -z "$depfile"; then
+   base=`echo "$object" | sed -e 's,^.*/,,' -e 's,\.\([^.]*\)$,.P\1,'`
+   dir=`echo "$object" | sed 's,/.*$,/,'`
+   if test "$dir" = "$object"; then
+      dir=
+   fi
+   # FIXME: should be _deps on DOS.
+   depfile="$dir.deps/$base"
+fi
+
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Some modes work just like other modes, but use different flags.  We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write.  Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+  # HP compiler uses -M and no extra arg.
+  gccflag=-M
+  depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+   # This is just like dashmstdout with a different argument.
+   dashmflag=-xM
+   depmode=dashmstdout
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want.  Yay!  Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff.  Hmm.
+  "$@" -MT "$object" -MD -MP -MF "$tmpdepfile"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  mv "$tmpdepfile" "$depfile"
+  ;;
+
+gcc)
+## There are various ways to get dependency output from gcc.  Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+##   up in a subdir.  Having to rename by hand is ugly.
+##   (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+##   -MM, not -M (despite what the docs say).
+## - Using -M directly means running the compiler twice (even worse
+##   than renaming).
+  if test -z "$gccflag"; then
+    gccflag=-MD,
+  fi
+  "$@" -Wp,"$gccflag$tmpdepfile"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+## The second -e expression handles DOS-style file names with drive letters.
+  sed -e 's/^[^:]*: / /' \
+      -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the `deleted header file' problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header).  We avoid this by adding
+## dummy dependencies for each header file.  Too bad gcc doesn't do
+## this for us directly.
+  tr ' ' '
+' < "$tmpdepfile" |
+## Some versions of gcc put a space before the `:'.  On the theory
+## that the space means something, we add a space to the output as
+## well.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+hp)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+sgi)
+  if test "$libtool" = yes; then
+    "$@" "-Wp,-MDupdate,$tmpdepfile"
+  else
+    "$@" -MDupdate "$tmpdepfile"
+  fi
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+
+  if test -f "$tmpdepfile"; then  # yes, the sourcefile depend on other files
+    echo "$object : \\" > "$depfile"
+
+    # Clip off the initial element (the dependent).  Don't try to be
+    # clever and replace this with sed code, as IRIX sed won't handle
+    # lines with more than a fixed number of characters (4096 in
+    # IRIX 6.2 sed, 8192 in IRIX 6.5).  We also remove comment lines;
+    # the IRIX cc adds comments like `#:fec' to the end of the
+    # dependency line.
+    tr ' ' '
+' < "$tmpdepfile" \
+    | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
+    tr '
+' ' ' >> $depfile
+    echo >> $depfile
+
+    # The second pass generates a dummy entry for each header file.
+    tr ' ' '
+' < "$tmpdepfile" \
+   | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+   >> $depfile
+  else
+    # The sourcefile does not contain any dependencies, so just
+    # store a dummy comment line, to avoid errors with the Makefile
+    # "include basename.Plo" scheme.
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile"
+  ;;
+
+aix)
+  # The C for AIX Compiler uses -M and outputs the dependencies
+  # in a .u file.  In older versions, this file always lives in the
+  # current directory.  Also, the AIX compiler puts `$object:' at the
+  # start of each line; $object doesn't have directory information.
+  # Version 6 uses the directory in both cases.
+  stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'`
+  tmpdepfile="$stripped.u"
+  if test "$libtool" = yes; then
+    "$@" -Wc,-M
+  else
+    "$@" -M
+  fi
+  stat=$?
+
+  if test -f "$tmpdepfile"; then :
+  else
+    stripped=`echo "$stripped" | sed 's,^.*/,,'`
+    tmpdepfile="$stripped.u"
+  fi
+
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+
+  if test -f "$tmpdepfile"; then
+    outname="$stripped.o"
+    # Each line is of the form `foo.o: dependent.h'.
+    # Do two passes, one to just change these to
+    # `$object: dependent.h' and one to simply `dependent.h:'.
+    sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile"
+    sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile"
+  else
+    # The sourcefile does not contain any dependencies, so just
+    # store a dummy comment line, to avoid errors with the Makefile
+    # "include basename.Plo" scheme.
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile"
+  ;;
+
+icc)
+  # Intel's C compiler understands `-MD -MF file'.  However on
+  #    icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
+  # ICC 7.0 will fill foo.d with something like
+  #    foo.o: sub/foo.c
+  #    foo.o: sub/foo.h
+  # which is wrong.  We want:
+  #    sub/foo.o: sub/foo.c
+  #    sub/foo.o: sub/foo.h
+  #    sub/foo.c:
+  #    sub/foo.h:
+  # ICC 7.1 will output
+  #    foo.o: sub/foo.c sub/foo.h
+  # and will wrap long lines using \ :
+  #    foo.o: sub/foo.c ... \
+  #     sub/foo.h ... \
+  #     ...
+
+  "$@" -MD -MF "$tmpdepfile"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  # Each line is of the form `foo.o: dependent.h',
+  # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
+  # Do two passes, one to just change these to
+  # `$object: dependent.h' and one to simply `dependent.h:'.
+  sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
+  # Some versions of the HPUX 10.20 sed can't process this invocation
+  # correctly.  Breaking it into two sed invocations is a workaround.
+  sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
+    sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+tru64)
+   # The Tru64 compiler uses -MD to generate dependencies as a side
+   # effect.  `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
+   # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+   # dependencies in `foo.d' instead, so we check for that too.
+   # Subdirectories are respected.
+   dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+   test "x$dir" = "x$object" && dir=
+   base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+
+   if test "$libtool" = yes; then
+      tmpdepfile1="$dir.libs/$base.lo.d"
+      tmpdepfile2="$dir.libs/$base.d"
+      "$@" -Wc,-MD
+   else
+      tmpdepfile1="$dir$base.o.d"
+      tmpdepfile2="$dir$base.d"
+      "$@" -MD
+   fi
+
+   stat=$?
+   if test $stat -eq 0; then :
+   else
+      rm -f "$tmpdepfile1" "$tmpdepfile2"
+      exit $stat
+   fi
+
+   if test -f "$tmpdepfile1"; then
+      tmpdepfile="$tmpdepfile1"
+   else
+      tmpdepfile="$tmpdepfile2"
+   fi
+   if test -f "$tmpdepfile"; then
+      sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+      # That's a tab and a space in the [].
+      sed -e 's,^.*\.[a-z]*:[	 ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+   else
+      echo "#dummy" > "$depfile"
+   fi
+   rm -f "$tmpdepfile"
+   ;;
+
+#nosideeffect)
+  # This comment above is used by automake to tell side-effect
+  # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout, regardless of -o.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test $1 != '--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  # Remove `-o $object'.
+  IFS=" "
+  for arg
+  do
+    case $arg in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    *)
+      set fnord "$@" "$arg"
+      shift # fnord
+      shift # $arg
+      ;;
+    esac
+  done
+
+  test -z "$dashmflag" && dashmflag=-M
+  # Require at least two characters before searching for `:'
+  # in the target name.  This is to cope with DOS-style filenames:
+  # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
+  "$@" $dashmflag |
+    sed 's:^[  ]*[^: ][^:][^:]*\:[    ]*:'"$object"'\: :' > "$tmpdepfile"
+  rm -f "$depfile"
+  cat < "$tmpdepfile" > "$depfile"
+  tr ' ' '
+' < "$tmpdepfile" | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+dashXmstdout)
+  # This case only exists to satisfy depend.m4.  It is never actually
+  # run, as this mode is specially recognized in the preamble.
+  exit 1
+  ;;
+
+makedepend)
+  "$@" || exit $?
+  # Remove any Libtool call
+  if test "$libtool" = yes; then
+    while test $1 != '--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+  # X makedepend
+  shift
+  cleared=no
+  for arg in "$@"; do
+    case $cleared in
+    no)
+      set ""; shift
+      cleared=yes ;;
+    esac
+    case "$arg" in
+    -D*|-I*)
+      set fnord "$@" "$arg"; shift ;;
+    # Strip any option that makedepend may not understand.  Remove
+    # the object too, otherwise makedepend will parse it as a source file.
+    -*|$object)
+      ;;
+    *)
+      set fnord "$@" "$arg"; shift ;;
+    esac
+  done
+  obj_suffix="`echo $object | sed 's/^.*\././'`"
+  touch "$tmpdepfile"
+  ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
+  rm -f "$depfile"
+  cat < "$tmpdepfile" > "$depfile"
+  sed '1,2d' "$tmpdepfile" | tr ' ' '
+' | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile" "$tmpdepfile".bak
+  ;;
+
+cpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test $1 != '--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  # Remove `-o $object'.
+  IFS=" "
+  for arg
+  do
+    case $arg in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    *)
+      set fnord "$@" "$arg"
+      shift # fnord
+      shift # $arg
+      ;;
+    esac
+  done
+
+  "$@" -E |
+    sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
+    sed '$ s: \\$::' > "$tmpdepfile"
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  cat < "$tmpdepfile" >> "$depfile"
+  sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+msvisualcpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout, regardless of -o,
+  # because we must use -o when running libtool.
+  "$@" || exit $?
+  IFS=" "
+  for arg
+  do
+    case "$arg" in
+    "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
+	set fnord "$@"
+	shift
+	shift
+	;;
+    *)
+	set fnord "$@" "$arg"
+	shift
+	shift
+	;;
+    esac
+  done
+  "$@" -E |
+  sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::	\1 \\:p' >> "$depfile"
+  echo "	" >> "$depfile"
+  . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+none)
+  exec "$@"
+  ;;
+
+*)
+  echo "Unknown depmode $depmode" 1>&2
+  exit 1
+  ;;
+esac
+
+exit 0

+ 56 - 0
doc/CVS.txt

@@ -0,0 +1,56 @@
+
+                     ngIRCd - Next Generation IRC Server
+
+                      (c)2001-2003 by Alexander Barton,
+                    alex@barton.de, http://www.barton.de/
+
+               ngIRCd is free software and published under the
+                   terms of the GNU General Public License.
+
+                                 -- CVS.txt --
+
+
+The source code of ngIRCd is maintained using the "Concurrent Versions
+System" (CVS). Thereby several developers can work with the source tree at
+the same time.
+
+
+I. Anonymous read-only Access
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+To access the source tree anonymously in read-only mode, follow these steps:
+
+Login to the CVS server:
+
+ $ cvs -d:pserver:anonymous@arthur.ath.cx:/usr/local/CVS/ngircd login
+
+Use "anonymous" as user name and no password (just hit Return). Now you can
+check out the sources:
+
+ $ cvs -d:pserver:anonymous@arthur.ath.cx:/usr/local/CVS/ngircd checkout ngircd
+
+Thereby a new folder "ngircd" will be created containing all the individual
+source files.
+
+This is the "working folder", all CVS commands will be executed from within
+this folder in the future.
+
+Please note: When checking out a fresh copy of ngIRCd from CVS, the
+configure script doesn't exist; you have to run the autogen.sh shell script
+(which is included in the source tree) to generate it. This requires you to
+have GNU automake and GNU autoconf installed on your system.
+
+Updating the CVS tree:
+
+ $ cvs update -d -P [<filename>]
+
+You can update a single file or the complete source tree.
+
+
+III. Write Access
+~~~~~~~~~~~~~~~~~
+If you want to contribute a couple of patches and write access to the CVS
+repository would be handy, please contact Alex Barton, <alex@barton.de>.
+
+
+-- 
+$Id: CVS.txt,v 1.7 2003/03/26 22:34:33 alex Exp $

+ 79 - 0
doc/FAQ.txt

@@ -0,0 +1,79 @@
+
+                     ngIRCd - Next Generation IRC Server
+
+                      (c)2001-2003 by Alexander Barton,
+                    alex@barton.de, http://www.barton.de/
+
+               ngIRCd is free software and published under the
+                   terms of the GNU General Public License.
+
+                    -- FAQ: Frequently Asked Questions --
+
+
+I. General
+~~~~~~~~~~
+Q: Is it possible to link the ngIRCd with non-ngIRCd servers?
+A: Yes. ngIRCd is compatible to the original ircd used by IRCNet. Actually
+   this is being tested with version 2.10.3p3.
+
+Q: Is there a homepage with further information and downloads?
+A: Yes. Please visit <http://ngircd.barton.de/>.
+
+Q: Why should I use ngIRCd instead of the original one?
+A: ngIRCd offers several benefits: no problems with dynamic IPs, easy to
+   configure, open source (GPL), under active development.
+
+
+II. Compilation
+~~~~~~~~~~~~~~~
+Q: I did a "CVS checkout" but can't execute ./configure because the script
+   is missing in the generated directory!?
+A: When using development versions via CVS, the configure script as well as
+   the Makefile.in templates must be generated using GNU automake and GNU
+   autoconf. To simplify this task run the ./autogen.sh script which will
+   execute the required tools for you; then continue with executing the
+   ./configure script as usual.
+
+Q: The ./autogen.sh script complains "aclocal: command not found".
+A: GNU automake is missing on your system but required for building CVS
+   versions of ngIRCd. Install GNU automake 1.6 or later and try again.
+
+Q: The ./autogen.sh script stops with "autoheader: command not found".
+A: GNU autoconf is missing on your system but required for building CVS
+   versions of ngIRCd. Install GNU autoconf 2.52 or later and try again.
+
+Q: The ./autogen.sh script fails and the message "automake: configure.in:
+   AM_INIT_AUTOMAKE must be used" is displayed.
+A: Most probably you are using version 1.5 of GNU automake which seems to be
+   incompatible to the build system of ngIRCd. Solution: upgrade to at least
+   version 1.6 of GNU automake.
+   (If you are using Debian 3.0 "Woody" you can try to downgrade to version
+   1.4 of GNU automake shipped with this distribution; it should work, too.)
+
+
+III. Runtime
+~~~~~~~~~~~~
+
+Q: I cannot connect to remote peers when I use the chroot option, the
+   following is logged: "Can't resolve example.com: unknown error!".
+A: On Linux/glibc with chroot enabled you need to put some libraries inside
+   the chroot as well, notably libnss_dns; maybe others. Unfortunately, even
+   linking ngircd statically does not help this. The only known workaround
+   is to either disable chroot support or to link against dietlibc instead
+   of glibc. (tnx to Sebastian Siewior)
+
+
+IV. Bugs!?
+~~~~~~~~~~
+Q: Is there a list of known bugs and desired feature enhancements?
+A: Yes. Have a look at the bug tracking system (Bugzilla) for ngIRCd located
+   at <http://ngircd.barton.de/bugzilla/index.cgi>. There you can file bug
+   reports and feature requests as well as search the bug database.
+
+Q: What should I do if I found a bug?
+A: Please file a bug report at <http://ngircd.barton.de/bugzilla/index.cgi>!
+   The author of the particular component will be notified automagically :-)
+
+
+-- 
+$Id: FAQ.txt,v 1.7.4.1 2005/07/09 14:41:39 alex Exp $

+ 42 - 0
doc/Makefile.am

@@ -0,0 +1,42 @@
+#
+# ngIRCd -- The Next Generation IRC Daemon
+# Copyright (c)2001-2003 by Alexander Barton (alex@barton.de)
+#
+# Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen
+# der GNU General Public License (GPL), wie von der Free Software Foundation
+# herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2
+# der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version.
+# Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
+# der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
+#
+# $Id: Makefile.am,v 1.18 2005/04/27 07:52:29 alex Exp $
+#
+
+EXTRA_DIST = CVS.txt FAQ.txt Protocol.txt Platforms.txt \
+	README-AUX.txt README-BeOS.txt RFC.txt sample-ngircd.conf
+
+maintainer-clean-local:
+	rm -f Makefile Makefile.in
+
+distclean-local:
+	rm -rf src
+
+docdir = $(datadir)/doc/$(PACKAGE)
+
+documents = $(EXTRA_DIST) ../AUTHORS ../COPYING ../ChangeLog ../INSTALL \
+	../NEWS ../README
+
+install-data-hook:
+	$(mkinstalldirs) $(DESTDIR)$(sysconfdir)
+	if [ ! -f $(DESTDIR)$(sysconfdir)/ngircd.conf ]; then \
+	  $(INSTALL) -m 600 -c $(srcdir)/sample-ngircd.conf $(DESTDIR)$(sysconfdir)/ngircd.conf; \
+	 fi
+	$(mkinstalldirs) $(DESTDIR)$(docdir)
+	for f in $(documents); do \
+	  $(INSTALL) -m 644 -c $(srcdir)/$$f $(DESTDIR)$(docdir)/; \
+	 done
+
+uninstall-hook:
+	rm -rf $(DESTDIR)$(docdir)
+
+# -eof-

+ 311 - 0
doc/Makefile.in

@@ -0,0 +1,311 @@
+# Makefile.in generated by automake 1.7.9 from Makefile.am.
+# @configure_input@
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# ngIRCd -- The Next Generation IRC Daemon
+# Copyright (c)2001-2003 by Alexander Barton (alex@barton.de)
+#
+# Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen
+# der GNU General Public License (GPL), wie von der Free Software Foundation
+# herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2
+# der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version.
+# Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
+# der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
+#
+# $Id: Makefile.am,v 1.18 2005/04/27 07:52:29 alex Exp $
+#
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_triplet = @host@
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+U = @U@
+VERSION = @VERSION@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+
+EXTRA_DIST = CVS.txt FAQ.txt Protocol.txt Platforms.txt \
+	README-AUX.txt README-BeOS.txt RFC.txt sample-ngircd.conf
+
+
+docdir = $(datadir)/doc/$(PACKAGE)
+
+documents = $(EXTRA_DIST) ../AUTHORS ../COPYING ../ChangeLog ../INSTALL \
+	../NEWS ../README
+
+subdir = doc
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/src/config.h
+CONFIG_CLEAN_FILES =
+DIST_SOURCES =
+DIST_COMMON = $(srcdir)/Makefile.in Makefile.am
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  Makefile.am  $(top_srcdir)/configure.in $(ACLOCAL_M4)
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  doc/Makefile
+Makefile:  $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
+uninstall-info-am:
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkinstalldirs) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile
+
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-local
+
+dvi: dvi-am
+
+dvi-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+	@$(NORMAL_INSTALL)
+	$(MAKE) $(AM_MAKEFLAGS) install-data-hook
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic \
+	maintainer-clean-local
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+	@$(NORMAL_INSTALL)
+	$(MAKE) $(AM_MAKEFLAGS) uninstall-hook
+
+.PHONY: all all-am check check-am clean clean-generic distclean \
+	distclean-generic distclean-local distdir dvi dvi-am info \
+	info-am install install-am install-data install-data-am \
+	install-exec install-exec-am install-info install-info-am \
+	install-man install-strip installcheck installcheck-am \
+	installdirs maintainer-clean maintainer-clean-generic \
+	maintainer-clean-local mostlyclean mostlyclean-generic pdf \
+	pdf-am ps ps-am uninstall uninstall-am uninstall-info-am
+
+
+maintainer-clean-local:
+	rm -f Makefile Makefile.in
+
+distclean-local:
+	rm -rf src
+
+install-data-hook:
+	$(mkinstalldirs) $(DESTDIR)$(sysconfdir)
+	if [ ! -f $(DESTDIR)$(sysconfdir)/ngircd.conf ]; then \
+	  $(INSTALL) -m 600 -c $(srcdir)/sample-ngircd.conf $(DESTDIR)$(sysconfdir)/ngircd.conf; \
+	 fi
+	$(mkinstalldirs) $(DESTDIR)$(docdir)
+	for f in $(documents); do \
+	  $(INSTALL) -m 644 -c $(srcdir)/$$f $(DESTDIR)$(docdir)/; \
+	 done
+
+uninstall-hook:
+	rm -rf $(DESTDIR)$(docdir)
+
+# -eof-
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:

+ 65 - 0
doc/Platforms.txt

@@ -0,0 +1,65 @@
+
+                     ngIRCd - Next Generation IRC Server
+
+                        (c)2001-2005 Alexander Barton
+                    alex@barton.de, http://www.barton.de/
+
+               ngIRCd is free software and published under the
+                   terms of the GNU General Public License.
+
+                              -- Platforms.txt --
+
+
+This file lists the status of all platforms on which the ngIRCd has been
+tested. Included is the date and version of the last "official" test and
+the name of the tester/maintainer.
+
+If you successfully compiled and tested ngIRCd on a platform that isn't
+listed here, please contact Alexander Barton, <alex@barton.de>, so that this
+list can be updated. Thanks for your help!
+
+
+                              the executable works ("runs") as expected --+
+                                tests run successfully ("make check") --+ |
+                                           ngIRCd compiles ("make") --+ | |
+                                                ./configure works --+ | | |
+                                                                    | | | |
+Platform                    Compiler     ngIRCd     Date     Tester C M T R See
+--------------------------- ------------ ---------- -------- ------ - - - - ---
+hppa/unknown/openbsd3.5     gcc 2.95.3   CVSHEAD    04-05-25 alex   Y Y Y Y
+hppa1.1/unknown/linux-gnu   gcc 3.3.3    0.8.0      04-05-30 alex   Y Y Y Y
+hppa2.0/unknown/linux-gnu   gcc 3.3.5    0.9.x-CVS  05-06-27 alex   Y Y Y Y
+i386/pc/solaris2.9          gcc 3.2.2    CVSHEAD    04-02-24 alex   Y Y Y Y
+i386/unknown/freebsd5.2.1   gcc 3.3.3    0.8.0      04-05-30 alex   Y Y Y Y
+i386/unknown/gnu0.3         gcc 3.3.3    0.8.0      04-05-30 alex   Y Y n Y
+i386/unknown/netbsdelf1.6.1 gcc 2.95.3   CVSHEAD    04-02-24 alex   Y Y Y Y
+i686/pc/cygwin              gcc 3.3.1    0.9.x-CVS  05-07-08 alex   Y Y n Y
+i686/pc/linux-gnu           gcc 2.95.4   0.8.0      04-05-30 alex   Y Y Y Y (1)
+i686/pc/linux-gnu           gcc 3.3.5    0.9.x-CVS  05-07-09 alex   Y Y Y Y (1)
+m68k/apple/aux3.1.1         Orig. A/UX   0.7.x-CVS  03-04-22 alex   Y Y Y Y (2)
+m68k/hp/hp-ux9.10           Orig. HPUX   0.7.x-CVS  03-04-30 goetz  Y Y Y Y
+m88k/dg/dgux5.4R3.10        gcc 2.5.8    CVSHEAD    04-03-15 alex   Y Y ? ?
+powerpc/apple/darwin6.5     gcc 3.1      0.7.x-CVS  03-04-23 alex   Y Y Y Y
+powerpc/apple/darwin7.4.0   gcc 3.3      0.8.0      04-05-30 alex   Y Y Y Y
+powerpc/apple/darwin8.1.0   gcc 4.0      0.9.x-CVS  05-06-27 alex   Y Y Y Y
+powerpc/unknown/linux-gnu   gcc 3.3.3    0.8.0      04-05-30 alex   Y Y Y Y
+sparc/sun/solaris2.6        gcc 2.95.3   0.7.x-CVS  03-04-22 alex   Y Y Y Y
+sparc/sun/solaris2.7        gcc 3.3      0.8.0      04-05-30 alex   Y Y Y Y
+sparc/unkn./netbsdelf1.6.1  gcc 2.95.3   0.8.0      04-05-30 alex   Y Y Y Y
+
+
+Notes
+~~~~~
+(1) i686/pc/linux-gnu:
+    ngIRCd has been tested with various Linux distributions, such as SuSE,
+    RedHat, Debian, and Gentoo using Kernels 2.2.x, 2.4.x and 2.6.x with
+    various versions of the GNU C compiler (2.95.3, 3.0, 3.2, and 3.3). The
+    eldest glibc used was glibc-2.0.7. ngIRCd compiled and run on all these
+    systems without problems.
+
+(2) This compiler is an pre-ANSI C compiler, therefore the source code is
+    automatically converted using the included ansi2knr tool while building.
+			
+
+-- 
+$Id: Platforms.txt,v 1.13.2.2 2005/07/09 11:16:38 alex Exp $

+ 118 - 0
doc/Protocol.txt

@@ -0,0 +1,118 @@
+
+                     ngIRCd - Next Generation IRC Server
+
+                      (c)2001-2003 by Alexander Barton,
+                    alex@barton.de, http://www.barton.de/
+
+               ngIRCd is free software and published under the
+                   terms of the GNU General Public License.
+
+                              -- Protocol.txt --
+
+
+I. Compatibility
+~~~~~~~~~~~~~~~~
+
+The ngIRCd implements the Internet Relay Chat (IRC) protocol version 2.10
+as defined in RFC ("request for comment") 1459 and 2810-2813. These (and
+probably further relevant RFCs) are listed in doc/RFC.txt.
+
+Unfortunately, even the "original" ircd doesn't follow these specifications
+in all details. But because the ngIRCd should be a fully compatible
+replacement for this server ("ircd") it tries to emulate these differences.
+
+If you don't like this behavior please ./configure the ngIRCd using the
+"--enable-strict-rfc" command line option. But keep in mind: not all IRC
+clients are compatible with a server configured that way, some can't even
+connect at all! Therefore this option usually isn't desired for "normal
+server operation".
+
+
+II. The IRC+ Protocol
+~~~~~~~~~~~~~~~~~~~~~
+
+Starting with version 0.5.0, the ngIRCd extends the original IRC protocol
+as defined in RFC 2810-2813. This enhanced protocol is named "IRC+". It is
+backwards compatible to the "plain" IRC protocol and will only be used by
+the ngIRCd if it detects that the peer supports it as well.
+
+The "PASS" command is used to detect the protocol and peer versions see
+RFC 2813 (section 4.1.1) and below.
+
+
+II.1 Register new server link
+
+     Command: PASS
+  Parameters: <password> <version> <flags> [<options>]
+     Used by: servers only (with these parameters)
+
+<password> is the password for this new server link as defined in the server
+configuration which is sent to the peer or received from it.
+
+<version> consists of two parts and is at least 4, at most 14 characters
+long: the first four bytes contain the IRC protocol version number, whereas
+the first two bytes represent the major version, the last two bytes the
+minor version (the string "0210" indicates version 2.10, e.g.).
+
+The following optional(!) 10 bytes contain an implementation-dependent
+version number. Servers supporting the IRC+ protocol as defined in this
+document provide the string "-IRC+" here.
+
+Example for <version>: "0210-IRC+".
+
+<flags> consists of two parts separated with the character "|" and is at
+most 100 bytes long. The first part contains the name of the implementation
+(ngIRCd sets this to "ngircd", the original ircd to "IRC", e.g.). The second
+part is implementation-dependent and should only be parsed if the peer
+supports the IRC+ protocol as well. In this case the following syntax is
+used: "<serverversion>[:<serverflags>]".
+
+<serverversion> is an ASCII representation of the clear-text server version
+number, <serverflags> indicates the supported IRC+ protocol extensions (and
+may be empty!).
+
+The following <serverflags> are defined at the moment:
+
+- C: The server supports the CHANINFO command.
+
+- L: INVITE- and BAN-lists should be synchronized between servers: if the
+     peer understands this flag, it will send "MODE +I" and "MODE +b"
+     commands after the server link has been established.
+
+- o: IRC operators are allowed to change channel- and channel-user-modes
+     even if they aren't channel-operator of the affected channel.
+
+- Z: Compressed server links are supported by the server.
+
+Example for a complete <flags> string: "ngircd|0.7.5:CZ".
+
+The optional parameter <options> is used to propagate server options as
+defined in RFC 2813, section 4.1.1.
+
+
+II.2 Exchange channel-modes, topics, and persistent channels
+
+     Command: CHANINFO
+  Parameters: <channel> +<modes> <key> <maxusers> [<topic>]
+     Used by: servers only
+
+CHANINFO is used by servers to inform each other about a channel: its
+modes, channel key, user limits and its topic. <topic> is optional.
+
+If the channel already exists on the server receiving the CHANINFO command,
+it only adopts the <modes> (or the <topic>) if there are no modes (or topic)
+already set. It there are already values set the server ignores the
+corresponding parameter.
+
+If the channel doesn't exists at all it will be created.
+
+The parameter <key> must be ignored if a channel has no key (the parameter
+<modes> doesn't list the "k" channel mode). In this case <key> should
+contain "*" because the parameter <key> is required by the CHANINFO syntax
+and therefore can't be omitted. The parameter <limit> must be ignored when
+a channel has no user limit (the parameter <modes> doesn't list the "l"
+channel mode). In this case <limit> should be "0".
+
+
+-- 
+$Id: Protocol.txt,v 1.12 2004/04/25 15:44:10 alex Exp $

+ 67 - 0
doc/README-AUX.txt

@@ -0,0 +1,67 @@
+
+                    ngIRCd - Next Generation IRC Server
+
+                      (c)2001-2005 Alexander Barton,
+                   alex@barton.de, http://www.barton.de/
+
+               ngIRCd is free software and published under the
+                  terms of the GNU General Public License.
+
+
+                           -- README-AUX.txt --
+
+
+Since version 0.2.2-pre Apple's A/UX belongs to the officially supported 
+platforms. It is not restricted in any way.
+
+Since version 0.5.0 ngIRCd's source compiles with the native A/UX c 
+compiler. GNU C isn't a must-have anymore.
+
+The following software packages are needed:
+
+ - GNU sed
+   Source:
+   http://www.rezepte-im-web.de/appleux/sed-3.02.tar.gz
+   ftp://arthur.barton.de/pub/UNIX/AUX/Tools/sed-3.02.tar.gz
+
+   A/UX comes with /bin/sed which isn't supporting all functions needed
+   by GNU automake/autoconf.
+
+   Warning: When installing GNU sed please make sure that A/UX doesn't
+   use the old one anymore which means set the $PATH or replace /bin/sed
+   at all.
+
+ - libUTIL.a
+   Source:
+   ftp://ftp.mayn.de/pub/really_old_stuff/apple/apple_unix/Sys_stuff/libUTIL-2.1.tar.gz>
+   ftp://arthur.barton.de/pub/UNIX/AUX/Libraries/libUTIL-2.1.tar.gz
+
+   This library contains functions that are common on other UNIX
+   systems but not on A/UX e.g. memmove(), strerror() und strdup().
+
+
+After installation of these packages just do a "./configure" and "make" to
+compile ngIRCd on A/UX.
+
+
+A few hints in case of errors:
+
+ - Either there's an 'install' on your system which is completely broken
+   (so 'configure' uses its own shell script) or use a fully functionable one.
+   There's at least one binary "out there" causing problems. The one
+   of the GNU fileutils works fine:
+   ftp://arthur.barton.de/pub/UNIX/AUX/Software/Tools/fileutils-4.0.tar.gz
+
+ - The precompiled binary of the old 'bash' shouldn't be installed within
+   /bin (better do this in /usr/local/bin) because 'configure' would
+   choose it as its shell which wouldn't work.
+
+ - Because of limitations of /bin/sh on A/UX it can't be used to create
+   the 'config.status' script. Better rename /bin/sh to /bin/sh.AUX and
+   replace it by a symbolic link to /bin/ksh (ln -s /bin/ksh /bin/sh as
+   root).
+   These procedure should'nt cause you into problems and is recommended
+   even if you don't use ngIRCd.
+
+-- 
+$Id: README-AUX.txt,v 1.9 2005/06/24 20:59:13 alex Exp $

+ 53 - 0
doc/README-BeOS.txt

@@ -0,0 +1,53 @@
+
+                     ngIRCd - Next Generation IRC Server
+
+                      (c)2001-2003 by Alexander Barton,
+                    alex@barton.de, http://www.barton.de/
+
+               ngIRCd is free software and published under the
+                   terms of the GNU General Public License.
+
+                             -- README-BeOS.txt --
+
+
+      +-------------------------------------------------------------+
+      | This text is only available in german at the moment, sorry! |
+      | Contributors for this text or the BeOS port are welcome :-) |
+      +-------------------------------------------------------------+
+
+
+BeOS gehoert im Moment (noch?) nicht zu den offiziell unterstuetzten Plat-
+formen: der ngIRCd enthaelt zwar bereits einige Anpassungen an BeOS und
+compiliert auch, jedoch bricht er bei jedem Connect-Versuch eines Clients
+mit diesem Fehler ab:
+
+   select(): Bad file descriptor!
+
+Es sieht leider so aus, als ob das select() von BeOS nicht mit File-Handles
+von Pipes verschiedener Prozesse umgehen kann: sobald der Resolver asyncron
+gestartet wird, also Pipe-Handles im select() vorhanden sind, fuehrt das zu
+obiger Meldung.
+
+Theoretische "Loesung"/Workaround:
+Den Resolver unter BeOS nicht verwenden, sondern mit IP-Adressen arbeiten.
+Nachteil: der ngIRCd koennte sich nicht zu Servern verbinden, die dynamische
+Adressen benutzen -- dazu muesste er den Namen aufloesen. Ansonsten sollte
+es eigentlich zu keinen Beeintraechtigungen kommen ...
+
+Also: wenn es jemand implementieren will ... ;-))
+
+Vielleicht mache ich es auch irgendwann mal selber. Mal sehen.
+
+2002-05-19:
+Ich habe gerade damit ein wenig gespielt und den Source hier so geaendert,
+dass unter BeOS keine Resolver-Subprozesse mehr erzeugt werden, sondern mit
+den "rohen" IP-Adressen gearbeitet wird. Das funktioniert so weit auch,
+allerdings verschluckt sich BeOS nun bei anderen Funktionen, so zum Beispiel
+bei close(), wenn ein Socket eines Clients geschlossen werden soll!?
+Sehr komisch.
+Wer Interesse daran hat, das weiter zu verfolgen, der moege sich bitte mit
+mir in Verbindung setzen (alex@barton.de), ich maile gerne meine Patches zu.
+Fuer eine Aenderung im CVS ist es aber meiner Meinung nach noch zu frueh ...
+
+-- 
+$Id: README-BeOS.txt,v 1.7 2003/05/15 21:47:57 alex Exp $

+ 33 - 0
doc/RFC.txt

@@ -0,0 +1,33 @@
+
+                     ngIRCd - Next Generation IRC Server
+
+                      (c)2001-2003 by Alexander Barton,
+                    alex@barton.de, http://www.barton.de/
+
+               ngIRCd is free software and published under the
+                   terms of the GNU General Public License.
+
+                                 -- RFC.txt --
+
+
+The Internet Relay Chat (IRC) protocol is documented in these Request for
+Comments (RFC), which you can get e.g. via <http://www.faqs.org/>:
+
+  1459	Oikarinen, J. & D. Reed, "Internet Relay Chat Protocol",
+	May 1993, [IRC].
+
+  2810	Kalt, C., "Internet Relay Chat: Architecture",
+	April 2000, [IRC-ARCH].
+
+  2811	Kalt, C., "Internet Relay Chat: Channel Management",
+	April 2000, [IRC-CHAN].
+
+  2812	Kalt, C., "Internet Relay Chat: Client Protocol",
+	April 2000, [IRC-CLIENT].
+
+  2813	Kalt, C., "Internet Relay Chat: Server Protocol",
+	April 2000, [IRC-SERVER].
+
+
+-- 
+$Id: RFC.txt,v 1.6 2003/03/07 20:42:20 alex Exp $

+ 181 - 0
doc/sample-ngircd.conf

@@ -0,0 +1,181 @@
+# $Id: sample-ngircd.conf,v 1.33 2005/03/15 16:58:01 alex Exp $
+
+#
+# This is a sample configuration file for the ngIRCd, which must be adepted
+# to the local preferences and needs.
+#
+# Comments are started with "#" or ";".
+#
+# Use "ngircd --configtest" (see manual page ngircd(8)) to validate that the
+# server interpreted the configuration file as expected!
+#
+
+[Global]
+	# The [Global] section of this file is used to define the main
+	# configuration of the server, like the server name and the ports
+	# on which the server should be listening.
+	
+	# Server name in the IRC network, must contain at least one dot
+	# (".") and be unique in the IRC network. Required!
+	Name = irc.the.net
+	
+	# Info text of the server. This will be shown by WHOIS and
+	# LINKS requests for example.
+	Info = Server Info Text
+
+	# Global password for all users needed to connect to the server
+	;Password = abc
+	
+	# Information about the server and the administrator, used by the
+	# ADMIN command. Not required by server but by RFC!
+	;AdminInfo1 = Description
+	;AdminInfo2 = Location
+	;AdminEMail = admin@irc.server
+ 
+	# Ports on which the server should listen. There may be more than
+	# one port, separated with ",". (Default: 6667)
+	;Ports = 6667, 6668, 6669
+
+	# IP address on which the server should listen. (Default: empty,
+	# so the server listens on all IP addresses of the system)
+	;Listen = 1.2.3.4
+	
+	# Text file with the "message of the day" (MOTD). This message will
+	# be shown to all users connecting to the server:
+	;MotdFile = /usr/local/etc/ngircd.motd
+
+	# A simple Phrase (<256 chars) if you don't want to use a motd file.
+	# If it is set no MotdFile will be read at all.
+	;MotdPhrase = "Hello world!"
+
+	# User ID under which the server should run; you can use the name
+	# of the user or the numerical ID. ATTENTION: For this to work the
+	# server must have been started with root privileges! In addition,
+	# the configuration and MOTD files must be readable by this user,
+	# otherwise RESTART and REHASH won't work!
+	;ServerUID = 65534
+
+	# Group ID under which the ngircd should run; you can use the name
+	# of the group or the numerical ID. ATTENTION: For this to work the
+	# server must have been started with root privileges!
+	;ServerGID = 65534
+
+	# A directory to chroot in when everything is initialized. It
+	# doesn't need to be populated if ngIRCd is compiled as a static
+	# binary. By default ngIRCd won't use the chroot() feature.
+	# ATTENTION: For this to work the server must have been started
+	# with root privileges!
+	;ChrootDir = /var/empty
+
+	# This tells ngircd to write its current process id to a file.
+	# Note that the pidfile is written AFTER chroot and switching uid,
+	# i. e. the Directory the pidfile resides in must be writeable by
+	# the ngircd user and exist in the chroot directory.
+	;PidFile = /var/run/ngircd/ngircd.pid
+
+	# After <PingTimeout> seconds of inactivity the server will send a
+	# PING to the peer to test whether it is alive or not.
+	;PingTimeout = 120
+
+	# If a client fails to answer a PING with a PONG within <PongTimeout>
+	# seconds, it will be disconnected by the server.
+	;PongTimeout = 20
+
+	# The server tries every <ConnectRetry> seconds to establish a link
+	# to not yet (or no longer) connected servers.
+	;ConnectRetry = 60
+
+	# Should IRC Operators be allowed to use the MODE command even if
+	# they are not(!) channel-operators?
+	;OperCanUseMode = no
+
+	# Mask IRC Operator mode requests as if they were coming from the
+	# server? (This is a compatibility hack for ircd-irc2 servers)
+	;OperServerMode = no
+	
+	# Maximum number of simultaneous connection the server is allowed
+	# to accept (<=0: unlimited):
+	;MaxConnections = -1
+	
+	# Maximum number of simultaneous connections from a single IP address
+	# the server will accept (<=0: unlimited):
+	;MaxConnectionsIP = 5
+
+	# Maximum number of channels a user can be member of (<=0: no limit):
+	;MaxJoins = 10
+
+[Operator]
+	# [Operator] sections are used to define IRC Operators. There may be
+	# more than one [Operator] block, one for each local operator.
+	
+	# ID of the operator (may be different of the nick name)
+	;Name = TheOper
+
+	# Password of the IRC operator
+	;Password = ThePwd
+
+	# Optional Mask from which /OPER will be accepted
+	;Mask = *!ident@somewhere.example.com
+
+[Operator]
+	# More [Operator] sections, if you like ...
+
+[Server]
+	# Other servers are configured in [Server] sections. If you
+	# configure a port for the connection, then this ngircd tries to
+	# connect to to the other server on the given port; if not it waits
+	# for the other server to connect.
+	# There may be more than one server block.
+	#
+	# Server Groups:
+	# The ngIRCd allows "server groups": You can assign an "ID" to every
+	# server with which you want this ngIRCd to link. If a server of a
+	# group won't answer, the ngIRCd tries to connect to the next server
+	# in the given group. But the ngircd never tries to connect to two
+	# servers with the same group ID.
+	
+	# IRC name of the server
+	;Name = irc2.the.net
+   
+	# Internet host name of the peer
+	;Host = connect-to-host.the.net
+
+	# Port of the server to which the ngIRCd should connect. If you
+	# assign no port the ngIRCd waits for incoming connections.
+	;Port = 6666
+
+	# Own password for the connection. This password has to be configured
+	# as "PeerPassword" on the other server.
+	;MyPassword = MySecret
+
+	# Foreign password for this connection. This password has to be
+	# configured as "MyPassword" on the other server.
+	;PeerPassword = PeerSecret
+	
+	# Group of this server (optional)
+	;Group = 123
+
+[Server]
+	# More [Server] sections, if you like ...
+
+[Channel]
+	# Pre-defined channels can be configured in [Channel] sections.
+	# Such channels are created by the server when starting up and even
+	# persist when there are no more members left.
+	# Persistent channels are marked with the mode 'P', which can be set
+	# and unset by IRC operators like other modes on the fly.
+	# There may be more than one [Channel] block.
+	
+	# Name of the channel
+	;Name = #TheName
+
+	# Topic for this channel
+	;Topic = a great topic
+	
+	# Initial channel modes
+	;Modes = tn
+
+[Channel]
+	# More [Channel] sections, if you like ...
+
+# -eof-

+ 294 - 0
install-sh

@@ -0,0 +1,294 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+#
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.  It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+	-c) instcmd=$cpprog
+	    shift
+	    continue;;
+
+	-d) dir_arg=true
+	    shift
+	    continue;;
+
+	-m) chmodcmd="$chmodprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-o) chowncmd="$chownprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-g) chgrpcmd="$chgrpprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-s) stripcmd=$stripprog
+	    shift
+	    continue;;
+
+	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
+	    shift
+	    continue;;
+
+	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+	    shift
+	    continue;;
+
+	*)  if [ x"$src" = x ]
+	    then
+		src=$1
+	    else
+		# this colon is to work around a 386BSD /bin/sh bug
+		:
+		dst=$1
+	    fi
+	    shift
+	    continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+	echo "$0: no input file specified" >&2
+	exit 1
+else
+	:
+fi
+
+if [ x"$dir_arg" != x ]; then
+	dst=$src
+	src=""
+
+	if [ -d "$dst" ]; then
+		instcmd=:
+		chmodcmd=""
+	else
+		instcmd=$mkdirprog
+	fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+	if [ -f "$src" ] || [ -d "$src" ]
+	then
+		:
+	else
+		echo "$0: $src does not exist" >&2
+		exit 1
+	fi
+
+	if [ x"$dst" = x ]
+	then
+		echo "$0: no destination specified" >&2
+		exit 1
+	else
+		:
+	fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+	if [ -d "$dst" ]
+	then
+		dst=$dst/`basename "$src"`
+	else
+		:
+	fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+	'
+IFS="${IFS-$defaultIFS}"
+
+oIFS=$IFS
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS=$oIFS
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+	pathcomp=$pathcomp$1
+	shift
+
+	if [ ! -d "$pathcomp" ] ;
+        then
+		$mkdirprog "$pathcomp"
+	else
+		:
+	fi
+
+	pathcomp=$pathcomp/
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+	$doit $instcmd "$dst" &&
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+	if [ x"$transformarg" = x ]
+	then
+		dstfile=`basename "$dst"`
+	else
+		dstfile=`basename "$dst" $transformbasename |
+			sed $transformarg`$transformbasename
+	fi
+
+# don't allow the sed command to completely eliminate the filename
+
+	if [ x"$dstfile" = x ]
+	then
+		dstfile=`basename "$dst"`
+	else
+		:
+	fi
+
+# Make a couple of temp file names in the proper directory.
+
+	dsttmp=$dstdir/_inst.$$_
+	rmtmp=$dstdir/_rm.$$_
+
+# Trap to clean up temp files at exit.
+
+	trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
+	trap '(exit $?); exit' 1 2 13 15
+
+# Move or copy the file name to the temp name
+
+	$doit $instcmd "$src" "$dsttmp" &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
+
+# Now remove or move aside any old file at destination location.  We try this
+# two ways since rm can't unlink itself on some systems and the destination
+# file might be busy for other reasons.  In this case, the final cleanup
+# might fail but the new file should still install successfully.
+
+{
+	if [ -f "$dstdir/$dstfile" ]
+	then
+		$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null ||
+		$doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null ||
+		{
+		  echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
+		  (exit 1); exit
+		}
+	else
+		:
+	fi
+} &&
+
+# Now rename the file to the real destination.
+
+	$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
+
+fi &&
+
+# The final little trick to "correctly" pass the exit status to the exit trap.
+
+{
+	(exit 0); exit
+}

+ 22 - 0
man/Makefile.am

@@ -0,0 +1,22 @@
+#
+# ngIRCd -- The Next Generation IRC Daemon
+# Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+#
+# Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen
+# der GNU General Public License (GPL), wie von der Free Software Foundation
+# herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2
+# der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version.
+# Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
+# der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
+#
+# $Id: Makefile.am,v 1.5 2002/04/04 13:02:41 alex Exp $
+#
+
+man_MANS = ngircd.conf.5 ngircd.8
+
+EXTRA_DIST = $(man_MANS)
+
+maintainer-clean-local:
+	rm -f Makefile Makefile.in
+
+# -eof-

+ 386 - 0
man/Makefile.in

@@ -0,0 +1,386 @@
+# Makefile.in generated by automake 1.7.9 from Makefile.am.
+# @configure_input@
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# ngIRCd -- The Next Generation IRC Daemon
+# Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+#
+# Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen
+# der GNU General Public License (GPL), wie von der Free Software Foundation
+# herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2
+# der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version.
+# Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
+# der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
+#
+# $Id: Makefile.am,v 1.5 2002/04/04 13:02:41 alex Exp $
+#
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_triplet = @host@
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+U = @U@
+VERSION = @VERSION@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+
+man_MANS = ngircd.conf.5 ngircd.8
+
+EXTRA_DIST = $(man_MANS)
+subdir = man
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/src/config.h
+CONFIG_CLEAN_FILES =
+DIST_SOURCES =
+
+NROFF = nroff
+MANS = $(man_MANS)
+DIST_COMMON = $(srcdir)/Makefile.in Makefile.am
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  Makefile.am  $(top_srcdir)/configure.in $(ACLOCAL_M4)
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  man/Makefile
+Makefile:  $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
+uninstall-info-am:
+
+man5dir = $(mandir)/man5
+install-man5: $(man5_MANS) $(man_MANS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(man5dir)
+	@list='$(man5_MANS) $(dist_man5_MANS) $(nodist_man5_MANS)'; \
+	l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+	for i in $$l2; do \
+	  case "$$i" in \
+	    *.5*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+	  else file=$$i; fi; \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  case "$$ext" in \
+	    5*) ;; \
+	    *) ext='5' ;; \
+	  esac; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed -e 's/^.*\///'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man5dir)/$$inst"; \
+	  $(INSTALL_DATA) $$file $(DESTDIR)$(man5dir)/$$inst; \
+	done
+uninstall-man5:
+	@$(NORMAL_UNINSTALL)
+	@list='$(man5_MANS) $(dist_man5_MANS) $(nodist_man5_MANS)'; \
+	l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+	for i in $$l2; do \
+	  case "$$i" in \
+	    *.5*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  case "$$ext" in \
+	    5*) ;; \
+	    *) ext='5' ;; \
+	  esac; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed -e 's/^.*\///'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " rm -f $(DESTDIR)$(man5dir)/$$inst"; \
+	  rm -f $(DESTDIR)$(man5dir)/$$inst; \
+	done
+
+man8dir = $(mandir)/man8
+install-man8: $(man8_MANS) $(man_MANS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(man8dir)
+	@list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \
+	l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+	for i in $$l2; do \
+	  case "$$i" in \
+	    *.8*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+	  else file=$$i; fi; \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  case "$$ext" in \
+	    8*) ;; \
+	    *) ext='8' ;; \
+	  esac; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed -e 's/^.*\///'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst"; \
+	  $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst; \
+	done
+uninstall-man8:
+	@$(NORMAL_UNINSTALL)
+	@list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \
+	l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+	for i in $$l2; do \
+	  case "$$i" in \
+	    *.8*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  case "$$ext" in \
+	    8*) ;; \
+	    *) ext='8' ;; \
+	  esac; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed -e 's/^.*\///'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " rm -f $(DESTDIR)$(man8dir)/$$inst"; \
+	  rm -f $(DESTDIR)$(man8dir)/$$inst; \
+	done
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkinstalldirs) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(MANS)
+
+installdirs:
+	$(mkinstalldirs) $(DESTDIR)$(man5dir) $(DESTDIR)$(man8dir)
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-man
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man: install-man5 install-man8
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic \
+	maintainer-clean-local
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am uninstall-man
+
+uninstall-man: uninstall-man5 uninstall-man8
+
+.PHONY: all all-am check check-am clean clean-generic distclean \
+	distclean-generic distdir dvi dvi-am info info-am install \
+	install-am install-data install-data-am install-exec \
+	install-exec-am install-info install-info-am install-man \
+	install-man5 install-man8 install-strip installcheck \
+	installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic maintainer-clean-local mostlyclean \
+	mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am \
+	uninstall-info-am uninstall-man uninstall-man5 uninstall-man8
+
+
+maintainer-clean-local:
+	rm -f Makefile Makefile.in
+
+# -eof-
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:

+ 80 - 0
man/ngircd.8

@@ -0,0 +1,80 @@
+.\"
+.\" $Id: ngircd.8,v 1.10 2005/06/04 13:39:20 alex Exp $
+.\"
+.TH ngircd 8 "Juni 2005" ngircd "ngIRCd Manual"
+.SH NAME
+ngIRCd \- the next generation IRC daemon
+.SH SYNOPSIS
+.B ngircd [
+.I Options
+.B ]
+.SH DESCRIPTION
+.BR ngIRCd
+is a free open source daemon for the Internet Relay Chat (IRC),
+developed under the GNU General Public License (GPL).
+.PP
+It's written from scratch and is not based upon the original IRCd like
+many others. It is easy to configure, supports server links (even with
+original ircd's) and runs on hosts with changing IP addresses (such as
+dial-in networks).
+.PP
+Currently supported platforms include AIX, A/UX, FreeBSD, HP-UX, IRIX,
+Linux, Mac OS X, NetBSD, OpenBSD, Solaris, and Windows with Cygwin.
+.PP
+As ngIRCd relies on UNIX standards and uses GNU automake and GNU autoconf
+there are good chances that it also supports other UNIX-based operating
+systems as well.
+.SH OPTIONS
+The default behaviour of
+.BR ngircd
+is to read its standard configuration file (see below), to detach from the
+controlling terminal and to wait for clients.
+.PP
+You can use these options to modify this default:
+.TP
+\fB\-f\fR \fIfile\fR, \fB\-\-config\fR \fIfile\fR
+Use
+.I file
+as configuration file.
+.TP
+\fB\-n\fR, \fB\-\-nodaemon\fR
+Don't fork a child and don't detach from controlling terminal.
+All log messages go to the console and you can use CTRL-C to
+terminate the server.
+.TP
+\fB\-p\fR, \fB\-\-passive\fR
+Disable automatic connections to other servers. You can use the IRC command
+CONNECT later on as IRC Operator to link this ngIRCd to other servers.
+.TP
+\fB\-t\fR, \fB\-\-configtest\fR
+Read, validate and display the configuration; then exit.
+.TP
+\fB\-\-version\fR
+Output version information and exit.
+.TP
+\fB\-\-help\fR
+Display a brief help text and exit.
+.SH FILES
+.I /usr/local/etc/ngircd.conf
+.RS
+The system wide default configuration file.
+.RE
+.I /usr/local/etc/ngircd.motd
+.RS
+Default "message of the day" (MOTD).
+.RE
+.SH AUTHOR
+Alexander Barton,
+.UR mailto:alex@barton.de
+alex@barton.de
+.UE
+.br
+Homepage:
+.UR http://arthur.ath.cx/~alex/ngircd/
+http://arthur.ath.cx/~alex/ngircd/
+.UE
+.SH "SEE ALSO"
+.BR ngircd.conf (5),
+.BR ircd (8)
+.\"
+.\" -eof-

+ 250 - 0
man/ngircd.conf.5

@@ -0,0 +1,250 @@
+.\"
+.\" $Id: ngircd.conf.5,v 1.18 2005/06/04 13:39:20 alex Exp $
+.\"
+.TH ngircd.conf 5 "Juni 2005" ngircd "ngIRCd Manual"
+.SH NAME
+ngircd.conf \- configuration file of ngIRCd
+.SH SYNOPSIS
+.B /usr/local/etc/ngircd.conf
+.SH DESCRIPTION
+.BR ngircd.conf
+is the configuration file for
+.BR ngircd (8)
+which you should adept to your local preferences and needs.
+.SH "FILE FORMAT"
+The file consists of sections and parameters. A section begins with the name
+of the section in square brackets and continues until the next section
+begins.
+.PP
+Sections contain parameters of the form
+.PP
+.RS
+.I name
+=
+.I value
+.RE
+.PP
+Any line beginning with a semicolon (';') or a hash ('#') character is
+treated as a comment and ignored.
+.PP
+The file format is line-based - that means, each newline-terminated line
+represents either a comment, a section name or a parameter.
+.PP
+Section and parameter names are not case sensitive.
+.SH "SECTION OVERVIEW"
+The file can contain blocks of four types: [Global], [Operator], [Server],
+and [Channel].
+.PP
+In the
+.I [Global]
+section, there is the main configuration like the server name and the
+ports on which the server should be listening. IRC operators of this
+server are defined in
+.I [Operator]
+blocks.
+.I [Server]
+is the section where server links are configured. And
+.I [Channel]
+blocks are used to configure pre-defined ("persistent") IRC channels.
+.PP
+There can be more than one [Operator], [Server] and [Channel] sections
+per configuration file, but only one [Global] section.
+.SH [GLOBAL]
+The
+.I [Global]
+section is used to define the server main configuration, like the server
+name and the ports on which the server should be listening.
+.TP
+\fBName\fR
+Server name in the IRC network
+.TP
+\fBInfo\fR
+Info text of the server. This will be shown by WHOIS and LINKS requests for
+example.
+.TP
+\fBAdminInfo1\fR, \fBAdminInfo2\fR, \fBAdminEMail\fR
+Information about the server and the administrator, used by the ADMIN
+command.
+.TP
+\fBPorts\fR
+Ports on which the server should listen. There may be more than one port,
+separated with ','. Default: 6667.
+.TP
+\fBListen\fR
+The IP address on which the server should listen. Default is empty, so
+the server listens on all configured IP addresses and interfaces.
+.TP
+\fBMotdFile\fR
+Text file with the "message of the day" (MOTD). This message will be shown
+to all users connecting to the server.
+.TP
+\fBMotdPhrase\fR
+A simple Phrase (<256 chars) if you don't want to use a MOTD file.
+If it is set no MotdFile will be read at all.
+.TP
+\fBServerUID\fR
+User ID under which the server should run; you can use the name of the user
+or the numerical ID.
+.PP
+.RS
+.B Attention:
+.br
+For this to work the server must have been
+started with root privileges! In addition, the configuration and MOTD files
+must be readable by this user, otherwise RESTART and REHASH won't work!
+.RE
+.TP
+\fBServerGID\fR
+Group ID under which the ngIRCd should run; you can use the name of the
+group or the numerical ID.
+.PP
+.RS
+.B Attention:
+.br
+For this to work the server must have
+been started with root privileges!
+.RE
+.TP
+\fBChrootDir\fR
+A directory to chroot in when everything is initialized. It doesn't need
+to be populated if ngIRCd is compiled as a static binary. By default ngIRCd
+won't use the chroot() feature.
+.PP
+.RS
+.B Attention:
+.br
+For this to work the server must have
+been started with root privileges!
+.RE
+.TP
+\fBPidFile\fR
+This tells ngIRCd to write its current process ID to a file. Note that the
+pidfile is written AFTER chroot and switching the user ID, i. e. the
+directory the pidfile resides in must be writeable by the ngIRCd user and
+exist in the chroot directory (if configured, see above).
+.RE
+.TP
+\fBPingTimeout\fR
+After <PingTimeout> seconds of inactivity the server will send a PING to
+the peer to test whether it is alive or not. Default: 120.
+.TP
+\fBPongTimeout\fR
+If a client fails to answer a PING with a PONG within <PongTimeout>
+seconds, it will be disconnected by the server. Default: 20.
+.TP
+\fBConnectRetry\fR
+The server tries every <ConnectRetry> seconds to establish a link to not yet
+(or no longer) connected servers. Default: 60.
+.TP
+\fBOperCanUseMode\fR
+Should IRC Operators be allowed to use the MODE command even if they are
+not(!) channel-operators? Default: no.
+.TP
+\fBOperServerMode\fR
+If OperCanUseMode is enabled, this may lead the compatibility problems with
+Servers that run the ircd-irc2 Software. This Option "masks" mode requests
+by non-chanops as if they were coming from the server. Default: no.
+.TP
+\fBMaxConnections\fR
+Maximum number of simultaneous connection the server is allowed to accept
+(<=0: unlimited). Default: -1.
+.TP
+\fBMaxConnectionsIP\fR
+Maximum number of simultaneous connections from a single IP address that
+the server will accept (<=0: unlimited). This configuration options lowers
+the risk of denial of service attacks (DoS). Default: 5.
+.TP
+\fBMaxJoins\fR
+Maximum number of channels a user can be member of (<=0: no limit).
+Default: 10.
+.SH [OPERATOR]
+.I [Operator]
+sections are used to define IRC Operators. There may be more than one
+.I [Operator]
+block, one for each local operator.
+.TP
+\fBName\fR
+ID of the operator (may be different of the nick name).
+.TP
+\fBPassword\fR
+Password of the IRC operator.
+.TP
+\fBMask\fR
+Mask that is to be checked before an /OPER for this account is accepted.
+Example: nick!ident@*.example.com
+.SH [SERVER]
+Other servers are configured in
+.I [Server]
+sections. If you configure a port for the connection, then this ngIRCd
+tries to connect to to the other server on the given port; if not, it waits
+for the other server to connect.
+.PP
+The ngIRCd allows "server groups": You can assign an "ID" to every server
+with which you want this ngIRCd to link. If a server of a group won't
+answer, the ngIRCd tries to connect to the next server in the given group.
+But ngIRCd never tries to connect to two servers with the same group ID.
+.PP
+There may be more than one
+.I [Server]
+block.
+.TP
+\fBName\fR
+IRC name of the server
+.TP
+\fBHost\fR
+Internet host name of the peer
+.TP
+\fBPort\fR
+Port of the server to which the ngIRCd should connect. If you assign no port
+the ngIRCd waits for incoming connections.
+.TP
+\fBMyPassword\fR
+Own password for this connection. This password has to be configured as
+"PeerPassword" on the other server.
+.TP
+\fBPeerPassword\fR
+Foreign password for this connection. This password has to be configured as
+"MyPassword" on the other server.
+.TP
+\fBGroup\fR
+Group of this server (optional).
+.SH [CHANNEL]
+Pre-defined channels can be configured in
+.I [Channel]
+sections. Such channels are created by the server when starting up and even
+persist when there are no more members left.
+.PP
+Persistent channels are marked with the mode 'P', which can be set and unset
+by IRC operators like other modes on the fly.
+.PP
+There may be more than one
+.I [Channel]
+block.
+.TP
+\fBName\fR
+Name of the channel
+.TP
+\fBTopic\fR
+Topic for this channel
+.TP
+\fBModes\fR
+Initial channel modes.
+.SH HINTS
+It's wise to use "ngircd --configtest" to validate the configuration file
+after changing it. See
+.BR ngircd (8)
+for details.
+.SH AUTHOR
+Alexander Barton,
+.UR mailto:alex@barton.de
+alex@barton.de
+.UE
+.br
+Homepage:
+.UR http://arthur.ath.cx/~alex/ngircd/
+http://arthur.ath.cx/~alex/ngircd/
+.UE
+.SH "SEE ALSO"
+.BR ngircd (8)
+.\"
+.\" -eof-

+ 336 - 0
missing

@@ -0,0 +1,336 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
+# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+  echo 1>&2 "Try \`$0 --help' for more information"
+  exit 1
+fi
+
+run=:
+
+# In the cases where this matters, `missing' is being run in the
+# srcdir already.
+if test -f configure.ac; then
+  configure_ac=configure.ac
+else
+  configure_ac=configure.in
+fi
+
+case "$1" in
+--run)
+  # Try to run requested program, and just exit if it succeeds.
+  run=
+  shift
+  "$@" && exit 0
+  ;;
+esac
+
+# If it does not exist, or fails to run (possibly an outdated version),
+# try to emulate it.
+case "$1" in
+
+  -h|--h|--he|--hel|--help)
+    echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+  -h, --help      display this help and exit
+  -v, --version   output version information and exit
+  --run           try to run the given command, and emulate it if it fails
+
+Supported PROGRAM values:
+  aclocal      touch file \`aclocal.m4'
+  autoconf     touch file \`configure'
+  autoheader   touch file \`config.h.in'
+  automake     touch all \`Makefile.in' files
+  bison        create \`y.tab.[ch]', if possible, from existing .[ch]
+  flex         create \`lex.yy.c', if possible, from existing .c
+  help2man     touch the output file
+  lex          create \`lex.yy.c', if possible, from existing .c
+  makeinfo     touch the output file
+  tar          try tar, gnutar, gtar, then tar without non-portable flags
+  yacc         create \`y.tab.[ch]', if possible, from existing .[ch]"
+    ;;
+
+  -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+    echo "missing 0.4 - GNU automake"
+    ;;
+
+  -*)
+    echo 1>&2 "$0: Unknown \`$1' option"
+    echo 1>&2 "Try \`$0 --help' for more information"
+    exit 1
+    ;;
+
+  aclocal*)
+    if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+       # We have it, but it failed.
+       exit 1
+    fi
+
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`acinclude.m4' or \`${configure_ac}'.  You might want
+         to install the \`Automake' and \`Perl' packages.  Grab them from
+         any GNU archive site."
+    touch aclocal.m4
+    ;;
+
+  autoconf)
+    if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+       # We have it, but it failed.
+       exit 1
+    fi
+
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`${configure_ac}'.  You might want to install the
+         \`Autoconf' and \`GNU m4' packages.  Grab them from any GNU
+         archive site."
+    touch configure
+    ;;
+
+  autoheader)
+    if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+       # We have it, but it failed.
+       exit 1
+    fi
+
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`acconfig.h' or \`${configure_ac}'.  You might want
+         to install the \`Autoconf' and \`GNU m4' packages.  Grab them
+         from any GNU archive site."
+    files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
+    test -z "$files" && files="config.h"
+    touch_files=
+    for f in $files; do
+      case "$f" in
+      *:*) touch_files="$touch_files "`echo "$f" |
+				       sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+      *) touch_files="$touch_files $f.in";;
+      esac
+    done
+    touch $touch_files
+    ;;
+
+  automake*)
+    if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+       # We have it, but it failed.
+       exit 1
+    fi
+
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
+         You might want to install the \`Automake' and \`Perl' packages.
+         Grab them from any GNU archive site."
+    find . -type f -name Makefile.am -print |
+	   sed 's/\.am$/.in/' |
+	   while read f; do touch "$f"; done
+    ;;
+
+  autom4te)
+    if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+       # We have it, but it failed.
+       exit 1
+    fi
+
+    echo 1>&2 "\
+WARNING: \`$1' is needed, and you do not seem to have it handy on your
+         system.  You might have modified some files without having the
+         proper tools for further handling them.
+         You can get \`$1' as part of \`Autoconf' from any GNU
+         archive site."
+
+    file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'`
+    test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'`
+    if test -f "$file"; then
+	touch $file
+    else
+	test -z "$file" || exec >$file
+	echo "#! /bin/sh"
+	echo "# Created by GNU Automake missing as a replacement of"
+	echo "#  $ $@"
+	echo "exit 0"
+	chmod +x $file
+	exit 1
+    fi
+    ;;
+
+  bison|yacc)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified a \`.y' file.  You may need the \`Bison' package
+         in order for those modifications to take effect.  You can get
+         \`Bison' from any GNU archive site."
+    rm -f y.tab.c y.tab.h
+    if [ $# -ne 1 ]; then
+        eval LASTARG="\${$#}"
+	case "$LASTARG" in
+	*.y)
+	    SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+	    if [ -f "$SRCFILE" ]; then
+	         cp "$SRCFILE" y.tab.c
+	    fi
+	    SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+	    if [ -f "$SRCFILE" ]; then
+	         cp "$SRCFILE" y.tab.h
+	    fi
+	  ;;
+	esac
+    fi
+    if [ ! -f y.tab.h ]; then
+	echo >y.tab.h
+    fi
+    if [ ! -f y.tab.c ]; then
+	echo 'main() { return 0; }' >y.tab.c
+    fi
+    ;;
+
+  lex|flex)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified a \`.l' file.  You may need the \`Flex' package
+         in order for those modifications to take effect.  You can get
+         \`Flex' from any GNU archive site."
+    rm -f lex.yy.c
+    if [ $# -ne 1 ]; then
+        eval LASTARG="\${$#}"
+	case "$LASTARG" in
+	*.l)
+	    SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+	    if [ -f "$SRCFILE" ]; then
+	         cp "$SRCFILE" lex.yy.c
+	    fi
+	  ;;
+	esac
+    fi
+    if [ ! -f lex.yy.c ]; then
+	echo 'main() { return 0; }' >lex.yy.c
+    fi
+    ;;
+
+  help2man)
+    if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+       # We have it, but it failed.
+       exit 1
+    fi
+
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+	 you modified a dependency of a manual page.  You may need the
+	 \`Help2man' package in order for those modifications to take
+	 effect.  You can get \`Help2man' from any GNU archive site."
+
+    file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+    if test -z "$file"; then
+	file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
+    fi
+    if [ -f "$file" ]; then
+	touch $file
+    else
+	test -z "$file" || exec >$file
+	echo ".ab help2man is required to generate this page"
+	exit 1
+    fi
+    ;;
+
+  makeinfo)
+    if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then
+       # We have makeinfo, but it failed.
+       exit 1
+    fi
+
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified a \`.texi' or \`.texinfo' file, or any other file
+         indirectly affecting the aspect of the manual.  The spurious
+         call might also be the consequence of using a buggy \`make' (AIX,
+         DU, IRIX).  You might want to install the \`Texinfo' package or
+         the \`GNU make' package.  Grab either from any GNU archive site."
+    file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+    if test -z "$file"; then
+      file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+      file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
+    fi
+    touch $file
+    ;;
+
+  tar)
+    shift
+    if test -n "$run"; then
+      echo 1>&2 "ERROR: \`tar' requires --run"
+      exit 1
+    fi
+
+    # We have already tried tar in the generic part.
+    # Look for gnutar/gtar before invocation to avoid ugly error
+    # messages.
+    if (gnutar --version > /dev/null 2>&1); then
+       gnutar "$@" && exit 0
+    fi
+    if (gtar --version > /dev/null 2>&1); then
+       gtar "$@" && exit 0
+    fi
+    firstarg="$1"
+    if shift; then
+	case "$firstarg" in
+	*o*)
+	    firstarg=`echo "$firstarg" | sed s/o//`
+	    tar "$firstarg" "$@" && exit 0
+	    ;;
+	esac
+	case "$firstarg" in
+	*h*)
+	    firstarg=`echo "$firstarg" | sed s/h//`
+	    tar "$firstarg" "$@" && exit 0
+	    ;;
+	esac
+    fi
+
+    echo 1>&2 "\
+WARNING: I can't seem to be able to run \`tar' with the given arguments.
+         You may want to install GNU tar or Free paxutils, or check the
+         command line arguments."
+    exit 1
+    ;;
+
+  *)
+    echo 1>&2 "\
+WARNING: \`$1' is needed, and you do not seem to have it handy on your
+         system.  You might have modified some files without having the
+         proper tools for further handling them.  Check the \`README' file,
+         it often tells you about the needed prerequisites for installing
+         this package.  You may also peek at any GNU archive site, in case
+         some other package would contain this missing \`$1' program."
+    exit 1
+    ;;
+esac
+
+exit 0

+ 111 - 0
mkinstalldirs

@@ -0,0 +1,111 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+errstatus=0
+dirmode=""
+
+usage="\
+Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..."
+
+# process command line arguments
+while test $# -gt 0 ; do
+  case $1 in
+    -h | --help | --h*)         # -h for help
+      echo "$usage" 1>&2
+      exit 0
+      ;;
+    -m)                         # -m PERM arg
+      shift
+      test $# -eq 0 && { echo "$usage" 1>&2; exit 1; }
+      dirmode=$1
+      shift
+      ;;
+    --)                         # stop option processing
+      shift
+      break
+      ;;
+    -*)                         # unknown option
+      echo "$usage" 1>&2
+      exit 1
+      ;;
+    *)                          # first non-opt arg
+      break
+      ;;
+  esac
+done
+
+for file
+do
+  if test -d "$file"; then
+    shift
+  else
+    break
+  fi
+done
+
+case $# in
+  0) exit 0 ;;
+esac
+
+case $dirmode in
+  '')
+    if mkdir -p -- . 2>/dev/null; then
+      echo "mkdir -p -- $*"
+      exec mkdir -p -- "$@"
+    fi
+    ;;
+  *)
+    if mkdir -m "$dirmode" -p -- . 2>/dev/null; then
+      echo "mkdir -m $dirmode -p -- $*"
+      exec mkdir -m "$dirmode" -p -- "$@"
+    fi
+    ;;
+esac
+
+for file
+do
+  set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+  shift
+
+  pathcomp=
+  for d
+  do
+    pathcomp="$pathcomp$d"
+    case $pathcomp in
+      -*) pathcomp=./$pathcomp ;;
+    esac
+
+    if test ! -d "$pathcomp"; then
+      echo "mkdir $pathcomp"
+
+      mkdir "$pathcomp" || lasterr=$?
+
+      if test ! -d "$pathcomp"; then
+  	errstatus=$lasterr
+      else
+  	if test ! -z "$dirmode"; then
+	  echo "chmod $dirmode $pathcomp"
+    	  lasterr=""
+  	  chmod "$dirmode" "$pathcomp" || lasterr=$?
+
+  	  if test ! -z "$lasterr"; then
+  	    errstatus=$lasterr
+  	  fi
+  	fi
+      fi
+    fi
+
+    pathcomp="$pathcomp/"
+  done
+done
+
+exit $errstatus
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# End:
+# mkinstalldirs ends here

+ 24 - 0
src/Makefile.am

@@ -0,0 +1,24 @@
+#
+# ngIRCd -- The Next Generation IRC Daemon
+# Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# Please read the file COPYING, README and AUTHORS for more information.
+#
+# $Id: Makefile.am,v 1.6 2005/04/09 12:22:41 alex Exp $
+#
+
+SUBDIRS = portab tool ngircd testsuite
+
+maintainer-clean-local:
+	rm -f Makefile Makefile.in config.h config.h.in stamp-h.in
+
+srcdoc:
+	@doxygen --version >/dev/null 2>&1 \
+	 || ( echo; echo "Error: \"doxygen\" not found!"; echo; exit 1 )
+	doxygen
+
+# -eof-

+ 453 - 0
src/Makefile.in

@@ -0,0 +1,453 @@
+# Makefile.in generated by automake 1.7.9 from Makefile.am.
+# @configure_input@
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# ngIRCd -- The Next Generation IRC Daemon
+# Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# Please read the file COPYING, README and AUTHORS for more information.
+#
+# $Id: Makefile.am,v 1.6 2005/04/09 12:22:41 alex Exp $
+#
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_triplet = @host@
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+U = @U@
+VERSION = @VERSION@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+
+SUBDIRS = portab tool ngircd testsuite
+subdir = src
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES =
+DIST_SOURCES =
+
+RECURSIVE_TARGETS = info-recursive dvi-recursive pdf-recursive \
+	ps-recursive install-info-recursive uninstall-info-recursive \
+	all-recursive install-data-recursive install-exec-recursive \
+	installdirs-recursive install-recursive uninstall-recursive \
+	check-recursive installcheck-recursive
+DIST_COMMON = $(srcdir)/Makefile.in Makefile.am config.h.in
+DIST_SUBDIRS = $(SUBDIRS)
+all: config.h
+	$(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  Makefile.am  $(top_srcdir)/configure.in $(ACLOCAL_M4)
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  src/Makefile
+Makefile:  $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
+
+config.h: stamp-h1
+	@if test ! -f $@; then \
+	  rm -f stamp-h1; \
+	  $(MAKE) stamp-h1; \
+	else :; fi
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+	@rm -f stamp-h1
+	cd $(top_builddir) && $(SHELL) ./config.status src/config.h
+
+$(srcdir)/config.h.in:  $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+	cd $(top_srcdir) && $(AUTOHEADER)
+	touch $(srcdir)/config.h.in
+
+distclean-hdr:
+	-rm -f config.h stamp-h1
+uninstall-info-am:
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+	@set fnord $$MAKEFLAGS; amf=$$2; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	   || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+	@set fnord $$MAKEFLAGS; amf=$$2; \
+	dot_seen=no; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	rev=''; for subdir in $$list; do \
+	  if test "$$subdir" = "."; then :; else \
+	    rev="$$subdir $$rev"; \
+	  fi; \
+	done; \
+	rev="$$rev ."; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	   || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+ctags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+	done
+
+ETAGS = etags
+ETAGSFLAGS =
+
+CTAGS = ctags
+CTAGSFLAGS =
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	if (etags --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	else \
+	  include_option=--include; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -f $$subdir/TAGS && \
+	      tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(ETAGS_ARGS)$$tags$$unique" \
+	  || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	     $$tags $$unique
+
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkinstalldirs) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -d $(distdir)/$$subdir \
+	    || mkdir $(distdir)/$$subdir \
+	    || exit 1; \
+	    (cd $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$(top_distdir)" \
+	        distdir=../$(distdir)/$$subdir \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-recursive
+all-am: Makefile config.h
+installdirs: installdirs-recursive
+installdirs-am:
+
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-hdr distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-recursive
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic \
+	maintainer-clean-local
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+uninstall-info: uninstall-info-recursive
+
+.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am clean \
+	clean-generic clean-recursive ctags ctags-recursive distclean \
+	distclean-generic distclean-hdr distclean-recursive \
+	distclean-tags distdir dvi dvi-am dvi-recursive info info-am \
+	info-recursive install install-am install-data install-data-am \
+	install-data-recursive install-exec install-exec-am \
+	install-exec-recursive install-info install-info-am \
+	install-info-recursive install-man install-recursive \
+	install-strip installcheck installcheck-am installdirs \
+	installdirs-am installdirs-recursive maintainer-clean \
+	maintainer-clean-generic maintainer-clean-local \
+	maintainer-clean-recursive mostlyclean mostlyclean-generic \
+	mostlyclean-recursive pdf pdf-am pdf-recursive ps ps-am \
+	ps-recursive tags tags-recursive uninstall uninstall-am \
+	uninstall-info-am uninstall-info-recursive uninstall-recursive
+
+
+maintainer-clean-local:
+	rm -f Makefile Makefile.in config.h config.h.in stamp-h.in
+
+srcdoc:
+	@doxygen --version >/dev/null 2>&1 \
+	 || ( echo; echo "Error: \"doxygen\" not found!"; echo; exit 1 )
+	doxygen
+
+# -eof-
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:

+ 308 - 0
src/config.h.in

@@ -0,0 +1,308 @@
+/* src/config.h.in.  Generated from configure.in by autoheader.  */
+
+/* Define if debug-mode should be enabled */
+#undef DEBUG
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#undef HAVE_ARPA_INET_H
+
+/* Define to 1 if you have the `bind' function. */
+#undef HAVE_BIND
+
+/* Define to 1 if you have the <ctype.h> header file. */
+#undef HAVE_CTYPE_H
+
+/* Define to 1 if you have the `deflate' function. */
+#undef HAVE_DEFLATE
+
+/* Define to 1 if you have the <DNSServiceDiscovery/DNSServiceDiscovery.h>
+   header file. */
+#undef HAVE_DNSSERVICEDISCOVERY_DNSSERVICEDISCOVERY_H
+
+/* Define to 1 if you have the `DNSServiceRegistrationCreate' function. */
+#undef HAVE_DNSSERVICEREGISTRATIONCREATE
+
+/* Define to 1 if you have the <errno.h> header file. */
+#undef HAVE_ERRNO_H
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the `fork' function. */
+#undef HAVE_FORK
+
+/* Define to 1 if you have the `gethostbyaddr' function. */
+#undef HAVE_GETHOSTBYADDR
+
+/* Define to 1 if you have the `gethostbyname' function. */
+#undef HAVE_GETHOSTBYNAME
+
+/* Define to 1 if you have the `gethostname' function. */
+#undef HAVE_GETHOSTNAME
+
+/* Define to 1 if you have the <ident.h> header file. */
+#undef HAVE_IDENT_H
+
+/* Define to 1 if you have the `ident_id' function. */
+#undef HAVE_IDENT_ID
+
+/* Define to 1 if you have the `inet_aton' function. */
+#undef HAVE_INET_ATON
+
+/* Define to 1 if you have the `inet_ntoa' function. */
+#undef HAVE_INET_NTOA
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `isdigit' function. */
+#undef HAVE_ISDIGIT
+
+/* Define to 1 if you have the `be' library (-lbe). */
+#undef HAVE_LIBBE
+
+/* Define to 1 if you have the `howl' library (-lhowl). */
+#undef HAVE_LIBHOWL
+
+/* Define to 1 if you have the `ident' library (-lident). */
+#undef HAVE_LIBIDENT
+
+/* Define to 1 if you have the `nsl' library (-lnsl). */
+#undef HAVE_LIBNSL
+
+/* Define to 1 if you have the `pthread' library (-lpthread). */
+#undef HAVE_LIBPTHREAD
+
+/* Define to 1 if you have the `socket' library (-lsocket). */
+#undef HAVE_LIBSOCKET
+
+/* Define to 1 if you have the `UTIL' library (-lUTIL). */
+#undef HAVE_LIBUTIL
+
+/* Define to 1 if you have the `z' library (-lz). */
+#undef HAVE_LIBZ
+
+/* Define to 1 if you have the <mach/port.h> header file. */
+#undef HAVE_MACH_PORT_H
+
+/* Define to 1 if you have the `malloc' function. */
+#undef HAVE_MALLOC
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#undef HAVE_MALLOC_H
+
+/* Define to 1 if you have the `memmove' function. */
+#undef HAVE_MEMMOVE
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `memset' function. */
+#undef HAVE_MEMSET
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#undef HAVE_NETDB_H
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#undef HAVE_NETINET_IN_H
+
+/* Define to 1 if you have the `realloc' function. */
+#undef HAVE_REALLOC
+
+/* Define to 1 if you have the <rendezvous/rendezvous.h> header file. */
+#undef HAVE_RENDEZVOUS_RENDEZVOUS_H
+
+/* Define to 1 if you have the `select' function. */
+#undef HAVE_SELECT
+
+/* Define to 1 if you have the `setsid' function. */
+#undef HAVE_SETSID
+
+/* Define to 1 if you have the `setsockopt' function. */
+#undef HAVE_SETSOCKOPT
+
+/* Define to 1 if you have the `sigaction' function. */
+#undef HAVE_SIGACTION
+
+/* Define to 1 if you have the `snprintf' function. */
+#undef HAVE_SNPRINTF
+
+/* Define to 1 if you have the `socket' function. */
+#undef HAVE_SOCKET
+
+/* Define to 1 if you have the <stdbool.h> header file. */
+#undef HAVE_STDBOOL_H
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#undef HAVE_STDDEF_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#undef HAVE_STRCASECMP
+
+/* Define to 1 if you have the `strchr' function. */
+#undef HAVE_STRCHR
+
+/* Define to 1 if you have the `strdup' function. */
+#undef HAVE_STRDUP
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* Define to 1 if you have the `strftime' function. */
+#undef HAVE_STRFTIME
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strlcat' function. */
+#undef HAVE_STRLCAT
+
+/* Define to 1 if you have the `strlcpy' function. */
+#undef HAVE_STRLCPY
+
+/* Define to 1 if you have the `strstr' function. */
+#undef HAVE_STRSTR
+
+/* Define to 1 if you have the `sw_discovery_init' function. */
+#undef HAVE_SW_DISCOVERY_INIT
+
+/* Define to 1 if you have the `syslog' function. */
+#undef HAVE_SYSLOG
+
+/* Define to 1 if you have the <syslog.h> header file. */
+#undef HAVE_SYSLOG_H
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
+#undef HAVE_SYS_WAIT_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the <varargs.h> header file. */
+#undef HAVE_VARARGS_H
+
+/* Define to 1 if you have the `vfork' function. */
+#undef HAVE_VFORK
+
+/* Define to 1 if you have the <vfork.h> header file. */
+#undef HAVE_VFORK_H
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#undef HAVE_VSNPRINTF
+
+/* Define to 1 if you have the `waitpid' function. */
+#undef HAVE_WAITPID
+
+/* Define to 1 if `fork' works. */
+#undef HAVE_WORKING_FORK
+
+/* Define to 1 if `vfork' works. */
+#undef HAVE_WORKING_VFORK
+
+/* Define to 1 if you have the <zlib.h> header file. */
+#undef HAVE_ZLIB_H
+
+/* Define if socklen_t exists */
+#undef HAVE_socklen_t
+
+/* Define if the server should do IDENT requests */
+#undef IDENTAUTH
+
+/* Define if IRC+ protocol should be used */
+#undef IRCPLUS
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define if compiler has function prototypes */
+#undef PROTOTYPES
+
+/* Define if Rendezvous support should be included */
+#undef RENDEZVOUS
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#undef RETSIGTYPE
+
+/* Define if IRC sniffer should be enabled */
+#undef SNIFFER
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define if ngIRCd should behave strict RFC compliant */
+#undef STRICT_RFC
+
+/* Define if syslog should be used for logging */
+#undef SYSLOG
+
+/* Target CPU name */
+#undef TARGET_CPU
+
+/* Target operating system name */
+#undef TARGET_OS
+
+/* Target system vendor */
+#undef TARGET_VENDOR
+
+/* Define if TCP wrappers should be used */
+#undef TCPWRAP
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Version number of package */
+#undef VERSION
+
+/* Define if zlib compression should be enabled */
+#undef ZLIB
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef pid_t
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define as `fork' if `vfork' does not work. */
+#undef vfork

+ 99 - 0
src/ngircd/Makefile.am

@@ -0,0 +1,99 @@
+#
+# ngIRCd -- The Next Generation IRC Daemon
+# Copyright (c)2001-2003 by Alexander Barton (alex@barton.de)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# Please read the file COPYING, README and AUTHORS for more information.
+#
+# $Id: Makefile.am,v 1.46 2005/05/23 00:11:15 alex Exp $
+#
+
+AUTOMAKE_OPTIONS = ../portab/ansi2knr
+
+INCLUDES = -I$(srcdir)/../portab -I$(srcdir)/../tool
+
+LINTARGS = -weak -warnunixlib +unixlib -booltype BOOLEAN \
+ -varuse -retvalother -emptyret -unrecog
+
+sbin_PROGRAMS = ngircd
+
+ngircd_SOURCES = ngircd.c channel.c client.c conf.c conn.c conn-zip.c conn-func.c \
+	hash.c irc.c irc-channel.c irc-info.c irc-login.c irc-mode.c irc-op.c \
+	irc-oper.c irc-server.c irc-write.c lists.c log.c match.c parse.c \
+	rendezvous.c resolve.c
+
+ngircd_LDFLAGS = -L../portab -L../tool
+
+ngircd_LDADD = -lngportab -lngtool
+
+noinst_HEADERS = ngircd.h channel.h client.h conf.h conn.h conn-zip.h conn-func.h \
+	hash.h irc.h irc-channel.h irc-info.h irc-login.h irc-mode.h irc-op.h \
+	irc-oper.h irc-server.h irc-write.h lists.h log.h match.h parse.h \
+	rendezvous.h resolve.h \
+	messages.h defines.h
+
+clean-local:
+	rm -f check-version check-help lint.out cvs-version.*
+
+maintainer-clean-local:
+	rm -f Makefile Makefile.in
+
+check-version: Makefile
+	echo "#!/bin/sh" > check-version
+	echo "./ngircd --version | grep ngircd > /dev/null 2>&1" >> check-version
+	chmod 755 check-version
+
+check-help: Makefile
+	echo "#!/bin/sh" > check-help
+	echo "./ngircd --help | grep help > /dev/null 2>&1" >> check-help
+	chmod 755 check-help
+
+lint:
+	@splint --version >/dev/null 2>&1 \
+	 || ( echo; echo "Error: \"splint\" not found!"; echo; exit 1 )
+	@echo; warnings=0; files=0; \
+	for f in *.c; do \
+	 echo "checking $$f ..."; \
+	 splint $$f $(LINTARGS) -I$(srcdir) -I$(srcdir)/.. \
+	  $(INCLUDES) $(AM_CFLAGS) >lint.out 2>&1; \
+	 grep "no warnings" lint.out > /dev/null 2>&1; \
+	 if [ $$? -ne 0 ]; then \
+	  waswarning=1; \
+	  echo; grep -v "^Command Line: " lint.out; echo; \
+	  w=$$( grep "code warning" lint.out | awk "{ print \$$4 }" ); \
+	  [ "$$w" -gt 0 ] && warnings=`expr $$warnings + $$w`; \
+	  files=`expr $$files + 1`; \
+	 else \
+	  waswarning=0; \
+	 fi; \
+	 rm -f lint.out; \
+	done; \
+	[ $$waswarning -eq 0 ] && echo; \
+	[ $$warnings -gt 0 ] \
+	 && echo "Result: $$warnings warning(s) in $$files file(s)!" \
+	 || echo "Result: no warnings found."; \
+	echo; [ $$warnings -gt 0 ] && exit 1
+
+ngircd.c: cvs-version.h
+
+irc-login.c: cvs-version.h
+
+irc-info.c: cvs-version.h
+
+cvs-version.h: cvs-date
+
+cvs-date:
+	grep VERSION ../config.h | grep "CVS" \
+	 && echo "#define CVSDATE \"$$( grep "\$$Id" $(srcdir)/*.c \
+	    | $(AWK) "{ print \$$9 }" | sort | tail -1 \
+	    | sed -e "s/\//-/g" )\"" > cvs-version.new \
+	 || echo "" > cvs-version.new
+	diff cvs-version.h cvs-version.new 2>/dev/null \
+	 || cp cvs-version.new cvs-version.h
+
+TESTS = check-version check-help
+
+# -eof-

+ 675 - 0
src/ngircd/Makefile.in

@@ -0,0 +1,675 @@
+# Makefile.in generated by automake 1.7.9 from Makefile.am.
+# @configure_input@
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# ngIRCd -- The Next Generation IRC Daemon
+# Copyright (c)2001-2003 by Alexander Barton (alex@barton.de)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# Please read the file COPYING, README and AUTHORS for more information.
+#
+# $Id: Makefile.am,v 1.46 2005/05/23 00:11:15 alex Exp $
+#
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../..
+
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_triplet = @host@
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+U = @U@
+VERSION = @VERSION@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+
+AUTOMAKE_OPTIONS = ../portab/ansi2knr
+
+INCLUDES = -I$(srcdir)/../portab -I$(srcdir)/../tool
+
+LINTARGS = -weak -warnunixlib +unixlib -booltype BOOLEAN \
+ -varuse -retvalother -emptyret -unrecog
+
+
+sbin_PROGRAMS = ngircd
+
+ngircd_SOURCES = ngircd.c channel.c client.c conf.c conn.c conn-zip.c conn-func.c \
+	hash.c irc.c irc-channel.c irc-info.c irc-login.c irc-mode.c irc-op.c \
+	irc-oper.c irc-server.c irc-write.c lists.c log.c match.c parse.c \
+	rendezvous.c resolve.c
+
+
+ngircd_LDFLAGS = -L../portab -L../tool
+
+ngircd_LDADD = -lngportab -lngtool
+
+noinst_HEADERS = ngircd.h channel.h client.h conf.h conn.h conn-zip.h conn-func.h \
+	hash.h irc.h irc-channel.h irc-info.h irc-login.h irc-mode.h irc-op.h \
+	irc-oper.h irc-server.h irc-write.h lists.h log.h match.h parse.h \
+	rendezvous.h resolve.h \
+	messages.h defines.h
+
+
+TESTS = check-version check-help
+subdir = src/ngircd
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/src/config.h
+CONFIG_CLEAN_FILES =
+sbin_PROGRAMS = ngircd$(EXEEXT)
+PROGRAMS = $(sbin_PROGRAMS)
+
+am_ngircd_OBJECTS = ngircd$U.$(OBJEXT) channel$U.$(OBJEXT) \
+	client$U.$(OBJEXT) conf$U.$(OBJEXT) conn$U.$(OBJEXT) \
+	conn-zip$U.$(OBJEXT) conn-func$U.$(OBJEXT) hash$U.$(OBJEXT) \
+	irc$U.$(OBJEXT) irc-channel$U.$(OBJEXT) irc-info$U.$(OBJEXT) \
+	irc-login$U.$(OBJEXT) irc-mode$U.$(OBJEXT) irc-op$U.$(OBJEXT) \
+	irc-oper$U.$(OBJEXT) irc-server$U.$(OBJEXT) \
+	irc-write$U.$(OBJEXT) lists$U.$(OBJEXT) log$U.$(OBJEXT) \
+	match$U.$(OBJEXT) parse$U.$(OBJEXT) rendezvous$U.$(OBJEXT) \
+	resolve$U.$(OBJEXT)
+ngircd_OBJECTS = $(am_ngircd_OBJECTS)
+ngircd_DEPENDENCIES =
+
+DEFAULT_INCLUDES =  -I. -I$(srcdir) -I$(top_builddir)/src
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/channel$U.Po ./$(DEPDIR)/client$U.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/conf$U.Po ./$(DEPDIR)/conn$U.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/conn-func$U.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/conn-zip$U.Po ./$(DEPDIR)/hash$U.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/irc$U.Po ./$(DEPDIR)/irc-channel$U.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/irc-info$U.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/irc-login$U.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/irc-mode$U.Po ./$(DEPDIR)/irc-op$U.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/irc-oper$U.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/irc-server$U.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/irc-write$U.Po ./$(DEPDIR)/lists$U.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/log$U.Po ./$(DEPDIR)/match$U.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/ngircd$U.Po ./$(DEPDIR)/parse$U.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/rendezvous$U.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/resolve$U.Po
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+DIST_SOURCES = $(ngircd_SOURCES)
+HEADERS = $(noinst_HEADERS)
+
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.in Makefile.am
+SOURCES = $(ngircd_SOURCES)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in:  Makefile.am  $(top_srcdir)/configure.in $(ACLOCAL_M4)
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  src/ngircd/Makefile
+Makefile:  $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
+sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(sbindir)
+	@list='$(sbin_PROGRAMS)'; for p in $$list; do \
+	  p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+	  if test -f $$p \
+	  ; then \
+	    f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+	   echo " $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f"; \
+	   $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f || exit 1; \
+	  else :; fi; \
+	done
+
+uninstall-sbinPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(sbin_PROGRAMS)'; for p in $$list; do \
+	  f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+	  echo " rm -f $(DESTDIR)$(sbindir)/$$f"; \
+	  rm -f $(DESTDIR)$(sbindir)/$$f; \
+	done
+
+clean-sbinPROGRAMS:
+	-test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS)
+ngircd$(EXEEXT): $(ngircd_OBJECTS) $(ngircd_DEPENDENCIES) 
+	@rm -f ngircd$(EXEEXT)
+	$(LINK) $(ngircd_LDFLAGS) $(ngircd_OBJECTS) $(ngircd_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT) core *.core
+
+distclean-compile:
+	-rm -f *.tab.c
+
+ANSI2KNR = ../portab/ansi2knr
+../portab/ansi2knr:
+	cd ../portab && $(MAKE) $(AM_MAKEFLAGS) ansi2knr
+
+mostlyclean-kr:
+	-test "$U" = "" || rm -f *_.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conn$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conn-func$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conn-zip$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/irc$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/irc-channel$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/irc-info$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/irc-login$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/irc-mode$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/irc-op$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/irc-oper$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/irc-server$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/irc-write$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lists$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/match$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ngircd$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rendezvous$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resolve$U.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
+@am__fastdepCC_TRUE@	  -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \
+@am__fastdepCC_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
+@am__fastdepCC_TRUE@	else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
+@am__fastdepCC_TRUE@	fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$<
+
+.c.obj:
+@am__fastdepCC_TRUE@	if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
+@am__fastdepCC_TRUE@	  -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \
+@am__fastdepCC_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
+@am__fastdepCC_TRUE@	else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
+@am__fastdepCC_TRUE@	fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`
+channel_.c: channel.c $(ANSI2KNR)
+	$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/channel.c; then echo $(srcdir)/channel.c; else echo channel.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+client_.c: client.c $(ANSI2KNR)
+	$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/client.c; then echo $(srcdir)/client.c; else echo client.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+conf_.c: conf.c $(ANSI2KNR)
+	$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/conf.c; then echo $(srcdir)/conf.c; else echo conf.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+conn_.c: conn.c $(ANSI2KNR)
+	$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/conn.c; then echo $(srcdir)/conn.c; else echo conn.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+conn-func_.c: conn-func.c $(ANSI2KNR)
+	$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/conn-func.c; then echo $(srcdir)/conn-func.c; else echo conn-func.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+conn-zip_.c: conn-zip.c $(ANSI2KNR)
+	$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/conn-zip.c; then echo $(srcdir)/conn-zip.c; else echo conn-zip.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+hash_.c: hash.c $(ANSI2KNR)
+	$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/hash.c; then echo $(srcdir)/hash.c; else echo hash.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+irc_.c: irc.c $(ANSI2KNR)
+	$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/irc.c; then echo $(srcdir)/irc.c; else echo irc.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+irc-channel_.c: irc-channel.c $(ANSI2KNR)
+	$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/irc-channel.c; then echo $(srcdir)/irc-channel.c; else echo irc-channel.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+irc-info_.c: irc-info.c $(ANSI2KNR)
+	$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/irc-info.c; then echo $(srcdir)/irc-info.c; else echo irc-info.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+irc-login_.c: irc-login.c $(ANSI2KNR)
+	$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/irc-login.c; then echo $(srcdir)/irc-login.c; else echo irc-login.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+irc-mode_.c: irc-mode.c $(ANSI2KNR)
+	$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/irc-mode.c; then echo $(srcdir)/irc-mode.c; else echo irc-mode.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+irc-op_.c: irc-op.c $(ANSI2KNR)
+	$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/irc-op.c; then echo $(srcdir)/irc-op.c; else echo irc-op.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+irc-oper_.c: irc-oper.c $(ANSI2KNR)
+	$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/irc-oper.c; then echo $(srcdir)/irc-oper.c; else echo irc-oper.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+irc-server_.c: irc-server.c $(ANSI2KNR)
+	$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/irc-server.c; then echo $(srcdir)/irc-server.c; else echo irc-server.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+irc-write_.c: irc-write.c $(ANSI2KNR)
+	$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/irc-write.c; then echo $(srcdir)/irc-write.c; else echo irc-write.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+lists_.c: lists.c $(ANSI2KNR)
+	$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/lists.c; then echo $(srcdir)/lists.c; else echo lists.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+log_.c: log.c $(ANSI2KNR)
+	$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/log.c; then echo $(srcdir)/log.c; else echo log.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+match_.c: match.c $(ANSI2KNR)
+	$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/match.c; then echo $(srcdir)/match.c; else echo match.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+ngircd_.c: ngircd.c $(ANSI2KNR)
+	$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ngircd.c; then echo $(srcdir)/ngircd.c; else echo ngircd.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+parse_.c: parse.c $(ANSI2KNR)
+	$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/parse.c; then echo $(srcdir)/parse.c; else echo parse.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+rendezvous_.c: rendezvous.c $(ANSI2KNR)
+	$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/rendezvous.c; then echo $(srcdir)/rendezvous.c; else echo rendezvous.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+resolve_.c: resolve.c $(ANSI2KNR)
+	$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/resolve.c; then echo $(srcdir)/resolve.c; else echo resolve.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+channel_.$(OBJEXT) client_.$(OBJEXT) conf_.$(OBJEXT) conn_.$(OBJEXT) \
+conn-func_.$(OBJEXT) conn-zip_.$(OBJEXT) hash_.$(OBJEXT) irc_.$(OBJEXT) \
+irc-channel_.$(OBJEXT) irc-info_.$(OBJEXT) irc-login_.$(OBJEXT) \
+irc-mode_.$(OBJEXT) irc-op_.$(OBJEXT) irc-oper_.$(OBJEXT) \
+irc-server_.$(OBJEXT) irc-write_.$(OBJEXT) lists_.$(OBJEXT) \
+log_.$(OBJEXT) match_.$(OBJEXT) ngircd_.$(OBJEXT) parse_.$(OBJEXT) \
+rendezvous_.$(OBJEXT) resolve_.$(OBJEXT) : $(ANSI2KNR)
+uninstall-info-am:
+
+ETAGS = etags
+ETAGSFLAGS =
+
+CTAGS = ctags
+CTAGSFLAGS =
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(ETAGS_ARGS)$$tags$$unique" \
+	  || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	     $$tags $$unique
+
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+	@failed=0; all=0; xfail=0; xpass=0; skip=0; \
+	srcdir=$(srcdir); export srcdir; \
+	list='$(TESTS)'; \
+	if test -n "$$list"; then \
+	  for tst in $$list; do \
+	    if test -f ./$$tst; then dir=./; \
+	    elif test -f $$tst; then dir=; \
+	    else dir="$(srcdir)/"; fi; \
+	    if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
+	      all=`expr $$all + 1`; \
+	      case " $(XFAIL_TESTS) " in \
+	      *" $$tst "*) \
+	        xpass=`expr $$xpass + 1`; \
+	        failed=`expr $$failed + 1`; \
+	        echo "XPASS: $$tst"; \
+	      ;; \
+	      *) \
+	        echo "PASS: $$tst"; \
+	      ;; \
+	      esac; \
+	    elif test $$? -ne 77; then \
+	      all=`expr $$all + 1`; \
+	      case " $(XFAIL_TESTS) " in \
+	      *" $$tst "*) \
+	        xfail=`expr $$xfail + 1`; \
+	        echo "XFAIL: $$tst"; \
+	      ;; \
+	      *) \
+	        failed=`expr $$failed + 1`; \
+	        echo "FAIL: $$tst"; \
+	      ;; \
+	      esac; \
+	    else \
+	      skip=`expr $$skip + 1`; \
+	      echo "SKIP: $$tst"; \
+	    fi; \
+	  done; \
+	  if test "$$failed" -eq 0; then \
+	    if test "$$xfail" -eq 0; then \
+	      banner="All $$all tests passed"; \
+	    else \
+	      banner="All $$all tests behaved as expected ($$xfail expected failures)"; \
+	    fi; \
+	  else \
+	    if test "$$xpass" -eq 0; then \
+	      banner="$$failed of $$all tests failed"; \
+	    else \
+	      banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \
+	    fi; \
+	  fi; \
+	  dashes="$$banner"; \
+	  skipped=""; \
+	  if test "$$skip" -ne 0; then \
+	    skipped="($$skip tests were not run)"; \
+	    test `echo "$$skipped" | wc -c` -gt `echo "$$banner" | wc -c` && \
+	      dashes="$$skipped"; \
+	  fi; \
+	  report=""; \
+	  if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+	    report="Please report to $(PACKAGE_BUGREPORT)"; \
+	    test `echo "$$report" | wc -c` -gt `echo "$$banner" | wc -c` && \
+	      dashes="$$report"; \
+	  fi; \
+	  dashes=`echo "$$dashes" | sed s/./=/g`; \
+	  echo "$$dashes"; \
+	  echo "$$banner"; \
+	  test -n "$$skipped" && echo "$$skipped"; \
+	  test -n "$$report" && echo "$$report"; \
+	  echo "$$dashes"; \
+	  test "$$failed" -eq 0; \
+	else :; fi
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ../..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkinstalldirs) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+	$(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile $(PROGRAMS) $(HEADERS)
+
+installdirs:
+	$(mkinstalldirs) $(DESTDIR)$(sbindir)
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-local clean-sbinPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am: install-sbinPROGRAMS
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic \
+	maintainer-clean-local
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic mostlyclean-kr
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am uninstall-sbinPROGRAMS
+
+.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \
+	clean-generic clean-local clean-sbinPROGRAMS ctags distclean \
+	distclean-compile distclean-generic distclean-tags distdir dvi \
+	dvi-am info info-am install install-am install-data \
+	install-data-am install-exec install-exec-am install-info \
+	install-info-am install-man install-sbinPROGRAMS install-strip \
+	installcheck installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic maintainer-clean-local mostlyclean \
+	mostlyclean-compile mostlyclean-generic mostlyclean-kr pdf \
+	pdf-am ps ps-am tags uninstall uninstall-am uninstall-info-am \
+	uninstall-sbinPROGRAMS
+
+
+clean-local:
+	rm -f check-version check-help lint.out cvs-version.*
+
+maintainer-clean-local:
+	rm -f Makefile Makefile.in
+
+check-version: Makefile
+	echo "#!/bin/sh" > check-version
+	echo "./ngircd --version | grep ngircd > /dev/null 2>&1" >> check-version
+	chmod 755 check-version
+
+check-help: Makefile
+	echo "#!/bin/sh" > check-help
+	echo "./ngircd --help | grep help > /dev/null 2>&1" >> check-help
+	chmod 755 check-help
+
+lint:
+	@splint --version >/dev/null 2>&1 \
+	 || ( echo; echo "Error: \"splint\" not found!"; echo; exit 1 )
+	@echo; warnings=0; files=0; \
+	for f in *.c; do \
+	 echo "checking $$f ..."; \
+	 splint $$f $(LINTARGS) -I$(srcdir) -I$(srcdir)/.. \
+	  $(INCLUDES) $(AM_CFLAGS) >lint.out 2>&1; \
+	 grep "no warnings" lint.out > /dev/null 2>&1; \
+	 if [ $$? -ne 0 ]; then \
+	  waswarning=1; \
+	  echo; grep -v "^Command Line: " lint.out; echo; \
+	  w=$$( grep "code warning" lint.out | awk "{ print \$$4 }" ); \
+	  [ "$$w" -gt 0 ] && warnings=`expr $$warnings + $$w`; \
+	  files=`expr $$files + 1`; \
+	 else \
+	  waswarning=0; \
+	 fi; \
+	 rm -f lint.out; \
+	done; \
+	[ $$waswarning -eq 0 ] && echo; \
+	[ $$warnings -gt 0 ] \
+	 && echo "Result: $$warnings warning(s) in $$files file(s)!" \
+	 || echo "Result: no warnings found."; \
+	echo; [ $$warnings -gt 0 ] && exit 1
+
+ngircd.c: cvs-version.h
+
+irc-login.c: cvs-version.h
+
+irc-info.c: cvs-version.h
+
+cvs-version.h: cvs-date
+
+cvs-date:
+	grep VERSION ../config.h | grep "CVS" \
+	 && echo "#define CVSDATE \"$$( grep "\$$Id" $(srcdir)/*.c \
+	    | $(AWK) "{ print \$$9 }" | sort | tail -1 \
+	    | sed -e "s/\//-/g" )\"" > cvs-version.new \
+	 || echo "" > cvs-version.new
+	diff cvs-version.h cvs-version.new 2>/dev/null \
+	 || cp cvs-version.new cvs-version.h
+
+# -eof-
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:

+ 896 - 0
src/ngircd/channel.c

@@ -0,0 +1,896 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001-2005 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * Channel management
+ */
+
+
+#define __channel_c__
+
+
+#include "portab.h"
+
+static char UNUSED id[] = "$Id: channel.c,v 1.50 2005/06/18 08:57:37 fw Exp $";
+
+#include "imp.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+
+#include "defines.h"
+#include "conn-func.h"
+#include "client.h"
+
+#include "exp.h"
+#include "channel.h"
+
+#include "imp.h"
+#include "irc-write.h"
+#include "resolve.h"
+#include "conf.h"
+#include "hash.h"
+#include "lists.h"
+#include "log.h"
+#include "messages.h"
+
+#include "exp.h"
+
+
+#define REMOVE_PART 0
+#define REMOVE_QUIT 1
+#define REMOVE_KICK 2
+
+
+LOCAL CHANNEL *My_Channels;
+LOCAL CL2CHAN *My_Cl2Chan;
+
+
+LOCAL CL2CHAN *Get_Cl2Chan PARAMS(( CHANNEL *Chan, CLIENT *Client ));
+LOCAL CL2CHAN *Add_Client PARAMS(( CHANNEL *Chan, CLIENT *Client ));
+LOCAL bool Remove_Client PARAMS(( int Type, CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, char *Reason, bool InformServer ));
+LOCAL CL2CHAN *Get_First_Cl2Chan PARAMS(( CLIENT *Client, CHANNEL *Chan ));
+LOCAL CL2CHAN *Get_Next_Cl2Chan PARAMS(( CL2CHAN *Start, CLIENT *Client, CHANNEL *Chan ));
+LOCAL bool Delete_Channel PARAMS(( CHANNEL *Chan ));
+
+
+GLOBAL void
+Channel_Init( void )
+{
+	My_Channels = NULL;
+	My_Cl2Chan = NULL;
+} /* Channel_Init */
+
+
+GLOBAL void
+Channel_InitPredefined( void )
+{
+	/* Vordefinierte persistente Channels erzeugen */
+
+	CHANNEL *chan;
+	char *c;
+	int i;
+	
+	for( i = 0; i < Conf_Channel_Count; i++ )
+	{
+		/* Ist ein Name konfiguriert? */
+		if( ! Conf_Channel[i].name[0] ) continue;
+
+		/* Gueltiger Channel-Name? */
+		if( ! Channel_IsValidName( Conf_Channel[i].name ))
+		{
+			Log( LOG_ERR, "Can't create pre-defined channel: invalid name: \"%s\"!", Conf_Channel[i].name );
+			continue;
+		}
+
+		/* Gibt es den Channel bereits? */
+		chan = Channel_Search( Conf_Channel[i].name );
+		if( chan )
+		{
+			Log( LOG_INFO, "Can't create pre-defined channel \"%s\": name already in use.", Conf_Channel[i].name );
+			continue;
+		}
+		
+		/* Channel anlegen */
+		chan = Channel_Create( Conf_Channel[i].name );
+		if( chan )
+		{
+			Channel_ModeAdd( chan, 'P' );
+			Channel_SetTopic( chan, Conf_Channel[i].topic );
+			c = Conf_Channel[i].modes;
+			while( *c ) Channel_ModeAdd( chan, *c++ );
+			Log( LOG_INFO, "Created pre-defined channel \"%s\".", Conf_Channel[i].name );
+		}
+		else Log( LOG_ERR, "Can't create pre-defined channel \"%s\"!", Conf_Channel[i].name );
+	}
+} /* Channel_InitPredefined */
+
+
+GLOBAL void
+Channel_Exit( void )
+{
+	CHANNEL *c, *c_next;
+	CL2CHAN *cl2chan, *cl2chan_next;
+	
+	/* Channel-Strukturen freigeben */
+	c = My_Channels;
+	while( c )
+	{
+		c_next = c->next;
+		free( c );
+		c = c_next;
+	}
+
+	/* Channel-Zuordnungstabelle freigeben */
+	cl2chan = My_Cl2Chan;
+	while( c )
+	{
+		cl2chan_next = cl2chan->next;
+		free( cl2chan );
+		cl2chan = cl2chan_next;
+	}
+} /* Channel_Exit */
+
+
+GLOBAL bool
+Channel_Join( CLIENT *Client, char *Name )
+{
+	CHANNEL *chan;
+	
+	assert( Client != NULL );
+	assert( Name != NULL );
+
+	/* Valider Channel-Name? */
+	if( ! Channel_IsValidName( Name ))
+	{
+		IRC_WriteStrClient( Client, ERR_NOSUCHCHANNEL_MSG, Client_ID( Client ), Name );
+		return false;
+	}
+
+	/* Channel suchen */
+	chan = Channel_Search( Name );
+	if( chan )
+	{
+		/* Ist der Client bereits Mitglied? */
+		if( Get_Cl2Chan( chan, Client )) return false;
+	}
+	else
+	{
+		/* Gibt es noch nicht? Dann neu anlegen: */
+		chan = Channel_Create( Name );
+		if( ! chan ) return false;
+	}
+
+	/* User dem Channel hinzufuegen */
+	if( ! Add_Client( chan, Client )) return false;
+	else return true;
+} /* Channel_Join */
+
+
+GLOBAL bool
+Channel_Part( CLIENT *Client, CLIENT *Origin, char *Name, char *Reason )
+{
+	CHANNEL *chan;
+
+	assert( Client != NULL );
+	assert( Name != NULL );
+	assert( Reason != NULL );
+
+	/* Channel suchen */
+	chan = Channel_Search( Name );
+	if(( ! chan ) || ( ! Get_Cl2Chan( chan, Client )))
+	{
+		IRC_WriteStrClient( Client, ERR_NOSUCHCHANNEL_MSG, Client_ID( Client ), Name );
+		return false;
+	}
+
+	/* User aus Channel entfernen */
+	if( ! Remove_Client( REMOVE_PART, chan, Client, Origin, Reason, true)) return false;
+	else return true;
+} /* Channel_Part */
+
+
+GLOBAL void
+Channel_Kick( CLIENT *Client, CLIENT *Origin, char *Name, char *Reason )
+{
+	CHANNEL *chan;
+
+	assert( Client != NULL );
+	assert( Origin != NULL );
+	assert( Name != NULL );
+	assert( Reason != NULL );
+
+	/* Channel suchen */
+	chan = Channel_Search( Name );
+	if( ! chan )
+	{
+		IRC_WriteStrClient( Origin, ERR_NOSUCHCHANNEL_MSG, Client_ID( Origin ), Name );
+		return;
+	}
+
+	/* Ist der User Mitglied in dem Channel? */
+	if( ! Channel_IsMemberOf( chan, Origin ))
+	{
+		IRC_WriteStrClient( Origin, ERR_NOTONCHANNEL_MSG, Client_ID( Origin ), Name );
+		return;
+	}
+
+	/* Ist der User Channel-Operator? */
+	if( ! strchr( Channel_UserModes( chan, Origin ), 'o' ))
+	{
+		IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Name);
+		return;
+	}
+
+	/* Ist der Ziel-User Mitglied im Channel? */
+	if( ! Channel_IsMemberOf( chan, Client ))
+	{
+		IRC_WriteStrClient( Origin, ERR_USERNOTINCHANNEL_MSG, Client_ID( Origin ), Client_ID( Client ), Name );
+		return;
+	}
+
+	Remove_Client( REMOVE_KICK, chan, Client, Origin, Reason, true);
+} /* Channel_Kick */
+
+
+GLOBAL void
+Channel_Quit( CLIENT *Client, char *Reason )
+{
+	CHANNEL *c, *next_c;
+
+	assert( Client != NULL );
+	assert( Reason != NULL );
+
+	IRC_WriteStrRelatedPrefix( Client, Client, false, "QUIT :%s", Reason );
+
+	c = My_Channels;
+	while( c )
+	{
+		next_c = c->next;
+		Remove_Client( REMOVE_QUIT, c, Client, Client, Reason, false );
+		c = next_c;
+	}
+} /* Channel_Quit */
+
+
+GLOBAL long
+Channel_Count( void )
+{
+	CHANNEL *c;
+	long count = 0;
+	
+	c = My_Channels;
+	while( c )
+	{
+		count++;
+		c = c->next;
+	}
+	return count;
+} /* Channel_Count */
+
+
+GLOBAL long
+Channel_MemberCount( CHANNEL *Chan )
+{
+	CL2CHAN *cl2chan;
+	long count = 0;
+
+	assert( Chan != NULL );
+
+	cl2chan = My_Cl2Chan;
+	while( cl2chan )
+	{
+		if( cl2chan->channel == Chan ) count++;
+		cl2chan = cl2chan->next;
+	}
+	return count;
+} /* Channel_MemberCount */
+
+
+GLOBAL int
+Channel_CountForUser( CLIENT *Client )
+{
+	/* Count number of channels a user is member of. */
+
+	CL2CHAN *cl2chan;
+	int count = 0;
+	
+	assert( Client != NULL );
+	
+	cl2chan = My_Cl2Chan;
+	while( cl2chan )
+	{
+		if( cl2chan->client == Client ) count++;
+		cl2chan = cl2chan->next;
+	}
+
+	return count;
+} /* Channel_CountForUser */
+
+
+GLOBAL int
+Channel_PCount( void )
+{
+	/* Count the number of persistent (mode 'P') channels */
+
+	CHANNEL *chan;
+	int count = 0;
+
+	chan = My_Channels;
+	while( chan )
+	{
+		if( strchr( chan->modes, 'P' )) count++;
+		chan = chan->next;
+	}
+
+	return count;
+} /* Channel_PCount */
+
+
+GLOBAL char *
+Channel_Name( CHANNEL *Chan )
+{
+	assert( Chan != NULL );
+	return Chan->name;
+} /* Channel_Name */
+
+
+GLOBAL char *
+Channel_Modes( CHANNEL *Chan )
+{
+	assert( Chan != NULL );
+	return Chan->modes;
+} /* Channel_Modes */
+
+
+GLOBAL char *
+Channel_Key( CHANNEL *Chan )
+{
+	assert( Chan != NULL );
+	return Chan->key;
+} /* Channel_Key */
+
+
+GLOBAL long
+Channel_MaxUsers( CHANNEL *Chan )
+{
+	assert( Chan != NULL );
+	return Chan->maxusers;
+} /* Channel_MaxUsers */
+
+
+GLOBAL CHANNEL *
+Channel_First( void )
+{
+	return My_Channels;
+} /* Channel_First */
+
+
+GLOBAL CHANNEL *
+Channel_Next( CHANNEL *Chan )
+{
+	assert( Chan != NULL );
+	return Chan->next;
+} /* Channel_Next */
+
+
+GLOBAL CHANNEL *
+Channel_Search( char *Name )
+{
+	/* Channel-Struktur suchen */
+	
+	CHANNEL *c;
+	UINT32 search_hash;
+
+	assert( Name != NULL );
+
+	search_hash = Hash( Name );
+	c = My_Channels;
+	while( c )
+	{
+		if( search_hash == c->hash )
+		{
+			/* lt. Hash-Wert: Treffer! */
+			if( strcasecmp( Name, c->name ) == 0 ) return c;
+		}
+		c = c->next;
+	}
+	return NULL;
+} /* Channel_Search */
+
+
+GLOBAL CL2CHAN *
+Channel_FirstMember( CHANNEL *Chan )
+{
+	assert( Chan != NULL );
+	return Get_First_Cl2Chan( NULL, Chan );
+} /* Channel_FirstMember */
+
+
+GLOBAL CL2CHAN *
+Channel_NextMember( CHANNEL *Chan, CL2CHAN *Cl2Chan )
+{
+	assert( Chan != NULL );
+	assert( Cl2Chan != NULL );
+	return Get_Next_Cl2Chan( Cl2Chan->next, NULL, Chan );
+} /* Channel_NextMember */
+
+
+GLOBAL CL2CHAN *
+Channel_FirstChannelOf( CLIENT *Client )
+{
+	assert( Client != NULL );
+	return Get_First_Cl2Chan( Client, NULL );
+} /* Channel_FirstChannelOf */
+
+
+GLOBAL CL2CHAN *
+Channel_NextChannelOf( CLIENT *Client, CL2CHAN *Cl2Chan )
+{
+	assert( Client != NULL );
+	assert( Cl2Chan != NULL );
+	return Get_Next_Cl2Chan( Cl2Chan->next, Client, NULL );
+} /* Channel_NextChannelOf */
+
+
+GLOBAL CLIENT *
+Channel_GetClient( CL2CHAN *Cl2Chan )
+{
+	assert( Cl2Chan != NULL );
+	return Cl2Chan->client;
+} /* Channel_GetClient */
+
+
+GLOBAL CHANNEL *
+Channel_GetChannel( CL2CHAN *Cl2Chan )
+{
+	assert( Cl2Chan != NULL );
+	return Cl2Chan->channel;
+} /* Channel_GetChannel */
+
+
+GLOBAL bool
+Channel_IsValidName( char *Name )
+{
+	/* Pruefen, ob Name als Channelname gueltig */
+
+	char *ptr, badchars[10];
+	
+	assert( Name != NULL );
+
+	if(( Name[0] != '#' ) || ( strlen( Name ) >= CHANNEL_NAME_LEN )) return false;
+
+	ptr = Name;
+	strcpy( badchars, " ,:\007" );
+	while( *ptr )
+	{
+		if( strchr( badchars, *ptr )) return false;
+		ptr++;
+	}
+	
+	return true;
+} /* Channel_IsValidName */
+
+
+GLOBAL bool
+Channel_ModeAdd( CHANNEL *Chan, char Mode )
+{
+	/* set Mode.
+	 * If the channel already had this mode, return false.
+	 * If the channel mode was newly set return true.
+	 */
+
+	char x[2];
+
+	assert( Chan != NULL );
+
+	x[0] = Mode; x[1] = '\0';
+	if( ! strchr( Chan->modes, x[0] ))
+	{
+		/* Channel does not have this mode yet, set it */
+		strlcat( Chan->modes, x, sizeof( Chan->modes ));
+		return true;
+	}
+	else return false;
+} /* Channel_ModeAdd */
+
+
+GLOBAL bool
+Channel_ModeDel( CHANNEL *Chan, char Mode )
+{
+	/* Delete mode.
+	 * if the mode was removed return true.
+	 * if the channel did not have the mode, return false.
+	*/
+	char x[2], *p;
+
+	assert( Chan != NULL );
+
+	x[0] = Mode; x[1] = '\0';
+
+	p = strchr( Chan->modes, x[0] );
+	if( ! p ) return false;
+
+	/* Channel has mode -> delete */
+	while( *p )
+	{
+		*p = *(p + 1);
+		p++;
+	}
+	return true;
+} /* Channel_ModeDel */
+
+
+GLOBAL bool
+Channel_UserModeAdd( CHANNEL *Chan, CLIENT *Client, char Mode )
+{
+	/* Set Channel-User-Mode.
+	 * if mode was newly set, return true.
+	 * if the User already had this channel-mode, return false.
+	 */
+
+	CL2CHAN *cl2chan;
+	char x[2];
+
+	assert( Chan != NULL );
+	assert( Client != NULL );
+
+	cl2chan = Get_Cl2Chan( Chan, Client );
+	assert( cl2chan != NULL );
+	
+	x[0] = Mode; x[1] = '\0';
+	if( ! strchr( cl2chan->modes, x[0] ))
+	{
+		/* mode not set, -> set it */
+		strlcat( cl2chan->modes, x, sizeof( cl2chan->modes ));
+		return true;
+	}
+	else return false;
+} /* Channel_UserModeAdd */
+
+
+GLOBAL bool
+Channel_UserModeDel( CHANNEL *Chan, CLIENT *Client, char Mode )
+{
+	/* Delete Channel-User-Mode.
+	 * If Mode was removed, return true.
+	 * If User did not have the Channel-Mode, return false.
+	 */
+
+	CL2CHAN *cl2chan;
+	char x[2], *p;
+
+	assert( Chan != NULL );
+	assert( Client != NULL );
+
+	cl2chan = Get_Cl2Chan( Chan, Client );
+	assert( cl2chan != NULL );
+
+	x[0] = Mode; x[1] = '\0';
+
+	p = strchr( cl2chan->modes, x[0] );
+	if( ! p ) return false;
+
+	/* Client has Mode -> delete */
+	while( *p )
+	{
+		*p = *(p + 1);
+		p++;
+	}
+	return true;
+} /* Channel_UserModeDel */
+
+
+GLOBAL char *
+Channel_UserModes( CHANNEL *Chan, CLIENT *Client )
+{
+	/* return Users' Channel-Modes */
+	
+	CL2CHAN *cl2chan;
+
+	assert( Chan != NULL );
+	assert( Client != NULL );
+
+	cl2chan = Get_Cl2Chan( Chan, Client );
+	assert( cl2chan != NULL );
+
+	return cl2chan->modes;
+} /* Channel_UserModes */
+
+
+GLOBAL bool
+Channel_IsMemberOf( CHANNEL *Chan, CLIENT *Client )
+{
+	/* Test if Client is on Channel Chan */
+
+	assert( Chan != NULL );
+	assert( Client != NULL );
+
+	if( Get_Cl2Chan( Chan, Client )) return true;
+	else return false;
+} /* Channel_IsMemberOf */
+
+
+GLOBAL char *
+Channel_Topic( CHANNEL *Chan )
+{
+	assert( Chan != NULL );
+	return Chan->topic;
+} /* Channel_Topic */
+
+
+GLOBAL void
+Channel_SetTopic( CHANNEL *Chan, char *Topic )
+{
+	assert( Chan != NULL );
+	assert( Topic != NULL );
+	
+	strlcpy( Chan->topic, Topic, sizeof( Chan->topic ));
+} /* Channel_SetTopic */
+
+
+GLOBAL void
+Channel_SetModes( CHANNEL *Chan, char *Modes )
+{
+	assert( Chan != NULL );
+	assert( Modes != NULL );
+
+	strlcpy( Chan->modes, Modes, sizeof( Chan->modes ));
+} /* Channel_SetModes */
+
+
+GLOBAL void
+Channel_SetKey( CHANNEL *Chan, char *Key )
+{
+	assert( Chan != NULL );
+	assert( Key != NULL );
+
+	strlcpy( Chan->key, Key, sizeof( Chan->key ));
+	Log( LOG_DEBUG, "Channel %s: Key is now \"%s\".", Chan->name, Chan->key );
+} /* Channel_SetKey */
+
+
+GLOBAL void
+Channel_SetMaxUsers( CHANNEL *Chan, long Count )
+{
+	assert( Chan != NULL );
+
+	Chan->maxusers = Count;
+	Log( LOG_DEBUG, "Channel %s: Member limit is now %ld.", Chan->name, Chan->maxusers );
+} /* Channel_SetMaxUsers */
+
+
+GLOBAL bool
+Channel_Write( CHANNEL *Chan, CLIENT *From, CLIENT *Client, char *Text )
+{
+	bool is_member, has_voice, is_op, ok;
+
+	/* Okay, target is a channel */
+	is_member = has_voice = is_op = false;
+	if( Channel_IsMemberOf( Chan, From ))
+	{
+		is_member = true;
+		if( strchr( Channel_UserModes( Chan, From ), 'v' )) has_voice = true;
+		if( strchr( Channel_UserModes( Chan, From ), 'o' )) is_op = true;
+	}
+
+	/* Is the client allowed to write to channel? */
+	ok = true;
+	if( strchr( Channel_Modes( Chan ), 'n' ) && ( ! is_member )) ok = false;
+	if( strchr( Channel_Modes( Chan ), 'm' ) && ( ! is_op ) && ( ! has_voice )) ok = false;
+	
+	/* Is the client banned? */
+	if( Lists_CheckBanned( From, Chan ))
+	{
+		/* Client is banned, bus is he channel operator or has voice? */
+		if(( ! has_voice ) && ( ! is_op )) ok = false;
+	}
+
+	if( ! ok ) return IRC_WriteStrClient( From, ERR_CANNOTSENDTOCHAN_MSG, Client_ID( From ), Channel_Name( Chan ));
+
+	/* Send text */
+	if( Client_Conn( From ) > NONE ) Conn_UpdateIdle( Client_Conn( From ));
+	return IRC_WriteStrChannelPrefix( Client, Chan, From, true, "PRIVMSG %s :%s", Channel_Name( Chan ), Text );
+} /* Channel_Write */
+
+
+GLOBAL CHANNEL *
+Channel_Create( char *Name )
+{
+	/* Create new CHANNEL structure and add it to linked list */
+	CHANNEL *c;
+
+	assert( Name != NULL );
+	
+	c = (CHANNEL *)malloc( sizeof( CHANNEL ));
+	if( ! c )
+	{
+		Log( LOG_EMERG, "Can't allocate memory! [New_Chan]" );
+		return NULL;
+	}
+	memset( c, 0, sizeof( CHANNEL ));
+	strlcpy( c->name, Name, sizeof( c->name ));
+	c->hash = Hash( c->name );
+	c->next = My_Channels;
+	My_Channels = c;
+	
+	Log( LOG_DEBUG, "Created new channel structure for \"%s\".", Name );
+	
+	return c;
+} /* Channel_Create */
+
+
+LOCAL CL2CHAN *
+Get_Cl2Chan( CHANNEL *Chan, CLIENT *Client )
+{
+	CL2CHAN *cl2chan;
+
+	assert( Chan != NULL );
+	assert( Client != NULL );
+
+	cl2chan = My_Cl2Chan;
+	while( cl2chan )
+	{
+		if(( cl2chan->channel == Chan ) && ( cl2chan->client == Client )) return cl2chan;
+		cl2chan = cl2chan->next;
+	}
+	return NULL;
+} /* Get_Cl2Chan */
+
+
+LOCAL CL2CHAN *
+Add_Client( CHANNEL *Chan, CLIENT *Client )
+{
+	CL2CHAN *cl2chan;
+
+	assert( Chan != NULL );
+	assert( Client != NULL );
+
+	/* neue CL2CHAN-Struktur anlegen */
+	cl2chan = (CL2CHAN *)malloc( sizeof( CL2CHAN ));
+	if( ! cl2chan )
+	{
+		Log( LOG_EMERG, "Can't allocate memory! [Add_Client]" );
+		return NULL;
+	}
+	cl2chan->channel = Chan;
+	cl2chan->client = Client;
+	strcpy( cl2chan->modes, "" );
+
+	/* Verketten */
+	cl2chan->next = My_Cl2Chan;
+	My_Cl2Chan = cl2chan;
+
+	Log( LOG_DEBUG, "User \"%s\" joined channel \"%s\".", Client_Mask( Client ), Chan->name );
+
+	return cl2chan;
+} /* Add_Client */
+
+
+LOCAL bool
+Remove_Client( int Type, CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, char *Reason, bool InformServer )
+{
+	CL2CHAN *cl2chan, *last_cl2chan;
+	CHANNEL *c;
+	
+	assert( Chan != NULL );
+	assert( Client != NULL );
+	assert( Origin != NULL );
+	assert( Reason != NULL );
+
+	last_cl2chan = NULL;
+	cl2chan = My_Cl2Chan;
+	while( cl2chan )
+	{
+		if(( cl2chan->channel == Chan ) && ( cl2chan->client == Client )) break;
+		last_cl2chan = cl2chan;
+		cl2chan = cl2chan->next;
+	}
+	if( ! cl2chan ) return false;
+
+	c = cl2chan->channel;
+	assert( c != NULL );
+
+	/* Aus Verkettung loesen und freigeben */
+	if( last_cl2chan ) last_cl2chan->next = cl2chan->next;
+	else My_Cl2Chan = cl2chan->next;
+	free( cl2chan );
+
+	switch( Type )
+	{
+		case REMOVE_QUIT:
+			/* QUIT: andere Server wurden bereits informiert, vgl. Client_Destroy();
+			 * hier also "nur" noch alle User in betroffenen Channeln infomieren */
+			assert( InformServer == false );
+			Log( LOG_DEBUG, "User \"%s\" left channel \"%s\" (%s).", Client_Mask( Client ), c->name, Reason );
+			break;
+		case REMOVE_KICK:
+			/* User wurde geKICKed: ggf. andere Server sowie alle betroffenen User
+			 * im entsprechenden Channel informieren */
+			if( InformServer ) IRC_WriteStrServersPrefix( Client_NextHop( Origin ), Origin, "KICK %s %s :%s", c->name, Client_ID( Client ), Reason );
+			IRC_WriteStrChannelPrefix( Client, c, Origin, false, "KICK %s %s :%s", c->name, Client_ID( Client ), Reason );
+			if(( Client_Conn( Client ) > NONE ) && ( Client_Type( Client ) == CLIENT_USER )) IRC_WriteStrClientPrefix( Client, Origin, "KICK %s %s :%s", c->name, Client_ID( Client ), Reason );
+			Log( LOG_DEBUG, "User \"%s\" has been kicked of \"%s\" by \"%s\": %s.", Client_Mask( Client ), c->name, Client_ID( Origin ), Reason );
+			break;
+		default:
+			/* PART */
+			if( InformServer ) IRC_WriteStrServersPrefix( Origin, Client, "PART %s :%s", c->name, Reason );
+			IRC_WriteStrChannelPrefix( Origin, c, Client, false, "PART %s :%s", c->name, Reason );
+			if(( Client_Conn( Origin ) > NONE ) && ( Client_Type( Origin ) == CLIENT_USER )) IRC_WriteStrClientPrefix( Origin, Client, "PART %s :%s", c->name, Reason );
+			Log( LOG_DEBUG, "User \"%s\" left channel \"%s\" (%s).", Client_Mask( Client ), c->name, Reason );
+	}
+
+	/* Wenn Channel nun leer und nicht pre-defined: loeschen */
+	if( ! strchr( Channel_Modes( Chan ), 'P' ))
+	{
+		if( ! Get_First_Cl2Chan( NULL, Chan )) Delete_Channel( Chan );
+	}
+		
+	return true;
+} /* Remove_Client */
+
+
+LOCAL CL2CHAN *
+Get_First_Cl2Chan( CLIENT *Client, CHANNEL *Chan )
+{
+	return Get_Next_Cl2Chan( My_Cl2Chan, Client, Chan );
+} /* Get_First_Cl2Chan */
+
+
+LOCAL CL2CHAN *
+Get_Next_Cl2Chan( CL2CHAN *Start, CLIENT *Client, CHANNEL *Channel )
+{
+	CL2CHAN *cl2chan;
+
+	assert( Client != NULL || Channel != NULL );
+	
+	cl2chan = Start;
+	while( cl2chan )
+	{
+		if(( Client ) && ( cl2chan->client == Client )) return cl2chan;
+		if(( Channel ) && ( cl2chan->channel == Channel )) return cl2chan;
+		cl2chan = cl2chan->next;
+	}
+	return NULL;
+} /* Get_Next_Cl2Chan */
+
+
+LOCAL bool
+Delete_Channel( CHANNEL *Chan )
+{
+	/* Channel-Struktur loeschen */
+	
+	CHANNEL *chan, *last_chan;
+
+	last_chan = NULL;
+	chan = My_Channels;
+	while( chan )
+	{
+		if( chan == Chan ) break;
+		last_chan = chan;
+		chan = chan->next;
+	}
+	if( ! chan ) return false;
+
+	Log( LOG_DEBUG, "Freed channel structure for \"%s\".", Chan->name );
+
+	/* Invite- und Ban-Lists aufraeumen */
+	Lists_DeleteChannel( chan );
+
+	/* Neu verketten und freigeben */
+	if( last_chan ) last_chan->next = chan->next;
+	else My_Channels = chan->next;
+	free( chan );
+		
+	return true;
+} /* Delete_Channel */
+
+
+/* -eof- */

+ 111 - 0
src/ngircd/channel.h

@@ -0,0 +1,111 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * $Id: channel.h,v 1.27 2005/03/19 18:43:48 fw Exp $
+ *
+ * Channel management (header)
+ */
+
+
+#ifndef __channel_h__
+#define __channel_h__
+
+
+#if defined(__channel_c__) | defined(S_SPLINT_S)
+
+#include "defines.h"
+
+typedef struct _CHANNEL
+{
+	struct _CHANNEL *next;
+	char name[CHANNEL_NAME_LEN];	/* Name of the channel */
+	UINT32 hash;			/* Hash of the (lowecase!) name */
+	char modes[CHANNEL_MODE_LEN];	/* Channel modes */
+	char topic[CHANNEL_TOPIC_LEN];	/* Topic of the channel */
+	char key[CLIENT_PASS_LEN];	/* Channel key ("password", mode "k" ) */
+	long maxusers;			/* Maximum number of members (mode "l") */
+} CHANNEL;
+
+typedef struct _CLIENT2CHAN
+{
+	struct _CLIENT2CHAN *next;
+	CLIENT *client;
+	CHANNEL *channel;
+	char modes[CHANNEL_MODE_LEN];	/* User-Modes in dem Channel */
+} CL2CHAN;
+
+#else
+
+typedef POINTER CHANNEL;
+typedef POINTER CL2CHAN;
+
+#endif
+
+
+GLOBAL void Channel_Init PARAMS(( void ));
+GLOBAL void Channel_InitPredefined PARAMS((  void ));
+GLOBAL void Channel_Exit PARAMS(( void ));
+
+GLOBAL bool Channel_Join PARAMS(( CLIENT *Client, char *Name ));
+GLOBAL bool Channel_Part PARAMS(( CLIENT *Client, CLIENT *Origin, char *Name, char *Reason ));
+
+GLOBAL void Channel_Quit PARAMS(( CLIENT *Client, char *Reason ));
+
+GLOBAL void Channel_Kick PARAMS((  CLIENT *Client, CLIENT *Origin, char *Name, char *Reason ));
+
+GLOBAL long Channel_Count PARAMS(( void ));
+GLOBAL long Channel_MemberCount PARAMS(( CHANNEL *Chan ));
+GLOBAL int Channel_CountForUser PARAMS(( CLIENT *Client ));
+GLOBAL int Channel_PCount PARAMS(( void ));
+
+GLOBAL char *Channel_Name PARAMS(( CHANNEL *Chan ));
+GLOBAL char *Channel_Modes PARAMS(( CHANNEL *Chan ));
+GLOBAL char *Channel_Topic PARAMS(( CHANNEL *Chan ));
+GLOBAL char *Channel_Key PARAMS(( CHANNEL *Chan ));
+GLOBAL long Channel_MaxUsers PARAMS(( CHANNEL *Chan ));
+
+GLOBAL void Channel_SetTopic PARAMS(( CHANNEL *Chan, char *Topic ));
+GLOBAL void Channel_SetModes PARAMS(( CHANNEL *Chan, char *Modes ));
+GLOBAL void Channel_SetKey PARAMS(( CHANNEL *Chan, char *Key ));
+GLOBAL void Channel_SetMaxUsers PARAMS(( CHANNEL *Chan, long Count ));
+
+GLOBAL CHANNEL *Channel_Search PARAMS(( char *Name ));
+
+GLOBAL CHANNEL *Channel_First PARAMS(( void ));
+GLOBAL CHANNEL *Channel_Next PARAMS(( CHANNEL *Chan ));
+
+GLOBAL CL2CHAN *Channel_FirstMember PARAMS(( CHANNEL *Chan ));
+GLOBAL CL2CHAN *Channel_NextMember PARAMS(( CHANNEL *Chan, CL2CHAN *Cl2Chan ));
+GLOBAL CL2CHAN *Channel_FirstChannelOf PARAMS(( CLIENT *Client ));
+GLOBAL CL2CHAN *Channel_NextChannelOf PARAMS(( CLIENT *Client, CL2CHAN *Cl2Chan ));
+
+GLOBAL CLIENT *Channel_GetClient PARAMS(( CL2CHAN *Cl2Chan ));
+GLOBAL CHANNEL *Channel_GetChannel PARAMS(( CL2CHAN *Cl2Chan ));
+
+GLOBAL bool Channel_IsValidName PARAMS(( char *Name ));
+
+GLOBAL bool Channel_ModeAdd PARAMS(( CHANNEL *Chan, char Mode ));
+GLOBAL bool Channel_ModeDel PARAMS(( CHANNEL *Chan, char Mode ));
+
+GLOBAL bool Channel_UserModeAdd PARAMS(( CHANNEL *Chan, CLIENT *Client, char Mode ));
+GLOBAL bool Channel_UserModeDel PARAMS(( CHANNEL *Chan, CLIENT *Client, char Mode ));
+GLOBAL char *Channel_UserModes PARAMS(( CHANNEL *Chan, CLIENT *Client ));
+
+GLOBAL bool Channel_IsMemberOf PARAMS(( CHANNEL *Chan, CLIENT *Client ));
+
+GLOBAL bool Channel_Write PARAMS(( CHANNEL *Chan, CLIENT *From, CLIENT *Client, char *Text ));
+
+GLOBAL CHANNEL *Channel_Create PARAMS(( char *Name ));
+
+
+#endif
+
+
+/* -eof- */

File diff suppressed because it is too large
+ 1183 - 0
src/ngircd/client.c


+ 161 - 0
src/ngircd/client.h

@@ -0,0 +1,161 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * $Id: client.h,v 1.39 2005/06/12 16:18:49 alex Exp $
+ *
+ * Client management (header)
+ */
+
+
+#ifndef __client_h__
+#define __client_h__
+
+
+#define CLIENT_UNKNOWN 1		/* connection of unknown type */
+#define CLIENT_GOTPASS 2		/* client did send PASS */
+#define CLIENT_GOTNICK 4		/* client did send NICK */
+#define CLIENT_GOTUSER 8		/* client did send USER */
+#define CLIENT_USER 16			/* client is an IRC user */
+#define CLIENT_UNKNOWNSERVER 32		/* unregistered server connection */
+#define CLIENT_GOTPASSSERVER 64		/* client did send PASS in "server style" */
+#define CLIENT_SERVER 128		/* client is a server */
+#define CLIENT_SERVICE 256		/* client is a service */
+
+#define CLIENT_TYPE int
+
+
+#if defined(__client_c__) | defined(S_SPLINT_S)
+
+typedef struct _CLIENT
+{
+	time_t starttime;		/* Start time of link */
+	char id[CLIENT_ID_LEN];		/* nick (user) / ID (server) */
+	UINT32 hash;			/* hash of lower-case ID */
+	POINTER *next;			/* pointer to next client structure */
+	CLIENT_TYPE type;		/* type of client, see CLIENT_xxx */
+	CONN_ID conn_id;		/* ID of the connection (if local) or NONE (remote) */
+	struct _CLIENT *introducer;	/* ID of the servers which the client is connected to */
+	struct _CLIENT *topserver;	/* toplevel servers (only valid if client is a server) */
+	char pwd[CLIENT_PASS_LEN];	/* password received of the client */
+	char host[CLIENT_HOST_LEN];	/* hostname of the client */
+	char user[CLIENT_USER_LEN];	/* user name ("login") */
+	char info[CLIENT_INFO_LEN];	/* long user name (user) / info text (server) */
+	char modes[CLIENT_MODE_LEN];	/* client modes */
+	int hops, token, mytoken;	/* "hops" and "Token" (see SERVER command) */
+	bool oper_by_me;		/* client is local IRC operator on this server? */
+	char away[CLIENT_AWAY_LEN];	/* AWAY text (valid if mode 'a' is set) */
+	char flags[CLIENT_FLAGS_LEN];	/* flags of the client */
+} CLIENT;
+
+#else
+
+typedef POINTER CLIENT;
+
+#endif
+
+
+typedef struct _WHOWAS
+{
+	time_t time;			/* time stamp of entry or 0 if unused */
+	char id[CLIENT_NICK_LEN];	/* client nick name */
+	char host[CLIENT_HOST_LEN];	/* hostname of the client */
+	char user[CLIENT_USER_LEN];	/* user name ("login") */
+	char info[CLIENT_INFO_LEN];	/* long user name */
+	char server[CLIENT_HOST_LEN];	/* server name */
+} WHOWAS;
+
+
+GLOBAL void Client_Init PARAMS(( void ));
+GLOBAL void Client_Exit PARAMS(( void ));
+
+GLOBAL CLIENT *Client_NewLocal PARAMS(( CONN_ID Idx, char *Hostname, int Type, bool Idented ));
+GLOBAL CLIENT *Client_NewRemoteServer PARAMS(( CLIENT *Introducer, char *Hostname, CLIENT *TopServer, int Hops, int Token, char *Info, bool Idented ));
+GLOBAL CLIENT *Client_NewRemoteUser PARAMS(( CLIENT *Introducer, char *Nick, int Hops, char *User, char *Hostname, int Token, char *Modes, char *Info, bool Idented ));
+GLOBAL CLIENT *Client_New PARAMS(( CONN_ID Idx, CLIENT *Introducer, CLIENT *TopServer, int Type, char *ID, char *User, char *Hostname, char *Info, int Hops, int Token, char *Modes, bool Idented ));
+
+GLOBAL void Client_Destroy PARAMS(( CLIENT *Client, char *LogMsg, char *FwdMsg, bool SendQuit ));
+#ifdef CONN_MODULE
+GLOBAL void Client_DestroyNow PARAMS(( CLIENT *Client ));
+#endif
+
+GLOBAL CLIENT *Client_ThisServer PARAMS(( void ));
+
+GLOBAL CLIENT *Client_GetFromConn PARAMS(( CONN_ID Idx ));
+GLOBAL CLIENT *Client_GetFromToken PARAMS(( CLIENT *Client, int Token ));
+
+GLOBAL CLIENT *Client_Search PARAMS(( char *ID ));
+GLOBAL CLIENT *Client_First PARAMS(( void ));
+GLOBAL CLIENT *Client_Next PARAMS(( CLIENT *c ));
+
+GLOBAL int Client_Type PARAMS(( CLIENT *Client ));
+GLOBAL CONN_ID Client_Conn PARAMS(( CLIENT *Client ));
+GLOBAL char *Client_ID PARAMS(( CLIENT *Client ));
+GLOBAL char *Client_Mask PARAMS(( CLIENT *Client ));
+GLOBAL char *Client_Info PARAMS(( CLIENT *Client ));
+GLOBAL char *Client_User PARAMS(( CLIENT *Client ));
+GLOBAL char *Client_Hostname PARAMS(( CLIENT *Client ));
+GLOBAL char *Client_Password PARAMS(( CLIENT *Client ));
+GLOBAL char *Client_Modes PARAMS(( CLIENT *Client ));
+GLOBAL char *Client_Flags PARAMS(( CLIENT *Client ));
+GLOBAL CLIENT *Client_Introducer PARAMS(( CLIENT *Client ));
+GLOBAL bool Client_OperByMe PARAMS(( CLIENT *Client ));
+GLOBAL int Client_Hops PARAMS(( CLIENT *Client ));
+GLOBAL int Client_Token PARAMS(( CLIENT *Client ));
+GLOBAL int Client_MyToken PARAMS(( CLIENT *Client ));
+GLOBAL CLIENT *Client_TopServer PARAMS(( CLIENT *Client ));
+GLOBAL CLIENT *Client_NextHop PARAMS(( CLIENT *Client ));
+GLOBAL char *Client_Away PARAMS(( CLIENT *Client ));
+GLOBAL time_t Client_StartTime PARAMS(( CLIENT *Client ));
+
+GLOBAL bool Client_HasMode PARAMS(( CLIENT *Client, char Mode ));
+
+GLOBAL void Client_SetHostname PARAMS(( CLIENT *Client, char *Hostname ));
+GLOBAL void Client_SetID PARAMS(( CLIENT *Client, char *Nick ));
+GLOBAL void Client_SetUser PARAMS(( CLIENT *Client, char *User, bool Idented ));
+GLOBAL void Client_SetInfo PARAMS(( CLIENT *Client, char *Info ));
+GLOBAL void Client_SetPassword PARAMS(( CLIENT *Client, char *Pwd ));
+GLOBAL void Client_SetType PARAMS(( CLIENT *Client, int Type ));
+GLOBAL void Client_SetHops PARAMS(( CLIENT *Client, int Hops ));
+GLOBAL void Client_SetToken PARAMS(( CLIENT *Client, int Token ));
+GLOBAL void Client_SetOperByMe PARAMS(( CLIENT *Client, bool OperByMe ));
+GLOBAL void Client_SetModes PARAMS(( CLIENT *Client, char *Modes ));
+GLOBAL void Client_SetFlags PARAMS(( CLIENT *Client, char *Flags ));
+GLOBAL void Client_SetIntroducer PARAMS(( CLIENT *Client, CLIENT *Introducer ));
+GLOBAL void Client_SetAway PARAMS(( CLIENT *Client, char *Txt ));
+
+GLOBAL bool Client_ModeAdd PARAMS(( CLIENT *Client, char Mode ));
+GLOBAL bool Client_ModeDel PARAMS(( CLIENT *Client, char Mode ));
+
+GLOBAL bool Client_CheckNick PARAMS(( CLIENT *Client, char *Nick ));
+GLOBAL bool Client_CheckID PARAMS(( CLIENT *Client, char *ID ));
+
+GLOBAL long Client_UserCount PARAMS(( void ));
+GLOBAL long Client_ServiceCount PARAMS(( void ));
+GLOBAL long Client_ServerCount PARAMS(( void ));
+GLOBAL long Client_OperCount PARAMS(( void ));
+GLOBAL long Client_UnknownCount PARAMS(( void ));
+GLOBAL long Client_MyUserCount PARAMS(( void ));
+GLOBAL long Client_MyServiceCount PARAMS(( void ));
+GLOBAL long Client_MyServerCount PARAMS(( void ));
+GLOBAL long Client_MaxUserCount PARAMS((  void ));
+GLOBAL long Client_MyMaxUserCount PARAMS((  void ));
+
+GLOBAL bool Client_IsValidNick PARAMS(( char *Nick ));
+
+GLOBAL WHOWAS *Client_GetWhowas PARAMS(( void ));
+GLOBAL int Client_GetLastWhowasIndex PARAMS(( void ));
+
+GLOBAL void Client_RegisterWhowas PARAMS(( CLIENT *Client ));
+
+
+#endif
+
+
+/* -eof- */

File diff suppressed because it is too large
+ 1075 - 0
src/ngircd/conf.c


+ 148 - 0
src/ngircd/conf.h

@@ -0,0 +1,148 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * $Id: conf.h,v 1.34 2005/03/20 13:54:06 fw Exp $
+ *
+ * Configuration management (header)
+ */
+
+
+#ifndef __conf_h__
+#define __conf_h__
+
+#include <time.h>
+
+#include "defines.h"
+#include "portab.h"
+
+typedef struct _Conf_Oper
+{
+	char name[CLIENT_PASS_LEN];	/* Name (ID) of IRC operator */
+	char pwd[CLIENT_PASS_LEN];	/* Password */
+	char *mask;
+} CONF_OPER;
+
+typedef struct _Conf_Server
+{
+	char host[HOST_LEN];		/* Hostname */
+	char ip[16];			/* IP address (Resolver) */
+	char name[CLIENT_ID_LEN];	/* IRC-Client-ID */
+	char pwd_in[CLIENT_PASS_LEN];	/* Password which must be received */
+	char pwd_out[CLIENT_PASS_LEN];	/* Password to send to peer */
+	UINT16 port;			/* Server port */
+	int group;			/* Group of server */
+	time_t lasttry;			/* Last connect attempt */
+	RES_STAT *res_stat;		/* Status of the resolver */
+	int flags;			/* Flags */
+	CONN_ID conn_id;		/* ID of server connection or NONE */
+} CONF_SERVER;
+
+typedef struct _Conf_Channel
+{
+	char name[CHANNEL_NAME_LEN];	/* Name of the channel */
+	char modes[CHANNEL_MODE_LEN];	/* Initial channel modes */
+	char topic[CHANNEL_TOPIC_LEN];	/* Initial topic */
+} CONF_CHANNEL;
+
+
+#define CONF_SFLAG_ONCE	1		/* Delete this entry after next disconnect */
+#define CONF_SFLAG_DISABLED 2		/* This server configuration entry is disabled */
+
+
+/* Name ("Nick") of the servers */
+GLOBAL char Conf_ServerName[CLIENT_ID_LEN];
+
+/* Server info text */
+GLOBAL char Conf_ServerInfo[CLIENT_INFO_LEN];
+
+/* Global server passwort */
+GLOBAL char Conf_ServerPwd[CLIENT_PASS_LEN];
+
+/* Administrative information */
+GLOBAL char Conf_ServerAdmin1[CLIENT_INFO_LEN];
+GLOBAL char Conf_ServerAdmin2[CLIENT_INFO_LEN];
+GLOBAL char Conf_ServerAdminMail[CLIENT_INFO_LEN];
+
+/* File with MOTD text */
+GLOBAL char Conf_MotdFile[FNAME_LEN];
+
+/* Phrase with MOTD text */
+GLOBAL char Conf_MotdPhrase[LINE_LEN];
+
+/* Ports the server should listen on */
+GLOBAL UINT16 Conf_ListenPorts[MAX_LISTEN_PORTS];
+GLOBAL int Conf_ListenPorts_Count;
+
+/* Address to which the socket should be bound or empty (=all) */
+GLOBAL char Conf_ListenAddress[16];
+
+/* User and group ID the server should run with */
+GLOBAL unsigned int Conf_UID;
+GLOBAL unsigned int Conf_GID;
+
+/* A directory to chroot() in */
+GLOBAL char Conf_Chroot[FNAME_LEN];
+
+/* File with PID of daemon */
+GLOBAL char Conf_PidFile[FNAME_LEN];
+
+/* Timeouts for PING and PONG */
+GLOBAL int Conf_PingTimeout;
+GLOBAL int Conf_PongTimeout;
+
+/* Seconds between connect attempts to other servers */
+GLOBAL int Conf_ConnectRetry;
+
+/* Operators */
+GLOBAL CONF_OPER Conf_Oper[MAX_OPERATORS];
+GLOBAL int Conf_Oper_Count;
+
+/* Servers */
+GLOBAL CONF_SERVER Conf_Server[MAX_SERVERS];
+
+/* Pre-defined channels */
+GLOBAL CONF_CHANNEL Conf_Channel[MAX_DEFCHANNELS];
+GLOBAL int Conf_Channel_Count;
+
+/* Are IRC operators allowed to always use MODE? */
+GLOBAL bool Conf_OperCanMode;
+
+/* If an IRC op gives chanop privileges without being a chanop,
+ * ircd2 will ignore the command. This enables a workaround:
+ * It masks the command as coming from the server */
+GLOBAL bool Conf_OperServerMode;
+
+/* Maximum number of connections to this server */
+GLOBAL long Conf_MaxConnections;
+
+/* Maximum number of channels a user can join */
+GLOBAL int Conf_MaxJoins;
+
+/* Maximum number of connections per IP address */
+GLOBAL int Conf_MaxConnectionsIP;
+
+
+GLOBAL void Conf_Init PARAMS((void ));
+GLOBAL void Conf_Rehash PARAMS((void ));
+GLOBAL int Conf_Test PARAMS((void ));
+
+GLOBAL void Conf_UnsetServer PARAMS(( CONN_ID Idx ));
+GLOBAL void Conf_SetServer PARAMS(( int ConfServer, CONN_ID Idx ));
+GLOBAL int Conf_GetServer PARAMS(( CONN_ID Idx ));
+
+GLOBAL bool Conf_EnableServer PARAMS(( char *Name, UINT16 Port ));
+GLOBAL bool Conf_DisableServer PARAMS(( char *Name ));
+GLOBAL bool Conf_AddServer PARAMS(( char *Name, UINT16 Port, char *Host, char *MyPwd, char *PeerPwd ));
+
+
+#endif
+
+
+/* -eof- */

+ 264 - 0
src/ngircd/conn-func.c

@@ -0,0 +1,264 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * Connection management: Global functions
+ */
+
+
+#define CONN_MODULE
+
+#include "portab.h"
+
+static char UNUSED id[] = "$Id: conn-func.c,v 1.6 2005/06/12 16:32:17 alex Exp $";
+
+#include "imp.h"
+#include <assert.h>
+#include <log.h>
+
+#include "conn.h"
+#include "client.h"
+
+#include "exp.h"
+#include "conn-func.h"
+
+
+GLOBAL void
+Conn_UpdateIdle( CONN_ID Idx )
+{
+	/* Idle-Timer zuruecksetzen */
+
+	assert( Idx > NONE );
+	My_Connections[Idx].lastprivmsg = time( NULL );
+}
+
+
+GLOBAL time_t
+Conn_GetIdle( CONN_ID Idx )
+{
+	/* Idle-Time einer Verbindung liefern (in Sekunden) */
+
+	assert( Idx > NONE );
+	return time( NULL ) - My_Connections[Idx].lastprivmsg;
+} /* Conn_GetIdle */
+
+
+GLOBAL time_t
+Conn_LastPing( CONN_ID Idx )
+{
+	/* Zeitpunkt des letzten PING liefern */
+
+	assert( Idx > NONE );
+	return My_Connections[Idx].lastping;
+} /* Conn_LastPing */
+
+
+GLOBAL void
+Conn_SetPenalty( CONN_ID Idx, time_t Seconds )
+{
+	/* Penalty-Delay fuer eine Verbindung (in Sekunden) setzen;
+	 * waehrend dieser Zeit wird der entsprechende Socket vom Server
+	 * bei Lese-Operationen komplett ignoriert. Der Delay kann mit
+	 * dieser Funktion nur erhoeht, nicht aber verringert werden. */
+	
+	time_t t;
+	
+	assert( Idx > NONE );
+	assert( Seconds >= 0 );
+
+	t = time( NULL ) + Seconds;
+	if( t > My_Connections[Idx].delaytime ) My_Connections[Idx].delaytime = t;
+} /* Conn_SetPenalty */
+
+
+GLOBAL void
+Conn_ResetPenalty( CONN_ID Idx )
+{
+	assert( Idx > NONE );
+	My_Connections[Idx].delaytime = 0;
+} /* Conn_ResetPenalty */
+
+
+GLOBAL void
+Conn_ClearFlags( void )
+{
+	/* Alle Connection auf "nicht-markiert" setzen */
+
+	CONN_ID i;
+
+	for( i = 0; i < Pool_Size; i++ ) My_Connections[i].flag = 0;
+} /* Conn_ClearFlags */
+
+
+GLOBAL int
+Conn_Flag( CONN_ID Idx )
+{
+	/* Ist eine Connection markiert (true) oder nicht? */
+
+	assert( Idx > NONE );
+	return My_Connections[Idx].flag;
+} /* Conn_Flag */
+
+
+GLOBAL void
+Conn_SetFlag( CONN_ID Idx, int Flag )
+{
+	/* Connection markieren */
+
+	assert( Idx > NONE );
+	My_Connections[Idx].flag = Flag;
+} /* Conn_SetFlag */
+
+
+GLOBAL CONN_ID
+Conn_First( void )
+{
+	/* Connection-Struktur der ersten Verbindung liefern;
+	 * Ist keine Verbindung vorhanden, wird NONE geliefert. */
+
+	CONN_ID i;
+	
+	for( i = 0; i < Pool_Size; i++ )
+	{
+		if( My_Connections[i].sock != NONE ) return i;
+	}
+	return NONE;
+} /* Conn_First */
+
+
+GLOBAL CONN_ID
+Conn_Next( CONN_ID Idx )
+{
+	/* Naechste Verbindungs-Struktur liefern; existiert keine
+	 * weitere, so wird NONE geliefert. */
+
+	CONN_ID i = NONE;
+
+	assert( Idx > NONE );
+	
+	for( i = Idx + 1; i < Pool_Size; i++ )
+	{
+		if( My_Connections[i].sock != NONE ) return i;
+	}
+	return NONE;
+} /* Conn_Next */
+
+
+GLOBAL int
+Conn_Options( CONN_ID Idx )
+{
+	assert( Idx > NONE );
+	return My_Connections[Idx].options;
+} /* Conn_Options */
+
+
+/**
+ * Get the start time of the connection.
+ * The result is the start time in seconds since 1970-01-01, as reported
+ * by the C function time(NULL).
+ */
+GLOBAL time_t
+Conn_StartTime( CONN_ID Idx )
+{
+	CLIENT *c;
+
+	assert(Idx > NONE);
+
+	/* Search client structure for this link ... */
+	c = Client_GetFromConn(Idx);
+	if(c != NULL)
+		return Client_StartTime(c);
+
+	return 0;
+} /* Conn_StartTime */
+
+
+GLOBAL int
+Conn_SendQ( CONN_ID Idx )
+{
+	/* Laenge der Daten im Schreibbuffer liefern */
+
+	assert( Idx > NONE );
+#ifdef ZLIB
+	if( My_Connections[Idx].options & CONN_ZIP ) return My_Connections[Idx].zip.wdatalen;
+	else
+#endif
+	return My_Connections[Idx].wdatalen;
+} /* Conn_SendQ */
+
+
+GLOBAL long
+Conn_SendMsg( CONN_ID Idx )
+{
+	/* Anzahl gesendeter Nachrichten liefern */
+
+	assert( Idx > NONE );
+	return My_Connections[Idx].msg_out;
+} /* Conn_SendMsg */
+
+
+GLOBAL long
+Conn_SendBytes( CONN_ID Idx )
+{
+	/* Anzahl gesendeter Bytes (unkomprimiert) liefern */
+
+	assert( Idx > NONE );
+	return My_Connections[Idx].bytes_out;
+} /* Conn_SendBytes */
+
+
+GLOBAL int
+Conn_RecvQ( CONN_ID Idx )
+{
+	/* Laenge der Daten im Lesebuffer liefern */
+
+	assert( Idx > NONE );
+#ifdef ZLIB
+	if( My_Connections[Idx].options & CONN_ZIP ) return My_Connections[Idx].zip.rdatalen;
+	else
+#endif
+	return My_Connections[Idx].rdatalen;
+} /* Conn_RecvQ */
+
+
+GLOBAL long
+Conn_RecvMsg( CONN_ID Idx )
+{
+	/* Anzahl empfangener Nachrichten liefern */
+
+	assert( Idx > NONE );
+	return My_Connections[Idx].msg_in;
+} /* Conn_RecvMsg */
+
+
+GLOBAL long
+Conn_RecvBytes( CONN_ID Idx )
+{
+	/* Anzahl empfangener Bytes (unkomprimiert) liefern */
+
+	assert( Idx > NONE );
+	return My_Connections[Idx].bytes_in;
+} /* Conn_RecvBytes */
+
+
+GLOBAL void
+Conn_ResetWCounter( void )
+{
+	WCounter = 0;
+} /* Conn_ResetWCounter */
+
+
+GLOBAL long
+Conn_WCounter( void )
+{
+	return WCounter;
+} /* Conn_WCounter */
+
+
+/* -eof- */

+ 62 - 0
src/ngircd/conn-func.h

@@ -0,0 +1,62 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * $Id: conn-func.h,v 1.4 2005/04/25 18:37:16 fw Exp $
+ *
+ * Connection management: Global functions (header)
+ */
+
+
+#ifndef __conn_func_h__
+#define __conn_func_h__
+
+
+/* Include the header conn.h if this header is _not_ included by any module
+ * containing connection handling functions. So other modules must only
+ * include this conn-func.h header. */
+#ifndef CONN_MODULE
+#	include "conn.h"
+#endif
+
+
+GLOBAL void Conn_UpdateIdle PARAMS(( CONN_ID Idx ));
+GLOBAL time_t Conn_GetIdle PARAMS(( CONN_ID Idx ));
+GLOBAL time_t Conn_LastPing PARAMS(( CONN_ID Idx ));
+GLOBAL time_t Conn_StartTime PARAMS(( CONN_ID Idx ));
+GLOBAL int Conn_SendQ PARAMS(( CONN_ID Idx ));
+GLOBAL int Conn_RecvQ PARAMS(( CONN_ID Idx ));
+GLOBAL long Conn_SendMsg PARAMS(( CONN_ID Idx ));
+GLOBAL long Conn_RecvMsg PARAMS(( CONN_ID Idx ));
+GLOBAL long Conn_SendBytes PARAMS(( CONN_ID Idx ));
+GLOBAL long Conn_RecvBytes PARAMS(( CONN_ID Idx ));
+
+GLOBAL void Conn_SetPenalty PARAMS(( CONN_ID Idx, time_t Seconds ));
+GLOBAL void Conn_ResetPenalty PARAMS(( CONN_ID Idx ));
+
+GLOBAL void Conn_ClearFlags PARAMS(( void ));
+GLOBAL int Conn_Flag PARAMS(( CONN_ID Idx ));
+GLOBAL void Conn_SetFlag PARAMS(( CONN_ID Idx, int Flag ));
+
+GLOBAL CONN_ID Conn_First PARAMS(( void ));
+GLOBAL CONN_ID Conn_Next PARAMS(( CONN_ID Idx ));
+
+GLOBAL int Conn_Options PARAMS(( CONN_ID Idx ));
+
+GLOBAL void Conn_ResetWCounter PARAMS(( void ));
+GLOBAL long Conn_WCounter PARAMS(( void ));
+
+#define Conn_OPTION_ADD( x, opt )   ( (x)->options |= opt ) 
+#define Conn_OPTION_DEL( x, opt )   ( (x)->options &= ~opt )
+#define Conn_OPTION_ISSET( x, opt ) ( (x)->options & opt )
+
+#endif
+
+
+/* -eof- */

+ 210 - 0
src/ngircd/conn-zip.c

@@ -0,0 +1,210 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * Connection compression using ZLIB
+ */
+
+
+#include "portab.h"
+
+#define CONN_MODULE
+
+
+#ifdef ZLIB
+
+static char UNUSED id[] = "$Id: conn-zip.c,v 1.7 2005/04/25 18:37:16 fw Exp $";
+
+#include "imp.h"
+#include <assert.h>
+#include <string.h>
+#include <zlib.h>
+
+#include "conn.h"
+#include "conn-func.h"
+#include "log.h"
+
+#include "exp.h"
+#include "conn-zip.h"
+
+
+GLOBAL bool
+Zip_InitConn( CONN_ID Idx )
+{
+	/* Kompression fuer Link initialisieren */
+
+	assert( Idx > NONE );
+
+	My_Connections[Idx].zip.in.avail_in = 0;
+	My_Connections[Idx].zip.in.total_in = 0;
+	My_Connections[Idx].zip.in.total_out = 0;
+	My_Connections[Idx].zip.in.zalloc = NULL;
+	My_Connections[Idx].zip.in.zfree = NULL;
+	My_Connections[Idx].zip.in.data_type = Z_ASCII;
+
+	if( inflateInit( &My_Connections[Idx].zip.in ) != Z_OK )
+	{
+		/* Fehler! */
+		Log( LOG_ALERT, "Can't initialize compression on connection %d (zlib inflate)!", Idx );
+		return false;
+	}
+
+	My_Connections[Idx].zip.out.total_in = 0;
+	My_Connections[Idx].zip.out.total_in = 0;
+	My_Connections[Idx].zip.out.zalloc = NULL;
+	My_Connections[Idx].zip.out.zfree = NULL;
+	My_Connections[Idx].zip.out.data_type = Z_ASCII;
+
+	if( deflateInit( &My_Connections[Idx].zip.out, Z_DEFAULT_COMPRESSION ) != Z_OK )
+	{
+		/* Fehler! */
+		Log( LOG_ALERT, "Can't initialize compression on connection %d (zlib deflate)!", Idx );
+		return false;
+	}
+
+	My_Connections[Idx].zip.bytes_in = My_Connections[Idx].bytes_in;
+	My_Connections[Idx].zip.bytes_out = My_Connections[Idx].bytes_out;
+
+	Log( LOG_INFO, "Enabled link compression (zlib) on connection %d.", Idx );
+	Conn_OPTION_ADD( &My_Connections[Idx], CONN_ZIP );
+
+	return true;
+} /* Zip_InitConn */
+
+
+GLOBAL bool
+Zip_Buffer( CONN_ID Idx, char *Data, int Len )
+{
+	/* Daten zum Komprimieren im "Kompressions-Puffer" sammeln.
+	* Es wird true bei Erfolg, sonst false geliefert. */
+
+	assert( Idx > NONE );
+	assert( Data != NULL );
+	assert( Len > 0 );
+
+	/* Ist noch Platz im Kompressions-Puffer? */
+	if( ZWRITEBUFFER_LEN - My_Connections[Idx].zip.wdatalen < Len + 50 )
+	{
+		/* Nein! Puffer zunaechst leeren ...*/
+		if( ! Zip_Flush( Idx )) return false;
+	}
+
+	/* Daten kopieren */
+	memmove( My_Connections[Idx].zip.wbuf + My_Connections[Idx].zip.wdatalen, Data, Len );
+	My_Connections[Idx].zip.wdatalen += Len;
+
+	return true;
+} /* Zip_Buffer */
+
+
+GLOBAL bool
+Zip_Flush( CONN_ID Idx )
+{
+	/* Daten komprimieren und in Schreibpuffer kopieren.
+	* Es wird true bei Erfolg, sonst false geliefert. */
+
+	int result, out_len;
+	z_stream *out;
+
+	out = &My_Connections[Idx].zip.out;
+
+	out->next_in = (void *)My_Connections[Idx].zip.wbuf;
+	out->avail_in = My_Connections[Idx].zip.wdatalen;
+	out->next_out = (void *)(My_Connections[Idx].wbuf + My_Connections[Idx].wdatalen);
+	out->avail_out = WRITEBUFFER_LEN - My_Connections[Idx].wdatalen;
+
+	result = deflate( out, Z_SYNC_FLUSH );
+	if(( result != Z_OK ) || ( out->avail_in > 0 ))
+	{
+		Log( LOG_ALERT, "Compression error: code %d!?", result );
+		Conn_Close( Idx, "Compression error!", NULL, false );
+		return false;
+	}
+
+	out_len = WRITEBUFFER_LEN - My_Connections[Idx].wdatalen - out->avail_out;
+	My_Connections[Idx].wdatalen += out_len;
+	My_Connections[Idx].bytes_out += out_len;
+	My_Connections[Idx].zip.bytes_out += My_Connections[Idx].zip.wdatalen;
+	My_Connections[Idx].zip.wdatalen = 0;
+
+	return true;
+} /* Zip_Flush */
+
+
+GLOBAL bool
+Unzip_Buffer( CONN_ID Idx )
+{
+	/* Daten entpacken und in Lesepuffer kopieren. Bei Fehlern
+	* wird false geliefert, ansonsten true. Der Fall, dass keine
+	* Daten mehr zu entpacken sind, ist _kein_ Fehler! */
+
+	int result, in_len, out_len;
+	z_stream *in;
+
+	assert( Idx > NONE );
+
+	if( My_Connections[Idx].zip.rdatalen <= 0 ) return true;
+
+	in = &My_Connections[Idx].zip.in;
+
+	in->next_in = (void *)My_Connections[Idx].zip.rbuf;
+	in->avail_in = My_Connections[Idx].zip.rdatalen;
+	in->next_out = (void *)(My_Connections[Idx].rbuf + My_Connections[Idx].rdatalen);
+	in->avail_out = READBUFFER_LEN - My_Connections[Idx].rdatalen - 1;
+
+	result = inflate( in, Z_SYNC_FLUSH );
+	if( result != Z_OK )
+	{
+		Log( LOG_ALERT, "Decompression error: %s (code=%d, ni=%d, ai=%d, no=%d, ao=%d)!?", in->msg, result, in->next_in, in->avail_in, in->next_out, in->avail_out );
+		Conn_Close( Idx, "Decompression error!", NULL, false );
+		return false;
+	}
+
+	in_len = My_Connections[Idx].zip.rdatalen - in->avail_in;
+	out_len = READBUFFER_LEN - My_Connections[Idx].rdatalen - 1 - in->avail_out;
+	My_Connections[Idx].rdatalen += out_len;
+
+	if( in->avail_in > 0 )
+	{
+		/* es konnten nicht alle Daten entpackt werden, vermutlich war
+		* im Ziel-Puffer kein Platz mehr. Umkopieren ... */
+		My_Connections[Idx].zip.rdatalen -= in_len;
+		memmove( My_Connections[Idx].zip.rbuf, My_Connections[Idx].zip.rbuf + in_len, My_Connections[Idx].zip.rdatalen );
+	}
+	else My_Connections[Idx].zip.rdatalen = 0;
+	My_Connections[Idx].zip.bytes_in += out_len;
+
+	return true;
+} /* Unzip_Buffer */
+
+
+GLOBAL long
+Zip_SendBytes( CONN_ID Idx )
+{
+	/* Anzahl gesendeter Bytes (komprimiert!) liefern */
+
+	assert( Idx > NONE );
+	return My_Connections[Idx].zip.bytes_out;
+} /* Zip_SendBytes */
+
+
+GLOBAL long
+Zip_RecvBytes( CONN_ID Idx )
+{
+	/* Anzahl gesendeter Bytes (komprimiert!) liefern */
+
+	assert( Idx > NONE );
+	return My_Connections[Idx].zip.bytes_in;
+} /* Zip_RecvBytes */
+
+
+#endif
+
+
+/* -eof- */

+ 38 - 0
src/ngircd/conn-zip.h

@@ -0,0 +1,38 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * $Id: conn-zip.h,v 1.3 2005/03/19 18:43:48 fw Exp $
+ *
+ * Connection compression using ZLIB (header)
+ */
+
+
+#ifdef ZLIB
+
+#ifndef __conn_zip_h__
+#define __conn_zip_h__
+
+
+GLOBAL bool Zip_InitConn PARAMS(( CONN_ID Idx ));
+
+GLOBAL bool Zip_Buffer PARAMS(( CONN_ID Idx, char *Data, int Len ));
+GLOBAL bool Zip_Flush PARAMS(( CONN_ID Idx ));
+GLOBAL bool Unzip_Buffer PARAMS(( CONN_ID Idx ));
+
+GLOBAL long Zip_SendBytes PARAMS(( CONN_ID Idx ));
+GLOBAL long Zip_RecvBytes PARAMS(( CONN_ID Idx ));
+
+
+#endif /* __conn_zip_h__ */
+
+#endif /* ZLIB */
+
+
+/* -eof- */

File diff suppressed because it is too large
+ 1723 - 0
src/ngircd/conn.c


+ 107 - 0
src/ngircd/conn.h

@@ -0,0 +1,107 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * $Id: conn.h,v 1.35.2.1 2005/07/30 23:24:50 alex Exp $
+ *
+ * Connection management (header)
+ */
+
+
+#ifndef __conn_h__
+#define __conn_h__
+
+
+#include <time.h>			/* for time_t, see below */
+
+
+#define CONN_ISCLOSING		1	/* Conn_Close() already called */
+#define CONN_ISCONNECTING	2	/* connect() in progress */
+
+#ifdef ZLIB
+#define CONN_ZIP		4	/* zlib compressed link */
+#endif
+
+
+typedef int CONN_ID;
+
+
+#ifdef CONN_MODULE
+
+#include "defines.h"
+#include "resolve.h"
+
+#ifdef ZLIB
+#include <zlib.h>
+typedef struct _ZipData
+{
+	z_stream in;			/* "Handle" for input stream */
+	z_stream out;			/* "Handle" for output stream */
+	char rbuf[READBUFFER_LEN];	/* Read buffer */
+	int rdatalen;			/* Length of data in read buffer (compressed) */
+	char wbuf[WRITEBUFFER_LEN];	/* Write buffer */
+	int wdatalen;			/* Length of data in write buffer (uncompressed) */
+	long bytes_in, bytes_out;	/* Counter for statistics (uncompressed!) */
+} ZIPDATA;
+#endif /* ZLIB */
+
+typedef struct _Connection
+{
+	int sock;			/* Socket handle */
+	struct sockaddr_in addr;	/* Client address */
+	RES_STAT *res_stat;		/* Status of resolver process, if any */
+	char host[HOST_LEN];		/* Hostname */
+	char rbuf[READBUFFER_LEN];	/* Read buffer */
+	int rdatalen;			/* Length of data in read buffer */
+	char wbuf[WRITEBUFFER_LEN];	/* Write buffer */
+	int wdatalen;			/* Length of data in write buffer */
+	time_t lastdata;		/* Last activity */
+	time_t lastping;		/* Last PING */
+	time_t lastprivmsg;		/* Last PRIVMSG */
+	time_t delaytime;		/* Ignore link ("penalty") */
+	long bytes_in, bytes_out;	/* Received and sent bytes */
+	long msg_in, msg_out;		/* Received and sent IRC messages */
+	int flag;			/* Flag (see "irc-write" module) */
+	UINT16 options;			/* Link options / connection state */
+#ifdef ZLIB
+	ZIPDATA zip;			/* Compression information */
+#endif  /* ZLIB */
+} CONNECTION;
+
+GLOBAL CONNECTION *My_Connections;
+GLOBAL CONN_ID Pool_Size;
+GLOBAL long WCounter;
+
+#endif /* CONN_MODULE */
+
+
+GLOBAL void Conn_Init PARAMS((void ));
+GLOBAL void Conn_Exit PARAMS(( void ));
+
+GLOBAL int Conn_InitListeners PARAMS(( void ));
+GLOBAL void Conn_ExitListeners PARAMS(( void ));
+
+GLOBAL bool Conn_NewListener PARAMS(( const UINT16 Port ));
+
+GLOBAL void Conn_Handler PARAMS(( void ));
+
+GLOBAL bool Conn_Write PARAMS(( CONN_ID Idx, char *Data, int Len ));
+GLOBAL bool Conn_WriteStr PARAMS(( CONN_ID Idx, char *Format, ... ));
+
+GLOBAL void Conn_Close PARAMS(( CONN_ID Idx, char *LogMsg, char *FwdMsg, bool InformClient ));
+
+GLOBAL void Conn_SyncServerStruct PARAMS(( void ));
+
+GLOBAL int Conn_MaxFD;
+
+
+#endif
+
+
+/* -eof- */

+ 112 - 0
src/ngircd/defines.h

@@ -0,0 +1,112 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001-2003 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * $Id: defines.h,v 1.52.2.2 2005/07/05 22:58:25 alex Exp $
+ *
+ * Global defines of ngIRCd.
+ */
+
+#ifndef __defines_h__
+#define __defines_h__
+
+
+#define NONE -1
+
+#define FNAME_LEN 256			/* max. length of file name */
+
+#define LINE_LEN 256			/* max. length of a line in the configuration file */
+
+#define HOST_LEN 256			/* max. lenght of fully qualified host names */
+
+#define MAX_LISTEN_PORTS 16		/* max. count of listening ports */
+
+#define MAX_OPERATORS 16		/* max. count of configurable operators */
+
+#define MAX_SERVERS 16			/* max. count of configurable servers ("peers") */
+
+#define MAX_DEFCHANNELS 16		/* max. count of preconfigurable channels */
+
+#define MAX_SERVICES 8			/* max. number of configurable services */
+
+#define MAX_WHOWAS 64			/* max. number of WHOWAS items */
+#define DEFAULT_WHOWAS 5		/* default count for WHOWAS command */
+
+#define CONNECTION_POOL 100		/* size of default connection pool */
+
+#define CLIENT_ID_LEN 64		/* max. length of an IRC ID; see RFC 2812, 1.1 and 1.2.1 */
+#define CLIENT_NICK_LEN 10		/* max. nick length; see. RFC 2812, 1.2.1 */
+#define CLIENT_PASS_LEN 21		/* max. password length */
+#define CLIENT_USER_LEN 10		/* Max. length of user name ("login")
+ 					   see RFC 2812, section 1.2.1 */
+#define CLIENT_NAME_LEN 32		/* max. length of "real names" */
+#define CLIENT_HOST_LEN 64		/* max. host name length */
+#define CLIENT_MODE_LEN 8		/* max. lenth of all client modes */
+#define CLIENT_INFO_LEN 64		/* max. length of server info texts */
+#define CLIENT_AWAY_LEN 128		/* max. length of away messages */
+#define CLIENT_FLAGS_LEN 100		/* max. length of client flags */
+
+#define CHANNEL_NAME_LEN 51		/* max. length of a channel name, see. RFC 2812, 1.3 */
+#define CHANNEL_MODE_LEN 9		/* max. length of channel modes */
+#define CHANNEL_TOPIC_LEN 128		/* max. length of a channel topic */
+
+#define COMMAND_LEN 513			/* max. IRC command length, see. RFC 2812, 3.2 */
+
+#define READBUFFER_LEN 2048		/* size of the read buffer of a connection (bytes) */
+#define WRITEBUFFER_LEN 4096		/* size of the write buffer of a connection (bytes) */
+
+#ifdef ZLIB
+#define ZREADBUFFER_LEN 1024		/* compressed read buffer of a connection (bytes) */
+#define ZWRITEBUFFER_LEN 4096		/* compressed write buffer of a connection (bytes) */
+#endif
+
+#define PROTOVER "0210"			/* implemented IRC protocol version (see RFC 2813, 4.1.1) */
+#define PROTOIRC "-IRC"			/* protocol suffix (see RFC 2813, 4.1.1) */
+#define PROTOIRCPLUS "-IRC+"		/* protokol suffix for IRC+ protocol (see doc/Protocol.txt) */
+
+#ifdef IRCPLUS
+# define IRCPLUSFLAGS "CL"		/* standard IRC+ flags */
+#endif
+
+#define STARTUP_DELAY 1			/* delay outgoing connections n seconds after startup */
+#define RECONNECT_DELAY 3		/* time to delay re-connect attempts (seconds) */
+
+#define USERMODES "aios"		/* supported user modes */
+#define CHANMODES "biklImnoPstv"	/* supported channel modes */
+
+#define CONNECTED true			/* internal status codes */
+#define DISCONNECTED false
+
+#define DEFAULT_AWAY_MSG "Away"		/* away message for users connected to linked servers */
+
+#define CONFIG_FILE "/ngircd.conf"
+#define MOTD_FILE "/ngircd.motd"
+#define MOTD_PHRASE ""
+#define CHROOT_DIR ""
+#define PID_FILE ""
+
+#define ERROR_DIR "/tmp"
+
+#define MAX_LOG_MSG_LEN 256		/* max. length of a log message */
+
+#define TOKEN_OUTBOUND -2		/* tag for outbound server links */
+
+#define NOTICE_TXTPREFIX ""		/* prefix for NOTICEs from the server to users */
+
+#define CUT_TXTSUFFIX "[CUT]"		/* Suffix for oversized messages that
+					   have been shortened and cut off. */
+#ifdef RENDEZVOUS
+#define RENDEZVOUS_TYPE "_ircu._tcp."	/* service type to register with Rendezvous */
+#endif
+
+
+#endif
+
+
+/* -eof- */

+ 125 - 0
src/ngircd/hash.c

@@ -0,0 +1,125 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * Hash calculation
+ */
+
+
+#include "portab.h"
+
+static char UNUSED id[] = "$Id: hash.c,v 1.11 2005/03/19 18:43:48 fw Exp $";
+
+#include "imp.h"
+#include <assert.h>
+#include <string.h>
+
+#include "defines.h"
+#include "tool.h"
+
+#include "exp.h"
+#include "hash.h"
+
+
+LOCAL UINT32 jenkins_hash PARAMS(( register UINT8 *k, register UINT32 length, register UINT32 initval ));
+
+
+GLOBAL UINT32
+Hash( char *String )
+{
+	/* Hash-Wert ueber String berechnen */
+
+	char buffer[LINE_LEN];
+
+	strlcpy( buffer, String, sizeof( buffer ));
+	return jenkins_hash( (UINT8 *)ngt_LowerStr( buffer ), strlen( buffer ), 42 );
+} /* Hash */
+
+
+/*
+ * Die hier verwendete Hash-Funktion stammt aus lookup2.c von Bob Jenkins
+ * (URL: <http://burtleburtle.net/bob/c/lookup2.c>). Aus dem Header:
+ * --------------------------------------------------------------------
+ * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
+ * hash(), hash2(), hash3, and mix() are externally useful functions.
+ * Routines to test the hash are included if SELF_TEST is defined.
+ * You can use this free for any purpose.  It has no warranty.
+ * --------------------------------------------------------------------
+ * nicht alle seiner Funktionen werden hier genutzt.
+ */
+
+
+#define hashsize(n) ((UINT32)1<<(n))
+#define hashmask(n) (hashsize(n)-1)
+
+#define mix(a,b,c) \
+{ \
+	a -= b; a -= c; a ^= (c>>13); \
+	b -= c; b -= a; b ^= (a<<8);  \
+	c -= a; c -= b; c ^= (b>>13); \
+	a -= b; a -= c; a ^= (c>>12); \
+	b -= c; b -= a; b ^= (a<<16); \
+	c -= a; c -= b; c ^= (b>>5);  \
+	a -= b; a -= c; a ^= (c>>3);  \
+	b -= c; b -= a; b ^= (a<<10); \
+	c -= a; c -= b; c ^= (b>>15); \
+} /* mix */
+
+
+LOCAL UINT32
+jenkins_hash( register UINT8 *k, register UINT32 length, register UINT32 initval )
+{
+	/* k: the key
+	 * length: length of the key
+	 * initval: the previous hash, or an arbitrary value
+	 */
+
+	register UINT32 a,b,c,len;
+
+	/* Set up the internal state */
+	len = length;
+	a = b = 0x9e3779b9;	/* the golden ratio; an arbitrary value */
+	c = initval;		/* the previous hash value */
+
+	/* handle most of the key */
+	while (len >= 12)
+	{
+		a += (k[0] +((UINT32)k[1]<<8) +((UINT32)k[2]<<16) +((UINT32)k[3]<<24));
+		b += (k[4] +((UINT32)k[5]<<8) +((UINT32)k[6]<<16) +((UINT32)k[7]<<24));
+		c += (k[8] +((UINT32)k[9]<<8) +((UINT32)k[10]<<16)+((UINT32)k[11]<<24));
+		mix(a,b,c);
+		k += 12; len -= 12;
+	}
+
+	/* handle the last 11 bytes */
+	c += length;
+	switch( (int)len )	/* all the case statements fall through */
+	{
+		case 11: c+=((UINT32)k[10]<<24);
+		case 10: c+=((UINT32)k[9]<<16);
+		case 9 : c+=((UINT32)k[8]<<8);
+		/* the first byte of c is reserved for the length */
+		case 8 : b+=((UINT32)k[7]<<24);
+		case 7 : b+=((UINT32)k[6]<<16);
+		case 6 : b+=((UINT32)k[5]<<8);
+		case 5 : b+=k[4];
+		case 4 : a+=((UINT32)k[3]<<24);
+		case 3 : a+=((UINT32)k[2]<<16);
+		case 2 : a+=((UINT32)k[1]<<8);
+		case 1 : a+=k[0];
+		/* case 0: nothing left to add */
+	}
+	mix(a,b,c);
+
+	/* report the result */
+	return c;
+} /* jenkins_hash */
+
+
+/* -eof- */

+ 27 - 0
src/ngircd/hash.h

@@ -0,0 +1,27 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * $Id: hash.h,v 1.5 2005/03/19 18:43:48 fw Exp $
+ *
+ * Hash calculation (header)
+ */
+
+
+#ifndef __hash_h__
+#define __hash_h__
+
+
+GLOBAL UINT32 Hash PARAMS((char *String ));
+
+
+#endif
+
+
+/* -eof- */

+ 495 - 0
src/ngircd/irc-channel.c

@@ -0,0 +1,495 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * IRC channel commands
+ */
+
+
+#include "portab.h"
+
+static char UNUSED id[] = "$Id: irc-channel.c,v 1.30 2005/06/12 18:23:59 alex Exp $";
+
+#include "imp.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "defines.h"
+#include "conn.h"
+#include "client.h"
+#include "channel.h"
+#include "lists.h"
+#include "log.h"
+#include "match.h"
+#include "messages.h"
+#include "parse.h"
+#include "irc-info.h"
+#include "irc-write.h"
+#include "resolve.h"
+#include "conf.h"
+
+#include "exp.h"
+#include "irc-channel.h"
+
+
+GLOBAL bool
+IRC_JOIN( CLIENT *Client, REQUEST *Req )
+{
+	char *channame, *key, *flags, *topic, modes[8];
+	bool is_new_chan, is_invited, is_banned;
+	CLIENT *target;
+	CHANNEL *chan;
+
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+	/* Bad number of arguments? */
+	if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+
+	/* Who is the sender? */
+	if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_Search( Req->prefix );
+	else target = Client;
+	if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
+
+	/* Are channel keys given? */
+	if( Req->argc > 1 ) key = Req->argv[1];
+	else key = NULL;
+
+	/* Channel-Namen durchgehen */
+	chan = NULL;
+	channame = strtok( Req->argv[0], "," );
+	while( channame )
+	{
+		chan = NULL; flags = NULL;
+
+		/* wird der Channel neu angelegt? */
+		if( Channel_Search( channame )) is_new_chan = false;
+		else is_new_chan = true;
+
+		/* Hat ein Server Channel-User-Modes uebergeben? */
+		if( Client_Type( Client ) == CLIENT_SERVER )
+		{
+			/* Channel-Flags extrahieren */
+			flags = strchr( channame, 0x7 );
+			if( flags )
+			{
+				*flags = '\0';
+				flags++;
+			}
+		}
+
+		/* Local client? */
+		if( Client_Type( Client ) == CLIENT_USER )
+		{
+			/* Test if the user has reached his maximum channel count */
+			if( Client_Type( Client ) == CLIENT_USER )
+			{
+				if(( Conf_MaxJoins > 0 ) && ( Channel_CountForUser( Client ) >= Conf_MaxJoins ))
+				{
+					IRC_WriteStrClient( Client, ERR_TOOMANYCHANNELS_MSG, Client_ID( Client ), channame );
+					return CONNECTED;
+				}
+			}
+
+			/* Existiert der Channel bereits, oder wird er im Moment neu erzeugt? */
+			if( is_new_chan )
+			{
+				/* Erster User im Channel: Operator-Flag setzen */
+				flags = "o";
+			}
+			else
+			{
+				/* Existierenden Channel suchen */
+				chan = Channel_Search( channame );
+				assert( chan != NULL );
+
+				is_banned = Lists_CheckBanned( target, chan );
+				is_invited = Lists_CheckInvited( target, chan );
+
+				/* Testen, ob Client gebanned ist */
+				if(( is_banned == true) &&  ( is_invited == false ))
+				{
+					/* Client ist gebanned (und nicht invited): */
+					IRC_WriteStrClient( Client, ERR_BANNEDFROMCHAN_MSG, Client_ID( Client ), channame );
+
+					/* Try next name, if any */
+					channame = strtok( NULL, "," );
+					continue;
+				}
+
+				/* Ist der Channel "invite-only"? */
+				if(( strchr( Channel_Modes( chan ), 'i' )) && ( is_invited == false ))
+				{
+					/* Channel ist "invite-only" und Client wurde nicht invited: */
+					IRC_WriteStrClient( Client, ERR_INVITEONLYCHAN_MSG, Client_ID( Client ), channame );
+
+					/* Try next name, if any */
+					channame = strtok( NULL, "," );
+					continue;
+				}
+
+				/* Is the channel protected by a key? */
+				if(( strchr( Channel_Modes( chan ), 'k' )) && ( strcmp( Channel_Key( chan ), key ? key : "" ) != 0 ))
+				{
+					/* Bad channel key! */
+					IRC_WriteStrClient( Client, ERR_BADCHANNELKEY_MSG, Client_ID( Client ), channame );
+
+					/* Try next name, if any */
+					channame = strtok( NULL, "," );
+					continue;
+				}
+
+				/* Are there already too many members? */
+				if(( strchr( Channel_Modes( chan ), 'l' )) && ( Channel_MaxUsers( chan ) <= Channel_MemberCount( chan )))
+				{
+					/* Bad channel key! */
+					IRC_WriteStrClient( Client, ERR_CHANNELISFULL_MSG, Client_ID( Client ), channame );
+
+					/* Try next name, if any */
+					channame = strtok( NULL, "," );
+					continue;
+				}
+			}
+		}
+		else
+		{
+			/* Remote server: we don't need to know whether the
+			 * client is invited or not, but we have to make sure
+			 * that the "one shot" entries (generated by INVITE
+			 * commands) in this list become deleted when a user
+			 * joins a channel this way. */
+			chan = Channel_Search( channame );
+			if( chan != NULL ) (void)Lists_CheckInvited( target, chan );
+		}
+
+		/* Channel joinen (und ggf. anlegen) */
+		if( ! Channel_Join( target, channame ))
+		{
+			/* naechsten Namen ermitteln */
+			channame = strtok( NULL, "," );
+			continue;
+		}
+		if( ! chan ) chan = Channel_Search( channame );
+		assert( chan != NULL );
+
+		/* Modes setzen (wenn vorhanden) */
+		while( flags && *flags )
+		{
+			Channel_UserModeAdd( chan, target, *flags );
+			flags++;
+		}
+
+		/* Wenn persistenter Channel und IRC-Operator: zum Channel-OP machen */
+		if(( strchr( Channel_Modes( chan ), 'P' )) && ( strchr( Client_Modes( target ), 'o' ))) Channel_UserModeAdd( chan, target, 'o' );
+
+		/* Muessen Modes an andere Server gemeldet werden? */
+		strlcpy( &modes[1], Channel_UserModes( chan, target ), sizeof( modes ) - 1 );
+		if( modes[1] ) modes[0] = 0x7;
+		else modes[0] = '\0';
+
+		/* An andere Server weiterleiten */
+		IRC_WriteStrServersPrefix( Client, target, "JOIN :%s%s", channame, modes );
+
+		/* im Channel bekannt machen */
+		IRC_WriteStrChannelPrefix( Client, chan, target, false, "JOIN :%s", channame );
+		if( modes[1] )
+		{
+			/* Modes im Channel bekannt machen */
+			IRC_WriteStrChannelPrefix( Client, chan, target, false, "MODE %s +%s %s", channame, &modes[1], Client_ID( target ));
+		}
+
+		if( Client_Type( Client ) == CLIENT_USER )
+		{
+			/* an Client bestaetigen */
+			IRC_WriteStrClientPrefix( Client, target, "JOIN :%s", channame );
+
+			/* Topic an Client schicken */
+			topic = Channel_Topic( chan );
+			if( *topic ) IRC_WriteStrClient( Client, RPL_TOPIC_MSG, Client_ID( Client ), channame, topic );
+
+			/* Mitglieder an Client Melden */
+			IRC_Send_NAMES( Client, chan );
+			IRC_WriteStrClient( Client, RPL_ENDOFNAMES_MSG, Client_ID( Client ), Channel_Name( chan ));
+		}
+
+		/* naechsten Namen ermitteln */
+		channame = strtok( NULL, "," );
+	}
+	return CONNECTED;
+} /* IRC_JOIN */
+
+
+GLOBAL bool
+IRC_PART( CLIENT *Client, REQUEST *Req )
+{
+	CLIENT *target;
+	char *chan;
+
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+	/* Falsche Anzahl Parameter? */
+	if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+
+	/* Wer ist der Absender? */
+	if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_Search( Req->prefix );
+	else target = Client;
+	if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
+
+	/* Channel-Namen durchgehen */
+	chan = strtok( Req->argv[0], "," );
+	while( chan )
+	{
+		if( ! Channel_Part( target, Client, chan, Req->argc > 1 ? Req->argv[1] : Client_ID( target )))
+		{
+			/* naechsten Namen ermitteln */
+			chan = strtok( NULL, "," );
+			continue;
+		}
+
+		/* naechsten Namen ermitteln */
+		chan = strtok( NULL, "," );
+	}
+	return CONNECTED;
+} /* IRC_PART */
+
+
+GLOBAL bool
+IRC_TOPIC( CLIENT *Client, REQUEST *Req )
+{
+	CHANNEL *chan;
+	CLIENT *from;
+	char *topic;
+
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+	/* Falsche Anzahl Parameter? */
+	if(( Req->argc < 1 ) || ( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+
+	if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
+	else from = Client;
+	if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
+
+	/* Welcher Channel? */
+	chan = Channel_Search( Req->argv[0] );
+	if( ! chan ) return IRC_WriteStrClient( from, ERR_NOSUCHCHANNEL_MSG, Client_ID( from ), Req->argv[0] );
+
+	/* Ist der User Mitglied in dem Channel? */
+	if( ! Channel_IsMemberOf( chan, from )) return IRC_WriteStrClient( from, ERR_NOTONCHANNEL_MSG, Client_ID( from ), Req->argv[0] );
+
+	if( Req->argc == 1 )
+	{
+		/* Topic erfragen */
+		topic = Channel_Topic( chan );
+		if( *topic ) return IRC_WriteStrClient( from, RPL_TOPIC_MSG, Client_ID( from ), Channel_Name( chan ), topic );
+		else return IRC_WriteStrClient( from, RPL_NOTOPIC_MSG, Client_ID( from ), Channel_Name( chan ));
+	}
+
+	if( strchr( Channel_Modes( chan ), 't' ))
+	{
+		/* Topic Lock. Ist der User ein Channel Operator? */
+		if( ! strchr( Channel_UserModes( chan, from ), 'o' )) return IRC_WriteStrClient( from, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( from ), Channel_Name( chan ));
+	}
+
+	/* Topic setzen */
+	Channel_SetTopic( chan, Req->argv[1] );
+	Log( LOG_DEBUG, "User \"%s\" set topic on \"%s\": %s", Client_Mask( from ), Channel_Name( chan ), Req->argv[1][0] ? Req->argv[1] : "<none>" );
+
+	/* im Channel bekannt machen und an Server weiterleiten */
+	IRC_WriteStrServersPrefix( Client, from, "TOPIC %s :%s", Req->argv[0], Req->argv[1] );
+	IRC_WriteStrChannelPrefix( Client, chan, from, false, "TOPIC %s :%s", Req->argv[0], Req->argv[1] );
+
+	if( Client_Type( Client ) == CLIENT_USER ) return IRC_WriteStrClientPrefix( Client, Client, "TOPIC %s :%s", Req->argv[0], Req->argv[1] );
+	else return CONNECTED;
+} /* IRC_TOPIC */
+
+
+/**
+ * Handler for the IRC "LIST" command.
+ * This implementation handles the local case as well as the forwarding of the
+ * LIST command to other servers in the IRC network.
+ */
+GLOBAL bool
+IRC_LIST( CLIENT *Client, REQUEST *Req )
+{
+	char *pattern;
+	CHANNEL *chan;
+	CLIENT *from, *target;
+
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+	/* Bad number of prameters? */
+	if( Req->argc > 2 )
+		return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG,
+			Client_ID( Client ), Req->command );
+
+	if( Req->argc > 0 )
+		pattern = strtok( Req->argv[0], "," );
+	else
+		pattern = "*";
+
+	/* Get sender from prefix, if any */
+	if( Client_Type( Client ) == CLIENT_SERVER )
+		from = Client_Search( Req->prefix );
+	else
+		from = Client;
+
+	if( ! from )
+		return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG,
+				Client_ID( Client ), Req->prefix );
+
+	if( Req->argc == 2 )
+	{
+		/* Forward to other server? */
+		target = Client_Search( Req->argv[1] );
+		if(( ! target ) || ( Client_Type( target ) != CLIENT_SERVER ))
+			return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG,
+					Client_ID( Client ), Req->argv[1] );
+
+		if( target != Client_ThisServer( ))
+		{
+			/* Target is indeed an other server, forward it! */
+			return IRC_WriteStrClientPrefix( target, from,
+					"LIST %s :%s", Client_ID( from ),
+					Req->argv[1] );
+		}
+	}
+	
+	while( pattern )
+	{
+		/* Loop through all the channels */
+		chan = Channel_First( );
+		while( chan )
+		{
+			/* Check search pattern */
+			if( Match( pattern, Channel_Name( chan )))
+			{
+				/* Gotcha! */
+				if( ! strchr( Channel_Modes( chan ), 's' ) ||
+				    Channel_IsMemberOf( chan, from ))
+				{
+					if( ! IRC_WriteStrClient( from,
+					    RPL_LIST_MSG, Client_ID( from ),
+					    Channel_Name( chan ),
+					    Channel_MemberCount( chan ),
+					    Channel_Topic( chan )))
+						return DISCONNECTED;
+				}
+			}
+			chan = Channel_Next( chan );
+		}
+		
+		/* Get next name ... */
+		if( Req->argc > 0 )
+			pattern = strtok( NULL, "," );
+		else
+			pattern = NULL;
+	}
+	
+	return IRC_WriteStrClient( from, RPL_LISTEND_MSG, Client_ID( from ));
+} /* IRC_LIST */
+
+
+GLOBAL bool
+IRC_CHANINFO( CLIENT *Client, REQUEST *Req )
+{
+	char modes_add[COMMAND_LEN], l[16], *ptr;
+	CLIENT *from;
+	CHANNEL *chan;
+	int arg_topic;
+
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+	/* Bad number of parameters? */
+	if(( Req->argc < 2 ) || ( Req->argc == 4 ) || ( Req->argc > 5 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+
+	/* Compatibility kludge */
+	if( Req->argc == 5 ) arg_topic = 4;
+	else if( Req->argc == 3 ) arg_topic = 2;
+	else arg_topic = -1;
+
+	/* Search origin */
+	from = Client_Search( Req->prefix );
+	if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
+
+	/* Search or create channel */
+	chan = Channel_Search( Req->argv[0] );
+	if( ! chan ) chan = Channel_Create( Req->argv[0] );
+	if( ! chan ) return CONNECTED;
+
+	if( Req->argv[1][0] == '+' )
+	{
+		ptr = Channel_Modes( chan );
+		if( ! *ptr )
+		{
+			/* OK, this channel doesn't have modes jet, set the received ones: */
+			Channel_SetModes( chan, &Req->argv[1][1] );
+
+			if( Req->argc == 5 )
+			{
+				if( strchr( Channel_Modes( chan ), 'k' )) Channel_SetKey( chan, Req->argv[2] );
+				if( strchr( Channel_Modes( chan ), 'l' )) Channel_SetMaxUsers( chan, atol( Req->argv[3] ));
+			}
+			else
+			{
+				/* Delete modes which we never want to inherit */
+				Channel_ModeDel( chan, 'l' );
+				Channel_ModeDel( chan, 'k' );
+			}
+
+			strcpy( modes_add, "" );
+			ptr = Channel_Modes( chan );
+			while( *ptr )
+			{
+				if( *ptr == 'l' )
+				{
+					snprintf( l, sizeof( l ), " %ld", Channel_MaxUsers( chan ));
+					strlcat( modes_add, l, sizeof( modes_add ));
+				}
+				if( *ptr == 'k' )
+				{
+					strlcat( modes_add, " ", sizeof( modes_add ));
+					strlcat( modes_add, Channel_Key( chan ), sizeof( modes_add ));
+				}
+	     			ptr++;
+			}
+			
+			/* Inform members of this channel */
+			IRC_WriteStrChannelPrefix( Client, chan, from, false, "MODE %s +%s%s", Req->argv[0], Channel_Modes( chan ), modes_add );
+		}
+	}
+	else Log( LOG_WARNING, "CHANINFO: invalid MODE format ignored!" );
+
+	if( arg_topic > 0 )
+	{
+		/* We got a topic */
+		ptr = Channel_Topic( chan );
+		if(( ! *ptr ) && ( Req->argv[arg_topic][0] ))
+		{
+			/* OK, there is no topic jet */
+			Channel_SetTopic( chan, Req->argv[arg_topic] );
+			IRC_WriteStrChannelPrefix( Client, chan, from, false, "TOPIC %s :%s", Req->argv[0], Channel_Topic( chan ));
+		}
+	}
+
+	/* Forward CHANINFO to other serevrs */
+	if( Req->argc == 5 ) IRC_WriteStrServersPrefixFlag( Client, from, 'C', "CHANINFO %s %s %s %s :%s", Req->argv[0], Req->argv[1], Req->argv[2], Req->argv[3], Req->argv[4] );
+	else if( Req->argc == 3 ) IRC_WriteStrServersPrefixFlag( Client, from, 'C', "CHANINFO %s %s :%s", Req->argv[0], Req->argv[1], Req->argv[2] );
+	else IRC_WriteStrServersPrefixFlag( Client, from, 'C', "CHANINFO %s %s", Req->argv[0], Req->argv[1] );
+
+	return CONNECTED;
+} /* IRC_CHANINFO */
+
+
+/* -eof- */

+ 33 - 0
src/ngircd/irc-channel.h

@@ -0,0 +1,33 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * $Id: irc-channel.h,v 1.7 2005/03/19 18:43:48 fw Exp $
+ *
+ * IRC channel commands (header)
+ */
+
+
+#ifndef __irc_channel_h__
+#define __irc_channel_h__
+
+
+GLOBAL bool IRC_JOIN PARAMS((CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_PART PARAMS((CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_TOPIC PARAMS((CLIENT *Client, REQUEST *Req ));
+
+GLOBAL bool IRC_LIST PARAMS((CLIENT *Client, REQUEST *Req ));
+
+GLOBAL bool IRC_CHANINFO PARAMS((CLIENT *Client, REQUEST *Req ));
+
+
+#endif
+
+
+/* -eof- */

File diff suppressed because it is too large
+ 1021 - 0
src/ngircd/irc-info.c


+ 44 - 0
src/ngircd/irc-info.h

@@ -0,0 +1,44 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * $Id: irc-info.h,v 1.3 2005/03/19 18:43:48 fw Exp $
+ *
+ * IRC info commands (header)
+ */
+
+
+#ifndef __irc_info_h__
+#define __irc_info_h__
+
+
+GLOBAL bool IRC_ADMIN PARAMS(( CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_ISON PARAMS(( CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_LINKS PARAMS(( CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_LUSERS PARAMS(( CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_MOTD PARAMS(( CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_NAMES PARAMS(( CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_STATS PARAMS(( CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_TIME PARAMS(( CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_USERHOST PARAMS(( CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_VERSION PARAMS(( CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_WHO PARAMS(( CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_WHOIS PARAMS(( CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_WHOWAS PARAMS(( CLIENT *Client, REQUEST *Req ));
+
+GLOBAL bool IRC_Send_LUSERS PARAMS(( CLIENT *Client ));
+GLOBAL bool IRC_Send_NAMES PARAMS(( CLIENT *Client, CHANNEL *Chan ));
+GLOBAL bool IRC_Show_MOTD PARAMS(( CLIENT *Client ));
+GLOBAL bool IRC_Send_WHO PARAMS(( CLIENT *Client, CHANNEL *Chan, bool OnlyOps ));
+
+
+#endif
+
+
+/* -eof- */

+ 577 - 0
src/ngircd/irc-login.c

@@ -0,0 +1,577 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * Login and logout
+ */
+
+
+#include "portab.h"
+
+static char UNUSED id[] = "$Id: irc-login.c,v 1.44 2005/06/04 12:32:09 fw Exp $";
+
+#include "imp.h"
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+
+#include "ngircd.h"
+#include "resolve.h"
+#include "conn-func.h"
+#include "conf.h"
+#include "client.h"
+#include "channel.h"
+#include "log.h"
+#include "messages.h"
+#include "parse.h"
+#include "irc.h"
+#include "irc-info.h"
+#include "irc-write.h"
+#include "cvs-version.h"
+
+#include "exp.h"
+#include "irc-login.h"
+
+
+LOCAL bool Hello_User PARAMS(( CLIENT *Client ));
+LOCAL void Kill_Nick PARAMS(( char *Nick, char *Reason ));
+
+
+GLOBAL bool
+IRC_PASS( CLIENT *Client, REQUEST *Req )
+{
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+	/* Fehler liefern, wenn kein lokaler Client */
+	if( Client_Conn( Client ) <= NONE ) return IRC_WriteStrClient( Client, ERR_UNKNOWNCOMMAND_MSG, Client_ID( Client ), Req->command );
+	
+	if(( Client_Type( Client ) == CLIENT_UNKNOWN ) && ( Req->argc == 1))
+	{
+		/* noch nicht registrierte unbekannte Verbindung */
+		Log( LOG_DEBUG, "Connection %d: got PASS command ...", Client_Conn( Client ));
+
+		/* Passwort speichern */
+		Client_SetPassword( Client, Req->argv[0] );
+
+		Client_SetType( Client, CLIENT_GOTPASS );
+		return CONNECTED;
+	}
+	else if((( Client_Type( Client ) == CLIENT_UNKNOWN ) || ( Client_Type( Client ) == CLIENT_UNKNOWNSERVER )) && (( Req->argc == 3 ) || ( Req->argc == 4 )))
+	{
+		char c2, c4, *type, *impl, *serverver, *flags, *ptr, *ircflags;
+		int protohigh, protolow;
+
+		/* noch nicht registrierte Server-Verbindung */
+		Log( LOG_DEBUG, "Connection %d: got PASS command (new server link) ...", Client_Conn( Client ));
+
+		/* Passwort speichern */
+		Client_SetPassword( Client, Req->argv[0] );
+
+		/* Protokollversion ermitteln */
+		if( strlen( Req->argv[1] ) >= 4 )
+		{
+			c2 = Req->argv[1][2];
+			c4 = Req->argv[1][4];
+
+			Req->argv[1][4] = '\0';
+			protolow = atoi( &Req->argv[1][2] );
+			Req->argv[1][2] = '\0';
+			protohigh = atoi( Req->argv[1] );
+			
+			Req->argv[1][2] = c2;
+			Req->argv[1][4] = c4;
+		}			
+		else protohigh = protolow = 0;
+
+		/* Protokoll-Typ */
+		if( strlen( Req->argv[1] ) > 4 ) type = &Req->argv[1][4];
+		else type = NULL;
+
+		/* IRC-Flags (nach RFC 2813) */
+		if( Req->argc >= 4 ) ircflags = Req->argv[3];
+		else ircflags = "";
+
+		/* Implementation, Version und ngIRCd-Flags */
+		impl = Req->argv[2];
+		ptr = strchr( impl, '|' );
+		if( ptr ) *ptr = '\0';
+
+		if( type && ( strcmp( type, PROTOIRCPLUS ) == 0 ))
+		{
+			/* auf der anderen Seite laeuft ein Server, der
+			 * ebenfalls das IRC+-Protokoll versteht */
+			serverver = ptr + 1;
+			flags = strchr( serverver, ':' );
+			if( flags )
+			{
+				*flags = '\0';
+				flags++;
+			}
+			else flags = "";
+			Log( LOG_INFO, "Peer announces itself as %s-%s using protocol %d.%d/IRC+ (flags: \"%s\").", impl, serverver, protohigh, protolow, flags );
+		}
+		else
+		{
+			/* auf der anderen Seite laeuft ein Server, der
+			 * nur das Originalprotokoll unterstuetzt */
+			serverver = "";
+			if( strchr( ircflags, 'Z' )) flags = "Z";
+			else flags = "";
+			Log( LOG_INFO, "Peer announces itself as \"%s\" using protocol %d.%d (flags: \"%s\").", impl, protohigh, protolow, flags );
+		}
+
+		Client_SetType( Client, CLIENT_GOTPASSSERVER );
+		Client_SetFlags( Client, flags );
+
+		return CONNECTED;
+	}
+	else if(( Client_Type( Client ) == CLIENT_UNKNOWN  ) || ( Client_Type( Client ) == CLIENT_UNKNOWNSERVER ))
+	{
+		/* Falsche Anzahl Parameter? */
+		return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+	}
+	else return IRC_WriteStrClient( Client, ERR_ALREADYREGISTRED_MSG, Client_ID( Client ));
+} /* IRC_PASS */
+
+
+/**
+ * IRC "NICK" command.
+ * This function implements the IRC command "NICK" which is used to register
+ * with the server, to change already registered nicknames and to introduce
+ * new users which are connected to other servers.
+ */
+GLOBAL bool
+IRC_NICK( CLIENT *Client, REQUEST *Req )
+{
+	CLIENT *intr_c, *target, *c;
+	char *modes;
+
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+#ifndef STRICT_RFC
+	/* Some IRC clients, for example BitchX, send the NICK and USER
+	 * commands in the wrong order ... */
+	if( Client_Type( Client ) == CLIENT_UNKNOWN
+	    || Client_Type( Client ) == CLIENT_GOTPASS
+	    || Client_Type( Client ) == CLIENT_GOTNICK
+	    || Client_Type( Client ) == CLIENT_GOTUSER
+	    || Client_Type( Client ) == CLIENT_USER
+	    || ( Client_Type( Client ) == CLIENT_SERVER && Req->argc == 1 ))
+#else
+	if( Client_Type( Client ) == CLIENT_UNKNOWN
+	    || Client_Type( Client ) == CLIENT_GOTPASS
+	    || Client_Type( Client ) == CLIENT_GOTNICK
+	    || Client_Type( Client ) == CLIENT_USER
+	    || ( Client_Type( Client ) == CLIENT_SERVER && Req->argc == 1 ))
+#endif
+	{
+		/* User registration or change of nickname */
+
+		/* Wrong number of arguments? */
+		if( Req->argc != 1 )
+			return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG,
+						   Client_ID( Client ),
+						   Req->command );
+
+		/* Search "target" client */
+		if( Client_Type( Client ) == CLIENT_SERVER )
+		{
+			target = Client_Search( Req->prefix );
+			if( ! target )
+				return IRC_WriteStrClient( Client,
+							   ERR_NOSUCHNICK_MSG,
+							   Client_ID( Client ),
+							   Req->argv[0] );
+		}
+		else
+		{
+			/* Is this a restricted client? */
+			if( Client_HasMode( Client, 'r' ))
+				return IRC_WriteStrClient( Client,
+							   ERR_RESTRICTED_MSG,
+							   Client_ID( Client ));
+
+			target = Client;
+		}
+
+#ifndef STRICT_RFC
+		/* If the clients tries to change to its own nickname we won't
+		 * do anything. This is how the original ircd behaves and some
+		 * clients (for example Snak) expect it to be like this.
+		 * But I doubt that this is "really the right thing" ... */
+		if( strcmp( Client_ID( target ), Req->argv[0] ) == 0 )
+			return CONNECTED;
+#endif
+
+		/* Check that the new nickname is available. Special case:
+		 * the client only changes from/to upper to lower case. */
+		if( strcasecmp( Client_ID( target ), Req->argv[0] ) != 0 )
+		{
+			if( ! Client_CheckNick( target, Req->argv[0] ))
+				return CONNECTED;
+		}
+
+		if(( Client_Type( target ) != CLIENT_USER )
+		   && ( Client_Type( target ) != CLIENT_SERVER ))
+		{
+			/* New client */
+			Log( LOG_DEBUG, "Connection %d: got valid NICK command ...", 
+			     Client_Conn( Client ));
+
+			/* Register new nickname of this client */
+			Client_SetID( target, Req->argv[0] );
+
+			/* If we received a valid USER command already then
+			 * register the new client! */
+			if( Client_Type( Client ) == CLIENT_GOTUSER )
+				return Hello_User( Client );
+			else
+				Client_SetType( Client, CLIENT_GOTNICK );
+		}
+		else
+		{
+			/* Nickname change */
+			if( Client_Conn( target ) > NONE )
+			{
+				/* Local client */
+				Log( LOG_INFO,
+				     "User \"%s\" changed nick (connection %d): \"%s\" -> \"%s\".",
+				     Client_Mask( target ), Client_Conn( target ),
+				     Client_ID( target ), Req->argv[0] );
+			}
+			else
+			{
+				/* Remote client */
+				Log( LOG_DEBUG,
+				     "User \"%s\" changed nick: \"%s\" -> \"%s\".",
+				     Client_Mask( target ), Client_ID( target ),
+				     Req->argv[0] );
+			}
+
+			/* Inform all users and servers (which have to know)
+			 * of this nickname change */
+			if( Client_Type( Client ) == CLIENT_USER )
+				IRC_WriteStrClientPrefix( Client, Client,
+							  "NICK :%s",
+							  Req->argv[0] );
+			IRC_WriteStrServersPrefix( Client, target,
+						   "NICK :%s", Req->argv[0] );
+			IRC_WriteStrRelatedPrefix( target, target, false,
+						   "NICK :%s", Req->argv[0] );
+			
+			/* Register old nickname for WHOWAS queries */
+			Client_RegisterWhowas( target );
+				
+			/* Save new nickname */
+			Client_SetID( target, Req->argv[0] );
+			
+			IRC_SetPenalty( target, 2 );
+		}
+
+		return CONNECTED;
+	}
+	else if( Client_Type( Client ) == CLIENT_SERVER )
+	{
+		/* Server introduces new client */
+
+		/* Falsche Anzahl Parameter? */
+		if( Req->argc != 7 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+
+		/* Nick ueberpruefen */
+		c = Client_Search( Req->argv[0] );
+		if( c )
+		{
+			/* Der neue Nick ist auf diesem Server bereits registriert:
+			 * sowohl der neue, als auch der alte Client muessen nun
+			 * disconnectiert werden. */
+			Log( LOG_ERR, "Server %s introduces already registered nick \"%s\"!", Client_ID( Client ), Req->argv[0] );
+			Kill_Nick( Req->argv[0], "Nick collision" );
+			return CONNECTED;
+		}
+
+		/* Server, zu dem der Client connectiert ist, suchen */
+		intr_c = Client_GetFromToken( Client, atoi( Req->argv[4] ));
+		if( ! intr_c )
+		{
+			Log( LOG_ERR, "Server %s introduces nick \"%s\" on unknown server!?", Client_ID( Client ), Req->argv[0] );
+			Kill_Nick( Req->argv[0], "Unknown server" );
+			return CONNECTED;
+		}
+
+		/* Neue Client-Struktur anlegen */
+		c = Client_NewRemoteUser( intr_c, Req->argv[0], atoi( Req->argv[1] ), Req->argv[2], Req->argv[3], atoi( Req->argv[4] ), Req->argv[5] + 1, Req->argv[6], true);
+		if( ! c )
+		{
+			/* Eine neue Client-Struktur konnte nicht angelegt werden.
+			 * Der Client muss disconnectiert werden, damit der Netz-
+			 * status konsistent bleibt. */
+			Log( LOG_ALERT, "Can't create client structure! (on connection %d)", Client_Conn( Client ));
+			Kill_Nick( Req->argv[0], "Server error" );
+			return CONNECTED;
+		}
+
+		modes = Client_Modes( c );
+		if( *modes ) Log( LOG_DEBUG, "User \"%s\" (+%s) registered (via %s, on %s, %d hop%s).", Client_Mask( c ), modes, Client_ID( Client ), Client_ID( intr_c ), Client_Hops( c ), Client_Hops( c ) > 1 ? "s": "" );
+		else Log( LOG_DEBUG, "User \"%s\" registered (via %s, on %s, %d hop%s).", Client_Mask( c ), Client_ID( Client ), Client_ID( intr_c ), Client_Hops( c ), Client_Hops( c ) > 1 ? "s": "" );
+
+		/* Andere Server, ausser dem Introducer, informieren */
+		IRC_WriteStrServersPrefix( Client, Client, "NICK %s %d %s %s %d %s :%s", Req->argv[0], atoi( Req->argv[1] ) + 1, Req->argv[2], Req->argv[3], Client_MyToken( intr_c ), Req->argv[5], Req->argv[6] );
+
+		return CONNECTED;
+	}
+	else return IRC_WriteStrClient( Client, ERR_ALREADYREGISTRED_MSG, Client_ID( Client ));
+} /* IRC_NICK */
+
+
+GLOBAL bool
+IRC_USER( CLIENT *Client, REQUEST *Req )
+{
+#ifdef IDENTAUTH
+	char *ptr;
+#endif
+
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+#ifndef STRICT_RFC
+	if( Client_Type( Client ) == CLIENT_GOTNICK || Client_Type( Client ) == CLIENT_GOTPASS || Client_Type( Client ) == CLIENT_UNKNOWN )
+#else
+	if( Client_Type( Client ) == CLIENT_GOTNICK || Client_Type( Client ) == CLIENT_GOTPASS )
+#endif
+	{
+		/* Wrong number of parameters? */
+		if( Req->argc != 4 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+
+		/* User name */
+#ifdef IDENTAUTH
+		ptr = Client_User( Client );
+		if( ! ptr || ! *ptr || *ptr == '~' ) Client_SetUser( Client, Req->argv[0], false );
+#else
+		Client_SetUser( Client, Req->argv[0], false );
+#endif
+
+		/* "Real name" or user info text: Don't set it to the empty string, the original ircd
+		 * can't deal with such "real names" (e. g. "USER user * * :") ... */
+		if( *Req->argv[3] ) Client_SetInfo( Client, Req->argv[3] );
+		else Client_SetInfo( Client, "-" );
+
+		Log( LOG_DEBUG, "Connection %d: got valid USER command ...", Client_Conn( Client ));
+		if( Client_Type( Client ) == CLIENT_GOTNICK ) return Hello_User( Client );
+		else Client_SetType( Client, CLIENT_GOTUSER );
+		return CONNECTED;
+	}
+	else if( Client_Type( Client ) == CLIENT_USER || Client_Type( Client ) == CLIENT_SERVER || Client_Type( Client ) == CLIENT_SERVICE )
+	{
+		return IRC_WriteStrClient( Client, ERR_ALREADYREGISTRED_MSG, Client_ID( Client ));
+	}
+	else return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
+} /* IRC_USER */
+
+
+GLOBAL bool
+IRC_QUIT( CLIENT *Client, REQUEST *Req )
+{
+	CLIENT *target;
+	char quitmsg[LINE_LEN];
+	
+	assert( Client != NULL );
+	assert( Req != NULL );
+		
+	/* Wrong number of arguments? */
+	if( Req->argc > 1 )
+		return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+
+	if (Req->argc == 1)
+		strlcpy(quitmsg, Req->argv[0], sizeof quitmsg);
+
+	if ( Client_Type( Client ) == CLIENT_SERVER )
+	{
+		/* Server */
+		target = Client_Search( Req->prefix );
+		if( ! target )
+		{
+			/* Den Client kennen wir nicht (mehr), also nichts zu tun. */
+			Log( LOG_WARNING, "Got QUIT from %s for unknown client!?", Client_ID( Client ));
+			return CONNECTED;
+		}
+
+		Client_Destroy( target, "Got QUIT command.", Req->argc == 1 ? quitmsg : NULL, true);
+
+		return CONNECTED;
+	}
+	else
+	{
+		if (Req->argc == 1 && quitmsg[0] != '\"') {
+			/* " " to avoid confusion */
+			strlcpy(quitmsg, "\"", sizeof quitmsg);
+			strlcat(quitmsg, Req->argv[0], sizeof quitmsg-1);
+			strlcat(quitmsg, "\"", sizeof quitmsg );
+		}
+
+		/* User, Service, oder noch nicht registriert */
+		Conn_Close( Client_Conn( Client ), "Got QUIT command.", Req->argc == 1 ? quitmsg : NULL, true);
+		
+		return DISCONNECTED;
+	}
+} /* IRC_QUIT */
+
+
+GLOBAL bool
+IRC_PING( CLIENT *Client, REQUEST *Req )
+{
+	CLIENT *target, *from;
+
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+	/* Falsche Anzahl Parameter? */
+	if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NOORIGIN_MSG, Client_ID( Client ));
+#ifdef STRICT_RFC
+	if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+#endif
+
+	if( Req->argc > 1 )
+	{
+		/* es wurde ein Ziel-Client angegeben */
+		target = Client_Search( Req->argv[1] );
+		if(( ! target ) || ( Client_Type( target ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[1] );
+		if( target != Client_ThisServer( ))
+		{
+			/* ok, forwarden */
+			if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
+			else from = Client;
+			if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->prefix );
+			return IRC_WriteStrClientPrefix( target, from, "PING %s :%s", Client_ID( from ), Req->argv[1] );
+		}
+	}
+
+	Log( LOG_DEBUG, "Connection %d: got PING, sending PONG ...", Client_Conn( Client ));
+	return IRC_WriteStrClient( Client, "PONG %s :%s", Client_ID( Client_ThisServer( )), Client_ID( Client ));
+} /* IRC_PING */
+
+
+GLOBAL bool
+IRC_PONG( CLIENT *Client, REQUEST *Req )
+{
+	CLIENT *target, *from;
+
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+	/* Falsche Anzahl Parameter? */
+	if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NOORIGIN_MSG, Client_ID( Client ));
+	if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+
+	/* forwarden? */
+	if( Req->argc == 2 )
+	{
+		target = Client_Search( Req->argv[1] );
+		if(( ! target ) || ( Client_Type( target ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[1] );
+		if( target != Client_ThisServer( ))
+		{
+			/* ok, forwarden */
+			if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
+			else from = Client;
+			if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->prefix );
+			return IRC_WriteStrClientPrefix( target, from, "PONG %s :%s", Client_ID( from ), Req->argv[1] );
+		}
+	}
+
+	/* Der Connection-Timestamp wurde schon beim Lesen aus dem Socket
+	 * aktualisiert, daher muss das hier nicht mehr gemacht werden. */
+
+	if( Client_Conn( Client ) > NONE ) Log( LOG_DEBUG, "Connection %d: received PONG. Lag: %ld seconds.", Client_Conn( Client ), time( NULL ) - Conn_LastPing( Client_Conn( Client )));
+	else Log( LOG_DEBUG, "Connection %d: received PONG.", Client_Conn( Client ));
+
+	return CONNECTED;
+} /* IRC_PONG */
+
+
+LOCAL bool
+Hello_User( CLIENT *Client )
+{
+#ifdef CVSDATE
+	char ver[12], vertxt[30];
+#endif
+
+	assert( Client != NULL );
+
+	/* Check password ... */
+	if( strcmp( Client_Password( Client ), Conf_ServerPwd ) != 0 )
+	{
+		/* Bad password! */
+		Log( LOG_ERR, "User \"%s\" rejected (connection %d): Bad password!", Client_Mask( Client ), Client_Conn( Client ));
+		Conn_Close( Client_Conn( Client ), NULL, "Bad password", true);
+		return DISCONNECTED;
+	}
+
+	Log( LOG_NOTICE, "User \"%s\" registered (connection %d).", Client_Mask( Client ), Client_Conn( Client ));
+
+	/* Inform other servers */
+	IRC_WriteStrServers( NULL, "NICK %s 1 %s %s 1 +%s :%s", Client_ID( Client ), Client_User( Client ), Client_Hostname( Client ), Client_Modes( Client ), Client_Info( Client ));
+
+	/* Welcome :-) */
+	if( ! IRC_WriteStrClient( Client, RPL_WELCOME_MSG, Client_ID( Client ), Client_Mask( Client ))) return false;
+
+	/* Version and system type */
+#ifdef CVSDATE
+	strlcpy( ver, CVSDATE, sizeof( ver ));
+	strncpy( ver + 4, ver + 5, 2 );
+	strncpy( ver + 6, ver + 8, 3 );
+	snprintf( vertxt, sizeof( vertxt ), "%s(%s)", PACKAGE_VERSION, ver );
+	if( ! IRC_WriteStrClient( Client, RPL_YOURHOST_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )), vertxt, TARGET_CPU, TARGET_VENDOR, TARGET_OS )) return false;
+#else
+	if( ! IRC_WriteStrClient( Client, RPL_YOURHOST_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )), PACKAGE_VERSION, TARGET_CPU, TARGET_VENDOR, TARGET_OS )) return false;
+#endif
+
+	if( ! IRC_WriteStrClient( Client, RPL_CREATED_MSG, Client_ID( Client ), NGIRCd_StartStr )) return false;
+#ifdef CVSDATE
+	if( ! IRC_WriteStrClient( Client, RPL_MYINFO_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )), vertxt, USERMODES, CHANMODES )) return false;	
+#else
+	if( ! IRC_WriteStrClient( Client, RPL_MYINFO_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )), PACKAGE_VERSION, USERMODES, CHANMODES )) return false;
+#endif
+
+	/* Features */
+	if( ! IRC_WriteStrClient( Client, RPL_ISUPPORT_MSG, Client_ID( Client ), CLIENT_NICK_LEN - 1, CHANNEL_TOPIC_LEN - 1, CLIENT_AWAY_LEN - 1, Conf_MaxJoins )) return DISCONNECTED;
+
+	Client_SetType( Client, CLIENT_USER );
+
+	if( ! IRC_Send_LUSERS( Client )) return DISCONNECTED;
+	if( ! IRC_Show_MOTD( Client )) return DISCONNECTED;
+
+	/* Suspend the client for a second ... */
+	IRC_SetPenalty( Client, 1 );
+
+	return CONNECTED;
+} /* Hello_User */
+
+
+LOCAL void
+Kill_Nick( char *Nick, char *Reason )
+{
+	REQUEST r;
+
+	assert( Nick != NULL );
+	assert( Reason != NULL );
+
+	r.prefix = (char *)Client_ThisServer( );
+	r.argv[0] = Nick;
+	r.argv[1] = Reason;
+	r.argc = 2;
+
+	Log( LOG_ERR, "User(s) with nick \"%s\" will be disconnected: %s", Nick, Reason );
+	IRC_KILL( Client_ThisServer( ), &r );
+} /* Kill_Nick */
+
+
+/* -eof- */

+ 32 - 0
src/ngircd/irc-login.h

@@ -0,0 +1,32 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * $Id: irc-login.h,v 1.6 2005/03/19 18:43:48 fw Exp $
+ *
+ * Login and logout (header)
+ */
+
+
+#ifndef __irc_login_h__
+#define __irc_login_h__
+
+
+GLOBAL bool IRC_PASS PARAMS((CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_NICK PARAMS((CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_USER PARAMS((CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_PING PARAMS((CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_PONG PARAMS((CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_QUIT PARAMS((CLIENT *Client, REQUEST *Req ));
+
+
+#endif
+
+
+/* -eof- */

+ 728 - 0
src/ngircd/irc-mode.c

@@ -0,0 +1,728 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001-2005 Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * IRC commands for mode changes (MODE, AWAY, ...)
+ */
+
+
+#include "portab.h"
+
+static char UNUSED id[] = "$Id: irc-mode.c,v 1.43 2005/06/17 19:14:58 fw Exp $";
+
+#include "imp.h"
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "defines.h"
+#include "conn.h"
+#include "client.h"
+#include "channel.h"
+#include "irc-write.h"
+#include "lists.h"
+#include "log.h"
+#include "parse.h"
+#include "messages.h"
+#include "resolve.h"
+#include "conf.h"
+
+#include "exp.h"
+#include "irc-mode.h"
+
+
+LOCAL bool Client_Mode PARAMS(( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ));
+LOCAL bool Channel_Mode PARAMS(( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel ));
+
+LOCAL bool Add_Invite PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern ));
+LOCAL bool Add_Ban PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern ));
+
+LOCAL bool Del_Invite PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern ));
+LOCAL bool Del_Ban PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern ));
+
+LOCAL bool Send_ListChange PARAMS(( char *Mode, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Mask ));
+
+
+GLOBAL bool
+IRC_MODE( CLIENT *Client, REQUEST *Req )
+{
+	CLIENT *cl, *origin;
+	CHANNEL *chan;
+
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+	/* No parameters? */
+	if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+
+	/* Origin for answers */
+	if( Client_Type( Client ) == CLIENT_SERVER )
+	{
+		origin = Client_Search( Req->prefix );
+		if( ! origin ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
+	}
+	else origin = Client;
+	
+	/* Channel or user mode? */
+	cl = chan = NULL;
+	if( Client_IsValidNick( Req->argv[0] )) cl = Client_Search( Req->argv[0] );
+	if( Channel_IsValidName( Req->argv[0] )) chan = Channel_Search( Req->argv[0] );
+
+	if( cl ) return Client_Mode( Client, Req, origin, cl );
+	if( chan ) return Channel_Mode( Client, Req, origin, chan );
+
+	/* No target found! */
+	return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] );
+} /* IRC_MODE */
+
+
+LOCAL bool
+Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
+{
+	/* Handle client mode requests */
+
+	char the_modes[COMMAND_LEN], x[2], *mode_ptr;
+	bool ok, set;
+	int mode_arg;
+	size_t len;
+
+	/* Is the client allowed to request or change the modes? */
+	if( Client_Type( Client ) == CLIENT_USER )
+	{
+		/* Users are only allowed to manipulate their own modes! */
+		if( Target != Client ) return IRC_WriteStrClient( Client, ERR_USERSDONTMATCH_MSG, Client_ID( Client ));
+	}
+
+	/* Mode request: let's answer it :-) */
+	if( Req->argc == 1 ) return IRC_WriteStrClient( Origin, RPL_UMODEIS_MSG, Client_ID( Origin ), Client_Modes( Target ));
+
+	mode_arg = 1;
+	mode_ptr = Req->argv[mode_arg];
+
+	/* Initial state: set or unset modes? */
+	if( *mode_ptr == '+' ) set = true;
+	else if( *mode_ptr == '-' ) set = false;
+	else return IRC_WriteStrClient( Origin, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Origin ));
+
+	/* Prepare reply string */
+	if( set ) strcpy( the_modes, "+" );
+	else strcpy( the_modes, "-" );
+
+	x[1] = '\0';
+	ok = CONNECTED;
+	while( mode_ptr )
+	{
+		mode_ptr++;
+		if( ! *mode_ptr )
+		{
+			/* Try next argument if there's any */
+			mode_arg++;
+			if( mode_arg < Req->argc ) mode_ptr = Req->argv[mode_arg];
+			else break;
+		}
+		
+		switch( *mode_ptr )
+		{
+			case '+':
+			case '-':
+				if((( *mode_ptr == '+' ) && ( ! set )) || (( *mode_ptr == '-' ) && ( set )))
+				{
+					/* Action modifier ("+"/"-") must be changed ... */
+					len = strlen( the_modes ) - 1;
+					if(( the_modes[len] == '+' ) || ( the_modes[len] == '-' ))
+					{
+						/* Adjust last action modifier in result */
+						the_modes[len] = *mode_ptr;
+					}
+					else
+					{
+						/* Append modifier character to result string */
+						x[0] = *mode_ptr;
+						strlcat( the_modes, x, sizeof( the_modes ));
+					}
+					if( *mode_ptr == '+' ) set = true;
+					else set = false;
+				}
+				continue;
+		}
+		
+		/* Validate modes */
+		x[0] = '\0';
+		switch( *mode_ptr )
+		{
+			case 'i': /* Invisible */
+			case 's': /* Server messages */
+				x[0] = *mode_ptr;
+				break;
+
+			case 'a': /* Away */
+				if( Client_Type( Client ) == CLIENT_SERVER )
+				{
+					x[0] = 'a';
+					Client_SetAway( Origin, DEFAULT_AWAY_MSG );
+				}
+				else ok = IRC_WriteStrClient( Origin, ERR_NOPRIVILEGES_MSG, Client_ID( Origin ));
+				break;
+
+			case 'o': /* IRC operator (only unsettable!) */
+				if(( ! set ) || ( Client_Type( Client ) == CLIENT_SERVER ))
+				{
+					Client_SetOperByMe( Target, false );
+					x[0] = 'o';
+				}
+				else ok = IRC_WriteStrClient( Origin, ERR_NOPRIVILEGES_MSG, Client_ID( Origin ));
+				break;
+
+			case 'r': /* Restricted (only settable) */
+				if(( set ) || ( Client_Type( Client ) == CLIENT_SERVER )) x[0] = 'r';
+				else ok = IRC_WriteStrClient( Origin, ERR_RESTRICTED_MSG, Client_ID( Origin ));
+				break;
+
+			default:
+				Log( LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\"!?", set ? '+' : '-', *mode_ptr, Client_ID( Origin ));
+				if( Client_Type( Client ) != CLIENT_SERVER ) ok = IRC_WriteStrClient( Origin, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Origin ), set ? '+' : '-', *mode_ptr );
+				x[0] = '\0';
+				goto client_exit;
+		}
+		if( ! ok ) break;
+
+		/* Is there a valid mode change? */
+		if( ! x[0] ) continue;
+
+		if( set )
+		{
+			/* Set mode */
+			if( Client_ModeAdd( Target, x[0] )) strlcat( the_modes, x, sizeof( the_modes ));
+
+		}
+		else
+		{
+			/* Unset mode */
+			if( Client_ModeDel( Target, x[0] )) strlcat( the_modes, x, sizeof( the_modes ));
+		}		
+	}
+client_exit:
+	
+	/* Are there changed modes? */
+	if( the_modes[1] )
+	{
+		/* Remoce needless action modifier characters */
+		len = strlen( the_modes ) - 1;
+		if(( the_modes[len] == '+' ) || ( the_modes[len] == '-' )) the_modes[len] = '\0';
+
+		if( Client_Type( Client ) == CLIENT_SERVER )
+		{
+			/* Forward modes to other servers */
+			IRC_WriteStrServersPrefix( Client, Origin, "MODE %s :%s", Client_ID( Target ), the_modes );
+		}
+		else
+		{
+			/* Send reply to client and inform other servers */
+			ok = IRC_WriteStrClientPrefix( Client, Origin, "MODE %s :%s", Client_ID( Target ), the_modes );
+			IRC_WriteStrServersPrefix( Client, Origin, "MODE %s :%s", Client_ID( Target ), the_modes );
+		}
+		Log( LOG_DEBUG, "User \"%s\": Mode change, now \"%s\".", Client_Mask( Target ), Client_Modes( Target ));
+	}
+	
+	IRC_SetPenalty( Client, 1 );	
+	return ok;
+} /* Client_Mode */
+
+
+LOCAL bool
+Channel_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel )
+{
+	/* Handle channel and channel-user modes */
+
+	char the_modes[COMMAND_LEN], the_args[COMMAND_LEN], x[2], argadd[CLIENT_PASS_LEN], *mode_ptr;
+	bool ok, set, modeok = false, skiponce, use_servermode = false;
+	int mode_arg, arg_arg;
+	CLIENT *client;
+	long l;
+	size_t len;
+
+	/* Mode request: let's answer it :-) */
+	if( Req->argc == 1 )
+	{
+		/* Member or not? -- That's the question! */
+		if( ! Channel_IsMemberOf( Channel, Origin )) return IRC_WriteStrClient( Origin, RPL_CHANNELMODEIS_MSG, Client_ID( Origin ), Channel_Name( Channel ), Channel_Modes( Channel ));
+
+		/* The sender is a member: generate extended reply */
+		strlcpy( the_modes, Channel_Modes( Channel ), sizeof( the_modes ));
+		mode_ptr = the_modes;
+		the_args[0] = '\0';
+		while( *mode_ptr )
+		{
+			switch( *mode_ptr )
+			{
+				case 'l':
+					snprintf( argadd, sizeof( argadd ), " %ld", Channel_MaxUsers( Channel ));
+					strlcat( the_args, argadd, sizeof( the_args ));
+					break;
+				case 'k':
+					strlcat( the_args, " ", sizeof( the_args ));
+					strlcat( the_args, Channel_Key( Channel ), sizeof( the_args ));
+					break;
+			}
+			mode_ptr++;
+		}
+		if( the_args[0] ) strlcat( the_modes, the_args, sizeof( the_modes ));
+
+		return IRC_WriteStrClient( Origin, RPL_CHANNELMODEIS_MSG, Client_ID( Origin ), Channel_Name( Channel ), the_modes );
+	}
+
+	/* Is the user allowed to change modes? */
+	if( Client_Type( Client ) == CLIENT_USER )
+	{
+		/* Is the originating user on that channel? */
+		if( ! Channel_IsMemberOf( Channel, Origin )) return IRC_WriteStrClient( Origin, ERR_NOTONCHANNEL_MSG, Client_ID( Origin ), Channel_Name( Channel ));
+
+		/* Is he channel operator? */
+		if( strchr( Channel_UserModes( Channel, Origin ), 'o' )) modeok = true;
+		else if( Conf_OperCanMode )
+		{
+			/* IRC-Operators can use MODE as well */
+			if( Client_OperByMe( Origin )) {
+				modeok = true;
+				if ( Conf_OperServerMode ) use_servermode = true; /* Change Origin to Server */
+			}
+		}
+	}
+	else modeok = true;
+
+	mode_arg = 1;
+	mode_ptr = Req->argv[mode_arg];
+	if( Req->argc > mode_arg + 1 ) arg_arg = mode_arg + 1;
+	else arg_arg = -1;
+
+	/* Initial state: set or unset modes? */
+	skiponce = false;
+	if( *mode_ptr == '-' ) set = false;
+	else if( *mode_ptr == '+' ) set = true;
+	else set = skiponce = true;
+
+	/* Prepare reply string */
+	if( set ) strcpy( the_modes, "+" );
+	else strcpy( the_modes, "-" );
+	strcpy( the_args, " " );
+
+	x[1] = '\0';
+	ok = CONNECTED;
+	while( mode_ptr )
+	{
+		if( ! skiponce ) mode_ptr++;
+		if( ! *mode_ptr )
+		{
+			/* Try next argument if there's any */
+			if( arg_arg > mode_arg ) mode_arg = arg_arg;
+			else mode_arg++;
+			if( mode_arg < Req->argc ) mode_ptr = Req->argv[mode_arg];
+			else break;
+			if( Req->argc > mode_arg + 1 ) arg_arg = mode_arg + 1;
+			else arg_arg = -1;
+		}
+		skiponce = false;
+
+		switch( *mode_ptr )
+		{
+			case '+':
+			case '-':
+				if((( *mode_ptr == '+' ) && ( ! set )) || (( *mode_ptr == '-' ) && ( set )))
+				{
+					/* Action modifier ("+"/"-") must be changed ... */
+					len = strlen( the_modes ) - 1;
+					if(( the_modes[len] == '+' ) || ( the_modes[len] == '-' ))
+					{
+						/* Adjust last action modifier in result */
+						the_modes[len] = *mode_ptr;
+					}
+					else
+					{
+						/* Append modifier character to result string */
+						x[0] = *mode_ptr;
+						strlcat( the_modes, x, sizeof( the_modes ));
+					}
+					if( *mode_ptr == '+' ) set = true;
+					else set = false;
+				}
+				continue;
+		}
+
+		/* Are there arguments left? */
+		if( arg_arg >= Req->argc ) arg_arg = -1;
+
+		/* Validate modes */
+		x[0] = '\0';
+		argadd[0] = '\0';
+		client = NULL;
+		switch( *mode_ptr )
+		{
+			/* --- Channel modes --- */
+
+			case 'i': /* Invite only */
+			case 'm': /* Moderated */
+			case 'n': /* Only members can write */
+			case 's': /* Secret channel */
+			case 't': /* Topic locked */
+				if( modeok ) x[0] = *mode_ptr;
+				else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
+				break;
+
+			case 'k': /* Channel key */
+				if( ! set )
+				{
+					if( modeok ) x[0] = *mode_ptr;
+					else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
+					break;
+				}
+				if( arg_arg > mode_arg )
+				{
+					if( modeok )
+					{
+						Channel_ModeDel( Channel, 'k' );
+						Channel_SetKey( Channel, Req->argv[arg_arg] );
+						strlcpy( argadd, Channel_Key( Channel ), sizeof( argadd ));
+						x[0] = *mode_ptr;
+					}
+					else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
+					Req->argv[arg_arg][0] = '\0';
+					arg_arg++;
+				}
+				else ok = IRC_WriteStrClient( Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID( Origin ), Req->command );
+				break;
+
+			case 'l': /* Member limit */
+				if( ! set )
+				{
+					if( modeok ) x[0] = *mode_ptr;
+					else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
+					break;
+				}
+				if( arg_arg > mode_arg )
+				{
+					if( modeok )
+					{
+						l = atol( Req->argv[arg_arg] );
+						if( l > 0 && l < 0xFFFF )
+						{
+							Channel_ModeDel( Channel, 'l' );
+							Channel_SetMaxUsers( Channel, l );
+							snprintf( argadd, sizeof( argadd ), "%ld", l );
+							x[0] = *mode_ptr;
+						}
+					}
+					else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
+					Req->argv[arg_arg][0] = '\0';
+					arg_arg++;
+				}
+				else ok = IRC_WriteStrClient( Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID( Origin ), Req->command );
+				break;
+
+			case 'P': /* Persistent channel */
+				if( modeok )
+				{
+					if( set && ( ! Client_OperByMe( Client )))
+					{
+						/* Only IRC operators are allowed to set P mode */
+						ok = IRC_WriteStrClient( Origin, ERR_NOPRIVILEGES_MSG, Client_ID( Origin ));
+					}
+					else x[0] = 'P';
+				}
+				else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
+				break;
+
+			/* --- Channel user modes --- */
+
+			case 'o': /* Channel operator */
+			case 'v': /* Voice */
+				if( arg_arg > mode_arg )
+				{
+					if( modeok )
+					{
+						client = Client_Search( Req->argv[arg_arg] );
+						if( client ) x[0] = *mode_ptr;
+						else ok = IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[arg_arg] );
+					}
+					else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
+					Req->argv[arg_arg][0] = '\0';
+					arg_arg++;
+				}
+				else ok = IRC_WriteStrClient( Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID( Origin ), Req->command );
+				break;
+
+			/* --- Channel lists --- */
+
+			case 'I': /* Invite lists */
+				if( arg_arg > mode_arg )
+				{
+					/* modify list */
+					if( modeok )
+					{
+						if( set ) Add_Invite( Origin, Client, Channel, Req->argv[arg_arg] );
+						else Del_Invite( Origin, Client, Channel, Req->argv[arg_arg] );
+					}
+					else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
+					Req->argv[arg_arg][0] = '\0';
+					arg_arg++;
+				}
+				else Lists_ShowInvites( Origin, Channel );
+				break;
+
+			case 'b': /* Ban lists */
+				if( arg_arg > mode_arg )
+				{
+					/* modify list */
+					if( modeok )
+					{
+						if( set ) Add_Ban( Origin, Client, Channel, Req->argv[arg_arg] );
+						else Del_Ban( Origin, Client, Channel, Req->argv[arg_arg] );
+					}
+					else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
+					Req->argv[arg_arg][0] = '\0';
+					arg_arg++;
+				}
+				else Lists_ShowBans( Origin, Channel );
+				break;
+
+			default:
+				Log( LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\" on %s!?", set ? '+' : '-', *mode_ptr, Client_ID( Origin ), Channel_Name( Channel ));
+				if( Client_Type( Client ) != CLIENT_SERVER ) ok = IRC_WriteStrClient( Origin, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Origin ), set ? '+' : '-', *mode_ptr );
+				x[0] = '\0';
+				goto chan_exit;
+		}
+		if( ! ok ) break;
+
+		/* Is there a valid mode change? */
+		if( ! x[0] ) continue;
+
+		/* Validate target client */
+		if( client && ( ! Channel_IsMemberOf( Channel, client )))
+		{
+			if( ! IRC_WriteStrClient( Origin, ERR_USERNOTINCHANNEL_MSG, Client_ID( Origin ), Client_ID( client ), Channel_Name( Channel ))) break;
+			continue;
+		}
+
+		if( set )
+		{
+			/* Set mode */
+			if( client )
+			{
+				/* Channel-User-Mode */
+				if( Channel_UserModeAdd( Channel, client, x[0] ))
+				{
+					strlcat( the_args, Client_ID( client ), sizeof( the_args ));
+					strlcat( the_args, " ", sizeof( the_args ));
+					strlcat( the_modes, x, sizeof( the_modes ));
+					Log( LOG_DEBUG, "User \"%s\": Mode change on %s, now \"%s\"", Client_Mask( client ), Channel_Name( Channel ), Channel_UserModes( Channel, client ));
+				}
+			}
+			else
+			{
+				/* Channel-Mode */
+				if( Channel_ModeAdd( Channel, x[0] ))
+				{
+					strlcat( the_modes, x, sizeof( the_modes ));
+					Log( LOG_DEBUG, "Channel %s: Mode change, now \"%s\".", Channel_Name( Channel ), Channel_Modes( Channel ));
+				}
+			}
+		}
+		else
+		{
+			/* Unset mode */
+			if( client )
+			{
+				/* Channel-User-Mode */
+				if( Channel_UserModeDel( Channel, client, x[0] ))
+				{
+					strlcat( the_args, Client_ID( client ), sizeof( the_args ));
+					strlcat( the_args, " ", sizeof( the_args ));
+					strlcat( the_modes, x, sizeof( the_modes ));
+					Log( LOG_DEBUG, "User \"%s\": Mode change on %s, now \"%s\"", Client_Mask( client ), Channel_Name( Channel ), Channel_UserModes( Channel, client ));
+				}
+			}
+			else
+			{
+				/* Channel-Mode */
+				if( Channel_ModeDel( Channel, x[0] ))
+				{
+					strlcat( the_modes, x, sizeof( the_modes ));
+					Log( LOG_DEBUG, "Channel %s: Mode change, now \"%s\".", Channel_Name( Channel ), Channel_Modes( Channel ));
+				}
+			}
+		}
+
+		/* Are there additional arguments to add? */
+		if( argadd[0] )
+		{
+			len = strlen( the_args ) - 1;
+			if( the_args[len] != ' ' ) strlcat( the_args, " ", sizeof( the_args ));
+			strlcat( the_args, argadd, sizeof( the_args ));
+		}
+	}
+chan_exit:
+
+	/* Are there changed modes? */
+	if( the_modes[1] )
+	{
+		/* Clean up mode string */
+		len = strlen( the_modes ) - 1;
+		if(( the_modes[len] == '+' ) || ( the_modes[len] == '-' )) the_modes[len] = '\0';
+
+		/* Clean up argument string if there are none */
+		if( ! the_args[1] ) the_args[0] = '\0';
+
+		if( Client_Type( Client ) == CLIENT_SERVER )
+		{
+			/* Forward mode changes to channel users and other servers */
+			IRC_WriteStrServersPrefix( Client, Origin, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args );
+			IRC_WriteStrChannelPrefix( Client, Channel, Origin, false, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args );
+		}
+		else
+		{
+			if ( use_servermode ) Origin = Client_ThisServer();
+
+			/* Send reply to client and inform other servers and channel users */
+			ok = IRC_WriteStrClientPrefix( Client, Origin, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args );
+			IRC_WriteStrServersPrefix( Client, Origin, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args );
+			IRC_WriteStrChannelPrefix( Client, Channel, Origin, false, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args );
+		}
+	}
+
+	IRC_SetPenalty( Client, 1 );
+	return CONNECTED;
+} /* Channel_Mode */
+
+
+GLOBAL bool
+IRC_AWAY( CLIENT *Client, REQUEST *Req )
+{
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+	/* Falsche Anzahl Parameter? */
+	if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+
+	if(( Req->argc == 1 ) && (Req->argv[0][0] ))
+	{
+		/* AWAY setzen */
+		Client_SetAway( Client, Req->argv[0] );
+		Client_ModeAdd( Client, 'a' );
+		IRC_WriteStrServersPrefix( Client, Client, "MODE %s :+a", Client_ID( Client ));
+		return IRC_WriteStrClient( Client, RPL_NOWAWAY_MSG, Client_ID( Client ));
+	}
+	else
+	{
+		/* AWAY loeschen */
+		Client_ModeDel( Client, 'a' );
+		IRC_WriteStrServersPrefix( Client, Client, "MODE %s :-a", Client_ID( Client ));
+		return IRC_WriteStrClient( Client, RPL_UNAWAY_MSG, Client_ID( Client ));
+	}
+} /* IRC_AWAY */
+
+
+LOCAL bool
+Add_Invite( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )
+{
+	char *mask;
+	bool already;
+
+	assert( Client != NULL );
+	assert( Channel != NULL );
+	assert( Pattern != NULL );
+
+	mask = Lists_MakeMask( Pattern );
+
+	already = Lists_IsInviteEntry( mask, Channel );
+	
+	if( ! Lists_AddInvited( mask, Channel, false )) return CONNECTED;
+	
+	if(( Client_Type( Prefix ) == CLIENT_SERVER ) && ( already == true)) return CONNECTED;
+
+	return Send_ListChange( "+I", Prefix, Client, Channel, mask );
+} /* Add_Invite */
+
+
+LOCAL bool
+Add_Ban( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )
+{
+	char *mask;
+	bool already;
+
+	assert( Client != NULL );
+	assert( Channel != NULL );
+	assert( Pattern != NULL );
+
+	mask = Lists_MakeMask( Pattern );
+
+	already = Lists_IsBanEntry( mask, Channel );
+
+	if( ! Lists_AddBanned( mask, Channel )) return CONNECTED;
+
+	if(( Client_Type( Prefix ) == CLIENT_SERVER ) && ( already == true)) return CONNECTED;
+
+	return Send_ListChange( "+b", Prefix, Client, Channel, mask );
+} /* Add_Ban */
+
+
+LOCAL bool
+Del_Invite( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )
+{
+	char *mask;
+
+	assert( Client != NULL );
+	assert( Channel != NULL );
+	assert( Pattern != NULL );
+
+	mask = Lists_MakeMask( Pattern );
+	Lists_DelInvited( mask, Channel );
+	return Send_ListChange( "-I", Prefix, Client, Channel, mask );
+} /* Del_Invite */
+
+
+LOCAL bool
+Del_Ban( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )
+{
+	char *mask;
+
+	assert( Client != NULL );
+	assert( Channel != NULL );
+	assert( Pattern != NULL );
+
+	mask = Lists_MakeMask( Pattern );
+	Lists_DelBanned( mask, Channel );
+	return Send_ListChange( "-b", Prefix, Client, Channel, mask );
+} /* Del_Ban */
+
+
+LOCAL bool
+Send_ListChange( char *Mode, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Mask )
+{
+	/* Bestaetigung an Client schicken & andere Server sowie Channel-User informieren */
+
+	bool ok;
+
+	if( Client_Type( Client ) == CLIENT_USER )
+	{
+		/* Bestaetigung an Client */
+		ok = IRC_WriteStrClientPrefix( Client, Prefix, "MODE %s %s %s", Channel_Name( Channel ), Mode, Mask );
+	}
+	else ok = true;
+
+	/* an andere Server */
+	IRC_WriteStrServersPrefix( Client, Prefix, "MODE %s %s %s", Channel_Name( Channel ), Mode, Mask );
+
+	/* und lokale User im Channel */
+	IRC_WriteStrChannelPrefix( Client, Channel, Prefix, false, "MODE %s %s %s", Channel_Name( Channel ), Mode, Mask );
+	
+	return ok;
+} /* Send_ListChange */
+
+
+/* -eof- */

+ 28 - 0
src/ngircd/irc-mode.h

@@ -0,0 +1,28 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * $Id: irc-mode.h,v 1.6 2005/03/19 18:43:48 fw Exp $
+ *
+ * IRC commands for mode changes (header)
+ */
+
+
+#ifndef __irc_mode_h__
+#define __irc_mode_h__
+
+
+GLOBAL bool IRC_MODE PARAMS((CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_AWAY PARAMS((CLIENT *Client, REQUEST *Req ));
+
+
+#endif
+
+
+/* -eof- */

+ 126 - 0
src/ngircd/irc-op.c

@@ -0,0 +1,126 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001-2005 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * Channel operator commands
+ */
+
+
+#include "portab.h"
+
+static char UNUSED id[] = "$Id: irc-op.c,v 1.15 2005/04/27 07:39:18 alex Exp $";
+
+#include "imp.h"
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "defines.h"
+#include "conn.h"
+#include "client.h"
+#include "channel.h"
+#include "irc-write.h"
+#include "lists.h"
+#include "log.h"
+#include "messages.h"
+#include "parse.h"
+
+#include "exp.h"
+#include "irc-op.h"
+
+
+GLOBAL bool
+IRC_KICK( CLIENT *Client, REQUEST *Req )
+{
+	CLIENT *target, *from;
+	
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+	/* Falsche Anzahl Parameter? */
+	if(( Req->argc < 2) || ( Req->argc > 3 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+
+	if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
+	else from = Client;
+	if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
+	
+	/* Ziel-User suchen */
+	target = Client_Search( Req->argv[1] );
+	if( ! target ) return IRC_WriteStrClient( from, ERR_NOSUCHNICK_MSG, Client_ID( from ), Req->argv[1] );
+
+	Channel_Kick( target, from, Req->argv[0], Req->argc == 3 ? Req->argv[2] : Client_ID( from ));
+	return CONNECTED;
+} /* IRC_KICK */	
+
+
+GLOBAL bool
+IRC_INVITE( CLIENT *Client, REQUEST *Req )
+{
+	CHANNEL *chan;
+	CLIENT *target, *from;
+	bool remember = false;
+
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+	/* Wrong number of parameters? */
+	if( Req->argc != 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+
+	if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
+	else from = Client;
+	if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
+	
+	/* Search user */
+	target = Client_Search( Req->argv[0] );
+	if(( ! target ) || ( Client_Type( target ) != CLIENT_USER )) return IRC_WriteStrClient( from, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] );
+
+	chan = Channel_Search( Req->argv[1] );
+
+	if( chan )
+	{
+		/* Channel exists. Is the user a valid member of the channel? */
+		if( ! Channel_IsMemberOf( chan, from )) return IRC_WriteStrClient( from, ERR_NOTONCHANNEL_MSG, Client_ID( Client ), Req->argv[1] );
+
+		/* Is the channel "invite-only"? */
+		if( strchr( Channel_Modes( chan ), 'i' ))
+		{
+			/* Yes. The user must be channel operator! */
+			if( ! strchr( Channel_UserModes( chan, from ), 'o' )) return IRC_WriteStrClient( from, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( from ), Channel_Name( chan ));
+			remember = true;
+		}
+
+		/* Is the target user already member of the channel? */
+		if( Channel_IsMemberOf( chan, target )) return IRC_WriteStrClient( from, ERR_USERONCHANNEL_MSG, Client_ID( from ), Req->argv[0], Req->argv[1] );
+
+		/* If the target user is banned on that channel: remember invite */
+		if( Lists_CheckBanned( target, chan )) remember = true;
+
+		if( remember )
+		{
+			/* We must memember this invite */
+			if( ! Lists_AddInvited( Client_Mask( target ), chan, true)) return CONNECTED;
+		}
+	}
+
+	Log( LOG_DEBUG, "User \"%s\" invites \"%s\" to \"%s\" ...", Client_Mask( from ), Req->argv[0], Req->argv[1] );
+	
+	/* Inform target client */
+	IRC_WriteStrClientPrefix( target, from, "INVITE %s %s", Req->argv[0], Req->argv[1] );
+
+	if( Client_Conn( target ) > NONE )
+	{
+		/* The target user is local, so we have to send the status code */
+		if( ! IRC_WriteStrClientPrefix( from, target, RPL_INVITING_MSG, Client_ID( from ), Req->argv[0], Req->argv[1] )) return DISCONNECTED;
+	}
+	
+	return CONNECTED;
+} /* IRC_INVITE */
+
+
+/* -eof- */

+ 28 - 0
src/ngircd/irc-op.h

@@ -0,0 +1,28 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * $Id: irc-op.h,v 1.4 2005/03/19 18:43:48 fw Exp $
+ *
+ * Channel operator commands (header)
+ */
+
+
+#ifndef __irc_op_h__
+#define __irc_op_h__
+
+
+GLOBAL bool IRC_KICK PARAMS(( CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_INVITE PARAMS(( CLIENT *Client, REQUEST *Req ));
+
+
+#endif
+
+
+/* -eof- */

+ 216 - 0
src/ngircd/irc-oper.c

@@ -0,0 +1,216 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * IRC operator commands
+ */
+
+
+#include "portab.h"
+
+static char UNUSED id[] = "$Id: irc-oper.c,v 1.22 2005/06/12 18:02:09 fw Exp $";
+
+#include "imp.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ngircd.h"
+#include "resolve.h"
+#include "conn.h"
+#include "conf.h"
+#include "client.h"
+#include "channel.h"
+#include "irc-write.h"
+#include "log.h"
+#include "match.h"
+#include "messages.h"
+#include "parse.h"
+
+#include <exp.h>
+#include "irc-oper.h"
+
+
+LOCAL bool
+Bad_OperPass(CLIENT *Client, char *errtoken, char *errmsg)
+{
+	Log( LOG_WARNING, "Got invalid OPER from \"%s\": \"%s\" -- %s", Client_Mask( Client ),
+										errtoken, errmsg);
+	IRC_SetPenalty(Client, 3);
+	return IRC_WriteStrClient( Client, ERR_PASSWDMISMATCH_MSG, Client_ID( Client ));
+}
+
+
+GLOBAL bool
+IRC_OPER( CLIENT *Client, REQUEST *Req )
+{
+	int i;
+
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+	/* Falsche Anzahl Parameter? */
+	if( Req->argc != 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+
+	/* Operator suchen */
+	for( i = 0; i < Conf_Oper_Count; i++)
+	{
+		if( Conf_Oper[i].name[0] && Conf_Oper[i].pwd[0] && ( strcmp( Conf_Oper[i].name, Req->argv[0] ) == 0 )) break;
+	}
+	if( i >= Conf_Oper_Count )
+		return Bad_OperPass(Client, Req->argv[0], "not configured");
+
+	/* Stimmt das Passwort? */
+	if( strcmp( Conf_Oper[i].pwd, Req->argv[1] ) != 0 )
+		return Bad_OperPass(Client, Conf_Oper[i].name, "Bad password");
+
+	/* Authorized Mask? */
+	if( Conf_Oper[i].mask && (! Match( Conf_Oper[i].mask, Client_Mask( Client ) )))
+		return Bad_OperPass(Client, Conf_Oper[i].mask, "hostmask check failed" );
+
+	if( ! Client_HasMode( Client, 'o' ))
+	{
+		/* noch kein o-Mode gesetzt */
+		Client_ModeAdd( Client, 'o' );
+		if( ! IRC_WriteStrClient( Client, "MODE %s :+o", Client_ID( Client ))) return DISCONNECTED;
+		IRC_WriteStrServersPrefix( NULL, Client, "MODE %s :+o", Client_ID( Client ));
+	}
+
+	if( ! Client_OperByMe( Client )) Log( LOG_NOTICE|LOG_snotice, "Got valid OPER from \"%s\", user is an IRC operator now.", Client_Mask( Client ));
+
+	Client_SetOperByMe( Client, true);
+	return IRC_WriteStrClient( Client, RPL_YOUREOPER_MSG, Client_ID( Client ));
+} /* IRC_OPER */
+
+
+GLOBAL bool
+IRC_DIE( CLIENT *Client, REQUEST *Req )
+{
+	/* Shut down server */
+
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+	/* Not a local IRC operator? */
+	if(( ! Client_HasMode( Client, 'o' )) || ( ! Client_OperByMe( Client ))) return IRC_WriteStrClient( Client, ERR_NOPRIVILEGES_MSG, Client_ID( Client ));
+	
+	/* Bad number of parameters? */
+	if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+
+	Log( LOG_NOTICE|LOG_snotice, "Got DIE command from \"%s\" ...", Client_Mask( Client ));
+	NGIRCd_SignalQuit = true;
+	return CONNECTED;
+} /* IRC_DIE */
+
+
+GLOBAL bool
+IRC_REHASH( CLIENT *Client, REQUEST *Req )
+{
+	/* Reload configuration file */
+
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+	/* Not a local IRC operator? */
+	if(( ! Client_HasMode( Client, 'o' )) || ( ! Client_OperByMe( Client ))) return IRC_WriteStrClient( Client, ERR_NOPRIVILEGES_MSG, Client_ID( Client ));
+
+	/* Bad number of parameters? */
+	if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+
+	Log( LOG_NOTICE|LOG_snotice, "Got REHASH command from \"%s\" ...", Client_Mask( Client ));
+	NGIRCd_SignalRehash = true;
+	
+	return CONNECTED;
+} /* IRC_REHASH */
+
+
+GLOBAL bool
+IRC_RESTART( CLIENT *Client, REQUEST *Req )
+{
+	/* Restart IRC server (fork a new process) */
+
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+	/* Not a local IRC operator? */
+	if(( ! Client_HasMode( Client, 'o' )) || ( ! Client_OperByMe( Client ))) return IRC_WriteStrClient( Client, ERR_NOPRIVILEGES_MSG, Client_ID( Client ));
+
+	/* Bad number of parameters? */
+	if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+
+	Log( LOG_NOTICE|LOG_snotice, "Got RESTART command from \"%s\" ...", Client_Mask( Client ));
+	NGIRCd_SignalRestart = true;
+	return CONNECTED;
+} /* IRC_RESTART */
+
+
+GLOBAL bool
+IRC_CONNECT(CLIENT *Client, REQUEST *Req )
+{
+	/* Connect configured or new server */
+
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+	/* Not a local IRC operator? */
+	if(( ! Client_HasMode( Client, 'o' )) || ( ! Client_OperByMe( Client ))) return IRC_WriteStrClient( Client, ERR_NOPRIVILEGES_MSG, Client_ID( Client ));
+
+	/* Bad number of parameters? */
+	if(( Req->argc != 2 ) && ( Req->argc != 5 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+
+	/* Invalid port number? */
+	if( atoi( Req->argv[1] ) < 1 )  return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+
+	Log( LOG_NOTICE|LOG_snotice, "Got CONNECT command from \"%s\" for \"%s\".", Client_Mask( Client ), Req->argv[0]);
+
+	if( Req->argc == 2 )
+	{
+		/* Connect configured server */
+		if( ! Conf_EnableServer( Req->argv[0], atoi( Req->argv[1] ))) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[0] );
+	}
+	else
+	{
+		/* Add server */
+		if( ! Conf_AddServer( Req->argv[0], atoi( Req->argv[1] ), Req->argv[2], Req->argv[3], Req->argv[4] )) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[0] );
+	}
+	return CONNECTED;
+} /* IRC_CONNECT */
+
+
+GLOBAL bool
+IRC_DISCONNECT(CLIENT *Client, REQUEST *Req )
+{
+	/* Disconnect and disable configured server */
+
+	CONN_ID my_conn;
+
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+	/* Not a local IRC operator? */
+	if(( ! Client_HasMode( Client, 'o' )) || ( ! Client_OperByMe( Client ))) return IRC_WriteStrClient( Client, ERR_NOPRIVILEGES_MSG, Client_ID( Client ));
+
+	/* Bad number of parameters? */
+	if( Req->argc != 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+
+	Log( LOG_NOTICE|LOG_snotice, "Got DISCONNECT command from \"%s\" for0 \"%s\".", Client_Mask( Client ), Req->argv[0]);
+
+	/* Save ID of this connection */
+	my_conn = Client_Conn( Client );
+
+	/* Connect configured server */
+	if( ! Conf_DisableServer( Req->argv[0] )) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[0] );
+
+	/* Are we still connected or were we killed, too? */
+	if( Client_GetFromConn( my_conn )) return CONNECTED;
+	else return DISCONNECTED;
+} /* IRC_CONNECT */
+
+
+/* -eof- */

+ 32 - 0
src/ngircd/irc-oper.h

@@ -0,0 +1,32 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * $Id: irc-oper.h,v 1.11 2005/03/19 18:43:48 fw Exp $
+ *
+ * IRC operator commands (header)
+ */
+
+
+#ifndef __irc_oper_h__
+#define __irc_oper_h__
+
+
+GLOBAL bool IRC_OPER PARAMS((CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_DIE PARAMS((CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_REHASH PARAMS((CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_RESTART PARAMS((CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_CONNECT PARAMS((CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_DISCONNECT PARAMS((CLIENT *Client, REQUEST *Req ));
+
+
+#endif
+
+
+/* -eof- */

+ 427 - 0
src/ngircd/irc-server.c

@@ -0,0 +1,427 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * IRC commands for server links
+ */
+
+
+#include "portab.h"
+
+static char UNUSED id[] = "$Id: irc-server.c,v 1.38 2005/03/19 18:43:49 fw Exp $";
+
+#include "imp.h"
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+
+#include "defines.h"
+#include "resolve.h"
+#include "conn.h"
+#include "conn-zip.h"
+#include "conf.h"
+#include "client.h"
+#include "channel.h"
+#include "irc-write.h"
+#include "lists.h"
+#include "log.h"
+#include "messages.h"
+#include "parse.h"
+#include "ngircd.h"
+
+#include "exp.h"
+#include "irc-server.h"
+
+
+GLOBAL bool
+IRC_SERVER( CLIENT *Client, REQUEST *Req )
+{
+	char str[LINE_LEN], *ptr, *modes, *topic;
+	CLIENT *from, *c, *cl;
+	CL2CHAN *cl2chan;
+	int max_hops, i;
+	CHANNEL *chan;
+	bool ok;
+	CONN_ID con;
+	
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+	/* Fehler liefern, wenn kein lokaler Client */
+	if( Client_Conn( Client ) <= NONE ) return IRC_WriteStrClient( Client, ERR_UNKNOWNCOMMAND_MSG, Client_ID( Client ), Req->command );
+
+	if( Client_Type( Client ) == CLIENT_GOTPASSSERVER )
+	{
+		/* Verbindung soll als Server-Server-Verbindung registriert werden */
+		Log( LOG_DEBUG, "Connection %d: got SERVER command (new server link) ...", Client_Conn( Client ));
+
+		/* Falsche Anzahl Parameter? */
+		if(( Req->argc != 2 ) && ( Req->argc != 3 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+
+		/* Ist dieser Server bei uns konfiguriert? */
+		for( i = 0; i < MAX_SERVERS; i++ ) if( strcasecmp( Req->argv[0], Conf_Server[i].name ) == 0 ) break;
+		if( i >= MAX_SERVERS )
+		{
+			/* Server ist nicht konfiguriert! */
+			Log( LOG_ERR, "Connection %d: Server \"%s\" not configured here!", Client_Conn( Client ), Req->argv[0] );
+			Conn_Close( Client_Conn( Client ), NULL, "Server not configured here", true);
+			return DISCONNECTED;
+		}
+		if( strcmp( Client_Password( Client ), Conf_Server[i].pwd_in ) != 0 )
+		{
+			/* Falsches Passwort */
+			Log( LOG_ERR, "Connection %d: Got bad password from server \"%s\"!", Client_Conn( Client ), Req->argv[0] );
+			Conn_Close( Client_Conn( Client ), NULL, "Bad password", true);
+			return DISCONNECTED;
+		}
+		
+		/* Ist ein Server mit dieser ID bereits registriert? */
+		if( ! Client_CheckID( Client, Req->argv[0] )) return DISCONNECTED;
+
+		/* Server-Strukturen fuellen ;-) */
+		Client_SetID( Client, Req->argv[0] );
+		Client_SetHops( Client, 1 );
+		Client_SetInfo( Client, Req->argv[Req->argc - 1] );
+
+		/* Meldet sich der Server bei uns an (d.h., bauen nicht wir
+		 * selber die Verbindung zu einem anderen Server auf)? */
+		con = Client_Conn( Client );
+		if( Client_Token( Client ) != TOKEN_OUTBOUND )
+		{
+			/* Eingehende Verbindung: Unseren SERVER- und PASS-Befehl senden */
+			ok = true;
+			if( ! IRC_WriteStrClient( Client, "PASS %s %s", Conf_Server[i].pwd_out, NGIRCd_ProtoID )) ok = false;
+			else ok = IRC_WriteStrClient( Client, "SERVER %s 1 :%s", Conf_ServerName, Conf_ServerInfo );
+			if( ! ok )
+			{
+				Conn_Close( con, "Unexpected server behavior!", NULL, false );
+				return DISCONNECTED;
+			}
+			Client_SetIntroducer( Client, Client );
+			Client_SetToken( Client, 1 );
+		}
+		else
+		{
+			/* Ausgehende verbindung, SERVER und PASS wurden von uns bereits
+			 * an die Gegenseite uerbermittelt */
+			Client_SetToken( Client, atoi( Req->argv[1] ));
+		}
+
+		Log( LOG_NOTICE|LOG_snotice, "Server \"%s\" registered (connection %d, 1 hop - direct link).", Client_ID( Client ), con );
+
+		Client_SetType( Client, CLIENT_SERVER );
+		Conf_SetServer( i, con );
+
+#ifdef ZLIB
+		/* Kompression initialisieren, wenn erforderlich */
+		if( strchr( Client_Flags( Client ), 'Z' ))
+		{
+			if( ! Zip_InitConn( con ))
+			{
+				/* Fehler! */
+				Conn_Close( con, "Can't inizialize compression (zlib)!", NULL, false );
+				return DISCONNECTED;
+			}
+		}
+#endif
+
+		/* maximalen Hop Count ermitteln */
+		max_hops = 0;
+		c = Client_First( );
+		while( c )
+		{
+			if( Client_Hops( c ) > max_hops ) max_hops = Client_Hops( c );
+			c = Client_Next( c );
+		}
+		
+		/* Alle bisherigen Server dem neuen Server bekannt machen,
+		 * die bisherigen Server ueber den neuen informierenn */
+		for( i = 0; i < ( max_hops + 1 ); i++ )
+		{
+			c = Client_First( );
+			while( c )
+			{
+				if(( Client_Type( c ) == CLIENT_SERVER ) && ( c != Client ) && ( c != Client_ThisServer( )) && ( Client_Hops( c ) == i ))
+				{
+					if( Client_Conn( c ) > NONE )
+					{
+						/* Dem gefundenen Server gleich den neuen
+						 * Server bekannt machen */
+						if( ! IRC_WriteStrClient( c, "SERVER %s %d %d :%s", Client_ID( Client ), Client_Hops( Client ) + 1, Client_MyToken( Client ), Client_Info( Client ))) return DISCONNECTED;
+					}
+					
+					/* Den neuen Server ueber den alten informieren */
+					if( ! IRC_WriteStrClientPrefix( Client, Client_Hops( c ) == 1 ? Client_ThisServer( ) : Client_Introducer( c ), "SERVER %s %d %d :%s", Client_ID( c ), Client_Hops( c ) + 1, Client_MyToken( c ), Client_Info( c ))) return DISCONNECTED;
+				}
+				c = Client_Next( c );
+			}
+		}
+
+		/* alle User dem neuen Server bekannt machen */
+		c = Client_First( );
+		while( c )
+		{
+			if( Client_Type( c ) == CLIENT_USER )
+			{
+				/* User an neuen Server melden */
+				if( ! IRC_WriteStrClient( Client, "NICK %s %d %s %s %d +%s :%s", Client_ID( c ), Client_Hops( c ) + 1, Client_User( c ), Client_Hostname( c ), Client_MyToken( Client_Introducer( c )), Client_Modes( c ), Client_Info( c ))) return DISCONNECTED;
+			}
+			c = Client_Next( c );
+		}
+
+		/* Channels dem neuen Server bekannt machen */
+		chan = Channel_First( );
+		while( chan )
+		{
+#ifdef IRCPLUS
+			/* Send CHANINFO if the peer supports it */
+			if( strchr( Client_Flags( Client ), 'C' ))
+			{
+#ifdef DEBUG
+				Log( LOG_DEBUG, "Sending CHANINFO commands ..." );
+#endif
+				modes = Channel_Modes( chan );
+				topic = Channel_Topic( chan );
+
+				if( *modes || *topic )
+				{
+					/* send CHANINFO */
+					if(( ! strchr( Channel_Modes( chan ), 'k' )) && ( ! strchr( Channel_Modes( chan ), 'l' )) && ( ! *topic ))
+					{
+						/* "CHANINFO <chan> +<modes>" */
+						if( ! IRC_WriteStrClient( Client, "CHANINFO %s +%s", Channel_Name( chan ), modes )) return DISCONNECTED;
+					}
+					else if(( ! strchr( Channel_Modes( chan ), 'k' )) && ( ! strchr( Channel_Modes( chan ), 'l' )))
+					{
+						/* "CHANINFO <chan> +<modes> :<topic>" */
+						if( ! IRC_WriteStrClient( Client, "CHANINFO %s +%s :%s", Channel_Name( chan ), modes, topic )) return DISCONNECTED;
+					}
+					else
+					{
+						/* "CHANINFO <chan> +<modes> <key> <limit> :<topic>" */
+						if( ! IRC_WriteStrClient( Client, "CHANINFO %s +%s %s %ld :%s", Channel_Name( chan ), modes, strchr( Channel_Modes( chan ), 'k' ) ? Channel_Key( chan ) : "*", strchr( Channel_Modes( chan ), 'l' ) ? Channel_MaxUsers( chan ) : 0L, topic )) return DISCONNECTED;
+					}
+				}
+			}
+#endif
+
+			/* alle Member suchen */
+			cl2chan = Channel_FirstMember( chan );
+			snprintf( str, sizeof( str ), "NJOIN %s :", Channel_Name( chan ));
+			while( cl2chan )
+			{
+				cl = Channel_GetClient( cl2chan );
+				assert( cl != NULL );
+
+				/* Nick, ggf. mit Modes, anhaengen */
+				if( str[strlen( str ) - 1] != ':' ) strlcat( str, ",", sizeof( str ));
+				if( strchr( Channel_UserModes( chan, cl ), 'v' )) strlcat( str, "+", sizeof( str ));
+				if( strchr( Channel_UserModes( chan, cl ), 'o' )) strlcat( str, "@", sizeof( str ));
+				strlcat( str, Client_ID( cl ), sizeof( str ));
+
+				if( strlen( str ) > ( LINE_LEN - CLIENT_NICK_LEN - 8 ))
+				{
+					/* Zeile senden */
+					if( ! IRC_WriteStrClient( Client, "%s", str )) return DISCONNECTED;
+					snprintf( str, sizeof( str ), "NJOIN %s :", Channel_Name( chan ));
+				}
+				
+				cl2chan = Channel_NextMember( chan, cl2chan );
+			}
+
+			/* noch Daten da? */
+			if( str[strlen( str ) - 1] != ':')
+			{
+				/* Ja; Also senden ... */
+				if( ! IRC_WriteStrClient( Client, "%s", str )) return DISCONNECTED;
+			}
+
+#ifdef IRCPLUS
+			if( strchr( Client_Flags( Client ), 'L' ))
+			{
+#ifdef DEBUG
+				Log( LOG_DEBUG, "Synchronizing INVITE- and BAN-lists ..." );
+#endif
+				/* Synchronize INVITE- and BAN-lists */
+				if( ! Lists_SendInvites( Client )) return DISCONNECTED;
+				if( ! Lists_SendBans( Client )) return DISCONNECTED;
+			}
+#endif
+
+			/* naechsten Channel suchen */
+			chan = Channel_Next( chan );
+		}
+		
+		return CONNECTED;
+	}
+	else if( Client_Type( Client ) == CLIENT_SERVER )
+	{
+		/* Neuer Server wird im Netz angekuendigt */
+
+		/* Falsche Anzahl Parameter? */
+		if( Req->argc != 4 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+
+		/* Ist ein Server mit dieser ID bereits registriert? */
+		if( ! Client_CheckID( Client, Req->argv[0] )) return DISCONNECTED;
+
+		/* Ueberfluessige Hostnamen aus Info-Text entfernen */
+		ptr = strchr( Req->argv[3] + 2, '[' );
+		if( ! ptr ) ptr = Req->argv[3];
+
+		from = Client_Search( Req->prefix );
+		if( ! from )
+		{
+			/* Hm, Server, der diesen einfuehrt, ist nicht bekannt!? */
+			Log( LOG_ALERT, "Unknown ID in prefix of SERVER: \"%s\"! (on connection %d)", Req->prefix, Client_Conn( Client ));
+			Conn_Close( Client_Conn( Client ), NULL, "Unknown ID in prefix of SERVER", true);
+			return DISCONNECTED;
+		}
+
+		/* Neue Client-Struktur anlegen */
+		c = Client_NewRemoteServer( Client, Req->argv[0], from, atoi( Req->argv[1] ), atoi( Req->argv[2] ), ptr, true);
+		if( ! c )
+		{
+			/* Neue Client-Struktur konnte nicht angelegt werden */
+			Log( LOG_ALERT, "Can't create client structure for server! (on connection %d)", Client_Conn( Client ));
+			Conn_Close( Client_Conn( Client ), NULL, "Can't allocate client structure for remote server", true);
+			return DISCONNECTED;
+		}
+
+		/* Log-Meldung zusammenbauen und ausgeben */
+		if(( Client_Hops( c ) > 1 ) && ( Req->prefix[0] )) snprintf( str, sizeof( str ), "connected to %s, ", Client_ID( from ));
+		else strcpy( str, "" );
+		Log( LOG_NOTICE|LOG_snotice, "Server \"%s\" registered (via %s, %s%d hop%s).", Client_ID( c ), Client_ID( Client ), str, Client_Hops( c ), Client_Hops( c ) > 1 ? "s": "" );
+
+		/* Andere Server informieren */
+		IRC_WriteStrServersPrefix( Client, from, "SERVER %s %d %d :%s", Client_ID( c ), Client_Hops( c ) + 1, Client_MyToken( c ), Client_Info( c ));
+
+		return CONNECTED;
+	}
+	else return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+} /* IRC_SERVER */
+
+
+GLOBAL bool
+IRC_NJOIN( CLIENT *Client, REQUEST *Req )
+{
+	char nick_in[COMMAND_LEN], nick_out[COMMAND_LEN], *channame, *ptr, modes[8];
+	bool is_op, is_voiced;
+	CHANNEL *chan;
+	CLIENT *c;
+	
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+	/* Falsche Anzahl Parameter? */
+	if( Req->argc != 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+
+	strlcpy( nick_in, Req->argv[1], sizeof( nick_in ));
+	strcpy( nick_out, "" );
+
+	channame = Req->argv[0];
+	ptr = strtok( nick_in, "," );
+	while( ptr )
+	{
+		is_op = is_voiced = false;
+		
+		/* Prefixe abschneiden */
+		while(( *ptr == '@' ) || ( *ptr == '+' ))
+		{
+			if( *ptr == '@' ) is_op = true;
+			if( *ptr == '+' ) is_voiced = true;
+			ptr++;
+		}
+
+		c = Client_Search( ptr );
+		if( c )
+		{
+			Channel_Join( c, channame );
+			chan = Channel_Search( channame );
+			assert( chan != NULL );
+			
+			if( is_op ) Channel_UserModeAdd( chan, c, 'o' );
+			if( is_voiced ) Channel_UserModeAdd( chan, c, 'v' );
+
+			/* im Channel bekannt machen */
+			IRC_WriteStrChannelPrefix( Client, chan, c, false, "JOIN :%s", channame );
+
+			/* Channel-User-Modes setzen */
+			strlcpy( modes, Channel_UserModes( chan, c ), sizeof( modes ));
+			if( modes[0] )
+			{
+				/* Modes im Channel bekannt machen */
+				IRC_WriteStrChannelPrefix( Client, chan, Client, false, "MODE %s +%s %s", channame, modes, Client_ID( c ));
+			}
+
+			if( nick_out[0] != '\0' ) strlcat( nick_out, ",", sizeof( nick_out ));
+			if( is_op ) strlcat( nick_out, "@", sizeof( nick_out ));
+			if( is_voiced ) strlcat( nick_out, "+", sizeof( nick_out ));
+			strlcat( nick_out, ptr, sizeof( nick_out ));
+		}
+		else Log( LOG_ERR, "Got NJOIN for unknown nick \"%s\" for channel \"%s\"!", ptr, channame );
+		
+		/* naechsten Nick suchen */
+		ptr = strtok( NULL, "," );
+	}
+
+	/* an andere Server weiterleiten */
+	if( nick_out[0] != '\0' ) IRC_WriteStrServersPrefix( Client, Client_ThisServer( ), "NJOIN %s :%s", Req->argv[0], nick_out );
+
+	return CONNECTED;
+} /* IRC_NJOIN */
+
+
+GLOBAL bool
+IRC_SQUIT( CLIENT *Client, REQUEST *Req )
+{
+	CLIENT *target;
+	char msg[LINE_LEN + 64];
+
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+	/* Falsche Anzahl Parameter? */
+	if( Req->argc != 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+
+	Log( LOG_DEBUG, "Got SQUIT from %s for \"%s\": \"%s\" ...", Client_ID( Client ), Req->argv[0], Req->argv[1] );
+
+	target = Client_Search( Req->argv[0] );
+	if( ! target )
+	{
+		/* Den Server kennen wir nicht (mehr), also nichts zu tun. */
+		Log( LOG_WARNING, "Got SQUIT from %s for unknown server \"%s\"!?", Client_ID( Client ), Req->argv[0] );
+		return CONNECTED;
+	}
+
+	if( Req->argv[1][0] )
+	{
+		if( strlen( Req->argv[1] ) > LINE_LEN ) Req->argv[1][LINE_LEN] = '\0';
+		snprintf( msg, sizeof( msg ), "%s (SQUIT from %s).", Req->argv[1], Client_ID( Client ));
+	}
+	else snprintf( msg, sizeof( msg ), "Got SQUIT from %s.", Client_ID( Client ));
+
+	if( Client_Conn( target ) > NONE )
+	{
+		/* dieser Server hat die Connection */
+		if( Req->argv[1][0] ) Conn_Close( Client_Conn( target ), msg, Req->argv[1], true);
+		else Conn_Close( Client_Conn( target ), msg, NULL, true);
+		return DISCONNECTED;
+	}
+	else
+	{
+		/* Verbindung hielt anderer Server */
+		Client_Destroy( target, msg, Req->argv[1], false );
+		return CONNECTED;
+	}
+} /* IRC_SQUIT */
+
+
+/* -eof- */

+ 29 - 0
src/ngircd/irc-server.h

@@ -0,0 +1,29 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * $Id: irc-server.h,v 1.5 2005/03/19 18:43:49 fw Exp $
+ *
+ * IRC commands for server links (header)
+ */
+
+
+#ifndef __irc_server_h__
+#define __irc_server_h__
+
+
+GLOBAL bool IRC_SERVER PARAMS((CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_NJOIN PARAMS((CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_SQUIT PARAMS((CLIENT *Client, REQUEST *Req ));
+
+
+#endif
+
+
+/* -eof- */

+ 428 - 0
src/ngircd/irc-write.c

@@ -0,0 +1,428 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001-2005 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * Sending IRC commands over the network
+ */
+
+
+#include "portab.h"
+
+static char UNUSED id[] = "$Id: irc-write.c,v 1.18 2005/04/27 07:39:18 alex Exp $";
+
+#include "imp.h"
+#include <assert.h>
+#ifdef PROTOTYPES
+#	include <stdarg.h>
+#else
+#	include <varargs.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+
+#include "defines.h"
+#include "conn-func.h"
+#include "client.h"
+#include "channel.h"
+
+#include "exp.h"
+#include "irc-write.h"
+
+
+#define SEND_TO_USER 1
+#define SEND_TO_SERVER 2
+
+
+LOCAL char *Get_Prefix PARAMS(( CLIENT *Target, CLIENT *Client ));
+
+
+#ifdef PROTOTYPES
+GLOBAL bool
+IRC_WriteStrClient( CLIENT *Client, char *Format, ... )
+#else
+GLOBAL bool
+IRC_WriteStrClient( Client, Format, va_alist )
+CLIENT *Client;
+char *Format;
+va_dcl
+#endif
+{
+	char buffer[1000];
+	bool ok = CONNECTED;
+	va_list ap;
+
+	assert( Client != NULL );
+	assert( Format != NULL );
+
+#ifdef PROTOTYPES
+	va_start( ap, Format );
+#else
+	va_start( ap );
+#endif
+	vsnprintf( buffer, 1000, Format, ap );
+	va_end( ap );
+
+	/* an den Client selber */
+	ok = IRC_WriteStrClientPrefix( Client, Client_ThisServer( ), "%s", buffer );
+
+	return ok;
+} /* IRC_WriteStrClient */
+
+
+#ifdef PROTOTYPES
+GLOBAL bool
+IRC_WriteStrClientPrefix( CLIENT *Client, CLIENT *Prefix, char *Format, ... )
+#else
+GLOBAL bool
+IRC_WriteStrClientPrefix( Client, Prefix, Format, va_alist )
+CLIENT *Client;
+CLIENT *Prefix;
+char *Format;
+va_dcl
+#endif
+{
+	/* Text an Clients, lokal bzw. remote, senden. */
+
+	char buffer[1000];
+	va_list ap;
+
+	assert( Client != NULL );
+	assert( Format != NULL );
+	assert( Prefix != NULL );
+
+#ifdef PROTOTYPES
+	va_start( ap, Format );
+#else
+	va_start( ap );
+#endif
+	vsnprintf( buffer, 1000, Format, ap );
+	va_end( ap );
+
+	return Conn_WriteStr( Client_Conn( Client_NextHop( Client )), ":%s %s", Get_Prefix( Client_NextHop( Client ), Prefix ), buffer );
+} /* IRC_WriteStrClientPrefix */
+
+
+#ifdef PROTOTYPES
+GLOBAL bool
+IRC_WriteStrChannel( CLIENT *Client, CHANNEL *Chan, bool Remote, char *Format, ... )
+#else
+GLOBAL bool
+IRC_WriteStrChannel( Client, Chan, Remote, Format, va_alist )
+CLIENT *Client;
+CHANNEL *Chan;
+bool Remote;
+char *Format;
+va_dcl
+#endif
+{
+	char buffer[1000];
+	va_list ap;
+
+	assert( Client != NULL );
+	assert( Format != NULL );
+
+#ifdef PROTOTYPES
+	va_start( ap, Format );
+#else
+	va_start( ap );
+#endif
+	vsnprintf( buffer, 1000, Format, ap );
+	va_end( ap );
+
+	return IRC_WriteStrChannelPrefix( Client, Chan, Client_ThisServer( ), Remote, "%s", buffer );
+} /* IRC_WriteStrChannel */
+
+
+#ifdef PROTOTYPES
+GLOBAL bool
+IRC_WriteStrChannelPrefix( CLIENT *Client, CHANNEL *Chan, CLIENT *Prefix, bool Remote, char *Format, ... )
+#else
+GLOBAL bool
+IRC_WriteStrChannelPrefix( Client, Chan, Prefix, Remote, Format, va_alist )
+CLIENT *Client;
+CHANNEL *Chan;
+CLIENT *Prefix;
+bool Remote;
+char *Format;
+va_dcl
+#endif
+{
+	bool ok = CONNECTED;
+	char buffer[1000];
+	CL2CHAN *cl2chan;
+	CONN_ID conn;
+	CLIENT *c;
+	va_list ap;
+
+	assert( Client != NULL );
+	assert( Chan != NULL );
+	assert( Prefix != NULL );
+	assert( Format != NULL );
+
+#ifdef PROTOTYPES
+	va_start( ap, Format );
+#else
+	va_start( ap  );
+#endif
+	vsnprintf( buffer, 1000, Format, ap );
+	va_end( ap );
+
+	Conn_ClearFlags( );
+
+	/* An alle Clients, die in den selben Channels sind.
+	 * Dabei aber nur einmal je Remote-Server */
+	cl2chan = Channel_FirstMember( Chan );
+	while( cl2chan )
+	{
+		c = Channel_GetClient( cl2chan );
+		if( ! Remote )
+		{
+			if( Client_Conn( c ) <= NONE ) c = NULL;
+			else if( Client_Type( c ) == CLIENT_SERVER ) c = NULL;
+		}
+		if( c ) c = Client_NextHop( c );
+			
+		if( c && ( c != Client ))
+		{
+			/* Ok, anderer Client */
+			conn = Client_Conn( c );
+			if( Client_Type( c ) == CLIENT_SERVER )	Conn_SetFlag( conn, SEND_TO_SERVER );
+			else Conn_SetFlag( conn, SEND_TO_USER );
+		}
+		cl2chan = Channel_NextMember( Chan, cl2chan );
+	}
+
+	/* Senden: alle Verbindungen durchgehen ... */
+	conn = Conn_First( );
+	while( conn != NONE )
+	{
+		/* muessen Daten ueber diese Verbindung verschickt werden? */
+		if( Conn_Flag( conn ) == SEND_TO_SERVER) ok = Conn_WriteStr( conn, ":%s %s", Client_ID( Prefix ), buffer );
+		else if( Conn_Flag( conn ) == SEND_TO_USER ) ok = Conn_WriteStr( conn, ":%s %s", Client_Mask( Prefix ), buffer );
+		if( ! ok ) break;
+
+		/* naechste Verbindung testen */
+		conn = Conn_Next( conn );
+	}
+
+	return ok;
+} /* IRC_WriteStrChannelPrefix */
+
+
+#ifdef PROTOTYPES
+GLOBAL void
+IRC_WriteStrServers( CLIENT *ExceptOf, char *Format, ... )
+#else
+GLOBAL void
+IRC_WriteStrServers( ExceptOf, Format, va_alist )
+CLIENT *ExceptOf;
+char *Format;
+va_dcl
+#endif
+{
+	char buffer[1000];
+	va_list ap;
+
+	assert( Format != NULL );
+
+#ifdef PROTOTYPES
+	va_start( ap, Format );
+#else
+	va_start( ap );
+#endif
+	vsnprintf( buffer, 1000, Format, ap );
+	va_end( ap );
+
+	/* an den Client selber */
+	IRC_WriteStrServersPrefix( ExceptOf, Client_ThisServer( ), "%s", buffer );
+} /* IRC_WriteStrServers */
+
+
+#ifdef PROTOTYPES
+GLOBAL void
+IRC_WriteStrServersPrefix( CLIENT *ExceptOf, CLIENT *Prefix, char *Format, ... )
+#else
+GLOBAL void
+IRC_WriteStrServersPrefix( ExceptOf, Prefix, Format, va_alist )
+CLIENT *ExceptOf;
+CLIENT *Prefix;
+char *Format;
+va_dcl
+#endif
+{
+	char buffer[1000];
+	va_list ap;
+
+	assert( Format != NULL );
+	assert( Prefix != NULL );
+
+#ifdef PROTOTYPES
+	va_start( ap, Format );
+#else
+	va_start( ap );
+#endif
+	vsnprintf( buffer, 1000, Format, ap );
+	va_end( ap );
+
+	IRC_WriteStrServersPrefixFlag( ExceptOf, Prefix, '\0', "%s", buffer );
+} /* IRC_WriteStrServersPrefix */
+	
+
+#ifdef PROTOTYPES
+GLOBAL void
+IRC_WriteStrServersPrefixFlag( CLIENT *ExceptOf, CLIENT *Prefix, char Flag, char *Format, ... )
+#else
+GLOBAL void
+IRC_WriteStrServersPrefixFlag( ExceptOf, Prefix, Flag, Format, va_alist )
+CLIENT *ExceptOf;
+CLIENT *Prefix;
+char Flag;
+char *Format;
+va_dcl
+#endif
+{
+	char buffer[1000];
+	CLIENT *c;
+	va_list ap;
+	
+	assert( Format != NULL );
+	assert( Prefix != NULL );
+
+#ifdef PROTOTYPES
+	va_start( ap, Format );
+#else
+	va_start( ap );
+#endif
+	vsnprintf( buffer, 1000, Format, ap );
+	va_end( ap );
+	
+	c = Client_First( );
+	while( c )
+	{
+		if(( Client_Type( c ) == CLIENT_SERVER ) && ( Client_Conn( c ) > NONE ) && ( c != Client_ThisServer( )) && ( c != ExceptOf ))
+		{
+			/* Ziel-Server gefunden. Nun noch pruefen, ob Flags stimmen */
+			if(( Flag == '\0' ) || ( strchr( Client_Flags( c ), Flag ) != NULL )) IRC_WriteStrClientPrefix( c, Prefix, "%s", buffer );
+		}
+		c = Client_Next( c );
+	}
+} /* IRC_WriteStrServersPrefixFlag */
+
+
+#ifdef PROTOTYPES
+GLOBAL bool
+IRC_WriteStrRelatedPrefix( CLIENT *Client, CLIENT *Prefix, bool Remote, char *Format, ... )
+#else
+GLOBAL bool
+IRC_WriteStrRelatedPrefix( Client, Prefix, Remote, Format, va_alist )
+CLIENT *Client;
+CLIENT *Prefix;
+bool Remote;
+char *Format;
+va_dcl
+#endif
+{
+	bool ok = CONNECTED;
+	CL2CHAN *chan_cl2chan, *cl2chan;
+	char buffer[1000];
+	CHANNEL *chan;
+	CONN_ID conn;
+	va_list ap;
+	CLIENT *c;
+
+	assert( Client != NULL );
+	assert( Prefix != NULL );
+	assert( Format != NULL );
+
+#ifdef PROTOTYPES
+	va_start( ap, Format );
+#else
+	va_start( ap );
+#endif
+	vsnprintf( buffer, 1000, Format, ap );
+	va_end( ap );
+
+	/* initialisieren */
+	Conn_ClearFlags( );
+
+	/* An alle Clients, die in einem Channel mit dem "Ausloeser" sind,
+	 * den Text schicken. An Remote-Server aber jeweils nur einmal. */
+	chan_cl2chan = Channel_FirstChannelOf( Client );
+	while( chan_cl2chan )
+	{
+		/* Channel des Users durchsuchen */
+		chan = Channel_GetChannel( chan_cl2chan );
+		cl2chan = Channel_FirstMember( chan );
+		while( cl2chan )
+		{
+			c = Channel_GetClient( cl2chan );
+			if( ! Remote )
+			{
+				if( Client_Conn( c ) <= NONE ) c = NULL;
+				else if( Client_Type( c ) == CLIENT_SERVER ) c = NULL;
+			}
+			if( c ) c = Client_NextHop( c );
+
+			if( c && ( c != Client ))
+			{
+				/* Ok, anderer Client */
+				conn = Client_Conn( c );
+				if( Client_Type( c ) == CLIENT_SERVER ) Conn_SetFlag( conn, SEND_TO_SERVER );
+				else Conn_SetFlag( conn, SEND_TO_USER );
+			}
+			cl2chan = Channel_NextMember( chan, cl2chan );
+		}
+		
+		/* naechsten Channel */
+		chan_cl2chan = Channel_NextChannelOf( Client, chan_cl2chan );
+	}
+
+	/* Senden: alle Verbindungen durchgehen ... */
+	conn = Conn_First( );
+	while( conn != NONE )
+	{
+		/* muessen ueber diese Verbindung Daten gesendet werden? */
+		if( Conn_Flag( conn ) == SEND_TO_SERVER ) ok = Conn_WriteStr( conn, ":%s %s", Client_ID( Prefix ), buffer );
+		else if( Conn_Flag( conn ) == SEND_TO_USER ) ok = Conn_WriteStr( conn, ":%s %s", Client_Mask( Prefix ), buffer );
+		if( ! ok ) break;
+
+		/* naechste Verbindung testen */
+		conn = Conn_Next( conn );
+	}
+	return ok;
+} /* IRC_WriteStrRelatedPrefix */
+
+
+GLOBAL void
+IRC_SetPenalty( CLIENT *Client, int Seconds )
+{
+	CONN_ID c;
+	
+	assert( Client != NULL );
+	assert( Seconds > 0 );
+	
+	if( Client_Type( Client ) == CLIENT_SERVER ) return;
+	
+	c = Client_Conn( Client );
+	if( c > NONE ) Conn_SetPenalty( c, Seconds );		
+} /* IRC_SetPenalty */
+
+
+LOCAL char *
+Get_Prefix( CLIENT *Target, CLIENT *Client )
+{
+	assert( Target != NULL );
+	assert( Client != NULL );
+
+	if( Client_Type( Target ) == CLIENT_SERVER ) return Client_ID( Client );
+	else return Client_Mask( Client );
+} /* Get_Prefix */
+
+
+/* -eof- */

+ 39 - 0
src/ngircd/irc-write.h

@@ -0,0 +1,39 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * $Id: irc-write.h,v 1.7 2005/03/19 18:43:49 fw Exp $
+ *
+ * Sending IRC commands over the network (header)
+ */
+
+
+#ifndef __irc_write_h__
+#define __irc_write_h__
+
+
+GLOBAL bool IRC_WriteStrClient PARAMS(( CLIENT *Client, char *Format, ... ));
+GLOBAL bool IRC_WriteStrClientPrefix PARAMS(( CLIENT *Client, CLIENT *Prefix, char *Format, ... ));
+
+GLOBAL bool IRC_WriteStrChannel PARAMS(( CLIENT *Client, CHANNEL *Chan, bool Remote, char *Format, ... ));
+GLOBAL bool IRC_WriteStrChannelPrefix PARAMS(( CLIENT *Client, CHANNEL *Chan, CLIENT *Prefix, bool Remote, char *Format, ... ));
+
+GLOBAL void IRC_WriteStrServers PARAMS(( CLIENT *ExceptOf, char *Format, ... ));
+GLOBAL void IRC_WriteStrServersPrefix PARAMS(( CLIENT *ExceptOf, CLIENT *Prefix, char *Format, ... ));
+GLOBAL void IRC_WriteStrServersPrefixFlag PARAMS(( CLIENT *ExceptOf, CLIENT *Prefix, char Flag, char *Format, ... ));
+
+GLOBAL bool IRC_WriteStrRelatedPrefix PARAMS(( CLIENT *Client, CLIENT *Prefix, bool Remote, char *Format, ... ));
+
+GLOBAL void IRC_SetPenalty PARAMS(( CLIENT *Client, int Seconds ));
+
+
+#endif
+
+
+/* -eof- */

+ 345 - 0
src/ngircd/irc.c

@@ -0,0 +1,345 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001-2004 Alexander Barton <alex@barton.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * IRC commands
+ */
+
+
+#include "portab.h"
+
+static char UNUSED id[] = "$Id: irc.c,v 1.126.2.1 2005/08/02 23:08:27 alex Exp $";
+
+#include "imp.h"
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "ngircd.h"
+#include "conn.h"
+#include "resolve.h"
+#include "conf.h"
+#include "conn-func.h"
+#include "client.h"
+#include "channel.h"
+#include "defines.h"
+#include "irc-write.h"
+#include "log.h"
+#include "messages.h"
+#include "parse.h"
+
+#include "exp.h"
+#include "irc.h"
+
+
+LOCAL char *Option_String PARAMS(( CONN_ID Idx ));
+
+
+GLOBAL bool
+IRC_ERROR( CLIENT *Client, REQUEST *Req )
+{
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+	if( Req->argc < 1 ) Log( LOG_NOTICE, "Got ERROR from \"%s\"!", Client_Mask( Client ));
+	else Log( LOG_NOTICE, "Got ERROR from \"%s\": %s!", Client_Mask( Client ), Req->argv[0] );
+
+	return CONNECTED;
+} /* IRC_ERROR */
+
+
+/**
+ * Kill client on request.
+ * This function implements the IRC command "KILL" wich is used to selectively
+ * disconnect clients. It can be used by IRC operators and servers, for example
+ * to "solve" nick collisions after netsplits.
+ * Please note that this function is also called internally, without a real
+ * KILL command beeing received over the network! Client is Client_ThisServer()
+ * in this case. */
+GLOBAL bool
+IRC_KILL( CLIENT *Client, REQUEST *Req )
+{
+	CLIENT *prefix, *c;
+	char reason[COMMAND_LEN], *msg;
+	CONN_ID my_conn, conn;
+
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+	if(( Client_Type( Client ) != CLIENT_SERVER ) &&
+	   ( ! Client_OperByMe( Client )))
+	{
+		/* The originator of the KILL is neither an IRC operator of
+		 * this server nor a server. */
+		return IRC_WriteStrClient( Client, ERR_NOPRIVILEGES_MSG,
+					   Client_ID( Client ));
+	}
+
+	if( Req->argc != 2 )
+	{
+		/* This command requires exactly 2 parameters! */
+		return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG,
+					   Client_ID( Client ), Req->command );
+	}
+
+	if( Req->prefix ) prefix = Client_Search( Req->prefix );
+	else prefix = Client;
+	if( ! prefix )
+	{
+		Log( LOG_WARNING, "Got KILL with invalid prefix: \"%s\"!",
+		     Req->prefix );
+		prefix = Client_ThisServer( );
+	}
+
+	if( Client != Client_ThisServer( ))
+	{
+		/* This is a "real" KILL received from the network. */
+		Log( LOG_NOTICE|LOG_snotice, "Got KILL command from \"%s\" for \"%s\": %s",
+		     Client_Mask( prefix ), Req->argv[0], Req->argv[1] );
+	}
+
+	/* Build reason string */
+	if( Client_Type( Client ) == CLIENT_USER )
+	{
+		/* Prefix the "reason" if the originator is a regular user,
+		 * so users can't spoof KILLs of servers. */
+		snprintf( reason, sizeof( reason ), "KILLed by %s: %s",
+			  Client_ID( Client ), Req->argv[1] );
+	}
+	else
+		strlcpy( reason, Req->argv[1], sizeof( reason ));
+
+	/* Inform other servers */
+	IRC_WriteStrServersPrefix( Client, prefix, "KILL %s :%s",
+				   Req->argv[0], reason );
+
+	/* Save ID of this connection */
+	my_conn = Client_Conn( Client );
+
+	/* Do we host such a client? */
+	c = Client_Search( Req->argv[0] );
+	if( c )
+	{
+		if(( Client_Type( c ) != CLIENT_USER ) &&
+		   ( Client_Type( c ) != CLIENT_GOTNICK ))
+		{
+			/* Target of this KILL is not a regular user, this is
+			 * invalid! So we ignore this case if we received a
+			 * regular KILL from the network and try to kill the
+			 * client/connection anyway (but log an error!) if the
+			 * origin is the local server. */
+
+			if( Client != Client_ThisServer( ))
+			{
+				/* Invalid KILL received from remote */
+				if( Client_Type( c ) == CLIENT_SERVER )
+					msg = ERR_CANTKILLSERVER_MSG;
+				else
+					msg = ERR_NOPRIVILEGES_MSG;
+				return IRC_WriteStrClient( Client, msg,
+					Client_ID( Client ));
+			}
+
+			Log( LOG_ERR, "Got KILL for invalid client type: %d, \"%s\"!",
+			     Client_Type( c ), Req->argv[0] );
+		}
+
+		/* Kill client NOW! */
+		conn = Client_Conn( c );
+		Client_Destroy( c, NULL, reason, false );
+		if( conn > NONE )
+			Conn_Close( conn, NULL, reason, true );
+	}
+	else
+		Log( LOG_NOTICE, "Client with nick \"%s\" is unknown here.", Req->argv[0] );
+
+	/* Are we still connected or were we killed, too? */
+	if(( my_conn > NONE ) && ( Client_GetFromConn( my_conn )))
+		return CONNECTED;
+	else
+		return DISCONNECTED;
+} /* IRC_KILL */
+
+
+GLOBAL bool
+IRC_NOTICE( CLIENT *Client, REQUEST *Req )
+{
+	CLIENT *to, *from;
+
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+	if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return CONNECTED;
+
+	/* Falsche Anzahl Parameter? */
+	if( Req->argc != 2 ) return CONNECTED;
+
+	if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
+	else from = Client;
+	if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
+
+	to = Client_Search( Req->argv[0] );
+	if(( to ) && ( Client_Type( to ) == CLIENT_USER ))
+	{
+		/* Okay, Ziel ist ein User */
+		return IRC_WriteStrClientPrefix( to, from, "NOTICE %s :%s", Client_ID( to ), Req->argv[1] );
+	}
+	else return CONNECTED;
+} /* IRC_NOTICE */
+
+
+GLOBAL bool
+IRC_PRIVMSG( CLIENT *Client, REQUEST *Req )
+{
+	CLIENT *cl, *from;
+	CHANNEL *chan;
+	
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+	/* Falsche Anzahl Parameter? */
+	if( Req->argc == 0 ) return IRC_WriteStrClient( Client, ERR_NORECIPIENT_MSG, Client_ID( Client ), Req->command );
+	if( Req->argc == 1 ) return IRC_WriteStrClient( Client, ERR_NOTEXTTOSEND_MSG, Client_ID( Client ));
+	if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+
+	if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
+	else from = Client;
+	if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
+
+	cl = Client_Search( Req->argv[0] );
+	if( cl )
+	{
+		/* Okay, Ziel ist ein Client. Aber ist es auch ein User? */
+		if( Client_Type( cl ) != CLIENT_USER ) return IRC_WriteStrClient( from, ERR_NOSUCHNICK_MSG, Client_ID( from ), Req->argv[0] );
+
+		/* Okay, Ziel ist ein User */
+		if(( Client_Type( Client ) != CLIENT_SERVER ) && ( strchr( Client_Modes( cl ), 'a' )))
+		{
+			/* Ziel-User ist AWAY: Meldung verschicken */
+			if( ! IRC_WriteStrClient( from, RPL_AWAY_MSG, Client_ID( from ), Client_ID( cl ), Client_Away( cl ))) return DISCONNECTED;
+		}
+
+		/* Text senden */
+		if( Client_Conn( from ) > NONE ) Conn_UpdateIdle( Client_Conn( from ));
+		return IRC_WriteStrClientPrefix( cl, from, "PRIVMSG %s :%s", Client_ID( cl ), Req->argv[1] );
+	}
+
+	chan = Channel_Search( Req->argv[0] );
+	if( chan ) return Channel_Write( chan, from, Client, Req->argv[1] );
+
+	return IRC_WriteStrClient( from, ERR_NOSUCHNICK_MSG, Client_ID( from ), Req->argv[0] );
+} /* IRC_PRIVMSG */
+
+
+GLOBAL bool
+IRC_TRACE( CLIENT *Client, REQUEST *Req )
+{
+	CLIENT *from, *target, *c;
+	CONN_ID idx, idx2;
+	char user[CLIENT_USER_LEN];
+
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+	/* Bad number of arguments? */
+	if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NORECIPIENT_MSG, Client_ID( Client ), Req->command );
+
+	/* Search sender */
+	if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
+	else from = Client;
+	if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
+
+	/* Search target */
+	if( Req->argc == 1 ) target = Client_Search( Req->argv[0] );
+	else target = Client_ThisServer( );
+	
+	/* Forward command to other server? */
+	if( target != Client_ThisServer( ))
+	{
+		if(( ! target ) || ( Client_Type( target ) != CLIENT_SERVER )) return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG, Client_ID( from ), Req->argv[0] );
+
+		/* Send RPL_TRACELINK back to initiator */
+		idx = Client_Conn( Client ); assert( idx > NONE );
+		idx2 = Client_Conn( Client_NextHop( target )); assert( idx2 > NONE );
+		if( ! IRC_WriteStrClient( from, RPL_TRACELINK_MSG, Client_ID( from ), PACKAGE_NAME, PACKAGE_VERSION, Client_ID( target ), Client_ID( Client_NextHop( target )), Option_String( idx2 ), time( NULL ) - Conn_StartTime( idx2 ), Conn_SendQ( idx ), Conn_SendQ( idx2 ))) return DISCONNECTED;
+
+		/* Forward command */
+		IRC_WriteStrClientPrefix( target, from, "TRACE %s", Req->argv[0] );
+		return CONNECTED;
+	}
+
+	/* Infos about all connected servers */
+	c = Client_First( );
+	while( c )
+	{
+		if( Client_Conn( c ) > NONE )
+		{
+			/* Local client */
+			if( Client_Type( c ) == CLIENT_SERVER )
+			{
+				/* Server link */
+				strlcpy( user, Client_User( c ), sizeof( user ));
+				if( user[0] == '~' ) strlcpy( user, "unknown", sizeof( user ));
+				if( ! IRC_WriteStrClient( from, RPL_TRACESERVER_MSG, Client_ID( from ), Client_ID( c ), user, Client_Hostname( c ), Client_Mask( Client_ThisServer( )), Option_String( Client_Conn( c )))) return DISCONNECTED;
+			}
+			if(( Client_Type( c ) == CLIENT_USER ) && ( strchr( Client_Modes( c ), 'o' )))
+			{
+				/* IRC Operator */
+				if( ! IRC_WriteStrClient( from, RPL_TRACEOPERATOR_MSG, Client_ID( from ), Client_ID( c ))) return DISCONNECTED;
+			}
+		}
+		c = Client_Next( c );
+	}
+
+	IRC_SetPenalty( Client, 3 );
+	return IRC_WriteStrClient( from, RPL_TRACEEND_MSG, Client_ID( from ), Conf_ServerName, PACKAGE_NAME, PACKAGE_VERSION, NGIRCd_DebugLevel );
+} /* IRC_TRACE */
+
+
+GLOBAL bool
+IRC_HELP( CLIENT *Client, REQUEST *Req )
+{
+	COMMAND *cmd;
+
+	assert( Client != NULL );
+	assert( Req != NULL );
+
+	/* Bad number of arguments? */
+	if( Req->argc > 0 ) return IRC_WriteStrClient( Client, ERR_NORECIPIENT_MSG, Client_ID( Client ), Req->command );
+
+	cmd = Parse_GetCommandStruct( );
+	while( cmd->name )
+	{
+		if( ! IRC_WriteStrClient( Client, "NOTICE %s :%s", Client_ID( Client ), cmd->name )) return DISCONNECTED;
+		cmd++;
+	}
+	
+	IRC_SetPenalty( Client, 2 );
+	return CONNECTED;
+} /* IRC_HELP */
+
+
+LOCAL char *
+Option_String( CONN_ID Idx )
+{
+	static char option_txt[8];
+	int options;
+
+	options = Conn_Options( Idx );
+
+	strcpy( option_txt, "F" );	/* No idea what this means but the original ircd sends it ... */
+#ifdef ZLIB
+	if( options & CONN_ZIP ) strcat( option_txt, "z" );
+#endif
+
+	return option_txt;
+} /* Option_String */
+
+
+/* -eof- */

+ 32 - 0
src/ngircd/irc.h

@@ -0,0 +1,32 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * $Id: irc.h,v 1.39 2005/03/19 18:43:49 fw Exp $
+ *
+ * IRC commands (header)
+ */
+
+
+#ifndef __irc_h__
+#define __irc_h__
+
+
+GLOBAL bool IRC_ERROR PARAMS(( CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_KILL PARAMS(( CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_NOTICE PARAMS(( CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_PRIVMSG PARAMS(( CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_TRACE PARAMS(( CLIENT *Client, REQUEST *Req ));
+GLOBAL bool IRC_HELP PARAMS(( CLIENT *Client, REQUEST *Req ));
+
+
+#endif
+
+
+/* -eof- */

+ 488 - 0
src/ngircd/lists.c

@@ -0,0 +1,488 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001-2005 Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * Management of IRC lists: ban, invite, ...
+ */
+
+
+#include "portab.h"
+
+static char UNUSED id[] = "$Id: lists.c,v 1.17 2005/03/19 18:43:49 fw Exp $";
+
+#include "imp.h"
+#include <assert.h>
+
+#include "defines.h"
+#include "conn.h"
+#include "client.h"
+#include "channel.h"
+#include "log.h"
+#include "match.h"
+#include "messages.h"
+#include "irc-write.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+
+#include "exp.h"
+#include "lists.h"
+
+
+#define MASK_LEN 2*CLIENT_HOST_LEN
+
+
+typedef struct _C2C
+{
+	struct _C2C *next;
+	char mask[MASK_LEN];
+	CHANNEL *channel;
+	bool onlyonce;
+} C2C;
+
+
+LOCAL C2C *My_Invites, *My_Bans;
+
+
+LOCAL C2C *New_C2C PARAMS(( char *Mask, CHANNEL *Chan, bool OnlyOnce ));
+
+LOCAL bool Check_List PARAMS(( C2C **Cl2Chan, CLIENT *Client, CHANNEL *Chan ));
+LOCAL bool Already_Registered PARAMS(( C2C *Cl2Chan, char *Mask, CHANNEL *Chan ));
+
+
+
+GLOBAL void
+Lists_Init( void )
+{
+	/* Modul initialisieren */
+
+	My_Invites = My_Bans = NULL;
+} /* Lists_Init */
+
+
+GLOBAL void
+Lists_Exit( void )
+{
+	/* Modul abmelden */
+
+	C2C *c2c, *next;
+
+	/* Invite-Lists freigeben */
+	c2c = My_Invites;
+	while( c2c )
+	{
+		next = c2c->next;
+		free( c2c );
+		c2c = next;
+	}
+
+	/* Ban-Lists freigeben */
+	c2c = My_Bans;
+	while( c2c )
+	{
+		next = c2c->next;
+		free( c2c );
+		c2c = next;
+	}
+} /* Lists_Exit */
+
+
+GLOBAL bool
+Lists_CheckInvited( CLIENT *Client, CHANNEL *Chan )
+{
+	return Check_List( &My_Invites, Client, Chan );
+} /* Lists_CheckInvited */
+
+
+GLOBAL bool
+Lists_IsInviteEntry( char *Mask, CHANNEL *Chan )
+{
+	assert( Mask != NULL );
+	assert( Chan != NULL );
+	
+	return Already_Registered( My_Invites, Mask, Chan );
+} /* Lists_IsInviteEntry */
+
+
+GLOBAL bool
+Lists_AddInvited( char *Mask, CHANNEL *Chan, bool OnlyOnce )
+{
+	C2C *c2c;
+
+	assert( Mask != NULL );
+	assert( Chan != NULL );
+
+	if( Already_Registered( My_Invites, Mask, Chan )) return true;
+	
+	c2c = New_C2C( Mask, Chan, OnlyOnce );
+	if( ! c2c )
+	{
+		Log( LOG_ERR, "Can't add new invite list entry!" );
+		return false;
+	}
+
+	/* verketten */
+	c2c->next = My_Invites;
+	My_Invites = c2c;
+
+	Log( LOG_DEBUG, "Added \"%s\" to invite list for \"%s\".", Mask, Channel_Name( Chan ));
+	return true;
+} /* Lists_AddInvited */
+
+
+GLOBAL void
+Lists_DelInvited( char *Mask, CHANNEL *Chan )
+{
+	C2C *c2c, *last, *next;
+
+	assert( Mask != NULL );
+	assert( Chan != NULL );
+
+	last = NULL;
+	c2c = My_Invites;
+	while( c2c )
+	{
+		next = c2c->next;
+		if(( c2c->channel == Chan ) && ( strcasecmp( c2c->mask, Mask ) == 0 ))
+		{
+			/* dieser Eintrag muss geloescht werden */
+			Log( LOG_DEBUG, "Deleted \"%s\" from invite list for \"%s\"." , c2c->mask, Channel_Name( Chan ));
+			if( last ) last->next = next;
+			else My_Invites = next;
+			free( c2c );
+		}
+		else last = c2c;
+		c2c = next;
+	}
+} /* Lists_DelInvited */
+
+
+GLOBAL bool
+Lists_ShowInvites( CLIENT *Client, CHANNEL *Channel )
+{
+	C2C *c2c;
+
+	assert( Client != NULL );
+	assert( Channel != NULL );
+
+	c2c = My_Invites;
+	while( c2c )
+	{
+		if( c2c->channel == Channel )
+		{
+			/* Eintrag fuer Channel gefunden; ausgeben: */
+			if( ! IRC_WriteStrClient( Client, RPL_INVITELIST_MSG, Client_ID( Client ), Channel_Name( Channel ), c2c->mask )) return DISCONNECTED;
+		}
+		c2c = c2c->next;
+	}
+	return IRC_WriteStrClient( Client, RPL_ENDOFINVITELIST_MSG, Client_ID( Client ), Channel_Name( Channel ));
+} /* Lists_ShowInvites */
+
+
+GLOBAL bool
+Lists_SendInvites( CLIENT *Client )
+{
+	C2C *c2c;
+	
+	assert( Client != NULL );
+	
+	c2c = My_Invites;
+	while( c2c )
+	{
+		if( ! IRC_WriteStrClient( Client, "MODE %s +I %s", Channel_Name( c2c->channel ), c2c->mask )) return DISCONNECTED;
+		c2c = c2c->next;
+	}
+	return CONNECTED;
+} /* Lists_SendInvites */
+
+
+GLOBAL bool
+Lists_SendBans( CLIENT *Client )
+{
+	C2C *c2c;
+	
+	assert( Client != NULL );
+	
+	c2c = My_Bans;
+	while( c2c )
+	{
+		if( ! IRC_WriteStrClient( Client, "MODE %s +b %s", Channel_Name( c2c->channel ), c2c->mask )) return DISCONNECTED;
+		c2c = c2c->next;
+	}
+	return CONNECTED;
+} /* Lists_SendBans */
+
+
+GLOBAL bool
+Lists_CheckBanned( CLIENT *Client, CHANNEL *Chan )
+{
+	return Check_List( &My_Bans, Client, Chan );
+} /* Lists_CheckBanned */
+
+
+GLOBAL bool
+Lists_IsBanEntry( char *Mask, CHANNEL *Chan )
+{
+	assert( Mask != NULL );
+	assert( Chan != NULL );
+	
+	return Already_Registered( My_Bans, Mask, Chan );
+} /* Lists_IsBanEntry */
+
+
+GLOBAL bool
+Lists_AddBanned( char *Mask, CHANNEL *Chan )
+{
+	C2C *c2c;
+
+	assert( Mask != NULL );
+	assert( Chan != NULL );
+
+	if( Already_Registered( My_Bans, Mask, Chan )) return true;
+
+	c2c = New_C2C( Mask, Chan, false );
+	if( ! c2c )
+	{
+		Log( LOG_ERR, "Can't add new ban list entry!" );
+		return false;
+	}
+
+	/* verketten */
+	c2c->next = My_Bans;
+	My_Bans = c2c;
+
+	Log( LOG_DEBUG, "Added \"%s\" to ban list for \"%s\".", Mask, Channel_Name( Chan ));
+	return true;
+} /* Lists_AddBanned */
+
+
+GLOBAL void
+Lists_DelBanned( char *Mask, CHANNEL *Chan )
+{
+	C2C *c2c, *last, *next;
+
+	assert( Mask != NULL );
+	assert( Chan != NULL );
+
+	last = NULL;
+	c2c = My_Bans;
+	while( c2c )
+	{
+		next = c2c->next;
+		if(( c2c->channel == Chan ) && ( strcasecmp( c2c->mask, Mask ) == 0 ))
+		{
+			/* dieser Eintrag muss geloescht werden */
+			Log( LOG_DEBUG, "Deleted \"%s\" from ban list for \"%s\"." , c2c->mask, Channel_Name( Chan ));
+			if( last ) last->next = next;
+			else My_Bans = next;
+			free( c2c );
+		}
+		else last = c2c;
+		c2c = next;
+	}
+} /* Lists_DelBanned */
+
+
+GLOBAL bool
+Lists_ShowBans( CLIENT *Client, CHANNEL *Channel )
+{
+	C2C *c2c;
+
+	assert( Client != NULL );
+	assert( Channel != NULL );
+
+	c2c = My_Bans;
+	while( c2c )
+	{
+		if( c2c->channel == Channel )
+		{
+			/* Eintrag fuer Channel gefunden; ausgeben: */
+			if( ! IRC_WriteStrClient( Client, RPL_BANLIST_MSG, Client_ID( Client ), Channel_Name( Channel ), c2c->mask )) return DISCONNECTED;
+		}
+		c2c = c2c->next;
+	}
+	return IRC_WriteStrClient( Client, RPL_ENDOFBANLIST_MSG, Client_ID( Client ), Channel_Name( Channel ));
+} /* Lists_ShowBans */
+
+
+GLOBAL void
+Lists_DeleteChannel( CHANNEL *Chan )
+{
+	/* Channel wurde geloescht, Invite- und Ban-Lists aufraeumen */
+
+	C2C *c2c, *last, *next;
+
+	/* Invite-List */
+	last = NULL;
+	c2c = My_Invites;
+	while( c2c )
+	{
+		next = c2c->next;
+		if( c2c->channel == Chan )
+		{
+			/* dieser Eintrag muss geloescht werden */
+			Log( LOG_DEBUG, "Deleted \"%s\" from invite list for \"%s\"." , c2c->mask, Channel_Name( Chan ));
+			if( last ) last->next = next;
+			else My_Invites = next;
+			free( c2c );
+		}
+		else last = c2c;
+		c2c = next;
+	}
+
+	/* Ban-List */
+	last = NULL;
+	c2c = My_Bans;
+	while( c2c )
+	{
+		next = c2c->next;
+		if( c2c->channel == Chan )
+		{
+			/* dieser Eintrag muss geloescht werden */
+			Log( LOG_DEBUG, "Deleted \"%s\" from ban list for \"%s\"." , c2c->mask, Channel_Name( Chan ));
+			if( last ) last->next = next;
+			else My_Bans = next;
+			free( c2c );
+		}
+		else last = c2c;
+		c2c = next;
+	}
+} /* Lists_DeleteChannel */
+
+
+GLOBAL char *
+Lists_MakeMask( char *Pattern )
+{
+	/* This function generats a valid IRC mask of "any" string. This
+	 * mask is only valid until the next call to Lists_MakeMask(),
+	 * because a single global buffer is used. You have to copy the
+	 * generated mask to some sane location yourself! */
+
+	static char TheMask[MASK_LEN];
+	char *excl, *at;
+
+	assert( Pattern != NULL );
+
+	excl = strchr( Pattern, '!' );
+	at = strchr( Pattern, '@' );
+
+	if(( at ) && ( at < excl )) excl = NULL;
+
+	if(( ! at ) && ( ! excl ))
+	{
+		/* Neither "!" nor "@" found: use string as nick name */
+		strlcpy( TheMask, Pattern, sizeof( TheMask ) - 5 );
+		strlcat( TheMask, "!*@*", sizeof( TheMask ));
+		return TheMask;
+	}
+
+	if(( ! at ) && ( excl ))
+	{
+		/* Domain part is missing */
+		strlcpy( TheMask, Pattern, sizeof( TheMask ) - 3 );
+		strlcat( TheMask, "@*", sizeof( TheMask ));
+		return TheMask;
+	}
+
+	if(( at ) && ( ! excl ))
+	{
+		/* User name is missing */
+		*at = '\0'; at++;
+		strlcpy( TheMask, Pattern, sizeof( TheMask ) - 5 );
+		strlcat( TheMask, "!*@", sizeof( TheMask ));
+		strlcat( TheMask, at, sizeof( TheMask ));
+		return TheMask;
+	}
+
+	/* All parts (nick, user and domain name) are given */
+	strlcpy( TheMask, Pattern, sizeof( TheMask ));
+	return TheMask;
+} /* Lists_MakeMask */
+
+
+LOCAL C2C *
+New_C2C( char *Mask, CHANNEL *Chan, bool OnlyOnce )
+{
+	C2C *c2c;
+	
+	assert( Mask != NULL );
+	assert( Chan != NULL );
+
+	/* Speicher fuer Eintrag anfordern */
+	c2c = (C2C *)malloc( sizeof( C2C ));
+	if( ! c2c )
+	{
+		Log( LOG_EMERG, "Can't allocate memory! [New_C2C]" );
+		return NULL;
+	}
+
+	strlcpy( c2c->mask, Mask, sizeof( c2c->mask ));
+	c2c->channel = Chan;
+	c2c->onlyonce = OnlyOnce;
+
+	return c2c;
+} /* New_C2C */
+
+
+LOCAL bool
+Check_List( C2C **Cl2Chan, CLIENT *Client, CHANNEL *Chan )
+{
+	C2C *c2c, *last;
+
+	assert( Cl2Chan != NULL );
+	assert( Client != NULL );
+	assert( Chan != NULL );
+
+	c2c = *Cl2Chan;
+	last = NULL;
+
+	while( c2c )
+	{
+		if( c2c->channel == Chan )
+		{
+			/* Ok, richtiger Channel. Passt die Maske? */
+			if( Match( c2c->mask, Client_Mask( Client )))
+			{
+				/* Treffer! */
+				if( c2c->onlyonce )
+				{
+					/* Eintrag loeschen */
+					Log( LOG_DEBUG, "Deleted \"%s\" from %s list for \"%s\".", c2c->mask, *Cl2Chan == My_Invites ? "invite" : "ban", Channel_Name( Chan ));
+					if( last ) last->next = c2c->next;
+					else *Cl2Chan = c2c->next;
+					free( c2c );
+				}
+				return true;
+			}
+		}
+		last = c2c;
+		c2c = c2c->next;
+	}
+
+	return false;
+} /* Check_List */
+
+
+LOCAL bool
+Already_Registered( C2C *List, char *Mask, CHANNEL *Chan )
+{
+	C2C *c2c;
+
+	c2c = List;
+	while( c2c )
+	{
+		if(( c2c->channel == Chan ) && ( strcasecmp( c2c->mask, Mask ) == 0 )) return true;
+		c2c = c2c->next;
+	}
+	return false;
+} /* Already_Registered */
+
+
+/* -eof- */

+ 46 - 0
src/ngircd/lists.h

@@ -0,0 +1,46 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * $Id: lists.h,v 1.12 2005/03/19 18:43:49 fw Exp $
+ *
+ * Management of IRC lists: ban, invite, ... (header)
+ */
+
+
+#ifndef __lists_h__
+#define __lists_h__
+
+
+GLOBAL void Lists_Init PARAMS(( void ));
+GLOBAL void Lists_Exit PARAMS(( void ));
+
+GLOBAL bool Lists_CheckInvited PARAMS(( CLIENT *Client, CHANNEL *Chan ));
+GLOBAL bool Lists_AddInvited PARAMS(( char *Mask, CHANNEL *Chan, bool OnlyOnce ));
+GLOBAL void Lists_DelInvited PARAMS(( char *Mask, CHANNEL *Chan ));
+GLOBAL bool Lists_ShowInvites PARAMS(( CLIENT *Client, CHANNEL *Channel ));
+GLOBAL bool Lists_SendInvites PARAMS(( CLIENT *Client ));
+GLOBAL bool Lists_IsInviteEntry PARAMS(( char *Mask, CHANNEL *Chan ));
+
+GLOBAL bool Lists_CheckBanned PARAMS(( CLIENT *Client, CHANNEL *Chan ));
+GLOBAL bool Lists_AddBanned PARAMS(( char *Mask, CHANNEL *Chan ));
+GLOBAL void Lists_DelBanned PARAMS(( char *Mask, CHANNEL *Chan ));
+GLOBAL bool Lists_ShowBans PARAMS(( CLIENT *Client, CHANNEL *Channel ));
+GLOBAL bool Lists_SendBans PARAMS(( CLIENT *Client ));
+GLOBAL bool Lists_IsBanEntry PARAMS(( char *Mask, CHANNEL *Chan ));
+
+GLOBAL void Lists_DeleteChannel PARAMS(( CHANNEL *Chan ));
+
+GLOBAL char *Lists_MakeMask PARAMS(( char *Pattern ));
+
+
+#endif
+
+
+/* -eof- */

+ 327 - 0
src/ngircd/log.c

@@ -0,0 +1,327 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001-2005 Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * Logging functions
+ */
+
+
+#include "portab.h"
+
+static char UNUSED id[] = "$Id: log.c,v 1.57.2.1 2005/08/29 11:19:48 alex Exp $";
+
+#include "imp.h"
+#include <assert.h>
+#include <errno.h>
+#ifdef PROTOTYPES
+#	include <stdarg.h>
+#else
+#	include <varargs.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifdef SYSLOG
+#include <syslog.h>
+#endif
+
+#include "ngircd.h"
+#include "defines.h"
+#include "conn.h"
+#include "client.h"
+#include "channel.h"
+#include "irc-write.h"
+
+#include "exp.h"
+#include "log.h"
+
+
+LOCAL char Init_Txt[127];
+LOCAL bool Is_Daemon;
+
+#ifdef DEBUG
+LOCAL char Error_File[FNAME_LEN];
+#endif
+
+
+LOCAL void Wall_ServerNotice PARAMS(( char *Msg ));
+
+
+GLOBAL void
+Log_Init( bool Daemon_Mode )
+{
+	Is_Daemon = Daemon_Mode;
+	
+#ifdef SYSLOG
+#ifndef LOG_CONS	/* Kludge: mips-dec-ultrix4.5 has no LOG_CONS/LOG_LOCAL5 */
+#define LOG_CONS 0
+#endif
+#ifndef LOG_LOCAL5
+#define LOG_LOCAL5 0
+#endif
+	/* Syslog initialisieren */
+	openlog( PACKAGE_NAME, LOG_CONS|LOG_PID, LOG_LOCAL5 );
+#endif
+
+	/* Hello World! */
+	Log( LOG_NOTICE, "%s started.", NGIRCd_Version );
+	  
+	/* Informationen uebern den "Operation Mode" */
+	Init_Txt[0] = '\0';
+#ifdef DEBUG
+	if( NGIRCd_Debug )
+	{
+		strlcpy( Init_Txt, "debug-mode", sizeof Init_Txt );
+	}
+#endif
+	if( ! Is_Daemon )
+	{
+		if( Init_Txt[0] ) strlcat( Init_Txt, ", ", sizeof Init_Txt );
+		strlcat( Init_Txt, "no-daemon-mode", sizeof Init_Txt );
+	}
+	if( NGIRCd_Passive )
+	{
+		if( Init_Txt[0] ) strlcat( Init_Txt, ", ", sizeof Init_Txt );
+		strlcat( Init_Txt, "passive-mode", sizeof Init_Txt );
+	}
+#ifdef SNIFFER
+	if( NGIRCd_Sniffer )
+	{
+		if( Init_Txt[0] ) strlcat( Init_Txt, ", ", sizeof Init_Txt );
+		strlcat( Init_Txt, "network sniffer", sizeof Init_Txt );
+	}
+#endif
+	if( Init_Txt[0] ) Log( LOG_INFO, "Activating: %s.", Init_Txt );
+
+#ifdef DEBUG
+	Error_File[0] = '\0';
+#endif
+} /* Log_Init */
+
+
+#ifdef DEBUG
+
+GLOBAL void
+Log_InitErrorfile( void )
+{
+	/* "Error-Log" initialisieren: stderr in Datei umlenken. Dort
+	 * landen z.B. alle Ausgaben von assert()-Aufrufen. */
+
+	/* Dateiname zusammen bauen */
+	snprintf( Error_File, sizeof Error_File, "%s/%s-%ld.err", ERROR_DIR, PACKAGE_NAME, (long)getpid( ));
+
+	/* stderr umlenken */
+	fflush( stderr );
+	if( ! freopen( Error_File, "w", stderr ))
+	{
+		Log( LOG_ERR, "Can't reopen stderr (\"%s\"): %s", Error_File, strerror( errno ));
+		return;
+	}
+
+	/* Einige Infos in das Error-File schreiben */
+	fputs( ctime( &NGIRCd_Start ), stderr );
+	fprintf( stderr, "%s started.\n", NGIRCd_Version );
+	fprintf( stderr, "Activating: %s\n\n", Init_Txt[0] ? Init_Txt : "-" );
+	fflush( stderr );
+
+#ifdef DEBUG
+	Log( LOG_DEBUG, "Redirected stderr to \"%s\".", Error_File );
+#endif
+} /* Log_InitErrfile */
+
+#endif
+
+
+GLOBAL void
+Log_Exit( void )
+{
+	/* Good Bye! */
+	if( NGIRCd_SignalRestart ) Log( LOG_NOTICE, "%s done (restarting).", PACKAGE_NAME );
+	else Log( LOG_NOTICE, "%s done.", PACKAGE_NAME );
+
+#ifdef DEBUG
+	if( Error_File[0] )
+	{
+		/* Error-File (stderr) loeschen */
+		if( unlink( Error_File ) != 0 ) Log( LOG_ERR, "Can't delete \"%s\": %s", Error_File, strerror( errno ));
+	}
+#endif
+
+#ifdef SYSLOG
+	/* syslog abmelden */
+	closelog( );
+#endif
+} /* Log_Exit */
+
+
+#ifdef PROTOTYPES
+GLOBAL void
+Log( int Level, const char *Format, ... )
+#else
+GLOBAL void
+Log( Level, Format, va_alist )
+int Level;
+const char *Format;
+va_dcl
+#endif
+{
+	/* Eintrag in Logfile(s) schreiben */
+
+	char msg[MAX_LOG_MSG_LEN];
+	bool snotice;
+	va_list ap;
+
+	assert( Format != NULL );
+
+	if( Level & LOG_snotice )
+	{
+		/* Notice an User mit "s" Mode */
+		snotice = true;
+		Level &= ~LOG_snotice;
+	}
+	else snotice = false;
+
+#ifdef DEBUG
+	if(( Level == LOG_DEBUG ) && ( ! NGIRCd_Debug )) return;
+#else
+	if( Level == LOG_DEBUG ) return;
+#endif
+
+	/* String mit variablen Argumenten zusammenbauen ... */
+#ifdef PROTOTYPES
+	va_start( ap, Format );
+#else
+	va_start( ap );
+#endif
+	vsnprintf( msg, MAX_LOG_MSG_LEN, Format, ap );
+	va_end( ap );
+
+	if( ! Is_Daemon )
+	{
+		/* auf Konsole ausgeben */
+		fprintf( stdout, "[%d:%d] %s\n", (int)getpid( ), Level, msg );
+		fflush( stdout );
+	}
+#ifdef SYSLOG
+	else
+	{
+		/* Syslog */
+		syslog( Level, "%s", msg );
+	}
+#endif
+
+	if( Level <= LOG_CRIT )
+	{
+		/* log critical messages to stderr */
+		fprintf( stderr, "%s\n", msg );
+		fflush( stderr );
+	}
+
+	if( snotice )
+	{
+		/* NOTICE an lokale User mit "s"-Mode */
+		Wall_ServerNotice( msg );
+	}
+} /* Log */
+
+
+GLOBAL void
+Log_Init_Resolver( void )
+{
+#ifdef SYSLOG
+	openlog( PACKAGE_NAME, LOG_CONS|LOG_PID, LOG_LOCAL5 );
+#endif
+#ifdef DEBUG
+	Log_Resolver( LOG_DEBUG, "Resolver sub-process starting, PID %d.", getpid( ));
+#endif
+} /* Log_Init_Resolver */
+
+
+GLOBAL void
+Log_Exit_Resolver( void )
+{
+#ifdef DEBUG
+	Log_Resolver( LOG_DEBUG, "Resolver sub-process %d done.", getpid( ));
+#endif
+#ifdef SYSLOG
+	closelog( );
+#endif
+} /* Log_Exit_Resolver */
+
+
+#ifdef PROTOTYPES
+GLOBAL void
+Log_Resolver( const int Level, const char *Format, ... )
+#else
+GLOBAL void
+Log_Resolver( Level, Format, va_alist )
+const int Level;
+const char *Format;
+va_dcl
+#endif
+{
+	/* Eintrag des Resolver in Logfile(s) schreiben */
+
+	char msg[MAX_LOG_MSG_LEN];
+	va_list ap;
+
+	assert( Format != NULL );
+
+#ifdef DEBUG
+	if(( Level == LOG_DEBUG ) && ( ! NGIRCd_Debug )) return;
+#else
+	if( Level == LOG_DEBUG ) return;
+#endif
+
+	/* String mit variablen Argumenten zusammenbauen ... */
+#ifdef PROTOTYPES
+	va_start( ap, Format );
+#else
+	va_start( ap );
+#endif
+	vsnprintf( msg, MAX_LOG_MSG_LEN, Format, ap );
+	va_end( ap );
+
+	if( ! Is_Daemon )
+	{
+		/* Output to console */
+		fprintf( stdout, "[%d:%d] %s\n", (int)getpid( ), Level, msg );
+		fflush( stdout );
+	}
+#ifdef SYSLOG
+	else syslog( Level, "%s", msg );
+#endif
+} /* Log_Resolver */
+
+
+/**
+ * Send log messages to users flagged with the "s" mode.
+ * @param Msg The message to send.
+ */
+LOCAL void
+Wall_ServerNotice( char *Msg )
+{
+	CLIENT *c;
+
+	assert( Msg != NULL );
+
+	c = Client_First( );
+	while(c) {
+		if (Client_Conn(c) > NONE && Client_HasMode(c, 's'))
+			IRC_WriteStrClient(c, "NOTICE %s :%s%s", Client_ID(c),
+							NOTICE_TXTPREFIX, Msg);
+
+		c = Client_Next( c );
+	}
+} /* Wall_ServerNotice */
+
+
+/* -eof- */

+ 56 - 0
src/ngircd/log.h

@@ -0,0 +1,56 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * $Id: log.h,v 1.18 2005/06/24 19:55:10 alex Exp $
+ *
+ * Logging functions (header)
+ */
+
+
+#ifndef __log_h__
+#define __log_h__
+
+
+#ifdef SYSLOG
+#	include <syslog.h>
+#else
+#	define LOG_EMERG 0
+#	define LOG_ALERT 1
+#	define LOG_CRIT 2
+#	define LOG_ERR 3
+#	define LOG_WARNING 4
+#	define LOG_NOTICE 5
+#	define LOG_INFO 6
+#	define LOG_DEBUG 7
+#endif
+
+
+#define LOG_snotice 1024
+
+
+GLOBAL void Log_Init PARAMS(( bool Daemon_Mode ));
+GLOBAL void Log_Exit PARAMS(( void ));
+
+GLOBAL void Log PARAMS(( int Level, const char *Format, ... ));
+
+GLOBAL void Log_Init_Resolver PARAMS(( void ));
+GLOBAL void Log_Exit_Resolver PARAMS(( void ));
+
+GLOBAL void Log_Resolver PARAMS(( const int Level, const char *Format, ... ));
+
+#ifdef DEBUG
+GLOBAL void Log_InitErrorfile PARAMS(( void ));
+#endif
+
+
+#endif
+
+
+/* -eof- */

+ 253 - 0
src/ngircd/match.c

@@ -0,0 +1,253 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * Wildcard pattern matching
+ */
+
+
+#include "portab.h"
+
+static char UNUSED id[] = "$Id: match.c,v 1.3 2005/03/19 18:43:49 fw Exp $";
+
+#include "imp.h"
+#include <assert.h>
+#include <string.h>
+
+#include "exp.h"
+#include "match.h"
+
+
+/*
+ * Die Pattern-Matching-Funkionen [Matche(), Matche_After_Star()] basieren
+ * auf Versionen von J. Kercheval. Die Version 1.1 wurde am 12.03.1991 als
+ * "public domain" freigegeben:
+ * <http://www.snippets.org/snippets/portable/MATCH+C.php3>
+ */
+
+
+LOCAL int Matche PARAMS(( char *p, char *t ));
+LOCAL int Matche_After_Star PARAMS(( char *p, char *t ));
+
+
+#define MATCH_PATTERN	6	/* bad pattern */
+#define MATCH_LITERAL	5	/* match failure on literal match */
+#define MATCH_RANGE	4	/* match failure on [..] construct */
+#define MATCH_ABORT	3	/* premature end of text string */
+#define MATCH_END	2	/* premature end of pattern string */
+#define MATCH_VALID	1	/* valid match */
+
+
+GLOBAL bool
+Match( char *Pattern, char *String )
+{
+	/* Pattern mit String vergleichen */
+	if( Matche( Pattern, String ) == MATCH_VALID ) return true;
+	else return false;
+} /* Match */
+
+
+LOCAL int
+Matche( char *p, char *t )
+{
+	register char range_start, range_end;
+	bool invert;
+	bool member_match;
+	bool loop;
+
+	for( ; *p; p++, t++ )
+	{
+		/* if this is the end of the text then this is the end of the match */
+		if( ! *t )
+		{
+			return ( *p == '*' && *++p == '\0' ) ? MATCH_VALID : MATCH_ABORT;
+		}
+
+		/* determine and react to pattern type */
+		switch( *p )
+		{
+			case '?':	/* single any character match */
+				break;
+
+			case '*':	/* multiple any character match */
+				return Matche_After_Star( p, t );
+
+			case '[':	/* [..] construct, single member/exclusion character match */
+				/* move to beginning of range */
+				p++;
+
+				/* check if this is a member match or exclusion match */
+				invert = false;
+				if( *p == '!' || *p == '^' )
+				{
+					invert = true;
+					p++;
+				}
+
+				/* if closing bracket here or at range start then we have a malformed pattern */
+				if ( *p == ']' ) return MATCH_PATTERN;
+
+				member_match = false;
+				loop = true;
+
+				while( loop )
+				{
+					/* if end of construct then loop is done */
+					if( *p == ']' )
+					{
+						loop = false;
+						continue;
+					}
+
+					/* matching a '!', '^', '-', '\' or a ']' */
+					if( *p == '\\' ) range_start = range_end = *++p;
+					else  range_start = range_end = *p;
+
+					/* if end of pattern then bad pattern (Missing ']') */
+					if( ! *p ) return MATCH_PATTERN;
+
+					/* check for range bar */
+					if( *++p == '-' )
+					{
+						/* get the range end */
+						range_end = *++p;
+
+						/* if end of pattern or construct then bad pattern */
+						if( range_end == '\0' || range_end == ']' ) return MATCH_PATTERN;
+
+						/* special character range end */
+						if( range_end == '\\' )
+						{
+							range_end = *++p;
+
+							/* if end of text then we have a bad pattern */
+							if ( ! range_end ) return MATCH_PATTERN;
+						}
+
+						/* move just beyond this range */
+						p++;
+					}
+
+					/* if the text character is in range then match found. make sure the range
+					 * letters have the proper relationship to one another before comparison */
+					if( range_start < range_end )
+					{
+						if( *t >= range_start && *t <= range_end )
+						{
+							member_match = true;
+							loop = false;
+						}
+					}
+					else
+					{
+						if( *t >= range_end && *t <= range_start )
+						{
+							member_match = true;
+							loop = false;
+						}
+					}
+				}
+
+				/* if there was a match in an exclusion set then no match */
+				/* if there was no match in a member set then no match */
+				if(( invert && member_match ) || ! ( invert || member_match )) return MATCH_RANGE;
+
+				/* if this is not an exclusion then skip the rest of the [...]
+				 * construct that already matched. */
+				if( member_match )
+				{
+					while( *p != ']' )
+					{
+						/* bad pattern (Missing ']') */
+						if( ! *p ) return MATCH_PATTERN;
+
+						/* skip exact match */
+						if( *p == '\\' )
+						{
+							p++;
+
+							/* if end of text then we have a bad pattern */
+							if( ! *p ) return MATCH_PATTERN;
+						}
+
+						/* move to next pattern char */
+						p++;
+					}
+				}
+				break;
+			case '\\':	/* next character is quoted and must match exactly */
+				/* move pattern pointer to quoted char and fall through */
+				p++;
+
+				/* if end of text then we have a bad pattern */
+				if( ! *p ) return MATCH_PATTERN;
+
+				/* must match this character exactly */
+			default:
+				if( *p != *t ) return MATCH_LITERAL;
+		}
+	}
+	/* if end of text not reached then the pattern fails */
+
+	if( *t ) return MATCH_END;
+	else return MATCH_VALID;
+} /* Matche */
+
+
+LOCAL int
+Matche_After_Star( char *p, char *t )
+{
+	register int nextp, match = 0;
+
+	/* pass over existing ? and * in pattern */
+	while( *p == '?' || *p == '*' )
+	{
+		/* take one char for each ? and + */
+		if (*p == '?')
+		{
+			/* if end of text then no match */
+			if( ! *t++ ) return MATCH_ABORT;
+		}
+
+		/* move to next char in pattern */
+		p++;
+	}
+
+	/* if end of pattern we have matched regardless of text left */
+	if( ! *p ) return MATCH_VALID;
+
+	/* get the next character to match which must be a literal or '[' */
+	nextp = *p;
+	if( nextp == '\\' )
+	{
+		nextp = p[1];
+
+		/* if end of text then we have a bad pattern */
+		if( ! nextp ) return MATCH_PATTERN;
+	}
+
+	/* Continue until we run out of text or definite result seen */
+	do
+	{
+		/* a precondition for matching is that the next character
+		 * in the pattern match the next character in the text or that
+		 * the next pattern char is the beginning of a range.  Increment
+		 * text pointer as we go here */
+		if( nextp == *t || nextp == '[' ) match = Matche( p, t );
+
+		/* if the end of text is reached then no match */
+		if( ! *t++ ) match = MATCH_ABORT;
+	} while( match != MATCH_VALID && match != MATCH_ABORT && match != MATCH_PATTERN );
+
+	/* return result */
+	return match;
+} /* Matche_After_Star */
+
+
+/* -eof- */

+ 27 - 0
src/ngircd/match.h

@@ -0,0 +1,27 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * $Id: match.h,v 1.3 2005/03/19 18:43:49 fw Exp $
+ *
+ * Wildcard pattern matching (header)
+ */
+
+
+#ifndef __match_h__
+#define __match_h__
+
+
+GLOBAL bool Match PARAMS(( char *Pattern, char *String ));
+
+
+#endif
+
+
+/* -eof- */

+ 128 - 0
src/ngircd/messages.h

@@ -0,0 +1,128 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001-2004 Alexander Barton <alex@barton.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * $Id: messages.h,v 1.66 2004/02/28 02:18:16 alex Exp $
+ *
+ * IRC numerics (Header)
+ */
+
+
+#ifndef __messages_h__
+#define __messages_h__
+
+
+#define RPL_WELCOME_MSG			"001 %s :Welcome to the Internet Relay Network %s"
+#define RPL_YOURHOST_MSG		"002 %s :Your host is %s, running version ngircd-%s (%s/%s/%s)"
+#define RPL_CREATED_MSG			"003 %s :This server has been started %s"
+#define RPL_MYINFO_MSG			"004 %s %s ngircd-%s %s %s"
+#define RPL_ISUPPORT_MSG		"005 %s NICKLEN=%d TOPICLEN=%d AWAYLEN=%d MAXCHANNELS=%d :are supported on this server"
+
+#define RPL_TRACELINK_MSG		"200 %s Link %s-%s %s %s V%s %ld %d %d"
+#define RPL_TRACEOPERATOR_MSG		"204 %s Oper 2 :%s"
+#define RPL_TRACESERVER_MSG		"206 %s Serv 1 0S 0C %s[%s@%s] *!*@%s :V%s"
+#define RPL_STATSLINKINFO_MSG		"211 %s %s %d %ld %ld %ld %ld :%ld"
+#define RPL_STATSCOMMANDS_MSG		"212 %s %s %ld %ld %ld"
+#define RPL_ENDOFSTATS_MSG		"219 %s %c :End of STATS report"
+#define RPL_UMODEIS_MSG			"221 %s +%s"
+#define RPL_LUSERCLIENT_MSG		"251 %s :There are %ld users and %ld services on %ld servers"
+#define RPL_LUSEROP_MSG			"252 %s %ld :operator(s) online"
+#define RPL_LUSERUNKNOWN_MSG		"253 %s %ld :unknown connection(s)"
+#define RPL_LUSERCHANNELS_MSG		"254 %s %ld :channels formed"
+#define RPL_LUSERME_MSG			"255 %s :I have %ld users, %ld services and %ld servers"
+#define RPL_ADMINME_MSG			"256 %s %s :Administrative info"
+#define RPL_ADMINLOC1_MSG		"257 %s :%s"
+#define RPL_ADMINLOC2_MSG		"258 %s :%s"
+#define RPL_ADMINEMAIL_MSG		"259 %s :%s"
+#define RPL_TRACEEND_MSG		"262 %s %s %s-%s.%s :End of TRACE"
+#define RPL_LOCALUSERS_MSG		"265 %s :Current local users: %ld, Max: %ld"
+#define RPL_NETUSERS_MSG		"266 %s :Current global users: %ld, Max: %ld"
+
+#define RPL_AWAY_MSG			"301 %s %s :%s"
+#define RPL_USERHOST_MSG		"302 %s :"
+#define RPL_ISON_MSG			"303 %s :"
+#define RPL_UNAWAY_MSG			"305 %s :You are no longer marked as being away"
+#define RPL_NOWAWAY_MSG			"306 %s :You have been marked as being away"
+#define RPL_WHOISUSER_MSG		"311 %s %s %s %s * :%s"
+#define RPL_WHOISSERVER_MSG		"312 %s %s %s :%s"
+#define RPL_WHOISOPERATOR_MSG		"313 %s %s :is an IRC operator"
+#define RPL_WHOWASUSER_MSG		"314 %s %s %s %s * :%s"
+#define RPL_ENDOFWHO_MSG		"315 %s %s :End of WHO list"
+#define RPL_WHOISIDLE_MSG		"317 %s %s %ld :seconds idle"
+#define RPL_ENDOFWHOIS_MSG		"318 %s %s :End of WHOIS list"
+#define RPL_WHOISCHANNELS_MSG		"319 %s %s :"
+#define RPL_LIST_MSG			"322 %s %s %ld :%s"
+#define RPL_LISTEND_MSG			"323 %s :End of LIST"
+#define RPL_CHANNELMODEIS_MSG		"324 %s %s +%s"
+#define RPL_NOTOPIC_MSG			"331 %s %s :No topic is set"
+#define RPL_TOPIC_MSG			"332 %s %s :%s"
+#define RPL_INVITING_MSG		"341 %s %s %s"
+#define RPL_INVITELIST_MSG		"346 %s %s %s"
+#define RPL_ENDOFINVITELIST_MSG		"347 %s %s :End of channel invite list"
+#define RPL_VERSION_MSG			"351 %s %s-%s.%s %s :%s"
+#define RPL_WHOREPLY_MSG		"352 %s %s %s %s %s %s %s :%d %s"
+#define RPL_NAMREPLY_MSG		"353 %s %s %s :"
+#define RPL_LINKS_MSG			"364 %s %s %s :%d %s"
+#define RPL_ENDOFLINKS_MSG		"365 %s %s :End of LINKS list"
+#define RPL_ENDOFNAMES_MSG		"366 %s %s :End of NAMES list"
+#define RPL_BANLIST_MSG			"367 %s %s %s"
+#define RPL_ENDOFBANLIST_MSG		"368 %s %s :End of channel ban list"
+#define RPL_ENDOFWHOWAS_MSG		"369 %s %s :End of WHOWAS list"
+#define RPL_MOTD_MSG			"372 %s :- %s"
+#define RPL_MOTDSTART_MSG		"375 %s :- %s message of the day"
+#define RPL_ENDOFMOTD_MSG		"376 %s :End of MOTD command"
+#define RPL_YOUREOPER_MSG		"381 %s :You are now an IRC Operator"
+#define RPL_YOURESERVICE_MSG		"383 %s :You are service %s"
+#define RPL_TIME_MSG			"391 %s %s :%s"
+
+#define ERR_NOSUCHNICK_MSG		"401 %s %s :No such nick or channel name"
+#define ERR_NOSUCHSERVER_MSG		"402 %s %s :No such server"
+#define ERR_NOSUCHCHANNEL_MSG		"403 %s %s :No such channel"
+#define ERR_CANNOTSENDTOCHAN_MSG	"404 %s %s :Cannot send to channel"
+#define ERR_TOOMANYCHANNELS_MSG		"405 %s %s :You have joined too many channels"
+#define ERR_WASNOSUCHNICK_MSG		"406 %s %s :There was no such nickname"
+#define ERR_NOORIGIN_MSG		"409 %s :No origin specified"
+#define ERR_NORECIPIENT_MSG		"411 %s :No receipient given (%s)"
+#define ERR_NOTEXTTOSEND_MSG		"412 %s :No text to send"
+#define ERR_UNKNOWNCOMMAND_MSG		"421 %s %s :Unknown command"
+#define ERR_NOMOTD_MSG			"422 %s :MOTD file is missing"
+#define ERR_ERRONEUSNICKNAME_MSG	"432 %s %s :Erroneous nickname"
+#define ERR_NICKNAMEINUSE_MSG		"433 %s %s :Nickname already in use"
+#define ERR_USERNOTINCHANNEL_MSG	"441 %s %s %s :They aren't on that channel"
+#define ERR_NOTONCHANNEL_MSG		"442 %s %s :You are not on that channel"
+#define ERR_USERONCHANNEL_MSG		"443 %s %s %s :is already on channel"
+#define ERR_NOTREGISTERED_MSG		"451 %s :Connection not registered"
+#define ERR_NOTREGISTEREDSERVER_MSG	"451 %s :Connection not registered as server link"
+#define ERR_NEEDMOREPARAMS_MSG		"461 %s %s :Syntax error"
+#define ERR_ALREADYREGISTRED_MSG	"462 %s :Connection already registered"
+#define ERR_PASSWDMISMATCH_MSG		"464 %s :Invalid password"
+#define ERR_CHANNELISFULL_MSG		"471 %s %s :Cannot join channel (+l)"
+#define ERR_UNKNOWNMODE_MSG		"472 %s: %c :is unknown mode char for %s"
+#define ERR_INVITEONLYCHAN_MSG		"473 %s %s :Cannot join channel (+i)"
+#define ERR_BANNEDFROMCHAN_MSG		"474 %s %s :Cannot join channel (+b)"
+#define ERR_BADCHANNELKEY_MSG		"475 %s %s :Cannot join channel (+k)"
+#define ERR_NOPRIVILEGES_MSG		"481 %s :Permission denied"
+#define ERR_CHANOPRIVSNEEDED_MSG	"482 %s %s :You are not channel operator"
+#define ERR_CANTKILLSERVER_MSG		"483 %s :You can't kill a server!"
+#define ERR_RESTRICTED_MSG		"484 %s :Your connection is restricted"
+#define ERR_NOOPERHOST_MSG		"491 %s :Not configured for your host"
+
+#define ERR_UMODEUNKNOWNFLAG_MSG	"501 %s :Unknown mode"
+#define ERR_UMODEUNKNOWNFLAG2_MSG	"501 %s :Unknown mode \"%c%c\""
+#define ERR_USERSDONTMATCH_MSG		"502 %s :Can't set/get mode for other users"
+
+#ifdef ZLIB
+#define RPL_STATSLINKINFOZIP_MSG	"211 %s %s %d %ld %ld/%ld %ld %ld/%ld :%ld"
+#endif
+
+
+#endif
+
+
+/* -eof- */

+ 811 - 0
src/ngircd/ngircd.c

@@ -0,0 +1,811 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001-2005 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ */
+
+
+#include "portab.h"
+
+static char UNUSED id[] = "$Id: ngircd.c,v 1.102.2.2 2005/07/08 23:20:04 alex Exp $";
+
+/**
+ * @file
+ * The main program, including the C function main() which is called
+ * by the loader of the operating system.
+ */
+
+#include "imp.h"
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include "defines.h"
+#include "resolve.h"
+#include "conn.h"
+#include "client.h"
+#include "channel.h"
+#include "conf.h"
+#include "cvs-version.h"
+#include "lists.h"
+#include "log.h"
+#include "parse.h"
+#include "irc.h"
+
+#ifdef RENDEZVOUS
+#include "rendezvous.h"
+#endif
+
+#include "exp.h"
+#include "ngircd.h"
+
+
+LOCAL void Initialize_Signal_Handler PARAMS(( void ));
+LOCAL void Signal_Handler PARAMS(( int Signal ));
+
+LOCAL void Show_Version PARAMS(( void ));
+LOCAL void Show_Help PARAMS(( void ));
+
+LOCAL void Pidfile_Create PARAMS(( long ));
+LOCAL void Pidfile_Delete PARAMS(( void ));
+
+LOCAL void Fill_Version PARAMS(( void ));
+
+LOCAL void Setup_FDStreams PARAMS(( void ));
+
+LOCAL bool NGIRCd_Init PARAMS(( bool ));
+
+/**
+ * The main() function of ngIRCd.
+ * Here all starts: this function is called by the operating system loader,
+ * it is the first portion of code executed of ngIRCd.
+ * @param argc The number of arguments passed to ngIRCd on the command line.
+ * @param argv An array containing all the arguments passed to ngIRCd.
+ * @return Global exit code of ngIRCd, zero on success.
+ */
+GLOBAL int
+main( int argc, const char *argv[] )
+{
+	bool ok, configtest = false;
+	bool NGIRCd_NoDaemon = false;
+	int i;
+	size_t n;
+
+	umask( 0077 );
+
+	NGIRCd_SignalQuit = NGIRCd_SignalRestart = NGIRCd_SignalRehash = false;
+	NGIRCd_Passive = false;
+#ifdef DEBUG
+	NGIRCd_Debug = false;
+#endif
+#ifdef SNIFFER
+	NGIRCd_Sniffer = false;
+#endif
+	strlcpy( NGIRCd_ConfFile, SYSCONFDIR, sizeof( NGIRCd_ConfFile ));
+	strlcat( NGIRCd_ConfFile, CONFIG_FILE, sizeof( NGIRCd_ConfFile ));
+
+	Fill_Version( );
+
+	/* Kommandozeile parsen */
+	for( i = 1; i < argc; i++ )
+	{
+		ok = false;
+		if(( argv[i][0] == '-' ) && ( argv[i][1] == '-' ))
+		{
+			/* Lange Option */
+
+			if( strcmp( argv[i], "--config" ) == 0 )
+			{
+				if( i + 1 < argc )
+				{
+					/* Ok, there's an parameter left */
+					strlcpy( NGIRCd_ConfFile, argv[i + 1], sizeof( NGIRCd_ConfFile ));
+
+					/* next parameter */
+					i++; ok = true;
+				}
+			}
+			if( strcmp( argv[i], "--configtest" ) == 0 )
+			{
+				configtest = true;
+				ok = true;
+			}
+#ifdef DEBUG
+			if( strcmp( argv[i], "--debug" ) == 0 )
+			{
+				NGIRCd_Debug = true;
+				ok = true;
+			}
+#endif
+			if( strcmp( argv[i], "--help" ) == 0 )
+			{
+				Show_Version( );
+				puts( "" ); Show_Help( ); puts( "" );
+				exit( 1 );
+			}
+			if( strcmp( argv[i], "--nodaemon" ) == 0 )
+			{
+				NGIRCd_NoDaemon = true;
+				ok = true;
+			}
+			if( strcmp( argv[i], "--passive" ) == 0 )
+			{
+				NGIRCd_Passive = true;
+				ok = true;
+			}
+#ifdef SNIFFER
+			if( strcmp( argv[i], "--sniffer" ) == 0 )
+			{
+				NGIRCd_Sniffer = true;
+				ok = true;
+			}
+#endif
+			if( strcmp( argv[i], "--version" ) == 0 )
+			{
+				Show_Version( );
+				exit( 1 );
+			}
+		}
+		else if(( argv[i][0] == '-' ) && ( argv[i][1] != '-' ))
+		{
+			/* Kurze Option */
+			for( n = 1; n < strlen( argv[i] ); n++ )
+			{
+				ok = false;
+#ifdef DEBUG
+				if( argv[i][n] == 'd' )
+				{
+					NGIRCd_Debug = true;
+					ok = true;
+				}
+#endif
+				if( argv[i][n] == 'f' )
+				{
+					if(( ! argv[i][n + 1] ) && ( i + 1 < argc ))
+					{
+						/* Ok, next character is a blank */
+						strlcpy( NGIRCd_ConfFile, argv[i + 1], sizeof( NGIRCd_ConfFile ));
+
+						/* go to the following parameter */
+						i++;
+						n = strlen( argv[i] );
+						ok = true;
+					}
+				}
+				if( argv[i][n] == 'n' )
+				{
+					NGIRCd_NoDaemon = true;
+					ok = true;
+				}
+				if( argv[i][n] == 'p' )
+				{
+					NGIRCd_Passive = true;
+					ok = true;
+				}
+#ifdef SNIFFER
+				if( argv[i][n] == 's' )
+				{
+					NGIRCd_Sniffer = true;
+					ok = true;
+				}
+#endif
+				if( argv[i][n] == 't' )
+				{
+					configtest = true;
+					ok = true;
+				}
+
+				if( ! ok )
+				{
+					printf( "%s: invalid option \"-%c\"!\n", PACKAGE_NAME, argv[i][n] );
+					printf( "Try \"%s --help\" for more information.\n", PACKAGE_NAME );
+					exit( 1 );
+				}
+			}
+
+		}
+		if( ! ok )
+		{
+			printf( "%s: invalid option \"%s\"!\n", PACKAGE_NAME, argv[i] );
+			printf( "Try \"%s --help\" for more information.\n", PACKAGE_NAME );
+			exit( 1 );
+		}
+	}
+
+	/* Debug-Level (fuer IRC-Befehl "VERSION") ermitteln */
+	NGIRCd_DebugLevel[0] = '\0';
+#ifdef DEBUG
+	if( NGIRCd_Debug ) strcpy( NGIRCd_DebugLevel, "1" );
+#endif
+#ifdef SNIFFER
+	if( NGIRCd_Sniffer )
+	{
+		NGIRCd_Debug = true;
+		strcpy( NGIRCd_DebugLevel, "2" );
+	}
+#endif
+
+	/* Soll nur die Konfigurations ueberprueft und ausgegeben werden? */
+	if( configtest )
+	{
+		Show_Version( ); puts( "" );
+		exit( Conf_Test( ));
+	}
+	
+	while( ! NGIRCd_SignalQuit )
+	{
+		/* Initialize global variables */
+		NGIRCd_Start = time( NULL );
+		(void)strftime( NGIRCd_StartStr, 64, "%a %b %d %Y at %H:%M:%S (%Z)", localtime( &NGIRCd_Start ));
+
+		NGIRCd_SignalRehash = false;
+		NGIRCd_SignalRestart = false;
+		NGIRCd_SignalQuit = false;
+
+		/* Initialize modules, part I */
+		Log_Init( ! NGIRCd_NoDaemon );
+		Conf_Init( );
+
+		if (!NGIRCd_Init( NGIRCd_NoDaemon )) {
+			Log(LOG_WARNING, "Fatal: Initialization failed");
+			exit(1);
+		}
+
+		/* Initialize modules, part II: these functions are eventually
+		 * called with already dropped privileges ... */
+		Resolve_Init( );
+		Lists_Init( );
+		Channel_Init( );
+		Client_Init( );
+#ifdef RENDEZVOUS
+		Rendezvous_Init( );
+#endif
+		Conn_Init( );
+
+#ifdef DEBUG
+		/* Redirect stderr handle to "error file" for debugging
+		 * when not running in "no daemon" mode: */
+		if( ! NGIRCd_NoDaemon ) Log_InitErrorfile( );
+#endif
+
+		/* Signal-Handler initialisieren */
+		Initialize_Signal_Handler( );
+
+		/* Protokoll- und Server-Identifikation erzeugen. Die vom ngIRCd
+		 * beim PASS-Befehl verwendete Syntax sowie die erweiterten Flags
+		 * sind in doc/Protocol.txt beschrieben. */
+#ifdef IRCPLUS
+		snprintf( NGIRCd_ProtoID, sizeof NGIRCd_ProtoID, "%s%s %s|%s:%s", PROTOVER, PROTOIRCPLUS, PACKAGE_NAME, PACKAGE_VERSION, IRCPLUSFLAGS );
+#ifdef ZLIB
+		strcat( NGIRCd_ProtoID, "Z" );
+#endif
+		if( Conf_OperCanMode ) strcat( NGIRCd_ProtoID, "o" );
+#else
+		snprintf( NGIRCd_ProtoID, sizeof NGIRCd_ProtoID, "%s%s %s|%s", PROTOVER, PROTOIRC, PACKAGE_NAME, PACKAGE_VERSION );
+#endif
+		strlcat( NGIRCd_ProtoID, " P", sizeof NGIRCd_ProtoID );
+#ifdef ZLIB
+		strlcat( NGIRCd_ProtoID, "Z", sizeof NGIRCd_ProtoID );
+#endif
+		Log( LOG_DEBUG, "Protocol and server ID is \"%s\".", NGIRCd_ProtoID );
+
+		/* Vordefinierte Channels anlegen */
+		Channel_InitPredefined( );
+
+		/* Listen-Ports initialisieren */
+		if( Conn_InitListeners( ) < 1 )
+		{
+			Log( LOG_ALERT, "Server isn't listening on a single port!" );
+			Log( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME );
+			Pidfile_Delete( );
+			exit( 1 );
+		}
+		
+		/* Hauptschleife */
+		Conn_Handler( );
+
+		/* Alles abmelden */
+		Conn_Exit( );
+#ifdef RENDEZVOUS
+		Rendezvous_Exit( );
+#endif
+		Client_Exit( );
+		Channel_Exit( );
+		Lists_Exit( );
+		Log_Exit( );
+	}
+	Pidfile_Delete( );
+
+	return 0;
+} /* main */
+
+
+/**
+ * Generate ngIRCd "version string".
+ * This string is generated once and then stored in NGIRCd_Version for
+ * further usage, for example by the IRC command VERSION and the --version
+ * command line switch.
+ */
+LOCAL void
+Fill_Version( void )
+{
+	NGIRCd_VersionAddition[0] = '\0';
+
+#ifdef SYSLOG
+	strlcpy( NGIRCd_VersionAddition, "SYSLOG", sizeof NGIRCd_VersionAddition );
+#endif
+#ifdef ZLIB
+	if( NGIRCd_VersionAddition[0] )
+		strlcat( NGIRCd_VersionAddition, "+", sizeof NGIRCd_VersionAddition );
+
+	strlcat( NGIRCd_VersionAddition, "ZLIB", sizeof NGIRCd_VersionAddition );
+#endif
+#ifdef TCPWRAP
+	if( NGIRCd_VersionAddition[0] )
+			strlcat( NGIRCd_VersionAddition, "+", sizeof NGIRCd_VersionAddition );
+
+	strlcat( NGIRCd_VersionAddition, "TCPWRAP", sizeof NGIRCd_VersionAddition );
+#endif
+#ifdef RENDEZVOUS
+	if( NGIRCd_VersionAddition[0] )
+		strlcat( NGIRCd_VersionAddition, "+", sizeof NGIRCd_VersionAddition );
+
+	strlcat( NGIRCd_VersionAddition, "RENDEZVOUS", sizeof NGIRCd_VersionAddition );
+#endif
+#ifdef IDENTAUTH
+	if( NGIRCd_VersionAddition[0] )
+		strlcat( NGIRCd_VersionAddition, "+", sizeof NGIRCd_VersionAddition );
+
+	strlcat( NGIRCd_VersionAddition, "IDENT", sizeof NGIRCd_VersionAddition );
+#endif
+#ifdef DEBUG
+	if( NGIRCd_VersionAddition[0] )
+		strlcat( NGIRCd_VersionAddition, "+", sizeof NGIRCd_VersionAddition );
+
+	strlcat( NGIRCd_VersionAddition, "DEBUG", sizeof NGIRCd_VersionAddition );
+#endif
+#ifdef SNIFFER
+	if( NGIRCd_VersionAddition[0] )
+		strlcat( NGIRCd_VersionAddition, "+", sizeof NGIRCd_VersionAddition );
+
+	strlcat( NGIRCd_VersionAddition, "SNIFFER", sizeof NGIRCd_VersionAddition );
+#endif
+#ifdef STRICT_RFC
+	if( NGIRCd_VersionAddition[0] )
+		strlcat( NGIRCd_VersionAddition, "+", sizeof NGIRCd_VersionAddition );
+
+	strlcat( NGIRCd_VersionAddition, "RFC", sizeof NGIRCd_VersionAddition );
+#endif
+#ifdef IRCPLUS
+	if( NGIRCd_VersionAddition[0] )
+		strlcat( NGIRCd_VersionAddition, "+", sizeof NGIRCd_VersionAddition );
+
+	strlcat( NGIRCd_VersionAddition, "IRCPLUS", sizeof NGIRCd_VersionAddition );
+#endif
+
+	if( NGIRCd_VersionAddition[0] )
+		strlcat( NGIRCd_VersionAddition, "-", sizeof( NGIRCd_VersionAddition ));
+
+	strlcat( NGIRCd_VersionAddition, TARGET_CPU, sizeof( NGIRCd_VersionAddition ));
+	strlcat( NGIRCd_VersionAddition, "/", sizeof( NGIRCd_VersionAddition ));
+	strlcat( NGIRCd_VersionAddition, TARGET_VENDOR, sizeof( NGIRCd_VersionAddition ));
+	strlcat( NGIRCd_VersionAddition, "/", sizeof( NGIRCd_VersionAddition ));
+	strlcat( NGIRCd_VersionAddition, TARGET_OS, sizeof( NGIRCd_VersionAddition ));
+
+#ifdef CVSDATE
+	snprintf( NGIRCd_Version, sizeof NGIRCd_Version,"%s %s(%s)-%s", PACKAGE_NAME, PACKAGE_VERSION, CVSDATE, NGIRCd_VersionAddition);
+#else
+	snprintf( NGIRCd_Version, sizeof NGIRCd_Version, "%s %s-%s", PACKAGE_NAME, PACKAGE_VERSION, NGIRCd_VersionAddition);
+#endif
+} /* Fill_Version */
+
+
+/**
+ * Reload the server configuration file.
+ */
+GLOBAL void
+NGIRCd_Rehash( void )
+{
+	char old_name[CLIENT_ID_LEN];
+
+	Log( LOG_NOTICE|LOG_snotice, "Re-reading configuration NOW!" );
+	NGIRCd_SignalRehash = false;
+
+	/* Close down all listening sockets */
+	Conn_ExitListeners( );
+
+	/* Remember old server name */
+	strlcpy( old_name, Conf_ServerName, sizeof old_name );
+
+	/* Re-read configuration ... */
+	Conf_Rehash( );
+
+	/* Recover old server name: it can't be changed during run-time */
+	if( strcmp( old_name, Conf_ServerName ) != 0 )
+	{
+		strcpy( Conf_ServerName, old_name );
+		Log( LOG_ERR, "Can't change \"ServerName\" on runtime! Ignored new name." );
+	}
+
+	/* Create new pre-defined channels */
+	Channel_InitPredefined( );
+	
+	/* Start listening on sockets */
+	Conn_InitListeners( );
+
+	/* Sync configuration with established connections */
+	Conn_SyncServerStruct( );
+
+	Log( LOG_NOTICE|LOG_snotice, "Re-reading of configuration done." );
+} /* NGIRCd_Rehash */
+
+
+/**
+ * Initialize the signal handler.
+ */
+LOCAL void
+Initialize_Signal_Handler( void )
+{
+	/* Signal-Handler initialisieren: einige Signale
+	 * werden ignoriert, andere speziell behandelt. */
+
+#ifdef HAVE_SIGACTION
+	/* sigaction() ist vorhanden */
+
+	struct sigaction saction;
+
+	/* Signal-Struktur initialisieren */
+	memset( &saction, 0, sizeof( saction ));
+	saction.sa_handler = Signal_Handler;
+#ifdef SA_RESTART
+	saction.sa_flags |= SA_RESTART;
+#endif
+#ifdef SA_NOCLDWAIT
+	saction.sa_flags |= SA_NOCLDWAIT;
+#endif
+
+	/* Signal-Handler einhaengen */
+	sigaction( SIGINT, &saction, NULL );
+	sigaction( SIGQUIT, &saction, NULL );
+	sigaction( SIGTERM, &saction, NULL);
+	sigaction( SIGHUP, &saction, NULL);
+	sigaction( SIGCHLD, &saction, NULL);
+
+	/* einige Signale ignorieren */
+	saction.sa_handler = SIG_IGN;
+	sigaction( SIGPIPE, &saction, NULL );
+#else
+	/* kein sigaction() vorhanden */
+
+	/* Signal-Handler einhaengen */
+	signal( SIGINT, Signal_Handler );
+	signal( SIGQUIT, Signal_Handler );
+	signal( SIGTERM, Signal_Handler );
+	signal( SIGHUP, Signal_Handler );
+	signal( SIGCHLD, Signal_Handler );
+
+	/* einige Signale ignorieren */
+	signal( SIGPIPE, SIG_IGN );
+#endif
+} /* Initialize_Signal_Handler */
+
+
+/**
+ * Signal handler of ngIRCd.
+ * This function is called whenever ngIRCd catches a signal sent by the
+ * user and/or the system to it. For example SIGTERM and SIGHUP.
+ * @param Signal Number of the signal to handle.
+ */
+LOCAL void
+Signal_Handler( int Signal )
+{
+	switch( Signal )
+	{
+		case SIGTERM:
+		case SIGINT:
+		case SIGQUIT:
+			/* wir soll(t)en uns wohl beenden ... */
+			NGIRCd_SignalQuit = true;
+			break;
+		case SIGHUP:
+			/* Konfiguration neu einlesen: */
+			NGIRCd_SignalRehash = true;
+			break;
+		case SIGCHLD:
+			/* Child-Prozess wurde beendet. Zombies vermeiden: */
+			while( waitpid( -1, NULL, WNOHANG ) > 0);
+			break;
+#ifdef DEBUG
+		default:
+			/* unbekanntes bzw. unbehandeltes Signal */
+			Log( LOG_DEBUG, "Got signal %d! Ignored.", Signal );
+#endif
+	}
+} /* Signal_Handler */
+
+
+/**
+ * Display copyright and version information of ngIRCd on the console.
+ */
+LOCAL void
+Show_Version( void )
+{
+	puts( NGIRCd_Version );
+	puts( "Copyright (c)2001-2005 by Alexander Barton (<alex@barton.de>)." );
+	puts( "Homepage: <http://arthur.ath.cx/~alex/ngircd/>\n" );
+	puts( "This is free software; see the source for copying conditions. There is NO" );
+	puts( "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." );
+} /* Show_Version */
+
+
+/**
+ * Display a short help text on the console.
+ * This help depends on the configuration of the executable and only shows
+ * options that are actually enabled.
+ */
+LOCAL void
+Show_Help( void )
+{
+#ifdef DEBUG
+	puts( "  -d, --debug        log extra debug messages" );
+#endif
+	puts( "  -f, --config <f>   use file <f> as configuration file" );
+	puts( "  -n, --nodaemon     don't fork and don't detach from controlling terminal" );
+	puts( "  -p, --passive      disable automatic connections to other servers" );
+#ifdef SNIFFER
+	puts( "  -s, --sniffer      enable network sniffer and display all IRC traffic" );
+#endif
+	puts( "  -t, --configtest   read, validate and display configuration; then exit" );
+ 	puts( "      --version      output version information and exit" );
+	puts( "      --help         display this help and exit" );
+} /* Show_Help */
+
+
+/**
+ * Delete the file containing the process ID (PID).
+ */
+LOCAL void
+Pidfile_Delete( void )
+{
+	/* Pidfile configured? */
+	if( ! Conf_PidFile[0] ) return;
+
+#ifdef DEBUG
+	Log( LOG_DEBUG, "Removing PID file (%s) ...", Conf_PidFile );
+#endif
+
+	if( unlink( Conf_PidFile ))
+		Log( LOG_ERR, "Error unlinking PID file (%s): %s", Conf_PidFile, strerror( errno ));
+} /* Pidfile_Delete */
+
+
+/**
+ * Create the file containing the process ID of ngIRCd ("PID file").
+ * @param pid The process ID to be stored in this file.
+ */
+LOCAL void
+Pidfile_Create( long pid )
+{
+	int pidfd;
+	char pidbuf[64];
+	int len;
+
+	/* Pidfile configured? */
+	if( ! Conf_PidFile[0] ) return;
+
+#ifdef DEBUG
+	Log( LOG_DEBUG, "Creating PID file (%s) ...", Conf_PidFile );
+#endif
+
+	pidfd = open( Conf_PidFile, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+	if ( pidfd < 0 ) {
+		Log( LOG_ERR, "Error writing PID file (%s): %s", Conf_PidFile, strerror( errno ));
+		return;
+	}
+
+	len = snprintf( pidbuf, sizeof pidbuf, "%ld\n", pid );
+	if (len < 0|| len < (int)sizeof pid) {
+		Log( LOG_ERR, "Error converting pid");
+		return;
+	}
+	
+	if( write( pidfd, pidbuf, len) != len)
+		Log( LOG_ERR, "Can't write PID file (%s): %s", Conf_PidFile, strerror( errno ));
+
+	if( close(pidfd) != 0 )
+		Log( LOG_ERR, "Error closing PID file (%s): %s", Conf_PidFile, strerror( errno ));
+} /* Pidfile_Create */
+
+
+/**
+ * Redirect stdin, stdout and stderr to apropriate file handles.
+ */
+LOCAL void
+Setup_FDStreams( void )
+{
+	int fd;
+
+	/* Test if we can open /dev/null for reading and writing. If not
+	 * we are most probably chrooted already and the server has been
+	 * restarted. So we simply don't try to redirect stdXXX ... */
+	fd = open( "/dev/null", O_RDWR );
+	if ( fd < 0 ) {
+		Log(LOG_WARNING, "Could not open /dev/null: %s", strerror(errno));	
+		return;
+	} 
+
+	fflush(stdout);
+	fflush(stderr);
+
+	/* Create new stdin(0), stdout(1) and stderr(2) descriptors */
+	dup2( fd, 0 ); dup2( fd, 1 ); dup2( fd, 2 );
+
+	/* Close newly opened file descriptor if not stdin/out/err */
+	if( fd > 2 ) close( fd );
+} /* Setup_FDStreams */
+
+
+LOCAL bool
+NGIRCd_getNobodyID(unsigned int *uid, unsigned int *gid )
+{
+	struct passwd *pwd;
+
+	pwd = getpwnam("nobody");
+	if (!pwd) return false;
+
+	if ( !pwd->pw_uid || !pwd->pw_gid)
+		return false;
+
+	*uid = pwd->pw_uid;	
+	*gid = pwd->pw_gid;
+	endpwent();
+
+	return true;	
+}
+
+
+LOCAL bool
+NGIRCd_Init( bool NGIRCd_NoDaemon ) 
+{
+	static bool initialized;
+	bool chrooted = false;
+	struct passwd *pwd;
+	struct group *grp;
+	int real_errno;
+	long pid;
+
+	if (initialized)
+		return true;
+
+	if( Conf_Chroot[0] ) {
+		if( chdir( Conf_Chroot ) != 0 ) {
+			Log( LOG_ERR, "Can't chdir() in ChrootDir (%s): %s", Conf_Chroot, strerror( errno ));
+			return false;
+		}
+
+		if( chroot( Conf_Chroot ) != 0 ) {
+			if (errno != EPERM) {
+				Log( LOG_ERR, "Can't change root directory to \"%s\": %s",
+								Conf_Chroot, strerror( errno ));
+
+				return false;
+			}
+		} else {
+			chrooted = true;
+			Log( LOG_INFO, "Changed root and working directory to \"%s\".", Conf_Chroot );
+		}
+	}
+
+	if (Conf_UID == 0) {
+		Log(LOG_INFO, "ServerUID must not be 0, using \"nobody\" instead.", Conf_UID);
+
+  		if (! NGIRCd_getNobodyID(&Conf_UID, &Conf_GID)) {
+			Log(LOG_WARNING, "Could not get user/group ID of user \"nobody\": %s",
+					errno ? strerror(errno) : "not found" );
+			return false;
+		}
+	}
+
+	if (getgid() != Conf_GID) {
+		/* Change group ID */
+		if (setgid(Conf_GID) != 0) {
+			real_errno = errno;
+			Log( LOG_ERR, "Can't change group ID to %u: %s", Conf_GID, strerror( errno ));
+			if (real_errno != EPERM) 
+				return false;
+		}
+	}
+
+	if (getuid() != Conf_UID) {
+		/* Change user ID */
+		if (setuid(Conf_UID) != 0) {
+			real_errno = errno;
+			Log(LOG_ERR, "Can't change user ID to %u: %s", Conf_UID, strerror(errno));
+			if (real_errno != EPERM) 
+				return false;
+		}
+	}
+
+	initialized = true;
+
+	/* Normally a child process is forked which isn't any longer
+	 * connected to ther controlling terminal. Use "--nodaemon"
+	 * to disable this "daemon mode" (useful for debugging). */
+	if ( ! NGIRCd_NoDaemon ) {
+		pid = (long)fork( );
+		if( pid > 0 ) {
+			/* "Old" process: exit. */
+			exit( 0 );
+		}
+		if( pid < 0 ) {
+			/* Error!? */
+			fprintf( stderr, "%s: Can't fork: %s!\nFatal error, exiting now ...\n",
+								PACKAGE_NAME, strerror( errno ));
+			exit( 1 );
+		}
+
+		/* New child process */
+		(void)setsid( );
+		chdir( "/" );
+
+		/* Detach stdin, stdout and stderr */
+		Setup_FDStreams( );
+	}
+	pid = getpid();
+
+	Pidfile_Create( pid );
+
+	/* Check UID/GID we are running as, can be different from values
+	 * configured (e. g. if we were already started with a UID>0. */
+	Conf_UID = getuid();
+	Conf_GID = getgid();
+
+	pwd = getpwuid( Conf_UID );
+	grp = getgrgid( Conf_GID );
+
+	Log( LOG_INFO, "Running as user %s(%ld), group %s(%ld), with PID %ld.",
+				pwd ? pwd->pw_name : "unknown", Conf_UID,
+				grp ? grp->gr_name : "unknown", Conf_GID, pid);
+
+	if ( chrooted ) {
+		Log( LOG_INFO, "Running chrooted, chrootdir \"%s\".",  Conf_Chroot );
+		return true;
+	} else {
+		Log( LOG_INFO, "Not running chrooted." );
+	}
+
+	/* Change working directory to home directory of the user
+	 * we are running as (only when running in daemon mode and not in chroot) */
+	
+	if ( pwd ) {
+		if (!NGIRCd_NoDaemon ) {
+			if( chdir( pwd->pw_dir ) == 0 ) 
+				Log( LOG_DEBUG, "Changed working directory to \"%s\" ...", pwd->pw_dir );
+			else 
+				Log( LOG_ERR, "Can't change working directory to \"%s\": %s",
+								pwd->pw_dir, strerror( errno ));
+		}
+	} else {
+		Log( LOG_ERR, "Can't get user informaton for UID %d!?", Conf_UID );
+	}
+
+return true;
+}
+
+/* -eof- */

+ 57 - 0
src/ngircd/ngircd.h

@@ -0,0 +1,57 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * $Id: ngircd.h,v 1.22 2005/06/24 19:20:56 fw Exp $
+ *
+ * Prototypes of the "main module".
+ */
+
+
+#ifndef __ngircd_h__
+#define __ngircd_h__
+
+#include <time.h>
+
+#include "defines.h"
+
+
+GLOBAL time_t NGIRCd_Start;		/* Startzeitpunkt des Daemon */
+GLOBAL char NGIRCd_StartStr[64];
+GLOBAL char NGIRCd_Version[126];
+GLOBAL char NGIRCd_VersionAddition[126];
+
+#ifdef DEBUG
+GLOBAL bool NGIRCd_Debug;		/* Debug-Modus aktivieren */
+#endif
+
+#ifdef SNIFFER
+GLOBAL bool NGIRCd_Sniffer;		/* Sniffer aktivieren */
+#endif
+
+GLOBAL bool NGIRCd_Passive;		/* nicht zu anderen Servern connecten */
+
+GLOBAL bool NGIRCd_SignalQuit;	/* true: quit server*/
+GLOBAL bool NGIRCd_SignalRestart;	/* true: restart server */
+GLOBAL bool NGIRCd_SignalRehash;	/* true: reload configuration */
+
+GLOBAL char NGIRCd_DebugLevel[2];	/* Debug-Level fuer IRC_VERSION() */
+
+GLOBAL char NGIRCd_ConfFile[FNAME_LEN];	/* Konfigurationsdatei */
+
+GLOBAL char NGIRCd_ProtoID[COMMAND_LEN];/* Protokoll- und Server-Identifikation */
+
+
+GLOBAL void NGIRCd_Rehash PARAMS(( void ));
+
+
+#endif
+
+
+/* -eof- */

+ 456 - 0
src/ngircd/parse.c

@@ -0,0 +1,456 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ */
+
+
+#include "portab.h"
+
+static char UNUSED id[] = "$Id: parse.c,v 1.63.2.1 2005/07/24 21:06:51 alex Exp $";
+
+/**
+ * @file
+ * IRC command parser and validator.
+ */
+
+#include "imp.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+
+#include "ngircd.h"
+#include "defines.h"
+#include "conn-func.h"
+#include "client.h"
+#include "channel.h"
+#include "log.h"
+#include "messages.h"
+#include "tool.h"
+
+#include "exp.h"
+#include "parse.h"
+
+#include "imp.h"
+#include "irc.h"
+#include "irc-channel.h"
+#include "irc-info.h"
+#include "irc-login.h"
+#include "irc-mode.h"
+#include "irc-op.h"
+#include "irc-oper.h"
+#include "irc-server.h"
+#include "irc-write.h"
+
+#include "exp.h"
+
+
+COMMAND My_Commands[] =
+{
+	{ "ADMIN", IRC_ADMIN, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
+	{ "AWAY", IRC_AWAY, CLIENT_USER, 0, 0, 0 },
+	{ "CONNECT", IRC_CONNECT, CLIENT_USER, 0, 0, 0 },
+	{ "DIE", IRC_DIE, CLIENT_USER, 0, 0, 0 },
+	{ "DISCONNECT", IRC_DISCONNECT, CLIENT_USER, 0, 0, 0 },
+	{ "ERROR", IRC_ERROR, 0xFFFF, 0, 0, 0 },
+	{ "HELP", IRC_HELP, CLIENT_USER, 0, 0, 0 },
+	{ "INVITE", IRC_INVITE, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
+	{ "ISON", IRC_ISON, CLIENT_USER, 0, 0, 0 },
+	{ "JOIN", IRC_JOIN, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
+	{ "KICK", IRC_KICK, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
+	{ "KILL", IRC_KILL, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
+	{ "LINKS", IRC_LINKS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
+	{ "LIST", IRC_LIST, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
+	{ "LUSERS", IRC_LUSERS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
+	{ "MODE", IRC_MODE, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
+	{ "MOTD", IRC_MOTD, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
+	{ "NAMES", IRC_NAMES, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
+	{ "NICK", IRC_NICK, 0xFFFF, 0, 0, 0 },
+	{ "NJOIN", IRC_NJOIN, CLIENT_SERVER, 0, 0, 0 },
+	{ "NOTICE", IRC_NOTICE, 0xFFFF, 0, 0, 0 },
+	{ "OPER", IRC_OPER, CLIENT_USER, 0, 0, 0 },
+	{ "PART", IRC_PART, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
+	{ "PASS", IRC_PASS, 0xFFFF, 0, 0, 0 },
+	{ "PING", IRC_PING, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
+	{ "PONG", IRC_PONG, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
+	{ "PRIVMSG", IRC_PRIVMSG, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
+	{ "QUIT", IRC_QUIT, 0xFFFF, 0, 0, 0 },
+	{ "REHASH", IRC_REHASH, CLIENT_USER, 0, 0, 0 },
+	{ "RESTART", IRC_RESTART, CLIENT_USER, 0, 0, 0 },
+	{ "SERVER", IRC_SERVER, 0xFFFF, 0, 0, 0 },
+	{ "SQUIT", IRC_SQUIT, CLIENT_SERVER, 0, 0, 0 },
+	{ "STATS", IRC_STATS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
+	{ "TIME", IRC_TIME, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
+	{ "TOPIC", IRC_TOPIC, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
+	{ "TRACE", IRC_TRACE, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
+	{ "USER", IRC_USER, 0xFFFF, 0, 0, 0 },
+	{ "USERHOST", IRC_USERHOST, CLIENT_USER, 0, 0, 0 },
+	{ "VERSION", IRC_VERSION, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
+	{ "WHO", IRC_WHO, CLIENT_USER, 0, 0, 0 },
+	{ "WHOIS", IRC_WHOIS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
+	{ "WHOWAS", IRC_WHOWAS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
+#ifdef IRCPLUS
+	{ "CHANINFO", IRC_CHANINFO, CLIENT_SERVER, 0, 0, 0 },
+#endif
+	{ NULL, NULL, 0x0, 0, 0, 0 } /* Ende-Marke */
+};
+
+
+LOCAL void Init_Request PARAMS(( REQUEST *Req ));
+
+LOCAL bool Validate_Prefix PARAMS(( CONN_ID Idx, REQUEST *Req, bool *Closed ));
+LOCAL bool Validate_Command PARAMS(( CONN_ID Idx, REQUEST *Req, bool *Closed ));
+LOCAL bool Validate_Args PARAMS(( CONN_ID Idx, REQUEST *Req, bool *Closed ));
+
+LOCAL bool Handle_Request PARAMS(( CONN_ID Idx, REQUEST *Req ));
+
+
+/**
+ * Return the pointer to the global "IRC command structure".
+ * This structure, an array of type "COMMAND" describes all the IRC commands
+ * implemented by ngIRCd and how to handle them.
+ * @return Pointer to the global command structure.
+ */
+GLOBAL COMMAND *
+Parse_GetCommandStruct( void )
+{
+	return My_Commands;
+} /* Parse_GetCommandStruct */
+
+
+/**
+ * Parse a command ("request") received from a client.
+ * 
+ * This function is called after the connection layer received a valid CR+LF
+ * terminated line of text: we asume that this is a valid IRC command and
+ * try to do something useful with it :-)
+ *
+ * All errors are reported to the client from which the command has been
+ * received, and if the error is fatal this connection is closed down.
+ *
+ * This function is able to parse the syntax as described in RFC 2812,
+ * section 2.3.
+ *
+ * @param Idx Index of the connection from which the command has been received.
+ * @param Request NULL terminated line of text (the "command").
+ * @return true on success (valid command or "regular" error), false if a
+ * 	fatal error occured and the connection has been shut down.
+ */
+GLOBAL bool
+Parse_Request( CONN_ID Idx, char *Request )
+{
+	REQUEST req;
+	char *start, *ptr;
+	bool closed;
+
+	assert( Idx >= 0 );
+	assert( Request != NULL );
+
+#ifdef SNIFFER
+	if( NGIRCd_Sniffer ) Log( LOG_DEBUG, " <- connection %d: '%s'.", Idx, Request );
+#endif
+
+	Init_Request( &req );
+
+	/* Fuehrendes und folgendes "Geraffel" verwerfen */
+	ngt_TrimStr( Request );
+
+	/* gibt es ein Prefix? */
+	if( Request[0] == ':' )
+	{
+		/* Prefix vorhanden */
+		req.prefix = Request + 1;
+		ptr = strchr( Request, ' ' );
+		if( ! ptr )
+		{
+			Log( LOG_DEBUG, "Connection %d: Parse error: prefix without command!?", Idx );
+			return Conn_WriteStr( Idx, "ERROR :Prefix without command!?" );
+		}
+		*ptr = '\0';
+#ifndef STRICT_RFC
+		/* multiple Leerzeichen als Trenner zwischen
+		 * Prefix und Befehl ignorieren */
+		while( *(ptr + 1) == ' ' ) ptr++;
+#endif
+		start = ptr + 1;
+	}
+	else start = Request;
+
+	/* Befehl */
+	ptr = strchr( start, ' ' );
+	if( ptr )
+	{
+		*ptr = '\0';
+#ifndef STRICT_RFC
+		/* multiple Leerzeichen als Trenner vor
+		 * Parametern ignorieren */
+		while( *(ptr + 1) == ' ' ) ptr++;
+#endif
+	}
+	req.command = start;
+
+	/* Argumente, Parameter */
+	if( ptr )
+	{
+		/* Prinzipiell gibt es welche :-) */
+		start = ptr + 1;
+		while( start )
+		{
+			/* Parameter-String "zerlegen" */
+			if( start[0] == ':' )
+			{
+				req.argv[req.argc] = start + 1;
+				ptr = NULL;
+			}
+			else
+			{
+				req.argv[req.argc] = start;
+				ptr = strchr( start, ' ' );
+				if( ptr )
+				{
+					*ptr = '\0';
+#ifndef STRICT_RFC
+					/* multiple Leerzeichen als
+					 * Parametertrenner ignorieren */
+					while( *(ptr + 1) == ' ' ) ptr++;
+#endif
+				}
+			}
+
+			req.argc++;
+
+			if( start[0] == ':' ) break;
+			if( req.argc > 14 ) break;
+
+			if( ptr ) start = ptr + 1;
+			else start = NULL;
+		}
+	}
+
+	/* Daten validieren */
+	if( ! Validate_Prefix( Idx, &req, &closed )) return ! closed;
+	if( ! Validate_Command( Idx, &req, &closed )) return ! closed;
+	if( ! Validate_Args( Idx, &req, &closed )) return ! closed;
+
+	return Handle_Request( Idx, &req );
+} /* Parse_Request */
+
+
+/**
+ * Initialize request structure.
+ * @param Req Request structure to be initialized.
+ */
+LOCAL void
+Init_Request( REQUEST *Req )
+{
+	/* Neue Request-Struktur initialisieren */
+
+	int i;
+
+	assert( Req != NULL );
+
+	Req->prefix = NULL;
+	Req->command = NULL;
+	for( i = 0; i < 15; Req->argv[i++] = NULL );
+	Req->argc = 0;
+} /* Init_Request */
+
+
+LOCAL bool
+Validate_Prefix( CONN_ID Idx, REQUEST *Req, bool *Closed )
+{
+	CLIENT *client, *c;
+
+	assert( Idx >= 0 );
+	assert( Req != NULL );
+
+	*Closed = false;
+
+	/* ist ueberhaupt ein Prefix vorhanden? */
+	if( ! Req->prefix ) return true;
+
+	/* Client-Struktur der Connection ermitteln */
+	client = Client_GetFromConn( Idx );
+	assert( client != NULL );
+
+	/* nur validieren, wenn bereits registrierte Verbindung */
+	if(( Client_Type( client ) != CLIENT_USER ) && ( Client_Type( client ) != CLIENT_SERVER ) && ( Client_Type( client ) != CLIENT_SERVICE ))
+	{
+		/* noch nicht registrierte Verbindung.
+		 * Das Prefix wird ignoriert. */
+		Req->prefix = NULL;
+		return true;
+	}
+
+	/* pruefen, ob der im Prefix angegebene Client bekannt ist */
+	c = Client_Search( Req->prefix );
+	if( ! c )
+	{
+		/* im Prefix angegebener Client ist nicht bekannt */
+		Log( LOG_ERR, "Invalid prefix \"%s\", client not known (connection %d, command %s)!?", Req->prefix, Idx, Req->command );
+		if( ! Conn_WriteStr( Idx, "ERROR :Invalid prefix \"%s\", client not known!?", Req->prefix )) *Closed = true;
+		return false;
+	}
+
+	/* pruefen, ob der Client mit dem angegebenen Prefix in Richtung
+	 * des Senders liegt, d.h. sicherstellen, dass das Prefix nicht
+	 * gefaelscht ist */
+	if( Client_NextHop( c ) != client )
+	{
+		/* das angegebene Prefix ist aus dieser Richtung, also
+		 * aus der gegebenen Connection, ungueltig! */
+		Log( LOG_ERR, "Spoofed prefix \"%s\" from \"%s\" (connection %d, command %s)!", Req->prefix, Client_Mask( Client_GetFromConn( Idx )), Idx, Req->command );
+		Conn_Close( Idx, NULL, "Spoofed prefix", true);
+		*Closed = true;
+		return false;
+	}
+
+	return true;
+} /* Validate_Prefix */
+
+
+LOCAL bool
+Validate_Command( UNUSED CONN_ID Idx, UNUSED REQUEST *Req, bool *Closed )
+{
+	assert( Idx >= 0 );
+	assert( Req != NULL );
+	*Closed = false;
+
+	return true;
+} /* Validate_Comman */
+
+
+LOCAL bool
+Validate_Args( UNUSED CONN_ID Idx, UNUSED REQUEST *Req, bool *Closed )
+{
+	assert( Idx >= 0 );
+	assert( Req != NULL );
+	*Closed = false;
+
+	return true;
+} /* Validate_Args */
+
+
+LOCAL bool
+Handle_Request( CONN_ID Idx, REQUEST *Req )
+{
+	/* Client-Request verarbeiten. Bei einem schwerwiegenden Fehler
+	 * wird die Verbindung geschlossen und false geliefert. */
+
+	CLIENT *client, *target, *prefix;
+	char str[LINE_LEN];
+	bool result;
+	COMMAND *cmd;
+	int i;
+
+	assert( Idx >= 0 );
+	assert( Req != NULL );
+	assert( Req->command != NULL );
+
+	client = Client_GetFromConn( Idx );
+	assert( client != NULL );
+
+	/* Statuscode? */
+	if(( Client_Type( client ) == CLIENT_SERVER ) && ( strlen( Req->command ) == 3 ) && ( atoi( Req->command ) > 100 ))
+	{
+		/* Command is a status code from an other server */
+
+		/* Determine target */
+		if( Req->argc > 0 ) target = Client_Search( Req->argv[0] );
+		else target = NULL;
+		if( ! target )
+		{
+			/* Status code without target!? */
+			if( Req->argc > 0 ) Log( LOG_WARNING, "Unknown target for status code %s: \"%s\"", Req->command, Req->argv[0] );
+			else Log( LOG_WARNING, "Unknown target for status code %s!", Req->command );
+			return true;
+		}
+		if( target == Client_ThisServer( ))
+		{
+			/* This server is the target, ignore it */
+			Log( LOG_DEBUG, "Ignored status code %s from \"%s\".", Req->command, Client_ID( client ));
+			return true;
+		}
+
+		/* Determine source */
+		if( ! Req->prefix[0] )
+		{
+			/* Oops, no prefix!? */
+			Log( LOG_WARNING, "Got status code %s from \"%s\" without prefix!?", Req->command, Client_ID( client ));
+			return true;
+		}
+		else prefix = Client_Search( Req->prefix );
+		if( ! prefix )
+		{
+			/* Oops, unknown prefix!? */
+			Log( LOG_WARNING, "Got status code %s from unknown source: \"%s\"", Req->command, Req->prefix );
+			return true;
+		}
+
+		/* Forward status code */
+		strlcpy( str, Req->command, sizeof( str ));
+		for( i = 0; i < Req->argc; i++ )
+		{
+			if( i < Req->argc - 1 ) strlcat( str, " ", sizeof( str ));
+			else strlcat( str, " :", sizeof( str ));
+			strlcat( str, Req->argv[i], sizeof( str ));
+		}
+		return IRC_WriteStrClientPrefix( target, prefix, "%s", str );
+	}
+
+	cmd = My_Commands;
+	while( cmd->name )
+	{
+		/* Befehl suchen */
+		if( strcasecmp( Req->command, cmd->name ) != 0 )
+		{
+			cmd++; continue;
+		}
+
+		if( Client_Type( client ) & cmd->type )
+		{
+			/* Command is allowed for this client: call it and count produced bytes */
+			Conn_ResetWCounter( );
+			result = (cmd->function)( client, Req );
+			cmd->bytes += Conn_WCounter( );
+
+			/* Adjust counters */
+			if( Client_Type( client ) != CLIENT_SERVER ) cmd->lcount++;
+			else cmd->rcount++;
+
+			return result;
+		}
+		else
+		{
+			/* Befehl ist fuer diesen Client-Typ nicht erlaubt! */
+			return IRC_WriteStrClient( client, ERR_NOTREGISTERED_MSG, Client_ID( client ));
+		}
+	}
+
+	if( Client_Type( client ) != CLIENT_USER &&
+	    Client_Type( client ) != CLIENT_SERVER &&
+	    Client_Type( client ) != CLIENT_SERVICE )
+		return true;
+	
+	/* Unknown command and registered connection: generate error: */
+	Log( LOG_DEBUG, "Connection %d: Unknown command \"%s\", %d %s,%s prefix.",
+			Client_Conn( client ), Req->command, Req->argc,
+			Req->argc == 1 ? "parameter" : "parameters",
+			Req->prefix ? "" : " no" );
+
+	if( Client_Type( client ) != CLIENT_SERVER )
+		return IRC_WriteStrClient( client, ERR_UNKNOWNCOMMAND_MSG,
+				Client_ID( client ), Req->command );
+
+	return true;
+} /* Handle_Request */
+
+
+/* -eof- */

+ 49 - 0
src/ngircd/parse.h

@@ -0,0 +1,49 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * $Id: parse.h,v 1.11 2005/03/19 18:43:49 fw Exp $
+ *
+ * IRC command parser and validator (header)
+ */
+
+
+#ifndef __parse_h__
+#define __parse_h__
+
+#include "portab.h"
+
+typedef struct _REQUEST			/* vgl. RFC 2812, 2.3 */
+{
+	char *prefix;			/* Prefix */
+	char *command;			/* IRC-Befehl */
+	char *argv[15];			/* Parameter (max. 15: 0..14) */
+	int argc;			/* Anzahl vorhandener Parameter */
+} REQUEST;
+
+
+typedef struct _COMMAND
+{
+	char *name;			/* command name */
+	bool (*function) PARAMS(( CLIENT *Client, REQUEST *Request ));
+	CLIENT_TYPE type;		/* valid client types (bit mask) */
+	long lcount, rcount;	/* number of local and remote calls */
+	long bytes;		/* number of bytes created */
+} COMMAND;
+
+
+GLOBAL bool Parse_Request PARAMS((CONN_ID Idx, char *Request ));
+
+GLOBAL COMMAND *Parse_GetCommandStruct PARAMS(( void ));
+
+
+#endif
+
+
+/* -eof- */

+ 366 - 0
src/ngircd/rendezvous.c

@@ -0,0 +1,366 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001-2004 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * Rendezvous service registration.
+ *
+ * Supported APIs are:
+ *  - Apple Mac OS X
+ *  - Howl
+ */
+
+
+#include "portab.h"
+
+#ifdef RENDEZVOUS
+
+
+static char UNUSED id[] = "$Id: rendezvous.c,v 1.5 2005/03/19 18:43:49 fw Exp $";
+
+#include "imp.h"
+#include <assert.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef HAVE_MACH_PORT_H
+#include "mach/port.h"
+#include "mach/message.h"
+#endif
+
+#ifdef HAVE_DNSSERVICEDISCOVERY_DNSSERVICEDISCOVERY_H
+#include <DNSServiceDiscovery/DNSServiceDiscovery.h>
+#endif
+
+#ifdef HAVE_RENDEZVOUS_RENDEZVOUS_H
+#include <rendezvous/rendezvous.h>
+#endif
+
+#include "defines.h"
+#include "log.h"
+
+#include "exp.h"
+#include "rendezvous.h"
+
+
+#if defined(HAVE_DNSSERVICEREGISTRATIONCREATE)
+#	define APPLE
+#elif defined(HAVE_SW_DISCOVERY_INIT)
+#	define HOWL
+#else
+#	error "Can't detect Rendezvous API!?"
+#endif
+
+
+#define MAX_RENDEZVOUS 1000
+
+typedef struct _service
+{
+	char Desc[CLIENT_ID_LEN];
+#ifdef APPLE
+	dns_service_discovery_ref Discovery_Ref;
+	mach_port_t Mach_Port;
+#endif
+#ifdef HOWL
+	sw_discovery_oid Id;
+#endif
+} SERVICE;
+
+LOCAL SERVICE My_Rendezvous[MAX_RENDEZVOUS];
+
+
+LOCAL void Unregister( int Idx );
+
+
+/* -- Apple API -- */
+
+#ifdef APPLE
+
+#define MAX_MACH_MSG_SIZE 512
+
+LOCAL void Registration_Reply_Handler( DNSServiceRegistrationReplyErrorType ErrCode, void *Context );
+
+#endif /* Apple */
+
+
+/* -- Howl API -- */
+
+#ifdef HOWL
+
+LOCAL sw_discovery My_Discovery_Session = NULL;
+LOCAL sw_salt My_Salt;
+
+LOCAL sw_result HOWL_API Registration_Reply_Handler( sw_discovery Session, sw_discovery_publish_status Status, sw_discovery_oid Id, sw_opaque Extra );
+
+#endif /* Howl */
+
+
+GLOBAL void Rendezvous_Init( void )
+{
+	/* Initialize structures */
+
+	int i;
+
+#ifdef HOWL
+	if( sw_discovery_init( &My_Discovery_Session ) != SW_OKAY )
+	{
+		Log( LOG_EMERG, "Can't initialize Rendezvous (Howl): sw_discovery_init() failed!" );
+		Log( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME );
+		exit( 1 );
+	}
+
+	if( sw_discovery_salt( My_Discovery_Session, &My_Salt ) != SW_OKAY )
+	{
+		Log( LOG_EMERG, "Can't initialize Rendezvous (Howl): sw_discovery_salt() failed!" );
+		Log( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME );
+		exit( 1 );
+	}
+#endif
+
+	for( i = 0; i < MAX_RENDEZVOUS; i++ ) My_Rendezvous[i].Desc[0] = '\0';
+} /* Rendezvous_Init */
+
+
+GLOBAL void Rendezvous_Exit( void )
+{
+	/* Clean up & exit module */
+
+	int i;
+
+	for( i = 0; i < MAX_RENDEZVOUS; i++ )
+	{
+		if( My_Rendezvous[i].Desc[0] ) Unregister( i );
+	}
+
+#ifdef HOWL
+	sw_discovery_fina( My_Discovery_Session );
+#endif
+} /* Rendezvous_Exit */
+
+
+GLOBAL bool Rendezvous_Register( char *Name, char *Type, unsigned int Port )
+{
+	/* Register new service */
+
+	int i;
+
+	/* Search free port structure */
+	for( i = 0; i < MAX_RENDEZVOUS; i++ ) if( ! My_Rendezvous[i].Desc[0] ) break;
+	if( i >= MAX_RENDEZVOUS )
+	{
+		Log( LOG_ERR, "Can't register \"%s\" with Rendezvous: limit (%d) reached!", Name, MAX_RENDEZVOUS );
+		return false;
+	}
+	strlcpy( My_Rendezvous[i].Desc, Name, sizeof( My_Rendezvous[i].Desc ));
+	
+#ifdef APPLE
+	/* Register new service */
+	My_Rendezvous[i].Discovery_Ref = DNSServiceRegistrationCreate( Name, Type, "", htonl( Port ), "", Registration_Reply_Handler, &My_Rendezvous[i] );
+	if( ! My_Rendezvous[i].Discovery_Ref )
+	{
+		Log( LOG_ERR, "Can't register \"%s\" with Rendezvous: can't register service!", My_Rendezvous[i].Desc );
+		My_Rendezvous[i].Desc[0] = '\0';
+		return false;
+	}
+	
+	/* Get and save the corresponding Mach Port */
+	My_Rendezvous[i].Mach_Port = DNSServiceDiscoveryMachPort( My_Rendezvous[i].Discovery_Ref );
+	if( ! My_Rendezvous[i].Mach_Port )
+	{
+		Log( LOG_ERR, "Can't register \"%s\" with Rendezvous: got no Mach Port!", My_Rendezvous[i].Desc );
+		/* Here we actually leek a descriptor :-( */
+		My_Rendezvous[i].Discovery_Ref = 0;
+		My_Rendezvous[i].Desc[0] = '\0';
+		return false;
+	}
+#endif /* Apple */
+
+#ifdef HOWL
+	if( sw_discovery_publish( My_Discovery_Session, 0, Name, Type, NULL, NULL, Port, NULL, 0, Registration_Reply_Handler, &My_Rendezvous[i], &My_Rendezvous[i].Id ) != SW_OKAY )
+	{
+		Log( LOG_ERR, "Can't register \"%s\" with Rendezvous: can't register service!", My_Rendezvous[i].Desc );
+		My_Rendezvous[i].Desc[0] = '\0';
+		return false;
+	}
+#endif /* Howl */
+
+	Log( LOG_DEBUG, "Rendezvous: Registering \"%s\" ...", My_Rendezvous[i].Desc );
+	return true;
+} /* Rendezvous_Register */
+
+
+GLOBAL bool Rendezvous_Unregister( char *Name )
+{
+	/* Unregister service from rendezvous */
+
+	int i;
+	bool ok;
+
+	ok = false;
+	for( i = 0; i < MAX_RENDEZVOUS; i++ )
+	{
+		if( strcmp( Name, My_Rendezvous[i].Desc ) == 0 )
+		{
+			Unregister( i );
+			ok = true;
+		}
+	}
+
+	return ok;
+} /* Rendezvous_Unregister */
+
+
+GLOBAL void Rendezvous_UnregisterListeners( void )
+{
+	/* Unregister all our listening sockets from Rendezvous */
+
+	int i;
+
+	for( i = 0; i < MAX_RENDEZVOUS; i++ )
+	{
+		if( My_Rendezvous[i].Desc[0] ) Unregister( i );
+	}
+} /* Rendezvous_UnregisterListeners */
+
+
+GLOBAL void Rendezvous_Handler( void )
+{
+	/* Handle all Rendezvous stuff; this function must be called
+	 * periodically from the run loop of the main program */
+
+#ifdef APPLE
+	int i;
+	char buffer[MAX_MACH_MSG_SIZE];
+	mach_msg_return_t result;
+	mach_msg_header_t *msg;
+
+	for( i = 0; i < MAX_RENDEZVOUS; i++ )
+	{
+		if( ! My_Rendezvous[i].Discovery_Ref ) continue;
+
+		/* Read message from Mach Port */
+		msg = (mach_msg_header_t *)buffer;
+		result = mach_msg( msg, MACH_RCV_MSG|MACH_RCV_TIMEOUT, 0, MAX_MACH_MSG_SIZE, My_Rendezvous[i].Mach_Port, 1, 0 );
+
+		/* Handle message */
+		if( result == MACH_MSG_SUCCESS ) DNSServiceDiscovery_handleReply( msg );
+#ifdef DEBUG
+		else if( result != MACH_RCV_TIMED_OUT ) Log( LOG_DEBUG, "mach_msg(): %ld", (long)result );
+#endif /* Debug */
+	}
+#endif /* Apple */
+
+#ifdef HOWL
+	sw_ulong msecs = 10;
+	sw_salt_step( My_Salt, &msecs );
+#endif
+} /* Rendezvous_Handler */
+
+
+LOCAL void Unregister( int Idx )
+{
+	/* Unregister service */
+
+#ifdef APPLE
+	DNSServiceDiscoveryDeallocate( My_Rendezvous[Idx].Discovery_Ref );
+#endif /* Apple */
+
+#ifdef HOWL
+	if( sw_discovery_cancel( My_Discovery_Session, My_Rendezvous[Idx].Id ) != SW_OKAY )
+	{
+		Log( LOG_ERR, "Rendezvous: Failed to unregister \"%s\"!", My_Rendezvous[Idx].Desc );
+		return;
+	}
+#endif /* Howl */
+	
+	Log( LOG_INFO, "Unregistered \"%s\" from Rendezvous.", My_Rendezvous[Idx].Desc );
+	My_Rendezvous[Idx].Desc[0] = '\0';
+} /* Unregister */
+
+
+/* -- Apple API -- */
+
+#ifdef APPLE
+
+
+LOCAL void Registration_Reply_Handler( DNSServiceRegistrationReplyErrorType ErrCode, void *Context )
+{
+	SERVICE *s = (SERVICE *)Context;
+	char txt[50];
+
+	if( ErrCode == kDNSServiceDiscoveryNoError )
+	{
+		/* Success! */
+		Log( LOG_INFO, "Successfully registered \"%s\" with Rendezvous.", s->Desc );
+		return;
+	}
+
+	switch( ErrCode )
+	{
+		case kDNSServiceDiscoveryAlreadyRegistered:
+			strcpy( txt, "name already registered!" );
+			break;
+		case kDNSServiceDiscoveryNameConflict:
+			strcpy( txt, "name conflict!" );
+			break;
+		default:
+			sprintf( txt, "error code %ld!", (long)ErrCode );
+	}
+
+	Log( LOG_INFO, "Can't register \"%s\" with Rendezvous: %s", s->Desc, txt );
+	s->Desc[0] = '\0';
+} /* Registration_Reply_Handler */
+
+
+#endif /* Apple */
+
+
+/* -- Howl API -- */
+
+#ifdef HOWL
+
+
+LOCAL sw_result HOWL_API Registration_Reply_Handler( sw_discovery Session, sw_discovery_publish_status Status, UNUSED sw_discovery_oid Id, sw_opaque Extra )
+{
+	SERVICE *s = (SERVICE *)Extra;
+	char txt[50];
+
+	assert( Session == My_Discovery_Session );
+	assert( Extra != NULL );
+
+	if( Status == SW_DISCOVERY_PUBLISH_STARTED || Status == SW_DISCOVERY_PUBLISH_STOPPED )
+	{
+		/* Success! */
+		Log( LOG_INFO, "Successfully registered \"%s\" with Rendezvous.", s->Desc );
+		return SW_OKAY;
+	}
+		
+	switch( Status )
+	{
+		case SW_DISCOVERY_PUBLISH_NAME_COLLISION:
+			strcpy( txt, "name conflict!" );
+			break;
+		default:
+			sprintf( txt, "error code %ld!", (long)Status );
+	}
+
+	Log( LOG_INFO, "Can't register \"%s\" with Rendezvous: %s", s->Desc, txt );
+	s->Desc[0] = '\0';
+
+	return SW_OKAY;
+} /* Registration_Reply_Handler */
+
+
+#endif /* Howl */
+
+
+#endif	/* RENDEZVOUS */
+
+
+/* -eof- */

+ 39 - 0
src/ngircd/rendezvous.h

@@ -0,0 +1,39 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001-2003 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * $Id: rendezvous.h,v 1.2 2005/03/19 18:43:49 fw Exp $
+ *
+ * "Rendezvous" functions (Header)
+ */
+
+
+#ifdef RENDEZVOUS
+
+#ifndef __rdezvous_h__
+#define __rdezvous_h__
+
+
+GLOBAL void Rendezvous_Init( void );
+GLOBAL void Rendezvous_Exit( void );
+
+GLOBAL bool Rendezvous_Register( char *Name, char *Type, unsigned int Port );
+
+GLOBAL bool Rendezvous_Unregister( char *Name );
+GLOBAL void Rendezvous_UnregisterListeners( void );
+
+GLOBAL void Rendezvous_Handler( void );
+
+
+#endif	/* __rdezvous_h__ */
+
+#endif	/* RENDEZVOUS */
+
+
+/* -eof- */

+ 325 - 0
src/ngircd/resolve.c

@@ -0,0 +1,325 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001-2003 by Alexander Barton (alex@barton.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ *
+ * Asynchronous resolver
+ */
+
+
+#include "portab.h"
+
+static char UNUSED id[] = "$Id: resolve.c,v 1.12.2.1 2005/09/02 22:07:38 fw Exp $";
+
+#include "imp.h"
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#ifdef IDENTAUTH
+#ifdef HAVE_IDENT_H
+#include <ident.h>
+#endif
+#endif
+
+#include "conn.h"
+#include "defines.h"
+#include "log.h"
+
+#include "exp.h"
+#include "resolve.h"
+
+
+#ifdef IDENTAUTH
+LOCAL void Do_ResolveAddr PARAMS(( struct sockaddr_in *Addr, int Sock, int w_fd ));
+#else
+LOCAL void Do_ResolveAddr PARAMS(( struct sockaddr_in *Addr, int w_fd ));
+#endif
+
+LOCAL void Do_ResolveName PARAMS(( char *Host, int w_fd ));
+
+#ifdef h_errno
+LOCAL char *Get_Error PARAMS(( int H_Error ));
+#endif
+
+LOCAL RES_STAT *New_Res_Stat PARAMS(( void ));
+
+
+GLOBAL void
+Resolve_Init( void )
+{
+	/* Initialize module */
+
+	FD_ZERO( &Resolver_FDs );
+} /* Resolve_Init */
+
+
+#ifdef IDENTAUTH
+GLOBAL RES_STAT *
+Resolve_Addr( struct sockaddr_in *Addr, int Sock )
+#else
+GLOBAL RES_STAT *
+Resolve_Addr( struct sockaddr_in *Addr )
+#endif
+{
+	/* Resolve IP (asynchronous!). On errors, e.g. if the child process
+	 * can't be forked, this functions returns NULL. */
+
+	RES_STAT *s;
+	int pid;
+
+	s = New_Res_Stat( );
+	if( ! s ) return NULL;
+
+	/* For sub-process */
+	pid = fork( );
+	if( pid > 0 )
+	{
+		/* Main process */
+		Log( LOG_DEBUG, "Resolver for %s created (PID %d).", inet_ntoa( Addr->sin_addr ), pid );
+		FD_SET( s->pipe[0], &Resolver_FDs );
+		if( s->pipe[0] > Conn_MaxFD ) Conn_MaxFD = s->pipe[0];
+		s->pid = pid;
+		return s;
+	}
+	else if( pid == 0 )
+	{
+		/* Sub process */
+		Log_Init_Resolver( );
+#ifdef IDENTAUTH
+		Do_ResolveAddr( Addr, Sock, s->pipe[1] );
+#else
+		Do_ResolveAddr( Addr, s->pipe[1] );
+#endif
+		Log_Exit_Resolver( );
+		exit( 0 );
+	}
+	else
+	{
+		/* Error! */
+		close(s->pipe[0]);
+		close(s->pipe[1]);
+		free( s );
+		Log( LOG_CRIT, "Resolver: Can't fork: %s!", strerror( errno ));
+		return NULL;
+	}
+} /* Resolve_Addr */
+
+
+GLOBAL RES_STAT *
+Resolve_Name( char *Host )
+{
+	/* Resolve hostname (asynchronous!). On errors, e.g. if the child
+	 * process can't be forked, this functions returns NULL. */
+
+	RES_STAT *s;
+	int pid;
+
+	s = New_Res_Stat( );
+	if( ! s ) return NULL;
+
+	/* Fork sub-process */
+	pid = fork( );
+	if( pid > 0 )
+	{
+		/* Main process */
+		Log( LOG_DEBUG, "Resolver for \"%s\" created (PID %d).", Host, pid );
+		FD_SET( s->pipe[0], &Resolver_FDs );
+		if( s->pipe[0] > Conn_MaxFD ) Conn_MaxFD = s->pipe[0];
+		s->pid = pid;
+		return s;
+	}
+	else if( pid == 0 )
+	{
+		/* Sub process */
+		Log_Init_Resolver( );
+		Do_ResolveName( Host, s->pipe[1] );
+		Log_Exit_Resolver( );
+		exit( 0 );
+	}
+	else
+	{
+		/* Error! */
+		close(s->pipe[0]);
+		close(s->pipe[1]);
+		free( s );
+		Log( LOG_CRIT, "Resolver: Can't fork: %s!", strerror( errno ));
+		return NULL;
+	}
+} /* Resolve_Name */
+
+
+#ifdef IDENTAUTH
+LOCAL void
+Do_ResolveAddr( struct sockaddr_in *Addr, int Sock, int w_fd )
+#else
+LOCAL void
+Do_ResolveAddr( struct sockaddr_in *Addr, int w_fd )
+#endif
+{
+	/* Resolver sub-process: resolve IP address and write result into
+	 * pipe to parent. */
+
+	char hostname[HOST_LEN];
+	struct hostent *h;
+	size_t len;
+#ifdef IDENTAUTH
+	char *res;
+#endif
+
+	/* Resolve IP address */
+	Log_Resolver( LOG_DEBUG, "Now resolving %s ...", inet_ntoa( Addr->sin_addr ));
+	h = gethostbyaddr( (char *)&Addr->sin_addr, sizeof( Addr->sin_addr ), AF_INET );
+	if( h ) strlcpy( hostname, h->h_name, sizeof( hostname ));
+	else
+	{
+#ifdef h_errno
+		Log_Resolver( LOG_WARNING, "Can't resolve address \"%s\": %s!", inet_ntoa( Addr->sin_addr ), Get_Error( h_errno ));
+#else
+		Log_Resolver( LOG_WARNING, "Can't resolve address \"%s\"!", inet_ntoa( Addr->sin_addr ));
+#endif	
+		strlcpy( hostname, inet_ntoa( Addr->sin_addr ), sizeof( hostname ));
+	}
+	Log_Resolver( LOG_DEBUG, "Ok, translated %s to \"%s\".", inet_ntoa( Addr->sin_addr ), hostname );
+
+	/* Write resolver result into pipe to parent */
+	len = strlen( hostname ); 
+	hostname[len] = '\n'; len++;
+	if( (size_t)write( w_fd, hostname, len ) != (size_t)len )
+	{
+		Log_Resolver( LOG_CRIT, "Resolver: Can't write to parent: %s!", strerror( errno ));
+		close( w_fd );
+		return;
+	}
+
+#ifdef IDENTAUTH
+	/* Do "IDENT" (aka "AUTH") lookup and write result to parent */
+	Log_Resolver( LOG_DEBUG, "Doing IDENT lookup on socket %d ...", Sock );
+	res = ident_id( Sock, 10 );
+	Log_Resolver( LOG_DEBUG, "Ok, IDENT lookup on socket %d done: \"%s\"", Sock, res ? res : "" );
+
+	/* Write IDENT result into pipe to parent */
+	if (res) {
+		len = strlen(res);
+		res[len] = '\n';
+		len++;
+	} else len = 1;
+
+	if( (size_t)write( w_fd, res ? res : "\n", len ) != (size_t)len )
+	{
+		Log_Resolver( LOG_CRIT, "Resolver: Can't write to parent (IDENT): %s!", strerror( errno ));
+		close( w_fd );
+	}
+	free( res );
+#endif
+} /* Do_ResolveAddr */
+
+
+LOCAL void
+Do_ResolveName( char *Host, int w_fd )
+{
+	/* Resolver sub-process: resolve name and write result into pipe
+	 * to parent. */
+
+	char ip[16];
+	struct hostent *h;
+	struct in_addr *addr;
+	int len;
+
+	Log_Resolver( LOG_DEBUG, "Now resolving \"%s\" ...", Host );
+
+	/* Resolve hostname */
+	h = gethostbyname( Host );
+	if( h )
+	{
+		addr = (struct in_addr *)h->h_addr;
+		strlcpy( ip, inet_ntoa( *addr ), sizeof( ip ));
+	}
+	else
+	{
+#ifdef h_errno
+		Log_Resolver( LOG_WARNING, "Can't resolve \"%s\": %s!", Host, Get_Error( h_errno ));
+#else
+		Log_Resolver( LOG_WARNING, "Can't resolve \"%s\"!", Host );
+#endif
+		ip[0] = '\0';
+	}
+	if( ip[0] ) Log_Resolver( LOG_DEBUG, "Ok, translated \"%s\" to %s.", Host, ip );
+
+	/* Write result into pipe to parent */
+	len = strlen( ip );
+	ip[len] = '\n'; len++;
+	if( (size_t)write( w_fd, ip, len ) != (size_t)len )
+	{
+		Log_Resolver( LOG_CRIT, "Resolver: Can't write to parent: %s!", strerror( errno ));
+		close( w_fd );
+	}
+} /* Do_ResolveName */
+
+
+#ifdef h_errno
+
+LOCAL char *
+Get_Error( int H_Error )
+{
+	/* Get error message for H_Error */
+
+	switch( H_Error )
+	{
+		case HOST_NOT_FOUND:
+			return "host not found";
+		case NO_DATA:
+			return "name valid but no IP address defined";
+		case NO_RECOVERY:
+			return "name server error";
+		case TRY_AGAIN:
+			return "name server temporary not available";
+		default:
+			return "unknown error";
+	}
+} /* Get_Error */
+
+#endif
+
+
+LOCAL RES_STAT *
+New_Res_Stat( void )
+{
+	RES_STAT *s;
+
+	/* Allocate memory */
+	s = (RES_STAT *)malloc( sizeof( RES_STAT ));
+	if( ! s )
+	{
+		Log( LOG_EMERG, "Resolver: Can't allocate memory! [Resolve_Addr]" );
+		return NULL;
+	}
+
+	/* Initialize pipe for result */
+	if( pipe( s->pipe ) != 0 )
+	{
+		free( s );
+		Log( LOG_ALERT, "Resolver: Can't create output pipe: %s!", strerror( errno ));
+		return NULL;
+	}
+
+	s->stage = 0;
+	s->bufpos = 0;
+	s->pid = -1;
+
+	return s;
+} /* New_Res_Stat */
+
+
+/* -eof- */

+ 0 - 0
src/ngircd/resolve.h


Some files were not shown because too many files changed in this diff