--- /dev/null
+|=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=|
+| UnrealIRCd 3.0 |
+| Configuration |
+|=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=|
+| http://unreal.tspre.org |
+|=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=|
--- /dev/null
+|=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=|
+| UnrealIRCD Custom Create Network Configuration|
+|=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=|
+| |
+| This will not be too hard, just follow the |
+| instructions, and answer the questions... |
+| |
+|=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=|
--- /dev/null
+List of helpers in the alpha/beta phase:
+* Headbang, Alpha/beta tester
\ No newline at end of file
--- /dev/null
+/*
+ * UnrealIRCd Changes File - (C) Carsten Munk 1999
+ * $Id$
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+*/
+*** BUGS ***
+* When a +q sets +L it sets it but displays an error msg
+(??:
+*** Stskeeps (cmunk@rox-56506.fyremoon.net) has joined channel #a
+*** #a 951758184
+*** Mode change "+q Stskeeps" on channel #a by Stskeeps
+*** Mode change "-oaATcfebW" for user Stskeeps by Stskeeps
+*** Channel mode +l <max> is requried for +L to be set
+*** Mode change "+l 1" on channel #a by Stskeeps
+*** Mode change "+L #moo" on channel #a by Stskeeps
+)
+
+*** Unreal3.0-Morrigan(fix) ***
+* NOTE: If your system clock is wrong you will have problems with TOPICs
+ being set on all servers. That is because TOPICs which are _new_ are
+ taken instead of old
+- Fixed +f not banning when * is specified
+- Fixed +q (chan owners) not being able to set +L (partially fixed)
+- Fixed /tsctl segfaulting the server
+- Fixed the killing bug. The cause was that when m_mode was called in the
+ NICKv2 parsing routine, it sent out a :nick MODE :+x which was an unknown
+ nick, and the NICK was being sent just after, causing it to kill the user
+ (was a _huge_ bastard to find)
+- If someone changes their nick to irc and WebTV is enabled, problems
+ occur FIX: deny change to that in m_nick (bug fixed)
+- Added lost unrealircd.bmp.gz file
+
+*** Unreal3.0-Morrigan ***
+- Added the new GUI main coded by DrBin, first coding by {X}
+- Added v64net.network
+- Added 972-scripterz.network
+- Made NO_FDLIST compilation work as well
+- Fixed DCCDENY bug (p->mask, p->mask) (*slaps sts*)
+- +F not flood off if netsplit happens
+- Made TODO, made "Unable to write tunefile" show an error if *nix
+- Added stormdancing.network
+- send.c sendto_realops problem solved
+- Fixed a segfaulting bug in /tsctl reported by x-wartech
+- Fixed segfaulting bug with -oh bounce stuff in channel.c reported by Dana
+- Fixed +q bug reported by several people, inc DrBin
+- Added networks/fireirc.network
+- Fixed +f * option not banning correctly
+- Fixed fdlist on win32 problem
+- Added /HTM for high traffic mode status (partially added)
+- Added networks/digitalirc.network
+- G:lines expire every 5th second now
+- /stats T now show incoming and outgoing rate
+- Some HTM stuff
+- Some release stuff
+- Fixed up some NICKv2 stuff, more faster stuff:)
+- Moved old Changes stuff to Changes.old
+- Made so /path ~path or ".."'s in T:lines arent possible
+- Made it so certain files ie ircd.conf,oper.motd, unrealircd.conf, ircd.log
+ can't be used in a T:line
+- Added dynconf option to specify SOCKS kill message & ban message & bantime
+- Fixed SOCKS exception bug (!!)
+- Fixed some indention in dynconf.c and a memory leak problem (what were you
+ smoking code?:P)
+- iNAH bugfixes( call them fixes and ill smash you;))
+- Recoded color striping to be ALOT more accurate and faster
+- Using hybrid IsMember()
+- Fixed +F bug (again)
+- Added FDlists, does those work on win32?
+- De-Potvinized addline, addmotd, and addomotd (should run faster)
+- Made addline, addmotd, addomotd display to the user what was written
+- Removed /snote and /snotes (no one used them)
+- GPL stuff
+- Some comestic tkl fixes..
+- Fixed +F bug
+- Made +F connect notices more bandwidth friendly,
+ only bad things:
+ - Not showing port in connect +F
+ - On servers rejoin you get +F flooded (will be fixed in an later
+ release)
+- Made ALLOW_CHATOPS a unrealircd.conf option rather than a #define
+- Fixed a bug where you had to be +AC to see adminchats
+- chatops, adchat, nachat, techat, wallops no longer require a leading :
+- More TKL stuff..
+- m_chatops uses sendto_umode now, and also removed sendto_chatops
+- Remote rehashes now support the - flags, ex -dcc, -vhost etc
+- Fixed more G:Line stuff
+- Fixed G:Line bug with not expiring correctly - thanks Dark-Prince for
+ being guinea pig, and to JojoII for finding it
+- Fixed +ix remote bug reported by RevPsych
+- /list can now make opers see +s channels
+- Did some SJOIN2 work..
+- Fixed /whois bug with WHOIS_Channels
+- Fixed a minor, yet annoying bug in the dynconf version system, thanks to GoNiS
+- Fixed bug: EpicII stripping too much of /oper fail notice
+- Fixed bug: SJOIN TS Change notice should not show when (ts == oldts)
+- Fixed WEBTV_NONOTICE bug with CTCPs - thanks rjameson
+- Fixed +h can +o themselves bug, thanks to Mikey, HERZ and many other
+ people
+- Added TSP client/server
+- Fixed m_netinfo stuff..
+- Fixed a bug with the new m_names and +h (chanmode)
+- Removed .CHANGES.NEW2 - not in use anyways
+- Now using new m_names from bahamut by Lucas Madar (DarkRot)
+- Removed zombie code
+- Fixed up the MODE_ADMINONLY code
+- Fixed some bugs in can_send
+- Added TS Change notice to SJOIN
+- Fixed a +f bug, and fixed SJOIN resynch bug (serious)
+- Fixed up the remote rehash code a bit
+- Updated conf.doc
+- Added some WebTV stuff, read config.h
+- Removed the NO_DEFAULT_INVISIBLE define from config.h
+- Added MODE_I to unrealircd.conf, auto setting of +i when a user connects
+- Fixed a minor unrealircd.conf bug
+- Fixed up all SJOIN fuzz, made RESYNCMODES be 12
+- Fixed this bug:
+ * After sync on other server
+ *** Stskeeps is using modes +oiwghsaHATcCreWIdt
+ should be:
+ Stskeeps is using modes +owghskaATcfrebW
+
+- Made unrealircd.conf option to hide U:lines from non-opers in /links
+- Updated the unrealircd.conf and all the .network files to support the
+ version system, and for unrealircd.conf to support HIDE_ULINES
+- Made a versioning system for unrealircd.conf and *.network (This will
+ allow us to makesure _old_ versions are not being used when new features
+ are added to the files)
+- TKL/zap bugfix!!
+- Channel mode +H errors in numeric 459 now, coded by Rev_Null- thanks
+- Moved RPL_WHOISSPECIAL to 320
+- Another TKL bug.
+- TKL bug fixed
+- Made TKL backwards compatible
+- TKLs are now syncing
+- Bug fixes..
+- Fixed TKL<->GLINE protocol problems
+- Renamed chmode +I to +V as it screwed up some clients thinking it was
+ IRCnet..
+- Took out m_fjoin, not in use
+- Fixed up +e so it works with mIRC channel dialog now
+- Added channel mode +H, only setable by SkoAdmin, makes +I users unable to
+ join channel - code&thanks to RevPsych & Rev_Null
+- Removed all MegaIRC references
+- Fixed VHOST desynch bug..
+- Removed aGline record
+- Fixed some idention in msg.h
+- Fixed warning in s_misc.c
+- Removes /ns, /cs, /ms, /os, /hs commands (not in use)
+- Fixed bug where /statserv needed a : for more than one param
+- Fixed so that /trace only cloaks hostname if it is an oper
+- Fixed token non case sensitive problem
+- Fixed warning in mp2parv..
+- Fixed DEBUGMODE compile bug..
+- Fixed BOTMOTD bug..
+- Fixed some bugs (1.16->1.17) and removed aClient->user->host and replaced
+ it by realhost. Saves memory
+- Fixing up for beta release
+- Updated networks/networks.ndx
+- Reason in temp and static K:lines like |kc.gline will show user klined
+ file kc.gline (only legal names are |kc.*)
+- Added e:lines to the docs
+- Added solargalaxy.network
+- Fixed a minor +S (chanmode) bug
+- Fixed a bug where if a channel was +n it would display a
+ must be +v msg rather than no external msgs (thank Potvin for that one)
+- Made dccdeny's notice +e users when a file is rejected
+- Added NOTICE in m_sajoin/m_sapart (You were forced to join/part #)
+- Added e:lines, SOCKS check exception lines
+ format: e:ip (not hostname):*:*
+- Added doc/faq entry about debian on sparcs..
+- added debian sparc support (read doc/faq)
+- SJOIN sortof working. Straight testing needed
+- made /botmotd use NOTICE AUTH (so all bots will see it)
+- fixed NICKv2 umode field when no mode bug..
+- added T (TechAdmin) to the SMO flags
+- fixed a little _mistake_ in the /dusers error message
+- fixed a bug where +c (chanmode) blocked all privmsgs :P
+- m_sjoin compiled, need to make it unreal3.0 compatible
+- added include/sjoin.h for SJOIN stuff
+- Deleted :server prefix from SWHOIS burst.
+- Added UMODE_SETHOST (+t), and set NICKv2 up to only send when a real
+ virthost. Spares bandwidth:) +t is _not_ user setable
+- Removed UMODE_COFOUND, UMODE_WMASTER, not in use anymore.
+- Fixed up MODE_LINK, MODE_FLOODLIMIT syncronization,
+ you can mode do /mode # -lf without parameters
+- Gave Unreal correct orgin (df4.6.5)
+- Gave /stats N,S a header
+- Added network solarxtreme.network
+- /stats N returns .network file information
+- /stats S returns unrealircd.conf information
+- Added a virtualhost field to NICKv2
+- Updated conf.doc
+- Removed all traces of CLIENT_COMPILE
+- Some Linux-ALPHA support.. i need accces to a alpha box :P
+ Fixes done by Ramuh (irc.risanet.com) originally for UltimateIRCd,
+ thanks to ShadowMastr for forwarding me..
+- Removed all traces of services.h..
+- NICKv2 working.. :)
+- Updated doc/faq slightly
+- Updated doc/example.conf with new lines an Oflags
+- Implemented NICKv2 (umode field in NICK)
+- Similar topics are sent along now .. was a bug ? (thanks Headbang,
+ WonderWal, etc)
+- Fixed up compile warnings
+- Fixed channel.c warning in can_join
+- Removed SHOW_PASSWORD define, not in use anymore
+- Removed USE_CASETABLES define, not in use anymore
+- Removed TIMED_KLINE define, not in use anymore
+- Added OPER_NO_HIDING define
+- Removed RelicNet +z, unreal isnt at use at relicnet anyways and
+ i still dont believe that potvin _thought_ he could make them use it?
+ hah!
+- Added REMOVE_ADVERTISING define (off by default) , check include/config.h
+ and src/s_user.c (m_message) for more info (by ice)
+- Fixed channel name similarity bug reported by IXpfah
+- Comment on Nickflood/joinflood thing (stskeeps): Services can do that?
+- Fixed up some version.c.SH stuff
+- Added SJOIN protoctl for preparing for SJOIN
+- Split up PROTOCTL_SUPPORTED in PROTOCTL_SERVER and PROTOCTL_CLIENT
+- Added networks/uzaynet.network
+- NOTICE auth, tells you that it found a bad SOCKS.
+- Made umode +d work correctly
+- Made it so users can't see the RPL_WHOISCHANNELS for a
+ +I user
+- Fixed a bug in +I where a +I user couldn't see themself
+ in /names
+- Fixed a minor bug in /chgident
+- Added bot.motd support on +B and /botmotd
+- /join 0 now shows "Left all channels" in reason why left
+- Added +H umode, hides oper status
+ in /who /who 0 o /whois (so opers
+ can spy on a channel and no one knows
+- win32: s_socks.c small problem fixed
+- Fixed a bug in the new zline code
+- Fixed a typo in the Win32 socks check (oops)
+- (development) added TODO.maybe
+- Added /vhost login password
+ read the s_extra.c on vhost.conf format
+- vhost.conf, added /rehash -vhost
+- Removed s_user.c/m_message warning
+- SOCKS check functioning
+- Removed src/list2.c - not in use
+- Removed networks/agitated.network, no longer existing network
+- Added networks/bunker7.network
+- Deleted ircdbug
+- Renamed LICENCE to LICENSE
+- /version shows alpha while in development..
+- (development) added include/stamp.h for static development stamping
+- send.c optimations from ircu :)
+- Added codemastr as offical developer
+- Now using GPL v2
+- NOTICE AUTH problem solved, i hope
+- Took out UNIXPORT code
+- Removed traces of R_LINE* in config.h
+- SOCKS check in progress
+- Fixed the Blowbug
+- TSCTL svstime works now :P correctly that is
+- nick is using modes +rx
+ instead of "nick is using modes [+rx]
+- Removed some lame brackets
+- /close sendto_ops() now
+- Fixed small SVSNICK bug (.)
+- Fixed +L resync bug..
+- df4.6.7 SVSNICK - fixes desynchs
+- Took out all the R_LINES code
+- Took out all SERVICES_MODE code
+- Took out all USE_SERVICES code
+- Added .crjava patch by Fish read include/config.h for more info..
+- Added IRCu .ack patch you can now use "ONE" in password line in I:Lines
+ to ensure only one connecting from that kind of I:line per IP.
+- /Lusers <mask> is not working anymore.. took out possible flood thing..
+- /List - IRCops should be able to see +s now (thanks Headbang and others)
+- RPL_YOURHOST - Your host is server, running version x
+ Removed [hostname].
+- RPL_MYINFO now selfupdates when adding new modes (channel and user)
+- Fixed umodestring
+- Umode +d avail to everyone now:P
+- Fixed channel mode +r defunctional bug
+ (thanks to gdb and the coder-com people who learnt me to use gdb:P)
+- SVSFLINE <+/-/*> [mask] [reason]
+ + = add (mask + reason)
+ - = delete (mask)
+ * = wipe all services F:Lines
+ (13/12/1999 working.)
+- Fixed server<->server token problem
+- Moved /info data to m_info_send
+- Made SIGSEGV do core too.. MAIL THEM TO ME ALONG WITH THE src/ircd FILE
+ if it tells ya to!
+- Fixed "GLINE @moo.org 10 :moo\r" G:Line bug (they haunt me)
+- New F:Line system (dccdeny.conf)
+- Removed OLD F:lines
+- Fixed up /stats f/F
+- Made /rehash -dcc = rehashes dccdeny.conf
+ /rehash -dyn = rehashes dynamic configuration (RISK OF TERMINATE:P)
+ /rehash -rest = rehashes channel restrict config chrestrict.conf
+- New channel restrict system
+ (chrestrict.conf)
+ # = comment
+ allow #moo = can join #moo
+ msg message = shows message when cannot join cos of allow
+
--- /dev/null
+#!/bin/sh
+#
+# Based off Config by Michael Graff (explorer@flame.org)
+# Copyright 1996, 1997
+#
+# (original that is =P)
+# UnrealIRCd - by Techie
+#
+# You may distribute this file without changes freely providing this notice
+# remains intact. This file may not be redistributed or made available for
+# distribution without the author's prior consent.
+#
+# $Id$
+IRCD_VERSION="Unreal3.0"
+CONF_DATE=`date`
+LAST_VERSION="very very old"
+#
+trap "" 13 14 15
+MV=mv
+RM=rm
+SETUP=include/setup.h
+OPTIONS_H=include/settings.h
+OPTIONS=Settings
+AUTO_CONFIG=""
+#
+STDLIBH=undef
+STDDEFH=undef
+SYSSYSLOGH=undef
+MALLOCH=undef
+PARAMH=undef
+UNISTDH=undef
+STRINGH=undef
+STRINGSH=undef
+RUSAGEH=undef
+NOINDEX=undef
+NSTRERROR=undef
+NSTRTOKEN=undef
+NSTRTOK=undef
+NINETADDR=undef
+NINETNTOA=undef
+NINETNETOF=undef
+GETTIMEOFDAY=undef
+LRAND48=undef
+STRTOUL=undef
+NEEDSKIPNAME=""
+CCPATH=''
+SIGNAL=''
+BLOCKING=''
+TMP=/tmp/.Configtmp$$.c
+EXEC=/tmp/.Configtmp$$
+PLATE=/tmp/.ConPlate$$
+c=''
+n=''
+#
+DIR=`pwd`
+#
+# Some reasonable defaults
+#
+DEFOPT="-O -g"
+DEFCFLAGS="$DEFOPT"
+DEFLIBS="none"
+OSNAME="an unrecgonized operating system"
+#
+IRCNET=""
+NOSPOOF="1"
+NOSPOOF_SEED01="0x12345678"
+NOSPOOF_SEED02="0x9abcdef0"
+KLINE_ADDRESS=""
+DPATH="$DIR"
+SPATH="$DIR/src/ircd"
+MODE_X=""
+TRUEHUB=""
+CRYPT_OPER_PASSWORD=""
+CRYPT_LINK_PASSWORD=""
+LISTEN_SIZE="5"
+MAXSENDQLENGTH="3000000"
+BUFFERPOOL="(9 * MAXSENDQLENGTH)"
+NICKNAMEHISTORYLENGTH="2000"
+MAXCONNECTIONS="1024"
+SHOWOPERS="Yes"
+
+#
+# load $OPTIONS if present
+#
+if [ -r "$OPTIONS" ] ; then
+ . $OPTIONS
+fi
+
+#
+2>/dev/null
+if [ "`eval echo -n 'a'`" = "-n a" ] ; then
+ c='\c'
+else
+ n='-n'
+fi
+
+clear
+
+if [ "$LAST_VERSION" != "$IRCD_VERSION" ] ; then
+ if [ -r .CHANGES.NEW ] ; then
+ more .CHANGES.NEW
+ echo $n "[Enter to begin]"
+ read cc
+ fi
+fi
+
+if [ "$1" = "-n" ] ; then
+ if [ "$LAST_VERSION" != "$IRCD_VERSION" ] ; then
+ echo "You specified the no-questions-asked configure, but the version"
+ echo "of Config which created your Settings file was $LAST_VERSION,"
+ echo "And the current version is $IRCD_VERSION."
+ echo " "
+ echo "Please read the prompts carefully since some of them may have"
+ echo "changed."
+ echo " "
+ else
+ AUTO_CONFIG=Yes
+ fi
+fi
+
+#
+# Take a wild stab at the OS, and take reasonable defaults for each
+#
+OS=`uname -a`
+case "$OS" in
+ *NetBSD*)
+ DEFCFLAGS="$DEFOPT"
+ DEFLIBS="-lcrypt"
+ OSNAME="NetBSD"
+ ;;
+ *FreeBSD*2.2.*)
+ DEFCFLAGS="$DEFOPT"
+ DEFLIBS="-lcrypt"
+ OSNAME="FreeBSD 2.2.x"
+ CRYPT_OPER_PASSWORD=""
+ CRYPT_LINK_PASSWORD=""
+ echo "You are using FreeBSD 2.2.x; do NOT crypt passwords at this time"
+ ;;
+ *FreeBSD*2.2*)
+ DEFCFLAGS="$DEFOPT"
+ DEFLIBS="none"
+ OSNAME="FreeBSD 2.2"
+ CRYPT_OPER_PASSWORD=""
+ CRYPT_LINK_PASSWORD=""
+ echo "You are using FreeBSD 2.2; do NOT crypt passwords at this time"
+ ;;
+ *FreeBSD*3*)
+ DEFCFLAGS="$DEFOPT"
+ DEFLIBS="-lcrypt"
+ OSNAME="FreeBSD 3.x"
+ CRYPT_OPER_PASSWORD=""
+ CRYPT_LINK_PASSWORD=""
+ echo "You are using FreeBSD 3.x; You can use encrypted passwords now."
+ ;;
+ *FreeBSD*)
+ DEFCFLAGS="$DEFOPT"
+ DEFLIBS="none"
+ OSNAME="FreeBSD"
+ CRYPT_OPER_PASSWORD=""
+ CRYPT_LINK_PASSWORD=""
+ echo "You are using FreeBSD ; do NOT crypt passwords at this time"
+ ;;
+ *SCO_SV*)
+ DEFCFLAGS="$DEFOPT -DSCOUNIX"
+ DEFLIBS="-lsocket"
+ OSNAME="SCO Openserver"
+ NEEDSKIPNAME="Yep"
+ echo "You're using SCO Unix. For more support, contact potvin@eliteircd.on.ca"
+ ;;
+ *Apple*)
+ DEFCFLAGS="$DEFOPT"
+ DEFLIBS="none"
+ OSNAME="MacOS X"
+ ;;
+
+ *OSF1*alpha*)
+ DEFCFLAGS="$DEFOPT"
+ DEFLIBS="none"
+ OSNAME="OSF/1 or Digital Unix"
+ ;;
+ *AmigaOS*68020*)
+ DEFCFLAGS="$DEFOPT -D_AMIGA -m68020"
+ DEFLIBS=""
+ OSNAME="AmigaOS (68020)"
+ ;;
+ *AmigaOS*68030*)
+ DEFCFLAGS="$DEFOPT -D_AMIGA -m68030"
+ DEFLIBS=""
+ OSNAME="AmigaOS (68030)"
+ ;;
+ *AmigaOS*68040*)
+ DEFCFLAGS="$DEFOPT -D_AMIGA -m68040"
+ DEFLIBS=""
+ OSNAME="AmigaOS (68040)"
+ ;;
+ *AmigaOS*68060*)
+ DEFCFLAGS="$DEFOPT -D_AMIGA -m68060"
+ DEFLIBS=""
+ OSNAME="AmigaOS (68060)"
+ ;;
+ *SunOS*4.*)
+ DEFCFLAGS="$DEFOPT"
+ DEFLIBS="none"
+ OSNAME="SunOS 4.x"
+ ;;
+ *SunOS*5.*)
+ DEFCFLAGS="$DEFOPT -DSOL20"
+ DEFLIBS="-lsocket -lnsl -lresolv"
+ OSNAME="Solaris 2.x (or SunOS 5.x)"
+ ;;
+ *Linux*)
+ cat > $TMP << __EOF__
+#include <stdio.h>
+main()
+{
+ printf("%d\n",
+#ifndef __GLIBC__
+0);
+#else
+__GLIBC__);
+#endif
+exit(0);
+}
+__EOF__
+ cc $TMP -o $EXEC >/dev/null 2>&1
+ GLIBCVERS=`$EXEC`
+ if [ -n "$GLIBCVERS" -a "$GLIBCVERS" -ge 2 ];then
+ OSNAME="Linux (with GLIBC 2.x or greater)"
+ DEFLIBS="-lcrypt -lresolv"
+ else
+ OSNAME="Linux"
+ DEFLIBS=""
+ fi
+ DEFCFLAGS="$DEFOPT"
+ ;;
+ *HP-UX*.09.*)
+ DEFCFLAGS="$DEFOPT"
+ DEFLIBS=""
+ OSNAME="HPUX 9.x"
+ ;;
+ *HP-UX*.10.*)
+ DEFCFLAGS="$DEFOPT"
+ DEFLIBS=""
+ OSNAME="HPUX 10.x"
+ ;;
+esac
+
+echo " "
+echo You are running $OSNAME...
+echo " "
+
+# Create Makefile if it doesn't exist...
+if [ ! -f Makefile ] ; then
+ cp Makefile.dist Makefile
+fi
+cat << __EOF__
+Welcome to the configuration for the Unreal IRCD.
+This UnrealIRCD version is: $IRCD_VERSION, Good Luck.
+
+Config will generate a system-specific $SETUP file, a top
+level Makefile, $OPTIONS_H, and a persistant options file named
+$OPTIONS
+
+Enter "none" at any prompt to effect a null entry.
+
+__EOF__
+runonce=""
+FOO=`egrep "^CC=" Makefile 2>/dev/null | sed -e 's/^[^=]*[ ]*=\(.*\)/\1/'`
+while [ -z "$CCPATH" ] ; do
+ MYP=`echo "$PATH" | sed -e 's/:/ /g'`
+ echo "Which compiler do you use, gcc or cc or...?"
+ echo $n "[$FOO] -> $c"
+ if [ -z "$AUTO_CONFIG" -o -n "$runonce" ] ; then
+ read cc
+ else
+ cc=""
+ fi
+ if [ -z "$cc" ] ; then
+ cc=$FOO
+ CCPATH=$FOO
+ elif [ -f $cc ] ; then
+ CCPATH=$cc
+ else
+ for i in $MYP; do
+ if [ -f $i/$cc -a -z "$CCPATH" ] ; then
+ CCPATH=$i/$cc
+ fi
+ done
+ fi
+ if [ -z "$CCPATH" ]; then runonce="Yes"; fi
+done
+if [ "$FOO" != "$cc" ] ; then
+ MYP=`echo "$CCPATH" | sed -e 's@/@ @g'`
+ set $MYP
+ if [ $2 ] ; then
+ while [ $2 ] ; do
+ shift
+ done
+ fi
+ if [ $1 = "gcc" ] ; then
+ CCPATH="$CCPATH"
+ fi
+fi
+echo "Compiler selected: $CCPATH"
+echo " "
+# Check it out
+cat > $TMP <<__EOF__
+main() {}
+__EOF__
+$CCPATH $TMP -o $EXEC >/dev/null 2>&1
+if [ ! -f $EXEC ] ; then
+ echo "You don't have $CCPATH or it's broken!"
+ exit 1
+fi
+# Fix Makefile
+#
+$RM -f Makefile.tmp
+sed -e "s@^CC=\(.*\)@CC=$CCPATH@" Makefile > Makefile.tmp
+cp Makefile.tmp Makefile
+$RM -f Makefile.tmp
+#
+echo "Enter additional flags to give to $CCPATH"
+FOO=`egrep "^XCFLAGS=" Makefile 2>/dev/null | sed -e 's/^[^=]*=[ ]*\(.*\)/\1/'`
+if [ -z "$FOO" ] ; then
+ echo "I recommend $DEFCFLAGS"
+ FOO="$DEFCFLAGS"
+fi
+echo $n "[$FOO] -> $c"
+if [ -z "$AUTO_CONFIG" -o -n "$runonce" ] ; then
+ read cc
+else
+ cc=""
+fi
+if [ -z "$cc" ] ; then
+ cc="$FOO"
+fi
+if [ "$cc" = "none" ] ; then
+ cc=''
+fi
+XCFLAGS=$cc
+# Fix Makefile
+#
+$RM -f Makefile.tmp
+sed -e "s@^XCFLAGS=\(.*\)@XCFLAGS=$XCFLAGS@" Makefile > Makefile.tmp
+cp Makefile.tmp Makefile
+$RM -f Makefile.tmp
+#
+cat <<__EOF__
+
+If you need to use any extra libraries when compiling the server,
+please tell me now (might need to look at the Makefiles) and please
+include all the -l and -L flags.
+
+You should use the recommended value unless you have a compelling reason
+not to...
+__EOF__
+LIBS=`egrep "^IRCDLIBS=" Makefile 2>/dev/null | sed -e 's/^[^=]*=\(.*\)/\1/' | tr -d "\012"`
+if [ -z "$LIBS" ] ; then
+ echo "I suggest: $DEFLIBS"
+ LIBS="$DEFLIBS"
+fi
+echo $n "[$LIBS] -> $c"
+if [ -z "$AUTO_CONFIG" -o -n "$runonce" ] ; then
+ read cc
+else
+ cc=""
+fi
+if [ -z "$cc" ] ; then
+ cc="$LIBS"
+fi
+if [ "$cc" = "none" ] ; then
+ cc=''
+fi
+LIBS=$cc
+# Fix Makefile
+#
+$RM -f Makefile.tmp
+sed -e "s@^IRCDLIBS=\(.*\)@IRCDLIBS=$LIBS@" Makefile > Makefile.tmp
+cp Makefile.tmp Makefile
+$RM -f Makefile.tmp
+#
+COMP="$CCPATH $XCFLAGS $TMP -o $EXEC $LIBS"
+#
+echo 'Checking out /usr/include'
+echo $n "...Looking for /usr/include/stdlib.h...$c"
+if [ -r /usr/include/stdlib.h ] ; then
+ STDLIBH=define
+ echo 'found!'
+else
+ echo 'not found :('
+fi
+echo $n "...Looking for stddef.h...$c"
+if [ -r /usr/include/stddef.h ] ; then
+ STDDEFH=define
+ echo 'found!'
+else
+ echo 'not found :('
+fi
+echo $n "...Looking for /usr/include/sys/syslog.h...$c"
+if [ -r /usr/include/sys/syslog.h ] ; then
+ SYSSYSLOGH=define
+ echo 'found!'
+else
+ echo 'not found :('
+fi
+#echo $n "...Looking for malloc.h...$c"
+#if [ -r /usr/include/malloc.h ] ; then
+# MALLOCH=malloc.h
+# echo 'found!'
+#elif [ -r /usr/include/sys/malloc.h ] ; then
+# MALLOCH=sys/malloc.h
+# echo 'found!'
+#else
+# echo 'not found :('
+# MALLOCH=undef
+#fi
+echo $n "...Looking for /usr/include/sys/param.h...$c"
+if [ -r /usr/include/sys/param.h ] ; then
+
+ PARAMH=define
+ echo 'found!'
+else
+ echo 'not found :('
+fi
+echo $n "...Looking for /usr/include/unistd.h...$c"
+if [ -r /usr/include/unistd.h ] ; then
+ UNISTDH=define
+ echo 'found!'
+else
+ echo 'not found :('
+fi
+echo $n "...Looking for /usr/include/string.h...$c"
+if [ -r /usr/include/string.h ] ; then
+ STRINGH=define
+ echo 'found!'
+else
+ echo 'not found :('
+fi
+echo $n "...Looking for /usr/include/strings.h...$c"
+if [ -r /usr/include/strings.h ] ; then
+ STRINGSH=define
+ echo 'found!'
+else
+ echo 'not found :('
+fi
+echo $n "...Looking for /usr/include/sys/rusage.h...$c"
+if [ -r /usr/include/sys/rusage.h ] ; then
+ RUSAGEH=define
+ echo 'found!'
+else
+ echo 'not found (good!)'
+fi
+#
+# to b or not to b
+#
+echo " "
+echo $n "To be or not to be...$c"
+cat > $TMP <<__EOF__
+main()
+{
+ char a[3], b[3];
+ bzero(b,3);
+ bcopy(a,b,3);
+ (void)bcmp(a,b,3);
+ exit(0);
+}
+__EOF__
+$COMP >/dev/null 2>&1
+if [ $? -eq 0 ] ; then
+ echo "and so it shall be! bcopy/bzero/bcmp are about!"
+ BZERO=bzero
+else
+ echo "and it wasn't. No bcopy/bzero/bcmp...hmpf"
+ BZERO=memset
+fi
+echo " "
+echo $n "Which one, gettimeofday, or lrand48..$c"
+cat > $TMP <<__EOF__
+#include <stdio.h>
+#include <sys/time.h>
+main()
+ {
+ struct timeval tv;
+ (void) gettimeofday(&tv, NULL);
+ }
+__EOF__
+$COMP >/dev/null 2>&1
+if [ $? -eq 0 ] ; then
+ echo "We have a winner! gettimeofday found."
+ GETTIMEOFDAY=define
+else
+ echo "No gettimeofday. Lets try lrand48."
+cat > $TMP <<__EOF__
+main()
+{
+ int a;
+ a=lrand48();
+}
+__EOF__
+ $COMP >/dev/null 2>&1
+ if [ $? -eq 0 ] ; then
+ echo "Bingo! lrand48!"
+ LRAND48=define
+ fi
+fi
+#
+# check for non-blocking fd style available..
+#
+echo " "
+echo 'Checking for POSIX/BSD/SYSV non-blocking stuff'
+if [ -f $TMP -o -d $TMP ] ; then
+ $RM -f $TMP
+fi
+cat > $PLATE <<__EOF__
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+#include <signal.h>
+alarmed()
+{
+ exit(1);
+}
+main()
+{
+ char b[12], x[32];
+ int f, l = sizeof(x);
+ f = socket(AF_INET, SOCK_DGRAM, 0);
+ if (f >= 0 && !(fcntl(f, F_SETFL, BLOCKING))) {
+ signal(SIGALRM, alarmed);
+ alarm(3);
+ recvfrom(f, b, 12, 0, x, &l);
+ alarm(0);
+ exit(0);
+ }
+ exit(1);
+}
+__EOF__
+sed -e 's/BLOCKING/O_NONBLOCK/' $PLATE > $TMP
+$COMP >/dev/null 2>&1
+if [ 0 -eq $? ] ; then
+ $EXEC
+fi
+if [ 0 -eq $? ] ; then
+ BLOCK=O_NONBLOCK
+else
+ echo 'O_NONBLOCK not present/working in fcntl.h or sys/ioctl.h'
+ if [ -f $TMP -o -d $TMP ] ; then
+ $RM -f $TMP $EXEC;
+ fi
+ sed -e 's/BLOCKING/O_NDELAY/' $PLATE > $TMP
+ $COMP >/dev/null 2>&1
+ if [ 0 -eq $? ] ; then
+ $EXEC
+ fi
+ if [ 0 -eq $? ] ; then
+ BLOCK=O_NDELAY
+ else
+ echo 'O_NDELAY not present/working in fcntl.h or sys/ioctl.h'
+ if [ -f $TMP -o -d $TMP ] ; then
+ $RM -f $TMP $EXEC;
+ fi
+ sed -e 's/BLOCKING/FIONBIO/' $PLATE > $TMP
+ $COMP >/dev/null 2>&1
+ if [ 0 -eq $? ] ; then
+ echo 'FIONBIO not found! No option found!'
+ BLOCK=none
+ else
+ BLOCK=FIONBIO
+ fi
+ fi
+fi
+$RM -f $TMP $PLATE $EXEC
+echo "Blocking selected: $BLOCK";
+#
+# reliable signals ?
+#
+echo 'Looking for reliable signals...'
+echo "Hmmm...wonder if you have 'action from POSIX..."
+cat > $TMP <<__EOF__
+#include <signal.h>
+
+main()
+{ /* poor replacement for NULL but who cares here ? */
+ sigaction(SIGTERM, (struct sigaction *)0L, (struct sigaction *)0L);
+}
+__EOF__
+$COMP >/dev/null 2>&1
+if [ $? -eq 0 ] ; then
+ echo "Ooooh, you are a lucky one! 'action from POSIX!"
+ SIGNAL=posix
+else
+ $RM -f $EXEC $TMP
+ cat > $TMP <<__EOF__
+#include <signal.h>
+int calls = 0;
+void handler()
+{
+ if (calls)
+ return;
+ calls++;
+ kill(getpid(), SIGTERM);
+ sleep(1);
+}
+main()
+{
+ signal(SIGTERM, handler);
+ kill(getpid(), SIGTERM);
+ exit (0);
+}
+__EOF__
+ echo $n "Nope, but you have...$c"
+ $COMP >/dev/null 2>&1
+ $EXEC
+ if [ $? -eq 0 ] ; then
+ echo 'reliable signals! Cheers BSD!'
+ SIGNAL=bsd
+ else
+ echo "yucky, unreliable SYSV!"
+ SIGNAL=sysv
+ fi
+fi
+$RM -f $EXEC $TMP
+#
+echo 'Now those strings libraries...hmm...which one is it...'
+cat > $TMP <<__EOF__
+#$STRINGH STRINGH
+#$STRINGSH STRINGSH
+#ifdef STRINGH
+#include <string.h>
+#endif
+#ifdef STRINGSH
+#include <strings.h>
+#endif
+main()
+{
+ char *s = index("foo", 'o');
+ exit(0);
+}
+__EOF__
+$COMP >/dev/null 2>&1
+if [ $? -eq 0 ] ; then
+ echo "Cool...you have index()!"
+else
+ NOINDEX=define
+ echo "Grmpf...I guess there is a strchr() out there somewhere..."
+fi
+$RM -f $EXEC $TMP
+#
+# getrusage or times ?
+#
+echo $n "One for debugging, mainly, getrusage(2) or times(2)...$c"
+cat > $TMP <<__EOF__
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+main()
+{
+ struct rusage rus;
+ (void)getrusage(RUSAGE_SELF, &rus);
+}
+__EOF__
+$COMP >/dev/null 2>&1
+if [ $? -eq 0 ] ; then
+ TIMES=getrusage
+ echo "getrusage()"
+else
+ $RM -f $EXEC $TMP
+ cat > $TMP <<__EOF__
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/times.h>
+main()
+{
+ struct tms tmsbuf;
+ (void)times(&tmsbuf);
+}
+__EOF__
+ $COMP >/dev/null 2>&1
+ if [ $? -eq 0 ] ; then
+ TIMES=times
+ echo "times()"
+ else
+ echo "couldn't get either ?!"
+ TIMES=none
+ fi
+fi
+#
+# what do we need that isn't here already ?
+#
+echo "What else do I need that you don't have..."
+echo $n "Lets see...$c"
+cat > $TMP <<__EOF__
+main()
+{
+ unsigned long foo;
+
+ char *s = strtoul("0x12345", &foo, 16);
+ exit(0);
+}
+__EOF__
+$COMP >/dev/null 2>&1
+if [ $? -ne 0 ] ; then
+ echo $n " strtoul$c"
+ $RM -f Makefile.tmp
+ sed -e "s@^STRTOUL=\(.*\)@STRTOUL=strtoul.o@" Makefile > Makefile.tmp
+ cp Makefile.tmp Makefile
+ $RM -f Makefile.tmp
+else
+ $RM -f Makefile.tmp
+ sed -e "s@^STRTOUL=\(.*\)@STRTOUL=@" Makefile > Makefile.tmp
+ cp Makefile.tmp Makefile
+ $RM -f Makefile.tmp
+fi
+$RM -f $EXEC $TMP
+cat > $TMP <<__EOF__
+main()
+{
+ char *s = strerror(0);
+ exit(0);
+}
+__EOF__
+$COMP >/dev/null 2>&1
+if [ $? -ne 0 ] ; then
+ echo $n " strerror$c"
+ NSTRERROR=define
+fi
+$RM -f $EXEC $TMP
+cat > $TMP <<__EOF__
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+main()
+{
+ dn_skipname("","");
+ exit(0);
+}
+__EOF__
+$COMP >/dev/null 2>&1
+if [ $? -ne 0 -o "$OSNAME" = "Linux RedHat 5.0" -o -n "$NEEDSKIPNAME" ] ; then
+ echo $n " dn_skipname$c"
+ $RM -f Makefile.tmp
+ sed -e "s@^RES=\(.*\)@RES=res_skipname.o@" Makefile > Makefile.tmp
+ cp Makefile.tmp Makefile
+ $RM -f Makefile.tmp
+else if [ $? -ne 0 -o "$OSNAME" = "Linux RedHat 5.1" -o -n "$NEEDSKIPNAME" ] ; then
+ echo $n " dn_skipname$c"
+ $RM -f Makefile.tmp
+ sed -e "s@^RES=\(.*\)@RES=res_skipname.o@" Makefile > Makefile.tmp
+ cp Makefile.tmp Makefile
+ $RM -f Makefile.tmp
+else
+ $RM -f Makefile.tmp
+ sed -e "s@^RES=\(.*\)@RES=@" Makefile > Makefile.tmp
+ cp Makefile.tmp Makefile
+ $RM -f Makefile.tmp
+fi
+fi
+$RM -f $EXEC $TMP
+cat > $TMP <<__EOF__
+#include <sys/types.h>
+main()
+{
+ u_int32_t foo;
+ exit(0);
+}
+__EOF__
+$COMP >/dev/null 2>&1
+if [ $? -ne 0 ] ; then
+ echo $n " u_int32_t$c"
+ $RM -f Makefile.tmp
+ sed -e "s@^NEED_U_INT32_T=\(.*\)@NEED_U_INT32_T=-DNEED_U_INT32_T@" Makefile > Makefile.tmp
+ cp Makefile.tmp Makefile
+ $RM -f Makefile.tmp
+else
+ $RM -f Makefile.tmp
+ sed -e "s@^NEED_U_INT32_T=\(.*\)@NEED_U_INT32_T=@" Makefile > Makefile.tmp
+ cp Makefile.tmp Makefile
+ $RM -f Makefile.tmp
+fi
+$RM -f $EXEC $TMP
+cat > $TMP <<__EOF__
+#$STRINGH STRINGH
+#$STRINGSH STRINGSH
+#ifdef STRINGH
+#include <string.h>
+#endif
+#ifdef STRINGSH
+#include <strings.h>
+#endif
+main()
+{
+ char *t = "a", **p = NULL, *s = strtoken(&p, t, ",");
+ if (!strcmp(t, s))
+ exit(0);
+ exit(1);
+}
+__EOF__
+$COMP >/dev/null 2>&1
+if [ $? -ne 0 ] ; then
+ echo $n " strtoken$c"
+ NSTRTOKEN=define
+else
+ $EXEC
+ if [ $? -ne 0 ] ; then
+ echo $n " strtoken$c"
+ NSTRTOKEN=define
+ fi
+fi
+$RM -f $EXEC $TMP
+cat > $TMP <<__EOF__
+#$STRINGH STRINGH
+#$STRINGSH STRINGSH
+#ifdef STRINGH
+#include <string.h>
+#endif
+#ifdef STRINGSH
+#include <strings.h>
+#endif
+main()
+{
+ char *t = "1\0", *s;
+ s = strtok(t, ",");
+ if (!strcmp(t, s))
+ exit(0);
+ exit(1);
+}
+__EOF__
+$COMP >/dev/null 2>&1
+if [ $? -ne 0 ] ; then
+ echo $n " strtok$c"
+ NSTRTOK=define
+else
+ $EXEC
+ if [ $? -ne 0 ] ; then
+ echo $n " strtok$c"
+ NSTRTOK=define
+ fi
+fi
+$RM -f $EXEC $TMP
+cat > $TMP << __EOF__
+#include <sys/types.h>
+#include <netinet/in.h>
+main()
+{
+ struct in_addr in;
+ (void)inet_addr("1.2.3.4");
+}
+__EOF__
+$COMP >/dev/null 2>&1
+if [ $? -ne 0 ] ; then
+ echo $n " inet_addr$c"
+ NINETADDR=define
+fi
+$RM -f $EXEC $TMP
+cat > $TMP << __EOF__
+#include <sys/types.h>
+#include <netinet/in.h>
+main()
+{
+ struct in_addr in;
+ in.s_addr = 0x12345678;
+ (void)inet_ntoa(in);
+}
+__EOF__
+$COMP >/dev/null 2>&1
+if [ $? -ne 0 ] ; then
+ echo $n " inet_ntoa$c"
+fi
+$RM -f $EXEC $TMP
+cat > $TMP << __EOF__
+#include <sys/types.h>
+#include <netinet/in.h>
+main()
+{
+ struct in_addr in;
+ in.s_addr = 0x87654321;
+ (void)inet_netof(in);
+}
+__EOF__
+$COMP >/dev/null 2>&1
+if [ $? -ne 0 ] ; then
+ echo $n " inet_netof$c"
+ NINETNETOF=define
+fi
+$RM -f $EXEC $TMP
+echo " "
+#
+#
+#
+echo " "
+echo "Ok, here's your chance...I think you should use $BLOCK, you want"
+echo "which of these ? O_NONBLOCK (POSIX) O_NDELAY (BSD) FIONBIO (SYSV)"
+echo $n "[$BLOCK] -> $c"
+if [ -z "$AUTO_CONFIG" -o -n "$runonce" ] ; then
+ read cc
+else
+ cc=""
+fi
+if [ "$cc" = "none" ] ; then
+ cc=''
+elif [ -z "$cc" ] ; then
+ cc=$BLOCK
+fi
+BLOCK=$cc
+echo "I found $SIGNAL signals."
+if [ "$cc" = "none" ] ; then
+ cc=''
+elif [ "$SIGNAL" = "posix" ] ; then
+ echo "Hmmm...I'm not sure if signal() is reliable or not either..."
+fi
+echo "You can choose between posix, bsd and sysv. What'll it be ?"
+echo $n "[$SIGNAL] -> $c"
+if [ -z "$AUTO_CONFIG" -o -n "$runonce" ] ; then
+ read cc
+else
+ cc=""
+fi
+if [ "$cc" = "none" ] ; then
+ cc=''
+elif [ -z "$cc" ] ; then
+ cc=$SIGNAL
+fi
+SIGNAL=$cc
+if [ "$TIMES" = "none" ] ; then
+ echo "I didn't find either getrusage or times earlier...If you do have"
+ echo "either of these, please tell me now."
+else
+ echo "I found $TIMES, out of getrusage and times. getrusage is"
+ echo "more informative. If you wish to swap your choice, please"
+ echo "do so now."
+fi
+echo $n "[$TIMES] -> $c"
+if [ -z "$AUTO_CONFIG" -o -n "$runonce" ] ; then
+ read cc
+else
+ cc=""
+fi
+if [ "$cc" = "none" ] ; then
+ cc=''
+elif [ -z "$cc" ] ; then
+ cc=$TIMES
+fi
+TIMES=$cc
+
+$RM -f $EXEC $TMP $PLATE
+cat > $SETUP <<__EOF__
+#ifndef __setup_include__
+#define __setup_include__
+#$PARAMH PARAMH
+#$UNISTDH UNISTDH
+#$STRINGH STRINGH
+#$STRINGSH STRINGSH
+#$STDLIBH STDLIBH
+#$STDDEFH STDDEFH
+#$SYSSYSLOGH SYSSYSLOGH
+#$NOINDEX NOINDEX
+#$NSTRERROR NEED_STRERROR
+#$NSTRTOKEN NEED_STRTOKEN
+#$NSTRTOK NEED_STRTOK
+#$NINETADDR NEED_INET_ADDR
+#$NINETNTOA NEED_INET_NTOA
+#$NINETNETOF NEED_INET_NETOF
+#$GETTIMEOFDAY GETTIMEOFDAY
+#$LRAND48 LRAND48
+__EOF__
+if [ "$MALLOCH" = "undef" ] ; then
+ echo "#undef MALLOCH" >> $SETUP
+else
+ echo "#define MALLOCH <$MALLOCH>" >> $SETUP
+fi
+if [ "$BZERO" = "memset" ] ; then
+ cat >> $SETUP <<__EOF__
+#define bzero(a,b) memset(a,0,b)
+#define bcopy(a,b,c) memcpy(b,a,c)
+#define bcmp memcmp
+__EOF__
+fi
+if [ "$BLOCK" = "O_NONBLOCK" ] ; then
+ echo "#define NBLOCK_POSIX" >> $SETUP
+elif [ "$BLOCK" = "O_NDELAY" ] ; then
+ echo "#define NBLOCK_BSD" >> $SETUP
+else
+ echo "#define NBLOCK_SYSV" >> $SETUP
+fi
+if [ "$SIGNAL" = "posix" ] ; then
+ echo "#define POSIX_SIGNALS" >> $SETUP
+elif [ "$SIGNAL" = "bsd" ] ; then
+ echo "#define BSD_RELIABLE_SIGNALS" >> $SETUP
+else
+ echo "#define SYSV_UNRELIABLE_SIGNALS" >> $SETUP
+fi
+if [ "$TIMES" = "times" ] ; then
+ echo "#define TIMES_2" >> $SETUP
+ echo "#undef GETRUSAGE_2" >> $SETUP
+elif [ "$TIMES" = "getrusage" ] ; then
+ echo "#undef TIMES_2" >> $SETUP
+ echo "#define GETRUSAGE_2" >> $SETUP
+else
+ echo "#undef TIMES_2" >> $SETUP
+ echo "#undef GETRUSAGE_2" >> $SETUP
+fi
+echo "#endif" >> $SETUP
+
+FOO=""
+runonce=""
+while [ -z "$FOO" ] ; do
+ if [ -n "$NOSPOOF" ] ; then
+ FOO="Yes"
+ else
+ FOO="No"
+ fi
+ echo ""
+ echo "Many operating systems are running with insecure TCP stacks."
+ echo "This allows IP spoofing attacks, which are very difficult for"
+ echo "operators to track down and ban."
+ echo ""
+ echo "If you are CERTAIN your operating system has secure TCP stacks"
+ echo "you do not need to define this. If you are not certain, define"
+ echo "this and find out if you need it later or not. You can mail the"
+ echo "source mailing list later; someone there can help you determine"
+ echo "if your OS is secure or not."
+ echo ""
+
+ if [ "$OSNAME" = "FreeBSD 2.2" ]; then
+ echo "Your version of FreeBSD is 2.2-Release or later, so you do not"
+ echo "need to run nospoof."
+ echo ""
+ FOO=No
+ fi
+
+ if [ "$OSNAME" = "FreeBSD" ]; then
+ echo "If your version of FreeBSD is 2.2-Release or later, you do not"
+ echo "need to run nospoof."
+ echo ""
+ fi
+
+ echo "Do you have an insecure operating system and therefore want to"
+ echo "use the server anti-spoof protection?"
+ echo $n "[$FOO] -> $c"
+ if [ -z "$AUTO_CONFIG" -o -n "$runonce" ] ; then
+ read cc
+ else
+ cc=""
+ runonce=Yes
+ fi
+ if [ -z "$cc" ] ; then
+ cc=$FOO
+ fi
+ case "$cc" in
+ [Yy]*)
+ NOSPOOF="1"
+ ;;
+ [Nn]*)
+ NOSPOOF=""
+ ;;
+ *)
+ echo ""
+ echo "You need to enter either Yes or No here..."
+ echo ""
+ FOO=""
+ ;;
+ esac
+done
+
+if [ -n "$NOSPOOF" ] ; then
+
+FOO=""
+runonce=""
+while [ -z "$FOO" ] ; do
+ FOO="$NOSPOOF_SEED01"
+ echo "For security, the nospoof code uses two special values, called"
+ echo "seeds. Here, please enter one of them. The values are in"
+ echo "hexidecimal (base 16) using the digits 0123456789abcdef. Each"
+ echo "value can contain up to 8 digits, and should be specified in the"
+ echo "form 0x12345678. If you use the defaults, that should be ok, but"
+ echo "it is more secure if you choose your own special values and keep"
+ echo "them secret."
+ echo $n "[$FOO] -> $c"
+ if [ -z "$AUTO_CONFIG" -o -n "$runonce" ] ; then
+ read cc
+ else
+ cc=""
+ runonce=Yes
+ fi
+ if [ -z "$cc" ] ; then
+ cc=$FOO
+ fi
+ case "$cc" in
+ 0x[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])
+ NOSPOOF_SEED01=$cc
+ ;;
+ [0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])
+ NOSPOOF_SEED01=0x$cc
+ ;;
+ *)
+ echo " "
+ echo "Read the instructions and try again... You did not enter the"
+ echo "value correctly."
+ echo ""
+ FOO=""
+ ;;
+ esac
+done
+
+FOO=""
+runonce=""
+while [ -z "$FOO" ] ; do
+ FOO="$NOSPOOF_SEED02"
+ echo "For security, the nospoof code uses two special values, called"
+ echo "seeds. Here, please enter one of them. The values are in"
+ echo "hexidecimal (base 16) using the digits 0123456789abcdef. Each"
+ echo "value can contain up to 8 digits, and should be specified in the"
+ echo "form 0x12345678. If you use the defaults, that should be ok, but"
+ echo "it is more secure if you choose your own special values and keep"
+ echo "them secret."
+ echo $n "[$FOO] -> $c"
+ if [ -z "$AUTO_CONFIG" -o -n "$runonce" ] ; then
+ read cc
+ else
+ cc=""
+ runonce=Yes
+ fi
+ if [ -z "$cc" ] ; then
+ cc=$FOO
+ fi
+ case "$cc" in
+ 0x[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])
+ NOSPOOF_SEED02=$cc
+ ;;
+ [0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])
+ NOSPOOF_SEED02=0x$cc
+ ;;
+ *)
+ echo " "
+ echo "Read the instructions and try again... You did not enter the"
+ echo "value correctly."
+ echo ""
+ FOO=""
+ ;;
+ esac
+done
+
+# this matches a NOSPOOF check waaaaaay up there
+fi
+
+FOO=""
+runonce=""
+while [ -z "$FOO" ] ; do
+ FOO="$DPATH"
+ echo ""
+ echo "What directory are all the server configuration files in?"
+ echo $n "[$FOO] -> $c"
+ if [ -z "$AUTO_CONFIG" -o -n "$runonce" ] ; then
+ read cc
+ else
+ cc=""
+ runonce=Yes
+ fi
+ if [ -z "$cc" ] ; then
+ cc=$FOO
+ fi
+done
+DPATH=$cc
+
+FOO=""
+runonce=""
+while [ -z "$FOO" ] ; do
+ FOO="$SPATH"
+ echo ""
+ echo "What is the explicit path to where the ircd binary will be"
+ echo "installed? This should point to a file, not a directory"
+ echo $n "[$FOO] -> $c"
+ if [ -z "$AUTO_CONFIG" -o -n "$runonce" ] ; then
+ read cc
+ else
+ cc=""
+ runonce=Yes
+ fi
+ if [ -z "$cc" ] ; then
+ cc=$FOO
+ fi
+done
+SPATH=$cc
+
+FOO=""
+runonce=""
+while [ -z "$FOO" ] ; do
+ if [ -n "$HUB" ] ; then
+ FOO="Hub"
+ else
+ FOO="Hub"
+ fi
+ echo ""
+ echo "Would you like to compile as a Halfhub or as a leaf?"
+ echo "The halfhub will be a real hub if set so in unrealircd.conf"
+ echo "Type Hub for selecting hub and Leaf for a leaf.."
+ echo $n "[$FOO] -> $c"
+ if [ -z "$AUTO_CONFIG" -o -n "$runonce" ] ; then
+ read cc
+ else
+ cc=""
+ runonce=Yes
+ fi
+ if [ -z "$cc" ] ; then
+ cc=$FOO
+ fi
+ case "$cc" in
+ [Hh]*)
+ HUB="1"
+ ;;
+ [Ll]*)
+ HUB=""
+ ;;
+ *)
+ echo ""
+ echo "You need to enter either Hub or Leaf here..."
+ echo ""
+ FOO=""
+ ;;
+ esac
+done
+
+DOMAINNAME="box.name"
+FOO=""
+runonce=""
+while [ -z "$FOO" ] ; do
+ FOO="$DOMAINNAME"
+ echo ""
+ echo "What is your box hostname?"
+ echo $n "[$FOO] -> $c"
+ if [ -z "$AUTO_CONFIG" -o -n "$runonce" ] ; then
+ read cc
+ else
+ cc=""
+ runonce=Yes
+ fi
+ if [ -z "$cc" ] ; then
+ cc=$FOO
+ fi
+done
+DOMAINNAME=$cc
+
+FOO=""
+runonce=""
+while [ -z "$FOO" ] ; do
+ if [ -n "$CRYPT_OPER_PASSWORD" ] ; then
+ FOO="Yes"
+ else
+ FOO="No"
+ fi
+ echo ""
+ echo "Do you use encrypted operator passwords?"
+ echo $n "[$FOO] -> $c"
+ if [ -z "$AUTO_CONFIG" -o -n "$runonce" ] ; then
+ read cc
+ else
+ cc=""
+ runonce=Yes
+ fi
+ if [ -z "$cc" ] ; then
+ cc=$FOO
+ fi
+ case "$cc" in
+ [Yy]*)
+ CRYPT_OPER_PASSWORD="1"
+ ;;
+ [Nn]*)
+ CRYPT_OPER_PASSWORD=""
+ ;;
+ *)
+ echo ""
+ echo "You need to enter either Yes or No here..."
+ echo ""
+ FOO=""
+ ;;
+ esac
+done
+
+FOO=""
+runonce=""
+while [ -z "$FOO" ] ; do
+ if [ -n "$CRYPT_LINK_PASSWORD" ] ; then
+ FOO="Yes"
+ else
+ FOO="No"
+ fi
+ echo ""
+ echo "Do you use encrypted incoming link passwords? (N lines only,"
+ echo "C lines must remain unencrypted always)"
+ echo $n "[$FOO] -> $c"
+ if [ -z "$AUTO_CONFIG" -o -n "$runonce" ] ; then
+ read cc
+ else
+ cc=""
+ runonce=Yes
+ fi
+ if [ -z "$cc" ] ; then
+ cc=$FOO
+ fi
+ case "$cc" in
+ [Yy]*)
+ CRYPT_LINK_PASSWORD="1"
+ ;;
+ [Nn]*)
+ CRYPT_LINK_PASSWORD=""
+ ;;
+ *)
+ echo ""
+ echo "You need to enter either Yes or No here..."
+ echo ""
+ FOO=""
+ ;;
+ esac
+done
+
+FOO=""
+runonce=""
+while [ -z "$FOO" ] ; do
+ FOO="$LISTEN_SIZE"
+ echo ""
+ echo "What listen() backlog value do you wish to use? Some servers"
+ echo "have problems with more than 5, others work fine with many, many"
+ echo "more."
+ echo $n "[$FOO] -> $c"
+ if [ -z "$AUTO_CONFIG" -o -n "$runonce" ] ; then
+ read cc
+ else
+ cc=""
+ runonce=Yes
+ fi
+ if [ -z "$cc" ] ; then
+ cc=$FOO
+ fi
+ case "$cc" in
+ [1-9]*)
+ LISTEN_SIZE="$cc"
+ ;;
+ *)
+ echo ""
+ echo "You need to enter a number here."
+ echo ""
+ FOO=""
+ ;;
+ esac
+done
+
+FOO=""
+runonce=""
+while [ -z "$FOO" ] ; do
+ FOO="$NICKNAMEHISTORYLENGTH"
+ echo ""
+ echo "How far back do you want to keep the nickname history?"
+ echo $n "[$FOO] -> $c"
+ if [ -z "$AUTO_CONFIG" -o -n "$runonce" ] ; then
+ read cc
+ else
+ cc=""
+ runonce=Yes
+ fi
+ if [ -z "$cc" ] ; then
+ cc=$FOO
+ fi
+ case "$cc" in
+ [1-9]*)
+ NICKNAMEHISTORYLENGTH="$cc"
+ ;;
+ *)
+ echo ""
+ echo "You need to enter a number here."
+ echo ""
+ FOO=""
+ ;;
+ esac
+done
+
+FOO=""
+runonce=""
+while [ -z "$FOO" ] ; do
+ FOO="$MAXSENDQLENGTH"
+ echo ""
+ echo "What sendq length do you wish to have?"
+ echo $n "[$FOO] -> $c"
+ if [ -z "$AUTO_CONFIG" -o -n "$runonce" ] ; then
+ read cc
+ else
+ cc=""
+ runonce=Yes
+ fi
+ if [ -z "$cc" ] ; then
+ cc=$FOO
+ fi
+ case "$cc" in
+ [1-9]*)
+ MAXSENDQLENGTH="$cc"
+ ;;
+ *)
+ echo ""
+ echo "You need to enter a number here."
+ echo ""
+ FOO=""
+ ;;
+ esac
+done
+
+FOO=""
+runonce=""
+while [ -z "$FOO" ] ; do
+ FOO="$BUFFERPOOL"
+ echo ""
+ echo "What size of a bufferpool (total of ALL sendq's in use) do you"
+ echo "do you wish to have?"
+ echo $n "[$FOO] -> $c"
+ if [ -z "$AUTO_CONFIG" -o -n "$runonce" ] ; then
+ read cc
+ else
+ cc=""
+ runonce=Yes
+ fi
+ if [ -z "$cc" ] ; then
+ cc=$FOO
+ fi
+ case "$cc" in
+ \([1-9]*\))
+ BUFFERPOOL="$cc"
+ ;;
+ *)
+ echo ""
+ echo "You need to enter a number here, either based on"
+ echo "MAXSENDQLENGTH or a literal value. Also, this value"
+ echo "MUST be enclosed in parens -- (9*MAXSENDQLENGTH), for example."
+ echo ""
+ FOO=""
+ ;;
+ esac
+done
+
+FOO=""
+runonce=""
+while [ -z "$FOO" ] ; do
+if [ "$OSNAME" = "Linux" ] ; then
+ FOO="256"
+elif [ "$OSNAME" = "Linux (with GLIBC 2.x or greater)" ] ; then
+ FOO="256"
+else
+ FOO="$MAXCONNECTIONS"
+fi
+ echo ""
+ echo "How many file descriptors (or sockets) can the irc server use?"
+ echo $n "[$FOO] -> $c"
+ if [ -z "$AUTO_CONFIG" -o -n "$runonce" ] ; then
+ read cc
+ else
+ cc=""
+ runonce=Yes
+ fi
+ if [ -z "$cc" ] ; then
+ cc=$FOO
+ fi
+ case "$cc" in
+ [1-9][0-9][0-9]*)
+ MAXCONNECTIONS="$cc"
+ ;;
+ *)
+ echo ""
+ echo "You need to enter a number here, greater or equal to 100."
+ echo ""
+ FOO=""
+ ;;
+ esac
+done
+
+#
+# check FD_SETSIZE and override if needed.
+#
+
+cat > $TMP <<__EOF__
+#include <stdio.h>
+#include <sys/types.h>
+
+#ifndef FD_SETSIZE
+#define FD_SETSIZE -1
+#endif
+
+/*
+ * Prints "notdef" if FD_SETSIZE is undefined,
+ * "ok" if FD_SETSIZE is at least as large as provided on the
+ * compile command line (-DMAXCONNECTIONS=1234)
+ * "###" if it is less. (### is the FD_SETSIZE value)
+ */
+int
+main(int argc, char *argv[])
+{
+ if (FD_SETSIZE == -1)
+ printf("notdef\n");
+ else if (FD_SETSIZE >= MAXCONNECTIONS)
+ printf("ok\n");
+ else
+ printf("%d\n", FD_SETSIZE);
+
+ return 0;
+}
+__EOF__
+$COMP "-DMAXCONNECTIONS=$MAXCONNECTIONS" >/dev/null 2>&1
+if [ $? -ne 0 ] ; then
+ echo " "
+ echo "I could not derrive what your system allows for the maximum number"
+ echo "of connections becuase the test program did not compile."
+ echo " "
+ FD_SETSIZE=""
+else
+ fd_setsize_ok=`$EXEC`
+ case $fd_setsize_ok in
+ notdef)
+ echo " "
+ echo "I could not derrive what your system allows for the maximum"
+ echo "number of connections because the test program did not find"
+ echo "a system-supplied value for FD_SETSIZE. Assuming it is"
+ echo "defined correctly but the test program cannot find it."
+ echo " "
+ FD_SETSIZE=""
+ ;;
+ ok)
+ echo " "
+ echo "Your system-supplied value for FD_SETSIZE is large enough"
+ echo "for ircd to leave it untouched."
+ echo " "
+ FD_SETSIZE=""
+ ;;
+ *)
+ echo " "
+ echo "Your system-supplied value for FD_SETSIZE is $fd_setsize_ok"
+ echo "but you requested $MAXCONNECTIONS for ircd. FD_SETSIZE will"
+ echo "be overridden using -DFD_SETSIZE=$MAXCONNECTIONS when"
+ echo "compiling ircd."
+ echo " "
+ FD_SETSIZE=$MAXCONNECTIONS
+ ;;
+ esac
+fi
+
+if [ -n "$FD_SETSIZE" ] ; then
+ $RM -f Makefile.tmp
+ sed -e "s@^FD_SETSIZE=\(.*\)@FD_SETSIZE=-DFD_SETSIZE=$FD_SETSIZE@" Makefile > Makefile.tmp
+ cp Makefile.tmp Makefile
+ $RM -f Makefile.tmp
+else
+ $RM -f Makefile.tmp
+ sed -e "s@^FD_SETSIZE=\(.*\)@FD_SETSIZE=@" Makefile > Makefile.tmp
+ cp Makefile.tmp Makefile
+ $RM -f Makefile.tmp
+fi
+
+$RM -f $EXEC $TMP
+
+$RM -f ./core
+#
+# create the $OPTIONS_H file
+#
+rm -f $OPTIONS_H
+cat > $OPTIONS_H << __EOF__
+
+/*
+ * VERSION: $IRCD_VERSION
+ * DATE: $CONF_DATE
+ * OS: $OSNAME
+ *
+ * You shouldn't have to edit this file, if you really need to change
+ * something, i'd suggest running Config again.
+ */
+
+#define MYOSNAME "$OS"
+#define DPATH "$DPATH"
+#define SPATH "$SPATH"
+#define DOMAINNAME "$DOMAINNAME"
+#define LISTEN_SIZE $LISTEN_SIZE
+#define MAXSENDQLENGTH $MAXSENDQLENGTH
+#define BUFFERPOOL $BUFFERPOOL
+#define MAXCONNECTIONS $MAXCONNECTIONS
+#define NICKNAMEHISTORYLENGTH $NICKNAMEHISTORYLENGTH
+__EOF__
+
+if [ -n "$CRYPT_OPER_PASSWORD" ] ; then
+ echo "#define CRYPT_OPER_PASSWORD 1" >> $OPTIONS_H
+else
+ echo "#undef CRYPT_OPER_PASSWORD" >> $OPTIONS_H
+fi
+if [ -n "$CRYPT_LINK_PASSWORD" ] ; then
+ echo "#define CRYPT_LINK_PASSWORD 1" >> $OPTIONS_H
+else
+ echo "#undef CRYPT_LINK_PASSWORD" >> $OPTIONS_H
+fi
+if [ -n "$HUB" ] ; then
+ echo "#define HUB 1" >> $OPTIONS_H
+else
+ echo "#undef HUB" >> $OPTIONS_H
+fi
+
+if [ -n "$NOSPOOF" ] ; then
+ echo "#define NOSPOOF 1" >> $OPTIONS_H
+else
+ echo "#undef NOSPOOF" >> $OPTIONS_H
+fi
+if [ -n "$NOSPOOF_SEED01" ] ; then
+ echo "#define NOSPOOF_SEED01 $NOSPOOF_SEED01" >> $OPTIONS_H
+fi
+if [ -n "$NOSPOOF_SEED02" ] ; then
+ echo "#define NOSPOOF_SEED02 $NOSPOOF_SEED02" >> $OPTIONS_H
+fi
+
+if [ "$OSNAME" = "Linux (with GLIBC 2.x or greater)" ]; then
+ echo "#define GLIBC2_x" >> $OPTIONS_H
+fi
+
+#
+# create the persistant file
+#
+rm -f $OPTIONS
+cat > $OPTIONS << __EOF__
+#
+# VERSION: $IRCD_VERSION
+# DATE: $CONF_DATE
+# OS: $OSNAME
+#
+# You shouldn't have to edit this file, if you really need to change
+# something, i'd suggest running Config again.
+#
+#
+IRCNET="$IRCNET"
+LAST_VERSION="$IRCD_VERSION"
+NOSPOOF="$NOSPOOF"
+NOSPOOF_SEED01="$NOSPOOF_SEED01"
+NOSPOOF_SEED02="$NOSPOOF_SEED02"
+DPATH="$DPATH"
+SPATH="$SPATH"
+CRYPT_OPER_PASSWORD="$CRYPT_OPER_PASSWORD"
+CRYPT_LINK_PASSWORD="$CRYPT_LINK_PASSWORD"
+LISTEN_SIZE="$LISTEN_SIZE"
+MAXSENDQLENGTH="$MAXSENDQLENGTH"
+BUFFERPOOL="$BUFFERPOOL"
+MAXCONNECTIONS="$MAXCONNECTIONS"
+NICKNAMEHISTORYLENGTH="$NICKNAMEHISTORYLENGTH"
+HUB="$HUB"
+DOMAINNAME="$DOMAINNAME"
+__EOF__
+
+if [ "$OSNAME" = "Linux (with GLIBC 2.x or greater)" ]; then
+ echo "GLIBC2_x="YES"" >> $OPTIONS
+ echo ""
+fi
+
+cat << __EOF__
+
+ _____________________________________________________________________
+| |
+| UnrealIRCd Compile-Time Config |
+| |
+| The file "$OPTIONS" was either created or rewritten to contain your |
+| answers to the above questions. |
+| |
+|_____________________________________________________________________|
+|_____________________________________________________________________|
+| |
+| Now all you have todo is type 'make' and let it compile. When thats |
+| done, you will receive other instructions on what todo next. |
+| |
+|_____________________________________________________________________|
+|_____________________________________________________________________|
+| - The UnrealIRCd Team - |
+| * Stskeeps stskeeps@tspre.org
+| * codemastr codemastr@tspre.org
+|_____________________________________________________________________|
+__EOF__
--- /dev/null
+Send donations to:
+
+UnrealIRCd Project
+P.O.Box 52
+7400 Herning
+Denmark
+
+(if you want to that is.. I mean .. I do my coding for fun.. -
+ send a teddybear or something to my nephews or something for
+ my nieces.. so they can keep quiet while I'm trying to do anything)
+
+ Disks, HD's, free internet time or alike are welcome ;p ;)
+
+-- Techie (which HAD got 20 MB free HD space out of 400 MB on his own puter)
+ (just got a 8.4gb and rh6.0 *_*)
+ (and used 200 MB on his shell to code this :>) ..
+ - oh and btw i'm male:P (*looks at BlueFlame^*)
+
+
+[ $Id$ ]
--- /dev/null
+$Id$
+
+Installation Procedures for the UnrealIRCD:
+=======================================================================
+Created by Stskeeps <stskeeps@tspre.org>
+=======================================================================
+
+This document describes how to install ircd, the unix daemon that acts as
+an IRC server.
+
+For more information on UnrealIRCD contact us at
+ unreal-dev@lists.sourceforge.net
+
+The UnrealIRCD is available from http://unreal.tspre.org
+along with the latest copy of this document.
+
+
+=======================================================================
+This version of the UnrealIRCD is known to compile on the following
+platforms, and with the following compilers. If you wish to add to this
+list, send the relevant information to us.
+
+OS and Version Compiler and Version Comments
+------------------- ------------------------ -------------------------------
+NetBSD 1.2B gcc 2.7.2
+
+FreeBSD 2.1.0 gcc 2.6.3 Do NOT use crypt at all...
+
+SunOS 4.1.4 gcc 2.7-96q1 (Cygnus)
+
+Solaris 2.4 gcc 2.7-96q1 (Cygnus) (SunOS 5.4)
+
+Solaris 2.5 SunWorks Pro C (SunOS 5.5.1)
+ cc: SC4.0 18 Oct 1995 C 4.0
+
+Digital Unix 3.2 gcc 2.7-96q3 (Cygnus)
+
+Linux 2.0.24 gcc 2.7.2.1
+
+HPUX 9.01 gcc 2.6.3
+
+HPUX 10.01 gcc 2.7-96q3 (Cygnus)
+
+Linux PPC (iMac)
+
+AmigaOS 3.0 GCC egcs-2.91.66 (compile with -D_AMIGA)
+
+Windows NT/95 MSVC++ 4.0
+
+Linux Mandrake Read FAQ
+=======================================================================
+Unpacking the Distribution
+
+If you are reading this, you have most likely already done this, but to
+recap:
+
+The UnrealIRCD server comes tarred and gziped. To uncompress it and expand
+it, use the following commands at the Unix prompt:
+
+gzip -d Unreal3.0.tar.gz
+tar -xvf Unreal3.0.tar
+
+This will create a new directory called Unreal3.0 and unpack the source
+into it.
+
+=======================================================================
+Editing the Configuration Files
+
+In previous versions of the source code many files had to be edited to
+make things right for any given server.
+
+In this version you DO NOT NEED TO EDIT THE Makefile OR ANY FILES
+IN include! That is, unless you set some strange options. If you
+find the need to edit include/config.h, for example,
+mail us and tell us why ; Config can be made smarter, and that will make
+it so you won't have to edit anything for the next version.
+
+=======================================================================
+Compiling Your Server
+
+Windows users: You must compile the Config program first. To do this
+run the following command: $CC src\Config.c
+where $CC is the name of your compiler. for MSVC users that is 'cl'
+
+To build the server, simply run
+ % ./Config
+to start the configuraton program. This program looks at your system
+and generate the include/setup.h, include/settings.h, and Options files.
+You will be asked some questions. Usually the default answers are the best
+ones and most correct. To accept the default, just hit RETURN.
+
+Next, type 'make'. This will compile your server. Depending on your system,
+this may be a good time for a caffeine break. (MSVC users run 'nmake')
+
+Hopefully, the server will compile without incident. If it does not, and
+you are not able to determine the error, please email
+unreal-dev@lists.sourceforge.net and hopefully someone will be able to help you with the problem. If you
+do need to fix something, mail there with a patch.
+
+BE CERTAIN TO INCLUDE OPERATING SYSTEM INFORMATION (uname -a) AND COMPILER
+VERSION (gcc -v, for instance) IN ALL BUG REPORTS.
+
+
+=======================================================================
+Installing the Files
+
+'make install' does not work in this release -- it doesn't do anything
+except a compile if that is needed.
+
+The only files you need are the binary from src/ircd and and an ircd.conf
+(see below for copying doc/example.conf as your initial ircd.conf). You
+probably will want to create a MOTD file too, as well as place the man
+pages from the doc directory to appropriate place in your system.
+
+
+=======================================================================
+Configuring Your Server
+
+The previous step places a file named 'example.conf' into your irc
+directory you specified to Config.
+
+To create an IRC configuration file, edit: ircd.conf
+
+Now edit this file to reflect your server. The file is mainly
+self-explanatory. Note that if you plan to use your server on ROXnet,
+make sure that you have the following line:
+
+U:services.roxnet.org:*:*
+
+If you need help configuring your file, please connect to ROXnet,
+(irc.flirt.org or irc.roxnet.org) - go to channel #UnrealIRCd, and ask.
+
+
+=======================================================================
+Starting Your Server
+
+Simply enter the complete path to the executable into the Unix command
+line, then hit return. Your server is now operational, assuming that you
+have completed all the steps described above.
+
+NOTE: If you get something like the following when running ircd:
+
+ircd fd table too big
+Hard Limit: 256 IRC max: 1024
+Fix MAXCONNECTIONS
+
+You need to change config.h and recompile. Find the line that says
+"#define MAXCONNECTIONS 1024", and change it to the number given after
+"Hard Limit" (most likely 256), then make the server again, following the
+above instructions.
+
+Enjoy!
+- The UnrealIRCd Team - unreal-dev@lists.sourceforge.net
--- /dev/null
+ 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.
+\f
+ 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.)
+\f
+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.
+\f
+ 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.
+\f
+ 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
+\f
+ 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.
--- /dev/null
+#/************************************************************************
+#* IRC - Internet Relay Chat, Makefile
+#* Copyright (C) 1990, Jarkko Oikarinen
+#*
+#* 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#*
+#* $Id$
+#*/
+
+CC=gcc
+INCLUDEDIR=../include
+NETWORKSDIR=
+FROMDOS=/home/cmunk/bin/4dos
+# [CHANGEME]
+# Default flags:
+# Change XCFLAGS if you don't like what Config puts there. Same with
+# IRCDLIBS.
+#
+# If you are configuring by hand, try "-O -g" for XCFLAGS, and leave
+# IRCDLIBS blank. If that fails, try recomendations below.
+#
+XCFLAGS=
+IRCDLIBS=
+
+#
+# use the following on MIPS:
+#CFLAGS= -systype bsd43 -DSYSTYPE_BSD43 -I$(INCLUDEDIR)
+# For Irix 4.x (SGI), use the following:
+#CFLAGS= -g -cckr -I$(INCLUDEDIR)
+#
+# on NEXT use:
+#CFLAGS=-bsd -I$(INCLUDEDIR)
+#on NeXT other than 2.0:
+#IRCDLIBS=-lsys_s
+#
+# AIX 370 flags
+#CFLAGS=-D_BSD -Hxa -I$(INCLUDEDIR)
+#IRCDLIBS=-lbsd
+#
+# Dynix/ptx V2.0.x
+#CFLAGS= -I$(INCLUDEDIR) -O -Xo
+#IRCDLIBS= -lsocket -linet -lnsl -lseq
+#
+# Dynix/ptx V1.x.x
+#IRCDLIBS= -lsocket -linet -lnsl -lseq
+#
+#use the following on SUN OS without nameserver libraries inside libc
+#IRCDLIBS=-lresolv
+#
+# Solaris 2
+#IRCDLIBS=-lsocket -lnsl -lresolv -L/usr/ucblib -R/usr/ucblib -lgen
+#
+# ESIX
+#CFLAGS=-O -I$(INCLUDEDIR) -I/usr/ucbinclude
+#IRCDLIBS=-L/usr/ucblib -L/usr/lib -lsocket -lucb -lns -lnsl
+#
+# LDFLAGS - flags to send the loader (ld). SunOS users may want to add
+# -Bstatic here.
+#
+#LDFLAGS=-Bstatic
+#
+#Dell SVR4
+#CC=gcc
+#CFLAGS= -I$(INCLUDEDIR) -O2
+#IRCDLIBS=-lsocket -lnsl -lucb
+
+# [CHANGEME]
+# IRCDMODE is the mode you want the binary to be.
+# The 4 at the front is important (allows for setuidness)
+#
+# WARNING: if you are making ircd SUID or SGID, check config.h to make sure
+# you are not defining CMDLINE_CONFIG
+IRCDMODE = 711
+
+# [CHANGEME]
+# IRCDDIR must be the same as DPATH in include/config.h
+#
+IRCDDIR=/usr/local/lib/ircd
+
+# [CHANGEME]
+# Some SunOS versions want this. Try it without first.
+#RES=res_init.o res_comp.o res_mkquery.o
+# BSDI systems want this.
+#RES=res_skipname.o
+# The rest are perfectly content with this.
+RES=
+
+# [CHANGEME]
+# If you get a compile-time error dealing with u_int32_t, comment out
+# this line.
+# NEED_U_INT32_T= -DNEED_U_INT32_T
+NEED_U_INT32_T=
+
+# [CHANGEME]
+# If you get a link-time error dealing with strtoul, comment out
+# this line.
+# STRTOUL= strtoul.o
+STRTOUL=
+
+# [CHANGEME]
+# If you get crashes around a specific number of clients, and that client
+# load comes close or a little over the system-defined value of FD_SETSIZE,
+# override it here and see what happens.
+FD_SETSIZE=
+
+CFLAGS=-I$(INCLUDEDIR) $(XCFLAGS) $(NEED_U_INT32_T) $(FD_SETSIZE)
+
+SHELL=/bin/sh
+SUBDIRS=src
+BINDIR=$(IRCDDIR)
+MANDIR=/usr/local/man
+INSTALL=/usr/bin/install
+RM=rm
+CP=cp
+TOUCH=touch
+
+all: build
+
+MAKEARGS = 'CFLAGS=${CFLAGS}' 'CC=${CC}' 'IRCDLIBS=${IRCDLIBS}' \
+ 'LDFLAGS=${LDFLAGS}' 'IRCDMODE=${IRCDMODE}' \
+ 'BINDIR=${BINDIR}' 'INSTALL=${INSTALL}' \
+ 'INCLUDEDIR=${INCLUDEDIR}' 'IRCDDIR=${IRCDDIR}' \
+ 'MANDIR=${MANDIR}' 'RM=${RM}' 'CP=${CP}' 'TOUCH=${TOUCH}' \
+ 'RES=${RES}' 'SHELL=${SHELL}' 'STRTOUL=${STRTOUL}'
+
+server:
+build:
+ -@if [ ! -f include/setup.h ] ; then \
+ echo "Hmm...doesn't look like you've run Config..."; \
+ echo "Doing so now."; \
+ sh Config; \
+ fi
+ @for i in $(SUBDIRS); do \
+ echo "Building $$i";\
+ ( cd $$i; ${MAKE} ${MAKEARGS} build; ) \
+ done
+ @echo ' __________________________________________________ '
+ @echo '| Compile is now complete. Now you have to go do |'
+ @echo '| The load-time configuration - try go read the |'
+ @echo '| file "dynconf" using your favourite viewer or |'
+ @echo '| editor. The file will contain instructions on how|'
+ @echo '| to do the dynamic configuration :) |'
+ @echo '| |'
+ @echo '| Thanks for using Unreal IRCd! If you are in need |'
+ @echo '| for any kind of help regarding the IRCd email us |'
+ @echo '| at unreal-dev@lists.sourceforge.net |'
+ @echo '|__________________________________________________|'
+
+clean:
+ $(RM) -f *~ \#* core *.orig include/*.orig
+ @for i in $(SUBDIRS); do \
+ echo "Cleaning $$i";\
+ ( cd $$i; ${MAKE} ${MAKEARGS} clean; ) \
+ done
+ -@if [ -f include/setup.h ] ; then \
+ echo "To really restart installation, remove include/setup.h" ; \
+ fi
+ -@if [ -f include/settings.h ] ; then \
+ echo "and include/settings.h" ; \
+ fi
+
+cleandir: clean
+ rm -rf include/networks.h include/setup.h include/settings.h Makefile Settings
+
+makex: fromdos
+ chmod +x Config newnet bsdinstall ircd ircdcron/ircdchk killircd
+ chmod +x makeconf rehash ircdreg
+
+fromdos: cleandir
+ $(FROMDOS) -dv *
+ $(FROMDOS) -dv src/*
+ $(FROMDOS) -dv include/*
+ $(FROMDOS) -dv doc/*
+ $(FROMDOS) -dv crypt/*
+ $(FROMDOS) -dv ircdcron/*
+makedist: makex
+ echo "Making UnrealIRCd compatible IRCd Dist."
+
+stamp: makedist
+ echo "/* Auto created release stamping */" > include/stamp.h
+ echo "#define RELEASEID2 \"`date +%s`\"" >> include/stamp.h
+ echo "#define RELEASESTUFF \"`hostname`\"" >> include/stamp.h
+ echo "" >> include/stamp.h
+
+depend:
+ @for i in $(SUBDIRS); do \
+ echo "Making dependencies in $$i";\
+ ( cd $$i; ${MAKE} ${MAKEARGS} depend; ) \
+ done
+
+install: all
+ @echo "Now install by hand; make install is broken."
+
--- /dev/null
+Some notes to remember:
+-----------------------
+* Don't EVER try to link it to incompatible IRCds (this does not
+ include services). It is *INCOMPATIBLE*. Please HEED this warning!!!
+
+* If you need any help you can email me at stskeeps@tspre.org
+
+* Please read the Changes file about release notes
+
+* Bugs? Read Unreal.nfo
+
+* Unreal IRCd is not meant to be a simple IRCd, rather an advanced
+ IRCd, please read the documentation before asking questions
+
+[ $Id$ ]
--- /dev/null
+TODO: (Possible 3.1)
+* Limit calls to these functions using parse()
+ 0.00 3.91 0.00 6475 0.00 0.00 check_registered
+ 0.00 3.91 0.00 6827 0.00 0.00 check_registered_user
+* Optimize:
+ 0.00 3.91 0.00 1292 0.00 0.01 is_banned
+ 12.55 9.61 2.57 41320 0.06 0.10 check_lusers
+ 4.64 11.54 0.95 41566 0.02 0.02 count_channels
+ 3.08 13.96 0.63 850968 0.00 0.00 flush_connections
+ (fdlists?)
+ 0.15 19.62 0.03 29 1.03 1.80 send_list
+* Add svsvline for global vlines
+* New /whowas system /who as well
+* Short MOTDs
+* B:Lines
+* Channel mode +d
+* Raising PING bug
+* Make alternative I/O engine using poll()
+* Remove some of the _little_ config.h defines and replace with
+ unrealircd.conf lines, ex ADMINCHAT, REMOTE_REHASH
+* X-Windows GUI (how bad it can be but hey! :P)
--- /dev/null
+
+ TSpre.org
+
+Many here maybe not heard of the Story
+how IRC started (and how EFnet started)
+EFnet's name means "Eris-Free Network".
+Eris was a central hub at the fomer world-
+wide IRC network, that anyone could just add
+C:N pairs for and connect to.
+
+I was inspired of the tought of a network
+where anyone could link without application and all
+that shit..
+
+Combined with the IRCd i made (Unreal) and the tspre.org
+domain i got donated by Nutcais (my IRC bro). Ive decided to
+start the TSpre IRC network, where anyone with TSpre servers
+(dreamforge, IRCu p9, and their alike)
+
+(mostly preffered is Unreal thou).. Its an experimental
+network where people can test out thier IRCds and
+wIRds without having to fill out apps and so on.
+
+There are no real rules. So just have fun :)
+
+See http://www.tspre.org for more info on this=)
+
+--Stskeeps (stskeeps@tspre.org)
--- /dev/null
+===============================================
+= UnrealIRCd v3.0 =
+===============================================
+ Was brought to you by:
+ * Stskeeps <stskeeps@tspre.org>
+ * codemastr <codemastr@tspre.org>
+
+ Precenses on the Internet:
+ * http://unreal.tspre.org or http://unreal.sourceforge.net
+ * ftp://unreal.sourceforge.net/pub/unreal
+ * ftp://ftp.shadow-realm.org/pub/ircd/UnrealIRCd
+
+ CVS Repository:
+ * Alpha versions (or beta)
+ ==========================
+cvs -z9 -d :pserver:anonymous@cvs.unreal.sourceforge.net:/cvsroot/unreal login
+ (just press enter when it asks for password)
+cvs -z9 -d :pserver:anonymous@cvs.unreal.sourgeforge.net:/cvsroot/unreal co alpha
+
+ * To get support
+ ================
+ * IRC: /server irc.flirt.org 6667 - /join #unrealircd
+ * Mailing list: unreal-support@lists.sourceforge.net (for support)
+
+ * Got a bug to report?
+ ======================
+ * If the server crashes and dumps core do this:
+ * Go into the Unreal directory and type this:
+ gdb src/ircd core.filename
+ where core.filename is the filename in the dumping core message
+ if it loads gdb, (not saying "command not found" etc), type "bt" in
+ the program (type "quit" to get out again)
+
+ The output coming out there please mail it to
+ unreal-dev@lists.sourceforge.net, along with OS type,
+ what "uname -a" says, any clues what it is, if you did anything etc
+ etc. Please keep the core dump files if we ask you to mail us them
+ if needed
+
+ * If you experince any wierdnesses (that doesnt crash the server)
+ please mail unreal-dev@lists.sourceforge.net with any clues on what
+ you did, what you experinced etc.
+
+ * Got a suggestion?
+ ===================
+ * Mail it to unreal-dev@lists.sourceforge.net :) or catch one from
+ the Unreal team online on IRC:)
+
+
\ No newline at end of file
--- /dev/null
+#! /bin/sh
+#
+# $Id$
+# Old: @(#)install.sh 4.5 (Berkeley) 10/12/83
+#
+cmd=/bin/mv
+strip=""
+chmod="/bin/chmod 755"
+chown="chown -f root"
+chgrp="/bin/chgrp -f bin"
+while true ; do
+ case $1 in
+ -s ) strip="strip"
+ shift
+ ;;
+ -c ) cmd="/bin/cp"
+ shift
+ ;;
+ -m ) chmod="/bin/chmod $2"
+ shift
+ shift
+ ;;
+ -o ) chown="/etc/chown -f $2"
+ shift
+ shift
+ ;;
+ -g ) chgrp="/bin/chgrp -f $2"
+ shift
+ shift
+ ;;
+ -d ) cmd="/bin/mkdir"
+ shift
+ ;;
+ * ) break
+ ;;
+ esac
+done
+
+if [ ! ${2-""} ]
+then echo "install: no destination specified"
+ exit 1
+fi
+if [ ${3-""} ]
+then echo "install: too many files specified -> $*"
+ exit 1
+fi
+if [ $1 = $2 -o $2 = . ]
+then echo "install: can't move $1 onto itself"
+ exit 1
+fi
+case $cmd in
+/bin/mkdir )
+ file=$2/$1
+ ;;
+* )
+ if [ '!' -f $1 ]
+ then echo "install: can't open $1"
+ exit 1
+ fi
+ if [ -d $2 ]
+ then file=$2/$1
+ else file=$2
+ fi
+ /bin/rm -f $file
+ ;;
+esac
+
+case $cmd in
+/bin/mkdir )
+ if [ ! -d "$file" ]
+ then $cmd $file
+ fi
+ ;;
+* )
+ $cmd $1 $file
+ if [ $strip ]
+ then $strip $file
+ fi
+ ;;
+esac
+
+$chown $file
+$chgrp $file
+$chmod $file
--- /dev/null
+#************************************************************************
+#* IRC - Internet Relay Chat, ircd/crypt/Makefile
+#* Copyright (C) 1991 Darren Reed
+#*
+#* 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#*
+#* $Id$
+#*/
+#
+# Change this to the path of your local ircd.conf file
+#
+
+IRCDCONF = ../ircd.conf
+
+all: mkpasswd
+crypt: install
+
+mkpasswd: mkpasswd.c
+ cc -lcrypt -O mkpasswd.c -o mkpasswd
+
+install:
+ crypter ${IRCDCONF}
+ @echo 'done.'
+
+clean:
+ /bin/rm -f mkpasswd
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, ircd/crypt/README
+ * Copyright (C) 1991 Nelson Minar
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ */
+
+The change implemented here is that the operator password in irc.conf
+is no longer stored in plaintext form, but is encrypted the same way
+that user passwords are encrypted on normal UNIX systems. Ie, instead
+of having
+
+ O:*:goodboy:Nelson
+
+in your ircd.conf file, you have
+
+ O:*:sCnvYRmbFJ7oI:Nelson
+
+You still type "/oper Nelson goodboy" to become operator. However, if
+someone gets ahold of your irc.conf file, they can no longer figure
+out what the password is from reading it. There are still other
+security holes, namely server-server passwords, but this closes one
+obvious problem.
+
+So how do you generate these icky looking strings for passwords?
+There's a simple program called mkpasswd to do that for you. Just run
+mkpasswd, and at the prompt type in your plaintext password. It will
+spit out the encrypted password, which you should then just copy into
+the irc.conf file. This should be done only when adding new passwords
+to your irc.conf file. To change over your irc.conf file to use
+encrypted passwords, define CRYPT_OPER_PASSWORD in config.h. You will
+need to recompile your server if you already compiled it with this
+feature disabled. Once compiled, edit the Makefile in this directory
+and chang "IRCDCONF" to your irc.conf file. Then "make install" in this
+directory to replace all the operator passwords in your irc.conf file
+with the encrypted format.
+
+Choose your passwords carefully. Do not choose something in a
+dictionary, make sure its at least 5 characters. Anything past 8
+characters is ignored.
+
+One thing to note about crypt() passwords - for every plaintext, there
+are 4096 different passwords. Some valid encryptions of "goodboy"
+include t1Ub2RhRQHd4g sCnvYRmbFJ7oI and Xr4Z.Kg5tcdy6. The first
+two characters (the "salt") determine which of the 4096 passwords
+you will get. mkpasswd chooses the salt randomly, or alternately
+will let you specify one on the command line.
+
+see also - crypt(3)
--- /dev/null
+#!/usr/local/bin/perl
+#************************************************************************
+#* IRC - Internet Relay Chat, ircd/crypt/crypter
+#* Copyright (C) 1991 Sean Batt
+#*
+#* 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#*
+#* $Id$
+#*
+#*/
+
+#From Sean Batt sean@coombs.anu.edu.au
+#
+#Temporary output file
+#
+$tmpfile = "/tmp/ircd.conf.tmp";
+
+#
+#Original ircd.conf file
+#
+$ircdconf = @ARGV[0];
+
+print "crypting ",$ircdconf,"\n";
+@saltset = ('a' .. 'z', 'A' .. 'Z', '0' .. '9', '.', '/');
+
+umask(0077);
+open ($ircdout, ">/tmp/ircd.conf.tmp") || die "open $!";
+
+while ($text = <>) {
+#if its not an "O" line we can ignore it
+ $text =~ /^o/i || print ($ircdout $text) && next;
+ chop($text);
+ @oline = split(':', $text);
+ $salt = $saltset[rand(time)%64].$saltset[(rand(time)>>6)%64];
+ $oline[2] = crypt(@oline[2], $salt);
+ print ($ircdout join(':',@oline)."\n");
+}
+close ($ircdout);
+close ($ircdin);
+print "/bin/cp ",$tmpfile," ",$ircdconf,"\n";
+(fork()==0) ? exec("/bin/cp", $tmpfile, $ircdconf) : wait;
+
+#unlink($tmpfile);
--- /dev/null
+/* simple password generator by Nelson Minar (minar@reed.edu)
+ * copyright 1991, all rights reserved.
+ * You can use this code as long as my name stays with it.
+ *
+ * $Id$
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+extern char *getpass();
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+ static char saltChars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
+ char salt[3];
+ char * plaintext;
+ int i;
+
+ if (argc < 2) {
+ srandom(time(0)); /* may not be the BEST salt, but its close */
+ salt[0] = saltChars[random() % 64];
+ salt[1] = saltChars[random() % 64];
+ salt[2] = 0;
+ }
+ else {
+ salt[0] = argv[1][0];
+ salt[1] = argv[1][1];
+ salt[2] = '\0';
+ if ((strchr(saltChars, salt[0]) == NULL) || (strchr(saltChars, salt[1]) == NULL))
+ fprintf(stderr, "illegal salt %s\n", salt), exit(1);
+ }
+
+ plaintext = getpass("Enter Password: ");
+
+ printf("Encryption: %s\n", crypt(plaintext, salt));
+ return 0;
+}
+
--- /dev/null
+# $Id$
+
+on ^367 * if ([$4] != []) {echo *** $1 \($3 - $stime($4)) $2} {echo *** $1-}
+on ^333 * echo *** Topic for $1 set by $2 on $stime($3)
+on ^317 * if (index(012345679 $3) != -1) {echo *** $1 has been idle for $2 seconds. Signon at $stime($3)} {echo *** $1 has been idle for $2 seconds.}
+On ^329 "*" echo *** $1 : created $stime($2)
+on ^
+alias silence quote silence
+alias sile quote silence
+on ^raw_irc "% SILENCE %" echo *** $*
+
+@ hideit = 0
+on ^server_notice "% % NOTICE -- CLIENT*" if (hideit != 1) {echo *** $2-}
+alias show @ hideit = 0;echo *** You can now see clients connecting/exiting
+alias hide @ hideit = 1;echo *** You will no longer see clients connecting/exiting
+
+
+# ctime and sendq written by bry
+# modified by Mmmm
+
+alias ctime {
+ ^on 211 -
+ if ( [$0] )
+ { ^assign SS $0- }
+ { ^assign SS $S }
+
+^on ^211 * {
+ eval ^assign hrs2 ${ ([$7]/60)/60}
+ eval ^assign min2 ${[$7]/60}
+
+ eval ^assign dys ${[$HRS2]/24}
+ eval ^assign hrs ${[$HRS2]-([$DYS]*24)}
+ eval ^assign min ${[$MIN2] - ( ([$HRS]+([$DYS]*24) )*60)}
+ eval ^assign sec ${[$7]-([$MIN2]*60)}
+ @ a = index(\[ $1) - 1
+ @ b = left($a $1)
+ if (index(. $b) == -1)
+ {eval echo *** $1 $[2]DYS days, $[2]HRS hrs, $[2]MIN min, $[2]SEC s}
+ {eval echo \ 2*** $1 $[2]DYS days, $[2]HRS hrs, $[2]MIN min, $[2]SEC s\ 2}
+ }
+ ^stats l $SS
+}
+
+alias sendq {
+ eval ^on ^211 "$SRV *" {
+ @ a = index(\[ $1) - 1
+ @ b = left($a $1)
+ if (index(. $b) == -1)
+ {eval echo *** $[11]2 sendq $1}
+ {eval echo *** $[11]2 sendq \ 2$1\ 2}
+ }
+ if ( [$0] )
+ { ^assign SRV $0- }
+ { ^assign SRV $S }
+ stats l $SRV
+ wait -cmd eval ^on ^211 -"$SRV *"
+}
+
+# If you use Daveman's toolbox or any auto rejoin line, remove the old
+# on raw_irc for KICK, and use the foll. one instead: (Run)
+#
+#ON ^RAW_IRC "% KICK % % *" {
+# IF ([$3]==[$N])
+# {
+# //QUOTE JOIN $2
+# ECHO $MID(11 5 $STIME($TIME())) * You have been kicked off channel $2 by $LEFT($INDEX(! $0) $0) \($MID(1 256 $4-)\)
+# }
+# {
+# ECHO $MID(11 5 $STIME($TIME())) * $3 has been kicked off channel $2 by $LEFT($INDEX(! $0) $0) \($MID(1 256 $4-)\)
+# }
+# }
+
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, doc/AUTHORS
+ * Copyright (C) 1990
+ *
+ * AUTHORS FILE:
+ * This file attempts to remember all contributors to the IRC
+ * developement. Names can be only added this file, no name
+ * should never be removed. This file must be included into all
+ * distributions of IRC and derived works.
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+IRC was conceived of and written by Jarkko Oikarinen <jto@tolsun.oulu.fi>.
+IRC was originally written in University of Oulu, Computing Center.
+Jan 1991 - IRC 2.6 jto@tolsun.oulu.fi
+ - Multiple Channels and protocol changes
+
+Contributions were made by a cast of dozens, including the following:
+
+Markku Jarvinen <mta@tut.fi>: Emacs-like editing facility for the client
+
+Kimmo Suominen <kim@kannel.lut.fi>: HP-UX port
+
+Jeff Trim <jtrim@orion.cair.du.edu>: enhancements and advice
+
+Vijay Subramaniam <vijay@lll-winken.llnl.gov>: advice and ruthless publicity
+
+Karl Kleinpaste <karl@cis.ohio-state.edu>: user's manual
+
+Greg Lindahl <gl8f@virginia.edu>: AUTOMATON code, the Wumpus GM automaton,
+myriad bug fixes
+
+Bill Wisner <wisner@hayes.fai.alaska.edu>: numerous bug fixes and code
+enhancements
+
+Tom Davis <conslt16@zeus.unl.edu> and Tim Russell <russell@zeus.unl.edu>:
+VMS modifications
+
+Markku Savela <msa@tel4.tel.vtt.fi>: advice, support, and being the
+incentive to do some of our *own* coding. :)
+
+Tom Hopkins <hoppie@buengf.bu.edu>: bug fixes, quarantine lines,
+consolidation of various patches.
+
+Christopher Davis <ckd@cs.bu.edu>: EFnet/Anet gateway coding,
+many automata ;), documentation fixing.
+
+Helen Rose <hrose@cs.bu.edu>: documentation updating, and fixing.
+
+Tom Hinds <rocker@bucsf.bu.edu>: emacs client updating.
+
+Tim Miller <cerebus@bu-pub.bu.edu>: various server and client-breaking
+features.
+
+Darren Reed <avalon@coombs.anu.edu.au>: various bug fixes and enhancements.
+Introduced nickname and channelname hash tables into the server.
+
+The version 2.2 release was coordinated by Mike Bolotski
+<mikeb@salmon.ee.ubc.ca>.
+
+The version 2.4 release was coordinated by Markku Savela and
+Chelsea Ashley Dyerman
+
+The version 2.5.2 release was coordinated by Christopher Davis, Helen Rose,
+and Tom Hopkins.
+
+The versions 2.6.2, 2.7 and 2.8 releases were coordinated by Darren Reed.
+
+Contributions for the 2.8 release from the following people:
+Matthew Green <phone@coombs.anu.edu.au>
+Chuck Kane <ckane@ece.uiuc.edu>
+Matt Lyle <matt@oc.com>
+Vesa Ruokonen <ruokonen@lut.fi>
+
+Markku Savela <Markku.Savela@vtt.fi> / April 1990
+Fixed various bugs in 2.2PL1 release server (2.2msa.4) and changed
+sockets to use non-blocking mode (2.2msa.9). [I have absolutely
+nothing to do with clients :-]
+
+Chelsea Ashley Dyerman <chelsea@earth.cchem.berkeley.edu> / April 1990
+Rewrote the Makefiles, restructuring of source tree. Added libIrcd.a to
+the Makefile macros, numerous reformatting of server text messages, and
+added mkversion.sh to keep track of compilation statistics. Numerous
+bug fixes and enhancements, and co-coordinator of the 2.4 release.
+
+Jarle Lyngaas (nmijl@alf.uib.no) added Note functions to ircd.
+
+Armin Gruner <gruner@informatik.tu-muenchen.de> / May, June 1990:
+* Patched KILL-line feature for ircd.conf, works now.
+ Enhancement: Time intervals can be specified in passwd-field.
+ Result: KILL-Line is only active during these intervals
+* Patched PRIVMSG handling, now OPER can specify masks for sending
+ private messages, advantage: msg to all at a specified server or host.
+* Little tests on irc 2.5 alpha, fixed some little typos in client code.
+ Change: common/debug.c has been moved to ircd/s_debug.c, and a
+ irc/c_debug.c has been created, for the benefit that wrong server msg
+ are displayed if client does not recognize them. (strange, if a server
+ sends an 'unknown command', isn't it?)
+
+Tom Hopkins <hoppie@buengf.bu.edu> / September, October 1990:
+* Patched msa's K lines for servers (Q lines).
+* Consolidated several patches, including Stealth's logging patch.
+* Fixed several minor bugs.
+* Has done lots of other stuff that I can't seem to remember, but he
+ always works on code, so he has to have done alot more than three
+ lines worth. :)
+
+Carsten Munk <stskeeps@mp3fans.co.uk> / May and futher 1999:
+* Made many features based on Elite.. :/
+
+Thanks go to those persons not mentioned here who have added their advice,
+opinions, and code to IRC.
+
+Various modifications, bugreports, cleanups and testing by:
+
+Hugo Calendar <hugo@ucscb.ucsc.edu>
+Bo Adler <adler@csvax.cs.caltech.edu>
+Michael Sandrof <ms5n+@andrew.cmu.edu>
+Jon Solomon <jsol@cs.bu.edu>
+Jan Peterson <jlp@hamblin.math.byu.edu>
+Nathan Glasser <nathan@brokaw.lcs.mit.edu>
+Helen Rose <hrose@eff.org>
+Mike Pelletier <stealth@caen.engin.umich.edu>
+Basalat Ali Raja <gwydion@tavi.rice.edu>
+Eric P. Scott <eps@toaster.sfsu.edu>
+Dan Goodwin <fornax@wpi.wpi.edu>
+Noah Friedman <friedman@ai.mit.edu>
+
+[ $Id$ ]
\ No newline at end of file
--- /dev/null
+SmartRoute
+Rule based connects
+Draft 4 - Aug 19, 1994
+by Tony Vencill
+
+Rule based connects allow an admin to specify under what conditions
+a connect should not be allowed. If no rules are specified for a
+given C and/or N line it will be allowed under any condition.
+
+A rule may consist of any legal combination of the following functions
+and operators.
+
+Functions
+---------
+connected(targetmask) - true if a server other than that processing
+ the rule is connected that matches the
+ target mask
+directcon(targetmask) - true if a server other than that processing
+ the rule is directly connected that matches
+ the target mask
+via(viamask, targetmask) - true if a server other than that processing
+ the rule matches the target mask and is
+ connected via a directly connected server
+ that matches the via mask
+directop() - true if an oper is directly connected
+
+Unary operators
+---------------
+! eg: !argument - true if the argument is false
+
+Binary operartors
+-----------------
+&& eg: arg1&&arg2 - true if arg1 and arg2 are both true
+|| eg: arg1||arg2 - true if arg1, arg2, or both are true
+
+Parenthesis () are allowed for grouping arguments, but if no parenthesis
+are included, && will take precedence over ||, ! will take precedence
+over both && and ||, and the function will be evaluated from left to
+right. White space in a rule is ignored. Invalid characters in a rule
+will lead to the rule being ignored.
+
+Examples
+--------
+
+A simple example of a connect rule might be:
+
+connected(*eu.under*)
+
+This might be used in a US undernet server for a Europe CN pair to
+insure that a second Europe link is not allowed if one US-EU link
+already exists. Note that on the undernet, US server names are
+city.state.us.undernet.org and Europe server names are
+city.country.eu.undernet.org.
+
+A more interesting example might be:
+
+connected(*eu.under*) &&
+ ( !direct(*eu.under*) || via(manhat*, *eu.under*) )
+
+Imagine the Boston undernet server uses this rule on its Europe CN
+pairs. This says that if a Europe server is already connected, a
+Boston-Europe connect will not be allowed. It also says that if a
+Europe server does already exist and Boston is not directly connected
+to one or more Europe servers or Manhattan is, the Boston-Europe
+connect will not be allowed. This has the effect of allowing multiple
+US-EU links but attempting to limit these links to one server (ie:
+Boston will not initiate its first Europe link if another server is
+already linking Europe). This rule will also prefer to let Manhattan
+handle the US-EU link by disallowing Boston-Europe links if a Europe
+server is already linked to Manhattan.
+
+A example of the remaining function, directop(), is:
+
+connected(*eu.under*) || directop()
+
+If this line is used on Boston for the Paderborn CN pair, it will allow
+connects to Paderborn only if another Europe server is not already
+connected and there is not an oper on Boston. If this rule is
+overrideable (ie: is applied only to autoconnects as described below),
+then it will disallow Boston autoconnects to Paderborn while a Boston
+oper is online, but allow oper-initiated connects to Paderborn under any
+circumstance. This directop() function could be used to invoke less
+prefered routes only when an oper is not present to handle routing, or
+conversly to allow use of less preferable routes only when an oper is
+present to monitor their performance.
+
+ircd.conf entries
+-----------------
+
+A rule is listed in the ircd.conf file using a D or d line (which can
+be thought of as a "disallow" line). D lines will apply to all oper
+and server originated connects, while d lines will apply only to
+autoconnects (ie: they are overrideable by opers). The formats are:
+
+D:targetmask::rule
+d:targetmask::rule
+
+Remember that newlines are not allowed in conf lines. Two examples
+(from above) are:
+
+D:*eu.under*::connected(*eu.under*)
+d:*eu.under*::connected(*eu.under*) || directop()
+
+Connects originating from other servers will be checked against and
+matching D lines, while matching d lines will be ignored as it will not
+be clear whether or not the connection attempt is oper initiated.
+
+Checking and viewing rules
+--------------------------
+
+The chkconf program that comes with the servers has been modified to
+also check your connect rules. If running in debug mode, parsing errors
+will show up at debug level 8. To view rules online, "/stats d" can be
+used to see all rules and "/stats D" can be used to view those rules
+which affect oper initiated connects and accepts.
+
+Processing and storage
+----------------------
+
+The rules are parsed when the conf file is read and transformed into a
+more efficiently computed form, then all applicable rules are
+evaluated each time a connect command is given or an autoconnect is
+due. If more than one applicable rule is given, only one need
+evaluate to true for the connect to be allowed (ie: the rules are ored
+together). Note that conditions that exist when the connect is
+initiated might differ from conditions when the link is established.
+
+[ $Id$ ]
\ No newline at end of file
--- /dev/null
+[ $Id$ ]
+---------------------------
+Version Elite2.0 ==========
+===========================
+- Since +x was rewritten, the ban bug is 100% fixed. :)
+- Rewrote +x hidden host function completely.
+- Fixed FUNNY bug with hiddenhost and /who (Reported by Prod|gy)
+- Added/Removed irc networks
+- Fixed bug in /watch (Reported/Fixed by Despise)
+- Added nick-change flood protection.
+- Added an awesome manual... ./manual to run
+- Removed /who notice for opers.
+- Added protection of /akill *@* :)
+- Removed java stuff completely. (Java clients are like normal IRC clients...right?)
+- Added new +a mode. This mode can only be set by +q channel owners. When you are +a in a
+ channel, you cannot be deopped or kicked. (Syntax: /mode #chan +a <nick>)
+- Added new +q channel mode. ChanServ must set the channel founder +q so they are also
+ known as channel owners via the ircd. Channel owners are protected and may set
+ other users +a which they will also be protected (but not chan owners).
+ (Syntax: /mode #chan +q <nick>)
+- Re-coded /MAP
+- Changed GLINE notices from sendto_ops to send to all opers with +e flag on.
+- Added (addnet) script, you can run this to add your net settings to the next release.
+- Changed <server> to <ircnetwork> in whois "Blah is an oper on <server>"
+- Added new +L channel mode. If a #chat has a limit (+l) of 10 users, and +L set to channel
+ #chat2, when a user trys to join #chat, they won't get "#chat is full", they will be
+ auto-joined to #chat2 - (Linked channels in other words).
+ (Syntax: /mode #chan +L <linked chan>)
+- Changes user@shadow-33.com to user@user-33.one.com (noone will know one.com is the realhost)
+- Changed +x for IP's from (x.x.x.***) to (x.x.x.network-#)
+- In oline flags * will introduce +e on oper up. (before: required +e in oline flag)
+- Removed +t usermode (UMODE_ALL) - wasn't used.
+- Made 'create your own network setting' feature more stable.
+- Added new channel mode (+x) to disable colored text in channel.
+- Added +C (Co Administrator)
+- Added +T (Technical Administrator)
+- Changed /map to numerics...
+- Made startup message when booting more stable.
+
+Version Elite1.3 (02/23/99)
+============================
+- Cleaned up version.c.SH
+- Added new net settings (netdomain & helpchan)
+- Added new net config creator in ./Config
+- Made ./Config more easier...
+- Created new usermode +j (Java user)
+- New hostname (java.shadownet.org) for java users.
+- Removed RUN_SERVICES code from entire ircd.
+
+Version Elite1.2.4 (02/14/99)
+============================
+- Fixed the nick crash bug! (damn m_kill small error)
+- New network(s) added.
+- Changed one thing in m_gline (nothing big)
+
+Version Elite1.2.3 (02/10/99)
+============================
+- Removed SOCKS checking. (possibly cause of crashing)
+- Added new networks
+
+Version Elite1.2.2 (02/02/99)
+============================
+- Fixed the crashing bug. (Changing nicks with linked servers)
+- Modified AceStar net settings.
+- Q-line notices are back (except for ULined clients).
+- Fixed /kill bug with services.
+
+Version Elite1.2.1 (01/29/99)
+============================
+- Fixed multiple notices from +N / -N
+- Added some text to s_err.c
+- Possibly fixed the odd crashing... ?
+
+Version Elite1.2 (01/24/99)
+============================
+- Netadmin can be used via +N in the oline slot now.
+- When +N is executed, net-wide oper msg's are sent about it.
+- Completely removed the freeze function (it's a toy unlike a command)
+- Changed abit of the GLINE adding notice.
+- Added logging to a file for glines (gline.log)
+- Implemented SOCKS checking (thx Rhom).
+- Changed channel lists only when 2 ppl in chan to 1.
+- Changed sendto_ops function in many places in s_user.c/s_serv.c to
+ sendto_locfailops.
+- Changed GNOTICE in s_user.c/s_serv.c to GLOBOPS
+- Fixed hiddenhost bug with /kill (+w could see real host of oper)
+- Fixed hiddenhost bug with /oper (+s could see real host of oper)
+
+[Special thanks goes out to Rhom for reporting/help patch bugs]
+
+Version Elite1.1.1 (12/12/98)
+=============================
+- Fixed /whois bug (had problems with mIRC clients *sigh*)
+- Fixed /topic bug (didn't allow topic changes at all.)
+
+Version Elite1.1 (12/6/98)
+============================
+- Fixed ./Config script (Net select)
+- Fixed /remgline bug.
+- If ULined clients, channels are not shown which they are in.
+- Fixed +e / +t / +b (non-opers could get +et before)
+- Fixed OperMode notice.
+- Fixed Gline sending extra Global on expire.
+- Fixed /whowas wrong hostname bug (by Thiago)
+- Fixed chkconf ZLINE error (by matt)
+- Added PhazeNet configuration
+- Added option for auto +x in ./Config
+- Freeze was disabled in this version (It will be back in 1.2)
+
+Version Elite1.0 (09/20/98)
+============================
+- Changed Shadow3.9 to Elite1.0 (Starting a new IRCD)
+- Changed some numeric's around in src/s_err.c
+- Auto +x on Oper up.
+- Fixed small error in ./ircd script.
+- Made ./Config more Linux-redhat friendly.
+- Added RelicNet to the ircd.
+- include/config.h is much more compatible with all IRC nets.
+- Added /gline (works 100%) [/gline <user@host> <seconds> <reason>].
+- Fixed up /map.
+- Added UMODE's +e & +t
+ * e: EYES [Can see ppl who /whois, and other notices.]
+ * t: ALL [See's all net notices ie: See's all Client connectings...]
+- Fixed the hiddenhost bug with IP's...
+- Fixed major bug with hiddenhost which caused coredump.
+- Made a new script (makeconf) -- generates the ircd.conf file.
--- /dev/null
+The foll. patches are NEW in 19.mu1 (besides the old patches of stats-w,
+ban, topic, client connect, signon time, trace times in previous .mu
+versions):
+
+* All the modifications contained in U3.2, namely - TSpre8, silence, bquiet
+
+* The K line comments patch.
+
+* The operfail notification patch
+
+* The mixed case userid reject patch
+
+For info on these check the file README.patches
+
+ - Mmmm
+[ $Id$ ]
\ No newline at end of file
--- /dev/null
+
+For starters, not a lot is new. What is ?
+
+ * STATS o and STATS h added;
+
+ * most STATS options are no longer oper-only;
+
+ * privacy fixes to all of WHO, WHOIS, TRACE and STATS;
+
+ * more options in the ircd.conf file;
+
+ * non-debilitating DNS/ident use (DNS routines written specifically
+ for ircd which indludes small local cache);
+
+ * less bugs;
+
+ * easier to compile;
+
+ * heaps and heaps of new numerics;
+
+ * more problems for old clients that do stupid things;
+
+ * more numeric replies which replace old NOTICE's;
+
+ * compulsory ident checks and optional result usage;
+
+ * sendQ can now be class dependant;
+
+ * server handles client flooding better;
+
+ * for more information on changes, bug fixes during development, see
+ ircd/ChangeLog and common/ChangeLog
+
+[ $Id$ ]
\ No newline at end of file
--- /dev/null
+ The Internet Relay Chat Program - IRC
+
+ Author: Jeff Trim, April '89
+ Revised: Greg Lindahl, Oct '90 (gl8f@virginia.edu)
+ Re-Revised: Helen Rose, March '94 (hrose@kei.com)
+
+Have you ever wanted to talk with other computer users in other parts of
+the world? Well guess what? You can! The program is called IRC and it
+is networked much over North America, Europe, and Asia, Oceania, and parts
+of Africa. This program is a substitution for talk(1), ytalk(1) and many
+other multiple talk programs you might have read about. When you are
+talking in IRC, everything you type will instantly be transmitted around
+the world to other users that might be watching their terminals at the
+time - they can then type something and RESPOND to your messages - and
+vise versa. I should warn you that the program can be very addictive once
+you begin to make friends and contacts on IRC ;-) especially when you
+learn how to cuss in 14 languages.
+
+Topics of discussion on IRC are varied, just like the topics of Usenet
+newsgroups are varied. Technical and political discussions are
+popular, especially when world events are in progress. IRC is also a
+way to expand your horizons, as people from many countries and
+cultures are on, 24 hours a day. Most conversations are in English,
+but there are always channels in German, Japanese, and Finnish, and
+occasionally other languages.
+
+ How To Get IRC (technical)
+
+IRC is a fully-distributed client-server system, much like
+NNTP-Usenet, with several clients availble in C and elisp. You may ftp
+documentation and clients from any of the following sites:
+
+many kinds of clients (C, elisp, X11, VMS, REXX for VM, MSDOS, Macintosh):
+cs.bu.edu:/irc/clients
+ftp.acsu.buffalo.edu:/pub/irc
+ftp.funet.fi:/pub/unix/irc
+coombs.anu.edu.au:/pub/irc
+
+If you have any questions about IRC installation, write to hrose@kei.com.
+
+[ $Id$ ]
\ No newline at end of file
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, doc/etiquette
+ * Copyright (C) 1990, Lea Viljanen and Ari Husa
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ */
+
+HOW TO BEHAVE ON IRC
+
+Authors: Lea Viljanen (LadyBug) viljanen@kreeta.helsinki.fi
+ Ari Husa (luru) so-luru@tolsun.oulu.fi
+
+
+1) Language
+
+ The most widely understood and spoken language on IRC is English.
+However! As IRC is used in many different countries, English is by
+no means the only language. If you want to speak some other language
+than English (for example with your friends), go to a separate channel
+and set the topic (with /topic) to indicate that. For example
+ /topic Finnish only!
+would mean that this channel would be reserved for Finnish discussion.
+On the other hand, you should check the topic (with /list command)
+before you move to a channel to see if there are any restrictions about
+language.
+ On a channel not restricted by /topic, please speak a language
+everybody can understand. If you want to do otherwise, change channels
+and set the topic accordingly.
+
+
+2) Hello/Goodbye
+
+ It's not necessary to greet everybody on a channel personally.
+Usually one "Hello" or equivalent is enough. And don't expect everybody
+to greet you back. On a channel with 20 people that would mean one
+screenful of hellos. It's sensible not to greet, in order not to be rude
+to the rest of the channel. If you must say hello, do it with a private /msg.
+The same applies to goodbyes.
+
+
+3) Discussion
+
+ When you come to a new channel it's advised you to listen
+for a while to get an impression of what's discussed. Please feel free
+to join in, but do not try to force your topic into the discussion
+if that doesn't come naturally.
+
+
+4) {}|[]\
+
+ IRC has quite a lot of people from Scandinavian countries,
+the above characters are letters in their alphabet. This
+has been explained on IRC about a thousand and one times, so
+read the following, do not ask it on IRC:
+
+ { is an A with 2 dots over it
+ } is an A with a small circle above it
+ | is either an O with 2 dots over it or an O with a dash (/) through it
+ [, ], and \ are the preceding three letters in upper case.
+
+ There are a lot of people from Japan as well, who use Kanji characters
+which may look quite exotic as well. As I don't know Kanji I don't
+even try to explain any of the characters.
+
+5) ATTENTION!
+
+ Remember, people on IRC form their opinions about you only by
+your actions, writings and comments on IRC. So think before you type.
+Do not "dump" to a channel or user (send large amounts of unwanted
+information). This is likely to get you /kicked off the channel or
+/killed off from irc. Dumping causes network 'burbs', connections going
+down because servers cannot handle the large amount of traffic any more.
--- /dev/null
+[ $Id$ ]
+
+The available patches for 2.8*mu servers are:
+
+Tp8 = TimeStampPre8 - A protocol which disallows netsplit ops and channel
+ desynchs.
+
+Bquiet - does not allow a person who is banned to speak over the channel
+
+Silence - Cuts off flooding at local server
+
+Anc = Anti-Nick collide - *Intentional* nick collides are impossible with
+ this wonderful patch.
+
+W = Wallops - lets you send messages to other IRC ops
+
+ban = BanInformation - Lets you see who did a ban and when, as well
+
+sw = /stats w - lets you gather statistics on average client connects
+
+To = TopicInformation - Lets you see who set the topic for a channel and when
+
+S = Signon Time - Tells you when a local user signed onto IRC
+
+Cl = Client connect - Notifies opers on your server of client connects/
+ disconnects (with disconnect reason)
+
+TT = Trace Times - displays the time (in secs) since your server last heard
+ anything from a client/server, when you do /trace.
+
+KL = K-line comments - Allows you to modify the lame "no ghosts allowed" default
+ comment to whatever you wish, or alternately, display a
+ file to a rejected client.
+
+OF = Oper fail patch - displays a warning to current ops when someone fails
+ in entering the right oper password.
+
+MC = Mixed case patch - useful for those pesky clone bots and hacked logins;
+ disallows userids which have mixed case or control chars
+
+N = Note - allows you keep a "note" for other users, amongst other things
+
+-----------------------------------------------------------------------------
+Explanations for these patches follow.....
+
+Help on patches written by Mandar Mirashi (mmmirash@mailhost.ecn.uoknor.edu)
+ Mmmm on IRC.
+
+
+=============================================================================
+ TIMESTAMP
+=============================================================================
+Author: Carlo, carlo@sg.tn.tudelft.nl, Run on IRC.
+Info on TS protocol:
+
+ TSpre7
+
+------
+Effects of the TS protocol:
+
+> No mode wars possible.
+ When you take someones op there are three possibilities:
+ - You were too late (You was already de-opped on your server).
+ - You take it (On the *whole* net).
+ - You start taking it (on your server, but it is 'bounced' (ie your mode
+ change is cancelled); This occurs when you try to do mode change
+ direct after a net re-connection in a situation were you hacked op by
+ net-break riding.
+> No desynchronisation possible.
+> No unnecessary MODE msg send. You can't send 'double' mode's that don't
+ make sense. Servers don't send unnecessary MODE's either.
+> Hacking op is from now on *only* possible by admins that hacked their
+ servercode, and therefor easier to prosecute. Also you can 'hack' op still
+ exactly like now (by riding net break) on an *opless* channel.
+> The protocol is fully compatible with older servers: It is invisible
+ and it works with old servers like this: Every 'block' of direct connected
+ 2.8.x.TS servers will stay synchronized, Hacking op is impossible by means
+ of riding a net break between two TS-servers on channels that were created
+ within that block. In all other cases the same happens as without TS.
+
+Here follow technical details implemented in TSpre7:
+
+------
+
+Reference: 2.8.14/15.TSpre7
+Full list of TS-MODE-Change protocol:
+
+-Mode changes (originating by clients) are refused only:
+ 1) from a client that is directly connected and has no chan ops on
+ the channel on its server.
+ 2) when not being a change of the internal state of a server (Well, refused
+ is to strong, propagation of the mode is just unnecessary and thus not
+ done).
+ 3) from someone flagged as de-opped-by-server. (flag is reset when this
+ person is opped again by anyone) (The server detecting this mode change
+ cancels the mode change, by bouncing it upstream, thus keeping the net
+ synchronized).
+
+-An extra parameter is added behind MODE changes *done* by servers, sended
+ *to* other servers. It is a Universal Time in ascii seconds. This extra
+ parameter is NOT sended when it is 0 (can happen with old servers on the
+ net), 0 means <NONE> rather then Jan 1st 1970 :).
+ This parameter is the creationtime of the channel being: the universal time at
+ which the channel was created by a *local* client; or the non-zero received
+ creation time from an other server (as parameter with a mode change) that
+ was earlier then its own; or equal 0 when the channel was created by
+ a non-local client and no MODE with TS was received (yet).
+
+-Of the channel_flags is 1 bit more used: CHFL_DEOPPED, set when de-opped
+ by a server (compare CHFL_CHANOP, set when channel operator). It's reset
+ when opped. (And starts reset on joining (creation?) of a channel, this
+ will be changed to 'set' on join, when all servers have TS; making detection
+ of op hacking by admins a bit easier).
+
+-Timestamps (sended by TS-servers) are handled as follows:
+ Received TS Own TS Bounced/Propagated
+ equal equal propagated
+ later >0,earlier if ops: bounced with own TS
+ if no ops: propagated with own TS
+ (own TS is sended upstream too, to make sure
+ TS stays synchronized).
+ earlier later TS copied, propagated
+ none any propagated, own TS sended.
+ >0 none if ops: propagated, no TS sended, own TS stays 0.
+ if no ops: TS copied, propagated.
+
+-A mode change +/-o nick (+/- v) from a person that is deopped by a server
+ results in a -/+o nick back up stream (and is not propagated) if it was
+ an attempt to change the internal state of the receiving server.
+
+-kick is handled as mode -o, internal state 'not on channel' being 'already
+ de-opped'. Bounce includes JOIN and restoring o and v flags.
+ (Effect: You don't even *see* the kick on one side, on the other side
+ the person joins again and gets his flags back from the bouncing server).
+
+-A received TimeStamp that claims a creation time *earlier* then that
+ this server dissapeared from the net results in a HACK: notice (with
+ time difference in seconds). Bye OPER.. (This meaning, to hack op
+ on an existing channel that was created 15 minutes before you disconnected
+ your server, you will have generated a HACK notice: Clock set back at least
+ 900 seconds by <nick>.) (Not yet implemented, prob. in pre8).
+
+
+ TSpre8
+
+
+From: Carlo Kid - Runaway <carlo@sg.tn.tudelft.nl>
+Subject: *** IMPORTANT; RFC
+To: wastelanders@rush.cc.edu (New Wastelanders MailingList)
+Date: Thu, 14 Apr 94 18:03:38 METDST
+Mailer: Elm [revision: 66.33]
+Status: RO
+
+Hi, please read this carefully and respond if you think it will result
+in INCORRECT behaviour under any circumstances:
+
+Here follow technical details implemented in TSpre8:
+
+------
+
+Reference: 2.8.17.TSpre8
+Full list of TS-MODE-Change protocol:
+
+-Mode changes (originating by clients) are refused only:
+ 1) from a client that is directly connected and has no chan ops on
+ the channel on its server.
+ 2) when not being a change of the internal state of a server (Well, refused
+ is to strong, propagation of the mode is just unnecessary and thus not
+ done).
+ 3) from someone flagged as de-opped-by-server. (flag is reset when this
+ person is opped again by anyone) (The server detecting this mode change
+ cancels the mode change, by bouncing it upstream, thus keeping the net
+ synchronized).
+ 4) When a '0' as timestamp is received, originating from a server (see below).
+ Then the whole mode is ignored, a HACK notice is sent to all ops and the
+ string is propagated as received.
+
+-An extra parameter is added behind MODE changes *done* by servers, sent
+ *to* other servers *containing* a +o, -o, +v or -v.
+ It is a Universal Time in ascii seconds.
+ Whenever a HACK is detected, a HACK: notice is sent to all local opers,
+ and the full MODE is propagated with a '0' as timestamp, generating
+ a HACK notice on all other servers.
+ Otherwise this parameter is the creationtime of the channel being: the
+ universal time at which the channel was created by a *local* client;
+ or the non-zero received creation time from an other server (as parameter
+ with a mode change) that was earlier then its own; or equal 0 when the
+ channel was created by a non-local client and no MODE with TS was received
+ (yet).
+
+-Of the channel_flags is 1 bit more used: CHFL_DEOPPED, set when de-opped
+ by a server (compare CHFL_CHANOP, set when channel operator). It's reset
+ when opped. It starts *set* on joining (creation?) of a channel, making
+ detection of op hacking by admins a bit easier.
+
+-Timestamps (sent by TS-servers) are handled as follows:
+ Received TS Own TS Bounced/Propagated
+ equal equal propagated
+ later >0,earlier if ops: bounced with own TS
+ if no ops: TS copied, propagated
+ earlier later TS copied, propagated
+ 0 or none any HACK generated, 0 propagated, own TS is kept
+ >0 none TS copied, propagated.
+
+-A mode change +/-o nick (+/- v) from a person that is deopped by a server
+ results in a -/+o nick back up stream (and is not propagated) if it was
+ an attempt to change the internal state of the receiving server.
+
+-kick is handled as mode -o, internal state 'not on channel' being 'already
+ de-opped'. Bounce includes JOIN and restoring o and v flags.
+ (Effect: You don't even *see* the kick on one side, on the other side
+ the person joins again and gets his flags back from the bouncing server).
+
+-A received TimeStamp that claims a creation time *earlier* then that
+ this server dissapeared from the net results in a HACK: notice (with
+ time difference in seconds). Bye OPER.. (This meaning, to hack op
+ on an existing channel that was created 15 minutes before you disconnected
+ your server, you will have generated a HACK notice: Clock set back at least
+ 900 seconds by <nick>.)
+
+
+
+
+From: Carlo Kid - Runaway <carlo@sg.tn.tudelft.nl>
+Subject: TSpre8 can work! :)
+To: wastelanders@rush.cc.edu (New Wastelanders MailingList)
+Date: Wed, 20 Apr 94 11:44:39 METDST
+Mailer: Elm [revision: 66.33]
+Status: RO
+
+Well... it took me a few days (a night and some dreams actually), but
+I think I found a solution for the problem I mentioned during the meeting :)
+
+Let me first repeat the problem:
+
+- I stated that TSpre8 would prevent op hacking by admins, but... later
+ I realized that that was impossible the way wanted it :(
+ My idea was at first: Simply generate a HACK notice when a server
+ comes on the net with a creation time earlier then when it did split off
+ (and earlier then my own creation time). This sounds nice, but in
+ even this simple case it doesn't work:
+
+Server A and B, users a and b:
+
+ A -- B
+ |
+ @a TS=100
+
+Split at t=200
+
+ A B
+ |
+ @a
+
+b joins at t=300
+
+ A(TS=100) B(TS=300)
+ | |
+ @a @b
+
+Net joins:
+
+ A -- B
+ | |
+ a b
+
+Both are de-opped: b because he sends a TS of 300 with is greater (later)
+then 100 (correctly: he used the netbreak). And a is deopped with a
+HACK notice by B, because he introduces 1) a TS earlier then the existing
+TS (100<300) and 2) the 100 is earlier then the time the split occured.
+
+The reason why this goes wrong is simply because B *forgets* the channel
+AND the TS of 100, after the split... If B would *keep* in memory that
+the channel existed on A and with what TS, it would be possible, but only
+at cost of a lot of extra memory usage...
+
+Now my new idea :) It allows hacking, but only in not so very interesting
+cases... And at least it makes it extremely difficult for a newbee, so we
+might at least catch 99% before they understand how it works :)
+
+(This explanation should not be on a public ftp site anymore after a while :)
+
+New rules:
+
+- Servers that are OFF the net for more then one day are forgotten.
+- New servers (or forgotten servers), are always bounced except on channels
+ that have no ops (when they create a channel of their own thus :) unless
+ the receiving server is younger then one day and the introduced TS is
+ earlier then the start up time (minus 10 minutes :/) of the receiving server.
+ 'Birthdays' of those servers are also kept.
+- A server that splitted off while a channel already existed, and thus
+ has a creation time earlier then the "received squit time" of that
+ server, is not allowed to introduce an earlier timestamp then the
+ creationtime of the channel (HACK), and also not an equal TS when
+ younger then one day.
+- A server introducing a server with an earlier "time of received squit"
+ inherrits that time as its own "time of received squit".
+
+This allows to hack op on a channel that didn't exist when you splitted
+(not interesting). You also can't keep a server off the net till you need
+it (a telnet connection), because those can't do anything for one day long,
+unless they send the TS *equal* to the existing TS (The only exception :(),
+having to connect between two and one days before the hack, break between
+zero and one day before the hack but before the channel existed, connect
+and hack with equal TS.
+
+What do you think? Just for fun? :)
+
+Apart from that it would be suspicious when someone connects/breaks every
+24 hours a "test" server, channels that exist longer then one day are
+unhackable.
+
+The "disadvantages" are: servers that break off the net for *longer* then
+one day, but keep a channel up with an op, on *both sides of the net, will
+be completely de-opped after reconnection.
+
+*** IMPORTANT:
+
+I am absolutely not sure ;) if there aren't any other disadvantages or
+unwanted effects :) Please, think this over and mail me if you find some
+objection...
+
+Run
+
+
+
+
+From: Carlo Kid - Runaway <carlo@sg.tn.tudelft.nl>
+Subject: 2.8.19.U3 RELEASED
+To: wastelanders@rush.cc.edu (New Wastelanders MailingList)
+Date: Sun, 22 May 94 14:15:41 METDST
+Cc: carlo@sg.tn.tudelft.nl
+Mailer: Elm [revision: 66.33]
+Status: RO
+
+Hi all :)
+
+Proud to present: 2.8.19.U3 :)
+
+I have spend *enormous* amounts of time in TESTING this version,
+and I really hope it is completely bug free, but the changes are
+very big, so maybe persons who only want to upgrade/compile ONCE
+should wait a little longer then the compile cracks we have here ;)
+
+For real testing we need the HUBs though! So please, don't hesitate,
+Delft (a HUB) is running it already for a long time, also linked to
+other 2.8.19.U3 test servers.
+
+Before I'll tell about whats new in U3, I want to especially thank
+President for the tremendous help in testing TSpre8 -- I would never
+have been able bring up the stength to go through the difficult
+periods without him being there to listen to my technical complaints ;)
+
+=======================================================================
+
+NEW in .U3
+----------
+
+First all, TSpre8.
+
+It did not become what I hoped/expected to be possible :(
+Hacking will still be possible, but at least it will be a LOT
+more difficult when you don't know what you are doing, and I think
+we WILL catch (new) admins that think they can abuse their powers
+to be GOD on "their" channel.
+
+Especially, nobody will be able to hack *anything* with a normal nick.
+And because server modes are more obvious a hack, this alone is a
+step forward against admin hacking prevention imho.
+
+The .patch file is
+-rw------- 1 carlo users 65142 May 22 01:29 irc2.8.19-TSpre8.patch
+big.
+
+I'll now brows through it and mentions changes in the order they appear
+in the .patch file, arbitrary order thus ;)
+
+Zombies
+-------
+
+As mentioned before on 'wastelanders', I changed the internal way a KICK
+is handled, to be able to stop illegal -hacked- kicks from *outside* the
+channel. This has no effect on server-server protocol nor on server-client
+protocol. But because this way it is possible to keep (a little) memory
+for channels you're not on (being kicked from) I thought it would be no
+more then logical to stop people from joining the usual 10 ten channels
+at the same time, *including* the ones you are kicked from (because they
+occupy memory). This memory is released when you 1) Try to rejoin (so with
+all people having a auto-rejoin-on kick NOTHING changed at all), or 2)
+when you do a part - this is new and only intended to use when you do
+NOT have auto-rejoin, when you do not even WANT to rejoin, or try, assuming
+you might not be banned, when you have been kicked like this of a lot of
+channels and all together are "on" 10 channels so you NEED to leave one
+before you can join another... For this rare case, you must know on
+*which* channels you "are", therefor this is visible when you do a
+/names, or /who or /whois to yourself. It is never visible for others.
+Example:
+
+12:07 * Run (Daryl@sg.tn.tudelft.nl) has joined channel #wasteland
+*** Mode change "+o Run" on channel #wasteland by Wasted
+*** #wasteland : created Fri May 13 17:08:34 1994
+<Macro> Hi Run !
+*** You have been kicked off channel #wasteland by Run (Test)
+*** Run is Daryl@sg.tn.tudelft.nl (/msg Run profile)
+*** on channels: !#wasteland
+*** on irc via server Delft.NL.EU.undernet.org (Runaway Server
++[130.161.188.188])
+*** Run is away: Writting E-mail
+*** Run is an IRC Operator
+*** Run has been idle for 642 seconds.
+
+As you can see, the channel is marked with a '!' to show you are NOT
+not that channel... Both, a part #wasteland as well as a join (being
+not able to actually join because of ban, invite-only, key or limit), will
+remove you from this channel. The part will be sent back to (only) you, and
+everything has turned out to be 100% compatible with ircii protocol.
+Finally, of course the channel is removed when everyone is kicked and/or
+left the channel (a channel with only zombies is removed immedeately).
+
+#define RPL_CREATIONTIME 329
+--------------------------------
+
+A new numeric is sent when you ask for a MODE of a channel, by doing
+/MODE #channel
+without parameters.
+The reply is the same as before, but followed by a new numeric 329:
+
+/MODE #wasteland
+Delft.NL.EU.undernet.org 324 Run #wasteland +t
+Delft.NL.EU.undernet.org 329 Run #wasteland 768845314
+
+To supress this, you'll have to add something like:
+ON ^329 *
+to your .ircrc file. If you want to see this new numeric, you would
+add
+On ^329 "*" echo *** $1 : created $stime($2)
+
+It turns out that ircii clients ask for this mode when you join a
+channel, therefor you will see the creationtime when you join a channel,
+I'll leave it as an exercise to suppress this, but still being able to
+see it when you specifically ask for it :)
+
+New ircd.conf line
+------------------
+
+This is IMPORTANT :
+In order for Uworld to work you MUST add those lines to your ircd.conf file:
+
+U:Uworld.undernet.org::*
+U:Underworld.nl::*
+
+The later to allow the backup Underworld.nl to still function.
+If you forget this, or do it wrong, your server might refuse to accept
+certain mode changes from Uworld.undernet.org and start *bouncing*
+modes done by lusers that got op from it. The name of servers allowed
+to hack have to be agreed upon totally, by all admins. If one admin
+removes his U: line, the service will not work always correctly.
+
+When a server does a mode change that is detected to be a hack, you
+will see -as an oper, or +s luser- this notice:
+
+-> *uworld* opcom MODE #wasteland +o Mmmm
+!Uworld.undernet.org! Run is using Uworld to : MODE #wasteland +o Mmmm
+*** Notice -- HACK: Uworld.undernet.org MODE #wasteland +o Mmmm
+*** Mode change "+o Mmmm" on channel #wasteland by Uworld.undernet.org
+
+Normally, this HACK notice would NOT take effect! You still *see* the
+HACK notice for the U: line server(s) but then they DO take effect.
+
+Every other message (some including the word HACK) do also take effect,
+and are only a warning that someone is MAYBE hacking...
+I didn't see it occur yet.
+
+Removed bugs
+------------
+
+I did find some bugs in TSpre7, never thought that was possible :)
+I forgot what it exactly was, but under (very rare) circumstances it
+could be pretty serious :/
+
+One rather important thing is that now the TimeStamp is sent during a
+net re.join when there are no ops. Before it was possible to create
+a partly TimeStamp less net on an opless channel. TSpre8 garantees
+that the TS is synchronized on the whole net at any time.
+
+Other messages
+--------------
+
+Apart from the (true) HACK notice, you can get a:
+
+BOUNCE or HACK: notice, which does take effect and is most probably
+just a bounce of a mode done by an attacker: someone immedeately after
+a net re.join with his net.ride ops trying to de-op the others.
+I don't think this will happen often because it will be clear to all lusers
+that it is useless to try.
+
+NET.RIDE on opless #channel notice, you'll see this if someone does
+really abuses a net break to get ops on some opless channel. The mode
+does take effect however.
+
+FULL bounce of modes
+--------------------
+
+When before someone would ride a net break, and try something, ONLY
+his +/- o/v modes. Other modes like +mlk 1 \\|/\|/ would still take
+effect. With TSpre8 this changed... All modes (except bans) are bounced
+when someone rides a net break. Also the bouncing is more compact, while
+with TSpre7 every o and v mode took one line, now all modes are kept into
+one line.
+
+More allowed
+------------
+
+Before you was (how lame) not allowed to mix things like k, o and v...
+Now you are allowed, why not? Also you can use up to six parameters,
+really gives you a power kick ;)
+
+*** Mode change "+vvvvvv flux epa Skip Run Mmmm gyn" on channel #wasteland by
++Run
+
+User friendly mask fixing
+-------------------------
+
+The lame way Avalon fixes a mask (for a ban) is like this:
+
+/mode * +bb *.tudelft.nl Daryl@sg*.tn.tudelft.nl
+
+becomes:
+
+*** Mode change "+bb *.tudelft!*@* Daryl!*@sg*.tn.tudelft.nl" on channel
++#wasteland by Run
+
+The same on a TSpre8 server gives:
+
+*** Mode change "+b *!*@*.tudelft.nl" on channel #wasteland by Run
+
+While just Daryl@sg*.tn.tudelft.nl results in:
+
+*** Mode change "+b *!Daryl@sg*.tn.tudelft.nl" on channel #wasteland by Run
+
+which what one would expect!
+
+
+----------------------------------------------------------------
+
+Goodluck with compiling,
+
+Run
+
+PS If you encounter any problems, realize it is VERY unlikely that
+ it is .U3, but if you really think so, then first try to compile
+ plain 2.8.19. If you succeed, save the Makefile the include/config.h
+ and the include/setup.h. Unpack .U3, replace those files and recompile.
+ With this I assume you don't put your ircd.conf inside the source
+ directories of course, that would still have the paths set wrong then.
+
+ A smart move is to make patch file once for your Makefile/config.h :
+ First ONLY edit the Makefile and config.h (or copy the them from a
+ working source tree to a empty directory), and then make a diff with:
+ diff -rc irc2.8.19.clean irc2.8.19.my.makefile > Makefile.config.h.patch
+
+ That really speeds up upgrading with later versions.
+ (irc2.8.19.my.makefile only needs to contain
+ irc2.8.19.my.makefile/Makefile
+ irc2.8.19.my.makefile/include/config.h )
+ Of course, keep the include/setup.h seperately.
+
+### KILL for Mmm. Mmmm (stop it lamer (unnecessary flooding of alexbot))
+
+
+=============================================================================
+ BQUIET
+=============================================================================
+Author: Carlo, carlo@sg.tn.tudelft.nl, Run on IRC.
+Helpful ideas by: Aaron, agifford@sci.dixie.edu, Karll on IRC
+
+
+In order to fight flooding, and as discussed on wastelanders, banning
+someone on a channel will now also stop him from doing anything visible
+on the channel. This allows to let someone see what you think of him
+without even kicking him, he will leave by himself.
+He will still be able to appologise by private msgs of course and then
+he can be de-banned. A ban is this way a short cut for +m+vvvv everyone
+excpet the flooder. Note that even NICK floods are stopped: When you are
+on a channel where you are banned, you are not allowed to change your nick.
+
+=============================================================================
+ SILENCE
+=============================================================================
+Author: Carlo, carlo@sg.tn.tudelft.nl, Run on IRC.
+Helpful ideas by: Aaron, agifford@sci.dixie.edu, Karll on IRC
+
+My solution to flooders with clone bots etc :)
+Let the user that GETS flooded decide he doesn't want that and stop
+the flooder right at his own server (the server of the flooder).
+This is a new command, and the clients will need unfortunately a few
+lines in their .ircrc before it can work.
+Moreover, before this works, ALL servers must have .U3.
+
+The lines I use at the moment are:
+
+ALIAS SILENCE QUOTE SILENCE
+ALIAS SILE QUOTE SILENCE
+ON ^RAW_IRC "% SILENCE %" echo *** $*
+
+It turns out that some auto-rejoin on kick lines, like Davemans toolbox,
+disables the use of ON RAW_IRC, or at least makes it work incorrectly.
+You should disable this auto-rejoin line and you could add the one I use
+instead:
+
+ON ^RAW_IRC "% KICK % % *" {
+ IF ([$3]==[$N]) {
+ //QUOTE JOIN $2
+ ECHO $MID(11 5 $STIME($TIME())) * You have been kicked off channel $2 by $LEFT($INDEX(! $0) $0) \($MID(1 256 $4-)\) } {
+ ECHO $MID(11 5 $STIME($TIME())) * $3 has been kicked off channel $2 by $LEFT($INDEX(! $0) $0) \($MID(1 256 $4-)\) }
+}
+
+which are 6 lines, not 8.
+
+The way the silence patch works is as follows:
+
+When you add a silence mask (using the same user friendly mask fixing)
+like:
+
+/SILENCE Tsunami*@
+
+It will echo back to you how it is added:
+
+*** Run!Daryl@sg.tn.tudelft.nl SILENCE +*!Tsunami*@*
+
+Note that there is a '+' infront of the mask now.
+You can also type:
+
+/SILENCE +bot*
+
+*** Run!Daryl@sg.tn.tudelft.nl SILENCE +bot*!*@*
+
+If you want to silence one particular nick, you must add the '+', because
+when you do:
+
+/SILENCE nick
+
+and 'nick' exists, you will get the silence list of nick. Just using
+/SILENCE gives your own silence list:
+
+*** Run bot*!*@*
+*** Run *!Tsunami*@*
+*** End of Silence List
+
+However, check the silence list of someone ELSE make only really sense
+when you already did sent a message to this person. Because a silence
+mask only propagates to the server of the flooder when it is actually
+necessary. For instance: You can add up to 5 silence masks and delete them
+again and it will only be local to your own server. Only when someone
+would message you, matching a mask, the mask propagates to the server of
+the flooder. And stays there till you signoff, or till you delete it.
+If you delete a mask, it follows the same path as the +masks...
+
+As a result of this, +s lusers and opers will see the message:
+
+*** SILENCE : Unknown command (from Lausanne.CH.EU.UnderNet.org)
+
+When someone from *behind* a non .U3 server sends you a message
+(Lausanne is this case). So, you will STILL be flooded ;) UNTIL ALL
+servers are upgraded... (Or must do -s, but at least the net is flooded).
+
+
+To: wastelanders@rush.cc.edu
+From: agifford@sci.dixie.edu (Aaron Gifford)
+Subject: HELP with HELP for SILENCE
+Status: RO
+
+Hey, here's a VERY VERY VERY rough draft of a HELP entry for SILENCE,
+assuming it becomes a new command for ircII and not a replacement for
+IGNORE either via new code, or aliases like:
+ ALIAS SILENCE { QUOTE SILENCE $* }
+
+Anyway, PLEASE PLEASE PLEASE alter, modify, correct, add, hack-up, etc this
+rough draft and send me your alterations. I just typed this up VERY
+quickly because StGeorge is now running irc2.8.19.U3.1. The bug I mention
+in the file will hopefully disappear very soon, so that text will have to
+do likewise and vanish. :)
+
+Here it is, draft #1 HELP for SILENCE:
+
+Usage: SILENCE [<nick>]
+ SILENCE [+|-<pattern>]
+
+ SILENCE allows you to TOTALLY ignore all private messages (PRIVMSG's)
+ and notices (NOTICE's) from any user whose nick!user@host matches
+ the <pattern> parameter. The characters * and ? can be used
+ as wildcards in the pattern.
+
+ If you wanted to ignore all users from "somewhere.com" you would use:
+ SILENCE +*!*@somewhere.com
+
+ To ignore some with the nickname "Jerk" you would use:
+ SILENCE +Jerk
+ NOTE: The server will complete the pattern, storing it as "Jerk!*@*"
+
+ The only drawback of just SILENCE'ing someone by nickname only is
+ that the user could quickly change nicknames to avoid your pattern.
+
+ To remove a pattern, use a - before the pattern you want to remove.
+ When the command is used without any parameters, the server will list
+ all stored patterns you are currently ignoring with the SILENCE
+ command.
+
+ When used in the first form listed, you will see the SILENCE list for
+ the specified user. This list is not necessarily complete nor accurate
+ because of how servers share SILENCE information internally. You can
+ check to see if someone is ignoring you with SILENCE by first sending
+ that user a private message, then using the command to see the user's
+ SILENCE list.
+
+ Currently there is a bug in the servers (hopefully to be fixed soon)
+ that will add the nickname you specify to your SILENCE list when you
+ attempt to see that user's SILENCE list if that user is not currently
+ online.
+
+ Because SILENCE is a part of the IRC server protocol (on the Undernet)
+ it works much more efficiently than IGNORE, but is limited to a very
+ brief list of patterns. Also, you don't have as may options as you
+ do with IGNORE. If a user is flooding you, SILENCE is many times
+ more efficient than IGNORE because the offending user's PRIMSG's or
+ NOTICE's (including CTCP) are stopped at the server and never even
+ sent to your client.
+
+See Also:
+ IGNORE
+
+
+
+
+From: Carlo Kid - Runaway <carlo@sg.tn.tudelft.nl>
+Subject: Re: HELP with HELP for SILENCE
+To: agifford@sci.dixie.edu (Aaron Gifford) (Aaron Gifford)
+Date: Wed, 25 May 94 12:29:37 METDST
+Cc: wastelanders@rush.cc.edu (New Wastelanders MailingList)
+In-Reply-To: <9405250313.AA18446@sci.dixie.edu>; from "Aaron Gifford" at May 24, 94 9:20 pm
+Mailer: Elm [revision: 66.33]
+Status: RO
+
+> Here it is, draft #1 HELP for SILENCE:
+>
+> Usage: SILENCE [<nick>]
+> SILENCE [+|-<pattern>]
+>
+
+As it is now (I do not consider what you mentioned as a bug, I was aware
+of this effect and didn't choose to alter it), it really is:
+
+Usage: SILENCE [+|-]<pattern>
+Or : SILENCE <nick>
+
+When you leave the '+|-' away A '+' is assumed.
+
+The second possibility allows you to check your own silence lists, or
+allows to check if you are silenced by someone after you did message
+him but didn't get a respond (did ping him for instance).
+Indeed, this could be interpreted as a pattern, when <nick> doesn't
+exists.
+
+> If you wanted to ignore all users from "somewhere.com" you would use:
+> SILENCE +*!*@somewhere.com
+
+SILENCE somewhere.com
+
+would do.
+
+> When used in the first form listed, you will see the SILENCE list for
+> the specified user. This list is not necessarily complete nor accurate
+> because of how servers share SILENCE information internally. You can
+> check to see if someone is ignoring you with SILENCE by first sending
+> that user a private message, then using the command to see the user's
+> SILENCE list.
+
+Mention that a EVAL CTCP <nick> PING $TIME() is better...
+It would not be necessary to do the silence if the ping returns...
+To determine between huge lag and silence, you have to do the silence
+check after that.
+If you add something like this in the manual, people will automatically
+wait a while after the 'message' (ping), so that the servers have time
+to send the silence mask back. Otherwise they might think they can do
+a quick msg+silence at the same time. Nah... Not too important, unless
+with huge lag + silence combination.
+
+>
+> Currently there is a bug in the servers (hopefully to be fixed soon)
+> that will add the nickname you specify to your SILENCE list when you
+> attempt to see that user's SILENCE list if that user is not currently
+> online.
+
+I didn't consider this as too bad...
+But if people want it, I can change it so that you MUST add a '+' to
+add a mask that doesn't contain a '.', '!' or '@'.
+That would lead to 2.8.19.U3.2 and a very tiny patch for the people who
+already compiled .U3
+
+Run
+
+
+=============================================================================
+ U3 - required additions to .ircrc
+=============================================================================
+
+
+From: Carlo Kid - Runaway <carlo@sg.tn.tudelft.nl>
+Subject: Re: .ircrc codes for the new patches :)
+To: lamberdc@dad.cs.tuns.ca
+Date: Mon, 23 May 94 11:41:31 METDST
+Cc: wastelanders@rush.cc.edu (New Wastelanders MailingList)
+In-Reply-To: <9405222118.AA02415@dad.cs.tuns.ca>; from "Donald "WHIZZARD" Lambert" at May 22, 94 6:18 pm
+Mailer: Elm [revision: 66.33]
+Status: RO
+
+> hiya All
+> I was wondering if some one could send me a copy of the script/
+> for the new patches including the ban , topic and client connecting patches.
+>
+> And whatever is now out with the new .19 code :)
+>
+> thanks
+>
+> -- Donnie
+>
+> aka WHIZZARD
+
+The ftp.undernet.org:/pub/undernet/servers/Patches/README file:
+
+These are lines you need to add to your .ircrc file in order
+to use all posibilities .U3 profides you:
+
+To see when a channel was created:
+
+On ^329 * echo *** $1 : created $stime($2)
+
+When your server has the .ban patch use this to see who did a ban and when:
+
+On ^367 * if ([$4] != []) {echo *** $1 \($3 - $stime($4)) $2} {echo *** $1-}
+
+---------------------------
+When ALL servers upgraded to .U3, you can use this command:
+
+ALIAS SILENCE QUOTE SILENCE
+On ^RAW_IRC "% SILENCE %" echo *** $*
+
+Use this as:
+/SILENCE +mask
+
+To add 'mask' to your silence list (will completely stop all private
+messages from people matching 'mask' with their nick!user@host).
+You can VIEW your silence list by typing:
+/SILENCE
+
+If you message someone and he doesn't react (like with ping), then you
+can check if you match a silence mask he added by viewing his silence list
+with:
+/SILENCE nick
+
+A mask can be deleted by using the command:
+/SILENCE -mask
+
+When the some messages you from behind a NON-.U3 server you will not
+receive his message but the line:
+*** Unknown command (SILENCE) (From server.name.undernet.org)
+instead, so you will still be flooded.
+We hope all servers will be upgraded within a few months.
+
+------
+And my ircd.motd from Delft* :
+
+*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%
+ N E W : - This server now runs the official released
+ beta version 2.8.19.U3.1.ban
+ For you as users this means that:
+ -More security : .U3 contains the .TSpre8 patch with
+ disallows even ADMINs of servers to hack op on your
+ channel with a nick, most server modes are detected.
+ -The possibility to see the *creationtime* of a channel
+ (used with the TimeStamp (TS) protocol - unique on
+ undernet (disables the possibility of 'net.riding'))
+ -The possibility to stop EVERY kind of channel flooding
+ by *banning* someone : Now a ban stops not only
+ part/join floods, but also message floods and even
+ nick floods!
+ -The possibility to see who did when a certain ban.
+ -The possibility to stop anyone flooding you with
+ any kind of private messages at his *own* server!
+ (This will only work when ALL servers have upgraded)
+To be able to use all of this, ftp to sg.tn.tudelft.nl
+login: ftp ; password : anything ; file: /pub/README
+Put those lines in your .ircrc initialisation file !
+Have fun, Run.
+
+----
+
+Run
+
+=============================================================================
+ U3.1 -> U3.2
+=============================================================================
+
+
+From: Carlo Kid - Runaway <carlo@sg.tn.tudelft.nl>
+Subject: *BUG* .U3.1 found !!
+To: wastelanders@rush.cc.edu (New Wastelanders MailingList)
+Date: Wed, 25 May 94 16:45:39 METDST
+In-Reply-To: <457.9405250732@ccws-09.brunel.ac.uk>; from "James T Lowe" at May 25, 94 8:32 am
+Mailer: Elm [revision: 66.33]
+Status: RO
+
+> :->
+> :-> Hiya..
+> :->
+> :-> Here's what I observed tonight:
+> :->
+> :-> *** Mmmm (mandar@roosevelt.ecn.uoknor.edu) has joined channel #friendly
+> :-> *** Users on #friendly: @Mmmm
+> :-> *** Mode change "-o Mmmm" on channel #friendly by Uxbridge.*
+>
+> Not surprising :
+>
+> #friendly RedRum H* cs93jtl@ccws-09.brunel.ac.uk
+> #friendly Emmy H lamphear@cheshire.oxy.edu
+> #friendly ChemBot H@ cmrobert@hellcat.ecn.uoknor.edu
+>
+>
+>
+> >From Norman :
+>
+> *** ChemBot is cmrobert@hellcat.ecn.uoknor.edu (Charles Michael Roberts)
+> *** on channels: @#ChatZone
+> *** on irc via server Norman.OK.US.undernet.org
+> *** ChemBot has been idle 10 minutes
+>
+>
+> and from Uxbridge :
+>
+> ** ChemBot is cmrobert@hellcat.ecn.uoknor.edu (Charles Michael Roberts)
+> *** on channels: @#chatZone @#friendly
+> *** on irc via server Norman.OK.US.undernet.org
+>
+> :-> But,
+> :->
+> :-> *** Mmmm has left channel #friendly
+> :-> *** Mmmm (mandar@roosevelt.ecn.uoknor.edu) has joined channel #test
+> :-> *** Users on #test: @Mmmm
+> :->
+> :-> works fine..
+> :->
+> :-> Is this due to the U lines? Uworld was in no way involved though :-(
+> :->
+> :-> I personally feel that uxbridge's retaining timestamps of old channels -
+> :-> Run, can ya take a look asap. It can prove most distressing for our users :(
+> :->
+> :-> Thanks!!
+> :->
+> :-> Mmmm
+>
+>
+
+Weeehhhw, yeah a real bug :/
+
+RedRum and I looked for it for almost 4 hours before it was found...
+
+I will release .U3.2 and a patch for .U3.1-U3.2 asap...
+
+Description of bug:
+
+When someone gets kicked (and doesn't (try to) rejoin), it is flagged
+as a zombie. After a net-break, users are mutual re-joined on both
+sides of the net. It turned out that a zombie is also rejoined after
+a net rejoin.
+
+What happened with ChemBot:
+
+ChemBot was on #friendly via Norman (non TSpre8). It was banned and then
+kicked. It tried to rejoin, but Norman didn't allow that (ban).
+Delft never saw this try, and ChemBot stayed as a zombie on #friendly.
+Then Delft-UxBridge broke and reconnected... Delft did send a JOIN for
+ChemBot to UxBridge, ending up in a nick-desynced state.
+When Mmmm joined #friendly, he was the first on #friendly on all of the
+net except UxBridge... He was opped by Norman, but that is considered
+as a HACK by UxBridge and was bounced (ChemBot was still there *with*
+ops (those flags aren't reset when someone is marked zombie)).
+The second time Mmmm joined, he again got ops from Norman which now
+was accepted by UxBridge because this +o could be a BOUNCE of the de-op
+by UxBridge (Generating a BOUNCE or HACK: notice on UxBridge).
+
+Run
+
+
+
+From: Carlo Kid - Runaway <carlo@sg.tn.tudelft.nl>
+Subject: Release 2.8.19.U3.2
+To: wastelanders@rush.cc.edu (New Wastelanders MailingList)
+Date: Wed, 25 May 94 23:30:57 METDST
+Mailer: Elm [revision: 66.33]
+Status: RO
+
+Hi all,
+
+I released 2.8.19.U3.2
+
+Fixed:
+
+ - Rejoining of zombies after net break :/ (ChemBot case)
+ - Silence command now give: No such nick, when doing /silence nick
+ - I fixed the way a kick is handle, because in a last minute
+ thought I realized MURC would get trouble otherwise, see below.
+
+As usual you can get it from ftp.undernet.org:/pub/undernet/servers
+
+Patches/irc2.8.19.U3.1-2.patch : If you already had .U3.1
+
+irc2.8.19.U3.2.tar.gz : If start from scratch (DO SO!!!)
+
+For those who use the irc2.8.19.U3.1-2.patch ...
+
+------------------------------------------
+*** EDIT include/patchlevel.h !!!!!!!! ***
+------------------------------------------
+
+This patch will change your version to irc2.8.19.U3.2 so if you run
+ .ban EDIT it !!!
+
+=========================================================================
+
+The change in KICK handling is as follows:
+
+- A kick received from a local client, or for a local client or
+ from a direction in which the kicked client is located, is
+ simply handled as before: completely removed from channel, no zombie.
+ This means also that there is no client-server protocol change anymore:
+ /who, /whois and /names won't change.
+
+- A kick received for a local client originating from a remote client
+ lets the server sent a PART upstream. Since this results for non TSpre8
+ servers in a remote "You're not on that channel" message, this
+ message is suppressed (would never occur anyway now we are completely
+ synced).
+
+The reason why this was needed is mainly because MURC constantly kicks
+people who have auto-rejoin disabled from different channels. With U3.1
+they would get into problems after ten channels (needed to send extra
+PART's).
+
+Run
+
+--
+-------------------------------------------------------------------------------
+| carlo@sg.tn.tudelft.nl | Run @ IRC |
+| | Admin of Delft.NL.EU.undernet.org |
+| * Don't expect anything of live, | and Ircserver.et.tudelft.nl |
+| or you'll miss all the rest of it.| |
+-------------------------------------------------------------------------------
+
+
+
+=============================================================================
+ U3->U4, ANTI NICK COLLIDE
+=============================================================================
+Author: Carlo, carlo@sg.tn.tudelft.nl, Run on IRC.
+
+Hi all...
+
+After we dealt with channel msg-, join/part- and nick-floods (.bquiet),
+and with private message flooding (.silence), now in a sort of follow up
+to the anti net.break.ride (.TSpre7) and anti admin.hacks (TSpre8) we are
+about to deal with one of the last vulnerabilities of our net:
+nick-collision bots.
+Called .anc (anti nick collision).
+ - - -
+
+Socially spoken it does the following (I hope):
+
+- Only kills the RIGHT person, when a nick collision occurs.
+
+This would mean:
+
+A) If someone tries to harash by connecting to servers that just broke off
+and then take the nick of a person on the other side, both would be
+killed on reconnection. But with the .anc patch on both connecting servers,
+only the net.break rider will be killed.
+
+B) Secondly, when your server (or side) breaks off and you connect to some
+other server on the other side, it happens sometimes that due to lag you get
+killed by a nick collision after reconnection of the net.
+
+A and B differ strongly in the sense that in case A the *new* -the youngest-
+nick must be killed, while in case B the *old* (lagged) nick must be
+killed.
+Technically this means that we have to look at the user@host.name too.
+This gives rise to some incompatible changes, and therefor, this patch
+must be done in two steps: First we deal with the nick-collision bots and
+make the server compatible with both - the old and new protocol. And then
+once all server upgraded, we deal with the last step: the nick collision
+with yourself.
+
+In the future there will be a third possible condition in which we can have
+a nick collision: (long example follows, can be skipped)
+
+C) The net breaks, and reconnects else where, and somehow a race condition
+occurs between the 'SERVER' messages of the servers of one side.
+For example:
+
+Servers: Part A Part B1 PartB2
+Nicks a(A),b(B) a(A),b(B) a(A),b(B)
+Part A breaks off Part B:
+ <-- :b QUIT --> :a QUIT
+ <-- SQUIT serversB --> SQUIT serversA
+Result: a(A) b(B) b(B)
+A reconnects to Part B1, but immedeately breaks off again:
+ -->SERVERs A
+ -->NICK a
+ -->:a USER ...
+Break:
+ -->SERVERs A
+ -->NICK a
+ -->:a USER ...
+ --> :a QUIT
+ --> SQUIT serversA
+A connects to part B2, note that 'part B1 --> part B2' is lagged and the
+"SERVERs A ... etc" didn't arrive yet on partB2.
+Servers: Part B1 Part B2 Part A
+Nicks: b(B) b(B) a(A)
+ -->SERVERs A
+ -->NICK a
+ -->:a USER ...
+ --> :a QUIT
+ --> SQUIT serversA
+ --> SERVERs B
+ --> NICK b
+ --> :b USER ...
+ <-- SERVERs A
+ <-- NICK a
+ <-- :a USER ...
+Result *before* the lagged messages arive on Part B2:
+Nicks: b(B) b(B),a(A) b(B),a(A)
+ -->SERVERs A
+ -->NICK a
+ -->:a USER ...
+ -->:a QUIT
+ -->SQUIT serversA
+And when the lagged messages arrive on Part B2, the
+'SERVERs A' get all ignored: "server exists", even more, Part B2 disconnects
+Part B1... :/. Now we are going to deal with the "server exists" problem
+*once* (attaching a timestamp to SERVER I think), in which case 'SERVERs A'
+would only be ignored by Part B2. Then the 'NICK a' would cause a nick
+collision with 1) Same user@host.name, 2) same server A, and 3) same
+nick-TS ! This means: We need to ignore 'NICK nick' when is has the same
+TimeStamp and the same user@host. But when the user@host differ, two people
+signed on at exactly the same time with the same nick and we must kill
+*both* to avoid a desync.
+----
+
+How to handle a nick collision, general
+---------------------------------------
+
+Up till now when a nick collision occurs, both nicks (when a nick change
+from 'old' to 'new' is involved) are KILLed in ALL directions.. wiped off the
+net thus.
+But even with wiping off the net in mind, it doesn't make sense to kill in
+old direction, it is sufficient to deal with "our side" of the net, because
+every nick collision occurs on two servers, both can deal with their side.
+As an example:
+
+Servers: A B
+Nicks: a(A) a(B)
+Reconnection:
+ <-- NICK a
+ NICK a -->
+
+As you see, if A receives the 'NICK a' from B, it only has to deal with
+its own side, because it is certain that B will receive the 'NICK a' from
+A and handle it too as a nick collision (and therefore this 'NICK a' *is*
+already a 'KILL' message).
+
+Thus, when we receive a 'NICK' that gives rise to the need of purging
+a nick on *our* side, we deal with it by doing:
+sendto_serv_butone(cptr,":%s KILL ...
+which sends the KILL to all server connections except the link 'cptr' that
+generated the nick collision.
+Also then we have to destroy the memory usage of the killed client on our
+own server, and disconnect him if it is ours, so we call exit_client().
+
+Summary so far
+--------------
+
+Ok, we discussed when to kill who. Resulting rules are:
+
+We receive a "NICK new" or ":old NICK new" from a server direction, and
+we already have a registered 'new'. Then we have a nick collison and deal
+with it as follows:
+1) If the user@host differ,
+ and our 'new' is younger or equal, KILL our 'new'.
+ and our 'new' is older, ignore the 'NICK new', but kill 'old' on
+ our side if it was a nick change.
+2) If user@host is the same:
+ and our 'new' is older, KILL our 'new'.
+ and our 'new' is younger, ignore the 'NICK new', but kill
+ 'old' on our side if it was a nick change.
+ and our 'new' is equal, KILL our 'new',
+ and kill 'old' on our side too if it was a nick change.
+
+Remarks:
+ The last case, where have a ':old NICK new' collission with
+the same user@host and TimeStamp, can't be case C), but it
+is possible that *we* did send a 'NICK new', and the server at
+the other side kills 'old' off... So we have to do it too.
+ With this protocol we *ignore* 'NICK new' message, but of course
+in most cases they will be followed by at least a ':new USER ...' and
+probably
+more like ':new JOIN #...'. This would cause 'Fake direction' errors and
+the current protocol KILLs such a nick in *ALL* direction (???). Now, we
+DON'T want to KILL the nick in the right direction do we? And killing the
+fake direction nick makes no sense: it will be killed automatically due to
+the fact we did send a 'NICK new' in that direction. Thus: we can/have to
+remove the Fake Direction kills.
+ Of course, when we receive a 'NICK new hopcount :TimeStamp', we
+*can't* compare with the user@host, because it takes some time before we
+will receive the 'USER'... We also can't store the nick, because it must
+be unique. To solve this, we need to change the protocol so that 'NICK new'
+contains all information and the USER message will be redundant and removed
+in a later patch. This also reduces net.bursts.
+
+Attaching a TimeStamp (TS) to nicks
+-----------------------------------
+
+Whenever someone takes a new nick, which is available of course, either by
+changing nick or by signing on, the local server attaches a TimeStamp (TS)
+to the nick. Now there will be sent:
+
+NICK new hopcount TS user host.name server.name :Real name
+or
+:old NICK new :TS
+
+This is 100% compatible with the existing protocol.
+
+When a server receives such a nick from a neighbouring server it copies the
+TS, keeping track of the local change time. (When not all servers have
+upgraded, and no TS is received, the .anc server will fill in the time
+itself - being a slight advantage over keeping it 0. It also will assume
+that the host.names are equal or not equal resulting a as many kills as
+needed in the worst case).
+
+
+Examples
+--------
+
+Servers: A B
+Nicks: a(A),b(B) b(B),a(A)
+Both change simultaneously to nick 'c', but 'a' slightly faster (at time=1,
+and b at time=2):
+ c(A),b(B) c(B),a(A)
+ -> :a NICK c :1
+ :b NICK c :2 <-
+Then A receives a ':b NICK c :2' where 2 > 1, and KILLs b on its own side.
+B however receives ':a NICK c :1' where 1 < 2, and KILLs c on its own side.
+Result: c(A) c(A)
+
+Due to 'lag', more :c PRIVMSG .. from B to A can follow, resulting in a
+fake direction. 'A' will simply ignore them and not kill c (kills for
+fake direction are nonsense anyway).
+
+In the case that someone signs on, taking the same nick as a nick change
+we have almost the same:
+
+Servers: A B
+Nicks: a(A) a(A)
+'a' changes simultaneously to nick 'c', but slightly faster (at time=1),
+as a new 'c' signs on at B (time=2).
+ c(A) a(A),c(B)
+ -> :a NICK c :1
+ NICK c 1 :2 <-
+Then A receives a 'NICK c 1 :2' where 2 > 1, and ignores it simply.
+B however receives ':a NICK c :1' where 1 < 2, and KILLs c on its own side.
+Result: c(A) c(A)
+
+If the new 'c' was a little bit earlier, we get:
+
+Servers: A B
+Nicks: a(A) a(A)
+'a' changes simultaneously to nick 'c', and slightly slower (at time=2),
+as a new 'c' signs on at B (time=1).
+ c(A) a(A),c(B)
+ -> :a NICK c :2
+ NICK c 1 :1 <-
+Then A receives a 'NICK c 1 :1' where 1 < 2, and KILLs c on its own side.
+B however receives ':a NICK c :2' where 2 > 1, and KILLs a on its own side.
+
+Result: c(B) c(B)
+
+Last case, two people sign on (or during a net reconnection):
+
+Server: A B
+Sign on: c(A) c(B)
+ -> NICK c 1 :1
+ NICK c 1 :2 <-
+Then A receives 'NICK c 1 :2' where 2 > 1, and ignores it.
+and B receives a 'NICK c 1 :1' where 1 < 2, and KILLs c on its own side.
+Result: c(A) c(A)
+
+Note: the above didn't take equal TS's into account, and I assumed
+user@hosts to be different: the nick collision bot cases.
+
+A last possibility when someone starts hacking... a 'NICK new' twice
+from the same direction, should not be accepted: we kill the earlier one
+always.
+
+Compatibility problems
+----------------------
+
+In the future, we want to also take 'user@host' into account... Therefor,
+we need to start to ignore 'NICK new' and only act upon ':new USER ...'.
+We can only do that if also 'USER contains the hopcount and TimeStamp'...
+If we change the protocol immedeately to say:
+:nick USER user host.name server.name hopcount TimeStamp :Real name
+the 'hopcount' would be treated as realname, and we the rest would be
+lost :(
+
+We can also transfer the info to 'NICK', with:
+
+:server.name NICK nick hopcount user host.name TimeStamp :Real name
+
+and later forget the USER message. Although someone lamer uses
+the C source line " if (sptr == cptr) ..." in m_nick() to determine if
+it was a 'NICK new' or a ':old NICK new' :/ Geesh (unlogical). He should
+have used " if (IsServer(sptr)) ...". You would need three upgrade steps
+or we will have to do with:
+NICK nick hopcount user host.name server.name TimeStamp :Real name
+
+The nice thing about this is, that we can check how many parameters we
+receive and then immedeately use the user@host if it is there... That way
+the .acn will immedeately work once everyone upgraded once, and the second
+step would only get rid of the 'USER' line between servers.
+
+Run
+
+
+=============================================================================
+ WALLOPS
+=============================================================================
+Usage: /WALLOPS <message>
+
+Sends a message to IRC ops on-line. Remember that users who are /umode +w
+can see wallops as well.
+
+
+=============================================================================
+ STATS W
+=============================================================================
+Author: Michael Vanloon (michaelv@iastate.edu) - mlv on IRC
+Help on /stats w :
+
+I've been working on something I think would be quite a useful
+addition to the ircd. It keeps track of the average number of local
+clients, total clients, and total connections (including servers) over
+various periods of time, currently over the last minute, hour, day and
+week. It is invoked by "/stats w server.name". You may try it
+yourself by "/stats w *.iastate.edu". A sample from
+ircserver.iastate.edu looks like this:
+
+*** Minute Hour Day Week Userload for:
+*** 44.91 39.4 33 33 iastate.edu clients
+*** 114.40 103.2 69 65 total clients
+*** 120.40 109.0 73 70 total connections
+*** * End of /STATS report
+
+I'm debating changing it to show average connections over the last
+minute, hour, day, prev. day, and prev. day, as I think the data
+doesn't change enough after that to really be useful to justify
+keeping it over an entire week.
+
+On smaller, less used servers, it should add a negligible amount to
+the resident memory consumed by the ircd. On a large hub such as the
+*.bu.edu servers, penfold, or ircserver.iastate.edu, it might add as
+much as 300k to the amount of memory the ircd attempts to keep
+resident. The amount is determined solely by the number of
+connects/disconnects the server processes over the span of time
+measured.
+
+The code is bulletproof and has undergone *extensive* debugging and
+testing before I announced it here.
+
+The reason I'm posting this is because I would like to know how many
+people think this would be a useful addition to the server. In
+addition, I'd like feedback on whether you think this should be a
+standard part of the distributed server code. I think it should, but
+Avalon wants me to post here first and see how others feel about it.
+I'd appreciate your input.
+
+I will be making a patched 2.7.2 server available with this included,
+for those who would like to have this and stability too. I'll also be
+hooking it into 2.8.x soon, and giving it back to Av to include in the
+standard 2.8 distribution as it matures, if he sees fit to do so.
+
+Thanks for your time...
+
+ --Michael (mlv)
+
+IRC log started Wed Aug 18 21:52
+*** Value of LOG set to ON
+*mlv* it's the usage of your server
+*mlv* average number of users on your server over the last minute, hour, day, yesterday, and the day before
+*mlv* local clients, total clients, and total connections (clients + servers)
+-ircserver.iastate.edu- Minute Hour Day Yest. YYest. Userload for:
+-ircserver.iastate.edu- 23.00 23.0 16 17 11 iastate.edu clients
+-ircserver.iastate.edu- 52.00 52.8 37 35 23 total clients
+-ircserver.iastate.edu- 61.00 61.7 45 42 21 total connections
+-> *mlv* hmm...so iastate had 23 local clients in the last minute?
+*mlv* right... in the last minute the average number of local users on our server was 23
+*mlv* 23.45 actually
+-> *mlv* okie...gotcha... thanks :) one other thing
+*mlv* there were an average of 23.1 local users on here over the last hour
+*mlv* shoot
+-> *mlv* is it possible to specify multiple domains?
+-> *mlv* for e.g. uoknor.edu and okstate.edu cos those will be local to midway
+*mlv* it could be coded in, but 1) my code doesn't support it out of the box, and 2) that would add more state info which would increase the memory usage a bit
+-> *mlv* hmm...
+*mlv* it's purely informational... i wouldn't worry about it, really that much
+-> *mlv* okay...also, the Makefile on the ftp site seems hosed.....there's junk at the end...I tried both the .Z and the .gz
+*mlv* i'm thinking about making it log by connection class... but i'll have to use a more efficient statistical algorithm (less precise) if i do that
+*mlv* that way you could put all the local domains into certain classes
+*mlv* oh yeah... it's harmless, just weird
+-> *mlv* that'll work :)
+-> *mlv* well...thanks for your help....will have a look at the stats w patch when you're finished with it :)
+IRC Log ended *** Wed Aug 18 22:22
+
+
+=============================================================================
+ BAN/TOPIC/SIGNON INFO
+=============================================================================
+Author: Paul Foley (pfoley@kauri.vuw.ac.nz) SIO on IRC
+
+Help on Ban/Topic/Signon :
+
+Since these patches allow the server to maintain additional information, the
+server replies have been changes for the /mode #channel +b (#367), /whois
+(#317) and an additional reply #333 has been added for topic info. The time
+is returned as a long integer in UTC format in all cases. Since the existing
+clients will ignore this additional information, you will need to either
+patch the client, or in case you're using ircII, use the foll. /on statements
+to take benefit of these patches :
+
+on ^367 * if ([$4] != []) {echo *** $1 \($3 - $stime($4)) $2} {echo *** $1-}
+on ^333 * echo *** Topic for $1 set by $2 on $stime($3)
+on ^317 * if (index(012345679 $3) != -1) {echo *** $1 has been idle for $2 seconds. Signon at $stime($3)} {echo *** $1 has been idle for $2 seconds.}
+
+
+Once you have done this, you can see info as follows:
+/mode #wasteland +b
+*** #wasteland (Mmmm - Thu Aug 19 04:44:24 1993) test!*@*
+
+/topic #wasteland
+*** Topic for #wasteland: We all love Axl Rose!
+*** Topic for #wasteland set by rbarnes on Thu Aug 19 04:26:56 1993
+
+/whois Mmmm
+*** Mmmm is mandar@essex.ecn.uoknor.edu (Mmmm,I get high with a little help
++from my friends)
+*** on channels: @#wasteland
+*** on irc via server essex.ecn.uoknor.edu (MIDWEST HUB..HELPS YOU GET THERE
++SOONER)
+*** Mmmm is an IRC Operator
+*** Mmmm has been idle for 454 seconds. Signon at Wed Aug 18 23:47:19 1993
+
+
+=============================================================================
+ CLIENT NOTIFY
+=============================================================================
+Authors: Patrick Ashmore (pda@engr.engr.uark.edu) - Twilight1 on IRC
+ Mandar Mirashi (mmmirash@mailhost.ecn.uoknor.edu) - Mmmm on IRC
+ Tony Vencill (vencill@iastate.edu) - Tony/Tonto on IRC
+
+Help on Client Notify:
+
+This patch allows all opers on your server to see clients connecting to your
+server and disconnecting from it (with the reason why they disconnected).
+This can help you identify troublesome clients, or redirect remote clients
+to closer servers, or troubleshoot the reason why a client disconnected.
+
+A sample output:
+
+*** Notice -- Client connecting : Karll (agifford@sci.dixie.edu).
+
+*** Notice -- Client exiting : Karll (agifford@sci.dixie.edu) [Bad link?].
+
+PS: if you wish to selectively decide when you wish to see these connection
+notices, use the foll. script
+
+on ^server_notice "% % NOTICE -- CLIENT*" if (hideit != 1) {echo *** $2-}
+alias show @ hideit = 0;echo *** You can now see clients connecting/exiting
+alias hide @ hideit = 1;echo *** You will no longer see clients connecting/exiting
+
+If you then wish to not see client connects/exits when you are opered, simply
+type /hide. If you wish to see them again, type /show.
+
+=============================================================================
+ TRACE TIMES
+=============================================================================
+Author: Tony Vencill (vencill@iastate.edu) - Tony/Tonto on IRC
+
+Help on Trace Time:
+
+ This useful patch lets you identify the times since your server last
+heard from any connected servers or clients. This time is displayed in
+seconds, appended to each line of your /trace output. It can be very
+helpful in identifying which servers are going to drop off or which
+clients may ping timeout from your server.
+
+A sample output:
+
+/trace essex*
+*** Serv [30] ==> 10S 8C cancun.caltech.edu *!*@essex.ecn.uoknor.edu 73
+*** Serv [30] ==> 9S 6C imageek.york.cuny.edu *!*@essex.ecn.uoknor.edu 27
+*** Serv [0] ==> 1S 0C inga1.acc.stolaf.edu[130.71.192.16]
++*!*@essex.ecn.uoknor.edu 58
+*** Serv [0] ==> 1S 0C shadow.acc.iit.edu *!*@essex.ecn.uoknor.edu 97
+*** Serv [0] ==> 1S 2C curie.ualr.edu Mmmm!mmmirash@essex.ecn.uoknor.edu 98
+*** Serv [0] ==> 1S 1C piaget.phys.ksu.edu *!*@essex.ecn.uoknor.edu 117
+*** Oper [0] ==> Mmmm[essex.ecn.uoknor.edu] 0
+*** Serv [50] ==> 1S 0C pv1629.vincent.iastate.edu *!*@essex.ecn.uoknor.edu 7
+*** Class 0 Entries linked: 6
+*** Class 50 Entries linked: 1
+*** Class 30 Entries linked: 2
+
+
+=============================================================================
+ K- line comments
+=============================================================================
+Author: Mandar Mirashi (mmmirash@mailhost.ecn.uoknor.edu) - Mmmm on IRC
+
+This extremely useful patch allows you to specify either a comment or an
+interval in the 2nd field of the K line (instead of the previous format
+of just a restricted interval). The "comment" can even be configured to
+be a *file* name which can then be displayed to the client rejected via
+the K line. All existing K lines will work as they are. This patch is
+an *enhancement* to the K-lines.
+
+e.g. (of a comment field)
+
+K:*.sdsu.edu:Flooding.is.not.cool.lamer:masc0482
+
+As far as possible, do not use a white space in the comment field, because
+this breaks ircII's /stats k handling. You can use the period (.) or the
+underscore instead (_).
+
+e.g (of a file to be output to a rejected client
+ - #define COMMENT_IS_FILE in config.h)
+
+K:*.netcom.com:/ecn/staff0/irc/servers/vinson/sorry.txt:*
+
+
+=============================================================================
+ OPER FAIL
+=============================================================================
+Authors: Michael Vanloon (michaelv@iastate.edu) - mlv on IRC
+ Jon C Green (jcgreen@iastate.edu) - Jon2 on IRC
+ Bryan Collins (b@ctpm.org) - bwy on IRC
+
+This patch notifies you if someone tries to gain oper on your server and
+fails. The notice goes out only to the operators on the server.
+
+*** Notice -- Failed OPER attempt by M (mmmirash@lincoln.ecn.uoknor.edu)
+[crackit]
+
+
+=============================================================================
+ MIXED CASE
+=============================================================================
+Authors: Michael Vanloon (michaelv@iastate.edu) - mlv on IRC
+ Jon C Green (jcgreen@iastate.edu) - Jon2 on IRC
+
+"Here's a patch mlv and I wrote that prevents clients with mixed-case usernames
+from connecting. I don't know of many sites that allow mixed-case, so it
+is effective for stopping many clonebot attacks and also stops many
+would-be username hackers." - Jon2
+
+This has been slightly modified by Mmmm to give an option of ignoring the
+case of the first character if desired (useful for those PC users who
+intuitevely enter their first name with the first letter capitalised).
+
+e.g.
+*** Notice -- Invalid username: buankBOT[saucer.cc.umr.edu]
+
+
+=============================================================================
+ NOTE
+=============================================================================
+
+Usage:
+ \ 2NOTE\ 2 USER [&passwd] [+-flags] [+-maxtime] <nick!username@host> <msg>
+- or SEND|SPY|FIND|WAITFOR|NEWS <same as USER args.>
+* or SEND|SPY|FIND|WAITFOR|WALL|WALLOPS|DENY|NEWS|KEY <see USER args.>
+ \ 2NOTE\ 2 LS|COUNT|RM|LOG [&pwd][+-flags][#ID] <nick!user@host> [date]
+ \ 2NOTE\ 2 FLAG [&passwd] [+-flags] [#ID] <nick!username@host> <+-flags>
+* \ 2NOTE\ 2 SENT [NAME|COUNT|USERS] <f.nick!f.name@host> <date> [RM]
+- \ 2NOTE\ 2 STATS [MSM|MSW|MUM|MUW|MST|MSF|USED]
+- \ 2NOTE\ 2 SENT [NAME|COUNT]
+* \ 2NOTE\ 2 STATS [MSM|MSW|MUM|MUW|MST|MSF|USED|RESET] [value]
+* \ 2NOTE\ 2 SAVE
+
+ The Note system have two main functions:
+ 1. Let you send one line messages to irc users which
+ they will get when they next sign on to irc.
+ Example: NOTE SEND <nick> Hi, this is a note to you.
+ 2. Let you spy on people, to see when they sign on or off,
+ change nick name or join channels.
+ Example: NOTE SPY +100 <nick> (spy on nick for 100 days)
+
+ You may fill in none or any of the arguments listed above, including
+ * or ? at any place, as nick@*.edu, !username, ni?k!username etc...
+ Other usefull features may be NOTE WAIT <nick>, making nick and
+ you get a message when you both are on at the same time.
+
+ Note was developed 1990 by jarle@stud.cs.uit.no (Wizible on IRC).
+
+
+*Usage: NOTE [<server>] ANTIWALL
+* Switch off b flag for wall's which you have received on specified
+* server. The person who queued the wall would be notified about
+* the antiwall, and who requested this.
+
+
+Usage: NOTE COUNT [&<passwd>] [+|-flags] [#<ID>] <nick!username@host>
+ Displays the number of messages sent from your nick and username. See
+ HELP LS for more info. See HELP FLAG for more info about flag setting.
+
+
+*Usage: NOTE DENY [&<passwd>] [+|-<flags>] [+|-<maxtime>]
+* <nick!user@host> <msg>
+* DENY is an alias for USER +RZ (default max 1 day)
+* This command makes it impossible for any matching recipient to
+* queue any Note requests until timeout.
+
+
+Usage: NOTE FIND [&<passwd>] [+|-<flags>] [+|-<maxtime>]
+ <nick!username@host> <msg>
+ FIND is an alias for USER +FLR (default max 1 day)
+ This command makes the server search for any matching recipient, and
+ send a note message back if this is found. If <msg> field is used, this
+ should specify the realname of the person to be searched for. Examples:
+ FIND -4 foo*!username@host
+ FIND @host Internet*
+ FIND nicky Annie*
+ FIND +7 * Annie*
+
+
+Usage: NOTE FLAG [&<passwd>] [+|-<flags>] [#<ID>]
+ <nick!username@host> <+|-flags>
+ You can add or delete as many flags as you wish with +/-<flag>.
+ + switch the flag on, and - switch it off. Example: -S+RL
+ Following flags with its default set specified first are available:
+ -S > News flag for subscribing.
+ -M > Request is removed after you sign off.
+ -Q > Ignore request if recipient's first nick is equal to username.
+ -I > Ignore request if recipient is not on same server as request.
+ -W > Ignore request if recipient is not an operator.
+ -Y > Ignore request if sender is not on IRC.
+ -N > Let server send a note to you if message is delivered.
+ -D > Same as N, except you only get a message (no queued note to you).
+ -R > Repeat processing the request until timeout.
+ -F > Let server send note info for matching recipient(s). Any message
+ part specify what to match with the realname of the recipient.
+ -L > Same as F, except you only get a message (no queued note to you).
+ -C > Make sender's nicks be valid in all cases username@host is valid.
+ -V > Make sender's "nick*" be valid in all cases username@host is valid.
+ -X > Let server display if recipient signs on/off IRC or change
+ nickname. Any message specified is returned to sender.
+ -A > Show what server matching user is on using X flag.
+ -J > Show what channel matching user is on using X flag.
+ -U > Do not display nick-change using X flag.
+ -E > Ignore request if nick, name and host matches the message text
+ starting with any number of this format: 'nick!name@host nick!... '
+* -B > Send a message to every account who match the nick!user@host
+* This creates a received list with flag H set. (see LS +h)
+* -T > Send a message not all nicks on same accounts too using B flag.
+* -K > Give keys to unlock privileged flags by setting that flags on.
+* The recipient does also get privileges to queue unlimited
+* numer of requests, list privileged flags and see all stats.
+* -Z > Make it impossible for recipient to queue anything at all.
+ Other flags which are only displayed but can't be set by user:
+ -O > Request is queued by an operator.
+ -G > Notice message is generated by server.
+- -B > Broadcasting message.
+* -H > Flag list for who's received Broadcast message (B flag).
+- Notice: Message is not sent to recipient using F, L, R or X flag.
+- Using this flags, no message needs to be specified.
+* Notice: Message is not sent to recip. using F, L, R, X, K, Z or H
+* flag (except if B flag is set for R). For this flags, no msg. needed.
+
+ Examples:
+ FLAG * +cj : Switch on c and j flag for all requests.
+ FLAG +x * +c : Switch on c flag for all req. which have x flag.
+ FLAG nick -c+j : Switch off c flag and which on j flag for nick
+
+
+*Usage: NOTE KEY [&<passwd>] [+|-<flags>] [+|-<maxtime>] <nick!user@host>
+* KEY is an alias for USER +KR (default max 1 day)
+* This command is for allowing no-opers to use oper-options by specifying
+* the flag to unlock. Be careful with this option!
+* Example: KEY +365 +s * would make it possible for everybody to use s flag.
+
+
+Usage: NOTE LOG [&<passwd>] [+|-<flags>] [#<ID>] <nick!username@host>
+ Displays how long time since matching person was on IRC. This works
+ only after use of NOTE SPY. The log is protected to be seen for other
+ users than the person who queued the SPY request. To get short
+ output, do not specify any arguments. Example:
+ LOG : Print short log of all
+ LOG * : Print long log including real names of all
+ LOG nick : Print long log for user nick.
+
+
+Usage: NOTE LS [&<passwd>] [+|-<flags>] [#<ID>]
+ <nick!username@host> [<date>]
+ Displays requests you have queued. No arguments would show you
+ all requests without the message field.
+ Use flags for matching all messages which have the specified flags set
+ on or off. See HELP NOTE FLAG for more info about flag settings. Time
+ can be specified on the form day.month.year or only day, or day/month,
+ and separated with one of the three '.,/' characters. You can also
+ specify -n for n days ago. Examples: 1.jan-90, 1/1.90, 3, 3/5, 3.may.
+ If only '-' and no number is specified max time is set to all days.
+ The time specified is always the local time on your system. Example:
+ LS !user would show you all requests to username@*
+ LS +x would show all your SPY requests.
+ LS #300 would show you only request #300.
+
+
+Usage: NOTE NEWS [&<passwd>] [+|-<flags>] [+|-<maxtime>]
+ <group!username@host>
+ NEWS with no message is an alias for USER +RS (default max 60 days)
+ This command is for subscribing on a specified newsgroup from any
+ user(s) or host(s). Wildcards may be used anywhere. Example:
+ NEWS irc.note : Subscribe on irc.note
+* NEWS irc.note@*.no : Send to group irc.note, but only for
+* users at host *.no
+* NEWS irc.note : Send to all for group irc.note
+* NEWS Users@*.edu Hi : Send Hi to all users using note in your
+* server located at host *.edu.
+ (Advanced users may use User +rs <...> <filter> where filter is a
+ string which must matches with field in received news message)
+- Only opers can send news as default.
+* To send news add message and use same format as subscribing, except
+* that username field must matches with subscribed group as alt.irc!*.irc -
+* everybody subscribing on a*.irc or *.irc or alt.irc... would get the news.
+* A speciall case is the group Users which everybody using note in the server
+* are member of.
+
+
+Usage: NOTE RM [&<passwd>] [+|-<flags>] [#<ID>] <nick!username@host>
+ Deletes any messages sent from your nick and username which matches
+ with nick and username@host. Use flags for matching all messages which
+ have the specified flags set on or off. See HELP FLAG for more info
+ about flag settings, and HELP LS for info about time.
+
+
+*Usage: NOTE SAVE
+* SAVE saves all messages with the save flag set. Notice that the
+* messages are automatically saved (see HELP STATS). Each time server is
+* restarted, the save file is read and messages are restored. If no users
+* are connected to this server when saving, the ID number for each
+* message is renumbered.
+
+
+Usage: NOTE SEND [&<passwd>] [+|-<flags>] [+|-<maxtime>]
+ <nick!username@host> <msg>
+ SEND is an alias for USER +D (default max 60 days)
+ This command is for sending a message to recipient, and let the server
+ send a note + a notice to sender if this is on IRC - if message is sent.
+ SEND foobar Hello, this is a test.
+ SEND +7 !username@*.edu Hello again!
+
+
+-Usage: NOTE SENT [NAME|COUNT]
+*Usage: NOTE SENT [NAME|COUNT|USERS] <f.nick!f.name@host> <date> [RM]
+ Displays host and time for messages which are queued without specifying
+ any password. If no option is specified SENT displays host/time for
+ messages sent from your nick and username.
+ NAME displays host/time for messages sent from your username
+ COUNT displays number of messages sent from your username
+* USERS Displays the number of messages in [], and names for all users
+* who have queued any message which matches with spec. nick/name/host.
+* RM means that the server removes the messages from the specified user.
+
+
+*Usage: NOTE SERVICE <nick> <note command>
+* Useful in robots. Note will take the requests as if from <nick>
+
+
+Usage: NOTE SPY [&<passwd>] [+|-<flags>] [+|-<maxtime>]
+ <nick!username@host> [msg]
+ SPY is an alias for USER +RX (default 1 max day)
+ SPY makes the server tell you if any matching recipient sign(s)
+ on/off IRC or change nick name. No message needs to be specified.
+ However, if a message is specified this is returned to sender including
+ with the message about recipient. Message could for example be one or
+ more Ctrl-G characters to activate the bell on senders machine.
+ As an alternative for using C flag, <msg> field could start with
+ any number of nicks on this format: %nick1 %nick2... %nickn, with
+ no space between % and the nick name you use. Spy messages would be
+ valid for any of the nicks specified.
+ SPY with no argument would tell you what users you have spy on who are
+ currently on IRC. The system logs last time the last matching person was
+ on IRC for each SPY request is queued in the server. See NOTE LOG for this.
+ You may use flag +A to see what server matching user is on,
+ and/or +J flag to see what channel. (Read HELP NOTE USER for more). Example:
+ SPY foobar!username@host <ctrl-G>
+ SPY +10 foobar
+ SPY +aj &secret * <ctrl-G>
+ SPY +365 +e !user nick!*@* <ctrl-G>
+ SPY % +7 foo!user
+ SPY +5 nicky %mynick %meenick
+
+
+-Usage: NOTE STATS [MSM|MSW|MUM|MUW|MST|MSF|USED]
+*Usage: NOTE STATS [MSM|MSW|MUM|MUW|MST|MSF|USED|RESET] [value]
+ STATS with no option displays the values of the following variables:
+ MSM: Max number of server messages.
+ MSW: Max number of server messages with username-wildcards.
+ MUM: Max number of user messages.
+ MUW: Max number of user messages with username-wildcards.
+ MST: Max server time.
+ MSF: Note save frequency (checks for save only when an user register)
+ Notice that 'dynamic' mark after MSM means that if there are more
+ messages in the server than MSM, the current number of messages are
+ displayed instead of MSM.
+ Only one of this variables are displayed if specified.
+* You can change any of the stats by specifying new value after it.
+* RESET sets the stats to the same values which is set when starting the
+* server daemon if no note file exist. Notice that this stats are saved
+* in same file as the other messages.
+
+
+Usage: NOTE USER [&<passwd>] [+|-<flags>] [+|-<maxtime>]
+ <nick!username@host> <msg>
+ With USER you can queue a message in the server, and when the recipient
+ signs on/off IRC, change nick or join any channel, note checks for
+ valid messages. This works even if the sender is not on IRC. See HELP
+ FLAGS for more info.
+ Password can be up to ten characters long. You may specify password
+ using the &, % or $ character. & is equal to to $, except working much
+ better cause client use $ for other things...
+ The % character works like &, except it makes the queuing silent. It
+ makess also sense to use this without any following password.
+ If any request queued is equal to any previous except time and maxtime,
+ only maxtime is changed as specified. You then get "Joined" instead of
+ "Queued".
+ HELP FLAGS for info about flag settings. Username can be specified
+ without @host. Do not use wildcards in username if you know what it
+ is, even if it's possible. Max time before the server automatically
+ remove the message from the queue, is specified with hours with a
+ '-' character first, or days if a '+' character is specified, as
+ -5 hours, or +10 days. Default maxtime is 7 days.
+ Note: The received message is *directly* displayed on the screen,
+ without the need for a read or remove request.
+ NOTE USER &secret +WN +10 Wizible!jarlek@ifi.uio.no Howdy!
+ is an example of a message sent only to the specified recipient if
+ this person is an operator, and after receiving the message, the server
+ sends a note message back to sender to inform about the delivery.
+ NOTE USER +XR -5 Anybody <ctrl-G>
+ is an example which makes the server to tell when Anybody signs
+ on/off irc, change nick etc. This process repeats for 5 hours.
+ NOTE USER +FL @*.edu *account*
+ is an example which makes the server send a message back if any real-
+ name of any user matches *account*. Message is sent back as note from
+ server, or directly as a notice if sender is on IRC at this time.
+
+
+Usage: NOTE WAITFOR [&<pwd>] [+|-<flags>] [+|-<maxtime>]
+ <nick!username@host> [<msg>]
+ WAITFOR is an alias for USER +YD (default max 1 day)
+ Default message is [Waiting]
+ This command is for telling the recipient if this appears on IRC that
+ you are waiting for him/her and notice that this got that message. Example:
+ WAITFOR foobar
+ WAITFOR -2 foobar!username@*
+ WAITFOR foobar Waiting for you until pm3:00..
+
+
+*Usage: NOTE WALL [&<passwd>] [+|-<flags>] [+|-<maxtime>]
+* <nick!user@host> <msg>
+* WALL is an alias for USER +BR (default max 1 day)
+* This command is for sending a message once to every matching user
+* on IRC. Be careful using this command. WALL creates a list of
+* persons received the message (and should not have it once more time)
+* with H flag set. This list can be displayed using ls +h from the
+* nick and username@host which the WALL request is queued from.
+* Removing the headers (H) before WALL request is removed would cause
+* the message to be sent once more to what users specified in list.
+* WALL +7 @*.edu Do not do this! - Makes it clear for all users using
+* IRC on host @*.edu the next 7 days how stupid it is to send such WALL's ;)
+
+
+*Usage: NOTE WALLOPS [&<passwd>] [+|-<flags>] [+|-<maxtime>]
+* <nick!user@host> <msg>
+* WALLOPS is an alias for USER +BRW (default max 1 day)
+* This command is same as WALL, except only opers could receive it.
+=============================================================================
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, doc/INSTALL
+ * Copyright (C) 1990,1991,1992, Jeff Trim, Mike Bolotski,
+ * Jarkko Oikarinen and Darren Reed.
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ */
+
+ Installing IRC - The Internet Relay Chat Program
+
+
+Overview of this document:
+
+ 1) The config.h file
+ 2) Editing the Makefile
+ 3) Compiling IRC
+ 4) The ircd.conf file
+
+
+1) Edit the "config.h" file and make changes to the various #DEFINE's:
+
+ a) Copy the config.h.dist file to config.h before editing.
+
+ b) Define what type of UNIX your machine uses.
+
+ Pick the machine type which best describes your machine and change
+ the #undef to #define (if needed). Some flavours of Unix require no
+ #define and in such cases all others should be #undef'd.
+
+ c) DEBUGMODE
+
+ Define DEBUGMODE if you want to see the ircd debugging information
+ as the daemon is running. Normally this function will be undefined
+ as ircd produces a considerable amount of output. DEBUGMODE must be
+ defined for either of -t or -x command line options to work.
+
+ d) DPATH, SPATH, CPATH, MPATH, LPATH, PPATH
+
+ DPATH is provided so that the other pathnames (SPATH, CPATH, etc)
+ may be provided in just filename form. When the server starts, it
+ chdir's to DPATH before chroot or any other file operation, making
+ it the "current directory" for the server. This is where core files
+ will go if it core dumps.
+
+ Define SPATH to be the directory path to ircd. This is usually
+ /usr/local/bin/ircd, unless you don't have installation permission
+ there.
+
+ Define CPATH to be the directory path to the "irc.conf" file.
+ This path is usually /usr/local/lib/irc.conf. The format of this file
+ will be discussed later.
+
+ The LPATH #define should be set to "/dev/null" unless you plan to
+ debug the program. Note that the logfile grows very quickly.
+
+ Define MPATH to be the path to the 'motd' (message of the day) file
+ for the server. Keep in mind this is displayed whenever anyone
+ signs on to your server.
+
+ The PPATH is optional, but if defined, should point to a file which
+ either doesn't exist (but is creatable) or a previously used PPATH
+ file. It is used for storing the server's PID so a ps(1) isn't
+ necessary.
+
+ e) CHROOTDIR
+
+ To use the CHROOTDIR feature, make sure it is #define'd and that
+ the server is being run as root. The server will chroot to the
+ directory name provded by DPATH.
+
+ f) ENABLE_SUMMON, ENABLE_USERS
+
+ For security conscious server admins, they may wish to leave
+ ENABLE_USERS undefined, disabling the USERS command which can be used
+ to glean information the same as finger can. ENABLE_SUMMON toggles
+ whether the server will attempt to summon local users to irc by
+ writing a message similar to that from talk(1) to a user's tty.
+
+ g) SHOW_INVISIBLE_LUSERS, NO_DEFAULT_INVISIBLE
+
+ On large IRC networks, the number of invisible users is likely to
+ be large and reporting that number cause no pain. To aid and effect
+ this, SHOW_INVISIBLE_LUSERS is provided to cause the LUSERS command
+ to report the number of invisible users to all people and not just
+ operators. The NO_DEFAULT_INVISIBLE define is used to toggle whether
+ clients are automatically made invisible when they register.
+
+ h) OPER_KILL, OPER_REHASH, OPER_RESTART, LOCAL_KILL_ONLY
+
+ The three operator only commands, KILL, REHASH and RESTART, may all
+ be disabled to ensure that an operator who does not have the correct
+ privilidges does not have the power to cause untoward things to occur.
+ To further curb the actions of guest operators, LOCAL_KILL_ONLY can
+ be defined to only allow locally connected clients to be KILLed.
+
+ i) The rest of the user changable #define's should be pretty much self
+ explanatory in the config.h file. It is *NOT* recommended that any
+ of the file undef the line with "STOP STOP" in it be changed.
+
+3) Configure and compile the code.
+
+ Edit the root Makefile for the server, uncomment/comment the correct
+ CFLAGS/IRCDLIBS lines as appropriate for your system.
+ Change DESTDIR to be the same as the path for DPATH in config.h.
+ Type "make". This will compile the server, the client, and the services.
+ At the end of this step, the server directory will contain 'ircd',
+ and the client directory will contain 'irc'. To get the server installed,
+ type "make install" which will build a default m4 file for preprocessing,
+ copy example.conf and put the server all in DESTDIR. The irc client and
+ a copy of the server will also be placed in BINDIR and the modes set
+ accordingly.
+
+4) The ircd.conf file.
+
+ After installing the ircd and irc programs, edit the irc.conf file
+ as per the instructions in this section and install it in the
+ location you specified in the config.h file. There is a sample
+ conf file called example.conf in the /doc directory.
+
+ Appendix A describes the differences between IP addresses and host
+ names. If you are unfamiliar with this, you should probably scan
+ through it before proceeding.
+
+ The irc.conf file contains various records that specify configuration
+ options. The record types are as follows:
+
+ 1. Server connections (C,N)
+ 2. Machine information (M)
+ 3. Client connections (I)
+ 4. Default local server (U)
+ 5. Operator priviliges (O)
+ 6. Administrative info (A)
+ 7. Excluded accounts (K)
+ 8. Excluded machines (Q)
+ 9. Connection Classes (Y)
+ 10. Leaf connections (L)
+ 11. Service connections (S)
+ 12. Port connections (P)
+ 13. Hub connections (H)
+
+
+ 1. SERVER CONNECTIONS: How to connect to other servers
+ How other servers can connect to you
+
+ WARNING:
+ The hostnames used as examples are really only examples and
+ not meant to be used (simply because they don't work) in real life.
+
+ Now you must decide WHICH hosts you want to connect to and WHAT ORDER you
+ want to connect to them in. For my example let us assume I am on the
+ machine "rieska.oulu.fi" and I want to connect to irc daemons on 3 other
+ machines:
+
+ "garfield.mit.edu" - Tertiary Connection
+ "irc.nada.kth.se" - Secondary Connection
+ "nic.funet.fi" - Primary Connection
+
+ And I prefer to connect to them in that order, meaning I first want to
+ try connecting to "nic.funet.fi", then to "irc.nada.kth.edu", and
+ finally to "garfield.mit.edu". So if "nic.funet.fi" is down or
+ unreachable, the program will try to connect to "irc.nada.kth.se".
+ If irc.nada.kth.se is down it will try to connect to garfield and so forth.
+ PLEASE limit the number of hosts you will attempt to connect to down to 3.
+ This is because of two main reasons:
+ a) to save your server from causing extra load and delays
+ to users
+ b) to save internet from extra network traffic
+ (remember the old rwho program with traffic problems when
+ the number of machines increased).
+
+ The format for the CONNECT entry in the "irc.conf" is:
+
+ C:<TARGET Host Addr>:<Password>:<TARGET Host NAME>:<TARGET Host PORT>
+Field: 1 2 3 4 5
+
+ for example:
+
+ C:nic.funet.fi:passwd:nic.funet.fi:6667
+
+ - or -
+
+ C:128.214.6.100:passwd:nic.funet.fi:6667
+
+ - or -
+
+ C:root@nic.funet.fi:passwd:nic.funet.fi:6667
+
+
+ Explanation:
+
+ Each field is separated with a ":" charcter:
+
+ Field 1: Field 1 tells the IRC program which option is being configured.
+ "C" corresponds to a server Connect option.
+
+ Field 2: Specifies the host name or IP address of the machine to connect
+ to. If "user@" prefixes the actual hostname or IP address
+ the server will require that the remote username returned by
+ the ident server be the same as the one given before the "@".
+
+ Field 3: The password of the other host. A password must always be
+ present for the line to be recognized.
+
+ Field 4: The full hostname of the target machine. This is the name that
+ the TARGET server will identify itself with when you connect
+ to it. If you were connecting to nic.funet.fi you would receive
+ "nic.funet.fi" and that is what you should place in
+ this field.
+
+ Field 5: The INTERNET Port that you want to connect to on the TARGET
+ machine. Most of the time this will be set to "6667".
+ If this field is left blank, then no connections will
+ be attempted to the TARGET host, and your host will accept
+ connections FROM the TARGET host instead.
+
+ Some examples:
+
+ C:nic.funet.fi::nic.funet.fi:6667
+
+ This reads: Connect to host "nic.funet.fi", with no password
+ and expect this server to identify itself to you as
+ "nic.funet.fi". Your machine will connect to this host to
+ PORT 6667.
+
+ C:18.72.0.252:Jeff:garfield.mit.edu:6667
+
+ This reads: Connect to a host at address "18.72.0.252", using a
+ password of "Jeff". The TARGET server should identify
+ itself as "garfield.mit.edu". You will connect to Internet
+ Port 6667 on this host.
+
+ C:irc.nada.kth.se::irc.nada.kth.se
+
+ This reads: do not attempt to connect to "irc.nada.kth.se",
+ but if "irc.nada.kth.se" requests a connection,
+ allow it to connect.
+
+ Now back to our original problem, we wanted OUR server CONNECT to 3
+ hosts, "nic.funet.fi", "irc.nada.kth.se" and "garfield.mit.edu" in
+ that order. So as we enter these entries into the file they must be
+ done in REVERSE order of how we could want to connect to them.
+
+ Here's how it would look if we connected "nic.funet.fi" first:
+
+ C:garfield.mit.edu::garfield.mit.edu:6667
+ C:irc.nada.kth.se::irc.nada.kth.se:6667
+ C:nic.funet.fi::nic.funet.fi:6667
+
+ Ircd will attempt to connect to nic.funet.fi first, then to irc.nada
+ and finally to garfield.
+
+ Reciprocal entries:
+
+ Each "C" entry requires a corresponding 'N' entry that specifies
+ connection priviliges to other hosts. The 'N' entry contains
+ the password, if any, that you require other hosts to have before
+ they can connect to you. These entries are of the same format as
+ the "C" entries.
+
+ Let us assume that "garfield.mit.edu" connects to your server
+ and you want to place password authorization authorization on garfield.
+ The "N" entry would be:
+
+ N:garfield.mit.edu:golden:garfield.mit.edu
+
+ This line says: expect a connection from host "garfield.mit.edu",
+ and expect a login password of "golden"
+ and expect the host to identify itself as "garfield.mit.edu".
+
+ N:18.72.0.252::garfield.mit.edu
+
+ This line says: expect a Connection from host "18.72.0.252", and
+ don't expect login password. The connecting host should identify itself
+ as "garfield.mit.edu".
+
+
+ Wildcards domains:
+ To reduce the great amount of servers in IRCnet wildcard
+ DOMAINS were introduced in 2.6. To explain the usage of
+ wildcard domains we take an example of such:
+ *.de - a domain name matching all machines
+ in Germany.
+ Wildcard domains are useful in that ALL SERVERS in Germany
+ (or any other domain area) can be shown as one to the
+ rest of the world. Imagine 100 servers in Germany, it
+ would be incredible waste of netwotk bandwidth to broadcast
+ all of them to all servers around the world.
+
+ So wildcard domains are a great help, but how to use them ?
+ They can be defined in the N-line for a given connection,
+ in place of port number you write a magic number called
+ wildcard count.
+
+ Wildcard count tells you HOW MANY PARTS of your server's name
+ should be replaced by a wildcard. For example, your server's
+ name is "tolsun.oulu.fi" and you want to represent it as
+ "*.oulu.fi" to "nic.funet.fi". In this case the wildcard count
+ is 1, because only one word (tolsun) is replaced by a wildcard.
+ If the wildcard count would be 2, then the wildcard domain would
+ be "*.fi". Note that with wildcard name "*.fi" you could NOT
+ connect to "nic.funet.fi", because that would result in a server
+ name COLLISION (*.fi matches nic.funet.fi).
+
+ I advice you to not to use wildcard servers before you know
+ for sure how they are used, they are mostly beneficial for
+ backbones of countries and other large areas with common domain.
+
+
+ 2. MACHINE INFORMATION
+
+ IRC needs to know a few things about your UNIX site, and the "M" command
+ specifies this information for IRC. The fomat of this command is:
+
+ M:<YOUR Host NAME>:xxx:<Geographic Location>:<Internet Port>
+ Field: 1 2 3 4 5
+
+ Explanation:
+
+ Field 1: "M" specifies a Machine description line
+
+ Field 2: The name of YOUR host adding any Internet DOMAINNAME that
+ might also be present.
+
+ Field 3: -- NOT USED --: Set to Value NULL (No spaces at ALL!).
+
+ Field 4: Geographic Location is used to say WHERE YOUR SEVRER is,
+ and gives people in other parts of the world a good
+ idea of where you are! If your server is in the USA, it is
+ usually best to say: <CITY> <STATE>, USA. Like for Denver
+ I say: "Denver Colorado, USA". Finnish sites (like
+ tolsun.oulu.fi generally say something like "Oulu, Finland".
+
+ Field 5: The Internet port your server will use. Should be set to
+ the same value as in the config.h file.
+
+
+ Example:
+ M:tolsun.oulu.fi::Oulu, Finland:6667
+
+ This line reads: My Host's name is "tolsun.oulu.fi" and
+ my site is located in "Oulu, Finland". My ircd will use
+ Internet Port 6667.
+
+
+ M:orion.cair.du.edu::Denver Colorado, USA:6667
+
+ This line reads: My Hosts name is "orion.cair.du.edu"
+ and my site is located in "Denver Colorado, USA".
+ I have defined Internet Port number "6667" to be used
+ as my IRCD Socket Port.
+
+
+ 3. CLIENT CONNECTIONS - How to let clients connect to your IRCD.
+
+ A client is a program that connects to the ircd daemon (ircd). Currently
+ there are clients written in C and in GNU Emacs Lisp. The "irc"
+ program is the C client. Each person that talks via IRC is running
+ their own client.
+
+ The irc.conf files contains entries that specify which clients are allowed
+ to connect to your irc daemon. Obviously you want to allow your cwn
+ machine's clients to connect. You may want to allow clients from
+ other sites to connect. These remote clients will use your server
+ as a connection point. All messages sent by these clients will pass
+ through your machine.
+
+ The format of this entry in the conf file is:
+
+ I:<TARGET Host Addr>:<Password>:<TARGET Hosts NAME>:<Internet Port>
+ Field:1 2 3 4 5
+
+
+ For example, if you were installing IRC on tolsun.oulu.fi and you wanted
+ to allow examples sake let us assume you were making this file for
+ tolsun and you wanted to let your own clients to connect to your
+ server, you would add this entry to the file:
+
+ I:128.214.5.6::tolsun.oulu.fi
+ or
+ I:tolsun.oulu.fi::tolsun.oulu.fi
+
+ If you wanted to let remote clients connect, you could add the
+ following lines:
+
+ I:*.du.edu::*.du.edu
+
+ Allow any clients from machines whose names end in "du.edu" to connect
+ with no password.
+
+ I:128.214.6.100::nic.funet.fi
+
+ Allow clients from a machine with that IP number and the name
+ nic.funet.fi to connect.
+
+ I:*.tut.fi:secret:*.tut.fi
+
+ Allow clients from machines matching *.tut.fi to connect
+ with the password 'secret'.
+
+ I:*::*
+
+ Allow anyone from anywhere to connect your server.
+ This is the easiest way, but it also allows people to for example
+ dump files to your server, or connect 1000 (or how many open
+ sockets per process your OS allows) clients to your machine
+ and take your network ports. Of course the same things can be
+ done by simply telnetting to your machine's SMTP port (for example).
+
+ NEW!!!
+ As of the 2.7.2d version of the server, the server is able to accept
+ connections on multiple ports. I-lines are required for each P-line
+ to allow connections to be accepted. For unix sockets, this means
+ either adding I:/path/port::/path/port or some variation (wildcards
+ are recognised here). For internet ports, there must be an I-line
+ which allows the host access as normal, but the port field of the
+ I-line must match that of the port of the socket accepting the
+ connectiion. A port number of 0 is a wildcard (matches all ports).
+
+ 4. DEFAULT HOSTS (for local clients)
+
+ This defines the default connection for the irc client. If you are
+ running an ircd server on the same machine, you will want to define
+ this command to connect to your own host. If your site is not running
+ a server then this command should contain the TARGET host's connection
+ information and password (if any). The format for this command is:
+
+ U:<TARGET Host addr>:<Password>:<TARGET Host NAME>:<Internet Port>
+ Field: 1 2 3 4 5
+
+
+ For example:
+
+ U:tolsun.oulu.fi::tolsun.oulu.fi:6667
+ U:128.214.5.6::tolsun.oulu.fi:6667
+ U:tolsun.oulu.fi::tolsun.oulu.fi
+
+ If the port number is omitted, irc will default to using 6667.
+
+ 5. OPERATOR Privileges: How to become the IRC administrator on your site
+
+ To become an IRC Administrator, IRC must know who is authorized to become
+ an operator and what their "Nickname" and "Password" is. To add this
+ information, EDIT your "irc.conf" file and add the following command
+ line to it:
+
+ O:<TARGET Host NAME>:<password>:<nickname>:<port>:<class>
+ Field: 1 2 3 4 5 6
+
+ Explanation:
+
+ Field 1: Speficies Operator record. If you use capital letter ('O')
+ in it, it specifies a global operator. Small letter ('o')
+ specifies a local operator. Local operator has basically the
+ same rights except global operator with some restrictions.
+
+ Field 2: Tells IRC which host you have the privileges FROM. This
+ means that you should be logged into this host when you
+ ask for the priviliges. If you specify "tolsun.oulu.fi"
+ then IRC will expect your CLIENT to be connected at
+ "tolsun.oulu.fi" - when you ask for OPERATOR privileges
+ from "tolsun.oulu.fi". You cannot be logged in at any
+ other host and be able to use your OPERATOR privileges
+ at tolsun, only when you are connected at TOLSUN will this
+ work - this is a safeguard against unauthorized sites.
+
+
+ Field 3: If your AUTHORIZATION Password - this is the password that
+ let's IRC know you are who you say you are! Never tell anyone
+ your password and always keep the "irc.conf" file protected
+ from all of the other users.
+
+ Field 4: The Nickname you usually go by - but you can make this what
+ you want. It is better to make this a NICKNAME that no one
+ else knows, but anything will do. I usually use my own
+ loginname.
+
+ Field 5: Unused.
+
+ Field 6: The class field should refer to an existing class (preferably
+ having a lower number than that for the relevant I-line) and
+ determines the maximum number of simultaneous uses of the
+ O-line allowable through the max. links field in the Y-line.
+
+ Example:
+ O:orion.cair.du.edu:pyunxc:Jeff
+
+ There is an OPERATOR at "orion.cair.du.edu" that can get
+ Operator priviliges if he specifies a password of "pyunxc"
+ and uses a NICKNAME of "Jeff".
+
+
+
+ 6. ADMINISTRATIVE INFORMATION
+
+ The "A" command is used for administrative information about a site.
+ The e-mail address of the person running the server should be included
+ here in case problems arise.
+
+
+ A:<Your Name/Location>:<Your Electronic Mailing Addr>:<other>
+ Field: 1 2 3 4
+
+ Explanation:
+
+ Field 1: "A" specifies an Admin record.
+
+
+ Field 2: Use this field to say tell your FULL NAME and where in the
+ world your machine is. Be sure to add your City,
+ State/Province and Country.
+
+
+ Field 3: Use this field to specify your Electronic Mailing Address
+ preferably your Internet Mailing Address. If you have
+ a UUCP or ARAPnet address - please add that as well. Be
+ sure to add any extra DOMAIN information that is needed,
+ for example "mail jtrim@orion" probably won't work as a
+ mail address to me if you happen to be in Alaska. But
+ "mail jtrim@orion.cair.du.edu" would work because you
+ know that "orion" is part of the DOMAIN "cair.du.edu".
+ So be sure to add your DOMAINNAMES to your mailing addresses.
+
+ Field 4: Is really an OTHER field - you can add what you want here,
+
+
+ Examples (the line is just one line in the confuration file, here it
+ is cut into two lines to make it clearer to read):
+
+A:Jeff Trim - Denver Colorado, USA:INET jtrim@orion.cair.du.edu UUCP {hao,
+isis}!udenva!jtrim:Terve! Heippa! Have you said hello in Finnish today?;)
+
+ Would look like this when printed out with the /admin command:
+
+ Jeff Trim - Denver Colorado, USA
+ INET jtrim@orion.cair.du.edu UUCP {hao,isis}!udenva!jtrim
+ Terve! Hei! Heippa! Have you said hello in Finnish today? ;)
+
+
+ Note that the A record cannot be split across multiple lines; it will
+ typically be longer than 80 characters and will therefore wrap around
+ the screen.
+
+
+ 7. REMOVING A USER FROM IRC Remove an errant user from IRC on your site.
+
+ Obviously it is hoped that you wouldn't have to use this command.
+ Unfortunately sometimes a user can become unmanageable and this is your
+ only recourse - the KILL USER command. THIS COMMAND ONLY AFFECTS YOUR
+ SERVER - If this user can connect to another SERVER somewhere else in
+ the IRC-Network then you would have to talk to the administrator on that
+ site to disable his access from that IRCD Server as well.
+
+ The format of this command is:
+
+ K:<Host Name>:<time interval(s)>:<User>
+ Field: 1 2 3 4
+
+ Explanation:
+
+ Field 1: "K" tells the IRCD that you are making a KILL USER command
+ entry.
+
+ Field 2: In this field you specify the Hostname that the user is
+ connecting from. If you wanted to REMOVE connects
+ to IRC from "orion.cair.du.edu" then you would want to enter
+ "orion.cair.du.edu". If you want to REMOVE ALL HOSTS
+ access you can use '*' (Wild Card notation) and no matter
+ what host the USERNAME (specified in Field 4) connects from
+ s/he will be denied access. Removing all hosts isn't
+ very smart thing to do though, why would you run an ircd
+ if you allow nobody to connect to it anyways ?
+
+ Field 3: Either leave this field empty (no spaces), then then lines
+ is active continuously for the specified user/host machine.
+ You may also specify intervals during the line should be
+ active, see examples above.
+
+ Field 4: The USERNAME of the user you want removed from IRC. For
+ example 'root'.
+
+
+ Some Examples:
+ K:orion.cair.du.edu::jtrim
+
+ If user 'jtrim' connects to IRC from host "orion.cair.du.edu"
+ then IMMEDIATELY REMOVE HIM from my IRCD.
+
+ K:*.cair.du.edu::root
+
+ If user 'root' connects to IRC from any host that has the
+ suffix "cair.du.edu" - then IMMEDIATELY REMOVE THEM from
+ my IRCD.
+
+ K:*::vijay
+
+ This line reads "I don't care WHAT HOST user 'vijay' is on,
+ I will NEVER allow username 'vijay' to login to my IRCD.
+
+ K:*.oulu.fi:0800-1200,1400-1900:*
+
+ This disallows all users from hosts with enddomain 'oulu.fi'
+ access to your server between 8 and 12am, 2 and 7pm.
+ Users get kicked off if they're already signed on when the
+ line becomes active (they'll get a warning 5 minutes ago).
+
+ 8. Disallowing SERVERS in your irc net.
+
+ In some cases people run into difficulties in net administration.
+ For one reason or another you do not want a certain server to be
+ in your net (for example because of the security holes it opens
+ for every server if it's not secured carefully). In that case
+ you should use Q-lines in your server. When you specify a server
+ name in Q-line, everytime some server link tries to introduce you
+ a server (remember, all server names are broadcast around the net),
+ that name is checked if it matches the Q-lines in your server.
+ If it matches, then your server disconnects the link. Note that
+ just placing Q-lines to your server probably results in your server
+ being left alone, unless other servers have agreed to have the
+ same Q-line in their ircd configuration files as well.
+
+ Example:
+ Q::of the security holes:foo.bar.baz
+
+ This command excludes a server named "foo.bar.baz", the reason
+ is given to be security holes (you should give a reason, it is
+ polite). The first field is unused, so leave it empty.
+
+ 9. Connection Classes.
+
+ To enable more efficient use of MAXIMUM_LINKS, connection classes
+ were implemented. To give a connection a class, add another field
+ (a sixth) to the C/N lines for a particular server.
+ Each line for a server should have the same number as the sixth
+ field. If it is absent, the server deaults it to 0, using the
+ defaults from the config.h file. To define a connection class,
+ you need to include a Y: line in the irc.conf file. This enables
+ you to define the ping frequency, connection frequency and maximum
+ number of links that class should have. Currently, the Y: line MUST
+ appear in the irc.conf file BEFORE it is used in any other way.
+
+ The format for the line is:
+
+ Y:<CLASS>:<PING FREQUENCY>:<CONNECT FREQUENCY>:<MAX LINKS>:<SENDQ>
+Field: 1 2 3 4 5 6
+
+ Field 2: This is the class number which gains the following attributes
+ and should match that which is on the end of the C/N line.
+
+ Field 3: This field defines how long the server will let the connection
+ remain "silent" before sending a PING message to make sure it is still
+ alive. Unless you are sure of what you are doing, use the default value
+ which is in your config.h file.
+
+ Field 4: By changing this number, you change how often your server
+ checks to see if it can connect to this server. If you want to check
+ very occasionally, use a large value, but if it is an important
+ connection, you might want a smaller value so that you connect to it
+ as soon as possible.
+
+ Field 5: This field defines the maximum number of links this class
+ will allow from automatic connections. Using /CONNECT overrides this
+ feature.
+
+ Field 6: This field defines the 'sendq' value for this class. If this
+ field is not present, the default (from config.h) is assigned.
+
+ NOTE: leaving any of the fields out means their value is 0 (ZERO)!!
+
+ example:
+
+ Y:23:120:300:5
+
+ define class 23 to allow 5 auto-connections, which are checked every
+ 300 seconds. The connection is allowed to remain silent for 120
+ seconds before a PING is sent. NOTE: fields 3 & 4 are in seconds.
+
+ You may also give I lines a class (again the sixth field to define
+ which class). This is only usefull (currently) for redefining the
+ ping frequency. It can also be useful as a diagnostic to see how
+ much each I line is used when combined with the TRACE output.
+
+ Another feature of connection class is the ability to do automatic
+ routing by using the class as a 'priority'. If you are connected
+ to a server which has a class lower than one of the servers that is
+ 'behind' it, the server will disconnect the lower class one and
+ schedule a 'new' connection for the higher class server.
+
+ 10. Leaf Connections.
+
+ To stop servers which should only act as leaves from hubs becoming
+ hubs accidently, the L line was introduced so that hubs can be aware
+ of which servers should and shouldnt be treated as leaves. A leaf
+ server is supposed to remain a node for the entirity of its life
+ whilst connected to the IRC server network. It is quite easy, however
+ for a leaf server to be incorrectly setup and create problems by
+ becoming a node of 2 or more servers, ending its life as a leaf. The
+ L line enables the administrator of an IRC 'Hub server' to 'stop' a
+ server which is meant to act as a leaf trying to make itself a hub.
+ If, for example, the leaf server connects to another server which doesnt
+ have an L-line for it, the one which does will drop the connection, once
+ again making the server a leaf.
+
+ L:<SERVER MASK>:*:<SERVER NAME>:<MAX DEPTH>
+Field: 1 2 3 4 5
+
+ Field 2 is a mask of which servers the leaf-like attributes are used on
+ when the server receives SERVER messages. The wildcards * and ? may be
+ used within this field for matching purposes. If this field is empty,
+ it acts the same as if it were a single * (ie matches everything).
+
+ Field 4 is the the server connectted to you that for which you want to
+ enforce leaf-like attributes upon.
+
+ Field 5 is the maximum depth allowed on that leaf and if not specified,
+ a value of 1 is assumed. The depth is checked each time a SERVER message
+ is received by the server, the hops to the server being the field checked
+ against this max depth and if greater, the connection to the server that
+ made its leaf too deep has its connection dropped.
+ For the L-line to come into effect, both fields, 2 and 4, must match up
+ with the new server being introduced and the server which is responsible
+ for introducing this new server.
+
+ 11. Service Connections (Not yet implemented)
+
+ Introduction.
+ The Service is a special kind of IRC client. It does not have the full
+ abilities of a normal user but can behave in a more active manner than
+ a normal client. Services as they stand now are not fully implemented.
+ The following line can be added to your ircd.conf file to enable a
+ service:
+
+ S:<TARGET Host Mask>:<password>:<service_name>
+ Field: 1 2 3 4
+
+ Explanation:
+
+ Field 2:
+ The host mask should be set to match the hosts(s) from which the
+ service will be connecting from. This may be either an IP# or full
+ name (prefered).
+
+ Field 3:
+ This is the password which must be passed in the SERVICE command.
+
+ Field 4:
+ The 'service name' is only used for the purpose of finding the
+ right S-line from the ircd.conf file for password matching. The
+ actual service name used is that set by NICK commands prior to
+ SERVICE being sent.
+
+ To connect a service to your server, you must first create an S-line
+ entry in your ircd.conf file and get your server to read this in (ie
+ rehash or reboot). Once your server has updated itself, you can then
+ attempt to register your connection as a service.
+ Registering as a service is similar to registering as a normal user
+ except that you must send NICK first and then SERVICE. The service
+ command should look something like this:
+
+ SERVICE secretpassword referencename :Service information
+
+ A successfull registering of a service at the server will result in
+ a RPL_YOURESERVICE (383) being sent back to you. Any other reply as
+ a result of sending service indicates an error has occured.
+
+ A service is not a very useful sort of client, it cannot join channels
+ or issue certain commands although most are available to it. Services,
+ however, are not affected by flood control. It is therefore wise to
+ oversee the use of S-lines with some care.
+
+ 12. Port Connections
+
+ Introduction.
+ The port line adds flexibility to the server's ability to accept
+ connections. By use of this line in the ircd.conf file, it is easy
+ to setup both Unix Domain ports for the server to accept connections
+ on as well as extra internet ports.
+
+ P:<Internet IP# Mask>:<*>:<*>:<PORT>
+Field: 1 2 3 4 5
+
+or
+
+ P:<Directory>:<*>:<*>:<PORT>
+Field: 1 2 3 4 5
+
+ Explanation
+ Internet Ports
+ Field 1
+ The internet IP mask defines where connections may come from and
+ be accepted. The IP mask uses either *'s or 0's as wildcards. The
+ following two lines are the same:
+
+ P:128.2.*:::6664
+ P:128.2.0.0:::6664
+
+ The incoming isnt matched against the mask, rather the ip# string
+ is decoded and compared segment by segment. Thus
+ P:128.2*.1.2:::6664
+ will not match 128.20.1.2.
+
+ Field 5
+ The port number field tells the server which port number it should
+ listen on for incoming connections.
+
+ Unix Socket Ports.
+ Field 1
+ The path set in field 1 should be the directory name in which to
+ create the unix socket for later listening to. The server will
+ attempt to create the directory before creating the unix socket.
+
+ Field 5
+ The port field when used in combination with a pathname in a P-line
+ is the filename created in the directory set in Field 1.
+
+ Example:
+ P:/tmp/.ircd:::6667
+
+ Creates a unix socket in the /tmp/.ircd directory called "6667".
+ The unix socket (file) must be a numerical.
+
+13. Hub Connections
+
+ In direct contrast to L-lines, the server also implements H-lines to
+ determine which servers may act as a hub and what they may 'hub for'.
+ If a server is only going to supply its own name (ie act as a solitary
+ leaf) then no H-line is required for, else a H-line must be added as
+ follows:
+
+ H:<SERVER MASK>:*:<SERVER NAME>
+Field: 1 2 3 4
+
+ Explanation:
+ Field 2
+ All servers that are allowed via this H-line must match the mask
+ given in this field.
+
+ Field 4
+ This field is used to match exactly against a server name, wildcards
+ being treated as literal characters.
+
+ Examples:
+
+ H:*.edu:*:*.bu.edu
+
+ Allows a server named "*.bu.edu" to introduce only servers that
+ match the "*.edu" name mask.
+
+ H:*:*:eff.org
+
+ Allow "eff.org" to introduce (and act as a hub for) any server.
+
+ Note: It is possible to have and use multiple H-lines (or L-lines) for
+ the one server. eg:
+
+ H:*.edu:*:*.bu.edu
+ H:*.au:*:*.bu.edu
+
+ is allowed as is
+
+ L:*.edu:*:*.au
+ L:*.com:*:*.au
+
+
+Appendix A: Difference between IP addresses and hostnames
+
+
+ There are 2 different types of INTERNET addresses, NAME addresses and
+ NUMERIC addresses. NAME addresses look like ENGLISH words (and indeed
+ they are ENGLISH words that refer to a given host). A NAME address looks
+ like "tolsun.oulu.fi" - and that particular address refers to the machine
+ named TOLSUN in Finland. It is a UNIQUE address because no other machine
+ in the world has its NAME address the same as "tolsun.oulu.fi". Anytime
+ you say "telnet tolsun.oulu.fi" - you would always connect to TOLSUN in
+ Finland. NUMERIC addresses refer to those addresses that are made up of
+ NUMBERS for example "128.214.5.6" is the NUMERIC address for TOLSUN. This
+ address is also UNIQUE in that no other machine in the world will be use
+ those NUMERIC numbers. The NUMERIC address is usually more reliable than
+ the NAME address because not all sites can recognize and translate the
+ NAME address into it's numeric counterpart. NUMERIC always seems to work
+ best, but use a NAME address when you can because it is easier to tell
+ what host you are connected to.
+
+
+ Every Unix machine has a file called "/etc/hosts" on it. This file
+ contains NAME and NUMERIC addresses. When you supply IRC with a NAME
+ address it will at first try to find it in /etc/hosts, and then (if it's
+ really smart), use the local Domain Name Server (DNS) to find the NUMERIC
+ address for the host you want to connect to. Thus if you plan to use NAME
+ addresses keep in mind that on SOME sites the entry for the TARGET machine
+ must be found in /etc/hosts or the NAME address will fail. A typical
+ entry in /etc/hosts looks like this:
+
+ 130.253.1.15 orion.cair.du.edu orion.du.edu orion # BSD 4.3
+
+ This particular example is the Host ORION at the University of Denver.
+ Notice that on the far left is the NUMERIC Address for orion. The
+ next few ENGLISH words are the NAME addresses that can be used for orion,
+ "orion.cair.du.edu", "orion.du.edu", "orion". ALL of these NAME addresses
+ will return the NUMERIC address "130.253.1.15" which IRC will use to
+ connect to the TARGET UNIX. (when I say TARGET UNIX I am refering to the
+ UNIX you want to connect to for IRC). Any futher questions about
+ /etc/hosts should be directed to "man hosts".
+
+
+Appendix B: Enabling Summon Messages
+
+ +-----------------------------------------------------------------------+
+ | E N A B L I N G / S U M M O N M E S S A G E S |
+ +-----------------------------------------------------------------------+
+
+ *NOTE* You must have ROOT or special access to the GROUP tty ('/dev')
+ to do this. If you want to allow users around the world to summon
+ users at your site to irc, then you should make sure that summon works.
+
+ The "IRCD" program needs access to the GROUP of '/dev'. This
+ directory is where user TTY's are stored (as UNIX treats each Terminal
+ as a FILE!) IRCD needs GROUP ACCESS to /dev so that users can be
+ SUMMONED to the program by others users that are *in* the program.
+ This allows people from other Universities around the world to SUMMON
+ your users to IRC so that they can chat with them. Berkeley, SUN, HP-UX
+ and most of the newer versions of UNIX check to see if a USER is
+ accepting MESSAGES via the GROUP access rights on their TTY listing
+ in the /dev directory. For example an entry in '/dev' looks like this:
+
+ (Unix Path on BSD 4.3 UNIX is: /dev/ttyp0)
+
+ crw------- 1 jtrim 20, 0 Apr 29 10:35 ttyp0
+
+ You will note that 'jtrim' OWNS this terminal and can READ/WRITE to this
+ terminal as well (which makes sense because I am ENTERING DATA and
+ RECEIVEING DATA back from the UNIX). I logged into this particular
+ UNIX on "April 29th" at "10:35am" and my TTY is "ttyp0". But further
+ of *note* is that I do not have my MESSAGES ON! (mesg n) -- This is
+ how my terminal would look with MESSAGES ON (mesg y):
+
+ crw--w---- 1 jtrim 20, 0 Apr 29 10:35 ttyp0
+
+ With my MESSAGES ON (mesg y) I can receive TALK(1) requests, use the
+ UNIX WRITE(1) command and other commands that allow users to talk
+ to one another. In IRC this would also allow me to get IRC /SUMMON
+ messages. To set up the "IRCD" program to work with /SUMMON type
+ the following: (using ROOT or an account that has access to '/dev').
+
+ % chgrp tty ircd
+ % chmod 6111 ircd
+
+ The above commands read: "Give IRCD access to GROUP tty (which is /dev)
+ and then when ANYONE runs the IRCD allow SETUID and SETGID priviliges
+ so that they can use the /SUMMON command.
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, doc/MANUAL
+ * Copyright (C) 1990, Karl Kleinpaste
+ *
+ * $Id$
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+ Date: 04 Apr 1989
+ Author: Karl Kleinpaste
+ karl@cis.ohio-state.edu
+
+ Last modification: 15 May 1992
+ by Mauri Haikola
+ mjh@stekt.oulu.fi
+
+
+ INTERNET RELAY CHAT
+ a real-time conversational system
+
+
+* 1: Irc - replacement for talk(1)
+
+Irc is a functional replacement for and improvement to talk(1). Talk
+is an old, primitive, atrocious, minimalist sort of keyboard/screen
+conversation tool, using a grotesque, machine-dependent protocol.
+Irc does everything talk does, but with a better protocol, allowing
+more than 2 users to talk at once, with access across the aggregate
+Internet, and providing a whole raft of other useful features.
+
+* 2: Entering Internet Relay Chat
+
+There are two ways to enter Internet Relay Chat. If you are using the
+emacs lisp client, you need to load the client into your Emacs session
+and then M-x irc. If you are using the C client (easier for beginners)
+then type (usually) irc. If you wish to be known by a nickname which
+is not one's login name, type `irc chosen-nickname' instead.
+
+* 3: How much can be seen from here
+
+The universe - seriously.
+
+This is most formally called Internet Relay Chat. Server hosts are
+connected via a tree structure. The various servers relay control and
+message data among themselves to advertise the existence of other
+servers, users, and the channels and other resources being occupied by
+those users.
+
+* 4: Structure
+
+There is quite a lot of structure to the operation of irc, as
+compared to crufty old talk(1). Since so little could be done with
+talk(1), it needed little structure. But to keep track of people
+spread literally around the world (the system was written by Jarkko
+Oikarinen of Finland, usually seen on the system as `Wiz'), the
+structure is useful so that one can speak to exactly those people with
+whom one wishes to speak.
+
+** 4.1: Nicknames
+
+All users of irc are known to the system by a `nickname.' By
+default, one's nickname is one's login name. Nickname clashes are not
+allowed; this is enforced by the servers. If one's intended nickname
+clashes with someone else as one enters chat, one will not be able to
+complete entry to irc until one changes one's nickname to something
+else.
+
+** 4.2: Presence on a channel
+
+Fundamental to the operation of irc is the concept of a channel. All
+users are `on a channel' while inside irc. One enters the `null
+channel' first. One cannot send any messages while not in any
+chatting channel unless one has set up a private conversation in some
+way. The number of channels is essentially unlimited - whatever will
+fit in a string of some ungodly length, that must start with a # sign.
+
+** 4.3: Main modes of channels
+
+Public
+
+This is the default mode for a channel. When one is on a public
+channel, one can be seen by all other users (if one's own user mode
+permits this). Anyone can notice users on a public channel and join
+such a channel's conversation.
+
+Private
+
+This means that, although anyone can see that one is using chat, no
+one can tell what channel one is using unless one is already on that
+channel with oneself. Since the number of potential channels is in
+the billions, this is quite some security - all one gives away is the
+acknowledgement that one is using chat.
+
+Secret
+
+While one is on a secret channel, no one who is not on one's channel
+with oneself can even see that one is there. One's name does not show
+up in a list of active users. The only indication of one's presence
+is that, when entering chat, all new users are told that there are "N
+users on P servers." If one checks on all users and finds less than N
+of them, one knows that others are hiding on secret channels. But a
+secret channel user still cannot be found except by brute-force
+checking through all channels, a hopeless proposition in the face of
+the huge number of possible channel names. Security through obscurity
+finally means something.
+
+Changing the mode
+
+The mode of a channel (private, secret, invite-only, moderated,
+topic-limited, person-number-limited, no-messages-to-channel, ban
+someone from channel) is set by the channel operator, who is the
+first person to join a channel, or someone who has had channel
+operatorship bestowed on them by another channel operator.
+
+
+*** 4.4: Conversations not using channels
+
+It is possible to conduct conversations with others without using the
+formalized channel structure. Doing so requires that two people set
+themselves up for private conversation using special commands; see
+User Commands below.
+
+* 5: Screen/keyboard structure
+
+Chat is a full-screen utility. It takes over the screen, with the
+bulk of activity happening in the top N-2 lines, a modeline (vaguely
+emacs-like) on the next to last line, and one's input being entered on
+the last line. A very good version of client is the IRC-II client,
+avaliable on anonymous ftp from various sites around the world.
+
+** 5.1: Keyboard input
+
+When typing commands at irc, one has a minimalist line-editing
+facility in an emacs style. That is, ^A moves the cursor to the
+beginning of the line, ^E goes to the end, ^D deletes the character
+under the cursor, ^K kills from the cursor to the end, and so on.
+
+** 5.2: Screen activity
+
+Almost everything happens in the upper bulk of the screen. This
+includes both messages from other users, as well as the output of the
+control commands.
+
+Normal messages from other users appear with the originating nickname
+in <angle brackets>. Private messages arrive with the originating
+nickname in *asterisks*. Messages which one sends to everyone appear
+with a preceding "> " whereas messages which one sends privately to
+one other user appear with "-> *nickname*."
+
+Other output (e.g., /who commands, invitations from other users to
+join channels, and so forth) appears interspersed with other activity
+on the screen.
+
+* 6: Command structure
+
+Ordinary text typed at irc is sent as one's messages to everyone else
+on the same channel, modulo personal choices for private messages and
+the like. Commands to irc itself all begin with a command character,
+which is initially `/' but may be changed to any other character
+desired.
+
+Commands may in general be abbreviated to a unique prefix.
+
+** 6.1: Leaving irc
+
+The way to get out of irc is to enter the /signoff command. "/si" is
+sufficient. Also equivalent are "/exit," "/bye," and "/quit." A
+signoff command may include a comment which will be seen by everyone
+on the current channel of the person who left.
+
+** 6.2: Getting help
+
+Type "/help." Follow the instructions.
+
+** 6.3: User commands
+
+The most important commands supported by irc are:
+
+ help signoff who whois
+ list topic join channel
+ links msg invite ignore
+ users stats nick away
+ info clear query cmdch
+ date mode
+
+*** 6.3.1: help
+
+Information on how to use the rest of the system is available via
+/help. The modeline says so as well.
+
+*** 6.3.2: signoff {comment}
+
+/signoff exits chat. Optional comment may be included; see above.
+
+*** 6.3.3: who
+
+/who returns information on who is using chat. /who without arguments
+prints info on all users that can be seen. Users of public channels
+show up with their channel identified. Users of private channels
+appear, but they are specified as being on a private, unspecified
+channel. Users of secret channels and users whose user mode is +i
+(invisible) do not appear at all.
+
+Giving a channel name as an argument to /who returns only those users of the
+specified channel. This still doesn't show users of secret channel or
+invisible users one is actually on the same channel with them. Users
+of private channels are shown, if an exact channel name is given.
+
+*** 6.3.4: whois
+
+This returns information about individual users. Say "/whois
+nickname" to get information on the login name and host from which the
+nicknamed user comes.
+
+*** 6.3.5: topic
+
+Channels can be given off-the-cuff "topics." Saying "/topic some
+string of text" will associate that topic with the current channel.
+
+*** 6.3.6: list
+
+/list will give lists of active channels, the number of users of each,
+and the topics therewith associated. Again, secret channels do not
+appear and private channels only appear as Prv.
+
+*** 6.3.7: join & channel
+
+/join or /channel are the means to enter a channel. Give the channel
+name as an argument. If this is a secret or hidden channel, /who
+commands will show oneself and any other users of one's channel.
+
+One's arrival on a channel is announced to the rest of the users
+already on that channel. Silent, anonymous "lurking" is not
+supported.
+
+*** 6.3.8: links
+
+/links lists the currently-active set of chat servers. Beware: this
+list can be quite long, and will undoubtedly get longer as chat gains
+wider use. As of 15 May, 1992, about 130 servers is typical.
+
+*** 6.3.9: msg
+
+A single message can be sent privately to a certain user with /msg.
+Type /msg nickname and the text to be sent. It will be sent privately
+to the indicated nickname.
+
+*** 6.3.10: invite
+
+If there is a user online to whom one wishes to speak, one may invite
+that user to join oneself on a certain channel. One types "/invite
+nickname" with an optional channel number. The receiving user gets a
+one-line message indicating the sender and the invitation. The
+receiving user is free to ignore the invitation, of course.
+
+*** 6.3.11: ignore
+
+If one wants to ignore messages sent by some other user or users, it
+may be done with /ignore command. One can ignore someone by their
+nickname, or by their user@host data. Wildcards may be used.
+
+*** 6.3.12: users
+
+/users will return a list of the users logged into one's system. With
+an optional hostname identifying a chat server host, the users logged
+into that system will be listed.
+
+*** 6.3.13: stats
+
+This command returns counts of various protocol operations of one's
+chat server. It is neither particularly useful nor interesting to
+users other than operators.
+
+*** 6.3.14: nick
+
+One can change nicknames by issuing "/nick new-nickname." All users
+on one's channel will be advised of the change. NOTE: If one enters
+chat with a nickname clash (e.g., one's login name is the same as
+someone else's, and the other user got there first), the system will
+not let one enter until one issues a /nick command with a unique
+nickname.
+
+*** 6.3.15: away
+
+Sometimes, one wishes to remain connected to the chat system, but one
+must be elsewhere for a while. One can issue an /away command with
+arbitrary text as argument, which will mark oneself as being away. If
+someone sends an away'd user a private message (via /msg or in a
+private session set up via /query; see below), the sender will get a
+message back from the server indicating the away-ness and the message
+which was set.
+
+*** 6.3.16: info
+
+/info returns information regarding the author and copyright of the
+chat system.
+
+*** 6.3.17: clear
+
+At times, one wishes that one's screen weren't so cluttered. /clear
+makes it so.
+
+*** 6.3.18: query
+
+This command is used to set up private communications `outside' the
+normal channel system.
+
+When one enters "/query nickname," the indicated nickname is set up as
+the sole recipient of anything which one types thereafter. Thus, if
+user A executes "/query B" and user B executes "/query A," they have
+set up a private communication between themselves. Significantly, it
+remains possible for them to stay on their respective channels, which
+need not be the same, and listen to whatever conversation is going on
+around them as well, though they cannot respond to that ambient
+conversation without leaving the private conversation they have set up.
+
+One leaves this private mode by issuing /query without arguments.
+
+*** 6.3.19: cmdch
+
+The `/' character may not be best for some people to use as their
+command character. It can be changed with "/cmdch <character>."
+
+*** 6.3.20: mode
+
+This command can be used for altering the various modes of a channel
+(see the explanation of channel modes above). /mode command can only
+be issued by channel operators.
+
+** 6.4: Operator commands
+
+The chat system administrators on each host have additional
+responsibilities and power over the configuration and operation of the
+servers. The commands to do so are delineated below.
+
+*** 6.4.1: oper
+
+Users who have the potential for operator privileges initially invoke
+those privileges by "/oper nickname password," where nickname is the
+nickname under which operation is intended, and password is the
+password known to the chat system for that nickname.
+
+*** 6.4.2: kill
+
+Obnoxious users had best beware the operator who's fast on the /kill
+command. "/kill nickname" blows any given nickname completely out of
+the chat system.
+
+Obnoxiousness is not to be tolerated. But operators should not use
+/kill lightly.
+
+*** 6.4.3: quote
+
+Raw access to the underlying server protocol is possible through the
+user of the /quote command. "/quote any text at all" is used to send
+direct, unmodified commands to the servers. This has a wide variety
+of uses, such as deliberately killing a local or remote chat daemon,
+invoking operator privileges for otherwise-operator-priv-forbidden
+users, and related tasks. It is, again, a very powerful operation,
+and not to be used lightly.
+
+* 7: Questions, problems, troubles?
+
+If you have problems, please contact Christopher Davis (ckd@eff.org) or
+Helen Rose (hrose@eff.org). Known as "ckd" and "Trillian" on irc,
+respectively. You can also ask for help on some of the operator
+channels on irc, for example #twilight_zone and #eu-opers. They will
+be able to assist you in whatever problems you are having with IRC.
+
--- /dev/null
+Internet Relay Chat Operator Etiquette Guide (May, 1992)
+[ $Id$ ]
+
+Welcome! You've either been selected to be an IRC Operator or you have set
+up your server and thus have taken on the dual task of IRC Server
+Administrator and IRC Operator. Your future days will be filled with hours
+of fun chatting on IRC, and then wondering why everyone you talked to went
+away, because the links had apparently broken.
+
+Linking:
+========
+
+You will be assigned links from the IRC Routing Coordinators. Please
+use these links and these links ONLY. The links have been designed to
+maximize efficiency and make delays in chatting minimal. You will
+usually be given two links, one to each regional backbone site.
+Connect to the primary site first and then to the secondary site. You
+should not need to connect to any other sites. You will be informed if
+this policy changes.
+
+Kills
+=====
+
+/kill is a special operator command. You should use it with
+care, and only if absolutely needed. The format is as follows:
+/kill NICKNAME comment. Comment can be a phrase of almost any length
+(within reason) and should be used for specifying the reason of the kill.
+Example: /kill Trillian She's a Ghost
+IRC Ghosts are created after a net split has occured and the net has yet to
+relink.
+
+/wallops PHRASE This is used to talk to those users who have their
+user mode set to +w. /wallops used to be a way for operators to talk
+about important matters in linking etc., but it has little use
+nowadays.
+
+/TRACE command /TRACE is useful to know what servers are connected to
+what. Sometimes /trace can be confusing, especially if you are using
+it for the first time. Here is an example of a trace from
+stekt1.oulu.fi to cdc835.cdc.polimi.it.
+
+/TRACE cdc835.cdc.polimi.it
+
+*** Link stekt1.oulu.fi<2.7.2> ==> cdc835.cdc.polimi.it
+*** Link rieska.oulu.fi<2.7.1>e ==> cdc835.cdc.polimi.it
+*** Link nic.funet.fi<2.7.1>e ==> cdc835.cdc.polimi.it
+*** Link ircserver.et.tudelft.nl<2.7.1>e ==> cdc835.cdc.polimi.it
+*** Link vesuv.unisg.ch<2.7.1>e ==> cdc835.cdc.polimi.it
+*** Link apollo.di.unipi.it<2.7.1>e ==> cdc835.cdc.polimi.it
+*** Oper Class[10] ==> Allanon[cdc835.cdc.polimi.it]
+*** User Class[11] ==> Lupandy[plus2.usr.dsi.unimi.it]
+*** Serv Class[3] ==> apollo.di.unipi.it[131.114.4.36] 132S 445C
+*** User Class[11] ==> Punk[pluto.sm.dsi.unimi.it]
+*** User Class[11] ==> TheEdge[pluto.sm.dsi.unimi.it]
+*** User Class[10] ==> Mork[cdc835.cdc.polimi.it]
+*** User Class[11] ==> Lollo[c700-2.sm.dsi.unimi.it]
+*** User Class[11] ==> Attila[hp2.sm.dsi.unimi.it]
+*** Class 0 Entries linked 1
+*** Class 11 Entries linked 5
+*** Class 10 Entries linked 2
+*** Class 3 Entries linked 1
+
+From this output you can see that the route goes first to
+rieska.oulu.fi (running version 2.7.1e), then nic.funet.fi,
+ircserver.et.tudelft.nl, vesuv.unisg.ch, and apollo.di.unipi.it, after
+which cdc835 is the next server. Then we see the connections on
+cdc835: One operator (Allanon) and 6 users are on line. The class of
+each connection is given. There is only one server connected to cdc835
+at the moment, and that server is apollo.di.unipi.it (cdc835 is said
+to be a "leaf" server at the moment). The numbers 132S 445C in the end
+of line tell us, that there are 132 servers and 445 clients connected
+to the servers from apollo onwards. Finally we see a grand total of
+connections in each connection class.
+
+
+/SQUIT server {comment}
+ /squit isolates a specified server from the next closest server, when
+you look at it along the trace path starting from your server.
+This is usually used in conjunction with CONNECT (explained later) to
+reroute traffic. This will be described in detail in the section
+"routing", preceding CONNECT.
+
+ Usage (and examples):
+
+ /squit E
+
+ If the network looks like this initially (and you are on server A)
+
+
+ A <---> B <---> C <---> D
+ ^
+ |
+ v
+ G <---> E <---> F <---> ... (rest of the net)
+
+
+ Then after issuing the previous /squit the network would look like this:
+
+ A <---> B <---> C <---> D
+
+
+ G <---> E <---> F <---> ...
+
+
+ /squit E {comment}
+
+ It usually helps to give a reason why you are sending a
+ SQUIT for a server. This can be accomplished by sending
+ the command "/squit server This link is making the US route
+ through Finland". The SQUIT will then be sent out, and the
+ server sending the squit will WALLOP sending the comment
+ so all operators can see it.
+
+/CONNECT server {portnum server2}
+ /connect is used to establish a link between two servers. These
+connections must be authorized by each server's ircd.conf file, but
+any operator can issue a CONNECT between authorized servers. This
+command is most often used in conjunction with SQUIT to reroute
+traffic.
+ If only one argument is given, this command causes the server you
+are on to attempt to connect to the server specified. For example,
+"/connect B" (in the previous example) would cause your server (A) to
+connect to B.
+ Suppose you wanted to reconnect server F to server E? You cannot
+contact server F since it is no longer part of your network. However,
+you can tell server E to connect to it. A remote CONNECT can be issued
+to server E.
+
+ Examples (assume you are on server A):
+
+ /connect B
+
+ If the network initially looks like this:
+
+ A B <---> ... (rest of network)
+
+ Then afterwards (if the connection succeeds) the network will look
+ like this:
+
+ A <---> B <---> ...
+
+
+ In the example where you wanted to reconnect server E to F, the
+ following syntax would be appropriate (note: we are assuming that
+ F's irc socket port is 6667, which is the default)
+
+ /connect F 6667 E
+
+ If the network initially looks like this:
+
+ A <---> B <---> C <---> D
+ ^
+ |
+ v
+ G <---> E F <---> ...
+
+ Then after your CONNECT request the network topology will look like this:
+
+ A <---> B <---> C <---> D
+ ^
+ |
+ v
+ G <---> E <---> F <---> ...
+
+ Be careful when connecting servers that you know which command to
+ use! If you simply issued "/connect F" from your server, the
+ network would look like this:
+
+
+ ... <---> F <---> A <---> B <---> C <---> D
+ ^
+ |
+ v
+ G <---> E
+
+ which for various reasons (discussed below) might be very
+ undesirable.
+
+Routing
+=======
+
+ When and how should you do rerouting? This depends on where your
+server is topologically located and whether you route traffic. If you
+are a leaf node (i.e. only connect to one server at a time) then
+chances are you won't need to do any routing at all. Your ircd.conf
+file should be written to connect to the best possible servers first
+before trying alternates. At the most, you may decide to squit an
+alternate server and connect to your primary if/when it goes back up.
+This only involves local squits, however.
+
+ If you are operating a backbone site, you may find yourself
+rerouting things quite often. If the servers badger.ugcs.caltech.edu
+(Pasadena, CA), irc.mit.edu (Boston, MA), minnie.cc.utexas.edu
+(Austin, TX) and ucsu.colorado.edu (Boulder, CO) were routing traffic
+in the following way:
+
+ ... <---> minnie <---> badger <---> bucsd <---> ucsu <---> ...
+
+It would make sense to either squit ucsu and reconnect it to minnie,
+or disconnect minnie from badger and connect to ucsu, because
+topologically (and geographically) ucsu and minnie are rather close.
+There are occasions when US traffic for some reasons winds up being
+routed through Australia. This is another case where traffic should
+definitely be rerouted. However, there are sometimes occasions when
+routing is going through "backdoor" methods. If you see something
+totally outrageous (like the east coast and the west coast being
+connected by eff.org) please ask for example on channel #twilight_zone
+before you send any squits, because chances are, it's like that for a
+reason.
+
+ Of course, any operator can remotely squit or connect servers, so
+if you see a problem and you're sure you know how to fix it, it's a
+good idea to do so. If the operator of a server which is is being
+routed poorly is online, it's probably best to contact him/her first,
+though.
+
+ Chances are that hub operators will be more familiar with the
+general topology of the network and which servers connect to which
+(which is why most of the manual routing is left to them), so if you
+have any problems, talk to the other operators on operator channels
+(#twilight_zone, #eu-opers etc.) That's what they are there for!
+ Also, be aware that servers will notify all the operators online of
+remote SQUITs and CONNECTs via WALLOPS.
+
+Please let us know if there should be any additions to this guide. Again,
+this is not MANDATORY, this is just a GUIDE. Please conduct yourself as
+an IRC Operator would...you are looked upon for assistance, both emotional
+and mental.
+
+Helen Rose Christopher Davis Noah Friedman
+<hrose@cs.bu.edu> <ckd@cs.bu.edu> <friedman@ai.mit.edu>
+
+January, 1991
+
+
+Updated by
+
+Mauri Haikola
+<mjh@stekt.oulu.fi>
+
+May, 1992
--- /dev/null
+esOriginally by Roddy Vagg -- roddy@dal.net
+modified for UnrealIRCD3.0
+
+--------------------
+
+ 1) ............................. Introduction
+ 2) ............................. ircd.conf Basics
+ 3) ............................. ircd.conf Lines
+ 3.1) .......................... M Lines
+ 3.2) .......................... A Lines
+ 3.3) .......................... Y Lines
+ 3.4) .......................... I Lines
+ 3.5) .......................... O Lines
+ 3.6) .......................... U Lines
+ 3.7) .......................... C and N Lines
+ 3.8) .......................... K Lines
+ 3.9) .......................... q Lines (server form)
+ 3.10) ......................... Q Lines (nickname form)
+ 3.11) ......................... L Lines
+ 3.12) ......................... H Lines
+ 3.13) ......................... P Lines
+ 3.14) ......................... T Lines
+ 3.15) ......................... E Lines
+ 3.16) ......................... e Lines
+ 3.17) ......................... Summary
+ 4) ............................. dccdeny.conf
+ 4.1) .......................... deny Lines
+ 5) ............................. chrestrict.conf
+ 5.1) .......................... msg Lines
+ 5.2) .......................... allow Lines
+ 6) ............................. vhost.conf
+ 6.1) .......................... vhost Lines
+ 7) ............................. unrealircd.conf
+ 7.1) .......................... Include Line
+ 7.2) .......................... Set KLINE_ADDRESS Line
+ 7.3) .......................... Set MODE_X Line
+ 7.4) .......................... Set MODE_I Line
+ 7.5) .......................... Set TRUEHUB Line
+ 7.6) .......................... Set CONFIG_FILE_STOP Line
+ 7.7) .......................... Set SHOWOPERS Line
+ 7.8) .......................... Set KILLDIFF Line
+ 7.9) .......................... Set SHOWOPERMOTD Line
+ 7.10) .......................... Set HIDE_ULINES Line
+ 8) ............................. network files
+ 8.1) .......................... Network Line
+ 8.2) .......................... Set ircnetwork Line
+ 8.3) .......................... Set defserver Line
+ 8.4) .......................... Set SERVICES_NAME Line
+ 8.5) .......................... Set oper_host Line
+ 8.6) .......................... Set admin_host Line
+ 8.7) .......................... Set locop_host Line
+ 8.8) .......................... Set sadmin_host Line
+ 8.9) .......................... Set netadmin_host Line
+ 8.10) ......................... Set coadmin_host Line
+ 8.11) ......................... Set techadmin_host Line
+ 8.12) ......................... Set hidden_host Line
+ 8.13) ......................... Set netdomain Line
+ 8.14) ......................... Set helpchan Line
+ 8.15) ......................... Set STATS_SERVER Line
+ 8.16) ......................... Set HUB Line
+ 8.17) ......................... Set iHAN Line
+ 8.18) ......................... Set net_quit Line
+
+--------------------
+
+1) Introduction:
+
+ If you are running, or planning on running an IRC server for a network,
+ you will need to setup an ircd.conf, your ircd.conf must meet the
+ requirements of a linked network server which means it must contain all
+ the standard network lines, these will be listed at the bottom of this
+ document. (If you make your own network you may customize them yourself)
+
+--------------------
+
+2) ircd.conf Basics:
+
+ When you compile your server, you must specify the correct paths to
+ where you plan on keeping your ircd.conf, for simplicity it is recomended
+ that you keep it in the same diretory as your ircd binary and other ircd
+ files.
+ note: You need only supply full pathnames for DPATH and SPATH, the
+ other defines will only point to files under these directories so you
+ need not put full path names.
+ For security reasons, your ircd.conf should have permissions set to 600,
+ if other users on your system gain access to view the file they may be
+ able to breach the security of your server and compromise the whole
+ network.
+ When you have made your ircd.conf you may check it with the program
+ `chkconf', this program is supplied with the source code release and will
+ be installed into your ircd directory when you run `make install',
+ `chkconf' will check your ircd.conf for errors so is a usefull tool for
+ beginners to ircd.conf.
+ Your ircd.conf will be made up of a series of lines, each line is used
+ for a different purpose in the running of your server, some lines are
+ mandatory for ircd, so you must enter these lines or your server will not
+ start, these lines are listed below.
+ You may enter comments in your ircd.conf with the use of a hash mark (#)
+ at the beginning of a line, it is recommended that you make full use of
+ this to add comments to everything you put in your ircd.conf so you dont
+ have any problems later.
+ eg: Put a contact email address and the name/nick of the server admin
+ above each C/N line pair.
+ When ircd reads the ircd.conf file, it does it upside down, so lines with
+ higher prefrence should go lower in the file, this will be explained later.
+
+--------------------
+
+3) ircd.conf Lines:
+
+ Each type of line in this section will be given a rating of how needed
+ it is in the running of the server, the ratings are:
+
+ MANDATORY: you absolutely MUST have this line
+ NETWORKED: you must have this line if plan on connecting your server
+ to other servers. (note: you can run ircd stand alone)
+ SUGGESTED: it is highly suggested that you use this line
+ OPTIONAL: it's completely up to you whether to define this or not
+ DISCOURAGED: you really really should not use this line if at all
+ possible.
+
+ Note that "*" in a field indicates an "unused" field.
+
+--------------------
+
+3.1) M Lines: [MANDATORY]
+
+ This line sets your server's name, description, and port number.
+ If you are to be a part of DALnet you will be assigned 2 different
+ DNS entries for your ircd machine, the 1st is for general public use
+ and involves: <servername>.DAL.net
+ The second is for use between servers for identification, these take
+ the form of: <servername>.[<state>].<country>.DAL.net
+ If your server is located in the US or Australia, you will be given
+ a `state' field in your server's real name, otherwise your `state', or
+ `area' will not be included.
+ Most IRC networks default to port 6667 for their client connection's,
+ but DALnet uses port 7000 as its standard, you should compile ircd with
+ port 7000, not 6667, but you may open up port 6667 (it is recomended
+ that you do) with a P line (see later). Your M line's port number
+ should be the same as the number you defined in your config.h at compile
+ time.
+
+ Syntax:
+M:hostname:IP:Description Of Your Server:7000
+ The 1st field should be the `real' name of your server, not the short
+ name.
+ The 2nd field is the IP the server should bind to - "*" if all interfaces
+ on the server
+ The 3rd field is your server's description, it is up to you what you
+ put in this field, but a short description of its geographic location
+ is recomended.
+ The 4th field is the port number you compiled ircd with. This should be
+ 7000 for DALnet.
+
+ Example:
+M:disney.irc.net::Walt's IRC Server:7000
+
+--------------------
+
+3.2) A Lines: [MANDATORY]
+
+ This line sets your server's administrative information.
+ Whenever a user types /admin on your server (or /admin <servername>)
+ they will recieve the information you put here.
+ This line has no set information, so you may put arbitrary text if you
+ like, but it is recomended that you at least put your nick and email
+ address so users may contact you if need be.
+
+ Syntax:
+A:A little info about your server:Admin's nick/real name:contact address
+ There is no fixed standard, so you may put whatever you like in each
+ field, but you should put enough information for users to contact someone
+ responsible for the server.
+
+ Example:
+A:Disney's IRC Server:Admin - Walt Disney:walt@RIP.org
+
+--------------------
+
+3.3) Y Lines: [SUGGESTED]
+
+ These lines define connection classes. They allow you to fine-tune
+ your incomming and outgoing connections, both server and client types.
+ These classes are for use with C, N, I and O lines, more on this in later
+ sections. DALnet has a set of Y lines that each server must use for their
+ server connections, these are listed below and again at the bottom of this
+ document. Client connection classes are your responsibility, you must
+ make up your own set of Y lines for client connections based on your own
+ situation (netwise location, machine, etc).
+ Connection classes define a number of parameters for connections, these
+ include:
+ o Ping frequency of a silent connection.
+ o Connect frequency (for server connections only!).
+ o Maximum number of links allowed on the specific connection class.
+ o Maximum sendq allowed for the connection before it is dropped.
+ Your Y line numbers are not arbitraty. For server connection classes, the
+ higher the class number, the higher the priority the connection's are given
+ when auto-connecting, (see C/N lines below).
+ - Ping frequency: When a connection is silent for this period of time
+ the server will send a PING to the connection, if the client/server
+ on the connection does not reply after a set period of time, the
+ connection will be dropped. A value in this field will override the
+ ping frequency defined at compile time in your config.h. For server
+ connection classes, you should have the same ping frequency on both ends
+ of the link, so you should stick with the standard DALnet classes.
+ - Connect frequency: Since clients connect to servers and NOT the other
+ way around, only server connection classes need to have a connect
+ frequency. Client classes should have this field set to 0. When a server
+ listed in the server's ircd.conf (see C/N lines) is missing and belongs
+ on a conenction class that is holding less connections that defined by
+ the max links field, the server will keep on trying to connect to
+ the missing server. The ammount time between connection attempts is what
+ you define in this field.
+ example:
+ server1 and server2 are listed in server0's ircd.conf but the only
+ visible server to server0 is server1, both server1 and server2 are
+ in server0's ircd.conf on the same connection class that allows for `2'
+ links, server0 will go looking for server2 and try to connect to
+ it each `connect frequency' seconds until the server becomes visible
+ again, either by direct connection to server0, or by connection to server1
+ - Maximum number of links: Each Y line should have a restriction on the number
+ of connections allowed on the class. For client connections, when the limit
+ is reached on a particular class, connecting clients trying to connect
+ through this class are rejected. A server connecting on a `full' connection
+ class will be allowed as this number on server connection classes is used for
+ auto-connect purposes. As shown in the above example, when a missing server
+ is listed for a particular connection class, and the class is not `full',
+ your server will try and connect to this server untill it becomes visible
+ again. Servers being connected manually on a `full' connection class via the
+ /connect command will be allowed as long as you compiled with MAXIMUM_LINKS
+ high enough to accomidate all of your server connections. (you must compile
+ as a HUB if you wish to hold more than one server connection, also see H
+ lines later in this document).
+ - Maximum sendq: SendQ defines the `que' of data waiting to be sent to the
+ client/server on the other end of the connection. SendQ's will build up if
+ the client requests more data than the link can handle, say if they issue the
+ /list command on a network with a lot of channels and they are only on a
+ 14.4K link, their sendq on the server will build up as all the data cannot
+ be sent at once, the sendq size will decrease as the data is sent, and
+ increase as more data is requested. Clients will normally sit with a sendq of
+ 0, it is `abnormal' for a sendq to be high for a client for a long period
+ of time. When 2 servers connect, they must send their own data to
+ eachother, this data includes: all the users on the server and already
+ connected servers, channels, user modes, channel modes, topics (DALnet only)
+ etc. When there are many clients on a particular side of the connection, a
+ sendq will build up, especially if the link is slow, or already congested
+ (example: the link from Australia to the US). When the sendq built up reaches
+ the max sendq defined in the connection class for the particular
+ client/server, the connection will be dropped. If max sendq's are
+ particularly high, it will allow clients/server to take up excess memory on
+ the ircd machine so a limit should be placed, especially on client connection
+ classes. (IMPORTANT!) If any value of max sendq defined in a connection
+ class exceeds the value defined at compile time in your config.h, the sendq
+ value will default back to the compile time sendq. If your sendq field in
+ a Y line is empty, the class will use the default defined in your config.h
+ SendQ's for all connections on your server can be viewed with the
+ /stats l <servername>
+ command, this will show information for all your server's current links.
+ You should have a set of standard server connection classes, at least one
+ client connection class, and an Operator class. (see relevant parts of this
+ document for notes on each of these)
+
+ Syntax:
+Y:Class #:Ping frequency:Connect frequency:Max links:Max sendq
+
+ Examples:
+Y:1:90:0:20:10000
+ In this case, connect-frequency is 0 indicating that this is a client
+ class (servers never connect to clients, it is the other way around).
+ Clients may only idle for 90 seconds before being pinged by the server.
+ The number of clients allowed to use this class is 20.
+ Clients may only build up a sendq on the server of 10000 bits.
+
+ These are the standard server Y lines used on DALnet:
+
+# Connecting a hub to a hub
+Y:20:10:300:1:3000000
+# Connecting a US hub to a US leaf
+Y:30:45:0:0:2000000
+# Connecting a US leaf to a US hub
+Y:35:45:20:1:2000000
+# Connecting a US hub to an EU leaf
+Y:40:60:0:0:2200000
+# Connecting an EU leaf to a US hub
+Y:45:60:20:1:2200000
+# Connecting a US hub to an AU leaf
+Y:42:240:0:0:2200000
+# Connecting an AU leaf to a US hub
+Y:43:240:60:1:2200000
+
+--------------------
+
+3.4) I Lines: [MANDATORY]
+
+ These lines are the ones initially responsible for letting clients connect
+ to your server. So called `client-authorization' lines, they define who
+ may connect, and which connection class they will connect through.
+ I lines, like C, N and O lines refer back to Y lines, as they allow
+ connections, and each connection to ircd needs to be assigned to a
+ connection class. If you dont provide a connection class, the connection
+ will be governed by the defaults set at compile time in your config.h.
+ When a client connects to the server, it gives its own information,
+ this information includes username, nick and can include a password, the
+ server then goes through its client-authorization rules (I lines) to see
+ if the client fits any of the connection criteria.
+ The rules for connection on the I lines are read from right to left, so
+ if a connection is made, it is made on the right most rule it matches on
+ the line. Also, since the ircd.conf is read upside down, the server will
+ put the client on the lowest I line matching the client information. This
+ means that if the 1st rule the client can connect on matches a connection
+ class (Y line) that is `full' (see above), the client will be rejected,
+ even if there is a line further up in the file that the client matches on
+ that uses a connection class that has room for more clients. This means
+ that I lines may be used in much the same fashion as K lines (see later)
+ to block certain clients. It also means that you may place certain clients
+ on many different connection classes. (examples later)
+
+ Syntax:
+I:IP-address-mask:optional password:host/domain-mask::connection class (opt)
+ Wildcards (`*') may be used in the mask fields (1 and 3) to allow for
+ very broad connection rules. Ident (for more information on this, see
+ rfc1413) can also be used by placing an `@' in the mask fields in the
+ appropriate positions. If you don't want to use ident, only give the
+ host/IP part of the connecting addresses, if you add a @ (usually used
+ as *@), ircd will try and use ident to check the real username of the
+ client, any connecting clients on host's that are running ident that
+ give usernames that dont match those found by ircd will be rejected by
+ the server. If the host is not running ident, a `~' will be placed in
+ front of the username of the connecting client to show that the its
+ host isnt running ident.
+
+ Examples:
+
+I:*@*:foobar:*@*::1
+ This line will allow anyone from any host that uses the password
+ "foobar" to connect through connection class 1 (Y line 1), the server
+ will also try and use ident to verify the username of the client.
+ Placed at the top of the I lines in your ircd.conf, this line may serve
+ as a fall-through for connecting clients, any client that does not match
+ any other I line but gives the password "foobar" will be able to connect
+ through this line (If Y line 1 has space).
+
+I:205.133.*::*.toledolink.com::1
+ This is a standard vanilla I: line which will permit anyone with an IP
+ address starting with 205.133 OR with a hostname ending in
+ .toledolink.com to connect to the server. remember, ircd uses the
+ right-most match, so if I connect as rmiller@glass.toledolink.com
+ (which is rmiller@205.133.127.8) I will show up on irc as
+ rmiller@glass.toledolink.com since that is the first match it found.
+ (Even though the second match is valid). Any clients comming through
+ on this line will use connection class 1.
+
+I:*@205.133.*::*@*.toledolink.com::1
+ Same as above, but the server will use ident. You may even specify
+ certain usernames with ident I lines, but they will only match if their
+ host is running ident.
+
+I:NOMATCH::rmiller@glass.toledolink.com::1
+ Putting NOMATCH in the first field will stop the ircd from matching
+ automatically against the IP address and it will force the server to
+ match against the hostname. (the "NOMATCH" string is not mandatory, you
+ can use any arbitrary text in the first field).
+
+I:*@*:ONE:*@*.com::1
+ Putting ONE is the second field says that only one user may connect through the
+ use of this I:line. Once that one user is connected this I:line is ignored by
+ other users.
+
+ Bulk example:
+I:NOMATCH::*@*::1
+I:NOMATCH::*@*.fr::2
+I:NOMATCH::*@*.de::3
+I:NOMATCH::*@*.se::4
+I:NOMATCH::*@*.au::5
+I:129.180.*::*.une.edu.au::6
+ In this example, conencting clients will 1st be matched against the mask
+ *.une.edu.au, if they match they will be placed on connection class 6
+ (note: if 6 is full, they will be rejected, they wont be passed on to the
+ next I line), then tried against the IP 129.180.*, if they match, they will
+ be placed on class 6. If the client dosen't match either of these masks, they
+ will be tried against the mask *.au, so if they are from Australia, but are
+ not from *.une.edu.au they will be placed on class 5. This goes on through
+ the other lines, being placed on the various connection classes if they match
+ any of the indicated host masks, if the client is not from the IP 129.180.*,
+ Australia, Sweden, Germany or France, they will be connected through the
+ final (top) I line as it serves as a fall-through, so these clients will be
+ put on class 1.
+
+--------------------
+
+3.5) O Lines: [OPTIONAL]
+
+ These lines provide rules as to who may gain Operator status on your server.
+ O lines are much like I lines in their operation and syntax.
+ Servers need not have any Operators as ircd, given well defined connection's
+ can perform all of its functions automatically. Server admins have the
+ ability to `kill -HUP' the server's PID to rehash the config file, removing
+ the need to use the /rehash command. However, a well running network such as
+ DALnet needs operators to oversee the users of the server, and make sure
+ users actually enjoy their time on IRC without being continually harrased
+ etc by troublematers.
+ O lines give users power over the whole network, to use commands
+ such as /kill, local Operators only have power on their local server, that
+ is, the server where they can use the /oper command to make themselves +o.
+ Abilities of Operators and Local Operators can be defined in your config.h.
+ When a user issues the /oper command to the server, the server will search
+ through all listed O lines for a match of the user's mask, much the same way
+ as I lines. As with I lines, you may specify the use of ident by placing an
+ `@' in the appropriate positions.
+
+ Syntax:
+
+O:hostname:password:nickname::class
+ See I lines for rules about the hostname and using ident.
+ If you use ident, a client matching the hostname must have ident running on
+ their host to be able to +o themselves.
+ If you compiled defining oper passwords to be crypted, you must 1st crypt
+ the plaintext using mkpasswd, a program supplied with the ircd distribution.
+ See src/crypt/README for more information on this.
+ The nickname is the nickname they must pass with the /oper command
+ ie:
+ /oper <nickname> <password>
+ The class is the connection class to be used when the user /oper's using
+ the O line, they connect using the standard I -- Y lines, but when they
+ /oper succusfully they are passed across to the new Y line.
+
+ Examples:
+
+O:RIP.org:waltspass:Walt::10
+ This line will allow anyone on the host RIP.org (running ident or not) to
+ issue the command `/oper Walt waltspass', at which point they will be moved
+ over to class 10 and be made usermode +o.
+
+--------------------
+
+3.6) U Lines: [OPTIONAL]
+
+ These lines define which server(s) on the network your server is connected
+ to will be able to `hack' channel modes.
+ On DALnet, services.dal.net is given this power, this allows the server
+ to change modes on channels without being a channel operator, the
+ commonly used form is ChanServ changing channel modes while not in the
+ channels.
+ If you are connected to a network such as DALnet that requires you to have
+ certain U lines and you don't have them, your server will cause problems
+ to the other servers when the server(s) that require U lines attempt to
+ change channel modes.
+ U lined servers also have the capability to add Akill's to your server,
+ Akill's are much the same as the /kline command except that they show up
+ as A: lines on /stats k.
+
+ Syntax:
+U:servername:*:*
+ The last 2 fields are currently unused so you only need to give the U
+ lined server's name.
+
+ Example:
+U:services.dal.net::
+U:services2.dal.net::
+ Both these lines are required on all DALnet server's, they allow servers
+ with the name's `services.dal.net' and `services2.dal.net' to hack channel
+ modes.
+
+--------------------
+
+3.7) C and N Lines [NETWORKED]
+
+ These lines are always used in pairs, one will not work without the other.
+ C lines define who your server may connect to, while N lines define what
+ servers may connect to you.
+ When two servers connect, they both send eachother the `SERVER' command,
+ this command contains the server name and server info (set by M lines)
+ along with this command is sent a password with the PASS command, C and N
+ lines provide a set of rules governing the connection between servers
+ given the details of the server and pass command's.
+ When one a server initiates the connection, the other server will check
+ the details of the incomming server against its N lines, if a match is
+ found, the server will return the server and pass command's to the
+ initiating server, which will also check its N lines for a match.
+ For a server to initiate a connection, it must have a C line. C lines
+ tell the server where to go to make the connection and what to send for
+ the pass command.
+ What this all means is that for two servers to make a complete connection,
+ they must have both C and N lines to refer to for the other server.
+
+ Syntax:
+C:remote server's hostname/IP:password:remote server's name:port:class
+N:remote server's hostname/IP:password:remote server's name:host mask:class
+ The remote server's hostname/IP should be the location on the internet that
+ the server can be found. IP addresses are prefered as they are more secure,
+ and can be a little quicker for the server. As with I and O lines, ident
+ can be used with this 1st field to specify the username the ircd on the
+ remote server is running from (if the remote server is running ident), to
+ use ident with C/N lines, place the username with an @ before the hostname.
+ The password should be crypted if you compile ircd specifying that link
+ passwords should be crypted. Your link passwords should be very secure, as
+ they provide more power, if hacked, than Operator passwords do. However
+ crypted link passwords can be very akward to keep track of.
+ Your C line password is the password used in the pass command, while your
+ N line password will be used to check against the pass command used by
+ incomming servers. So, your C line password should match the listed
+ server's N line password, and your N line password should match their C
+ line password.
+ If you compile your ircd specifying crypted link passwords, you only need
+ to crypt your N line passwords, use the same method as with O line
+ passwords. If you crypt your C line passwords, your link will not work!
+ Crypted passwords are a one sided affair, because one server crypts its
+ N line passwords does not mean the connecting servers must crypt their
+ C line passwords for that server.
+ For the 3rd field, the remote servers `name' should be used, this name is
+ the one given in that servers M line (see above). This name will be sent
+ with the SERVER command, so it must match the one given. The C and N line
+ pair should have the same name for this field.
+ The 4th field of C lines may contain the remote servers connection port.
+ Even though DALnet runs all its servers with a standard port 7000 open,
+ server -- server connections should be taken place through port 7325. It is
+ not mandatory that you place a port number in this field. If you don't give
+ a port number, the server will not try and autoconnect to the listed
+ server. If you do give a port number, the server will only try and
+ autoconnect to the listed server if there is enough room on the connection
+ class listed at the end of the C line (connection classes are covered in
+ more detail above, under Y lines), and the listed server is not visible
+ (ie: it is not connected to the network). If you don't give a port number,
+ any /connect commands for this C line will use the default port specified
+ in your config.h unless a port is given with the command. If you do put a
+ port number, any /connect command's will use this port unless another port
+ number is given with the command.
+ The 4th field of N lines is called the `host mask', this defined how many
+ parts of your hostname the incomming server will mask to. So, if your
+ server's name is disney.us.dal.net, and you want the connecting server to
+ see you as *.us.dal.net you will give a host mask of 1 in your N line. This
+ field should normally be left blank.
+ The 5th (last) field of both C and N lines gives the connection class to
+ place the connection on. If your C line has a 42 in this field, and your
+ server initiates a connection through this line, the connection will be
+ placed on class 42, however, if You have a 42 in your C line and a 43 in
+ your N line and an incomming server initiates a connection via this N
+ line, the server connection will be placed on class 43.
+
+ Examples:
+C:143.53.233.32:mypass:somewhere.fr.dal.net:7325:35
+N:143.53.233.32:yourpass:somewhere.fr.dal.net::35
+ This set will allow a server named somewhere.fr.dal.net to connect to your
+ server if it has the IP address of 143.53.233.32 and gives a password of
+ `yourpass'. This connection will be governed by connection class 35.
+ If your server recieves the command /connect somewhere.*, it will try and
+ connect to the IP 143.53.233.32 through port 7325 and give the password
+ `mypass'.
+
+C:143.53.233.32:mypass:somewhere.fr.dal.net:7325:35
+N:143.53.233.32:yourpass:somewhere.fr.dal.net::35
+C:ircd@176.43.652.31:apass:elsewhere.jp.dal.net:7235:35
+N:ircd@176.43.652.31:THEpass:elsewhere.jp.dal.net::33
+ Both these set's will work as explained above, but if your Y line defining
+ class 35 has `max links' set to 1, and one of these servers is connected to
+ your server, your server will not try and autoconnect to the other since
+ the Y line is `full', but it will accept any incomming connections from the
+ other server and any /connect commands given for this server. If your Y
+ line allows for more connections but your C lines do not have port numbers,
+ your server will not try and autoconnect.
+ Since the second set in this example has a username, ident will be used to
+ authenticate any connections made to this server. If the listed server does
+ not run ident, or the incomming connection comes from another username, the
+ connection will be rejected.
+ If a connection is made via the second set by your server, the connection
+ will be ruled by connection class 35, if the other server initiates the
+ connection, the connection will use class 33.
+ Autoconnect C/N line pairs can be given prefrence over other pairs by placing
+ them lower in your ircd.conf, the lower the line, the higher the priority
+ when autoconnecting.
+ Connection classes and C/N line set's allow you to refine your autoconnects
+ to a very high degree, with practice you can have your server running so
+ it does not need any help.
+
+--------------------
+
+3.8) K Lines [OPTIONAL]
+
+ These lines restric access to certain users to your server based on
+ user@host matches and time of the day.
+ K lines can come in 3 forms, only one of which you can specify in your
+ ircd.conf, this type will show up as K on /stats k, the other other types
+ are `AutoKill' which will show up as A on /stats k, and `kline' which will
+ show up as k on /stats k. AutoKill's are set by U lined servers (see
+ above), they act in the same way as K lines except that they are set
+ remotly and are usually set on all servers, they dissapear when you
+ /rehash or restart your server. klines are set via the /kline command,
+ they operate more like AutoKill's than K lines because they also dissapear
+ when you /rehash, or restart the server. The /kline command can be used on
+ nicknames that appear on IRC, or you can use a user@host mask. If the
+ /kline is done on an existing nickname, a kline will be set with that users
+ mask and they will be killed off the server.
+
+ Syntax:
+K:hostmask:time/comment:username
+ The hostmask is the host that the user will have on IRC, this may be an
+ IP address or a standard host name. The time/comment field may either
+ contain nothing, a set of times, or a comment. This field should not
+ contain spaces, if you place a comment in the field, you should try and
+ be creative in your avoidance of spaces. The syntax of time specification
+ is:
+ from-to[,from-to[,from-to]]....
+ Again, you should not use spaces in this field, but you may specify as
+ many time periods as you want/need. 24 hour time should be used, AM and PM
+ will not work.
+ You may also specify a filename as a reason. To do so use |kc.reason as the
+ reason. Replace reason with the reason for the ban. Note, all files must be in
+ the format of kc.* to ensure no important configuration files are sent to the
+ user.
+ The username will be the username that shows up on IRC.
+ Wildcards (`*', `?') may be used with K lines in both the hostmask and
+ username fields.
+
+ Examples:
+K:RIP.org::walt
+ This will reject any user who appears as `walt@RIP.org'.
+
+K:*.edu:0800-1200,1300-1700:*
+ This will reject any user from any host with a top level `edu', In other
+ words, anyone appearing as *@*.edu are banned from the server.
+ This ban is only present during the hours of 8AM to 12AM, and again from
+ 1PM to 5PM, at times other than this, the K line will not be active.
+
+K:*.lamer.org:|kc.spamming:*
+ This will reject all users from *.lamer.org and play the file kc.spamming as
+ the reason.
+
+K:*::*rad
+ This K line will reject anyone with the username `rad', or anything ending
+ in `rad'. This ban will dissalow anyone using `rad' running ident or not.
+ You must always take into account the ident character (`~') that is placed
+ infront of usernames when their host is not running ident. If you place a
+ K line on a username `rad' the user will be banned only if they are running
+ ident, but if this user can turn off ident they can appear as ~rad, this
+ will allow them to bypass any ban of username `rad'. So, wildcards should
+ be used with usernames to take into account the ability to turn ident on
+ and off. (The ability to change usernames can only be tackled with a `*'
+ in the username field)
+
+--------------------
+
+3.9) Q Lines (server form) [DISCOURAGED]
+
+ Server form Q lines on DALnet servers are used to dissalow operators on
+ certain servers to use commands such as remote /kill's, and remote
+ /connect's, this will effectivly restrict the operators on the server to
+ local operator priveleges. These lines are usually only used for `test'
+ server situations. If a server isn't officially part of DALnet, they may
+ be temporarily linked and Q lined, this means the server can be tested
+ while not posing a threat to the rest of DALnet. Q lines need only be
+ placed on the hub connecting the `test' server.
+
+ Syntax:
+Q:*:*:servername
+ The 1st 2 fields are currently unused. A Q line placed on a hub connected
+ to the named server will dissalow operators on the server to affect other
+ DALnet users/servers.
+
+ Example:
+Q:::test-server.my.dal.net
+ Q line a server with the name `test-server.my.dal.net'.
+
+--------------------
+
+3.10) Q lines (nickname form) [OPTIONAL]
+
+ Nickname form Q lines have the ability to deny certain nicknames to users.
+ If a nickname is Q lined, the only people allowed to use those nicknames
+ are Operators. Q lines, like most other things in your ircd.conf, are local
+ only, for a nickname to be Q lined on a whole network all servers must have
+ a Q line for that nick. Q lines may also contain comments, these comments
+ are given to the user when they attempt to use the nickname and are asked
+ to choose another.
+
+ Syntax:
+Q:*:reason why nick is quarantined:nickname
+ The 1st field is currently unused. The 2nd field is the comment sent to any
+ user attempting to use the nickname. Unlike K lines, you may use spaces.
+ The last field is the nickname to be quarantined, this nickname may contain
+ wildcards.
+
+ Examples:
+Q::No nicknames on MY server!:*
+ This Q line will dissalow any nicknames on the server giving the reason:
+ No nicknames on MY server!
+ Only Operators will be allowed to use any nicknames, but since you must be
+ a user before you can be +o, you will effectivly ban everyone from your
+ server.
+
+Q::Do not use the Lords name in vain!:God
+ Anyone attempting to use the nickname `God' on your server will be told
+ that they must find a new nickname and will be given the reason:
+ Do not use the Lords name in vain!
+
+ DALnet has a set of standard Q lines that should be in place on all
+ server's. They are as follows:
+
+Q::Reserved for services:*Chan*S*rv*
+Q::Reserved for services:*Nick*S*rv*
+Q::Reserved for services:*Memo*S*rv
+Q::Reserved for services:*Oper*S*rv*
+Q::Reserved for services:*Help*S*rv*
+Q::Reserved for operators:DALnet
+Q::Reserved for operators:IRC*op*
+Q::Causes problems with mIRC:Status
+
+--------------------
+
+3.11) L Lines [OPTIONAL/NETWORKED]
+
+ These lines specify which servers are to behave as leaves, that is,
+ servers that may not have any other servers connected to them.
+ They will only be usefull if your server is a non-leaf (hub) server.
+ Not only can you limit servers to leaves, but you can also specify
+ what tree depth may appear after certain servers. If a server connects
+ but tells your server that it has a larger tree depth behind it than is
+ allowed via your L line for the server, the server will be rejected.
+ A limit of `0' will mean the server may only be a leaf. A limit of `1'
+ will mean that only leaf servers may be connected to the L lined server
+ when it is connected to your server.
+ You may also use L lines to restrict what servers may connect to certain
+ servers while they are connected to your server.
+
+ Syntax:
+L:hostmask of disallowed servers:*:server name:depth
+ The 1st field defines the limitations on servers allowed to connect to
+ the L lined server by hostmask. If any server connects to the L lined
+ server while it is connected to your server, and it's name matches the
+ hostmask given here, it will be rejected. Wildcards are allowed. You do not
+ need to put a value in this field.
+ The 2nd field is currently unused and should be left blank.
+ The 3rd field is the name of the server to be L lined, when this server
+ connects to your server, the restrictions defined by the L line are placed
+ on this server. Wildcards are allowed.
+ The 4th field defines the depth of servers allowed to be connected behind
+ the L lined server.
+
+ Examples:
+L:::leaf.de.dal.net
+ This line will allow a server named `leaf.de.dal.net' to connect only as
+ a leaf. So this server may not connect any other servers behind it.
+
+L:::semi-hub.sg.dal.net:1
+ This line will force the server named `semi-hub.sg.dal.net' to allow only
+ leaf servers to connect behind it. ie: to have a tree depth of 1.
+
+L:*.us.dal.net::*.au.dal.net
+L:*.eu.dal.net::*.au.dal.net
+ These lines will make sure that any server with a name matching
+ *.au.dal.net will not introduce any servers matching *.us.dal.net or
+ *.eu.dal.net. This can be usefull for stopping certain hubs from letting
+ its autoconnects route the network badly.
+
+--------------------
+
+3.12) H Lines [OPTIONAL/NETWORKED]
+
+ These lines are similar to L lines, except that they define what servers
+ may act as a hub while connected to you. That is, which servers may
+ introduce other servers behind them.
+ You may limit what servers may be connected behind the H lined server.
+
+ Syntax:
+H:servers which are allowed behind the hub:*:hub servername
+ The 1st field defines what servernames the H lined server is allowed to
+ introduce. Wildcards are allowed.
+ The 2nd field is currently unused and should be left blank.
+ The 3rd field should be the exact name of the server allowed to be a hub
+ while connected to you. You may not use wildcards with this field unless
+ the server's name includes a `*' (See N lines for host masking).
+
+ Examples:
+H:*::dal-hub.us.dal.net
+ This line will allow the server with the name `dal-hub.us.dal.net' to act
+ as a hub server while you are connected to it, there are no restrictions
+ on the names of the servers it may introduce.
+
+H:*.us.dal.net::usa-hub.us.dal.net
+ This line will allow the server named `usa-hub.us.dal.net' to act as a hub
+ while your server is connected to it, but it is limited to introducing
+ servers with names matching `*.us.dal.net', so any servers trying to
+ connect to `usa-hub.us.dal.net' with a name such as `bad-link.nz.dal.net'
+ will be rejected by your server.
+
+--------------------
+
+3.13) P lines [OPTIONAL]
+
+ These lines will open up ports other than the port you specified in your
+ config.h when you compiled your ircd.
+ Using internet domain ports below 1024 mean that you must run ircd from
+ inetd. ircd can listen to ports in the UNIX domain as well as the internet
+ domain. With UNIX domain ports you must give a unix socket file, you must
+ also compile ircd with UNIXPORT defined in your config.h.
+ You may limit usage of ports in the internet domain to certain hostmasks.
+ You do not need to provide a P line for the default port you defined in
+ your config.h, only extra ports you wish to open. You should compile ircd
+ to run from port 7000, but it is recomended that you add a P line for port
+ 6667 as most IRC clients default to this port when connecting. If you are
+ connected to DALnet, you should have a P line for port 7325, this is the
+ standard server connection port for all DALnet servers.
+
+ Syntax:
+P:hostmask or UNIX socket file:*:*:port number
+ The 1st field should either specify a path to a UNIX socket file, or give
+ a hostmask to match against connecting clients on this port. Clients not
+ matching this mask will be rejected.
+ The 2nd and 3rd field's are currently unused, and should be left blank.
+ The last field is the port number to open up and listen to for connections.
+
+ Examples:
+P:*:::7325
+ This will open up the DALnet server connection port and wait for
+ connections. This line is mandatory if you run a server connected to DALnet
+
+P:*.net:::6665
+ This line will open up port 6665 and wait for connections, connections from
+ hosts not matching `*.net' will be rejected.
+
+P:/tmp/.ircd:*:*:6666
+ This line will open up the port 6666 in the UNIX domain, with a socket file
+ of: /tmp/.ircd.
+
+--------------------
+
+3.14) T lines [OPTIONAL]
+
+ These lines allow you to have multiple MOTD and RULES files in the same IRCd.
+ The idea of this is to allow you to have MOTD and RULES files in different
+ languages for your users all over the world. The way this works is you can
+ match a MOTD and RULES file to a certain part of a users host. For example
+ *.fr (France) now you can make it so all *.fr users see a French MOTD and
+ RULES where as everyone else still sees the default.
+
+ Syntax:
+T:hostmask:motd file:rules file
+ The first field is where you specify the hostmask to match. This should be a
+ TLD (Top Level Domain) but doesn't have to be. The second is the location of
+ the MOTD file to display, this should be relative to DPATH. The last field is
+ the path to the RULES file, again this should also be relative to DPATH. The
+ best way to keep your T:lines MOTD/RULES files in order is to make a motds/ and
+ rules/ then make files such as spanish.motd and spanish.rules etc.
+
+ Examples:
+T:bngr216-37-173ppp107.epix.net:motds/epix.motd:rules/epix.rules
+ This T:line uses a matches a specific host. When a user with the host bngr216-
+ 37-173ppp107.epix.net requests a /MOTD they will see the file motds/epix.motd
+ and when they request a /RULES they will see the file rules/epix.rules.
+
+T:*.epix.net:motds/epix.motd:rules/epix.rules
+ This T:line matches based on ISP. When a user from *.epix.net requests a /MOTD
+ or /RULES the specified files are played.
+
+T:*.dk:motds/danish.motd:rules/danish.rules
+ This T:line matches based on TLD. This is probably the most efficient method to
+ use. When a user from the .dk TLD requests a /MOTD the Danish MOTD is played
+ when they request a /RULES the Danish RULES file is played.
+
+--------------------
+
+3.15) E Lines [OPTIONAL]
+
+ These lines allow you to exclude certain people from a K:line, or to prevent
+ certain people from receiving a K:line. E:lines can be used with a more strict
+ host than a K:line so for example if you K:line *.net and then E:line
+ splitrock.net only users from splitrock.net may connect. These lines are also
+ often used to prevent the server's staff from being K:lined from that server.
+
+ Syntax:
+E:hostmask:reason:ident
+ The first field is where you enter the hostmask that the E:line will apply to.
+ The reason parameter allows you to specify why that hostmask is E:lined. The
+ third field is optional. To E:line all idents just specify this field as an *.
+
+ Examples:
+E:*.epix.net:Admin's ISP:*
+ This E:line affects all *.epix.net users with reason 'Admin's ISP'. The * in
+ the ident field says that it applies to all *.epix.net users.
+
+E:*.epix.net:Server Admin:n64master
+ This E:line affects any *.epix.net user using the n64master ident, with reason 'Server Admin'. This is probably the best way to go if you are making the E:line
+ to protect server staff.
+
+--------------------
+
+3.16) e Lines [OPTIONAL]
+
+ These lines allow you to specify which hosts will not be scaned by the proxy
+ scanner. This will allow you to make certain proxys to connect while the rest
+ are still killed. Note, if you want to allow all proxys, don't e:line *, just
+ disable it at compile time.
+
+ Syntax:
+e:IP address:*:*
+ This line requires only one field, the first field is the IP address of the
+ host to be e lined. Make sure you use an IP and not a hostname or this will not
+ work.
+
+ Examples:
+e:234.45.32.1:*:*
+ This will prevent any user who's host resolves to 234.45.32.1 from being
+ scanned for an open wingate/proxy by the proxy scanner when they connect.
+
+--------------------
+
+3.17) Summary:
+
+ Well, thats it for the lines you may use in your ircd.conf. Remember that
+ ircd.conf is an art, just like any other type of programming. Some parts
+ are particularly easy, but other's, like Y lines, can take a while to get
+ used to. Given a little time experementing with lines on a network of
+ servers, you will become well versed in ircd.conf programming.
+
+Good luck!
+
+--------------------
+
+4) dccdeny.conf:
+
+ The dccdeny.conf allows you to specify files which may not be sent through the
+ use of DCC (Direct Client Connection). This is mainly to keep the speading of
+ virii at a minimum on your network. It is strongly suggested that you set up a
+ dccdeny.conf as it will help you provide a safe enviromnet for your users.
+
+4.1) deny Lines:
+
+ As with the ircd.conf, dccdeny.conf supports comments in the form of # comment.
+ It is suggested that you place comments above each dccdeny for easy reference.
+
+ Syntax:
+deny filename reason
+ The first field is required to be deny, this tells the server that this line
+ specifies a file which should be denied. The second field is where you specify
+ what file should be denied. The last field is where you specify a reason. It is
+ recommended you place a web address such as http://www.nohack.net in the reason
+ so if the user is infected with a virus, they can learn how to remove it.
+
+deny dmsetup.exe You may be infected with DMSetup, visit http://www.nohack.net
+ This line will deny users to send the file dmsetup.exe. If they attempt to
+ send this file the server will display the reason which is 'You may be infected
+ with DMSetup, visit http://www.nohack.net.
+
+deny *.jpg.bat You may be infected with a virus, visit http://www.nohack.net
+ This line will deny sends matching *.jpg.bat and display the reason 'You may be infected with a virus, visit http://www.nohack.net' when a send is attempted.
+
+--------------------
+
+5) chrestrict.conf:
+
+ The chrestrict.conf allows you to limit what channels users may join. This is
+ strongly discouraged for most networks. This is just provided for the networks
+ that wish to have one open channel on a specific topic.
+
+--------------------
+
+5.1) msg Lines:
+
+ The msg line allows you to specify a message that will be played when a user
+ attempts to join a channel that is not allowed.
+
+ Syntax:
+msg message
+ The first field tells the server that this is a message line. The second field
+ is where you specify the message that will be displayed when a user attempts to
+ join a denied channel.
+
+ Examples:
+msg Sorry, the channel you attempted to join is not allowed on this network
+ This line will display 'Sorry, the channel you attempted to join is not allowed
+ on this network' when a user trys to enter a channel that is denied.
+
+--------------------
+
+5.2) allow Lines:
+
+ The allow lines say which channels users are allowed to join. Any channel not
+ in an allow line will be denied to the user.
+
+ Syntax:
+allow channel
+ The first field tells the server this is an allow line. The second is where you
+ specify the channel which users are allowed to join.
+
+ Examples:
+allow #help
+ This line will allow users to join #help and deny them from joining all other
+ channels.
+
+--------------------
+
+6) vhost.conf:
+
+ The vhost.conf file allows you to integrate a BNC type program into your ircd.
+ This command works through use of the SETHOST command. You must be set +x in
+ order for you to be able to keep your vhost, setting -x will return you to your
+ normal host.
+
+6.1) vhost Lines:
+
+ vhost lines are the lines that allow you to create specific vhosts for certain
+ users. These lines are used along with the /VHOST login password command.
+
+ Syntax:
+vhost virtualhost username password hostmask
+ The first field tells the server this is a vhost command. The second field is
+ where you specify what the users host will be changed to once they use the
+ /VHOST command. The third field is the username field and forth is password, a
+ user must use the correct username and password in order to use the vhost. The
+ last field is the hostmask. This allows you to specify which users can use that
+ vhost based on host, to allow all users use *@*.
+
+ Examples:
+vhost i.work.at.the.foobar.net john21 asdf1234 *@*
+ This line will grant the user the hostname i.work.at.the.foobar.net, if they
+ supply the username john21 and the password asdf1234. This line allows any
+ hostmask to use the line since it has *@*.
+
+vhost i.am.a.lamer.org codemastr jnh32 n64master@*.epix.net
+ This line will give the user the hostname i.am.a.lamer.org, if they supply the
+ username codemastr and the password jnh32, but only if they match the hostmask
+ n64master@*.epix.net.
+
+--------------------
+
+7) unrealircd.conf
+
+ The unrealircd.conf allows you to change certain settings in your IRCd that
+ used to be set at compile time. This feature is especially beneficial to
+ Windows users since they use a precompiled version. The unrealircd.conf works
+ along with your network file (explained in section 8) to provide a completely
+ customized IRCd.
+
+--------------------
+
+7.1) Include Line:
+
+ The include line allows you to tell the unrealircd.conf where your network file
+ is located. This path must be relative to DPATH in order for your IRCd to work.
+
+ Syntax:
+Include .................: filename
+ This line will say that the network file is located in the field filename,
+ again the path to the file must be relative to DPATH.
+
+ Examples:
+Include .................: networks/roxnet.network
+ This line says that you will be using the roxnet.network file, which is located
+ in the networks directory. The networks/yourfile.network is most likely the
+ format you will use if you keep the standard DPATH.
+
+Include .................: roxnet.network
+ This line says you will use the file roxnet.network which is located in the
+ same directory as DPATH. This is valid although it is not the default.
+
+--------------------
+
+7.2) Set KLINE_ADDRESS Line:
+
+ This line allows you to tell the IRCd what email should be displayed to a user
+ when they are klined. It is strongly encouraged that you set this to a valid
+ email address of someone on the server staff.
+
+ Syntax:
+Set KLINE_ADDRESS .......: emailaddress
+ This line tells the server that the K:Line email address is located in the
+ field emailaddress. Note, the emailaddress is not checked to see if it is valid
+ so it is up to you to set it right.
+
+ Examples:
+Set KLINE_ADDRESS .......: bob@myserver.net
+ This tells the server that the K:Line email address is bob@myserver.net and
+ when a user gets klined this will be the email address shown to them.
+
+--------------------
+
+7.3) Set MODE_X Line:
+
+ This line lets you tell the server whether or not to set a user +x when they
+ connect to the server. Set it to 1 for yes, or 0 for no. It is encouraged that
+ you set this to 1 as it will help prevent users against nukes and other
+ malicious attacks.
+
+ Syntax:
+Set MODE_X ..............: 1/0
+ If this line is set to 1 then the server will set users +x when they connect to
+ the server. If it is set to 0 they will not be set +x on connect.
+
+ Examples:
+Set MODE_X ..............: 1
+ This line has auto +x on connect enabled, this is the recommended setting for
+ security purposes.
+
+Set MODE_X ..............: 0
+ This line has auto +x disabled. This is discouraged, but it is not required
+ that auto +x be enabled.
+
+--------------------
+
+7.4) Set MODE_I Line:
+
+ This line lets you tell the server whether or not to set a user +i when they
+ connect to the server. Set it to 1 for yes, or 0 for no. It is encouraged that
+ you set this to 1 as it will help prevent users from getting unwanted messages
+ from users.
+
+ Syntax:
+Set MODE_I ..............: 1/0
+ If this line is set to 1 then the server will set users +i when they connect to
+ the server. If it is set to 0 they will not be set +i on connect.
+
+ Examples:
+Set MODE_I ..............: 1
+ This line has auto +i on connect enabled, this is the recommended setting for
+ security purposes.
+
+Set MODE_I ..............: 0
+ This line has auto +i disabled. This is discouraged, but it is not required
+ that auto +i be enabled.
+
+--------------------
+
+7.5) Set TRUEHUB Line:
+
+ The Set TRUEHUB line allows you to tell the server the server you are a Hub and
+ not a HalfHub. For most networks it is recommended that you set this to 1 to
+ enable your server as a Hub. Note, if you compiled your server as a leaf and
+ set this to 1 it will give an error. Only set this to 1 if you compiled your
+ server as a hub.
+
+ Syntax:
+Set TRUEHUB .............: 1/0
+ If this line is set to 1 then TRUEHUB is enabled. If it is set to 0 it is
+ disabled. Again it is recommended for most networks that this is set to 1, and
+ may only be used if you compiled as a Hub.
+
+ Examples:
+Set TRUEHUB .............: 1
+ This line has TRUEHUB enabled, the server will send a GLOBOPS when it links.
+
+Set TRUEHUB .............: 0
+ This line has TRUEHUB disabled. The server will not send a GLOBOPS when it
+ links, and it will link as a half hub.
+
+--------------------
+
+7.6) Set CONFIG_FILE_STOP Line:
+
+ The Set CONFIG_FILE_STOP line must be set to 0 in order for your IRCd to work.
+ If this is set to 1 your IRCd will give an error and won't start. This line is
+ there just to makesure you take the time to read over your unrealircd.conf and
+ configure it correctly.
+
+ Syntax:
+Set CONFIG_FILE_STOP ....: 1/0
+ If this line is set to 1 then your IRCd will not start and will give you an
+ error. It must be set to 0 in order to work. If set to 0 your IRCd will load
+ normally.
+
+ Examples:
+Set CONFIG_FILE_STOP ....: 1
+ In this line, the IRCd will die and give an error when it attempts to load the
+ unrealircd.conf.
+
+Set CONFIG_FILE_STOP ....: 0
+ This line will allow the IRCd to load and run fine without giving any errors.
+
+--------------------
+
+7.7) Set SHOWOPERS line:
+
+ This line sets whether non opers will be allowed to user /stats O to see a list
+ of IRCOps on the server. This line may be set to whatever you want, although it
+ is recommended you set this to 0 you may set it to 1.
+
+ Syntax:
+Set SHOWOPERS ...........: 1/0
+ If this line is set to 1, then all users will be able to see a list of O:lines,
+ note a non oper will not see the host allowed by this line for security
+ reasons. If this line is set to 0 then only opers may request a /stats O.
+
+ Examples:
+Set SHOWOPERS ...........: 1
+ This line allows all users to view a list of all the opers on a server. Again
+ they will not be able to see the O:lines hosts or flags for security reasons.
+
+Set SHOWOPERS ...........: 0
+ This line only allows opers to request a /stats O, if a user requests it, it
+ will return no information.
+
+--------------------
+
+7.8) Set KILLDIFF Line:
+
+ This line allows you to set whether the new /kill format should be used. Then
+ new format includes the server from which the /kill came from, the old format
+ does not.
+
+ Syntax:
+Set KILLDIFF ............: 1/0
+ If this line is set to 1 the new format will be used. If it is set to 0 then
+ the standard format will be used. Note, if you set this to 1 then some users
+ scripts may not function correctly, so if you want backwards compatibility set
+ this to 0.
+
+ Examples:
+Set KILLDIFF ............: 1
+ This line will make the server use the new /kill format, and the server name
+ will be displayed.
+
+Set KILLDIFF ............: 0
+ This line will disable the new /kill format and the standard format will be
+ displayed to the user. This is recommended for backwards compatibility.
+
+--------------------
+
+7.9) Set SHOWOPERMOTD Line:
+
+ This line allows you to set whether or not the OperMOTD will be displayed to a
+ user when they /oper. This is completely up to you as to what it shoul be set
+ to, although it is recommended that if you do not have an OperMOTD you set this
+ to 0 to avoid the error message from being displayed.
+
+ Syntax:
+Set SHOWOPERMOTD ........: 1/0
+ If this line is set to 1 then the OperMOTD is displayed when the user /oper's.
+ If it is set to 0 then the user must /OperMOTD to see the OperMOTD.
+
+Set SHOWOPERMOTD ........: 1
+ This line will make the server display the OperMOTD to the user when the /oper
+ up.
+
+Set SHOWOPERMOTD ........: 0
+ This line will not make the server display the OperMOTD, and instead make the
+ user have to type /OperMOTD to view the OperMOTD.
+
+--------------------
+
+7.10) Set HIDE_ULINES Line:
+
+ This line allows you to hide U:lined servers from non-opers in /links. This can
+ help in adding security, since a user can not DoS services uplink to disconnect
+ the services, but can also be a disadvantage if you have servers with a lot of
+ hops to services, since a user can not get closer to the services server.
+
+ Syntax:
+Set HIDE_ULINES .........: 1/0
+ If this line is set to 1, then non-opers can not see U:lines in /links, if it
+ is set to 0 non-opers can see U:lines in /links.
+
+ Examples:
+Set HIDE_ULINES .........: 1
+ This line makes it so only opers can see U:lined servers in /links.
+
+Set HIDE_ULINES .........: 0
+ This line makes it so anyone can see U:lined servers in /links.
+
+--------------------
+
+8) network files:
+
+ The networks files allow you to specify some information specific about your
+ network you may use a current network file, or you can create your own. To
+ create your own network file edit the template.network file to suit your needs,
+ then add that file to your unrealircd.conf (See section 7.1). To use an
+ existing network file just add the file to your unrealircd.conf (See section
+ 7.1).
+
+--------------------
+
+8.1) Network line:
+
+ The Network line tells the server what the name of your IRC network is. You can
+ set this line to anything you want, although it may not be left empty.
+
+ Syntax:
+Network >..........: yournetwork
+ This line tells the server that your networks name is located in the field
+ yournetwork. Note, yournetwork should be the same on all servers to let users
+ know what network they are on.
+
+ Examples:
+Network >..........: NeoHorizon
+ This tells the server that your network is called NeoHorizon and will display
+ this to the user when it is requested.
+
+--------------------
+
+8.2) Set ircnetwork Line:
+
+ This line does the same thing as the Network line, but it is required that Set
+ ircnetwork be the exact same as the Network line or your IRCd will not work. So
+ if your Network line has Bunker7 then your Set ircnetwork line must also have
+ Bunker7.
+
+ Syntax:
+Set ircnetwork ....: yournetwork
+ This tells the server that your network's name is found in the file called
+ yournetwork.
+
+ Examples:
+Set ircnetwork ....: Bunker7
+ This defines your IRC networks name as Bunker7, again if this was your line you
+ must also have Bunker7 in your Network line.
+
+--------------------
+
+8.3) Set defserver Line:
+
+ This line defines the server that the IRCd will tell users to go to when the
+ IRCd is full. It is recommended that you point this to a random server pool if
+ one is available.
+
+ Syntax:
+Set defserver .......: servername
+ This tells the server to tell the user to go to the contents of the field names
+ servername with the server is full.
+
+ Examples:
+Set defserver .......: irc.dragonwings.org
+ This will display the server irc.dragonwings.org in the server is full message
+ when a user attempts to connect to a full server.
+
+--------------------
+
+8.4) Set SERVICES_NAME Line:
+
+ This line is very important. It must be set correctly for commands such as
+ /nickserv, /chanserv, /memoserv, /operserv, etc. to work. If this is not set
+ correctly you must use /msg servicesname to use services.
+
+ Syntax:
+Set SERVICES_NAME .: servicesserver
+ This line tells the IRCd to redirect /nickserv, /chanserv etc to servicesserver
+ and find the correct client.
+
+ Examples:
+Set SERVICES_NAME .: services.realchat.org
+ This tells the server to redirect the services commands to
+ services.realchat.org.
+
+--------------------
+
+8.5) Set oper_host Line:
+
+ This allows you to specify a host that Global IRCOps will receive when they
+ /oper, this only works if iNAH (See section 8.17) is enabled. If this is left
+ blank it can cause some problems in your IRCd so it is recommended that you
+ fill in a value.
+
+ Syntax:
+Set oper_host .....: operhost
+ This tells the server to switch the host of the user to operhost when they
+ /oper.
+
+ Examples:
+Set oper_host .....: opers.nevernet.net
+ This will make a Global Oper's host change to opers.nevernet.net when they
+ /oper up if iNAH is enabled.
+
+--------------------
+
+8.6) Set admin_host Line:
+
+ This allows you to specify a host that Admins will receive when they
+ /oper, this only works if iNAH (See section 8.17) is enabled. If this is left
+ blank it can cause some problems in your IRCd so it is recommended that you
+ fill in a value.
+
+ Syntax:
+Set admin_host ....: adminhost
+ This tells the server to switch the host of the admin to adminhost when they
+ /oper.
+
+ Examples:
+Set admin_host ....: admins.nevernet.net
+ This will make a Admin's host change to admins.nevernet.net when they /oper up
+ if iNAH is enabled.
+
+--------------------
+
+8.7) Set locop_host Line:
+
+ This allows you to specify a host that Local IRCOps will receive when they
+ /oper, this only works if iNAH (See section 8.17) is enabled. If this is left
+ blank it can cause some problems in your IRCd so it is recommended that you
+ fill in a value.
+
+ Syntax:
+Set locop_host ....: locophost
+ This tells the server to switch the host of the Local Oper to locophost when
+ they /oper.
+
+ Examples:
+Set locop_host ....: locop.nhn.net
+ This will make a Local Oper's host change to locop.nhn.net when they /oper up
+ if iNAH is enabled.
+
+--------------------
+
+8.8) Set sadmin_host Line:
+
+ This allows you to specify a host that Services Admins will receive when they
+ /oper, this only works if iNAH (See section 8.17) is enabled. If this is left
+ blank it can cause some problems in your IRCd so it is recommended that you
+ fill in a value.
+
+ Syntax:
+Set sadmin_host ...: sadminhost
+ This tells the server to switch the host of the Services Admin to sadminhost
+ when they /oper.
+
+ Examples:
+Set sadmin_host ...: sops.spynet.org
+ This will make a Services Admin's host change to sops.spynet.org when they
+ /oper up if iNAH is enabled.
+
+--------------------
+
+8.9) Set netadmin_host Line:
+
+ This allows you to specify a host that NetAdmins will receive when they
+ /oper, this only works if iNAH (See section 8.17) is enabled. If this is left
+ blank it can cause some problems in your IRCd so it is recommended that you
+ fill in a value.
+
+ Syntax:
+Set netadmin_host .: netadminhost
+ This tells the server to switch the host of the NetAdmin to netadminhost when
+ they /oper.
+
+ Examples:
+Set netadmin_host .: netadmin.spynet.org
+ This will make a NetAdmin's host change to netadmin.spynet.org when they /oper
+ up if iNAH is enabled.
+
+--------------------
+
+8.10) Set coadmin_host Line:
+
+ This allows you to specify a host that CoAdmins will receive when they
+ /oper, this only works if iNAH (See section 8.17) is enabled. If this is left
+ blank it can cause some problems in your IRCd so it is recommended that you
+ fill in a value.
+
+ Syntax:
+Set coadmin_host ..: coadminhost
+ This tells the server to switch the host of the CoAdmin to coadminhost when
+ they /oper.
+
+ Examples:
+Set coadmin_host ..: coadmin.starspace.net
+ This will make a CoAdmin's host change to coadmin.starspace.net when they /oper
+ up if iNAH is enabled.
+
+--------------------
+
+8.11) Set techadmin_host Line:
+
+ This allows you to specify a host that TechAdmins will receive when they
+ /oper, this only works if iNAH (See section 8.17) is enabled. If this is left
+ blank it can cause some problems in your IRCd so it is recommended that you
+ fill in a value.
+
+ Syntax:
+Set techadmin_host : techadminhost
+ This tells the server to switch the host of the TechAdmin to techadminhost when
+ they /oper.
+
+ Examples:
+Set techadmin_host : techadmin.starspace.net
+ This will make a TechAdmin's host change to techadmin.starspace.net when they
+ /oper up if iNAH is enabled.
+
+--------------------
+
+8.12) Set hidden_host Line:
+
+ The Set hidden_host line allows you to specify what the masked part of a users
+ host will look like when they set +x. Most networks tend to use a part of their
+ network's name, for example MegaIRC uses mega for their hidden host. Note, if
+ you leave this blank it may cause some problems in your IRCd.
+
+ Syntax:
+Set hidden_host ...: hiddenhost
+ This tells the server to use the contents of hiddenhost as the masked part of a
+ users host when they set +x.
+
+ Examples:
+Set hidden_host ...: neo
+ This will use the word neo as the masked part of a users host.
+
+--------------------
+
+8.13) Set netdomain Line:
+
+ This is used to specify the domain name of your IRC network. It is used to give
+ the user your www address and ftp address in the /info reply. If you leave this
+ blank, users may find difficulty getting help with a specific topic.
+
+ Syntax:
+Set netdomain .....: networkdomain
+ This tells the server to use the field networkdomain for your networks domain.
+
+ Examples:
+Set netdomain .....: Infinity-IRC.org
+ This will make the server set your domain as Infinity-IRC.org, and display the
+ www and ftp as www.Infinity-IRC.org and ftp.Infinity-IRC.org in the /info
+ reply.
+
+--------------------
+
+8.14) Set helpchan Line:
+
+ This line specifies a channel which the user can go to for help, this is also
+ used as a reply in the /info command. Again, leaving this blank may cause users
+ to have problems when seeking help.
+
+ Syntax:
+Set helpchan ......: channel
+ This will make the server use the field channel as your Official Help Channel
+ in the /info reply.
+
+ Examples:
+Set helpchan ......: #help
+ This will tell the user that the server's help channel is #help when they
+ request a /info.
+
+--------------------
+
+8.15) Set STATS_SERVER Line:
+
+ This line is used to tell the IRCd where your StatServ is located for use in
+ the /StatServ command.
+
+ Syntax:
+Set STATS_SERVER ..: statserver
+ This tells the server to send all /StatServ's to the field statserver.
+
+ Examples:
+Set STATS_SERVER ..: stats.tspre.org
+ This tells the server to forward all /StatServ commands to stats.tspre.org.
+
+--------------------
+
+8.16) Set HUB Line:
+
+ This line is obsolete and no longer in use. It is provided only for backwards
+ compatibility.
+
+--------------------
+
+8.17) Set iNAH Line:
+
+ This line allows you to specify whether or not oper's hosts should be changed
+ when they send a /oper command. Most networks set this on, but there are some
+ that do not like the host masking feature.
+
+ Syntax:
+Set iNAH ..........: 1/0
+ Set this line to 1 to enable the oper host masking, or set it to 0 to disable
+ the host masking.
+
+ Examples:
+Set iNAH ..........: 1
+ This line tells the server to mask an oper's host when they issue a /oper
+ command.
+
+Set iNAH ..........: 0
+ This tells the server not to mask an oper's host when they send a /oper
+ command.
+
+--------------------
+
+8.18) Set net_quit Line:
+
+ This line is no longer in use and is only provided for compatibility with older
+ versions of Unreal.
+
+--------------------
+
+[ $Id$ ]
--- /dev/null
+#
+# IRC - Internet Relay Chat, doc/example.conf
+# Copyright (C) 1994, Helen Rose
+# $Id$
+#
+# 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# This is an example configuration file for the Unreal3.0-Morrican
+# and higher IRC servers.
+#
+# You only need an ircd.conf (IRC server configuration file) if you are
+# running an IRC server. If you are running a standalone client this file
+# is not necessary.
+#
+# This file will explain the various lines in the IRC server
+# configuration file. Not all lines are mandatory. You can check to make
+# sure that your configuration file is correct by using the program
+# "chkconf", provided in the server distribution (and when you do "make
+# install" this program will be installed in the same directory as the irc
+# server).
+#
+# This document modified for use by with the Unreal3.0 IRCD
+#
+#
+# The options for whether a line is needed or not are:
+# MANDATORY: you absolutely MUST have this line
+# NETWORKED: you must have this line if you are connecting this irc
+# server to any other server (servers can run standalone).
+# SUGGESTED: it is highly suggested that you use this line
+# OPTIONAL: it's completely up to you whether to define this or not
+# DISCOURAGED: you really really should not use this line if at all
+# possible.
+# OBSOLETE: an old or out of date line that isn't needed.
+#
+# MANDATORY lines are absolute *musts*, that is, if you do not have this
+# line then your server will not work properly. SUGGESTED lines are
+# close-to-mandatory (that is, the server will run without it, but you are
+# highly encouraged to use these lines).
+#
+# Note that "*" in a field indicates an "unused" field.
+#
+#
+# ========================================================================
+# NOTE! this entire configuration file is read UPSIDE-DOWN! So if you have
+# to put something in a specific order (for example, client-connection
+# lines), put them in reverse order!
+# ========================================================================
+#
+#
+# M: [MANDATORY]. This line sets your server's name, description, port
+# number, and IP address to bind to. Fields, in order, are:
+#
+# If you are compiling this server for use on dalnet, port number 7000
+# as the default is recommended. If you leave IP address field blank or
+# *, it defaults to binding all local IP addresses on the machine.
+#
+# M:hostname:IP:Description Of Your Server:7000
+#
+M:server.my.net:*:My IRC Server:7000
+#
+# A: [MANDATORY]. This line lists your administrative information
+# (contact address, etc). To view this information, /admin (server) will
+# show it to you.
+#
+# The A: line has no set information, in fact, you can put arbitrary text
+# in there if you wish (it is encouraged that you put at *least* a contact
+# address for a person responsible for the irc server, however)
+#
+A:Generic Internet Access:Admin John Doe:jdoe@generic.com
+#
+# Y: [SUGGESTED]. These lines define connection classes. Connection
+# classes allow you to fine-tune your client and server connections. It is
+# suggested that clients and servers be placed in seperate classes, and if
+# you have lots of server connections (if you do have lots of servers you
+# shouldn't be reading this file :-) each set of servers (defined
+# arbitrarily by you) should have its own class. If you have clients
+# coming in from lots of different sites, you may want to seperate them
+# out into classes. For instance, you may want to put local users in one
+# class, with remote users in another class.
+#
+# The class numbers are not arbitrary. In auto-connecting servers -- that
+# is, servers that you have a port number (e.g. 6667) on the end of the C:
+# line (see below) the higher the number the higher the priority in
+# auto-connecting.
+#
+# The fields in order are: class number, ping frequency (in seconds),
+# connect frequency (in seconds), maximum number of links (used for
+# auto-connecting, and for limiting the number of clients in that class),
+# and sendq (this overrides any value set in include/config.h for #define
+# MAXSENDQLENGTH).
+#
+# Note that it is a good idea to have ping frequency the same at both ends
+# of the link.
+#
+# in this case, connect-frequency is 0 indicating that this is a client
+# class (servers never connect to clients, it is the other way around).
+Y:1:90:0:20:100000
+#
+# These are the recommended server Y:lines for connecting to dalnet.
+# In addition to these you should have at *least* one client class, and one
+# oper class (see O:lines). By convention on dalnet, these are usually
+# numbered from 5 to 10.
+#
+# Class 50 - Hub to hub, autoconnect
+Y:50:90:60:1:4000000
+#
+# Class 51 - Hub to hub, no autoconnect
+Y:51:90:60:0:4000000
+#
+# Class 30 - Hub to US leaf
+Y:30:90:0:0:3500000
+#
+# Class 32 - Hub to EU leaf
+Y:32:180:0:0:3500000
+#
+# Class 34 - Hub to AU leaf
+Y:34:300:0:0:3500000
+#
+# Class 40 - US leaf to hub, autoconnect
+Y:40:90:90:1:3500000
+#
+# Class 41 - US leaf to hub, no autoconnect
+Y:41:90:90:0:3500000
+#
+# Class 42 - EU leaf hub
+Y:42:180:90:1:3500000
+#
+# Class 44 - AU leaf to hub
+Y:44:300:120:1:3500000
+#
+# I: [MANDATORY]. The I: lines are client-authorization lines. Without
+# these lines, no clients will be able to connect to your server.
+# Wildcards ("*") are permitted. Passwords are also permitted (clients can
+# be configured to send passwords).
+#
+# Ident (for more information on this, see rfc1413) can also be used by
+# placing a @ in the appropriate fields.
+#
+# Fields are as follows:
+# I:IP-address-mask:optional password:domain-mask::connection class (opt)
+#
+# With a password..... This will allow anyone from anywhere to connect
+# as long as they know the password ("foobar"). Note listing this I: line
+# first, it will be read *last*, meaning it is the "fall-through". That
+# is, anyone who doesn't match the I: lines listed below must know the
+# password ("foobar") to connect.
+#
+I:*@*:foobar:*@*::1
+# This is a standard vanilla I: line which will permit anyone with an IP
+# address starting with 205.133 OR with a hostname ending in
+# .toledolink.com to connect to the server. NOTE, the ircd matches on the
+# *right-most* match, so if I connect as rmiller@glass.toledolink.com
+# (which is rmiller@205.133.127.8) I will show up on irc as
+# rmiller@glass.toledolink.com since that is the first match it found.
+# (Even though the second match is valid).
+I:205.133.*::*.toledolink.com::1
+#
+# using ident
+I:*@205.133.*::*@*.toledolink.com::1
+# and you can even specify just certain usernames running ident (as long
+# as the client's site is running the ident daemon):
+I:NOMATCH::rmiller@glass.toledolink.com::1
+# putting NOMATCH in the first field will stop the ircd from matching
+# automatically against the IP address and it will force the server to
+# match against the hostname. (the "NOMATCH" string is not mandatory, you
+# can use any arbitrary text in the first field).
+I:*@*:ONE:*@*::1
+# putting the ONE in the password field makes it so that only 1 user matching
+# that host or IP can connect through that I:line.
+#
+#
+# O: [OPTIONAL]. These lines define operator access. You do not need to
+# have an operator to run a server. A well configured leaf site should not
+# need an operator online, if it's connections are well defined, the irc
+# administrator can use kill -HUP on the ircd to reload the configuration
+# file.
+# The fields are as follows:
+# O:hostname (ident "@" permitted):password:NickName:AccessFlags:class
+# if the person in "NickName" is not coming from the hostname defined in
+# the first field then the person will get the error message "No O: lines
+# for your host".
+# NOTE that since Crypted Passwords are defined by default in
+# include/config.h this text probably will not be plaintext. See
+# ircd/crypt/README for more information.
+#
+# class is the Y:Line class you want this operator to end up in after they
+# have successfully /oper'd.
+#
+# Access flags may be left blank, or * to give full access rights. Flags
+# are in the form of single characters making a string. Any combination
+# of the following can be used(these are cAsE sensitive characters):
+#
+# r = access to /rehash server
+# R = access to /restart server
+# D = access to /die server
+# h = oper can send /help ops
+# g = oper can send /globops
+# w = oper can send /wallops
+# l = oper can send /locops
+# c = access to do local /squits and /connects
+# L = access to do remote /squits and /connects
+# k = access to do local /kills
+# K = access to do global /kills
+# b = oper can /kline users from server
+# B = oper can /unkline users from server
+# n = oper can send local server notices(/notice $servername message)
+# G = oper can send global server notices(/notce $*.my.net message)
+# S = oper can join unlimited amount of channels
+# A = admin
+# u = oper can set /umode +c
+# f = oper can set /umode +f
+# ^ = oper can set /umode +I
+# e = oper can set /umode +e
+# W = oper can set /umode +W
+# H = oper gets auto +x on /oper
+# o = local oper, flags included: rhgwlckbBnuf
+# O = global oper, flags included: oRDCK
+# a = services admin, access to /samode
+# C = co admin
+# T = tech admin
+# A = admin
+# N = network admin access to remote /rehash and remote /restart and a bunch more
+# * = flags included: AaNCTzSHW^
+
+#
+# This is a plain vanilla O:line:
+O:*.toledolink.com:nopassword:Russell:*:10
+#
+# and this line forces ident:
+O:rmiller@glass.toledolink.com:nopassword:Russell::10
+#
+# This line is a generic "local operator", because of the flags, the only
+# thing that really makes them global operators, is if they have the flags
+# CKN set in their access flags.
+#
+# this line permits the nickname "jhs" with the password of "ITBites" to
+# be a local operator only (be able to issue commands locally -- can /kill
+# and /squit and /connect -- but *only* locally)
+#
+O:*.something.net:ITBites:jhs:o:10
+#
+# a crypted password line (NOTE that if you have crypted passwords, *all*
+# of you passwords must be crypted! In fact, if you are getting an error
+# "Incorrect Password" it may well be because crypted passwords are
+# defined and you have used plaintext. So my example of plaintext and
+# crypted strings in the same IRC server configuration file is an
+# impossibility (but it is just theoretical, which is why I explained both).
+#
+O:rmiller@*.toledolink.com:T0eiVgHrqeKTQ:Russell::10
+#
+# U: [OPTIONAL]. This line defines the servers that IRC recognizes as being
+# allowed to make various changes to the IRC environment (mode changes, for
+# example), without complaining or otherwise obstructing them. For example,
+# DALnet requires the following line:
+U:services.my.net:*:*
+#
+# X: [ENCOURAGED]. This line defines the password that an operator must use
+# to restart or die the server. Note that they still myst have they R and D
+# flags. This is just a security precaution against accidentaly typing
+# /die or /restart
+# X:<password for /DIE>:<password for /RESTART>
+X:diepass:restartpass
+
+# C: [NETWORKED]. These lines define what servers your server tries to
+# connect to.
+# N: [NETWORKED]. These lines define what servers your server permits
+# connections to be initiated from.
+# C/N lines MUST be used in pairs. You cannot have one without the other.
+#
+# C: lines contain the following fields:
+# C:remote server's hostname:passwd:remote server's name:port:conn class
+# (connection class)
+# N: lines contain the following fields:
+# N:remote server's hostname:passwd:remote server's name:host mask:conn class
+# (connection class)
+# "host mask" is the number of parts in *your* hostname to mask to. For
+# instance, with my servername being "csa.bu.edu", if I wanted to present
+# my servername to be "*.bu.edu" I would have a host-mask portion of "1".
+#
+# it is *strongly* advised that your C/N line passwords be different for
+# security's sake.
+#
+# ident is allowed in the server's hostname part of the field.
+# these lines tell the server to automatically (note the port number, that
+# means automatic connection) connect to server2.my.net:
+C:foobar@server2.my.net:bigspark:server2.my.net:7000:32
+N:foobar@server2.my.net:bigalpha:server2.my.net::32
+#
+# This server's connection lines are more vanilla, masking the host to
+# *.toledolink.com (as described above):
+C:*.my.net:camelsrk00l:*.my.net::32
+N:*.my.net:andsoarellamas:*.my.net:1:32
+#
+# K: [OPTIONAL]. These lines define user@host patterns to be banned from
+# this particular server (with an optional time field). Note that K: lines
+# are *not* global, and if you ban a user they can still use any other IRC
+# server (unless they have specifically been banned there as well).
+#
+# The time field (same as reason) is only used if you #define
+# TIMED_KLINES in config.h, and even then they are discouraged.
+#
+# the fields are defined as:
+# K:hostmask:reason:username
+# wildcards are permitted in any one of the fields, in other words, you can
+# K:*::* if you wanted (but your server wouldn't be used much ;-)
+#
+# Spaces are permitted in the reason field (you don't have to use _).
+# The /stats command has been modified to replace all spaces with _'s when
+# doing a /stats k. K:lines also allows you to specify a file to play to the
+# user when they are K:lined. To use this feature the reason must be in the
+# format of |filename. the filename must be kc.anythinghere, this is to prevent
+# the sending of text files such as your ircd.conf.
+#
+# This K: line bans the username "hrose" (the wildcards are used to make
+# sure that any ident-checking character will match) on any machine from
+# the University of Boston.
+K:*.bu.edu:Hacking #UnrealIRCD:*hrose*
+#
+# This K: line bans any users from acs*.bu.edu between the hours of 8am
+# and 12pm and 1pm and 5pm (the time is always the server's local time).
+# Time-based K-lines such as this require TIMED_KLINES in config.h to be
+# #defined.
+K:acs*.bu.edu:0800-1200,1300-1700:*
+# Note that 24 hour time is used (no "AM" or "PM").
+# This K: line bans all *.foobar.com users and will play the file |kc.flooding
+# to the user as the reason.
+K:*.foobar.com:|kc.flooding:*
+#
+# E: [OPTIONAL]. This allows kline exceptions, even if a person matches
+# a K:line or /kline they are still allowed to connect.
+#
+# The fields are as follows
+# E:hostmask:reason:usermask
+#
+E:foo.bar.com:Oper on this server:*john21*
+#
+#
+# q: [DISCOURAGED]. These lines "quarantine" specified servers. Because
+# of the way they operates, the same q: lines MUST be installed by
+# everyone or the net will keep breaking. I CANNOT EMPHASIZE THIS ENOUGH.
+# Do NOT use q: lines lightly!
+#
+# This is NOT a nick q-line, if you wish to quarantine a NICK, see below.
+#
+# The fields are as follows:
+# q:*:reason why quarantine is in place:servername
+#
+q::this server is too slow and lags the net:cm5.eng.umd.edu
+#
+# Q: [OPTIONAL]. Different from the above type of q: line, these lines
+# prevent users on your server from picking certain nicks. This is useful
+# if your network has 'reserved' nicknames that should not be taken by
+# normal users. Note the difference in capitalization and BE CAREFUL!
+#
+# The fields are as follows:
+# Q:*:reason why quarantine is in place:nickname
+#
+# For example, You might want to use the following lines:
+Q::Reserved for services:ChanServ
+Q::Reserved for services:NickServ
+Q::Reserved for services:MemoServ
+Q::Reserved for services:OperServ
+Q::Reserved for services:HelpServ
+Q::Reserved for services:StatServ
+Q::Reserved for operators:IRCop
+Q::Reserved for operators:*Oper*
+Q::Reserved for administrators:Admin*
+#
+#
+# T: [OPTIONAL]. These allow you to specify different MOTD and RULES files
+# based on a users host. This is made so you can have MOTDs in different
+# languages so all users can see the MOTD and understand it.
+#
+# The fields are as follows:
+# T:host:motdfile:rulesfile
+#
+# T:*.fr:french.motd:french.rules
+#
+#
+# e: [OPTIONAL]. These lines allow you to specify a host which will not
+# be scanned by the proxy scanner when they connect. This is made so you
+# can allow some open proxys to connect while still killing others. Make
+# sure you use an IP and not a host for this line or it will not work.
+# NOTE: These are not the same as E:lines.
+#
+# The fields are as follows:
+# e:IP:*:*
+#
+# e:123.123.123:*:*
+#
+#
+# Z: [DISCOURAGED]. These block ALL incoming connections from a certain
+# IP address mask. They can stop users who log on and issue the SERVER
+# command a couple of times just to annoy irc ops. They are more
+# powerful that K-lines because they can stop users before they've had a
+# chance to register. This works on servers, SO BE VERY CAREFUL WITH
+# YOUR Z-LINE MASKS. Z-lines are a LAST RESORT. They are much too
+# dangerous and powerful to be using them instead of K-lines and akills.
+#
+# NOTE 1: Z-lines do NOT work on host names! Only IP addresses.
+# NOTE 2: Z-lines are part of /stats k.
+# NOTE 3: The :* at the end is REQUIRED. Not using it will cause both
+# ircd and chkconf to segfault without saying why.
+#
+# Syntax:
+# Z:IP mask:reason for zapping:*
+Z:127.0.0.1:Please don't log on from the local machine:*
+#
+# L: [OPTIONAL]. These lines "Leaf" specified servers. They are only
+# useful if you are a non-leaf site yourself. There are two ways you can
+# use L: lines. The first will limit one particular site to a particular
+# tree depth (including 0, which would mean the server has to connect with
+# no servers linked behind it otherwise the connection will fail). The
+# second will allow you to be selective about which other servers you wish
+# the connecting server to behave as a leaf towards.
+#
+# The fields are as follows:
+# L:disallow connections to this hostmask::server name:depth
+# For example, this will force kaja.gi.alaska.edu to connect only as a
+# leaf (if it is not a leaf, the link will be dropped):
+L:::kaja.gi.alaska.edu
+# This line will force cm5.eng.umd.edu to have a depth of only 1 below it
+# (that is, it is allowed to have only leaves connected to it):
+L:::cm5.eng.umd.edu:1
+#
+# This line will prohibit anything matching *.edu to be connected behind
+# any server matching *.au:
+L:*.edu::*.au
+#
+# H: [OPTIONAL]. These lines define who you permit to act as a "hub" to
+# you (that is, who you permit to connect non-leafed servers to you).
+#
+# the first field may use wildcards, the third field *must* be an exact
+# match for a server's name (NOT a server's hostname, if they differ, the
+# server's name must be used). If the servername is a wildcard (e.g. *.au)
+# that is an acceptable name for the third field.
+#
+# The fields are as follows:
+# H:servers which are permitted entry::hub server
+#
+# Example, permit server.my.net to allow any servers behind it to
+# connect:
+H:*::server2.my.net
+#
+# Example, permit irc-2.mit.edu to allow any MIT servers behind it to
+# connect:
+H:*.mit.edu::irc-2.mit.edu
+#
+# P: [OPTIONAL]. This field allows the server to listen on various ports
+# (other than 7000) for connections. Any internet domain port that is
+# below 1024 means the ircd has to be run from inetd. The server can
+# listen to ports in the UNIX domain or the internet domain. If you wish
+# to create a port in the UNIX domain you must compile with UNIXPORT
+# defined in include/config.h. If you are permitting connections to a
+# seperate port, you can control access to that port by the host field.
+#
+# You can now bind internet ports to specific IP interface devices. To do
+# this put the IP address of the interface in the host field. To bind to
+# all interfaces, leave empty or put * in.
+#
+# The fields are as follows::
+# P:IP# or UNIX socket file:*:*:port number
+# for example, an internet domain socket on port 6665 for the local
+# computer
+P:127.0.0.1:*:*:6665
+#
+# This line is an example of a UNIX domain socket in /tmp
+P:/tmp/.ircd:*:*:6666
+
--- /dev/null
+[ $Id$ ]
+
+UnrealIRCd FAQ
+Made by Stskeeps
+
+This file will contain frequently asked questions about
+Unreal IRCd. If you need more help email stskeeps@tspre.org
+
+1) * I compile and everything seems fine during the compiling, but when it
+ comes time for the program to link, I get errors complaining about dns and
+ res things. What causes this?
+
+A: You need to make sure -lresolv is included in the "extra libraries"
+ option of ./Config (or IRCDLIBS in top-level makefile)
+
+2) * When I start up the IRCd it complains about something with chdir()?
+
+A: You need to make sure the right directory is specified when you was
+ asked about "What directory are all the server configuration files in?"
+ ./Config question
+
+3) The server says like:
+ *** Link server1 -> server2 is now synced [secs: 30 recv: 130.4 sent: 120.0]
+ when I link two servers together, what does that mean?
+
+A: That means the link is "synced" (all infodata transfered about the server).
+ The "secs" (30 in this example) means it took 30 seconds to do the sync
+ "recv: 130.4" means there was recieved 130 KiloBytes and 4 bytes.
+ "sent: 120.0" means there was sent 120 kilobytes from my side.
+
+4) What is a negative TS split?
+
+A: Every computer/server has got a time (so they can do TimeStamps) ..
+ When the clock on the computer is set wrong and the computer it links
+ upto is wrong it creates a Negative TS split (means time is lower it
+ actually is. How to fix this is contacting the root of the machine
+ and ask him to fix the time (when you made sure it's YOUR server that's
+ wrong)
+
+5) What is an uProtocol ?
+
+A: UnrealIRCd uses numbers to check if a link is compatible with itself
+ F.x Unreal v2.1.3 has got number 2103 while version 2.1 only has got
+ 2100 - This means .. if the number is lower/higher than the uProtocol
+ the server uses, it's an incompatible link (of some reasons)
+
+6) How does T:Lines work and what are they?
+
+A: T:Lines is a new Unreal feature that makes it able to show different
+ MOTDs and RULES to people who matches a certain hostmask . Lemme show you some examples:
+
+ T:*.dk:motds/danish.motd:rules/danish.rules
+ T:*.fr:motds/french.motd:rules/french.rules
+
+ This will get people from Denmark to see the "Danish" MOTD and the "Dandish" RULLES
+ and people from France to see the French ones:)
+
+ NOTE: T:Lines are read up side down so if you have a T:*:ircd.motd:ircd.rules in the bottom
+ it should be at the top so the other motd lines can work as well
+
+7) Where can i download updates to Unreal?
+
+A: Mostly you can download the newest version at
+ http://unreal.tspre.org
+
+ Versions may be spewed out regulary due to new features and bugs..
+
+8) Why does it say "unlimit core failed" or something when I boot the IRCd?
+A: It's just a warning, mainly just ignore it.
+
+9) I use Linux Mandrake and ./Config always hangs! What can I do??
+A: Go edit the Config script and remove those lines:
+-SNIP START-
+cat > $TMP <<__EOF__
+#$STRINGH STRINGH
+#$STRINGSH STRINGSH
+#ifdef STRINGH
+#include <string.h>
+#endif
+#ifdef STRINGSH
+#include <strings.h>
+#endif
+main()
+{
+ char *t = "a", *s = strtok(t, ",");
+ if (!strcmp(t, s))
+ exit(0);
+ exit(1);
+}
+__EOF__
+$COMP >/dev/null 2>&1
+if [ $? -ne 0 ] ; then
+ echo $n " strtok$c"
+ NSTRTOK=define
+else
+ $EXEC
+ if [ $? -ne 0 ] ; then
+ echo $n " strtok$c"
+ NSTRTOK=define
+ fi
+fi
+$RM -f $EXEC $TMP
+--- SNIP END---
+And replace it by
+NSTRTOK=undef
+
+This should get it to work=) (thanks to Joe Whipple for reporting this bug)
+---END----
+
+10) Hosts show up as (null).network.net !!
+A: This is because you have forgotten to include the network file.
+ The correct form is (in unrealircd.conf)
+ Include ..........: <network file>
+
+ If this doesn't work .. seek me at irc.global-irc.net #unrealircd
+
+11) The IRCd uses like 66.7% CPU !!!?
+A: Try run it with nice :
+ /usr/bin/nice -n 19 src/ircd
+
+ if services go this way too just place ./<name> instead of src/ircd
+ Any more support seek me at the default place:P
+
+12) My IRCd which runs on a FreeBSD says something about FDs and
+ Max: 0 What shall I do??
+A: Well it's somekinda bug but you can workaround it by removing those
+ lines in src/s_bsd.c: (init_sys())
+
+<- snippet 1 ->
+#ifdef RLIMIT_FD_MAX
+ struct rlimit limit;
+ int pid;
+
+ if (!getrlimit(RLIMIT_FD_MAX, &limit))
+ {
+# ifdef pyr
+ if (limit.rlim_cur < MAXCONNECTIONS)
+#else
+ if (limit.rlim_max < MAXCONNECTIONS)
+# endif
+ {
+ (void)fprintf(stderr,"ircd fd table too big\n");
+ (void)fprintf(stderr,"Hard Limit: %d IRC max: %d\n",
+ limit.rlim_max, MAXCONNECTIONS);
+ (void)fprintf(stderr,"Fix MAXCONNECTIONS\n");
+ exit(-1);
+ }
+# ifndef pyr
+ limit.rlim_cur = limit.rlim_max; /* make soft limit the max */
+ if (setrlimit(RLIMIT_FD_MAX, &limit) == -1)
+ {
+ (void)fprintf(stderr,"error setting max fd's to %d\n",
+ limit.rlim_cur);
+ exit(-1);
+ }
+# endif
+ }
+#endif
+
+<-snippet 2->
+#ifdef sequent
+# ifndef DYNIXPTX
+ int fd_limit;
+
+ fd_limit = setdtablesize(MAXCONNECTIONS + 1);
+ if (fd_limit < MAXCONNECTIONS)
+ {
+ (void)fprintf(stderr,"ircd fd table too big\n");
+ (void)fprintf(stderr,"Hard Limit: %d IRC max: %d\n",
+ fd_limit, MAXCONNECTIONS);
+ (void)fprintf(stderr,"Fix MAXCONNECTIONS\n");
+ exit(-1);
+ }
+# endif
+#endif
+
+13) I run debian-sparc and i get errors when compiling in match.c
+ What should I do?
+A: If it says like this
+<-snippet->
+match.c: In function 'myncmp':
+match.c:247: argument 'str1' doesn't match prototype
+/usr/include/string.h:255: prototype declaration
+match.c:247: argument 'str2' doesn't match prototype
+/usr/include/string.h:255: prototype declaration
+match.c:247: argument 'n' doesn't match prototype
+/usr/include/string.h:255: prototype declaration
+<-end of snippet>
+
+Then go into include/setup.h and add this line:
+#define GOT_STRCASECMP
+
+(C) Carsten Munk 1999
\ No newline at end of file
--- /dev/null
+.\" $Id$
+.TH IRC 1 "7 October 1990"
+.SH NAME
+irc \- User Interface to Internet Relay Chat Protocol
+.SH SYNOPSIS
+\fBirc\fP [\fB-p\fP \fIportnum\fP] [\fB-c\fP \fIchannel\fP] [ \fInickname\fP [ \fIserver\fP ]]
+.SH DESCRIPTION
+.LP
+\fBIrc\fP is a user interface to the Internet Relay Chat, a CB-like
+interactive discussion environment. It is structured into \fIchannels\fP,
+which are public discussion forums, and also allows for private intercommunication.
+Each participant has a \fInickname\fP, which is the one specified in the command
+line or else his login name.
+.LP
+Once invoked, \fBirc\fP connects as a client to the specified server,
+\fIserver\fP or to the default one (see below). The screen splits into a dialogue
+window (the major part
+of the screen) and a command line, from which messages can be sent and
+commands given to control irc.
+.SH COMMAND SYNTAX
+The syntax of irc commands is of the form \fB/COMMAND\fP. The most notable
+ones are listed below. For an uptodate list, use the \fBHELP\fP command
+of \fBirc\fP. Case is ignored.
+.IP "\fB/ADMIN\fR [\fIserver\fP]"
+Prints administrative information about an IRC \fIserver\fP.
+.IP "\fB/AWAY\fP [\fImessage\fP]"
+Mark yourself as being away (with an automatic reply \fImessage\fP
+if specified)
+.IP "\fB/BYE\fR, \fB/EXIT\fR, \fB/QUIT\fR"
+Terminate the session
+.IP "\fB/CHANNEL\fR [\fIchannel\fP]"
+Join another \fIchannel\fP
+.IP "\fB/CLEAR\fR"
+Clear the screen
+.IP "\fB/HELP\fR [\fIcommand\fP]"
+Display a brief description of the \fIcommand\fP (or list all commands, if none
+specified).
+.IP "\fB/SUMMON\fR \fIuser\fP"
+Allows to summon a \fIuser\fP specified as a full Internet address, i.e.,
+\fIlogin@host.domain\fP, to an IRC dialogue session (in much the same
+way as the talk(1) command). It is usable ONLY if the irc daemon runs on
+the target machine (host.domain).
+.IP "\fB/TOPIC\fR \fItopic\fP"
+Sets the \fItopic\fP for the current channel
+.IP "\fB/WHO\fR [\fIchannel\fP|*]"
+Lists all users of IRC if no argument, of the specified \fIchannel\fP or of the
+current channel (*).
+.SH ARGUMENTS
+.IP "\fB-p\fP \fIportnum\fP"
+TCP/IP "port number. Default is 6667 and this option should seldom if ever"
+be used.
+.IP "\fB-c\fP \fIchannel\fP"
+\fIChannel\fP number to join upon beginning of the session. Default is no channel.
+.IP "\fInickname\fP"
+\fINickname\fP used in the session (can be changed with the \fB/NICK\fP command).
+Default is user login name.
+.IP "\fIserver\fP"
+\fIServer\fP to connect to. Default is specified in the irc system configuration
+file, and can be superseded with the environment variable IRCSERVER.
+.SH EXAMPLE
+.RS
+.nf
+tolmoon% \fBirc -p6667 Wizard tolsun\fP
+.fi
+.RE
+.LP
+connects you to irc server in host tolsun (port 6667) with nickname Wizard
+.SH COPYRIGHT
+Copyright (c) 1988 University of Oulu, Computing Center, Finland.
+.nf
+Copyright (c) 1988,1989,1990 Jarkko Oikarinen
+.nf
+All rights reserved.
+For full COPYRIGHT see LICENSE file with IRC package.
+.SH "SEE ALSO"
+ircd(8)
+.SH BUGS
+What bugs ?
+.SH AUTHOR
+Jarkko Oikarinen <jto@tolsun.oulu.fi>
+.nf
+Manual page updated by Michel Fingerhut <Michel.Fingerhut@ircam.fr>
--- /dev/null
+.\" $Id$
+.TH IRCD 8 "29 March 1989"
+.SH NAME
+ircd \- The Internet Relay Chat Program Server
+.SH SYNOPSIS
+.hy 0
+.IP \fBircd\fP
+[-a] [-c] [-i] [-o] [-q] [-t] [-d directory]
+[-f configfile] [-x debuglevel] [-h hostname] [-p portnum]
+.SH DESCRIPTION
+.LP
+\fIircd\fP is the server (daemon) program for the Internet Relay Chat
+Program. The \fIircd\fP is a server in that its function is to "serve"
+the client program \fIirc(1)\fP with messages and commands. All commands
+and user messages are passed directly to the \fIircd\fP for processing
+and relaying to other ircd sites. The \fIirc(1)\fP program depends upon
+there being an \fIircd\fP server running somewhere (either on your local
+UNIX site or a remote ircd site) so that it will have somewhere to connect
+to and thus allow the user to begin talking to other users.
+.SH OPTIONS
+.TP
+.B \-d directory
+This option tells the server to change to that directory and use
+that as a reference point when opening \fIircd.conf\fP and other startup
+files.
+.TP
+.B \-o
+Starts up a local ircdaemon. Standard input can be used to send IRC
+commands to the daemon. The user logging in from standard input will
+be given operator privileges on this local ircd. If ircd is a setuid program,
+it will call setuid(getuid()) before going to local mode. This option
+can be used in inetd.conf to allow users to open their own irc clients
+by simply connecting their clients to the correct ports. For example:
+.TP
+.B
+irc stream tcp nowait irc /etc/ircd ircd \\-f/etc/ircd.conf \\-o
+
+allows users connecting to irc port (specified in /etc/services) to start
+up their own ircdaemon. The configuration file should be used to check from
+which hosts these connections are allowed from. This option also turns
+on the autodie option -a.
+.TP
+.B \-a
+Instructs the server to automatically die off if it loses all it's clients.
+.TP
+.B \-t
+Instructs the server to direct debugging output to standard output.
+.TP
+.B \-x#
+Defines the debuglevel for ircd. The higher the debuglevel, the more stuff
+gets directed to debugging file (or standard output if -t option was used
+as well).
+.TP
+.B \-i
+The server was started by inetd and it should start accepting connections
+from standard input. The following inetd.conf-line could be used to start
+up ircd automatically when needed:
+.TP
+.B
+ircd stream tcp wait irc /etc/ircd ircd \-i
+
+allows inetd to start up ircd on request.
+.TP
+.B \-f filename
+Specifies the ircd.conf file to be used for this ircdaemon. The option
+is used to override the default ircd.conf given at compile time.
+.TP
+.B \-c
+This flag must be given if you are running ircd from \fI/dev/console\fP or
+any other situation where fd 0 isnt a tty and you want the server to fork
+off and run in the background. This needs to be given if you are starting
+\fIircd\fP from an \fIrc\fP (such as \fI/etc/rc.local\fP) file.
+.TP
+.B \-q
+Using the -q option stops the server from doing DNS lookups on all the
+servers in your \fIircd.conf\fP file when it boots. This can take a lengthy
+amount of time if you have a large number of servers and they are not all
+close by.
+.TP
+.B \-h hostname
+Allows the user to manually set the server name at startup. The default
+name is hostname.domainname.
+.B \-p portname
+Specifies the port where the daemon should start waiting for connections.
+This overrides the default which is given at compile time.
+.TP
+.SH
+If you plan to connect your \fIircd\fP server to an existing Irc-Network,
+you will need to alter your local IRC CONFIGURATION FILE (typically named
+"ircd.conf") so that it will accept and make connections to other \fIircd\fP
+servers. This file contains the hostnames, Network Addresses, and sometimes
+passwords for connections to other ircds around the world. Because
+description of the actual file format of the "ircs.conf" file is beyond the
+scope of this document, please refer to the file INSTALL in the IRC source
+files documentation directory.
+.LP
+BOOTING THE SERVER: The \fIircd\fP server can be started as part of the
+UNIX boot procedure or just by placing the server into Unix Background.
+Keep in mind that if it is *not* part of your UNIXES Boot-up procedure
+then you will have to manually start the \fIircd\fP server each time your
+UNIX is rebooted. This means if your UNIX is prone to crashing
+or going for for repairs a lot it would make sense to start the \fIircd\fP
+server as part of your UNIX bootup procedure. In some cases the \fIirc(1)\fP
+will automatically attempt to boot the \fIircd\fP server if the user is
+on the SAME UNIX that the \fIircd\fP is supposed to be running on. If the
+\fIirc(1)\fP cannot connect to the \fIircd\fP server it will try to start
+the server on it's own and will then try to reconnect to the newly booted
+\fIircd\fP server.
+.SH EXAMPLE
+.RS
+.nf
+tolsun% \fBircd\fP
+.fi
+.RE
+.LP
+Places \fIircd\fP into UNIX Background and starts up the server for use.
+Note: You do not have to add the "&" to this command, the program will
+automatically detach itself from tty.
+.SH COPYRIGHT
+(c) 1988,1989 University of Oulu, Computing Center, Finland,
+.LP
+(c) 1988,1989 Department of Information Processing Science,
+University of Oulu, Finland
+.LP
+(c) 1988,1989,1990,1991 Jarkko Oikarinen
+.LP
+For full COPYRIGHT see LICENSE file with IRC package.
+.LP
+.RE
+.SH FILES
+ /etc/utmp
+ "irc.conf"
+.SH "SEE ALSO"
+irc(1)
+.SH BUGS
+None... ;-) if somebody finds one, please inform author
+.SH AUTHOR
+Jarkko Oikarinen, currently jto@tolsun.oulu.fi,
+manual page written by Jeff Trim, jtrim@orion.cair.du.edu,
+later modified by jto@tolsun.oulu.fi.
--- /dev/null
+[ $Id$ ]
+The following macros are included in "ircd.m4" for use with the m4 text
+preprocessor. "ircd.m4" is parsed before the IRC server conf file so they
+are all available for use with that.
+
+NOTE: The "ircd.m4" file is *ONLY* created by a "make install".
+
+VERSION - current version string as in patchlevel.h
+DEBUGMODE - if DEBUGMODE is define in config.h, is also defined for m4.
+HOSTNAME - taken from hostname(1)
+USER - username of person doing the "make install"
+PORT - default port number as in config.h
+PFREQ - default ping frequency as in config.h
+CFREQ - default connect frequency as in config.h
+MAXSENDQ - default max sendq as in config.h
+CL - use this to wrap a class number
+HOST - use this to wrap a hostname
+HOSTM - use this to wrap the hostmask number in N-lines
+ID - when wrapping the host field in an I-line, causes ident string return
+ to be used instead of user supplised username.
+PASS - use this to wrap passwords in C/N/I/O lines
+PING - use this to wrap the ping value in Y-lines
+APORT - use this to wrap the port number in I-lines
+CPORT - use this to wrap the port number in C-lines
+SERV - use this to wrap server names
+
+You might use some of these as
+C:foo.bar.edu:PASS(boo):foo.bar.edu:APORT(6667)
+I:ID(128.250.*)::ID(*.mu.oz.au):CPORT(6667)
+
+In addition to these (rather weak macros), some more complete ones are
+defined which already perform the above.
+
+ADMIN - provide fields to it as you would an A-line
+ALLOW - provide fields to it as you would an N-line
+BAN - provide fields to it as you would an K-line
+CLASS - provide fields to it as you would an Y-line
+CLIENT - provide fields to it as you would an I-line
+CONNECT - provide fields to it as you would an C-line
+ME - provide fields to it as you would an M-line
+HUB - first parameter is server you want to hub, second is optional and is
+ a mask against which other servers introduced must match against.
+LEAF - works like HUB, except that the mask is matched against server names
+ to check if the link should be dropped.
+SERVER - uses 6 fields, the first 4 as are found in an N-line, the last two
+ should be as you would use in a C-line. It expands out to provide
+ both a C and N line.
--- /dev/null
+ [ $Id$ ]
+From: Carlo Kid - Runaway <carlo@sg.tn.tudelft.nl>
+Subject: GUIDE for compiling your server
+To: wastelanders@rush.cc.edu (New Wastelanders MailingList)
+Date: Thu, 26 May 94 13:44:10 METDST
+Cc: carlo@sg.tn.tudelft.nl
+Mailer: Elm [revision: 66.33]
+Status: RO
+
+GUIDE for compiling your server, by Runaway
+===============================================
+
+First of all you must get all the files you need, as an example
+I will explain how to compile irc2.8.19.U3.2.
+The files you'll need in general are:
+
+- irc2.8.19.U3.2.tar.gz
+
+Or, when you already have an older version -say irc2.8.19.U3.1- a patch:
+
+- irc2.8.19.U3.1-2.patch
+
+It is possible you need more then one patch, especially when you already
+upgraded more often. But in that case you already have those old patches.
+Of course, in that case, you also already have the old directory tree:
+
+/home..../yourname/....ircd/irc2.8.19.U3.1/
+
+Scripts, patches and directory trees
+====================================
+
+It is good practise to:
+1) Call the directory tree after the version
+2) Let this directory ONLY contain what comes with the .tar.gz file!
+ Thus: Do NOT put ircd.conf, or any patches etc in it!!!
+ In general, you must be able to delete this whole directory tree
+ when you still have the original .tar.gz file and patches applied to it.
+3) Put it in a directory ending on /ircd, THIS directory will contain
+ your ircd.motd, ircd.pid, ircd.conf and patches...
+
+So, you end up with:
+
+...ircd/irc2.8.19.U3.1-2.patch
+...ircd/irc2.8.19.U3.1.tar.gz
+
+or just:
+
+...ircd/irc2.8.19.U3.2.tar.gz
+
+at once.
+
+Before you can delete the old directory tree, you must be SURE to save
+everything thats in it. This is thus the .tar.gz file, all patches but
+ALSO the following files:
+
+Makefile
+include/config.h
+include/setup.h
+
+You should always keep a copy of those files OUTSIDE the irc2.8.19.U3.2/
+directory tree. For instance:
+
+...ircd/irc.personal/Makefile
+...ircd/irc.personal/include/config.h
+...ircd/irc.personal/include/setup.h
+
+To make these backups easy, you should make a script, called backup.personal
+containing:
+
+cp Makefile ../irc.personal/Makefile
+cp include/config.h ../irc.personal/include/config.h
+cp include/setup.h ../irc.personal/include/setup.h
+
+If you also change anything in the other Makefiles (ircd/Makefile and
+common/Makefile) you can add those too. Be sure to make the directories
+by hand first.
+
+Make the script 'backup.personal' executable with:
+chmod 700 backup.personal
+You must be able to run it from any directory, so put it in your ..bin/
+
+Ok... so now you have a backup of everything. If you wanted to start
+ALL over you could delete the directory tree, unzip and untar the archive
+again, apply all patches to it, change the Makefile and config.h again,
+put setup.h back, recompile and reinstall.
+In some cases it is easy to do this with an other script, I call it 'repatch',
+it provides you with an easy-to-change overview of the patched you have used.
+Here is how my 'repatch' looks now (it is located in .../ircd/repatch).
+
+cd ~/irc/ircd
+rm -rf irc2.8.19 irc2.8.19.U3.2
+zcat irc2.8.19.tar.gz | tar xf -
+mv irc2.8.19 irc2.8.19.U3.2
+cd irc2.8.19.U3.2
+#patch -p1 < ../Makefile.config.h.patch 2> ../patch.out
+#cp ../setup.h include/setup.h
+patch -p1 < ../irc2.8.19-TSpre8.2.patch 2>> ../patch.out
+patch -p1 < ../irc2.8.19.TSpre8-note.patch 2>> ../patch.out
+patch -p1 < ../irc2.8.19.TSpre8-wallops.patch 2>> ../patch.out
+patch -p1 < ../irc2.8.19.TSpre8-bquiet.patch 2>> ../patch.out
+patch -p1 < ../irc2.8.19.TSpre8-silence.2.patch 2>> ../patch.out
+#patch -p1 < ../irc2.8.19.U3-ban.patch 2>> ../patch.out
+make clean
+vi include/patchlevel.h
+grep -e '\.rej' -e '[Ff]ail' -e fuzz ../patch.out
+
+As you can see I commented out the patches Makefile.config.h.patch and
+irc2.8.19.U3-ban.patch, and don't copy setup.h here. This is because
+I wanted to make a virgin .U3.2.tar.gz for distribution via ftp-sites.
+If I change the name of the directory, I have to change it in three
+places :/
+This script forces me to edit the patchlevel.h :) :)
+The last grep warns me if anything went wrong with the patches.
+
+Moreover, as you can see, I have a 'Makefile.config.h.patch'.
+You should make your own as soon as you completely installed
+and tested your server. It is very handy for re-installing a new
+version.
+
+To make this patch, edit the Makefile's and and config.h and type:
+
+backup.personal
+cd ..
+rm -rf irc2.8.19
+zcat irc2.8.19.tar.gz | tar xf -
+diff -rc irc2.8.19 irc.personal > Makefile.config.h.patch
+
+Check it with an editor if it looks ok. In the above, 'irc2.8.19.tar.gz'
+is the virgin 'Avalon' version, I change the Makefiles in the .U3
+however also, so you might wanna use the virgin .U3.2.tar.gz.
+
+Starting ALL over (or begining for the first time)
+==================================================
+
+This is about EDITTING the Makefile(s) and config.h, and creating the
+setup.h for the first time.
+
+2.8.19 is different from 2.8.16 and before. You will have to EDIT the
+Makefile and config.h that comes with the distribution. You can NOT
+use the old Makefile and config.h you had !
+
+First write down the path you want to use where you are going to put
+the ircd.conf etc...
+
+Edit the Makefile. Comments are in it. You should simply define that
+what is needed for your Operating System.
+
+Then edit the config.h
+
+Then run ./Config to create setup.h ... at first simply hit return all the
+time. If you insist on using gcc instead of cc, you must edit that in your
+Makefile BEFORE running setup.h. You can't change that running Config,
+although it asks for it. If you have more then one cc, you can add the
+right path to in the Makefile (if it uses the wrong one).
+
+Since U3.2, I changed the Makefile and config.h a little. The changes are:
+- I added note.o to the dependency
+- I added *.orig files to the 'make clean' (otherwise the *.orig generated
+ by some 'patch' programs will be left).
+If you want this too, and you have .U3.1, you can get the patch from
+sg.tn.tudelft.nl (file: Makefile.conf.U3.patch).
+
+As soon as you are done, run backup.personal. To stay up to date with your
+backup.
+
+Then make the Makefile.conf.patch as described above. (or wait with that
+till you are sure it works... otherwise it might be done more then once
+which is a waste of time).
+
+Special remarks
+---------------
+
+Makefile:
+First occurance of
+ CC=cc
+Change this NOT if you want another compiler, add another CC= later, close
+to your OS specific #defines...
+
+# IRCDDIR must be the same as DPATH in include/config.h
+#
+IRCDDIR=/sb/users/carlo/irc/ircd
+Make sure you use the same path in the config.h :)
+
+SUBDIRS=common ircd
+By removing the 'irc' from this line, you stop 'make' from making the client
+as well.
+
+config.h:
+/*
+ * NOTE: On some systems, valloc() causes many problems.
+ */
+#undef VALLOC /* Define this if you have valloc(3) */
+I never try it, even if I have it.
+
+#define USE_VARARGS
+For defines like this, you best check the online manual if you have them
+(man vprintf in this case)... I didn't have man page for vscanf() but it
+still worked... (I DO have them for vprintf and vsprinf).
+
+#undef DEBUGMODE /* define DEBUGMODE to enable debugging mode.*/
+Debug mode uses a lot more memory and is a lot slower. ONLY define
+when your server gives problems like crashing/coredumping, or other
+things like not wanting to startup etc. In other words: when you are really
+*USING* this feature to do DEBUGing !
+
+#define NPATH "/sb/users/carlo/irc/server/Undernet/.ircdnote"
+The '#ifdef notdef' '#endif' around NPATH mean: notdef = NOT DEFINED.
+You should *never* #define notdef... It is used to "comment out" *examples*.
+By defining it, you enable all examples (like making your server SUI :/)
+Simply *remove* the lines '#ifdef notdef' and '#endif' around the NPATH.
+
+#define DPATH "/sb/users/carlo/irc/ircd"
+Must be the same as in the Makefile!
+#define SPATH "/sb/users/carlo/bin/ircd" /* path to server executeable */
+This is used when you do a /RESTART. For fast restarting a NEW version (upgrade)you can let this point to a symbolic link, and then change this link to the
+new executable. Do a 'restart' and voila...
+For instance:
+.../bin/ircd.U3.2*
+.../bin/ircd -> ircd.U3.2
+The last made with:
+ln -s ircd.U3.2 ircd
+Then when you upgrade:
+rm ircd
+ln -s ircd.U3.3 ircd
+and a /RESTART
+
+#undef CRYPT_LINK_PASSWORD
+Make sure your ircd.conf isn't world readable like on pasadena :/
+(and on ircserver.et.tudelft.nl once - we DID have to change all passwords
+ then)
+
+Compiling the server
+====================
+
+*** FIRST edit your include/patchlevel.h ***
+
+If you don't want to compile the client, you can change the Makefile
+as mentioned above, or type:
+make server
+
+After a succesfull compilation (ignore warning ;), you can type
+make install
+or just
+cp ircd/ircd ~/bin/ircd.U3.2
+cd ~/bin
+chmod 700 ircd.U3.2
+rm ircd
+ln -s ircd.U3.2 ircd
+
+I changed my Makefile to do the latter thing when I type 'make install'
+
+Then run the server by typing 'ircd'. Don't do this on the
+...ircd/irc2.8.19.U3.2/ircd/ directory, because when in your PATH the
+'.' comes before your '~/bin' you start up THAT exucutable, disallowing
+you to recompile later (text file busy).
+
+Compile errors
+==============
+
+If anything goes wrong with note, it most likely is because you
+1) Didn't define NPATH correctly
+2) Didn't add the note.o to the dependencies.. remove note.o and recompile.
+
+[ For a non-undernet version: irc2.8.19.tar.gz is bugged, get the -note.patch
+ from ftp.undernet.org. ]
+
+If you get problems while linking saying it has undefined _something
+and something is something with 'res', you must add -lresolv to your
+IRCDLIBS in the Makefile.
+
+If you get problems with any function beging defines twice are giving
+errors like not compatible with previous definition (likely atol() in
+note.c), just remove that whole function from the .c file (put #ifdef notdef
+around it). You have it already in your system libraries.
+
+Last remarks
+============
+
+Add those U: lines!!!
+And change your ircd.motd to reflect the new commands/features :)
+( /MOTD uxb* -- Nice motd RedRum! :)
+
+-------------------------------------------------------------------
+
+Run
+
+--
+-------------------------------------------------------------------------------
+| carlo@sg.tn.tudelft.nl | Run @ IRC |
+| | Admin of Delft.NL.EU.undernet.org |
+| * Don't expect anything of live, | and Ircserver.et.tudelft.nl |
+| or you'll miss all the rest of it.| |
+-------------------------------------------------------------------------------
+
--- /dev/null
+
+The Tao of Internet Relay Chat
+Copyright (C) Ove Ruben R Olsen 1994
+Version of 940110
+Contributing masters: Master ScottM
+
+-----
+Something is formed by the electrons, born in the silent cable. Shaping
+and growing and ungrowing. It is there yet not there. It is the source of
+Internet Relay Chat. I do not know the name, thus I will call it the Tao
+of Internet Relay Chat.
+
+If the Tao is great, then the IRC is running ceaselessly. If the IRC is
+great then the server is running without ever stoping. If the server is
+great then the client will always be the server. The luser is then pleased
+and there is Chat in the world.
+
+The Tao of IRC squits far away and connects on returning.
+
+
+-----
+The genetic potential of birth, a lot to know, yet unknown.
+
+In the begining there was nothing.
+
+Out of nothing the Tao gave birth to tolsun.oulu.fi. tolsun gave birth to
+OuluBox.
+
+OuluBox gave birth to rmsg.
+
+rmsg was not Tao, so MUT gave birth to IRC.
+
+No one knows when IRC came into existance, the mighty master WiZ have it
+to be at the end of the eight month in the year of the Dragon.
+
+
+-----
+Each channel has its purpose, however humble. Each channel is the Yin and
+Yang of IRC. Each channels has it's place within the IRC.
+
+In the beginning there was only channel 0, thus channel 0 is the soil of
+IRC.
+
+Channel 1 to channel 10 then was open as the sea. Channel 11 to 999 was the
+trees and forests of IRC. Channels above 999 should not be mentioned, and
+channels below 0 were unborn and contained many secrets.
+
+This was not the right Tao, so IRC gave birth to +channels.
+
++channels had the yin and yang. Mode does not.
+
+This was not the right Tao still, so IRC gave birth to #channels.
+
+#channels have the yin and yang.
+
+Only channel 0 is the right path to Tao, but avoid speaking on channel 0.
+
+
+-----
+There was a great dispute among the Broom-Walkers of the Relay. Some of them
+wanted neither yin nor yang. Out of this Eris came into existance. Some of the
+Broom-Walkers then created Eris Free-net.
+
+This was the right Tao.
+
+Kind Gentle and Boring Net was another wrong path to the Tao of Internet Relay
+Chat.
+
+Some time later there was a quantity of some lusers who wanted to be
+Broom-Walkers also. The Eris Free Broom-Walkers did not agree with them,
+thus a new IRC was born. This IRC is called the Undernet.
+
+But this is not the right Tao, either.
+
+
+-----
+There will always be disputes among the Broom-Walkers of Internet Relay Chat.
+
+This is the very nature of the IRC.
+
+
+-----
+Lusers that do not understand the Tao is always using the yang of Mode on
+their channels. Lusers that do understand the Tao are always using Ignore
+on their channels.
+
+How could this not be so ?
+
+
+-----
+The wise sage luser is told about the Chat and uses it. The luser is told
+about the IRC and is looking for it. The flock are told about the Tao and
+make a fool of the IRC.
+
+If there was no laughter, there would be no Tao.
+
+
+-----
+The master says:
+"Without the Tao of Internet Relay Chat, life becomes meaningless."
+
+The Relay of the old time was mysterious and sacred. We can neither imagine
+its thoughts nor path; we are left but to describe.
+
+
+-----
+The sage luser must be aware like a frog crossing the highway.
+
+
+-----
+The great master Wumpus once dreamed that he was an automaton. When he awoke
+he exclaimed:
+ "I don't know whether I am Wumpus dreaming that I am a client,
+ or a client dreaming that I am Wumpus!"
+
+So was the first Automata born.
+
+The master Nap then said:
+ "Any automata should not speak unless spoken to.
+ Any automata shall only whisper when spoken to."
+
+Thus replied the master Gnarfer:
+ "The lusers shall keep in mind that a automata can be either good or
+ bad. Create good automata, and the IRC will hail you and you will
+ gain fame and fortune. Create bad automata and people will start to
+ hate you, and finaly you will be /KILLed to ethernal damnation"
+
+Many lusers have fallen into the clutches of ethernal damnation. They where
+not following the Tao.
+
+
+-----
+There once was a luser who went to #BotSex. Each day he saw the automatons.
+The luser decided that he also would have such a automata.
+He asked another luser for his automata. The other luser gave his automata
+away.
+
+The luser was not within the Tao, so he just started the automata. The automata
+had only Yang inside so all the lusers files where deleted.
+
+Some moons laither the same luser then had become a sage luser, and did create
+his automata from the very grounds with materials found inside the IRC.
+The luser was now within the Tao and his automata lived happily ever after.
+
+
+-----
+There once was a master who wrote automatons without the help of master Phone.
+A novice luser, seeking to imitate him, began with the help of master Phone.
+When the novice luser asked the master to evaluate his automata the master
+replied: "What is a working automata for the master is not for the luser.
+You must must BE the IRC before automating."
+
+
+-----
+Master BigCheese gave birth to master Troy; his duty clear. Master Troy gave
+birth to master Phone, for the Tao of Irc must be eternal and must flow as the
+ceaseless river of Time itself.
+
+
+-----
+Master Phone once said about the ircII client:
+ "public_msg is for a message from someone NOT on the channel
+ public_other is for a message on a channel that doesn't belong to
+ a window. public is for a message on a channel that belongs to a
+ window!"
+
+Out of this raised the mighty chaos.
+
+
+-----
+The sage luser came to the master who wrote automata without the help of
+master Phone. The sage luser asked the master who wrote automata: "Which is
+easiest to make. A automata with the help of master Phone or an automata
+made with the help of a language ?"
+
+The master who wrote automata then replied:
+ "With the help of a language."
+
+The sage luser was disapointed and exclaimed: "But, with master Phone you
+do not need to know anything about the soil of IRC. Is not that the easiet
+way ?"
+
+"Not really" said the master who wrote automata, "when using master Phone
+you are closed inside a box. For sure, it is a great box for the lusers,
+but the master will need more power, thus a language is the only path to go.
+With the language the master will never have to limit himself. When using
+such a language the master will seek the best between the need and the
+availibility."
+
+"I see", said the sage luser.
+
+This is the essence of Tao of IRC automatas.
+
+
+-----
+A client should be light and be used for communication. The spirit of a good
+client is that it should be very convinient for the luser to use, but hard
+for the luser who want to create automata.
+There should never ever be too many functions or too few functions.
+
+There should always be a ignore.
+
+Without ignore the client is not within the Tao of Chating.
+
+The client should always respond the luser with messages that will not
+astnonish him too much. The server likewise. If the server does not, then it
+is the clients job to explain what the server says.
+
+A client which fails this, will be useless and cause confusion for the lusers.
+The only way to correct this is to use another client or to write a new one.
+
+
+-----
+A luser asked the masters on #IrcHelp: "My client does not work".
+The masters replied: "Upgrade your client".
+The luser then wondered why the master knew. The master then told him about
+the Protocol.
+
+"Your client does not work beaucse it does not understand the server. Why
+should it always work ? Only a fool would expect such. But, clients are made
+by humans, and humans are not perfect. Only Tao is.
+
+The IRC is solid. The IRC is floating, and will always be dynamic. Live with
+that or /quit."
+
+
+-----
+The luser came to the masters of #IrcHelp, asking about the Tao of IRC within
+the client.
+The masters then said that the Tao of IRC always lies inside the client
+regardless of how the client connects to the server.
+
+"Is the Tao in irc ?" asked the luser.
+"It so is" replied the masters of #IrcHelp.
+"Is the Tao in the ircII, Kiwi, rxirc, vms, rockers and msa ?" asked the
+luser.
+"In all of them and in the TPC, irchat, zenirc, zircon X11-irc and even the
+dos irc has the Tao" said the master quietly.
+"Is the Tao in a telnet connection directly to the server ?"
+
+The master then was quiet for a long time and said. "Please leave, such
+questions are not within the Tao of IRC".
+
+
+-----
+The master says: "Without the Protocol of TCP the messages will not travel.
+ Without the client, the server is useless."
+
+
+-----
+There once was a luser who used the ircII client. "ircII can do anything I
+ever need for using IRC" said the emacs client user, "I have /ON's, I have
+assignments, I have aliasing. Why don't you use this instead of the huge
+emacs client, which also has a messy screen?"
+The emacs client user then replied by saying that "it is better to have a
+scripting language that is the client instead of have a client that has
+a scripting language." Upon hearing this, the ircII client luser fell silent.
+
+
+-----
+The master Wumpus said: "Time for you to leave. I did, now I'm happy."
+The master Gnarfer replied: "Use, but never overuse IRC, then you will also
+be happy within IRC"
+
+
+-----
+A luser came unto the masters of #EU-Opers and asked, "How can I be, yet not
+be, a user@host within the IRC?"
+The masters of #EU-Opers replied: "To be Tao is to be ones true self. To hide
+ones self is not Tao, and is not IRC, you have much to learn before you shall
+be at rest within the Flow of Irc. Please leave"
--- /dev/null
+ ****** UnrealIRCd v2.1.7 Documentation ******
+ [ $Id$ ]
+
+1) About UnrealIRCd
+
+ I started making UnrealIRCd about 1-2 months ago. (July 1999 now)
+ First it was called mpx2.0b13.soundforge - as I was
+ inspired of the 'forge' word. I quickly changed name
+ after I realized the IRCd had more potential.
+ Unreal is based off Elite2.0b13 and some of
+ the minor bugfixes Potvin came up with. First lemme
+ introduce myself. My nick is Techie/Stskeeps. I hang
+ out at Global-IRC.net, DALnet, DragonWings.org and so on
+
+ Unreal is a hybrid of Elite (as I said) mixed with some
+ Twilight IRCd, TerraIRCd, TS4 (channel mode +h & +e) features
+ (IMHO TwilightIRCd is one of the best dreamforge hybrids I've seen!
+ Unreal is not a rip-off of other IRCds - I added a lot of features myself!
+ I really cannot mention some major features as I think a IRCd is a
+ IRCd when it has got useful commands- and people actually say mine has!
+
+ Anyways I dunt demand donations or anything. I just do coding for fun
+ I treat coding like playing with toys. It makes me happy(or is it just
+ caffeine?;). An addy to send donations is at the Donation file in the IRCd dir
+ And.. I don't sweat while making features unlike some Potvin coder so dunt
+ send me towels;) I would be more happy if someone e-mailed me with ideas
+ to the IRCd.. The whole IRCd is GNU so if you want to rip off any of my ideas
+ You are generally welcome:) Just remember to do what's said in the Changes file!
+ -- So.. Enjoy this IRCd:) It may become a dream to IRCd owners as its infact
+ a sortof hybrid of EliteIRCd (Cite .man-pages/page1 in Elite:
+ EliteIRCD has become a dream to many ircd owners</end cite>
+ -- Carsten Munk / Techie .. =)
+
+2) Commands (User Commands)
+
+ *** WATCH Command ***
+ Watch is a new notify-type system in UnrealIRCd which is both faster
+ and uses less network resources than any old-style notify
+ system. You may add entries to your Watch list with the command
+ /watch +nick1 [+nick2 +nick3 ..., and the server will send
+ you a message when any nickname in your watch list logs on or off.
+ Use /watch -nick to remove a nickname from the watch list, and
+ just /watch to view your watch list.
+ The watch list DOES NOT REMAIN BETWEEN SESSIONS - you (or your
+ script or client) must add the nicknames to your watch list every
+ time you connect to an IRC server. /Watch was made in DreamForge IRCd
+ which UnrealIRCd in ground is based off
+
+ *** HELPOP Command ***
+ HelpOp is a new system of getting IRC Server help. You type either
+ /HelpOp ? <help system topic> or /HelpOp ! <question>
+ The "?" in /HelpOp means query the help system and if you get no
+ response you can choose '!' to send it to the Help Operators online
+ ------------oOo--------------
+
+ *** LIST Command ***
+ New extended /list command options are supported. To use these
+ features, you will likely need to prefix the LIST command with
+ /quote to avoid your client interpreting the command.
+
+ Usage: /quote LIST options
+
+ If you don't include any options, the default is to send you the
+ entire unfiltered list of channels. Below are the options you can
+ use, and what channels LIST will return when you use them.
+ >number List channels with more than <number> people.
+ <number List channels with less than <number> people.
+ C>number List channels created between now and <number> minutes ago.
+ C<number List channels created earlier than <number> minutes ago.
+ T>number List channels whose topics are older than <number> minutes
+ (Ie., they have not changed in the last <number> minutes.
+ T<number List channels whose topics are newer than <number> minutes.
+ *mask* List channels that match *mask*
+ !*mask* List channels that do not match *mask*
+ LIST defaults to sending a list of channels with 2 or more members,
+ so use the >0 option to get the full channel listing.
+
+ *** PRIVMSG Command ***
+ PRIVMSG and NOTICE, which are used internally by the client for
+ /msg and /notice, in UnrealIRCd support two additional formats:
+ /msg @#channel <text> will send the text to channel-ops on the
+ given channel only. /msg @+#channel <text> will send the text
+ to both ops and voiced users on the channel. While some clients
+ may support these as-is, on others (such as ircII), it's necessary
+ to use /quote privmsg @#channel <text> instead. It's perhaps a
+ good idea to add the/alias omsg /quote privmsg @$0 $1 into
+ your script (.ircrc) file in that case.
+
+ **** KNOCK Command ****
+ /Knock is a new UnrealIRCd command which enables you to
+ 'knock' on a channel if it is +i and these criteria is met
+ - Channel is not +K (No knocks)
+ - Channel is not +I (No invites!)
+ - You're not banned!
+ - And you are not already there:)
+
+ Syntax:
+ /Knock #Channel :Reason
+
+ **** LICENSE Command ****
+ This command shows the GNU License
+ Which is hard-coded into the IRCd:)
+ Syntax: /License [optional server]
+
+ *** SetName Command ***
+ /SetName is a new feature in UnrealIRCd
+ Which allows users to change their 'Real name'
+ (GECOS) directly online at IRC without reconnecting
+
+ Syntax:
+ /SetName :New Real Name
+
+
+ *** MODE Command ***
+ This is basically the /mode command as it has always
+ been on IRC. Thou in Channel mode basis it has got an
+ Extra feature (/mode #Channel ^ ) which reports channel
+ modes represented in a bitstring (may be handy, maybe not)
+ UnrealIRCd has got some new channel / usermodes I think you
+ wish to take a look at
+ Channel Modes Help: /HelpOp CHMODES
+ User modes help: /HelpOp UMODES
+
+ *** STATSERV Command ***
+ This is a alias for the /msg StatServ command,
+ But is more secure. If the IRC network doesn't have StatServ
+ It will report it is down.
+
+ Syntax:
+ /StatServ <command>
+
+ *** /Credits Help ***
+ This command will list the credits I've created
+ to thank the people who has helped me with making
+ UnrealIRCd. Anyone who I've forgotten all my kind
+ thoughts go to -- Techie'99
+
+ Syntax:
+ /Credits [optional server]
+
+ *** /DALINFO Help ***
+ This command will list the credits that the
+ Dreamforge IRCd team/the IRCd developers
+ from the start when IRCd got developed
+
+ Syntax:
+ /DALInfo [optional server]
+
+3) Operator Commands
+
+ This section is the IRCOp's only commands
+ area:) - These topics are available:
+ Note: This doesnt include Dreamforge commands
+
+ SETHOST SETIDENT SDESC
+ ADCHAT NACHAT TECHAT
+ GLINE REMGLINE STATS
+ MKPASSWD SNOTES SNOTE
+ ADDLINE LAG RPING
+ ADDMOTD ADDOMOTD OPERMOTD
+ CHGHOST TSCTL SAJOIN
+
+ *** ADDMOTD Command Help ***");
+ This will add the text you specify to the MOTD
+ (the general motd - T:lines doesnt count ..)
+ Server Admin & Co-Admin only
+
+ Syntax: /ADDMOTD :text
+
+ *** ADDOMOTD Command Help ***
+ This will add the text you specify to the Operator MOTD
+ Server Admin & Co-Admin only
+
+ Syntax: /ADDOMOTD :text
+
+ *** OPERMOTD Command Help ***
+ This is a IRCop only command - shows the IRCd Operator MOTD
+ Syntax: /OperMotd
+
+ *** SETHOST Command Help ***
+ This command is so you can change your
+ Virtual host (hiddenhost) to everything you want to
+ Except special characters;).
+
+ Syntax:
+ /SetHost <new hostname>)
+
+ Example:
+ /Sethost ircaddicts.org
+
+ *** SETIDENT Command Help ***
+ With this command you can change your
+ ident (username).
+
+ Syntax:
+ /SetIdent <new ident>
+
+ Example:
+ /SetIdent root
+
+ *** SDesc Command help ***
+ NOTE: This is a Server Admin/Co Admin only command
+ With this command you can change your Server Info Line
+ Without having to squit and reconnect.
+ Syntax: /SDesc :New description
+ Example: /SDesc :If you belong to me..
+
+ *** AdChat Command Help ***
+ This command sends to all Admins online (IsAdmin)
+ Only for Admins. This is a ChatOps style command
+ Syntax: /AdChat :<text>
+ Example: /AdChat :Hey guys!
+
+ *** NAChat Command Help ***
+ This command sends to all NetAdmins & TechAdmins online
+ Only for Net/Techadmins. This is a ChatOps style command
+ Syntax: /NAChat :<text>
+ Example: /NAChat :Hey guys!
+
+ *** Stats Command Help ***
+ UnrealIRCd has got a extension called /Stats G
+ Which will list the current G:Lines
+ Syntax: /Stats G
+
+ *** TEChat Command Help ***
+ This command sends to all TechAdmins online
+ Only for Net/Techadmins. This is a ChatOps style command
+ Syntax: /TEChat :<text>
+ Example: /TEChat :Hey guys!
+
+ *** CHGHOST Command help ***
+ This command makes you able to change other people's virtual hostname
+ - IRCop only.
+ Syntax: /CHGHOST <nick> <newhost>
+
+ *** TSCTL Command Help ***");
+ This is a highly advanced command");
+ Syntax:");
+ /TSCTL OFFSET +|- <time> - Adjust internal IRC clock");
+ /TSCTL TIME - Will give TS report");
+
+ *** SAJOIN Command help **");
+ Makes <nick> join channel <channel>");
+ Services Admin only..");
+ Syntax: /SAJOIN nick channel");
+
+
+ *** RemGline Command Help
+ This command can remove G:Lines
+
+ Syntax:
+ /RemGline <user@host mask>
+
+ Example:
+ /RemGline *@*.flirt.org
+
+ *** G:line command Help ***
+ This command provides timed G:Lines. If you match
+ a G:Line you cannot connect to ANY server at the
+ IRC network
+ Syntax:
+ /GLINE <user@host mask> <seconds to be banned> :<reason>
+ Example:
+ /GLINE *@*.dal.net 900 :Spammers
+ this will ban all users matching *@*.dal.net for 15 minutes
+ with reason 'Spammers'
+
+ *** MkPasswd Command help ***
+ This command will encrypt the string it has been given
+ So u can add it directly to the ircd.conf if you use
+ Encrypted passwords. /MKPassWd is disabled in UnrealIRCd/32
+ Syntax : /MkPasswd :string to be encrypted
+
+ *** SNOTE Command Help ***
+ This will store the parameter of the command to a file
+ Which then can be read by using /SNOTES LIST
+ Syntax: /SNOTE :<message>
+
+ *** SNOTES Command Help ***
+ This command is made to view notes
+ Written to the SNOTE file by using /SNOTE
+ Syntax: /SNOTES LIST
+ or /SNOTES <number>
+
+ *** ADDLINE Command Help ***
+ This command can be used to add lines to the ircd.conf file
+ Only for Server Admins
+ Syntax: /AddLine :<line>
+
+ *** LAG Command Help ***
+ This command is like a sonar/traceroute for IRC servers
+ You type in /lag server1.irc.net and it will
+ reply from every server it passes with time and so on
+ Useful for looking where lag is and optional TS future/past travels
+ Syntax: /LAG <servername>
+
+ **** RPING Command help ***
+ This will calculate the milliseconds (lag) between servers
+
+ Syntax: /RPING <servermask>
+
+ 4) *** UnrealIRCd Usermodes ***
+ o = Global IRCop
+ O = Local IRCop
+ i = Invisible (Not shown in /who searches)
+ w = Can listen to wallop messages
+ g = Can read & send to globops, and locops
+ h = Available for help
+ s = Can listen to server notices
+ k = See's all the /KILL's which were executed
+ S = For services only. (Protects them)
+ a = Is a services admin
+ A = Is a server admin
+ N = Is a network admin
+ T = Is a tech admin
+ C = Is a co admin
+ c = See's all connects/disconnects on local server
+ f = Listen to flood alerts from server
+ r = Identifies the nick as being registered
+ x = Gives the user hidden hostname
+ e = Can listen to server messages sent to +e users
+ b = Can read & send to chatops
+ W = (IRCops only) Lets you see when people does a /whois on you
+ q = (Services Admins only) Gets you unable to be
+ kicked unless by U:Lines
+ B = (users) Marks you being a Bot
+ F = (net|tech admin only) Lets you see far client connect/disconnects
+ I = (net|tech admin only) Invisible Join/Part. Makes you
+ being hidden at channels
+ 1 = (IRCops only) Marks you a Coder
+5) *** UnrealIRCd Channel Modes ***
+ p = Private channel
+ s = Secret channel
+ i = Invite-only allowed
+ m = Moderated channel, noone can speak except users with mode +voh
+ n = No messages from outside channel
+ t = Only channel operators may set the topic
+ r = Channel is registered
+ R = Requires a registered nickname to join the channel
+ x = No ANSI color can be sent to the channel
+ q = Channel owner (The big cheese)
+ Q = No kicks able in channel unless by U:Lines
+ O = IRCop only channel (setable by Opers)
+ A = Server Admin | Network Admin | Tech Admin only channel (same as above)
+ K = /Knock is not allowed
+ I = /Invite is not allowed
+ S = Strip all incoming colours away
+ l <number of max users> = Channel may hold at most <number> of users
+ b <nick!user@host> = Bans the nick!user@host from the channel
+ k <key> = Needs the channel key to join the channel
+ o <nickname> = Gives operator status to the user
+ v <nickname> = Gives voice to the user (May talk if chan is +m)
+ a <nickname> = Gives protection to the user (No kick/drop)
+ e <exception ban> = Exception ban - If someone matches it
+ they can join even if some else ban matches!
+ h <nickname> = Gives halfop status to the user
+ L <chan2> = If channel is full (+l) the next user
+ will autojoin <chan2>
+ You can get additional explanation on modes:
+ Q h
+ With /HELPOP mode-<x> where <x> is Q f.x. like mode-Q
+
+ *** Channel mode +Q ***
+ This is the 'peace' mode. Noone can kick eachother
+ except by U:Lines. Bans can be placed thou.
+
+ *** Channel halfops (+h) ***
+ If you are marked as halfop (% in /names) you can do:
+ - Set topic
+ - Kick non-ops
+ - Set modes +vmntibe
+
+6) *** UnrealIRCd O:Line flags ***
+ r = Access to /rehash server
+ R = Access to /restart server
+ D = Access to /die server
+ h = Oper can send /help ops - gets +h on oper up
+ g = Oper can send /globops
+ w = Oper can send /wallops
+ l = Oper can send /locops
+ c = Access to do local /squits and /connects
+ Y = Access to do remote /squits and /connects
+ k = Access to do local /kills
+ K = Access to do global /kills
+ b = Oper can /kline users from server
+ B = Oper can /unkline users from server
+ n = Oper can send local server notices(/notice $servername message)
+ N = Oper can send global notices(/notice $*.network.net message)
+ u = Oper can set /umode +c
+ f = Oper can set /umode +f
+ o = Local oper, flags included: rhgwlckbBnuf
+ O = Global oper, flags included: oRDCKN
+ A = Gets +A on oper up. Is server admin
+ a = Gets +a on oper up. Is services admin
+ N = Gets +N on oper up. Is network admin
+ T = Gets +T on oper up. Is tech admin
+ C = Gets +C on oper up. Is co admin
+ z = Can add /zlines
+ H = Gets +x on oper up.
+ W = Gets +W on oper up.
+ ^ = Allows to use umode +I
+
+7) Last word
+
+This documentation is based off src/help.c in Unreal2.1.7
+For version Unreal2.1.7 - $Date$
+Made by Carsten Munk 1999 (Stskeeps)
\ No newline at end of file
--- /dev/null
+ [ $Id$ ]
+ Dynamic Configuration Guide
+
+Okay first you have to go edit the file "unrealircd.conf" in
+the directory "networks/". In that file you see a field with
+name "Include" .. if you want to create your own network file
+(IRC network specification) you have to write like
+"networks/<irc network>.network" like "networks/myircnetwork.network"
+
+If there is already a network file you can just put in the path
+like : "networks/dragonwings.org"
+
+If you want to create your own network file
+copy the file "template.network" to the name you want to use for
+your network file and edit it.
+
+If you experince any problems email me at stskeeps@tspre.org
+or try msg me at /server irc.global-irc.net : #UnrealIRCd
+My nick is mostly Stskeeps or Techie (or Nightwalker if i had a bad night:P)
+
+--Stskeeps
--- /dev/null
+...
\ No newline at end of file
--- /dev/null
+all: client server
+
+client:
+ gcc -o tsp-client tsp-client.c sscript.c
+
+server:
+ gcc -o tsp-server-run tsp-server-run.c
+ gcc -o tsp-skin socker.c
+
+clean:
+ rm -f *~
+ rm -f tsp-server-run tsp-client tsp-skin
\ No newline at end of file
--- /dev/null
+
+how to use tsp-client:
+
+first make it "make"
+
+then run it like this:
+$ ./tsp-client <tsp server> <port>
+
+do this a couple of times
+if the answers come within 1 second count its right
+then take the most common time difference count and do in UnrealIRCd like
+this:
+
+/quote tsctl offset + <difference count>
+
+then your server is time synched
+
+current tsp servers online:
+
+server port
+-----------------------------
+irc.flirt.org 6100
+
+
+if you want to make your own TSP server (must be a box using NTP)
+run ./tsp-server, it will then start running on port 6100
\ No newline at end of file
--- /dev/null
+
+
+ Socket Script C library
+ -----------------------
+
+Home page:
+http://www.linsupport.com
+
+This is a simple library that provides usefull functions for C
+networking applications. It's based on the Socket Script scripting
+language, but meant for C programmers. These functions are really
+shortcuts to C functions, meant to make their use simple.
+
+This can create a static lib: libsscript.a
+
+To compile:
+
+make
+
+Then to install it:
+
+make install
+
+
+(C) Copyright 1998-2000 Patrick Lambert <drow@post.com>
+
+This library is under the LGPL license which means:
+
+1- You can copy and use this program freely.
+
+2- You may not claim that you wrote it.
+
+3- If you want to include parts of this software in your own product,
+you can do so if that product stays under free software and if all
+copyright notices in source and documentation, as well as the no warranty
+comment, remains.
+
+4- This program is distributed without ANY WARRANTY, without even
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
--- /dev/null
+/*
+ SOCKER Socket redirector version 0.1
+ Patrick Doyle Oct 1998
+ Based on tserver by Michael Johnson and Erik Troan
+
+ Puts a normal stdin & stdout based program up on a port
+ as a server process. Each connection spawns a new copy
+ of the program.
+
+ Please notify me of any changes to this code tha you
+ subsequently redistribute. I can be contacted at
+ patrick@minotaursoftware.com.
+
+ Also, please leave my name and those of Michael Johnson
+ and Erik Troan at the top of this file.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#define ZOMBIE /* Causes zombies to be collected. Only works under Linux. */
+
+#define debug printf
+#undef debug
+void debug(char *format, ...){}
+
+int sock = -1;
+
+void die(char *msg){
+ perror(msg);
+ exit(1);
+}
+
+void handle_sig(int signum){
+ if(signum == SIGCHLD){
+ /* Collect exit statuses. Prevent zombies. */
+ int status;
+ while(0 < waitpid(-1, &status, WNOHANG));
+ }else{
+ fprintf(stderr, "\nSocker exiting normally.\n");
+ close(sock);
+ exit(0);
+ }
+}
+
+#define asizeof(x) (sizeof(x)/sizeof(x[0]))
+
+void setup_sig_handler(){
+ int sa_num;
+ static int sigs[] = {
+ SIGHUP, SIGINT, SIGQUIT, SIGXCPU, SIGXFSZ, SIGTERM
+# ifdef ZOMBIE
+ , SIGCHLD
+# endif
+ };
+ static struct sigaction sig_actions[asizeof(sigs)];
+ debug("Starting setup_sig_handler\n");
+ memset(sig_actions, 0, sizeof(sig_actions));
+ sig_actions[0].sa_handler = handle_sig;
+ sigemptyset(&(sig_actions[0].sa_mask));
+ for(sa_num=1; sa_num < asizeof(sigs); sa_num++){
+ memcpy(sig_actions+sa_num, sig_actions, sizeof(sig_actions[0]));
+ }
+ for(sa_num=0; sa_num < asizeof(sigs); sa_num++){
+ if(sigaction(sigs[sa_num], sig_actions+sa_num, NULL))
+ die("sigaction");
+ }
+# ifdef ZOMBIE
+ siginterrupt(SIGCHLD, 0); /* Don't let SIGCHLD interrupt socket calls */
+# endif
+ debug("Ending setup_sig_handler\n");
+}
+
+int main(int argc, char *argv[]) {
+ struct sockaddr_in address;
+ int conn, i, portnum;
+ size_t addrLength = sizeof(struct sockaddr_in);
+
+ fprintf(stderr, "SOCKER Socket Redirector Patrick Doyle Oct 1998\n");
+
+ if (argc < 3 || !(portnum = atoi(argv[1]))){
+ fprintf(stderr, "Usage: socker {port_num} {command}\n");
+ fprintf(stderr, "Waits for TCP connections on the given port, and then\n");
+ fprintf(stderr, "spawns a new process executing {command} for each connection.\n");
+ fprintf(stderr, "Exit status: 0=caught signal and exited; 1=error\n");
+ exit(1);
+ }
+
+ if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0)
+ die("socket");
+
+ debug("Calling setup_sig_handler\n");
+ setup_sig_handler();
+
+ /* Let the kernel reuse the socket address. This lets us run
+ twice in a row, without waiting for the (ip, port) tuple
+ to time out. */
+ i = 1;
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*)&i, i);
+
+ address.sin_family = AF_INET;
+ address.sin_port = htons(portnum);
+ memset(&address.sin_addr, 0, sizeof(address.sin_addr));
+
+ if (bind(sock, (struct sockaddr *) &address, sizeof(address)))
+ die("bind");
+
+ if (listen(sock, 5))
+ die("listen");
+
+ while ((conn = accept(sock, (struct sockaddr *) &address, &addrLength)) >= 0) {
+ if(fork()){ /* Parent; loop back to accept another */
+ close(conn);
+ }else{ /* Child; exec given command line */
+ close(sock);
+ /* Redirect stdin & stdout to socket */
+ if(0 != dup2(conn, 0) || 1 != dup2(conn, 1))
+ die("dup2 redirection");
+ /* Turn off buffering */
+ /* Note: this seems to have no effect beyond execvp */
+ setbuf(stdin, 0);
+ setbuf(stdout, 0);
+ setbuf(stderr, 0);
+ /* Execute command */
+ execvp(argv[2], argv+2);
+ /* Error if we get here */
+ fprintf(stderr, "execvp failed. Please make sure that '%s' refers to a valid program.\n", argv[2]);
+ _exit(1)/*
+ man fork says _exit should be called to prevent parent from
+ being corrupted.
+ */;
+ }
+ }
+
+ if (conn < 0)
+ die("accept");
+
+ /* Shouldn't get here */
+ close(sock);
+ return 2;
+}
--- /dev/null
+Socket Script Library 2.0
+-------------------------
+
+Here are the functions and errno code numbers returned by some of SScript's
+functions:
+
+errno:
+SSCRIPT_SOCKET_FAILED 10
+SSCRIPT_BIND_FAILED 11
+SSCRIPT_GETSOCKETNAME_FAILED 12
+SSCRIPT_FLAGS_FAILED 13
+SSCRIPT_CONNECT_FAILED 20
+SSCRIPT_UDPSEND_FAILED 31
+SSCRIPT_UDPRECEIVE_FAILED 32
+SSCRIPT_READ_FAILED 33
+
+The following are the SScript functions available in this library.
+They return either a string, an int or void. If an error occurs, it returns
+NULL (in case of a string) or -1 (in case of an int) and sets errno to
+the right error code (see above). Note that since each connection is
+associated with a socket number (sockfd), it is possible to make
+multiple connections.
+
+- char *sscript_lindex(char *input_string, int word_number);
+Get <word_number> from <input_string>. Returns the requested word.
+
+- char *sscript_lrange(char *input_string, int starting_at);
+Return everything after <starting_at> in <input_string>.
+
+- int sscript_connect(char *server, int port, char *virtual);
+Connect to <server> at port <port>, binding to virtual address
+<virtual>. If no binding is required, use NULL. Returns the socket
+number.
+
+- int sscript_server(int port);
+Initialize a server socket. Returns the socket number.
+
+- int sscript_wait_clients(int sockfd, int port, int forking);
+Listen to port <port> and wait for clients. This function is a
+blocking function. It will stay there untill it gets a client, and when
+it does, it will create a child and return its associated socket number.
+The child will go in the background if <forking> is set to 1
+(required for multithreading). This returns the child' sockfd.
+
+- char *sscript_get_remote_ip();
+This function returns the IP that connected to a server-oriented program.
+
+- void sscript_disconnect(int sockfd);
+Diconnects the connection pointed by <sockfd>.
+
+- void sscript_dump(int sockfd, char *filename);
+Dumps the content of <filename> to the connection pointed by <sockfd>.
+
+- void sscript_ping(char *hostname);
+Sends a TCP ping (echo to port 7) to <hostname>. This is a blocking
+function and only returns if the ping worked.
+
+- int sscript_test(char *hostname, int port);
+This tests if port <port> from <hostname> is open. Returns 0 if it is.
+
+- char *sscript_version();
+Returns the current library version.
+
+- char *sscript_read(int sockfd, int chop);
+Read from the connection pointed by <sockfd> and clear the last
+char if <chop> is set to 1.
+
+- void sscript_write(int sockfd, char *string);
+Write <string> to the connection pointed by <sockfd>.
+
+- int sscript_udp_send(char *hostname, int port, char *msg);
+Send an UDP packet to <hostname> at port <port> containing the message <msg>
+
+- char *sscript_udp_listen(int port);
+Listen for UDP packets on port <port>. Available to root only.
+
+- char *sscript_icmp_detect();
+Listen for ICMP messages and return the type (see ICMP.types) and the IP
+that sent one. Available to root only.
+
+- char *sscript_resolve_host(char *hostname);
+Resolve <hostname> into an IP.
+
+- char *sscript_resolve_ip(char *ip);
+Resolve <ip> into an hostname.
+
+- char *sscript_get_localhost();
+Get the local hostname.
+
+- void sscript_binary_send(int sockfd, char *filename);
+This function sends a binary file.
+
+- void sscript_binary_get(int sockfd);
+This function receives a binary file.
+
+- char *sscript_login_to_passwd(char *login)
+This function converts a login name to its crypted password.
+
+- char *sscript_uid_to_login(long uid)
+This function finds the login name for the UID provided.
+
+- int sscript_sokstat(char *option, int sockfd)
+This will give the settings for the currently open socket sockfd. Option
+is what you want the setting of and can be sendbuf, recvbuf, error or type.
+
+- char *sscript_time_read(int sockfd, int time);
+This function reads from sockfd for time secs, and then returns what it
+read, or "timeout".
+
+- void sscript_redir(int sockfd1, int sockfd2);
+This function will redirect packets from sockfd1 to sockfd2, and the
+other way around.
+
+- void sscript_nodelay(int sockfd);
+Set the socket in non-blocking mode.
--- /dev/null
+/*
+* SScript - See the sscript.doc
+* (C) 1998 Drow <drow@wildstar.net>
+* http://devplanet.fastethernet.net
+*/
+
+#include "sscript.h"
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <strings.h>
+#include <sys/file.h>
+#include <signal.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#ifndef FNDELAY
+#define FNDELAY O_NONBLOCK
+#endif
+#ifdef POSIX
+#include <pwd.h>
+#include <sys/utsname.h>
+#endif
+
+char global_var[9][1024]; /* need to find why gcc outputs warns without this */
+char remoteIP[30];
+
+char *sscript_lindex(char *input_string, int word_number)
+{
+ char *tokens[1024];
+ static char tmpstring[1024];
+ int i;
+ strncpy(tmpstring,input_string,1024);
+ (char *)tokens[i=0] = (char *)strtok(tmpstring, " ");
+ while (((char *)tokens[++i] = (char *)strtok(NULL, " ")));
+ tokens[i] = NULL;
+ return(tokens[word_number]);
+}
+
+int sscript_connect(char *server, int port, char *virtual)
+{
+ struct sockaddr_in address;
+ struct sockaddr_in la;
+ int len, sockfd;
+ sockfd = socket(AF_INET, SOCK_STREAM, 0);
+ if(sockfd<1)
+ {
+ errno = SSCRIPT_SOCKET_FAILED;
+ return -1;
+ }
+ address.sin_family = AF_INET;
+ address.sin_addr.s_addr = inet_addr(server);
+ address.sin_port = htons(port);
+ len = sizeof(address);
+ if(virtual!=NULL)
+ {
+ la.sin_family = AF_INET;
+ la.sin_addr.s_addr = inet_addr(virtual);
+ la.sin_port = 0;
+ bind(sockfd, (struct sockaddr *)&la, sizeof(la));
+ }
+ if(connect(sockfd, (struct sockaddr *)&address, len)<0)
+ {
+ errno = SSCRIPT_CONNECT_FAILED;
+ return -1;
+ }
+ return sockfd;
+}
+
+int sscript_server(int port)
+{
+ int sockfd2, listen_len;
+ struct sockaddr_in listen_addr;
+ sockfd2 = socket(AF_INET, SOCK_STREAM, 0);
+ if(sockfd2<1)
+ {
+ errno = SSCRIPT_SOCKET_FAILED;
+ return -1;
+ }
+ listen_addr.sin_family = AF_INET;
+ listen_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ listen_addr.sin_port = htons(port);
+ listen_len = sizeof(listen_addr);
+ if(bind(sockfd2, (struct sockaddr *)&listen_addr, listen_len))
+ {
+ errno = SSCRIPT_BIND_FAILED;
+ return -1;
+ }
+ return sockfd2;
+}
+
+int sscript_wait_clients(int sockfd2, int port, int forking)
+{
+ int sockfd=(int)NULL,len,from_len,pid;
+ struct sockaddr_in address;
+ struct sockaddr_in from_addr;
+ struct sockaddr_in listen_addr;
+ listen_addr.sin_family = AF_INET;
+ listen_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ listen_addr.sin_port = htons(port);
+ len = sizeof(address);
+ listen(sockfd2, 5);
+ for(;;)
+ {
+ if(forking) if(sockfd!=(int)NULL) close(sockfd);
+ sockfd = accept(sockfd2, (struct sockaddr *)&address, &len);
+ if(forking) if((pid=fork())) break;
+ }
+ from_len=sizeof(from_addr);
+ memset(&from_addr, 0, sizeof(from_addr));
+ if(getpeername(sockfd, (struct sockaddr *)&from_addr,&from_len) < 0)
+ {
+ strcpy(remoteIP,"unknown");
+ }
+ else
+ {
+ strcpy(remoteIP,inet_ntoa(from_addr.sin_addr));
+ }
+ return sockfd;
+}
+
+char *sscript_get_remote_ip()
+{
+ return remoteIP;
+}
+
+void sscript_disconnect(int sockfd)
+{
+ shutdown(sockfd,2);
+ close(sockfd);
+}
+
+void sscript_dump(int sockfd, char *filename)
+{
+ char temp[1024]="";
+ FILE *fpa;
+ fpa=fopen(filename,"r");
+ if(fpa==NULL) return;
+ while(fgets(temp,1024,fpa)!=NULL)
+ write(sockfd, temp, strlen(temp));
+ fclose(fpa);
+}
+
+void sscript_ping(char *hostname)
+{
+ struct sockaddr_in other_addr;
+ int sockfd, result;
+ char temp[255];
+ sockfd=socket(AF_INET, SOCK_STREAM, 0);
+ if(sockfd<0)
+ {
+ errno = SSCRIPT_SOCKET_FAILED;
+ return;
+ }
+ other_addr.sin_family = AF_INET;
+ other_addr.sin_addr.s_addr = inet_addr(hostname);
+ other_addr.sin_port = htons(7);
+ connect(sockfd, (struct sockaddr*) &other_addr,sizeof(other_addr));
+ result=write(sockfd,"ping\n",strlen("ping\n"));
+ result=read(sockfd,temp,result);
+ close(sockfd);
+}
+
+int sscript_test(char *hostname, int port)
+{
+ int sockfd;
+ struct sockaddr_in other_addr;
+ if((sockfd=socket(AF_INET, SOCK_STREAM, 0))<0)
+ {
+ errno = SSCRIPT_SOCKET_FAILED;
+ return -1;
+ }
+ other_addr.sin_family = AF_INET;
+ other_addr.sin_addr.s_addr = inet_addr(hostname);
+ other_addr.sin_port = htons(port);
+ if(connect(sockfd, (struct sockaddr*)&other_addr,sizeof(other_addr))==-1)
+ {
+ errno = SSCRIPT_CONNECT_FAILED;
+ close(sockfd);
+ return -1;
+ }
+ close(sockfd);
+ return 0;
+}
+
+char *sscript_version()
+{
+ return ABOUT;
+}
+
+char *sscript_read(int sockfd, int chop)
+{
+ int i, result;
+ char inchar;
+ char string[1024];
+ bzero(string,1024);
+ strcpy(string,"");
+ for(i=0;(result=read(sockfd,&inchar,1))!='\0';i++)
+ {
+ string[i]=inchar;
+ if(inchar=='\n') break;
+ }
+ if (chop) string[i-1]=' ';
+ strcpy(global_var[0],string);
+ return global_var[0];
+}
+
+void sscript_write(int sockfd, char *string)
+{
+ write(sockfd, string, strlen(string));
+}
+
+int sscript_compare(char *case1, char *case2)
+{
+ return (strcmp(case1,case2));
+}
+
+char *sscript_lrange(char *input_string, int starting_at)
+{
+ char *tokens[555];
+ static char tmpstring[512]="";
+ int i;
+ char out_string[512]="";
+ strcpy(out_string,"");
+ if(input_string==NULL) {
+ strcpy(out_string," ");
+ strcat(out_string,NULL);
+ strcpy(global_var[1],out_string);
+ return global_var[1]; }
+ strcpy(tmpstring,input_string);
+ (char *)tokens[i=0] = (char *)strtok(tmpstring, " ");
+ while(((char *)tokens[++i] = (char *)strtok(NULL, " ")));
+ tokens[i] = NULL;
+ i++;
+ if(i<starting_at) return (int)NULL;
+ while(tokens[starting_at] != NULL)
+ {
+ strcat(out_string,tokens[starting_at]);
+ strcat(out_string, " ");
+ starting_at++;
+ }
+ strcpy(global_var[2],out_string);
+ return global_var[2];
+}
+
+int sscript_udp_send(char *hostname, int port, char *msg)
+{
+ int udpsock;
+ struct sockaddr_in udpaddr;
+ udpsock = socket(AF_INET, SOCK_DGRAM, 0);
+ if(udpsock<0)
+ {
+ errno = SSCRIPT_SOCKET_FAILED;
+ return -1;
+ }
+ udpaddr.sin_family = AF_INET;
+ udpaddr.sin_port = htons(port);
+ udpaddr.sin_addr.s_addr = inet_addr(hostname);
+ if(sendto(udpsock,msg,sizeof(msg),0,(struct sockaddr *)&udpaddr,sizeof(udpaddr))<0)
+ {
+ errno = SSCRIPT_UDPSEND_FAILED;
+ return -1;
+ }
+ return 0;
+}
+
+char *sscript_udp_listen(int port)
+{
+ int udpsock,len;
+ struct sockaddr_in udpaddr, from;
+ char msg[255];
+ udpsock = socket(AF_INET, SOCK_DGRAM, 0);
+ if(udpsock<0)
+ {
+ errno = SSCRIPT_SOCKET_FAILED;
+ return (char *)NULL;
+ }
+ udpaddr.sin_family = AF_INET;
+ udpaddr.sin_addr.s_addr = INADDR_ANY;
+ udpaddr.sin_port = htons(port);
+ if(bind(udpsock,(struct sockaddr *)&udpaddr,sizeof(udpaddr))<0)
+ {
+ errno = SSCRIPT_BIND_FAILED;
+ close(udpsock);
+ return (char *)NULL;
+ }
+ len = sizeof(from);
+ if(recvfrom(udpsock,msg,sizeof(msg),0,(struct sockaddr *)&from,&len)<0)
+ {
+ errno = SSCRIPT_UDPRECEIVE_FAILED;
+ close(udpsock);
+ return (char *)NULL;
+ }
+ close(udpsock);
+ strcpy(global_var[3],msg);
+ return global_var[3];
+}
+
+char *sscript_icmp_detect()
+{
+ int icmpsock,len,result,type;
+ struct sockaddr_in icmpaddr;
+ char readbuf[1024]="";
+ char msg[255];
+ if((icmpsock=socket(AF_INET, SOCK_RAW, IPPROTO_ICMP))<0)
+ {
+ errno = SSCRIPT_SOCKET_FAILED;
+ return (char *)NULL;
+ }
+ icmpaddr.sin_family = AF_INET;
+ icmpaddr.sin_addr.s_addr = INADDR_ANY;
+ icmpaddr.sin_port = 0;
+ if(bind(icmpsock,(struct sockaddr *)&icmpaddr,sizeof(icmpaddr))<0)
+ {
+ errno = SSCRIPT_BIND_FAILED;
+ close(icmpsock);
+ return (char *)NULL;
+ }
+ len=sizeof(icmpaddr);
+ if(getsockname(icmpsock,(struct sockaddr *)&icmpaddr,&len)<0)
+ {
+ errno = SSCRIPT_GETSOCKETNAME_FAILED;
+ close(icmpsock);
+ return (char *)NULL;
+ }
+ if((result=read(icmpsock,readbuf,sizeof(readbuf)))<0)
+ {
+ errno = SSCRIPT_READ_FAILED;
+ close(icmpsock);
+ return (char *)NULL;
+ }
+ type=readbuf[20] & 0xff;
+ sprintf(msg,"%d %d.%d.%d.%d ",type,readbuf[12]&0xff,readbuf[13]&0xff,readbuf[14]&0xff,readbuf[15]&0xff);
+ close(icmpsock);
+ strcpy(global_var[4],msg);
+ return global_var[4];
+}
+
+char *sscript_resolve_host(char *hostname)
+{
+ struct hostent *hp;
+ struct sockaddr_in from;
+ char result[255];
+ memset(&from, 0, sizeof(struct sockaddr_in));
+ from.sin_family = AF_INET;
+ hp=gethostbyname(hostname);
+ if(hp==NULL) strcpy(result,"unknown");
+ else
+ {
+ memcpy(&from.sin_addr,hp->h_addr,hp->h_length);
+ strcpy(result,inet_ntoa(from.sin_addr));
+ }
+ strcpy(global_var[5],result);
+ return global_var[5];
+}
+
+char *sscript_resolve_ip(char *ip)
+{
+ struct hostent *hp;
+ struct sockaddr_in from;
+ char result[255];
+ from.sin_family = AF_INET;
+ from.sin_addr.s_addr = inet_addr(ip);
+ hp=gethostbyaddr((char *)&from.sin_addr, sizeof(struct in_addr),from.sin_family);
+ if(hp==NULL) strcpy(result,"unknown");
+ else strcpy(result,(char *)hp->h_name);;
+ strcpy(global_var[6],result);
+ return global_var[6];
+}
+
+char *sscript_get_localhost()
+{
+ char result[255];
+ gethostname(result,sizeof(result));
+ strcpy(global_var[7],result);
+ return global_var[7];
+}
+
+void sscript_binary_send(int sockfd, char *string)
+{
+ char temp4[255], temp2[255];
+ int cnt;
+ FILE *fpa;
+ sprintf(temp4,"uuencode %s %s > %s/.temp.uue 2>/dev/null",string,string,TMP_DIR);
+ system(temp4);
+ sprintf(temp2,"%s/.temp.uue",TMP_DIR);
+ fpa=fopen(temp2,"r");
+ if(fpa==NULL || fileno(fpa)<0) return;
+ else {
+ while((cnt = read(fileno(fpa), temp4, 250))>0)
+ write(sockfd, temp4, cnt);
+ if(fpa!=NULL) fclose(fpa);
+ sprintf(temp4,"rm -f %s/.temp.uue",TMP_DIR);
+ system(temp4);
+ }
+}
+
+void sscript_binary_get(int sockfd)
+{
+ char temp2[255], temp4[255], inchar, inall[1024];
+ FILE *fpa;
+ int i;
+ sprintf(temp2,"%s/.temp.uue",TMP_DIR);
+ fpa=fopen(temp2,"w");
+ if(fpa==NULL || fileno(fpa)<0) return;
+ while(strcasecmp(inall,"end\n"))
+ {
+ bzero(inall, 1024);
+ for(i=0;read(sockfd,&inchar,1)!='\0';i++)
+ {
+ inall[i]=inchar;
+ if(inchar=='\n') break;
+ }
+ fputs(inall,fpa);
+ }
+ if(fpa!=NULL) fclose(fpa);
+ sprintf(temp4,"uudecode %s/.temp.uue",TMP_DIR);
+ system(temp4);
+ sprintf(temp4,"rm -f %s/.temp.uue",TMP_DIR);
+ system(temp4);
+}
+
+char *sscript_login_to_passwd(char *login)
+{
+#ifdef POSIX
+ struct passwd *pw;
+ pw = getpwnam(login);
+ if(pw!=NULL) return pw->pw_passwd;
+#endif
+ return (char *)NULL;
+}
+
+char *sscript_uid_to_login(long my_uid)
+{
+#ifdef POSIX
+ struct passwd *pw;
+ pw = getpwuid(my_uid);
+ if(pw!=NULL) return pw->pw_name;
+#endif
+ return (char *)NULL;
+}
+
+int sscript_sokstat(char *option, int sockfd)
+{
+ int optlen=sizeof(int),optval=1;
+ if(!strcasecmp(option,"sendbuf")) getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&optval, &optlen);
+ else if(!strcasecmp(option,"recvbuf")) getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&optval, &optlen);
+ else if(!strcasecmp(option,"error")) getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char *)&optval, &optlen);
+ else if(!strcasecmp(option,"type")) getsockopt(sockfd, SOL_SOCKET, SO_TYPE, (char *)&optval, &optlen);
+ else optval=-1;
+ return optval;
+}
+
+char *sscript_time_read(int sockfd, int time_sec)
+{
+ struct timeval timeout;
+ int max_fd;
+ fd_set readfs, newfs;
+ timeout.tv_sec=time_sec;
+ timeout.tv_usec=0;
+ FD_ZERO(&readfs);
+ FD_SET(sockfd, &readfs);
+ max_fd = sockfd;
+ memcpy(&newfs, &readfs, sizeof(readfs));
+ select(max_fd+1, &newfs, NULL, NULL, &timeout);
+ if(FD_ISSET (sockfd, &newfs))
+ {
+ read(sockfd, global_var[8], sizeof(global_var[8]));
+ return(global_var[8]);
+ }
+ return("timeout");
+}
+
+void sscript_redir(int sockfd, int rsck)
+{
+ char buf[4096];
+ fd_set readfs, newfs;
+ int max_fd, len;
+ FD_ZERO(&readfs);
+ FD_SET(sockfd, &readfs);
+ FD_SET(rsck, &readfs);
+ if(sockfd>rsck) max_fd = sockfd;
+ else max_fd = rsck;
+ while(1) {
+ memcpy(&newfs, &readfs, sizeof(readfs));
+ select(max_fd+1, &newfs, NULL, NULL, NULL);
+ if(FD_ISSET(sockfd, &newfs))
+ {
+ if((len=read(sockfd, buf, sizeof(buf)))<1) break;
+ if(write(rsck, buf, len)!=len) break;
+ }
+ if(FD_ISSET(rsck, &newfs))
+ {
+ if((len=read(rsck, buf, sizeof(buf)))<1) break;
+ if(write(sockfd, buf, len)!=len) break;
+ }
+ }
+}
+
+void sscript_nodelay(int sockfd)
+{
+ int i;
+ if(( i = fcntl(sockfd, F_GETFL, 0)) == -1);
+ else if (fcntl(sockfd, F_SETFL, i | FNDELAY) == -1);
+}
+
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#define SSCRIPT_SOCKET_FAILED 10
+#define SSCRIPT_BIND_FAILED 11
+#define SSCRIPT_GETSOCKETNAME_FAILED 12
+#define SSCRIPT_FLAGS_FAILED 13
+#define SSCRIPT_CONNECT_FAILED 20
+#define SSCRIPT_UDPSEND_FAILED 31
+#define SSCRIPT_UDPRECEIVE_FAILED 32
+#define SSCRIPT_READ_FAILED 33
+
+#define ABOUT "Socket Script library 2.0 by Patrick Lambert (drow@post.com)"
+#define POSIX
+#define TMP_DIR "."
+
+char *sscript_lindex(char *input_string, int word_number);
+int sscript_connect(char *server, int port, char *virtual);
+int sscript_server(int port);
+int sscript_wait_clients(int sockfd2, int port, int forking);
+char *sscript_get_remote_ip();
+void sscript_disconnect(int sockfd);
+void sscript_dump(int sockfd, char *filename);
+void sscript_ping(char *hostname);
+int sscript_test(char *hostname, int port);
+char *sscript_version();
+char *sscript_read(int sockfd, int chop);
+void sscript_write(int sockfd, char *string);
+int sscript_compare(char *case1, char *case2);
+char *sscript_lrange(char *input_string, int starting_at);
+int sscript_udp_send(char *hostname, int port, char *msg);
+char *sscript_udp_listen(int port);
+char *sscript_icmp_detect();
+char *sscript_resolve_host(char *hostname);
+char *sscript_resolve_ip(char *ip);
+char *sscript_get_localhost();
+void sscript_binary_send(int sockfd, char *string);
+void sscript_binary_get(int sockfd);
+char *sscript_login_to_passwd(char *login);
+char *sscript_uid_to_login(long my_uid);
+int sscript_sokstat(char *option, int sockfd);
+char *sscript_time_read(int sockfd, int time_sec);
+void sscript_redir(int sockfd, int rsck);
+void sscript_nodelay(int sockfd);
--- /dev/null
+ /* compile with: gcc -lsscript -o example example.c */
+
+#include <stdio.h>
+#include <errno.h>
+#include <time.h>
+main(int argc, char *argv[])
+{
+/* initializing variables */
+ char result[255]=".";
+ char *p;
+ int port = atoi(argv[2]);
+ int sockfd=0,i;
+time_t t,d;
+/* connect somewhere */
+ printf("Connecting to %s:%i .. \n", argv[1], port);
+/* call to sscript_connect to connect to the server */
+ sockfd=sscript_connect(sscript_resolve_host(argv[1]),port,NULL);
+
+/* if it returns -1, then print the error code */
+ if(sockfd<1)
+ {
+ printf("An error occured: %d\n",errno);
+ exit(1);
+ }
+
+/* call to sscript_read and copy the result in 'result' */
+ p = (char *)sscript_time_read(sockfd,5);
+ if (p)
+ {
+ strcpy(result,p);
+ t = atol(result);
+ d = t - time(NULL);
+ printf("TS difference from timeserver is %li (%li)\n", d, t);
+ }
+/* print the result */
+/* disconnects */
+ sscript_disconnect(sockfd);
+}
+
--- /dev/null
+#!/bin/sh
+./tsp-skin 6100 ./tsp-server-run &
\ No newline at end of file
--- /dev/null
+main() {
+ printf("%li", time(0));
+}
\ No newline at end of file
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, ircd/channel.h
+ * Copyright (C) 1990 Jarkko Oikarinen
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ */
+
+#ifndef __channel_include__
+#define __channel_include__
+#define CREATE 1 /* whether a channel should be
+ created or just tested for existance */
+
+#define MODEBUFLEN 200
+
+#define NullChn ((aChannel *)0)
+
+#define ChannelExists(n) (find_channel(n, NullChn) != NullChn)
+
+#define IsULine(cptr,sptr) (sptr->flags & FLAGS_ULINE)
+
+/* NOTE: Timestamps will be added to MODE-commands, so never make
+ * RESYNCMODES and MODEPARAMS higher than MAXPARA-3. DALnet servers
+ * before Dreamforge aren't safe with more than six. -Donwulff
+ */
+#include "msg.h"
+#define MAXMODEPARAMS (MAXPARA-2) /* Maximum modes processed */
+#define RESYNCMODES 12 /* Max modes per MODE in resync */
+#define MODEPARAMS 6 /* Max modes from user */
+
+#endif
--- /dev/null
+// $Id$
+#include <windows.h>
+
+
+#define CIOCLASS "CioClass"
+
+#ifndef CIO
+#define CIO
+
+typedef struct tag_CioLine
+{
+ BYTE *Data;
+ WORD Len;
+ struct tag_CioLine *Prev, *Next;
+} CioLine;
+
+typedef struct tag_CioWndInfo
+{
+ CioLine *FirstLine, *CurLine;
+ int Lines, Scroll;
+ int Width, Height, XChar, YChar, YJunk, ScrollMe;
+ HFONT hFont;
+ BYTE FR, FG, FB;
+} CioWndInfo;
+
+#endif
+
--- /dev/null
+// $Id$
+#include "Cio.h"
+
+#define GWL_USER 0
+#define CIO_ADDSTRING WM_USER
+#define CIO_CLEAR WM_USER+1
+
+// Cio_Init.c
+BOOL Cio_Init(HINSTANCE hInstance);
+
+// Cio_Main.c
+LRESULT CALLBACK Cio_WndProc(HWND, UINT, WPARAM, LPARAM);
+HWND Cio_Create(HINSTANCE hInstance, HWND hParent, DWORD Style, int X, int Y, int W, int H);
+BOOL Cio_WndCreate(HWND hWnd);
+BOOL Cio_WndPaint(HWND hWnd);
+BOOL Cio_WndDestroy(HWND hWnd);
+BOOL Cio_WndAddString(HWND hWnd, int Len, char *Buffer);
+BOOL Cio_WndSize(HWND hWnd, LPARAM lParam);
+void Cio_Scroll(HWND hWnd, CioWndInfo *CWI, int Scroll);
+BOOL Cio_PrintF(HWND hWnd, char *InBuf, ...);
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, include/class.h
+ * Copyright (C) 1990 Darren Reed
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ */
+
+#ifndef __class_include__
+#define __class_include__
+
+#ifndef PROTO
+#if __STDC__
+# define PROTO(x) x
+#else
+# define PROTO(x) ()
+#endif
+#endif
+
+typedef struct Class {
+ int class;
+ int conFreq;
+ int pingFreq;
+ int maxLinks;
+ long maxSendq;
+ int links;
+ struct Class *next;
+} aClass;
+
+#define Class(x) ((x)->class)
+#define ConFreq(x) ((x)->conFreq)
+#define PingFreq(x) ((x)->pingFreq)
+#define MaxLinks(x) ((x)->maxLinks)
+#define MaxSendq(x) ((x)->maxSendq)
+#define Links(x) ((x)->links)
+
+#define ConfLinks(x) (Class(x)->links)
+#define ConfMaxLinks(x) (Class(x)->maxLinks)
+#define ConfClass(x) (Class(x)->class)
+#define ConfConFreq(x) (Class(x)->conFreq)
+#define ConfPingFreq(x) (Class(x)->pingFreq)
+#define ConfSendq(x) (Class(x)->maxSendq)
+
+#define FirstClass() classes
+#define NextClass(x) ((x)->next)
+
+extern aClass *classes;
+
+extern aClass *find_class PROTO((int));
+extern int get_conf_class PROTO((aConfItem *));
+extern int get_client_class PROTO((aClient *));
+extern int get_client_ping PROTO((aClient *));
+extern int get_con_freq PROTO((aClass *));
+extern void add_class PROTO((int, int, int, int, long));
+extern void check_class PROTO((void));
+extern void initclass PROTO((void));
+
+#endif /* __class_include__ */
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, include/common.h
+ * Copyright (C) 1990 Armin Gruner
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ */
+
+#ifndef __common_include__
+#define __common_include__
+
+#include <time.h>
+#ifdef _WIN32
+#include <malloc.h>
+#include <windows.h>
+#include <winsock.h>
+#include <process.h>
+#include <io.h>
+#include "struct.h"
+#endif
+#include "dynconf.h"
+
+#ifdef PARAMH
+#include <sys/param.h>
+#endif
+
+#ifndef PROTO
+#if __STDC__
+# define PROTO(x) x
+#else
+# define PROTO(x) ()
+#endif
+#endif
+
+#define ID_CVS(x) static char id_cvs[] = x
+#define ID_Copyright(x) static char id_copyright[] = x
+#define ID_Notes(x) static char id_notes[] = x
+
+#define BMAGIC 0x4675636B596F754661736369737473
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifdef TRUE
+#undef TRUE
+#endif
+
+#ifdef FALSE
+#undef FALSE
+#endif
+
+#define FALSE (0)
+#define TRUE (!FALSE)
+
+#ifndef UNSURE
+#define UNSURE (2)
+#endif
+
+#if 0
+#ifndef MALLOCH
+char *malloc(), *calloc();
+void free();
+#else
+#include MALLOCH
+#endif
+#endif
+
+
+extern int match PROTO((char *, char *));
+#define mycmp(a,b) \
+ ( (toupper((a)[0])!=toupper((b)[0])) || smycmp((a)+1,(b)+1) )
+extern int smycmp PROTO((char *, char *));
+#ifndef GLIBC2_x
+extern int myncmp PROTO((char *, char *, int));
+#endif
+
+#ifdef NEED_STRTOK
+extern char *strtok2 PROTO((char *, char *));
+#endif
+#ifdef NEED_STRTOKEN
+extern char *strtoken PROTO((char **, char *, char *));
+#endif
+#ifdef NEED_INET_ADDR
+extern unsigned long inet_addr PROTO((char *));
+#endif
+
+#if defined(NEED_INET_NTOA) || defined(NEED_INET_NETOF) && !defined(_WIN32)
+#include <netinet/in.h>
+#endif
+#ifdef NEED_INET_NTOA
+extern char *inet_ntoa PROTO((struct in_addr));
+#endif
+
+#ifdef NEED_INET_NETOF
+extern int inet_netof PROTO((struct in_addr));
+#endif
+
+int global_count, max_global_count;
+extern char *myctime PROTO((time_t));
+extern char *strtoken PROTO((char **, char *, char *));
+
+#define PRECISE_CHECK
+
+#ifndef MAX
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+#define DupString(x,y) do{x=MyMalloc(strlen(y)+1);(void)strcpy(x,y);}while(0)
+
+#ifdef USE_CASETABLES
+extern int casetable;
+extern u_char *tolowertab, tolowertab1[], tolowertab2[];
+extern u_char *touppertab, touppertab1[], touppertab2[];
+#else
+extern u_char tolowertab[], touppertab[];
+#endif
+
+#undef tolower
+#define tolower(c) (tolowertab[(c)])
+
+#undef toupper
+#define toupper(c) (touppertab[(c)])
+
+#undef isalpha
+#undef isdigit
+#undef isxdigit
+#undef isalnum
+#undef isprint
+#undef isascii
+#undef isgraph
+#undef ispunct
+#undef islower
+#undef isupper
+#undef isspace
+#undef iscntrl
+
+extern unsigned char char_atribs[];
+
+#define PRINT 1
+#define CNTRL 2
+#define ALPHA 4
+#define PUNCT 8
+#define DIGIT 16
+#define SPACE 32
+#define ALLOW 64
+
+#ifndef KLINE_TEMP
+#define KLINE_PERM 0
+#define KLINE_TEMP 1
+#define KLINE_AKILL 2
+#define KLINE_EXCEPT 3
+#endif
+
+#define iscntrl(c) (char_atribs[(u_char)(c)]&CNTRL)
+#define isallowed(c) (char_atribs[(u_char)(c)]&ALLOW)
+#define isalpha(c) (char_atribs[(u_char)(c)]&ALPHA)
+#define isspace(c) (char_atribs[(u_char)(c)]&SPACE)
+#define islower(c) ((char_atribs[(u_char)(c)]&ALPHA) && ((u_char)(c) > 0x5f))
+#define isupper(c) ((char_atribs[(u_char)(c)]&ALPHA) && ((u_char)(c) < 0x60))
+#define isdigit(c) (char_atribs[(u_char)(c)]&DIGIT)
+#define isxdigit(c) (isdigit(c) || 'a' <= (c) && (c) <= 'f' || \
+ 'A' <= (c) && (c) <= 'F')
+#define isalnum(c) (char_atribs[(u_char)(c)]&(DIGIT|ALPHA))
+#define isprint(c) (char_atribs[(u_char)(c)]&PRINT)
+#define isascii(c) ((u_char)(c) >= 0 && (u_char)(c) <= 0x7f)
+#define isgraph(c) ((char_atribs[(u_char)(c)]&PRINT) && ((u_char)(c) != 0x32))
+#define ispunct(c) (!(char_atribs[(u_char)(c)]&(CNTRL|ALPHA|DIGIT)))
+
+extern char *MyMalloc();
+extern void flush_connections();
+extern struct SLink *find_user_link(/* struct SLink *, struct Client * */);
+
+/*
+ * Protocol support text. DO NO CHANGE THIS unless you know what
+ * you are doing.
+ */
+#define PROTOCTL_CLIENT "TOKEN WATCH=128 SAFELIST HCN PREFIX=@+%"
+#define PROTOCTL_SERVER "NOQUIT TOKEN NICKv2 SJOIN SJOIN2"
+
+#ifdef _WIN32
+/*
+ * Used to display a string to the GUI interface.
+ * Windows' internal strerror() function doesn't work with socket errors.
+ */
+extern int DisplayString(HWND hWnd, char *InBuf, ...);
+#undef strerror
+#endif
+
+#if defined(__FreeBSD__) || defined(__APPLE__)
+extern char *malloc_options;
+#endif
+
+extern int lu_noninv, lu_inv, lu_serv, lu_oper,
+ lu_unknown, lu_channel, lu_lu, lu_lulocal, lu_lserv,
+ lu_clu, lu_mlu, lu_cglobalu, lu_mglobalu;
+
+time_t now;
+
+#endif /* __common_include__ */
--- /dev/null
+/*
+ * IRC - Internet Relay Chat, include/config.h
+ * Copyright (C) 1990 Jarkko Oikarinen
+ *
+ * $Id$
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __config_include__
+#define __config_include__
+
+#include "setup.h"
+#include "settings.h"
+/*
+ *
+ * NOTICE
+ *
+ * Under normal conditions, you should not have to edit this file. Run
+ * the Config script in the root directory instead!
+ *
+ * Windows is not a normal condition, edit this file if you use it. :-)
+ *
+ *
+ */
+/*
+ * To windows porters:
+ * You can specify name and url for their diff wircd sites
+ * #undef WIN32_SPECIFY for not having any notice about it in the wIRCd
+ * --Techie
+ */
+#undef WIN32_SPECIFY
+
+#ifdef WIN32_SPECIFY
+#define WIN32_PORTER ""
+#define WIN32_URL ""
+#endif
+
+ /*
+ * Define this if you're testing/debugging/programming.
+ */
+#undef DEBUG
+
+/* Type of host. These should be made redundant somehow. -avalon */
+
+/* BSD Nothing Needed 4.{2,3} BSD, SunOS 3.x, 4.x */
+/* HPUX Nothing needed (A.08/A.09) */
+/* ULTRIX Nothing needed (4.2) */
+/* OSF Nothing needed (1.2) */
+/* #undef AIX /* IBM ugly so-called Unix, AIX */
+/* #undef MIPS /* MIPS Unix */
+/* SGI Nothing needed (IRIX 4.0.4) */
+/* #undef SVR3 /* SVR3 stuff - being worked on where poss. */
+/* #undef DYNIXPTX /* Sequents Brain-dead Posix implement. */
+/* #undef SOL20 /* Solaris2 */
+/* #undef ESIX /* ESIX */
+/* #undef NEXT /* NeXTStep */
+/* #undef SVR4 /* */
+
+/* Additional flags to give FreeBSD's malloc, only play with this if you
+ * know what you're doing.
+ */
+
+#define MALLOC_FLAGS_EXTRA ""
+/*
+ ConferenceRoom Java Client Hack -Fish
+ if you want it to work #define CONFROOM_JAVA_PORT <port>
+ where port MUST be a seperate port java clients connects on ..
+*/
+#undef CONFROOM_JAVA_PORT
+
+/*
+ REMOVE_ADVERTISING -ice
+ If you send a text to a user like "irc.roxnet.org" it will show up as "irc.******.org"
+ Off by default --stskeeps
+*/
+#undef REMOVE_ADVERTISING
+
+/*
+ UnrealIRCd WebTV support
+*/
+#undef WEBTV
+
+#ifdef WEBTV
+/* enable /msg irc user */
+#define WEBTV_IRCUSER
+/* NOTICE's dont exist (except from server) */
+#define WEBTV_NONOTICE
+#endif
+
+/*
+ dog3/comstud ircd fdlists
+ undef this to make them work
+*/
+
+#undef NO_FDLIST
+/*
+ OPER_NO_HIDING
+ This makes +I an unexisting mode
+ On by default --stskeeps
+*/
+#undef OPER_NO_HIDING
+
+/*
+ * Admin's chat...
+ */
+#define ADMINCHAT 1
+
+/*
+ Remote rehash
+*/
+#define REMOTE_REHASH
+
+/*
+ * No spoof code
+ *
+ * This enables the spoof protection.
+ */
+/* #define NOSPOOF 1 /* */
+
+/*
+ *
+ * This controls the "nospoof" system. These numbers are "seeds" of the
+ * "random" number generating formula. Choose any number you like in the
+ * range of 0x00000000 to 0xFFFFFFFF. Don't tell anyone these numbers, and
+ * don't use the default ones. Change both #define NOSPOOF... lines below.
+ *
+ * Other data is mixed in as well, but these guarantee a per-server secret.
+ * Also, these values need not remain constant over compilations... Change
+ * them as often as you like.
+ */
+#ifdef NOSPOOF
+
+#ifndef NOSPOOF_SEED01
+#define NOSPOOF_SEED01 0x12345678
+#endif
+
+#ifndef NOSPOOF_SEED02
+#define NOSPOOF_SEED02 0x87654321
+#endif
+
+#endif /* NOSPOOF */
+
+/*
+ * HOSTILENAME - Define this if you want the hostile username patch included,
+ * it will strip characters that are not 0-9,a-z,A-Z,_,- or .
+ */
+#define HOSTILENAME /* */
+
+/*
+ * Define this to prevent mixed case userids that clonebots use. However
+ * this affects the servers running telclients WLD* FIN* etc.
+ */
+#undef DISALLOW_MIXED_CASE
+
+/*
+ * Define this if you wish to ignore the case of the first character of
+ * the user id when disallowing mixed case. This allows PC users to
+ * enter the more intuitive first name with the first letter capitalised
+ */
+#define IGNORE_CASE_FIRST_CHAR
+
+/*
+** Nick flood limit
+** Minimum time between nick changes.
+** (The first two changes are allowed quickly after another however).
+**
+** Define NICK_DELAY if you want this feature.
+*/
+
+#define NICK_DELAY 15 /* recommended value 15 */
+
+/*
+ * Define this if you wish to output a *file* to a K lined client rather
+ * than the K line comment (the comment field is treated as a filename)
+ */
+#undef COMMENT_IS_FILE
+
+
+/* Do these work? I dunno... */
+
+/* #undef VMS /* Should work for IRC client, not server */
+/* #undef MAIL50 /* If you're running VMS 5.0 */
+/* #undef PCS /* PCS Cadmus MUNIX, use with BSD flag! */
+
+/*
+ * NOTE: On some systems, valloc() causes many problems.
+ */
+#undef VALLOC /* Define this if you have valloc(3) */
+
+/*
+ * read/write are restarted after signals defining this 1, gets
+ * siginterrupt call compiled, which attempts to remove this
+ * behaviour (apollo sr10.1/bsd4.3 needs this)
+ */
+#ifdef APOLLO
+#define RESTARTING_SYSTEMCALLS
+#endif
+
+/*
+ * If your host supports varargs and has vsprintf(), vprintf() and vscanf()
+ * C calls in its library, then you can define USE_VARARGS to use varargs
+ * instead of imitation variable arg passing.
+#define USE_VARARGS
+
+ * NOTE: with current server code, varargs doesn't survive because it can't
+ * be used in a chain of 3 or more funtions which all have a variable
+ * number of params. If anyone has a solution to this, please notify
+ * the maintainer.
+ */
+
+/* #undef DEBUGMODE /* define DEBUGMODE to enable debugging mode.*/
+
+/*
+ * defining FORCE_CORE will automatically "unlimit core", forcing the
+ * server to dump a core file whenever it has a fatal error. -mlv
+ */
+#define FORCE_CORE
+
+/*
+ * Full pathnames and defaults of irc system's support files. Please note that
+ * these are only the recommened names and paths. Change as needed.
+ * You must define these to something, even if you don't really want them.
+ */
+#define CPATH "ircd.conf" /* server configuration file */
+#define MPATH "ircd.motd" /* server MOTD file */
+#define RPATH "ircd.rules" /* server rules file */
+#define ZPATH "ircd.notes" /* server notes */
+#define ZCONF "networks/unrealircd.conf" /* ircd configuration .. */
+#define OPATH "oper.motd" /* Operators MOTD file */
+#define LPATH "debug.log" /* Where the debug file lives, if DEBUGMODE */
+#define PPATH "ircd.pid" /* file for server pid */
+#define lPATH "ircd.log" /* server log file */
+#define VPATH "ircd.svsmotd" /* Services MOTD append. */
+#define IRCDTUNE "ircd.tune" /* tuning .. */
+
+/*
+ * Define this filename to maintain a list of persons who log
+ * into this server. Logging will stop when the file does not exist.
+ * Logging will be disable also if you do not define this.
+ * FNAME_USERLOG just logs user connections, FNAME_OPERLOG logs every
+ * successful use of /oper. These are either full paths or files within DPATH.
+ */
+#define FNAME_USERLOG "users.log"
+#define FNAME_OPERLOG "opers.log"
+
+/* FAILOPER_WARN
+ *
+ * When defined, warns users on a failed oper attempt that it was/is logged
+ * Only works when FNAME_OPERLOG is defined, and a logfile exists.
+ * NOTE: Failed oper attempts are logged regardless.
+ */
+#define FAILOPER_WARN
+
+/* CHROOTDIR
+ *
+ * Define for value added security if you are a rooter.
+ *
+ * All files you access must be in the directory you define as DPATH.
+ * (This may effect the PATH locations above, though you can symlink it)
+ *
+ * You may want to define IRC_UID and IRC_GID
+ */
+/* #define CHROOTDIR /* */
+
+/* SHOW_INVISIBLE_LUSERS
+ *
+ * As defined this will show the correct invisible count for anyone who does
+ * LUSERS on your server. On a large net this doesnt mean much, but on a
+ * small net it might be an advantage to undefine it.
+ * (This will get defined for you if you're using userload (stats w). -mlv)
+ */
+#define SHOW_INVISIBLE_LUSERS
+
+
+/* OPER_* defines
+ *
+ * See ./docs/example.conf for examples of how to restrict access for
+ * your IRC Operators
+ */
+
+/* MAXIMUM LINKS
+ *
+ * This define is useful for leaf nodes and gateways. It keeps you from
+ * connecting to too many places. It works by keeping you from
+ * connecting to more than "n" nodes which you have C:blah::blah:6667
+ * lines for.
+ *
+ * Note that any number of nodes can still connect to you. This only
+ * limits the number that you actively reach out to connect to.
+ *
+ * Leaf nodes are nodes which are on the edge of the tree. If you want
+ * to have a backup link, then sometimes you end up connected to both
+ * your primary and backup, routing traffic between them. To prevent
+ * this, #define MAXIMUM_LINKS 1 and set up both primary and
+ * secondary with C:blah::blah:6667 lines. THEY SHOULD NOT TRY TO
+ * CONNECT TO YOU, YOU SHOULD CONNECT TO THEM.
+ *
+ * Gateways such as the server which connects Australia to the US can
+ * do a similar thing. Put the American nodes you want to connect to
+ * in with C:blah::blah:6667 lines, and the Australian nodes with
+ * C:blah::blah lines. Have the Americans put you in with C:blah::blah
+ * lines. Then you will only connect to one of the Americans.
+ *
+ * This value is only used if you don't have server classes defined, and
+ * a server is in class 0 (the default class if none is set).
+ *
+ */
+
+#define MAXIMUM_LINKS 1
+
+/*
+ * NOTE: defining CMDLINE_CONFIG and installing ircd SUID or SGID is a MAJOR
+ * security problem - they can use the "-f" option to read any files
+ * that the 'new' access lets them. Note also that defining this is
+ * a major security hole if your ircd goes down and some other user
+ * starts up the server with a new conf file that has some extra
+ * O-lines. So don't use this unless you're debugging.
+ */
+#define CMDLINE_CONFIG /* allow conf-file to be specified on command line */
+
+/*
+ * To use m4 as a preprocessor on the ircd.conf file, define M4_PREPROC.
+ * The server will then call m4 each time it reads the ircd.conf file,
+ * reading m4 output as the server's ircd.conf file.
+ */
+#undef M4_PREPROC
+
+/*
+ * If you wish to have the server send 'vital' messages about server
+ * through syslog, define USE_SYSLOG. Only system errors and events critical
+ * to the server are logged although if this is defined with FNAME_USERLOG,
+ * syslog() is used instead of the above file. It is not recommended that
+ * this option is used unless you tell the system administrator beforehand
+ * and obtain their permission to send messages to the system log files.
+ */
+#ifndef _WIN32
+#undef USE_SYSLOG
+#endif
+
+#ifdef USE_SYSLOG
+/*
+ * If you use syslog above, you may want to turn some (none) of the
+ * spurious log messages for KILL/SQUIT off.
+ */
+#undef SYSLOG_KILL /* log all operator kills to syslog */
+#undef SYSLOG_SQUIT /* log all remote squits for all servers to syslog */
+#undef SYSLOG_CONNECT /* log remote connect messages for other all servs */
+#undef SYSLOG_USERS /* send userlog stuff to syslog */
+#undef SYSLOG_OPER /* log all users who successfully become an Op */
+
+/*
+ * If you want to log to a different facility than DAEMON, change
+ * this define.
+ */
+#define LOG_FACILITY LOG_DAEMON
+#endif /* USE_SYSLOG */
+
+/*
+ * IDLE_FROM_MSG
+ *
+ * Idle-time nullified only from privmsg, if undefined idle-time
+ * is nullified from everything except ping/pong.
+ * Added 3.8.1992, kny@cs.hut.fi (nam)
+ */
+#define IDLE_FROM_MSG
+
+/*
+ * Size of the LISTEN request. Some machines handle this large
+ * without problem, but not all. It defaults to 5, but can be
+ * raised if you know your machine handles it.
+ */
+#ifndef LISTEN_SIZE
+#define LISTEN_SIZE 5
+#endif
+
+/*
+ * Max amount of internal send buffering when socket is stuck (bytes)
+ */
+#ifndef MAXSENDQLENGTH
+#define MAXSENDQLENGTH 3000000
+#endif
+/*
+ * BUFFERPOOL is the maximum size of the total of all sendq's.
+ * Recommended value is 2 * MAXSENDQLENGTH, for hubs, 5 *.
+ */
+#ifndef BUFFERPOOL
+#define BUFFERPOOL (9 * MAXSENDQLENGTH)
+#endif
+
+/*
+ * IRC_UID
+ *
+ * If you start the server as root but wish to have it run as another user,
+ * define IRC_UID to that UID. This should only be defined if you are running
+ * as root and even then perhaps not.
+ */
+/* #undef IRC_UID /* */
+/* #undef IRC_GID /* */
+
+/*
+ * CLIENT_FLOOD
+ *
+ * this controls the number of bytes the server will allow a client to
+ * send to the server without processing before disconnecting the client for
+ * flooding it. Values greater than 8000 make no difference to the server.
+ */
+#define CLIENT_FLOOD 8000
+
+/* Define this if you want the server to accomplish ircII standard */
+/* Sends an extra NOTICE in the beginning of client connection */
+#undef IRCII_KLUDGE
+
+/*
+ * Define your network service names here.
+ */
+#define ChanServ "ChanServ"
+#define MemoServ "MemoServ"
+#define NickServ "NickServ"
+#define OperServ "OperServ"
+#define HelpServ "HelpServ"
+#define StatServ "StatServ"
+
+/*
+ * How many seconds in between simultaneous nick changes?
+ */
+#define NICK_CHANGE_DELAY 30
+
+/*
+ * How many open targets can one nick have for messaging nicks and
+ * inviting them?
+ */
+
+#define MAXTARGETS 20
+#define TARGET_DELAY 120
+
+/*
+ * Would you like all clients to see the progress of their connections?
+ */
+
+#define SHOWCONNECTINFO
+
+/*
+ * SOCKS proxy checker
+ *
+ * At the moment this isn't an ideal solution, however it's better
+ * than nothing. Smaller servers shouldn't notice much of a performance
+ * hit, larger servers might have to reduce their Y-lines. In either
+ * case it's advisable to increase the number of FD's you define by
+ * about 10%.
+ *
+ * This determines the port on the local ircd machine that the open
+ * SOCKS server test attempts to connect back to. The default should
+ * be fine except for those unusual situations where the default
+ * port is in use for some reason.
+ *
+ * Undefining this will eliminate the checker from ircd.
+ */
+#define SOCKSPORT 6013
+
+/* Define default Z:line time for SOCKS -taz */
+#define ZLINE_TIME 300
+
+/* STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP */
+
+/* You shouldn't change anything below this line, unless absolutely needed. */
+
+/*
+ * Port where ircd resides. NOTE: This *MUST* be greater than 1024 if you
+ * plan to run ircd under any other uid than root.
+ */
+#define PORTNUM 6667 /* 6667 is default */
+
+/*
+ * Maximum number of network connections your server will allow. This should
+ * never exceed max. number of open file descrpitors and wont increase this.
+ * Should remain LOW as possible. Most sites will usually have under 30 or so
+ * connections. A busy hub or server may need this to be as high as 50 or 60.
+ * Making it over 100 decreases any performance boost gained from it being low.
+ * if you have a lot of server connections, it may be worth splitting the load
+ * over 2 or more servers.
+ * 1 server = 1 connection, 1 user = 1 connection.
+ * This should be at *least* 3: 1 listen port, 1 dns port + 1 client
+ *
+ * Note: this figure will be too high for most systems. If you get an
+ * fd-related error on compile, change this to 256.
+ *
+ * Windows users: This should be a fairly high number. Some operations
+ * will slow down because of this, but it is _required_ because of the way
+ * windows NT(and possibly 95) allocate fd handles. A good number is 16384.
+ */
+#ifndef MAXCONNECTIONS
+#define MAXCONNECTIONS 1024
+#endif
+
+/*
+ * this defines the length of the nickname history. each time a user changes
+ * nickname or signs off, their old nickname is added to the top of the list.
+ * The following sizes are recommended:
+ * 8MB or less core memory : 500 (at least 1/4 of max users)
+ * 8MB-16MB core memory : 500-750 (1/4 -> 1/2 of max users)
+ * 16MB-32MB core memory : 750-1000 (1/2 -> 3/4 of max users)
+ * 32MB or more core memory : 1000+ (> 3/4 if max users)
+ * where max users is the expected maximum number of users.
+ * (100 nicks/users ~ 25k)
+ * NOTE: this is directly related to the amount of memory ircd will use whilst
+ * resident and running - it hardly ever gets swapped to disk! You can
+ * ignore these recommendations- they only are meant to serve as a guide
+ * NOTE: But the *Minimum* ammount should be 100, in order to make nick
+ * chasing possible for mode and kick.
+ */
+#ifndef NICKNAMEHISTORYLENGTH
+#define NICKNAMEHISTORYLENGTH 2000
+#endif
+
+/*
+ * Time interval to wait and if no messages have been received, then check for
+ * PINGFREQUENCY and CONNECTFREQUENCY
+ */
+#define TIMESEC 60 /* Recommended value: 60 */
+
+/*
+ * If daemon doesn't receive anything from any of its links within
+ * PINGFREQUENCY seconds, then the server will attempt to check for
+ * an active link with a PING message. If no reply is received within
+ * (PINGFREQUENCY * 2) seconds, then the connection will be closed.
+ */
+#define PINGFREQUENCY 120 /* Recommended value: 120 */
+
+/*
+ * If the connection to to uphost is down, then attempt to reconnect every
+ * CONNECTFREQUENCY seconds.
+ */
+#define CONNECTFREQUENCY 600 /* Recommended value: 600 */
+
+/*
+ * Often net breaks for a short time and it's useful to try to
+ * establishing the same connection again faster than CONNECTFREQUENCY
+ * would allow. But, to keep trying on bad connection, we require
+ * that connection has been open for certain minimum time
+ * (HANGONGOODLINK) and we give the net few seconds to steady
+ * (HANGONRETRYDELAY). This latter has to be long enough that the
+ * other end of the connection has time to notice it broke too.
+ */
+#define HANGONRETRYDELAY 20 /* Recommended value: 20 seconds */
+#define HANGONGOODLINK 300 /* Recommended value: 5 minutes */
+
+/*
+ * Number of seconds to wait for write to complete if stuck.
+ */
+#define WRITEWAITDELAY 15 /* Recommended value: 15 */
+
+/*
+ * Number of seconds to wait for a connect(2) call to complete.
+ * NOTE: this must be at *LEAST* 10. When a client connects, it has
+ * CONNECTTIMEOUT - 10 seconds for its host to respond to an ident lookup
+ * query and for a DNS answer to be retrieved.
+ */
+#define CONNECTTIMEOUT 90 /* Recommended value: 90 */
+
+/*
+ * Max time from the nickname change that still causes KILL
+ * automaticly to switch for the current nick of that user. (seconds)
+ */
+#define KILLCHASETIMELIMIT 90 /* Recommended value: 90 */
+
+/*
+ * Max number of channels a user is allowed to join.
+ */
+#define MAXCHANNELSPERUSER 10 /* Recommended value: 10 */
+
+/*
+ * SendQ-Always causes the server to put all outbound data into the sendq and
+ * flushing the sendq at the end of input processing. This should cause more
+ * efficient write's to be made to the network.
+ * There *shouldn't* be any problems with this method.
+ * -avalon
+ */
+#define SENDQ_ALWAYS
+
+/* ------------------------- END CONFIGURATION SECTION -------------------- */
+#define MOTD MPATH
+#define RULES RPATH
+#define SNOTES ZPATH
+#define MYNAME SPATH
+#define CONFIGFILE CPATH
+#define IRCD_PIDFILE PPATH
+#define GLINE_LOG GPATH
+
+#ifdef __osf__
+#define OSF
+/* OSF defines BSD to be its version of BSD */
+#undef BSD
+#include <sys/param.h>
+#ifndef BSD
+#define BSD
+#endif
+#endif
+
+#ifdef _SEQUENT_ /* Dynix 1.4 or 2.0 Generic Define.. */
+#undef BSD
+#define SYSV /* Also #define SYSV */
+#endif
+
+#ifdef ultrix
+#define ULTRIX
+#endif
+
+#ifdef __hpux
+#define HPUX
+#endif
+
+#ifdef sgi
+#define SGI
+#endif
+
+#ifndef KLINE_TEMP
+#define KLINE_PERM 0
+#define KLINE_TEMP 1
+#define KLINE_AKILL 2
+#define KLINE_EXCEPT 3
+#endif
+
+#ifdef DEBUGMODE
+extern void debug();
+# define Debug(x) debug x
+# define LOGFILE LPATH
+#else
+# define Debug(x) ;
+# if VMS
+# define LOGFILE "NLA0:"
+# else
+# define LOGFILE "/dev/null"
+# endif
+#endif
+
+#ifndef ENABLE_SUMMON
+# undef LEAST_IDLE
+#endif
+
+#if defined(mips) || defined(PCS)
+#undef SYSV
+#endif
+
+#ifdef MIPS
+#undef BSD
+#define BSD 1 /* mips only works in bsd43 environment */
+#endif
+
+#ifdef sequent /* Dynix (sequent OS) */
+#define SEQ_NOFILE 128 /* set to your current kernel impl, */
+#endif /* max number of socket connections */
+
+#ifdef _SEQUENT_
+#define DYNIXPTX
+#endif
+
+#ifdef BSD_RELIABLE_SIGNALS
+# if defined(SYSV_UNRELIABLE_SIGNALS) || defined(POSIX_SIGNALS)
+error You stuffed up config.h signals #defines use only one.
+# endif
+#define HAVE_RELIABLE_SIGNALS
+#endif
+
+#ifdef SYSV_UNRELIABLE_SIGNALS
+# ifdef POSIX_SIGNALS
+error You stuffed up config.h signals #defines use only one.
+# endif
+#undef HAVE_RELIABLE_SIGNALS
+#endif
+
+#ifdef POSIX_SIGNALS
+#define HAVE_RELIABLE_SIGNALS
+#endif
+
+/*
+ * safety margin so we can always have one spare fd, for motd/authd or
+ * whatever else. -4 allows "safety" margin of 1 and space reserved.
+ */
+#define MAXCLIENTS (MAXCONNECTIONS-4)
+
+#ifdef HAVECURSES
+# define DOCURSES
+#else
+# undef DOCURSES
+#endif
+
+#ifdef HAVETERMCAP
+# define DOTERMCAP
+#else
+# undef DOTERMCAP
+#endif
+
+# define stricmp strcasecmp
+# define strnicmp strncasecmp
+
+#if defined(CLIENT_FLOOD)
+# if (CLIENT_FLOOD > 8000)
+# define CLIENT_FLOOD 8000
+# else
+# if (CLIENT_FLOOD < 512)
+error CLIENT_FLOOD needs redefining.
+# endif
+# endif
+#else
+error CLIENT_FLOOD undefined
+#endif
+#if (NICKNAMEHISTORYLENGTH < 100)
+# define NICKNAMEHISTORYLENGTH 100
+#endif
+
+/*
+ * Some ugliness for AIX platforms.
+ */
+#ifdef AIX
+# include <sys/machine.h>
+# if BYTE_ORDER == BIG_ENDIAN
+# define BIT_ZERO_ON_LEFT
+# endif
+# if BYTE_ORDER == LITTLE_ENDIAN
+# define BIT_ZERO_ON_RIGHT
+# endif
+/*
+ * this one is used later in sys/types.h (or so i believe). -avalon
+ */
+# define BSD_INCLUDES
+#endif
+
+/*
+ * Cleaup for WIN32 platform.
+ */
+#ifdef _WIN32
+# undef FORCE_CORE
+#endif
+/* use cflag longmodes */
+#define USE_LONGMODE
+#define Reg1 register
+#define Reg2 register
+#define Reg3 register
+#define Reg4 register
+#define Reg5 register
+#define Reg6 register
+#define Reg7 register
+#define Reg8 register
+#define Reg9 register
+#define Reg10 register
+
+#endif /* __config_include__ */
+
+
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, include/dbuf.h
+ * Copyright (C) 1990 Markku Savela
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ */
+
+#ifndef __dbuf_include__
+#define __dbuf_include__
+
+#ifndef PROTO
+#ifdef __STDC__
+# define PROTO(x) x
+#else
+# define PROTO(x) ()
+#endif /* __STDC__ */
+#endif /* ! PROTO */
+
+/*
+** dbuf is a collection of functions which can be used to
+** maintain a dynamic buffering of a byte stream.
+** Functions allocate and release memory dynamically as
+** required [Actually, there is nothing that prevents
+** this package maintaining the buffer on disk, either]
+*/
+
+/*
+** These structure definitions are only here to be used
+** as a whole, *DO NOT EVER REFER TO THESE FIELDS INSIDE
+** THE STRUCTURES*! It must be possible to change the internal
+** implementation of this package without changing the
+** interface.
+*/
+#if !defined(_SEQUENT_)
+typedef struct dbuf
+ {
+ u_int length; /* Current number of bytes stored */
+ u_int offset; /* Offset to the first byte */
+ struct dbufbuf *head; /* First data buffer, if length > 0 */
+ /* added by mnystrom@mit.edu: */
+ struct dbufbuf *tail; /* last data buffer, if length > 0 */
+ } dbuf;
+#else
+typedef struct dbuf
+ {
+ uint length; /* Current number of bytes stored */
+ uint offset; /* Offset to the first byte */
+ struct dbufbuf *head; /* First data buffer, if length > 0 */
+ /* added by mnystrom@mit.edu: */
+ struct dbufbuf *tail; /* last data buffer, if length > 0 */
+ } dbuf;
+#endif
+/*
+** And this 'dbufbuf' should never be referenced outside the
+** implementation of 'dbuf'--would be "hidden" if C had such
+** keyword...
+** If it was possible, this would compile to be exactly 1 memory
+** page in size. 2048 bytes seems to be the most common size, so
+** as long as a pointer is 4 bytes, we get 2032 bytes for buffer
+** data after we take away a bit for malloc to play with. -avalon
+*/
+typedef struct dbufbuf
+ {
+ struct dbufbuf *next; /* Next data buffer, NULL if this is last */
+ char data[2032]; /* Actual data stored here */
+ } dbufbuf;
+
+/*
+** dbuf_put
+** Append the number of bytes to the buffer, allocating more
+** memory as needed. Bytes are copied into internal buffers
+** from users buffer.
+**
+** returns > 0, if operation successfull
+** < 0, if failed (due memory allocation problem)
+*/
+int dbuf_put PROTO((dbuf *, char *, int));
+ /* Dynamic buffer header */
+ /* Pointer to data to be stored */
+ /* Number of bytes to store */
+
+/*
+** dbuf_get
+** Remove number of bytes from the buffer, releasing dynamic
+** memory, if applicaple. Bytes are copied from internal buffers
+** to users buffer.
+**
+** returns the number of bytes actually copied to users buffer,
+** if >= 0, any value less than the size of the users
+** buffer indicates the dbuf became empty by this operation.
+**
+** Return 0 indicates that buffer was already empty.
+**
+** Negative return values indicate some unspecified
+** error condition, rather fatal...
+*/
+int dbuf_get PROTO(( dbuf *, char *, int));
+ /* Dynamic buffer header */
+ /* Pointer to buffer to receive the data */
+ /* Max amount of bytes that can be received */
+
+/*
+** dbuf_map, dbuf_delete
+** These functions are meant to be used in pairs and offer
+** a more efficient way of emptying the buffer than the
+** normal 'dbuf_get' would allow--less copying needed.
+**
+** map returns a pointer to a largest contiguous section
+** of bytes in front of the buffer, the length of the
+** section is placed into the indicated "long int"
+** variable. Returns NULL *and* zero length, if the
+** buffer is empty.
+**
+** delete removes the specified number of bytes from the
+** front of the buffer releasing any memory used for them.
+**
+** Example use (ignoring empty condition here ;)
+**
+** buf = dbuf_map(&dyn, &count);
+** <process N bytes (N <= count) of data pointed by 'buf'>
+** dbuf_delete(&dyn, N);
+**
+** Note: delete can be used alone, there is no real binding
+** between map and delete functions...
+*/
+char *dbuf_map PROTO((dbuf *, int *));
+ /* Dynamic buffer header */
+ /* Return number of bytes accessible */
+
+int dbuf_delete PROTO((dbuf *, int));
+ /* Dynamic buffer header */
+ /* Number of bytes to delete */
+
+/*
+** DBufLength
+** Return the current number of bytes stored into the buffer.
+** (One should use this instead of referencing the internal
+** length field explicitly...)
+*/
+#define DBufLength(dyn) ((dyn)->length)
+
+/*
+** DBufClear
+** Scratch the current content of the buffer. Release all
+** allocated buffers and make it empty.
+*/
+#define DBufClear(dyn) dbuf_delete((dyn),DBufLength(dyn))
+
+extern int dbuf_getmsg PROTO((dbuf *, char *, int));
+
+#endif /* __dbuf_include__ */
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, include/dynconf.h
+ * Copyright (C) 1999 Carsten Munk
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ */
+
+
+#define DYNCONF_H
+typedef struct zNetwork aNetwork;
+struct zNetwork {
+ char *x_ircnetwork;
+ char *x_defserv;
+ char *x_services_name;
+ char *x_oper_host;
+ char *x_admin_host;
+ char *x_locop_host;
+ char *x_sadmin_host;
+ char *x_netadmin_host;
+ char *x_coadmin_host;
+ char *x_techadmin_host;
+ char *x_hidden_host;
+ char *x_netdomain;
+ char *x_helpchan;
+ char *x_stats_server;
+ int x_halfhub;
+ int x_inah;
+ char *x_net_quit;
+ int x_se;
+};
+
+typedef struct zConfiguration aConfiguration;
+struct zConfiguration {
+ long nospoof_seed01;
+ long nospoof_seed02;
+ char *kline_address;
+ char *include;
+ char *domainname;
+ char *domainmask; /* '*' + domainname */
+ int som;
+ int mode_x;
+ int mode_i;
+ int truehub;
+ int stop;
+ int showopers;
+ int killdiff;
+ int hide_ulines;
+ int allow_chatops;
+ int socksbantime;
+ char *socksbanmessage;
+ char *socksquitmessage;
+ aNetwork network;
+};
+
+#ifndef DYNCONF_C
+extern aConfiguration iConf;
+#endif
+
+// #define NOSPOOF_SEED01 iConf.nospoof_seed01
+// #define NOSPOOF_SEED02 iConf.nospoof_seed02
+#define KLINE_ADDRESS iConf.kline_address
+#define INCLUDE iConf.include
+#define DOMAINNAMEMASK "*" DOMAINNAME
+#define MODE_X iConf.mode_x
+#define MODE_I iConf.mode_i
+#define TRUEHUB iConf.truehub
+#define SHOWOPERS iConf.showopers
+#define KILLDIFF iConf.killdiff
+#define SHOWOPERMOTD iConf.som
+#define HIDE_ULINES iConf.hide_ulines
+#define ALLOW_CHATOPS iConf.allow_chatops
+
+#define ircnetwork iConf.network.x_ircnetwork
+#define defserv iConf.network.x_defserv
+#define SERVICES_NAME iConf.network.x_services_name
+#define oper_host iConf.network.x_oper_host
+#define admin_host iConf.network.x_admin_host
+#define locop_host iConf.network.x_locop_host
+#define sadmin_host iConf.network.x_sadmin_host
+#define netadmin_host iConf.network.x_netadmin_host
+#define coadmin_host iConf.network.x_coadmin_host
+#define techadmin_host iConf.network.x_techadmin_host
+#define hidden_host iConf.network.x_hidden_host
+#define netdomain iConf.network.x_netdomain
+#define helpchan iConf.network.x_helpchan
+#define STATS_SERVER iConf.network.x_stats_server
+#define iNAH iConf.network.x_inah
+#define net_quit iConf.network.x_net_quit
+#define STOPSE iConf.network.x_se
\ No newline at end of file
--- /dev/null
+#ifndef _IRCD_DOG3_FDLIST
+#define _IRCD_DOG3_FDLIST
+
+/* $Id$ */
+
+typedef struct fdstruct {
+ int entry[MAXCONNECTIONS + 2];
+ int last_entry;
+} fdlist;
+
+void addto_fdlist(int a, fdlist * b);
+void delfrom_fdlist(int a, fdlist * b);
+void init_fdlist(fdlist * b);
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#define LOADCFREQ 5
+#define LOADRECV 35
+#define FDLISTCHKFREQ 2
+
+#endif /*
+ * _IRCD_DOG3_FDLIST
+ */
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, include/h.h
+ * Copyright (C) 1992 Darren Reed
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ */
+
+/*
+ * "h.h". - Headers file.
+ *
+ * Most of the externs and prototypes thrown in here to 'cleanup' things.
+ * -avalon
+ */
+#ifndef NO_FDLIST
+#include "fdlist.h"
+#endif
+
+extern time_t nextconnect, nextdnscheck, nextping;
+extern aClient *client, me, *local[];
+extern aChannel *channel;
+extern struct stats *ircstp;
+extern int bootopt;
+extern time_t TSoffset;
+/* Prototype added to force errors -- Barubary */
+extern time_t check_pings(time_t now, int check_kills);
+
+/* Remmed out for win32 compatibility.. as stated of 467leaf win32 port.. */
+
+#ifdef _WIN32
+// extern void *hCio;
+#endif
+
+#ifdef SHOWCONNECTINFO
+
+#ifdef SOCKSPORT
+#define BREPORT_DO_SOCKS "NOTICE AUTH :*** Checking for open socks server...\r\n"
+#define BREPORT_GOOD_SOCKS "NOTICE AUTH :*** Secure socks found (good!)...\r\n"
+#define BREPORT_NO_SOCKS "NOTICE AUTH :*** No socks server found (good!)...\r\n"
+#endif
+
+#define BREPORT_DO_DNS "NOTICE AUTH :*** Looking up your hostname...\r\n"
+#define BREPORT_FIN_DNS "NOTICE AUTH :*** Found your hostname\r\n"
+#define BREPORT_FIN_DNSC "NOTICE AUTH :*** Found your hostname (cached)\r\n"
+#define BREPORT_FAIL_DNS "NOTICE AUTH :*** Couldn't resolve your hostname; using your IP address instead\r\n"
+#define BREPORT_DO_ID "NOTICE AUTH :*** Checking ident...\r\n"
+#define BREPORT_FIN_ID "NOTICE AUTH :*** Received identd response\r\n"
+#define BREPORT_FAIL_ID "NOTICE AUTH :*** No ident response; username prefixed with ~\r\n"
+
+extern char REPORT_DO_DNS[128], REPORT_FIN_DNS[128], REPORT_FIN_DNSC[128],
+ REPORT_FAIL_DNS[128], REPORT_DO_ID[128], REPORT_FIN_ID[128],
+ REPORT_FAIL_ID[128];
+#ifdef SOCKSPORT
+extern char REPORT_DO_SOCKS[128], REPORT_GOOD_SOCKS[128],
+ REPORT_NO_SOCKS[128];
+#endif
+
+extern int R_do_dns, R_fin_dns, R_fin_dnsc, R_fail_dns,
+ R_do_id, R_fin_id, R_fail_id;
+#ifdef SOCKSPORT
+ extern int R_do_socks,
+ R_good_socks, R_no_socks;
+#endif
+#endif
+extern aChannel *find_channel PROTO((char *, aChannel *));
+extern void remove_user_from_channel PROTO((aClient *, aChannel *));
+/* for services */
+extern void del_invite PROTO((aClient *, aChannel *));
+extern int del_silence PROTO((aClient *, char *));
+extern void send_user_joins PROTO((aClient *, aClient *));
+extern void clean_channelname PROTO((char *));
+extern int do_nick_name PROTO((char *));
+extern int can_send PROTO((aClient *, aChannel *, char *));
+extern int is_chan_op PROTO((aClient *, aChannel *));
+extern int is_zombie PROTO((aClient *, aChannel *));
+extern int has_voice PROTO((aClient *, aChannel *));
+extern int is_chanowner PROTO((aClient *, aChannel *));
+extern int count_channels PROTO((aClient *));
+extern Ban *is_banned PROTO((aClient *, aClient *, aChannel *));
+extern int parse_help PROTO((aClient *, char *, char *));
+
+extern void ircd_log PROTO((char *, ...));
+extern aClient *find_client PROTO((char *, aClient *));
+extern aClient *find_name PROTO((char *, aClient *));
+extern aClient *find_nickserv PROTO((char *, aClient *));
+extern aClient *find_person PROTO((char *, aClient *));
+extern aClient *find_server PROTO((char *, aClient *));
+extern aClient *find_service PROTO((char *, aClient *));
+
+extern int attach_conf PROTO((aClient *, aConfItem *));
+extern aConfItem *attach_confs PROTO((aClient*, char *, int));
+extern aConfItem *attach_confs_host PROTO((aClient*, char *, int));
+extern int attach_Iline PROTO((aClient *, struct hostent *, char *));
+extern aConfItem *conf, *find_me PROTO(()), *find_admin PROTO(());
+extern aConfItem *count_cnlines PROTO((Link *));
+extern aSqlineItem *sqline;
+extern void det_confs_butmask PROTO((aClient *, int));
+extern int detach_conf PROTO((aClient *, aConfItem *));
+extern aSqlineItem *find_sqline_nick PROTO((char *));
+extern aSqlineItem *find_sqline_match PROTO((char *));
+extern aConfItem *det_confs_butone PROTO((aClient *, aConfItem *));
+extern char *find_diepass();
+extern char *find_restartpass();
+extern aConfItem *find_conf PROTO((Link *, char*, int));
+extern aConfItem *find_conf_exact PROTO((char *, char *, char *, int));
+extern aConfItem *find_conf_host PROTO((Link *, char *, int));
+extern aConfItem *find_conf_ip PROTO((Link *, char *, char *, int));
+extern aConfItem *find_conf_name PROTO((char *, int));
+extern aConfItem *find_temp_conf_entry PROTO((aConfItem *, u_int));
+extern aConfItem *find_conf_servern PROTO((char *));
+extern int find_kill PROTO((aClient *));
+extern char *find_zap PROTO((aClient *, int));
+extern int find_restrict PROTO((aClient *));
+extern int rehash PROTO((aClient *, aClient *, int));
+extern int initconf PROTO((int));
+extern void add_temp_conf();
+extern void inittoken PROTO(());
+extern void reset_help PROTO(());
+extern int find_exception(char *); /* hidden host */
+
+extern char *MyMalloc PROTO((int)), *MyRealloc PROTO((char *, int));
+extern char *debugmode, *configfile, *sbrk0;
+extern char *getfield PROTO((char *));
+extern void get_sockhost PROTO((aClient *, char *));
+extern char *rpl_str PROTO((int)), *err_str PROTO((int));
+extern char *strerror PROTO((int));
+extern int dgets PROTO((int, char *, int));
+extern char *inetntoa PROTO((char *));
+
+#ifdef _WIN32
+extern int dbufalloc, dbufblocks, debuglevel;
+#else
+extern int dbufalloc, dbufblocks, debuglevel, errno, h_errno;
+#endif
+extern int highest_fd, debuglevel, portnum, debugtty, maxusersperchannel;
+extern int readcalls, udpfd, resfd;
+extern aClient *add_connection PROTO((aClient *, int));
+extern int add_listener PROTO((aConfItem *));
+extern void add_local_domain PROTO((char *, int));
+extern int check_client PROTO((aClient *));
+extern int check_server PROTO((aClient *, struct hostent *, \
+ aConfItem *, aConfItem *, int));
+extern int check_server_init PROTO((aClient *));
+extern void close_connection PROTO((aClient *));
+extern void close_listeners PROTO(());
+extern int connect_server PROTO((aConfItem *, aClient *, struct hostent *));
+extern void get_my_name PROTO((aClient *, char *, int));
+extern int get_sockerr PROTO((aClient *));
+extern int inetport PROTO((aClient *, char *, int));
+extern void init_sys PROTO(());
+
+#ifdef NO_FDLIST
+extern int read_message PROTO((time_t));
+#else
+extern int read_message PROTO((time_t, fdlist *));
+#endif
+
+extern void report_error PROTO((char *, aClient *));
+extern void set_non_blocking PROTO((int, aClient *));
+extern int setup_ping PROTO(());
+extern void summon PROTO((aClient *, char *, char *, char *));
+extern int unixport PROTO((aClient *, char *, int));
+extern int utmp_open PROTO(());
+extern int utmp_read PROTO((int, char *, char *, char *, int));
+extern int utmp_close PROTO((int));
+
+extern void start_auth PROTO((aClient *));
+extern void read_authports PROTO((aClient *));
+extern void send_authports PROTO((aClient *));
+
+#ifdef SOCKSPORT
+extern void init_socks PROTO((aClient *));
+extern void start_socks PROTO((aClient *));
+extern void send_socksquery PROTO((aClient *));
+extern void read_socks PROTO((aClient *));
+#endif
+
+extern void restart PROTO((char *));
+extern void send_channel_modes PROTO((aClient *, aChannel *));
+extern void server_reboot PROTO((char *));
+extern void terminate PROTO(()), write_pidfile PROTO(());
+
+extern int send_queued PROTO((aClient *));
+/*VARARGS2*/
+// extern void sendto_one(char *, ...);
+/*VARARGS4*/
+/* i know this is naughty but :P --stskeeps */
+extern void sendto_channel_butone(aClient *, aClient *, aChannel *, char *, ...);
+extern void sendto_channelops_butone(aClient *, aClient *, aChannel *, char *, ...);
+extern void sendto_channelvoice_butone(aClient *, aClient *, aChannel *, char *, ...);
+/*VARARGS2*/
+extern void sendto_serv_butone(aClient *, char *, ...);
+/*VARARGS2*/
+extern void sendto_serv_butone_quit(aClient *, char *, ...);
+extern void sendto_serv_butone_sjoin(aClient *, char *, ...);
+extern void sendto_serv_sjoin(aClient *, char *, ...);
+/*VARARGS2*/
+
+extern void sendto_common_channels(aClient *, char *, ...);
+/*VARARGS3*/
+extern void sendto_channel_butserv(aChannel *, aClient *, char *, ...);
+/*VARARGS3*/
+extern void sendto_match_servs(aChannel *, aClient *, char *, ...);
+/*VARARGS5*/
+extern void sendto_match_butone(aClient *, aClient *, char *, int, char *pattern, ...);
+/*VARARGS3*/
+extern void sendto_all_butone(aClient *, aClient *, char *, ...);
+/*VARARGS1*/
+extern void sendto_ops(char *, ...);
+/*VARARGS3*/
+extern void sendto_ops_butone(aClient *, aClient *, char *, ...);
+/*VARARGS3*/
+extern void sendto_ops_butme(aClient *, char *, ...);
+/*VARARGS3*/
+extern void sendto_prefix_one(aClient *, aClient *, const char *, ...);
+/*VARARGS3*/
+extern void sendto_failops_whoare_opers(char *, ...);
+/*VARARGS3*/
+extern void sendto_failops(char *, ...);
+/*VARARGS3*/
+extern void sendto_opers(char *, ...);
+/*VARARGS?*/
+extern void sendto_umode(int, char *, ...);
+extern void sendto_conn_hcn(char *, ...);
+extern int writecalls, writeb[];
+extern int deliver_it PROTO((aClient *, char *, int));
+
+extern int check_registered PROTO((aClient *));
+extern int check_registered_user PROTO((aClient *));
+extern char *get_client_name PROTO((aClient *, int));
+extern char *get_client_host PROTO((aClient *));
+extern char *my_name_for_link PROTO((char *, aConfItem *));
+extern char *myctime PROTO((time_t)), *date PROTO((time_t));
+extern int exit_client PROTO((aClient *, aClient *, aClient *, char *));
+extern void initstats PROTO(()), tstats PROTO((aClient *, char *));
+extern char *check_string PROTO((char *));
+extern char *make_nick_user_host PROTO((char *, char *, char *));
+
+extern int parse PROTO((aClient *, char *, char *, struct Message *));
+extern int do_numeric PROTO((int, aClient *, aClient *, int, char **));
+extern int hunt_server PROTO((aClient *,aClient *,char *,int,int,char **));
+extern aClient *next_client PROTO((aClient *, char *));
+extern int m_umode PROTO((aClient *, aClient *, int, char **));
+extern int m_names PROTO((aClient *, aClient *, int, char **));
+extern int m_server_estab PROTO((aClient *));
+extern void send_umode PROTO((aClient *, aClient *, int, int, char *));
+extern void send_umode_out PROTO((aClient*, aClient *, int));
+
+extern void free_client PROTO((aClient *));
+extern void free_link PROTO((Link *));
+extern void free_ban PROTO((Ban *));
+extern void free_conf PROTO((aConfItem *));
+extern void free_class PROTO((aClass *));
+extern void free_user PROTO((anUser *, aClient *));
+extern int find_str_match_link PROTO((Link **, char *));
+extern void free_str_list PROTO ((Link *));
+extern Link *make_link PROTO(());
+extern Ban *make_ban PROTO(());
+extern anUser *make_user PROTO((aClient *));
+extern aSqlineItem *make_sqline PROTO(());
+extern aConfItem *make_conf PROTO(());
+extern aClass *make_class PROTO(());
+extern aServer *make_server PROTO(());
+extern aClient *make_client PROTO((aClient *, aClient *));
+extern Link *find_user_link PROTO((Link *, aClient *));
+extern Link *find_channel_link PROTO((Link *, aChannel *));
+extern char *pretty_mask PROTO((char *));
+extern void add_client_to_list PROTO((aClient *));
+extern void checklist PROTO(());
+extern void remove_client_from_list PROTO((aClient *));
+extern void initlists PROTO(());
+
+extern void add_class PROTO((int, int, int, int, long));
+extern void fix_class PROTO((aConfItem *, aConfItem *));
+extern long get_sendq PROTO((aClient *));
+extern int get_con_freq PROTO((aClass *));
+extern int get_client_ping PROTO((aClient *));
+extern int get_client_class PROTO((aClient *));
+extern int get_conf_class PROTO((aConfItem *));
+extern void report_classes PROTO((aClient *));
+
+extern struct hostent *get_res PROTO((char *));
+extern struct hostent *gethost_byaddr PROTO((char *, Link *));
+extern struct hostent *gethost_byname PROTO((char *, Link *));
+extern void flush_cache PROTO(());
+extern int init_resolver PROTO((int));
+extern time_t timeout_query_list PROTO((time_t));
+extern time_t expire_cache PROTO((time_t));
+extern void del_queries PROTO((char *));
+
+extern void clear_channel_hash_table PROTO(());
+extern void clear_client_hash_table PROTO(());
+extern void clear_notify_hash_table PROTO(());
+extern int add_to_client_hash_table PROTO((char *, aClient *));
+extern int del_from_client_hash_table PROTO((char *, aClient *));
+extern int add_to_channel_hash_table PROTO((char *, aChannel *));
+extern int del_from_channel_hash_table PROTO((char *, aChannel *));
+extern int add_to_notify_hash_table PROTO((char *, aClient *));
+extern int del_from_notify_hash_table PROTO((char *, aClient *));
+extern int hash_check_notify PROTO((aClient *, int));
+extern int hash_del_notify_list PROTO((aClient *));
+extern void count_watch_memory PROTO((int *, u_long *));
+extern aNotify *hash_get_notify PROTO((char *));
+extern aChannel *hash_get_chan_bucket PROTO((int));
+extern aChannel *hash_find_channel PROTO((char *, aChannel *));
+extern aClient *hash_find_client PROTO((char *, aClient *));
+extern aClient *hash_find_nickserver PROTO((char *, aClient *));
+extern aClient *hash_find_server PROTO((char *, aClient *));
+
+extern void add_history PROTO((aClient *));
+extern aClient *get_history PROTO((char *, time_t));
+extern void initwhowas PROTO(());
+extern void off_history PROTO((aClient *));
+
+extern int dopacket PROTO((aClient *, char *, int));
+
+/*VARARGS2*/
+extern void debug();
+#if defined(DEBUGMODE)
+extern void send_usage PROTO((aClient *, char *));
+extern void send_listinfo PROTO((aClient *, char *));
+extern void count_memory PROTO((aClient *, char *));
+#endif
+
+char *crule_parse PROTO((char *));
+int crule_eval PROTO((char *));
+void crule_free PROTO((char **));
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, include/hash.h
+ * Copyright (C) 1991 Darren Reed
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ */
+
+#ifndef __hash_include__
+#define __hash_include__
+
+/* Ditch the stats if not running in debugmode */
+#ifdef DEBUGMODE
+typedef struct hashentry {
+ int hits;
+ int links;
+ void *list;
+ } aHashEntry;
+#else /* DEBUGMODE */
+typedef void *aHashEntry;
+#endif /* DEBUGMODE */
+
+#ifndef DEBUGMODE
+#define HASHSIZE 32003 /* prime number */
+#define CHANNELHASHSIZE 10007 /* prime number */
+#else
+extern int HASHSIZE;
+extern int CHANNELHASHSIZE;
+#endif
+
+#define NOTIFYHASHSIZE 10007 /* prime number */
+
+#define NullChn ((aChannel *)0)
+
+#endif /* __hash_include__ */
--- /dev/null
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement: ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Id$
+ *
+ * @(#)inet.h 5.4 (Berkeley) 6/1/90
+ */
+
+/* External definitions for functions in inet(3) */
+#include "config.h" /* for system definitions */
+
+#ifdef __alpha
+#define __u_l unsigned int
+#else
+#define __u_l unsigned long
+#endif
+
+#ifdef __STDC__
+# ifndef _WIN32
+extern __u_l inet_addr(char *);
+extern char *inet_ntoa(char *);
+# endif
+extern __u_l inet_makeaddr(int , int);
+extern __u_l inet_network(char *);
+extern __u_l inet_lnaof(struct in_addr);
+#else
+# ifndef _WIN32
+extern __u_l inet_addr();
+extern char *inet_ntoa();
+# endif
+#ifndef HPUX
+extern __u_l inet_makeaddr();
+#endif
+#endif
+#ifndef HPUX
+extern __u_l inet_network();
+extern __u_l inet_lnaof();
+#endif
+#undef __u_l
--- /dev/null
+/*
+ * IRC - Internet Relay Chat, include/license.h
+ * Copyright (C) 1999 Carsten Munk
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * This file may not be removed from the IRCd package.
+ * It will be a violation of copyright. This program must always
+ * stay free and not be sold, or charged.
+ *
+ * $Id$
+ */
+
+/*
+ * GNU License converted by Techie <stskeeps@tspre.org>
+ *
+*/
+
+static char *Statement[] = {
+" * This file may not be removed from the IRCd package.",
+" * It will be a violation of copyright. This program must always",
+" * stay free and not be charged for, being sold commercially or privately",
+" * Only charge may be for the transport medium like one CD-ROM, floppy",
+" * or other kinds.",
+0};
+
+char *gnulicense[] = {
+" \2UnrealIRCd License\2",
+"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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.",
+"",
+"To see the UnrealIRCd License, please point your browser",
+"at http://www.gnu.org/copyleft/gpl.html or look in the",
+"file LICENSE in the UnrealIRCd dist",
+0
+};
+
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, include/msg.h
+ * Copyright (C) 1990 Jarkko Oikarinen and
+ * University of Oulu, Computing Center
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ */
+
+#ifndef __msg_include__
+#define __msg_include__
+
+/*
+ * The tokens are in the ascii character range of 33-127, and we start
+ * from 33 and just move up. It would be nice to match then up so they
+ * are slightly related to their string counterpart, but that makes it
+ * too confusing when we want to add another one and need to make sure
+ * we're not using one already used. -Cabal95
+ *
+ * As long as the #defines are kept statically placed, it will be fine.
+ * We don't care/worry about the msgtab[] since it can be dynamic, but
+ * the tokens it uses will still be static according to the messages
+ * they represent. In other words leave the #defines in order, if you're
+ * going to add something, PUT IT AT THE END. Do not even look for an
+ * open spot somewhere, as that may lead to one type of message being
+ * sent by server A to server B, but server B thinks its something else.
+ * Remember, skip the : since its got a special use, and I skip the \ too
+ * since it _may_ cause problems, but not sure. -Cabal95
+ * I'm skipping A and a as well, because some clients and scripts use
+ * these to test if the server has already processed whole queue.
+ * Since the client could request this protocol withhout the script
+ * knowing it, I'm considering that reserved, and TRACE/A is now 'b'.
+ * The normal msgtab should probably process this as special. -Donwulff
+ */
+
+/* 12/05/1999 - I was wrong - I didnt see the token[2] in struct Message
+ okie 60*60 commands more :P - Sowwy!!! -sts
+
+ */
+
+#define MSG_PRIVATE "PRIVMSG" /* PRIV */
+#define TOK_PRIVATE "!" /* 33 */
+#define MSG_WHO "WHO" /* WHO -> WHOC */
+#define TOK_WHO "\"" /* 34 */
+#define MSG_WHOIS "WHOIS" /* WHOI */
+#define TOK_WHOIS "#" /* 35 */
+#define MSG_WHOWAS "WHOWAS" /* WHOW */
+#define TOK_WHOWAS "$" /* 36 */
+#define MSG_USER "USER" /* USER */
+#define TOK_USER "%" /* 37 */
+#define MSG_NICK "NICK" /* NICK */
+#define TOK_NICK "&" /* 38 */
+#define MSG_SERVER "SERVER" /* SERV */
+#define TOK_SERVER "'" /* 39 */
+#define MSG_LIST "LIST" /* LIST */
+#define TOK_LIST "(" /* 40 */
+#define MSG_TOPIC "TOPIC" /* TOPI */
+#define TOK_TOPIC ")" /* 41 */
+#define MSG_INVITE "INVITE" /* INVI */
+#define TOK_INVITE "*" /* 42 */
+#define MSG_VERSION "VERSION" /* VERS */
+#define TOK_VERSION "+" /* 43 */
+#define MSG_QUIT "QUIT" /* QUIT */
+#define TOK_QUIT "," /* 44 */
+#define MSG_SQUIT "SQUIT" /* SQUI */
+#define TOK_SQUIT "-" /* 45 */
+#define MSG_KILL "KILL" /* KILL */
+#define TOK_KILL "." /* 46 */
+#define MSG_INFO "INFO" /* INFO */
+#define TOK_INFO "/" /* 47 */
+#define MSG_LINKS "LINKS" /* LINK */
+#define TOK_LINKS "0" /* 48 */
+#define MSG_SUMMON "SUMMON" /* SUMM */
+#define TOK_SUMMON "1" /* 49 */
+#define MSG_STATS "STATS" /* STAT */
+#define TOK_STATS "2" /* 50 */
+#define MSG_USERS "USERS" /* USER -> USRS */
+#define TOK_USERS "3" /* 51 */
+#define MSG_HELP "HELP" /* HELP */
+#define MSG_HELPOP "HELPOP" /* HELP */
+#define MSG_IRCDHELP "IRCDHELP" /* HELP */
+#define TOK_HELP "4" /* 52 */
+#define MSG_ERROR "ERROR" /* ERRO */
+#define TOK_ERROR "5" /* 53 */
+#define MSG_AWAY "AWAY" /* AWAY */
+#define TOK_AWAY "6" /* 54 */
+#define MSG_CONNECT "CONNECT" /* CONN */
+#define TOK_CONNECT "7" /* 55 */
+#define MSG_PING "PING" /* PING */
+#define TOK_PING "8" /* 56 */
+#define MSG_PONG "PONG" /* PONG */
+#define TOK_PONG "9" /* 57 */
+#define MSG_OPER "OPER" /* OPER */
+#define TOK_OPER ";" /* 59 */
+#define MSG_PASS "PASS" /* PASS */
+#define TOK_PASS "<" /* 60 */
+#define MSG_WALLOPS "WALLOPS" /* WALL */
+#define TOK_WALLOPS "=" /* 61 */
+#define MSG_TIME "TIME" /* TIME */
+#define TOK_TIME ">" /* 62 */
+#define MSG_NAMES "NAMES" /* NAME */
+#define TOK_NAMES "?" /* 63 */
+#define MSG_ADMIN "ADMIN" /* ADMI */
+#define TOK_ADMIN "@" /* 64 */
+#define MSG_NOTICE "NOTICE" /* NOTI */
+#define TOK_NOTICE "B" /* 66 */
+#define MSG_JOIN "JOIN" /* JOIN */
+#define TOK_JOIN "C" /* 67 */
+#define MSG_PART "PART" /* PART */
+#define TOK_PART "D" /* 68 */
+#define MSG_LUSERS "LUSERS" /* LUSE */
+#define TOK_LUSERS "E" /* 69 */
+#define MSG_MOTD "MOTD" /* MOTD */
+#define TOK_MOTD "F" /* 70 */
+#define MSG_MODE "MODE" /* MODE */
+#define TOK_MODE "G" /* 71 */
+#define MSG_KICK "KICK" /* KICK */
+#define TOK_KICK "H" /* 72 */
+#define MSG_SERVICE "SERVICE" /* SERV -> SRVI */
+#define TOK_SERVICE "I" /* 73 */
+#define MSG_USERHOST "USERHOST" /* USER -> USRH */
+#define TOK_USERHOST "J" /* 74 */
+#define MSG_ISON "ISON" /* ISON */
+#define TOK_ISON "K" /* 75 */
+#define MSG_REHASH "REHASH" /* REHA */
+#define TOK_REHASH "O" /* 79 */
+#define MSG_RESTART "RESTART" /* REST */
+#define TOK_RESTART "P" /* 80 */
+#define MSG_CLOSE "CLOSE" /* CLOS */
+#define TOK_CLOSE "Q" /* 81 */
+#define MSG_DIE "DIE" /* DIE */
+#define TOK_DIE "R" /* 82 */
+#define MSG_HASH "HASH" /* HASH */
+#define TOK_HASH "S" /* 83 */
+#define MSG_DNS "DNS" /* DNS -> DNSS */
+#define TOK_DNS "T" /* 84 */
+#define MSG_SILENCE "SILENCE" /* SILE */
+#define TOK_SILENCE "U" /* 85 */
+#define MSG_AKILL "AKILL" /* AKILL */
+#define TOK_AKILL "V" /* 86 */
+#define MSG_KLINE "KLINE" /* KLINE */
+#define TOK_KLINE "W" /* 87 */
+#define MSG_UNKLINE "UNKLINE" /* UNKLINE */
+#define TOK_UNKLINE "X" /* 88 */
+#define MSG_RAKILL "RAKILL" /* RAKILL */
+#define TOK_RAKILL "Y" /* 89 */
+#define MSG_GNOTICE "GNOTICE" /* GNOTICE */
+#define TOK_GNOTICE "Z" /* 90 */
+#define MSG_GOPER "GOPER" /* GOPER */
+#define TOK_GOPER "[" /* 91 */
+#define MSG_GLOBOPS "GLOBOPS" /* GLOBOPS */
+#define TOK_GLOBOPS "]" /* 93 */
+#define MSG_LOCOPS "LOCOPS" /* LOCOPS */
+#define TOK_LOCOPS "^" /* 94 */
+#define MSG_PROTOCTL "PROTOCTL" /* PROTOCTL */
+#define TOK_PROTOCTL "_" /* 95 */
+#define MSG_WATCH "WATCH" /* WATCH */
+#define TOK_WATCH "`" /* 96 */
+#define MSG_TRACE "TRACE" /* TRAC */
+#define TOK_TRACE "b" /* 97 */
+#define MSG_SQLINE "SQLINE" /* SQLINE */
+#define TOK_SQLINE "c" /* 98 */
+#define MSG_UNSQLINE "UNSQLINE" /* UNSQLINE */
+#define TOK_UNSQLINE "d" /* 99 */
+#define MSG_SVSNICK "SVSNICK" /* SVSNICK */
+#define TOK_SVSNICK "e" /* 100 */
+#define MSG_SVSNOOP "SVSNOOP" /* SVSNOOP */
+#define TOK_SVSNOOP "f" /* 101 */
+#define MSG_IDENTIFY "IDENTIFY" /* IDENTIFY */
+#define TOK_IDENTIFY "g" /* 102 */
+#define MSG_SVSKILL "SVSKILL" /* SVSKILL */
+#define TOK_SVSKILL "h" /* 103 */
+#define MSG_NICKSERV "NICKSERV" /* NICKSERV */
+#define MSG_NS "NS"
+#define TOK_NICKSERV "i" /* 104 */
+#define MSG_CHANSERV "CHANSERV" /* CHANSERV */
+#define MSG_CS "CS"
+#define TOK_CHANSERV "j" /* 105 */
+#define MSG_OPERSERV "OPERSERV" /* OPERSERV */
+#define MSG_OS "OS"
+#define TOK_OPERSERV "k" /* 106 */
+#define MSG_MEMOSERV "MEMOSERV" /* MEMOSERV */
+#define MSG_MS "MS"
+#define TOK_MEMOSERV "l" /* 107 */
+#define MSG_SERVICES "SERVICES" /* SERVICES */
+#define TOK_SERVICES "m" /* 108 */
+#define MSG_SVSMODE "SVSMODE" /* SVSMODE */
+#define TOK_SVSMODE "n" /* 109 */
+#define MSG_SAMODE "SAMODE" /* SAMODE */
+#define TOK_SAMODE "o" /* 110 */
+#define MSG_CHATOPS "CHATOPS" /* CHATOPS */
+#define TOK_CHATOPS "p" /* 111 */
+#define MSG_ZLINE "ZLINE" /* ZLINE */
+#define TOK_ZLINE "q" /* 112 */
+#define MSG_UNZLINE "UNZLINE" /* UNZLINE */
+#define TOK_UNZLINE "r" /* 113 */
+#define MSG_HELPSERV "HELPSERV" /* HELPSERV */
+#define MSG_HS "HS"
+#define TOK_HELPSERV "s" /* 114 */
+#define MSG_RULES "RULES" /* RULES */
+#define TOK_RULES "t" /* 115 */
+#define MSG_MAP "MAP" /* MAP */
+#define TOK_MAP "u" /* 117 */
+#define MSG_SVS2MODE "SVS2MODE" /* SVS2MODE */
+#define TOK_SVS2MODE "v" /* 118 */
+#define MSG_DALINFO "DALINFO" /* dalinfo */
+#define TOK_DALINFO "w" /* 119 */
+#define MSG_ADMINCHAT "ADCHAT" /* Admin chat */
+#define TOK_ADMINCHAT "x" /* 120 */
+#define MSG_MKPASSWD "MKPASSWD" /* MKPASSWD */
+#define TOK_MKPASSWD "y" /* 121 */
+#define MSG_ADDLINE "ADDLINE" /* ADDLINE */
+#define TOK_ADDLINE "z" /* 122 */
+#define MSG_GLINE "GLINE" /* The awesome g-line */
+#define TOK_GLINE "}" /* 125 */
+#define MSG_SJOIN "SJOIN"
+#define TOK_SJOIN "~"
+#define MSG_SETHOST "SETHOST" /* sethost */
+#define TOK_SETHOST "AA" /* 127 4ever !;) */
+#define MSG_TECHAT "TECHAT" /* techadmin chat */
+#define TOK_TECHAT "AB" /* questionmark? */
+#define MSG_NACHAT "NACHAT" /* netadmin chat */
+#define TOK_NACHAT "AC" /* *beep* */
+#define MSG_SETIDENT "SETIDENT" /* set ident */
+#define TOK_SETIDENT "AD" /* good old BASIC ;P */
+#define MSG_SETNAME "SETNAME" /* set GECOS */
+#define TOK_SETNAME "AE" /* its almost unreeaaall... */
+#define MSG_LAG "LAG" /* Lag detect */
+#define TOK_LAG "AF" /* a or ? */
+#define MSG_SDESC "SDESC" /* set description */
+#define TOK_SDESC "AG"
+#define MSG_STATSERV "STATSERV" /* alias */
+#define TOK_STATSERV "AH"
+#define MSG_KNOCK "KNOCK"
+#define TOK_KNOCK "AI"
+#define MSG_CREDITS "CREDITS"
+#define TOK_CREDITS "AJ"
+#define MSG_LICENSE "LICENSE"
+#define TOK_LICENSE "AK"
+#define MSG_CHGHOST "CHGHOST"
+#define TOK_CHGHOST "AL"
+#define MSG_RPING "RPING"
+#define TOK_RPING "AM"
+#define MSG_RPONG "RPONG"
+#define TOK_RPONG "AN"
+#define MSG_NETINFO "NETINFO"
+#define TOK_NETINFO "AO"
+#define MSG_SENDUMODE "SENDUMODE"
+#define TOK_SENDUMODE "AP"
+#define MSG_ADDMOTD "ADDMOTD"
+#define TOK_ADDMOTD "AQ"
+#define MSG_ADDOMOTD "ADDOMOTD"
+#define TOK_ADDOMOTD "AR"
+#define MSG_SVSMOTD "SVSMOTD"
+#define TOK_SVSMOTD "AS"
+#define MSG_DUSERS "DUSERS"
+#define TOK_DUSERS "AT"
+#define MSG_SMO "SMO"
+#define TOK_SMO "AU"
+#define MSG_OPERMOTD "OPERMOTD"
+#define TOK_OPERMOTD "AV"
+#define MSG_TSCTL "TSCTL"
+#define TOK_TSCTL "AW"
+#define MSG_SVSJOIN "SVSJOIN"
+#define TOK_SVSJOIN "AX"
+#define MSG_SAJOIN "SAJOIN"
+#define TOK_SAJOIN "AY"
+#define MSG_SVSPART "SVSPART"
+#define TOK_SVSPART "AX"
+#define MSG_SAPART "SAPART"
+#define TOK_SAPART "AY"
+#define MSG_CHGIDENT "CHGIDENT"
+#define TOK_CHGIDENT "AZ"
+#define MSG_SWHOIS "SWHOIS"
+#define TOK_SWHOIS "BA"
+#define MSG_SVSO "SVSO"
+#define TOK_SVSO "BB"
+#define MSG_SVSFLINE "SVSFLINE"
+#define TOK_SVSFLINE "BC"
+#define MSG_TKL "TKL"
+#define TOK_TKL "BD"
+#define MSG_VHOST "VHOST"
+#define TOK_VHOST "BE"
+#define MSG_BOTMOTD "BOTMOTD"
+#define TOK_BOTMOTD "BF"
+#define MSG_REMGLINE "REMGLINE" /* remove g-line */
+#define TOK_REMGLINE "BG"
+#define MSG_HTM "HTM"
+#define TOK_HTM "BH"
+#define MAXPARA 15
+
+
+extern int m_private(), m_topic(), m_join(), m_part(), m_mode(), m_svsmode();
+extern int m_ping(), m_pong(), m_wallops(), m_kick(), m_svsnick();
+extern int m_nick(), m_error(), m_notice(), m_samode(), m_svsnoop();
+extern int m_invite(), m_quit(), m_kill(), m_svskill(), m_identify();
+extern int m_akill(), m_kline(), m_unkline(), m_rakill(), m_sqline();
+extern int m_zline(), m_unzline();
+extern int m_gnotice(), m_goper(), m_globops(), m_locops(), m_unsqline(), m_chatops();
+extern int m_protoctl();
+extern int m_motd(), m_who(), m_whois(), m_user(), m_list();
+extern int m_server(), m_info(), m_links(), m_summon(), m_stats();
+extern int m_users(), m_version(), m_help();
+extern int m_nickserv(), m_operserv(), m_chanserv(), m_memoserv(), m_helpserv(), m_services(), m_identify();
+extern int m_statserv();
+extern int m_squit(), m_away(), m_connect();
+extern int m_oper(), m_pass(), m_trace();
+extern int m_time(), m_names(), m_admin();
+extern int m_lusers(), m_umode(), m_close();
+extern int m_motd(), m_whowas(), m_silence();
+extern int m_service(), m_userhost(), m_ison(), m_watch();
+extern int m_service(), m_servset(), m_servlist(), m_squery();
+extern int m_rehash(), m_restart(), m_die(), m_dns(), m_hash();
+/*extern int m_noshortn(),m_noshortc(),m_noshortm(),m_noshorto(),m_noshorth();*/
+
+extern int m_gline(), m_remgline(), m_map(), m_svs2mode(), m_admins(), m_dalinfo();
+extern int m_addline(), m_rules(), m_mkpasswd();
+extern int m_sethost(), m_nachat(), m_techat(), m_setident(), m_setname();
+extern int m_lag(), m_sdesc(), m_knock(), m_credits();
+extern int m_license(), m_chghost(), m_rping(), m_rpong();
+extern int m_netinfo(), m_sendumode(), m_addmotd(), m_addomotd();
+extern int m_svsmotd(), m_dusers(), m_opermotd(), m_tsctl();
+extern int m_svsjoin(), m_sajoin(), m_svspart(), m_sapart();
+extern int m_chgident(), m_swhois(), m_svso(), m_svsfline();
+extern int m_tkl(), m_vhost(), m_botmotd(), m_sjoin(), m_htm();
+
+#ifdef MSGTAB
+struct Message *msgmap[256];
+struct Message msgtab[] = {
+ { MSG_PRIVATE, m_private, 0, MAXPARA, 1, TOK_PRIVATE, 0L },
+ { MSG_NICK, m_nick, 0, MAXPARA, 1, TOK_NICK, 0L },
+ { MSG_NOTICE, m_notice, 0, MAXPARA, 1, TOK_NOTICE, 0L },
+ { MSG_JOIN, m_join, 0, MAXPARA, 1, TOK_JOIN, 0L },
+ { MSG_MODE, m_mode, 0, MAXPARA, 1, TOK_MODE, 0L },
+ { MSG_QUIT, m_quit, 0, MAXPARA, 1, TOK_QUIT, 0L },
+ { MSG_PART, m_part, 0, MAXPARA, 1, TOK_PART, 0L },
+ { MSG_TOPIC, m_topic, 0, MAXPARA, 1, TOK_TOPIC, 0L },
+ { MSG_INVITE, m_invite, 0, MAXPARA, 1, TOK_INVITE, 0L },
+ { MSG_KICK, m_kick, 0, MAXPARA, 1, TOK_KICK, 0L },
+ { MSG_WALLOPS, m_wallops, 0, 1, 1, TOK_WALLOPS, 0L },
+ { MSG_PING, m_ping, 0, MAXPARA, 1, TOK_PING, 0L },
+ { MSG_PONG, m_pong, 0, MAXPARA, 1, TOK_PONG, 0L },
+ { MSG_ERROR, m_error, 0, MAXPARA, 1, TOK_ERROR, 0L },
+ { MSG_KILL, m_kill, 0, MAXPARA, 1, TOK_KILL, 0L },
+ { MSG_PROTOCTL,m_protoctl, 0, MAXPARA, 1, TOK_PROTOCTL,0L },
+ { MSG_USER, m_user, 0, MAXPARA, 1, TOK_USER, 0L },
+ { MSG_AWAY, m_away, 0, MAXPARA, 1, TOK_AWAY, 0L },
+ { MSG_ISON, m_ison, 0, 1, 1, TOK_ISON, 0L },
+ { MSG_WATCH, m_watch, 0, 1, 1, TOK_WATCH, 0L },
+ { MSG_SERVER, m_server, 0, MAXPARA, 1, TOK_SERVER, 0L },
+ { MSG_SQUIT, m_squit, 0, MAXPARA, 1, TOK_SQUIT, 0L },
+ { MSG_WHOIS, m_whois, 0, MAXPARA, 1, TOK_WHOIS, 0L },
+ { MSG_WHO, m_who, 0, MAXPARA, 1, TOK_WHO, 0L },
+ { MSG_WHOWAS, m_whowas, 0, MAXPARA, 1, TOK_WHOWAS, 0L },
+ { MSG_LIST, m_list, 0, MAXPARA, 1, TOK_LIST, 0L },
+ { MSG_NAMES, m_names, 0, MAXPARA, 1, TOK_NAMES, 0L },
+ { MSG_USERHOST,m_userhost, 0, 1, 1, TOK_USERHOST,0L },
+ { MSG_TRACE, m_trace, 0, MAXPARA, 1, TOK_TRACE, 0L },
+ { MSG_PASS, m_pass, 0, MAXPARA, 1, TOK_PASS, 0L },
+ { MSG_LUSERS, m_lusers, 0, MAXPARA, 1, TOK_LUSERS, 0L },
+ { MSG_TIME, m_time, 0, MAXPARA, 1, TOK_TIME, 0L },
+ { MSG_OPER, m_oper, 0, MAXPARA, 1, TOK_OPER, 0L },
+ { MSG_CONNECT, m_connect, 0, MAXPARA, 1, TOK_CONNECT, 0L },
+ { MSG_VERSION, m_version, 0, MAXPARA, 1, TOK_VERSION, 0L },
+ { MSG_STATS, m_stats, 0, MAXPARA, 1, TOK_STATS, 0L },
+ { MSG_LINKS, m_links, 0, MAXPARA, 1, TOK_LINKS, 0L },
+ { MSG_ADMIN, m_admin, 0, MAXPARA, 1, TOK_ADMIN, 0L },
+ { MSG_USERS, m_users, 0, MAXPARA, 1, TOK_USERS, 0L },
+ { MSG_SVSMODE, m_svsmode, 0, MAXPARA, 1, TOK_SVSMODE, 0L },
+ { MSG_SAMODE, m_samode, 0, MAXPARA, 1, TOK_SAMODE, 0L },
+ { MSG_SVSKILL, m_svskill, 0, MAXPARA, 1, TOK_SVSKILL, 0L },
+ { MSG_SVSNICK, m_svsnick, 0, MAXPARA, 1, TOK_SVSNICK, 0L },
+ { MSG_SVSNOOP, m_svsnoop, 0, MAXPARA, 1, TOK_SVSNOOP, 0L },
+ { MSG_CHANSERV,m_chanserv, 0, 1, 1, TOK_CHANSERV,0L },
+ /* { MSG_CS, m_noshortc, 0, 1, 1, TOK_CHANSERV,0L }, */
+ { MSG_NICKSERV,m_nickserv, 0, 1, 1, TOK_NICKSERV,0L },
+ /* { MSG_NS, m_noshortn, 0, 1, 1, TOK_NICKSERV,0L }, */
+ { MSG_OPERSERV,m_operserv, 0, 1, 1, TOK_OPERSERV,0L },
+ /* { MSG_OS, m_noshorto, 0, 1, 1, TOK_OPERSERV,0L }, */
+ { MSG_MEMOSERV,m_memoserv, 0, 1, 1, TOK_MEMOSERV,0L },
+ /*{ MSG_MS, m_noshortm, 0, 1, 1, TOK_MEMOSERV,0L }, */
+ { MSG_HELPSERV,m_helpserv, 0, 1, 1, TOK_HELPSERV,0L },
+ /* { MSG_HS, m_noshorth, 0, 1, 1, TOK_HELPSERV,0L }, */
+ { MSG_SERVICES,m_services, 0, 1, 1, TOK_SERVICES,0L },
+ { MSG_IDENTIFY,m_identify, 0, 1, 1, TOK_IDENTIFY,0L },
+ { MSG_SUMMON, m_summon, 0, MAXPARA, 1, TOK_SUMMON, 0L },
+ { MSG_HELP, m_help, 0, 1, 1, TOK_HELP, 0L },
+ { MSG_HELPOP, m_help, 0, 1, 1, TOK_HELP, 0L },
+ { MSG_INFO, m_info, 0, MAXPARA, 1, TOK_INFO, 0L },
+ { MSG_MOTD, m_motd, 0, MAXPARA, 1, TOK_MOTD, 0L },
+ { MSG_CLOSE, m_close, 0, MAXPARA, 1, TOK_CLOSE, 0L },
+ { MSG_SILENCE, m_silence, 0, MAXPARA, 1, TOK_SILENCE, 0L },
+ { MSG_AKILL, m_akill, 0, MAXPARA, 1, TOK_AKILL, 0L },
+ { MSG_SQLINE, m_sqline, 0, MAXPARA, 1, TOK_SQLINE, 0L },
+ { MSG_UNSQLINE,m_unsqline, 0, MAXPARA, 1, TOK_UNSQLINE,0L },
+ { MSG_KLINE, m_kline, 0, MAXPARA, 1, TOK_KLINE, 0L },
+ { MSG_UNKLINE, m_unkline, 0, MAXPARA, 1, TOK_UNKLINE, 0L },
+ { MSG_ZLINE, m_zline, 0, MAXPARA, 1, TOK_ZLINE, 0L },
+ { MSG_UNZLINE, m_unzline, 0, MAXPARA, 1, TOK_UNZLINE, 0L },
+ { MSG_RAKILL, m_rakill, 0, MAXPARA, 1, TOK_RAKILL, 0L },
+ { MSG_GNOTICE, m_gnotice, 0, MAXPARA, 1, TOK_GNOTICE, 0L },
+ { MSG_GOPER, m_goper, 0, MAXPARA, 1, TOK_GOPER, 0L },
+ { MSG_GLOBOPS, m_globops, 0, MAXPARA, 1, TOK_GLOBOPS, 0L },
+ { MSG_CHATOPS, m_chatops, 0, 1, 1, TOK_CHATOPS, 0L },
+ { MSG_LOCOPS, m_locops, 0, 1, 1, TOK_LOCOPS, 0L },
+ { MSG_HASH, m_hash, 0, MAXPARA, 1, TOK_HASH, 0L },
+ { MSG_DNS, m_dns, 0, MAXPARA, 1, TOK_DNS, 0L },
+ { MSG_REHASH, m_rehash, 0, MAXPARA, 1, TOK_REHASH, 0L },
+ { MSG_RESTART, m_restart, 0, MAXPARA, 1, TOK_RESTART, 0L },
+ { MSG_DIE, m_die, 0, MAXPARA, 1, TOK_DIE, 0L },
+ { MSG_RULES, m_rules, 0, MAXPARA, 1, TOK_RULES, 0L },
+ { MSG_MAP, m_map, 0, MAXPARA, 1, TOK_MAP, 0L },
+ { MSG_GLINE, m_gline, 0, MAXPARA, 1, TOK_GLINE, 0L },
+ { MSG_REMGLINE,m_remgline, 0, MAXPARA, 1, TOK_REMGLINE,0L },
+ { MSG_DALINFO, m_dalinfo, 0, MAXPARA, 1, TOK_DALINFO, 0L },
+ { MSG_SVS2MODE,m_svs2mode, 0, MAXPARA, 1, TOK_SVS2MODE,0L },
+ { MSG_MKPASSWD, m_mkpasswd, 0, MAXPARA, 1, TOK_MKPASSWD, 0L },
+ { MSG_ADDLINE, m_addline, 0, 1, 1, TOK_ADDLINE, 0L },
+ { MSG_ADMINCHAT, m_admins, 0, 1, 1, TOK_ADMINCHAT, 0L },
+ { MSG_SETHOST, m_sethost, 0, MAXPARA, 1, TOK_SETHOST, 0L },
+ { MSG_TECHAT, m_techat, 0, 1, 1, TOK_TECHAT, 0L },
+ { MSG_NACHAT, m_nachat, 0, 1, 1, TOK_NACHAT, 0L },
+ { MSG_SETIDENT, m_setident,0, MAXPARA, 1, TOK_SETIDENT, 0L },
+ { MSG_SETNAME, m_setname, 0, 1, 1, TOK_SETNAME, 0L },
+ { MSG_LAG, m_lag, 0, MAXPARA, 1, TOK_LAG, 0L },
+ { MSG_SDESC, m_sdesc, 0, 1, 1, TOK_SDESC, 0L },
+ { MSG_STATSERV,m_statserv, 0, 1, 1, TOK_STATSERV,0L },
+ { MSG_KNOCK, m_knock, 0, 2, 1, TOK_KNOCK, 0L },
+ { MSG_CREDITS, m_credits, 0, MAXPARA, 1, TOK_CREDITS, 0L },
+ { MSG_LICENSE, m_license, 0, MAXPARA, 1, TOK_LICENSE, 0L },
+ { MSG_CHGHOST, m_chghost, 0, MAXPARA, 1, TOK_CHGHOST, 0L },
+ { MSG_RPING, m_rping, 0, MAXPARA, 1, TOK_RPING, 0L },
+ { MSG_RPONG, m_rpong, 0, MAXPARA, 1, TOK_RPONG, 0L },
+ { MSG_NETINFO, m_netinfo, 0, MAXPARA, 1, TOK_NETINFO, 0L},
+ { MSG_SENDUMODE, m_sendumode, 0, MAXPARA, 1, TOK_SENDUMODE, 0L},
+ { MSG_SMO, m_sendumode, 0, MAXPARA, 1, TOK_SMO, 0L},
+ { MSG_ADDMOTD, m_addmotd, 0, 1, 1, TOK_ADDMOTD, 0L},
+ { MSG_ADDOMOTD, m_addomotd, 0, 1, 1, TOK_ADDOMOTD, 0L},
+ { MSG_SVSMOTD, m_svsmotd, 0, MAXPARA, 1, TOK_SVSMOTD, 0L},
+ { MSG_DUSERS, m_dusers, 0, MAXPARA, 1, TOK_DUSERS, 0L},
+ { MSG_OPERMOTD, m_opermotd, 0, MAXPARA, 1, TOK_OPERMOTD, 0L},
+ { MSG_TSCTL, m_tsctl, 0, MAXPARA, 1, TOK_TSCTL, 0L},
+ { MSG_SVSJOIN, m_svsjoin, 0, MAXPARA, 1, TOK_SVSJOIN, 0L},
+ { MSG_SAJOIN, m_sajoin, 0, MAXPARA, 1, TOK_SAJOIN,0L},
+ { MSG_SVSPART, m_svspart, 0, MAXPARA, 1, TOK_SVSPART, 0L},
+ { MSG_SAPART, m_sapart, 0, MAXPARA, 1, TOK_SAPART,0L},
+ { MSG_CHGIDENT, m_chgident,0, MAXPARA, 1, TOK_CHGIDENT,0L},
+ { MSG_SWHOIS, m_swhois, 0, MAXPARA, 1, TOK_SWHOIS, 0L},
+ { MSG_SVSO, m_svso, 0, MAXPARA, 1, TOK_SVSO, 0L},
+ { MSG_SVSFLINE, m_svsfline, 0, MAXPARA,1,TOK_SVSFLINE,0L},
+ { MSG_TKL, m_tkl, 0, MAXPARA,1,TOK_TKL,0L},
+ { MSG_VHOST, m_vhost, 0, MAXPARA,1,TOK_VHOST,0L},
+ { MSG_BOTMOTD, m_botmotd, 0, MAXPARA,1,TOK_BOTMOTD,0L},
+ { MSG_SJOIN, m_sjoin, 0, MAXPARA, 1, TOK_SJOIN,0L},
+ { MSG_HTM, m_htm, 0, MAXPARA, 1, TOK_HTM, 0L},
+ { (char *) 0, (int (*)()) 0 , 0, 0, 0, 0, 0L}
+};
+
+#else
+extern struct Message msgtab[];
+extern struct Message *msgmap[256];
+#endif
+#endif /* __msg_include__ */
--- /dev/null
+/*
+ * Copyright (c) 1983, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement: ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Id$
+ * @(#)nameser.h 5.24 (Berkeley) 6/1/90
+ */
+
+/*
+ * Define constants based on rfc883
+ */
+#define PACKETSZ 512 /* maximum packet size */
+#define MAXDNAME 256 /* maximum domain name */
+#define MAXCDNAME 255 /* maximum compressed domain name */
+#define MAXLABEL 63 /* maximum length of domain label */
+ /* Number of bytes of fixed size data in query structure */
+#define QFIXEDSZ 4
+ /* number of bytes of fixed size data in resource record */
+#define RRFIXEDSZ 10
+
+/*
+ * Internet nameserver port number
+ */
+#define NAMESERVER_PORT 53
+
+/*
+ * Currently defined opcodes
+ */
+#define QUERY 0x0 /* standard query */
+#define IQUERY 0x1 /* inverse query */
+#define STATUS 0x2 /* nameserver status query */
+/*#define xxx 0x3 /* 0x3 reserved */
+ /* non standard */
+#define UPDATEA 0x9 /* add resource record */
+#define UPDATED 0xa /* delete a specific resource record */
+#define UPDATEDA 0xb /* delete all nemed resource record */
+#define UPDATEM 0xc /* modify a specific resource record */
+#define UPDATEMA 0xd /* modify all named resource record */
+
+#define ZONEINIT 0xe /* initial zone transfer */
+#define ZONEREF 0xf /* incremental zone referesh */
+
+/*
+ * Currently defined response codes
+ */
+#ifdef NOERROR /* defined by solaris2 in */
+#undef NOERROR /* <sys/stream.h> to be -1 */
+#endif
+#define NOERROR 0 /* no error */
+#define FORMERR 1 /* format error */
+#define SERVFAIL 2 /* server failure */
+#define NXDOMAIN 3 /* non existent domain */
+#define NOTIMP 4 /* not implemented */
+#define REFUSED 5 /* query refused */
+ /* non standard */
+#define NOCHANGE 0xf /* update failed to change db */
+
+/*
+ * Type values for resources and queries
+ */
+#define T_A 1 /* host address */
+#define T_NS 2 /* authoritative server */
+#define T_MD 3 /* mail destination */
+#define T_MF 4 /* mail forwarder */
+#define T_CNAME 5 /* connonical name */
+#define T_SOA 6 /* start of authority zone */
+#define T_MB 7 /* mailbox domain name */
+#define T_MG 8 /* mail group member */
+#define T_MR 9 /* mail rename name */
+#define T_NULL 10 /* null resource record */
+#define T_WKS 11 /* well known service */
+#define T_PTR 12 /* domain name pointer */
+#define T_HINFO 13 /* host information */
+#define T_MINFO 14 /* mailbox information */
+#define T_MX 15 /* mail routing information */
+#define T_TXT 16 /* text strings */
+ /* non standard */
+#define T_UINFO 100 /* user (finger) information */
+#define T_UID 101 /* user ID */
+#define T_GID 102 /* group ID */
+#define T_UNSPEC 103 /* Unspecified format (binary data) */
+ /* Query type values which do not appear in resource records */
+#define T_AXFR 252 /* transfer zone of authority */
+#define T_MAILB 253 /* transfer mailbox records */
+#define T_MAILA 254 /* transfer mail agent records */
+#define T_ANY 255 /* wildcard match */
+
+/*
+ * Values for class field
+ */
+
+#define C_IN 1 /* the arpa internet */
+#define C_CHAOS 3 /* for chaos net at MIT */
+#define C_HS 4 /* for Hesiod name server at MIT */
+ /* Query class values which do not appear in resource records */
+#define C_ANY 255 /* wildcard match */
+
+/*
+ * Status return codes for T_UNSPEC conversion routines
+ */
+#define CONV_SUCCESS 0
+#define CONV_OVERFLOW -1
+#define CONV_BADFMT -2
+#define CONV_BADCKSUM -3
+#define CONV_BADBUFLEN -4
+
+#ifndef BYTE_ORDER
+#define LITTLE_ENDIAN 1234 /* least-significant byte first (vax) */
+#define BIG_ENDIAN 4321 /* most-significant byte first (IBM, net) */
+#define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long (pdp) */
+
+#if defined(vax) || defined(ns32000) || defined(sun386) || defined(MIPSEL) || \
+ defined(BIT_ZERO_ON_RIGHT) || defined(sequent) || defined(i386) ||\
+ defined(___vax__) || defined(__ns32000__) || defined(__sun386__) ||\
+ defined(__alpha) || defined(_WIN32)
+#define BYTE_ORDER LITTLE_ENDIAN
+
+#endif
+#if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \
+ defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \
+ defined(MIPSEB) || defined(__hpux) || defined(__convex__) || \
+ defined(__pyr__) || defined(__mc68000__) || defined(__sparc__) ||\
+ defined(_IBMR2) || defined (BIT_ZERO_ON_LEFT)
+#define BYTE_ORDER BIG_ENDIAN
+#endif
+#endif /* BYTE_ORDER */
+
+#ifndef BYTE_ORDER
+/* you must determine what the correct bit order is for your compiler */
+ UNDEFINED_BIT_ORDER;
+#endif
+/*
+ * Structure for query header, the order of the fields is machine and
+ * compiler dependent, in our case, the bits within a byte are assignd
+ * least significant first, while the order of transmition is most
+ * significant first. This requires a somewhat confusing rearrangement.
+ */
+
+typedef struct {
+ u_short id; /* query identification number */
+#if BYTE_ORDER == BIG_ENDIAN
+ /* fields in third byte */
+ u_char qr:1; /* response flag */
+ u_char opcode:4; /* purpose of message */
+ u_char aa:1; /* authoritive answer */
+ u_char tc:1; /* truncated message */
+ u_char rd:1; /* recursion desired */
+ /* fields in fourth byte */
+ u_char ra:1; /* recursion available */
+ u_char pr:1; /* primary server required (non standard) */
+ u_char unused:2; /* unused bits */
+ u_char rcode:4; /* response code */
+#endif
+#if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN
+ /* fields in third byte */
+ u_char rd:1; /* recursion desired */
+ u_char tc:1; /* truncated message */
+ u_char aa:1; /* authoritive answer */
+ u_char opcode:4; /* purpose of message */
+ u_char qr:1; /* response flag */
+ /* fields in fourth byte */
+ u_char rcode:4; /* response code */
+ u_char unused:2; /* unused bits */
+ u_char pr:1; /* primary server required (non standard) */
+ u_char ra:1; /* recursion available */
+#endif
+ /* remaining bytes */
+ u_short qdcount; /* number of question entries */
+ u_short ancount; /* number of answer entries */
+ u_short nscount; /* number of authority entries */
+ u_short arcount; /* number of resource entries */
+} HEADER;
+
+/*
+ * Defines for handling compressed domain names
+ */
+#define INDIR_MASK 0xc0
+
+/*
+ * Structure for passing resource records around.
+ */
+struct rrec {
+ short r_zone; /* zone number */
+ short r_class; /* class number */
+ short r_type; /* type number */
+#ifdef __alpha
+ u_int r_ttl; /* time to live */
+#else
+ u_long r_ttl; /* time to live */
+#endif
+ int r_size; /* size of data area */
+ char *r_data; /* pointer to data */
+};
+
+extern u_short _getshort();
+#ifdef __alpha
+extern u_int _getlong();
+#else
+extern u_long _getlong();
+#endif
+
+/*
+ * Inline versions of get/put short/long.
+ * Pointer is advanced; we assume that both arguments
+ * are lvalues and will already be in registers.
+ * cp MUST be u_char *.
+ */
+#define GETSHORT(s, cp) { \
+ (s) = *(cp)++ << 8; \
+ (s) |= *(cp)++; \
+}
+
+#define GETLONG(l, cp) { \
+ (l) = *(cp)++ << 8; \
+ (l) |= *(cp)++; (l) <<= 8; \
+ (l) |= *(cp)++; (l) <<= 8; \
+ (l) |= *(cp)++; \
+}
+
+
+#define PUTSHORT(s, cp) { \
+ *(cp)++ = (s) >> 8; \
+ *(cp)++ = (s); \
+}
+
+/*
+ * Warning: PUTLONG destroys its first argument.
+ */
+#define PUTLONG(l, cp) { \
+ (cp)[3] = l; \
+ (cp)[2] = (l >>= 8); \
+ (cp)[1] = (l >>= 8); \
+ (cp)[0] = l >> 8; \
+ (cp) += sizeof(u_long); \
+}
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, include/numeric.h
+ * Copyright (C) 1990 Jarkko Oikarinen
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ */
+
+/*
+ * -- Potvin -- Feb 20/98
+ *
+ * Added numerics 600-799 as numeric_replies2[], we ran out
+ */
+
+/*
+ * Reserve numerics 000-099 for server-client connections where the client
+ * is local to the server. If any server is passed a numeric in this range
+ * from another server then it is remapped to 100-199.
+ */
+
+#define RPL_WELCOME 001
+#define RPL_YOURHOST 002
+#define RPL_CREATED 003
+#define RPL_MYINFO 004
+#define RPL_PROTOCTL 005
+
+/*
+ * Errors are in the range from 400-599 currently and are grouped by what
+ * commands they come from.
+ */
+#define ERR_NOSUCHNICK 401
+#define ERR_NOSUCHSERVER 402
+#define ERR_NOSUCHCHANNEL 403
+#define ERR_CANNOTSENDTOCHAN 404
+#define ERR_TOOMANYCHANNELS 405
+#define ERR_WASNOSUCHNICK 406
+#define ERR_TOOMANYTARGETS 407
+#define ERR_NOSUCHSERVICE 408
+#define ERR_NOORIGIN 409
+
+#define ERR_NORECIPIENT 411
+#define ERR_NOTEXTTOSEND 412
+#define ERR_NOTOPLEVEL 413
+#define ERR_WILDTOPLEVEL 414
+
+#define ERR_UNKNOWNCOMMAND 421
+#define ERR_NOMOTD 422
+#define ERR_NOADMININFO 423
+#define ERR_FILEERROR 424
+#define ERR_NOOPERMOTD 425
+#define ERR_NONICKNAMEGIVEN 431
+#define ERR_ERRONEUSNICKNAME 432
+#define ERR_NICKNAMEINUSE 433
+#define ERR_NORULES 434
+#define ERR_SERVICECONFUSED 435
+#define ERR_NICKCOLLISION 436
+#define ERR_BANNICKCHANGE 437
+#define ERR_NCHANGETOOFAST 438
+#define ERR_TARGETTOOFAST 439
+#define ERR_SERVICESDOWN 440
+
+#define ERR_USERNOTINCHANNEL 441
+#define ERR_NOTONCHANNEL 442
+#define ERR_USERONCHANNEL 443
+#define ERR_NOLOGIN 444
+#define ERR_SUMMONDISABLED 445
+#define ERR_USERSDISABLED 446
+
+#define ERR_NOTREGISTERED 451
+
+#define ERR_HOSTILENAME 455
+
+#define ERR_NOHIDING 459
+#define ERR_NOTFORHALFOPS 460
+#define ERR_NEEDMOREPARAMS 461
+#define ERR_ALREADYREGISTRED 462
+#define ERR_NOPERMFORHOST 463
+#define ERR_PASSWDMISMATCH 464
+#define ERR_YOUREBANNEDCREEP 465
+#define ERR_YOUWILLBEBANNED 466
+#define ERR_KEYSET 467
+#define ERR_ONLYSERVERSCANCHANGE 468
+#define ERR_LINKSET 469
+#define ERR_LINKCHANNEL 470
+#define ERR_CHANNELISFULL 471
+#define ERR_UNKNOWNMODE 472
+#define ERR_INVITEONLYCHAN 473
+#define ERR_BANNEDFROMCHAN 474
+#define ERR_BADCHANNELKEY 475
+#define ERR_BADCHANMASK 476
+#define ERR_NEEDREGGEDNICK 477
+#define ERR_BANLISTFULL 478
+#define ERR_LINKFAIL 479
+#define ERR_CANNOTKNOCK 480
+
+#define ERR_NOPRIVILEGES 481
+#define ERR_CHANOPRIVSNEEDED 482
+#define ERR_CANTKILLSERVER 483
+#define ERR_ATTACKDENY 484
+#define ERR_KILLDENY 485
+
+#define ERR_NOOPERHOST 491
+#define ERR_NOSERVICEHOST 492
+
+#define ERR_UMODEUNKNOWNFLAG 501
+#define ERR_USERSDONTMATCH 502
+
+#define ERR_SILELISTFULL 511
+#define ERR_TOOMANYWATCH 512
+#define ERR_NEEDPONG 513
+
+#define ERR_NOINVITE 518
+#define ERR_ADMONLY 519
+#define ERR_OPERONLY 520
+#define ERR_LISTSYNTAX 521
+
+/*
+ * Numberic replies from server commands.
+ * These are currently in the range 200-399.
+ */
+#define RPL_NONE 300
+#define RPL_AWAY 301
+#define RPL_USERHOST 302
+#define RPL_ISON 303
+#define RPL_TEXT 304
+#define RPL_UNAWAY 305
+#define RPL_NOWAWAY 306
+#define RPL_WHOISREGNICK 307
+#define RPL_RULESSTART 308
+#define RPL_ENDOFRULES 309
+#define RPL_WHOISHELPOP 310 /* -Donwulff */
+
+#define RPL_WHOISUSER 311
+#define RPL_WHOISSERVER 312
+#define RPL_WHOISOPERATOR 313
+
+#define RPL_WHOWASUSER 314
+/* rpl_endofwho below (315) */
+#define RPL_ENDOFWHOWAS 369
+
+#define RPL_WHOISCHANOP 316 /* redundant and not needed but reserved */
+#define RPL_WHOISIDLE 317
+
+#define RPL_ENDOFWHOIS 318
+#define RPL_WHOISCHANNELS 319
+#define RPL_WHOISSPECIAL 320
+#define RPL_LISTSTART 321
+#define RPL_LIST 322
+#define RPL_LISTEND 323
+#define RPL_CHANNELMODEIS 324
+#define RPL_CREATIONTIME 329
+#define RPL_NOTOPIC 331
+#define RPL_TOPIC 332
+#define RPL_TOPICWHOTIME 333
+
+#define RPL_LISTSYNTAX 334
+#define RPL_WHOISBOT 335
+#define RPL_INVITING 341
+#define RPL_SUMMONING 342
+
+#define RPL_VERSION 351
+
+#define RPL_WHOREPLY 352
+#define RPL_ENDOFWHO 315
+#define RPL_NAMREPLY 353
+#define RPL_ENDOFNAMES 366
+#define RPL_INVITELIST 346
+#define RPL_ENDOFINVITELIST 347
+
+#define RPL_EXLIST 348
+#define RPL_ENDOFEXLIST 349
+#define RPL_KILLDONE 361
+#define RPL_CLOSING 362
+#define RPL_CLOSEEND 363
+#define RPL_LINKS 364
+#define RPL_ENDOFLINKS 365
+/* rpl_endofnames above (366) */
+#define RPL_BANLIST 367
+#define RPL_ENDOFBANLIST 368
+/* rpl_endofwhowas above (369) */
+
+#define RPL_INFO 371
+#define RPL_MOTD 372
+#define RPL_INFOSTART 373
+#define RPL_ENDOFINFO 374
+#define RPL_MOTDSTART 375
+#define RPL_ENDOFMOTD 376
+
+#define RPL_WHOISHOST 378
+#define RPL_WHOISMODES 379
+#define RPL_YOUREOPER 381
+#define RPL_REHASHING 382
+#define RPL_YOURESERVICE 383
+#define RPL_MYPORTIS 384
+#define RPL_NOTOPERANYMORE 385
+
+#define RPL_TIME 391
+#define RPL_USERSSTART 392
+#define RPL_USERS 393
+#define RPL_ENDOFUSERS 394
+#define RPL_NOUSERS 395
+
+#define RPL_TRACELINK 200
+#define RPL_TRACECONNECTING 201
+#define RPL_TRACEHANDSHAKE 202
+#define RPL_TRACEUNKNOWN 203
+#define RPL_TRACEOPERATOR 204
+#define RPL_TRACEUSER 205
+#define RPL_TRACESERVER 206
+#define RPL_TRACESERVICE 207
+#define RPL_TRACENEWTYPE 208
+#define RPL_TRACECLASS 209
+
+#define RPL_STATSLINKINFO 211
+#define RPL_STATSCOMMANDS 212
+#define RPL_STATSCLINE 213
+#define RPL_STATSNLINE 214
+#define RPL_STATSILINE 215
+#define RPL_STATSKLINE 216
+#define RPL_STATSQLINE 217
+#define RPL_STATSYLINE 218
+#define RPL_ENDOFSTATS 219
+#define RPL_STATSBLINE 220
+
+#define RPL_UMODEIS 221
+#define RPL_SQLINE_NICK 222
+#define RPL_STATSGLINE 223
+#define RPL_STATSTLINE 224
+#define RPL_SERVICEINFO 231
+#define RPL_RULES 232
+#define RPL_SERVICE 233
+#define RPL_SERVLIST 234
+#define RPL_SERVLISTEND 235
+
+#define RPL_STATSLLINE 241
+#define RPL_STATSUPTIME 242
+#define RPL_STATSOLINE 243
+#define RPL_STATSHLINE 244
+#define RPL_STATSSLINE 245
+#define RPL_STATSXLINE 247
+#define RPL_STATSULINE 248
+#define RPL_STATSDEBUG 249
+#define RPL_STATSCONN 250
+
+#define RPL_LUSERCLIENT 251
+#define RPL_LUSEROP 252
+#define RPL_LUSERUNKNOWN 253
+#define RPL_LUSERCHANNELS 254
+#define RPL_LUSERME 255
+#define RPL_ADMINME 256
+#define RPL_ADMINLOC1 257
+#define RPL_ADMINLOC2 258
+#define RPL_ADMINEMAIL 259
+
+#define RPL_TRACELOG 261
+
+#define RPL_LOCALUSERS 265
+#define RPL_GLOBALUSERS 266
+
+#define RPL_SILELIST 271
+#define RPL_ENDOFSILELIST 272
+
+#define RPL_STATSDLINE 275
+
+#define RPL_HELPHDR 290
+#define RPL_HELPOP 291
+#define RPL_HELPTLR 292
+#define RPL_HELPHLP 293
+#define RPL_HELPFWD 294
+#define RPL_HELPIGN 295
+
+/*
+ * New /MAP format.
+ */
+#define RPL_MAP 006
+#define RPL_MAPMORE 610
+#define RPL_MAPEND 007
+
+/*
+ * Numberic replies from server commands.
+ * These are also in the range 600-799.
+ */
+
+#define RPL_LOGON 600
+#define RPL_LOGOFF 601
+#define RPL_WATCHOFF 602
+#define RPL_WATCHSTAT 603
+#define RPL_NOWON 604
+#define RPL_NOWOFF 605
+#define RPL_WATCHLIST 606
+#define RPL_ENDOFWATCHLIST 607
+#define RPL_DUMPING 640
+#define RPL_DUMPRPL 641
+#define RPL_EODUMP 642
--- /dev/null
+/*
+ * Relinfo.h
+ *
+ * If anyone makes another release or a hybrid of Unreal
+ * PLEASE CHANGE RELEASEID2 to the current time(NULL) (date +%s)
+ * if another hybrid please change releaseprefix
+ * if a unreal special edtion please select an IDTAG for it
+ * - Stskeeps -
+*/
+
+#include "stamp.h"
+#define RELEASEPREFIX "unrealircd"
+#define RELEASEIDTAG "000"
+#define RELEASEID RELEASEPREFIX "[" RELEASESTUFF "(" RELEASEID2 "/" RELEASEIDTAG ")]"
--- /dev/null
+/*
+ * irc2.7.2/ircd/res.h (C)opyright 1992 Darren Reed.
+ * $Id$
+ */
+#ifndef __res_include__
+#define __res_include__
+
+#define RES_INITLIST 1
+#define RES_CALLINIT 2
+#define RES_INITSOCK 4
+#define RES_INITDEBG 8
+#define RES_INITCACH 16
+
+#define MAXPACKET 1024
+#define MAXALIASES 35
+#define MAXADDRS 35
+
+#define AR_TTL 600 /* TTL in seconds for dns cache entries */
+
+struct hent {
+ char *h_name; /* official name of host */
+ char *h_aliases[MAXALIASES]; /* alias list */
+ int h_addrtype; /* host address type */
+ int h_length; /* length of address */
+ /* list of addresses from name server */
+ struct in_addr h_addr_list[MAXADDRS];
+#define h_addr h_addr_list[0] /* address, for backward compatiblity */
+};
+
+typedef struct reslist {
+ int id;
+ int sent; /* number of requests sent */
+ int srch;
+ time_t ttl;
+ char type;
+ char retries; /* retry counter */
+ char sends; /* number of sends (>1 means resent) */
+ char resend; /* send flag. 0 == dont resend */
+ time_t sentat;
+ time_t timeout;
+ struct in_addr addr;
+ char *name;
+ struct reslist *next;
+ Link cinfo;
+#ifndef _WIN32
+ struct hent he;
+#else
+ struct hostent *he;
+ char locked;
+#endif
+ } ResRQ;
+
+typedef struct cache {
+ time_t expireat;
+ time_t ttl;
+#ifndef _WIN32
+ struct hostent he;
+#else
+ struct hostent *he;
+#endif
+ struct cache *hname_next, *hnum_next, *list_next;
+ } aCache;
+
+typedef struct cachetable {
+ aCache *num_list;
+ aCache *name_list;
+ } CacheTable;
+
+#define ARES_CACSIZE 101
+
+#define MAXCACHED 81
+
+#endif /* __res_include__ */
--- /dev/null
+/*
+ * Copyright (c) 1983, 1987, 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement: ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Id$
+ * @(#)resolv.h 5.10.1 (Berkeley) 6/1/90
+ */
+
+/*
+ * Resolver configuration file.
+ * Normally not present, but may contain the address of the
+ * inital name server(s) to query and the domain search list.
+ */
+
+#ifndef _PATH_RESCONF
+#define _PATH_RESCONF "/etc/resolv.conf"
+#endif
+
+/*
+ * Global defines and variables for resolver stub.
+ */
+#define MAXNS 3 /* max # name servers we'll track */
+#define MAXDFLSRCH 3 /* # default domain levels to try */
+#define MAXDNSRCH 6 /* max # domains in search path */
+#define LOCALDOMAINPARTS 2 /* min levels in name that is "local" */
+#define MAXSERVICES 2 /* max # of services to search */
+
+#define RES_TIMEOUT 5 /* min. seconds between retries */
+
+struct state {
+ int retrans; /* retransmition time interval */
+ int retry; /* number of times to retransmit */
+ long options; /* option flags - see below. */
+ int nscount; /* number of name servers */
+ struct sockaddr_in nsaddr_list[MAXNS]; /* address of name server */
+#define nsaddr nsaddr_list[0] /* for backward compatibility */
+ unsigned short id; /* current packet id */
+ char defdname[MAXDNAME]; /* default domain */
+ char *dnsrch[MAXDNSRCH+1]; /* components of domain to search */
+ unsigned short order[MAXSERVICES+1]; /* search service order */
+};
+
+#define RES_SERVICE_NONE 0
+#define RES_SERVICE_BIND 1
+#define RES_SERVICE_LOCAL 2
+
+/*
+ * Resolver options
+ */
+#define RES_INIT 0x0001 /* address initialized */
+#define RES_DEBUG 0x0002 /* print debug messages */
+#define RES_AAONLY 0x0004 /* authoritative answers only */
+#define RES_USEVC 0x0008 /* use virtual circuit */
+#define RES_PRIMARY 0x0010 /* query primary server only */
+#define RES_IGNTC 0x0020 /* ignore trucation errors */
+#define RES_RECURSE 0x0040 /* recursion desired */
+#define RES_DEFNAMES 0x0080 /* use default domain name */
+#define RES_STAYOPEN 0x0100 /* Keep TCP socket open */
+#define RES_DNSRCH 0x0200 /* search up local domain tree */
+
+#define RES_DEFAULT (RES_RECURSE | RES_DEFNAMES | RES_DNSRCH)
+
+extern struct state _res;
+extern char *p_cdname(), *p_rr(), *p_type(), *p_class(), *p_time();
+
--- /dev/null
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by GENERIC.RC
+// $Id$
+#define IDC_USERID 1051
+#define IDC_REALNAME 1052
+#define IDC_PNICK 1053
+#define IDC_ANICK 1054
+#define IDC_SERVERLIST 1057
+#define IDC_NEWSERVER 1058
+#define IDC_EDITSERVER 1059
+#define IDC_IRCDCONF 1059
+#define IDC_DELSERVER 1060
+#define IDC_SHOW_GLOBOPS 1060
+#define IDC_SHOW_WALLOPS 1061
+#define IDC_SHOW_HELPOPS 1062
+#define IDC_SHOW_SERVNOTICE 1063
+#define IDC_INFOTEXT 1063
+#define IDM_OPEN 40001
+#define IDM_SAVE 40002
+#define IDM_SAVEAS 40003
+#define IDM_EXIT 40004
+#define IDM_ABOUT 40005
+#define IDM_WINDOWCHILD 40006
+#define IDM_REHASH 40007
+#define IDM_OPTIONS 40008
+#define IDM_CREDITS 40009
+#define IDM_DF 40010
+#define IDM_LICENSE 40011
+#define IDM_DBGOFF 41099
+#define IDM_DBGFATAL 41100
+#define IDM_DBGERROR 41101
+#define IDM_DBGNOTICE 41103
+#define IDM_DBGDNS 41104
+#define IDM_DBGINFO 41105
+#define IDM_DBGNUM 41106
+#define IDM_DBGSEND 41107
+#define IDM_DBGDEBUG 41108
+#define IDM_DBGMALLOC 41109
+#define IDM_DBGLIST 41110
+#define IDM_POPUP 50000
+#define IDC_STATIC -1
+#define IDM_IRCDRULES 65530
+#define IDM_IRCDMOTD 65531
+#define IDC_VERSION 65532
+#define IDM_SETUP 65536
+#define IDM_IRCDCONF 65535
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NO_MFC 1
+#define _APS_NEXT_RESOURCE_VALUE 113
+#define _APS_NEXT_COMMAND_VALUE 40011
+#define _APS_NEXT_CONTROL_VALUE 1064
+#define _APS_NEXT_SYMED_VALUE 104
+#endif
+#endif
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, include/sjoin.h
+ * (C) Carsten Munk 2000
+ * Contains code from StarChat IRCd, (C) their respective authors
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ */
+
+
+typedef struct SynchList aSynchList;
+
+/* SJOIN synch structure */
+struct SynchList {
+ char nick[NICKLEN];
+ int deop;
+ int devoice;
+ int dehalf;
+ int deown;
+ int deprot;
+ int op;
+ int voice;
+ int half;
+ int own;
+ int prot;
+ aSynchList *next, *prev;
+};
+
+aSynchList *SJSynchList = NULL;
+
+aSynchList *make_synchlist()
+{
+ Reg1 aSynchList *synchptr;
+
+ synchptr = (aSynchList *) MyMalloc(sizeof(aSynchList));
+
+ synchptr->nick[0] = 0;
+ synchptr->deop = synchptr->dehalf = synchptr->deown = synchptr->deprot = 0;
+ synchptr->devoice = 0;
+ synchptr->op = 0;
+ synchptr->voice = synchptr->half = synchptr->own = synchptr->prot = 0;
+ synchptr->prev = synchptr->next = NULL;
+
+ return synchptr;
+}
+
+void free_synchlist(synchptr)
+ aSynchList *synchptr;
+{
+ MyFree((char *) synchptr);
+}
+
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, include/sock.h
+ * Copyright (C) 1990 Jarkko Oikarinen and
+ * University of Oulu, Computing Center
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * $Id$
+ *
+ * $Log$
+ * Revision 1.1.1.1 2000/01/30 12:16:33 stskeeps
+ * Begin of CVS at cvs.unreal.sourceforge.net
+ *
+ *
+ * Revision 1.1.1.1 1999/09/01 23:20:37 stskeeps
+ *
+ * Revision 1.2 1999/07/22 14:09:26 stskeeps
+ * *** empty log message ***
+ *
+ * Revision 1.1.1.1 1999/07/22 13:56:40 stskeeps
+ * 16:56 22-07-99 techie
+ * - Started on using CVS to develop Unreal
+ *
+ *
+ * Revision 1.1.1.1 1999/07/21 10:48:18 stskeeps
+ * 12:47 GMT+2 21 July 1999 - Techie
+ * Starting Unreal with CVS..
+ *
+ * Revision 1.2 1997/12/29 07:17:35 wd
+ * df4.6.2
+ * ee CHANGES for updates
+ * -wd
+ *
+ * Revision 1.1.1.1 1997/08/22 17:23:01 donwulff
+ * Original import from the "deadlined" version.
+ *
+ * Revision 1.1.1.1 1996/11/18 07:53:41 explorer
+ * ircd 4.3.3 -- about time
+ *
+ * Revision 1.1.1.1.4.1 1996/09/16 02:45:38 donwulff
+ * *** empty log message ***
+ *
+ * Revision 6.1 1991/07/04 21:04:35 gruner
+ * Revision 2.6.1 [released]
+ *
+ * Revision 6.0 1991/07/04 18:05:04 gruner
+ * frozen beta revision 2.6.1
+ *
+ */
+
+#ifndef FD_ZERO
+#define FD_ZERO(set) (((set)->fds_bits[0]) = 0)
+#define FD_SET(s1, set) (((set)->fds_bits[0]) |= 1 << (s1))
+#define FD_ISSET(s1, set) (((set)->fds_bits[0]) & (1 << (s1)))
+#define FD_SETSIZE 30
+#endif
+
+#ifdef RCVTIMEO
+#define SO_RCVTIMEO 0x1006 /* receive timeout */
+#endif
+
--- /dev/null
+/* Auto created release stamping */
+#define RELEASEID2 "951777936"
+#define RELEASESTUFF "draconic"
+
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, include/struct.h
+ * Copyright (C) 1990 Jarkko Oikarinen and
+ * University of Oulu, Computing Center
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ */
+
+#ifndef __struct_include__
+#define __struct_include__
+
+#include "config.h"
+#include "common.h"
+#include "sys.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#ifndef _WIN32
+#include <netinet/in.h>
+#include <netdb.h>
+#endif
+#ifdef STDDEFH
+# include <stddef.h>
+#endif
+
+#ifdef USE_SYSLOG
+# include <syslog.h>
+# ifdef SYSSYSLOGH
+# include <sys/syslog.h>
+# endif
+#endif
+#ifdef pyr
+#include <sys/time.h>
+#endif
+
+typedef struct t_fline aFline;
+typedef struct t_crline aCRline;
+typedef struct t_vhline aVHline;
+typedef struct t_kline aTKline;
+typedef struct t_vhost aVhost;
+typedef struct t_hush aHush;
+
+typedef struct SqlineItem aSqlineItem;
+typedef struct ConfItem aConfItem;
+typedef struct Notify aNotify;
+typedef struct Client aClient;
+typedef struct Channel aChannel;
+typedef struct User anUser;
+typedef struct Server aServer;
+typedef struct SLink Link;
+typedef struct SBan Ban;
+typedef struct SMode Mode;
+typedef struct ListOptions LOpts;
+typedef struct FloodOpt aFloodOpt;
+typedef struct CloneItem aClone;
+
+#ifdef NEED_U_INT32_T
+typedef unsigned int u_int32_t; /* XXX Hope this works! */
+#endif
+
+#ifndef VMSP
+#include "class.h"
+#include "dbuf.h" /* THIS REALLY SHOULDN'T BE HERE!!! --msa */
+#endif
+
+#define HOSTLEN 63 /* Length of hostname. Updated to */
+ /* comply with RFC1123 */
+
+#define NICKLEN 30 /* Necessary to put 9 here instead of 10
+ ** if s_msg.c/m_nick has been corrected.
+ ** This preserves compatibility with old
+ ** servers --msa
+ */
+#define USERLEN 10
+#define REALLEN 50
+#define TOPICLEN 307
+/* DAL MADE ME PUT THIS IN THE FIEND: --Russell
+ * This number will be expanded to 200 in the near future
+ */
+#define CHANNELLEN 32
+#define PASSWDLEN 32 /* orig. 20, changed to 32 for nickpasswords */
+#define KEYLEN 23
+#define LINKLEN 32
+#define BUFSIZE 512 /* WARNING: *DONT* CHANGE THIS!!!! */
+#define MAXRECIPIENTS 20
+#define MAXKILLS 20
+#define MAXBANS 60
+#define MAXBANLENGTH 1024
+#define MAXSILES 5
+#define MAXSILELENGTH 128
+/*
+ * Watch it - Don't change this unless you also change the ERR_TOOMANYWATCH
+ * and PROTOCOL_SUPPORTED settings.
+ */
+#define MAXWATCH 128
+
+#define USERHOST_REPLYLEN (NICKLEN+HOSTLEN+USERLEN+5)
+
+#ifdef USE_SERVICES
+#include "service.h"
+#endif
+
+/* NOTE: this must be down here so the stuff from struct.h IT uses works */
+#include "whowas.h"
+
+
+/*
+** 'offsetof' is defined in ANSI-C. The following definition
+** is not absolutely portable (I have been told), but so far
+** it has worked on all machines I have needed it. The type
+** should be size_t but... --msa
+*/
+#ifndef offsetof
+#define offsetof(t,m) (int)((&((t *)0L)->m))
+#endif
+
+#define elementsof(x) (sizeof(x)/sizeof(x[0]))
+
+/*
+** flags for bootup options (command line flags)
+*/
+#define BOOT_CONSOLE 1
+#define BOOT_QUICK 2
+#define BOOT_DEBUG 4
+#define BOOT_INETD 8
+#define BOOT_TTY 16
+#define BOOT_OPER 32
+#define BOOT_AUTODIE 64
+
+#define STAT_LOG -6 /* logfile for -x */
+#define STAT_MASTER -5 /* Local ircd master before identification */
+#define STAT_CONNECTING -4
+#define STAT_HANDSHAKE -3
+#define STAT_ME -2
+#define STAT_UNKNOWN -1
+#define STAT_SERVER 0
+#define STAT_CLIENT 1
+#define STAT_SERVICE 2 /* Services not implemented yet */
+
+/*
+ * status macros.
+ */
+#define IsRegisteredUser(x) ((x)->status == STAT_CLIENT)
+#define IsRegistered(x) ((x)->status >= STAT_SERVER)
+#define IsConnecting(x) ((x)->status == STAT_CONNECTING)
+#define IsHandshake(x) ((x)->status == STAT_HANDSHAKE)
+#define IsMe(x) ((x)->status == STAT_ME)
+#define IsUnknown(x) ((x)->status == STAT_UNKNOWN || \
+ (x)->status == STAT_MASTER)
+#define IsServer(x) ((x)->status == STAT_SERVER)
+#define IsClient(x) ((x)->status == STAT_CLIENT)
+#define IsLog(x) ((x)->status == STAT_LOG)
+#define IsService(x) 0
+
+#define SetMaster(x) ((x)->status = STAT_MASTER)
+#define SetConnecting(x) ((x)->status = STAT_CONNECTING)
+#define SetHandshake(x) ((x)->status = STAT_HANDSHAKE)
+#define SetMe(x) ((x)->status = STAT_ME)
+#define SetUnknown(x) ((x)->status = STAT_UNKNOWN)
+#define SetServer(x) ((x)->status = STAT_SERVER)
+#define SetClient(x) ((x)->status = STAT_CLIENT)
+#define SetLog(x) ((x)->status = STAT_LOG)
+#define SetService(x) ((x)->status = STAT_SERVICE)
+
+#define FLAGS_PINGSENT 0x0001 /* Unreplied ping sent */
+#define FLAGS_DEADSOCKET 0x0002 /* Local socket is dead--Exiting soon */
+#define FLAGS_KILLED 0x0004 /* Prevents "QUIT" from being sent for this */
+#define FLAGS_BLOCKED 0x0008 /* socket is in a blocked condition */
+#define FLAGS_UNIX 0x0010 /* socket is in the unix domain, not inet */
+#define FLAGS_CLOSING 0x0020 /* set when closing to suppress errors */
+#define FLAGS_LISTEN 0x0040 /* used to mark clients which we listen() on */
+#define FLAGS_CHKACCESS 0x0080 /* ok to check clients access if set */
+#define FLAGS_DOINGDNS 0x0100 /* client is waiting for a DNS response */
+#define FLAGS_AUTH 0x0200 /* client is waiting on rfc931 response */
+#define FLAGS_WRAUTH 0x0400 /* set if we havent writen to ident server */
+#define FLAGS_LOCAL 0x0800 /* set for local clients */
+#define FLAGS_GOTID 0x1000 /* successful ident lookup achieved */
+#define FLAGS_DOID 0x2000 /* I-lines say must use ident return */
+#define FLAGS_NONL 0x4000 /* No \n in buffer */
+#define FLAGS_TS8 0x8000 /* Why do you want to know? */
+#define FLAGS_ULINE 0x10000 /* User/server is considered U-lined */
+#define FLAGS_SQUIT 0x20000 /* Server has been /squit by an oper */
+#define FLAGS_PROTOCTL 0x40000 /* Received a PROTOCTL message */
+#define FLAGS_PING 0x80000
+#define FLAGS_ASKEDPING 0x100000
+#define FLAGS_NETINFO 0x200000
+#define FLAGS_HYBNOTICE 0x400000
+#ifdef SOCKSPORT
+#define FLAGS_SOCKS 0x800000
+#define FLAGS_WRSOCKS 0x1000000
+#define FLAGS_GOTSOCKS 0x2000000
+#endif
+#define FLAGS_HUSHED 0x4000000
+#define FLAGS_MAP 0x80000000 /* Show this entry in /map */
+
+/* Dec 26th, 1997 - added flags2 when I ran out of room in flags -DuffJ
+
+/* Dec 26th, 1997 - having a go at
+ * splitting flags into flags and umodes
+ * -DuffJ
+ */
+
+#define UMODE_INVISIBLE 0x0001 /* makes user invisible */
+#define UMODE_OPER 0x0002 /* Operator */
+#define UMODE_WALLOP 0x0004 /* send wallops to them */
+#define UMODE_FAILOP 0x0008 /* Shows some global messages */
+#define UMODE_HELPOP 0x0010 /* Help system operator */
+#define UMODE_REGNICK 0x0020 /* Nick set by services as registered */
+#define UMODE_SADMIN 0x0040 /* Services Admin */
+#define UMODE_ADMIN 0x0080 /* Admin */
+#define UMODE_SERVNOTICE 0x0100 /* server notices such as kill */
+#define UMODE_LOCOP 0x0200 /* Local operator -- SRB */
+#define UMODE_KILLS 0x0400 /* Show server-kills... */
+#define UMODE_CLIENT 0x0800 /* Show client information */
+#define UMODE_FLOOD 0x1000 /* Receive flood warnings */
+#define UMODE_CHATOP 0x2000 /* can receive chatops */
+#define UMODE_SERVICES 0x4000 /* services */
+#define UMODE_HIDE 0x8000 /* Hide from Nukes */
+#define UMODE_NETADMIN 0x10000 /* Network Admin */
+#define UMODE_EYES 0x20000 /* Mode to see server stuff */
+#define UMODE_TECHADMIN 0x40000 /* Tech Admin */
+#define UMODE_COADMIN 0x80000 /* Co Admin */
+#define UMODE_WHOIS 0x100000 /* gets notice on /whois */
+#define UMODE_KIX 0x200000 /* usermode +q */
+#define UMODE_BOT 0x400000 /* User is a bot */
+#define UMODE_CODER 0x800000 /* User is a network coder */
+#define UMODE_FCLIENT 0x1000000 /* recieve client on far connects.. */
+#define UMODE_HIDING 0x2000000 /* Totally invisible .. */
+#define UMODE_AGENT 0x4000000 /* Is an IRCd Agent local only */
+#define UMODE_VICTIM 0x8000000 /* Intentional Victim */
+#define UMODE_DEAF 0x10000000
+#define UMODE_HIDEOPER 0x20000000 /* Hide oper mode */
+#define UMODE_SETHOST 0x40000000 /* used sethost */
+
+#define SEND_UMODES (UMODE_INVISIBLE|UMODE_OPER|UMODE_WALLOP|UMODE_FAILOP|UMODE_HELPOP|UMODE_REGNICK|UMODE_SADMIN|UMODE_NETADMIN|UMODE_TECHADMIN|UMODE_COADMIN|UMODE_ADMIN|UMODE_SERVICES|UMODE_HIDE|UMODE_EYES|UMODE_WHOIS|UMODE_KIX|UMODE_BOT|UMODE_CODER|UMODE_FCLIENT|UMODE_HIDING|UMODE_AGENT|UMODE_DEAF|UMODE_VICTIM|UMODE_HIDEOPER|UMODE_SETHOST)
+#define ALL_UMODES (SEND_UMODES|UMODE_SERVNOTICE|UMODE_LOCOP|UMODE_KILLS|UMODE_CLIENT|UMODE_FLOOD|UMODE_CHATOP|UMODE_SERVICES|UMODE_EYES|UMODE_AGENT)
+#define FLAGS_ID (FLAGS_DOID|FLAGS_GOTID)
+
+#define PROTO_NOQUIT 0x1 /* Negotiated NOQUIT protocol */
+#define PROTO_TOKEN 0x2 /* Negotiated TOKEN protocol */
+#define PROTO_SJOIN 0x4 /* Negotiated SJOIN protocol */
+#define PROTO_NICKv2 0x8 /* Negotiated NICKv2 protocol */
+#define PROTO_SJOIN2 0x10 /* Negotiated SJOIN2 protocol */
+/*
+ * flags macros.
+ */
+#define IsVictim(x) ((x)->umodes & UMODE_VICTIM)
+#define IsDeaf(x) ((x)->umodes & UMODE_DEAF)
+#define IsKillsF(x) ((x)->umodes & UMODE_KILLS)
+#define IsClientF(x) ((x)->umodes & UMODE_CLIENT)
+#define IsFloodF(x) ((x)->umodes & UMODE_FLOOD)
+#define IsEyes(x) ((x)->umodes & UMODE_EYES)
+#define IsWhois(x) ((x)->umodes & UMODE_WHOIS)
+#define IsKix(x) ((x)->umodes & UMODE_KIX)
+#define IsHelpOp(x) ((x)->umodes & UMODE_HELPOP)
+#define IsAdmin(x) ((x)->umodes & UMODE_ADMIN)
+#define IsHiding(x) ((x)->umodes & UMODE_HIDING)
+#define IsNetAdmin(x) ((x)->umodes & UMODE_NETADMIN)
+#define IsTechAdmin(x) ((x)->umodes & UMODE_TECHADMIN)
+#define IsCoAdmin(x) ((x)->umodes & UMODE_COADMIN)
+#define IsSAdmin(x) ((x)->umodes & UMODE_SADMIN)
+#define SendFailops(x) ((x)->umodes & UMODE_FAILOP)
+#define SendChatops(x) ((x)->umodes & UMODE_CHATOP)
+#define IsOper(x) ((x)->umodes & UMODE_OPER)
+#define IsLocOp(x) ((x)->umodes & UMODE_LOCOP)
+#define IsAgent(x) ((x)->umodes & UMODE_AGENT)
+#define IsInvisible(x) ((x)->umodes & UMODE_INVISIBLE)
+#define IsServices(x) ((x)->umodes & UMODE_SERVICES)
+#define IsAnOper(x) ((x)->umodes & (UMODE_OPER|UMODE_LOCOP))
+#define IsARegNick(x) ((x)->umodes & (UMODE_REGNICK))
+#define IsRegNick(x) ((x)->umodes & UMODE_REGNICK)
+#define IsPerson(x) ((x)->user && IsClient(x))
+#define IsPasser(x) ((x)->user & UMODE_PASSER)
+#define IsPrivileged(x) (IsAnOper(x) || IsServer(x))
+#define SendWallops(x) ((x)->umodes & UMODE_WALLOP)
+#define SendServNotice(x) ((x)->umodes & UMODE_SERVNOTICE)
+#define IsUnixSocket(x) ((x)->flags & FLAGS_UNIX)
+#define IsListening(x) ((x)->flags & FLAGS_LISTEN)
+#define DoAccess(x) ((x)->flags & FLAGS_CHKACCESS)
+#define IsLocal(x) ((x)->flags & FLAGS_LOCAL)
+#define IsDead(x) ((x)->flags & FLAGS_DEADSOCKET)
+#define GotProtoctl(x) ((x)->flags & FLAGS_PROTOCTL)
+#define IsBlocked(x) ((x)->flags & FLAGS_BLOCKED)
+#define GotNetInfo(x) ((x)->flags & FLAGS_NETINFO)
+#define SetNetInfo(x) ((x)->flags |= FLAGS_NETINFO)
+
+#define IsHushed(x) ((x)->flags & FLAGS_HUSHED)
+#define SetHushed(x) ((x)->flags |= FLAGS_HUSHED)
+#define ClearHushed(x) ((x)->flags &= ~FLAGS_HUSHED)
+
+#define IsHybNotice(x) ((x)->flags & FLAGS_HYBNOTICE)
+#define SetHybNotice(x) ((x)->flags |= FLAGS_HYBNOTICE)
+#define IsHidden(x) ((x)->umodes & UMODE_HIDE)
+#define IsHideOper(x) ((x)->umodes & UMODE_HIDEOPER)
+
+#ifdef NOSPOOF
+#define IsNotSpoof(x) ((x)->nospoof == 0)
+#else
+#define IsNotSpoof(x) (1)
+#endif
+
+#define SetKillsF(x) ((x)->umodes |= UMODE_KILLS)
+#define SetClientF(x) ((x)->umodes |= UMODE_CLIENT)
+#define SetFloodF(x) ((x)->umodes |= UMODE_FLOOD)
+#define SetHelpOp(x) ((x)->umodes |= UMODE_HELPOP)
+#define SetOper(x) ((x)->umodes |= UMODE_OPER)
+#define SetLocOp(x) ((x)->umodes |= UMODE_LOCOP)
+#define SetAgent(x) ((x)->umodes |= UMODE_AGENT)
+#define SetAdmin(x) ((x)->umodes |= UMODE_ADMIN)
+#define SetSAdmin(x) ((x)->umodes |= UMODE_SADMIN)
+#define SetNetAdmin(x) ((x)->umodes |= UMODE_NETADMIN)
+#define SetTechAdmin(x) ((x)->umodes |= UMODE_TECHADMIN)
+#define SetCoAdmin(x) ((x)->umodes |= UMODE_COADMIN)
+#define SetInvisible(x) ((x)->umodes |= UMODE_INVISIBLE)
+#define SetEyes(x) ((x)->umodes |= UMODE_EYES)
+#define SetWallops(x) ((x)->umodes |= UMODE_WALLOP)
+#define SetUnixSock(x) ((x)->flags |= FLAGS_UNIX)
+#define SetDNS(x) ((x)->flags |= FLAGS_DOINGDNS)
+#define DoingDNS(x) ((x)->flags & FLAGS_DOINGDNS)
+#define SetAccess(x) ((x)->flags |= FLAGS_CHKACCESS)
+#define SetBlocked(x) ((x)->flags |= FLAGS_BLOCKED)
+#define DoingAuth(x) ((x)->flags & FLAGS_AUTH)
+#ifdef SOCKSPORT
+#define DoingSocks(x) ((x)->flags & FLAGS_SOCKS)
+#endif
+#define NoNewLine(x) ((x)->flags & FLAGS_NONL)
+#define SetRegNick(x) ((x)->umodes & UMODE_REGNICK)
+#define SetHidden(x) ((x)->umodes |= UMODE_HIDE)
+#define SetHideOper(x) ((x)->umodes |= UMODE_HIDEOPER)
+
+#define ClearAdmin(x) ((x)->umodes &= ~UMODE_ADMIN)
+#define ClearNetAdmin(x) ((x)->umodes &= ~UMODE_NETADMIN)
+#define ClearTechAdmin(x) ((x)->umodes &= ~UMODE_TECHADMIN)
+#define ClearCoAdmin(x) ((x)->umodes &= ~UMODE_COADMIN)
+#define ClearSAdmin(x) ((x)->umodes &= ~UMODE_SADMIN)
+#define ClearKillsF(x) ((x)->umodes &= ~UMODE_KILLS)
+#define ClearClientF(x) ((x)->umodes &= ~UMODE_CLIENT)
+#define ClearFloodF(x) ((x)->umodes &= ~UMODE_FLOOD)
+#define ClearEyes(x) ((x)->umodes &= ~UMODE_EYES)
+#define ClearHelpOp(x) ((x)->umodes &= ~UMODE_HELPOP)
+#define ClearFailops(x) ((x)->umodes &= ~UMODE_FAILOP)
+#define ClearChatops(x) ((x)->umodes &= ~UMODE_CHATOP)
+#define ClearOper(x) ((x)->umodes &= ~UMODE_OPER)
+#define ClearAgent(x) ((x)->umodes &= ~UMODE_AGENT)
+#define ClearInvisible(x) ((x)->umodes &= ~UMODE_INVISIBLE)
+#define ClearServices(x) ((x)->umodes &= ~UMODE_SERVICES)
+#define ClearWallops(x) ((x)->umodes &= ~UMODE_WALLOP)
+#define ClearDNS(x) ((x)->flags &= ~FLAGS_DOINGDNS)
+#define ClearAuth(x) ((x)->flags &= ~FLAGS_AUTH)
+#define ClearAccess(x) ((x)->flags &= ~FLAGS_CHKACCESS)
+#define ClearBlocked(x) ((x)->flags &= ~FLAGS_BLOCKED)
+#define ClearHidden(x) ((x)->umodes &= ~UMODE_HIDE)
+#define ClearHideOper(x) ((x)->umodes &= ~UMODE_HIDEOPER)
+
+#ifdef SOCKSPORT
+#define ClearSocks(x) ((x)->flags &= ~FLAGS_SOCKS)
+#endif
+
+/*
+ * ProtoCtl options
+ */
+#define DontSendQuit(x) ((x)->proto & PROTO_NOQUIT)
+#define IsToken(x) ((x)->proto & PROTO_TOKEN)
+#define SupportSJOIN(x) ((x)->proto & PROTO_SJOIN)
+#define SupportNICKv2(x) ((x)->proto & PROTO_NICKv2)
+#define SupportSJOIN2(x) ((x)->proto & PROTO_SJOIN2)
+
+#define SetSJOIN(x) ((x)->proto |= PROTO_SJOIN)
+#define SetNoQuit(x) ((x)->proto |= PROTO_NOQUIT)
+#define SetToken(x) ((x)->proto |= PROTO_TOKEN)
+#define SetNICKv2(x) ((x)->proto |= PROTO_NICKv2)
+#define SetSJOIN2(x) ((x)->proto |= PROTO_SJOIN2)
+
+#define ClearSJOIN(x) ((x)->proto &= ~PROTO_SJOIN)
+#define ClearNoQuit(x) ((x)->proto &= ~PROTO_NOQUIT)
+#define ClearToken(x) ((x)->proto &= ~PROTO_TOKEN)
+#define ClearNICKv2(x) ((x)->proto &= ~PROTO_NICKv2)
+#define ClearSJOIN2(x) ((x)->proto &= ~PROTO_SJOIN2)
+
+/*
+ * defined operator access levels
+ */
+#define OFLAG_REHASH 0x00000001 /* Oper can /rehash server */
+#define OFLAG_DIE 0x00000002 /* Oper can /die the server */
+#define OFLAG_RESTART 0x00000004 /* Oper can /restart the server */
+#define OFLAG_HELPOP 0x00000010 /* Oper can send /HelpOps */
+#define OFLAG_GLOBOP 0x00000020 /* Oper can send /GlobOps */
+#define OFLAG_WALLOP 0x00000040 /* Oper can send /WallOps */
+#define OFLAG_LOCOP 0x00000080 /* Oper can send /LocOps */
+#define OFLAG_LROUTE 0x00000100 /* Oper can do local routing */
+#define OFLAG_GROUTE 0x00000200 /* Oper can do global routing */
+#define OFLAG_LKILL 0x00000400 /* Oper can do local kills */
+#define OFLAG_GKILL 0x00000800 /* Oper can do global kills */
+#define OFLAG_KLINE 0x00001000 /* Oper can /kline users */
+#define OFLAG_UNKLINE 0x00002000 /* Oper can /unkline users */
+#define OFLAG_LNOTICE 0x00004000 /* Oper can send local serv notices */
+#define OFLAG_GNOTICE 0x00008000 /* Oper can send global notices */
+#define OFLAG_ADMIN 0x00010000 /* Admin */
+#define OFLAG_UMODEC 0x00020000 /* Oper can set umode +c */
+#define OFLAG_UMODEF 0x00040000 /* Oper can set umode +f */
+#define OFLAG_ZLINE 0x00080000 /* Oper can use /zline and /unzline */
+#define OFLAG_EYES 0x00100000 /* Oper auto gets +e */
+#define OFLAG_NETADMIN 0x00200000 /* netadmin gets +N */
+#define OFLAG_TECHADMIN 0x00400000 /* tech admin gets +T */
+#define OFLAG_COADMIN 0x00800000 /* co admin gets +C */
+#define OFLAG_SADMIN 0x01000000 /* services admin gets +a */
+#define OFLAG_WHOIS 0x02000000 /* gets auto +W on oper up */
+#define OFLAG_HIDE 0x04000000 /* gets auto +x on oper up */
+#define OFLAG_AGENT 0x08000000 /* Is an IRCd Agent */
+#define OFLAG_AFOUNDER 0x10000000
+#define OFLAG_COFOUND 0x20000000
+#define OFLAG_WMASTER 0x40000000
+#define OFLAG_INVISIBLE 0x80000000
+#define OFLAG_LOCAL (OFLAG_REHASH|OFLAG_HELPOP|OFLAG_GLOBOP|OFLAG_WALLOP|OFLAG_LOCOP|OFLAG_LROUTE|OFLAG_LKILL|OFLAG_KLINE|OFLAG_UNKLINE|OFLAG_LNOTICE|OFLAG_UMODEC|OFLAG_UMODEF)
+#define OFLAG_GLOBAL (OFLAG_LOCAL|OFLAG_GROUTE|OFLAG_GKILL|OFLAG_GNOTICE)
+#define OFLAG_ISGLOBAL (OFLAG_GROUTE|OFLAG_GKILL|OFLAG_GNOTICE)
+
+
+#define OPCanZline(x) ((x)->oflag & OFLAG_ZLINE)
+#define OPCanRehash(x) ((x)->oflag & OFLAG_REHASH)
+#define OPCanDie(x) ((x)->oflag & OFLAG_DIE)
+#define OPCanRestart(x) ((x)->oflag & OFLAG_RESTART)
+#define OPCanHelpOp(x) ((x)->oflag & OFLAG_HELPOP)
+#define OPCanGlobOps(x) ((x)->oflag & OFLAG_GLOBOP)
+#define OPCanWallOps(x) ((x)->oflag & OFLAG_WALLOP)
+#define OPCanLocOps(x) ((x)->oflag & OFLAG_LOCOP)
+#define OPCanLRoute(x) ((x)->oflag & OFLAG_LROUTE)
+#define OPCanGRoute(x) ((x)->oflag & OFLAG_GROUTE)
+#define OPCanLKill(x) ((x)->oflag & OFLAG_LKILL)
+#define OPCanGKill(x) ((x)->oflag & OFLAG_GKILL)
+#define OPCanKline(x) ((x)->oflag & OFLAG_KLINE)
+#define OPCanUnKline(x) ((x)->oflag & OFLAG_UNKLINE)
+#define OPCanLNotice(x) ((x)->oflag & OFLAG_LNOTICE)
+#define OPCanGNotice(x) ((x)->oflag & OFLAG_GNOTICE)
+#define OPIsAdmin(x) ((x)->oflag & OFLAG_ADMIN)
+#define OPIsSAdmin(x) ((x)->oflag & OFLAG_SADMIN)
+#define OPIsNetAdmin(x) ((x)->oflag & OFLAG_NETADMIN)
+#define OPIsTechAdmin(x) ((x)->oflag & OFLAG_TECHADMIN)
+#define OPIsCoAdmin(x) ((x)->oflag & OFLAG_COADMIN)
+#define OPCanUModeC(x) ((x)->oflag & OFLAG_UMODEC)
+#define OPCanUModeF(x) ((x)->oflag & OFLAG_UMODEF)
+#define OPIsEyes(x) ((x)->oflag & OFLAG_EYES)
+#define OPIsWhois(x) ((x)->oflag & OFLAG_WHOIS)
+
+#define OPSetRehash(x) ((x)->oflag |= OFLAG_REHASH)
+#define OPSetDie(x) ((x)->oflag |= OFLAG_DIE)
+#define OPSetRestart(x) ((x)->oflag |= OFLAG_RESTART)
+#define OPSetHelpOp(x) ((x)->oflag |= OFLAG_HELPOP)
+#define OPSetGlobOps(x) ((x)->oflag |= OFLAG_GLOBOP)
+#define OPSetWallOps(x) ((x)->oflag |= OFLAG_WALLOP)
+#define OPSetLocOps(x) ((x)->oflag |= OFLAG_LOCOP)
+#define OPSetLRoute(x) ((x)->oflag |= OFLAG_LROUTE)
+#define OPSetGRoute(x) ((x)->oflag |= OFLAG_GROUTE)
+#define OPSetLKill(x) ((x)->oflag |= OFLAG_LKILL)
+#define OPSetGKill(x) ((x)->oflag |= OFLAG_GKILL)
+#define OPSetKline(x) ((x)->oflag |= OFLAG_KLINE)
+#define OPSetUnKline(x) ((x)->oflag |= OFLAG_UNKLINE)
+#define OPSetLNotice(x) ((x)->oflag |= OFLAG_LNOTICE)
+#define OPSetGNotice(x) ((x)->oflag |= OFLAG_GNOTICE)
+#define OPSSetAdmin(x) ((x)->oflag |= OFLAG_ADMIN)
+#define OPSSetSAdmin(x) ((x)->oflag |= OFLAG_SADMIN)
+#define OPSSetNetAdmin(x) ((x)-> oflag |= OFLAG_NETADMIN)
+#define OPSSetTechAdmin(x) ((x)-> oflag |= OFLAG_TECHADMIN)
+#define OPSSetCoAdmin(x) ((x)->oflag |= OFLAG_COADMIN)
+#define OPSetUModeC(x) ((x)->oflag |= OFLAG_UMODEC)
+#define OPSetUModeF(x) ((x)->oflag |= OFLAG_UMODEF)
+#define OPSetEyes(x) ((x)->oflag |= OFLAG_EYES)
+#define OPSetZLine(x) ((x)->oflag |= OFLAG_ZLINE)
+#define OPSetWhois(x) ((x)->oflag |= OFLAG_WHOIS)
+#define OPSetPasser(x) ((x)->oflag |= OFLAG_ISPASSER)
+#define OPClearRehash(x) ((x)->oflag &= ~OFLAG_REHASH)
+#define OPClearDie(x) ((x)->oflag &= ~OFLAG_DIE)
+#define OPClearRestart(x) ((x)->oflag &= ~OFLAG_RESTART)
+#define OPClearHelpOp(x) ((x)->oflag &= ~OFLAG_HELPOP)
+#define OPClearGlobOps(x) ((x)->oflag &= ~OFLAG_GLOBOP)
+#define OPClearWallOps(x) ((x)->oflag &= ~OFLAG_WALLOP)
+#define OPClearLocOps(x) ((x)->oflag &= ~OFLAG_LOCOP)
+#define OPClearLRoute(x) ((x)->oflag &= ~OFLAG_LROUTE)
+#define OPClearGRoute(x) ((x)->oflag &= ~OFLAG_GROUTE)
+#define OPClearLKill(x) ((x)->oflag &= ~OFLAG_LKILL)
+#define OPClearGKill(x) ((x)->oflag &= ~OFLAG_GKILL)
+#define OPClearKline(x) ((x)->oflag &= ~OFLAG_KLINE)
+#define OPClearUnKline(x) ((x)->oflag &= ~OFLAG_UNKLINE)
+#define OPClearLNotice(x) ((x)->oflag &= ~OFLAG_LNOTICE)
+#define OPClearGNotice(x) ((x)->oflag &= ~OFLAG_GNOTICE)
+#define OPClearPasser(x) ((x)->oflag &= ~OFLAG_PASSER)
+#define OPClearAdmin(x) ((x)->oflag &= ~OFLAG_ADMIN)
+#define OPClearSAdmin(x) ((x)->oflag &= ~OFLAG_SADMIN)
+#define OPClearNetAdmin(x) ((x)->oflag &= ~OFLAG_NETADMIN)
+#define OPClearTechAdmin(x) ((x)->oflag &= ~OFLAG_TECHADMIN)
+#define OPClearCoAdmin(x) ((x)->oflag &= ~OFLAG_COADMIN)
+#define OPClearUModeC(x) ((x)->oflag &= ~OFLAG_UMODEC)
+#define OPClearUModeF(x) ((x)->oflag &= ~OFLAG_UMODEF)
+#define OPClearEyes(x) ((x)->oflag &= ~OFLAG_EYES)
+#define OPClearZLine(x) ((x)->oflag &= ~OFLAG_ZLINE)
+#define OPClearWhois(x) ((x)->oflag &= ~OFLAG_WHOIS)
+/*
+ * defined debugging levels
+ */
+#define DEBUG_FATAL 0
+#define DEBUG_ERROR 1 /* report_error() and other errors that are found */
+#define DEBUG_NOTICE 3
+#define DEBUG_DNS 4 /* used by all DNS related routines - a *lot* */
+#define DEBUG_INFO 5 /* general usful info */
+#define DEBUG_NUM 6 /* numerics */
+#define DEBUG_SEND 7 /* everything that is sent out */
+#define DEBUG_DEBUG 8 /* anything to do with debugging, ie unimportant :) */
+#define DEBUG_MALLOC 9 /* malloc/free calls */
+#define DEBUG_LIST 10 /* debug list use */
+
+/*
+ * defines for curses in client
+ */
+#define DUMMY_TERM 0
+#define CURSES_TERM 1
+#define TERMCAP_TERM 2
+
+struct SqlineItem {
+ unsigned int status;
+ char *sqline;
+ char *reason;
+ struct SqlineItem *next;
+};
+
+struct ConfItem {
+ unsigned int status; /* If CONF_ILLEGAL, delete when no clients */
+ int clients; /* Number of *LOCAL* clients using this */
+ struct in_addr ipnum; /* ip number of host field */
+ char *host;
+ char *passwd;
+ char *name;
+ int port;
+ time_t hold; /* Hold action until this time (calendar time) */
+ int tmpconf;
+#ifndef VMSP
+ aClass *class; /* Class of connection */
+#endif
+ struct ConfItem *next;
+};
+
+#define CONF_ILLEGAL 0x80000000
+#define CONF_MATCH 0x40000000
+#define CONF_QUARANTINED_SERVER 0x0001
+#define CONF_CLIENT 0x0002
+#define CONF_CONNECT_SERVER 0x0004
+#define CONF_NOCONNECT_SERVER 0x0008
+#define CONF_LOCOP 0x0010
+#define CONF_OPERATOR 0x0020
+#define CONF_ME 0x0040
+#define CONF_KILL 0x0080
+#define CONF_ADMIN 0x0100
+#ifdef R_LINES
+#define CONF_RESTRICT 0x0200
+#endif
+#define CONF_CLASS 0x0400
+#define CONF_SERVICE 0x0800
+#define CONF_LEAF 0x1000
+#define CONF_LISTEN_PORT 0x2000
+#define CONF_HUB 0x4000
+#define CONF_UWORLD 0x8000
+#define CONF_QUARANTINED_NICK 0x10000
+#define CONF_ZAP 0x20000
+#define CONF_CONFIG 0x100000
+#define CONF_CRULEALL 0x200000
+#define CONF_CRULEAUTO 0x400000
+#define CONF_MISSING 0x800000
+#define CONF_SADMIN 0x1000000
+#define CONF_DRPASS 0x2000000 /* DIE/RESTART pass - NikB */
+#define CONF_EXCEPT 0x4000000 /* K:Line exception */
+#define CONF_TLINE 0x8000000 /* T:Line */
+#define CONF_SOCKSEXCEPT 0x10000000
+#define CONF_OPS (CONF_OPERATOR | CONF_LOCOP)
+#define CONF_SERVER_MASK (CONF_CONNECT_SERVER | CONF_NOCONNECT_SERVER)
+#define CONF_CLIENT_MASK (CONF_CLIENT | CONF_SERVICE | CONF_OPS | \
+ CONF_SERVER_MASK)
+#define CONF_CRULE (CONF_CRULEALL | CONF_CRULEAUTO)
+#define CONF_QUARANTINE (CONF_QUARANTINED_SERVER|CONF_QUARANTINED_NICK)
+
+#define IsIllegal(x) ((x)->status & CONF_ILLEGAL)
+#define IsTemp(x) ((x)->tmpconf)
+
+/*
+ * Client structures
+ */
+struct User {
+ struct User *nextu;
+ Link *channel; /* chain of channel pointer blocks */
+ Link *invited; /* chain of invite pointer blocks */
+ Link *silence; /* chain of silence pointer blocks */
+ char *away; /* pointer to away message */
+ time_t last;
+ u_int32_t servicestamp; /* Services' time stamp variable */
+ int refcnt; /* Number of times this block is referenced */
+ int joined; /* number of channels joined */
+ char username[USERLEN+1];
+ char realhost[HOSTLEN+1];
+ char virthost[HOSTLEN+1];
+ char server[HOSTLEN+1];
+ char *swhois; /* special whois thing */
+ aClient *serv;
+
+#ifdef LIST_DEBUG
+ aClient *bcptr;
+#endif
+};
+
+struct Server {
+ struct Server *nexts;
+ anUser *user; /* who activated this connection */
+ char up[HOSTLEN+1]; /* uplink for this server */
+ char by[NICKLEN+1];
+ aConfItem *nline; /* N-line pointer for this server */
+ time_t timestamp; /* Remotely determined connect try time */
+ time_t ghost; /* Local time at which a new server caused a Ghost */
+ u_short prot; /* Major protocol */
+#ifdef LIST_DEBUG
+ aClient *bcptr;
+#endif
+};
+
+struct t_vhost {
+ char *usermask;
+ char *hostmask;
+ char *login;
+ char *password;
+ char *virthost;
+ aVhost *next;
+ aVhost *prev;
+};
+
+struct t_hush {
+ char *nuhmask;
+ char *setby;
+ time_t set_at;
+ time_t expire_at;
+ aHush *next;
+ aHush *prev;
+};
+
+/* tkl:
+ * TKL_KILL|TKL_GLOBAL = Global K:Line (G:Line)
+ * TKL_ZAP|TKL_GLOBAL = Global Z:Line (ZLINE)
+ * TKL_KILL = Timed local K:Line
+ * TKL_ZAP = Local Z:Line
+ */
+#define TKL_KILL 0x0001
+#define TKL_ZAP 0x0002
+#define TKL_GLOBAL 0x0004
+
+
+struct t_kline {
+ int type;
+ char *usermask;
+ char *hostmask;
+ char *reason;
+ char *setby;
+ time_t expire_at;
+ time_t set_at;
+ aTKline *next;
+ aTKline *prev;
+};
+
+struct t_fline {
+ char *mask;
+ char *reason;
+ int type;
+ aFline *next;
+ aFline *prev;
+};
+
+struct t_crline {
+ char *channel;
+ int type;
+ aCRline *next, *prev;
+};
+
+struct t_vhline {
+ char *login;
+ char *password;
+ char *vhost;
+ int type;
+ aVHline *next, *prev;
+};
+
+struct Client {
+ struct Client *next, *prev, *hnext;
+ anUser *user; /* ...defined, if this is a User */
+ aServer *serv; /* ...defined, if this is a server */
+ int tag; /* tag */
+ int iown; /* 1 if mine, 0 if not */
+#ifdef USE_SERVICES
+ aService *service;
+#endif
+ time_t lasttime; /* ...should be only LOCAL clients? --msa */
+ time_t firsttime; /* time client was created */
+ time_t since; /* last time we parsed something */
+ time_t lastnick; /* TimeStamp on nick */
+ time_t nextnick; /* Time the next nick change will be allowed */
+ time_t nexttarget; /* Time until a change in targets is allowed */
+ u_char targets[MAXTARGETS]; /* Hash values of current targets */
+ long flags; /* client flags */
+ long umodes; /* client usermodes */
+ aClient *from; /* == self, if Local Client, *NEVER* NULL! */
+ int fd; /* >= 0, for local clients */
+ int hopcount; /* number of servers to this 0 = local */
+ int curruser; /* Number of users on this server */
+ short status; /* Client type */
+ char name[HOSTLEN+1]; /* Unique name of the client, nick or host */
+ char username[USERLEN+1]; /* username here now for auth stuff */
+ char info[REALLEN+1]; /* Free form additional client information */
+ char virthost[HOSTLEN+1]; /* hidden host */
+ aClient *srvptr; /* Server introducing this. May be &me */
+ Link *history; /* Whowas linked list */
+ /*
+ ** The following fields are allocated only for local clients
+ ** (directly connected to *this* server with a socket.
+ ** The first of them *MUST* be the "count"--it is the field
+ ** to which the allocation is tied to! *Never* refer to
+ ** these fields, if (from != self).
+ */
+ int count; /* Amount of data in buffer */
+ char buffer[BUFSIZE]; /* Incoming message buffer */
+ short lastsq; /* # of 2k blocks when sendqueued called last*/
+ dbuf sendQ; /* Outgoing message queue--if socket full */
+ dbuf recvQ; /* Hold for data incoming yet to be parsed */
+#ifdef NOSPOOF
+ u_int32_t nospoof; /* Anti-spoofing random number */
+#endif
+ long oflag; /* Operator access flags -Cabal95 */
+ long proto; /* ProtoCtl options */
+ long sendM; /* Statistics: protocol messages send */
+ long sendK; /* Statistics: total k-bytes send */
+ long receiveM; /* Statistics: protocol messages received */
+#ifndef NO_FDLIST
+ long lastrecvM; /* to check for activity --Mika */
+ int priority;
+#endif
+ long receiveK; /* Statistics: total k-bytes received */
+ u_short sendB; /* counters to count upto 1-k lots of bytes */
+ u_short receiveB; /* sent and received. */
+ aClient *acpt; /* listening client which we accepted from */
+ Link *confs; /* Configuration record associated */
+ int authfd; /* fd for rfc931 authentication */
+#ifdef SOCKSPORT
+ int socksfd;
+#endif
+ struct in_addr ip; /* keep real ip# too */
+ u_short port; /* and the remote port# too :-) */
+ struct hostent *hostp;
+ u_short notifies; /* Keep track of count of notifies */
+ Link *notify; /* Links to clients notify-structures */
+ LOpts *lopt; /* Saved /list options */
+#ifdef pyr
+ struct timeval lw;
+#endif
+ char sockhost[HOSTLEN+1]; /* This is the host name from the socket
+ ** and after which the connection was
+ ** accepted.
+ */
+ char passwd[PASSWDLEN+1];
+#ifdef DEBUGMODE
+ time_t cputime;
+#endif
+};
+
+#define CLIENT_LOCAL_SIZE sizeof(aClient)
+#define CLIENT_REMOTE_SIZE offsetof(aClient,count)
+
+/*
+ * statistics structures
+ */
+struct stats {
+ unsigned int is_cl; /* number of client connections */
+ unsigned int is_sv; /* number of server connections */
+ unsigned int is_ni; /* connection but no idea who it was */
+ unsigned short is_cbs; /* bytes sent to clients */
+ unsigned short is_cbr; /* bytes received to clients */
+ unsigned short is_sbs; /* bytes sent to servers */
+ unsigned short is_sbr; /* bytes received to servers */
+ unsigned long is_cks; /* k-bytes sent to clients */
+ unsigned long is_ckr; /* k-bytes received to clients */
+ unsigned long is_sks; /* k-bytes sent to servers */
+ unsigned long is_skr; /* k-bytes received to servers */
+ time_t is_cti; /* time spent connected by clients */
+ time_t is_sti; /* time spent connected by servers */
+ unsigned int is_ac; /* connections accepted */
+ unsigned int is_ref; /* accepts refused */
+ unsigned int is_unco; /* unknown commands */
+ unsigned int is_wrdi; /* command going in wrong direction */
+ unsigned int is_unpf; /* unknown prefix */
+ unsigned int is_empt; /* empty message */
+ unsigned int is_num; /* numeric message */
+ unsigned int is_kill; /* number of kills generated on collisions */
+ unsigned int is_fake; /* MODE 'fakes' */
+ unsigned int is_asuc; /* successful auth requests */
+ unsigned int is_abad; /* bad auth requests */
+ unsigned int is_udp; /* packets recv'd on udp port */
+ unsigned int is_loc; /* local connections made */
+};
+
+struct ListOptions {
+ LOpts *next;
+ Link *yeslist, *nolist;
+ int starthash;
+ short int showall;
+ unsigned short usermin;
+ int usermax;
+ time_t currenttime;
+ time_t chantimemin;
+ time_t chantimemax;
+ time_t topictimemin;
+ time_t topictimemax;
+};
+
+/* mode structure for channels */
+struct SMode {
+#ifndef USE_LONGMODE
+ unsigned int mode;
+#else
+ long mode;
+#endif
+ int limit;
+ char key[KEYLEN+1];
+ char link[LINKLEN+1];
+ /* x:y */
+ int msgs; /* x */
+ int per; /* y */
+ int kmode; /* mode 0 = kick 1 = ban */
+};
+
+/* Message table structure */
+
+struct Message {
+ char *cmd;
+ int (* func)();
+ unsigned int count;
+ int parameters;
+ char flags;
+ /* bit 0 set means that this command is allowed to be used
+ * only on the average of once per 2 seconds -SRB */
+ u_char token[2]; /* Cheat for tokenized value */
+ unsigned long bytes;
+#ifdef DEBUGMODE
+ unsigned long lticks;
+ unsigned long rticks;
+#endif
+};
+
+/* Used for notify-hash buckets... -Donwulff */
+
+struct Notify {
+ aNotify *hnext;
+ time_t lasttime;
+ Link *notify;
+ char nick[1];
+};
+
+/* general link structure used for chains */
+
+struct SLink {
+ struct SLink *next;
+ int flags;
+ aFloodOpt *flood;
+ union {
+ aClient *cptr;
+ aChannel *chptr;
+ aConfItem *aconf;
+ aNotify *nptr;
+ aName *whowas;
+ char *cp;
+ struct {
+ char *banstr;
+ char *who;
+ time_t when;
+ } ban;
+ } value;
+};
+
+struct SBan {
+ struct SBan *next;
+ char *banstr;
+ char *who;
+ time_t when;
+};
+
+struct DSlink {
+ struct DSlink *next;
+ struct DSlink *prev;
+ union {
+ aClient *cptr;
+ aChannel *chptr;
+ aConfItem *aconf;
+ char *cp;
+ } value;
+};
+
+/* channel structure */
+
+struct Channel {
+ struct Channel *nextch, *prevch, *hnextch;
+ Mode mode;
+ time_t creationtime;
+ char topic[TOPICLEN+1];
+ char topic_nick[NICKLEN+1];
+ time_t topic_time;
+ int users;
+ Link *members;
+ Link *invites;
+ Link *blist;
+ Ban *banlist;
+ Ban *exlist; /* exceptions */
+ char chname[1];
+};
+
+/*
+** Channel Related macros follow
+*/
+
+/* Channel related flags */
+
+#define CHFL_CHANOP 0x0001 /* Channel operator */
+#define CHFL_VOICE 0x0002 /* the power to speak */
+
+#define CHFL_DEOPPED 0x0004 /* Is de-opped by a server */
+#define CHFL_SERVOPOK 0x0008 /* Server op allowed */
+#define CHFL_ZOMBIE 0x0010 /* Kicked from channel */
+/* Bans are stored in separate linked list, so phase this out? */
+#define CHFL_BAN 0x0020 /* ban channel flag */
+#define CHFL_CHANOWNER 0x0040 /* channel owner */
+#define CHFL_CHANPROT 0x0080 /* chan op protection */
+#define CHFL_HALFOP 0x0100 /* halfop */
+#define CHFL_EXCEPT 0x0200 /* phase this out ? +e */
+
+#define CHFL_OVERLAP (CHFL_CHANOWNER|CHFL_CHANPROT|CHFL_CHANOP|CHFL_VOICE|CHFL_HALFOP)
+
+/* Channel macros */
+
+#define MODE_CHANOP CHFL_CHANOP
+#define MODE_VOICE CHFL_VOICE
+#define MODE_PRIVATE 0x0004
+#define MODE_SECRET 0x0008
+#define MODE_MODERATED 0x0010
+#define MODE_TOPICLIMIT 0x0020
+#define MODE_CHANOWNER 0x0040
+#define MODE_CHANPROT 0x0080
+#define MODE_HALFOP 0x0100
+#define MODE_EXCEPT 0x0200
+#define MODE_BAN 0x0400
+#define MODE_INVITEONLY 0x0800
+#define MODE_NOPRIVMSGS 0x1000
+#define MODE_KEY 0x2000
+#define MODE_LIMIT 0x4000
+#define MODE_RGSTR 0x8000
+#define MODE_RGSTRONLY 0x10000
+#define MODE_LINK 0x20000
+#define MODE_NOCOLOR 0x40000
+#define MODE_OPERONLY 0x80000
+#define MODE_ADMONLY 0x100000
+#define MODE_NOKICKS 0x200000
+#define MODE_STRIP 0x400000
+#define MODE_NOKNOCK 0x800000
+#define MODE_NOINVITE 0x1000000
+#define MODE_FLOODLIMIT 0x2000000
+#define MODE_NOHIDING 0x4000000
+#define is_halfop is_half_op
+/*
+ * mode flags which take another parameter (With PARAmeterS)
+ */
+#define MODE_WPARAS (MODE_HALFOP|MODE_CHANOP|MODE_VOICE|MODE_CHANOWNER|MODE_CHANPROT|MODE_BAN|MODE_KEY|MODE_LINK|MODE_LIMIT|MODE_EXCEPT)
+/*
+ * Undefined here, these are used in conjunction with the above modes in
+ * the source.
+#define MODE_DEL 0x200000000
+#define MODE_ADD 0x400000000
+ */
+
+#define HoldChannel(x) (!(x))
+/* name invisible */
+#define SecretChannel(x) ((x) && ((x)->mode.mode & MODE_SECRET))
+/* channel not shown but names are */
+#define HiddenChannel(x) ((x) && ((x)->mode.mode & MODE_PRIVATE))
+/* channel visible */
+#define ShowChannel(v,c) (PubChannel(c) || IsMember((v),(c)))
+#define PubChannel(x) ((!x) || ((x)->mode.mode &\
+ (MODE_PRIVATE | MODE_SECRET)) == 0)
+
+#define IsChannelName(name) ((name) && (*(name) == '#' || *(name) == '&' || *(name) == '+'))
+#define IsModelessChannel(name) ((name) && (*(name) == '+'))
+
+#define IsMember(blah,chan) ((blah && blah->user && \
+ find_channel_link((blah->user)->channel, chan)) ? 1 : 0)
+
+struct s_gline {
+ char name[128];
+ char sname[128];
+ char host[128];
+ char reason[128];
+ char timemsg[128];
+ long expire_at;
+ long set_at;
+};
+
+struct FloodOpt {
+ int nmsg;
+ time_t lastmsg;
+};
+
+/* Misc macros */
+
+#define BadPtr(x) (!(x) || (*(x) == '\0'))
+
+#define isvalid(c) (((c) >= 'A' && (c) <= '~') || isdigit(c) || (c) == '-')
+
+#define MyConnect(x) ((x)->fd >= 0)
+#define MyClient(x) (MyConnect(x) && IsClient(x))
+#define MyOper(x) (MyConnect(x) && IsOper(x))
+
+#define TStime() (time(NULL)+TSoffset)
+
+/* Lifted somewhat from Undernet code --Rak */
+
+#define IsSendable(x) (DBufLength(&x->sendQ) < 2048)
+#define DoList(x) ((x)->lopt)
+
+/* String manipulation macros */
+
+/* strncopynt --> strncpyzt to avoid confusion, sematics changed
+ N must be now the number of bytes in the array --msa */
+#define strncpyzt(x, y, N) do{(void)strncpy(x,y,N);x[N-1]='\0';}while(0)
+#define StrEq(x,y) (!strcmp((x),(y)))
+
+/* used in SetMode() in channel.c and m_umode() in s_msg.c */
+
+#define MODE_NULL 0
+#define MODE_ADD 0x40000000
+#define MODE_DEL 0x20000000
+
+/* return values for hunt_server() */
+
+#define HUNTED_NOSUCH (-1) /* if the hunted server is not found */
+#define HUNTED_ISME 0 /* if this server should execute the command */
+#define HUNTED_PASS 1 /* if message passed onwards successfully */
+
+/* used when sending to #mask or $mask */
+
+#define MATCH_SERVER 1
+#define MATCH_HOST 2
+
+/* used for async dns values */
+
+#define ASYNC_NONE (-1)
+#define ASYNC_CLIENT 0
+#define ASYNC_CONNECT 1
+#define ASYNC_CONF 2
+#define ASYNC_SERVER 3
+
+/* misc variable externs */
+
+extern char *version, *infotext[], *dalinfotext[], *unrealcredits[];
+extern char *generation, *creation;
+extern char *gnulicense[];
+/* misc defines */
+
+#define FLUSH_BUFFER -2
+#define UTMP "/etc/utmp"
+#define COMMA ","
+
+#endif /* __struct_include__ */
--- /dev/null
+/*
+ * IRC - Internet Relay Chat, include/sys.h
+ * Copyright (C) 1990 University of Oulu, Computing Center
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ */
+
+#ifndef __sys_include__
+#define __sys_include__
+#ifdef ISC202
+#include <net/errno.h>
+#else
+# ifndef _WIN32
+#include <sys/errno.h>
+# else
+#include <errno.h>
+# endif
+#endif
+
+#include "setup.h"
+#include <stdio.h>
+#include <sys/types.h>
+#ifndef _WIN32
+#include <sys/param.h>
+#else
+#include <stdarg.h>
+#endif
+
+#ifdef UNISTDH
+#include <unistd.h>
+#endif
+#ifdef STDLIBH
+#include <stdlib.h>
+#endif
+
+#ifdef STRINGSH
+#include <strings.h>
+#else
+# ifdef STRINGH
+# include <string.h>
+# endif
+#endif
+
+#ifndef GOT_STRCASECMP
+#define strcasecmp mycmp
+#define strncasecmp myncmp
+#endif
+
+#ifdef NOINDEX
+#define index strchr
+#define rindex strrchr
+/*
+extern char *index PROTO((char *, char));
+extern char *rindex PROTO((char *, char));
+*/
+#endif
+#ifdef NOBCOPY
+#define bcopy(x,y,z) memcpy(y,x,z)
+#define bcmp(x,y,z) memcmp(x,y,z)
+#define bzero(p,s) memset(p,0,s)
+#endif
+
+#ifdef AIX
+#include <sys/select.h>
+#endif
+#if defined(HPUX )|| defined(AIX) || defined(_WIN32)
+#include <time.h>
+#ifdef AIX
+#include <sys/time.h>
+#endif
+#else
+#include <sys/time.h>
+#endif
+
+#if !defined(DEBUGMODE)
+# ifndef _WIN32
+# define MyFree(x) if ((x) != NULL) free(x)
+# else
+# define MyFree(x) if ((x) != NULL) GlobalFree(x)
+# endif
+#else
+#define free(x) MyFree(x)
+#endif
+
+#ifdef NEXT
+#define VOIDSIG int /* whether signal() returns int of void */
+#else
+#define VOIDSIG void /* whether signal() returns int of void */
+#endif
+
+#ifdef SOL20
+#define OPT_TYPE char /* opt type for get/setsockopt */
+#else
+#define OPT_TYPE void
+#endif
+
+/*
+ * Different name on NetBSD, FreeBSD, and BSDI
+ */
+#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__bsdi__) || defined(__linux__) || defined(__APPLE__)
+#define dn_skipname __dn_skipname
+#endif
+
+#ifndef _WIN32
+extern VOIDSIG dummy();
+#endif
+
+#ifdef DYNIXPTX
+#define NO_U_TYPES
+typedef unsigned short n_short; /* short as received from the net */
+typedef unsigned long n_long; /* long as received from the net */
+typedef unsigned long n_time; /* ms since 00:00 GMT, byte rev */
+#define _NETINET_IN_SYSTM_INCLUDED
+#endif
+
+#ifdef NO_U_TYPES
+typedef unsigned char u_char;
+typedef unsigned short u_short;
+typedef unsigned long u_long;
+typedef unsigned int u_int;
+#endif
+
+#ifdef _WIN32
+#define MYOSNAME "Win32"
+#endif
+
+#endif /* __sys_include__ */
--- /dev/null
+/****************************************************************************
+ * Userload module by Michael L. VanLoon (mlv) <michaelv@iastate.edu>
+ * Written 2/93. Originally grafted into irc2.7.2g 4/93.
+ *
+ * IRC - Internet Relay Chat, ircd/userload.h
+ * Copyright (C) 1990 University of Oulu, Computing Center
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************/
+
+/* $Id$ */
+
+/* This needs to be defined for the counts to be correct--it should be the
+ * default anyway, as opers shouldn't be superior to lusers except where
+ * absolutely necessary, and here it isn't necessary. */
+#ifndef SHOW_INVISIBLE_LUSERS
+#define SHOW_INVISIBLE_LUSERS
+#endif
+
+struct current_load_struct {
+ u_short client_count, local_count, conn_count;
+ u_long entries;
+};
+
+extern struct current_load_struct current_load_data;
+
+struct load_entry {
+ struct load_entry *prev;
+ u_short client_count, local_count, conn_count;
+#ifdef DEBUGMODE
+ u_short cpu_usage;
+#endif
+ long time_incr;
+};
+
+extern struct load_entry *load_list_head, *load_list_tail,
+ *load_free_head, *load_free_tail;
+
+
+extern void initload PROTO ((void));
+extern void update_load PROTO ((void));
+extern void calc_load PROTO ((aClient *, char *));
--- /dev/null
+/*
+**
+** version.h
+** UnrealIRCd
+** $Id$
+*/
+#ifndef __versioninclude
+#define __versioninclude 1
+
+#include "relinfo.h"
+/*
+ * Mark of settings
+ */
+#ifdef DEBUGMODE
+#define DEBUGMODESET "+(debug)"
+#else
+#define DEBUGMODESET ""
+#endif
+/**/
+#ifdef DEBUG
+#define DEBUGSET "(Debug)"
+#else
+#define DEBUGSET ""
+#endif
+/**/
+#define COMPILEINFO DEBUGMODESET DEBUGSET
+#ifndef WEBTV
+#define XTRAINFO ""
+#else
+#define XTRAINFO "(WebTV)"
+#endif
+/*
+ * Version Unreal3.0
+ */
+#define UnrealProtocol 2300
+#define PATCH1 "3"
+#define PATCH2 ".0"
+#define PATCH3 "-Morrigan"
+#define PATCH4 "(fix)"
+#define PATCH5 ""
+#define PATCH6 ""
+#define PATCH7 ""
+#define PATCH8 COMPILEINFO
+#define PATCH9 XTRAINFO
+
+#ifndef _WIN32
+#define BASE_VERSION "Unreal"
+#else
+#define BASE_VERSION "UnrealIRCd/32 v"
+#endif
+
+#define VERSIONONLY PATCH1 PATCH2 PATCH3 PATCH4 PATCH5 PATCH6 PATCH7
+
+#endif /* __versioninclude */
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, include/whowas.h
+ * Copyright (C) 1990 Markku Savela
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * $Id$
+ *
+ * $Log$
+ * Revision 1.1.1.1 2000/01/30 12:16:34 stskeeps
+ * Begin of CVS at cvs.unreal.sourceforge.net
+ *
+ *
+ * Revision 1.1.1.1 1999/09/01 23:20:37 stskeeps
+ *
+ * Revision 1.1.1.1 1999/07/22 13:56:41 stskeeps
+ * 16:56 22-07-99 techie
+ * - Started on using CVS to develop Unreal
+ *
+ *
+ * Revision 1.1.1.1 1999/07/21 10:48:18 stskeeps
+ * 12:47 GMT+2 21 July 1999 - Techie
+ * Starting Unreal with CVS..
+ *
+ *
+ * Revision 1.2 1997/12/29 07:17:35 wd
+ * df4.6.2
+ * ee CHANGES for updates
+ * -wd
+ *
+ * Revision 1.1.1.1 1997/08/22 17:23:01 donwulff
+ * Original import from the "deadlined" version.
+ *
+ * Revision 1.1.1.1 1996/11/18 07:53:42 explorer
+ * ircd 4.3.3 -- about time
+ *
+ * Revision 1.1.1.1.4.1 1996/09/16 02:45:41 donwulff
+ * *** empty log message ***
+ *
+ * Revision 6.1 1991/07/04 21:04:39 gruner
+ * Revision 2.6.1 [released]
+ *
+ * Revision 6.0 1991/07/04 18:05:08 gruner
+ * frozen beta revision 2.6.1
+ *
+ */
+
+#ifndef __whowas_include__
+#define __whowas_include__
+
+#ifndef PROTO
+#if __STDC__
+# define PROTO(x) x
+#else
+# define PROTO(x) ()
+#endif /* __STDC__ */
+#endif /* ! PROTO */
+
+/*
+** WHOWAS structure moved here from whowas.c
+*/
+typedef struct aname {
+ anUser *ww_user;
+ aClient *ww_online;
+ time_t ww_logout;
+ long ww_umodes;
+ char ww_nick[NICKLEN+1];
+ char ww_info[REALLEN+1];
+} aName;
+
+/*
+** add_history
+** Add the currently defined name of the client to history.
+** usually called before changing to a new name (nick).
+** Client must be a fully registered user (specifically,
+** the user structure must have been allocated).
+*/
+void add_history PROTO((aClient *));
+
+/*
+** off_history
+** This must be called when the client structure is about to
+** be released. History mechanism keeps pointers to client
+** structures and it must know when they cease to exist. This
+** also implicitly calls AddHistory.
+*/
+void off_history PROTO((aClient *));
+
+/*
+** get_history
+** Return the current client that was using the given
+** nickname within the timelimit. Returns NULL, if no
+** one found...
+*/
+aClient *get_history PROTO((char *, time_t));
+ /* Nick name */
+ /* Time limit in seconds */
+
+int m_whowas PROTO((aClient *, aClient *, int, char *[]));
+
+/*
+** for debugging...counts related structures stored in whowas array.
+*/
+void count_whowas_memory PROTO((int *, int *, u_long *));
+
+#endif /* __whowas_include__ */
--- /dev/null
+#define SPATH "."
+#define DPATH "."
+#define DOMAINNAME "irc.net"
\ No newline at end of file
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, include/win32/setup.h
+ * Copyright (C) 1999 Carsten Munk
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ */
+
+#ifndef __setup_include__
+#define __setup_include__
+#undef PARAMH
+#undef UNISTDH
+#define STRINGH
+#undef STRINGSH
+#define STDLIBH
+#undef STDDEFH
+#undef SYSSYSLOGH
+#define NOINDEX
+#define NOBCOPY
+#define NEED_STRERROR
+#define NEED_STRTOKEN
+#undef NEED_STRTOK
+#undef NEED_INET_ADDR
+#undef NEED_INET_NTOA
+#define NEED_INET_NETOF
+#define GETTIMEOFDAY
+#undef LRAND48
+#define MALLOCH <malloc.h>
+#undef NBLOCK_POSIX
+#undef POSIX_SIGNALS
+#undef TIMES_2
+#undef GETRUSAGE_2
+
+#define NO_U_TYPES
+#define NEED_U_INT32_T
+#endif
--- /dev/null
+#!/bin/sh
+# IRCD Script v3.0
+# $Id$
+#
+DIR=`pwd`
+DATE=`date +"%a, %b %e %Y"`
+TIME=`date +"%H:%M:%S %Z"`
+IRCDPID="ircd.pid"
+BACKUP="ircd.bak"
+
+if [ -r $IRCDPID ]; then
+mv -f $IRCDPID $BACKUP
+src/ircd
+sleep 1
+if [ ! -r $IRCDPID ]; then
+mv -f $BACKUP $IRCDPID
+echo "|--------------------------------------------|"
+echo "| **** ERROR **** |"
+echo "| Possible problems: |"
+echo "| (1) IRCd already running. |"
+echo "| (2) The correct IP was not placed in the |"
+echo "| M:line of the ircd.conf. |"
+echo "| (3) DPATH or SPATH's are incorrect. Run |"
+echo "| ./Config to correct that. |"
+echo "| (4) Someone else is running an ircd on the |"
+echo "| default port you chose in ircd.conf. |"
+echo "|********************************************|"
+echo "| If you can't get Unreal IRCd to work - go |"
+echo "| to /server irc.flirt.org and join |"
+echo "| #UnrealIRCd or mail us at |"
+echo "| unreal-support@lists.sourceforge.net |"
+echo "| |"
+echo "|--------------------------------------------|"
+exit
+else
+echo "|----------------------------------------"
+echo "| UnrealIRCD successfully loaded."
+echo "| Directory: $DIR"
+echo "| Date: $DATE"
+echo "| Time: $TIME"
+PID=`cat ircd.pid`
+echo "| Process ID: $PID"
+echo "|----------------------------------------"
+rm -f $BACKUP
+ fi
+else
+src/ircd
+sleep 2
+if [ ! -r $IRCDPID ]; then
+echo "|--------------------------------------------|"
+echo "| **** ERROR **** |"
+echo "| Possible problems: |"
+echo "| (1) IRCd already running. |"
+echo "| (2) The correct IP was not placed in the |"
+echo "| M:line of the ircd.conf. |"
+echo "| (3) DPATH or SPATH's are incorrect. Run |"
+echo "| ./Config to correct that. |"
+echo "| (4) Someone else is running an ircd on the |"
+echo "| default port you chose in ircd.conf. |"
+echo "|********************************************|"
+echo "| If you can't get Unreal IRCd to work - go |"
+echo "| to /server irc.global-irc.net and join |"
+echo "| #Global - Try ask in the channel or /msg |"
+echo "| Stskeeps/Techie(me!) or else-- email me at |"
+echo "| stskeeps@tspre.org |"
+echo "|--------------------------------------------|"
+
+exit
+else
+echo "|----------------------------------------"
+echo "| UnrealIRCD successfully loaded."
+echo "| Directory: $DIR"
+echo "| Date: $DATE"
+echo "| Time: $TIME"
+PID=`cat ircd.pid`
+echo "| Process ID: $PID"
+echo "|----------------------------------------"
+ fi
+fi
--- /dev/null
+0,10,20,30,40,50 * * * * /home/mydir-to/ircdcron/ircdchk >/dev/null 2>&1
--- /dev/null
+#!/bin/sh
+#
+# UnrealIRCD Crontab v2.1
+# $Id$
+#
+# This is a script suitable for use in a crontab. It checks to make sure
+# your ircd is running. YOU NEED A SEPARATE CRON JOB FOR EACH IRCD. If your
+# ircd isn't found, it'll try to start it back up.
+#
+# You'll need to edit this script for your ircd.
+#
+# To check for your ircd every 10 minutes, put the following line in your
+# crontab:
+# 0,10,20,30,40,50 * * * * /home/mydir/ircdchk
+# And if you don't want to get email from crontab when it checks you ircd,
+# put the following in your crontab:
+# 0,10,20,30,40,50 * * * * /home/mydir/ircdchk >/dev/null 2>&1
+#
+# change this to the mail address to mail output to:
+MAIL=me
+# change this to the directory you run your ircd from:
+dir="../"
+
+# change this to the name of your ircd's file in that directory:
+ircdexe="ircd"
+
+# I wouldn't touch this if I were you.
+ircdname="ircd.pid"
+
+########## you probably don't need to change anything below here ##########
+
+cd $dir
+if test -r $ircdname; then
+ # there is a pid file -- is it current?
+ ircdpid=`cat $ircdname`
+ if `kill -CHLD $ircdpid >/dev/null 2>&1`; then
+ # it's still going
+ # back out quietly
+ exit 0
+ fi
+ echo "UnrealIRCd Crontab notice:"
+ echo ""
+ echo "Stale $ircdname file (erasing it)"
+ rm -f $ircdname
+fi
+echo ""
+echo "Couldn't find the ircd running. Reloading it..."
+echo ""
+./$ircdexe
--- /dev/null
+#!/bin/sh
+# $Id$
+
+lynx http://unreal.sourceforge.net/register.html
--- /dev/null
+#!/bin/sh
+# Kill Script v2.0
+# Created by Potvin
+# $Id$
+DIR=`pwd`
+DATE=`date +"%a, %b %e %Y"`
+TIME=`date +"%H:%M:%S %Z"`
+IRCDPID="ircd.pid"
+
+if [ ! -r $IRCDPID ]; then
+clear
+echo "|--------------------------------------------|"
+echo "| **** ERROR **** |"
+echo "| Possible problems: |"
+echo "| (1) $IRCDPID not found |"
+echo "| (2) The IRCd is not running |"
+echo "|--------------------------------------------|"
+else
+PID=`cat $IRCDPID`
+kill -9 $PID >/dev/null 2>&1
+rm -f $IRCDPID
+echo "|----------------------------------------"
+echo "| UnrealIRCD successfully shutdown."
+echo "| Directory: $DIR"
+echo "| Date: $DATE"
+echo "| Time: $TIME"
+echo "| Process ID: $PID"
+echo "|----------------------------------------"
+fi
--- /dev/null
+#!/bin/sh
+# $Id$
+# Defaults
+#
+TIME=`date +"%H:%M:%S %Z"`
+DATE=`date +"%a, %b %e %Y"`
+IRCDCONF="ircd.conf"
+SERVNAME="Server.IRC.net"
+COMMENT="IRC server!"
+ADMIN="Admin-name"
+ADMNICK="Admin"
+ADMADDR="admin@no.where.com"
+OPERNAME="admin"
+OPERADDR="*@*"
+OPERPASS="password"
+PORT="6667"
+OPRT="default"
+LINKPASS="linkpass"
+VIRTUAL="1.2.3.4"
+ENCRYPT="Yes"
+FLAGS="OAZHWe"
+RESTARTPASS="restartpass"
+DIEPASS="diepass"
+SERVICES="Services.ShadowNet.Org"
+
+# these are so I can use stuff like $1 without it replacing it...like by
+# using $dlrsgn$uno for $1
+dlrsgn="$"
+uno="1"
+dos="2"
+
+# remove the temp file if it exists
+rm -f mkconf.tmp
+
+# make a quick script for replacing one line with another
+
+cat > repl_str << __EOF__
+sed -e "s@^$dlrsgn$uno\(.*\)@$dlrsgn$dos" $IRCDCONF > mkconf.tmp
+cp mkconf.tmp $IRCDCONF
+rm mkconf.tmp
+__EOF__
+
+# mark repl_str as an executable
+chmod +x repl_str
+rm -f repl_str
+# Checking out how to specify not to make a new line with the current OS
+c=''
+n=''
+2>/dev/null
+if [ "`eval echo -n 'a'`" = "-n a" ]; then
+ c='\c'
+else
+ n='-n'
+fi
+
+# If Settings exist, load the info, otherwise tell them to run Config.
+
+if [ -r Settings ]; then
+ . Settings
+else
+ echo "Hmm, you need to run Config first!"
+ echo "Type ./Config"
+ echo "If you have run Config, make sure you are in the directory"
+ echo "you ran it from."
+ exit 1
+fi
+
+CONF=$IRCDCONF
+
+if [ -r "$CONF" ]; then
+ echo "$IRCDCONF found"
+ echo " "
+ echo " I don't suggest running this with the conf file already"
+ echo "existing, since you will lose all the data in your conf file."
+ echo "This script is just for creating one. If you want to recreate"
+ echo "a conf file, type 'recreate'."
+ echo $n " [exit] -> $c"
+ read cc
+
+ if [ "$cc" != "recreate" ]; then
+ echo " "
+ echo " OK, do you want to edit $IRCDCONF using an editor?"
+ echo "If so, specify the editor you want to use. Otherwise,"
+ echo "type 'exit'."
+ EDITFND="not found"
+
+ if [ -r /usr/bin/pico ]; then
+ EDITFND="pico"
+ fi
+
+ if [ -r /usr/bin/joe ]; then
+ EDITFND="joe"
+ fi
+
+ if [ -r /usr/bin/vi ]; then
+ EDITFND="vi"
+ fi
+
+ if [ -r /usr/bin/vim ]; then
+ EDITFND="vim"
+ fi
+
+ while [ "c" = "c" ]; do
+ echo $n " [$EDITFND] -> $c"
+ read EDITOR
+
+ if [ -z "$EDITOR" ]; then
+ EDITOR="$EDITFND"
+ fi
+
+ if [ "$EDITOR" = "exit" ]; then
+ echo "Have a nice day."
+ exit 1
+ fi
+
+ if [ -f $EDITOR ]; then
+ $EDITOR $CONF
+ exit 1
+ fi
+
+ if [ -f /usr/bin/$EDITOR ]; then
+ /usr/bin/$EDITOR $CONF
+ exit 1
+ fi
+
+ echo " Editor not found. Specify a valid editor or"
+ echo "type 'exit' to quit this script."
+ done
+
+ fi
+
+ mv $CONF "$CONF.saved"
+ rm $CONF
+ echo "$IRCDCONF has been renamed to ircd.conf.saved"
+else
+ echo "$IRCDCONF is not found. (good)"
+fi
+
+clear
+echo "|=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=|"
+echo "| Welcome to the $IRCDCONF generator. |"
+echo "|=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=|"
+echo " "
+echo "What will your server name be? (ie: $SERVNAME)"
+echo $n " [$SERVNAME] -> $c"
+read cc
+if [ ! -z "$cc" ]; then
+ SERVNAME="$cc"
+fi
+
+echo " "
+echo "What is your IRC server's IP? (ie: $VIRTUAL)"
+echo "Use * to bind to all interfaces"
+echo $n " [$VIRTUAL] -> $c"
+read cc
+if [ ! -z "$cc" ]; then
+ VIRTUAL="$cc"
+fi
+
+echo " "
+echo "Server comment? (ie: Main Hub Server)"
+echo $n " [$COMMENT] -> $c"
+read cc
+if [ ! -z "$cc" ]; then
+ COMMENT="$cc"
+fi
+
+echo " "
+echo "Main port? (ie: 6667)"
+echo $n " [$PORT] -> $c"
+read cc
+if [ ! -z "$cc" ]; then
+ PORT="$cc"
+fi
+
+echo " "
+echo "What is your real name? (ie: John Doe)"
+echo $n " [$ADMIN] -> $c"
+read cc
+if [ ! -z "$cc" ]; then
+ ADMIN="$cc"
+fi
+
+echo " "
+echo "What is your IRC nickname? (ie: JD)"
+echo $n " [$ADMNICK] -> $c"
+read cc
+if [ ! -z "$cc" ]; then
+ ADMNICK="$cc"
+fi
+
+echo " "
+echo "What is your e-mail address? (ie: john@doe.com)"
+echo $n " [$ADMADDR] -> $c"
+read cc
+if [ ! -z "$cc" ]; then
+ ADMADDR="$cc"
+fi
+
+echo " "
+OPERNAME="$ADMNICK"
+echo "What will your opername be for your O:line? (ie: johndoe)"
+echo $n " [$OPERNAME] -> $c"
+read cc
+if [ ! -z "$cc" ]; then
+ OPERNAME="$cc"
+fi
+
+echo " "
+echo "What oper flags do you want to have? (ie: OAWZ)"
+echo "Some flags to choose from:"
+echo " o = local oper"
+echo " O = global oper"
+echo " N = network administrator"
+echo " A = server administrator"
+echo " C = co administrator"
+echo " T = technical administrator"
+echo " read unrealircd.doc for more info about O:line flags)"
+echo $n " [$FLAGS] -> $c"
+read cc
+if [ ! -z "$cc" ]; then
+ FLAGS="$cc"
+fi
+
+ echo " "
+ ENCRYPT=""
+ ENCRYPT="bad"
+ while [ "$ENCRYPT" = "bad" ]; do
+ echo "Do you use encrypted oper passwords?"
+ echo $n " [Yes] -> $c"
+ read cc
+ if [ -z "$cc" ]; then
+ cc="Yes"
+ fi
+ case "$cc" in
+ [Yy]*)
+ ENCRYPT="Yes"
+ ;;
+ [Nn]*)
+ ENCRYPT="No"
+ ;;
+ *)
+ echo "Please specify yes or no."
+ ENCRYPT="bad"
+ ;;
+ esac
+ done
+
+if [ "$ENCRYPT" = "Yes" ] ; then
+echo "Compile the file called mkpasswd.c in the 'crypt' directory"
+echo "Then run it (./mkpasswd) and input the passwd to be encrypted"
+echo "Then copy the output into the passwd slot in the O:line"
+echo "NOTE: You can encrypt on irc via /mkpasswd <passwd>"
+fi
+
+echo " "
+echo "What will your /oper password be? (ie: snoopy67)"
+echo $n " [$OPERPASS] -> $c"
+read cc
+if [ ! -z "$cc" ]; then
+ OPERPASS="$cc"
+fi
+
+echo " "
+echo "What is your user@host mask on IRC? (ie: *@*.toronto.globalserve.net)"
+echo $n " [$OPERADDR] -> $c"
+read cc
+if [ ! -z "$cc" ]; then
+ OPERADDR="$cc"
+fi
+
+echo " "
+echo "What do you want your die password to be?"
+echo $n " [$DIEPASS] -> $c"
+read cc
+if [ ! -z "$cc" ]; then
+ DIEPASS="$cc"
+fi
+
+echo " "
+echo "What do you want your restart password to be?"
+echo $n " [$RESTARTPASS] -> $c"
+read cc
+if [ ! -z "$cc" ]; then
+ RESTARTPASS="$cc"
+fi
+
+echo " "
+echo "If your running services, or linking to a network that has"
+echo "services, please state the services servername."
+echo "If you are running a non-services network, just type 'next'"
+echo $n " [$SERVICES] -> $c"
+read cc
+
+#if [ ! -z "$cc" ]; then
+# SERVICES="$cc"
+#fi
+
+if [ "$cc" = "next" ]; then
+ SERVICES="No.Services.Selected"
+elif [ ! -z "$cc" ]; then
+ SERVICES="$cc"
+fi
+
+cat > $CONF << __EOF__
+########################
+#
+# Filename: $IRCDCONF
+# Created: $DATE - $TIME
+#
+########################
+
+############ Server Info ############
+M:$SERVNAME:$VIRTUAL:$COMMENT:$PORT
+#####################################
+
+############ Administrator Information #############
+A:$ADMIN:$ADMNICK:$ADMADDR
+####################################################
+
+############ Y-lines #############
+# Client Y:lines
+Y:1:90:0:$MAXCONNECTIONS:100000
+# Server Y:lines
+Y:50:300:600:1:1000000
+##################################
+
+############ I/Access Lines #############
+I:*@*::*@*::1
+#########################################
+
+############ X:LINE Die/Restart Password ############
+X:$DIEPASS:$RESTARTPASS
+#####################################################
+
+## O-line (O:hostmask:password:opername:flags:1) ##
+O:$OPERADDR:$OPERPASS:$OPERNAME:$FLAGS:1
+###################################################
+
+__EOF__
+
+
+echo " "
+echo " Would you like to configure any servers for linking?"
+echo "Type the servername, or type 'done' when finished."
+echo $n " [done] -> $c"
+read cc
+
+if [ -z "$cc" ]; then
+ cc="done"
+fi
+
+while [ "$cc" != "done" ]; do
+ THESERV="$cc"
+
+ SHOST="none"
+ while [ "$SHOST" = "none" ]; do
+ echo " "
+ echo "Hostname or ip for the other server? Must be specified."
+ echo $n " [] -> $c"
+ read SHOST
+ done
+
+ echo " "
+ echo "Password to send to the other server?"
+ echo $n " [$LINKPASS] -> $c"
+ read CLP
+ if [ -z "$CLP" ]; then
+ CLP="$LINKPASS"
+ fi
+
+ echo " "
+ AUTOPORT=""
+ AUTOCONN="bad"
+ while [ "$AUTOCONN" = "bad" ]; do
+ echo " "
+ echo "Should we autconnect to this server?"
+ echo $n " [Yes] -> $c"
+ read cc
+ if [ -z "$cc" ]; then
+ cc="Yes"
+ fi
+ case "$cc" in
+ [Yy]*)
+ AUTOCONN="yes"
+ echo "What port should we autoconnect to?"
+ echo $n " [7029] -> $c"
+ read AUTOPORT
+ if [ -z "$AUTOPORT" ]; then
+ AUTOPORT="7029"
+ fi
+ ;;
+ [Nn]*)
+ AUTOCONN="no"
+ ;;
+ *)
+ echo "Please specify yes or no."
+ AUTOCONN="bad"
+ ;;
+ esac
+ done
+
+ echo " "
+ HUB="bad"
+ while [ "$HUB" = "bad" ]; do
+ echo " "
+ echo "Will this server be a hub?"
+ echo $n " [Yes] -> $c"
+ read cc
+ if [ -z "$cc" ]; then
+ cc="Yes"
+ fi
+ case "$cc" in
+ [Yy]*)
+ HUB="Yes"
+ ;;
+ [Nn]*)
+ HUB="no"
+ ;;
+ *)
+ echo "Please specify yes or no."
+ HUB="bad"
+ ;;
+ esac
+ done
+
+ if [ "$HUB" = "Yes" ]; then
+ echo "############ HUB LINES #############" >> $CONF
+ echo "H:*:*:$THESERV" >> $CONF
+ echo "####################################" >> $CONF
+ echo "" >> $CONF
+ fi
+
+ echo "############ C/N LINES #############" >> $CONF
+ echo "C:$SHOST:$CLP:$THESERV:$AUTOPORT:50" >> $CONF
+ echo "N:$SHOST:$CLP:$THESERV::50" >> $CONF
+ echo "####################################" >> $CONF
+ echo "" >> $CONF
+
+ echo " "
+ echo "Type the servername, or type 'done' when finished."
+ echo $n " [done] -> $c"
+ read cc
+ if [ -z "$cc" ]; then
+ cc="done"
+ fi
+done
+
+cat >> $CONF << __EOF__
+############ Uline for Services ############
+U:$SERVICES:*:*
+############################################
+
+############ Q-Lined NickNames ############
+Q::Reserved for services:*C*h*a*n*S*e*r*v*
+Q::Reserved for services:*N*i*c*k*S*e*r*v*
+Q::Reserved for services:*M*e*m*o*S*e*r*v*
+Q::Reserved for services:*H*e*l*p*S*e*r*v*
+Q::Reserved for services:*O*p*e*r*S*e*r*v*
+Q::Reserved for services:*I*n*f*o*S*e*r*v*
+Q::Reserved for Administrator:*Admin*
+Q::Reserved for ircops:*IRC*op*
+Q::Reserved for ircops:*Oper*
+Q::Bug in mIRC:Status
+###########################################
+
+############ PORT LINES #############
+__EOF__
+
+cc="blank"
+echo " "
+echo " "
+echo " Would you like any extra ports, other than 6667? Enter them here."
+echo "Type 'done' when you are finished. Type 'default' to use 6665-6669/7000."
+while [ "$cc" != "done" ]; do
+ echo $n " [$OPRT] -> $c"
+ read cc
+ if [ -z "$cc" ]; then
+ cc="$OPRT"
+ fi
+ if [ "$cc" = "default" ]; then
+ echo "P:$VIRTUAL:*:*:6660" >> $CONF
+ echo "P:$VIRTUAL:*:*:6661" >> $CONF
+ echo "P:$VIRTUAL:*:*:6662" >> $CONF
+ echo "P:$VIRTUAL:*:*:6663" >> $CONF
+ echo "P:$VIRTUAL:*:*:6664" >> $CONF
+ echo "P:$VIRTUAL:*:*:6665" >> $CONF
+ echo "P:$VIRTUAL:*:*:6666" >> $CONF
+ echo "P:$VIRTUAL:*:*:6668" >> $CONF
+ echo "P:$VIRTUAL:*:*:6669" >> $CONF
+ echo "P:$VIRTUAL:*:*:7000" >> $CONF
+ echo "P:$VIRTUAL:*:*:7029" >> $CONF
+ echo "#####################################" >> $CONF
+ cc="done"
+ fi
+ if [ "$cc" != "done" ]; then
+ if [ $cc = "$PORT" ]; then
+ echo " No, $PORT is already defined in the M:line,"
+ echo "please use a port other than $PORT."
+ else
+ echo "P:$VIRTUAL:*:*:$cc" >> $CONF
+ fi
+ fi
+ case "$OPRT" in
+ 6660) OPRT="done"
+ ;;
+ 6661) OPRT="6660"
+ ;;
+ 6662) OPRT="6661"
+ ;;
+ 6663) OPRT="6662"
+ ;;
+ 6664) OPRT="6663"
+ ;;
+ 6665) OPRT="6664"
+ ;;
+ 6666) OPRT="6665"
+ ;;
+ 6669) OPRT="6666"
+ ;;
+ 6668) OPRT="6669"
+ ;;
+ 6667) OPRT="6668"
+ ;;
+ *) OPRT="done"
+ ;;
+ esac
+done
+
+# Make it so ONLY the one who created the conf can read or write.
+chmod 700 $IRCDCONF
+
+cat << __EOF__
+
+
+ OK, $IRCDCONF has been generated according to what you specified.
+Make sure you double check for errors in $IRCDCONF. We recommend that
+you take a look at your $IRCDCONF right now. Thanks for using UnrealIRCd
+
+__EOF__
+ echo "Have a nice day."
+ echo ""
+ exit 1
--- /dev/null
+#
+# Win32Gui Config File .. By DrBin
+#
+CC=cl
+# Here you put your settings
+FD_SETSIZE=/D FD_SETSIZE=16384
+NS_ADDRESS=/D NS_ADDRESS="\"nospoof@dal.net\""
+CFLAGS=/MT /O2 /G5 /I ./INCLUDE /Fosrc/ /nologo $(FD_SETSIZE) $(NS_ADDRESS) /D _WIN32GUI /D NOSPOOF=1 /c
+INCLUDES=./include/struct.h ./include/config.h ./include/sys.h \
+ ./include/common.h ./include/version.h ./include/h.h ./include/numeric.h \
+ ./include/msg.h ./include/setup.h ./include/dynconf.h
+LINK=link.exe
+LFLAGS=kernel32.lib user32.lib gdi32.lib shell32.lib wsock32.lib \
+ oldnames.lib libcmt.lib comctl32.lib /nodefaultlib /nologo /out:WIRCD2.EXE
+OBJ_FILES=SRC/CHANNEL.OBJ SRC/USERLOAD.OBJ SRC/SEND.OBJ SRC/BSD.OBJ \
+ SRC/S_CONF.OBJ SRC/FDLIST.OBJ SRC/DBUF.OBJ SRC/RES.OBJ \
+ SRC/CLOAK.OBJ SRC/HASH.OBJ SRC/PARSE.OBJ SRC/IRCD.OBJ \
+ SRC/S_NUMERIC.OBJ SRC/WHOWAS.OBJ SRC/RES_COMP.OBJ SRC/S_AUTH.OBJ \
+ SRC/HELP.OBJ SRC/S_MISC.OBJ SRC/MATCH.OBJ SRC/CRULE.OBJ \
+ SRC/S_DEBUG.OBJ SRC/RES_INIT.OBJ SRC/SUPPORT.OBJ SRC/LIST.OBJ \
+ SRC/S_ERR.OBJ SRC/PACKET.OBJ SRC/CLASS.OBJ SRC/S_BSD.OBJ \
+ SRC/MD5.OBJ SRC/S_SERV.OBJ SRC/S_USER.OBJ SRC/WIN32GUI.OBJ \
+ SRC/VERSION.OBJ SRC/win32/WIN32.RES SRC/S_UNREAL.OBJ SRC/DYNCONF.OBJ \
+ SRC/S_SOCKS.OBJ SRC/S_KLINE.OBJ SRC/S_EXTRA.OBJ
+RC=rc.exe
+
+ALL: WIRCD.EXE CHKCONF.EXE
+ @echo Please, please REMEMBER to add those U lines!
+ @echo Read the file READTHIS.NOW formore info
+
+CLEAN:
+ -@erase src\*.exe 2>NUL
+ -@erase src\*.obj 2>NUL
+ -@erase src\win32.res 2>NUL
+ -@erase src\version.c 2>NUL
+ -@erase src\win32\*.obj 2>NUL
+ -@erase .\*.exe 2>NUL
+
+#include/setup.h:
+# @echo Hmm...doesn't look like you've run Config...
+# @echo Doing so now.
+# @config.exe
+
+#src/version.c: dummy
+# @config.exe -v
+
+src/version.obj: src/win32/version.c
+ $(CC) $(CFLAGS) src/win32/version.c
+
+./WIRCD.EXE: $(OBJ_FILES) src/win32/version.obj
+ $(LINK) $(LFLAGS) $(OBJ_FILES)
+
+./CHKCONF.EXE: ./include/struct.h ./include/config.h ./include/sys.h \
+ ./include/common.h ./src/crule.c ./src/match.c ./src/chkconf.c
+ $(CC) /nologo /I ./include /D CR_CHKCONF /Fosrc/chkcrule.obj /c src/crule.c
+ $(CC) /nologo /I ./include /D CR_CHKCONF /Fosrc/chkmatch.obj /c src/match.c
+ $(CC) /nologo /I ./include /D CR_CHKCONF /Fosrc/chkconf.obj /c src/chkconf.c
+ $(LINK) /nologo /out:./chkconf.exe src/chkconf.obj src/chkmatch.obj \
+ src/chkcrule.obj
+
+src/parse.obj: src/parse.c $(INCLUDES)
+ $(CC) $(CFLAGS) src/parse.c
+
+src/bsd.obj: src/bsd.c $(INCLUDES)
+ $(CC) $(CFLAGS) src/bsd.c
+
+src/dbuf.obj: src/dbuf.c $(INCLUDES) ./include/dbuf.h
+ $(CC) $(CFLAGS) src/dbuf.c
+
+src/packet.obj: src/packet.c $(INCLUDES)
+ $(CC) $(CFLAGS) src/packet.c
+
+src/fdlist.obj: src/fdlist.c $(INCLUDES)
+ $(CC) $(CFLAGS) src/fdlist.c
+
+src/dynconf.obj: src/dynconf.c $(INCLUDES) ./include/dbuf.h \
+ ./include/channel.h ./include/whowas.h
+ $(CC) $(CFLAGS) src/dynconf.c
+
+src/send.obj: src/send.c $(INCLUDES)
+ $(CC) $(CFLAGS) src/send.c
+
+src/match.obj: src/match.c $(INCLUDES)
+ $(CC) $(CFLAGS) src/match.c
+
+src/support.obj: src/support.c $(INCLUDES)
+ $(CC) $(CFLAGS) src/support.c
+
+src/channel.obj: src/channel.c $(INCLUDES) ./include/channel.h
+ $(CC) $(CFLAGS) src/channel.c
+
+src/class.obj: src/class.c $(INCLUDES) ./include/class.h
+ $(CC) $(CFLAGS) src/class.c
+
+src/ircd.obj: src/ircd.c $(INCLUDES)
+ $(CC) $(CFLAGS) src/ircd.c
+
+src/list.obj: src/list.c $(INCLUDES)
+ $(CC) $(CFLAGS) src/list.c
+
+src/res.obj: src/res.c $(INCLUDES)
+ $(CC) $(CFLAGS) src/res.c
+
+src/s_bsd.obj: src/s_bsd.c $(INCLUDES)
+ $(CC) $(CFLAGS) src/s_bsd.c
+
+src/s_auth.obj: src/s_auth.c $(INCLUDES)
+ $(CC) $(CFLAGS) src/s_auth.c
+
+src/s_conf.obj: src/s_conf.c $(INCLUDES)
+ $(CC) $(CFLAGS) src/s_conf.c
+
+src/s_debug.obj: src/s_debug.c $(INCLUDES)
+ $(CC) $(CFLAGS) src/s_debug.c
+
+src/s_err.obj: src/s_err.c $(INCLUDES)
+ $(CC) $(CFLAGS) src/s_err.c
+
+src/s_kline.obj: src/s_kline.c $(INCLUDES)
+ $(CC) $(CFLAGS) src/s_kline.c
+
+src/s_misc.obj: src/s_misc.c $(INCLUDES) ./include/dbuf.h
+ $(CC) $(CFLAGS) src/s_misc.c
+
+src/s_socks.obj: src/s_socks.c $(INCLUDES)
+ $(CC) $(CFLAGS) src/s_socks.c
+
+src/s_user.obj: src/s_user.c $(INCLUDES) ./include/dbuf.h \
+ ./include/channel.h ./include/whowas.h
+ $(CC) $(CFLAGS) src/s_user.c
+
+src/s_extra.obj: src/s_extra.c $(INCLUDES) ./include/dbuf.h \
+ ./include/channel.h ./include/whowas.h
+ $(CC) $(CFLAGS) src/s_extra.c
+
+src/s_unreal.obj: src/s_unreal.c $(INCLUDES) ./include/dbuf.h \
+ ./include/channel.h ./include/whowas.h
+ $(CC) $(CFLAGS) src/s_unreal.c
+
+src/s_serv.obj: src/s_serv.c $(INCLUDES) ./include/dbuf.h ./include/whowas.h
+ $(CC) $(CFLAGS) src/s_serv.c
+
+src/s_numeric.obj: src/s_numeric.c $(INCLUDES) ./include/dbuf.h
+ $(CC) $(CFLAGS) src/s_numeric.c
+
+src/whowas.obj: src/whowas.c $(INCLUDES) ./include/dbuf.h ./include/whowas.h
+ $(CC) $(CFLAGS) src/whowas.c
+
+src/hash.obj: src/hash.c $(INCLUDES) ./include/hash.h
+ $(CC) $(CFLAGS) src/hash.c
+
+src/crule.obj: src/crule.c $(INCLUDES)
+ $(CC) $(CFLAGS) src/crule.c
+
+src/win32gui.obj: src/win32/win32gui.c $(INCLUDES) ./src/win32/resource.h
+#./include/resource.h
+ $(CC) $(CFLAGS) src/win32/win32gui.c
+
+src/res_comp.obj: src/res_comp.c $(INCLUDES)
+ $(CC) $(CFLAGS) src/res_comp.c
+
+src/res_init.obj: src/res_init.c $(INCLUDES)
+ $(CC) $(CFLAGS) src/res_init.c
+
+src/help.obj: src/help.c $(INCLUDES)
+ $(CC) $(CFLAGS) src/help.c
+
+src/md5.obj: src/md5.c $(INCLUDES)
+ $(CC) $(CFLAGS) src/md5.c
+
+src/win32/win32.res: src/win32/win32gui.rc
+ $(RC) /l 0x409 /fosrc/win32/win32.res /i ./include /i ./src \
+ /d NDEBUG src/win32/win32gui.rc
+
+dummy:
+
+
--- /dev/null
+ver2^2
+#
+# Network Configuration File Template
+# -----------------------------------------
+# Added-at: <day> <month> <year> <hh:dd> GMT
+# Author: <nick> (<real name>)
+# E-Mail: <email>
+# $Id$
+# -----------------------------------------
+# This is a template so you can create your own network configuration files
+# Just follow the instructions and it will prolly work ;)
+# 0 = No 1 = Yes
+# -------------------------------------------------------
+#
+# These two specify the name of the IRC network, set the same in both fields
+Network >..........: 972-Scripterz
+Set ircnetwork ....: 972-Scripterz
+
+# This is where your DNS pool is (like irc.dal.net)
+Set defserv .......: irc.972-Scripterz.org
+
+# This is the name of your Services Server
+Set SERVICES_NAME .: services.972-Scripterz.org
+
+# This is the virtual hostname IRCops will get if iNAH option is enabled
+# on oper up
+Set oper_host .....: ircop.972-Scripterz.org
+
+# This is the virtual hostname Server Admins will get if iNAH option is enabled
+# on oper up
+Set admin_host ....: admin.972-Scripterz.org
+
+# This is the virtual hostname Local IRCops will get if iNAH option is enabled
+# on oper up
+
+Set locop_host ....: locop.972-Scripterz.org
+
+# This is the virtual hostname Services Operators/Admins will get
+# if iNAH option is enabled on oper up
+
+Set sadmin_host ...: serviceop.972-Scripterz.org
+
+# This is the virtual hostname NetAdmins will get
+# if iNAH option is enabled on oper up
+
+Set netadmin_host .: netadmin.972-Scripterz.org
+
+# This is the virtual hostname CoAdmins will get
+# if iNAH option is enabled on oper up
+Set coadmin_host ..: coadmin.972-Scripterz.org
+
+
+# This is the virtual hostname TechAdmins will get
+# if iNAH option is enabled on oper up
+Set techadmin_host : techadmin.972-Scripterz.org
+
+# This is the prefix of the hidden host (cloaking) hostname
+Set hidden_host ...: sz
+# This is the domain of the IRC network
+Set netdomain .....: 972-Scripterz.org
+# This is where people can go for help
+Set helpchan ......: #972-Scripterz
+# This is the name of the stats server
+Set STATS_SERVER ..: stats.972-Scripters.org
+# -- Not in use--
+Set HUB ...........: 0
+# This enables the auto-setting of f.x @netadmin.network.net
+# on oper up
+Set iNAH ..........: 0
+# -- Not in use but still here --
+Set net_quit ......: sz
--- /dev/null
+ver^2.2
+#
+# Network Configuration File Template
+# -----------------------------------------
+# Added-at: <11> <09> <1999> <14:32> GMT
+# Author: <Kerjin> Steve>)
+# E-Mail: <kerjin@alternativenet.org>
+# $Id$
+# -----------------------------------------
+# This is a template so you can create your own network configuration files
+# Just follow the instructions and it will prolly work ;)
+# 0 = No 1 = Yes
+# -------------------------------------------------------
+#
+# These two specify the name of the IRC network, set the same in both fields
+Network >..........: AltNet IRC
+Set ircnetwork ....: AltNet IRC
+
+# This is where your DNS pool is (like irc.dal.net)
+Set defserv .......: irc.alternativenet.org
+
+# This is the name of your Services Server
+Set SERVICES_NAME .: services.alternativenet.org
+
+# This is the virtual hostname IRCops will get if iNAH option is enabled
+# on oper up
+Set oper_host .....: ircop.alternativenet.org
+
+# This is the virtual hostname Server Admins will get if iNAH option is enabled
+# on oper up
+Set admin_host ....: admin.alternativenet.org
+
+# This is the virtual hostname Local IRCops will get if iNAH option is enabled
+# on oper up
+
+Set locop_host ....: locop.alternativenet.org
+
+# This is the virtual hostname Services Operators/Admins will get
+# if iNAH option is enabled on oper up
+
+Set sadmin_host ...: serviceop.alternativenet.org
+
+# This is the virtual hostname NetAdmins will get
+# if iNAH option is enabled on oper up
+
+Set netadmin_host .: netadmin.alternativenet.org
+
+# This is the virtual hostname CoAdmins will get
+# if iNAH option is enabled on oper up
+Set coadmin_host ..: coadmin.alternativenet.org
+
+
+# This is the virtual hostname TechAdmins will get
+# if iNAH option is enabled on oper up
+Set techadmin_host : techadmin.alternativenet.org
+
+# This is the prefix of the hidden host (cloaking) hostname
+Set hidden_host ...: altirc
+# This is the domain of the IRC network
+Set netdomain .....: alternativenet.org
+# This is where people can go for help
+Set helpchan ......: #AltNetHelp
+# This is the name of the stats server
+Set STATS_SERVER ..: statistics.alternativenet.org
+# -- Not in use--
+Set HUB ...........: 1
+# This enables the auto-setting of f.x @netadmin.network.net
+# on oper up
+Set iNAH ..........: 1
+# -- Not in use but still here --
+Set net_quit ......: alt
--- /dev/null
+ver^2.2
+#
+# Bunker7.net Network Configuration File
+# -----------------------------------------
+# Added-at: 17 August 1999 12:34 CT
+# Author: Rogue
+# E-Mail: rogue@bunker7.net
+# $Id$
+# -----------------------------------------
+#
+
+Network >..........: bunker7
+Set ircnetwork ....: bunker7
+Set defserv .......: irc.bunker7.net
+Set SERVICES_NAME .: services.bunker7.net
+Set oper_host .....: global.bunker7.net
+Set admin_host ....: admin.bunker7.net
+Set locop_host ....: local.bunker7.net
+Set sadmin_host ...: sadm.bunker7.net
+Set netadmin_host .: netadmin.bunker7.net
+Set coadmin_host ..: coadmin.bunker7.net
+Set techadmin_host : techadmin.bunker7.net
+Set hidden_host ...: bunker7
+Set netdomain .....: bunker7.net
+Set helpchan ......: #bunker7
+Set STATS_SERVER ..: stats.bunker7.net
+Set HUB ...........: 1
+Set iNAH ..........: 0
+Set net_quit ......: B7
--- /dev/null
+#
+# Network Configuration File Template
+# -----------------------------------------
+# Added-at: <day> <month> <year> <hh:dd> GMT
+# Author: Curt|s
+# E-Mail: <email>
+# $Id$
+#
+# These two specify the name of the IRC network, set the same in both fields
+Network >..........: DigitalIRC.Net
+Set ircnetwork ....: DigitalIRC.Net
+
+# This is where your DNS pool is (like irc.dal.net)
+Set defserv .......: irc.digitalirc.net
+
+# This is the name of your Services Server
+Set SERVICES_NAME .: Services.DigitalIRC.Net
+
+# This is the virtual hostname IRCops will get if iNAH option is enabled
+# on oper up
+Set oper_host .....: Oper.DigitalIRC.Net
+
+# This is the virtual hostname Server Admins will get if iNAH option is enabled
+# on oper up
+Set admin_host ....: Admin.DigitalIRC.Net
+
+# This is the virtual hostname Local IRCops will get if iNAH option is enabled
+# on oper up
+
+Set locop_host ....: LocOper.DigitalIRC.Net
+
+# This is the virtual hostname Services Operators/Admins will get
+# if iNAH option is enabled on oper up
+
+Set sadmin_host ...: ServicesOp.DigitalIRC.Net
+
+# This is the virtual hostname NetAdmins will get
+# if iNAH option is enabled on oper up
+
+Set netadmin_host .: NetAdmin.DigitalIRC.Net
+
+# This is the virtual hostname CoAdmins will get
+# if iNAH option is enabled on oper up
+Set coadmin_host ..: NetAdmin.DigitalIRC.Net
+
+
+# This is the virtual hostname TechAdmins will get
+# if iNAH option is enabled on oper up
+Set techadmin_host : Tech.DigitalIRC.Net
+
+# This is the prefix of the hidden host (cloaking) hostname
+Set hidden_host ...: NN
+# This is the domain of the IRC network
+Set netdomain .....: DigtialIRC.Net
+#This is where people can go for help
+Set helpchan ......: #Digitalirc
+# This is the name of the stats server
+Set STATS_SERVER ..: Statistics.DigitalIRC.com
+# -- Not in use--
+Set HUB ...........: 1
+# This enables the auto-setting of f.x @netadmin.network.net
+# on oper up
+Set iNAH ..........: 0
+# -- Not in use but still here --
+Set net_quit ......: ic
--- /dev/null
+ver^2.2
+#
+# DragonWings.org Network Configuration File
+# -----------------------------------------
+# Added-at: 14 July 1999 00:00 GMT
+# Author: Stskeeps (Carsten Munk)
+# E-Mail: stskeeps@global-irc.net
+# $Id$
+# -----------------------------------------
+#
+
+Network >..........: DragonWings
+Set ircnetwork ....: DragonWings
+Set defserv .......: irc.dragonwings.org
+Set SERVICES_NAME .: saturn.dragonwings.org
+Set oper_host .....: ircop.dragonwings.org
+Set admin_host ....: admin.dragonwings.org
+Set locop_host ....: locop.dragonwings.org
+Set sadmin_host ...: serviceop.dragonwings.org
+Set netadmin_host .: netadmin.dragonwings.org
+Set coadmin_host ..: coadmin.dragonwings.org
+Set techadmin_host : techadmin.dragonwings.org
+Set hidden_host ...: dw
+Set netdomain .....: dragonwings.org
+Set helpchan ......: #DragonWings
+Set STATS_SERVER ..: stats.dragonwings.org
+Set HUB ...........: 1
+Set iNAH ..........: 0
+Set net_quit ......: DW
--- /dev/null
+\r
+#\r
+# FireIRC Network Configuration File\r
+# -----------------------------------------\r
+# Added-at: 14 July 1999 00:00 GMT\r
+# Author: MasterSatan (Erik Kerr)\r
+# E-Mail: Kerrfarm@bright.net\r
+#\r
+# -----------------------------------------\r
+# \r
+\r
+\r
+Network >..........: FireIRC\r
+Set ircnetwork ....: FireIRC\r
+Set defserv .......: irc.FireIRC.Net\r
+Set SERVICES_NAME .: services.FireIRC.Net\r
+Set oper_host .....: ircOP.FireIRC.Net\r
+Set admin_host ....: Admin.FireIRC.Net\r
+Set locop_host ....: localOP.FireIRC.Net\r
+Set sadmin_host ...: serviceOP.FireIRC.Net\r
+Set netadmin_host .: NetADMIN.FireIRC.Net\r
+Set coadmin_host ..: CoADMIN.FireIRC.Net\r
+Set techadmin_host : TechAdmin.FireIRC.Net\r
+Set hidden_host ...: FireIRC\r
+Set netdomain .....: FireIRC.Net\r
+Set helpchan ......: #Services\r
+Set STATS_SERVER ..: stats.FireIRC.Net\r
+Set HUB ...........: 1\r
+Set iNAH ..........: 0\r
+Set net_quit ......: FI
\ No newline at end of file
--- /dev/null
+ver^2.2
+#
+# Global-IRC.net Network Configuration File
+# -----------------------------------------
+# Added-at: 14 July 1999 00:00 GMT
+# Author: Stskeeps (Carsten Munk)
+# E-Mail: stskeeps@global-irc.net
+# $Id$
+# -----------------------------------------
+#
+
+Network >..........: Global-IRC
+Set ircnetwork ....: Global-IRC
+Set defserv .......: irc.global-irc.net
+Set SERVICES_NAME .: services.global-irc.net
+Set oper_host .....: ircop.global-irc.net
+Set admin_host ....: admin.global-irc.net
+Set locop_host ....: locop.global-irc.net
+Set sadmin_host ...: serviceop.global-irc.net
+Set netadmin_host .: netadmin.global-irc.net
+Set coadmin_host ..: coadmin.global-irc.net
+Set techadmin_host : techadmin.global-irc.net
+Set hidden_host ...: global
+Set netdomain .....: global-irc.net
+Set helpchan ......: #Global
+Set STATS_SERVER ..: stats.global-irc.net
+Set HUB ...........: 1
+Set iNAH ..........: 0
+Set net_quit ......: GI
--- /dev/null
+ver^2.2
+#
+# Global-IRC.net Network Configuration File
+# -----------------------------------------
+# Added-at: 14 July 1999 00:00 GMT
+# Author: Stskeeps (Carsten Munk)
+# E-Mail: stskeeps@global-irc.net
+# $Id$
+# -----------------------------------------
+#
+
+Network >..........: Infinity-IRC.org
+Set ircnetwork ....: Infinity-IRC.org
+Set defserv .......: irc.infinity-irc.org
+Set SERVICES_NAME .: services.infinity-irc.org
+Set oper_host .....: IRCop.Infinity-IRC.org
+Set admin_host ....: IRCop-Admin.Infinity-IRC.org
+Set locop_host ....: LOCop.Infinity-IRC.org
+Set sadmin_host ...: IRCop-ServiceAdmin.Infinity-IRC.org
+Set netadmin_host .: IRCop-NetAdmin.Infinity-IRC.org
+Set coadmin_host ..: IRCop-CoAdmin.Infinity-IRC.org
+Set techadmin_host : IRCop-TechAdmin.Infinity-IRC.org
+Set hidden_host ...: Infinity
+Set netdomain .....: Infinity-IRC.org
+Set helpchan ......: #Infinity
+Set STATS_SERVER ..: stats.infinity-irc.org
+Set HUB ...........: 1
+Set iNAH ..........: 1
+Set net_quit ......: IN
--- /dev/null
+ver^2.2
+#
+# MegaIRC.net Network Configuration File
+# -----------------------------------------
+# Added-at: 1 August 1999 00:00 GMT
+# Author: NonMortal (Luke Slotwinski)
+# E-Mail: NonMortal@MegaIRC.Com
+# $Id$
+# -----------------------------------------
+#
+
+Network >..........: MegaIRC
+Set ircnetwork ....: MegaIRC
+Set defserv .......: irc.MegaIRC.Net
+Set SERVICES_NAME .: Services.MegaIRC.Net
+Set oper_host .....: Ircop.MegaIRC.Net
+Set admin_host ....: Server-Admin.MegaIRC.Net
+Set locop_host ....: Local-Ircop.MegaIRC.Net
+Set sadmin_host ...: SOP.MegaIRC.Net
+Set netadmin_host .: NetAdmin.MegaIRC.Net
+Set coadmin_host ..: Server-CoAdmin.MegaIRC.Net
+Set techadmin_host : TechAdmin.MegaIRC.Net
+Set hidden_host ...: mega
+Set netdomain .....: MegaIRC.Net
+Set helpchan ......: #helpdesk
+Set STATS_SERVER ..: Stats.MegaIRC.Net
+Set HUB ...........: 1
+Set iNAH ..........: 1
+Set net_quit ......: MI
+# To protect people from using normal edition Unreal to link to MegaIRC
+Set STOPSE ........: 1
--- /dev/null
+ver^2.2
+#
+# Mp3Fans.net Network Configuration File
+# -----------------------------------------
+# Added-at: 14 July 1999 00:00 GMT
+# Author: Stskeeps (Carsten Munk)
+# E-Mail: stskeeps@global-irc.net
+# $Id$
+# -----------------------------------------
+#
+
+Network >..........: Mp3FansNet
+Set ircnetwork ....: Mp3FansNet
+Set defserv .......: irc.mp3fans.net
+Set SERVICES_NAME .: services.mp3fans.net
+Set oper_host .....: ircop.mp3fans.net
+Set admin_host ....: admin.mp3fans.net
+Set locop_host ....: locop.mp3fans.net
+Set sadmin_host ...: serviceop.mp3fans.net
+Set netadmin_host .: netadmin.mp3fans.net
+Set coadmin_host ..: coadmin.mp3fans.net
+Set techadmin_host : techadmin.mp3fans.net
+Set hidden_host ...: mpx
+Set netdomain .....: mp3fans.net
+Set helpchan ......: #Mp3Fans
+Set STATS_SERVER ..: stats.mp3fans.net
+Set HUB ...........: 1
+Set iNAH ..........: 0
+Set net_quit ......: m3
--- /dev/null
+ver^2.2
+#
+# Network Configuration File Template
+# -----------------------------------------
+# Added-at: 23 August 1999 <18:00> GMT
+# Author: codemastr <codemastr@elite-hacker.cx>
+# $Id$
+# -----------------------------------------
+# This is a template so you can create your own network configuration files
+# Just follow the instructions and it will prolly work ;)
+# 0 = No 1 = Yes
+# -------------------------------------------------------
+#
+# These two specify the name of the IRC network, set the same in both fields
+Network >..........: NeoHorizon
+Set ircnetwork ....: NeoHorizon
+
+# This is where your DNS pool is (like irc.dal.net)
+Set defserv .......: irc.nhn.net
+
+# This is the name of your Services Server
+Set SERVICES_NAME .: services.nhn.net
+
+# This is the virtual hostname IRCops will get if iNAH option is enabled
+# on oper up
+Set oper_host .....: IRCop.nhn.net
+
+# This is the virtual hostname Server Admins will get if iNAH option is enabled
+# on oper up
+Set admin_host ....: Admin.nhn.net
+
+# This is the virtual hostname Local IRCops will get if iNAH option is enabled
+# on oper up
+
+Set locop_host ....: Locop.nhn.net
+
+# This is the virtual hostname Services Operators/Admins will get
+# if iNAH option is enabled on oper up
+
+Set sadmin_host ...: ServicesOP.nhn.net
+
+# This is the virtual hostname NetAdmins will get
+# if iNAH option is enabled on oper up
+
+Set netadmin_host .: NetAdmin.nhn.net
+
+# This is the virtual hostname CoAdmins will get
+# if iNAH option is enabled on oper up
+Set coadmin_host ..: Co-Admin.nhn.net
+
+
+# This is the virtual hostname TechAdmins will get
+# if iNAH option is enabled on oper up
+Set techadmin_host : techadmin.nhn.net
+
+# This is the prefix of the hidden host (cloaking) hostname
+Set hidden_host ...: Neo
+# This is the domain of the IRC network
+Set netdomain .....: nhn.net
+# This is where people can go for help
+Set helpchan ......: #neohorizon
+# This is the name of the stats server
+Set STATS_SERVER ..: stats.nhn.net
+# -- Not in use--
+Set HUB ...........: 1
+# This enables the auto-setting of f.x @netadmin.network.net
+# on oper up
+Set iNAH ..........: 1
+# -- Not in use but still here --
+Set net_quit ......: NH
--- /dev/null
+# Networks index file - do not touch please
+networks/global-irc.network ......: Global-IRC (http://www.global-irc.net)
+networks/mp3fans.network .........: Mp3Fans.Net (http://www.mp3fans.net)
+networks/roxnet.network ..........: ROXnet (http://www.rox.za.net)
+networks/dragonwings.network .....: DragonWings (http://www.dragonwings.org)
+networks/megairc.network .........: MegaIRC (http://www.megairc.net)
+networks/neohorizon.network ......: NeoHorizon (http://www.nhn.net)
+networks/spynet.network ..........: SpyNet (http://www.spynet.org)
+networks/nevernet.network ........: NeverNET (http://www.nevernet.net)
+networks/altirc.network ..........: AlternativeNet IRC (http://www.
+networks/bunker7.network .........: Bunker7 (http://www.bunker7.net)
+networks/realchat.network ........: RealChat.org (http://www.realchat.org)
+networks/newmilennium.network ....: NewMilennium (http://www.newmilennium.net)
+networks/solarxtreme.network .....: SolarXTreme (http://www.solarxtreme.net)
+networks/ss.network ..............: StarSpace (http://www.starspace.net)
+networks/uzaynet.network .........: UzayNet (http://www.uzaynet.nu)
+networks/infinity.network ........: Infinity-IRC.org (http://www.infinity-irc.org)
+networks/tspre.network ...........: TSpre (http://www.tspre.org)
+networks/solargalaxy.network .....: SolarGalaxy (http://www.solargalaxy.net)
+networks/digitalirc.network ......: DigitalIRC (http://www.digitalirc.net)
+networks/fireirc.network .........: FireIRC (http://www.fireirc.net)
+networks/stormdancing.network ....: StormDancing (http://www.stormdancing.net)
+networks/972-scripterz.network ...: 972-scripterz
+networks/v64net.network ..........: v64
\ No newline at end of file
--- /dev/null
+ver^2.2
+
+#
+# Network Configuration File Template
+# -----------------------------------------
+# Added-at: <day> <month> <year> <hh:dd> GMT
+# Author: <nick> (<real name>)
+# E-Mail: <email>
+# $Id$
+# -----------------------------------------
+# This is a template so you can create your own network configuration files
+# Just follow the instructions and it will prolly work ;)
+# 0 = No 1 = Yes
+# -------------------------------------------------------
+#
+# These two specify the name of the IRC network, set the same in both fields
+Network >..........: NeverNET
+Set ircnetwork ....: NeverNET
+
+# This is where your DNS pool is (like irc.dal.net)
+Set defserv .......: IRC.NeverNET.Net
+
+# This is the name of your Services Server
+Set SERVICES_NAME .: Services.NeverNET.Net
+
+# This is the virtual hostname IRCops will get if iNAH option is enabled
+# on oper up
+Set oper_host .....: Opers.NeverNET.Net
+
+# This is the virtual hostname Server Admins will get if iNAH option is enabled
+# on oper up
+Set admin_host ....: Admins.NeverNET.Net
+
+# This is the virtual hostname Local IRCops will get if iNAH option is enabled
+# on oper up
+
+Set locop_host ....: Opers.NeverNET.Net
+
+# This is the virtual hostname Services Operators/Admins will get
+# if iNAH option is enabled on oper up
+
+Set sadmin_host ...: Services.NeverNET.Net
+
+# This is the virtual hostname NetAdmins will get
+# if iNAH option is enabled on oper up
+
+Set netadmin_host .: Nevermore.NeverNET.Net
+
+# This is the virtual hostname CoAdmins will get
+# if iNAH option is enabled on oper up
+Set coadmin_host ..: NetAdmins.NeverNET.Net
+
+
+# This is the virtual hostname TechAdmins will get
+# if iNAH option is enabled on oper up
+Set techadmin_host : Tech.NeverNET.Net
+
+# This is the prefix of the hidden host (cloaking) hostname
+Set hidden_host ...: NN
+# This is the domain of the IRC network
+Set netdomain .....: NeverNET.Net
+#This is where people can go for help
+Set helpchan ......: #NeverNET
+# This is the name of the stats server
+Set STATS_SERVER ..: Stats.NeverNET.Net
+# -- Not in use--
+Set HUB ...........: 1
+# This enables the auto-setting of f.x @netadmin.network.net
+# on oper up
+Set iNAH ..........: 0
+# -- Not in use but still here --
+Set net_quit ......: ic
--- /dev/null
+ver^2.2
+#
+# newmilennium.net Network Configuration File
+# Made by: Dave Ellsworth (MasterJedi)
+# E-Mail: mj@planetz.net
+# ---------------------------------------
+
+
+Network >..........: NewMilennium
+Set ircnetwork ....: NewMilennium
+Set defserv .......: irc.NewMilennium.net
+Set SERVICES_NAME .: Services.NewMilennium.net
+Set oper_host .....: ircop.newmilennium.net
+Set admin_host ....: admin.newmilennium.net
+Set locop_host ....: locop.newmilennium.net
+Set sadmin_host ...: serviceop.newmilennium.net
+Set netadmin_host .: netadmin.newmilennium.net
+Set coadmin_host ..: coadmin.newmilennium.net
+Set techadmin_host : techadmin.newmilennium.net
+Set hidden_host ...: newmilennium
+Set netdomain .....: newmilennium.net
+Set helpchan ......: #newmilennium
+Set STATS_SERVER ..: stats.newmilennium.net
+Set HUB ...........: 1
+Set iNAH ..........: 1
+Set net_quit ......: SN
--- /dev/null
+ver^2.2
+#
+# Network Configuration File Template
+# -----------------------------------------
+# Added-at: 14 August 1999 16:34 GMT
+# Author: Sandman
+# $Id$
+# -----------------------------------------
+# This is a template so you can create your own network configuration files
+# Just follow the instructions and it will prolly work ;)
+# 0 = No 1 = Yes
+# -------------------------------------------------------
+#
+# These two specify the name of the IRC network, set the same in both fields
+Network >..........: RealChat.Org
+Set ircnetwork ....: RealChat.Org
+
+# This is where your DNS pool is (like irc.dal.net)
+Set defserv .......: irc.RealChat.Org
+
+# This is the name of your Services Server
+Set SERVICES_NAME .: Services.RealChat.Org
+
+# This is the virtual hostname IRCops will get if iNAH option is enabled
+# on oper up
+Set oper_host .....: Oper.RealChat.Org
+
+# This is the virtual hostname Server Admins will get if iNAH option is enabled
+# on oper up
+Set admin_host ....: Admins.RealChat.Org
+
+# This is the virtual hostname Local IRCops will get if iNAH option is enabled
+# on oper up
+
+Set locop_host ....: LocalOper.RealChat.Org
+
+# This is the virtual hostname Services Operators/Admins will get
+# if iNAH option is enabled on oper up
+
+Set sadmin_host ...: servicesOper.RealChat.Org
+
+# This is the virtual hostname NetAdmins will get
+# if iNAH option is enabled on oper up
+
+Set netadmin_host .: NetAdmin.RealChat.Org
+
+# This is the virtual hostname CoAdmins will get
+# if iNAH option is enabled on oper up
+Set coadmin_host ..: CoAdmin.RealChat.Org
+
+
+# This is the virtual hostname TechAdmins will get
+# if iNAH option is enabled on oper up
+Set techadmin_host : TechAdmin.RealChat.Org
+
+# This is the prefix of the hidden host (cloaking) hostname
+Set hidden_host ...: realchat
+# This is the domain of the IRC network
+Set netdomain .....: RealChat.Org
+# This is where people can go for help
+Set helpchan ......: #services
+# This is the name of the stats server
+Set STATS_SERVER ..: stats.realchat.org
+# -- Not in use--
+Set HUB ...........: 1
+# This enables the auto-setting of f.x @netadmin.network.net
+# on oper up
+Set iNAH ..........: 0
+# -- Not in use but still here --
+Set net_quit ......: RC
--- /dev/null
+ver^2.2
+#
+# ROXnet (irc.rox.za.net) Network Configuration File
+# --------------------------------------------------
+# Added-at: 14 July 1999 00:00 GMT
+# Author: Stskeeps (Carsten Munk)
+# E-Mail: stskeeps@roxnet.org
+# $Id$
+# -----------------------------------------
+#
+
+Network >..........: ROXnet
+Set ircnetwork ....: ROXnet
+Set defserv .......: irc.roxnet.org
+Set SERVICES_NAME .: services.roxnet.org
+Set oper_host .....: ircop.roxnet.org
+Set admin_host ....: admin.roxnet.org
+Set locop_host ....: locop.roxnet.org
+Set sadmin_host ...: csops.roxnet.org
+Set netadmin_host .: netadmin.roxnet.org
+Set coadmin_host ..: coadmin.roxnet.org
+Set techadmin_host : techadmin.roxnet.org
+Set hidden_host ...: rox
+Set netdomain .....: roxnet.org
+Set helpchan ......: #ROXnet
+Set STATS_SERVER ..: stats.roxnet.org
+Set HUB ...........: 1
+Set iNAH ..........: 0
+Set net_quit ......: Rox
+
--- /dev/null
+ver^2.2
+Network >..........: SolarGalaxy
+
+Set ircnetwork ....: SolarGalaxy
+
+Set defserv .......: Irc.SolarGalaxy.Net
+
+Set SERVICES_NAME .: Services.SolarGalaxy.Net
+
+Set oper_host .....: IRCop.SolarGalaxy.Net
+
+Set admin_host ....: Admin.SolarGalaxy.Net
+
+Set locop_host ....: Locop.SolarGalaxy.Net
+
+Set sadmin_host ...: ServiceOp.SolarGalaxy.Net
+
+Set netadmin_host .: NetAdmin.SolarGalaxy.Net
+
+Set coadmin_host ..: CoAdmin.SolarGalaxy.Net
+
+Set techadmin_host : TechAdmin.SolarGalaxy.Net
+
+Set hidden_host ...: solargalaxy
+
+Set netdomain .....: SolarGalaxy.Net
+
+Set helpchan ......: #SolarGalaxy
+
+Set STATS_SERVER ..: Stats.SolarGalaxy.Net
+
+Set HUB ...........: 1
+
+Set iNAH ..........: 1
+
+Set net_quit ......: sg
--- /dev/null
+ver^2.2
+#
+# Network Configuration File Template
+# -----------------------------------------
+# $Id$
+# -----------------------------------------
+# This is a template so you can create your own network configuration
+# files Just follow the instructions and it will prolly work ;) 0 = No 1
+# = Yes -------------------------------------------------------
+#
+# These two specify the name of the IRC network, set the same in both
+# fields
+Network >..........: SolarXTreme
+Set ircnetwork ....: SolarXTreme
+
+# This is where your DNS pool is (like irc.dal.net)
+Set defserv .......: irc.solarxtreme.net
+
+# This is the name of your Services Server
+Set SERVICES_NAME .: Services.SolarXTreme.Net
+
+# This is the virtual hostname IRCops will get if iNAH option is enabled
+# on oper up
+Set oper_host .....: IRCop.SolarXTreme.Net
+
+# This is the virtual hostname Server Admins will get if iNAH option is
+# enabled on oper up
+Set admin_host ....: Admin.SolarXTreme.Net
+
+# This is the virtual hostname Local IRCops will get if iNAH option is
+# enabled on oper up
+
+Set locop_host ....: LocOp.SolarXTreme.Net
+
+# This is the virtual hostname Services Operators/Admins will get
+# if iNAH option is enabled on oper up
+
+Set sadmin_host ...: ServicesOp.SolarXTreme.Net
+
+# This is the virtual hostname NetAdmins will get
+# if iNAH option is enabled on oper up
+
+Set netadmin_host .: NetAdmin.SolarXTreme.Net
+
+# This is the virtual hostname CoAdmins will get
+# if iNAH option is enabled on oper up
+Set coadmin_host ..: CoAdmin.SolarXTreme.Net
+
+
+# This is the virtual hostname TechAdmins will get
+# if iNAH option is enabled on oper up
+Set techadmin_host : TechAdmin.SolarXTreme.Net
+
+# This is the prefix of the hidden host (cloaking) hostname
+Set hidden_host ...: solar
+# This is the domain of the IRC network
+Set netdomain .....: solarxtreme.net
+# This is where people can go for help
+Set helpchan ......: #SolarHelp
+# This is the name of the stats server
+Set STATS_SERVER ..: Stats.SolarXTreme.Net
+# -- Not in use--
+Set HUB ...........: 1
+# This enables the auto-setting of f.x @netadmin.network.net
+# on oper up
+Set iNAH ..........: 1
+# -- Not in use but still here --
+Set net_quit ......: ic
+
--- /dev/null
+ver^2.2
+# SpyNet Network Configuration File
+# -----------------------------------------
+# Added-at: 23 August 1999 18:00 GMT
+# Author: Son|c
+# E-Mail: stskeeps@global-irc.net
+# $Id$
+# -----------------------------------------
+#
+
+Network >..........: SpyNet
+Set ircnetwork ....: SpyNet
+Set defserv .......: irc.SpyNet.Org
+Set SERVICES_NAME .: Services.SpyNet.Org
+Set oper_host .....: IRCops.SpyNet.Org
+Set admin_host ....: Admin.SpyNet.Org
+Set locop_host ....: LocalOper.SpyNet.Org
+Set sadmin_host ...: Sops.SpyNet.Org
+Set netadmin_host .: NetAdmin.SpyNet.Org
+Set coadmin_host ..: CoAdmin.SpyNet.Org
+Set techadmin_host : TechAdmin.SpyNet.Org
+Set hidden_host ...: Spy
+Set netdomain .....: SpyNet.Org
+Set helpchan ......: #SpyNet
+Set STATS_SERVER ..: stats.SpyNet.Org
+Set HUB ...........: 0
+Set iNAH ..........: 0
+Set net_quit ......: SN
--- /dev/null
+ver^2.2
+# These two specify the name of the IRC network, set the same in both fields
+Network >..........: StarSpace
+Set ircnetwork ....: StarSpace
+
+# This is where your DNS pool is (like irc.dal.net)
+Set defserv .......: IRC.StarSpace.Net
+
+# This is the name of your Services Server
+Set SERVICES_NAME .: Services.StarSpace.Net
+
+# This is the virtual hostname IRCops will get if iNAH option is enabled
+# on oper up
+Set oper_host .....: Global.StarSpace.Net
+
+# This is the virtual hostname Server Admins will get if iNAH option is enabled
+# on oper up
+Set admin_host ....: Admin.StarSpace.Net
+
+# This is the virtual hostname Local IRCops will get if iNAH option is enabled
+# on oper up
+
+Set locop_host ....: Local.StarSpace.Net
+
+# This is the virtual hostname Services Operators/Admins will get
+# if iNAH option is enabled on oper up
+
+Set sadmin_host ...: ServOp.StarSpace.Net
+
+# This is the virtual hostname NetAdmins will get
+# if iNAH option is enabled on oper up
+
+Set netadmin_host .: NetAdmin.StarSpace.Net
+
+# This is the virtual hostname CoAdmins will get
+# if iNAH option is enabled on oper up
+Set coadmin_host ..: CoAdmin.StarSpace.Net
+
+
+# This is the virtual hostname TechAdmins will get
+# if iNAH option is enabled on oper up
+Set techadmin_host : TechAdmin.StarSpace.Net
+
+# This is the prefix of the hidden host (cloaking) hostname
+Set hidden_host ...: starspace
+# This is the domain of the IRC network
+Set netdomain .....: StarSpace.Net
+# This is where people can go for help
+Set helpchan ......: #OperHelp
+# This is the name of the stats server
+Set STATS_SERVER ..: Stats.StarSpace.Net
+# -- Not in use--
+Set HUB ...........: 1
+# This enables the auto-setting of f.x @netadmin.network.net
+# on oper up
+Set iNAH ..........: 1
+# -- Not in use but still here --
+Set net_quit ......: SS
--- /dev/null
+ver^2.2
+#
+# Network Configuration File Template
+# -----------------------------------------
+# Added-at: <day> <month> <year> <hh:dd> GMT
+# Author: <nick> (<real name>)
+# E-Mail: <email>
+# $Id$
+# -----------------------------------------
+# This is a template so you can create your own network configuration files
+# Just follow the instructions and it will prolly work ;)
+# 0 = No 1 = Yes
+# -------------------------------------------------------
+#
+# These two specify the name of the IRC network, set the same in both fields
+Network >..........: IRC
+Set ircnetwork ....: IRC
+
+# This is where your DNS pool is (like irc.dal.net)
+Set defserv .......: irc.ircnet.org
+
+# This is the name of your Services Server
+Set SERVICES_NAME .: services.ircnet.org
+
+# This is the virtual hostname IRCops will get if iNAH option is enabled
+# on oper up
+Set oper_host .....: ircop.ircnet.org
+
+# This is the virtual hostname Server Admins will get if iNAH option is enabled
+# on oper up
+Set admin_host ....: admin.ircnet.org
+
+# This is the virtual hostname Local IRCops will get if iNAH option is enabled
+# on oper up
+
+Set locop_host ....: locop.ircnet.org
+
+# This is the virtual hostname Services Operators/Admins will get
+# if iNAH option is enabled on oper up
+
+Set sadmin_host ...: serviceop.ircnet.org
+
+# This is the virtual hostname NetAdmins will get
+# if iNAH option is enabled on oper up
+
+Set netadmin_host .: netadmin.ircnet.org
+
+# This is the virtual hostname CoAdmins will get
+# if iNAH option is enabled on oper up
+Set coadmin_host ..: coadmin.ircnet.org
+
+
+# This is the virtual hostname TechAdmins will get
+# if iNAH option is enabled on oper up
+Set techadmin_host : techadmin.ircnet.org
+
+# This is the prefix of the hidden host (cloaking) hostname
+Set hidden_host ...: mpx
+# This is the domain of the IRC network
+Set netdomain .....: ircnet.org
+# This is where people can go for help
+Set helpchan ......: #IRC
+# This is the name of the stats server
+Set STATS_SERVER ..: stats.ircnet.org
+# -- Not in use--
+Set HUB ...........: 1
+# This enables the auto-setting of f.x @netadmin.network.net
+# on oper up
+Set iNAH ..........: 0
+# -- Not in use but still here --
+Set net_quit ......: ic
--- /dev/null
+ver^2.2
+#
+# Network Configuration File Template
+# -----------------------------------------
+# Added-at: <day> <month> <year> <hh:dd> GMT
+# Author: <nick> (<real name>)
+# E-Mail: <email>
+# $Id$
+# -----------------------------------------
+# This is a template so you can create your own network configuration files
+# Just follow the instructions and it will prolly work ;)
+# 0 = No 1 = Yes
+# -------------------------------------------------------
+#
+# These two specify the name of the IRC network, set the same in both fields
+Network >..........: TSpre
+Set ircnetwork ....: TSpre
+
+# This is where your DNS pool is (like irc.dal.net)
+Set defserv .......: irc.tspre.org
+
+# This is the name of your Services Server
+Set SERVICES_NAME .: services.tspre.org
+
+# This is the virtual hostname IRCops will get if iNAH option is enabled
+# on oper up
+Set oper_host .....: ircop.tspre.org
+
+# This is the virtual hostname Server Admins will get if iNAH option is enabled
+# on oper up
+Set admin_host ....: admin.tspre.org
+
+# This is the virtual hostname Local IRCops will get if iNAH option is enabled
+# on oper up
+
+Set locop_host ....: locop.tspre.org
+
+# This is the virtual hostname Services Operators/Admins will get
+# if iNAH option is enabled on oper up
+
+Set sadmin_host ...: serviceop.tspre.org
+
+# This is the virtual hostname NetAdmins will get
+# if iNAH option is enabled on oper up
+
+Set netadmin_host .: netadmin.tspre.org
+
+# This is the virtual hostname CoAdmins will get
+# if iNAH option is enabled on oper up
+Set coadmin_host ..: coadmin.tspre.org
+
+
+# This is the virtual hostname TechAdmins will get
+# if iNAH option is enabled on oper up
+Set techadmin_host : techadmin.tspre.org
+
+# This is the prefix of the hidden host (cloaking) hostname
+Set hidden_host ...: ts
+# This is the domain of the IRC network
+Set netdomain .....: tspre.org
+# This is where people can go for help
+Set helpchan ......: #TSpre
+# This is the name of the stats server
+Set STATS_SERVER ..: stats.tspre.org
+# -- Not in use--
+Set HUB ...........: 1
+# This enables the auto-setting of f.x @netadmin.network.net
+# on oper up
+Set iNAH ..........: 0
+# -- Not in use but still here --
+Set net_quit ......: ic
--- /dev/null
+ver^1.1
+#
+# UnrealIRCd Configuration file - unrealircd.conf
+# (C) Carsten Munk 1999 - Under the GNU license
+# $Id$
+# Follow the instructions here.
+#
+# change the filename to what network header file you use
+# relative to DPATH
+Include .................: networks/roxnet.network
+
+#
+# What K:Line address can K:lined users mail at?
+#
+Set KLINE_ADDRESS .......: the admin of this server
+
+# If you want users to get auto +x on connect
+# 1 = Yes 0 = No
+Set MODE_X ..............: 1
+
+# Auto +i users when they connect?
+# 1 = Yes 0 = No
+Set MODE_I ..............: 0
+
+# If compiled on a halfhub network this will upgrade it to be a real hub
+# * else if tried on a leaf (not hub) it will cause an error
+# * NOTE: There are only TWO versions of UnrealIRCd - Leaf and [Half]Hub
+# * (in wIRCd terms)
+# * Leafs are normal leafs
+# * Halfhubs are hubs that doesn't send out a GLOBOPS when connect estab
+# * (unless if #define TRUEHUB)
+# 1 = Yes 0 = No
+
+Set TRUEHUB .............: 1
+
+#
+# The IRCd won't boot if not this setting set correctly
+# RTFM and go thru the config file (this file)
+# 1 = Yes 0 = No
+Set CONFIG_FILE_STOP ....: 0
+
+#
+# If to let non-opers do /stats O
+#
+#
+Set SHOWOPERS ...........: 0
+
+#
+# This will get the IRCd to exit links with different protocol ( < / > )
+#
+Set KILLDIFF ............: 1
+
+#
+# Show Oper MOTD at oper up?
+# 1 = Yes 0 = No
+Set SHOWOPERMOTD ........: 1
+
+#
+# Hide U:lines from non-opers in /links?
+# 1 = Yes 0 = No
+Set HIDE_ULINES .........: 0
+
+#
+# Allow use of ChatOps?
+# 1 = Yes 0 = No
+Set ALLOW_CHATOPS .......: 1
+
+#
+# What message do you want send to Z:lined SOCKS users?
+#
+Set SOCKS_BAN_MESSAGE ...: Insecure SOCKS server
+
+#
+# What quit message do we want to send not yet Z:lined SOCKS users?
+#
+Set SOCKS_QUIT_MESSAGE ..: Insecure SOCKS server
+
+#
+# How many seconds will a insecure SOCKS be banned?
+#
+Set SOCKSBANTIME ........: 86400
--- /dev/null
+ver^2.2
+#
+# Network Configuration File Template
+# -----------------------------------------
+# Added-at: <day> <month> <year> <hh:dd> GMT
+# Author: <nick> (<real name>)
+# E-Mail: <email>
+# $Id$
+# -----------------------------------------
+# This is a template so you can create your own network configuration files
+# Just follow the instructions and it will prolly work ;)
+# 0 = No 1 = Yes
+# -------------------------------------------------------
+#
+# These two specify the name of the IRC network, set the same in both fields
+Network >..........: UzayNet
+Set ircnetwork ....: UzayNet
+
+# This is where your DNS pool is (like irc.dal.net)
+Set defserv .......: uzaynet.com
+
+
+# This is the name of your Services Server
+Set SERVICES_NAME .: service.uzaynet.com
+
+# This is the virtual hostname IRCops will get if iNAH option is enabled
+# on oper up
+Set oper_host .....: ircop.silverserver.nu
+
+# This is the virtual hostname Server Admins will get if iNAH option is enabled
+# on oper up
+Set admin_host ....: admin.uzaynet.nu
+
+# This is the virtual hostname Local IRCops will get if iNAH option is enabled
+# on oper up
+
+Set locop_host ....: locop.uzaynet.nu
+
+# This is the virtual hostname Services Operators/Admins will get
+# if iNAH option is enabled on oper up
+
+Set sadmin_host ...: serviceop.uzaynet.nu
+
+# This is the virtual hostname NetAdmins will get
+# if iNAH option is enabled on oper up
+
+Set netadmin_host .: netadmin.uzaynet.nu
+
+# This is the virtual hostname CoAdmins will get
+# if iNAH option is enabled on oper up
+Set coadmin_host ..: coadmin.uzaynet.nu
+
+
+# This is the virtual hostname TechAdmins will get
+# if iNAH option is enabled on oper up
+Set techadmin_host : techadmin.uzaynet.nu
+
+# This is the prefix of the hidden host (cloaking) hostname
+Set hidden_host ...: UzayNet
+# This is the domain of the IRC network
+Set netdomain .....: uzaynet.nu
+# This is where people can go for help
+Set helpchan ......: #Help
+# This is the name of the stats server
+Set STATS_SERVER ..: statserv.uzaynet.com
+# -- Not in use--
+Set HUB ...........: 1
+# This enables the auto-setting of f.x @netadmin.network.net
+# on oper up
+Set iNAH ..........: 1
+# -- Not in use but still here --
+Set net_quit ......: ic
--- /dev/null
+ver^2.2
+#
+# Network Configuration File Template
+# -----------------------------------------
+# Added-at: 27 February 2000 05:46 CST
+# Author: Venusaur64 (Jahn Veach)
+# E-Mail: venusaur@flash.net
+# $Id$
+# -----------------------------------------
+# This is a template so you can create your own network configuration files
+# Just follow the instructions and it will prolly work ;)
+# 0 = No 1 = Yes
+# -------------------------------------------------------
+#
+# These two specify the name of the IRC network, set the same in both fields
+Network >..........: V64net
+Set ircnetwork ....: V64net
+
+# This is where your DNS pool is (like irc.dal.net)
+Set defserv .......: irc.v64.net
+
+# This is the name of your Services Server
+Set SERVICES_NAME .: services.v64.net
+
+# This is the virtual hostname IRCops will get if iNAH option is enabled
+# on oper up
+Set oper_host .....: ircop.v64.net
+
+# This is the virtual hostname Server Admins will get if iNAH option is enabled
+# on oper up
+Set admin_host ....: admin.v64.net
+
+# This is the virtual hostname Local IRCops will get if iNAH option is enabled
+# on oper up
+
+Set locop_host ....: locop.v64.net
+
+# This is the virtual hostname Services Operators/Admins will get
+# if iNAH option is enabled on oper up
+
+Set sadmin_host ...: serviceop.v64.net
+
+# This is the virtual hostname NetAdmins will get
+# if iNAH option is enabled on oper up
+
+Set netadmin_host .: netadmin.v64.net
+
+# This is the virtual hostname CoAdmins will get
+# if iNAH option is enabled on oper up
+Set coadmin_host ..: coadmin.v64.net
+
+
+# This is the virtual hostname TechAdmins will get
+# if iNAH option is enabled on oper up
+Set techadmin_host : techadmin.v64.net
+
+# This is the prefix of the hidden host (cloaking) hostname
+Set hidden_host ...: V64net
+# This is the domain of the IRC network
+Set netdomain .....: v64.net
+# This is where people can go for help
+Set helpchan ......: #HELP
+# This is the name of the stats server
+Set STATS_SERVER ..: stats.v64.net
+# -- Not in use--
+Set HUB ...........: 1
+# This enables the auto-setting of f.x @netadmin.network.net
+# on oper up
+Set iNAH ..........: 0
+# -- Not in use but still here --
+Set net_quit ......: ic
--- /dev/null
+#!/bin/sh
+# $Id$
+ echo "|=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= "
+ echo "| UnrealIRCd Network Submission "
+ echo "| "
+ echo "| If you want your networks network file in the "
+ echo "| next release please attach your network file "
+ echo "| to an email and mail it to "
+ echo" | unreal-networks@lists.sourceforge.net "
+ echo "| "
+ echo "|=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= "
+ exit 1
--- /dev/null
+#!/bin/sh
+# Rehash Script v2.0
+# $Id$
+
+IRCDPID="ircd.pid"
+
+if [ ! -r $IRCDPID ]; then
+clear
+echo "|--------------------------------------------|"
+echo "| **** ERROR **** |"
+echo "| Possible problems: |"
+echo "| (1) $IRCDPID not found |"
+echo "| (2) The IRCd is not running |"
+echo "|--------------------------------------------|"
+else
+PID=`cat $IRCDPID`
+kill -HUP $PID
+echo "|----------------------------------------"
+echo "| UnrealIRCD successfully rehashed."
+echo "| Process ID: $PID"
+echo "|----------------------------------------"
+fi
+
--- /dev/null
+/*
+ * $Id$
+ */
+#include <stdio.h>
+#ifdef _WIN32
+#include <io.h>
+#endif
+#include <fcntl.h>
+#ifdef _WIN32
+#include <sys\stat.h>
+#endif
+#include <time.h>
+
+int _FD_SETSIZE = 1024;
+char _NS_ADDRESS[256], _KLINE_ADDRESS[256];
+
+
+char Makefile[] =
+"CC=cl\n"
+"FD_SETSIZE=/D FD_SETSIZE=$FD_SETSIZE\n"
+"CFLAGS=/MT /O2 /I ./INCLUDE /Fosrc/ /nologo $(FD_SETSIZE) $(NS_ADDRESS) /D NOSPOOF=1 /c\n"
+"INCLUDES=./include/struct.h ./include/config.h ./include/sys.h \\\n"
+" ./include/common.h ./include/settings.h ./include/h.h ./include/numeric.h \\\n"
+" ./include/msg.h ./include/setup.h\n"
+"LINK=link.exe\n"
+"LFLAGS=kernel32.lib user32.lib gdi32.lib shell32.lib wsock32.lib \\\n"
+" oldnames.lib libcmt.lib /nodefaultlib /nologo /out:SRC/WIRCD.EXE\n"
+"OBJ_FILES=SRC/CHANNEL.OBJ SRC/USERLOAD.OBJ SRC/SEND.OBJ SRC/BSD.OBJ \\\n"
+" SRC/CIO_MAIN.OBJ SRC/S_CONF.OBJ SRC/DBUF.OBJ SRC/RES.OBJ \\\n"
+" SRC/HASH.OBJ SRC/CIO_INIT.OBJ SRC/PARSE.OBJ SRC/IRCD.OBJ \\\n"
+" SRC/S_NUMERIC.OBJ SRC/WHOWAS.OBJ SRC/RES_COMP.OBJ SRC/S_AUTH.OBJ \\\n"
+" SRC/HELP.OBJ SRC/S_MISC.OBJ SRC/MATCH.OBJ SRC/CRULE.OBJ \\\n"
+" SRC/S_DEBUG.OBJ SRC/RES_INIT.OBJ SRC/SUPPORT.OBJ SRC/LIST.OBJ \\\n"
+" SRC/S_ERR.OBJ SRC/PACKET.OBJ SRC/CLASS.OBJ SRC/S_BSD.OBJ \\\n"
+" SRC/MD5.OBJ SRC/S_SERV.OBJ SRC/S_USER.OBJ SRC/WIN32.OBJ \\\n"
+" SRC/DYNCONF.OBJ\\\n"
+" SRC/VERSION.OBJ SRC/WIN32.RES SRC/CLOAK.OBJ SRC/S_UNREAL.OBJ\n"
+"RC=rc.exe\n"
+"\n"
+"ALL: SRC/WIRCD.EXE SRC/CHKCONF.EXE\n"
+" @echo Complete.\n"
+"\n"
+"CLEAN:\n"
+" -@erase src\\*.exe 2>NUL\n"
+" -@erase src\\*.obj 2>NUL\n"
+" -@erase src\\win32.res 2>NUL\n"
+" -@erase src\\version.c 2>NUL\n"
+"\n"
+"include/setup.h:\n"
+" @echo Hmm...doesn't look like you've run Config...\n"
+" @echo Doing so now.\n"
+" @config.exe\n"
+"\n"
+"src/version.c: dummy\n"
+" @config.exe -v\n"
+"\n"
+"src/version.obj: src/version.c\n"
+" $(CC) $(CFLAGS) src/version.c\n"
+"\n"
+"SRC/WIRCD.EXE: $(OBJ_FILES) src/version.obj\n"
+" $(LINK) $(LFLAGS) $(OBJ_FILES)\n"
+"\n"
+"SRC/CHKCONF.EXE: ./include/struct.h ./include/config.h ./include/sys.h \\\n"
+" ./include/common.h ./src/crule.c ./src/match.c ./src/chkconf.c\n"
+" $(CC) /nologo /I ./include /D CR_CHKCONF /Fosrc/chkcrule.obj /c src/crule.c\n"
+" $(CC) /nologo /I ./include /D CR_CHKCONF /Fosrc/chkmatch.obj /c src/match.c\n"
+" $(CC) /nologo /I ./include /D CR_CHKCONF /Fosrc/chkconf.obj /c src/chkconf.c\n"
+" $(LINK) /nologo /out:src/chkconf.exe src/chkconf.obj src/chkmatch.obj \\\n"
+" src/chkcrule.obj\n"
+"\n"
+"src/parse.obj: src/parse.c $(INCLUDES)\n"
+" $(CC) $(CFLAGS) src/parse.c\n"
+"\n"
+"src/bsd.obj: src/bsd.c $(INCLUDES)\n"
+" $(CC) $(CFLAGS) src/bsd.c\n"
+"\n"
+"src/dbuf.obj: src/dbuf.c $(INCLUDES) ./include/dbuf.h\n"
+" $(CC) $(CFLAGS) src/dbuf.c\n"
+"\n"
+"src/packet.obj: src/packet.c $(INCLUDES)\n"
+" $(CC) $(CFLAGS) src/packet.c\n"
+"\n"
+"src/send.obj: src/send.c $(INCLUDES)\n"
+" $(CC) $(CFLAGS) src/send.c\n"
+"\n"
+"src/match.obj: src/match.c $(INCLUDES)\n"
+" $(CC) $(CFLAGS) src/match.c\n"
+"\n"
+"src/support.obj: src/support.c $(INCLUDES)\n"
+" $(CC) $(CFLAGS) src/support.c\n"
+"\n"
+"src/channel.obj: src/channel.c $(INCLUDES) ./include/channel.h\n"
+" $(CC) $(CFLAGS) src/channel.c\n"
+"\n"
+"src/class.obj: src/class.c $(INCLUDES) ./include/class.h\n"
+" $(CC) $(CFLAGS) src/class.c\n"
+"\n"
+"src/ircd.obj: src/ircd.c $(INCLUDES)\n"
+" $(CC) $(CFLAGS) src/ircd.c\n"
+"\n"
+"src/list.obj: src/list.c $(INCLUDES)\n"
+" $(CC) $(CFLAGS) src/list.c\n"
+"\n"
+"src/res.obj: src/res.c $(INCLUDES)\n"
+" $(CC) $(CFLAGS) src/res.c\n"
+"\n"
+"src/s_bsd.obj: src/s_bsd.c $(INCLUDES)\n"
+" $(CC) $(CFLAGS) src/s_bsd.c\n"
+"\n"
+"src/s_auth.obj: src/s_auth.c $(INCLUDES)\n"
+" $(CC) $(CFLAGS) src/s_auth.c\n"
+"\n"
+"src/s_conf.obj: src/s_conf.c $(INCLUDES)\n"
+" $(CC) $(CFLAGS) src/s_conf.c\n"
+"\n"
+"src/s_debug.obj: src/s_debug.c $(INCLUDES)\n"
+" $(CC) $(CFLAGS) src/s_debug.c\n"
+"\n"
+"src/s_err.obj: src/s_err.c $(INCLUDES)\n"
+" $(CC) $(CFLAGS) src/s_err.c\n"
+"\n"
+"src/s_misc.obj: src/s_misc.c $(INCLUDES) ./include/dbuf.h\n"
+" $(CC) $(CFLAGS) src/s_misc.c\n"
+"\n"
+"src/s_user.obj: src/s_user.c $(INCLUDES) ./include/dbuf.h \\\n"
+" ./include/channel.h ./include/whowas.h\n"
+" $(CC) $(CFLAGS) src/s_user.c\n"
+"\n"
+"src/dynconf.obj: src/dynconf.c $(INCLUDES) ./include/dbuf.h \\\n"
+" ./include/channel.h ./include/whowas.h ./include/dynconf.h\n"
+" $(CC) $(CFLAGS) src/dynconf.c\n"
+"\n"
+"src/s_unreal.obj: src/s_unreal.c $(INCLUDES) ./include/dbuf.h \\\n"
+" ./include/channel.h ./include/whowas.h\n"
+" $(CC) $(CFLAGS) src/s_unreal.c\n"
+"\n"
+"src/cloak.obj: src/cloak.c $(INCLUDES) ./include/dbuf.h \\\n"
+" ./include/channel.h ./include/whowas.h\n"
+" $(CC) $(CFLAGS) src/s_unreal.c\n"
+"\n"
+"src/s_serv.obj: src/s_serv.c $(INCLUDES) ./include/dbuf.h ./include/whowas.h\n"
+" $(CC) $(CFLAGS) src/s_serv.c\n"
+"\n"
+"src/s_numeric.obj: src/s_numeric.c $(INCLUDES) ./include/dbuf.h\n"
+" $(CC) $(CFLAGS) src/s_numeric.c\n"
+"\n"
+"src/whowas.obj: src/whowas.c $(INCLUDES) ./include/dbuf.h ./include/whowas.h\n"
+" $(CC) $(CFLAGS) src/whowas.c\n"
+"\n"
+"src/hash.obj: src/hash.c $(INCLUDES) ./include/hash.h\n"
+" $(CC) $(CFLAGS) src/hash.c\n"
+"\n"
+"src/crule.obj: src/crule.c $(INCLUDES)\n"
+" $(CC) $(CFLAGS) src/crule.c\n"
+"\n"
+"src/win32.obj: src/win32.c $(INCLUDES) ./include/resource.h\n"
+" $(CC) $(CFLAGS) src/win32.c\n"
+"\n"
+"src/cio_main.obj: src/cio_main.c $(INCLUDES) ./include/cio.h ./include/ciofunc.h\n"
+" $(CC) $(CFLAGS) src/cio_main.c\n"
+"\n"
+"src/cio_init.obj: src/cio_init.c $(INCLUDES) ./include/cio.h ./include/ciofunc.h\n"
+" $(CC) $(CFLAGS) src/cio_init.c\n"
+"\n"
+"src/res_comp.obj: src/res_comp.c $(INCLUDES)\n"
+" $(CC) $(CFLAGS) src/res_comp.c\n"
+"\n"
+"src/res_init.obj: src/res_init.c $(INCLUDES)\n"
+" $(CC) $(CFLAGS) src/res_init.c\n"
+"\n"
+"src/help.obj: src/help.c $(INCLUDES)\n"
+" $(CC) $(CFLAGS) src/help.c\n"
+"\n"
+"src/md5.obj: src/md5.c $(INCLUDES)\n"
+" $(CC) $(CFLAGS) src/md5.c\n"
+"\n"
+"src/win32.res: src/win32.rc\n"
+" $(RC) /l 0x409 /fosrc/win32.res /i ./include /i ./src \\\n"
+" /d NDEBUG src/win32.rc\n"
+"\n"
+"dummy:\n"
+"\n";
+
+
+char SetupH[] =
+"/* This is only a wrapper.. --Stskeeps */\n"
+"#include \"win32/setup.h\"\n";
+
+
+int main(int argc, char *argv[])
+{
+ if (argc>1)
+ {
+ if (!strcmp(argv[1], "-v"))
+ return do_version();
+
+ if (!strcmp(argv[1], "-n"))
+ return do_config(1);
+ }
+ printf("To do win32 compiling copy include/win32/setup.h to include/\n");
+ printf("Copy include/win32/settings.h to include/ and modify it\n");
+ printf("and copy makefile.win32 to Makefile\n");
+// return do_config(0);
+}
+
+
+int do_config(int autoconf)
+{
+ int fd;
+ char str[128];
+
+
+ if ((fd = open("include\\setup.h", O_CREAT|O_TRUNC|O_WRONLY|O_TEXT,
+ S_IREAD|S_IWRITE)) == -1)
+ printf("Error opening include\\setup.h\n\r");
+ else
+ {
+ write(fd, SetupH, strlen(SetupH));
+ close(fd);
+ }
+
+ while (1)
+ {
+ /*
+ * FD_SETSIZE
+ */
+ printf("\n");
+ printf("How many file descriptors (or sockets) can the irc server use?");
+ printf("\n");
+ printf("[%d] -> ", _FD_SETSIZE);
+ gets(str);
+ if (*str != '\n' && *str != '\r')
+ sscanf(str, "%d", &_FD_SETSIZE);
+
+ if (_FD_SETSIZE >= 100)
+ {
+ printf("\n");
+ printf("FD_SETSIZE will be overridden using -D "
+ "FD_SETSIZE=%d when compiling ircd.", _FD_SETSIZE);
+ printf("\n");
+ break;
+ }
+ printf("\n");
+ printf("You need to enter a number here, greater or equal to 100.\n");
+ }
+ while (1) {
+ }
+ /*
+ * Now write the makefile out.
+ */
+ write_makefile();
+
+ return 0;
+}
+
+
+int write_makefile(void)
+{
+ int fd, makfd, len;
+ char *buffer, *s;
+
+ buffer = (char *)malloc(strlen(Makefile)+4096);
+ memcpy(buffer, Makefile, strlen(Makefile)+1);
+
+ s = (char *)strstr(buffer, "$FD_SETSIZE");
+ if (s)
+ {
+ itoa(_FD_SETSIZE, s, 10);
+ memmove(s+strlen(s), s+11, strlen(s+11)+1);
+ }
+
+
+ if ((makfd = open("Makefile", O_CREAT|O_TRUNC|O_WRONLY|O_TEXT,
+ S_IREAD|S_IWRITE)) == -1)
+ {
+ printf("Error creating Makefile\n\r");
+ return 1;
+ }
+ write(makfd, buffer, strlen(buffer));
+ close(makfd);
+
+ free(buffer);
+ return 0;
+}
+
+
+int do_version(void)
+{
+ int fd, verfd, generation=0, len, doingvernow=0;
+ char buffer[16384], *s;
+
+ if ((verfd = open("src\\version.c", O_RDONLY | O_TEXT)) != -1)
+ {
+ while (!eof(verfd))
+ {
+ len = read(verfd, buffer, sizeof(buffer)-1);
+ if (len == -1)
+ break;
+ buffer[len] = 0;
+ s = (char *)strstr(buffer, "char *generation = \"");
+ if (s)
+ {
+ s += 20;
+ generation = atoi(s);
+ break;
+ }
+ }
+
+ close(verfd);
+ }
+
+ if ((fd = open("src\\version.c.SH", O_RDONLY | O_TEXT)) == -1)
+ {
+ printf("Error opening src\\version.c.SH\n\r");
+ return 1;
+ }
+
+ if ((verfd = open("src\\version.c", O_CREAT|O_TRUNC|O_WRONLY|O_TEXT,
+ S_IREAD|S_IWRITE)) == -1)
+ {
+ printf("Error opening src\\version.c\n\r");
+ return 1;
+ }
+
+ generation++;
+
+ printf("Extracting IRC/ircd/version.c...\n\r");
+
+ while (!eof(fd))
+ {
+ len = read(fd, buffer, sizeof(buffer)-1);
+ if (len == -1)
+ break;
+ buffer[len] = 0;
+ if (!doingvernow)
+ {
+ s = (char *)strstr(buffer, "/*");
+ if (!s)
+ continue;
+ memmove(buffer, s, strlen(s)+1);
+ doingvernow=1;
+ }
+ s = (char *)strstr(buffer, "$generation");
+ if (s)
+ {
+ itoa(generation, s, 10);
+ memmove(s+strlen(s), s+11, strlen(s+11)+1);
+ }
+ s = (char *)strstr(buffer, "$creation");
+ if (s)
+ {
+ time_t t = time(0);
+ char *ct = ctime(&t);
+
+ memmove(s+strlen(ct)-1, s+9, strlen(s+9)+1);
+ memmove(s, ct, strlen(ct)-1);
+ }
+ s = (char *)strstr(buffer, "$package");
+ if (s)
+ {
+ memmove(s, "IRC", 3);
+ memmove(s+3, s+8, strlen(s+8)+1);
+ }
+
+ s = (char *)strstr(buffer, "!SUB!THIS!");
+ if (s)
+ *s = 0;
+
+ write(verfd, buffer, strlen(buffer));
+ }
+
+ close(fd);
+ close(verfd);
+ return 0;
+}
+
+
--- /dev/null
+#************************************************************************
+#* IRC - Internet Relay Chat, src/Makefile
+#* Copyright (C) 1990 Jarkko Oikarinen
+#*
+#* 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#*
+#* $Id$
+#*/
+
+CC=danger will robinson
+
+LINTFLAGS=-hba
+
+OBJS=bsd.o dbuf.o packet.o send.o match.o parse.o support.o channel.o \
+ class.o hash.o ircd.o list.o res.o cloak.o s_auth.o s_bsd.o s_conf.o \
+ s_debug.o s_err.o s_extra.o s_misc.o s_numeric.o s_serv.o s_user.o s_unreal.o \
+ whowas.o userload.o crule.o help.o md5.o version.o dynconf.o \
+ s_socks.o s_kline.o fdlist.o \
+ $(RES) $(STRTOUL)
+
+SRC=$(OBJS:%.o=%.c)
+
+MAKE = make 'CFLAGS=${CFLAGS}' 'CC=${CC}' 'IRCDLIBS=${IRCDLIBS}' \
+ 'LDFLAGS=${LDFLAGS}' 'IRCDMODE=${IRCDMODE}'
+
+INCLUDES = ../include/struct.h ../include/config.h ../include/settings.h \
+ ../include/sys.h ../include/common.h ../include/version.h \
+ ../include/h.h ../include/numeric.h ../include/msg.h \
+ ../include/dynconf.h
+
+all: build
+
+build: ircd chkconf
+
+version.c:
+ $(SHELL) version.c.SH
+
+version.o: version.c ../include/version.h
+ $(CC) $(CFLAGS) -c version.c
+
+ircd: $(OBJS)
+ $(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) $(IRCDLIBS) -o ircd
+ chmod $(IRCDMODE) ircd
+
+chkconf: ../include/struct.h ../include/config.h ../include/settings.h ../include/sys.h \
+ ../include/common.h crule.c chkconf.c
+ $(CC) $(CFLAGS) -DCR_CHKCONF -o chkcrule.o -c crule.c
+ $(CC) $(CFLAGS) -DCR_CHKCONF -o chkmatch.o -c match.c
+ $(CC) $(CFLAGS) chkconf.c chkmatch.o chkcrule.o \
+ $(LDFLAGS) $(IRCDLIBS) -o chkconf
+
+saber: $(SRC)
+ #load -I../include $(SRC) version.c $(IRCDLIBS)
+
+lint:
+ lint $(LINTFLAGS) -I../include $(SRC) | egrep -v 'sendto_|debug'
+
+parse.o: parse.c $(INCLUDES)
+bsd.o: bsd.c $(INCLUDES)
+dbuf.o: dbuf.c $(INCLUDES) ../include/dbuf.h
+packet.o: packet.c $(INCLUDES)
+send.o: send.c $(INCLUDES)
+match.o: match.c $(INCLUDES)
+support.o: support.c $(INCLUDES)
+
+#install: all
+# -if [ ! -d ${IRCDDIR} -a ! -f ${IRCDDIR} ] ; then \
+# mkdir ${IRCDDIR}; \
+# fi
+# ../bsdinstall -m ${IRCDMODE} ircd ${BINDIR}
+# ../bsdinstall -m 700 chkconf ${BINDIR}
+# $(CP) ../doc/example.conf ${IRCDDIR}
+# $(TOUCH) ${IRCDDIR}/ircd.motd
+# $(RM) -f ${IRCDDIR}/ircd.m4
+# $(TOUCH) ${IRCDDIR}/ircd.m4
+# chmod +x buildm4
+# ./buildm4 ${IRCDDIR}
+
+clean:
+ $(RM) -f *.o *~ core ircd version.c chkconf
+
+cleandir: clean
+
+depend:
+ makedepend -I${INCLUDEDIR} ${SRC}
+
+channel.o: channel.c $(INCLUDES) ../include/channel.h
+ $(CC) $(CFLAGS) -c channel.c
+
+class.o: class.c $(INCLUDES) ../include/class.h
+ $(CC) $(CFLAGS) -c class.c
+
+ircd.o: ircd.c ../include/dbuf.h $(INCLUDES)
+ $(CC) $(CFLAGS) -c ircd.c
+
+list.o: list.c ../include/dbuf.h $(INCLUDES)
+ $(CC) $(CFLAGS) -c list.c
+
+res.o: res.c ../include/res.h $(INCLUDES)
+ $(CC) $(CFLAGS) -c res.c
+
+cloak.o: cloak.c ../include/res.h $(INCLUDES)
+ $(CC) $(CFLAGS) -c cloak.c
+
+fdlist.o: fdlist.c ../include/fdlist.h $(INCLUDES)
+ $(CC) $(CFLAGS) -c fdlist.c
+
+s_bsd.o: s_bsd.c ../include/dbuf.h $(INCLUDES)
+ $(CC) $(CFLAGS) -c s_bsd.c
+
+s_auth.o: s_auth.c ../include/dbuf.h $(INCLUDES)
+ $(CC) $(CFLAGS) -c s_auth.c
+
+s_socks.o: s_socks.c ../include/dbuf.h $(INCLUDES)
+ $(CC) $(CFLAGS) -c s_socks.c
+
+s_conf.o: s_conf.c ../include/dbuf.h $(INCLUDES)
+ $(CC) $(CFLAGS) -c s_conf.c
+
+s_debug.o: ../include/sys.h s_debug.c $(INCLUDES)
+ $(CC) $(CFLAGS) -c s_debug.c
+
+s_err.o: ../include/msg.h s_err.c $(INCLUDES)
+ $(CC) $(CFLAGS) -c s_err.c
+
+s_misc.o: s_misc.c ../include/dbuf.h $(INCLUDES)
+ $(CC) $(CFLAGS) -c s_misc.c
+
+s_user.o: s_user.c $(INCLUDES) \
+ ../include/dbuf.h ../include/channel.h ../include/whowas.h
+ $(CC) $(CFLAGS) -c s_user.c
+
+s_extra.o: s_extra.c $(INCLUDES) \
+ s_numeric.c ../include/dbuf.h ../include/channel.h ../include/whowas.h
+ $(CC) $(CFLAGS) -c s_extra.c
+
+s_kline.o: s_kline.c $(INCLUDES) \
+ s_numeric.c ../include/dbuf.h ../include/channel.h ../include/whowas.h
+ $(CC) $(CFLAGS) -c s_kline.c
+
+s_unreal.o: s_unreal.c $(INCLUDES) \
+ s_numeric.c ../include/dbuf.h ../include/channel.h ../include/whowas.h
+ $(CC) $(CFLAGS) -c s_unreal.c
+
+s_serv.o: s_serv.c $(INCLUDES) \
+ ../include/dbuf.h ../include/whowas.h
+ $(CC) $(CFLAGS) -c s_serv.c
+
+s_numeric.o: s_numeric.c ../include/dbuf.h $(INCLUDES)
+ $(CC) $(CFLAGS) -c s_numeric.c
+
+whowas.o: whowas.c ../include/dbuf.h ../include/whowas.h $(INCLUDES)
+ $(CC) $(CFLAGS) -c whowas.c
+
+hash.o: hash.c ../include/hash.h $(INCLUDES)
+ $(CC) $(CFLAGS) -c hash.c
+
+crule.o: crule.c $(INCLUDES)
+ $(CC) $(CFLAGS) -c crule.c
+
+dynconf.o: dynconf.c $(INCLUDES) \
+ s_numeric.c ../include/dbuf.h ../include/channel.h ../include/whowas.h ../include/dynconf.h
+ $(CC) $(CFLAGS) -c dynconf.c
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, common/bsd.c
+ * Copyright (C) 1990 Jarkko Oikarinen and
+ * University of Oulu, Computing Center
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#include "h.h"
+#include <signal.h>
+
+ID_CVS("$Id$");
+ID_Copyright("(C) 1988 University of Oulu, Computing Center and Jarkko Oikarinen");
+
+
+#ifndef _WIN32
+extern int errno; /* ...seems that errno.h doesn't define this everywhere */
+#endif
+#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__linux__)
+extern char *sys_errlist[];
+#endif
+
+#ifdef DEBUGMODE
+int writecalls = 0, writeb[10] = {0,0,0,0,0,0,0,0,0,0};
+#endif
+#ifndef _WIN32
+VOIDSIG dummy()
+{
+#ifndef HAVE_RELIABLE_SIGNALS
+ (void)signal(SIGALRM, dummy);
+ (void)signal(SIGPIPE, dummy);
+#ifndef HPUX /* Only 9k/800 series require this, but don't know how to.. */
+# ifdef SIGWINCH
+ (void)signal(SIGWINCH, dummy);
+# endif
+#endif
+#else
+# ifdef POSIX_SIGNALS
+ struct sigaction act;
+
+ act.sa_handler = dummy;
+ act.sa_flags = 0;
+ (void)sigemptyset(&act.sa_mask);
+ (void)sigaddset(&act.sa_mask, SIGALRM);
+ (void)sigaddset(&act.sa_mask, SIGPIPE);
+# ifdef SIGWINCH
+ (void)sigaddset(&act.sa_mask, SIGWINCH);
+# endif
+ (void)sigaction(SIGALRM, &act, (struct sigaction *)NULL);
+ (void)sigaction(SIGPIPE, &act, (struct sigaction *)NULL);
+# ifdef SIGWINCH
+ (void)sigaction(SIGWINCH, &act, (struct sigaction *)NULL);
+# endif
+# endif
+#endif
+}
+#endif /* _WIN32 */
+
+
+/*
+** deliver_it
+** Attempt to send a sequence of bytes to the connection.
+** Returns
+**
+** < 0 Some fatal error occurred, (but not EWOULDBLOCK).
+** This return is a request to close the socket and
+** clean up the link.
+**
+** >= 0 No real error occurred, returns the number of
+** bytes actually transferred. EWOULDBLOCK and other
+** possibly similar conditions should be mapped to
+** zero return. Upper level routine will have to
+** decide what to do with those unwritten bytes...
+**
+** *NOTE* alarm calls have been preserved, so this should
+** work equally well whether blocking or non-blocking
+** mode is used...
+**
+** *NOTE* I nuked 'em. At the load of current ircd servers
+** you can't run with stuff that blocks. And we don't.
+*/
+int deliver_it(cptr, str, len)
+aClient *cptr;
+int len;
+char *str;
+ {
+ int retval;
+ aClient *acpt = cptr->acpt;
+
+#ifdef DEBUGMODE
+ writecalls++;
+#endif
+#ifdef VMS
+ retval = netwrite(cptr->fd, str, len);
+#else
+ if (IsDead(cptr) || (!IsServer(cptr) && !IsPerson(cptr) && !IsHandshake(cptr) && !IsUnknown(cptr)))
+ {
+ str[len]='\0';
+ sendto_ops("* * * DEBUG ERROR * * * !!! Calling deliver_it() for %s, status %d %s, with message: %s",
+ cptr->name, cptr->status, IsDead(cptr)?"DEAD":"", str);
+ return -1;
+ }
+ retval = send(cptr->fd, str, len, 0);
+ /*
+ ** Convert WOULDBLOCK to a return of "0 bytes moved". This
+ ** should occur only if socket was non-blocking. Note, that
+ ** all is Ok, if the 'write' just returns '0' instead of an
+ ** error and errno=EWOULDBLOCK.
+ **
+ ** ...now, would this work on VMS too? --msa
+ */
+# ifndef _WIN32
+ if (retval < 0 && (errno == EWOULDBLOCK || errno == EAGAIN ||
+ errno == ENOBUFS))
+# else
+ if (retval < 0 && (WSAGetLastError() == WSAEWOULDBLOCK ||
+ WSAGetLastError() == WSAENOBUFS))
+# endif
+ {
+ retval = 0;
+ SetBlocked(cptr);
+ }
+ else if (retval > 0)
+ {
+#ifdef pyr
+ (void)gettimeofday(&cptr->lw, NULL);
+#endif
+ ClearBlocked(cptr);
+ }
+
+#endif
+#ifdef DEBUGMODE
+ if (retval < 0) {
+ writeb[0]++;
+# ifndef _WIN32
+ Debug((DEBUG_ERROR,"write error (%s) to %s",
+ sys_errlist[errno], cptr->name));
+# else
+ Debug((DEBUG_ERROR,"write error (%s) to %s",
+ sys_errlist[WSAGetLastError()], cptr->name));
+# endif
+
+ } else if (retval == 0)
+ writeb[1]++;
+ else if (retval < 16)
+ writeb[2]++;
+ else if (retval < 32)
+ writeb[3]++;
+ else if (retval < 64)
+ writeb[4]++;
+ else if (retval < 128)
+ writeb[5]++;
+ else if (retval < 256)
+ writeb[6]++;
+ else if (retval < 512)
+ writeb[7]++;
+ else if (retval < 1024)
+ writeb[8]++;
+ else
+ writeb[9]++;
+#endif
+ if (retval > 0)
+ {
+ cptr->sendB += retval;
+ me.sendB += retval;
+ if (cptr->sendB > 1023)
+ {
+ cptr->sendK += (cptr->sendB >> 10);
+ cptr->sendB &= 0x03ff; /* 2^10 = 1024, 3ff = 1023 */
+ }
+ if (acpt != &me)
+ {
+ acpt->sendB += retval;
+ if (acpt->sendB > 1023)
+ {
+ acpt->sendK += (acpt->sendB >> 10);
+ acpt->sendB &= 0x03ff;
+ }
+ }
+ else if (me.sendB > 1023)
+ {
+ me.sendK += (me.sendB >> 10);
+ me.sendB &= 0x03ff;
+ }
+ }
+ return(retval);
+}
--- /dev/null
+#!/bin/sh
+# IRC - Internet Relay Chat, ircd/buildm4
+# Copyright (C) 1993 Darren Reed
+#
+# 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# - $Id$
+#
+# If only this was a perl script...*sigh*
+#
+IRCDDIR=$1
+M4=$IRCDDIR/ircd.m4
+/bin/rm -f $M4
+egrep "^#def[^P]*VERSION" ../include/version.h | \
+sed -e 's/[^\"]*\"\([^\"]*\)\"/define(VERSION,\1)/' >>$M4
+DEBUG=`egrep "^#define[ ]*DEBUGMODE" ../include/config.h`
+if [ -n "$DEBUG" ] ; then
+ echo "define(DEBUGMODE,1)" >>$M4
+else
+ echo "undefine(DEBUGMODE)" >>$M4
+fi
+echo -n "define(HOSTNAME," >> $M4
+echo "`hostname`" | sed -e 's/\([a-zA-Z0-9\-]*\).*/\1)/' >> $M4
+echo "define(USER,$USER)" >>$M4
+echo -n 'define(PORT,' >>$M4
+PORT=`egrep '^#define[ ]*PORT[ ]*[0-9]*' ../include/config.h`
+echo "$PORT" | sed -e 's/[^0-9]*\([0-9]*\).*/\1)/' >> $M4
+echo -n 'define(PFREQ,' >>$M4
+PING=`egrep '^#define[ ]*PINGFREQUENCY[ ]*[0-9]*' ../include/config.h`
+echo "$PING" | sed -e 's/[^0-9]*\([0-9]*\).*/\1)/' >> $M4
+echo -n 'define(CFREQ,' >>$M4
+CONT=`egrep '^#define[ ]*CONNECTFREQUENCY[ ]*[0-9]*' ../include/config.h`
+echo "$CONT" | sed -e 's/[^0-9]*\([0-9]*\).*/\1)/' >> $M4
+echo -n "define(MAXSENDQ," >>$M4
+MAXQ=`egrep '^#define[ ]*MAXSENDQLENGTH[ ]*[0-9]*' ../include/config.h`
+echo "$MAXQ" | sed -e 's/[^0-9]*\([0-9]*\).*/\1)/' >> $M4
+echo -n "define(MAXLINKS," >>$M4
+MAXL=`egrep '^#define[ ]*MAXIMUM_LINKS[ ]*[0-9]* | head -1' \
+../include/config.h`
+echo "$MAXL" | sed -e 's/[^0-9]*\([0-9]*\).*/\1)/' >> $M4
+DOM=`egrep '^domain' /etc/resolv.conf | \
+sed -e 's/^domain[ ]*\([a-zA-Z\-\.0-9]*\).*/\1/'`
+echo "define(DOMAIN,$DOM)" >> $M4
+
+cat >>$M4 <<_EOF_
+define(CL,\`ifelse(len(\$1),0,0,\$1)')
+define(HOST,\$1)
+define(HOSTM,\$1)
+define(ID,*@\$1)
+define(PASS,\$1)
+define(PING,\`ifelse(len(\$1),0,PFREQ,\$1)')
+define(APORT,\`ifelse(len(\$1),0,PORT,\$1)')
+define(FREQ,\`ifelse(len(\$1),0,CFREQ,\$1)')
+define(SENDQ,\`ifelse(len(\$1),0,MAXSENDQ,\$1)')
+define(MAX,\`ifelse(len(\$1),0,MAXLINKS,\$1)')
+define(CPORT,\$1)
+define(SERV,\$1)
+define(ADMIN,A:\$1:\$2:\$3:\$4:\$5)
+define(ALLOW,N:\`HOST(\$1)':\`PASS(\$2)':\`SERV(\$3)':\`HOSTM(\$4)':\`CL(\$5)')
+define(BAN,K:\$1:\$2:\$3)
+define(CLASS,Y:\$1:\`PING(\$2)':\$3:\`MAX(\$4)':\`SENDQ(\$5)')
+define(CLIENT,I:\`HOST(\$1)':\`PASS(\$2)':\`ifelse(len(HOST(\$3)),0,\$1,\$3)':\
+\`APORT(\$4)':\`CL(\$5)')
+define(CONNECT,C:\`HOST(\$1)':\`PASS(\$2)':\`SERV(\$3)':\
+\`CPORT(\$4)':\`CL(\$5)')
+define(ME,M:\$1:\$2:\$3:\$4:\$5)
+define(HUB,H:\`ifelse(len(\$2),0,*,\$2)':*:\$1)
+define(LEAF,L:\`ifelse(len(\$2),0,*,\$2)':*:\$1:1)
+define(SERVER,\`
+CONNECT(\$1,\$2,\$3,\$5,\$6)
+ALLOW(\$1,\$2,\$3,\$4,\$6)
+')
+_EOF_
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, ircd/channel.c
+ * Copyright (C) 1990 Jarkko Oikarinen and
+ * University of Oulu, Co Center
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * 23 Jun 1999
+ * Changing unsigned int modes to long
+ * --- Sts - 28 May 1999
+ Incorporated twilight mode system
+*/
+/* -- Jto -- 09 Jul 1990
+ * Bug fix
+ */
+
+/* -- Jto -- 03 Jun 1990
+ * Moved m_channel() and related functions from s_msg.c to here
+ * Many changes to start changing into string channels...
+ */
+
+/* -- Jto -- 24 May 1990
+ * Moved is_full() from list.c
+ */
+
+
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#include "numeric.h"
+#include "channel.h"
+#include "msg.h" /* For TOK_*** and MSG_*** strings */
+#include "hash.h" /* For CHANNELHASHSIZE */
+#include "h.h"
+
+ID_CVS("$Id$");
+ID_Copyright("(C) 1990 University of Oulu, Computing Center and Jarkko Oikarinen");
+
+#define MAXBOUNCE 5 /** Most sensible */
+
+typedef struct ChLink CHLINK;
+struct CHLink {
+ aChannel *chan;
+};
+
+static int bouncedtimes = 0;
+
+struct CHLink chlbounce[MAXBOUNCE];
+int chbounce = 0;
+static long opermode = 0;
+aChannel *channel = NullChn;
+extern aCRline *crlines;
+extern char *cannotjoin_msg;
+// #define is_zombie(x,y) 0
+
+static void add_invite PROTO((aClient *, aChannel *));
+static int add_banid PROTO((aClient *, aChannel *, char *));
+static int can_join PROTO((aClient *, aClient *, aChannel *, char *, char *, char **));
+static int channel_link PROTO((aClient *, aClient *, int, char **));
+static void channel_modes PROTO((aClient *, char *, char *, aChannel *));
+static int check_channelmask PROTO((aClient *, aClient *, char *));
+static int del_banid PROTO((aChannel *, char *));
+static int find_banid PROTO((aChannel *, char *));
+static int have_ops PROTO((aChannel *));
+// static int number_of_zombies PROTO((aChannel *));
+static int is_deopped PROTO((aClient *, aChannel *));
+static void set_mode PROTO((aChannel *, aClient *, int, char **, u_int *, \
+ char [MAXMODEPARAMS][MODEBUFLEN+3], int));
+static void make_mode_str PROTO((aChannel *, long, long, int, \
+ char [MAXMODEPARAMS][MODEBUFLEN+3], char *, char *, char));
+static int do_mode_char PROTO((aChannel *, long, char, char *, u_int, \
+ aClient *, u_int *, char [MAXMODEPARAMS][MODEBUFLEN+3], char));
+static void do_mode PROTO((aChannel *, aClient *, aClient *, int, char **,
+ int, int));
+static void bounce_mode PROTO((aChannel *, aClient *, int, char **));
+
+static void sub1_from_channel PROTO((aChannel *));
+
+void clean_channelname PROTO((char *));
+void del_invite PROTO((aClient *, aChannel *));
+
+static char *PartFmt = ":%s PART %s";
+static char *PartFmt2 = ":%s PART %s :%s";
+/*
+ * some buffers for rebuilding channel/nick lists with ,'s
+ */
+static char nickbuf[BUFSIZE], buf[BUFSIZE];
+static char modebuf[MODEBUFLEN], parabuf[MODEBUFLEN];
+static long linkedjoined = 0;
+#include "sjoin.h"
+
+#ifdef USE_LONGMODE
+typedef struct {
+ long mode;
+ char flag;
+ int halfop; /* 1 = yes 0 = no */
+} aCtab;
+// typedef struct CFlagTab aCtab;
+#define MODESYS_LINKOK /* We do this for a TEST */
+aCtab cFlagTab[] = {
+ {MODE_LIMIT, 'l', 0},
+ {MODE_VOICE, 'v', 1},
+ {MODE_HALFOP, 'h', 0},
+ {MODE_CHANOP, 'o', 0},
+ {MODE_PRIVATE, 'p', 0},
+ {MODE_SECRET, 's', 0},
+ {MODE_MODERATED, 'm', 1},
+ {MODE_NOPRIVMSGS, 'n', 1},
+ {MODE_TOPICLIMIT, 't', 1},
+ {MODE_INVITEONLY, 'i', 1},
+ {MODE_KEY, 'k', 1},
+ {MODE_RGSTR, 'r', 0},
+ {MODE_RGSTRONLY, 'R', 0},
+ {MODE_NOCOLOR, 'c', 0},
+ {MODE_CHANPROT, 'a', 0},
+ {MODE_CHANOWNER, 'q', 0},
+ {MODE_OPERONLY, 'O', 0},
+ {MODE_ADMONLY, 'A', 0},
+ {MODE_LINK, 'L', 0},
+ {MODE_NOKICKS, 'Q', 0},
+ {MODE_BAN, 'b', 1},
+ {MODE_STRIP, 'S', 0}, /* works? */
+ {MODE_EXCEPT, 'e', 1}, /* exception ban */
+ {MODE_NOKNOCK, 'K', 0}, /* knock knock (no way!) */
+ {MODE_NOINVITE, 'V', 0}, /* no invites */
+ {MODE_FLOODLIMIT, 'f', 0}, /* flood limiter */
+ {MODE_NOHIDING, 'H', 0}, /* no +I joiners */
+ {0x0, 0x0, 0x0}
+};
+#endif
+
+
+#define BADOP_BOUNCE 1
+#define BADOP_USER 2
+#define BADOP_SERVER 3
+#define BADOP_OVERRIDE 4
+
+/* is some kind of admin */
+#define IsSkoAdmin(sptr) (IsAdmin(sptr) || IsNetAdmin(sptr) || IsTechAdmin(sptr) || IsSAdmin(sptr))
+
+char cmodestring[512];
+
+void make_cmodestr(void)
+{
+ char *p = &cmodestring[0];
+ aCtab *tab = &cFlagTab[0];
+
+ while (tab->mode != 0x0) {
+ *p = tab->flag;
+ p++;
+ tab++;
+ }
+ *p = '\0';
+}
+
+int Halfop_mode(long mode) {
+ aCtab *tab = &cFlagTab[0];
+
+ while (tab->mode != 0x0) {
+ if (tab->mode == mode)
+ return (tab->halfop == 1 ? TRUE : FALSE);
+ tab++;
+ }
+}
+
+/*
+ * return the length (>=0) of a chain of links.
+ */
+static int list_length(lp)
+Reg1 Link *lp;
+{
+ Reg2 int count = 0;
+
+ for (; lp; lp = lp->next)
+ count++;
+ return count;
+}
+
+/*
+** find_chasing
+** Find the client structure for a nick name (user) using history
+** mechanism if necessary. If the client is not found, an error
+** message (NO SUCH NICK) is generated. If the client was found
+** through the history, chasing will be 1 and otherwise 0.
+*/
+static aClient *find_chasing(sptr, user, chasing)
+aClient *sptr;
+char *user;
+Reg1 int *chasing;
+{
+ Reg2 aClient *who = find_client(user, (aClient *)NULL);
+
+ if (chasing)
+ *chasing = 0;
+ if (who)
+ return who;
+ if (!(who = get_history(user, (long)KILLCHASETIMELIMIT)))
+ {
+ sendto_one(sptr, err_str(ERR_NOSUCHNICK),
+ me.name, sptr->name, user);
+ return NULL;
+ }
+ if (chasing)
+ *chasing = 1;
+ return who;
+}
+/*
+ Exception functions to work with mode +e
+ -sts
+
+
+/* add_exbanid - add an id to be excepted to the channel bans (belongs to cptr) */
+
+static int add_exbanid(cptr, chptr, banid)
+aClient *cptr;
+aChannel *chptr;
+char *banid;
+{
+ Reg1 Ban *ban;
+ Reg2 int cnt = 0, len = 0;
+
+ if (MyClient(cptr))
+ (void)collapse(banid);
+ for (ban = chptr->exlist; ban; ban = ban->next)
+ {
+ len += strlen(ban->banstr);
+ if (MyClient(cptr))
+ if ((len > MAXBANLENGTH) || (++cnt >= MAXBANS))
+ {
+ sendto_one(cptr, err_str(ERR_BANLISTFULL),
+ me.name, cptr->name,
+ chptr->chname, banid);
+ return -1;
+ }
+ else
+ {
+ if (!match(ban->banstr, banid) ||
+ !match(banid, ban->banstr))
+ return -1;
+ }
+ else if (!mycmp(ban->banstr, banid))
+ return -1;
+
+ }
+ ban = make_ban();
+ bzero((char *)ban, sizeof(Ban));
+ /* ban->flags = CHFL_BAN; They're all bans!! */
+ ban->next = chptr->exlist;
+ ban->banstr = (char *)MyMalloc(strlen(banid)+1);
+ (void)strcpy(ban->banstr, banid);
+ ban->who = (char *)MyMalloc(strlen(cptr->name)+1);
+ (void)strcpy(ban->who, cptr->name);
+ ban->when = TStime();
+ chptr->exlist = ban;
+ return 0;
+}
+/*
+ * del_exbanid - delete an id belonging to cptr
+ */
+static int del_exbanid(chptr, banid)
+aChannel *chptr;
+char *banid;
+{
+ Reg1 Ban **ban;
+ Reg2 Ban *tmp;
+
+ if (!banid)
+ return -1;
+ for (ban = &(chptr->exlist); *ban; ban = &((*ban)->next))
+ if (mycmp(banid, (*ban)->banstr)==0)
+ {
+ tmp = *ban;
+ *ban = tmp->next;
+ MyFree(tmp->banstr);
+ MyFree(tmp->who);
+ free_ban(tmp);
+ return 0;
+ }
+ return -1;
+}
+
+/*
+ * find_banid - Find an exact match for a exban
+ */
+static int find_exbanid(chptr, banid)
+aChannel *chptr;
+char *banid;
+{
+ Reg1 Ban **ban;
+ Reg2 Ban *tmp;
+
+ if (!banid)
+ return -1;
+ for (ban = &(chptr->exlist); *ban; ban = &((*ban)->next))
+ if (!mycmp(banid, (*ban)->banstr)) return 1;
+ return 0;
+}
+
+
+/*
+ * Ban functions to work with mode +b
+ */
+/* add_banid - add an id to be banned to the channel (belongs to cptr) */
+
+static int add_banid(cptr, chptr, banid)
+aClient *cptr;
+aChannel *chptr;
+char *banid;
+{
+ Reg1 Ban *ban;
+ Reg2 int cnt = 0, len = 0;
+
+ if (MyClient(cptr))
+ (void)collapse(banid);
+ for (ban = chptr->banlist; ban; ban = ban->next)
+ {
+ len += strlen(ban->banstr);
+ if (MyClient(cptr))
+ if ((len > MAXBANLENGTH) || (++cnt >= MAXBANS))
+ {
+ sendto_one(cptr, err_str(ERR_BANLISTFULL),
+ me.name, cptr->name,
+ chptr->chname, banid);
+ return -1;
+ }
+ else
+ {
+ if (!match(ban->banstr, banid) ||
+ !match(banid, ban->banstr))
+ return -1;
+ }
+ else if (!mycmp(ban->banstr, banid))
+ return -1;
+
+ }
+ ban = make_ban();
+ bzero((char *)ban, sizeof(Ban));
+ /* ban->flags = CHFL_BAN; They're all bans!! */
+ ban->next = chptr->banlist;
+ ban->banstr = (char *)MyMalloc(strlen(banid)+1);
+ (void)strcpy(ban->banstr, banid);
+ ban->who = (char *)MyMalloc(strlen(cptr->name)+1);
+ (void)strcpy(ban->who, cptr->name);
+ ban->when = TStime();
+ chptr->banlist = ban;
+ return 0;
+}
+/*
+ * del_banid - delete an id belonging to cptr
+ */
+static int del_banid(chptr, banid)
+aChannel *chptr;
+char *banid;
+{
+ Reg1 Ban **ban;
+ Reg2 Ban *tmp;
+
+ if (!banid)
+ return -1;
+ for (ban = &(chptr->banlist); *ban; ban = &((*ban)->next))
+ if (mycmp(banid, (*ban)->banstr)==0)
+ {
+ tmp = *ban;
+ *ban = tmp->next;
+ MyFree(tmp->banstr);
+ MyFree(tmp->who);
+ free_ban(tmp);
+ return 0;
+ }
+ return -1;
+}
+
+/*
+ * find_banid - Find an exact match for a ban
+ */
+static int find_banid(chptr, banid)
+aChannel *chptr;
+char *banid;
+{
+ Reg1 Ban **ban;
+ Reg2 Ban *tmp;
+
+ if (!banid)
+ return -1;
+ for (ban = &(chptr->banlist); *ban; ban = &((*ban)->next))
+ if (!mycmp(banid, (*ban)->banstr)) return 1;
+ return 0;
+}
+
+/*
+ * IsMember - returns 1 if a person is joined and not a zombie
+ * Moved to struct.h
+ */
+
+/*
+ * is_banned - returns a pointer to the ban structure if banned else NULL
+ */
+extern Ban *is_banned(cptr, sptr, chptr)
+aClient *cptr, *sptr;
+aChannel *chptr;
+{
+ Reg1 Ban *tmp;
+ char *s, realhost[NICKLEN+USERLEN+HOSTLEN+6],
+ virthost[NICKLEN+USERLEN+HOSTLEN+6];
+
+ int dovirt = 0;
+
+ if (!IsPerson(cptr))
+ return NULL;
+
+ if (strcmp(cptr->user->realhost, cptr->user->virthost))
+ dovirt = 1;
+
+ s = make_nick_user_host(cptr->name, cptr->user->username,
+ cptr->user->realhost);
+ strcpy(realhost, s);
+
+ s = make_nick_user_host(cptr->name, cptr->user->username,
+ cptr->user->virthost);
+ strcpy(virthost, s);
+ /* -- exceptions are BEFORE testing bans */
+ for (tmp = chptr->exlist; tmp; tmp = tmp->next)
+ if ((match(tmp->banstr, realhost) == 0) ||
+ (dovirt && (match(tmp->banstr, virthost) == 0))
+ )
+ return (NULL); /* exception ! */
+
+ for (tmp = chptr->banlist; tmp; tmp = tmp->next)
+ if ((match(tmp->banstr, realhost) == 0) ||
+ (dovirt && (match(tmp->banstr, virthost) == 0))
+ )
+ break;
+ return (tmp);
+}
+
+/*
+ * adds a user to a channel by adding another link to the channels member
+ * chain.
+ */
+static void add_user_to_channel(chptr, who, flags)
+aChannel *chptr;
+aClient *who;
+int flags;
+{
+ Reg1 Link *ptr;
+
+ if (who->user)
+ {
+ ptr = make_link();
+ ptr->value.cptr = who;
+ ptr->flags = flags;
+ ptr->flood = (aFloodOpt *) MyMalloc(sizeof(aFloodOpt));
+ ptr->flood->nmsg = 0;
+ ptr->flood->lastmsg = 0;
+ ptr->next = chptr->members;
+ chptr->members = ptr;
+ chptr->users++;
+
+ ptr = make_link();
+ ptr->value.chptr = chptr;
+ ptr->next = who->user->channel;
+ who->user->channel = ptr;
+ who->user->joined++;
+ }
+}
+
+void remove_user_from_channel(sptr, chptr)
+aClient *sptr;
+aChannel *chptr;
+{
+ Reg1 Link **curr;
+ Reg2 Link *tmp;
+ Reg3 Link *lp = chptr->members;
+
+ for (; lp && (lp->value.cptr==sptr);
+ lp=lp->next);
+ for (;;)
+ {
+ for (curr = &chptr->members; (tmp = *curr); curr = &tmp->next)
+ if (tmp->value.cptr == sptr)
+ {
+ if (tmp->flood)
+ MyFree((aFloodOpt *) tmp->flood);
+ *curr = tmp->next;
+ free_link(tmp);
+ break;
+ }
+ for (curr = &sptr->user->channel; (tmp = *curr); curr = &tmp->next)
+ if (tmp->value.chptr == chptr)
+ {
+ *curr = tmp->next;
+ free_link(tmp);
+ break;
+ }
+ sptr->user->joined--;
+ if (lp) break;
+ if (chptr->members) sptr = chptr->members->value.cptr;
+ else break;
+ sub1_from_channel(chptr);
+ }
+ sub1_from_channel(chptr);
+}
+
+
+static int have_ops(chptr)
+aChannel *chptr;
+{
+ Reg1 Link *lp;
+
+ if (chptr)
+ {
+ lp=chptr->members;
+ while (lp)
+ {
+ if (lp->flags & CHFL_CHANOP) return(1);
+ lp = lp->next;
+ }
+ }
+ return 0;
+}
+
+int is_chan_op(cptr, chptr)
+aClient *cptr;
+aChannel *chptr;
+{
+ Reg1 Link *lp;
+/* chanop/halfop ? */
+ if (chptr)
+ if (lp = find_user_link(chptr->members, cptr))
+ return ((lp->flags & CHFL_CHANOP));
+
+ return 0;
+}
+
+
+/* This was the original function that allowed mode hacking - not
+ anymore. -- Barubary */
+static int is_deopped(cptr, chptr)
+aClient *cptr;
+aChannel *chptr;
+{
+ if (!IsPerson(cptr)) return 0;
+ return !is_chan_op(cptr, chptr);
+}
+
+
+int has_voice(cptr, chptr)
+aClient *cptr;
+aChannel *chptr;
+{
+ Reg1 Link *lp;
+
+ if (chptr)
+ if ((lp = find_user_link(chptr->members, cptr)))
+ return (lp->flags & CHFL_VOICE);
+
+ return 0;
+}
+int is_halfop(cptr, chptr)
+aClient *cptr;
+aChannel *chptr;
+{
+ Reg1 Link *lp;
+
+ if (chptr)
+ if (lp = find_user_link(chptr->members, cptr))
+ if (!is_chan_op(cptr, chptr)) /* excessive but needed */
+ return (lp->flags & CHFL_HALFOP);
+
+ return 0;
+}
+
+int is_chanowner(cptr, chptr)
+aClient *cptr;
+aChannel *chptr;
+{
+ Reg1 Link *lp;
+
+ if (chptr)
+ if (lp = find_user_link(chptr->members, cptr))
+ return (lp->flags & CHFL_CHANOWNER);
+
+ return 0;
+}
+
+int is_chanprot(cptr, chptr)
+aClient *cptr;
+aChannel *chptr;
+{
+ Reg1 Link *lp;
+
+ if (chptr)
+ if (lp = find_user_link(chptr->members, cptr))
+ return (lp->flags & CHFL_CHANPROT);
+
+ return 0;
+}
+
+#define CANNOT_SEND_MODERATED 1
+#define CANNOT_SEND_NOPRIVMSGS 2
+#define CANNOT_SEND_NOCOLOR 3
+#define CANNOT_SEND_BAN 4
+// #define CAN_SEND_STRIP 5
+
+int can_send(cptr, chptr, msgtext)
+aClient *cptr;
+aChannel *chptr;
+char *msgtext;
+{
+ Reg1 Link *lp;
+ Reg2 int member;
+
+ /* Moved check here, kinda faster.
+ * Note IsULine only uses the other parameter. -Donwulff */
+ if (IsULine(cptr,cptr)||IsServer(cptr)) return 0;
+
+ member = IsMember(cptr, chptr);
+ lp = find_user_link(chptr->members, cptr);
+
+ if (chptr->mode.mode & MODE_MODERATED &&
+ (!lp || !(lp->flags & (CHFL_CHANOP|CHFL_VOICE|CHFL_CHANOWNER|CHFL_HALFOP|CHFL_CHANPROT))))
+ return (CANNOT_SEND_MODERATED);
+
+ if (chptr->mode.mode & MODE_NOPRIVMSGS && !member)
+ /* Yet another bug by Potvin
+ return (CANNOT_SEND_MODERATED);
+ */
+ return (CANNOT_SEND_NOPRIVMSGS);
+
+ if (chptr->mode.mode & MODE_NOCOLOR)
+ if(strchr((char *) msgtext, 3) || strchr((char *) msgtext, 27))
+ return (CANNOT_SEND_NOCOLOR);
+/* Fixed strip bug --sts */
+/* if (chptr->mode.mode & MODE_STRIP) {
+ if ((strchr(msgtext, 3) != NULL) ||
+ (strchr(msgtext, 27) != NULL)) {
+ return (CAN_SEND_STRIP);
+ }
+ }
+*/
+if ((!lp || !(lp->flags & (CHFL_CHANOP|CHFL_VOICE|CHFL_CHANOWNER|CHFL_HALFOP|CHFL_CHANPROT))) && MyClient(cptr) &&
+ is_banned(cptr, cptr, chptr))
+ return (CANNOT_SEND_BAN);
+
+ return 0;
+}
+
+aChannel *find_channel(chname, chptr)
+Reg1 char *chname;
+Reg2 aChannel *chptr;
+{
+ return hash_find_channel(chname, chptr);
+}
+
+/*
+ * write the "simple" list of channel modes for channel chptr onto buffer mbuf
+ * with the parameters in pbuf.
+ */
+static void channel_modes(cptr, mbuf, pbuf, chptr)
+aClient *cptr;
+Reg1 char *mbuf, *pbuf;
+aChannel *chptr;
+{
+ int *ip, *ipx;
+ long zode;
+ aCtab *tab = &cFlagTab[0];
+ char bcbuf[1024];
+
+ *mbuf++ = '+';
+ while (tab->mode != 0x0) {
+ if ((chptr->mode.mode & tab->mode)) {
+ zode = chptr->mode.mode;
+ if (!(zode & (MODE_LIMIT|MODE_KEY|MODE_LINK)))
+ if (!(zode & (MODE_CHANOP|MODE_VOICE|MODE_CHANOWNER)))
+ if (!(zode & (MODE_BAN|MODE_EXCEPT|MODE_CHANPROT)))
+ if (!(zode & (MODE_HALFOP)))
+ *mbuf++ = tab->flag;
+ }
+ tab++;
+ }
+ if (chptr->mode.limit)
+ {
+ *mbuf++ = 'l';
+ if (IsMember(cptr, chptr) || IsServer(cptr) || IsULine(cptr,cptr))
+ (void)sprintf(pbuf, "%d ", chptr->mode.limit);
+ }
+ if (*chptr->mode.key)
+ {
+ *mbuf++ = 'k';
+ if (IsMember(cptr, chptr) || IsServer(cptr) || IsULine(cptr,cptr))
+ (void)strcat(pbuf, chptr->mode.key);
+ }
+ if (*chptr->mode.link)
+ {
+ *mbuf++ = 'L';
+ if (IsMember(cptr, chptr) || IsServer(cptr) || IsULine(cptr,cptr))
+ (void)strcat(pbuf, chptr->mode.link);
+ }
+ if (chptr->mode.per)
+ {
+ *mbuf++ = 'f';
+ if (IsMember(cptr, chptr) || IsServer(cptr) || IsULine(cptr,cptr))
+ {
+ if (chptr->mode.kmode == 1)
+ sprintf(bcbuf, "*%i:%i", chptr->mode.msgs, chptr->mode.per);
+ else
+ sprintf(bcbuf, "%i:%i", chptr->mode.msgs, chptr->mode.per);
+ (void)strcat(pbuf, bcbuf);
+ }
+
+ }
+ *mbuf++ = '\0';
+ return;
+}
+
+static int send_mode_list(cptr, chname, creationtime, top, mask, flag)
+aClient *cptr;
+Link *top;
+int mask;
+char flag, *chname;
+time_t creationtime;
+{
+ Reg1 Link *lp;
+ Reg2 char *cp, *name;
+ int count = 0, send = 0, sent = 0;
+
+ cp = modebuf + strlen(modebuf);
+ if (*parabuf) /* mode +l or +k xx */
+ count = 1;
+ for (lp = top; lp; lp = lp->next)
+ {
+ /*
+ * Okay, since ban's are stored in their own linked
+ * list, we won't even bother to check if CHFL_BAN
+ * is set in the flags. This should work as long
+ * as only ban-lists are feed in with CHFL_BAN mask.
+ * However, we still need to typecast... -Donwulff
+ */
+ if ((mask == CHFL_BAN) || (mask == CHFL_EXCEPT)) {
+/* if (!(((Ban *)lp)->flags & mask)) continue; */
+ name = ((Ban *)lp)->banstr;
+ } else {
+ if (!(lp->flags & mask)) continue;
+ name = lp->value.cptr->name;
+ }
+ if (strlen(parabuf) + strlen(name) + 11 < (size_t) MODEBUFLEN)
+ {
+ if(*parabuf) (void)strcat(parabuf, " ");
+ (void)strcat(parabuf, name);
+ count++;
+ *cp++ = flag;
+ *cp = '\0';
+ }
+ else if (*parabuf)
+ send = 1;
+ if (count == RESYNCMODES)
+ send = 1;
+ if (send)
+ {
+ /* cptr is always a server! So we send creationtimes */
+ sendmodeto_one(cptr, me.name, chname, modebuf,
+ parabuf, creationtime);
+ sent = 1;
+ send = 0;
+ *parabuf = '\0';
+ cp = modebuf;
+ *cp++ = '+';
+ if (count != RESYNCMODES)
+ {
+ (void)strcpy(parabuf, name);
+ *cp++ = flag;
+ }
+ count = 0;
+ *cp = '\0';
+ }
+ }
+ return sent;
+}
+
+/*
+ * send "cptr" a full list of the modes for channel chptr.
+ */
+void send_channel_modes(cptr, chptr)
+aClient *cptr;
+aChannel *chptr;
+{ int sent;
+/* fixed a bit .. to fit halfops --sts */
+ if (*chptr->chname != '#')
+ return;
+
+ *parabuf = '\0';
+ *modebuf = '\0';
+ channel_modes(cptr, modebuf, parabuf, chptr);
+ sent=send_mode_list(cptr, chptr->chname, chptr->creationtime,
+ chptr->members, CHFL_CHANOP, 'o');
+ if (!sent && chptr->creationtime)
+ sendto_one(cptr, ":%s %s %s %s %s %lu", me.name,
+ (IsToken(cptr)?TOK_MODE:MSG_MODE), chptr->chname, modebuf,
+ parabuf, chptr->creationtime);
+ else if (modebuf[1] || *parabuf)
+ sendmodeto_one(cptr, me.name,
+ chptr->chname, modebuf, parabuf, chptr->creationtime);
+
+ *parabuf = '\0';
+ *modebuf = '+';
+ modebuf[1] = '\0';
+
+ sent=send_mode_list(cptr, chptr->chname, chptr->creationtime,
+ chptr->members, CHFL_HALFOP, 'h');
+ if (!sent && chptr->creationtime)
+ sendto_one(cptr, ":%s %s %s %s %s %lu", me.name,
+ (IsToken(cptr)?TOK_MODE:MSG_MODE), chptr->chname, modebuf,
+ parabuf, chptr->creationtime);
+ else if (modebuf[1] || *parabuf)
+ sendmodeto_one(cptr, me.name,
+ chptr->chname, modebuf, parabuf, chptr->creationtime);
+
+ *parabuf = '\0';
+ *modebuf = '+';
+ modebuf[1] = '\0';
+ (void)send_mode_list(cptr, chptr->chname,chptr->creationtime,
+ chptr->banlist, CHFL_BAN, 'b');
+ if (modebuf[1] || *parabuf)
+ sendmodeto_one(cptr, me.name, chptr->chname, modebuf,
+ parabuf, chptr->creationtime);
+
+ *parabuf = '\0';
+ *modebuf = '+';
+ modebuf[1] = '\0';
+ (void)send_mode_list(cptr, chptr->chname,chptr->creationtime,
+ chptr->exlist, CHFL_EXCEPT, 'e');
+ if (modebuf[1] || *parabuf)
+ sendmodeto_one(cptr, me.name, chptr->chname, modebuf,
+ parabuf, chptr->creationtime);
+
+ *parabuf = '\0';
+ *modebuf = '+';
+ modebuf[1] = '\0';
+ (void)send_mode_list(cptr, chptr->chname,chptr->creationtime,
+ chptr->members, CHFL_VOICE, 'v');
+ if (modebuf[1] || *parabuf)
+ sendmodeto_one(cptr, me.name, chptr->chname, modebuf,
+ parabuf, chptr->creationtime);
+
+ *parabuf = '\0';
+ *modebuf = '+';
+ modebuf[1] = '\0';
+ (void)send_mode_list(cptr, chptr->chname,chptr->creationtime,
+ chptr->members, CHFL_CHANOWNER, 'q');
+ if (modebuf[1] || *parabuf)
+ sendmodeto_one(cptr, me.name, chptr->chname, modebuf,
+ parabuf, chptr->creationtime);
+
+ *parabuf = '\0';
+ *modebuf = '+';
+ modebuf[1] = '\0';
+ (void)send_mode_list(cptr, chptr->chname,chptr->creationtime,
+ chptr->members, CHFL_CHANPROT, 'a');
+ if (modebuf[1] || *parabuf)
+ sendmodeto_one(cptr, me.name, chptr->chname, modebuf,
+ parabuf, chptr->creationtime);
+
+
+
+
+}
+/*********/
+
+/*
+ * m_samode
+ * parv[0] = sender
+ * parv[1] = channel
+ * parv[2] = modes
+ * -taz
+ */
+int m_samode(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ static char tmp[MODEBUFLEN];
+ int badop, sendts;
+ aChannel *chptr;
+
+ if (check_registered(cptr))
+ return 0;
+
+ if (!IsPrivileged(cptr) || !IsSAdmin(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+
+ if (parc > 2)
+ {
+ chptr = find_channel(parv[1], NullChn);
+ if (chptr == NullChn)
+ return 0;
+ }
+ else
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "MODE");
+ return 0;
+ }
+ opermode = 0;
+ (void)do_mode(chptr, cptr, sptr, parc - 2, parv + 2, 0, 1);
+
+ return 0;
+
+}
+
+/*
+ * m_mode -- written by binary (garryb@binary.islesfan.net)
+ * Completely rewrote it. The old mode command was 820 lines of ICKY
+ * coding, which is a complete waste, because I wrote it in 570 lines of
+ * *decent* coding. This is also easier to read, change, and fine-tune. Plus,
+ * everything isn't scattered; everything's grouped where it should be.
+ *
+ * parv[0] - sender
+ * parv[1] - channel
+ */
+int m_mode(cptr, sptr, parc, parv)
+aClient *cptr;
+aClient *sptr;
+int parc;
+char *parv[];
+{
+ static char tmp[MODEBUFLEN];
+ static char mode_buf[MODEBUFLEN], parabuf[MODEBUFLEN];
+ char tmp1[1024];
+// int opermode = 0;
+
+ long unsigned timestamp, sendts;
+ Ban *ban; Link *l;
+ aChannel *chptr;
+
+ if (check_registered(sptr))
+ return 0;
+
+ /* Now, try to find the channel in question */
+ if (parc > 1)
+ {
+ chptr = find_channel(parv[1], NullChn);
+ if (chptr == NullChn)
+ return m_umode(cptr, sptr, parc, parv);
+ }
+ else
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "MODE");
+ return 0;
+ }
+
+ sptr->flags&=~FLAGS_TS8;
+
+ if (MyConnect(sptr))
+ clean_channelname(parv[1]);
+ if (check_channelmask(sptr, cptr, parv[1]))
+ return 0;
+
+ if (parc < 3)
+ {
+ *mode_buf = *parabuf = '\0';
+ mode_buf[1] = '\0';
+ channel_modes(sptr, mode_buf, parabuf, chptr);
+ sendto_one(sptr, rpl_str(RPL_CHANNELMODEIS), me.name, parv[0],
+ chptr->chname, mode_buf, parabuf);
+ sendto_one(sptr, rpl_str(RPL_CREATIONTIME), me.name, parv[0],
+ chptr->chname, chptr->creationtime);
+ return 0;
+ }
+
+ if (IsPerson(sptr) && parc<4 && ((*parv[2]=='b' && parv[2][1]=='\0')
+ || (parv[2][1]=='b' && parv[2][2] == '\0' && (*parv[2] == '+'
+ || *parv[2] == '-'))))
+ {
+ if (!IsMember(sptr, chptr))
+ return 0;
+ /* send ban list */
+ for (ban=chptr->banlist; ban; ban=ban->next)
+ sendto_one(sptr, rpl_str(RPL_BANLIST), me.name,
+ sptr->name, chptr->chname, ban->banstr,
+ ban->who, ban->when);
+ sendto_one(cptr,
+ rpl_str(RPL_ENDOFBANLIST), me.name, sptr->name,
+ chptr->chname);
+ return 0;
+ }
+
+ if (IsPerson(sptr) && parc<4 && ((*parv[2]=='e' && parv[2][1]=='\0')
+ || (parv[2][1]=='e' && parv[2][2] == '\0' && (*parv[2] == '+'
+ || *parv[2] == '-'))))
+ {
+ if (!IsMember(sptr, chptr))
+ return 0;
+ /* send exban list */
+ for (ban=chptr->exlist; ban; ban=ban->next)
+ sendto_one(sptr, rpl_str(RPL_EXLIST), me.name,
+ sptr->name, chptr->chname, ban->banstr,
+ ban->who, ban->when);
+ sendto_one(cptr,
+ rpl_str(RPL_ENDOFEXLIST), me.name, sptr->name,
+ chptr->chname);
+ return 0;
+ }
+ if (IsPerson(sptr) && parc<4 && ((*parv[2]=='I' && parv[2][1]=='\0')
+ || (parv[2][1]=='I' && parv[2][2] == '\0' && (*parv[2] == '+'
+ || *parv[2] == '-'))))
+ {
+ if (!IsMember(sptr, chptr))
+ return 0;
+ sendto_one(sptr, rpl_str(RPL_ENDOFINVITELIST), me.name, sptr->name, chptr->chname);
+ return 0;
+ }
+ opermode = 0;
+ /* opermode stuff --sts */
+ if (IsPerson(sptr) && !IsULine(cptr, sptr) && !is_chan_op(sptr, chptr))
+ if (IsOper(sptr)) {
+ sendts = 0;
+ opermode = 1;
+ goto aftercheck;
+ }
+/*-------*/
+
+
+ if (is_half_op(sptr, chptr)) {
+ opermode = 2;
+ goto aftercheck;
+ }
+ if (IsPerson(sptr) && !IsULine(cptr, sptr) && !is_chan_op(sptr, chptr)
+ && !is_half_op(sptr, chptr)
+ && (cptr == sptr || !IsSAdmin(sptr) || !IsOper(sptr)))
+ {
+ if (cptr == sptr)
+ {
+ sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED),
+ me.name, parv[0], chptr->chname);
+ return 0;
+ }
+ sendto_one(cptr, ":%s MODE %s -oh %s %s 0",
+ me.name, chptr->chname, parv[0], parv[0]);
+ /* Tell the other server that the user is
+ * de-opped. Fix op desyncs. */
+ bounce_mode(chptr, cptr, parc - 2, parv + 2);
+ return 0;
+ }
+
+ if (IsServer(sptr) && (sendts = atoi(parv[parc-1]))
+ && !IsULine(cptr,sptr) && chptr->creationtime
+ && sendts > chptr->creationtime)
+ {
+ if (!(*parv[2] == '&')) /* & denotes a bounce */
+ {
+ /* !!! */
+ sendto_umode(UMODE_EYES, "*** TS bounce for %s - %lu(ours) %lu(theirs)",
+ chptr->chname, chptr->creationtime, sendts);
+ bounce_mode(chptr, cptr, parc - 2, parv + 2);
+ return 0;
+ }
+ /* other server will resync soon enough... */
+ }
+ if (IsServer(sptr) && !sendts && *parv[parc - 1] != '0')
+ sendts = -1;
+ if (IsServer(sptr) && sendts != -1)
+ parc--; /* server supplied a time stamp, remove it now */
+
+aftercheck:
+/* if (IsPerson(sptr) && IsOper(sptr)) {
+ if (!is_chan_op(sptr, chptr)) {
+ if (MyClient(sptr) && !IsULine(cptr, cptr))
+ sendto_umode(UMODE_EYES, "*** OperMode [IRCop: %s] - [Channel: %s] - [Mode: %s %s]",
+ sptr->name, chptr->chname, mode_buf, parabuf);
+ sendts = 0;
+ }
+ }
+*/
+ /* Filter out the unprivileged FIRST. *
+ * Now, we can actually do the mode. */
+
+ (void)do_mode(chptr, cptr, sptr, parc - 2, parv + 2, sendts, 0);
+
+ return 0;
+}
+
+/* bounce_mode -- written by binary
+ * User or server is NOT authorized to change the mode. This takes care
+ * of making the bounce string and bounce it. Because of the 1 for the bounce
+ * param (last param) of the calls to set_mode and make_mode_str, it will not
+ * set the mode, but create the bounce string.
+ */
+void bounce_mode(chptr, cptr, parc, parv)
+aChannel *chptr;
+aClient *cptr;
+int parc;
+char *parv[];
+{
+ char pvar[MAXMODEPARAMS][MODEBUFLEN+3];
+ int pcount;
+ long oldm, oldl;
+ char mode_buf[MODEBUFLEN], parabuf[MODEBUFLEN];
+
+ oldm = chptr->mode.mode;
+ oldl = chptr->mode.limit;
+ set_mode(chptr, cptr, parc, parv, &pcount, pvar, 1);
+ make_mode_str(chptr, oldm, oldl, pcount, pvar, mode_buf,
+ parabuf, 1);
+
+ sendto_one(cptr, ":%s MODE %s &%s %s %lu", me.name, chptr->chname,
+ mode_buf, parabuf, chptr->creationtime);
+ /* the '&' denotes a bounce so servers won't bounce a bounce */
+}
+
+/* do_mode -- written by binary
+ * User or server is authorized to do the mode. This takes care of
+ * setting the mode and relaying it to other users and servers.
+ */
+void do_mode(chptr, cptr, sptr, parc, parv, sendts, samode)
+aChannel *chptr;
+aClient *cptr, *sptr;
+int parc, sendts, samode;
+char *parv[];
+{
+ char pvar[MAXMODEPARAMS][MODEBUFLEN+3];
+ int pcount;
+ long oldm, oldl;
+ char tschange = 0, isbounce = 0; /* fwd'ing bounce */
+ char mode_buf[MODEBUFLEN], parabuf[MODEBUFLEN];
+
+ if (**parv == '&')
+ isbounce = 1;
+ oldm = chptr->mode.mode;
+ oldl = chptr->mode.limit;
+
+ set_mode(chptr, sptr, parc, parv, &pcount, pvar, 0);
+ make_mode_str(chptr, oldm, oldl, pcount, pvar, mode_buf,
+ parabuf, 0);
+
+ if (IsServer(sptr))
+ {
+ if (sendts > 0)
+ {
+ if (!chptr->creationtime || sendts < chptr->creationtime)
+ {
+ tschange = 1;
+ if (chptr->creationtime != 0)
+ sendto_umode(UMODE_EYES, "*** TS fix for %s - %lu(ours) %lu(theirs)",
+ chptr->chname, chptr->creationtime, sendts);
+ chptr->creationtime = sendts;
+ /* new chan or our timestamp is wrong */
+ /* now works for double-bounce prevention */
+
+ }
+ if (sendts > chptr->creationtime && chptr->creationtime)
+ {
+ /* theirs is wrong but we let it pass anyway */
+ sendts = chptr->creationtime;
+ sendto_one(cptr, ":%s MODE %s + %lu", me.name,
+ chptr->chname, chptr->creationtime);
+ }
+ }
+ if (sendts == -1 && chptr->creationtime)
+ sendts = chptr->creationtime;
+ }
+ if (*mode_buf == '\0' || (*(mode_buf+1) == '\0' && (*mode_buf == '+' ||
+ *mode_buf == '-')))
+ {
+ if (tschange || isbounce) /* relay bounce time changes */
+ sendto_serv_butone(cptr, ":%s MODE %s %s+ %lu", me.name,
+ chptr->chname, isbounce ? "&" : "",
+ chptr->creationtime);
+ return; /* nothing to send */
+ }
+ /* opermode for twimodesystem --sts*/
+ if (opermode == 1) {
+ if (MyClient(sptr))
+ sendto_umode(UMODE_EYES, "*** OperMode [IRCop: %s] - [Channel: %s] - [Mode: %s %s]",
+ sptr->name, chptr->chname, mode_buf, parabuf);
+ sendts = 0;
+ }
+
+ if (IsPerson(sptr) && samode && MyClient(sptr))
+ {
+ sendto_serv_butone(NULL,
+ ":%s GLOBOPS :%s used SAMODE %s (%s %s)",
+ me.name, sptr->name, chptr->chname, mode_buf, parabuf);
+ sendto_failops_whoare_opers(
+ "from %s: %s used SAMODE %s (%s %s)",
+ me.name, sptr->name, chptr->chname, mode_buf, parabuf);
+ sptr = &me;
+ sendts = 0;
+ }
+ sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s %s",
+ sptr->name, chptr->chname, mode_buf, parabuf);
+ if (IsServer(sptr) && sendts != -1)
+ sendto_serv_butone(cptr, ":%s MODE %s %s%s %s %lu",
+ sptr->name, chptr->chname, isbounce ? "&" : "",
+ mode_buf, parabuf, sendts);
+ else
+ sendto_serv_butone(cptr, ":%s MODE %s %s%s %s NoTS",
+ sptr->name, chptr->chname, isbounce ? "&" : "",
+ mode_buf, parabuf);
+ /* tell them it's not a timestamp, in case the last param
+ ** is a number. */
+}
+/* make_mode_str -- written by binary
+ * Reconstructs the mode string, to make it look clean. mode_buf will
+ * contain the +x-y stuff, and the parabuf will contain the parameters.
+ * If bounce is set to 1, it will make the string it needs for a bounce.
+ */
+void make_mode_str(chptr, oldm, oldl, pcount, pvar, mode_buf, parabuf, bounce)
+aChannel *chptr;
+int pcount;
+long oldm, oldl;
+char pvar[MAXMODEPARAMS][MODEBUFLEN+3], *mode_buf, *parabuf, bounce;
+{
+
+ char *x = mode_buf, tmpbuf[MODEBUFLEN], *tmpstr, foo;
+ // int *ip;
+ aCtab *tab = &cFlagTab[0];
+ int what, cnt, z;
+
+ what = 0;
+
+ *tmpbuf = '\0';
+ *mode_buf = '\0';
+ *parabuf = '\0';
+ what = 0;
+ /* + param-less modes */
+ tab = &cFlagTab[0];
+ while (tab->mode != 0x0) {
+ if (chptr->mode.mode & tab->mode) {
+ if (!(oldm & tab->mode)) {
+ if (what != MODE_ADD)
+ {
+ *x++ = bounce ? '-' : '+';
+ what = MODE_ADD;
+ }
+ *x++ = tab->flag;
+ }
+ }
+ tab++;
+ }
+
+ *x = '\0';
+/* + param-less modes */
+ tab = &cFlagTab[0];
+ while (tab->mode != 0x0) {
+ if (!(chptr->mode.mode & tab->mode)) {
+ if (oldm & tab->mode) {
+ if (what != MODE_DEL)
+ {
+ *x++ = bounce ? '+' : '-';
+ what = MODE_DEL;
+ }
+ *x++ = tab->flag;
+ }
+ }
+ tab++;
+ }
+
+ *x = '\0';
+ /* reconstruct bkov chain */
+ for (cnt = 0; cnt < pcount; cnt++)
+ {
+ if ((*(pvar[cnt]) == '+') && what != MODE_ADD)
+ {
+ *x++ = bounce ? '-' : '+';
+ what = MODE_ADD;
+ }
+ if ((*(pvar[cnt]) == '-') && what != MODE_DEL)
+ {
+ *x++ = bounce ? '+' : '-';
+ what = MODE_DEL;
+ }
+ *x++ = *(pvar[cnt] + 1);
+ tmpstr = &pvar[cnt][2];
+ strncat(parabuf, tmpstr, MODEBUFLEN - 1);
+ parabuf[MODEBUFLEN-1] = '\0';
+ z = strlen(parabuf);
+ parabuf[z] = ' '; /* add a space */
+ parabuf[z+1] = '\0';
+ }
+ /* user limit */
+ if (chptr->mode.limit != oldl)
+ {
+ if ((!bounce && chptr->mode.limit == 0) ||
+ (bounce && chptr->mode.limit != 0))
+ {
+ if (what != MODE_DEL)
+ {
+ *x++ = '-';
+ what = MODE_DEL;
+ }
+ if (bounce)
+ chptr->mode.limit = 0; /* set it back */
+ *x++ = 'l';
+ }
+ else
+ {
+ if (what != MODE_ADD)
+ {
+ *x++ = '+';
+ what = MODE_ADD;
+ }
+ *x++ = 'l';
+ if (bounce)
+ chptr->mode.limit = oldl; /* set it back */
+ sprintf(parabuf, "%s%d", parabuf, chptr->mode.limit);
+ }
+ }
+ if (bounce)
+ chptr->mode.mode = oldm;
+ z = strlen(parabuf);
+ if (parabuf[z-1] == ' ')
+ parabuf[z-1] = '\0';
+ *x = '\0';
+ if (*mode_buf == '\0')
+ {
+ *mode_buf = '+';
+ mode_buf++;
+ *mode_buf = '\0';
+ /* Don't send empty lines. */
+ }
+ return;
+}
+
+
+/* do_mode_char
+ * processes one mode character
+ * returns 1 if it ate up a param, otherwise 0
+ * written by binary
+ * modified for Unreal by stskeeps..
+ */
+
+int do_mode_char(chptr, modetype, modechar, param, what, cptr, pcount, pvar,
+ bounce)
+char *param, modechar, pvar[MAXMODEPARAMS][MODEBUFLEN+3], bounce;
+u_int what;
+long modetype;
+u_int *pcount;
+aClient *cptr;
+aChannel *chptr;
+
+{
+ aCtab *tab = &cFlagTab[0];
+
+
+ int retval = 0;
+ Link *member;
+ aClient *who;
+ unsigned int tmp = 0;
+ char tmpbuf[512], *tmpstr;
+ char tc; /* */
+ int chasing, x;
+ int xxi, xyi, xzi;
+ char *xxx;
+ char *xp;
+
+ chasing = 0;
+ if (opermode == 2 && !is_chan_op(cptr, chptr)) {
+ /* Ugly halfop hack --sts
+ - this allows halfops to do +b +e +v and so on */
+ if (Halfop_mode(modetype) == FALSE) {
+ while (tab->mode != 0x0) {
+ if (tab->mode == modetype) {
+ sendto_one(cptr, err_str(ERR_NOTFORHALFOPS),
+ me.name,
+ cptr->name,
+ tab->flag);
+ }
+ tab++;
+ }
+ return(0);
+ }
+ }
+ switch(modetype)
+ {
+ case MODE_OPERONLY:
+ if (!IsAnOper(cptr) && !IsServer(cptr) && !IsULine(cptr,cptr)) {
+ sendto_one(cptr, ":%s NOTICE %s :*** Only IRCops can set that mode", me.name, cptr->name);
+ break;
+ }
+ goto setthephuckingmode;
+ case MODE_ADMONLY:
+ if (!IsSkoAdmin(cptr) && !IsServer(cptr) && !IsULine(cptr,cptr)) {
+ sendto_one(cptr, ":%s NOTICE %s :*** Only admins can set that mode", me.name, cptr->name);
+ break;
+ }
+ goto setthephuckingmode;
+ case MODE_RGSTR:
+ if (!IsServer(cptr) && !IsULine(cptr,cptr))
+ break;
+ goto setthephuckingmode;
+ case MODE_NOHIDING:
+ if (!IsSkoAdmin(cptr) && !IsServer(cptr) && !IsULine(cptr,cptr))
+ {
+ sendto_one(cptr, ":%s NOTICE %s :*** Only admins can set that mode", me.name, cptr->name);
+ break;
+ }
+ goto setthephuckingmode;
+ case MODE_SECRET:
+ case MODE_PRIVATE:
+ case MODE_MODERATED:
+ case MODE_TOPICLIMIT:
+ case MODE_NOPRIVMSGS:
+ case MODE_INVITEONLY:
+ case MODE_RGSTRONLY:
+ case MODE_NOCOLOR:
+ case MODE_NOKICKS:
+ case MODE_STRIP:
+ case MODE_NOKNOCK:
+ case MODE_NOINVITE:
+setthephuckingmode:
+ /* +sp bugfix.. */
+ if (modetype == MODE_SECRET && (chptr->mode.mode & MODE_PRIVATE))
+ chptr->mode.mode &= ~MODE_PRIVATE;
+ if (modetype == MODE_PRIVATE && (chptr->mode.mode & MODE_SECRET))
+ chptr->mode.mode &= ~MODE_SECRET;
+ if (modetype == MODE_NOCOLOR && (chptr->mode.mode & MODE_STRIP))
+ chptr->mode.mode &= ~MODE_STRIP;
+ if (modetype == MODE_STRIP && (chptr->mode.mode & MODE_NOCOLOR))
+ chptr->mode.mode &= ~MODE_NOCOLOR;
+ retval = 0;
+ if (what == MODE_ADD)
+ chptr->mode.mode |= modetype;
+ else
+ chptr->mode.mode &= ~modetype;
+ break;
+
+/* do pro-opping here (popping) */
+ case MODE_CHANOWNER:
+ if (!IsULine(cptr,cptr) && !IsServer(cptr) && !IsNetAdmin(cptr) &&
+ !IsCoAdmin(cptr) && !IsTechAdmin(cptr) && !is_chanowner(cptr, chptr)) {
+ sendto_one(cptr, err_str(ERR_ONLYSERVERSCANCHANGE),
+ me.name, cptr->name, chptr->chname);
+ break;
+ }
+ case MODE_CHANPROT:
+ if (!IsULine(cptr,cptr) && !IsServer(cptr) && !IsNetAdmin(cptr) &&
+ !IsCoAdmin(cptr) && !IsTechAdmin(cptr) && !is_chanowner(cptr, chptr)) {
+ sendto_one(cptr, ":%s NOTICE %s :*** Protected users can only be set by the channel owner.",
+ me.name, cptr->name);
+ break;
+ }
+
+ case MODE_HALFOP:
+ case MODE_CHANOP:
+ case MODE_VOICE:
+ switch (modetype)
+ {
+ case MODE_CHANOWNER: xxx = "deown"; break;
+ case MODE_CHANPROT: xxx = "deprot"; break;
+ case MODE_HALFOP: xxx = "dehalfop"; break;
+ case MODE_CHANOP: xxx = "deop"; break;
+ case MODE_VOICE: xxx ="devoice"; break;
+ default: xxx = "whatthefuckisthatmode?";
+ }
+ if (!param || *pcount >= MAXMODEPARAMS)
+ {
+ retval = 0;
+ break;
+ }
+ retval = 1;
+ if (!(who = find_chasing(cptr, param, &chasing)))
+ break;
+ if (!(member = find_user_link(chptr->members, who)))
+ {
+ sendto_one(cptr, err_str(ERR_USERNOTINCHANNEL),
+ me.name, cptr->name,
+ who->name, chptr->chname);
+ break;
+ }
+ /* we make the rules, we bend the rules */
+ if (IsServer(cptr) || IsULine(cptr, cptr))
+ goto breaktherules;
+
+ if (is_chanowner(member->value.cptr, chptr) && member->value.cptr != cptr && !is_chanowner(cptr, chptr) && !IsServer(cptr) && !IsULine(cptr,cptr) && (what == MODE_DEL)) {
+ if (MyClient(cptr)) {
+ sendto_one(cptr, ":%s NOTICE %s :*** You cannot %s because %s is %s channel owner (+q)",
+ me.name, cptr->name, xxx, member->value.cptr->name, chptr->chname);
+ }
+ break;
+ }
+ if (is_chanprot(member->value.cptr, chptr) && member->value.cptr != cptr && !is_chanowner(cptr, chptr) && !IsServer(cptr) && modetype != MODE_CHANOWNER && (what==MODE_DEL)) {
+ if (MyClient(cptr)) {
+ sendto_one(cptr, ":%s NOTICE %s :*** You cannot %s because %s is %s protected user (+a)",
+ me.name, cptr->name, xxx, member->value.cptr->name, chptr->chname);
+ }
+ break;
+ }
+breaktherules:
+ tmp = member->flags;
+ if (what == MODE_ADD)
+ member->flags |= modetype;
+ else
+ member->flags &= ~modetype;
+ if (tmp == member->flags &&
+ (bounce || !IsULine(cptr,cptr)))
+ break;
+ /* It's easier to undo the mode here instead of later
+ * when you call make_mode_str for a bounce string.
+ * Why set it if it will be instantly removed?
+ * Besides, pvar keeps a log of it. */
+ if (bounce)
+ member->flags = tmp;
+ if (modetype == MODE_CHANOWNER)
+ tc = 'q';
+ if (modetype == MODE_CHANPROT)
+ tc = 'a';
+ if (modetype == MODE_CHANOP)
+ tc = 'o';
+ if (modetype == MODE_HALFOP)
+ tc = 'h';
+ if (modetype == MODE_VOICE)
+ tc = 'v';
+
+ (void)sprintf(pvar[*pcount], "%c%c%s",
+ what == MODE_ADD ? '+' : '-',
+ tc,
+ who->name);
+
+ (*pcount)++;
+ break;
+ case MODE_LIMIT:
+ if (what == MODE_ADD)
+ {
+ if (!param)
+ {
+ retval = 0;
+ break;
+ }
+ retval = 1;
+ tmp = atoi(param);
+ if (chptr->mode.limit == tmp)
+ break;
+ chptr->mode.limit = tmp;
+ }
+ else
+ {
+ retval = 0;
+ if (!chptr->mode.limit)
+ break;
+ chptr->mode.limit = 0;
+ }
+ break;
+ case MODE_KEY:
+ if (!param || *pcount >= MAXMODEPARAMS)
+ {
+ retval = 0;
+ break;
+ }
+ retval = 1;
+ for (x = 0; x < *pcount; x++)
+ {
+ if (pvar[x][1] == 'k')
+ { /* don't allow user to change key
+ * more than once per command. */
+ retval = 0;
+ break;
+ }
+ }
+ if (retval == 0) /* you can't break a case from loop */
+ break;
+ if (what == MODE_ADD)
+ {
+ if (!bounce) /* don't do the mode at all. */
+ strncpyzt(chptr->mode.key, param,
+ sizeof(chptr->mode.key));
+ tmpstr = param;
+ }
+ else
+ {
+ if (!*chptr->mode.key)
+ break; /* no change */
+ strncpyzt(tmpbuf, chptr->mode.key,
+ sizeof(tmpbuf));
+ tmpstr = tmpbuf;
+ if (!bounce)
+ strcpy(chptr->mode.key, "");
+ }
+ retval = 1;
+
+ (void)sprintf(pvar[*pcount], "%ck%s",
+ what == MODE_ADD ? '+' : '-', tmpstr);
+ (*pcount)++;
+ break;
+
+ case MODE_BAN:
+ if (!param || *pcount >= MAXMODEPARAMS)
+ {
+ retval = 0;
+ break;
+ }
+ retval = 1;
+ tmpstr = pretty_mask(param);
+ /* For bounce, we don't really need to worry whether
+ * or not it exists on our server. We'll just always
+ * bounce it. */
+ if (!bounce &&
+ ((what==MODE_ADD && add_banid(cptr, chptr, tmpstr))
+ || (what == MODE_DEL && del_banid(chptr, tmpstr))))
+ break; /* already exists */
+ (void)sprintf(pvar[*pcount], "%cb%s",
+ what == MODE_ADD ? '+' : '-', tmpstr);
+ (*pcount)++;
+ break;
+ case MODE_EXCEPT:
+ if (!param || *pcount >= MAXMODEPARAMS)
+ {
+ retval = 0;
+ break;
+ }
+ retval = 1;
+ tmpstr = pretty_mask(param);
+ /* For bounce, we don't really need to worry whether
+ * or not it exists on our server. We'll just always
+ * bounce it. */
+ if (!bounce &&
+ ((what==MODE_ADD && add_exbanid(cptr, chptr, tmpstr))
+ || (what == MODE_DEL && del_exbanid(chptr, tmpstr))))
+ break; /* already exists */
+ (void)sprintf(pvar[*pcount], "%ce%s",
+ what == MODE_ADD ? '+' : '-', tmpstr);
+ (*pcount)++;
+ break;
+ case MODE_LINK:
+ if (IsULine(cptr, cptr) || IsServer(cptr)) {
+ goto linkok;
+ }
+#ifndef OPSLINK
+ if (!IsNetAdmin(cptr) && !IsCoAdmin(cptr) && !IsTechAdmin(cptr) && !is_chanowner(cptr,chptr))
+ {
+ sendto_one(cptr, ":%s NOTICE %s :*** Channel mode +L can only be set by the channel owner", me.name, cptr->name);
+ break;
+ }
+#endif
+ linkok:
+ if (!chptr->mode.limit && what == MODE_ADD) {
+ sendto_one(cptr, ":%s NOTICE %s :*** Channel mode +l <max> is requried for +L to be set", me.name, cptr->name);
+ break;
+ }
+ retval = 1;
+ for (x = 0; x < *pcount; x++)
+ {
+ if (pvar[x][1] == 'L')
+ { /* don't allow user to change link
+ * more than once per command. */
+ retval = 0;
+ break;
+ }
+ }
+ if (retval == 0) /* you can't break a case from loop */
+ break;
+ if (what == MODE_ADD)
+ {
+ if (!param || *pcount >= MAXMODEPARAMS)
+ {
+ retval = 0;
+ break;
+ }
+
+ if (!bounce) /* don't do the mode at all. */
+ strncpyzt(chptr->mode.link, param,
+ sizeof(chptr->mode.link));
+ tmpstr = param;
+ }
+ else
+ {
+ if (!*chptr->mode.link)
+ break; /* no change */
+ strncpyzt(tmpbuf, chptr->mode.link,
+ sizeof(tmpbuf));
+ tmpstr = tmpbuf;
+ if (!bounce)
+ strcpy(chptr->mode.link, "");
+ }
+ retval = 1;
+
+ (void)sprintf(pvar[*pcount], "%cL%s",
+ what == MODE_ADD ? '+' : '-', tmpstr);
+ (*pcount)++;
+ break;
+ case MODE_FLOODLIMIT:
+ retval = 1;
+ for (x = 0; x < *pcount; x++)
+ {
+ if (pvar[x][1] == 'f')
+ { /* don't allow user to change flood
+ * more than once per command. */
+ retval = 0;
+ break;
+ }
+ }
+ if (retval == 0) /* you can't break a case from loop */
+ break;
+ if (what == MODE_ADD)
+ {
+ if (!bounce) /* don't do the mode at all. */
+ {
+ if (!param || *pcount >= MAXMODEPARAMS)
+ {
+ retval = 0;
+ break;
+ }
+
+ /* like 1:1 and if its less than 3 chars then ahem.. */
+ if (strlen(param) < 3)
+ {
+ break;
+ }
+ /* may not contain other chars
+ than 0123456789: & NULL */
+ for (xp = param; *xp; xp++)
+ {
+ /* fast alpha check */
+ if ( (*xp < '0')
+ && (*xp > '9')
+ && (*xp != '\0')
+ && (*xp != ':')
+ && (*xp == '*' && xp != param))
+
+ break;
+ }
+ /* haven't got a : .. oh well */
+ if (!strchr(param, ':'))
+ {
+ break;
+ }
+ /* got multiple :'s .. omg */
+ if (strchr(param, ':') != strrchr(param, ':'))
+ {
+ break;
+ }
+ if (*param == '*' )
+ {
+ xzi = 1;
+ chptr->mode.kmode = 1;
+ }
+ else
+ {
+ xzi = 0;
+
+ chptr->mode.kmode = 0;
+ }
+ xp = index(param, ':');
+ *xp = '\0';
+ xxi = atoi((*param == '*' ? (param + 1) : param));
+ xp++;
+ xyi = atoi(xp);
+ xp--;
+ *xp = ':';
+ if ((xxi == 0) || (xyi == 0))
+ break;
+ if ((chptr->mode.msgs == xxi) && (chptr->mode.per == xyi) && (chptr->mode.kmode == xzi))
+ break; chptr->mode.msgs = xxi;
+ chptr->mode.per = xyi;
+ }
+ tmpstr = param;
+ retval = 1;
+ }
+ else
+ {
+ if (!chptr->mode.msgs || !chptr->mode.per)
+ break; /* no change */
+ sprintf(tmpbuf, (chptr->mode.kmode > 0 ? "*%i:%i" : "%i:%i"), chptr->mode.msgs, chptr->mode.per);
+ tmpstr = tmpbuf;
+ if (!bounce)
+ {
+ chptr->mode.msgs = chptr->mode.per = chptr->mode.kmode = 0;
+ }
+ retval = 0;
+ }
+
+ (void)sprintf(pvar[*pcount], "%cf%s",
+ what == MODE_ADD ? '+' : '-', tmpstr);
+ (*pcount)++;
+ break;
+#ifdef _WIN32
+ default: ;
+#else
+ default:
+#endif
+ }
+ return(retval);
+}
+
+/*
+ * ListBits(bitvalue, bitlength);
+ * written by Stskeeps
+*/
+char *ListBits(long bits, long length) {
+ char *bitstr, *p;
+ long l,x,y;
+ y = 1;
+ bitstr = (char *) MyMalloc(length + 1);
+ p = bitstr;
+ for (l = 1; l <= length; l++) {
+ if (bits & y)
+ *p = '1';
+ else
+ *p = '0';
+ p++;
+ y = y + y;
+ }
+ *p = '\0';
+ return (bitstr);
+}
+
+
+/* set_mode
+ * written by binary
+ */
+void set_mode(chptr, cptr, parc, parv, pcount, pvar, bounce)
+aChannel *chptr;
+aClient *cptr;
+int parc;
+u_int *pcount;
+char bounce;
+char *parv[], pvar[MAXMODEPARAMS][MODEBUFLEN+3];
+// long opermode;
+{
+ Reg1 char *curchr;
+ u_int what = MODE_ADD;
+ long modetype;
+ int paracount;
+ char *tmpo;
+ int *ip, xid;
+ aCtab *tab = &cFlagTab[0];
+ aCtab foundat;
+ int found = 0;
+ paracount = 1;
+ *pcount = 0;
+ for (curchr = parv[0]; *curchr; curchr++)
+ {
+ switch(*curchr)
+ {
+ case '+':
+ what = MODE_ADD;
+ break;
+ case '-':
+ what = MODE_DEL;
+ break;
+ case '^':
+ tmpo = (char *) ListBits(chptr->mode.mode, 64);
+ sendto_one(cptr, ":%s NOTICE %s :*** %s mode is %li (0x%lx) [%s]",
+ me.name,
+ cptr->name,
+ chptr->chname,
+ chptr->mode.mode,
+ chptr->mode.mode,
+ tmpo);
+ MyFree(tmpo);
+ break;
+
+ case 'x':
+ if (MyClient(cptr))
+ {
+ sendto_one(cptr, ":%s NOTICE %s :*** Mode not set - Please do not use mode +x as this is now named +c instead (Colorblock)",
+ me.name,
+ cptr->name);
+ break;
+ }
+ else
+ {
+ /* compatiblity */
+ *curchr = 'c';
+ }
+ goto jumpdammit;
+ case 'I':
+ if (MyClient(cptr))
+ {
+ break;
+ }
+ else
+ {
+ /* compatiblity */
+ *curchr = 'V';
+ }
+jumpdammit:
+ default:
+ found = 0;
+ tab = &cFlagTab[0]; while ((tab->mode != 0x0) && found == 0) {
+ if (tab->flag == *curchr) {
+ found = 1;
+ foundat = *tab;
+ }
+ tab++;
+ }
+ if (found == 1)
+ modetype = foundat.mode;
+ if (found == 0)
+ modetype = 0;
+
+ if (modetype == 0)
+ {
+ if (!MyClient(cptr))
+ break;
+ /* don't flood other servers */
+ sendto_one(cptr,
+ err_str(ERR_UNKNOWNMODE),
+ me.name, cptr->name, *curchr);
+ break;
+ }
+ if (parv[paracount] &&
+ strlen(parv[paracount]) >=
+ MODEBUFLEN)
+ parv[paracount][MODEBUFLEN-1] = '\0';
+ paracount += do_mode_char(chptr, modetype,
+ *curchr, parv[paracount], what, cptr,
+ pcount, pvar, bounce);
+ break;
+ }
+ }
+}
+
+int DoesOp(modebuf)
+char *modebuf;
+{
+ modebuf--; /* Is it possible that a mode starts with o and not +o ? */
+ while (*++modebuf) if (*modebuf == 'h' || *modebuf=='o' || *modebuf=='v' || *modebuf=='q') return(1);
+ return 0;
+}
+
+int sendmodeto_one(cptr, from, name, mode, param, creationtime)
+Reg2 aClient *cptr;
+char *from,*name,*mode,*param;
+time_t creationtime;
+{
+ if ((IsServer(cptr) && DoesOp(mode) && creationtime) ||
+ IsULine(cptr,cptr))
+ sendto_one(cptr,":%s %s %s %s %s %lu", from,
+ (IsToken(cptr)?TOK_MODE:MSG_MODE), name, mode, param,
+ creationtime);
+ else
+ sendto_one(cptr,":%s %s %s %s %s", from,
+ (IsToken(cptr)?TOK_MODE:MSG_MODE), name, mode, param);
+}
+
+char *pretty_mask(mask)
+char *mask;
+{ Reg1 char *cp;
+ Reg2 char *user;
+ Reg3 char *host;
+
+ if ((user = index((cp = mask), '!'))) *user++ = '\0';
+ if ((host = rindex(user ? user : cp, '@')))
+ { *host++ = '\0';
+ if (!user) return make_nick_user_host(NULL, cp, host); }
+ else if (!user && index(cp, '.')) return make_nick_user_host(NULL, NULL, cp);
+ return make_nick_user_host(cp, user, host);
+}
+/* Now let _invited_ people join thru bans, +i and +l.
+ * Checking if an invite exist could be done only if a block exists,
+ * but I'm not too fancy of the complicated structure that'd cause,
+ * when optimization will hopefully take care of it. Most of the time
+ * a user won't have invites on him anyway. -Donwulff
+ */
+
+static int can_join(cptr, sptr, chptr, key, link, parv)
+aClient *cptr, *sptr;
+Reg2 aChannel *chptr;
+char *key, *link;
+char *parv[];
+{
+ Reg1 Link *lp;
+ int ib = 1;
+
+ /* 0 = noone 1 = IRCops 2 = Net Admins 3 =Net/Tech admins (override) */
+
+ if ((chptr->mode.limit && chptr->users >= chptr->mode.limit)) {
+ if (chptr->mode.link) {
+ if (*chptr->mode.link != '\0') {
+ /* We are linked. */
+ sendto_one(sptr, err_str(ERR_LINKCHANNEL), me.name, sptr->name,
+ chptr->chname, chptr->mode.link);
+ parv[0] = sptr->name;
+ parv[1] = (chptr->mode.link);
+ channel_link(cptr, sptr, 2, parv);
+ return -1;
+ }
+ }
+ return (ERR_CHANNELISFULL);
+ }
+
+/* if ((chptr->mode.mode & MODE_OPERONLY) && IsOper(sptr)) {
+ goto admok;
+ } */
+ if ((chptr->mode.mode & MODE_OPERONLY) && !IsOper(sptr)) {
+ return (ERR_OPERONLY);
+ }
+ if ((chptr->mode.mode & MODE_ADMONLY)) {
+ if (!IsSkoAdmin(sptr))
+ return (ERR_ADMONLY);
+ }
+
+ if ((chptr->mode.mode & MODE_NOHIDING) && IsHiding(sptr))
+ return (ERR_NOHIDING);
+
+ if ((IsOper(sptr) && !(chptr->mode.mode & MODE_ADMONLY))) {
+ return 0; /* may override */
+ }
+ if ((IsOper(sptr) && is_banned(cptr, sptr, chptr) && (chptr->mode.mode & MODE_OPERONLY)))
+ return (ERR_BANNEDFROMCHAN); /* banned as an ircop at a +O cannot join */
+
+/* if (ib == 1)
+ if (IsOper(sptr))
+ return 0;
+ else
+ if (ib == 2)
+ if (IsNetAdmin(sptr))
+ return 0;
+*/
+ switch(ib) {
+ case 1: if (IsOper(sptr))
+ {
+ return 0;
+ }
+ break;
+ case 2: if (IsNetAdmin(sptr))
+ {
+ return 0;
+ }
+ break;
+ case 3: if (IsNetAdmin(sptr) || IsTechAdmin(sptr)) return 0;
+ break;
+ default: break;
+ }
+ if ((chptr->mode.mode & MODE_RGSTRONLY) && !IsARegNick(sptr))
+ return (ERR_NEEDREGGEDNICK);
+
+ if (*chptr->mode.key && (BadPtr(key) || mycmp(chptr->mode.key, key)))
+ return (ERR_BADCHANNELKEY);
+
+ for (lp = sptr->user->invited; lp; lp = lp->next)
+ if (lp->value.chptr == chptr)
+ break;
+
+ if ((chptr->mode.mode & MODE_INVITEONLY) && !lp)
+ return (ERR_INVITEONLYCHAN);
+
+ if ((chptr->mode.limit && chptr->users >= chptr->mode.limit))
+ return (ERR_CHANNELISFULL);
+
+ if (is_banned(sptr, sptr, chptr) && !lp)
+ return (ERR_BANNEDFROMCHAN);
+
+
+
+ return 0;
+}
+
+
+/*
+** Remove bells and commas from channel name
+*/
+
+void clean_channelname(cn)
+char *cn;
+{
+ Reg1 u_char *ch = (u_char *)cn;
+
+
+ for (; *ch; ch++)
+ /* Don't allow any control chars, the space, the comma,
+ * or the "non-breaking space" in channel names.
+ * Might later be changed to a system where the list of
+ * allowed/non-allowed chars for channels was a define
+ * or some such.
+ * --Wizzu
+ */
+ if (*ch < 33 || *ch == ',' || *ch == 160)
+ {
+ *ch = '\0';
+ return;
+ }
+}
+
+/*
+** Return -1 if mask is present and doesnt match our server name.
+*/
+static int check_channelmask(sptr, cptr, chname)
+aClient *sptr, *cptr;
+char *chname;
+{
+ Reg1 char *s;
+
+ if (*chname == '&' && IsServer(cptr))
+ return -1;
+ s = rindex(chname, ':');
+ if (!s)
+ return 0;
+
+ s++;
+ if (match(s, me.name) || (IsServer(cptr) && match(s, cptr->name)))
+ {
+ if (MyClient(sptr))
+ sendto_one(sptr, err_str(ERR_BADCHANMASK),
+ me.name, sptr->name, chname);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+** Get Channel block for i (and allocate a new channel
+** block, if it didn't exists before).
+*/
+static aChannel *get_channel(cptr, chname, flag)
+aClient *cptr;
+char *chname;
+int flag;
+ {
+ Reg1 aChannel *chptr;
+ int len;
+
+ if (BadPtr(chname))
+ return NULL;
+
+ len = strlen(chname);
+ if (MyClient(cptr) && len > CHANNELLEN)
+ {
+ len = CHANNELLEN;
+ *(chname+CHANNELLEN) = '\0';
+ }
+ if ((chptr = find_channel(chname, (aChannel *)NULL)))
+ return (chptr);
+ if (flag == CREATE)
+ {
+ chptr = (aChannel *)MyMalloc(sizeof(aChannel) + len);
+ bzero((char *)chptr, sizeof(aChannel));
+ strncpyzt(chptr->chname, chname, len+1);
+ if (channel)
+ channel->prevch = chptr;
+ chptr->prevch = NULL;
+ chptr->nextch = channel;
+ chptr->creationtime = MyClient(cptr)?TStime():(time_t)0;
+ channel = chptr;
+ (void)add_to_channel_hash_table(chname, chptr);
+ }
+ return chptr;
+ }
+
+/*
+ * Slight changes in routine, now working somewhat symmetrical:
+ * First try to remove the client & channel pair to avoid duplicates
+ * Second check client & channel invite-list lengths and remove tail
+ * Finally add new invite-links to both client and channel
+ * Should U-lined clients have higher limits? -Donwulff
+ */
+
+static void add_invite(cptr, chptr)
+aClient *cptr;
+aChannel *chptr;
+{
+ Reg1 Link *inv, *tmp;
+
+ del_invite(cptr, chptr);
+ /*
+ * delete last link in chain if the list is max length
+ */
+ if (list_length(cptr->user->invited) >= MAXCHANNELSPERUSER)
+ {
+/* This forgets the channel side of invitation -Vesa
+ inv = cptr->user->invited;
+ cptr->user->invited = inv->next;
+ free_link(inv);
+*/
+ for (tmp = cptr->user->invited; tmp->next; tmp = tmp->next)
+ ;
+ del_invite(cptr, tmp->value.chptr);
+
+ }
+ /* We get pissy over too many invites per channel as well now,
+ * since otherwise mass-inviters could take up some major
+ * resources -Donwulff
+ */
+ if (list_length(chptr->invites) >= MAXCHANNELSPERUSER) {
+ for (tmp = chptr->invites; tmp->next; tmp = tmp->next)
+ ;
+ del_invite(tmp->value.cptr, chptr);
+ }
+ /*
+ * add client to the beginning of the channel invite list
+ */
+ inv = make_link();
+ inv->value.cptr = cptr;
+ inv->next = chptr->invites;
+ chptr->invites = inv;
+ /*
+ * add channel to the beginning of the client invite list
+ */
+ inv = make_link();
+ inv->value.chptr = chptr;
+ inv->next = cptr->user->invited;
+ cptr->user->invited = inv;
+}
+
+/*
+ * Delete Invite block from channel invite list and client invite list
+ */
+void del_invite(cptr, chptr)
+aClient *cptr;
+aChannel *chptr;
+{
+ Reg1 Link **inv, *tmp;
+
+ for (inv = &(chptr->invites); (tmp = *inv); inv = &tmp->next)
+ if (tmp->value.cptr == cptr)
+ {
+ *inv = tmp->next;
+ free_link(tmp);
+ break;
+ }
+
+ for (inv = &(cptr->user->invited); (tmp = *inv); inv = &tmp->next)
+ if (tmp->value.chptr == chptr)
+ {
+ *inv = tmp->next;
+ free_link(tmp);
+ break;
+ }
+}
+
+/*
+** Subtract one user from channel i (and free channel
+** block, if channel became empty).
+*/
+static void sub1_from_channel(chptr)
+Reg1 aChannel *chptr;
+{
+ Ban *ban;
+ Link *lp;
+
+ if (--chptr->users <= 0)
+ {
+ /*
+ * Now, find all invite links from channel structure
+ */
+ while ((lp = chptr->invites))
+ del_invite(lp->value.cptr, chptr);
+
+ while (chptr->banlist)
+ {
+ ban = chptr->banlist;
+ chptr->banlist = ban->next;
+ MyFree(ban->banstr);
+ MyFree(ban->who);
+ free_ban(ban);
+ }
+ while (chptr->exlist)
+ {
+ ban = chptr->exlist;
+ chptr->exlist = ban->next;
+ MyFree(ban->banstr);
+ MyFree(ban->who);
+ free_ban(ban);
+ }
+ if (chptr->prevch)
+ chptr->prevch->nextch = chptr->nextch;
+ else
+ channel = chptr->nextch;
+ if (chptr->nextch)
+ chptr->nextch->prevch = chptr->prevch;
+ (void)del_from_channel_hash_table(chptr->chname, chptr);
+ MyFree((char *)chptr);
+ }
+}
+
+
+/*
+ * Channel Link
+ */
+int channel_link(cptr, sptr, parc, parv)
+Reg2 aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ static char jbuf[BUFSIZE], *tmp;
+ Reg1 Link *lp;
+ Reg3 aChannel *chptr;
+ Reg4 char *name, *key = NULL, *link = NULL;
+ int i,i1, flags = 0, zombie = 0;
+ char *p = NULL, *p2 = NULL;
+
+ if (check_registered_user(sptr))
+ return 0;
+
+
+ if (parc < 2 || *parv[1] == '\0')
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "JOIN");
+ return 0;
+ }
+
+ *jbuf = '\0';
+ /*
+ ** Rebuild list of channels joined to be the actual result of the
+ ** JOIN. Note that "JOIN 0" is the destructive problem.
+ */
+ bouncedtimes++;
+ if (bouncedtimes > MAXBOUNCE) {
+ /* bounced too many times */
+ sendto_one(sptr, ":%s NOTICE %s :*** Couldn't join %s ! - Link setting was too bouncy",
+ me.name,
+ sptr->name,
+ parv[1]);
+ return;
+ }
+ for (i = 0, name = strtoken(&p, parv[1], ","); name;
+ name = strtoken(&p, NULL, ","))
+ {
+ /* pathological case only on longest channel name.
+ ** If not dealt with here, causes desynced channel ops
+ ** since ChannelExists() doesn't see the same channel
+ ** as one being joined. cute bug. Oct 11 1997, Dianora/comstud
+ ** Copied from Dianora's "hybrid 5" ircd.
+ */
+
+ if(strlen(name) > CHANNELLEN) /* same thing is done in get_channel() */
+ name[CHANNELLEN] = '\0';
+
+ if (MyConnect(sptr))
+ clean_channelname(name);
+ if (check_channelmask(sptr, cptr, name)==-1)
+ continue;
+ if (*name == '&' && !MyConnect(sptr))
+ continue;
+ if (*name == '0' && !atoi(name))
+ {
+ (void)strcpy(jbuf, "0");
+ i = 1;
+ continue;
+ }
+ else if (!IsChannelName(name))
+ {
+ if (MyClient(sptr))
+ sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL),
+ me.name, parv[0], name);
+ continue;
+ }
+ if (*jbuf)
+ (void)strcat(jbuf, ",");
+ (void)strncat(jbuf, name, sizeof(jbuf) - i - 1);
+ i += strlen(name)+1;
+ }
+ (void)strcpy(parv[1], jbuf);
+
+ p = NULL;
+ if (parv[2])
+ if (parv[2])
+ key = strtoken(&p2, parv[2], ",");
+ parv[2] = NULL; /* for m_names call later, parv[parc] must == NULL */
+ for (name = strtoken(&p, jbuf, ","); name;
+ key = (key) ? strtoken(&p2, NULL, ",") : NULL,
+ name = strtoken(&p, NULL, ","))
+ {
+ /*
+ ** JOIN 0 sends out a part for all channels a user
+ ** has joined.
+ */
+ if (*name == '0' && !atoi(name))
+ {
+ while ((lp = sptr->user->channel))
+ {
+ chptr = lp->value.chptr;
+ sendto_channel_butserv(chptr, sptr, PartFmt,
+ parv[0], chptr->chname);
+ remove_user_from_channel(sptr, chptr);
+ }
+ sendto_serv_butone(cptr, ":%s JOIN 0", parv[0]);
+ continue;
+ }
+
+ if (MyConnect(sptr))
+ {
+ /*
+ ** local client is first to enter previously nonexistant
+ ** channel so make them (rightfully) the Channel
+ ** Operator.
+ */
+ if (!IsModelessChannel(name))
+ flags = (ChannelExists(name)) ? CHFL_DEOPPED :
+ CHFL_CHANOP;
+ else
+ flags = CHFL_DEOPPED;
+
+ if (sptr->user->joined >= MAXCHANNELSPERUSER)
+ {
+ sendto_one(sptr, err_str(ERR_TOOMANYCHANNELS),
+ me.name, parv[0], name);
+ return 0;
+ }
+ }
+
+ chptr = get_channel(sptr, name, CREATE);
+
+ if (chptr && (lp=find_user_link(chptr->members, sptr)))
+ continue;
+
+ if (!MyConnect(sptr)) flags = CHFL_DEOPPED;
+ if (sptr->flags & FLAGS_TS8) flags|=CHFL_SERVOPOK;
+
+ i1 = 0;
+ if (chptr == NULL)
+ return;
+
+ if (!chptr ||
+ (MyConnect(sptr) && (i = can_join(cptr, sptr, chptr, key, link, parv))))
+ {
+ if ( i != -1 )
+ { sendto_one(sptr, err_str(i),
+ me.name, parv[0], name);
+ }
+ continue;
+ }
+
+ /*
+ ** Complete user entry to the new channel (if any)
+ */
+ add_user_to_channel(chptr, sptr, flags);
+ /*
+ ** notify all other users on the new channel
+ */
+ if (!IsHiding(sptr))
+ sendto_channel_butserv(chptr, sptr, ":%s JOIN :%s",
+ parv[0], name);
+ else {
+ if (MyClient(sptr))
+ sendto_one(sptr, ":%s!%s@%s JOIN :%s", sptr->name, sptr->user->username,
+ (IsHidden(sptr) ? sptr->user->virthost : sptr->user->realhost),
+ name);
+ sendto_umode(UMODE_NETADMIN|UMODE_TECHADMIN, "*** Invisible(+I) user %s joined %s", sptr->name, chptr->chname);
+ }
+ sendto_match_servs(chptr, cptr, ":%s JOIN :%s", parv[0], name);
+
+ if (MyClient(sptr))
+ {
+ /*
+ ** Make a (temporal) creationtime, if someone joins
+ ** during a net.reconnect : between remote join and
+ ** the mode with TS. --Run
+ */
+ if (chptr->creationtime == 0)
+ { chptr->creationtime = TStime();
+ sendto_match_servs(chptr, cptr, ":%s MODE %s + %lu",
+ me.name, name, chptr->creationtime);
+ }
+ del_invite(sptr, chptr);
+ if (flags & CHFL_CHANOP)
+ sendto_match_servs(chptr, cptr,
+ ":%s MODE %s +o %s %lu",
+ me.name, name, parv[0], chptr->creationtime);
+ if (chptr->topic[0] != '\0') {
+ sendto_one(sptr, rpl_str(RPL_TOPIC), me.name,
+ parv[0], name, chptr->topic);
+ sendto_one(sptr, rpl_str(RPL_TOPICWHOTIME),
+ me.name, parv[0], name,
+ chptr->topic_nick,
+ chptr->topic_time);
+ }
+ parv[1] = name;
+ (void)m_names(cptr, sptr, 2, parv);
+ bouncedtimes = 0;
+ }
+
+ }
+ return 0;
+}
+
+/*
+** m_join
+** parv[0] = sender prefix
+** parv[1] = channel
+** parv[2] = channel password (key)
+*/
+int m_join(cptr, sptr, parc, parv)
+Reg2 aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ static char jbuf[BUFSIZE], *tmp;
+ Reg1 Link *lp;
+ Reg3 aChannel *chptr;
+ Reg4 char *name, *key = NULL, *link = NULL;
+ int i, flags = 0, zombie = 0;
+ char *p = NULL, *p2 = NULL;
+
+ if (check_registered_user(sptr))
+ return 0;
+
+ bouncedtimes = 0;
+
+ if (parc < 2 || *parv[1] == '\0')
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "JOIN");
+ return 0;
+ }
+
+ *jbuf = '\0';
+ /*
+ ** Rebuild list of channels joined to be the actual result of the
+ ** JOIN. Note that "JOIN 0" is the destructive problem.
+ */
+ for (i = 0, name = strtoken(&p, parv[1], ","); name;
+ name = strtoken(&p, NULL, ","))
+ {
+ /* pathological case only on longest channel name.
+ ** If not dealt with here, causes desynced channel ops
+ ** since ChannelExists() doesn't see the same channel
+ ** as one being joined. cute bug. Oct 11 1997, Dianora/comstud
+ ** Copied from Dianora's "hybrid 5" ircd.
+ */
+
+ if(strlen(name) > CHANNELLEN) /* same thing is done in get_channel() */
+ name[CHANNELLEN] = '\0';
+
+ if (MyConnect(sptr))
+ clean_channelname(name);
+ if (check_channelmask(sptr, cptr, name)==-1)
+ continue;
+ if (*name == '&' && !MyConnect(sptr))
+ continue;
+ if (*name == '0' && !atoi(name))
+ {
+ (void)strcpy(jbuf, "0");
+ i = 1;
+ continue;
+ }
+ else if (!IsChannelName(name))
+ {
+ if (MyClient(sptr))
+ sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL),
+ me.name, parv[0], name);
+ continue;
+ }
+ if (*jbuf)
+ (void)strcat(jbuf, ",");
+ (void)strncat(jbuf, name, sizeof(jbuf) - i - 1);
+ i += strlen(name)+1;
+ }
+ (void)strcpy(parv[1], jbuf);
+
+ p = NULL;
+ if (parv[2])
+ key = strtoken(&p2, parv[2], ",");
+ parv[2] = NULL; /* for m_names call later, parv[parc] must == NULL */
+ for (name = strtoken(&p, jbuf, ","); name;
+ key = (key) ? strtoken(&p2, NULL, ",") : NULL,
+ name = strtoken(&p, NULL, ","))
+ {
+ /*
+ ** JOIN 0 sends out a part for all channels a user
+ ** has joined.
+ */
+ if (*name == '0' && !atoi(name))
+ {
+ while ((lp = sptr->user->channel))
+ {
+ chptr = lp->value.chptr;
+ sendto_channel_butserv(chptr, sptr, PartFmt2,
+ parv[0], chptr->chname, "Left all channels");
+ remove_user_from_channel(sptr, chptr);
+ }
+ sendto_serv_butone(cptr, ":%s JOIN 0", parv[0]);
+ continue;
+ }
+
+ if (MyConnect(sptr))
+ {
+ /*
+ ** local client is first to enter previously nonexistant
+ ** channel so make them (rightfully) the Channel
+ ** Operator.
+ */
+ if (!IsModelessChannel(name))
+ flags = (ChannelExists(name)) ? CHFL_DEOPPED :
+ CHFL_CHANOWNER;
+ else
+ flags &= ~CHFL_CHANOWNER;
+
+ if (!IsModelessChannel(name))
+ flags = (ChannelExists(name)) ? CHFL_DEOPPED :
+ CHFL_CHANOP;
+ else
+ flags = CHFL_DEOPPED;
+
+ if (!(sptr->umodes & UMODE_AGENT)) /* Agents can join as many channels as needed */
+ if (sptr->user->joined >= MAXCHANNELSPERUSER)
+ {
+ sendto_one(sptr, err_str(ERR_TOOMANYCHANNELS),
+ me.name, parv[0], name);
+ return 0;
+ }
+/* RESTRICTCHAN */
+ if (crlines)
+ {
+ if (channel_canjoin(sptr, name) != 1)
+ {
+ if (cannotjoin_msg)
+ sendto_one(sptr, ":%s NOTICE %s :%s", me.name, sptr->name, cannotjoin_msg);
+ return 0;
+ }
+ }
+ }
+
+ chptr = get_channel(sptr, name, CREATE);
+ if (chptr && (lp=find_user_link(chptr->members, sptr)))
+ continue;
+
+ if (!MyConnect(sptr)) flags = CHFL_DEOPPED;
+ if (sptr->flags & FLAGS_TS8) flags|=CHFL_SERVOPOK;
+
+ if (!chptr ||
+ (MyConnect(sptr) && (i = can_join(cptr, sptr, chptr, key, link, parv))))
+ {
+
+ if (i != -1)
+ sendto_one(sptr, err_str(i),
+ me.name, parv[0], name);
+
+ /* uhm? was *chptr ??? *NULL = dangerous */
+ continue;
+
+ }
+ if (is_banned(cptr, sptr, chptr) && IsOper(sptr))
+ {
+ sendto_umode(UMODE_EYES, "*** Banwalk [IRCop: %s] [Channel: %s]", sptr->name, chptr->chname);
+ }
+ /*
+ ** Complete user entry to the new channel (if any)
+ */
+ add_user_to_channel(chptr, sptr, flags);
+ /*
+ ** notify all other users on the new channel
+ */
+ if (!(IsHiding(sptr)))
+ sendto_channel_butserv(chptr, sptr, ":%s JOIN :%s",
+ parv[0], chptr->chname);
+ else {
+ if (MyClient(sptr))
+ sendto_one(sptr, ":%s!%s@%s JOIN :%s", sptr->name, sptr->user->username,
+ (IsHidden(sptr) ? sptr->user->virthost : sptr->user->realhost),
+ chptr->chname);
+ if (MyClient(sptr)) {
+ sendto_umode(UMODE_ADMIN, "*** [+I] %s invisible joined %s", sptr->name, chptr->chname);
+ sendto_serv_butone(&me, ":%s SMO A :[+I] %s invisible joined %s", me.name, sptr->name, chptr->chname);
+ }
+ }
+ sendto_match_servs(chptr, cptr, ":%s JOIN :%s", parv[0], chptr->chname);
+
+ if (MyClient(sptr))
+ {
+ /*
+ ** Make a (temporal) creationtime, if someone joins
+ ** during a net.reconnect : between remote join and
+ ** the mode with TS. --Run
+ */
+ if (chptr->creationtime == 0)
+ { chptr->creationtime = TStime();
+ sendto_match_servs(chptr, cptr, ":%s MODE %s + %lu",
+ me.name, chptr->chname, chptr->creationtime);
+ }
+ del_invite(sptr, chptr);
+ if (flags & CHFL_CHANOP)
+ sendto_match_servs(chptr, cptr,
+ ":%s MODE %s +o %s %lu",
+ me.name, chptr->chname, parv[0], chptr->creationtime);
+ if (chptr->topic[0] != '\0') {
+ sendto_one(sptr, rpl_str(RPL_TOPIC), me.name,
+ parv[0], name, chptr->topic);
+ sendto_one(sptr, rpl_str(RPL_TOPICWHOTIME),
+ me.name, parv[0], name,
+ chptr->topic_nick,
+ chptr->topic_time);
+ }
+ parv[1] = chptr->chname;
+ (void)m_names(cptr, sptr, 2, parv);
+ }
+
+ }
+
+ bouncedtimes = 0;
+ return 0;
+}
+
+/*
+** m_part
+** parv[0] = sender prefix
+** parv[1] = channel
+** parv[2] = comment (added by Lefler)
+*/
+int m_part(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ int xx = 0;
+ Reg1 aChannel *chptr;
+ Reg2 Link *lp;
+ char *p = NULL, *name;
+ register char *comment = (parc > 2 && parv[2]) ? parv[2] : NULL;
+
+ if (check_registered_user(sptr))
+ return 0;
+
+ sptr->flags&=~FLAGS_TS8;
+
+ if (parc < 2 || parv[1][0] == '\0')
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "PART");
+ return 0;
+ }
+
+#ifdef V28PlusOnly
+ *buf = '\0';
+#endif
+
+ for (; (name = strtoken(&p, parv[1], ",")); parv[1] = NULL)
+ {
+ chptr = get_channel(sptr, name, 0);
+ if (!chptr)
+ {
+ sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL),
+ me.name, parv[0], name);
+ continue;
+ }
+ if (check_channelmask(sptr, cptr, name))
+ continue;
+ if (!(lp=find_user_link(chptr->members, sptr)))
+ {
+ /* Normal to get get when our client did a kick
+ ** for a remote client (who sends back a PART),
+ ** so check for remote client or not --Run
+ */
+ if (MyClient(sptr))
+ sendto_one(sptr, err_str(ERR_NOTONCHANNEL),
+ me.name, parv[0], name);
+ continue;
+ }
+ /*
+ ** Remove user from the old channel (if any)
+ */
+#ifdef V28PlusOnly
+ if (*buf)
+ (void)strcat(buf, ",");
+ (void)strcat(buf, name);
+#else
+ if (parc < 3)
+ sendto_match_servs(chptr, cptr, PartFmt, parv[0], name);
+ else
+ sendto_match_servs(chptr, cptr, PartFmt2, parv[0], name, comment);
+#endif
+ if (1)
+ {
+ if (!IsHiding(sptr))
+ {
+ if (parc < 3)
+ {
+ sendto_channel_butserv(chptr, sptr, PartFmt, parv[0], name);
+ }
+ else
+ {
+ sendto_channel_butserv(chptr, sptr, PartFmt2, parv[0], name, comment);
+ }
+ }
+ else
+ {
+ if (MyClient(sptr))
+ {
+ sendto_umode(UMODE_ADMIN, "*** [+I] %s invisible parted %s", sptr->name, chptr->chname);
+ sendto_serv_butone(&me, ":%s SMO A :[+I] %s invisible parted %s", me.name, sptr->name, chptr->chname);
+ }
+ if (MyClient(sptr))
+ /* awful hack .. */
+ if (parc < 3)
+ sendto_one(sptr, ":%s!%s@%s PART %s", sptr->name, sptr->user->username,
+ (IsHidden(sptr) ? sptr->user->virthost : sptr->user->realhost),
+ name);
+ else
+ sendto_one(sptr, ":%s!%s@%s PART %s :%s", sptr->name, sptr->user->username,
+ (IsHidden(sptr) ? sptr->user->virthost : sptr->user->realhost),
+ name, comment);
+ }
+ remove_user_from_channel(sptr, chptr);
+ }
+ }
+#ifdef V28PlusOnly
+ sendto_serv_butone(cptr, PartFmt, parv[0], buf);
+#endif
+ return 0;
+ }
+
+/*
+** m_kick
+** parv[0] = sender prefix
+** parv[1] = channel
+** parv[2] = client to kick
+** parv[3] = kick comment
+*/
+int m_kick(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ aClient *who;
+ aChannel *chptr;
+ int chasing = 0;
+ char *comment, *name, *p = NULL, *user, *p2 = NULL;
+ Link *lp,*lp2;
+
+ if (check_registered(sptr))
+ return 0;
+
+ sptr->flags&=~FLAGS_TS8;
+
+ if (parc < 3 || *parv[1] == '\0')
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "KICK");
+ return 0;
+ }
+
+ comment = (BadPtr(parv[3])) ? parv[0] : parv[3];
+ if (strlen(comment) > (size_t) TOPICLEN)
+ comment[TOPICLEN] = '\0';
+
+ *nickbuf = *buf = '\0';
+
+ for (; (name = strtoken(&p, parv[1], ",")); parv[1] = NULL)
+ {
+ chptr = get_channel(sptr, name, !CREATE);
+ if (!chptr)
+ {
+ sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL),
+ me.name, parv[0], name);
+ continue;
+ }
+ if (check_channelmask(sptr, cptr, name))
+ continue;
+ if (!IsServer(cptr) && !IsOper(sptr) && !IsULine(cptr,sptr) && !is_chan_op(sptr, chptr) && !is_halfop(sptr,chptr))
+ {
+ sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED),
+ me.name, parv[0], chptr->chname);
+ continue;
+ }
+
+ lp2=find_user_link(chptr->members, sptr);
+ for (; (user = strtoken(&p2, parv[2], ",")); parv[2] = NULL)
+ {
+ if (!(who = find_chasing(sptr, user, &chasing)))
+ continue; /* No such user left! */
+ if ((lp=find_user_link(chptr->members, who)))
+ {
+ if (IsULine(cptr,sptr))
+ goto attack;
+ /* Hiding patch by }{ */
+ if (IsHiding(who)) {
+ sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], user, name);
+ sendto_one(who, ":%s NOTICE %s :*** Hidden: %s tried to kick you from channel %s (%s)", me.name, who->name, parv[0], chptr->chname, comment);
+ break;
+ }
+
+ if ((chptr->mode.mode & MODE_NOKICKS)
+ && !IsULine(cptr, sptr))
+ {
+ sendto_one(sptr, ":%s NOTICE %s :*** You cannot kick people on %s",
+ me.name, sptr->name,
+ chptr->chname);
+ goto deny;
+ continue;
+ }
+
+ if (IsOper(sptr))
+ if (!is_chan_op(sptr, chptr)) {
+ sendto_umode(UMODE_EYES, "*** OperKick [%s @ %s -> %s (%s)]", sptr->name, chptr->chname, who->name, comment);
+ goto attack;
+ } /* is_chan_op */
+ if (is_chanprot(who, chptr) || is_chanowner(who, chptr) || IsServices(who))
+ if (!IsULine(cptr, sptr) && who != sptr)
+ {
+ sendto_one(sptr, ":%s NOTICE %s :*** You cannot kick %s from %s because %s is channel protected",
+ me.name, sptr->name, who->name, chptr->chname, who->name);
+ goto deny;
+ continue;
+ } /* chanprot/chanowner */
+ if (is_chan_op(who,chptr) && is_halfop(sptr, chptr) && !is_chan_op(sptr, chptr) && !IsULine(cptr, sptr)) {
+ sendto_one(sptr, ":%s NOTICE %s :*** You cannot kick channel operators on %s if you only are halfop", me.name, sptr->name, chptr->chname);
+ goto deny;
+ } /* halfop */
+
+ if (IsKix(who) && !IsULine(cptr, sptr))
+ {
+ if (!(IsNetAdmin(sptr) || IsTechAdmin(sptr)))
+ {
+ sendto_one(sptr, ":%s NOTICE %s :*** Cannot kick %s from channel %s (usermode +q)", me.name, sptr->name, who->name, chptr->chname);
+ sendto_one(who, ":%s NOTICE %s :*** Q: %s tried to kick you from channel %s (%s)", me.name, who->name, parv[0], chptr->chname, comment);
+ goto deny;
+ }
+ }
+
+ goto attack;
+
+ deny:
+ sendto_one(sptr, err_str(ERR_ATTACKDENY), me.name, parv[0], chptr->chname, user);
+ continue;
+
+ attack:
+ if (lp)
+ sendto_channel_butserv(chptr, sptr,
+ ":%s KICK %s %s :%s", parv[0],
+ name, who->name, comment);
+ sendto_match_servs(chptr, cptr,
+ ":%s KICK %s %s :%s",
+ parv[0], name,
+ who->name, comment);
+ if (lp)
+ {
+ remove_user_from_channel(who, chptr);
+ }
+ }
+ else if (MyClient(sptr))
+ sendto_one(sptr, err_str(ERR_USERNOTINCHANNEL),
+ me.name, parv[0], user, name);
+ if (!IsServer(cptr) || !IsULine(cptr,sptr))
+ break;
+ } /* loop on parv[2] */
+ if (!IsServer(cptr) || !IsULine(cptr,sptr))
+ break;
+ } /* loop on parv[1] */
+
+ return 0;
+}
+
+
+int count_channels(sptr)
+aClient *sptr;
+{
+Reg1 aChannel *chptr;
+ Reg2 int count = 0;
+
+ for (chptr = channel; chptr; chptr = chptr->nextch)
+#ifdef SHOW_INVISIBLE_LUSERS
+ if (SecretChannel(chptr))
+ {
+ if (IsAnOper(sptr))
+ count++;
+ }
+ else
+#endif
+ count++;
+ return (count);
+}
+
+/*
+** m_topic
+** parv[0] = sender prefix
+** parv[1] = topic text
+**
+** For servers using TS: (Lefler)
+** parv[0] = sender prefix
+** parv[1] = channel list
+** parv[2] = topic nickname
+** parv[3] = topic time
+** parv[4] = topic text
+*/
+int m_topic(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ aChannel *chptr = NullChn;
+ char *topic = NULL, *name, *p = NULL, *tnick = NULL;
+ time_t ttime = 0;
+
+ if (check_registered(sptr))
+ return 0;
+
+ if (parc < 2)
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "TOPIC");
+ return 0;
+ }
+
+ for (; (name = strtoken(&p, parv[1], ",")); parv[1] = NULL)
+ {
+ if (parc > 1 && IsChannelName(name))
+ {
+ chptr = find_channel(name, NullChn);
+ if (!chptr || (!IsMember(sptr, chptr) &&
+ !IsServer(sptr) && !IsULine(cptr,sptr)))
+ {
+ sendto_one(sptr, err_str(ERR_NOTONCHANNEL),
+ me.name, parv[0], name);
+ continue;
+ }
+ if (parc > 2)
+ topic = parv[2];
+ if (parc > 4) {
+ tnick = parv[2];
+ ttime = atol(parv[3]);
+ topic = parv[4];
+ }
+ }
+
+ if (!chptr)
+ {
+ sendto_one(sptr, rpl_str(RPL_NOTOPIC),
+ me.name, parv[0], name);
+ return 0;
+ }
+
+ if (check_channelmask(sptr, cptr, name))
+ continue;
+
+ if (!topic) /* only asking for topic */
+ {
+ if (chptr->topic[0] == '\0')
+ sendto_one(sptr, rpl_str(RPL_NOTOPIC),
+ me.name, parv[0], chptr->chname);
+ else {
+ sendto_one(sptr, rpl_str(RPL_TOPIC),
+ me.name, parv[0],
+ chptr->chname, chptr->topic);
+ sendto_one(sptr, rpl_str(RPL_TOPICWHOTIME),
+ me.name, parv[0], chptr->chname,
+ chptr->topic_nick,
+ chptr->topic_time);
+ }
+ }
+ else if (ttime && topic && (IsServer(sptr) || IsULine(cptr,sptr)))
+ {
+ if (!chptr->topic_time || ttime < chptr->topic_time)
+ {
+ /* setting a topic */
+ strncpyzt(chptr->topic, topic, sizeof(chptr->topic));
+ strcpy(chptr->topic_nick, tnick);
+ chptr->topic_time = ttime;
+ sendto_match_servs(chptr, cptr,":%s TOPIC %s %s %lu :%s",
+ parv[0], chptr->chname,
+ chptr->topic_nick, chptr->topic_time,
+ chptr->topic);
+ sendto_channel_butserv(chptr, sptr, ":%s TOPIC %s :%s (%s)",
+ parv[0], chptr->chname,
+ chptr->topic, chptr->topic_nick);
+ }
+ }
+ else if (((chptr->mode.mode & MODE_TOPICLIMIT) == 0 ||
+ is_chan_op(sptr, chptr)) || IsOper(sptr) || IsULine(cptr,sptr)
+ || is_halfop(sptr, chptr) && topic)
+ {
+ /* setting a topic */
+ if (IsOper(sptr) && !(is_halfop(sptr, chptr) || IsULine(cptr,sptr) || is_chan_op(sptr, chptr)) && (chptr->mode.mode & MODE_TOPICLIMIT))
+ {
+ sendto_umode(UMODE_EYES, "*** OperTopic [IRCop: %s] - [Channel: %s] - [Topic: %s]", sptr->name, chptr->chname, topic);
+ }
+ strncpyzt(chptr->topic, topic, sizeof(chptr->topic));
+ strcpy(chptr->topic_nick, sptr->name);
+ if (ttime && IsServer(cptr))
+ chptr->topic_time = ttime;
+ else
+ chptr->topic_time = TStime();
+ sendto_match_servs(chptr, cptr,":%s TOPIC %s %s %lu :%s",
+ parv[0], chptr->chname, parv[0],
+ chptr->topic_time, chptr->topic);
+ sendto_channel_butserv(chptr, sptr, ":%s TOPIC %s :%s",
+ parv[0],
+ chptr->chname, chptr->topic);
+ }
+ else
+ sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED),
+ me.name, parv[0], chptr->chname);
+ }
+ return 0;
+ }
+
+/*
+** m_invite
+** parv[0] - sender prefix
+** parv[1] - user to invite
+** parv[2] - channel number
+*/
+int m_invite(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ aClient *acptr;
+ aChannel *chptr;
+
+ if (check_registered_user(sptr))
+ return 0;
+
+ if (parc < 3 || *parv[1] == '\0')
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "INVITE");
+ return -1;
+ }
+
+ if (!(acptr = find_person(parv[1], (aClient *)NULL)))
+ {
+ sendto_one(sptr, err_str(ERR_NOSUCHNICK),
+ me.name, parv[0], parv[1]);
+ return 0;
+ }
+
+ if (MyConnect(sptr))
+ clean_channelname(parv[2]);
+ if (check_channelmask(sptr, cptr, parv[2]))
+ return 0;
+ if (!(chptr = find_channel(parv[2], NullChn)))
+ {
+
+ sendto_prefix_one(acptr, sptr, ":%s INVITE %s :%s",
+ parv[0], parv[1], parv[2]);
+ return 0;
+ }
+ if (chptr->mode.mode & MODE_NOINVITE)
+ if (!IsULine(cptr,sptr)) {
+ sendto_one(sptr, err_str(ERR_NOINVITE),
+ me.name, parv[0], parv[2]);
+ return -1;
+ }
+ if (chptr && !IsMember(sptr, chptr) && !IsULine(cptr,sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOTONCHANNEL),
+ me.name, parv[0], parv[2]);
+ return -1;
+ }
+
+ if (IsMember(acptr, chptr))
+ {
+ sendto_one(sptr, err_str(ERR_USERONCHANNEL),
+ me.name, parv[0], parv[1], parv[2]);
+ return 0;
+ }
+ if (chptr && (chptr->mode.mode & MODE_INVITEONLY))
+ {
+ if (!is_chan_op(sptr, chptr) && !IsULine(cptr,sptr))
+ {
+ sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED),
+ me.name, parv[0], chptr->chname);
+ return -1;
+ }
+ else if (!IsMember(sptr, chptr) && !IsULine(cptr,sptr))
+ {
+ sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED),
+ me.name, parv[0],
+ ((chptr) ? (chptr->chname) : parv[2]));
+ return -1;
+ }
+ }
+
+ if (MyConnect(sptr))
+ {
+ if(check_for_target_limit(sptr, acptr, acptr->name))
+ return 0;
+
+ sendto_one(sptr, rpl_str(RPL_INVITING), me.name, parv[0],
+ acptr->name, ((chptr) ? (chptr->chname) : parv[2]));
+ if (acptr->user->away)
+ sendto_one(sptr, rpl_str(RPL_AWAY), me.name, parv[0],
+ acptr->name, acptr->user->away);
+ }
+ /* Note: is_banned() here will cause some extra CPU load,
+ * and we're really only relying on the existence
+ * of the limit because we could momentarily have
+ * less people on channel.
+ */
+ if (MyConnect(acptr))
+ if (chptr && sptr->user && (is_banned(acptr, sptr, chptr) ||
+ (chptr->mode.mode & MODE_INVITEONLY) ||
+ chptr->mode.limit) &&
+ (is_chan_op(sptr, chptr) || IsULine(cptr,sptr)))
+ {
+ add_invite(acptr, chptr);
+ sendto_channelops_butone(NULL, &me, chptr,
+ ":%s NOTICE @%s :%s invited %s into the channel.",
+ me.name, chptr->chname, sptr->name, acptr->name);
+ }
+ sendto_prefix_one(acptr, sptr, ":%s INVITE %s :%s",parv[0],
+ acptr->name, ((chptr) ? (chptr->chname) : parv[2]));
+ return 0;
+ }
+
+
+
+
+/*
+ * send_list
+ *
+ * The function which sends
+ * The function which sends the actual /list output back to the user.
+ * Operates by stepping through the hashtable, sending the entries back if
+ * they match the criteria.
+ * cptr = Local client to send the output back to.
+ * numsend = Number (roughly) of lines to send back. Once this number has
+ * been exceeded, send_list will finish with the current hash bucket,
+ * and record that number as the number to start next time send_list
+ * is called for this user. So, this function will almost always send
+ * back more lines than specified by numsend (though not by much,
+ * assuming CHANNELHASHSIZE is was well picked). So be conservative
+ * if altering numsend };> -Rak
+ */
+void send_list(cptr, numsend)
+aClient *cptr;
+int numsend;
+{
+ int hashptr, done = 0;
+ aChannel *chptr;
+ Link *tmpl;
+
+#define l cptr->lopt /* lazy shortcut */
+
+ for (hashptr = l->starthash; hashptr < CHANNELHASHSIZE; hashptr++) {
+ for (chptr = hash_get_chan_bucket(hashptr);
+ chptr; chptr = chptr->hnextch) {
+ if (IsAnOper(cptr))
+ goto showmethesecrets;
+ if (SecretChannel(chptr) && !IsMember(cptr, chptr))
+ continue;
+showmethesecrets:
+ if (!l->showall && ((chptr->users <= l->usermin) ||
+ ((l->usermax == -1)?0:(chptr->users >= l->usermax)) ||
+ ((chptr->creationtime||1) <= l->chantimemin) ||
+ (chptr->topic_time < l->topictimemin) ||
+ (chptr->creationtime >= l->chantimemax) ||
+ (chptr->topic_time > l->topictimemax)))
+ continue;
+ /* For now, just extend to topics as well. Use patterns starting
+ * with # to stick to searching channel names only. -Donwulff
+ */
+ if (l->nolist &&
+ (find_str_match_link(&(l->nolist), chptr->chname) ||
+ find_str_match_link(&(l->nolist), chptr->topic)))
+ continue;
+ if (l->yeslist &&
+ (!find_str_match_link(&(l->yeslist), chptr->chname) &&
+ !find_str_match_link(&(l->yeslist), chptr->topic)))
+ continue;
+ if (!IsAnOper(cptr))
+ sendto_one(cptr, rpl_str(RPL_LIST), me.name, cptr->name,
+ ShowChannel(cptr, chptr) ? chptr->chname : "*",
+ chptr->users,
+ ShowChannel(cptr, chptr) ? chptr->topic : "");
+ else
+ sendto_one(cptr, rpl_str(RPL_LIST), me.name, cptr->name, chptr->chname, chptr->users, chptr->topic);
+ if (--numsend == 0) /* Send to the end of the list and return */
+ done = 1;
+ }
+
+ if (done && (++hashptr < CHANNELHASHSIZE)) {
+ l->starthash = hashptr;
+ return;
+ }
+ }
+
+ sendto_one(cptr, rpl_str(RPL_LISTEND), me.name, cptr->name);
+ free_str_list(l->yeslist);
+ free_str_list(l->nolist);
+ MyFree(l);
+ l = NULL;
+
+ /* List finished, penalize by 10 seconds -Donwulff */
+ if (!IsPrivileged(cptr))
+ cptr->since+=10;
+
+ return;
+}
+
+int check_for_chan_flood(cptr, sptr, chptr)
+aClient *cptr, *sptr;
+aChannel *chptr;
+{
+ Reg1 Link *lp;
+
+ if (!MyClient(sptr))
+ return 0;
+ if (IsOper(sptr) || IsULine(cptr,sptr))
+ return 0;
+ if (is_chan_op(sptr, chptr))
+ return 0;
+
+ if (!(lp = find_user_link(chptr->members, sptr)))
+ return 0;
+
+ if ((chptr->mode.msgs < 1) || (chptr->mode.per < 1))
+ return 0;
+
+ /* Theory here is
+ If current - lastmsgtime <= mode.per
+ and nummsg is higher than mode.msgs
+ then kick
+ */
+
+ if ( (TStime() - (lp->flood->lastmsg)) >= /* current - lastmsgtime */
+ chptr->mode.per) /* mode.per */
+ {
+ /* reset the message counter */
+ lp->flood->lastmsg = TStime();
+ lp->flood->nmsg = 1;
+ return 0; /* forget about it.. */
+ }
+
+ /* increase msgs */
+ lp->flood->nmsg++;
+ lp->flood->lastmsg = TStime();
+
+ if ( (lp->flood->nmsg) > chptr->mode.msgs )
+ {
+ char comment[1024], mask[1024];
+
+ sprintf(comment, "Flooding (Limit is %i lines per %i seconds)",
+ chptr->mode.msgs, chptr->mode.per);
+ if (chptr->mode.kmode == 1)
+ { /* ban. */
+ sprintf(mask, "*!*@%s", (IsHidden(sptr) ? sptr->user->virthost : sptr->user->realhost));
+ add_banid(&me, chptr, mask);
+ sendto_serv_butone(&me, ":%s MODE %s +b %s NoTS", me.name, chptr->chname, mask);
+ sendto_channel_butserv (chptr, &me, ":%s MODE %s +b %s", me.name, chptr->chname, mask);
+ }
+ sendto_channel_butserv (chptr, &me,
+ ":%s KICK %s %s :%s", me.name,
+ chptr->chname,
+ sptr->name,
+ comment);
+ sendto_serv_butone(cptr, ":%s KICK %s %s :%s",
+ me.name,
+ chptr->chname,
+ sptr->name,
+ comment);
+ remove_user_from_channel (sptr, chptr);
+ return 1;
+ }
+}
+
+/*
+ * m_list
+ * parv[0] = sender prefix
+ * parv[1,2,3...] = Channels or list options.
+ */
+int m_list(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ aChannel *chptr;
+ char *name, *p = NULL;
+ LOpts *lopt;
+ short int showall = 0;
+ Link *yeslist = NULL, *nolist = NULL, *listptr;
+ short usermin = 0, usermax = -1;
+ time_t currenttime = TStime();
+ time_t chantimemin = 0, topictimemin = 0;
+ time_t chantimemax, topictimemax;
+
+ static char *usage[] = {
+ " Usage: /raw LIST options (on mirc) or /quote LIST options (ircII)",
+ "",
+ "If you don't include any options, the default is to send you the",
+ "entire unfiltered list of channels. Below are the options you can",
+ "use, and what channels LIST will return when you use them.",
+ ">number List channels with more than <number> people.",
+ "<number List channels with less than <number> people.",
+ "C>number List channels created between now and <number> minutes ago.",
+ "C<number List channels created earlier than <number> minutes ago.",
+ "T>number List channels whose topics are older than <number> minutes",
+ " (Ie, they have not changed in the last <number> minutes.",
+ "T<number List channels whose topics are not older than <number> minutes.",
+ "*mask* List channels that match *mask*",
+ "!*mask* List channels that do not match *mask*",
+ NULL
+ };
+
+
+ /* None of that unregistered LIST stuff. -- Barubary */
+ if (check_registered(sptr)) return 0;
+
+ /*
+ * I'm making the assumption it won't take over a day to transmit
+ * the list... -Rak
+ */
+ chantimemax = topictimemax = currenttime + 86400;
+
+
+ if ((parc == 2) && (!strcasecmp(parv[1], "?"))) {
+ char **ptr = usage;
+
+ for (; *ptr; ptr++)
+ sendto_one(sptr, rpl_str(RPL_LISTSYNTAX), me.name,
+ cptr->name, *ptr);
+ return 0;
+ }
+
+ /*
+ * A list is already in process, for now we just interrupt the
+ * current listing, perhaps later we can allow stacked ones...
+ * -Donwulff (Not that it's hard or anything, but I don't see
+ * much use for it, beyond flooding)
+ */
+
+ if(cptr->lopt) {
+ free_str_list(cptr->lopt->yeslist);
+ free_str_list(cptr->lopt->nolist);
+ MyFree(cptr->lopt);
+ cptr->lopt=NULL;
+ sendto_one(sptr, rpl_str(RPL_LISTEND), me.name, cptr->name);
+ /* Interrupted list, penalize 10 seconds */
+ if(!IsPrivileged(sptr))
+ sptr->since+=10;
+
+ return 0;
+ }
+
+ sendto_one(sptr, rpl_str(RPL_LISTSTART), me.name, cptr->name);
+
+ /* LIST with no arguements */
+ if (parc < 2 || BadPtr(parv[1])) {
+ lopt = (LOpts *)MyMalloc(sizeof(LOpts));
+ if (!lopt)
+ return 0;
+
+ /*
+ * Changed to default to ignoring channels with only
+ * 1 person on, to decrease floods... -Donwulff
+ */
+ bzero(lopt, sizeof(LOpts)); /* To be sure! */
+ lopt->next = (LOpts *)lopt->yeslist=lopt->nolist=(Link *)NULL;
+ lopt->usermin = 0; /* Default */
+ lopt->usermax = -1;
+ lopt->chantimemax = lopt->topictimemax = currenttime + 86400;
+ cptr->lopt = lopt;
+ if (IsSendable(cptr))
+ send_list(cptr, 64);
+ return 0;
+ }
+
+
+ /*
+ * General idea: We don't need parv[0], since we can get that
+ * information from cptr.name. So, let's parse each element of
+ * parv[], setting pointer parv to the element being parsed.
+ */
+ while (--parc) {
+ parv += 1;
+ if (BadPtr(parv)) /* Sanity check! */
+ continue;
+
+ name = strtoken(&p, *parv, ",");
+
+ while (name) {
+ switch (*name) {
+ case '>':
+ showall = 1;
+ usermin = strtol(++name, (char **) 0, 10);
+ break;
+
+ case '<':
+ showall = 1;
+ usermax = strtol(++name, (char **) 0, 10);
+ break;
+
+ case 't':
+ case 'T':
+ showall = 1;
+ switch (*++name) {
+ case '>':
+ topictimemax = currenttime - 60 *
+ strtol(++name, (char **) 0, 10);
+ break;
+
+ case '<':
+ topictimemin = currenttime - 60 *
+ strtol(++name, (char **) 0, 10);
+ break;
+
+ case '\0':
+ topictimemin = 1;
+ break;
+
+ default:
+ sendto_one(sptr, err_str(ERR_LISTSYNTAX),
+ me.name, cptr->name);
+ free_str_list(yeslist);
+ free_str_list(nolist);
+ sendto_one(sptr, rpl_str(RPL_LISTEND),
+ me.name, cptr->name);
+
+ return 0;
+ }
+ break;
+
+ case 'c':
+ case 'C':
+ showall = 1;
+ switch (*++name) {
+ case '>':
+ chantimemin = currenttime - 60 *
+ strtol(++name, (char **) 0, 10);
+ break;
+
+ case '<':
+ chantimemax = currenttime - 60 *
+ strtol(++name, (char **) 0, 10);
+ break;
+
+ default:
+ sendto_one(sptr, err_str(ERR_LISTSYNTAX),
+ me.name, cptr->name);
+ free_str_list(yeslist);
+ free_str_list(nolist);
+ sendto_one(sptr, rpl_str(RPL_LISTEND),
+ me.name, cptr->name);
+ return 0;
+ }
+ break;
+
+ default: /* A channel or channel mask */
+
+ /*
+ * new syntax: !channelmask will tell ircd to ignore
+ * any channels matching that mask, and then
+ * channelmask will tell ircd to send us a list of
+ * channels only masking channelmask. Note: Specifying
+ * a channel without wildcards will return that
+ * channel even if any of the !channelmask masks
+ * matches it.
+ */
+
+ if (*name == '!') {
+ showall = 1;
+ listptr = make_link();
+ listptr->next = nolist;
+ DupString(listptr->value.cp, name+1);
+ nolist = listptr;
+ }
+ else if (strchr(name, '*') || strchr(name, '?')) {
+ showall = 1;
+ listptr = make_link();
+ listptr->next = yeslist;
+ DupString(listptr->value.cp, name);
+ yeslist = listptr;
+ }
+ else {
+ chptr = find_channel(name, NullChn);
+ if (chptr && ShowChannel(sptr, chptr))
+ sendto_one(sptr, rpl_str(RPL_LIST),
+ me.name, cptr->name,
+ ShowChannel(sptr,chptr) ? name : "*",
+ chptr->users,
+ chptr->topic);
+ }
+ } /* switch (*name) */
+ name = strtoken(&p, NULL, ",");
+ } /* while(name) */
+ } /* while(--parc) */
+
+ if (!showall || (chantimemin > currenttime) ||
+ (topictimemin > currenttime)) {
+ free_str_list(yeslist);
+ free_str_list(nolist);
+ sendto_one(sptr, rpl_str(RPL_LISTEND), me.name, cptr->name);
+
+ return 0;
+ }
+
+ lopt = (LOpts *)MyMalloc(sizeof(LOpts));
+
+ lopt->showall = 0;
+ lopt->next = NULL;
+ lopt->yeslist = yeslist;
+ lopt->nolist = nolist;
+ lopt->starthash = 0;
+ lopt->usermin = usermin;
+ lopt->usermax = usermax;
+ lopt->currenttime = currenttime;
+ lopt->chantimemin = chantimemin;
+ lopt->chantimemax = chantimemax;
+ lopt->topictimemin = topictimemin;
+ lopt->topictimemax = topictimemax;
+
+ cptr->lopt = lopt;
+ send_list(cptr, 64);
+
+
+
+ return 0;
+}
+
+
+/************************************************************************
+ * m_names() - Added by Jto 27 Apr 1989
+ * 12 Feb 2000 - geesh, time for a rewrite -lucas
+ ************************************************************************/
+/*
+** m_names
+** parv[0] = sender prefix
+** parv[1] = channel
+*/
+#define TRUNCATED_NAMES 64
+int m_names(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ int mlen = strlen(me.name) + NICKLEN + 7;
+ aChannel *chptr;
+ aClient *acptr;
+ int member;
+ Link *cm;
+ int idx, flag = 1, spos;
+ char *s, *para = parv[1];
+
+ if (check_registered(sptr)) return 0;
+
+ if (parc < 2 || !MyConnect(sptr))
+ {
+ sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0], "*");
+ return 0;
+ }
+
+ if (parc > 1 &&
+ hunt_server(cptr, sptr, ":%s NAMES %s %s", 2, parc, parv))
+ return 0;
+
+ for(s = para; *s; s++)
+ {
+ if(*s == ',')
+ {
+ para[TRUNCATED_NAMES] = '\0';
+ sendto_realops("names abuser %s %s", get_client_name(sptr, FALSE), para);
+ sendto_one(sptr, err_str(ERR_TOOMANYTARGETS), me.name, sptr->name, "NAMES");
+ return 0;
+ }
+ }
+
+ chptr = find_channel(para, (aChannel *) NULL);
+
+ if (!chptr || !ShowChannel(sptr, chptr))
+ {
+ sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0], para);
+ return 0;
+ }
+
+ /* cache whether this user is a member of this channel or not */
+ member = IsMember(sptr, chptr);
+
+ if(PubChannel(chptr))
+ buf[0] = '=';
+ else if(SecretChannel(chptr))
+ buf[0] = '@';
+ else
+ buf[0] = '*';
+
+ idx = 1;
+ buf[idx++] = ' ';
+ for(s = chptr->chname; *s; s++)
+ buf[idx++] = *s;
+ buf[idx++] = ' ';
+ buf[idx++] = ':';
+
+ spos = idx; /* starting point in buffer for names!*/
+
+ for (cm = chptr->members; cm; cm = cm->next)
+ {
+ acptr = cm->value.cptr;
+ if(IsInvisible(acptr) && !member)
+ continue;
+ if(cm->flags & CHFL_CHANOP)
+ buf[idx++] = '@';
+ else if (cm->flags & CHFL_HALFOP)
+ buf[idx++] = '%';
+ else if(cm->flags & CHFL_VOICE)
+ buf[idx++] = '+';
+ for(s = acptr->name; *s; s++)
+ buf[idx++] = *s;
+ buf[idx++] = ' ';
+ buf[idx] = '\0';
+ flag = 1;
+ if(mlen + idx + NICKLEN > BUFSIZE - 3)
+ {
+ sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
+ idx = spos;
+ flag = 0;
+ }
+ }
+
+ if (flag)
+ sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
+
+ sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0], para);
+
+ return 0;
+
+}
+
+void send_user_joins(cptr, user)
+aClient *cptr, *user;
+{
+ Reg1 Link *lp;
+ Reg2 aChannel *chptr;
+ Reg3 int cnt = 0, len = 0, clen;
+ char *mask;
+
+ sprintf(buf, ":%s %s ", user->name,
+ (IsToken(cptr)?TOK_JOIN:MSG_JOIN));
+ len = strlen(buf);
+
+ for (lp = user->user->channel; lp; lp = lp->next)
+ {
+ chptr = lp->value.chptr;
+ if ((mask = index(chptr->chname, ':')))
+ if (match(++mask, cptr->name))
+ continue;
+ if (*chptr->chname == '&')
+ continue;
+ clen = strlen(chptr->chname);
+ if (clen + 1 + len > BUFSIZE - 3)
+ {
+ if (cnt)
+ {
+ buf[len-1]='\0';
+ sendto_one(cptr, "%s", buf);
+ }
+ sprintf(buf, ":%s %s ", user->name,
+ (IsToken(cptr)?TOK_JOIN:MSG_JOIN));
+ len = strlen(buf);
+ cnt = 0;
+ }
+ (void)strcpy(buf + len, chptr->chname);
+ cnt++;
+ len += clen;
+ if (lp->next)
+ {
+ len++;
+ (void)strcat(buf, ",");
+ }
+ }
+ if (*buf && cnt)
+ sendto_one(cptr, "%s", buf);
+
+ return;
+}
+
+
+/*
+** m_knock
+** parv[0] - sender prefix
+** parv[1] - channel
+** parv[2] - reason
+**
+** Coded by Stskeeps
+** Additional bugfixes/ideas by codemastr
+** (C) codemastr & Stskeeps
+**
+*/
+int m_knock(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ aClient *acptr;
+ aChannel *chptr;
+
+ if (check_registered_user(sptr))
+ return 0;
+
+ if (parc < 3 || *parv[1] == '\0')
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "KNOCK");
+ return -1;
+ }
+
+ if (MyConnect(sptr))
+ clean_channelname(parv[1]);
+
+ if (check_channelmask(sptr, cptr, parv[1]))
+ return 0;
+ /* bugfix for /knock PRv Please? */
+ if (*parv[1] != '#' && *parv[1] != '&')
+ {
+ sendto_one(sptr, err_str(ERR_CANNOTKNOCK),
+ me.name,
+ sptr->name,
+ parv[1],
+ "Remember to use a # prefix in channel name");
+
+ return 0;
+ }
+ if (!(chptr = find_channel(parv[1], NullChn)))
+ {
+ sendto_one(sptr, err_str(ERR_CANNOTKNOCK),
+ me.name,
+ sptr->name,
+ parv[1],
+ "Channel does not exist!");
+ return 0;
+ }
+
+ /* IsMember bugfix by codemastr */
+ if (IsMember(sptr, chptr)==1) {
+ sendto_one(sptr, err_str(ERR_CANNOTKNOCK),
+ me.name,
+ sptr->name,
+ chptr->chname,
+ "You're already there!");
+ return 0;
+ }
+ if (chptr->mode.mode & MODE_NOKNOCK) {
+ sendto_one(sptr, err_str(ERR_CANNOTKNOCK),
+ me.name,
+ sptr->name,
+ chptr->chname,
+ "No knocks are allowed! (+K)");
+ return 0;
+ }
+
+ if (chptr->mode.mode & MODE_INVITEONLY) {
+ }
+ else
+ {
+ sendto_one(sptr, err_str(ERR_CANNOTKNOCK),
+ me.name,
+ sptr->name,
+ chptr->chname,
+ "Channel is not invite only!");
+ return 0;
+ }
+
+ if (is_banned(cptr, sptr, chptr)) {
+ sendto_one(sptr, err_str(ERR_CANNOTKNOCK),
+ me.name,
+ sptr->name,
+ chptr->chname,
+ "You're banned!");
+ return 0;
+ }
+
+ if (chptr->mode.mode & MODE_NOINVITE) {
+ sendto_one(sptr, err_str(ERR_CANNOTKNOCK),
+ me.name,
+ sptr->name,
+ chptr->chname,
+ "You can not get invited anyways! (+I)");
+
+ return 0;
+ }
+
+ sendto_channelops_butone(NULL, &me, chptr,
+ ":%s NOTICE @%s :[Knock] by %s!%s@%s (%s) ",
+ me.name, chptr->chname, sptr->name,
+ sptr->user->username,
+ (IsHidden(sptr) ? sptr->user->virthost : sptr->user->realhost),
+ parv[2]);
+
+ sendto_one(sptr, ":%s NOTICE %s :Knocked on to %s", me.name, sptr->name,
+ chptr->chname);
+ return 0;
+}
+
+typedef struct xParv aParv;
+struct xParv
+{
+ int parc;
+ char *parv[256];
+};
+
+aParv pparv;
+
+aParv *mp2parv(char *xmbuf, char *parmbuf)
+{
+ int c;
+ char *p;
+ pparv.parv[0] = xmbuf;
+ c = 1;
+ for (p = (char *)strtok((char *) parmbuf, " "); p; p = (char *)strtok((char *)NULL, " "))
+ {
+ c++;
+ pparv.parv[c-1] = p;
+ }
+ pparv.parc = c;
+ return (&pparv);
+}
+
+/*
+ ** m_sjoin
+ **
+ ** SJOIN will synch channels and channelmodes using the new STS1 protocol
+ ** that is based on the EFnet TS3 protocol.
+ ** -GZ (gz@starchat.net)
+ **
+ ** Modified for Unreal3.0 by Stskeeps
+ ** parv[0] = sender prefix
+ ** parv[1] = channel timestamp
+ ** parv[2] = channel name
+ ** parv[3] = channel modes
+ ** parv[4] = channel mode parameters (key/limit)
+ ** parv[5] = nick names + modes - all in one parameter
+ */
+#define FL_VOICE 0x1
+#define FL_HALFOP 0x2
+#define FL_CHANOP 0x4
+#define FL_PROT 0x8
+#define FL_FOUNDER 0x10
+
+int m_sjoin(cptr, sptr, parc, parv)
+ Reg2 aClient *cptr, *sptr;
+ int parc;
+ char *parv[];
+{
+ aClient *acptr, *tempptr;
+ aChannel *chptr;
+ aSynchList *synchptr, *synchptr2, *synchptr3;
+ aParv *ap;
+ char *p; int i;
+ char pvar[MAXMODEPARAMS][MODEBUFLEN+3];
+ Link *lp, *lp2, *members;
+ static char nick[NICKLEN];
+ char *t, *bp;
+ int c, f, fl, ts, copy, merge, wipem, nopara;
+ int nickstatus, ns, tc, xsend, susp_ts, pcount;
+ int oldts,xxsend = 0;
+
+ if (IsClient(sptr) || parc < 6 || !IsServer(sptr)) /* Double check redundant? yeah, I think so -GZ */
+ return 0;
+
+ if (!IsChannelName(parv[2]))
+ return 0;
+
+ nopara = 0;
+
+ if (!strncmp(parv[4], "<none>", 6) || !strncmp(parv[4], "<->", 3)) {
+ nopara = 1;
+ }
+ xsend = 1;
+
+ /* If length of modebuf is 1, we dont have to do anything */
+
+ if (parv[3][1] == 0) /* ie if the 2nd character is NULL, its length is one (or zero, but thats not possible */
+ xsend = 0;
+
+ chptr = get_channel(cptr, parv[2], CREATE);
+
+ ts = atol(parv[1]);
+
+ copy = merge = tc = wipem = susp_ts = 0;
+
+ if (chptr->creationtime > ts) {
+ copy = wipem = 1;
+ } else if (chptr->creationtime == ts) {
+ merge = 1;
+ }
+ /* If our timestamp is 0 this is a new channel, copy it. */
+
+ if (chptr->creationtime == 0 && ts > 0) {
+ copy = 1;
+ oldts = -1;
+ }
+ else
+ oldts = chptr->creationtime;
+ /* Hmmmmmm.....timestamp is below 750000, something fishy is going on
+ * let's just not take this SJOIN too seriously... -GZ
+ */
+
+ if (ts < 750000) {
+ if (ts != 0)
+ sendto_ops("Warning! Possible desynch: SJOIN for channel %s has a fishy timestamp (%ld)", chptr->chname, ts);
+ susp_ts = 1;
+ }
+ t = parv[5];
+ bp = buf;
+
+ c = fl = nickstatus = 0;
+ f = 1;
+
+ /* Let's see what the channel-modes are first here */
+
+ parabuf[0] = '\0';
+ modebuf[0] = '+';
+ modebuf[1] = '\0';
+ channel_modes(cptr, modebuf, parabuf, chptr);
+
+ /* Let's clean our channel-modes if nescessary */
+
+ if (wipem && (modebuf[1] != '\0') && !susp_ts) {
+
+ modebuf[0] = '-';
+ ap = mp2parv(modebuf, parabuf);
+ set_mode(chptr, cptr, ap->parc, ap->parv, &pcount, pvar, 0);
+ sendto_serv_butone_sjoin(cptr, ":%s %s %s %s %s %lu", me.name, MSG_MODE, chptr->chname, modebuf,
+ parabuf, chptr->creationtime);
+ sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s %s", me.name,
+ chptr->chname, modebuf, parabuf);
+ }
+ /* Now let's apply the modes as required */
+
+ if ((copy || merge) && xsend && !susp_ts) {
+ *parabuf = '\0';
+ *modebuf = '+';
+ modebuf[1] = '\0';
+
+ if (parv[3]) {
+ strcpy(modebuf, parv[3]);
+ xsend = 1;
+ }
+ if (!nopara)
+ strcpy(parabuf, parv[4]);
+ else
+ parabuf[0] = '\0';
+
+ if (xsend) {
+ sendto_serv_butone_sjoin(cptr, ":%s %s %s %s %s %lu", me.name,
+ MSG_MODE, chptr->chname, modebuf,
+ parabuf, chptr->creationtime);
+ sendto_channel_butserv(chptr,sptr, ":%s MODE %s %s %s", me.name,
+ chptr->chname, modebuf, parabuf);
+ ap = mp2parv(modebuf, parabuf);
+ set_mode(chptr, cptr, ap->parc, ap->parv, &pcount, pvar, 0);
+ }
+ }
+ xsend = 0;
+
+ /* First we better wipe our chanop list if our TS is older than SJOIN TS */
+
+ if (wipem && !susp_ts)
+ {
+ members = chptr->members;
+ for (lp2 = members; lp2; lp2 = lp2->next)
+ {
+
+ if ((lp2->flags & MODE_CHANOP)) {
+ lp2->flags &= ~MODE_CHANOP;
+ acptr = lp2->value.cptr;
+
+ sendto_channel_butserv(chptr, cptr, ":%s MODE %s -o %s", me.name, chptr->chname, lp2->value.cptr->name);
+ sendto_serv_butone_sjoin(cptr, ":%s MODE %s -o %s %lu", me.name, chptr->chname, acptr->name, chptr->creationtime);
+ }
+ if ((lp2->flags & MODE_VOICE))
+ {
+ lp2->flags &= ~MODE_VOICE;
+
+ acptr = lp2->value.cptr;
+
+ sendto_channel_butserv(chptr, cptr, ":%s MODE %s -v %s", me.name, chptr->chname, acptr->name);
+ sendto_serv_butone_sjoin(cptr, ":%s MODE %s -v %s %lu", me.name, chptr->chname, acptr->name, chptr->creationtime);
+ }
+ if ((lp2->flags & MODE_HALFOP))
+ {
+ lp2->flags &= ~MODE_HALFOP;
+
+ acptr = lp2->value.cptr;
+
+ sendto_channel_butserv(chptr, cptr, ":%s MODE %s -h %s", me.name, chptr->chname, acptr->name);
+ sendto_serv_butone_sjoin(cptr, ":%s MODE %s -h %s %lu", me.name, chptr->chname, acptr->name, chptr->creationtime);
+ }
+ if ((lp2->flags & MODE_CHANOWNER)) {
+ lp2->flags &= ~MODE_CHANOWNER;
+
+ acptr = lp2->value.cptr;
+
+ sendto_channel_butserv(chptr, cptr, ":%s MODE %s -q %s", me.name, chptr->chname, acptr->name);
+ sendto_serv_butone_sjoin(cptr, ":%s MODE %s -q %s %lu", me.name, chptr->chname, acptr->name, chptr->creationtime);
+ }
+ if ((lp2->flags & MODE_CHANPROT)) {
+ lp2->flags &= ~MODE_CHANPROT;
+
+ acptr = lp2->value.cptr;
+
+ sendto_channel_butserv(chptr, cptr, ":%s MODE %s -a %s", me.name, chptr->chname, acptr->name);
+ sendto_serv_butone_sjoin(cptr, ":%s MODE %s -a %s %lu", me.name, chptr->chname, acptr->name, chptr->creationtime);
+ }
+ }
+ }
+ /* Ok - it should now all be wiped so lets see what they have to offer us */
+ /* t points to parv[5], nick list
+ * f is 1 to begin with.
+ * c is 0 to begin with.
+ * bp points to buf.
+ */
+
+ while (*t != '\0')
+ {
+ if (*t == ' ')
+ {
+ if (f)
+ strncpyzt(bp, (t - c), (c + 1)); /* Put the nick in bp */
+ else
+ strncpyzt(bp, (t - (c - 1)), c); /* Put the nick in bp */
+
+
+ i = 0;
+ ns = 0;
+ for (p = bp; *p; p++)
+ {
+ if (*p == '@')
+ {
+ ns |= FL_CHANOP;
+ i++;
+ }
+ else if (*p == '+')
+ {
+ ns |= FL_VOICE; i++;
+ }
+ else if (*p == '%')
+ {
+ ns |= FL_HALFOP; i++;
+ }
+ else if (*p == '*')
+ {
+ ns |= FL_FOUNDER; i++;
+ }
+ else if (*p == '~')
+ {
+ ns |= FL_PROT; i++;
+ } else
+ break;
+ }
+ if (i != 0)
+ strncpyzt(nick, bp + i, c);
+ else
+ strncpyzt(nick, bp, (c+1));
+ if (!(acptr = find_client(nick, NULL)))
+ {
+ /* The client doesn't exist, probably Killed off for some reason, this is
+ * ok, we will just ignore it
+ */
+ /* horrible, horrible thing to do, but this while loop needs rewriting anyhow */
+ sendto_realops("Missing user %s in SJOIN at %s !", nick, chptr->chname);
+ goto bad_nick_jump;
+
+ }
+ /* ok, now, is this an evil nick (ie, one on our side), or a good one,
+ * ie, one on the other side?
+ */
+ /* sptr = server who is sending the SJOIN */
+ tempptr = acptr;
+
+ while (tempptr != &me && tempptr != sptr)
+ tempptr = tempptr->srvptr;
+
+ if (tempptr == &me)
+ {
+ /* this nick is an evil nick, since its on my
+ * side... ignore this nick.
+ */
+ /* horrible, horrible thing to do, but this while loop needs rewriting anyhow */
+ goto bad_nick_jump;
+ }
+ fl = 0;
+ if (ns & FL_CHANOP)
+ fl |= CHFL_CHANOP;
+ if (ns & FL_VOICE)
+ fl |= CHFL_VOICE;
+ if (ns & FL_HALFOP)
+ fl |= CHFL_HALFOP;
+ if (ns & FL_FOUNDER)
+ fl |= CHFL_CHANOWNER;
+ if (ns & FL_PROT)
+ fl |= CHFL_CHANPROT;
+ if (!IsMember(acptr, chptr))
+ {
+ /* Its not really possible for the user to be a member of this
+ * channel already, unless something is broken, but its not
+ * too bad checking for this, just in case
+ */
+ add_user_to_channel(chptr, acptr, fl);
+ if (!IsHiding(acptr))
+ sendto_channel_butserv(chptr, acptr, ":%s JOIN :%s", nick, parv[2]);
+ sendto_serv_butone_sjoin(cptr, ":%s JOIN :%s", nick, parv[2]);
+ }
+
+ lp = find_user_link(chptr->members, acptr);
+
+ if (!lp)
+ sendto_ops("WARNING! possible desynch from %s in %s", nick, chptr->chname);
+
+ synchptr = make_synchlist();
+
+ strncpyzt(synchptr->nick, nick, sizeof(synchptr->nick));
+
+ if (ns & FL_VOICE)
+ synchptr->voice = 1;
+ if (ns & FL_HALFOP)
+ synchptr->half = 1;
+ if (ns & FL_CHANOP)
+ synchptr->op = 1;
+ if (ns & FL_PROT)
+ synchptr->prot = 1;
+ if (ns & FL_FOUNDER)
+ synchptr->own = 1;
+
+ if (SJSynchList == NULL)
+ SJSynchList = synchptr;
+ else
+ {
+ SJSynchList->prev = synchptr;
+ synchptr->next = SJSynchList;
+ SJSynchList = synchptr;
+ }
+bad_nick_jump:
+ tc++;
+ c = f = fl = 0;
+ }
+ t++;
+ c++;
+ }
+
+ /* Ok, we parsed the nicks, we made them join. Time to set their modes -GZ */
+
+ xsend = 0;
+
+ if (!susp_ts)
+ {
+ if (SJSynchList == NULL)
+ goto EndMode;
+
+ modebuf[1] = '\0';
+ parabuf[0] = '\0';
+ modebuf[0] = '+';
+
+ xsend = 0;
+
+ for (synchptr2 = SJSynchList; synchptr2; synchptr2 = synchptr3)
+ {
+
+ synchptr3 = synchptr2->next;
+
+ if ((synchptr2->op)) {
+ strcat(modebuf, "o");
+ strcat(parabuf, synchptr2->nick);
+ strcat(parabuf, " ");
+ xsend++;
+
+ if (xsend == RESYNCMODES) {
+ strcat(modebuf, "\0");
+ strcat(parabuf, "\0");
+
+ sendto_channel_butserv(chptr, cptr, ":%s MODE %s %s %s", cptr->name, chptr->chname, modebuf, parabuf);
+ sendto_serv_butone_sjoin(cptr, ":%s MODE %s %s %s", cptr->name, chptr->chname, modebuf, parabuf, chptr->creationtime);
+
+ modebuf[1] = '\0';
+ parabuf[0] = '\0';
+ modebuf[0] = '+';
+ xsend = 0;
+ }
+ }
+ }
+
+ if (SJSynchList == NULL)
+ goto EndMode;
+
+ for (synchptr2 = SJSynchList; synchptr2; synchptr2 = synchptr3) {
+
+ synchptr3 = synchptr2->next;
+
+ if ((synchptr2->voice)) {
+ strcat(modebuf, "v");
+ strcat(parabuf, synchptr2->nick);
+ strcat(parabuf, " ");
+ xsend++;
+
+ if (xsend == RESYNCMODES) {
+ strcat(modebuf, "\0");
+ strcat(parabuf, "\0");
+
+ sendto_channel_butserv(chptr, cptr, ":%s MODE %s %s %s", cptr->name, chptr->chname, modebuf, parabuf);
+ sendto_serv_butone_sjoin(cptr, ":%s MODE %s %s %s", cptr->name, chptr->chname, modebuf, parabuf, chptr->creationtime);
+
+ modebuf[1] = '\0';
+ parabuf[0] = '\0';
+ modebuf[0] = '+';
+
+ xsend = 0;
+ }
+ }
+ }
+
+ if (SJSynchList == NULL)
+ goto EndMode;
+
+ for (synchptr2 = SJSynchList; synchptr2; synchptr2 = synchptr3) {
+
+ synchptr3 = synchptr2->next;
+
+ if ((synchptr2->half)) {
+ strcat(modebuf, "h");
+ strcat(parabuf, synchptr2->nick);
+ strcat(parabuf, " ");
+ xsend++;
+
+ if (xsend == RESYNCMODES) {
+ strcat(modebuf, "\0");
+ strcat(parabuf, "\0");
+
+ sendto_channel_butserv(chptr, cptr, ":%s MODE %s %s %s", cptr->name, chptr->chname, modebuf, parabuf);
+ sendto_serv_butone_sjoin(cptr, ":%s MODE %s %s %s", cptr->name, chptr->chname, modebuf, parabuf, chptr->creationtime);
+
+ modebuf[1] = '\0';
+ parabuf[0] = '\0';
+ modebuf[0] = '+';
+
+ xsend = 0;
+ }
+ }
+ }
+
+ if (SJSynchList == NULL)
+ goto EndMode;
+
+
+ for (synchptr2 = SJSynchList; synchptr2; synchptr2 = synchptr3) {
+
+ synchptr3 = synchptr2->next;
+
+ if ((synchptr2->own)) {
+ strcat(modebuf, "q");
+ strcat(parabuf, synchptr2->nick);
+ strcat(parabuf, " ");
+ xsend++;
+
+ if (xsend == RESYNCMODES) {
+ strcat(modebuf, "\0");
+ strcat(parabuf, "\0");
+
+ sendto_channel_butserv(chptr, cptr, ":%s MODE %s %s %s", cptr->name, chptr->chname, modebuf, parabuf);
+ sendto_serv_butone_sjoin(cptr, ":%s MODE %s %s %s", cptr->name, chptr->chname, modebuf, parabuf, chptr->creationtime);
+
+ modebuf[1] = '\0';
+ parabuf[0] = '\0';
+ modebuf[0] = '+';
+
+ xsend = 0;
+ }
+ }
+ }
+
+ if (SJSynchList == NULL)
+ goto EndMode;
+
+ for (synchptr2 = SJSynchList; synchptr2; synchptr2 = synchptr3) {
+
+ synchptr3 = synchptr2->next;
+
+ if ((synchptr2->prot)) {
+ strcat(modebuf, "a");
+ strcat(parabuf, synchptr2->nick);
+ strcat(parabuf, " ");
+ xsend++;
+
+ if (xsend == RESYNCMODES) {
+ strcat(modebuf, "\0");
+ strcat(parabuf, "\0");
+
+ sendto_channel_butserv(chptr, cptr, ":%s MODE %s %s %s", cptr->name, chptr->chname, modebuf, parabuf);
+ sendto_serv_butone_sjoin(cptr, ":%s MODE %s %s %s", cptr->name, chptr->chname, modebuf, parabuf, chptr->creationtime);
+
+ modebuf[1] = '\0';
+ parabuf[0] = '\0';
+ modebuf[0] = '+';
+
+ xsend = 0;
+ }
+ }
+ }
+
+ if (SJSynchList == NULL)
+ goto EndMode;
+
+ }
+ /* Ok! all done, time to clean up the mess */
+
+ for (synchptr2 = SJSynchList; synchptr2; synchptr2 = synchptr3) {
+
+ synchptr3 = synchptr2->next;
+
+ if (synchptr2->prev)
+ synchptr2->prev->next = synchptr2->next;
+ else
+ SJSynchList = synchptr2->next;
+ if (synchptr2->next)
+ synchptr2->next->prev = synchptr2->prev;
+ free_synchlist(synchptr2);
+
+ }
+
+ EndMode:
+ if (xsend) {
+ sendto_channel_butserv(chptr, cptr, ":%s MODE %s %s %s", cptr->name, chptr->chname, modebuf, parabuf);
+ sendto_serv_butone_sjoin(cptr, ":%s MODE %s %s %s", cptr->name, chptr->chname, modebuf, parabuf, chptr->creationtime);
+ }
+
+ /* After all is done, synch timestamps as channels should now be identical */
+
+ if (!(ts > chptr->creationtime) && !susp_ts)
+ chptr->creationtime = ts;
+
+ else if (chptr->creationtime == 0 && ts > 0)
+ chptr->creationtime = ts;
+
+ /* And we are desynched! - kidding! - *whew!* */
+ if (oldts != -1)
+ if (oldts != ts)
+ sendto_channel_butserv(chptr, &me, ":%s NOTICE %s :*** Notice -- TS for %s changed from %ld to %ld",
+ me.name, chptr->chname, chptr->chname, oldts, ts);
+
+ sendto_serv_sjoin(cptr, ":%s SJOIN %s %s %s %s :%s", parv[0], parv[1], parv[2], parv[3], parv[4], parv[5]);
+
+ return 0;
+}
+
+/*
+ * This will send "cptr" a full list of the modes for channel chptr,
+ */
+
+void send_channel_modes_sjoin(cptr, chptr)
+ aClient *cptr;
+ aChannel *chptr;
+{
+
+ Link *members;
+ Reg1 Link *lp;
+ Reg2 char *name;
+ char *bufptr;
+
+ int n = 0;
+
+ if (*chptr->chname != '#')
+ return;
+
+ members = chptr->members;
+
+ /* First we'll send channel, channel modes and members and status */
+
+ *modebuf = *parabuf = '\0';
+ channel_modes(cptr, modebuf, parabuf, chptr);
+
+ if (*parabuf)
+ strcat(parabuf, " ");
+ else
+ {
+ if (!SupportSJOIN2(cptr))
+ strcpy(parabuf, "<none>");
+ else
+ strcpy(parabuf, "<->");
+ }
+ sprintf(buf, "%s %ld %s %s %s :",
+ (IsToken(cptr) ? TOK_SJOIN : MSG_SJOIN),
+ chptr->creationtime,
+ chptr->chname, modebuf, parabuf);
+
+ bufptr = buf + strlen(buf);
+
+ for (lp = members; lp; lp = lp->next) {
+
+ if (lp->flags & MODE_CHANOP)
+ *bufptr++ = '@';
+
+ if (lp->flags & MODE_VOICE)
+ *bufptr++ = '+';
+
+ if (lp->flags & MODE_HALFOP)
+ *bufptr++ = '%';
+ if (lp->flags & MODE_CHANOWNER)
+ *bufptr++ = '*';
+ if (lp->flags & MODE_CHANPROT)
+ *bufptr++ = '~';
+
+
+
+ name = lp->value.cptr->name;
+
+ strcpy(bufptr, name);
+ bufptr += strlen(bufptr);
+ *bufptr++ = ' ';
+ n++;
+
+ if (bufptr - buf > BUFSIZE - 80) {
+ *bufptr++ = '\0';
+ if (bufptr[-1] == ' ')
+ bufptr[-1] = '\0';
+ sendto_one(cptr, "%s", buf);
+
+ sprintf(buf, "%s %ld %s %s %s :", (IsToken(cptr) ? TOK_SJOIN : MSG_SJOIN),
+ chptr->creationtime,
+ chptr->chname, modebuf, parabuf);
+ n = 0;
+
+ bufptr = buf + strlen(buf);
+ }
+ }
+
+ if (n) {
+ *bufptr++ = '\0';
+ if (bufptr[-1] == ' ')
+ bufptr[-1] = '\0';
+ sendto_one(cptr, "%s", buf);
+ }
+ /* Then we'll send the ban-list */
+
+ *parabuf = '\0';
+ *modebuf = '+';
+ modebuf[1] = '\0';
+ // fixme
+// send_ban_list(cptr, chptr->chname, chptr->creationtime, chptr->banlist);
+
+ if (modebuf[1] || *parabuf)
+ sendto_one(cptr, ":%s MODE %s %s %s", me.name, chptr->chname, modebuf, parabuf);
+
+ return;
+}
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, ircd/chkconf.c
+ * Copyright (C) 1993 Darren Reed
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#include "numeric.h"
+#ifndef _WIN32
+#include <sys/socket.h>
+#endif
+#include <sys/stat.h>
+#include <fcntl.h>
+#ifdef __hpux
+#include "inet.h"
+#endif
+#ifdef PCS
+#include <time.h>
+#endif
+
+ID_CVS("$Id$");
+ID_Copyright("(C) 1993 Darren Reed");
+ID_Notes("DF version was 1.9 1/30/94");
+
+#ifdef DYNIXPTX
+#include <sys/types.h>
+#include <time.h>
+#endif
+
+/* for the connect rule patch.. these really should be in a header,
+** but i see h.h isn't included for some reason.. so they're here */
+char *crule_parse PROTO((char *rule));
+void crule_free PROTO((char **elem));
+
+#undef free
+#define MyMalloc(x) malloc(x)
+
+static void new_class();
+static char *getfield(), confchar ();
+static int openconf(), validate();
+static aClass *get_class();
+static aConfItem *initconf();
+
+static int numclasses = 0, *classarr = (int *)NULL, debugflag = 0;
+static char *configfile = CONFIGFILE;
+static char nullfield[] = "";
+static char maxsendq[12];
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ new_class(0);
+
+ if (chdir(DPATH))
+ {
+ perror("chdir");
+ exit(-1);
+ }
+ if (argc > 1 && !strncmp(argv[1], "-d", 2))
+ {
+ debugflag = 1;
+ if (argv[1][2])
+ debugflag = atoi(argv[1]+2);
+ argc--, argv++;
+ }
+ if (argc > 1)
+ configfile = argv[1];
+ return validate(initconf());
+}
+
+/*
+ * openconf
+ *
+ * returns -1 on any error or else the fd opened from which to read the
+ * configuration file from. This may either be th4 file direct or one end
+ * of a pipe from m4.
+ */
+static int openconf()
+{
+#ifdef M4_PREPROC
+ int pi[2];
+
+ if (pipe(pi) == -1)
+ return -1;
+ switch(fork())
+ {
+ case -1 :
+ return -1;
+ case 0 :
+ (void)close(pi[0]);
+ if (pi[1] != 1)
+ {
+ (void)dup2(pi[1], 1);
+ (void)close(pi[1]);
+ }
+ (void)dup2(1,2);
+ /*
+ * m4 maybe anywhere, use execvp to find it. Any error
+ * goes out with report_error. Could be dangerous,
+ * two servers running with the same fd's >:-) -avalon
+ */
+ (void)execlp("m4", "m4", "ircd.m4", configfile, 0);
+ perror("m4");
+ exit(-1);
+ default :
+ }
+ (void)close(pi[1]);
+ return pi[0];
+
+#else
+ return open(configfile, O_RDONLY);
+#endif
+}
+
+#define STAR1 OFLAG_SADMIN|OFLAG_ADMIN|OFLAG_NETADMIN|OFLAG_COADMIN
+#define STAR2 OFLAG_TECHADMIN|OFLAG_ZLINE|OFLAG_AGENT|OFLAG_HIDE|OFLAG_WHOIS
+static int oper_access[] = {
+ ~(STAR1|STAR2), '*',
+ OFLAG_LOCAL, 'o',
+ OFLAG_GLOBAL, 'O',
+ OFLAG_REHASH, 'r',
+ OFLAG_EYES, 'e',
+ OFLAG_DIE, 'D',
+ OFLAG_RESTART, 'R',
+ OFLAG_HELPOP, 'h',
+ OFLAG_GLOBOP, 'g',
+ OFLAG_WALLOP, 'w',
+ OFLAG_LOCOP, 'l',
+ OFLAG_LROUTE, 'c',
+ OFLAG_GROUTE, 'L',
+ OFLAG_LKILL, 'k',
+ OFLAG_GKILL, 'K',
+ OFLAG_KLINE, 'b',
+ OFLAG_UNKLINE, 'B',
+ OFLAG_LNOTICE, 'n',
+ OFLAG_GNOTICE, 'G',
+ OFLAG_ADMIN, 'A',
+ OFLAG_SADMIN, 'a',
+ OFLAG_NETADMIN, 'N',
+ OFLAG_COADMIN, 'C',
+ OFLAG_TECHADMIN, 'T',
+ OFLAG_UMODEC, 'u',
+ OFLAG_UMODEF, 'f',
+ OFLAG_ZLINE, 'z',
+ OFLAG_WHOIS, 'W',
+ OFLAG_HIDE, 'H',
+ OFLAG_AGENT, 'S',
+ 0, 0 };
+
+
+/*
+** initconf()
+** Read configuration file.
+**
+** returns -1, if file cannot be opened
+** 0, if file opened
+*/
+
+static aConfItem *initconf(opt)
+int opt;
+{
+ int fd;
+ char line[512], *tmp, c[80], *s, *crule;
+ int ccount = 0, ncount = 0, dh, flags = 0;
+ int lineno;
+ aConfItem *aconf = NULL, *ctop = NULL;
+
+ (void)fprintf(stderr, "initconf(): ircd.conf = %s\n", configfile);
+ if ((fd = openconf()) == -1)
+ {
+#ifdef M4_PREPROC
+ (void)wait(0);
+#endif
+ return NULL;
+ }
+
+ lineno = 1;
+ (void)dgets(-1, NULL, 0); /* make sure buffer is at empty pos */
+ while ((dh = dgets(fd, line, sizeof(line) - 1)) > 0)
+ {
+ printf("%u: End of file\r",lineno++);
+ if (aconf)
+ {
+ if (aconf->host)
+ (void)free(aconf->host);
+ if (aconf->passwd)
+ (void)free(aconf->passwd);
+ if (aconf->name)
+ (void)free(aconf->name);
+ }
+ else
+ aconf = (aConfItem *)malloc(sizeof(*aconf));
+ aconf->host = (char *)NULL;
+ aconf->passwd = (char *)NULL;
+ aconf->name = (char *)NULL;
+ aconf->class = (aClass *)NULL;
+ if (tmp = (char *)index(line, '\n'))
+ *tmp = 0;
+ else while(dgets(fd, c, sizeof(c) - 1))
+ if (tmp = (char *)index(c, '\n'))
+ {
+ *tmp = 0;
+ break;
+ }
+ /*
+ * Do quoting of characters and # detection.
+ */
+ for (tmp = line; *tmp; tmp++)
+ {
+ if (*tmp == '\\')
+ {
+ switch (*(tmp+1))
+ {
+ case 'n' :
+ *tmp = '\n';
+ break;
+ case 'r' :
+ *tmp = '\r';
+ break;
+ case 't' :
+ *tmp = '\t';
+ break;
+ case '0' :
+ *tmp = '\0';
+ break;
+ default :
+ *tmp = *(tmp+1);
+ break;
+ }
+ if (!*(tmp+1))
+ break;
+ else
+ for (s = tmp; *s = *++s; )
+ ;
+ tmp++;
+ }
+ else if (*tmp == '#')
+ *tmp = '\0';
+ }
+ if (!*line || *line == '#' || *line == '\n' ||
+ *line == ' ' || *line == '\t')
+ continue;
+ if (*line == 'X' || *line == 'T')
+ continue;
+ if (*line == 'x' || *line == 't')
+ continue;
+
+ if (line[1] != ':')
+ {
+ (void)fprintf(stderr, "ERROR: Bad config line (%s)\n",
+ line);
+ continue;
+ }
+
+ if (debugflag)
+ (void)printf("\n%s\n",line);
+ (void)fflush(stdout);
+
+ tmp = getfield(line);
+ if (!tmp)
+ {
+ (void)fprintf(stderr, "\tERROR: no fields found\n");
+ continue;
+ }
+
+ aconf->status = CONF_ILLEGAL;
+
+ switch (*tmp)
+ {
+ case 'A': /* Name, e-mail address of administrator */
+ aconf->status = CONF_ADMIN;
+ break;
+ case 'a': /* of this server. */
+ aconf->status = CONF_SADMIN;
+ break;
+ case 'C': /* Server where I should try to connect */
+ case 'c': /* in case of lp failures */
+ ccount++;
+ aconf->status = CONF_CONNECT_SERVER;
+ break;
+ /* Connect rule */
+ case 'D':
+ aconf->status = CONF_CRULEALL;
+ break;
+ /* Connect rule - autos only */
+ case 'd':
+ aconf->status = CONF_CRULEAUTO;
+ break;
+ case 'H': /* Hub server line */
+ case 'h':
+ aconf->status = CONF_HUB;
+ break;
+ case 'I': /* Just plain normal irc client trying */
+ case 'i': /* to connect me */
+ aconf->status = CONF_CLIENT;
+ break;
+ case 'K': /* Kill user line on ircd.conf */
+ case 'k':
+ aconf->status = CONF_KILL;
+ break;
+ /* Operator. Line should contain at least */
+ /* password and host where connection is */
+ case 'L': /* guaranteed leaf server */
+ case 'l':
+ aconf->status = CONF_LEAF;
+ break;
+ /* Me. Host field is name used for this host */
+ /* and port number is the number of the port */
+ case 'M':
+ case 'm':
+ aconf->status = CONF_ME;
+ break;
+ case 'N': /* Server where I should NOT try to */
+ case 'n': /* connect in case of lp failures */
+ /* but which tries to connect ME */
+ ++ncount;
+ aconf->status = CONF_NOCONNECT_SERVER;
+ break;
+ case 'O':
+ aconf->status = CONF_OPERATOR;
+ break;
+ /* Local Operator, (limited privs --SRB)
+ * Not anymore, OperFlag access levels. -Cabal95 */
+ case 'o':
+ aconf->status = CONF_OPERATOR;
+ break;
+ case 'P': /* listen port line */
+ case 'p':
+ aconf->status = CONF_LISTEN_PORT;
+ break;
+ case 'Q': /* a server that you don't want in your */
+ case 'q': /* network. USE WITH CAUTION! */
+ aconf->status = CONF_QUARANTINED_SERVER;
+ break;
+ case 'S': /* Service. Same semantics as */
+ case 's': /* CONF_OPERATOR */
+ aconf->status = CONF_SERVICE;
+ break;
+ case 'U':
+ case 'u':
+ aconf->status = CONF_UWORLD;
+ break;
+ case 'Y':
+ case 'y':
+ aconf->status = CONF_CLASS;
+ break;
+ case 'Z':
+ case 'z':
+ aconf->status = CONF_ZAP;
+ break;
+ default:
+ (void)fprintf(stderr,
+ "\tERROR: unknown conf line letter (%c)\n",
+ *tmp);
+ break;
+ }
+
+ if (IsIllegal(aconf))
+ continue;
+
+ for (;;) /* Fake loop, that I can use break here --msa */
+ {
+ if ((tmp = getfield(NULL)) == NULL)
+ break;
+ DupString(aconf->host, tmp);
+ if ((tmp = getfield(NULL)) == NULL)
+ break;
+ DupString(aconf->passwd, tmp);
+ if ((tmp = getfield(NULL)) == NULL)
+ break;
+ DupString(aconf->name, tmp);
+ if ((tmp = getfield(NULL)) == NULL)
+ break;
+ if (aconf->status & CONF_OPERATOR) {
+ int *i, flag;
+ char *m = "*";
+ /*
+ * Now we use access flags to define
+ * what an operator can do with their O.
+ */
+ for (m = (*tmp) ? tmp : m; *m; m++) {
+ for (i = oper_access; (flag = *i); i += 2)
+ if (*m == (char)(*(i+1))) {
+ aconf->port |= flag;
+ break;
+ }
+ if (flag == 0)
+ fprintf(stderr,
+ "\tWARNING: Unknown oper access level '%c'\n",
+ *m);
+ }
+ if (!(aconf->port&OFLAG_ISGLOBAL))
+ aconf->status = CONF_LOCOP;
+ }
+ else
+ aconf->port = atoi(tmp);
+ if ((tmp = getfield(NULL)) == NULL)
+ break;
+ if (!(aconf->status & CONF_CLASS))
+ aconf->class = get_class(atoi(tmp));
+ break;
+ }
+ if (!aconf->class && (aconf->status & (CONF_CONNECT_SERVER|
+ CONF_NOCONNECT_SERVER|CONF_OPS|CONF_CLIENT)))
+ {
+ (void)fprintf(stderr,
+ "\tWARNING: No class. Default 0\n");
+ aconf->class = get_class(0);
+ }
+ /* Check for bad Z-lines */
+ if (aconf->status == CONF_ZAP)
+ {
+ char *tempc = aconf->host;
+ if (!tempc)
+ {
+ fprintf(stderr, "\tERROR: Bad Z-line\n");
+ }
+ for (; *tempc; tempc++)
+ if ((*tempc >= '0') && (*tempc <= '9'))
+ goto zap_safe;
+ fprintf(stderr, "\tERROR: Z-line mask too broad\n");
+ zap_safe:;
+ }
+ /*
+ ** If conf line is a class definition, create a class entry
+ ** for it and make the conf_line illegal and delete it.
+ */
+ if (aconf->status & CONF_CLASS)
+ {
+ int class = 0;
+
+ if (!aconf->host)
+ {
+ (void)fprintf(stderr,"\tERROR: no class #\n");
+ continue;
+ }
+ if (!tmp)
+ {
+ (void)fprintf(stderr,
+ "\tWARNING: missing sendq field\n");
+ (void)fprintf(stderr, "\t\t default: %d\n",
+ MAXSENDQLENGTH);
+ (void)sprintf(maxsendq, "%d", MAXSENDQLENGTH);
+ }
+ else
+ (void)sprintf(maxsendq, "%d", atoi(tmp));
+ new_class(atoi(aconf->host));
+ aconf->class = get_class(atoi(aconf->host));
+ goto print_confline;
+ }
+
+ if (aconf->status & CONF_LISTEN_PORT)
+ {
+ if (!aconf->host)
+ (void)fprintf(stderr, "\tERROR: %s\n",
+ "null host field in P-line");
+ else if (index(aconf->host, '/'))
+ (void)fprintf(stderr, "\t%s %s\n",
+ "WARNING: / present in P-line",
+ "for non-UNIXPORT configuration");
+ aconf->class = get_class(0);
+ goto print_confline;
+ }
+
+ if (aconf->status & CONF_SERVER_MASK &&
+ (!aconf->host || index(aconf->host, '*') ||
+ index(aconf->host, '?')))
+ {
+ (void)fprintf(stderr, "\tERROR: bad host field\n");
+ continue;
+ }
+
+ if (aconf->status & CONF_SERVER_MASK && BadPtr(aconf->passwd))
+ {
+ (void)fprintf(stderr,
+ "\tERROR: empty/no password field\n");
+ continue;
+ }
+
+ if (aconf->status & CONF_SERVER_MASK && !aconf->name)
+ {
+ (void)fprintf(stderr, "\tERROR: bad name field\n");
+ continue;
+ }
+
+ if (aconf->status & (CONF_SERVER_MASK|CONF_OPS))
+ if (!index(aconf->host, '@'))
+ {
+ char *newhost;
+ int len = 3; /* *@\0 = 3 */
+
+ len += strlen(aconf->host);
+ newhost = (char *)MyMalloc(len);
+ (void)sprintf(newhost, "*@%s", aconf->host);
+ (void)free(aconf->host);
+ aconf->host = newhost;
+ }
+
+ /* parse the connect rules to detect errors, but free
+ ** any allocated storage immediately -- we're just looking
+ ** for errors.. */
+ if (aconf->status & CONF_CRULE)
+ if ((crule =
+ (char *) crule_parse (aconf->name)) != NULL)
+ crule_free (&crule);
+
+ if (!aconf->class)
+ aconf->class = get_class(0);
+ (void)sprintf(maxsendq, "%d", aconf->class->class);
+
+ if (!aconf->name)
+ aconf->name = nullfield;
+ if (!aconf->passwd)
+ aconf->passwd = nullfield;
+ if (!aconf->host)
+ aconf->host = nullfield;
+ if (aconf->status & (CONF_ME|CONF_ADMIN))
+ {
+ if (flags & aconf->status)
+ (void)fprintf(stderr,
+ "ERROR: multiple %c-lines\n",
+ toupper(confchar(aconf->status)));
+ else
+ flags |= aconf->status;
+ }
+print_confline:
+ if (debugflag > 8)
+ (void)printf("(%d) (%s) (%s) (%s) (%d) (%s)\n",
+ aconf->status, aconf->host, aconf->passwd,
+ aconf->name, aconf->port, maxsendq);
+ (void)fflush(stdout);
+ if (aconf->status & (CONF_SERVER_MASK|CONF_HUB|CONF_LEAF))
+ {
+ aconf->next = ctop;
+ ctop = aconf;
+ aconf = NULL;
+ }
+ }
+ printf("\n");
+ (void)close(fd);
+#ifdef M4_PREPROC
+ (void)wait(0);
+#endif
+ return ctop;
+}
+
+static aClass *get_class(cn)
+int cn;
+{
+ static aClass cls;
+ int i = numclasses - 1;
+
+ cls.class = -1;
+ for (; i >= 0; i--)
+ if (classarr[i] == cn)
+ {
+ cls.class = cn;
+ break;
+ }
+ if (i == -1)
+ (void)fprintf(stderr,"\tWARNING: class %d not found\n", cn);
+ return &cls;
+}
+
+static void new_class(cn)
+int cn;
+{
+ numclasses++;
+ if (classarr)
+ classarr = (int *)realloc(classarr, sizeof(int) * numclasses);
+ else
+ classarr = (int *)malloc(sizeof(int));
+ classarr[numclasses-1] = cn;
+}
+
+/*
+ * field breakup for ircd.conf file.
+ */
+static char *getfield(newline)
+char *newline;
+{
+ static char *line = NULL;
+ char *end, *field;
+
+ if (newline)
+ line = newline;
+ if (line == NULL)
+ return(NULL);
+
+ field = line;
+ if ((end = (char *)index(line,':')) == NULL)
+ {
+ line = NULL;
+ if ((end = (char *)index(field,'\n')) == NULL)
+ end = field + strlen(field);
+ }
+ else
+ line = end + 1;
+ *end = '\0';
+ return(field);
+}
+
+
+/*
+** read a string terminated by \r or \n in from a fd
+**
+** Created: Sat Dec 12 06:29:58 EST 1992 by avalon
+** Returns:
+** 0 - EOF
+** -1 - error on read
+** >0 - number of bytes returned (<=num)
+** After opening a fd, it is necessary to init dgets() by calling it as
+** dgets(x,y,0);
+** to mark the buffer as being empty.
+*/
+int dgets(fd, buf, num)
+int fd, num;
+char *buf;
+{
+ static char dgbuf[8192];
+ static char *head = dgbuf, *tail = dgbuf;
+ register char *s, *t;
+ register int n, nr;
+
+ /*
+ ** Sanity checks.
+ */
+ if (head == tail)
+ *head = '\0';
+ if (!num)
+ {
+ head = tail = dgbuf;
+ *head = '\0';
+ return 0;
+ }
+ if (num > sizeof(dgbuf) - 1)
+ num = sizeof(dgbuf) - 1;
+dgetsagain:
+ if (head > dgbuf)
+ {
+ for (nr = tail - head, s = head, t = dgbuf; nr > 0; nr--)
+ *t++ = *s++;
+ tail = t;
+ head = dgbuf;
+ }
+ /*
+ ** check input buffer for EOL and if present return string.
+ */
+ if (head < tail &&
+ ((s = index(head, '\n')) || (s = index(head, '\r'))) && s < tail)
+ {
+ n = MIN(s - head + 1, num); /* at least 1 byte */
+dgetsreturnbuf:
+ bcopy(head, buf, n);
+ head += n;
+ if (head == tail)
+ head = tail = dgbuf;
+ return n;
+ }
+
+ if (tail - head >= num) /* dgets buf is big enough */
+ {
+ n = num;
+ goto dgetsreturnbuf;
+ }
+
+ n = sizeof(dgbuf) - (tail - dgbuf) - 1;
+ nr = read(fd, tail, n);
+ if (nr == -1)
+ {
+ head = tail = dgbuf;
+ return -1;
+ }
+ if (!nr)
+ {
+ if (head < tail)
+ {
+ n = MIN(head - tail, num);
+ goto dgetsreturnbuf;
+ }
+ head = tail = dgbuf;
+ return 0;
+ }
+ tail += nr;
+ *tail = '\0';
+ for (t = head; (s = index(t, '\n')); )
+ {
+ if ((s > head) && (s > dgbuf))
+ {
+ t = s-1;
+ for (nr = 0; *t == '\\'; nr++)
+ t--;
+ if (nr & 1)
+ {
+ t = s+1;
+ s--;
+ nr = tail - t;
+ while (nr--)
+ *s++ = *t++;
+ tail -= 2;
+ *tail = '\0';
+ }
+ else
+ s++;
+ }
+ else
+ s++;
+ t = s;
+ }
+ *tail = '\0';
+ goto dgetsagain;
+}
+
+
+static int validate(top)
+aConfItem *top;
+{
+ Reg1 aConfItem *aconf, *bconf;
+ u_int otype, valid = 0;
+
+ if (!top)
+ return 0;
+
+ for (aconf = top; aconf; aconf = aconf->next)
+ {
+ if (aconf->status & CONF_MATCH)
+ continue;
+
+ if (aconf->status & CONF_SERVER_MASK)
+ {
+ if (aconf->status & CONF_CONNECT_SERVER)
+ otype = CONF_NOCONNECT_SERVER;
+ else if (aconf->status & CONF_NOCONNECT_SERVER)
+ otype = CONF_CONNECT_SERVER;
+
+ for (bconf = top; bconf; bconf = bconf->next)
+ {
+ if (bconf == aconf || !(bconf->status & otype))
+ continue;
+ if (bconf->class == aconf->class &&
+ !mycmp(bconf->name, aconf->name) &&
+ !mycmp(bconf->host, aconf->host))
+ {
+ aconf->status |= CONF_MATCH;
+ bconf->status |= CONF_MATCH;
+ break;
+ }
+ }
+ }
+ else
+ for (bconf = top; bconf; bconf = bconf->next)
+ {
+ if ((bconf == aconf) ||
+ !(bconf->status & CONF_SERVER_MASK))
+ continue;
+ if (!mycmp(bconf->name, aconf->name))
+ {
+ aconf->status |= CONF_MATCH;
+ break;
+ }
+ }
+ }
+
+ (void) fprintf(stderr, "\n");
+ for (aconf = top; aconf; aconf = aconf->next)
+ if (aconf->status & CONF_MATCH)
+ valid++;
+ else
+ (void)fprintf(stderr, "Unmatched %c:%s:%s:%s\n",
+ confchar(aconf->status), aconf->host,
+ aconf->passwd, aconf->name);
+ return valid ? 0 : -1;
+}
+
+static char confchar(status)
+u_int status;
+{
+ static char letrs[] = "QICNoOMKARYSLPHXT";
+ char *s = letrs;
+
+ status &= ~(CONF_MATCH|CONF_ILLEGAL);
+
+ for (; *s; s++, status >>= 1)
+ if (status & 1)
+ return *s;
+ return '-';
+}
+
+outofmemory()
+{
+ (void)write(2, "Out of memory\n", 14);
+ exit(-1);
+}
+
+
--- /dev/null
+#include <windows.h>
+#include "Cio.h"
+#include "CioFunc.h"
+#include "common.h"
+ID_CVS("$Id$");
+
+//
+// FUNCTION: Cio_Init(void)
+//
+// PURPOSE: Initializes window data and registers window class and other stuff
+//
+BOOL Cio_Init(HINSTANCE hInstance)
+{
+ WNDCLASS wc;
+
+ // Fill in window class structure with parameters that describe
+ // the main window.
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+ wc.lpfnWndProc = (WNDPROC)Cio_WndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 4;
+ wc.hInstance = hInstance;
+ wc.hIcon = NULL;
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = CIOCLASS;
+
+ if ( !RegisterClass(&wc) ) return FALSE;
+
+ return TRUE;
+}
--- /dev/null
+#include <windows.h>
+#include <memory.h>
+#include <stdio.h>
+#include <crtdbg.h>
+#include "Cio.h"
+#include "CioFunc.h"
+#include "common.h"
+ID_CVS("$Id$");
+
+CioLine *CioMakeLine(CioLine *Prev, CioLine *Next)
+{
+ CioLine *Line;
+
+ Line = LocalAlloc(LPTR, sizeof(CioLine));
+ _ASSERT(Line);
+ if ( Prev )
+ {
+ Prev->Next = Line;
+ Line->Prev = Prev;
+ }
+ if ( Next )
+ {
+ Next->Prev = Line;
+ Line->Next = Next;
+ }
+
+ return Line;
+}
+
+
+void CioRemoveLine(CioWndInfo *CWI, CioLine *Line)
+{
+ if ( Line->Next )
+ Line->Next->Prev = Line->Prev;
+ if ( Line->Prev )
+ Line->Prev->Next = Line->Next;
+ else
+ CWI->FirstLine = Line->Next;
+
+ if ( Line->Data )
+ LocalFree(Line->Data);
+ LocalFree(Line);
+}
+
+
+
+//
+// FUNCTION: Cio_Create(HANDLE, HWND, DWORD, int, int, int, int)
+//
+// PURPOSE: Creates main CIO window
+//
+HWND Cio_Create(HINSTANCE hInstance, HWND hParent, DWORD Style, int X, int Y, int W, int H)
+{
+ HWND hWnd;
+
+ if ( hParent == NULL )
+ return NULL;
+
+ hWnd = CreateWindow(CIOCLASS, NULL, WS_CHILD | WS_VSCROLL | Style,
+ X, Y, W, H, hParent, NULL, hInstance, NULL);
+
+ return hWnd;
+}
+
+
+//
+// FUNCTION: Cio_WndProc(HWND, unsigned, WORD, LONG)
+//
+// PURPOSE: Processes messages for a CIO window.
+//
+LRESULT CALLBACK Cio_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ DWORD Style;
+
+ switch (message)
+ {
+ case WM_CREATE:
+ return Cio_WndCreate(hWnd);
+
+ case WM_RBUTTONDOWN: // RightClick in windows client area...
+ return 0;
+
+ case WM_PAINT:
+ return Cio_WndPaint(hWnd);
+
+ case WM_SIZE:
+ Style = GetWindowLong(GetParent(hWnd), GWL_STYLE);
+ if ( Style & WS_MINIMIZE )
+ return 0;
+ return Cio_WndSize(hWnd, lParam);
+
+ case WM_VSCROLL:
+ return Cio_WndScroll(hWnd, wParam);
+
+ case WM_DESTROY:
+ return Cio_WndDestroy(hWnd);
+
+ case WM_SETFONT:
+ return Cio_SetFont(hWnd, wParam);
+
+ case CIO_ADDSTRING:
+ return Cio_WndAddString(hWnd, wParam, (char *)lParam);
+
+ default:
+ return (DefWindowProc(hWnd, message, wParam, lParam));
+ }
+ return (0);
+}
+
+
+BOOL Cio_WndCreate(HWND hWnd)
+{
+ CioWndInfo *CWI;
+ LOGFONT lfFont;
+ TEXTMETRIC tm;
+ HDC hdc;
+
+ CWI = LocalAlloc(LPTR, sizeof(CioWndInfo));
+ _ASSERT(CWI);
+ lfFont.lfHeight = 12;
+ lfFont.lfWidth = 0;
+ lfFont.lfEscapement = 0;
+ lfFont.lfOrientation = 0;
+ lfFont.lfWeight = 400;
+ lfFont.lfItalic = 0;
+ lfFont.lfUnderline = 0;
+ lfFont.lfStrikeOut = 0;
+ lfFont.lfCharSet = ANSI_CHARSET;
+ lfFont.lfOutPrecision = OUT_STRING_PRECIS;
+ lfFont.lfClipPrecision = CLIP_STROKE_PRECIS;
+ lfFont.lfQuality = DRAFT_QUALITY;
+ lfFont.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
+ wsprintf(lfFont.lfFaceName, "FixedSys");
+
+ CWI->hFont = CreateFontIndirect(&lfFont);
+
+ hdc = GetDC(hWnd);
+ SelectObject(hdc, CWI->hFont);
+ GetTextMetrics(hdc, &tm);
+ ReleaseDC(hWnd, hdc);
+
+ CWI->XChar = tm.tmAveCharWidth;
+ CWI->YChar = tm.tmHeight + tm.tmExternalLeading;
+
+ CWI->FirstLine = CWI->CurLine = CioMakeLine(NULL, NULL);
+ CWI->Lines=0;
+
+ SetWindowLong(hWnd, GWL_USER, (DWORD)CWI);
+
+ return 0;
+}
+
+
+BOOL Cio_WndPaint(HWND hWnd)
+{
+ PAINTSTRUCT ps;
+ CioWndInfo *CWI;
+ HDC hdc;
+ HFONT hOldFont;
+ CioLine *Line;
+ RECT rect;
+ int nCol, nEndCol, nMaxCol, nRow, nEndRow, nBegCol, nCount, i=0;
+ int nVertPos, nHorzPos, nOff, nBegOff, NewColorAt=0;
+ BYTE Red, Green, Blue, NewColor=0, UnderLine=0;
+ HPEN hpen;
+
+
+ CWI = (CioWndInfo *)GetWindowLong(hWnd, GWL_USER);
+ hdc = BeginPaint(hWnd, &ps);
+
+ hOldFont = SelectObject(hdc, CWI->hFont);
+ rect = ps.rcPaint;
+ nCol = max(0, rect.left / CWI->XChar);
+ nEndCol = rect.right / CWI->XChar;
+ nEndCol = min(CWI->Width, nEndCol+1);
+ nEndRow = max(0, rect.top / CWI->YChar);
+ nRow = rect.bottom / CWI->YChar;
+ nRow = min(CWI->Height, nRow+1);
+
+ nBegOff = nCol;
+ nBegCol = nCol;
+
+ /*
+ * Find the first line to use, and work up from there.
+ */
+ Line = CWI->FirstLine;
+ while ( Line && i < CWI->Scroll )
+ {
+ if ( Line->Data )
+ i++;
+ Line = Line->Next;
+ }
+ i = 0;
+ while ( Line && i < (CWI->Height-nRow) )
+ {
+ if ( Line->Data )
+ i++;
+ Line = Line->Next;
+ }
+
+ for ( ; nRow >= nEndRow; nRow-- )
+ {
+ UnderLine=0;
+ while ( Line && !Line->Data )
+ Line = Line->Next;
+ if ( !Line )
+ continue;
+
+ nMaxCol = Line->Len;
+ nOff = nBegOff;
+ nCol = 0;
+ nCount = 0;
+ for ( i = 0; i < Line->Len; i++ )
+ {
+ if ( Line->Data[i] == 0 )
+ {
+ Red = Line->Data[i+1];
+ Green = Line->Data[i+2];
+ Blue = Line->Data[i+3];
+ SetTextColor(hdc, RGB(Red, Green, Blue));
+ SetBkColor(hdc, RGB(255, 255, 255));
+ i += 3;
+ nCol += 4;
+ continue;
+ }
+ if ( nCount >= nBegCol )
+ break;
+ nCol++;
+ nCount++;
+ }
+ if ( i >= Line->Len )
+ continue;
+
+ for ( ; nCol <= nMaxCol; nCol++ )
+ {
+ nCount = nMaxCol-nCol;
+ for ( i = 0; i < (nMaxCol-nCol); i++ )
+ {
+ if ( Line->Data[nCol+i] == 0x1F )
+ {
+ nCount = i;
+ if ( UnderLine == 0 )
+ {
+ UnderLine = 1;
+ break;
+ }
+ if ( UnderLine == 1 )
+ {
+ UnderLine = 2;
+ break;
+ }
+ break;
+ }
+ if ( Line->Data[nCol+i] == 0x0F )
+ {
+ nCount = i;
+ UnderLine = 0;
+ break;
+ }
+ if ( Line->Data[nCol+i] == 0 )
+ {
+ NewColor = 1;
+ NewColorAt = nCol+i;
+ nCount = i;
+ i += 3;
+ break;
+ }
+ }
+
+ if ( nCount )
+ {
+ nVertPos = nRow * CWI->YChar - CWI->YChar +
+ CWI->YJunk;
+ nHorzPos = nOff * CWI->XChar;
+ rect.top = nVertPos;
+ rect.bottom = nVertPos + CWI->YChar;
+ rect.left = nHorzPos;
+ rect.right = nHorzPos + (CWI->XChar*nCount);
+ SetBkMode(hdc, OPAQUE);
+
+ ExtTextOut(hdc, nHorzPos, nVertPos, ETO_OPAQUE,
+ &rect, (LPSTR) Line->Data+nCol,
+ nCount, NULL);
+ nOff += nCount;
+
+ if ( UnderLine == 2 )
+ {
+ hpen = CreatePen(PS_SOLID, 0,
+ RGB(Red, Green, Blue));
+ SelectObject(hdc, hpen);
+ MoveToEx(hdc, (int)rect.left,
+ (int)rect.bottom-1,
+ (LPPOINT)NULL);
+ LineTo(hdc, (int)rect.right,
+ (int)rect.bottom-1);
+ DeleteObject(hpen);
+ UnderLine = 0;
+ }
+ }
+ if ( UnderLine == 1 )
+ UnderLine = 2;
+
+ nCol += i;
+ if ( NewColor )
+ {
+ Red = Line->Data[NewColorAt+1];
+ Green = Line->Data[NewColorAt+2];
+ Blue = Line->Data[NewColorAt+3];
+ SetTextColor(hdc, RGB(Red, Green, Blue));
+ SetBkColor(hdc, RGB(255, 255, 255));
+ NewColor = 0;
+ }
+ }
+ Line = Line->Next;
+ }
+
+ SelectObject(hdc, hOldFont);
+ EndPaint(hWnd, &ps);
+ return 0;
+}
+
+
+BOOL Cio_WndDestroy(HWND hWnd)
+{
+ CioWndInfo *CWI;
+
+ CWI = (CioWndInfo *)GetWindowLong(hWnd, GWL_USER);
+ while ( CWI->FirstLine )
+ CioRemoveLine(CWI, CWI->FirstLine);
+
+ DeleteObject(CWI->hFont);
+ LocalFree(CWI);
+
+ return 0;
+}
+
+
+int Cio_WndAddString(HWND hWnd, int Len, char *Buffer)
+{
+ CioWndInfo *CWI;
+ CioLine *Line;
+ int TLen=0, DLen=0, Loop=0, LastSpace=0, Scrolled=0, Pad=0;
+ BYTE Red=0, Grn=0, Blu=0;
+
+
+ CWI = (CioWndInfo *)GetWindowLong(hWnd, GWL_USER);
+
+ if ( CWI->ScrollMe == TRUE )
+ {
+ Cio_Scroll(hWnd, CWI, 1);
+ Scrolled++;
+ CWI->ScrollMe = FALSE;
+ }
+ if ( Buffer[Len-1] == '\r' )
+ {
+ CWI->ScrollMe = TRUE;
+ Len-=1;
+ }
+
+ while ( Len )
+ {
+ /*
+ * Check the current line to see if we have room to tack
+ * on our string to the end of. If not, put as much as
+ * possible on, then scroll up a new line.
+ */
+ TLen=DLen=0;
+ Line = CWI->FirstLine;
+ while ( TLen < Line->Len )
+ {
+ if ( Line->Data[TLen] == 0 )
+ {
+ TLen+=4;
+ continue;
+ }
+ TLen+=1;
+ DLen+=1;
+ }
+ Loop=TLen=0;
+ while ( TLen < Len )
+ {
+ if ( Buffer[TLen] == 0 )
+ {
+ TLen+=4;
+ continue;
+ }
+ TLen+=1;
+ Loop+=1;
+ }
+ if ( DLen+Loop > CWI->Width )
+ {
+ Cio_Scroll(hWnd, CWI, 1);
+ Scrolled++;
+ Loop=TLen=0;
+ do
+ {
+ if ( Buffer[TLen] == 0 )
+ {
+ Red = Buffer[TLen+1];
+ Grn = Buffer[TLen+2];
+ Blu = Buffer[TLen+3];
+ TLen+=4;
+ continue;
+ }
+ if ( TLen >= Len || DLen+Loop >= CWI->Width )
+ break;
+ if ( Buffer[TLen] == ' ' )
+ LastSpace = TLen;
+ TLen+=1;
+ Loop+=1;
+ } while ( TLen < Len && DLen+Loop < CWI->Width );
+
+ if ( TLen != Len && Buffer[TLen] != ' ' &&
+ LastSpace && (LastSpace-TLen) < 16 )
+ TLen = LastSpace;
+
+ if ( Line->Data != NULL )
+ {
+ Line->Data = LocalReAlloc(Line->Data,
+ Line->Len+TLen+Pad, LMEM_MOVEABLE);
+ _ASSERT(Line->Data);
+ memset(Line->Data, ' ', Pad);
+ memmove(Line->Data+Line->Len+Pad, Buffer, TLen);
+ Line->Len += TLen + Pad;
+ }
+ else
+ {
+ if ( Buffer[0] == 0 )
+ {
+ Line->Data = LocalAlloc(LPTR, TLen+Pad);
+ _ASSERT(Line->Data);
+ memset(Line->Data, ' ', Pad);
+ memmove(Line->Data+Pad, Buffer, TLen);
+ Line->Len = TLen + Pad;
+ }
+ else
+ {
+ Line->Data = LocalAlloc(LPTR, TLen+4+Pad);
+ _ASSERT(Line->Data);
+ memset(Line->Data+4, ' ', Pad);
+ memmove(Line->Data+4+Pad, Buffer, TLen);
+ Line->Len = TLen+4+Pad;
+ Line->Data[0] = 0;
+ Line->Data[1] = Red;
+ Line->Data[2] = Grn;
+ Line->Data[3] = Blu;
+ }
+ }
+
+ if ( TLen == LastSpace )
+ TLen++;
+ Pad = 3;
+ Len -= TLen;
+ memmove(Buffer, Buffer+TLen, Len);
+ if ( Buffer[0] == '\r' && Len == 1 )
+ Len=0;
+ continue;
+ } /* if ( DLen+Loop > CWI->Width ) */
+
+ Line = CWI->FirstLine;
+ if ( Line->Data != NULL )
+ {
+ Line->Data = LocalReAlloc(Line->Data, Line->Len+TLen+Pad,
+ LMEM_MOVEABLE);
+ _ASSERT(Line->Data);
+ memset(Line->Data, ' ', Pad);
+ memmove(Line->Data+Line->Len+Pad, Buffer, Len);
+ Line->Len += Len + Pad;
+ }
+ else
+ {
+ if ( Buffer[0] == 0 )
+ {
+ Line->Data = LocalAlloc(LPTR, Len+Pad);
+ _ASSERT(Line->Data);
+ memset(Line->Data, ' ', Pad);
+ memmove(Line->Data+Pad, Buffer, Len);
+ Line->Len = Len + Pad;
+ }
+ else
+ {
+ Line->Data = LocalAlloc(LPTR, Len+4+Pad);
+ _ASSERT(Line->Data);
+ memset(Line->Data+4, ' ', Pad);
+ memmove(Line->Data+4+Pad, Buffer, Len);
+ Line->Len = Len+4+Pad;
+ Line->Data[0] = 0;
+ Line->Data[1] = Red;
+ Line->Data[2] = Grn;
+ Line->Data[3] = Blu;
+ }
+ }
+
+ break;
+ } /* while (Len) */
+
+ if ( !CWI->Scroll )
+ {
+ RECT rc;
+
+ rc.left = rc.top = 0;
+ rc.right = CWI->Width*CWI->XChar;
+ rc.bottom = CWI->Height*CWI->YChar+CWI->YJunk;
+ ScrollWindow(hWnd, 0, -(Scrolled*CWI->YChar), &rc, NULL);
+ rc.top = (CWI->Height-Scrolled)*CWI->YChar+CWI->YJunk;
+ if ( rc.top < 0 )
+ rc.top = 0;
+ return Scrolled;
+ }
+ return 0;
+}
+
+
+BOOL Cio_WndSize(HWND hWnd, LPARAM lParam)
+{
+ CioWndInfo *CWI;
+ SCROLLINFO si;
+
+ CWI = (CioWndInfo *)GetWindowLong(hWnd, GWL_USER);
+
+ CWI->Scroll = 0;
+ CWI->Width = LOWORD(lParam) / CWI->XChar;
+ CWI->Height = HIWORD(lParam) / CWI->YChar;
+ CWI->YJunk = HIWORD(lParam) - (CWI->Height * CWI->YChar);
+
+ InvalidateRect(hWnd, NULL, TRUE);
+
+ /* Set the Scroll Bar information. */
+
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS | SIF_DISABLENOSCROLL;
+ si.nMin = 1;
+ si.nMax = CWI->Lines;
+ si.nPage = CWI->Height-1;
+ si.nPos = si.nMax;
+ SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
+
+ return 0;
+}
+
+
+BOOL Cio_WndScroll(HWND hWnd, WPARAM wParam)
+{
+ CioWndInfo *CWI;
+ SCROLLINFO si;
+ int Amnt=0, nPos=0;
+
+ CWI = (CioWndInfo *)GetWindowLong(hWnd, GWL_USER);
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
+ GetScrollInfo(hWnd, SB_VERT, &si);
+
+ si.nMax-=si.nPage;
+ si.nMax+=si.nMin;
+ nPos = si.nPos;
+
+ switch(LOWORD (wParam))
+ {
+ case SB_PAGEUP:
+ Amnt = -(int)si.nPage;
+ break;
+
+ case SB_PAGEDOWN:
+ Amnt = si.nPage;
+ break;
+
+ case SB_LINEUP:
+ Amnt = -(int)1;
+ break;
+
+ case SB_LINEDOWN:
+ Amnt = 1;
+ break;
+
+ case SB_THUMBTRACK:
+ break;
+ }
+
+ if ( Amnt )
+ {
+ nPos += Amnt;
+
+ if ( nPos < si.nMin )
+ {
+ Amnt -= nPos - si.nMin;
+ nPos = si.nMin;
+ }
+
+ if ( nPos > si.nMax )
+ {
+ Amnt -= nPos - si.nMax;
+ nPos = si.nMax;
+ }
+
+ if ( Amnt )
+ {
+ SetScrollPos(hWnd, SB_VERT, nPos, TRUE);
+ CWI->Scroll = si.nMax-nPos;
+ InvalidateRect(hWnd, NULL, TRUE);
+ }
+ }
+
+ return 0;
+}
+
+
+void Cio_Scroll(HWND hWnd, CioWndInfo *CWI, int Scroll)
+{
+ int i=0, KillAmt=0, StopAt=0;
+ SCROLLINFO si;
+ CioLine *Line, *Next;
+
+ if ( CWI->Lines+Scroll > 500 && !CWI->Scroll )
+ {
+ Line = CWI->FirstLine;
+ KillAmt = max((CWI->Lines+Scroll)-500, 20);
+ for ( i = 0; Line && i < (CWI->Lines-KillAmt); i++ )
+ Line = Line->Next;
+
+ while ( Line )
+ {
+ Next = Line->Next;
+ CioRemoveLine(CWI, Line);
+ Line = Next;
+ }
+ CWI->Lines -= KillAmt;
+ }
+
+ for ( i = 0; i < Scroll; i++ )
+ CWI->FirstLine = CioMakeLine(NULL, CWI->FirstLine);
+
+ CWI->Lines+=Scroll;
+ if ( CWI->Scroll )
+ CWI->Scroll += Scroll;
+
+ /* Set the Scroll Bar information. */
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS | SIF_DISABLENOSCROLL;
+ GetScrollInfo(hWnd, SB_VERT, &si);
+
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_RANGE | SIF_POS | SIF_PAGE | SIF_DISABLENOSCROLL;
+ si.nMin = 1;
+ si.nMax = CWI->Lines;
+ si.nPage = CWI->Height-1;
+ si.nPos = CWI->Lines - si.nPage - CWI->Scroll;
+ SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
+}
+
+
+BOOL Cio_PrintF(HWND hWnd, char *InBuf, ...)
+{
+ CioWndInfo *CWI;
+ va_list argptr;
+ char *Buffer=NULL, *Ptr = NULL;
+ DWORD Len=0, TLen, Off;
+ int Scrolled=0;
+ RECT rc;
+
+
+ if ( (Buffer = LocalAlloc(LPTR, 16384)) == NULL )
+ return FALSE;
+
+ va_start(argptr, InBuf);
+ Len = vsprintf(Buffer, InBuf, argptr);
+ va_end(argptr);
+ if ( Len == 0 )
+ {
+ LocalFree(Buffer);
+ return FALSE;
+ }
+
+ CWI = (CioWndInfo *)GetWindowLong(hWnd, GWL_USER);
+ Ptr = memchr(Buffer, 0, TLen=Len);
+ while ( Ptr != NULL )
+ {
+ Off = Ptr-Buffer;
+
+ CWI->FR = Buffer[Off+1];
+ CWI->FG = Buffer[Off+2];
+ CWI->FB = Buffer[Off+3];
+
+ Off += 4;
+ TLen = Len-Off;
+ if ( TLen == 0 )
+ break;
+ Ptr = memchr(Buffer+Off, 0, TLen);
+ }
+ if ( Buffer[0] != 0 )
+ {
+ memmove(Buffer+4, Buffer, Len);
+ Len+=4;
+ Buffer[0] = 0;
+ Buffer[1] = CWI->FR;
+ Buffer[2] = CWI->FG;
+ Buffer[3] = CWI->FB;
+ }
+
+ rc.left = 0;
+ rc.right = CWI->Width*CWI->XChar;
+ rc.top = rc.bottom = CWI->Height*CWI->YChar;
+
+ do
+ {
+ Ptr = memchr(Buffer, '\r', Len);
+ if ( Ptr )
+ TLen = (Ptr-Buffer)+1;
+ else
+ TLen = Len;
+ if ( Buffer[0] != '\r' || CWI->ScrollMe == FALSE )
+ {
+ Scrolled = Cio_WndAddString(hWnd, TLen, Buffer);
+ rc.top -= Scrolled*CWI->YChar;
+ }
+ Len -= TLen;
+ memmove(Buffer, Buffer+TLen, Len);
+ } while ( Len );
+
+ if ( rc.top < rc.bottom )
+ {
+ if ( rc.top < 0 )
+ rc.top = 0;
+ InvalidateRect(hWnd, &rc, TRUE);
+ UpdateWindow(hWnd);
+ }
+ LocalFree(Buffer);
+ return TRUE;
+}
+
+
+BOOL Cio_Puts(HWND hWnd, char *InBuf, DWORD Len)
+{
+ CioWndInfo *CWI;
+ char *Buffer = NULL, *Ptr = NULL;
+ DWORD TLen, Off;
+ int Scrolled=0;
+ RECT rc;
+
+
+ if ( !Len )
+ return FALSE;
+
+ if ( (Buffer = LocalAlloc(LPTR, 16384)) == NULL )
+ return FALSE;
+ memmove(Buffer, InBuf, Len);
+
+ CWI = (CioWndInfo *)GetWindowLong(hWnd, GWL_USER);
+ Ptr = memchr(Buffer, 0, TLen=Len);
+ while ( Ptr != NULL )
+ {
+ Off = Ptr-Buffer;
+
+ CWI->FR = Buffer[Off+1];
+ CWI->FG = Buffer[Off+2];
+ CWI->FB = Buffer[Off+3];
+
+ Off += 4;
+ TLen = Len-Off;
+ if ( TLen == 0 )
+ break;
+ Ptr = memchr(Buffer+Off, 0, TLen);
+ }
+ if ( Buffer[0] != 0 )
+ {
+ memmove(Buffer+4, Buffer, Len);
+ Len+=4;
+ Buffer[0] = 0;
+ Buffer[1] = CWI->FR;
+ Buffer[2] = CWI->FG;
+ Buffer[3] = CWI->FB;
+ }
+
+ rc.left = 0;
+ rc.right = CWI->Width*CWI->XChar;
+ rc.top = rc.bottom = CWI->Height*CWI->YChar;
+
+ do
+ {
+ Ptr = memchr(Buffer, '\r', Len);
+ if ( Ptr )
+ TLen = (Ptr-Buffer)+1;
+ else
+ TLen = Len;
+ if ( Buffer[0] != '\r' || CWI->ScrollMe == FALSE )
+ {
+ Scrolled = Cio_WndAddString(hWnd, TLen, Buffer);
+ rc.top -= Scrolled*CWI->YChar;
+ }
+ Len -= TLen;
+ memmove(Buffer, Buffer+TLen, Len);
+ } while ( Len );
+
+ if ( rc.top < rc.bottom )
+ {
+ if ( rc.top < 0 )
+ rc.top = 0;
+ InvalidateRect(hWnd, &rc, TRUE);
+ UpdateWindow(hWnd);
+ }
+ LocalFree(Buffer);
+ return TRUE;
+}
+
+
+BOOL Cio_SetFont(HWND hWnd, WPARAM wParam)
+{
+ CioWndInfo *CWI;
+ TEXTMETRIC tm;
+ HFONT hFont = (HFONT)wParam;
+ HDC hdc;
+ RECT rc;
+
+
+ CWI = (CioWndInfo *)GetWindowLong(hWnd, GWL_USER);
+
+ if ( CWI->hFont )
+ DeleteObject(CWI->hFont);
+ CWI->hFont = hFont;
+ hdc = GetDC(hWnd);
+ SelectObject(hdc, CWI->hFont);
+ GetTextMetrics(hdc, &tm);
+ ReleaseDC(hWnd, hdc);
+
+ CWI->XChar = tm.tmAveCharWidth;
+ CWI->YChar = tm.tmHeight + tm.tmExternalLeading;
+
+ /*
+ * Send resize message so it will pick up the new font size.
+ */
+ GetClientRect(hWnd, &rc);
+ SendMessage(hWnd, WM_SIZE, 0, MAKELPARAM(rc.right-rc.left, rc.bottom-rc.top));
+ InvalidateRect(hWnd, NULL, TRUE);
+
+ return TRUE;
+}
+
--- /dev/null
+/*
+ * IRC - Internet Relay Chat, ircd/class.c
+ * Copyright (C) 1990 Darren Reed
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include "struct.h"
+#include "common.h"
+#include "numeric.h"
+#include "h.h"
+
+ID_CVS("$Id$");
+ID_Copyright("(C) 1990 Darren Reed");
+ID_Notes("1.4 6/28/93");
+
+
+#define BAD_CONF_CLASS -1
+#define BAD_PING -2
+#define BAD_CLIENT_CLASS -3
+
+aClass *classes;
+
+int get_conf_class(aconf)
+aConfItem *aconf;
+{
+ if ((aconf) && Class(aconf))
+ return (ConfClass(aconf));
+
+ Debug((DEBUG_DEBUG,"No Class For %s",
+ (aconf) ? aconf->name : "*No Conf*"));
+
+ return (BAD_CONF_CLASS);
+
+}
+
+static int get_conf_ping(aconf)
+aConfItem *aconf;
+{
+ if ((aconf) && Class(aconf))
+ return (ConfPingFreq(aconf));
+
+ Debug((DEBUG_DEBUG,"No Ping For %s",
+ (aconf) ? aconf->name : "*No Conf*"));
+
+ return (BAD_PING);
+}
+
+
+
+int get_client_class(acptr)
+aClient *acptr;
+{
+ Reg1 Link *tmp;
+ Reg2 aClass *cl;
+ int i = 0, retc = BAD_CLIENT_CLASS;
+
+ if (acptr && !IsMe(acptr) && (acptr->confs))
+ for (tmp = acptr->confs; tmp; tmp = tmp->next)
+ {
+ if (!tmp->value.aconf ||
+ !(cl = tmp->value.aconf->class))
+ continue;
+ if (Class(cl) > retc)
+ retc = Class(cl);
+ }
+
+ Debug((DEBUG_DEBUG,"Returning Class %d For %s",retc,acptr->name));
+
+ return (retc);
+}
+
+int get_client_ping(acptr)
+aClient *acptr;
+{
+ int ping = 0, ping2;
+ aConfItem *aconf;
+ Link *link;
+
+ link = acptr->confs;
+
+ if (link)
+ while (link)
+ {
+ aconf = link->value.aconf;
+ if (aconf->status & (CONF_CLIENT|CONF_CONNECT_SERVER|
+ CONF_NOCONNECT_SERVER))
+ {
+ ping2 = get_conf_ping(aconf);
+ if ((ping2 != BAD_PING) && ((ping > ping2) ||
+ !ping))
+ ping = ping2;
+ }
+ link = link->next;
+ }
+ else
+ {
+ ping = PINGFREQUENCY;
+ Debug((DEBUG_DEBUG,"No Attached Confs"));
+ }
+ if (ping <= 0)
+ ping = PINGFREQUENCY;
+ Debug((DEBUG_DEBUG,"Client %s Ping %d", acptr->name, ping));
+ return (ping);
+}
+
+int get_con_freq(clptr)
+aClass *clptr;
+{
+ if (clptr)
+ return (ConFreq(clptr));
+ else
+ return (CONNECTFREQUENCY);
+}
+
+/*
+ * When adding a class, check to see if it is already present first.
+ * if so, then update the information for that class, rather than create
+ * a new entry for it and later delete the old entry.
+ * if no present entry is found, then create a new one and add it in
+ * immeadiately after the first one (class 0).
+ */
+void add_class(class, ping, confreq, maxli, sendq)
+int class, ping, confreq, maxli;
+long sendq;
+{
+ aClass *t, *p;
+
+ t = find_class(class);
+ if ((t == classes) && (class != 0))
+ {
+ p = (aClass *)make_class();
+ NextClass(p) = NextClass(t);
+ NextClass(t) = p;
+ }
+ else
+ p = t;
+ Debug((DEBUG_DEBUG,
+ "Add Class %d: p %x t %x - cf: %d pf: %d ml: %d sq: %l",
+ class, p, t, confreq, ping, maxli, sendq));
+ Class(p) = class;
+ ConFreq(p) = confreq;
+ PingFreq(p) = ping;
+ MaxLinks(p) = maxli;
+ MaxSendq(p) = (sendq > 0) ? sendq : MAXSENDQLENGTH;
+ if (p != t)
+ Links(p) = 0;
+}
+
+aClass *find_class(cclass)
+int cclass;
+{
+ aClass *cltmp;
+
+ for (cltmp = FirstClass(); cltmp; cltmp = NextClass(cltmp))
+ if (Class(cltmp) == cclass)
+ return cltmp;
+ return classes;
+}
+
+void check_class()
+{
+ Reg1 aClass *cltmp, *cltmp2;
+
+ Debug((DEBUG_DEBUG, "Class check:"));
+
+ for (cltmp2 = cltmp = FirstClass(); cltmp; cltmp = NextClass(cltmp2))
+ {
+ Debug((DEBUG_DEBUG,
+ "Class %d : CF: %d PF: %d ML: %d LI: %d SQ: %ld",
+ Class(cltmp), ConFreq(cltmp), PingFreq(cltmp),
+ MaxLinks(cltmp), Links(cltmp), MaxSendq(cltmp)));
+ if (MaxLinks(cltmp) < 0)
+ {
+ NextClass(cltmp2) = NextClass(cltmp);
+ if (Links(cltmp) <= 0)
+ free_class(cltmp);
+ }
+ else
+ cltmp2 = cltmp;
+ }
+}
+
+void initclass()
+{
+ classes = (aClass *)make_class();
+
+ Class(FirstClass()) = 0;
+ ConFreq(FirstClass()) = CONNECTFREQUENCY;
+ PingFreq(FirstClass()) = PINGFREQUENCY;
+ MaxLinks(FirstClass()) = MAXIMUM_LINKS;
+ MaxSendq(FirstClass()) = MAXSENDQLENGTH;
+ Links(FirstClass()) = 0;
+ NextClass(FirstClass()) = NULL;
+}
+
+void report_classes(sptr)
+aClient *sptr;
+{
+ Reg1 aClass *cltmp;
+
+ for (cltmp = FirstClass(); cltmp; cltmp = NextClass(cltmp))
+ sendto_one(sptr, rpl_str(RPL_STATSYLINE), me.name, sptr->name,
+ 'Y', Class(cltmp), PingFreq(cltmp), ConFreq(cltmp),
+ MaxLinks(cltmp), MaxSendq(cltmp));
+}
+
+long get_sendq(cptr)
+aClient *cptr;
+{
+ Reg1 int sendq = MAXSENDQLENGTH, retc = BAD_CLIENT_CLASS;
+ Reg2 Link *tmp;
+ Reg2 aClass *cl;
+
+ if (cptr && !IsMe(cptr) && (cptr->confs))
+ for (tmp = cptr->confs; tmp; tmp = tmp->next)
+ {
+ if (!tmp->value.aconf ||
+ !(cl = tmp->value.aconf->class))
+ continue;
+ if (Class(cl) > retc)
+ sendq = MaxSendq(cl);
+ }
+ return sendq;
+}
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, src/cloak.c
+ * (C) VirtualWorld code made originally by RogerY (rogery@austnet.org)
+ * Some coding by Potvin (potvin@shadownet.org)
+ * Modified by Stskeeps with some TerraX codebits
+ * TerraX (devcom@terrax.net) - great job guys!
+ * Stskeeps (stskeeps@tspre.org)
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+#ifdef lint
+static char sccxid[] = "@(#)cloak.c 9.00 7/12/99 UnrealIRCd";
+#endif
+*/
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#include "numeric.h"
+#include "msg.h"
+#include "channel.h"
+#include "userload.h"
+#include <sys/stat.h>
+#include <fcntl.h>
+#ifndef _WIN32
+#include <utmp.h>
+#endif
+#include "h.h"
+
+ID_CVS("$Id$");
+
+// #define iNAH /* networks.h now */
+/* Hidden host code below */
+
+#define MAXVIRTSIZE (3 + 5 + 1)
+#define HASHVAL_TOTAL 30011
+#define HASHVAL_PARTIAL 211
+
+extern aClient me;
+extern int seed;
+int match(char *, char *), find_exception(char *);
+
+extern unsigned char tolowertab[];
+
+int str2array(char **pparv, char *string, char *delim)
+{
+ char *tok;
+ int pparc=0;
+
+ tok=(char *) strtok((char *) string,delim);
+ while(tok != NULL)
+ {
+ pparv[pparc++]=tok;
+ tok= (char *) strtok((char *) NULL,(char *) delim);
+ }
+
+ return pparc;
+}
+
+
+void truncstring(char *stringvar, int firstlast, int amount){
+ if (firstlast)
+ {
+ stringvar+=amount;
+ *stringvar=0;
+ stringvar-=amount;
+ }
+ else
+ {
+ stringvar+=strlen(stringvar);
+ stringvar-=amount;
+ }
+}
+
+#define B_BASE 1000
+
+int Maskchecksum (char *data, int len)
+{
+ int i;
+ int j;
+
+ j=0;
+ for (i=0 ; i<len ; i++)
+ {
+ j += *data++ * (i < 16 ? (i+1)*(i+1) : i*(i-15));
+ }
+
+ return (j+B_BASE)%0xffff;
+}
+
+
+/* hidehost
+ * command takes the realhost of a user
+ * and changes the content of it.
+ * new hidehost by vmlinuz
+ * added some extra fixes by stskeeps
+ * originally based on TerraIRCd
+ */
+
+char *hidehost (char *s, int useless)
+{
+// static char mask[128];
+ char *mask;
+ static char ipmask[64];
+ int csum;
+ char *dot,*tmp;
+ char *cp;
+ int i, isdns;
+ int dots = 0;
+
+ mask = MyMalloc(129);
+ memset (mask, 0, 128);
+
+ csum = Maskchecksum (s, strlen(s));
+
+ if (strlen (s) > 127) /* this isn't likely to happen: s is limited to HOSTLEN+1 (64) */
+ {
+ s[128] = 0;
+ }
+
+ isdns = 0;
+ cp = s;
+ for (i=0; i < strlen(s); i++)
+ {
+ if (*cp == '.') {
+ dots++;
+ }
+ cp++;
+ }
+
+ for (i=0 ; i<strlen(s) ; i++)
+ {
+ if (s[i] == '.') {
+ continue;
+ }
+
+ if (isalpha(s[i]))
+ {
+ isdns = 1;
+ break;
+ }
+ }
+
+ if (isdns)
+ {
+ /* it is a resolved yes.. */
+ if (dots == 1) { /* mystro.org f.x */
+ sprintf(mask, "%s%c%d.%s",
+ hidden_host,
+ (csum < 0 ? '=' : '-'),
+ (csum < 0 ? -csum : csum), s);
+ }
+ if (dots == 0) { /* localhost */
+ sprintf(mask, "%s%c%d",
+ s,
+ (csum < 0 ? '=' : '-'),
+ (csum < 0 ? -csum : csum));
+ }
+
+ if (dots > 1) {
+ dot = (char *) strchr((char *) s, '.');
+
+ /* mask like *<first dot> */
+ sprintf(mask, "%s%c%d.%s",
+ hidden_host,
+ (csum < 0 ? '=' : '-'),
+ (csum < 0 ? -csum : csum), dot+1);
+ }
+ }
+ else
+ {
+ strncpy(ipmask, s, sizeof(ipmask));
+ ipmask[sizeof(ipmask)-1]='\0'; /* safety check */
+ dot = (char *) strrchr((char *) ipmask, '.');
+ *dot = '\0';
+
+ if (dot == NULL) /* dot should never be NULL: IP needs dots */
+ sprintf (mask, "%s%c%i",
+ hidden_host,
+ (csum < 0 ? '=' : '-'),
+ (csum < 0 ? -csum : csum));
+ else
+ sprintf (mask, "%s.%s%c%i",
+ ipmask,
+ hidden_host,
+ (csum < 0 ? '=' : '-'),
+ (csum < 0 ? -csum : csum));
+ }
+
+ok1:
+ return mask;
+}
+
+
+/* Regular user host */
+void make_virthost(char *curr, char *new)
+{
+ char *mask;
+ if (curr == NULL)
+ return;
+ if (new == NULL)
+ return;
+
+ mask = hidehost(curr, 0);
+
+ strncpyzt(new, mask, HOSTLEN); /* */
+ return;
+}
+
+/* Netadmin host */
+void make_netadminhost(char *new)
+{
+ char tmpnew[HOSTLEN];
+
+#ifndef iNAH2
+ sprintf(tmpnew, "%s", netadmin_host);
+ strncpyzt(new, tmpnew, HOSTLEN);
+#endif
+ return;
+
+}
+/* Coadmin host */
+void make_coadminhost(char *new)
+{
+ char tmpnew[HOSTLEN];
+
+#ifndef iNAH2
+ sprintf(tmpnew, "%s", coadmin_host);
+ strncpyzt(new, tmpnew, HOSTLEN);
+#endif
+ return;
+}
+/* Techadmin host */
+void make_techadminhost(char *new)
+{
+ char tmpnew[HOSTLEN];
+#ifndef iNAH2
+ sprintf(tmpnew, "%s", techadmin_host);
+ strncpyzt(new, tmpnew, HOSTLEN);
+#endif
+ return;
+}
+/* Server admin host */
+void make_adminhost(char *new)
+{
+ char tmpnew[HOSTLEN];
+#ifndef iNAH2
+ sprintf(tmpnew, "%s", admin_host);
+ strncpyzt(new, tmpnew, HOSTLEN);
+#endif
+ return;
+}
+/* Service admin host */
+void make_sadminhost(char *new)
+{
+ char tmpnew[HOSTLEN];
+#ifndef iNAH2
+ sprintf(tmpnew, "%s", sadmin_host);
+ strncpyzt(new, tmpnew, HOSTLEN);
+#endif
+ return;
+}
+/* Global Oper host */
+void make_operhost(char *new)
+{
+ char tmpnew[HOSTLEN];
+#ifndef iNAH2
+ sprintf(tmpnew, "%s", oper_host);
+ strncpyzt(new, tmpnew, HOSTLEN);
+#endif
+ return;
+}
+/* Local Oper host */
+void make_locophost(char *new)
+{
+ char tmpnew[HOSTLEN];
+#ifndef iNAH2
+ sprintf(tmpnew, "%s", locop_host);
+ strncpyzt(new, tmpnew, HOSTLEN);
+#endif
+ return;
+}
+
+/* Make SETHOST */
+
+void make_sethost(char *new, char *new2)
+{
+ char tmpnew[HOSTLEN];
+
+ sprintf(tmpnew,"%s", new2);
+ strncpyzt(new, tmpnew, HOSTLEN);
+ return;
+}
+/* make setname */
+void make_setname(char *new, char *new2)
+{
+ char tmpnew[REALLEN];
+
+ sprintf(tmpnew,"%s", new2);
+ strncpyzt(new, tmpnew, REALLEN);
+ return;
+}
+/* make setident */
+
+void make_setident(char *new, char *new2)
+{
+ char tmpnew[USERLEN];
+
+ sprintf(tmpnew, "%s", new2);
+ strncpyzt(new, tmpnew, USERLEN);
+ return;
+}
\ No newline at end of file
--- /dev/null
+/*
+ * UnrealIRCd Configuration Tool (unrealircd.conf & network.network)
+ * $Id$
+*/
+
+int main() {
+ printf("|=-=-=-=-=-==-==--=-=-=-=-=-==-==--=-=-=-=-=-==-==|\n");
+ printf("| |\n");
+ printf("| UnrealIRCd Configuration Tool |\n");
+ printf("| Version 1.0 by Techie <stskeeps@tspre.org> |\n");
+ printf("| |\n");
+ printf("|-=-=-=-=-=-==-=-=-=-=-=-=-=-==-==-=-=-=-=-=-==-==|\n");
+
+ printf("Actually this is only a demo .. so wait for it to be released;p");
+}
\ No newline at end of file
--- /dev/null
+/*
+ * SmartRoute phase 1
+ * connection rule patch
+ * by Tony Vencill (Tonto on IRC) <vencill@bga.com>
+ *
+ * The majority of this file is a recusive descent parser used to convert
+ * connection rules into expression trees when the conf file is read.
+ * All parsing structures and types are hidden in the interest of good
+ * programming style and to make possible future data structure changes
+ * without affecting the interface between this patch and the rest of the
+ * server. The only functions accessible externally are crule_parse,
+ * crule_free, and crule_eval. Prototypes for these functions can be
+ * found in h.h.
+ *
+ * Please direct any connection rule or SmartRoute questions to Tonto on
+ * IRC or by email to vencill@bga.com.
+ *
+ * For parser testing, defining CR_DEBUG generates a stand-alone parser
+ * that takes rules from stdin and prints out memory allocation
+ * information and the parsed rule. This stand alone parser is ignorant
+ * of the irc server and thus cannot do rule evaluation. Do not define
+ * this flag when compiling the server! If you wish to generate the
+ * test parser, compile from the ircd directory with a line similar to
+ * cc -o parser -DCR_DEBUG crule.c
+ *
+ * The define CR_CHKCONF is provided to generate routines needed in
+ * chkconf. These consist of the parser, a different crule_parse that
+ * prints errors to stderr, and crule_free (just for good style and to
+ * more closely simulate the actual ircd environment). crule_eval and
+ * the rule functions are made empty functions as in the stand-alone
+ * test parser.
+ */
+
+#ifndef CR_DEBUG
+/* ircd functions and types we need */
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#include "h.h"
+
+char *collapse PROTO((char *pattern));
+extern aClient *client, *local[];
+
+ID_CVS("$Id$");
+ID_Copyright("(C) Tony Vincell");
+
+#else
+/* includes and defines to make the stand-alone test parser */
+#include <stdio.h>
+#include <string.h>
+#define BadPtr(x) (!(x) || (*(x) == '\0'))
+#define DupString(x,y) do{x=(char *)MyMalloc(strlen(y)+1);(void)strcpy(x,y);}while(0)
+#define mycmp strcasecmp
+#endif
+
+#ifndef PROTO
+#if __STDC__
+# define PROTO(x) x
+#else
+# define PROTO(x) ()
+#endif
+#endif
+#if defined(CR_DEBUG) || defined(CR_CHKCONF)
+#define MyMalloc malloc
+#undef MyFree
+#undef free
+#define MyFree free
+#endif
+
+/* some constants and shared data types */
+#define CR_MAXARGLEN 80 /* why 80? why not? it's > hostname lengths */
+#define CR_MAXARGS 3 /* there's a better way to do this, but not now */
+
+/* some symbols for easy reading */
+enum crule_token
+{CR_UNKNOWN, CR_END, CR_AND, CR_OR, CR_NOT, CR_OPENPAREN, CR_CLOSEPAREN,
+ CR_COMMA, CR_WORD};
+enum crule_errcode
+{CR_NOERR, CR_UNEXPCTTOK, CR_UNKNWTOK, CR_EXPCTAND, CR_EXPCTOR,
+ CR_EXPCTPRIM, CR_EXPCTOPEN, CR_EXPCTCLOSE, CR_UNKNWFUNC, CR_ARGMISMAT};
+
+/* expression tree structure, function pointer, and tree pointer */
+/* local! */
+typedef int (*crule_funcptr) PROTO((int, void **));
+struct crule_treestruct
+{
+ crule_funcptr funcptr;
+ int numargs;
+ void *arg[CR_MAXARGS]; /* for operators arg points to a tree element;
+ for functions arg points to a char string */
+};
+typedef struct crule_treestruct crule_treeelem;
+typedef crule_treeelem *crule_treeptr;
+
+/* rule function prototypes - local! */
+int crule_connected PROTO((int, void **));
+int crule_directcon PROTO((int, void **));
+int crule_via PROTO((int, void **));
+int crule_directop PROTO((int, void **));
+int crule__andor PROTO((int, void **));
+int crule__not PROTO((int, void **));
+
+/* parsing function prototypes - local! */
+int crule_gettoken PROTO((int *, char **));
+void crule_getword PROTO((char *, int *, int, char **));
+int crule_parseandexpr PROTO((crule_treeptr *, int *, char **));
+int crule_parseorexpr PROTO((crule_treeptr *, int *, char **));
+int crule_parseprimary PROTO((crule_treeptr *, int *, char **));
+int crule_parsefunction PROTO((crule_treeptr *, int *, char **));
+int crule_parsearglist PROTO((crule_treeptr, int *, char **));
+
+#if defined(CR_DEBUG) || defined(CR_CHKCONF)
+/* prototypes for the test parser; if not debugging, these are
+ * defined in h.h */
+char *crule_parse PROTO((char *));
+void crule_free PROTO((char **));
+#ifdef CR_DEBUG
+void print_tree PROTO((crule_treeptr));
+#endif
+#endif
+
+/* error messages */
+char *crule_errstr[] =
+{
+ "Unknown error", /* NOERR? - for completeness */
+ "Unexpected token", /* UNEXPCTTOK */
+ "Unknown token", /* UNKNWTOK */
+ "And expr expected", /* EXPCTAND */
+ "Or expr expected", /* EXPCTOR */
+ "Primary expected", /* EXPCTPRIM */
+ "( expected", /* EXPCTOPEN */
+ ") expected", /* EXPCTCLOSE */
+ "Unknown function", /* UNKNWFUNC */
+ "Argument mismatch" /* ARGMISMAT */
+};
+
+/* function table - null terminated */
+struct crule_funclistent
+{
+ char name[15]; /* MAXIMUM FUNCTION NAME LENGTH IS 14 CHARS!! */
+ int reqnumargs;
+ crule_funcptr funcptr;
+};
+struct crule_funclistent crule_funclist[] =
+{
+ /* maximum function name length is 14 chars */
+ {"connected", 1, crule_connected},
+ {"directcon", 1, crule_directcon},
+ {"via", 2, crule_via},
+ {"directop", 0, crule_directop},
+ {"", 0, NULL} /* this must be here to mark end of list */
+};
+
+int crule_connected (numargs, crulearg)
+int numargs;
+void *crulearg[];
+{
+#if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
+ aClient *acptr;
+
+ /* taken from m_links */
+ for (acptr = client; acptr; acptr = acptr->next)
+ {
+ if (!IsServer(acptr) && !IsMe(acptr))
+ continue;
+ if (match((char *) crulearg[0], acptr->name))
+ continue;
+ return (1);
+ }
+ return (0);
+#endif
+}
+
+int crule_directcon (numargs, crulearg)
+int numargs;
+void *crulearg[];
+{
+#if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
+ int i;
+ aClient *acptr;
+
+ /* adapted from m_trace and exit_one_client */
+ for (i = 0; i <= highest_fd; i++)
+ {
+ if (!(acptr = local[i]) || !IsServer(acptr))
+ continue;
+ if (match((char *) crulearg[0], acptr->name))
+ continue;
+ return (1);
+ }
+ return (0);
+#endif
+}
+
+int crule_via (numargs, crulearg)
+int numargs;
+void *crulearg[];
+{
+#if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
+ aClient *acptr;
+
+ /* adapted from m_links */
+ for (acptr = client; acptr; acptr = acptr->next)
+ {
+ if (!IsServer(acptr) && !IsMe(acptr))
+ continue;
+ if (match((char *) crulearg[1], acptr->name))
+ continue;
+ if (match((char *) crulearg[0], (local[acptr->fd])->name))
+ continue;
+ return (1);
+ }
+ return (0);
+#endif
+}
+
+int crule_directop (numargs, crulearg)
+int numargs;
+void *crulearg[];
+{
+#if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
+ int i;
+ aClient *acptr;
+
+ /* adapted from m_trace */
+ for (i = 0; i <= highest_fd; i++)
+ {
+ if (!(acptr = local[i]) || !IsAnOper(acptr))
+ continue;
+ return (1);
+ }
+ return (0);
+#endif
+}
+
+int crule__andor (numargs, crulearg)
+int numargs;
+void *crulearg[];
+{
+ int result1;
+
+ result1 = ((crule_treeptr) crulearg[0])->funcptr
+ (((crule_treeptr) crulearg[0])->numargs,
+ (void *) ((crule_treeptr) crulearg[0])->arg);
+ if (crulearg[2]) /* or */
+ return (result1 ||
+ ((crule_treeptr) crulearg[1])->funcptr
+ (((crule_treeptr) crulearg[1])->numargs,
+ (void *) ((crule_treeptr) crulearg[1])->arg));
+ else
+ return (result1 &&
+ ((crule_treeptr) crulearg[1])->funcptr
+ (((crule_treeptr) crulearg[1])->numargs,
+ (void *) ((crule_treeptr) crulearg[1])->arg));
+}
+
+int crule__not (numargs, crulearg)
+int numargs;
+void *crulearg[];
+{
+ return (!((crule_treeptr) crulearg[0])->funcptr
+ (((crule_treeptr) crulearg[0])->numargs,
+ (void *) ((crule_treeptr) crulearg[0])->arg));
+}
+
+#if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
+int crule_eval (rule)
+char *rule;
+{
+ return (((crule_treeptr) rule)->funcptr
+ (((crule_treeptr) rule)->numargs,
+ ((crule_treeptr) rule)->arg));
+}
+#endif
+
+int crule_gettoken (next_tokp, ruleptr)
+int *next_tokp;
+char **ruleptr;
+{
+ char pending = '\0';
+
+ *next_tokp = CR_UNKNOWN;
+ while (*next_tokp == CR_UNKNOWN)
+ switch (*(*ruleptr)++)
+ {
+ case ' ': case '\t':
+ break;
+ case '&':
+ if (pending == '\0')
+ pending = '&';
+ else if (pending == '&')
+ *next_tokp = CR_AND;
+ else
+ return (CR_UNKNWTOK);
+ break;
+ case '|':
+ if (pending == '\0')
+ pending = '|';
+ else if (pending == '|')
+ *next_tokp = CR_OR;
+ else
+ return (CR_UNKNWTOK);
+ break;
+ case '!':
+ *next_tokp = CR_NOT;
+ break;
+ case '(':
+ *next_tokp = CR_OPENPAREN;
+ break;
+ case ')':
+ *next_tokp = CR_CLOSEPAREN;
+ break;
+ case ',':
+ *next_tokp = CR_COMMA;
+ break;
+ case '\0':
+ (*ruleptr)--;
+ *next_tokp = CR_END;
+ break;
+ case ':':
+ *next_tokp = CR_END;
+ break;
+ default:
+ if ((isalpha (*(--(*ruleptr)))) || (**ruleptr == '*') ||
+ (**ruleptr == '?') || (**ruleptr == '.'))
+ *next_tokp = CR_WORD;
+ else
+ return (CR_UNKNWTOK);
+ break;
+ }
+ return CR_NOERR;
+}
+
+void crule_getword (word, wordlenp, maxlen, ruleptr)
+char *word;
+int *wordlenp;
+int maxlen;
+char **ruleptr;
+{
+ char *word_ptr;
+
+ word_ptr = word;
+ while ((isalnum (**ruleptr)) || (**ruleptr == '*') ||
+ (**ruleptr == '?') || (**ruleptr == '.'))
+ *word_ptr++ = *(*ruleptr)++;
+ *word_ptr = '\0';
+ *wordlenp = word_ptr - word;
+}
+
+/*
+ * Grammar
+ * rule:
+ * orexpr END END is end of input or :
+ * orexpr:
+ * andexpr
+ * andexpr || orexpr
+ * andexpr:
+ * primary
+ * primary && andexpr
+ * primary:
+ * function
+ * ! primary
+ * ( orexpr )
+ * function:
+ * word ( ) word is alphanumeric string, first character
+ * word ( arglist ) must be a letter
+ * arglist:
+ * word
+ * word , arglist
+ */
+
+char *crule_parse (rule)
+char *rule;
+{
+ char *ruleptr = rule;
+ int next_tok;
+ crule_treeptr ruleroot = NULL;
+ int errcode = CR_NOERR;
+
+ if ((errcode = crule_gettoken (&next_tok, &ruleptr)) == CR_NOERR)
+ if ((errcode = crule_parseorexpr (&ruleroot, &next_tok,
+ &ruleptr)) == CR_NOERR)
+ if (ruleroot != NULL)
+ if (next_tok == CR_END)
+ return ((char *) ruleroot);
+ else
+ errcode = CR_UNEXPCTTOK;
+ else
+ errcode = CR_EXPCTOR;
+ if (ruleroot != NULL)
+ crule_free ((char **) &ruleroot);
+#if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
+ Debug ((DEBUG_ERROR, "%s in rule: %s", crule_errstr[errcode], rule));
+#else
+ (void) fprintf (stderr, "%s in rule: %s\n", crule_errstr[errcode], rule);
+#endif
+ return NULL;
+}
+
+int crule_parseorexpr (orrootp, next_tokp, ruleptr)
+crule_treeptr *orrootp;
+int *next_tokp;
+char **ruleptr;
+{
+ int errcode = CR_NOERR;
+ crule_treeptr andexpr;
+ crule_treeptr orptr;
+
+ *orrootp = NULL;
+ while (errcode == CR_NOERR)
+ {
+ errcode = crule_parseandexpr (&andexpr, next_tokp, ruleptr);
+ if ((errcode == CR_NOERR) && (*next_tokp == CR_OR))
+ {
+ orptr = (crule_treeptr) MyMalloc (sizeof (crule_treeelem));
+#ifdef CR_DEBUG
+ (void) fprintf (stderr, "allocating or element at %ld\n", orptr);
+#endif
+ orptr->funcptr = crule__andor;
+ orptr->numargs = 3;
+ orptr->arg[2] = (void *) 1;
+ if (*orrootp != NULL)
+ {
+ (*orrootp)->arg[1] = andexpr;
+ orptr->arg[0] = *orrootp;
+ }
+ else
+ orptr->arg[0] = andexpr;
+ *orrootp = orptr;
+ }
+ else
+ {
+ if (*orrootp != NULL)
+ if (andexpr != NULL)
+ {
+ (*orrootp)->arg[1] = andexpr;
+ return (errcode);
+ }
+ else
+ {
+ (*orrootp)->arg[1] = NULL; /* so free doesn't seg fault */
+ return (CR_EXPCTAND);
+ }
+ else
+ {
+ *orrootp = andexpr;
+ return (errcode);
+ }
+ }
+ if ((errcode = crule_gettoken (next_tokp, ruleptr)) != CR_NOERR)
+ return (errcode);
+ }
+ return (errcode);
+}
+
+int crule_parseandexpr (androotp, next_tokp, ruleptr)
+crule_treeptr *androotp;
+int *next_tokp;
+char **ruleptr;
+{
+ int errcode = CR_NOERR;
+ crule_treeptr primary;
+ crule_treeptr andptr;
+
+ *androotp = NULL;
+ while (errcode == CR_NOERR)
+ {
+ errcode = crule_parseprimary (&primary, next_tokp, ruleptr);
+ if ((errcode == CR_NOERR) && (*next_tokp == CR_AND))
+ {
+ andptr = (crule_treeptr) MyMalloc (sizeof (crule_treeelem));
+#ifdef CR_DEBUG
+ (void) fprintf (stderr, "allocating and element at %ld\n", andptr);
+#endif
+ andptr->funcptr = crule__andor;
+ andptr->numargs = 3;
+ andptr->arg[2] = (void *) 0;
+ if (*androotp != NULL)
+ {
+ (*androotp)->arg[1] = primary;
+ andptr->arg[0] = *androotp;
+ }
+ else
+ andptr->arg[0] = primary;
+ *androotp = andptr;
+ }
+ else
+ {
+ if (*androotp != NULL)
+ if (primary != NULL)
+ {
+ (*androotp)->arg[1] = primary;
+ return (errcode);
+ }
+ else
+ {
+ (*androotp)->arg[1] = NULL; /* so free doesn't seg fault */
+ return (CR_EXPCTPRIM);
+ }
+ else
+ {
+ *androotp = primary;
+ return (errcode);
+ }
+ }
+ if ((errcode = crule_gettoken (next_tokp, ruleptr)) != CR_NOERR)
+ return (errcode);
+ }
+ return (errcode);
+}
+
+int crule_parseprimary (primrootp, next_tokp, ruleptr)
+crule_treeptr *primrootp;
+int *next_tokp;
+char **ruleptr;
+{
+ crule_treeptr *insertionp;
+ int errcode = CR_NOERR;
+
+ *primrootp = NULL;
+ insertionp = primrootp;
+ while (errcode == CR_NOERR)
+ {
+ switch (*next_tokp)
+ {
+ case CR_OPENPAREN:
+ if ((errcode = crule_gettoken (next_tokp, ruleptr)) != CR_NOERR)
+ break;
+ if ((errcode = crule_parseorexpr (insertionp, next_tokp,
+ ruleptr)) != CR_NOERR)
+ break;
+ if (*insertionp == NULL)
+ {
+ errcode = CR_EXPCTAND;
+ break;
+ }
+ if (*next_tokp != CR_CLOSEPAREN)
+ {
+ errcode = CR_EXPCTCLOSE;
+ break;
+ }
+ errcode = crule_gettoken (next_tokp, ruleptr);
+ break;
+ case CR_NOT:
+ *insertionp = (crule_treeptr) MyMalloc (sizeof (crule_treeelem));
+#ifdef CR_DEBUG
+ (void) fprintf (stderr,
+ "allocating primary element at %ld\n", *insertionp);
+#endif
+ (*insertionp)->funcptr = crule__not;
+ (*insertionp)->numargs = 1;
+ (*insertionp)->arg[0] = NULL;
+ insertionp = (crule_treeptr *) &((*insertionp)->arg[0]);
+ if ((errcode = crule_gettoken (next_tokp, ruleptr)) != CR_NOERR)
+ break;
+ continue;
+ case CR_WORD:
+ errcode = crule_parsefunction (insertionp, next_tokp, ruleptr);
+ break;
+ default:
+ if (*primrootp == NULL)
+ errcode = CR_NOERR;
+ else
+ errcode = CR_EXPCTPRIM;
+ break;
+ }
+ return (errcode);
+ }
+ return (errcode);
+}
+
+int crule_parsefunction (funcrootp, next_tokp, ruleptr)
+crule_treeptr *funcrootp;
+int *next_tokp;
+char **ruleptr;
+{
+ int errcode = CR_NOERR;
+ char funcname[CR_MAXARGLEN];
+ int namelen;
+ int funcnum;
+
+ *funcrootp = NULL;
+ crule_getword (funcname, &namelen, CR_MAXARGLEN, ruleptr);
+ if ((errcode = crule_gettoken (next_tokp, ruleptr)) != CR_NOERR)
+ return (errcode);
+ if (*next_tokp == CR_OPENPAREN)
+ {
+ for (funcnum = 0; ; funcnum++)
+ {
+ if (mycmp (crule_funclist[funcnum].name, funcname) == 0)
+ break;
+ if (crule_funclist[funcnum].name[0] == '\0')
+ return (CR_UNKNWFUNC);
+ }
+ if ((errcode = crule_gettoken (next_tokp, ruleptr)) != CR_NOERR)
+ return (errcode);
+ *funcrootp = (crule_treeptr) MyMalloc (sizeof (crule_treeelem));
+#ifdef CR_DEBUG
+ (void) fprintf (stderr, "allocating function element at %ld\n",
+ *funcrootp);
+#endif
+ (*funcrootp)->funcptr = NULL; /* for freeing aborted trees */
+ if ((errcode = crule_parsearglist (*funcrootp, next_tokp,
+ ruleptr)) != CR_NOERR)
+ return (errcode);
+ if (*next_tokp != CR_CLOSEPAREN)
+ return (CR_EXPCTCLOSE);
+ if ((crule_funclist[funcnum].reqnumargs != (*funcrootp)->numargs) &&
+ (crule_funclist[funcnum].reqnumargs != -1))
+ return (CR_ARGMISMAT);
+ if ((errcode = crule_gettoken (next_tokp, ruleptr)) != CR_NOERR)
+ return (errcode);
+ (*funcrootp)->funcptr = crule_funclist[funcnum].funcptr;
+ return (CR_NOERR);
+ }
+ else
+ return (CR_EXPCTOPEN);
+}
+
+int crule_parsearglist (argrootp, next_tokp, ruleptr)
+crule_treeptr argrootp;
+int *next_tokp;
+char **ruleptr;
+{
+ int errcode = CR_NOERR;
+ char *argelemp = NULL;
+ char currarg[CR_MAXARGLEN];
+ int arglen = 0;
+ char word[CR_MAXARGLEN];
+ int wordlen = 0;
+
+ argrootp->numargs = 0;
+ currarg[0] = '\0';
+ while (errcode == CR_NOERR)
+ {
+ switch (*next_tokp)
+ {
+ case CR_WORD:
+ crule_getword (word, &wordlen, CR_MAXARGLEN, ruleptr);
+ if (currarg[0] != '\0')
+ {
+ if ((arglen + wordlen) < (CR_MAXARGLEN - 1))
+ {
+ strcat (currarg, " ");
+ strcat (currarg, word);
+ arglen += wordlen + 1;
+ }
+ }
+ else
+ {
+ strcpy (currarg, word);
+ arglen = wordlen;
+ }
+ errcode = crule_gettoken (next_tokp, ruleptr);
+ break;
+ default:
+#if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
+ (void) collapse (currarg);
+#endif
+ if (!BadPtr (currarg))
+ {
+ DupString (argelemp, currarg);
+ argrootp->arg[argrootp->numargs++] = (void *) argelemp;
+ }
+ if (*next_tokp != CR_COMMA)
+ return (CR_NOERR);
+ currarg[0] = '\0';
+ errcode = crule_gettoken (next_tokp, ruleptr);
+ break;
+ }
+ }
+ return (errcode);
+}
+
+/*
+ * this function is recursive.. i wish i knew a nonrecursive way but
+ * i dont. anyway, recursion is fun.. :)
+ * DO NOT CALL THIS FUNTION WITH A POINTER TO A NULL POINTER
+ * (ie: if *elem is NULL, you're doing it wrong - seg fault)
+ */
+void crule_free (elem)
+char **elem;
+{
+ int arg, numargs;
+
+ if ((*((crule_treeptr *) elem))->funcptr == crule__not)
+ {
+ /* type conversions and ()'s are fun! ;) here have an asprin.. */
+ if ((*((crule_treeptr *)elem))->arg[0] != NULL)
+ crule_free ((char **) &((*((crule_treeptr *) elem))->arg[0]));
+ }
+ else if ((*((crule_treeptr *)elem))->funcptr == crule__andor)
+ {
+ crule_free ((char **) &((*((crule_treeptr *) elem))->arg[0]));
+ if ((*((crule_treeptr *)elem))->arg[1] != NULL)
+ crule_free ((char **) &((*((crule_treeptr *) elem))->arg[1]));
+ }
+ else
+ {
+ numargs = (*((crule_treeptr *) elem))->numargs;
+ for (arg = 0; arg < numargs; arg++)
+ MyFree ((char *) (*((crule_treeptr *) elem))->arg[arg]);
+ }
+#ifdef CR_DEBUG
+ (void) fprintf (stderr, "freeing element at %ld\n", *elem);
+#endif
+ MyFree (*elem);
+ *elem = NULL;
+}
+
+#ifdef CR_DEBUG
+void print_tree (printelem)
+crule_treeptr printelem;
+{
+ int funcnum, arg;
+
+ if (printelem->funcptr == crule__not)
+ {
+ printf ("!( ");
+ print_tree ((crule_treeptr) printelem->arg[0]);
+ printf (") ");
+ }
+ else if (printelem->funcptr == crule__andor)
+ {
+ printf ("( ");
+ print_tree ((crule_treeptr) printelem->arg[0]);
+ if (printelem->arg[2])
+ printf ("|| ");
+ else
+ printf ("&& ");
+ print_tree ((crule_treeptr) printelem->arg[1]);
+ printf (") ");
+ }
+ else
+ {
+ for (funcnum = 0; ;funcnum++)
+ {
+ if (printelem->funcptr == crule_funclist[funcnum].funcptr)
+ break;
+ if (crule_funclist[funcnum].funcptr == NULL)
+ {
+ printf ("\nACK! *koff* *sputter*\n");
+ exit (1);
+ }
+ }
+ printf ("%s(", crule_funclist[funcnum].name);
+ for (arg = 0; arg < printelem->numargs; arg++)
+ {
+ if (arg != 0)
+ printf (",");
+ printf ("%s", (char *) printelem->arg[arg]);
+ }
+ printf (") ");
+ }
+}
+#endif
+
+#ifdef CR_DEBUG
+void main ()
+{
+ char indata[256];
+ char *rule;
+
+ printf ("rule: ");
+ while (fgets (indata, 256, stdin) != NULL)
+ {
+ indata[strlen (indata) - 1] = '\0'; /* lose the newline */
+ if ((rule = crule_parse (indata)) != NULL)
+ {
+ printf ("equivalent rule: ");
+ print_tree ((crule_treeptr) rule);
+ printf ("\n");
+ crule_free (&rule);
+ }
+ printf ("\nrule: ");
+ }
+ printf ("\n");
+}
+#endif
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, common/dbuf.c
+ * Copyright (C) 1990 Markku Savela
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* -- Jto -- 20 Jun 1990
+ * extern void free() fixed as suggested by
+ * gruner@informatik.tu-muenchen.de
+ */
+
+/* -- Jto -- 10 May 1990
+ * Changed memcpy into bcopy and removed the declaration of memset
+ * because it was unnecessary.
+ * Added the #includes for "struct.h" and "sys.h" to get bcopy/memcpy
+ * work
+ */
+
+/*
+** For documentation of the *global* functions implemented here,
+** see the header file (dbuf.h).
+**
+*/
+
+#include <stdio.h>
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+
+ID_CVS("$Id$");
+ID_Copyright("(C) 1990 Markku Savela");
+ID_Notes("2.17 1/30/94 (C) 1990 Markku Savela");
+
+#if !defined(VALLOC) && !defined(valloc)
+# ifndef _WIN32
+# define valloc malloc
+# else
+# define valloc MyMalloc
+# endif
+#endif
+
+int dbufalloc = 0, dbufblocks = 0;
+static dbufbuf *freelist = NULL;
+
+/* This is a dangerous define because a broken compiler will set DBUFSIZ
+** to 4, which will work but will be very inefficient. However, there
+** are other places where the code breaks badly if this is screwed
+** up, so... -- Wumpus
+*/
+
+#define DBUFSIZ sizeof(((dbufbuf *)0)->data)
+
+/*
+** dbuf_alloc - allocates a dbufbuf structure either from freelist or
+** creates a new one.
+*/
+static dbufbuf *dbuf_alloc()
+{
+#if defined(VALLOC) && !defined(DEBUGMODE)
+ Reg1 dbufbuf *dbptr, *db2ptr;
+ Reg2 int num;
+#else
+ Reg1 dbufbuf *dbptr;
+#endif
+
+ dbufalloc++;
+ if ((dbptr = freelist))
+ {
+ freelist = freelist->next;
+ return dbptr;
+ }
+ if (dbufalloc * DBUFSIZ > BUFFERPOOL)
+ {
+ dbufalloc--;
+ return NULL;
+ }
+
+#if defined(VALLOC) && !defined(DEBUGMODE)
+# if defined(SOL20) || defined(_SC_PAGESIZE)
+ num = sysconf(_SC_PAGESIZE)/sizeof(dbufbuf);
+# else
+ num = getpagesize()/sizeof(dbufbuf);
+# endif
+ if (num < 0)
+ num = 1;
+
+ dbufblocks += num;
+
+ dbptr = (dbufbuf *)valloc(num*sizeof(dbufbuf));
+ if (!dbptr)
+ return (dbufbuf *)NULL;
+
+ num--;
+ for (db2ptr = dbptr; num; num--)
+ {
+ db2ptr = (dbufbuf *)((char *)db2ptr + sizeof(dbufbuf));
+ db2ptr->next = freelist;
+ freelist = db2ptr;
+ }
+ return dbptr;
+#else
+ dbufblocks++;
+ return (dbufbuf *)MyMalloc(sizeof(dbufbuf));
+#endif
+}
+/*
+** dbuf_free - return a dbufbuf structure to the freelist
+*/
+static void dbuf_free(ptr)
+Reg1 dbufbuf *ptr;
+{
+ dbufalloc--;
+ ptr->next = freelist;
+ freelist = ptr;
+}
+/*
+** This is called when malloc fails. Scrap the whole content
+** of dynamic buffer and return -1. (malloc errors are FATAL,
+** there is no reason to continue this buffer...). After this
+** the "dbuf" has consistent EMPTY status... ;)
+*/
+static int dbuf_malloc_error(dyn)
+dbuf *dyn;
+ {
+ dbufbuf *p;
+
+ dyn->length = 0;
+ dyn->offset = 0;
+ while ((p = dyn->head) != NULL)
+ {
+ dyn->head = p->next;
+ dbuf_free(p);
+ }
+ dyn->tail = dyn->head;
+ return -1;
+ }
+
+
+int dbuf_put(dyn, buf, length)
+dbuf *dyn;
+char *buf;
+int length;
+{
+ Reg1 dbufbuf **h, *d;
+ Reg2 int off;
+ Reg3 int chunk;
+
+ if(!length) return 1; /* Nothing to do */
+
+ off = (dyn->offset + dyn->length) % DBUFSIZ;
+ /*
+ ** Locate the last non-empty buffer. If the last buffer is
+ ** full, the loop will terminate with 'd==NULL'. This loop
+ ** assumes that the 'dyn->length' field is correctly
+ ** maintained, as it should--no other check really needed.
+ */
+ if (!dyn->length) h = &(dyn->head);
+ else {
+ if (off) h = &(dyn->tail);
+ else h = &(dyn->tail->next);
+ }
+ /*
+ ** Append users data to buffer, allocating buffers as needed
+ */
+ chunk = DBUFSIZ - off;
+ dyn->length += length;
+ for ( ;length > 0; h = &(d->next))
+ {
+ if ((d = *h) == NULL)
+ {
+ if ((d = (dbufbuf *)dbuf_alloc()) == NULL)
+ return dbuf_malloc_error(dyn);
+ dyn->tail = d;
+ *h = d;
+ d->next = NULL;
+ }
+ if (chunk > length)
+ chunk = length;
+ bcopy(buf, d->data + off, chunk);
+ length -= chunk;
+ buf += chunk;
+ off = 0;
+ chunk = DBUFSIZ;
+ }
+ return 1;
+ }
+
+
+char *dbuf_map(dyn,length)
+dbuf *dyn;
+int *length;
+ {
+ if (dyn->head == NULL)
+ {
+ dyn->tail = NULL;
+ *length = 0;
+ return NULL;
+ }
+ *length = DBUFSIZ - dyn->offset;
+ if (*length > dyn->length)
+ *length = dyn->length;
+ return (dyn->head->data + dyn->offset);
+ }
+
+int dbuf_delete(dyn,length)
+dbuf *dyn;
+int length;
+ {
+ dbufbuf *d;
+ int chunk;
+
+ if (length > dyn->length)
+ length = dyn->length;
+ chunk = DBUFSIZ - dyn->offset;
+ while (length > 0)
+ {
+ if (chunk > length)
+ chunk = length;
+ length -= chunk;
+ dyn->offset += chunk;
+ dyn->length -= chunk;
+ if (dyn->offset == DBUFSIZ || dyn->length == 0)
+ {
+ d = dyn->head;
+ dyn->head = d->next;
+ dyn->offset = 0;
+ dbuf_free(d);
+ }
+ chunk = DBUFSIZ;
+ }
+ if (dyn->head == (dbufbuf *)NULL) {
+ dyn->length = 0;
+ dyn->tail = 0;
+ }
+ return 0;
+ }
+
+int dbuf_get(dyn, buf, length)
+dbuf *dyn;
+char *buf;
+int length;
+ {
+ int moved = 0;
+ int chunk;
+ char *b;
+
+ while (length > 0 && (b = dbuf_map(dyn, &chunk)) != NULL)
+ {
+ if (chunk > length)
+ chunk = length;
+ bcopy(b, buf, (int)chunk);
+ (void)dbuf_delete(dyn, chunk);
+ buf += chunk;
+ length -= chunk;
+ moved += chunk;
+ }
+ return moved;
+ }
+
+/*
+** dbuf_getmsg
+**
+** Check the buffers to see if there is a string which is terminted with
+** either a \r or \n prsent. If so, copy as much as possible (determined by
+** length) into buf and return the amount copied - else return 0.
+*/
+int dbuf_getmsg(dyn, buf, length)
+dbuf *dyn;
+char *buf;
+register int length;
+{
+ dbufbuf *d;
+ register char *s;
+ register int dlen;
+ register int i;
+ int copy;
+
+getmsg_init:
+ d = dyn->head;
+ dlen = dyn->length;
+ i = DBUFSIZ - dyn->offset;
+ if (i <= 0)
+ return -1;
+ copy = 0;
+ if (d && dlen)
+ s = dyn->offset + d->data;
+ else
+ return 0;
+
+ if (i > dlen)
+ i = dlen;
+ while (length > 0 && dlen > 0)
+ {
+ dlen--;
+ if (*s == '\n' || *s == '\r')
+ {
+ copy = dyn->length - dlen;
+ /*
+ ** Shortcut this case here to save time elsewhere.
+ ** -avalon
+ */
+ if (copy == 1)
+ {
+ (void)dbuf_delete(dyn, 1);
+ goto getmsg_init;
+ }
+ break;
+ }
+ length--;
+ if (!--i)
+ {
+ if ((d = d->next))
+ {
+ s = d->data;
+ i = MIN(DBUFSIZ, dlen);
+ }
+ }
+ else
+ s++;
+ }
+
+ if (copy <= 0)
+ return 0;
+
+ /*
+ ** copy as much of the message as wanted into parse buffer
+ */
+ i = dbuf_get(dyn, buf, MIN(copy, length));
+ /*
+ ** and delete the rest of it!
+ */
+ if (copy - i > 0)
+ (void)dbuf_delete(dyn, copy - i);
+ if (i >= 0)
+ *(buf+i) = '\0'; /* mark end of messsage */
+
+ return i;
+}
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, dynconf.c
+ * (C) 1999 Carsten Munk (Techie/Stskeeps) <cmunk@toybox.flirt.org>
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define DYNCONF_C
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#include "numeric.h"
+#include "msg.h"
+#include "channel.h"
+#include "userload.h"
+#include <time.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef _WIN32
+#include <utmp.h>
+#else
+#include <io.h>
+#endif
+#include <fcntl.h>
+#include "h.h"
+
+ID_CVS("$Id$");
+ID_Copyright("(C) 1999 Carsten Munk");
+#define DoDebug fprintf(stderr, "[%s] %s | %li\n", babuf, __FILE__, __LINE__);
+#define AllocCpy(x,y) if ((x) && type == 1) MyFree((x)); x = (char *) MyMalloc(strlen(y) + 1); strcpy(x,y)
+#define XtndCpy(x,y) x = (char *) MyMalloc(strlen(y) + 2); *x = '\0'; strcat(x, "*"); strcpy(x,y)
+
+aConfiguration iConf;
+int icx = 0;
+void iCstrip(char *line)
+{
+ char *c;
+
+ if ((c = strchr(line, '\n'))) *c = '\0';
+ if ((c = strchr(line, '\r'))) *c = '\0';
+}
+
+/*
+ for (q = p; *q; q++) {
+ printf("%x ", *q);
+ }
+*/
+
+
+/* Get the unrealircd.conf/*.network file version and check it */
+char *get_version(char *file) {
+ FILE *fd = fopen(file, "r");
+ char buf[24], *tmp = '\0', *buf2 = '\0', *version = '\0';
+
+ /* This should never happen, but we'll keep it just to be safe */
+ if (!fd) {
+#ifdef _WIN32
+ MessageBox(NULL, "UnrealIRCD/32 Init Error", "Unable to load dynamic config (or network) file !! ", MB_OK);
+#else
+ fprintf(stderr, "[error] Couldn't load %s !!!\n", file);
+#endif
+ exit(-1);
+ }
+/* We only want to read the first line */
+ fgets(buf, 24, fd);
+ tmp = strtok(buf, "\n");
+/* Make sure that it is a valid version line */
+ buf2 = strtok(tmp,"^");
+/* If it isn't exit */
+ if (strcmp(buf2, "ver")) {
+#ifdef _WIN32
+ MessageBox(NULL, "Dynamic config file (or network file) is not valid, visit http://unreal.tspre.org to learn how to upgrade", "UnrealIRCD/32 Init Error", MB_OK);
+#else
+ fprintf(stderr, "%s is invalid, visit http://unreal.tspre.org to learn how to upgrade", file);
+#endif
+ exit(-1);
+ }
+ /* If it is we get the version number */
+ version = strtok(NULL, "");
+ fclose(fd);
+ /* Now return the version */
+ return version;
+}
+
+int load_conf(char *file, int type)
+{
+ FILE *zConf;
+ char *stat;
+ char *buf = MyMalloc(1024);
+ char *babuf = MyMalloc(1024);
+ char *p, *q;
+ char *var, *setto;
+ long aint;
+ int v1, v2;
+ /* Since we have no real way of knowing what file we are dealing with, we will check
+ * for *.conf then get the version */
+ if(!match("*.conf",file)) {
+ if (strcmp(get_version(file), "1.1")) {
+#ifdef _WIN32
+
+ MessageBox(NULL, "Dynamic config file is not valid, visit http://unreal.tspre.org to learn how to upgrade", "UnrealIRCD/32 Init Error", MB_OK);
+#else
+ fprintf(stderr, "%s is invalid, visit http://unreal.tspre.org to learn how to upgrade\n", file);
+#endif
+ exit(-1);
+ }
+}
+
+ zConf = fopen(file, "r");
+ if (zConf == NULL && (type == 0)) {
+#ifdef _WIN32
+ MessageBox(NULL, "UnrealIRCD/32 Init Error", "Unable to load dynamic config (or network) file !! ", MB_OK);
+#else
+ fprintf(stderr, "[error] Couldn't load %s !!!\n", file);
+#endif
+ exit(-1);
+ }
+ else
+ if (zConf == NULL && (type == 1))
+ {
+ sendto_ops("[error] Couldnt load dynconf file %s !!", file);
+ }
+ *buf = '\1';
+ stat = buf;
+
+ while (stat != NULL)
+ {
+ stat = fgets(buf,1020, zConf);
+ if (*buf == '#') /* comment */
+ continue;
+ if (*buf == '/') /* comment */
+ continue;
+ iCstrip(buf); /* strip crlf .. */
+ strcpy(babuf, buf);
+ if (*buf == '\0')
+ continue;
+
+ p = strtok(buf, " ");
+ if (strcmp(p, "Include")==0)
+ {
+ strtok(NULL, " ");
+ setto = strtok(NULL, "");
+ /* We need this for STATS S */
+ AllocCpy(INCLUDE, setto);
+#ifndef _WIN32
+#endif
+ /* Check the version before we read the file */
+
+ if (strcmp(get_version(setto),"2.2"))
+ {
+#ifdef _WIN32
+ MessageBox(NULL, "Network file is not valid, visit http://unreal.tspre.org to learn how to upgrade", "UnrealIRCD/32 Init Error", MB_OK);
+#else
+ fprintf(stderr, "%s is invalid, visit http://unreal.tspre.org to learn how to upgrade\n", setto);
+#endif
+ exit(-1);
+ }
+
+ load_conf(setto,type);
+ }
+
+ else
+ if (strcmp(p, "Set")==0)
+ {
+ var = strtok(NULL, " ");
+ /* Yes it was a good idea when i moved it. */
+ if (var == NULL)
+ continue;
+ if (*var == '\0')
+ continue;
+
+ strtok(NULL, " ");
+ setto = strtok(NULL, "");
+ if (setto == NULL)
+ continue;
+ if (*setto == '\0')
+ continue;
+
+ if (*setto >= '0' && *setto <= '9') {
+ aint = atol(setto);
+ if (strcmp(var, "MODE_X")==0)
+ MODE_X = aint;
+ else
+ if (strcmp(var, "MODE_I")==0)
+ MODE_I = aint;
+ else
+ if (strcmp(var, "TRUEHUB")==0) {
+ TRUEHUB = aint;
+#ifndef HUB
+ /* Only display if _not_ called thru /rehash */
+ if (aint == 1 && type == 0) {
+#ifdef _WIN32
+ MessageBox(NULL, "UnrealIRCD/32 Init Error", "I'm a leaf NOT an hub! ", MB_OK);
+
+#else
+ fprintf(stderr, "[error] I'm a leaf NOT a hub!\n");
+#endif
+ return 0;
+ }
+#endif
+ }
+ if (strcmp(var, "CONFIG_FILE_STOP")==0) {
+ if (aint == 1) {
+#ifdef _WIN32
+ MessageBox(NULL, "UnrealIRCD/32 Init Error", "Read Config stop code in file", MB_OK);
+#else
+ fprintf(stderr, "[fatal error] File stop code recieved in %s - RTFM\n", file);
+#endif
+ exit(-1);
+ }
+ }
+
+ if (strcmp(var, "SHOWOPERS")==0) {
+ SHOWOPERS = aint;
+ }
+ if (strcmp(var, "SHOWOPERMOTD")==0) {
+ SHOWOPERMOTD = aint;
+ }
+ if (strcmp(var, "SOCKSBANTIME")==0) {
+ iConf.socksbantime = aint;
+ }
+ if (strcmp(var, "iNAH")==0) {
+ iNAH = aint;
+ }
+ if (strcmp(var, "ALLOW_CHATOPS")==0) {
+ ALLOW_CHATOPS = aint;
+ }
+ if (strcmp(var, "HIDE_ULINES")==0) {
+ HIDE_ULINES = aint;
+ }
+ if (strcmp(var, "KILLDIFF")==0) {
+ KILLDIFF = aint;
+ }
+ continue;
+ }
+/* if (strcmp(var, "DOMAINNAME")==0) {
+ AllocCpy(DOMAINNAME, setto);
+ XtndCpy(DOMAINNAMEMASK, setto);
+ }
+*/
+ /* uhm networks */
+ if (strcmp(var, "ircnetwork")==0) {
+ AllocCpy(ircnetwork, setto);
+ }
+ else
+ if (strcmp(var, "defserv")==0) {
+ AllocCpy(defserv, setto);
+ }
+ else
+ if (strcmp(var, "SERVICES_NAME")==0) {
+ AllocCpy(SERVICES_NAME, setto);
+ }
+ else
+ if (strcmp(var, "oper_host")==0) {
+ AllocCpy(oper_host, setto);
+ }
+ else
+ if (strcmp(var, "admin_host")==0) {
+ AllocCpy(admin_host, setto);
+ }
+ else
+ if (strcmp(var, "locop_host")==0) {
+ AllocCpy(locop_host, setto);
+ }
+ else
+ if (strcmp(var, "sadmin_host")==0) {
+ AllocCpy(sadmin_host, setto);
+ }
+ else
+ if (strcmp(var, "netadmin_host")==0) {
+ AllocCpy(netadmin_host, setto);
+ }
+ else
+ if (strcmp(var, "techadmin_host")==0) {
+ AllocCpy(techadmin_host, setto);
+ }
+ else
+ if (strcmp(var, "coadmin_host")==0) {
+ AllocCpy(coadmin_host, setto);
+ }
+ else
+ if (strcmp(var, "hidden_host")==0) {
+ AllocCpy(hidden_host, setto);
+ }
+ else
+ if (strcmp(var, "netdomain")==0) {
+ AllocCpy(netdomain, setto);
+ }
+ else
+ if (strcmp(var, "helpchan")==0) {
+ AllocCpy(helpchan, setto);
+ }
+ else
+ if (strcmp(var, "STATS_SERVER")==0) {
+ AllocCpy(STATS_SERVER, setto);
+ }
+ else
+ if (strcmp(var, "KLINE_ADDRESS")==0) {
+ AllocCpy(KLINE_ADDRESS, setto);
+ }
+ else
+ if (strcmp(var, "SOCKS_BAN_MESSAGE")==0) {
+ AllocCpy(iConf.socksbanmessage, setto);
+ }
+ else
+ if (strcmp(var, "SOCKS_QUIT_MESSAGE")==0) {
+ AllocCpy(iConf.socksquitmessage, setto);
+ }
+
+ }
+ }
+#ifndef _WIN32
+ fprintf(stderr, "* Loaded %s ..\n", file);
+#endif
+}
+
+void doneconf(void) {
+
+}
+
+/* Report the unrealircd.conf info -codemastr*/
+void report_dynconf (aClient *sptr)
+{
+ sendto_one(sptr, ":%s %i %s :*** Dynamic Configuration Report ***", me.name, RPL_TEXT, sptr->name);
+ sendto_one(sptr, ":%s %i %s :INCLUDE: %s", me.name, RPL_TEXT, sptr->name, INCLUDE);
+ sendto_one(sptr, ":%s %i %s :KLINE_ADDRESS: %s", me.name, RPL_TEXT, sptr->name, KLINE_ADDRESS);
+ sendto_one(sptr, ":%s %i %s :MODE_X: %i", me.name, RPL_TEXT, sptr->name, MODE_X);
+ sendto_one(sptr, ":%s %i %s :MODE_I: %i", me.name, RPL_TEXT, sptr->name, MODE_I);
+ sendto_one(sptr, ":%s %i %s :TRUEHUB: %i", me.name, RPL_TEXT, sptr->name, TRUEHUB);
+ sendto_one(sptr, ":%s %i %s :SHOWOPERS: %i", me.name, RPL_TEXT, sptr->name, SHOWOPERS);
+ sendto_one(sptr, ":%s %i %s :KILLDIFF: %i", me.name, RPL_TEXT, sptr->name, KILLDIFF);
+ sendto_one(sptr, ":%s %i %s :SHOWOPERMOTD: %i", me.name, RPL_TEXT, sptr->name, SHOWOPERMOTD);
+ sendto_one(sptr, ":%s %i %s :HIDE_ULINES: %i", me.name, RPL_TEXT, sptr->name, HIDE_ULINES);
+ sendto_one(sptr, ":%s %i %s :ALLOW_CHATOPS: %i", me.name, RPL_TEXT, sptr->name, ALLOW_CHATOPS);
+ sendto_one(sptr, ":%s %i %s :SOCKS_BAN_MESSAGE: %s", me.name, RPL_TEXT, sptr->name, iConf.socksbanmessage);
+ sendto_one(sptr, ":%s %i %s :SOCKS_QUIT_MESSAGE: %s", me.name, RPL_TEXT, sptr->name, iConf.socksquitmessage);
+ sendto_one(sptr, ":%s %i %s :SOCKSBANTIME: %i",me.name, RPL_TEXT, sptr->name, iConf.socksbantime);
+}
+
+/* Report the network file info -codemastr */
+void report_network (aClient *sptr)
+{
+sendto_one(sptr, ":%s %i %s :*** Network Configuration Report ***", me.name, RPL_TEXT, sptr->name);
+sendto_one(sptr, ":%s %i %s :NETWORK: %s", me.name, RPL_TEXT, sptr->name, ircnetwork);
+sendto_one(sptr, ":%s %i %s :DEFAULT_SERVER: %s", me.name, RPL_TEXT, sptr->name, defserv);
+sendto_one(sptr, ":%s %i %s :SERVICES_NAME: %s", me.name, RPL_TEXT, sptr->name, SERVICES_NAME);
+sendto_one(sptr, ":%s %i %s :OPER_HOST: %s", me.name, RPL_TEXT, sptr->name, oper_host);
+sendto_one(sptr, ":%s %i %s :ADMIN_HOST: %s", me.name, RPL_TEXT, sptr->name, admin_host);
+sendto_one(sptr, ":%s %i %s :LOCOP_HOST: %s", me.name, RPL_TEXT, sptr->name, locop_host);
+sendto_one(sptr, ":%s %i %s :SADMIN_HOST: %s", me.name, RPL_TEXT, sptr->name, sadmin_host);
+sendto_one(sptr, ":%s %i %s :NETADMIN_HOST: %s", me.name, RPL_TEXT, sptr->name, netadmin_host);
+sendto_one(sptr, ":%s %i %s :COADMIN_HOST: %s", me.name, RPL_TEXT, sptr->name, coadmin_host);
+sendto_one(sptr, ":%s %i %s :TECHADMIN_HOST: %s", me.name, RPL_TEXT, sptr->name, techadmin_host);
+sendto_one(sptr, ":%s %i %s :HIDDEN_HOST: %s", me.name, RPL_TEXT, sptr->name, hidden_host);
+sendto_one(sptr, ":%s %i %s :NETDOMAIN: %s", me.name, RPL_TEXT, sptr->name, netdomain);
+sendto_one(sptr, ":%s %i %s :HELPCHAN: %s", me.name, RPL_TEXT, sptr->name, helpchan);
+sendto_one(sptr, ":%s %i %s :STATS_SERVER: %s", me.name, RPL_TEXT, sptr->name, STATS_SERVER);
+sendto_one(sptr, ":%s %i %s :INAH: %i", me.name, RPL_TEXT, sptr->name, iNAH);
+}
--- /dev/null
+/*
+ * fdlist.c maintain lists of certain important fds
+ */
+
+/* $Id$ */
+
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#include "h.h"
+#include "config.h"
+#include "fdlist.h"
+
+void
+addto_fdlist(int fd, fdlist * listp)
+{
+ int index;
+
+ if ((index = ++listp->last_entry) >= MAXCONNECTIONS) {
+ /*
+ * list too big.. must exit
+ */
+ --listp->last_entry;
+
+#ifdef USE_SYSLOG
+ (void) syslog(LOG_CRIT, "fdlist.c list too big.. must exit");
+#endif
+ abort();
+ }
+ else
+ listp->entry[index] = fd;
+ return;
+}
+
+void
+delfrom_fdlist(int fd, fdlist * listp)
+{
+ int i;
+
+ for (i = listp->last_entry; i; i--) {
+ if (listp->entry[i] == fd)
+ break;
+ }
+ if (!i)
+ return; /*
+ * could not find it!
+ */
+ /*
+ * swap with last_entry
+ */
+ if (i == listp->last_entry) {
+ listp->entry[i] = 0;
+ listp->last_entry--;
+ return;
+ }
+ else {
+ listp->entry[i] = listp->entry[listp->last_entry];
+ listp->entry[listp->last_entry] = 0;
+ listp->last_entry--;
+ return;
+ }
+}
+
+void
+init_fdlist(fdlist * listp)
+{
+ listp->last_entry = 0;
+ memset((char *) listp->entry, '\0', sizeof(listp->entry));
+ return;
+}
--- /dev/null
+ /************************************************************************
+ * IRC - Internet Relay Chat, ircd/hash.c
+ * Copyright (C) 1991 Darren Reed
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <limits.h>
+#include "numeric.h"
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#include "hash.h"
+#include "h.h"
+
+ID_CVS("$Id$");
+ID_Copyright("(C) 1991 Darren Reed");
+ID_Notes("2.10 7/3/93");
+
+/* Quick & dirty inline version of mycmp for hash-tables -Donwulff */
+#define thecmp(str1, str2, where) { \
+ register char *st1=str1, *st2=str2; \
+ while (tolower(*st1)==tolower(*st2)) \
+ { \
+ if (!*st1) goto where; \
+ st1++; st2++; \
+ } \
+ }
+
+#ifdef DEBUGMODE
+static aHashEntry *clientTable = NULL;
+static aHashEntry *channelTable = NULL;
+static int clhits, clmiss;
+static int chhits, chmiss;
+int HASHSIZE = 32003;
+int CHANNELHASHSIZE = 10007;
+#else /* DEBUGMODE */
+static aHashEntry clientTable[HASHSIZE];
+static aHashEntry channelTable[CHANNELHASHSIZE];
+#endif /* DEBUGMODE */
+
+static aNotify *notifyTable[NOTIFYHASHSIZE];
+
+/*
+ * Hashing.
+ *
+ * The server uses a chained hash table to provide quick and efficient
+ * hash table mantainence (providing the hash function works evenly over
+ * the input range). The hash table is thus not susceptible to problems
+ * of filling all the buckets or the need to rehash.
+ * It is expected that the hash table would look somehting like this
+ * during use:
+ * +-----+ +-----+ +-----+ +-----+
+ * ---| 224 |----| 225 |----| 226 |---| 227 |---
+ * +-----+ +-----+ +-----+ +-----+
+ * | | |
+ * +-----+ +-----+ +-----+
+ * | A | | C | | D |
+ * +-----+ +-----+ +-----+
+ * |
+ * +-----+
+ * | B |
+ * +-----+
+ *
+ * A - GOPbot, B - chang, C - hanuaway, D - *.mu.OZ.AU
+ *
+ * The order shown above is just one instant of the server. Each time a
+ * lookup is made on an entry in the hash table and it is found, the entry
+ * is moved to the top of the chain.
+ */
+
+#ifndef ELFHASH
+/*
+ * hash_nn_name
+ *
+ * Well, extensive profiling seems to indicate that the hash-function
+ * is a major provider to ircd's CPU-usage after all, so we're using
+ * _really_ minimalistic hash-function and make up for it with huge
+ * hash-tables. -Donwulff
+ */
+unsigned int hash_nn_name (hname)
+const char *hname;
+{
+ unsigned int hash_value;
+
+ for ( hash_value = 0; *hname; ++hname)
+ hash_value = ( hash_value << 2 ) ^ tolower(*hname);
+
+ return ( hash_value );
+}
+#else
+/* Take equal propotions from the size of int on all arcitechtures */
+#define BITS_IN_int ( sizeof(int) * CHAR_BIT )
+#define THREE_QUARTERS ((int) ((BITS_IN_int * 3) / 4))
+#define ONE_EIGHTH ((int) (BITS_IN_int / 8))
+#define HIGH_BITS ( ~((unsigned int)(~0) >> ONE_EIGHTH ))
+
+unsigned int hash_nn_name (hname)
+const char *hname;
+{
+ unsigned int hash_value, i;
+
+ for ( hash_value = 0; *hname; ++hname )
+ {
+ /* Shift hash-value by one eights of int for adding every letter */
+ hash_value = ( hash_value << ONE_EIGHTH ) + tolower(*hname);
+ /* If the next shift would cause an overflow... */
+ if (( i = hash_value & HIGH_BITS ) != 0 )
+ /* Then wrap the upper quarter of bits back to the value */
+ hash_value = ( hash_value ^
+ ( i >> THREE_QUARTERS )) & ~HIGH_BITS;
+ }
+
+ return ( hash_value );
+}
+#endif
+
+/*
+ * clear_*_hash_table
+ *
+ * Nullify the hashtable and its contents so it is completely empty.
+ */
+void clear_client_hash_table()
+{
+#ifdef DEBUGMODE
+ clhits = 0;
+ clmiss = 0;
+ if (!clientTable)
+ clientTable = (aHashEntry *)MyMalloc(HASHSIZE *
+ sizeof(aHashEntry));
+#endif /* DEBUGMODE */
+
+ bzero((char *)clientTable, sizeof(aHashEntry) * HASHSIZE);
+}
+
+void clear_channel_hash_table()
+{
+#ifdef DEBUGMODE
+ chmiss = 0;
+ chhits = 0;
+ if (!channelTable)
+ channelTable = (aHashEntry *)MyMalloc(CHANNELHASHSIZE *
+ sizeof(aHashEntry));
+#endif /* DEBUGMODE */
+ bzero((char *)channelTable, sizeof(aHashEntry) * CHANNELHASHSIZE);
+}
+
+void clear_notify_hash_table(void)
+{
+ bzero((char *)notifyTable, sizeof(notifyTable));
+}
+
+/*
+ * add_to_client_hash_table
+ */
+int add_to_client_hash_table(name, cptr)
+char *name;
+aClient *cptr;
+{
+ int hashv;
+ aClient *acptr;
+
+ hashv = hash_nn_name(name)%HASHSIZE;
+
+#ifdef DEBUGMODE
+ if(acptr=(aClient *)clientTable[hashv].list) {
+ while(acptr&&mycmp(acptr->name,name)) acptr=acptr->hnext;
+ if(acptr) dumpcore("add_to_client_hash_table %s",name);
+ }
+ cptr->hnext = (aClient *)clientTable[hashv].list;
+ clientTable[hashv].list = (void *)cptr;
+ clientTable[hashv].links++;
+ clientTable[hashv].hits++;
+#else /* DEBUGMODE */
+#ifdef INSERTCHECK
+ if(acptr=(aClient *)clientTable[hashv]) {
+ while(acptr&&mycmp(acptr->name,name)) acptr=acptr->hnext;
+ if(acptr) dumpcore("add_to_client_hash_table %s",name);
+ }
+#endif /* INSERTCHECK */
+ cptr->hnext = (aClient *)clientTable[hashv];
+ clientTable[hashv] = (void *)cptr;
+#endif /* DEBUGMODE */
+ return 0;
+}
+
+/*
+ * add_to_channel_hash_table
+ */
+int add_to_channel_hash_table(name, chptr)
+char *name;
+aChannel *chptr;
+{
+ int hashv;
+ aChannel *chan;
+
+ hashv = hash_nn_name(name)%CHANNELHASHSIZE;
+
+#ifdef DEBUGMODE
+ if(chan=(aChannel *)channelTable[hashv].list) {
+ while(chan&&mycmp(chan->chname,name)) chan=chan->hnextch;
+ if(chan) dumpcore("add_to_channel_hash_table %s",name);
+ }
+ chptr->hnextch = (aChannel *)channelTable[hashv].list;
+ channelTable[hashv].list = (void *)chptr;
+ channelTable[hashv].links++;
+ channelTable[hashv].hits++;
+#else /* DEBUGMODE */
+#ifdef INSERTCHECK
+ if(chan=(aChannel *)channelTable[hashv]) {
+ while(chan&&mycmp(chan->chname,name)) chan=chan->hnextch;
+ if(chan) dumpcore("add_to_channel_hash_table %s",name);
+ }
+#endif /* INSERTCHECK */
+ chptr->hnextch = (aChannel *)channelTable[hashv];
+ channelTable[hashv] = (void *)chptr;
+#endif /* DEBUGMODE */
+ return 0;
+}
+
+/*
+ * Rough figure of the datastructures for notify:
+ *
+ * NOTIFY HASH cptr1
+ * | |- nick1
+ * nick1-|- cptr1 |- nick2
+ * | |- cptr2 cptr3
+ * | |- cptr3 cptr2 |- nick1
+ * | |- nick1
+ * nick2-|- cptr2 |- nick2
+ * |- cptr1
+ *
+ * add-to-notify-hash-table:
+ * del-from-notify-hash-table:
+ * hash-del-notify-list:
+ * hash-check-notify:
+ * hash-get-notify:
+ */
+
+/*
+ * count_watch_memory
+ */
+void count_watch_memory(count, memory)
+int *count;
+u_long *memory;
+{
+ int i = NOTIFYHASHSIZE;
+ aNotify *anptr;
+
+
+ while (i--) {
+ anptr = notifyTable[i];
+ while (anptr) {
+ (*count)++;
+ (*memory) += sizeof(aNotify)+strlen(anptr->nick);
+ anptr = anptr->hnext;
+ }
+ }
+}
+
+/*
+ * add_to_notify_hash_table
+ */
+int add_to_notify_hash_table(nick, cptr)
+char *nick;
+aClient *cptr;
+{
+ int hashv;
+ aNotify *anptr;
+ Link *lp;
+
+
+ /* Get the right bucket... */
+ hashv = hash_nn_name(nick)%NOTIFYHASHSIZE;
+
+ /* Find the right nick (header) in the bucket, or NULL... */
+ if ((anptr = (aNotify *)notifyTable[hashv]))
+ while (anptr && mycmp(anptr->nick, nick))
+ anptr = anptr->hnext;
+
+ /* If found NULL (no header for this nick), make one... */
+ if (!anptr) {
+ anptr = (aNotify *)MyMalloc(sizeof(aNotify)+strlen(nick));
+ anptr->lasttime = 0;
+ strcpy(anptr->nick, nick);
+
+ anptr->notify = NULL;
+
+ anptr->hnext = notifyTable[hashv];
+ notifyTable[hashv] = anptr;
+ }
+
+ /* Is this client already on the notify-list? */
+ if ((lp = anptr->notify))
+ while (lp && (lp->value.cptr != cptr))
+ lp = lp->next;
+
+ /* No it isn't, so add it in the bucket and client addint it */
+ if (!lp) {
+ lp = anptr->notify;
+ anptr->notify = make_link();
+ anptr->notify->value.cptr = cptr;
+ anptr->notify->next = lp;
+
+ lp = make_link();
+ lp->next = cptr->notify;
+ lp->value.nptr = anptr;
+ cptr->notify = lp;
+ cptr->notifies++;
+ }
+
+ return 0;
+}
+
+/*
+ * hash_check_notify
+ */
+int hash_check_notify(cptr, reply)
+aClient *cptr;
+int reply;
+{
+ int hashv;
+ aNotify *anptr;
+ Link *lp;
+
+
+ /* Get us the right bucket */
+ hashv = hash_nn_name(cptr->name)%NOTIFYHASHSIZE;
+
+ /* Find the right header in this bucket */
+ if ((anptr = (aNotify *)notifyTable[hashv]))
+ while (anptr && mycmp(anptr->nick, cptr->name))
+ anptr = anptr->hnext;
+ if (!anptr)
+ return 0; /* This nick isn't on notify */
+
+ /* Update the time of last change to item */
+ anptr->lasttime = time(NULL);
+
+ /* Send notifies out to everybody on the list in header */
+ for (lp = anptr->notify; lp; lp = lp->next)
+ sendto_one(lp->value.cptr, rpl_str(reply), me.name,
+ lp->value.cptr->name, cptr->name,
+ (IsPerson(cptr)?cptr->user->username:"<N/A>"),
+ (IsPerson(cptr)?
+ (IsHidden(cptr) ? cptr->user->virthost : cptr->user->realhost) :"<N/A>"),
+ anptr->lasttime, cptr->info);
+
+ return 0;
+}
+
+/*
+ * hash_get_notify
+ */
+aNotify *hash_get_notify(name)
+char *name;
+{
+ int hashv;
+ aNotify *anptr;
+
+
+ hashv = hash_nn_name(name)%NOTIFYHASHSIZE;
+
+ if ((anptr = (aNotify *)notifyTable[hashv]))
+ while (anptr && mycmp(anptr->nick, name))
+ anptr = anptr->hnext;
+
+ return anptr;
+}
+
+/*
+ * del_from_notify_hash_table
+ */
+int del_from_notify_hash_table(nick, cptr)
+char *nick;
+aClient *cptr;
+{
+ int hashv;
+ aNotify *anptr, *nlast = NULL;
+ Link *lp, *last = NULL;
+
+
+ /* Get the bucket for this nick... */
+ hashv = hash_nn_name(nick)%NOTIFYHASHSIZE;
+
+ /* Find the right header, maintaining last-link pointer... */
+ if ((anptr = (aNotify *)notifyTable[hashv]))
+ while (anptr && mycmp(anptr->nick, nick)) {
+ nlast = anptr;
+ anptr = anptr->hnext;
+ }
+ if (!anptr)
+ return 0; /* No such notify */
+
+ /* Find this client from the list of notifies... with last-ptr. */
+ if ((lp = anptr->notify))
+ while (lp && (lp->value.cptr != cptr)) {
+ last = lp;
+ lp = lp->next;
+ }
+ if (!lp)
+ return 0; /* No such client to notify */
+
+ /* Fix the linked list under header, then remove the notify entry */
+ if (!last)
+ anptr->notify = lp->next;
+ else
+ last->next = lp->next;
+ free_link(lp);
+
+ /* Do the same regarding the links in client-record... */
+ last = NULL;
+ if ((lp = cptr->notify))
+ while (lp && (lp->value.nptr != anptr)) {
+ last = lp;
+ lp = lp->next;
+ }
+
+ /*
+ * Give error on the odd case... probobly not even neccessary
+ *
+ * No error checking in ircd is unneccessary ;) -Cabal95
+ */
+ if (!lp)
+ sendto_ops("WATCH debug error: del_from_notify_hash_table "
+ "found a watch entry with no client "
+ "counterpoint processing nick %s on client %s!",
+ nick, cptr->user);
+ else {
+ if (!last) /* First one matched */
+ cptr->notify = lp->next;
+ else
+ last->next = lp->next;
+ free_link(lp);
+ }
+
+ /* In case this header is now empty of notices, remove it */
+ if (!anptr->notify) {
+ if (!nlast)
+ notifyTable[hashv] = anptr->hnext;
+ else
+ nlast->hnext = anptr->hnext;
+ MyFree(anptr);
+ }
+
+ /* Update count of notifies on nick */
+ cptr->notifies--;
+
+ return 0;
+}
+
+/*
+ * hash_del_notify_list
+ */
+int hash_del_notify_list(cptr)
+aClient *cptr;
+{
+ int hashv;
+ aNotify *anptr;
+ Link *np, *lp, *last;
+
+
+ if (!(np = cptr->notify))
+ return 0; /* Nothing to do */
+
+ cptr->notify = NULL; /* Break the notify-list for client */
+ while (np) {
+ /* Find the notify-record from hash-table... */
+ anptr = np->value.nptr;
+ last = NULL;
+ for (lp = anptr->notify; lp && (lp->value.cptr != cptr);
+ lp = lp->next)
+ last = lp;
+
+ /* Not found, another "worst case" debug error */
+ if (!lp)
+ sendto_ops("WATCH Debug error: hash_del_notify_list "
+ "found a WATCH entry with no table "
+ "counterpoint processing client %s!",
+ cptr->name);
+ else {
+ /* Fix the notify-list and remove entry */
+ if (!last)
+ anptr->notify = lp->next;
+ else
+ last->next = lp->next;
+ free_link(lp);
+
+ /*
+ * If this leaves a header without notifies,
+ * remove it. Need to find the last-pointer!
+ */
+ if (!anptr->notify) {
+ aNotify *np2, *nl;
+
+ hashv = hash_nn_name(anptr->nick)%NOTIFYHASHSIZE;
+
+ nl = NULL;
+ np2 = notifyTable[hashv];
+ while (np2 != anptr) {
+ nl = np2;
+ np2 = np2->hnext;
+ }
+
+ if (nl)
+ nl->hnext = anptr->hnext;
+ else
+ notifyTable[hashv] = anptr->hnext;
+ MyFree(anptr);
+ }
+ }
+
+ lp = np; /* Save last pointer processed */
+ np = np->next; /* Jump to the next pointer */
+ free_link(lp); /* Free the previous */
+ }
+
+ cptr->notifies = 0;
+
+ return 0;
+}
+
+
+/*
+ * del_from_client_hash_table
+ */
+int del_from_client_hash_table(name, cptr)
+char *name;
+aClient *cptr;
+{
+ Reg1 aClient *tmp, *prev = NULL;
+ Reg2 int hashv;
+
+ hashv = hash_nn_name(name)%HASHSIZE;
+#ifdef DEBUGMODE
+ for (tmp = (aClient *)clientTable[hashv].list; tmp; tmp = tmp->hnext)
+ {
+ if (tmp == cptr)
+ {
+ if (prev)
+ prev->hnext = tmp->hnext;
+ else
+ clientTable[hashv].list = (void *)tmp->hnext;
+ tmp->hnext = NULL;
+ if (clientTable[hashv].links > 0)
+ {
+ clientTable[hashv].links--;
+ return 1;
+ }
+ else
+ /*
+ * Should never actually return from here and
+ * if we do it is an error/inconsistency in the
+ * hash table.
+ */
+ return -1;
+ return 0; /* Found, we can return -Donwulff */
+ }
+ prev = tmp;
+ }
+#else /* DEBUGMODE */
+ for (tmp = (aClient *)clientTable[hashv]; tmp; tmp = tmp->hnext) {
+ if (tmp == cptr) {
+ if (prev)
+ prev->hnext = tmp->hnext;
+ else
+ clientTable[hashv] = (void *)tmp->hnext;
+ tmp->hnext = NULL;
+ return 0; /* Found, we can return -Donwulff */
+ }
+ prev = tmp;
+ }
+#endif /* DEBUGMODE */
+ return 0;
+}
+
+/*
+ * del_from_channel_hash_table
+ */
+int del_from_channel_hash_table(name, chptr)
+char *name;
+aChannel *chptr;
+{
+ Reg1 aChannel *tmp, *prev = NULL;
+ Reg2 int hashv;
+
+ hashv = hash_nn_name(name)%CHANNELHASHSIZE;
+#ifdef DEBUGMODE
+ for (tmp = (aChannel *)channelTable[hashv].list; tmp;
+ tmp = tmp->hnextch)
+ {
+ if (tmp == chptr)
+ {
+ if (prev)
+ prev->hnextch = tmp->hnextch;
+ else
+ channelTable[hashv].list=(void *)tmp->hnextch;
+ tmp->hnextch = NULL;
+ if (channelTable[hashv].links > 0)
+ {
+ channelTable[hashv].links--;
+ return 1;
+ }
+ else
+ return -1;
+ return 0; /* Found, we can return -Donwulff */
+ }
+ prev = tmp;
+ }
+#else /* DEBUGMODE */
+ for (tmp = (aChannel *)channelTable[hashv]; tmp; tmp = tmp->hnextch) {
+ if (tmp == chptr) {
+ if (prev)
+ prev->hnextch = tmp->hnextch;
+ else
+ channelTable[hashv]=(void *)tmp->hnextch;
+ tmp->hnextch = NULL;
+ return 0; /* Found, we can return -Donwulff */
+ }
+ prev = tmp;
+ }
+#endif /* DEBUGMODE */
+ return 0;
+}
+
+
+/*
+ * hash_get_chan_bucket
+ */
+aChannel *hash_get_chan_bucket(hashv)
+int hashv;
+{
+ if (hashv > CHANNELHASHSIZE)
+ return NULL;
+#ifdef DEBUGMODE
+ return (aChannel *)channelTable[hashv].list;
+#else
+ return (aChannel *)channelTable[hashv];
+#endif
+}
+
+
+/*
+ * hash_find_client
+ */
+aClient *hash_find_client(name, cptr)
+char *name;
+aClient *cptr;
+{
+ Reg1 aClient *tmp;
+ Reg2 aClient *prv = NULL;
+#ifdef DEBUGMODE
+ Reg3 aHashEntry *tmp3;
+#endif /* DEBUGMODE */
+ int hashv;
+
+ hashv = hash_nn_name(name)%HASHSIZE;
+
+ /*
+ * Got the bucket, now search the chain.
+ */
+#ifdef DEBUGMODE
+tmp3 = &clientTable[hashv];
+
+ for (tmp = (aClient *)tmp3->list; tmp; prv = tmp, tmp = tmp->hnext)
+ thecmp(name, tmp->name, c_move_to_top);
+ clmiss++;
+ return (cptr);
+c_move_to_top:
+ clhits++;
+ /*
+ * If the member of the hashtable we found isnt at the top of its
+ * chain, put it there. This builds a most-frequently used order into
+ * the chains of the hash table, giving speadier lookups on those nicks
+ * which are being used currently. This same block of code is also
+ * used for channels and servers for the same performance reasons.
+ */
+ if (prv)
+ {
+ aClient *tmp2;
+
+ tmp2 = (aClient *)tmp3->list;
+ tmp3->list = (void *)tmp;
+ prv->hnext = tmp->hnext;
+ tmp->hnext = tmp2;
+ }
+#else /* DEBUGMODE */
+ for (tmp = (aClient *)clientTable[hashv]; tmp; prv = tmp, tmp = tmp->hnext)
+ thecmp(name, tmp->name, c_move_to_top);
+ return (cptr);
+c_move_to_top:
+ if (prv) {
+ aClient *tmp2;
+
+ tmp2 = (aClient *)clientTable[hashv];
+ clientTable[hashv] = (void *)tmp;
+ prv->hnext = tmp->hnext;
+ tmp->hnext = tmp2;
+ }
+#endif /* DEBUGMODE */
+ return (tmp);
+}
+
+/*
+ * hash_find_nickserver
+ */
+aClient *hash_find_nickserver(name, cptr)
+char *name;
+aClient *cptr;
+{
+ Reg1 aClient *tmp;
+ Reg2 aClient *prv = NULL;
+#ifdef DEBUGMODE
+ Reg3 aHashEntry *tmp3;
+#endif /* DEBUGMODE */
+ int hashv;
+ char *serv;
+
+ serv = index(name, '@');
+ *serv++ = '\0';
+ hashv = hash_nn_name(name)%HASHSIZE;
+
+ /*
+ * Got the bucket, now search the chain.
+ */
+#ifdef DEBUGMODE
+tmp3 = &clientTable[hashv];
+ for (tmp = (aClient *)tmp3->list; tmp; prv = tmp, tmp = tmp->hnext)
+ if (tmp->user &&
+ mycmp(name, tmp->name) == 0 &&
+ mycmp(serv, tmp->user->server) == 0)
+ goto c_move_to_top;
+
+ clmiss++;
+/* *--serv = '\0'; */ /* This code has no function, perhaps meant @? */
+ return (cptr); /* For now, just remarking it out... -Donwulff */
+
+c_move_to_top:
+ clhits++;
+ if (prv)
+ {
+ aClient *tmp2;
+
+ tmp2 = (aClient *)tmp3->list;
+ tmp3->list = (void *)tmp;
+ prv->hnext = tmp->hnext;
+ tmp->hnext = tmp2;
+ }
+#else /* DEBUGMODE */
+ for (tmp = (aClient *)clientTable[hashv]; tmp; prv = tmp, tmp = tmp->hnext)
+ if (tmp->user &&
+ mycmp(name, tmp->name) == 0 &&
+ mycmp(serv, tmp->user->server) == 0)
+ goto c_move_to_top;
+/* *--serv = '\0'; */ /* This code has no function, perhaps meant @? */
+ return (cptr); /* For now, just remarking it out... -Donwulff */
+
+c_move_to_top:
+ if (prv) {
+ aClient *tmp2;
+
+ tmp2 = (aClient *)clientTable[hashv];
+ clientTable[hashv] = (void *)tmp;
+ prv->hnext = tmp->hnext;
+ tmp->hnext = tmp2;
+ }
+#endif /* DEBUGMODE */
+/* *--serv = '\0'; */ /* This code has no function, perhaps meant @? */
+ return (tmp); /* For now, just remarking it out... -Donwulff */
+}
+
+/*
+ * hash_find_server
+ */
+aClient *hash_find_server(server, cptr)
+char *server;
+aClient *cptr;
+{
+ Reg1 aClient *tmp, *prv = NULL;
+ Reg2 char *t;
+ Reg3 char ch;
+#ifdef DEBUGMODE
+ aHashEntry *tmp3;
+#endif /* DEBUGMODE */
+
+ int hashv;
+
+ hashv = hash_nn_name(server)%HASHSIZE;
+
+#ifdef DEBUGMODE
+ tmp3 = &clientTable[hashv];
+
+ for (tmp = (aClient *)tmp3->list; tmp; prv = tmp, tmp = tmp->hnext)
+ {
+ if (!IsServer(tmp) && !IsMe(tmp))
+ continue;
+ thecmp(server, tmp->name, s_move_to_top);
+ }
+#else /* DEBUGMODE */
+ for (tmp = (aClient *)clientTable[hashv]; tmp; prv = tmp, tmp = tmp->hnext) {
+ if (!IsServer(tmp) && !IsMe(tmp))
+ continue;
+ thecmp(server, tmp->name, s_move_to_top);
+ }
+#endif /* DEBUGMODE */
+ t = ((char *)server + strlen(server));
+ /*
+ * Whats happening in this next loop ? Well, it takes a name like
+ * foo.bar.edu and proceeds to search for *.edu and then *.bar.edu.
+ * This is for checking full server names against masks although
+ * it isnt often done this way in lieu of using match().
+ */
+ for (;;)
+ {
+ t--;
+ for (; t > server; t--)
+ if (*(t+1) == '.')
+ break;
+ if (t <= server || *t == '*')
+ break;
+ ch = *t;
+ *t = '*';
+ /*
+ * Dont need to check IsServer() here since nicknames cant
+ *have *'s in them anyway.
+ */
+ if (((tmp = hash_find_client(t, cptr))) != cptr)
+ {
+ *t = ch;
+ return (tmp);
+ }
+ *t = ch;
+ }
+#ifdef DEBUGMODE
+ clmiss++;
+ return (cptr);
+s_move_to_top:
+ clhits++;
+
+ if (prv)
+ {
+ aClient *tmp2;
+
+ tmp2 = (aClient *)tmp3->list;
+ tmp3->list = (void *)tmp;
+ prv->hnext = tmp->hnext;
+ tmp->hnext = tmp2;
+ }
+#else /* DEBUGMODE */
+ return (cptr);
+s_move_to_top:
+ if (prv) {
+ aClient *tmp2;
+
+ tmp2 = (aClient *)clientTable[hashv];
+ clientTable[hashv] = (void *)tmp;
+ prv->hnext = tmp->hnext;
+ tmp->hnext = tmp2;
+ }
+#endif /* DEBUGMODE */
+ return (tmp);
+}
+
+/*
+ * hash_find_channel
+ */
+aChannel *hash_find_channel(name, chptr)
+char *name;
+aChannel *chptr;
+{
+ int hashv;
+ Reg1 aChannel *tmp;
+ Reg2 aChannel *prv = NULL;
+#ifdef DEBUGMODE
+ aHashEntry *tmp3;
+#endif /* DEBUGMODE */
+ hashv = hash_nn_name(name)%CHANNELHASHSIZE;
+
+#ifdef DEBUGMODE
+ tmp3 = &channelTable[hashv];
+
+ for (tmp = (aChannel *)tmp3->list; tmp; prv = tmp, tmp = tmp->hnextch)
+ thecmp(name, tmp->chname, c_move_to_top);
+ chmiss++;
+ return chptr;
+c_move_to_top:
+ chhits++;
+ if (prv)
+ {
+ register aChannel *tmp2;
+
+ tmp2 = (aChannel *)tmp3->list;
+ tmp3->list = (void *)tmp;
+ prv->hnextch = tmp->hnextch;
+ tmp->hnextch = tmp2;
+ }
+#else /* DEBUGMODE */
+ for (tmp = (aChannel *)channelTable[hashv]; tmp; prv = tmp, tmp = tmp->hnextch)
+ thecmp(name, tmp->chname, c_move_to_top);
+ return chptr;
+c_move_to_top:
+ if(prv) {
+ register aChannel *tmp2;
+
+ tmp2 = (aChannel *)channelTable[hashv];
+ channelTable[hashv] = (void *)tmp;
+ prv->hnextch = tmp->hnextch;
+ tmp->hnextch = tmp2;
+ }
+#endif /* DEBUGMODE */
+ return (tmp);
+}
+
+/*
+ * NOTE: this command is not supposed to be an offical part of the ircd
+ * protocol. It is simply here to help debug and to monitor the
+ * performance of the hash functions and table, enabling a better
+ * algorithm to be sought if this one becomes troublesome.
+ * -avalon
+ */
+
+int m_hash(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+#ifndef DEBUGMODE
+ return 0;
+#else
+ register int l, i;
+ register aHashEntry *tab;
+ int deepest = 0, deeplink = 0, showlist = 0, tothits = 0;
+ int mosthit = 0, mosthits = 0, used = 0, used_now = 0, totlink = 0;
+ int link_pop[10], size = HASHSIZE;
+ char ch;
+ aHashEntry *table;
+
+ if(!IsPrivileged(sptr)) return 0;
+
+ if (parc > 1) {
+ ch = *parv[1];
+ if (islower(ch))
+ table = clientTable;
+ else {
+ table = channelTable;
+ size = CHANNELHASHSIZE;
+ }
+ if (ch == 'L' || ch == 'l')
+ showlist = 1;
+ } else {
+ ch = '\0';
+ table = clientTable;
+ }
+
+ for (i = 0; i < 10; i++)
+ link_pop[i] = 0;
+ for (i = 0; i < size; i++) {
+ tab = &table[i];
+ l = tab->links;
+ if (showlist)
+ sendto_one(sptr,
+ "NOTICE %s :Hash Entry:%6d Hits:%7d Links:%6d",
+ parv[0], i, tab->hits, l);
+ if (l > 0) {
+ if (l < 10)
+ link_pop[l]++;
+ else
+ link_pop[9]++;
+ used_now++;
+ totlink += l;
+ if (l > deepest) {
+ deepest = l;
+ deeplink = i;
+ }
+ }
+ else
+ link_pop[0]++;
+ l = tab->hits;
+ if (l) {
+ used++;
+ tothits += l;
+ if (l > mosthits) {
+ mosthits = l;
+ mosthit = i;
+ }
+ }
+ }
+ switch((int)ch)
+ {
+ case 'V' : case 'v' :
+ {
+ register aClient *acptr;
+ int bad = 0, listlength = 0;
+
+ for (acptr = client; acptr; acptr = acptr->next) {
+ if (hash_find_client(acptr->name,acptr) != acptr) {
+ if (ch == 'V')
+ sendto_one(sptr, "NOTICE %s :Bad hash for %s",
+ parv[0], acptr->name);
+ bad++;
+ }
+ listlength++;
+ }
+ sendto_one(sptr,"NOTICE %s :List Length: %d Bad Hashes: %d",
+ parv[0], listlength, bad);
+ }
+ case 'P' : case 'p' :
+ for (i = 0; i < 10; i++)
+ sendto_one(sptr,"NOTICE %s :Entires with %d links : %d",
+ parv[0], i, link_pop[i]);
+ return (0);
+ case 'r' :
+ {
+ Reg1 aClient *acptr;
+
+ sendto_one(sptr,"NOTICE %s :Rehashing Client List.", parv[0]);
+ clear_client_hash_table();
+ for (acptr = client; acptr; acptr = acptr->next)
+ (void)add_to_client_hash_table(acptr->name, acptr);
+ break;
+ }
+ case 'R' :
+ {
+ Reg1 aChannel *acptr;
+
+ sendto_one(sptr,"NOTICE %s :Rehashing Channel List.", parv[0]);
+ clear_channel_hash_table();
+ for (acptr = channel; acptr; acptr = acptr->nextch)
+ (void)add_to_channel_hash_table(acptr->chname, acptr);
+ break;
+ }
+ case 'H' :
+ if (parc > 2)
+ sendto_one(sptr,"NOTICE %s :%s hash to entry %d",
+ parv[0], parv[2],
+ hash_nn_name(parv[2])%CHANNELHASHSIZE);
+ return (0);
+ case 'h' :
+ if (parc > 2)
+ sendto_one(sptr,"NOTICE %s :%s hash to entry %d",
+ parv[0], parv[2],
+ hash_nn_name(parv[2])%HASHSIZE);
+ return (0);
+/* Quick hack for getting memory statistics from list.c -Donwulff */
+ case 'm' :
+ send_listinfo(sptr, parv[0]);
+ return(0);
+ case 'n' :
+ {
+ aClient *tmp;
+ int max;
+
+ if (parc <= 2)
+ return (0);
+ l = atoi(parv[2]) % HASHSIZE;
+ if (parc > 3)
+ max = atoi(parv[3]) % HASHSIZE;
+ else
+ max = l;
+ for (;l <= max; l++)
+ for (i = 0, tmp = (aClient *)clientTable[l].list; tmp;
+ i++, tmp = tmp->hnext)
+ {
+ if (parv[1][2] == '1' && tmp != tmp->from)
+ continue;
+ sendto_one(sptr,"NOTICE %s :Node: %d #%d %s",
+ parv[0], l, i, tmp->name);
+ }
+ return (0);
+ }
+ case 'N' :
+ {
+ aChannel *tmp;
+ int max;
+
+ if (parc <= 2)
+ return (0);
+ l = atoi(parv[2]) % CHANNELHASHSIZE;
+ if (parc > 3)
+ max = atoi(parv[3]) % CHANNELHASHSIZE;
+ else
+ max = l;
+ for (;l <= max; l++)
+ for (i = 0, tmp = (aChannel *)channelTable[l].list; tmp;
+ i++, tmp = tmp->hnextch)
+ sendto_one(sptr,"NOTICE %s :Node: %d #%d %s",
+ parv[0], l, i, tmp->chname);
+ return (0);
+ }
+ case 'z' :
+ {
+ Reg1 aClient *acptr;
+
+ if (parc <= 2)
+ return 0;
+ l = atoi(parv[2]);
+ if (l < 256)
+ return 0;
+ (void)MyFree((char *)clientTable);
+ clientTable = (aHashEntry *)MyMalloc(sizeof(aHashEntry) * l);
+ HASHSIZE = l;
+ clear_client_hash_table();
+ for (acptr = client; acptr; acptr = acptr->next)
+ {
+ acptr->hnext = NULL;
+ (void)add_to_client_hash_table(acptr->name, acptr);
+ }
+ sendto_one(sptr, "NOTICE %s :HASHSIZE now %d", parv[0], l);
+ break;
+ }
+ case 'Z' :
+ {
+ Reg1 aChannel *acptr;
+
+ if (parc <= 2)
+ return 0;
+ l = atoi(parv[2]);
+ if (l < 256)
+ return 0;
+ (void)MyFree((char *)channelTable);
+ channelTable = (aHashEntry *)MyMalloc(sizeof(aHashEntry) * l);
+ CHANNELHASHSIZE = l;
+ clear_channel_hash_table();
+ for (acptr = channel; acptr; acptr = acptr->nextch)
+ {
+ acptr->hnextch = NULL;
+ (void)add_to_channel_hash_table(acptr->chname, acptr);
+ }
+ sendto_one(sptr, "NOTICE %s :CHANNELHASHSIZE now %d",
+ parv[0], l);
+ break;
+ }
+ default :
+ break;
+ }
+ sendto_one(sptr,"NOTICE %s :Entries Hashed: %d NonEmpty: %d of %d",
+ parv[0], totlink, used_now, size);
+ if (!used_now)
+ used_now = 1;
+ sendto_one(sptr,"NOTICE %s :Hash Ratio (av. depth): %f %%Full: %f",
+ parv[0], (float)((1.0 * totlink) / (1.0 * used_now)),
+ (float)((1.0 * used_now) / (1.0 * size)));
+ sendto_one(sptr,"NOTICE %s :Deepest Link: %d Links: %d",
+ parv[0], deeplink, deepest);
+ if (!used)
+ used = 1;
+ sendto_one(sptr,"NOTICE %s :Total Hits: %d Unhit: %d Av Hits: %f",
+ parv[0], tothits, size-used,
+ (float)((1.0 * tothits) / (1.0 * used)));
+ sendto_one(sptr,"NOTICE %s :Entry Most Hit: %d Hits: %d",
+ parv[0], mosthit, mosthits);
+ sendto_one(sptr,"NOTICE %s :Client hits %d miss %d",
+ parv[0], clhits, clmiss);
+ sendto_one(sptr,"NOTICE %s :Channel hits %d miss %d",
+ parv[0], chhits, chmiss);
+ return 0;
+#endif /* DEBUGMODE */
+}
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, ircd/help.c
+ * Copyright (C) 1996 DALnet
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Updated to use UnrealIRCd commands -Techie/Stskeeps
+ *
+*/
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#include "h.h"
+
+ID_CVS("$Id$");
+ID_Copyright("DALnet & Techie");
+ID_Notes("6.20 7/5/99");
+
+void xx(sptr, str, num)
+aClient *sptr;
+char *str;
+int num;
+{
+ if (sptr == NULL) {
+ printf("%s\n", str);
+ return;
+ }
+ sendto_one(sptr, ":%s %i %s :%s", me.name, num, sptr->name, str);
+}
+
+#define HDR(str) xx(sptr, str, 290)
+#define SND(str) xx(sptr, str, 291)
+#define FTR(str) xx(sptr, str, 292)
+#define HLP(str) xx(sptr, str, 293)
+
+/*
+ * This is _not_ the final help.c, we're just testing the functionality...
+ * Return 0 to forward request to helpops... -Donwulff
+ */
+extern struct Message msgtab[];
+int parse_help (sptr, name, help)
+aClient *sptr;
+char *name;
+char *help;
+{
+
+ int i;
+// sendto_one(sptr, ":%s NOTICE %s :%s", me.name, sptr->name, help);
+
+ if(BadPtr(help)) {
+HDR(" ***** \ 2UnrealIRCd Help System\ 2 *****");
+SND(" You need to specify your question after the help-command");
+SND(" If the IRC Server is unable to satisfy your help-request");
+SND(" it will be forwarded to appropriate people for handling.");
+SND(" Preceed your question with ! to automatically forward it to");
+SND(" qualified helpers, or ? to never forward it.");
+SND(" Else type /HELPOP CMDS to get some help on the IRCd");
+SND(" /HELPOP ABOUT gets some info about UnrealIRCd");
+ }
+ else if (!myncmp(help, "CMDS", 8)) {
+ HDR(" *** UnrealIRCd Commands *** ");
+ SND(" Currently help is available on these commands ");
+ SND(" Use /HelpOp <command name> to get info about the command");
+ SND(" WATCH HELPOP LIST");
+ SND(" PRIVMSG KNOCK LICENSE");
+ SND(" SETNAME MODE STATSERV");
+ SND(" CREDITS DALINFO");
+ SND(" ----------------------------");
+ SND(" OPERCMDS - IRCop Commands");
+ SND(" UMODES - Usermodes");
+ SND(" CHMODES - Channelmodes");
+ SND(" OFLAGS - O:Line flags");
+ SND(" -----------oOo------------");
+ }
+ else if (!myncmp(help, "ABOUT", 8)) {
+ HDR(" *** About UnrealIRCd ***");
+ SND("I started making UnrealIRCd about 3-4 months ago.");
+ SND("First it was called mpx2.0b13.soundforge - as I was");
+ SND("inspired of the 'forge' word. I quickly changed name");
+ SND("after I realized the IRCd had more potential for other");
+ SND("IRC nets. Unreal is based off df4.6.5 and some of");
+ SND("First lemme");
+ SND("introduce myself. My nick is Techie/Stskeeps. I hang");
+ SND("out at Global-IRC.net, DALnet, DragonWings.org and so on");
+ SND("--");
+ SND("Unreal is a hybrid of Dreamforge (as I said) mixed with some");
+ SND("Twilight IRCd, TerraIRCd, TS4 (channel mode +h & +e) features");
+ SND("(IMHO TwilightIRCd is one of the best dreamforge hybrids I've seen!)");
+ SND("Unreal is not a rip-off of other IRCds - I added a lot of features myself!");
+ SND("I really cannot mention some major features as I think a IRCd is a");
+ SND("IRCd when it has got useful commands- and people actually say mine has!");
+ SND("--");
+ SND("Anyways I dunt demand donations or anything. I just do coding for fun");
+ SND("I treat coding like playing with toys. It makes me happy(or is it just");
+ SND("caffeine?;). An addy to send donations is at the Donation file in the IRCd dir");
+ SND("I would be more happy if someone e-mailed me with ideas");
+ SND("to the IRCd.. The whole IRCd is GNU so if you want to rip off any of my ideas");
+ SND("You are generally welcome:) Just remember to do what's said in the Changes file!");
+ SND("-- So.. Enjoy this IRCd:)");
+ SND(" -- Carsten Munk / Techie .. =)");
+ }
+ else if (!myncmp(help, "WATCH", 8)) {
+ HDR(" *** WATCH Command ***");
+ SND("Watch is a new notify-type system in UnrealIRCd which is both faster");
+ SND("and uses less network resources than any old-style notify");
+ SND("system. You may add entries to your Watch list with the command");
+ SND("/watch +nick1 [+nick2 +nick3 ..., and the server will send");
+ SND("you a message when any nickname in your watch list logs on or off.");
+ SND("Use /watch -nick to remove a nickname from the watch list, and");
+ SND("just /watch to view your watch list.");
+ SND("The watch list DOES NOT REMAIN BETWEEN SESSIONS - you (or your");
+ SND("script or client) must add the nicknames to your watch list every");
+ SND("time you connect to an IRC server. /Watch was made in DreamForge IRCd");
+ SND("which UnrealIRCd in ground is based off");
+ }
+ else if (!myncmp(help, "HELPOP", 8)) {
+ HDR(" *** HELPOP Command ***");
+ SND("HelpOp is a new system of getting IRC Server help. You type either");
+ SND("/HelpOp ? <help system topic> or /HelpOp ! <question>");
+ SND("The ï?ï in /HelpOp means query the help system and if you get no");
+ SND("response you can choose '!' to send it to the Help Operators online");
+ SND("------------oOo--------------");
+ }
+ else if (!myncmp(help, "LIST", 8)) {
+ HDR(" *** LIST Command ***");
+ SND("New extended /list command options are supported. To use these");
+ SND("features, you will likely need to prefix the LIST command with");
+ SND("/quote to avoid your client interpreting the command.");
+ SND("");
+ SND("Usage: /quote LIST options");
+ SND("");
+ SND("If you don't include any options, the default is to send you the");
+ SND("entire unfiltered list of channels. Below are the options you can");
+ SND("use, and what channels LIST will return when you use them.");
+ SND(">number List channels with more than <number> people.");
+ SND("<number List channels with less than <number> people.");
+ SND("C>number List channels created between now and <number> minutes ago.");
+ SND("C<number List channels created earlier than <number> minutes ago.");
+ SND("T>number List channels whose topics are older than <number> minutes");
+ SND(" (Ie., they have not changed in the last <number> minutes.");
+ SND("T<number List channels whose topics are newer than <number> minutes.");
+ SND("*mask* List channels that match *mask*");
+ SND("!*mask* List channels that do not match *mask*");
+ SND("LIST defaults to sending a list of channels with 2 or more members,");
+ SND("so use the >0 option to get the full channel listing.");
+ }
+ else if (!myncmp(help, "PRIVMSG", 8)) {
+ HDR("*** PRIVMSG Command ***");
+ SND("PRIVMSG and NOTICE, which are used internally by the client for");
+ SND("/msg and /notice, in UnrealIRCd support two additional formats:");
+ SND("/msg @#channel <text> will send the text to channel-ops on the");
+ SND("given channel only. /msg @+#channel <text> will send the text");
+ SND("to both ops and voiced users on the channel. While some clients");
+ SND("may support these as-is, on others (such as ircII), it's necessary");
+ SND("to use/quote privmsg @#channel <text> instead. It's perhaps a");
+ SND("good idea to add the/alias omsg /quote privmsg @$0 $1 into");
+ SND("your script (.ircrc) file in that case.");
+ }
+ else if (!myncmp(help, "KNOCK", 8)) {
+ HDR("**** KNOCK Command ****");
+ SND("/Knock is a new UnrealIRCd command which enables you to");
+ SND("'knock' on a channel if it is +i and these criteria is met");
+ SND("- Channel is not +K (No knocks)");
+ SND("- Channel is not +I (No invites!)");
+ SND("- You're not banned!");
+ SND("- And you are not already there:)");
+ SND("Syntax:");
+ SND(" /Knock #Channel :Reason");
+ }
+
+ else if (!myncmp(help, "LICENSE", 8)) {
+ HDR("*** LICENSE Command ***");
+ SND("This command shows the GNU License");
+ SND("Which is hard-coded into the IRCd");
+ SND("Syntax: /License [optional server]");
+ }
+ else if (!myncmp(help, "SETNAME", 8)) {
+ HDR("*** SetName Command ***");
+ SND("/SetName is a new feature in UnrealIRCd");
+ SND("Which allows users to change their 'Real name'");
+ SND(" (GECOS) directly online at IRC without reconnecting");
+ SND("Syntax:");
+ SND(" /SetName :New Real Name");
+ }
+ else if (!myncmp(help, "MODE", 8)) {
+ HDR("*** MODE Command ***");
+ SND("This is basically the /mode command as it has always");
+ SND("been on IRC. Thou in Channel mode basis it has got an");
+ SND("Extra feature (/mode #Channel ^ ) which reports channel");
+ SND("modes represented in a bitstring (may be handy, maybe not)");
+ SND("UnrealIRCd has got some new channel / usermodes I think you");
+ SND("wish to take a look at");
+ SND("Channel Modes Help: /HelpOp CHMODES");
+ SND("User modes help: /HelpOp UMODES");
+ }
+ else if (!myncmp(help, "STATSERV", 8)) {
+ HDR("*** STATSERV Command ***");
+ SND("This is a alias for the /msg StatServ command,");
+ SND("But is more secure. If the IRC network doesn't have StatServ");
+ SND("It will report it is down.");
+ SND("Syntax:");
+ SND("/StatServ <command>");
+ }
+ else if (!myncmp(help, "CREDITS", 8)) {
+ HDR("*** /Credits Help ***");
+ SND("This command will list the credits I've created");
+ SND("to thank the people who has helped me with making");
+ SND("UnrealIRCd. Anyone who I've forgotten all my kind");
+ SND("thoughts go to -- Techie'99");
+ SND("Syntax:");
+ SND(" /Credits [optional server]");
+ }
+ else if (!myncmp(help, "DALINFO", 8)) {
+ HDR("*** /DALINFO Help ***");
+ SND("This command will list the credits that the");
+ SND("Dreamforge IRCd team/the IRCd developers");
+ SND("from the start when IRCd got developed");
+ SND("Syntax:");
+ SND(" /DALInfo [optional server]");
+ }
+ else if (!myncmp(help, "OPERCMDS", 8)) {
+ HDR("*** IRCop Commands Help ***");
+ SND("This section is the IRCOp's only commands");
+ SND("area:) - These topics are available:");
+ SND("Note: This doesnt include Dreamforge commands");
+ SND("-------------oOo---------------");
+ SND("SETHOST SETIDENT SDESC");
+ SND("ADCHAT NACHAT TECHAT");
+ SND("GLINE REMGLINE STATS");
+ SND("MKPASSWD SNOTES SNOTE");
+ SND("ADDLINE LAG RPING");
+ SND("ADDMOTD ADDOMOTD OPERMOTD");
+ SND("CHGHOST");
+ SND("-------------oOo---------------");
+ }
+ else if (!myncmp(help, "ADDMOTD", 8)) {
+ HDR("*** ADDMOTD Command Help ***");
+ SND("This will add the text you specify to the MOTD");
+ SND("(the general motd - T:lines doesnt count ..)");
+ SND("Server Admin & Co-Admin only");
+ SND("-");
+ SND("Syntax: /ADDMOTD :text");
+ }
+ else if (!myncmp(help, "ADDOMOTD", 8)) {
+ HDR("*** ADDOMOTD Command Help ***");
+ SND("This will add the text you specify to the Operator MOTD");
+ SND("Server Admin & Co-Admin only");
+ SND("-");
+ SND("Syntax: /ADDOMOTD :text");
+ }
+ else if (!myncmp(help, "CHGHOST", 8))
+ {
+ HDR("*** CHGHOST Command help ***");
+ SND("This command makes you able to change other people's virtual hostname");
+ SND("- IRCop only.");
+ SND("Syntax: /CHGHOST <nick> <newhost>");
+ }
+
+ else if (!myncmp(help, "OPERMOTD", 8)) {
+ HDR("*** OPERMOTD Command Help ***");
+ HDR("This is a IRCop only command - shows the IRCd Operator MOTD");
+ HDR("Syntax: /OperMotd");
+ }
+ else if (!myncmp(help, "SETHOST", 8)) {
+ HDR("*** SETHOST Command Help ***");
+ SND("This command is so you can change your");
+ SND("Virtual host (hiddenhost) to everything you want to");
+ SND("Except special characters;). Syntax:");
+ SND("/SetHost <new hostname>)");
+ SND("Example:");
+ SND(" /Sethost ircaddicts.org");
+ }
+ else if (!myncmp(help, "SETIDENT", 8)) {
+ HDR("*** SETIDENT Command Help ***");
+ SND("With this command you can change your");
+ SND("ident (username).");
+ SND("Syntax:");
+ SND("/SetIdent <new ident>");
+ SND("Example:");
+ SND(" /SetIdent root");
+ }
+ else if (!myncmp(help, "SDESC", 8)) {
+ HDR("*** SDesc Command help ***");
+ SND("NOTE: This is a Server Admin/Co Admin only command");
+ SND("With this command you can change your Server Info Line");
+ SND("Without having to squit and reconnect.");
+ SND("Syntax: /SDesc :New description");
+ SND("Example: /SDesc :If you belong to me..");
+ }
+ else if (!myncmp(help, "ADCHAT", 8)) {
+ HDR("*** AdChat Command Help ***");
+ SND("This command sends to all Admins online (IsAdmin)");
+ SND("Only for Admins. This is a ChatOps style command");
+ SND("Syntax: /AdChat :<text>");
+ SND("Example: /AdChat :Hey guys!");
+ }
+ else if (!myncmp(help, "NACHAT", 8)) {
+ HDR("*** NAChat Command Help ***");
+ SND("This command sends to all NetAdmins & TechAdmins online");
+ SND("Only for Net/Techadmins. This is a ChatOps style command");
+ SND("Syntax: /NAChat :<text>");
+ SND("Example: /NAChat :Hey guys!");
+ }
+
+ else if (!myncmp(help, "STATS", 8)) {
+ HDR("*** Stats Command Help ***");
+ SND("UnrealIRCd has got a extension called /Stats G");
+ SND("Which will list the current G:Lines");
+ SND("Syntax: /Stats G");
+ }
+ else if (!myncmp(help, "TECHAT", 8)) {
+ HDR("*** TEChat Command Help ***");
+ SND("This command sends to all TechAdmins online");
+ SND("Only for Net/Techadmins. This is a ChatOps style command");
+ SND("Syntax: /TEChat :<text>");
+ SND("Example: /TEChat :Hey guys!");
+ }
+ else if (!myncmp(help, "REMGLINE", 8)) {
+ HDR("*** RemGline Command Help");
+ SND("This command can remove G:Lines");
+ SND("Syntax:");
+ SND(" /RemGline <user@host mask>");
+ SND("Example:");
+ SND(" /RemGline *@*.flirt.org");
+ }
+ else if (!myncmp(help, "GLINE", 8)) {
+ HDR("*** G:line command Help ***");
+ SND("This command provides timed G:Lines. If you match");
+ SND("a G:Line you cannot connect to ANY server at the");
+ SND("IRC network");
+ SND("Syntax:");
+ SND(" /GLINE <user@host mask> <seconds to be banned> :<reason>");
+ SND("Example:");
+ SND(" /GLINE *@*.dal.net 900 :Spammers");
+ SND(" this will ban all users matching *@*.dal.net for 15 minutes");
+ SND(" with reason 'Spammers'");
+ }
+ else if (!myncmp(help, "MKPASSWD", 8)) {
+ HDR("*** MkPasswd Command help ***");
+ SND("This command will encrypt the string it has been given");
+ SND("So u can add it directly to the ircd.conf if you use");
+ SND("Encrypted passwords. /MKPassWd is disabled in UnrealIRCd/32");
+ SND("Syntax : /MkPasswd :string to be encrypted");
+ }
+ else if (!myncmp(help, "SNOTE", 8)) {
+ HDR("*** SNOTE Command Help ***");
+ SND("This will store the parameter of the command to a file");
+ SND("Which then can be read by using /SNOTES LIST");
+ SND("Syntax: /SNOTE :<message>");
+ }
+ else if (!myncmp(help, "SNOTES", 8)) {
+ HDR("*** SNOTES Command Help ***");
+ SND("This command is made to view notes");
+ SND("Written to the SNOTE file by using /SNOTE");
+ SND("Syntax: /SNOTES LIST");
+ SND(" or /SNOTES <number>");
+ }
+ else if (!myncmp(help, "ADDLINE",8)) {
+ HDR("*** ADDLINE Command Help ***");
+ SND("This command can be used to add lines to the ircd.conf file");
+ SND("Only for Server Admins");
+ SND("Syntax: /AddLine :<line>");
+ }
+ else if (!myncmp(help, "LAG", 8)) {
+ HDR("*** LAG Command Help ***");
+ SND("This command is like a sonar/traceroute for IRC servers");
+ SND("You type in /lag server1.irc.net and it will");
+ SND("reply from every server it passes with time and so on");
+ SND("Useful for looking where lag is and optional TS future/past travels");
+ SND("Syntax: /LAG <servername>");
+ }
+ else if (!myncmp(help, "RPING", 8)) {
+ HDR("*** RPING Command Help ***");
+ SND("This will calculate the milliseconds (lag) between servers");
+ SND("Syntax: /RPING <servermask>");
+ }
+ else if (!myncmp(help, "TSCTL", 8)) {
+ HDR("*** TSCTL Command Help ***");
+ SND("This is a highly advanced command");
+ SND("Syntax:");
+ SND(" /TSCTL OFFSET +|- <time> - Adjust internal IRC clock");
+ SND(" /TSCTL TIME - Will give TS report");
+ }
+ else if (!myncmp(help, "SAJOIN", 8)) {
+ HDR("*** SAJOIN Command help **");
+ SND("Makes <nick> join channel <channel>");
+ SND("Services Admin only..");
+ SND("Syntax: /SAJOIN nick channel");
+ }
+ else if(!myncmp(help, "UMODES", 8)) {
+ HDR("*** UnrealIRCd Usermodes ***");
+ SND("o = Global IRCop");
+ SND("O = Local IRCop");
+ SND("i = Invisible (Not shown in /who searches)");
+ SND("w = Can listen to wallop messages");
+ SND("g = Can read & send to globops, and locops");
+ SND("h = Available for help");
+ SND("s = Can listen to server notices");
+ SND("k = See's all the /KILL's which were executed");
+ SND("S = For services only. (Protects them)");
+ SND("a = Is a services admin");
+ SND("A = Is a server admin");
+ SND("N = Is a network admin");
+ SND("T = Is a tech admin");
+ SND("C = Is a co admin");
+ SND("c = See's all connects/disconnects on local server");
+ SND("f = Listen to flood alerts from server");
+ SND("r = Identifies the nick as being registered");
+ SND("x = Gives the user hidden hostname");
+ SND("e = Can listen to server messages sent to +e users");
+ SND("b = Can read & send to chatops");
+ SND("W = (IRCops only) Lets you see when people does a /whois on you");
+ SND("q = (Services Admins only) Gets you unable to be");
+ SND(" kicked unless by U:Lines");
+ SND("B = (users) Marks you being a Bot");
+ SND("F = (netadmins&techadmins) Lets you recieve far connect notices + local notices");
+ SND("I = (netadmins&techadmins) Invisible Join/Part. Makes you being hidden at channels");
+ SND("1 = (ircops only) Marks you being a Coder");
+ HDR("---------------------oOo-------------------");
+ }
+ else if(!myncmp(help, "CHMODES", 8)) {
+ HDR("*** UnrealIRCd Channel Modes ***");
+ SND("p = Private channel");
+ SND("s = Secret channel");
+ SND("i = Invite-only allowed");
+ SND("m = Moderated channel, noone can speak except users with mode +voh");
+ SND("n = No messages from outside channel");
+ SND("t = Only channel operators may set the topic");
+ SND("r = Channel is registered");
+ SND("R = Requires a registered nickname to join the channel");
+ SND("x = No ANSI color can be sent to the channel");
+ SND("q = Channel owner (The big cheese)");
+ SND("Q = No kicks able in channel unless by U:Lines");
+ SND("O = IRCop only channel (setable by Opers)");
+ SND("A = Server Admin | Network Admin | Tech Admin only channel (same as above)");
+ SND("K = /Knock is not allowed");
+ SND("I = /Invite is not allowed");
+ SND("S = Strip all incoming colours away");
+ SND("l <number of max users> = Channel may hold at most <number> of users");
+ SND("b <nick!user@host> = Bans the nick!user@host from the channel");
+ SND("k <key> = Needs the channel key to join the channel");
+ SND("o <nickname> = Gives operator status to the user");
+ SND("v <nickname> = Gives voice to the user (May talk if chan is +m)");
+ SND("L <chan2> = If +l is full, the next user will auto-join <chan2>");
+ SND("a <nickname> = Gives protection to the user (No kick/drop)");
+ SND("e <exception ban> = Exception ban - If someone matches it");
+ SND(" they can join even if some else ban matches!");
+ SND("h <nickname> = Gives halfop status to the user");
+ HDR("You can get additional explanation on modes:");
+ SND(" Q h");
+ SND("With /HELPOP mode-<x> where <x> is Q f.x. like mode-Q");
+ }
+ else if (!myncmp(help, "mode-Q", 8)) {
+ HDR("*** Channel mode +Q ***");
+ SND("This is the 'peace' mode. Noone can kick eachother");
+ SND("except by U:Lines. Bans can be placed thou.");
+ }
+ else if (!myncmp(help, "MODE-h", 8)) {
+ HDR("*** Channel halfops (+h) *** ");
+ SND("If you are marked as halfop (% in /names) you can do:");
+ SND(" - Set topic");
+ SND(" - Kick non-ops");
+ SND(" - Set modes +vmntibe");
+ }
+ else if(!myncmp(help, "OFLAGS", 8)) {
+ HDR("*** UnrealIRCd O:Line flags ***");
+ SND("r = Access to /rehash server");
+ SND("R = Access to /restart server");
+ SND("D = Access to /die server");
+ SND("h = Oper can send /help ops - gets +h on oper up");
+ SND("g = Oper can send /globops");
+ SND("w = Oper can send /wallops");
+ SND("l = Oper can send /locops");
+ SND("c = Access to do local /squits and /connects");
+ SND("Y = Access to do remote /squits and /connects");
+ SND("k = Access to do local /kills");
+ SND("K = Access to do global /kills");
+ SND("b = Oper can /kline users from server");
+ SND("B = Oper can /unkline users from server");
+ SND("n = Oper can send local server notices(/notice $servername message)");
+ SND("N = Oper can send global notices(/notice $*.network.net message)");
+ SND("u = Oper can set /umode +c");
+ SND("f = Oper can set /umode +f");
+ SND("o = Local oper, flags included: rhgwlckbBnuf");
+ SND("O = Global oper, flags included: oRDCKN");
+ SND("A = Gets +A on oper up. Is server admin");
+ SND("a = Gets +a on oper up. Is services admin");
+ SND("N = Gets +N on oper up. Is network admin");
+ SND("T = Gets +T on oper up. Is tech admin");
+ SND("C = Gets +C on oper up. Is co admin");
+ SND("z = Can add /zlines");
+ SND("H = Gets +x on oper up.");
+ SND("W = Gets +W on oper up.");
+ SND("^ = Allows to use umode +I");
+ SND("----------oOo-----------");
+ }
+ else if(!myncmp(help, "COMMANDS", 8)) {
+ HDR("***** Full Command List *****");
+ SND("Full command list, in the format: command token");
+ /* Send the command list (with tokens)
+ * -Wizzu
+ */
+ for (i = 0; msgtab[i].cmd; i++)
+ /* The following command is (almost) the same as the SND
+ * macro, but includes variables. -Wizzu
+ */
+ if (sptr != NULL)
+ sendto_one(sptr,":%s 291 %s :%s %s",
+ me.name, name, msgtab[i].cmd, msgtab[i].token);
+ else
+ printf("%s %s\n",
+ msgtab[i].cmd, msgtab[i].token);
+
+ if (sptr != NULL)
+ sendto_one(sptr, ":%s 291 %s :End of command list - %i commands shown",
+ me.name, name, (i - 1));
+ else
+ printf("End of command list - %i commands shown\n",(i -1));
+
+ }
+
+ else { /* Flood back the user ;) */
+ HLP("If you need help on services, try...");
+ HLP(" \ 2/helpop nickserv\ 2 - for help on registering nicknames.");
+ HLP(" \ 2/helpop chanserv\ 2 - for help on registering channels.");
+ HLP(" \ 2/helpop memoserv\ 2 - for help on sending short messages.");
+ HLP("If you are using ircII, use \ 2/quote helpop\ 2 instead of /helpops.");
+ sendto_one(sptr, ":%s %i %s : ***** Go to %s if you have any further questions *****", me.name, 292, sptr->name, helpchan);
+ return 0;
+ }
+ sendto_one(sptr, ":%s %i %s : ***** Go to %s if you have any further questions *****", me.name, 292, sptr->name, helpchan);
+
+ return 1;
+}
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, ircd/ircd.c
+ * Copyright (C) 1990 Jarkko Oikarinen and
+ * University of Oulu, Computing Center
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)ircd.c 2.48 3/9/94 (C) 1988 University of Oulu, \
+Computing Center and Jarkko Oikarinen";
+#endif
+
+
+/* debug --sts (chdir kludge) */
+// #define UNREAL_DEBUG
+
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#include "numeric.h"
+#include "userload.h"
+#include <sys/stat.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#ifndef _WIN32
+#include <sys/file.h>
+#include <pwd.h>
+#include <sys/time.h>
+#else
+#include <io.h>
+#include <direct.h>
+#endif
+#ifdef HPUX
+#define _KERNEL /* HPUX has the world's worst headers... */
+#endif
+#ifndef _WIN32
+#include <sys/resource.h>
+#endif
+#ifdef HPUX
+#undef _KERNEL
+#endif
+#include <errno.h>
+#include "h.h"
+#ifndef NO_FDLIST
+#include "fdlist.h"
+#endif
+
+ID_CVS("$Id$");
+ID_Copyright("(C) 1988 University of Oulu, Computing Center and Jarkko Oikarinen");
+ID_Notes("2.48 3/9/94");
+#ifdef __FreeBSD__
+char *malloc_options="h" MALLOC_FLAGS_EXTRA;
+#endif
+
+
+#ifdef SHOWCONNECTINFO
+int R_do_dns, R_fin_dns, R_fin_dnsc, R_fail_dns,
+ R_do_id, R_fin_id, R_fail_id;
+#ifdef SOCKSPORT
+int R_do_socks, R_no_socks, R_good_socks;
+#endif
+
+char REPORT_DO_DNS[128], REPORT_FIN_DNS[128], REPORT_FIN_DNSC[128],
+ REPORT_FAIL_DNS[128], REPORT_DO_ID[128], REPORT_FIN_ID[128],
+ REPORT_FAIL_ID[128];
+#ifdef SOCKSPORT
+char REPORT_DO_SOCKS[128], REPORT_NO_SOCKS[128], REPORT_GOOD_SOCKS[128];
+#endif
+#endif
+aClient me; /* That's me */
+aClient *client = &me; /* Pointer to beginning of Client list */
+extern char backupbuf[8192];
+
+#ifndef NO_FDLIST
+fdlist default_fdlist;
+fdlist busycli_fdlist;
+fdlist serv_fdlist;
+fdlist oper_fdlist;
+float currentrate;
+float currentrate2; /* outgoing */
+float highest_rate = 0;
+float highest_rate2 = 0;
+int lifesux = 0;
+
+time_t check_fdlists();
+#endif
+void server_reboot(char *);
+void restart PROTO((char *));
+static void open_debugfile(), setup_signals();
+void check_lusers(void);
+extern void init_glines(void);
+
+char **myargv;
+int portnum = -1; /* Server port number, listening this */
+char *configfile = CONFIGFILE; /* Server configuration file */
+int debuglevel = -1; /* Server debug level */
+int bootopt = 0; /* Server boot option flags */
+char *debugmode = ""; /* -"- -"- -"- */
+char *sbrk0; /* initial sbrk(0) */
+static int dorehash = 0;
+static char *dpath = DPATH;
+int booted = FALSE;
+time_t nextconnect = 1; /* time for next try_connections call */
+time_t nextping = 1; /* same as above for check_pings() */
+time_t nextdnscheck = 0; /* next time to poll dns to force timeouts */
+time_t nextexpire = 1; /* next expire run on the dns cache */
+time_t nextkillcheck = 1; /* next time to check for nickserv kills */
+time_t lastlucheck = 0;
+int lu_noninv, lu_inv, lu_serv, lu_oper, lu_unknown, lu_channel,
+ lu_lu, lu_lulocal, lu_lserv, lu_clu, lu_mlu, lu_cglobalu, lu_mglobalu;
+/* */
+#ifdef UNREAL_DEBUG
+#undef CHROOTDIR
+#define CHROOT
+#endif
+#ifdef CLONE_CHECK
+ aClone *Clones = NULL;
+ char clonekillhost[100];
+#endif
+
+time_t NOW;
+#if defined(PROFIL) && !defined(_WIN32)
+extern etext();
+
+VOIDSIG s_monitor()
+{
+ static int mon = 0;
+#ifdef POSIX_SIGNALS
+ struct sigaction act;
+#endif
+
+ (void)moncontrol(mon);
+ mon = 1 - mon;
+#ifdef POSIX_SIGNALS
+ act.sa_handler = s_rehash;
+ act.sa_flags = 0;
+ (void)sigemptyset(&act.sa_mask);
+ (void)sigaddset(&act.sa_mask, SIGUSR1);
+ (void)sigaction(SIGUSR1, &act, NULL);
+#else
+ (void)signal(SIGUSR1, s_monitor);
+#endif
+}
+#endif
+
+VOIDSIG s_die()
+{
+#ifdef USE_SYSLOG
+ (void)syslog(LOG_CRIT, "Server Killed By SIGTERM");
+#endif
+ flush_connections(me.fd);
+#ifndef _WIN32
+ exit(-1);
+#endif
+}
+
+#ifndef _WIN32
+static VOIDSIG s_rehash()
+#else
+VOIDSIG s_rehash()
+#endif
+{
+#ifdef POSIX_SIGNALS
+ struct sigaction act;
+#endif
+ dorehash = 1;
+#ifdef POSIX_SIGNALS
+ act.sa_handler = s_rehash;
+ act.sa_flags = 0;
+ (void)sigemptyset(&act.sa_mask);
+ (void)sigaddset(&act.sa_mask, SIGHUP);
+ (void)sigaction(SIGHUP, &act, NULL);
+#else
+# ifndef _WIN32
+ (void)signal(SIGHUP, s_rehash); /* sysV -argv */
+# endif
+#endif
+}
+
+void restart(mesg)
+char *mesg;
+{
+#ifdef USE_SYSLOG
+ (void)syslog(LOG_WARNING, "Restarting Server because: %s",mesg);
+#endif
+ server_reboot(mesg);
+}
+
+VOIDSIG s_restart()
+{
+ static int restarting = 0;
+
+#ifdef USE_SYSLOG
+ (void)syslog(LOG_WARNING, "Server Restarting on SIGINT");
+#endif
+ if (restarting == 0)
+ {
+ /* Send (or attempt to) a dying scream to oper if present */
+
+ restarting = 1;
+ server_reboot("SIGINT");
+ }
+}
+
+VOIDSIG s_segv()
+{
+ Reg1 int i;
+ FILE *log;
+ Reg2 int p;
+ char corename[512];
+#ifdef USE_SYSLOG
+ (void)syslog(LOG_WARNING, "Server terminating: Segmention fault!!!");
+ (void)closelog();
+#endif
+ sendto_ops("Aieeee!!! Server terminating: Segmention fault (buf: %s)", backupbuf);
+ sendto_serv_butone(&me, ":%s GLOBOPS :AIEEE!!! Server Terminating: Segmention fault (buf: %s)", me.name, backupbuf);
+ log = fopen(lPATH, "a");
+ if (log)
+ {
+ fprintf(log,"%li - Aieeee!!! Server terminating: Segmention fault (buf: %s)\n",time(NULL),backupbuf);
+ fclose(log);
+ }
+
+#if !defined(_WIN32) && !defined(_AMIGA)
+ p = getpid();
+ if (fork()>0) {
+ kill(p, 3);
+ kill(p, 9);
+ }
+ write_pidfile();
+ (void)sprintf(corename, "core.%d", p);
+ (void)rename("core", corename);
+ sendto_ops("Dumped core to %s - please read Unreal.nfo on what to do!", corename);
+#endif
+ flush_connections(me.fd);
+
+#ifndef _WIN32
+ for (i = 3; i < MAXCONNECTIONS; i++)
+ (void)close(i);
+#else
+ for (i = 0; i < highest_fd; i++)
+ if ( closesocket(i) == -1 ) close(i);
+#endif
+ exit(-1);
+}
+void server_reboot(mesg)
+char *mesg;
+{
+ Reg1 int i;
+
+ sendto_ops("Aieeeee!!! Restarting server... %s", mesg);
+ Debug((DEBUG_NOTICE,"Restarting server... %s", mesg));
+ flush_connections(me.fd);
+ /*
+ ** fd 0 must be 'preserved' if either the -d or -i options have
+ ** been passed to us before restarting.
+ */
+#ifdef USE_SYSLOG
+ (void)closelog();
+#endif
+#ifndef _WIN32
+ for (i = 3; i < MAXCONNECTIONS; i++)
+ (void)close(i);
+ if (!(bootopt & (BOOT_TTY|BOOT_DEBUG)))
+ (void)close(2);
+ (void)close(1);
+ if ((bootopt & BOOT_CONSOLE) || isatty(0))
+ (void)close(0);
+ if (!(bootopt & (BOOT_INETD|BOOT_OPER)))
+ (void)execv(MYNAME, myargv);
+#else
+ for (i = 0; i < highest_fd; i++)
+ if ( closesocket(i) == -1 ) close(i);
+
+ (void)execv(myargv[0], myargv);
+#endif
+#ifdef USE_SYSLOG
+ /* Have to reopen since it has been closed above */
+
+ openlog(myargv[0], LOG_PID|LOG_NDELAY, LOG_FACILITY);
+ syslog(LOG_CRIT, "execv(%s,%s) failed: %m\n", MYNAME, myargv[0]);
+ closelog();
+#endif
+#ifndef _WIN32
+ Debug((DEBUG_FATAL,"Couldn't restart server: %s", strerror(errno)));
+#else
+ Debug((DEBUG_FATAL,"Couldn't restart server: %s", strerror(GetLastError())));
+#endif
+ exit(-1);
+}
+
+
+/*
+** try_connections
+**
+** Scan through configuration and try new connections.
+** Returns the calendar time when the next call to this
+** function should be made latest. (No harm done if this
+** is called earlier or later...)
+*/
+static time_t try_connections(currenttime)
+time_t currenttime;
+{
+ Reg1 aConfItem *aconf;
+ Reg2 aClient *cptr;
+ aConfItem **pconf;
+ int connecting, confrq;
+ time_t next = 0;
+ aClass *cltmp;
+ aConfItem *cconf, *con_conf;
+ int con_class = 0;
+
+ connecting = FALSE;
+ Debug((DEBUG_NOTICE,"Connection check at : %s",
+ myctime(currenttime)));
+ for (aconf = conf; aconf; aconf = aconf->next )
+ {
+ /* Also when already connecting! (update holdtimes) --SRB */
+ if (!(aconf->status & CONF_CONNECT_SERVER) || aconf->port <= 0)
+ continue;
+ cltmp = Class(aconf);
+ /*
+ ** Skip this entry if the use of it is still on hold until
+ ** future. Otherwise handle this entry (and set it on hold
+ ** until next time). Will reset only hold times, if already
+ ** made one successfull connection... [this algorithm is
+ ** a bit fuzzy... -- msa >;) ]
+ */
+
+ if ((aconf->hold > currenttime))
+ {
+ if ((next > aconf->hold) || (next == 0))
+ next = aconf->hold;
+ continue;
+ }
+
+ confrq = get_con_freq(cltmp);
+ aconf->hold = currenttime + confrq;
+ /*
+ ** Found a CONNECT config with port specified, scan clients
+ ** and see if this server is already connected?
+ */
+ cptr = find_name(aconf->name, (aClient *)NULL);
+
+ if (!cptr && (Links(cltmp) < MaxLinks(cltmp)) &&
+ (!connecting || (Class(cltmp) > con_class)))
+ {
+ /* Check connect rules to see if we're allowed to try */
+ for (cconf = conf; cconf; cconf = cconf->next)
+ if ((cconf->status & CONF_CRULE) &&
+ (match(cconf->host, aconf->name) == 0))
+ if (crule_eval (cconf->passwd))
+ break;
+ if (!cconf)
+ {
+ con_class = Class(cltmp);
+ con_conf = aconf;
+ /* We connect only one at time... */
+ connecting = TRUE;
+ }
+ }
+ if ((next > aconf->hold) || (next == 0))
+ next = aconf->hold;
+ }
+ if (connecting)
+ {
+ if (con_conf->next) /* are we already last? */
+ {
+ for (pconf = &conf; (aconf = *pconf);
+ pconf = &(aconf->next))
+ /* put the current one at the end and
+ * make sure we try all connections
+ */
+ if (aconf == con_conf)
+ *pconf = aconf->next;
+ (*pconf = con_conf)->next = 0;
+ }
+ if (connect_server(con_conf, (aClient *)NULL,
+ (struct hostent *)NULL) == 0)
+ sendto_ops("Connection to %s[%s] activated.",
+ con_conf->name, con_conf->host);
+ }
+ Debug((DEBUG_NOTICE,"Next connection check : %s", myctime(next)));
+ return (next);
+}
+
+/* Now find_kill is only called when a kline-related command is used:
+ AKILL/RAKILL/KLINE/UNKLINE/REHASH. Very significant CPU usage decrease.
+ I made changes to evm_lusers
+ery check_pings call to add new parameter.
+ -- Barubary */
+extern time_t check_pings(time_t currenttime, int check_kills)
+{
+ Reg1 aClient *cptr;
+ Reg2 int killflag;
+ int ping = 0, i, i1, rflag = 0;
+ time_t oldest = 0, timeout;
+
+#ifdef PRECISE_CHECK
+ for (i1 = 0; i1 <= 7; i1++) {
+ for (i = 0; i <= highest_fd; i++)
+ {
+ if (!(cptr = local[i]) || IsMe(cptr) || IsLog(cptr))
+ continue;
+#else
+ for (cptr = &me; cptr; cptr = cptr->prev)
+ {
+ if (IsMe(cptr) || !MyClient(cptr) || IsLog(cptr))
+ continue;
+#endif
+
+ /*
+ ** Note: No need to notify opers here. It's
+ ** already done when "FLAGS_DEADSOCKET" is set.
+ */
+ if (cptr->flags & FLAGS_DEADSOCKET)
+ {
+ (void)exit_client(cptr, cptr, &me, "Dead socket");
+ continue;
+ }
+
+ if (check_kills)
+ killflag = IsPerson(cptr) ? find_kill(cptr) : 0;
+ else
+ killflag = 0;
+ if (check_kills && !killflag && IsPerson(cptr))
+ if (find_zap(cptr, 1) || find_tkline_match(cptr, 2)>-1)
+ killflag = 1;
+ ping = IsRegistered(cptr) ? get_client_ping(cptr) :
+ CONNECTTIMEOUT;
+ Debug((DEBUG_DEBUG, "c(%s)=%d p %d k %d r %d a %d",
+ cptr->name, cptr->status, ping, killflag, rflag,
+ currenttime - cptr->lasttime));
+ /*
+ * Ok, so goto's are ugly and can be avoided here but this code
+ * is already indented enough so I think its justified. -avalon
+ */
+ if (!killflag && !rflag && IsRegistered(cptr) &&
+ (ping >= currenttime - cptr->lasttime))
+ goto ping_timeout;
+ /*
+ * If the server hasnt talked to us in 2*ping seconds
+ * and it has a ping time, then close its connection.
+ * If the client is a user and a KILL line was found
+ * to be active, close this connection too.
+ */
+ if (killflag || rflag ||
+ ((currenttime - cptr->lasttime) >= (2 * ping) &&
+ (cptr->flags & FLAGS_PINGSENT)) ||
+ (!IsRegistered(cptr) &&
+ (currenttime - cptr->firsttime) >= ping))
+ {
+ if (!IsRegistered(cptr) &&
+ (DoingDNS(cptr) || DoingAuth(cptr)
+#ifdef SOCKSPORT
+|| DoingSocks(cptr)
+#endif
+ ))
+ {
+ if (cptr->authfd >= 0)
+ {
+#ifndef _WIN32
+ (void)close(cptr->authfd);
+#else
+ (void)closesocket(cptr->authfd);
+#endif
+ cptr->authfd = -1;
+ cptr->count = 0;
+ *cptr->buffer = '\0';
+ }
+#ifdef SOCKSPORT
+ if (cptr->socksfd >= 0)
+ {
+#ifndef _WIN32
+ (void)close(cptr->socksfd);
+#else
+ (void)closesocket(cptr->socksfd);
+#endif /* _WIN32 */
+ cptr->socksfd = -1;
+ }
+#endif /* SOCKSPORT */
+
+
+#ifdef SHOWCONNECTINFO
+ if (DoingDNS(cptr))
+#ifndef _WIN32
+ write(cptr->fd, REPORT_FAIL_DNS,
+ R_fail_dns);
+#else
+ send(cptr->fd, REPORT_FAIL_DNS,
+ R_fail_dns, 0);
+#endif
+ else if (DoingAuth(cptr))
+#ifndef _WIN32
+ write(cptr->fd, REPORT_FAIL_ID,
+ R_fail_id);
+#else
+ send(cptr->fd, REPORT_FAIL_ID,
+ R_fail_id, 0);
+#endif
+
+#ifdef SOCKSPORT
+ else
+#ifndef _WIN32
+ write(cptr->fd, REPORT_NO_SOCKS,
+ R_no_socks);
+#else
+ send(cptr->fd, REPORT_NO_SOCKS,
+ R_no_socks, 0);
+
+#endif
+#endif /* SOCKSPORT */
+
+#endif
+ Debug((DEBUG_NOTICE,
+ "DNS/AUTH timeout %s",
+ get_client_name(cptr,TRUE)));
+ del_queries((char *)cptr);
+ ClearAuth(cptr);
+ ClearDNS(cptr);
+#ifdef SOCKSPORT
+ ClearSocks(cptr);
+#endif
+ SetAccess(cptr);
+ cptr->firsttime = currenttime;
+ cptr->lasttime = currenttime;
+ continue;
+ }
+ if (IsServer(cptr) || IsConnecting(cptr) ||
+ IsHandshake(cptr)) {
+ sendto_ops("No response from %s, closing link",
+ get_client_name(cptr, FALSE));
+ sendto_serv_butone(&me, ":%s GNOTICE :No response from %s, closing link",
+ me.name, get_client_name(cptr, FALSE));
+ }
+ /*
+ * this is used for KILL lines with time restrictions
+ * on them - send a messgae to the user being killed
+ * first.
+ */
+ if (killflag && IsPerson(cptr))
+ sendto_ops("Kill line active for %s",
+ get_client_name(cptr, FALSE));
+
+ if (killflag)
+ (void)exit_client(cptr, cptr, &me,
+ "User has been banned");
+ else
+ (void)exit_client(cptr, cptr, &me,
+ "Ping timeout");
+ continue;
+ }
+ else if (IsRegistered(cptr) &&
+ (cptr->flags & FLAGS_PINGSENT) == 0)
+ {
+ /*
+ * if we havent PINGed the connection and we havent
+ * heard from it in a while, PING it to make sure
+ * it is still alive.
+ */
+ cptr->flags |= FLAGS_PINGSENT;
+ /* not nice but does the job */
+ cptr->lasttime = currenttime - ping;
+ sendto_one(cptr, "PING :%s", me.name);
+ }
+ping_timeout:
+ timeout = cptr->lasttime + ping;
+ while (timeout <= currenttime)
+ timeout += ping;
+ if (timeout < oldest || !oldest)
+ oldest = timeout;
+ }
+#ifdef PRECISE_CHECK
+ }
+#endif
+
+ if (!oldest || oldest < currenttime)
+ oldest = currenttime + PINGFREQUENCY;
+ Debug((DEBUG_NOTICE,"Next check_ping() call at: %s, %d %d %d",
+ myctime(oldest), ping, oldest, currenttime));
+
+ return (oldest);
+}
+
+/*
+** bad_command
+** This is called when the commandline is not acceptable.
+** Give error message and exit without starting anything.
+*/
+static int bad_command()
+{
+#ifndef _WIN32
+ (void)printf(
+ "Usage: ircd %s[-h servername] [-p portnumber] [-x loglevel] [-t] [-H]\n",
+#ifdef CMDLINE_CONFIG
+ "[-f config] "
+#else
+ ""
+#endif
+ );
+ (void)printf("Server not started\n\n");
+#else
+ MessageBox(NULL,
+ "Usage: wircd [-h servername] [-p portnumber] [-x loglevel]\n",
+ "UnrealIRCD/32", MB_OK);
+#endif
+ return (-1);
+}
+
+#ifndef _WIN32
+int main(argc, argv)
+#else
+int InitwIRCD(argc, argv)
+#endif
+int argc;
+char *argv[];
+{
+#ifdef _WIN32
+ WORD wVersionRequested = MAKEWORD(1, 1);
+ WSADATA wsaData;
+#else
+ uid_t uid, euid;
+ time_t delay = 0;
+#endif
+ int portarg = 0;
+#ifdef FORCE_CORE
+ struct rlimit corelim;
+#endif
+#ifndef NO_FDLIST
+ int mainloops=0; /* counter of how many times we have gone through
+ the main loop */
+ time_t nextfdlistcheck=0; /*end of priority code */
+#endif
+ static time_t lastglinecheck = 0;
+
+#if !defined(_WIN32) && !defined(_AMIGA)
+ sbrk0 = (char *)sbrk((size_t)0);
+ uid = getuid();
+ euid = geteuid();
+# ifdef PROFIL
+ (void)monstartup(0, etext);
+ (void)moncontrol(1);
+ (void)signal(SIGUSR1, s_monitor);
+# endif
+#endif
+
+#ifdef CHROOTDIR
+ if (chdir(dpath))
+ {
+ perror("chdir");
+ exit(-1);
+ }
+ res_init();
+ if (chroot(DPATH))
+ {
+ (void)fprintf(stderr,"ERROR: Cannot chdir/chroot\n");
+ exit(5);
+ }
+#endif /*CHROOTDIR*/
+
+ myargv = argv;
+#ifndef _WIN32
+ (void)umask(077); /* better safe than sorry --SRB */
+#else
+ WSAStartup(wVersionRequested, &wsaData);
+#endif
+ bzero((char *)&me, sizeof(me));
+
+#ifndef _WIN32
+ setup_signals();
+#endif
+ initload();
+
+#ifdef FORCE_CORE
+ corelim.rlim_cur = corelim.rlim_max = RLIM_INFINITY;
+ if (setrlimit(RLIMIT_CORE, &corelim))
+ printf("unlimit core size failed; errno = %d\n", errno);
+#endif
+
+ /*
+ ** All command line parameters have the syntax "-fstring"
+ ** or "-f string" (e.g. the space is optional). String may
+ ** be empty. Flag characters cannot be concatenated (like
+ ** "-fxyz"), it would conflict with the form "-fstring".
+ */
+ while (--argc > 0 && (*++argv)[0] == '-')
+ {
+ char *p = argv[0]+1;
+ int flag = *p++;
+
+ if (flag == '\0' || *p == '\0')
+ if (argc > 1 && argv[1][0] != '-')
+ {
+ p = *++argv;
+ argc -= 1;
+ }
+ else
+ p = "";
+
+ switch (flag)
+ {
+#ifndef _WIN32
+ case 'a':
+ bootopt |= BOOT_AUTODIE;
+ break;
+ case 'c':
+ bootopt |= BOOT_CONSOLE;
+ break;
+ case 'q':
+ bootopt |= BOOT_QUICK;
+ break;
+ case 'd' :
+ (void)setuid((uid_t)uid);
+#else
+ case 'd':
+#endif
+ dpath = p;
+ break;
+#ifndef _WIN32
+ case 'o': /* Per user local daemon... */
+ (void)setuid((uid_t)uid);
+ bootopt |= BOOT_OPER;
+ break;
+#ifdef CMDLINE_CONFIG
+ case 'f':
+ (void)setuid((uid_t)uid);
+ configfile = p;
+ break;
+#endif
+ case 'h':
+ strncpyzt(me.name, p, sizeof(me.name));
+ break;
+ case 'H':
+ unrealmanual();
+ exit(0);
+ case 'i':
+ bootopt |= BOOT_INETD|BOOT_AUTODIE;
+ break;
+#endif
+ case 'p':
+ if ((portarg = atoi(p)) > 0 )
+ portnum = portarg;
+ break;
+ case 's':
+ (void)printf("sizeof(aClient) == %u\n", sizeof(aClient));
+ (void)printf("sizeof(aChannel) == %u\n", sizeof(aChannel));
+ (void)printf("sizeof(aServer) == %u\n", sizeof(aServer));
+ exit(0);
+ break;
+#ifndef _WIN32
+ case 't':
+ (void)setuid((uid_t)uid);
+ bootopt |= BOOT_TTY;
+ break;
+ case 'v':
+ (void)printf("ircd %s\n", version);
+#else
+ case 'v':
+ MessageBox(NULL, version, "UnrealIRCD/Win32 version", MB_OK);
+#endif
+ exit(0);
+ case 'x':
+#ifdef DEBUGMODE
+# ifndef _WIN32
+ (void)setuid((uid_t)uid);
+# endif
+ debuglevel = atoi(p);
+ debugmode = *p ? p : "0";
+ bootopt |= BOOT_DEBUG;
+ break;
+#else
+# ifndef _WIN32
+ (void)fprintf(stderr,
+ "%s: DEBUGMODE must be defined for -x y\n",
+ myargv[0]);
+# else
+ MessageBox(NULL,
+ "DEBUGMODE must be defined for -x option",
+ "UnrealIRCD/32", MB_OK);
+# endif
+ exit(0);
+#endif
+ default:
+ bad_command();
+ break;
+ }
+ }
+
+#ifndef CHROOT
+ if (chdir(dpath))
+ {
+# ifndef _WIN32
+ perror("chdir");
+# else
+ MessageBox(NULL, strerror(GetLastError()), "UnrealIRCD/32: chdir()",
+ MB_OK);
+# endif
+ exit(-1);
+ }
+#endif
+
+#if !defined(IRC_UID) && !defined(_WIN32)
+ if ((uid != euid) && !euid)
+ {
+ (void)fprintf(stderr,
+ "ERROR: do not run ircd setuid root. Make it setuid a\
+ normal user.\n");
+ exit(-1);
+ }
+#endif
+
+#if (!defined(CHROOTDIR) || (defined(IRC_UID) && defined(IRC_GID))) \
+ && !defined(_WIN32)
+# ifndef AIX
+ (void)setuid((uid_t)uid);
+ (void)setuid((uid_t)euid);
+# endif
+
+ if ((int)getuid() == 0)
+ {
+# if defined(IRC_UID) && defined(IRC_GID)
+
+ /* run as a specified user */
+ (void)fprintf(stderr,"WARNING: running ircd with uid = %d\n",
+ IRC_UID);
+ (void)fprintf(stderr," changing to gid %d.\n",IRC_GID);
+ (void)setuid(IRC_UID);
+ (void)setgid(IRC_GID);
+#else
+ /* check for setuid root as usual */
+ (void)fprintf(stderr,
+ "ERROR: do not run ircd setuid root. Make it setuid a\
+ normal user.\n");
+ exit(-1);
+# endif
+ }
+#endif /*CHROOTDIR/UID/GID/_WIN32*/
+
+#ifndef _WIN32
+ /* didn't set debuglevel */
+ /* but asked for debugging output to tty */
+ if ((debuglevel < 0) && (bootopt & BOOT_TTY))
+ {
+ (void)fprintf(stderr,
+ "you specified -t without -x. use -x <n>\n");
+ exit(-1);
+ }
+#endif
+
+ if (argc > 0)
+ return bad_command(); /* This should exit out */
+ fprintf(stderr, "=====================================================================\n");
+ fprintf(stderr, "= %s loading..\n", version);
+ fprintf(stderr, "=====================================================================\n");
+
+ clear_client_hash_table();
+ clear_channel_hash_table();
+ clear_notify_hash_table();
+ inittoken();
+ initlists();
+ initclass();
+ initwhowas();
+ initstats();
+ booted = FALSE;
+ load_conf(ZCONF, 0);
+ booted = TRUE;
+ if (dcc_loadconf() == 0)
+ {
+ fprintf(stderr, "* Loaded DCC deny configuration file ..\n");
+ }
+ if (cr_loadconf() == 0)
+ {
+ fprintf(stderr, "* Loaded Channel Restrict configuration file..\n");
+ }
+ if (vhost_loadconf() == 0)
+ {
+ fprintf(stderr, "* Loaded Vhost configuration file..\n");
+ }
+ load_tunefile();
+ make_umodestr();
+ make_cmodestr();
+ fprintf(stderr, "* Dynamic configuration initialized .. booting IRCd.\n");
+ fprintf(stderr, "---------------------------------------------------------------------\n");
+
+ open_debugfile();
+#ifndef NO_FDLIST
+ init_fdlist(&serv_fdlist);
+ init_fdlist(&busycli_fdlist);
+ init_fdlist(&default_fdlist);
+ init_fdlist(&oper_fdlist);
+ {
+ register int i;
+ for (i=MAXCONNECTIONS+1 ; i>0 ; i--)
+ default_fdlist.entry[i] = i-1;
+ }
+#endif
+ if (portnum < 0)
+ portnum = PORTNUM;
+ me.port = portnum;
+ (void)init_sys();
+ me.flags = FLAGS_LISTEN;
+#ifndef _WIN32
+ if (bootopt & BOOT_INETD)
+ {
+ me.fd = 0;
+ local[0] = &me;
+ me.flags = FLAGS_LISTEN;
+ }
+ else
+#endif
+ me.fd = -1;
+
+#ifdef USE_SYSLOG
+ openlog(myargv[0], LOG_PID|LOG_NDELAY, LOG_FACILITY);
+#endif
+ if (initconf(bootopt) == -1)
+ {
+ Debug((DEBUG_FATAL, "Failed in reading configuration file %s",
+ configfile));
+#ifndef _WIN32
+ (void)printf("Couldn't open configuration file %s\n",
+ configfile);
+#else
+ MessageBox(NULL, "Couldn't open configuration file "CONFIGFILE,
+ "UnrealIRCD/32", MB_OK);
+#endif
+ exit(-1);
+ }
+ if (!(bootopt & BOOT_INETD))
+ {
+ static char star[] = "*";
+ aConfItem *aconf;
+
+ if ((aconf = find_me()) && portarg <= 0 && aconf->port > 0)
+ portnum = aconf->port;
+ Debug((DEBUG_ERROR, "Port = %d", portnum));
+ if (inetport(&me, aconf->passwd, portnum))
+ exit(1);
+ }
+ else if (inetport(&me, "*", 0))
+ exit(1);
+
+ (void)setup_ping();
+ (void)get_my_name(&me, me.sockhost, sizeof(me.sockhost)-1);
+ if (me.name[0] == '\0')
+ strncpyzt(me.name, me.sockhost, sizeof(me.name));
+ me.hopcount = 0;
+ me.authfd = -1;
+ me.confs = NULL;
+ me.next = NULL;
+ me.user = NULL;
+ me.from = &me;
+#ifdef SOCKSPORT
+ me.socksfd = -1;
+#endif
+ SetMe(&me);
+ make_server(&me);
+ (void)strcpy(me.serv->up, me.name);
+
+ me.lasttime = me.since = me.firsttime = TStime();
+ (void)add_to_client_hash_table(me.name, &me);
+#if !defined(_AMIGA) && !defined(_WIN32)
+ if (fork())
+ exit(0);
+
+#endif
+
+#ifdef SHOWCONNECTINFO
+ (void)sprintf(REPORT_DO_DNS, ":%s %s", me.name, BREPORT_DO_DNS);
+ (void)sprintf(REPORT_FIN_DNS, ":%s %s", me.name, BREPORT_FIN_DNS);
+ (void)sprintf(REPORT_FIN_DNSC, ":%s %s", me.name, BREPORT_FIN_DNSC);
+ (void)sprintf(REPORT_FAIL_DNS, ":%s %s", me.name, BREPORT_FAIL_DNS);
+ (void)sprintf(REPORT_DO_ID, ":%s %s", me.name, BREPORT_DO_ID);
+ (void)sprintf(REPORT_FIN_ID, ":%s %s", me.name, BREPORT_FIN_ID);
+ (void)sprintf(REPORT_FAIL_ID, ":%s %s", me.name, BREPORT_FAIL_ID);
+#ifdef SOCKSPORT
+ (void)sprintf(REPORT_DO_SOCKS, ":%s %s", me.name, BREPORT_DO_SOCKS);
+ (void)sprintf(REPORT_NO_SOCKS, ":%s %s", me.name, BREPORT_NO_SOCKS);
+ (void)sprintf(REPORT_GOOD_SOCKS, ":%s %s", me.name, BREPORT_GOOD_SOCKS);
+#endif
+
+ R_do_dns = strlen(REPORT_DO_DNS);
+ R_fin_dns = strlen(REPORT_FIN_DNS);
+ R_fin_dnsc = strlen(REPORT_FIN_DNSC);
+ R_fail_dns = strlen(REPORT_FAIL_DNS);
+ R_do_id = strlen(REPORT_DO_ID);
+ R_fin_id = strlen(REPORT_FIN_ID);
+ R_fail_id = strlen(REPORT_FAIL_ID);
+#ifdef SOCKSPORT
+ R_do_socks = strlen(REPORT_DO_SOCKS);
+ R_no_socks = strlen(REPORT_NO_SOCKS);
+ R_good_socks = strlen(REPORT_GOOD_SOCKS);
+#endif /* SOCKSPORT */
+#endif
+#ifdef SOCKSPORT
+ init_socks(&me);
+#endif
+
+ check_class();
+ if (bootopt & BOOT_OPER)
+ {
+ aClient *tmp = add_connection(&me, 0);
+
+ if (!tmp)
+ exit(1);
+ SetMaster(tmp);
+ }
+ else
+ write_pidfile();
+
+ Debug((DEBUG_NOTICE,"Server ready..."));
+#ifdef USE_SYSLOG
+ syslog(LOG_NOTICE, "Server Ready");
+#endif
+#ifndef NO_FDLIST
+ check_fdlists(TStime());
+#endif
+ nextkillcheck = TStime() + (time_t)1;
+
+#ifdef _WIN32
+ return 1;
+}
+
+void SocketLoop(void *dummy)
+{
+ time_t delay = 0, now;
+ static time_t lastglinecheck = 0;
+#ifndef NO_FDLIST
+ int mainloops=0; /* counter of how many times we have gone through
+ the main loop */
+ time_t nextfdlistcheck=0; /*end of priority code */
+#endif
+
+ while (1)
+#else
+ for (;;)
+#endif
+ {
+ now = TStime();
+ if (now - lastglinecheck > 4)
+ {
+ tkl_check_expire();
+ lastglinecheck = now;
+ }
+ /*
+ ** Run through the hashes and check lusers every
+ ** second
+ ** also check for expiring glines
+ */
+
+#ifndef NO_FDLIST
+ {
+ static time_t lasttime=0;
+ static long lastrecvK, lastsendK;
+ static int init=0;
+ static time_t loadcfreq=LOADCFREQ;
+
+ if (now-lasttime < loadcfreq)
+ goto done_check;
+ lasttime = now;
+ if (me.receiveK - lastrecvK >= LOADRECV)
+ {
+ if (!lifesux)
+ {
+ loadcfreq *= 2; /* add hysteresis */
+ lifesux = TRUE;
+ sendto_ops("Entering high-traffic mode (incoming = %0.2f kb/s, outgoing = %0.2f kb/s currently)", currentrate, currentrate2);
+ }
+ }
+ else
+ {
+ loadcfreq = LOADCFREQ;
+ if (lifesux)
+ {
+ lifesux = 0;
+ sendto_ops("Resuming standard operation (incoming = %0.2f kb/s, outgoing = %0.2f kb/s now)", currentrate, currentrate2);
+ }
+ }
+ lastrecvK = me.receiveK;
+ lastsendK = me.sendK;
+done_check:
+ if (lasttime != now)
+ {
+ currentrate = ((float)(me.receiveK-lastrecvK))/((float)(now-lasttime));
+ currentrate2 = ((float)(me.sendK-lastsendK))/((float)(now-lasttime));
+ if (currentrate > highest_rate)
+ highest_rate = currentrate;
+ if (currentrate2 > highest_rate2)
+ highest_rate2 = currentrate2;
+ }
+ ;
+ }
+#endif
+ if(lastlucheck < now) {
+ check_lusers();
+ lastlucheck=now;
+// check_expire_gline ();
+ }
+ /*
+ ** We only want to connect if a connection is due,
+ ** not every time through. Note, if there are no
+ ** active C lines, this call to Tryconnections is
+ ** made once only; it will return 0. - avalon
+ */
+ if (nextconnect && now >= nextconnect)
+ nextconnect = try_connections(now);
+ /*
+ ** DNS checks. One to timeout queries, one for cache expiries.
+ */
+ if (now >= nextdnscheck)
+ nextdnscheck = timeout_query_list(now);
+ if (now >= nextexpire)
+ nextexpire = expire_cache(now);
+ /*
+ ** take the smaller of the two 'timed' event times as
+ ** the time of next event (stops us being late :) - avalon
+ ** WARNING - nextconnect can return 0!
+ */
+ if (nextconnect)
+ delay = MIN(nextping, nextconnect);
+ else
+ delay = nextping;
+ delay = MIN(nextdnscheck, delay);
+ delay = MIN(nextexpire, delay);
+ delay -= now;
+ /*
+ ** Adjust delay to something reasonable [ad hoc values]
+ ** (one might think something more clever here... --msa)
+ ** We don't really need to check that often and as long
+ ** as we don't delay too long, everything should be ok.
+ ** waiting too long can cause things to timeout...
+ ** i.e. PINGS -> a disconnection :(
+ ** - avalon
+ */
+ if (delay < 1)
+ delay = 1;
+ else
+ delay = MIN(delay, TIMESEC);
+#ifdef NO_FDLIST
+ (void)read_message(delay);
+#else
+ (void)read_message(0,&serv_fdlist); /* servers */
+ (void)read_message(1,&busycli_fdlist); /* busy clients */
+ if (lifesux)
+ (void)read_message(1,&serv_fdlist);
+ /* read servs more often */
+ {
+ static time_t lasttime=0;
+ if ((lasttime + (lifesux +1) * 2)< (now = TStime()))
+ {
+ read_message(delay,NULL); /* check everything */
+ lasttime = now;
+ }
+ }
+
+#endif
+ Debug((DEBUG_DEBUG ,"Got message(s)"));
+
+ now = TStime();
+ /*
+ ** ...perhaps should not do these loops every time,
+ ** but only if there is some chance of something
+ ** happening (but, note that conf->hold times may
+ ** be changed elsewhere--so precomputed next event
+ ** time might be too far away... (similarly with
+ ** ping times) --msa
+ */
+#ifdef NO_FDLIST
+ if (now >= nextping)
+#else
+ if (now >= nextping && !lifesux)
+#endif
+ nextping = check_pings(now, 0);
+
+ if (dorehash)
+ {
+ (void)rehash(&me, &me, 1);
+ dorehash = 0;
+ }
+ /*
+ ** Flush output buffers on all connections now if they
+ ** have data in them (or at least try to flush)
+ ** -avalon
+ */
+#ifndef NO_FDLIST
+ /* check which clients are active */
+ if (now > nextfdlistcheck)
+ nextfdlistcheck = check_fdlists(now);
+#endif
+ flush_connections(me.fd);
+ }
+ }
+#ifndef NO_FDLIST
+time_t check_fdlists(now)
+time_t now;
+{
+ register aClient *cptr;
+ int pri; /* temp. for priority */
+ register int i,j;
+ j = 0;
+
+ for(i=highest_fd;i>=0; i--)
+ {
+ if (!(cptr=local[i]))
+ continue;
+ if (IsServer(cptr) || IsListening(cptr) || IsOper(cptr) ||
+ DoingAuth(cptr))
+ {
+ busycli_fdlist.entry[++j] = i;
+ continue;
+ }
+ pri = cptr->priority;
+ if (cptr->receiveM==cptr->lastrecvM)
+ pri+=2; /* lower a bit */
+ else
+ pri-=30;
+ if (pri < 0) pri = 0;
+ if (pri > 80) pri = 80;
+
+ cptr->lastrecvM = cptr->receiveM;
+ cptr->priority = pri;
+ if ((pri <10) || (!lifesux && (pri < 25)))
+ busycli_fdlist.entry[++j] = i;
+ }
+ busycli_fdlist.last_entry=j; /* rest of the fdlist is garbage */
+
+ return (now + FDLISTCHKFREQ + lifesux * FDLISTCHKFREQ);
+}
+#endif
+
+/*
+ * open_debugfile
+ *
+ * If the -t option is not given on the command line when the server is
+ * started, all debugging output is sent to the file set by LPATH in config.h
+ * Here we just open that file and make sure it is opened to fd 2 so that
+ * any fprintf's to stderr also goto the logfile. If the debuglevel is not
+ * set from the command line by -x, use /dev/null as the dummy logfile as long
+ * as DEBUGMODE has been defined, else dont waste the fd.
+ */
+static void open_debugfile()
+{
+#ifdef DEBUGMODE
+ int fd;
+ aClient *cptr;
+
+ if (debuglevel >= 0)
+ {
+ cptr = make_client(NULL, NULL);
+ cptr->fd = 2;
+ SetLog(cptr);
+ cptr->port = debuglevel;
+ cptr->flags = 0;
+ cptr->acpt = cptr;
+ local[2] = cptr;
+ (void)strcpy(cptr->sockhost, me.sockhost);
+# ifndef _WIN32
+ (void)printf("isatty = %d ttyname = %#x\n",
+ isatty(2), (u_int)ttyname(2));
+ if (!(bootopt & BOOT_TTY)) /* leave debugging output on fd 2 */
+ {
+ (void)truncate(LOGFILE, 0);
+ if ((fd = open(LOGFILE, O_WRONLY | O_CREAT, 0600)) < 0)
+ if ((fd = open("/dev/null", O_WRONLY)) < 0)
+ exit(-1);
+ if (fd != 2)
+ {
+ (void)dup2(fd, 2);
+ (void)close(fd);
+ }
+ strncpyzt(cptr->name, LOGFILE, sizeof(cptr->name));
+ }
+ else if (isatty(2) && ttyname(2))
+ strncpyzt(cptr->name, ttyname(2), sizeof(cptr->name));
+ else
+# endif
+ (void)strcpy(cptr->name, "FD2-Pipe");
+ Debug((DEBUG_FATAL, "Debug: File <%s> Level: %d at %s",
+ cptr->name, cptr->port, myctime(time(NULL))));
+ }
+ else
+ local[2] = NULL;
+#endif
+ return;
+}
+
+#ifndef _WIN32
+static void setup_signals()
+{
+#ifdef POSIX_SIGNALS
+ struct sigaction act;
+
+ act.sa_handler = SIG_IGN;
+ act.sa_flags = 0;
+ (void)sigemptyset(&act.sa_mask);
+ (void)sigaddset(&act.sa_mask, SIGPIPE);
+ (void)sigaddset(&act.sa_mask, SIGALRM);
+# ifdef SIGWINCH
+ (void)sigaddset(&act.sa_mask, SIGWINCH);
+ (void)sigaction(SIGWINCH, &act, NULL);
+# endif
+ (void)sigaction(SIGPIPE, &act, NULL);
+ act.sa_handler = dummy;
+ (void)sigaction(SIGALRM, &act, NULL);
+ act.sa_handler = s_rehash;
+ (void)sigemptyset(&act.sa_mask);
+ (void)sigaddset(&act.sa_mask, SIGHUP);
+ (void)sigaction(SIGHUP, &act, NULL);
+ act.sa_handler = s_restart;
+ (void)sigaddset(&act.sa_mask, SIGINT);
+ (void)sigaction(SIGINT, &act, NULL);
+ act.sa_handler = s_die;
+ (void)sigaddset(&act.sa_mask, SIGTERM);
+ (void)sigaction(SIGTERM, &act, NULL);
+/* handling of SIGSEGV as well -sts */
+ act.sa_handler = s_segv;
+ (void)sigaddset(&act.sa_mask, SIGSEGV);
+ (void)sigaction(SIGSEGV, &act, NULL);
+
+#else
+# ifndef HAVE_RELIABLE_SIGNALS
+ (void)signal(SIGPIPE, dummy);
+# ifdef SIGWINCH
+ (void)signal(SIGWINCH, dummy);
+# endif
+# else
+# ifdef SIGWINCH
+ (void)signal(SIGWINCH, SIG_IGN);
+# endif
+ (void)signal(SIGPIPE, SIG_IGN);
+# endif
+ (void)signal(SIGALRM, dummy);
+ (void)signal(SIGHUP, s_rehash);
+ (void)signal(SIGTERM, s_die);
+ (void)signal(SIGINT, s_restart);
+ (void)signal(SIGSEGV, s_segv);
+#endif
+
+#ifdef RESTARTING_SYSTEMCALLS
+ /*
+ ** At least on Apollo sr10.1 it seems continuing system calls
+ ** after signal is the default. The following 'siginterrupt'
+ ** should change that default to interrupting calls.
+ */
+ (void)siginterrupt(SIGALRM, 1);
+#endif
+}
+#endif /* !_Win32 */
+
+
+
+
+void check_lusers(void) {
+ aClient *acptr;
+ lu_noninv=lu_inv=lu_serv=lu_oper=lu_unknown=lu_channel=lu_lu=lu_lserv=
+ lu_clu=lu_cglobalu=0;
+ for (acptr = client; acptr; acptr = acptr->next) {
+ switch (acptr->status) {
+ case STAT_SERVER:
+ if (MyConnect(acptr))
+ lu_lserv++;
+ case STAT_ME:
+ lu_serv++;
+ break;
+ case STAT_CLIENT:
+ if (IsOper(acptr))
+ lu_oper++;
+ if (MyConnect(acptr)) {
+ lu_lu++;
+ if (match(DOMAINNAMEMASK, acptr->sockhost) == 0)
+ lu_lulocal++;
+ }
+ if (!IsInvisible(acptr))
+ lu_noninv++;
+ else
+ lu_inv++;
+ break;
+ default:
+ lu_unknown++;
+ break;
+ }
+ }
+ lu_clu=lu_lu;
+ lu_cglobalu=lu_noninv + lu_inv;
+ if (lu_clu > lu_mlu)
+ lu_mlu = lu_lu;
+ lu_cglobalu = lu_noninv + lu_inv;
+ if (lu_cglobalu > lu_mglobalu)
+ lu_mglobalu = lu_cglobalu;
+
+ lu_channel=count_channels(&me);
+}
+
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, ircd/list.c
+ * Copyright (C) 1990 Jarkko Oikarinen and
+ * University of Oulu, Finland
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* -- Jto -- 20 Jun 1990
+ * extern void free() fixed as suggested by
+ * gruner@informatik.tu-muenchen.de
+ */
+
+/* -- Jto -- 03 Jun 1990
+ * Added chname initialization...
+ */
+
+/* -- Jto -- 24 May 1990
+ * Moved is_full() to channel.c
+ */
+
+/* -- Jto -- 10 May 1990
+ * Added #include <sys.h>
+ * Changed memset(xx,0,yy) into bzero(xx,yy)
+ */
+
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#include "h.h"
+#include "numeric.h"
+#ifdef DBMALLOC
+#include "malloc.h"
+#endif
+void free_link PROTO((Link *));
+Link *make_link PROTO(());
+
+ID_CVS("$Id$");
+ID_Copyright("(C) 1988 University of Oulu, Computing Center and Jarkko Oikarinen");
+ID_Notes("2.24 4/20/94");
+
+#ifdef DEBUGMODE
+static struct liststats {
+ int inuse;
+} cloc, crem, users, servs, links, classs, aconfs;
+
+#endif
+
+void outofmemory();
+
+int flinks = 0;
+Link *freelink = NULL;
+
+int numclients = 0;
+
+void initlists()
+{
+#ifdef DEBUGMODE
+ bzero((char *)&cloc, sizeof(cloc));
+ bzero((char *)&crem, sizeof(crem));
+ bzero((char *)&users, sizeof(users));
+ bzero((char *)&servs, sizeof(servs));
+ bzero((char *)&links, sizeof(links));
+ bzero((char *)&classs, sizeof(classs));
+ bzero((char *)&aconfs, sizeof(aconfs));
+#endif
+}
+
+void outofmemory()
+{
+ Debug((DEBUG_FATAL, "Out of memory: restarting server..."));
+ restart("Out of Memory");
+}
+
+
+/*
+** Create a new aClient structure and set it to initial state.
+**
+** from == NULL, create local client (a client connected
+** to a socket).
+**
+** from, create remote client (behind a socket
+** associated with the client defined by
+** 'from'). ('from' is a local client!!).
+*/
+aClient *make_client(from, servr)
+aClient *from, *servr;
+{
+ Reg1 aClient *cptr = NULL;
+ Reg2 unsigned size = CLIENT_REMOTE_SIZE;
+
+ /*
+ * Check freelists first to see if we can grab a client without
+ * having to call malloc.
+ */
+ if (!from)
+ size = CLIENT_LOCAL_SIZE;
+
+ if (!(cptr = (aClient *)MyMalloc(size)))
+ outofmemory();
+ bzero((char *)cptr, (int)size);
+
+#ifdef DEBUGMODE
+ if (size == CLIENT_LOCAL_SIZE)
+ cloc.inuse++;
+ else
+ crem.inuse++;
+#endif
+
+ /* Note: structure is zero (calloc) */
+ cptr->from = from ? from : cptr; /* 'from' of local client is self! */
+ cptr->next = NULL; /* For machines with NON-ZERO NULL pointers >;) */
+ cptr->prev = NULL;
+ cptr->hnext = NULL;
+ cptr->user = NULL;
+ cptr->serv = NULL;
+ cptr->srvptr = servr;
+ cptr->status = STAT_UNKNOWN;
+ cptr->fd = -1;
+ (void)strcpy(cptr->username, "unknown");
+ if (size == CLIENT_LOCAL_SIZE)
+ {
+ cptr->since = cptr->lasttime =
+ cptr->lastnick = cptr->firsttime = TStime();
+ cptr->confs = NULL;
+ cptr->sockhost[0] = '\0';
+ cptr->buffer[0] = '\0';
+ cptr->authfd = -1;
+#ifdef SOCKSPORT
+ cptr->socksfd = -1;
+#endif
+ }
+ return (cptr);
+}
+
+void free_client(cptr)
+aClient *cptr;
+{
+ MyFree((char *)cptr);
+}
+
+/*
+** 'make_user' add's an User information block to a client
+** if it was not previously allocated.
+*/
+anUser *make_user(cptr)
+aClient *cptr;
+{
+ Reg1 anUser *user;
+
+ user = cptr->user;
+ if (!user)
+ {
+ user = (anUser *)MyMalloc(sizeof(anUser));
+#ifdef DEBUGMODE
+ users.inuse++;
+#endif
+ user->swhois = NULL;
+ user->away = NULL;
+ user->refcnt = 1;
+ user->joined = 0;
+ user->channel = NULL;
+ user->invited = NULL;
+ user->silence = NULL;
+ cptr->user = user;
+ }
+ return user;
+}
+
+aServer *make_server(cptr)
+aClient *cptr;
+{
+ Reg1 aServer *serv = cptr->serv;
+
+ if (!serv)
+ {
+ serv = (aServer *)MyMalloc(sizeof(aServer));
+#ifdef DEBUGMODE
+ servs.inuse++;
+#endif
+ serv->user = NULL;
+ serv->nexts = NULL;
+ *serv->by = '\0';
+ *serv->up = '\0';
+ cptr->serv = serv;
+ }
+ return cptr->serv;
+}
+
+/*
+** free_user
+** Decrease user reference count by one and realease block,
+** if count reaches 0
+*/
+void free_user(user, cptr)
+Reg1 anUser *user;
+aClient *cptr;
+{
+ if (--user->refcnt <= 0)
+ {
+ if (user->away)
+ MyFree((char *)user->away);
+ if (user->swhois)
+ MyFree((char *)user->swhois);
+ /*
+ * sanity check
+ */
+ if (user->joined || user->refcnt < 0 ||
+ user->invited || user->channel)
+#ifdef DEBUGMODE
+ dumpcore("%#x user (%s!%s@%s) %#x %#x %#x %d %d",
+ cptr, cptr ? cptr->name : "<noname>",
+ user->username, user->realhost, user,
+ user->invited, user->channel, user->joined,
+ user->refcnt);
+#else
+ sendto_ops("* %#x user (%s!%s@%s) %#x %#x %#x %d %d *",
+ cptr, cptr ? cptr->name : "<noname>",
+ user->username, user->realhost, user,
+ user->invited, user->channel, user->joined,
+ user->refcnt);
+#endif
+ MyFree((char *)user);
+#ifdef DEBUGMODE
+ users.inuse--;
+#endif
+ }
+}
+
+/*
+ * taken the code from ExitOneClient() for this and placed it here.
+ * - avalon
+ */
+void remove_client_from_list(cptr)
+Reg1 aClient *cptr;
+{
+ checklist();
+ if (cptr->prev)
+ cptr->prev->next = cptr->next;
+ else
+ {
+ client = cptr->next;
+ if (client)
+ client->prev = NULL;
+ }
+ if (cptr->next)
+ cptr->next->prev = cptr->prev;
+ if (IsPerson(cptr)) /* Only persons can have been added before */
+ {
+ add_history(cptr);
+ off_history(cptr); /* Remove all pointers to cptr */
+ }
+ if (cptr->user)
+ (void)free_user(cptr->user, cptr);
+ if (cptr->serv)
+ {
+ if (cptr->serv->user)
+ free_user(cptr->serv->user, cptr);
+ MyFree((char *)cptr->serv);
+#ifdef DEBUGMODE
+ servs.inuse--;
+#endif
+ }
+#ifdef DEBUGMODE
+ if (cptr->fd == -2)
+ cloc.inuse--;
+ else
+ crem.inuse--;
+#endif
+ (void)free_client(cptr);
+ numclients--;
+ return;
+}
+
+/*
+ * although only a small routine, it appears in a number of places
+ * as a collection of a few lines...functions like this *should* be
+ * in this file, shouldnt they ? after all, this is list.c, isnt it ?
+ * -avalon
+ */
+void add_client_to_list(cptr)
+aClient *cptr;
+{
+ /*
+ * since we always insert new clients to the top of the list,
+ * this should mean the "me" is the bottom most item in the list.
+ */
+ cptr->next = client;
+ client = cptr;
+ if (cptr->next)
+ cptr->next->prev = cptr;
+ return;
+}
+
+/*
+ * Look for ptr in the linked listed pointed to by link.
+ */
+Link *find_user_link(lp, ptr)
+Reg1 Link *lp;
+Reg2 aClient *ptr;
+{
+ if (ptr)
+ while (lp)
+ {
+ if (lp->value.cptr == ptr)
+ return (lp);
+ lp = lp->next;
+ }
+ return NULL;
+}
+
+Link *find_channel_link(lp, ptr)
+Reg1 Link *lp;
+Reg2 aChannel *ptr;
+{
+ if (ptr)
+ while (lp)
+ {
+ if (lp->value.chptr == ptr)
+ return (lp);
+ lp = lp->next;
+ }
+ return NULL;
+}
+
+
+
+/*
+ * Look for a match in a list of strings. Go through the list, and run
+ * match() on it. Side effect: if found, this link is moved to the top of
+ * the list.
+ */
+int find_str_match_link(lp, str)
+Reg1 Link **lp; /* Two **'s, since we might modify the original *lp */
+Reg2 char *str;
+{
+ Link *ptr, **head = lp;
+
+ if (lp && *lp)
+ {
+ if (!match((*lp)->value.cp, str))
+ return 1;
+ for (; (*lp)->next; *lp = (*lp)->next)
+ if (!match((*lp)->next->value.cp, str))
+ {
+ Link *temp = (*lp)->next;
+ *lp = (*lp)->next->next;
+ temp->next = *head;
+ *head = temp;
+ return 1;
+ }
+ return 0;
+ }
+ return 0;
+}
+
+void free_str_list(lp)
+Reg1 Link *lp;
+{
+ Reg2 Link *next;
+
+
+ while (lp) {
+ next = lp->next;
+ MyFree((char *)lp->value.cp);
+ free_link(lp);
+ lp = next;
+ }
+
+ return;
+}
+
+
+#define LINKSIZE (4072/sizeof(Link))
+
+Link *make_link()
+{
+ Link *lp;
+ int i;
+
+ /* "caching" slab-allocator... ie. we're allocating one pages
+ (hopefully - upped to the Linux default, not dbuf.c) worth of
+ link-structures at time to avoid all the malloc overhead.
+ All links left free from this process or separately freed
+ by a call to free_link() are moved over to freelink-list.
+ Impact? Let's see... -Donwulff */
+ if(freelink==NULL) {
+ lp = (Link *)MyMalloc(LINKSIZE*sizeof(Link));
+ freelink=lp+1;
+ flinks+=LINKSIZE;
+ for(i=1;i<(LINKSIZE-1);i++)
+ (lp+i)->next=lp+i+1; (lp+i)->next=NULL;
+ } else {
+ lp = freelink;
+ freelink=freelink->next;
+ }
+#ifdef DEBUGMODE
+ links.inuse++;
+#endif
+ return lp;
+}
+
+void free_link(lp)
+Reg1 Link *lp;
+{
+ lp->next=freelink;
+ freelink=lp;
+#ifdef DEBUGMODE
+ links.inuse--;
+#endif
+}
+
+Ban *make_ban()
+{
+ Reg1 Ban *lp;
+
+ lp = (Ban *)MyMalloc(sizeof(Ban));
+#ifdef DEBUGMODE
+ links.inuse++;
+#endif
+ return lp;
+}
+
+void free_ban(lp)
+Reg1 Ban *lp;
+{
+ MyFree((char *)lp);
+#ifdef DEBUGMODE
+ links.inuse--;
+#endif
+}
+
+aClass *make_class()
+{
+ Reg1 aClass *tmp;
+
+ tmp = (aClass *)MyMalloc(sizeof(aClass));
+#ifdef DEBUGMODE
+ classs.inuse++;
+#endif
+ return tmp;
+}
+
+void free_class(tmp)
+Reg1 aClass *tmp;
+{
+ MyFree((char *)tmp);
+#ifdef DEBUGMODE
+ classs.inuse--;
+#endif
+}
+
+aSqlineItem *make_sqline()
+{
+ Reg1 aSqlineItem *asqline;
+
+ asqline = (struct SqlineItem *)MyMalloc(sizeof(aSqlineItem));
+ asqline->next = NULL;
+ asqline->sqline = asqline->reason = NULL;
+
+ return (asqline);
+}
+
+aConfItem *make_conf()
+{
+ Reg1 aConfItem *aconf;
+
+ aconf = (struct ConfItem *)MyMalloc(sizeof(aConfItem));
+#ifdef DEBUGMODE
+ aconfs.inuse++;
+#endif
+ bzero((char *)&aconf->ipnum, sizeof(struct in_addr));
+ aconf->next = NULL;
+ aconf->host = aconf->passwd = aconf->name = NULL;
+ aconf->status = CONF_ILLEGAL;
+ aconf->clients = 0;
+ aconf->port = 0;
+ aconf->hold = 0;
+ Class(aconf) = 0;
+ return (aconf);
+}
+
+void delist_conf(aconf)
+aConfItem *aconf;
+{
+ if (aconf == conf)
+ conf = conf->next;
+ else
+ {
+ aConfItem *bconf;
+
+ for (bconf = conf; aconf != bconf->next; bconf = bconf->next)
+ ;
+ bconf->next = aconf->next;
+ }
+ aconf->next = NULL;
+}
+
+void free_sqline(asqline)
+aSqlineItem *asqline;
+{
+ del_queries((char *)asqline);
+ MyFree(asqline->sqline);
+ MyFree(asqline->reason);
+ MyFree((char *)asqline);
+ return;
+}
+
+void free_conf(aconf)
+aConfItem *aconf;
+{
+ del_queries((char *)aconf);
+ MyFree(aconf->host);
+ if (aconf->passwd)
+ bzero(aconf->passwd, strlen(aconf->passwd));
+ MyFree(aconf->passwd);
+ MyFree(aconf->name);
+ MyFree((char *)aconf);
+#ifdef DEBUGMODE
+ aconfs.inuse--;
+#endif
+ return;
+}
+
+#ifdef DEBUGMODE
+void send_listinfo(cptr, name)
+aClient *cptr;
+char *name;
+{
+ int inuse = 0, mem = 0, tmp = 0;
+
+ sendto_one(cptr, ":%s %d %s :Local: inuse: %d(%d)",
+ me.name, RPL_STATSDEBUG, name, inuse += cloc.inuse,
+ tmp = cloc.inuse * CLIENT_LOCAL_SIZE);
+ mem += tmp;
+ sendto_one(cptr, ":%s %d %s :Remote: inuse: %d(%d)",
+ me.name, RPL_STATSDEBUG, name,
+ crem.inuse, tmp = crem.inuse * CLIENT_REMOTE_SIZE);
+ mem += tmp;
+ inuse += crem.inuse;
+ sendto_one(cptr, ":%s %d %s :Users: inuse: %d(%d)",
+ me.name, RPL_STATSDEBUG, name, users.inuse,
+ tmp = users.inuse * sizeof(anUser));
+ mem += tmp;
+ inuse += users.inuse,
+ sendto_one(cptr, ":%s %d %s :Servs: inuse: %d(%d)",
+ me.name, RPL_STATSDEBUG, name, servs.inuse,
+ tmp = servs.inuse * sizeof(aServer));
+ mem += tmp;
+ inuse += servs.inuse,
+ sendto_one(cptr, ":%s %d %s :Links: inuse: %d(%d)",
+ me.name, RPL_STATSDEBUG, name, links.inuse,
+ tmp = links.inuse * sizeof(Link));
+ mem += tmp;
+ inuse += links.inuse,
+ sendto_one(cptr, ":%s %d %s :Classes: inuse: %d(%d)",
+ me.name, RPL_STATSDEBUG, name, classs.inuse,
+ tmp = classs.inuse * sizeof(aClass));
+ mem += tmp;
+ inuse += classs.inuse,
+ sendto_one(cptr, ":%s %d %s :Confs: inuse: %d(%d)",
+ me.name, RPL_STATSDEBUG, name, aconfs.inuse,
+ tmp = aconfs.inuse * sizeof(aConfItem));
+ mem += tmp;
+ inuse += aconfs.inuse,
+ sendto_one(cptr, ":%s %d %s :Totals: inuse %d %d",
+ me.name, RPL_STATSDEBUG, name, inuse, mem);
+}
+#endif
--- /dev/null
+/*
+ * IRC - Internet Relay Chat, common/match.c
+ * Copyright (C) 1990 Jarkko Oikarinen
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+
+ID_CVS("$Id$");
+ID_Copyright("(C) 1990 Jarkko Oikarinen");
+
+/*
+ * Compare if a given string (name) matches the given
+ * mask (which can contain wild cards: '*' - match any
+ * number of chars, '?' - match any single character.
+ *
+ * return 0, if match
+ * 1, if no match
+ */
+
+u_char touppertab[], tolowertab[];
+#define tolowertab2 tolowertab
+
+/*
+ * match()
+ * written by binary
+ */
+int match(mask, name)
+char *mask, *name;
+{
+ Reg1 u_char *m; /* why didn't the old one use registers ?!??!?!?! */
+ Reg2 u_char *n;
+ Reg3 u_char cm;
+ Reg4 u_char *mylowertab;
+ u_char *wsn;
+ u_char *wsm;
+
+ m = (u_char *)mask;
+
+ cm = *m;
+
+ mylowertab = tolowertab2;
+#define lc(x) mylowertab[x] /* use mylowertab, because registers are FASTER */
+
+ n = (u_char *)name;
+ if (cm == '*')
+ {
+ if (m[1] == '\0') /* mask is just "*", so true */
+ return 0;
+ }
+ else if (cm != '?' && lc(cm) != lc(*n))
+ return 1; /* most likely first chars won't match */
+ else
+ {
+ m++;
+ n++;
+ }
+ cm = lc(*m);
+ wsm = (char *)NULL;
+ while (1)
+ {
+ if (cm == '*') /* found the * wildcard */
+ {
+ m++; /* go to next char of mask */
+ if (!*m) /* if at end of mask, */
+ return 0; /* function becomes true. */
+ while (*m == '*') /* while the char at m is "*" */
+ {
+ m++; /* go to next char of mask */
+ if (!*m) /* if at end of mask, */
+ return 0; /* function becomes true. */
+ }
+ cm = *m;
+ if (cm == '\\') /* don't do ? checking if a \ */
+ {
+ cm = *(++m); /* just skip this char, no ? checking */
+ }
+ else if (cm == '?') /* if it's a ? */
+ {
+ do
+ {
+ m++; /* go to the next char of both */
+ n++;
+ if (!*n) /* if end of test string... */
+ return (!*m ? 0 : 1); /* true if end of mask str, else false */
+ } while (*m == '?'); /* while we have ?'s */
+ cm = *m;
+ if (!cm) /* last char of mask is ?, so it's true */
+ return 0;
+ }
+ cm = lc(cm);
+ while (lc(*n) != cm)
+ { /* compare */
+ n++; /* go to next char of n */
+ if (!*n) /* if at end of n string */
+ return 1; /* function becomes false. */
+ }
+ wsm = m; /* mark after where wildcard found */
+ cm = lc(*(++m)); /* go to next mask char */
+ wsn = n; /* mark spot first char was found */
+ n++; /* go to next char of n */
+ continue;
+ }
+ if (cm == '?') /* found ? wildcard */
+ {
+ cm = lc(*(++m)); /* just skip and go to next */
+ n++;
+ if (!*n) /* return true if end of both, */
+ return (cm ? 1 : 0); /* false if end of test str only */
+ continue;
+ }
+ if (cm == '\\') /* next char will not be a wildcard. */
+ { /* skip wild checking, don't continue */
+ cm = lc(*(++m));
+ n++;
+ }
+ /* Complicated to read, but to save CPU time. Every ounce counts. */
+ if (lc(*n) != cm) /* if the current chars don't equal, */
+ {
+ if (!wsm) /* if there was no * wildcard, */
+ return 1; /* function becomes false. */
+ n = wsn + 1; /* start on char after the one we found last */
+ m = wsm; /* set m to the spot after the "*" */
+ cm = lc(*m);
+ while (cm != lc(*n))
+ { /* compare them */
+ n++; /* go to next char of n */
+ if (!*n) /* if we reached end of n string, */
+ return 1; /* function becomes false. */
+ }
+ wsn = n; /* mark spot first char was found */
+ }
+ if (!cm) /* cm == cn, so if !cm, then we've */
+ return 0; /* reached end of BOTH, so it matches */
+ m++; /* go to next mask char */
+ n++; /* go to next testing char */
+ cm = lc(*m); /* pointers are slower */
+ }
+}
+
+/*
+ * collapse a pattern string into minimal components.
+ * This particular version is "in place", so that it changes the pattern
+ * which is to be reduced to a "minimal" size.
+ */
+char *
+collapse(pattern)
+ char *pattern;
+{
+ Reg1 char *s;
+ Reg2 char *s1;
+ Reg3 char *t;
+
+ s = pattern;
+
+ if (BadPtr(pattern))
+ return pattern;
+ /*
+ * Collapse all \** into \*, \*[?]+\** into \*[?]+
+ */
+ for (; *s; s++)
+ if (*s == '\\')
+ {
+ if (!*(s + 1))
+ break;
+ else
+ s++;
+ }
+ else if (*s == '*') {
+ if (*(t = s1 = s + 1) == '*')
+ while (*t == '*')
+ t++;
+ else if (*t == '?')
+ for (t++, s1++; *t == '*' || *t == '?'; t++)
+ if (*t == '?')
+ *s1++ = *t;
+ while ((*s1++ = *t++))
+ ;
+ }
+ return pattern;
+}
+
+
+/*
+ * Case insensitive comparison of two NULL terminated strings.
+ *
+ * returns 0, if s1 equal to s2
+ * <0, if s1 lexicographically less than s2
+ * >0, if s1 lexicographically greater than s2
+ */
+int
+smycmp(s1, s2)
+ char *s1;
+ char *s2;
+{
+ Reg1 u_char *str1;
+ Reg2 u_char *str2;
+ Reg3 int res;
+
+ str1 = (u_char *)s1;
+ str2 = (u_char *)s2;
+
+ while ((res = toupper(*str1) - toupper(*str2)) == 0) {
+ if (*str1 == '\0')
+ return 0;
+ str1++;
+ str2++;
+ }
+ return (res);
+}
+
+
+int
+myncmp(str1, str2, n)
+ char *str1;
+ char *str2;
+ int n;
+{
+ Reg1 u_char *s1;
+ Reg2 u_char *s2;
+ Reg3 int res;
+
+ s1 = (u_char *)str1;
+ s2 = (u_char *)str2;
+
+ while ((res = toupper(*s1) - toupper(*s2)) == 0)
+ {
+ s1++;
+ s2++;
+ n--;
+ if (n == 0 || (*s1 == '\0' && *s2 == '\0'))
+ return 0;
+ }
+ return (res);
+}
+
+
+u_char tolowertab[] = {
+ 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
+ 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
+ 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
+ 0x1e, 0x1f,
+ ' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')',
+ '*', '+', ',', '-', '.', '/',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ ':', ';', '<', '=', '>', '?',
+ '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
+ 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
+ 't', 'u', 'v', 'w', 'x', 'y', 'z', '[', '\\', ']', '^',
+ '_',
+ '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
+ 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
+ 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~',
+ 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+ 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
+ 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
+ 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
+ 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
+ 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
+ 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+ 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
+ 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+u_char touppertab[] = {
+ 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
+ 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
+ 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
+ 0x1e, 0x1f,
+ ' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')',
+ '*', '+', ',', '-', '.', '/',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ ':', ';', '<', '=', '>', '?',
+ '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
+ 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
+ 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^',
+ 0x5f,
+ '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
+ 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
+ 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~',
+ 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+ 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
+ 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
+ 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
+ 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
+ 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
+ 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+ 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
+ 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+u_char char_atribs[] = {
+/* 0-7 */ CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL,
+/* 8-12 */ CNTRL, CNTRL|SPACE, CNTRL|SPACE, CNTRL|SPACE, CNTRL|SPACE,
+/* 13-15 */ CNTRL|SPACE, CNTRL, CNTRL,
+/* 16-23 */ CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL,
+/* 24-31 */ CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL,
+/* space */ PRINT|SPACE,
+/* !"#$%&'( */ PRINT, PRINT, PRINT, PRINT, PRINT, PRINT, PRINT, PRINT,
+/* )*+,-./ */ PRINT, PRINT, PRINT, PRINT, PRINT|ALLOW, PRINT|ALLOW, PRINT,
+/* 012 */ PRINT|DIGIT|ALLOW, PRINT|DIGIT|ALLOW, PRINT|DIGIT|ALLOW,
+/* 345 */ PRINT|DIGIT|ALLOW, PRINT|DIGIT|ALLOW, PRINT|DIGIT|ALLOW,
+/* 678 */ PRINT|DIGIT|ALLOW, PRINT|DIGIT|ALLOW, PRINT|DIGIT|ALLOW,
+/* 9:; */ PRINT|DIGIT|ALLOW, PRINT, PRINT,
+/* <=>? */ PRINT, PRINT, PRINT, PRINT,
+/* @ */ PRINT,
+/* ABC */ PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW,
+/* DEF */ PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW,
+/* GHI */ PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW,
+/* JKL */ PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW,
+/* MNO */ PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW,
+/* PQR */ PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW,
+/* STU */ PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW,
+/* VWX */ PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW,
+/* YZ[ */ PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW, PRINT|ALPHA,
+/* \]^ */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA,
+/* _` */ PRINT|ALLOW,PRINT,
+/* abc */ PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW,
+/* def */ PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW,
+/* ghi */ PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW,
+/* jkl */ PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW,
+/* mno */ PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW,
+/* pqr */ PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW,
+/* stu */ PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW,
+/* vwx */ PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW,
+/* yz{ */ PRINT|ALPHA|ALLOW, PRINT|ALPHA|ALLOW, PRINT|ALPHA,
+/* |}~ */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA,
+/* del */ 0,
+/* 80-8f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* 90-9f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* a0-af */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* b0-bf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* c0-cf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* d0-df */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* e0-ef */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* f0-ff */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
--- /dev/null
+/* $Id$ */
+
+/*
+ * Copyright (c) 1996 Michael Shalayeff.
+ *
+ * This software derived from one contributed by Colin Plumb.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Colin Plumb.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * The code for MD5 transform was taken from Colin Plumb's
+ * implementation, which has been placed in the public domain. The
+ * MD5 cryptographic checksum was devised by Ronald Rivest, and is
+ * documented in RFC 1321, "The MD5 Message Digest Algorithm".
+ *
+ */
+
+#include <sys/types.h>
+
+#include "struct.h"
+#include "common.h"
+
+ID_CVS("$Id$");
+/*
+ * MD5 transform algorithm, taken from code written by Colin Plumb,
+ * and put into the public domain
+ *
+ * QUESTION: Replace this with SHA, which as generally received better
+ * reviews from the cryptographic community?
+ */
+void
+MD5Init(buf)
+ u_int32_t buf[4];
+{
+ buf[0] = 0x67452301;
+ buf[1] = 0xefcdab89;
+ buf[2] = 0x98badcfe;
+ buf[3] = 0x10325476;
+}
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+ ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data.
+ */
+void
+MD5Transform(buf, in)
+ u_int32_t buf[4];
+ u_int32_t in[16];
+{
+ u_int32_t a, b, c, d;
+
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
+
+ MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, common/packet.c
+ * Copyright (C) 1990 Jarkko Oikarinen and
+ * University of Oulu, Computing Center
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#include "msg.h"
+#include "h.h"
+
+ID_CVS("$Id$");
+ID_Copyright("(C) 1988 University of Oulu, Computing Center and Jarkko Oikarinen");
+ID_Notes("2.12 1/30/94");
+/*
+ * inittoken
+ * Cheat here, blah. Build the lookup tables from msgtab's,
+ * call them msgmap's. Called in main() with other inits.
+ * Yes, I know this is not the right module, but I said I cheat ;)
+ */
+void inittoken(void)
+{
+ Reg1 int loopy;
+ Reg2 int final;
+
+ /* Find the zero-entry */
+ for (final = 0; msgtab[final].cmd; final++)
+ ;
+ /* Point all entries to it */
+ for (loopy = 0; loopy<256; loopy++)
+ msgmap[loopy] = &msgtab[final];
+ /* Build references to existing commands */
+ for (loopy = 0; msgtab[loopy].cmd; loopy++)
+ msgmap[msgtab[loopy].token[0]] = &msgtab[loopy];
+}
+
+/*
+** dopacket
+** cptr - pointer to client structure for which the buffer data
+** applies.
+** buffer - pointr to the buffer containing the newly read data
+** length - number of valid bytes of data in the buffer
+**
+** Note:
+** It is implicitly assumed that dopacket is called only
+** with cptr of "local" variation, which contains all the
+** necessary fields (buffer etc..)
+*/
+int dopacket(cptr, buffer, length)
+Reg3 aClient *cptr;
+char *buffer;
+Reg4 int length;
+{
+ register char *ch1;
+ register char *ch2;
+ aClient *acpt = cptr->acpt;
+
+ me.receiveB += length; /* Update bytes received */
+ cptr->receiveB += length;
+ if (cptr->receiveB > 1023)
+ {
+ cptr->receiveK += (cptr->receiveB >> 10);
+ cptr->receiveB &= 0x03ff; /* 2^10 = 1024, 3ff = 1023 */
+ }
+ if (acpt != &me)
+ {
+ acpt->receiveB += length;
+ if (acpt->receiveB > 1023)
+ {
+ acpt->receiveK += (acpt->receiveB >> 10);
+ acpt->receiveB &= 0x03ff;
+ }
+ }
+ else if (me.receiveB > 1023)
+ {
+ me.receiveK += (me.receiveB >> 10);
+ me.receiveB &= 0x03ff;
+ }
+ ch1 = cptr->buffer + cptr->count;
+ ch2 = buffer;
+
+ while (--length >= 0)
+ {
+ register char g=(*ch1 = *ch2++);
+ /*
+ * Yuck. Stuck. To make sure we stay backward compatible,
+ * we must assume that either CR or LF terminates the message
+ * and not CR-LF. By allowing CR or LF (alone) into the body
+ * of messages, backward compatibility is lost and major
+ * problems will arise. - Avalon
+ */
+ if (g<'\16' && (g == '\n' || g == '\r'))
+ {
+ if (ch1 == cptr->buffer)
+ continue; /* Skip extra LF/CR's */
+ *ch1 = '\0';
+ me.receiveM += 1; /* Update messages received */
+ cptr->receiveM += 1;
+ if (cptr->acpt != &me)
+ cptr->acpt->receiveM += 1;
+ cptr->count = 0; /* ...just in case parse returns with
+ ** FLUSH_BUFFER without removing the
+ ** structure pointed by cptr... --msa
+ */
+ if (parse(cptr, cptr->buffer, ch1, msgtab) ==
+ FLUSH_BUFFER)
+ /*
+ ** FLUSH_BUFFER means actually that cptr
+ ** structure *does* not exist anymore!!! --msa
+ */
+ return FLUSH_BUFFER;
+ /*
+ ** Socket is dead so exit (which always returns with
+ ** FLUSH_BUFFER here). - avalon
+ */
+ if (cptr->flags & FLAGS_DEADSOCKET)
+ return exit_client(cptr, cptr, &me,
+ "Dead Socket");
+ ch1 = cptr->buffer;
+ }
+ else if (ch1 < cptr->buffer + (sizeof(cptr->buffer)-1))
+ ch1++; /* There is always room for the null */
+ }
+ cptr->count = ch1 - cptr->buffer;
+ return 0;
+}
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, common/parse.c
+ * Copyright (C) 1990 Jarkko Oikarinen and
+ * University of Oulu, Computing Center
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* -- Jto -- 03 Jun 1990
+ * Changed the order of defines...
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)parse.c 2.33 1/30/94 (C) 1988 University of Oulu, \
+Computing Center and Jarkko Oikarinen";
+#endif
+#include "struct.h"
+#include "common.h"
+
+ID_CVS("$Id$");
+ID_Copyright("(C) 1988 University of Oulu, Computing Center and Jarkko Oikarinen");
+ID_Notes("2.33 1/30/94");
+#undef RAWDEBUG
+
+char backupbuf[8192];
+
+#define MSGTAB
+#include "msg.h"
+#undef MSGTAB
+#include "sys.h"
+#include "numeric.h"
+#include "h.h"
+
+/*
+ * NOTE: parse() should not be called recursively by other functions!
+ */
+static char *para[MAXPARA+1];
+
+static char sender[HOSTLEN+1];
+static int cancel_clients PROTO((aClient *, aClient *, char *));
+static void remove_unknown PROTO((aClient *, char *));
+/*
+** Find a client (server or user) by name.
+**
+** *Note*
+** Semantics of this function has been changed from
+** the old. 'name' is now assumed to be a null terminated
+** string and the search is the for server and user.
+*/
+aClient *find_client(name, cptr)
+char *name;
+Reg1 aClient *cptr;
+ {
+ if (name)
+ cptr = hash_find_client(name, cptr);
+
+ return cptr;
+ }
+
+aClient *find_nickserv(name, cptr)
+char *name;
+Reg1 aClient *cptr;
+ {
+ if (name)
+ cptr = hash_find_nickserver(name, cptr);
+
+ return cptr;
+ }
+
+
+/*
+** Find server by name.
+**
+** This implementation assumes that server and user names
+** are unique, no user can have a server name and vice versa.
+** One should maintain separate lists for users and servers,
+** if this restriction is removed.
+**
+** *Note*
+** Semantics of this function has been changed from
+** the old. 'name' is now assumed to be a null terminated
+** string.
+*/
+aClient *find_server(name, cptr)
+char *name;
+Reg1 aClient *cptr;
+{
+ if (name)
+ cptr = hash_find_server(name, cptr);
+ return cptr;
+}
+
+aClient *find_name(name, cptr)
+char *name;
+aClient *cptr;
+{
+ Reg1 aClient *c2ptr = cptr;
+
+ if (!collapse(name))
+ return c2ptr;
+
+ if ((c2ptr = hash_find_server(name, cptr)))
+ return (c2ptr);
+ if (!index(name, '*'))
+ return c2ptr;
+ for (c2ptr = client; c2ptr; c2ptr = c2ptr->next)
+ {
+ if (!IsServer(c2ptr) && !IsMe(c2ptr))
+ continue;
+ if (match(name, c2ptr->name) == 0)
+ break;
+ if (index(c2ptr->name, '*'))
+ if (match(c2ptr->name, name) == 0)
+ break;
+ }
+ return (c2ptr ? c2ptr : cptr);
+}
+
+/*
+** Find person by (nick)name.
+*/
+aClient *find_person(name, cptr)
+char *name;
+aClient *cptr;
+ {
+ Reg1 aClient *c2ptr = cptr;
+
+ c2ptr = find_client(name, c2ptr);
+
+ if (c2ptr && IsClient(c2ptr) && c2ptr->user)
+ return c2ptr;
+ else
+ return cptr;
+ }
+
+/*
+ * parse a buffer.
+ *
+ * NOTE: parse() should not be called recusively by any other fucntions!
+ */
+int parse(cptr, buffer, bufend, mptr)
+aClient *cptr;
+char *buffer, *bufend;
+struct Message *mptr;
+ {
+ Reg1 aClient *from = cptr;
+ Reg2 char *ch, *s;
+ Reg3 int len, i, numeric, paramcount, noprefix = 0;
+ Reg4 int token,mfound;
+#ifdef DEBUGMODE
+ time_t then, ticks;
+ int retval;
+#endif
+ struct Message *bmptr;
+
+ Debug((DEBUG_ERROR,"Parsing: %s (from %s)", buffer,(*cptr->name ? cptr->name : "*")));
+ if (IsDead(cptr))
+ return 0;
+
+#ifdef RAWDEBUG
+ sendto_ops("Debug: parse(): %s", buffer);
+#endif
+ backupbuf[0] = '\0';
+ strcpy(backupbuf, buffer);
+ s = sender;
+ *s = '\0';
+ for (ch = buffer; *ch == ' '; ch++)
+ ;
+ para[0] = from->name;
+ if (*ch == ':')
+ {
+ /*
+ ** Copy the prefix to 'sender' assuming it terminates
+ ** with SPACE (or NULL, which is an error, though).
+ */
+ for (++ch, i = 0; *ch && *ch != ' '; ++ch )
+ if (s < (sender + sizeof(sender)-1))
+ *s++ = *ch; /* leave room for NULL */
+ *s = '\0';
+ /*
+ ** Actually, only messages coming from servers can have
+ ** the prefix--prefix silently ignored, if coming from
+ ** a user client...
+ **
+ ** ...sigh, the current release "v2.2PL1" generates also
+ ** null prefixes, at least to NOTIFY messages (e.g. it
+ ** puts "sptr->nickname" as prefix from server structures
+ ** where it's null--the following will handle this case
+ ** as "no prefix" at all --msa (": NOTICE nick ...")
+ */
+ if (*sender && IsServer(cptr))
+ {
+ from = find_client(sender, (aClient *) NULL);
+ if (!from || match(from->name, sender))
+ from = find_server(sender, (aClient *)NULL);
+ else if (!from && index(sender, '@'))
+ from = find_nickserv(sender, (aClient *)NULL);
+
+ para[0] = sender;
+
+ /* Hmm! If the client corresponding to the
+ * prefix is not found--what is the correct
+ * action??? Now, I will ignore the message
+ * (old IRC just let it through as if the
+ * prefix just wasn't there...) --msa
+ */
+ if (!from)
+ {
+ Debug((DEBUG_ERROR,
+ "Unknown prefix (%s)(%s) from (%s)",
+ sender, buffer, cptr->name));
+ ircstp->is_unpf++;
+ remove_unknown(cptr, sender);
+ return -1;
+ }
+ if (from->from != cptr)
+ {
+ ircstp->is_wrdi++;
+ Debug((DEBUG_ERROR,
+ "Message (%s) coming from (%s)",
+ buffer, cptr->name));
+ return cancel_clients(cptr, from, ch);
+ }
+ }
+ while (*ch == ' ')
+ ch++;
+ }
+ else
+ noprefix = 1;
+ if (*ch == '\0')
+ {
+ ircstp->is_empt++;
+ Debug((DEBUG_NOTICE, "Empty message from host %s:%s",
+ cptr->name, from->name));
+ return(-1);
+ }
+ /*
+ ** Extract the command code from the packet. Point s to the end
+ ** of the command code and calculate the length using pointer
+ ** arithmetic. Note: only need length for numerics and *all*
+ ** numerics must have paramters and thus a space after the command
+ ** code. -avalon
+ */
+ s = (char *)index(ch, ' '); /* s -> End of the command code */
+ len = (s) ? (s - ch) : 0;
+ if (len == 3 &&
+ isdigit(*ch) && isdigit(*(ch + 1)) && isdigit(*(ch + 2)))
+ {
+ mptr = NULL;
+ numeric = (*ch - '0') * 100 + (*(ch + 1) - '0') * 10
+ + (*(ch + 2) - '0');
+ paramcount = MAXPARA;
+ ircstp->is_num++;
+ }
+ else
+ {
+ if (s)
+ *s++ = '\0';
+
+ /* xx or x = token :P */
+ if ((strlen(ch) < 3) && IsServer(cptr))
+ {
+ token = 1;
+ }
+ else
+ {
+ token = 0;
+ }
+ bmptr = mptr;
+
+ /* run a fast token search through if token */
+ mfound = 0;
+ if (token == 1)
+ {
+ for (; mptr->cmd; mptr++)
+ {
+ if (strcmp(mptr->token, ch)==0)
+ {
+ mfound = 1;
+ break;
+ }
+ }
+ }
+
+ /* no token match .. grr :P */
+ if (mfound == 0)
+ {
+ mptr = bmptr;
+ for (; mptr->cmd; mptr++)
+ {
+ if (mycmp(mptr->cmd, ch)==0)
+ break;
+ }
+ }
+/* if (ch[1] == '\0' && IsToken(cptr))
+ mptr = msgmap[(u_char)*ch];
+ else
+*/
+ if (!mptr->cmd)
+ {
+ /*
+ ** Note: Give error message *only* to recognized
+ ** persons. It's a nightmare situation to have
+ ** two programs sending "Unknown command"'s or
+ ** equivalent to each other at full blast....
+ ** If it has got to person state, it at least
+ ** seems to be well behaving. Perhaps this message
+ ** should never be generated, though... --msa
+ ** Hm, when is the buffer empty -- if a command
+ ** code has been found ?? -Armin
+ */
+ if (buffer[0] != '\0')
+ {
+ if (IsPerson(from))
+ sendto_one(from,
+ ":%s %d %s %s :Unknown command",
+ me.name, ERR_UNKNOWNCOMMAND,
+ from->name, ch);
+ Debug((DEBUG_ERROR,"Unknown (%s) from %s",
+ ch, get_client_name(cptr, TRUE)));
+ }
+ ircstp->is_unco++;
+ return(-1);
+ }
+ paramcount = mptr->parameters;
+ i = bufend - ch; /* Is this right? -Donwulff */
+ mptr->bytes += i;
+ if ((mptr->flags & 1) && !(IsServer(cptr) || IsService(cptr)))
+ cptr->since += (2 + i / 120);
+ /* Allow only 1 msg per 2 seconds
+ * (on average) to prevent dumping.
+ * to keep the response rate up,
+ * bursts of up to 5 msgs are allowed
+ * -SRB
+ */
+ }
+ /*
+ ** Must the following loop really be so devious? On
+ ** surface it splits the message to parameters from
+ ** blank spaces. But, if paramcount has been reached,
+ ** the rest of the message goes into this last parameter
+ ** (about same effect as ":" has...) --msa
+ */
+
+ /* Note initially true: s==NULL || *(s-1) == '\0' !! */
+
+ i = 0;
+ if (s)
+ {
+ if (paramcount > MAXPARA)
+ paramcount = MAXPARA;
+ for (;;)
+ {
+ /*
+ ** Never "FRANCE " again!! ;-) Clean
+ ** out *all* blanks.. --msa
+ */
+ while (*s == ' ')
+ *s++ = '\0';
+
+ if (*s == '\0')
+ break;
+ if (*s == ':')
+ {
+ /*
+ ** The rest is single parameter--can
+ ** include blanks also.
+ */
+ para[++i] = s + 1;
+ break;
+ }
+ para[++i] = s;
+ if (i >= paramcount)
+ break;
+ for (; *s != ' ' && *s; s++)
+ ;
+ }
+ }
+ para[++i] = NULL;
+ if (mptr == NULL)
+ return (do_numeric(numeric, cptr, from, i, para));
+ mptr->count++;
+ if (IsRegisteredUser(cptr) &&
+#ifdef IDLE_FROM_MSG
+ mptr->func == m_private)
+#else
+ mptr->func != m_ping && mptr->func != m_pong)
+#endif
+ from->user->last = TStime();
+
+ /* Lame protocol 4 stuff... this if can be removed when all are 2.9 */
+ if (noprefix && IsServer(cptr) && i >= 2 && mptr->func == m_squit &&
+ (!(from = find_server(para[1], (aClient *)NULL)) ||
+ from->from != cptr))
+ {
+ Debug((DEBUG_DEBUG,"Ignoring protocol 4 \"%s %s %s ...\"",
+ para[0], para[1], para[2]));
+ return 0;
+ }
+
+#ifndef DEBUGMODE
+ return (*mptr->func)(cptr, from, i, para);
+#else
+ then = clock();
+ retval = (*mptr->func)(cptr, from, i, para);
+ if (retval != FLUSH_BUFFER) {
+ ticks = (clock()-then);
+ if (IsServer(cptr))
+ mptr->rticks += ticks;
+ else
+ mptr->lticks += ticks;
+ cptr->cputime += ticks;
+ }
+
+ return retval;
+#endif
+ }
+
+/*
+ * field breakup for ircd.conf file.
+ */
+char *getfield(newline)
+char *newline;
+{
+ static char *line = NULL;
+ char *end, *field;
+
+ if (newline)
+ line = newline;
+ if (line == NULL)
+ return(NULL);
+
+ field = line;
+ if ((end = (char *)index(line,':')) == NULL)
+ {
+ line = NULL;
+ if ((end = (char *)index(field,'\n')) == NULL)
+ end = field + strlen(field);
+ }
+ else
+ line = end + 1;
+ *end = '\0';
+ return(field);
+}
+
+static int cancel_clients(cptr, sptr, cmd)
+aClient *cptr, *sptr;
+char *cmd;
+{
+ char *cmdpriv;
+ /*
+ * kill all possible points that are causing confusion here,
+ * I'm not sure I've got this all right...
+ * - avalon
+ * No you didn't...
+ * - Run
+ */
+ /* This little bit of code allowed paswords to nickserv to be
+ * seen. A definite no-no. --Russell
+ sendto_ops("Message (%s) for %s[%s!%s@%s] from %s", cmd,
+ sptr->name, sptr->from->name, sptr->from->username,
+ sptr->from->sockhost, get_client_name(cptr, TRUE));*/
+ /*
+ * Incorrect prefix for a server from some connection. If it is a
+ * client trying to be annoying, just QUIT them, if it is a server
+ * then the same deal.
+ */
+ if (IsServer(sptr) || IsMe(sptr))
+ {
+ /*
+ * First go at tracking down what really causes the
+ * dreaded Fake Direction error. It should not be possible
+ * ever to happen. Assume nothing here since this is an
+ * impossibility.
+ *
+ * Check for valid fields, then send out globops with
+ * the msg command recieved, who apperently sent it,
+ * where it came from, and where it was suppose to come
+ * from. We send the msg command to find out if its some
+ * bug somebody found with an old command, maybe some
+ * weird thing like, /ping serverto.* serverfrom.* and on
+ * the way back, fake direction? Don't know, maybe this
+ * will tell us. -Cabal95
+ *
+ * Take #2 on Fake Direction. Most of them seem to be
+ * numerics. But sometimes its getting fake direction on
+ * SERVER msgs.. HOW?? Display the full message now to
+ * figure it out... -Cabal95
+ *
+ * Okay I give up. Can't find it. Seems like it will
+ * exist untill ircd is completely rewritten. :/ For now
+ * just completely ignore them. Needs to be modified to
+ * send these messages to a special oper channel. -Cabal95
+ *
+ aClient *from;
+ char *fromname=NULL, *sptrname=NULL, *cptrname=NULL, *s;
+
+ while (*cmd == ' ')
+ cmd++;
+ if (s = index(cmd, ' '))
+ *s++ = '\0';
+ if (!strcasecmp(cmd, "PRIVMSG") ||
+ !strcasecmp(cmd, "NOTICE") ||
+ !strcasecmp(cmd, "PASS"))
+ s = NULL;
+ if (sptr && sptr->name)
+ sptrname = sptr->name;
+ if (cptr && cptr->name)
+ cptrname = cptr->name;
+ if (sptr && sptr->from && sptr->from->name)
+ fromname = sptr->from->name;
+
+ sendto_serv_butone(NULL, ":%s GLOBOPS :"
+ "Fake Direction: Message[%s %s] from %s via %s "
+ "instead of %s (Tell Cabal95)", me.name, cmd,
+ (s ? s : ""),
+ (sptr->name!=NULL)?sptr->name:"<unknown>",
+ (cptr->name!=NULL)?cptr->name:"<unknown>",
+ (fromname!=NULL)?fromname:"<unknown>");
+ sendto_ops(
+ "Fake Direction: Message[%s %s] from %s via %s "
+ "instead of %s (Tell Cabal95)", cmd,
+ (s ? s : ""),
+ (sptr->name!=NULL)?sptr->name:"<unknown>",
+ (cptr->name!=NULL)?cptr->name:"<unknown>",
+ (fromname!=NULL)?fromname:"<unknown>");
+
+ /*
+ * We don't drop the server anymore. Just ignore
+ * the message and go about your business. And hope
+ * we don't get flooded. :-) -Cabal95
+ sendto_ops("Dropping server %s", cptr->name);
+ return exit_client(cptr, cptr, &me, "Fake Direction");
+ */
+ return 0;
+ }
+ /*
+ * Ok, someone is trying to impose as a client and things are
+ * confused. If we got the wrong prefix from a server, send out a
+ * kill, else just exit the lame client.
+ */
+ if (IsServer(cptr))
+ {
+ /*
+ ** It is NOT necessary to send a KILL here...
+ ** We come here when a previous 'NICK new'
+ ** nick collided with an older nick, and was
+ ** ignored, and other messages still were on
+ ** the way (like the following USER).
+ ** We simply ignore it all, a purge will be done
+ ** automatically by the server 'cptr' as a reaction
+ ** on our 'NICK older'. --Run
+ */
+ return 0; /* On our side, nothing changed */
+ }
+ return exit_client(cptr, cptr, &me, "Fake prefix");
+}
+
+static void remove_unknown(cptr, sender)
+aClient *cptr;
+char *sender;
+{
+ if (!IsRegistered(cptr) || IsClient(cptr))
+ return;
+ /*
+ * Not from a server so don't need to worry about it.
+ */
+ if (!IsServer(cptr))
+ return;
+
+ /*
+ * Do kill if it came from a server because it means there is a ghost
+ * user on the other server which needs to be removed. -avalon
+ */
+ if (!index(sender, '.'))
+ sendto_one(cptr, ":%s KILL %s :%s (%s(?) <- %s)",
+ me.name, sender, me.name, sender,
+ get_client_name(cptr, FALSE));
+ else
+ sendto_one(cptr, ":%s SQUIT %s :(Unknown from %s)",
+ me.name, sender, get_client_name(cptr, FALSE));
+}
--- /dev/null
+/*
+ * ircd/res.c (C)opyright 1992, 1993, 1994 Darren Reed. All rights reserved.
+ * This file may not be distributed without the author's prior permission in
+ * any shape or form. The author takes no responsibility for any damage or
+ * loss of property which results from the use of this software. Distribution
+ * of this file must include this notice.
+ */
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#include "res.h"
+#include "numeric.h"
+#include "h.h"
+
+#include <signal.h>
+#ifndef _WIN32
+#include <sys/time.h>
+#include <sys/socket.h>
+#endif
+#include "nameser.h"
+#include "resolv.h"
+
+#ifndef lint
+static char sccsid[] = "@(#)res.c 2.38 4/13/94 (C) 1992 Darren Reed";
+#endif
+
+ID_CVS("$Id$");
+ID_Copyright("(C) 1992 Darren Reed");
+ID_Notes("2.38 4/13/94");
+
+#undef DEBUG /* because there is a lot of debug code in here :-) */
+
+extern int dn_expand PROTO((char *, char *, char *, char *, int));
+extern int dn_skipname PROTO((char *, char *));
+extern int res_mkquery PROTO((int, char *, int, int, char *, int,
+ struct rrec *, char *, int));
+
+#ifndef _WIN32
+extern int errno, h_errno;
+#endif
+extern int highest_fd;
+extern aClient *local[];
+
+static char hostbuf[512]; /* tq lamego/ptlink ircd */
+static char dot[] = ".";
+static int incache = 0;
+static CacheTable hashtable[ARES_CACSIZE];
+static aCache *cachetop = NULL;
+static ResRQ *last, *first;
+
+static void rem_cache PROTO((aCache *));
+static void rem_request PROTO((ResRQ *));
+static int do_query_name PROTO((Link *, char *, ResRQ *));
+static int do_query_number PROTO((Link *, struct in_addr *, ResRQ *));
+static void resend_query PROTO((ResRQ *));
+static int proc_answer PROTO((ResRQ *, HEADER *, char *, char *));
+static int query_name PROTO((char *, int, int, ResRQ *));
+static aCache *make_cache PROTO((ResRQ *));
+static aCache *find_cache_name PROTO((char *));
+static aCache *find_cache_number PROTO((ResRQ *, char *));
+static int add_request PROTO((ResRQ *));
+static ResRQ *make_request PROTO((Link *));
+static int send_res_msg PROTO((char *, int, int));
+static ResRQ *find_id PROTO((int));
+static int hash_number PROTO((unsigned char *));
+static void update_list PROTO((ResRQ *, aCache *));
+static int hash_name PROTO((char *));
+
+#ifdef _WIN32
+static void async_dns(void *parm);
+#endif
+
+static struct cacheinfo {
+ int ca_adds;
+ int ca_dels;
+ int ca_expires;
+ int ca_lookups;
+ int ca_na_hits;
+ int ca_nu_hits;
+ int ca_updates;
+} cainfo;
+
+static struct resinfo {
+ int re_errors;
+ int re_nu_look;
+ int re_na_look;
+ int re_replies;
+ int re_requests;
+ int re_resends;
+ int re_sent;
+ int re_timeouts;
+ int re_shortttl;
+ int re_unkrep;
+} reinfo;
+
+int init_resolver(op)
+int op;
+{
+ int ret = 0;
+
+#ifdef LRAND48
+ srand48(TStime());
+#endif
+ if (op & RES_INITLIST)
+ {
+ bzero((char *)&reinfo, sizeof(reinfo));
+ first = last = NULL;
+ }
+ if (op & RES_CALLINIT)
+ {
+ ret = res_init();
+ if (!_res.nscount)
+ {
+ _res.nscount = 1;
+ _res.nsaddr_list[0].sin_addr.s_addr =
+ inet_addr("127.0.0.1");
+ }
+ }
+
+ if (op & RES_INITSOCK)
+ {
+#ifndef _WIN32
+ int on = 0;
+ ret = resfd = socket(AF_INET, SOCK_DGRAM, 0);
+ set_non_blocking(resfd, &me);
+ (void) setsockopt(ret, SOL_SOCKET, SO_BROADCAST,
+ (char *)&on, sizeof(on));
+#else
+ /* We use Windows internal resolv functions so we have nothing
+ * to do here
+ */
+#endif
+ }
+#ifdef DEBUG
+ if (op & RES_INITDEBG);
+ _res.options |= RES_DEBUG;
+#endif
+ if (op & RES_INITCACH)
+ {
+ bzero((char *)&cainfo, sizeof(cainfo));
+ bzero((char *)hashtable, sizeof(hashtable));
+ }
+ if (op == 0)
+ ret = resfd;
+ return ret;
+}
+
+static int add_request(new)
+ResRQ *new;
+{
+ if (!new)
+ return -1;
+ if (!first)
+ first = last = new;
+ else
+ {
+ last->next = new;
+ last = new;
+ }
+ new->next = NULL;
+ reinfo.re_requests++;
+ return 0;
+}
+
+/*
+ * remove a request from the list. This must also free any memory that has
+ * been allocated for temporary storage of DNS results.
+ */
+static void rem_request(old)
+ResRQ *old;
+{
+ Reg1 ResRQ **rptr, *r2ptr = NULL;
+ Reg2 int i;
+ Reg3 char *s;
+
+ if (!old)
+ return;
+#ifdef _WIN32
+ while (old->locked)
+ Sleep(0);
+#endif
+ for (rptr = &first; *rptr; r2ptr = *rptr, rptr = &(*rptr)->next)
+ if (*rptr == old)
+ {
+ *rptr = old->next;
+ if (last == old)
+ last = r2ptr;
+ break;
+ }
+#ifdef DEBUG
+ Debug((DEBUG_INFO,"rem_request:Remove %#x at %#x %#x",
+ old, *rptr, r2ptr));
+#endif
+ r2ptr = old;
+#ifndef _WIN32
+ if (r2ptr->he.h_name)
+ MyFree((char *)r2ptr->he.h_name);
+ for (i = 0; i < MAXALIASES; i++)
+ if ((s = r2ptr->he.h_aliases[i]))
+ MyFree(s);
+#else
+ if (r2ptr->he)
+ MyFree(r2ptr->he);
+#endif
+ if (r2ptr->name)
+ MyFree(r2ptr->name);
+ MyFree(r2ptr);
+
+ return;
+}
+
+/*
+ * Create a DNS request record for the server.
+ */
+static ResRQ *make_request(lp)
+Link *lp;
+{
+ Reg1 ResRQ *nreq;
+
+ nreq = (ResRQ *)MyMalloc(sizeof(ResRQ));
+ bzero((char *)nreq, sizeof(ResRQ));
+ nreq->next = NULL; /* where NULL is non-zero ;) */
+ nreq->sentat = TStime();
+ nreq->retries = 3;
+ nreq->resend = 1;
+ nreq->srch = -1;
+ if (lp)
+ bcopy((char *)lp, (char *)&nreq->cinfo, sizeof(Link));
+ else
+ bzero((char *)&nreq->cinfo, sizeof(Link));
+ nreq->timeout = 4; /* start at 4 and exponential inc. */
+#ifndef _WIN32
+ nreq->he.h_addrtype = AF_INET;
+ nreq->he.h_name = NULL;
+ nreq->he.h_aliases[0] = NULL;
+#else
+ nreq->he = (struct hostent *)MyMalloc(MAXGETHOSTSTRUCT);
+ bzero((char *)nreq->he, MAXGETHOSTSTRUCT);
+ nreq->he->h_addrtype = AF_INET;
+ nreq->he->h_name = NULL;
+#endif
+ (void)add_request(nreq);
+ return nreq;
+}
+
+/*
+ * Remove queries from the list which have been there too long without
+ * being resolved.
+ */
+time_t timeout_query_list(now)
+time_t now;
+{
+ Reg1 ResRQ *rptr, *r2ptr;
+ Reg2 time_t next = 0, tout;
+ aClient *cptr;
+
+ Debug((DEBUG_DNS,"timeout_query_list at %s",myctime(now)));
+ for (rptr = first; rptr; rptr = r2ptr)
+ {
+ r2ptr = rptr->next;
+ tout = rptr->sentat + rptr->timeout;
+#ifndef _WIN32
+ if (now >= tout)
+#else
+ if (now >= tout && !rptr->locked)
+#endif
+ if (--rptr->retries <= 0)
+ {
+#ifdef DEBUG
+ Debug((DEBUG_ERROR,"timeout %x now %d cptr %x",
+ rptr, now, rptr->cinfo.value.cptr));
+#endif
+ reinfo.re_timeouts++;
+ cptr = rptr->cinfo.value.cptr;
+ switch (rptr->cinfo.flags)
+ {
+ case ASYNC_CLIENT :
+#ifdef SHOWCONNECTINFO
+#ifndef _WIN32
+ write(cptr->fd, REPORT_FAIL_DNS,
+ R_fail_dns);
+#else
+ send(cptr->fd, REPORT_FAIL_DNS,
+ R_fail_dns, 0);
+#endif
+#endif
+ ClearDNS(cptr);
+ if (!DoingAuth(cptr))
+ SetAccess(cptr);
+ break;
+ case ASYNC_SERVER :
+ sendto_ops("Host %s unknown",
+ rptr->name);
+ ClearDNS(cptr);
+ if (check_server(cptr, NULL,
+ NULL, NULL, 1))
+ (void)exit_client(cptr, cptr,
+ &me, "No Permission");
+ break;
+ case ASYNC_CONNECT :
+ sendto_ops("Host %s unknown",
+ rptr->name);
+ break;
+ }
+ rem_request(rptr);
+ continue;
+ }
+ else
+ {
+ rptr->sentat = now;
+ rptr->timeout += rptr->timeout;
+#ifndef _WIN32
+ resend_query(rptr);
+#endif
+ tout = now + rptr->timeout;
+#ifdef DEBUG
+ Debug((DEBUG_INFO,"r %x now %d retry %d c %x",
+ rptr, now, rptr->retries,
+ rptr->cinfo.value.cptr));
+#endif
+ }
+ if (!next || tout < next)
+ next = tout;
+ }
+ Debug((DEBUG_DNS,"Next timeout_query_list() at %s, %d",
+ myctime((next > now) ? next : (now + AR_TTL)),
+ (next > now) ? (next - now) : AR_TTL));
+ return (next > now) ? next : (now + AR_TTL);
+}
+
+/*
+ * del_queries - called by the server to cleanup outstanding queries for
+ * which there no longer exist clients or conf lines.
+ */
+void del_queries(cp)
+char *cp;
+{
+ Reg1 ResRQ *rptr, *r2ptr;
+
+ for (rptr = first; rptr; rptr = r2ptr)
+ {
+ r2ptr = rptr->next;
+ if (cp == rptr->cinfo.value.cp)
+ rem_request(rptr);
+ }
+}
+
+#ifndef _WIN32
+/*
+ * sends msg to all nameservers found in the "_res" structure.
+ * This should reflect /etc/resolv.conf. We will get responses
+ * which arent needed but is easier than checking to see if nameserver
+ * isnt present. Returns number of messages successfully sent to
+ * nameservers or -1 if no successful sends.
+ */
+static int send_res_msg(msg, len, rcount)
+char *msg;
+int len, rcount;
+{
+ Reg1 int i;
+ int sent = 0, max;
+
+ if (!msg)
+ return -1;
+
+ max = MIN(_res.nscount, rcount);
+ if (_res.options & RES_PRIMARY)
+ max = 1;
+ if (!max)
+ max = 1;
+
+ for (i = 0; i < max; i++)
+ {
+ _res.nsaddr_list[i].sin_family = AF_INET;
+ if (sendto(resfd, msg, len, 0, (struct sockaddr *)
+ &(_res.nsaddr_list[i]), sizeof(struct sockaddr)) == len)
+ {
+ reinfo.re_sent++;
+ sent++;
+ }
+ else
+ Debug((DEBUG_ERROR,"s_r_m:sendto: %d on %d",
+ errno, resfd));
+ }
+
+ return (sent) ? sent : -1;
+}
+#endif /*_WIN32*/
+
+/*
+ * find a dns request id (id is determined by dn_mkquery)
+ */
+static ResRQ *find_id(id)
+int id;
+{
+ Reg1 ResRQ *rptr;
+
+ for (rptr = first; rptr; rptr = rptr->next)
+ if (rptr->id == id)
+ return rptr;
+ return NULL;
+}
+
+struct hostent *gethost_byname(name, lp)
+char *name;
+Link *lp;
+{
+ Reg1 aCache *cp;
+
+ reinfo.re_na_look++;
+ if ((cp = find_cache_name(name)))
+#ifndef _WIN32
+ return (struct hostent *)&(cp->he);
+#else
+ return (struct hostent *)cp->he;
+#endif
+ if (!lp)
+ return NULL;
+ (void)do_query_name(lp, name, NULL);
+ return NULL;
+}
+
+struct hostent *gethost_byaddr(addr, lp)
+char *addr;
+Link *lp;
+{
+ aCache *cp;
+
+ reinfo.re_nu_look++;
+ if ((cp = find_cache_number(NULL, addr)))
+#ifndef _WIN32
+ return (struct hostent *)&(cp->he);
+#else
+ return (struct hostent *)cp->he;
+#endif
+ if (!lp)
+ return NULL;
+ (void)do_query_number(lp, (struct in_addr *)addr, NULL);
+ return NULL;
+}
+
+static int do_query_name(lp, name, rptr)
+Link *lp;
+char *name;
+Reg1 ResRQ *rptr;
+{
+#ifndef _WIN32
+ char hname[HOSTLEN+1];
+ int len;
+
+ (void)strncpy(hname, name, sizeof(hname) - 1);
+ len = strlen(hname);
+
+ if (rptr && !index(hname, '.') && _res.options & RES_DEFNAMES)
+ {
+ (void)strncat(hname, dot, sizeof(hname) - len - 1);
+ len++;
+ (void)strncat(hname, _res.defdname, sizeof(hname) - len -1);
+ }
+#endif
+ /*
+ * Store the name passed as the one to lookup and generate other host
+ * names to pass onto the nameserver(s) for lookups.
+ */
+ if (!rptr)
+ {
+ rptr = make_request(lp);
+ rptr->type = T_A;
+ rptr->name = (char *)MyMalloc(strlen(name) + 1);
+ (void)strcpy(rptr->name, name);
+ }
+#ifndef _WIN32
+ return (query_name(hname, C_IN, T_A, rptr));
+#else
+
+ rptr->id = _beginthread(async_dns, 0, (void *)rptr);
+ rptr->sends++;
+ return 0;
+#endif
+}
+
+/*
+ * Use this to do reverse IP# lookups.
+ */
+static int do_query_number(lp, numb, rptr)
+Link *lp;
+struct in_addr *numb;
+Reg1 ResRQ *rptr;
+{
+#ifndef _WIN32
+ char ipbuf[32];
+ Reg2 u_char *cp;
+
+ cp = (u_char *)&numb->s_addr;
+ (void)sprintf(ipbuf,"%u.%u.%u.%u.in-addr.arpa.",
+ (u_int)(cp[3]), (u_int)(cp[2]),
+ (u_int)(cp[1]), (u_int)(cp[0]));
+#endif
+ if (!rptr)
+ {
+ rptr = make_request(lp);
+ rptr->type = T_PTR;
+ rptr->addr.s_addr = numb->s_addr;
+#ifndef _WIN32
+ bcopy((char *)&numb->s_addr,
+ (char *)&rptr->he.h_addr, sizeof(struct in_addr));
+ rptr->he.h_length = sizeof(struct in_addr);
+#else
+ rptr->he->h_length = sizeof(struct in_addr);
+#endif
+ }
+#ifndef _WIN32
+ return (query_name(ipbuf, C_IN, T_PTR, rptr));
+#else
+ rptr->id = _beginthread(async_dns, 0, (void *)rptr);
+ rptr->sends++;
+ return 0;
+#endif
+}
+
+#ifndef _WIN32
+/*
+ * generate a query based on class, type and name.
+ */
+static int query_name(name, class, type, rptr)
+char *name;
+int class, type;
+ResRQ *rptr;
+{
+ struct timeval tv;
+ char buf[MAXPACKET];
+ int r,s,k = 0;
+ HEADER *hptr;
+
+ Debug((DEBUG_DNS,"query_name: na %s cl %d ty %d", name, class, type));
+ bzero(buf, sizeof(buf));
+ r = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
+ buf, sizeof(buf));
+ if (r <= 0)
+ {
+ h_errno = NO_RECOVERY;
+ return r;
+ }
+ hptr = (HEADER *)buf;
+#ifdef LRAND48
+ do {
+ hptr->id = htons(ntohs(hptr->id) + k + lrand48() & 0xffff);
+#else
+ (void) gettimeofday(&tv, NULL);
+ do {
+ /* htons/ntohs can be assembler macros, which cannot
+ be nested. Thus two lines. -Vesa */
+ u_short nstmp = ntohs(hptr->id) + k +
+ (u_short)(tv.tv_usec & 0xffff);
+ hptr->id = htons(nstmp);
+#endif /* LRAND48 */
+ k++;
+ } while (find_id(ntohs(hptr->id)));
+ rptr->id = ntohs(hptr->id);
+ rptr->sends++;
+ s = send_res_msg(buf, r, rptr->sends);
+ if (s == -1)
+ {
+ h_errno = TRY_AGAIN;
+ return -1;
+ }
+ else
+ rptr->sent += s;
+ return 0;
+}
+
+static void resend_query(rptr)
+ResRQ *rptr;
+{
+ if (rptr->resend == 0)
+ return;
+ reinfo.re_resends++;
+ switch(rptr->type)
+ {
+ case T_PTR:
+ (void)do_query_number(NULL, &rptr->addr, rptr);
+ break;
+ case T_A:
+ (void)do_query_name(NULL, rptr->name, rptr);
+ break;
+ default:
+ break;
+ }
+ return;
+}
+
+/*
+ * process name server reply.
+ */
+static int proc_answer(rptr, hptr, buf, eob)
+ResRQ *rptr;
+char *buf, *eob;
+HEADER *hptr;
+{
+ Reg1 char *cp, **alias;
+ Reg2 struct hent *hp;
+ int class, type, dlen, len, ans = 0, n;
+ struct in_addr dr, *adr;
+
+ cp = buf + sizeof(HEADER);
+ hp = (struct hent *)&(rptr->he);
+ adr = &hp->h_addr;
+ while (adr->s_addr)
+ adr++;
+ alias = hp->h_aliases;
+ while (*alias)
+ alias++;
+#ifdef SOL20 /* brain damaged compiler (Solaris2) it seems */
+ for (; hptr->qdcount > 0; hptr->qdcount--)
+#else
+ while (hptr->qdcount-- > 0)
+#endif
+ if ((n = dn_skipname(cp, eob)) == -1)
+ break;
+ else
+ cp += (n + QFIXEDSZ);
+ /*
+ * proccess each answer sent to us blech.
+ */
+ while (hptr->ancount-- > 0 && cp && cp < eob) {
+ n = dn_expand(buf, eob, cp, hostbuf, sizeof(hostbuf));
+ if (n <= 0)
+ break;
+
+ cp += n;
+ type = (int)_getshort(cp);
+ cp += sizeof(short);
+ class = (int)_getshort(cp);
+ cp += sizeof(short);
+ rptr->ttl = _getlong(cp);
+#ifndef LINUX_ALPHA
+ cp += sizeof(rptr->ttl);
+#else
+ /* This should really use the GETLONG macro which advances
+ * the pointer for us, but I don't know if that'll break other
+ * systems. sizeof(_getlong) does not always equal sizeof(time_t).
+ * This is the case on Linux alpha. 4 is the current standard
+ * for this portion of the resolver reply it would seem.
+ * heydowns@borg.com
+ */
+ cp += 4;
+
+#endif
+ dlen = (int)_getshort(cp);
+ cp += sizeof(short);
+ rptr->type = type;
+
+ len = strlen(hostbuf);
+ /* name server never returns with trailing '.' */
+ if (!index(hostbuf,'.') && (_res.options & RES_DEFNAMES))
+ {
+ (void)strcat(hostbuf, dot);
+ len++;
+ (void)strncat(hostbuf, _res.defdname,
+ sizeof(hostbuf) - 1 - len);
+ len = MIN(len + strlen(_res.defdname),
+ sizeof(hostbuf) - 1);
+ }
+
+ switch(type)
+ {
+ case T_A :
+ hp->h_length = dlen;
+ if (ans == 1)
+ hp->h_addrtype = (class == C_IN) ?
+ AF_INET : AF_UNSPEC;
+ bcopy(cp, (char *)&dr, dlen);
+ adr->s_addr = dr.s_addr;
+ Debug((DEBUG_INFO,"got ip # %s for %s",
+ inetntoa((char *)adr), hostbuf));
+ if (!hp->h_name)
+ {
+ hp->h_name =(char *)MyMalloc(len+1);
+ (void)strcpy(hp->h_name, hostbuf);
+ }
+ ans++;
+ adr++;
+ cp += dlen;
+ break;
+ case T_PTR :
+ if((n = dn_expand(buf, eob, cp, hostbuf,
+ sizeof(hostbuf) )) < 0)
+ {
+ cp = NULL;
+ break;
+ }
+ cp += n;
+ len = strlen(hostbuf);
+ Debug((DEBUG_INFO,"got host %s",hostbuf));
+ /*
+ * copy the returned hostname into the host name
+ * or alias field if there is a known hostname
+ * already.
+ */
+ if (hp->h_name)
+ {
+ if (alias >= &(hp->h_aliases[MAXALIASES-1]))
+ break;
+ *alias = (char *)MyMalloc(len + 1);
+ (void)strcpy(*alias++, hostbuf);
+ *alias = NULL;
+ }
+ else
+ {
+ hp->h_name = (char *)MyMalloc(len + 1);
+ (void)strcpy(hp->h_name, hostbuf);
+ }
+ ans++;
+ break;
+ case T_CNAME :
+ cp += dlen;
+ Debug((DEBUG_INFO,"got cname %s", hostbuf));
+ if (alias >= &(hp->h_aliases[MAXALIASES-1]))
+ break;
+ *alias = (char *)MyMalloc(len + 1);
+ (void)strcpy(*alias++, hostbuf);
+ *alias = NULL;
+ ans++;
+ break;
+ default :
+#ifdef DEBUG
+ Debug((DEBUG_INFO,"proc_answer: type:%d for:%s",
+ type, hostbuf));
+#endif
+ break;
+ }
+ }
+ return ans;
+}
+#endif /*_WIN32*/
+
+/*
+ * read a dns reply from the nameserver and process it.
+ */
+#ifndef _WIN32
+struct hostent *get_res(lp)
+char *lp;
+#else
+struct hostent *get_res(lp, id)
+char *lp;
+long id;
+#endif
+{
+#ifndef _WIN32
+ static char buf[sizeof(HEADER) + MAXPACKET];
+ Reg1 HEADER *hptr;
+ struct sockaddr_in sin;
+ int rc, a, len = sizeof(sin), max;
+#else
+ Reg3 struct hostent *he;
+#endif
+ Reg2 ResRQ *rptr = NULL;
+ aCache *cp;
+
+#ifndef _WIN32
+ rc = recvfrom(resfd, buf, sizeof(buf), 0, (struct sockaddr *)&sin,
+ &len);
+ if (rc == -1 || rc <= sizeof(HEADER))
+ goto getres_err;
+ /*
+ * convert DNS reply reader from Network byte order to CPU byte order.
+ */
+ hptr = (HEADER *)buf;
+ hptr->id = ntohs(hptr->id);
+ hptr->ancount = ntohs(hptr->ancount);
+ hptr->qdcount = ntohs(hptr->qdcount);
+ hptr->nscount = ntohs(hptr->nscount);
+ hptr->arcount = ntohs(hptr->arcount);
+#ifdef DEBUG
+ Debug((DEBUG_NOTICE, "get_res:id = %d rcode = %d ancount = %d",
+ hptr->id, hptr->rcode, hptr->ancount));
+#endif
+#endif
+ reinfo.re_replies++;
+ /*
+ * response for an id which we have already received an answer for
+ * just ignore this response.
+ */
+#ifndef _WIN32
+ rptr = find_id(hptr->id);
+#else
+ rptr = find_id(id);
+#endif
+ if (!rptr)
+ goto getres_err;
+#ifndef _WIN32
+ /*
+ * check against possibly fake replies
+ */
+ max = MIN(_res.nscount, rptr->sends);
+ if (!max)
+ max = 1;
+
+ for (a = 0; a < max; a++)
+ if (!_res.nsaddr_list[a].sin_addr.s_addr ||
+ !bcmp((char *)&sin.sin_addr,
+ (char *)&_res.nsaddr_list[a].sin_addr,
+ sizeof(struct in_addr)))
+ break;
+ if (a == max)
+ {
+ reinfo.re_unkrep++;
+ goto getres_err;
+ }
+
+ if ((hptr->rcode != NOERROR) || (hptr->ancount == 0))
+ {
+ switch (hptr->rcode)
+ {
+ case NXDOMAIN:
+ h_errno = TRY_AGAIN;
+ break;
+ case SERVFAIL:
+ h_errno = TRY_AGAIN;
+ break;
+ case NOERROR:
+ h_errno = NO_DATA;
+ break;
+ case FORMERR:
+ case NOTIMP:
+ case REFUSED:
+ default:
+ h_errno = NO_RECOVERY;
+ break;
+ }
+ reinfo.re_errors++;
+ /*
+ ** If a bad error was returned, we stop here and dont send
+ ** send any more (no retries granted).
+ */
+ if (h_errno != TRY_AGAIN)
+ {
+ Debug((DEBUG_DNS, "Fatal DNS error %d for %d",
+ h_errno, hptr->rcode));
+ rptr->resend = 0;
+ rptr->retries = 0;
+ }
+ goto getres_err;
+ }
+ a = proc_answer(rptr, hptr, buf, buf+rc);
+#ifdef DEBUG
+ Debug((DEBUG_INFO,"get_res:Proc answer = %d",a));
+#endif
+ if (a && rptr->type == T_PTR)
+ {
+ struct hostent *hp2 = NULL;
+
+ Debug((DEBUG_DNS, "relookup %s <-> %s",
+ rptr->he.h_name, inetntoa((char *)&rptr->he.h_addr)));
+ /*
+ * Lookup the 'authoritive' name that we were given for the
+ * ip#. By using this call rather than regenerating the
+ * type we automatically gain the use of the cache with no
+ * extra kludges.
+ */
+ if ((hp2 = gethost_byname(rptr->he.h_name, &rptr->cinfo)))
+ if (lp)
+ bcopy((char *)&rptr->cinfo, lp, sizeof(Link));
+ /*
+ * If name wasn't found, a request has been queued and it will
+ * be the last one queued. This is rather nasty way to keep
+ * a host alias with the query. -avalon
+ */
+ if (!hp2 && rptr->he.h_aliases[0])
+ for (a = 0; rptr->he.h_aliases[a]; a++)
+ {
+ Debug((DEBUG_DNS, "Copied CNAME %s for %s",
+ rptr->he.h_aliases[a],
+ rptr->he.h_name));
+ last->he.h_aliases[a] = rptr->he.h_aliases[a];
+ rptr->he.h_aliases[a] = NULL;
+ }
+
+ rem_request(rptr);
+ return hp2;
+ }
+
+ if (a > 0)
+ {
+ if (lp)
+ bcopy((char *)&rptr->cinfo, lp, sizeof(Link));
+ cp = make_cache(rptr);
+#ifdef DEBUG
+ Debug((DEBUG_INFO,"get_res:cp=%#x rptr=%#x (made)",cp,rptr));
+#endif
+
+ rem_request(rptr);
+ }
+ else
+ if (!rptr->sent)
+ rem_request(rptr);
+ return cp ? (struct hostent *)&cp->he : NULL;
+
+getres_err:
+ /*
+ * Reprocess an error if the nameserver didnt tell us to "TRY_AGAIN".
+ */
+ if (rptr)
+ {
+ if (h_errno != TRY_AGAIN)
+ {
+ /*
+ * If we havent tried with the default domain and its
+ * set, then give it a try next.
+ */
+ if (_res.options & RES_DEFNAMES && ++rptr->srch == 0)
+ {
+ rptr->retries = _res.retry;
+ rptr->sends = 0;
+ rptr->resend = 1;
+ resend_query(rptr);
+ }
+ else
+ resend_query(rptr);
+ }
+ else if (lp)
+ bcopy((char *)&rptr->cinfo, lp, sizeof(Link));
+ }
+#else /*_WIN32*/
+ he = rptr->he;
+
+ if (he && he->h_name && ((struct in_addr *)he->h_addr)->s_addr &&
+ rptr->locked < 2)
+ {
+ /*
+ * We only need to re-check the DNS if its a "byaddr" call,
+ * the "byname" calls will work correctly. -Cabal95
+ */
+ char tempname[120];
+ int i;
+ long amt;
+ struct hostent *hp, *he = rptr->he;
+
+ strcpy(tempname, he->h_name);
+ hp = gethostbyname(tempname);
+ if (hp && !bcmp(hp->h_addr, he->h_addr, sizeof(struct in_addr)))
+ {
+ }
+ else
+ rptr->he->h_name = NULL;
+ }
+ if (lp)
+ bcopy((char *)&rptr->cinfo, lp, sizeof(Link));
+ cp = make_cache(rptr);
+# ifdef DEBUG
+ Debug((DEBUG_INFO,"get_res:cp=%#x rptr=%#x (made)", cp, rptr));
+# endif
+ rptr->locked = 0;
+ rem_request(rptr);
+ return cp ? (struct hostent *)cp->he : NULL;
+
+getres_err:
+ if (lp && rptr)
+ bcopy((char *)&rptr->cinfo, lp, sizeof(Link));
+#endif
+ return (struct hostent *)NULL;
+}
+
+static int hash_number(ip)
+Reg1 unsigned char *ip;
+{
+ Reg1 u_int hashv = 0;
+
+ /* could use loop but slower */
+ hashv += (int)*ip++;
+ hashv += hashv + (int)*ip++;
+ hashv += hashv + (int)*ip++;
+ hashv += hashv + (int)*ip++;
+ hashv %= ARES_CACSIZE;
+ return (hashv);
+}
+
+static int hash_name(name)
+register char *name;
+{
+ Reg1 u_int hashv = 0;
+
+ if (name == NULL) {
+ sendto_realops ("Caught NULL pointer in hash_name(). (Bad thing -- tell rwg.)");
+ return (0);
+ }
+
+ for (; *name && *name != '.'; name++)
+ hashv += *name;
+ hashv %= ARES_CACSIZE;
+ return (hashv);
+}
+
+/*
+** Add a new cache item to the queue and hash table.
+*/
+static aCache *add_to_cache(ocp)
+Reg1 aCache *ocp;
+{
+ Reg1 aCache *cp = NULL;
+ Reg2 int hashv;
+
+#ifdef DEBUG
+ Debug((DEBUG_INFO,
+ "add_to_cache:ocp %#x he %#x name %#x addrl %#x 0 %#x",
+ ocp, &ocp->he, ocp->he.h_name, ocp->he.h_addr_list,
+ ocp->he.h_addr_list[0]));
+#endif
+ ocp->list_next = cachetop;
+ cachetop = ocp;
+
+#ifndef _WIN32
+ hashv = hash_name(ocp->he.h_name);
+#else
+ hashv = hash_name(ocp->he->h_name);
+#endif
+ ocp->hname_next = hashtable[hashv].name_list;
+ hashtable[hashv].name_list = ocp;
+
+#ifndef _WIN32
+ hashv = hash_number((u_char *)ocp->he.h_addr);
+#else
+ hashv = hash_number((u_char *)ocp->he->h_addr);
+#endif
+ ocp->hnum_next = hashtable[hashv].num_list;
+ hashtable[hashv].num_list = ocp;
+
+#ifdef DEBUG
+ Debug((DEBUG_INFO, "add_to_cache:added %s[%08x] cache %#x.",
+# ifndef _WIN32
+ ocp->he.h_name, ocp->he.h_addr_list[0], ocp));
+# else
+ ocp->he->h_name, ocp->he->h_addr_list[0], ocp));
+# endif
+ Debug((DEBUG_INFO,
+ "add_to_cache:h1 %d h2 %x lnext %#x namnext %#x numnext %#x",
+# ifndef _WIN32
+ hash_name(ocp->he.h_name), hashv, ocp->list_next,
+# else
+ hash_name(ocp->he->h_name), hashv, ocp->list_next,
+# endif
+ ocp->hname_next, ocp->hnum_next));
+#endif
+
+ /*
+ * LRU deletion of excessive cache entries.
+ */
+ if (++incache > MAXCACHED)
+ {
+ for (cp = cachetop; cp->list_next; cp = cp->list_next)
+ ;
+ rem_cache(cp);
+ }
+ cainfo.ca_adds++;
+
+ return ocp;
+}
+
+/*
+** update_list does not alter the cache structure passed. It is assumed that
+** it already contains the correct expire time, if it is a new entry. Old
+** entries have the expirey time updated.
+*/
+static void update_list(rptr, cachep)
+ResRQ *rptr;
+aCache *cachep;
+{
+ Reg1 aCache **cpp, *cp = cachep;
+ Reg2 char *s, *t, **base;
+ Reg3 int i, j;
+ int addrcount;
+
+ /*
+ ** search for the new cache item in the cache list by hostname.
+ ** If found, move the entry to the top of the list and return.
+ */
+ cainfo.ca_updates++;
+
+ for (cpp = &cachetop; *cpp; cpp = &((*cpp)->list_next))
+ if (cp == *cpp)
+ break;
+ if (!*cpp)
+ return;
+ *cpp = cp->list_next;
+ cp->list_next = cachetop;
+ cachetop = cp;
+#ifndef _WIN32
+ if (!rptr)
+ return;
+
+#ifdef DEBUG
+ Debug((DEBUG_DEBUG,"u_l:cp %#x na %#x al %#x ad %#x",
+ cp,cp->he.h_name,cp->he.h_aliases,cp->he.h_addr));
+ Debug((DEBUG_DEBUG,"u_l:rptr %#x h_n %#x", rptr, rptr->he.h_name));
+#endif
+ /*
+ * Compare the cache entry against the new record. Add any
+ * previously missing names for this entry.
+ */
+ for (i = 0; cp->he.h_aliases[i]; i++)
+ ;
+ addrcount = i;
+ for (i = 0, s = rptr->he.h_name; s && i < MAXALIASES;
+ s = rptr->he.h_aliases[i++])
+ {
+ for (j = 0, t = cp->he.h_name; t && j < MAXALIASES;
+ t = cp->he.h_aliases[j++])
+ if (!mycmp(t, s))
+ break;
+ if (!t && j < MAXALIASES-1)
+ {
+ base = cp->he.h_aliases;
+
+ addrcount++;
+ base = (char **)MyRealloc((char *)base,
+ sizeof(char *) * (addrcount + 1));
+ cp->he.h_aliases = base;
+#ifdef DEBUG
+ Debug((DEBUG_DNS,"u_l:add name %s hal %x ac %d",
+ s, cp->he.h_aliases, addrcount));
+#endif
+ base[addrcount-1] = s;
+ base[addrcount] = NULL;
+ if (i)
+ rptr->he.h_aliases[i-1] = NULL;
+ else
+ rptr->he.h_name = NULL;
+ }
+ }
+ for (i = 0; cp->he.h_addr_list[i]; i++)
+ ;
+ addrcount = i;
+
+ /*
+ * Do the same again for IP#'s.
+ */
+ for (s = (char *)&rptr->he.h_addr.s_addr;
+ ((struct in_addr *)s)->s_addr; s += sizeof(struct in_addr))
+ {
+ for (i = 0; (t = cp->he.h_addr_list[i]); i++)
+ if (!bcmp(s, t, sizeof(struct in_addr)))
+ break;
+ if (i >= MAXADDRS || addrcount >= MAXADDRS)
+ break;
+ /*
+ * Oh man this is bad...I *HATE* it. -avalon
+ *
+ * Whats it do ? Reallocate two arrays, one of pointers
+ * to "char *" and the other of IP addresses. Contents of
+ * the IP array *MUST* be preserved and the pointers into
+ * it recalculated.
+ */
+ if (!t)
+ {
+ base = cp->he.h_addr_list;
+ addrcount++;
+ t = (char *)MyRealloc(*base,
+ addrcount * sizeof(struct in_addr));
+ base = (char **)MyRealloc((char *)base,
+ (addrcount + 1) * sizeof(char *));
+ cp->he.h_addr_list = base;
+#ifdef DEBUG
+ Debug((DEBUG_DNS,"u_l:add IP %x hal %x ac %d",
+ ntohl(((struct in_addr *)s)->s_addr),
+ cp->he.h_addr_list,
+ addrcount));
+#endif
+ for (; addrcount; addrcount--)
+ {
+ *base++ = t;
+ t += sizeof(struct in_addr);
+ }
+ *base = NULL;
+ bcopy(s, *--base, sizeof(struct in_addr));
+ }
+ }
+#endif /*_WIN32*/
+ return;
+}
+
+static aCache *find_cache_name(name)
+char *name;
+{
+ Reg1 aCache *cp;
+ Reg2 char *s;
+ Reg3 int hashv, i;
+
+ hashv = hash_name(name);
+
+ cp = hashtable[hashv].name_list;
+#ifdef DEBUG
+ Debug((DEBUG_DNS,"find_cache_name:find %s : hashv = %d",name,hashv));
+#endif
+
+ for (; cp; cp = cp->hname_next)
+#ifndef _WIN32
+ for (i = 0, s = cp->he.h_name; s; s = cp->he.h_aliases[i++])
+#else
+ for (i = 0, s = cp->he->h_name; s; s = cp->he->h_aliases[i++])
+#endif
+ if (mycmp(s, name) == 0)
+ {
+ cainfo.ca_na_hits++;
+ update_list(NULL, cp);
+ return cp;
+ }
+
+ for (cp = cachetop; cp; cp = cp->list_next)
+ {
+ /*
+ * if no aliases or the hash value matches, we've already
+ * done this entry and all possiblilities concerning it.
+ */
+#ifndef _WIN32
+ if (!*cp->he.h_aliases)
+ continue;
+ if (hashv == hash_name(cp->he.h_name))
+ continue;
+ for (i = 0, s = cp->he.h_aliases[i]; s && i < MAXALIASES; i++)
+ if (!mycmp(name, s)) {
+#else
+ if (!cp->he->h_aliases)
+ continue;
+ if (hashv == hash_name(cp->he->h_name))
+ continue;
+ for (i = 0, s = cp->he->h_aliases[i]; s && i < MAXALIASES; i++)
+ if (!mycmp(name, s)) {
+#endif
+ cainfo.ca_na_hits++;
+ update_list(NULL, cp);
+ return cp;
+ }
+ }
+ return NULL;
+}
+
+/*
+ * find a cache entry by ip# and update its expire time
+ */
+static aCache *find_cache_number(rptr, numb)
+ResRQ *rptr;
+char *numb;
+{
+ Reg1 aCache *cp;
+ Reg2 int hashv,i;
+#ifdef DEBUG
+ struct in_addr *ip = (struct in_addr *)numb;
+#endif
+
+ hashv = hash_number((u_char *)numb);
+
+ cp = hashtable[hashv].num_list;
+#ifdef DEBUG
+ Debug((DEBUG_DNS,"find_cache_number:find %s[%08x]: hashv = %d",
+ inetntoa(numb), ntohl(ip->s_addr), hashv));
+#endif
+
+ for (; cp; cp = cp->hnum_next)
+#ifndef _WIN32
+ for (i = 0; cp->he.h_addr_list[i]; i++)
+ if (!bcmp(cp->he.h_addr_list[i], numb,
+ sizeof(struct in_addr)))
+#else
+ for (i = 0; cp->he->h_addr_list && cp->he->h_addr_list[i]; i++)
+ if (!bcmp(cp->he->h_addr_list[i], numb,
+ sizeof(struct in_addr)))
+#endif
+ {
+ cainfo.ca_nu_hits++;
+ update_list(rptr, cp);
+ return cp;
+ }
+
+ for (cp = cachetop; cp; cp = cp->list_next)
+ {
+ /*
+ * single address entry...would have been done by hashed
+ * search above...
+ */
+#ifndef _WIN32
+ if (!cp->he.h_addr_list[1])
+#else
+ if (!cp->he->h_addr_list[1])
+#endif
+ continue;
+ /*
+ * if the first IP# has the same hashnumber as the IP# we
+ * are looking for, its been done already.
+ */
+#ifndef _WIN32
+ if (hashv == hash_number((u_char *)cp->he.h_addr_list[0]))
+ continue;
+ for (i = 1; cp->he.h_addr_list[i]; i++)
+ if (!bcmp(cp->he.h_addr_list[i], numb,
+ sizeof(struct in_addr)))
+#else
+ if (hashv == hash_number((u_char *)cp->he->h_addr_list[0]))
+ continue;
+ for (i = 1; cp->he->h_addr_list && cp->he->h_addr_list[i]; i++)
+ if (!bcmp(cp->he->h_addr_list[i], numb,
+ sizeof(struct in_addr)))
+#endif
+ {
+ cainfo.ca_nu_hits++;
+ update_list(rptr, cp);
+ return cp;
+ }
+ }
+ return NULL;
+}
+
+static aCache *make_cache(rptr)
+ResRQ *rptr;
+{
+ Reg1 aCache *cp;
+ Reg2 int i, n;
+ Reg3 struct hostent *hp;
+ Reg3 char *s, **t;
+
+ /*
+ ** shouldn't happen but it just might...
+ */
+#ifndef _WIN32
+ if (!rptr->he.h_name || !rptr->he.h_addr.s_addr)
+#else
+ if (!rptr->he->h_name || !((struct in_addr *)rptr->he->h_addr)->s_addr)
+#endif
+ return NULL;
+ /*
+ ** Make cache entry. First check to see if the cache already exists
+ ** and if so, return a pointer to it.
+ */
+#ifndef _WIN32
+ if ((cp = find_cache_number(rptr, (char *)&rptr->he.h_addr.s_addr)))
+ return cp;
+ for (i = 1; rptr->he.h_addr_list[i].s_addr; i++)
+ if ((cp = find_cache_number(rptr,
+ (char *)&(rptr->he.h_addr_list[i].s_addr))))
+#else
+ if ((cp = find_cache_number(rptr, (char *)&((struct in_addr *)rptr->he->h_addr)->s_addr)))
+ return cp;
+ for (i = 1; rptr->he->h_addr_list[i] &&
+ ((struct in_addr *)rptr->he->h_addr_list[i])->s_addr; i++)
+ if ((cp = find_cache_number(rptr,
+ (char *)&((struct in_addr *)rptr->he->h_addr_list[i])->s_addr )))
+#endif
+ return cp;
+
+ /*
+ ** a matching entry wasnt found in the cache so go and make one up.
+ */
+ cp = (aCache *)MyMalloc(sizeof(aCache));
+ bzero((char *)cp, sizeof(aCache));
+#ifdef _WIN32
+ cp->he = (struct hostent *)MyMalloc(MAXGETHOSTSTRUCT);
+ res_copyhostent(rptr->he, cp->he);
+#else
+ hp = &cp->he;
+ for (i = 0; i < MAXADDRS; i++)
+ if (!rptr->he.h_addr_list[i].s_addr)
+ break;
+
+ /*
+ ** build two arrays, one for IP#'s, another of pointers to them.
+ */
+ t = hp->h_addr_list = (char **)MyMalloc(sizeof(char *) * (i+1));
+ bzero((char *)t, sizeof(char *) * (i+1));
+
+ s = (char *)MyMalloc(sizeof(struct in_addr) * i);
+ bzero(s, sizeof(struct in_addr) * i);
+
+ for (n = 0; n < i; n++, s += sizeof(struct in_addr))
+ {
+ *t++ = s;
+ bcopy((char *)&(rptr->he.h_addr_list[n].s_addr), s,
+ sizeof(struct in_addr));
+ }
+ *t = (char *)NULL;
+
+ /*
+ ** an array of pointers to CNAMEs.
+ */
+ for (i = 0; i < MAXALIASES; i++)
+ if (!rptr->he.h_aliases[i])
+ break;
+ i++;
+ t = hp->h_aliases = (char **)MyMalloc(sizeof(char *) * i);
+ for (n = 0; n < i; n++, t++)
+ {
+ *t = rptr->he.h_aliases[n];
+ rptr->he.h_aliases[n] = NULL;
+ }
+
+ hp->h_addrtype = rptr->he.h_addrtype;
+ hp->h_length = rptr->he.h_length;
+ hp->h_name = rptr->he.h_name;
+#endif
+ if (rptr->ttl < 600)
+ {
+ reinfo.re_shortttl++;
+ cp->ttl = 600;
+ }
+ else
+ cp->ttl = rptr->ttl;
+ cp->expireat = TStime() + cp->ttl;
+#ifndef _WIN32
+ rptr->he.h_name = NULL;
+#else
+ rptr->he->h_name = NULL;
+#endif
+#ifdef DEBUG
+ Debug((DEBUG_INFO,"make_cache:made cache %#x", cp));
+#endif
+ return add_to_cache(cp);
+}
+
+/*
+ * rem_cache
+ * delete a cache entry from the cache structures and lists and return
+ * all memory used for the cache back to the memory pool.
+ */
+static void rem_cache(ocp)
+aCache *ocp;
+{
+ Reg1 aCache **cp;
+#ifndef _WIN32
+ Reg2 struct hostent *hp = &ocp->he;
+#else
+ Reg2 struct hostent *hp = ocp->he;
+#endif
+ Reg3 int hashv;
+ Reg4 aClient *cptr;
+
+#ifdef DEBUG
+ Debug((DEBUG_DNS, "rem_cache: ocp %#x hp %#x l_n %#x aliases %#x",
+ ocp, hp, ocp->list_next, hp->h_aliases));
+#endif
+ /*
+ ** Cleanup any references to this structure by destroying the
+ ** pointer.
+ */
+ for (hashv = highest_fd; hashv >= 0; hashv--)
+ if ((cptr = local[hashv]) && (cptr->hostp == hp))
+ cptr->hostp = NULL;
+ /*
+ * remove cache entry from linked list
+ */
+ for (cp = &cachetop; *cp; cp = &((*cp)->list_next))
+ if (*cp == ocp)
+ {
+ *cp = ocp->list_next;
+ break;
+ }
+ /*
+ * remove cache entry from hashed name lists
+ */
+ hashv = hash_name(hp->h_name);
+#ifdef DEBUG
+ Debug((DEBUG_DEBUG,"rem_cache: h_name %s hashv %d next %#x first %#x",
+ hp->h_name, hashv, ocp->hname_next,
+ hashtable[hashv].name_list));
+#endif
+ for (cp = &hashtable[hashv].name_list; *cp; cp = &((*cp)->hname_next))
+ if (*cp == ocp)
+ {
+ *cp = ocp->hname_next;
+ break;
+ }
+ /*
+ * remove cache entry from hashed number list
+ */
+ hashv = hash_number((u_char *)hp->h_addr);
+#ifdef DEBUG
+ Debug((DEBUG_DEBUG,"rem_cache: h_addr %s hashv %d next %#x first %#x",
+ inetntoa(hp->h_addr), hashv, ocp->hnum_next,
+ hashtable[hashv].num_list));
+#endif
+ for (cp = &hashtable[hashv].num_list; *cp; cp = &((*cp)->hnum_next))
+ if (*cp == ocp)
+ {
+ *cp = ocp->hnum_next;
+ break;
+ }
+
+#ifdef _WIN32
+ MyFree((char *)hp);
+#else
+ /*
+ * free memory used to hold the various host names and the array
+ * of alias pointers.
+ */
+ if (hp->h_name)
+ MyFree(hp->h_name);
+ if (hp->h_aliases)
+ {
+ for (hashv = 0; hp->h_aliases[hashv]; hashv++)
+ MyFree(hp->h_aliases[hashv]);
+ MyFree((char *)hp->h_aliases);
+ }
+
+ /*
+ * free memory used to hold ip numbers and the array of them.
+ */
+ if (hp->h_addr_list)
+ {
+ if (*hp->h_addr_list)
+ MyFree((char *)*hp->h_addr_list);
+ MyFree((char *)hp->h_addr_list);
+ }
+#endif /*_WIN32*/
+ MyFree((char *)ocp);
+
+ incache--;
+ cainfo.ca_dels++;
+
+ return;
+}
+
+/*
+ * removes entries from the cache which are older than their expirey times.
+ * returns the time at which the server should next poll the cache.
+ */
+time_t expire_cache(now)
+time_t now;
+{
+ Reg1 aCache *cp, *cp2;
+ Reg2 time_t next = 0;
+
+ for (cp = cachetop; cp; cp = cp2)
+ {
+ cp2 = cp->list_next;
+
+ if (now >= cp->expireat)
+ {
+ cainfo.ca_expires++;
+ rem_cache(cp);
+ }
+ else if (!next || next > cp->expireat)
+ next = cp->expireat;
+ }
+ return (next > now) ? next : (now + AR_TTL);
+}
+
+/*
+ * remove all dns cache entries.
+ */
+void flush_cache()
+{
+ Reg1 aCache *cp;
+
+ while ((cp = cachetop))
+ rem_cache(cp);
+}
+
+int m_dns(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ Reg1 aCache *cp;
+ Reg2 int i;
+
+ if (parv[1] && *parv[1] == 'l') {
+ for(cp = cachetop; cp; cp = cp->list_next)
+ {
+ sendto_one(sptr, "NOTICE %s :Ex %d ttl %d host %s(%s)",
+ parv[0], cp->expireat - TStime(), cp->ttl,
+#ifndef _WIN32
+ cp->he.h_name, inetntoa(cp->he.h_addr));
+ for (i = 0; cp->he.h_aliases[i]; i++)
+ sendto_one(sptr,"NOTICE %s : %s = %s (CN)",
+ parv[0], cp->he.h_name,
+ cp->he.h_aliases[i]);
+ for (i = 1; cp->he.h_addr_list[i]; i++)
+ sendto_one(sptr,"NOTICE %s : %s = %s (IP)",
+ parv[0], cp->he.h_name,
+ inetntoa(cp->he.h_addr_list[i]));
+#else
+ cp->he->h_name, inetntoa(cp->he->h_addr));
+ for (i = 0; cp->he->h_aliases[i]; i++)
+ sendto_one(sptr,"NOTICE %s : %s = %s (CN)",
+ parv[0], cp->he->h_name,
+ cp->he->h_aliases[i]);
+ for (i = 1; cp->he->h_addr_list[i]; i++)
+ sendto_one(sptr,"NOTICE %s : %s = %s (IP)",
+ parv[0], cp->he->h_name,
+ inetntoa(cp->he->h_addr_list[i]));
+#endif
+ }
+ return 0;
+ }
+ sendto_one(sptr,"NOTICE %s :Ca %d Cd %d Ce %d Cl %d Ch %d:%d Cu %d",
+ sptr->name,
+ cainfo.ca_adds, cainfo.ca_dels, cainfo.ca_expires,
+ cainfo.ca_lookups,
+ cainfo.ca_na_hits, cainfo.ca_nu_hits, cainfo.ca_updates);
+
+ sendto_one(sptr,"NOTICE %s :Re %d Rl %d/%d Rp %d Rq %d",
+ sptr->name, reinfo.re_errors, reinfo.re_nu_look,
+ reinfo.re_na_look, reinfo.re_replies, reinfo.re_requests);
+ sendto_one(sptr,"NOTICE %s :Ru %d Rsh %d Rs %d(%d) Rt %d", sptr->name,
+ reinfo.re_unkrep, reinfo.re_shortttl, reinfo.re_sent,
+ reinfo.re_resends, reinfo.re_timeouts);
+ return 0;
+}
+
+u_long cres_mem(sptr)
+aClient *sptr;
+{
+ register aCache *c = cachetop;
+ register struct hostent *h;
+ register int i;
+ u_long nm = 0, im = 0, sm = 0, ts = 0;
+
+ for ( ;c ; c = c->list_next)
+ {
+ sm += sizeof(*c);
+#ifndef _WIN32
+ h = &c->he;
+#else
+ h = c->he;
+#endif
+ for (i = 0; h->h_addr_list[i]; i++)
+ {
+ im += sizeof(char *);
+ im += sizeof(struct in_addr);
+ }
+ im += sizeof(char *);
+ for (i = 0; h->h_aliases[i]; i++)
+ {
+ nm += sizeof(char *);
+ nm += strlen(h->h_aliases[i]);
+ }
+ nm += i - 1;
+ nm += sizeof(char *);
+ if (h->h_name)
+ nm += strlen(h->h_name);
+ }
+ ts = ARES_CACSIZE * sizeof(CacheTable);
+ sendto_one(sptr, ":%s %d %s :RES table %d",
+ me.name, RPL_STATSDEBUG, sptr->name, ts);
+ sendto_one(sptr, ":%s %d %s :Structs %d IP storage %d Name storage %d",
+ me.name, RPL_STATSDEBUG, sptr->name, sm, im, nm);
+ return ts + sm + im + nm;
+}
+
+#ifdef _WIN32
+/*
+ * Main thread function for handling DNS requests.
+ */
+void async_dns(void *parm)
+{
+ ResRQ *rptr = (ResRQ *)parm;
+ struct hostent *hp, *he = rptr->he;
+ int i, x;
+ long amt;
+
+ if (rptr->type == T_A)
+ {
+ rptr->locked = 2;
+ hp = gethostbyname(rptr->name);
+ }
+ else
+ {
+ rptr->locked = 1;
+ hp = gethostbyaddr((char *)(&rptr->addr.s_addr), 4, PF_INET);
+ }
+ if ( !hp )
+ {
+ /*
+ * Now heres a stupid check to forget, this apprently is
+ * what hasbeen causing most of the crashes. I hope anyway.
+ */
+ do_dns_async(rptr->id);
+ _endthread();
+ }
+ if ( (hp->h_aliases[0] && (hp->h_aliases[0]-(char *)hp)>MAXGETHOSTSTRUCT) ||
+ (hp->h_addr_list[0] && (hp->h_addr_list[0]-(char *)hp)>MAXGETHOSTSTRUCT))
+ {
+ /*
+ * Seems windows does some weird, aka stupid, stuff with DNS.
+ * If the address is resolved from the HOSTS file, then the
+ * pointers will exceed MAXGETHOSTSTRUCT. Good and bad. Good
+ * because its an easy way to tell if the Admin is spoofing
+ * with his HOSTS file, bad because it also causes invalid
+ * pointers without this check. -Cabal95
+ */
+ do_dns_async(rptr->id);
+ _endthread();
+ }
+
+ res_copyhostent(hp, rptr->he);
+ do_dns_async(rptr->id);
+ _endthread();
+}
+
+int res_copyhostent(struct hostent *from, struct hostent *to)
+{
+ int amt, x, i;
+
+ to->h_addrtype = from->h_addrtype;
+ to->h_length = from->h_length;
+ /*
+ * Get to "primary" offset in to hostent buffer and copy over
+ * to hostname.
+ */
+ amt = (long)to + sizeof(struct hostent);
+ to->h_name = (char *)amt;
+ strcpy(to->h_name, from->h_name);
+ amt += strlen(to->h_name)+1;
+ /* Setup tto alias list */
+ if (amt&0x3)
+ amt = (amt&0xFFFFFFFC)+4;
+ to->h_aliases = (char **)amt;
+ for (x = 0; from->h_aliases[x]; x++)
+ ;
+ x *= sizeof(char *);
+ amt += sizeof(char *);
+ for (i = 0; from->h_aliases[i]; i++)
+ {
+ to->h_aliases[i] = (char *)(amt+x);
+ strcpy(to->h_aliases[i], from->h_aliases[i]);
+ amt += strlen(to->h_aliases[i])+1;
+ if (amt&0x3)
+ amt = (amt&0xFFFFFFFC)+4;
+ }
+ to->h_aliases[i] = NULL;
+ /* Setup tto IP address list */
+ to->h_addr_list = (char **)amt;
+ for (x = 0; from->h_addr_list[x]; x++)
+ ;
+ x *= sizeof(char *);
+ for (i = 0; from->h_addr_list[i]; i++)
+ {
+ amt += 4;
+ to->h_addr_list[i] = (char *)(amt+x);
+ ((struct in_addr *)to->h_addr_list[i])->s_addr = ((struct in_addr *)from->h_addr_list[i])->s_addr;
+ }
+ to->h_addr_list[i] = NULL;
+}
+#endif /*_WIN32*/
--- /dev/null
+/*
+ * Copyright (c) 1985 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted provided
+ * that: (1) source distributions retain this entire copyright notice and
+ * comment, and (2) distributions including binaries display the following
+ * acknowledgement: ``This product includes software developed by the
+ * University of California, Berkeley and its contributors'' in the
+ * documentation or other materials provided with the distribution and in
+ * all advertising materials mentioning features or use of this software.
+ * Neither the name of the University nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_comp.c 6.18 (Berkeley) 6/27/90";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include "common.h"
+#include "sys.h"
+#include "nameser.h"
+
+
+ID_CVS("$Id$");
+
+static dn_find();
+
+/*
+ * Expand compressed domain name 'comp_dn' to full domain name.
+ * 'msg' is a pointer to the begining of the message,
+ * 'eomorig' points to the first location after the message,
+ * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
+ * Return size of compressed name or -1 if there was an error.
+ */
+dn_expand(msg, eomorig, comp_dn, exp_dn, length)
+ u_char *msg, *eomorig, *comp_dn, *exp_dn;
+ int length;
+{
+ register u_char *cp, *dn;
+ register int n, c;
+ u_char *eom;
+ int len = -1, checked = 0;
+
+ dn = exp_dn;
+ cp = comp_dn;
+ eom = exp_dn + length;
+ /*
+ * fetch next label in domain name
+ */
+ while (n = *cp++) {
+ /*
+ * Check for indirection
+ */
+ switch (n & INDIR_MASK) {
+ case 0:
+ if (dn != exp_dn) {
+ if (dn >= eom)
+ return (-1);
+ *dn++ = '.';
+ }
+ if (dn+n >= eom)
+ return (-1);
+ checked += n + 1;
+ while (--n >= 0) {
+ if ((c = *cp++) == '.') {
+ if (dn + n + 2 >= eom)
+ return (-1);
+ *dn++ = '\\';
+ }
+ *dn++ = c;
+ if (cp >= eomorig) /* out of range */
+ return(-1);
+ }
+ break;
+
+ case INDIR_MASK:
+ if (len < 0)
+ len = cp - comp_dn + 1;
+ cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
+ if (cp < msg || cp >= eomorig) /* out of range */
+ return(-1);
+ checked += 2;
+ /*
+ * Check for loops in the compressed name;
+ * if we've looked at the whole message,
+ * there must be a loop.
+ */
+ if (checked >= eomorig - msg)
+ return (-1);
+ break;
+
+ default:
+ return (-1); /* flag error */
+ }
+ }
+ *dn = '\0';
+ if (len < 0)
+ len = cp - comp_dn;
+ return (len);
+}
+
+/*
+ * Compress domain name 'exp_dn' into 'comp_dn'.
+ * Return the size of the compressed name or -1.
+ * 'length' is the size of the array pointed to by 'comp_dn'.
+ * 'dnptrs' is a list of pointers to previous compressed names. dnptrs[0]
+ * is a pointer to the beginning of the message. The list ends with NULL.
+ * 'lastdnptr' is a pointer to the end of the arrary pointed to
+ * by 'dnptrs'. Side effect is to update the list of pointers for
+ * labels inserted into the message as we compress the name.
+ * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
+ * is NULL, we don't update the list.
+ */
+dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
+ u_char *exp_dn, *comp_dn;
+ int length;
+ u_char **dnptrs, **lastdnptr;
+{
+ register u_char *cp, *dn;
+ register int c, l;
+ u_char **cpp, **lpp, *sp, *eob;
+ u_char *msg;
+
+ dn = exp_dn;
+ cp = comp_dn;
+ eob = cp + length;
+ if (dnptrs != NULL) {
+ if ((msg = *dnptrs++) != NULL) {
+ for (cpp = dnptrs; *cpp != NULL; cpp++)
+ ;
+ lpp = cpp; /* end of list to search */
+ }
+ } else
+ msg = NULL;
+ for (c = *dn++; c != '\0'; ) {
+ /* look to see if we can use pointers */
+ if (msg != NULL) {
+ if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) {
+ if (cp+1 >= eob)
+ return (-1);
+ *cp++ = (l >> 8) | INDIR_MASK;
+ *cp++ = l % 256;
+ return (cp - comp_dn);
+ }
+ /* not found, save it */
+ if (lastdnptr != NULL && cpp < lastdnptr-1) {
+ *cpp++ = cp;
+ *cpp = NULL;
+ }
+ }
+ sp = cp++; /* save ptr to length byte */
+ do {
+ if (c == '.') {
+ c = *dn++;
+ break;
+ }
+ if (c == '\\') {
+ if ((c = *dn++) == '\0')
+ break;
+ }
+ if (cp >= eob) {
+ if (msg != NULL)
+ *lpp = NULL;
+ return (-1);
+ }
+ *cp++ = c;
+ } while ((c = *dn++) != '\0');
+ /* catch trailing '.'s but not '..' */
+ if ((l = cp - sp - 1) == 0 && c == '\0') {
+ cp--;
+ break;
+ }
+ if (l <= 0 || l > MAXLABEL) {
+ if (msg != NULL)
+ *lpp = NULL;
+ return (-1);
+ }
+ *sp = l;
+ }
+ if (cp >= eob) {
+ if (msg != NULL)
+ *lpp = NULL;
+ return (-1);
+ }
+ *cp++ = '\0';
+ return (cp - comp_dn);
+}
+
+/*
+ * Skip over a compressed domain name. Return the size or -1.
+ */
+dn_skipname(comp_dn, eom)
+ u_char *comp_dn, *eom;
+{
+ register u_char *cp;
+ register int n;
+
+ cp = comp_dn;
+ while (cp < eom && (n = *cp++)) {
+ /*
+ * check for indirection
+ */
+ switch (n & INDIR_MASK) {
+ case 0: /* normal case, n == len */
+ cp += n;
+ continue;
+ default: /* illegal type */
+ return (-1);
+ case INDIR_MASK: /* indirection */
+ cp++;
+ }
+ break;
+ }
+ return (cp - comp_dn);
+}
+
+/*
+ * Search for expanded name from a list of previously compressed names.
+ * Return the offset from msg if found or -1.
+ * dnptrs is the pointer to the first name on the list,
+ * not the pointer to the start of the message.
+ */
+static
+dn_find(exp_dn, msg, dnptrs, lastdnptr)
+ u_char *exp_dn, *msg;
+ u_char **dnptrs, **lastdnptr;
+{
+ register u_char *dn, *cp, **cpp;
+ register int n;
+ u_char *sp;
+
+ for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
+ dn = exp_dn;
+ sp = cp = *cpp;
+ while (n = *cp++) {
+ /*
+ * check for indirection
+ */
+ switch (n & INDIR_MASK) {
+ case 0: /* normal case, n == len */
+ while (--n >= 0) {
+ if (*dn == '.')
+ goto next;
+ if (*dn == '\\')
+ dn++;
+ if (*dn++ != *cp++)
+ goto next;
+ }
+ if ((n = *dn++) == '\0' && *cp == '\0')
+ return (sp - msg);
+ if (n == '.')
+ continue;
+ goto next;
+
+ default: /* illegal type */
+ return (-1);
+
+ case INDIR_MASK: /* indirection */
+ cp = msg + (((n & 0x3f) << 8) | *cp);
+ }
+ }
+ if (*dn == '\0')
+ return (sp - msg);
+ next: ;
+ }
+ return (-1);
+}
+
+/*
+ * Routines to insert/extract short/long's. Must account for byte
+ * order and non-alignment problems. This code at least has the
+ * advantage of being portable.
+ *
+ * used by sendmail.
+ */
+
+u_short
+_getshort(msgp)
+ u_char *msgp;
+{
+ register u_char *p = (u_char *) msgp;
+#ifdef vax
+ /*
+ * vax compiler doesn't put shorts in registers
+ */
+ register u_long u;
+#else
+ register u_short u;
+#endif
+
+ u = *p++ << 8;
+ return ((u_short)(u | *p));
+}
+
+u_long
+_getlong(msgp)
+ u_char *msgp;
+{
+ register u_char *p = (u_char *) msgp;
+ register u_long u;
+
+ u = *p++; u <<= 8;
+ u |= *p++; u <<= 8;
+ u |= *p++; u <<= 8;
+ return (u | *p);
+}
+
+
+putshort(s, msgp)
+ register u_short s;
+ register u_char *msgp;
+{
+
+ msgp[1] = s;
+ msgp[0] = s >> 8;
+}
+
+putlong(l, msgp)
+ register u_long l;
+ register u_char *msgp;
+{
+
+ msgp[3] = l;
+ msgp[2] = (l >>= 8);
+ msgp[1] = (l >>= 8);
+ msgp[0] = l >> 8;
+}
--- /dev/null
+/*-
+ * Copyright (c) 1985, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted provided
+ * that: (1) source distributions retain this entire copyright notice and
+ * comment, and (2) distributions including binaries display the following
+ * acknowledgement: ``This product includes software developed by the
+ * University of California, Berkeley and its contributors'' in the
+ * documentation or other materials provided with the distribution and in
+ * all advertising materials mentioning features or use of this software.
+ * Neither the name of the University nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_init.c 6.14.1 (Berkeley) 6/27/90";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#ifndef _WIN32
+#include <sys/socket.h>
+#include <netinet/in.h>
+#endif
+#include <stdio.h>
+#include "config.h" /* To get #define SOL20 Vesa */
+#include "sys.h"
+#include "common.h"
+#include "nameser.h"
+#include "resolv.h"
+
+ID_CVS("$Id$");
+/*
+ * Resolver state default settings
+ */
+
+struct state _res = {
+ RES_TIMEOUT, /* retransmition time interval */
+ 4, /* number of times to retransmit */
+ RES_DEFAULT, /* options flags */
+ 1, /* number of name servers */
+};
+
+/*
+ * Set up default settings. If the configuration file exist, the values
+ * there will have precedence. Otherwise, the server address is set to
+ * INADDR_ANY and the default domain name comes from the gethostname().
+ *
+ * The configuration file should only be used if you want to redefine your
+ * domain or run without a server on your machine.
+ *
+ * Return 0 if completes successfully, -1 on error
+ */
+res_init()
+{
+#ifndef _WIN32
+ register FILE *fp;
+ register char *cp, *dp, **pp;
+ extern u_long inet_addr();
+#else
+ register char *cp, **pp;
+#endif
+ register int n;
+ char buf[BUFSIZ];
+ extern char *getenv();
+ int nserv = 0; /* number of nameserver records read from file */
+ int norder = 0;
+ int haveenv = 0;
+ int havesearch = 0;
+
+ _res.nsaddr.sin_addr.s_addr = INADDR_ANY;
+ _res.nsaddr.sin_family = AF_INET;
+#ifdef TESTNET
+ _res.nsaddr.sin_port = htons(NAMESERVER_PORT + 10000);
+#else
+ _res.nsaddr.sin_port = htons(NAMESERVER_PORT);
+#endif
+ _res.nscount = 1;
+
+ /* Allow user to override the local domain definition */
+ if ((cp = getenv("LOCALDOMAIN")) != NULL) {
+ (void)strncpy(_res.defdname, cp, sizeof(_res.defdname));
+ haveenv++;
+ }
+
+#ifndef _WIN32
+ if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
+ /* read the config file */
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ /* read default domain name */
+ if (!strncmp(buf, "domain", sizeof("domain") - 1)) {
+ if (haveenv) /* skip if have from environ */
+ continue;
+ cp = buf + sizeof("domain") - 1;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if ((*cp == '\0') || (*cp == '\n'))
+ continue;
+ (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
+ if ((cp = index(_res.defdname, '\n')) != NULL)
+ *cp = '\0';
+ havesearch = 0;
+ continue;
+ }
+ /* set search list */
+ if (!strncmp(buf, "search", sizeof("search") - 1)) {
+ if (haveenv) /* skip if have from environ */
+ continue;
+ cp = buf + sizeof("search") - 1;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if ((*cp == '\0') || (*cp == '\n'))
+ continue;
+ (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
+ if ((cp = index(_res.defdname, '\n')) != NULL)
+ *cp = '\0';
+ /*
+ * Set search list to be blank-separated strings
+ * on rest of line.
+ */
+ cp = _res.defdname;
+ pp = _res.dnsrch;
+ *pp++ = cp;
+ for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
+ if (*cp == ' ' || *cp == '\t') {
+ *cp = 0;
+ n = 1;
+ } else if (n) {
+ *pp++ = cp;
+ n = 0;
+ }
+ }
+ /* null terminate last domain if there are excess */
+ while (*cp != '\0' && *cp != ' ' && *cp != '\t')
+ cp++;
+ *cp = '\0';
+ *pp++ = 0;
+ havesearch = 1;
+ continue;
+ }
+ /* read nameservers to query */
+ if (!strncmp(buf, "nameserver", sizeof("nameserver") - 1) &&
+ nserv < MAXNS) {
+ cp = buf + sizeof("nameserver") - 1;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if ((*cp == '\0') || (*cp == '\n'))
+ continue;
+ if ((_res.nsaddr_list[nserv].sin_addr.s_addr =
+ inet_addr(cp)) == (unsigned)-1) {
+ _res.nsaddr_list[nserv].sin_addr.s_addr
+ = INADDR_ANY;
+ continue;
+ }
+ _res.nsaddr_list[nserv].sin_family = AF_INET;
+#ifdef TESTNET
+ _res.nsaddr_list[nserv].sin_port = htons(NAMESERVER_PORT +
+ 10000);
+#else
+ _res.nsaddr_list[nserv].sin_port = htons(NAMESERVER_PORT);
+#endif
+ nserv++;
+ continue;
+ }
+ /* read service order */
+ if (!strncmp(buf, "order", sizeof("order") - 1)) {
+ cp = buf + sizeof("order") - 1;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if ((*cp == '\0') || (*cp == '\n'))
+ continue;
+ norder = 0;
+ do {
+ if ((dp = index(cp, ',')) != NULL)
+ *dp = '\0';
+ if (norder >= MAXSERVICES)
+ continue;
+ if (!strncmp(cp, "bind", sizeof("bind") - 1))
+ _res.order[norder++] = RES_SERVICE_BIND;
+ else if (!strncmp(cp, "local", sizeof("local") - 1))
+ _res.order[norder++] = RES_SERVICE_LOCAL;
+ cp = dp + 1;
+ } while (dp != NULL);
+ _res.order[norder] = RES_SERVICE_NONE;
+ continue;
+ }
+ }
+ if (nserv > 1)
+ _res.nscount = nserv;
+ (void) fclose(fp);
+ }
+#endif /*_WIN32*/
+ if (_res.defdname[0] == 0) {
+ if (gethostname(buf, sizeof(_res.defdname)) == 0 &&
+ (cp = index(buf, '.')))
+ (void)strcpy(_res.defdname, cp + 1);
+ }
+
+ /* find components of local domain that might be searched */
+ if (havesearch == 0) {
+ pp = _res.dnsrch;
+ *pp++ = _res.defdname;
+ for (cp = _res.defdname, n = 0; *cp; cp++)
+ if (*cp == '.')
+ n++;
+ cp = _res.defdname;
+ for (; n >= LOCALDOMAINPARTS && pp < _res.dnsrch + MAXDFLSRCH;
+ n--) {
+ cp = index(cp, '.');
+ *pp++ = ++cp;
+ }
+ *pp++ = 0;
+ }
+ /* default search order to bind only */
+ if (norder == 0) {
+ _res.order[0] = RES_SERVICE_BIND;
+ _res.order[1] = RES_SERVICE_NONE;
+ }
+ _res.options |= RES_INIT;
+ return (0);
+}
--- /dev/null
+/*
+ * Copyright (c) 1985 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement: ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_mkquery.c 6.12 (Berkeley) 6/1/90";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include "config.h"
+#include "sys.h"
+#include "nameser.h"
+#include "resolv.h"
+#include "common.h"
+
+ID_CVS("$Id$");
+
+/*
+ * Form all types of queries.
+ * Returns the size of the result or -1.
+ */
+res_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen)
+ int op; /* opcode of query */
+ char *dname; /* domain name */
+ int class, type; /* class and type of query */
+ char *data; /* resource record data */
+ int datalen; /* length of data */
+ struct rrec *newrr; /* new rr for modify or append */
+ char *buf; /* buffer to put query */
+ int buflen; /* size of buffer */
+{
+ register HEADER *hp;
+ register char *cp;
+ register int n;
+ char *dnptrs[10], **dpp, **lastdnptr;
+
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf("res_mkquery(%d, %s, %d, %d)\n", op, dname, class, type);
+#endif /*DEBUG*/
+ /*
+ * Initialize header fields.
+ */
+ if ((buf == NULL) || (buflen < sizeof(HEADER)))
+ return(-1);
+ bzero(buf, sizeof(HEADER));
+ hp = (HEADER *) buf;
+ hp->id = htons(++_res.id);
+ hp->opcode = op;
+ hp->pr = (_res.options & RES_PRIMARY) != 0;
+ hp->rd = (_res.options & RES_RECURSE) != 0;
+ hp->rcode = NOERROR;
+ cp = buf + sizeof(HEADER);
+ buflen -= sizeof(HEADER);
+ dpp = dnptrs;
+ *dpp++ = buf;
+ *dpp++ = NULL;
+ lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]);
+ /*
+ * perform opcode specific processing
+ */
+ switch (op) {
+ case QUERY:
+ if ((buflen -= QFIXEDSZ) < 0)
+ return(-1);
+ if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
+ return (-1);
+ cp += n;
+ buflen -= n;
+ putshort(type, cp);
+ cp += sizeof(u_short);
+ putshort(class, cp);
+ cp += sizeof(u_short);
+ hp->qdcount = htons(1);
+ if (op == QUERY || data == NULL)
+ break;
+ /*
+ * Make an additional record for completion domain.
+ */
+ buflen -= RRFIXEDSZ;
+ if ((n = dn_comp(data, cp, buflen, dnptrs, lastdnptr)) < 0)
+ return (-1);
+ cp += n;
+ buflen -= n;
+ putshort(T_NULL, cp);
+ cp += sizeof(u_short);
+ putshort(class, cp);
+ cp += sizeof(u_short);
+ putlong(0, cp);
+ cp += sizeof(u_long);
+ putshort(0, cp);
+ cp += sizeof(u_short);
+ hp->arcount = htons(1);
+ break;
+
+ case IQUERY:
+ /*
+ * Initialize answer section
+ */
+ if (buflen < 1 + RRFIXEDSZ + datalen)
+ return (-1);
+ *cp++ = '\0'; /* no domain name */
+ putshort(type, cp);
+ cp += sizeof(u_short);
+ putshort(class, cp);
+ cp += sizeof(u_short);
+ putlong(0, cp);
+ cp += sizeof(u_long);
+ putshort(datalen, cp);
+ cp += sizeof(u_short);
+ if (datalen) {
+ bcopy(data, cp, datalen);
+ cp += datalen;
+ }
+ hp->ancount = htons(1);
+ break;
+
+#ifdef ALLOW_UPDATES
+ /*
+ * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
+ * (Record to be modified is followed by its replacement in msg.)
+ */
+ case UPDATEM:
+ case UPDATEMA:
+
+ case UPDATED:
+ /*
+ * The res code for UPDATED and UPDATEDA is the same; user
+ * calls them differently: specifies data for UPDATED; server
+ * ignores data if specified for UPDATEDA.
+ */
+ case UPDATEDA:
+ buflen -= RRFIXEDSZ + datalen;
+ if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
+ return (-1);
+ cp += n;
+ putshort(type, cp);
+ cp += sizeof(u_short);
+ putshort(class, cp);
+ cp += sizeof(u_short);
+ putlong(0, cp);
+ cp += sizeof(u_long);
+ putshort(datalen, cp);
+ cp += sizeof(u_short);
+ if (datalen) {
+ bcopy(data, cp, datalen);
+ cp += datalen;
+ }
+ if ( (op == UPDATED) || (op == UPDATEDA) ) {
+ hp->ancount = htons(0);
+ break;
+ }
+ /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
+
+ case UPDATEA: /* Add new resource record */
+ buflen -= RRFIXEDSZ + datalen;
+ if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
+ return (-1);
+ cp += n;
+ putshort(newrr->r_type, cp);
+ cp += sizeof(u_short);
+ putshort(newrr->r_class, cp);
+ cp += sizeof(u_short);
+ putlong(0, cp);
+ cp += sizeof(u_long);
+ putshort(newrr->r_size, cp);
+ cp += sizeof(u_short);
+ if (newrr->r_size) {
+ bcopy(newrr->r_data, cp, newrr->r_size);
+ cp += newrr->r_size;
+ }
+ hp->ancount = htons(0);
+ break;
+
+#endif /* ALLOW_UPDATES */
+ }
+ return (cp - buf);
+}
--- /dev/null
+#include <sys/types.h>
+#include <stdio.h>
+#include "nameser.h"
+#include "common.h"
+
+ID_CVS("$Id$");
+/*
+ * Skip over a compressed domain name. Return the size or -1.
+ */
+dn_skipname(comp_dn, eom)
+ u_char *comp_dn, *eom;
+{
+ register u_char *cp;
+ register int n;
+
+ cp = comp_dn;
+ while (cp < eom && (n = *cp++)) {
+ /*
+ * check for indirection
+ */
+ switch (n & INDIR_MASK) {
+ case 0: /* normal case, n == len */
+ cp += n;
+ continue;
+ default: /* illegal type */
+ return (-1);
+ case INDIR_MASK: /* indirection */
+ cp++;
+ }
+ break;
+ }
+ return (cp - comp_dn);
+}
+
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, ircd/s_auth.c
+ * Copyright (C) 1992 Darren Reed
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)s_auth.c 1.18 4/18/94 (C) 1992 Darren Reed";
+#endif
+
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#include "res.h"
+#include "numeric.h"
+#include "version.h"
+#ifndef _WIN32
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#if defined(__hpux)
+# include "inet.h"
+#endif
+#else
+#include <io.h>
+#endif
+#include <fcntl.h>
+#include "sock.h" /* If FD_ZERO isn't define up to this point, */
+ /* define it (BSD4.2 needs this) */
+#include "h.h"
+
+ID_CVS("$Id$");
+/*
+ * start_auth
+ *
+ * Flag the client to show that an attempt to contact the ident server on
+ * the client's host. The connect and subsequently the socket are all put
+ * into 'non-blocking' mode. Should the connect or any later phase of the
+ * identifing process fail, it is aborted and the user is given a username
+ * of "unknown".
+ */
+void start_auth(cptr)
+Reg1 aClient *cptr;
+{
+ struct sockaddr_in sock;
+ int addrlen = sizeof(struct sockaddr_in);
+
+ Debug((DEBUG_NOTICE,"start_auth(%x) fd %d status %d",
+ cptr, cptr->fd, cptr->status));
+ if ((cptr->authfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+ {
+#ifdef USE_SYSLOG
+ syslog(LOG_ERR, "Unable to create auth socket for %s:%m",
+ get_client_name(cptr,TRUE));
+#endif
+ Debug((DEBUG_ERROR, "Unable to create auth socket for %s:%s",
+ get_client_name(cptr, TRUE),
+ strerror(get_sockerr(cptr))));
+ if (!DoingDNS(cptr))
+ SetAccess(cptr);
+ ircstp->is_abad++;
+ return;
+ }
+#ifndef _WIN32
+ if (cptr->authfd >= (MAXCONNECTIONS - 3))
+ {
+ sendto_ops("Can't allocate fd for auth on %s",
+ get_client_name(cptr, TRUE));
+ (void)close(cptr->authfd);
+ return;
+ }
+#endif
+
+
+#ifdef SHOWCONNECTINFO
+#ifndef _WIN32
+ write(cptr->fd, REPORT_DO_ID, R_do_id);
+#else
+ send(cptr->fd, REPORT_DO_ID, R_do_id,0);
+#endif
+#endif
+
+ set_non_blocking(cptr->authfd, cptr);
+
+ getsockname(cptr->fd, (struct sockaddr *)&sock, &addrlen);
+ sock.sin_port = 0;
+ sock.sin_family = AF_INET; /* redundant? */
+ (void)bind(cptr->authfd, (struct sockaddr *)&sock, sizeof(sock));
+
+ bcopy((char *)&cptr->ip, (char *)&sock.sin_addr,
+ sizeof(struct in_addr));
+
+ sock.sin_port = htons(113);
+ sock.sin_family = AF_INET;
+
+ if (connect(cptr->authfd, (struct sockaddr *)&sock,
+#ifndef _WIN32
+ sizeof(sock)) == -1 && errno != EINPROGRESS)
+#else
+ sizeof(sock)) == -1 && (WSAGetLastError() !=
+ WSAEINPROGRESS && WSAGetLastError() != WSAEWOULDBLOCK))
+#endif
+ {
+ ircstp->is_abad++;
+ /*
+ * No error report from this...
+ */
+#ifndef _WIN32
+ (void)close(cptr->authfd);
+#else
+ (void)closesocket(cptr->authfd);
+#endif
+ cptr->authfd = -1;
+ if (!DoingDNS(cptr))
+ SetAccess(cptr);
+#ifdef SHOWCONNECTINFO
+#ifndef _WIN32
+ write(cptr->fd, REPORT_FAIL_ID, R_fail_id);
+#else
+ send(cptr->fd, REPORT_FAIL_ID, R_fail_id, 0);
+#endif
+#endif
+ return;
+ }
+ cptr->flags |= (FLAGS_WRAUTH|FLAGS_AUTH);
+ if (cptr->authfd > highest_fd)
+ highest_fd = cptr->authfd;
+ return;
+}
+
+/*
+ * send_authports
+ *
+ * Send the ident server a query giving "theirport , ourport".
+ * The write is only attempted *once* so it is deemed to be a fail if the
+ * entire write doesn't write all the data given. This shouldnt be a
+ * problem since the socket should have a write buffer far greater than
+ * this message to store it in should problems arise. -avalon
+ */
+void send_authports(cptr)
+aClient *cptr;
+{
+ struct sockaddr_in us, them;
+ char authbuf[32];
+ int ulen, tlen;
+
+ Debug((DEBUG_NOTICE,"write_authports(%x) fd %d authfd %d stat %d",
+ cptr, cptr->fd, cptr->authfd, cptr->status));
+ tlen = ulen = sizeof(us);
+ if (getsockname(cptr->fd, (struct sockaddr *)&us, &ulen) ||
+ getpeername(cptr->fd, (struct sockaddr *)&them, &tlen))
+ {
+#ifdef USE_SYSLOG
+ syslog(LOG_ERR, "auth get{sock,peer}name error for %s:%m",
+ get_client_name(cptr, TRUE));
+#endif
+ goto authsenderr;
+ }
+
+ (void)sprintf(authbuf, "%u , %u\r\n",
+ (unsigned int)ntohs(them.sin_port),
+ (unsigned int)ntohs(us.sin_port));
+
+ Debug((DEBUG_SEND, "sending [%s] to auth port %s.113",
+ authbuf, inetntoa((char *)&them.sin_addr)));
+#ifndef _WIN32
+ if (write(cptr->authfd, authbuf, strlen(authbuf)) != strlen(authbuf))
+#else
+ if (send(cptr->authfd, authbuf, strlen(authbuf), 0) != (int)strlen(authbuf))
+#endif
+ {
+authsenderr:
+ ircstp->is_abad++;
+#ifndef _WIN32
+ (void)close(cptr->authfd);
+#else
+ (void)closesocket(cptr->authfd);
+#endif
+ if (cptr->authfd == highest_fd)
+ while (!local[highest_fd])
+ highest_fd--;
+ cptr->authfd = -1;
+ cptr->flags &= ~FLAGS_AUTH;
+#ifdef SHOWCONNECTINFO
+#ifndef _WIN32
+ write(cptr->fd, REPORT_FAIL_ID, R_fail_id);
+#else
+ send(cptr->fd, REPORT_FAIL_ID, R_fail_id, 0);
+#endif
+#endif
+ if (!DoingDNS(cptr))
+ SetAccess(cptr);
+ }
+ cptr->flags &= ~FLAGS_WRAUTH;
+ return;
+}
+
+/*
+ * read_authports
+ *
+ * read the reply (if any) from the ident server we connected to.
+ * The actual read processijng here is pretty weak - no handling of the reply
+ * if it is fragmented by IP.
+ */
+void read_authports(cptr)
+Reg1 aClient *cptr;
+{
+ Reg1 char *s, *t;
+ Reg2 int len;
+ char ruser[USERLEN+1], system[8];
+ u_short remp = 0, locp = 0;
+
+ *system = *ruser = '\0';
+ Debug((DEBUG_NOTICE,"read_authports(%x) fd %d authfd %d stat %d",
+ cptr, cptr->fd, cptr->authfd, cptr->status));
+ /*
+ * Nasty. Cant allow any other reads from client fd while we're
+ * waiting on the authfd to return a full valid string. Use the
+ * client's input buffer to buffer the authd reply.
+ * Oh. this is needed because an authd reply may come back in more
+ * than 1 read! -avalon
+ */
+#ifndef _WIN32
+ if ((len = read(cptr->authfd, cptr->buffer + cptr->count,
+ sizeof(cptr->buffer) - 1 - cptr->count)) >= 0)
+#else
+ if ((len = recv(cptr->authfd, cptr->buffer + cptr->count,
+ sizeof(cptr->buffer) - 1 - cptr->count, 0)) >= 0)
+#endif
+ {
+ cptr->count += len;
+ cptr->buffer[cptr->count] = '\0';
+ }
+
+ cptr->lasttime = TStime();
+ if ((len > 0) && (cptr->count != (sizeof(cptr->buffer) - 1)) &&
+ (sscanf(cptr->buffer, "%hd , %hd : USERID : %*[^:]: %10s",
+ &remp, &locp, ruser) == 3))
+ {
+ s = rindex(cptr->buffer, ':');
+ *s++ = '\0';
+ for (t = (rindex(cptr->buffer, ':') + 1); *t; t++)
+ if (!isspace(*t))
+ break;
+ strncpyzt(system, t, sizeof(system));
+ for (t = ruser; *s && *s != '@' && (t < ruser + sizeof(ruser)); s++)
+ if (!isspace(*s) && *s != ':')
+ *t++ = *s;
+ *t = '\0';
+ Debug((DEBUG_INFO,"auth reply ok [%s] [%s]", system, ruser));
+ }
+ else if (len != 0)
+ {
+ if (!index(cptr->buffer, '\n') && !index(cptr->buffer, '\r'))
+ return;
+ Debug((DEBUG_ERROR,"local %d remote %d", locp, remp));
+ Debug((DEBUG_ERROR,"bad auth reply in [%s]", cptr->buffer));
+ *ruser = '\0';
+ }
+#ifndef _WIN32
+ (void)close(cptr->authfd);
+#else
+ (void)closesocket(cptr->authfd);
+#endif
+ if (cptr->authfd == highest_fd)
+ while (!local[highest_fd])
+ highest_fd--;
+ cptr->count = 0;
+ cptr->authfd = -1;
+ ClearAuth(cptr);
+ if (!DoingDNS(cptr))
+ SetAccess(cptr);
+ if (len > 0)
+ Debug((DEBUG_INFO,"ident reply: [%s]", cptr->buffer));
+
+#ifdef SHOWCONNECTINFO
+#ifndef _WIN32
+ write(cptr->fd, REPORT_FIN_ID, R_fin_id);
+#else
+ send(cptr->fd, REPORT_FIN_ID, R_fin_id, 0);
+#endif
+#endif
+
+ if (!locp || !remp || !*ruser)
+ {
+ ircstp->is_abad++;
+ return;
+ }
+ ircstp->is_asuc++;
+ strncpyzt(cptr->username, ruser, USERLEN+1);
+/* if (strncmp(system, "OTHER", 5))
+*/ cptr->flags |= FLAGS_GOTID;
+ Debug((DEBUG_INFO, "got username [%s]", ruser));
+ return;
+}
--- /dev/null
+/*
+ * IRC - Internet Relay Chat, ircd/s_bsd.c
+ * Copyright (C) 1990 Jarkko Oikarinen and
+ * University of Oulu, Computing Center
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* -- Jto -- 07 Jul 1990
+ * Added jlp@hamblin.byu.edu's debugtty fix
+ */
+
+/* -- Armin -- Jun 18 1990
+ * Added setdtablesize() for more socket connections
+ * (sequent OS Dynix only) -- maybe select()-call must be changed ...
+ */
+
+/* -- Jto -- 13 May 1990
+ * Added several fixes from msa:
+ * Better error messages
+ * Changes in check_access
+ * Added SO_REUSEADDR fix from zessel@informatik.uni-kl.de
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)s_bsd.c 2.78 2/7/94 (C) 1988 University of Oulu, \
+Computing Center and Jarkko Oikarinen";
+#endif
+
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#include "res.h"
+#include "numeric.h"
+#include "version.h"
+#ifndef _WIN32
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <utmp.h>
+#include <sys/resource.h>
+#else
+#include <io.h>
+#endif
+#if defined(SOL20)
+#include <sys/filio.h>
+#endif
+#include "inet.h"
+#include <stdio.h>
+#include <signal.h>
+#include <fcntl.h>
+#ifdef AIX
+# include <time.h>
+# include <arpa/nameser.h>
+#else
+# include "nameser.h"
+#endif
+#include "resolv.h"
+#include "sock.h" /* If FD_ZERO isn't define up to this point, */
+ /* define it (BSD4.2 needs this) */
+#include "h.h"
+#ifndef NO_FDLIST
+#include "fdlist.h"
+#endif
+
+ID_CVS("$Id$");
+
+#ifndef IN_LOOPBACKNET
+#define IN_LOOPBACKNET 0x7f
+#endif
+
+#ifdef _WIN32
+extern HWND hwIRCDWnd;
+#endif
+aClient *local[MAXCONNECTIONS];
+int highest_fd = 0, readcalls = 0, udpfd = -1, resfd = -1;
+static struct sockaddr_in mysk;
+static void polludp();
+
+static struct sockaddr *connect_inet PROTO((aConfItem *, aClient *, int *));
+static int completed_connection PROTO((aClient *));
+static int check_init PROTO((aClient *, char *));
+#ifndef _WIN32
+static void do_dns_async PROTO(()), set_sock_opts PROTO((int, aClient *));
+#else
+static void set_sock_opts PROTO((int, aClient *));
+#endif
+static char readbuf[8192];
+char zlinebuf[BUFSIZE];
+extern char *version;
+
+#ifndef NO_FDLIST
+extern fdlist default_fdlist;
+extern fdlist busycli_fdlist;
+extern fdlist serv_fdlist;
+extern fdlist oper_fdlist;
+extern fdlist socks_fdlist;
+#endif
+
+/*
+ * Try and find the correct name to use with getrlimit() for setting the max.
+ * number of files allowed to be open by this process.
+ */
+#ifdef RLIMIT_FDMAX
+# define RLIMIT_FD_MAX RLIMIT_FDMAX
+#else
+# ifdef RLIMIT_NOFILE
+# define RLIMIT_FD_MAX RLIMIT_NOFILE
+# else
+# ifdef RLIMIT_OPEN_MAX
+# define RLIMIT_FD_MAX RLIMIT_OPEN_MAX
+# else
+# undef RLIMIT_FD_MAX
+# endif
+# endif
+#endif
+
+/*
+** add_local_domain()
+** Add the domain to hostname, if it is missing
+** (as suggested by eps@TOASTER.SFSU.EDU)
+*/
+
+void add_local_domain(hname, size)
+char *hname;
+int size;
+{
+#ifdef RES_INIT
+ /* try to fix up unqualified names */
+ if (!index(hname, '.'))
+ {
+ if (!(_res.options & RES_INIT))
+ {
+ Debug((DEBUG_DNS,"res_init()"));
+ res_init();
+ }
+ if (_res.defdname[0])
+ {
+ (void)strncat(hname, ".", size-1);
+ (void)strncat(hname, _res.defdname, size-2);
+ }
+ }
+#endif
+ return;
+}
+
+/*
+** Cannot use perror() within daemon. stderr is closed in
+** ircd and cannot be used. And, worse yet, it might have
+** been reassigned to a normal connection...
+*/
+
+/*
+** report_error
+** This a replacement for perror(). Record error to log and
+** also send a copy to all *LOCAL* opers online.
+**
+** text is a *format* string for outputting error. It must
+** contain only two '%s', the first will be replaced
+** by the sockhost from the cptr, and the latter will
+** be taken from sys_errlist[errno].
+**
+** cptr if not NULL, is the *LOCAL* client associated with
+** the error.
+*/
+void report_error(text, cptr)
+char *text;
+aClient *cptr;
+{
+#ifndef _WIN32
+ Reg1 int errtmp = errno; /* debug may change 'errno' */
+#else
+ Reg1 int errtmp = WSAGetLastError(); /* debug may change 'errno' */
+#endif
+ Reg2 char *host;
+ int err, len = sizeof(err);
+
+ host = (cptr) ? get_client_name(cptr, FALSE) : "";
+
+ fprintf(stderr, text, host, strerror(errtmp));
+ fputc('\n',stderr);
+ Debug((DEBUG_ERROR, text, host, strerror(errtmp)));
+
+ /*
+ * Get the *real* error from the socket (well try to anyway..).
+ * This may only work when SO_DEBUG is enabled but its worth the
+ * gamble anyway.
+ */
+#ifdef SO_ERROR
+ if (cptr && !IsMe(cptr) && cptr->fd >= 0)
+ if (!getsockopt(cptr->fd, SOL_SOCKET, SO_ERROR, (OPT_TYPE *)&err, &len))
+ if (err)
+ errtmp = err;
+#endif
+ sendto_ops(text, host, strerror(errtmp));
+#ifdef USE_SYSLOG
+ syslog(LOG_WARNING, text, host, strerror(errtmp));
+#endif
+ return;
+}
+
+/*
+ * inetport
+ *
+ * Create a socket in the AF_INET domain, bind it to the port given in
+ * 'port' and listen to it. Connections are accepted to this socket
+ * depending on the IP# mask given by 'name'. Returns the fd of the
+ * socket created or -1 on error.
+ */
+int inetport(cptr, name, port)
+aClient *cptr;
+char *name;
+int port;
+{
+ static struct sockaddr_in server;
+ int ad[4], len = sizeof(server);
+ char ipname[20];
+
+ if (BadPtr(name))
+ name = "*";
+ ad[0] = ad[1] = ad[2] = ad[3] = 0;
+
+ /*
+ * do it this way because building ip# from separate values for each
+ * byte requires endian knowledge or some nasty messing. Also means
+ * easy conversion of "*" 0.0.0.0 or 134.* to 134.0.0.0 :-)
+ */
+ (void)sscanf(name, "%d.%d.%d.%d", &ad[0], &ad[1], &ad[2], &ad[3]);
+ (void)sprintf(ipname, "%d.%d.%d.%d", ad[0], ad[1], ad[2], ad[3]);
+
+ if (cptr != &me)
+ {
+ (void)sprintf(cptr->sockhost, "%-.42s.%.u",
+ name, (unsigned int)port);
+ (void)strcpy(cptr->name, me.name);
+ }
+ /*
+ * At first, open a new socket
+ */
+ if (cptr->fd == -1)
+ cptr->fd = socket(AF_INET, SOCK_STREAM, 0);
+
+ if (cptr->fd < 0)
+ {
+// fprintf(
+#if !defined(DEBUGMODE) && !defined(_WIN32)
+#endif
+ report_error("opening stream socket %s:%s", cptr);
+ return -1;
+ }
+ else if (cptr->fd >= MAXCLIENTS)
+ {
+ sendto_ops("No more connections allowed (%s)", cptr->name);
+#ifndef _WIN32
+ (void)close(cptr->fd);
+#else
+ (void)closesocket(cptr->fd);
+#endif
+ return -1;
+ }
+ set_sock_opts(cptr->fd, cptr);
+ /*
+ * Bind a port to listen for new connections if port is non-null,
+ * else assume it is already open and try get something from it.
+ */
+ if (port)
+ {
+ server.sin_family = AF_INET;
+ /* per-port bindings, fixes /stats l */
+ server.sin_addr.s_addr = inet_addr(ipname);
+#ifdef TESTNET
+ server.sin_port = htons(port + 10000);
+#else
+ server.sin_port = htons(port);
+#endif
+ /*
+ * Try 10 times to bind the socket with an interval of 20
+ * seconds. Do this so we dont have to keepp trying manually
+ * to bind. Why ? Because a port that has closed often lingers
+ * around for a short time.
+ * This used to be the case. Now it no longer is.
+ * Could cause the server to hang for too long - avalon
+ */
+ if (bind(cptr->fd, (struct sockaddr *)&server,
+ sizeof(server)) == -1)
+ {
+ report_error("binding stream socket %s:%s", cptr);
+#ifndef _WIN32
+ (void)close(cptr->fd);
+#else
+ (void)closesocket(cptr->fd);
+#endif
+ return -1;
+ }
+ }
+ if (getsockname(cptr->fd, (struct sockaddr *)&server, &len))
+ {
+ report_error("getsockname failed for %s:%s",cptr);
+#ifndef _WIN32
+ (void)close(cptr->fd);
+#else
+ (void)closesocket(cptr->fd);
+#endif
+ return -1;
+ }
+
+ if (cptr == &me) /* KLUDGE to get it work... */
+ {
+ char buf[1024];
+
+#ifdef TESTNET
+ (void)sprintf(buf, rpl_str(RPL_MYPORTIS), me.name, "*",
+ ntohs(server.sin_port) - 10000);
+#else
+ (void)sprintf(buf, rpl_str(RPL_MYPORTIS), me.name, "*",
+ ntohs(server.sin_port));
+#endif
+ (void)write(0, buf, strlen(buf));
+ }
+ if (cptr->fd > highest_fd)
+ highest_fd = cptr->fd;
+ cptr->ip.s_addr = name ? inet_addr(ipname) : me.ip.s_addr;
+#ifdef TESTNET
+ cptr->port = (int)ntohs(server.sin_port) - 10000;
+#else
+ cptr->port = (int)ntohs(server.sin_port);
+#endif
+ (void)listen(cptr->fd, LISTEN_SIZE);
+ local[cptr->fd] = cptr;
+
+ return 0;
+}
+
+/*
+ * add_listener
+ *
+ * Create a new client which is essentially the stub like 'me' to be used
+ * for a socket that is passive (listen'ing for connections to be accepted).
+ */
+int add_listener(aconf)
+aConfItem *aconf;
+{
+ aClient *cptr;
+
+ cptr = make_client(NULL, NULL);
+ cptr->flags = FLAGS_LISTEN;
+ cptr->acpt = cptr;
+ cptr->from = cptr;
+ SetMe(cptr);
+ strncpyzt(cptr->name, aconf->host, sizeof(cptr->name));
+ if (inetport(cptr, aconf->host, aconf->port))
+ cptr->fd = -2;
+
+ if (cptr->fd >= 0)
+ {
+ cptr->confs = make_link();
+ cptr->confs->next = NULL;
+ cptr->confs->value.aconf = aconf;
+ set_non_blocking(cptr->fd, cptr);
+ }
+ else
+ free_client(cptr);
+ return 0;
+}
+
+/*
+ * close_listeners
+ *
+ * Close and free all clients which are marked as having their socket open
+ * and in a state where they can accept connections. Unix sockets have
+ * the path to the socket unlinked for cleanliness.
+ */
+void close_listeners()
+{
+ Reg1 aClient *cptr;
+ Reg2 int i;
+ Reg3 aConfItem *aconf;
+
+ /*
+ * close all 'extra' listening ports we have and unlink the file
+ * name if it was a unix socket.
+ */
+ for (i = highest_fd; i >= 0; i--)
+ {
+ if (!(cptr = local[i]))
+ continue;
+ if (!IsMe(cptr) || cptr == &me || !IsListening(cptr))
+ continue;
+ aconf = cptr->confs->value.aconf;
+
+ if (IsIllegal(aconf) && aconf->clients == 0)
+ {
+ close_connection(cptr);
+ }
+ }
+}
+
+/*
+ * init_sys
+ */
+void init_sys()
+{
+ Reg1 int fd;
+#ifdef RLIMIT_FD_MAX
+ struct rlimit limit;
+ int pid;
+
+ if (!getrlimit(RLIMIT_FD_MAX, &limit))
+ {
+# ifdef pyr
+ if (limit.rlim_cur < MAXCONNECTIONS)
+#else
+ if (limit.rlim_max < MAXCONNECTIONS)
+# endif
+ {
+ (void)fprintf(stderr,"ircd fd table too big\n");
+ (void)fprintf(stderr,"Hard Limit: %d IRC max: %d\n",
+ limit.rlim_max, MAXCONNECTIONS);
+ (void)fprintf(stderr,"Fix MAXCONNECTIONS\n");
+ exit(-1);
+ }
+# ifndef pyr
+ limit.rlim_cur = limit.rlim_max; /* make soft limit the max */
+ if (setrlimit(RLIMIT_FD_MAX, &limit) == -1)
+ {
+ (void)fprintf(stderr,"error setting max fd's to %d\n",
+ limit.rlim_cur);
+ exit(-1);
+ }
+# endif
+ }
+#endif
+
+ /* Startup message
+ pid = getpid();
+ pid++;
+ fprintf(stderr, "|---------------------------------------------\n");
+ fprintf(stderr, "| UnrealIRCD has successfully loaded.\n");
+ fprintf(stderr, "| Config Directory: %s\n", DPATH);
+ fprintf(stderr, "| MAXCONNECTIONS set at %d\n", MAXCONNECTIONS);
+ fprintf(stderr, "| Process ID: %d\n", pid);
+ fprintf(stderr, "|---------------------------------------------\n");*/
+
+#ifdef sequent
+# ifndef DYNIXPTX
+ int fd_limit;
+
+ fd_limit = setdtablesize(MAXCONNECTIONS + 1);
+ if (fd_limit < MAXCONNECTIONS)
+ {
+ (void)fprintf(stderr,"ircd fd table too big\n");
+ (void)fprintf(stderr,"Hard Limit: %d IRC max: %d\n",
+ fd_limit, MAXCONNECTIONS);
+ (void)fprintf(stderr,"Fix MAXCONNECTIONS\n");
+ exit(-1);
+ }
+# endif
+#endif
+#if defined(PCS) || defined(DYNIXPTX) || defined(SVR3)
+ char logbuf[BUFSIZ];
+
+ (void)setvbuf(stderr,logbuf,_IOLBF,sizeof(logbuf));
+#else
+# if defined(HPUX)
+ (void)setvbuf(stderr, NULL, _IOLBF, 0);
+# else
+# if !defined(SOL20) && !defined(_WIN32)
+ (void)setlinebuf(stderr);
+# endif
+# endif
+#endif
+#ifndef _WIN32
+ for (fd = 3; fd < MAXCONNECTIONS; fd++)
+ {
+ (void)close(fd);
+ local[fd] = NULL;
+ }
+ local[1] = NULL;
+ (void)close(1);
+
+ if (bootopt & BOOT_TTY) /* debugging is going to a tty */
+ goto init_dgram;
+ if (!(bootopt & BOOT_DEBUG))
+ (void)close(2);
+
+ if (((bootopt & BOOT_CONSOLE) || isatty(0)) &&
+ !(bootopt & (BOOT_INETD|BOOT_OPER)))
+ {
+#ifndef _AMIGA
+/* if (fork())
+ exit(0);
+*/
+#endif
+#ifdef TIOCNOTTY
+ if ((fd = open("/dev/tty", O_RDWR)) >= 0)
+ {
+ (void)ioctl(fd, TIOCNOTTY, (char *)NULL);
+ (void)close(fd);
+ }
+#endif
+
+#if defined(HPUX) || defined(SOL20) || defined(DYNIXPTX) || \
+ defined(_POSIX_SOURCE) || defined(SVR4) || defined(SGI)
+ (void)setsid();
+#else
+ (void)setpgrp(0, (int)getpid());
+#endif
+ (void)close(0); /* fd 0 opened by inetd */
+ local[0] = NULL;
+ }
+init_dgram:
+#endif /*_WIN32*/
+ resfd = init_resolver(0x1f);
+
+ return;
+}
+
+void write_pidfile()
+{
+#ifdef IRCD_PIDFILE
+ int fd;
+ char buff[20];
+ if ((fd = open(IRCD_PIDFILE, O_CREAT|O_WRONLY, 0600))>=0)
+ {
+ bzero(buff, sizeof(buff));
+ (void)sprintf(buff,"%5d\n", (int)getpid());
+ if (write(fd, buff, strlen(buff)) == -1)
+ Debug((DEBUG_NOTICE,"Error writing to pid file %s",
+ IRCD_PIDFILE));
+ (void)close(fd);
+ return;
+ }
+#ifdef DEBUGMODE
+ else
+ Debug((DEBUG_NOTICE,"Error opening pid file %s",
+ IRCD_PIDFILE));
+#endif
+#endif
+}
+
+/*
+ * Initialize the various name strings used to store hostnames. This is set
+ * from either the server's sockhost (if client fd is a tty or localhost)
+ * or from the ip# converted into a string. 0 = success, -1 = fail.
+ */
+static int check_init(cptr, sockn)
+Reg1 aClient *cptr;
+Reg2 char *sockn;
+{
+ struct sockaddr_in sk;
+ int len = sizeof(struct sockaddr_in);
+
+
+ /* If descriptor is a tty, special checking... */
+#ifndef _WIN32
+ if (isatty(cptr->fd))
+#else
+ if (0)
+#endif
+ {
+ strncpyzt(sockn, me.sockhost, HOSTLEN);
+ bzero((char *)&sk, sizeof(struct sockaddr_in));
+ }
+ else if (getpeername(cptr->fd, (struct sockaddr *)&sk, &len) == -1)
+ {
+ report_error("connect failure: %s %s", cptr);
+ return -1;
+ }
+ (void)strcpy(sockn, (char *)inetntoa((char *)&sk.sin_addr));
+ if (inet_netof(sk.sin_addr) == IN_LOOPBACKNET)
+ {
+ cptr->hostp = NULL;
+ strncpyzt(sockn, me.sockhost, HOSTLEN);
+ }
+ bcopy((char *)&sk.sin_addr, (char *)&cptr->ip,
+ sizeof(struct in_addr));
+
+#ifdef TESTNET
+ cptr->port = (int)ntohs(sk.sin_port) - 10000;
+#else
+ cptr->port = (int)ntohs(sk.sin_port);
+#endif
+
+ return 0;
+}
+
+/*
+ * Ordinary client access check. Look for conf lines which have the same
+ * status as the flags passed.
+ * 0 = Success
+ * -1 = Access denied
+ * -2 = Bad socket.
+ */
+int check_client(cptr)
+Reg1 aClient *cptr;
+{
+ static char sockname[HOSTLEN+1];
+ Reg2 struct hostent *hp = NULL;
+ Reg3 int i;
+
+ ClearAccess(cptr);
+ Debug((DEBUG_DNS, "ch_cl: check access for %s[%s]",
+ cptr->name, inetntoa((char *)&cptr->ip)));
+
+ if (check_init(cptr, sockname))
+ return -2;
+
+ if (!IsUnixSocket(cptr))
+ hp = cptr->hostp;
+ /*
+ * Verify that the host to ip mapping is correct both ways and that
+ * the ip#(s) for the socket is listed for the host.
+ */
+ if (hp)
+ {
+ for (i = 0; hp->h_addr_list[i]; i++)
+ if (!bcmp(hp->h_addr_list[i], (char *)&cptr->ip,
+ sizeof(struct in_addr)))
+ break;
+ if (!hp->h_addr_list[i])
+ {
+ sendto_ops("IP# Mismatch: %s != %s[%08x]",
+ inetntoa((char *)&cptr->ip), hp->h_name,
+ *((unsigned long *)hp->h_addr));
+ hp = NULL;
+ }
+ }
+
+ if ((i = attach_Iline(cptr, hp, sockname)))
+ {
+ Debug((DEBUG_DNS,"ch_cl: access denied: %s[%s]",
+ cptr->name, sockname));
+ return i;
+ }
+
+ Debug((DEBUG_DNS, "ch_cl: access ok: %s[%s]",
+ cptr->name, sockname));
+
+ if (inet_netof(cptr->ip) == IN_LOOPBACKNET || IsUnixSocket(cptr) ||
+ inet_netof(cptr->ip) == inet_netof(mysk.sin_addr))
+ {
+ ircstp->is_loc++;
+ cptr->flags |= FLAGS_LOCAL;
+ }
+ return 0;
+}
+
+#define CFLAG CONF_CONNECT_SERVER
+#define NFLAG CONF_NOCONNECT_SERVER
+/*
+ * check_server_init(), check_server()
+ * check access for a server given its name (passed in cptr struct).
+ * Must check for all C/N lines which have a name which matches the
+ * name given and a host which matches. A host alias which is the
+ * same as the server name is also acceptable in the host field of a
+ * C/N line.
+ * 0 = Success
+ * -1 = Access denied
+ * -2 = Bad socket.
+ */
+int check_server_init(cptr)
+aClient *cptr;
+{
+ Reg1 char *name;
+ Reg2 aConfItem *c_conf = NULL, *n_conf = NULL;
+ struct hostent *hp = NULL;
+ Link *lp;
+
+ name = cptr->name;
+ Debug((DEBUG_DNS, "sv_cl: check access for %s[%s]",
+ name, cptr->sockhost));
+
+ if (IsUnknown(cptr) && !attach_confs(cptr, name, CFLAG|NFLAG))
+ {
+ Debug((DEBUG_DNS,"No C/N lines for %s", name));
+ return -1;
+ }
+ lp = cptr->confs;
+ /*
+ * We initiated this connection so the client should have a C and N
+ * line already attached after passing through the connec_server()
+ * function earlier.
+ */
+ if (IsConnecting(cptr) || IsHandshake(cptr))
+ {
+ c_conf = find_conf(lp, name, CFLAG);
+ n_conf = find_conf(lp, name, NFLAG);
+ if (!c_conf || !n_conf)
+ {
+ sendto_ops("Connecting Error: %s[%s]", name,
+ cptr->sockhost);
+ det_confs_butmask(cptr, 0);
+ return -1;
+ }
+ }
+
+ /*
+ ** If the servername is a hostname, either an alias (CNAME) or
+ ** real name, then check with it as the host. Use gethostbyname()
+ ** to check for servername as hostname.
+ */
+ if (!IsUnixSocket(cptr) && !cptr->hostp)
+ {
+ Reg1 aConfItem *aconf;
+
+ aconf = count_cnlines(lp);
+ if (aconf)
+ {
+ Reg1 char *s;
+ Link lin;
+
+ /*
+ ** Do a lookup for the CONF line *only* and not
+ ** the server connection else we get stuck in a
+ ** nasty state since it takes a SERVER message to
+ ** get us here and we cant interrupt that very
+ ** well.
+ */
+ ClearAccess(cptr);
+ lin.value.aconf = aconf;
+ lin.flags = ASYNC_CONF;
+ nextdnscheck = 1;
+ if ((s = index(aconf->host, '@')))
+ s++;
+ else
+ s = aconf->host;
+ Debug((DEBUG_DNS,"sv_ci:cache lookup (%s)",s));
+ hp = gethost_byname(s, &lin);
+ }
+ }
+ return check_server(cptr, hp, c_conf, n_conf, 0);
+
+}
+
+int check_server(cptr, hp, c_conf, n_conf, estab)
+aClient *cptr;
+Reg1 aConfItem *n_conf, *c_conf;
+Reg2 struct hostent *hp;
+int estab;
+{
+ Reg3 char *name;
+ char abuff[HOSTLEN+USERLEN+2];
+ char sockname[HOSTLEN+1], fullname[HOSTLEN+1];
+ Link *lp = cptr->confs;
+ int i;
+
+ ClearAccess(cptr);
+ if (check_init(cptr, sockname))
+ return -2;
+
+check_serverback:
+ if (hp)
+ {
+ for (i = 0; hp->h_addr_list[i]; i++)
+ if (!bcmp(hp->h_addr_list[i], (char *)&cptr->ip,
+ sizeof(struct in_addr)))
+ break;
+ if (!hp->h_addr_list[i])
+ {
+ sendto_ops("IP# Mismatch: %s != %s[%08x]",
+ inetntoa((char *)&cptr->ip), hp->h_name,
+ *((unsigned long *)hp->h_addr));
+ hp = NULL;
+ }
+ }
+ else if (cptr->hostp)
+ {
+ hp = cptr->hostp;
+ goto check_serverback;
+ }
+
+ if (hp)
+ /*
+ * if we are missing a C or N line from above, search for
+ * it under all known hostnames we have for this ip#.
+ */
+ for (i=0,name = hp->h_name; name ; name = hp->h_aliases[i++])
+ {
+ strncpyzt(fullname, name, sizeof(fullname));
+ add_local_domain(fullname, HOSTLEN-strlen(fullname));
+ Debug((DEBUG_DNS, "sv_cl: gethostbyaddr: %s->%s",
+ sockname, fullname));
+ (void)sprintf(abuff, "%s@%s",
+ cptr->username, fullname);
+ if (!c_conf)
+ c_conf = find_conf_host(lp, abuff, CFLAG);
+ if (!n_conf)
+ n_conf = find_conf_host(lp, abuff, NFLAG);
+ if (c_conf && n_conf)
+ {
+ get_sockhost(cptr, fullname);
+ break;
+ }
+ }
+ name = cptr->name;
+
+ /*
+ * Check for C and N lines with the hostname portion the ip number
+ * of the host the server runs on. This also checks the case where
+ * there is a server connecting from 'localhost'.
+ */
+ if (IsUnknown(cptr) && (!c_conf || !n_conf))
+ {
+ (void)sprintf(abuff, "%s@%s", cptr->username, sockname);
+ if (!c_conf)
+ c_conf = find_conf_host(lp, abuff, CFLAG);
+ if (!n_conf)
+ n_conf = find_conf_host(lp, abuff, NFLAG);
+ }
+ /*
+ * Attach by IP# only if all other checks have failed.
+ * It is quite possible to get here with the strange things that can
+ * happen when using DNS in the way the irc server does. -avalon
+ */
+ if (!hp)
+ {
+ if (!c_conf)
+ c_conf = find_conf_ip(lp, (char *)&cptr->ip,
+ cptr->username, CFLAG);
+ if (!n_conf)
+ n_conf = find_conf_ip(lp, (char *)&cptr->ip,
+ cptr->username, NFLAG);
+ }
+ else
+ for (i = 0; hp->h_addr_list[i]; i++)
+ {
+ if (!c_conf)
+ c_conf = find_conf_ip(lp, hp->h_addr_list[i],
+ cptr->username, CFLAG);
+ if (!n_conf)
+ n_conf = find_conf_ip(lp, hp->h_addr_list[i],
+ cptr->username, NFLAG);
+ }
+ /*
+ * detach all conf lines that got attached by attach_confs()
+ */
+ det_confs_butmask(cptr, 0);
+ /*
+ * if no C or no N lines, then deny access
+ */
+ if (!c_conf || !n_conf)
+ {
+ get_sockhost(cptr, sockname);
+ Debug((DEBUG_DNS, "sv_cl: access denied: %s[%s@%s] c %x n %x",
+ name, cptr->username, cptr->sockhost,
+ c_conf, n_conf));
+ return -1;
+ }
+ /*
+ * attach the C and N lines to the client structure for later use.
+ */
+ (void)attach_conf(cptr, n_conf);
+ (void)attach_conf(cptr, c_conf);
+ (void)attach_confs(cptr, name, CONF_HUB|CONF_LEAF|CONF_UWORLD);
+
+ if ((c_conf->ipnum.s_addr == -1) && !IsUnixSocket(cptr))
+ bcopy((char *)&cptr->ip, (char *)&c_conf->ipnum,
+ sizeof(struct in_addr));
+ if (!IsUnixSocket(cptr))
+ get_sockhost(cptr, c_conf->host);
+
+ Debug((DEBUG_DNS,"sv_cl: access ok: %s[%s]",
+ name, cptr->sockhost));
+ if (estab)
+ return m_server_estab(cptr);
+ return 0;
+}
+#undef CFLAG
+#undef NFLAG
+
+/*
+** completed_connection
+** Complete non-blocking connect()-sequence. Check access and
+** terminate connection, if trouble detected.
+**
+** Return TRUE, if successfully completed
+** FALSE, if failed and ClientExit
+*/
+static int completed_connection(cptr)
+aClient *cptr;
+{
+ aConfItem *aconf;
+
+ SetHandshake(cptr);
+
+ aconf = find_conf(cptr->confs, cptr->name, CONF_CONNECT_SERVER);
+ if (!aconf)
+ {
+ sendto_ops("Lost C-Line for %s", get_client_name(cptr,FALSE));
+ return -1;
+ }
+ if (!BadPtr(aconf->passwd))
+ sendto_one(cptr, "PASS :%s", aconf->passwd);
+
+ aconf = find_conf(cptr->confs, cptr->name, CONF_NOCONNECT_SERVER);
+ if (!aconf)
+ {
+ sendto_ops("Lost N-Line for %s", get_client_name(cptr,FALSE));
+ return -1;
+ }
+ sendto_one(cptr, "PROTOCTL %s", PROTOCTL_SERVER);
+ sendto_one(cptr, "SERVER %s 1 :%s",
+ my_name_for_link(me.name, aconf), me.info);
+ if (!IsDead(cptr))
+ start_auth(cptr);
+
+ return (IsDead(cptr)) ? -1 : 0;
+}
+
+/*
+** close_connection
+** Close the physical connection. This function must make
+** MyConnect(cptr) == FALSE, and set cptr->from == NULL.
+*/
+void close_connection(cptr)
+aClient *cptr;
+{
+ Reg1 aConfItem *aconf;
+ Reg2 int i,j;
+ int empty = cptr->fd;
+
+ if (IsServer(cptr))
+ {
+ ircstp->is_sv++;
+ ircstp->is_sbs += cptr->sendB;
+ ircstp->is_sbr += cptr->receiveB;
+ ircstp->is_sks += cptr->sendK;
+ ircstp->is_skr += cptr->receiveK;
+ ircstp->is_sti += TStime() - cptr->firsttime;
+ if (ircstp->is_sbs > 1023)
+ {
+ ircstp->is_sks += (ircstp->is_sbs >> 10);
+ ircstp->is_sbs &= 0x3ff;
+ }
+ if (ircstp->is_sbr > 1023)
+ {
+ ircstp->is_skr += (ircstp->is_sbr >> 10);
+ ircstp->is_sbr &= 0x3ff;
+ }
+ }
+ else if (IsClient(cptr))
+ {
+ ircstp->is_cl++;
+ ircstp->is_cbs += cptr->sendB;
+ ircstp->is_cbr += cptr->receiveB;
+ ircstp->is_cks += cptr->sendK;
+ ircstp->is_ckr += cptr->receiveK;
+ ircstp->is_cti += TStime() - cptr->firsttime;
+ if (ircstp->is_cbs > 1023)
+ {
+ ircstp->is_cks += (ircstp->is_cbs >> 10);
+ ircstp->is_cbs &= 0x3ff;
+ }
+ if (ircstp->is_cbr > 1023)
+ {
+ ircstp->is_ckr += (ircstp->is_cbr >> 10);
+ ircstp->is_cbr &= 0x3ff;
+ }
+ }
+ else
+ ircstp->is_ni++;
+
+ /*
+ * remove outstanding DNS queries.
+ */
+ del_queries((char *)cptr);
+ /*
+ * If the connection has been up for a long amount of time, schedule
+ * a 'quick' reconnect, else reset the next-connect cycle.
+ *
+ * Now just hold on a minute. We're currently doing this when a
+ * CLIENT exits too? I don't think so! If its not a server, or
+ * the SQUIT flag has been set, then we don't schedule a fast
+ * reconnect. Pisses off too many opers. :-) -Cabal95
+ */
+ if (IsServer(cptr) && !(cptr->flags & FLAGS_SQUIT) &&
+ (aconf = find_conf_exact(cptr->name, cptr->username,
+ cptr->sockhost, CONF_CONNECT_SERVER)))
+ {
+ /*
+ * Reschedule a faster reconnect, if this was a automaticly
+ * connected configuration entry. (Note that if we have had
+ * a rehash in between, the status has been changed to
+ * CONF_ILLEGAL). But only do this if it was a "good" link.
+ */
+ aconf->hold = TStime();
+ aconf->hold += (aconf->hold - cptr->since > HANGONGOODLINK) ?
+ HANGONRETRYDELAY : ConfConFreq(aconf);
+ if (nextconnect > aconf->hold)
+ nextconnect = aconf->hold;
+ }
+
+ if (cptr->authfd >= 0)
+#ifndef _WIN32
+ (void)close(cptr->authfd);
+#else
+ (void)closesocket(cptr->authfd);
+#endif
+
+#ifdef SOCKSPORT
+ if (cptr->socksfd >= 0)
+#ifndef _WIN32
+ (void)close(cptr->socksfd);
+#else
+ (void)closesocket(cptr->socksfd);
+#endif /* _WIN32 */
+#endif /* SOCKSPORT */
+
+
+
+ if (cptr->fd >= 0)
+ {
+ flush_connections(cptr->fd);
+ local[cptr->fd] = NULL;
+#ifndef _WIN32
+ (void)close(cptr->fd);
+#else
+ (void)closesocket(cptr->fd);
+#endif
+ cptr->fd = -2;
+ DBufClear(&cptr->sendQ);
+ DBufClear(&cptr->recvQ);
+ bzero(cptr->passwd, sizeof(cptr->passwd));
+ /*
+ * clean up extra sockets from P-lines which have been
+ * discarded.
+ */
+ if (cptr->acpt != &me && cptr->acpt != cptr)
+ {
+ aconf = cptr->acpt->confs->value.aconf;
+ if (aconf->clients > 0)
+ aconf->clients--;
+ if (!aconf->clients && IsIllegal(aconf))
+ close_connection(cptr->acpt);
+ }
+ }
+ for (; highest_fd > 0; highest_fd--)
+ if (local[highest_fd])
+ break;
+
+ det_confs_butmask(cptr, 0);
+ cptr->from = NULL; /* ...this should catch them! >:) --msa */
+
+ /*
+ * fd remap to keep local[i] filled at the bottom.
+ */
+ if (empty > 0)
+ if ((j = highest_fd) > (i = empty) &&
+ (local[j]->status != STAT_LOG))
+ {
+ if (dup2(j,i) == -1)
+ return;
+ local[i] = local[j];
+ local[i]->fd = i;
+ local[j] = NULL;
+#ifndef NO_FDLIST
+ /* update server list */
+ if (IsServer(local[i]))
+ {
+ delfrom_fdlist(j,&busycli_fdlist);
+ delfrom_fdlist(j,&serv_fdlist);
+ addto_fdlist(i,&busycli_fdlist);
+ addto_fdlist(i,&serv_fdlist);
+ }
+ if (IsAnOper(local[i])) {
+ delfrom_fdlist(j, &busycli_fdlist);
+ delfrom_fdlist(j, &oper_fdlist);
+ addto_fdlist(i, &busycli_fdlist);
+ addto_fdlist(i, &oper_fdlist);
+ }
+#endif
+#ifndef _WIN32
+ (void)close(j);
+#else
+ (void)closesocket(j);
+#endif
+ while (!local[highest_fd])
+ highest_fd--;
+ }
+ return;
+}
+
+/*
+** set_sock_opts
+*/
+static void set_sock_opts(fd, cptr)
+int fd;
+aClient *cptr;
+{
+ int opt;
+#ifdef SO_REUSEADDR
+ opt = 1;
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (OPT_TYPE *)&opt, sizeof(opt)) < 0)
+ report_error("setsockopt(SO_REUSEADDR) %s:%s", cptr);
+#endif
+#if defined(SO_DEBUG) && defined(DEBUGMODE) && 0
+/* Solaris with SO_DEBUG writes to syslog by default */
+#if !defined(SOL20) || defined(USE_SYSLOG)
+ opt = 1;
+ if (setsockopt(fd, SOL_SOCKET, SO_DEBUG, (OPT_TYPE *)&opt, sizeof(opt)) < 0)
+ report_error("setsockopt(SO_DEBUG) %s:%s", cptr);
+#endif /* SOL20 */
+#endif
+#if defined(SO_USELOOPBACK) && !defined(_WIN32)
+ opt = 1;
+ if (setsockopt(fd, SOL_SOCKET, SO_USELOOPBACK, (OPT_TYPE *)&opt, sizeof(opt)) < 0)
+ report_error("setsockopt(SO_USELOOPBACK) %s:%s", cptr);
+#endif
+#ifdef SO_RCVBUF
+ opt = 8192;
+ if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (OPT_TYPE *)&opt, sizeof(opt)) < 0)
+ report_error("setsockopt(SO_RCVBUF) %s:%s", cptr);
+#endif
+#ifdef SO_SNDBUF
+# ifdef _SEQUENT_
+/* seems that Sequent freezes up if the receving buffer is a different size
+ * to the sending buffer (maybe a tcp window problem too).
+ */
+ opt = 8192;
+# else
+ opt = 8192;
+# endif
+ if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (OPT_TYPE *)&opt, sizeof(opt)) < 0)
+ report_error("setsockopt(SO_SNDBUF) %s:%s", cptr);
+#endif
+#if defined(IP_OPTIONS) && defined(IPPROTO_IP) && !defined(_WIN32)
+ {
+ char *s = readbuf, *t = readbuf + sizeof(readbuf) / 2;
+
+ opt = sizeof(readbuf) / 8;
+ if (getsockopt(fd, IPPROTO_IP, IP_OPTIONS, (OPT_TYPE *)t, &opt) < 0)
+ report_error("getsockopt(IP_OPTIONS) %s:%s", cptr);
+ else if (opt > 0 && opt != sizeof(readbuf) / 8)
+ {
+ for (*readbuf = '\0'; opt > 0; opt--, s+= 3)
+ (void)sprintf(s, "%02.2x:", *t++);
+ *s = '\0';
+ sendto_ops("Connection %s using IP opts: (%s)",
+ get_client_name(cptr, TRUE), readbuf);
+ }
+ if (setsockopt(fd, IPPROTO_IP, IP_OPTIONS, (OPT_TYPE *)NULL, 0) < 0)
+ report_error("setsockopt(IP_OPTIONS) %s:%s", cptr);
+ }
+#endif
+}
+
+
+int get_sockerr(cptr)
+aClient *cptr;
+{
+#ifndef _WIN32
+ int errtmp = errno, err = 0, len = sizeof(err);
+#else
+ int errtmp = WSAGetLastError(), err = 0, len = sizeof(err);
+#endif
+#ifdef SO_ERROR
+ if (cptr->fd >= 0)
+ if (!getsockopt(cptr->fd, SOL_SOCKET, SO_ERROR, (OPT_TYPE *)&err, &len))
+ if (err)
+ errtmp = err;
+#endif
+ return errtmp;
+}
+
+/*
+** set_non_blocking
+** Set the client connection into non-blocking mode. If your
+** system doesn't support this, you can make this a dummy
+** function (and get all the old problems that plagued the
+** blocking version of IRC--not a problem if you are a
+** lightly loaded node...)
+*/
+void set_non_blocking(fd, cptr)
+int fd;
+aClient *cptr;
+{
+ int res, nonb = 0;
+
+ /*
+ ** NOTE: consult ALL your relevant manual pages *BEFORE* changing
+ ** these ioctl's. There are quite a few variations on them,
+ ** as can be seen by the PCS one. They are *NOT* all the same.
+ ** Heed this well. - Avalon.
+ */
+#ifdef NBLOCK_POSIX
+ nonb |= O_NONBLOCK;
+#endif
+#ifdef NBLOCK_BSD
+ nonb |= O_NDELAY;
+#endif
+#ifdef NBLOCK_SYSV
+ /* This portion of code might also apply to NeXT. -LynX */
+ res = 1;
+
+ if (ioctl (fd, FIONBIO, &res) < 0)
+ report_error("ioctl(fd,FIONBIO) failed for %s:%s", cptr);
+#else
+# if !defined(_WIN32)
+ if ((res = fcntl(fd, F_GETFL, 0)) == -1)
+ report_error("fcntl(fd, F_GETFL) failed for %s:%s",cptr);
+ else if (fcntl(fd, F_SETFL, res | nonb) == -1)
+ report_error("fcntl(fd, F_SETL, nonb) failed for %s:%s",cptr);
+# else
+ nonb=1;
+ if (ioctlsocket(fd, FIONBIO, &nonb) < 0)
+ report_error("ioctlsocket(fd,FIONBIO) failed for %s:%s", cptr);
+# endif
+#endif
+ return;
+}
+
+/*
+ * Creates a client which has just connected to us on the given fd.
+ * The sockhost field is initialized with the ip# of the host.
+ * The client is added to the linked list of clients but isnt added to any
+ * hash tables yuet since it doesnt have a name.
+ */
+aClient *add_connection(cptr, fd)
+aClient *cptr;
+int fd;
+{
+ Link lin;
+ aClient *acptr;
+ aConfItem *aconf = NULL;
+ char *message[20];
+ acptr = make_client(NULL, &me);
+
+ if (cptr != &me)
+ aconf = cptr->confs->value.aconf;
+ /* Removed preliminary access check. Full check is performed in
+ * m_server and m_user instead. Also connection time out help to
+ * get rid of unwanted connections.
+ */
+#ifndef _WIN32
+ if (isatty(fd)) /* If descriptor is a tty, special checking... */
+#else
+ if (0)
+#endif
+ get_sockhost(acptr, cptr->sockhost);
+ else
+ {
+ Reg1 char *s, *t;
+ struct sockaddr_in addr;
+ int len = sizeof(struct sockaddr_in);
+
+ if (getpeername(fd, (struct sockaddr *) &addr, &len) == -1)
+ {
+ report_error("Failed in connecting to %s :%s", cptr);
+add_con_refuse:
+ ircstp->is_ref++;
+ acptr->fd = -2;
+ free_client(acptr);
+#ifndef _WIN32
+ (void)close(fd);
+#else
+ (void)closesocket(fd);
+#endif
+ return NULL;
+ }
+ /* don't want to add "Failed in connecting to" here.. */
+ if (aconf && IsIllegal(aconf))
+ goto add_con_refuse;
+ /* Copy ascii address to 'sockhost' just in case. Then we
+ * have something valid to put into error messages...
+ */
+ get_sockhost(acptr, (char *)inetntoa((char *)&addr.sin_addr));
+ bcopy ((char *)&addr.sin_addr, (char *)&acptr->ip,
+ sizeof(struct in_addr));
+ /* Check for zaps -- Barubary */
+ if (find_zap(acptr, 0))
+ {
+ set_non_blocking(fd, acptr);
+ set_sock_opts(fd, acptr);
+ send(fd, zlinebuf, strlen(zlinebuf), 0);
+ goto add_con_refuse;
+ }
+ else
+ if (find_tkline_match(acptr, 2) != -1)
+ {
+ set_non_blocking(fd, acptr);
+ set_sock_opts(fd, acptr);
+ send(fd, zlinebuf, strlen(zlinebuf), 0);
+ goto add_con_refuse;
+ }
+#ifdef TESTNET
+ acptr->port = ntohs(addr.sin_port) - 10000;
+#else
+ acptr->port = ntohs(addr.sin_port);
+#endif
+#if 0
+ /*
+ * Some genious along the lines of ircd took out the code
+ * where ircd loads the IP mask from the P:Lines, so this
+ * is useless untill that's added back. :)
+ */
+ /*
+ * Check that this socket (client) is allowed to accept
+ * connections from this IP#.
+ */
+ for (s = (char *)&cptr->ip, t = (char *)&acptr->ip, len = 4;
+ len > 0; len--, s++, t++)
+ {
+ if (!*s)
+ continue;
+ if (*s != *t)
+ break;
+ }
+
+ if (len)
+ goto add_con_refuse;
+#endif
+#ifdef SHOWCONNECTINFO
+#ifndef _WIN32
+ write(fd, REPORT_DO_DNS, R_do_dns);
+#else
+ send(fd, REPORT_DO_DNS, R_do_dns, 0);
+#endif
+#endif
+ lin.flags = ASYNC_CLIENT;
+ lin.value.cptr = acptr;
+ Debug((DEBUG_DNS, "lookup %s",
+ inetntoa((char *)&addr.sin_addr)));
+ acptr->hostp = gethost_byaddr((char *)&acptr->ip, &lin);
+ if (!acptr->hostp)
+ SetDNS(acptr);
+#ifdef SHOWCONNECTINFO
+ else
+#ifndef _WIN32
+ write(fd, REPORT_FIN_DNSC, R_fin_dnsc);
+#else
+ send(fd, REPORT_FIN_DNSC, R_fin_dnsc, 0);
+#endif
+
+#endif
+ nextdnscheck = 1;
+ }
+
+ if (aconf)
+ aconf->clients++;
+ acptr->fd = fd;
+ if (fd > highest_fd)
+ highest_fd = fd;
+ local[fd] = acptr;
+ acptr->acpt = cptr;
+ add_client_to_list(acptr);
+ set_non_blocking(acptr->fd, acptr);
+ set_sock_opts(acptr->fd, acptr);
+ start_auth(acptr);
+#ifdef SOCKSPORT
+ start_socks(acptr);
+#endif
+ return acptr;
+}
+
+/*
+** read_packet
+**
+** Read a 'packet' of data from a connection and process it. Read in 8k
+** chunks to give a better performance rating (for server connections).
+** Do some tricky stuff for client connections to make sure they don't do
+** any flooding >:-) -avalon
+*/
+static int read_packet(cptr, rfd)
+Reg1 aClient *cptr;
+fd_set *rfd;
+{
+ Reg1 int dolen = 0, length = 0, done;
+ time_t now = TStime();
+
+ if (FD_ISSET(cptr->fd, rfd) &&
+ !(IsPerson(cptr) && DBufLength(&cptr->recvQ) > 6090))
+ {
+#ifndef _WIN32
+ errno = 0;
+#else
+ WSASetLastError(0);
+#endif
+ length = recv(cptr->fd, readbuf, sizeof(readbuf), 0);
+
+ cptr->lasttime = now;
+ if (cptr->lasttime > cptr->since)
+ cptr->since = cptr->lasttime;
+ cptr->flags &= ~(FLAGS_PINGSENT|FLAGS_NONL);
+ /*
+ * If not ready, fake it so it isnt closed
+ */
+ if (length == -1 &&
+#ifndef _WIN32
+ ((errno == EWOULDBLOCK) || (errno == EAGAIN)))
+#else
+ (WSAGetLastError() == WSAEWOULDBLOCK))
+#endif
+ return 1;
+ if (length <= 0)
+ return length;
+ }
+
+ /*
+ ** For server connections, we process as many as we can without
+ ** worrying about the time of day or anything :)
+ */
+ if (IsServer(cptr) || IsConnecting(cptr) || IsHandshake(cptr) ||
+ IsService(cptr))
+ {
+ if (length > 0)
+ if ((done = dopacket(cptr, readbuf, length)))
+ return done;
+ }
+ else
+ {
+ /*
+ ** Before we even think of parsing what we just read, stick
+ ** it on the end of the receive queue and do it when its
+ ** turn comes around.
+ */
+ if (dbuf_put(&cptr->recvQ, readbuf, length) < 0)
+ return exit_client(cptr, cptr, cptr, "dbuf_put fail");
+
+ if (IsPerson(cptr) &&
+ DBufLength(&cptr->recvQ) > CLIENT_FLOOD)
+ {
+ sendto_umode(UMODE_FLOOD|UMODE_OPER,
+ "*** Flood -- %s!%s@%s (%d) exceeds %d recvQ",
+ cptr->name[0] ? cptr->name : "*",
+ cptr->user ? cptr->user->username : "*",
+ cptr->user ? cptr->user->realhost : "*",
+ DBufLength(&cptr->recvQ), CLIENT_FLOOD);
+ return exit_client(cptr, cptr, cptr, "Excess Flood");
+ }
+
+ while (DBufLength(&cptr->recvQ) && !NoNewLine(cptr) &&
+ ((cptr->status < STAT_UNKNOWN) ||
+ (cptr->since - now < 10)))
+ {
+ /*
+ ** If it has become registered as a Service or Server
+ ** then skip the per-message parsing below.
+ */
+ if (IsService(cptr) || IsServer(cptr))
+ {
+ dolen = dbuf_get(&cptr->recvQ, readbuf,
+ sizeof(readbuf));
+ if (dolen <= 0)
+ break;
+ if ((done = dopacket(cptr, readbuf, dolen)))
+ return done;
+ break;
+ }
+ dolen = dbuf_getmsg(&cptr->recvQ, readbuf,
+ sizeof(readbuf));
+ /*
+ ** Devious looking...whats it do ? well..if a client
+ ** sends a *long* message without any CR or LF, then
+ ** dbuf_getmsg fails and we pull it out using this
+ ** loop which just gets the next 512 bytes and then
+ ** deletes the rest of the buffer contents.
+ ** -avalon
+ */
+ while (dolen <= 0)
+ {
+ if (dolen < 0)
+ return exit_client(cptr, cptr, cptr,
+ "dbuf_getmsg fail");
+ if (DBufLength(&cptr->recvQ) < 510)
+ {
+ cptr->flags |= FLAGS_NONL;
+ break;
+ }
+ dolen = dbuf_get(&cptr->recvQ, readbuf, 511);
+ if (dolen > 0 && DBufLength(&cptr->recvQ))
+ DBufClear(&cptr->recvQ);
+ }
+
+ if (dolen > 0 &&
+ (dopacket(cptr, readbuf, dolen) == FLUSH_BUFFER))
+ return FLUSH_BUFFER;
+ }
+ }
+ return 1;
+}
+
+
+/*
+ * Check all connections for new connections and input data that is to be
+ * processed. Also check for connections with data queued and whether we can
+ * write it out.
+ */
+#ifdef NO_FDLIST
+int read_message(delay)
+#else
+int read_message(delay, listp)
+#endif
+time_t delay; /* Don't ever use ZERO here, unless you mean to poll and then
+ * you have to have sleep/wait somewhere else in the code.--msa
+ */
+#ifndef NO_FDLIST
+fdlist *listp;
+#endif
+{
+ Reg1 aClient *cptr;
+ Reg2 int nfds;
+ struct timeval wait;
+#ifdef pyr
+ struct timeval nowt;
+ u_long us;
+#endif
+#ifndef _WIN32
+ fd_set read_set, write_set;
+#else
+ fd_set read_set, write_set, excpt_set;
+#endif
+ register int j;
+ time_t delay2 = delay, now;
+ u_long usec = 0;
+ int res, length, fd, i;
+ int auth = 0;
+#ifdef SOCKSPORT
+ int socks = 0;
+#endif
+ int sockerr;
+ static time_t last_tune = 0;
+
+#ifndef NO_FDLIST
+ /* if it is called with NULL we check all active fd's */
+ if (!listp)
+ {
+ listp = &default_fdlist;
+ listp->last_entry = highest_fd+1; /* remember the 0th entry isnt used */
+ }
+#endif
+
+ if ((time(NULL) - last_tune) > 300)
+ {
+ last_tune = time(NULL);
+ save_tunefile();
+ }
+#ifdef pyr
+ (void) gettimeofday(&nowt, NULL);
+ now = nowt.tv_sec;
+#else
+ now = TStime();
+#endif
+
+ for (res = 0;;)
+ {
+ FD_ZERO(&read_set);
+ FD_ZERO(&write_set);
+#ifdef _WIN32
+ FD_ZERO(&excpt_set);
+#endif
+
+#ifdef NO_FDLIST
+ for (i = highest_fd; i >= 0; i--)
+#else
+ for (i=listp->entry[j=1];j<=listp->last_entry;
+ i=listp->entry[++j])
+#endif
+ {
+ if (!(cptr = local[i]))
+ continue;
+ if (IsLog(cptr))
+ continue;
+#ifdef SOCKSPORT
+ if (DoingSocks(cptr))
+ {
+ socks++;
+ FD_SET(cptr->socksfd, &read_set);
+#ifdef _WIN32
+ FD_SET(cptr->socksfd, &excpt_set);
+#endif
+ if (cptr->flags & FLAGS_WRSOCKS)
+ FD_SET(cptr->socksfd, &write_set);
+ }
+#endif /* SOCKSPORT */
+
+ if (DoingAuth(cptr))
+ {
+ auth++;
+ Debug((DEBUG_NOTICE,"auth on %x %d", cptr, i));
+ FD_SET(cptr->authfd, &read_set);
+#ifdef _WIN32
+ FD_SET(cptr->authfd, &excpt_set);
+#endif
+ if (cptr->flags & FLAGS_WRAUTH)
+ FD_SET(cptr->authfd, &write_set);
+ }
+ if (DoingDNS(cptr) || DoingAuth(cptr)
+#ifdef SOCKSPORT
+ || DoingSocks(cptr)
+#endif
+ )
+ continue;
+ if (IsMe(cptr) && IsListening(cptr))
+ {
+ FD_SET(i, &read_set);
+ }
+ else if (!IsMe(cptr))
+ {
+ if (DBufLength(&cptr->recvQ) && delay2 > 2)
+ delay2 = 1;
+ if (DBufLength(&cptr->recvQ) < 4088)
+ FD_SET(i, &read_set);
+ }
+
+ if (DBufLength(&cptr->sendQ) || IsConnecting(cptr) ||
+ (DoList(cptr) && IsSendable(cptr)))
+#ifndef pyr
+ FD_SET(i, &write_set);
+#else
+ {
+ if (!IsBlocked(cptr))
+ FD_SET(i, &write_set);
+ else
+ delay2 = 0, usec = 500000;
+ }
+ if (now - cptr->lw.tv_sec &&
+ nowt.tv_usec - cptr->lw.tv_usec < 0)
+ us = 1000000;
+ else
+ us = 0;
+ us += nowt.tv_usec;
+ if (us - cptr->lw.tv_usec > 500000)
+ ClearBlocked(cptr);
+#endif
+ }
+
+#ifdef SOCKSPORT
+ if (me.socksfd >= 0)
+ FD_SET(me.socksfd, &read_set);
+#endif
+ if (udpfd >= 0)
+ FD_SET(udpfd, &read_set);
+#ifndef _WIN32
+ if (resfd >= 0)
+ FD_SET(resfd, &read_set);
+#endif
+
+ wait.tv_sec = MIN(delay2, delay);
+ wait.tv_usec = usec;
+#ifdef HPUX
+ nfds = select(FD_SETSIZE, (int *)&read_set, (int *)&write_set,
+ 0, &wait);
+#else
+# ifndef _WIN32
+ nfds = select(FD_SETSIZE, &read_set, &write_set, 0, &wait);
+# else
+ nfds = select(FD_SETSIZE, &read_set, &write_set, &excpt_set, &wait);
+# endif
+#endif
+#ifndef _WIN32
+ if (nfds == -1 && errno == EINTR)
+#else
+ if (nfds == -1 && WSAGetLastError() == WSAEINTR)
+#endif
+ return -1;
+ else if (nfds >= 0)
+ break;
+ report_error("select %s:%s", &me);
+ res++;
+ if (res > 5)
+ restart("too many select errors");
+#ifndef _WIN32
+ sleep(10);
+#else
+ Sleep(10);
+#endif
+ }
+#ifdef SOCKSPORT
+ if (me.socksfd >= 0 && FD_ISSET(me.socksfd, &read_set))
+ {
+ int tmpsock;
+
+ tmpsock = accept(me.socksfd, NULL, NULL);
+ if(tmpsock >= 0)
+#ifdef _WIN32
+ closesocket(tmpsock);
+#else
+ close(tmpsock);
+#endif /* _WIN32 */
+ FD_CLR(me.socksfd, &read_set);
+ }
+#endif /* SOCKSPORT */
+
+ if (udpfd >= 0 && FD_ISSET(udpfd, &read_set))
+ {
+ polludp();
+ nfds--;
+ FD_CLR(udpfd, &read_set);
+ }
+#ifndef _WIN32
+ if (resfd >= 0 && FD_ISSET(resfd, &read_set))
+ {
+ do_dns_async();
+ nfds--;
+ FD_CLR(resfd, &read_set);
+ }
+#endif
+ /*
+ * Check fd sets for the auth fd's (if set and valid!) first
+ * because these can not be processed using the normal loops below.
+ * -avalon
+ */
+#ifdef NO_FDLIST
+ for (i = highest_fd; (auth > 0) && (i >= 0); i--)
+#else
+ for (i=listp->entry[j=1];j <= listp->last_entry;
+ i=listp->entry[++j])
+#endif
+ {
+ if (!(cptr = local[i]))
+ continue;
+ if (cptr->authfd < 0)
+ continue;
+ auth--;
+#ifdef _WIN32
+ /*
+ * Because of the way windows uses select(), we have to use
+ * the exception FD set to find out when a connection is
+ * refused. ie Auth ports and /connect's. -Cabal95
+ */
+ if (FD_ISSET(cptr->authfd, &excpt_set))
+ {
+ int err, len = sizeof(err);
+
+ if (getsockopt(cptr->authfd, SOL_SOCKET, SO_ERROR,
+ (OPT_TYPE *)&err, &len) || err)
+ {
+ ircstp->is_abad++;
+ closesocket(cptr->authfd);
+ if (cptr->authfd == highest_fd)
+ while (!local[highest_fd])
+ highest_fd--;
+ cptr->authfd = -1;
+ cptr->flags &= ~(FLAGS_AUTH|FLAGS_WRAUTH);
+ if (!DoingDNS(cptr))
+ SetAccess(cptr);
+ if (nfds > 0)
+ nfds--;
+ continue;
+ }
+ }
+#endif
+ if ((nfds > 0) && FD_ISSET(cptr->authfd, &write_set))
+ {
+ nfds--;
+ send_authports(cptr);
+ }
+ else if ((nfds > 0) && FD_ISSET(cptr->authfd, &read_set))
+ {
+ nfds--;
+ read_authports(cptr);
+ }
+ }
+#ifdef SOCKSPORT
+ /*
+ * I really hate to do this.. but another loop
+ * to check to see if we have any socks fd's.. - darkrot
+ */
+ for (i = highest_fd; (socks > 0) && (i >= 0); i--)
+ {
+ if (!(cptr = local[i]))
+ continue;
+ if (cptr->socksfd < 0 || IsMe(cptr))
+ continue;
+ socks--;
+#ifdef _WIN32
+ /*
+ * Because of the way windows uses select(), we have to use
+ * the exception FD set to find out when a connection is
+ * refused. ie Auth ports and /connect's. -Cabal95
+ */
+ if (FD_ISSET(cptr->socksfd, &excpt_set))
+ {
+ int err, len = sizeof(err);
+
+ if (getsockopt(cptr->socksfd, SOL_SOCKET, SO_ERROR,
+ (OPT_TYPE *)&err, &len) || err)
+ {
+ ircstp->is_abad++;
+ closesocket(cptr->socksfd);
+ if (cptr->socksfd == highest_fd)
+ while (!local[highest_fd])
+ highest_fd--;
+ cptr->socksfd = -1;
+ cptr->flags &= ~(FLAGS_SOCKS|FLAGS_WRSOCKS);
+ if (nfds > 0)
+ nfds--;
+ continue;
+ }
+ }
+#endif /* _WIN32 */
+ if ((nfds > 0) && FD_ISSET(cptr->socksfd, &write_set))
+ {
+ nfds--;
+ send_socksquery(cptr);
+ }
+ else if ((nfds > 0) && FD_ISSET(cptr->socksfd, &read_set))
+ {
+ nfds--;
+ read_socks(cptr);
+ }
+ }
+#endif /* SOCKSPORT */
+
+ for (i = highest_fd; i >= 0; i--)
+ if ((cptr = local[i]) && FD_ISSET(i, &read_set) &&
+ IsListening(cptr))
+ {
+ FD_CLR(i, &read_set);
+ nfds--;
+ cptr->lasttime = TStime();
+ /*
+ ** There may be many reasons for error return, but
+ ** in otherwise correctly working environment the
+ ** probable cause is running out of file descriptors
+ ** (EMFILE, ENFILE or others?). The man pages for
+ ** accept don't seem to list these as possible,
+ ** although it's obvious that it may happen here.
+ ** Thus no specific errors are tested at this
+ ** point, just assume that connections cannot
+ ** be accepted until some old is closed first.
+ */
+ if ((fd = accept(i, NULL, NULL)) < 0)
+ {
+ report_error("Cannot accept connections %s:%s",
+ cptr);
+ break;
+ }
+ ircstp->is_ac++;
+ if (fd >= MAXCLIENTS)
+ {
+ ircstp->is_ref++;
+ sendto_ops("All connections in use. (%s)",
+ get_client_name(cptr, TRUE));
+ (void)send(fd,
+ "ERROR :All connections in use\r\n",
+ 32, 0);
+#ifndef _WIN32
+ (void)close(fd);
+#else
+ (void)closesocket(fd);
+#endif
+ break;
+ }
+ /*
+ * Use of add_connection (which never fails :) meLazy
+ */
+ (void)add_connection(cptr, fd);
+ nextping = TStime();
+ if (!cptr->acpt)
+ cptr->acpt = &me;
+ }
+
+ for (i = highest_fd; i >= 0; i--)
+ {
+ if (!(cptr = local[i]) || IsMe(cptr))
+ continue;
+ if (FD_ISSET(i, &write_set))
+ {
+ int write_err = 0;
+ nfds--;
+ /*
+ ** ...room for writing, empty some queue then...
+ */
+ ClearBlocked(cptr);
+ if (IsConnecting(cptr))
+ write_err = completed_connection(cptr);
+ if (!write_err) {
+ if (DoList(cptr) && IsSendable(cptr))
+ send_list(cptr, 32);
+ (void)send_queued(cptr);
+ }
+
+ if (IsDead(cptr) || write_err)
+ {
+deadsocket:
+ if (FD_ISSET(i, &read_set))
+ {
+ nfds--;
+ FD_CLR(i, &read_set);
+ }
+ (void)exit_client(cptr, cptr, &me,
+ ((sockerr = get_sockerr(cptr))
+ ? strerror(sockerr)
+ : "Client exited"));
+ continue;
+ }
+ }
+ length = 1; /* for fall through case */
+ if (!NoNewLine(cptr) || FD_ISSET(i, &read_set))
+ length = read_packet(cptr, &read_set);
+ if (length > 0)
+ flush_connections(i);
+ if ((length != FLUSH_BUFFER) && IsDead(cptr))
+ goto deadsocket;
+ if (!FD_ISSET(i, &read_set) && length > 0)
+ continue;
+ nfds--;
+ readcalls++;
+ if (length > 0)
+ continue;
+
+ /*
+ ** ...hmm, with non-blocking sockets we might get
+ ** here from quite valid reasons, although.. why
+ ** would select report "data available" when there
+ ** wasn't... so, this must be an error anyway... --msa
+ ** actually, EOF occurs when read() returns 0 and
+ ** in due course, select() returns that fd as ready
+ ** for reading even though it ends up being an EOF. -avalon
+ */
+#ifndef _WIN32
+ Debug((DEBUG_ERROR, "READ ERROR: fd = %d %d %d",
+ i, errno, length));
+#else
+ Debug((DEBUG_ERROR, "READ ERROR: fd = %d %d %d",
+ i, WSAGetLastError(), length));
+#endif
+
+ /*
+ ** NOTE: if length == -2 then cptr has already been freed!
+ */
+ if (length != -2 && (IsServer(cptr) || IsHandshake(cptr)))
+ {
+ if (length == 0) {
+ sendto_locfailops("Server %s closed the connection",
+ get_client_name(cptr,FALSE));
+ sendto_serv_butone(&me,
+ ":%s GLOBOPS :Server %s closed the connection",
+ me.name, get_client_name(cptr,FALSE));
+ }
+ else
+ report_error("Lost connection to %s:%s",
+ cptr);
+ }
+ if (length != FLUSH_BUFFER)
+ (void)exit_client(cptr, cptr, &me,
+ ((sockerr = get_sockerr(cptr))
+ ? strerror(sockerr)
+ : "Client exited"));
+ }
+ return 0;
+}
+
+/*
+ * connect_server
+ */
+int connect_server(aconf, by, hp)
+aConfItem *aconf;
+aClient *by;
+struct hostent *hp;
+{
+ Reg1 struct sockaddr *svp;
+ Reg2 aClient *cptr, *c2ptr;
+ Reg3 char *s;
+ int errtmp, len;
+
+ Debug((DEBUG_NOTICE,"Connect to %s[%s] @%s",
+ aconf->name, aconf->host, inetntoa((char *)&aconf->ipnum)));
+
+ if ((c2ptr = find_server(aconf->name, NULL)))
+ {
+ sendto_ops("Server %s already present from %s",
+ aconf->name, get_client_name(c2ptr, TRUE));
+ if (by && IsPerson(by) && !MyClient(by))
+ sendto_one(by,
+ ":%s NOTICE %s :Server %s already present from %s",
+ me.name, by->name, aconf->name,
+ get_client_name(c2ptr, TRUE));
+ return -1;
+ }
+
+ /*
+ * If we dont know the IP# for this host and itis a hostname and
+ * not a ip# string, then try and find the appropriate host record.
+ */
+ if ( ( !aconf->ipnum.s_addr )
+ )
+ {
+ Link lin;
+
+ lin.flags = ASYNC_CONNECT;
+ lin.value.aconf = aconf;
+ nextdnscheck = 1;
+ s = (char *)index(aconf->host, '@');
+ s++; /* should NEVER be NULL */
+ if ((aconf->ipnum.s_addr = inet_addr(s)) == -1)
+ {
+ aconf->ipnum.s_addr = 0;
+ hp = gethost_byname(s, &lin);
+ Debug((DEBUG_NOTICE, "co_sv: hp %x ac %x na %s ho %s",
+ hp, aconf, aconf->name, s));
+ if (!hp)
+ return 0;
+ bcopy(hp->h_addr, (char *)&aconf->ipnum,
+ sizeof(struct in_addr));
+ }
+ }
+ cptr = make_client(NULL, NULL);
+ cptr->hostp = hp;
+ /*
+ * Copy these in so we have something for error detection.
+ */
+ strncpyzt(cptr->name, aconf->name, sizeof(cptr->name));
+ strncpyzt(cptr->sockhost, aconf->host, HOSTLEN+1);
+
+ svp = connect_inet(aconf, cptr, &len);
+
+ if (!svp)
+ {
+ if (cptr->fd != -1)
+#ifndef _WIN32
+ (void)close(cptr->fd);
+#else
+ (void)closesocket(cptr->fd);
+#endif
+ cptr->fd = -2;
+ free_client(cptr);
+ return -1;
+ }
+
+ set_non_blocking(cptr->fd, cptr);
+ set_sock_opts(cptr->fd, cptr);
+#ifndef _WIN32
+ (void)signal(SIGALRM, dummy);
+ if (connect(cptr->fd, svp, len) < 0 && errno != EINPROGRESS)
+ {
+ errtmp = errno; /* other system calls may eat errno */
+#else
+ if (connect(cptr->fd, svp, len) < 0 &&
+ WSAGetLastError() != WSAEINPROGRESS &&
+ WSAGetLastError() != WSAEWOULDBLOCK)
+ {
+ errtmp = WSAGetLastError(); /* other system calls may eat errno */
+#endif
+ report_error("Connect to host %s failed: %s",cptr);
+ if (by && IsPerson(by) && !MyClient(by))
+ sendto_one(by,
+ ":%s NOTICE %s :Connect to host %s failed.",
+ me.name, by->name, cptr);
+#ifndef _WIN32
+ (void)close(cptr->fd);
+#else
+ (void)closesocket(cptr->fd);
+#endif
+ cptr->fd = -2;
+ free_client(cptr);
+#ifndef _WIN32
+ errno = errtmp;
+ if (errno == EINTR)
+ errno = ETIMEDOUT;
+#else
+ WSASetLastError(errtmp);
+ if (errtmp == WSAEINTR)
+ WSASetLastError(WSAETIMEDOUT);
+#endif
+ return -1;
+ }
+
+ /* Attach config entries to client here rather than in
+ * completed_connection. This to avoid null pointer references
+ * when name returned by gethostbyaddr matches no C lines
+ * (could happen in 2.6.1a when host and servername differ).
+ * No need to check access and do gethostbyaddr calls.
+ * There must at least be one as we got here C line... meLazy
+ */
+ (void)attach_confs_host(cptr, aconf->host,
+ CONF_NOCONNECT_SERVER | CONF_CONNECT_SERVER);
+
+ if (!find_conf_host(cptr->confs, aconf->host, CONF_NOCONNECT_SERVER) ||
+ !find_conf_host(cptr->confs, aconf->host, CONF_CONNECT_SERVER))
+ {
+ sendto_ops("Host %s is not enabled for connecting:no C/N-line",
+ aconf->host);
+ if (by && IsPerson(by) && !MyClient(by))
+ sendto_one(by,
+ ":%s NOTICE %s :Connect to host %s failed.",
+ me.name, by->name, cptr);
+ det_confs_butmask(cptr, 0);
+#ifndef _WIN32
+ (void)close(cptr->fd);
+#else
+ (void)closesocket(cptr->fd);
+#endif
+ cptr->fd = -2;
+ free_client(cptr);
+ return(-1);
+ }
+ /*
+ ** The socket has been connected or connect is in progress.
+ */
+ (void)make_server(cptr);
+ if (by && IsPerson(by))
+ {
+ (void)strcpy(cptr->serv->by, by->name);
+ if (cptr->serv->user) free_user(cptr->serv->user, NULL);
+ cptr->serv->user = by->user;
+ by->user->refcnt++;
+ }
+ else
+ {
+ (void)strcpy(cptr->serv->by, "AutoConn.");
+ if (cptr->serv->user) free_user(cptr->serv->user, NULL);
+ cptr->serv->user = NULL;
+ }
+ (void)strcpy(cptr->serv->up, me.name);
+ if (cptr->fd > highest_fd)
+ highest_fd = cptr->fd;
+ local[cptr->fd] = cptr;
+ cptr->acpt = &me;
+ SetConnecting(cptr);
+
+ get_sockhost(cptr, aconf->host);
+ add_client_to_list(cptr);
+ nextping = TStime();
+
+ return 0;
+}
+
+static struct sockaddr *connect_inet(aconf, cptr, lenp)
+Reg1 aConfItem *aconf;
+Reg2 aClient *cptr;
+int *lenp;
+{
+ static struct sockaddr_in server;
+ Reg3 struct hostent *hp;
+
+ /*
+ * Might as well get sockhost from here, the connection is attempted
+ * with it so if it fails its useless.
+ */
+ cptr->fd = socket(AF_INET, SOCK_STREAM, 0);
+ if (cptr->fd >= MAXCLIENTS)
+ {
+ sendto_ops("No more connections allowed (%s)", cptr->name);
+ return NULL;
+ }
+ mysk.sin_port = 0;
+ bzero((char *)&server, sizeof(server));
+ server.sin_family = AF_INET;
+ get_sockhost(cptr, aconf->host);
+
+ if (cptr->fd == -1)
+ {
+ report_error("opening stream socket to server %s:%s", cptr);
+ return NULL;
+ }
+ get_sockhost(cptr, aconf->host);
+ server.sin_port = 0;
+ server.sin_addr = me.ip;
+ server.sin_family = AF_INET;
+ /*
+ ** Bind to a local IP# (with unknown port - let unix decide) so
+ ** we have some chance of knowing the IP# that gets used for a host
+ ** with more than one IP#.
+ */
+ /* No we don't bind it, not all OS's can handle connecting with
+ ** an already bound socket, different ip# might occur anyway
+ ** leading to a freezing select() on this side for some time.
+ ** I had this on my Linux 1.1.88 --Run
+ */
+ /* We do now. Virtual interface stuff --ns */
+ if (me.ip.s_addr != INADDR_ANY)
+ if (bind(cptr->fd, (struct sockaddr *)&server, sizeof(server)) == -1)
+ {
+ report_error("error binding to local port for %s:%s", cptr);
+ return NULL;
+ }
+ bzero((char *)&server, sizeof(server));
+ server.sin_family = AF_INET;
+ /*
+ * By this point we should know the IP# of the host listed in the
+ * conf line, whether as a result of the hostname lookup or the ip#
+ * being present instead. If we dont know it, then the connect fails.
+ */
+ if (isdigit(*aconf->host) && (aconf->ipnum.s_addr == -1))
+ aconf->ipnum.s_addr = inet_addr(aconf->host);
+ if (aconf->ipnum.s_addr == -1)
+ {
+ hp = cptr->hostp;
+ if (!hp)
+ {
+ Debug((DEBUG_FATAL, "%s: unknown host", aconf->host));
+ return NULL;
+ }
+ bcopy(hp->h_addr, (char *)&aconf->ipnum,
+ sizeof(struct in_addr));
+ }
+ bcopy((char *)&aconf->ipnum, (char *)&server.sin_addr,
+ sizeof(struct in_addr));
+ bcopy((char *)&aconf->ipnum, (char *)&cptr->ip,
+ sizeof(struct in_addr));
+#ifdef TESTNET
+ server.sin_port = htons(((aconf->port > 0) ? aconf->port : portnum)
+ + 10000);
+#else
+ server.sin_port = htons(((aconf->port > 0) ? aconf->port : portnum));
+#endif
+ *lenp = sizeof(server);
+ return (struct sockaddr *)&server;
+}
+
+/*
+ * The following section of code performs summoning of users to irc.
+ */
+#if defined(ENABLE_SUMMON) || defined(ENABLE_USERS)
+int utmp_open()
+{
+#ifdef O_NOCTTY
+ return (open(UTMP, O_RDONLY|O_NOCTTY));
+#else
+ return (open(UTMP, O_RDONLY));
+#endif
+}
+
+int utmp_read(fd, name, line, host, hlen)
+int fd, hlen;
+char *name, *line, *host;
+{
+ struct utmp ut;
+ while (read(fd, (char *)&ut, sizeof (struct utmp))
+ == sizeof (struct utmp))
+ {
+ strncpyzt(name, ut.ut_name, 9);
+ strncpyzt(line, ut.ut_line, 10);
+#ifdef USER_PROCESS
+# if defined(HPUX) || defined(AIX)
+ strncpyzt(host,(ut.ut_host[0]) ? (ut.ut_host) : me.name, 16);
+# else
+ strncpyzt(host, me.name, 9);
+# endif
+ if (ut.ut_type == USER_PROCESS)
+ return 0;
+#else
+ strncpyzt(host, (ut.ut_host[0]) ? (ut.ut_host) : me.name,
+ hlen);
+ if (ut.ut_name[0])
+ return 0;
+#endif
+ }
+ return -1;
+}
+
+int utmp_close(fd)
+int fd;
+{
+ return(close(fd));
+}
+
+#ifdef ENABLE_SUMMON
+void summon(who, namebuf, linebuf, chname)
+aClient *who;
+char *namebuf, *linebuf, *chname;
+{
+ static char wrerr[] = "NOTICE %s :Write error. Couldn't summon.";
+ int fd;
+ char line[120];
+ time_t now;
+ struct tm *tp;
+
+ now = TStime();
+ tp = localtime(&now);
+ if (strlen(linebuf) > (size_t) 9)
+ {
+ sendto_one(who,"NOTICE %s :Serious fault in SUMMON.",
+ who->name);
+ sendto_one(who,
+ "NOTICE %s :linebuf too long. Inform Administrator",
+ who->name);
+ return;
+ }
+ /*
+ * Following line added to prevent cracking to e.g. /dev/kmem if
+ * UTMP is for some silly reason writable to everyone...
+ */
+ if ((linebuf[0] != 't' || linebuf[1] != 't' || linebuf[2] != 'y')
+ && (linebuf[0] != 'c' || linebuf[1] != 'o' || linebuf[2] != 'n')
+#ifdef HPUX
+ && (linebuf[0] != 'p' || linebuf[1] != 't' || linebuf[2] != 'y' ||
+ linebuf[3] != '/')
+#endif
+ )
+ {
+ sendto_one(who,
+ "NOTICE %s :Looks like mere mortal souls are trying to",
+ who->name);
+ sendto_one(who,"NOTICE %s :enter the twilight zone... ",
+ who->name);
+ Debug((0, "%s (%s@%s, nick %s, %s)",
+ "FATAL: major security hack. Notify Administrator !",
+ who->username, who->user->host,
+ who->name, who->info));
+ return;
+ }
+
+ (void)sprintf(line,"/dev/%s", linebuf);
+#ifdef O_NOCTTY
+ if ((fd = open(line, O_WRONLY | O_NDELAY | O_NOCTTY)) == -1)
+#else
+ if ((fd = open(line, O_WRONLY | O_NDELAY)) == -1)
+#endif
+ {
+ sendto_one(who,
+ "NOTICE %s :%s seems to have disabled summoning...",
+ who->name, namebuf);
+ return;
+ }
+#if !defined(O_NOCTTY) && defined(TIOCNOTTY)
+ (void) ioctl(fd, TIOCNOTTY, NULL);
+#endif
+ (void)sprintf(line,"\n\r\007Message from IRC_Daemon@%s at %d:%02d\n\r",
+ me.name, tp->tm_hour, tp->tm_min);
+ if (write(fd, line, strlen(line)) != strlen(line))
+ {
+ (void)close(fd);
+ sendto_one(who, wrerr, who->name);
+ return;
+ }
+ (void)strcpy(line, "ircd: You are being summoned to Internet Relay \
+Chat on\n\r");
+ if (write(fd, line, strlen(line)) != strlen(line))
+ {
+ (void)close(fd);
+ sendto_one(who, wrerr, who->name);
+ return;
+ }
+ (void)sprintf(line, "ircd: Channel %s, by %s@%s (%s) %s\n\r",
+ chname, who->user->username, who->user->host, who->name, who->info);
+ if (write(fd, line, strlen(line)) != strlen(line))
+ {
+ (void)close(fd);
+ sendto_one(who, wrerr, who->name);
+ return;
+ }
+ (void)strcpy(line,"ircd: Respond with irc\n\r");
+ if (write(fd, line, strlen(line)) != strlen(line))
+ {
+ (void)close(fd);
+ sendto_one(who, wrerr, who->name);
+ return;
+ }
+ (void)close(fd);
+ sendto_one(who, rpl_str(RPL_SUMMONING), me.name, who->name, namebuf);
+ return;
+}
+# endif
+#endif /* ENABLE_SUMMON */
+
+/*
+** find the real hostname for the host running the server (or one which
+** matches the server's name) and its primary IP#. Hostname is stored
+** in the client structure passed as a pointer.
+*/
+void get_my_name(cptr, name, len)
+aClient *cptr;
+char *name;
+int len;
+{
+ static char tmp[HOSTLEN+1];
+ struct hostent *hp;
+ char *cname = cptr->name;
+
+ /*
+ ** Setup local socket structure to use for binding to.
+ */
+ bzero((char *)&mysk, sizeof(mysk));
+ mysk.sin_family = AF_INET;
+
+ if (gethostname(name,len) == -1)
+ return;
+ name[len] = '\0';
+
+ /* assume that a name containing '.' is a FQDN */
+ if (!index(name,'.'))
+ add_local_domain(name, len - strlen(name));
+
+ /*
+ ** If hostname gives another name than cname, then check if there is
+ ** a CNAME record for cname pointing to hostname. If so accept
+ ** cname as our name. meLazy
+ */
+ if (BadPtr(cname))
+ return;
+ if ((hp = gethostbyname(cname)) || (hp = gethostbyname(name)))
+ {
+ char *hname;
+ int i = 0;
+
+ for (hname = hp->h_name; hname; hname = hp->h_aliases[i++])
+ {
+ strncpyzt(tmp, hname, sizeof(tmp));
+ add_local_domain(tmp, sizeof(tmp) - strlen(tmp));
+
+ /*
+ ** Copy the matching name over and store the
+ ** 'primary' IP# as 'myip' which is used
+ ** later for making the right one is used
+ ** for connecting to other hosts.
+ */
+ if (!mycmp(me.name, tmp))
+ break;
+ }
+ if (mycmp(me.name, tmp))
+ strncpyzt(name, hp->h_name, len);
+ else
+ strncpyzt(name, tmp, len);
+ bcopy(hp->h_addr, (char *)&mysk.sin_addr,
+ sizeof(struct in_addr));
+ Debug((DEBUG_DEBUG,"local name is %s",
+ get_client_name(&me,TRUE)));
+ }
+ return;
+}
+
+/*
+** setup a UDP socket and listen for incoming packets
+*/
+int setup_ping()
+{
+ struct sockaddr_in from;
+ int on = 1;
+
+ bzero((char *)&from, sizeof(from));
+ from.sin_addr = me.ip;
+#ifdef TESTNET
+ from.sin_port = htons(17007);
+#else
+ from.sin_port = htons(7007);
+#endif
+ from.sin_family = AF_INET;
+
+ if ((udpfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
+ {
+#ifndef _WIN32
+ Debug((DEBUG_ERROR, "socket udp : %s", strerror(errno)));
+#else
+ Debug((DEBUG_ERROR, "socket udp : %s",
+ strerror(WSAGetLastError())));
+#endif
+ return -1;
+ }
+ if (setsockopt(udpfd, SOL_SOCKET, SO_REUSEADDR,
+ (OPT_TYPE *)&on, sizeof(on)) == -1)
+ {
+#ifdef USE_SYSLOG
+ syslog(LOG_ERR, "setsockopt udp fd %d : %m", udpfd);
+#endif
+#ifndef _WIN32
+ Debug((DEBUG_ERROR, "setsockopt so_reuseaddr : %s",
+ strerror(errno)));
+ (void)close(udpfd);
+#else
+ Debug((DEBUG_ERROR, "setsockopt so_reuseaddr : %s",
+ strerror(WSAGetLastError())));
+ (void)closesocket(udpfd);
+#endif
+ udpfd = -1;
+ return -1;
+ }
+ on = 0;
+ (void) setsockopt(udpfd, SOL_SOCKET, SO_BROADCAST,
+ (char *)&on, sizeof(on));
+ if (bind(udpfd, (struct sockaddr *)&from, sizeof(from))==-1)
+ {
+#ifdef USE_SYSLOG
+ syslog(LOG_ERR, "bind udp.%d fd %d : %m",
+ from.sin_port, udpfd);
+#endif
+#ifndef _WIN32
+ Debug((DEBUG_ERROR, "bind : %s", strerror(errno)));
+ (void)close(udpfd);
+#else
+ Debug((DEBUG_ERROR, "bind : %s", strerror(WSAGetLastError())));
+ (void)closesocket(udpfd);
+#endif
+ udpfd = -1;
+ return -1;
+ }
+#ifndef _WIN32
+ if (fcntl(udpfd, F_SETFL, FNDELAY)==-1)
+ {
+ Debug((DEBUG_ERROR, "fcntl fndelay : %s", strerror(errno)));
+ (void)close(udpfd);
+ udpfd = -1;
+ return -1;
+ }
+#endif
+ return udpfd;
+}
+
+/*
+ * max # of pings set to 15/sec.
+ */
+static void polludp()
+{
+ Reg1 char *s;
+ struct sockaddr_in from;
+ int n, fromlen = sizeof(from);
+ static time_t last = 0, now;
+ static int cnt = 0, mlen = 0;
+
+ /*
+ * find max length of data area of packet.
+ */
+ if (!mlen)
+ {
+ mlen = sizeof(readbuf) - strlen(me.name) - strlen(version);
+ mlen -= 6;
+ if (mlen < 0)
+ mlen = 0;
+ }
+ Debug((DEBUG_DEBUG,"udp poll"));
+
+ n = recvfrom(udpfd, readbuf, mlen, 0,
+ (struct sockaddr *)&from, &fromlen);
+ now = TStime();
+ if (now == last)
+ if (++cnt > 14)
+ return;
+ cnt = 0;
+ last = now;
+
+ if (n == -1)
+ {
+#ifndef _WIN32
+ if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
+#else
+ if ((WSAGetLastError() == WSAEWOULDBLOCK))
+#endif
+ return;
+ else
+ {
+ report_error("udp port recvfrom (%s): %s", &me);
+ return;
+ }
+ }
+ ircstp->is_udp++;
+ if (n < 19)
+ return;
+
+ s = readbuf + n;
+ /*
+ * attach my name and version for the reply
+ */
+ *readbuf |= 1;
+ (void)strcpy(s, me.name);
+ s += strlen(s)+1;
+ (void)strcpy(s, version);
+ s += strlen(s);
+ (void)sendto(udpfd, readbuf, s-readbuf, 0,
+ (struct sockaddr *)&from ,sizeof(from));
+ return;
+}
+
+/*
+ * do_dns_async
+ *
+ * Called when the fd returned from init_resolver() has been selected for
+ * reading.
+ */
+#ifndef _WIN32
+static void do_dns_async()
+#else
+void do_dns_async(id)
+int id;
+#endif
+{
+ static Link ln;
+ aClient *cptr;
+ aConfItem *aconf;
+ struct hostent *hp;
+
+ ln.flags = -1;
+#ifndef _WIN32
+ hp = get_res((char *)&ln);
+#else
+ hp = get_res((char *)&ln, id);
+#endif
+ while (hp != NULL)
+ {
+ Debug((DEBUG_DNS,"%#x = get_res(%d,%#x)",hp,ln.flags,ln.value.cptr));
+
+ switch (ln.flags)
+ {
+ case ASYNC_NONE :
+ /*
+ * no reply was processed that was outstanding or had a client
+ * still waiting.
+ */
+ break;
+ case ASYNC_CLIENT :
+ if ((cptr = ln.value.cptr))
+ {
+ del_queries((char *)cptr);
+#ifdef SHOWCONNECTINFO
+#ifndef _WIN32
+ write(cptr->fd, REPORT_FIN_DNS, R_fin_dns);
+#else
+ send(cptr->fd, REPORT_FIN_DNS, R_fin_dns, 0);
+#endif
+#endif
+ ClearDNS(cptr);
+ if (!DoingAuth(cptr))
+ SetAccess(cptr);
+ cptr->hostp = hp;
+ }
+ break;
+ case ASYNC_CONNECT :
+ aconf = ln.value.aconf;
+ if (hp && aconf)
+ {
+ bcopy(hp->h_addr, (char *)&aconf->ipnum,
+ sizeof(struct in_addr));
+ (void)connect_server(aconf, NULL, hp);
+ }
+ else
+ sendto_ops("Connect to %s failed: host lookup",
+ (aconf) ? aconf->host : "unknown");
+ break;
+ case ASYNC_CONF :
+ aconf = ln.value.aconf;
+ if (hp && aconf)
+ bcopy(hp->h_addr, (char *)&aconf->ipnum,
+ sizeof(struct in_addr));
+ break;
+ case ASYNC_SERVER :
+ cptr = ln.value.cptr;
+ del_queries((char *)cptr);
+ ClearDNS(cptr);
+ if (check_server(cptr, hp, NULL, NULL, 1))
+ (void)exit_client(cptr, cptr, &me,
+ "No Authorization");
+ break;
+ default :
+ break;
+ }
+
+ ln.flags = -1;
+#ifndef _WIN32
+ hp = get_res((char *)&ln);
+#else
+ hp = get_res((char *)&ln, id);
+#endif
+ } /* while (hp != NULL) */
+}
--- /dev/null
+/*
+ * IRC - Internet Relay Chat, ircd/s_conf.c
+ * Copyright (C) 1990 Jarkko Oikarinen and
+ * University of Oulu, Computing Center
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Changed all calls of check_pings so that only when a kline-related command
+ is used will a kline check occur -- Barubary */
+
+#define KLINE_RET_AKILL 3
+#define KLINE_RET_PERM 2
+#define KLINE_RET_DELOK 1
+#define KLINE_DEL_ERR 0
+
+
+#ifndef lint
+static char sccsid[] = "@(#)s_conf.c 2.56 02 Apr 1994 (C) 1988 University of Oulu, \
+Computing Center and Jarkko Oikarinen";
+#endif
+
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#include "numeric.h"
+#include "channel.h"
+#include <fcntl.h>
+#ifndef _WIN32
+#include <sys/socket.h>
+#include <sys/wait.h>
+#else
+#include <io.h>
+#endif
+#include <sys/stat.h>
+#ifdef __hpux
+#include "inet.h"
+#endif
+#if defined(PCS) || defined(AIX) || defined(DYNIXPTX) || defined(SVR3)
+#include <time.h>
+#endif
+
+ID_CVS("$Id$");
+ID_Notes("O:line flags in here");
+#include "h.h"
+
+static int check_time_interval PROTO((char *, char *));
+static int lookup_confhost PROTO((aConfItem *));
+static int is_comment PROTO((char *));
+static int advanced_check(char *, int);
+
+aSqlineItem *sqline = NULL;
+aConfItem *conf = NULL;
+extern char zlinebuf[];
+
+/*
+ * remove all conf entries from the client except those which match
+ * the status field mask.
+ */
+void det_confs_butmask(cptr, mask)
+aClient *cptr;
+int mask;
+{
+ Reg1 Link *tmp, *tmp2;
+
+ for (tmp = cptr->confs; tmp; tmp = tmp2)
+ {
+ tmp2 = tmp->next;
+ if ((tmp->value.aconf->status & mask) == 0)
+ (void)detach_conf(cptr, tmp->value.aconf);
+ }
+}
+
+/*
+ * Add a temporary line to the configuration
+ */
+void add_temp_conf(status, host, passwd, name, port, class, temp)
+unsigned int status;
+char *host;
+char *passwd;
+char *name;
+int port, class, temp; /* temp: 0 = perm 1 = temp 2 = akill */
+{
+ Reg1 aConfItem *aconf;
+
+ aconf = make_conf();
+
+ aconf->tmpconf = temp;
+ aconf->status = status;
+ if (host)
+ DupString(aconf->host, host);
+ if (passwd)
+ DupString(aconf->passwd, passwd);
+ if (name)
+ DupString(aconf->name, name);
+ aconf->port = port;
+ if (class)
+ Class(aconf) = find_class(class);
+ if (!find_temp_conf_entry(aconf, status)) {
+ aconf->next = conf;
+ conf = aconf;
+ aconf = NULL;
+ }
+
+ if (aconf)
+ free_conf(aconf);
+}
+
+/*
+ * delete a temporary conf line. *only* temporary conf lines may be deleted.
+ */
+int del_temp_conf(status, host, passwd, name, port, class, akill)
+unsigned int status, akill;
+char *host;
+char *passwd;
+char *name;
+int port, class;
+{
+ Reg1 aConfItem *aconf;
+ Reg3 aConfItem *bconf;
+ u_int mask;
+ u_int result=KLINE_DEL_ERR;
+
+ aconf = make_conf();
+
+ aconf->status=status;
+ if(host)
+ DupString(aconf->host, host);
+ if(passwd)
+ DupString(aconf->passwd, passwd);
+ if(name)
+ DupString(aconf->name, name);
+ aconf->port = port;
+ if(class)
+ Class(aconf) = find_class(class);
+ mask = status;
+ if (bconf=find_temp_conf_entry(aconf,mask)) /* only if non-null ptr */
+ {
+/* Completely skirt the akill error messages if akill is set to 1
+ * this allows RAKILL to do its thing without having to go through the
+ * error checkers. If it had to it would go kaplooey. --Russell
+ */
+ if (bconf->tmpconf == KLINE_PERM && (akill != 3))
+ result = KLINE_RET_PERM;/* Kline permanent */
+ else if (!akill && (bconf->tmpconf == KLINE_AKILL))
+ result = KLINE_RET_AKILL; /* Akill */
+ else if (akill && (bconf->tmpconf != KLINE_AKILL))
+ result = KLINE_RET_PERM;
+ else
+ {
+ bconf->status |= CONF_ILLEGAL; /* just mark illegal */
+ result = KLINE_RET_DELOK; /* same as deletion */
+ }
+
+ }
+ if (aconf)
+ free_conf(aconf);
+ return result; /* if it gets to here, it doesn't exist */
+}
+
+/*
+ * find the first (best) I line to attach.
+ */
+int attach_Iline(cptr, hp, sockhost)
+aClient *cptr;
+Reg2 struct hostent *hp;
+char *sockhost;
+{
+ Reg1 aConfItem *aconf;
+ Reg3 char *hname;
+ Reg4 int i;
+ static char uhost[HOSTLEN+USERLEN+3];
+ static char fullname[HOSTLEN+1];
+
+ for (aconf = conf; aconf; aconf = aconf->next)
+ {
+ if (aconf->status != CONF_CLIENT)
+ continue;
+ if (aconf->port && aconf->port != cptr->acpt->port)
+ continue;
+ if (!aconf->host || !aconf->name)
+ goto attach_iline;
+ if (hp)
+ for (i = 0, hname = hp->h_name; hname;
+ hname = hp->h_aliases[i++])
+ {
+ (void)strncpy(fullname, hname,
+ sizeof(fullname)-1);
+ add_local_domain(fullname,
+ HOSTLEN - strlen(fullname));
+ Debug((DEBUG_DNS, "a_il: %s->%s",
+ sockhost, fullname));
+ if (index(aconf->name, '@'))
+ {
+ (void)strcpy(uhost, cptr->username);
+ (void)strcat(uhost, "@");
+ }
+ else
+ *uhost = '\0';
+ (void)strncat(uhost, fullname,
+ sizeof(uhost) - strlen(uhost));
+ if (!match(aconf->name, uhost))
+ goto attach_iline;
+ }
+
+ if (index(aconf->host, '@'))
+ {
+ strncpyzt(uhost, cptr->username, sizeof(uhost));
+ (void)strcat(uhost, "@");
+ }
+ else
+ *uhost = '\0';
+ (void)strncat(uhost, sockhost, sizeof(uhost) - strlen(uhost));
+ if (!match(aconf->host, uhost))
+ goto attach_iline;
+ continue;
+attach_iline:
+ if (index(uhost, '@'))
+ cptr->flags |= FLAGS_DOID;
+ get_sockhost(cptr, uhost);
+
+ if (aconf->passwd && !strcmp(aconf->passwd, "ONE"))
+ {
+ for (i = highest_fd; i >= 0; i--)
+ if (local[i] && MyClient(local[i]) &&
+ local[i]->ip.s_addr == cptr->ip.s_addr)
+ return -1; /* Already got one with that ip# */
+ }
+
+ return attach_conf(cptr, aconf);
+ }
+ return -1;
+}
+
+/*
+ * Find the single N line and return pointer to it (from list).
+ * If more than one then return NULL pointer.
+ */
+aConfItem *count_cnlines(lp)
+Reg1 Link *lp;
+{
+ Reg1 aConfItem *aconf, *cline = NULL, *nline = NULL;
+
+ for (; lp; lp = lp->next)
+ {
+ aconf = lp->value.aconf;
+ if (!(aconf->status & CONF_SERVER_MASK))
+ continue;
+ if (aconf->status == CONF_CONNECT_SERVER && !cline)
+ cline = aconf;
+ else if (aconf->status == CONF_NOCONNECT_SERVER && !nline)
+ nline = aconf;
+ }
+ return nline;
+}
+
+/*
+** detach_conf
+** Disassociate configuration from the client.
+** Also removes a class from the list if marked for deleting.
+*/
+int detach_conf(cptr, aconf)
+aClient *cptr;
+aConfItem *aconf;
+{
+ Reg1 Link **lp, *tmp;
+
+ lp = &(cptr->confs);
+
+ while (*lp)
+ {
+ if ((*lp)->value.aconf == aconf)
+ {
+ if ((aconf) && (Class(aconf)))
+ {
+ if (aconf->status & CONF_CLIENT_MASK)
+ if (ConfLinks(aconf) > 0)
+ --ConfLinks(aconf);
+ if (ConfMaxLinks(aconf) == -1 &&
+ ConfLinks(aconf) == 0)
+ {
+ free_class(Class(aconf));
+ Class(aconf) = NULL;
+ }
+ }
+ if (aconf && !--aconf->clients && IsIllegal(aconf))
+ free_conf(aconf);
+ tmp = *lp;
+ *lp = tmp->next;
+ free_link(tmp);
+ return 0;
+ }
+ else
+ lp = &((*lp)->next);
+ }
+ return -1;
+}
+
+static int is_attached(aconf, cptr)
+aConfItem *aconf;
+aClient *cptr;
+{
+ Reg1 Link *lp;
+
+ for (lp = cptr->confs; lp; lp = lp->next)
+ if (lp->value.aconf == aconf)
+ break;
+
+ return (lp) ? 1 : 0;
+}
+
+/*
+** attach_conf
+** Associate a specific configuration entry to a *local*
+** client (this is the one which used in accepting the
+** connection). Note, that this automaticly changes the
+** attachment if there was an old one...
+*/
+int attach_conf(cptr, aconf)
+aConfItem *aconf;
+aClient *cptr;
+{
+ Reg1 Link *lp;
+
+ if (is_attached(aconf, cptr))
+ return 1;
+ if (IsIllegal(aconf))
+ return -1;
+ if ((aconf->status & (CONF_LOCOP | CONF_OPERATOR | CONF_CLIENT)) &&
+ aconf->clients >= ConfMaxLinks(aconf) && ConfMaxLinks(aconf) > 0)
+ return -3; /* Use this for printing error message */
+ lp = make_link();
+ lp->next = cptr->confs;
+ lp->value.aconf = aconf;
+ cptr->confs = lp;
+ aconf->clients++;
+ if (aconf->status & CONF_CLIENT_MASK)
+ ConfLinks(aconf)++;
+ return 0;
+}
+
+
+aConfItem *find_tline(char *host)
+ {
+ Reg1 aConfItem *aconf;
+
+ for (aconf = conf; aconf; aconf = aconf->next)
+ if (aconf->status & CONF_TLINE)
+ if (!match(aconf->host, host)) {
+ return(aconf);
+ }
+ return(NULL);
+ }
+
+aConfItem *find_socksexcept(char *host)
+ {
+ Reg1 aConfItem *aconf;
+
+ for (aconf = conf; aconf; aconf = aconf->next)
+ if (aconf->status & CONF_SOCKSEXCEPT)
+ if (!match(aconf->host, host)) {
+ return(aconf);
+ }
+ return(NULL);
+ }
+
+aConfItem *find_admin()
+ {
+ Reg1 aConfItem *aconf;
+
+ for (aconf = conf; aconf; aconf = aconf->next)
+ if (aconf->status & CONF_ADMIN)
+ break;
+ return(aconf);
+ }
+
+/* Find a DR_PASS line for the /DIE or /RESTART command
+ * Instead of returning the whole structure we return a
+ * char* which is the pass.
+ * Added December 28 1997 -- NikB
+ */
+char *find_diepass()
+ {
+ Reg1 aConfItem *aconf;
+
+ for (aconf = conf; aconf; aconf = aconf->next)
+ if (aconf->status & CONF_DRPASS)
+ return (aconf->host);
+
+ return NULL; /* Return NULL (We did not find any) */
+ }
+
+char *find_restartpass()
+ {
+ Reg1 aConfItem *aconf;
+
+ for (aconf = conf; aconf; aconf = aconf->next)
+ if (aconf->status & CONF_DRPASS)
+ return (aconf->passwd);
+
+ return NULL; /* Return NULL (We did not find any) */
+ }
+
+aConfItem *find_me()
+ {
+ Reg1 aConfItem *aconf;
+ for (aconf = conf; aconf; aconf = aconf->next)
+ if (aconf->status & CONF_ME)
+ break;
+
+ return (aconf);
+ }
+
+/*
+ * attach_confs
+ * Attach a CONF line to a client if the name passed matches that for
+ * the conf file (for non-C/N lines) or is an exact match (C/N lines
+ * only). The difference in behaviour is to stop C:*::* and N:*::*.
+ */
+aConfItem *attach_confs(cptr, name, statmask)
+aClient *cptr;
+char *name;
+int statmask;
+{
+ Reg1 aConfItem *tmp;
+ aConfItem *first = NULL;
+ int len = strlen(name);
+
+ if (!name || len > HOSTLEN)
+ return NULL;
+ for (tmp = conf; tmp; tmp = tmp->next)
+ {
+ if ((tmp->status & statmask) && !IsIllegal(tmp) &&
+ ((tmp->status & (CONF_SERVER_MASK|CONF_HUB)) == 0)
+ && tmp->name && !match(tmp->name, name))
+ {
+ if (!attach_conf(cptr, tmp) && !first)
+ first = tmp;
+ }
+ else if ((tmp->status & statmask) && !IsIllegal(tmp) &&
+ (tmp->status & (CONF_SERVER_MASK|CONF_HUB)) &&
+ tmp->name && !match(tmp->name, name))
+ {
+ if (!attach_conf(cptr, tmp) && !first)
+ first = tmp;
+ }
+ }
+ return (first);
+}
+
+/*
+ * Added for new access check meLazy
+ */
+aConfItem *attach_confs_host(cptr, host, statmask)
+aClient *cptr;
+char *host;
+int statmask;
+{
+ Reg1 aConfItem *tmp;
+ aConfItem *first = NULL;
+ int len = strlen(host);
+
+ if (!host || len > HOSTLEN)
+ return NULL;
+
+ for (tmp = conf; tmp; tmp = tmp->next)
+ {
+ if ((tmp->status & statmask) && !IsIllegal(tmp) &&
+ (tmp->status & CONF_SERVER_MASK) == 0 &&
+ (!tmp->host || match(tmp->host, host) == 0))
+ {
+ if (!attach_conf(cptr, tmp) && !first)
+ first = tmp;
+ }
+ else if ((tmp->status & statmask) && !IsIllegal(tmp) &&
+ (tmp->status & CONF_SERVER_MASK) &&
+ (tmp->host && mycmp(tmp->host, host) == 0))
+ {
+ if (!attach_conf(cptr, tmp) && !first)
+ first = tmp;
+ }
+ }
+ return (first);
+}
+
+/*
+ * find a conf entry which matches the hostname and has the same name.
+ */
+aConfItem *find_conf_exact(name, user, host, statmask)
+char *name, *host, *user;
+int statmask;
+{
+ Reg1 aConfItem *tmp;
+ char userhost[USERLEN+HOSTLEN+3];
+
+ (void)sprintf(userhost, "%s@%s", user, host);
+
+ for (tmp = conf; tmp; tmp = tmp->next)
+ {
+ if (!(tmp->status & statmask) || !tmp->name || !tmp->host ||
+ mycmp(tmp->name, name))
+ continue;
+ if (tmp->status & CONF_ILLEGAL)
+ continue;
+ /*
+ ** Accept if the *real* hostname (usually sockecthost)
+ ** socket host) matches *either* host or name field
+ ** of the configuration.
+ */
+ if (match(tmp->host, userhost))
+ continue;
+ if (tmp->status & (CONF_OPERATOR|CONF_LOCOP))
+ {
+ if (tmp->clients < MaxLinks(Class(tmp)))
+ return tmp;
+ else
+ continue;
+ }
+ else
+ return tmp;
+ }
+ return NULL;
+}
+
+aConfItem *find_conf_name(name, statmask)
+char *name;
+int statmask;
+{
+ Reg1 aConfItem *tmp;
+
+ for (tmp = conf; tmp; tmp = tmp->next)
+ {
+ /*
+ ** Accept if the *real* hostname (usually sockecthost)
+ ** matches *either* host or name field of the configuration.
+ */
+ if ((tmp->status & statmask) &&
+ (!tmp->name || match(tmp->name, name) == 0))
+ return tmp;
+ }
+ return NULL;
+}
+
+aConfItem *find_conf_servern(name)
+char *name;
+{
+ Reg1 aConfItem *tmp;
+
+ for (tmp = conf; tmp; tmp = tmp->next)
+ {
+ /*
+ ** Accept if the *real* hostname (usually sockecthost)
+ ** matches *either* host or name field of the configuration.
+ */
+ if ((tmp->status & CONF_NOCONNECT_SERVER) &&
+ (!tmp->name || match(tmp->name, name) == 0))
+ return tmp;
+ }
+ return NULL;
+}
+
+aConfItem *find_conf(lp, name, statmask)
+char *name;
+Link *lp;
+int statmask;
+{
+ Reg1 aConfItem *tmp;
+ int namelen = name ? strlen(name) : 0;
+
+ if (namelen > HOSTLEN)
+ return (aConfItem *) 0;
+
+ for (; lp; lp = lp->next)
+ {
+ tmp = lp->value.aconf;
+ if ((tmp->status & statmask) &&
+ (((tmp->status & (CONF_SERVER_MASK|CONF_HUB)) &&
+ tmp->name && !match(tmp->name, name)) ||
+ ((tmp->status & (CONF_SERVER_MASK|CONF_HUB)) == 0 &&
+ tmp->name && !match(tmp->name, name))))
+ return tmp;
+ }
+ return NULL;
+}
+
+/*
+ * Added for new access check meLazy
+ */
+aConfItem *find_conf_host(lp, host, statmask)
+Reg2 Link *lp;
+char *host;
+Reg3 int statmask;
+{
+ Reg1 aConfItem *tmp;
+ int hostlen = host ? strlen(host) : 0;
+
+ if (hostlen > HOSTLEN || BadPtr(host))
+ return (aConfItem *)NULL;
+ for (; lp; lp = lp->next)
+ {
+ tmp = lp->value.aconf;
+ if (tmp->status & statmask &&
+ (!(tmp->status & CONF_SERVER_MASK || tmp->host) ||
+ (tmp->host && !match(tmp->host, host))))
+ return tmp;
+ }
+ return NULL;
+}
+
+/* find_exception
+** find a virtual exception
+*/
+int find_exception(char *abba)
+{
+ aConfItem *tmp;
+
+ for (tmp=conf; tmp; tmp=tmp->next)
+ {}
+
+ return 0;
+}
+
+/*
+ * find_conf_ip
+ *
+ * Find a conf line using the IP# stored in it to search upon.
+ * Added 1/8/92 by Avalon.
+ */
+aConfItem *find_conf_ip(lp, ip, user, statmask)
+char *ip, *user;
+Link *lp;
+int statmask;
+{
+ Reg1 aConfItem *tmp;
+ Reg2 char *s;
+
+ for (; lp; lp = lp->next)
+ {
+ tmp = lp->value.aconf;
+ if (!(tmp->status & statmask))
+ continue;
+ s = index(tmp->host, '@');
+ *s = '\0';
+ if (match(tmp->host, user))
+ {
+ *s = '@';
+ continue;
+ }
+ *s = '@';
+ if (!bcmp((char *)&tmp->ipnum, ip, sizeof(struct in_addr)))
+ return tmp;
+ }
+ return NULL;
+}
+
+/*
+ * find_conf_entry
+ *
+ * - looks for a match on all given fields.
+ */
+aConfItem *find_conf_entry(aconf, mask)
+aConfItem *aconf;
+u_int mask;
+{
+ Reg1 aConfItem *bconf;
+
+ for (bconf = conf, mask &= ~CONF_ILLEGAL; bconf; bconf = bconf->next)
+ {
+ if (!(bconf->status & mask) || (bconf->port != aconf->port))
+ continue;
+
+ if ((BadPtr(bconf->host) && !BadPtr(aconf->host)) ||
+ (BadPtr(aconf->host) && !BadPtr(bconf->host)))
+ continue;
+ if (!BadPtr(bconf->host) && mycmp(bconf->host, aconf->host))
+ continue;
+
+ if ((BadPtr(bconf->passwd) && !BadPtr(aconf->passwd)) ||
+ (BadPtr(aconf->passwd) && !BadPtr(bconf->passwd)))
+ continue;
+ if (!BadPtr(bconf->passwd) && mycmp(bconf->passwd, "ONE") &&
+ mycmp(bconf->passwd, aconf->passwd))
+ continue;
+
+ if ((BadPtr(bconf->name) && !BadPtr(aconf->name)) ||
+ (BadPtr(aconf->name) && !BadPtr(bconf->name)))
+ continue;
+ if (!BadPtr(bconf->name) && mycmp(bconf->name, aconf->name))
+ continue;
+ break;
+ }
+ return bconf;
+}
+
+/*
+ * find_temp_conf_entry
+ *
+ * - looks for a match on all given fields for a TEMP conf line.
+ * Right now the passwd,port, and class fields are ignored, because it's
+ * only useful for k:lines anyway. -Russell 11/22/95
+ * 1/21/95 Now looks for any conf line. I'm leaving this routine and its
+ * call in because this routine has potential in future upgrades. -Russell
+ */
+aConfItem *find_temp_conf_entry(aconf, mask)
+aConfItem *aconf;
+u_int mask;
+{
+ Reg1 aConfItem *bconf;
+
+ for (bconf = conf, mask &= ~CONF_ILLEGAL; bconf; bconf = bconf->next)
+ {
+ /* kline/unkline/kline fix -- Barubary */
+ if (bconf->status & CONF_ILLEGAL) continue;
+ if (!(bconf->status & mask) || (bconf->port != aconf->port))
+ continue;
+/* if (!bconf->tempconf) continue;*/
+ if ((BadPtr(bconf->host) && !BadPtr(aconf->host)) ||
+ (BadPtr(aconf->host) && !BadPtr(bconf->host)))
+ continue;
+ if (!BadPtr(bconf->host) && mycmp(bconf->host, aconf->host))
+ continue;
+
+/* if ((BadPtr(bconf->passwd) && !BadPtr(aconf->passwd)) ||
+ (BadPtr(aconf->passwd) && !BadPtr(bconf->passwd)))
+ continue;
+ if (!BadPtr(bconf->passwd) &&
+ mycmp(bconf->passwd, aconf->passwd))
+ continue;*/
+
+ if ((BadPtr(bconf->name) && !BadPtr(aconf->name)) ||
+ (BadPtr(aconf->name) && !BadPtr(bconf->name)))
+ continue;
+ if (!BadPtr(bconf->name) && mycmp(bconf->name, aconf->name))
+ continue;
+ break;
+ }
+ return bconf;
+}
+
+aSqlineItem *find_sqline_nick(nickmask)
+char *nickmask;
+{
+ Reg1 aSqlineItem *asqline;
+
+ for(asqline = sqline; asqline; asqline = asqline->next) {
+ if(!BadPtr(asqline->sqline) && (asqline->status !=
+ CONF_ILLEGAL) && !mycmp(asqline->sqline, nickmask))
+ return asqline;
+ }
+ return NULL;
+}
+
+aSqlineItem *find_sqline_match(nickname)
+char *nickname;
+{
+ Reg1 aSqlineItem *asqline;
+
+ for(asqline = sqline; asqline; asqline = asqline->next) {
+ if(!BadPtr(asqline->sqline) && (asqline->status !=
+ CONF_ILLEGAL) && !match(asqline->sqline,nickname))
+ return asqline;
+ }
+ return NULL;
+}
+
+/*
+** parv[0] = sender prefix
+** parv[1] = server
+** parv[2] = +/-
+**
+*/
+int m_svsnoop(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ Reg1 aConfItem *aconf;
+
+ if (!(check_registered(sptr) && IsULine(cptr, sptr) && parc > 2))
+ return 0;
+/* svsnoop bugfix --binary */
+ if (hunt_server(cptr, sptr, ":%s SVSNOOP %s :%s", 1, parc, parv) == HUNTED_ISME) {
+ if (parv[2][0] == '+')
+ for(aconf=conf;aconf;aconf=aconf->next) {
+ if (aconf->status & CONF_OPERATOR || aconf->status & CONF_LOCOP)
+ aconf->status = CONF_ILLEGAL;
+ }
+ else
+ (void)rehash(&me, &me, 2);
+ }
+}
+#define doDebug debugNotice( __FILE__, __LINE__)
+
+void debugNotice(char *file, long line) {
+ /* a little handy debug tool --sts */
+#ifdef STSDEBUG
+ sendto_ops("# !Debug! # %s:%i", file, line);
+ flush_connections(me.fd);
+#endif
+}
+#define DoFlush flush_connections(me.fd)
+/*
+ * rehash
+ *
+ * Actual REHASH service routine. Called with sig == 0 if it has been called
+ * as a result of an operator issuing this command, else assume it has been
+ * called as a result of the server receiving a HUP signal.
+ */
+int rehash(cptr, sptr, sig)
+aClient *cptr, *sptr;
+int sig;
+{
+ Reg1 aConfItem **tmp = &conf, *tmp2;
+ Reg2 aClass *cltmp;
+ Reg1 aClient *acptr;
+ Reg2 int i;
+ int ret = 0;
+ /* One of the REHASH bugs -- sts*/
+ flush_connections(me.fd);
+ if (sig == 1)
+ {
+ sendto_ops("Got signal SIGHUP, reloading ircd conf. file");
+#ifdef ULTRIX
+ if (fork() > 0)
+ exit(0);
+ write_pidfile();
+#endif
+ }
+ for (i = 0; i <= highest_fd; i++)
+ if ((acptr = local[i]) && !IsMe(acptr))
+ {
+ /*
+ * Nullify any references from client structures to
+ * this host structure which is about to be freed.
+ * Could always keep reference counts instead of
+ * this....-avalon
+ */
+ acptr->hostp = NULL;
+ }
+ while ((tmp2 = *tmp))
+ if (tmp2->clients || tmp2->status & CONF_LISTEN_PORT)
+ {
+ /*
+ ** Configuration entry is still in use by some
+ ** local clients, cannot delete it--mark it so
+ ** that it will be deleted when the last client
+ ** exits...
+ */
+ if (!(tmp2->status & (CONF_LISTEN_PORT|CONF_CLIENT)))
+ {
+ *tmp = tmp2->next;
+ tmp2->next = NULL;
+ }
+ else
+ tmp = &tmp2->next;
+ tmp2->status |= CONF_ILLEGAL;
+ }
+ else
+ {
+ *tmp = tmp2->next;
+ /* free expression trees of connect rules */
+ if ((tmp2->status & (CONF_CRULEALL|CONF_CRULEAUTO))
+ && (tmp2->passwd != NULL))
+ crule_free (&(tmp2->passwd));
+ free_conf(tmp2);
+ }
+ /*
+ * We don't delete the class table, rather mark all entries
+ * for deletion. The table is cleaned up by check_class. - avalon
+ */
+ for (cltmp = NextClass(FirstClass()); cltmp; cltmp = NextClass(cltmp))
+ MaxLinks(cltmp) = -1;
+ if (sig != 2)
+ flush_cache();
+
+ (void) initconf(0);
+ DoFlush;
+ close_listeners();
+ /*
+ * flush out deleted I and P lines although still in use.
+ */
+ for (tmp = &conf; (tmp2 = *tmp); )
+ if (!(tmp2->status & CONF_ILLEGAL))
+ tmp = &tmp2->next;
+ else
+ {
+ *tmp = tmp2->next;
+ tmp2->next = NULL;
+ if (!tmp2->clients)
+ free_conf(tmp2);
+ }
+ /* Added to make sure K-lines are checked -- Barubary */
+ check_pings(TStime(), 1);
+ /* Recheck all U-lines -- Barubary */
+ for (i = 0; i < highest_fd; i++)
+ if ((acptr = local[i]) && !IsMe(acptr))
+ {
+ if (find_conf_host(acptr->from->confs, acptr->name,
+ CONF_UWORLD) || (acptr->user && find_conf_host(
+ acptr->from->confs, acptr->user->server,
+ CONF_UWORLD)))
+ acptr->flags |= FLAGS_ULINE;
+ else
+ acptr->flags &= ~FLAGS_ULINE;
+ }
+ reset_help(); /* Reinitialize help-system. -Donwulff */
+ return ret;
+}
+
+/*
+ * openconf
+ *
+ * returns -1 on any error or else the fd opened from which to read the
+ * configuration file from. This may either be th4 file direct or one end
+ * of a pipe from m4.
+ */
+int openconf()
+{
+#ifdef M4_PREPROC
+ int pi[2], i;
+
+ if (pipe(pi) == -1)
+ return -1;
+ switch(fork())
+ {
+ case -1 :
+ return -1;
+ case 0 :
+ (void)close(pi[0]);
+ if (pi[1] != 1)
+ {
+ (void)dup2(pi[1], 1);
+ (void)close(pi[1]);
+ }
+ (void)dup2(1,2);
+ for (i = 3; i < MAXCONNECTIONS; i++)
+ if (local[i])
+ (void) close(i);
+ /*
+ * m4 maybe anywhere, use execvp to find it. Any error
+ * goes out with report_error. Could be dangerous,
+ * two servers running with the same fd's >:-) -avalon
+ */
+ (void)execlp("m4", "m4", "ircd.m4", configfile, 0);
+ report_error("Error executing m4 %s:%s", &me);
+ exit(-1);
+ default :
+ (void)close(pi[1]);
+ return pi[0];
+ }
+#else
+ return open(configfile, O_RDONLY);
+#endif
+}
+extern char *getfield();
+
+#define STAR1 OFLAG_SADMIN|OFLAG_ADMIN|OFLAG_NETADMIN|OFLAG_COADMIN
+#define STAR2 OFLAG_TECHADMIN|OFLAG_ZLINE|OFLAG_AGENT|OFLAG_HIDE|OFLAG_WHOIS
+#define STAR3 OFLAG_INVISIBLE
+static int oper_access[] = {
+ ~(STAR1|STAR2|STAR3), '*',
+ OFLAG_LOCAL, 'o',
+ OFLAG_GLOBAL, 'O',
+ OFLAG_REHASH, 'r',
+ OFLAG_EYES, 'e',
+ OFLAG_DIE, 'D',
+ OFLAG_RESTART, 'R',
+ OFLAG_HELPOP, 'h',
+ OFLAG_GLOBOP, 'g',
+ OFLAG_WALLOP, 'w',
+ OFLAG_LOCOP, 'l',
+ OFLAG_LROUTE, 'c',
+ OFLAG_GROUTE, 'L',
+ OFLAG_LKILL, 'k',
+ OFLAG_GKILL, 'K',
+ OFLAG_KLINE, 'b',
+ OFLAG_UNKLINE, 'B',
+ OFLAG_LNOTICE, 'n',
+ OFLAG_GNOTICE, 'G',
+ OFLAG_ADMIN, 'A',
+ OFLAG_SADMIN, 'a',
+ OFLAG_NETADMIN, 'N',
+ OFLAG_COADMIN, 'C',
+ OFLAG_TECHADMIN, 'T',
+ OFLAG_UMODEC, 'u',
+ OFLAG_UMODEF, 'f',
+ OFLAG_ZLINE, 'z',
+ OFLAG_WHOIS, 'W',
+ OFLAG_HIDE, 'H',
+ OFLAG_AGENT, 'S',
+ OFLAG_INVISIBLE, '^',
+ 0, 0 };
+
+char oflagbuf[128];
+
+char *oflagstr(long oflag)
+{
+ int *i, flag;
+ char m;
+ char *p = oflagbuf;
+
+ for (i = &oper_access[6], m = *(i + 1); (flag = *i); i += 2, m = *(i + 1))
+ {
+ if (oflag & flag)
+ {
+ *p = m;
+ p++;
+ }
+ }
+ *p = '\0';
+ return oflagbuf;
+}
+
+/*
+** initconf()
+** Read configuration file.
+**
+** returns -1, if file cannot be opened
+** 0, if file opened
+*/
+
+#define MAXCONFLINKS 150
+
+int initconf(opt)
+int opt;
+{
+ static char quotes[9][2] = {{'b', '\b'}, {'f', '\f'}, {'n', '\n'},
+ {'r', '\r'}, {'t', '\t'}, {'v', '\v'},
+ {'\\', '\\'}, { 0, 0}};
+ Reg1 char *tmp, *s;
+ int fd, i;
+ char line[512], c[80];
+ int ccount = 0, ncount = 0;
+ aConfItem *aconf = NULL;
+
+ Debug((DEBUG_DEBUG, "initconf(): ircd.conf = %s", configfile));
+ if ((fd = openconf()) == -1)
+ {
+#ifdef M4_PREPROC
+ (void)wait(0);
+#endif
+ return -1;
+ }
+ (void)dgets(-1, NULL, 0); /* make sure buffer is at empty pos */
+ while ((i = dgets(fd, line, sizeof(line) - 1)) > 0)
+ {
+ line[i] = '\0';
+ if ((tmp = (char *)index(line, '\n')))
+ *tmp = 0;
+ else while(dgets(fd, c, sizeof(c) - 1) > 0)
+ if ((tmp = (char *)index(c, '\n')))
+ {
+ *tmp = 0;
+ break;
+ }
+ /*
+ * Do quoting of characters and # detection.
+ */
+ for (tmp = line; *tmp; tmp++)
+ {
+ if (*tmp == '\\')
+ {
+ for (i = 0; quotes[i][0]; i++)
+ if (quotes[i][0] == *(tmp+1))
+ {
+ *tmp = quotes[i][1];
+ break;
+ }
+ if (!quotes[i][0])
+ *tmp = *(tmp+1);
+ if (!*(tmp+1))
+ break;
+ else
+ for (s = tmp; *s = *(s+1); s++)
+ ;
+ }
+ else if (*tmp == '#')
+ *tmp = '\0';
+ }
+ if (!*line || line[0] == '#' || line[0] == '\n' ||
+ line[0] == ' ' || line[0] == '\t')
+ continue;
+
+ /* Could we test if it's conf line at all? -Vesa */
+ if (line[1] != ':')
+ {
+ Debug((DEBUG_ERROR, "Bad config line: %s", line));
+ continue;
+ }
+ if (aconf)
+ free_conf(aconf);
+ aconf = make_conf();
+
+ tmp = getfield(line);
+ if (!tmp)
+ continue;
+ switch (*tmp)
+ {
+ case 'A': /* Name, e-mail address of administrator */
+ aconf->status = CONF_ADMIN;
+ break;
+ case 'a': /* of this server. */
+ aconf->status = CONF_SADMIN;
+ break;
+ case 'C': /* Server where I should try to connect */
+ case 'c': /* in case of lp failures */
+ ccount++;
+ aconf->status = CONF_CONNECT_SERVER;
+ break;
+ /* Connect rule */
+ case 'D':
+ aconf->status = CONF_CRULEALL;
+ break;
+ /* Connect rule - autos only */
+ case 'd':
+ aconf->status = CONF_CRULEAUTO;
+ break;
+ case 'e':
+ aconf->status = CONF_SOCKSEXCEPT;
+ break;
+ case 'E':
+ aconf->status = CONF_EXCEPT;
+ break;
+ case 'G':
+ case 'g':
+ /* General config options */
+ aconf->status = CONF_CONFIG;
+ break;
+ case 'H': /* Hub server line */
+ case 'h':
+ aconf->status = CONF_HUB;
+ break;
+ case 'I': /* Just plain normal irc client trying */
+ case 'i': /* to connect me */
+ aconf->status = CONF_CLIENT;
+ break;
+ case 'K': /* Kill user line on ircd.conf */
+ case 'k':
+ aconf->status = CONF_KILL;
+ break;
+ /* Operator. Line should contain at least */
+ /* password and host where connection is */
+ case 'L': /* guaranteed leaf server */
+ case 'l':
+ aconf->status = CONF_LEAF;
+ break;
+ /* Me. Host field is name used for this host */
+ /* and port number is the number of the port */
+ case 'M':
+ case 'm':
+ aconf->status = CONF_ME;
+ break;
+ case 'N': /* Server where I should NOT try to */
+ case 'n': /* connect in case of lp failures */
+ /* but which tries to connect ME */
+ ++ncount;
+ aconf->status = CONF_NOCONNECT_SERVER;
+ break;
+ case 'O':
+ aconf->status = CONF_OPERATOR;
+ break;
+ /* Local Operator, (limited privs --SRB)
+ * Not anymore, OperFlag access levels. -Cabal95 */
+ case 'o':
+ aconf->status = CONF_OPERATOR;
+ break;
+ case 'P': /* listen port line */
+ case 'p':
+ aconf->status = CONF_LISTEN_PORT;
+ break;
+ case 'Q': /* reserved nicks */
+ aconf->status = CONF_QUARANTINED_NICK;
+ break;
+ case 'q': /* a server that you don't want in your */
+ /* network. USE WITH CAUTION! */
+ aconf->status = CONF_QUARANTINED_SERVER;
+
+ break;
+ case 'S': /* Service. Same semantics as */
+ case 's': /* CONF_OPERATOR */
+ aconf->status = CONF_SERVICE;
+ break;
+ case 'T':
+ aconf->status = CONF_TLINE;
+ break;
+ case 'U': /* Underworld server, allowed to hack modes */
+ case 'u': /* *Every* server on the net must define the same !!! */
+ aconf->status = CONF_UWORLD;
+ break;
+ case 'Y':
+ case 'y':
+ aconf->status = CONF_CLASS;
+ break;
+ case 'Z':
+ case 'z':
+ aconf->status = CONF_ZAP;
+ break;
+ case 'X':
+ case 'x':
+ aconf->status = CONF_DRPASS;
+ break;
+ default:
+ Debug((DEBUG_ERROR, "Error in config file: %s", line));
+ break;
+ }
+ if (IsIllegal(aconf))
+ continue;
+
+ for (;;) /* Fake loop, that I can use break here --msa */
+ {
+ /* Yes I know this could be much cleaner, but I did not
+ * want to put it into its own separate function, but
+ * I believe the X:should be like this:
+ * X:restartpass:diepass
+ * which leaves this code untouched. This is already indented
+ * enough to justify that...
+ */
+ if ((tmp = getfield(NULL)) == NULL)
+ break;
+ DupString(aconf->host, tmp);
+ if ((tmp = getfield(NULL)) == NULL)
+ break;
+ DupString(aconf->passwd, tmp);
+ if ((tmp = getfield(NULL)) == NULL)
+ break;
+ DupString(aconf->name, tmp);
+ if ((tmp = getfield(NULL)) == NULL)
+ break;
+ if (aconf->status & CONF_OPS) {
+ int *i, flag;
+ char *m = "*";
+ /*
+ * Now we use access flags to define
+ * what an operator can do with their O.
+ */
+ for (m = (*tmp) ? tmp : m; *m; m++) {
+ for (i = oper_access; (flag = *i); i += 2)
+ if (*m == (char)(*(i+1))) {
+ aconf->port |= flag;
+ break;
+ }
+ }
+ if (!(aconf->port&OFLAG_ISGLOBAL))
+ aconf->status = CONF_LOCOP;
+ }
+ else
+ aconf->port = atoi(tmp);
+ if ((tmp = getfield(NULL)) == NULL)
+ break;
+ Class(aconf) = find_class(atoi(tmp));
+ break;
+ }
+ /*
+ ** If conf line is a general config, just
+ ** see if we recognize the keyword, and set
+ ** the appropriate global. We don't use a "standard"
+ ** config link here, because these are things which need
+ ** to be tested SO often that a simple global test
+ ** is much better! -Aeto
+ */
+ if ((aconf->status & CONF_CONFIG) == CONF_CONFIG) {
+ continue;
+ }
+
+ /* Check for bad Z-lines masks as they are *very* dangerous
+ if not correct!!! */
+ if (aconf->status == CONF_ZAP)
+ {
+ char *tempc = aconf->host;
+ if (!tempc)
+ {
+ free_conf(aconf);
+ aconf = NULL;
+ continue;
+ }
+ for (; *tempc; tempc++)
+ if ((*tempc >= '0') && (*tempc <= '9'))
+ goto zap_safe;
+ free_conf(aconf);
+ aconf = NULL;
+ continue;
+ zap_safe:;
+ }
+ /*
+ ** T:Line protection stuff..
+ **
+ **
+ */
+ if (aconf->status & CONF_TLINE)
+ {
+ if (*aconf->passwd == '/')
+ goto badtline;
+ if (strstr(aconf->passwd, ".."))
+ goto badtline;
+ if (strchr(aconf->passwd, '~'))
+ goto badtline;
+ if (!strcmp(aconf->passwd, configfile) || !strcmp(aconf->name, configfile))
+ goto badtline;
+ if (!strcmp(aconf->passwd, CPATH) || !strcmp(aconf->name, CPATH))
+ goto badtline;
+ if (!strcmp(aconf->passwd, ZCONF) || !strcmp(aconf->name, ZCONF))
+ goto badtline;
+ if (!strcmp(aconf->passwd, OPATH) || !strcmp(aconf->name, OPATH))
+ goto badtline;
+ if (!strcmp(aconf->passwd, lPATH) || !strcmp(aconf->name, lPATH))
+ goto badtline;
+
+ goto tline_safe;
+ badtline:
+ free_conf(aconf);
+ aconf = NULL;
+ continue;
+ tline_safe:;
+ }
+ /*
+ ** If conf line is a class definition, create a class entry
+ ** for it and make the conf_line illegal and delete it.
+ */
+ if (aconf->status & CONF_CLASS)
+ {
+ add_class(atoi(aconf->host), atoi(aconf->passwd),
+ atoi(aconf->name), aconf->port,
+ tmp ? atoi(tmp) : 0);
+ continue;
+ }
+ /*
+ ** associate each conf line with a class by using a pointer
+ ** to the correct class record. -avalon
+ */
+ if (aconf->status & (CONF_CLIENT_MASK|CONF_LISTEN_PORT))
+ {
+ if (Class(aconf) == 0)
+ Class(aconf) = find_class(0);
+ if (MaxLinks(Class(aconf)) < 0)
+ Class(aconf) = find_class(0);
+ }
+ if (aconf->status & (CONF_LISTEN_PORT|CONF_CLIENT))
+ {
+ aConfItem *bconf;
+
+ if (bconf = find_conf_entry(aconf, aconf->status))
+ {
+ delist_conf(bconf);
+ bconf->status &= ~CONF_ILLEGAL;
+ if (aconf->status == CONF_CLIENT)
+ {
+ bconf->class->links -= bconf->clients;
+ bconf->class = aconf->class;
+ if (bconf->class)
+ bconf->class->links += bconf->clients;
+ }
+ free_conf(aconf);
+ aconf = bconf;
+ }
+ else if (aconf->host &&
+ aconf->status == CONF_LISTEN_PORT)
+ (void)add_listener(aconf);
+ }
+ if (aconf->status & CONF_SERVER_MASK)
+ if (ncount > MAXCONFLINKS || ccount > MAXCONFLINKS ||
+ !aconf->host || !aconf->name)
+ continue;
+
+ if (aconf->status &
+ (CONF_SERVER_MASK|CONF_LOCOP|CONF_OPERATOR))
+ if (!index(aconf->host, '@') && *aconf->host != '/')
+ {
+ char *newhost;
+ int len = 3; /* *@\0 = 3 */
+
+ len += strlen(aconf->host);
+ newhost = (char *)MyMalloc(len);
+ (void)sprintf(newhost, "*@%s", aconf->host);
+ MyFree(aconf->host);
+ aconf->host = newhost;
+ }
+ if (aconf->status & CONF_SERVER_MASK)
+ {
+ if (BadPtr(aconf->passwd))
+ continue;
+ else
+ if (!(opt & BOOT_QUICK))
+ (void)lookup_confhost(aconf);
+ }
+
+ /* Create expression tree from connect rule...
+ ** If there's a parsing error, nuke the conf structure */
+ if (aconf->status & (CONF_CRULEALL | CONF_CRULEAUTO))
+ {
+ MyFree (aconf->passwd);
+ if ((aconf->passwd =
+ (char *) crule_parse (aconf->name)) == NULL)
+ {
+ free_conf (aconf);
+ aconf = NULL;
+ continue;
+ }
+ }
+
+ /*
+ ** Own port and name cannot be changed after the startup.
+ ** (or could be allowed, but only if all links are closed
+ ** first).
+ ** Configuration info does not override the name and port
+ ** if previously defined. Note, that "info"-field can be
+ ** changed by "/rehash".
+ */
+ if (aconf->status == CONF_ME)
+ {
+ strncpyzt(me.info, aconf->name, sizeof(me.info));
+ if (me.name[0] == '\0' && aconf->host[0])
+ strncpyzt(me.name, aconf->host,
+ sizeof(me.name));
+ if (aconf->passwd[0] && (aconf->passwd[0] != '*'))
+ me.ip.s_addr = inet_addr(aconf->passwd);
+ else
+ me.ip.s_addr = INADDR_ANY;
+ if (portnum < 0 && aconf->port >= 0)
+ portnum = aconf->port;
+ }
+ if (aconf->status == CONF_EXCEPT)
+ aconf->tmpconf = KLINE_EXCEPT;
+ if (aconf->status == CONF_KILL)
+ aconf->tmpconf = KLINE_PERM;
+ (void)collapse(aconf->host);
+ (void)collapse(aconf->name);
+ Debug((DEBUG_NOTICE,
+ "Read Init: (%d) (%s) (%s) (%s) (%d) (%d)",
+ aconf->status, aconf->host, aconf->passwd,
+ aconf->name, aconf->port, Class(aconf)));
+ aconf->next = conf;
+ conf = aconf;
+ aconf = NULL;
+ }
+ if (aconf)
+ free_conf(aconf);
+ (void)dgets(-1, NULL, 0); /* make sure buffer is at empty pos */
+ (void)close(fd);
+#ifdef M4_PREPROC
+ (void)wait(0);
+#endif
+ check_class();
+ nextping = nextconnect = TStime();
+ return 0;
+ }
+
+/*
+ * lookup_confhost
+ * Do (start) DNS lookups of all hostnames in the conf line and convert
+ * an IP addresses in a.b.c.d number for to IP#s.
+ */
+static int lookup_confhost(aconf)
+Reg1 aConfItem *aconf;
+{
+ Reg2 char *s;
+ Reg3 struct hostent *hp;
+ Link ln;
+
+ if (BadPtr(aconf->host) || BadPtr(aconf->name))
+ goto badlookup;
+ if ((s = index(aconf->host, '@')))
+ s++;
+ else
+ s = aconf->host;
+ /*
+ ** Do name lookup now on hostnames given and store the
+ ** ip numbers in conf structure.
+ */
+ if (!isalpha(*s) && !isdigit(*s))
+ goto badlookup;
+
+ /*
+ ** Prepare structure in case we have to wait for a
+ ** reply which we get later and store away.
+ */
+ ln.value.aconf = aconf;
+ ln.flags = ASYNC_CONF;
+
+ if (isdigit(*s))
+ aconf->ipnum.s_addr = inet_addr(s);
+ else if ((hp = gethost_byname(s, &ln)))
+ bcopy(hp->h_addr, (char *)&(aconf->ipnum),
+ sizeof(struct in_addr));
+
+ if (aconf->ipnum.s_addr == -1)
+ goto badlookup;
+ return 0;
+badlookup:
+ if (aconf->ipnum.s_addr == -1)
+ bzero((char *)&aconf->ipnum, sizeof(struct in_addr));
+ Debug((DEBUG_ERROR,"Host/server name error: (%s) (%s)",
+ aconf->host, aconf->name));
+ return -1;
+}
+
+int find_kill(cptr)
+aClient *cptr;
+{
+ char reply[256], *host, *name;
+ aConfItem *tmp;
+
+ if (!cptr->user)
+ return 0;
+
+ host = cptr->sockhost;
+ name = cptr->user->username;
+
+ if (strlen(host) > (size_t) HOSTLEN ||
+ (name ? strlen(name) : 0) > (size_t) HOSTLEN)
+ return (0);
+
+ reply[0] = '\0';
+
+ for (tmp = conf; tmp; tmp = tmp->next)
+ if ((tmp->status == CONF_EXCEPT) && tmp->host && tmp->name &&
+ (match(tmp->host, host) == 0) &&
+ (!name || match(tmp->name, name) == 0) &&
+ (!tmp->port || (tmp->port == cptr->acpt->port)))
+ /* can short-circuit evaluation - not taking chances
+ cos check_time_interval destroys tmp->passwd
+ - Mmmm
+ */
+ if (BadPtr(tmp->passwd))
+ break;
+ else if (is_comment(tmp->passwd))
+ break;
+ else if (check_time_interval(tmp->passwd, reply))
+ break;
+
+
+ if (tmp) {
+ /* This is an E:Line */
+ return 0;
+ }
+
+ for (tmp = conf; tmp; tmp = tmp->next)
+ if ((tmp->status == CONF_KILL) && tmp->host && tmp->name &&
+ (match(tmp->host, host) == 0) &&
+ (!name || match(tmp->name, name) == 0) &&
+ (!tmp->port || (tmp->port == cptr->acpt->port)))
+ /* can short-circuit evaluation - not taking chances
+ cos check_time_interval destroys tmp->passwd
+ - Mmmm
+ */
+ if (BadPtr(tmp->passwd))
+ break;
+ else if (is_comment(tmp->passwd))
+ break;
+ else if (check_time_interval(tmp->passwd, reply))
+ break;
+
+
+ if (reply[0])
+ sendto_one(cptr,reply,
+ me.name, ERR_YOUREBANNEDCREEP, cptr->name, KLINE_ADDRESS);
+ else if (tmp)
+ if (BadPtr(tmp->passwd))
+ sendto_one(cptr,
+ ":%s %d %s :*** You are not welcome on this server."
+ " Email %s for more information.",
+ me.name, ERR_YOUREBANNEDCREEP, cptr->name, KLINE_ADDRESS);
+ else
+#ifdef COMMENT_IS_FILE
+ m_killcomment(cptr,cptr->name, tmp->passwd);
+#else
+ {
+ if (*tmp->passwd == '|' && !strchr(tmp->passwd, '/') && match("|kc.*", tmp->passwd))
+ {
+ m_killcomment(cptr, cptr->name, (tmp->passwd) + 1);
+ }
+ else
+ if (tmp->tmpconf == KLINE_AKILL)
+ sendto_one(cptr,
+ ":%s %d %s :*** %s",
+ me.name, ERR_YOUREBANNEDCREEP, cptr->name,
+ tmp->passwd);
+ else
+ sendto_one(cptr,
+ ":%s %d %s :*** You are not welcome on this server: "
+ "%s. Email %s for more information.",
+ me.name, ERR_YOUREBANNEDCREEP, cptr->name,
+ tmp->passwd, KLINE_ADDRESS);
+ }
+#endif /* COMMENT_IS_FILE */
+
+ return (tmp ? -1 : 0);
+}
+
+char *find_zap(aClient *cptr, int dokillmsg)
+{
+ aConfItem *tmp;
+ char *retval = NULL;
+ for (tmp = conf; tmp; tmp = tmp->next)
+ if ((tmp->status == CONF_ZAP) && tmp->host &&
+ !match(tmp->host, inetntoa((char *) &cptr->ip)))
+ {
+ retval = (tmp->passwd) ? tmp->passwd :
+ "Reason unspecified";
+ break;
+ }
+ if (dokillmsg && retval)
+ sendto_one(cptr,
+ ":%s %d %s :*** You are not welcome on this server: "
+ "%s. Email %s for more information.",
+ me.name, ERR_YOUREBANNEDCREEP, cptr->name,
+ retval, KLINE_ADDRESS);
+ if (!dokillmsg && retval)
+ {
+ sprintf(zlinebuf,
+ "ERROR :Closing Link: [%s] (You are not welcome on "
+ "this server: %s. Email %s for more"
+ " information.)\r\n", inetntoa((char *) &cptr->ip),
+ retval, KLINE_ADDRESS);
+ retval = zlinebuf;
+ }
+ return retval;
+}
+
+int find_kill_byname(host, name)
+char *host, *name;
+{
+ aConfItem *tmp;
+
+ for (tmp = conf; tmp; tmp = tmp->next) {
+ if ((tmp->status == CONF_KILL) && tmp->host && tmp->name &&
+ (match(tmp->host, host) == 0) &&
+ (!name || match(tmp->name, name) == 0))
+ return 1;
+ }
+
+ return 0;
+ }
+
+
+/*
+** output the reason for being k lined from a file - Mmmm
+** sptr is server
+** parv is the sender prefix
+** filename is the file that is to be output to the K lined client
+*/
+int m_killcomment(sptr, parv, filename)
+aClient *sptr;
+char *parv, *filename;
+{
+ int fd;
+ char line[80];
+ Reg1 char *tmp;
+ struct stat sb;
+ struct tm *tm;
+
+ /*
+ * stop NFS hangs...most systems should be able to open a file in
+ * 3 seconds. -avalon (curtesy of wumpus)
+ */
+ fd = open(filename, O_RDONLY);
+ if (fd == -1)
+ {
+ sendto_one(sptr, err_str(ERR_NOMOTD), me.name, parv);
+ sendto_one(sptr,
+ ":%s %d %s :*** You are not welcome to this server.",
+ me.name, ERR_YOUREBANNEDCREEP, parv);
+ return 0;
+ }
+ (void)fstat(fd, &sb);
+ tm = localtime(&sb.st_mtime);
+ (void)dgets(-1, NULL, 0); /* make sure buffer is at empty pos */
+ while (dgets(fd, line, sizeof(line)-1) > 0)
+ {
+ if ((tmp = (char *)index(line,'\n')))
+ *tmp = '\0';
+ if ((tmp = (char *)index(line,'\r')))
+ *tmp = '\0';
+ /* sendto_one(sptr,
+ ":%s %d %s : %s.",
+ me.name, ERR_YOUREBANNEDCREEP, parv,line); */
+ sendto_one(sptr, rpl_str(RPL_MOTD), me.name, parv, line);
+ }
+ sendto_one(sptr,
+ ":%s %d %s :*** You are not welcome to this server.",
+ me.name, ERR_YOUREBANNEDCREEP, parv);
+ (void)dgets(-1, NULL, 0); /* make sure buffer is at empty pos */
+ (void)close(fd);
+ return 0;
+ }
+
+
+/*
+** is the K line field an interval or a comment? - Mmmm
+*/
+
+static int is_comment(comment)
+char *comment;
+{
+ int i;
+ for (i=0; i<strlen(comment); i++)
+ if ( (comment[i] != ' ') && (comment[i] != '-')
+ && (comment[i] != ',')
+ && ( (comment[i] < '0') || (comment[i] > '9') ) )
+ return(1);
+
+ return(0);
+}
+
+
+/*
+** check against a set of time intervals
+*/
+
+static int check_time_interval(interval, reply)
+char *interval, *reply;
+{
+ struct tm *tptr;
+ time_t tick;
+ char *p;
+ int perm_min_hours, perm_min_minutes,
+ perm_max_hours, perm_max_minutes;
+ int now, perm_min, perm_max;
+
+ tick = TStime();
+ tptr = localtime(&tick);
+ now = tptr->tm_hour * 60 + tptr->tm_min;
+
+ while (interval)
+ {
+ p = (char *)index(interval, ',');
+ if (p)
+ *p = '\0';
+ if (sscanf(interval, "%2d%2d-%2d%2d",
+ &perm_min_hours, &perm_min_minutes,
+ &perm_max_hours, &perm_max_minutes) != 4)
+ {
+ if (p)
+ *p = ',';
+ return(0);
+ }
+ if (p)
+ *(p++) = ',';
+ perm_min = 60 * perm_min_hours + perm_min_minutes;
+ perm_max = 60 * perm_max_hours + perm_max_minutes;
+ /*
+ ** The following check allows intervals over midnight ...
+ */
+ if ((perm_min < perm_max)
+ ? (perm_min <= now && now <= perm_max)
+ : (perm_min <= now || now <= perm_max))
+ {
+ (void)sprintf(reply,
+ ":%%s %%d %%s :%s %d:%02d to %d:%02d.",
+ "You are not allowed to connect from",
+ perm_min_hours, perm_min_minutes,
+ perm_max_hours, perm_max_minutes);
+ return(ERR_YOUREBANNEDCREEP);
+ }
+ if ((perm_min < perm_max)
+ ? (perm_min <= now + 5 && now + 5 <= perm_max)
+ : (perm_min <= now + 5 || now + 5 <= perm_max))
+ {
+ (void)sprintf(reply, ":%%s %%d %%s :%d minute%s%s",
+ perm_min-now,(perm_min-now)>1?"s ":" ",
+ "and you will be denied for further access");
+ return(ERR_YOUWILLBEBANNED);
+ }
+ interval = p;
+ }
+ return(0);
+}
+
+/*
+** m_rakill;
+** parv[0] = sender prefix
+** parv[1] = hostmask
+** parv[2] = username
+** parv[3] = comment
+*/
+int m_rakill(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ char *hostmask, *usermask;
+ int result;
+
+ if (check_registered(sptr))
+ return 0;
+
+ if (parc < 2 && IsPerson(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "AKILL");
+ return 0;
+ }
+
+ if (IsServer(sptr) && parc < 3)
+ return 0;
+
+ if (!IsServer(cptr))
+ {
+ if (!IsOper(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name,
+ sptr->name);
+ return 0;
+ }
+ else
+ {
+ if ((hostmask = (char *)index(parv[1], '@')))
+ {
+ *hostmask = 0;
+ hostmask++;
+ usermask = parv[1];
+ }
+ else
+ {
+ sendto_one(sptr, ":%s NOTICE %s :%s", me.name,
+ sptr->name, "Please use a user@host mask.");
+ return 0;
+ }
+ }
+ }
+ else
+ {
+ hostmask = parv[1];
+ usermask = parv[2];
+ }
+
+ if (!usermask || !hostmask)
+ {
+ /*
+ * This is very bad, it should never happen.
+ */
+ sendto_ops("Error adding akill from %s!", sptr->name);
+ return 0;
+ }
+
+ result = del_temp_conf(CONF_KILL, hostmask, NULL, usermask, 0, 0, 2);
+ if (result == KLINE_DEL_ERR)
+ {
+ if (!MyClient(sptr))
+ {
+ sendto_serv_butone(cptr, ":%s RAKILL %s %s",
+ IsServer(cptr) ? parv[0] : me.name, hostmask, usermask);
+ return 0;
+ }
+ sendto_one(sptr, ":%s NOTICE %s :Akill %s@%s does not exist.",
+ me.name, sptr->name, usermask, hostmask);
+ return 0;
+ }
+
+ if (MyClient(sptr))
+ {
+ sendto_ops("%s removed akill for %s@%s",
+ sptr->name, usermask, hostmask);
+ sendto_serv_butone(&me,
+ ":%s GLOBOPS :%s removed akill for %s@%s",
+ me.name, sptr->name, usermask, hostmask);
+ }
+
+ sendto_serv_butone(cptr, ":%s RAKILL %s %s",
+ IsServer (cptr) ? parv[0] : me.name,
+ hostmask, usermask);
+
+ check_pings(TStime(), 1);
+ }
+
+/* ** m_akill;
+** parv[0] = sender prefix
+** parv[1] = hostmask
+** parv[2] = username
+** parv[3] = comment
+*/
+int m_akill(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ char *hostmask, *usermask, *comment;
+
+ if (check_registered(sptr))
+ return 0;
+
+ if (parc < 2 && IsPerson(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "AKILL");
+ return 0;
+ }
+
+ if (IsServer(sptr) && parc < 3)
+ return 0;
+
+ if (!IsServer(cptr))
+ {
+ if (!IsOper(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name,
+ sptr->name);
+ return 0;
+ }
+ else
+ {
+ comment = parc < 3 ? NULL : parv[2];
+ if ((hostmask = (char *)index(parv[1], '@')))
+ {
+ *hostmask = 0;
+ hostmask++;
+ usermask = parv[1];
+ }
+ else
+ {
+ sendto_one(sptr, ":%s NOTICE %s :%s", me.name,
+ sptr->name, "Please use a nick!user@host mask.");
+ return 0;
+ }
+ if (!strcmp(usermask, "*") || !strchr(hostmask, '.'))
+ {
+ sendto_one (sptr, "NOTICE %s :*** What a sweeping AKILL. If only your admin knew you tried that..", parv[0]);
+ sendto_realops("%s attempted to /akill *@*", parv[0]);
+ return 0;
+ }
+ if (MyClient(sptr))
+ {
+ sendto_ops("%s added akill for %s@%s (%s)",
+ sptr->name, usermask, hostmask,
+ !BadPtr(comment) ? comment : "no reason");
+ sendto_serv_butone(&me,
+ ":%s GLOBOPS :%s added akill for %s@%s (%s)",
+ me.name, sptr->name, usermask, hostmask,
+ !BadPtr(comment) ? comment : "no reason");
+ }
+ }
+ }
+ else
+ {
+ hostmask = parv[1];
+ usermask = parv[2];
+ comment = parc < 4 ? NULL : parv[3];
+ }
+
+ if (!usermask || !hostmask)
+ {
+ /*
+ * This is very bad, it should never happen.
+ */
+ sendto_ops("Error adding akill from %s!", sptr->name);
+ return 0;
+ }
+
+ if (!find_kill_byname(hostmask, usermask))
+ {
+
+#ifndef COMMENT_IS_FILE
+ add_temp_conf(CONF_KILL, hostmask, comment, usermask, 0, 0, 2);
+#else
+ add_temp_conf(CONF_KILL, hostmask, NULL, usermask, 0, 0, 2);
+#endif
+ }
+
+ if (comment)
+ sendto_serv_butone(cptr, ":%s AKILL %s %s :%s",
+ IsServer(cptr) ? parv[0] : me.name, hostmask,
+ usermask, comment);
+ else
+ sendto_serv_butone(cptr, ":%s AKILL %s %s",
+ IsServer (cptr) ? parv[0] : me.name,
+ hostmask, usermask);
+
+
+ check_pings(TStime(), 1);
+
+ }
+
+/* m_sqline
+** parv[0] = sender
+** parv[1] = nickmask
+** parv[2] = reason
+*/
+int m_sqline(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ Reg1 aSqlineItem *asqline;
+
+ if (!IsServer(sptr) || parc < 2)
+ return 0;
+
+ if(parv[2])
+ sendto_serv_butone(cptr, ":%s SQLINE %s :%s", parv[0],
+ parv[1], parv[2]);
+ else
+ sendto_serv_butone(cptr, ":%s SQLINE %s", parv[0],
+ parv[1]);
+
+ asqline = make_sqline();
+
+ if (parv[2])
+ DupString(asqline->reason, parv[2]);
+ if (parv[1])
+ DupString(asqline->sqline, parv[1]);
+
+ if (!find_sqline_nick(parv[1])) {
+ asqline->next = sqline;
+ sqline = asqline;
+ asqline = NULL;
+ }
+
+ if (asqline)
+ free_sqline(asqline);
+}
+
+/* m_unsqline
+** parv[0] = sender
+** parv[1] = nickmask
+*/
+int m_unsqline(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ Reg1 aSqlineItem *asqline;
+
+ if (!IsServer(sptr) || parc < 1)
+ return 0;
+
+ sendto_serv_butone(cptr, ":%s UNSQLINE %s", parv[0],
+ parv[1]);
+
+ if(!(asqline = find_sqline_nick(parv[1])))
+ return;
+
+ asqline->status = CONF_ILLEGAL;
+
+}
+
+/*
+** m_kline;
+** parv[0] = sender prefix
+** parv[1] = nickname
+** parv[2] = comment or filename
+*/
+int m_kline(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ char *host, *tmp, *hosttemp;
+ char uhost[80], name[80];
+ int ip1, ip2, ip3, temp;
+ aClient *acptr;
+ FILE *aLog;
+
+ if (!MyClient(sptr) || !OPCanKline(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+
+ if (check_registered(sptr))
+ return 0;
+
+ if (parc < 2)
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "KLINE");
+ return 0;
+ }
+
+
+/* This patch allows opers to quote kline by address as well as nick
+ * --Russell
+ */
+ if (hosttemp = (char *) strchr((char *) parv[1], '@'))
+ {
+ temp = 0;
+ while (temp <= 20)
+ name[temp++] = 0;
+ strcpy(uhost, ++hosttemp);
+ strncpy(name, parv[1], hosttemp-1-parv[1]);
+ if (name[0] == '\0' || uhost[0] == '\0')
+ {
+ Debug((DEBUG_INFO, "KLINE: Bad field!"));
+ sendto_one (sptr, "NOTICE %s :If you're going to add a userhost, at LEAST specify both fields", parv[0]);
+ return 0;
+ }
+ if (!strcmp(uhost, "*") || !strchr(uhost, '.'))
+ {
+ sendto_one (sptr, "NOTICE %s :*** What a sweeping K:Line. If only your admin knew you tried that..", parv[0]);
+ sendto_realops("%s attempted to /kline *@*", parv[0]);
+ return 0;
+ }
+ }
+
+/* by nick */
+ else
+ {
+ if (!(acptr = find_client(parv[1], NULL))) {
+ if (!(acptr = get_history(parv[1], (long)KILLCHASETIMELIMIT))) {
+ sendto_one(sptr, "NOTICE %s :Can't find user %s to add KLINE",
+ parv[0], parv[1]);
+ return 0;
+ }
+ }
+
+ if (!acptr->user)
+ return 0;
+
+ strcpy(name, acptr->user->username);
+ if (MyClient(acptr))
+ host = acptr->sockhost;
+ else
+ host = acptr->user->realhost;
+
+ /* Sanity checks */
+
+ if (name == '\0' || host == '\0')
+ {
+ Debug((DEBUG_INFO, "KLINE: Bad field"));
+ sendto_one(sptr, "NOTICE %s :Bad field!", parv[0]);
+ return 0;
+ }
+
+ /* Add some wildcards */
+
+
+ strcpy(uhost, host);
+ if (isdigit(host[strlen(host)-1])) {
+ if (sscanf(host, "%d.%d.%d.%*d", &ip1, &ip2, &ip3))
+ sprintf(uhost, "%d.%d.%d.*", ip1, ip2, ip3);
+ }
+ else if (sscanf(host, "%*[^.].%*[^.].%s", uhost)) { /* Not really... */
+ tmp = (char*)strchr(host, '.');
+ sprintf(uhost, "*%s", tmp);
+ }
+ }
+
+ sendto_ops("%s added a temp k:line for %s@%s %s", parv[0], name, uhost, parv[2] ? parv[2] : "");
+ aLog = fopen(lPATH, "a");
+ if (aLog)
+ {
+ fprintf(aLog, "(%s) %s added a temp k:line for %s@%s %s", myctime(TStime()), parv[0], name, uhost, parv[2] ? parv[2] : "");
+ fclose(aLog);
+ }
+
+ add_temp_conf(CONF_KILL, uhost, parv[2], name, 0, 0, 1);
+ check_pings(TStime(), 1);
+ }
+
+
+/*
+ * m_unkline
+ * parv[0] = sender prefix
+ * parv[1] = userhost
+ */
+
+int m_unkline(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+
+ int result, temp;
+ char *hosttemp=parv[1], host[80], name[80];
+ FILE *aLog;
+
+ if (!MyClient(sptr) || !OPCanUnKline(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ if (parc<2)
+ {
+ sendto_one(sptr,"NOTICE %s :Not enough parameters", parv[0]);
+ return 0;
+ }
+ if (hosttemp = (char *) strchr((char *)parv[1], '@'))
+ {
+ temp = 0;
+ while (temp <= 20)
+ name[temp++] = 0;
+ strcpy(host, ++hosttemp);
+ strncpy(name, parv[1], hosttemp-1-parv[1]);
+ if (name[0] == '\0' || host[0] == '\0')
+ {
+ Debug((DEBUG_INFO, "UNKLINE: Bad field"));
+ sendto_one(sptr, "NOTICE %s : Both user and host fields must be non-null", parv[0]);
+ return 0;
+ }
+ result = del_temp_conf(CONF_KILL, host, NULL, name,
+ NULL, NULL, 0);
+ if (result == KLINE_RET_AKILL) { /* akill - result = 3 */
+ sendto_one(sptr, "NOTICE %s :You may not remove autokills. Only U:lined clients may.", parv[0]);
+ return 0;
+ }
+ if (result == KLINE_RET_PERM) { /* Not a temporary line - result =2 */
+ sendto_one(sptr,"NOTICE %s :You may not remove permanent K:Lines - talk to the admin", parv[0]);
+ return 0;
+ }
+ if (result == KLINE_RET_DELOK) { /* Successful result = 1*/
+ sendto_one(sptr,"NOTICE %s :Temp K:Line %s@%s is now removed.", parv[0],name,host);
+ sendto_ops("%s removed temp k:line %s@%s", parv[0], name, host);
+ aLog = fopen(lPATH, "a");
+ if (aLog)
+ {
+ fprintf(aLog, "(%s) %s removed temp k:line %s@%s", myctime(TStime()), parv[0], name, host);
+ fclose(aLog);
+ }
+ return 0;
+ }
+ if (result == KLINE_DEL_ERR) { /* Unsuccessful result = 0*/
+ sendto_one(sptr,"NOTICE %s :Temporary K:Line %s@%s not found", parv[0],name,host);
+ return 0;
+ }
+ }
+ /* This wasn't here before -- Barubary */
+ check_pings(TStime(), 1);
+}
+
+/*
+ * m_zline add a temporary zap line
+ * parv[0] = sender prefix
+ * parv[1] = host
+ * parv[2] = reason
+ */
+
+int m_zline(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ char userhost[512+2]="", *in;
+ int result=0, uline=0, i=0, propo=0;
+ char *reason, *mask, *server, *person;
+ aClient *acptr;
+
+ reason=mask=server=person=NULL;
+
+ reason = ((parc>=3) ? parv[parc-1] : "Reason unspecified");
+ mask = ((parc>=2) ? parv[parc-2] : NULL);
+ server = ((parc>=4) ? parv[parc-1] : NULL);
+
+ if (parc == 4)
+ {
+ mask = parv[parc-3];
+ server = parv[parc-2];
+ reason = parv[parc-1];
+ }
+
+ uline = IsULine(cptr, sptr) ? 1 : 0;
+
+ if (!uline && (!MyConnect(sptr) || !OPCanZline(sptr) || !IsOper(sptr)))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return -1;
+ }
+
+ if (uline)
+ {
+ if (parc>=4 && server)
+ {
+ if (hunt_server(cptr, sptr, ":%s ZLINE %s %s :%s", 2, parc, parv)
+ != HUNTED_ISME)
+ return 0;
+ else ;
+ }
+ else propo=1;
+ }
+
+ if (parc < 2)
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "ZLINE");
+ return -1;
+ }
+
+ if (acptr = find_client(parv[1], NULL))
+ {
+ strcpy(userhost, inetntoa((char *) &acptr->ip));
+ person = &acptr->name[0];
+ acptr = NULL;
+ }
+ /* z-lines don't support user@host format, they only
+ work with ip addresses and nicks */
+ else
+ if ((in = index(parv[1], '@')) && (*(in+1)!='\0'))
+ {
+ strcpy(userhost, in+1);
+ in = &userhost[0];
+ while(*in)
+ {
+ if (!isdigit(*in) && !ispunct(*in))
+ {
+ sendto_one(sptr, ":%s NOTICE %s :z:lines work only with ip addresses (you cannot specify ident either)", me.name, sptr->name);
+ return;
+ }
+ in++;
+ }
+ } else if (in && !(*(in+1))) /* sheesh not only specifying a ident@, but
+ omitting the ip...?*/
+ {
+ sendto_one(sptr, ":%s NOTICE %s :Hey! z:lines need an ip address...",
+ me.name, sptr->name);
+ return -1;
+ }
+ else
+ {
+ strcpy(userhost, parv[1]);
+ in = &userhost[0];
+ while(*in)
+ {
+ if (!isdigit(*in) && !ispunct(*in))
+ {
+ sendto_one(sptr, ":%s NOTICE %s :z:lines work only with ip addresses (you cannot specify ident either)", me.name, sptr->name);
+ return;
+ }
+ in++;
+ }
+ }
+
+ /* this'll protect against z-lining *.* or something */
+ if (advanced_check(userhost, TRUE) == FALSE)
+ {
+ sendto_ops("Bad z:line mask from %s *@%s [%s]", parv[0], userhost, reason?reason:"");
+ if (MyClient(sptr))
+ sendto_one(sptr, ":%s NOTICE %s :*@%s is a bad z:line mask...", me.name, sptr->name, userhost);
+ return;
+ }
+
+ if (uline == 0)
+ {
+ if (person)
+ sendto_ops("%s added a temp z:line for %s (*@%s) [%s]", parv[0], person, userhost, reason?reason:"");
+ else
+ sendto_ops("%s added a temp z:line *@%s [%s]", parv[0], userhost, reason?reason:"");
+ (void) add_temp_conf(CONF_ZAP, userhost, reason, NULL, 0, 0, KLINE_TEMP);
+ }
+ else
+ {
+ if (person)
+ sendto_ops("%s z:lined %s (*@%s) on %s [%s]", parv[0], person, userhost, server?server:ircnetwork , reason?reason:"");
+ else
+ sendto_ops("%s z:lined *@%s on %s [%s]", parv[0], userhost, server?server:ircnetwork , reason?reason:"");
+ (void) add_temp_conf(CONF_ZAP, userhost, reason, NULL, 0, 0, KLINE_AKILL);
+ }
+
+ /* something's wrong if i'm
+ zapping the command source... */
+ if (find_zap(cptr, 0)||find_zap(sptr, 0))
+ {
+ sendto_failops_whoare_opers("z:line error: mask=%s parsed=%s I tried to zap cptr", mask, userhost);
+ sendto_serv_butone(NULL,":%s GLOBOPS :z:line error: mask=%s parsed=%s I tried to zap cptr", me.name, mask, userhost);
+ flush_connections(me.fd);
+ (void)rehash(&me, &me, 0);
+ return;
+ }
+#ifdef PRECISE_CHECK
+ for (i=highest_fd;i>0;i--)
+ {
+ if (!(acptr = local[i]) || IsLog(acptr) || IsMe(acptr));
+ continue;
+#else
+ for (acptr = &me; acptr; acptr = acptr->prev)
+ {
+ if (IsMe(cptr) || !MyClient(cptr) || IsLog(cptr))
+ continue;
+#endif
+
+ if ( find_zap(acptr, 1) )
+ {
+ if (!IsServer(acptr))
+ {
+ sendto_one(sptr,":%s NOTICE %s :*** %s %s",
+ me.name, sptr->name,
+ acptr->name[0]?acptr->name:"<unknown>");
+ exit_client(acptr, acptr, acptr, "z-lined");
+ }
+ else
+ {
+ sendto_one(sptr, ":%s NOTICE %s :*** exiting %s",
+ me.name, sptr->name, acptr->name);
+ sendto_ops("dropping server %s (z-lined)", acptr->name);
+ sendto_serv_butone(cptr, "GNOTICE :dropping server %s (z-lined)",
+ acptr->name);
+ exit_client(acptr, acptr, acptr, "z-lined");
+
+ }
+ }
+ }
+
+ if (propo==1) /* propo is if a ulined server is propagating a z-line
+ this should go after the above check */
+ sendto_serv_butone(cptr, ":%s ZLINE %s :%s", parv[0], parv[1], reason?reason:"");
+
+ check_pings(TStime(), 1);
+
+}
+
+
+/*
+ * m_unzline remove a temporary zap line
+ * parv[0] = sender prefix
+ * parv[1] = host
+ */
+
+int m_unzline(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+char userhost[512+2]="", *in;
+int result=0, uline=0, akill=0;
+aConfItem *aconf, *tmp;
+aConfItem dummy;
+char *mask, *server;
+
+uline = IsULine(cptr, sptr)? 1 : 0;
+
+ if (parc < 2)
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "UNZLINE");
+ return -1;
+ }
+
+
+ if (parc < 3 || !uline)
+ {
+ mask = parv[parc-1];
+ server = NULL;
+ }
+ else if (parc == 3)
+ {
+ mask = parv[parc-2];
+ server = parv[parc-1];
+ }
+
+ if (!uline && (!MyConnect(sptr) || !OPCanZline(sptr) || !IsOper(sptr)))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return -1;
+ }
+
+ /* before we even check ourselves we need to do the uline checks
+ because we aren't supposed to add a z:line if the message is
+ destined to be passed on...*/
+
+ if (uline)
+ {
+ if (parc == 3 && server)
+ {
+ if (hunt_server(cptr, sptr, ":%s UNZLINE %s %s", 2, parc, parv) != HUNTED_ISME)
+ return 0;
+ else ;
+ }
+ else
+ sendto_serv_butone(cptr, ":%s UNZLINE %s", parv[0], parv[1]);
+
+ }
+
+
+ /* parse the removal mask the same way so an oper can just use
+ the same thing to remove it if they specified *@ or something... */
+ if ((in = index(parv[1], '@')))
+ {
+ strcpy(userhost, in+1);
+ in = &userhost[0];
+ while(*in)
+ {
+ if (!isdigit(*in) && !ispunct(*in))
+ {
+ sendto_one(sptr, ":%s NOTICE %s :it's not possible to have a z:line that's not an ip addresss...", me.name, sptr->name);
+ return;
+ }
+ in++;
+ }
+ }
+ else
+ {
+ strcpy(userhost, parv[1]);
+ in = &userhost[0];
+ while(*in)
+ {
+ if (!isdigit(*in) && !ispunct(*in))
+ {
+ sendto_one(sptr, ":%s NOTICE %s :it's not possible to have a z:line that's not an ip addresss...", me.name, sptr->name);
+ return;
+ }
+ in++;
+ }
+ }
+
+ akill = 0;
+retry_unzline:
+
+ if (uline == 0)
+ {
+ result = del_temp_conf(CONF_ZAP, userhost, NULL, NULL, 0, 0, akill);
+ if ((result) == KLINE_RET_DELOK)
+ {
+ sendto_one(sptr,":%s NOTICE %s :temp z:line *@%s removed", me.name, parv[0], userhost);
+ sendto_ops("%s removed temp z:line *@%s", parv[0], userhost);
+ }
+ else if (result == KLINE_RET_PERM)
+ sendto_one(sptr, ":%s NOTICE %s :You may not remove permanent z:lines talk to your admin...", me.name, sptr->name);
+
+ else if (result == KLINE_RET_AKILL && !(sptr->umodes & UMODE_SADMIN))
+ {
+ sendto_one(sptr, ":%s NOTICE %s :You may not remove z:lines placed by services...", me.name, sptr->name);
+ }
+ else if (result == KLINE_RET_AKILL && !akill)
+ {
+ akill=1;
+ goto retry_unzline;
+ }
+ else
+ sendto_one(sptr, ":%s NOTICE %s :Couldn't find/remove zline for *@%s", me.name, sptr->name, userhost);
+
+ }
+ else
+ { /* services did it, services should be able to remove
+ both types...;> */
+ if (del_temp_conf(CONF_ZAP, userhost, NULL, NULL, 0, 0, 1) == KLINE_RET_DELOK||
+ del_temp_conf(CONF_ZAP, userhost, NULL, NULL, 0, 0, 0) == KLINE_RET_DELOK)
+ {
+ if (MyClient(sptr))
+ sendto_one(sptr,"NOTICE %s :temp z:line *@%s removed", parv[0], userhost);
+ sendto_ops("%s removed temp z:line *@%s", parv[0], userhost);
+ }
+ else
+ sendto_one(sptr, ":%s NOTICE %s :ERROR Removing z:line", me.name, sptr->name);
+ }
+
+}
+
+
+/* ok, given a mask, our job is to determine
+ * wether or not it's a safe mask to banish...
+ *
+ * userhost= mask to verify
+ * ipstat= TRUE == it's an ip
+ * FALSE == it's a hostname
+ * UNSURE == we need to find out
+ * return value
+ * TRUE == mask is ok
+ * FALSE == mask is not ok
+ * UNSURE == [unused] something went wrong
+ */
+
+advanced_check(char *userhost, int ipstat)
+{
+ register int retval = TRUE;
+ char *up, *p, *thisseg;
+ int numdots=0, segno=0, numseg, i=0;
+ char *ipseg[10+2];
+ char safebuffer[512]=""; /* buffer strtoken() can mess up to its heart's content...;>*/
+
+ strcpy(safebuffer, userhost);
+
+#define userhost safebuffer
+#define IP_WILDS_OK(x) ((x)<2? 0 : 1)
+
+ if (ipstat == UNSURE)
+ {
+ ipstat=TRUE;
+ for (;*up;up++)
+ {
+ if (*up=='.') numdots++;
+ if (!isdigit(*up) && !ispunct(*up)) {ipstat=FALSE; continue;}
+ }
+ if (numdots != 3) ipstat=FALSE;
+ if (numdots < 1 || numdots > 9) return(0);
+ }
+
+ /* fill in the segment set */
+ {
+ int l = 0;
+ for (segno = 0, i = 0, thisseg = strtoken(&p, userhost, "."); thisseg;
+ thisseg = strtoken(&p, NULL, "."), i++)
+ {
+
+ l = strlen(thisseg)+2;
+ ipseg[segno] = calloc(1, l);
+ strncpy(ipseg[segno++], thisseg, l);
+ }
+ }
+ if (segno < 2 && ipstat==TRUE) retval = FALSE;
+ numseg = segno;
+ if (ipstat==TRUE)
+ for(i=0;i<numseg;i++)
+ {
+ if (!IP_WILDS_OK(i) && index(ipseg[i], '*')||index(ipseg[i], '?'))
+ retval=FALSE;
+ MyFree(ipseg[i]);
+ }
+ else
+ {
+ int wildsok=0;
+
+ for(i=0;i<numseg;i++)
+ {
+ /* for hosts, let the mask extent all the way to
+ the second-level domain... */
+ wildsok=1;
+ if (i==numseg||(i+1)==numseg) wildsok=0;
+ if (wildsok == 0 && (index(ipseg[i], '*')||index(ipseg[i], '?')))
+ {
+ retval=FALSE;
+ }
+ MyFree(ipseg[i]);
+ }
+
+
+ }
+
+ return(retval);
+#undef userhost
+#undef IP_WILDS_OK
+
+}
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, ircd/s_debug.c
+ * Copyright (C) 1990 Jarkko Oikarinen and
+ * University of Oulu, Computing Center
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#ifndef lint
+static char sccsid[] = "@(#)s_debug.c 2.30 1/3/94 (C) 1988 University of Oulu, \
+Computing Center and Jarkko Oikarinen";
+#endif
+
+#include "struct.h"
+/*
+ * Option string. Must be before #ifdef DEBUGMODE.
+ */
+char serveropts[] = {
+#ifdef SENDQ_ALWAYS
+'A',
+#endif
+#ifdef CHROOTDIR
+'c',
+#endif
+#ifdef CMDLINE_CONFIG
+'C',
+#endif
+#ifdef DO_ID
+'d',
+#endif
+#ifdef DEBUGMODE
+'D',
+#endif
+#ifdef NOTE_FORWARDER
+'f',
+#endif
+#ifndef NO_FDLIST
+'F',
+#endif
+#ifdef HUB
+'h',
+#endif
+#ifdef SHOW_INVISIBLE_LUSERS
+'i',
+#endif
+#ifndef NO_DEFAULT_INVISIBLE
+'I',
+#endif
+#ifdef LEAST_IDLE
+'L',
+#endif
+#ifdef M4_PREPROC
+'m',
+#endif
+#ifdef IDLE_FROM_MSG
+'M',
+#endif
+#ifdef CRYPT_OPER_PASSWORD
+'p',
+#endif
+#ifdef CRYPT_LINK_PASSWORD
+'P',
+#endif
+#ifdef NOSPOOF
+'n',
+#endif
+#ifdef NPATH
+'N',
+#endif
+#ifdef SCRIPTINIFIX
+'s',
+#endif
+#ifdef ENABLE_SUMMON
+'S',
+#endif
+#ifdef IRCII_KLUDGE
+'u',
+#endif
+#ifdef ENABLE_USERS
+'U',
+#endif
+#ifdef VALLOC
+'V',
+#endif
+#ifdef REMOVE_ADVERTISING
+'R',
+#endif
+#ifdef _WIN32
+'W',
+#endif
+#ifdef USE_SYSLOG
+'Y',
+#endif
+#ifdef V28PlusOnly
+'8',
+#endif
+#ifdef SCRIPTINIFIX
+'S',
+#endif
+#ifdef OPER_NO_HIDING
+'H',
+#endif
+'\0'};
+
+#include "numeric.h"
+#include "common.h"
+#include "sys.h"
+#include "whowas.h"
+#include "hash.h"
+#ifndef _WIN32
+#include <sys/file.h>
+#endif
+#ifdef HPUX
+#include <fcntl.h>
+#endif
+#if !defined(ULTRIX) && !defined(SGI) && !defined(sequent) && \
+ !defined(__convex__) && !defined(_WIN32)
+# include <sys/param.h>
+#endif
+#ifdef HPUX
+# include <sys/syscall.h>
+# define getrusage(a,b) syscall(SYS_GETRUSAGE, a, b)
+#endif
+#ifdef GETRUSAGE_2
+# ifdef SOL20
+# include <sys/time.h>
+# ifdef RUSAGEH
+# include <sys/rusage.h>
+# endif
+# endif
+# include <sys/resource.h>
+#else
+# ifdef TIMES_2
+# include <sys/times.h>
+# endif
+#endif
+#ifdef PCS
+# include <time.h>
+#endif
+#ifdef HPUX
+#include <unistd.h>
+#ifdef DYNIXPTX
+#include <sys/types.h>
+#include <time.h>
+#endif
+#endif
+#include "h.h"
+
+#ifndef ssize_t
+#define ssize_t unsigned int
+#endif
+
+ID_CVS("$Id$");
+
+#ifdef DEBUGMODE
+static char debugbuf[1024];
+
+#ifndef USE_VARARGS
+/*VARARGS2*/
+void debug(level, form, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)
+int level;
+char *form, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10;
+{
+# ifndef _WIN32
+ int err = errno;
+# else
+ int err = WSAGetLastError();
+# endif
+#else
+void debug(level, form, va_alist)
+int level;
+char *form;
+va_dcl
+{
+ va_list vl;
+# ifndef _WIN32
+ int err = errno;
+# else
+ int err = WSAGetLastError();
+# endif
+
+ va_start(vl);
+#endif
+
+ if ((debuglevel >= 0) && (level <= debuglevel))
+ {
+#ifndef USE_VARARGS
+ (void)sprintf(debugbuf, form,
+ p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
+#else
+ (void)vsprintf(debugbuf, form, vl);
+#endif
+
+#ifndef _WIN32
+ if (local[2])
+ {
+ local[2]->sendM++;
+ local[2]->sendB += strlen(debugbuf);
+ }
+ (void)fprintf(stderr, "%s", debugbuf);
+ (void)fputc('\n', stderr);
+ }
+ errno = err;
+#else
+ strcat(debugbuf, "\r");
+#ifndef _WIN32GUI
+ Cio_Puts(hCio, debugbuf, strlen(debugbuf));
+#endif
+ }
+ WSASetLastError(err);
+#endif
+}
+
+/*
+ * This is part of the STATS replies. There is no offical numeric for this
+ * since this isnt an official command, in much the same way as HASH isnt.
+ * It is also possible that some systems wont support this call or have
+ * different field names for "struct rusage".
+ * -avalon
+ */
+void send_usage(cptr, nick)
+aClient *cptr;
+char *nick;
+{
+
+#ifdef GETRUSAGE_2
+ struct rusage rus;
+ time_t secs, rup;
+#ifdef hz
+# define hzz hz
+#else
+# ifdef HZ
+# define hzz HZ
+# else
+ int hzz = 1;
+# ifdef HPUX
+ hzz = (int)sysconf(_SC_CLK_TCK);
+# endif
+# endif
+#endif
+
+ if (getrusage(RUSAGE_SELF, &rus) == -1)
+ {
+#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__APPLE__)
+/* extern char *sys_errlist[]; */
+#endif
+ sendto_one(cptr,":%s NOTICE %s :Getruseage error: %s.",
+ me.name, nick, sys_errlist[errno]);
+ return;
+ }
+ secs = rus.ru_utime.tv_sec + rus.ru_stime.tv_sec;
+ rup = time(NULL) - me.since;
+ if (secs == 0)
+ secs = 1;
+
+ sendto_one(cptr,
+ ":%s %d %s :CPU Secs %d:%d User %d:%d System %d:%d",
+ me.name, RPL_STATSDEBUG, nick, secs/60, secs%60,
+ rus.ru_utime.tv_sec/60, rus.ru_utime.tv_sec%60,
+ rus.ru_stime.tv_sec/60, rus.ru_stime.tv_sec%60);
+ sendto_one(cptr, ":%s %d %s :RSS %d ShMem %d Data %d Stack %d",
+ me.name, RPL_STATSDEBUG, nick, rus.ru_maxrss,
+ rus.ru_ixrss / (rup * hzz), rus.ru_idrss / (rup * hzz),
+ rus.ru_isrss / (rup * hzz));
+ sendto_one(cptr, ":%s %d %s :Swaps %d Reclaims %d Faults %d",
+ me.name, RPL_STATSDEBUG, nick, rus.ru_nswap,
+ rus.ru_minflt, rus.ru_majflt);
+ sendto_one(cptr, ":%s %d %s :Block in %d out %d",
+ me.name, RPL_STATSDEBUG, nick, rus.ru_inblock,
+ rus.ru_oublock);
+ sendto_one(cptr, ":%s %d %s :Msg Rcv %d Send %d",
+ me.name, RPL_STATSDEBUG, nick, rus.ru_msgrcv, rus.ru_msgsnd);
+ sendto_one(cptr, ":%s %d %s :Signals %d Context Vol. %d Invol %d",
+ me.name, RPL_STATSDEBUG, nick, rus.ru_nsignals,
+ rus.ru_nvcsw, rus.ru_nivcsw);
+#else
+# ifdef TIMES_2
+ struct tms tmsbuf;
+ time_t secs, mins;
+ int hzz = 1, ticpermin;
+ int umin, smin, usec, ssec;
+
+# ifdef HPUX
+ hzz = sysconf(_SC_CLK_TCK);
+# endif
+ ticpermin = hzz * 60;
+
+ umin = tmsbuf.tms_utime / ticpermin;
+ usec = (tmsbuf.tms_utime%ticpermin)/(float)hzz;
+ smin = tmsbuf.tms_stime / ticpermin;
+ ssec = (tmsbuf.tms_stime%ticpermin)/(float)hzz;
+ secs = usec + ssec;
+ mins = (secs/60) + umin + smin;
+ secs %= hzz;
+
+ if (times(&tmsbuf) == -1)
+ {
+ sendto_one(cptr,":%s %d %s :times(2) error: %s.",
+# ifndef _WIN32
+ me.name, RPL_STATSDEBUG, nick, strerror(errno));
+# else
+ me.name, RPL_STATSDEBUG, nick,
+ strerror(WSAGetLastError()));
+# endif
+ return;
+ }
+ secs = tmsbuf.tms_utime + tmsbuf.tms_stime;
+
+ sendto_one(cptr,
+ ":%s %d %s :CPU Secs %d:%d User %d:%d System %d:%d",
+ me.name, RPL_STATSDEBUG, nick, mins, secs, umin, usec,
+ smin, ssec);
+# endif
+#endif
+ sendto_one(cptr, ":%s %d %s :Reads %d Writes %d",
+ me.name, RPL_STATSDEBUG, nick, readcalls, writecalls);
+ sendto_one(cptr, ":%s %d %s :DBUF alloc %d blocks %d",
+ me.name, RPL_STATSDEBUG, nick, dbufalloc, dbufblocks);
+ sendto_one(cptr,
+ ":%s %d %s :Writes: <0 %d 0 %d <16 %d <32 %d <64 %d",
+ me.name, RPL_STATSDEBUG, nick,
+ writeb[0], writeb[1], writeb[2], writeb[3], writeb[4]);
+ sendto_one(cptr,
+ ":%s %d %s :<128 %d <256 %d <512 %d <1024 %d >1024 %d",
+ me.name, RPL_STATSDEBUG, nick,
+ writeb[5], writeb[6], writeb[7], writeb[8], writeb[9]);
+ return;
+}
+#endif
+
+void count_memory(cptr, nick)
+aClient *cptr;
+char *nick;
+{
+ extern aChannel *channel;
+ extern aClass *classes;
+ extern aConfItem *conf;
+ extern int flinks;
+ extern Link *freelink;
+
+ aClient *acptr;
+ Ban *ban;
+ Link *link;
+ aChannel *chptr;
+ aConfItem *aconf;
+ aClass *cltmp;
+
+ int lc = 0, /* local clients */
+ ch = 0, /* channels */
+ lcc = 0, /* local client conf links */
+ rc = 0, /* remote clients */
+ us = 0, /* user structs */
+ chu = 0, /* channel users */
+ chi = 0, /* channel invites */
+ chb = 0, /* channel bans */
+ wwu = 0, /* whowas users */
+ fl = 0, /* free links */
+ cl = 0, /* classes */
+ co = 0; /* conf lines */
+
+ int usi = 0, /* users invited */
+ usc = 0, /* users in channels */
+ aw = 0, /* aways set */
+ wwa = 0, /* whowas aways */
+ wlh = 0, /* watchlist headers */
+ wle = 0; /* watchlist entries */
+
+ u_long chm = 0, /* memory used by channels */
+ chbm = 0, /* memory used by channel bans */
+ lcm = 0, /* memory used by local clients */
+ rcm = 0, /* memory used by remote clients */
+ awm = 0, /* memory used by aways */
+ wwam = 0, /* whowas away memory used */
+ wwm = 0, /* whowas array memory used */
+ com = 0, /* memory used by conf lines */
+ wlhm = 0, /* watchlist memory used */
+ db = 0, /* memory used by dbufs */
+ rm = 0, /* res memory used */
+ totcl = 0,
+ totch = 0,
+ totww = 0,
+ tot = 0;
+
+ count_whowas_memory(&wwu, &wwa, &wwam);
+ count_watch_memory(&wlh, &wlhm);
+ wwm = sizeof(aName) * NICKNAMEHISTORYLENGTH;
+
+ for (acptr = client; acptr; acptr = acptr->next)
+ {
+ if (MyConnect(acptr))
+ {
+ lc++;
+ for (link = acptr->confs; link; link = link->next)
+ lcc++;
+ wle += acptr->notifies;
+ }
+ else
+ rc++;
+ if (acptr->user)
+ {
+ us++;
+ for (link = acptr->user->invited; link;
+ link = link->next)
+ usi++;
+ for (link = acptr->user->channel; link;
+ link = link->next)
+ usc++;
+ if (acptr->user->away)
+ {
+ aw++;
+ awm += (strlen(acptr->user->away)+1);
+ }
+ }
+ }
+ lcm = lc * CLIENT_LOCAL_SIZE;
+ rcm = rc * CLIENT_REMOTE_SIZE;
+
+ for (chptr = channel; chptr; chptr = chptr->nextch)
+ {
+ ch++;
+ chm += (strlen(chptr->chname) + sizeof(aChannel));
+ for (link = chptr->members; link; link = link->next)
+ chu++;
+ for (link = chptr->invites; link; link = link->next)
+ chi++;
+ for (ban = chptr->banlist; ban; ban = ban->next)
+ {
+ chb++;
+ chbm += (strlen(ban->banstr)+1+
+ strlen(ban->who)+1+sizeof(Ban));
+ }
+ }
+
+ for (aconf = conf; aconf; aconf = aconf->next)
+ {
+ co++;
+ com += aconf->host ? strlen(aconf->host)+1 : 0;
+ com += aconf->passwd ? strlen(aconf->passwd)+1 : 0;
+ com += aconf->name ? strlen(aconf->name)+1 : 0;
+ com += sizeof(aConfItem);
+ }
+
+ for (cltmp = classes; cltmp; cltmp = cltmp->next)
+ cl++;
+
+ sendto_one(cptr, ":%s %d %s :Client Local %d(%d) Remote %d(%d)",
+ me.name, RPL_STATSDEBUG, nick, lc, lcm, rc, rcm);
+ sendto_one(cptr, ":%s %d %s :Users %d(%d) Invites %d(%d)",
+ me.name, RPL_STATSDEBUG, nick, us, us*sizeof(anUser), usi,
+ usi * sizeof(Link));
+ sendto_one(cptr, ":%s %d %s :User channels %d(%d) Aways %d(%d)",
+ me.name, RPL_STATSDEBUG, nick, usc, usc*sizeof(Link),
+ aw, awm);
+ sendto_one(cptr, ":%s %d %s :WATCH headers %d(%d) entries %d(%d)",
+ me.name, RPL_STATSDEBUG, nick, wlh, wlhm,
+ wle, wle*sizeof(Link));
+ sendto_one(cptr, ":%s %d %s :Attached confs %d(%d)",
+ me.name, RPL_STATSDEBUG, nick, lcc, lcc*sizeof(Link));
+
+ totcl = lcm + rcm + us*sizeof(anUser) + usc*sizeof(Link) + awm;
+ totcl += lcc*sizeof(Link) + usi*sizeof(Link) + wlhm;
+ totcl += wle*sizeof(Link);
+
+ sendto_one(cptr, ":%s %d %s :Conflines %d(%d)",
+ me.name, RPL_STATSDEBUG, nick, co, com);
+
+ sendto_one(cptr, ":%s %d %s :Classes %d(%d)",
+ me.name, RPL_STATSDEBUG, nick, cl, cl*sizeof(aClass));
+
+ sendto_one(cptr, ":%s %d %s :Channels %d(%d) Bans %d(%d)",
+ me.name, RPL_STATSDEBUG, nick, ch, chm, chb, chbm);
+ sendto_one(cptr, ":%s %d %s :Channel membrs %d(%d) invite %d(%d)",
+ me.name, RPL_STATSDEBUG, nick, chu, chu*sizeof(Link),
+ chi, chi*sizeof(Link));
+
+ totch = chm + chbm + chu*sizeof(Link) + chi*sizeof(Link);
+
+ sendto_one(cptr, ":%s %d %s :Whowas users %d(%d) away %d(%d)",
+ me.name, RPL_STATSDEBUG, nick, wwu, wwu*sizeof(anUser),
+ wwa, wwam);
+ sendto_one(cptr, ":%s %d %s :Whowas array %d(%d)",
+ me.name, RPL_STATSDEBUG, nick, NICKNAMEHISTORYLENGTH, wwm);
+
+ totww = wwu*sizeof(anUser) + wwam + wwm;
+
+ sendto_one(cptr, ":%s %d %s :Hash: client %d(%d) chan %d(%d) watch %d(%d)",
+ me.name, RPL_STATSDEBUG, nick, HASHSIZE,
+ sizeof(aHashEntry) * HASHSIZE,
+ CHANNELHASHSIZE, sizeof(aHashEntry) * CHANNELHASHSIZE,
+ NOTIFYHASHSIZE, sizeof(aNotify *) * NOTIFYHASHSIZE);
+ db = dbufblocks * sizeof(dbufbuf);
+ sendto_one(cptr, ":%s %d %s :Dbuf blocks %d(%d)",
+ me.name, RPL_STATSDEBUG, nick, dbufblocks, db);
+
+ link=freelink; while(link=link->next) fl++; fl++;
+ sendto_one(cptr, ":%s %d %s :Link blocks free %d(%d) total %d(%d)",
+ me.name, RPL_STATSDEBUG, nick, fl, fl*sizeof(Link),
+ flinks, flinks*sizeof(Link));
+
+ rm = cres_mem(cptr);
+
+ tot = totww + totch + totcl + com + cl*sizeof(aClass) + db + rm;
+ tot += fl*sizeof(Link);
+ tot += sizeof(aHashEntry) * HASHSIZE;
+ tot += sizeof(aHashEntry) * CHANNELHASHSIZE;
+ tot += sizeof(aNotify *) * NOTIFYHASHSIZE;
+
+ sendto_one(cptr, ":%s %d %s :Total: ww %d ch %d cl %d co %d db %d",
+ me.name, RPL_STATSDEBUG, nick, totww, totch, totcl, com, db);
+#if !defined(_WIN32) && !defined(_AMIGA)
+#ifdef LINUX_ALPHA
+ sendto_one(cptr, ":%s %d %s :TOTAL: %d sbrk(0)-etext: %u",
+ me.name, RPL_STATSDEBUG, nick, tot,
+ (u_int)sbrk((size_t)0)-(u_int)sbrk0);
+#else
+ sendto_one(cptr, ":%s %d %s :TOTAL: %d sbrk(0)-etext: %ul",
+ me.name, RPL_STATSDEBUG, nick, tot,
+ (u_long)sbrk((size_t)0)-(u_long)sbrk0);
+
+#endif
+#else
+ sendto_one(cptr, ":%s %d %s :TOTAL: %d",
+ me.name, RPL_STATSDEBUG, nick, tot);
+#endif
+ return;
+}
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, ircd/s_err.c
+ * Copyright (C) 1992 Darren Reed
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "struct.h"
+#include "numeric.h"
+#include "common.h"
+
+#ifndef lint
+static char sccsid[] = "@(#)s_err.c 1.12 11/1/93 (C) 1992 Darren Reed";
+#endif
+
+ID_CVS("$Id$");
+
+typedef struct {
+ int num_val;
+ char *num_form;
+} Numeric;
+
+static char *prepbuf PROTO((char *, int, char *));
+static char numbuff[514];
+static char numbers[] = "0123456789";
+
+static Numeric local_replies[] = {
+/* 000 */ 0, (char *)NULL,
+/* 001 */ RPL_WELCOME, ":Welcome to the %s IRC Network %s!%s@%s",
+/* 002 */ RPL_YOURHOST, ":Your host is %s, running version %s",
+/* 003 */ RPL_CREATED, ":This server was created %s",
+/* 004 */ RPL_MYINFO, "%s %s %s %s",
+/* 005 */ RPL_PROTOCTL, "%s :are available on this server",
+/* 006 */ RPL_MAP, ":%s%-*s\2[Users:%5d] [%2d%%]\2",
+/* 007 */ RPL_MAPEND, ":End of /MAP",
+ 0, (char *)NULL
+};
+
+static Numeric numeric_errors[] = {
+/* 401 */ ERR_NOSUCHNICK, "%s :No such nick/channel",
+/* 402 */ ERR_NOSUCHSERVER, "%s :No such server",
+/* 403 */ ERR_NOSUCHCHANNEL, "%s :No such channel",
+/* 404 */ ERR_CANNOTSENDTOCHAN, "%s :Cannot send to channel (%s)",
+/* 405 */ ERR_TOOMANYCHANNELS, "%s :You have joined too many channels",
+/* 406 */ ERR_WASNOSUCHNICK, "%s :There was no such nickname",
+/* 407 */ ERR_TOOMANYTARGETS,
+ "%s :Duplicate recipients. No message delivered",
+/* 408 */ ERR_NOSUCHSERVICE, (char *)NULL,
+/* 409 */ ERR_NOORIGIN, ":No origin specified",
+ 0, (char *)NULL,
+/* 411 */ ERR_NORECIPIENT, ":No recipient given (%s)",
+/* 412 */ ERR_NOTEXTTOSEND, ":No text to send",
+/* 413 */ ERR_NOTOPLEVEL, "%s :No toplevel domain specified",
+/* 414 */ ERR_WILDTOPLEVEL, "%s :Wildcard in toplevel Domain",
+ 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
+ 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
+/* 421 */ ERR_UNKNOWNCOMMAND, "%s :Unknown command",
+/* 422 */ ERR_NOMOTD, ":MOTD File is missing",
+/* 423 */ ERR_NOADMININFO,
+ "%s :No administrative info available",
+/* 424 */ ERR_FILEERROR, ":File error doing %s on %s",
+/* 425*/ ERR_NOOPERMOTD, ":OPERMOTD File is missing",
+ 0, (char *) NULL, 0, (char *)NULL,
+ 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
+/* 431 */ ERR_NONICKNAMEGIVEN, ":No nickname given",
+/* 432 */ ERR_ERRONEUSNICKNAME, "%s :Erroneous Nickname: %s",
+/* 433 */ ERR_NICKNAMEINUSE, "%s :Nickname is already in use.",
+/* 434 */ ERR_NORULES, ":RULES File is missing",
+/* 435 */ ERR_SERVICECONFUSED, (char *)NULL,
+/* 436 */ ERR_NICKCOLLISION, "%s :Nickname collision KILL",
+/* 437 */ ERR_BANNICKCHANGE,
+ "%s :Cannot change nickname while banned on channel",
+/* 438 */ ERR_NCHANGETOOFAST, "%s :Nick change too fast. Please wait %d seconds",
+/* 439 */ ERR_TARGETTOOFAST, "%s :Message target change too fast. Please wait %d seconds",
+/* 440 */ ERR_SERVICESDOWN, "%s :Services are currently down. Please try again later.",
+/* 441 */ ERR_USERNOTINCHANNEL, "%s %s :They aren't on that channel",
+/* 442 */ ERR_NOTONCHANNEL, "%s :You're not on that channel",
+/* 443 */ ERR_USERONCHANNEL, "%s %s :is already on channel",
+/* 444 */ ERR_NOLOGIN, "%s :User not logged in",
+#ifndef ENABLE_SUMMON
+/* 445 */ ERR_SUMMONDISABLED, ":SUMMON has been disabled",
+#else
+ 0, (char *)NULL,
+#endif
+#ifndef ENABLE_USERS
+/* 446 */ ERR_USERSDISABLED, ":USERS has been disabled",
+#else
+ 0, (char *)NULL,
+#endif
+ 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
+ 0, (char *)NULL,
+/* 451 */ ERR_NOTREGISTERED, ":You have not registered",
+ 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
+#ifdef HOSTILENAME
+/* 455 */ ERR_HOSTILENAME, ":Your username %s contained the invalid "
+ "character(s) %s and has been changed to %s. "
+ "Please use only the characters 0-9 a-z A-Z _ - "
+ "or . in your username. Your username is the part "
+ "before the @ in your email address.",
+#else
+ 0, (char *)NULL,
+#endif
+ 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
+/* 459 */ ERR_NOHIDING, "%s :Cannot join channel (+H)",
+/* 460 */ ERR_NOTFORHALFOPS, ":Halfops cannot set mode %c",
+/* 461 */ ERR_NEEDMOREPARAMS, "%s :Not enough parameters",
+/* 462 */ ERR_ALREADYREGISTRED, ":You may not reregister",
+/* 463 */ ERR_NOPERMFORHOST, ":Your host isn't among the privileged",
+/* 464 */ ERR_PASSWDMISMATCH, ":Password Incorrect",
+/* 465 */ ERR_YOUREBANNEDCREEP, ":You are banned from this server. Mail %s for more information",
+/* 466 */ ERR_YOUWILLBEBANNED, (char *)NULL,
+/* 467 */ ERR_KEYSET, "%s :Channel key already set",
+/* 468 */ ERR_ONLYSERVERSCANCHANGE, "%s :Only servers can change that mode",
+/* 469 */ ERR_LINKSET, "%s :Channel link already set",
+/* 470 */ ERR_LINKCHANNEL, "[Link] %s has become full, so you are automatically being transferred to the linked channel %s",
+/* 471 */ ERR_CHANNELISFULL, "%s :Cannot join channel (+l)",
+/* 472 */ ERR_UNKNOWNMODE , "%c :is unknown mode char to me",
+/* 473 */ ERR_INVITEONLYCHAN, "%s :Cannot join channel (+i)",
+/* 474 */ ERR_BANNEDFROMCHAN, "%s :Cannot join channel (+b)",
+/* 475 */ ERR_BADCHANNELKEY, "%s :Cannot join channel (+k)",
+/* 476 */ ERR_BADCHANMASK, "%s :Bad Channel Mask",
+/* 477 */ ERR_NEEDREGGEDNICK, "%s :You need a registered nick to join that channel.",
+/* 478 */ ERR_BANLISTFULL, "%s %s :Channel ban/ignore list is full",
+/* 479 */ ERR_LINKFAIL, "%s :Sorry, the channel has an invalid channel link set.",
+/* 480 */ ERR_CANNOTKNOCK, ":Cannot knock on %s (%s)",
+/* 481 */ ERR_NOPRIVILEGES, ":Permission Denied- You do not have the correct IRC operator privileges",
+/* 482 */ ERR_CHANOPRIVSNEEDED, "%s :You're not channel operator",
+/* 483 */ ERR_CANTKILLSERVER, ":You cant kill a server!",
+/* 484 */ ERR_ATTACKDENY, "%s :Cannot kick protected user %s.",
+/* 485 */ ERR_KILLDENY, ":Cannot kill protected user %s.",
+ 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
+ 0, (char *)NULL, 0, (char *)NULL,
+/* 491 */ ERR_NOOPERHOST, ":No O-lines for your host",
+/* 492 */ ERR_NOSERVICEHOST, (char *)NULL,
+ 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
+ 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
+ 0, (char *)NULL, 0, (char *)NULL,
+/* 501 */ ERR_UMODEUNKNOWNFLAG, ":Unknown MODE flag",
+/* 502 */ ERR_USERSDONTMATCH, ":Cant change mode for other users",
+ 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
+ 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
+ 0, (char *)NULL, 0, (char *)NULL,
+/* 511 */ ERR_SILELISTFULL, "%s :Your silence list is full",
+/* 512 */ ERR_TOOMANYWATCH, "%s :Maximum size for WATCH-list is 128 entries",
+/* 513 */ ERR_NEEDPONG, ":To connect, type /QUOTE PONG %lX",
+ 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
+ 0, (char *)NULL,
+ 518, ":Cannot invite (+I) at channel",
+ 519, ":Cannot join channel (Admin only)",
+ 520, ":Cannot join channel (IRCops only)",
+/* 521 */ ERR_LISTSYNTAX, "Bad list syntax, type /quote list ? or /raw list ?"
+};
+
+static Numeric numeric_replies[] = {
+/* 300 */ RPL_NONE, (char *)NULL,
+/* 301 */ RPL_AWAY, "%s :%s",
+/* 302 */ RPL_USERHOST, ":",
+/* 303 */ RPL_ISON, ":",
+/* 304 */ RPL_TEXT, (char *)NULL,
+/* 305 */ RPL_UNAWAY, ":You are no longer marked as being away",
+/* 306 */ RPL_NOWAWAY, ":You have been marked as being away",
+/* 307 */ RPL_WHOISREGNICK, "%s :is a registered nick",
+/* 308 */ RPL_RULESSTART, ":- %s Server Rules - ",
+/* 309 */ RPL_ENDOFRULES, ":End of RULES command.",
+/* 310 */ RPL_WHOISHELPOP, "%s :is available for help.",
+/* 311 */ RPL_WHOISUSER, "%s %s %s * :%s",
+/* 312 */ RPL_WHOISSERVER, "%s %s :%s",
+/* 313 */ RPL_WHOISOPERATOR, "%s :is %s on %s",
+/* 314 */ RPL_WHOWASUSER, "%s %s %s * :%s",
+/* 315 */ RPL_ENDOFWHO, "%s :End of /WHO list.",
+/* 316 */ RPL_WHOISCHANOP, (char *)NULL,
+/* 317 */ RPL_WHOISIDLE, "%s %ld %ld :seconds idle, signon time",
+/* 318 */ RPL_ENDOFWHOIS, "%s :End of /WHOIS list.",
+/* 319 */ RPL_WHOISCHANNELS, "%s :%s",
+ RPL_WHOISSPECIAL, "%s :%s",
+/* 321 */ RPL_LISTSTART, "Channel :Users Name",
+/* 322 */ RPL_LIST, "%s %d :%s",
+/* 323 */ RPL_LISTEND, ":End of /LIST",
+/* 324 */ RPL_CHANNELMODEIS, "%s %s %s",
+ 0, (char *)NULL, 0, (char *)NULL,
+ 0, (char *)NULL, 0, (char *)NULL,
+/* 329 */ RPL_CREATIONTIME, "%s %lu",
+ 0, (char *)NULL,
+/* 331 */ RPL_NOTOPIC, "%s :No topic is set.",
+/* 332 */ RPL_TOPIC, "%s :%s",
+/* 333 */ RPL_TOPICWHOTIME, "%s %s %lu",
+/* 334 */ RPL_LISTSYNTAX, ":%s",
+/* 335 */ RPL_WHOISBOT, "%s :is a \2Bot\2 on %s",
+ 0, (char *)NULL, 0, (char *)NULL,
+ 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
+/* 341 */ RPL_INVITING, "%s %s",
+/* 342 */ RPL_SUMMONING, "%s :User summoned to irc",
+ 0, (char *)NULL, 0, (char *)NULL,
+ 0, (char *)NULL,
+ RPL_INVITELIST, "%s %s",
+ RPL_ENDOFINVITELIST, "%s :End of Channel Invite List",
+ RPL_EXLIST, "%s %s %s %lu",
+ RPL_ENDOFEXLIST, "%s :End of Channel Exception List",
+ 0, (char *)NULL,
+/* 351 */ RPL_VERSION, "%s(%s).%s %s :%s [%s=%li%s]",
+/* 352 */ RPL_WHOREPLY, "%s %s %s %s %s %s :%d %s",
+/* 353 */ RPL_NAMREPLY, "%s",
+ 354, ":Reserved for Undernet",
+
+ 0, (char *)NULL, 0, (char *)NULL,
+ 0, (char *)NULL, 0, (char *)NULL,
+ 0, (char *)NULL, 0, (char *)NULL,
+/* 361 */ RPL_KILLDONE, (char *)NULL,
+/* 362 */ RPL_CLOSING, "%s :Closed. Status = %d",
+/* 363 */ RPL_CLOSEEND, "%d: Connections Closed",
+/* 364 */ RPL_LINKS, "%s %s :%d %s",
+/* 365 */ RPL_ENDOFLINKS, "%s :End of /LINKS list.",
+/* 366 */ RPL_ENDOFNAMES, "%s :End of /NAMES list.",
+/* 367 */ RPL_BANLIST, "%s %s %s %lu",
+/* 368 */ RPL_ENDOFBANLIST, "%s :End of Channel Ban List",
+/* 369 */ RPL_ENDOFWHOWAS, "%s :End of WHOWAS",
+ 0, (char *)NULL,
+/* 371 */ RPL_INFO, ":%s",
+/* 372 */ RPL_MOTD, ":- %s",
+/* 373 */ RPL_INFOSTART, ":Server INFO",
+/* 374 */ RPL_ENDOFINFO, ":End of /INFO list.",
+/* 375 */ RPL_MOTDSTART, ":- %s Message of the Day - ",
+/* 376 */ RPL_ENDOFMOTD, ":End of /MOTD command.",
+ 0, (char *)NULL,
+/* 378 */ RPL_WHOISHOST, "%s :is connecting from *@%s",
+/* 379 */ RPL_WHOISMODES, "%s is using modes %s",
+ 0, (char *)NULL,
+/* 381 */ RPL_YOUREOPER, ":You are now an IRC Operator",
+/* 382 */ RPL_REHASHING, "%s :Rehashing",
+/* 383 */ RPL_YOURESERVICE, (char *)NULL,
+/* 384 */ RPL_MYPORTIS, "%d :Port to local server is\r\n",
+/* 385 */ RPL_NOTOPERANYMORE, (char *)NULL,
+ 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
+ 0, (char *)NULL, 0, (char *)NULL,
+/* 391 */ RPL_TIME, "%s :%s",
+#ifdef ENABLE_USERS
+/* 392 */ RPL_USERSSTART, ":UserID Terminal Host",
+/* 393 */ RPL_USERS, ":%-8s %-9s %-8s",
+/* 394 */ RPL_ENDOFUSERS, ":End of Users",
+/* 395 */ RPL_NOUSERS, ":Nobody logged in.",
+#else
+ 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
+ 0, (char *)NULL,
+#endif
+ 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
+ 0, (char *)NULL,
+/* 200 */ RPL_TRACELINK, "Link %s%s %s %s",
+/* 201 */ RPL_TRACECONNECTING, "Attempt %d %s",
+/* 202 */ RPL_TRACEHANDSHAKE, "Handshaking %d %s",
+/* 203 */ RPL_TRACEUNKNOWN, "???? %d %s",
+/* 204 */ RPL_TRACEOPERATOR, "Operator %d %s [%s] %ld",
+/* 205 */ RPL_TRACEUSER, "User %d %s [%s] %ld",
+/* 206 */ RPL_TRACESERVER, "Server %d %dS %dC %s %s!%s@%s %ld",
+/* 207 */ RPL_TRACESERVICE, "Service %d %s",
+/* 208 */ RPL_TRACENEWTYPE, "<newtype> 0 %s",
+/* 209 */ RPL_TRACECLASS, "Class %d %d",
+ 0, (char *)NULL,
+/* 211 */ RPL_STATSLINKINFO, (char *)NULL,
+#ifdef DEBUGMODE
+/* 212 */ RPL_STATSCOMMANDS, "%s %u %u %u %u %u %u",
+#else
+/* 212 */ RPL_STATSCOMMANDS, "%s %u %u",
+#endif
+/* 213 */ RPL_STATSCLINE, "%c %s * %s %d %d",
+/* 214 */ RPL_STATSNLINE, "%c %s * %s %d %d",
+/* 215 */ RPL_STATSILINE, "%c %s * %s %d %d",
+/* 216 */ RPL_STATSKLINE, "%c %s %s %s %d %d",
+/* 217 */ RPL_STATSQLINE, "%c %s %s %s %d %d",
+/* 218 */ RPL_STATSYLINE, "%c %d %d %d %d %ld",
+/* 219 */ RPL_ENDOFSTATS, "%c :End of /STATS report",
+/* 220 */ RPL_STATSBLINE, "%c %s %s %s %d %d",
+/* 221 */ RPL_UMODEIS, "%s",
+/* 222 */ RPL_SQLINE_NICK, "%s :%s",
+/* 223 */ RPL_STATSGLINE, "%c %s@%s %li %li %s :%s",
+/* 224 */ RPL_STATSTLINE, "T %s %s %s",
+ 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
+ 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
+/* 231 */ RPL_SERVICEINFO, (char *)NULL,
+/* 232 */ RPL_RULES, ":- %s",
+/* 233 */ RPL_SERVICE, (char *)NULL,
+/* 234 */ RPL_SERVLIST, (char *)NULL,
+/* 235 */ RPL_SERVLISTEND, (char *)NULL,
+ 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
+ 0, (char *)NULL, 0, (char *)NULL,
+/* 241 */ RPL_STATSLLINE, "%c %s * %s %d %d",
+/* 242 */ RPL_STATSUPTIME, ":Server Up %d days, %d:%02d:%02d",
+/* 243 */ RPL_STATSOLINE, "%c %s * %s %s %d",
+/* 244 */ RPL_STATSHLINE, "%c %s * %s %d %d",
+/* 245 */ RPL_STATSSLINE, "%c %s * %s %d %d",
+ 0, (char *)NULL,
+/* 247 */ RPL_STATSXLINE, "X %s %d",
+/* 248 */ RPL_STATSULINE, "%c %s * %s %d %d",
+ 0, (char *)NULL,
+/* 250 */ RPL_STATSCONN,
+ ":Highest connection count: %d (%d clients)",
+/* 251 */ RPL_LUSERCLIENT,
+ ":There are %d users and %d invisible on %d servers",
+/* 252 */ RPL_LUSEROP, "%d :operator(s) online",
+/* 253 */ RPL_LUSERUNKNOWN, "%d :unknown connection(s)",
+/* 254 */ RPL_LUSERCHANNELS, "%d :channels formed",
+/* 255 */ RPL_LUSERME, ":I have %d clients and %d servers",
+/* 256 */ RPL_ADMINME, ":Administrative info about %s",
+/* 257 */ RPL_ADMINLOC1, ":%s",
+/* 258 */ RPL_ADMINLOC2, ":%s",
+/* 259 */ RPL_ADMINEMAIL, ":%s",
+ 0, (char *)NULL,
+/* 261 */ RPL_TRACELOG, "File %s %d",
+ 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
+/* 265 */ RPL_LOCALUSERS, ":Current Local Users: %d Max: %d",
+/* 266 */ RPL_GLOBALUSERS, ":Current Global Users: %d Max: %d",
+ 0, (char *)NULL,
+ 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
+/* 271 */ RPL_SILELIST, "%s %s",
+/* 272 */ RPL_ENDOFSILELIST, ":End of Silence List",
+ 0, (char *)NULL, 0, (char *)NULL,
+/* 275 */ RPL_STATSDLINE, "%c %s %s",
+ 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
+ 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
+ 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
+ 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
+ 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
+ 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
+/* 294 */ RPL_HELPFWD, ":Your help-request has been forwarded to Help Operators",
+/* 295 */ RPL_HELPIGN, ":Your address has been ignored from forwarding"
+};
+
+/*
+ * NOTE: Unlike the others, this one goes strait through, 600-799
+ */
+static Numeric numeric_replies2[] = {
+/* 600 */ RPL_LOGON, "%s %s %s %d :logged online",
+/* 601 */ RPL_LOGOFF, "%s %s %s %d :logged offline",
+/* 602 */ RPL_WATCHOFF, "%s %s %s %d :stopped watching",
+/* 603 */ RPL_WATCHSTAT, ":You have %d and are on %d WATCH entries",
+/* 604 */ RPL_NOWON, "%s %s %s %d :is online",
+/* 605 */ RPL_NOWOFF, "%s %s %s %d :is offline",
+/* 606 */ RPL_WATCHLIST, ":%s",
+/* 607 */ RPL_ENDOFWATCHLIST, ":End of WATCH %c",
+
+/* 610 */ RPL_MAPMORE, ":%s%-*s --> *more*",
+/* 611 */ 0, (char *)NULL,
+/* 612 */ 0, (char *)NULL,
+/* 613 */ 0, (char *)NULL,
+/* 614 */ 0, (char *)NULL,
+/* 615 */ 0, (char *)NULL,
+/* 616 */ 0, (char *)NULL,
+/* 617 */ 0, (char *)NULL,
+/* 618 */ 0, (char *)NULL,
+/* 619 */ 0, (char *)NULL,
+/* 620 */ 0,(char *) NULL,
+/* 621 */ 0,(char *) NULL,
+/* 622 */ 0,(char *) NULL,
+ 0,(char *) NULL,
+ 0,(char *) NULL,
+ 0,(char *) NULL,
+ 0,(char *) NULL,
+ 0,(char *) NULL,
+ 0,(char *) NULL,
+ 0,(char *) NULL,
+ 0,(char *) NULL,
+ 0,(char *) NULL,
+ 0,(char *) NULL,
+ 0,(char *) NULL,
+ 0,(char *) NULL,
+ 0,(char *) NULL,
+ 0,(char *) NULL,
+ 0,(char *) NULL,
+ 0,(char *) NULL,
+ 0,(char *) NULL,
+/* 640 */ RPL_DUMPING, ":Dumping clients matching %s",
+/* 641 */ RPL_DUMPRPL, "%s %s %s %s %s%s%s%s",
+/* 642 */ RPL_EODUMP, ":End of /dusers - %i",
+ 0, (char *) NULL,
+ 0, (char *)NULL
+};
+
+char *err_str(numeric)
+int numeric;
+{
+ Reg1 Numeric *nptr;
+ Reg2 int num = numeric;
+
+ num -= numeric_errors[0].num_val;
+ if (num < 0 || num > ERR_NEEDPONG)
+ (void)sprintf(numbuff,
+ ":%%s %d %%s :INTERNAL ERROR: BAD NUMERIC! %d",
+ numeric, num);
+ else
+ {
+ nptr = &numeric_errors[num];
+ if (!nptr->num_form || !nptr->num_val)
+ (void)sprintf(numbuff,
+ ":%%s %d %%s :NO ERROR FOR NUMERIC ERROR %d",
+ numeric, num);
+ else
+ (void)prepbuf(numbuff, nptr->num_val, nptr->num_form);
+ }
+ return numbuff;
+}
+
+
+char *rpl_str(numeric)
+int numeric;
+{
+ Reg1 Numeric *nptr;
+ Reg2 int num = numeric;
+
+ if (num > 99)
+ num -= (num > 300) ? 300 : 100;
+
+ if ((num < 0 || num > 200) && (num < 300 || num > 499))
+ (void)sprintf(numbuff,
+ ":%%s %d %%s :INTERNAL REPLY ERROR: BAD NUMERIC! %d",
+ numeric, num);
+ else
+ {
+ if (numeric > 599) {
+ num -= 300;
+ nptr = &numeric_replies2[num];
+ }
+ else if (numeric > 99)
+ nptr = &numeric_replies[num];
+ else
+ nptr = &local_replies[num];
+ Debug((DEBUG_NUM, "rpl_str: numeric %d num %d nptr %x %d %x",
+ numeric, num, nptr, nptr->num_val, nptr->num_form));
+ if (!nptr->num_form || !nptr->num_val)
+ (void)sprintf(numbuff,
+ ":%%s %d %%s :NO REPLY FOR NUMERIC ERROR %d",
+ numeric, num);
+ else
+ (void)prepbuf(numbuff, nptr->num_val, nptr->num_form);
+ }
+ return numbuff;
+}
+
+static char *prepbuf(buffer, num, tail)
+char *buffer;
+Reg1 int num;
+char *tail;
+{
+ Reg1 char *s;
+
+ (void)strcpy(buffer, ":%s ");
+ s = buffer + 4;
+
+ *s++ = numbers[num/100];
+ num %= 100;
+ *s++ = numbers[num/10];
+ *s++ = numbers[num%10];
+ (void)strcpy(s, " %s ");
+ (void)strcpy(s+4, tail);
+ return buffer;
+}
+
+/* this was the old RPL_MYINFO line ....
+ RPL_MYINFO, "%s %s oiwsghOkcSNfraAbexTCWq biklmnopstvRzqxOAqa", */
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, s_extra.c
+ * (C) 1999 Carsten Munk (Techie/Stskeeps) <stskeeps@tspre.org>
+ *
+ * See file AUTHORS in IRC package for additional names of
+ * the programmers.
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#include "numeric.h"
+#include "msg.h"
+#include "channel.h"
+#include "userload.h"
+#include <time.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#ifndef _WIN32
+#include <utmp.h>
+#else
+#include <io.h>
+#endif
+#include <fcntl.h>
+#include "h.h"
+
+ID_CVS("$Id$");
+ID_Copyright("(C) Carsten Munk 1999");
+
+/*
+ fl->type =
+ 0 = set by dccconf.conf
+ 1 = set by services
+ 2 = set by ircops by /dccdeny
+*/
+
+#define AllocCpy(x,y) x = (char *) MyMalloc(strlen(y) + 1); strcpy(x,y)
+#define IRCD_DCCDENY "dccdeny.conf"
+#define IRCD_RESTRICT "chrestrict.conf"
+#define IRCD_VHOST "vhost.conf"
+
+aFline *flines = NULL;
+aCRline *crlines = NULL;
+aVhost *vhosts = NULL;
+aHush *hushes = NULL;
+
+char *cannotjoin_msg = NULL;
+
+/* ircd.dcc configuration */
+
+aFline *dcc_isforbidden(cptr,sptr,target,filename)
+aClient *cptr,*sptr,*target;
+char *filename;
+{
+ aFline *p;
+
+ if (!flines || !target || !filename)
+ return NULL;
+
+ if (IsOper(sptr) || IsULine(cptr, sptr))
+ return NULL;
+
+ if (IsOper(target))
+ return NULL;
+ if (IsVictim(target))
+ {
+ return NULL;
+ }
+ for (p = flines; p; p = p->next)
+ {
+ if (!match(p->mask, filename))
+ return p;
+ }
+
+ /* no target found */
+ return NULL;
+}
+
+int dcc_add_fline(mask, reason, type)
+char *mask, *reason;
+int type;
+{
+ aFline *fl;
+
+ fl = (aFline *) MyMalloc(sizeof(aFline));
+
+ AllocCpy(fl->mask, mask);
+ AllocCpy(fl->reason, reason);
+ fl->type = type;
+ fl->next = flines;
+ fl->prev = NULL;
+ if (flines)
+ flines->prev = fl;
+ flines = fl;
+}
+
+aFline *dcc_del_fline(fl)
+aFline *fl;
+{
+ aFline *p, *q;
+ for (p = flines; p; p = p->next) {
+ if (p == fl)
+ {
+ q = p->next;
+ MyFree((char *) p->mask);
+ MyFree((char *) p->reason);
+ /* chain1 to chain3 */
+ if (p->prev) {
+ p->prev->next = p->next;
+ }
+ else
+ {
+ flines = p->next;
+ }
+ if (p->next) {
+ p->next->prev = p->prev;
+ }
+ MyFree((aFline *) p);
+ return q;
+ }
+ }
+ return NULL;
+}
+
+void dcc_wipe_all(void)
+{
+ aFline *p,q;
+
+ for (p = flines; p; p = p->next)
+ {
+ q.next = dcc_del_fline(p);
+ p = &q;
+ }
+}
+
+aFline *dcc_find(mask)
+char *mask;
+{
+ aFline *p,q;
+
+ for (p = flines; p; p = p->next)
+ {
+ if (!strcmp(p->mask, mask))
+ return(p);
+ }
+ return NULL;
+}
+
+void dcc_rehash(void)
+{
+ aFline *p,q;
+
+ for (p = flines; p; p = p->next)
+ {
+ if ((p->type == 0) || (p->type == 2))
+ {
+ q.next = dcc_del_fline(p);
+ p = &q;
+ }
+ }
+ dcc_loadconf();
+}
+
+void dcc_wipe_services(void)
+{
+ aFline *p,q;
+
+ for (p = flines; p; p = p->next)
+ {
+ if ((p->type == 1))
+ {
+ q.next = dcc_del_fline(p);
+ p = &q;
+ }
+ }
+}
+
+void report_flines(sptr)
+aClient *sptr;
+{
+ aFline *tmp;
+ char *filemask, *reason;
+ char a;
+
+ if (flines)
+ {
+ }
+ for (tmp = flines; tmp; tmp = tmp->next)
+ {
+ filemask = BadPtr(tmp->mask) ? "<NULL>" : tmp->mask;
+ reason = BadPtr(tmp->reason) ? "<NULL>" : tmp->reason;
+ if (tmp->type == 0)
+ a = 'c';
+ if (tmp->type == 1)
+ a = 's';
+ if (tmp->type == 2)
+ a = 'o';
+ sendto_one(sptr, ":%s NOTICE %s :*** (dcc) [%c] %-22s %s", me.name, sptr->name, a, filemask, reason);
+ }
+
+}
+
+/*
+ dccdeny.conf
+ ------------
+# DMSetup trojan
+deny dmsetup.exe - Possible infected file. Please join #nohack for more information
+
+*/
+int dcc_loadconf(void)
+{
+ char buf[2048];
+ char *x,*y,*z;
+ FILE *f;
+
+ f = fopen(IRCD_DCCDENY, "r");
+ if (!f)
+ return -1;
+
+ while (fgets(buf, 2048,f))
+ {
+ iCstrip(buf);
+ x = strtok(buf, " ");
+ if (strcmp("deny", x)==0)
+ {
+ y = strtok(NULL, " ");
+ z = strtok(NULL, "");
+ if (!y || !x)
+ continue;
+ dcc_add_fline(y,z,0);
+ }
+ }
+ return 0;
+}
+
+int m_svsfline(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ if (!IsULine(cptr,sptr))
+ return 0;
+
+ if (parc < 2)
+ return 0;
+
+ switch (*parv[1])
+ {
+ case '+': {
+ if (parc < 4)
+ return 0;
+ dcc_add_fline(parv[2], parv[3], 1);
+ sendto_serv_butone(cptr, ":%s SVSFLINE + %s :%s",
+ sptr->name, parv[2], parv[3]);
+ break;
+ }
+ case '-':
+ {
+ if (parc < 3)
+ return 0;
+ dcc_del_fline(dcc_find(parv[2]));
+ sendto_serv_butone(cptr, ":%s SVSFLINE - %s",
+ sptr->name, parv[2]);
+ break;
+ }
+ case '*':
+ {
+ dcc_wipe_services();
+ sendto_serv_butone(cptr, ":%s SVSFLINE *", sptr->name);
+ break;
+ }
+
+ }
+}
+
+/* restrict channel stuff */
+
+
+int channel_canjoin(sptr,name)
+aClient *sptr;
+char *name;
+{
+ aCRline *p;
+
+ if (IsOper(sptr))
+ return 1;
+ if (IsULine(sptr,sptr))
+ return 1;
+ if (!crlines)
+ return 1;
+ for (p = crlines; p; p = p->next)
+ {
+ if (!match(p->channel, name))
+ return 1;
+ }
+ return 0;
+}
+
+int cr_add(channel, type)
+char *channel;
+int type;
+{
+ aCRline *fl;
+
+ fl = (aCRline *) MyMalloc(sizeof(aCRline));
+
+ AllocCpy(fl->channel, channel);
+ fl->type = type;
+ fl->next = crlines;
+ fl->prev = NULL;
+ if (crlines)
+ crlines->prev = fl;
+ crlines = fl;
+}
+
+aCRline *cr_del(fl)
+aCRline *fl;
+{
+ aCRline *p, *q;
+ for (p = crlines; p; p = p->next) {
+ if (p == fl)
+ {
+ q = p->next;
+ MyFree((char *) p->channel);
+ /* chain1 to chain3 */
+ if (p->prev) {
+ p->prev->next = p->next;
+ }
+ else
+ {
+ crlines = p->next;
+ }
+ if (p->next) {
+ p->next->prev = p->prev;
+ }
+ MyFree((aCRline *) p);
+ return q;
+ }
+ }
+ return NULL;
+}
+
+/*
+ chrestrict.conf
+ ------------
+allow #cafe
+allow #teens
+*/
+int cr_loadconf(void)
+{
+ char buf[2048];
+ char *x,*y;
+ FILE *f;
+
+ f = fopen(IRCD_RESTRICT, "r");
+ if (!f)
+ return -1;
+
+ while (fgets(buf, 2048,f))
+ {
+ iCstrip(buf);
+ x = strtok(buf, " ");
+ if (strcmp("allow", x)==0)
+ {
+ y = strtok(NULL, " ");
+ if (!y)
+ continue;
+ cr_add(y,0);
+ }
+ else
+ if (strcmp("msg", x)==0)
+ {
+ y = strtok(NULL, "");
+ if (!y)
+ continue;
+ if (cannotjoin_msg)
+ MyFree((char *) cannotjoin_msg);
+ cannotjoin_msg = MyMalloc(strlen(y) + 1);
+ strcpy(cannotjoin_msg, y);
+ }
+
+ }
+ return 0;
+}
+
+void cr_rehash(void)
+{
+ aCRline *p,q;
+
+ for (p = crlines; p; p = p->next)
+ {
+ if ((p->type == 0) || (p->type == 2))
+ {
+ q.next = cr_del(p);
+ p = &q;
+ }
+ }
+ cr_loadconf();
+}
+
+void cr_report(sptr)
+aClient *sptr;
+{
+ aCRline *tmp;
+ char *filemask, *reason;
+ char a;
+
+ if (crlines)
+ {
+ }
+ for (tmp = crlines; tmp; tmp = tmp->next)
+ {
+ filemask = BadPtr(tmp->channel) ? "<NULL>" : tmp->channel;
+ if (tmp->type == 0)
+ a = 'c';
+ if (tmp->type == 1)
+ a = 's';
+ if (tmp->type == 2)
+ a = 'o';
+ sendto_one(sptr, ":%s NOTICE %s :*** (allow) [%c] %s", me.name, sptr->name, a, filemask);
+ }
+
+}
+
+/* vhost configuration (vhost.conf)
+ vhost - login password vhost
+*/
+
+int vhost_add(vhost, login, password, usermask, hostmask)
+char *vhost, *login, *password, *usermask, *hostmask;
+{
+ aVhost *fl;
+
+ fl = (aVhost *) MyMalloc(sizeof(aVhost));
+
+ AllocCpy(fl->virthost, vhost);
+ AllocCpy(fl->usermask, usermask);
+ AllocCpy(fl->hostmask, hostmask);
+ AllocCpy(fl->login, login);
+ AllocCpy(fl->password, password);
+ fl->next = vhosts;
+ fl->prev = NULL;
+ if (vhosts)
+ vhosts->prev = fl;
+ vhosts = fl;
+}
+
+aVhost *vhost_del(fl)
+aVhost *fl;
+{
+ aVhost *p, *q;
+ for (p = vhosts; p; p = p->next) {
+ if (p == fl)
+ {
+ q = p->next;
+ MyFree((char *) (fl->virthost));
+ MyFree((char *) (fl->usermask));
+ MyFree((char *) (fl->hostmask));
+ MyFree((char *) (fl->login));
+ MyFree((char *) (fl->password));
+ /* chain1 to chain3 */
+ if (p->prev) {
+ p->prev->next = p->next;
+ }
+ else
+ {
+ vhosts = p->next;
+ }
+ if (p->next) {
+ p->next->prev = p->prev;
+ }
+ MyFree((aVhost *) p);
+ return q;
+ }
+ }
+ return NULL;
+}
+
+/*
+ vhost.conf
+ ------------
+# vhost virtualhost username password mask
+
+vhost microsoft.com billgates ilovelinux *@*
+*/
+int vhost_loadconf(void)
+{
+ char buf[2048];
+ char *x,*y, *login, *password, *mask, *usermask, *hostmask;
+ FILE *f;
+/* _not_ a failsafe routine .. */
+ f = fopen(IRCD_VHOST, "r");
+ if (!f)
+ return -1;
+
+ while (fgets(buf, 2048,f))
+ {
+ iCstrip(buf);
+ x = strtok(buf, " ");
+ if (strcmp("vhost", x)==0)
+ {
+ y = strtok(NULL, " ");
+ if (!y)
+ continue;
+ login = strtok(NULL, " ");
+ password = strtok(NULL, " ");
+ mask = strtok(NULL, "");
+ usermask = strtok(mask, "@");
+ hostmask = strtok(NULL, " ");
+ vhost_add(y, login,password,usermask, hostmask);
+ }
+ }
+ return 0;
+}
+
+void vhost_rehash(void)
+{
+ aVhost *p,q;
+
+ for (p = vhosts; p; p = p->next)
+ {
+ q.next = vhost_del(p);
+ p = &q;
+ }
+ vhost_loadconf();
+}
+
+void vhost_report(sptr)
+aClient *sptr;
+{
+ aVhost *tmp;
+ char *filemask, *reason;
+ char a;
+
+ for (tmp = vhosts; tmp; tmp = tmp->next)
+ {
+ filemask = BadPtr(tmp->virthost) ? "<NULL>" : tmp->virthost;
+ a = 'V';
+ sendto_one(sptr, ":%s NOTICE %s :*** (vhost) [%c] %s %s (%s@%s)", me.name, sptr->name, a, filemask, tmp->login, tmp->usermask, tmp->hostmask);
+ }
+
+}
+
+int m_vhost(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ aVhost *p;
+ char *user, *pwd;
+ if (check_registered(sptr))
+ return 0;
+
+ if (parc < 3)
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "VHOST");
+ return 0;
+
+ }
+ if (!MyClient(sptr))
+ return 0;
+
+ user = parv[1];
+ pwd = parv[2];
+
+ for (p = vhosts; p; p = p->next)
+ {
+ if (!strcmp(p->login, user))
+ {
+ /* First check hostmask.. */
+ if (!match(p->hostmask, sptr->user->realhost) && !match(p->usermask, sptr->user->username))
+ {
+ /* that was okay, lets check password */
+ if (!strcmp(p->password, pwd))
+ {
+ /* let's vhost him .. */
+ strcpy(sptr->user->virthost, p->virthost);
+ sptr->umodes |= UMODE_HIDE;
+ sptr->umodes |= UMODE_SETHOST;
+ sendto_serv_butone(cptr, ":%s SETHOST %s", sptr->name, p->virthost);
+ sendto_one(sptr, ":%s MODE %s :+tx", sptr->name, sptr->name);
+ sendto_one(sptr, ":%s NOTICE %s :*** Your hostname is now %s", me.name, sptr->name, p->virthost);
+ sendto_umode(UMODE_EYES, "[\2vhost\2] %s (%s!%s@%s) is now using vhost %s",
+ user, sptr->name, sptr->user->username, sptr->user->realhost, p->virthost);
+ return 0;
+ }
+ else
+ {
+ sendto_one(sptr, ":%s NOTICE %s :*** [\2vhost\2] Login for %s failed - password incorrect", me.name, sptr->name, user);
+ return 0;
+ }
+ }
+ }
+ }
+ sendto_one(sptr, ":%s NOTICE %s :*** No vHost lines available for your host", me.name, sptr->name);
+ return 0;
+}
+
+/* hush */
+#ifdef MOO
+int hush_add(vhost, login, password, usermask, hostmask)
+char *vhost, *login, *password, *usermask, *hostmask;
+{
+ aHush *fl;
+
+ fl = (aHush *) MyMalloc(sizeof(aHush));
+
+ AllocCpy(fl->virthost, vhost);
+ AllocCpy(fl->usermask, usermask);
+ AllocCpy(fl->hostmask, hostmask);
+ AllocCpy(fl->login, login);
+ AllocCpy(fl->password, password);
+ fl->next = vhosts;
+ fl->prev = NULL;
+ if (vhosts)
+ vhosts->prev = fl;
+ vhosts = fl;
+}
+
+aVhost *vhost_del(fl)
+aVhost *fl;
+{
+ aVhost *p, *q;
+ for (p = vhosts; p; p = p->next) {
+ if (p == fl)
+ {
+ q = p->next;
+ MyFree((char *) (fl->virthost));
+ MyFree((char *) (fl->usermask));
+ MyFree((char *) (fl->hostmask));
+ MyFree((char *) (fl->login));
+ MyFree((char *) (fl->password));
+ /* chain1 to chain3 */
+ if (p->prev) {
+ p->prev->next = p->next;
+ }
+ else
+ {
+ vhosts = p->next;
+ }
+ if (p->next) {
+ p->next->prev = p->prev;
+ }
+ MyFree((aVhost *) p);
+ return q;
+ }
+ }
+ return NULL;
+}
+#endif
+/* irc logs.. */
+void ircd_log(char *format, ...)
+{
+ va_list ap;
+ FILE *f;
+
+ va_start(ap, format);
+ f = fopen(lPATH, "a+");
+ if (!f)
+ {
+#if !defined(_WIN32) && !defined(_AMIGA)
+ sendto_realops("Couldn't write to %s - %s", lPATH, strerror(errno));
+#endif
+ return;
+ }
+ fprintf(f, "(%s) ", myctime(TStime()));
+ vfprintf(f, format, ap);
+ fprintf(f, "\n");
+ fclose(f);
+ va_end(ap);
+}
+
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, s_kline.c
+ * (C) 1999 Carsten Munk (Techie/Stskeeps) <cmunk@toybox.flirt.org>
+ * File to take care of dynamic K:/G:/Z: lines
+ *
+ *
+ * See file AUTHORS in IRC package for additional names of
+ * the programmers.
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#include "numeric.h"
+#include "msg.h"
+#include "channel.h"
+#include "userload.h"
+#include <time.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef _WIN32
+#include <utmp.h>
+#else
+#include <io.h>
+#endif
+#include <fcntl.h>
+#include "h.h"
+
+
+aTKline *tklines = NULL;
+
+#define AllocCpy(x,y) x = (char *) MyMalloc(strlen(y) + 1); strcpy(x,y)
+#define GFreeStr(x) MyFree((char *) x)
+#define GFreeGline(x) MyFree((aGline *) x)
+extern char zlinebuf[];
+
+/*
+
+ * type = TKL_*
+ * usermask@hostmask
+ * reason
+ * setby = whom set it
+ * expire_at = when to expire - 0 if not to expire
+ * set_at = was set at
+*/
+
+int tkl_add_line(type, usermask, hostmask, reason, setby, expire_at, set_at)
+int type;
+char *usermask, *hostmask, *reason, *setby;
+time_t expire_at, set_at;
+{
+ aTKline *nl;
+
+ nl = (aTKline *) MyMalloc(sizeof(aTKline));
+
+ if (!nl)
+ return -1;
+
+ nl->type = type;
+ nl->expire_at = expire_at;
+ nl->set_at = set_at;
+ AllocCpy(nl->usermask, usermask);
+ AllocCpy(nl->hostmask, hostmask);
+ AllocCpy(nl->reason, reason);
+ AllocCpy(nl->setby, setby);
+ nl->prev = NULL;
+ nl->next = tklines;
+ if (tklines)
+ tklines->prev = nl;
+ tklines = nl;
+}
+
+aTKline *tkl_del_line(tkl)
+aTKline *tkl;
+{
+ aTKline *p, *q;
+
+ for (p = tklines; p; p = p->next) {
+ if (p == tkl) {
+ q = p->next;
+ GFreeStr(p->hostmask);
+ GFreeStr(p->usermask);
+ GFreeStr(p->reason);
+ GFreeStr(p->setby);
+ /* chain1 to chain3 */
+ if (p->prev) {
+ p->prev->next = p->next;
+ }
+ else
+ {
+ tklines = p->next;
+ }
+ if (p->next) {
+ p->next->prev = p->prev;
+ }
+ MyFree((aTKline *) p);
+ return q;
+ }
+ }
+ return NULL;
+
+}
+
+aTKline *tkl_expire(aTKline *tmp)
+{
+ FILE *tklinelog;
+ char whattype[512];
+
+ if (!tmp)
+ return NULL;
+
+ whattype[0] = 0;
+
+ if ( (tmp->expire_at == 0) || (tmp->expire_at > TStime()) )
+ {
+ sendto_ops("tkl_expire(): expire for not-yet-expired tkline %s@%s",
+ tmp->usermask,
+ tmp->hostmask);
+ return (tmp->next);
+ }
+
+ if (tmp->type & TKL_GLOBAL)
+ {
+ if (tmp->type & TKL_KILL)
+ {
+ strcpy(whattype, "G:Line");
+ }
+ else
+ if (tmp->type & TKL_ZAP)
+ {
+ strcpy(whattype, "Global Z:Line");
+ }
+ }
+ else
+ {
+ if (tmp->type & TKL_KILL)
+ {
+ strcpy(whattype, "Timed K:Line");
+ }
+ else
+ if (tmp->type & TKL_ZAP)
+ {
+ strcpy(whattype, "Timed Z:Line");
+ }
+ }
+ sendto_umode(UMODE_EYES, "*** Expiring %s (%s@%s) made by %s (Reason: %s) set %li seconds ago",
+ whattype, tmp->usermask, tmp->hostmask, tmp->setby, tmp->reason, TStime() - tmp->set_at);
+
+ ircd_log("Expiring %s (%s@%s) made by %s (Reason: %s) set %li seconds ago",
+ whattype, tmp->usermask, tmp->hostmask, tmp->setby, tmp->reason, TStime() - tmp->set_at);
+
+ return(tkl_del_line(tmp));
+}
+
+void tkl_check_expire (void)
+{
+ aTKline *gp, t;
+ time_t nowtime;
+
+ nowtime = TStime();
+
+ for (gp = tklines; gp; gp = gp->next)
+ {
+ if (gp->expire_at <= nowtime && !(gp->expire_at == 0))
+ {
+ t.next = tkl_expire(gp);
+ gp = &t;
+ }
+ }
+}
+
+
+
+/*
+ returns -1 if no tkline found
+ returns >= 0 if client exits
+*/
+
+int find_tkline_match(cptr, xx)
+aClient *cptr;
+int xx;
+{
+ aTKline *lp;
+ char *chost, *cname,*cip;
+ time_t nowtime;
+ int is_ip;
+ char msge[1024];
+
+ if (IsServer(cptr) || IsMe(cptr))
+ return -1;
+
+
+ nowtime = TStime();
+ chost = cptr->sockhost;
+ cname = cptr->user->username;
+
+cip = (char *) inet_ntoa(cptr->ip);
+
+
+ for (lp = tklines; lp; lp = lp->next)
+ {
+ if (!(*lp->hostmask < '0') && (*lp->hostmask > '9'))
+ is_ip = 1;
+ else
+ is_ip = 0;
+
+ if (is_ip == 0 ? (!match(lp->hostmask, chost) && !match(lp->usermask, cname))
+ : (!match(lp->hostmask, chost) || !match(lp->hostmask, cip)) && !match(lp->usermask, cname))
+ {
+ ircstp->is_ref++;
+ if ((lp->type & (TKL_KILL)) && (xx != 2))
+ {
+ if (lp->type & TKL_GLOBAL)
+ {
+ sendto_one(cptr, "NOTICE %s :*** You are banned for %li seconds (%s)",
+ cptr->name, lp->expire_at - TStime(), lp->reason);
+ sprintf(msge, "User has been banned from %s", ircnetwork);
+ return(exit_client(cptr, cptr, &me, msge));
+ }
+ else
+ {
+ sendto_one(cptr, "NOTICE %s :*** You are banned for %li seconds (%s)",
+ cptr->name, lp->expire_at - TStime(), lp->reason);
+ sprintf(msge, "User has banned from using %s", me.name);
+ return(exit_client(cptr, cptr, &me, msge));
+ }
+ }
+ else
+ if (lp->type & (TKL_ZAP))
+ {
+ sprintf(msge, "ERROR :Closing Link: [%s] Z:Lined (%s)\r\n", inetntoa((char *) &cptr->ip), lp->reason);
+ strcpy(zlinebuf, msge);
+ return(1);
+ }
+ }
+ }
+ return -1;
+}
+
+
+int tkl_sweep() {
+ /* just sweeps net for people that should be killed */
+ aClient *acptr;
+ long i,i1;
+
+ tkl_check_expire();
+ for (i1 = 0; i1 <= 5; i1++)
+ {
+ for (i = 0; i <= (MAXCONNECTIONS -1) ; i++ )
+ {
+ if (acptr = local[i])
+ if (MyClient(acptr))
+ find_tkline_match(acptr,0);
+ }
+ }
+ return 1;
+}
+
+void tkl_stats(cptr)
+aClient *cptr;
+{
+ aTKline *tk;
+ time_t curtime;
+
+ /*
+ We output in this row:
+ Glines,GZlines,KLine, ZLIne
+ Character:
+ G, Z, K, z
+ */
+ tkl_check_expire();
+ curtime = TStime();
+ for (tk = tklines; tk; tk = tk->next)
+ {
+ if (tk->type == (TKL_KILL|TKL_GLOBAL))
+ {
+ sendto_one(cptr, rpl_str(RPL_STATSGLINE), me.name, cptr->name,
+ 'G', tk->usermask, tk->hostmask, (tk->expire_at - curtime),
+ (curtime - tk->set_at), tk->setby, tk->reason);
+ }
+ }
+ for (tk = tklines; tk; tk = tk->next)
+ {
+ if (tk->type == (TKL_ZAP|TKL_GLOBAL))
+ {
+ sendto_one(cptr, rpl_str(RPL_STATSGLINE), me.name, cptr->name,
+ 'Z', tk->usermask, tk->hostmask, (tk->expire_at - curtime),
+ (curtime - tk->set_at), tk->setby, tk->reason);
+ }
+ }
+ for (tk = tklines; tk; tk = tk->next)
+ {
+ if (tk->type == (TKL_KILL))
+ {
+ sendto_one(cptr, rpl_str(RPL_STATSGLINE), me.name, cptr->name,
+ 'K', tk->usermask, tk->hostmask, (tk->expire_at - curtime),
+ (curtime - tk->set_at), tk->setby, tk->reason);
+ }
+ }
+ for (tk = tklines; tk; tk = tk->next)
+ {
+ if (tk->type == (TKL_ZAP))
+ {
+ sendto_one(cptr, rpl_str(RPL_STATSGLINE), me.name, cptr->name,
+ 'z', tk->usermask, tk->hostmask, (tk->expire_at - curtime),
+ (curtime - tk->set_at), tk->setby, tk->reason);
+ }
+ }
+
+}
+
+void tkl_synch(aClient *sptr)
+{
+ aTKline *tk;
+
+
+ for (tk = tklines; tk; tk = tk->next)
+ {
+ if (tk->type & TKL_GLOBAL)
+ {
+ if ((tk->type & TKL_KILL) && !SupportSJOIN(sptr))
+ sendto_one(sptr, ":%s GLINE %s@%s %li %li %s :%s", me.name,
+ tk->usermask, tk->hostmask, tk->expire_at, tk->set_at, tk->setby, tk->reason);
+ else
+ sendto_one(sptr, ":%s %s + %s %s %s %s %li %li :%s",
+ me.name, IsToken(sptr) ? TOK_TKL : MSG_TKL,
+ (tk->type & TKL_KILL ? "G" : "Z"), tk->usermask, tk->hostmask,
+ tk->setby, tk->expire_at, tk->set_at, tk->reason);
+ }
+ }
+}
+
+/*
+ Service function for timed *:lines
+
+ add: TKL + type user host setby expire_at set_at reason
+ del: TKL - type user host removedby
+ list: TKL ?
+
+ only global lines are spread out this way.
+ type= G = G:Line
+ Z = Z:Line
+*/
+
+int m_tkl(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ aTKline *tk;
+ int type;
+ int found = 0;
+ char gmt[256], gmt2[256];
+ char txt[256];
+ time_t expiry_1, setat_1;
+
+
+ if (!IsServer(sptr) && !IsOper(sptr) && !IsMe(sptr))
+ return 0;
+ if (parc < 2)
+ return 0;
+
+ tkl_check_expire();
+
+ switch (*parv[1])
+ {
+ case '+': {
+ /* we relay on servers to be failsafe.. */
+ if (!IsServer(sptr) && !IsMe(sptr))
+ return 0;
+ if (parc < 9)
+ return 0;
+
+ if (*parv[2] == 'G')
+ type = TKL_KILL|TKL_GLOBAL;
+ else if (*parv[2] == 'Z')
+ type = TKL_ZAP|TKL_GLOBAL;
+ else if (*parv[2] == 'z')
+ type = TKL_ZAP;
+ else if (*parv[2] == 'k')
+ type = TKL_KILL;
+ else return 0;
+
+ found = 0;
+ for (tk = tklines; tk; tk = tk->next)
+ {
+ if (tk->type == type)
+ {
+ if (!strcmp(tk->hostmask, parv[4])
+ && !strcmp(tk->usermask, parv[3]))
+ {
+ found = 1;
+ break;
+ }
+ }
+ }
+ /* G:Line already exists, don't add */
+ if (found == 1)
+ return 0;
+
+ tkl_add_line(type, parv[3], parv[4], parv[8], parv[5], atol(parv[6]), atol(parv[7]));
+
+ expiry_1 = atol(parv[6]);
+ setat_1 = atol(parv[7]);
+
+ strncpy(gmt, asctime(gmtime((clock_t*)&setat_1)), sizeof(gmt));
+ strncpy(gmt2, asctime(gmtime((clock_t*)&expiry_1)), sizeof(gmt2));
+ gmt[strlen(gmt) - 1] = '\0';
+ gmt2[strlen(gmt2) - 1] = '\0';
+
+ switch(type)
+ {
+ case TKL_KILL:
+ strcpy(txt, "Timed K:Line");
+ break;
+ case TKL_ZAP:
+ strcpy(txt, "Timed Z:Line");
+ break;
+ case TKL_KILL|TKL_GLOBAL:
+ strcpy(txt, "G:Line");
+ break;
+ case TKL_ZAP|TKL_GLOBAL:
+ strcpy(txt, "Global Z:line");
+ break;
+ default:
+ strcpy(txt, "Unknown *:Line");
+ }
+
+ sendto_umode(UMODE_EYES, "*** %s added for %s@%s on %s GMT (from %s to expire at %s GMT: %s)",
+ txt,
+ parv[3], parv[4], gmt, parv[5], gmt2, parv[8]);
+ ircd_log("%s added for %s@%s on %s GMT (from %s to expire at %s GMT: %s)",
+ txt,
+ parv[3], parv[4], gmt, parv[5], gmt2, parv[8]);
+ tkl_sweep();
+ if (type & TKL_GLOBAL)
+ {
+ sendto_serv_sjoin(cptr, ":%s TKL %s %s %s %s %s %s :%s",
+ sptr->name, parv[1], parv[2], parv[3], parv[4],
+ parv[5], parv[6], parv[7], parv[8]);
+ if (type & TKL_KILL)
+ sendto_serv_butone_sjoin(cptr, ":%s GLINE %s@%s %s %s %s :%s",
+ me.name, parv[3], parv[4], parv[6], parv[7], parv[5],
+ parv[8]);
+ }
+ return 0;
+ }
+ case '-':
+ if (!IsServer(sptr) && !IsMe(sptr))
+ return 0;
+ if (*parv[2] == 'G')
+ type = TKL_KILL|TKL_GLOBAL;
+ else if (*parv[2] == 'Z')
+ type = TKL_ZAP|TKL_GLOBAL;
+ else if (*parv[2] == 'z')
+ type = TKL_ZAP;
+ else if (*parv[2] == 'k')
+ type = TKL_KILL;
+ else return 0;
+
+ switch(type)
+ {
+ case TKL_KILL:
+ strcpy(txt, "Timed K:Line");
+ break;
+ case TKL_ZAP:
+ strcpy(txt, "Timed Z:Line");
+ break;
+ case TKL_KILL|TKL_GLOBAL:
+ strcpy(txt, "G:Line");
+ break;
+ case TKL_ZAP|TKL_GLOBAL:
+ strcpy(txt, "Global Z:line");
+ break;
+ default:
+ strcpy(txt, "Unknown *:Line");
+ }
+
+ found = 0;
+ for (tk = tklines; tk; tk = tk->next)
+ {
+ if (tk->type == type)
+ {
+ if (!strcmp(tk->hostmask, parv[4])
+ && !strcmp(tk->usermask, parv[3]))
+ {
+ strncpy(gmt, asctime(gmtime((clock_t*)&tk->set_at)), sizeof(gmt));
+ gmt[strlen(gmt) - 1] = '\0';
+ sendto_umode(UMODE_EYES, "%s removed %s %s@%s (set at %s - reason: %s)",
+ parv[5], txt,
+ tk->usermask, tk->hostmask,
+ gmt, tk->reason);
+ tkl_del_line(tk);
+ if (type & TKL_GLOBAL)
+ sendto_serv_sjoin(cptr, ":%s TKL %s %s %s %s %s",
+ sptr->name, parv[1], parv[2], parv[3], parv[4], parv[5]);
+ if (type & (TKL_GLOBAL|TKL_KILL))
+ sendto_serv_butone_sjoin(cptr, ":%s REMGLINE %s@%s", me.name, parv[3], parv[4]);
+ break;
+ }
+ }
+ }
+
+ break;
+
+ case '?':
+ if (IsAnOper(sptr))
+ tkl_stats(sptr);
+ }
+}
+
+/*
+** m_gline (oper function - /TKL takes care of distribution)
+** /gline [+|-]u@h mask time :reason
+**
+** parv[0] = sender
+** parv[1] = [+|-]u@h mask
+** parv[2] = for how long
+** parv[3] = reason
+*/
+
+int m_gline (aClient *cptr, aClient *sptr, int parc, char *parv[])
+{
+ aTKline *tk;
+ time_t secs;
+ int whattodo = 0; /* 0 = add 1 = del */
+ int found = 0;
+ int i;
+ char *mask = NULL;
+ char mo[1024], mo2[1024];
+ char *p, *usermask, *hostmask;
+ char *tkllayer[9] =
+ {
+ me.name, /*0 server.name*/
+ NULL, /*1 +|- */
+ "G", /*2 G */
+ NULL, /*3 user */
+ NULL, /*4 host */
+ NULL, /*5 setby */
+ NULL, /*6 expire_at */
+ NULL, /*7 set_at */
+ NULL /*8 reason */
+ };
+
+ if (parc == 1)
+ {
+ tkl_stats(sptr);
+ return 0;
+ }
+
+ if (IsServer(sptr))
+ {
+ tkllayer[1] = "+";
+ tkllayer[2] = "G";
+ tkllayer[3] = strtok(parv[1], "@");
+ tkllayer[4] = strtok(NULL, "@");
+ tkllayer[5] = parv[4];
+ tkllayer[6] = parv[2];
+ tkllayer[7] = parv[3];
+ tkllayer[8] = parv[5];
+ m_tkl(&me, &me, 9, tkllayer);
+ return;
+ }
+ if (!IsOper(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, sptr->name);
+ return 0;
+ }
+
+ if (parc < 2)
+ {
+ sendto_one (sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, sptr->name, "GLINE");
+ return;
+ }
+
+ mask = parv[1];
+ if (*mask == '-')
+ {
+ if (parc < 2)
+ {
+ sendto_one (sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, sptr->name, "GLINE");
+ return;
+ }
+ whattodo = 1;
+ mask++;
+ }
+ else
+ if (*mask == '+')
+ {
+ if (parc < 4)
+ {
+ sendto_one (sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, sptr->name, "GLINE");
+ return;
+ }
+ whattodo = 0;
+ mask++;
+ }
+ if (whattodo == 0)
+ {
+ if (parc < 4)
+ {
+ sendto_one (sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, sptr->name, "GLINE");
+ return;
+ }
+ }
+
+ /* Check if its a hostmask and legal .. */
+ p = strchr(mask, '@');
+ if (!p || (p == mask))
+ {
+ sendto_one(sptr, ":%s NOTICE %s :*** [G:Line error] Please use a user@host mask.", me.name, sptr->name);
+ return 0;
+ }
+
+ if (whattodo == 1)
+ goto nochecks;
+ if (p)
+ {
+ p++;
+ i = 0;
+ while (*p)
+ {
+ if (*p != '*' && *p != '.') i++;
+ p++;
+ }
+ if (i<4)
+ {
+ sendto_one(sptr, ":%s NOTICE %s :*** [G:Line error] Too broad mask", me.name, sptr->name);
+ return 0;
+ }
+ }
+
+nochecks:
+ usermask = strtok(mask, "@");
+ hostmask = strtok(NULL, "@");
+ tkl_check_expire();
+
+ for (tk = tklines; tk; tk = tk->next)
+ {
+ if (tk->type = (TKL_GLOBAL|TKL_KILL))
+ {
+ if (!match(tk->hostmask, usermask)
+ && !match(tk->usermask, hostmask))
+ {
+ found = 1;
+ break;
+ }
+ }
+ }
+
+ if ((found == 1) && whattodo == 0)
+ {
+ sendto_one(sptr, ":%s NOTICE %s :*** [G:Line error] Match already exists!", me.name, sptr->name);
+ return 0;
+ }
+ if ((found == 1) && whattodo == 1)
+ {
+ sendto_one(sptr, ":%s NOTICE %s :*** [G:Line error] No such G:Line", me.name, sptr->name);
+ return 0;
+ }
+ if (whattodo == 0)
+ {
+ secs = atol(parv[2]);
+ if (secs < 1)
+ {
+ sendto_one(sptr, ":%s NOTICE %s :*** [G:Line error] Please specify a positive value for time", me.name, sptr->name);
+ return 0;
+ }
+ }
+ tkllayer[1] = whattodo == 0 ? "+" : "-";
+ tkllayer[3] = usermask;
+ tkllayer[4] = hostmask;
+ tkllayer[5] = make_nick_user_host(sptr->name, sptr->user->username, (IsHidden(sptr) ? sptr->user->virthost : sptr->user->realhost));
+ if (whattodo == 0)
+ {
+ sprintf(mo, "%li", secs+TStime());
+ sprintf(mo2, "%li", TStime());
+ tkllayer[6] = mo;
+ tkllayer[7] = mo2;
+ tkllayer[8] = parv[3];
+ /* call the tkl layer .. */
+ m_tkl(&me, &me, 9, tkllayer);
+ }
+ else
+ {
+ /* call the tkl layer .. */
+ m_tkl(&me, &me, 6, tkllayer);
+
+ }
+}
\ No newline at end of file
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, ircd/s_misc.c (formerly ircd/date.c)
+ * Copyright (C) 1990 Jarkko Oikarinen and
+ * University of Oulu, Computing Center
+ *
+ * See file AUTHORS in IRC package for additional names of
+ * the programmers.
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)s_misc.c 2.42 3/1/94 (C) 1988 University of Oulu, \
+Computing Center and Jarkko Oikarinen";
+#endif
+
+#ifndef _WIN32
+#include <sys/time.h>
+#endif
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#include "numeric.h"
+#include "userload.h"
+#include <sys/stat.h>
+#include <fcntl.h>
+#if !defined(ULTRIX) && !defined(SGI) && !defined(sequent) && \
+ !defined(__convex__) && !defined(_WIN32)
+# include <sys/param.h>
+#endif
+#if defined(PCS) || defined(AIX) || defined(SVR3)
+# include <time.h>
+#endif
+#ifdef HPUX
+#include <unistd.h>
+#endif
+#ifdef DYNIXPTX
+#include <sys/types.h>
+#include <time.h>
+#endif
+#ifdef _WIN32
+# include <io.h>
+#endif
+#include "h.h"
+#include "channel.h"
+
+#ifndef NO_FDLIST
+extern fdlist serv_fdlist;
+extern fdlist oper_fdlist;
+extern float currentrate;
+extern float currentrate2;
+#endif
+
+ID_CVS("$Id$");
+static void exit_one_client PROTO((aClient *,aClient *,aClient *,char *));
+static void exit_one_client_in_split PROTO((aClient *,aClient *,aClient *,char *));
+
+static char *months[] = {
+ "January", "February", "March", "April",
+ "May", "June", "July", "August",
+ "September", "October", "November", "December"
+};
+
+static char *weekdays[] = {
+ "Sunday", "Monday", "Tuesday", "Wednesday",
+ "Thursday", "Friday", "Saturday"
+};
+
+/*
+ * stats stuff
+ */
+struct stats ircst, *ircstp = &ircst;
+
+char *date(clock)
+time_t clock;
+{
+ static char buf[80], plus;
+ Reg1 struct tm *lt, *gm;
+ struct tm gmbuf;
+ int minswest;
+
+ if (!clock)
+ time(&clock);
+ gm = gmtime(&clock);
+ bcopy((char *)gm, (char *)&gmbuf, sizeof(gmbuf));
+ gm = &gmbuf;
+ lt = localtime(&clock);
+
+ if (lt->tm_yday == gm->tm_yday)
+ minswest = (gm->tm_hour - lt->tm_hour) * 60 +
+ (gm->tm_min - lt->tm_min);
+ else if (lt->tm_yday > gm->tm_yday)
+ minswest = (gm->tm_hour - (lt->tm_hour + 24)) * 60;
+ else
+ minswest = ((gm->tm_hour + 24) - lt->tm_hour) * 60;
+
+ plus = (minswest > 0) ? '-' : '+';
+ if (minswest < 0)
+ minswest = -minswest;
+
+ (void)sprintf(buf, "%s %s %d %d -- %02d:%02d %c%02d:%02d",
+ weekdays[lt->tm_wday], months[lt->tm_mon],lt->tm_mday,
+ 1900+lt->tm_year,
+ lt->tm_hour, lt->tm_min,
+ plus, minswest/60, minswest%60);
+
+ return buf;
+}
+
+/*
+ * Fixes a string so that the first white space found becomes an end of
+ * string marker (`\-`). returns the 'fixed' string or "*" if the string
+ * was NULL length or a NULL pointer.
+ */
+char *check_string(s)
+Reg1 char *s;
+{
+ static char star[2] = "*";
+ char *str = s;
+
+ if (BadPtr(s))
+ return star;
+
+ for ( ;*s; s++)
+ if (isspace(*s))
+ {
+ *s = '\0';
+ break;
+ }
+
+ return (BadPtr(str)) ? star : str;
+}
+
+/*
+ * create a string of form "foo!bar@fubar" given foo, bar and fubar
+ * as the parameters. If NULL, they become "*".
+ */
+char *make_nick_user_host(nick, name, host)
+Reg1 char *nick, *name, *host;
+{
+ static char namebuf[NICKLEN+USERLEN+HOSTLEN+6];
+ Reg2 char *s = namebuf;
+
+ bzero(namebuf, sizeof(namebuf));
+ nick = check_string(nick);
+ strncpyzt(namebuf, nick, NICKLEN + 1);
+ s += strlen(s);
+ *s++ = '!';
+ name = check_string(name);
+ strncpyzt(s, name, USERLEN + 1);
+ s += strlen(s);
+ *s++ = '@';
+ host = check_string(host);
+ strncpyzt(s, host, HOSTLEN + 1);
+ s += strlen(s);
+ *s = '\0';
+ return (namebuf);
+}
+
+/**
+ ** myctime()
+ ** This is like standard ctime()-function, but it zaps away
+ ** the newline from the end of that string. Also, it takes
+ ** the time value as parameter, instead of pointer to it.
+ ** Note that it is necessary to copy the string to alternate
+ ** buffer (who knows how ctime() implements it, maybe it statically
+ ** has newline there and never 'refreshes' it -- zapping that
+ ** might break things in other places...)
+ **
+ **/
+
+char *myctime(value)
+time_t value;
+{
+ static char buf[28];
+ Reg1 char *p;
+
+ (void)strcpy(buf, ctime(&value));
+ if ((p = (char *)index(buf, '\n')) != NULL)
+ *p = '\0';
+
+ return buf;
+}
+
+/*
+** check_registered_user is used to cancel message, if the
+** originator is a server or not registered yet. In other
+** words, passing this test, *MUST* guarantee that the
+** sptr->user exists (not checked after this--let there
+** be coredumps to catch bugs... this is intentional --msa ;)
+**
+** There is this nagging feeling... should this NOT_REGISTERED
+** error really be sent to remote users? This happening means
+** that remote servers have this user registered, althout this
+** one has it not... Not really users fault... Perhaps this
+** error message should be restricted to local clients and some
+** other thing generated for remotes...
+*/
+int check_registered_user(sptr)
+aClient *sptr;
+{
+ if (!IsRegisteredUser(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOTREGISTERED), me.name, "*");
+ return -1;
+ }
+ return 0;
+}
+
+/*
+** check_registered user cancels message, if 'x' is not
+** registered (e.g. we don't know yet whether a server
+** or user)
+*/
+int check_registered(sptr)
+aClient *sptr;
+{
+ if (!IsRegistered(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOTREGISTERED), me.name, "*");
+ return -1;
+ }
+ return 0;
+}
+
+/*
+** get_client_name
+** Return the name of the client for various tracking and
+** admin purposes. The main purpose of this function is to
+** return the "socket host" name of the client, if that
+** differs from the advertised name (other than case).
+** But, this can be used to any client structure.
+**
+** Returns:
+** "name[user@ip#.port]" if 'showip' is true;
+** "name[sockethost]", if name and sockhost are different and
+** showip is false; else
+** "name".
+**
+** NOTE 1:
+** Watch out the allocation of "nbuf", if either sptr->name
+** or sptr->sockhost gets changed into pointers instead of
+** directly allocated within the structure...
+**
+** NOTE 2:
+** Function return either a pointer to the structure (sptr) or
+** to internal buffer (nbuf). *NEVER* use the returned pointer
+** to modify what it points!!!
+*/
+char *get_client_name(sptr, showip)
+aClient *sptr;
+int showip;
+{
+ static char nbuf[HOSTLEN * 2 + USERLEN + 5];
+
+ if (MyConnect(sptr))
+ {
+ if (IsUnixSocket(sptr))
+ {
+ if (showip)
+ (void) sprintf(nbuf, "%s[%s]",
+ sptr->name, sptr->sockhost);
+ else
+ (void) sprintf(nbuf, "%s[%s]",
+ sptr->name, me.sockhost);
+ }
+ else
+ {
+ if (showip)
+ (void)sprintf(nbuf, "%s[%s@%s.%u]",
+ sptr->name,
+ (!(sptr->flags & FLAGS_GOTID)) ? "" :
+ sptr->username,
+ inetntoa((char *)&sptr->ip),
+ (unsigned int)sptr->port);
+ else
+ {
+ if (mycmp(sptr->name, sptr->sockhost))
+ (void)sprintf(nbuf, "%s[%s]",
+ sptr->name, sptr->sockhost);
+ else
+ return sptr->name;
+ }
+ }
+ return nbuf;
+ }
+ return sptr->name;
+}
+
+char *get_client_host(cptr)
+aClient *cptr;
+{
+ static char nbuf[HOSTLEN * 2 + USERLEN + 5];
+
+ if (!MyConnect(cptr))
+ return cptr->name;
+ if (!cptr->hostp)
+ return get_client_name(cptr, FALSE);
+ if (IsUnixSocket(cptr))
+ (void) sprintf(nbuf, "%s[%s]", cptr->name, me.name);
+ else
+ (void)sprintf(nbuf, "%s[%-.*s@%-.*s]",
+ cptr->name, USERLEN,
+ (!(cptr->flags & FLAGS_GOTID)) ? "" : cptr->username,
+ HOSTLEN, cptr->hostp->h_name);
+ return nbuf;
+}
+
+/*
+ * Form sockhost such that if the host is of form user@host, only the host
+ * portion is copied.
+ */
+void get_sockhost(cptr, host)
+Reg1 aClient *cptr;
+Reg2 char *host;
+{
+ Reg3 char *s;
+ if ((s = (char *)index(host, '@')))
+ s++;
+ else
+ s = host;
+ strncpyzt(cptr->sockhost, s, sizeof(cptr->sockhost));
+}
+
+/*
+ * Return wildcard name of my server name according to given config entry
+ * --Jto
+ */
+char *my_name_for_link(name, aconf)
+char *name;
+aConfItem *aconf;
+{
+ static char namebuf[HOSTLEN];
+ register int count = aconf->port;
+ register char *start = name;
+
+ if (count <= 0 || count > 5)
+ return start;
+
+ while (count-- && name)
+ {
+ name++;
+ name = (char *)index(name, '.');
+ }
+ if (!name)
+ return start;
+
+ namebuf[0] = '*';
+ (void)strncpy(&namebuf[1], name, HOSTLEN - 1);
+ namebuf[HOSTLEN - 1] = '\0';
+
+ return namebuf;
+}
+
+/*
+** exit_client
+** This is old "m_bye". Name changed, because this is not a
+** protocol function, but a general server utility function.
+**
+** This function exits a client of *any* type (user, server, etc)
+** from this server. Also, this generates all necessary prototol
+** messages that this exit may cause.
+**
+** 1) If the client is a local client, then this implicitly
+** exits all other clients depending on this connection (e.g.
+** remote clients having 'from'-field that points to this.
+**
+** 2) If the client is a remote client, then only this is exited.
+**
+** For convenience, this function returns a suitable value for
+** m_funtion return value:
+**
+** FLUSH_BUFFER if (cptr == sptr)
+** 0 if (cptr != sptr)
+*/
+int exit_client(cptr, sptr, from, comment)
+aClient *cptr; /*
+ ** The local client originating the exit or NULL, if this
+ ** exit is generated by this server for internal reasons.
+ ** This will not get any of the generated messages.
+ */
+aClient *sptr; /* Client exiting */
+aClient *from; /* Client firing off this Exit, never NULL! */
+char *comment; /* Reason for the exit */
+ {
+ Reg1 aClient *acptr;
+ Reg2 aClient *next;
+#ifdef FNAME_USERLOG
+ time_t on_for;
+#endif
+ static char comment1[HOSTLEN + HOSTLEN + 2];
+ static int recurse=0;
+
+ if (MyConnect(sptr))
+ {
+#ifndef NO_FDLIST
+ if (IsAnOper(sptr))
+ delfrom_fdlist(sptr->fd, &oper_fdlist);
+ if (IsServer(sptr))
+ delfrom_fdlist(sptr->fd,&serv_fdlist);
+#endif
+
+ sptr->flags |= FLAGS_CLOSING;
+ if (IsPerson(sptr)) {
+ sendto_umode(UMODE_OPER|UMODE_CLIENT,"*** Notice -- Client exiting: %s (%s@%s) [%s]",
+ sptr->name, sptr->user->username, sptr->user->realhost, comment);
+ sendto_conn_hcn("*** Notice -- Client exiting: %s (%s@%s) [%s] [%s]",
+ sptr->name, sptr->user->username,sptr->user->realhost, comment,
+ sptr->sockhost);
+
+ }
+ current_load_data.conn_count--;
+ if (IsPerson(sptr)) {
+ char mydom_mask[HOSTLEN + 1];
+ mydom_mask[0] = '\0';
+ strncpy(&mydom_mask[1], DOMAINNAME, HOSTLEN - 1);
+ current_load_data.client_count--;
+ if (match(mydom_mask, sptr->sockhost) == 0)
+ current_load_data.local_count--;
+ /* Clean out list and watch structures -Donwulff */
+ hash_del_notify_list(sptr);
+ if (sptr->lopt) {
+ free_str_list(sptr->lopt->yeslist);
+ free_str_list(sptr->lopt->nolist);
+ MyFree(sptr->lopt);
+ }
+ }
+ update_load();
+#ifdef FNAME_USERLOG
+ on_for = TStime() - sptr->firsttime;
+# if defined(USE_SYSLOG) && defined(SYSLOG_USERS)
+ if (IsPerson(sptr))
+ syslog(LOG_NOTICE, "%s (%3d:%02d:%02d): %s@%s (%s)\n",
+ myctime(sptr->firsttime),
+ on_for / 3600, (on_for % 3600)/60,
+ on_for % 60, sptr->user->username,
+ sptr->sockhost, sptr->name);
+# else
+ {
+ char linebuf[160];
+ int logfile;
+
+ /*
+ * This conditional makes the logfile active only after
+ * it's been created - thus logging can be turned off by
+ * removing the file.
+ *
+ * stop NFS hangs...most systems should be able to open a
+ * file in 3 seconds. -avalon (curtesy of wumpus)
+ */
+ if (IsPerson(sptr) &&
+ (logfile = open(FNAME_USERLOG, O_WRONLY|O_APPEND)) != -1)
+ {
+ (void)sprintf(linebuf,
+ "%s (%3d:%02d:%02d): %s@%s [%s]\n",
+ myctime(sptr->firsttime),
+ on_for / 3600, (on_for % 3600)/60,
+ on_for % 60,
+ sptr->user->username, sptr->user->realhost,
+ sptr->username);
+ (void)write(logfile, linebuf, strlen(linebuf));
+ (void)close(logfile);
+ }
+ /* Modification by stealth@caen.engin.umich.edu */
+ }
+# endif
+#endif
+ if (sptr->fd >= 0 && !IsConnecting(sptr))
+ {
+ if (cptr != NULL && sptr != cptr)
+ sendto_one(sptr, "ERROR :Closing Link: %s %s (%s)",
+ get_client_name(sptr,FALSE),
+ cptr->name, comment);
+ else
+ sendto_one(sptr, "ERROR :Closing Link: %s (%s)",
+ get_client_name(sptr,FALSE), comment);
+ }
+ /*
+ ** Currently only server connections can have
+ ** depending remote clients here, but it does no
+ ** harm to check for all local clients. In
+ ** future some other clients than servers might
+ ** have remotes too...
+ **
+ ** Close the Client connection first and mark it
+ ** so that no messages are attempted to send to it.
+ ** (The following *must* make MyConnect(sptr) == FALSE!).
+ ** It also makes sptr->from == NULL, thus it's unnecessary
+ ** to test whether "sptr != acptr" in the following loops.
+ */
+ close_connection(sptr);
+ }
+
+ /*
+ * Recurse down the client list and get rid of clients who are no
+ * longer connected to the network (from my point of view)
+ * Only do this expensive stuff if exited==server -Donwulff
+ */
+
+ if (IsServer(sptr)) {
+ /*
+ * Is this right? Not recreateing the split message if
+ * we have been called recursivly? I hope so, cuz thats
+ * the only way I could make this give the right servers
+ * in the quit msg. -Cabal95
+ */
+ if (cptr && !recurse) {
+ (void)strcpy(comment1, sptr->srvptr->name);
+ (void)strcat(comment1, " ");
+ (void)strcat(comment1, sptr->name);
+ }
+ /*
+ * First, remove the clients on the server itself.
+ */
+ for (acptr = client; acptr; acptr=next) {
+ next = acptr->next;
+ if (IsClient(acptr) && (acptr->srvptr == sptr))
+ exit_one_client_in_split(NULL, acptr,
+ &me, comment1);
+#ifdef DEBUGMODE
+ else if (IsClient(acptr) &&
+ (find_server(acptr->user->server,NULL)==sptr)) {
+ sendto_ops("WARNING, srvptr!=sptr but "
+ "find_server did! User %s on %s "
+ "thought it was on %s while "
+ "loosing %s. Tell coding team.",
+ acptr->name, acptr->user->server,
+ acptr->srvptr?acptr->srvptr->name:"<noserver>",
+ sptr->name);
+ exit_one_client_in_split(NULL, acptr,
+ &me, comment1);
+ }
+#endif
+ }
+
+ /*
+ * Now, go SQUIT off the servers which are down-stream of
+ * the one we just lost.
+ */
+ recurse++;
+ for (acptr = client; acptr; acptr=next) {
+ next = acptr->next;
+ if (IsServer(acptr) && acptr->srvptr == sptr)
+ exit_client(sptr, acptr, /* RECURSION */
+ sptr, comment1);
+ /*
+ * I am not masking SQUITS like I do QUITs. This
+ * is probobly something we could easily do, but
+ * how much savings is there really in something
+ * like that?
+ */
+#ifdef DEBUGMODE
+ else if (IsServer(acptr) &&
+ (find_server(acptr->serv->up, NULL)==sptr)) {
+ sendto_ops("WARNING, srvptr!=sptr but "
+ "find_server did! Server %s on "
+ "%s thought it was on %s while "
+ "loosing %s. Tell coding team.",
+ acptr->name, acptr->serv->up,
+ acptr->srvptr?acptr->srvptr->name:"<noserver>",
+ sptr->name);
+ exit_client(sptr, acptr, sptr, comment1);
+ }
+#endif
+ }
+ recurse--;
+ }
+
+ /*
+ * Finally, clear out the server we lost itself
+ */
+ exit_one_client(cptr, sptr, from, comment);
+ return cptr == sptr ? FLUSH_BUFFER : 0;
+ }
+
+/*
+** Exit one client, local or remote. Assuming all dependants have
+** been already removed, and socket closed for local client.
+*/
+/* DANGER: Ugly hack follows. */
+/* Yeah :/ */
+static void exit_one_client_backend(cptr, sptr, from, comment, split)
+aClient *sptr;
+aClient *cptr;
+aClient *from;
+char *comment;
+int split;
+{
+ Reg1 aClient *acptr;
+ Reg2 int i;
+ Reg3 Link *lp;
+
+ /*
+ ** For a server or user quitting, propagage the information to
+ ** other servers (except to the one where is came from (cptr))
+ */
+ if (IsMe(sptr))
+ {
+ sendto_ops("ERROR: tried to exit me! : %s", comment);
+ return; /* ...must *never* exit self!! */
+ }
+ else if (IsServer(sptr)) {
+ /*
+ ** Old sendto_serv_but_one() call removed because we now
+ ** need to send different names to different servers
+ ** (domain name matching)
+ */
+ for (i = 0; i <= highest_fd; i++)
+ {
+ Reg4 aConfItem *aconf;
+
+ if (!(acptr = local[i]) || !IsServer(acptr) ||
+ acptr == cptr || IsMe(acptr))
+ continue;
+ if ((aconf = acptr->serv->nline) &&
+ (match(my_name_for_link(me.name, aconf),
+ sptr->name) == 0))
+ continue;
+ /*
+ ** SQUIT going "upstream". This is the remote
+ ** squit still hunting for the target. Use prefixed
+ ** form. "from" will be either the oper that issued
+ ** the squit or some server along the path that
+ ** didn't have this fix installed. --msa
+ */
+ if (sptr->from == acptr)
+ {
+ sendto_one(acptr, ":%s SQUIT %s :%s",
+ from->name, sptr->name, comment);
+ }
+ else
+ {
+ sendto_one(acptr, "SQUIT %s :%s",
+ sptr->name, comment);
+ }
+ }
+ } else if (!(IsPerson(sptr) || IsService(sptr)))
+ /* ...this test is *dubious*, would need
+ ** some thougth.. but for now it plugs a
+ ** nasty hole in the server... --msa
+ */
+ ; /* Nothing */
+ else if (sptr->name[0]) /* ...just clean all others with QUIT... */
+ {
+ /*
+ ** If this exit is generated from "m_kill", then there
+ ** is no sense in sending the QUIT--KILL's have been
+ ** sent instead.
+ */
+ if ((sptr->flags & FLAGS_KILLED) == 0)
+ {
+ if (split == 0)
+ sendto_serv_butone(cptr,":%s QUIT :%s",
+ sptr->name, comment);
+ else
+ /*
+ * Then this is a split, only old (stupid)
+ * clients need to get quit messages
+ */
+ sendto_serv_butone_quit(cptr, ":%s QUIT :%s",
+ sptr->name, comment);
+ }
+ /*
+ ** If a person is on a channel, send a QUIT notice
+ ** to every client (person) on the same channel (so
+ ** that the client can show the "**signoff" message).
+ ** (Note: The notice is to the local clients *only*)
+ */
+ if (sptr->user)
+ {
+ sendto_common_channels(sptr, ":%s QUIT :%s",
+ sptr->name, comment);
+
+ if (!IsULine(cptr,sptr) && !MyClient(sptr) && !split)
+ sendto_umode(UMODE_FCLIENT, "*** Notice -- Client exiting at %s: %s!%s@%s (%s)",
+ sptr->user->server, sptr->name, sptr->user->username, sptr->user->realhost,
+ comment);
+ while ((lp = sptr->user->channel))
+ remove_user_from_channel(sptr,lp->value.chptr);
+
+ /* Clean up invitefield */
+ while ((lp = sptr->user->invited))
+ del_invite(sptr, lp->value.chptr);
+ /* again, this is all that is needed */
+
+ /* Clean up silencefield */
+ while ((lp = sptr->user->silence))
+ (void)del_silence(sptr, lp->value.cp);
+ }
+ }
+
+ /* Remove sptr from the client list */
+ if (del_from_client_hash_table(sptr->name, sptr) != 1)
+ Debug((DEBUG_ERROR, "%#x !in tab %s[%s] %#x %#x %#x %d %d %#x",
+ sptr, sptr->name,
+ sptr->from ? sptr->from->sockhost : "??host",
+ sptr->from, sptr->next, sptr->prev, sptr->fd,
+ sptr->status, sptr->user));
+ if (IsRegisteredUser(sptr))
+ hash_check_notify(sptr, RPL_LOGOFF);
+ remove_client_from_list(sptr);
+ return;
+}
+
+static void exit_one_client(cptr, sptr, from, comment)
+aClient *sptr, *cptr, *from;
+char *comment;
+{
+ exit_one_client_backend(cptr, sptr, from, comment, 0);
+}
+
+static void exit_one_client_in_split(cptr, sptr, from, comment)
+aClient *sptr, *cptr, *from;
+char *comment;
+{
+ exit_one_client_backend(cptr, sptr, from, comment, 1);
+}
+
+
+void checklist()
+{
+ Reg1 aClient *acptr;
+ Reg2 int i,j;
+
+ if (!(bootopt & BOOT_AUTODIE))
+ return;
+ for (j = i = 0; i <= highest_fd; i++)
+ if (!(acptr = local[i]))
+ continue;
+ else if (IsClient(acptr))
+ j++;
+ if (!j)
+ {
+#ifdef USE_SYSLOG
+ syslog(LOG_WARNING,"ircd exiting: autodie");
+#endif
+ exit(0);
+ }
+ return;
+}
+
+void initstats()
+{
+ bzero((char *)&ircst, sizeof(ircst));
+}
+
+void tstats(cptr, name)
+aClient *cptr;
+char *name;
+{
+ Reg1 aClient *acptr;
+ Reg2 int i;
+ Reg3 struct stats *sp;
+ struct stats tmp;
+ time_t now = TStime();
+
+ sp = &tmp;
+ bcopy((char *)ircstp, (char *)sp, sizeof(*sp));
+#ifndef _WIN32
+ for (i = 0; i < MAXCONNECTIONS; i++)
+#else
+ for (i = 0; i < highest_fd; i++)
+#endif
+ {
+ if (!(acptr = local[i]))
+ continue;
+ if (IsServer(acptr))
+ {
+ sp->is_sbs += acptr->sendB;
+ sp->is_sbr += acptr->receiveB;
+ sp->is_sks += acptr->sendK;
+ sp->is_skr += acptr->receiveK;
+ sp->is_sti += now - acptr->firsttime;
+ sp->is_sv++;
+ if (sp->is_sbs > 1023)
+ {
+ sp->is_sks += (sp->is_sbs >> 10);
+ sp->is_sbs &= 0x3ff;
+ }
+ if (sp->is_sbr > 1023)
+ {
+ sp->is_skr += (sp->is_sbr >> 10);
+ sp->is_sbr &= 0x3ff;
+ }
+ }
+ else if (IsClient(acptr))
+ {
+ sp->is_cbs += acptr->sendB;
+ sp->is_cbr += acptr->receiveB;
+ sp->is_cks += acptr->sendK;
+ sp->is_ckr += acptr->receiveK;
+ sp->is_cti += now - acptr->firsttime;
+ sp->is_cl++;
+ if (sp->is_cbs > 1023)
+ {
+ sp->is_cks += (sp->is_cbs >> 10);
+ sp->is_cbs &= 0x3ff;
+ }
+ if (sp->is_cbr > 1023)
+ {
+ sp->is_ckr += (sp->is_cbr >> 10);
+ sp->is_cbr &= 0x3ff;
+ }
+ }
+ else if (IsUnknown(acptr))
+ sp->is_ni++;
+ }
+
+ sendto_one(cptr, ":%s %d %s :accepts %u refused %u",
+ me.name, RPL_STATSDEBUG, name, sp->is_ac, sp->is_ref);
+ sendto_one(cptr, ":%s %d %s :unknown commands %u prefixes %u",
+ me.name, RPL_STATSDEBUG, name, sp->is_unco, sp->is_unpf);
+ sendto_one(cptr, ":%s %d %s :nick collisions %u unknown closes %u",
+ me.name, RPL_STATSDEBUG, name, sp->is_kill, sp->is_ni);
+ sendto_one(cptr, ":%s %d %s :wrong direction %u empty %u",
+ me.name, RPL_STATSDEBUG, name, sp->is_wrdi, sp->is_empt);
+ sendto_one(cptr, ":%s %d %s :numerics seen %u mode fakes %u",
+ me.name, RPL_STATSDEBUG, name, sp->is_num, sp->is_fake);
+ sendto_one(cptr, ":%s %d %s :auth successes %u fails %u",
+ me.name, RPL_STATSDEBUG, name, sp->is_asuc, sp->is_abad);
+ sendto_one(cptr, ":%s %d %s :local connections %u udp packets %u",
+ me.name, RPL_STATSDEBUG, name, sp->is_loc, sp->is_udp);
+ sendto_one(cptr, ":%s %d %s :Client Server",
+ me.name, RPL_STATSDEBUG, name);
+ sendto_one(cptr, ":%s %d %s :connected %u %u",
+ me.name, RPL_STATSDEBUG, name, sp->is_cl, sp->is_sv);
+ sendto_one(cptr, ":%s %d %s :bytes sent %u.%uK %u.%uK",
+ me.name, RPL_STATSDEBUG, name,
+ sp->is_cks, sp->is_cbs, sp->is_sks, sp->is_sbs);
+ sendto_one(cptr, ":%s %d %s :bytes recv %u.%uK %u.%uK",
+ me.name, RPL_STATSDEBUG, name,
+ sp->is_ckr, sp->is_cbr, sp->is_skr, sp->is_sbr);
+ sendto_one(cptr, ":%s %d %s :time connected %u %u",
+ me.name, RPL_STATSDEBUG, name, sp->is_cti, sp->is_sti);
+#ifndef NO_FDLIST
+ sendto_one(cptr, ":%s %d %s :incoming rate %0.2f kb/s - outgoing rate %0.2f kb/s",
+ me.name, RPL_STATSDEBUG, name, currentrate, currentrate2);
+#endif
+}
+
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, ircd/s_numeric.c
+ * Copyright (C) 1990 Jarkko Oikarinen
+ *
+ * Numerous fixes by Markku Savela
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)s_numeric.c 2.14 1/30/94 (C) 1988 University of Oulu, \
+Computing Center and Jarkko Oikarinen";
+#endif
+
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#include "numeric.h"
+#include "h.h"
+
+ID_CVS("$Id$");
+
+static char buffer[1024];
+
+/*
+** DoNumeric (replacement for the old do_numeric)
+**
+** parc number of arguments ('sender' counted as one!)
+** parv[0] pointer to 'sender' (may point to empty string) (not used)
+** parv[1]..parv[parc-1]
+** pointers to additional parameters, this is a NULL
+** terminated list (parv[parc] == NULL).
+**
+** *WARNING*
+** Numerics are mostly error reports. If there is something
+** wrong with the message, just *DROP* it! Don't even think of
+** sending back a neat error message -- big danger of creating
+** a ping pong error message...
+*/
+int do_numeric(numeric, cptr, sptr, parc, parv)
+int numeric;
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ aClient *acptr;
+ aChannel *chptr;
+ char *nick, *p;
+ int i;
+
+ if (parc < 1 || !IsServer(sptr))
+ return 0;
+ /* Remap low number numerics. */
+ if (numeric < 100)
+ numeric += 100;
+ /*
+ ** Prepare the parameter portion of the message into 'buffer'.
+ ** (Because the buffer is twice as large as the message buffer
+ ** for the socket, no overflow can occur here... ...on current
+ ** assumptions--bets are off, if these are changed --msa)
+ ** Note: if buffer is non-empty, it will begin with SPACE.
+ */
+ buffer[0] = '\0';
+ if (parc > 2)
+ {
+ for (i = 2; i < (parc - 1); i++)
+ {
+ (void)strcat(buffer, " ");
+ (void)strcat(buffer, parv[i]);
+ }
+ (void)strcat(buffer, " :");
+ (void)strcat(buffer, parv[parc-1]);
+ } else sendto_realops("do_numeric( %i, %s, %s, %i, { %s, %s } )!",
+ numeric, cptr->name, sptr->name, parc,
+ parv[0], parv[1]?parv[1]:"<null>");
+ for (; (nick = strtoken(&p, parv[1], ",")); parv[1] = NULL)
+ {
+ if ((acptr = find_client(nick, (aClient *)NULL)))
+ {
+ /*
+ ** Drop to bit bucket if for me...
+ ** ...one might consider sendto_ops
+ ** here... --msa
+ ** And so it was done. -avalon
+ ** And regretted. Dont do it that way. Make sure
+ ** it goes only to non-servers. -avalon
+ ** Check added to make sure servers don't try to loop
+ ** with numerics which can happen with nick collisions.
+ ** - Avalon
+ */
+ if (!IsMe(acptr) && IsPerson(acptr))
+ {
+ /* Added for .U3.2. drop remote 'You are not on
+ ** that channel', we should be synced anyway,
+ ** and this is an annoying message with TSpre7
+ ** still on the net; would result in numeric 442 for
+ ** every KICK... Can be removed when TSpre7 is gone.
+ ** --Run
+ */
+ if (numeric==ERR_NOTONCHANNEL) return 0;
+
+ sendto_prefix_one(acptr, sptr,":%s %d %s%s",
+ parv[0], numeric, nick, buffer);
+ }
+ else if (IsServer(acptr) && acptr->from != cptr)
+ sendto_prefix_one(acptr, sptr,":%s %d %s%s",
+ parv[0], numeric, nick, buffer);
+ }
+ else if ((acptr = find_server(nick, (aClient *)NULL)))
+ {
+ if (!IsMe(acptr) && acptr->from != cptr)
+ sendto_prefix_one(acptr, sptr,":%s %d %s%s",
+ parv[0], numeric, nick, buffer);
+ }
+ else if ((chptr = find_channel(nick, (aChannel *)NULL)))
+ sendto_channel_butone(cptr,sptr,chptr,":%s %d %s%s",
+ parv[0],
+ numeric, chptr->chname, buffer);
+ }
+ return 0;
+}
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, src/s_serv.c
+ * Copyright (C) 1990 Jarkko Oikarinen and
+ * University of Oulu, Computing Center
+ *
+ * See file AUTHORS in IRC package for additional names of
+ * the programmers.
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)s_serv.c 2.55 2/7/94 (C) 1988 University of Oulu, Computing Center and Jarkko Oikarinen";
+#endif
+
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#include "numeric.h"
+#include "msg.h"
+#include "channel.h"
+#include "userload.h"
+#include "version.h"
+#if defined(PCS) || defined(AIX) || defined(DYNIXPTX) || defined(SVR3)
+#include <time.h>
+#endif
+#include <sys/stat.h>
+#include <fcntl.h>
+#ifndef _WIN32
+#include <utmp.h>
+#else
+#include <io.h>
+#endif
+#include <time.h>
+#include "h.h"
+
+ID_CVS("$Id$");
+
+
+static char buf[BUFSIZE];
+
+int max_connection_count = 1, max_client_count = 1;
+
+/*
+** m_functions execute protocol messages on this server:
+**
+** cptr is always NON-NULL, pointing to a *LOCAL* client
+** structure (with an open socket connected!). This
+** identifies the physical socket where the message
+** originated (or which caused the m_function to be
+** executed--some m_functions may call others...).
+**
+** sptr is the source of the message, defined by the
+** prefix part of the message if present. If not
+** or prefix not found, then sptr==cptr.
+**
+** (!IsServer(cptr)) => (cptr == sptr), because
+** prefixes are taken *only* from servers...
+**
+** (IsServer(cptr))
+** (sptr == cptr) => the message didn't
+** have the prefix.
+**
+** (sptr != cptr && IsServer(sptr) means
+** the prefix specified servername. (?)
+**
+** (sptr != cptr && !IsServer(sptr) means
+** that message originated from a remote
+** user (not local).
+**
+** combining
+**
+** (!IsServer(sptr)) means that, sptr can safely
+** taken as defining the target structure of the
+** message in this server.
+**
+** *Always* true (if 'parse' and others are working correct):
+**
+** 1) sptr->from == cptr (note: cptr->from == cptr)
+**
+** 2) MyConnect(sptr) <=> sptr == cptr (e.g. sptr
+** *cannot* be a local connection, unless it's
+** actually cptr!). [MyConnect(x) should probably
+** be defined as (x == x->from) --msa ]
+**
+** parc number of variable parameter strings (if zero,
+** parv is allowed to be NULL)
+**
+** parv a NULL terminated list of parameter pointers,
+**
+** parv[0], sender (prefix string), if not present
+** this points to an empty string.
+** parv[1]...parv[parc-1]
+** pointers to additional parameters
+** parv[parc] == NULL, *always*
+**
+** note: it is guaranteed that parv[0]..parv[parc-1] are all
+** non-NULL pointers.
+*/
+#ifndef NO_FDLIST
+extern fdlist serv_fdlist;
+#endif
+
+/*
+** m_version
+** parv[0] = sender prefix
+** parv[1] = remote server
+*/
+int m_version(cptr, sptr, parc, parv)
+aClient *sptr, *cptr;
+int parc;
+char *parv[];
+{
+ extern char serveropts[];
+ char *x;
+
+ if (TRUEHUB == 1)
+ x = "(H)";
+ else
+ x = "";
+ if (check_registered(sptr))
+ return 0;
+
+ if (hunt_server(cptr,sptr,":%s VERSION :%s",1,parc,parv)==HUNTED_ISME)
+
+ sendto_one(sptr, rpl_str(RPL_VERSION), me.name,
+ parv[0], version, ircnetwork, debugmode, me.name,
+ serveropts,
+ (IsAnOper(sptr) ? MYOSNAME : "*"),
+ UnrealProtocol,
+ x);
+ return 0;
+}
+
+/*int IsMe (acptr)
+aClient *acptr, server;
+{
+if (memcmp (acptr, server, sizeof(aClient)) == 0)
+return 1;
+return 0;
+ }*/
+
+
+/*
+** m_squit
+** parv[0] = sender prefix
+** parv[1] = server name
+** parv[parc-1] = comment
+*/
+int m_squit(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ Reg1 aConfItem *aconf;
+ char *server;
+ Reg2 aClient *acptr;
+ char *comment = (parc > 2 && parv[parc-1]) ?
+ parv[parc-1] : cptr->name;
+
+ if (check_registered(sptr))
+ return 0;
+
+ if (!IsPrivileged(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+
+ if (parc > 1)
+ {
+ server = parv[1];
+ /*
+ ** To accomodate host masking, a squit for a masked server
+ ** name is expanded if the incoming mask is the same as
+ ** the server name for that link to the name of link.
+ */
+ while ((*server == '*') && IsServer(cptr))
+ {
+ aconf = cptr->serv->nline;
+ if (!aconf)
+ break;
+ if (!mycmp(server, my_name_for_link(me.name, aconf)))
+ server = cptr->name;
+ break; /* WARNING is normal here */
+ }
+ /*
+ ** The following allows wild cards in SQUIT. Only usefull
+ ** when the command is issued by an oper.
+ */
+ for (acptr = client; (acptr = next_client(acptr, server));
+ acptr = acptr->next)
+ if (IsServer(acptr) || IsMe(acptr))
+ break;
+ if (acptr && IsMe(acptr))
+ {
+ acptr = cptr;
+ server = cptr->sockhost;
+ }
+ }
+ else
+ {
+ /*
+ ** This is actually protocol error. But, well, closing
+ ** the link is very proper answer to that...
+ */
+ server = cptr->sockhost;
+ acptr = cptr;
+ }
+
+ /*
+ ** SQUIT semantics is tricky, be careful...
+ **
+ ** The old (irc2.2PL1 and earlier) code just cleans away the
+ ** server client from the links (because it is never true
+ ** "cptr == acptr".
+ **
+ ** This logic here works the same way until "SQUIT host" hits
+ ** the server having the target "host" as local link. Then it
+ ** will do a real cleanup spewing SQUIT's and QUIT's to all
+ ** directions, also to the link from which the orinal SQUIT
+ ** came, generating one unnecessary "SQUIT host" back to that
+ ** link.
+ **
+ ** One may think that this could be implemented like
+ ** "hunt_server" (e.g. just pass on "SQUIT" without doing
+ ** nothing until the server having the link as local is
+ ** reached). Unfortunately this wouldn't work in the real life,
+ ** because either target may be unreachable or may not comply
+ ** with the request. In either case it would leave target in
+ ** links--no command to clear it away. So, it's better just
+ ** clean out while going forward, just to be sure.
+ **
+ ** ...of course, even better cleanout would be to QUIT/SQUIT
+ ** dependant users/servers already on the way out, but
+ ** currently there is not enough information about remote
+ ** clients to do this... --msa
+ */
+ if (!acptr)
+ {
+ sendto_one(sptr, err_str(ERR_NOSUCHSERVER),
+ me.name, parv[0], server);
+ return 0;
+ }
+ if (MyClient(sptr) && ((!OPCanGRoute(sptr) && !MyConnect(acptr)) ||
+ (!OPCanLRoute(sptr) && MyConnect(acptr))))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ /*
+ ** Notify all opers, if my local link is remotely squitted
+ */
+ if (MyConnect(acptr) && !IsAnOper(cptr))
+ {
+
+ sendto_locfailops("Received SQUIT %s from %s (%s)",
+ acptr->name, get_client_name(sptr,FALSE), comment);
+ sendto_serv_butone(&me, ":%s GLOBOPS :Received SQUIT %s from %s (%s)",
+ me.name, server, get_client_name(sptr,FALSE), comment);
+#if defined(USE_SYSLOG) && defined(SYSLOG_SQUIT)
+ syslog(LOG_DEBUG,"SQUIT From %s : %s (%s)",
+ parv[0], server, comment);
+#endif
+ }
+ else if (MyConnect(acptr)) {
+ if (acptr->user) {
+ sendto_one(sptr, ":%s NOTICE :*** Cannot do fake kill by SQUIT !!!", me.name);
+ sendto_ops("%s tried to do a fake kill using SQUIT (%s (%s))", sptr->name, acptr->name, comment);
+ sendto_serv_butone(&me, ":%s GLOBOPS :%s tried to fake kill using SQUIT (%s (%s))", me.name, sptr->name, acptr->name, comment);
+ return 0;
+ }
+ sendto_locfailops("Received SQUIT %s from %s (%s)",
+ acptr->name, get_client_name(sptr,FALSE), comment);
+ sendto_serv_butone(&me, ":%s GLOBOPS :Received SQUIT %s from %s (%s)",
+ me.name, acptr->name, get_client_name(sptr,FALSE), comment);
+ }
+ if (IsAnOper(sptr)) {
+ /*
+ * It was manually /squit'ed by a human being(we hope),
+ * there is a very good chance they don't want us to
+ * reconnect right away. -Cabal95
+ */
+ acptr->flags |= FLAGS_SQUIT;
+ }
+
+ return exit_client(cptr, acptr, sptr, comment);
+ }
+
+/*
+ * m_protoctl
+ * parv[0] = Sender prefix
+ * parv[1+] = Options
+ */
+int m_protoctl(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ int i;
+ char proto[128], *options, *equal;
+ static char *dummyblank=""; /* Yes, it is kind of ugly */
+
+
+ if (GotProtoctl(sptr)) {
+ /*
+ * But we already GOT a protoctl msg!
+ */
+ if (!IsServer(sptr))
+ sendto_one(cptr, "ERROR :Already got a PROTOCTL from you.");
+ return 0;
+ }
+
+ cptr->flags |= FLAGS_PROTOCTL;
+ /* parv[parc - 1]*/
+ for (i = 1; i < parc; i++) {
+ strncpy(proto, parv[i], 127);
+ proto[127] = '\0'; /* Just to be safe... */
+ equal = (char *)index(proto, '=');
+ if (equal == NULL)
+ options = dummyblank;
+ else {
+ options = &equal[1]; /* Variable-byte-size safe */
+ equal[0] = '\0';
+ }
+
+ if (strcmp(proto, "NOQUIT") == 0) {
+ Debug((DEBUG_ERROR, "Chose protocol %s for link %s", proto, cptr->name));
+ SetNoQuit(cptr);
+ } else if (strcmp(proto, "TOKEN") == 0) {
+ Debug((DEBUG_ERROR, "Chose protocol %s for link %s", proto, cptr->name));
+ SetToken(cptr);
+ } else if (strcmp(proto, "HCN")==0)
+ {
+ Debug((DEBUG_ERROR, "Chose protocol %s for link %s", proto, cptr->name));
+ SetHybNotice(cptr);
+ } else if (strcmp(proto, "SJOIN")==0)
+ {
+ Debug((DEBUG_ERROR, "Chose protocol %s for link %s", proto, cptr->name));
+ SetSJOIN(cptr);
+ }
+ else if (strcmp(proto, "SJOIN2")==0)
+ {
+ Debug((DEBUG_ERROR, "Chose protocol %s for link %s", proto, cptr->name));
+ SetSJOIN2(cptr);
+ } else if (strcmp(proto, "NICKv2")==0)
+ {
+ Debug((DEBUG_ERROR, "Chose protocol %s for link %s", proto, cptr->name));
+ SetNICKv2(cptr);
+ }
+ /*
+ * Add other protocol extensions here, with proto
+ * containing the base option, and options containing
+ * what it equals, if anything.
+ *
+ * DO NOT error or warn on unknown proto; we just don't
+ * support it.
+ */
+ }
+
+ return 0;
+}
+
+
+/*
+** m_server
+** parv[0] = sender prefix
+** parv[1] = servername
+** parv[2] = serverinfo/hopcount
+** parv[3] = serverinfo
+*/
+int m_server(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ Reg1 char *ch;
+ Reg2 int i;
+ char info[REALLEN+1], *inpath, *host, *encr;
+ aClient *acptr, *bcptr;
+ aConfItem *aconf, *cconf;
+ int hop, ts = 0;
+
+ info[0] = '\0';
+ inpath = get_client_name(cptr,FALSE);
+ if (parc < 2 || *parv[1] == '\0')
+ {
+ sendto_one(cptr,"ERROR :No servername");
+ return 0;
+ }
+ hop = 0;
+ host = parv[1];
+ if (parc > 4) {
+ ts = atoi(parv[3]);
+ hop = atoi(parv[2]);
+ (void)strncpy(info, parv[4], REALLEN);
+ info[REALLEN] = '\0';
+ }
+ else if (parc > 3 && atoi(parv[2]))
+ {
+ hop = atoi(parv[2]);
+ (void)strncpy(info, parv[3], REALLEN);
+ info[REALLEN] = '\0';
+ }
+ else if (parc > 2)
+ {
+ (void)strncpy(info, parv[2], REALLEN);
+ if (parc > 3 && ((i = strlen(info)) < (REALLEN-2)))
+ {
+ (void)strcat(info, " ");
+ (void)strncat(info, parv[3], REALLEN - i - 2);
+ info[REALLEN] = '\0';
+ }
+ }
+ /*
+ ** Check for "FRENCH " infection ;-) (actually this should
+ ** be replaced with routine to check the hostname syntax in
+ ** general). [ This check is still needed, even after the parse
+ ** is fixed, because someone can send "SERVER :foo bar " ].
+ ** Also, changed to check other "difficult" characters, now
+ ** that parse lets all through... --msa
+ */
+ if (strlen(host) > HOSTLEN)
+ host[HOSTLEN] = '\0';
+ for (ch = host; *ch; ch++)
+ if (*ch <= ' ' || *ch > '~')
+ break;
+ if (*ch || !index(host, '.'))
+ {
+ sendto_one(sptr,"ERROR :Bogus server name (%s)",
+ sptr->name, host);
+ sendto_ops("Bogus server name (%s) from %s", host,
+ get_client_name(cptr, TRUE));
+ sptr->since += 7;
+ return 0;
+ }
+
+ if (IsPerson(cptr))
+ {
+ /*
+ ** A local link that has been identified as a USER
+ ** tries something fishy... ;-)
+ */
+ sendto_one(cptr, err_str(ERR_ALREADYREGISTRED),
+ me.name, parv[0]);
+// sendto_one(cptr, ":%s NOTICE %s :Sorry, but your IRC program doesn't appear to support changing servers.", me.name, cptr->name);
+ sendto_ops("User %s trying to become a server %s",
+ get_client_name(cptr, TRUE),host);
+ sptr->since += 7;
+ return 0;
+ }
+ /* *WHEN* can it be that "cptr != sptr" ????? --msa */
+ /* When SERVER command (like now) has prefix. -avalon */
+
+ /* take a prepeek at the password..*/
+ if (IsUnknown(cptr)) {
+ aconf = find_conf_servern(host);
+ if (!aconf) {
+ sendto_locfailops("ERROR :No Access (No N line) %s",
+ inpath);
+ sendto_locfailops("Access denied (No N line) %s", inpath);
+ return exit_client(cptr, cptr, cptr, "No N line");
+ }
+#ifdef CRYPT_LINK_PASSWORD
+ /* use first two chars of the password they send in as salt */
+
+ /* passwd may be NULL. Head it off at the pass... */
+ if(*cptr->passwd)
+ {
+ char salt[3];
+ extern char *crypt();
+
+ salt[0]=aconf->passwd[0];
+ salt[1]=aconf->passwd[1];
+ salt[2]='\0';
+ encr = crypt(cptr->passwd, salt);
+ }
+ else
+ encr = "";
+#else
+ encr = cptr->passwd;
+#endif /* CRYPT_LINK_PASSWORD */
+ if (*aconf->passwd && !StrEq(aconf->passwd, encr))
+ {
+ sendto_one(cptr, "ERROR :No Access (passwd mismatch) %s",
+ inpath);
+ sendto_locfailops("Access denied (passwd mismatch) %s", inpath);
+ return exit_client(cptr, cptr, cptr, "Bad Password");
+ }
+ /* bzero(cptr->passwd, sizeof(cptr->passwd));*/
+ }
+
+ if ((acptr = find_name(host, NULL)))
+ {
+ aClient *ocptr;
+
+ /*
+ * This link is trying feed me a server that I already have
+ * access through another path -- multiple paths not accepted
+ * currently, kill this link immeatedly!!
+ *
+ * Rather than KILL the link which introduced it, KILL the
+ * youngest of the two links. -avalon
+ */
+ acptr = acptr->from;
+ ocptr = (cptr->firsttime > acptr->firsttime) ? acptr : cptr;
+ acptr = (cptr->firsttime > acptr->firsttime) ? cptr : acptr;
+ sendto_one(acptr,"ERROR :Server %s already exists from %s",
+ host,
+ (ocptr->from ? ocptr->from->name : "<nobody>"));
+ sendto_ops("Link %s cancelled, server %s already exists from %s",
+ get_client_name(acptr, TRUE), host,
+ (ocptr->from ? ocptr->from->name : "<nobody>"));
+ return exit_client(acptr, acptr, acptr, "Server Exists");
+ }
+ if ((acptr = find_client(host, NULL)))
+ {
+ /*
+ ** Server trying to use the same name as a person. Would
+ ** cause a fair bit of confusion. Enough to make it hellish
+ ** for a while and servers to send stuff to the wrong place.
+ */
+ sendto_one(cptr,"ERROR :Nickname %s already exists!", host);
+ sendto_locfailops("Link %s cancelled: Server/nick collision on %s",
+ inpath, host);
+ sendto_serv_butone(&me, ":%s GLOBOPS : Link %s cancelled: Server/nick collision on %s",
+ parv[0], inpath, host);
+ return exit_client(cptr, cptr, cptr, "Nick as Server");
+ }
+
+ if (IsServer(cptr))
+ {
+ /*
+ ** Server is informing about a new server behind
+ ** this link. Create REMOTE server structure,
+ ** add it to list and propagate word to my other
+ ** server links...
+ */
+ if (parc == 1 || info[0] == '\0')
+ {
+ sendto_one(cptr,
+ "ERROR :No server info specified for %s",
+ host);
+ return 0;
+ }
+
+ /*
+ ** See if the newly found server is behind a guaranteed
+ ** leaf (L-line). If so, close the link.
+ */
+ if ((aconf = find_conf_host(cptr->confs, host, CONF_LEAF)) &&
+ (!aconf->port || (hop > aconf->port)))
+ {
+ sendto_ops("Leaf-only link %s->%s - Closing",
+ get_client_name(cptr, TRUE),
+ aconf->host ? aconf->host : "*");
+ sendto_one(cptr, "ERROR :Leaf-only link, sorry.");
+ return exit_client(cptr, cptr, cptr, "Leaf Only");
+ }
+ /*
+ **
+ */
+ if (!(aconf = find_conf_host(cptr->confs, host, CONF_HUB)) ||
+ (aconf->port && (hop > aconf->port)) )
+ {
+ sendto_ops("Non-Hub link %s introduced %s(%s).",
+ get_client_name(cptr, TRUE), host,
+ aconf ? (aconf->host ? aconf->host : "*") :
+ "!");
+ return exit_client(cptr, cptr, cptr,
+ "Too many servers");
+ }
+ /*
+ ** See if the newly found server has a Q line for it in
+ ** our conf. If it does, lose the link that brought it
+ ** into our network. Format:
+ **
+ ** Q:<unused>:<reason>:<servername>
+ **
+ ** Example: Q:*:for the hell of it:eris.Berkeley.EDU
+ */
+ if ((aconf = find_conf_name(host, CONF_QUARANTINED_SERVER)))
+ {
+ sendto_ops_butone(NULL, &me,
+ ":%s WALLOPS * :%s brought in %s, %s %s",
+ me.name, get_client_name(cptr,FALSE),
+ host, "closing link because",
+ BadPtr(aconf->passwd) ? "reason unspecified" :
+ aconf->passwd);
+
+ sendto_one(cptr,
+ "ERROR :%s is not welcome: %s. %s",
+ host, BadPtr(aconf->passwd) ?
+ "reason unspecified" : aconf->passwd,
+ "Try another network");
+
+ return exit_client(cptr, cptr, cptr, "Q-Lined Server");
+ }
+
+ acptr = make_client(cptr, find_server(parv[0], NULL));
+ (void)make_server(acptr);
+ acptr->hopcount = hop;
+ strncpyzt(acptr->name, host, sizeof(acptr->name));
+ strncpyzt(acptr->info, info, sizeof(acptr->info));
+ strncpyzt(acptr->serv->up, parv[0], sizeof(acptr->serv->up));
+ SetServer(acptr);
+ acptr->flags|=FLAGS_TS8;
+ add_client_to_list(acptr);
+ (void)add_to_client_hash_table(acptr->name, acptr);
+ /*
+ ** Old sendto_serv_but_one() call removed because we now
+ ** need to send different names to different servers
+ ** (domain name matching)
+ */
+ for (i = 0; i <= highest_fd; i++)
+ {
+ if (!(bcptr = local[i]) || !IsServer(bcptr) ||
+ bcptr == cptr || IsMe(bcptr))
+ continue;
+ if (!(aconf = bcptr->serv->nline))
+ {
+ sendto_ops("Lost N-line for %s on %s. Closing",
+ get_client_name(cptr, TRUE), host);
+ return exit_client(cptr, cptr, cptr,
+ "Lost N line");
+ }
+ if (match(my_name_for_link(me.name, aconf),
+ acptr->name) == 0)
+ continue;
+ if (ts)
+ sendto_one(bcptr, ":%s SERVER %s %d %d :%s",
+ parv[0], acptr->name, hop+1, ts,
+ acptr->info);
+ else
+ sendto_one(bcptr, ":%s SERVER %s %d :%s",
+ parv[0], acptr->name, hop+1,
+ acptr->info);
+ }
+ /* Check for U-line status -- Barubary */
+ if (find_conf_host(cptr->confs, acptr->name, CONF_UWORLD))
+ acptr->flags |= FLAGS_ULINE;
+ return 0;
+ }
+
+ if (!IsUnknown(cptr) && !IsHandshake(cptr))
+ return 0;
+ /*
+ ** A local link that is still in undefined state wants
+ ** to be a SERVER. Check if this is allowed and change
+ ** status accordingly...
+ */
+ strncpyzt(cptr->name, host, sizeof(cptr->name));
+ strncpyzt(cptr->info, info[0] ? info:me.name, sizeof(cptr->info));
+ cptr->hopcount = hop;
+
+ /* check connection rules */
+ for (cconf = conf; cconf; cconf = cconf->next)
+ if ((cconf->status == CONF_CRULEALL) &&
+ (match(cconf->host, host) == 0))
+ if (crule_eval (cconf->passwd))
+ {
+ ircstp->is_ref++;
+ sendto_ops("Refused connection from %s.",
+ get_client_host(cptr));
+ return exit_client(cptr, cptr, cptr,
+ "Disallowed by connection rule");
+ }
+
+ switch (check_server_init(cptr))
+ {
+ case 0 :
+ return m_server_estab(cptr);
+ case 1 :
+ sendto_ops("Access check for %s in progress",
+ get_client_name(cptr,TRUE));
+ return 1;
+ default :
+ ircstp->is_ref++;
+ sendto_ops("Received unauthorized connection from %s.", get_client_host(cptr));
+ sendto_serv_butone(&me, ":%s GLOBOPS :Recieved unauthorized connection from %s.",
+ parv[0], get_client_host(cptr));
+ return exit_client(cptr, cptr, cptr, "No C/N conf lines");
+ }
+
+}
+
+int m_server_estab(cptr)
+Reg1 aClient *cptr;
+{
+ Reg2 aClient *acptr;
+ Reg3 aConfItem *aconf, *bconf;
+ char *inpath, *host, *s, *encr;
+ int split, i;
+
+ inpath = get_client_name(cptr,TRUE); /* "refresh" inpath with host */
+ split = mycmp(cptr->name, cptr->sockhost);
+ host = cptr->name;
+
+ current_load_data.conn_count++;
+ update_load();
+
+ if (!(aconf = find_conf(cptr->confs, host, CONF_NOCONNECT_SERVER)))
+ {
+ ircstp->is_ref++;
+ sendto_one(cptr,
+ "ERROR :Access denied. No N line for server %s",
+ inpath);
+ sendto_ops("Access denied. No N line for server %s", inpath);
+ return exit_client(cptr, cptr, cptr, "No N line for server");
+ }
+ if (!(bconf = find_conf(cptr->confs, host, CONF_CONNECT_SERVER)))
+ {
+ ircstp->is_ref++;
+ sendto_one(cptr, "ERROR :Only N (no C) field for server %s",
+ inpath);
+ sendto_ops("Only N (no C) field for server %s",inpath);
+ return exit_client(cptr, cptr, cptr, "No C line for server");
+ }
+
+#ifdef CRYPT_LINK_PASSWORD
+ /* use first two chars of the password they send in as salt */
+
+ /* passwd may be NULL. Head it off at the pass... */
+ if(*cptr->passwd)
+ {
+ char salt[3];
+ extern char *crypt();
+
+ salt[0]=aconf->passwd[0];
+ salt[1]=aconf->passwd[1];
+ salt[2]='\0';
+ encr = crypt(cptr->passwd, salt);
+ }
+ else
+ encr = "";
+#else
+ encr = cptr->passwd;
+#endif /* CRYPT_LINK_PASSWORD */
+ if (*aconf->passwd && !StrEq(aconf->passwd, encr))
+ {
+ ircstp->is_ref++;
+ sendto_one(cptr, "ERROR :No Access (passwd mismatch) %s",
+ inpath);
+ sendto_ops("Access denied (passwd mismatch) %s", inpath);
+ return exit_client(cptr, cptr, cptr, "Bad Password");
+ }
+ bzero(cptr->passwd, sizeof(cptr->passwd));
+#ifndef HUB
+ for (i = 0; i <= highest_fd; i++)
+ if (local[i] && IsServer(local[i]))
+ {
+ ircstp->is_ref++;
+ sendto_one(cptr, "ERROR :I'm a leaf not a hub");
+ return exit_client(cptr, cptr, cptr, "I'm a leaf");
+ }
+#endif
+ if (IsUnknown(cptr))
+ {
+ sendto_one(cptr, "PROTOCTL %s", PROTOCTL_SERVER);
+ if (bconf->passwd[0])
+ sendto_one(cptr,"PASS :%s",bconf->passwd);
+ /*
+ ** Pass my info to the new server
+ */
+ sendto_one(cptr, "SERVER %s 1 :%s",
+ my_name_for_link(me.name, aconf),
+ (me.info[0]) ? (me.info) : "IRCers United");
+ }
+ else
+ {
+ s = (char *)index(aconf->host, '@');
+ *s = '\0'; /* should never be NULL */
+ Debug((DEBUG_INFO, "Check Usernames [%s]vs[%s]",
+ aconf->host, cptr->username));
+ if (match(aconf->host, cptr->username))
+ {
+ *s = '@';
+ ircstp->is_ref++;
+ sendto_ops("Username mismatch [%s]v[%s] : %s",
+ aconf->host, cptr->username,
+ get_client_name(cptr, TRUE));
+ sendto_one(cptr, "ERROR :No Username Match");
+ return exit_client(cptr, cptr, cptr, "Bad User");
+ }
+ *s = '@';
+ sendto_one(cptr, "PROTOCTL %s", PROTOCTL_SERVER);
+ }
+
+ det_confs_butmask(cptr,
+ CONF_LEAF|CONF_HUB|CONF_NOCONNECT_SERVER|CONF_UWORLD);
+ /*
+ ** *WARNING*
+ ** In the following code in place of plain server's
+ ** name we send what is returned by get_client_name
+ ** which may add the "sockhost" after the name. It's
+ ** *very* *important* that there is a SPACE between
+ ** the name and sockhost (if present). The receiving
+ ** server will start the information field from this
+ ** first blank and thus puts the sockhost into info.
+ ** ...a bit tricky, but you have been warned, besides
+ ** code is more neat this way... --msa
+ */
+ SetServer(cptr);
+#ifndef NO_FDLIST
+ addto_fdlist(cptr->fd,&serv_fdlist);
+#endif
+ if (find_conf_host(cptr->confs, cptr->name, CONF_UWORLD))
+ cptr->flags |= FLAGS_ULINE;
+ cptr->flags|=FLAGS_TS8;
+ nextping = TStime();
+
+ if (TRUEHUB == 1)
+ sendto_serv_butone(&me, ":%s GLOBOPS :Link with %s established.",
+ me.name, inpath);
+ sendto_locfailops("Link with %s established.", inpath);
+ /* Insert here */
+ (void)add_to_client_hash_table(cptr->name, cptr);
+ /* doesnt duplicate cptr->serv if allocted this struct already */
+ (void)make_server(cptr);
+ (void)strcpy(cptr->serv->up, me.name);
+ cptr->srvptr = &me;
+ cptr->serv->nline = aconf;
+ if (find_conf_host(cptr->confs, cptr->name, CONF_UWORLD))
+ cptr->flags |= FLAGS_ULINE;
+
+ /*
+ ** Old sendto_serv_but_one() call removed because we now
+ ** need to send different names to different servers
+ ** (domain name matching) Send new server to other servers.
+ */
+ for (i = 0; i <= highest_fd; i++)
+ {
+ if (!(acptr = local[i]) || !IsServer(acptr) ||
+ acptr == cptr || IsMe(acptr))
+ continue;
+ if ((aconf = acptr->serv->nline) &&
+ !match(my_name_for_link(me.name, aconf), cptr->name))
+ continue;
+ if (split)
+ sendto_one(acptr,":%s %s %s 2 :%s",
+ me.name,
+ (IsToken(cptr) ? TOK_SERVER : MSG_SERVER),
+ cptr->name,
+ cptr->info);
+ else
+ sendto_one(acptr,":%s %s %s 2 :%s",
+ me.name,
+ (IsToken(cptr) ? TOK_SERVER : MSG_SERVER),
+
+ cptr->name, cptr->info);
+ }
+
+ /*
+ ** Pass on my client information to the new server
+ **
+ ** First, pass only servers (idea is that if the link gets
+ ** cancelled beacause the server was already there,
+ ** there are no NICK's to be cancelled...). Of course,
+ ** if cancellation occurs, all this info is sent anyway,
+ ** and I guess the link dies when a read is attempted...? --msa
+ **
+ ** Note: Link cancellation to occur at this point means
+ ** that at least two servers from my fragment are building
+ ** up connection this other fragment at the same time, it's
+ ** a race condition, not the normal way of operation...
+ **
+ ** ALSO NOTE: using the get_client_name for server names--
+ ** see previous *WARNING*!!! (Also, original inpath
+ ** is destroyed...)
+ */
+
+ aconf = cptr->serv->nline;
+ for (acptr = &me; acptr; acptr = acptr->prev)
+ {
+ /* acptr->from == acptr for acptr == cptr */
+ if (acptr->from == cptr)
+ continue;
+ if (IsServer(acptr))
+ {
+ if (match(my_name_for_link(me.name, aconf),
+ acptr->name) == 0)
+ continue;
+ split = (MyConnect(acptr) &&
+ mycmp(acptr->name, acptr->sockhost));
+ if (split)
+ sendto_one(cptr, ":%s %s %s %d :%s",
+ acptr->serv->up,
+ (IsToken(cptr) ? TOK_SERVER : MSG_SERVER),
+
+ acptr->name,
+ acptr->hopcount+1,
+ acptr->info);
+ else
+ sendto_one(cptr, ":%s %s %s %d :%s",
+ acptr->serv->up,
+ (IsToken(cptr) ? TOK_SERVER : MSG_SERVER),
+
+ acptr->name,
+ acptr->hopcount+1, acptr->info);
+
+ }
+ }
+
+ for (acptr = &me; acptr; acptr = acptr->prev)
+ {
+ /* acptr->from == acptr for acptr == cptr */
+ if (acptr->from == cptr)
+ continue;
+ if (IsPerson(acptr))
+ {
+ /*
+ ** IsPerson(x) is true only when IsClient(x) is true.
+ ** These are only true when *BOTH* NICK and USER have
+ ** been received. -avalon
+ ** Apparently USER command was forgotten... -Donwulff
+ */
+
+
+ if (!SupportNICKv2(cptr))
+ {
+ sendto_one(cptr,"%s %s %d %d %s %s %s %lu :%s",
+ (IsToken(cptr)?TOK_NICK:MSG_NICK),
+ acptr->name, acptr->hopcount + 1, acptr->lastnick,
+ acptr->user->username, acptr->user->realhost,
+ acptr->user->server, acptr->user->servicestamp,
+ acptr->info);
+ send_umode(cptr, acptr, 0, SEND_UMODES, buf);
+ if (IsHidden(acptr))
+ sendto_one(cptr, ":%s %s %s", acptr->name,
+ (IsToken(cptr)?TOK_SETHOST:MSG_SETHOST),
+ acptr->user->virthost);
+ }
+ else
+ {
+ send_umode(NULL, acptr, 0, SEND_UMODES, buf);
+ sendto_one(cptr,"%s %s %d %d %s %s %s %lu %s %s :%s",
+ (IsToken(cptr)?TOK_NICK:MSG_NICK),
+ acptr->name, acptr->hopcount + 1, acptr->lastnick,
+ acptr->user->username, acptr->user->realhost,
+ acptr->user->server,
+ acptr->user->servicestamp,
+ (!buf || *buf == '\0' ? "+" : buf),
+ ((IsHidden(acptr) && (acptr->umodes & UMODE_SETHOST)) ? acptr->user->virthost : "*"),
+ acptr->info);
+
+ }
+
+ if (acptr->user->away)
+ sendto_one(cptr,":%s %s :%s", acptr->name,
+ (IsToken(cptr)?TOK_AWAY:MSG_AWAY),
+ acptr->user->away);
+ if (acptr->user->swhois)
+ if (*acptr->user->swhois != '\0')
+ sendto_one(cptr, "%s %s :%s",
+ (IsToken(cptr)?TOK_SWHOIS:MSG_SWHOIS),
+ acptr->name, acptr->user->swhois);
+
+ if (!SupportSJOIN(cptr))
+ send_user_joins(cptr, acptr);
+ }
+ else if (IsService(acptr))
+ {
+ sendto_one(cptr,"NICK %s :%d",
+ acptr->name, acptr->hopcount + 1);
+ sendto_one(cptr,":%s SERVICE * * :%s",
+ acptr->name, acptr->info);
+ }
+ }
+ /*
+ ** Last, pass all channels plus statuses
+ */
+ {
+ Reg1 aChannel *chptr;
+ for (chptr = channel; chptr; chptr = chptr->nextch)
+ {
+ if (!SupportSJOIN(cptr))
+ send_channel_modes(cptr, chptr);
+ else
+ send_channel_modes_sjoin(cptr, chptr);
+ if (chptr->topic_time)
+ sendto_one(cptr,"%s %s %s %lu :%s",
+ (IsToken(cptr)?TOK_TOPIC:MSG_TOPIC),
+ chptr->chname, chptr->topic_nick,
+ chptr->topic_time, chptr->topic);
+ }
+ }
+ /* pass on TKLs */
+ tkl_synch(cptr);
+ /*
+ ** Pass on all services based q-lines
+ */
+ {
+ Reg1 aSqlineItem *tmp;
+
+ for(tmp=sqline;tmp;tmp=tmp->next) {
+ if(tmp->status != CONF_ILLEGAL)
+ if(tmp->reason)
+ sendto_one(cptr,":%s %s %s :%s", me.name,
+ (IsToken(cptr)?TOK_SQLINE:MSG_SQLINE),
+ tmp->sqline, tmp->reason);
+ else
+ sendto_one(cptr,":%s %s %s", me.name,
+ tmp->sqline);
+ }
+ }
+
+ sendto_one(cptr, "%s %li %li %li 0 0 0 0 :%s",
+ (IsToken(cptr)?TOK_NETINFO:MSG_NETINFO),
+ lu_mglobalu,
+ TStime(),
+ UnrealProtocol,
+ ircnetwork);
+ return 0;
+}
+
+/*
+** m_links
+** parv[0] = sender prefix
+** parv[1] = servername mask
+** or
+** parv[0] = sender prefix
+** parv[1] = server to query
+** parv[2] = servername mask
+*/
+int m_links(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ char *mask;
+ aClient *acptr;
+
+ if (check_registered_user(sptr))
+ return 0;
+
+ if (parc > 2 && IsOper(cptr))
+ {
+ if (hunt_server(cptr, sptr, ":%s LINKS %s :%s", 1, parc, parv)
+ != HUNTED_ISME)
+ return 0;
+ mask = parv[2];
+ }
+ else
+ mask = parc < 2 ? NULL : parv[1];
+
+ for (acptr = client, (void)collapse(mask); acptr; acptr = acptr->next)
+ {
+ if (!IsServer(acptr) && !IsMe(acptr))
+ continue;
+ if (!BadPtr(mask) && match(mask, acptr->name))
+ continue;
+ if (HIDE_ULINES == 1) {
+ if (IsULine(acptr, acptr) && !IsAnOper(sptr))
+ continue;
+ }
+ sendto_one(sptr, rpl_str(RPL_LINKS),
+ me.name, parv[0], acptr->name, acptr->serv->up,
+ acptr->hopcount, (acptr->info[0] ? acptr->info :
+ "(Unknown Location)"));
+ }
+
+ sendto_one(sptr, rpl_str(RPL_ENDOFLINKS), me.name, parv[0],
+ BadPtr(mask) ? "*" : mask);
+ return 0;
+}
+
+
+/*
+** m_netinfo
+** by Stskeeps
+** parv[0] = sender prefix
+** parv[1] = max global count
+** parv[2] = time of end sync
+** parv[3] = unreal protocol using (numeric)
+** parv[4] = free(for unrealprotocol > 2100)
+** parv[5] = free(**)
+** parv[6] = free(**)
+** parv[7] = free(**)
+** parv[8] = ircnet
+**/
+
+int m_netinfo(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ long lmax;
+ time_t xx;
+ long endsync, protocol;
+
+ if (IsPerson(sptr))
+ return 0;
+ if (!IsServer(cptr))
+ return 0;
+
+ if (parc < 3) {
+ /* Talking to a UnProtocol 2090 */
+ sendto_realops("Link %s is using a too old UnProtocol - (parc < 3)", cptr->name);
+ if (KILLDIFF == 1) {
+ sendto_realops("Dropped link %s - unProtocol 2090 is not compatible with unProtocol %li", cptr->name, UnrealProtocol);
+ sendto_one(cptr, "ERROR :unProtocol 2090 is not compatible with unProtocol %li",
+ UnrealProtocol);
+ exit_client(cptr, cptr, cptr, "Link using unProtocol 2090");
+ }
+ return 0;
+ }
+ if (parc < 9) {
+ return 0;
+ }
+
+ if (GotNetInfo(cptr)) {
+ sendto_realops("Already got NETINFO from Link %s", cptr->name);
+ return 0;
+ }
+ /* is a long therefore not ATOI */
+ lmax = atol(parv[1]);
+ endsync = atol(parv[2]);
+ protocol = atol(parv[3]);
+
+ /* update stats */
+ check_lusers();
+
+ /* max global count != max_global_count --sts */
+ if (lmax > lu_mglobalu) {
+ lu_mglobalu = lmax;
+ sendto_realops("Max Global Count is now %li (set by link %s)", lmax, cptr->name);
+ }
+
+ xx = TStime();
+ if ((xx - endsync) < 0) {
+ sendto_realops("Possible negative TS split at link %s (%li - %li = %li)",
+ cptr->name,
+ (xx),
+ (endsync),
+ (xx - endsync));
+ sendto_serv_butone(&me, ":%s SMO o :\2(sync)\2 Possible negative TS split at link %s (%li - %li = %li)",
+ me.name,
+ cptr->name,
+ (xx),
+ (endsync),
+ (xx - endsync));
+ }
+ sendto_realops("Link %s -> %s is now synced [secs: %li recv: %li.%li sent: %li.%li]",
+ cptr->name,
+ me.name,
+ (TStime() - endsync),
+ sptr->receiveK,
+ sptr->receiveB,
+ sptr->sendK,
+ sptr->sendB);
+
+ sendto_serv_butone(&me, ":%s SMO o :\2(sync)\2 Link %s -> %s is now synced [secs: %li recv: %li.%li sent: %li.%li]",
+ me.name,
+ cptr->name,
+ me.name,
+ (TStime() - endsync),
+ sptr->receiveK,
+ sptr->receiveB,
+ sptr->sendK,
+ sptr->sendB);
+
+ if (!(strcmp(ircnetwork, parv[8])==0)) {
+ sendto_realops("Network name mismatch from link %s (%s != %s)", cptr->name, parv[8], ircnetwork);
+ sendto_serv_butone(&me, ":%s SMO o :\2(sync)\2 Network name mismatch from link %s (%s != %s)", me.name, cptr->name, parv[8], ircnetwork);
+ }
+
+ if (protocol != UnrealProtocol) {
+ sendto_realops("Link %s is running Protocol u%li while we are running %li!",
+ cptr->name, protocol, UnrealProtocol);
+ sendto_serv_butone(&me, ":%s SMO o :\2(sync)\2 Link %s is running u%li while %s is running %li!",
+ me.name, cptr->name, protocol,me.name,UnrealProtocol);
+
+ }
+
+ SetNetInfo(cptr);
+}
+
+#ifndef IRCDTOTALVERSION
+#define IRCDTOTALVERSION BASE_VERSION PATCH1 PATCH2 PATCH3 PATCH4 PATCH5 PATCH6 PATCH7 PATCH8 PATCH9
+#endif
+
+/*
+ * sends m_info into to sptr
+*/
+
+void m_info_send(sptr)
+aClient *sptr;
+{
+ sendto_one(sptr, ":%s %d %s :=-=-=-=-=-==-== %s =-=-=-=-=-==-==",
+ me.name, RPL_INFO, sptr->name, ircnetwork);
+ sendto_one(sptr, ":%s %d %s :|Web Page: | http://www.%s",
+ me.name, RPL_INFO, sptr->name, netdomain);
+ sendto_one(sptr, ":%s %d %s :|FTP Archive: | ftp://ftp.%s",
+ me.name, RPL_INFO, sptr->name, netdomain);
+ sendto_one(sptr, ":%s %d %s :|Help channel: | %s",
+ me.name, RPL_INFO, sptr->name, helpchan);
+ sendto_one(sptr, ":%s %d %s :|=-=-=-=-=-==-==|-=-=-=-=-=-=-==-==-=-=-=-=-=-=-=",
+ me.name, RPL_INFO, sptr->name);
+ sendto_one(sptr, ":%s %d %s :|IRCd version: | %s",
+ me.name, RPL_INFO, sptr->name, IRCDTOTALVERSION);
+ sendto_one(sptr, ":%s %d %s :| Developers: | Stskeeps <stskeeps@tspre.org>",
+ me.name, RPL_INFO, sptr->name);
+ sendto_one(sptr, ":%s %d %s :| | codemastr <codemastr@tspre.org>>",
+ me.name, RPL_INFO, sptr->name);
+
+#ifdef _WIN32
+#ifdef WIN32_SPECIFY
+ sendto_one(sptr, ":%s %d %s :| wIRCd porter: | %s",
+ me.name, RPL_INFO, sptr->name, WIN32_PORTER);
+ sendto_one(sptr, ":%s %d %s :| >>URL: | %s",
+ me.name, RPL_INFO, sptr->name, WIN32_URL);
+#endif
+#endif
+ sendto_one(sptr, ":%s %d %s :|Credits: | Type /Credits",
+ me.name, RPL_INFO, sptr->name);
+ sendto_one(sptr, ":%s %d %s :|DALnet Credits | Type /DalInfo",
+ me.name, RPL_INFO, sptr->name);
+ sendto_one(sptr, ":%s %d %s :-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-",
+ me.name, RPL_INFO, sptr->name);
+ sendto_one(sptr, ":%s %d %s :Birth Date: %s, compile # %s",
+ me.name, RPL_INFO, sptr->name, creation, generation);
+ sendto_one(sptr, ":%s %d %s :On-line since %s",
+ me.name, RPL_INFO, sptr->name,
+ myctime(me.firsttime));
+ sendto_one(sptr, ":%s %d %s :ReleaseID (%s)",
+ me.name, RPL_INFO, sptr->name,
+ RELEASEID);
+ sendto_one(sptr, rpl_str(RPL_ENDOFINFO), me.name, sptr->name);
+}
+
+/*
+** m_info
+** parv[0] = sender prefix
+** parv[1] = servername
+** Modified for hardcode by Stskeeps
+*/
+
+int m_info(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ char **text = infotext;
+
+ if (check_registered(sptr))
+ return 0;
+
+ if (hunt_server(cptr,sptr,":%s INFO :%s",1,parc,parv) == HUNTED_ISME)
+ {
+ m_info_send(sptr);
+ }
+
+ return 0;
+}
+
+/*
+** m_dalinfo
+** parv[0] = sender prefix
+** parv[1] = servername
+*/
+int m_dalinfo(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ char **text = dalinfotext;
+ if (check_registered(sptr))
+ return 0;
+
+ if (hunt_server(cptr,sptr,":%s DALINFO :%s",1,parc,parv) == HUNTED_ISME)
+ {
+ while (*text)
+ sendto_one(sptr, rpl_str(RPL_INFO),
+ me.name, parv[0], *text++);
+
+ sendto_one(sptr, rpl_str(RPL_INFO), me.name, parv[0], "");
+ sendto_one(sptr,
+ ":%s %d %s :Birth Date: %s, compile # %s",
+ me.name, RPL_INFO, parv[0], creation, generation);
+ sendto_one(sptr, ":%s %d %s :On-line since %s",
+ me.name, RPL_INFO, parv[0],
+ myctime(me.firsttime));
+ sendto_one(sptr, rpl_str(RPL_ENDOFINFO), me.name, parv[0]);
+ }
+
+ return 0;
+}
+
+/*
+** m_license
+** parv[0] = sender prefix
+** parv[1] = servername
+*/
+int m_license(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ char **text = gnulicense;
+ if (check_registered(sptr))
+ return 0;
+
+ if (hunt_server(cptr,sptr,":%s LICENSE :%s",1,parc,parv) == HUNTED_ISME)
+ {
+ while (*text)
+ sendto_one(sptr, rpl_str(RPL_INFO),
+ me.name, parv[0], *text++);
+
+ sendto_one(sptr, rpl_str(RPL_INFO), me.name, parv[0], "");
+ sendto_one(sptr, rpl_str(RPL_ENDOFINFO), me.name, parv[0]);
+ }
+
+ return 0;
+}
+
+/*
+** m_credits
+** parv[0] = sender prefix
+** parv[1] = servername
+*/
+int m_credits(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ char **text = unrealcredits;
+ if (check_registered(sptr))
+ return 0;
+
+ if (hunt_server(cptr,sptr,":%s CREDITS :%s",1,parc,parv) == HUNTED_ISME)
+ {
+ while (*text)
+ sendto_one(sptr, rpl_str(RPL_INFO),
+ me.name, parv[0], *text++);
+
+ sendto_one(sptr, rpl_str(RPL_INFO), me.name, parv[0], "");
+ sendto_one(sptr,
+ ":%s %d %s :Birth Date: %s, compile # %s",
+ me.name, RPL_INFO, parv[0], creation, generation);
+ sendto_one(sptr, ":%s %d %s :On-line since %s",
+ me.name, RPL_INFO, parv[0],
+ myctime(me.firsttime));
+ sendto_one(sptr, rpl_str(RPL_ENDOFINFO), me.name, parv[0]);
+ }
+
+ return 0;
+}
+
+
+/*
+ * RPL_NOWON - Online at the moment (Succesfully added to WATCH-list)
+ * RPL_NOWOFF - Offline at the moement (Succesfully added to WATCH-list)
+ * RPL_WATCHOFF - Succesfully removed from WATCH-list.
+ * ERR_TOOMANYWATCH - Take a guess :> Too many WATCH entries.
+ */
+static void show_watch(cptr, name, rpl1, rpl2)
+aClient *cptr;
+char *name;
+int rpl1, rpl2;
+{
+ aClient *acptr;
+
+
+ if ((acptr = find_person(name, NULL))) {
+ make_virthost(acptr->user->realhost, acptr->user->virthost);
+ sendto_one(cptr, rpl_str(rpl1), me.name, cptr->name,
+ acptr->name, acptr->user->username,
+ acptr->user->virthost, acptr->lastnick);
+ }
+ else
+ sendto_one(cptr, rpl_str(rpl2), me.name, cptr->name,
+ name, "*", "*", 0);
+}
+
+/*
+ * m_watch
+ */
+int m_watch(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ char namebuf[USERLEN+HOSTLEN+4];
+ Reg1 aClient *acptr;
+ Reg2 char *s, **pav = parv, *user;
+ Reg3 int len;
+ char *p = NULL, *def = "l";
+
+
+ if (check_registered(sptr))
+ return 0;
+
+ if (parc < 2) {
+ /*
+ * Default to 'l' - list who's currently online
+ */
+ parc = 2;
+ parv[1] = def;
+ }
+
+ for (s = (char *)strtoken(&p, *++pav, " "); s;
+ s = (char *)strtoken(&p, NULL, " ")) {
+ if ((user = (char *)index(s, '!')))
+ *user++ = '\0'; /* Not used */
+
+ /*
+ * Prefix of "+", they want to add a name to their WATCH
+ * list.
+ */
+ if (*s == '+') {
+ if (do_nick_name(s+1)) {
+ if (sptr->notifies >= MAXWATCH) {
+ sendto_one(sptr, err_str(ERR_TOOMANYWATCH),
+ me.name, cptr->name, s+1);
+
+ continue;
+ }
+
+ add_to_notify_hash_table(s+1, sptr);
+ }
+
+ show_watch(sptr, s+1, RPL_NOWON, RPL_NOWOFF);
+ continue;
+ }
+
+ /*
+ * Prefix of "-", coward wants to remove somebody from their
+ * WATCH list. So do it. :-)
+ */
+ if (*s == '-') {
+ del_from_notify_hash_table(s+1, sptr);
+ show_watch(sptr, s+1, RPL_WATCHOFF, RPL_WATCHOFF);
+
+ continue;
+ }
+
+ /*
+ * Fancy "C" or "c", they want to nuke their WATCH list and start
+ * over, so be it.
+ */
+ if (*s == 'C' || *s == 'c') {
+ hash_del_notify_list(sptr);
+
+ continue;
+ }
+
+ /*
+ * Now comes the fun stuff, "S" or "s" returns a status report of
+ * their WATCH list. I imagine this could be CPU intensive if its
+ * done alot, perhaps an auto-lag on this?
+ */
+ if (*s == 'S' || *s == 's') {
+ Link *lp;
+ aNotify *anptr;
+ int count = 0;
+
+ /*
+ * Send a list of how many users they have on their WATCH list
+ * and how many WATCH lists they are on.
+ */
+ anptr = hash_get_notify(sptr->name);
+ if (anptr)
+ for (lp = anptr->notify, count = 1; (lp = lp->next); count++)
+ ;
+ sendto_one(sptr, rpl_str(RPL_WATCHSTAT), me.name, parv[0],
+ sptr->notifies, count);
+
+ /*
+ * Send a list of everybody in their WATCH list. Be careful
+ * not to buffer overflow.
+ */
+ if ((lp = sptr->notify) == NULL) {
+ sendto_one(sptr, rpl_str(RPL_ENDOFWATCHLIST), me.name, parv[0],
+ *s);
+ continue;
+ }
+ *buf = '\0';
+ strcpy(buf, lp->value.nptr->nick);
+ count = strlen(parv[0])+strlen(me.name)+10+strlen(buf);
+ while ((lp = lp->next)) {
+ if (count+strlen(lp->value.nptr->nick)+1 > BUFSIZE - 2) {
+ sendto_one(sptr, rpl_str(RPL_WATCHLIST), me.name,
+ parv[0], buf);
+ *buf = '\0';
+ count = strlen(parv[0])+strlen(me.name)+10;
+ }
+ strcat(buf, " ");
+ strcat(buf, lp->value.nptr->nick);
+ count += (strlen(lp->value.nptr->nick)+1);
+ }
+ sendto_one(sptr, rpl_str(RPL_WATCHLIST), me.name, parv[0], buf);
+
+ sendto_one(sptr, rpl_str(RPL_ENDOFWATCHLIST), me.name, parv[0],
+ *s);
+ continue;
+ }
+
+ /*
+ * Well that was fun, NOT. Now they want a list of everybody in
+ * their WATCH list AND if they are online or offline? Sheesh,
+ * greedy arn't we?
+ */
+ if (*s == 'L' || *s == 'l') {
+ Link *lp = sptr->notify;
+
+ while (lp) {
+ if ((acptr = find_person(lp->value.nptr->nick, NULL))) {
+ make_virthost(acptr->user->realhost, acptr->user->virthost);
+
+ sendto_one(sptr, rpl_str(RPL_NOWON), me.name, parv[0],
+ acptr->name, acptr->user->username,
+ acptr->user->virthost, acptr->lastnick);
+ }
+ /*
+ * But actually, only show them offline if its a capital
+ * 'L' (full list wanted).
+ */
+ else if (isupper(*s))
+ sendto_one(sptr, rpl_str(RPL_NOWOFF), me.name, parv[0],
+ lp->value.nptr->nick, "*", "*",
+ lp->value.nptr->lasttime);
+ lp = lp->next;
+ }
+
+ sendto_one(sptr, rpl_str(RPL_ENDOFWATCHLIST), me.name, parv[0],
+ *s);
+
+ continue;
+ }
+
+ /*
+ * Hmm.. unknown prefix character.. Ignore it. :-)
+ */
+ }
+
+ return 0;
+}
+
+
+
+
+/*
+** m_summon should be redefined to ":prefix SUMMON host user" so
+** that "hunt_server"-function could be used for this too!!! --msa
+** As of 2.7.1e, this was the case. -avalon
+**
+** parv[0] = sender prefix
+** parv[1] = user
+** parv[2] = server
+** parv[3] = channel (optional)
+*/
+int m_summon(cptr, sptr, parc, parv)
+aClient *sptr, *cptr;
+int parc;
+char *parv[];
+{
+ char *host, *user, *chname;
+#ifdef ENABLE_SUMMON
+ char hostbuf[17], namebuf[10], linebuf[10];
+# ifdef LEAST_IDLE
+ char linetmp[10], ttyname[15]; /* Ack */
+ struct stat stb;
+ time_t ltime = (time_t)0;
+# endif
+ int fd, flag = 0;
+#endif
+
+ if (check_registered_user(sptr))
+ return 0;
+ if (parc < 2 || *parv[1] == '\0')
+ {
+ sendto_one(sptr, err_str(ERR_NORECIPIENT),
+ me.name, parv[0], "SUMMON");
+ return 0;
+ }
+ user = parv[1];
+ host = (parc < 3 || BadPtr(parv[2])) ? me.name : parv[2];
+ chname = (parc > 3) ? parv[3] : "*";
+ /*
+ ** Summoning someone on remote server, find out which link to
+ ** use and pass the message there...
+ */
+ parv[1] = user;
+ parv[2] = host;
+ parv[3] = chname;
+ parv[4] = NULL;
+ if (hunt_server(cptr, sptr, ":%s SUMMON %s %s %s", 2, parc, parv) ==
+ HUNTED_ISME)
+ {
+#ifdef ENABLE_SUMMON
+ if ((fd = utmp_open()) == -1)
+ {
+ sendto_one(sptr, err_str(ERR_FILEERROR),
+ me.name, parv[0], "open", UTMP);
+ return 0;
+ }
+# ifndef LEAST_IDLE
+ while ((flag = utmp_read(fd, namebuf, linebuf, hostbuf,
+ sizeof(hostbuf))) == 0)
+ if (StrEq(namebuf,user))
+ break;
+# else
+ /* use least-idle tty, not the first
+ * one we find in utmp. 10/9/90 Spike@world.std.com
+ * (loosely based on Jim Frost jimf@saber.com code)
+ */
+
+ while ((flag = utmp_read(fd, namebuf, linetmp, hostbuf,
+ sizeof(hostbuf))) == 0)
+ {
+ if (StrEq(namebuf,user))
+ {
+ (void)sprintf(ttyname,"/dev/%s",linetmp);
+ if (stat(ttyname,&stb) == -1)
+ {
+ sendto_one(sptr,
+ err_str(ERR_FILEERROR),
+ me.name, sptr->name,
+ "stat", ttyname);
+ return 0;
+ }
+ if (!ltime)
+ {
+ ltime= stb.st_mtime;
+ (void)strcpy(linebuf,linetmp);
+ }
+ else if (stb.st_mtime > ltime) /* less idle */
+ {
+ ltime= stb.st_mtime;
+ (void)strcpy(linebuf,linetmp);
+ }
+ }
+ }
+# endif
+ (void)utmp_close(fd);
+# ifdef LEAST_IDLE
+ if (ltime == 0)
+# else
+ if (flag == -1)
+# endif
+ sendto_one(sptr, err_str(ERR_NOLOGIN),
+ me.name, parv[0], user);
+ else
+ summon(sptr, user, linebuf, chname);
+#else
+ sendto_one(sptr, err_str(ERR_SUMMONDISABLED),
+ me.name, parv[0]);
+#endif /* ENABLE_SUMMON */
+ }
+ return 0;
+}
+
+
+/*
+** m_stats
+** parv[0] = sender prefix
+** parv[1] = statistics selector (defaults to Message frequency)
+** parv[2] = server name (current server defaulted, if omitted)
+**
+** Currently supported are:
+** M = Message frequency (the old stat behaviour)
+** L = Local Link statistics
+** C = Report C and N configuration lines
+*/
+/*
+** m_stats/stats_conf
+** Report N/C-configuration lines from this server. This could
+** report other configuration lines too, but converting the
+** status back to "char" is a bit akward--not worth the code
+** it needs...
+**
+** Note: The info is reported in the order the server uses
+** it--not reversed as in ircd.conf!
+*/
+
+static int report_array[18][3] = {
+ { CONF_CONNECT_SERVER, RPL_STATSCLINE, 'C'},
+ { CONF_NOCONNECT_SERVER, RPL_STATSNLINE, 'N'},
+ { CONF_CLIENT, RPL_STATSILINE, 'I'},
+ { CONF_KILL, RPL_STATSKLINE, 'K'},
+ { CONF_EXCEPT, RPL_STATSKLINE, 'E'},
+ { CONF_ZAP, RPL_STATSKLINE, 'Z'},
+ { CONF_QUARANTINED_NICK, RPL_STATSQLINE, 'Q'},
+ { CONF_LEAF, RPL_STATSLLINE, 'L'},
+ { CONF_OPERATOR, RPL_STATSOLINE, 'O'},
+ { CONF_HUB, RPL_STATSHLINE, 'H'},
+ { CONF_LOCOP, RPL_STATSOLINE, 'o'},
+ { CONF_CRULEALL, RPL_STATSDLINE, 'D'},
+ { CONF_CRULEAUTO, RPL_STATSDLINE, 'd'},
+ { CONF_UWORLD, RPL_STATSULINE, 'U'},
+ { CONF_MISSING, RPL_STATSXLINE, 'X'},
+ { CONF_TLINE, RPL_STATSTLINE, 't'},
+ { 0, 0}
+ };
+
+static void report_sqlined_nicks(sptr)
+aClient *sptr;
+{
+ aSqlineItem *tmp;
+ char *nickmask, *reason;
+
+ for(tmp = sqline; tmp; tmp=tmp->next) {
+ if(tmp->status != CONF_ILLEGAL) {
+ nickmask = BadPtr(tmp->sqline) ? "<NULL>" : tmp->sqline;
+ reason = BadPtr(tmp->reason) ? "<NULL>" : tmp->reason;
+ sendto_one(sptr, rpl_str(RPL_SQLINE_NICK), me.name,
+ sptr->name, nickmask, reason);
+ }
+ }
+}
+
+static void report_configured_links(sptr, mask)
+aClient *sptr;
+int mask;
+{
+ static char null[] = "<NULL>";
+ aConfItem *tmp;
+ int *p, port, tmpmask;
+ char c, *host, *pass, *name;
+ char *pp, *ppx;
+ tmpmask = (mask == CONF_MISSING) ? CONF_CONNECT_SERVER : mask;
+
+ for (tmp = conf; tmp; tmp = tmp->next)
+ if (tmp->status & tmpmask)
+ {
+ for (p = &report_array[0][0]; *p; p += 3)
+ if (*p == tmp->status)
+ break;
+ if (!*p)
+ continue;
+ c = (char)*(p+2);
+ host = BadPtr(tmp->host) ? null : tmp->host;
+ pass = BadPtr(tmp->passwd) ? null : tmp->passwd;
+ name = BadPtr(tmp->name) ? null : tmp->name;
+ port = (int)tmp->port;
+ /*
+ * On K line the passwd contents can be
+ * displayed on STATS reply. -Vesa
+ */
+ /* Same with Z-lines and q/Q-lines -- Barubary */
+ if ((tmp->status == CONF_KILL) || (tmp->status &
+ CONF_QUARANTINE) || (tmp->status & CONF_EXCEPT)
+ ||
+ (tmp->status == CONF_ZAP))
+ {
+/* These mods are to tell the difference between the different kinds
+ * of klines. the only effect it has is in the display. --Russell
+ */
+/* Now translates spaces to _'s to show comments in klines -- Barubary */
+ char *temp;
+ if (!pass) strcpy(buf, "<NULL>");
+ else {
+ strcpy(buf, pass);
+ for (temp = buf; *temp; temp++)
+ if (*temp == ' ') *temp = '_';
+ }
+ /* semicolon intentional -- Barubary */
+ if (tmp->status == CONF_QUARANTINED_NICK);
+ /* Hide password for servers -- Barubary */
+ else if (tmp->status & CONF_QUARANTINE)
+ strcpy(buf, "*");
+ else {
+/* This wasn't documented before - comments aren't displayed for akills
+ because they are all the same. -- Barubary */
+ if (tmp->tmpconf == KLINE_AKILL)
+ strcpy(buf, "*");
+
+ /* Show comments in E:Lines..
+ if (tmp->tmpconf == KLINE_EXCEPT)
+ strcpy(buf, "*");
+ */
+ /* KLINE_PERM == 0 - watch out when doing
+ Z-lines. -- Barubary */
+ if (tmp->status != CONF_ZAP)
+ {
+ if (tmp->tmpconf == KLINE_PERM) c = 'K';
+ if (tmp->tmpconf == KLINE_TEMP) c = 'k';
+ if (tmp->tmpconf == KLINE_AKILL) c = 'A';
+ if (tmp->tmpconf == KLINE_EXCEPT) c = 'E';
+ }
+ else
+ {
+ if (tmp->tmpconf == KLINE_PERM) c = 'Z';
+ if (tmp->tmpconf == KLINE_TEMP) c = 'z';
+ if (tmp->tmpconf == KLINE_AKILL) c = 'S';
+ if (tmp->tmpconf == KLINE_EXCEPT) c = 'e';
+ }
+ }
+ sendto_one(sptr, rpl_str(p[1]), me.name,
+ sptr->name, c, host,
+ buf, name, port,
+ get_conf_class(tmp));
+ }
+ else if (mask & CONF_OPS)
+ {
+ sendto_one(sptr, rpl_str(p[1]), me.name,
+ sptr->name,c,host,name, oflagstr(port),
+ get_conf_class(tmp));
+ }
+
+ /* connect rules are classless */
+ else if (tmp->status & CONF_CRULE)
+ sendto_one(sptr, rpl_str(p[1]), me.name,
+ sptr->name, c, host, name);
+ /* Only display on X if server is missing */
+ else if (mask == CONF_MISSING) {
+ if (!find_server(name, NULL))
+ sendto_one(sptr, rpl_str(RPL_STATSXLINE), me.name,
+ sptr->name, name, port);
+ }
+ else if (mask == CONF_TLINE)
+ {
+ sendto_one(sptr, rpl_str(RPL_STATSTLINE), me.name,
+ sptr->name, host, pass, name);
+ }
+/* else if (mask == CONF_EXCEPT)
+ {
+ ppx = MyMalloc(strlen(tmp->passwd) + 1);
+ strcpy(ppx, tmp->passwd);
+ for (pp = ppx; *pp != '\0'; pp++) {
+ if (*pp == ' ')
+ *pp = '_';
+ }
+ sendto_one(sptr, rpl_str(RPL_STATSKLINE), me.name,
+ sptr->name, "E", host, ppx, name, 0,0, -1);
+ MyFree(ppx);
+ } */
+ else {
+ if(!IsOper(sptr)&&(mask&CONF_NOCONNECT_SERVER ||
+ mask&CONF_CONNECT_SERVER))
+ sendto_one(sptr, rpl_str(p[1]), me.name,
+ sptr->name, c, "*", name, port,
+ get_conf_class(tmp));
+ else
+ sendto_one(sptr, rpl_str(p[1]), me.name,
+ sptr->name, c, host, name, port,
+ get_conf_class(tmp));
+ }
+ }
+ return;
+}
+
+
+
+/* Used to blank out ports -- Barubary */
+char *get_client_name2(aClient *acptr, int showports)
+{
+ char *pointer = get_client_name(acptr, TRUE);
+
+ if (!pointer) return NULL;
+ if (showports) return pointer;
+ if (!strrchr(pointer, '.')) return NULL;
+ strcpy((char *) strrchr((char *) pointer, '.'), ".0]");
+
+ return pointer;
+}
+
+int m_stats(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+#ifndef DEBUGMODE
+ static char Sformat[] = ":%s %d %s SendQ SendM SendBytes RcveM RcveBytes Open_since :Idle";
+ static char Lformat[] = ":%s %d %s %s %u %u %u %u %u %u :%u";
+#else
+ static char Sformat[] = ":%s %d %s SendQ SendM SendBytes RcveM RcveBytes Open_since CPU :Idle";
+ static char Lformat[] = ":%s %d %s %s %u %u %u %u %u %u %s";
+ char pbuf[96]; /* Should be enough for to ints */
+#endif
+ struct Message *mptr;
+ aClient *acptr;
+ char stat = parc > 1 ? parv[1][0] : '\0';
+ Reg1 int i;
+ int doall = 0, wilds = 0, showports = IsAnOper(sptr), remote=0;
+ char *name;
+
+ if (check_registered(sptr))
+ return 0;
+
+#ifdef STATS_ONLYOPER
+ if (!IsAnOper(sptr))
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+
+#endif
+
+ if (hunt_server(cptr,sptr,":%s STATS %s :%s",2,parc,parv)!=HUNTED_ISME)
+ return 0;
+
+ if (parc > 2)
+ {
+ name = parv[2];
+ if (!mycmp(name, me.name))
+ doall = 2;
+ else if (match(name, me.name) == 0)
+ doall = 1;
+ if (index(name, '*') || index(name, '?'))
+ wilds = 1;
+ }
+ else
+ name = me.name;
+
+ if (stat != '\0')
+ sendto_umode(UMODE_EYES,"Stats \'%c\' requested by %s (%s@%s)", stat, sptr->name,
+ sptr->user->username, IsHidden(sptr) ? sptr->user->virthost : sptr->user->realhost);
+ else
+ sendto_umode(UMODE_EYES,"Stats \'NULL\' requested by %s (%s@%s)", sptr->name,
+ sptr->user->username, IsHidden(sptr) ? sptr->user->virthost : sptr->user->realhost);
+
+ switch (stat)
+ {
+ case 'L' : case 'l' :
+ /*
+ * send info about connections which match, or all if the
+ * mask matches me.name. Only restrictions are on those who
+ * are invisible not being visible to 'foreigners' who use
+ * a wild card based search to list it.
+ */
+ sendto_one(sptr, Sformat, me.name, RPL_STATSLINKINFO, parv[0]);
+ if (IsServer(cptr)) {
+ remote = 1;
+ wilds = 0;
+ }
+ for (i = 0; i <= highest_fd; i++)
+ {
+ if (!(acptr = local[i]))
+ continue;
+ if (IsInvisible(acptr) && (doall || wilds) &&
+ !(MyConnect(sptr) && IsOper(sptr)) &&
+ !IsAnOper(acptr) && (acptr != sptr))
+ continue;
+ if (remote && doall && !IsServer(acptr) &&
+ !IsMe(acptr))
+ continue;
+ if (remote && !doall && IsServer(acptr))
+ continue;
+ if (!doall && wilds && match(name, acptr->name))
+ continue;
+ if (!(parc == 2 && IsServer(acptr)) &&
+ !(doall || wilds) && mycmp(name, acptr->name))
+ continue;
+#ifdef DEBUGMODE
+ sprintf(pbuf, "%d :%d", acptr->cputime,
+ (acptr->user && MyConnect(acptr)) ?
+ TStime() - acptr->user->last : 0);
+#endif
+ if(IsOper(sptr)) {
+ sendto_one(sptr, Lformat, me.name,
+ RPL_STATSLINKINFO, parv[0],
+ (isupper(stat)) ?
+ get_client_name2(acptr, showports) :
+ get_client_name(acptr, FALSE),
+ (int)DBufLength(&acptr->sendQ),
+ (int)acptr->sendM, (int)acptr->sendK,
+ (int)acptr->receiveM, (int)acptr->receiveK,
+ TStime() - acptr->firsttime,
+#ifndef DEBUGMODE
+ (acptr->user && MyConnect(acptr)) ?
+ TStime() - acptr->user->last : 0);
+#else
+ pbuf);
+#endif
+ if (!IsServer(acptr) && IsAnOper(acptr))
+ sendto_one(acptr, ":%s NOTICE %s :*** %s did a /stats L on you! IP may have been shown", me.name, acptr->name, sptr->name);
+ }
+ else if(!strchr(acptr->name,'.'))
+ sendto_one(sptr, Lformat, me.name,
+ RPL_STATSLINKINFO, parv[0],
+ IsHidden(acptr) ? acptr->name :
+ (isupper(stat)) ? /* Potvin - PreZ */
+ get_client_name2(acptr, showports) :
+ get_client_name(acptr, FALSE),
+ (int)DBufLength(&acptr->sendQ),
+ (int)acptr->sendM, (int)acptr->sendK,
+ (int)acptr->receiveM, (int)acptr->receiveK,
+ TStime() - acptr->firsttime,
+#ifndef DEBUGMODE
+ (acptr->user && MyConnect(acptr)) ?
+ TStime() - acptr->user->last : 0);
+#else
+ pbuf);
+#endif
+ }
+ break;
+ case 'C' : case 'c' :
+ report_configured_links(sptr, CONF_CONNECT_SERVER|
+ CONF_NOCONNECT_SERVER);
+ break;
+ case 'f' : case 'F' :
+ report_flines(sptr);
+ break;
+
+ case 'G' : case 'g' :
+ tkl_stats (sptr);
+ break;
+ case 'H' : case 'h' :
+ report_configured_links(sptr, CONF_HUB|CONF_LEAF);
+ break;
+ case 'I' : case 'i' :
+ report_configured_links(sptr, CONF_CLIENT);
+ break;
+ case 'E' : case 'e' :
+ report_configured_links(sptr, CONF_EXCEPT);
+ break;
+ case 'K' : case 'k' :
+ report_configured_links(sptr, CONF_KILL|CONF_ZAP|CONF_EXCEPT);
+ break;
+ case 'M' : case 'm' :
+ for (mptr = msgtab; mptr->cmd; mptr++)
+ if (mptr->count)
+#ifndef DEBUGMODE
+ sendto_one(sptr, rpl_str(RPL_STATSCOMMANDS),
+ me.name, parv[0], mptr->cmd,
+ mptr->count, mptr->bytes);
+#else
+ sendto_one(sptr, rpl_str(RPL_STATSCOMMANDS),
+ me.name, parv[0], mptr->cmd,
+ mptr->count, mptr->bytes,
+ mptr->lticks,
+ mptr->lticks/CLOCKS_PER_SEC,
+ mptr->rticks,
+ mptr->rticks/CLOCKS_PER_SEC);
+#endif
+ break;
+ case 'N': case 'n':
+ if (IsOper(sptr))
+ report_network(sptr);
+ break;
+ case 'o' : case 'O' :
+/* if (SHOWOPERS == 1) {
+ if(IsOper(sptr)) {
+ report_configured_links(sptr, CONF_OPS);
+ break;
+ }
+ }
+ else
+ if (SHOWOPERS == 0) {
+ report_configured_links(sptr, CONF_OPS);
+*/
+ if (SHOWOPERS == 0 && (IsOper(sptr))) {
+ report_configured_links(sptr, CONF_OPS);
+ break;
+ }
+ if (SHOWOPERS == 1)
+ report_configured_links(sptr, CONF_OPS);
+ break;
+ case 'Q' :
+ report_configured_links(sptr, CONF_QUARANTINE);
+ break;
+ case 'q' :
+ report_sqlined_nicks(sptr);
+ break;
+ case 'R' :
+#ifdef DEBUGMODE
+ send_usage(sptr,parv[0]);
+#endif
+ break;
+ case 'S' :
+ if (IsOper(sptr))
+ report_dynconf(sptr);
+ break;
+ case 'D' :
+ report_configured_links(sptr, CONF_CRULEALL);
+ break;
+ case 'd' :
+ report_configured_links(sptr, CONF_CRULE);
+ break;
+ case 'r' :
+ cr_report(sptr);
+ break;
+ case 't' :
+ report_configured_links(sptr, CONF_TLINE);
+ break;
+ case 'T' : /* /stats T not t:lines .. */
+ tstats(sptr, parv[0]);
+ break;
+ case 'U' :
+ report_configured_links(sptr, CONF_UWORLD);
+ break;
+ case 'u' :
+ {
+ register time_t tmpnow;
+
+ tmpnow = TStime() - me.since;
+ sendto_one(sptr, rpl_str(RPL_STATSUPTIME), me.name, parv[0],
+ tmpnow/86400, (tmpnow/3600)%24, (tmpnow/60)%60, tmpnow%60);
+ sendto_one(sptr, rpl_str(RPL_STATSCONN), me.name, parv[0],
+ max_connection_count, max_client_count);
+ break;
+ }
+ case 'v' : case 'V' :
+ vhost_report(sptr);
+ break;
+ case 'W' : case 'w' :
+ calc_load(sptr, parv[0]);
+ break;
+ case 'X' : case 'x' :
+ report_configured_links(sptr, CONF_MISSING);
+ break;
+ case 'Y' : case 'y' :
+ report_classes(sptr);
+ break;
+ case 'Z' : case 'z' :
+ count_memory(sptr, parv[0]);
+ break;
+ default :
+ stat = '*';
+ break;
+ }
+ sendto_one(sptr, rpl_str(RPL_ENDOFSTATS), me.name, parv[0], stat);
+ return 0;
+ }
+
+/*
+** m_users
+** parv[0] = sender prefix
+** parv[1] = servername
+*/
+int m_users(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+#ifdef ENABLE_USERS
+ char namebuf[10],linebuf[10],hostbuf[17];
+ int fd, flag = 0;
+#endif
+
+ if (check_registered_user(sptr))
+ return 0;
+
+ if (hunt_server(cptr,sptr,":%s USERS :%s",1,parc,parv) == HUNTED_ISME)
+ {
+#ifdef ENABLE_USERS
+ if ((fd = utmp_open()) == -1)
+ {
+ sendto_one(sptr, err_str(ERR_FILEERROR),
+ me.name, parv[0], "open", UTMP);
+ return 0;
+ }
+
+ sendto_one(sptr, rpl_str(RPL_USERSSTART), me.name, parv[0]);
+ while (utmp_read(fd, namebuf, linebuf,
+ hostbuf, sizeof(hostbuf)) == 0)
+ {
+ flag = 1;
+ sendto_one(sptr, rpl_str(RPL_USERS), me.name, parv[0],
+ namebuf, linebuf, hostbuf);
+ }
+ if (flag == 0)
+ sendto_one(sptr, rpl_str(RPL_NOUSERS),
+ me.name, parv[0]);
+
+ sendto_one(sptr, rpl_str(RPL_ENDOFUSERS), me.name, parv[0]);
+ (void)utmp_close(fd);
+#else
+ sendto_one(sptr, err_str(ERR_USERSDISABLED), me.name, parv[0]);
+#endif
+ }
+ return 0;
+}
+
+/*
+** Note: At least at protocol level ERROR has only one parameter,
+** although this is called internally from other functions
+** --msa
+**
+** parv[0] = sender prefix
+** parv[*] = parameters
+*/
+int m_error(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ Reg1 char *para;
+
+ para = (parc > 1 && *parv[1] != '\0') ? parv[1] : "<>";
+
+ Debug((DEBUG_ERROR,"Received ERROR message from %s: %s",
+ sptr->name, para));
+ /*
+ ** Ignore error messages generated by normal user clients
+ ** (because ill-behaving user clients would flood opers
+ ** screen otherwise). Pass ERROR's from other sources to
+ ** the local operator...
+ */
+ if (IsPerson(cptr) || IsUnknown(cptr) || IsService(cptr))
+ return 0;
+ if (cptr == sptr) {
+ sendto_serv_butone(&me, ":%s GLOBOPS :ERROR from %s -- %s",
+ me.name, get_client_name(cptr, FALSE), para);
+ sendto_locfailops("ERROR :from %s -- %s",
+ get_client_name(cptr, FALSE), para);
+ }
+ else {
+ sendto_serv_butone(&me, ":%s GLOBOPS :ERROR from %s via %s -- %s",
+ me.name, sptr->name, get_client_name(cptr, FALSE), para);
+ sendto_ops("ERROR :from %s via %s -- %s", sptr->name,
+ get_client_name(cptr,FALSE), para);
+ }
+ return 0;
+ }
+
+Link *helpign=NULL;
+
+/* Now just empty ignore-list, in future reload dynamic help.
+ * Move out to help.c -Donwulff */
+void reset_help() {
+ free_str_list(helpign);
+}
+
+
+
+
+/*
+** m_help (help/write to +h currently online) -Donwulff
+** parv[0] = sender prefix
+** parv[1] = optional message text
+*/
+int m_help(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ int i;
+ char *message, *pv[4], *s;
+ Link *tmpl;
+
+ if (check_registered(sptr))
+ return 0;
+
+ message = parc > 1 ? parv[1] : NULL;
+
+/* Drags along from wallops code... I'm not sure what it's supposed to do,
+ at least it won't do that gracefully, whatever it is it does - but
+ checking whether or not it's a person _is_ good... -Donwulff */
+
+ if (!IsServer(sptr) && MyConnect(sptr) && !IsPerson(sptr))
+ {
+ check_registered(sptr);
+ return 0;
+ }
+
+ if (IsServer(sptr) || IsHelpOp(sptr)) {
+ if(BadPtr(message)) return 0;
+ if(message[0]=='?') {
+ parse_help(sptr, parv[0], message+1);
+ return 0;
+ }
+ if (message[1]=='!')
+ sendto_serv_butone(IsServer(cptr) ? cptr : NULL,
+ ":%s HELP %s", parv[0], message);
+ if(!myncmp(message, "IGNORE ", 7)) {
+ tmpl=make_link();
+ DupString(tmpl->value.cp, message+7);
+ tmpl->next = helpign;
+ helpign=tmpl;
+ }
+ sendto_helpops("from %s (HelpOp): %s", parv[0], message);
+ } else if (MyConnect(sptr)) {
+ /* New syntax: ?... never goes out, !... always does. */
+ if(!BadPtr(message)) {
+ parse_help(sptr, parv[0], message);
+ return 0;
+ }
+ if((!BadPtr(message)&&!(message[0]=='!'))||BadPtr(message))
+ if(parse_help(sptr, parv[0], message)) return 0;
+
+ s = make_nick_user_host(cptr->name, cptr->user->username,
+ cptr->user->realhost);
+ for (tmpl = helpign; tmpl; tmpl = tmpl->next)
+ if (match(tmpl->value.cp, s) == 0) {
+ sendto_one(sptr, rpl_str(RPL_HELPIGN), me.name, parv[0]);
+ return 0;
+ }
+
+ sendto_serv_butone(IsServer(cptr) ? cptr : NULL,
+ ":%s HELP %s", parv[0], message);
+ sendto_helpops("from %s (Local): %s", parv[0], message);
+ sendto_one(sptr, rpl_str(RPL_HELPFWD), me.name, parv[0]);
+ } else {
+ sendto_serv_butone(IsServer(cptr) ? cptr : NULL,
+ ":%s HELP %s", parv[0], message);
+ sendto_helpops("from %s: %s", parv[0], message);
+ }
+
+ return 0;
+}
+
+/*
+ * parv[0] = sender
+ * parv[1] = host/server mask.
+ * parv[2] = server to query
+ */
+int m_lusers(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ int s_count, c_count, u_count, i_count;
+ int o_count, m_client, m_client_local, m_server;
+ char mydom_mask[HOSTLEN + 1];
+ aClient *acptr;
+
+ if (check_registered_user(sptr))
+ return 0;
+
+/* Doesn't work anyways --Stskeeps
+
+ if (parc > 2)
+ if(hunt_server(cptr, sptr, ":%s LUSERS %s :%s", 2, parc, parv)
+ != HUNTED_ISME)
+ return 0;
+*/
+
+ mydom_mask[0] = '*';
+ strncpy(&mydom_mask[1], DOMAINNAME, HOSTLEN - 1);
+ if(parc==1) {
+ s_count = lu_serv;
+ c_count = lu_noninv;
+ u_count = lu_unknown;
+ i_count = lu_inv;
+ o_count = lu_oper;
+ m_client = lu_lu;
+ m_client_local = lu_lulocal;
+ m_server = lu_lserv;
+ global_count=lu_cglobalu;
+ }
+ else {
+ s_count=c_count=u_count=i_count=o_count=m_client=
+ m_client_local=m_server=0;
+ (void)collapse(parv[1]);
+ for (acptr = client; acptr; acptr = acptr->next)
+ {
+ if (parc>1)
+ if (!IsServer(acptr) && acptr->user)
+ {
+ if (match(parv[1], acptr->user->server))
+ continue;
+ }
+ else
+ if (match(parv[1], acptr->name))
+ continue;
+
+ switch (acptr->status)
+ {
+ case STAT_SERVER:
+ if (MyConnect(acptr))
+ m_server++;
+ case STAT_ME:
+ s_count++;
+ break;
+ case STAT_CLIENT:
+ if (IsOper(acptr))
+ o_count++;
+ if (MyConnect(acptr)) {
+ m_client++;
+ if (match(mydom_mask, acptr->sockhost) == 0)
+ m_client_local++;
+ }
+ if (!IsInvisible(acptr))
+ c_count++;
+ else
+ i_count++;
+ break;
+ default:
+ u_count++;
+ break;
+ }
+ }
+ }
+ sendto_one(sptr, rpl_str(RPL_LUSERCLIENT), me.name, parv[0],
+ c_count, i_count, s_count);
+ max_client_count = lu_mlu;
+ max_global_count = lu_mglobalu;
+
+ if (o_count)
+ sendto_one(sptr, rpl_str(RPL_LUSEROP),
+ me.name, parv[0], o_count);
+ if (u_count > 0)
+ sendto_one(sptr, rpl_str(RPL_LUSERUNKNOWN),
+ me.name, parv[0], u_count);
+ if ((c_count = count_channels(sptr))>0)
+ sendto_one(sptr, rpl_str(RPL_LUSERCHANNELS),
+ me.name, parv[0], lu_channel);
+ sendto_one(sptr, rpl_str(RPL_LUSERME),
+ me.name, parv[0], m_client, m_server);
+ sendto_one(sptr, rpl_str(RPL_LOCALUSERS),
+ me.name, parv[0], m_client, max_client_count);
+ sendto_one(sptr, rpl_str(RPL_GLOBALUSERS),
+ me.name, parv[0], global_count, max_global_count);
+ if ((m_client + m_server) > max_connection_count) {
+ max_connection_count = m_client + m_server;
+ if (max_connection_count % 10 == 0) /* only send on even tens */
+ sendto_ops("Maximum connections: %d (%d clients)",
+ max_connection_count, max_client_count);
+ }
+ current_load_data.local_count = m_client_local;
+ current_load_data.client_count = m_client;
+ current_load_data.conn_count = m_client + m_server;
+ return 0;
+}
+
+
+void save_tunefile(void)
+{
+ FILE *tunefile;
+
+ tunefile = fopen(IRCDTUNE, "w+");
+ if (!tunefile) {
+#if !defined(_WIN32) && !defined(_AMIGA)
+ sendto_ops("Unable to write tunefile.. %s", strerror(errno));
+#else
+ sendto_ops("Unable to write tunefile..");
+#endif
+ return;
+ }
+ fprintf(tunefile, "%li\n", TSoffset);
+ fprintf(tunefile, "%li\n", lu_mlu);
+ fclose(tunefile);
+}
+
+void load_tunefile(void)
+{
+ FILE *tunefile;
+ char buf[1024];
+
+ tunefile = fopen(IRCDTUNE, "r");
+ if (!tunefile)
+ return;
+ fprintf(stderr, "* Loading tunefile..\n");
+ fgets(buf, 1023, tunefile);
+ TSoffset = atol(buf);
+ fgets(buf, 1023, tunefile);
+ lu_mlu = atol(buf);
+ fclose(tunefile);
+}
+
+/***********************************************************************
+ * m_connect() - Added by Jto 11 Feb 1989
+ ***********************************************************************/
+
+/*
+** m_connect
+** parv[0] = sender prefix
+** parv[1] = servername
+** parv[2] = port number
+** parv[3] = remote server
+*/
+int m_connect(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ int port, tmpport, retval;
+ aConfItem *aconf, *cconf;
+ aClient *acptr;
+
+ if (check_registered(sptr))
+ return 0;
+
+ if (!IsPrivileged(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return -1;
+ }
+
+ if (MyClient(sptr) && !OPCanGRoute(sptr) && parc > 3)
+ { /* Only allow LocOps to make */
+ /* local CONNECTS --SRB */
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ if (MyClient(sptr) && !OPCanLRoute(sptr) && parc <= 3)
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ if (hunt_server(cptr,sptr,":%s CONNECT %s %s :%s",
+ 3,parc,parv) != HUNTED_ISME)
+ return 0;
+
+ if (parc < 2 || *parv[1] == '\0')
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "CONNECT");
+ return -1;
+ }
+
+ if ((acptr = find_server(parv[1], NULL)))
+ {
+ sendto_one(sptr, ":%s NOTICE %s :Connect: Server %s %s %s.",
+ me.name, parv[0], parv[1], "already exists from",
+ acptr->from->name);
+ return 0;
+ }
+
+ for (aconf = conf; aconf; aconf = aconf->next)
+ if (aconf->status == CONF_CONNECT_SERVER &&
+ match(parv[1], aconf->name) == 0)
+ break;
+ /* Checked first servernames, then try hostnames. */
+ if (!aconf)
+ for (aconf = conf; aconf; aconf = aconf->next)
+ if (aconf->status == CONF_CONNECT_SERVER &&
+ (match(parv[1], aconf->host) == 0 ||
+ match(parv[1], index(aconf->host, '@')+1) == 0))
+ break;
+
+ if (!aconf)
+ {
+ sendto_one(sptr,
+ "NOTICE %s :Connect: Host %s not listed in ircd.conf",
+ parv[0], parv[1]);
+ return 0;
+ }
+ /*
+ ** Get port number from user, if given. If not specified,
+ ** use the default form configuration structure. If missing
+ ** from there, then use the precompiled default.
+ */
+ tmpport = port = aconf->port;
+ if (parc > 2 && !BadPtr(parv[2]))
+ {
+ if ((port = atoi(parv[2])) <= 0)
+ {
+ sendto_one(sptr,
+ "NOTICE %s :Connect: Illegal port number",
+ parv[0]);
+ return 0;
+ }
+ }
+ else if (port <= 0 && (port = PORTNUM) <= 0)
+ {
+ sendto_one(sptr, ":%s NOTICE %s :Connect: missing port number",
+ me.name, parv[0]);
+ return 0;
+ }
+
+ /*
+ ** Evaluate connection rules... If no rules found, allow the
+ ** connect. Otherwise stop with the first true rule (ie: rules
+ ** are ored together. Oper connects are effected only by D
+ ** lines (CRULEALL) not d lines (CRULEAUTO).
+ */
+ for (cconf = conf; cconf; cconf = cconf->next)
+ if ((cconf->status == CONF_CRULEALL) &&
+ (match(cconf->host, aconf->name) == 0))
+ if (crule_eval (cconf->passwd))
+ {
+ sendto_one(sptr,
+ "NOTICE %s :Connect: Disallowed by rule: %s",
+ parv[0], cconf->name);
+ return 0;
+ }
+
+ /*
+ ** Notify all operators about remote connect requests
+ */
+ if (!IsAnOper(cptr))
+ {
+ sendto_serv_butone(&me,
+ ":%s GLOBOPS :Remote CONNECT %s %s from %s",
+ me.name, parv[1], parv[2] ? parv[2] : "",
+ get_client_name(sptr,FALSE));
+#if defined(USE_SYSLOG) && defined(SYSLOG_CONNECT)
+ syslog(LOG_DEBUG, "CONNECT From %s : %s %d", parv[0], parv[1], parv[2] ? parv[2] : "");
+#endif
+ }
+ aconf->port = port;
+ switch (retval = connect_server(aconf, sptr, NULL))
+ {
+ case 0:
+ sendto_one(sptr,
+ ":%s NOTICE %s :*** Connecting to %s[%s].",
+ me.name, parv[0], aconf->host, aconf->name);
+ break;
+ case -1:
+ sendto_one(sptr, ":%s NOTICE %s :*** Couldn't connect to %s.",
+ me.name, parv[0], aconf->host);
+ break;
+ case -2:
+ sendto_one(sptr, ":%s NOTICE %s :*** Host %s is unknown.",
+ me.name, parv[0], aconf->host);
+ break;
+ default:
+ sendto_one(sptr,
+ ":%s NOTICE %s :*** Connection to %s failed: %s",
+ me.name, parv[0], aconf->host, strerror(retval));
+ }
+ aconf->port = tmpport;
+ return 0;
+ }
+
+/*
+** m_wallops (write to *all* opers currently online)
+** parv[0] = sender prefix
+** parv[1] = message text
+*/
+int m_wallops(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ char *message, *pv[4];
+
+ if (check_registered(sptr))
+ return 0;
+
+ message = parc > 1 ? parv[1] : NULL;
+
+ if (BadPtr(message))
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "WALLOPS");
+ return 0;
+ }
+ if (MyClient(sptr) && !OPCanWallOps(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ sendto_ops_butone(IsServer(cptr) ? cptr : NULL, sptr,
+ ":%s WALLOPS :%s", parv[0], message);
+ return 0;
+ }
+
+
+/* m_gnotice (Russell) sort of like wallop, but only to +g clients on
+** this server.
+** parv[0] = sender prefix
+** parv[1] = message text
+*/
+int m_gnotice(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ char *message, *pv[4];
+
+ if (check_registered(sptr))
+ return 0;
+
+ message = parc > 1 ? parv[1] : NULL;
+
+ if (BadPtr(message))
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "GNOTICE");
+ return 0;
+ }
+ if (!IsServer(sptr) && MyConnect(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ sendto_serv_butone(IsServer(cptr) ? cptr : NULL, ":%s GNOTICE :%s",
+ parv[0], message);
+ sendto_failops("from %s: %s", parv[0], message);
+ return 0;
+}
+
+/*
+** m_addline (write a line to ircd.conf)
+**
+** De-Potvinized by codemastr
+*/
+int m_addline(aClient *cptr, aClient *sptr, int parc, char *parv[])
+{
+ FILE *conf;
+ int i;
+ char *text;
+ text = parc > 1 ? parv[1] : NULL;
+
+ if (check_registered(sptr))
+ return 0;
+
+
+ if (!(IsAdmin(sptr) || IsCoAdmin(sptr)))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ if (parc < 2)
+ {
+ sendto_one (sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "ADDLINE");
+ return 0;
+ }
+ conf = fopen (CPATH, "a");
+ if (conf == NULL)
+ {
+ return 0;
+ }
+ /* Display what they wrote too */
+ sendto_one(sptr, ":%s NOTICE %s :*** Wrote (%s) to ircd.conf",
+ me.name, parv[0], text);
+ fprintf(conf, "# Added by %s\n", make_nick_user_host(sptr->name,sptr->user->username,sptr->user->realhost));
+/* for (i=1 ; i<parc ; i++)
+ {
+ if (i!=parc-1)
+ fprintf (conf,"%s ",parv[i]);
+ else
+ fprintf (conf,"%s\n",parv[i]);
+ }
+ /* I dunno what Potvin was smoking when he made this code, but it plain SUX
+ * this should work just as good, and no need for a loop -- codemastr */
+ fprintf(conf, "%s\n", text);
+
+ fclose (conf);
+ return 1;
+}
+
+/*
+** m_addmotd (write a line to ircd.motd)
+**
+** De-Potvinized by codemastr
+*/
+int m_addmotd(aClient *cptr, aClient *sptr, int parc, char *parv[])
+{
+ FILE *conf;
+ char *text;
+
+ int i;
+
+ text = parc > 1 ? parv[1] : NULL;
+
+ if (check_registered(sptr))
+ return 0;
+ if (!MyConnect(sptr))
+ return 0;
+
+ if (!(IsAdmin(sptr) || IsCoAdmin(sptr)))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ if (parc < 2)
+ {
+ sendto_one (sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "ADDMOTD");
+ return 0;
+ }
+ conf = fopen (MOTD, "a");
+ if (conf == NULL)
+ {
+ return 0;
+ }
+ sendto_one(sptr, ":%s NOTICE %s :*** Wrote (%s) to file: ircd.motd",
+ me.name, parv[0], text);
+ /* for (i=1 ; i<parc ; i++)
+ {
+ if (i!=parc-1)
+ fprintf (conf,"%s ",parv[i]);
+ else
+ fprintf (conf,"%s\n",parv[i]);
+ } */
+ fprintf(conf, "%s\n", text);
+
+ fclose (conf);
+ return 1;
+}
+
+/*
+** m_svsmotd
+**
+*/
+int m_svsmotd(aClient *cptr, aClient *sptr, int parc, char *parv[])
+{
+ FILE *conf = NULL;
+ int i;
+
+ if (check_registered(sptr))
+ return 0;
+
+ if (!IsULine(cptr, sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+
+ if (parc < 2)
+ {
+ sendto_one (sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "SVSMOTD");
+ return 0;
+ }
+
+ if ((*parv[1] != '!') && parc < 3) {
+ sendto_one (sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "SVSMOTD");
+ return 0;
+ }
+
+ switch (*parv[1]) {
+ case '#' : conf = fopen(VPATH, "a");
+ sendto_ops("Added '%s' to services motd", parv[2]);
+ break;
+ case '!' : {
+ remove(VPATH);
+ sendto_ops("Wiped out services motd data");
+ break;
+ }
+ default: break;
+ }
+
+ sendto_serv_butone(cptr, ":%s SVSMOTD %s :%s", parv[0], parv[1], parv[2]);
+
+ if (conf == NULL)
+ {
+ return 0;
+ }
+
+ if (parc < 3 && (*parv[1]=='!')) {
+ fclose(conf);
+ return 1;
+ }
+ fprintf(conf, "%s\n", parv[2]);
+ if (*parv[1]=='!')
+ sendto_ops("Added '%s' to services motd", parv[2]);
+
+ fclose (conf);
+ return 1;
+}
+
+/*
+** m_addomotd (write a line to opermotd)
+**
+** De-Potvinized by codemastr
+*/
+int m_addomotd(aClient *cptr, aClient *sptr, int parc, char *parv[])
+{
+ FILE *conf;
+ char *text;
+ int i;
+
+ text = parc > 1 ? parv[1] : NULL;
+
+ if (check_registered(sptr))
+ return 0;
+ if (!MyConnect(sptr))
+ return 0;
+
+ if (!(IsAdmin(sptr) || IsCoAdmin(sptr)))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ if (parc < 2)
+ {
+ sendto_one (sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "ADDMOTD");
+ return 0;
+ }
+ conf = fopen (OPATH, "a");
+ if (conf == NULL)
+ {
+ return 0;
+ }
+ sendto_one(sptr, ":%s NOTICE %s :*** Wrote (%s) to OperMotd",
+ me.name, parv[0], text);
+ /* for (i=1 ; i<parc ; i++)
+ {
+ if (i!=parc-1)
+ fprintf (conf,"%s ",parv[i]);
+ else
+ fprintf (conf,"%s\n",parv[i]);
+ } */
+ fprintf(conf, "%s\n", text);
+
+ fclose (conf);
+ return 1;
+}
+
+
+/*
+** m_globops (write to opers who are +g currently online)
+** parv[0] = sender prefix
+** parv[1] = message text
+*/
+int m_globops(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ char *message, *pv[4];
+
+ if (check_registered(sptr))
+ return 0;
+
+ message = parc > 1 ? parv[1] : NULL;
+
+ if (BadPtr(message))
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "GLOBOPS");
+ return 0;
+ }
+ if (MyClient(sptr) && !OPCanGlobOps(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ sendto_serv_butone(IsServer(cptr) ? cptr : NULL,
+ ":%s GLOBOPS :%s", parv[0], message);
+ sendto_failops_whoare_opers("from %s: %s", parv[0], message);
+ return 0;
+ }
+
+/*
+** m_locops (write to opers who are +g currently online *this* server)
+** parv[0] = sender prefix
+** parv[1] = message text
+*/
+int m_locops(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ char *message, *pv[4];
+
+ if (check_registered_user(cptr))
+ return 0;
+
+ message = parc > 1 ? parv[1] : NULL;
+
+ if (BadPtr(message))
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "LOCOPS");
+ return 0;
+ }
+ if (MyClient(sptr) && !OPCanLocOps(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ sendto_locfailops("from %s: %s", parv[0], message);
+ return 0;
+ }
+
+/*
+** m_chatops (write to opers who are +b currently online)
+** parv[0] = sender prefix
+** parv[1] = message text
+*/
+int m_chatops(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ char *message, *pv[4];
+
+ if (check_registered(sptr))
+ return 0;
+
+ message = parc > 1 ? parv[1] : NULL;
+
+ if (BadPtr(message))
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "CHATOPS");
+ return 0;
+ }
+ if (ALLOW_CHATOPS == 1) {
+ if (MyClient(sptr) && !SendChatops(sptr)) {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ }
+ else {
+ if (MyClient(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ }
+ sendto_serv_butone(IsServer(cptr) ? cptr : NULL,
+ ":%s CHATOPS :%s", parv[0], message);
+ if (ALLOW_CHATOPS == 1)
+ /* sendto_chatops("from %s: %s", parv[0], message); */
+ sendto_umode(UMODE_CHATOP, "*** ChatOps -- from %s: %s", parv[0], message);
+
+ return 0;
+ }
+
+
+/* m_goper (Russell) sort of like wallop, but only to ALL +o clients on
+** every server.
+** parv[0] = sender prefix
+** parv[1] = message text
+*/
+int m_goper(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ char *message, *pv[4];
+
+ if (check_registered(sptr))
+ return 0;
+
+ message = parc > 1 ? parv[1] : NULL;
+
+ if (BadPtr(message))
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "GOPER");
+ return 0;
+ }
+/* if (!IsServer(sptr) && MyConnect(sptr) && !IsAnOper(sptr))*/
+ if (!IsServer(sptr) || !IsULine(cptr,sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ sendto_serv_butone(IsServer(cptr) ? cptr : NULL, ":%s GOPER :%s",
+ parv[0], message);
+ sendto_opers("from %s: %s", parv[0], message);
+ return 0;
+}
+/*
+** m_time
+** parv[0] = sender prefix
+** parv[1] = servername
+*/
+int m_time(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ if (check_registered_user(sptr))
+ return 0;
+ if (hunt_server(cptr,sptr,":%s TIME :%s",1,parc,parv) == HUNTED_ISME)
+ sendto_one(sptr, rpl_str(RPL_TIME), me.name,
+ parv[0], me.name, date((long)0));
+ return 0;
+ }
+
+/*
+** m_svskill
+** parv[0] = servername
+** parv[1] = client
+** parv[2] = kill message
+*/
+int m_svskill(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ aClient *acptr;
+ char *comment;
+
+ (parc > 2 && parv[2]) ? parv[2] : "SVS Killed";
+
+ if (parc < 2)
+ return -1;
+ if (parc == 3)
+ comment = parv[2];
+
+ if (parc == 2)
+ comment = "SVS Killed";
+
+ if(!IsULine(cptr, sptr))
+ return -1;
+
+/* if (hunt_server(cptr,sptr,":%s SVSKILL %s :%s",1,parc,parv) != HUNTED_ISME)
+ return 0;
+*/
+
+ if(parc < 1 || (!(acptr = find_client(parv[1], NULL))))
+ return 0;
+ sendto_serv_butone(cptr, ":%s SVSKILL %s :%s", parv[0], parv[1], comment);
+
+ return exit_client(cptr, acptr, sptr, comment);
+
+}
+
+/*
+** m_admin
+** parv[0] = sender prefix
+** parv[1] = servername
+*/
+int m_admin(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ aConfItem *aconf;
+
+ /* Users may want to get the address in case k-lined, etc. -- Barubary
+ if (check_registered(sptr))
+ return 0; */
+
+ /* Only allow remote ADMINs if registered -- Barubary */
+ if (IsPerson(sptr) || IsServer(cptr))
+ if (hunt_server(cptr,sptr,":%s ADMIN :%s",1,parc,parv) != HUNTED_ISME)
+ return 0;
+ if ((aconf = find_admin()))
+ {
+ sendto_one(sptr, rpl_str(RPL_ADMINME),
+ me.name, parv[0], me.name);
+ sendto_one(sptr, rpl_str(RPL_ADMINLOC1),
+ me.name, parv[0],
+ (aconf->host ? aconf->host : "-"));
+ sendto_one(sptr, rpl_str(RPL_ADMINLOC2),
+ me.name, parv[0],
+ (aconf->passwd ? aconf->passwd : "-"));
+ sendto_one(sptr, rpl_str(RPL_ADMINEMAIL),
+ me.name, parv[0],
+ (aconf->name ? aconf->name : "-"));
+ }
+ else
+ sendto_one(sptr, err_str(ERR_NOADMININFO),
+ me.name, parv[0], me.name);
+ return 0;
+ }
+
+
+/*
+** m_rehash
+** remote rehash by binary
+** now allows the -flags in remote rehash
+** ugly code but it seems to work :) -- codemastr
+*/
+int m_rehash(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ int x;
+
+/* if ((!MyClient(sptr) && !(IsNetAdmin(sptr) || IsTechAdmin(sptr)) && !IsULine(cptr, sptr)) ||
+ (MyClient(sptr) && !OPCanRehash(sptr)))
+*/ if (MyClient(sptr) && !OPCanRehash(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ if (!MyClient(sptr) && !(IsTechAdmin(sptr) ||IsNetAdmin(sptr)) && !IsULine(cptr, sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ x = 0;
+
+ if (!BadPtr(parv[1]))
+ {
+ if (*parv[1] == '-')
+ {
+ if (!match("-dcc*", parv[1]))
+ {
+ sendto_ops("Rehashing dccdeny.conf on request of %s", sptr->name);
+ dcc_rehash();
+ return 0;
+ }
+ if (!match("-dyn*", parv[1]))
+ {
+ if (!IsAdmin(sptr))
+ return 0;
+ sendto_ops("Rehashing dynamic configuration on request of %s", sptr->name);
+ load_conf(ZCONF, 1);
+ return 0;
+ }
+ if (!match("-rest*", parv[1]))
+ {
+ if (!IsAdmin(sptr))
+ return 0;
+ sendto_ops("Rehashing channel restrict configuration on request of %s", sptr->name);
+ cr_rehash();
+ return 0;
+ }
+ if (!match("-vhos*", parv[1]))
+ {
+ if (!IsAdmin(sptr))
+ return 0;
+ sendto_ops("Rehashing vhost configuration on request of %s", sptr->name);
+ vhost_rehash();
+ return 0;
+ }
+ }
+ if (MyClient(sptr) && !(IsNetAdmin(sptr) || IsTechAdmin(sptr)))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ /* This little number allows us to send a -param to another server,
+ * but only if it exists -- codemastr*/
+ if (parv[2] != NULL) {
+ if ((x=hunt_server(cptr,sptr,":%s REHASH %s %s",1,parc,parv))
+ != HUNTED_ISME)
+ return 0;
+ }
+ if (parv[2] == NULL) {
+ if ((x=hunt_server(cptr,sptr,":%s REHASH %s",1,parc,parv))
+ != HUNTED_ISME)
+ return 0;
+ }
+
+ }
+
+ if (cptr != sptr)
+ {
+
+#ifndef REMOTE_REHASH
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+#else
+ if (parv[2] == NULL) {
+ sendto_serv_butone(&me, ":%s GLOBOPS :%s is remotely rehashing server config file",
+ me.name, sptr->name);
+ sendto_ops("%s is remotely rehashing server config file", parv[0]);
+ }
+ /* Then we have a hack here to parse the flags (thats the ugly part) */
+ else {
+ if (!BadPtr(parv[2]))
+ {
+ if (*parv[2] == '-')
+ {
+ if (!match("-dcc*", parv[2]))
+ {
+ sendto_serv_butone(&me, ":%s GLOBOPS :%s is remotely rehashing dccdeny.conf",
+ me.name, sptr->name);
+ sendto_ops("Remotely rehashing dccdeny.conf on request of %s", sptr->name);
+ dcc_rehash();
+ return 0;
+ }
+ if (!match("-dyn*", parv[2]))
+ {
+ sendto_serv_butone(&me, ":%s GLOBOPS :%s is remotely rehashing dynamic configuration",
+ me.name, sptr->name);
+ sendto_ops("Remotely rehashing dynamic configuration on request of %s", sptr->name);
+ load_conf(ZCONF, 1);
+ return 0;
+ }
+ if (!match("-rest*", parv[2]))
+ {
+ sendto_serv_butone(&me, ":%s GLOBOPS :%s is remotely rehashing channel restrict configuration",
+ me.name, sptr->name);
+ sendto_ops("Remotely rehashing channel restrict configuration on request of %s", sptr->name);
+ cr_rehash();
+ return 0;
+ }
+ if (!match("-vhos*", parv[2]))
+ {
+ sendto_serv_butone(&me, ":%s GLOBOPS :%s is remotely rehashing vhost configuration",
+ me.name, sptr->name);
+ sendto_ops("Remotely rehashing vhost configuration on request of %s", sptr->name);
+ vhost_rehash();
+ return 0;
+ }
+ }
+ }
+ }
+
+#endif
+ }
+ else {
+ sendto_ops("%s is rehashing server config file", parv[0]);
+ }
+ sendto_one(sptr, rpl_str(RPL_REHASHING), me.name, parv[0], configfile);
+#ifdef USE_SYSLOG
+ syslog(LOG_INFO, "REHASH From %s\n", get_client_name(sptr, FALSE));
+#endif
+ return rehash(cptr, sptr, (parc > 1) ? ((*parv[1] == 'q')?2:0) : 0);
+}
+
+/*
+** m_restart
+**
+** parv[1] - password *OR* reason if no X:line
+** parv[2] - reason for restart (optional & only if X:line exists)
+**
+** The password is only valid if there is a matching X line in the
+** config file. If it is not, then it becomes the
+*/
+int m_restart(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ char *pass = NULL;
+ int x;
+ if (check_registered(sptr))
+ return 0;
+
+ if (MyClient(sptr) && !OPCanRestart(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ if (!MyClient(sptr) && !(IsTechAdmin(sptr) ||IsNetAdmin(sptr)) && !IsULine(cptr, sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ if (parc > 2)
+ {
+ /* Remote restart. */
+ if (MyClient(sptr) && !(IsNetAdmin(sptr) || IsTechAdmin(sptr)))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+
+ if ((x=hunt_server(cptr,sptr,":%s RESTART %s %s :%s",2,parc,parv))
+ != HUNTED_ISME)
+ return 0;
+ }
+
+ if (cptr != sptr) {
+ sendto_serv_butone(&me, ":%s GLOBOPS :%s is remotely restarting server (%s)",
+ me.name, sptr->name, parv[3]);
+ sendto_ops("%s is remotely restarting IRCd (%s)", parv[0], parv[3]);
+
+ }
+
+ if ((pass = find_restartpass()))
+ {
+ if (parc < 2)
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "RESTART");
+ return 0;
+ }
+
+ if (strcmp(pass, parv[1]))
+ {
+ sendto_one(sptr, err_str(ERR_PASSWDMISMATCH), me.name, parv[0]);
+ return 0;
+ }
+ /* Hack to make the code after this if { } easier: we assign the comment to the
+ * first param, as if we had not had an X:line. We do not need the password
+ * now anyways. Accordingly we decrement parc ;) -- NikB
+ */
+ parv[1] = parv[2];
+ parc--;
+ }
+
+#ifdef USE_SYSLOG
+ syslog(LOG_WARNING, "Server RESTART by %s - %s\n",
+ get_client_name(sptr,FALSE),
+ (!MyClient(sptr) ? (parc > 2 ? parv[3] : "No reason")
+ : (parc > 1 ? parv[2] : "No reason")));
+#endif
+ sendto_ops("Server is Restarting by request of %s", parv[0]);
+ server_reboot((!MyClient(sptr) ? (parc > 2 ? parv[3] : "No reason")
+ : (parc > 1 ? parv[2] : "No reason")));
+ return 0;
+}
+
+/*
+** m_trace
+** parv[0] = sender prefix
+** parv[1] = servername
+*/
+int m_trace(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ Reg1 int i;
+ Reg2 aClient *acptr, *acptr2;
+ aClass *cltmp;
+ char *tname;
+ int doall, link_s[MAXCONNECTIONS], link_u[MAXCONNECTIONS];
+ int cnt = 0, wilds, dow;
+ time_t now;
+
+ if (check_registered(sptr))
+ return 0;
+
+ if (parc > 2)
+ if (hunt_server(cptr, sptr, ":%s TRACE %s :%s",
+ 2, parc, parv))
+ return 0;
+
+ if (parc > 1)
+ tname = parv[1];
+ else
+ tname = me.name;
+
+ if(!IsOper(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+
+ switch (hunt_server(cptr, sptr, ":%s TRACE :%s", 1, parc, parv))
+ {
+ case HUNTED_PASS: /* note: gets here only if parv[1] exists */
+ {
+ aClient *ac2ptr;
+
+ ac2ptr = next_client(client, tname);
+ sendto_one(sptr, rpl_str(RPL_TRACELINK), me.name, parv[0],
+ version, debugmode, tname, ac2ptr->from->name);
+ return 0;
+ }
+ case HUNTED_ISME:
+ break;
+ default:
+ return 0;
+ }
+
+ doall = (parv[1] && (parc > 1)) ? !match(tname, me.name): TRUE;
+ wilds = !parv[1] || index(tname, '*') || index(tname, '?');
+ dow = wilds || doall;
+
+#ifndef _WIN32
+ for (i = 0; i < MAXCONNECTIONS; i++)
+ link_s[i] = 0, link_u[i] = 0;
+#else
+ bzero(link_s, sizeof(link_s));
+ bzero(link_u, sizeof(link_u));
+#endif
+
+ if (doall)
+ for (acptr = client; acptr; acptr = acptr->next)
+#ifdef SHOW_INVISIBLE_LUSERS
+ if (IsPerson(acptr))
+ link_u[acptr->from->fd]++;
+#else
+ if (IsPerson(acptr) &&
+ (!IsInvisible(acptr) || IsOper(sptr)))
+ link_u[acptr->from->fd]++;
+#endif
+ else if (IsServer(acptr))
+ link_s[acptr->from->fd]++;
+
+ /* report all direct connections */
+
+ now = TStime();
+ for (i = 0; i <= highest_fd; i++)
+ {
+ char *name;
+ int class;
+
+ if (!(acptr = local[i])) /* Local Connection? */
+ continue;
+/* More bits of code to allow oers to see all users on remote traces
+ * if (IsInvisible(acptr) && dow &&
+ * if (dow &&
+ * !(MyConnect(sptr) && IsOper(sptr)) && */
+ if (!IsOper(sptr) &&
+ !IsAnOper(acptr) && (acptr != sptr))
+ continue;
+ if (!doall && wilds && match(tname, acptr->name))
+ continue;
+ if (!dow && mycmp(tname, acptr->name))
+ continue;
+ name = get_client_name(acptr,FALSE);
+ class = get_client_class(acptr);
+
+ switch(acptr->status)
+ {
+ case STAT_CONNECTING:
+ sendto_one(sptr, rpl_str(RPL_TRACECONNECTING), me.name,
+ parv[0], class, name);
+ cnt++;
+ break;
+ case STAT_HANDSHAKE:
+ sendto_one(sptr, rpl_str(RPL_TRACEHANDSHAKE), me.name,
+ parv[0], class, name);
+ cnt++;
+ break;
+ case STAT_ME:
+ break;
+ case STAT_UNKNOWN:
+ sendto_one(sptr, rpl_str(RPL_TRACEUNKNOWN),
+ me.name, parv[0], class, name);
+ cnt++;
+ break;
+ case STAT_CLIENT:
+ /* Only opers see users if there is a wildcard
+ * but anyone can see all the opers.
+ */
+/* if (IsOper(sptr) &&
+ * Allow opers to see invisible users on a remote trace or wildcard
+ * search ... sure as hell helps to find clonebots. --Russell
+ * (MyClient(sptr) || !(dow && IsInvisible(acptr)))
+ * || !dow || IsAnOper(acptr)) */
+ if (IsOper(sptr) ||
+ (IsAnOper(acptr) && !IsInvisible(acptr)))
+ {
+ if (IsAnOper(acptr))
+ sendto_one(sptr,
+ rpl_str(RPL_TRACEOPERATOR),
+ me.name,
+ parv[0], class, acptr->name, IsHidden(acptr) ? acptr->user->virthost : acptr->user->realhost,
+ now - acptr->lasttime);
+ else
+ sendto_one(sptr,rpl_str(RPL_TRACEUSER),
+ me.name, parv[0],
+ class, acptr->name, acptr->user->realhost,
+ now - acptr->lasttime);
+ cnt++;
+ }
+ break;
+ case STAT_SERVER:
+ if (acptr->serv->user)
+ sendto_one(sptr, rpl_str(RPL_TRACESERVER),
+ me.name, parv[0], class, link_s[i],
+ link_u[i], name, acptr->serv->by,
+ acptr->serv->user->username,
+ acptr->serv->user->realhost,
+ now - acptr->lasttime);
+ else
+ sendto_one(sptr, rpl_str(RPL_TRACESERVER),
+ me.name, parv[0], class, link_s[i],
+ link_u[i], name, *(acptr->serv->by) ?
+ acptr->serv->by : "*", "*", me.name,
+ now - acptr->lasttime);
+ cnt++;
+ break;
+ case STAT_SERVICE:
+ sendto_one(sptr, rpl_str(RPL_TRACESERVICE),
+ me.name, parv[0], class, name);
+ cnt++;
+ break;
+ case STAT_LOG:
+ sendto_one(sptr, rpl_str(RPL_TRACELOG), me.name,
+ parv[0], LOGFILE, acptr->port);
+ cnt++;
+ break;
+ default: /* ...we actually shouldn't come here... --msa */
+ sendto_one(sptr, rpl_str(RPL_TRACENEWTYPE), me.name,
+ parv[0], name);
+ cnt++;
+ break;
+ }
+ }
+ /*
+ * Add these lines to summarize the above which can get rather long
+ * and messy when done remotely - Avalon
+ */
+ if (!IsAnOper(sptr) || !cnt)
+ {
+ if (cnt)
+ return 0;
+ /* let the user have some idea that its at the end of the
+ * trace
+ */
+ sendto_one(sptr, rpl_str(RPL_TRACESERVER),
+ me.name, parv[0], 0, link_s[me.fd],
+ link_u[me.fd], me.name, "*", "*", me.name);
+ return 0;
+ }
+ for (cltmp = FirstClass(); doall && cltmp; cltmp = NextClass(cltmp))
+ if (Links(cltmp) > 0)
+ sendto_one(sptr, rpl_str(RPL_TRACECLASS), me.name,
+ parv[0], Class(cltmp), Links(cltmp));
+ return 0;
+ }
+/*
+** m_motd
+** parv[0] = sender prefix
+** parv[1] = servername
+** Modified for T:Lines by Stskeeps
+*/
+int m_motd(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ int fd, nr;
+ char line[80];
+ Reg1 char *tmp;
+ struct stat sb;
+ struct tm *tm;
+ aConfItem *motdconf;
+ int svsnofile = 0;
+ if (check_registered(sptr))
+ return 0;
+
+ if (hunt_server(cptr, sptr, ":%s MOTD :%s", 1,parc,parv)!=HUNTED_ISME)
+ return 0;
+ /*
+ * stop NFS hangs...most systems should be able to open a file in
+ * 3 seconds. -avalon (curtesy of wumpus)
+ */
+/*
+ Remote. - Should this be replaced by a
+ find_conf_host(conf, "Remote", CONF_TLINE) ?
+ -Sts
+*/
+ if (!MyConnect(sptr))
+#ifndef TLINE_Remote
+ fd = open(MOTD, O_RDONLY);
+#else
+ {
+ motdconf = find_tline("Remote");
+ if (motdconf == NULL) /* no match found*/
+ fd = open(MOTD, O_RDONLY);
+ else {
+ fd = open(motdconf->passwd, O_RDONLY);
+ if (fd == -1)
+ {
+ /* Actually there is a T:Line but not a MOTD.. */
+ /* I choose to use default MOTD instead */
+#ifndef TLINE_REPORT_MISSING
+ fd = open(MOTD, O_RDONLY);
+#endif
+ }
+ }
+ }
+#endif
+ else {
+ motdconf = (aConfItem *) find_tline((char *)sptr->user->realhost);
+ if (motdconf == NULL) /* no match found*/
+ fd = open(MOTD, O_RDONLY);
+ else {
+ fd = open((char *)motdconf->passwd, O_RDONLY);
+ if (fd == -1)
+ {
+ /* Actually there is a T:Line but not a MOTD.. */
+ /* I choose to use default MOTD instead */
+#ifndef TLINE_REPORT_MISSING
+ fd = open(MOTD, O_RDONLY);
+#endif
+ }
+ }
+ }
+ if (fd == -1)
+ {
+ sendto_one(sptr, err_str(ERR_NOMOTD), me.name, parv[0]);
+ svsnofile = 1;
+ goto svsmotd;
+ }
+ (void)fstat(fd, &sb);
+ sendto_one(sptr, rpl_str(RPL_MOTDSTART), me.name, parv[0], me.name);
+ tm = localtime(&sb.st_mtime);
+ sendto_one(sptr, ":%s %d %s :- %d/%d/%d %d:%02d", me.name, RPL_MOTD,
+ parv[0], tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year,
+ tm->tm_hour, tm->tm_min);
+ (void)dgets(-1, NULL, 0); /* make sure buffer is at empty pos */
+ while ((nr=dgets(fd, line, sizeof(line)-1)) > 0)
+ {
+ line[nr]='\0';
+ if ((tmp = (char *)index(line,'\n')))
+ *tmp = '\0';
+ if ((tmp = (char *)index(line,'\r')))
+ *tmp = '\0';
+ sendto_one(sptr, rpl_str(RPL_MOTD), me.name, parv[0], line);
+ }
+ (void)dgets(-1, NULL, 0); /* make sure buffer is at empty pos */
+ (void)close(fd);
+svsmotd:
+ /* SVSMOTD */
+ if ((fd = open(VPATH, O_RDONLY)) == -1) {
+ }
+ else
+ {
+ (void)dgets(-1, NULL, 0); /* make sure buffer is at empty pos */
+ while ((nr=dgets(fd, line, sizeof(line)-1)) > 0)
+ {
+ line[nr]='\0';
+ if ((tmp = (char *)index(line,'\n')))
+ *tmp = '\0';
+ if ((tmp = (char *)index(line,'\r')))
+ *tmp = '\0';
+ sendto_one(sptr, rpl_str(RPL_MOTD), me.name, parv[0], line);
+ }
+ (void)dgets(-1, NULL, 0); /* make sure buffer is at empty pos */
+ (void)close(fd);
+
+ }
+ if (svsnofile==0)
+ sendto_one(sptr, rpl_str(RPL_ENDOFMOTD), me.name, parv[0]);
+
+ return 0;
+ }
+/*
+** m_opermotd
+** parv[0] = sender prefix
+** parv[1] = servername
+*/
+int m_opermotd(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ int fd, nr;
+ char line[80];
+ Reg1 char *tmp;
+ struct stat sb;
+ struct tm *tm;
+
+ if (check_registered(sptr))
+ return 0;
+
+ if (!MyConnect(sptr))
+ return 0;
+ if (!IsAnOper(sptr))
+ return 0;
+ /*
+ * stop NFS hangs...most systems should be able to open a file in
+ * 3 seconds. -avalon (curtesy of wumpus)
+ */
+
+ fd = open(OPATH, O_RDONLY);
+ if (fd == -1)
+ {
+ sendto_one(sptr, err_str(ERR_NOOPERMOTD), me.name, parv[0]);
+ return 0;
+ }
+ (void)fstat(fd, &sb);
+ sendto_one(sptr, rpl_str(RPL_MOTDSTART), me.name, parv[0], me.name);
+ tm = localtime(&sb.st_mtime);
+ sendto_one(sptr, ":%s %d %s :- %d/%d/%d %d:%02d", me.name, RPL_MOTD,
+ parv[0], tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year,
+ tm->tm_hour, tm->tm_min);
+ sendto_one(sptr, rpl_str(RPL_MOTD), me.name, parv[0], "\2IRC Operator Message of the Day\2");
+ (void)dgets(-1, NULL, 0); /* make sure buffer is at empty pos */
+ while ((nr=dgets(fd, line, sizeof(line)-1)) > 0)
+ {
+ line[nr]='\0';
+ if ((tmp = (char *)index(line,'\n')))
+ *tmp = '\0';
+ if ((tmp = (char *)index(line,'\r')))
+ *tmp = '\0';
+ sendto_one(sptr, rpl_str(RPL_MOTD), me.name, parv[0], line);
+ }
+ (void)dgets(-1, NULL, 0); /* make sure buffer is at empty pos */
+ sendto_one(sptr, rpl_str(RPL_ENDOFMOTD), me.name, parv[0]);
+ (void)close(fd);
+ return 0;
+ }
+
+/*
+** m_botmotd
+** same as motd but is for bot specific rules, reads from bot.motd
+** cloned from the origional m_motd in dream forge -- codemastr
+** parv[0] = sender prefix
+** parv[1] = servername
+*/
+int m_botmotd(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ int fd, nr;
+ char line[80];
+ Reg1 char *tmp;
+ struct stat sb;
+ struct tm *tm;
+
+ if (check_registered(sptr))
+ return 0;
+
+ if (hunt_server(cptr, sptr, ":%s BOTMOTD :%s", 1,parc,parv)!=HUNTED_ISME)
+ return 0;
+ /*
+ * stop NFS hangs...most systems should be able to open a file in
+ * 3 seconds. -avalon (curtesy of wumpus)
+ */
+ fd = open("bot.motd", O_RDONLY);
+ if (fd == -1)
+ {
+ sendto_one(sptr, ":%s NOTICE AUTH :BOTMOTD File not found", me.name);
+ return 0;
+ }
+ (void)fstat(fd, &sb);
+ sendto_one(sptr, ":%s NOTICE AUTH :- %s Bot Message of the Day - ", me.name, me.name);
+ tm = localtime(&sb.st_mtime);
+ sendto_one(sptr, ":%s NOTICE AUTH :- %d/%d/%d %d:%02d", me.name, tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year,
+ tm->tm_hour, tm->tm_min);
+
+ (void)dgets(-1, NULL, 0); /* make sure buffer is at empty pos */
+ while ((nr=dgets(fd, line, sizeof(line)-1)) > 0)
+ {
+ line[nr]='\0';
+ if ((tmp = (char *)index(line,'\n')))
+ *tmp = '\0';
+ if ((tmp = (char *)index(line,'\r')))
+ *tmp = '\0';
+ sendto_one(sptr, ":%s NOTICE AUTH :- %s", me.name, line);
+ }
+ (void)dgets(-1, NULL, 0); /* make sure buffer is at empty pos */
+ sendto_one(sptr, ":%s NOTICE AUTH :End of /BOTMOTD command.", me.name);
+ (void)close(fd);
+ return 0;
+ }
+
+
+/*
+** m_rules
+** parv[0] = sender prefix
+** parv[1] = servername
+** Modified for T:Lines by Codemastr (cloned from m_motd)
+** Included in unrealircd by stskeeps
+*/
+int m_rules(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ int fd, nr;
+ char line[80];
+ Reg1 char *tmp;
+ struct stat sb;
+ struct tm *tm;
+ aConfItem *rulesconf;
+
+ if (check_registered(sptr))
+ return 0;
+
+ if (hunt_server(cptr, sptr, ":%s RULES :%s", 1,parc,parv)!=HUNTED_ISME)
+ return 0;
+ /*
+ * stop NFS hangs...most systems should be able to open a file in
+ * 3 seconds. -avalon (curtesy of wumpus)
+ */
+/*
+ Remote. - Should this be replaced by a
+ find_conf_host(conf, "Remote", CONF_TLINE) ?
+ -Sts
+*/
+ if (!MyConnect(sptr))
+#ifndef TLINE_Remote
+ fd = open(RPATH, O_RDONLY);
+#else
+ {
+ rulesconf = (aConfItem *) find_tline("Remote");
+ if (rulesconf == NULL) /* no match found*/
+ fd = open(RPATH, O_RDONLY);
+ else {
+ fd = open(rulesconf->name, O_RDONLY);
+ if (fd == -1)
+ {
+ /* Actually there is a T:Line but not a MOTD.. */
+ /* I choose to use default MOTD instead */
+#ifndef TLINE_REPORT_MISSING
+ fd = open(RPATH, O_RDONLY);
+#endif
+ }
+ }
+ }
+#endif
+ else {
+ rulesconf = (aConfItem *) find_tline(sptr->user->realhost);
+ if (rulesconf == NULL) /* no match found*/
+ fd = open(RPATH, O_RDONLY);
+ else {
+ fd = open((char *)rulesconf->name, O_RDONLY);
+ if (fd == -1)
+ {
+ /* Actually there is a T:Line but not a MOTD.. */
+ /* I choose to use default MOTD instead */
+#ifndef TLINE_REPORT_MISSING
+ fd = open(RPATH, O_RDONLY);
+#endif
+ }
+ }
+ }
+ if (fd == -1)
+ {
+ sendto_one(sptr, err_str(ERR_NORULES), me.name, parv[0]);
+ return 0;
+ }
+ (void)fstat(fd, &sb);
+ sendto_one(sptr, rpl_str(RPL_RULESSTART), me.name, parv[0], me.name);
+ tm = localtime(&sb.st_mtime);
+ sendto_one(sptr, ":%s %d %s :- %d/%d/%d %d:%02d", me.name, RPL_RULES,
+ parv[0], tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year,
+ tm->tm_hour, tm->tm_min);
+ (void)dgets(-1, NULL, 0); /* make sure buffer is at empty pos */
+ while ((nr=dgets(fd, line, sizeof(line)-1)) > 0)
+ {
+ line[nr]='\0';
+ if ((tmp = (char *)index(line,'\n')))
+ *tmp = '\0';
+ if ((tmp = (char *)index(line,'\r')))
+ *tmp = '\0';
+ sendto_one(sptr, rpl_str(RPL_RULES), me.name, parv[0], line);
+ }
+ (void)dgets(-1, NULL, 0); /* make sure buffer is at empty pos */
+ (void)close(fd);
+ /* SVSMOTD */
+#ifndef SVSRULES
+ if ((fd = open(VPATH, O_RDONLY)) == -1) {
+ }
+ else
+ {
+ (void)dgets(-1, NULL, 0); /* make sure buffer is at empty pos */
+ while ((nr=dgets(fd, line, sizeof(line)-1)) > 0)
+ {
+ line[nr]='\0';
+ if ((tmp = (char *)index(line,'\n')))
+ *tmp = '\0';
+ if ((tmp = (char *)index(line,'\r')))
+ *tmp = '\0';
+ sendto_one(sptr, rpl_str(RPL_RULES), me.name, parv[0], line);
+ }
+ (void)dgets(-1, NULL, 0); /* make sure buffer is at empty pos */
+ (void)close(fd);
+
+ }
+#endif
+ sendto_one(sptr, rpl_str(RPL_ENDOFRULES), me.name, parv[0]);
+
+ return 0;
+ }
+
+/*
+** m_close - added by Darren Reed Jul 13 1992.
+*/
+int m_close(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ Reg1 aClient *acptr;
+ Reg2 int i;
+ int closed = 0;
+
+ if (check_registered(sptr))
+ return 0;
+
+ if (!MyOper(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+
+ for (i = highest_fd; i; i--)
+ {
+ if (!(acptr = local[i]))
+ continue;
+ if (!IsUnknown(acptr) && !IsConnecting(acptr) &&
+ !IsHandshake(acptr))
+ continue;
+ sendto_one(sptr, rpl_str(RPL_CLOSING), me.name, parv[0],
+ get_client_name(acptr, TRUE), acptr->status);
+ (void)exit_client(acptr, acptr, acptr, "Oper Closing");
+ closed++;
+ }
+ sendto_one(sptr, rpl_str(RPL_CLOSEEND), me.name, parv[0], closed);
+ sendto_ops("%s!%s@%s closed %d unknown connections", sptr->name, sptr->user->username, sptr->user->realhost, closed);
+
+ return 0;
+}
+
+/* m_die, this terminates the server, and it intentionally does not
+ * have a reason. If you use it you should first do a GLOBOPS and
+ * then a server notice to let everyone know what is going down...
+ */
+int m_die(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ Reg1 aClient *acptr;
+ Reg2 int i;
+ char *pass = NULL;
+
+ if (check_registered(sptr))
+ return 0;
+
+ if (!MyClient(sptr) || !OPCanDie(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+
+ if ((pass = find_diepass())) /* See if we have and DIE/RESTART password */
+ {
+ if (parc < 2) /* And if so, require a password :) */
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "DIE");
+ return 0;
+ }
+
+ if (strcmp(pass, parv[1]))
+ {
+ sendto_one(sptr, err_str(ERR_PASSWDMISMATCH), me.name, parv[0]);
+ return 0;
+ }
+ }
+
+ /* Let the +s know what is going on */
+ sendto_ops("Server Terminating by request of %s", parv[0]);
+
+ for (i = 0; i <= highest_fd; i++)
+ {
+ if (!(acptr = local[i]))
+ continue;
+ if (IsClient(acptr))
+ sendto_one(acptr,
+ ":%s NOTICE %s :Server Terminating. %s",
+ me.name, acptr->name,
+ get_client_name(sptr, TRUE));
+ else if (IsServer(acptr))
+ sendto_one(acptr, ":%s ERROR :Terminated by %s",
+ me.name, get_client_name(sptr, TRUE));
+ }
+ (void)s_die();
+ return 0;
+}
+
+char servername[128][128];
+int server_usercount[128];
+int numservers=0;
+
+/*
+ * New /MAP format -Potvin
+ * dump_map function.
+ */
+void dump_map(cptr, server, mask, prompt_length, length)
+aClient *cptr, *server;
+char *mask;
+register int prompt_length;
+int length;
+{
+ static char prompt[64];
+ register char *p = &prompt[prompt_length];
+ register int cnt = 0, local = 0;
+ aClient *acptr;
+
+ *p='\0';
+
+ if (prompt_length > 60)
+ sendto_one(cptr, rpl_str(RPL_MAPMORE), me.name, cptr->name, prompt, server->name);
+ else
+ {
+ for (acptr = client; acptr; acptr = acptr->next)
+ {
+ if (IsPerson(acptr))
+ {
+ ++cnt; /* == */
+ if (!strcmp(acptr->user->server, server->name)) ++local;
+ }
+ }
+
+ sendto_one(cptr, rpl_str(RPL_MAP), me.name, cptr->name, prompt, length, server->name, local, (local*100)/cnt );
+ cnt = 0;
+ }
+
+ if (prompt_length > 0)
+ {
+ p[-1] = ' ';
+ if (p[-2] == '`') p[-2] = ' ';
+ }
+ if (prompt_length > 60) return;
+
+ strcpy(p, "|-");
+
+
+ for (acptr = client; acptr ; acptr = acptr->next)
+ {
+#ifdef HIDE_ULINES
+ if (IsServer(acptr) && IsULine(acptr, acptr) && !IsAnOper(cptr))
+ continue;
+#endif
+ if ( !IsServer (acptr) || strcmp(acptr->serv->up, server->name)) continue;
+
+ if ( match(mask, acptr->name) )
+ acptr->flags &= ~FLAGS_MAP;
+ else
+ {
+ acptr->flags |= FLAGS_MAP;
+ cnt++;
+ }
+ }
+
+ for (acptr = client; acptr ; acptr = acptr->next)
+ {
+ if ( ! (acptr->flags & FLAGS_MAP) || /* != */
+ !IsServer (acptr) || strcmp(acptr->serv->up, server->name)) continue;
+ if (--cnt == 0) *p = '`';
+ dump_map (cptr, acptr, mask, prompt_length+2, length-2);
+ }
+
+ if (prompt_length > 0) p[-1] = '-';
+}
+
+/*
+** New /MAP format. -Potvin
+** m_map (NEW)
+**
+** parv[0] = sender prefix
+** parv[1] = server mask
+**/
+int m_map(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+aClient *acptr;
+int longest=strlen(me.name);
+
+ if (check_registered(sptr))
+ return 0;
+
+ if (parc < 2)
+ parv[1]="*";
+ for (acptr = client; acptr; acptr = acptr->next)
+ if (IsServer(acptr) && ( strlen(acptr->name) + acptr->hopcount*2 ) > longest) longest = strlen(acptr->name) + acptr->hopcount*2;
+
+ if (longest > 60) longest = 60;
+ longest += 2;
+ dump_map(sptr, &me, "*", 0, longest);
+ sendto_one(sptr, rpl_str(RPL_MAPEND), me.name, parv[0]);
+
+ return 0;
+}
+
+
+#ifdef _WIN32
+/*
+ * Added to let the local console shutdown the server without just
+ * calling exit(-1), in Windows mode. -Cabal95
+ */
+int localdie(void)
+{
+ Reg1 aClient *acptr;
+ Reg2 int i;
+
+ for (i = 0; i <= highest_fd; i++)
+ {
+ if (!(acptr = local[i]))
+ continue;
+ if (IsClient(acptr))
+ sendto_one(acptr,
+ ":%s NOTICE %s :Server Terminated by local console",
+ me.name, acptr->name);
+ else if (IsServer(acptr))
+ sendto_one(acptr, ":%s ERROR :Terminated by local console",
+ me.name);
+ }
+ (void)s_die();
+ return 0;
+}
+#endif
--- /dev/null
+/* UltimateIRCd - Ultimate Internet Relay Chat Daemon, src/s_socks.c
+**
+** Written for UltimateIRCd by ShadowRealm Creations.
+** Copyright (C) 1997-1999 Infomedia 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef lint
+static char sccsid[] = "@(#)s_socks.c 1.0 28/9/98 (C) 1998 InfoMedia Inc.";
+#endif
+
+
+/* All these includes are copied from auth.c because we are
+ just doing something very similar */
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#include "res.h"
+#include "numeric.h"
+#include "version.h"
+#ifndef _WIN32
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#ifdef UNIXPORT
+# include <sys/un.h>
+#endif
+#if defined(__hpux)
+# include "inet.h"
+#endif
+#else
+#include <io.h>
+#endif
+#include <fcntl.h>
+#include "sock.h" /* If FD_ZERO isn't define up to this point, */
+ /* define it (BSD4.2 needs this) */
+#include "h.h"
+#ifdef SOCKSPORT
+
+static unsigned char socksid[12];
+
+#define HICHAR(s) (((unsigned short) s) >> 8)
+#define LOCHAR(s) (((unsigned short) s) & 0xFF)
+
+
+/* init_socks
+ * Set up socksid, simply.
+ */
+
+void init_socks(aClient *cptr)
+{
+ unsigned short sport = SOCKSPORT;
+ struct sockaddr_in sin;
+
+ socksid[0] = 4;
+ socksid[1] = 1;
+ socksid[2] = HICHAR(sport);
+ socksid[3] = LOCHAR(sport);
+ socksid[8] = 0;
+
+ if ((cptr->socksfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+ return;
+
+ set_non_blocking(cptr->socksfd, cptr);
+
+ sin.sin_addr.s_addr = INADDR_ANY;
+ sin.sin_port = htons(sport);
+ sin.sin_family = AF_INET;
+
+ if(bind(cptr->socksfd, (struct sockaddr *)&sin, sizeof(sin)))
+ {
+#ifdef _WIN32
+ closesocket(cptr->socksfd);
+#else
+ close(cptr->socksfd);
+#endif
+ cptr->socksfd = -1;
+ return;
+ }
+
+ listen(cptr->socksfd, LISTEN_SIZE);
+
+ /* Socks lietening port is now set up */
+ /* Similar to discard port */
+}
+
+/*
+ * start_socks
+ *
+ * attempts to connect to a socks server on port 1080 of the host.
+ * if the connect fails, the user passes the socks check
+ * otherwise, the connection is checked to see if it is a "secure"
+ * socks4+ server
+ */
+void start_socks(cptr)
+aClient *cptr;
+{
+ struct sockaddr_in sin;
+ int sinlen = sizeof(struct sockaddr_in);
+
+ if ((cptr->socksfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+ {
+ Debug((DEBUG_ERROR, "Unable to create socks socket for %s:%s",
+ get_client_name(cptr, TRUE),
+ strerror(get_sockerr(cptr))));
+ return;
+ }
+#ifndef _WIN32 /* this is here in s_auth.c, so I guess it breaks win */
+ if (cptr->socksfd >= (MAXCONNECTIONS - 3))
+ {
+ sendto_ops("Can't allocate fd for socks on %s",
+ get_client_name(cptr, TRUE));
+ close(cptr->socksfd);
+ cptr->socksfd = -1;
+ return;
+ }
+#endif
+ if (find_socksexcept((char *)inetntoa((char *) &cptr->ip)))
+ goto skip_socks;
+
+#ifdef SHOWCONNECTINFO
+#ifndef _WIN32
+ write(cptr->fd, REPORT_DO_SOCKS, R_do_socks);
+#else
+ send(cptr->fd, REPORT_DO_SOCKS, R_do_socks,0);
+#endif
+#endif
+
+ set_non_blocking(cptr->socksfd, cptr);
+
+ sin.sin_port = htons(1080);
+ sin.sin_family = AF_INET;
+ bcopy((char *)&cptr->ip, (char *)&sin.sin_addr,
+ sizeof(struct in_addr));
+
+ if (connect(cptr->socksfd, (struct sockaddr *)&sin,
+#ifndef _WIN32
+ sinlen) == -1 && errno != EINPROGRESS)
+#else
+ sinlen) == -1 && (WSAGetLastError() !=
+ WSAEINPROGRESS && WSAGetLastError() != WSAEWOULDBLOCK))
+#endif
+ {
+ /* we have no socks server! */
+#ifndef _WIN32
+ close(cptr->socksfd);
+#else
+ closesocket(cptr->socksfd);
+#endif
+ cptr->socksfd = -1;
+#ifdef SHOWCONNECTINFO
+#ifndef _WIN32
+ write(cptr->fd, REPORT_NO_SOCKS, R_no_socks);
+#else
+ send(cptr->fd, REPORT_NO_SOCKS, R_no_socks,0);
+#endif
+#endif
+ return;
+ }
+ cptr->flags |= (FLAGS_WRSOCKS|FLAGS_SOCKS);
+ if (cptr->socksfd > highest_fd)
+ highest_fd = cptr->socksfd;
+ return;
+
+skip_socks:
+#ifndef _WIN32
+ close(cptr->socksfd);
+#else
+ closesocket(cptr->socksfd);
+#endif
+ cptr->socksfd = -1;
+ cptr->socksfd = -1;
+#ifdef SHOWCONNECTINFO
+#ifndef _WIN32
+ write(cptr->fd, REPORT_NO_SOCKS, R_no_socks);
+#else
+ send(cptr->fd, REPORT_NO_SOCKS, R_no_socks,0);
+#endif
+#endif
+ return;
+}
+
+/*
+ * send_socksquery
+ *
+ * send the socks server a query to see if it's open.
+ */
+void send_socksquery(cptr)
+aClient *cptr;
+{
+ struct sockaddr_in sin;
+ int sinlen = sizeof(struct sockaddr_in);
+ unsigned char socksbuf[12];
+ unsigned long theip;
+
+ bcopy((char *)&socksid, (char *)&socksbuf, 9);
+
+ getsockname(cptr->fd, (struct sockaddr *)&sin, &sinlen);
+
+ theip = htonl(sin.sin_addr.s_addr);
+
+ socksbuf[4] = (theip >> 24);
+ socksbuf[5] = (theip >> 16) & 0xFF;
+ socksbuf[6] = (theip >> 8) & 0xFF;
+ socksbuf[7] = theip & 0xFF;
+
+ if (send(cptr->socksfd, socksbuf, 9, 0) != 9)
+ {
+#ifndef _WIN32
+ close(cptr->socksfd);
+#else
+ closesocket(cptr->socksfd);
+#endif
+ if (cptr->socksfd == highest_fd)
+ while (!local[highest_fd])
+ highest_fd--;
+ cptr->socksfd = -1;
+ cptr->flags &= ~FLAGS_SOCKS;
+#ifdef SHOWCONNECTINFO
+#ifndef _WIN32
+ write(cptr->fd, REPORT_NO_SOCKS, R_no_socks);
+#else
+ send(cptr->fd, REPORT_NO_SOCKS, R_no_socks,0);
+#endif
+#endif
+ }
+ cptr->flags &= ~FLAGS_WRSOCKS;
+ return;
+}
+
+/*
+ * read_socks
+ *
+ * process the socks reply.
+ */
+
+void read_socks(cptr)
+aClient *cptr;
+{
+ unsigned char socksbuf[12];
+ int len;
+
+ len = recv(cptr->socksfd, socksbuf, 9, 0);
+
+#ifndef _WIN32
+ (void)close(cptr->socksfd);
+#else
+ (void)closesocket(cptr->socksfd);
+#endif
+ if (cptr->socksfd == highest_fd)
+ while (!local[highest_fd])
+ highest_fd--;
+ cptr->socksfd = -1;
+ ClearSocks(cptr);
+
+ if(len < 4)
+ {
+#ifdef SHOWCONNECTINFO
+#ifndef _WIN32
+ write(cptr->fd, REPORT_NO_SOCKS, R_no_socks);
+#else
+ send(cptr->fd, REPORT_NO_SOCKS, R_no_socks,0);
+#endif
+#endif
+ return;
+ }
+
+ if(socksbuf[1] == 90)
+ {
+ cptr->flags |= FLAGS_GOTSOCKS;
+ return;
+ }
+
+#ifdef SHOWCONNECTINFO
+#ifndef _WIN32
+ write(cptr->fd, REPORT_GOOD_SOCKS, R_good_socks);
+#else
+ send(cptr->fd, REPORT_GOOD_SOCKS, R_good_socks,0);
+#endif
+#endif
+ return;
+}
+#endif
\ No newline at end of file
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, s_unreal.c
+ * (C) 1999 Carsten Munk (Techie/Stskeeps) <cmunk@toybox.flirt.org>
+ *
+ * See file AUTHORS in IRC package for additional names of
+ * the programmers.
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#include "numeric.h"
+#include "msg.h"
+#include "channel.h"
+#include "userload.h"
+#include "version.h"
+#include <time.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef _WIN32
+#include <utmp.h>
+#else
+#include <io.h>
+#endif
+#include <fcntl.h>
+#include "h.h"
+
+ID_CVS("$Id$");
+ID_Copyright("(C) Carsten Munk 1999");
+
+time_t TSoffset = 0;
+
+#ifndef NO_FDLIST
+extern float currentrate;
+extern float currentrate2;
+extern float highest_rate;
+extern float highest_rate2;
+extern int lifesux;
+#endif
+/*
+ m_sethost() added by Stskeeps (30/04/1999)
+ (modified at 15/05/1999) by Stskeeps | Potvin
+ :prefix SETHOST newhost
+ parv[0] - sender
+ parv[1] - newhost
+ D: this performs a mode +x function to set hostname
+ to whatever you want to (if you are IRCop) **efg**
+ Very experimental currently
+ A: Remember to see server_etabl ;)))))
+ *evil fucking grin*
+*/
+int m_sethost(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ char *vhost, *s;
+ int permit = 0; // 0 = opers(glob/locop) 1 = global oper 2 = not MY clients..
+ int donotice = 0; /* send out notices if local connect ( 0 = NOT 1 = yes ) */
+ int legalhost = 1; /* is legal characters? */
+
+ if (check_registered(sptr))
+ return 0;
+
+ if (!MyConnect(sptr))
+ goto have_permit1;
+ switch (permit) {
+ case 0: if (!IsAnOper(sptr)) {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ break;
+ case 1: if (!IsOper(sptr)) {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ break;
+ case 2: if (MyConnect(sptr)) {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ default:
+ sendto_ops_butone(IsServer(cptr) ? cptr : NULL, sptr,
+ ":%s WALLOPS :[SETHOST] Somebody fixing this corrupted server? !(0|1) !!!", me.name);
+ break;
+ }
+
+ have_permit1:
+ if (parc < 2)
+ vhost = NULL;
+ else
+ vhost = parv[1];
+
+ /* bad bad bad boys .. ;p */
+ if (vhost == NULL) {
+ if (MyConnect(sptr)) {
+ sendto_one(sptr, ":%s NOTICE %s :*** Syntax: /SetHost <new host>", me.name, parv[0]);
+ }
+ return;
+ }
+ /* uh uh .. too small */
+ if (strlen(parv[1]) < 1) {
+ if (MyConnect(sptr))
+ sendto_one(sptr, ":%s NOTICE %s :*** /SetHost Error: Atleast write SOMETHING that makes sense (':' string)",
+ me.name, sptr->name);
+ }
+ /* too large huh? */
+ if (strlen(parv[1]) > (HOSTLEN - 1) ) {
+ /* ignore us as well if we're not a child of 3k */
+ if (MyConnect(sptr))
+ sendto_one(sptr, ":%s NOTICE %s :*** /SetHost Error: Hostnames are limited to %i characters.", me.name, sptr->name, HOSTLEN);
+ return;
+ }
+
+ /* illegal?! */
+ for (s = vhost; *s; s++) {
+ if (!isallowed(*s)) {
+ legalhost = 0;
+ }
+ }
+
+ if (legalhost == 0) {
+ sendto_one(sptr, ":%s NOTICE %s :*** /SetHost Error: A hostname may contain a-z, A-Z, 0-9, '-' & '.' - Please only use them", me.name, parv[0]);
+ return 0;
+ }
+
+ /* hide it */
+ sptr->umodes |= UMODE_HIDE;
+ sptr->umodes |= UMODE_SETHOST;
+ /* get it in */
+ sprintf(sptr->user->virthost, "%s", vhost);
+ /* spread it out */
+ sendto_serv_butone(cptr, ":%s SETHOST %s", sptr->name, parv[1]);
+
+ if (MyConnect(sptr)) {
+ sendto_one(sptr, ":%s MODE %s :+xt", sptr->name, sptr->name);
+ sendto_one(sptr, ":%s NOTICE %s :Your nick!user@host-mask is now (%s!%s@%s) - To disable it type /mode %s -x", me.name, parv[0],
+ parv[0], sptr->user->username, vhost, parv[0]);
+ }
+ return 0;
+}
+
+/*
+ * m_chghost - 12/07/1999 (two months after I made SETIDENT) - Stskeeps
+ * :prefix CHGHOST <nick> <new hostname>
+ * parv[0] - sender
+ * parv[1] - nickname
+ * parv[2] - hostname
+ *
+*/
+
+int m_chghost(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ aClient *acptr;
+ char *s;
+ int legalhost = 1;
+
+ if (check_registered(sptr))
+ return 0;
+
+
+ if (MyClient(sptr))
+ if (!IsAnOper(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+
+ }
+
+ if (parc < 3) {
+ sendto_one(sptr, ":%s NOTICE %s :*** /ChgHost syntax is /ChgHost <nick> <newhost>", me.name, sptr->name);
+ return 0;
+ }
+
+ if (strlen(parv[2]) < 1) {
+ sendto_one(sptr, ":%s NOTICE %s :*** Write atleast something to change the host to!", me.name, sptr->name);
+ return 0;
+ }
+
+ if (strlen(parv[2]) > (HOSTLEN - 1)) {
+ sendto_one(sptr, ":%s NOTICE %s :*** ChgHost Error: Too long hostname!!", me.name, sptr->name);
+ }
+
+ /* illegal?! */
+ for (s = parv[2]; *s; s++) {
+ if (!isallowed(*s)) {
+ legalhost = 0;
+ }
+ }
+
+ if (legalhost == 0) {
+ sendto_one(sptr, ":%s NOTICE %s :*** /ChgHost Error: A hostname may contain a-z, A-Z, 0-9, '-' & '.' - Please only use them", me.name, parv[0]);
+ return 0;
+ }
+
+ if ((acptr = find_person(parv[1], NULL))) {
+ if (!IsULine(cptr, sptr)) {
+ sendto_umode(UMODE_EYES, "%s changed the virtual hostname of %s (%s@%s) to be %s",
+ sptr->name, acptr->name, acptr->user->username,
+ (acptr->umodes & UMODE_HIDE ? acptr->user->virthost : acptr->user->realhost),
+ parv[2]);
+ }
+ acptr->umodes |= UMODE_HIDE;
+ acptr->umodes |= UMODE_SETHOST;
+ sendto_serv_butone(cptr, ":%s CHGHOST %s %s",
+ sptr->name,
+ acptr->name,
+ parv[2]);
+ sprintf(acptr->user->virthost, "%s", parv[2]);
+ return 0;
+ }
+ else
+ {
+ sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, sptr->name, parv[1]);
+ return 0;
+ }
+ return 0;
+}
+
+/*
+ * m_chgident - 12/07/1999 (two months after I made SETIDENT) - Stskeeps
+ * :prefix CHGHOST <nick> <new identname>
+ * parv[0] - sender
+ * parv[1] - nickname
+ * parv[2] - identname
+ *
+*/
+
+int m_chgident(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ aClient *acptr;
+ char *s;
+ int legalident = 1;
+
+ if (check_registered(sptr))
+ return 0;
+
+
+ if (MyClient(sptr))
+ if (!IsAnOper(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+
+ }
+
+ if (parc < 3) {
+ sendto_one(sptr, ":%s NOTICE %s :*** /ChgIdent syntax is /ChgIdent <nick> <newident>", me.name, sptr->name);
+ return 0;
+ }
+
+ if (strlen(parv[2]) < 1) {
+ sendto_one(sptr, ":%s NOTICE %s :*** Write atleast something to change the ident to!", me.name, sptr->name);
+ return 0;
+ }
+
+ if (strlen(parv[2]) > (HOSTLEN - 1)) {
+ sendto_one(sptr, ":%s NOTICE %s :*** ChgIdent Error: Too long ident!!", me.name, sptr->name);
+ }
+
+ /* illegal?! */
+ for (s = parv[2]; *s; s++) {
+ if (!isallowed(*s)) {
+ legalident = 0;
+ }
+ }
+
+ if (legalident == 0) {
+ sendto_one(sptr, ":%s NOTICE %s :*** /ChgIdent Error: A ident may contain a-z, A-Z, 0-9, '-' & '.' - Please only use them", me.name, parv[0]);
+ return 0;
+ }
+
+ if ((acptr = find_person(parv[1], NULL))) {
+ if (!IsULine(cptr, sptr)) {
+ sendto_umode(UMODE_EYES, "%s changed the virtual ident of %s (%s@%s) to be %s",
+ sptr->name, acptr->name, acptr->user->username,
+ (acptr->umodes & UMODE_HIDE ? acptr->user->realhost : acptr->user->realhost),
+ parv[2]);
+ }
+ sendto_serv_butone(cptr, ":%s CHGIDENT %s %s",
+ sptr->name,
+ acptr->name,
+ parv[2]);
+ sprintf(acptr->user->username, "%s", parv[2]);
+ return 0;
+ }
+ else
+ {
+ sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, sptr->name, parv[1]);
+ return 0;
+ }
+ return 0;
+}
+
+/* m_setident - 12/05/1999 - Stskeeps
+ * :prefix SETIDENT newident
+ * parv[0] - sender
+ * parv[1] - newident
+ * D: This will set your username to be <x> (like (/setident Root))
+ * (if you are IRCop) **efg*
+ * Very experimental currently
+ * Cloning of m_sethost at some points - so same authors ;P
+*/
+
+int m_setident(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+
+ char *vident, *s;
+ int permit = 0; /* 0 = opers(glob/locop) 1 = global oper */
+ int donotice = 0; /* send out notices if local connect ( 0 = NOT 1 = yes )*/
+ int legalident = 1; /* is legal characters? */
+ if (check_registered(sptr))
+ return 0;
+ if (!MyConnect(sptr))
+ goto permit_2;
+ switch (permit) {
+ case 0: if (!IsAnOper(sptr)) {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ break;
+ case 1: if (!IsOper(sptr)) {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ break;
+ case 2: if (MyConnect(sptr)) {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ break;
+ default:
+ sendto_ops_butone(IsServer(cptr) ? cptr : NULL, sptr,
+ ":%s WALLOPS :[SETIDENT] Somebody fixing this corrupted server? !(0|1) !!!", me.name);
+ break;
+ }
+ permit_2:
+ if (parc < 2)
+ vident = NULL;
+ else
+ vident = parv[1];
+
+ /* bad bad bad boys .. ;p */
+ if (vident == NULL) {
+ if (MyConnect(sptr)) {
+ sendto_one(sptr, ":%s NOTICE %s :*** Syntax: /SetIdent <new host>", me.name, parv[0]);
+ }
+ return;
+ }
+ if (strlen(parv[1]) < 1) {
+ if (MyConnect(sptr))
+ sendto_one(sptr, ":%s NOTICE %s :*** /SetIdent Error: Atleast write SOMETHING that makes sense (':' string)",
+ me.name, sptr->name);
+ }
+
+ /* too large huh? */
+ if (strlen(vident) > ( USERLEN - 1)) {
+ /* ignore us as well if we're not a child of 3k */
+ if (MyConnect(sptr))
+ sendto_one(sptr, ":%s NOTICE %s :*** /SetIdent Error: Usernames are limited to %i characters.", me.name, sptr->name, USERLEN);
+ return;
+ }
+
+ /* illegal?! */
+ for (s = vident; *s; s++) {
+ if (!isallowed(*s)) {
+ legalident = 0;
+ }
+ if (*s == '~')
+ legalident = 1;
+
+ }
+
+ if (legalident == 0) {
+ sendto_one(sptr, ":%s NOTICE %s :*** /SetIdent Error: A username may contain a-z, A-Z, 0-9, '-', '~' & '.' - Please only use them", me.name, parv[0]);
+ return 0;
+ }
+
+ /* get it in */
+ sprintf(sptr->user->username, "%s", vident);
+ /* spread it out */
+ sendto_serv_butone(cptr, ":%s SETIDENT %s", sptr->name, parv[1]);
+
+ if (MyConnect(sptr)) {
+ sendto_one(sptr, ":%s NOTICE %s :Your nick!user@host-mask is now (%s!%s@%s) - To disable ident set change it manually by /setident'ing again", me.name, parv[0],
+ parv[0], sptr->user->username,
+ IsHidden(sptr) ? sptr->user->virthost : sptr->user->realhost);
+ }
+ return;
+}
+/* m_setname - 12/05/1999 - Stskeeps
+ * :prefix SETNAME :gecos
+ * parv[0] - sender
+ * parv[1] - gecos
+ * D: This will set your gecos to be <x> (like (/setname :The lonely wanderer))
+ yes it is experimental but anyways ;P
+ FREEDOM TO THE USERS! ;)
+*/
+
+int m_setname(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ if (parc < 2)
+ return;
+ if (strlen(parv[1]) > (REALLEN - 2)) {
+ if (MyConnect(sptr)) {
+ sendto_one(sptr, ":%s NOTICE %s :*** /SetName Error: \"Real names\" may maximum be %i characters of length", me.name, sptr->name, REALLEN);
+ }
+ return 0;
+ }
+
+ if (strlen(parv[1]) < 1) {
+ sendto_one(sptr, ":%s NOTICE %s :Couldn't change realname - Nothing in parameter",
+ me.name, sptr->name);
+ return 0;
+ }
+ else
+ sprintf(sptr->info, "%s", parv[1]);
+
+
+ sendto_serv_butone(&me, ":%s SETNAME :%s", parv[0], parv[1]);
+ if (MyConnect(sptr))
+ sendto_one(sptr, ":%s NOTICE %s :Your \"real name\" is now set to be %s - you have to set it manually to undo it", me.name, parv[0], parv[1]);
+ return 0;
+
+// sendto_serv_butone(cptr, ":%s SETNAME %s", parv[0], parv[1]);
+ return 0;
+}
+
+/* m_sdesc - 15/05/1999 - Stskeeps
+ * :prefix SDESC
+ * parv[0] - sender
+ * parv[1] - description
+ * D: Sets server info if you are Server Admin (ONLINE)
+*/
+
+int m_sdesc(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ if (IsCoAdmin(sptr))
+ goto sdescok;
+ /* ignoring */
+ if (!IsAdmin(sptr))
+ return;
+sdescok:
+
+ if (parc < 2)
+ return;
+ if (strlen(parv[1]) < 1) {
+ if (MyConnect(sptr)) {
+ sendto_one(sptr, ":%s NOTICE %s :*** Nothing to change to (SDESC)", me.name, sptr->name);
+ }
+ }
+ if (strlen(parv[1]) > (REALLEN - 1)) {
+ if (MyConnect(sptr)) {
+ sendto_one(sptr, ":%s NOTICE %s :*** /SDESC Error: \"Server info\" may maximum be %i characters of length", me.name, sptr->name, REALLEN);
+ }
+ return 0;
+ }
+
+ sprintf(sptr->srvptr->info, "%s", parv[1]);
+
+ sendto_serv_butone(&me, ":%s SDESC :%s", parv[0], parv[1]);
+
+ if (MyConnect(sptr))
+ sendto_one(sptr, ":%s NOTICE %s :Your \"server description\" is now set to be %s - you have to set it manually to undo it", me.name, parv[0], parv[1]);
+ return 0;
+
+ sendto_ops("Server description for %s is now '%s' changed by %s", sptr->srvptr->name, sptr->srvptr->info, parv[0]);
+}
+
+
+/*
+** m_admins (Admin chat only) -Potvin
+** parv[0] = sender prefix
+** parv[1] = message text
+*/
+int m_admins(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ char *message, *pv[4];
+
+ if (check_registered(sptr))
+ return 0;
+
+ message = parc > 1 ? parv[1] : NULL;
+
+ if (BadPtr(message))
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "ADCHAT");
+ return 0;
+ }
+#ifdef ADMINCHAT
+ if (MyClient(sptr) && !IsAdmin(sptr))
+#else
+ if (MyClient(sptr))
+#endif
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ sendto_serv_butone(IsServer(cptr) ? cptr : NULL,
+ ":%s ADCHAT :%s", parv[0], message);
+#ifdef ADMINCHAT
+ sendto_umode(UMODE_ADMIN, "*** AdminChat -- from %s: %s",
+ parv[0], message);
+ sendto_umode(UMODE_COADMIN, "*** AdminChat -- from %s: %s",
+ parv[0], message);
+#endif
+ return 0;
+ }
+/*
+** m_techat (Techadmin chat only) -Potvin (cloned by --sts)
+** parv[0] = sender prefix
+** parv[1] = message text
+*/
+int m_techat(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ char *message, *pv[4];
+
+ if (check_registered(sptr))
+ return 0;
+
+ message = parc > 1 ? parv[1] : NULL;
+
+ if (BadPtr(message))
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "TECHAT");
+ return 0;
+ }
+#ifdef ADMINCHAT
+ if (MyClient(sptr))
+ if (!(IsTechAdmin(sptr) || IsNetAdmin(sptr)))
+#else
+ if (MyClient(sptr))
+#endif
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ sendto_serv_butone(IsServer(cptr) ? cptr : NULL,
+ ":%s TECHAT :%s", parv[0], message);
+#ifdef ADMINCHAT
+ sendto_umode(UMODE_TECHADMIN, "*** Te-chat -- from %s: %s",
+ parv[0], message);
+// sendto_techat("from %s: %s", parv[0], message);
+// sendto_achat(1,"from %s: %s", parv[0], message);
+#endif
+ return 0;
+ }
+/*
+** m_nachat (netAdmin chat only) -Potvin - another sts cloning
+** parv[0] = sender prefix
+** parv[1] = message text
+*/
+int m_nachat(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ char *message, *pv[4];
+
+ if (check_registered(sptr))
+ return 0;
+
+ message = parc > 1 ? parv[1] : NULL;
+
+ if (BadPtr(message))
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "NACHAT");
+ return 0;
+ }
+#ifdef ADMINCHAT
+ if (MyClient(sptr))
+ if (!(IsNetAdmin(sptr) || IsTechAdmin(sptr)))
+#else
+ if (MyClient(sptr))
+#endif
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+
+ sendto_serv_butone(IsServer(cptr) ? cptr : NULL,
+ ":%s NACHAT :%s", parv[0], message);
+#ifdef ADMINCHAT
+ sendto_umode(UMODE_NETADMIN, "*** NetAdmin.Chat -- from %s: %s",
+ parv[0], message);
+ sendto_umode(UMODE_TECHADMIN, "*** NetAdmin.Chat -- from %s: %s",
+ parv[0], message);
+#endif
+ return 0;
+ }
+
+/* m_lag (lag measure) - Stskeeps
+ * parv[0] = prefix
+ * parv[1] = server to query
+*/
+
+int m_lag(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ int i;
+ if (check_registered_user(sptr))
+ return 0;
+
+ if (MyClient(sptr))
+ if (!IsAnOper(sptr)) {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+
+ if (parc < 2) {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "LAG");
+ return 0;
+ }
+ if (*parv[1] == '\0') {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "LAG");
+ return 0;
+ }
+ if (hunt_server(cptr, sptr, ":%s LAG :%s", 1, parc, parv) == HUNTED_NOSUCH) {
+ return 0;
+ }
+
+ sendto_one(sptr, ":%s NOTICE %s :Lag reply -- %s %s %li",
+ me.name, sptr->name,
+ me.name, parv[1],
+ TStime());
+
+ return 0;
+}
+
+/*
+ * m_dusers (dump users) (not passed on to other servers - Stskeeps
+ * /DUSERS <mask>
+ * parv[0] = prefix
+ * parv[1] = mask
+ * parv[2] = (optional) options
+*/
+#define DOPT_OPS 0x0001
+#define DOPT_BOTS 0x0002
+#define DOPT_MINE 0x0004
+
+int m_dusers(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ aClient *acptr;
+ long ccount = 0;
+ int opt = 0; /* 1 */
+ char *op;
+
+ if (!IsAnOper(sptr)) {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+/* Will now say it is not available in what ever version it is */
+ sendto_one(sptr, ":%s NOTICE %s :*** /Dusers is disabled in %s%s - sorry", me.name, sptr->name, BASE_VERSION, VERSIONONLY);
+ return 0;
+
+ if (parc < 2) {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "DUSERS");
+ return 0;
+ }
+
+ if (*parv[1] == '\0') {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "DUSERS");
+ return 0;
+ }
+
+ if (parc < 4) { /* we got options .. */
+ op = parv[2];
+ while (*op != '\0') {
+ switch (*op) {
+ case '+': break;
+ case 'o': opt |= DOPT_OPS; break;
+ case 'B': opt |= DOPT_BOTS; break;
+ case 'l': opt |= DOPT_MINE; break;
+ default: sendto_one(sptr, ":%s NOTICE %s :Unknown /DUSERS option flag (%c)", me.name, sptr->name, *op);
+ }
+ op++;
+ }
+ }
+ sendto_one(sptr, rpl_str(RPL_DUMPING), me.name, parv[0], parv[1]);
+
+ for (acptr = client; acptr; acptr = acptr->next) {
+ if (IsClient(acptr)) {
+ if (IsOper(acptr) && !(opt & DOPT_OPS))
+ continue;
+ if (!(acptr->umodes & UMODE_BOT) && (opt & DOPT_BOTS))
+ continue;
+ if (!MyConnect(acptr) && (opt & DOPT_MINE))
+ continue;
+
+ /* Complicated. */
+ sendto_one(sptr, rpl_str(RPL_DUMPRPL), me.name, parv[0],
+ acptr->name, acptr->user->username,
+ (IsHidden(acptr) ? acptr->user->virthost : acptr->user->realhost),
+ acptr->user->serv->name,
+ (IsOper(acptr) ? "o" : ""),
+ ((acptr->umodes & UMODE_BOT) ? "b" : ""),
+ (IsServices(acptr) ? "s" : ""),
+(!(IsOper(acptr) || (acptr->umodes & UMODE_BOT) || IsServices(acptr)) ? "n" : ""));
+ ccount++;
+ }
+ }
+ sendto_one(sptr, rpl_str(RPL_EODUMP), me.name, parv[0], ccount);
+}
+
+/*
+ Help.c interface for command line :)
+*/
+void unrealmanual(void) {
+ char *str;
+ int x = 0;
+
+ str = MyMalloc(1024);
+ printf("Starting UnrealIRCD Interactive help system\n");
+ printf("Use 'QUIT' as topic name to get out of help system\n");
+ x = parse_help(NULL, NULL, NULL);
+ if (x == 0) {
+ printf("*** Couldn't find main help topic!!\n");
+ return;
+ }
+ while (myncmp(str, "QUIT", 8)) {
+ printf("Topic?> ");
+ str = fgets(str, 1023, stdin);
+ printf("\n");
+ if (myncmp(str, "QUIT", 8))
+ x = parse_help(NULL, NULL, str);
+ if (x == 0) {
+ printf("*** Couldn't find help topic '%s'\n", str);
+ }
+ }
+ MyFree(str);
+}
+
+static char *militime(char *sec, char *usec)
+{
+ struct timeval tv;
+ static char timebuf[18];
+#ifndef _WIN32
+ gettimeofday(&tv, NULL);
+#else
+ /* win32 unreal cannot fix gettimeofday - therefore only 90% precise */
+ tv.tv_sec = TStime();
+ tv.tv_usec = 0;
+#endif
+ if (sec && usec)
+ sprintf(timebuf, "%ld",
+ (tv.tv_sec - atoi(sec)) * 1000 + (tv.tv_usec - atoi(usec)) / 1000);
+ else
+ sprintf(timebuf, "%ld %ld", tv.tv_sec, tv.tv_usec);
+
+ return timebuf;
+}
+
+aClient *find_match_server(char *mask)
+{
+ aClient *acptr;
+
+ if (BadPtr(mask))
+ return NULL;
+ for (acptr = client, collapse(mask); acptr; acptr = acptr->next)
+ {
+ if (!IsServer(acptr) && !IsMe(acptr))
+ continue;
+ if (!match(mask, acptr->name))
+ break;
+ continue;
+ }
+ return acptr;
+}
+
+/*
+ * m_rping -- by Run
+ *
+ * parv[0] = sender (sptr->name thus)
+ * if sender is a person: (traveling towards start server)
+ * parv[1] = pinged server[mask]
+ * parv[2] = start server (current target)
+ * parv[3] = optional remark
+ * if sender is a server: (traveling towards pinged server)
+ * parv[1] = pinged server (current target)
+ * parv[2] = original sender (person)
+ * parv[3] = start time in s
+ * parv[4] = start time in us
+ * parv[5] = the optional remark
+ */
+int m_rping(aClient *cptr, aClient *sptr, int parc, char *parv[])
+{
+ aClient *acptr;
+
+ if (!IsPrivileged(sptr))
+ return 0;
+
+ if (parc < (IsAnOper(sptr) ? (MyConnect(sptr) ? 2 : 3) : 6))
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "RPING");
+ return 0;
+ }
+ if (MyClient(sptr))
+ {
+ if (parc == 2)
+ parv[parc++] = me.name;
+ else if (!(acptr = find_match_server(parv[2])))
+ {
+ parv[3] = parv[2];
+ parv[2] = me.name;
+ parc++;
+ }
+ else
+ parv[2] = acptr->name;
+ if (parc == 3)
+ parv[parc++] = "<No client start time>";
+ }
+
+ if (IsAnOper(sptr))
+ {
+ if (hunt_server(cptr, sptr, ":%s RPING %s %s :%s", 2, parc, parv) != HUNTED_ISME)
+ return 0;
+ if (!(acptr = find_match_server(parv[1])) || !IsServer(acptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOSUCHSERVER), me.name, parv[0], parv[1]);
+ return 0;
+ }
+ sendto_one(acptr, ":%s RPING %s %s %s :%s",
+ me.name, acptr->name, sptr->name, militime(NULL, NULL), parv[3]);
+ }
+ else
+ {
+ if (hunt_server(cptr, sptr, ":%s RPING %s %s %s %s :%s", 1, parc, parv) != HUNTED_ISME)
+ return 0;
+ sendto_one(cptr, ":%s RPONG %s %s %s %s :%s", me.name, parv[0],
+ parv[2], parv[3], parv[4], parv[5]);
+ }
+ return 0;
+}
+
+/*
+ * m_rpong -- by Run too :)
+ *
+ * parv[0] = sender prefix
+ * parv[1] = from pinged server: start server; from start server: sender
+ * parv[2] = from pinged server: sender; from start server: pinged server
+ * parv[3] = pingtime in ms
+ * parv[4] = client info (for instance start time)
+ */
+int m_rpong(aClient *cptr, aClient *sptr, int parc, char *parv[])
+{
+ aClient *acptr;
+
+ if (!IsServer(sptr))
+ return 0;
+
+ if (parc < 5)
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "RPING");
+ return 0;
+ }
+
+ /* rping blowbug */
+ if (!(acptr = find_client(parv[1], (aClient *)NULL)))
+ return 0;
+
+
+ if (!IsMe(acptr))
+ {
+ if (IsServer(acptr) && parc > 5)
+ {
+ sendto_one(acptr, ":%s RPONG %s %s %s %s :%s",
+ parv[0], parv[1], parv[2], parv[3], parv[4], parv[5]);
+ return 0;
+ }
+ }
+ else
+ {
+ parv[1] = parv[2];
+ parv[2] = sptr->name;
+ parv[0] = me.name;
+ parv[3] = militime(parv[3], parv[4]);
+ parv[4] = parv[5];
+ if (!(acptr = find_person(parv[1], (aClient *)NULL)))
+ return 0; /* No bouncing between servers ! */
+ }
+
+ sendto_one(acptr, ":%s RPONG %s %s %s :%s",
+ parv[0], parv[1], parv[2], parv[3], parv[4]);
+ return 0;
+}
+/*
+ * m_swhois
+ * parv[1] = nickname
+ * parv[2] = new swhois
+ *
+*/
+
+int m_swhois(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ aClient *acptr;
+
+/* if (!IsServer(sptr) && !IsULine(cptr, sptr) && !(IsNetAdmin(sptr) || IsTechAdmin(sptr)))
+ {
+ return 0;
+ }*/
+ if (!IsServer(sptr) && !IsULine(cptr, sptr))
+ return 0;
+ if (parc < 3)
+ return 0;
+
+ acptr = find_person(parv[1], (aClient *) NULL);
+ if (!acptr)
+ return 0;
+
+ if (acptr->user->swhois)
+ MyFree(acptr->user->swhois);
+ acptr->user->swhois = MyMalloc(strlen(parv[2]) + 1);
+ sprintf(acptr->user->swhois, "%s", parv[2]);
+ sendto_serv_butone(cptr, ":%s SWHOIS %s :%s", sptr->name, parv[1], parv[2]);
+ return 0;
+}
+/*
+** m_sendumode - Stskeeps
+** parv[0] = sender prefix
+** parv[1] = target
+** parv[2] = message text
+** Pretty handy proc..
+** Servers can use this to f.x:
+** :server.unreal.net SENDUMODE F :Client connecting at server server.unreal.net port 4141 usw..
+** or for sending msgs to locops.. :P
+*/
+int m_sendumode(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ char *message, *pv[4];
+ char *p;
+ if (check_registered(sptr))
+ return 0;
+
+ message = parc > 2 ? parv[2] : NULL;
+
+ if (BadPtr(message))
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "SENDUMODE");
+ return 0;
+ }
+
+ if (!IsServer(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+
+ sendto_serv_butone(IsServer(cptr) ? cptr : NULL,
+ ":%s SMO %s :%s", parv[0], parv[1], message);
+
+
+ for (p = parv[1]; *p; p++)
+ {
+ switch (*p)
+ {
+ case 'e': sendto_umode(UMODE_EYES, "%s", parv[2]); break;
+ case 'F':
+ {
+ if (*parv[2] != 'C' && *(parv[2]+1) != 'l')
+ sendto_umode(UMODE_FCLIENT, "%s", parv[2]); break;
+ }
+ case 'o': sendto_umode(UMODE_OPER, "%s", parv[2]); break;
+ case 'O': sendto_umode(UMODE_LOCOP, "%s", parv[2]); break;
+ case 'h': sendto_umode(UMODE_HELPOP, "%s", parv[2]); break;
+ case 'N': sendto_umode(UMODE_NETADMIN|UMODE_TECHADMIN, "%s", parv[2]); break;
+ case 'A': sendto_umode(UMODE_ADMIN, "%s", parv[2]); break;
+ case '1': sendto_umode(UMODE_CODER, "%s", parv[2]); break;
+ case 'I': sendto_umode(UMODE_HIDING, "%s", parv[2]); break;
+ case 'w': sendto_umode(UMODE_WALLOP, "%s", parv[2]); break;
+ case 's': sendto_umode(UMODE_SERVNOTICE, "%s", parv[2]); break;
+ case 'T': sendto_umode(UMODE_TECHADMIN, "%s", parv[2]); break;
+ }
+ }
+ return 0;
+ }
+
+
+/*
+** m_tsctl - Stskeeps
+** parv[0] = sender prefix
+** parv[1] = command
+** parv[2] = options
+*/
+
+int m_tsctl(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ time_t timediff;
+
+ if (check_registered(sptr))
+ return 0;
+
+ if (!MyClient(sptr))
+ goto doit;
+ if (!IsAdmin(sptr) && !IsCoAdmin(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ doit:
+ if (parv[1])
+ {
+ if (*parv[1] == '\0' )
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "TSCTL");
+ return 0;
+ }
+
+ if (strcmp(parv[1], "offset")==0) {
+ if (!parv[3])
+ {
+ sendto_one(sptr, ":%s NOTICE %s :*** TSCTL OFFSET: /tsctl offset <+|-> <time>", me.name, sptr->name);
+ return 0;
+ }
+ if (*parv[2] == '\0' || *parv[3] == '\0')
+ {
+ sendto_one(sptr, ":%s NOTICE %s :*** TSCTL OFFSET: /tsctl offset <+|-> <time>", me.name, sptr->name);
+ return 0;
+ }
+ if (!(*parv[2] == '+' || *parv[2] == '-'))
+ {
+ sendto_one(sptr, ":%s NOTICE %s :*** TSCTL OFFSET: /tsctl offset <+|-> <time>", me.name, sptr->name);
+ return 0;
+
+ }
+
+ switch (*parv[2])
+ {
+ case '+' :
+ timediff = atol(parv[3]);
+ TSoffset = timediff;
+ sendto_ops("TS Control - %s set TStime() to be diffed +%li", sptr->name, timediff);
+ sendto_serv_butone(&me, ":%s GLOBOPS :TS Control - %s set TStime to be diffed +%li", me.name, sptr->name, timediff);
+ break;
+ case '-' :
+ timediff = atol(parv[3]);
+ TSoffset = -timediff;
+ sendto_ops("TS Control - %s set TStime() to be diffed -%li", sptr->name, timediff);
+ sendto_serv_butone(&me, ":%s GLOBOPS :TS Control - %s set TStime to be diffed -%li", me.name, sptr->name, timediff);
+ break;
+ }
+ return 0;
+ }
+ if (strcmp(parv[1], "time")==0)
+ {
+ sendto_one(sptr, ":%s NOTICE %s :*** TStime=%li time()=%li TSoffset=%li", me.name,
+ sptr->name, TStime(), time(NULL), TSoffset);
+ return 0;
+ }
+ if (strcmp(parv[1], "alltime")==0)
+ {
+ sendto_one(sptr, ":%s NOTICE %s :*** Server=%s TStime=%li time()=%li TSoffset=%li", me.name,
+ sptr->name, me.name, TStime(), time(NULL), TSoffset);
+ sendto_serv_butone(cptr, ":%s TSCTL alltime", sptr->name);
+ return 0;
+
+ }
+ if (strcmp(parv[1], "svstime")==0)
+ {
+ if (parc < 3 || *parv[3] == '\0')
+ {
+ return 0;
+ }
+ if (!IsULine(cptr, sptr))
+ {
+ return 0;
+ }
+
+ timediff = atol(parv[3]);
+ timediff = timediff - time(NULL);
+ TSoffset = timediff;
+ sendto_ops("TS Control - U:line set time to be %li (timediff: %li)", atol(parv[3]), timediff);
+ sendto_serv_butone(cptr, ":%s TSCTL svstime %li", sptr->name, atol(parv[3]));
+ return 0;
+ }
+ }
+}
+
+
+/*
+** m_svso - Stskeeps
+** parv[0] = sender prefix
+** parv[1] = nick
+** parv[2] = options
+*/
+
+int m_svso(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ aClient *acptr;
+ long fLag;
+
+ if (check_registered(sptr))
+ return 0;
+ if (!IsULine(cptr, sptr))
+ return 0;
+
+ if (parc < 3)
+ return 0;
+
+ if (!(acptr = find_client(parv[1], (aClient *)NULL)))
+ return 0;
+
+ if (!MyClient(acptr))
+ {
+ sendto_one(acptr, ":%s SVSO %s %s", parv[0], parv[1], parv[2]);
+ return 0;
+ }
+
+ if (*parv[2] == '-')
+ {
+ fLag = acptr->umodes;
+ acptr->umodes &= ~(UMODE_OPER|UMODE_LOCOP|UMODE_HELPOP|UMODE_SERVICES|UMODE_SADMIN|UMODE_ADMIN);
+ acptr->umodes &= ~(UMODE_NETADMIN|UMODE_TECHADMIN|UMODE_CLIENT|UMODE_FLOOD|UMODE_EYES|UMODE_CHATOP|UMODE_WHOIS);
+ acptr->umodes &= ~(UMODE_KIX|UMODE_FCLIENT|UMODE_HIDING|UMODE_AGENT|UMODE_CODER|UMODE_DEAF);
+ acptr->oflag = 0;
+ send_umode_out(acptr, acptr, fLag);
+ }
+}
+
+int m_shun(cptr, sptr, parc,parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+}
+
+int m_htm(cptr, sptr, parc,parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ if (!IsOper(sptr))
+ return 0;
+
+#ifndef NO_FDLIST
+ sendto_one(sptr, ":%s NOTICE %s :*** Current incoming rate: %0.2f kb/s", me.name, sptr->name, currentrate);
+ sendto_one(sptr, ":%s NOTICE %s :*** Current outgoing rate: %0.2f kb/s", me.name, sptr->name, currentrate2);
+ sendto_one(sptr, ":%s NOTICE %s :*** Highest incoming rate: %0.2f kb/s", me.name, sptr->name, highest_rate);
+ sendto_one(sptr, ":%s NOTICE %s :*** Highest outgoing rate: %0.2f kb/s", me.name, sptr->name, highest_rate2);
+ sendto_one(sptr, ":%s NOTICE %s :*** High traffic mode is currently \2%s\2", me.name, sptr->name, (lifesux ? "ON" : "OFF"));
+ sendto_one(sptr, ":%s NOTICE %s :*** HTM will be activated if incoming > %i kb/s", me.name, sptr->name, LOADRECV);
+#else
+ sendto_one(sptr, ":%s NOTICE %s :*** High traffic mode and fdlists are not enabled on this server", me.name, sptr->name);
+#endif
+}
+
+
--- /dev/null
+/*
+ * IRC - Internet Relay Chat, ircd/s_user.c (formerly ircd/s_msg.c)
+ * Copyright (C) 1990 Jarkko Oikarinen and
+ * University of Oulu, Computing Center
+ *
+ * See file AUTHORS in IRC package for additional names of
+ * the programmers.
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)s_user.c 2.74 2/8/94 (C) 1988 University of Oulu, \
+Computing Center and Jarkko Oikarinen";
+#endif
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#include "numeric.h"
+#include "msg.h"
+#include "channel.h"
+#include "userload.h"
+#include <time.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef _WIN32
+#include <utmp.h>
+#else
+#include <io.h>
+#endif
+#include <fcntl.h>
+#include "h.h"
+
+ID_CVS("$Id$");
+void send_umode_out PROTO((aClient*, aClient *, int));
+void send_umode_out_nickv2 PROTO((aClient*, aClient *, int));
+void send_svsmode_out PROTO((aClient*, aClient *, aClient *, int));
+void send_umode PROTO((aClient *, aClient *, int, int, char *));
+static is_silenced PROTO((aClient *, aClient *));
+/* static Link *is_banned PROTO((aClient *, aChannel *)); */
+
+int sendanyways = 0;
+int dontspread = 0;
+
+static char buf[BUFSIZE], buf2[BUFSIZE];
+static int user_modes[] = { UMODE_OPER, 'o',
+ UMODE_LOCOP, 'O',
+ UMODE_INVISIBLE, 'i',
+ UMODE_WALLOP, 'w',
+ UMODE_FAILOP, 'g',
+ UMODE_HELPOP, 'h',
+ UMODE_SERVNOTICE, 's',
+ UMODE_KILLS, 'k',
+ UMODE_SERVICES, 'S',
+ UMODE_SADMIN, 'a',
+ UMODE_HIDEOPER, 'H',
+ UMODE_ADMIN, 'A',
+ UMODE_NETADMIN, 'N',
+ UMODE_TECHADMIN, 'T',
+ UMODE_CLIENT, 'c',
+ UMODE_COADMIN, 'C',
+ UMODE_FLOOD, 'f',
+ UMODE_REGNICK, 'r',
+ UMODE_HIDE, 'x',
+ UMODE_EYES, 'e',
+ UMODE_CHATOP, 'b',
+ UMODE_WHOIS, 'W',
+ UMODE_KIX, 'q',
+ UMODE_BOT, 'B',
+ UMODE_FCLIENT, 'F',
+#ifndef OPER_NO_HIDING
+ UMODE_HIDING, 'I',
+#endif
+ UMODE_AGENT, 'Z',
+ UMODE_CODER, '1',
+ UMODE_DEAF, 'd',
+ UMODE_VICTIM, 'v',
+ UMODE_SETHOST, 't',
+ 0, 0 };
+
+/* annoying but tricky function.. */
+#define iNAH_host(x, y) strncpyzt((x)->user->virthost, (y), HOSTLEN); \
+ if (MyConnect(x)) \
+ sendto_serv_butone(&me, ":%s SETHOST %s", (x)->name, (x)->user->virthost); \
+ sptr->umodes |= UMODE_SETHOST
+
+
+/*
+** m_functions execute protocol messages on this server:
+**
+** cptr is always NON-NULL, pointing to a *LOCAL* client
+** structure (with an open socket connected!). This
+** identifies the physical socket where the message
+** originated (or which caused the m_function to be
+** executed--some m_functions may call others...).
+**
+** sptr is the source of the message, defined by the
+** prefix part of the message if present. If not
+** or prefix not found, then sptr==cptr.
+**
+** (!IsServer(cptr)) => (cptr == sptr), because
+** prefixes are taken *only* from servers...
+**
+** (IsServer(cptr))
+** (sptr == cptr) => the message didn't
+** have the prefix.
+**
+** (sptr != cptr && IsServer(sptr) means
+** the prefix specified servername. (?)
+**
+** (sptr != cptr && !IsServer(sptr) means
+** that message originated from a remote
+** user (not local).
+**
+** combining
+**
+** (!IsServer(sptr)) means that, sptr can safely
+** taken as defining the target structure of the
+** message in this server.
+**
+** *Always* true (if 'parse' and others are working correct):
+**
+** 1) sptr->from == cptr (note: cptr->from == cptr)
+**
+** 2) MyConnect(sptr) <=> sptr == cptr (e.g. sptr
+** *cannot* be a local connection, unless it's
+** actually cptr!). [MyConnect(x) should probably
+** be defined as (x == x->from) --msa ]
+**
+** parc number of variable parameter strings (if zero,
+** parv is allowed to be NULL)
+**
+** parv a NULL terminated list of parameter pointers,
+**
+** parv[0], sender (prefix string), if not present
+** this points to an empty string.
+** parv[1]...parv[parc-1]
+** pointers to additional parameters
+** parv[parc] == NULL, *always*
+**
+** note: it is guaranteed that parv[0]..parv[parc-1] are all
+** non-NULL pointers.
+*/
+
+#ifndef NO_FDLIST
+extern fdlist oper_fdlist;
+#endif
+
+/* Recoded to be alot more accurate
+ * not based on netgod's (net@lite.net)
+ * StripColors, but it was used as a
+ * reference and some of his code was
+ * used, all in all this is still a
+ * messy function, but it should be
+ * more accurate (and faster?)
+ * -- codemastr
+ */
+
+static char *StripColors(char *buffer)
+{
+static char tmp[512], out[512];
+register int i = 0, j = 0, hascomma = 0;
+
+/* If there isn't any color in the string, just return */
+if (!strchr(buffer, '\003'))
+return buffer;
+bzero((char *)out, sizeof(out));
+memcpy(tmp, buffer, 512);
+
+while (tmp[i])
+{
+ /* Color code found, so parse */
+ if (tmp[i] == '\003') {
+ hascomma = 0;
+
+ /* Increase it by 1 so we can see if it is valid */
+ i++;
+ /* It's fake, so continue */
+ if (!isdigit(tmp[i]))
+ continue;
+
+ while(isdigit(tmp[i]) || (isdigit(tmp[i-1]) && tmp[i] == ',' && isdigit(tmp[i+1]) && hascomma == 0))
+ {
+ if (tmp[i] == ',' && hascomma == 1)
+ break;
+
+ if (tmp[i] == ',' && hascomma == 0)
+ hascomma = 1;
+ i++;
+ }
+ continue;
+ }
+out[j] = tmp[i];
+i++;
+j++;
+ }
+return out;
+
+}
+
+char umodestring[512];
+
+void make_umodestr(void)
+{
+ char *p;
+ char *q;
+
+ Reg1 int flag;
+ Reg2 int *s;
+ Reg3 char *m;
+
+ m = umodestring;
+
+ for (s = user_modes; *s; s += 2)
+ {
+ *m++ = (char) (*(s + 1));
+ }
+
+ *m = '\0';
+}
+
+/*
+** next_client
+** Local function to find the next matching client. The search
+** can be continued from the specified client entry. Normal
+** usage loop is:
+**
+** for (x = client; x = next_client(x,mask); x = x->next)
+** HandleMatchingClient;
+**
+*/
+aClient *next_client(next, ch)
+Reg1 aClient *next; /* First client to check */
+Reg2 char *ch; /* search string (may include wilds) */
+{
+ Reg3 aClient *tmp = next;
+
+ next = find_client(ch, tmp);
+ if (tmp && tmp->prev == next)
+ return NULL;
+ if (next != tmp)
+ return next;
+ for ( ; next; next = next->next)
+ {
+ if (IsService(next))
+ continue;
+ if (!match(ch, next->name) || !match(next->name, ch))
+ break;
+ }
+ return next;
+}
+
+/*
+** hunt_server
+**
+** Do the basic thing in delivering the message (command)
+** across the relays to the specific server (server) for
+** actions.
+**
+** Note: The command is a format string and *MUST* be
+** of prefixed style (e.g. ":%s COMMAND %s ...").
+** Command can have only max 8 parameters.
+**
+** server parv[server] is the parameter identifying the
+** target server.
+**
+** *WARNING*
+** parv[server] is replaced with the pointer to the
+** real servername from the matched client (I'm lazy
+** now --msa).
+**
+** returns: (see #defines)
+*/
+int hunt_server(cptr, sptr, command, server, parc, parv)
+aClient *cptr, *sptr;
+char *command, *parv[];
+int server, parc;
+ {
+ aClient *acptr;
+
+ /*
+ ** Assume it's me, if no server
+ */
+ if (parc <= server || BadPtr(parv[server]) ||
+ match(me.name, parv[server]) == 0 ||
+ match(parv[server], me.name) == 0)
+ return (HUNTED_ISME);
+ /*
+ ** These are to pickup matches that would cause the following
+ ** message to go in the wrong direction while doing quick fast
+ ** non-matching lookups.
+ */
+ if ((acptr = find_client(parv[server], NULL)))
+ if (acptr->from == sptr->from && !MyConnect(acptr))
+ acptr = NULL;
+ if (!acptr && (acptr = find_server(parv[server], NULL)))
+ if (acptr->from == sptr->from && !MyConnect(acptr))
+ acptr = NULL;
+ if (!acptr)
+ for (acptr = client, (void)collapse(parv[server]);
+ (acptr = next_client(acptr, parv[server]));
+ acptr = acptr->next)
+ {
+ if (acptr->from == sptr->from && !MyConnect(acptr))
+ continue;
+ /*
+ * Fix to prevent looping in case the parameter for
+ * some reason happens to match someone from the from
+ * link --jto
+ */
+ if (IsRegistered(acptr) && (acptr != cptr))
+ break;
+ }
+ if (acptr)
+ {
+ if (IsMe(acptr) || MyClient(acptr))
+ return HUNTED_ISME;
+ if (match(acptr->name, parv[server]))
+ parv[server] = acptr->name;
+ sendto_one(acptr, command, parv[0],
+ parv[1], parv[2], parv[3], parv[4],
+ parv[5], parv[6], parv[7], parv[8]);
+ return(HUNTED_PASS);
+ }
+ sendto_one(sptr, err_str(ERR_NOSUCHSERVER), me.name,
+ parv[0], parv[server]);
+ return(HUNTED_NOSUCH);
+ }
+
+
+/*
+** check_for_target_limit
+**
+** Return Values:
+** True(1) == too many targets are addressed
+** False(0) == ok to send message
+**
+*/
+int check_for_target_limit(aClient *sptr, void *target, const char *name)
+{
+#ifndef _WIN32 /* This is not windows compatible */
+ register u_char *p;
+#ifndef LINUX_ALPHA
+ register u_int tmp = ((u_int)target & 0xffff00) >> 8;
+#else
+ register u_int tmp = ((u_long)target & 0xffff00) >> 8;
+#endif
+ u_char hash = (tmp * tmp) >> 12;
+
+ if(IsAnOper(sptr))
+ return 0;
+ if (sptr->targets[0] == hash)
+ return 0;
+
+ for (p = sptr->targets; p < &sptr->targets[MAXTARGETS - 1];)
+ if (*++p == hash) {
+ memmove(&sptr->targets[1], &sptr->targets[0], p - sptr->targets);
+ sptr->targets[0] = hash;
+ return 0;
+ }
+
+ if (now < sptr->nexttarget) {
+ if (sptr->nexttarget - now < TARGET_DELAY + 8) {
+ sptr->nexttarget += 2;
+ sendto_one(sptr, err_str(ERR_TARGETTOOFAST),
+ me.name, sptr->name, name, sptr->nexttarget - now);
+ }
+ return 1;
+ } else {
+ sptr->nexttarget += TARGET_DELAY;
+ if (sptr->nexttarget < now - (TARGET_DELAY * (MAXTARGETS - 1)))
+ sptr->nexttarget = now - (TARGET_DELAY * (MAXTARGETS - 1));
+ }
+ memmove(&sptr->targets[1], &sptr->targets[0], MAXTARGETS - 1);
+ sptr->targets[0] = hash;
+#endif
+ return 0;
+}
+
+
+
+
+/*
+** 'do_nick_name' ensures that the given parameter (nick) is
+** really a proper string for a nickname (note, the 'nick'
+** may be modified in the process...)
+**
+** RETURNS the length of the final NICKNAME (0, if
+** nickname is illegal)
+**
+** Nickname characters are in range
+** 'A'..'}', '_', '-', '0'..'9'
+** anything outside the above set will terminate nickname.
+** In addition, the first character cannot be '-'
+** or a Digit.
+**
+** Note:
+** '~'-character should be allowed, but
+** a change should be global, some confusion would
+** result if only few servers allowed it...
+*/
+
+int do_nick_name(nick)
+char *nick;
+{
+ Reg1 char *ch;
+
+ if (*nick == '-' || isdigit(*nick)) /* first character in [0..9-] */
+ return 0;
+
+ for (ch = nick; *ch && (ch - nick) < NICKLEN; ch++)
+ if (!isvalid(*ch) || isspace(*ch))
+ break;
+
+ *ch = '\0';
+
+ return (ch - nick);
+}
+
+
+/*
+** canonize
+**
+** reduce a string of duplicate list entries to contain only the unique
+** items. Unavoidably O(n^2).
+*/
+char *canonize(buffer)
+char *buffer;
+{
+ static char cbuf[BUFSIZ];
+ register char *s, *t, *cp = cbuf;
+ register int l = 0;
+ char *p = NULL, *p2;
+
+ *cp = '\0';
+
+ for (s = strtoken(&p, buffer, ","); s; s = strtoken(&p, NULL, ","))
+ {
+ if (l)
+ {
+ for (p2 = NULL, t = strtoken(&p2, cbuf, ","); t;
+ t = strtoken(&p2, NULL, ","))
+ if (!mycmp(s, t))
+ break;
+ else if (p2)
+ p2[-1] = ',';
+ }
+ else
+ t = NULL;
+ if (!t)
+ {
+ if (l)
+ *(cp-1) = ',';
+ else
+ l = 1;
+ (void)strcpy(cp, s);
+ if (p)
+ cp += (p - s);
+ }
+ else if (p2)
+ p2[-1] = ',';
+ }
+ return cbuf;
+}
+
+int m_remgline (aClient *cptr, aClient *sptr, int parc, char *parv[])
+{
+ if (!IsOper(sptr))
+ return 0;
+
+ sendto_one(sptr, ":%s NOTICE %s :*** Please use /gline -mask instead of /Remgline", me.name, sptr->name);
+}
+
+extern char cmodestring[512];
+
+/*
+** register_user
+** This function is called when both NICK and USER messages
+** have been accepted for the client, in whatever order. Only
+** after this the USER message is propagated.
+**
+** NICK's must be propagated at once when received, although
+** it would be better to delay them too until full info is
+** available. Doing it is not so simple though, would have
+** to implement the following:
+**
+** 1) user telnets in and gives only "NICK foobar" and waits
+** 2) another user far away logs in normally with the nick
+** "foobar" (quite legal, as this server didn't propagate
+** it).
+** 3) now this server gets nick "foobar" from outside, but
+** has already the same defined locally. Current server
+** would just issue "KILL foobar" to clean out dups. But,
+** this is not fair. It should actually request another
+** nick from local user or kill him/her...
+*/
+extern aTKline *tklines;
+
+static int register_user(cptr, sptr, nick, username, umode,virthost)
+aClient *cptr;
+aClient *sptr;
+char *nick, *username,*virthost, *umode;
+{
+ Reg1 aConfItem *aconf;
+ char *parv[3], *tmpstr, c;
+#ifdef HOSTILENAME
+ char stripuser[USERLEN+1], *u1=stripuser, *u2, olduser[USERLEN+1],
+ userbad[USERLEN*2+1], *ubad=userbad, noident=0;
+#endif
+ short oldstatus = sptr->status, upper = 0, lower = 0, special = 0;
+ int xx;
+ anUser *user = sptr->user;
+ aClient *nsptr;
+ int i;
+#ifdef OWNLOGON
+ FILE* ownlog;
+#endif
+ char mo[256], mo2[256];
+ char *tmpx;
+ char *tkllayer[9] =
+ {
+ me.name, /*0 server.name*/
+ "+", /*1 +|- */
+ "z", /*2 G */
+ "*", /*3 user */
+ NULL, /*4 host */
+ NULL,
+ NULL, /*6 expire_at */
+ NULL, /*7 set_at */
+ NULL /*8 reason */
+ };
+ user->last = TStime();
+ parv[0] = sptr->name;
+ parv[1] = parv[2] = NULL;
+
+ if (MyConnect(sptr))
+ {
+ sptr->iown = 1;
+ }
+ else
+ {
+ sptr->iown = 0;
+ }
+#ifdef OWNLOGON
+ ownlog = fopen ("iown.log", "a");
+ if (ownlog != NULL)
+ {
+ fprintf (ownlog, "%s connected, (iown=%d)\n",nick,sptr->iown);
+ fclose (ownlog);
+ }
+#endif
+
+ if (MyConnect(sptr))
+ {
+#ifdef SOCKSPORT
+ if (sptr->flags & FLAGS_GOTSOCKS)
+ {
+ char hostip[128];
+
+ strcpy(hostip, inetntoa((char *) &sptr->ip));
+
+ sendto_one(sptr, ":%s NOTICE AUTH :*** Found open SOCKS server (bad)", me.name);
+
+ sendto_umode(UMODE_EYES, "Open SOCKS server from client %s",
+ get_client_host(sptr));
+
+
+
+ i = exit_client(cptr, sptr, &me, iConf.socksquitmessage);
+
+ tkllayer[4] = hostip;
+ tkllayer[5] = me.name;
+ sprintf(mo, "%li", iConf.socksbantime+TStime());
+ sprintf(mo2, "%li", TStime());
+ tkllayer[6] = mo;
+ tkllayer[7] = mo2;
+ tkllayer[8] = iConf.socksbanmessage;
+ m_tkl(&me, &me, 9, tkllayer);
+ return i;
+ }
+
+#endif /* SOCKSPORT */
+
+ if ((i = check_client(sptr)))
+ {
+ sendto_umode(UMODE_OPER|UMODE_CLIENT,
+ "*** Notice -- %s from %s.",
+ i == -3 ? "Too many connections" :
+ "Unauthorized connection",
+ get_client_host(sptr));
+ ircstp->is_ref++;
+ tmpx = MyMalloc(1024);
+ sprintf(tmpx, "This server is full. Please try %s", defserv);
+ xx = exit_client(cptr, sptr, &me, i == -3 ?
+ tmpx : "You are not authorized to connect to this server");
+ MyFree(tmpx);
+ return xx;
+ }
+ if (IsUnixSocket(sptr))
+ strncpyzt(user->realhost, me.sockhost, sizeof(user->realhost));
+ else if (sptr->hostp) {
+ /* No control-chars or ip-like dns replies... I cheat :)
+ -- OnyxDragon */
+ for (tmpstr = sptr->sockhost; *tmpstr > ' ' &&
+ *tmpstr < 127; tmpstr++);
+ if (*tmpstr || !*user->realhost || isdigit(*(tmpstr-1)))
+ strncpyzt(sptr->sockhost, (char *)inetntoa((char *)&sptr->ip), sizeof(sptr->sockhost)); /* Fix the sockhost for debug jic */
+ strncpyzt(user->realhost, sptr->sockhost, sizeof(sptr->sockhost));
+ }
+ else /* Failsafe point, don't let the user define their
+ own hostname via the USER command --Cabal95 */
+ strncpyzt(user->realhost, sptr->sockhost, HOSTLEN+1);
+ strncpyzt(user->realhost, user->realhost, sizeof(user->realhost));
+ aconf = sptr->confs->value.aconf;
+ /*
+ * I do not consider *, ~ or ! 'hostile' in usernames,
+ * as it is easy to differentiate them (Use \*, \? and \\)
+ * with the possible?
+ * exception of !. With mIRC etc. ident is easy to fake
+ * to contain @ though, so if that is found use non-ident
+ * username. -Donwulff
+ *
+ * I do, We only allow a-z A-Z 0-9 _ - and . now so the
+ * !strchr(sptr->username, '@') check is out of date. -Cabal95
+ *
+ * Moved the noident stuff here. -OnyxDragon
+ */
+ if (!(sptr->flags & FLAGS_DOID))
+ strncpyzt(user->username, username, USERLEN+1);
+ else if (sptr->flags & FLAGS_GOTID)
+ strncpyzt(user->username, sptr->username, USERLEN+1);
+ else
+ {
+ /* because username may point to user->username */
+ char temp[USERLEN+1];
+
+ strncpyzt(temp, username, USERLEN+1);
+ *user->username = '~';
+ (void)strncpy(&user->username[1], temp, USERLEN);
+ user->username[USERLEN] = '\0';
+#ifdef HOSTILENAME
+ noident = 1;
+#endif
+ }
+#ifdef HOSTILENAME
+ /*
+ * Limit usernames to just 0-9 a-z A-Z _ - and .
+ * It strips the "bad" chars out, and if nothing is left
+ * changes the username to the first 8 characters of their
+ * nickname. After the MOTD is displayed it sends numeric
+ * 455 to the user telling them what(if anything) happened.
+ * -Cabal95
+ *
+ * Moved the noident thing to the right place - see above
+ * -OnyxDragon
+ */
+ for (u2 = user->username+noident; *u2; u2++)
+ {
+ if (isallowed(*u2))
+ *u1++ = *u2;
+ else if (*u2 < 32)
+ {
+ /*
+ * Make sure they can read what control
+ * characters were in their username.
+ */
+ *ubad++ = '^';
+ *ubad++ = *u2+'@';
+ }
+ else
+ *ubad++ = *u2;
+ }
+ *u1 = '\0';
+ *ubad = '\0';
+ if (strlen(stripuser) != strlen(user->username+noident))
+ {
+ if (stripuser[0] == '\0')
+ {
+ strncpy(stripuser, cptr->name, 8);
+ stripuser[8] = '\0';
+ }
+
+ strcpy(olduser, user->username+noident);
+ strncpy(user->username+1, stripuser, USERLEN-1);
+ user->username[0] = '~';
+ user->username[USERLEN] = '\0';
+ }
+ else
+ u1 = NULL;
+#endif
+
+ if (!BadPtr(aconf->passwd) && !StrEq("ONE", aconf->passwd)) {
+ if (!StrEq(sptr->passwd, aconf->passwd)) {
+ ircstp->is_ref++;
+ sendto_one(sptr, err_str(ERR_PASSWDMISMATCH),
+ me.name, parv[0]);
+ return exit_client(cptr, sptr, &me, "Bad Password");
+ }
+ /* .. Else password check was successful, clear the pass
+ * so it doesn't get sent to NickServ.
+ * - Wizzu
+ */
+ else sptr->passwd[0] = '\0';
+ }
+
+ /*
+ * following block for the benefit of time-dependent K:-lines
+ */
+ if (find_kill(sptr))
+ {
+ ircstp->is_ref++;
+ tmpx = MyMalloc(1024);
+ sprintf(tmpx, "[%s] You are banned from using this server", ircnetwork);
+ xx = exit_client(cptr, sptr, &me, "You are banned from using this server");
+ MyFree(tmpx);
+ return xx;
+ }
+ tkl_check_expire();
+ if ((xx = find_tkline_match(sptr, 0)) != -1)
+ {
+ ircstp->is_ref++;
+ return xx;
+ }
+
+#ifdef DISALLOW_MIXED_CASE
+/* check for mixed case usernames, meaning probably hacked Jon2 3-94
+*/
+#ifdef IGNORE_CASE_FIRST_CHAR
+ tmpstr = (username[0] == '~' ? &username[2] : &username[1]);
+#else
+ tmpstr = (username[0] == '~' ? &username[1] : username);
+#endif /* IGNORE_CASE_FIRST_CHAR */
+ while (*tmpstr && !(lower && upper || special)) {
+ c = *tmpstr;
+ tmpstr++;
+ if (islower(c)) {
+ lower++;
+ continue; /* bypass rest of tests */
+ }
+ if (isupper(c)) {
+ upper++;
+ continue;
+ }
+ if (c == '-' || c == '_' || c == '.' || isdigit(c))
+ continue;
+ special++;
+ }
+ if (lower && upper || special) {
+ sendto_ops("Invalid username: %s",
+ get_client_name(sptr,FALSE));
+ ircstp->is_ref++;
+ return exit_client(cptr, sptr, sptr , "Invalid username");
+ }
+
+#endif /* DISALLOW_MIXED_CASE */
+
+ if (oldstatus == STAT_MASTER && MyConnect(sptr))
+ (void)m_oper(&me, sptr, 1, parv);
+ }
+ else
+ {
+ strncpyzt(user->username, username, USERLEN+1);
+ }
+ SetClient(sptr);
+ make_virthost(user->realhost, user->virthost);
+ if (MyConnect(sptr))
+ {
+ sendto_one(sptr, rpl_str(RPL_WELCOME), me.name, nick,
+ ircnetwork, nick,
+ user->username, user->realhost);
+ /* This is a duplicate of the NOTICE but see below...*/
+ sendto_one(sptr, rpl_str(RPL_YOURHOST), me.name, nick,
+ me.name, version);
+#ifdef IRCII_KLUDGE
+ /*
+ ** Don't mess with this one - IRCII needs it! -Avalon
+ */
+ sendto_one(sptr,
+ "NOTICE %s :*** Your host is %s, running version %s",
+ nick, get_client_name(&me, FALSE), version);
+#endif
+ sendto_one(sptr, rpl_str(RPL_CREATED),me.name,nick,creation);
+#ifdef CONFROOM_JAVA_PORT
+ if (!(sptr->acpt->port == CONFROOM_JAVA_PORT))
+#endif
+ sendto_one(sptr, rpl_str(RPL_MYINFO), me.name, parv[0],
+ me.name, version,umodestring, cmodestring);
+ sendto_one(sptr, rpl_str(RPL_PROTOCTL), me.name,nick, PROTOCTL_CLIENT);
+ (void)m_lusers(sptr, sptr, 1, parv);
+ update_load();
+ (void)m_motd(sptr, sptr, 1, parv);
+
+#ifdef HOSTILENAME
+ /*
+ * Now send a numeric to the user telling them what, if
+ * anything, happened.
+ */
+ if (u1)
+ sendto_one(sptr, err_str(ERR_HOSTILENAME), me.name,
+ sptr->name, olduser, userbad, stripuser);
+#endif
+ nextping = TStime();
+ sendto_connectnotice(nick, user, sptr);
+/* sendto_umode(UMODE_OPER|UMODE_CLIENT,"*** Notice -- Client connecting on port %d: %s (%s@%s)",
+ sptr->acpt->port, nick, user->username,
+ user->realhost);
+ sendto_conn_hcn("*** Notice -- Client connecting: %s (%s@%s) [%s] {%d}",
+ nick,user->username, user->realhost, sptr->sockhost, get_client_class(sptr));
+*/
+/* This is a huge bastard of bandwidth use --sts */
+#ifdef BASTARDFCONNECTNOTICES
+ sendto_serv_butone(&me, ":%s SMO F :Client connecting at %s port %d: %s (%s@%s)",
+ me.name, me.name, sptr->acpt->port, nick, user->username, user->realhost);
+#endif
+ }
+ else if (IsServer(cptr))
+ {
+ aClient *acptr;
+
+ if (!(acptr = find_server(user->server, NULL)))
+ {
+ sendto_ops("Bad USER [%s] :%s USER %s %s : No such server",
+ cptr->name, nick, user->username, user->server);
+ sendto_one(cptr, ":%s KILL %s :%s (No such server: %s)",
+ me.name, sptr->name, me.name, user->server);
+ sptr->flags |= FLAGS_KILLED;
+ return exit_client(sptr, sptr, &me,
+ "USER without prefix(2.8) or wrong prefix");
+ }
+ else if (acptr->from != sptr->from)
+ {
+ sendto_ops("Bad User [%s] :%s USER %s %s, != %s[%s]",
+ cptr->name, nick, user->username, user->server,
+ acptr->name, acptr->from->name);
+ sendto_one(cptr, ":%s KILL %s :%s (%s != %s[%s])",
+ me.name, sptr->name, me.name, user->server,
+ acptr->from->name, acptr->from->sockhost);
+ sptr->flags |= FLAGS_KILLED;
+ return exit_client(sptr, sptr, &me,
+ "USER server wrong direction");
+ }
+ else sptr->flags|=(acptr->flags & FLAGS_TS8);
+ /* *FINALL* this gets in ircd... -- Barubary */
+ if (find_conf_host(cptr->confs, sptr->name, CONF_UWORLD)
+ || (sptr->user && find_conf_host(cptr->confs,
+ sptr->user->server, CONF_UWORLD)))
+ sptr->flags |= FLAGS_ULINE;
+ }
+
+ if (virthost && umode)
+ {
+ tkllayer[0] = nick;
+ tkllayer[1] = nick;
+ tkllayer[2] = umode;
+ dontspread = 1;
+ m_mode(cptr,sptr, 3, tkllayer);
+ dontspread = 0;
+ if (virthost && *virthost != '*')
+ sprintf(sptr->user->virthost, virthost);
+ }
+ hash_check_notify(sptr, RPL_LOGON); /* Uglier hack */
+ sendto_serv_butone_nickv2(cptr, "NICK %s %d %d %s %s %s %lu :%s", nick,
+ sptr->hopcount+1, sptr->lastnick, user->username, user->realhost,
+ user->server, sptr->user->servicestamp, sptr->info);
+ if (virthost && *virthost != '*')
+ sendto_serv_butone_nickv2(cptr, ":%s SETHOST %s", sptr->name, sptr->user->virthost);
+ send_umode(NULL, sptr, 0, SEND_UMODES, buf);
+ sendto_serv_nickv2(cptr, "NICK %s %d %d %s %s %s %lu %s %s :%s", nick,
+ sptr->hopcount+1, sptr->lastnick, user->username, user->realhost,
+ user->server, sptr->user->servicestamp,
+ (!buf || *buf == '\0' ? "+" : buf),
+ ((IsHidden(sptr) && (sptr->umodes & UMODE_SETHOST)) ? sptr->user->virthost : "*"),
+ sptr->info);
+
+ /* Send password from sptr->passwd to NickServ for identification,
+ * if passwd given and if NickServ is online.
+ * - by taz, modified by Wizzu
+ */
+ if (MyConnect(sptr)) {
+ send_umode_out_nickv2(cptr, sptr, 0);
+ if (sptr->passwd[0] && (nsptr = find_person(NickServ, NULL)))
+ sendto_one(nsptr,":%s PRIVMSG %s@%s :IDENTIFY %s",
+ sptr->name, NickServ, SERVICES_NAME, sptr->passwd);
+ }
+
+ if(MyConnect(sptr) && !BadPtr(sptr->passwd))
+ bzero(sptr->passwd, sizeof(sptr->passwd));
+
+
+ return 0;
+ }
+
+/*
+** m_svsnick
+** parv[0] = sender
+** parv[1] = old nickname
+** parv[2] = new nickname
+** parv[3] = timestamp
+*/
+int m_svsnick(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ aClient *acptr;
+
+ if (!IsULine(cptr, sptr) || parc < 4 || (strlen(parv[2]) > NICKLEN))
+ return -1; /* This looks like an error anyway -Studded */
+
+ if (!hunt_server(cptr, sptr, ":%s SVSNICK %s %s :%s", 1, parc, parv) != HUNTED_ISME) {
+ if ((acptr = find_person(parv[1], NULL))) {
+ if(find_client(parv[2], NULL)) /* Collision */
+ return exit_client(cptr, acptr, sptr,
+ "Nickname collision due to Services enforced "
+ "nickname change, your nick was overruled");
+ if (strchr(parv[2], '.'))
+ return exit_client(cptr, acptr, sptr,
+ "SVSNICK Collide (nick changed to be server)");
+ acptr->umodes &= ~UMODE_REGNICK;
+ acptr->lastnick = atoi(parv[3]);
+ sendto_common_channels(acptr, ":%s NICK :%s", parv[1], parv[2]);
+ if (IsPerson(acptr))
+ add_history(acptr);
+ sendto_serv_butone(NULL, ":%s NICK %s :%i", parv[1], parv[2], atoi(parv[3]));
+ if(acptr->name[0]) {
+ (void)del_from_client_hash_table(acptr->name, acptr);
+ if(IsPerson(acptr)) hash_check_notify(acptr, RPL_LOGOFF);
+ }
+ (void)strcpy(acptr->name, parv[2]);
+ (void)add_to_client_hash_table(parv[2], acptr);
+ if (IsPerson(acptr)) hash_check_notify(acptr, RPL_LOGON);
+ }
+ }
+ return 0;
+}
+
+/*
+** m_nick
+** parv[0] = sender prefix
+** parv[1] = nickname
+** if from new client -taz
+** parv[2] = nick password
+** if from server:
+** parv[2] = hopcount
+** parv[3] = timestamp
+** parv[4] = username
+** parv[5] = hostname
+** parv[6] = servername
+** if NICK version 1:
+** parv[7] = servicestamp
+** parv[8] = info
+** if NICK version 2:
+** parv[7] = servicestamp
+** parv[8] = umodes
+** parv[9] = virthost, * if none
+** parv[10] = info
+*/
+int m_nick(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ aConfItem *aconf;
+ aSqlineItem *asqline;
+ aClient *acptr, *serv;
+ char nick[NICKLEN+2], *s;
+ Link *lp;
+ time_t lastnick = (time_t)0;
+ int differ = 1;
+
+ static int firstnsrun=0;
+ u_int32_t md5data[16];
+ static u_int32_t md5hash[4];
+
+ /*
+ * If the user didn't specify a nickname, complain
+ */
+ if (parc < 2)
+ {
+ sendto_one(sptr, err_str(ERR_NONICKNAMEGIVEN),
+ me.name, parv[0]);
+ return 0;
+ }
+
+ if (MyConnect(sptr) && (s = (char *)index(parv[1], '~')))
+ *s = '\0';
+
+ strncpyzt(nick, parv[1], NICKLEN+1);
+ /*
+ * if do_nick_name() returns a null name OR if the server sent a nick
+ * name and do_nick_name() changed it in some way (due to rules of nick
+ * creation) then reject it. If from a server and we reject it,
+ * and KILL it. -avalon 4/4/92
+ */
+ if (do_nick_name(nick) == 0 ||
+ (IsServer(cptr) && strcmp(nick, parv[1])))
+ {
+ sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME),
+ me.name, parv[0], parv[1], "Illegal characters");
+
+ if (IsServer(cptr))
+ {
+ ircstp->is_kill++;
+ sendto_failops("Bad Nick: %s From: %s %s",
+ parv[1], parv[0],
+ get_client_name(cptr, FALSE));
+ sendto_one(cptr, ":%s KILL %s :%s (%s <- %s[%s])",
+ me.name, parv[1], me.name, parv[1],
+ nick, cptr->name);
+ if (sptr != cptr)
+ { /* bad nick change */
+ sendto_serv_butone(cptr,
+ ":%s KILL %s :%s (%s <- %s!%s@%s)",
+ me.name, parv[0], me.name,
+ get_client_name(cptr, FALSE),
+ parv[0],
+ sptr->user ? sptr->username : "",
+ sptr->user ? sptr->user->server :
+ cptr->name);
+ sptr->flags |= FLAGS_KILLED;
+ return exit_client(cptr,sptr,&me,"BadNick");
+ }
+ }
+ return 0;
+ }
+
+ /*
+ ** Protocol 4 doesn't send the server as prefix, so it is possible
+ ** the server doesn't exist (a lagged net.burst), in which case
+ ** we simply need to ignore the NICK. Also when we got that server
+ ** name (again) but from another direction. --Run
+ */
+ /*
+ ** We should really only deal with this for msgs from servers.
+ ** -- Aeto
+ */
+ if (IsServer(cptr) &&
+ (parc > 7 && (!(serv = find_server(parv[6], NULL)) ||
+ serv->from != cptr->from)))
+ return 0;
+
+ /*
+ ** Check against nick name collisions.
+ **
+ ** Put this 'if' here so that the nesting goes nicely on the screen :)
+ ** We check against server name list before determining if the nickname
+ ** is present in the nicklist (due to the way the below for loop is
+ ** constructed). -avalon
+ */
+ if ((acptr = find_server(nick, NULL)))
+ {
+ if (MyConnect(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_NICKNAMEINUSE), me.name,
+ BadPtr(parv[0]) ? "*" : parv[0], nick);
+ return 0; /* NICK message ignored */
+ }
+ }
+
+ /*
+ ** Check for a Q-lined nickname. If we find it, and it's our
+ ** client, just reject it. -Lefler
+ ** Allow opers to use Q-lined nicknames. -Russell
+ */
+#ifdef WEBTV_IRCUSER
+ if (!match("irc", nick))
+ {
+ sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name,
+ BadPtr(parv[0]) ? "*" : parv[0], nick,
+ "Reserved for internal IRCd purposes");
+ return 0;
+ }
+#endif
+ if (!IsULine(cptr, sptr) && ((aconf = find_conf_name(nick, CONF_QUARANTINED_NICK)) ||
+ (asqline = find_sqline_match(nick))))
+ {
+ sendto_realops ("Q-lined nick %s from %s on %s.", nick,
+ (*sptr->name!=0 && !IsServer(sptr)) ? sptr->name :
+ "<unregistered>",
+ (sptr->user==NULL) ? ((IsServer(sptr)) ? parv[6] : me.name) :
+ sptr->user->server);
+ if ((!IsServer(cptr)) && (!IsOper(cptr)))
+ {
+
+ if(aconf)
+ sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name,
+ BadPtr(parv[0]) ? "*" : parv[0], nick,
+ BadPtr(aconf->passwd) ? "reason unspecified" :
+ aconf->passwd);
+ else if(asqline)
+ sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name,
+ BadPtr(parv[0]) ? "*" : parv[0], nick,
+ BadPtr(asqline->reason) ? "reason unspecified" :
+ asqline->reason);
+
+ sendto_realops("Forbidding Q-lined nick %s from %s.",
+ nick, get_client_name(cptr, FALSE));
+ return 0; /* NICK message ignored */
+ }
+ }
+
+ /*
+ ** acptr already has result from previous find_server()
+ */
+ if (acptr)
+ {
+ /*
+ ** We have a nickname trying to use the same name as
+ ** a server. Send out a nick collision KILL to remove
+ ** the nickname. As long as only a KILL is sent out,
+ ** there is no danger of the server being disconnected.
+ ** Ultimate way to jupiter a nick ? >;-). -avalon
+ */
+ sendto_failops("Nick collision on %s(%s <- %s)",
+ sptr->name, acptr->from->name,
+ get_client_name(cptr, FALSE));
+ ircstp->is_kill++;
+ sendto_one(cptr, ":%s KILL %s :%s (%s <- %s)",
+ me.name, sptr->name, me.name, acptr->from->name,
+ /* NOTE: Cannot use get_client_name
+ ** twice here, it returns static
+ ** string pointer--the other info
+ ** would be lost
+ */
+ get_client_name(cptr, FALSE));
+ sptr->flags |= FLAGS_KILLED;
+ return exit_client(cptr, sptr, &me, "Nick/Server collision");
+ }
+
+ if (MyClient(cptr) && !IsOper(cptr))
+ cptr->since += 3; /* Nick-flood prot. -Donwulff */
+
+ if (!(acptr = find_client(nick, NULL)))
+ goto nickkilldone; /* No collisions, all clear... */
+ /*
+ ** If the older one is "non-person", the new entry is just
+ ** allowed to overwrite it. Just silently drop non-person,
+ ** and proceed with the nick. This should take care of the
+ ** "dormant nick" way of generating collisions...
+ */
+ /* Moved before Lost User Field to fix some bugs... -- Barubary */
+ if (IsUnknown(acptr) && MyConnect(acptr))
+ {
+ /* This may help - copying code below */
+ if (acptr == cptr)
+ return 0;
+ acptr->flags |= FLAGS_KILLED;
+ exit_client(NULL, acptr, &me, "Overridden");
+ goto nickkilldone;
+ }
+ /* A sanity check in the user field... */
+ if (acptr->user == NULL)
+ {
+ /* This is a Bad Thing */
+ sendto_failops("Lost user field for %s in change from %s",
+ acptr->name, get_client_name(cptr,FALSE));
+ ircstp->is_kill++;
+ sendto_one(acptr, ":%s KILL %s :%s (Lost user field!)",
+ me.name, acptr->name, me.name);
+ acptr->flags |= FLAGS_KILLED;
+ /* Here's the previous versions' desynch. If the old one is
+ messed up, trash the old one and accept the new one.
+ Remember - at this point there is a new nick coming in!
+ Handle appropriately. -- Barubary */
+ exit_client (NULL, acptr, &me, "Lost user field");
+ goto nickkilldone;
+ }
+ /*
+ ** If acptr == sptr, then we have a client doing a nick
+ ** change between *equivalent* nicknames as far as server
+ ** is concerned (user is changing the case of his/her
+ ** nickname or somesuch)
+ */
+ if (acptr == sptr)
+ if (strcmp(acptr->name, nick) != 0)
+ /*
+ ** Allows change of case in his/her nick
+ */
+ goto nickkilldone; /* -- go and process change */
+ else
+ /*
+ ** This is just ':old NICK old' type thing.
+ ** Just forget the whole thing here. There is
+ ** no point forwarding it to anywhere,
+ ** especially since servers prior to this
+ ** version would treat it as nick collision.
+ */
+ return 0; /* NICK Message ignored */
+ /*
+ ** Note: From this point forward it can be assumed that
+ ** acptr != sptr (point to different client structures).
+ */
+ /*
+ ** Decide, we really have a nick collision and deal with it
+ */
+ if (!IsServer(cptr))
+ {
+ /*
+ ** NICK is coming from local client connection. Just
+ ** send error reply and ignore the command.
+ */
+ sendto_one(sptr, err_str(ERR_NICKNAMEINUSE),
+ /* parv[0] is empty when connecting */
+ me.name, BadPtr(parv[0]) ? "*" : parv[0], nick);
+ return 0; /* NICK message ignored */
+ }
+ /*
+ ** NICK was coming from a server connection.
+ ** This means we have a race condition (two users signing on
+ ** at the same time), or two net fragments reconnecting with
+ ** the same nick.
+ ** The latter can happen because two different users connected
+ ** or because one and the same user switched server during a
+ ** net break.
+ ** If we have the old protocol (no TimeStamp and no user@host)
+ ** or if the TimeStamps are equal, we kill both (or only 'new'
+ ** if it was a "NICK new"). Otherwise we kill the youngest
+ ** when user@host differ, or the oldest when they are the same.
+ ** --Run
+ **
+ */
+ if (IsServer(sptr))
+ {
+ /*
+ ** A new NICK being introduced by a neighbouring
+ ** server (e.g. message type "NICK new" received)
+ */
+ if (parc > 3)
+ {
+ lastnick = atoi(parv[3]);
+ if (parc > 5)
+ differ = (mycmp(acptr->user->username, parv[4]) ||
+ mycmp(acptr->user->realhost, parv[5]));
+ }
+ sendto_failops("Nick collision on %s (%s %d <- %s %d)",
+ acptr->name, acptr->from->name, acptr->lastnick,
+ get_client_name(cptr, FALSE), lastnick);
+ /*
+ ** I'm putting the KILL handling here just to make it easier
+ ** to read, it's hard to follow it the way it used to be.
+ ** Basically, this is what it will do. It will kill both
+ ** users if no timestamp is given, or they are equal. It will
+ ** kill the user on our side if the other server is "correct"
+ ** (user@host differ and their user is older, or user@host are
+ ** the same and their user is younger), otherwise just kill the
+ ** user an reintroduce our correct user.
+ ** The old code just sat there and "hoped" the other server
+ ** would kill their user. Not anymore.
+ ** -- binary
+ */
+ if (!(parc > 3) || (acptr->lastnick == lastnick))
+ {
+ ircstp->is_kill++;
+ sendto_serv_butone(NULL,
+ ":%s KILL %s :%s (Nick Collision: %s <- %s)",
+ me.name, acptr->name, me.name, acptr->from->name,
+ parc > 5 ? parv[5] : get_client_name(cptr, FALSE));
+ acptr->flags |= FLAGS_KILLED;
+ (void)exit_client(NULL, acptr, &me,
+ "Nick collision with no timestamp/equal timestamps");
+ return 0; /* We killed both users, now stop the process. */
+ }
+
+ if ((differ && (acptr->lastnick > lastnick)) ||
+ (!differ && (acptr->lastnick < lastnick)) ||
+ acptr->from == cptr) /* we missed a QUIT somewhere ? */
+ {
+ ircstp->is_kill++;
+ sendto_serv_butone(cptr,
+ ":%s KILL %s :%s (Nick Collision: %s <- %s)",
+ me.name, acptr->name, me.name, acptr->from->name,
+ parc > 5 ? parv[5] : get_client_name(cptr, FALSE));
+ acptr->flags |= FLAGS_KILLED;
+ (void)exit_client(NULL, acptr, &me,
+ "Nick collision");
+ goto nickkilldone; /* OK, we got rid of the "wrong" user,
+ ** now we're going to add the user the
+ ** other server introduced.
+ */
+ }
+
+ if ((differ && (acptr->lastnick < lastnick)) ||
+ (!differ && (acptr->lastnick > lastnick)))
+ {
+ /*
+ * Introduce our "correct" user to the other server
+ */
+
+ sendto_one(cptr, ":%s KILL %s :%s (Nick Collision)",
+ me.name, parv[1], me.name);
+ sendto_one(cptr, "NICK %s %d %d %s %s %s :%s",
+ acptr->name, acptr->hopcount + 1, acptr->lastnick,
+ acptr->user->username, acptr->user->realhost,
+ acptr->user->server, acptr->info);
+ send_umode(cptr, acptr, 0, SEND_UMODES, buf);
+ if (IsHidden(acptr)) {
+ sendto_one(cptr, ":%s SETHOST %s", acptr->name, acptr->user->virthost);
+ }
+ if (acptr->user->away)
+ sendto_one(cptr, ":%s AWAY :%s", acptr->name,
+ acptr->user->away);
+ send_user_joins(cptr, acptr);
+ return 0; /* Ignore the NICK */
+ }
+ return 0;
+ }
+ else
+ {
+ /*
+ ** A NICK change has collided (e.g. message type ":old NICK new").
+ */
+ if (parc > 2)
+ lastnick = atoi(parv[2]);
+ differ = (mycmp(acptr->user->username, sptr->user->username) ||
+ mycmp(acptr->user->realhost, sptr->user->realhost));
+ sendto_failops(
+ "Nick change collision from %s to %s (%s %d <- %s %d)",
+ sptr->name, acptr->name, acptr->from->name,
+ acptr->lastnick, sptr->from->name, lastnick);
+ if (!(parc > 2) || lastnick == acptr->lastnick)
+ {
+ ircstp->is_kill += 2;
+ sendto_serv_butone(NULL, /* First kill the new nick. */
+ ":%s KILL %s :%s (Self Collision)",
+ me.name, acptr->name, me.name);
+ sendto_serv_butone(cptr, /* Tell my servers to kill the old */
+ ":%s KILL %s :%s (Self Collision)",
+ me.name, sptr->name, me.name);
+ sptr->flags |= FLAGS_KILLED;
+ acptr->flags |= FLAGS_KILLED;
+ (void)exit_client(NULL, sptr, &me, "Self Collision");
+ (void)exit_client(NULL, acptr, &me, "Self Collision");
+ return 0; /* Now that I killed them both, ignore the NICK */
+ }
+ if ((differ && (acptr->lastnick > lastnick)) ||
+ (!differ && (acptr->lastnick < lastnick)))
+ {
+ /* sptr (their user) won, let's kill acptr (our user) */
+ ircstp->is_kill++;
+ sendto_serv_butone(cptr,
+ ":%s KILL %s :%s (Nick collision: %s <- %s)",
+ me.name, acptr->name, me.name,
+ acptr->from->name, sptr->from->name);
+ acptr->flags |= FLAGS_KILLED;
+ (void)exit_client(NULL, acptr, &me, "Nick collision");
+ goto nickkilldone; /* their user won, introduce new nick */
+ }
+ if ((differ && (acptr->lastnick < lastnick)) ||
+ (!differ && (acptr->lastnick > lastnick)))
+ {
+ /* acptr (our user) won, let's kill sptr (their user),
+ ** and reintroduce our "correct" user
+ */
+ ircstp->is_kill++;
+ /* Kill the user trying to change their nick. */
+ sendto_serv_butone(cptr,
+ ":%s KILL %s :%s (Nick collision: %s <- %s)",
+ me.name, sptr->name, me.name,
+ sptr->from->name, acptr->from->name);
+ sptr->flags |= FLAGS_KILLED;
+ (void)exit_client(NULL, sptr, &me, "Nick collision");
+ /*
+ * Introduce our "correct" user to the other server
+ */
+ /* Kill their user. */
+ sendto_one(cptr, ":%s KILL %s :%s (Nick Collision)",
+ me.name, parv[1], me.name);
+ sendto_one(cptr, "NICK %s %d %d %s %s %s :%s",
+ acptr->name, acptr->hopcount + 1, acptr->lastnick,
+ acptr->user->username, acptr->user->realhost,
+ acptr->user->server, acptr->info);
+ send_umode(cptr, acptr, 0, SEND_UMODES, buf);
+ if (acptr->user->away)
+ sendto_one(cptr, ":%s AWAY :%s", acptr->name,
+ acptr->user->away);
+ if (IsHidden(acptr)) {
+ sendto_one(cptr, ":%s SETHOST %s", acptr->name, acptr->user->virthost);
+ }
+
+ send_user_joins(cptr, acptr);
+ return 0; /* their user lost, ignore the NICK */
+ }
+
+ }
+ return 0; /* just in case */
+nickkilldone:
+ if (IsServer(sptr)) {
+ /* A server introducing a new client, change source */
+
+ sptr = make_client(cptr, serv);
+ add_client_to_list(sptr);
+ if (parc > 2)
+ sptr->hopcount = atoi(parv[2]);
+ if (parc > 3)
+ sptr->lastnick = atoi(parv[3]);
+ else /* Little bit better, as long as not all upgraded */
+ sptr->lastnick = TStime();
+ } else if (sptr->name[0]&&IsPerson(sptr)) {
+ /*
+ ** If the client belongs to me, then check to see
+ ** if client is currently on any channels where it
+ ** is currently banned. If so, do not allow the nick
+ ** change to occur.
+ ** Also set 'lastnick' to current time, if changed.
+ */
+ if (MyClient(sptr))
+ for (lp = cptr->user->channel; lp; lp = lp->next)
+ if (is_banned(cptr, &me, lp->value.chptr)) {
+ sendto_one(cptr,
+ err_str(ERR_BANNICKCHANGE),
+ me.name, parv[0],
+ lp->value.chptr->chname);
+ return 0;
+ }
+
+ /*
+ * Client just changing his/her nick. If he/she is
+ * on a channel, send note of change to all clients
+ * on that channel. Propagate notice to other servers.
+ */
+ if (mycmp(parv[0], nick) ||
+ /* Next line can be removed when all upgraded --Run */
+ !MyClient(sptr) && parc>2 && atoi(parv[2])<sptr->lastnick)
+ sptr->lastnick = (MyClient(sptr) || parc < 3) ?
+ TStime():atoi(parv[2]);
+ SetRegNick(sptr);
+ add_history(sptr);
+ sendto_common_channels(sptr, ":%s NICK :%s", parv[0], nick);
+ sendto_serv_butone(cptr, ":%s NICK %s :%d",
+ parv[0], nick, sptr->lastnick);
+ } else if(!sptr->name[0])
+ {
+#ifdef NOSPOOF
+ /*
+ * Client setting NICK the first time.
+ *
+ * Generate a random string for them to pong with.
+ *
+ * The first two are server specific. The intent is to randomize
+ * things well.
+ *
+ * We use lots of junk here, but only "low cost" things.
+ */
+ md5data[0] = NOSPOOF_SEED01;
+ md5data[1] = NOSPOOF_SEED02;
+ md5data[2] = TStime();
+ md5data[3] = me.sendM;
+ md5data[4] = me.receiveM;
+ md5data[5] = 0;
+ md5data[6] = getpid();
+ md5data[7] = sptr->ip.s_addr;
+ md5data[8] = sptr->fd;
+ md5data[9] = 0;
+ md5data[10] = 0;
+ md5data[11] = 0;
+ md5data[12] = md5hash[0]; /* previous runs... */
+ md5data[13] = md5hash[1];
+ md5data[14] = md5hash[2];
+ md5data[15] = md5hash[3];
+
+ /*
+ * initialize the md5 buffer to known values
+ */
+ MD5Init(md5hash);
+
+ /*
+ * transform the above information into gibberish
+ */
+ MD5Transform(md5hash, md5data);
+
+ /*
+ * Never release any internal state of our generator. Instead,
+ * use two parts of the returned hash and xor them to hide
+ * both values.
+ */
+ sptr->nospoof = (md5hash[0] ^ md5hash[1]);
+
+ /*
+ * If on the odd chance it comes out zero, make it something
+ * non-zero.
+ */
+ if (sptr->nospoof == 0)
+ sptr->nospoof = 0xdeadbeef;
+ sendto_one(sptr, "NOTICE %s :*** If you are having problems"
+ " connecting due to ping timeouts, please"
+ " type /notice %X nospoof now.",
+ nick, sptr->nospoof, sptr->nospoof);
+ sendto_one(sptr, "PING :%X", sptr->nospoof);
+#endif /* NOSPOOF */
+
+#ifdef CONTACT_EMAIL
+ sendto_one(sptr, ":%s NOTICE %s :*** If you need assistance with a"
+ " connection problem, please email " CONTACT_EMAIL
+ " with the name and version of the client you are"
+ " using, and the server you tried to connect to: %s",
+ me.name, nick, me.name);
+#endif /* CONTACT_EMAIL */
+#ifdef CONTACT_URL
+ sendto_one(sptr, ":%s NOTICE %s :*** If you need assistance with"
+ " connecting to this server, %s, please refer to: "
+ CONTACT_URL, me.name, nick, me.name);
+#endif /* CONTACT_URL */
+
+ /* Copy password to the passwd field if it's given after NICK
+ * - originally by taz, modified by Wizzu
+ */
+ if((parc > 2) && (strlen(parv[2]) < sizeof(sptr->passwd)))
+ (void)strcpy(sptr->passwd,parv[2]);
+
+ /* This had to be copied here to avoid problems.. */
+ (void)strcpy(sptr->name, nick);
+ if (sptr->user && IsNotSpoof(sptr)) {
+ /*
+ ** USER already received, now we have NICK.
+ ** *NOTE* For servers "NICK" *must* precede the
+ ** user message (giving USER before NICK is possible
+ ** only for local client connection!). register_user
+ ** may reject the client and call exit_client for it
+ ** --must test this and exit m_nick too!!!
+ */
+ sptr->lastnick = TStime(); /* Always local client */
+ if (register_user(cptr, sptr, nick,
+ sptr->user->username, NULL, NULL)
+
+ == FLUSH_BUFFER)
+ return FLUSH_BUFFER; }
+ }
+ /*
+ * Finally set new nick name.
+ */
+ if (sptr->name[0]) {
+ (void)del_from_client_hash_table(sptr->name, sptr);
+ if (IsPerson(sptr))
+ hash_check_notify(sptr, RPL_LOGOFF);
+ }
+ (void)strcpy(sptr->name, nick);
+ (void)add_to_client_hash_table(nick, sptr);
+ if (IsServer(cptr) && parc>7) {
+ parv[3]=nick;
+ m_user(cptr, sptr, parc-3, &parv[3]);
+ if (GotNetInfo(cptr))
+ sendto_umode(UMODE_FCLIENT, "*** Notice -- Client connecting at %s: %s (%s@%s)",
+ sptr->user->server, sptr->name, sptr->user->username, sptr->user->realhost);
+ }
+ else if (IsPerson(sptr))
+ hash_check_notify(sptr, RPL_LOGON);
+
+ return 0;
+}
+
+/*
+** m_message (used in m_private() and m_notice())
+** the general function to deliver MSG's between users/channels
+**
+** parv[0] = sender prefix
+** parv[1] = receiver list
+** parv[2] = message text
+**
+** massive cleanup
+** rev argv 6/91
+**
+*/
+
+static int m_message(cptr, sptr, parc, parv, notice)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+int notice;
+{
+ Reg1 aClient *acptr;
+ Reg2 char *s;
+ aChannel *chptr;
+ char *nick, *server, *p, *cmd, *host, *ctcp;
+ int cansend = 0;
+#ifdef REMOVE_ADVERTISING
+ /* patch by ice (ircadmin@fornet.net.tr) */
+ char *reklam,*reklam1,*reklam2, *sonuc;
+ char bas[200];
+ int b;
+#endif
+
+ /*
+ * Reasons why someone can't send to a channel
+ */
+ static char *err_cantsend[] = {
+ "You need voice (+v)",
+ "No external channel messages",
+ "Colour is not permitted in this channel",
+ "You are banned",
+ NULL
+ };
+
+ if (IsHandshake(sptr))
+ return 0;
+
+ if (notice)
+ {
+ if (check_registered(sptr))
+ return 0;
+ }
+ else if (check_registered_user(sptr))
+ return 0;
+
+ sptr->flags&=~FLAGS_TS8;
+ cmd = notice ? MSG_NOTICE : MSG_PRIVATE;
+ if (parc < 2 || *parv[1] == '\0')
+ {
+ sendto_one(sptr, err_str(ERR_NORECIPIENT),
+ me.name, parv[0], cmd);
+ return -1;
+ }
+
+ if (parc < 3 || *parv[2] == '\0')
+ {
+ sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]);
+ return -1;
+ }
+
+#ifdef WEBTV_NONOTICE
+ if (*parv[2] != '\1')
+ {
+ cmd = MSG_PRIVATE;
+ }
+#endif
+ if (MyConnect(sptr))
+ parv[1] = canonize(parv[1]);
+ for (p = NULL, nick = strtoken(&p, parv[1], ","); nick;
+ nick = strtoken(&p, NULL, ","))
+ {
+ /*
+ ** nickname addressed?
+ */
+#ifdef WEBTV_IRCUSER
+ if (!strcasecmp(nick, "irc") && MyClient(sptr))
+ {
+ parse(sptr, parv[2], (parv[2] + strlen(parv[2])), msgtab);
+ continue;
+ }
+#endif
+ if ((acptr = find_person(nick, NULL)))
+ {
+ /* F:Line stuff by _Jozeph_ added by Stskeeps with comments */
+ if (*parv[2] == 1 && MyClient(sptr) && !IsOper(sptr))
+ /* somekinda ctcp thing
+ and i don't want to waste cpu on what others already checked..
+ (should this be checked ??) --Sts
+ */
+ {
+ ctcp = &parv[2][1];
+ /* Most likely a DCC send .. */
+ if (!myncmp(ctcp, "DCC SEND ", 9))
+ {
+ aFline *fl;
+ char *end, file[BUFSIZE];
+ int size_string = 0;
+
+ ctcp = &parv[2][10];
+ end = (char *)index(ctcp, ' ');
+
+ /* check if it was fake.. just pass it along then .. */
+ if (!end || (end < ctcp))
+ goto dcc_was_ok;
+
+ size_string=(int)(end - ctcp);
+
+ if (!size_string || (size_string>(BUFSIZE-1)))
+ goto dcc_was_ok;
+
+ strncpy(file, ctcp, size_string);
+ file[size_string] = '\0';
+
+ if ((fl = (aFline *) dcc_isforbidden(cptr,sptr,acptr, file)))
+ {
+ sendto_one(sptr, ":%s %d %s :Cannot DCC SEND file %s to %s (%s)",
+ me.name, RPL_TEXT, sptr->name,
+ file, acptr->name, fl->reason ? fl->reason :
+ "Possible infected virus file");
+ /* Alert +e's too so preventive measure can be taken */
+ sendto_umode(UMODE_EYES, "%s tried to send forbidden file %s (%s) to %s", sptr->name, file, fl->reason, acptr->name);
+ sendto_umode(UMODE_VICTIM, "%s tried to send forbidden file %s (%s) to %s", sptr->name, file, fl->reason, acptr->name);
+ continue;
+ }
+ /* if it went here it was a legal send .. */
+ }
+ }
+dcc_was_ok:
+#ifdef REMOVE_ADVERTISING
+ /* remove advertisment patch by ice - a bit ugly but it works? :P*/
+ reklam=strstr(parv[2],"irc.");
+ if (!reklam) reklam=strstr(parv[2],"IRC.");
+ if (!reklam) reklam=strstr(parv[2],"Irc.");
+ if (!reklam) reklam=strstr(parv[2],"IRc.");
+ if (!reklam) reklam=strstr(parv[2],"irC.");
+ if (!reklam) reklam=strstr(parv[2],"iRc.");
+ if (!reklam) reklam=strstr(parv[2],"iRC.");
+ if (!reklam) reklam=strstr(parv[2],"IrC.");
+ if (reklam) {
+ b=strlen(parv[2])-strlen(reklam);
+ while (reklam) {
+ reklam1=reklam;
+ reklam=strstr(reklam1,".");
+ reklam2=reklam;
+ reklam=strstr(reklam2,"irc.");
+ if (!reklam) reklam=strstr(reklam2,"IRC.");
+ if (!reklam) reklam=strstr(reklam2,"Irc.");
+ if (!reklam) reklam=strstr(reklam2,"IRc.");
+ if (!reklam) reklam=strstr(reklam2,"IrC.");
+ if (!reklam) reklam=strstr(reklam2,"iRC.");
+ if (!reklam) reklam=strstr(reklam2,"iRc.");
+ if (!reklam) reklam=strstr(reklam2,"irC.");
+ }
+ strcpy(bas,"");
+ if (b <= 150) strncat(bas,parv[2],b);
+ sonuc=strstr(reklam1,".com");
+ if (!sonuc) sonuc=strstr(reklam1,".net");
+ if (!sonuc) sonuc=strstr(reklam1,".COM");
+ if (!sonuc) sonuc=strstr(reklam1,".NET");
+ if (!sonuc) sonuc=strstr(reklam1,".gen");
+ if (!sonuc) sonuc=strstr(reklam1,".GEN");
+ if (!sonuc) sonuc=strstr(reklam1,".ORG");
+ if (!sonuc) sonuc=strstr(reklam1,".org");
+ if (!sonuc) sonuc=strstr(reklam1,".EDU");
+ if (!sonuc) sonuc=strstr(reklam1,".edu");
+ if (!sonuc) sonuc=strstr(reklam1,".");
+ if (!sonuc) sonuc=strstr(reklam1," ");
+ strcat(bas,"irc.*****");
+ if ((strlen(sonuc)+strlen(bas)) <=150) strcat(bas,sonuc);
+ parv[2]=bas;
+ }
+#endif
+
+ if (MyClient(sptr) && check_for_target_limit(sptr, acptr, acptr->name))
+ continue;
+
+ if (!is_silenced(sptr, acptr))
+ {
+ if (!notice && MyConnect(sptr) &&
+ acptr->user && acptr->user->away)
+ sendto_one(sptr, rpl_str(RPL_AWAY), me.name,
+ parv[0], acptr->name,
+ acptr->user->away);
+ sendto_prefix_one(acptr, sptr, ":%s %s %s :%s",
+ parv[0], cmd, nick, parv[2]);
+ }
+ continue;
+ }
+
+ if (nick[0] == '@')
+ {
+
+ /*
+ * If its a message for all Channel OPs call the function
+ * sendto_channelops_butone() to handle it. -Cabal95
+ */
+ if ( nick[1] == '#' )
+ {
+ if (chptr = find_channel(nick+1, NullChn))
+ {
+ cansend = can_send(sptr, chptr, parv[2]);
+ if (cansend == 0)
+ if (check_for_chan_flood(cptr, sptr, chptr) == 1)
+ continue;
+ if (cansend == 0 || IsULine(cptr,sptr))
+ if (!(chptr->mode.mode & MODE_STRIP))
+ {
+ sendto_channelops_butone(cptr, sptr, chptr, ":%s %s %s :%s", parv[0], cmd, nick, parv[2]);
+ }
+ else
+ {
+ sendto_channelops_butone(cptr, sptr, chptr, ":%s %s %s :%s", parv[0], cmd, nick, StripColors(parv[2]));
+ }
+ else if (!notice)
+ sendto_one(sptr, err_str(ERR_CANNOTSENDTOCHAN), me.name, parv[0], nick+1, err_cantsend[cansend-1]);
+ }
+ else
+ sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], nick+1);
+ }
+
+ /*
+ * If its a message for all Channel ops and voices call the function
+ * sendto_channelvoice_butone() to handle it. -DuffJ
+ */
+ else if (nick[1] == '+' && nick[2] == '#')
+ {
+ if (chptr = find_channel(nick+2, NullChn))
+ {
+ cansend = can_send(sptr, chptr, parv[2]);
+ if (cansend == 0)
+ if (check_for_chan_flood(cptr, sptr, chptr) == 1)
+ continue;
+
+ if (cansend == 0 || IsULine(cptr,sptr))
+ if (!(chptr->mode.mode & MODE_STRIP))
+ sendto_channelvoice_butone(cptr, sptr, chptr, ":%s %s %s :%s", parv[0], cmd, nick, parv[2]);
+ else
+ sendto_channelvoice_butone(cptr, sptr, chptr, ":%s %s %s :%s", parv[0], cmd, nick, StripColors(parv[2]));
+ else if (!notice)
+ sendto_one(sptr, err_str(ERR_CANNOTSENDTOCHAN), me.name, parv[0], nick+2, err_cantsend[cansend-1]);
+ }
+ else sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], nick+2);
+ }
+ /*
+ * If its a message for all Channel ops and halfops call the function
+ * sendto_channelhalfop_butone() to handle it. -Stskeeps
+ */
+ else if ( nick[1] == '%' && nick[2] == '#' )
+ {
+ if (chptr = find_channel(nick+2, NullChn))
+ {
+ cansend = can_send(sptr, chptr, parv[2]);
+ if (cansend == 0)
+ if (check_for_chan_flood(cptr, sptr, chptr) == 1)
+ continue;
+
+ if (cansend == 0 || IsULine(cptr,sptr))
+ if (!(chptr->mode.mode & MODE_STRIP))
+ sendto_channelhalfop_butone(cptr, sptr, chptr, ":%s %s %s :%s", parv[0], cmd, nick, parv[2]);
+ else
+ sendto_channelhalfop_butone(cptr, sptr, chptr, ":%s %s %s :%s", parv[0], cmd, nick, StripColors(parv[2]));
+
+ else if (!notice)
+ sendto_one(sptr, err_str(ERR_CANNOTSENDTOCHAN), me.name, parv[0], nick+2, err_cantsend[cansend-1]);
+ }
+ else sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], nick+2);
+ }
+ continue;
+ }
+
+ /*
+ ** channel msg?
+ ** Now allows U-lined users to send to channel no problemo
+ ** -- Barubary
+ */
+ if ((chptr = find_channel(nick, NullChn)))
+ {
+ cansend = can_send(sptr, chptr, parv[2]);
+ if (cansend == 0)
+ if (check_for_chan_flood(cptr, sptr, chptr) == 1)
+ continue;
+
+ if (cansend == 0) {
+ if(MyClient(sptr) && check_for_target_limit(sptr, chptr, chptr->chname))
+ continue;
+ if (parv[2][0] == '`')
+ {
+ sendanyways = 1;
+ }
+ else sendanyways = 0;
+ if (!(chptr->mode.mode & MODE_STRIP))
+ sendto_channel_butone(cptr, sptr, chptr,
+ ":%s %s %s :%s",
+ parv[0], cmd, nick,
+ parv[2]);
+ else
+ sendto_channel_butone(cptr, sptr, chptr,
+ ":%s %s %s :%s",
+ parv[0], cmd, nick,
+ StripColors(parv[2]));
+
+ sendanyways = 0;
+ }
+ else if (!notice)
+ sendto_one(sptr, err_str(ERR_CANNOTSENDTOCHAN),
+ me.name, parv[0], nick, err_cantsend[cansend-1]);
+ continue;
+ }
+
+ /*
+ ** the following two cases allow masks in NOTICEs
+ ** (for OPERs only)
+ **
+ ** Armin, 8Jun90 (gruner@informatik.tu-muenchen.de)
+ */
+ if ((*nick == '$' || *nick == '#') && IsAnOper(sptr))
+ {
+ if (!(s = (char *)rindex(nick, '.')))
+ {
+ sendto_one(sptr, err_str(ERR_NOTOPLEVEL),
+ me.name, parv[0], nick);
+ continue;
+ }
+ while (*++s)
+ if (*s == '.' || *s == '*' || *s == '?')
+ break;
+ if (*s == '*' || *s == '?')
+ {
+ sendto_one(sptr, err_str(ERR_WILDTOPLEVEL),
+ me.name, parv[0], nick);
+ continue;
+ }
+ sendto_match_butone(IsServer(cptr) ? cptr : NULL,
+ sptr, nick + 1,
+ (*nick == '#') ? MATCH_HOST :
+ MATCH_SERVER,
+ ":%s %s %s :%s", parv[0],
+ cmd, nick, parv[2]);
+ continue;
+ }
+
+ /*
+ ** user[%host]@server addressed?
+ */
+ if ((server = (char *)index(nick, '@')) &&
+ (acptr = find_server(server + 1, NULL)))
+ {
+ /*
+ ** Not destined for a user on me :-(
+ */
+ if (!IsMe(acptr))
+ {
+ sendto_one(acptr,":%s %s %s :%s", parv[0],
+ cmd, nick, parv[2]);
+ continue;
+ }
+
+ /*
+ ** Find the nick@server using hash.
+ */
+ acptr = find_nickserv(nick, (aClient *)NULL);
+ if (acptr) {
+ sendto_prefix_one(acptr, sptr,
+ ":%s %s %s :%s",
+ parv[0], cmd,
+ acptr->name,
+ parv[2]);
+ continue;
+ }
+ }
+ if (server && strncasecmp(server+1, SERVICES_NAME,
+ strlen(SERVICES_NAME))==0)
+ sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name,
+ parv[0], nick);
+ else
+ sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name,
+ parv[0], nick);
+ }
+ return 0;
+}
+
+/*
+** m_private
+** parv[0] = sender prefix
+** parv[1] = receiver list
+** parv[2] = message text
+*/
+
+int m_private(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ return m_message(cptr, sptr, parc, parv, 0);
+}
+
+
+/*
+ * Built in services aliasing for ChanServ, Memoserv, NickServ and
+ * OperServ. This not only is an alias, but is also a security measure,
+ * because PRIVMSG's arent sent to 'ChanServ' they are now sent to
+ * 'ChanServ@Services.Network.Org' so nobody can snoop /cs commands :)
+ */
+
+int m_chanserv(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ aClient *acptr;
+
+ if (check_registered_user(sptr))
+ return 0;
+
+ if (parc < 2 || *parv[1] == '\0') {
+ sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]);
+ return -1;
+ }
+
+ if ((acptr = find_person(ChanServ, NULL)))
+ sendto_one(acptr,":%s PRIVMSG %s@%s :%s", parv[0],
+ ChanServ, SERVICES_NAME, parv[1]);
+ else
+ sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name,
+ parv[0], ChanServ);
+}
+
+int m_memoserv(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ aClient *acptr;
+
+ if (check_registered_user(sptr))
+ return 0;
+
+ if (parc < 2 || *parv[1] == '\0') {
+ sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]);
+ return -1;
+ }
+
+ if ((acptr = find_person(MemoServ, NULL)))
+ sendto_one(acptr,":%s PRIVMSG %s@%s :%s", parv[0],
+ MemoServ, SERVICES_NAME, parv[1]);
+ else
+ sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name,
+ parv[0], MemoServ);
+}
+
+int m_nickserv(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ aClient *acptr;
+
+ if (check_registered_user(sptr))
+ return 0;
+
+ if (parc < 2 || *parv[1] == '\0') {
+ sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]);
+ return -1;
+ }
+
+ if ((acptr = find_person(NickServ, NULL)))
+ sendto_one(acptr,":%s PRIVMSG %s@%s :%s", parv[0],
+ NickServ, SERVICES_NAME, parv[1]);
+ else
+ sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name,
+ parv[0], NickServ);
+}
+
+int m_operserv(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ aClient *acptr;
+
+ if (check_registered_user(sptr))
+ return 0;
+
+ if (parc < 2 || *parv[1] == '\0') {
+ sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]);
+ return -1;
+ }
+ if ((acptr = find_person(OperServ, NULL)))
+ sendto_one(acptr,":%s PRIVMSG %s@%s :%s", parv[0],
+ OperServ, SERVICES_NAME, parv[1]);
+ else
+ sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name,
+ parv[0], OperServ);
+}
+
+int m_helpserv(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ aClient *acptr;
+
+ if (check_registered_user(sptr))
+ return 0;
+
+ if (parc < 2 || *parv[1] == '\0') {
+ sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]);
+ return -1;
+ }
+
+ if ((acptr = find_person(HelpServ, NULL)))
+ sendto_one(acptr,":%s PRIVMSG %s@%s :%s", parv[0],
+ HelpServ, SERVICES_NAME, parv[1]);
+ else
+ sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name,
+ parv[0], HelpServ);
+}
+
+int m_statserv(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+
+ aClient *acptr;
+
+
+ if (check_registered_user(sptr))
+ return 0;
+
+ if (parc < 2 || *parv[1] == '\0') {
+ sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]);
+ return -1;
+ }
+
+ if ((acptr = find_person(StatServ, NULL)))
+#ifndef STATSERV_ABSOLUTE
+ if (!strncmp(acptr->srvptr->name, STATS_SERVER, strlen(STATS_SERVER)))
+ {
+ sendto_one(acptr,":%s PRIVMSG %s :%s", parv[0],
+ StatServ, parv[1]);
+ }
+ else
+ {
+ sendto_one(sptr, ":%s NOTICE %s :*** Couldn't send to %s due to my setting of StatServ is not equal to what server it is on", me.name, sptr->name,
+ StatServ);
+ return;
+ }
+#else
+ sendto_one(acptr,":%s PRIVMSG %s@%s :%s", parv[0],
+ StatServ, STATS_SERVER, parv[1]);
+#endif
+ else
+ sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name,
+ parv[0], StatServ);
+}
+
+
+/*
+ * Automatic NickServ/ChanServ direction for the identify command
+ * -taz
+ */
+int m_identify(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ aClient *acptr;
+
+ if (check_registered_user(sptr))
+ return 0;
+
+ if (parc < 2 || *parv[1] == '\0') {
+ sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]);
+ return -1;
+ }
+
+ if (*parv[1]) {
+ if((*parv[1] == '#') && ((char *)index(parv[1], ' '))) {
+ if ((acptr = find_person(ChanServ, NULL)))
+ sendto_one(acptr,":%s PRIVMSG %s@%s :IDENTIFY %s", parv[0],
+ ChanServ, SERVICES_NAME, parv[1]);
+ else
+ sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name,
+ parv[0], ChanServ);
+ } else {
+ if ((acptr = find_person(NickServ, NULL)))
+ sendto_one(acptr,":%s PRIVMSG %s@%s :IDENTIFY %s", parv[0],
+ NickServ, SERVICES_NAME, parv[1]);
+ else
+ sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name,
+ parv[0], NickServ);
+ }
+ }
+}
+
+/*
+ * Automatic NickServ/ChanServ parsing. If the second word of parv[1]
+ * starts with a '#' this message goes to ChanServ. If it starts with
+ * anything else, it goes to NickServ. If there is no second word in
+ * parv[1], the message defaultly goes to NickServ. If parv[1] == 'help'
+ * the user in instructed to /cs, /ns or /ms HELP for the help they need.
+ * -taz
+ */
+
+int m_services(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ aClient *acptr;
+ char *tmps;
+
+ if (check_registered_user(sptr))
+ return 0;
+
+ if (parc < 2 || *parv[1] == '\0') {
+ sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]);
+ return -1;
+ }
+
+ if ((strlen(parv[1])>=4) && (!strncmp(parv[1], "help", 4))) {
+ sendto_one(sptr, ":Services!Services@%s NOTICE %s :For ChanServ help use: /chanserv help", SERVICES_NAME, sptr->name);
+ sendto_one(sptr, ":Services!Services@%s NOTICE %s :For NickServ help use: /nickserv help", SERVICES_NAME, sptr->name);
+ sendto_one(sptr, ":Services!Services@%s NOTICE %s :For MemoServ help use: /memoserv help", SERVICES_NAME, sptr->name);
+ sendto_one(sptr, ":Services!Services@%s NOTICE %s :For HelpServ help use: /helpserv help", SERVICES_NAME, sptr->name);
+
+ return;
+ }
+
+ if ((tmps = (char *)index(parv[1], ' '))) {
+ tmps++;
+ if(*tmps == '#')
+ return m_chanserv(cptr, sptr, parc, parv);
+ else
+ return m_nickserv(cptr, sptr, parc, parv);
+ }
+
+ return m_nickserv(cptr, sptr, parc, parv);
+
+}
+
+/*
+** m_notice
+** parv[0] = sender prefix
+** parv[1] = receiver list
+** parv[2] = notice text
+*/
+
+int m_notice(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ if (!IsRegistered(cptr) && (cptr->name[0]) && !IsNotSpoof(cptr))
+ {
+ if (BadPtr(parv[1])) return 0;
+#ifdef NOSPOOF
+ if (strtoul(parv[1], NULL, 16) != cptr->nospoof)
+ goto temp;
+ sptr->nospoof = 0;
+#endif
+ if (sptr->user && sptr->name[0])
+ return register_user(cptr, sptr, sptr->name,
+ sptr->user->username, NULL, NULL);
+ return 0;
+ }
+ temp:
+ return m_message(cptr, sptr, parc, parv, 1);
+}
+
+int channelwho = 0;
+
+static void do_who(sptr, acptr, repchan)
+aClient *sptr, *acptr;
+aChannel *repchan;
+{
+ char status[5];
+ int i = 0;
+
+ if (acptr->user->away)
+ status[i++] = 'G';
+ else
+ status[i++] = 'H';
+ /* Check for +H here too -- codemastr */
+ if (IsAnOper(acptr) && !IsHideOper(acptr))
+ status[i++] = '*';
+ else if (IsInvisible(acptr) && sptr != acptr && IsAnOper(sptr))
+ status[i++] = '%';
+ if (repchan && is_chan_op(acptr, repchan))
+ status[i++] = '@';
+ else if (repchan && has_voice(acptr, repchan))
+ status[i++] = '+';
+ status[i] = '\0';
+ if (IsWhois(acptr) && channelwho == 0) {
+ sendto_one(acptr, ":%s NOTICE %s :*** %s either did a /who or a specific /who on you", me.name, acptr->name, sptr->name);
+ }
+ sendto_one(sptr, rpl_str(RPL_WHOREPLY), me.name, sptr->name,
+ (repchan) ? (repchan->chname) : "*", acptr->user->username,
+ IsHidden(acptr) ? acptr->user->virthost : acptr->user->realhost, acptr->user->server, acptr->name,
+ status, acptr->hopcount, acptr->info);
+
+}
+
+
+/*
+** m_who
+** parv[0] = sender prefix
+** parv[1] = nickname mask list
+** parv[2] = additional selection flag, only 'o' for now.
+*/
+int m_who(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ Reg1 aClient *acptr;
+ Reg2 char *mask = parc > 1 ? parv[1] : NULL;
+ Reg3 Link *lp;
+ aChannel *chptr;
+ aChannel *mychannel;
+ char *channame = NULL, *s;
+ int oper = parc > 2 ? (*parv[2] == 'o' ): 0; /* Show OPERS only */
+ int member;
+
+ if (check_registered_user(sptr))
+ return 0;
+
+ if (!BadPtr(mask))
+ {
+ if ((s = (char *)index(mask, ',')))
+ {
+ parv[1] = ++s;
+ (void)m_who(cptr, sptr, parc, parv);
+ }
+ clean_channelname(mask);
+ }
+ channelwho = 0;
+ mychannel = NullChn;
+ if (oper) {
+ sendto_helpops("from %s: [Did a /who 0 o]", parv[0]);
+ sendto_serv_butone(&me, ":%s HELP :[Did a /who 0 o]", parv[0]);
+ }
+ if (sptr->user)
+ if ((lp = sptr->user->channel))
+ mychannel = lp->value.chptr;
+
+ /* Allow use of m_who without registering */
+
+ /*
+ ** Following code is some ugly hacking to preserve the
+ ** functions of the old implementation. (Also, people
+ ** will complain when they try to use masks like "12tes*"
+ ** and get people on channel 12 ;) --msa
+ */
+ if (!mask || *mask == '\0')
+ mask = NULL;
+ else if (mask[1] == '\0' && mask[0] == '*')
+ {
+ mask = NULL;
+ if (mychannel)
+ channame = mychannel->chname;
+ }
+ else if (mask[1] == '\0' && mask[0] == '0') /* "WHO 0" for irc.el */
+ mask = NULL;
+ else
+ channame = mask;
+ (void)collapse(mask);
+
+ if (IsChannelName(channame))
+ {
+ /*
+ * List all users on a given channel
+ */
+ chptr = find_channel(channame, NULL);
+ if (chptr)
+ {
+ member = IsMember(sptr, chptr);
+ if (member || !SecretChannel(chptr))
+ for (lp = chptr->members; lp; lp = lp->next)
+ {
+ if (oper && (!IsAnOper(lp->value.cptr) || IsHideOper(lp->value.cptr)))
+ continue;
+ if (IsHiding(lp->value.cptr) && !(IsNetAdmin(sptr) || IsTechAdmin(sptr)))
+ continue;
+ if (lp->value.cptr!=sptr && IsInvisible(lp->value.cptr) && !member)
+ continue;
+ channelwho = 1;
+ do_who(sptr, lp->value.cptr, chptr);
+ }
+ }
+ }
+ else for (acptr = client; acptr; acptr = acptr->next)
+ {
+ aChannel *ch2ptr = NULL;
+ int showperson, isinvis;
+
+ if (!IsPerson(acptr))
+ continue;
+ if (oper && (!IsAnOper(acptr) || IsHideOper(acptr)))
+ continue;
+ showperson = 0;
+ /*
+ * Show user if they are on the same channel, or not
+ * invisible and on a non secret channel (if any).
+ * Do this before brute force match on all relevant fields
+ * since these are less cpu intensive (I hope :-) and should
+ * provide better/more shortcuts - avalon
+ */
+ isinvis = acptr!=sptr && IsInvisible(acptr) && !IsAnOper(sptr);
+ for (lp = acptr->user->channel; lp; lp = lp->next)
+ {
+ chptr = lp->value.chptr;
+ member = IsMember(sptr, chptr);
+ if (isinvis && !member)
+ continue;
+ if (IsAnOper(sptr)) showperson = 1;
+ if (member || (!isinvis &&
+ ShowChannel(sptr, chptr)))
+ {
+ ch2ptr = chptr;
+ showperson = 1;
+ break;
+ }
+ if (HiddenChannel(chptr) && !SecretChannel(chptr) &&
+ !isinvis)
+ showperson = 1;
+ }
+ if (!acptr->user->channel && !isinvis)
+ showperson = 1;
+ /*
+ ** This is brute force solution, not efficient...? ;(
+ ** Show entry, if no mask or any of the fields match
+ ** the mask. --msa
+ */
+ if (showperson &&
+ (!mask ||
+ match(mask, acptr->name) == 0 ||
+ match(mask, acptr->user->username) == 0 ||
+ (!IsAnOper(sptr) || match(mask, acptr->user->realhost)) == 0 ||
+ (!IsHidden(acptr) || match(mask, acptr->user->virthost)) == 0 ||
+ (IsHidden(acptr) || match(mask, acptr->user->realhost)) == 0 ||
+ match(mask, acptr->user->server) == 0 ||
+ match(mask, acptr->info) == 0))
+ do_who(sptr, acptr, ch2ptr);
+ }
+ sendto_one(sptr, rpl_str(RPL_ENDOFWHO), me.name, parv[0],
+ BadPtr(mask) ? "*" : mask);
+ return 0;
+}
+
+/*
+** get_mode_str
+** by vmlinuz
+** returns an ascii string of modes
+*/
+char *get_mode_str (aClient *acptr)
+{
+ Reg1 int flag;
+ Reg2 int *s;
+ Reg3 char *m;
+
+ m = buf;
+ *m++ = '+';
+ for (s = user_modes; (flag = *s) && (m - buf < BUFSIZE - 4);
+ s += 2)
+ if ((acptr->umodes & flag))
+ *m++ = (char)(*(s+1));
+ *m = '\0';
+ return buf;
+}
+
+/*
+** m_whois
+** parv[0] = sender prefix
+** parv[1] = nickname masklist
+*/
+int m_whois(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ static anUser UnknownUser =
+ {
+ NULL, /* nextu */
+ NULL, /* channel */
+ NULL, /* invited */
+ NULL, /* silence */
+ NULL, /* away */
+ 0, /* last */
+ 0, /* servicestamp */
+ 1, /* refcount */
+ 0, /* joined */
+ "<Unknown>", /* username */
+ "<Unknown>", /* host */
+ "<Unknown>" /* server */
+ };
+ Reg2 Link *lp;
+ Reg3 anUser *user;
+ aClient *acptr, *a2cptr;
+ aChannel *chptr;
+ char *nick, *tmp, *name, *temp;
+ char *p = NULL;
+ int found, len, mlen, t;
+
+
+ if (check_registered_user(sptr))
+ return 0;
+
+ if (parc < 2)
+ {
+ sendto_one(sptr, err_str(ERR_NONICKNAMEGIVEN),
+ me.name, parv[0]);
+ return 0;
+ }
+
+ if (parc > 2)
+ {
+ if (hunt_server(cptr,sptr,":%s WHOIS %s :%s", 1,parc,parv) !=
+ HUNTED_ISME)
+ return 0;
+ parv[1] = parv[2];
+ }
+
+ for (tmp = parv[1]; (nick = strtoken(&p, tmp, ",")); tmp = NULL)
+ {
+ int invis, showperson, member, wilds;
+
+ found = 0;
+ (void)collapse(nick);
+ wilds = (index(nick, '?') || index(nick, '*'));
+ if (wilds) continue;
+
+ for (acptr = client; (acptr = next_client(acptr, nick));
+ acptr = acptr->next)
+ {
+ if (IsServer(acptr))
+ continue;
+ /*
+ * I'm always last :-) and acptr->next == NULL!!
+ */
+ if (IsMe(acptr))
+ break;
+ /*
+ * 'Rules' established for sending a WHOIS reply:
+ *
+ * - only allow a remote client to get replies for
+ * local clients if wildcards are being used;
+ *
+ * - if wildcards are being used dont send a reply if
+ * the querier isnt any common channels and the
+ * client in question is invisible and wildcards are
+ * in use (allow exact matches only);
+ *
+ * - only send replies about common or public channels
+ * the target user(s) are on;
+ */
+ if (!MyConnect(sptr) && !MyConnect(acptr) && wilds)
+ continue;
+ user = acptr->user ? acptr->user : &UnknownUser;
+ name = (!*acptr->name) ? "?" : acptr->name;
+
+ invis = acptr!=sptr && IsInvisible(acptr);
+ member = (user->channel) ? 1 : 0;
+ showperson = (wilds && !invis && !member) || !wilds;
+
+ for (lp = user->channel; lp; lp = lp->next)
+ {
+ chptr = lp->value.chptr;
+ member = IsMember(sptr, chptr);
+ if (invis && !member)
+ continue;
+ if (member || (!invis && PubChannel(chptr)))
+ {
+ showperson = 1;
+ break;
+ }
+ if (!invis && HiddenChannel(chptr) &&
+ !SecretChannel(chptr))
+ showperson = 1;
+ }
+ if (!showperson)
+ continue;
+ a2cptr = find_server(user->server, NULL);
+
+ if (!IsPerson(acptr))
+ continue;
+
+ if (IsWhois(acptr)) {
+ sendto_one(acptr, ":%s NOTICE %s :*** %s (%s@%s) did a /whois on you.",
+ me.name, acptr->name,
+ sptr->name, sptr->user->username,
+ IsHidden(acptr) ? sptr->user->virthost : sptr->user->realhost);
+ }
+
+ sendto_one(sptr, rpl_str(RPL_WHOISUSER), me.name,
+ parv[0], name,
+ user->username, IsHidden(acptr) ? user->virthost : user->realhost,
+ acptr->info);
+
+ if (IsEyes(sptr))
+ {
+ /* send the target user's modes */
+ sendto_one(sptr, rpl_str(RPL_WHOISMODES),
+ me.name, parv[0], name,
+ get_mode_str(acptr));
+ }
+ if (IsAnOper(sptr) && IsHidden(acptr) ||
+ acptr == sptr && IsHidden(sptr)) {
+ sendto_one(sptr, rpl_str(RPL_WHOISHOST), me.name,
+ parv[0], acptr->name, acptr->user->realhost);
+ }
+ if (IsARegNick(acptr))
+ sendto_one(sptr, rpl_str(RPL_WHOISREGNICK),
+ me.name, parv[0], name);
+ found = 1;
+ mlen = strlen(me.name) + strlen(parv[0]) + 6 +
+ strlen(name);
+ for (len = 0, *buf = '\0', lp = user->channel; lp;
+ lp = lp->next)
+ {
+ chptr = lp->value.chptr;
+ if (ShowChannel(sptr, chptr) &&
+ (acptr==sptr || IsMember(acptr, chptr)))
+ {
+ if (len + strlen(chptr->chname)
+ > (size_t) BUFSIZE - 4 - mlen)
+ {
+ sendto_one(sptr,
+ ":%s %d %s %s :%s",
+ me.name,
+ RPL_WHOISCHANNELS,
+ parv[0], name, buf);
+ *buf = '\0';
+ len = 0;
+ }
+ if (is_chanowner(acptr, chptr))
+ *(buf + len++) = '*';
+ else if (is_chanprot(acptr, chptr))
+ *(buf + len++) = '^';
+ else if (is_chan_op(acptr, chptr))
+ *(buf + len++) = '@';
+ else if (has_voice(acptr, chptr))
+ *(buf + len++) = '+';
+ else if (is_half_op(acptr, chptr))
+ *(buf + len++) = '%';
+ if (len)
+ *(buf + len) = '\0';
+ (void)strcpy(buf + len, chptr->chname);
+ len += strlen(chptr->chname);
+ (void)strcat(buf + len, " ");
+ len++;
+ }
+ }
+
+ if (IsULine(acptr, acptr))
+ goto next;
+
+ if (IsHiding(acptr) && sptr != acptr && !IsNetAdmin(sptr) && !IsTechAdmin(sptr))
+ goto next;
+
+ if (buf[0] != '\0')
+ sendto_one(sptr, rpl_str(RPL_WHOISCHANNELS),
+ me.name, parv[0], name, buf);
+
+ next:
+ sendto_one(sptr, rpl_str(RPL_WHOISSERVER),
+ me.name, parv[0], name, user->server,
+ a2cptr?a2cptr->info:"*Not On This Net*");
+
+ if (user->away)
+ sendto_one(sptr, rpl_str(RPL_AWAY), me.name,
+ parv[0], name, user->away);
+ /* makesure they aren't +H (we'll also check
+ before we display a helpop or IRCD Coder msg)
+ -- codemastr */
+ if ((IsAnOper(acptr) || IsServices(acptr)) && !IsHideOper(acptr)) {
+ buf[0]='\0';
+ if (IsNetAdmin(acptr))
+ strcat(buf, "a Network Administrator");
+ else if (IsTechAdmin(acptr))
+ strcat(buf, "a Technical Administrator");
+ else if (IsSAdmin(acptr))
+ strcat(buf, "a Services Operator");
+ else if (IsAdmin(acptr) && !IsCoAdmin(acptr))
+ strcat(buf, "a Server Administrator");
+ else if (IsCoAdmin(acptr))
+ strcat(buf, "a Co Administrator");
+ else if (IsServices(acptr))
+ strcat(buf, "a Network Service");
+ else if (IsOper(acptr))
+ strcat(buf, "an IRC Operator");
+
+ else
+ strcat(buf, "a Local IRC Operator");
+ if(buf[0])
+ sendto_one(sptr, rpl_str(RPL_WHOISOPERATOR),
+ me.name, parv[0], name, buf, ircnetwork);
+ }
+
+ if (IsHelpOp(acptr) && !IsHideOper(acptr))
+ if (!acptr->user->away)
+ sendto_one(sptr, rpl_str(RPL_WHOISHELPOP),
+ me.name, parv[0], name);
+
+ if (acptr->umodes & UMODE_BOT) {
+ sendto_one(sptr, rpl_str(RPL_WHOISBOT),
+ me.name, parv[0], name, ircnetwork);
+ }
+ if (acptr->umodes & UMODE_CODER && !IsHideOper(acptr)) {
+ sendto_one(sptr, rpl_str(RPL_WHOISOPERATOR),
+ me.name, parv[0], name, "a \2Coder\2", ircnetwork);
+ }
+ if (acptr->user->swhois)
+ {
+ if (*acptr->user->swhois != '\0')
+ sendto_one(sptr, ":%s %d %s %s :%s", me.name,
+ RPL_WHOISSPECIAL,
+ parv[0], name,
+ acptr->user->swhois);
+ }
+
+ if (acptr->user && MyConnect(acptr))
+ sendto_one(sptr, rpl_str(RPL_WHOISIDLE),
+ me.name, parv[0], name,
+ TStime() - user->last,
+ acptr->firsttime);
+ }
+ if (!found)
+ sendto_one(sptr, err_str(ERR_NOSUCHNICK),
+ me.name, parv[0], nick);
+ if (p)
+ p[-1] = ',';
+ }
+ sendto_one(sptr, rpl_str(RPL_ENDOFWHOIS), me.name, parv[0], parv[1]);
+
+ return 0;
+}
+
+/*
+** m_user
+** parv[0] = sender prefix
+** parv[1] = username (login name, account)
+** parv[2] = client host name (used only from other servers)
+** parv[3] = server host name (used only from other servers)
+** parv[4] = users real name info
+*/
+int m_user(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+#define UFLAGS (UMODE_INVISIBLE|UMODE_WALLOP|UMODE_SERVNOTICE)
+ char *username, *host, *server, *realname, *umodex = NULL, *virthost = NULL;
+ u_int32_t sstamp = 0;
+ anUser *user;
+ char *mparv[] = {sptr->name, sptr->name, NULL};
+
+ if (IsServer(cptr) && !IsUnknown(sptr))
+ return 0;
+
+ if (parc > 2 && (username = (char *)index(parv[1],'@')))
+ *username = '\0';
+ if (parc < 5 || *parv[1] == '\0' || *parv[2] == '\0' ||
+ *parv[3] == '\0' || *parv[4] == '\0')
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "USER");
+ if (IsServer(cptr))
+ sendto_ops("bad USER param count for %s from %s",
+ parv[0], get_client_name(cptr, FALSE));
+ else
+ return 0;
+ }
+
+ /* Copy parameters into better documenting variables */
+
+ username = (parc < 2 || BadPtr(parv[1])) ? "<bad-boy>" : parv[1];
+ host = (parc < 3 || BadPtr(parv[2])) ? "<nohost>" : parv[2];
+ server = (parc < 4 || BadPtr(parv[3])) ? "<noserver>" : parv[3];
+
+ /* This we can remove as soon as all servers have upgraded. */
+
+ if (parc == 6 && IsServer(cptr)) {
+ if (isdigit(*parv[4]))
+ sstamp = atol(parv[4]);
+ realname = (BadPtr(parv[5])) ? "<bad-realname>" : parv[5];
+ umodex = NULL;
+ } else if (parc == 8 && IsServer(cptr))
+ {
+ if (isdigit(*parv[4]))
+ sstamp = atol(parv[4]);
+ realname = (BadPtr(parv[7])) ? "<bad-realname>" : parv[7];
+ umodex = parv[5];
+ virthost = parv[6];
+ } else
+ {
+ realname = (BadPtr(parv[4])) ? "<bad-realname>" : parv[4];
+ }
+ user = make_user(sptr);
+
+ if (!MyConnect(sptr))
+ {
+ if (sptr->srvptr == NULL)
+ sendto_ops("WARNING, User %s introduced as being "
+ "on non-existant server %s.", sptr->name,
+ server);
+ strncpyzt(user->server, server, sizeof(user->server));
+ strncpyzt(user->realhost, host, sizeof(user->realhost));
+ strncpyzt(user->realhost, host, sizeof(user->realhost));
+ goto user_finish;
+ }
+
+ if (!IsUnknown(sptr))
+ {
+ sendto_one(sptr, err_str(ERR_ALREADYREGISTRED),
+ me.name, parv[0]);
+ return 0;
+ }
+ if (!IsServer(cptr))
+ {
+ if (MODE_I == 1)
+ sptr->umodes |= UMODE_INVISIBLE;
+ if (MODE_X == 1) {
+ sptr->umodes |= (UMODE_HIDE);
+ SetHidden(sptr);
+ }
+ }
+
+ sptr->umodes |= (UFLAGS & atoi(host));
+
+ strncpyzt(user->realhost, host, sizeof(user->realhost));
+ strncpyzt(user->realhost, host, sizeof(user->realhost));
+ strncpyzt(user->server, me.name, sizeof(user->server));
+user_finish:
+ user->servicestamp = sstamp;
+ strncpyzt(sptr->info, realname, sizeof(sptr->info));
+ if (sptr->name[0] && (IsServer(cptr) ? 1 : IsNotSpoof(sptr)))
+ /* NICK and no-spoof already received, now we have USER... */
+ {
+ int xx;
+
+ xx = register_user(cptr, sptr, sptr->name, username, umodex, virthost);
+ return xx;
+ }
+ else
+ strncpyzt(sptr->user->username, username, USERLEN+1);
+
+ return 0;
+}
+
+/*
+** m_quit
+** parv[0] = sender prefix
+** parv[1] = comment
+*/
+int m_quit(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ char *ocomment = (parc > 1 && parv[1]) ? parv[1] : parv[0];
+ static char comment[TOPICLEN];
+
+ if (!IsServer(cptr)) {
+ sprintf(comment, "Quit: ");
+ strncpy(comment+6,ocomment,TOPICLEN-7);
+ comment[TOPICLEN] = '\0';
+ return exit_client(cptr, sptr, sptr, comment);
+ } else
+ return exit_client(cptr, sptr, sptr, ocomment);
+ }
+
+
+/*
+** m_kill
+** parv[0] = sender prefix
+** parv[1] = kill victim(s) - comma separated list
+** parv[2] = kill path
+*/
+int m_kill(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ static anUser UnknownUser =
+ {
+ NULL, /* nextu */
+ NULL, /* channel */
+ NULL, /* invited */
+ NULL, /* silence */
+ NULL, /* away */
+ 0, /* last */
+ 0, /* servicestamp */
+ 1, /* refcount */
+ 0, /* joined */
+ "<Unknown>", /* username */
+ "<Unknown>", /* host */
+ "<Unknown>" /* server */
+ };
+ aClient *acptr;
+ anUser *auser;
+ char inpath[HOSTLEN * 2 + USERLEN + 5];
+ char *oinpath = get_client_name(cptr,FALSE);
+ char *user, *path, *killer, *nick, *p, *s;
+ int chasing = 0, kcount = 0;
+
+
+ if (check_registered(sptr))
+ return 0;
+
+ if (parc < 2 || *parv[1] == '\0')
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "KILL");
+ return 0;
+ }
+
+ user = parv[1];
+ path = parv[2]; /* Either defined or NULL (parc >= 2!!) */
+
+ strcpy(inpath, oinpath);
+
+#ifndef ROXnet
+ if (IsServer(cptr) && (s = (char *)index(inpath, '.')) != NULL)
+ *s = '\0'; /* Truncate at first "." */
+#endif
+
+ if (!IsPrivileged(cptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ if (IsAnOper(cptr))
+ {
+ if (BadPtr(path))
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "KILL");
+ return 0;
+ }
+ if (strlen(path) > (size_t) TOPICLEN)
+ path[TOPICLEN] = '\0';
+ }
+
+ if (MyClient(sptr))
+ user = canonize(user);
+
+ for (p = NULL, nick = strtoken(&p, user, ","); nick;
+ nick = strtoken(&p, NULL, ","))
+ {
+
+ chasing = 0;
+
+ if (!(acptr = find_client(nick, NULL)))
+ {
+ /*
+ ** If the user has recently changed nick, we automaticly
+ ** rewrite the KILL for this new nickname--this keeps
+ ** servers in synch when nick change and kill collide
+ */
+ if (!(acptr = get_history(nick, (long)KILLCHASETIMELIMIT)))
+ {
+ sendto_one(sptr, err_str(ERR_NOSUCHNICK),
+ me.name, parv[0], nick);
+ continue;
+ }
+ sendto_one(sptr,":%s NOTICE %s :KILL changed from %s to %s",
+ me.name, parv[0], nick, acptr->name);
+ chasing = 1;
+ }
+ if ((!MyConnect(acptr) && MyClient(cptr) && !OPCanGKill(cptr)) ||
+ (MyConnect(acptr) && MyClient(cptr) && !OPCanLKill(cptr)))
+ {
+ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
+ continue;
+ }
+ if (IsServer(acptr) || IsMe(acptr))
+ {
+ sendto_one(sptr, err_str(ERR_CANTKILLSERVER),
+ me.name, parv[0]);
+ continue;
+ }
+
+ if (IsServices(acptr) && !(IsNetAdmin(sptr) || IsTechAdmin(sptr) || IsULine(cptr, sptr)))
+ {
+ sendto_one(sptr, err_str(ERR_KILLDENY), me.name, parv[0], parv[1]);
+ return 0;
+ }
+/* if (IsULine(cptr, sptr) || (IsSAdmin(sptr) && !IsSAdmin(acptr)) || (IsNetAdmin(sptr)) || (IsTechAdmin(sptr) || (IsCoAdmin(sptr)))) {
+ goto aftermath;
+ } else if (IsULine(cptr, acptr)) {
+ goto error;
+ } else {
+ goto aftermath;
+ }
+
+ error:
+
+ return 0;
+*/
+ aftermath:
+
+ /* From here on, the kill is probably going to be successful. */
+
+ kcount++;
+
+ if (!IsServer(sptr) && (kcount > MAXKILLS))
+ {
+ sendto_one(sptr,":%s NOTICE %s :Too many targets, kill list was truncated. Maximum is %d.",me.name, parv[0], MAXKILLS);
+ break;
+ }
+ if (!IsServer(cptr))
+ {
+ /*
+ ** The kill originates from this server, initialize path.
+ ** (In which case the 'path' may contain user suplied
+ ** explanation ...or some nasty comment, sigh... >;-)
+ **
+ ** ...!operhost!oper
+ ** ...!operhost!oper (comment)
+ */
+ if (IsUnixSocket(cptr)) /* Don't use get_client_name syntax */
+ strcpy(inpath, me.name);
+ else
+ strcpy(inpath, IsHidden(cptr) ? cptr->user->virthost : cptr->user->realhost);
+ if (kcount < 2) /* Only check the path the first time
+ around, or it gets appended to itself. */
+ if (!BadPtr(path))
+ {
+ (void)sprintf(buf, "%s%s (%s)",
+ cptr->name, IsOper(sptr) ? "" : "(L)", path);
+ path = buf;
+ }
+ else
+ path = cptr->name;
+ }
+ else if (BadPtr(path))
+ path = "*no-path*"; /* Bogus server sending??? */
+ /*
+ ** Notify all *local* opers about the KILL (this includes the one
+ ** originating the kill, if from this server--the special numeric
+ ** reply message is not generated anymore).
+ **
+ ** Note: "acptr->name" is used instead of "user" because we may
+ ** have changed the target because of the nickname change.
+ */
+
+ auser = acptr->user ? acptr->user : &UnknownUser;
+
+ if (index(parv[0], '.'))
+ sendto_umode(UMODE_KILLS, "*** Notice -- Received KILL message for %s!%s@%s from %s Path: %s!%s",
+ acptr->name, auser->username,
+ IsHidden(acptr) ? auser->virthost : auser->realhost,
+ parv[0], inpath, path);
+#ifdef SHOWREALHOSTATKILL
+ sendto_umode(UMODE_EYES, "*** /kill victim was %s!%s@%s", acptr->name, auser->username, auser->realhost);
+#endif
+ else
+ sendto_umode(UMODE_KILLS, "*** Notice -- Received KILL message for %s!%s@%s from %s Path: %s!%s",
+ acptr->name, auser->username,
+ IsHidden(acptr) ? auser->virthost : auser->realhost,
+ parv[0], inpath, path);
+#if defined(USE_SYSLOG) && defined(SYSLOG_KILL)
+ if (IsOper(sptr))
+ syslog(LOG_DEBUG,"KILL From %s For %s Path %s!%s",
+ parv[0], acptr->name, inpath, path);
+#endif
+ /*
+ ** And pass on the message to other servers. Note, that if KILL
+ ** was changed, the message has to be sent to all links, also
+ ** back.
+ ** Suicide kills are NOT passed on --SRB
+ */
+ if (!MyConnect(acptr) || !MyConnect(sptr) || !IsAnOper(sptr))
+ {
+ sendto_serv_butone(cptr, ":%s KILL %s :%s!%s",
+ parv[0], acptr->name, inpath, path);
+ if (chasing && IsServer(cptr))
+ sendto_one(cptr, ":%s KILL %s :%s!%s",
+ me.name, acptr->name, inpath, path);
+ acptr->flags |= FLAGS_KILLED;
+ }
+
+ /*
+ ** Tell the victim she/he has been zapped, but *only* if
+ ** the victim is on current server--no sense in sending the
+ ** notification chasing the above kill, it won't get far
+ ** anyway (as this user don't exist there any more either)
+ */
+ if (MyConnect(acptr))
+ sendto_prefix_one(acptr, sptr,":%s KILL %s :%s!%s",
+ parv[0], acptr->name, inpath, path);
+ /*
+ ** Set FLAGS_KILLED. This prevents exit_one_client from sending
+ ** the unnecessary QUIT for this. (This flag should never be
+ ** set in any other place)
+ */
+ if (MyConnect(acptr) && MyConnect(sptr) && IsAnOper(sptr))
+ (void)sprintf(buf2, "[%s] Local kill by %s (%s)", me.name, sptr->name,
+ BadPtr(parv[2]) ? sptr->name : parv[2]);
+ else
+ {
+ if ((killer = index(path, ' ')))
+ {
+ while (*killer && *killer != '!')
+ killer--;
+ if (!*killer)
+ killer = path;
+ else
+ killer++;
+ }
+ else
+ killer = path;
+ (void)sprintf(buf2, "Killed (%s)", killer);
+ }
+ if(exit_client(cptr, acptr, sptr, buf2) == FLUSH_BUFFER)
+ return FLUSH_BUFFER;
+ }
+ return 0;
+}
+
+/***********************************************************************
+ * m_away() - Added 14 Dec 1988 by jto.
+ * Not currently really working, I don't like this
+ * call at all...
+ *
+ * ...trying to make it work. I don't like it either,
+ * but perhaps it's worth the load it causes to net.
+ * This requires flooding of the whole net like NICK,
+ * USER, MODE, etc messages... --msa
+ ***********************************************************************/
+
+/*
+** m_away
+** parv[0] = sender prefix
+** parv[1] = away message
+*/
+int m_away(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ Reg1 char *away, *awy2 = parv[1];
+
+ if (check_registered_user(sptr))
+ return 0;
+
+ away = sptr->user->away;
+ if (parc < 2 || !*awy2)
+ {
+ /* Marking as not away */
+
+ if (away)
+ {
+ MyFree(away);
+ sptr->user->away = NULL;
+ }
+ sendto_serv_butone(cptr, ":%s AWAY", parv[0]);
+ if (MyConnect(sptr))
+ sendto_one(sptr, rpl_str(RPL_UNAWAY),
+ me.name, parv[0]);
+ return 0;
+ }
+
+ /* Marking as away */
+
+ if (strlen(awy2) > (size_t) TOPICLEN)
+ awy2[TOPICLEN] = '\0';
+
+ if (away)
+ if (strcmp(away, parv[1])==0)
+ {
+ return 0;
+ }
+ sendto_serv_butone(cptr, ":%s AWAY :%s", parv[0], awy2);
+
+ if (away)
+ away = (char *)MyRealloc(away, strlen(awy2)+1);
+ else
+ away = (char *)MyMalloc(strlen(awy2)+1);
+
+ sptr->user->away = away;
+ (void)strcpy(away, awy2);
+ if (MyConnect(sptr))
+ sendto_one(sptr, rpl_str(RPL_NOWAWAY), me.name, parv[0]);
+ return 0;
+}
+
+/*
+** m_ping
+** parv[0] = sender prefix
+** parv[1] = origin
+** parv[2] = destination
+*/
+int m_ping(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ aClient *acptr;
+ char *origin, *destination;
+
+ if (check_registered(sptr))
+ return 0;
+
+ if (parc < 2 || *parv[1] == '\0')
+ {
+ sendto_one(sptr, err_str(ERR_NOORIGIN), me.name, parv[0]);
+ return 0;
+ }
+ origin = parv[1];
+ destination = parv[2]; /* Will get NULL or pointer (parc >= 2!!) */
+
+ acptr = find_client(origin, NULL);
+ if (!acptr)
+ acptr = find_server(origin, NULL);
+ if (acptr && acptr != sptr)
+ origin = cptr->name;
+ if (!BadPtr(destination) && mycmp(destination, me.name) != 0)
+ {
+ if ((acptr = find_server(destination, NULL)))
+ sendto_one(acptr,":%s PING %s :%s", parv[0],
+ origin, destination);
+ else
+ {
+ sendto_one(sptr, err_str(ERR_NOSUCHSERVER),
+ me.name, parv[0], destination);
+ return 0;
+ }
+ }
+ else
+ sendto_one(sptr,":%s PONG %s :%s", me.name,
+ (destination) ? destination : me.name, origin);
+ return 0;
+ }
+
+#ifdef NOSPOOF
+/*
+** m_nospoof - allows clients to respond to no spoofing patch
+** parv[0] = prefix
+** parv[1] = code
+*/
+int m_nospoof(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+unsigned long result;
+
+ if (IsNotSpoof(cptr)) return 0;
+ if (IsRegistered(cptr)) return 0;
+ if (!*sptr->name) return 0;
+ if (BadPtr(parv[1])) goto temp;
+ result = strtoul(parv[1], NULL, 16);
+ /* Accept code in second parameter (ircserv) */
+ if (result != sptr->nospoof)
+ {
+ if (BadPtr(parv[2])) goto temp;
+ result = strtoul(parv[2], NULL, 16);
+ if (result != sptr->nospoof) goto temp;
+ }
+ sptr->nospoof = 0;
+ if (sptr->user && sptr->name[0])
+ return register_user(cptr, sptr, sptr->name,
+ sptr->user->username, NULL, NULL);
+ return 0;
+ temp:
+ /* Homer compatibility */
+ sendto_one(cptr, ":%X!nospoof@%s PRIVMSG %s :%cVERSION%c",
+ cptr->nospoof, me.name, cptr->name, (char) 1, (char) 1);
+ return 0;
+}
+#endif /* NOSPOOF */
+
+/*
+** m_pong
+** parv[0] = sender prefix
+** parv[1] = origin
+** parv[2] = destination
+*/
+int m_pong(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ aClient *acptr;
+ char *origin, *destination;
+
+#ifdef NOSPOOF
+ if (!IsRegistered(cptr))
+ return m_nospoof(cptr, sptr, parc, parv);
+#endif
+
+ if (parc < 2 || *parv[1] == '\0')
+ {
+ sendto_one(sptr, err_str(ERR_NOORIGIN), me.name, parv[0]);
+ return 0;
+ }
+
+ origin = parv[1];
+ destination = parv[2];
+ cptr->flags &= ~FLAGS_PINGSENT;
+ sptr->flags &= ~FLAGS_PINGSENT;
+
+ if (!BadPtr(destination) && mycmp(destination, me.name) != 0)
+ {
+ if ((acptr = find_client(destination, NULL)) ||
+ (acptr = find_server(destination, NULL)))
+ {
+ if (!IsServer(cptr) && !IsServer(acptr))
+ {
+ sendto_one(sptr, err_str(ERR_NOSUCHSERVER),
+ me.name, parv[0], destination);
+ return 0;
+ }
+ else
+ sendto_one(acptr,":%s PONG %s %s",
+ parv[0], origin, destination);
+ }
+ else
+ {
+ sendto_one(sptr, err_str(ERR_NOSUCHSERVER),
+ me.name, parv[0], destination);
+ return 0;
+ }
+ }
+#ifdef DEBUGMODE
+ else
+ Debug((DEBUG_NOTICE, "PONG: %s %s", origin,
+ destination ? destination : "*"));
+#endif
+ return 0;
+ }
+
+/*
+** m_mkpasswd
+** parv[0] = sender prefix
+** parv[1] = password to encrypt
+*/
+#ifndef _WIN32
+int m_mkpasswd(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ static char saltChars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
+ char salt[3];
+ extern char *crypt();
+ int i;
+ int useable = 0;
+
+ if (!IsAnOper(sptr))
+ return -1;
+ if (parc > 1)
+ {
+ if (strlen(parv[1]) >= 1)
+ useable = 1;
+ }
+
+ if (useable == 0)
+ {
+ sendto_one(sptr, ":%s NOTICE %s :*** Encryption's MUST be atleast 1 character in length", me.name, parv[0]);
+ return 0;
+ }
+ srandom(time(0));
+ salt[0] = saltChars[random() % 64];
+ salt[1] = saltChars[random() % 64];
+ salt[2] = 0;
+
+ if ((strchr(saltChars, salt[0]) == NULL) || (strchr(saltChars, salt[1]) == NULL))
+ {
+ sendto_one(sptr, ":%s NOTICE %s :*** Illegal salt %s", me.name, parv[0], salt);
+ return 0;
+ }
+
+
+ sendto_one(sptr, ":%s NOTICE %s :*** Encryption for [%s] is %s", me.name, parv[0], parv[1], crypt(parv[1], salt));
+ return 0;
+}
+
+#else
+int m_mkpasswd(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ sendto_one(sptr, ":%s NOTICE %s :*** Encryption is disabled on UnrealIRCD-win32",
+ me.name, parv[0]);
+ return 0;
+ }
+
+#endif
+
+/*
+** m_oper
+** parv[0] = sender prefix
+** parv[1] = oper name
+** parv[2] = oper password
+*/
+int m_oper(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ aConfItem *aconf;
+ aClient *acptr;
+ char *name, *password, *encr;
+ anUser *user = sptr->user;
+#ifdef CRYPT_OPER_PASSWORD
+ char salt[3];
+ extern char *crypt();
+#endif /* CRYPT_OPER_PASSWORD */
+
+ if (check_registered_user(sptr))
+ return 0;
+
+ name = parc > 1 ? parv[1] : NULL;
+ password = parc > 2 ? parv[2] : NULL;
+
+ if (!IsServer(cptr) && (BadPtr(name) || BadPtr(password)))
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "OPER");
+ return 0;
+ }
+
+ /* if message arrived from server, trust it, and set to oper */
+
+ if ((IsServer(cptr) || IsMe(cptr)) && !IsOper(sptr))
+ {
+ sptr->umodes |= UMODE_OPER;
+ sendto_serv_butone(cptr, ":%s MODE %s :+o", parv[0], parv[0]);
+ if (IsMe(cptr)) {
+ sendto_one(sptr, rpl_str(RPL_YOUREOPER),
+ me.name, parv[0]);
+ }
+ return 0;
+ }
+ else if (IsOper(sptr))
+ {
+ if (MyConnect(sptr))
+ sendto_one(sptr, rpl_str(RPL_YOUREOPER),
+ me.name, parv[0]);
+ return 0;
+ }
+
+ if (!(aconf = find_conf_exact(name, sptr->username, sptr->sockhost, CONF_OPS)) &&
+ !(aconf = find_conf_exact(name, sptr->username, inetntoa((char *)&cptr->ip), CONF_OPS)))
+ {
+ sendto_one(sptr, err_str(ERR_NOOPERHOST), me.name, parv[0]);
+ sendto_realops("Failed OPER attempt by %s (%s@%s)",
+ parv[0], sptr->user->username, sptr->sockhost);
+ sptr->since += 7;
+ return 0;
+ }
+
+#ifdef CRYPT_OPER_PASSWORD
+ /* use first two chars of the password they send in as salt */
+
+ /* passwd may be NULL. Head it off at the pass... */
+ salt[0] = '\0';
+ if (password && aconf->passwd && aconf->passwd[0] && aconf->passwd[1])
+ {
+ salt[0] = aconf->passwd[0];
+ salt[1] = aconf->passwd[1];
+ salt[2] = '\0';
+ encr = crypt(password, salt);
+ }
+ else
+ {
+ encr = "";
+ }
+#else /* CRYPT_OPER_PASSWORD */
+ encr = password;
+#endif /* CRYPT_OPER_PASSWORD */
+
+ if ((aconf->status & CONF_OPS) && StrEq(encr, aconf->passwd)
+ && !attach_conf(sptr, aconf))
+ {
+ int old = (sptr->umodes & ALL_UMODES);
+ char *s;
+
+ s = index(aconf->host, '@');
+ *s++ = '\0';
+ if ((aconf->port & OFLAG_AGENT))
+ sptr->umodes |= UMODE_AGENT;
+ if ((aconf->port & OFLAG_HELPOP))
+ {
+ sptr->umodes |= UMODE_HELPOP;
+ }
+
+ if (!(aconf->port & OFLAG_ISGLOBAL))
+ {
+ SetLocOp(sptr);
+ }
+ else
+ if (aconf->port & OFLAG_NETADMIN) {
+ if (aconf->port & OFLAG_SADMIN) {
+ sptr->umodes |= (UMODE_NETADMIN|UMODE_ADMIN|UMODE_SADMIN);
+ SetNetAdmin(sptr);
+ SetSAdmin(sptr);
+ SetAdmin(sptr);
+ SetOper(sptr);
+ }
+ else
+ {
+ sptr->umodes |= (UMODE_NETADMIN|UMODE_ADMIN);
+ SetNetAdmin(sptr);
+ SetAdmin(sptr);
+ SetOper(sptr);
+ }
+ }
+ else
+ if (aconf->port & OFLAG_COADMIN)
+ {
+ if (aconf->port & OFLAG_SADMIN) {
+ sptr->umodes |= (UMODE_COADMIN|UMODE_ADMIN|UMODE_SADMIN);
+ SetCoAdmin(sptr);
+ SetSAdmin(sptr);
+ SetAdmin(sptr);
+ SetOper(sptr);
+ }
+ else
+ {
+ sptr->umodes |= (UMODE_COADMIN|UMODE_ADMIN);
+ SetCoAdmin(sptr);
+ SetAdmin(sptr);
+ SetOper(sptr);
+ }
+ }
+ else
+ if (aconf->port & OFLAG_TECHADMIN)
+ {
+ if (aconf->port & OFLAG_SADMIN) {
+ sptr->umodes |= (UMODE_TECHADMIN|UMODE_ADMIN|UMODE_SADMIN);
+ SetTechAdmin(sptr);
+ SetSAdmin(sptr);
+ SetAdmin(sptr);
+ SetOper(sptr);
+ }
+ else
+ {
+ sptr->umodes |= (UMODE_TECHADMIN|UMODE_ADMIN);
+ SetTechAdmin(sptr);
+ SetAdmin(sptr);
+ SetOper(sptr);
+ }
+ }
+ else
+ if (aconf->port & OFLAG_ADMIN && aconf->port & OFLAG_SADMIN) {
+ sptr->umodes |= (UMODE_ADMIN|UMODE_SADMIN);
+ SetAdmin(sptr);
+ SetSAdmin(sptr);
+ SetOper(sptr);
+ }
+ else
+ if (aconf->port & OFLAG_SADMIN) {
+ sptr->umodes |= (UMODE_SADMIN);
+ SetSAdmin(sptr);
+ SetOper(sptr);
+ }
+ else
+ if (aconf->port & OFLAG_ADMIN) {
+ sptr->umodes |= (UMODE_ADMIN);
+ SetAdmin(sptr);
+ SetOper(sptr);
+ }
+ else
+ {
+ if (aconf->port & OFLAG_SADMIN) {
+ sptr->umodes |= (UMODE_OPER|UMODE_SADMIN);
+ SetSAdmin(sptr);
+ SetOper(sptr);
+ }
+ else
+ {
+ sptr->umodes |= (UMODE_OPER);
+ SetOper(sptr);
+ }
+ }
+
+ if (aconf->port & OFLAG_EYES)
+ {
+ sptr->umodes |= (UMODE_EYES);
+ SetEyes(sptr);
+ }
+
+ if (aconf->port & OFLAG_WHOIS) {
+ sptr->umodes |= (UMODE_WHOIS);
+ }
+
+ if (aconf->port & OFLAG_HIDE) {
+ sptr->umodes |= (UMODE_HIDE);
+ }
+
+ sptr->oflag = aconf->port;
+
+ *--s = '@';
+
+ sptr->umodes |= (UMODE_SERVNOTICE|UMODE_WALLOP|UMODE_FAILOP|UMODE_FLOOD|UMODE_CLIENT|UMODE_KILLS);
+ if (ALLOW_CHATOPS == 1)
+ sptr->umodes |= UMODE_CHATOP;
+
+ send_umode_out(cptr, sptr, old);
+#ifndef NO_FDLIST
+ addto_fdlist(sptr->fd, &oper_fdlist);
+#endif
+ sendto_one(sptr, rpl_str(RPL_YOUREOPER), me.name, parv[0]);
+
+ if (!(aconf->port & OFLAG_ISGLOBAL))
+ {
+ sendto_ops("%s (%s@%s) is now a local operator (o)", parv[0],
+ sptr->user->username, IsHidden(sptr) ? sptr->user->virthost : sptr->user->realhost);
+ if (iNAH == 1 && (sptr->oflag & OFLAG_HIDE))
+ iNAH_host(sptr, locop_host);
+ sptr->umodes &= ~UMODE_OPER;
+ }
+ else
+ if ((aconf->port & OFLAG_AGENT))
+ {
+ sendto_ops("%s (%s@%s) is now an IRCd Agent (S)", parv[0],
+ sptr->user->username, IsHidden(sptr) ? sptr->user->virthost : sptr->user->realhost);
+ }
+ else
+ if (aconf->port & OFLAG_NETADMIN)
+ {
+ sendto_ops("%s (%s@%s) is now a network administrator (N)", parv[0],
+ sptr->user->username, IsHidden(cptr) ? sptr->user->virthost : sptr->user->realhost);
+ if (MyClient (sptr))
+ {
+ sendto_serv_butone(&me, ":%s GLOBOPS :%s (%s@%s) is now a network administrator (N)", me.name, parv[0],
+ sptr->user->username, IsHidden(sptr) ? sptr->user->virthost : sptr->user->realhost);
+ }
+
+ if (iNAH == 1 && (sptr->oflag & OFLAG_HIDE))
+ iNAH_host(sptr, netadmin_host);
+ }
+ else
+ if (aconf->port & OFLAG_COADMIN)
+ {
+ sendto_ops("%s (%s@%s) is now a co administrator (C)", parv[0],
+ sptr->user->username, IsHidden(sptr) ? sptr->user->virthost : sptr->user->realhost);
+ if (MyClient (sptr))
+ {
+ /* sendto_serv_butone(&me, ":%s GLOBOPS :%s (%s@%s) is now a co administrator (C)", me.name, parv[0],
+ sptr->user->username, IsHidden(sptr) ? sptr->user->virthost : sptr->user->realhost);
+ */
+ }
+ if (iNAH == 1 && (sptr->oflag & OFLAG_HIDE))
+ iNAH_host(sptr, coadmin_host);
+ }
+ else
+ if (aconf->port & OFLAG_TECHADMIN) {
+ sendto_ops("%s (%s@%s) is now a technical administrator (T)", parv[0],
+ sptr->user->username, IsHidden(sptr) ? sptr->user->virthost : sptr->user->realhost);
+ if (MyClient (sptr))
+ {
+ sendto_serv_butone(&me, ":%s GLOBOPS :%s (%s@%s) is now a technical administrator (T)", me.name, parv[0],
+ sptr->user->username, IsHidden(sptr) ? sptr->user->virthost : sptr->user->realhost);
+ }
+ if (iNAH == 1 && (sptr->oflag & OFLAG_HIDE))
+ iNAH_host(sptr, techadmin_host);
+ }
+ else
+ if (aconf->port & OFLAG_SADMIN)
+ {
+ sendto_ops("%s (%s@%s) is now a services admin (a)", parv[0],
+ sptr->user->username, IsHidden(sptr) ? sptr->user->virthost : sptr->user->realhost);
+ if (MyClient (sptr))
+ {
+ sendto_serv_butone(&me, ":%s GLOBOPS :%s (%s@%s) is now a services administrator (a)", me.name, parv[0],
+ sptr->user->username, IsHidden(sptr) ? sptr->user->virthost : sptr->user->realhost);
+ }
+ if (iNAH == 1 && (sptr->oflag & OFLAG_HIDE))
+ iNAH_host(sptr, sadmin_host);
+ }
+ else
+ if (aconf->port & OFLAG_ADMIN)
+ {
+ sendto_ops("%s (%s@%s) is now a server admin (A)", parv[0],
+ sptr->user->username, IsHidden(sptr) ? sptr->user->virthost : sptr->user->realhost);
+ if (iNAH == 1 && (sptr->oflag & OFLAG_HIDE))
+ iNAH_host(sptr, admin_host);
+ }
+ else
+ {
+ sendto_ops("%s (%s@%s) is now an operator (O)", parv[0],
+ sptr->user->username, IsHidden(sptr) ? sptr->user->virthost : sptr->user->realhost);
+ if (iNAH == 1 && (sptr->oflag & OFLAG_HIDE))
+ iNAH_host(sptr, oper_host);
+ }
+ if (SHOWOPERMOTD == 1)
+ m_opermotd(cptr, sptr, parc, parv);
+
+#if !defined(CRYPT_OPER_PASSWORD) && (defined(FNAME_OPERLOG) ||\
+ (defined(USE_SYSLOG) && defined(SYSLOG_OPER)))
+ encr = "";
+#endif
+#if defined(USE_SYSLOG) && defined(SYSLOG_OPER)
+ syslog(LOG_INFO, "OPER (%s) (%s) by (%s!%s@%s)",
+ name, encr,
+ parv[0], sptr->user->username, sptr->sockhost);
+#endif
+#ifdef FNAME_OPERLOG
+ {
+ int logfile;
+
+ /*
+ * This conditional makes the logfile active only after
+ * it's been created - thus logging can be turned off by
+ * removing the file.
+ *
+ * stop NFS hangs...most systems should be able to open a
+ * file in 3 seconds. -avalon (curtesy of wumpus)
+ */
+ if (IsPerson(sptr) &&
+ (logfile = open(FNAME_OPERLOG, O_WRONLY|O_APPEND)) != -1)
+ {
+ (void)sprintf(buf, "%s OPER (%s) (%s) by (%s!%s@%s)\n",
+ myctime(TStime()), name, encr,
+ parv[0], sptr->user->username,
+ sptr->sockhost);
+ (void)write(logfile, buf, strlen(buf));
+ (void)close(logfile);
+ }
+ /* Modification by pjg */
+ }
+#endif
+
+ }
+ else
+ {
+ (void)detach_conf(sptr, aconf);
+ sendto_one(sptr,err_str(ERR_PASSWDMISMATCH),me.name, parv[0]);
+#ifdef FAILOPER_WARN
+ sendto_one(sptr,":%s NOTICE :*** Your attempt has been logged.",me.name);
+#endif
+ sendto_realops("Failed OPER attempt by %s (%s@%s) using UID %s [NOPASSWORD]",
+ parv[0], sptr->user->username, sptr->sockhost, name);
+ sendto_serv_butone(&me, ":%s GLOBOPS :Failed OPER attempt by %s (%s@%s) using UID %s [---]",
+ me.name, parv[0], sptr->user->username, sptr->sockhost, name);
+ sptr->since += 7;
+#ifdef FNAME_OPERLOG
+ {
+ int logfile;
+
+ /*
+ * This conditional makes the logfile active only after
+ * it's been created - thus logging can be turned off by
+ * removing the file.
+ *
+ * stop NFS hangs...most systems should be able to open a
+ * file in 3 seconds. -avalon (curtesy of wumpus)
+ */
+ if (IsPerson(sptr) &&
+ (logfile = open(FNAME_OPERLOG, O_WRONLY|O_APPEND)) != -1)
+ {
+ (void)sprintf(buf, "%s FAILED OPER (%s) (%s) by (%s!%s@%s)\n PASSWORD %s",
+ myctime(TStime()), name, encr,
+ parv[0], sptr->user->username,
+ sptr->sockhost, password);
+ (void)write(logfile, buf, strlen(buf));
+ (void)close(logfile);
+ }
+ /* Modification by pjg */
+ }
+#endif
+ }
+ return 0;
+ }
+
+/***************************************************************************
+ * m_pass() - Added Sat, 4 March 1989
+ ***************************************************************************/
+
+/*
+** m_pass
+** parv[0] = sender prefix
+** parv[1] = password
+*/
+int m_pass(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+ {
+ char *password = parc > 1 ? parv[1] : NULL;
+
+ if (BadPtr(password))
+ {
+ sendto_one(cptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "PASS");
+ return 0;
+ }
+ if (!MyConnect(sptr) || (!IsUnknown(cptr) && !IsHandshake(cptr)))
+ {
+ sendto_one(cptr, err_str(ERR_ALREADYREGISTRED),
+ me.name, parv[0]);
+ return 0;
+ }
+ strncpyzt(cptr->passwd, password, sizeof(cptr->passwd));
+ return 0;
+ }
+
+/*
+ * m_userhost added by Darren Reed 13/8/91 to aid clients and reduce
+ * the need for complicated requests like WHOIS. It returns user/host
+ * information only (no spurious AWAY labels or channels).
+ */
+int m_userhost(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ int catsize;
+ char *p = NULL;
+ aClient *acptr;
+ char *s;
+ char *curpos;
+ int resid;
+
+ if (check_registered(sptr))
+ return 0;
+
+ if (parc > 2)
+ (void)m_userhost(cptr, sptr, parc-1, parv+1);
+
+ if (parc < 2)
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "USERHOST");
+ return 0;
+ }
+
+ /*
+ * use curpos to keep track of where we are in the output buffer,
+ * and use resid to keep track of the remaining space in the
+ * buffer
+ */
+ curpos = buf;
+ curpos += sprintf(curpos, rpl_str(RPL_USERHOST), me.name, parv[0]);
+ resid = sizeof(buf) - (curpos - buf) - 1; /* remaining space */
+
+ /*
+ * for each user found, print an entry if it fits.
+ */
+ for (s = strtoken(&p, parv[1], " "); s;
+ s = strtoken(&p, (char *)NULL, " "))
+ if ((acptr = find_person(s, NULL))) {
+ catsize = strlen(acptr->name)
+ + (IsAnOper(acptr) ? 1 : 0)
+ + 3
+ + strlen(acptr->user->username)
+ + strlen(acptr->user->realhost) + 1;
+ if (catsize <= resid) {
+ curpos += sprintf(curpos, "%s%s=%c%s@%s ",
+ acptr->name,
+ IsAnOper(acptr) ? "*" : "",
+ (acptr->user->away) ? '-' : '+',
+ acptr->user->username,
+ ( (IsOper(sptr) || acptr == sptr) ?
+ acptr->user->realhost :
+ (IsHidden(acptr) ? acptr->user->virthost : acptr->user->realhost)
+ )
+ );
+ if (IsWhois(acptr) && IsOper(sptr))
+ {
+ sendto_one(acptr, ":%s NOTICE %s :*** %s did a /userhost on you.", me.name, sptr->name, sptr->name);
+ }
+ resid -= catsize;
+ }
+ }
+
+ /*
+ * because of some trickery here, we might have the string end in
+ * "...:" or "foo " (note the trailing space)
+ * If we have a trailing space, nuke it here.
+ */
+ curpos--;
+ if (*curpos != ':')
+ *curpos = '\0';
+ sendto_one(sptr, "%s", buf);
+ return 0;
+}
+
+/*
+ * m_ison added by Darren Reed 13/8/91 to act as an efficent user indicator
+ * with respect to cpu/bandwidth used. Implemented for NOTIFY feature in
+ * clients. Designed to reduce number of whois requests. Can process
+ * nicknames in batches as long as the maximum buffer length.
+ *
+ * format:
+ * ISON :nicklist
+ */
+
+int m_ison(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ char namebuf[USERLEN+HOSTLEN+4];
+ Reg1 aClient *acptr;
+ Reg2 char *s, **pav = parv, *user;
+ Reg3 int len;
+ char *p = NULL;
+
+ if (check_registered(sptr))
+ return 0;
+
+ if (parc < 2)
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "ISON");
+ return 0;
+ }
+
+ (void)sprintf(buf, rpl_str(RPL_ISON), me.name, *parv);
+ len = strlen(buf);
+#ifndef NO_FDLIST
+ cptr->priority +=30; /* this keeps it from moving to 'busy' list */
+#endif
+ for (s = strtoken(&p, *++pav, " "); s; s = strtoken(&p, NULL, " "))
+ {
+ if(user=index(s, '!')) *user++='\0';
+ if ((acptr = find_person(s, NULL)))
+ {
+ if (user) {
+ strcpy(namebuf, acptr->user->username);
+ strcat(namebuf, "@");
+ strcat(namebuf, acptr->user->realhost);
+ if(match(user, namebuf))
+ continue;
+ *--user='!';
+ }
+
+ (void)strncat(buf, s, sizeof(buf) - len);
+ len += strlen(s);
+ (void)strncat(buf, " ", sizeof(buf) - len);
+ len++;
+ }
+ }
+ sendto_one(sptr, "%s", buf);
+ return 0;
+}
+
+/*
+ * m_umode() added 15/10/91 By Darren Reed.
+ * parv[0] - sender
+ * parv[1] - username to change mode for
+ * parv[2] - modes to change
+ */
+int m_umode(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ Reg1 int flag;
+ Reg2 int *s;
+ Reg3 char **p, *m;
+ aClient *acptr;
+ anUser *user = sptr->user;
+ aConfItem *aconf;
+ int what, setflags;
+
+ if (check_registered_user(sptr))
+ return 0;
+
+ what = MODE_ADD;
+
+ if (parc < 2)
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
+ me.name, parv[0], "MODE");
+ return 0;
+ }
+
+ if (!(acptr = find_person(parv[1], NULL)))
+ {
+ if (MyConnect(sptr))
+ sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL),
+ me.name, parv[0], parv[1]);
+ return 0;
+ }
+
+ if (parc < 3)
+ {
+ m = buf;
+ *m++ = '+';
+ for (s = user_modes; (flag = *s) && (m - buf < BUFSIZE - 4);
+ s += 2)
+ if ((sptr->umodes & flag))
+ *m++ = (char)(*(s+1));
+ *m = '\0';
+ sendto_one(sptr, rpl_str(RPL_UMODEIS),
+ me.name, parv[0], buf);
+ return 0;
+ }
+
+ /* find flags already set for user */
+ setflags = 0;
+ for (s = user_modes; (flag = *s); s += 2)
+ if ((sptr->umodes & flag))
+ setflags |= flag;
+
+ /*
+ * parse mode change string(s)
+ */
+ for (p = &parv[2]; p && *p; p++ )
+ for (m = *p; *m; m++)
+ switch(*m)
+ {
+ case '+' :
+ what = MODE_ADD;
+ break;
+ case '-' :
+ what = MODE_DEL;
+ break;
+
+ /* we may not get these,
+ * but they shouldnt be in default
+ */
+ case ' ' :
+ case '\n' :
+ case '\r' :
+ case '\t' :
+ break;
+ case 'r' :
+ case 't' :
+ if (MyClient(sptr))
+ break;
+ /* since we now use chatops define in unrealircd.conf, we have
+ * to disallow it here */
+ case 'b':
+ if (ALLOW_CHATOPS == 0 && what == MODE_ADD && MyClient(sptr))
+ break;
+ goto def;
+ case 'B' :
+ if (what == MODE_ADD && MyClient(sptr))
+ (void)m_botmotd(sptr, sptr, 1, parv);
+ default :
+def:
+ for (s = user_modes; (flag = *s); s += 2)
+ if (*m == (char)(*(s+1)))
+ {
+ if (what == MODE_ADD) {
+ sptr->umodes |= flag;
+ } else {
+ sptr->umodes &= ~flag;
+ }
+
+ break;
+ }
+
+ if (flag == 0 && MyConnect(sptr))
+ sendto_one(sptr,
+ err_str(ERR_UMODEUNKNOWNFLAG),
+ me.name, parv[0]);
+ break;
+ }
+ /*
+ * stop users making themselves operators too easily
+ */
+
+ if (!(setflags & UMODE_OPER) && IsOper(sptr) && !IsServer(cptr))
+ ClearOper(sptr);
+ if (!(setflags & UMODE_LOCOP) && IsLocOp(sptr) && !IsServer(cptr))
+ sptr->umodes &= ~UMODE_LOCOP;
+ /*
+ * Let only operators set HelpOp
+ * Helpops get all /quote help <mess> globals -Donwulff
+ */
+ if (MyClient(sptr) && IsHelpOp(sptr) && !OPCanHelpOp(sptr))
+ ClearHelpOp(sptr);
+ /*
+ * Let only operators set FloodF, ClientF; also
+ * remove those flags if they've gone -o/-O.
+ * FloodF sends notices about possible flooding -Cabal95
+ * ClientF sends notices about clients connecting or exiting
+ * Admin is for server admins
+ */
+ if (!IsAnOper(sptr) && !IsServer(cptr))
+ {
+ if (IsWhois(sptr))
+ sptr->umodes &= ~UMODE_WHOIS;
+ if (IsClientF(sptr))
+ ClearClientF(sptr);
+ if (IsFloodF(sptr))
+ ClearFloodF(sptr);
+ if (IsAdmin(sptr))
+ ClearAdmin(sptr);
+ if (IsSAdmin(sptr))
+ ClearSAdmin(sptr);
+ if (IsNetAdmin(sptr))
+ ClearNetAdmin(sptr);
+ if (IsHideOper(sptr))
+ ClearHideOper(sptr);
+ if (IsCoAdmin(sptr))
+ ClearCoAdmin(sptr);
+ if (IsTechAdmin(sptr))
+ ClearTechAdmin(sptr);
+ if (IsEyes(sptr))
+ ClearEyes(sptr);
+ if (ALLOW_CHATOPS == 1) {
+ if (SendChatops(sptr))
+ ClearChatops(sptr);
+ }
+
+ }
+
+ /*
+ * New oper access flags - Only let them set certian usermodes on
+ * themselves IF they have access to set that specific mode in their
+ * O:Line.
+ */
+ if (MyClient(sptr) && IsAnOper(sptr))
+ {
+ if (IsClientF(sptr) && !OPCanUModeC(sptr))
+ ClearClientF(sptr);
+ if (IsFloodF(sptr) && !OPCanUModeF(sptr))
+ ClearFloodF(sptr);
+ if (IsAdmin(sptr) && !OPIsAdmin(sptr))
+ ClearAdmin(sptr);
+ if (IsSAdmin(sptr) && !OPIsSAdmin(sptr))
+ ClearSAdmin(sptr);
+ if (IsNetAdmin(sptr) && !OPIsNetAdmin(sptr))
+ ClearNetAdmin(sptr);
+ if (IsCoAdmin(sptr) && !OPIsCoAdmin(sptr))
+ ClearCoAdmin(sptr);
+ if (IsTechAdmin(sptr) && !OPIsTechAdmin(sptr))
+ ClearTechAdmin(sptr);
+ if ((sptr->umodes & UMODE_HIDING) && !(sptr->oflag & OFLAG_INVISIBLE))
+ sptr->umodes &= ~UMODE_HIDING;
+ if (MyClient(sptr) && (sptr->umodes & UMODE_CODER) && !IsAnOper(sptr))
+ sptr->umodes &= ~UMODE_CODER;
+
+
+ }
+
+ /*
+ * For Services Protection...
+ */
+ if (!IsServer(cptr) && !IsULine(cptr,sptr))
+ {
+ if (IsServices(sptr))
+ ClearServices(sptr);
+/* if (IsDeaf(sptr))
+ sptr->umodes &= ~UMODE_DEAF;
+*/
+ }
+ if ((setflags & UMODE_HIDE) && !IsHidden(sptr))
+ sptr->umodes &= ~UMODE_SETHOST;
+
+ if (IsHidden(sptr) && !(setflags & UMODE_HIDE))
+ {
+ make_virthost(sptr->user->realhost, sptr->user->virthost);
+ }
+
+ /*
+ This is to remooove the kix bug.. and to protect some stuffie
+ -techie
+ */
+ if (MyConnect(sptr))
+ {
+ if ((sptr->umodes & (UMODE_KIX)) && !(IsNetAdmin(sptr) || IsTechAdmin(sptr)))
+ sptr->umodes &= ~UMODE_KIX;
+ if ((sptr->umodes & (UMODE_FCLIENT)) && !(IsNetAdmin(sptr) || IsTechAdmin(sptr)))
+ sptr->umodes &= ~UMODE_FCLIENT;
+
+ /* Agents */
+ if ((sptr->umodes & (UMODE_AGENT)) && !(sptr->oflag & OFLAG_AGENT))
+ sptr->umodes &= ~UMODE_AGENT;
+ if ((sptr->umodes & UMODE_HIDING) && !IsAnOper(sptr))
+ sptr->umodes &= ~UMODE_HIDING;
+
+ if ((sptr->umodes & UMODE_HIDING) && !(sptr->oflag & OFLAG_INVISIBLE))
+ sptr->umodes &= ~UMODE_HIDING;
+ if (MyClient(sptr) && (sptr->umodes & UMODE_CODER) && !IsAnOper(sptr))
+ sptr->umodes &= ~UMODE_CODER;
+
+ if ((sptr->umodes & (UMODE_HIDING)) && !(setflags & UMODE_HIDING)) {
+ sendto_umode(UMODE_ADMIN, "[+I] Activated total invisibility mode on %s", sptr->name);
+ sendto_serv_butone(cptr, ":%s SMO A :[+I] Activated total invisibility mode on %s",me.name, sptr->name);
+ }
+ if (!(sptr->umodes & (UMODE_HIDING))) {
+ if (setflags & UMODE_HIDING) {
+ sendto_umode(UMODE_ADMIN, "[+I] De-activated total invisibility mode on %s", sptr->name);
+ sendto_serv_butone(cptr, ":%s SMO A :[+I] De-activated total invisibility mode on %s", me.name, sptr->name);
+ }
+ }
+ }
+ /*
+ * If I understand what this code is doing correctly...
+ * If the user WAS an operator and has now set themselves -o/-O
+ * then remove their access, d'oh!
+ * In order to allow opers to do stuff like go +o, +h, -o and
+ * remain +h, I moved this code below those checks. It should be
+ * O.K. The above code just does normal access flag checks. This
+ * only changes the operflag access level. -Cabal95
+ */
+ if ((setflags & (UMODE_OPER|UMODE_LOCOP)) && !IsAnOper(sptr) &&
+ MyConnect(sptr))
+ {
+#ifndef NO_FDLIST
+ delfrom_fdlist(sptr->fd, &oper_fdlist);
+#endif
+ det_confs_butmask(sptr, CONF_CLIENT & ~CONF_OPS);
+ sptr->oflag = 0;
+ }
+
+ /*
+ * compare new flags with old flags and send string which
+ * will cause servers to update correctly.
+ */
+ if (dontspread == 0)
+ send_umode_out(cptr, sptr, setflags);
+
+ return 0;
+}
+
+/*
+ * m_svs2mode() added by Potvin
+ * parv[0] - sender
+ * parv[1] - username to change mode for
+ * parv[2] - modes to change
+ * parv[3] - Service Stamp (if mode == d)
+ */
+int m_svs2mode(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ Reg1 int flag;
+ Reg2 int *s;
+ Reg3 char **p, *m;
+ aClient *acptr;
+ int what, setflags;
+
+ if (!IsULine(cptr, sptr))
+ return 0;
+
+ what = MODE_ADD;
+
+ if (parc < 3)
+ return 0;
+
+ if (!(acptr = find_person(parv[1], NULL)))
+ return 0;
+
+ setflags = 0;
+ for (s = user_modes; (flag = *s); s += 2)
+ if (acptr->umodes & flag)
+ setflags |= flag;
+ /*
+ * parse mode change string(s)
+ */
+ for (p = &parv[2]; p && *p; p++ )
+ for (m = *p; *m; m++)
+ switch(*m)
+ {
+ case '+' :
+ what = MODE_ADD;
+ break;
+ case '-' :
+ what = MODE_DEL;
+ break;
+ /* we may not get these,
+ * but they shouldnt be in default
+ */
+ case ' ' :
+ case '\n' :
+ case '\r' :
+ case '\t' :
+ break;
+ case 'l' :
+ if(parv[3] && isdigit(*parv[3]))
+ max_global_count = atoi(parv[3]);
+ break;
+ case 'd' :
+ if(parv[3] && isdigit(*parv[3]))
+ acptr->user->servicestamp = atol(parv[3]);
+ break;
+ default :
+ for (s = user_modes; (flag = *s); s += 2)
+ if (*m == (char)(*(s+1)))
+ {
+ if (what == MODE_ADD)
+ acptr->umodes |= flag;
+ else
+ acptr->umodes &= ~flag;
+ break;
+ }
+ break;
+ }
+
+ if(parc > 3)
+ sendto_serv_butone(cptr, ":%s SVS2MODE %s %s %s",
+ parv[0], parv[1], parv[2], parv[3]);
+ else
+ sendto_serv_butone(cptr, ":%s SVS2MODE %s %s", parv[0],
+ parv[1], parv[2]);
+
+ sendto_one(acptr, ":%s MODE %s :%s",
+ parv[0], parv[1], parv[2]);
+
+ return 0;
+}
+
+/*
+ * m_svsmode() added by taz
+ * parv[0] - sender
+ * parv[1] - username to change mode for
+ * parv[2] - modes to change
+ * parv[3] - Service Stamp (if mode == d)
+ */
+int m_svsmode(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ Reg1 int flag;
+ Reg2 int *s;
+ Reg3 char **p, *m;
+ aClient *acptr;
+ int what, setflags;
+
+ if (!IsULine(cptr, sptr))
+ return 0;
+
+ what = MODE_ADD;
+
+ if (parc < 3)
+ return 0;
+
+ if (!(acptr = find_person(parv[1], NULL)))
+ return 0;
+
+ setflags = 0;
+ for (s = user_modes; (flag = *s); s += 2)
+ if (acptr->umodes & flag)
+ setflags |= flag;
+ /*
+ * parse mode change string(s)
+ */
+ for (p = &parv[2]; p && *p; p++ )
+ for (m = *p; *m; m++)
+ switch(*m)
+ {
+ case '+' :
+ what = MODE_ADD;
+ break;
+ case '-' :
+ what = MODE_DEL;
+ break;
+ /* we may not get these,
+ * but they shouldnt be in default
+ */
+ case ' ' :
+ case '\n' :
+ case '\r' :
+ case '\t' :
+ break;
+ case 'l' :
+ if(parv[3] && isdigit(*parv[3]))
+ max_global_count = atoi(parv[3]);
+ break;
+ case 'd' :
+ if(parv[3] && isdigit(*parv[3]))
+ acptr->user->servicestamp = atol(parv[3]);
+ break;
+ default :
+ for (s = user_modes; (flag = *s); s += 2)
+ if (*m == (char)(*(s+1)))
+ {
+ if (what == MODE_ADD)
+ acptr->umodes |= flag;
+ else
+ acptr->umodes &= ~flag;
+ break;
+ }
+ break;
+ }
+
+
+ if(parc > 3)
+ sendto_serv_butone(cptr, ":%s SVSMODE %s %s %s",
+ parv[0], parv[1], parv[2], parv[3]);
+ else
+ sendto_serv_butone(cptr, ":%s SVSMODE %s %s", parv[0],
+ parv[1], parv[2]);
+
+ return 0;
+}
+
+/*
+ * send the MODE string for user (user) to connection cptr
+ * -avalon
+ */
+void send_umode(cptr, sptr, old, sendmask, umode_buf)
+aClient *cptr, *sptr;
+int old, sendmask;
+char *umode_buf;
+{
+ Reg1 int *s, flag;
+ Reg2 char *m;
+ int what = MODE_NULL;
+
+ /*
+ * build a string in umode_buf to represent the change in the user's
+ * mode between the new (sptr->flag) and 'old'.
+ */
+ m = umode_buf;
+ *m = '\0';
+ for (s = user_modes; (flag = *s); s += 2)
+ {
+ if (MyClient(sptr) && !(flag & sendmask))
+ continue;
+ if ((flag & old) && !(sptr->umodes & flag))
+ {
+ if (what == MODE_DEL)
+ *m++ = *(s+1);
+ else
+ {
+ what = MODE_DEL;
+ *m++ = '-';
+ *m++ = *(s+1);
+ }
+ }
+ else if (!(flag & old) && (sptr->umodes & flag))
+ {
+ if (what == MODE_ADD)
+ *m++ = *(s+1);
+ else
+ {
+ what = MODE_ADD;
+ *m++ = '+';
+ *m++ = *(s+1);
+ }
+ }
+ }
+ *m = '\0';
+ if (*umode_buf && cptr)
+ sendto_one(cptr, ":%s %s %s :%s", sptr->name,
+ (IsToken(cptr)?TOK_MODE:MSG_MODE),
+ sptr->name, umode_buf);
+}
+
+/*
+ * added Sat Jul 25 07:30:42 EST 1992
+ */
+void send_umode_out(cptr, sptr, old)
+aClient *cptr, *sptr;
+int old;
+{
+ Reg1 int i;
+ Reg2 aClient *acptr;
+
+ send_umode(NULL, sptr, old, SEND_UMODES, buf);
+
+ for (i = highest_fd; i >= 0; i--)
+ if ((acptr = local[i]) && IsServer(acptr) &&
+ (acptr != cptr) && (acptr != sptr) && *buf)
+ sendto_one(acptr, ":%s MODE %s :%s",
+ sptr->name, sptr->name, buf);
+
+ if (cptr && MyClient(cptr))
+ send_umode(cptr, sptr, old, ALL_UMODES, buf);
+
+}
+
+void send_umode_out_nickv2(cptr, sptr, old)
+aClient *cptr, *sptr;
+int old;
+{
+ Reg1 int i;
+ Reg2 aClient *acptr;
+
+ send_umode(NULL, sptr, old, SEND_UMODES, buf);
+
+ for (i = highest_fd; i >= 0; i--)
+ if ((acptr = local[i]) && IsServer(acptr) && !SupportNICKv2(acptr) &&
+ (acptr != cptr) && (acptr != sptr) && *buf)
+ sendto_one(acptr, ":%s MODE %s :%s",
+ sptr->name, sptr->name, buf);
+
+ if (cptr && MyClient(cptr))
+ send_umode(cptr, sptr, old, ALL_UMODES, buf);
+
+}
+
+/*
+ * added by taz
+ */
+void send_svsmode_out(cptr, sptr, bsptr, old)
+aClient *cptr, *sptr, *bsptr;
+
+int old;
+{
+ Reg1 int i;
+ Reg2 aClient *acptr;
+
+ send_umode(NULL, sptr, old, SEND_UMODES, buf);
+
+ sendto_serv_butone(acptr, ":%s SVSMODE %s :%s",
+ bsptr->name, sptr->name, buf);
+
+/* if (cptr && MyClient(cptr))
+ send_umode(cptr, sptr, old, ALL_UMODES, buf);
+*/
+}
+
+/***********************************************************************
+ * m_silence() - Added 19 May 1994 by Run.
+ *
+ ***********************************************************************/
+
+/*
+ * is_silenced : Does the actual check wether sptr is allowed
+ * to send a message to acptr.
+ * Both must be registered persons.
+ * If sptr is silenced by acptr, his message should not be propagated,
+ * but more over, if this is detected on a server not local to sptr
+ * the SILENCE mask is sent upstream.
+ */
+static int is_silenced(sptr, acptr)
+aClient *sptr;
+aClient *acptr;
+{ Reg1 Link *lp;
+ Reg2 anUser *user;
+ static char sender[HOSTLEN+NICKLEN+USERLEN+5];
+
+ if (!(acptr->user) || !(lp = acptr->user->silence) ||
+ !(user = sptr->user)) return 0;
+ sprintf(sender,"%s!%s@%s",sptr->name,user->username,user->realhost);
+ for (; lp; lp = lp->next)
+ { if (!match(lp->value.cp, sender))
+ { if (!MyConnect(sptr))
+ { sendto_one(sptr->from, ":%s SILENCE %s :%s",acptr->name,
+ sptr->name, lp->value.cp);
+ lp->flags=1; }
+ return 1; } }
+ return 0;
+}
+
+int del_silence(sptr, mask)
+aClient *sptr;
+char *mask;
+{ Reg1 Link **lp;
+ Reg2 Link *tmp;
+
+ for (lp = &(sptr->user->silence); *lp; lp = &((*lp)->next))
+ if (mycmp(mask, (*lp)->value.cp)==0)
+ { tmp = *lp;
+ *lp = tmp->next;
+ MyFree(tmp->value.cp);
+ free_link(tmp);
+ return 0; }
+ return -1;
+}
+
+static int add_silence(sptr, mask)
+aClient *sptr;
+char *mask;
+{ Reg1 Link *lp;
+ Reg2 int cnt = 0, len = 0;
+
+ for (lp = sptr->user->silence; lp; lp = lp->next)
+ { len += strlen(lp->value.cp);
+ if (MyClient(sptr))
+ if ((len > MAXSILELENGTH) || (++cnt >= MAXSILES))
+ { sendto_one(sptr, err_str(ERR_SILELISTFULL), me.name, sptr->name, mask);
+ return -1; }
+ else
+ { if (!match(lp->value.cp, mask))
+ return -1; }
+ else if (!mycmp(lp->value.cp, mask))
+ return -1;
+ }
+ lp = make_link();
+ bzero((char *)lp, sizeof(Link));
+ lp->next = sptr->user->silence;
+ lp->value.cp = (char *)MyMalloc(strlen(mask)+1);
+ (void)strcpy(lp->value.cp, mask);
+ sptr->user->silence = lp;
+ return 0;
+}
+
+/*
+** m_silence
+** parv[0] = sender prefix
+** From local client:
+** parv[1] = mask (NULL sends the list)
+** From remote client:
+** parv[1] = nick that must be silenced
+** parv[2] = mask
+*/
+
+int m_silence(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ Link *lp;
+ aClient *acptr;
+ char c, *cp, *user, *host;
+
+ if (check_registered_user(sptr)) return 0;
+
+ if (MyClient(sptr))
+ {
+ acptr = sptr;
+ if (parc < 2 || *parv[1]=='\0' || (acptr = find_person(parv[1], NULL)))
+ { if (!(acptr->user)) return 0;
+ for (lp = acptr->user->silence; lp; lp = lp->next)
+ sendto_one(sptr, rpl_str(RPL_SILELIST), me.name,
+ sptr->name, acptr->name, lp->value.cp);
+ sendto_one(sptr, rpl_str(RPL_ENDOFSILELIST), me.name, acptr->name);
+ return 0; }
+ cp = parv[1];
+ c = *cp;
+ if (c=='-' || c=='+') cp++;
+ else if (!(index(cp, '@') || index(cp, '.') ||
+ index(cp, '!') || index(cp, '*')))
+ { sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], parv[1]);
+ return -1; }
+ else c = '+';
+ cp = pretty_mask(cp);
+ if ((c=='-' && !del_silence(sptr,cp)) ||
+ (c!='-' && !add_silence(sptr,cp)))
+ { sendto_prefix_one(sptr, sptr, ":%s SILENCE %c%s", parv[0], c, cp);
+ if (c=='-')
+ sendto_serv_butone(NULL, ":%s SILENCE * -%s", sptr->name, cp);
+ }
+ }
+ else if (parc < 3 || *parv[2]=='\0')
+ {
+ sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "SILENCE");
+ return -1;
+ }
+ else if ((c = *parv[2])=='-' || (acptr = find_person(parv[1], NULL)))
+ {
+ if (c=='-')
+ { if (!del_silence(sptr,parv[2]+1))
+ sendto_serv_butone(cptr, ":%s SILENCE %s :%s",
+ parv[0], parv[1], parv[2]); }
+ else
+ { (void)add_silence(sptr,parv[2]);
+ if (!MyClient(acptr))
+ sendto_one(acptr, ":%s SILENCE %s :%s",
+ parv[0], parv[1], parv[2]); }
+ }
+ else
+ {
+ sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], parv[1]);
+ return -1;
+ }
+ return 0;
+}
+
+/* m_svsjoin() - Lamego - Wed Jul 21 20:04:48 1999
+ Copied off PTlink IRCd (C) PTlink coders team.
+ parv[0] - sender
+ parv[1] - nick to make join
+ parv[2] - channel(s) to join
+*/
+int m_svsjoin(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ aClient *acptr;
+ if (!IsULine(cptr, sptr))
+ return 0;
+
+ if (parc!=3 || !(acptr = find_person(parv[1], NULL)))
+ return 0;
+
+ if(MyClient(acptr)) {
+ parv [0] = parv [1];
+ parv [1] = parv [2];
+ (void)m_join(acptr,acptr,2,parv);
+ }
+ else
+ sendto_serv_butone(cptr, ":%s SVSJOIN %s %s", parv[0],
+ parv[1], parv[2]);
+
+ return 0;
+}
+
+/* m_sajoin() - Lamego - Wed Jul 21 20:04:48 1999
+ Copied off PTlink IRCd (C) PTlink coders team.
+ Coded for Sadmin by Stskeeps
+ parv[0] - sender
+ parv[1] - nick to make join
+ parv[2] - channel(s) to join
+*/
+int m_sajoin(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ aClient *acptr;
+ if (!IsSAdmin(sptr) && !IsULine(cptr, sptr))
+ return 0;
+
+ if (parc!=3 || !(acptr = find_person(parv[1], NULL)))
+ return 0;
+
+ sendto_realops("%s used SAJOIN to make %s join %s", sptr->name, parv[1], parv[2]);
+
+ if(MyClient(acptr)) {
+ parv [0] = parv [1];
+ parv [1] = parv [2];
+ sendto_one(acptr, ":%s NOTICE %s :*** You were forced to join %s", me.name, acptr->name, parv[2]);
+ (void)m_join(acptr,acptr,2,parv);
+ }
+ else
+ sendto_serv_butone(cptr, ":%s SAJOIN %s %s", parv[0],
+ parv[1], parv[2]);
+
+ return 0;
+}
+/* m_svspart() - Lamego - Wed Jul 21 20:04:48 1999
+ Copied off PTlink IRCd (C) PTlink coders team.
+ Modified for PART by Stskeeps
+ parv[0] - sender
+ parv[1] - nick to make part
+ parv[2] - channel(s) to part
+*/
+int m_svspart(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ aClient *acptr;
+ if (!IsULine(cptr, sptr))
+ return 0;
+
+ if (parc!=3 || !(acptr = find_person(parv[1], NULL)))
+ return 0;
+
+ if(MyClient(acptr)) {
+ parv [0] = parv [1];
+ parv [1] = parv [2];
+ (void)m_part(acptr,acptr,2,parv);
+ }
+ else
+ sendto_serv_butone(cptr, ":%s SVSPART %s %s", parv[0],
+ parv[1], parv[2]);
+
+ return 0;
+}
+
+/* m_sapart() - Lamego - Wed Jul 21 20:04:48 1999
+ Copied off PTlink IRCd (C) PTlink coders team.
+ Coded for Sadmin by Stskeeps
+ parv[0] - sender
+ parv[1] - nick to make part
+ parv[2] - channel(s) to part
+*/
+int m_sapart(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ aClient *acptr;
+ if (!IsSAdmin(sptr) && !IsULine(cptr, sptr))
+ return 0;
+
+ if (parc!=3 || !(acptr = find_person(parv[1], NULL)))
+ return 0;
+
+ sendto_realops("%s used SAPART to make %s part %s", sptr->name, parv[1], parv[2]);
+
+ if(MyClient(acptr)) {
+ parv [0] = parv [1];
+ parv [1] = parv [2];
+ sendto_one(acptr, ":%s NOTICE %s :*** You were forced to part %s", me.name, acptr->name, parv[2]);
+ (void)m_part(acptr,acptr,2,parv);
+ }
+ else
+ sendto_serv_butone(cptr, ":%s SAPART %s %s", parv[0],
+ parv[1], parv[2]);
+
+ return 0;
+}
+/* These just waste space
+int m_noshortn(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{ sendto_one(sptr, "NOTICE %s :*** Please use /nickserv for that command",sptr->name);
+}
+int m_noshortc(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{ sendto_one(sptr, "NOTICE %s :*** Please use /chanserv for that command",sptr->name);
+}
+int m_noshortm(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{ sendto_one(sptr, "NOTICE %s :*** Please use /memoserv for that command",sptr->name);
+}
+int m_noshorto(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{ sendto_one(sptr, "NOTICE %s :*** Please use /operserv for that command",sptr->name);
+}
+int m_noshorth(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{ sendto_one(sptr, "NOTICE %s :*** Please use /helpserv for that command",sptr->name);
+}
+*/
--- /dev/null
+/*
+ * IRC - Internet Relay Chat, common/send.c
+ * Copyright (C) 1990 Jarkko Oikarinen and
+ * University of Oulu, Computing Center
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* -- Jto -- 16 Jun 1990
+ * Added Armin's PRIVMSG patches...
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)send.c 2.32 2/28/94 (C) 1988 University of Oulu, Computing Center and Jarkko Oikarinen";
+#endif
+
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#include "h.h"
+#include <stdarg.h>
+#include <stdio.h>
+#ifdef _WIN32
+#include <io.h>
+#endif
+
+ID_CVS("$Id$");
+
+void vsendto_one(aClient *to, char *pattern, va_list vl);
+void sendbufto_one(aClient *to);
+extern int sendanyways;
+#ifndef NO_FDLIST
+extern fdlist serv_fdlist;
+extern fdlist oper_fdlist;
+#endif
+
+#ifdef IRCII_KLUDGE
+#define NEWLINE "\n"
+#else
+#define NEWLINE "\r\n"
+#endif
+
+static char sendbuf[2048];
+static int send_message PROTO((aClient *, char *, int));
+
+static int sentalong[MAXCONNECTIONS];
+
+void vsendto_prefix_one(struct Client *to, struct Client *from,
+ const char* pattern, va_list vl);
+
+int sentalong_marker;
+
+/*
+** dead_link
+** An error has been detected. The link *must* be closed,
+** but *cannot* call ExitClient (m_bye) from here.
+** Instead, mark it with FLAGS_DEADSOCKET. This should
+** generate ExitClient from the main loop.
+**
+** If 'notice' is not NULL, it is assumed to be a format
+** for a message to local opers. I can contain only one
+** '%s', which will be replaced by the sockhost field of
+** the failing link.
+**
+** Also, the notice is skipped for "uninteresting" cases,
+** like Persons and yet unknown connections...
+*/
+static int dead_link(to, notice)
+aClient *to;
+char *notice;
+{
+ to->flags |= FLAGS_DEADSOCKET;
+ /*
+ * If because of BUFFERPOOL problem then clean dbuf's now so that
+ * notices don't hurt operators below.
+ */
+ DBufClear(&to->recvQ);
+ DBufClear(&to->sendQ);
+ if (!IsPerson(to) && !IsUnknown(to) && !(to->flags & FLAGS_CLOSING))
+ (void)sendto_failops_whoare_opers(notice, get_client_name(to, FALSE));
+ Debug((DEBUG_ERROR, notice, get_client_name(to, FALSE)));
+ return -1;
+}
+
+/*
+** flush_connections
+** Used to empty all output buffers for all connections. Should only
+** be called once per scan of connections. There should be a select in
+** here perhaps but that means either forcing a timeout or doing a poll.
+** When flushing, all we do is empty the obuffer array for each local
+** client and try to send it. if we cant send it, it goes into the sendQ
+** -avalon
+*/
+void flush_connections(fd)
+int fd;
+{
+#ifdef SENDQ_ALWAYS
+ Reg1 int i;
+ Reg2 aClient *cptr;
+
+ if (fd == me.fd)
+ {
+ for (i = highest_fd; i >= 0; i--)
+ if ((cptr = local[i]) && DBufLength(&cptr->sendQ) > 0)
+ (void)send_queued(cptr);
+ }
+ else if (fd >= 0 && (cptr = local[fd]) && DBufLength(&cptr->sendQ) > 0)
+ (void)send_queued(cptr);
+#endif
+}
+
+/*
+** send_queued
+** This function is called from the main select-loop (or whatever)
+** when there is a chance the some output would be possible. This
+** attempts to empty the send queue as far as possible...
+*/
+int send_queued(to)
+aClient *to;
+{
+ char *msg;
+ int len, rlen;
+
+#ifndef pyr
+ if (IsBlocked(to)) return; /* Can't write to already blocked socket */
+#endif /* pyr */
+
+ /*
+ ** Once socket is marked dead, we cannot start writing to it,
+ ** even if the error is removed...
+ */
+ if (IsDead(to))
+ {
+ /*
+ ** Actually, we should *NEVER* get here--something is
+ ** not working correct if send_queued is called for a
+ ** dead socket... --msa
+ */
+#ifndef SENDQ_ALWAYS
+ return dead_link(to, "send_queued called for a DEADSOCKET:%s");
+#else
+ return -1;
+#endif
+ }
+ while (DBufLength(&to->sendQ) > 0)
+ {
+ msg = dbuf_map(&to->sendQ, &len);
+ /* Returns always len > 0 */
+ if ((rlen = deliver_it(to, msg, len)) < 0)
+ return dead_link(to,"Write error to %s, closing link");
+ (void)dbuf_delete(&to->sendQ, rlen);
+ to->lastsq = DBufLength(&to->sendQ)/1024;
+ if (rlen < len) {
+ /* If we can't write full message, mark the socket
+ * as "blocking" and stop trying. -Donwulff */
+ SetBlocked(to);
+ break;
+ }
+ }
+
+ return (IsDead(to)) ? -1 : 0;
+}
+
+/*
+ * send message to single client
+ */
+void sendto_one(aClient *to, char *pattern, ...)
+{
+ va_list vl;
+ va_start(vl, pattern);
+ vsendto_one(to, pattern, vl);
+ va_end(vl);
+}
+
+void vsendto_one(aClient *to, char *pattern, va_list vl)
+{
+ vsprintf(sendbuf, pattern, vl);
+ sendbufto_one(to);
+}
+
+void sendbufto_one(aClient *to)
+{
+ int len;
+
+ Debug((DEBUG_ERROR, "Sending [%s] to %s", sendbuf, to->name));
+
+ if (to->from)
+ to = to->from;
+ if (IsDead(to))
+ return; /* This socket has already
+ been marked as dead */
+ if (to->fd < 0)
+ {
+ /* This is normal when 'to' was being closed (via exit_client
+ * and close_connection) --Run
+ * Print the debug message anyway...
+ */
+ Debug((DEBUG_ERROR, "Local socket %s with negative fd %d... AARGH!",
+ to->name, to->fd));
+ return;
+}
+
+ len = strlen(sendbuf);
+ if (sendbuf[len - 1] != '\n')
+ {
+ if (len > 510)
+ len = 510;
+ sendbuf[len++] = '\r';
+ sendbuf[len++] = '\n';
+ sendbuf[len] = '\0';
+ }
+
+ if (IsMe(to))
+ {
+ char tmp_sendbuf[sizeof(sendbuf)];
+
+ strcpy(tmp_sendbuf, sendbuf);
+ sendto_ops("Trying to send [%s] to myself!", tmp_sendbuf);
+ return;
+ }
+
+ if (DBufLength(&to->sendQ) > get_sendq(to))
+ {
+ if (IsServer(to))
+ sendto_ops("Max SendQ limit exceeded for %s: "
+ "%lu > %lu",
+ get_client_name(to, FALSE), DBufLength(&to->sendQ), get_sendq(to));
+ dead_link(to, "Max SendQ exceeded");
+ return;
+ }
+
+ else if (!dbuf_put(&to->sendQ, sendbuf, len))
+ {
+ dead_link(to, "Buffer allocation error");
+ return;
+ }
+ /*
+ * Update statistics. The following is slightly incorrect
+ * because it counts messages even if queued, but bytes
+ * only really sent. Queued bytes get updated in SendQueued.
+ */
+ to->sendM += 1;
+ me.sendM += 1;
+ if (to->acpt != &me)
+ to->acpt->sendM += 1;
+ /*
+ * This little bit is to stop the sendQ from growing too large when
+ * there is no need for it to. Thus we call send_queued() every time
+ * 2k has been added to the queue since the last non-fatal write.
+ * Also stops us from deliberately building a large sendQ and then
+ * trying to flood that link with data (possible during the net
+ * relinking done by servers with a large load).
+ */
+ if (DBufLength(&to->sendQ) / 1024 > to->lastsq)
+ send_queued(to);
+}
+
+void sendto_channel_butone(aClient *one, aClient *from, aChannel *chptr, char *pattern, ...)
+{
+ va_list vl;
+ Link *lp;
+ aClient *acptr;
+ int i;
+
+ va_start(vl, pattern);
+
+ ++sentalong_marker;
+ for (lp = chptr->members; lp; lp = lp->next)
+ {
+ acptr = lp->value.cptr;
+ /* ...was the one I should skip */
+ if (acptr->from == one || (IsDeaf(acptr) && !(sendanyways==1)))
+ continue;
+ if (MyConnect(acptr)) /* (It is always a client) */
+ vsendto_prefix_one(acptr, from, pattern, vl);
+ else if (sentalong[(i = acptr->from->fd)] != sentalong_marker)
+ {
+ sentalong[i] = sentalong_marker;
+ /*
+ * Burst messages comes here..
+ */
+ vsendto_prefix_one(acptr, from, pattern, vl);
+ }
+ }
+ va_end(vl);
+}
+
+/*
+ * sendto_channelops_butone Added 1 Sep 1996 by Cabal95.
+ * Send a message to all OPs in channel chptr that
+ * are directly on this server and sends the message
+ * on to the next server if it has any OPs.
+ *
+ * All servers must have this functional ability
+ * or one without will send back an error message. -- Cabal95
+ */
+void sendto_channelops_butone(aClient *one, aClient *from, aChannel *chptr, char *pattern, ...)
+{
+ va_list vl;
+ Reg1 Link *lp;
+ Reg2 aClient *acptr;
+ Reg3 int i;
+
+ va_start(vl,pattern);
+ for (i = 0; i < MAXCONNECTIONS; i++)
+ sentalong[i] = 0;
+ for (lp = chptr->members; lp; lp = lp->next)
+ {
+ acptr = lp->value.cptr;
+ if (acptr->from == one ||
+ !(lp->flags & CHFL_CHANOP))
+ continue; /* ...was the one I should skip
+ or user not not a channel op */
+ i = acptr->from->fd;
+ if (MyConnect(acptr) && IsRegisteredUser(acptr))
+ {
+ vsendto_prefix_one(acptr, from, pattern, vl);
+ sentalong[i] = 1;
+ }
+ else
+ {
+ /* Now check whether a message has been sent to this
+ * remote link already */
+ if (sentalong[i] == 0)
+ {
+ vsendto_prefix_one(acptr, from, pattern, vl);
+ sentalong[i] = 1;
+ }
+ }
+ }
+ va_end(vl);
+ return;
+}
+
+/*
+ * sendto_channelvoice_butone
+ * direct port of Cabal95's sendto_channelops_butone
+ * to allow for /notice @+#channel messages
+ * not exactly the most adventurous coding (made heavy use of copy-paste) <G>
+ * but it's needed to avoid mass-msg trigger in script vnotices
+ * -DuffJ
+ */
+
+void sendto_channelvoice_butone(aClient *one, aClient *from, aChannel *chptr, char *pattern, ...)
+{
+ va_list vl;
+ Reg1 Link *lp;
+ Reg2 aClient *acptr;
+ Reg3 int i;
+
+ va_start(vl,pattern);
+ for (i = 0; i < MAXCONNECTIONS; i++)
+ sentalong[i] = 0;
+ for (lp = chptr->members; lp; lp = lp->next)
+ {
+ acptr = lp->value.cptr;
+ if (acptr->from == one ||
+ !((lp->flags & CHFL_VOICE) || (lp->flags & CHFL_CHANOP) || (lp->flags & CHFL_HALFOP)))
+ continue; /* ...was the one I should skip
+ or user not (a channel voice or op) */
+ i = acptr->from->fd;
+ if (MyConnect(acptr) && IsRegisteredUser(acptr))
+ {
+ vsendto_prefix_one(acptr, from, pattern, vl);
+ sentalong[i] = 1;
+ }
+ else
+ {
+ /* Now check whether a message has been sent to this
+ * remote link already */
+ if (sentalong[i] == 0)
+ {
+ vsendto_prefix_one(acptr, from, pattern, vl);
+ sentalong[i] = 1;
+ }
+ }
+ }
+ va_end(vl);
+ return;
+}
+
+/*
+ * sendto_channelhalfop_butone
+ * direct port of Cabal95's sendto_channelops_butone
+ * to allow for /notice @+#channel messages
+ * not exactly the most adventurous coding (made heavy use of copy-paste) <G>
+ * but it's needed to avoid mass-msg trigger in script hnotices
+ * -Stskeeps
+ */
+
+void sendto_channelhalfop_butone(aClient *one, aClient *from, aChannel *chptr, char *pattern, ...)
+{
+ va_list vl;
+ Reg1 Link *lp;
+ Reg2 aClient *acptr;
+ Reg3 int i;
+
+ va_start(vl,pattern);
+ for (i = 0; i < MAXCONNECTIONS; i++)
+ sentalong[i] = 0;
+ for (lp = chptr->members; lp; lp = lp->next)
+ {
+ acptr = lp->value.cptr;
+ if (acptr->from == one ||
+ !((lp->flags & CHFL_HALFOP) || (lp->flags & CHFL_CHANOP)))
+ continue; /* ...was the one I should skip
+ or user not (a channel halfop or op) */
+ i = acptr->from->fd;
+ if (MyConnect(acptr) && IsRegisteredUser(acptr))
+ {
+ vsendto_prefix_one(acptr, from, pattern, vl);
+ sentalong[i] = 1;
+ }
+ else
+ {
+ /* Now check whether a message has been sent to this
+ * remote link already */
+ if (sentalong[i] == 0)
+ {
+ vsendto_prefix_one(acptr, from, pattern, vl);
+ sentalong[i] = 1;
+ }
+ }
+ }
+ va_end(vl);
+ return;
+}
+
+/*
+ * sendto_server_butone
+ *
+ * Send a message to all connected servers except the client 'one'.
+ */
+void sendto_serv_butone(aClient *one, char *pattern, ...)
+{
+ va_list vl;
+ Reg1 int i;
+ Reg2 aClient *cptr;
+#ifndef NO_FDLIST
+ Reg3 int j;
+#endif
+
+ va_start(vl,pattern);
+#ifdef NO_FDLIST
+ for (i = 0; i <= highest_fd; i++)
+#else
+ for (i=serv_fdlist.entry[j=1];j<=serv_fdlist.last_entry;
+ i=serv_fdlist.entry[++j])
+#endif
+ {
+ if (!(cptr = local[i]) || (one && cptr == one->from))
+ continue;
+#ifdef NO_FDLIST
+ if (IsServer(cptr))
+#endif
+ vsendto_one(cptr, pattern, vl);
+ }
+ va_end(vl);
+ return;
+}
+
+/*
+ * sendto_serv_butone_quit
+ *
+ * Send a message to all connected servers except the client 'one'.
+ * BUT, don't send to NOQUIT servers.
+ */
+void sendto_serv_butone_quit(aClient *one, char *pattern, ...)
+{
+ va_list vl;
+ Reg1 int i;
+ Reg2 aClient *cptr;
+#ifndef NO_FDLIST
+ Reg3 int j;
+#endif
+ va_start(vl,pattern);
+
+#ifdef NO_FDLIST
+ for (i = 0; i <= highest_fd; i++)
+#else
+ for (i=serv_fdlist.entry[j=1];j<=serv_fdlist.last_entry;
+ i=serv_fdlist.entry[++j])
+#endif
+ {
+ if (!(cptr = local[i]) || (one && cptr == one->from))
+ continue;
+#ifdef NO_FDLIST
+ if (IsServer(cptr) && !DontSendQuit(cptr))
+#else
+ if (!DontSendQuit(cptr))
+#endif
+ vsendto_one(cptr, pattern, vl);
+ }
+ va_end(vl);
+ return;
+}
+
+/*
+ * sendto_serv_butone_sjoin
+ *
+ * Send a message to all connected servers except the client 'one'.
+ * BUT, don't send to SJOIN servers.
+ */
+void sendto_serv_butone_sjoin(aClient *one, char *pattern, ...)
+{
+ va_list vl;
+ Reg1 int i;
+ Reg2 aClient *cptr;
+#ifndef NO_FDLIST
+ Reg3 int j;
+#endif
+ va_start(vl,pattern);
+#ifdef NO_FDLIST
+ for (i = 0; i <= highest_fd; i++)
+#else
+ for (i=serv_fdlist.entry[j=1];j<=serv_fdlist.last_entry;
+ i=serv_fdlist.entry[++j])
+#endif
+ {
+ if (!(cptr = local[i]) || (one && cptr == one->from))
+ continue;
+#ifdef NO_FDLIST
+ if (IsServer(cptr) && !SupportSJOIN(cptr))
+#else
+ if (!SupportSJOIN(cptr))
+#endif
+ vsendto_one(cptr, pattern, vl);
+ }
+ va_end(vl);
+ return;
+}
+
+/*
+ * sendto_serv_sjoin
+ *
+ * Send a message to all connected servers except the client 'one'.
+ * BUT only send to SJOIN servers.
+ */
+void sendto_serv_sjoin(aClient *one, char *pattern, ...)
+{
+ va_list vl;
+ Reg1 int i;
+ Reg2 aClient *cptr;
+#ifndef NO_FDLIST
+ Reg3 int j;
+#endif
+ va_start(vl,pattern);
+
+#ifdef NO_FDLIST
+ for (i = 0; i <= highest_fd; i++)
+#else
+ for (i=serv_fdlist.entry[j=1];j<=serv_fdlist.last_entry;
+ i=serv_fdlist.entry[++j])
+#endif
+ {
+ if (!(cptr = local[i]) || (one && cptr == one->from))
+ continue;
+#ifdef NO_FDLIST
+ if (IsServer(cptr) && SupportSJOIN(cptr))
+#else
+ if (SupportSJOIN(cptr))
+#endif
+ vsendto_one(cptr, pattern, vl);
+ }
+ va_end(vl);
+ return;
+}
+
+/*
+ * sendto_serv_butone_nickv2
+ *
+ * Send a message to all connected servers except the client 'one'.
+ * BUT, don't send to NICKv2 servers.
+ */
+void sendto_serv_butone_nickv2(aClient *one, char *pattern, ...)
+{
+ va_list vl;
+ Reg1 int i;
+ Reg2 aClient *cptr;
+#ifndef NO_FDLIST
+ Reg3 int j;
+#endif
+ va_start(vl,pattern);
+
+#ifdef NO_FDLIST
+ for (i = 0; i <= highest_fd; i++)
+#else
+ for (i=serv_fdlist.entry[j=1];j<=serv_fdlist.last_entry;
+ i=serv_fdlist.entry[++j])
+#endif
+ {
+ if (!(cptr = local[i]) || (one && cptr == one->from))
+ continue;
+#ifdef NO_FDLIST
+ if (IsServer(cptr) && !SupportNICKv2(cptr))
+#else
+ if (!SupportNICKv2(cptr))
+#endif
+ vsendto_one(cptr, pattern, vl);
+ }
+ va_end(vl);
+ return;
+}
+
+/*
+ * sendto_serv_nickv2
+ *
+ * Send a message to all connected servers except the client 'one'.
+ * BUT only send to NICKv2 servers.
+ */
+void sendto_serv_nickv2(aClient *one, char *pattern, ...)
+{
+ va_list vl;
+ Reg1 int i;
+ Reg2 aClient *cptr;
+#ifndef NO_FDLIST
+ Reg3 int j;
+#endif
+ va_start(vl,pattern);
+
+#ifdef NO_FDLIST
+ for (i = 0; i <= highest_fd; i++)
+#else
+ for (i=serv_fdlist.entry[j=1];j<=serv_fdlist.last_entry;
+ i=serv_fdlist.entry[++j])
+#endif
+ {
+ if (!(cptr = local[i]) || (one && cptr == one->from))
+ continue;
+#ifdef NO_FDLIST
+ if (IsServer(cptr) && SupportNICKv2(cptr))
+#else
+ if (SupportNICKv2(cptr))
+#endif
+ vsendto_one(cptr, pattern, vl);
+ }
+ va_end(vl);
+ return;
+}
+
+/*
+ * sendto_common_channels()
+ *
+ * Sends a message to all people (inclusing user) on local server who are
+ * in same channel with user.
+ */
+void sendto_common_channels(aClient *user, char *pattern, ...)
+{
+va_list vl;
+
+register Link *channels;
+register Link *users;
+register aClient *cptr;
+
+ va_start(vl,pattern);
+ memset((char *) sentalong, '\0', sizeof(sentalong));
+ if (user->fd >= 0)
+ sentalong[user->fd] = 1;
+ if (user->user)
+ for (channels = user->user->channel; channels; channels = channels->next)
+ for (users = channels->value.chptr->members; users; users = users->next) {
+ cptr = users->value.cptr;
+ if (!MyConnect(cptr) || sentalong[cptr->fd])
+ continue;
+ sentalong[cptr->fd]++;
+ vsendto_prefix_one(cptr, user, pattern, vl);
+ }
+ if (MyConnect(user))
+ vsendto_prefix_one(user, user, pattern, vl);
+ va_end(vl);
+ return;
+}
+/*
+ * sendto_channel_butserv
+ *
+ * Send a message to all members of a channel that are connected to this
+ * server.
+ */
+void sendto_channel_butserv(aChannel *chptr, aClient *from, char *pattern, ...)
+{
+ va_list vl;
+ Reg1 Link *lp;
+ Reg2 aClient *acptr;
+
+ for (va_start(vl,pattern), lp = chptr->members; lp; lp = lp->next)
+ if (MyConnect(acptr = lp->value.cptr))
+ vsendto_prefix_one(acptr, from, pattern, vl);
+ va_end(vl);
+ return;
+}
+
+/*
+** send a msg to all ppl on servers/hosts that match a specified mask
+** (used for enhanced PRIVMSGs)
+**
+** addition -- Armin, 8jun90 (gruner@informatik.tu-muenchen.de)
+*/
+
+static int match_it(one, mask, what)
+aClient *one;
+char *mask;
+int what;
+{
+ switch (what)
+ {
+ case MATCH_HOST:
+ return (match(mask, one->user->realhost)==0);
+ case MATCH_SERVER:
+ default:
+ return (match(mask, one->user->server)==0);
+ }
+}
+
+/*
+ * sendto_match_servs
+ *
+ * send to all servers which match the mask at the end of a channel name
+ * (if there is a mask present) or to all if no mask.
+ */
+void sendto_match_servs(aChannel *chptr, aClient *from, char *format, ...)
+{
+ va_list vl;
+ Reg1 int i;
+ Reg2 aClient *cptr;
+ char *mask;
+
+ va_start(vl, format);
+
+ if (chptr)
+ {
+ if (*chptr->chname == '&')
+ return;
+ if (mask = (char *)rindex(chptr->chname, ':'))
+ mask++;
+ }
+ else
+ mask = (char *)NULL;
+
+ for (i = 0; i <= highest_fd; i++)
+ {
+ if (!(cptr = local[i]))
+ continue;
+ if ((cptr == from) || !IsServer(cptr))
+ continue;
+ if (!BadPtr(mask) && IsServer(cptr) &&
+ match(mask, cptr->name))
+ continue;
+ vsendto_one(cptr, format, vl);
+ }
+ va_end(vl);
+}
+
+/*
+ * sendto_match_butone
+ *
+ * Send to all clients which match the mask in a way defined on 'what';
+ * either by user hostname or user servername.
+ */
+void sendto_match_butone(aClient *one, aClient *from, char *mask, int what, char *pattern, ...)
+{
+ va_list vl;
+ Reg1 int i;
+ Reg2 aClient *cptr, *acptr;
+ char cansendlocal, cansendglobal;
+
+ va_start(vl,pattern);
+ if (MyConnect(from))
+ {
+ cansendlocal = (OPCanLNotice(from)) ? 1 : 0;
+ cansendglobal = (OPCanGNotice(from)) ? 1 : 0;
+ }
+ else
+ cansendlocal = cansendglobal = 1;
+
+ for (i = 0; i <= highest_fd; i++)
+ {
+ if (!(cptr = local[i]))
+ continue; /* that clients are not mine */
+ if (cptr == one) /* must skip the origin !! */
+ continue;
+ if (IsServer(cptr))
+ {
+ if (!cansendglobal)
+ continue;
+ for (acptr = client; acptr; acptr = acptr->next)
+ if (IsRegisteredUser(acptr)
+ && match_it(acptr, mask, what)
+ && acptr->from == cptr)
+ break;
+ /* a person on that server matches the mask, so we
+ ** send *one* msg to that server ...
+ */
+ if (acptr == NULL)
+ continue;
+ /* ... but only if there *IS* a matching person */
+ }
+ /* my client, does he match ? */
+ else if (!cansendlocal || (!(IsRegisteredUser(cptr) &&
+ match_it(cptr, mask, what))))
+ continue;
+ vsendto_prefix_one(cptr, from, pattern, vl);
+ }
+ va_end(vl);
+ return;
+}
+
+/*
+ * sendto_all_butone.
+ *
+ * Send a message to all connections except 'one'. The basic wall type
+ * message generator.
+ */
+
+void sendto_all_butone(aClient *one, aClient *from, char *pattern, ...)
+{
+ va_list vl;
+ Reg1 int i;
+ Reg2 aClient *cptr;
+
+ for (va_start(vl,pattern), i = 0; i <= highest_fd; i++)
+ if ((cptr = local[i]) && !IsMe(cptr) && one != cptr)
+ vsendto_prefix_one(cptr, from, pattern, vl);
+ va_end(vl);
+ return;
+}
+
+/*
+ * sendto_ops
+ *
+ * Send to *local* ops only.
+ */
+void sendto_ops(char *pattern, ...)
+{
+ va_list vl;
+ Reg1 aClient *cptr;
+ Reg2 int i;
+ char nbuf[1024];
+
+ va_start(vl,pattern);
+ for (i = 0; i <= highest_fd; i++)
+ if ((cptr = local[i]) && !IsServer(cptr) && !IsMe(cptr) &&
+ SendServNotice(cptr))
+ {
+ (void)sprintf(nbuf, ":%s NOTICE %s :*** Notice -- ",
+ me.name, cptr->name);
+ (void)strncat(nbuf, pattern,
+ sizeof(nbuf) - strlen(nbuf));
+ vsendto_one(cptr, nbuf, vl);
+ }
+ va_end(vl);
+ return;
+}
+
+/*
+ * sendto_failops
+ *
+ * Send to *local* mode +g ops only.
+ */
+void sendto_failops(char *pattern, ...)
+{
+ va_list vl;
+ Reg1 aClient *cptr;
+ Reg2 int i;
+ char nbuf[1024];
+
+ va_start(vl,pattern);
+ for (i = 0; i <= highest_fd; i++)
+ if ((cptr = local[i]) && !IsServer(cptr) && !IsMe(cptr) &&
+ SendFailops(cptr))
+ {
+ (void)sprintf(nbuf, ":%s NOTICE %s :*** Global -- ",
+ me.name, cptr->name);
+ (void)strncat(nbuf, pattern,
+ sizeof(nbuf) - strlen(nbuf));
+ vsendto_one(cptr, nbuf, vl);
+ }
+ va_end(vl);
+ return;
+}
+
+/*
+ * sendto_chatops
+ *
+ * Send to *local* mode +b ops only.
+ */
+/*
+sendto_umode does just as good a job -- codemastr
+ void sendto_chatops(char *pattern, ...)
+{
+ va_list vl;
+ Reg1 aClient *cptr;
+ Reg2 int i;
+ char nbuf[1024];
+
+ va_start(vl,pattern);
+ for (i = 0; i <= highest_fd; i++)
+ if ((cptr = local[i]) && !IsServer(cptr) && !IsMe(cptr) &&
+ SendChatops(cptr))
+ {
+ (void)sprintf(nbuf, ":%s NOTICE %s :*** ChatOps -- ",
+ me.name, cptr->name);
+ (void)strncat(nbuf, pattern,
+ sizeof(nbuf) - strlen(nbuf));
+ vsendto_one(cptr, nbuf, vl);
+ }
+ va_end(vl);
+ return;
+} */
+
+/*
+ * sendto_helpops
+ *
+ * Send to mode +h people
+ */
+void sendto_helpops(char *pattern, ...)
+{
+ va_list vl;
+ Reg1 aClient *cptr;
+ Reg2 int i;
+ char nbuf[1024];
+
+ va_start(vl,pattern);
+ for (i = 0; i <= highest_fd; i++)
+ if ((cptr = local[i]) && !IsServer(cptr) && !IsMe(cptr) &&
+ IsHelpOp(cptr))
+ {
+ (void)sprintf(nbuf, ":%s NOTICE %s :*** HelpOp -- ",
+ me.name, cptr->name);
+ (void)strncat(nbuf, pattern,
+ sizeof(nbuf) - strlen(nbuf));
+ vsendto_one(cptr, nbuf, vl);
+ }
+ va_end(vl);
+ return;
+}
+
+/*
+ * sendto_umode
+ *
+ * Send to specified umode
+ */
+void sendto_umode(int umodes, char *pattern, ...)
+{
+ va_list vl;
+ Reg1 aClient *cptr;
+ Reg2 int i;
+ char nbuf[1024];
+ Reg3 int w;
+ va_start(vl,pattern);
+ w = (umodes == UMODE_OPER|UMODE_CLIENT ? 1 : 0);
+ for (i = 0; i <= highest_fd; i++)
+ if ((cptr = local[i]) && !IsServer(cptr) && !IsMe(cptr) &&
+ (cptr->umodes & umodes)==umodes && ((w == 1) && !IsHybNotice(cptr)))
+ {
+ (void)sprintf(nbuf, ":%s NOTICE %s :",
+ me.name, cptr->name);
+ (void)strncat(nbuf, pattern,
+ sizeof(nbuf) - strlen(nbuf));
+ vsendto_one(cptr, nbuf, vl);
+ }
+ va_end(vl);
+ return;
+}
+
+/*
+ * sendto_conn_hcn
+ *
+ * Send to umode +c && IsHybNotice(cptr)
+ */
+void sendto_conn_hcn(char *pattern, ...)
+{
+ va_list vl;
+ Reg1 aClient *cptr;
+ Reg2 int i;
+ char nbuf[1024];
+
+ va_start(vl,pattern);
+ for (i = 0; i <= highest_fd; i++)
+ if ((cptr = local[i]) && !IsServer(cptr) && !IsMe(cptr) &&
+ (cptr->umodes & UMODE_CLIENT) && IsHybNotice(cptr))
+ {
+ (void)sprintf(nbuf, ":%s NOTICE %s :",
+ me.name, cptr->name);
+ (void)strncat(nbuf, pattern,
+ sizeof(nbuf) - strlen(nbuf));
+ vsendto_one(cptr, nbuf, vl);
+ }
+ va_end(vl);
+ return;
+}
+
+/*
+ * sendto_failops_whoare_opers
+ *
+ * Send to *local* mode +g ops only who are also +o.
+ */
+void sendto_failops_whoare_opers(char *pattern, ...)
+{
+ va_list vl;
+ Reg1 aClient *cptr;
+ Reg2 int i;
+ char nbuf[1024];
+
+ va_start(vl,pattern);
+ for (i = 0; i <= highest_fd; i++)
+ if ((cptr = local[i]) && !IsServer(cptr) && !IsMe(cptr) &&
+ SendFailops(cptr) && IsAnOper(cptr))
+ {
+ (void)sprintf(nbuf, ":%s NOTICE %s :*** Global -- ",
+ me.name, cptr->name);
+ (void)strncat(nbuf, pattern,
+ sizeof(nbuf) - strlen(nbuf));
+ vsendto_one(cptr, nbuf, vl);
+ }
+ va_end(vl);
+ return;
+}
+/*
+ * sendto_locfailops
+ *
+ * Send to *local* mode +g ops only who are also +o.
+ */
+void sendto_locfailops(char *pattern, ...)
+{
+ va_list vl;
+ Reg1 aClient *cptr;
+ Reg2 int i;
+ char nbuf[1024];
+
+ va_start(vl, pattern);
+ for (i = 0; i <= highest_fd; i++)
+ if ((cptr = local[i]) && !IsServer(cptr) && !IsMe(cptr) &&
+ SendFailops(cptr) && IsAnOper(cptr))
+ {
+ (void)sprintf(nbuf, ":%s NOTICE %s :*** LocOps -- ",
+ me.name, cptr->name);
+ (void)strncat(nbuf, pattern,
+ sizeof(nbuf) - strlen(nbuf));
+ vsendto_one(cptr, nbuf, vl);
+ }
+ va_end(vl);
+ return;
+}
+/*
+ * sendto_opers
+ *
+ * Send to *local* ops only. (all +O or +o people)
+ */
+void sendto_opers(char *pattern, ...)
+{
+ va_list vl;
+ Reg1 aClient *cptr;
+ Reg2 int i;
+ char nbuf[1024];
+
+ va_start(vl,pattern);
+ for (i = 0; i <= highest_fd; i++)
+ if ((cptr = local[i]) && !IsServer(cptr) && !IsMe(cptr) &&
+ IsAnOper(cptr))
+ {
+ (void)sprintf(nbuf, ":%s NOTICE %s :*** Oper -- ",
+ me.name, cptr->name);
+ (void)strncat(nbuf, pattern,
+ sizeof(nbuf) - strlen(nbuf));
+ vsendto_one(cptr, nbuf, vl);
+ }
+ va_end(vl);
+ return;
+}
+
+/* ** sendto_ops_butone
+** Send message to all operators.
+** one - client not to send message to
+** from- client which message is from *NEVER* NULL!!
+*/
+void sendto_ops_butone(aClient *one, aClient *from, char *pattern, ...)
+{
+ va_list vl;
+ Reg1 int i;
+ Reg2 aClient *cptr;
+
+ va_start(vl,pattern);
+ for (i=0; i <= highest_fd; i++)
+ sentalong[i] = 0;
+ for (cptr = client; cptr; cptr = cptr->next)
+ {
+ if (!SendWallops(cptr))
+ continue;
+ i = cptr->from->fd; /* find connection oper is on */
+ if (sentalong[i]) /* sent message along it already ? */
+ continue;
+ if (cptr->from == one)
+ continue; /* ...was the one I should skip */
+ sentalong[i] = 1;
+ vsendto_prefix_one(cptr->from, from, pattern, vl);
+ }
+ va_end(vl);
+ return;
+}
+
+/*
+** sendto_ops_butone
+** Send message to all operators regardless of whether they are +w or
+** not..
+** one - client not to send message to
+** from- client which message is from *NEVER* NULL!!
+*/
+void sendto_opers_butone(aClient *one, aClient *from, char *pattern, ...)
+{
+ va_list vl;
+ Reg1 int i;
+ Reg2 aClient *cptr;
+
+ va_start(vl,pattern);
+ for (i=0; i <= highest_fd; i++)
+ sentalong[i] = 0;
+ for (cptr = client; cptr; cptr = cptr->next)
+ {
+ if (!IsAnOper(cptr))
+ continue;
+ i = cptr->from->fd; /* find connection oper is on */
+ if (sentalong[i]) /* sent message along it already ? */
+ continue;
+ if (cptr->from == one)
+ continue; /* ...was the one I should skip */
+ sentalong[i] = 1;
+ vsendto_prefix_one(cptr->from, from, pattern, vl);
+ }
+ va_end(vl);
+ return;
+}
+/*
+** sendto_ops_butme
+** Send message to all operators except local ones
+** from- client which message is from *NEVER* NULL!!
+*/
+void sendto_ops_butme(aClient *from, char *pattern, ...)
+{
+ va_list vl;
+ Reg1 int i;
+ Reg2 aClient *cptr;
+
+ va_start(vl,pattern);
+ for (i=0; i <= highest_fd; i++)
+ sentalong[i] = 0;
+ for (cptr = client; cptr; cptr = cptr->next)
+ {
+ if (!SendWallops(cptr))
+ continue;
+ i = cptr->from->fd; /* find connection oper is on */
+ if (sentalong[i]) /* sent message along it already ? */
+ continue;
+ if (!strcmp(cptr->user->server, me.name)) /* a locop */
+ continue;
+ sentalong[i] = 1;
+ vsendto_prefix_one(cptr->from, from, pattern, vl);
+ }
+ va_end(vl);
+ return;
+}
+
+void vsendto_prefix_one(struct Client *to, struct Client *from,
+ const char* pattern, va_list vl)
+{
+ if (to && from && MyClient(to) && from->user)
+ {
+ static char sender[HOSTLEN + NICKLEN + USERLEN + 5];
+ char *par;
+ int flag = 0;
+ struct User *user = from->user;
+
+ par = va_arg(vl, char *);
+ strcpy(sender, from->name);
+ if (user)
+ {
+ if (*user->username)
+ {
+ strcat(sender, "!");
+ strcat(sender, user->username);
+ }
+ if (*user->realhost && !MyConnect(from))
+ {
+ strcat(sender, "@");
+ (void)strcat(sender, (!IsHidden(from) ?user->realhost:user->virthost));
+ flag = 1;
+ }
+ }
+ /*
+ * Flag is used instead of strchr(sender, '@') for speed and
+ * also since username/nick may have had a '@' in them. -avalon
+ */
+ if (!flag && MyConnect(from) && *user->realhost)
+ {
+ strcat(sender, "@");
+ strcat(sender, (!IsHidden(from) ? from->sockhost : user->virthost));
+ }
+ *sendbuf = ':';
+ strcpy(&sendbuf[1], sender);
+ /* Assuming 'pattern' always starts with ":%s ..." */
+ vsprintf(sendbuf + strlen(sendbuf), &pattern[3], vl);
+ }
+ else
+ vsprintf(sendbuf, pattern, vl);
+ sendbufto_one(to);
+}
+
+/*
+ * sendto_prefix_one
+ *
+ * to - destination client
+ * from - client which message is from
+ *
+ * NOTE: NEITHER OF THESE SHOULD *EVER* BE NULL!!
+ * -avalon
+ */
+
+void sendto_prefix_one(aClient *to, aClient *from, const char *pattern, ...)
+{
+ va_list vl;
+ va_start(vl, pattern);
+ vsendto_prefix_one(to, from, pattern, vl);
+ va_end(vl);
+}
+
+/*
+ * sendto_realops
+ *
+ * Send to *local* ops only but NOT +s nonopers.
+ */
+void sendto_realops(char *pattern, ...)
+{
+ va_list vl;
+ Reg1 aClient *cptr;
+ Reg2 int i;
+#ifndef NO_FDLIST
+ Reg3 int j;
+#endif
+ char nbuf[1024];
+
+ va_start(vl, pattern);
+#ifdef NO_FDLIST
+ for (i = 0; i <= highest_fd; i++)
+#else
+ for (i=oper_fdlist.entry[j=1];j<=oper_fdlist.last_entry;
+ i=oper_fdlist.entry[++j])
+#endif
+#ifdef NO_FDLIST
+ if ((cptr = local[i]) && !IsServer(cptr) && !IsMe(cptr) &&
+ IsOper(cptr))
+#else
+ if ((cptr = local[i]))
+#endif
+ {
+ (void)sprintf(nbuf, ":%s NOTICE %s :*** Notice -- ",
+ me.name, cptr->name);
+ (void)strncat(nbuf, pattern,
+ sizeof(nbuf) - strlen(nbuf));
+ vsendto_one(cptr, nbuf, vl);
+ }
+ va_end(vl);
+ return;
+}
+
+void sendto_connectnotice(nick, user,sptr)
+char *nick;
+anUser *user;
+aClient *sptr;
+{
+ Reg1 aClient *cptr;
+ Reg2 int i;
+ char connectd[1024];
+ char connecth[1024];
+ sprintf(connectd, "*** Notice -- Client connecting on port %d: %s (%s@%s)",
+ sptr->acpt->port, nick, user->username, user->realhost);
+ sprintf(connecth, "*** Notice -- Client connecting: %s (%s@%s) [%s] {%d}",
+ nick, user->username, user->realhost, sptr->sockhost, get_client_class(sptr));
+
+ for (i = 0; i <= highest_fd; i++)
+ if ((cptr = local[i]) && !IsServer(cptr) && !IsMe(cptr) &&
+ IsOper(cptr) && (cptr->umodes & UMODE_CLIENT))
+ {
+ if (IsHybNotice(cptr))
+ sendto_one(cptr, ":%s NOTICE %s :%s", me.name, cptr->name, connecth);
+ else
+ sendto_one(cptr, ":%s NOTICE %s :%s", me.name, cptr->name, connectd);
+
+ }
+}
\ No newline at end of file
--- /dev/null
+/* $NetBSD: strtoul.c,v 1.9 1996/07/20 01:00:57 jtc Exp $ */
+
+/*
+ * Copyright (c) 1990 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char *sccsid = "from: @(#)strtoul.c 5.3 (Berkeley) 2/23/91";
+#else
+static char *rcsid = "$NetBSD: strtoul.c,v 1.9 1996/07/20 01:00:57 jtc Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+
+/*
+ * Convert a string to an unsigned long integer.
+ *
+ * Ignores `locale' stuff. Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+unsigned long
+strtoul(nptr, endptr, base)
+ char *nptr;
+ char **endptr;
+ int base;
+{
+ char *s;
+ unsigned long acc, cutoff;
+ int c;
+ int neg, any, cutlim;
+
+ /*
+ * See strtol for comments as to the logic used.
+ */
+ s = nptr;
+ do {
+ c = (unsigned char) *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else {
+ neg = 0;
+ if (c == '+')
+ c = *s++;
+ }
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+
+ cutoff = ULONG_MAX / (unsigned long)base;
+ cutlim = ULONG_MAX % (unsigned long)base;
+ for (acc = 0, any = 0;; c = (unsigned char) *s++) {
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0)
+ continue;
+ if (acc > cutoff || acc == cutoff && c > cutlim) {
+ any = -1;
+ acc = ULONG_MAX;
+ errno = ERANGE;
+ } else {
+ any = 1;
+ acc *= (unsigned long)base;
+ acc += c;
+ }
+ }
+ if (neg && any > 0)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (char *) (any ? s - 1 : nptr);
+ return (acc);
+}
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, common/support.c
+ * Copyright (C) 1990, 1991 Armin Gruner
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)support.c 2.21 4/13/94 1990, 1991 Armin Gruner;\
+1992, 1993 Darren Reed";
+#endif
+
+#include "config.h"
+#ifdef DYNIXPTX
+#include <sys/timers.h>
+#include <stddef.h>
+#endif
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#ifdef _WIN32
+#include <io.h>
+#else
+
+ID_CVS("$Id$");
+
+extern int errno; /* ...seems that errno.h doesn't define this everywhere */
+#endif
+extern void outofmemory();
+
+#ifdef NEED_STRTOKEN
+/*
+** strtoken.c -- walk through a string of tokens, using a set
+** of separators
+** argv 9/90
+**
+** $Id$
+*/
+
+char *strtoken(save, str, fs)
+char **save;
+char *str, *fs;
+{
+ char *pos = *save; /* keep last position across calls */
+ Reg1 char *tmp;
+
+ if (str)
+ pos = str; /* new string scan */
+
+ while (pos && *pos && index(fs, *pos) != NULL)
+ pos++; /* skip leading separators */
+
+ if (!pos || !*pos)
+ return (pos = *save = NULL); /* string contains only sep's */
+
+ tmp = pos; /* now, keep position of the token */
+
+ while (*pos && index(fs, *pos) == NULL)
+ pos++; /* skip content of the token */
+
+ if (*pos)
+ *pos++ = '\0'; /* remove first sep after the token */
+ else
+ pos = NULL; /* end of string */
+
+ *save = pos;
+ return(tmp);
+}
+#endif /* NEED_STRTOKEN */
+
+#ifdef NEED_STRTOK
+/*
+** NOT encouraged to use!
+*/
+
+char *strtok2(str, fs)
+char *str, *fs;
+{
+ static char *pos;
+
+ return strtoken(&pos, str, fs);
+}
+
+#endif /* NEED_STRTOK */
+
+#ifdef NEED_STRERROR
+/*
+** strerror - return an appropriate system error string to a given errno
+**
+** argv 11/90
+** $Id$
+*/
+
+char *strerror(err_no)
+int err_no;
+{
+ extern char *sys_errlist[]; /* Sigh... hopefully on all systems */
+ extern int sys_nerr;
+
+ static char buff[40];
+ char *errp;
+
+ errp = (err_no > sys_nerr ? (char *)NULL : sys_errlist[err_no]);
+
+ if (errp == (char *)NULL)
+ {
+ errp = buff;
+#ifndef _WIN32
+ (void) sprintf(errp, "Unknown Error %d", err_no);
+#else
+ switch (err_no)
+ {
+ case WSAECONNRESET:
+ sprintf(errp, "Connection reset by peer");
+ break;
+ default:
+ sprintf(errp, "Unknown Error %d", err_no);
+ break;
+ }
+#endif
+ }
+ return errp;
+}
+
+#endif /* NEED_STRERROR */
+
+/*
+** inetntoa -- changed name to remove collision possibility and
+** so behaviour is gaurunteed to take a pointer arg.
+** -avalon 23/11/92
+** inet_ntoa -- returned the dotted notation of a given
+** internet number (some ULTRIX don't have this)
+** argv 11/90).
+** inet_ntoa -- its broken on some Ultrix/Dynix too. -avalon
+** $Id$
+*/
+
+char *inetntoa(in)
+char *in;
+{
+ static char buf[16];
+ Reg1 u_char *s = (u_char *)in;
+ Reg2 int a,b,c,d;
+
+ a = (int)*s++;
+ b = (int)*s++;
+ c = (int)*s++;
+ d = (int)*s++;
+ (void) sprintf(buf, "%d.%d.%d.%d", a,b,c,d );
+
+ return buf;
+}
+
+#ifdef NEED_INET_NETOF
+/*
+** inet_netof -- return the net portion of an internet number
+** argv 11/90
+** $Id$
+**
+*/
+
+int inet_netof(in)
+struct in_addr in;
+{
+ int addr = in.s_net;
+
+ if (addr & 0x80 == 0)
+ return ((int) in.s_net);
+
+ if (addr & 0x40 == 0)
+ return ((int) in.s_net * 256 + in.s_host);
+
+ return ((int) in.s_net * 256 + in.s_host * 256 + in.s_lh);
+}
+#endif /* NEED_INET_NETOF */
+
+
+#if defined(DEBUGMODE)
+void dumpcore(msg, p1, p2, p3, p4, p5, p6, p7, p8, p9)
+char *msg, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9;
+{
+ static time_t lastd = 0;
+ static int dumps = 0;
+ char corename[12];
+ time_t now;
+ int p;
+
+ now = time(NULL);
+
+ if (!lastd)
+ lastd = now;
+ else if (now - lastd < 60 && dumps > 2)
+ (void)s_die();
+ if (now - lastd > 60)
+ {
+ lastd = now;
+ dumps = 1;
+ }
+ else
+ dumps++;
+#if !defined(_WIN32) && !defined(_AMIGA)
+ p = getpid();
+ if (fork()>0) {
+ kill(p, 3);
+ kill(p, 9);
+ }
+ write_pidfile();
+ (void)sprintf(corename, "core.%d", p);
+ (void)rename("core", corename);
+ Debug((DEBUG_FATAL, "Dumped core : core.%d", p));
+ sendto_ops("Dumped core : core.%d", p);
+#endif
+ Debug((DEBUG_FATAL, msg, p1, p2, p3, p4, p5, p6, p7, p8, p9));
+ sendto_ops(msg, p1, p2, p3, p4, p5, p6, p7, p8, p9);
+ (void)s_die();
+}
+
+static char *marray[20000];
+static int mindex = 0;
+
+#define SZ_EX (sizeof(char *) + sizeof(size_t) + 4)
+#define SZ_CHST (sizeof(char *) + sizeof(size_t))
+#define SZ_CH (sizeof(char *))
+#define SZ_ST (sizeof(size_t))
+
+char *MyMalloc(x)
+size_t x;
+{
+ register int i;
+ register char **s;
+ char *ret;
+
+#ifndef _WIN32
+ ret = (char *)malloc(x + (size_t)SZ_EX);
+#else
+ ret = (char *)GlobalAlloc(GPTR, x + (size_t)SZ_EX);
+#endif
+
+ if (!ret)
+ {
+ outofmemory();
+ }
+ bzero(ret, (int)x + SZ_EX);
+ bcopy((char *)&ret, ret, SZ_CH);
+ bcopy((char *)&x, ret + SZ_CH, SZ_ST);
+ bcopy("VAVA", ret + SZ_CHST + (int)x, 4);
+ Debug((DEBUG_MALLOC, "MyMalloc(%ld) = %#x", x, ret+8));
+ for(i = 0, s = marray; *s && i < mindex; i++, s++)
+ ;
+ if (i < 20000)
+ {
+ *s = ret;
+ if (i == mindex)
+ mindex++;
+ }
+ return ret + SZ_CHST;
+ }
+
+char *MyRealloc(x, y)
+char *x;
+size_t y;
+ {
+ register int l;
+ register char **s;
+ char *ret, *cp;
+ size_t i;
+ int k;
+
+ x -= SZ_CHST;
+ bcopy(x, (char *)&cp, SZ_CH);
+ bcopy(x + SZ_CH, (char *)&i, SZ_ST);
+ bcopy(x + (int)i + SZ_CHST, (char *)&k, 4);
+ if (bcmp((char *)&k, "VAVA", 4) || (x != cp))
+ dumpcore("MyRealloc %#x %d %d %#x %#x", x, y, i, cp, k);
+#ifndef _WIN32
+ ret = (char *)realloc(x, y + (size_t)SZ_EX);
+#else
+ ret = (char *)GlobalReAlloc(x, y + (size_t)SZ_EX, GMEM_MOVEABLE|GMEM_ZEROINIT);
+#endif
+
+ if (!ret)
+ {
+ outofmemory();
+ }
+ bcopy((char *)&ret, ret, SZ_CH);
+ bcopy((char *)&y, ret + SZ_CH, SZ_ST);
+ bcopy("VAVA", ret + SZ_CHST + (int)y, 4);
+ Debug((DEBUG_NOTICE, "MyRealloc(%#x,%ld) = %#x", x, y, ret + SZ_CHST));
+ for(l = 0, s = marray; *s != x && l < mindex; l++, s++)
+ ;
+ if (l < mindex)
+ *s = NULL;
+ else if (l == mindex)
+ Debug((DEBUG_MALLOC, "%#x !found", x));
+ for(l = 0, s = marray; *s && l < mindex; l++,s++)
+ ;
+ if (l < 20000)
+ {
+ *s = ret;
+ if (l == mindex)
+ mindex++;
+ }
+ return ret + SZ_CHST;
+ }
+
+void MyFree(x)
+char *x;
+{
+ size_t i;
+ char *j;
+ u_char k[4];
+ register int l;
+ register char **s;
+
+ if (!x)
+ return;
+ x -= SZ_CHST;
+
+ bcopy(x, (char *)&j, SZ_CH);
+ bcopy(x + SZ_CH, (char *)&i, SZ_ST);
+ bcopy(x + SZ_CHST + (int)i, (char *)k, 4);
+
+ if (bcmp((char *)k, "VAVA", 4) || (j != x))
+ dumpcore("MyFree %#x %ld %#x %#x", x, i, j,
+ (k[3]<<24) | (k[2]<<16) | (k[1]<<8) | k[0]);
+
+#undef free
+#ifndef _WIN32
+ (void)free(x);
+#else
+ (void)GlobalFree(x);
+#endif
+#define free(x) MyFree(x)
+ Debug((DEBUG_MALLOC, "MyFree(%#x)",x + SZ_CHST));
+
+ for (l = 0, s = marray; *s != x && l < mindex; l++, s++)
+ ;
+ if (l < mindex)
+ *s = NULL;
+ else if (l == mindex)
+ Debug((DEBUG_MALLOC, "%#x !found", x));
+}
+
+#else
+char *MyMalloc(x)
+size_t x;
+{
+#ifndef _WIN32
+ char *ret = (char *)malloc(x);
+#else
+ char *ret = (char *)GlobalAlloc(GPTR, x);
+#endif
+
+ if (!ret)
+ {
+ outofmemory();
+ }
+ return ret;
+}
+
+char *MyRealloc(x, y)
+char *x;
+size_t y;
+ {
+#ifndef _WIN32
+ char *ret = (char *)realloc(x, y);
+#else
+ char *ret = (char *)GlobalReAlloc(x, y, GMEM_MOVEABLE|GMEM_ZEROINIT);
+#endif
+
+ if (!ret)
+ {
+ outofmemory();
+ }
+ return ret;
+ }
+#endif
+
+
+/*
+** read a string terminated by \r or \n in from a fd
+**
+** Created: Sat Dec 12 06:29:58 EST 1992 by avalon
+** Returns:
+** 0 - EOF
+** -1 - error on read
+** >0 - number of bytes returned (<=num)
+** After opening a fd, it is necessary to init dgets() by calling it as
+** dgets(x,y,0);
+** to mark the buffer as being empty.
+*/
+int dgets(fd, buf, num)
+int fd, num;
+char *buf;
+{
+ static char dgbuf[8192];
+ static char *head = dgbuf, *tail = dgbuf;
+ register char *s, *t;
+ register int n, nr;
+
+ /*
+ ** Sanity checks.
+ */
+ if (head == tail)
+ *head = '\0';
+ if (!num)
+ {
+ head = tail = dgbuf;
+ *head = '\0';
+ return 0;
+ }
+ if (num > sizeof(dgbuf) - 1)
+ num = sizeof(dgbuf) - 1;
+dgetsagain:
+ if (head > dgbuf)
+ {
+ for (nr = tail - head, s = head, t = dgbuf; nr > 0; nr--)
+ *t++ = *s++;
+ tail = t;
+ head = dgbuf;
+ }
+ /*
+ ** check input buffer for EOL and if present return string.
+ */
+ if (head < tail &&
+ ((s = index(head, '\n')) || (s = index(head, '\r'))) && s < tail)
+ {
+ n = MIN(s - head + 1, num); /* at least 1 byte */
+dgetsreturnbuf:
+ bcopy(head, buf, n);
+ head += n;
+ if (head == tail)
+ head = tail = dgbuf;
+ return n;
+ }
+
+ if (tail - head >= num) /* dgets buf is big enough */
+ {
+ n = num;
+ goto dgetsreturnbuf;
+ }
+
+ n = sizeof(dgbuf) - (tail - dgbuf) - 1;
+ nr = read(fd, tail, n);
+ if (nr == -1)
+ {
+ head = tail = dgbuf;
+ return -1;
+ }
+ if (!nr)
+ {
+ if (head < tail)
+ {
+ n = MIN(tail - head, num);
+ goto dgetsreturnbuf;
+ }
+ head = tail = dgbuf;
+ return 0;
+ }
+ tail += nr;
+ *tail = '\0';
+ for (t = head; (s = index(t, '\n')); )
+ {
+ if ((s > head) && (s > dgbuf))
+ {
+ t = s-1;
+ for (nr = 0; *t == '\\'; nr++)
+ t--;
+ if (nr & 1)
+ {
+ t = s+1;
+ s--;
+ nr = tail - t;
+ while (nr--)
+ *s++ = *t++;
+ tail -= 2;
+ *tail = '\0';
+ }
+ else
+ s++;
+ }
+ else
+ s++;
+ t = s;
+ }
+ *tail = '\0';
+ goto dgetsagain;
+}
--- /dev/null
+/****************************************************************************
+ * Userload module by Michael L. VanLoon (mlv) <michaelv@iastate.edu>
+ * Written 2/93. Originally grafted into irc2.7.2g 4/93.
+ *
+ * IRC - Internet Relay Chat, ircd/userload.c
+ * Copyright (C) 1990 University of Oulu, Computing Center
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************/
+
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#include "userload.h"
+#include <stdio.h>
+#ifndef _WIN32
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/errno.h>
+#else
+#include <io.h>
+#endif
+#include <string.h>
+#include <signal.h>
+#ifndef _WIN32
+#include <sys/resource.h>
+#endif
+#include "h.h"
+
+ID_CVS("$Id$");
+
+struct current_load_struct current_load_data;
+struct load_entry *load_list_head = NULL, *load_list_tail = NULL,
+ *load_free_head = NULL, *load_free_tail = NULL;
+
+#ifdef DEBUGMODE
+clock_t clock_last = 0;
+#endif
+
+void update_load()
+{
+ static struct timeval now, last;
+ register struct load_entry *cur_load_entry;
+
+ /* This seems to get polluted on startup by an exit_client()
+ * before any connections have been recorded.
+ */
+ if (current_load_data.local_count > MAXCONNECTIONS ||
+ current_load_data.client_count > MAXCONNECTIONS ||
+ current_load_data.conn_count > MAXCONNECTIONS)
+ bzero(¤t_load_data, sizeof(struct current_load_struct));
+
+ memcpy(&last, &now, sizeof(struct timeval));
+#ifndef _WIN32
+ if (gettimeofday(&now, NULL) != 0)
+ return; /* error getting time of day--can't calculate time diff */
+#else
+ /* Well, since the windows libs don't have gettimeofday() we have
+ * to improvise a bit, hopefully this will achieve close to the
+ * same result. -Cabal95
+ */
+ now.tv_sec = TStime();
+#endif
+
+ if (load_free_tail == NULL) {
+ if ((cur_load_entry =
+ (struct load_entry *) MyMalloc(sizeof(struct load_entry))) == NULL)
+ return;
+ /* printf("malloc pointer: %x\n", cur_load_entry); */
+ } else {
+ cur_load_entry = load_free_tail;
+ load_free_tail = cur_load_entry->prev;
+ if (load_free_tail == NULL)
+ load_free_head = NULL;
+ /* printf("free pointer: %x\n", cur_load_entry); */
+ }
+ if (load_list_tail != NULL) {
+#ifndef _WIN32
+ cur_load_entry->time_incr = ((now.tv_sec * 1000 + now.tv_usec / 1000 + 5)
+ - (last.tv_sec * 1000 + last.tv_usec / 1000)) / 10;
+#else
+ /* Don't even use *.tv_usec since its an unknown value. -Cabal95 */
+ cur_load_entry->time_incr = ((now.tv_sec * 1000 + 5)
+ - last.tv_sec * 1000) / 10;
+#endif
+ cur_load_entry->local_count = current_load_data.local_count;
+ cur_load_entry->client_count = current_load_data.client_count;
+ cur_load_entry->conn_count = current_load_data.conn_count;
+#ifdef DEBUGMODE
+ cur_load_entry->cpu_usage = (clock()-clock_last);
+ clock_last = clock();
+#endif
+ } else {
+ load_list_head = cur_load_entry;
+ bzero(cur_load_entry, sizeof(struct load_entry));
+ cur_load_entry->time_incr = 1;
+ }
+ cur_load_entry->prev = load_list_tail;
+ load_list_tail = cur_load_entry;
+}
+
+
+void calc_load(sptr, parv)
+aClient *sptr;
+char *parv; /* we only get passed the original parv[0] */
+{
+ register struct load_entry *cur_load_entry;
+ struct load_entry *last;
+#ifdef DEBUGMODE
+ u_long secs = 0, adj_secs, total[4], adj[4];/*[local,client,conn,cpu]*/
+ int i;
+ u_int times[5][4]; /* [min,hour,day,Yest,YYest][local,client,conn,cpu] */
+ char what[4][HOSTLEN + 1];
+
+ bzero(total, 4 * sizeof(u_long));
+#else
+ u_long secs = 0, adj_secs, total[3], adj[3];/*[local,client,conn]*/
+ int i, times[5][3]; /* [min,hour,day,Yest,YYest][local,client,conn] */
+ char what[3][HOSTLEN + 1];
+
+ bzero(total, 3 * sizeof(u_long));
+#endif
+
+ current_load_data.entries = 0;
+
+ update_load(); /* we want stats accurate as of *now* */
+
+ for (cur_load_entry = load_list_tail; (secs < 6000) &&
+ (cur_load_entry != NULL); cur_load_entry = cur_load_entry->prev) {
+ u_long time_incr = cur_load_entry->time_incr;
+ total[0] += time_incr * cur_load_entry->local_count;
+ total[1] += time_incr * cur_load_entry->client_count;
+ total[2] += time_incr * cur_load_entry->conn_count;
+#ifdef DEBUGMODE
+ total[3] += cur_load_entry->cpu_usage;
+#endif
+ last = cur_load_entry;
+ secs += cur_load_entry->time_incr;
+ current_load_data.entries++;
+ }
+ if ((secs > 6000) && (last != NULL)) {
+ adj_secs = secs - 6000;
+ adj[0] = adj_secs * last->local_count;
+ adj[1] = adj_secs * last->client_count;
+ adj[2] = adj_secs * last->conn_count;
+#ifdef DEBUGMODE
+ times[0][3] = total[3]-(last->cpu_usage*(double)adj_secs/last->time_incr);
+ } else {
+ adj_secs = adj[0] = adj[1] = adj[2] = adj[3] = 0;
+ times[0][3] = total[3];
+ }
+#else
+ } else
+ adj_secs = adj[0] = adj[1] = adj[2] = 0;
+#endif
+ for (i = 0; i < 3; i++) {
+ times[0][i] = ((total[i] - adj[i]) * 1000 / (secs - adj_secs) + 5) / 10;
+ }
+
+ secs = (secs + 5) / 10;
+ for (i = 0; i < 3; i++)
+ total[i] = (total[i] + 5) / 10;
+
+ for ( ; (secs < 36000) && (cur_load_entry != NULL); secs +=
+ (cur_load_entry->time_incr + 5) / 10, cur_load_entry =
+ cur_load_entry->prev, current_load_data.entries++) {
+ u_long time_incr = (cur_load_entry->time_incr + 5) / 10;
+ total[0] += time_incr * cur_load_entry->local_count;
+ total[1] += time_incr * cur_load_entry->client_count;
+ total[2] += time_incr * cur_load_entry->conn_count;
+#ifdef DEBUGMODE
+ total[3] += cur_load_entry->cpu_usage;
+#endif
+ last = cur_load_entry;
+ }
+ if ((secs > 36000) && (last != NULL)) {
+ adj_secs = secs - 36000;
+ adj[0] = adj_secs * last->local_count;
+ adj[1] = adj_secs * last->client_count;
+ adj[2] = adj_secs * last->conn_count;
+#ifdef DEBUGMODE
+ times[1][3] = total[3]-(last->cpu_usage*(double)adj_secs/last->time_incr);
+ } else {
+ adj_secs = adj[0] = adj[1] = adj[2] = adj[3] = 0;
+ times[1][3] = total[3];
+ }
+#else
+ } else
+ adj_secs = adj[0] = adj[1] = adj[2] = 0;
+#endif
+ for (i = 0; i < 3; i++) {
+ times[1][i] = ((total[i] - adj[i]) * 100 / (secs - adj_secs) + 5) / 10;
+ }
+
+ secs = (secs + 5) / 10;
+ for (i = 0; i < 3; i++)
+ total[i] = (total[i] + 5) / 10;
+
+ for ( ; (secs < 86400) && (cur_load_entry != NULL); secs +=
+ (cur_load_entry->time_incr + 50) / 100, cur_load_entry =
+ cur_load_entry->prev, current_load_data.entries++) {
+ u_long time_incr = (cur_load_entry->time_incr + 50) / 100;
+ total[0] += time_incr * cur_load_entry->local_count;
+ total[1] += time_incr * cur_load_entry->client_count;
+ total[2] += time_incr * cur_load_entry->conn_count;
+#ifdef DEBUGMODE
+ total[3] += cur_load_entry->cpu_usage;
+#endif
+ last = cur_load_entry;
+ }
+ if ((secs > 86400) && (last != NULL)) {
+ adj_secs = secs - 86400;
+ adj[0] = adj_secs * last->local_count;
+ adj[1] = adj_secs * last->client_count;
+ adj[2] = adj_secs * last->conn_count;
+#ifdef DEBUGMODE
+ times[2][3] = total[3]-(last->cpu_usage*(double)adj_secs/last->time_incr);
+ } else {
+ adj_secs = adj[0] = adj[1] = adj[2] = adj[3] = 0;
+ times[2][3] = total[3];
+ }
+#else
+ } else
+ adj_secs = adj[0] = adj[1] = adj[2] = 0;
+#endif
+ for (i = 0; i < 3; i++) {
+ times[2][i] = ((total[i] - adj[i]) * 10 / (secs - adj_secs) + 5) / 10;
+ }
+
+#ifdef DEBUGMODE
+ bzero(total, 4 * sizeof(u_long));
+#else
+ bzero(total, 3 * sizeof(u_long));
+#endif
+
+ for (secs = 1 ; (secs < 86400) && (cur_load_entry != NULL); secs +=
+ (cur_load_entry->time_incr + 50) / 100, cur_load_entry =
+ cur_load_entry->prev, current_load_data.entries++) {
+ u_long time_incr = (cur_load_entry->time_incr + 50) / 100;
+ total[0] += time_incr * cur_load_entry->local_count;
+ total[1] += time_incr * cur_load_entry->client_count;
+ total[2] += time_incr * cur_load_entry->conn_count;
+#ifdef DEBUGMODE
+ total[3] += cur_load_entry->cpu_usage;
+#endif
+ last = cur_load_entry;
+ }
+ if ((secs > 86400) && (last != NULL)) {
+ adj_secs = secs - 86400;
+ adj[0] = adj_secs * last->local_count;
+ adj[1] = adj_secs * last->client_count;
+ adj[2] = adj_secs * last->conn_count;
+#ifdef DEBUGMODE
+ times[3][3] = total[3]-(last->cpu_usage*(double)adj_secs/last->time_incr);
+ } else {
+ adj_secs = adj[0] = adj[1] = adj[2] = adj[3] = 0;
+ times[3][3] = total[3];
+ }
+#else
+ } else
+ adj_secs = adj[0] = adj[1] = adj[2] = 0;
+#endif
+ for (i = 0; i < 3; i++) {
+ times[3][i] = ((total[i] - adj[i]) * 10 / (secs - adj_secs) + 5) / 10;
+ }
+
+#ifdef DEBUGMODE
+ bzero(total, 4 * sizeof(u_long));
+#else
+ bzero(total, 3 * sizeof(u_long));
+#endif
+
+ for (secs = 1 ; (secs < 86400) && (cur_load_entry != NULL); secs +=
+ (cur_load_entry->time_incr + 50) / 100, cur_load_entry =
+ cur_load_entry->prev, current_load_data.entries++) {
+ u_long time_incr = (cur_load_entry->time_incr + 50) / 100;
+ total[0] += time_incr * cur_load_entry->local_count;
+ total[1] += time_incr * cur_load_entry->client_count;
+ total[2] += time_incr * cur_load_entry->conn_count;
+#ifdef DEBUGMODE
+ total[3] += cur_load_entry->cpu_usage;
+#endif
+ last = cur_load_entry;
+ }
+ if ((secs > 86400) && (last != NULL)) {
+ adj_secs = secs - 86400;
+ adj[0] = adj_secs * last->local_count;
+ adj[1] = adj_secs * last->client_count;
+ adj[2] = adj_secs * last->conn_count;
+#ifdef DEBUGMODE
+ times[4][3] = total[3]-(last->cpu_usage*(double)adj_secs/last->time_incr);
+ } else {
+ adj_secs = adj[0] = adj[1] = adj[2] = adj[3] = 0;
+ times[4][3] = total[3];
+ }
+#else
+ } else
+ adj_secs = adj[0] = adj[1] = adj[2] = 0;
+#endif
+ for (i = 0; i < 3; i++) {
+ times[4][i] = ((total[i] - adj[i]) * 10 / (secs - adj_secs) + 5) / 10;
+ }
+
+ if ((cur_load_entry != NULL) && (cur_load_entry->prev != NULL) &&
+ (secs > 86400)) { /* have nodes to free -- more than 3 days old */
+ struct load_entry *cur_free_entry = load_free_head;
+
+ load_free_head = load_list_head;
+ load_list_head = cur_load_entry;
+ if (cur_free_entry != NULL)
+ cur_free_entry->prev = cur_load_entry->prev;
+ else
+ load_free_tail = cur_load_entry->prev;
+
+ /* printf("freeing: %x (head: %x, tail: %x)\n", cur_load_entry->prev,
+ load_free_head, load_free_tail); */
+
+ cur_load_entry->prev = NULL;
+ }
+
+ strcpy(what[0], DOMAINNAME);
+ strcat(what[0], " clients");
+ strcpy(what[1], "total clients");
+ strcpy(what[2], "total connections");
+#ifdef DEBUGMODE
+ strcpy(what[3], "CPU usage");
+#endif
+ sendto_one(sptr,
+ ":%s NOTICE %s :Minute Hour Day Yest. YYest. Userload for:",
+ me.name, parv);
+ for (i = 0; i < 3; i++)
+ sendto_one(sptr,
+ ":%s NOTICE %s :%3d.%02d %3d.%01d %3d %3d %3d %s",
+ me.name, parv, times[0][i] / 100, times[0][i] % 100, times[1][i] / 10,
+ times[1][i] % 10, times[2][i], times[3][i], times[4][i], what[i]);
+
+#ifdef DEBUGMODE
+ sendto_one(sptr,
+ ":%s NOTICE %s :%6.2f%% %5.1f%% %3d%% %3d%% %3d%% %s",
+ me.name, parv,
+ (double)((double)times[0][3]/(0.6*CLOCKS_PER_SEC)),
+ (double)((double)times[1][3]/(36*CLOCKS_PER_SEC)),
+ (int)((double)times[2][3]/(864*CLOCKS_PER_SEC)),
+ (int)((double)times[3][3]/(864*CLOCKS_PER_SEC)),
+ (int)((double)times[4][3]/(864*CLOCKS_PER_SEC)),
+ what[3]);
+#endif
+}
+
+
+void initload()
+{
+ bzero(¤t_load_data, sizeof(struct current_load_struct));
+ update_load(); /* Initialize the load list */
+}
--- /dev/null
+# $Id$
+case $CONFIG in
+'') if test -r ../config.sh
+ then
+ . ../config.sh ;
+ else
+ spitshell=cat
+ package=IRC
+ fi
+ ;;
+esac
+
+echo "Extracting $package/ircd/version.c..."
+
+if test -r version.c
+then
+ generation=`sed -n 's/^char \*generation = \"\(.*\)\";/\1/p' < version.c`
+ if test ! "$generation" ; then generation=0; fi
+else
+ generation=0
+fi
+
+generation=`expr $generation + 1`
+
+creation=`date | \
+awk '{if (NF == 6) \
+ { print $1 " " $2 " " $3 " " $6 " at " $4 " " $5 } \
+else \
+ { print $1 " " $2 " " $3 " " $7 " at " $4 " " $5 " " $6 }}'`
+
+$spitshell >version.c <<!SUB!THIS!
+/*
+ * IRC - Internet Relay Chat, ircd/version.c
+ * Copyright (C) 1990 Chelsea Ashley Dyerman
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ */
+
+/*
+ * This file is generated by version.c.SH. Any changes made will go away.
+ */
+
+#include "struct.h"
+#include "version.h"
+#include "license.h"
+
+char *generation = "$generation";
+char *creation = "$creation";
+#define IRCDTOTALVERSION BASE_VERSION PATCH1 PATCH2 PATCH3 PATCH4 PATCH5 PATCH6 PATCH7 PATCH8 PATCH9
+char *version = IRCDTOTALVERSION;
+
+/* moved to s_serv.c */
+char *infotext[] =
+{ 0 };
+
+char *unrealcredits[] =
+{
+ "-=-=-=-=-=-=-=-=-=-= [ " IRCDTOTALVERSION " Credits ] -=-=-=-=-",
+ "The people on this list is people who have helped up through",
+ "the development of UnrealIRCd. The Unreal Team would like to thank",
+ "those people by listing them here:",
+ "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=",
+ " \2\37The UnrealIRCd Team would like to thank:\2\37",
+ "Nutcais (Phil Hawkins)",
+ "- the original shell for Unreal development, useful comments,",
+ " being a real IRCbrother for me (Stskeeps) :), learning me a lot",
+ " about IRC stuff, getting me more and more into IRCd business",
+ " thanks for the *.tspre.org domain as well :)",
+ "",
+ "\37Local Irelands (http://www.local.ie)\37",
+ "- Thanks for sponsoring UnrealIRCd, test facilities,",
+ " supporting UnrealIRCd, many new ideas, thanks for making",
+ " Unreal what it is today:)",
+ "Mick and Sp^",
+ "- Amiga port of Unreal (UnrealIRCd/Amiga), continually strange",
+ " comments on #UnrealIRCd, being great supporters of Unreal",
+ " and following Unreal development all the way",
+ "DrBin (Dave) drbin@tspre.org",
+ "- Recoded & made the new UnrealIRCd/32 code, support,"
+ " finding bugs, and tonnes of other stuff:)",
+ "{X} (Laurie) x@tspre.org",
+ "- Making the main code/design of UnrealIRCd/32 gui",
+ " bugfounds, etc",
+ "SourceForge.net",
+ "- Good hosting, CVS hosting, FTP etc etc:) - thanks for",
+ " supporting opensource projects",
+ "",
+ " \37Donations to Unreal:\37",
+ "BlueFlame^",
+ " - the first UnrealIRCd donation :)",
+ " (yes your name can be here too;)",
+ "",
+ " \37These people have helped alpha/betatesting\37",
+ "zshack, Headbang, Mick, Sp^, WonderWal, bomb, BullFrog, JacobD,",
+ "SirDeath, l33, EiniD, uo, RevPsych and the subgenius.net network,",
+ "^RavenX^, Mich[a]el, {X}, Fish, Shmad, Killer, BrainSCAN, RevNull,",
+ "GoNiS (irc.coreplex.org), Mikey, DrBin, and others",
+ "",
+ "",
+ " \2\37Stskeeps would like to thank:\2\37",
+ "Morrigan Julie Frederiksen",
+ " - Being a friend, thinking I was cute, uhm laying on a recycle",
+ " thing.. 'Its the wrong recycle box Julie!', 'you got too cold",
+ " hands *freezing*', etc ;)",
+ "DJBoxy *unknown* *unknown*",
+ " - For getting me up from #wIRCd bringing me to Mp3fansNet and",
+ " after we linked to Global-IRC.net - and made people choose me",
+ " as netadmin/ircd coder - Thanx!",
+ "TC Tabita Clausen (reallife)",
+ " - Making me smile of my life, talking with me, being a friend",
+ " always got a pen sharpener when needed=/, accepting some",
+ " wierdnesses from my side, going to the cinema with me",
+ " and many other stuff. You'll always be in my heart,",
+ " sorry for all the things I did or maybe didn't",
+ " love you :(",
+ "KUFO John MacKenzie",
+ " - Support, helping me always with getting through my life",
+ " shells, etc etc ;)",
+ "Sporty_McFly Cedric",
+ " - Comments, helping me when I got problems with my life and so on",
+ " *toh* to him - Thanks!",
+ "Del_Monte K. Hawkes k.hawkes@zombies.force9.net",
+ " - Is just trying to put the lamer side of things across :cP",
+ " No. I saw 2 moos. - Well having to input in seconds",
+ " is fine if you're real quick at maths - but if not - it's a PAIN",
+ " - Comments, bugfixes, moral support etc.;)",
+ "Skywalker Chris Morley skywalker@irc.ru.ac.za",
+ " - Helping me start up ROXnet at first (which brought me",
+ " into IRCd business.. + Numerous kicks /Kills akills and alike;)",
+ "zero9000 Kevin Alford",
+ " - UnrealIRCd logo, graphics, null desu ;), ideas etc.",
+ " \2\37codemastr would like to thank:\2\37",
+ "CaliMonk Ivo Teel calimonk@nhn.net",
+ " - Getting me started at NeoHorizon which basically got me",
+ " started coding IRCd",
+ "Kenpo Ian Ricci ianr@nhn.net",
+ " - Starting me out learning *nix and giving me a place",
+ " to develop Unreal",
+ "[FBI] Corey Lang *unknown*",
+ " - Being a good IRC friend and getting me started with",
+ " IRC through our old little wIRCd net :)",
+ "",
+ " \2\37Also thanks to:\2\37",
+ "Enforcer, Andy Church, Mick, Sp^, ShadowMastr, Almaris",
+ "}{, Erik/Dr|zzt, Hedge, Kyle, MissKel, jfc, Fish, kore, Syndicate, Bagge,",
+ "#Coder-Com@Undernet, ^NeVeR^, flygirl^, DannyM, JuliuZ, wah-wah^, Lisa,",
+ "Melisa, NonMortal, Andryan, TomaHawk, Lushes, Skywalker, Merlin, Sporty_McFly,",
+ "zero9000, #wIRCd@DALnet, comstud, dog3, Dianora, Isomer, and others who arent listed here:)",
+ "",
+ "------------------------------------------------------",
+ "Unreal 3.0 and up is dedicated to Morrigan - Julie Frederiksen",
+ "- a girl who have helped me through anything in my life, hugging",
+ "me at the right times, a definate dedication. Thanks for the kisses",
+ "long phonetalks, waste of my mobilephone ;), crying together",
+ "and making life go on for us both. I will never forget you",
+ "never leave you, love ya forever",
+ "------------------------------------------------------",
+ "This IRCd is dedicated to the love that has always been",
+ "and will always be there - Thanks to the girls & friends that kept me up",
+ "when I was down",
+ 0
+};
+char *unrealcreditsold[] =
+{
+ "------------------------------------------------------",
+ "Unreal 3.0 and up is dedicated to Morrigan - Julie Frederiksen",
+ "- a girl who have helped me through anything in my life, hugging",
+ "me at the right times, a definate dedication. Thanks for the kisses",
+ "long phonetalks, waste of my mobilephone ;), crying together",
+ "and making life go on for us both. I will never forget you",
+ "never leave you, love ya forever",
+ "------------------------------------------------------",
+ "This IRCd is dedicated to the love that has always been",
+ "and will always be there - Thanks to the girls & friends that kept me up",
+ "when I was down",
+ 0
+};
+
+char *dalinfotext[] =
+ {
+ "$package --",
+ "Based on the original code written by Jarkko Oikarinen",
+ "Copyright 1988, 1989, 1990, 1991 University of Oulu, Computing Center",
+ "",
+ "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 1, or",
+ "(at your option) any later version.",
+ "- Any name/comment should never be changed except by the one who made it -",
+ "",
+ "UnrealIRCd contains code developed by:",
+ "Potvin Chris Wolkowski potvin@acestar.org",
+ "RogerY Roger Y. rogery@austnet.org",
+ "GZ gz@starchat.net",
+ "binary",
+ "",
+ "",
+ "The following people have helped in making the DALnet ircd",
+ "that is based on irc2.8.21.mu3.2 :",
+ "",
+ "Russell Russell Miller russell@dal.net",
+ "Donwulff Jukka Santala donwulff@dal.net",
+ "Aetobatus Michael Sawyer aetobatus@dal.net",
+ "Dalvenjah Sven Nielsen dalvenjah@dal.net",
+ "Skandranon Michael Graff explorer@flame.org",
+ "Barubary - barubary@dal.net",
+ "white_dragon Chip Norkus wd@dal.net",
+ "DuffJ Dafydd James duffj@dal.net",
+ "taz David Kopstain taz@dal.net",
+ "NikB Nik Bougalis nikb@dal.net",
+ "Rakarra - rakarra@dal.net",
+ "DarkRot Lucas Madar darkrot@dal.net",
+ "Studded - studded@dal.net",
+ "JoelKatz David Schwartz joelkatz@dal.net",
+ "",
+ "This product includes software developed by Colin Plumb.",
+ "",
+ "The following persons have made many changes and enhancements to the",
+ "code and still know how IRC really works if you have questions about it:",
+ "",
+ "Run Carlo Kid carlo@runaway.xs4all.nl",
+ "Avalon Darren Reed avalon@coombs.anu.edu.au",
+ "msa Markku Savela Markku.Savela@vtt.fi",
+ "Wumpus Greg Lindahl gl8f@virginia.edu",
+ "WiZ Jarkko Oikarinen jto@tolsun.oulu.fi",
+ "Argv Armin Gruner Armin.Gruner@Informatik.TU-Muenchen.de",
+ "",
+ "Thanks to the following people for help with preparing 2.8",
+ "",
+ "phone Matthew Green phone@coombs.anu.edu.au",
+ "Sodapop Chuck Kane ckane@ece.uiuc.edu",
+ "Skygod Matt Lyle matt@oc.com",
+ "Vesa Vesa Ruokonen ruokonen@lut.fi",
+ "Nap Nicolas PIOCH pioch@poly.polytechnique.fr",
+ "",
+ "Those who helped in prior versions and continue to be helpful:",
+ "",
+ "Stellan Klebom Dan Goodwin Mike Bolotski",
+ "Ian Frechette Markku Jarvinen Kimmo Suominen",
+ "Jeff Trim Vijay Subramaniam Karl Kleinpaste",
+ "Bill Wisner Tom Davis Hugo Calendar",
+ "Tom Hopkins Stephen van den Berg",
+ "Bo Adler Michael Sandrof Jon Solomon",
+ "Jan Peterson Helen Rose Paul Graham",
+ "",
+ "Thanks also goes to those persons not mentioned here who have added",
+ "their advice, opinions, and code to IRC.",
+ "Thanks also to those who provide the kind sys admins who let me and",
+ "others continue to develop IRC.",
+ "",
+
+ 0
+ };
+!SUB!THIS!
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, ircd/whowas.c
+ * Copyright (C) 1990 Markku Savela
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * --- avalon --- 6th April 1992
+ * rewritten to scrap linked lists and use a table of structures which
+ * is referenced like a circular loop. Should be faster and more efficient.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)whowas.c 2.16 08 Nov 1993 (C) 1988 Markku Savela";
+#endif
+
+#include "struct.h"
+#include "common.h"
+#include "sys.h"
+#include "numeric.h"
+#include "whowas.h"
+#include "h.h"
+
+ID_CVS("$Id$");
+
+static aName was[NICKNAMEHISTORYLENGTH];
+static int ww_index = 0;
+
+void add_history(cptr)
+Reg1 aClient *cptr;
+{
+ aName ntmp;
+ Reg2 aName *np = &ntmp, *np2;
+ Link *lp;
+
+ strncpyzt(np->ww_nick, cptr->name, NICKLEN+1);
+ strncpyzt(np->ww_info, cptr->info, REALLEN+1);
+ np->ww_user = cptr->user;
+ np->ww_logout = TStime();
+ np->ww_online = (cptr->from != NULL) ? cptr : NULL;
+ np->ww_user->refcnt++;
+
+ np2 = &was[ww_index];
+ if (np2->ww_user)
+ free_user(np2->ww_user, np2->ww_online);
+ /*
+ * New whowas handling, we keep a list of what whowas entries
+ * are "used" by a client, in its cptr structure. This means
+ * that when we overwrite a whowas entry, we have to remove the
+ * relative pointer in the client. -Cabal95
+ */
+ if (np2->ww_online) {
+ Link *last = NULL;
+
+ for (lp = np2->ww_online->history; lp;
+ last = lp, lp = lp->next)
+ if (lp->value.whowas == np2)
+ break;
+
+ if (lp) { /* Sanity check, never trust anything */
+ if (last)
+ last->next = lp->next;
+ else
+ np2->ww_online->history = lp->next;
+
+ free_link(lp);
+ }
+ }
+
+ bcopy((char *)&ntmp, (char *)np2, sizeof(aName));
+
+ /*
+ * Add this whowas entry into the clients history list
+ */
+ lp = make_link();
+ lp->value.whowas = np2;
+ lp->next = cptr->history;
+ cptr->history = lp;
+
+ ww_index++;
+ if (ww_index >= NICKNAMEHISTORYLENGTH)
+ ww_index = 0;
+ return;
+}
+
+/*
+** get_history
+** Return the current client that was using the given
+** nickname within the timelimit. Returns NULL, if no
+** one found...
+*/
+aClient *get_history(nick, timelimit)
+char *nick;
+time_t timelimit;
+{
+ Reg1 aName *wp, *wp2;
+ Reg2 int i = 0;
+
+ if (ww_index == 0)
+ wp = wp2 = &was[NICKNAMEHISTORYLENGTH - 1];
+ else
+ wp = wp2 = &was[ww_index - 1];
+ timelimit = TStime()-timelimit;
+
+ do {
+ if (!mycmp(nick, wp->ww_nick) && wp->ww_logout >= timelimit)
+ break;
+ if (wp == was)
+ {
+ i = 1;
+ wp = &was[NICKNAMEHISTORYLENGTH - 1];
+ }
+ else
+ wp--;
+ } while (wp != wp2);
+
+ if (wp != wp2 || !i)
+ return (wp->ww_online);
+ return (NULL);
+}
+
+void off_history(cptr)
+Reg3 aClient *cptr;
+{
+ Reg1 Link *lp;
+ Reg2 Link *next;
+
+
+ for (lp = cptr->history; lp; lp = next) {
+ next = lp->next;
+ lp->value.whowas->ww_online = NULL;
+ free_link(lp);
+ }
+
+ cptr->history = NULL;
+
+ return;
+}
+
+void initwhowas()
+{
+ Reg1 int i;
+
+ for (i = 0; i < NICKNAMEHISTORYLENGTH; i++)
+ bzero((char *)&was[i], sizeof(aName));
+ return;
+}
+
+
+/*
+** m_whowas
+** parv[0] = sender prefix
+** parv[1] = nickname queried
+*/
+int m_whowas(cptr, sptr, parc, parv)
+aClient *cptr, *sptr;
+int parc;
+char *parv[];
+{
+ Reg1 aName *wp, *wp2 = NULL;
+ Reg2 int j = 0;
+ Reg3 anUser *up = NULL;
+ int max = -1;
+ char *p, *nick, *s;
+
+ if (parc < 2)
+ {
+ sendto_one(sptr, err_str(ERR_NONICKNAMEGIVEN),
+ me.name, parv[0]);
+ return 0;
+ }
+ if (parc > 2)
+ max = atoi(parv[2]);
+ if (parc > 3)
+ if (hunt_server(cptr,sptr,":%s WHOWAS %s %s :%s", 3,parc,parv))
+ return 0;
+
+ for (s = parv[1]; (nick = strtoken(&p, s, ",")); s = NULL)
+ {
+ wp = wp2 = &was[ww_index - 1];
+
+ do {
+ if (wp < was)
+ wp = &was[NICKNAMEHISTORYLENGTH - 1];
+ if (mycmp(nick, wp->ww_nick) == 0)
+ {
+ up = wp->ww_user;
+ sendto_one(sptr, rpl_str(RPL_WHOWASUSER),
+ me.name, parv[0], wp->ww_nick,
+ up->username,
+ (IsOper(sptr) ?
+ up->realhost :
+ (up->virthost[0] != '\0') ?
+ up->virthost : up->realhost),
+ wp->ww_info);
+ sendto_one(sptr, rpl_str(RPL_WHOISSERVER),
+ me.name, parv[0], wp->ww_nick,
+ up->server, myctime(wp->ww_logout));
+ if (up->away)
+ sendto_one(sptr, rpl_str(RPL_AWAY),
+ me.name, parv[0],
+ wp->ww_nick, up->away);
+ j++;
+ }
+ if (max > 0 && j >= max)
+ break;
+ wp--;
+ } while (wp != wp2);
+
+ if (up == NULL)
+ sendto_one(sptr, err_str(ERR_WASNOSUCHNICK),
+ me.name, parv[0], nick);
+ up=NULL;
+
+ if (p)
+ p[-1] = ',';
+ }
+ sendto_one(sptr, rpl_str(RPL_ENDOFWHOWAS), me.name, parv[0], parv[1]);
+ return 0;
+ }
+
+
+void count_whowas_memory(wwu, wwa, wwam)
+int *wwu, *wwa;
+u_long *wwam;
+{
+ Reg1 anUser *tmp;
+ Reg2 int i, j;
+ int u = 0, a = 0;
+ u_long am = 0;
+
+ for (i = 0; i < NICKNAMEHISTORYLENGTH; i++)
+ if ((tmp = was[i].ww_user))
+ if (!was[i].ww_online)
+ {
+ for (j = 0; j < i; j++)
+ if (was[j].ww_user == tmp)
+ break;
+ if (j < i)
+ continue;
+ u++;
+ if (tmp->away)
+ {
+ a++;
+ am += (strlen(tmp->away)+1);
+ }
+ }
+ *wwu = u;
+ *wwa = a;
+ *wwam = am;
+
+ return;
+}
--- /dev/null
+/************************************************************************
+ * IRC - Internet Relay Chat, win32.c
+ * Copyright (C) 1996 Daniel Hazelbaker
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)win32.c 2.01 10/21/96 (C) 1996 Daniel Hazelbaker";
+#endif
+
+
+#define APPNAME "wIRCD"
+#define wTITLEBAR "UnrealIRCd"
+
+// Windows Header Files:
+#include "common.h"
+#include <windows.h>
+#include <commctrl.h>
+#include <process.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <memory.h>
+#include <io.h>
+#include <fcntl.h>
+#include "struct.h"
+#include "sys.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "h.h"
+#include "version.h"
+#include "resource.h"
+#include "CioFunc.h"
+
+ID_CVS("$Id$");
+
+
+BOOL InitApplication(HINSTANCE);
+BOOL InitInstance(HINSTANCE, int);
+LRESULT CALLBACK FrameWndProc(HWND, UINT, WPARAM, LPARAM);
+LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
+LRESULT CALLBACK Dlg_IRCDCONF(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
+LRESULT CALLBACK Dlg_IRCDMOTD(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
+LRESULT CALLBACK Dlg_IRCDRULES(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
+
+BOOL DisplayString(HWND hWnd, char *InBuf, ...);
+void LoadSetup(void);
+void SaveSetup(void);
+int SetDebugLevel(HWND hWnd, int NewLevel);
+
+LRESULT CALLBACK Credits(HWND, UINT, WPARAM, LPARAM);
+LRESULT CALLBACK Dreamforge(HWND, UINT, WPARAM, LPARAM);
+LRESULT CALLBACK IRCDLicense(HWND, UINT, WPARAM, LPARAM);
+
+
+extern void SocketLoop(void *dummy), s_rehash(), do_dns_async(HANDLE id);
+extern int localdie(void), InitwIRCD(int argc, char *argv[]);
+
+
+HINSTANCE hInst; // current instance
+char szAppName[] = APPNAME; // The name of this application
+char szTitle[] = wTITLEBAR; // The title bar text
+HWND hwIRCDWnd=NULL, hCio=NULL;
+HANDLE hMainThread = 0;
+
+#ifndef IRCDTOTALVERSION
+#define IRCDTOTALVERSION BASE_VERSION PATCH1 PATCH2 PATCH3 PATCH4 PATCH5 PATCH6 PATCH7 PATCH8 PATCH9
+#endif
+
+/*
+ * FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
+ *
+ * PURPOSE: Entry point for the application.
+ *
+ * COMMENTS:
+ *
+ * This function initializes the application and processes the
+ * message loop.
+ */
+int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
+{
+ MSG msg;
+ HANDLE hAccelTable;
+ int argc=1;
+ char *s, *argv[20], String[128];
+
+ if (!hPrevInstance)
+ if (!InitApplication(hInstance))
+ return (FALSE);
+
+ if (!InitInstance(hInstance, nCmdShow))
+ return (FALSE);
+
+ argv[0] = "WIRCD.EXE";
+ if ( *(s = lpCmdLine) )
+ {
+ argv[argc++] = s;
+ while ( (s = strchr(s, ' ')) != NULL )
+ {
+ while ( *s == ' ' ) *s++ = 0;
+ argv[argc++] = s;
+ }
+ }
+ argv[argc] = NULL;
+ if ( InitwIRCD(argc, argv) != 1 )
+ return FALSE;
+
+ wsprintf(String, "UnrealIRCd/32 - %s", me.name);
+ SetWindowText(hwIRCDWnd, String);
+
+ SetDebugLevel(hwIRCDWnd, debuglevel);
+
+ hMainThread = (HANDLE)_beginthread(SocketLoop, 0, NULL);
+ hAccelTable = LoadAccelerators (hInstance, szAppName);
+
+ LoadSetup();
+ atexit(SaveSetup);
+
+ /* Say we are ready to recieve connections */
+ wsprintf(String, "%c%c%c%c[info] -=-=[ UnrealIRCd/32 v%s Ready ] - %s\r", 0,0,0,0, VERSIONONLY);
+ DisplayString(hCio, String);
+ /* Main message loop */
+ while (GetMessage(&msg, NULL, 0, 0))
+ {
+ if ( !TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+
+ return (msg.wParam);
+ lpCmdLine; /* This will prevent 'unused formal parameter' warnings */
+}
+
+
+/*
+ * FUNCTION: InitApplication(HANDLE)
+ *
+ * PURPOSE: Initializes window data and registers window class
+ *
+ * COMMENTS:
+ *
+ * In this function, we initialize a window class by filling out a data
+ * structure of type WNDCLASS and calling either RegisterClass or
+ * the internal MyRegisterClass.
+ */
+BOOL InitApplication(HINSTANCE hInstance)
+{
+ WNDCLASS wc;
+
+ // Fill in window class structure.
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+ wc.lpfnWndProc = (WNDPROC)FrameWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = hInstance;
+ wc.hIcon = LoadIcon (hInstance, APPNAME);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
+ wc.lpszMenuName = szAppName;
+ wc.lpszClassName = szAppName;
+
+ if ( !RegisterClass(&wc) ) return 0;
+
+ return 1;
+}
+
+
+/*
+ * FUNCTION: InitInstance(HANDLE, int)
+ *
+ * PURPOSE: Saves instance handle and creates main window
+ *
+ * COMMENTS:
+ *
+ * In this function, we save the instance handle in a global variable and
+ * create and display the main program window.
+ */
+BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
+{
+ HWND hWnd;
+ WSADATA WSAData;
+
+
+ if ( WSAStartup(MAKEWORD(1, 1), &WSAData) != 0 )
+ {
+ MessageBox(NULL, "UnrealIRCD/32 Init Error", "Unable to initialize WinSock DLL", MB_OK);
+ return FALSE;
+ }
+
+ hInst = hInstance; /* Store instance handle in our global variable */
+
+ if ( !Cio_Init(hInst) )
+ {
+ MessageBox(NULL, "UnrealIRCD/32 Init Error", "Couldn't Init CIO Library", MB_OK);
+ return FALSE;
+ }
+
+ hWnd = CreateWindow(szAppName, szTitle, WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
+ NULL, NULL, hInstance, NULL);
+
+ if ( !hWnd )
+ return (FALSE);
+
+ ShowWindow(hWnd, nCmdShow);
+ UpdateWindow(hwIRCDWnd = hWnd);
+
+ return (TRUE);
+}
+
+
+/*
+ * FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
+ *
+ * PURPOSE: Processes messages for the main window.
+ *
+ */
+LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ int wmId, wmEvent;
+ char *xx = NULL;
+
+ switch (message)
+ {
+ case WM_CREATE:
+ hCio = Cio_Create(hInst, hWnd, WS_VISIBLE, 0, 0, 300, 200);
+ xx = MyMalloc(1024);
+ sprintf(xx, "%c%c%c%c[info] -=-=[ UnrealIRCd/32 v%s Loading ]-=-=\r", 0, 0, 0, 0,
+ VERSIONONLY);
+ DisplayString(hCio, xx);
+#ifdef WIN32_SPECIFY
+ sprintf(xx, "%c%c%c%c[info] - Ported by %s", 0,0,0,0, WIN32_PORTER);
+ DisplayString(hCio, xx);
+ sprintf(xx, "%c%c%c%c[info] - %s", 0,0,0,0, WIN32_URL);
+ DisplayString(hCio, xx);
+#endif
+ MyFree(xx);
+ return 0;
+ case WM_COMMAND:
+ wmId = LOWORD(wParam);
+ wmEvent = HIWORD(wParam);
+
+ switch (wmId)
+ {
+ case IDM_ABOUT:
+ DialogBox(hInst, "AboutBox", hWnd, (DLGPROC)About);
+ break;
+ case IDM_CREDITS:
+ DialogBox(hInst, "AboutBox", hWnd, (DLGPROC)Credits);
+ break;
+ case IDM_DF:
+ DialogBox(hInst, "AboutBox", hWnd, (DLGPROC)Dreamforge);
+ break;
+ case IDM_LICENSE:
+ DialogBox(hInst, "AboutBox", hWnd, (DLGPROC)IRCDLicense);
+ break;
+
+ case IDM_IRCDCONF:
+ DialogBox(hInst, "DLG_IRCDCONF", hWnd, (DLGPROC)Dlg_IRCDCONF);
+ break;
+ case IDM_IRCDMOTD:
+ DialogBox(hInst, "DLG_IRCDMOTD", hWnd, (DLGPROC)Dlg_IRCDMOTD);
+ break;
+ case IDM_IRCDRULES:
+ DialogBox(hInst, "DLG_IRCDRULES", hWnd, (DLGPROC)Dlg_IRCDRULES);
+ break;
+ case IDM_REHASH:
+ s_rehash();
+ break;
+
+ case IDM_EXIT:
+ if ( MessageBox(hWnd, "Are you sure?",
+ "Terminate UnrealIRCD/32",
+ MB_ICONQUESTION | MB_YESNO) == IDNO )
+ break;
+ DestroyWindow(hWnd);
+ break;
+
+ case IDM_DBGOFF:
+ case IDM_DBGFATAL:
+ case IDM_DBGERROR:
+ case IDM_DBGNOTICE:
+ case IDM_DBGDNS:
+ case IDM_DBGINFO:
+ case IDM_DBGNUM:
+ case IDM_DBGSEND:
+ case IDM_DBGDEBUG:
+ case IDM_DBGMALLOC:
+ case IDM_DBGLIST:
+ SetDebugLevel(hWnd, wmId-IDM_DBGFATAL);
+ break;
+
+ default:
+ return (DefWindowProc(hWnd, message, wParam, lParam));
+ }
+ break;
+
+ case WM_CLOSE:
+ if ( MessageBox(hWnd, "Are you sure?", "Terminate UnrealIRCd/32",
+ MB_ICONQUESTION | MB_YESNO) == IDNO )
+ break;
+ return (DefWindowProc(hWnd, message, wParam, lParam));
+
+ case WM_DESTROY:
+ localdie(); /* Never returns */
+ PostQuitMessage(0);
+ break;
+
+ case WM_SIZE:
+ SetWindowPos(hCio, NULL, 0, 0, LOWORD(lParam), HIWORD(lParam),
+ SWP_NOZORDER);
+ /* Fallthrough to get the default handling too. */
+
+ default:
+ return (DefWindowProc(hWnd, message, wParam, lParam));
+ }
+ return (0);
+}
+
+
+/*
+ * FUNCTION: About(HWND, unsigned, WORD, LONG)
+ *
+ * PURPOSE: Processes messages for "About" dialog box
+ * This version allows greater flexibility over the contents of the 'About' box,
+ * by pulling out values from the 'Version' resource.
+ *
+ * MESSAGES:
+ *
+ * WM_INITDIALOG - initialize dialog box
+ * WM_COMMAND - Input received
+ *
+ */
+LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message)
+ {
+ case WM_INITDIALOG:
+#define Ccat strcat(String, String2)
+ {
+ char String[16384], String2[16384], **s = infotext;
+ sprintf(String, "%s\n%s", version, creation);
+ SetDlgItemText(hDlg, IDC_VERSION, String);
+ String[0] = 0; String2[0] = 0;
+ sprintf(String2, "-=-=-=-=-=-==-==- %s -=-=-==-==-=-=-=-=-=-\r\n", ircnetwork); Ccat;
+ sprintf(String2, "|Web Page: | http://www.%s\r\n", netdomain); Ccat;
+ sprintf(String2, "|FTP Archive: | ftp://ftp.%s\r\n", netdomain); Ccat;
+ sprintf(String2, "|Help channel: | %s\r\n", helpchan); Ccat;
+ sprintf(String2, "|=-=-=-=-=-==-==|-=-=-=-=-=-=-==-==-=-=-=-=-=-=-=\r\n"); Ccat;
+ sprintf(String2, "|IRCd version: | %s\r\n", IRCDTOTALVERSION); Ccat;
+ sprintf(String2, "| Developers: | Stskeeps <stskeeps@tspre.org>\r\n"); Ccat;
+ sprintf(String2, "| | codemastr <codemastr@tspre.org>\r\n"); Ccat;
+#if defined(_WIN32) && defined(WIN32_SPECIFY)
+ sprintf(String2, "| Win32 Porter: | %s\r\n", WIN32_PORTER); Ccat;
+ sprintf(String2, "| >>URL: | %s\r\n", WIN32_URL); Ccat;
+#endif
+ sprintf(String2, "|Credits: | Type /Credits\r\n"); Ccat;
+ sprintf(String2, "|DALnet Credits:| Type /DALinfo\r\n"); Ccat;
+ sprintf(String2, "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\r\n"); Ccat;
+ sprintf(String2, "| Unreal IRCd can be downloaded at http://unreal.tspre.org\r\n"); Ccat;
+ sprintf(String2, "| This notice may not be removed from the IRCd package\r\n"); Ccat;
+ sprintf(String2, "| It will be a violation of copyright. This program must always stay free of charge\r\n"); Ccat;
+ sprintf(String2, "| being sold commercially or privately\r\n"); Ccat;
+ sprintf(String2, "| Only charge may be for the transport medium like on CD-ROM, floppy\r\n"); Ccat;
+ sprintf(String2, "| or other kinds (-Stskeeps'1999)\r\n"); Ccat;
+ sprintf(String2, "--------------------------------------------\r\n"); Ccat;
+ SetDlgItemText(hDlg, IDC_INFOTEXT, String);
+#undef Ccat
+ ShowWindow (hDlg, SW_SHOW);
+ return (TRUE);
+ }
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
+ {
+ EndDialog(hDlg, TRUE);
+ return (TRUE);
+ }
+ break;
+ }
+ return FALSE;
+}
+
+/*
+ * FUNCTION: Credits(HWND, unsigned, WORD, LONG)
+ *
+ * PURPOSE: Processes messages for "Credits" dialog box
+ * This version allows greater flexibility over the contents of the 'Credits' box,
+ * by pulling out values from the 'Version' resource.
+ *
+ * MESSAGES:
+ *
+ * WM_INITDIALOG - initialize dialog box
+ * WM_COMMAND - Input received
+ *
+ */
+LRESULT CALLBACK Credits(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message)
+ {
+ case WM_INITDIALOG:
+ {
+ char String[16384], **s = unrealcredits;
+
+ sprintf(String, "%s\n%s", version, creation);
+ SetDlgItemText(hDlg, IDC_VERSION, String);
+ String[0] = 0;
+ while ( *s )
+ {
+ strcat(String, *s++);
+ if ( *s )
+ strcat(String, "\r\n");
+ }
+ SetDlgItemText(hDlg, IDC_INFOTEXT, String);
+
+
+ ShowWindow (hDlg, SW_SHOW);
+ return (TRUE);
+ }
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
+ {
+ EndDialog(hDlg, TRUE);
+ return (TRUE);
+ }
+ break;
+ }
+ return FALSE;
+}
+
+/*
+ * FUNCTION: Dreamforge(HWND, unsigned, WORD, LONG)
+ *
+ * PURPOSE: Processes messages for "Dreamforge" dialog box
+ * This version allows greater flexibility over the contents of the 'Dreamforge' box,
+ * by pulling out values from the 'Version' resource.
+ *
+ * MESSAGES:
+ *
+ * WM_INITDIALOG - initialize dialog box
+ * WM_COMMAND - Input received
+ *
+ */
+LRESULT CALLBACK Dreamforge(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message)
+ {
+ case WM_INITDIALOG:
+ {
+ char String[16384], **s = dalinfotext;
+
+ sprintf(String, "%s\n%s", version, creation);
+ SetDlgItemText(hDlg, IDC_VERSION, String);
+ String[0] = 0;
+ while ( *s )
+ {
+ strcat(String, *s++);
+ if ( *s )
+ strcat(String, "\r\n");
+ }
+ SetDlgItemText(hDlg, IDC_INFOTEXT, String);
+
+
+ ShowWindow (hDlg, SW_SHOW);
+ return (TRUE);
+ }
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
+ {
+ EndDialog(hDlg, TRUE);
+ return (TRUE);
+ }
+ break;
+ }
+ return FALSE;
+}
+
+/*
+ * FUNCTION: IRCDLicense(HWND, unsigned, WORD, LONG)
+ *
+ * PURPOSE: Processes messages for "IRCDLicense" dialog box
+ * This version allows greater flexibility over the contents of the 'IRCDLicense' box,
+ * by pulling out values from the 'Version' resource.
+ *
+ * MESSAGES:
+ *
+ * WM_INITDIALOG - initialize dialog box
+ * WM_COMMAND - Input received
+ *
+ */
+LRESULT CALLBACK IRCDLicense(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message)
+ {
+ case WM_INITDIALOG:
+ {
+ char String[16384], **s = gnulicense;
+
+ sprintf(String, "%s\n%s", version, creation);
+ SetDlgItemText(hDlg, IDC_VERSION, String);
+ String[0] = 0;
+ while ( *s )
+ {
+ strcat(String, *s++);
+ if ( *s )
+ strcat(String, "\r\n");
+ }
+ SetDlgItemText(hDlg, IDC_INFOTEXT, String);
+
+
+ ShowWindow (hDlg, SW_SHOW);
+ return (TRUE);
+ }
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
+ {
+ EndDialog(hDlg, TRUE);
+ return (TRUE);
+ }
+ break;
+ }
+ return FALSE;
+}
+
+
+/*
+ * FUNCTION: Dlg_IrcdConf(HWND, unsigned, WORD, LONG)
+ *
+ * PURPOSE: Processes messages for "DLG_IRCDCONF" dialog box
+ *
+ */
+LRESULT CALLBACK Dlg_IRCDCONF(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message)
+ {
+ case WM_INITDIALOG:
+ {
+ char *Buffer = MyMalloc(65535); /* Should be big enough */
+ int fd, Len;
+
+ if ( !Buffer )
+ {
+ MessageBox(hDlg, "Error: Could not allocate temporary buffer",
+ "UnrealIRCd/32 Setup", MB_OK);
+ EndDialog(hDlg, FALSE);
+ return FALSE;
+ }
+ /* Open the ircd.conf file */
+ fd = open(CONFIGFILE, _O_RDONLY | _O_BINARY);
+ if ( fd == -1 )
+ {
+ MessageBox(hDlg, "Error: Could not open configuration file",
+ "UnrealIRCd/32 Setup", MB_OK);
+ MyFree(Buffer);
+ EndDialog(hDlg, FALSE);
+ return FALSE;
+ }
+
+ Buffer[0] = 0; /* Incase read() fails */
+ Len = read(fd, Buffer, 65535);
+ Buffer[Len] = 0;
+ /* Set the text for the edit control to what was in the file */
+ SendDlgItemMessage(hDlg, IDC_IRCDCONF, WM_SETTEXT, 0,
+ (LPARAM)(LPCTSTR)Buffer);
+
+ close(fd);
+ MyFree(Buffer);
+ }
+ return (TRUE);
+
+ case WM_COMMAND:
+ if ( LOWORD(wParam) == IDOK )
+ {
+ char *Buffer = MyMalloc(65535); /* Should be big enough */
+ DWORD Len;
+ int fd;
+
+ if ( !Buffer )
+ {
+ MessageBox(hDlg, "Error: Could not allocate temporary buffer",
+ "UnrealIRCD/32 Setup", MB_OK);
+ return TRUE;
+ }
+ /* Open the ircd.conf file */
+ fd = open(CONFIGFILE, _O_TRUNC|_O_CREAT|_O_RDWR|_O_BINARY,
+ S_IREAD|S_IWRITE);
+ if ( fd == -1 )
+ {
+ MessageBox(hDlg, "Error: Could not open configuration file",
+ "UnrealIRCD/32 Setup", MB_OK);
+ MyFree(Buffer);
+ return TRUE;
+ }
+
+ /* Get the text from the edit control and save it to disk. */
+ Len = SendDlgItemMessage(hDlg, IDC_IRCDCONF, WM_GETTEXT, 65535,
+ (LPARAM)(LPCTSTR)Buffer);
+ write(fd, Buffer, Len);
+
+ close(fd);
+ MyFree(Buffer);
+
+ EndDialog(hDlg, TRUE);
+ return TRUE;
+ }
+ if ( LOWORD(wParam) == IDCANCEL )
+ {
+ EndDialog(hDlg, FALSE);
+ return TRUE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+/*
+ * FUNCTION: Dlg_Dlg_IRCdMotd(HWND, unsigned, WORD, LONG)
+ *
+ * PURPOSE: Processes messages for "DLG_IRCDCONF" dialog box
+ *
+ */
+LRESULT CALLBACK Dlg_IRCDMOTD(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message)
+ {
+ case WM_INITDIALOG:
+ {
+ char *Buffer = MyMalloc(65535*2); /* Should be big enough */
+ int fd, Len;
+
+ if ( !Buffer )
+ {
+ MessageBox(hDlg, "Error: Could not allocate temporary buffer",
+ "UnrealIRCd/32 Setup", MB_OK);
+ EndDialog(hDlg, FALSE);
+ return FALSE;
+ }
+ /* Open the ircd.motd file */
+ fd = open(MPATH, _O_RDONLY | _O_BINARY);
+ if ( fd == -1 )
+ {
+ MessageBox(hDlg, "Error: Could not open MOTD file",
+ "UnrealIRCd/32 Setup", MB_OK);
+ MyFree(Buffer);
+ EndDialog(hDlg, FALSE);
+ return FALSE;
+ }
+
+ Buffer[0] = 0; /* Incase read() fails */
+ Len = read(fd, Buffer, 65535);
+ Buffer[Len] = 0;
+ /* Set the text for the edit control to what was in the file */
+ SendDlgItemMessage(hDlg, IDC_IRCDCONF, WM_SETTEXT, 0,
+ (LPARAM)(LPCTSTR)Buffer);
+
+ close(fd);
+ MyFree(Buffer);
+ }
+ return (TRUE);
+
+ case WM_COMMAND:
+ if ( LOWORD(wParam) == IDOK )
+ {
+ char *Buffer = MyMalloc(65535); /* Should be big enough */
+ DWORD Len;
+ int fd;
+
+ if ( !Buffer )
+ {
+ MessageBox(hDlg, "Error: Could not allocate temporary buffer",
+ "UnrealIRCD/32 Setup", MB_OK);
+ return TRUE;
+ }
+ /* Open the ircd.motd file */
+ fd = open(MPATH, _O_TRUNC|_O_CREAT|_O_RDWR|_O_BINARY,
+ S_IREAD|S_IWRITE);
+ if ( fd == -1 )
+ {
+ MessageBox(hDlg, "Error: Could not open motd file",
+ "UnrealIRCD/32 Setup", MB_OK);
+ MyFree(Buffer);
+ return TRUE;
+ }
+
+ /* Get the text from the edit control and save it to disk. */
+ Len = SendDlgItemMessage(hDlg, IDC_IRCDCONF, WM_GETTEXT, 65535,
+ (LPARAM)(LPCTSTR)Buffer);
+ write(fd, Buffer, Len);
+
+ close(fd);
+ MyFree(Buffer);
+
+ EndDialog(hDlg, TRUE);
+ return TRUE;
+ }
+ if ( LOWORD(wParam) == IDCANCEL )
+ {
+ EndDialog(hDlg, FALSE);
+ return TRUE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+/*
+ * FUNCTION: Dlg_IRCdRules(HWND, unsigned, WORD, LONG)
+ *
+ * PURPOSE: Processes messages for "DLG_IRCDCONF" dialog box
+ *
+ */
+LRESULT CALLBACK Dlg_IRCDRULES(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message)
+ {
+ case WM_INITDIALOG:
+ {
+ char *Buffer = MyMalloc(65535*2); /* Should be big enough */
+ int fd, Len;
+
+ if ( !Buffer )
+ {
+ MessageBox(hDlg, "Error: Could not allocate temporary buffer",
+ "UnrealIRCd/32 Setup", MB_OK);
+ EndDialog(hDlg, FALSE);
+ return FALSE;
+ }
+ /* Open the ircd.rules file */
+ fd = open(RPATH, _O_RDONLY | _O_BINARY);
+ if ( fd == -1 )
+ {
+ MessageBox(hDlg, "Error: Could not open rules file",
+ "UnrealIRCd/32 Setup", MB_OK);
+ MyFree(Buffer);
+ EndDialog(hDlg, FALSE);
+ return FALSE;
+ }
+
+ Buffer[0] = 0; /* Incase read() fails */
+ Len = read(fd, Buffer, 65535);
+ Buffer[Len] = 0;
+ /* Set the text for the edit control to what was in the file */
+ SendDlgItemMessage(hDlg, IDC_IRCDCONF, WM_SETTEXT, 0,
+ (LPARAM)(LPCTSTR)Buffer);
+
+ close(fd);
+ MyFree(Buffer);
+ }
+ return (TRUE);
+
+ case WM_COMMAND:
+ if ( LOWORD(wParam) == IDOK )
+ {
+ char *Buffer = MyMalloc(65535); /* Should be big enough */
+ DWORD Len;
+ int fd;
+
+ if ( !Buffer )
+ {
+ MessageBox(hDlg, "Error: Could not allocate temporary buffer",
+ "UnrealIRCD/32 Setup", MB_OK);
+ return TRUE;
+ }
+ /* Open the ircd.rules file */
+ fd = open(RPATH, _O_TRUNC|_O_CREAT|_O_RDWR|_O_BINARY,
+ S_IREAD|S_IWRITE);
+ if ( fd == -1 )
+ {
+ MessageBox(hDlg, "Error: Could not open rules file",
+ "UnrealIRCD/32 Setup", MB_OK);
+ MyFree(Buffer);
+ return TRUE;
+ }
+
+ /* Get the text from the edit control and save it to disk. */
+ Len = SendDlgItemMessage(hDlg, IDC_IRCDCONF, WM_GETTEXT, 65535,
+ (LPARAM)(LPCTSTR)Buffer);
+ write(fd, Buffer, Len);
+
+ close(fd);
+ MyFree(Buffer);
+
+ EndDialog(hDlg, TRUE);
+ return TRUE;
+ }
+ if ( LOWORD(wParam) == IDCANCEL )
+ {
+ EndDialog(hDlg, FALSE);
+ return TRUE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+
+int DisplayString(HWND hWnd, char *InBuf, ...)
+{
+ CioWndInfo *CWI;
+ va_list argptr;
+ char *Buffer=NULL, *Ptr=NULL;
+ DWORD Len=0, TLen=0, Off=0, i=0;
+ BYTE Red=0, Green=0, Blue=0;
+ BOOL Bold = FALSE;
+
+ if ( (Buffer = LocalAlloc(LPTR, 16384)) == NULL ) return FALSE;
+
+ va_start(argptr, InBuf);
+ Len = vsprintf(Buffer, InBuf, argptr);
+ va_end(argptr);
+ if ( Len == 0 )
+ {
+ LocalFree(Buffer);
+ return FALSE;
+ }
+
+ CWI = (CioWndInfo *)GetWindowLong(hWnd, GWL_USER);
+ for ( i = 0; i < Len; i++ )
+ {
+ if ( Buffer[i] == 0 )
+ {
+ i+=3;
+ continue;
+ }
+ if ( Buffer[i] == 0x02 )
+ {
+ if ( !Bold )
+ {
+ Buffer[i] = 0;
+ Cio_Puts(hWnd, Buffer+Off, i-Off);
+ Red = CWI->FR;
+ Green = CWI->FG;
+ Blue = CWI->FB;
+
+ Off=i+1;
+ Cio_PrintF(hWnd, "%c%c%c%c", 0, 255, 32, 32);
+ Bold = 1;
+ continue;
+ }
+ if ( Bold )
+ {
+ Buffer[i] = 0;
+ Cio_Puts(hWnd, Buffer+Off, i-Off);
+ Off=i+1;
+ Cio_PrintF(hWnd, "%c%c%c%c", 0, Red, Green, Blue);
+ Bold = 0;
+ continue;
+ }
+ }
+ }
+ Cio_Puts(hWnd, Buffer+Off, Len-Off);
+
+ LocalFree(Buffer);
+ return TRUE;
+}
+
+
+void LoadSetup(void)
+{
+}
+
+void SaveSetup(void)
+{
+}
+
+
+int SetDebugLevel(HWND hWnd, int NewLevel)
+{
+ HMENU hMenu = GetMenu(hWnd);
+
+ if ( !hMenu || !(hMenu = GetSubMenu(hMenu, 1)) ||
+ !(hMenu = GetSubMenu(hMenu, 4)) )
+ return -1;
+
+ CheckMenuItem(hMenu, IDM_DBGFATAL+debuglevel,
+ MF_BYCOMMAND | MF_UNCHECKED);
+ debuglevel = NewLevel;
+ CheckMenuItem(hMenu,IDM_DBGFATAL+debuglevel,
+ MF_BYCOMMAND | MF_CHECKED);
+
+ return debuglevel;
+}
+
+
--- /dev/null
+//Microsoft Developer Studio generated resource script.
+//
+// $Id$
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#define APSTUDIO_HIDDEN_SYMBOLS
+#include "windows.h"
+#undef APSTUDIO_HIDDEN_SYMBOLS
+#include "resource.h"
+#include "winver.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+WIRCD MENU DISCARDABLE
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "E&xit", IDM_EXIT
+ END
+ POPUP "&System"
+ BEGIN
+ MENUITEM "Ircd.&Conf", IDM_IRCDCONF
+ MENUITEM "Ircd.&Motd", IDM_IRCDMOTD
+ MENUITEM "Ircd.R&ules", IDM_IRCDRULES
+ MENUITEM SEPARATOR
+ MENUITEM "&Rehash", IDM_REHASH
+ POPUP "Debug Level"
+ BEGIN
+ MENUITEM "&Off", IDM_DBGOFF
+ MENUITEM "&Fatal", IDM_DBGFATAL
+ MENUITEM "&Error", IDM_DBGERROR
+ MENUITEM "&Notice", IDM_DBGNOTICE
+ MENUITEM "&DNS", IDM_DBGDNS
+ MENUITEM "&Info", IDM_DBGINFO
+ MENUITEM "N&umerics", IDM_DBGNUM
+ MENUITEM "&Send", IDM_DBGSEND
+ MENUITEM "&Debug", IDM_DBGDEBUG
+ MENUITEM "&Malloc", IDM_DBGMALLOC
+ MENUITEM "&List", IDM_DBGLIST
+ END
+ END
+ POPUP "&Help", HELP
+ BEGIN
+ MENUITEM "&Credits...", IDM_CREDITS
+ MENUITEM "&Dreamforge Credits...", IDM_DF
+ MENUITEM "&License...", IDM_LICENSE
+ MENUITEM "&About UnrealIRCD/32...", IDM_ABOUT
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+ABOUTBOX DIALOGEX 22, 17, 264, 129
+STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "UnrealIRCd Information"
+FONT 8, "System", 0, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,228,5,32,18,WS_GROUP,WS_EX_DLGMODALFRAME |
+ WS_EX_CLIENTEDGE
+ CTEXT "Version",IDC_VERSION,5,5,120,18,SS_SUNKEN
+ EDITTEXT IDC_INFOTEXT,0,28,264,100,ES_MULTILINE | ES_READONLY |
+ WS_VSCROLL
+END
+
+DLG_IRCDCONF DIALOG DISCARDABLE 0, 0, 294, 159
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "UnrealIRCd Setup"
+FONT 9, "Fixedsys"
+BEGIN
+ DEFPUSHBUTTON "&Save",IDOK,3,143,50,14
+ PUSHBUTTON "&Cancel",IDCANCEL,241,143,50,14
+ EDITTEXT IDC_IRCDCONF,0,0,294,140,ES_MULTILINE | ES_AUTOVSCROLL |
+ ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL | WS_HSCROLL
+END
+
+DLG_IRCDRULES DIALOG DISCARDABLE 0, 0, 294, 159
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "UnrealIRCd Setup"
+FONT 9, "Fixedsys"
+BEGIN
+ DEFPUSHBUTTON "&Save",IDOK,3,143,50,14
+ PUSHBUTTON "&Cancel",IDCANCEL,241,143,50,14
+ EDITTEXT IDC_IRCDCONF,0,0,294,140,ES_MULTILINE | ES_AUTOVSCROLL |
+ ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL | WS_HSCROLL
+END
+
+DLG_IRCDMOTD DIALOG DISCARDABLE 0, 0, 294, 159
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "UnrealIRCd Setup"
+FONT 9, "Fixedsys"
+BEGIN
+ DEFPUSHBUTTON "&Save",IDOK,3,143,50,14
+ PUSHBUTTON "&Cancel",IDCANCEL,241,143,50,14
+ EDITTEXT IDC_IRCDCONF,0,0,294,140,ES_MULTILINE | ES_AUTOVSCROLL |
+ ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL | WS_HSCROLL
+END
+
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+1 VERSIONINFO
+ FILEVERSION 3,5,0,0
+ PRODUCTVERSION 3,5,0,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0xbL
+#else
+ FILEFLAGS 0xaL
+#endif
+ FILEOS 0x10001L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ VALUE "StringFileInfo", "\0"
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", "\0"
+ END
+END
+
+#endif // !_MAC
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "#include ""windows.h""\r\n"
+ "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "#include ""resource.h""\r\n"
+ "#include ""winver.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ "ABOUTBOX", DIALOG
+ BEGIN
+ RIGHTMARGIN, 115
+ BOTTOMMARGIN, 78
+ END
+
+ "DLG_IRCDCONF", DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 287
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 152
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
--- /dev/null
+/************************************************************************\r
+ * IRC - Internet Relay Chat, Win32GUI.c\r
+ * Copyright (C) 2000 David Flynn (DrBin)\r
+ * \r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 1, or (at your option)\r
+ * any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ */\r
+\r
+\r
+\r
+#define APPNAME "wIRCD"\r
+#define wTITLEBAR "UnrealIRCd"\r
+#define OEMRESOURCE\r
+//#define _WIN32_IE 0x0500\r
+\r
+\r
+/* debug stuff*/\r
+#define WINDEBUGLEVEL_0 0x01\r
+#define WINDEBUGLEVEL_1 0x02\r
+#define WINDEBUGLEVEL_2 0x04\r
+#define WINDEBUGLEVEL_3 0x08\r
+#define WINDEBUGLEVEL_FLUSH 0x10\r
+#define WINDEBUG_FORCE 0x20\r
+#define WINNOTIFY_0 0x0100\r
+#define WINNOTIFY_1 0x0200\r
+#define WINNOTIFY_2 0x0400\r
+#define WINNOTIFY_3 0x0800\r
+/*end*/\r
+//#define ircnetwork "a network"\r
+//#define netdomain "netdomain"\r
+//#define helpchan "helpchan"\r
+//#define IRCDTOTALVERSION "3"\r
+#ifndef IRCDTOTALVERSION\r
+#define IRCDTOTALVERSION BASE_VERSION PATCH1 PATCH2 PATCH3 PATCH4 PATCH5 PATCH6 PATCH7 PATCH8 PATCH9\r
+#endif\r
+\r
+#include <windows.h>\r
+#include "resource.h"\r
+#include "version.h"\r
+#include "setup.h"\r
+#include <commctrl.h>\r
+\r
+/* These came from ircd.c*/\r
+#include "struct.h"\r
+#include "common.h"\r
+#include "sys.h"\r
+#include "numeric.h"\r
+#include "userload.h"\r
+//#include "services.h"\r
+#include <sys/stat.h>\r
+#include <signal.h>\r
+#include <fcntl.h>\r
+#include <sys/types.h>\r
+#include <io.h>\r
+#include <direct.h>\r
+#include <errno.h>\r
+#include "h.h"\r
+#include "Win32New.h"\r
+#include <richedit.h>\r
+\r
+/* end */\r
+int SetDebugLevel(HWND hWnd, int NewLevel);\r
+void SetupPopups(HWND hDlg);\r
+HWND CreateATreeView(HWND hwndParent/*, LPSTR lpszFileName*/,RECT rcClient); \r
+HTREEITEM AddItemToTree(HWND hWnd, LPSTR lpszItem, int nLevel);\r
+void win_map(cptr, server, mask, prompt_length, length,hwTreeView);\r
+LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);\r
+LRESULT CALLBACK MainDLG(HWND, UINT, WPARAM, LPARAM);\r
+LRESULT CALLBACK wStatusDLG(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);\r
+LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);\r
+LRESULT CALLBACK Dlg_IRCDRULES(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);\r
+LRESULT CALLBACK Dlg_IRCDMOTD(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);\r
+LRESULT CALLBACK Dlg_IRCDCONF(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);\r
+LRESULT CALLBACK Credits(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);\r
+LRESULT CALLBACK Dreamforge(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);\r
+LRESULT CALLBACK IRCDLicense(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);\r
+extern void SocketLoop(void *dummy), s_rehash(), do_dns_async(HANDLE id);\r
+void windebug(level, form, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);\r
+extern struct /*current_load_struct */current_load_data;\r
+LRESULT CALLBACK GraphCtlProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);\r
+void NiceQuit(void);\r
+extern int max_client_count;\r
+HINSTANCE hInst;\r
+HWND hStatsWnd,hgraphwnd;\r
+int windebuglevel = 0 ;\r
+//| WINDEBUGLEVEL_0 | WINDEBUGLEVEL_1 | WINDEBUGLEVEL_2 | WINDEBUGLEVEL_3 | WINDEBUGLEVEL_FLUSH ;\r
+int usernumhistory[530], usernumpointer;\r
+char String[2048];\r
+#include "version.h"\r
+FILE *debugfile;\r
+aConfiguration iConf;\r
+char *version, *creation;\r
+char shortversion[] = BASE_VERSION PATCH1;\r
+char szAppName[] = APPNAME; // The name of this application\r
+char szTitle[] = wTITLEBAR; // The title bar text\r
+HWND hwIRCDWnd=NULL/* hwnd=NULL*/;\r
+INFRICHLINE AllLines;\r
+ NOTIFYICONDATA SysTray;\r
+HANDLE hMainThread = 0;\r
+HMENU ConfPopup, AboutPopup, DebugPopup;\r
+int APIENTRY WinMain(HINSTANCE hInstance,\r
+ HINSTANCE hPrevInstance,\r
+ LPSTR lpCmdLine,\r
+ int nCmdShow)\r
+{\r
+ MSG msg;\r
+ HANDLE hAccelTable;\r
+ int argc=0, yy;\r
+ char *s, *argv[20], String[128];\r
+ HWND hWnd;\r
+ WSADATA WSAData;\r
+ char meep[MAX_PATH];\r
+\r
+ if ((debugfile = fopen("debugout2.log","ac"))==NULL)\r
+ MessageBox(NULL, "UnrealIRCD/32 Initalization Error", "Unable to create debugout.log",MB_OK);\r
+ windebug(WINDEBUG_FORCE,"Initializing Unreal wIRCd");\r
+ windebug(WINDEBUG_FORCE,"%s compiled on %s %s",version,__DATE__,__TIME__);\r
+ windebug(WINDEBUG_FORCE,"%s Last modifed %s",__FILE__,__TIMESTAMP__);\r
+\r
+\r
+ /* Create a new instance */\r
+ if ( WSAStartup(MAKEWORD(1, 1), &WSAData) != 0 )\r
+ {\r
+ MessageBox(NULL, "UnrealIRCD/32 Initalization Error", "Unable to initialize WinSock", MB_OK);\r
+ return FALSE;\r
+ }\r
+ /* Store instance handle in our global variable */\r
+ hInst = hInstance; \r
+ \r
+ hWnd = CreateDialog(hInstance, "wIRCD", 0, MainDLG); \r
+ if ( !hWnd )\r
+ return (FALSE);\r
+ hwIRCDWnd = hWnd;\r
+\r
+ {\r
+\r
+ HICON hIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(sysicondisabled), IMAGE_ICON,16, 16, 0);\r
+ SysTray.cbSize = sizeof (NOTIFYICONDATA);\r
+ \r
+ SysTray.hIcon = hIcon;\r
+ SysTray.hWnd = hwIRCDWnd;\r
+ lstrcpyn(SysTray.szTip, shortversion, sizeof(shortversion));;\r
+ SysTray.uCallbackMessage = WM_USER;\r
+ SysTray.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE; \r
+ SysTray.uID = 0;\r
+ \r
+ Shell_NotifyIcon(NIM_ADD ,&SysTray);\r
+ if (hIcon)\r
+ {\r
+ DestroyIcon(hIcon);\r
+ }\r
+ }\r
+\r
+ /*\r
+ ** We have initialised, start doing something usefull !\r
+ */\r
+ /* Parse the command line */\r
+ /*argv[0] = "WIRCD.EXE";*/\r
+ if ( (s = /*lpCmdLine*/ GetCommandLine()) )\r
+ {\r
+ argv[argc++] = s;\r
+ /*while ( (s = strchr(s, ' ')) != NULL )\r
+ {*/\r
+ // while ( *s == ' ' ) *s++ = 0;\r
+ // argv[argc++] = s;\r
+ // }\r
+ }\r
+ argv[argc] = NULL;\r
+\r
+ if ( InitwIRCD(argc, argv) != 1 )\r
+ {\r
+ MessageBox(NULL,"Unreal IRCd for Windows has failed to initialise in InitwIRCD()","Error:",MB_OK);\r
+ return FALSE;\r
+ }\r
+\r
+ /*Make sure we have the common controlls loaded ...\r
+ *And the Rich edit controll */\r
+ InitCommonControls();\r
+ LoadLibrary("RichEd20.Dll");\r
+ {\r
+\r
+ /* Setup WNDCLASS for graphy control*/\r
+ WNDCLASS wc;\r
+ memset(&wc,0,sizeof(WNDCLASS));\r
+\r
+ wc.style = CS_DBLCLKS ;\r
+ wc.lpfnWndProc = GraphCtlProc;\r
+ wc.cbWndExtra = 4;\r
+ wc.hInstance = hInst;\r
+ wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);\r
+ wc.lpszClassName = "Graph";\r
+ wc.lpszMenuName = NULL;\r
+ wc.hCursor = LoadCursor(NULL,IDC_ARROW);\r
+\r
+ if (!RegisterClass (&wc))\r
+ {\r
+ MessageBox (NULL,"Error Initializing RegisterClass() for class Graphy",\r
+ (LPCTSTR) "UnrealIRCD/32 Initalization Error", MB_OK | MB_ICONEXCLAMATION);\r
+ }\r
+ }\r
+\r
+ wsprintf(String, "UnrealIRCd/32 - %s", me.name);\r
+ SetWindowText(hwIRCDWnd, String);\r
+ SetDebugLevel(hwIRCDWnd, debuglevel);\r
+\r
+ hMainThread = (HANDLE) _beginthread(SocketLoop, 0, NULL);\r
+ hAccelTable = LoadAccelerators (hInstance, szAppName);\r
+ {\r
+ HICON hIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(sysicon), IMAGE_ICON,16, 16, 0);\r
+ SysTray.hIcon = hIcon;\r
+ Shell_NotifyIcon(NIM_MODIFY ,&SysTray);\r
+ if (hIcon)\r
+ {\r
+ DestroyIcon(hIcon);\r
+ }\r
+ }\r
+\r
+ atexit(NiceQuit);\r
+\r
+ /* Main message loop */\r
+ while (GetMessage(&msg, NULL, 0, 0))\r
+ {\r
+ TranslateMessage(&msg);\r
+ DispatchMessage(&msg);\r
+ }\r
+\r
+ windebug(WINDEBUG_FORCE,"Unreal Terminating ....");\r
+ Shell_NotifyIcon(NIM_DELETE ,&SysTray);\r
+ fclose(debugfile);\r
+\r
+ return msg.wParam;\r
+}\r
+\r
+void NiceQuit(void)\r
+{\r
+ windebug(WINDEBUG_FORCE,"Unreal Terminating ....");\r
+ Shell_NotifyIcon(NIM_DELETE ,&SysTray);\r
+ fclose(debugfile);\r
+}\r
+\r
+LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+ switch (message)\r
+ {\r
+ case WM_CREATE :\r
+ return 0;\r
+\r
+/* case WM_USER:\r
+ windebug(WINDEBUGLEVEL_2,"entering WM_USER");\r
+ switch(lParam)\r
+ {\r
+ case WM_LBUTTONDOWN:\r
+ /* We want to first ... get a pasword if required, then show the window*/\r
+/* if (hwIRCDWnd)\r
+ {\r
+ ShowWindow (hwIRCDWnd, SW_SHOW);\r
+ ShowWindow (hwIRCDWnd,SW_RESTORE);\r
+ SetForegroundWindow(hwIRCDWnd);\r
+ }else{\r
+ hwIRCDWnd = CreateDialog(hInst, "wIRCD", 0, MainDLG);\r
+ ShowWindow (hwIRCDWnd, SW_SHOW);\r
+ }\r
+ break;\r
+ }\r
+ return 1;*/\r
+ }\r
+ return DefWindowProc(hWnd, message, wParam, lParam);\r
+}\r
+\r
+\r
+LRESULT CALLBACK MainDLG(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+int wmId, wmEvent; \r
+static HMENU hMenu, hSystemSubMenu, hHelpSubMenu;\r
+switch (message)\r
+ {\r
+ case WM_INITDIALOG:\r
+ {\r
+ /* ToDo :: ReWrite whole menu routine .. to actually work properly ... and use MF_(UN)CHECKED !\r
+ ** -- David Flynn 15-02-2000 **/\r
+ /* Done ! Now uses windebuglevel -- David Flynn 16-02-2000 **/\r
+\r
+ hMenu = LoadMenu(hInst, "Menu_PopUp");\r
+ hSystemSubMenu = GetSubMenu(hMenu, 2);\r
+ hHelpSubMenu = GetSubMenu(hMenu, 3);\r
+ SetMenuDefaultItem(hSystemSubMenu,IDM_IRCDCONF, MF_BYCOMMAND);\r
+ SetTimer (hDlg, UPDATE_TIMER, UPDATE_INTERVAL, NULL);\r
+ }\r
+ return 1;\r
+\r
+ case WM_SIZE :\r
+ windebug(WINDEBUGLEVEL_2,"recieved WM_SIZE");\r
+ if (wParam & SIZE_MINIMIZED)\r
+ {\r
+ ShowWindow(hDlg,SW_HIDE);\r
+ return 0;\r
+ }\r
+\r
+ case WM_USER:\r
+ windebug(WINDEBUGLEVEL_2,"entering WM_USER");\r
+ switch(lParam)\r
+ {\r
+ case WM_LBUTTONDOWN:\r
+ /* We want to first ... get a pasword if required, then show the window*/\r
+ /* if (hwIRCDWnd)\r
+ {*/\r
+ ShowWindow (hDlg, SW_SHOW);\r
+ ShowWindow (hDlg,SW_RESTORE);\r
+ SetForegroundWindow(hDlg);\r
+ // }else{\r
+ // hwIRCDWnd = CreateDialog(hInst, "wIRCD", 0, MainDLG);\r
+ // ShowWindow (hwIRCDWnd, SW_SHOW);\r
+ // }\r
+ break;\r
+ }\r
+ return 1;\r
+\r
+ case WM_TIMER :\r
+ switch(wParam)\r
+ {\r
+ case UPDATE_TIMER:\r
+ usernumhistory[usernumpointer] = lu_clu;\r
+ usernumpointer++;\r
+ usernumpointer %= 370;\r
+ if (hStatsWnd != NULL)\r
+ PostMessage(hgraphwnd,(WM_USER +1), 0,0);\r
+ return 1;\r
+ }\r
+ break;\r
+\r
+ case WM_COMMAND:\r
+ \r
+ wmId = LOWORD(wParam);\r
+ wmEvent = HIWORD(wParam);\r
+\r
+ switch(LOWORD(wParam))\r
+ {\r
+ case MM_WINDEBUGLEVEL_0 :\r
+ /*Standard Level Debug ... not much stuff*/\r
+ windebug(WINDEBUGLEVEL_1,"Recieved MM_WINDEBUGLEVEL_0, windebuglevel = %X", windebuglevel);\r
+ if ((windebuglevel & WINDEBUGLEVEL_0) != 0)\r
+ {\r
+ windebug(WINDEBUGLEVEL_1,"(windebuglevel & WINDEBUGLEVEL_0) != 0");\r
+ CheckMenuItem(hSystemSubMenu,MM_WINDEBUGLEVEL_0,MF_UNCHECKED);\r
+ windebuglevel &= ~WINDEBUGLEVEL_0;\r
+ }else{\r
+ windebug(WINDEBUGLEVEL_1,"(windebuglevel & WINDEBUGLEVEL_0) = 0");\r
+ CheckMenuItem(hSystemSubMenu,MM_WINDEBUGLEVEL_0,MF_CHECKED);\r
+ windebuglevel |= WINDEBUGLEVEL_0;\r
+ }\r
+ windebug(WINDEBUGLEVEL_1,"finished MM_WINDEBUGLEVEL_0, windebuglevel = %X", windebuglevel);\r
+ return 0;\r
+ case MM_WINDEBUGLEVEL_1 :\r
+ /*Higher Level ... Look at when functions are called*/\r
+ windebug(WINDEBUGLEVEL_1,"Recieved MM_WINDEBUGLEVEL_1, windebuglevel = %X", windebuglevel);\r
+ if ((windebuglevel & WINDEBUGLEVEL_1) != 0)\r
+ {\r
+ windebug(WINDEBUGLEVEL_1,"(windebuglevel & WINDEBUGLEVEL_1) != 0");\r
+ CheckMenuItem(hSystemSubMenu,MM_WINDEBUGLEVEL_1,MF_UNCHECKED);\r
+ windebuglevel &= ~WINDEBUGLEVEL_1;\r
+ }else{\r
+ windebug(WINDEBUGLEVEL_1,"(windebuglevel & WINDEBUGLEVEL_1) = 0");\r
+ CheckMenuItem(hSystemSubMenu,MM_WINDEBUGLEVEL_1,MF_CHECKED);\r
+ windebuglevel |= WINDEBUGLEVEL_1;\r
+ }\r
+ windebug(WINDEBUGLEVEL_1,"finished MM_WINDEBUGLEVEL_1, windebuglevel = %X", windebuglevel);\r
+ return 0;\r
+ case MM_WINDEBUGLEVEL_2 :\r
+ /*Higher Still ... Look at what happens in functions*/\r
+ windebug(WINDEBUGLEVEL_1,"Recieved MM_WINDEBUGLEVEL_2, windebuglevel = %X", windebuglevel);\r
+ if ((windebuglevel & WINDEBUGLEVEL_2) != 0)\r
+ {\r
+ windebug(WINDEBUGLEVEL_1,"(windebuglevel & WINDEBUGLEVEL_2) != 0");\r
+ CheckMenuItem(hSystemSubMenu,MM_WINDEBUGLEVEL_2,MF_UNCHECKED);\r
+ windebuglevel &= ~WINDEBUGLEVEL_2;\r
+ }else{\r
+ windebug(WINDEBUGLEVEL_1,"(windebuglevel & WINDEBUGLEVEL_2) = 0");\r
+ CheckMenuItem(hSystemSubMenu,MM_WINDEBUGLEVEL_2,MF_CHECKED);\r
+ windebuglevel |= WINDEBUGLEVEL_2;\r
+ }\r
+ windebug(WINDEBUGLEVEL_1,"finished MM_WINDEBUGLEVEL_2, windebuglevel = %X", windebuglevel);\r
+ return 0;\r
+ case MM_WINDEBUGLEVEL_FLUSH :\r
+ /*Make fflush happen on windebug()*/\r
+ windebug(WINDEBUGLEVEL_1,"Recieved MM_WINDEBUGLEVEL_FLUSH, windebuglevel = %X", windebuglevel);\r
+ if ((windebuglevel & WINDEBUGLEVEL_FLUSH) != 0)\r
+ {\r
+ windebug(WINDEBUGLEVEL_1,"(windebuglevel & WINDEBUGLEVEL_FLUSH) != 0");\r
+ CheckMenuItem(hSystemSubMenu,MM_WINDEBUGLEVEL_FLUSH,MF_UNCHECKED);\r
+ windebuglevel &= ~WINDEBUGLEVEL_FLUSH;\r
+ }else{\r
+ windebug(WINDEBUGLEVEL_1,"(windebuglevel & WINDEBUGLEVEL_FLUSH) = 0");\r
+ CheckMenuItem(hSystemSubMenu,MM_WINDEBUGLEVEL_FLUSH,MF_CHECKED);\r
+ windebuglevel |= WINDEBUGLEVEL_FLUSH;\r
+ }\r
+ windebug(WINDEBUGLEVEL_1,"finished MM_WINDEBUGLEVEL_FLUSH, windebuglevel = %X", windebuglevel);\r
+ return 0;\r
+ case IDM_ABOUT:\r
+ DialogBox(hInst, "AboutBox", hDlg, (DLGPROC)About);\r
+ return 0;\r
+ case IDM_CREDITS:\r
+ DialogBox(hInst, "AboutBox", hDlg, (DLGPROC)Credits);\r
+ return 0;\r
+ case IDM_DF:\r
+ DialogBox(hInst, "AboutBox", hDlg, (DLGPROC)Dreamforge);\r
+ return 0;\r
+ case IDM_LICENSE:\r
+ DialogBox(hInst, "AboutBox", hDlg, (DLGPROC)IRCDLicense);\r
+ return 0;\r
+ case IDM_IRCDCONF:\r
+ DialogBox(hInst, "Dlg_IRCDCONF", hDlg, (DLGPROC)Dlg_IRCDCONF);\r
+ return 0;\r
+ case IDM_IRCDMOTD:\r
+ DialogBox(hInst, "DLG_IRCDMOTD", hDlg, (DLGPROC)Dlg_IRCDMOTD);\r
+ return 0;\r
+ case IDM_IRCDRULES:\r
+ DialogBox(hInst, "DLG_IRCDRULES", hDlg, (DLGPROC)Dlg_IRCDRULES);\r
+ return 0;\r
+ case IDM_REHASH:\r
+ MessageBox(hDlg,"Server Rehashing ....","Unreal wIRCd3",MB_OK | MB_APPLMODAL);\r
+ s_rehash();\r
+ return 0;\r
+\r
+ case IDM_EXIT:\r
+ if ( MessageBox(hDlg, "Are you sure?",\r
+ "Terminate UnrealIRCD/32",\r
+ MB_ICONQUESTION | MB_YESNO) == IDNO )\r
+ return 0;\r
+ DestroyWindow(hDlg);\r
+ return 0;\r
+ }\r
+ return 0;\r
+\r
+ case WM_RBUTTONDBLCLK:\r
+ case WM_LBUTTONDBLCLK:\r
+ // emulate default menu item for double click\r
+ DialogBox(hInst, "Dlg_IRCDCONF", hDlg, (DLGPROC)Dlg_IRCDCONF);\r
+ break;\r
+\r
+ case WM_LBUTTONDOWN: {\r
+ POINT p;\r
+ p.x = LOWORD(lParam);\r
+ p.y = HIWORD(lParam);\r
+ /* Config popup */\r
+ if ((p.x >= 149) && (p.x <= 198)\r
+ && (p.y >= 173) && (p.y <= 186))\r
+ {\r
+\r
+ ClientToScreen(hDlg,&p);\r
+ TrackPopupMenu(hSystemSubMenu,\r
+ TPM_LEFTALIGN|TPM_LEFTBUTTON,\r
+ p.x,p.y,0,hDlg,NULL);\r
+\r
+ return 0;\r
+ }\r
+ /* about popup */\r
+ if ((p.x >= 206) && (p.x <= 252)\r
+ && (p.y >= 173) && (p.y <= 186))\r
+ {\r
+ ClientToScreen(hDlg,&p);\r
+ TrackPopupMenu(hHelpSubMenu,\r
+ TPM_LEFTALIGN|TPM_LEFTBUTTON,\r
+ p.x,p.y,0,hDlg,NULL);\r
+ return 0;\r
+ }\r
+ /* rehash button */\r
+ if ((p.x >= 31) && (p.x <= 81)\r
+ && (p.y >= 173) && (p.y <= 186))\r
+ {\r
+ PostMessage(hDlg, WM_COMMAND, IDM_REHASH, 0); \r
+ return 0;\r
+ }\r
+ /* quit button */\r
+ if ((p.x >= 264) && (p.x <= 328)\r
+ && (p.y >= 173) && (p.y <= 186))\r
+ {\r
+ PostMessage(hDlg, WM_COMMAND, IDM_EXIT, 0);\r
+ return 0;\r
+ }\r
+ /* status button */\r
+ if ((p.x >= 93) && (p.x <= 138)\r
+ && (p.y >= 173) && (p.y <= 186))\r
+ {\r
+ if (hStatsWnd == NULL){\r
+ DialogBox(hInst, /*"WIRCDSTATUS"*/"DLG_STATS", NULL, (DLGPROC)wStatusDLG);\r
+ return 0;\r
+ }else{\r
+ if (SetForegroundWindow(hStatsWnd)==0){\r
+ windebug(WINDEBUG_FORCE,"Error at BringWindowToTop(), Err=%d",GetLastError());\r
+ }\r
+ return 0;\r
+ }\r
+ }\r
+ \r
+ break;\r
+ }\r
+ case WM_CLOSE:\r
+ PostMessage(hDlg, WM_COMMAND, IDM_EXIT, 0);\r
+ \r
+ return 0;\r
+ /* Fall through to destroy the window and then send to WM_QUIT to the msg que*/\r
+\r
+ case WM_DESTROY:\r
+ KillTimer(hDlg, UPDATE_TIMER);\r
+ localdie();\r
+\r
+ /* Never returns *//* i hope it does ... */\r
+ /* Ok ... It doesnt ... That _NEEDS_ Fixing !!!!!*/\r
+ /* Fixed -- i hope */\r
+ PostQuitMessage(0);\r
+ return 0;\r
+\r
+ case WM_QUIT:\r
+ if ( MessageBox(hDlg, "WM_QUIT Are you sure?", "Terminate UnrealIRCd/32",\r
+ MB_ICONQUESTION | MB_YESNO | MB_APPLMODAL) == IDNO )\r
+ return 0;\r
+\r
+ return 0;\r
+\r
+ }\r
+ DefWindowProc(hDlg, message, wParam, lParam);\r
+ return 0;\r
+}\r
+\r
+\r
+\r
+LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+ switch (message)\r
+ {\r
+ case WM_INITDIALOG:\r
+#define Ccat strcat(String, String2)\r
+ {\r
+ char String[16384], String2[16384], **s = infotext;\r
+ wsprintf(String, "%s\n%s", version, creation);\r
+ SetDlgItemText(hDlg, IDC_VERSION, String);\r
+ String[0] = 0; String2[0] = 0;\r
+ wsprintf(String2, "-=-=-=-=-=-==-==- %s -=-=-==-==-=-=-=-=-=-\r\n", ircnetwork); Ccat;\r
+ wsprintf(String2, "|Web Page: | http://www.%s\r\n", netdomain); Ccat;\r
+ wsprintf(String2, "|FTP Archive: | ftp://ftp.%s\r\n", netdomain); Ccat;\r
+ wsprintf(String2, "|Help channel: | %s\r\n", helpchan); Ccat;\r
+ wsprintf(String2, "|=-=-=-=-=-==-==|-=-=-=-=-=-=-==-==-=-=-=-=-=-=-=\r\n"); Ccat;\r
+ wsprintf(String2, "|IRCd version: | %s\r\n", IRCDTOTALVERSION); Ccat; \r
+ wsprintf(String2, "| Programmer: | Stskeeps <stskeeps@tspre.org>\r\n"); Ccat;\r
+ wsprintf(String2, "| Win32 Coders: | DrBin <drbin@tspre.org>\r\n"); Ccat;\r
+ wsprintf(String2, "| | codemastr <codemastr@tspre.org>\r\n"); Ccat; \r
+ wsprintf(String2, "| | {X} <x@tspre.org>\r\n"); Ccat; \r
+#if defined(_WIN32) && defined(WIN32_SPECIFY)\r
+ wsprintf(String2, "| Win32 Porter: | %s\r\n", WIN32_PORTER); Ccat;\r
+ wsprintf(String2, "| >>URL: | %s\r\n", WIN32_URL); Ccat;\r
+#endif\r
+ wsprintf(String2, "|Credits: | Type /Credits\r\n"); Ccat;\r
+ wsprintf(String2, "|DALnet Credits:| Type /DALinfo\r\n"); Ccat;\r
+ wsprintf(String2, "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\r\n"); Ccat;\r
+ wsprintf(String2, "| Unreal IRCd can be downloaded at http://unreal.tspre.org\r\n"); Ccat; \r
+ wsprintf(String2, "| This notice may not be removed from the IRCd package\r\n"); Ccat;\r
+ wsprintf(String2, "| It will be a violation of copyright. This program must always\r\n"); Ccat;\r
+ wsprintf(String2, "| stay free of charge being sold commercially or privately\r\n"); Ccat;\r
+ wsprintf(String2, "| Only charge may be for the transport medium like on CD-ROM, floppy\r\n"); Ccat;\r
+ wsprintf(String2, "| or other kinds (-Stskeeps'1999)\r\n"); Ccat;\r
+ wsprintf(String2, "--------------------------------------------\r\n"); Ccat;\r
+ SetDlgItemText(hDlg, IDC_INFOTEXT, String);\r
+#undef Ccat\r
+ ShowWindow (hDlg, SW_SHOW);\r
+ return (TRUE);\r
+ }\r
+\r
+ case WM_COMMAND:\r
+ if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)\r
+ {\r
+ EndDialog(hDlg, TRUE);\r
+ return (TRUE);\r
+ }\r
+ break;\r
+ }\r
+ return FALSE;\r
+}\r
+\r
+/*\r
+ * FUNCTION: Credits(HWND, unsigned, WORD, LONG)\r
+ *\r
+ * PURPOSE: Processes messages for "Credits" dialog box\r
+ * This version allows greater flexibility over the contents of the 'Credits' box,\r
+ * by pulling out values from the 'Version' resource.\r
+ *\r
+ * MESSAGES:\r
+ *\r
+ * WM_INITDIALOG - initialize dialog box\r
+ * WM_COMMAND - Input received\r
+ *\r
+ */\r
+LRESULT CALLBACK Credits(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+ switch (message)\r
+ {\r
+ case WM_INITDIALOG:\r
+ {\r
+ char String[16384], **s = unrealcredits;\r
+\r
+ wsprintf(String, "%s\n%s", version, creation);\r
+ SetDlgItemText(hDlg, IDC_VERSION, String);\r
+ String[0] = 0;\r
+ while ( *s )\r
+ {\r
+ strcat(String, *s++);\r
+ if ( *s )\r
+ strcat(String, "\r\n");\r
+ }\r
+ SetDlgItemText(hDlg, IDC_INFOTEXT, String);\r
+\r
+\r
+ ShowWindow (hDlg, SW_SHOW);\r
+ return (TRUE);\r
+ }\r
+\r
+ case WM_COMMAND:\r
+ if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)\r
+ {\r
+ EndDialog(hDlg, TRUE);\r
+ return (TRUE);\r
+ }\r
+ break;\r
+ }\r
+ return FALSE;\r
+}\r
+\r
+/*\r
+ * FUNCTION: Dreamforge(HWND, unsigned, WORD, LONG)\r
+ *\r
+ * PURPOSE: Processes messages for "Dreamforge" dialog box\r
+ * This version allows greater flexibility over the contents of the 'Dreamforge' box,\r
+ * by pulling out values from the 'Version' resource.\r
+ *\r
+ * MESSAGES:\r
+ *\r
+ * WM_INITDIALOG - initialize dialog box\r
+ * WM_COMMAND - Input received\r
+ *\r
+ */\r
+LRESULT CALLBACK Dreamforge(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+ switch (message)\r
+ {\r
+ case WM_INITDIALOG:\r
+ {\r
+ char String[16384], **s = dalinfotext;\r
+\r
+ wsprintf(String, "%s\n%s", version, creation);\r
+ SetDlgItemText(hDlg, IDC_VERSION, String);\r
+ String[0] = 0;\r
+ while ( *s )\r
+ {\r
+ strcat(String, *s++);\r
+ if ( *s )\r
+ strcat(String, "\r\n");\r
+ }\r
+ SetDlgItemText(hDlg, IDC_INFOTEXT, String);\r
+\r
+\r
+ ShowWindow (hDlg, SW_SHOW);\r
+ return (TRUE);\r
+ }\r
+\r
+ case WM_COMMAND:\r
+ if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)\r
+ {\r
+ EndDialog(hDlg, TRUE);\r
+ return (TRUE);\r
+ }\r
+ break;\r
+ }\r
+ return FALSE;\r
+}\r
+\r
+/*\r
+ * FUNCTION: IRCDLicense(HWND, unsigned, WORD, LONG)\r
+ *\r
+ * PURPOSE: Processes messages for "IRCDLicense" dialog box\r
+ * This version allows greater flexibility over the contents of the 'IRCDLicense' box,\r
+ * by pulling out values from the 'Version' resource.\r
+ *\r
+ * MESSAGES:\r
+ *\r
+ * WM_INITDIALOG - initialize dialog box\r
+ * WM_COMMAND - Input received\r
+ *\r
+ */\r
+LRESULT CALLBACK IRCDLicense(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+ switch (message)\r
+ {\r
+ case WM_INITDIALOG:\r
+ {\r
+ char String[16384], **s = gnulicense;\r
+\r
+ wsprintf(String, "%s\n%s", version, creation);\r
+ SetDlgItemText(hDlg, IDC_VERSION, String);\r
+ String[0] = 0;\r
+ while ( *s )\r
+ {\r
+ strcat(String, *s++);\r
+ if ( *s )\r
+ strcat(String, "\r\n");\r
+ }\r
+ SetDlgItemText(hDlg, IDC_INFOTEXT, String);\r
+\r
+\r
+ ShowWindow (hDlg, SW_SHOW);\r
+ return (TRUE);\r
+ }\r
+\r
+ case WM_COMMAND:\r
+ if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)\r
+ {\r
+ EndDialog(hDlg, TRUE);\r
+ return (TRUE);\r
+ }\r
+ break;\r
+ }\r
+ return FALSE;\r
+}\r
+\r
+\r
+/*\r
+ * FUNCTION: Dlg_IrcdConf(HWND, unsigned, WORD, LONG)\r
+ *\r
+ * PURPOSE: Processes messages for "DLG_IRCDCONF" dialog box\r
+ *\r
+ */\r
+LRESULT CALLBACK Dlg_IRCDCONF(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+ switch (message)\r
+ {\r
+ case WM_INITDIALOG:\r
+ {\r
+ char *Buffer = MyMalloc(65535); /* Should be big enough */\r
+ int fd, Len;\r
+\r
+ if ( !Buffer )\r
+ {\r
+ MessageBox(hDlg, "Error: Could not allocate temporary buffer",\r
+ "UnrealIRCd/32 Setup", MB_OK);\r
+ EndDialog(hDlg, FALSE);\r
+ return FALSE;\r
+ }\r
+ /* Open the ircd.conf file */\r
+ fd = open(CONFIGFILE, _O_RDONLY | _O_BINARY);\r
+ if ( fd == -1 )\r
+ {\r
+ MessageBox(hDlg, "Error: Could not open configuration file",\r
+ "UnrealIRCd/32 Setup", MB_OK);\r
+ MyFree(Buffer);\r
+ EndDialog(hDlg, FALSE);\r
+ return FALSE;\r
+ }\r
+\r
+ Buffer[0] = 0; /* Incase read() fails */\r
+ Len = read(fd, Buffer, 65535);\r
+ Buffer[Len] = 0;\r
+ /* Set the text for the edit control to what was in the file */\r
+ SendDlgItemMessage(hDlg, IDC_IRCDCONF, WM_SETTEXT, 0,\r
+ (LPARAM)(LPCTSTR)Buffer);\r
+\r
+ close(fd);\r
+ MyFree(Buffer);\r
+ }\r
+ return (TRUE);\r
+\r
+ case WM_COMMAND:\r
+ if ( LOWORD(wParam) == IDOK )\r
+ {\r
+ char *Buffer = MyMalloc(65535); /* Should be big enough */\r
+ DWORD Len;\r
+ int fd;\r
+\r
+ if ( !Buffer )\r
+ {\r
+ MessageBox(hDlg, "Error: Could not allocate temporary buffer",\r
+ "UnrealIRCD/32 Setup", MB_OK);\r
+ return TRUE;\r
+ }\r
+ /* Open the ircd.conf file */\r
+ fd = open(CONFIGFILE, _O_TRUNC|_O_CREAT|_O_RDWR|_O_BINARY,\r
+ S_IREAD|S_IWRITE);\r
+ if ( fd == -1 )\r
+ {\r
+ MessageBox(hDlg, "Error: Could not open configuration file",\r
+ "UnrealIRCD/32 Setup", MB_OK);\r
+ MyFree(Buffer);\r
+ return TRUE;\r
+ }\r
+\r
+ /* Get the text from the edit control and save it to disk. */\r
+ Len = SendDlgItemMessage(hDlg, IDC_IRCDCONF, WM_GETTEXT, 65535,\r
+ (LPARAM)(LPCTSTR)Buffer);\r
+ write(fd, Buffer, Len);\r
+\r
+ close(fd);\r
+ MyFree(Buffer);\r
+\r
+ EndDialog(hDlg, TRUE);\r
+ return TRUE;\r
+ }\r
+ if ( LOWORD(wParam) == IDCANCEL )\r
+ {\r
+ EndDialog(hDlg, FALSE);\r
+ return TRUE;\r
+ }\r
+ break;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/*\r
+ * FUNCTION: Dlg_Dlg_IRCdMotd(HWND, unsigned, WORD, LONG)\r
+ *\r
+ * PURPOSE: Processes messages for "DLG_IRCDCONF" dialog box\r
+ *\r
+ */\r
+LRESULT CALLBACK Dlg_IRCDMOTD(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+ switch (message)\r
+ {\r
+ case WM_INITDIALOG:\r
+ {\r
+ char *Buffer = MyMalloc(65535*2); /* Should be big enough */\r
+ int fd, Len;\r
+\r
+ if ( !Buffer )\r
+ {\r
+ MessageBox(hDlg, "Error: Could not allocate temporary buffer",\r
+ "UnrealIRCd/32 Setup", MB_OK);\r
+ EndDialog(hDlg, FALSE);\r
+ return FALSE;\r
+ }\r
+ /* Open the ircd.motd file */\r
+ fd = open(MPATH, _O_RDONLY | _O_BINARY);\r
+ if ( fd == -1 )\r
+ {\r
+ MessageBox(hDlg, "Error: Could not open MOTD file",\r
+ "UnrealIRCd/32 Setup", MB_OK);\r
+ MyFree(Buffer);\r
+ EndDialog(hDlg, FALSE);\r
+ return FALSE;\r
+ }\r
+\r
+ Buffer[0] = 0; /* Incase read() fails */\r
+ Len = read(fd, Buffer, 65535);\r
+ Buffer[Len] = 0;\r
+ /* Set the text for the edit control to what was in the file */\r
+ SendDlgItemMessage(hDlg, IDC_IRCDCONF, WM_SETTEXT, 0,\r
+ (LPARAM)(LPCTSTR)Buffer);\r
+\r
+ close(fd);\r
+ MyFree(Buffer);\r
+ }\r
+ return (TRUE);\r
+\r
+ case WM_COMMAND:\r
+ if ( LOWORD(wParam) == IDOK )\r
+ {\r
+ char *Buffer = MyMalloc(65535); /* Should be big enough */\r
+ DWORD Len;\r
+ int fd;\r
+\r
+ if ( !Buffer )\r
+ {\r
+ MessageBox(hDlg, "Error: Could not allocate temporary buffer",\r
+ "UnrealIRCD/32 Setup", MB_OK);\r
+ return TRUE;\r
+ }\r
+ /* Open the ircd.motd file */\r
+ fd = open(MPATH, _O_TRUNC|_O_CREAT|_O_RDWR|_O_BINARY,\r
+ S_IREAD|S_IWRITE);\r
+ if ( fd == -1 )\r
+ {\r
+ MessageBox(hDlg, "Error: Could not open motd file",\r
+ "UnrealIRCD/32 Setup", MB_OK);\r
+ MyFree(Buffer);\r
+ return TRUE;\r
+ }\r
+\r
+ /* Get the text from the edit control and save it to disk. */\r
+ Len = SendDlgItemMessage(hDlg, IDC_IRCDCONF, WM_GETTEXT, 65535,\r
+ (LPARAM)(LPCTSTR)Buffer);\r
+ write(fd, Buffer, Len);\r
+\r
+ close(fd);\r
+ MyFree(Buffer);\r
+\r
+ EndDialog(hDlg, TRUE);\r
+ return TRUE;\r
+ }\r
+ if ( LOWORD(wParam) == IDCANCEL )\r
+ {\r
+ EndDialog(hDlg, FALSE);\r
+ return TRUE;\r
+ }\r
+ break;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/*\r
+ * FUNCTION: Dlg_IRCdRules(HWND, unsigned, WORD, LONG)\r
+ *\r
+ * PURPOSE: Processes messages for "DLG_IRCDCONF" dialog box\r
+ *\r
+ */\r
+LRESULT CALLBACK Dlg_IRCDRULES(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+ switch (message)\r
+ {\r
+ case WM_INITDIALOG:\r
+ {\r
+ char *Buffer = MyMalloc(65535*2); /* Should be big enough */\r
+ int fd, Len;\r
+\r
+ if ( !Buffer )\r
+ {\r
+ MessageBox(hDlg, "Error: Could not allocate temporary buffer",\r
+ "UnrealIRCd/32 Setup", MB_OK);\r
+ EndDialog(hDlg, FALSE);\r
+ return FALSE;\r
+ }\r
+ /* Open the ircd.rules file */\r
+ fd = open(RPATH, _O_RDONLY | _O_BINARY);\r
+ if ( fd == -1 )\r
+ {\r
+ MessageBox(hDlg, "Error: Could not open rules file",\r
+ "UnrealIRCd/32 Setup", MB_OK);\r
+ MyFree(Buffer);\r
+ EndDialog(hDlg, FALSE);\r
+ return FALSE;\r
+ }\r
+\r
+ Buffer[0] = 0; /* Incase read() fails */\r
+ Len = read(fd, Buffer, 65535);\r
+ Buffer[Len] = 0;\r
+ /* Set the text for the edit control to what was in the file */\r
+ SendDlgItemMessage(hDlg, IDC_IRCDCONF, WM_SETTEXT, 0,\r
+ (LPARAM)(LPCTSTR)Buffer);\r
+\r
+ close(fd);\r
+ MyFree(Buffer);\r
+ }\r
+ return (TRUE);\r
+\r
+ case WM_COMMAND:\r
+ if ( LOWORD(wParam) == IDOK )\r
+ {\r
+ char *Buffer = MyMalloc(65535); /* Should be big enough */\r
+ DWORD Len;\r
+ int fd;\r
+\r
+ if ( !Buffer )\r
+ {\r
+ MessageBox(hDlg, "Error: Could not allocate temporary buffer",\r
+ "UnrealIRCD/32 Setup", MB_OK);\r
+ return TRUE;\r
+ }\r
+ /* Open the ircd.rules file */\r
+ fd = open(RPATH, _O_TRUNC|_O_CREAT|_O_RDWR|_O_BINARY,\r
+ S_IREAD|S_IWRITE);\r
+ if ( fd == -1 )\r
+ {\r
+ MessageBox(hDlg, "Error: Could not open rules file",\r
+ "UnrealIRCD/32 Setup", MB_OK);\r
+ MyFree(Buffer);\r
+ return TRUE;\r
+ }\r
+\r
+ /* Get the text from the edit control and save it to disk. */\r
+ Len = SendDlgItemMessage(hDlg, IDC_IRCDCONF, WM_GETTEXT, 65535,\r
+ (LPARAM)(LPCTSTR)Buffer);\r
+ write(fd, Buffer, Len);\r
+\r
+ close(fd);\r
+ MyFree(Buffer);\r
+\r
+ EndDialog(hDlg, TRUE);\r
+ return TRUE;\r
+ }\r
+ if ( LOWORD(wParam) == IDCANCEL )\r
+ {\r
+ EndDialog(hDlg, FALSE);\r
+ return TRUE;\r
+ }\r
+ break;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/*\r
+ * FUNCTION: wStatusDLG(HWND, unsigned, WORD, LONG)\r
+ *\r
+ * PURPOSE: Processes messages for "DLG_IRCDCONF" dialog box\r
+ *\r
+ */\r
+HWND hreditwnd;\r
+LRESULT CALLBACK wStatusDLG(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+static HWND hwTreeView/*hreditwnd*/;\r
+POINT p;\r
+char string[1024];\r
+const int i=0;\r
+LPNMTREEVIEW lpnmtv;\r
+static HWND hgraph;\r
+\r
+ RECT TV;\r
+ switch (message)\r
+ {\r
+ case WM_INITDIALOG:\r
+ {\r
+CHARFORMAT2 FontFormat;\r
+WINSTATS pWSTATS /*= (pWINSTATS) LocalAlloc (LPTR, sizeof(pWINSTATS))*/;\r
+ windebug(WINDEBUGLEVEL_1,"wStatusDLG recieved WM_INITDIALOG");\r
+ hStatsWnd = hDlg;\r
+ TV.left=14;\r
+ TV.right=140;\r
+ TV.top=14;\r
+ TV.bottom=240;\r
+ SetLastError(0);\r
+ if ((hreditwnd=CreateWindowEx(WS_EX_CLIENTEDGE,RICHEDIT_CLASS ,"Unreal wIRCd 3", WS_VISIBLE | WS_CHILD |\r
+ ES_AUTOVSCROLL | ES_MULTILINE | ES_READONLY ,\r
+ 0, 245, 535, 185, hDlg, NULL, hInst, NULL))==NULL)\r
+ MessageBox(NULL,"garhle","grargle", MB_OK);\r
+ if (GetLastError()!=0)\r
+ windebug(WINDEBUG_FORCE,"error %d",GetLastError());\r
+\r
+ FontFormat.cbSize = sizeof(CHARFORMAT2);\r
+ FontFormat.yHeight = 8 * 20 /* We measure it in twips (1/20th of a point !)*/;\r
+ FontFormat.crTextColor = RGB(0,150,0);\r
+ lstrcpyn(FontFormat.szFaceName, "Lucida Console", sizeof("Lucida Console"));;;\r
+ FontFormat.dwMask = CFM_COLOR | CFM_FACE | CFM_SIZE | CFM_BOLD | CFM_PROTECTED;\r
+\r
+ SendMessage(hreditwnd,EM_SETCHARFORMAT,SCF_ALL,&FontFormat);\r
+\r
+\r
+\r
+ hwTreeView = CreateATreeView(hDlg,TV);\r
+ win_map(NULL, &me, "*", 0, 60,hwTreeView);\r
+ windebug(WINDEBUGLEVEL_2,"hDlg = %d",hDlg);\r
+ windebug(WINDEBUGLEVEL_2,"win_map completed");\r
+ // for (i=0;i<TreeView_GetCount(hwTreeView);i++)\r
+ // {\r
+ // windebug(WINDEBUGLEVEL_2,"Allocating pWSTATS for i=%d of max %d",i,TreeView_GetCount(hwTreeView));\r
+ {\r
+ \r
+ windebug(WINDEBUGLEVEL_2,"Allocated pWSTATS");\r
+ windebug(WINDEBUGLEVEL_2,"assigning pWSTATS.connections");\r
+ pWSTATS.connections=current_load_data.conn_count;\r
+ windebug(WINDEBUGLEVEL_2,"pWSTATS.connections=%d",pWSTATS.connections);\r
+\r
+ windebug(WINDEBUGLEVEL_2,"assigning pWSTATS.CurrGlobUsers");\r
+ pWSTATS.CurrGlobUsers=lu_cglobalu;\r
+ windebug(WINDEBUGLEVEL_2,"pWSTATS.CurrGlobUsers=%d",pWSTATS.CurrGlobUsers);\r
+\r
+ windebug(WINDEBUGLEVEL_2,"assigning pWSTATS.CurrLoclUsers");\r
+ pWSTATS.CurrLoclUsers=lu_clu;\r
+ windebug(WINDEBUGLEVEL_2,"pWSTATS.CurrLoclUsers=%d",pWSTATS.CurrLoclUsers);\r
+\r
+ windebug(WINDEBUGLEVEL_2,"assigning pWSTATS.MaxGlobUsers");\r
+ pWSTATS.MaxGlobUsers=max_client_count;\r
+ windebug(WINDEBUGLEVEL_2,"pWSTATS.MaxGlobUsers=%d",pWSTATS.MaxGlobUsers);\r
+\r
+ windebug(WINDEBUGLEVEL_2,"assigning pWSTATS.NumUsers");\r
+ pWSTATS.NumUsers=lu_noninv;\r
+ windebug(WINDEBUGLEVEL_2,"pWSTATS.NumUsers=%d",pWSTATS.NumUsers);\r
+\r
+ windebug(WINDEBUGLEVEL_2,"assigning pWSTATS.Invisible");\r
+ pWSTATS.Invisible=lu_inv;\r
+ windebug(WINDEBUGLEVEL_2,"pWSTATS.Invisible=%d",pWSTATS.Invisible);\r
+\r
+ windebug(WINDEBUGLEVEL_2,"assigning pWSTATS.Servers");\r
+ pWSTATS.Servers=TreeView_GetCount(hwTreeView);\r
+ windebug(WINDEBUGLEVEL_2,"pWSTATS.Servers=%d",pWSTATS.Servers);\r
+\r
+ windebug(WINDEBUGLEVEL_2,"assigning pWSTATS.LocalClients");\r
+ pWSTATS.LocalClients=lu_mlu;\r
+ windebug(WINDEBUGLEVEL_2,"pWSTATS.LocalClients=%d",pWSTATS.LocalClients);\r
+\r
+ windebug(WINDEBUGLEVEL_2,"assigning pWSTATS.LocalServers");\r
+ pWSTATS.LocalServers=lu_lserv;\r
+ windebug(WINDEBUGLEVEL_2,"pWSTATS.LocalServers=%d",pWSTATS.LocalServers);\r
+\r
+ windebug(WINDEBUGLEVEL_2,"assigning pWSTATS.NumIRCops");\r
+ pWSTATS.NumIRCops=lu_oper;\r
+ windebug(WINDEBUGLEVEL_2,"pWSTATS.NumIRCops=%d",pWSTATS.NumIRCops);\r
+\r
+ windebug(WINDEBUGLEVEL_2,"assigning pWSTATS.chans");\r
+ pWSTATS.chans=lu_channel;\r
+ windebug(WINDEBUGLEVEL_2,"pWSTATS.chans=%d",pWSTATS.chans);\r
+ wsprintf(string, "%d",pWSTATS.CurrLoclUsers);\r
+ SetDlgItemText(hDlg,EDIT_CLOCAL,string);\r
+ wsprintf(string, "%d",pWSTATS.MaxLoclUsers);\r
+ SetDlgItemText(hDlg,EDIT_CLOCALMAX,string);\r
+ wsprintf(string, "%d",pWSTATS.Invisible);\r
+ SetDlgItemText(hDlg,EDIT_INV,string);\r
+ wsprintf(string, "%d",pWSTATS.NumUsers);\r
+ SetDlgItemText(hDlg,EDIT_NONINV,string);\r
+ wsprintf(string, "%d",pWSTATS.Servers);\r
+ SetDlgItemText(hDlg,EDIT_IRCSERVERS,string);\r
+ wsprintf(string, "%d",pWSTATS.LocalClients);\r
+ SetDlgItemText(hDlg,EDIT_MYUSERS,string);\r
+ wsprintf(string, "%d",pWSTATS.LocalServers);\r
+ SetDlgItemText(hDlg,EDIT_MYSERVERS,string);\r
+ wsprintf(string, "%d",pWSTATS.CurrGlobUsers);\r
+ SetDlgItemText(hDlg,EDIT_GLOBAL,string);\r
+ wsprintf(string, "%d",pWSTATS.MaxLoclUsers);\r
+ SetDlgItemText(hDlg,EDIT_GLOBALMAX,string);\r
+ wsprintf(string, "%d",pWSTATS.NumIRCops);\r
+ SetDlgItemText(hDlg,EDIT_IRCOPS,string);\r
+ wsprintf(string, "%d",pWSTATS.chans);\r
+ SetDlgItemText(hDlg,EDIT_CHANNELS,string);\r
+ wsprintf(string, "%d",MAXCLIENTS);\r
+ SetDlgItemText(hDlg,EDIT_LOCALMAXPOS,string);\r
+\r
+ SetLastError(0);\r
+ // SetWindowLong (hDlg,i, (LONG) pWSTATS);\r
+ windebug(WINDEBUGLEVEL_2,"Saved (pWSTATS) into (hDlg) offset = i = %d, Last error =%u",i,GetLastError());\r
+//LocalFree (LocalHandle ((LPVOID) pWSTATS));\r
+\r
+ //store them in a safe place that we can find later\r
+ \r
+ }\r
+ // }\r
+ // {\r
+\r
+\r
+ if ((hgraph=CreateWindowEx(WS_EX_CLIENTEDGE,"Graph","m",WS_VISIBLE | WS_CHILD, 166, 70, 364, 70, hDlg, NULL, hInst, NULL))==NULL)\r
+ {\r
+ MessageBox (NULL,\r
+ "Error Creating Graph Control \n CreateWindow (\"Graph\", \"\",WS_VISIBLE , 335, 25, 100, 400, hDlg, NULL, hInst, NULL)","Error CreatingWindow",\r
+ MB_OK | MB_ICONEXCLAMATION);\r
+ }\r
+ windebug(WINDEBUGLEVEL_2,"CreateWindowEx==Success");\r
+ UpdateWindow(hgraph);\r
+ windebug(WINDEBUGLEVEL_1,"UpdateWindow");\r
+ //}\r
+ /* {\r
+ pWINSTATS pWSTATS = (pWINSTATS) GetWindowLong (hDlg, 0);\r
+ if (pWSTATS == NULL)\r
+ {\r
+ windebug(WINDEBUGLEVEL_1,"Error Getting pWSTATS from GetWindowLong (hDlg,0) -> LastError = %u",GetLastError());\r
+ }else{\r
+\r
+ }\r
+ }*/\r
+ }\r
+ return (TRUE);\r
+\r
+ case WM_DESTROY:\r
+ // MessageBox(NULL,"destroying ....","WM_DESTROY",MB_OK);\r
+ // windebug(WINDEBUG_FORCE,"hreditwnd = %d , TreeViewCount = %d",hreditwnd,TreeView_GetCount(hwTreeView));\r
+// for (i=0;i<TreeView_GetCount(hwTreeView);i++)\r
+ {\r
+ // pWINSTATS pWSTATS = (pWINSTATS) GetWindowLong (hDlg, i);\r
+ // LocalFree (LocalHandle ((LPVOID) pWSTATS));\r
+ }\r
+ DestroyWindow(hreditwnd);\r
+ return (TRUE);\r
+ \r
+ case WM_NOTIFY: \r
+ switch (((LPNMHDR) lParam)->code) {\r
+ case TVN_SELCHANGED :\r
+ lpnmtv = ((LPNMTREEVIEW) lParam);\r
+ \r
+ wsprintf(string, "%d",lpnmtv->itemNew.hItem);\r
+ SetDlgItemText(hDlg,EDIT_CHANNELS,string);\r
+ \r
+ break; \r
+\r
+ // Handle other notifications here. \r
+\r
+ }\r
+ break; \r
+\r
+ case WM_RBUTTONDOWN: {\r
+ p.x = LOWORD(lParam);\r
+ p.y = HIWORD(lParam);\r
+ wsprintf(String, "Clicked at (%li, %li)", p.x, p.y);\r
+ SetWindowText(hDlg, String);\r
+ }\r
+ return TRUE;\r
+ case WM_COMMAND:\r
+ if ( LOWORD(wParam) == IDOK )\r
+ {\r
+ \r
+ EndDialog(hDlg, TRUE);\r
+ return TRUE;\r
+ }\r
+ if ( LOWORD(wParam) == IDCANCEL )\r
+ {\r
+ EndDialog(hDlg, FALSE);\r
+ return TRUE;\r
+ }\r
+ break;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+HTREEITEM AddItemToTree (HWND hWnd, LPSTR lpszItem, int nLevel)\r
+{\r
+ \r
+ TVITEM tvi; \r
+ TVINSERTSTRUCT tvins; \r
+ static HTREEITEM hPrev = (HTREEITEM) TVI_FIRST; \r
+ static HTREEITEM hPrevRootItem = NULL; \r
+ static HTREEITEM hPrevLev2Item = NULL; \r
+ HTREEITEM hti; \r
+ \r
+ tvi.mask = TVIF_TEXT | TVIF_PARAM; \r
+ \r
+ // Set the text of the item. \r
+ tvi.pszText = lpszItem; \r
+ tvi.cchTextMax = lstrlen(lpszItem); \r
+ \r
+ // Assume the item is not a parent item, so give it a \r
+ // document image. \r
+// tvi.iImage = g_nDocument; \r
+// tvi.iSelectedImage = g_nDocument; \r
+ \r
+ // Save the heading level in the item's application-defined \r
+ // data area. \r
+ tvi.lParam = (LPARAM) nLevel; \r
+ \r
+ tvins.item = tvi; \r
+ tvins.hInsertAfter = hPrev; \r
+ \r
+ // Set the parent item based on the specified level. \r
+ if (nLevel == 1) \r
+ tvins.hParent = TVI_ROOT; \r
+ else if (nLevel == 2) \r
+ tvins.hParent = hPrevRootItem; \r
+ else \r
+ tvins.hParent = hPrevLev2Item; \r
+ \r
+ // Add the item to the tree view control. \r
+ hPrev = (HTREEITEM) SendMessage(hWnd, TVM_INSERTITEM, 0, \r
+ (LPARAM) (LPTVINSERTSTRUCT) &tvins); \r
+ \r
+ // Save the handle to the item. \r
+ if (nLevel == 1) \r
+ hPrevRootItem = hPrev; \r
+ else if (nLevel == 2) {\r
+ hPrevLev2Item = hPrev; \r
+ TreeView_EnsureVisible(hWnd,hPrev);\r
+ }\r
+ // The new item is a child item. Give the parent item a \r
+ // closed folder bitmap to indicate it now has child items. \r
+ if (nLevel > 1) { \r
+ hti = TreeView_GetParent(hWnd, hPrev); \r
+ tvi.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE; \r
+ tvi.hItem = hti; \r
+// tvi.iImage = g_nClosed; \r
+// tvi.iSelectedImage = g_nClosed; \r
+ TreeView_SetItem(hWnd, &tvi); \r
+ } \r
+ \r
+ return hPrev; \r
+} \r
+\r
+\r
+// CreateATreeView - creates a tree view control. \r
+// Returns the handle to the new control if successful,\r
+// or NULL otherwise. \r
+// hwndParent - handle to the control's parent window. \r
+// lpszFileName - name of the file to parse for tree view items.\r
+\r
+HWND CreateATreeView(HWND hwndParent/*, LPSTR lpszFileName*/,RECT rcClient) \r
+{ \r
+ // RECT rcClient; // dimensions of client area \r
+ HWND hwndTV; // handle to tree view control \r
+ \r
+ // Ensure that the common control DLL is loaded. \r
+ InitCommonControls(); \r
+ \r
+ // Get the dimensions of the parent window's client area, and create \r
+ // the tree view control. \r
+ //GetClientRect(hwndParent, &rcClient); \r
+ hwndTV = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, "Tree View", \r
+ WS_VISIBLE | WS_CHILD /*| WS_BORDER | */| TVS_HASBUTTONS /*| TVS_DISABLEDRAGDROP \r
+ | TVS_SHOWSELALWAYS */ | TVS_HASLINES, \r
+ 0, 0, rcClient.right, rcClient.bottom, \r
+ hwndParent, NULL/*(HMENU) ID_TREEVIEW*/, hInst, NULL); \r
+ \r
+ \r
+ // Initialize the image list, and add items to the control. \r
+ // InitTreeViewImageLists and InitTreeViewItems are application- \r
+ // defined functions. \r
+ /* if (!InitTreeViewImageLists(hwndTV) || \r
+ !InitTreeViewItems(hwndTV, lpszFileName)) { \r
+ DestroyWindow(hwndTV); \r
+ return FALSE; \r
+ }*/ \r
+ return hwndTV;\r
+} \r
+\r
+/*\r
+ * Based on the New /MAP format [dump_map()] -Potvin\r
+ * Now used to create list of servers for server list tree view -- David Flynn\r
+ */\r
+void win_map(cptr, server, mask, prompt_length, length, hwTreeView)\r
+aClient *cptr, *server;\r
+char *mask;\r
+register int prompt_length;\r
+int length;\r
+HWND hwTreeView;\r
+{\r
+ static char prompt[64];\r
+ register char *p = &prompt[prompt_length];\r
+ register int cnt = 0, local = 0;\r
+ aClient *acptr;\r
+\r
+\r
+ for (acptr = client; acptr; acptr = acptr->next)\r
+ {\r
+ if (IsPerson(acptr))\r
+ {\r
+ ++cnt; /* == */\r
+ if (!strcmp(acptr->user->server, server->name)) ++local;\r
+ }\r
+ }\r
+\r
+ // sendto_one(cptr, rpl_str(RPL_MAP), me.name, cptr->name, prompt, length, server->name,\r
+ // local, (local*100)/cnt );\r
+ AddItemToTree (hwTreeView,server->name,1+prompt_length);\r
+ cnt = 0;\r
+ \r
+/* if (prompt_length > 0)\r
+ {\r
+ p[-1] = ' ';\r
+ if (p[-2] == '`') p[-2] = ' ';\r
+ }*/\r
+\r
+// if (prompt_length > 60) return;\r
+\r
+ strcpy(p, "|-");\r
+\r
+\r
+ for (acptr = client; acptr ; acptr = acptr->next)\r
+ {\r
+ if ( !IsServer (acptr) || strcmp(acptr->serv->up, server->name)) continue;\r
+\r
+ if ( match(mask, acptr->name) )\r
+ acptr->flags &= ~FLAGS_MAP;\r
+ else\r
+ {\r
+ acptr->flags |= FLAGS_MAP;\r
+ cnt++;\r
+ }\r
+ }\r
+\r
+ for (acptr = client; acptr ; acptr = acptr->next)\r
+ {\r
+ if ( ! (acptr->flags & FLAGS_MAP) || /* != */\r
+ !IsServer (acptr) || strcmp(acptr->serv->up, server->name)) continue;\r
+ if (--cnt == 0) *p = '`';\r
+ win_map (cptr, acptr, mask, prompt_length+1, length-2,hwTreeView);\r
+ }\r
+\r
+ if (prompt_length > 0) p[-1] = '-';\r
+}\r
+\r
+/****************************************************************\r
+********** Graphy !!!! (C) David Flynn 2000 *****************/\r
+\r
+LRESULT CALLBACK GraphCtlProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)\r
+{\r
+ HDC mem;\r
+ PAINTSTRUCT ps;\r
+ RECT r;\r
+\r
+ switch (msg) {\r
+ case WM_CREATE:\r
+ {\r
+ RECT temprect;\r
+ HDC hdc;\r
+ LPCREATESTRUCT lpcs = (LPCREATESTRUCT) lParam;\r
+ PGRAPHINFO pSCI = (PGRAPHINFO) LocalAlloc (LPTR, sizeof(GRAPHINFO));\r
+ if (!pSCI)\r
+ {\r
+ MessageBox (NULL,\r
+ "It Seems that you have a potential problem ... \n This function dont want to do a LocallAlloc() ... Report this at once !!!!",\r
+ (LPCTSTR) "GRAPHCNT.DLL",\r
+ MB_OK | MB_ICONEXCLAMATION);\r
+ return -1;\r
+ }\r
+ hgraphwnd=hwnd;\r
+ /*\r
+ ** I am initialising the "constants" now ... as they could be a root to my problems\r
+ */\r
+ pSCI->Grid = 0x00008000;\r
+ pSCI->BackColor = 0x00000000;\r
+ pSCI->GridColor = 0x00008000;\r
+ pSCI->CPUColor = 0x00000000;\r
+\r
+ GetClientRect(hwnd,&temprect);\r
+ pSCI->WindowSize.cx = temprect.right;\r
+ pSCI->WindowSize.cy = temprect.bottom;\r
+\r
+ windebug(WINDEBUGLEVEL_2,"memset(pSCI->cpuhistory, -1, 2048)");\r
+ memset(pSCI->cpuhistory, -1, 2048);\r
+ windebug(WINDEBUGLEVEL_2,"memset completed");\r
+ windebug(WINDEBUGLEVEL_2,"hwnd = %d",hwnd);\r
+\r
+ /*\r
+ ** Alloc the compatible DC for this control.\r
+ */\r
+\r
+ pSCI->DCBack = GetDC (hwnd);\r
+ windebug(WINDEBUGLEVEL_2,"got hdc");\r
+\r
+ pSCI->DCDblBuff = CreateCompatibleDC (pSCI->DCBack);\r
+\r
+ if (pSCI->DCDblBuff == NULL)\r
+ {\r
+ windebug(WINDEBUG_FORCE,"Damn Bloody Errors ... pSCI->DCDblBuff == NULL ... GAH !");\r
+ }else{\r
+ windebug(WINDEBUGLEVEL_2,"[((pSCI->DCDblBuff (=%d) = CreateCompatibleDC (hdc)) != NULL)] ~> GOOD!!!",pSCI->DCDblBuff);\r
+ }\r
+ /*\r
+ ** Baa ... What is going on here, i ask myself ... referencing things before i have initialised them ..\r
+ ** -- fixed !!!!\r
+ */\r
+\r
+ pSCI->BMDblBuff = CreateCompatibleBitmap(pSCI->DCBack, pSCI->WindowSize.cx, pSCI->WindowSize.cy);\r
+\r
+ if ((pSCI->BMDblBuff == NULL))\r
+ {\r
+ windebug(WINDEBUG_FORCE,"According to my calculations ... pSCI->BMDblBuff = NULL --Ooops");\r
+ }else{\r
+ windebug(WINDEBUGLEVEL_2,"Created Compatable Bitmap (pSCI->BMDblBuff) from (pSCI->DCBack)");\r
+ } \r
+\r
+ pSCI->OldDblBuff = (HBITMAP)SelectObject(pSCI->DCDblBuff, pSCI->BMDblBuff);\r
+ windebug(WINDEBUGLEVEL_2,"Selected (pSCI->BMDblBuff) into (pSCI->DCDblBuff) -- old value saved to (pSCI->OldDblBuff)");\r
+\r
+ ReleaseDC (hwnd, pSCI->DCBack);\r
+ windebug(WINDEBUGLEVEL_2,"Released (hdc)");\r
+\r
+\r
+\r
+ SetLastError(0);\r
+ \r
+ SetWindowLong (hwnd, GWL_GRAPHDATA, (LONG) pSCI);\r
+ \r
+// windebug(WINDEBUGLEVEL_2,"Saved (pSCI) into (hwnd) offset = GWL_GRAPHDATA, Last error =%u",GetLastError());\r
+// SetTimer (hwnd, GRAPH_EVENT, UPDATE_INTERVAL, NULL);\r
+// windebug(WINDEBUGLEVEL_2,"SetTimer");\r
+\r
+ return 1;\r
+ }\r
+ case WM_ERASEBKGND:\r
+ {\r
+ windebug(WINDEBUGLEVEL_2,"recieved WM_ERASEBKGND");\r
+ }\r
+ return 1;\r
+ case WM_PAINT:\r
+ windebug(WINDEBUGLEVEL_2,"recieved WM_PAINT");\r
+ SetLastError(0);\r
+ {\r
+ PGRAPHINFO pSCI = (PGRAPHINFO) GetWindowLong (hwnd, GWL_GRAPHDATA);\r
+ if (pSCI==NULL)\r
+ {\r
+ windebug(WINDEBUGLEVEL_2,"Error from GetWindowLong ~> %u",GetLastError);\r
+ return FALSE;\r
+ }\r
+ windebug(WINDEBUGLEVEL_2,"got pSCI from GetWindowLong()");\r
+ windebug(WINDEBUGLEVEL_2,"Testing pSCI .... pSCI->BMDblBuff=%d",pSCI->BMDblBuff);\r
+ GetClientRect(hwnd, &r);\r
+ windebug(WINDEBUGLEVEL_2,"got GetClientRect()=&r= r.bottom->%d, r.left->%d, r.right->%d, r.top->%d",r.bottom ,r.left,r.right,r.top);\r
+\r
+ DrawMonitor(pSCI->DCDblBuff, r,hwnd);\r
+ windebug(WINDEBUGLEVEL_2,"DrawMonitor returned");\r
+ mem = BeginPaint(hwnd, &ps);\r
+ BitBlt(mem, 0, 0, pSCI->WindowSize.cx, pSCI->WindowSize.cy, pSCI->DCDblBuff, 0, 0, SRCCOPY);\r
+ EndPaint(hwnd, &ps);\r
+ DeleteDC(mem);\r
+ return 0;\r
+ }\r
+\r
+ case (WM_USER + 1):\r
+ GetClientRect(hwnd, &r);\r
+ InvalidateRect(hwnd, &r, FALSE);\r
+\r
+ case WM_TIMER:\r
+ windebug(WINDEBUGLEVEL_2,"recieved WM_TIMER");\r
+ switch (wParam)\r
+ {\r
+ case GRAPH_EVENT:\r
+ {\r
+ windebug(WINDEBUGLEVEL_2," -> Specifically GRAPH_EVENT");\r
+ {PGRAPHINFO pSCI = (PGRAPHINFO) GetWindowLong (hwnd, GWL_GRAPHDATA);\r
+ if (pSCI == NULL)\r
+ windebug(WINDEBUGLEVEL_2,"Failed retreval of pSCI");\r
+ pSCI->cpuhistory[pSCI->cpupointer] = (rand()%100)/1.5+20/**data*/;\r
+ pSCI->cpupointer++;\r
+ pSCI->cpupointer %= pSCI->width;\r
+ SetWindowLong (hwnd, GWL_GRAPHDATA, (LONG) pSCI);\r
+ // Invalidate client. This causes a WM_PAINT message to be sent to our window\r
+ GetClientRect(hwnd, &r);\r
+ InvalidateRect(hwnd, &r, FALSE);\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+\r
+ case WM_DESTROY:\r
+ {\r
+\r
+ PGRAPHINFO pSCI = (PGRAPHINFO) GetWindowLong (hwnd, GWL_GRAPHDATA);\r
+// KillTimer(hwnd, GRAPH_EVENT);\r
+ hStatsWnd = NULL;\r
+ //New DoubleBuffer Code\r
+ //SelectObject(DCBack, OldBack);\r
+\r
+ if(pSCI->DCBack)\r
+ DeleteDC(pSCI->DCBack);\r
+ if(pSCI->BMBack)\r
+ DeleteObject(pSCI->BMBack);\r
+ //Free our DoubleBuffer Handles\r
+\r
+ if(pSCI->DCDblBuff) {\r
+ SelectObject(pSCI->DCDblBuff, pSCI->OldDblBuff);\r
+ DeleteDC(pSCI->DCDblBuff);\r
+ }\r
+\r
+ pSCI->DCDblBuff = NULL;\r
+\r
+ if(pSCI->BMDblBuff) {\r
+ DeleteObject(pSCI->BMDblBuff);\r
+ }\r
+\r
+ pSCI->BMDblBuff = NULL;\r
+\r
+\r
+ LocalFree (LocalHandle ((LPVOID) pSCI));\r
+ }\r
+ break;\r
+\r
+ default:\r
+ return DefWindowProc(hwnd,msg,wParam,lParam);\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+void DrawMonitor(HDC hdc, RECT r,HWND hwnd)\r
+{\r
+ {\r
+ windebug(WINDEBUGLEVEL_2,"Entering DrawMonitor"); \r
+ }\r
+ {\r
+ PGRAPHINFO pSCI = (PGRAPHINFO) GetWindowLong (hwnd, GWL_GRAPHDATA);\r
+ \r
+\r
+\r
+ int i, j;\r
+ HBRUSH brush;\r
+ HPEN pen, oldpen, dotpen;\r
+ HBITMAP graphmask;\r
+ HDC image, mask;\r
+ int height;\r
+int BorderTop = 0, BorderBottom = 0, BorderLeft= 0,BorderRight=0;\r
+windebug(WINDEBUGLEVEL_2,"Got pSCI from hwnd (=%d)",hwnd);\r
+windebug(WINDEBUGLEVEL_2,"initialised vars");\r
+ // Set border\r
+ r.top += BorderTop;\r
+ r.bottom -= BorderBottom;\r
+ r.left += BorderLeft;\r
+ r.right -= BorderRight;\r
+windebug(WINDEBUGLEVEL_2,"initialised vars -- 1");\r
+ pSCI->width = (r.right - r.left); // Width of graph\r
+ height = (r.bottom - r.top); // Height of graph\r
+windebug(WINDEBUGLEVEL_2,"initialised vars -- 2");\r
+windebug(WINDEBUGLEVEL_2,"pSCI->Background=%d,pSCI->BMBack=%d,pSCI->BMDblBuff=%d,pSCI->BackColor=%d,pSCI->GridColor=%d,pSCI->WindowSize.cx=%d,pSCI->WindowSize.cy=%d,pSCI->cpupointer=%d",pSCI->Background,pSCI->BMBack,pSCI->BMDblBuff,pSCI->BackColor,pSCI->GridColor,pSCI->WindowSize.cx,pSCI->WindowSize.cy,pSCI->cpupointer);\r
+\r
+ // Draw Background\r
+ /*if (Background)\r
+ {\r
+ HDC src = CreateCompatibleDC(NULL);\r
+ SelectObject(src, Background);\r
+ BitBlt(hdc, 0, 0, WindowSize.cx, WindowSize.cy, src, 0, 0, SRCCOPY);\r
+ DeleteObject(src);\r
+ }\r
+ else*/\r
+ {\r
+ brush = CreateSolidBrush(pSCI->BackColor);\r
+ FillRect(hdc, &r, brush);\r
+ DeleteObject(brush);\r
+ }\r
+\r
+ // Draw Grid\r
+ if (pSCI->Grid) {\r
+ pen = CreatePen(PS_SOLID, 1, pSCI->GridColor);\r
+ oldpen = SelectObject(hdc, pen);\r
+\r
+ for (i=1; i<((r.bottom - r.top)%10 + 1); i++) {\r
+ MoveToEx(hdc, r.left, r.top +/* ((r.bottom - r.top) / 10)*/ 10 * i, NULL);\r
+ LineTo(hdc, r.right/*-1*/, r.top + /*((r.bottom - r.top) / 10)*/ 10 * i);\r
+ windebug(WINDEBUGLEVEL_2,"i =%d, pen = %d , oldpen = %d , pSCI->Grid = %d", i,pen,oldpen,pSCI->Grid);\r
+ }\r
+\r
+ for (i=1; i<((r.right-r.left)/10+/*pSCI->cpupointer*/usernumpointer); i++) {\r
+ MoveToEx(hdc, r.left + ((/*(r.right-r.left) / */ 10)*i-(/*pSCI->cpupointer*/usernumpointer)), r.top, NULL);\r
+ LineTo(hdc, r.left + ((/*(r.right-r.left)/ */ 10)*i-(/*pSCI->cpupointer*/usernumpointer)), r.bottom/*-1*/);\r
+ }\r
+\r
+ SelectObject(hdc, oldpen);\r
+ DeleteObject(pen);\r
+ }\r
+windebug(WINDEBUGLEVEL_2,"Drawn Grid");\r
+\r
+/* mask = CreateCompatibleDC(NULL);\r
+\r
+ graphmask = CreateCompatibleBitmap(mask, pSCI->WindowSize.cx, pSCI->WindowSize.cy);\r
+ SelectObject(mask, graphmask);\r
+\r
+ brush = CreateSolidBrush(0x0FFFFFF);\r
+ FillRect(mask, &r, brush);\r
+ DeleteObject(brush);\r
+\r
+ pen = CreatePen(PS_SOLID, 1, 0x0FFFFF);\r
+ SelectObject(mask, pen);\r
+ oldpen = SelectObject(mask, pen);*/\r
+\r
+\r
+ j = (/*pSCI->cpupointer*/ usernumpointer + pSCI->width) % pSCI->width;\r
+ if (usernumhistory/*pSCI->cpuhistory*/[j-1]!= -1){ \r
+ //MoveToEx(mask, r.left, r.bottom-(height * pSCI->cpuhistory[j]/100), NULL);\r
+\r
+ for (i=0; i<pSCI->width; i++)\r
+ {\r
+ j++;\r
+ j %= pSCI->width;\r
+// MoveToEx(mask, r.left+i, r.bottom-(height * pSCI->cpuhistory[j]/100), NULL);\r
+ // LineTo(mask, r.left+i, r.bottom);\r
+//windebug(WINDEBUGLEVEL_2,"j = %d pSCI->width= %d , i= %d , pSCI->cpuhistory[j]=%d pSCI->cpuhistory[j+1]= %d pSCI->cpuhistory[j-1]= %d",j,pSCI->width,i,pSCI->cpuhistory[j],pSCI->cpuhistory[j+1],pSCI->cpuhistory[j-1]);\r
+ if (i==0)\r
+ MoveToEx(hdc, r.left-1, r.bottom-(pSCI->width * usernumhistory/*pSCI->cpuhistory*/[j]/ MAXCLIENTS /*(1+lu_mlu+(lu_mlu*(75/100)))*/), NULL);\r
+ dotpen = CreatePen(PS_SOLID, 0, 0x0000FF00);\r
+ oldpen = SelectObject(hdc, dotpen);\r
+ LineTo(hdc, r.left+i, r.bottom-(pSCI->width * usernumhistory/*pSCI->cpuhistory*/[j]/ MAXCLIENTS/*(1+lu_mlu+(lu_mlu*(75/100)))*/));\r
+ SelectObject(hdc, oldpen);\r
+ DeleteObject(dotpen);\r
+\r
+ }\r
+ }\r
+// SelectObject(mask, oldpen);\r
+// DeleteObject(pen);\r
+\r
+// image = CreateCompatibleDC(NULL);\r
+// SelectObject(image, CPUMap);\r
+\r
+// BitBlt(hdc, BorderLeft, BorderTop,pSCI->width, height, image, BorderLeft, BorderTop, SRCINVERT);\r
+ //BitBlt(hdc, BorderLeft, BorderTop,width, height, mask, BorderLeft, BorderTop, SRCAND);\r
+// BitBlt(hdc, BorderLeft, BorderTop,pSCI->width, height, image, BorderLeft, BorderTop, SRCINVERT);\r
+\r
+ DeleteObject(graphmask);\r
+\r
+// DeleteObject(CPUMap);\r
+\r
+ DeleteDC(mask);\r
+// DeleteDC(image);\r
+ SetWindowLong (hwnd, GWL_GRAPHDATA, (LONG) pSCI);\r
+}\r
+\r
+}\r
+\r
+\r
+/***************************************************************\r
+***************** Debug Code Added 14-02 *********************\r
+***************** Modified 16-02 ********************/\r
+\r
+void windebug(level, form, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)\r
+int level;\r
+char *form, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10;\r
+{\r
+ static char windebugbuf[1024];\r
+ static char windebugbuf2[1024];\r
+ char tmpbuf[128];\r
+ char tmpbuf2[128];\r
+/*\r
+0x0000001 = General Debug\r
+0x0000002 = Graphy Specific Debug\r
+0x0000004 = [undefined]\r
+0x0000008 = [undefined]\r
+0x0000010 = [undefined]\r
+*/\r
+ if (((windebuglevel & level) != 0)||(level & WINDEBUG_FORCE))\r
+ {\r
+ int err = WSAGetLastError();\r
+ (void)sprintf(windebugbuf, form,\r
+ p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);\r
+ _strdate( tmpbuf );\r
+ _strtime( tmpbuf2 );\r
+ (void)sprintf(windebugbuf2, "%s %s::%s", tmpbuf,tmpbuf2,windebugbuf );\r
+\r
+\r
+ strcat(windebugbuf2, "\n");\r
+ fprintf(debugfile,windebugbuf2);\r
+ if (((windebuglevel & WINDEBUGLEVEL_FLUSH) != 0)||(level & WINDEBUG_FORCE))\r
+ fflush(debugfile);\r
+ WSASetLastError(err);\r
+ }\r
+if (0)\r
+ {\r
+SETTEXTEX TextEx;\r
+TextEx.codepage = CP_ACP;\r
+SendMessage(hreditwnd,EM_SETTEXTEX,&TextEx,form);\r
+ }\r
+}\r
+\r
+int SetDebugLevel(HWND hWnd, int NewLevel)\r
+{\r
+ HMENU hMenu = GetMenu(hWnd);\r
+\r
+ if ( !hMenu || !(hMenu = GetSubMenu(hMenu, 1)) ||\r
+ !(hMenu = GetSubMenu(hMenu, 4)) )\r
+ return -1;\r
+\r
+ CheckMenuItem(hMenu, IDM_DBGFATAL+debuglevel,\r
+ MF_BYCOMMAND | MF_UNCHECKED);\r
+ debuglevel = NewLevel;\r
+ CheckMenuItem(hMenu,IDM_DBGFATAL+debuglevel,\r
+ MF_BYCOMMAND | MF_CHECKED);\r
+\r
+ return debuglevel;\r
+}\r
+\r
+/**************************************************************/\r
+int GUI_TextWaiting(char *szInBuf,int iLength)\r
+{\r
+return 0;\r
+}
\ No newline at end of file
--- /dev/null
+//Microsoft Developer Studio generated resource script.\r
+//\r
+#include "resource.h"\r
+\r
+#define APSTUDIO_READONLY_SYMBOLS\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 2 resource.\r
+//\r
+#define APSTUDIO_HIDDEN_SYMBOLS\r
+#include "windows.h"\r
+#undef APSTUDIO_HIDDEN_SYMBOLS\r
+#include "resource.h"\r
+#include "winver.h"\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#undef APSTUDIO_READONLY_SYMBOLS\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// English (U.S.) resources\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r
+#ifdef _WIN32\r
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\r
+#pragma code_page(1252)\r
+#endif //_WIN32\r
+\r
+#ifdef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// TEXTINCLUDE\r
+//\r
+\r
+1 TEXTINCLUDE DISCARDABLE \r
+BEGIN\r
+ "resource.h\0"\r
+END\r
+\r
+2 TEXTINCLUDE DISCARDABLE \r
+BEGIN\r
+ "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"\r
+ "#include ""windows.h""\r\n"\r
+ "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"\r
+ "#include ""resource.h""\r\n"\r
+ "#include ""winver.h""\r\n"\r
+ "\0"\r
+END\r
+\r
+3 TEXTINCLUDE DISCARDABLE \r
+BEGIN\r
+ "\r\n"\r
+ "\0"\r
+END\r
+\r
+#endif // APSTUDIO_INVOKED\r
+\r
+#endif // English (U.S.) resources\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// English (U.K.) resources\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)\r
+#ifdef _WIN32\r
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK\r
+#pragma code_page(1252)\r
+#endif //_WIN32\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Menu\r
+//\r
+\r
+MENU_POPUP MENU DISCARDABLE \r
+BEGIN\r
+ POPUP "popup"\r
+ BEGIN\r
+ POPUP "&System"\r
+ BEGIN\r
+ MENUITEM "Ircd.&Conf", 65535\r
+ MENUITEM "Ircd.&Motd", IDM_IRCDMOTD\r
+ MENUITEM "Ircd.R&ules", IDM_IRCDRULES\r
+ MENUITEM SEPARATOR\r
+ MENUITEM "&Rehash", IDM_REHASH\r
+ END\r
+ END\r
+ POPUP """popup"""\r
+ BEGIN\r
+ POPUP "&System"\r
+ BEGIN\r
+ MENUITEM "Ircd.&Conf", 65535\r
+ MENUITEM "Ircd.&Motd", IDM_IRCDMOTD\r
+ MENUITEM "Ircd.R&ules", IDM_IRCDRULES\r
+ MENUITEM SEPARATOR\r
+ MENUITEM "&Rehash", IDM_REHASH\r
+ END\r
+ END\r
+ POPUP "system"\r
+ BEGIN\r
+ MENUITEM "Ircd.&Conf", 65535\r
+ MENUITEM "Ircd.&Motd", IDM_IRCDMOTD\r
+ MENUITEM "Ircd.R&ules", IDM_IRCDRULES\r
+ MENUITEM SEPARATOR\r
+ MENUITEM "&Rehash", IDM_REHASH\r
+ POPUP "Debug Level"\r
+ BEGIN\r
+ MENUITEM "&Off", IDM_DBGOFF\r
+ MENUITEM "&Fatal", IDM_DBGFATAL\r
+ MENUITEM "&Error", IDM_DBGERROR\r
+ MENUITEM "&Notice", IDM_DBGNOTICE\r
+ MENUITEM "&DNS", IDM_DBGDNS\r
+ MENUITEM "&Info", IDM_DBGINFO\r
+ MENUITEM "N&umerics", IDM_DBGNUM\r
+ MENUITEM "&Send", IDM_DBGSEND\r
+ MENUITEM "&Debug", IDM_DBGDEBUG\r
+ MENUITEM "&Malloc", IDM_DBGMALLOC\r
+ MENUITEM "&List", IDM_DBGLIST\r
+ END\r
+ POPUP "WinDebugLevel"\r
+ BEGIN\r
+ MENUITEM "1 - Application General", MM_WINDEBUGLEVEL_0\r
+ MENUITEM "2 - Flow Debug", MM_WINDEBUGLEVEL_1\r
+ MENUITEM "3 - Extreeme Deatail", MM_WINDEBUGLEVEL_2\r
+ MENUITEM SEPARATOR\r
+ MENUITEM "Flush Every WinDebug()", MM_WINDEBUGLEVEL_FLUSH\r
+ END\r
+ END\r
+ POPUP "help"\r
+ BEGIN\r
+ MENUITEM "&Credits...", IDM_CREDITS\r
+ MENUITEM "&Dreamforge Credits...", IDM_DF\r
+ MENUITEM "&License...", IDM_LICENSE\r
+ MENUITEM "&About UnrealIRCD/32...", IDM_ABOUT\r
+ END\r
+END\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Dialog\r
+//\r
+\r
+DLG_IRCDCONF DIALOG DISCARDABLE 0, 0, 294, 159\r
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU\r
+CAPTION "UnrealIRCd Setup"\r
+FONT 9, "MS Sans Serif"\r
+BEGIN\r
+ DEFPUSHBUTTON "&Save",IDOK,3,143,50,14\r
+ PUSHBUTTON "&Cancel",IDCANCEL,241,143,50,14\r
+ EDITTEXT IDC_IRCDCONF,0,0,294,140,ES_MULTILINE | ES_AUTOVSCROLL | \r
+ ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL | WS_HSCROLL\r
+END\r
+\r
+DLG_IRCDRULES DIALOG DISCARDABLE 0, 0, 294, 159\r
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU\r
+CAPTION "UnrealIRCd Setup"\r
+FONT 9, "MS Sans Serif"\r
+BEGIN\r
+ DEFPUSHBUTTON "&Save",IDOK,3,143,50,14\r
+ PUSHBUTTON "&Cancel",IDCANCEL,241,143,50,14\r
+ EDITTEXT IDC_IRCDCONF,0,0,294,140,ES_MULTILINE | ES_AUTOVSCROLL | \r
+ ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL | WS_HSCROLL\r
+END\r
+\r
+DLG_IRCDMOTD DIALOG DISCARDABLE 0, 0, 294, 159\r
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU\r
+CAPTION "UnrealIRCd Setup"\r
+FONT 9, "MS Sans Serif"\r
+BEGIN\r
+ DEFPUSHBUTTON "&Save",IDOK,3,143,50,14\r
+ PUSHBUTTON "&Cancel",IDCANCEL,241,143,50,14\r
+ EDITTEXT IDC_IRCDCONF,0,0,294,140,ES_MULTILINE | ES_AUTOVSCROLL | \r
+ ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL | WS_HSCROLL\r
+END\r
+\r
+WIRCD DIALOG DISCARDABLE 0, 0, 240, 130\r
+STYLE DS_ABSALIGN | DS_MODALFRAME | DS_3DLOOK | DS_NOFAILCREATE | \r
+ WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU\r
+CAPTION "Unreal IRCD/32"\r
+FONT 8, "MS Sans Serif"\r
+BEGIN\r
+ CTEXT "Ported by Stskeeps <stskeeps@tspre.org> - http://unreal.tspre.org",\r
+ TXT_PORT,7,120,225,10\r
+ CONTROL "OBM_wIRCD",IDC_STATIC,"Static",SS_BITMAP,7,7,225,97\r
+ CONTROL "OBM_bar",IDC_STATIC,"Static",SS_BITMAP,7,105,225,14\r
+END\r
+\r
+WIRCDSTATUS DIALOG DISCARDABLE 0, 0, 400, 164\r
+STYLE DS_ABSALIGN | DS_MODALFRAME | DS_3DLOOK | DS_NOFAILCREATE | \r
+ DS_CENTERMOUSE | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | \r
+ WS_SYSMENU\r
+CAPTION "IRCd Status"\r
+FONT 8, "MS Sans Serif"\r
+BEGIN\r
+ CONTROL "",IDC_STATIC,"Static",SS_BLACKFRAME,230,5,168,97\r
+ LTEXT "Current Local Users:",TXT_LOCALUSERS,232,7,118,10\r
+ EDITTEXT EDIT_CLOCAL,310,7,30,10,ES_READONLY\r
+ LTEXT "Max:",TXT_LOCALMAX,345,7,30,10\r
+ EDITTEXT EDIT_CLOCALMAX,365,7,30,10,ES_READONLY\r
+ LTEXT "Current Global Users:",TXT_GLOBALUSERS,232,17,118,10\r
+ EDITTEXT EDIT_GLOBAL,310,17,30,10,ES_READONLY\r
+ LTEXT "Max:",TXT_GLOBALMAX,345,17,30,10\r
+ EDITTEXT EDIT_GLOBALMAX,365,17,30,10,ES_READONLY\r
+ LTEXT "Users:",TXT_NONINV,232,27,118,10\r
+ EDITTEXT EDIT_NONINV,310,27,30,10,ES_READONLY\r
+ LTEXT "Inv:",TXT_INV,345,27,30,10\r
+ EDITTEXT EDIT_INV,365,27,30,10,ES_READONLY\r
+ LTEXT "IRC servers networked:",TXT_IRCSERVERS,232,37,118,10\r
+ EDITTEXT EDIT_IRCSERVERS,310,37,30,10,ES_READONLY\r
+ LTEXT "IRC operator(s) online:",TXT_IRCOPS,232,47,118,10\r
+ EDITTEXT EDIT_IRCOPS,310,47,30,10,ES_READONLY\r
+ LTEXT "Local clients",TXT_MYUSERS,232,57,118,10\r
+ EDITTEXT EDIT_MYUSERS,310,57,30,10,ES_READONLY\r
+ LTEXT "Local server links",TXT_MYSERVERS,232,67,118,10\r
+ EDITTEXT EDIT_MYSERVERS,310,67,30,10,ES_READONLY\r
+ LTEXT "Channels formed",TXT_CHANNELS,232,77,118,10\r
+ EDITTEXT EDIT_CHANNELS,310,77,30,10,ES_READONLY\r
+ CTEXT "Report from dd/mm/yy hh:dd",TXT_WHEN,260,87,120,10\r
+ LTEXT "[ UnrealIRCd/32 v2.1.7 ] - Release *",TXT_VERSION,7,104,\r
+ 350,10\r
+ LTEXT "UnrealIRCd/32 GUI is (C) Stskeeps <stskeeps@tspre.org> and {X} <djhype@home.com>",\r
+ TXT_CRINFO,7,114,350,10\r
+ LTEXT "UnrealIRCd logo (C) zero9000 (Kevin Alford)",\r
+ TXT_CRINFO1,7,124,350,10\r
+ LTEXT "Copying/Ripping this GUI for other wIRCds is NOT allowed unless permission is gained by the authors",\r
+ TXT_CRINFO2,7,134,350,10\r
+ LTEXT "The source is placed under the GPL but the look-n-feel may not be copied",\r
+ TXT_CRINFO3,7,144,350,10\r
+ LTEXT "- contact stskeeps@tspre.org for more information",TXT_CRINFO4,7,\r
+ 154,350,10\r
+ CONTROL "OBM_wIRCD",IDC_STATIC,"Static",SS_BITMAP,7,5,225,97\r
+END\r
+\r
+WIRCDABOUT DIALOG DISCARDABLE 0, 0, 400, 164\r
+STYLE DS_ABSALIGN | DS_MODALFRAME | DS_3DLOOK | DS_NOFAILCREATE | \r
+ DS_CENTERMOUSE | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | \r
+ WS_SYSMENU\r
+CAPTION "About UnrealIRCd/32"\r
+FONT 8, "MS Sans Serif"\r
+BEGIN\r
+END\r
+\r
+DLG_STATS DIALOGEX 0, 0, 359, 263\r
+STYLE DS_ABSALIGN | DS_MODALFRAME | DS_3DLOOK | DS_NOFAILCREATE | WS_POPUP | \r
+ WS_VISIBLE | WS_CAPTION | WS_SYSMENU\r
+EXSTYLE WS_EX_TOOLWINDOW\r
+CAPTION "Unreal 3.0 Configuration"\r
+FONT 8, "MS Sans Serif"\r
+BEGIN\r
+ LTEXT "Current Local Users:",TXT_LOCALUSERS,110,5,65,8\r
+ LTEXT "Max:",TXT_LOCALMAX,224,5,16,8\r
+ LTEXT "Current Global Users:",TXT_GLOBALUSERS,115,100,68,8\r
+ LTEXT "Max:",TXT_GLOBALMAX,224,100,16,8\r
+ LTEXT "Inv:",TXT_INV,280,5,13,8\r
+ LTEXT "IRC servers networked:",TXT_IRCSERVERS,110,15,75,8\r
+ LTEXT "IRC operator(s) online:",TXT_IRCOPS,115,110,71,8\r
+ LTEXT "Local clients",TXT_MYUSERS,110,25,40,8\r
+ LTEXT "Local server links",TXT_MYSERVERS,110,34,56,8\r
+ LTEXT "Channels formed:",TXT_CHANNELS,115,120,56,8\r
+ GROUPBOX "Global",IDC_STATIC,110,90,175,55\r
+ RTEXT "",EDIT_GLOBALMAX,245,100,25,8,SS_SUNKEN\r
+ RTEXT "",EDIT_GLOBAL,190,100,25,8,SS_SUNKEN\r
+ RTEXT "",EDIT_CHANNELS,190,120,25,8,SS_SUNKEN\r
+ RTEXT "",EDIT_IRCOPS,190,110,25,8,SS_SUNKEN\r
+ RTEXT "",EDIT_CLOCAL,190,5,25,8,SS_SUNKEN\r
+ RTEXT "",EDIT_CLOCALMAX,245,5,25,8,SS_SUNKEN\r
+ RTEXT "",EDIT_INV,301,5,25,8,SS_SUNKEN\r
+ RTEXT "",EDIT_IRCSERVERS,190,15,25,8,SS_SUNKEN\r
+ RTEXT "",EDIT_MYUSERS,190,25,25,8,SS_SUNKEN\r
+ RTEXT "",EDIT_MYSERVERS,190,34,25,8,SS_SUNKEN\r
+ LTEXT "Maximum Possible users",TXT_LOCALMAXPOS,223,15,77,8\r
+ RTEXT "",EDIT_LOCALMAXPOS,301,16,25,8,SS_SUNKEN\r
+END\r
+\r
+ABOUTBOX DIALOG DISCARDABLE 0, 0, 294, 159\r
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU\r
+CAPTION "UnrealIRCd About Stuff"\r
+FONT 9, "Lucida Console"\r
+BEGIN\r
+ DEFPUSHBUTTON "&OK",IDOK,122,143,50,14\r
+ EDITTEXT IDC_INFOTEXT,0,0,294,140,ES_MULTILINE | ES_AUTOVSCROLL | \r
+ ES_AUTOHSCROLL | ES_READONLY | ES_WANTRETURN | \r
+ WS_VSCROLL\r
+END\r
+\r
+\r
+#ifndef _MAC\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Version\r
+//\r
+\r
+1 VERSIONINFO\r
+ FILEVERSION 3,0,4,2\r
+ PRODUCTVERSION 3,0,0,0\r
+ FILEFLAGSMASK 0x3fL\r
+#ifdef _DEBUG\r
+ FILEFLAGS 0x29L\r
+#else\r
+ FILEFLAGS 0x28L\r
+#endif\r
+ FILEOS 0x4L\r
+ FILETYPE 0x1L\r
+ FILESUBTYPE 0x0L\r
+BEGIN\r
+ BLOCK "StringFileInfo"\r
+ BEGIN\r
+ BLOCK "080904b0"\r
+ BEGIN\r
+ VALUE "Comments", "Its for windows ->.. dont expect it to be stable :->\0"\r
+ VALUE "CompanyName", "UnrealIRCD\0"\r
+ VALUE "FileDescription", "The Unreal Chat Server for Windows\0"\r
+ VALUE "FileVersion", "3.0.04.02\0"\r
+ VALUE "InternalName", "Unreal-win32\0"\r
+ VALUE "LegalCopyright", "Copyright © 2000 Unreal Developer Network\0"\r
+ VALUE "LegalTrademarks", "All rights reserved\0"\r
+ VALUE "OriginalFilename", "wircd.exe\0"\r
+ VALUE "PrivateBuild", "3.0.04.02\0"\r
+ VALUE "ProductName", "The Unreal Chat Server for Windows\0"\r
+ VALUE "ProductVersion", "3.0 Release\0"\r
+ VALUE "SpecialBuild", "For Windows\0"\r
+ END\r
+ END\r
+ BLOCK "VarFileInfo"\r
+ BEGIN\r
+ VALUE "Translation", 0x809, 1200\r
+ END\r
+END\r
+\r
+#endif // !_MAC\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// DESIGNINFO\r
+//\r
+\r
+#ifdef APSTUDIO_INVOKED\r
+GUIDELINES DESIGNINFO DISCARDABLE \r
+BEGIN\r
+ "DLG_IRCDCONF", DIALOG\r
+ BEGIN\r
+ LEFTMARGIN, 7\r
+ RIGHTMARGIN, 287\r
+ TOPMARGIN, 7\r
+ BOTTOMMARGIN, 152\r
+ END\r
+\r
+ "WIRCD", DIALOG\r
+ BEGIN\r
+ LEFTMARGIN, 7\r
+ RIGHTMARGIN, 233\r
+ TOPMARGIN, 7\r
+ BOTTOMMARGIN, 119\r
+ END\r
+\r
+ "DLG_STATS", DIALOG\r
+ BEGIN\r
+ LEFTMARGIN, 7\r
+ RIGHTMARGIN, 352\r
+ TOPMARGIN, 7\r
+ BOTTOMMARGIN, 256\r
+ END\r
+\r
+ "ABOUTBOX", DIALOG\r
+ BEGIN\r
+ LEFTMARGIN, 7\r
+ RIGHTMARGIN, 287\r
+ TOPMARGIN, 7\r
+ BOTTOMMARGIN, 152\r
+ END\r
+END\r
+#endif // APSTUDIO_INVOKED\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Icon\r
+//\r
+\r
+// Icon with lowest ID value placed first to ensure application icon\r
+// remains consistent on all systems.\r
+sysicon ICON DISCARDABLE "ico00001.ico"\r
+WIRCD ICON DISCARDABLE "icon1.ico"\r
+sysicondisabled ICON DISCARDABLE "sysicon1.ico"\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Bitmap\r
+//\r
+\r
+OBM_WIRCD BITMAP DISCARDABLE "unrealircd.bmp"\r
+OBM_BAR BITMAP DISCARDABLE "bar.bmp"\r
+#endif // English (U.K.) resources\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+\r
+#ifndef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 3 resource.\r
+//\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#endif // not APSTUDIO_INVOKED\r
+\r
--- /dev/null
+typedef struct {\r
+ unsigned int CurrLoclUsers;\r
+ unsigned int CurrGlobUsers;\r
+ unsigned int MaxLoclUsers;\r
+ unsigned int MaxGlobUsers;\r
+ unsigned int NumUsers; // Eh ??\r
+ unsigned int Invisible;\r
+ unsigned int connections;\r
+ unsigned int NumIRCops;\r
+ unsigned int LocalClients; // Eh??\r
+ unsigned int LocalServers;\r
+ unsigned int chans;\r
+ unsigned int Servers;\r
+\r
+ /* ToBe Added\r
+ int TSsync stuff .... dont know what yet\r
+ */\r
+} WINSTATS, *pWINSTATS;\r
+\r
+typedef struct RichLine\r
+{\r
+ BYTE *Data;\r
+ WORD Len;\r
+ struct RichLine *Prev, *Next;\r
+} aRichLine;\r
+\r
+typedef struct AllRichLines\r
+ {\r
+ aRichLine *First, *Current;\r
+ int NumLines;\r
+ } INFRICHLINE;\r
+\r
+\r
+\r
+/**********************************************************\r
+********** Graphy Header (C) David Flynn 2000 ************/\r
+\r
+#define SS_NORM 0x0001 // spincube window styles\r
+#define SS_SLOW 0x0002\r
+#define SS_FAST 0x0003\r
+\r
+#define CCHSTYLE 20 // size of style string, i.e. "SS_ERASE"\r
+\r
+#define NUM_GRAPH_STYLES 2\r
+\r
+\r
+#define GRAPH_EXTRA 4 // number of extra bytes for spincube class\r
+\r
+\r
+#define IDS_REGCLASSFAIL 16\r
+#define IDS_UNREGFAIL 17\r
+#define IDS_DLGBOXFAIL 18\r
+#define IDS_ALLOCFAIL 19\r
+#define IDS_CREATEDCFAIL 20\r
+#define IDS_CREATEBITMAPFAIL 21\r
+#define GWL_GRAPHDATA 0 \r
+// offset of control's instance data\r
+\r
+#define GRAPHCLASS "Graph"\r
+#define GRAPHDESCRIPTION "An animated control"\r
+#define GRAPHDEFAULTTEXT ":-)"\r
+#define GRAPH_EVENT 1\r
+#define UPDATE_TIMER 2\r
+#define UPDATE_INTERVAL /*60000*/ 30\r
+\r
+typedef struct\r
+{\r
+ HDC hdcCompat; // the DC that will contain our off-screen\r
+ // image\r
+ //HBITMAP hbmSave; // Save previous selected bitmap\r
+ //HBITMAP hbmCompat; // The bitmap that will contain the actual\r
+ // image, i.e. we will always do our\r
+ // drawing on this bmp & then blt the\r
+ // result to the screen.\r
+ BOOL InitDraw; //Did we draw once yet?\r
+ int width; // Width of monitor (= size of history)\r
+ int cpupointer; // pointer to cpu history\r
+\r
+ HDC DCBack;\r
+ HBITMAP BMBack;\r
+ HBITMAP OldBack;\r
+ HDC DCDblBuff;\r
+ HBITMAP BMDblBuff;\r
+ HBITMAP OldDblBuff;\r
+\r
+ HBITMAP Background;\r
+ HBITMAP CPUMap;\r
+ SIZE WindowSize;\r
+ BOOL Border;\r
+ BOOL Grid;\r
+\r
+ COLORREF BorderColor;\r
+ COLORREF BackColor;\r
+ COLORREF GridColor;\r
+ COLORREF CPUColor;\r
+ COLORREF AVGCPUColor;\r
+ COLORREF MEMColor;\r
+ char cpuhistory[2048];\r
+ char BackgroundPath[256];\r
+char CPUMapPath[256];\r
+ int iOptions; // Contains the current options for this\r
+ // ctrl, i.e. erase background.\r
+\r
+} GRAPHINFO, *PGRAPHINFO;\r
+\r
+\r
+\r
+/******************************************************************************\\r
+* FUNCTION PROTOTYPES\r
+\******************************************************************************/\r
+\r
+LRESULT CALLBACK GraphWndProc (HWND, UINT, WPARAM, LPARAM);\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+DWORD Reserved,dataType,dataLen=8192;\r
+\r
+\r
+\r
+// DoubleBuffer Stuff\r
+void DrawMonitor(HDC hdc, RECT r,HWND);\r
+\r
+\r
+void CreateDblBuff(HWND);\r
+void FreeDblBuff(void);\r
--- /dev/null
+//{{NO_DEPENDENCIES}}\r
+// Microsoft Developer Studio generated include file.\r
+// Used by Win32GUI.rc\r
+//\r
+#define sysicon 114\r
+#define sysicondisabled 115\r
+#define IDC_USERID 1051\r
+#define IDC_REALNAME 1052\r
+#define IDC_PNICK 1053\r
+#define IDC_ANICK 1054\r
+#define IDC_SERVERLIST 1057\r
+#define IDC_NEWSERVER 1058\r
+#define IDC_EDITSERVER 1059\r
+#define IDC_IRCDCONF 1059\r
+#define IDC_DELSERVER 1060\r
+#define IDC_SHOW_GLOBOPS 1060\r
+#define IDC_SHOW_WALLOPS 1061\r
+#define IDC_SHOW_HELPOPS 1062\r
+#define IDC_SHOW_SERVNOTICE 1063\r
+#define IDC_INFOTEXT 1063\r
+#define IDC_INFOTEXT2 1063\r
+#define IDOK2 1065\r
+#define IDC_RICHEDIT1 1070\r
+#define TXT_LOCALUSERS 1100\r
+#define TXT_LOCALMAX 1101\r
+#define TXT_GLOBALUSERS 1102\r
+#define TXT_GLOBALMAX 1103\r
+#define TXT_IRCSERVERS 1104\r
+#define TXT_IRCOPS 1105\r
+#define TXT_NONINV 1106\r
+#define TXT_LOCALMAXPOS 1106\r
+#define TXT_INV 1107\r
+#define TXT_MYUSERS 1108\r
+#define TXT_MYSERVERS 1109\r
+#define TXT_CHANNELS 1110\r
+#define TXT_WHEN 1111\r
+#define TXT_VERSION 1112\r
+#define TXT_PORT 1200\r
+#define TXT_CRINFO 1301\r
+#define TXT_CRINFO1 1302\r
+#define TXT_CRINFO2 1303\r
+#define TXT_CRINFO3 1304\r
+#define TXT_CRINFO4 1305\r
+#define EDIT_CLOCAL 1400\r
+#define EDIT_CLOCALMAX 1401\r
+#define EDIT_GLOBAL 1402\r
+#define EDIT_GLOBALMAX 1403\r
+#define EDIT_IRCSERVERS 1404\r
+#define EDIT_IRCOPS 1405\r
+#define EDIT_NONINV 1406\r
+#define EDIT_LOCALMAXPOS 1406\r
+#define EDIT_INV 1407\r
+#define EDIT_MYUSERS 1408\r
+#define EDIT_MYSERVERS 1409\r
+#define EDIT_CHANNELS 1410\r
+#define IDM_OPEN 40001\r
+#define IDM_SAVE 40002\r
+#define IDM_SAVEAS 40003\r
+#define IDM_EXIT 40004\r
+#define IDM_ABOUT 40005\r
+#define IDM_WINDOWCHILD 40006\r
+#define IDM_REHASH 40007\r
+#define IDM_OPTIONS 40008\r
+#define IDM_CREDITS 40009\r
+#define IDM_DF 40010\r
+#define IDM_LICENSE 40011\r
+#define MM_WINDEBUGLEVEL_0 40016\r
+#define MM_WINDEBUGLEVEL_1 40017\r
+#define MM_WINDEBUGLEVEL_2 40018\r
+#define MM_WINDEBUGLEVEL_FLUSH 40019\r
+#define IDM_DBGOFF 41099\r
+#define IDM_DBGFATAL 41100\r
+#define IDM_DBGERROR 41101\r
+#define IDM_DBGNOTICE 41103\r
+#define IDM_DBGDNS 41104\r
+#define IDM_DBGINFO 41105\r
+#define IDM_DBGNUM 41106\r
+#define IDM_DBGSEND 41107\r
+#define IDM_DBGDEBUG 41108\r
+#define IDM_DBGMALLOC 41109\r
+#define IDM_DBGLIST 41110\r
+#define IDM_POPUP 50000\r
+#define IDM_IRCDRULES 65530\r
+#define IDM_IRCDMOTD 65531\r
+#define IDC_VERSION 65532\r
+#define IDC_VERSION2 65532\r
+#define IDC_STATIC -1\r
+#define IDM_SETUP 65535\r
+#define IDM_IRCDCONF 65535\r
+\r
+// Next default values for new objects\r
+// \r
+#ifdef APSTUDIO_INVOKED\r
+#ifndef APSTUDIO_READONLY_SYMBOLS\r
+#define _APS_NO_MFC 1\r
+#define _APS_NEXT_RESOURCE_VALUE 115\r
+#define _APS_NEXT_COMMAND_VALUE 40020\r
+#define _APS_NEXT_CONTROL_VALUE 1072\r
+#define _APS_NEXT_SYMED_VALUE 104\r
+#endif\r
+#endif\r
--- /dev/null
+/*
+ * IRC - Internet Relay Chat, ircd/version.c
+ * Copyright (C) 1990 Chelsea Ashley Dyerman
+ *
+ * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * : version.c.SH,v 1.8 2000/02/27 11:53:16 stskeeps Exp $
+ */
+
+/*
+ * This file is generated by version.c.SH. Any changes made will go away.
+ */
+
+#include "struct.h"
+#include "version.h"
+#include "license.h"
+
+char *generation = "1";
+char *creation = "Sun Feb 27 2000 at 11:55:29 GMT";
+#define IRCDTOTALVERSION BASE_VERSION PATCH1 PATCH2 PATCH3 PATCH4 PATCH5 PATCH6 PATCH7 PATCH8 PATCH9
+char *version = IRCDTOTALVERSION;
+
+/* moved to s_serv.c */
+char *infotext[] =
+{ 0 };
+
+char *unrealcredits[] =
+{
+ "-=-=-=-=-=-=-=-=-=-= [ " IRCDTOTALVERSION " Credits ] -=-=-=-=-",
+ "The people on this list is people who have helped up through",
+ "the development of UnrealIRCd. The Unreal Team would like to thank",
+ "those people by listing them here:",
+ "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=",
+ " \2\37The UnrealIRCd Team would like to thank:\2\37",
+ "Nutcais (Phil Hawkins)",
+ "- the original shell for Unreal development, useful comments,",
+ " being a real IRCbrother for me (Stskeeps) :), learning me a lot",
+ " about IRC stuff, getting me more and more into IRCd business",
+ " thanks for the *.tspre.org domain as well :)",
+ "",
+ "\37Local Irelands (http://www.local.ie)\37",
+ "- Thanks for sponsoring UnrealIRCd, test facilities,",
+ " supporting UnrealIRCd, many new ideas, thanks for making",
+ " Unreal what it is today:)",
+ "Mick and Sp^",
+ "- Amiga port of Unreal (UnrealIRCd/Amiga), continually strange",
+ " comments on #UnrealIRCd, being great supporters of Unreal",
+ " and following Unreal development all the way",
+ "DrBin (Dave) drbin@tspre.org",
+ "- Recoded & made the new UnrealIRCd/32 code, support,"
+ " finding bugs, and tonnes of other stuff:)",
+ "{X} (Laurie) x@tspre.org",
+ "- Making the main code/design of UnrealIRCd/32 gui",
+ " bugfounds, etc",
+ "SourceForge.net",
+ "- Good hosting, CVS hosting, FTP etc etc:) - thanks for",
+ " supporting opensource projects",
+ "",
+ " \37Donations to Unreal:\37",
+ "BlueFlame^",
+ " - the first UnrealIRCd donation :)",
+ " (yes your name can be here too;)",
+ "",
+ " \37These people have helped alpha/betatesting\37",
+ "zshack, Headbang, Mick, Sp^, WonderWal, bomb, BullFrog, JacobD,",
+ "SirDeath, l33, EiniD, uo, RevPsych and the subgenius.net network,",
+ "^RavenX^, Mich[a]el, {X}, Fish, Shmad, Killer, BrainSCAN, RevNull,",
+ "GoNiS (irc.coreplex.org), Mikey, DrBin, and others",
+ "",
+ "",
+ " \2\37Stskeeps would like to thank:\2\37",
+ "Morrigan Julie Frederiksen",
+ " - Being a friend, thinking I was cute, uhm laying on a recycle",
+ " thing.. 'Its the wrong recycle box Julie!', 'you got too cold",
+ " hands *freezing*', etc ;)",
+ "DJBoxy *unknown* *unknown*",
+ " - For getting me up from #wIRCd bringing me to Mp3fansNet and",
+ " after we linked to Global-IRC.net - and made people choose me",
+ " as netadmin/ircd coder - Thanx!",
+ "TC Tabita Clausen (reallife)",
+ " - Making me smile of my life, talking with me, being a friend",
+ " always got a pen sharpener when needed=/, accepting some",
+ " wierdnesses from my side, going to the cinema with me",
+ " and many other stuff. You'll always be in my heart,",
+ " sorry for all the things I did or maybe didn't",
+ " love you :(",
+ "KUFO John MacKenzie",
+ " - Support, helping me always with getting through my life",
+ " shells, etc etc ;)",
+ "Sporty_McFly Cedric",
+ " - Comments, helping me when I got problems with my life and so on",
+ " *toh* to him - Thanks!",
+ "Del_Monte K. Hawkes k.hawkes@zombies.force9.net",
+ " - Is just trying to put the lamer side of things across :cP",
+ " No. I saw 2 moos. - Well having to input in seconds",
+ " is fine if you're real quick at maths - but if not - it's a PAIN",
+ " - Comments, bugfixes, moral support etc.;)",
+ "Skywalker Chris Morley skywalker@irc.ru.ac.za",
+ " - Helping me start up ROXnet at first (which brought me",
+ " into IRCd business.. + Numerous kicks /Kills akills and alike;)",
+ "zero9000 Kevin Alford",
+ " - UnrealIRCd logo, graphics, null desu ;), ideas etc.",
+ " \2\37codemastr would like to thank:\2\37",
+ "",
+ " \2\37Also thanks to:\2\37",
+ "Enforcer, Andy Church, Mick, Sp^, ShadowMastr, Almaris",
+ "}{, Erik/Dr|zzt, Hedge, Kyle, MissKel, jfc, Fish, kore, Syndicate, Bagge,",
+ "#Coder-Com@Undernet, ^NeVeR^, flygirl^, DannyM, JuliuZ, wah-wah^, Lisa,",
+ "Melisa, NonMortal, Andryan, TomaHawk, Lushes, Skywalker, Merlin, Sporty_McFly,",
+ "zero9000, #wIRCd@DALnet, comstud, dog3, Dianora, Isomer, and others who arent listed here:)",
+ "",
+ "------------------------------------------------------",
+ "Unreal 3.0 and up is dedicated to Morrigan - Julie Frederiksen",
+ "- a girl who have helped me through anything in my life, hugging",
+ "me at the right times, a definate dedication. Thanks for the kisses",
+ "long phonetalks, waste of my mobilephone ;), crying together",
+ "and making life go on for us both. I will never forget you",
+ "never leave you, love ya forever",
+ "------------------------------------------------------",
+ "This IRCd is dedicated to the love that has always been",
+ "and will always be there - Thanks to the girls & friends that kept me up",
+ "when I was down",
+ 0
+};
+char *unrealcreditsold[] =
+{
+ "------------------------------------------------------",
+ "Unreal 3.0 and up is dedicated to Morrigan - Julie Frederiksen",
+ "- a girl who have helped me through anything in my life, hugging",
+ "me at the right times, a definate dedication. Thanks for the kisses",
+ "long phonetalks, waste of my mobilephone ;), crying together",
+ "and making life go on for us both. I will never forget you",
+ "never leave you, love ya forever",
+ "------------------------------------------------------",
+ "This IRCd is dedicated to the love that has always been",
+ "and will always be there - Thanks to the girls & friends that kept me up",
+ "when I was down",
+ 0
+};
+
+char *dalinfotext[] =
+ {
+ "IRC --",
+ "Based on the original code written by Jarkko Oikarinen",
+ "Copyright 1988, 1989, 1990, 1991 University of Oulu, Computing Center",
+ "",
+ "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 1, or",
+ "(at your option) any later version.",
+ "- Any name/comment should never be changed except by the one who made it -",
+ "",
+ "UnrealIRCd contains code developed by:",
+ "Potvin Chris Wolkowski potvin@acestar.org",
+ "RogerY Roger Y. rogery@austnet.org",
+ "GZ gz@starchat.net",
+ "binary",
+ "",
+ "",
+ "The following people have helped in making the DALnet ircd",
+ "that is based on irc2.8.21.mu3.2 :",
+ "",
+ "Russell Russell Miller russell@dal.net",
+ "Donwulff Jukka Santala donwulff@dal.net",
+ "Aetobatus Michael Sawyer aetobatus@dal.net",
+ "Dalvenjah Sven Nielsen dalvenjah@dal.net",
+ "Skandranon Michael Graff explorer@flame.org",
+ "Barubary - barubary@dal.net",
+ "white_dragon Chip Norkus wd@dal.net",
+ "DuffJ Dafydd James duffj@dal.net",
+ "taz David Kopstain taz@dal.net",
+ "NikB Nik Bougalis nikb@dal.net",
+ "Rakarra - rakarra@dal.net",
+ "DarkRot Lucas Madar darkrot@dal.net",
+ "Studded - studded@dal.net",
+ "JoelKatz David Schwartz joelkatz@dal.net",
+ "",
+ "This product includes software developed by Colin Plumb.",
+ "",
+ "The following persons have made many changes and enhancements to the",
+ "code and still know how IRC really works if you have questions about it:",
+ "",
+ "Run Carlo Kid carlo@runaway.xs4all.nl",
+ "Avalon Darren Reed avalon@coombs.anu.edu.au",
+ "msa Markku Savela Markku.Savela@vtt.fi",
+ "Wumpus Greg Lindahl gl8f@virginia.edu",
+ "WiZ Jarkko Oikarinen jto@tolsun.oulu.fi",
+ "Argv Armin Gruner Armin.Gruner@Informatik.TU-Muenchen.de",
+ "",
+ "Thanks to the following people for help with preparing 2.8",
+ "",
+ "phone Matthew Green phone@coombs.anu.edu.au",
+ "Sodapop Chuck Kane ckane@ece.uiuc.edu",
+ "Skygod Matt Lyle matt@oc.com",
+ "Vesa Vesa Ruokonen ruokonen@lut.fi",
+ "Nap Nicolas PIOCH pioch@poly.polytechnique.fr",
+ "",
+ "Those who helped in prior versions and continue to be helpful:",
+ "",
+ "Stellan Klebom Dan Goodwin Mike Bolotski",
+ "Ian Frechette Markku Jarvinen Kimmo Suominen",
+ "Jeff Trim Vijay Subramaniam Karl Kleinpaste",
+ "Bill Wisner Tom Davis Hugo Calendar",
+ "Tom Hopkins Stephen van den Berg",
+ "Bo Adler Michael Sandrof Jon Solomon",
+ "Jan Peterson Helen Rose Paul Graham",
+ "",
+ "Thanks also goes to those persons not mentioned here who have added",
+ "their advice, opinions, and code to IRC.",
+ "Thanks also to those who provide the kind sys admins who let me and",
+ "others continue to develop IRC.",
+ "",
+
+ 0
+ };
--- /dev/null
+################################
+####### Virtual IP Help ########
+################################
+
+It's very simple to setup a virtual ip with this ircd.
+In your ircd.conf your M:line should be:
+M:Servername.com:Virtual-IP:Server Info:6667
+example:
+M:IRC.SERVER.COM:206.163.45.108:IRC Server:6667
+
+Also in ircd.conf, add P:lines like: P:Virtual-IP:*:*:Port
+example:
+P:206.163.211.108:*:*:6668
+
+[ $Id$ ]
--- /dev/null
+To do win32 compiling
+- Copy include/win32/setup.h to include/
+- Copy makefile.win32 to Makefile
+- Modify makefile to suit you
+- Modify config.h to suit you
+- Make settings.h to suit you
+you'll need to unzip src/wircd/unrealircd.bmp.gz as well using winzip
+
+UnrealIRCd is not absolute to compile on Win32 yet