mirror of
https://github.com/anope/anope.git
synced 2026-06-30 00:36:37 +02:00
Initial Anope Import
git-svn-id: svn://svn.anope.org/anope/trunk@1 31f1291d-b8d6-0310-a050-a5561fc1590b git-svn-id: http://anope.svn.sourceforge.net/svnroot/anope/trunk@1 5417fbe8-f217-4b02-8779-1006273d7864
This commit is contained in:
Vendored
+1
@@ -0,0 +1 @@
|
||||
-kr -nut
|
||||
+428
@@ -0,0 +1,428 @@
|
||||
Anope Version 1.6.0
|
||||
--------------------
|
||||
** ADDED CONFIGURATION DIRECTIVES **
|
||||
|
||||
###########################################################################
|
||||
#
|
||||
# DefCon configuration
|
||||
#
|
||||
###########################################################################
|
||||
# DefConLevel <level> [OPTIONAL]
|
||||
# Default defcon level (1-5) to use when starting services up, level 5
|
||||
# instructs services to run as normal.
|
||||
|
||||
#DefConLevel 5
|
||||
|
||||
# DefCon1-4 <numeric> [REQUIRED if Defcon is activated]
|
||||
# These numercics determine which of the following operations take place
|
||||
# at each level, the correct numeric can be found by adding together the
|
||||
# number for each restriction you wish to place at a level.
|
||||
# No new channel registrations 1
|
||||
# No New Nick Registrations 2
|
||||
# No MLOCK changes 4
|
||||
# Force Chan Mode 8
|
||||
# Use Reduced Session Limit 16
|
||||
# KILL any new clients trying to connect 32
|
||||
# Services will ignore everyone but opers 64
|
||||
# Services will silently ignore everyone but opers 128
|
||||
# AKILL all new clients trying to connect 256
|
||||
# No new memos sent to block memoserv attacks 512
|
||||
|
||||
#DefCon4 23
|
||||
# No channel reg + No Nick Reg + No MLOCK changes + Use Reduced Session Limit
|
||||
# 1 + 2 + 4 + 16
|
||||
|
||||
#DefCon3 31
|
||||
# As DefCon4 + Services will Force Chan Mode's on channels
|
||||
# 23 + 8
|
||||
|
||||
#DefCon2 159
|
||||
# As DefCon3 + Services will silently ignore everyone but opers
|
||||
# 32 + 128
|
||||
|
||||
#DefCon1 415
|
||||
# As DefCon2 + AKILL all new clients trying to connect
|
||||
# 159 + 256
|
||||
|
||||
# DefConSessionLimit <limit> [REQUIRED if DefCon is activated]
|
||||
# New session limit to use when a defcon level is using "reduced"
|
||||
# session limiting.
|
||||
# NOTE: When using DefCon this value needs to be defined
|
||||
#DefConSessionLimit 2
|
||||
|
||||
# DefConAkillExpire <time> [REQUIRED if DefCon is activated]
|
||||
# Length of time to add the AKILL for when DEFCON is preventing
|
||||
# all new clients from connecting to the network
|
||||
#
|
||||
# NOTE: As with all expire times, the expirey check will only be
|
||||
# carried out once every "ExpireTimeout" so if this setting is
|
||||
# 30m the the akill could last for 30m regardless of this setting.
|
||||
#
|
||||
# NOTE: When using DefCon this value needs to be defined
|
||||
#DefConAkillExpire 5m
|
||||
|
||||
# DefConChanModes <modes> [REQUIRED if DefCon is activated]
|
||||
# The channel modes to set on all channel's when the DefCon channel
|
||||
# mode system is in use.
|
||||
#
|
||||
# NOTE: Choose these modes carefully, because when defcon switches to
|
||||
# a level which does NOT have the mode setting selected, services will
|
||||
# set the reverse on all channel's, e.g. if this setting is +RN
|
||||
# when defcon is used all channel's will be set to +RN, when
|
||||
# defcon is removed, channels will all be set to -RN. You don't
|
||||
# want to set this to +k for example because when defcon is removed all
|
||||
# channels will -k.
|
||||
# NOTE: mlock'ed modes will not be lost
|
||||
#DefConChanModes "+R"
|
||||
|
||||
# DefConTimeOut <time> [OPTIONAL]
|
||||
# This value can be used to automaticaly return the network to
|
||||
# defcon 5 after the specified time period - just in case any opers
|
||||
# forget to remove a defcon setting.
|
||||
#DefConTimeOut 15m
|
||||
|
||||
# GlobalOnDefcon [OPTIONAL]
|
||||
#
|
||||
# Setting this directive will make Services send a global message on
|
||||
# Defcon Level changes.
|
||||
#GlobalOnDefcon
|
||||
|
||||
# GlobalOnDefconMore [OPTIONAL]
|
||||
#
|
||||
# Setting this directive will make Services send a global message on
|
||||
# Defcon Level changes. Uncommenting this will allow you to send along
|
||||
# with the new level, the DefconMessage.
|
||||
#GlobalOnDefconMore
|
||||
|
||||
#DefconMessage "Put your message to send your users here. Dont forget to uncomment GlobalOnDefconMore"
|
||||
|
||||
# DefConOffMessage [OPTIONAL]
|
||||
#
|
||||
# If this is defined, it will be used in place of GlobalOnDefcon and
|
||||
# GlobalOnDefconMore when defcon is returned to level 5
|
||||
#DefConOffMessage "Services are now back to normal, sorry for any inconvenience"
|
||||
|
||||
# DefConAkillReason <text> [REQUIRED if DefCon is activated]
|
||||
#
|
||||
# When using DEFCON this setting will be used when any clients are killed
|
||||
# or akilled from the network by defcon
|
||||
#
|
||||
#DefConAkillReason "This network is currently not accepting connections, please try again later"
|
||||
|
||||
###########################################################################
|
||||
#
|
||||
# MySQL configuration
|
||||
#
|
||||
###########################################################################
|
||||
#
|
||||
# Mysql [OPTIONAL]
|
||||
#
|
||||
# Your MySQL configuration for use with Anope.
|
||||
# To disable MySQL functionality, just comment out this block.
|
||||
# To make use of MySQL use these directives and change their
|
||||
# setting to the appropiate values.
|
||||
#
|
||||
# MysqlHost defines the Mysql server hostname.
|
||||
# MysqlUser defines the Mysql user to log in with.
|
||||
# MysqlPass defines the Mysql pass required for the specified user to log in.
|
||||
# MysqlName defines the Mysql database name Anope uses
|
||||
# MysqlSock defines the Mysql UNIX socket
|
||||
# MysqlPort defines the Mysql TCP port
|
||||
#
|
||||
#MysqlHost "localhost"
|
||||
#MysqlUser "Anonymous"
|
||||
#MysqlPass ""
|
||||
#MysqlName "anope"
|
||||
#MysqlSock "/tmp/mysql.sock"
|
||||
#MysqlPort 3306
|
||||
|
||||
# MysqlSecure "<des>|<md5>|<sha>|<key>" [OPTIONAL]
|
||||
#
|
||||
# Method for storing passwords on MySQL. Available methods are:
|
||||
# Empty or not set will save your passwords as clear text.
|
||||
# des : Encrypt using a simple DES algorithm.
|
||||
# md5 : Produces the md5 hash for the password.
|
||||
# sha : Calculates the checksum using a Secure Hash Algorithm.
|
||||
# key : Encodes using "key" as password.
|
||||
# Please read docs/MYSQL file for more info and details.
|
||||
#
|
||||
#MysqlSecure ""
|
||||
|
||||
# MysqlRetries <value> [OPTIONAL]
|
||||
# MysqlRetryGap <value> [OPTIONAL]
|
||||
#
|
||||
# These values let you define how often and with how much interruption Anope
|
||||
# shall retry to open a connection when losing the contact to the mysql db.
|
||||
# The product of these values must be between 1 and 60.
|
||||
#
|
||||
#MysqlRetries 10
|
||||
#MysqlRetryGap 1
|
||||
|
||||
###########################################################################
|
||||
#
|
||||
# Module configuration
|
||||
#
|
||||
###########################################################################
|
||||
#
|
||||
# ModuleAutoload [OPTIONAL]
|
||||
#
|
||||
# When compiled with module support, this contains a space seperated list
|
||||
# of modules to automaticaly load as soon as possible, e.g. IRCD support modules.
|
||||
#
|
||||
#ModuleAutoload "hs_moo ircd_defizzer"
|
||||
|
||||
# ModuleDelayedAutoload [OPTIONAL]
|
||||
#
|
||||
# When compiled with module support, this contains a space seperated list
|
||||
# of modules to automaticaly load when services are ready for new clients.
|
||||
# e.g. new pesudo clients such as CatServ :-) *meow*
|
||||
#
|
||||
#ModuleDelayedAutoload "ircd_catserv"
|
||||
|
||||
###########################################################################
|
||||
#
|
||||
# Misc configuration
|
||||
#
|
||||
###########################################################################
|
||||
# AnonymousGlobal [OPTIONAL]
|
||||
# hides the oper's nick in a globalmsg
|
||||
#AnonymousGlobal
|
||||
|
||||
# DontQuoteAddresses [OPTIONAL]
|
||||
#
|
||||
# When enabled, services will not attempt to "" the TO: fields in mails
|
||||
#
|
||||
# So far we only know of ESMTP which needs this set.
|
||||
#
|
||||
#DontQuoteAddresses
|
||||
|
||||
# If services can't connect to the RemoteServer, they will try
|
||||
# RemoteServer2 (if defined). If they can't connect to RemoteServer2,
|
||||
# they will use RemoteServer3 (if defined).
|
||||
RemoteServer localhost 6667 "mypass"
|
||||
#RemoteServer2 localhost 6667 "mypass"
|
||||
#RemoteServer3 localhost 6667 "mypass"
|
||||
|
||||
# NSRestrictGetPass [OPTIONAL]
|
||||
#
|
||||
# When enabled, services will only allow Services Root to use the getpass
|
||||
# command on a nick.
|
||||
#
|
||||
#NSRestrictGetPass
|
||||
|
||||
# CSRestrictGetPass [OPTIONAL]
|
||||
#
|
||||
# When enabled, services will only allow Services Root to use the getpass
|
||||
# command on a channel.
|
||||
#
|
||||
#CSRestrictGetPass
|
||||
|
||||
# CSOpersOnly [OPTIONAL]
|
||||
# If this is defined, only IRC Operators will be permitted to use ChanServ.
|
||||
#CSOpersOnly
|
||||
|
||||
# GlobalOnCycleMessage <text> [OPTIONAL]
|
||||
#
|
||||
# This is the message to global when using GlobalOnCycle
|
||||
#GlobalOnCycleMEssage "Services are restarting, they will be back shortley - please be good while were gone"
|
||||
|
||||
# GlobalOnCycleUP <text> [OPTIONAL]
|
||||
#
|
||||
# if defined, this string will be globaled when services join the network
|
||||
#GlobalOnCycleUP "Services are now back online - have a nice day"
|
||||
|
||||
# ChanKillExpiry <time> [REQUIRED]
|
||||
# Default /OS CHANKILL expire time
|
||||
ChanKillExpiry 7d
|
||||
|
||||
# HostSetters <nicks> [DISCOURAGED]
|
||||
# Specifies the nicks of NON-OPERS allowed to Set/Remove vHosts using
|
||||
# HostServ. Can be re-loaded with /msg operserv reload
|
||||
# You can specify more than one nick by separating each one by a space.
|
||||
#
|
||||
# make sure you insert the correct nick(s) here..
|
||||
#HostSetters "rob dengel certus"
|
||||
|
||||
Anope Version 1.4.18
|
||||
--------------------
|
||||
** ADDED CONFIGURATION DIRECTIVES **
|
||||
# PreNickServDB prenick.db
|
||||
|
||||
# NSEmailReg [OPTIONAL]
|
||||
# This option splits the nick registration into 2 steps, the first
|
||||
# after registering a email with a passcode is sent to the supplied
|
||||
# email address, this passcode needs to be entered with a confirm
|
||||
# command before the nick registration will be completed.
|
||||
#
|
||||
# You must have mail / forcemail set for this to work correctly.
|
||||
# It is also recommended that MailDelay be set to a sensible value
|
||||
# to prevent mail flooding
|
||||
|
||||
# NSEmailReg
|
||||
|
||||
# NSRExpire <time> [OPTIONAL]
|
||||
# Sets the length of time a user gets to enter the confirmation code
|
||||
# which has been e-mailed to them before the nick will be relased
|
||||
# for general use again
|
||||
|
||||
# NSRExpire 1d
|
||||
|
||||
# NSModeOnID [OPTIONAL]
|
||||
#
|
||||
# When enabled, services will set channel modes a user has when they identify
|
||||
#
|
||||
|
||||
# NSModeOnID
|
||||
|
||||
# HideStatsO [OPTIONAL]
|
||||
#
|
||||
# Setting this directive will make Services only show Stats O to
|
||||
# IRC Operators.
|
||||
|
||||
#HideStatsO
|
||||
|
||||
# GlobalOnCycle [OPTIONAL]
|
||||
#
|
||||
# Setting this directive will make Services send global messages on
|
||||
# starting up and shuting down/restarting.
|
||||
|
||||
#GlobalOnCycle
|
||||
|
||||
** MODIFIED CONFIGURATION DIRECTIVES **
|
||||
# NetworkDomain <name> [OPTIONAL]
|
||||
#
|
||||
# If your network has a common domain name, specify it there (for
|
||||
# example, all IRCZONE servers have a name ending in ".irczone.cl",
|
||||
# so "irczone.cl" would be set there. It will be used by the OperServ
|
||||
# GLOBAL command, and if you don't have a common domain name, this
|
||||
# command may just not work.
|
||||
#
|
||||
# You can specify more than one Network Domain by separating each one by
|
||||
# a space: NetworkDomain "localnet.net localnet.com"
|
||||
NetworkDomain "localnet.com"
|
||||
|
||||
AnopeVersion 1.4.26
|
||||
--------------------------
|
||||
** ADDED CONFIGURATION DIRECTIVES **
|
||||
# DontQuoteAddresses [OPTIONAL]
|
||||
#
|
||||
# When enabled, services will not attempt to "" the to fields in mails
|
||||
#
|
||||
# So far we only know of ESMTP which needs this set.
|
||||
#
|
||||
|
||||
#DontQuoteAddresses
|
||||
|
||||
Anope Version 1.4.18
|
||||
--------------------
|
||||
** ADDED CONFIGURATION DIRECTIVES **
|
||||
# PreNickServDB prenick.db
|
||||
|
||||
# NSEmailReg [OPTIONAL]
|
||||
# This option splits the nick registration into 2 steps, the first
|
||||
# after registering a email with a passcode is sent to the supplied
|
||||
# email address, this passcode needs to be entered with a confirm
|
||||
# command before the nick registration will be completed.
|
||||
#
|
||||
# You must have mail / forcemail set for this to work correctly.
|
||||
# It is also recommended that MailDelay be set to a sensible value
|
||||
# to prevent mail flooding
|
||||
|
||||
# NSEmailReg
|
||||
|
||||
# NSRExpire <time> [OPTIONAL]
|
||||
# Sets the length of time a user gets to enter the confirmation code
|
||||
# which has been e-mailed to them before the nick will be relased
|
||||
# for general use again
|
||||
|
||||
# NSRExpire 1d
|
||||
|
||||
# NSModeOnID [OPTIONAL]
|
||||
#
|
||||
# When enabled, services will set channel modes a user has when they identify
|
||||
#
|
||||
|
||||
# NSModeOnID
|
||||
|
||||
# HideStatsO [OPTIONAL]
|
||||
#
|
||||
# Setting this directive will make Services only show Stats O to
|
||||
# IRC Operators.
|
||||
|
||||
#HideStatsO
|
||||
|
||||
# GlobalOnCycle [OPTIONAL]
|
||||
#
|
||||
# Setting this directive will make Services send global messages on
|
||||
# starting up and shuting down/restarting.
|
||||
|
||||
#GlobalOnCycle
|
||||
|
||||
Anope Version 1.4.16
|
||||
--------------------
|
||||
** ADDED CONFIGURATION DIRECTIVES **
|
||||
HostServName "HostServ" "vHost Server"
|
||||
HostServDB hosts.db
|
||||
HostServAlias "HostServ2" "Vhostname Server Forwarder"
|
||||
|
||||
** MODIFIED CONFIGURATION DIRECTIVES **
|
||||
|
||||
# ForceForbidReason [OPTIONAL]
|
||||
#
|
||||
# If set, Services will require a reason when a forbid is added, else
|
||||
# the reason is optional. This directive also applies to SUSPENDed
|
||||
# channels as well.
|
||||
|
||||
ForceForbidReason
|
||||
|
||||
** DELETED CONFIGURATION DIRECTIVES **
|
||||
|
||||
Anope Version 1.4.15
|
||||
--------------------
|
||||
** ADDED CONFIGURATION DIRECTIVES **
|
||||
|
||||
# ...Alias <nick> <string> [OPTIONAL]
|
||||
# Specify alternate nicknames for services. When a user will /msg
|
||||
# NickServAlias sthing, it will be forwarded to NickServName, and
|
||||
# NickServName will answer. This can be used to ease the migration
|
||||
# from another network, for example if your services are called
|
||||
# NickKeeper, ChanKeeper, etc ... and the other network calls them
|
||||
# NickServ, ChanServ, etc ...
|
||||
|
||||
NickServAlias "NickServ2" "Nickname Server Forwarder"
|
||||
ChanServAlias "ChanServ2" "Channel Server Forwarder"
|
||||
MemoServAlias "MemoServ2" "Memo Server Forwarder"
|
||||
BotServAlias "BotServ2" "Bot Server Forwarder"
|
||||
HelpServAlias "HelpServ2" "Help Server Forwarder"
|
||||
OperServAlias "OperServ2" "Operator Server Forwarder"
|
||||
GlobalAlias "Global2" "Global Noticer Forwarder"
|
||||
#DevNullName "DevNull2" "/dev/null -- message sink Forwarder"
|
||||
|
||||
# LogChannel <channel> [OPTIONAL]
|
||||
#
|
||||
# When defined, services will output log messages to this channel.
|
||||
# IMPORTANT: This can be a security risk so make certain this channel
|
||||
# is sufficiently protected from normal access.
|
||||
|
||||
#LogChannel "#services"
|
||||
|
||||
# LogChannel [OPTIONAL]
|
||||
#
|
||||
# When defined, services will output all BotServ chatter to the defined
|
||||
# LogChan above. It shows all uses of BotServ ACT and SAY commands. Note
|
||||
# that there is no logging to the log file. Only works is LogChannel is
|
||||
# also defined.
|
||||
|
||||
#LogBot
|
||||
|
||||
# SuperAdmin [OPTIONAL]
|
||||
# Having this flag enabled will turn all Services Admin to have Founder
|
||||
# level on *all* registered channels.
|
||||
|
||||
#SuperAdmin
|
||||
|
||||
# AddAkiller [OPTIONAL]
|
||||
# Adds the nickname of the Operator issuing an AKILL to the kill reason.
|
||||
#
|
||||
|
||||
AddAkiller
|
||||
+963
@@ -0,0 +1,963 @@
|
||||
Anope Version 1.6.0
|
||||
--------------------
|
||||
|
||||
New Strings:
|
||||
CHAN_HELP_ULTIMATE3
|
||||
DEFCON_GLOBAL
|
||||
END_OF_ANY_LIST
|
||||
HELP_HELP_HOST
|
||||
HOST_DELALL
|
||||
HOST_DELALL_SYNTAX
|
||||
HOST_HELP_DELALL
|
||||
HOST_LIST_FOOTER
|
||||
HOST_LIST_KEY_FOOTER
|
||||
HOST_LIST_RANGE_FOOTER
|
||||
HOST_OPER_HELP
|
||||
MEMO_HELP_ADMIN
|
||||
MEMO_HELP_FOOTER
|
||||
MEMO_HELP_OPER
|
||||
MEMO_HELP_SENDALL
|
||||
MEMO_HELP_STAFF
|
||||
MEMO_MASS_SENT
|
||||
MODULE_HELP_HEADER
|
||||
NICK_ALREADY_IDENTIFIED
|
||||
NICK_GETEMAIL_EMAILS_ARE
|
||||
NICK_GETEMAIL_NOT_USED
|
||||
NICK_GETEMAIL_SYNTAX
|
||||
NICK_HELP_UPDATE
|
||||
NICK_LOGOUT_SERVICESADMIN
|
||||
NICK_SERVADMIN_HELP_GETEMAIL
|
||||
NICK_UPDATE_SUCCESS
|
||||
NICK_X_ILLEGAL
|
||||
NICK_X_IN_USE
|
||||
NICK_X_TRUNCATED
|
||||
OPER_CHANKILL_SYNTAX
|
||||
OPER_DEFCON_CHANGED
|
||||
OPER_DEFCON_DENIED
|
||||
OPER_DEFCON_NO_CONF
|
||||
OPER_DEFCON_SYNTAX
|
||||
OPER_DEFCON_WALL
|
||||
OPER_HELP_ADMIN_CMD
|
||||
OPER_HELP_CHANKILL
|
||||
OPER_HELP_DEFCON
|
||||
OPER_HELP_DEFCON_AKILL_NEW_CLIENTS
|
||||
OPER_HELP_DEFCON_FORCE_CHAN_MODES
|
||||
OPER_HELP_DEFCON_NO_MLOCK_CHANGE
|
||||
OPER_HELP_DEFCON_NO_NEW_CHANNELS
|
||||
OPER_HELP_DEFCON_NO_NEW_CLIENTS
|
||||
OPER_HELP_DEFCON_NO_NEW_MEMOS
|
||||
OPER_HELP_DEFCON_NO_NEW_NICKS
|
||||
OPER_HELP_DEFCON_OPER_ONLY
|
||||
OPER_HELP_DEFCON_REDUCE_SESSION
|
||||
OPER_HELP_DEFCON_SILENT_OPER_ONLY
|
||||
OPER_HELP_LOGGED
|
||||
OPER_HELP_MODINFO
|
||||
OPER_HELP_MODLIST
|
||||
OPER_HELP_MODLOAD
|
||||
OPER_HELP_MODUNLOAD
|
||||
OPER_HELP_OPER_CMD
|
||||
OPER_HELP_ROOT_CMD
|
||||
OPER_HELP_SVSNICK
|
||||
OPER_MODULE_CMD_LIST
|
||||
OPER_MODULE_INFO_LIST
|
||||
OPER_MODULE_INFO_SYNTAX
|
||||
OPER_MODULE_LIST
|
||||
OPER_MODULE_LOADED
|
||||
OPER_MODULE_LOAD_FAIL
|
||||
OPER_MODULE_LOAD_SYNTAX
|
||||
OPER_MODULE_MSG_LIST
|
||||
OPER_MODULE_NO_INFO
|
||||
OPER_MODULE_NO_LIST
|
||||
OPER_MODULE_REMOVE_FAIL
|
||||
OPER_MODULE_UNLOADED
|
||||
OPER_MODULE_UNLOAD_SYNTAX
|
||||
OPER_STAFF_AFORMAT
|
||||
OPER_STAFF_FORMAT
|
||||
OPER_STAFF_LIST_HEADER
|
||||
OPER_SVSNICK_NEWNICK
|
||||
OPER_SVSNICK_SYNTAX
|
||||
|
||||
Modified strings (need to be re-translated):
|
||||
BOT_ASSIGN_ALREADY
|
||||
CHAN_HELP_LOGOUT
|
||||
CHAN_HELP_ULTIMATE
|
||||
CHAN_SERVADMIN_HELP_LOGOUT
|
||||
HOST_ENTRY
|
||||
HOST_HELP_DEL
|
||||
HOST_HELP_LIST
|
||||
HOST_HELP_SET
|
||||
HOST_IDENT_ENTRY
|
||||
HOST_OPER_HELP
|
||||
MEMO_HELP
|
||||
NICK_HELP_DROP
|
||||
OPER_HELP
|
||||
OPER_HELP_ADMIN
|
||||
OPER_HELP_UMODE
|
||||
|
||||
Anope Version 1.4.22
|
||||
--------------------
|
||||
New strings:
|
||||
OPER_JUPE_HOST_ERROR
|
||||
CHAN_UNSUSPEND_ERROR
|
||||
|
||||
Anope Version 1.4.21
|
||||
--------------------
|
||||
New strings:
|
||||
BOT_BAD_NICK
|
||||
BOT_BAD_HOST
|
||||
BOT_BAD_IDENT
|
||||
HOST_SET_IDENT_ERROR
|
||||
|
||||
Modified strings (need to be re-translated):
|
||||
HOST_SET_ERROR
|
||||
|
||||
Anope Version 1.4.18
|
||||
--------------------
|
||||
New strings:
|
||||
MEMO_X_MANY_NOTICE
|
||||
MEMO_X_ONE_NOTICE
|
||||
MEMO_NEW_X_MEMO_ARRIVED
|
||||
MEMO_CHAN_DELETED_ALL
|
||||
NICK_REQUESTED
|
||||
NICK_IS_PREREG
|
||||
NICK_ENTER_REG_CODE
|
||||
NICK_CONFIRM_NOT_FOUND
|
||||
NICK_CONFIRM_INVALID
|
||||
NICK_REG_MAIL_SUBJECT
|
||||
NICK_REG_MAIL_HEAD
|
||||
NICK_REG_MAIL_LINE_1
|
||||
NICK_REG_MAIL_LINE_2
|
||||
NICK_REG_MAIL_LINE_3
|
||||
NICK_REG_MAIL_LINE_4
|
||||
NICK_REG_MAIL_LINE_5
|
||||
HOST_HELP_GROUP
|
||||
HOST_IDENT_GROUP
|
||||
HOST_GROUP
|
||||
NICK_REG_RESENT
|
||||
NICK_REG_UNABLE
|
||||
NICK_GETPASS_PASSCODE_IS
|
||||
NICK_FORCE_REG
|
||||
BOT_EXCEPT
|
||||
OPER_IGNORE_SYNTAX
|
||||
OPER_IGNORE_VALID_TIME
|
||||
OPER_IGNORE_TIME_DONE
|
||||
OPER_IGNORE_PERM_DONE
|
||||
OPER_IGNORE_DEL_DONE
|
||||
OPER_IGNORE_LIST_NOMATCH
|
||||
OPER_IGNORE_LIST_CLEARED
|
||||
OPER_HELP_IGNORE
|
||||
OPER_HELP_UMODE
|
||||
OPER_HELP_OLINE
|
||||
OPER_UMODE_SYNTAX
|
||||
OPER_OLINE_SYNTAX
|
||||
OPER_OLINE_SUCCESS
|
||||
OPER_SUPER_ADMIN_ON
|
||||
OPER_SUPER_ADMIN_OFF
|
||||
OPER_SUPER_ADMIN_SYNTAX
|
||||
OPER_SUPER_ADMIN_WALL_ON
|
||||
OPER_SUPER_ADMIN_WALL_OFF
|
||||
OPER_UMODE_SUCCESS
|
||||
OPER_UMODE_CHANGED
|
||||
OPER_SUPER_ADMIN_ONLY
|
||||
OPER_HELP_SET_SUPERADMIN
|
||||
OPER_OLINE_IRCOP
|
||||
|
||||
Modified strings (need to be re-translated):
|
||||
HOST_HELP
|
||||
NICK_LIST_SERVADMIN_SYNTAX
|
||||
MEMO_HELP_DEL
|
||||
OPER_HELP
|
||||
OPER_HELP_SET
|
||||
|
||||
Deleted strings:
|
||||
|
||||
|
||||
Anope Version 1.4.17
|
||||
--------------------
|
||||
New strings:
|
||||
NICK_INFO_VHOST
|
||||
HOST_SET_ERROR
|
||||
HOST_SET_TOOLONG
|
||||
NICK_ALIST_SYNTAX
|
||||
NICK_ALIST_HEADER
|
||||
NICK_ALIST_HEADER_X
|
||||
NICK_ALIST_XOP_FORMAT
|
||||
NICK_ALIST_ACCESS_FORMAT
|
||||
NICK_ALIST_FOOTER
|
||||
NICK_HELP_ALIST
|
||||
NICK_SERVADMIN_HELP_ALIST
|
||||
HOST_IDENT_SET
|
||||
HOST_IDENT_SETALL
|
||||
HOST_SET_IDENTTOOLONG
|
||||
HOST_IDENT_ACTIVATED
|
||||
HOST_NO_VIDENT
|
||||
|
||||
Modified strings (need to be re-translated):
|
||||
RAW_DISABLED
|
||||
HOST_OFF_UNREAL
|
||||
HOST_HELP_SET
|
||||
HOST_HELP_SETALL
|
||||
|
||||
Deleted strings:
|
||||
CHAN_CLIST_SYNTAX
|
||||
CHAN_CLIST_HEADER
|
||||
CHAN_CLIST_FORMAT
|
||||
CHAN_CLIST_FOOTER
|
||||
CHAN_ALIST_SYNTAX
|
||||
CHAN_ALIST_HEADER
|
||||
CHAN_ALIST_XOP_FORMAT
|
||||
CHAN_ALIST_AXS_FORMAT
|
||||
CHAN_ALIST_FOOTER
|
||||
CHAN_HELP_CLIST
|
||||
CHAN_HELP_ALIST
|
||||
|
||||
Anope Version 1.4.16
|
||||
--------------------
|
||||
New strings:
|
||||
CHAN_X_SUSPENDED
|
||||
CHAN_AOP_MOVED
|
||||
CHAN_HOP_MOVED
|
||||
CHAN_SOP_MOVED
|
||||
CHAN_VOP_MOVED
|
||||
CHAN_ACCESS_LIST_XOP_FORMAT
|
||||
CHAN_ACCESS_LIST_AXS_FORMAT
|
||||
CHAN_ALIST_SYNTAX
|
||||
CHAN_ALIST_HEADER
|
||||
CHAN_ALIST_XOP_FORMAT
|
||||
CHAN_ALIST_AXS_FORMAT
|
||||
CHAN_ALIST_FOOTER
|
||||
CHAN_CLEARED_EXCEPTS
|
||||
CHAN_FORBID_REASON
|
||||
CHAN_SUSPEND_SYNTAX
|
||||
CHAN_SUSPEND_SYNTAX_REASON
|
||||
CHAN_SUSPEND_SUCCEEDED
|
||||
CHAN_SUSPEND_FAILED
|
||||
CHAN_SUSPEND_REASON
|
||||
CHAN_UNSUSPEND_SYNTAX
|
||||
CHAN_UNSUSPEND_SUCCEEDED
|
||||
CHAN_UNSUSPEND_FAILED
|
||||
CHAN_EXCEPTED
|
||||
CHAN_HELP_CLIST
|
||||
CHAN_HELP_ALIST
|
||||
CHAN_SERVADMIN_HELP_SUSPEND
|
||||
CHAN_SERVADMIN_HELP_UNSUSPEND
|
||||
HOST_EMPTY
|
||||
HOST_ENTRY
|
||||
HOST_SET
|
||||
HOST_SETALL
|
||||
HOST_NOREG
|
||||
HOST_SET_SYNTAX
|
||||
HOST_SETALL_SYNTAX
|
||||
HOST_DENIED
|
||||
HOST_NOT_ASSIGNED
|
||||
HOST_ACTIVATED
|
||||
HOST_ID
|
||||
HOST_NOT_REGED
|
||||
HOST_DEL
|
||||
HOST_DEL_SYNTAX
|
||||
HOST_OFF_UNREAL
|
||||
HOST_HELP
|
||||
HOST_OPER_HELP
|
||||
HOST_ADMIN_HELP
|
||||
HOST_HELP_ON
|
||||
HOST_HELP_SET
|
||||
HOST_HELP_SETALL
|
||||
HOST_HELP_OFF
|
||||
HOST_HELP_DEL
|
||||
HOST_HELP_LIST
|
||||
|
||||
Modified strings:
|
||||
CHAN_HELP
|
||||
CHAN_CLIST_HEADER
|
||||
CHAN_CLIST_FORMAT
|
||||
CHAN_SERVADMIN_HELP
|
||||
CHAN_SERVADMIN_HELP_LIST
|
||||
CHAN_LIST_SERVADMIN_SYNTAX
|
||||
CHAN_HELP_SET
|
||||
CHAN_SERVADMIN_HELP
|
||||
|
||||
Deleted strings:
|
||||
CHAN_SERVADMIN_HELP_CLIST
|
||||
CHAN_ACCESS_LIST_FORMAT
|
||||
CHAN_XOP_ALREADY_EXISTS
|
||||
|
||||
Anope Version 1.4.15
|
||||
--------------------
|
||||
New strings:
|
||||
RAW_DISABLED
|
||||
CHAN_ACCESS_LIST_FOOTER
|
||||
OPER_SET_LOGCHAN_ON
|
||||
OPER_SET_LOGCHAN_OFF
|
||||
OPER_SET_LOGCHAN_ERROR
|
||||
OPER_HELP_SET_LOGCHAN
|
||||
|
||||
Modified strings:
|
||||
OPER_HELP_SET
|
||||
|
||||
Epona Version 1.4.0
|
||||
-------------------
|
||||
New strings:
|
||||
BOT_BOTLIST_FOOTER
|
||||
BOT_BOTLIST_PRIVATE_HEADER
|
||||
BOT_INFO_BOT_OPTIONS
|
||||
BOT_INFO_OPT_PRIVATE
|
||||
BOT_SERVADMIN_HELP_SET_PRIVATE
|
||||
BOT_SET_PRIVATE_...
|
||||
CHAN_ACCESS_XOP
|
||||
CHAN_AKICK_STUCK
|
||||
CHAN_AKICK_UNSTUCK
|
||||
CHAN_AKICK_VIEW_FORMAT_STUCK
|
||||
CHAN_AOP_...
|
||||
CHAN_HELP_AOP
|
||||
CHAN_HELP_BAN
|
||||
CHAN_HELP_DEOWNER
|
||||
CHAN_HELP_HOP
|
||||
CHAN_HELP_OWNER
|
||||
CHAN_HELP_SET_PEACE
|
||||
CHAN_HELP_SET_XOP
|
||||
CHAN_HELP_SOP
|
||||
CHAN_HELP_VOP
|
||||
CHAN_HELP_TOPIC
|
||||
CHAN_HOP_...
|
||||
CHAN_INFO_OPT_OPNOTICE
|
||||
CHAN_INFO_OPT_PEACE
|
||||
CHAN_INFO_OPT_XOP
|
||||
CHAN_LEVEL_BANME
|
||||
CHAN_LEVEL_BAN
|
||||
CHAN_LEVEL_INFO
|
||||
CHAN_LEVEL_TOPIC
|
||||
CHAN_LEVELS_XOP
|
||||
CHAN_SET_MLOCK_IMPOSSIBLE_CHAR
|
||||
CHAN_SET_MLOCK_K_REQUIRED
|
||||
CHAN_SET_PEACE_...
|
||||
CHAN_SET_XOP_...
|
||||
CHAN_SOP_...
|
||||
CHAN_TOPIC_SYNTAX
|
||||
CHAN_VOP_...
|
||||
CHAN_XOP_...
|
||||
NEWS_HELP_RANDOM
|
||||
NEWS_RANDOM_...
|
||||
NEWS_RANDOM_TEXT
|
||||
NICK_GROUP_TOO_MANY
|
||||
NICK_X_NOT_ON_CHAN
|
||||
OPER_CACHE_...
|
||||
OPER_HELP_CACHE
|
||||
OPER_HELP_SQLINE
|
||||
OPER_SQLINE_...
|
||||
OPER_STATS_PROXY_MEM
|
||||
OPER_STATS_SQLINE_...
|
||||
|
||||
Modified strings:
|
||||
BOT_HELP_INFO
|
||||
BOT_HELP_SET_SYMBIOSIS
|
||||
BOT_SERVADMIN_HELP_SET
|
||||
CHAN_AKICK_SYNTAX
|
||||
CHAN_AKICK_LIST_FORMAT
|
||||
CHAN_HELP
|
||||
CHAN_HELP_AKICK
|
||||
CHAN_HELP_CLEAR
|
||||
CHAN_HELP_DEHALFOP
|
||||
CHAN_HELP_DEOP
|
||||
CHAN_HELP_DEPROTECT
|
||||
CHAN_HELP_DEVOICE
|
||||
CHAN_HELP_HALFOP
|
||||
CHAN_HELP_INFO
|
||||
CHAN_HELP_INVITE
|
||||
CHAN_HELP_KICK
|
||||
CHAN_HELP_OP
|
||||
CHAN_HELP_PROTECT
|
||||
CHAN_HELP_SET
|
||||
CHAN_HELP_SET_MLOCK
|
||||
CHAN_HELP_VOICE
|
||||
CHAN_HELP_ULTIMATE
|
||||
CHAN_HELP_UNREAL
|
||||
CHAN_HELP_UNBAN
|
||||
NO_REASON
|
||||
OPER_CHANLIST_HEADER
|
||||
OPER_CHANLIST_HEADER_USER
|
||||
OPER_CHANLIST_RECORD
|
||||
OPER_HELP
|
||||
OPER_HELP_KILLCLONES
|
||||
OPER_HELP_JUPE
|
||||
|
||||
Deleted strings:
|
||||
CHAN_HELP_ADMIN
|
||||
CHAN_HELP_DEADMIN
|
||||
CHAN_HELP_SET_TOPIC
|
||||
CHAN_LEVEL_ADMIN
|
||||
CHAN_LEVEL_ADMINME
|
||||
CHAN_LEVEL_AUTOADMIN
|
||||
CHAN_MLOCK_REMOVED
|
||||
CHAN_NO_AOP_SOP
|
||||
CHAN_SET_MLOCK_FLOOD_REQUIRED
|
||||
CHAN_SET_MLOCK_KEY_REQUIRED
|
||||
CHAN_SET_MLOCK_LIMIT_POSITIVE
|
||||
CHAN_SET_MLOCK_LIMIT_REQUIRED
|
||||
CHAN_SET_MLOCK_REDIRECT_REQUIRED
|
||||
CHAN_SET_TOPIC_FAILED
|
||||
NICK_INFO_LINKED_TO
|
||||
|
||||
Epona Version 1.3.0
|
||||
-------------------
|
||||
New strings:
|
||||
CHAN_LEVEL_ADMIN
|
||||
CHAN_LEVEL_ADMINME
|
||||
CHAN_LEVEL_AUTOADMIN
|
||||
BOT_REASON_BADWORD_GENTLE
|
||||
CHAN_CLIST_...
|
||||
CHAN_HELP_ADMIN
|
||||
CHAN_HELP_DEADMIN
|
||||
CHAN_HELP_ULTIMATE
|
||||
CHAN_SERVADMIN_HELP_CLIST
|
||||
EXPIRES_...
|
||||
MAIL_X_INVALID
|
||||
NICK_HELP_GLIST
|
||||
NICK_HELP_GROUP
|
||||
NICK_HELP_SET_DISPLAY
|
||||
NICK_HELP_SET_MSG
|
||||
NICK_IDENTIFY_EMAIL_HOWTO
|
||||
NICK_INFO_OPT_MSG
|
||||
NICK_GLIST_...
|
||||
NICK_GROUP_...
|
||||
NICK_SERVADMIN_HELP_GLIST
|
||||
NICK_SET_DISPLAY_...
|
||||
NICK_SET_MSG_...
|
||||
NICK_SET_OPTION_DISABLED
|
||||
OBSOLETE_COMMAND
|
||||
OPER_AKILL_EXISTS
|
||||
OPER_AKILL_ALREADY_COVERED
|
||||
OPER_AKILL_REACHED_LIMIT
|
||||
OPER_AKILL_CHANGED
|
||||
OPER_AKILL_NO_MATCH
|
||||
OPER_AKILL_DELETED
|
||||
OPER_AKILL_DELETED_ONE
|
||||
OPER_AKILL_DELETED_SEVERAL
|
||||
OPER_AKILL_LIST_EMPTY
|
||||
OPER_AKILL_VIEW_HEADER
|
||||
OPER_AKILL_CLEAR
|
||||
OPER_HELP_NOOP
|
||||
OPER_HELP_SGLINE
|
||||
OPER_HELP_SZLINE
|
||||
OPER_NOOP_...
|
||||
OPER_SGLINE_...
|
||||
OPER_STATS_ALIASES_MEM
|
||||
OPER_STATS_GROUPS_MEM
|
||||
OPER_STATS_SGLINE_...
|
||||
OPER_STATS_SZLINE_...
|
||||
OPER_SZLINE_...
|
||||
|
||||
Modified strings:
|
||||
CHAN_HELP
|
||||
CHAN_ACCESS_LIST_FORMAT
|
||||
CHAN_SERVADMIN_HELP
|
||||
NICK_HELP
|
||||
NICK_HELP_DROP
|
||||
NICK_HELP_EXPIRES
|
||||
NICK_HELP_GHOST
|
||||
NICK_HELP_RECOVER
|
||||
NICK_HELP_REGISTER
|
||||
NICK_HELP_RELEASE
|
||||
NICK_HELP_SET
|
||||
NICK_IDENTIFY_EMAIL_REQUIRED
|
||||
NICK_SERVADMIN_HELP
|
||||
NICK_SERVADMIN_HELP_DROP
|
||||
OPER_ADMIN_LIST_FORMAT
|
||||
OPER_AKILL_SYNTAX
|
||||
OPER_AKILL_ADDED
|
||||
OPER_AKILL_NOT_FOUND
|
||||
OPER_AKILL_LIST_HEADER
|
||||
OPER_AKILL_LIST_FORMAT
|
||||
OPER_AKILL_VIEW_FORMAT
|
||||
OPER_OPER_LIST_FORMAT
|
||||
OPER_HELP
|
||||
OPER_HELP_AKILL
|
||||
|
||||
Deleted strings:
|
||||
CHAN_HELP_SET_LEAVEOPS
|
||||
CHAN_INFO_OPT_LEAVEOPS
|
||||
CHAN_SET_LEAVEOPS_...
|
||||
NICK_DROP_SYNTAX
|
||||
NICK_HELP_LINK
|
||||
NICK_HELP_UNLINK
|
||||
NICK_LINK_SYNTAX
|
||||
NICK_LINK_DISABLED
|
||||
NICK_LINK_FAILED
|
||||
NICK_LINK_CIRCULAR
|
||||
NICK_LINKED
|
||||
NICK_LISTLINKS_SYNTAX
|
||||
NICK_LISTLINKS_HEADER
|
||||
NICK_LISTLINKS_FOOTER
|
||||
NICK_NO_LINK_SAME
|
||||
NICK_NOT_LINKED
|
||||
NICK_SERVADMIN_HELP_LISTLINKS
|
||||
NICK_SERVADMIN_HELP_UNLINK
|
||||
NICK_UNLINK_SYNTAX
|
||||
NICK_UNLINK_FAILED
|
||||
NICK_UNLINKED
|
||||
NICK_X_NOT_LINKED
|
||||
NICK_X_UNLINKED
|
||||
OPER_AKILL_ADD_SYNTAX
|
||||
OPER_AKILL_DEL_SYNTAX
|
||||
OPER_AKILL_REMOVED
|
||||
OPER_AKILL_NO_EXPIRE
|
||||
OPER_AKILL_EXPIRES_SOON
|
||||
OPER_AKILL_EXPIRES_M
|
||||
OPER_AKILL_EXPIRES_1M
|
||||
OPER_AKILL_EXPIRES_HM
|
||||
OPER_AKILL_EXPIRES_H1M
|
||||
OPER_AKILL_EXPIRES_1HM
|
||||
OPER_AKILL_EXPIRES_1H1M
|
||||
OPER_AKILL_EXPIRES_D
|
||||
OPER_AKILL_EXPIRES_1D
|
||||
OPER_STATS_NICKSERV_MEM
|
||||
OPER_TOO_MANY_AKILLS
|
||||
|
||||
Epona Version 1.2.3
|
||||
-------------------
|
||||
New strings:
|
||||
HELP_HELP_BOT
|
||||
|
||||
Epona Version 1.2.0
|
||||
-------------------
|
||||
New strings:
|
||||
BOT_INFO_OPT_NOBOT
|
||||
BOT_SEEN_BOT
|
||||
BOT_SEEN_YOU
|
||||
BOT_SEEN_ON_CHANNEL
|
||||
BOT_SEEN_ON_CHANNEL_AS
|
||||
BOT_SEEN_ON
|
||||
BOT_SEEN_NEVER
|
||||
BOT_SEEN_UNKNOWN
|
||||
BOT_SERVADMIN_HELP_SET
|
||||
BOT_SERVADMIN_HELP_SET_NOBOT
|
||||
BOT_SET_NOBOT_SYNTAX
|
||||
BOT_SET_NOBOT_ON
|
||||
BOT_SET_NOBOT_OFF
|
||||
CHAN_HELP_KICK
|
||||
CHAN_HELP_LOGOUT
|
||||
CHAN_HELP_SET_SIGNKICK
|
||||
CHAN_INFO_OPT_SIGNKICK
|
||||
CHAN_LEVEL_KICKME
|
||||
CHAN_LEVEL_KICK
|
||||
CHAN_LOGOUT_SYNTAX
|
||||
CHAN_LOGOUT_SERVADMIN_SYNTAX
|
||||
CHAN_LOGOUT_SUCCEEDED
|
||||
CHAN_LOGOUT_ALL_SUCCEEDED
|
||||
CHAN_SERVADMIN_HELP_LOGOUT
|
||||
CHAN_SET_SIGNKICK_SYNTAX
|
||||
CHAN_SET_SIGNKICK_ON
|
||||
CHAN_SET_SIGNKICK_LEVEL
|
||||
CHAN_SET_SIGNKICK_OFF
|
||||
CHAN_SUCCESSOR_IS_FOUNDER
|
||||
DURATION_DAY
|
||||
DURATION_DAYS
|
||||
DURATION_HOUR
|
||||
DURATION_HOURS
|
||||
DURATION_MINUTE
|
||||
DURATION_MINUTES
|
||||
DURATION_SECOND
|
||||
DURATION_SECONDS
|
||||
MEMO_INFO_NOTIFY_OFF
|
||||
MEMO_INFO_NOTIFY_ON
|
||||
MEMO_INFO_NOTIFY_RECEIVE
|
||||
MEMO_INFO_NOTIFY_SIGNON
|
||||
MEMO_INFO_X_NOTIFY_OFF
|
||||
MEMO_INFO_X_NOTIFY_ON
|
||||
MEMO_INFO_X_NOTIFY_RECEIVE
|
||||
MEMO_INFO_X_NOTIFY_SIGNON
|
||||
NICK_HELP_EXPIRES
|
||||
NICK_HELP_LOGOUT
|
||||
NICK_HELP_SET_ICQ
|
||||
NICK_INFO_ICQ
|
||||
NICK_INFO_SERVICES_ADMIN
|
||||
NICK_INFO_SERVICES_OPER
|
||||
NICK_LOGOUT_SYNTAX
|
||||
NICK_LOGOUT_SUCCEEDED
|
||||
NICK_LOGOUT_X_SUCCEEDED
|
||||
NICK_SERVADMIN_HELP_LOGOUT
|
||||
NICK_SET_ICQ_CHANGED
|
||||
NICK_SET_ICQ_UNSET
|
||||
NICK_SET_ICQ_INVALID
|
||||
OPER_ADMIN_CLEAR
|
||||
OPER_ADMIN_DELETED
|
||||
OPER_ADMIN_DELETED_ONE
|
||||
OPER_ADMIN_DELETED_SEVERAL
|
||||
OPER_ADMIN_LIST_EMPTY
|
||||
OPER_ADMIN_LIST_FORMAT
|
||||
OPER_ADMIN_NO_MATCH
|
||||
OPER_ADMIN_REACHED_LIMIT
|
||||
OPER_HELP_RELOAD
|
||||
OPER_OPER_CLEAR
|
||||
OPER_OPER_DELETED
|
||||
OPER_OPER_DELETED_ONE
|
||||
OPER_OPER_DELETED_SEVERAL
|
||||
OPER_OPER_LIST_EMPTY
|
||||
OPER_OPER_LIST_FORMAT
|
||||
OPER_OPER_NO_MATCH
|
||||
OPER_OPER_REACHED_LIMIT
|
||||
OPER_RELOAD
|
||||
USERHOST_MASK_TOO_WIDE
|
||||
|
||||
Modified strings:
|
||||
BOT_HELP_SET_FANTASY
|
||||
CHAN_HELP
|
||||
CHAN_HELP_SET
|
||||
MEMO_INFO_X_HARD_LIMIT
|
||||
NICK_HELP
|
||||
NICK_HELP_SET
|
||||
NICK_SERVADMIN_HELP
|
||||
OPER_ADMIN_LIST_HEADER
|
||||
OPER_HELP
|
||||
OPER_HELP_ADMIN
|
||||
OPER_HELP_OPER
|
||||
OPER_OPER_LIST_HEADER
|
||||
|
||||
Deleted strings:
|
||||
BOT_KICK_NO_COLORS
|
||||
NICK_HELP_EXPIRE_ZERO
|
||||
OPER_ADMIN_ADD_SYNTAX
|
||||
OPER_ADMIN_DEL_SYNTAX
|
||||
OPER_ADMIN_REMOVED
|
||||
OPER_ADMIN_TOO_MANY
|
||||
OPER_OPER_ADD_SYNTAX
|
||||
OPER_OPER_DEL_SYNTAX
|
||||
OPER_OPER_REMOVED
|
||||
OPER_OPER_TOO_MANY
|
||||
|
||||
Epona Version 1.1.x
|
||||
-------------------
|
||||
New strings:
|
||||
BOT_BADWORDS_CLEAR
|
||||
BOT_HELP_SET_GREET
|
||||
BOT_INFO_OPT_GREET
|
||||
CHAN_ACCESS_CLEAR
|
||||
CHAN_AKICK_VIEW_FORMAT
|
||||
CHAN_AKICK_CLEAR
|
||||
CHAN_FORBID_SYNTAX_REASON
|
||||
CHAN_HELP
|
||||
CHAN_HELP_DEVOICE
|
||||
CHAN_HELP_DEHALFOP
|
||||
CHAN_HELP_DEPROTECT
|
||||
CHAN_HELP_GETKEY
|
||||
CHAN_HELP_HALFOP
|
||||
CHAN_HELP_PROTECT
|
||||
CHAN_HELP_SET_BANTYPE
|
||||
CHAN_HELP_SET_SECUREFOUNDER
|
||||
CHAN_HELP_UNREAL
|
||||
CHAN_HELP_VOICE
|
||||
CHAN_INFO_BANTYPE
|
||||
CHAN_INFO_OPT_SECUREFOUNDER
|
||||
CHAN_LEVEL_AUTOHALFOP
|
||||
CHAN_LEVEL_AUTOPROTECT
|
||||
CHAN_LEVEL_GETKEY
|
||||
CHAN_LEVEL_GREET
|
||||
CHAN_LEVEL_HALFOPME
|
||||
CHAN_LEVEL_HALFOP
|
||||
CHAN_LEVEL_OPDEOPME
|
||||
CHAN_LEVEL_PROTECTME
|
||||
CHAN_LEVEL_PROTECT
|
||||
CHAN_LEVEL_VOICEME
|
||||
CHAN_LEVEL_VOICE
|
||||
CHAN_LIST_SERVADMIN_SYNTAX
|
||||
CHAN_SET_BANTYPE_INVALID
|
||||
CHAN_SET_BANTYPE_CHANGED
|
||||
CHAN_SET_MLOCK_FLOOD_REQUIRED
|
||||
CHAN_SET_MLOCK_REDIRECT_REQUIRED
|
||||
CHAN_SET_MLOCK_L_REQUIRED
|
||||
CHAN_SET_SECUREFOUNDER_SYNTAX
|
||||
CHAN_SET_SECUREFOUNDER_ON
|
||||
CHAN_SET_SECUREFOUNDER_OFF
|
||||
CHAN_X_FORBIDDEN_OPER
|
||||
MEMO_HELP_CANCEL
|
||||
MEMO_CANCEL_SYNTAX
|
||||
MEMO_CANCEL_DISABLED
|
||||
MEMO_CANCEL_NONE
|
||||
MEMO_CANCELLED
|
||||
NICK_FORBID_SYNTAX_REASON
|
||||
NICK_HELP_SET_GREET
|
||||
NICK_INFO_GREET
|
||||
NICK_INFO_LINKED_TO
|
||||
NICK_SET_GREET_CHANGED
|
||||
NICK_SET_GREET_UNSET
|
||||
NICK_X_FORBIDDEN_OPER
|
||||
NO_REASON
|
||||
OPER_HELP_SET_NOEXPIRE
|
||||
OPER_SET_READONLY_ON
|
||||
OPER_SET_READONLY_OFF
|
||||
OPER_SET_READONLY_ERROR
|
||||
OPER_STATS_RESET
|
||||
UNKNOWN
|
||||
|
||||
Modified strings:
|
||||
BOT_BADWORDS_SYNTAX
|
||||
BOT_BADWORDS_LIST_FORMAT
|
||||
BOT_HELP_BADWORDS
|
||||
BOT_HELP_SET
|
||||
CHAN_ACCESS_SYNTAX
|
||||
CHAN_AKICK_SYNTAX
|
||||
CHAN_FORBID_SYNTAX
|
||||
CHAN_HELP
|
||||
CHAN_HELP_ACCESS
|
||||
CHAN_HELP_AKICK
|
||||
CHAN_HELP_FORBID
|
||||
CHAN_HELP_SET
|
||||
CHAN_SERVADMIN_HELP_LIST
|
||||
MEMO_HELP
|
||||
NICK_FORBID_SYNTAX
|
||||
NICK_HELP_FORBID
|
||||
NICK_HELP_SET
|
||||
OPER_HELP_SET
|
||||
OPER_HELP_STATS
|
||||
NICK_LIST_SERVADMIN_SYNTAX
|
||||
|
||||
Deleted strings:
|
||||
OPER_HELP_ROTATELOG
|
||||
OPER_ROTATELOG_*
|
||||
|
||||
Epona Version 1.0x
|
||||
------------------
|
||||
Deleted strings:
|
||||
CHAN_OP_SYNTAX
|
||||
CHAN_DEOP_SYNTAX
|
||||
DISCONNECT_IN_1_MINUTE
|
||||
DISCONNECT_IN_20_SECONDS
|
||||
DISCONNECT_NOW
|
||||
|
||||
Modified strings:
|
||||
CHAN_HELP_OP
|
||||
CHAN_HELP_DEOP
|
||||
NICK_HELP_REGISTER
|
||||
NICK_HELP_SET
|
||||
NICK_HELP_SET_KILL
|
||||
NICK_INFO_OPT_KILL
|
||||
NICK_REGISTER_SYNTAX
|
||||
NICK_SET_KILL_ON
|
||||
NICK_SET_KILL_QUICK
|
||||
NICK_SET_KILL_IMMED
|
||||
NICK_SET_KILL_OFF
|
||||
|
||||
New strings:
|
||||
BOT_DOES_NOT_EXIST
|
||||
BOT_NOT_ASSIGNED
|
||||
BOT_NOT_ON_CHANNEL
|
||||
BOT_REASON_BADWORD
|
||||
BOT_REASON_BOLD
|
||||
BOT_REASON_CAPS
|
||||
BOT_REASON_COLOR
|
||||
BOT_REASON_FLOOD
|
||||
BOT_REASON_REPEAT
|
||||
BOT_REASON_REVERSE
|
||||
BOT_REASON_UNDERLINE
|
||||
BOT_BOT_SYNTAX
|
||||
BOT_BOT_ALREADY_EXISTS
|
||||
BOT_BOT_CREATION_FAILED
|
||||
BOT_BOT_READONLY
|
||||
BOT_BOT_ADDED
|
||||
BOT_BOT_ANY_CHANGES
|
||||
BOT_BOT_CHANGED
|
||||
BOT_BOT_DELETED
|
||||
BOT_BOTLIST_HEADER
|
||||
BOT_BOTLIST_EMPTY
|
||||
BOT_ASSIGN_SYNTAX
|
||||
BOT_ASSIGN_READONLY
|
||||
BOT_ASSIGN_ALREADY
|
||||
BOT_ASSIGN_ASSIGNED
|
||||
BOT_UNASSIGN_SYNTAX
|
||||
BOT_UNASSIGN_UNASSIGNED
|
||||
BOT_INFO_SYNTAX
|
||||
BOT_INFO_NOT_FOUND
|
||||
BOT_INFO_BOT_HEADER
|
||||
BOT_INFO_BOT_MASK
|
||||
BOT_INFO_BOT_REALNAME
|
||||
BOT_INFO_BOT_CREATED
|
||||
BOT_INFO_BOT_USAGE
|
||||
BOT_INFO_CHAN_HEADER
|
||||
BOT_INFO_CHAN_BOT
|
||||
BOT_INFO_CHAN_BOT_NONE
|
||||
BOT_INFO_CHAN_KICK_BADWORDS
|
||||
BOT_INFO_CHAN_KICK_BOLDS
|
||||
BOT_INFO_CHAN_KICK_CAPS_ON
|
||||
BOT_INFO_CHAN_KICK_CAPS_OFF
|
||||
BOT_INFO_CHAN_KICK_COLORS
|
||||
BOT_INFO_CHAN_KICK_FLOOD_ON
|
||||
BOT_INFO_CHAN_KICK_FLOOD_OFF
|
||||
BOT_INFO_CHAN_KICK_REPEAT_ON
|
||||
BOT_INFO_CHAN_KICK_REPEAT_OFF
|
||||
BOT_INFO_CHAN_KICK_REVERSES
|
||||
BOT_INFO_CHAN_KICK_UNDERLINES
|
||||
BOT_INFO_CHAN_KICK_BADWORDS_BAN
|
||||
BOT_INFO_CHAN_KICK_BOLDS_BAN
|
||||
BOT_INFO_CHAN_KICK_CAPS_BAN
|
||||
BOT_INFO_CHAN_KICK_COLORS_BAN
|
||||
BOT_INFO_CHAN_KICK_FLOOD_BAN
|
||||
BOT_INFO_CHAN_KICK_REPEAT_BAN
|
||||
BOT_INFO_CHAN_KICK_REVERSES_BAN
|
||||
BOT_INFO_CHAN_KICK_UNDERLINES_BAN
|
||||
BOT_INFO_ACTIVE
|
||||
BOT_INFO_INACTIVE
|
||||
BOT_INFO_CHAN_OPTIONS
|
||||
BOT_INFO_OPT_DONTKICKOPS
|
||||
BOT_INFO_OPT_DONTKICKVOICES
|
||||
BOT_INFO_OPT_FANTASY
|
||||
BOT_INFO_OPT_SYMBIOSIS
|
||||
BOT_INFO_OPT_NONE
|
||||
BOT_SET_SYNTAX
|
||||
BOT_SET_DISABLED
|
||||
BOT_SET_UNKNOWN
|
||||
BOT_SET_DONTKICKOPS_SYNTAX
|
||||
BOT_SET_DONTKICKOPS_ON
|
||||
BOT_SET_DONTKICKOPS_OFF
|
||||
BOT_SET_DONTKICKVOICES_SYNTAX
|
||||
BOT_SET_DONTKICKVOICES_ON
|
||||
BOT_SET_DONTKICKVOICES_OFF
|
||||
BOT_SET_FANTASY_SYNTAX
|
||||
BOT_SET_FANTASY_ON
|
||||
BOT_SET_FANTASY_OFF
|
||||
BOT_SET_SYMBIOSIS_SYNTAX
|
||||
BOT_SET_SYMBIOSIS_ON
|
||||
BOT_SET_SYMBIOSIS_OFF
|
||||
BOT_KICK_SYNTAX
|
||||
BOT_KICK_DISABLED
|
||||
BOT_KICK_UNKNOWN
|
||||
BOT_KICK_NO_COLORS
|
||||
BOT_KICK_BAD_TTB
|
||||
BOT_KICK_BADWORDS_ON
|
||||
BOT_KICK_BADWORDS_ON_BAN
|
||||
BOT_KICK_BADWORDS_OFF
|
||||
BOT_KICK_BOLDS_ON
|
||||
BOT_KICK_BOLDS_ON_BAN
|
||||
BOT_KICK_BOLDS_OFF
|
||||
BOT_KICK_CAPS_ON
|
||||
BOT_KICK_CAPS_ON_BAN
|
||||
BOT_KICK_CAPS_OFF
|
||||
BOT_KICK_COLORS_ON
|
||||
BOT_KICK_COLORS_ON_BAN
|
||||
BOT_KICK_COLORS_OFF
|
||||
BOT_KICK_FLOOD_ON
|
||||
BOT_KICK_FLOOD_ON_BAN
|
||||
BOT_KICK_FLOOD_OFF
|
||||
BOT_KICK_REPEAT_ON
|
||||
BOT_KICK_REPEAT_ON_BAN
|
||||
BOT_KICK_REPEAT_OFF
|
||||
BOT_KICK_REVERSES_ON
|
||||
BOT_KICK_REVERSES_ON_BAN
|
||||
BOT_KICK_REVERSES_OFF
|
||||
BOT_KICK_UNDERLINES_ON
|
||||
BOT_KICK_UNDERLINES_ON_BAN
|
||||
BOT_KICK_UNDERLINES_OFF
|
||||
BOT_BADWORDS_SYNTAX
|
||||
BOT_BADWORDS_DISABLED
|
||||
BOT_BADWORDS_REACHED_LIMIT
|
||||
BOT_BADWORDS_ALREADY_EXISTS
|
||||
BOT_BADWORDS_ADDED
|
||||
BOT_BADWORDS_NO_SUCH_ENTRY
|
||||
BOT_BADWORDS_NOT_FOUND
|
||||
BOT_BADWORDS_NO_MATCH
|
||||
BOT_BADWORDS_DELETED
|
||||
BOT_BADWORDS_DELETED_ONE
|
||||
BOT_BADWORDS_DELETED_SEVERAL
|
||||
BOT_BADWORDS_LIST_EMPTY
|
||||
BOT_BADWORDS_LIST_HEADER
|
||||
BOT_BADWORDS_LIST_FORMAT
|
||||
BOT_SAY_SYNTAX
|
||||
BOT_ACT_SYNTAX
|
||||
BOT_HELP
|
||||
BOT_HELP_BOTLIST
|
||||
BOT_HELP_ASSIGN
|
||||
BOT_HELP_UNASSIGN
|
||||
BOT_HELP_INFO
|
||||
BOT_HELP_SET
|
||||
BOT_HELP_SET_DONTKICKOPS
|
||||
BOT_HELP_SET_DONTKICKVOICES
|
||||
BOT_HELP_SET_FANTASY
|
||||
BOT_HELP_SET_SYMBIOSIS
|
||||
BOT_HELP_KICK
|
||||
BOT_HELP_KICK_BADWORDS
|
||||
BOT_HELP_KICK_BOLDS
|
||||
BOT_HELP_KICK_CAPS
|
||||
BOT_HELP_KICK_COLORS
|
||||
BOT_HELP_KICK_FLOOD
|
||||
BOT_HELP_KICK_REPEAT
|
||||
BOT_HELP_KICK_REVERSES
|
||||
BOT_HELP_KICK_UNDERLINES
|
||||
BOT_HELP_BADWORDS
|
||||
BOT_HELP_SAY
|
||||
BOT_HELP_ACT
|
||||
BOT_SERVADMIN_HELP
|
||||
BOT_SERVADMIN_HELP_BOT
|
||||
CHAN_LEVEL_ASSIGN
|
||||
CHAN_LEVEL_BADWORDS
|
||||
CHAN_LEVEL_FANTASIA
|
||||
CHAN_LEVEL_NOKICK
|
||||
CHAN_SENDPASS_SYNTAX
|
||||
CHAN_SENDPASS_UNAVAILABLE
|
||||
CHAN_SENDPASS_SUBJECT
|
||||
CHAN_SENDPASS_HEAD
|
||||
CHAN_SENDPASS_LINE_1
|
||||
CHAN_SENDPASS_LINE_2
|
||||
CHAN_SENDPASS_LINE_3
|
||||
CHAN_SENDPASS_LINE_4
|
||||
CHAN_SENDPASS_LINE_5
|
||||
CHAN_SENDPASS_OK
|
||||
HELP_HELP
|
||||
MAIL_DISABLED
|
||||
MAIL_INVALID
|
||||
MAIL_LATER
|
||||
NICK_REGISTER_SYNTAX_EMAIL
|
||||
NICK_IDENTIFY_EMAIL_REQUIRED
|
||||
NICK_SET_EMAIL_UNSET_IMPOSSIBLE
|
||||
NICK_SENDPASS_SYNTAX
|
||||
NICK_SENDPASS_UNAVAILABLE
|
||||
NICK_SENDPASS_SUBJECT
|
||||
NICK_SENDPASS_HEAD
|
||||
NICK_SENDPASS_LINE_1
|
||||
NICK_SENDPASS_LINE_2
|
||||
NICK_SENDPASS_LINE_3
|
||||
NICK_SENDPASS_LINE_4
|
||||
NICK_SENDPASS_LINE_5
|
||||
NICK_SENDPASS_OK
|
||||
OPER_STATS_BOTSERV_MEM
|
||||
OPER_CHANLIST_HEADER
|
||||
OPER_CHANLIST_RECORD
|
||||
OPER_CHANLIST_END
|
||||
OPER_USERLIST_HEADER
|
||||
OPER_USERLIST_HEADER_CHAN
|
||||
OPER_USERLIST_RECORD
|
||||
OPER_USERLIST_END
|
||||
OPER_HELP_CHANLIST
|
||||
OPER_HELP_USERLIST
|
||||
|
||||
Version 4.3
|
||||
-----------
|
||||
Modified strings:
|
||||
DISCONNECT_NOW
|
||||
NICK_INFO_SYNTAX
|
||||
CHAN_AKICK_SYNTAX
|
||||
CHAN_INFO_SYNTAX
|
||||
NICK_HELP_INFO
|
||||
CHAN_HELP_SET
|
||||
CHAN_HELP_AKICK
|
||||
CHAN_HELP_INFO
|
||||
OPER_HELP
|
||||
|
||||
New strings:
|
||||
BAD_EXPIRY_TIME
|
||||
FORCENICKCHANGE_...
|
||||
NICK_INFO_ADDRESS_ONLINE...
|
||||
CHAN_AKICK_ENFORCE_DONE
|
||||
CHAN_INFO_SUCCESSOR
|
||||
CHAN_INFO_NO_SUCCESSOR
|
||||
CHAN_INFO_ENTRYMSG
|
||||
CHAN_INFO_NO_EXPIRE
|
||||
OPER_STATS_BYTES_...
|
||||
OPER_STATS_SESSIONS_MEM
|
||||
OPER_KILLCLONES_...
|
||||
OPER_ROTATELOG_...
|
||||
OPER_EXCEPTION_...
|
||||
OPER_SESSION_...
|
||||
OPER_HELP_EXCEPTION
|
||||
OPER_HELP_SESSION
|
||||
NICK_SERVADMIN_HELP_INFO
|
||||
CHAN_SERVADMIN_HELP_INFO
|
||||
OPER_HELP_KILLCLONES
|
||||
OPER_HELP_ROTATELOG
|
||||
@@ -0,0 +1,174 @@
|
||||
# Makefile for Epona.
|
||||
#
|
||||
# Epona (c) 2000-2002 PegSoft
|
||||
# Contact us at epona@pegsoft.net
|
||||
#
|
||||
# This program is free but copyrighted software; see the file COPYING for
|
||||
# details.
|
||||
#
|
||||
# Based on the original code of Services by Andy Church.
|
||||
|
||||
include Makefile.inc
|
||||
|
||||
###########################################################################
|
||||
########################## Configuration section ##########################
|
||||
|
||||
# Note that changing any of these options (or, in fact, anything in this
|
||||
# file) will automatically cause a full rebuild of Services.
|
||||
|
||||
# Compilation options:
|
||||
# -DCLEAN_COMPILE Attempt to compile without any warnings (note that
|
||||
# this may reduce performance)
|
||||
# -DSTREAMLINED Leave out "fancy" options to enhance performance
|
||||
|
||||
CDEFS =
|
||||
|
||||
# Add any extra flags you want here. The default line enables warnings and
|
||||
# debugging symbols on GCC. If you have a non-GCC compiler, you may want
|
||||
# to comment it out or change it.
|
||||
|
||||
MORE_CFLAGS = -Wall -g
|
||||
|
||||
|
||||
######################## End configuration section ########################
|
||||
###########################################################################
|
||||
|
||||
|
||||
CFLAGS = $(CDEFS) $(BASE_CFLAGS) $(MORE_CFLAGS)
|
||||
|
||||
|
||||
OBJS = actions.o botserv.o channels.o chanserv.o commands.o compat.o converter.o \
|
||||
config.o datafiles.o encrypt.o helpserv.o hostserv.o init.o language.o list.o log.o mail.o main.o \
|
||||
memory.o memoserv.o messages.o misc.o modules.o news.o nickserv.o operserv.o \
|
||||
process.o protocol.o proxy.o send.o sessions.o slist.o sockutil.o \
|
||||
timeout.o users.o \
|
||||
$(VSNPRINTF_O) $(RDB_O) $(MYSQL_O)
|
||||
SRCS = actions.c botserv.c channels.c chanserv.c commands.c compat.c converter.c \
|
||||
config.c datafiles.c encrypt.c helpserv.c hostserv.c init.c language.c list.c log.c mail.c main.c \
|
||||
memory.c memoserv.c messages.c misc.c modules.c news.c nickserv.c operserv.c \
|
||||
process.c protocol.c proxy.c send.c sessions.c slist.c sockutil.c \
|
||||
timeout.c users.c \
|
||||
$(VSNPRINTF_C) $(RDB_C) $(MYSQL_C)
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
|
||||
all: $(PROGRAM) languages modules
|
||||
@echo Now run \"$(MAKE) install\" to install Services.
|
||||
|
||||
myclean:
|
||||
rm -f *.o $(PROGRAM) a.out
|
||||
|
||||
|
||||
clean: myclean
|
||||
(cd lang ; $(MAKE) spotless)
|
||||
rm -f language.h
|
||||
(cd modules ; $(MAKE) clean)
|
||||
|
||||
spotless: myclean
|
||||
(cd lang ; $(MAKE) spotless)
|
||||
(cd modules ; rm -f *.so Makefile.inc)
|
||||
rm -f config.cache configure.log sysconf.h Makefile.inc language.h version.h *~
|
||||
|
||||
distclean: spotless
|
||||
|
||||
install: $(PROGRAM) languages
|
||||
$(INSTALL) services $(BINDEST)/services
|
||||
rm -f $(BINDEST)/listnicks $(BINDEST)/listchans
|
||||
ln $(BINDEST)/services $(BINDEST)/listnicks
|
||||
ln $(BINDEST)/services $(BINDEST)/listchans
|
||||
(cd lang ; $(MAKE) install)
|
||||
$(CP_ALL) data/* $(DATDEST)
|
||||
test -d $(DATDEST)/backups || mkdir $(DATDEST)/backups
|
||||
test -d $(DATDEST)/logs || mkdir $(DATDEST)/logs
|
||||
@if [ "$(MODULE_PATH)" ] ; then \
|
||||
(cd modules ; $(MAKE) install) ; \
|
||||
fi
|
||||
@if [ "$(RUNGROUP)" ] ; then \
|
||||
echo chgrp -R $(RUNGROUP) $(DATDEST) ; \
|
||||
chgrp -R $(RUNGROUP) $(DATDEST) ; \
|
||||
echo chmod -R g+rw $(DATDEST) ; \
|
||||
chmod -R g+rw $(DATDEST) ; \
|
||||
echo find $(DATDEST) -type d -exec chmod g+xs \'\{\}\' \\\; ; \
|
||||
find $(DATDEST) -type d -exec chmod g+xs '{}' \; ; \
|
||||
fi
|
||||
@echo ""
|
||||
@echo "Don't forget to create/update your services.conf file! See"
|
||||
@echo "the README for details."
|
||||
@echo ""
|
||||
|
||||
###########################################################################
|
||||
|
||||
$(PROGRAM): version.h $(OBJS)
|
||||
$(CC) $(LFLAGS) $(OBJS) $(LIBS) $(MLIBS) -o $@ $(ELIBS)
|
||||
|
||||
languages: FRC
|
||||
(cd lang ; $(MAKE) CFLAGS="$(CFLAGS)")
|
||||
|
||||
modules: FRC
|
||||
@if [ "$(MODULE_PATH)" ] ; then \
|
||||
(cd modules ; ./configure ; $(MAKE) CFLAGS="$(CFLAGS)") \
|
||||
fi
|
||||
|
||||
# Catch any changes in compilation options at the top of this file
|
||||
$(OBJS): Makefile
|
||||
|
||||
actions.o: actions.c services.h
|
||||
botserv.o: botserv.c services.h pseudo.h
|
||||
channels.o: channels.c services.h
|
||||
chanserv.o: chanserv.c services.h pseudo.h
|
||||
commands.o: commands.c services.h commands.h language.h
|
||||
compat.o: compat.c services.h
|
||||
config.o: config.c services.h
|
||||
converter.o: converter.c services.h datafiles.h
|
||||
datafiles.o: datafiles.c services.h datafiles.h
|
||||
encrypt.o: encrypt.c encrypt.h sysconf.h
|
||||
init.o: init.c services.h
|
||||
hostserv.o: hostserv.c services.h pseudo.h
|
||||
language.o: language.c services.h language.h
|
||||
list.o: list.c services.h
|
||||
log.o: log.c services.h pseudo.h
|
||||
mail.o: mail.c services.h language.h
|
||||
main.o: main.c services.h timeout.h version.h
|
||||
memory.o: memory.c services.h
|
||||
memoserv.o: memoserv.c services.h pseudo.h
|
||||
messages.o: messages.c services.h messages.h language.h
|
||||
misc.o: misc.c services.h language.h
|
||||
news.o: news.c services.h pseudo.h
|
||||
nickserv.o: nickserv.c services.h pseudo.h
|
||||
operserv.o: operserv.c services.h pseudo.h
|
||||
process.o: process.c services.h messages.h
|
||||
protocol.o: protocol.c services.h
|
||||
proxy.o: proxy.c services.h pseudo.h
|
||||
send.o: send.c services.h
|
||||
sessions.o: sessions.c services.h pseudo.h
|
||||
slist.o: slist.c services.h slist.h
|
||||
sockutil.o: sockutil.c services.h
|
||||
timeout.o: timeout.c services.h timeout.h
|
||||
users.o: users.c services.h
|
||||
vsnprintf.o: vsnprintf.c
|
||||
|
||||
|
||||
services.h: sysconf.h config.h extern.h
|
||||
touch $@
|
||||
|
||||
extern.h: slist.h
|
||||
touch $@
|
||||
|
||||
pseudo.h: commands.h language.h timeout.h encrypt.h datafiles.h slist.h
|
||||
touch $@
|
||||
|
||||
version.h: Makefile version.sh version.log services.h pseudo.h messages.h $(SRCS)
|
||||
sh version.sh
|
||||
|
||||
language.h: lang/language.h
|
||||
cp -p lang/language.h .
|
||||
|
||||
lang/language.h: lang/Makefile lang/index
|
||||
(cd lang ; $(MAKE) language.h)
|
||||
|
||||
|
||||
###########################################################################
|
||||
|
||||
FRC:
|
||||
@@ -0,0 +1,93 @@
|
||||
/* Various routines to perform simple actions.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: actions.c,v 1.6 2003/07/20 01:15:49 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "services.h"
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Note a bad password attempt for the given user. If they've used up
|
||||
* their limit, toss them off.
|
||||
*/
|
||||
|
||||
void bad_password(User * u)
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
|
||||
if (!BadPassLimit)
|
||||
return;
|
||||
|
||||
if (BadPassTimeout > 0 && u->invalid_pw_time > 0
|
||||
&& u->invalid_pw_time < now - BadPassTimeout)
|
||||
u->invalid_pw_count = 0;
|
||||
u->invalid_pw_count++;
|
||||
u->invalid_pw_time = now;
|
||||
if (u->invalid_pw_count >= BadPassLimit)
|
||||
#ifdef IRC_BAHAMUT
|
||||
send_cmd(NULL, "SVSKILL %s :%s", u->nick,
|
||||
"Too many invalid passwords");
|
||||
#else
|
||||
kill_user(NULL, u->nick, "Too many invalid passwords");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void change_user_mode(User * u, char *modes, char *arg)
|
||||
{
|
||||
#ifndef IRC_HYBRID
|
||||
int ac = 1;
|
||||
char *av[2];
|
||||
|
||||
av[0] = modes;
|
||||
if (arg) {
|
||||
av[1] = arg;
|
||||
ac++;
|
||||
}
|
||||
#ifdef IRC_BAHAMUT
|
||||
send_cmd(ServerName, "SVSMODE %s %ld %s%s%s", u->nick, u->timestamp,
|
||||
av[0], (ac == 2 ? " " : ""), (ac == 2 ? av[1] : ""));
|
||||
#else
|
||||
send_cmd(ServerName, "SVSMODE %s %s%s%s", u->nick, av[0],
|
||||
(ac == 2 ? " " : ""), (ac == 2 ? av[1] : ""));
|
||||
#endif
|
||||
set_umode(u, ac, av);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Remove a user from the IRC network. `source' is the nick which should
|
||||
* generate the kill, or NULL for a server-generated kill.
|
||||
*/
|
||||
|
||||
void kill_user(const char *source, const char *user, const char *reason)
|
||||
{
|
||||
char *av[2];
|
||||
char buf[BUFSIZE];
|
||||
|
||||
if (!user || !*user)
|
||||
return;
|
||||
if (!source || !*source)
|
||||
source = ServerName;
|
||||
if (!reason)
|
||||
reason = "";
|
||||
snprintf(buf, sizeof(buf), "%s (%s)", source, reason);
|
||||
av[0] = sstrdup(user);
|
||||
av[1] = buf;
|
||||
send_cmd(source, "KILL %s :%s", user, av[1]);
|
||||
do_kill(source, 2, av);
|
||||
free(av[0]);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# $Id: checklang,v 1.1 2003/07/16 04:34:04 dane Exp $
|
||||
#
|
||||
|
||||
if [ ! -f en_us.l ]; then
|
||||
echo "*** You must run this script on the lang directory."
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for lang in $(ls *.l)
|
||||
do
|
||||
echo "*** CHECKING $lang ***"
|
||||
./obs.pl $lang
|
||||
done
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ $1 = "-t" ] ; then
|
||||
shift
|
||||
fi
|
||||
if [ ! "$2" ] ; then
|
||||
echo >&2 Usage: $0 '<sourcedir> <targetdir>'
|
||||
exit 1
|
||||
fi
|
||||
if [ -d "$1" ] ; then
|
||||
dir="$1"
|
||||
else
|
||||
dir="`echo $1 | sed 's#\(.*\)/.*#\1#'`"
|
||||
fi
|
||||
while [ "$2" ] ; do
|
||||
shift
|
||||
done
|
||||
if [ ! -d $1 ] ; then
|
||||
mkdir -p $1 || exit 1
|
||||
fi
|
||||
/bin/tar -Ccf $dir - . | /bin/tar -Cxf $1 -
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# $Id: fixlang,v 1.1 2003/07/16 04:34:04 dane Exp $
|
||||
#
|
||||
|
||||
if [ ! -f en_us.l ]; then
|
||||
echo "*** You must run this script on the lang directory."
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for lang in $(ls *.l)
|
||||
do
|
||||
echo "*** CHECKING $lang ***"
|
||||
./fixlang.pl $lang
|
||||
mv fixed.l $lang
|
||||
done
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# $Id: getanope,v 1.2 2003/11/24 20:23:28 dane Exp $
|
||||
#
|
||||
|
||||
MODULE="anope-dev"
|
||||
BRANCH=""
|
||||
|
||||
if [ "$1" == "" ]; then
|
||||
DST="$MODULE"
|
||||
else
|
||||
DST="$1"
|
||||
fi
|
||||
|
||||
let cnt="$(echo $CVSROOT | grep anope | wc -l)"
|
||||
if [ $cnt -eq 0 ]; then
|
||||
echo "*** Environment variable CVSROOT is not set. Please set it"
|
||||
echo "*** if you have a developer account with write access."
|
||||
echo ""
|
||||
echo "*** Assuming anonymous access. If prompted for a password,"
|
||||
echo "*** just press RETURN to continue."
|
||||
echo ""
|
||||
export CVSROOT=":pserver:pubcvs@zero.org:/home/cvs/anope"
|
||||
|
||||
let login="$(grep "pubcvs@zero.org" ~/.cvspass 2> /dev/null | grep anope | wc -l)"
|
||||
|
||||
if [ $login -eq 0 ]; then
|
||||
cvs -d$CVSROOT login
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Checking out $MODULE"
|
||||
|
||||
if [ "$BRANCH" == "" ]; then
|
||||
cvs -z3 -d$CVSROOT checkout -d$DST $MODULE
|
||||
else
|
||||
cvs -z3 -d$CVSROOT checkout -r$BRANCH -d$DST $MODULE
|
||||
fi
|
||||
|
||||
echo "*** All done!"
|
||||
|
||||
exit 0
|
||||
Executable
+239
@@ -0,0 +1,239 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# Ribosome's all in one language tool
|
||||
# 1) Compares to check for missing lines
|
||||
# 2) Compares to check for equal lines
|
||||
# 3) Fixes (on request) missing lines
|
||||
# 4) Checks for errors in lines
|
||||
# 5) Checks for long lines (>60 characters)
|
||||
#
|
||||
|
||||
# Check to see if we have received arguments
|
||||
if (!$ARGV[0]) {
|
||||
print "Usage: $0 [language file]\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
# If yes, set $sourcefile to the language filename
|
||||
$testagainst = $ARGV[0];
|
||||
|
||||
# Set $sourcefile to en_us language file
|
||||
$sourcefile = "en_us.l";
|
||||
|
||||
# Number of Keys in File, Number of Equal Lines, Number of Missing Lines
|
||||
# Fixed Lines (optional) and Number of Format Error Lines, Number of Long Lines
|
||||
my $numberlines = 0;
|
||||
my $equallines = 0;
|
||||
my $missinglines = 0;
|
||||
my $fixedlines = 0;
|
||||
my $errorline = 0;
|
||||
my $longlines = 0;
|
||||
|
||||
# Array to hold the lines from the source file and explosion array for long line check
|
||||
|
||||
my @sourcearray;
|
||||
my @explosion;
|
||||
|
||||
# Create associative arrays which will contain keys and definitions
|
||||
# One for the control source and one for what is being tested against
|
||||
|
||||
my %sourcehash= ();
|
||||
my %testhash= ();
|
||||
|
||||
# Check if Files Exist
|
||||
|
||||
if (! -f $sourcefile) {
|
||||
print "Critical Error: The source file does not exist or is unreadable.\nNote: This tool must be run from the language directory.\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
if (! -f $testagainst) {
|
||||
print "Critical Error: The language file does not exist or is unreadable\n";
|
||||
exit;
|
||||
}
|
||||
###########################################
|
||||
# Function to load sourcefile into memory #
|
||||
###########################################
|
||||
|
||||
sub load_sourcefile {
|
||||
|
||||
my $_key; # This variable will hold the key
|
||||
my $_def; # This variable will hold the definition
|
||||
my $line; # This variable will hold the current line
|
||||
|
||||
open (SOURCEFILE, "< $sourcefile"); # Open the source file
|
||||
while (<SOURCEFILE>) { # For each line the source file
|
||||
$line = $_; # $line is set to the line in the source file
|
||||
|
||||
# Skip comments
|
||||
if (/^#/) { # This checks for # which indicates comment
|
||||
next; # If detected, the next line is skipped to
|
||||
}
|
||||
|
||||
# Start of a key
|
||||
if (/^[A-Z]/) { # Checks to see if the line is a key
|
||||
chomp($line); # Removes things that shouldn't be at the end
|
||||
push (@sourcearray, $line); # Puts the line into the source array
|
||||
# If a key is defined, load definition into the hash
|
||||
if ($_key ne undef) { # If the key is defined
|
||||
$sourcehash{$_key} = $_def; # Add the definition to the associative array
|
||||
}
|
||||
$_key=$line; # Set the key to the line
|
||||
$_def=""; # Reset the definition
|
||||
next; # Move onto the next line
|
||||
}
|
||||
|
||||
if ($_key ne undef) { # If the key is set already
|
||||
$_def.=$line; # The definition is the current line
|
||||
}
|
||||
|
||||
$sourcehash{$_key} = $_def; # Load the definition into the associative array
|
||||
} # End of while which reads lines
|
||||
|
||||
close (SOURCEFILE); # Close the source file
|
||||
|
||||
} # End of load_sourcefile function
|
||||
|
||||
#################################################
|
||||
# Function to load testagainst file into memory #
|
||||
#################################################
|
||||
|
||||
sub load_testagainst {
|
||||
|
||||
my $_key; # This variable will hold the key
|
||||
my $_def; # This variable will hold the definition
|
||||
my $line; # This variable will hold the current line
|
||||
|
||||
open (TESTAGAINSTFILE, "< $testagainst"); # Open the file containing the control lines
|
||||
while (<TESTAGAINSTFILE>) { # For each line in the file
|
||||
$line = $_; # $line is set to the lines value
|
||||
|
||||
|
||||
# Skip comments
|
||||
if (/^#/) { # This checks for # which indicates comment
|
||||
next; # If detected, the next line is skipped to
|
||||
}
|
||||
|
||||
# Start of a key
|
||||
if (/^[A-Z]/) { # Checks to see if the line is a key
|
||||
chomp($line); # Removes things that shouldn't be at the end
|
||||
|
||||
|
||||
if ($_key ne undef) { # If the key is defined
|
||||
$testhash{$_key} = $_def; # Add the definition to the associative array
|
||||
}
|
||||
$_key=$line; # Set the key to the line
|
||||
$_def=""; # Reset the definition
|
||||
next; # Move onto the next line
|
||||
}
|
||||
|
||||
if ($_key ne undef) { # If the key is set already
|
||||
$_def.=$line; # The definition is the current line
|
||||
}
|
||||
|
||||
$testhash{$_key} = $_def; # Load the definition into the associative array
|
||||
} # End of while which reads lines
|
||||
close (TESTAGAINSTFILE); # Close the source file
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub get_format { # Function to get the formatting from a string
|
||||
my $fmt="";
|
||||
my $str=shift; # Get the input
|
||||
|
||||
while ($str =~ m/%\w/g) {
|
||||
$fmt .= $&;
|
||||
}
|
||||
|
||||
return $fmt; # Return the formatting
|
||||
}
|
||||
|
||||
|
||||
load_sourcefile; # Call function to load the source file
|
||||
load_testagainst; # Call function to load the test file
|
||||
|
||||
if (!grep(/^LANG_NAME/,%testhash)) {
|
||||
print "Critical Error: $ARGV[0] is not a valid language file!\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
open (LOG,"> langcheck.log"); # Open logfile for writing
|
||||
|
||||
foreach $sourcearray (@sourcearray) { # For each key stored in the source array
|
||||
my $_key=$_; # Store key from source array in $_key
|
||||
|
||||
if ((get_format($sourcehash{$sourcearray})) ne (get_format($testhash{$sourcearray}))) {
|
||||
if ($sourcearray !~ STRFTIME ) {
|
||||
$errorline++;
|
||||
print LOG "FORMAT: $sourcearray - (expecting '".get_format($sourcehash{$sourcearray})."' and got '".get_format($testhash{$sourcearray})."')\n";
|
||||
} }
|
||||
|
||||
if ($testhash{$sourcearray} eq $sourcehash{$sourcearray} ) {
|
||||
# If the definitions between the source and the test are equal
|
||||
$equallines++; # Number of equal lines increases
|
||||
print LOG "EQUAL: $sourcearray\n"; # Line is written to logfile
|
||||
}
|
||||
|
||||
if (!grep(/^$sourcearray/,%testhash)) { # If the key is found in the testhash associative array
|
||||
$missinglines++; # Increase missing lines
|
||||
print LOG "MISSING: $sourcearray\n"; # Line is written to logfile
|
||||
}
|
||||
|
||||
@explosion = split(/\n/, $testhash{$sourcearray});
|
||||
foreach $explosion (@explosion) {
|
||||
$explosion =~ s/\002//g;
|
||||
$explosion =~ s/\037//g;
|
||||
if (length($explosion) > 61) {
|
||||
print LOG "LONGLINE: $sourcearray (".substr($explosion,1,30)."...)\n";
|
||||
$longlines++;
|
||||
}
|
||||
}
|
||||
|
||||
$numberlines++; # Increase the number of lines tested by 1
|
||||
}
|
||||
close (LOG); # Close the logfile
|
||||
|
||||
|
||||
#########################
|
||||
# Show the test results #
|
||||
#########################
|
||||
|
||||
print "Calculation Results:\n";
|
||||
print "----------------------------------\n";
|
||||
print "[$numberlines] line(s) were compared\n";
|
||||
print "[$equallines] line(s) were found to equal their $sourcefile counterpart(s)\n";
|
||||
print "[$missinglines] line(s) were found to be missing\n";
|
||||
print "[$longlines] line(s) were found to be long (>60 chars)\n";
|
||||
print "[$errorline] line(s) were found to have formatting errors\n";
|
||||
print "The specific details of the test have been saved in langcheck.log\n";
|
||||
|
||||
if ($missinglines) { # If missing lines exist
|
||||
print "----------------------------------\n";
|
||||
print "Missing line(s) have been detected in this test, would you like to fix the file?\n";
|
||||
print "This automatically inserts values from the control file ($sourcefile) for the missing values\n";
|
||||
print "y/N? (Default: No) ";
|
||||
|
||||
my $input = <STDIN>; # Ask if the file should be fixed
|
||||
if ((substr($input,0,1) eq "y") || (substr($input,0,1) eq "Y")) { # If Yes...
|
||||
|
||||
open (FIX, ">> $testagainst"); # Open the file and append changes
|
||||
|
||||
foreach $sourcearray (@sourcearray) { # For each key stored in the source array
|
||||
my $_key=$_; # Store key from source array in $_key
|
||||
|
||||
if (!grep(/^$sourcearray/,%testhash)) { # If the key is not found in the testhash associative array
|
||||
print FIX "$sourcearray\n$sourcehash{$sourcearray}"; # Add the line(s) to the language file
|
||||
$fixedlines++; # Increase the fixed line count
|
||||
}
|
||||
}
|
||||
|
||||
close (FIX); # Close file after fixing
|
||||
|
||||
print "Fixing Compete. [$fixedlines] line(s) fixed.\n";
|
||||
exit; # And Exit!
|
||||
}
|
||||
# Otherwise, quit without fixing
|
||||
print "Exiting. The language file has NOT been fixed.\n";
|
||||
|
||||
}
|
||||
Executable
+83
@@ -0,0 +1,83 @@
|
||||
#!/bin/bash
|
||||
# Daniel Engel (dane@zero.org)
|
||||
#
|
||||
# Creates a patch from any version of Anope to another within the
|
||||
# same CVS module (in this case, anope-rel). Usage:
|
||||
#
|
||||
# ./anope-mkpatch 1.5.1 1.5.5
|
||||
#
|
||||
# The earliest version you can use is 1.5.1 (the first CVS tag)
|
||||
#
|
||||
# Feel free to improve this script at will.
|
||||
#
|
||||
CVSROOT=":pserver:pubcvs@zero.org:/home/cvs/anope"
|
||||
MODULE="anope-dev"
|
||||
OLD="$1"
|
||||
NEW="$2"
|
||||
NAME="$1-$2.diff"
|
||||
|
||||
echo "*** Note: This script is able to create patches from one version of 1.5.x"
|
||||
echo "*** to anoter. The earliest valid version is 1.5.1, and you can only make"
|
||||
echo "*** a patch between two released versions (i.e. no -rnum versions)"
|
||||
echo ""
|
||||
|
||||
if [[ $OLD == "" ]]; then
|
||||
echo "*** Usage: $0 [OLD] [NEW]"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
if [[ $NEW == "" ]]; then
|
||||
echo "*** Usage: $0 [OLD] [NEW]"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
OLD="anope-$OLD"
|
||||
NEW="anope-$NEW"
|
||||
|
||||
if [[ -d $OLD ]]; then
|
||||
echo "*** Directory $OLD already exists... aborting."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ -d $NEW ]]; then
|
||||
echo "*** Directory $OLD already exists... aborting."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "*** Issuing the CVS login, when prompted for a password, just press RETURN..."
|
||||
cvs -d $CVSROOT login
|
||||
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "*** ERROR: CVS login failed... aborting."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
TOLD="$(echo $OLD | sed 's/\./_/g')"
|
||||
TNEW="$(echo $NEW | sed 's/\./_/g')"
|
||||
|
||||
echo "*** Cheking out $MODULE ($TOLD)"
|
||||
cvs -d $CVSROOT checkout -r $TOLD -d $OLD $MODULE > /dev/null 2>&1
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "*** ERROR: Unable to checkout $MODULE ($TNEW)... aborting."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "*** Cheking out $MODULE ($TNEW)"
|
||||
cvs -d $CVSROOT checkout -r $TNEW -d $NEW $MODULE > /dev/null 2>&1
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "*** ERROR: Unable to checkout $MODULE ($TNEW)... aborting."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# I wish i could use cvsrmadm here, but not everybody has it :(
|
||||
echo "*** Removing CVS control files"
|
||||
find $OLD -name CVS -exec rm -rf {} \; > /dev/null 2>&1
|
||||
find $NEW -name CVS -exec rm -rf {} \; > /dev/null 2>&1
|
||||
|
||||
echo "*** Creating the patch..."
|
||||
diff -urN $OLD $NEW > $NAME
|
||||
|
||||
echo "*** Done! The patch is $NAME";
|
||||
echo "*** You might want to clean things up with:"
|
||||
echo "*** rm -rf $OLD $NEW"
|
||||
Executable
+194
@@ -0,0 +1,194 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
|
||||
# Location of the .sql file with the schema
|
||||
DBFILE="data/tables.sql"
|
||||
|
||||
# Schema Version
|
||||
SVER="1"
|
||||
|
||||
# Local Version, defaults to 0
|
||||
LVER="0"
|
||||
|
||||
TFILE="/tmp/.anopedb.$$"
|
||||
|
||||
if [ "`eval echo -n 'a'`" = "-n a" ] ; then
|
||||
c="\c"
|
||||
else
|
||||
n="-n"
|
||||
fi
|
||||
|
||||
if [ ! -f $DBFILE ] ; then
|
||||
echo "Error: Required file $DBFILE is inaccessible!";
|
||||
exit
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "This script will guide you through the process of configuring your Anope"
|
||||
echo "installation to make use of MySQL support. This script must be used for both"
|
||||
echo "new installs as well as for upgrading for users who have a previous version"
|
||||
echo "of Anope installed"
|
||||
|
||||
while [ -z "$SQLHOST" ] ; do
|
||||
echo ""
|
||||
echo "What is the hostname of your MySQL server?"
|
||||
echo $n "-> $c"
|
||||
read cc
|
||||
if [ ! -z "$cc" ] ; then
|
||||
SQLHOST=$cc
|
||||
fi
|
||||
done
|
||||
|
||||
while [ -z "$SQLUSER" ] ; do
|
||||
echo ""
|
||||
echo "What is your MySQL username?"
|
||||
echo $n "-> $c"
|
||||
read cc
|
||||
if [ ! -z "$cc" ] ; then
|
||||
SQLUSER=$cc
|
||||
fi
|
||||
done
|
||||
|
||||
OLD_TTY=`stty -g`
|
||||
|
||||
echo ""
|
||||
echo "What is your MySQL password?"
|
||||
echo $n "-> $c"
|
||||
stty -echo echonl
|
||||
read cc
|
||||
if [ ! -z "$cc" ] ; then
|
||||
SQLPASS=$cc
|
||||
fi
|
||||
stty $OLD_TTY
|
||||
|
||||
mysqlshow -h$SQLHOST -u$SQLUSER -p$SQLPASS >/dev/null 2>&1
|
||||
if test "$?" = "1" ; then
|
||||
echo "Error: Unable to login, verify your login/password and hostname"
|
||||
exit
|
||||
fi
|
||||
|
||||
while [ -z "$SQLDB" ] ; do
|
||||
echo ""
|
||||
echo "What is the name of the Anope SQL database?"
|
||||
echo $n "-> $c"
|
||||
read cc
|
||||
if [ ! -z "$cc" ] ; then
|
||||
SQLDB=$cc
|
||||
fi
|
||||
done
|
||||
|
||||
MYSQLSHOW="mysqlshow -h$SQLHOST -u$SQLUSER -p$SQLPASS $SQLDB"
|
||||
MYSQL="mysql -h$SQLHOST -u$SQLUSER -p$SQLPASS $SQLDB"
|
||||
|
||||
echo ""
|
||||
|
||||
$MYSQLHOW >/dev/null 2>&1
|
||||
if test "$?" = "1" ; then
|
||||
echo "It appears that database does not exist. Or that you don't have the"
|
||||
echo "correct credentials to access it. Please verify that you have entered"
|
||||
echo "the correct values."
|
||||
exit
|
||||
fi
|
||||
|
||||
|
||||
res="$($MYSQL -Bs -e "show tables like 'anope_os_core'" | wc -l)"
|
||||
if test "$res" = "0" ; then
|
||||
echo -n "Unable to find Anope schema, creating... "
|
||||
mysql -h$SQLHOST -u$SQLUSER -p$SQLPASS $SQLDB < $DBFILE
|
||||
if test "$?" = "0" ; then
|
||||
echo "done!"
|
||||
else
|
||||
echo "failed!"
|
||||
FAILED="$FAILED 'schema creation'"
|
||||
fi
|
||||
else
|
||||
# Introduced on Anope 1.6.0 -> Table anope_info
|
||||
res="$($MYSQL -Bs -e "show tables like 'anope_info'" | wc -l)"
|
||||
if test "$res" = "0" ; then
|
||||
echo -n "Unable to find Anope info table, creating... "
|
||||
echo "CREATE TABLE anope_info (version int, date datetime) TYPE=MyISAM" > $TFILE
|
||||
mysql -h$SQLHOST -u$SQLUSER -p$SQLPASS $SQLDB < $TFILE >/dev/null 2>&1
|
||||
if test "$?" = "0" ; then
|
||||
echo "done!"
|
||||
|
||||
else
|
||||
echo "failed!"
|
||||
FAILED="$FAILED 'anope_info table'"
|
||||
fi
|
||||
else
|
||||
LVER="$($MYSQL -sB -e "select version from anope_info")"
|
||||
if test "x$LVER" = "x" ; then
|
||||
LVER=0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Introduced on Anope 1.5.14.5 -> anope_cs_info.memomax
|
||||
res="$($MYSQL -Bs -e "describe anope_cs_info memomax" 2> /dev/null | wc -l)"
|
||||
if test "$res" = "0" ; then
|
||||
echo -n "Unable to find anope_cs_info.memomax, altering... "
|
||||
echo "ALTER TABLE anope_cs_info ADD memomax smallint unsigned NOT NULL default 0" > $TFILE
|
||||
mysql -h$SQLHOST -u$SQLUSER -p$SQLPASS $SQLDB < $TFILE >/dev/null 2>&1
|
||||
if test "$?" = "0" ; then
|
||||
echo "done!"
|
||||
|
||||
else
|
||||
echo "failed!"
|
||||
FAILED="$FAILED 'anope_cs_info.ttb alter'"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Introduced on Anope 1.5.14.5 -> anope_cs_info.ttb
|
||||
res="$($MYSQL -Bs -e "describe anope_cs_info ttb" | wc -l)"
|
||||
if test "$res" = "0" ; then
|
||||
echo -n "Unable to find anope_cs_info.ttb, altering... "
|
||||
echo "ALTER TABLE anope_cs_info ADD ttb smallint NOT NULL default 0" > $TFILE
|
||||
mysql -h$SQLHOST -u$SQLUSER -p$SQLPASS $SQLDB < $TFILE >/dev/null 2>&1
|
||||
if test "$?" = "0" ; then
|
||||
echo "done!"
|
||||
|
||||
else
|
||||
echo "failed!"
|
||||
FAILED="$FAILED 'anope_cs_info.ttb alter'"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
fi
|
||||
|
||||
# Insert initial version number. This will have to be redesigned for 1.7
|
||||
if [ $LVER -ne $SVER ]; then
|
||||
echo -n "Inserting initial version number... "
|
||||
$MYSQL -Bs -e "delete from anope_info"
|
||||
echo "INSERT INTO anope_info (version, date) VALUES ($SVER, now())" > $TFILE
|
||||
$MYSQL < $TFILE >/dev/null 2>&1
|
||||
if test "$?" = "0" ; then
|
||||
echo "done!"
|
||||
else
|
||||
echo "failed!"
|
||||
FAILED="$FAILED 'version insert'"
|
||||
fi
|
||||
fi
|
||||
|
||||
rm -f $TFILE
|
||||
if test "x$FAILED" = "x" ; then
|
||||
# Try to find out more about this installation
|
||||
SQLSOCK="$(mysql_config --socket 2> /dev/null)"
|
||||
SQLPORT="$(mysql_config --port 2> /dev/null)"
|
||||
echo ""
|
||||
echo "Your MySQL setup is complete and your Anope schema is up to date. Make"
|
||||
echo "sure you configure MySQL on your services.conf file prior to launching"
|
||||
echo "Anope with MySQL support. Your configuration values are:"
|
||||
echo ""
|
||||
echo "MysqlHost \"$SQLHOST\""
|
||||
echo "MysqlUser \"$SQLUSER\""
|
||||
echo "MysqlPass \"$SQLPASS\""
|
||||
echo "MysqlName \"$SQLDB\""
|
||||
echo "MysqlSock \"$SQLSOCK\""
|
||||
echo "MysqlPort \"$SQLPORT\""
|
||||
echo ""
|
||||
else
|
||||
echo "The following operations failed:"
|
||||
echo "$FAILED"
|
||||
fi
|
||||
|
||||
exit
|
||||
Executable
+104
@@ -0,0 +1,104 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# $Id: putanope,v 1.14 2003/12/02 23:02:28 joris Exp $
|
||||
#
|
||||
|
||||
CTRL="version.log"
|
||||
MODULE="anope-dev"
|
||||
TMP="/tmp/putanope.$$"
|
||||
TMP2="/tmp/putanope2.$$"
|
||||
|
||||
# We need an editor for the log entry
|
||||
if [ "$EDITOR" == "" ]; then
|
||||
EDITOR="vi"
|
||||
fi
|
||||
|
||||
# Use default target, or provided?
|
||||
if [ "$1" == "" ]; then
|
||||
DST="$MODULE"
|
||||
else
|
||||
DST="$1"
|
||||
fi
|
||||
|
||||
# Find where to run the rest of the script from.
|
||||
if [ ! -d $DST ]; then
|
||||
cd ..
|
||||
if [ ! -d $DST ]; then
|
||||
cd ..
|
||||
if [ ! -d $DST ]; then
|
||||
echo "*** Directory $DST does not exist, what's going on?"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# CVSROOT dosnt need to be set, just read it form the CVS file :-)
|
||||
CVSROOT=`cat ${DST}/CVS/Root`
|
||||
|
||||
cd $DST
|
||||
|
||||
# source control file
|
||||
. $CTRL
|
||||
|
||||
# Version arithmetics
|
||||
CVER="${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}.${VERSION_BUILD}"
|
||||
let minor="$(echo $VERSION_BUILD)"
|
||||
let new="$minor + 1"
|
||||
NVER="${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}.${new}"
|
||||
|
||||
# Greet the developer
|
||||
echo ""
|
||||
echo "*** Using CVSROOT: $CVSROOT"
|
||||
echo "*** Using module : $MODULE"
|
||||
echo "*** Current ver : $CVER"
|
||||
echo "*** Updated ver : $NVER"
|
||||
echo ""
|
||||
echo "*** Make sure you have updated Changes, Changes.conf, and"
|
||||
echo "*** Changes.lang acordingly before you proceed."
|
||||
echo -n "*** Ready to continue? (RETURN if so, CTRL-C otherwise) "
|
||||
read FOO
|
||||
|
||||
cat > $TMP2 <<EOF
|
||||
# Anope commit utility. Please use this template for your commits.
|
||||
# Add Mantis bugs separated by spaces. The note part is free form.
|
||||
BUILD : $NVER
|
||||
BUGS :
|
||||
NOTES :
|
||||
EOF
|
||||
|
||||
$EDITOR $TMP2
|
||||
|
||||
echo "*** Ready to commit, please verify:"
|
||||
echo ""
|
||||
grep -v "^#" $TMP2
|
||||
echo ""
|
||||
echo -n "*** Perform commit? (RETURN if so, CTRL-C otherwise) "
|
||||
read FOO
|
||||
|
||||
echo "*** Running indent..."
|
||||
for source in *.c
|
||||
do
|
||||
indent -kr -nut $source
|
||||
done
|
||||
|
||||
# Clean up indent backup files
|
||||
rm -f *~
|
||||
|
||||
echo "*** Bumping the version number..."
|
||||
sed "s/VERSION_BUILD=\"$VERSION_BUILD\"/VERSION_BUILD=\"$new\"/" $CTRL > $TMP
|
||||
cat $TMP > $CTRL
|
||||
|
||||
TS="$(date '+%F %R')"
|
||||
grep -v "^#" $TMP2 > $TMP
|
||||
echo "VTAG : cvs checkout -D \"$TS\" $MODULE" >> $TMP
|
||||
|
||||
cd ..
|
||||
|
||||
cvs -d$CVSROOT commit -F $TMP $DST
|
||||
|
||||
rm -f $TMP $TMP2
|
||||
|
||||
echo "*** Done!"
|
||||
|
||||
exit 0
|
||||
+1595
File diff suppressed because it is too large
Load Diff
+6187
File diff suppressed because it is too large
Load Diff
+178
@@ -0,0 +1,178 @@
|
||||
/* Routines for looking up commands in a *Serv command list.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: commands.c,v 1.13 2003/09/22 21:40:23 rob Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "services.h"
|
||||
#include "commands.h"
|
||||
#include "language.h"
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Return the Command corresponding to the given name, or NULL if no such
|
||||
* command exists.
|
||||
*/
|
||||
|
||||
Command *lookup_cmd(Command * list, const char *cmd)
|
||||
{
|
||||
Command *c;
|
||||
|
||||
for (c = list; c->name; c++) {
|
||||
if (stricmp(c->name, cmd) == 0)
|
||||
return c;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Run the routine for the given command, if it exists and the user has
|
||||
* privilege to do so; if not, print an appropriate error message.
|
||||
*/
|
||||
|
||||
void run_cmd(const char *service, User * u, Command * list,
|
||||
const char *cmd)
|
||||
{
|
||||
Command *c = lookup_cmd(list, cmd);
|
||||
do_run_cmd(service, u, c, cmd);
|
||||
}
|
||||
|
||||
void mod_run_cmd(const char *service, User * u, CommandHash * cmdTable[],
|
||||
const char *cmd)
|
||||
{
|
||||
Command *c = findCommand(cmdTable, cmd);
|
||||
do_run_cmd(service, u, c, cmd);
|
||||
}
|
||||
|
||||
void do_run_cmd(const char *service, User * u, Command * c,
|
||||
const char *cmd)
|
||||
{
|
||||
int retVal = 0;
|
||||
Command *current;
|
||||
|
||||
if (c && c->routine) {
|
||||
if ((checkDefCon(DEFCON_OPER_ONLY)
|
||||
|| checkDefCon(DEFCON_SILENT_OPER_ONLY)) && !is_oper(u)) {
|
||||
if (!checkDefCon(DEFCON_SILENT_OPER_ONLY)) {
|
||||
notice_lang(service, u, OPER_DEFCON_DENIED);
|
||||
}
|
||||
} else {
|
||||
if ((c->has_priv == NULL) || c->has_priv(u)) {
|
||||
mod_current_module_name = c->mod_name;
|
||||
retVal = c->routine(u);
|
||||
mod_current_module_name = NULL;
|
||||
if (retVal == MOD_CONT) {
|
||||
current = c->next;
|
||||
while (current && retVal == MOD_CONT) {
|
||||
mod_current_module_name = c->mod_name;
|
||||
retVal = current->routine(u);
|
||||
mod_current_module_name = NULL;
|
||||
current = current->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
notice_lang(service, u, ACCESS_DENIED);
|
||||
alog("Access denied for %s with service %s and command %s",
|
||||
u->nick, service, cmd);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((!checkDefCon(DEFCON_SILENT_OPER_ONLY)) || is_oper(u))
|
||||
notice_lang(service, u, UNKNOWN_COMMAND_HELP, cmd, service);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Print a help message for the given command. */
|
||||
|
||||
void do_help_cmd(const char *service, User * u, Command * c,
|
||||
const char *cmd)
|
||||
{
|
||||
Command *current;
|
||||
int has_had_help = 0;
|
||||
int cont = MOD_CONT;
|
||||
const char *p1 = NULL, *p2 = NULL, *p3 = NULL, *p4 = NULL;
|
||||
|
||||
for (current = c; (current) && (cont == MOD_CONT);
|
||||
current = current->next) {
|
||||
p1 = current->help_param1;
|
||||
p2 = current->help_param2;
|
||||
p3 = current->help_param3;
|
||||
p4 = current->help_param4;
|
||||
if (current->helpmsg_all >= 0) {
|
||||
notice_help(service, u, current->helpmsg_all, p1, p2, p3, p4);
|
||||
has_had_help = 1;
|
||||
} else if (current->all_help) {
|
||||
cont = current->all_help(u);
|
||||
has_had_help = 1;
|
||||
}
|
||||
if (is_services_root(u)) {
|
||||
if (current->helpmsg_root >= 0) {
|
||||
notice_help(service, u, current->helpmsg_root, p1, p2, p3,
|
||||
p4);
|
||||
has_had_help = 1;
|
||||
} else if (current->root_help) {
|
||||
cont = current->root_help(u);
|
||||
has_had_help = 1;
|
||||
}
|
||||
} else if (is_services_admin(u)) {
|
||||
if (current->helpmsg_admin >= 0) {
|
||||
notice_help(service, u, current->helpmsg_admin, p1, p2, p3,
|
||||
p4);
|
||||
has_had_help = 1;
|
||||
} else if (current->admin_help) {
|
||||
cont = current->admin_help(u);
|
||||
has_had_help = 1;
|
||||
}
|
||||
} else if (is_services_oper(u)) {
|
||||
if (current->helpmsg_oper >= 0) {
|
||||
notice_help(service, u, current->helpmsg_oper, p1, p2, p3,
|
||||
p4);
|
||||
has_had_help = 1;
|
||||
} else if (current->oper_help) {
|
||||
cont = current->oper_help(u);
|
||||
has_had_help = 1;
|
||||
}
|
||||
} else {
|
||||
if (current->helpmsg_reg >= 0) {
|
||||
notice_help(service, u, current->helpmsg_reg, p1, p2, p3,
|
||||
p4);
|
||||
has_had_help = 1;
|
||||
} else if (current->regular_help) {
|
||||
cont = current->regular_help(u);
|
||||
has_had_help = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (has_had_help == 0) {
|
||||
notice_lang(service, u, NO_HELP_AVAILABLE, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
void help_cmd(const char *service, User * u, Command * list,
|
||||
const char *cmd)
|
||||
{
|
||||
Command *c = lookup_cmd(list, cmd);
|
||||
do_help_cmd(service, u, c, cmd);
|
||||
}
|
||||
|
||||
void mod_help_cmd(const char *service, User * u, CommandHash * cmdTable[],
|
||||
const char *cmd)
|
||||
{
|
||||
Command *c = findCommand(cmdTable, cmd);
|
||||
do_help_cmd(service, u, c, cmd);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/* Declarations for command data.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: commands.h,v 1.6 2003/08/16 22:13:47 rob Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "modules.h"
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Routines for looking up commands. Command lists are arrays that must be
|
||||
* terminated with a NULL name.
|
||||
*/
|
||||
|
||||
extern Command *lookup_cmd(Command *list, const char *name);
|
||||
extern void run_cmd(const char *service, User *u, Command *list,
|
||||
const char *name);
|
||||
extern void help_cmd(const char *service, User *u, Command *list,
|
||||
const char *name);
|
||||
extern void do_run_cmd(const char *service, User * u, Command *c,const char *cmd);
|
||||
extern void do_help_cmd(const char *service, User * u, Command *c,const char *cmd);
|
||||
extern void mod_help_cmd(const char *service, User *u, CommandHash *cmdTable[],const char *cmd);
|
||||
extern void mod_run_cmd(const char *service, User *u, CommandHash *cmdTable[],const char *cmd);
|
||||
|
||||
extern char *mod_current_module_name;
|
||||
/*************************************************************************/
|
||||
@@ -0,0 +1,212 @@
|
||||
/* Compatibility routines.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: compat.c,v 1.5 2003/07/20 01:15:49 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "services.h"
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#if !HAVE_SNPRINTF
|
||||
|
||||
/* [v]snprintf: Like [v]sprintf, but don't write more than len bytes
|
||||
* (including null terminator). Return the number of bytes
|
||||
* written.
|
||||
*/
|
||||
|
||||
#if BAD_SNPRINTF
|
||||
int vsnprintf(char *buf, size_t len, const char *fmt, va_list args)
|
||||
{
|
||||
if (len <= 0)
|
||||
return 0;
|
||||
*buf = 0;
|
||||
#undef vsnprintf
|
||||
vsnprintf(buf, len, fmt, args);
|
||||
#define vsnprintf my_vsnprintf
|
||||
buf[len - 1] = 0;
|
||||
return strlen(buf);
|
||||
}
|
||||
#endif /* BAD_SNPRINTF */
|
||||
|
||||
int snprintf(char *buf, size_t len, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
return vsnprintf(buf, len, fmt, args);
|
||||
}
|
||||
|
||||
#endif /* !HAVE_SNPRINTF */
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#if !HAVE_STRICMP && !HAVE_STRCASECMP
|
||||
|
||||
/* stricmp, strnicmp: Case-insensitive versions of strcmp() and
|
||||
* strncmp().
|
||||
*/
|
||||
|
||||
int stricmp(const char *s1, const char *s2)
|
||||
{
|
||||
register int c;
|
||||
|
||||
while ((c = tolower(*s1)) == tolower(*s2)) {
|
||||
if (c == 0)
|
||||
return 0;
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
if (c < tolower(*s2))
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int strnicmp(const char *s1, const char *s2, size_t len)
|
||||
{
|
||||
register int c;
|
||||
|
||||
if (!len)
|
||||
return 0;
|
||||
while ((c = tolower(*s1)) == tolower(*s2) && len > 0) {
|
||||
if (c == 0 || --len == 0)
|
||||
return 0;
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
if (c < tolower(*s2))
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#if !HAVE_STRDUP
|
||||
char *strdup(const char *s)
|
||||
{
|
||||
char *new = calloc(strlen(s) + 1, 1);
|
||||
if (new)
|
||||
strcpy(new, s);
|
||||
return new;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#if !HAVE_STRSPN
|
||||
size_t strspn(const char *s, const char *accept)
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
while (*s && strchr(accept, *s))
|
||||
++i, ++s;
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#if !HAVE_STRERROR
|
||||
# if HAVE_SYS_ERRLIST
|
||||
extern char *sys_errlist[];
|
||||
# endif
|
||||
|
||||
char *strerror(int errnum)
|
||||
{
|
||||
# if HAVE_SYS_ERRLIST
|
||||
return sys_errlist[errnum];
|
||||
# else
|
||||
static char buf[20];
|
||||
snprintf(buf, sizeof(buf), "Error %d", errnum);
|
||||
return buf;
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#if !HAVE_STRSIGNAL
|
||||
char *strsignal(int signum)
|
||||
{
|
||||
static char buf[32];
|
||||
switch (signum) {
|
||||
case SIGHUP:
|
||||
strscpy(buf, "Hangup", sizeof(buf));
|
||||
break;
|
||||
case SIGINT:
|
||||
strscpy(buf, "Interrupt", sizeof(buf));
|
||||
break;
|
||||
case SIGQUIT:
|
||||
strscpy(buf, "Quit", sizeof(buf));
|
||||
break;
|
||||
#ifdef SIGILL
|
||||
case SIGILL:
|
||||
strscpy(buf, "Illegal instruction", sizeof(buf));
|
||||
break;
|
||||
#endif
|
||||
#ifdef SIGABRT
|
||||
case SIGABRT:
|
||||
strscpy(buf, "Abort", sizeof(buf));
|
||||
break;
|
||||
#endif
|
||||
#if defined(SIGIOT) && (!defined(SIGABRT) || SIGIOT != SIGABRT)
|
||||
case SIGIOT:
|
||||
strscpy(buf, "IOT trap", sizeof(buf));
|
||||
break;
|
||||
#endif
|
||||
#ifdef SIGBUS
|
||||
case SIGBUS:
|
||||
strscpy(buf, "Bus error", sizeof(buf));
|
||||
break;
|
||||
#endif
|
||||
case SIGFPE:
|
||||
strscpy(buf, "Floating point exception", sizeof(buf));
|
||||
break;
|
||||
case SIGKILL:
|
||||
strscpy(buf, "Killed", sizeof(buf));
|
||||
break;
|
||||
case SIGUSR1:
|
||||
strscpy(buf, "User signal 1", sizeof(buf));
|
||||
break;
|
||||
case SIGSEGV:
|
||||
strscpy(buf, "Segmentation fault", sizeof(buf));
|
||||
break;
|
||||
case SIGUSR2:
|
||||
strscpy(buf, "User signal 2", sizeof(buf));
|
||||
break;
|
||||
case SIGPIPE:
|
||||
strscpy(buf, "Broken pipe", sizeof(buf));
|
||||
break;
|
||||
case SIGALRM:
|
||||
strscpy(buf, "Alarm clock", sizeof(buf));
|
||||
break;
|
||||
case SIGTERM:
|
||||
strscpy(buf, "Terminated", sizeof(buf));
|
||||
break;
|
||||
case SIGSTOP:
|
||||
strscpy(buf, "Suspended (signal)", sizeof(buf));
|
||||
break;
|
||||
case SIGTSTP:
|
||||
strscpy(buf, "Suspended", sizeof(buf));
|
||||
break;
|
||||
case SIGIO:
|
||||
strscpy(buf, "I/O error", sizeof(buf));
|
||||
break;
|
||||
default:
|
||||
snprintf(buf, sizeof(buf), "Signal %d\n", signum);
|
||||
break;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*************************************************************************/
|
||||
@@ -0,0 +1,81 @@
|
||||
/* Services configuration.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: config.h,v 1.7 2003/09/04 18:55:34 rob Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
/* Note that most of the options which used to be here have been moved to
|
||||
* services.conf. */
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/******* General configuration *******/
|
||||
|
||||
/* Name of configuration file (in Services directory) */
|
||||
#define SERVICES_CONF "services.conf"
|
||||
|
||||
/* Name of log file (in Services directory) */
|
||||
#define LOG_FILENAME "services.log"
|
||||
|
||||
/* Maximum amount of data from/to the network to buffer (bytes). */
|
||||
#define NET_BUFSIZE 65536
|
||||
|
||||
/******* OperServ configuration *******/
|
||||
|
||||
/* How big a hostname list do we keep for clone detection? On large nets
|
||||
* (over 500 simultaneous users or so), you may want to increase this if
|
||||
* you want a good chance of catching clones. */
|
||||
#define CLONE_DETECT_SIZE 16
|
||||
|
||||
/* Define this to enable OperServ's svs commands (superadmin only). */
|
||||
#define USE_OSSVS
|
||||
|
||||
/* Define this to enable OperServ's debugging commands (Services root
|
||||
* only). These commands are undocumented; "use the source, Luke!" */
|
||||
/* #define DEBUG_COMMANDS */
|
||||
|
||||
/******************* END OF USER-CONFIGURABLE SECTION ********************/
|
||||
|
||||
/* Size of input buffer (note: this is different from BUFSIZ)
|
||||
* This must be big enough to hold at least one full IRC message, or messy
|
||||
* things will happen. */
|
||||
#define BUFSIZE 1024
|
||||
|
||||
/* Extra warning: If you change CHANMAX, your ChanServ database will be
|
||||
* unusable.
|
||||
*/
|
||||
|
||||
/* Maximum length of a channel name, including the trailing null. Any
|
||||
* channels with a length longer than (CHANMAX-1) including the leading #
|
||||
* will not be usable with ChanServ. */
|
||||
#define CHANMAX 64
|
||||
|
||||
/* Maximum length of a nickname, including the trailing null. This MUST be
|
||||
* at least one greater than the maximum allowable nickname length on your
|
||||
* network, or people will run into problems using Services! The default
|
||||
* (32) works with all servers I know of. */
|
||||
#define NICKMAX 32
|
||||
|
||||
/* Maximum length of a password */
|
||||
#define PASSMAX 32
|
||||
|
||||
/* Maximum length of a username */
|
||||
#define USERMAX 10
|
||||
|
||||
/* Maximum length of a domain */
|
||||
#define HOSTMAX 64
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
#endif /* CONFIG_H */
|
||||
File diff suppressed because it is too large
Load Diff
+398
@@ -0,0 +1,398 @@
|
||||
/* Database converters.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: converter.c,v 1.5 2003/07/20 01:15:49 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "services.h"
|
||||
#include "datafiles.h"
|
||||
|
||||
/* Each converter will try to convert the databases to the format used
|
||||
* by ircservices-4.3 (that is compatible with Epona).
|
||||
*/
|
||||
|
||||
#ifdef USE_CONVERTER
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#define IS43_VERSION 7
|
||||
|
||||
#define SAFER(x) do { \
|
||||
if ((x) < 0) { \
|
||||
fatal("Read error on %s", rdb); \
|
||||
return 0; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SAFEW(x) do { \
|
||||
if ((x) < 0) { \
|
||||
fatal("Write error on %s", wdb); \
|
||||
return 0; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*************************************************************************/
|
||||
/*****************************ircservices-4.4*****************************/
|
||||
/*************************************************************************/
|
||||
|
||||
#ifdef IS44_CONVERTER
|
||||
|
||||
#define IS44_VERSION 8
|
||||
#define IS44_CA_SIZE 13
|
||||
|
||||
int convert_ircservices_44(void)
|
||||
{
|
||||
dbFILE *f, *g; /* f for reading, g for writing */
|
||||
int c, i, j;
|
||||
char *rdb, *wdb;
|
||||
|
||||
char *tmp;
|
||||
int16 tmp16;
|
||||
int32 tmp32;
|
||||
|
||||
char nick[NICKMAX];
|
||||
char pass[PASSMAX];
|
||||
char chan[CHANMAX];
|
||||
|
||||
/* NickServ database */
|
||||
|
||||
if (rename("nick.db", "nick.db.old") == -1) {
|
||||
fatal("Converter: unable to rename nick.db to nick.db.old: %s",
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(f = open_db(s_NickServ, "nick.db.old", "r", IS44_VERSION))) {
|
||||
fatal("Converter: unable to open nick.db.old in read access: %s",
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(g = open_db(s_NickServ, NickDBName, "w", IS43_VERSION))) {
|
||||
fatal("Converter: unable to open %s in write access: %s",
|
||||
NickDBName, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
rdb = sstrdup("nick.db.old");
|
||||
wdb = sstrdup(NickDBName);
|
||||
|
||||
get_file_version(f);
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
while ((c = getc_db(f)) == 1) {
|
||||
if (c != 1)
|
||||
fatal("Invalid format in %s", wdb);
|
||||
|
||||
SAFEW(write_int8(1, g));
|
||||
|
||||
SAFER(read_buffer(nick, f));
|
||||
SAFEW(write_buffer(nick, g));
|
||||
SAFER(read_buffer(pass, f));
|
||||
SAFEW(write_buffer(pass, g));
|
||||
|
||||
SAFER(read_string(&tmp, f));
|
||||
SAFEW(write_string(tmp, g));
|
||||
if (tmp)
|
||||
free(tmp);
|
||||
SAFER(read_string(&tmp, f));
|
||||
SAFEW(write_string(tmp, g));
|
||||
if (tmp)
|
||||
free(tmp);
|
||||
|
||||
SAFER(read_string(&tmp, f));
|
||||
SAFEW(write_string(tmp, g));
|
||||
if (tmp)
|
||||
free(tmp);
|
||||
SAFER(read_string(&tmp, f));
|
||||
SAFEW(write_string(tmp, g));
|
||||
if (tmp)
|
||||
free(tmp);
|
||||
SAFER(read_string(&tmp, f));
|
||||
SAFEW(write_string(tmp, g));
|
||||
if (tmp)
|
||||
free(tmp);
|
||||
SAFER(read_int32(&tmp32, f));
|
||||
SAFEW(write_int32(tmp32, g));
|
||||
SAFER(read_int32(&tmp32, f));
|
||||
SAFEW(write_int32(tmp32, g));
|
||||
|
||||
SAFER(read_int16(&tmp16, f));
|
||||
SAFEW(write_int16(tmp16, g));
|
||||
|
||||
SAFER(read_string(&tmp, f));
|
||||
SAFEW(write_string(tmp, g));
|
||||
|
||||
SAFER(read_int16(&tmp16, f));
|
||||
SAFEW(write_int16(tmp16, g));
|
||||
|
||||
if (tmp) {
|
||||
if (tmp)
|
||||
free(tmp);
|
||||
SAFER(read_int16(&tmp16, f));
|
||||
SAFEW(write_int16(tmp16, g));
|
||||
} else {
|
||||
int32 flags;
|
||||
int16 memocount, accesscount;
|
||||
|
||||
SAFER(read_int32(&flags, f));
|
||||
tmp32 = (flags & ~0x10000000);
|
||||
SAFEW(write_int32(tmp32, g));
|
||||
|
||||
/* Suspend stuff that we don't convert */
|
||||
if (flags & 0x10000000) {
|
||||
SAFER(read_buffer(nick, f));
|
||||
SAFER(read_string(&tmp, f));
|
||||
if (tmp)
|
||||
free(tmp);
|
||||
SAFER(read_int32(&tmp32, f));
|
||||
SAFER(read_int32(&tmp32, f));
|
||||
}
|
||||
|
||||
SAFER(read_int16(&tmp16, f));
|
||||
accesscount = tmp16;
|
||||
SAFEW(write_int16(tmp16, g));
|
||||
|
||||
if (accesscount) {
|
||||
for (j = 0; j < accesscount; j++) {
|
||||
SAFER(read_string(&tmp, f));
|
||||
SAFEW(write_string(tmp, g));
|
||||
if (tmp)
|
||||
free(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
SAFER(read_int16(&memocount, f));
|
||||
SAFEW(write_int16(memocount, g));
|
||||
SAFER(read_int16(&tmp16, f));
|
||||
SAFEW(write_int16(tmp16, g));
|
||||
|
||||
if (memocount) {
|
||||
for (j = 0; j < memocount; j++) {
|
||||
SAFER(read_int32(&tmp32, f));
|
||||
SAFEW(write_int32(tmp32, g));
|
||||
SAFER(read_int16(&tmp16, f));
|
||||
SAFEW(write_int16(tmp16, g));
|
||||
SAFER(read_int32(&tmp32, f));
|
||||
SAFEW(write_int32(tmp32, g));
|
||||
SAFER(read_buffer(nick, f));
|
||||
SAFEW(write_buffer(nick, g));
|
||||
SAFER(read_string(&tmp, f));
|
||||
SAFEW(write_string(tmp, g));
|
||||
if (tmp)
|
||||
free(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
SAFER(read_int16(&tmp16, f));
|
||||
SAFEW(write_int16(tmp16, g));
|
||||
SAFER(read_int16(&tmp16, f));
|
||||
SAFEW(write_int16(tmp16, g));
|
||||
|
||||
SAFER(read_int16(&tmp16, f));
|
||||
SAFEW(write_int16(tmp16, g));
|
||||
}
|
||||
} /* while (getc_db(f) != 0) */
|
||||
SAFEW(write_int8(0, g));
|
||||
} /* for (i) */
|
||||
|
||||
close_db(f);
|
||||
close_db(g);
|
||||
|
||||
free(rdb);
|
||||
free(wdb);
|
||||
|
||||
/* ChanServ */
|
||||
|
||||
rdb = sstrdup("chan.db.old");
|
||||
wdb = sstrdup(ChanDBName);
|
||||
|
||||
if (rename("chan.db", rdb) == -1) {
|
||||
fatal("Converter: unable to rename chan.db to %s: %s", rdb,
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(f = open_db(s_ChanServ, rdb, "r", IS44_VERSION))) {
|
||||
fatal("Converter: unable to open %s in read access: %s", rdb,
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(g = open_db(s_ChanServ, wdb, "w", IS43_VERSION))) {
|
||||
fatal("Converter: unable to open %s in write access: %s", wdb,
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
get_file_version(f);
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
while ((c = getc_db(f)) != 0) {
|
||||
int16 n_levels, accesscount, akickcount, memocount;
|
||||
|
||||
if (c != 1)
|
||||
fatal("Invalid format in %s", wdb);
|
||||
|
||||
SAFEW(write_int8(1, g));
|
||||
|
||||
SAFER(read_buffer(chan, f));
|
||||
SAFEW(write_buffer(chan, g));
|
||||
|
||||
SAFER(read_string(&tmp, f));
|
||||
SAFEW(write_string(tmp, g));
|
||||
if (tmp)
|
||||
free(tmp);
|
||||
SAFER(read_string(&tmp, f));
|
||||
SAFEW(write_string(tmp, g));
|
||||
if (tmp)
|
||||
free(tmp);
|
||||
|
||||
SAFER(read_buffer(pass, f));
|
||||
SAFEW(write_buffer(pass, g));
|
||||
SAFER(read_string(&tmp, f));
|
||||
SAFEW(write_string(tmp, g));
|
||||
if (tmp)
|
||||
free(tmp);
|
||||
|
||||
SAFER(read_string(&tmp, f));
|
||||
SAFEW(write_string(tmp, g));
|
||||
if (tmp)
|
||||
free(tmp);
|
||||
SAFER(read_string(&tmp, f));
|
||||
SAFEW(write_string(tmp, g));
|
||||
if (tmp)
|
||||
free(tmp);
|
||||
|
||||
SAFER(read_int32(&tmp32, f));
|
||||
SAFEW(write_int32(tmp32, g));
|
||||
SAFER(read_int32(&tmp32, f));
|
||||
SAFEW(write_int32(tmp32, g));
|
||||
|
||||
SAFER(read_string(&tmp, f));
|
||||
SAFEW(write_string(tmp, g));
|
||||
if (tmp)
|
||||
free(tmp);
|
||||
SAFER(read_buffer(nick, f));
|
||||
SAFEW(write_buffer(nick, g));
|
||||
SAFER(read_int32(&tmp32, f));
|
||||
SAFEW(write_int32(tmp32, g));
|
||||
|
||||
SAFER(read_int32(&tmp32, f));
|
||||
SAFEW(write_int32(tmp32, g));
|
||||
|
||||
SAFER(read_int16(&n_levels, f));
|
||||
SAFEW(write_int16(n_levels, g));
|
||||
|
||||
for (j = 0; j < n_levels; j++) {
|
||||
SAFER(read_int16(&tmp16, f));
|
||||
if (j < IS44_CA_SIZE)
|
||||
SAFEW(write_int16(tmp16, g));
|
||||
}
|
||||
|
||||
SAFER(read_int16(&accesscount, f));
|
||||
SAFEW(write_int16(accesscount, g));
|
||||
|
||||
if (accesscount) {
|
||||
for (j = 0; j < accesscount; j++) {
|
||||
SAFER(read_int16(&tmp16, f));
|
||||
SAFEW(write_int16(tmp16, g));
|
||||
if (tmp16) {
|
||||
SAFER(read_int16(&tmp16, f));
|
||||
SAFEW(write_int16(tmp16, g));
|
||||
SAFER(read_string(&tmp, f));
|
||||
SAFEW(write_string(tmp, g));
|
||||
if (tmp)
|
||||
free(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SAFER(read_int16(&akickcount, f));
|
||||
SAFEW(write_int16(akickcount, g));
|
||||
|
||||
if (akickcount) {
|
||||
for (j = 0; j < akickcount; j++) {
|
||||
SAFER(read_int16(&tmp16, f));
|
||||
SAFEW(write_int16(tmp16, g));
|
||||
if (tmp16) {
|
||||
SAFER(read_int16(&tmp16, f));
|
||||
SAFEW(write_int16(tmp16, g));
|
||||
SAFER(read_string(&tmp, f));
|
||||
SAFEW(write_string(tmp, g));
|
||||
if (tmp)
|
||||
free(tmp);
|
||||
SAFER(read_string(&tmp, f));
|
||||
SAFEW(write_string(tmp, g));
|
||||
if (tmp)
|
||||
free(tmp);
|
||||
SAFER(read_buffer(nick, f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SAFER(read_int16(&tmp16, f));
|
||||
SAFEW(write_int16(tmp16, g));
|
||||
SAFER(read_int16(&tmp16, f));
|
||||
SAFEW(write_int16(tmp16, g));
|
||||
SAFER(read_int32(&tmp32, f));
|
||||
SAFEW(write_int32(tmp32, g));
|
||||
SAFER(read_string(&tmp, f));
|
||||
SAFEW(write_string(tmp, g));
|
||||
if (tmp)
|
||||
free(tmp);
|
||||
|
||||
SAFER(read_int16(&memocount, f));
|
||||
SAFEW(write_int16(memocount, g));
|
||||
SAFER(read_int16(&tmp16, f));
|
||||
SAFEW(write_int16(tmp16, g));
|
||||
|
||||
if (memocount) {
|
||||
for (j = 0; j < memocount; j++) {
|
||||
SAFER(read_int32(&tmp32, f));
|
||||
SAFEW(write_int32(tmp32, g));
|
||||
SAFER(read_int16(&tmp16, f));
|
||||
SAFEW(write_int16(tmp16, g));
|
||||
SAFER(read_int32(&tmp32, f));
|
||||
SAFEW(write_int32(tmp32, g));
|
||||
SAFER(read_buffer(nick, f));
|
||||
SAFER(write_buffer(nick, g));
|
||||
SAFER(read_string(&tmp, f));
|
||||
SAFEW(write_string(tmp, g));
|
||||
if (tmp)
|
||||
free(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
SAFER(read_string(&tmp, f));
|
||||
SAFEW(write_string(tmp, g));
|
||||
if (tmp)
|
||||
free(tmp);
|
||||
} /* while (getc_db(f) != 0) */
|
||||
SAFEW(write_int8(0, g));
|
||||
} /* for (i) */
|
||||
|
||||
close_db(f);
|
||||
close_db(g);
|
||||
|
||||
free(rdb);
|
||||
free(wdb);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*************************************************************************/
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Crontab script for Anope
|
||||
#
|
||||
# To know how to install the crontab, read the INSTALL file.
|
||||
|
||||
###############################################################
|
||||
# CONFIGURATION
|
||||
###############################################################
|
||||
|
||||
# Anope binary directory
|
||||
ANOPATH=/home/ircd/services/
|
||||
|
||||
# Name of the pid file
|
||||
ANOPIDF=services.pid
|
||||
|
||||
# Name of the executable
|
||||
ANOPROG=services
|
||||
|
||||
# Parameters to pass to the executable
|
||||
ANOARGS=""
|
||||
#ANOARGS="-debug"
|
||||
|
||||
###############################################################
|
||||
# DON'T EDIT ANYTHING BELOW #
|
||||
###############################################################
|
||||
|
||||
PATH=/bin:/usr/bin:/usr/local/bin
|
||||
|
||||
ANOPID=
|
||||
|
||||
cd $ANOPATH
|
||||
|
||||
if [ -f $ANOPIDF ]
|
||||
then
|
||||
ANOPID=`cat $ANOPIDF`
|
||||
if [ `ps ux| grep $ANOPROG | grep $ANOPID | grep -v -c grep` = 1 ]
|
||||
then
|
||||
exit
|
||||
fi
|
||||
rm -f $ANOPIDF
|
||||
fi
|
||||
|
||||
./$ANOPROG $ANOARGS
|
||||
+1450
File diff suppressed because it is too large
Load Diff
+470
@@ -0,0 +1,470 @@
|
||||
|
||||
-- If you need to create your db, uncomment the following lines.
|
||||
-- create database anope;
|
||||
-- use anope;
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_info`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_info;
|
||||
CREATE TABLE anope_info (
|
||||
version int(11) default NULL,
|
||||
date datetime default NULL
|
||||
) TYPE=MyISAM;
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_bs_core`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_bs_core;
|
||||
CREATE TABLE anope_bs_core (
|
||||
bs_id int(11) NOT NULL auto_increment,
|
||||
nick varchar(255) NOT NULL default '',
|
||||
user text NOT NULL,
|
||||
host text NOT NULL,
|
||||
rname text NOT NULL,
|
||||
flags int(11) NOT NULL default '0',
|
||||
created int(11) NOT NULL default '0',
|
||||
chancount int(11) NOT NULL default '0',
|
||||
PRIMARY KEY (bs_id),
|
||||
UNIQUE KEY nick (nick),
|
||||
KEY nick_index (nick(10))
|
||||
) TYPE=MyISAM;
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_cs_access`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_cs_access;
|
||||
CREATE TABLE anope_cs_access (
|
||||
ca_id int(11) NOT NULL auto_increment,
|
||||
in_use int(11) NOT NULL default '0',
|
||||
level int(11) NOT NULL default '0',
|
||||
display varchar(255) NOT NULL default '',
|
||||
channel varchar(255) NOT NULL default '',
|
||||
last_seen int(11) NOT NULL default '0',
|
||||
PRIMARY KEY (ca_id)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_cs_akicks`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_cs_akicks;
|
||||
CREATE TABLE anope_cs_akicks (
|
||||
ck_id int(11) NOT NULL auto_increment,
|
||||
channel varchar(255) NOT NULL default '',
|
||||
flags int(11) NOT NULL default '0',
|
||||
dmask text NOT NULL,
|
||||
reason text NOT NULL,
|
||||
creator text NOT NULL,
|
||||
addtime int(11) NOT NULL default '0',
|
||||
PRIMARY KEY (ck_id)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_cs_badwords`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_cs_badwords;
|
||||
CREATE TABLE anope_cs_badwords (
|
||||
cw_id int(11) NOT NULL auto_increment,
|
||||
channel varchar(255) NOT NULL default '',
|
||||
word text NOT NULL,
|
||||
type int(11) NOT NULL default '0',
|
||||
PRIMARY KEY (cw_id)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_cs_info`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_cs_info;
|
||||
CREATE TABLE anope_cs_info (
|
||||
ci_id int(11) NOT NULL auto_increment,
|
||||
name varchar(255) NOT NULL default '',
|
||||
founder text NOT NULL,
|
||||
successor text NOT NULL,
|
||||
founderpass tinyblob NOT NULL,
|
||||
descr text NOT NULL,
|
||||
url text NOT NULL,
|
||||
email text NOT NULL,
|
||||
time_registered int(10) unsigned NOT NULL default '0',
|
||||
last_used int(10) unsigned NOT NULL default '0',
|
||||
last_topic text NOT NULL,
|
||||
last_topic_setter text NOT NULL,
|
||||
last_topic_time int(10) unsigned NOT NULL default '0',
|
||||
flags int(10) unsigned NOT NULL default '0',
|
||||
forbidby text NOT NULL,
|
||||
forbidreason text NOT NULL,
|
||||
bantype smallint(6) NOT NULL default '0',
|
||||
accesscount smallint(6) NOT NULL default '0',
|
||||
akickcount smallint(6) NOT NULL default '0',
|
||||
mlock_on int(10) unsigned NOT NULL default '0',
|
||||
mlock_off int(10) unsigned NOT NULL default '0',
|
||||
mlock_limit int(10) unsigned NOT NULL default '0',
|
||||
mlock_key text NOT NULL,
|
||||
mlock_flood text NOT NULL,
|
||||
mlock_redirect text NOT NULL,
|
||||
entry_message text NOT NULL,
|
||||
memomax smallint(5) unsigned NOT NULL default '0',
|
||||
botnick varchar(255) NOT NULL default '',
|
||||
botflags int(10) unsigned NOT NULL default '0',
|
||||
ttb smallint(6) NOT NULL default '0',
|
||||
bwcount smallint(6) NOT NULL default '0',
|
||||
capsmin smallint(6) NOT NULL default '0',
|
||||
capspercent smallint(6) NOT NULL default '0',
|
||||
floodlines smallint(6) NOT NULL default '0',
|
||||
floodsecs smallint(6) NOT NULL default '0',
|
||||
repeattimes smallint(6) NOT NULL default '0',
|
||||
active tinyint(1) NOT NULL default '1',
|
||||
PRIMARY KEY (ci_id),
|
||||
UNIQUE KEY name (name),
|
||||
KEY name_index (name(10))
|
||||
) TYPE=MyISAM;
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_cs_levels`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_cs_levels;
|
||||
CREATE TABLE anope_cs_levels (
|
||||
cl_id int(11) NOT NULL auto_increment,
|
||||
channel varchar(255) NOT NULL default '',
|
||||
position int(11) NOT NULL default '0',
|
||||
level int(11) NOT NULL default '0',
|
||||
PRIMARY KEY (cl_id)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_hs_core`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_hs_core;
|
||||
CREATE TABLE anope_hs_core (
|
||||
bs_id int(11) NOT NULL auto_increment,
|
||||
nick varchar(255) NOT NULL default '',
|
||||
vident text NOT NULL,
|
||||
vhost text NOT NULL,
|
||||
creator text NOT NULL,
|
||||
time int(11) NOT NULL default '0',
|
||||
PRIMARY KEY (bs_id),
|
||||
UNIQUE KEY nick (nick),
|
||||
KEY nick_index (nick(10))
|
||||
) TYPE=MyISAM;
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_ms_info`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_ms_info;
|
||||
CREATE TABLE anope_ms_info (
|
||||
nm_id int(11) NOT NULL auto_increment,
|
||||
receiver text NOT NULL,
|
||||
number int(11) NOT NULL default '0',
|
||||
flags int(11) NOT NULL default '0',
|
||||
time int(11) NOT NULL default '0',
|
||||
sender text NOT NULL,
|
||||
text blob NOT NULL,
|
||||
serv enum('NICK','CHAN') NOT NULL default 'NICK',
|
||||
PRIMARY KEY (nm_id)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_ns_access`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_ns_access;
|
||||
CREATE TABLE anope_ns_access (
|
||||
na_id int(11) NOT NULL auto_increment,
|
||||
display varchar(255) NOT NULL default '',
|
||||
access text NOT NULL,
|
||||
PRIMARY KEY (na_id)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_ns_alias`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_ns_alias;
|
||||
CREATE TABLE anope_ns_alias (
|
||||
na_id int(11) NOT NULL auto_increment,
|
||||
display varchar(255) NOT NULL default '',
|
||||
nick varchar(255) NOT NULL default '',
|
||||
time_registered int(10) unsigned NOT NULL default '0',
|
||||
last_seen int(10) unsigned NOT NULL default '0',
|
||||
status smallint(6) NOT NULL default '0',
|
||||
last_usermask text NOT NULL,
|
||||
last_realname text NOT NULL,
|
||||
last_quit text NOT NULL,
|
||||
active tinyint(1) NOT NULL default '1',
|
||||
PRIMARY KEY (na_id),
|
||||
UNIQUE KEY nick (nick),
|
||||
KEY nick_index (nick(10))
|
||||
) TYPE=MyISAM;
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_ns_core`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_ns_core;
|
||||
CREATE TABLE anope_ns_core (
|
||||
nc_id int(11) NOT NULL auto_increment,
|
||||
display varchar(255) NOT NULL default '',
|
||||
pass tinyblob NOT NULL,
|
||||
email text NOT NULL,
|
||||
icq int(10) unsigned NOT NULL default '0',
|
||||
url text NOT NULL,
|
||||
flags int(11) NOT NULL default '0',
|
||||
language smallint(5) unsigned NOT NULL default '0',
|
||||
accesscount smallint(6) NOT NULL default '0',
|
||||
memocount smallint(5) unsigned NOT NULL default '0',
|
||||
memomax smallint(5) unsigned NOT NULL default '0',
|
||||
channelcount smallint(5) unsigned NOT NULL default '0',
|
||||
channelmax smallint(5) unsigned NOT NULL default '0',
|
||||
greet text NOT NULL,
|
||||
active tinyint(1) NOT NULL default '1',
|
||||
PRIMARY KEY (nc_id),
|
||||
UNIQUE KEY display (display),
|
||||
KEY display_index (display(10))
|
||||
) TYPE=MyISAM;
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_ns_request`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_ns_request;
|
||||
CREATE TABLE anope_ns_request (
|
||||
nr_id int(11) NOT NULL auto_increment,
|
||||
nick varchar(255) NOT NULL default '',
|
||||
passcode text NOT NULL,
|
||||
password tinyblob NOT NULL,
|
||||
email text NOT NULL,
|
||||
requested int(11) NOT NULL default '0',
|
||||
active int(1) NOT NULL default '1',
|
||||
PRIMARY KEY (nr_id),
|
||||
UNIQUE KEY nick (nick),
|
||||
KEY nick_index (nick(10))
|
||||
) TYPE=MyISAM;
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_os_akills`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_os_akills;
|
||||
CREATE TABLE anope_os_akills (
|
||||
ok_id int(11) NOT NULL auto_increment,
|
||||
user text NOT NULL,
|
||||
host text NOT NULL,
|
||||
xby text NOT NULL,
|
||||
reason text NOT NULL,
|
||||
seton int(11) NOT NULL default '0',
|
||||
expire int(11) NOT NULL default '0',
|
||||
PRIMARY KEY (ok_id)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_os_core`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_os_core;
|
||||
CREATE TABLE anope_os_core (
|
||||
oc_id int(11) NOT NULL auto_increment,
|
||||
maxusercnt int(11) NOT NULL default '0',
|
||||
maxusertime int(11) NOT NULL default '0',
|
||||
akills_count int(11) NOT NULL default '0',
|
||||
sglines_count int(11) NOT NULL default '0',
|
||||
sqlines_count int(11) NOT NULL default '0',
|
||||
szlines_count int(11) NOT NULL default '0',
|
||||
PRIMARY KEY (oc_id)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_os_exceptions`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_os_exceptions;
|
||||
CREATE TABLE anope_os_exceptions (
|
||||
oe_id int(11) NOT NULL auto_increment,
|
||||
mask text NOT NULL,
|
||||
lim int(11) NOT NULL default '0',
|
||||
who text NOT NULL,
|
||||
reason text NOT NULL,
|
||||
time int(11) NOT NULL default '0',
|
||||
expires int(11) NOT NULL default '0',
|
||||
PRIMARY KEY (oe_id)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_os_hcache`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_os_hcache;
|
||||
CREATE TABLE anope_os_hcache (
|
||||
oh_id int(11) NOT NULL auto_increment,
|
||||
mask text NOT NULL,
|
||||
status int(11) NOT NULL default '0',
|
||||
used int(11) NOT NULL default '0',
|
||||
PRIMARY KEY (oh_id)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_os_news`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_os_news;
|
||||
CREATE TABLE anope_os_news (
|
||||
on_id int(11) NOT NULL auto_increment,
|
||||
type int(11) NOT NULL default '0',
|
||||
num int(11) NOT NULL default '0',
|
||||
ntext text NOT NULL,
|
||||
who text NOT NULL,
|
||||
time int(11) NOT NULL default '0',
|
||||
PRIMARY KEY (on_id)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_os_sglines`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_os_sglines;
|
||||
CREATE TABLE anope_os_sglines (
|
||||
og_id int(11) NOT NULL auto_increment,
|
||||
mask text NOT NULL,
|
||||
xby text NOT NULL,
|
||||
reason text NOT NULL,
|
||||
seton int(11) NOT NULL default '0',
|
||||
expire int(11) NOT NULL default '0',
|
||||
PRIMARY KEY (og_id)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_os_sqlines`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_os_sqlines;
|
||||
CREATE TABLE anope_os_sqlines (
|
||||
og_id int(11) NOT NULL auto_increment,
|
||||
mask text NOT NULL,
|
||||
xby text NOT NULL,
|
||||
reason text NOT NULL,
|
||||
seton int(11) NOT NULL default '0',
|
||||
expire int(11) NOT NULL default '0',
|
||||
PRIMARY KEY (og_id)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_os_status`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_os_status;
|
||||
CREATE TABLE anope_os_status (
|
||||
os_id int(11) NOT NULL auto_increment,
|
||||
host text NOT NULL,
|
||||
status int(11) NOT NULL default '0',
|
||||
used int(11) NOT NULL default '0',
|
||||
PRIMARY KEY (os_id)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_os_szlines`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_os_szlines;
|
||||
CREATE TABLE anope_os_szlines (
|
||||
og_id int(11) NOT NULL auto_increment,
|
||||
mask text NOT NULL,
|
||||
xby text NOT NULL,
|
||||
reason text NOT NULL,
|
||||
seton int(11) NOT NULL default '0',
|
||||
expire int(11) NOT NULL default '0',
|
||||
PRIMARY KEY (og_id)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
--
|
||||
-- Table structure for table `bugs`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS bugs;
|
||||
CREATE TABLE bugs (
|
||||
b_id int(9) NOT NULL auto_increment,
|
||||
b_moduleid int(9) NOT NULL default '0',
|
||||
b_title varchar(40) NOT NULL default '',
|
||||
b_desc text NOT NULL,
|
||||
b_reporter varchar(15) NOT NULL default '',
|
||||
PRIMARY KEY (b_id)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
--
|
||||
-- Table structure for table `modules`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS modules;
|
||||
CREATE TABLE modules (
|
||||
m_id int(9) NOT NULL auto_increment,
|
||||
m_name varchar(30) NOT NULL default '',
|
||||
m_category enum('OperServ','NickServ','MemoServ','ChanServ','BotServ','HostServ','HelpServ','Misc') NOT NULL default 'Misc',
|
||||
m_description longtext NOT NULL,
|
||||
m_activated enum('0','1') NOT NULL default '0',
|
||||
m_owner varchar(15) NOT NULL default '',
|
||||
m_path varchar(40) NOT NULL default '',
|
||||
m_updated date NOT NULL default '0000-00-00',
|
||||
m_official enum('0','1') NOT NULL default '0',
|
||||
m_version varchar(5) NOT NULL default '',
|
||||
PRIMARY KEY (m_id)
|
||||
) TYPE=MyISAM PACK_KEYS=0;
|
||||
|
||||
--
|
||||
-- Table structure for table `requests`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS requests;
|
||||
CREATE TABLE requests (
|
||||
r_id int(3) NOT NULL auto_increment,
|
||||
r_title varchar(30) NOT NULL default '',
|
||||
r_category enum('OperServ','NickServ','MemoServ','ChanServ','BotServ','HostServ','HelpServ','Misc') NOT NULL default 'Misc',
|
||||
r_description longtext NOT NULL,
|
||||
r_owner varchar(15) NOT NULL default 'Anonymous',
|
||||
r_assigned varchar(15) NOT NULL default '',
|
||||
PRIMARY KEY (r_id)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
--
|
||||
-- Table structure for table `uploaded`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS uploaded;
|
||||
CREATE TABLE uploaded (
|
||||
mu_id int(9) NOT NULL auto_increment,
|
||||
mu_name varchar(30) NOT NULL default '',
|
||||
mu_category enum('OperServ','NickServ','MemoServ','ChanServ','BotServ','HostServ','HelpServ','Misc') NOT NULL default 'Misc',
|
||||
mu_description longtext NOT NULL,
|
||||
mu_activated enum('0','1') NOT NULL default '0',
|
||||
mu_owner varchar(15) NOT NULL default '',
|
||||
mu_path varchar(40) NOT NULL default '',
|
||||
mu_updated date NOT NULL default '0000-00-00',
|
||||
mu_official enum('0','1') NOT NULL default '0',
|
||||
mu_version varchar(5) NOT NULL default '',
|
||||
PRIMARY KEY (mu_id)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
--
|
||||
-- Table structure for table `users`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS users;
|
||||
CREATE TABLE users (
|
||||
u_id int(9) NOT NULL auto_increment,
|
||||
u_username varchar(15) NOT NULL default '',
|
||||
u_password varchar(32) NOT NULL default '',
|
||||
u_email varchar(40) NOT NULL default '',
|
||||
u_location varchar(40) NOT NULL default '',
|
||||
u_status enum('normal','coder','admin','root') NOT NULL default 'normal',
|
||||
u_confirmed enum('0','1') NOT NULL default '1',
|
||||
u_registered date NOT NULL default '0000-00-00',
|
||||
u_lastvisit date NOT NULL default '0000-00-00',
|
||||
u_hideemail enum('0','1') NOT NULL default '0',
|
||||
PRIMARY KEY (u_id)
|
||||
) TYPE=MyISAM PACK_KEYS=0;
|
||||
|
||||
+507
@@ -0,0 +1,507 @@
|
||||
/* Database file handling routines.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: datafiles.c,v 1.8 2003/07/20 01:15:49 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "services.h"
|
||||
#include "datafiles.h"
|
||||
#include <fcntl.h>
|
||||
|
||||
static int curday = 0;
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* Return the version number on the file. Return 0 if there is no version
|
||||
* number or the number doesn't make sense (i.e. less than 1 or greater
|
||||
* than FILE_VERSION).
|
||||
*/
|
||||
|
||||
int get_file_version(dbFILE * f)
|
||||
{
|
||||
FILE *fp = f->fp;
|
||||
int version =
|
||||
fgetc(fp) << 24 | fgetc(fp) << 16 | fgetc(fp) << 8 | fgetc(fp);
|
||||
if (ferror(fp)) {
|
||||
#ifndef NOT_MAIN
|
||||
log_perror("Error reading version number on %s", f->filename);
|
||||
#endif
|
||||
return 0;
|
||||
} else if (feof(fp)) {
|
||||
#ifndef NOT_MAIN
|
||||
alog("Error reading version number on %s: End of file detected",
|
||||
f->filename);
|
||||
#endif
|
||||
return 0;
|
||||
} else if (version < 1) {
|
||||
#ifndef NOT_MAIN
|
||||
alog("Invalid version number (%d) on %s", version, f->filename);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Write the current version number to the file. Return 0 on error, 1 on
|
||||
* success.
|
||||
*/
|
||||
|
||||
int write_file_version(dbFILE * f, uint32 version)
|
||||
{
|
||||
FILE *fp = f->fp;
|
||||
if (fputc(version >> 24 & 0xFF, fp) < 0 ||
|
||||
fputc(version >> 16 & 0xFF, fp) < 0 ||
|
||||
fputc(version >> 8 & 0xFF, fp) < 0 ||
|
||||
fputc(version & 0xFF, fp) < 0) {
|
||||
#ifndef NOT_MAIN
|
||||
log_perror("Error writing version number on %s", f->filename);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
static dbFILE *open_db_read(const char *service, const char *filename)
|
||||
{
|
||||
dbFILE *f;
|
||||
FILE *fp;
|
||||
|
||||
f = scalloc(sizeof(*f), 1);
|
||||
if (!f) {
|
||||
#ifndef NOT_MAIN
|
||||
log_perror("Can't read %s database %s", service, filename);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
strscpy(f->filename, filename, sizeof(f->filename));
|
||||
f->mode = 'r';
|
||||
fp = fopen(f->filename, "rb");
|
||||
if (!fp) {
|
||||
int errno_save = errno;
|
||||
#ifndef NOT_MAIN
|
||||
if (errno != ENOENT)
|
||||
log_perror("Can't read %s database %s", service, f->filename);
|
||||
#endif
|
||||
free(f);
|
||||
errno = errno_save;
|
||||
return NULL;
|
||||
}
|
||||
f->fp = fp;
|
||||
f->backupfp = NULL;
|
||||
return f;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static dbFILE *open_db_write(const char *service, const char *filename,
|
||||
uint32 version)
|
||||
{
|
||||
dbFILE *f;
|
||||
int fd;
|
||||
|
||||
f = scalloc(sizeof(*f), 1);
|
||||
if (!f) {
|
||||
#ifndef NOT_MAIN
|
||||
log_perror("Can't read %s database %s", service, filename);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
strscpy(f->filename, filename, sizeof(f->filename));
|
||||
filename = f->filename;
|
||||
f->mode = 'w';
|
||||
|
||||
*f->backupname = 0;
|
||||
snprintf(f->backupname, sizeof(f->backupname), "%s.save", filename);
|
||||
if (!*f->backupname || strcmp(f->backupname, filename) == 0) {
|
||||
int errno_save = errno;
|
||||
#ifndef NOT_MAIN
|
||||
alog("Opening %s database %s for write: Filename too long",
|
||||
service, filename);
|
||||
#endif
|
||||
free(f);
|
||||
errno = errno_save;
|
||||
return NULL;
|
||||
}
|
||||
unlink(f->backupname);
|
||||
f->backupfp = fopen(filename, "rb");
|
||||
if (rename(filename, f->backupname) < 0 && errno != ENOENT) {
|
||||
int errno_save = errno;
|
||||
#ifndef NOT_MAIN
|
||||
static int walloped = 0;
|
||||
if (!walloped) {
|
||||
walloped++;
|
||||
wallops(NULL, "Can't back up %s database %s", service,
|
||||
filename);
|
||||
}
|
||||
errno = errno_save;
|
||||
log_perror("Can't back up %s database %s", service, filename);
|
||||
if (!NoBackupOkay) {
|
||||
#endif
|
||||
if (f->backupfp)
|
||||
fclose(f->backupfp);
|
||||
free(f);
|
||||
errno = errno_save;
|
||||
return NULL;
|
||||
#ifndef NOT_MAIN
|
||||
}
|
||||
#endif
|
||||
*f->backupname = 0;
|
||||
}
|
||||
unlink(filename);
|
||||
/* Use open() to avoid people sneaking a new file in under us */
|
||||
fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0666);
|
||||
f->fp = fdopen(fd, "wb"); /* will fail and return NULL if fd < 0 */
|
||||
if (!f->fp || !write_file_version(f, version)) {
|
||||
int errno_save = errno;
|
||||
#ifndef NOT_MAIN
|
||||
static int walloped = 0;
|
||||
if (!walloped) {
|
||||
walloped++;
|
||||
wallops(NULL, "Can't write to %s database %s", service,
|
||||
filename);
|
||||
}
|
||||
errno = errno_save;
|
||||
log_perror("Can't write to %s database %s", service, filename);
|
||||
#endif
|
||||
if (f->fp) {
|
||||
fclose(f->fp);
|
||||
unlink(filename);
|
||||
}
|
||||
if (*f->backupname && rename(f->backupname, filename) < 0)
|
||||
#ifndef NOT_MAIN
|
||||
log_perror("Cannot restore backup copy of %s", filename);
|
||||
#else
|
||||
;
|
||||
#endif
|
||||
errno = errno_save;
|
||||
return NULL;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Open a database file for reading (*mode == 'r') or writing (*mode == 'w').
|
||||
* Return the stream pointer, or NULL on error. When opening for write, it
|
||||
* is an error for rename() to return an error (when backing up the original
|
||||
* file) other than ENOENT, if NO_BACKUP_OKAY is not defined; it is an error
|
||||
* if the version number cannot be written to the file; and it is a fatal
|
||||
* error if opening the file for write fails and the backup was successfully
|
||||
* made but cannot be restored.
|
||||
*/
|
||||
|
||||
dbFILE *open_db(const char *service, const char *filename,
|
||||
const char *mode, uint32 version)
|
||||
{
|
||||
if (*mode == 'r') {
|
||||
return open_db_read(service, filename);
|
||||
} else if (*mode == 'w') {
|
||||
return open_db_write(service, filename, version);
|
||||
} else {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Restore the database file to its condition before open_db(). This is
|
||||
* identical to close_db() for files open for reading; however, for files
|
||||
* open for writing, we first attempt to restore any backup file before
|
||||
* closing files.
|
||||
*/
|
||||
|
||||
void restore_db(dbFILE * f)
|
||||
{
|
||||
int errno_save = errno;
|
||||
|
||||
if (f->mode == 'w') {
|
||||
int ok = 0; /* Did we manage to restore the old file? */
|
||||
errno = errno_save = 0;
|
||||
if (*f->backupname && strcmp(f->backupname, f->filename) != 0) {
|
||||
if (rename(f->backupname, f->filename) == 0)
|
||||
ok = 1;
|
||||
}
|
||||
if (!ok && f->backupfp) {
|
||||
char buf[1024];
|
||||
int i;
|
||||
ok = 1;
|
||||
if (fseek(f->fp, 0, SEEK_SET) < 0)
|
||||
ok = 0;
|
||||
while (ok && (i = fread(buf, 1, sizeof(buf), f->backupfp)) > 0) {
|
||||
if (fwrite(buf, 1, i, f->fp) != i)
|
||||
ok = 0;
|
||||
}
|
||||
if (ok) {
|
||||
fflush(f->fp);
|
||||
ftruncate(fileno(f->fp), ftell(f->fp));
|
||||
}
|
||||
}
|
||||
#ifndef NOT_MAIN
|
||||
if (!ok && errno > 0)
|
||||
log_perror("Unable to restore backup of %s", f->filename);
|
||||
#endif
|
||||
errno_save = errno;
|
||||
if (f->backupfp)
|
||||
fclose(f->backupfp);
|
||||
if (*f->backupname)
|
||||
unlink(f->backupname);
|
||||
}
|
||||
fclose(f->fp);
|
||||
if (!errno_save)
|
||||
errno_save = errno;
|
||||
free(f);
|
||||
errno = errno_save;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Close a database file. If the file was opened for write, remove the
|
||||
* backup we (may have) created earlier.
|
||||
*/
|
||||
|
||||
void close_db(dbFILE * f)
|
||||
{
|
||||
if (f->mode == 'w' && *f->backupname
|
||||
&& strcmp(f->backupname, f->filename) != 0) {
|
||||
if (f->backupfp)
|
||||
fclose(f->backupfp);
|
||||
unlink(f->backupname);
|
||||
}
|
||||
fclose(f->fp);
|
||||
free(f);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* Read and write 2- and 4-byte quantities, pointers, and strings. All
|
||||
* multibyte values are stored in big-endian order (most significant byte
|
||||
* first). A pointer is stored as a byte, either 0 if NULL or 1 if not,
|
||||
* and read pointers are returned as either (void *)0 or (void *)1. A
|
||||
* string is stored with a 2-byte unsigned length (including the trailing
|
||||
* \0) first; a length of 0 indicates that the string pointer is NULL.
|
||||
* Written strings are truncated silently at 65534 bytes, and are always
|
||||
* null-terminated.
|
||||
*
|
||||
* All routines return -1 on error, 0 otherwise.
|
||||
*/
|
||||
|
||||
|
||||
int read_int16(uint16 * ret, dbFILE * f)
|
||||
{
|
||||
int c1, c2;
|
||||
|
||||
c1 = fgetc(f->fp);
|
||||
c2 = fgetc(f->fp);
|
||||
if (c1 == EOF || c2 == EOF)
|
||||
return -1;
|
||||
*ret = c1 << 8 | c2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int write_int16(uint16 val, dbFILE * f)
|
||||
{
|
||||
if (fputc((val >> 8) & 0xFF, f->fp) == EOF
|
||||
|| fputc(val & 0xFF, f->fp) == EOF)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int read_int32(uint32 * ret, dbFILE * f)
|
||||
{
|
||||
int c1, c2, c3, c4;
|
||||
|
||||
c1 = fgetc(f->fp);
|
||||
c2 = fgetc(f->fp);
|
||||
c3 = fgetc(f->fp);
|
||||
c4 = fgetc(f->fp);
|
||||
if (c1 == EOF || c2 == EOF || c3 == EOF || c4 == EOF)
|
||||
return -1;
|
||||
*ret = c1 << 24 | c2 << 16 | c3 << 8 | c4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int write_int32(uint32 val, dbFILE * f)
|
||||
{
|
||||
if (fputc((val >> 24) & 0xFF, f->fp) == EOF)
|
||||
return -1;
|
||||
if (fputc((val >> 16) & 0xFF, f->fp) == EOF)
|
||||
return -1;
|
||||
if (fputc((val >> 8) & 0xFF, f->fp) == EOF)
|
||||
return -1;
|
||||
if (fputc((val) & 0xFF, f->fp) == EOF)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int read_ptr(void **ret, dbFILE * f)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = fgetc(f->fp);
|
||||
if (c == EOF)
|
||||
return -1;
|
||||
*ret = (c ? (void *) 1 : (void *) 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int write_ptr(const void *ptr, dbFILE * f)
|
||||
{
|
||||
if (fputc(ptr ? 1 : 0, f->fp) == EOF)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int read_string(char **ret, dbFILE * f)
|
||||
{
|
||||
char *s;
|
||||
uint16 len;
|
||||
|
||||
if (read_int16(&len, f) < 0)
|
||||
return -1;
|
||||
if (len == 0) {
|
||||
*ret = NULL;
|
||||
return 0;
|
||||
}
|
||||
s = scalloc(len, 1);
|
||||
if (len != fread(s, 1, len, f->fp)) {
|
||||
free(s);
|
||||
return -1;
|
||||
}
|
||||
*ret = s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int write_string(const char *s, dbFILE * f)
|
||||
{
|
||||
uint32 len;
|
||||
|
||||
if (!s)
|
||||
return write_int16(0, f);
|
||||
len = strlen(s);
|
||||
if (len > 65534)
|
||||
len = 65534;
|
||||
if (write_int16((uint16) (len + 1), f) < 0)
|
||||
return -1;
|
||||
if (len > 0 && fwrite(s, 1, len, f->fp) != len)
|
||||
return -1;
|
||||
if (fputc(0, f->fp) == EOF)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* Renames a database */
|
||||
|
||||
static void rename_database(char *name, char *ext)
|
||||
{
|
||||
|
||||
char destpath[PATH_MAX];
|
||||
|
||||
snprintf(destpath, sizeof(destpath), "backups/%s.%s", name, ext);
|
||||
if (rename(name, destpath) != 0) {
|
||||
alog("Backup of %s failed.", name);
|
||||
wallops(s_OperServ, "WARNING! Backup of %s failed.", name);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Removes old databases */
|
||||
|
||||
static void remove_backups(void)
|
||||
{
|
||||
|
||||
char ext[9];
|
||||
char path[PATH_MAX];
|
||||
|
||||
time_t t;
|
||||
struct tm tm;
|
||||
|
||||
time(&t);
|
||||
t -= (60 * 60 * 24 * KeepBackups);
|
||||
tm = *localtime(&t);
|
||||
strftime(ext, sizeof(ext), "%Y%m%d", &tm);
|
||||
|
||||
snprintf(path, sizeof(path), "backups/%s.%s", NickDBName, ext);
|
||||
unlink(path);
|
||||
snprintf(path, sizeof(path), "backups/%s.%s", BotDBName, ext);
|
||||
unlink(path);
|
||||
snprintf(path, sizeof(path), "backups/%s.%s", ChanDBName, ext);
|
||||
unlink(path);
|
||||
snprintf(path, sizeof(path), "backups/%s.%s", OperDBName, ext);
|
||||
unlink(path);
|
||||
snprintf(path, sizeof(path), "backups/%s.%s", NewsDBName, ext);
|
||||
unlink(path);
|
||||
snprintf(path, sizeof(path), "backups/%s.%s", ExceptionDBName, ext);
|
||||
unlink(path);
|
||||
snprintf(path, sizeof(path), "backups/%s.%s", HostDBName, ext);
|
||||
unlink(path);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Handles database backups. */
|
||||
|
||||
void backup_databases(void)
|
||||
{
|
||||
|
||||
time_t t;
|
||||
struct tm tm;
|
||||
|
||||
if (!KeepBackups)
|
||||
return;
|
||||
|
||||
time(&t);
|
||||
tm = *localtime(&t);
|
||||
|
||||
if (!curday) {
|
||||
curday = tm.tm_yday;
|
||||
return;
|
||||
}
|
||||
|
||||
if (curday != tm.tm_yday) {
|
||||
|
||||
char ext[9];
|
||||
|
||||
alog("Backing up databases");
|
||||
|
||||
remove_backups();
|
||||
|
||||
curday = tm.tm_yday;
|
||||
strftime(ext, sizeof(ext), "%Y%m%d", &tm);
|
||||
|
||||
if (!skeleton) {
|
||||
rename_database(NickDBName, ext);
|
||||
if (s_BotServ)
|
||||
rename_database(BotDBName, ext);
|
||||
rename_database(ChanDBName, ext);
|
||||
if (s_HostServ)
|
||||
rename_database(HostDBName, ext);
|
||||
}
|
||||
|
||||
rename_database(OperDBName, ext);
|
||||
rename_database(NewsDBName, ext);
|
||||
rename_database(ExceptionDBName, ext);
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/* Database file descriptor structure and file handling routine prototypes.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: datafiles.h,v 1.4 2003/07/20 01:15:49 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DATAFILES_H
|
||||
#define DATAFILES_H
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
typedef struct dbFILE_ dbFILE;
|
||||
struct dbFILE_ {
|
||||
int mode; /* 'r' for reading, 'w' for writing */
|
||||
FILE *fp; /* The normal file descriptor */
|
||||
FILE *backupfp; /* Open file pointer to a backup copy of
|
||||
* the database file (if non-NULL) */
|
||||
char filename[PATH_MAX]; /* Name of the database file */
|
||||
char backupname[PATH_MAX]; /* Name of the backup file */
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Prototypes and macros: */
|
||||
|
||||
E void check_file_version(dbFILE *f);
|
||||
E int get_file_version(dbFILE *f);
|
||||
E int write_file_version(dbFILE *f, uint32 version);
|
||||
|
||||
E dbFILE *open_db(const char *service, const char *filename, const char *mode, uint32 version);
|
||||
E void restore_db(dbFILE *f); /* Restore to state before open_db() */
|
||||
E void close_db(dbFILE *f);
|
||||
E void backup_databases(void);
|
||||
|
||||
#define read_db(f,buf,len) (fread((buf),1,(len),(f)->fp))
|
||||
#define write_db(f,buf,len) (fwrite((buf),1,(len),(f)->fp))
|
||||
#define getc_db(f) (fgetc((f)->fp))
|
||||
|
||||
E int read_int16(uint16 *ret, dbFILE *f);
|
||||
E int write_int16(uint16 val, dbFILE *f);
|
||||
E int read_int32(uint32 *ret, dbFILE *f);
|
||||
E int write_int32(uint32 val, dbFILE *f);
|
||||
E int read_ptr(void **ret, dbFILE *f);
|
||||
E int write_ptr(const void *ptr, dbFILE *f);
|
||||
E int read_string(char **ret, dbFILE *f);
|
||||
E int write_string(const char *s, dbFILE *f);
|
||||
|
||||
#define read_int8(ret,f) ((*(ret)=fgetc((f)->fp))==EOF ? -1 : 0)
|
||||
#define write_int8(val,f) (fputc((val),(f)->fp)==EOF ? -1 : 0)
|
||||
#define read_buffer(buf,f) (read_db((f),(buf),sizeof(buf)) == sizeof(buf))
|
||||
#define write_buffer(buf,f) (write_db((f),(buf),sizeof(buf)) == sizeof(buf))
|
||||
#define read_buflen(buf,len,f) (read_db((f),(buf),(len)) == (len))
|
||||
#define write_buflen(buf,len,f) (write_db((f),(buf),(len)) == (len))
|
||||
#define read_variable(var,f) (read_db((f),&(var),sizeof(var)) == sizeof(var))
|
||||
#define write_variable(var,f) (write_db((f),&(var),sizeof(var)) == sizeof(var))
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#endif /* DATAFILES_H */
|
||||
@@ -0,0 +1,40 @@
|
||||
/* Set default values for any constants that should be in include files but
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
*
|
||||
* $Id: defs.h,v 1.4 2003/07/20 01:15:49 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef NAME_MAX
|
||||
# define NAME_MAX 255
|
||||
#endif
|
||||
|
||||
#ifndef BUFSIZ
|
||||
# define BUFSIZ 256
|
||||
#else
|
||||
# if BUFSIZ < 256
|
||||
# define BUFSIZ 256
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Length of an array: */
|
||||
#define lenof(a) (sizeof(a) / sizeof(*(a)))
|
||||
|
||||
/* Telling compilers about printf()-like functions: */
|
||||
#ifdef __GNUC__
|
||||
# define FORMAT(type,fmt,start) __attribute__((format(type,fmt,start)))
|
||||
#else
|
||||
# define FORMAT(type,fmt,start)
|
||||
#endif
|
||||
|
||||
/*************************************************************************/
|
||||
@@ -0,0 +1,17 @@
|
||||
Reported Bugs from Mantis: http://www.anope.org/bug
|
||||
===================================================
|
||||
|
||||
.- Strange Segfault on expiring nicknames. Almost arbitrary, very hard
|
||||
to reproduce.
|
||||
|
||||
.- Clone detection can give false warnings if a user connects and then
|
||||
signs off several times in rapid succession. Clone detection also
|
||||
goes off wrongly if a server links and has a number of clients from
|
||||
the same hostname.
|
||||
|
||||
.- If there is absolutely no activity on your network, Services may delay
|
||||
timed events (nick kills, database saving, etc.) until the next message
|
||||
comes in from Services' uplink server.
|
||||
|
||||
.- Modules will not work on OpenBSD machines, due to limitations on libdl.
|
||||
|
||||
+339
@@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
675 Mass Ave, Cambridge, MA 02139, USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Appendix: 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) 19yy <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., 675 Mass Ave, Cambridge, MA 02139, 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) 19yy 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.
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
Anope DefCon
|
||||
------------
|
||||
|
||||
Introduction:
|
||||
|
||||
Anope 1.6 onwards supports a unique protection mechanism based on the
|
||||
military "Defense Readiness Condition" (DefCon) system. It is based on
|
||||
5 levels of defense readiness defined as:
|
||||
|
||||
DEFCON5 Normal peacetime readiness
|
||||
DEFCON4 Increased intelligence and security readiness
|
||||
DEFCON3 Increase in force readiness
|
||||
DEFCON2 Further increase in force readiness
|
||||
DEFCON1 Maximum force readiness.
|
||||
|
||||
These are configurable levels that mandates what actions Anope should
|
||||
take in case of emergency and change in readiness status.
|
||||
|
||||
It is used to prevent abuse to both Services, and the ircd on which they
|
||||
are running. Also to protect the users, primarily in the event of Clones
|
||||
and/or FloodBOT attacks.
|
||||
|
||||
Installation:
|
||||
|
||||
The DefCon system is part of Anope's core,
|
||||
|
||||
The DefCon system has to be configured on your services.conf file to
|
||||
be enabled. All directives are optional unless they depend on what
|
||||
options you enable for each level. Look for the "DefCon configuration"
|
||||
section on your services.conf file for more information.
|
||||
|
||||
Make sure you restart Anope after changing the DefCon configuration
|
||||
directives.
|
||||
|
||||
Configuration:
|
||||
|
||||
Pre-defined DefCon actions:
|
||||
|
||||
No new channel registrations 1
|
||||
No New Nick Registrations 2
|
||||
No MLOCK changes 4
|
||||
Force Chan Mode 8
|
||||
Use Reduced Session Limit 16
|
||||
KILL any new clients trying to connect 32
|
||||
Services will ignore everyone but opers 64
|
||||
Services will silently ignore everyone but opers 128
|
||||
AKILL all new clients trying to connect 256
|
||||
No new memos sent to block memoserv attacks 512
|
||||
|
||||
These are the values used to determine each defcon setting, are set via:
|
||||
|
||||
DefCon1 XX
|
||||
DefCon2 XX
|
||||
DefCon3 XX
|
||||
DefCon4 XX
|
||||
|
||||
To set the desired value, you simply add the value of the numbers together
|
||||
and place that as your DefCon# setting. For instance:
|
||||
|
||||
Say you wish to set:
|
||||
|
||||
No Channel Registrations, No Nickname Registrations and Services Ignoring
|
||||
everyone except for Operators. You would do this by:
|
||||
|
||||
1 + 2 + 128 (Each value listed above is added together)
|
||||
Giving: 131
|
||||
|
||||
You would then place this as which ever Defcon setting you want:
|
||||
|
||||
DefCon1 131
|
||||
|
||||
The recommended default values are safe to use on any network.
|
||||
|
||||
Usage:
|
||||
|
||||
Anope starts up in DEFCON5 (normal readiness). To change the Defcon level
|
||||
in action use:
|
||||
|
||||
/msg OperServ DEFCON 1|2|3|4|5
|
||||
|
||||
Example:
|
||||
|
||||
Place the network on DEFCON4:
|
||||
|
||||
/msg OperServ DEFCON 4
|
||||
|
||||
*** Global -- from OperServ: dengel Changed the DEFCON level to 4
|
||||
|
||||
-OperServ- Services are now at DEFCON 4
|
||||
-OperServ- * No new channel registrations
|
||||
-OperServ- * No new nick registrations
|
||||
-OperServ- * No MLOCK changes
|
||||
-OperServ- * Use the reduced session limit of 5
|
||||
|
||||
-Global- The Defcon Level is now at Level: 4
|
||||
|
||||
Restore normal readiness:
|
||||
|
||||
/msg OperServ DEFCON 5
|
||||
|
||||
*** Global -- from OperServ: dengel Changed the DEFCON level to 5
|
||||
|
||||
-OperServ- Services are now at DEFCON 5
|
||||
|
||||
-Global- Services are now back to normal, sorry for any inconvenience
|
||||
|
||||
Support:
|
||||
|
||||
You might get DefCon support by posting on our online forum, or maybe on
|
||||
our #anope channel at /server irc.anope.org.
|
||||
|
||||
@@ -0,0 +1,423 @@
|
||||
Frequently Asked Questions (FAQ) concerning Anope
|
||||
=================================================
|
||||
|
||||
Index:
|
||||
|
||||
1. What is Anope?
|
||||
|
||||
2. Where can I find Anope?
|
||||
|
||||
3. Does Anope run under Windows?
|
||||
|
||||
4. Can I send you questions without reading the FAQ, INSTALL or
|
||||
README files?
|
||||
|
||||
5. When I run "make", I get an error message like "missing separator",
|
||||
"Unassociated shell command", "Unexpected end of line seen", etc.
|
||||
|
||||
6. I get an error like "Makefile.inc not found".
|
||||
|
||||
7. I typed "./services" at the command line, but nothing happened!
|
||||
|
||||
8. I need support for the XYZ protocol.
|
||||
|
||||
9. Whenever I start Anope, I get a message on my IRC server saying
|
||||
"connection refused" or something similar, and Anope gives an error
|
||||
message from the server saying "Closing Link: ...".
|
||||
|
||||
10. My IRC server is giving me messages like "Connection to
|
||||
services.whatever.net[127.0.0.1] activated" and then "Access denied --
|
||||
no N line". Why?
|
||||
|
||||
11. When I say "/connect services.*", it doesn't work!
|
||||
|
||||
12. Anope complains in the logfile about being unable to load the
|
||||
default language.
|
||||
|
||||
13. Anope always dies after about five minutes, saying "FATAL ERROR!
|
||||
Can't back up nick.db".
|
||||
|
||||
14. Anope starts up okay, but if I try to register a nickname, it comes
|
||||
back with "Sorry, registration failed."
|
||||
|
||||
15. Anope crashed with a segmentation fault.
|
||||
|
||||
16. Anope's channel mode setting doesn't work. I can't set modes with
|
||||
OperServ, and every time ChanServ tries to set a mode, my server
|
||||
reverses the change.
|
||||
|
||||
17. Using the OperServ JUPE command results in server messages like
|
||||
"Server juped.server introduced by non-hub server services.my.net".
|
||||
|
||||
18. I can't use the ADMIN command to add Services admins--it tells me
|
||||
"Permission denied."
|
||||
|
||||
19. When I add an AKILL, the users matching it don't get killed.
|
||||
|
||||
20. Anope reports (via /stats u or /msg OperServ STATS) a different
|
||||
number of users online than I get from doing /lusers.
|
||||
|
||||
21. Anope ignored the SET SUCCESSOR setting and deleted a channel when
|
||||
the founder expired.
|
||||
|
||||
22. Trying to use OperServ gives me "Access denied", but my nick is in the
|
||||
ServicesRoot directive and is registered, and I've identified for my
|
||||
nick.
|
||||
|
||||
23. Anope spricht kein Deutsch!, etc. (Anope doesn't speak my
|
||||
language!)
|
||||
|
||||
24. I selected a language other than English, but sometimes Anope sends
|
||||
responses in English instead.
|
||||
|
||||
25. I've found a bug that's not mentioned here or in the
|
||||
BUGS files. What should I do?
|
||||
|
||||
26. Your Services program doesn't do XYZ like DALnet Services. What's
|
||||
wrong?
|
||||
|
||||
27. I've got a great new idea for Anope. Do you want it?
|
||||
|
||||
28. Examples of features I have been asked about and why we won't add (or
|
||||
haven't yet added) them--so don't ask us about them.
|
||||
|
||||
29. How do I add bots to BotServ?
|
||||
|
||||
30. When I used the OperServ RAW command, Anope and/or my network
|
||||
crashed, or did weird things! Please fix this bug!
|
||||
|
||||
31. I would like to have the list of the differents RAW on operserv
|
||||
|
||||
32. I can't get /OS UMODES and /OS SVSNICK do not work!
|
||||
|
||||
33. What is a Super-Admin? How does it work? Why might it not work?
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
1. What is Anope?
|
||||
|
||||
Anope is a set of services for IRC networks. See the README
|
||||
file for more information. And in case you were wondering,
|
||||
Anope is Epona spelt backwards :)
|
||||
|
||||
|
||||
2. Where can I find Anope?
|
||||
|
||||
The latest version can always be found at the official Anope
|
||||
distribution site:
|
||||
|
||||
http://www.anope.org/
|
||||
|
||||
New version announcements can also be found at http://anope.zero.org/
|
||||
in the Announcement section.
|
||||
|
||||
|
||||
3. Does Anope run under Windows?
|
||||
|
||||
Well... not officialy. Bu there is a cygwin based patch that makes
|
||||
Anope work on Windows. Note, however, that some features might not
|
||||
work, and you should take that into consideration when answering
|
||||
the questions of ./configure (i.e. MySQL, Modules).
|
||||
|
||||
You can obtain a pre-build copy of Anope for Windoes from
|
||||
http://www.wircds.net/ although we have "blessed" that port,
|
||||
we do not provide support for it. If you can't get it work,
|
||||
go to wIRCds.net forum.
|
||||
|
||||
If you feel capable of taking ownership of an official windows
|
||||
port, and to keep it current, please let the current Development
|
||||
team know.
|
||||
|
||||
|
||||
4. Can I send you questions without reading the FAQ, INSTALL or README
|
||||
files?
|
||||
|
||||
No. If you don't read those files, your messages will most probably
|
||||
be ignored. We don't mean to be rude, but if we took the time
|
||||
to write down some documentation, we'd expect you to take some
|
||||
time to read it.
|
||||
|
||||
|
||||
5. When I run "make", I get an error message like "missing separator",
|
||||
"Unassociated shell command", "Unexpected end of line seen", etc.
|
||||
|
||||
Your make program isn't compatible with the Makefile for Anope.
|
||||
The Makefile was designed to work with GNU make, and as such may
|
||||
not work on other systems' "make" programs. If you get an error
|
||||
from "make", obtain GNU make from ftp://prep.ai.mit.edu/pub/gnu/
|
||||
(or wherever you prefer) and use it instead of your system's
|
||||
default "make". Note that GNU make may already be installed on
|
||||
your system; try using the command "gmake" instead of "make".
|
||||
|
||||
The make programs bundled with SunOS/Solaris and FreeBSD have been
|
||||
reported not to work; you will need to use GNU make on these
|
||||
systems.
|
||||
|
||||
6. I get an error like "Makefile.inc not found".
|
||||
|
||||
You forgot to run the configure script first. See the INSTALL file
|
||||
for compilation instructions.
|
||||
|
||||
|
||||
7. I typed "./services" at the command line, but nothing happened!
|
||||
|
||||
Anope puts itself in the background when it starts, so you get
|
||||
your shell prompt right back. Meanwhile, Anope will continue
|
||||
setting up, then connect to the IRC server specified in
|
||||
services.conf (or on the command line). If it doesn't connect, you
|
||||
probably specified the wrong server type when running the configure
|
||||
script. (Also make sure that you are actually running one of the
|
||||
supported servers. There are a gazillion different variations on
|
||||
the basic IRC protocol out there, and I have neither the time nor
|
||||
the desire to add support for them.)
|
||||
|
||||
The recommended server, under which Epona (the original code base
|
||||
used by Anope) was developed, is Bahamut. DreamForge 4.6.7 will also
|
||||
work fine, but it's a bit obsolete nowadays. Derivatives of Bahamut
|
||||
and DreamForge may also work, if they don't change the server<->server
|
||||
protocol too much; contact their authors for more information.
|
||||
Most people, though, are running Anope with UnrealIRCd, UltimateIRCd
|
||||
or Bahamut.
|
||||
|
||||
As always, you can check the log file (services.log by default) for
|
||||
error messages.
|
||||
|
||||
|
||||
8. I need support for the XYZ protocol.
|
||||
|
||||
Hang in there! We are working on making Anope protocol independent.
|
||||
It should show up sometime soon... more details to follow.
|
||||
|
||||
|
||||
9. Whenever I start Anope, I get a message on my IRC server saying
|
||||
"connection refused" or something similar, and Anope gives an error
|
||||
message from the server saying "Closing Link: ...".
|
||||
|
||||
See seection 3 of the INSTALL file.
|
||||
|
||||
|
||||
10. My IRC server is giving me messages like "Connection to
|
||||
services.whatever.net[127.0.0.1] activated" and then "Access denied --
|
||||
no N line". Why?
|
||||
|
||||
This is typically caused by including a port number in the C:line
|
||||
for services, which tells your server to try to autoconnect to it
|
||||
(depending on the class (Y:line) settings). This is not what you
|
||||
want, because Anope will connect to the server itself, but does
|
||||
not listen for servers to connect to it. The solution is to remove
|
||||
the port number from the C:line.
|
||||
|
||||
|
||||
11. When I say "/connect services.*", it doesn't work!
|
||||
|
||||
Of course not. RTFM (Read The Fine Manual), and see the previous
|
||||
answer.
|
||||
|
||||
|
||||
12. Anope complains in the logfile about being unable to load the
|
||||
default language.
|
||||
|
||||
You forgot to run "make install".
|
||||
|
||||
13. Anope always dies after about five minutes, saying "FATAL ERROR!
|
||||
Can't back up nick.db".
|
||||
|
||||
Make sure that the user Anope runs as has write access to the
|
||||
data directory, and that the data directory actually exists (the
|
||||
latter shouldn't be a problem if you ran the configure script).
|
||||
This means Anope needs write and execute permission on the data
|
||||
directory itself and execute permission on every parent directory
|
||||
of the data directory.
|
||||
|
||||
|
||||
14. Anope starts up okay, but if I try to register a nickname, it comes
|
||||
back with "Sorry, registration failed."
|
||||
|
||||
Make sure you've selected the correct IRC server type in the
|
||||
configure script; see question 9 for details.
|
||||
|
||||
|
||||
15. Anope crashed with a segmentation fault.
|
||||
|
||||
See if you can reproduce this by doing a certain sequence of
|
||||
things. If so, please report it to us (see part 6 of README file). If
|
||||
not, you're probably out of luck; if you like, you can report it to
|
||||
us anyway, but chances are it won't get fixed if we don't have
|
||||
instructions on reproducing it. If you do have such a problem, you
|
||||
may find the crontab utility useful for dealing with it.
|
||||
|
||||
Also, see the DumpCore directive in the configuration file. It allows
|
||||
Anope to dump its core whenever it's segfaulting, usually calling it
|
||||
core and placing it into Anope's main directory.
|
||||
Open up gdb by issuing the following command at your shell:
|
||||
gdb services core
|
||||
(of course replacing 'core' with the name of the core if different)
|
||||
and type 'bt' at the gdb prompt. After that, send us the output you
|
||||
got and keep the core file in a safe place, in case we need it to
|
||||
dig deeper into the problem.
|
||||
|
||||
16. Anope's channel mode setting doesn't work. I can't set modes with
|
||||
OperServ, and every time ChanServ tries to set a mode, my server
|
||||
reverses the change.
|
||||
|
||||
Make sure EVERY servers on your network has a U: line for Services in
|
||||
ircd.conf, for example:
|
||||
|
||||
U:services.whatever.net:*:*
|
||||
|
||||
|
||||
17. Using the OperServ JUPE command results in server messages like
|
||||
"Server juped.server introduced by non-hub server services.my.net".
|
||||
|
||||
Services' uplink must have an H: line for Services in the
|
||||
ircd.conf file, which looks something like:
|
||||
|
||||
H:*::services.whatever.net
|
||||
|
||||
|
||||
18. I can't use the ADMIN command to add Services admins--it tells me
|
||||
"Permission denied."
|
||||
|
||||
Did you define yourself as the Services root? You need to insert
|
||||
your nickname in the ServicesRoot directive in services.conf.
|
||||
|
||||
|
||||
19. When I add an AKILL, the users matching it don't get killed.
|
||||
|
||||
Use the AkillOnAdd configuration directive.
|
||||
|
||||
|
||||
20. Anope reports (via /stats u or /msg OperServ STATS) a different
|
||||
number of users online than I get from doing /lusers.
|
||||
|
||||
Anope doesn't count its own pseudo-clients (NickServ, ChanServ,
|
||||
etc.) in its user count.
|
||||
|
||||
|
||||
21. Anope ignored the SET SUCCESSOR setting and deleted a channel when
|
||||
the founder expired.
|
||||
|
||||
Normally, this is because the successor had too many channels
|
||||
registered; in this case, you will see an entry in the log file
|
||||
like the following:
|
||||
|
||||
[date] Successor (SuccessorNick) of channel #somechannel owns too
|
||||
many channels, deleting channel #somechannel
|
||||
|
||||
If you don't get a message like this or you can verify that the
|
||||
successor wasn't running into the channel limit, please report it
|
||||
using the bug-reporting procedure below (see section 6 of the
|
||||
README file).
|
||||
|
||||
|
||||
22. Trying to use OperServ gives me "Access denied", but my nick is in the
|
||||
ServicesRoot directive and is registered, and I've identified for my
|
||||
nick.
|
||||
|
||||
You need to be opered (i.e. user mode +o) to access OperServ.
|
||||
|
||||
|
||||
23. Anope spricht kein Deutsch!, etc. (Anope doesn't speak my
|
||||
language!)
|
||||
|
||||
See section 5 of the README file.
|
||||
|
||||
|
||||
24. I selected a language other than English, but sometimes Anope sends
|
||||
responses in English instead.
|
||||
|
||||
Some language files are not complete--in other words, they don't
|
||||
have a translation of every message Anope uses, but only some of
|
||||
them. In this case, the missing messages will be displayed in
|
||||
English. You can either wait for the primary translator to provide
|
||||
us with a translation, or do the translation yourself and send us
|
||||
the messages translated into your language.
|
||||
|
||||
|
||||
25. I've found a bug that's not mentioned here or in the README or
|
||||
BUGS files. What should I do?
|
||||
|
||||
See section 6 of the README file.
|
||||
|
||||
|
||||
26. Your Services program doesn't do XYZ like DALnet (or other) Services.
|
||||
What's wrong?
|
||||
|
||||
Nothing is wrong, except your expectations. Anope is a
|
||||
completely different program from that used on DALnet; they are
|
||||
similar in concept only.
|
||||
|
||||
|
||||
27. I've got a great new idea for Services. Do you want it?
|
||||
|
||||
We are always interested in hearing new ideas. HOWEVER, do not
|
||||
expect your proposal to be in the next Anope release for sure.
|
||||
As a rule, we usually don't add anything that can be equivalently
|
||||
done by other means, or that we consider totally useless; see below
|
||||
for examples of things we don't plan to add.
|
||||
|
||||
Our general intent is for Anope to provide as much functionality
|
||||
as possible--while staying as lean as possible. So features which
|
||||
are arguably beneficial will tend to be added, while features of
|
||||
limited or no benefit or which can be equally provided by something
|
||||
else already in use will tend to be passed over.
|
||||
|
||||
If you'd like to give us your idea, you can go to our website at
|
||||
http://www.anope.org/ and add it as a Feature Request on our Bug
|
||||
Tracking System. Or, if unsure, you can discuss it on our online
|
||||
Forum, in the Ideas and Suggestions section.
|
||||
|
||||
28. Examples of features we have been asked about and why we won't add (or
|
||||
haven't yet added) them--so don't ask us about them:
|
||||
|
||||
- An option to make ChanServ stay in some/all registered channels:
|
||||
we see absolutely no necessity for this feature, since BotServ
|
||||
already does this anyway.
|
||||
|
||||
- A "current time" field in NickServ and ChanServ INFO displays:
|
||||
Most people have clocks of some sort either on their computer
|
||||
screens or on their walls (or both), and all IRC servers, as well
|
||||
as Services, have a command to return the server's current time.
|
||||
Thus a current-time field in INFO displays would simply take up
|
||||
extra space for no reason.
|
||||
|
||||
|
||||
29. How do I add bots to BotServ?
|
||||
|
||||
Read /msg BotServ HELP and /msg BotServ HELP BOT.
|
||||
|
||||
30. When I used the OperServ RAW command, Anope and/or my network
|
||||
crashed, or did weird things! Please fix this bug!
|
||||
|
||||
"That's not a bug, it's a feature."
|
||||
|
||||
Have you ever typed /msg OperServ HELP RAW? It's clearly stated
|
||||
there that this command is dangerous and that its use may result
|
||||
in very bad things.
|
||||
|
||||
And that's why this command has been disabled by default. If you
|
||||
enabled and used it, YOU'RE ON YOUR OWN. All help requests will
|
||||
be ignored, even if the problem happens not immediately.
|
||||
|
||||
|
||||
31. I would like to have the list of the differents RAW on operserv
|
||||
|
||||
If you have to ask, you should not be messing with RAW :)
|
||||
|
||||
|
||||
32. I can't get /OS UMODES and /OS SVSNICK do not work!
|
||||
|
||||
Make sure you the USE_OSSVS is defined on config.h. Since these
|
||||
are very controversial commands, they are turned off by default.
|
||||
Then, make clean ; make ; make install
|
||||
|
||||
|
||||
33. What is a Super-Admin? How does it work? Why might it not work?
|
||||
|
||||
Super-Admin's have extra privileges, including being founder on
|
||||
all channels. It must be activated on a per user basis and is
|
||||
only available to Services Admins and Services Roots.
|
||||
It is set using OperServ and is not persistent.
|
||||
It only works if SuperAdmin is uncommented in the services
|
||||
configuration file. This is commented by default.
|
||||
Read /msg OperServ HELP SET SUPERADMIN for further help.
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
ANOPE INSTALLATION INSTRUCTIONS
|
||||
===============================
|
||||
|
||||
Table of contents
|
||||
-----------------
|
||||
1. Installing Anope
|
||||
2. Upgrading Anope
|
||||
3. Setting up the IRCd
|
||||
4. Starting Anope
|
||||
5. Setting up a crontab
|
||||
|
||||
You should also read the README and FAQ files!
|
||||
|
||||
1. Installing Anope
|
||||
-------------------
|
||||
|
||||
IMPORTANT NOTE: it is not recommended to use (and therefore install)
|
||||
Anope as root. Use an unprivileged user instead -- the one you're
|
||||
using for the ircd or a dedicated one will be good enough.
|
||||
|
||||
The very first thing you need to do is to get the Anope package
|
||||
(if not already done). You can find it at the following place:
|
||||
|
||||
http://www.anope.org/
|
||||
|
||||
Next, unpack the package in your home directory, and go into the
|
||||
created directory.
|
||||
|
||||
Now type ./configure to start the configuration script. It will
|
||||
ask you a few questions, and figure out how to compile Anope on
|
||||
your system. If you are unsure about the answer to a question,
|
||||
use the default value.
|
||||
|
||||
NOTE: although you may specify different binary and data paths,
|
||||
it is RECOMMENDED that you use the same value for both.
|
||||
|
||||
You can now type make to compile Anope. If there are errors in the
|
||||
Makefile, *try to use gmake* instead. If it still doesn't work, you
|
||||
(or the system administrator if it's a shell) must install GNU
|
||||
make. You may find it at ftp://prep.ai.mit.edu/pub/gnu/.
|
||||
|
||||
Now type make install (or gmake install; see above). This will
|
||||
install all the needed files in the paths you specified with the
|
||||
configure script, and setup file permissions. You should ensure
|
||||
that the data directory is not accessible by other users, as malicious
|
||||
users may cause troubles on your network if passwords are not
|
||||
encrypted, or read the memos of any user.
|
||||
|
||||
If you see errors during this process, please mail us with the
|
||||
*complete* error output, and don't forget to mention your OS,
|
||||
compiler and C library versions.
|
||||
|
||||
Now go into the data directory (by default, ~/services). Copy the
|
||||
example.conf file to services.conf, and open the latter with your
|
||||
favourite text editor. It contains all the configuration
|
||||
directives Anope will use at startup. Read the instructions contained
|
||||
in the file carefully. Using the default values is NOT a good idea,
|
||||
and will most likely not work!
|
||||
|
||||
If you need help, you should subscribe to the Anope mailing list and
|
||||
mail there to get help from other users. See the README file for more
|
||||
information.
|
||||
|
||||
|
||||
2. Upgrading Anope
|
||||
------------------
|
||||
|
||||
If you got a .diff file and want to patch the old Anope sources with it, do
|
||||
the following:
|
||||
* Copy the .diff file into the root Anope sources directory.
|
||||
* Type patch -p1 <file.diff
|
||||
|
||||
To upgrade Anope, just follow the installation instructions described in
|
||||
section 1. There are however a few specific guidelines:
|
||||
|
||||
* IMPORTANT: Back up your old databases!
|
||||
* If you are upgrading to a new major release, ALWAYS restart a
|
||||
fresh configuration file from example.conf.
|
||||
|
||||
|
||||
3. Setting up the IRCd
|
||||
----------------------
|
||||
|
||||
Services acts as an IRC server with pseudo-clients on it. To link
|
||||
them to your network, you'll need to add some lines in the ircd.conf
|
||||
of their hub server (as stated in the RemoteServer configuration
|
||||
directive).
|
||||
|
||||
For samples below we'll take Services.LocalHost.Net as the name of
|
||||
the Services (as stated in the ServerName configuration directive).
|
||||
|
||||
First, the C/N lines, that allow Services to link. They also need a
|
||||
Y:line to work correctly.
|
||||
|
||||
Y:27:180:0:0:4000000
|
||||
C:127.0.0.1:mypass:Services.LocalHost.Net::30
|
||||
N:127.0.0.1:mypass:Services.LocalHost.Net::30
|
||||
|
||||
mypass is the same password you mentionned in the RemoteServer
|
||||
configuration directive. 127.0.0.1 is the IP from which Services
|
||||
connect from (linking in localhost is the most efficient way
|
||||
to run Services).
|
||||
|
||||
Then, you have to set-up an U:line, that will allow Services to
|
||||
change channel modes, topics, and much more without being opped
|
||||
in the channel.
|
||||
|
||||
U:Services.LocalHost.Net:*:*
|
||||
|
||||
NOTE: if you have more than one server in your network, this line
|
||||
MUST be added on ALL servers, or things won't work.
|
||||
|
||||
Finally, you'll need to add an H:line, to make the OperServ JUPE
|
||||
command work correctly.
|
||||
|
||||
H:*::Services.LocalHost.Net
|
||||
|
||||
Don't forget to /rehash to apply changes.
|
||||
|
||||
A new trend in ircd configuration is popping all over the place,
|
||||
good examples are the latest Hybrid and Unreal, which use a more
|
||||
"readable" for of configuration. For those, use something like:
|
||||
|
||||
link Services.LocalHost.Net
|
||||
{
|
||||
username *;
|
||||
hostname localhost;
|
||||
bind-ip *;
|
||||
port 6667;
|
||||
hub *;
|
||||
password-connect "mypass";
|
||||
password-receive "mypass";
|
||||
class servers;
|
||||
};
|
||||
|
||||
|
||||
4. Starting Anope
|
||||
-----------------
|
||||
|
||||
Go into the directory where binaries were installed (by default,
|
||||
~/services). Type ./services to launch Anope.
|
||||
|
||||
If there are syntax errors in the configuration file they will be
|
||||
displayed on the screen. Correct them until there are no errors
|
||||
anymore. A successful startup won't generate any message.
|
||||
|
||||
Give to Services at least one minute to link to your network, as
|
||||
certain IRCds on some OSes may be really slow for the link process.
|
||||
If nothing happens then, it is probably a configuration problem.
|
||||
Try to launch Anope with ./services -debug -nofork to see any errors
|
||||
that it encounters, and try to correct them.
|
||||
|
||||
If you need help to solve errors, feel free to subscribe to the
|
||||
Anope mailing list and ask there. See the README file for details.
|
||||
|
||||
|
||||
5. Setting up a crontab
|
||||
-----------------------
|
||||
|
||||
A crontab entry will allow you to check periodically whether Anope
|
||||
is still running, and restart it if not. You'll need to have
|
||||
Anope binaries and data installed in the same directory for this to
|
||||
work without modification.
|
||||
|
||||
First rename the example.chk script that is in Anope path (by default,
|
||||
~/services) to services.chk and edit it. You'll need to modify the
|
||||
CONFIGURATION part of the file. Then ensure that the file is marked as
|
||||
executable by typing chmod +x services.chk, and try to launch the script
|
||||
to see if it works (Anope must not be running when you do this ;).
|
||||
|
||||
When this is done, you'll have to add the crontab entry. Type crontab -e.
|
||||
This will open the default text editor with the crontab file. Enter the
|
||||
following (with correct path):
|
||||
*/5 * * * * /home/ircd/services/services.chk >/dev/null 2>&1
|
||||
The */5 at the beginning means "check every 5 minutes". You may replace
|
||||
the 5 with other another number if you want (but less than 60).
|
||||
Save and exit, and it's installed.
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
Anope Modules
|
||||
-------------
|
||||
|
||||
Introduction:
|
||||
|
||||
Anope 1.6 onwards supports external modules. External modules are pieces
|
||||
of code that can be attached to a running Anope process dynamically. These
|
||||
modules can serve several purposes, and perform all kind of operations to
|
||||
enhance your network.
|
||||
|
||||
Installation:
|
||||
|
||||
1. You need to configure Anope to be compiled with module support. To
|
||||
do so you must run ./configure and answer "Yes" when asked for
|
||||
Module Support, and selecting a folder where your modules will live
|
||||
in (the default path is safe for most people).
|
||||
|
||||
Notes:
|
||||
|
||||
* Modules are not supported on the following platforms: OpenBSD, Windows.
|
||||
* You might need to run "make distclean" prior to running ./configure
|
||||
|
||||
2. Compile Anope as usual. The gmake process will now compile module
|
||||
support into Anope, and compile the default sample modules, and/or
|
||||
any other module located on the "modules" folder.
|
||||
|
||||
3. Install Anope as usual. The install process will place the compiled
|
||||
modules in their runtime location, making them available for loading.
|
||||
|
||||
4. Start or restart services to make use of the new Anope executable.
|
||||
|
||||
Usage:
|
||||
|
||||
All module manipulation commands are done through OperServ. These are:
|
||||
|
||||
MODLOAD Load a module
|
||||
MODUNLOAD Un-Load a module
|
||||
MODLIST List loaded modules
|
||||
MODINFO Info about a loaded module
|
||||
|
||||
These commands available to Service Roots only.
|
||||
|
||||
You can also load (and pre-load) Modules automatically by loading them
|
||||
on startup. To do so, edit your services.conf file and change the values
|
||||
of "ModuleAutoload" and "ModuleDelayedAutoload" to include the modules
|
||||
you want to load every time Anope starts.
|
||||
|
||||
Example:
|
||||
|
||||
/msg OperServ modload hs_moo
|
||||
*** Global -- from OperServ: dengel loaded module hs_moo
|
||||
-OperServ- Module hs_moo loaded
|
||||
|
||||
/msg OperServ modinfo hs_moo
|
||||
-OperServ- Module: hs_moo Version: 1.1 Author: Anope loaded: Mar 21 10:54:37 2004 CLT
|
||||
-OperServ- Providing command: /msg HostServ moo
|
||||
|
||||
/msg HostServ moo
|
||||
-HostServ- MOO! - This command was loaded via a module!
|
||||
|
||||
/msg OperServ modunload hs_moo
|
||||
*** Global -- from OperServ: dengel unloaded module hs_moo
|
||||
-OperServ- Module hs_moo unloaded
|
||||
|
||||
/msg HostServ moo
|
||||
-HostServ- Unknown command moo. "/msg HostServ HELP" for help.
|
||||
|
||||
* Note that the name of the module file is "hs_moo.c", yet we load
|
||||
and reference the module as "hs_moo" only. By naming convention
|
||||
modules have an abreviated service name they attach to (hs_ for
|
||||
HostServ, cs_ for ChanServ, etc) followed by a descriptive keyword.
|
||||
|
||||
More Modules:
|
||||
|
||||
Anope ships with two sample modules that only ilustrates some of the
|
||||
implemented module capabilities. They don't really do much or anything
|
||||
useful.
|
||||
|
||||
You can download more useful modules from http://www.anope.org/ or from
|
||||
our interim modules development website http://modules.anope.org/. Just
|
||||
grab the module file (usualy with a .c extension). Place the module
|
||||
file on your compile "modules" folder. The same folder that contain both
|
||||
hs_moo.c and catserv.c module files.
|
||||
|
||||
The new modules need to be compiled and installed before you can make
|
||||
use of them:
|
||||
|
||||
1. Change directories to your compile "modules" folder.
|
||||
2. Run ./configure
|
||||
3. Run make
|
||||
4. Run make install
|
||||
|
||||
You can now use /msg OperServ MODLOAD to load the new modules.
|
||||
|
||||
Support:
|
||||
|
||||
The Anope team is not responsible or liable for any unofficial module
|
||||
(i.e. anything other than what was released with the Anope package).
|
||||
|
||||
Use modules at your own risk, and make sure you get them from a
|
||||
reputable source. You might get module support by contacting the module
|
||||
author, posting on our online forum, or maybe on our #anope channel
|
||||
at /server irc.anope.org.
|
||||
|
||||
Developers:
|
||||
|
||||
Please take a look at:
|
||||
|
||||
* http://geniusdex.dezeserver.nl/anope
|
||||
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
Anope MySQL Support
|
||||
-------------------
|
||||
|
||||
Introduction:
|
||||
|
||||
Anope 1.6 onwards supports MySQL databases. On Anope 1.6.0 only PHASE 1
|
||||
has been implemented. Since the next phases require major changes in the
|
||||
core, we decided to save it for 2.0. However, having your db's easily
|
||||
accessible on your website is still a great feature.
|
||||
|
||||
PHASE 1:Anope will be able to save all it's databases to MySQL. It will
|
||||
happen in conjuction with the current FFF databases. This first step is
|
||||
nothing more than a MySQL dump of the databases (i.e. read-only), since
|
||||
Anope will not (for now) read from Mysql. (COMPLETED)
|
||||
|
||||
PHASE 2:The next step is load the databases from mysql, being able to
|
||||
replace the FFF completely as an archive method (since all changes to
|
||||
the mysql db would be lost on the next Services save). All, while keeping
|
||||
FFF intact. This is still not the final goal, but it's a milestone.
|
||||
|
||||
PHASE 3:The next step, and most convoluted of all (since we'll need to
|
||||
modify pretty much all the source) is to load/save (SELECT/INSERT) data
|
||||
in realtime. That way the mysql db could be modified externaly (web?).
|
||||
Again, the FFF will be kept intact.
|
||||
|
||||
Requirements:
|
||||
|
||||
1. MySQL server version 3.23.32 or greater
|
||||
2. MySQL libs and development files (usualy called mysql-dev).
|
||||
3. A MySQL user account
|
||||
4. A MySQL database
|
||||
|
||||
Installation:
|
||||
|
||||
1. You need to configure Anope to be compiled with MySQL support. To
|
||||
do so you must run ./configure and answer "Yes" when asked for
|
||||
MySQL Support.
|
||||
|
||||
Notes:
|
||||
|
||||
* MySQL is not supported on the following platforms: Windows.
|
||||
* You might need to run "make distclean" prior to running ./configure
|
||||
|
||||
2. Compile Anope as usual. The gmake process will now compile MySQL
|
||||
support into Anope.
|
||||
|
||||
3. Install Anope as usual.
|
||||
|
||||
Configuration:
|
||||
|
||||
1. Run bin/mydbgen to help on the schema creation and adjustments.
|
||||
|
||||
2. Edit services.conf and add your mysql data to the MySQL configuration
|
||||
block.
|
||||
|
||||
3. Start or restart services to make use of the new Anope executable.
|
||||
|
||||
Security:
|
||||
|
||||
To add a layer of security you have the option of encrypting or encoding
|
||||
all passwords for nicks and chans. Use the "MysqlSecure" directive on your
|
||||
services.conf file to enable it. The availabe storage methods are:
|
||||
|
||||
#MysqlSecure "" or MysqlSecure ""
|
||||
|
||||
Disables security. All passwords will be saved on the MySQL database
|
||||
as clear text, with no encryption or encoding. FASTEST
|
||||
|
||||
MysqlSecure "des"
|
||||
|
||||
Encrypts all passwords using a unix DES encription. This is a one way
|
||||
encryption algorithm. You can only validate it agains another DES
|
||||
encrypted string, using the same "salt" (the first two characters of
|
||||
the encrypted string). FAST
|
||||
|
||||
MysqlSecure "md5"
|
||||
|
||||
Calculates an MD5 128-bit checksum for the password. The value is
|
||||
returned as a 32-digit hex number that may be used as a hash key.
|
||||
SLOW
|
||||
|
||||
MysqlSecure "sha"
|
||||
|
||||
Calculates an SHA 160-bit checksum for the password. The value is
|
||||
returned as a 40-digit hex number. SLOWEST
|
||||
|
||||
MysqlSecure "mykey"
|
||||
|
||||
Encodes the passwords using "mykey" as the encryption password. It
|
||||
produces a binary string and can be decoded using the MySQL builtit
|
||||
function DECODE(crypt_str,mykey). VARIABLE
|
||||
|
||||
Caveat: Keep in mind that this if you use any method other than clear
|
||||
text, services will need to encrypt/encode every single password on
|
||||
every database save. On large networks, it may impact responsiveness
|
||||
during the saves.
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
Highlighted News in Anope 1.6
|
||||
=============================
|
||||
* Fixed various exploits and vulverabilities.
|
||||
* Fixed various language typos and inconsistencies.
|
||||
* Improved ignore system.
|
||||
* Improved ./configure script.
|
||||
* Removed all compile warning fixed.
|
||||
* Converted HelpServ into a proper service.
|
||||
* Added external module support.
|
||||
* Added Defense Condition (DEFCON) System.
|
||||
* Added MySQL support for mirroring databases.
|
||||
* Added multi-server configuration.
|
||||
* Added multi-domain /OS GLOBAL support.
|
||||
* Added combined +oq +oa +ha +va on net-joins.
|
||||
* Added support for ircd changes and upgrades.
|
||||
* Added HostSetters configuration directive.
|
||||
* Added /OS STAFF command.
|
||||
* Added /OS SVSNICK command.
|
||||
* Added /OS CHANKILL command.
|
||||
* Added /MS STAFF command.
|
||||
* Added /NS UPDATE command.
|
||||
* Added /MS SENDALL command.
|
||||
* Added /NS GETMAIL command.
|
||||
* Added /HS DELALL command.
|
||||
* Added /HS LIST command with pattern matching.
|
||||
* New support scripts and tools.
|
||||
* New ircd support, complete list: DreamForge 4.6.7, Bahamut 1.4.27,
|
||||
UnrealIRCd 3.1.1, UltimateIRCd 2.8.2,
|
||||
UltimateIRCd 3.0.0, Hybrid IRCd 7.0
|
||||
ViagraIRCd 1.3.x, PTlink 6.15.0
|
||||
* New Language files, complete list: cat.l, de.l, en_us.l, es.l, fr.l,
|
||||
gr.l, it.l, nl.l, pt.l, ru.l, tr.l
|
||||
|
||||
Highlighted News in Anope 1.4
|
||||
=============================
|
||||
|
||||
After the change from Epona to Anope
|
||||
------------------------------------
|
||||
* New Italian Language file
|
||||
* Added support for UltimateIRCd 3.0 and later
|
||||
* Services realtime logging to a channel
|
||||
* SuperAdmin directive for access to "super" commands.
|
||||
* Ban system is now exception aware.
|
||||
* HostServ for hostname masquarading.
|
||||
* Smarter XOP System.
|
||||
* Email verification/handshake upon registration.
|
||||
* Services can now /ignore users.
|
||||
* Smarter memo notification for channels.
|
||||
* Channel can be SUSPENDed instead of FORBIDen.
|
||||
|
||||
Before the change from Epona to Anope
|
||||
-------------------------------------
|
||||
* HostServ for networks that support them.
|
||||
* UnrealIRCd support has been rewritten, it is now fully
|
||||
working (hopefully) and officially supported again.
|
||||
* Added support for UltimateIRCd 2.8.2 and later.
|
||||
* A multi-threaded proxy detector that can scan Wingates,
|
||||
SOCKS 4/5 and HTTP proxies on ports 3128 and 8080. Don't use
|
||||
it if you have not been authorized to use it by your system
|
||||
administrator!
|
||||
* The ChanServ AOP/SOP/VOP commands, and, on networks that
|
||||
support halfops, the HOP command, have been added. They
|
||||
allow a more user-friendly control of channel privileges.
|
||||
* Use of services IDs that allow an user to be automatically
|
||||
identified after a split (if he was identified before the split)
|
||||
in a secure way. This also saves lots of bandwidth.
|
||||
* Services' default language can now be set in services.conf.
|
||||
* The OperServ RANDOMNEWS command provides an easy way to show
|
||||
network news in a random manner without flooding your users
|
||||
with them (one news per connection).
|
||||
* The BotServ SET PRIVATE option allows services admins to
|
||||
make the bot usable by IRC operators only.
|
||||
* The OperServ SQLINE command allows you to forbid nick masks
|
||||
and even channel masks with the latest Bahamut.
|
||||
* The ChanServ AKICK STICK command allows akicks to be permanently
|
||||
kept on channel.
|
||||
* The ChanServ SET TOPIC command has been renamed to TOPIC, and
|
||||
a new BAN command has been added. They both have their own
|
||||
associated levels.
|
||||
* A SET PEACE command has been added to ChanServ. It prevents
|
||||
users to use pejorative services commands (DEOP, KICK, ...)
|
||||
on users with greater or equal levels.
|
||||
|
||||
Networks using Bahamut must upgrade to Bahamut 1.4.27 or later,
|
||||
while networks using UnrealIRCd must upgrade to Unreal 3.1.1.
|
||||
|
||||
For the full changes, see the Changes file.
|
||||
|
||||
For announcements and discussions about Anope, subscribe to the mailing
|
||||
list by sending an e-mail to epona-request@epona.org with "subscribe"
|
||||
in the body (quotes excluded). You can then post to the mailing list
|
||||
by sending an e-mail to epona@epona.org.
|
||||
+307
@@ -0,0 +1,307 @@
|
||||
Anope -- a set of IRC services for IRC networks
|
||||
===============================================
|
||||
|
||||
Anope is 2003-2004 Anope Team <info@anope.org>
|
||||
Based on Epona 2000-2002 PegSoft <epona@pegsoft.net>.
|
||||
Based on Services 1996-1999 Andrew Church <achurch@dragonfire.net>.
|
||||
|
||||
This program is free but copyrighted software; see the file COPYING for
|
||||
details.
|
||||
|
||||
Information about Anope may be found at http://www.anope.org/
|
||||
Information about Epona may be found at http://www.epona.org/
|
||||
Information about Services may be found at http://www.ircservices.za.net/
|
||||
|
||||
TABLE OF CONTENTS
|
||||
-----------------
|
||||
1. Credits
|
||||
2. Presentation
|
||||
3. Installation
|
||||
4. Command line options
|
||||
5. Messages translation
|
||||
6. Contact and mailing list
|
||||
|
||||
1. CREDITS
|
||||
----------
|
||||
|
||||
Anope is based on Lara's Epona version 1.4.14.
|
||||
Epona is based on Andy Church's IRC Services version 4.3.3.
|
||||
|
||||
The original credits:
|
||||
Mauritz Antunes -- Portuguese translation
|
||||
Jose R. Holzmann, Raul S. Villarreal -- Spanish translation
|
||||
Andrew Kempe <theshadow@shadowfire.org> -- news system
|
||||
<d.duca@eurcom.net> -- Italian translation
|
||||
<mikado@holyfire.com> -- Turkish translation
|
||||
Andrew Kempe <theshadow@shadowfire.org> -- session limiting
|
||||
Epona credits:
|
||||
lara <lara@pegsoft.net> -- Main coding
|
||||
CafeiN <oytuny@yahoo.com> -- Turkish translation
|
||||
Sylvain Cresto aka tost <scresto@netsante.fr> -- FreeBSD 5 patch
|
||||
Marcelo Conde Foscarini aka Bras <ircadmin@brmarket.net> -- Portuguese translation
|
||||
Alvaro Toledo aka POLLITO <atoledo@keldon.org> -- Spanish translation
|
||||
chemical <chemical@musicplay.de> -- German translation
|
||||
shine <dh@shinewelt.de> -- German translation
|
||||
Guven Guzelbey aka MeShGuL <guzelbey@cs.utk.edu> -- Turkish translation
|
||||
Jordi Pujol <jordi.pujol@aujac.org> -- Catalan translation
|
||||
Eva Dachs <evadachs@terra.es> -- Catalan translation
|
||||
Toni Perez <toni.perez@aujac.org> -- Catalan translation
|
||||
Sergios Karalis <sergios_k@hotmail.com> -- Greek translation
|
||||
Thomas J. Stensas aka ShadowMaster <shadowmaster@shadow-realm.org> -- Ultimate 3.x support
|
||||
Anope credits:
|
||||
Adam Kramer <ribosome@anope.org>
|
||||
Alvaro Toledo <atoledo@keldon.org>
|
||||
Björn Stiddien <keeper@anope.org>
|
||||
Daniel Engel <dane@zero.org>
|
||||
David <dv@diboo.net>
|
||||
David Narayan <jester@phrixus.net>
|
||||
David Robson <rob@anope.org>
|
||||
Daniele Nicolucci <jollino@sogno.net>
|
||||
Florian Schulze <certus@anope.org>
|
||||
JH <jh@irc-chat.net>
|
||||
Joris Vink <joris@anope.org>
|
||||
Lucas Nussbaum <lucas@lucas-nussbaum.net>
|
||||
Thomas Juberg Stensås <ShadowMaster@Shadow-Realm.org>
|
||||
Trystan .S Lee <trystan@anope.org>
|
||||
openglx <openglx@brasnerd.com.br>
|
||||
Anope Translations:
|
||||
GeniousDex (nl.l)
|
||||
Oleg Nikolaev aka Isot <isot@complife.ru> (ru.l)
|
||||
Stuff <the.stuff@gmx.de> (de.l)
|
||||
DrStein (es.l)
|
||||
|
||||
|
||||
2. PRESENTATION
|
||||
---------------
|
||||
|
||||
Anope is a set of Services for IRC networks that allows users to
|
||||
manage their nicks and channels in a secure and efficient way, and
|
||||
administrators to manage their network with powerful tools.
|
||||
|
||||
Currently available services are:
|
||||
|
||||
* NickServ, a powerful nickname manager that users can use to
|
||||
protect themselves against nick stealing. Each user has its
|
||||
own nickname group, that allows him to register as many nicks as
|
||||
he needs while still being able to take profit of his privileges
|
||||
and to modify his nick configuration. NickServ also has an optional
|
||||
password retrieval feature.
|
||||
|
||||
* ChanServ, a powerful channel manager that helps users to administer
|
||||
their channels in a totally customizable way. ChanServ has an internal
|
||||
list of privilegied users and banned users that controls accesses
|
||||
on a per-channel basis. It eliminates all takeover problems,
|
||||
because of its powerful op/unban/invite and even mass deop and mass
|
||||
kick functions.
|
||||
|
||||
* MemoServ, an helpful companion that allows sending short messages
|
||||
to offline users, that they can then read when they come online
|
||||
later.
|
||||
|
||||
* BotServ, an original service that allows users to get a permanent,
|
||||
friendly bot on their channels in an easy way. Each bot can be
|
||||
configured to monitor the channels against floods, repetitions,
|
||||
caps writing, swear, and take appropriate actions. It also can
|
||||
handle user-friendly commands (!op,!deop,!voice,!devoice,!kick,...),
|
||||
say a short greet message when an user joins a channel, and even
|
||||
"take over" ChanServ actions such as auto-opping users, saying the
|
||||
entry notice, and so on. This service can be disabled if you
|
||||
want to save some bandwidth.
|
||||
|
||||
* OperServ, the IRCops' and IRC admins' black box, that allows them
|
||||
to manage the list of network bans (also known as AKILL (DALnet) or
|
||||
GLINE (Undernet)), to configure messages displayed to users when
|
||||
they log on, to set modes and to kick users from any channel,
|
||||
to send notices quickly to the entire network, and much more!
|
||||
|
||||
* HostServ, a neat service that allows users to show custom
|
||||
vHosts (virtual hosts) instead of their real IP address; this only
|
||||
works on deamons supporting ip cloaking, such as UnrealIRCd and
|
||||
UltimateIRCd.
|
||||
|
||||
* HelpServ, a skeleton service used to serve help files.
|
||||
|
||||
Anope currently works with:
|
||||
- DreamForge 4.6.7
|
||||
- Bahamut 1.4.27 or later
|
||||
- UnrealIRCd 3.1.1 or later (including 3.2)
|
||||
- UltimateIRCd 2.8.2 or later (including 3.0.0)
|
||||
- ViagraIRCd 1.3 or later
|
||||
- Hybrid 7 or later
|
||||
- PTlink 6.15 or later
|
||||
|
||||
Anope could also work with some of the deamons derivated by the ones
|
||||
listed above.
|
||||
|
||||
|
||||
3. INSTALLATION
|
||||
---------------
|
||||
|
||||
See the INSTALL file.
|
||||
|
||||
|
||||
4. COMMAND LINE OPTIONS
|
||||
-----------------------
|
||||
|
||||
Normally, Anope can be run simply by invoking the "services"
|
||||
executable. Anope will then use the defaults specified in the
|
||||
services.conf file, and connect to the specified uplink server.
|
||||
Alternatively, any of the following command-line options can be specified
|
||||
to change the default values:
|
||||
|
||||
-remote server[:port] Connect to the specified server
|
||||
-local host -or- Connect from the specified address (e.g.
|
||||
[host]:[port] for multihomed servers)
|
||||
-name servername Our server name (e.g. services.some.net)
|
||||
-desc string Description of us (e.g. SomeNet Services)
|
||||
-user username Username for Services' nicks (e.g. services)
|
||||
-host hostname Hostname for Services' nicks (e.g. esper.net)
|
||||
-dir directory Directory containing Services' data files
|
||||
(e.g. /usr/local/lib/services)
|
||||
-log filename Services log filename (e.g. services.log)
|
||||
-update secs How often to update databases (in seconds)
|
||||
-expire secs How often to check for nick/channel
|
||||
expiration (in seconds)
|
||||
|
||||
Additionally, the following command-line options can be used to modify
|
||||
the behavior of Anope:
|
||||
|
||||
-debug Enable debugging mode--more info sent to log
|
||||
(give option more times for more info)
|
||||
-readonly Enable read-only mode--no changes to
|
||||
databases allowed, .db files and log
|
||||
not written
|
||||
-skeleton Enable skeleton mode--like read-only mode,
|
||||
but only OperServ is available
|
||||
-nofork Do not fork after startup; log messages will
|
||||
be written to terminal (as well as to
|
||||
the log file if not in read-only mode)
|
||||
-forceload Try to load as much of the databases as
|
||||
possible, even if errors are encountered
|
||||
-noexpire Expiration routines won't be run at all
|
||||
-logchan Startup with logchan enabled
|
||||
|
||||
Upon starting, Anope will parse its command-line parameters, open
|
||||
its logfile, then (assuming the -nofork option is not given) detach itself
|
||||
and run in the background. If Anope encounters a problem reading the
|
||||
database files or cannot connect to its uplink server, it will terminate
|
||||
immediately; otherwise, it will run until the connection is terminated (or
|
||||
a QUIT, SHUTDOWN, or RESTART command is sent--see OperServ's help). In the
|
||||
case of an error, an appropriate error message will be written to the log
|
||||
file.
|
||||
|
||||
If Anope is run with the "-readonly" command-line option, it can
|
||||
serve as a "backup" to the full version of services. A "full" version of
|
||||
services (run without -readonly) will automatically reintroduce its
|
||||
pseudo-clients (NickServ, ChanServ, etc.), while a "backup" services will
|
||||
not, thus allowing full services to be brought up at any time without
|
||||
disrupting the network (and without having to take backup services down
|
||||
beforehand).
|
||||
|
||||
If Anope is run with the "-skeleton" command-line option, it will
|
||||
not try to load the nickname or channel databases, and will respond with
|
||||
"service is inactive" messages to any commands sent to NickServ, ChanServ,
|
||||
MemoServ or BotServ. This can be useful as an emergency stopgap measure
|
||||
when the main copy of Anope cannot be started.
|
||||
|
||||
The "-debug" option is useful if you find or suspect a problem in
|
||||
Anope. Giving it once on the command line will cause all traffic to and
|
||||
from services as well as some other debugging information to be recorded in
|
||||
the log file; if you send a bug report, PLEASE include an excerpt from the
|
||||
log file WITH DEBUGGING ACTIVE--I cannot emphasize enough how important
|
||||
this is to tracking down problems. (You can also enable debugging while
|
||||
Services is running using OperServ's SET DEBUG command.) If you repeat the
|
||||
-debug option more than once, the debugging level will be increased, which
|
||||
provides more detailed information but may also slow Anope down
|
||||
considerably and make the log file grow dramatically faster (in particular,
|
||||
at debug level 4 a message is written to the log for every character
|
||||
received from the server). In general, a debug level of 1 is sufficient
|
||||
for the coding team to be able to trace a problem, because all network
|
||||
traffic is included and we can usually reproduce the problem.
|
||||
|
||||
The "-forceload" option is provided to attempt recovery of data from
|
||||
corrupted or truncated databases. Normally, if Anope encounters an
|
||||
error writing to a database file, it will attempt to restore the original
|
||||
version of the file and report an error to the logfile and through WALLOPS.
|
||||
However, if this should fail (which normally should not happen), or if
|
||||
Anope is terminated abruptly e.g. by kill -9 or a power failure, then
|
||||
one or more of the databases may be corrupt. Normally, this will cause
|
||||
Anope to abort the next time you try to run it; however, if you give
|
||||
the -forceload option to Anope, it will instead read as much as it can,
|
||||
then skip to the next database. For obvious reasons, it's recommended to
|
||||
keep backup copies of your databases in case something does happen (since
|
||||
Anope will stop at the first error even with -forceload, meaning you
|
||||
lose any data after that).
|
||||
|
||||
|
||||
5. MESSAGES TRANSLATIONS
|
||||
------------------------
|
||||
|
||||
Anope has a powerful option in NickServ allowing users to choose what
|
||||
language it must use when sending messages to users. Messages
|
||||
are stored in language files (located in the lang directory).
|
||||
|
||||
Anope is currently provided with eleven languages: Catalan, Dutch, English,
|
||||
French, German, Greek, Italian, Portuguese, Russian, Spanish and
|
||||
Turkish. If you want to translate Anope messages into another language,
|
||||
follow the following instructions:
|
||||
|
||||
* Copy the lang/en_us.l file to a meaningful name (for example, if
|
||||
you would like to translate messages in Spanish, you would
|
||||
rename it to es.l).
|
||||
* Edit the file with your favourite text editor. Carefully read
|
||||
the instructions given at the top of the file, and start
|
||||
translating the whole file. The file is big so make sure you have
|
||||
some coffee available. ;) Try to avoid the use of English words
|
||||
as much as possible. If the new language contains only a few 'special'
|
||||
characters, try and use latin representations of it, if possible.
|
||||
Remember that most clients are only capable of handling the
|
||||
ISO-8859-1 charset. Of course, if you are translating Anope to a
|
||||
language with a totally different charset, such as Russian, feel free
|
||||
to use the one that suites it best (and the one that is in use by
|
||||
most speakers of that language ;).
|
||||
* When this is done, you have two solutions: either patch Services
|
||||
source code so they take in account the new language file (basically,
|
||||
you'll have to modify lang/Makefile, language.c and maybe services.h),
|
||||
or send us the translated file so we can make the patch and
|
||||
include your language in the next Anope release.
|
||||
* Note that there is a language tool on bin/langtool.pl that can aid
|
||||
the verification process on newly created language files. Try to use
|
||||
it before you submit a language file.
|
||||
|
||||
When new major releases come out, you'll not have to retranslate the whole
|
||||
file; the Changes.lang file will help you to know which messages were
|
||||
added, modified or deleted.
|
||||
|
||||
If you did a language file translation, and want to let others use it,
|
||||
please send it to dev@anope.org (don't forget to mention clearly your
|
||||
(nick)name, your e-mail and the language name). You'll of course get full
|
||||
credit for it, and will even get future final major releases before anyone
|
||||
else to complete the translation!... ;)
|
||||
|
||||
|
||||
6. CONTACT
|
||||
---------------------------
|
||||
|
||||
* For announcements and discussions about Anope, please visit our Portal
|
||||
and Forums at http://www.anope.org/ make sure you register yourself and
|
||||
your netowrk to get full benefits.
|
||||
|
||||
* If you read the documentation carefully, and didn't find the answer
|
||||
to your question, feel free to post on the website forums or join our
|
||||
irc channel (irc.anope.org #anope). Once you join our Support channel,
|
||||
just type "? report" for instructions on how to report a Bug. Be as
|
||||
precise as possible when asking a question, because we have no extraordinary
|
||||
powers and can't guess things if they aren't provided. The more precise you
|
||||
are, the sooner you'll be likely to get an answer.
|
||||
|
||||
* If you think you found a bug, add it to the bug tracking system on our
|
||||
website (http://www.anope.org) and - again - be as precise as possible. Also
|
||||
say whether the bug happens always or under what circumstances, and anything
|
||||
that could be useful to track your bug down. If you wrote a patch, send it
|
||||
over. :)
|
||||
|
||||
* We do *not* support Windows versions of Anope. You must seek support from
|
||||
the website you downloaded the Windows port from. Anope Services was never
|
||||
meant to run on Windows... it might in the future, but for the time being
|
||||
you are on your own. And for Mac fans... Anope runs like a champ on OSX.
|
||||
@@ -0,0 +1,434 @@
|
||||
/* Include file for high-level encryption routines.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: encrypt.c,v 1.5 2003/07/20 01:15:49 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "services.h"
|
||||
#include "encrypt.h"
|
||||
|
||||
#ifdef USE_ENCRYPTION
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/******** Code specific to the type of encryption. ********/
|
||||
|
||||
#ifdef /********/ ENCRYPT_MD5 /********/
|
||||
|
||||
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
|
||||
rights reserved.
|
||||
|
||||
License to copy and use this software is granted provided that it
|
||||
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
|
||||
Algorithm" in all material mentioning or referencing this software
|
||||
or this function.
|
||||
|
||||
License is also granted to make and use derivative works provided
|
||||
that such works are identified as "derived from the RSA Data
|
||||
Security, Inc. MD5 Message-Digest Algorithm" in all material
|
||||
mentioning or referencing the derived work.
|
||||
|
||||
RSA Data Security, Inc. makes no representations concerning either
|
||||
the merchantability of this software or the suitability of this
|
||||
software for any particular purpose. It is provided "as is"
|
||||
without express or implied warranty of any kind.
|
||||
|
||||
These notices must be retained in any copies of any part of this
|
||||
documentation and/or software.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
typedef unsigned int UINT4;
|
||||
|
||||
/* MD5 context. */
|
||||
typedef struct {
|
||||
UINT4 state[4]; /* state (ABCD) */
|
||||
UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
|
||||
unsigned char buffer[64]; /* input buffer */
|
||||
} MD5_CTX;
|
||||
|
||||
/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
|
||||
*/
|
||||
|
||||
typedef void *POINTER;
|
||||
|
||||
/* Constants for MD5Transform routine.
|
||||
*/
|
||||
#define S11 7
|
||||
#define S12 12
|
||||
#define S13 17
|
||||
#define S14 22
|
||||
#define S21 5
|
||||
#define S22 9
|
||||
#define S23 14
|
||||
#define S24 20
|
||||
#define S31 4
|
||||
#define S32 11
|
||||
#define S33 16
|
||||
#define S34 23
|
||||
#define S41 6
|
||||
#define S42 10
|
||||
#define S43 15
|
||||
#define S44 21
|
||||
|
||||
static void MD5Transform(UINT4[4], unsigned char[64]);
|
||||
static void Encode(unsigned char *, UINT4 *, unsigned int);
|
||||
static void Decode(UINT4 *, unsigned char *, unsigned int);
|
||||
|
||||
static unsigned char PADDING[64] = {
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/* F, G, H and I are basic MD5 functions.
|
||||
*/
|
||||
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
|
||||
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
|
||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
#define I(x, y, z) ((y) ^ ((x) | (~z)))
|
||||
|
||||
/* ROTATE_LEFT rotates x left n bits.
|
||||
*/
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
|
||||
|
||||
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
|
||||
Rotation is separate from addition to prevent recomputation.
|
||||
*/
|
||||
#define FF(a, b, c, d, x, s, ac) { \
|
||||
(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define GG(a, b, c, d, x, s, ac) { \
|
||||
(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define HH(a, b, c, d, x, s, ac) { \
|
||||
(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define II(a, b, c, d, x, s, ac) { \
|
||||
(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
|
||||
/* MD5 initialization. Begins an MD5 operation, writing a new context.
|
||||
*/
|
||||
static void MD5Init(context)
|
||||
MD5_CTX *context; /* context */
|
||||
{
|
||||
context->count[0] = context->count[1] = 0;
|
||||
/* Load magic initialization constants.
|
||||
*/
|
||||
context->state[0] = 0x67452301;
|
||||
context->state[1] = 0xefcdab89;
|
||||
context->state[2] = 0x98badcfe;
|
||||
context->state[3] = 0x10325476;
|
||||
}
|
||||
|
||||
/* MD5 block update operation. Continues an MD5 message-digest
|
||||
operation, processing another message block, and updating the
|
||||
context.
|
||||
*/
|
||||
static void MD5Update(context, input, inputLen)
|
||||
MD5_CTX *context; /* context */
|
||||
unsigned char *input; /* input block */
|
||||
unsigned int inputLen; /* length of input block */
|
||||
{
|
||||
unsigned int i, index, partLen;
|
||||
|
||||
/* Compute number of bytes mod 64 */
|
||||
index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
|
||||
|
||||
/* Update number of bits */
|
||||
if ((context->count[0] += ((UINT4) inputLen << 3))
|
||||
< ((UINT4) inputLen << 3))
|
||||
context->count[1]++;
|
||||
context->count[1] += ((UINT4) inputLen >> 29);
|
||||
|
||||
partLen = 64 - index;
|
||||
|
||||
/* Transform as many times as possible.
|
||||
*/
|
||||
if (inputLen >= partLen) {
|
||||
memcpy
|
||||
((POINTER) & context->buffer[index], (POINTER) input, partLen);
|
||||
MD5Transform(context->state, context->buffer);
|
||||
|
||||
for (i = partLen; i + 63 < inputLen; i += 64)
|
||||
MD5Transform(context->state, &input[i]);
|
||||
|
||||
index = 0;
|
||||
} else
|
||||
i = 0;
|
||||
|
||||
/* Buffer remaining input */
|
||||
memcpy
|
||||
((POINTER) & context->buffer[index], (POINTER) & input[i],
|
||||
inputLen - i);
|
||||
}
|
||||
|
||||
/* MD5 finalization. Ends an MD5 message-digest operation, writing the
|
||||
the message digest and zeroizing the context.
|
||||
*/
|
||||
static void MD5Final(digest, context)
|
||||
unsigned char digest[16]; /* message digest */
|
||||
MD5_CTX *context; /* context */
|
||||
{
|
||||
unsigned char bits[8];
|
||||
unsigned int index, padLen;
|
||||
|
||||
/* Save number of bits */
|
||||
Encode(bits, context->count, 8);
|
||||
|
||||
/* Pad out to 56 mod 64.
|
||||
*/
|
||||
index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
|
||||
padLen = (index < 56) ? (56 - index) : (120 - index);
|
||||
MD5Update(context, PADDING, padLen);
|
||||
|
||||
/* Append length (before padding) */
|
||||
MD5Update(context, bits, 8);
|
||||
/* Store state in digest */
|
||||
Encode(digest, context->state, 16);
|
||||
|
||||
/* Zeroize sensitive information.
|
||||
*/
|
||||
memset((POINTER) context, 0, sizeof(*context));
|
||||
}
|
||||
|
||||
/* MD5 basic transformation. Transforms state based on block.
|
||||
*/
|
||||
static void MD5Transform(state, block)
|
||||
UINT4 state[4];
|
||||
unsigned char block[64];
|
||||
{
|
||||
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
|
||||
|
||||
Decode(x, block, 64);
|
||||
|
||||
/* Round 1 */
|
||||
FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
|
||||
FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
|
||||
FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
|
||||
FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
|
||||
FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
|
||||
FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
|
||||
FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
|
||||
FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
|
||||
FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
|
||||
FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
|
||||
FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
|
||||
FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
|
||||
FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
|
||||
FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
|
||||
FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
|
||||
FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
|
||||
|
||||
/* Round 2 */
|
||||
GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
|
||||
GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
|
||||
GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
|
||||
GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
|
||||
GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
|
||||
GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
|
||||
GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
|
||||
GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
|
||||
GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
|
||||
GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
|
||||
GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
|
||||
GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
|
||||
GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
|
||||
GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
|
||||
GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
|
||||
GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
|
||||
|
||||
/* Round 3 */
|
||||
HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
|
||||
HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
|
||||
HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
|
||||
HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
|
||||
HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
|
||||
HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
|
||||
HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
|
||||
HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
|
||||
HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
|
||||
HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
|
||||
HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
|
||||
HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
|
||||
HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
|
||||
HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
|
||||
HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
|
||||
HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
|
||||
|
||||
/* Round 4 */
|
||||
II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
|
||||
II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
|
||||
II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
|
||||
II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
|
||||
II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
|
||||
II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
|
||||
II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
|
||||
II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
|
||||
II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
|
||||
II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
|
||||
II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
|
||||
II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
|
||||
II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
|
||||
II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
|
||||
II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
|
||||
II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
|
||||
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
|
||||
/* Zeroize sensitive information.
|
||||
*/
|
||||
memset((POINTER) x, 0, sizeof(x));
|
||||
}
|
||||
|
||||
/* Encodes input (UINT4) into output (unsigned char). Assumes len is
|
||||
a multiple of 4.
|
||||
*/
|
||||
static void Encode(output, input, len)
|
||||
unsigned char *output;
|
||||
UINT4 *input;
|
||||
unsigned int len;
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0, j = 0; j < len; i++, j += 4) {
|
||||
output[j] = (unsigned char) (input[i] & 0xff);
|
||||
output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff);
|
||||
output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff);
|
||||
output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
/* Decodes input (unsigned char) into output (UINT4). Assumes len is
|
||||
a multiple of 4.
|
||||
*/
|
||||
static void Decode(output, input, len)
|
||||
UINT4 *output;
|
||||
unsigned char *input;
|
||||
unsigned int len;
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0, j = 0; j < len; i++, j += 4)
|
||||
output[i] = ((UINT4) input[j]) | (((UINT4) input[j + 1]) << 8) |
|
||||
(((UINT4) input[j + 2]) << 16) | (((UINT4) input[j + 3]) <<
|
||||
24);
|
||||
}
|
||||
|
||||
#endif /******** ENCRYPT_MD5 ********/
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/******** Our own high-level routines. ********/
|
||||
|
||||
|
||||
#define XTOI(c) ((c)>9 ? (c)-'A'+10 : (c)-'0')
|
||||
|
||||
/* Encrypt `src' of length `len' and store the result in `dest'. If the
|
||||
* resulting string would be longer than `size', return -1 and leave `dest'
|
||||
* unchanged; else return 0.
|
||||
*/
|
||||
int encrypt(const char *src, int len, char *dest, int size)
|
||||
{
|
||||
|
||||
#ifdef ENCRYPT_MD5
|
||||
|
||||
MD5_CTX context;
|
||||
char digest[33];
|
||||
int i;
|
||||
|
||||
if (size < 16)
|
||||
return -1;
|
||||
|
||||
memset(&context, 0, sizeof(context));
|
||||
memset(&digest, 0, sizeof(digest));
|
||||
|
||||
MD5Init(&context);
|
||||
MD5Update(&context, src, len);
|
||||
MD5Final(digest, &context);
|
||||
for (i = 0; i < 32; i += 2)
|
||||
dest[i / 2] = XTOI(digest[i]) << 4 | XTOI(digest[i + 1]);
|
||||
return 0;
|
||||
|
||||
#endif
|
||||
|
||||
return -1; /* unknown encryption algorithm */
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Shortcut for encrypting a null-terminated string in place. */
|
||||
int encrypt_in_place(char *buf, int size)
|
||||
{
|
||||
return encrypt(buf, strlen(buf), buf, size);
|
||||
}
|
||||
|
||||
|
||||
/* Compare a plaintext string against an encrypted password. Return 1 if
|
||||
* they match, 0 if not, and -1 if something went wrong. */
|
||||
|
||||
int check_password(const char *plaintext, const char *password)
|
||||
{
|
||||
char buf[BUFSIZE];
|
||||
|
||||
if (encrypt(plaintext, strlen(plaintext), buf, sizeof(buf)) < 0)
|
||||
return -1;
|
||||
#ifdef ENCRYPT_MD5
|
||||
if (memcmp(buf, password, 16) == 0)
|
||||
#else
|
||||
if (0)
|
||||
#endif
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#else /* !USE_ENCRYPTION */
|
||||
|
||||
int encrypt(const char *src, int len, char *dest, int size)
|
||||
{
|
||||
if (size < len)
|
||||
return -1;
|
||||
memcpy(dest, src, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int encrypt_in_place(char *buf, int size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int check_password(const char *plaintext, const char *password)
|
||||
{
|
||||
if (strcmp(plaintext, password) == 0)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* USE_ENCRYPTION */
|
||||
|
||||
/*************************************************************************/
|
||||
@@ -0,0 +1,17 @@
|
||||
/* Include file for high-level encryption routines.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: encrypt.h,v 1.4 2003/07/20 01:15:49 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
extern int encrypt(const char *src, int len, char *dest, int size);
|
||||
extern int encrypt_in_place(char *buf, int size);
|
||||
extern int check_password(const char *plaintext, const char *password);
|
||||
@@ -0,0 +1,838 @@
|
||||
/* Prototypes and external variable declarations.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: extern.h,v 1.65 2004/03/13 13:55:59 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EXTERN_H
|
||||
#define EXTERN_H
|
||||
|
||||
#include "slist.h"
|
||||
|
||||
#define E extern
|
||||
|
||||
|
||||
/**** modules.c ****/
|
||||
E void moduleCallBackRun(void);
|
||||
|
||||
/**** actions.c ****/
|
||||
|
||||
E void change_user_mode(User *u, char *modes, char *arg);
|
||||
E void kill_user(const char *source, const char *user, const char *reason);
|
||||
E void bad_password(User *u);
|
||||
|
||||
/**** botserv.c ****/
|
||||
|
||||
E BotInfo *botlists[256];
|
||||
|
||||
E void get_botserv_stats(long *nrec, long *memuse);
|
||||
|
||||
E void bs_init(void);
|
||||
E void botserv(User *u, char *buf);
|
||||
E void botmsgs(User *u, BotInfo *bi, char *buf);
|
||||
E void botchanmsgs(User *u, ChannelInfo *ci, char *buf);
|
||||
E void load_bs_dbase(void);
|
||||
E void save_bs_dbase(void);
|
||||
E void save_bs_rdb_dbase(void);
|
||||
|
||||
E BotInfo *findbot(char *nick);
|
||||
E void bot_join(ChannelInfo *ci);
|
||||
E void bot_rejoin_all(BotInfo *bi);
|
||||
|
||||
/**** channels.c ****/
|
||||
|
||||
E Channel *chanlist[1024];
|
||||
E CBMode cbmodes[128];
|
||||
E CBModeInfo cbmodeinfos[];
|
||||
|
||||
E void get_channel_stats(long *nrec, long *memuse);
|
||||
E Channel *findchan(const char *chan);
|
||||
E Channel *firstchan(void);
|
||||
E Channel *nextchan(void);
|
||||
|
||||
E void chan_deluser(User *user, Channel *c);
|
||||
|
||||
E int is_on_chan(Channel *c, User *u);
|
||||
E User *nc_on_chan(Channel *c, NickCore *nc);
|
||||
|
||||
E char *chan_get_modes(Channel *chan, int complete, int plus);
|
||||
E void chan_set_modes(const char *source, Channel *chan, int ac, char **av, int check);
|
||||
|
||||
E int chan_get_user_status(Channel *chan, User *user);
|
||||
E int chan_has_user_status(Channel *chan, User *user, int16 status);
|
||||
E void chan_remove_user_status(Channel *chan, User *user, int16 status);
|
||||
E void chan_set_user_status(Channel *chan, User *user, int16 status);
|
||||
|
||||
E int get_access_level(ChannelInfo *ci, NickAlias *na);
|
||||
E char *get_xop_level(int level);
|
||||
|
||||
E void do_cmode(const char *source, int ac, char **av);
|
||||
E void do_join(const char *source, int ac, char **av);
|
||||
E void do_kick(const char *source, int ac, char **av);
|
||||
E void do_part(const char *source, int ac, char **av);
|
||||
E void do_sjoin(const char *source, int ac, char **av);
|
||||
E void do_topic(const char *source, int ac, char **av);
|
||||
E void do_mass_mode(char *modes);
|
||||
#define whosends(ci) ((!(ci) || !((ci)->botflags & BS_SYMBIOSIS) || !(ci)->bi || !(ci)->c || (ci)->c->usercount < BSMinUsers) ? s_ChanServ : (ci)->bi->nick)
|
||||
|
||||
/**** chanserv.c ****/
|
||||
|
||||
E ChannelInfo *chanlists[256];
|
||||
E CSModeUtil csmodeutils[];
|
||||
|
||||
E void listchans(int count_only, const char *chan);
|
||||
E void get_chanserv_stats(long *nrec, long *memuse);
|
||||
|
||||
E void cs_init(void);
|
||||
E void chanserv(User *u, char *buf);
|
||||
E void load_cs_dbase(void);
|
||||
E void save_cs_dbase(void);
|
||||
E void save_cs_rdb_dbase(void);
|
||||
E void expire_chans(void);
|
||||
E void cs_remove_nick(const NickCore *nc);
|
||||
E void cs_remove_bot(const BotInfo *bi);
|
||||
|
||||
E void check_modes(Channel *c);
|
||||
#ifdef IRC_ULTIMATE3
|
||||
E int check_valid_admin(User *user, Channel *chan, int servermode);
|
||||
#endif
|
||||
E int check_valid_op(User *user, Channel *chan, int servermode);
|
||||
E int check_should_op(User *user, const char *chan);
|
||||
E int check_should_voice(User *user, const char *chan);
|
||||
#ifdef HAS_HALFOP
|
||||
E int check_should_halfop(User *user, const char *chan);
|
||||
#endif
|
||||
#if defined(IRC_UNREAL) || defined(IRC_VIAGRA)
|
||||
E int check_should_owner(User *user, const char *chan);
|
||||
E int check_should_protect(User *user, const char *chan);
|
||||
#endif
|
||||
#ifdef IRC_ULTIMATE3
|
||||
E int check_should_protect(User *user, const char *chan);
|
||||
#endif
|
||||
E int check_kick(User *user, char *chan);
|
||||
E void record_topic(const char *chan);
|
||||
E void restore_topic(const char *chan);
|
||||
E int check_topiclock(Channel *c, time_t topic_time);
|
||||
|
||||
E ChannelInfo *cs_findchan(const char *chan);
|
||||
E int check_access(User *user, ChannelInfo *ci, int what);
|
||||
E int is_founder(User *user, ChannelInfo *ci);
|
||||
E int get_access(User *user, ChannelInfo *ci);
|
||||
E ChanAccess *get_access_entry(NickCore *nc, ChannelInfo *ci);
|
||||
E void update_cs_lastseen(User *user, ChannelInfo *ci);
|
||||
E int get_idealban(ChannelInfo *ci, User *u, char *ret, int retlen);
|
||||
E AutoKick *is_stuck(ChannelInfo *ci, char *mask);
|
||||
E void stick_mask(ChannelInfo *ci, AutoKick *akick);
|
||||
E void stick_all(ChannelInfo *ci);
|
||||
|
||||
#ifdef HAS_FMODE
|
||||
E char *cs_get_flood(ChannelInfo *ci);
|
||||
E void cs_set_flood(ChannelInfo *ci, char *value);
|
||||
#endif
|
||||
E char *cs_get_key(ChannelInfo *ci);
|
||||
E void cs_set_key(ChannelInfo *ci, char *value);
|
||||
E char *cs_get_limit(ChannelInfo *ci);
|
||||
E void cs_set_limit(ChannelInfo *ci, char *value);
|
||||
#ifdef HAS_LMODE
|
||||
E char *cs_get_redirect(ChannelInfo *ci);
|
||||
E void cs_set_redirect(ChannelInfo *ci, char *value);
|
||||
#endif
|
||||
|
||||
/**** compat.c ****/
|
||||
|
||||
#if !HAVE_SNPRINTF
|
||||
# if BAD_SNPRINTF
|
||||
# define snprintf my_snprintf
|
||||
# endif
|
||||
# define vsnprintf my_vsnprintf
|
||||
E int vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
|
||||
E int snprintf(char *buf, size_t size, const char *fmt, ...);
|
||||
#endif
|
||||
#if !HAVE_STRICMP && !HAVE_STRCASECMP
|
||||
E int stricmp(const char *s1, const char *s2);
|
||||
E int strnicmp(const char *s1, const char *s2, size_t len);
|
||||
#endif
|
||||
#if !HAVE_STRDUP
|
||||
E char *strdup(const char *s);
|
||||
#endif
|
||||
#if !HAVE_STRSPN
|
||||
E size_t strspn(const char *s, const char *accept);
|
||||
#endif
|
||||
#if !HAVE_STRERROR
|
||||
E char *strerror(int errnum);
|
||||
#endif
|
||||
#if !HAVE_STRSIGNAL
|
||||
char *strsignal(int signum);
|
||||
#endif
|
||||
|
||||
|
||||
/**** config.c ****/
|
||||
|
||||
E char *RemoteServer;
|
||||
E int RemotePort;
|
||||
E char *RemotePassword;
|
||||
E char *RemoteServer2;
|
||||
E int RemotePort2;
|
||||
E char *RemotePassword2;
|
||||
E char *RemoteServer3;
|
||||
E int RemotePort3;
|
||||
E char *RemotePassword3;
|
||||
E char *LocalHost;
|
||||
E int LocalPort;
|
||||
|
||||
E char *ServerName;
|
||||
E char *ServerDesc;
|
||||
E char *ServiceUser;
|
||||
E char *ServiceHost;
|
||||
|
||||
E char *HelpChannel;
|
||||
E char *LogChannel;
|
||||
E char **NetworkDomains;
|
||||
E int DomainNumber;
|
||||
E char *NetworkName;
|
||||
|
||||
E char *s_NickServ;
|
||||
E char *s_ChanServ;
|
||||
E char *s_MemoServ;
|
||||
E char *s_BotServ;
|
||||
E char *s_HelpServ;
|
||||
E char *s_OperServ;
|
||||
E char *s_GlobalNoticer;
|
||||
E char *s_IrcIIHelp;
|
||||
E char *s_DevNull;
|
||||
E char *desc_NickServ;
|
||||
E char *desc_ChanServ;
|
||||
E char *desc_MemoServ;
|
||||
E char *desc_BotServ;
|
||||
E char *desc_HelpServ;
|
||||
E char *desc_OperServ;
|
||||
E char *desc_GlobalNoticer;
|
||||
E char *desc_IrcIIHelp;
|
||||
E char *desc_DevNull;
|
||||
|
||||
E char *HostDBName;
|
||||
E char *desc_HostServ;
|
||||
E char *s_HostServ;
|
||||
E void load_hs_dbase(void);
|
||||
E void save_hs_dbase(void);
|
||||
E void save_hs_rdb_dbase(void);
|
||||
E int do_on_id(User *u);
|
||||
E void delHostCore(char *nick);
|
||||
E void hostserv(User *u, char *buf);
|
||||
|
||||
E char *s_NickServAlias;
|
||||
E char *s_ChanServAlias;
|
||||
E char *s_MemoServAlias;
|
||||
E char *s_BotServAlias;
|
||||
E char *s_HelpServAlias;
|
||||
E char *s_OperServAlias;
|
||||
E char *s_GlobalNoticerAlias;
|
||||
E char *s_DevNullAlias;
|
||||
E char *s_HostServAlias;
|
||||
E char *desc_NickServAlias;
|
||||
E char *desc_ChanServAlias;
|
||||
E char *desc_MemoServAlias;
|
||||
E char *desc_BotServAlias;
|
||||
E char *desc_HelpServAlias;
|
||||
E char *desc_OperServAlias;
|
||||
E char *desc_GlobalNoticerAlias;
|
||||
E char *desc_DevNullAlias;
|
||||
E char *desc_HostServAlias;
|
||||
|
||||
E char *PIDFilename;
|
||||
E char *MOTDFilename;
|
||||
E char *NickDBName;
|
||||
E char *PreNickDBName;
|
||||
E char *ChanDBName;
|
||||
E char *BotDBName;
|
||||
E char *OperDBName;
|
||||
E char *AutokillDBName;
|
||||
E char *NewsDBName;
|
||||
|
||||
E int NoBackupOkay;
|
||||
E int StrictPasswords;
|
||||
E int BadPassLimit;
|
||||
E int BadPassTimeout;
|
||||
E int UpdateTimeout;
|
||||
E int ExpireTimeout;
|
||||
E int ReadTimeout;
|
||||
E int WarningTimeout;
|
||||
E int TimeoutCheck;
|
||||
E int KeepLogs;
|
||||
E int KeepBackups;
|
||||
E int ForceForbidReason;
|
||||
E int UsePrivmsg;
|
||||
E int DumpCore;
|
||||
E int LogUsers;
|
||||
|
||||
E char **HostSetters;
|
||||
E int HostNumber;
|
||||
|
||||
E int UseMail;
|
||||
E char *SendMailPath;
|
||||
E char *SendFrom;
|
||||
E int RestrictMail;
|
||||
E int MailDelay;
|
||||
E int DontQuoteAddresses;
|
||||
|
||||
E int ProxyDetect;
|
||||
E int ProxyThreads;
|
||||
E char *ProxyMessage[8];
|
||||
E int ProxyCheckWingate;
|
||||
E int ProxyCheckSocks4;
|
||||
E int ProxyCheckSocks5;
|
||||
E int ProxyCheckHTTP1;
|
||||
E int ProxyCheckHTTP2;
|
||||
E int ProxyCheckHTTP3;
|
||||
E int ProxyTimeout;
|
||||
E char *ProxyTestServer;
|
||||
E int ProxyTestPort;
|
||||
E int ProxyExpire;
|
||||
E int ProxyCacheExpire;
|
||||
E char *ProxyAkillReason;
|
||||
E int WallProxy;
|
||||
E int ProxyMax;
|
||||
|
||||
E int NSDefFlags;
|
||||
E int NSDefLanguage;
|
||||
E int NSRegDelay;
|
||||
E int NSExpire;
|
||||
E int NSRExpire;
|
||||
E int NSForceEmail;
|
||||
E int NSMaxAliases;
|
||||
E int NSAccessMax;
|
||||
E char *NSEnforcerUser;
|
||||
E char *NSEnforcerHost;
|
||||
E int NSReleaseTimeout;
|
||||
E int NSAllowKillImmed;
|
||||
E int NSNoGroupChange;
|
||||
E int NSListOpersOnly;
|
||||
E int NSListMax;
|
||||
E char *NSGuestNickPrefix;
|
||||
E int NSSecureAdmins;
|
||||
E int NSStrictPrivileges;
|
||||
E int NSEmailReg;
|
||||
E int NSModeOnID;
|
||||
E int NSRestrictGetPass;
|
||||
|
||||
E int CSDefFlags;
|
||||
E int CSMaxReg;
|
||||
E int CSExpire;
|
||||
E int CSDefBantype;
|
||||
E int CSAccessMax;
|
||||
E int CSAutokickMax;
|
||||
E char *CSAutokickReason;
|
||||
E int CSInhabit;
|
||||
E int CSListOpersOnly;
|
||||
E int CSListMax;
|
||||
E int CSRestrictGetPass;
|
||||
E int CSOpersOnly;
|
||||
|
||||
E int MSMaxMemos;
|
||||
E int MSSendDelay;
|
||||
E int MSNotifyAll;
|
||||
|
||||
E int BSDefFlags;
|
||||
E int BSKeepData;
|
||||
E int BSMinUsers;
|
||||
E int BSBadWordsMax;
|
||||
E int BSSmartJoin;
|
||||
E int BSGentleBWReason;
|
||||
|
||||
E int HideStatsO;
|
||||
E int GlobalOnCycle;
|
||||
E int AnonymousGlobal;
|
||||
E char *GlobalOnCycleMessage;
|
||||
E char *GlobalOnCycleUP;
|
||||
E char **ServicesRoots;
|
||||
E int RootNumber;
|
||||
E int LogMaxUsers;
|
||||
E int SuperAdmin;
|
||||
E int LogBot;
|
||||
E int AutokillExpiry;
|
||||
E int ChankillExpiry;
|
||||
E int SGLineExpiry;
|
||||
E int SQLineExpiry;
|
||||
E int SZLineExpiry;
|
||||
E int AkillOnAdd;
|
||||
E int DisableRaw;
|
||||
E int WallOper;
|
||||
E int WallBadOS;
|
||||
E int WallOSGlobal;
|
||||
E int WallOSMode;
|
||||
E int WallOSClearmodes;
|
||||
E int WallOSKick;
|
||||
E int WallOSAkill;
|
||||
E int WallOSSGLine;
|
||||
E int WallOSSQLine;
|
||||
E int WallOSSZLine;
|
||||
E int WallOSNoOp;
|
||||
E int WallOSJupe;
|
||||
E int WallOSRaw;
|
||||
E int WallAkillExpire;
|
||||
E int WallSGLineExpire;
|
||||
E int WallSQLineExpire;
|
||||
E int WallSZLineExpire;
|
||||
E int WallExceptionExpire;
|
||||
E int WallDrop;
|
||||
E int WallForbid;
|
||||
E int WallGetpass;
|
||||
E int WallSetpass;
|
||||
E int CheckClones;
|
||||
E int CloneMinUsers;
|
||||
E int CloneMaxDelay;
|
||||
E int CloneWarningDelay;
|
||||
E int KillClones;
|
||||
E int AddAkiller;
|
||||
|
||||
E char **ModulesAutoload;
|
||||
E int ModulesNumber;
|
||||
E char **ModulesDelayedAutoload;
|
||||
E int ModulesDelayedNumber;
|
||||
|
||||
|
||||
E int KillClonesAkillExpire;
|
||||
|
||||
E int LimitSessions;
|
||||
E int DefSessionLimit;
|
||||
E int ExceptionExpiry;
|
||||
E int MaxSessionKill;
|
||||
E int MaxSessionLimit;
|
||||
E int SessionAutoKillExpiry;
|
||||
E char *ExceptionDBName;
|
||||
E char *SessionLimitDetailsLoc;
|
||||
E char *SessionLimitExceeded;
|
||||
|
||||
#ifdef USE_RDB
|
||||
E int rdb_init();
|
||||
E int rdb_open();
|
||||
E int rdb_close();
|
||||
E int rdb_tag_table(char *table);
|
||||
E int rdb_tag_table(char *table);
|
||||
E int rdb_clear_table(char *table);
|
||||
E int rdb_scrub_table(char *table, char *clause);
|
||||
E int rdb_direct_query(char *query);
|
||||
E int rdb_ns_set_display(char *newnick, char *oldnick);
|
||||
E int rdb_cs_set_founder(char *channel, char *founder);
|
||||
E int rdb_cs_deluser(char *nick);
|
||||
E int rdb_cs_delchan(ChannelInfo * ci);
|
||||
E void rdb_save_ns_core(NickCore * nc);
|
||||
E void rdb_save_ns_alias(NickAlias * na);
|
||||
E void rdb_save_ns_req(NickRequest * nr);
|
||||
E void rdb_save_cs_info(ChannelInfo * ci);
|
||||
E void rdb_save_bs_core(BotInfo * bi);
|
||||
E void rdb_save_bs_rdb_core(BotInfo * bi);
|
||||
E void rdb_save_hs_core(HostCore * hc);
|
||||
E void rdb_save_os_db(unsigned int maxucnt, unsigned int maxutime,
|
||||
SList * ak, SList * sgl, SList * sql, SList * szl,
|
||||
HostCache * hc);
|
||||
E void rdb_save_news(NewsItem * ni);
|
||||
E void rdb_save_exceptions(Exception * e);
|
||||
#endif
|
||||
|
||||
#ifdef USE_MYSQL
|
||||
E char *MysqlHost;
|
||||
E char *MysqlUser;
|
||||
E char *MysqlPass;
|
||||
E char *MysqlName;
|
||||
E int MysqlPort;
|
||||
E char *MysqlSock;
|
||||
E char *MysqlSecure;
|
||||
E int MysqlRetries;
|
||||
E int MysqlRetryGap;
|
||||
#endif
|
||||
|
||||
E int read_config(int reload);
|
||||
|
||||
E int DefConLevel;
|
||||
E int DefCon[6];
|
||||
E int checkDefCon(int level);
|
||||
E void resetDefCon(int level);
|
||||
E int DefConSessionLimit;
|
||||
E char *DefConTimeOut;
|
||||
E char *DefConAKILL;
|
||||
E char *DefConChanModes;
|
||||
E int GlobalOnDefcon;
|
||||
E int GlobalOnDefconMore;
|
||||
E char *DefconMessage;
|
||||
E char *DefConAkillReason;
|
||||
E char *DefConOffMessage;
|
||||
|
||||
/**** converter.c ****/
|
||||
|
||||
E int convert_ircservices_44(void);
|
||||
|
||||
/**** init.c ****/
|
||||
|
||||
E void introduce_user(const char *user);
|
||||
E int init(int ac, char **av);
|
||||
E int servernum;
|
||||
|
||||
/**** language.c ****/
|
||||
|
||||
E char **langtexts[NUM_LANGS];
|
||||
E char *langnames[NUM_LANGS];
|
||||
E int langlist[NUM_LANGS];
|
||||
|
||||
E void lang_init(void);
|
||||
#define getstring(na,index) \
|
||||
(langtexts[((na)&&((NickAlias*)na)->nc&&!(((NickAlias*)na)->status & NS_VERBOTEN)?((NickAlias*)na)->nc->language:NSDefLanguage)][(index)])
|
||||
#define getstring2(nc,index) \
|
||||
(langtexts[((nc)?((NickCore*)nc)->language:NSDefLanguage)][(index)])
|
||||
E int strftime_lang(char *buf, int size, User *u, int format, struct tm *tm);
|
||||
E void syntax_error(const char *service, User *u, const char *command, int msgnum);
|
||||
|
||||
|
||||
/**** list.c ****/
|
||||
|
||||
E void do_listnicks(int ac, char **av);
|
||||
E void do_listchans(int ac, char **av);
|
||||
|
||||
|
||||
/**** log.c ****/
|
||||
|
||||
E int open_log(void);
|
||||
E void close_log(void);
|
||||
E void alog(const char *fmt, ...) FORMAT(printf,1,2);
|
||||
E void log_perror(const char *fmt, ...) FORMAT(printf,1,2);
|
||||
E void fatal(const char *fmt, ...) FORMAT(printf,1,2);
|
||||
E void fatal_perror(const char *fmt, ...) FORMAT(printf,1,2);
|
||||
|
||||
/**** mail.c ****/
|
||||
|
||||
E MailInfo *MailBegin(User *u, NickCore *nc, char *subject, char *service);
|
||||
E MailInfo *MailRegBegin(User *u, NickRequest *nr, char *subject, char *service);
|
||||
E void MailEnd(MailInfo *mail);
|
||||
E void MailReset(User *u, NickCore *nc);
|
||||
E int MailValidate(const char *email);
|
||||
|
||||
/**** main.c ****/
|
||||
|
||||
E const char version_number[];
|
||||
E const char version_build[];
|
||||
E const char version_protocol[];
|
||||
E const char version_flags[];
|
||||
|
||||
E char *services_dir;
|
||||
E char *log_filename;
|
||||
E int debug;
|
||||
E int readonly;
|
||||
E int logchan;
|
||||
E int skeleton;
|
||||
E int nofork;
|
||||
E int forceload;
|
||||
E int noexpire;
|
||||
|
||||
#ifdef USE_RDB
|
||||
E int do_mysql;
|
||||
#endif
|
||||
|
||||
E int is44;
|
||||
|
||||
E int quitting;
|
||||
E int delayed_quit;
|
||||
E char *quitmsg;
|
||||
E char inbuf[BUFSIZE];
|
||||
E int servsock;
|
||||
E int save_data;
|
||||
E int got_alarm;
|
||||
E time_t start_time;
|
||||
|
||||
E void save_databases(void);
|
||||
|
||||
/**** memory.c ****/
|
||||
|
||||
E void *smalloc(long size);
|
||||
E void *scalloc(long elsize, long els);
|
||||
E void *srealloc(void *oldptr, long newsize);
|
||||
E char *sstrdup(const char *s);
|
||||
|
||||
|
||||
/**** memoserv.c ****/
|
||||
|
||||
E void ms_init(void);
|
||||
E void memoserv(User *u, char *buf);
|
||||
E void check_memos(User *u);
|
||||
|
||||
|
||||
/**** misc.c ****/
|
||||
|
||||
E char *strscpy(char *d, const char *s, size_t len);
|
||||
E char *stristr(char *s1, char *s2);
|
||||
E char *strnrepl(char *s, int32 size, const char *old, const char *new);
|
||||
|
||||
E char *merge_args(int argc, char **argv);
|
||||
|
||||
E int match_wild(const char *pattern, const char *str);
|
||||
E int match_wild_nocase(const char *pattern, const char *str);
|
||||
|
||||
E int dotime(const char *s);
|
||||
E char *duration(NickAlias *na, char *buf, int bufsize, time_t seconds);
|
||||
E char *expire_left(NickAlias *na, char *buf, int len, time_t expires);
|
||||
|
||||
typedef int (*range_callback_t)(User *u, int num, va_list args);
|
||||
E int process_numlist(const char *numstr, int *count_ret,
|
||||
range_callback_t callback, User *u, ...);
|
||||
|
||||
E int isValidHost(const char *host, int type);
|
||||
E int isvalidchar(char c);
|
||||
|
||||
E char *myStrGetToken(const char *str, const char dilim, int token_number);
|
||||
E char *myStrGetOnlyToken(const char *str, const char dilim,
|
||||
int token_number);
|
||||
E char *myStrSubString(const char *src, int start, int end);
|
||||
E char *myStrGetTokenRemainder(const char *str, const char dilim,
|
||||
int token_number);
|
||||
E void doCleanBuffer(char *str);
|
||||
|
||||
/**** news.c ****/
|
||||
|
||||
E void get_news_stats(long *nrec, long *memuse);
|
||||
E void load_news(void);
|
||||
E void save_news(void);
|
||||
E void save_rdb_news(void);
|
||||
E void display_news(User *u, int16 type);
|
||||
E int do_logonnews(User *u);
|
||||
E int do_opernews(User *u);
|
||||
E int do_randomnews(User *u);
|
||||
|
||||
|
||||
/**** nickserv.c ****/
|
||||
|
||||
E NickAlias *nalists[1024];
|
||||
E NickCore *nclists[1024];
|
||||
E NickRequest *nrlists[1024];
|
||||
|
||||
E void listnicks(int count_only, const char *nick);
|
||||
E void get_aliases_stats(long *nrec, long *memuse);
|
||||
E void get_core_stats(long *nrec, long *memuse);
|
||||
|
||||
E void ns_init(void);
|
||||
E void nickserv(User *u, char *buf);
|
||||
E void load_ns_dbase(void);
|
||||
E void load_ns_req_db(void);
|
||||
E void save_ns_dbase(void);
|
||||
E void save_ns_req_dbase(void);
|
||||
E void save_ns_rdb_dbase(void);
|
||||
E void save_ns_req_rdb_dbase(void);
|
||||
E int validate_user(User *u);
|
||||
E void cancel_user(User *u);
|
||||
E int nick_identified(User *u);
|
||||
E int nick_recognized(User *u);
|
||||
E void expire_nicks(void);
|
||||
E void expire_requests(void);
|
||||
E int ns_do_register(User * u);
|
||||
|
||||
E int delnick(NickAlias *na);
|
||||
E NickAlias *findnick(const char *nick);
|
||||
E NickCore *findcore(const char *nick);
|
||||
E void clean_ns_timeouts(NickAlias *na);
|
||||
|
||||
/**** helpserv.c ****/
|
||||
E void helpserv(User *u, char *buf);
|
||||
E void helpserv_init(void);
|
||||
|
||||
/**** hostserv.c ****/
|
||||
E void hostserv_init(void);
|
||||
|
||||
/**** operserv.c ****/
|
||||
|
||||
E SList servadmins;
|
||||
E SList servopers;
|
||||
|
||||
E void operserv(User *u, char *buf);
|
||||
E void os_init(void);
|
||||
E void load_os_dbase(void);
|
||||
E void save_os_dbase(void);
|
||||
E void save_os_rdb_dbase(void);
|
||||
|
||||
E void os_remove_nick(NickCore *nc);
|
||||
E int is_services_root(User *u);
|
||||
E int is_services_admin(User *u);
|
||||
E int is_services_oper(User *u);
|
||||
E int nick_is_services_admin(NickCore *nc);
|
||||
E int nick_is_services_oper(NickCore *nc);
|
||||
|
||||
E int add_akill(User *u, char *mask, const char *by, const time_t expires, const char *reason);
|
||||
E int check_akill(const char *nick, const char *username, const char *host, const char *vhost, const char *ip);
|
||||
E void expire_akills(void);
|
||||
E void oper_global(char *nick, char *fmt, ...);
|
||||
#ifdef IRC_BAHAMUT
|
||||
E int add_sgline(User *u, char *mask, const char *by, const time_t expires, const char *reason);
|
||||
E int check_sgline(const char *nick, const char *realname);
|
||||
E void expire_sglines(void);
|
||||
#endif
|
||||
|
||||
E int add_sqline(User *u, char *mask, const char *by, const time_t expires, const char *reason);
|
||||
E int check_sqline(const char *nick, int nick_change);
|
||||
#ifdef IRC_BAHAMUT
|
||||
E int check_chan_sqline(const char *chan);
|
||||
#endif
|
||||
E void expire_sqlines(void);
|
||||
|
||||
#ifdef IRC_BAHAMUT
|
||||
E int add_szline(User *u, char *mask, const char *by, const time_t expires, const char *reason);
|
||||
E void expire_szlines(void);
|
||||
#endif
|
||||
|
||||
E void check_clones(User *user);
|
||||
|
||||
E void delete_ignore(const char *nick);
|
||||
|
||||
/**** process.c ****/
|
||||
|
||||
E int allow_ignore;
|
||||
E IgnoreData *ignore[];
|
||||
|
||||
E void add_ignore(const char *nick, time_t delta);
|
||||
E IgnoreData *get_ignore(const char *nick);
|
||||
|
||||
E int split_buf(char *buf, char ***argv, int colon_special);
|
||||
E void process(void);
|
||||
|
||||
/**** protocol.c ****/
|
||||
|
||||
E void s_akill(char *user, char *host, char *who, time_t when, time_t expires, char *reason);
|
||||
E void s_rakill(char *user, char *host);
|
||||
E void s_sgline(char *mask, char *reason);
|
||||
E void s_sqline(char *mask, char *reason);
|
||||
E void s_svsnoop(char *server, int set);
|
||||
E void s_szline(char *mask, char *reason);
|
||||
E void s_unsgline(char *mask);
|
||||
E void s_unsqline(char *mask);
|
||||
E void s_unszline(char *mask);
|
||||
|
||||
/**** proxy.c ****/
|
||||
|
||||
E HostCache *hcache[1024];
|
||||
|
||||
E void get_proxy_stats(long *nrec, long *memuse);
|
||||
E void ntoa(struct in_addr addr, char *ipaddr, int len);
|
||||
E int proxy_check(char *nick, char *host, uint32 ip);
|
||||
E void proxy_expire();
|
||||
E int proxy_init(void);
|
||||
|
||||
E int do_cache(User *u);
|
||||
|
||||
/**** send.c ****/
|
||||
|
||||
E void send_cmd(const char *source, const char *fmt, ...)
|
||||
FORMAT(printf,2,3);
|
||||
E void vsend_cmd(const char *source, const char *fmt, va_list args)
|
||||
FORMAT(printf,2,0);
|
||||
|
||||
E void wallops(const char *source, const char *fmt, ...)
|
||||
FORMAT(printf,2,3);
|
||||
|
||||
E void notice(const char *source, const char *dest, const char *fmt, ...)
|
||||
FORMAT(printf,3,4);
|
||||
E void notice_user(const char *source, User *u, const char *fmt, ...)
|
||||
FORMAT(printf,3,4);
|
||||
|
||||
E void notice_list(const char *source, const char *dest, const char **text);
|
||||
E void notice_lang(const char *source, User *dest, int message, ...);
|
||||
E void notice_help(const char *source, User *dest, int message, ...);
|
||||
|
||||
E void privmsg(const char *source, const char *dest, const char *fmt, ...)
|
||||
FORMAT(printf,3,4);
|
||||
|
||||
/**** sessions.c ****/
|
||||
|
||||
E void get_session_stats(long *nrec, long *memuse);
|
||||
E void get_exception_stats(long *nrec, long *memuse);
|
||||
|
||||
E int do_session(User *u);
|
||||
E int add_session(const char *nick, const char *host);
|
||||
E void del_session(const char *host);
|
||||
|
||||
E void load_exceptions(void);
|
||||
E void save_exceptions(void);
|
||||
E void save_rdb_exceptions(void);
|
||||
E int do_exception(User *u);
|
||||
E void expire_exceptions(void);
|
||||
|
||||
/**** sockutil.c ****/
|
||||
|
||||
E int32 total_read, total_written;
|
||||
E int32 read_buffer_len(void);
|
||||
E int32 write_buffer_len(void);
|
||||
|
||||
E int sgetc(int s);
|
||||
E char *sgets(char *buf, int len, int s);
|
||||
E char *sgets2(char *buf, int len, int s);
|
||||
E int sread(int s, char *buf, int len);
|
||||
E int sputs(char *str, int s);
|
||||
E int sockprintf(int s, char *fmt,...);
|
||||
E int conn(const char *host, int port, const char *lhost, int lport);
|
||||
E void disconn(int s);
|
||||
|
||||
/**** users.c ****/
|
||||
|
||||
E User *userlist[1024];
|
||||
|
||||
E int32 usercnt, opcnt, maxusercnt;
|
||||
E time_t maxusertime;
|
||||
|
||||
E void set_umode(User *user, int ac, char **av);
|
||||
|
||||
E void get_user_stats(long *nusers, long *memuse);
|
||||
E User *finduser(const char *nick);
|
||||
E User *firstuser(void);
|
||||
E User *nextuser(void);
|
||||
|
||||
#if defined(IRC_ULTIMATE) || defined(IRC_UNREAL) || defined(IRC_ULTIMATE3) || defined(IRC_VIAGRA) || defined(IRC_PTLINK)
|
||||
E void change_user_host(User *user, const char *host);
|
||||
E void change_user_username(User *user, const char *username);
|
||||
E void change_user_realname(User *user, const char *realname);
|
||||
#endif
|
||||
|
||||
E User *do_nick(const char *source, char *nick, char *username, char *host, char *server, char *realname, time_t ts, uint32 svid, ...);
|
||||
E void do_umode(const char *source, int ac, char **av);
|
||||
E void do_quit(const char *source, int ac, char **av);
|
||||
E void do_kill(const char *source, int ac, char **av);
|
||||
|
||||
E int is_oper(User *user);
|
||||
E int is_protected(User *user);
|
||||
|
||||
#if defined(IRC_ULTIMATE) || defined(IRC_UNREAL) || defined(IRC_ULTIMATE3) || defined(IRC_VIAGRA) || defined(IRC_HYBRID)
|
||||
E int is_excepted(ChannelInfo *ci, User *user);
|
||||
E int is_excepted_mask(ChannelInfo *ci, char *mask);
|
||||
#endif
|
||||
|
||||
E int match_usermask(const char *mask, User *user);
|
||||
E void split_usermask(const char *mask, char **nick, char **user, char **host);
|
||||
E char *create_mask(User *u);
|
||||
|
||||
#ifdef USE_MYSQL
|
||||
/**** mysql.c ****/
|
||||
E MYSQL *mysql;
|
||||
E MYSQL_RES *mysql_res;
|
||||
E MYSQL_FIELD *mysql_fields;
|
||||
E MYSQL_ROW mysql_row;
|
||||
|
||||
E int db_mysql_init();
|
||||
E int db_mysql_open();
|
||||
E int db_mysql_close();
|
||||
E int db_mysql_query(char *sql);
|
||||
E char *db_mysql_quote(char *sql);
|
||||
E void db_mysql_save_ns_core(NickCore * nc);
|
||||
E void db_mysql_save_ns_alias(NickAlias * na);
|
||||
E void db_mysql_save_ns_req(NickRequest * nr);
|
||||
E void db_mysql_save_cs_info(ChannelInfo * ci);
|
||||
E void db_mysql_save_os_db(unsigned int maxucnt, unsigned int maxutime, SList *ak, SList *sgl, SList *sql, SList *szl, HostCache *hc);
|
||||
E void db_mysql_save_news(NewsItem * ni);
|
||||
E void db_mysql_save_exceptions(Exception * e);
|
||||
E void db_mysql_save_hs_core(HostCore * hc);
|
||||
E void db_mysql_save_bs_core(BotInfo * bi);
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* EXTERN_H */
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
/* HelpServ functions
|
||||
*
|
||||
* (C) 2003 Anope Team / GeniusDex
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: helpserv.c,v 1.2 2004/01/18 04:33:25 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
/*************************************************************************/
|
||||
#include "services.h"
|
||||
#include "pseudo.h"
|
||||
|
||||
#define HELP_VERSION 1
|
||||
|
||||
void helpserv_init(void);
|
||||
static int do_help(User * u);
|
||||
void moduleAddHelpServCmds(void);
|
||||
|
||||
/*************************************************************************/
|
||||
void moduleAddHelpServCmds(void)
|
||||
{
|
||||
Command *c;
|
||||
c = createCommand("HELP", do_help, NULL, -1, -1, -1, -1, -1);
|
||||
addCoreCommand(HELPSERV, c);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*************************************************************************/
|
||||
/* HelpServ initialization. */
|
||||
void helpserv_init(void)
|
||||
{
|
||||
moduleAddHelpServCmds();
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* Main HelpServ routine. */
|
||||
void helpserv(User * u, char *buf)
|
||||
{
|
||||
char *cmd, *s;
|
||||
|
||||
cmd = strtok(buf, " ");
|
||||
|
||||
if (!cmd) {
|
||||
return;
|
||||
} else if (stricmp(cmd, "\1PING") == 0) {
|
||||
if (!(s = strtok(NULL, "")))
|
||||
s = "\1";
|
||||
notice(s_HelpServ, u->nick, "\1PING %s", s);
|
||||
} else {
|
||||
mod_run_cmd(s_HelpServ, u, HELPSERV, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* Display the HelpServ help. */
|
||||
/* This core function has been embed in the source for a long time, but */
|
||||
/* it moved into it's own file so we now all can enjoy the joy of */
|
||||
/* modules for HelpServ. */
|
||||
|
||||
static int do_help(User * u)
|
||||
{
|
||||
char *cmd = strtok(NULL, "");
|
||||
|
||||
if (!cmd) {
|
||||
notice_help(s_HelpServ, u, HELP_HELP, s_NickServ, s_ChanServ,
|
||||
s_MemoServ);
|
||||
if (s_BotServ)
|
||||
notice_help(s_HelpServ, u, HELP_HELP_BOT, s_BotServ);
|
||||
if (s_HostServ)
|
||||
notice_help(s_HelpServ, u, HELP_HELP_HOST, s_HostServ);
|
||||
moduleDisplayHelp(7, u);
|
||||
} else {
|
||||
mod_help_cmd(s_HelpServ, u, HELPSERV, cmd);
|
||||
}
|
||||
return MOD_CONT;
|
||||
}
|
||||
+1108
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,807 @@
|
||||
/* Initalization and related routines.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: init.c,v 1.40 2004/03/13 13:55:59 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "services.h"
|
||||
#include "pseudo.h"
|
||||
int servernum = 0;
|
||||
|
||||
extern void moduleAddMsgs(void);
|
||||
/*************************************************************************/
|
||||
|
||||
/* Send a NICK command for the given pseudo-client. If `user' is NULL,
|
||||
* send NICK commands for all the pseudo-clients.
|
||||
*
|
||||
* Now also sends MODE and SQLINE */
|
||||
#if defined(IRC_HYBRID)
|
||||
# define NICK(nick,name,modes) \
|
||||
do { \
|
||||
kill_user(NULL, (nick), "Nick used by Services"); \
|
||||
send_cmd(NULL, "NICK %s 1 %ld %s %s %s %s :%s", (nick), time(NULL), (modes), \
|
||||
ServiceUser, ServiceHost, ServerName, (name)); \
|
||||
} while (0)
|
||||
#elif defined(IRC_ULTIMATE3)
|
||||
# define NICK(nick,name,modes) \
|
||||
do { \
|
||||
send_cmd(NULL, "CLIENT %s 1 %ld %s + %s %s * %s 0 0 :%s", (nick), time(NULL), (modes), \
|
||||
ServiceUser, ServiceHost, ServerName, (name)); \
|
||||
send_cmd(NULL, "SQLINE %s :Reserved for services", (nick)); \
|
||||
} while (0)
|
||||
#elif defined(IRC_BAHAMUT)
|
||||
# define NICK(nick,name,modes) \
|
||||
do { \
|
||||
send_cmd(NULL, "NICK %s 1 %ld %s %s %s %s 0 0 :%s", (nick), time(NULL), (modes), \
|
||||
ServiceUser, ServiceHost, ServerName, (name)); \
|
||||
send_cmd(NULL, "SQLINE %s :Reserved for services", (nick)); \
|
||||
} while (0)
|
||||
#elif defined(IRC_UNREAL)
|
||||
# define NICK(nick,name,modes) \
|
||||
do { \
|
||||
send_cmd(NULL, "NICK %s 1 %ld %s %s %s 0 %s * :%s", (nick), time(NULL), \
|
||||
ServiceUser, ServiceHost, ServerName, (modes), (name)); \
|
||||
send_cmd(NULL, "SQLINE %s :Reserved for services", (nick)); \
|
||||
} while (0)
|
||||
#elif defined(IRC_DREAMFORGE)
|
||||
# define NICK(nick,name,modes) \
|
||||
do { \
|
||||
send_cmd(NULL, "NICK %s 1 %ld %s %s %s 0 :%s", (nick), time(NULL), \
|
||||
ServiceUser, ServiceHost, ServerName, (name)); \
|
||||
if (strcmp(modes, "+")) send_cmd((nick), "MODE %s %s", (nick), (modes)); \
|
||||
send_cmd(NULL, "SQLINE %s :Reserved for services", (nick)); \
|
||||
} while (0)
|
||||
#elif defined(IRC_PTLINK)
|
||||
# define NICK(nick,name,modes) \
|
||||
do { \
|
||||
send_cmd(NULL, "NICK %s 1 %lu %s %s %s %s %s :%s", (nick), time(NULL), \
|
||||
(modes), ServiceUser, ServiceHost, ServiceHost, ServerName, (name)); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
void introduce_user(const char *user)
|
||||
{
|
||||
/* Watch out for infinite loops... */
|
||||
#define LTSIZE 20
|
||||
static int lasttimes[LTSIZE];
|
||||
if (lasttimes[0] >= time(NULL) - 3)
|
||||
fatal("introduce_user() loop detected");
|
||||
memmove(lasttimes, lasttimes + 1, sizeof(lasttimes) - sizeof(int));
|
||||
lasttimes[LTSIZE - 1] = time(NULL);
|
||||
#undef LTSIZE
|
||||
|
||||
if (!user || stricmp(user, s_NickServ) == 0)
|
||||
#if defined(IRC_ULTIMATE) || defined(IRC_ULTIMATE3)
|
||||
NICK(s_NickServ, desc_NickServ, "+S");
|
||||
#elif defined(IRC_UNREAL) || defined(IRC_VIAGRA)
|
||||
NICK(s_NickServ, desc_NickServ, "+oS");
|
||||
#else
|
||||
NICK(s_NickServ, desc_NickServ, "+o");
|
||||
#endif
|
||||
if (!user || stricmp(user, s_ChanServ) == 0)
|
||||
#if defined(IRC_ULTIMATE) || defined(IRC_ULTIMATE3)
|
||||
NICK(s_ChanServ, desc_ChanServ, "+S");
|
||||
#elif defined(IRC_UNREAL) || defined(IRC_VIAGRA)
|
||||
NICK(s_ChanServ, desc_ChanServ, "+oS");
|
||||
#else
|
||||
NICK(s_ChanServ, desc_ChanServ, "+o");
|
||||
#endif
|
||||
|
||||
#ifdef HAS_VHOST
|
||||
if (s_HostServ && (!user || stricmp(user, s_HostServ) == 0))
|
||||
#if defined(IRC_ULTIMATE) || defined(IRC_UNREAL) || defined(IRC_VIAGRA)
|
||||
NICK(s_HostServ, desc_HostServ, "+oS");
|
||||
#else
|
||||
NICK(s_HostServ, desc_HostServ, "+o");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (!user || stricmp(user, s_MemoServ) == 0)
|
||||
#if defined(IRC_ULTIMATE) || defined(IRC_ULTIMATE3)
|
||||
NICK(s_MemoServ, desc_MemoServ, "+S");
|
||||
#elif defined(IRC_UNREAL) || defined(IRC_VIAGRA)
|
||||
NICK(s_MemoServ, desc_MemoServ, "+oS");
|
||||
#else
|
||||
NICK(s_MemoServ, desc_MemoServ, "+o");
|
||||
#endif
|
||||
if (s_BotServ && (!user || stricmp(user, s_BotServ) == 0))
|
||||
#if defined(IRC_ULTIMATE) || defined(IRC_ULTIMATE3)
|
||||
NICK(s_BotServ, desc_BotServ, "+S");
|
||||
#elif defined(IRC_UNREAL) || defined(IRC_VIAGRA)
|
||||
NICK(s_BotServ, desc_BotServ, "+oS");
|
||||
#else
|
||||
NICK(s_BotServ, desc_BotServ, "+o");
|
||||
#endif
|
||||
if (!user || stricmp(user, s_HelpServ) == 0)
|
||||
#if defined(IRC_ULTIMATE) || defined(IRC_ULTIMATE3)
|
||||
NICK(s_HelpServ, desc_HelpServ, "+Sh");
|
||||
#elif defined(IRC_UNREAL) || defined(IRC_VIAGRA)
|
||||
NICK(s_HelpServ, desc_HelpServ, "+oS");
|
||||
#else
|
||||
NICK(s_HelpServ, desc_HelpServ, "+h");
|
||||
#endif
|
||||
if (!user || stricmp(user, s_OperServ) == 0)
|
||||
#if defined(IRC_ULTIMATE) || defined(IRC_ULTIMATE3)
|
||||
NICK(s_OperServ, desc_OperServ, "+iS");
|
||||
#elif defined(IRC_UNREAL) || defined(IRC_VIAGRA)
|
||||
NICK(s_OperServ, desc_OperServ, "+ioS");
|
||||
#else
|
||||
NICK(s_OperServ, desc_OperServ, "+io");
|
||||
#endif
|
||||
if (s_DevNull && (!user || stricmp(user, s_DevNull) == 0))
|
||||
#if defined(IRC_ULTIMATE) || defined(IRC_UNREAL) || defined(IRC_ULTIMATE3)
|
||||
NICK(s_DevNull, desc_DevNull, "+iS");
|
||||
#else
|
||||
NICK(s_DevNull, desc_DevNull, "+i");
|
||||
#endif
|
||||
if (!user || stricmp(user, s_GlobalNoticer) == 0)
|
||||
#if defined(IRC_ULTIMATE) || defined(IRC_ULTIMATE3)
|
||||
NICK(s_GlobalNoticer, desc_GlobalNoticer, "+iS");
|
||||
#elif defined(IRC_UNREAL) || defined(IRC_VIAGRA)
|
||||
NICK(s_GlobalNoticer, desc_GlobalNoticer, "+ioS");
|
||||
#else
|
||||
NICK(s_GlobalNoticer, desc_GlobalNoticer, "+io");
|
||||
#endif
|
||||
|
||||
/* We make aliases go online */
|
||||
if (s_NickServAlias && (!user || stricmp(user, s_NickServAlias) == 0))
|
||||
#if defined(IRC_ULTIMATE) || defined(IRC_UNREAL) || defined(IRC_VIAGRA)
|
||||
NICK(s_NickServAlias, desc_NickServAlias, "+oS");
|
||||
#else
|
||||
NICK(s_NickServAlias, desc_NickServAlias, "+o");
|
||||
#endif
|
||||
if (s_ChanServAlias && (!user || stricmp(user, s_ChanServAlias) == 0))
|
||||
#if defined(IRC_ULTIMATE) || defined(IRC_UNREAL) || defined(IRC_VIAGRA)
|
||||
NICK(s_ChanServAlias, desc_ChanServAlias, "+oS");
|
||||
#else
|
||||
NICK(s_ChanServAlias, desc_ChanServAlias, "+o");
|
||||
#endif
|
||||
if (s_MemoServAlias && (!user || stricmp(user, s_MemoServAlias) == 0))
|
||||
#if defined(IRC_ULTIMATE) || defined(IRC_UNREAL) || defined(IRC_VIAGRA)
|
||||
NICK(s_MemoServAlias, desc_MemoServAlias, "+oS");
|
||||
#else
|
||||
NICK(s_MemoServAlias, desc_MemoServAlias, "+o");
|
||||
#endif
|
||||
if (s_BotServAlias && (!user || stricmp(user, s_BotServAlias) == 0))
|
||||
#if defined(IRC_ULTIMATE) || defined(IRC_UNREAL) || defined(IRC_VIAGRA)
|
||||
NICK(s_BotServAlias, desc_BotServAlias, "+oS");
|
||||
#else
|
||||
NICK(s_BotServAlias, desc_BotServAlias, "+o");
|
||||
#endif
|
||||
if (s_HelpServAlias && (!user || stricmp(user, s_HelpServAlias) == 0))
|
||||
#if defined(IRC_ULTIMATE) || defined(IRC_UNREAL) || defined(IRC_VIAGRA)
|
||||
NICK(s_HelpServAlias, desc_HelpServAlias, "+oS");
|
||||
#else
|
||||
NICK(s_HelpServAlias, desc_HelpServAlias, "+h");
|
||||
#endif
|
||||
if (s_OperServAlias && (!user || stricmp(user, s_OperServAlias) == 0))
|
||||
#if defined(IRC_ULTIMATE) || defined(IRC_UNREAL) || defined(IRC_VIAGRA)
|
||||
NICK(s_OperServAlias, desc_OperServAlias, "+ioS");
|
||||
#else
|
||||
NICK(s_OperServAlias, desc_OperServAlias, "+io");
|
||||
#endif
|
||||
if (s_DevNullAlias && (!user || stricmp(user, s_DevNullAlias) == 0))
|
||||
#if defined(IRC_ULTIMATE) || defined(IRC_UNREAL) || defined(IRC_VIAGRA)
|
||||
NICK(s_DevNullAlias, desc_DevNullAlias, "+iS");
|
||||
#else
|
||||
NICK(s_DevNullAlias, desc_DevNullAlias, "+i");
|
||||
#endif
|
||||
if (s_HostServAlias && (!user || stricmp(user, s_HostServAlias) == 0))
|
||||
#if defined(IRC_ULTIMATE) || defined(IRC_UNREAL) || defined(IRC_VIAGRA)
|
||||
NICK(s_HostServAlias, desc_HostServAlias, "+ioS");
|
||||
#else
|
||||
NICK(s_HostServAlias, desc_HostServAlias, "+io");
|
||||
#endif
|
||||
if (s_GlobalNoticerAlias
|
||||
&& (!user || stricmp(user, s_GlobalNoticerAlias) == 0))
|
||||
#if defined(IRC_ULTIMATE) || defined(IRC_UNREAL)
|
||||
NICK(s_GlobalNoticerAlias, desc_GlobalNoticerAlias, "+ioS");
|
||||
#else
|
||||
NICK(s_GlobalNoticerAlias, desc_GlobalNoticerAlias, "+io");
|
||||
#endif
|
||||
|
||||
/* We make the bots go online */
|
||||
if (s_BotServ) {
|
||||
BotInfo *bi;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
for (bi = botlists[i]; bi; bi = bi->next)
|
||||
if (!user || !stricmp(user, bi->nick))
|
||||
#if defined(IRC_UNREAL) || defined(IRC_VIAGRA)
|
||||
NEWNICK(bi->nick, bi->user, bi->host, bi->real, "+qS",
|
||||
1);
|
||||
#elif defined(IRC_ULTIMATE)
|
||||
NEWNICK(bi->nick, bi->user, bi->host, bi->real, "+pS",
|
||||
1);
|
||||
#elif defined(IRC_ULTIMATE3)
|
||||
NEWNICK(bi->nick, bi->user, bi->host, bi->real, "+S",
|
||||
1);
|
||||
#else
|
||||
NEWNICK(bi->nick, bi->user, bi->host, bi->real, "+",
|
||||
1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#undef NICK
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Set GID if necessary. Return 0 if successful (or if RUNGROUP not
|
||||
* defined), else print an error message to logfile and return -1.
|
||||
*/
|
||||
|
||||
static int set_group(void)
|
||||
{
|
||||
#if defined(RUNGROUP) && defined(HAVE_SETGRENT)
|
||||
struct group *gr;
|
||||
|
||||
setgrent();
|
||||
while ((gr = getgrent()) != NULL) {
|
||||
if (strcmp(gr->gr_name, RUNGROUP) == 0)
|
||||
break;
|
||||
}
|
||||
endgrent();
|
||||
if (gr) {
|
||||
setgid(gr->gr_gid);
|
||||
return 0;
|
||||
} else {
|
||||
alog("Unknown group `%s'\n", RUNGROUP);
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Parse command-line options for the "-dir" option only. Return 0 if all
|
||||
* went well or -1 for a syntax error.
|
||||
*/
|
||||
|
||||
/* XXX this could fail if we have "-some-option-taking-an-argument -dir" */
|
||||
|
||||
static int parse_dir_options(int ac, char **av)
|
||||
{
|
||||
int i;
|
||||
char *s;
|
||||
|
||||
for (i = 1; i < ac; i++) {
|
||||
s = av[i];
|
||||
if (*s == '-') {
|
||||
s++;
|
||||
if (strcmp(s, "dir") == 0) {
|
||||
if (++i >= ac) {
|
||||
fprintf(stderr, "-dir requires a parameter\n");
|
||||
return -1;
|
||||
}
|
||||
services_dir = av[i];
|
||||
} else if (strcmp(s, "log") == 0) {
|
||||
if (++i >= ac) {
|
||||
fprintf(stderr, "-log requires a parameter\n");
|
||||
return -1;
|
||||
}
|
||||
log_filename = av[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Parse command-line options. Return 0 if all went well, -1 for an error
|
||||
* with an option, or 1 for -help.
|
||||
*/
|
||||
|
||||
static int parse_options(int ac, char **av)
|
||||
{
|
||||
int i;
|
||||
char *s, *t;
|
||||
|
||||
for (i = 1; i < ac; i++) {
|
||||
s = av[i];
|
||||
if (*s == '-') {
|
||||
s++;
|
||||
if (strcmp(s, "remote") == 0) {
|
||||
if (++i >= ac) {
|
||||
fprintf(stderr, "-remote requires hostname[:port]\n");
|
||||
return -1;
|
||||
}
|
||||
s = av[i];
|
||||
t = strchr(s, ':');
|
||||
if (t) {
|
||||
*t++ = 0;
|
||||
if (atoi(t) > 0)
|
||||
RemotePort = atoi(t);
|
||||
else {
|
||||
fprintf(stderr,
|
||||
"-remote: port number must be a positive integer. Using default.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
RemoteServer = s;
|
||||
} else if (strcmp(s, "local") == 0) {
|
||||
if (++i >= ac) {
|
||||
fprintf(stderr,
|
||||
"-local requires hostname or [hostname]:[port]\n");
|
||||
return -1;
|
||||
}
|
||||
s = av[i];
|
||||
t = strchr(s, ':');
|
||||
if (t) {
|
||||
*t++ = 0;
|
||||
if (atoi(t) >= 0)
|
||||
LocalPort = atoi(t);
|
||||
else {
|
||||
fprintf(stderr,
|
||||
"-local: port number must be a positive integer or 0. Using default.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
LocalHost = s;
|
||||
} else if (strcmp(s, "name") == 0) {
|
||||
if (++i >= ac) {
|
||||
fprintf(stderr, "-name requires a parameter\n");
|
||||
return -1;
|
||||
}
|
||||
ServerName = av[i];
|
||||
} else if (strcmp(s, "desc") == 0) {
|
||||
if (++i >= ac) {
|
||||
fprintf(stderr, "-desc requires a parameter\n");
|
||||
return -1;
|
||||
}
|
||||
ServerDesc = av[i];
|
||||
} else if (strcmp(s, "user") == 0) {
|
||||
if (++i >= ac) {
|
||||
fprintf(stderr, "-user requires a parameter\n");
|
||||
return -1;
|
||||
}
|
||||
ServiceUser = av[i];
|
||||
} else if (strcmp(s, "host") == 0) {
|
||||
if (++i >= ac) {
|
||||
fprintf(stderr, "-host requires a parameter\n");
|
||||
return -1;
|
||||
}
|
||||
ServiceHost = av[i];
|
||||
} else if (strcmp(s, "dir") == 0) {
|
||||
/* Handled by parse_dir_options() */
|
||||
i++; /* Skip parameter */
|
||||
} else if (strcmp(s, "log") == 0) {
|
||||
/* Handled by parse_dir_options(), too */
|
||||
i++; /* Skip parameter */
|
||||
} else if (strcmp(s, "update") == 0) {
|
||||
if (++i >= ac) {
|
||||
fprintf(stderr, "-update requires a parameter\n");
|
||||
return -1;
|
||||
}
|
||||
s = av[i];
|
||||
if (atoi(s) <= 0) {
|
||||
fprintf(stderr,
|
||||
"-update: number of seconds must be positive");
|
||||
return -1;
|
||||
} else
|
||||
UpdateTimeout = atol(s);
|
||||
} else if (strcmp(s, "expire") == 0) {
|
||||
if (++i >= ac) {
|
||||
fprintf(stderr, "-expire requires a parameter\n");
|
||||
return -1;
|
||||
}
|
||||
s = av[i];
|
||||
if (atoi(s) <= 0) {
|
||||
fprintf(stderr,
|
||||
"-expire: number of seconds must be positive");
|
||||
return -1;
|
||||
} else
|
||||
ExpireTimeout = atol(s);
|
||||
} else if (strcmp(s, "debug") == 0) {
|
||||
debug++;
|
||||
} else if (strcmp(s, "readonly") == 0) {
|
||||
readonly = 1;
|
||||
skeleton = 0;
|
||||
} else if (strcmp(s, "skeleton") == 0) {
|
||||
readonly = 0;
|
||||
skeleton = 1;
|
||||
} else if (strcmp(s, "nofork") == 0) {
|
||||
nofork = 1;
|
||||
} else if (strcmp(s, "logchan") == 0) {
|
||||
logchan = 1;
|
||||
#ifdef IRC_HYBRID
|
||||
fprintf(stderr,
|
||||
"LogChan will only work if your logchannel is not set to +n\n");
|
||||
#endif
|
||||
} else if (strcmp(s, "forceload") == 0) {
|
||||
forceload = 1;
|
||||
} else if (!strcmp(s, "noexpire")) {
|
||||
noexpire = 1;
|
||||
#ifdef IS44_CONVERTER
|
||||
} else if (!strcmp(s, "is44")) {
|
||||
is44 = 1;
|
||||
#endif
|
||||
} else {
|
||||
fprintf(stderr, "Unknown option -%s\n", s);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Non-option arguments not allowed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Remove our PID file. Done at exit. */
|
||||
|
||||
static void remove_pidfile(void)
|
||||
{
|
||||
remove(PIDFilename);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Create our PID file and write the PID to it. */
|
||||
|
||||
static void write_pidfile(void)
|
||||
{
|
||||
FILE *pidfile;
|
||||
|
||||
pidfile = fopen(PIDFilename, "w");
|
||||
if (pidfile) {
|
||||
fprintf(pidfile, "%d\n", (int) getpid());
|
||||
fclose(pidfile);
|
||||
atexit(remove_pidfile);
|
||||
} else {
|
||||
log_perror("Warning: cannot write to PID file %s", PIDFilename);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Overall initialization routine. Returns 0 on success, -1 on failure. */
|
||||
|
||||
int init(int ac, char **av)
|
||||
{
|
||||
int i;
|
||||
int openlog_failed = 0, openlog_errno = 0;
|
||||
int started_from_term = isatty(0) && isatty(1) && isatty(2);
|
||||
|
||||
/* Imported from main.c */
|
||||
extern void sighandler(int signum);
|
||||
|
||||
|
||||
/* Set file creation mask and group ID. */
|
||||
#if defined(DEFUMASK) && HAVE_UMASK
|
||||
umask(DEFUMASK);
|
||||
#endif
|
||||
if (set_group() < 0)
|
||||
return -1;
|
||||
|
||||
/* Parse command line for -dir option. */
|
||||
parse_dir_options(ac, av);
|
||||
|
||||
/* Chdir to Services data directory. */
|
||||
if (chdir(services_dir) < 0) {
|
||||
fprintf(stderr, "chdir(%s): %s\n", services_dir, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Open logfile, and complain if we didn't. */
|
||||
if (open_log() < 0) {
|
||||
openlog_errno = errno;
|
||||
if (started_from_term) {
|
||||
fprintf(stderr, "Warning: unable to open log file %s: %s\n",
|
||||
log_filename, strerror(errno));
|
||||
} else {
|
||||
openlog_failed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read configuration file; exit if there are problems. */
|
||||
if (!read_config(0))
|
||||
return -1;
|
||||
|
||||
/* Add Core MSG handles */
|
||||
moduleAddMsgs();
|
||||
|
||||
/* Parse all remaining command-line options. */
|
||||
parse_options(ac, av);
|
||||
|
||||
/* Detach ourselves if requested. */
|
||||
if (!nofork) {
|
||||
if ((i = fork()) < 0) {
|
||||
perror("fork()");
|
||||
return -1;
|
||||
} else if (i != 0) {
|
||||
exit(0);
|
||||
}
|
||||
if (started_from_term) {
|
||||
close(0);
|
||||
close(1);
|
||||
close(2);
|
||||
}
|
||||
if (setpgid(0, 0) < 0) {
|
||||
perror("setpgid()");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write our PID to the PID file. */
|
||||
write_pidfile();
|
||||
|
||||
/* Announce ourselves to the logfile. */
|
||||
if (debug || readonly || skeleton) {
|
||||
alog("Anope %s (compiled for %s) starting up (options:%s%s%s)",
|
||||
version_number, version_protocol,
|
||||
debug ? " debug" : "", readonly ? " readonly" : "",
|
||||
skeleton ? " skeleton" : "");
|
||||
} else {
|
||||
alog("Anope %s (compiled for %s) starting up",
|
||||
version_number, version_protocol);
|
||||
}
|
||||
start_time = time(NULL);
|
||||
|
||||
/* If in read-only mode, close the logfile again. */
|
||||
if (readonly)
|
||||
close_log();
|
||||
|
||||
/* Set signal handlers. Catch certain signals to let us do things or
|
||||
* panic as necessary, and ignore all others.
|
||||
*/
|
||||
|
||||
#if defined(NSIG) && !defined(LINUX20) && !defined(LINUX22)
|
||||
for (i = 1; i <= NSIG - 1; i++) {
|
||||
#else
|
||||
for (i = 1; i <= 31; i++) {
|
||||
#endif
|
||||
#if defined(USE_THREADS) && defined(LINUX20)
|
||||
if (i != SIGUSR1 && i != SIGUSR2)
|
||||
#endif
|
||||
signal(i, SIG_IGN);
|
||||
}
|
||||
|
||||
#ifndef USE_THREADS
|
||||
signal(SIGINT, sighandler);
|
||||
#else
|
||||
signal(SIGINT, SIG_DFL);
|
||||
#endif
|
||||
signal(SIGTERM, sighandler);
|
||||
signal(SIGQUIT, sighandler);
|
||||
if (!DumpCore) {
|
||||
signal(SIGSEGV, sighandler);
|
||||
signal(SIGBUS, sighandler);
|
||||
signal(SIGILL, sighandler);
|
||||
signal(SIGTRAP, sighandler);
|
||||
} else {
|
||||
signal(SIGSEGV, SIG_DFL);
|
||||
signal(SIGBUS, SIG_DFL);
|
||||
signal(SIGILL, SIG_DFL);
|
||||
signal(SIGTRAP, SIG_DFL);
|
||||
}
|
||||
signal(SIGQUIT, sighandler);
|
||||
signal(SIGHUP, sighandler);
|
||||
|
||||
#ifdef SIGIOT
|
||||
signal(SIGIOT, sighandler);
|
||||
#endif
|
||||
signal(SIGFPE, sighandler);
|
||||
|
||||
#if !defined(USE_THREADS) || !defined(LINUX20)
|
||||
signal(SIGUSR1, sighandler); /* This is our "out-of-memory" panic switch */
|
||||
#endif
|
||||
|
||||
/* Initialize multi-language support */
|
||||
lang_init();
|
||||
if (debug)
|
||||
alog("debug: Loaded languages");
|
||||
|
||||
/* Initialize subservices */
|
||||
ns_init();
|
||||
cs_init();
|
||||
ms_init();
|
||||
bs_init();
|
||||
os_init();
|
||||
hostserv_init();
|
||||
helpserv_init();
|
||||
|
||||
#ifdef USE_RDB
|
||||
db_mysql_init();
|
||||
#endif
|
||||
|
||||
/* Initialize proxy detection */
|
||||
#ifdef USE_THREADS
|
||||
if (ProxyDetect && !proxy_init()) {
|
||||
perror("proxy_init()");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* load any custom modules */
|
||||
modules_init();
|
||||
|
||||
#ifdef USE_CONVERTER
|
||||
/* Convert the databases NOW! */
|
||||
# ifdef IS44_CONVERTER
|
||||
if (is44) {
|
||||
convert_ircservices_44();
|
||||
alog("debug: Databases converted");
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Load up databases */
|
||||
if (!skeleton) {
|
||||
load_ns_dbase();
|
||||
if (debug)
|
||||
alog("debug: Loaded %s database (1/9)", s_NickServ);
|
||||
if (s_HostServ) {
|
||||
load_hs_dbase();
|
||||
if (debug)
|
||||
alog("debug: Loaded %s database (2/9)", s_HostServ);
|
||||
}
|
||||
if (s_BotServ) {
|
||||
load_bs_dbase();
|
||||
if (debug)
|
||||
alog("debug: Loaded %s database (3/9)", s_BotServ);
|
||||
} else if (debug)
|
||||
alog("debug: BotServ database (4/9) not loaded because BotServ is disabled");
|
||||
load_cs_dbase();
|
||||
if (debug)
|
||||
alog("debug: Loaded %s database (5/9)", s_ChanServ);
|
||||
}
|
||||
load_os_dbase();
|
||||
if (debug)
|
||||
alog("debug: Loaded %s database (6/9)", s_OperServ);
|
||||
load_news();
|
||||
if (debug)
|
||||
alog("debug: Loaded news database (7/9)");
|
||||
load_exceptions();
|
||||
if (debug)
|
||||
alog("debug: Loaded exception database (8/9)");
|
||||
if (PreNickDBName) {
|
||||
load_ns_req_db();
|
||||
if (debug)
|
||||
alog("debug: Loaded PreNick database (9/9)");
|
||||
}
|
||||
|
||||
alog("Databases loaded");
|
||||
|
||||
/* Save the databases back to file/mysql to reflect any changes */
|
||||
save_databases();
|
||||
|
||||
/* Connect to the remote server */
|
||||
servsock = conn(RemoteServer, RemotePort, LocalHost, LocalPort);
|
||||
if (servsock < 0 && RemoteServer2) {
|
||||
servsock = conn(RemoteServer2, RemotePort2, LocalHost, LocalPort);
|
||||
if (servsock < 0 && RemoteServer3) {
|
||||
servsock =
|
||||
conn(RemoteServer3, RemotePort3, LocalHost, LocalPort);
|
||||
if (servsock < 0) {
|
||||
fatal_perror("Can't connect to server");
|
||||
} else {
|
||||
servernum = 3;
|
||||
alog("Connected to Server %d (%s:%d)", servernum,
|
||||
RemoteServer3, RemotePort3);
|
||||
}
|
||||
} else {
|
||||
if (servsock < 0) {
|
||||
fatal_perror("Can't connect to server");
|
||||
}
|
||||
servernum = 2;
|
||||
alog("Connected to Server %d (%s:%d)", servernum,
|
||||
RemoteServer2, RemotePort2);
|
||||
}
|
||||
} else {
|
||||
if (servsock < 0) {
|
||||
fatal_perror("Can't connect to server");
|
||||
}
|
||||
servernum = 1;
|
||||
alog("Connected to Server %d (%s:%d)", servernum, RemoteServer,
|
||||
RemotePort);
|
||||
}
|
||||
|
||||
#ifdef IRC_UNREAL
|
||||
send_cmd(NULL, "PROTOCTL NICKv2 VHP");
|
||||
#endif
|
||||
#if defined(IRC_ULTIMATE3)
|
||||
if (servernum == 1)
|
||||
send_cmd(NULL, "PASS %s :TS", RemotePassword);
|
||||
else if (servernum == 2)
|
||||
send_cmd(NULL, "PASS %s :TS", RemotePassword2);
|
||||
else if (servernum == 3)
|
||||
send_cmd(NULL, "PASS %s :TS", RemotePassword3);
|
||||
send_cmd(NULL, "CAPAB NICKIP SSJ5 TS5 CLIENT");
|
||||
|
||||
#elif defined(IRC_BAHAMUT)
|
||||
if (servernum == 1)
|
||||
send_cmd(NULL, "PASS %s :TS", RemotePassword);
|
||||
else if (servernum == 2)
|
||||
send_cmd(NULL, "PASS %s :TS", RemotePassword2);
|
||||
else if (servernum == 3)
|
||||
send_cmd(NULL, "PASS %s :TS", RemotePassword3);
|
||||
send_cmd(NULL, "CAPAB NICKIP SSJOIN TS3");
|
||||
#elif defined(IRC_HYBRID)
|
||||
if (servernum == 1)
|
||||
send_cmd(NULL, "PASS %s :TS", RemotePassword);
|
||||
else if (servernum == 2)
|
||||
send_cmd(NULL, "PASS %s :TS", RemotePassword2);
|
||||
else if (servernum == 3)
|
||||
send_cmd(NULL, "PASS %s :TS", RemotePassword3);
|
||||
send_cmd(NULL, "CAPAB TS5 EX IE HOPS HUB AOPS");
|
||||
#elif defined(IRC_PTLINK)
|
||||
if (servernum == 1)
|
||||
send_cmd(NULL, "PASS %s :TS", RemotePassword);
|
||||
else if (servernum == 2)
|
||||
send_cmd(NULL, "PASS %s :TS", RemotePassword2);
|
||||
else if (servernum == 3)
|
||||
send_cmd(NULL, "PASS %s :TS", RemotePassword3);
|
||||
#else
|
||||
if (servernum == 1)
|
||||
send_cmd(NULL, "PASS :%s", RemotePassword);
|
||||
if (servernum == 2)
|
||||
send_cmd(NULL, "PASS :%s", RemotePassword2);
|
||||
if (servernum == 3)
|
||||
send_cmd(NULL, "PASS :%s", RemotePassword3);
|
||||
#endif
|
||||
#ifdef IRC_PTLINK
|
||||
send_cmd(NULL, "SERVER %s 1 Anope.Services%s :%s",
|
||||
ServerName, version_number, ServerDesc);
|
||||
#else
|
||||
send_cmd(NULL, "SERVER %s 1 :%s", ServerName, ServerDesc);
|
||||
#endif
|
||||
#ifdef IRC_BAHAMUT
|
||||
send_cmd(NULL, "SVINFO 3 1 0 :%ld", time(NULL));
|
||||
#endif
|
||||
#ifdef IRC_HYBRID
|
||||
send_cmd(NULL, "SVSINFO 5 5 0 :%ld", time(NULL));
|
||||
#endif
|
||||
#ifdef IRC_PTLINK
|
||||
send_cmd(NULL, "SVINFO 3 6 %lu", time(NULL));
|
||||
send_cmd(NULL, "SVSINFO %lu %d", time(NULL), maxusercnt);
|
||||
#endif
|
||||
sgets2(inbuf, sizeof(inbuf), servsock);
|
||||
if (strnicmp(inbuf, "ERROR", 5) == 0) {
|
||||
/* Close server socket first to stop wallops, since the other
|
||||
* server doesn't want to listen to us anyway */
|
||||
disconn(servsock);
|
||||
servsock = -1;
|
||||
fatal("Remote server returned: %s", inbuf);
|
||||
}
|
||||
|
||||
/* Announce a logfile error if there was one */
|
||||
if (openlog_failed) {
|
||||
wallops(NULL, "Warning: couldn't open logfile: %s",
|
||||
strerror(openlog_errno));
|
||||
}
|
||||
|
||||
/* Bring in our pseudo-clients */
|
||||
introduce_user(NULL);
|
||||
|
||||
/**
|
||||
* Load our delayed modeles - modules that are planing on making clients need to wait till now
|
||||
* where as modules wanting to modify our ircd connection messages need to load eariler :|
|
||||
**/
|
||||
modules_delayed_init();
|
||||
|
||||
/* Write the StartGlobal */
|
||||
if (GlobalOnCycle) {
|
||||
if (GlobalOnCycleUP)
|
||||
oper_global(NULL, GlobalOnCycleUP);
|
||||
}
|
||||
|
||||
/* Success! */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
@@ -0,0 +1,29 @@
|
||||
#!/bin/sh
|
||||
|
||||
SRC= ; DEST= ; MODE= ; USER= ; GROUP= ; export SRC DEST MODE USER GROUP
|
||||
while [ $# -gt 0 ] ; do
|
||||
case $1 in
|
||||
-m) MODE=$2; shift; shift;;
|
||||
-u) USER=$2; shift; shift;;
|
||||
-g) GROUP=$2; shift; shift;;
|
||||
-c) shift;;
|
||||
*) SRC="$DEST"; DEST="$1"; shift;;
|
||||
esac
|
||||
done
|
||||
if [ ! "$DEST" ] ; then
|
||||
echo >&2 "Usage: $0 [-c] [-m mode] [-u user] [-g group] source dest"
|
||||
exit 1
|
||||
fi
|
||||
if [ -d "$DEST" ] ; then
|
||||
DEST="$DEST/$SRC"
|
||||
fi
|
||||
/bin/cp -p "$SRC" "$DEST"
|
||||
if [ "$MODE" ] ; then
|
||||
/bin/chmod $MODE "$DEST"
|
||||
fi
|
||||
if [ "$USER" ] ; then
|
||||
/bin/chown "$USER" "$DEST"
|
||||
fi
|
||||
if [ "$GROUP" ] ; then
|
||||
/bin/chgrp "$GROUP" "$DEST"
|
||||
fi
|
||||
@@ -0,0 +1,79 @@
|
||||
# Makefile for language module
|
||||
|
||||
include ../Makefile.inc
|
||||
|
||||
|
||||
LANGOBJS = cat de en_us es fr gr nl pt tr it ru
|
||||
LANGSRCS = cat de en_us.l es fr.l gr.l nl.l pt.l tr.l it.l ru.l
|
||||
|
||||
LANGCOMP = ./langcomp
|
||||
#LANGCOMP = ./langcomp -w
|
||||
|
||||
|
||||
all: $(LANGOBJS)
|
||||
|
||||
|
||||
install: all
|
||||
mkdir -p $(DATDEST)/languages
|
||||
ifdef RUNGROUP
|
||||
chgrp $(RUNGROUP) $(DATDEST)/languages
|
||||
chmod 770 $(DATDEST)/languages
|
||||
else
|
||||
chmod 700 $(DATDEST)/languages
|
||||
endif
|
||||
cp $(LANGOBJS) $(DATDEST)/languages
|
||||
ifdef RUNGROUP
|
||||
chgrp $(RUNGROUP) $(DATDEST)/languages/*
|
||||
chmod 660 $(DATDEST)/languages/*
|
||||
else
|
||||
chmod 600 $(DATDEST)/languages/*
|
||||
endif
|
||||
|
||||
|
||||
clean:
|
||||
rm -f $(LANGOBJS) langcomp
|
||||
|
||||
spotless: clean
|
||||
rm -f language.h
|
||||
|
||||
|
||||
cat: cat.l langcomp index
|
||||
./langcomp $@.l
|
||||
de: de.l langcomp index
|
||||
./langcomp $@.l
|
||||
en_us: en_us.l langcomp index
|
||||
./langcomp $@.l
|
||||
es: es.l langcomp index
|
||||
./langcomp $@.l
|
||||
fr: fr.l langcomp index
|
||||
./langcomp $@.l
|
||||
gr: gr.l langcomp index
|
||||
./langcomp $@.l
|
||||
nl: nl.l langcomp index
|
||||
./langcomp $@.l
|
||||
pt: pt.l langcomp index
|
||||
./langcomp $@.l
|
||||
tr: tr.l langcomp index
|
||||
./langcomp $@.l
|
||||
it: it.l langcomp index
|
||||
./langcomp $@.l
|
||||
ru: ru.l langcomp index
|
||||
./langcomp $@.l
|
||||
|
||||
langcomp: langcomp.c
|
||||
$(CC) $(CFLAGS) langcomp.c -o $@
|
||||
|
||||
|
||||
language.h: index Makefile
|
||||
@perl -e <index >$@ '\
|
||||
print STDERR "Generating language.h... "; \
|
||||
$$i=0; \
|
||||
while (<>) { \
|
||||
chop; \
|
||||
printf "#define %-32s %d\n", $$_, $$i++; \
|
||||
} \
|
||||
print "\n#define NUM_STRINGS $$i\n"; \
|
||||
print STDERR "$$i strings\n";'
|
||||
|
||||
index: en_us.l
|
||||
grep '^[A-Z]' en_us.l >index
|
||||
+6172
File diff suppressed because it is too large
Load Diff
+5946
File diff suppressed because it is too large
Load Diff
Executable
+118
@@ -0,0 +1,118 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# Tries to fix a language file using the reference
|
||||
# language (en_us), and injecting all new strings
|
||||
# (in english) into the newly generated fixed.pl
|
||||
#
|
||||
# check the result with obs.pl then copy on top
|
||||
# of the source language file.
|
||||
#
|
||||
my $srcfile = $ARGV[0];
|
||||
my $dstfile = "fixed.l";
|
||||
my $engfile = "en_us.l";
|
||||
my %is_there= ();
|
||||
my $pos=0;
|
||||
my $wc=0;
|
||||
|
||||
my @defs;
|
||||
my @efile;
|
||||
|
||||
sub error {
|
||||
|
||||
my $msg = shift ;
|
||||
print "*** Error: $msg \n";
|
||||
exit ;
|
||||
}
|
||||
|
||||
sub not_del {
|
||||
$line = shift;
|
||||
if ($is_there{$line}) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Could not think of a worse of doing this...
|
||||
sub new_def {
|
||||
my $ndef;
|
||||
my $start=0;
|
||||
|
||||
$def = shift;
|
||||
for (@efile) {
|
||||
my $line = $_;
|
||||
chomp $line;
|
||||
|
||||
if (/^[A-Z]/) {
|
||||
$start=0;
|
||||
}
|
||||
|
||||
if ($start) {
|
||||
$ndef.=$_;
|
||||
}
|
||||
|
||||
if ($line eq $def) {
|
||||
$ndef=$_;
|
||||
$start=1;
|
||||
}
|
||||
|
||||
}
|
||||
return $ndef;
|
||||
}
|
||||
|
||||
error("Usage $0 [lang.l]") unless ($srcfile);
|
||||
error("Can't find language file: $srcfile") if (! -f $srcfile);
|
||||
error("Can't find language file: $engfile") if (! -f $engfile);
|
||||
|
||||
open (EFILE, "< $engfile");
|
||||
while (<EFILE>) {
|
||||
my $line = $_;
|
||||
push(@efile, $line);
|
||||
chomp $line;
|
||||
if (/^[A-Z]/) {
|
||||
$wc = push (@defs, $line);
|
||||
}
|
||||
}
|
||||
close(EFILE);
|
||||
|
||||
# Need to load entiry text into hash...
|
||||
for (@defs) {
|
||||
$is_there{$_} = 1;
|
||||
}
|
||||
|
||||
open (SFILE, "< $srcfile");
|
||||
open (DFILE, "> $dstfile");
|
||||
while (<SFILE>) {
|
||||
my $line = $_;
|
||||
chomp $line;
|
||||
if (/^[A-Z]/) {
|
||||
|
||||
$del = 0;
|
||||
if (not_del($line)) {
|
||||
while ($line ne $defs[$pos]) {
|
||||
print "ADD: $defs[$pos]\n";
|
||||
# Need to reference the hash...
|
||||
my $ndef = new_def($defs[$pos]);
|
||||
print DFILE $ndef;
|
||||
$pos++;
|
||||
}
|
||||
$pos++;
|
||||
} else {
|
||||
$del = 1;
|
||||
print "DEL: $line\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (! $del) {
|
||||
print DFILE "$line\n";
|
||||
}
|
||||
}
|
||||
|
||||
for($pos ; $pos < $wc; $pos++) {
|
||||
print "ADD: $defs[$pos]\n";
|
||||
my $ndef = new_def($defs[$pos]);
|
||||
print DFILE $ndef;
|
||||
}
|
||||
close(SFILE);
|
||||
close(DFILE);
|
||||
+1410
File diff suppressed because it is too large
Load Diff
+256
@@ -0,0 +1,256 @@
|
||||
/* Compiler for language definition files.
|
||||
*
|
||||
* Epona (c) 2000-2002 PegSoft
|
||||
* Contact us at epona@pegsoft.net
|
||||
*
|
||||
* This program is free but copyrighted software; see the file COPYING for
|
||||
* details.
|
||||
*
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* A language definition file contains all strings which Services sends to
|
||||
* users in a particular language. A language file may contain comments
|
||||
* (lines beginning with "#") and blank lines. All other lines must adhere
|
||||
* to the following format:
|
||||
*
|
||||
* Each string definition begins with the C name of a message (as defined
|
||||
* in the file "index"--see below). This must be alone on a line, preceded
|
||||
* and followed by no blank space. Following this line are zero or more
|
||||
* lines of text; each line of text must begin with exactly one tab
|
||||
* character, which is discarded. Newlines are retained in the strings,
|
||||
* except the last newline in the text, which is discarded. A message with
|
||||
* no text is replaced by a null pointer in the array (not an empty
|
||||
* string).
|
||||
*
|
||||
* All messages in the program are listed, one per line, in the "index"
|
||||
* file. No comments or blank lines are permitted in that file. The index
|
||||
* file can be generated from a language file with a command like:
|
||||
* grep '^[A-Z]' en_us.l >index
|
||||
*
|
||||
* This program takes one parameter, the name of the language file. It
|
||||
* generates a compiled language file whose name is created by removing any
|
||||
* extension on the source file on the input filename.
|
||||
*
|
||||
* You may also pass a "-w" option to print warnings for missing strings.
|
||||
*
|
||||
* This program isn't very flexible, because it doesn't need to be, but
|
||||
* anyone who wants to try making it more flexible is welcome to.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#undef getline
|
||||
int numstrings = 0; /* Number of strings we should have */
|
||||
char **stringnames; /* Names of the strings (from index file) */
|
||||
char **strings; /* Strings we have loaded */
|
||||
|
||||
int linenum = 0; /* Current line number in input file */
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Read the index file and load numstrings and stringnames. Return -1 on
|
||||
* error, 0 on success. */
|
||||
|
||||
int read_index_file()
|
||||
{
|
||||
FILE *f;
|
||||
char buf[256];
|
||||
int i;
|
||||
|
||||
if (!(f = fopen("index", "r"))) {
|
||||
perror("fopen(index)");
|
||||
return -1;
|
||||
}
|
||||
while (fgets(buf, sizeof(buf), f))
|
||||
numstrings++;
|
||||
if (!(stringnames = calloc(sizeof(char *), numstrings))) {
|
||||
perror("calloc(stringnames)");
|
||||
return -1;
|
||||
}
|
||||
if (!(strings = calloc(sizeof(char *), numstrings))) {
|
||||
perror("calloc(strings)");
|
||||
return -1;
|
||||
}
|
||||
fseek(f, 0, SEEK_SET);
|
||||
i = 0;
|
||||
while (fgets(buf, sizeof(buf), f)) {
|
||||
if (buf[strlen(buf)-1] == '\n')
|
||||
buf[strlen(buf)-1] = '\0';
|
||||
if (!(stringnames[i++] = strdup(buf))) {
|
||||
perror("strdup()");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Return the index of a string name in stringnames, or -1 if not found. */
|
||||
|
||||
int stringnum(const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < numstrings; i++) {
|
||||
if (strcmp(stringnames[i], name) == 0)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Read a non-comment, non-blank line from the input file. Return NULL at
|
||||
* end of file. */
|
||||
|
||||
char *getline(FILE *f)
|
||||
{
|
||||
static char buf[1024];
|
||||
char *s;
|
||||
|
||||
do {
|
||||
if (!(fgets(buf, sizeof(buf), f)))
|
||||
return NULL;
|
||||
linenum++;
|
||||
} while (*buf == '#' || *buf == '\n');
|
||||
s = buf + strlen(buf)-1;
|
||||
if (*s == '\n')
|
||||
*s = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Write a 32-bit value to a file in big-endian order. */
|
||||
|
||||
int fput32(int val, FILE *f)
|
||||
{
|
||||
if (fputc(val>>24, f) < 0 ||
|
||||
fputc(val>>16, f) < 0 ||
|
||||
fputc(val>> 8, f) < 0 ||
|
||||
fputc(val , f) < 0
|
||||
) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
unsigned char *filename = NULL, *s;
|
||||
char langname[254], outfile[256];
|
||||
FILE *in, *out;
|
||||
int warn = 0;
|
||||
int retval = 0;
|
||||
int curstring = -2, i;
|
||||
char *line;
|
||||
int pos;
|
||||
int maxerr = 50; /* Max errors before we bail out */
|
||||
|
||||
if (ac >= 2 && strcmp(av[1], "-w") == 0) {
|
||||
warn = 1;
|
||||
av[1] = av[2];
|
||||
ac--;
|
||||
}
|
||||
if (ac != 2) {
|
||||
fprintf(stderr, "Usage: %s [-w] <lang-file>\n", av[0]);
|
||||
return 1;
|
||||
}
|
||||
filename = av[1];
|
||||
s = strrchr(filename, '.');
|
||||
if (!s)
|
||||
s = filename + strlen(filename);
|
||||
if (s-filename > sizeof(langname)-3)
|
||||
s = filename + sizeof(langname)-1;
|
||||
strncpy(langname, filename, s-filename);
|
||||
langname[s-filename] = '\0';
|
||||
snprintf(outfile, sizeof(outfile), "%s", langname);
|
||||
|
||||
if (read_index_file() < 0)
|
||||
return 1;
|
||||
if (!(in = fopen(filename, "r"))) {
|
||||
perror(filename);
|
||||
return 1;
|
||||
}
|
||||
if (!(out = fopen(outfile, "w"))) {
|
||||
perror(outfile);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (maxerr > 0 && (line = getline(in)) != NULL) {
|
||||
if (*line == '\t') {
|
||||
if (curstring == -2) {
|
||||
fprintf(stderr, "%s:%d: Junk at beginning of file\n",
|
||||
filename, linenum);
|
||||
retval = 1;
|
||||
} else if (curstring >= 0) {
|
||||
line++;
|
||||
i = strings[curstring] ? strlen(strings[curstring]) : 0;
|
||||
if (!(strings[curstring] =
|
||||
realloc(strings[curstring], i+strlen(line)+2))) {
|
||||
fprintf(stderr, "%s:%d: Out of memory!\n",filename,linenum);
|
||||
return 2;
|
||||
}
|
||||
sprintf(strings[curstring]+i, "%s\n", line);
|
||||
}
|
||||
} else {
|
||||
|
||||
if ((curstring = stringnum(line)) < 0) {
|
||||
fprintf(stderr, "%s:%d: Unknown string name `%s'\n",
|
||||
filename, linenum, line);
|
||||
retval = 1;
|
||||
maxerr--;
|
||||
} else if (strings[curstring]) {
|
||||
fprintf(stderr, "%s:%d: Duplicate occurrence of string `%s'\n",
|
||||
filename, linenum, line);
|
||||
retval = 1;
|
||||
maxerr--;
|
||||
} else {
|
||||
if (!(strings[curstring] = malloc(1))) {
|
||||
fprintf(stderr, "%s:%d: Out of memory!\n",filename,linenum);
|
||||
return 2;
|
||||
}
|
||||
*strings[curstring] = '\0';
|
||||
}
|
||||
|
||||
if (maxerr == 0)
|
||||
fprintf(stderr, "%s:%d: Too many errors!\n", filename, linenum);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fput32(numstrings, out);
|
||||
pos = numstrings * 8 + 4;
|
||||
for (i = 0; i < numstrings; i++) {
|
||||
int len = strings[i] && *strings[i] ? strlen(strings[i])-1 : 0;
|
||||
fput32(pos, out);
|
||||
fput32(len, out);
|
||||
pos += len;
|
||||
}
|
||||
for (i = 0; i < numstrings; i++) {
|
||||
if (strings[i]) {
|
||||
if (*strings[i])
|
||||
strings[i][strlen(strings[i])-1] = '\0'; /* kill last \n */
|
||||
if (*strings[i])
|
||||
fputs(strings[i], out);
|
||||
} else if (warn) {
|
||||
fprintf(stderr, "%s: String `%s' missing\n", filename,
|
||||
stringnames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
Executable
+129
@@ -0,0 +1,129 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# Checks a language file against the reference language (en_us), and
|
||||
# finds #define string diferences
|
||||
#
|
||||
my $srcfile = $ARGV[0];
|
||||
my $engfile = "en_us.l";
|
||||
my %is_there= ();
|
||||
my $pos=0;
|
||||
my $wc=0;
|
||||
my $edef="";
|
||||
my $sdef="";
|
||||
|
||||
my @efile;
|
||||
my @sfile;
|
||||
my @defs;
|
||||
|
||||
sub error {
|
||||
|
||||
my $msg = shift ;
|
||||
print "*** Error: $msg \n";
|
||||
exit ;
|
||||
}
|
||||
|
||||
sub not_del {
|
||||
$line = shift;
|
||||
if ($is_there{$line}) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sub get_format {
|
||||
my $fmt="";
|
||||
|
||||
my $str=shift;
|
||||
|
||||
while ($str =~ m/%\w/g) {
|
||||
$fmt .= $&;
|
||||
}
|
||||
|
||||
return $fmt;
|
||||
}
|
||||
|
||||
# Could not think of a worse of doing this...
|
||||
sub get_def {
|
||||
my $ndef;
|
||||
my $start=0;
|
||||
my $found=0;
|
||||
|
||||
$buf = shift;
|
||||
$def = shift;
|
||||
for (@$buf) {
|
||||
my $line = $_;
|
||||
chomp $line;
|
||||
|
||||
if (/^[A-Z]/) {
|
||||
$start=0;
|
||||
last if $found;
|
||||
}
|
||||
|
||||
if ($start) {
|
||||
$found=1;
|
||||
$ndef.=$_;
|
||||
}
|
||||
|
||||
if ($line eq $def) {
|
||||
$start=1;
|
||||
}
|
||||
|
||||
}
|
||||
return $ndef;
|
||||
}
|
||||
|
||||
error("Usage $0 [lang.l]") unless ($srcfile);
|
||||
error("Can't find language file: $srcfile") if (! -f $srcfile);
|
||||
error("Can't find language file: $engfile") if (! -f $engfile);
|
||||
|
||||
open (EFILE, "< $engfile");
|
||||
while (<EFILE>) {
|
||||
my $line = $_;
|
||||
push(@efile, $line);
|
||||
chomp $line;
|
||||
if (/^[A-Z]/) {
|
||||
$wc = push (@defs, $line);
|
||||
$is_there{$line} = 1;
|
||||
}
|
||||
}
|
||||
close(EFILE);
|
||||
|
||||
open (SFILE, "< $srcfile");
|
||||
while (<SFILE>) {
|
||||
push(@sfile, $_);
|
||||
}
|
||||
close(SFILE);
|
||||
|
||||
#for (@defs) {
|
||||
# $is_there{$_} = 1;
|
||||
#}
|
||||
|
||||
for (@sfile) {
|
||||
my $line = $_;
|
||||
chomp $line;
|
||||
if (/^[A-Z]/) {
|
||||
if (not_del($line)) {
|
||||
while ($line ne $defs[$pos]) {
|
||||
print "ADD: $defs[$pos]\n";
|
||||
$pos++;
|
||||
}
|
||||
if (! /^STRFTIME/ ) {
|
||||
$edef = get_format(get_def(\@efile, $line)) ;
|
||||
$sdef = get_format(get_def(\@sfile, $line)) ;
|
||||
if ( $edef ne $sdef ) {
|
||||
print "FORMAT: $line (expecting '$edef' and got '$sdef')\n";
|
||||
}
|
||||
}
|
||||
$pos++;
|
||||
} else {
|
||||
print "DEL: $line\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for($pos ; $pos < $wc; $pos++) {
|
||||
print "ADD: $defs[$pos]\n";
|
||||
}
|
||||
|
||||
+265
@@ -0,0 +1,265 @@
|
||||
/* Multi-language support.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: language.c,v 1.9 2003/12/12 16:04:57 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "services.h"
|
||||
#include "language.h"
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* The list of lists of messages. */
|
||||
char **langtexts[NUM_LANGS];
|
||||
|
||||
/* The list of names of languages. */
|
||||
char *langnames[NUM_LANGS];
|
||||
|
||||
/* Indexes of available languages: */
|
||||
int langlist[NUM_LANGS];
|
||||
|
||||
/* Order in which languages should be displayed: (alphabetical) */
|
||||
static int langorder[NUM_LANGS] = {
|
||||
LANG_EN_US, /* English (US) */
|
||||
LANG_FR, /* French */
|
||||
LANG_DE, /* German */
|
||||
LANG_IT, /* Italian */
|
||||
LANG_JA_JIS, /* Japanese (JIS encoding) */
|
||||
LANG_JA_EUC, /* Japanese (EUC encoding) */
|
||||
LANG_JA_SJIS, /* Japanese (SJIS encoding) */
|
||||
LANG_PT, /* Portugese */
|
||||
LANG_ES, /* Spanish */
|
||||
LANG_TR, /* Turkish */
|
||||
LANG_CAT, /* Catalan */
|
||||
LANG_GR, /* Greek */
|
||||
LANG_NL, /* Dutch */
|
||||
LANG_RU, /* Russian */
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Load a language file. */
|
||||
|
||||
static int read_int32(int32 * ptr, FILE * f)
|
||||
{
|
||||
int a = fgetc(f);
|
||||
int b = fgetc(f);
|
||||
int c = fgetc(f);
|
||||
int d = fgetc(f);
|
||||
if (a == EOF || b == EOF || c == EOF || d == EOF)
|
||||
return -1;
|
||||
*ptr = a << 24 | b << 16 | c << 8 | d;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void load_lang(int index, const char *filename)
|
||||
{
|
||||
char buf[256];
|
||||
FILE *f;
|
||||
int num, i;
|
||||
|
||||
if (debug) {
|
||||
alog("debug: Loading language %d from file `languages/%s'",
|
||||
index, filename);
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "languages/%s", filename);
|
||||
if (!(f = fopen(buf, "r"))) {
|
||||
log_perror("Failed to load language %d (%s)", index, filename);
|
||||
return;
|
||||
} else if (read_int32(&num, f) < 0) {
|
||||
alog("Failed to read number of strings for language %d (%s)",
|
||||
index, filename);
|
||||
return;
|
||||
} else if (num != NUM_STRINGS) {
|
||||
alog("Warning: Bad number of strings (%d, wanted %d) "
|
||||
"for language %d (%s)", num, NUM_STRINGS, index, filename);
|
||||
}
|
||||
langtexts[index] = scalloc(sizeof(char *), NUM_STRINGS);
|
||||
if (num > NUM_STRINGS)
|
||||
num = NUM_STRINGS;
|
||||
for (i = 0; i < num; i++) {
|
||||
int32 pos, len;
|
||||
fseek(f, i * 8 + 4, SEEK_SET);
|
||||
if (read_int32(&pos, f) < 0 || read_int32(&len, f) < 0) {
|
||||
alog("Failed to read entry %d in language %d (%s) TOC",
|
||||
i, index, filename);
|
||||
while (--i >= 0) {
|
||||
if (langtexts[index][i])
|
||||
free(langtexts[index][i]);
|
||||
}
|
||||
free(langtexts[index]);
|
||||
langtexts[index] = NULL;
|
||||
return;
|
||||
}
|
||||
if (len == 0) {
|
||||
langtexts[index][i] = NULL;
|
||||
} else if (len >= 65536) {
|
||||
alog("Entry %d in language %d (%s) is too long (over 64k)--"
|
||||
"corrupt TOC?", i, index, filename);
|
||||
while (--i >= 0) {
|
||||
if (langtexts[index][i])
|
||||
free(langtexts[index][i]);
|
||||
}
|
||||
free(langtexts[index]);
|
||||
langtexts[index] = NULL;
|
||||
return;
|
||||
} else if (len < 0) {
|
||||
alog("Entry %d in language %d (%s) has negative length--"
|
||||
"corrupt TOC?", i, index, filename);
|
||||
while (--i >= 0) {
|
||||
if (langtexts[index][i])
|
||||
free(langtexts[index][i]);
|
||||
}
|
||||
free(langtexts[index]);
|
||||
langtexts[index] = NULL;
|
||||
return;
|
||||
} else {
|
||||
langtexts[index][i] = scalloc(len + 1, 1);
|
||||
fseek(f, pos, SEEK_SET);
|
||||
if (fread(langtexts[index][i], 1, len, f) != len) {
|
||||
alog("Failed to read string %d in language %d (%s)",
|
||||
i, index, filename);
|
||||
while (--i >= 0) {
|
||||
if (langtexts[index][i])
|
||||
free(langtexts[index][i]);
|
||||
}
|
||||
free(langtexts[index]);
|
||||
langtexts[index] = NULL;
|
||||
return;
|
||||
}
|
||||
langtexts[index][i][len] = 0;
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Initialize list of lists. */
|
||||
|
||||
void lang_init()
|
||||
{
|
||||
int i, j, n = 0;
|
||||
|
||||
load_lang(LANG_CAT, "cat");
|
||||
load_lang(LANG_DE, "de");
|
||||
load_lang(LANG_EN_US, "en_us");
|
||||
load_lang(LANG_ES, "es");
|
||||
load_lang(LANG_FR, "fr");
|
||||
load_lang(LANG_GR, "gr");
|
||||
load_lang(LANG_PT, "pt");
|
||||
load_lang(LANG_TR, "tr");
|
||||
load_lang(LANG_IT, "it");
|
||||
load_lang(LANG_NL, "nl");
|
||||
load_lang(LANG_RU, "ru");
|
||||
|
||||
for (i = 0; i < NUM_LANGS; i++) {
|
||||
if (langtexts[langorder[i]] != NULL) {
|
||||
langnames[langorder[i]] = langtexts[langorder[i]][LANG_NAME];
|
||||
langlist[n++] = langorder[i];
|
||||
for (j = 0; j < NUM_STRINGS; j++) {
|
||||
if (!langtexts[langorder[i]][j]) {
|
||||
langtexts[langorder[i]][j] =
|
||||
langtexts[DEF_LANGUAGE][j];
|
||||
}
|
||||
if (!langtexts[langorder[i]][j]) {
|
||||
langtexts[langorder[i]][j] = langtexts[LANG_EN_US][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while (n < NUM_LANGS)
|
||||
langlist[n++] = -1;
|
||||
|
||||
/* Not what I intended to do, but these services are so archaïc
|
||||
* that it's difficult to do more. */
|
||||
if ((NSDefLanguage = langlist[NSDefLanguage]) < 0)
|
||||
NSDefLanguage = DEF_LANGUAGE;
|
||||
|
||||
if (!langtexts[DEF_LANGUAGE])
|
||||
fatal("Unable to load default language");
|
||||
for (i = 0; i < NUM_LANGS; i++) {
|
||||
if (!langtexts[i])
|
||||
langtexts[i] = langtexts[DEF_LANGUAGE];
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* Format a string in a strftime()-like way, but heed the user's language
|
||||
* setting for month and day names. The string stored in the buffer will
|
||||
* always be null-terminated, even if the actual string was longer than the
|
||||
* buffer size.
|
||||
* Assumption: No month or day name has a length (including trailing null)
|
||||
* greater than BUFSIZE.
|
||||
*/
|
||||
|
||||
int strftime_lang(char *buf, int size, User * u, int format, struct tm *tm)
|
||||
{
|
||||
int language = u && u->na ? u->na->nc->language : NSDefLanguage;
|
||||
char tmpbuf[BUFSIZE], buf2[BUFSIZE];
|
||||
char *s;
|
||||
int i, ret;
|
||||
|
||||
strscpy(tmpbuf, langtexts[language][format], sizeof(tmpbuf));
|
||||
if ((s = langtexts[language][STRFTIME_DAYS_SHORT]) != NULL) {
|
||||
for (i = 0; i < tm->tm_wday; i++)
|
||||
s += strcspn(s, "\n") + 1;
|
||||
i = strcspn(s, "\n");
|
||||
strncpy(buf2, s, i);
|
||||
buf2[i] = 0;
|
||||
strnrepl(tmpbuf, sizeof(tmpbuf), "%a", buf2);
|
||||
}
|
||||
if ((s = langtexts[language][STRFTIME_DAYS_LONG]) != NULL) {
|
||||
for (i = 0; i < tm->tm_wday; i++)
|
||||
s += strcspn(s, "\n") + 1;
|
||||
i = strcspn(s, "\n");
|
||||
strncpy(buf2, s, i);
|
||||
buf2[i] = 0;
|
||||
strnrepl(tmpbuf, sizeof(tmpbuf), "%A", buf2);
|
||||
}
|
||||
if ((s = langtexts[language][STRFTIME_MONTHS_SHORT]) != NULL) {
|
||||
for (i = 0; i < tm->tm_mon; i++)
|
||||
s += strcspn(s, "\n") + 1;
|
||||
i = strcspn(s, "\n");
|
||||
strncpy(buf2, s, i);
|
||||
buf2[i] = 0;
|
||||
strnrepl(tmpbuf, sizeof(tmpbuf), "%b", buf2);
|
||||
}
|
||||
if ((s = langtexts[language][STRFTIME_MONTHS_LONG]) != NULL) {
|
||||
for (i = 0; i < tm->tm_mon; i++)
|
||||
s += strcspn(s, "\n") + 1;
|
||||
i = strcspn(s, "\n");
|
||||
strncpy(buf2, s, i);
|
||||
buf2[i] = 0;
|
||||
strnrepl(tmpbuf, sizeof(tmpbuf), "%B", buf2);
|
||||
}
|
||||
ret = strftime(buf, size, tmpbuf, tm);
|
||||
if (ret == size)
|
||||
buf[size - 1] = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* Send a syntax-error message to the user. */
|
||||
|
||||
void syntax_error(const char *service, User * u, const char *command,
|
||||
int msgnum)
|
||||
{
|
||||
const char *str = getstring(u->na, msgnum);
|
||||
notice_lang(service, u, SYNTAX_ERROR, str);
|
||||
notice_lang(service, u, MORE_INFO, service, command);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
@@ -0,0 +1,178 @@
|
||||
/* Routines to handle `listnicks' and `listchans' invocations.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: list.c,v 1.5 2003/07/20 01:15:49 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "services.h"
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void do_listnicks(int ac, char **av)
|
||||
{
|
||||
int count = 0; /* Count only rather than display? */
|
||||
int usage = 0; /* Display command usage? (>0 also indicates error) */
|
||||
int i;
|
||||
|
||||
i = 1;
|
||||
while (i < ac) {
|
||||
if (av[i][0] == '-') {
|
||||
switch (av[i][1]) {
|
||||
case 'h':
|
||||
usage = -1;
|
||||
break;
|
||||
case 'c':
|
||||
if (i > 1)
|
||||
usage = 1;
|
||||
count = 1;
|
||||
break;
|
||||
case 'd':
|
||||
if (av[i][2]) {
|
||||
services_dir = av[i] + 2;
|
||||
} else {
|
||||
if (i >= ac - 1) {
|
||||
usage = 1;
|
||||
break;
|
||||
}
|
||||
ac--;
|
||||
memmove(av + i, av + i + 1, sizeof(char *) * ac - i);
|
||||
services_dir = av[i];
|
||||
}
|
||||
default:
|
||||
usage = 1;
|
||||
break;
|
||||
} /* switch */
|
||||
ac--;
|
||||
if (i < ac)
|
||||
memmove(av + i, av + i + 1, sizeof(char *) * ac - i);
|
||||
} else {
|
||||
if (count)
|
||||
usage = 1;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (usage) {
|
||||
fprintf(stderr, "\
|
||||
\n\
|
||||
Usage: listnicks [-c] [-d data-dir] [nick [nick...]]\n\
|
||||
-c: display only count of registered nicks\n\
|
||||
(cannot be combined with nicks)\n\
|
||||
nick: nickname(s) to display information for\n\
|
||||
\n\
|
||||
If no nicks are given, the entire nickname database is printed out in\n\
|
||||
compact format followed by the number of registered nicks (with -c, the\n\
|
||||
list is suppressed and only the count is printed). If one or more nicks\n\
|
||||
are given, detailed information about those nicks is displayed.\n\
|
||||
\n");
|
||||
exit(usage > 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
if (chdir(services_dir) < 0) {
|
||||
fprintf(stderr, "chdir(%s): %s\n", services_dir, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
if (!read_config(0))
|
||||
exit(1);
|
||||
load_ns_dbase();
|
||||
|
||||
lang_init();
|
||||
|
||||
if (ac > 1) {
|
||||
for (i = 1; i < ac; i++)
|
||||
listnicks(0, av[i]);
|
||||
} else {
|
||||
listnicks(count, NULL);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void do_listchans(int ac, char **av)
|
||||
{
|
||||
int count = 0; /* Count only rather than display? */
|
||||
int usage = 0; /* Display command usage? (>0 also indicates error) */
|
||||
int i;
|
||||
|
||||
i = 1;
|
||||
while (i < ac) {
|
||||
if (av[i][0] == '-') {
|
||||
switch (av[i][1]) {
|
||||
case 'h':
|
||||
usage = -1;
|
||||
break;
|
||||
case 'c':
|
||||
if (i > 1)
|
||||
usage = 1;
|
||||
count = 1;
|
||||
break;
|
||||
case 'd':
|
||||
if (av[i][2]) {
|
||||
services_dir = av[i] + 2;
|
||||
} else {
|
||||
if (i >= ac - 1) {
|
||||
usage = 1;
|
||||
break;
|
||||
}
|
||||
ac--;
|
||||
memmove(av + i, av + i + 1, sizeof(char *) * ac - i);
|
||||
services_dir = av[i];
|
||||
}
|
||||
default:
|
||||
usage = 1;
|
||||
break;
|
||||
} /* switch */
|
||||
ac--;
|
||||
if (i < ac)
|
||||
memmove(av + i, av + i + 1, sizeof(char *) * ac - i);
|
||||
} else {
|
||||
if (count)
|
||||
usage = 1;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (usage) {
|
||||
fprintf(stderr, "\
|
||||
\n\
|
||||
Usage: listchans [-c] [-d data-dir] [channel [channel...]]\n\
|
||||
-c: display only count of registered channels\n\
|
||||
(cannot be combined with channels)\n\
|
||||
channel: channel(s) to display information for\n\
|
||||
\n\
|
||||
If no channels are given, the entire channel database is printed out in\n\
|
||||
compact format followed by the number of registered channels (with -c, the\n\
|
||||
list is suppressed and only the count is printed). If one or more channels\n\
|
||||
are given, detailed information about those channels is displayed.\n\
|
||||
\n");
|
||||
exit(usage > 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
if (chdir(services_dir) < 0) {
|
||||
fprintf(stderr, "chdir(%s): %s\n", services_dir, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
if (!read_config(0))
|
||||
exit(1);
|
||||
load_ns_dbase();
|
||||
load_cs_dbase();
|
||||
|
||||
lang_init();
|
||||
|
||||
if (ac > 1) {
|
||||
for (i = 1; i < ac; i++)
|
||||
listchans(0, av[i]);
|
||||
} else {
|
||||
listchans(count, NULL);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
@@ -0,0 +1,298 @@
|
||||
/* Logging routines.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: log.c,v 1.8 2003/07/20 01:15:49 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "services.h"
|
||||
#include "pseudo.h"
|
||||
|
||||
static FILE *logfile;
|
||||
|
||||
static int curday = 0;
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static int get_logname(char *name, int count, struct tm *tm)
|
||||
{
|
||||
|
||||
char timestamp[32];
|
||||
|
||||
if (!tm) {
|
||||
time_t t;
|
||||
|
||||
time(&t);
|
||||
tm = localtime(&t);
|
||||
}
|
||||
|
||||
strftime(timestamp, count, "%Y%m%d", tm);
|
||||
snprintf(name, count, "logs/%s.%s", log_filename, timestamp);
|
||||
curday = tm->tm_yday;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static void remove_log(void)
|
||||
{
|
||||
time_t t;
|
||||
struct tm tm;
|
||||
|
||||
char name[PATH_MAX];
|
||||
|
||||
if (!KeepLogs)
|
||||
return;
|
||||
|
||||
time(&t);
|
||||
t -= (60 * 60 * 24 * KeepLogs);
|
||||
tm = *localtime(&t);
|
||||
|
||||
if (!get_logname(name, sizeof(name), &tm))
|
||||
return;
|
||||
unlink(name);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static void checkday(void)
|
||||
{
|
||||
time_t t;
|
||||
struct tm tm;
|
||||
|
||||
time(&t);
|
||||
tm = *localtime(&t);
|
||||
|
||||
if (curday != tm.tm_yday) {
|
||||
close_log();
|
||||
remove_log();
|
||||
open_log();
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Open the log file. Return -1 if the log file could not be opened, else
|
||||
* return 0. */
|
||||
|
||||
int open_log(void)
|
||||
{
|
||||
char name[PATH_MAX];
|
||||
|
||||
if (logfile)
|
||||
return 0;
|
||||
|
||||
if (!get_logname(name, sizeof(name), NULL))
|
||||
return 0;
|
||||
logfile = fopen(name, "a");
|
||||
|
||||
if (logfile)
|
||||
setbuf(logfile, NULL);
|
||||
return logfile != NULL ? 0 : -1;
|
||||
}
|
||||
|
||||
/* Close the log file. */
|
||||
|
||||
void close_log(void)
|
||||
{
|
||||
if (!logfile)
|
||||
return;
|
||||
fclose(logfile);
|
||||
logfile = NULL;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Log stuff to the log file with a datestamp. Note that errno is
|
||||
* preserved by this routine and log_perror().
|
||||
*/
|
||||
|
||||
void alog(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
time_t t;
|
||||
struct tm tm;
|
||||
char buf[256];
|
||||
int errno_save = errno;
|
||||
|
||||
checkday();
|
||||
|
||||
va_start(args, fmt);
|
||||
time(&t);
|
||||
tm = *localtime(&t);
|
||||
#if HAVE_GETTIMEOFDAY
|
||||
if (debug) {
|
||||
char *s;
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
strftime(buf, sizeof(buf) - 1, "[%b %d %H:%M:%S", &tm);
|
||||
s = buf + strlen(buf);
|
||||
s += snprintf(s, sizeof(buf) - (s - buf), ".%06d", tv.tv_usec);
|
||||
strftime(s, sizeof(buf) - (s - buf) - 1, " %Y] ", &tm);
|
||||
} else {
|
||||
#endif
|
||||
strftime(buf, sizeof(buf) - 1, "[%b %d %H:%M:%S %Y] ", &tm);
|
||||
#if HAVE_GETTIMEOFDAY
|
||||
}
|
||||
#endif
|
||||
if (logfile) {
|
||||
fputs(buf, logfile);
|
||||
vfprintf(logfile, fmt, args);
|
||||
fputc('\n', logfile);
|
||||
}
|
||||
if (nofork) {
|
||||
fputs(buf, stderr);
|
||||
vfprintf(stderr, fmt, args);
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
|
||||
if (LogChannel && logchan && !debug && findchan(LogChannel)) {
|
||||
char str[BUFSIZE];
|
||||
vsnprintf(str, sizeof(str), fmt, args);
|
||||
privmsg(s_GlobalNoticer, LogChannel, str);
|
||||
}
|
||||
|
||||
errno = errno_save;
|
||||
}
|
||||
|
||||
|
||||
/* Like alog(), but tack a ": " and a system error message (as returned by
|
||||
* strerror()) onto the end.
|
||||
*/
|
||||
|
||||
void log_perror(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
time_t t;
|
||||
struct tm tm;
|
||||
char buf[256];
|
||||
int errno_save = errno;
|
||||
|
||||
checkday();
|
||||
|
||||
va_start(args, fmt);
|
||||
time(&t);
|
||||
tm = *localtime(&t);
|
||||
#if HAVE_GETTIMEOFDAY
|
||||
if (debug) {
|
||||
char *s;
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
strftime(buf, sizeof(buf) - 1, "[%b %d %H:%M:%S", &tm);
|
||||
s = buf + strlen(buf);
|
||||
s += snprintf(s, sizeof(buf) - (s - buf), ".%06d", tv.tv_usec);
|
||||
strftime(s, sizeof(buf) - (s - buf) - 1, " %Y] ", &tm);
|
||||
} else {
|
||||
#endif
|
||||
strftime(buf, sizeof(buf) - 1, "[%b %d %H:%M:%S %Y] ", &tm);
|
||||
#if HAVE_GETTIMEOFDAY
|
||||
}
|
||||
#endif
|
||||
if (logfile) {
|
||||
fputs(buf, logfile);
|
||||
vfprintf(logfile, fmt, args);
|
||||
fprintf(logfile, ": %s\n", strerror(errno_save));
|
||||
}
|
||||
if (nofork) {
|
||||
fputs(buf, stderr);
|
||||
vfprintf(stderr, fmt, args);
|
||||
fprintf(stderr, ": %s\n", strerror(errno_save));
|
||||
}
|
||||
errno = errno_save;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* We've hit something we can't recover from. Let people know what
|
||||
* happened, then go down.
|
||||
*/
|
||||
|
||||
void fatal(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
time_t t;
|
||||
struct tm tm;
|
||||
char buf[256], buf2[4096];
|
||||
|
||||
checkday();
|
||||
|
||||
va_start(args, fmt);
|
||||
time(&t);
|
||||
tm = *localtime(&t);
|
||||
#if HAVE_GETTIMEOFDAY
|
||||
if (debug) {
|
||||
char *s;
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
strftime(buf, sizeof(buf) - 1, "[%b %d %H:%M:%S", &tm);
|
||||
s = buf + strlen(buf);
|
||||
s += snprintf(s, sizeof(buf) - (s - buf), ".%06d", tv.tv_usec);
|
||||
strftime(s, sizeof(buf) - (s - buf) - 1, " %Y] ", &tm);
|
||||
} else {
|
||||
#endif
|
||||
strftime(buf, sizeof(buf) - 1, "[%b %d %H:%M:%S %Y] ", &tm);
|
||||
#if HAVE_GETTIMEOFDAY
|
||||
}
|
||||
#endif
|
||||
vsnprintf(buf2, sizeof(buf2), fmt, args);
|
||||
if (logfile)
|
||||
fprintf(logfile, "%sFATAL: %s\n", buf, buf2);
|
||||
if (nofork)
|
||||
fprintf(stderr, "%sFATAL: %s\n", buf, buf2);
|
||||
if (servsock >= 0)
|
||||
wallops(NULL, "FATAL ERROR! %s", buf2);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/* Same thing, but do it like perror(). */
|
||||
|
||||
void fatal_perror(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
time_t t;
|
||||
struct tm tm;
|
||||
char buf[256], buf2[4096];
|
||||
int errno_save = errno;
|
||||
|
||||
checkday();
|
||||
|
||||
va_start(args, fmt);
|
||||
time(&t);
|
||||
tm = *localtime(&t);
|
||||
#if HAVE_GETTIMEOFDAY
|
||||
if (debug) {
|
||||
char *s;
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
strftime(buf, sizeof(buf) - 1, "[%b %d %H:%M:%S", &tm);
|
||||
s = buf + strlen(buf);
|
||||
s += snprintf(s, sizeof(buf) - (s - buf), ".%06d", tv.tv_usec);
|
||||
strftime(s, sizeof(buf) - (s - buf) - 1, " %Y] ", &tm);
|
||||
} else {
|
||||
#endif
|
||||
strftime(buf, sizeof(buf) - 1, "[%b %d %H:%M:%S %Y] ", &tm);
|
||||
#if HAVE_GETTIMEOFDAY
|
||||
}
|
||||
#endif
|
||||
vsnprintf(buf2, sizeof(buf2), fmt, args);
|
||||
if (logfile)
|
||||
fprintf(logfile, "%sFATAL: %s: %s\n", buf, buf2,
|
||||
strerror(errno_save));
|
||||
if (stderr)
|
||||
fprintf(stderr, "%sFATAL: %s: %s\n", buf, buf2,
|
||||
strerror(errno_save));
|
||||
if (servsock >= 0)
|
||||
wallops(NULL, "FATAL ERROR! %s: %s", buf2, strerror(errno_save));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
@@ -0,0 +1,202 @@
|
||||
/* Mail utility routines.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: mail.c,v 1.9 2003/09/04 18:55:34 rob Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "services.h"
|
||||
#include "language.h"
|
||||
|
||||
/* Begins to send a mail. Must be followed by a MailEnd call.
|
||||
* Returns NULL if the call failed. Error messages are
|
||||
* automatically sent to the user.
|
||||
*/
|
||||
|
||||
MailInfo *MailRegBegin(User * u, NickRequest * nr, char *subject,
|
||||
char *service)
|
||||
{
|
||||
if (!u || !nr || !subject)
|
||||
return NULL;
|
||||
|
||||
if (!UseMail) {
|
||||
notice_lang(service, u, MAIL_DISABLED);
|
||||
} else if ((time(NULL) - u->lastmail < MailDelay)
|
||||
|| (time(NULL) - nr->lastmail < MailDelay)) {
|
||||
notice_lang(service, u, MAIL_DELAYED, MailDelay);
|
||||
} else if (!nr->email) {
|
||||
notice_lang(service, u, MAIL_INVALID, nr->nick);
|
||||
} else {
|
||||
MailInfo *mail;
|
||||
|
||||
mail = scalloc(sizeof(MailInfo), 1);
|
||||
mail->sender = u;
|
||||
mail->recipient = NULL;
|
||||
mail->recip = nr;
|
||||
|
||||
if (!(mail->pipe = popen(SendMailPath, "w"))) {
|
||||
free(mail);
|
||||
notice_lang(service, u, MAIL_LATER);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fprintf(mail->pipe, "From: %s\n", SendFrom);
|
||||
if (DontQuoteAddresses) {
|
||||
fprintf(mail->pipe, "To: %s <%s>\n", nr->nick, nr->email);
|
||||
} else {
|
||||
fprintf(mail->pipe, "To: \"%s\" <%s>\n", nr->nick, nr->email);
|
||||
}
|
||||
fprintf(mail->pipe, "Subject: %s\n", subject);
|
||||
return mail;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Begins to send a mail. Must be followed by a MailEnd call.
|
||||
* Returns NULL if the call failed. Error messages are
|
||||
* automatically sent to the user.
|
||||
*/
|
||||
|
||||
MailInfo *MailBegin(User * u, NickCore * nc, char *subject, char *service)
|
||||
{
|
||||
if (!u || !nc || !subject)
|
||||
return NULL;
|
||||
|
||||
if (!UseMail) {
|
||||
notice_lang(service, u, MAIL_DISABLED);
|
||||
} else if (((time(NULL) - u->lastmail < MailDelay)
|
||||
|| (time(NULL) - nc->lastmail < MailDelay))
|
||||
&& !is_services_root(u)) {
|
||||
notice_lang(service, u, MAIL_DELAYED, MailDelay);
|
||||
} else if (!nc->email) {
|
||||
notice_lang(service, u, MAIL_INVALID, nc->display);
|
||||
} else {
|
||||
MailInfo *mail;
|
||||
|
||||
mail = scalloc(sizeof(MailInfo), 1);
|
||||
mail->sender = u;
|
||||
mail->recipient = nc;
|
||||
mail->recip = NULL;
|
||||
|
||||
if (!(mail->pipe = popen(SendMailPath, "w"))) {
|
||||
free(mail);
|
||||
notice_lang(service, u, MAIL_LATER);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fprintf(mail->pipe, "From: %s\n", SendFrom);
|
||||
if (DontQuoteAddresses) {
|
||||
fprintf(mail->pipe, "To: %s <%s>\n", nc->display, nc->email);
|
||||
} else {
|
||||
fprintf(mail->pipe, "To: \"%s\" <%s>\n", nc->display,
|
||||
nc->email);
|
||||
}
|
||||
fprintf(mail->pipe, "Subject: %s\n", subject);
|
||||
|
||||
return mail;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Finish to send the mail. Cleanup everything. */
|
||||
|
||||
void MailEnd(MailInfo * mail)
|
||||
{
|
||||
if (!mail || !mail->sender || !mail->pipe)
|
||||
return;
|
||||
|
||||
if (!mail->recipient && !mail->recip)
|
||||
return;
|
||||
|
||||
pclose(mail->pipe);
|
||||
|
||||
mail->sender->lastmail = time(NULL);
|
||||
if (mail->recipient)
|
||||
mail->recipient->lastmail = time(NULL);
|
||||
else
|
||||
mail->recip->lastmail = time(NULL);
|
||||
|
||||
|
||||
free(mail);
|
||||
}
|
||||
|
||||
/* Resets the MailDelay protection */
|
||||
|
||||
void MailReset(User * u, NickCore * nc)
|
||||
{
|
||||
if (u)
|
||||
u->lastmail = 0;
|
||||
if (nc)
|
||||
nc->lastmail = 0;
|
||||
}
|
||||
|
||||
/* Checks whether we have a valid, common e-mail address.
|
||||
* This is NOT entirely RFC compliant, and won't be so, because I said
|
||||
* *common* cases. ;) It is very unlikely that e-mail addresses that
|
||||
* are really being used will fail the check.
|
||||
*
|
||||
* FIXME: rewrite this a bit cleaner.
|
||||
*/
|
||||
|
||||
int MailValidate(const char *email)
|
||||
{
|
||||
int i, j, has_period = 0, len;
|
||||
char copy[BUFSIZE], *domain;
|
||||
|
||||
static char specials[] =
|
||||
{ '(', ')', '<', '>', '@', ',', ';', ':', '\\', '\"', '[', ']',
|
||||
' '
|
||||
};
|
||||
|
||||
if (!email)
|
||||
return 0;
|
||||
strcpy(copy, email);
|
||||
|
||||
domain = strchr(copy, '@');
|
||||
if (!domain)
|
||||
return 0;
|
||||
*domain = '\0';
|
||||
domain++;
|
||||
|
||||
/* Don't accept NULL copy or domain. */
|
||||
if (*copy == 0 || *domain == 0)
|
||||
return 0;
|
||||
|
||||
/* Check for forbidden characters in the name */
|
||||
for (i = 0; i < strlen(copy); i++) {
|
||||
|
||||
if (copy[i] <= 31 || copy[i] >= 127)
|
||||
return 0;
|
||||
for (j = 0; j < 13; j++)
|
||||
if (copy[i] == specials[j])
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check for forbidden characters in the domain, and if it seems to be valid. */
|
||||
for (i = 0; i < (len = strlen(domain)); i++) {
|
||||
if (domain[i] <= 31 || domain[i] >= 127)
|
||||
return 0;
|
||||
for (j = 0; j < 13; j++)
|
||||
if (domain[i] == specials[j])
|
||||
return 0;
|
||||
if (domain[i] == '.') {
|
||||
if (i == 0 || i == len - 1)
|
||||
return 0;
|
||||
has_period = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_period)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,521 @@
|
||||
/* Services -- main source file.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* 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 (see the file COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: main.c,v 1.23 2004/03/13 13:55:59 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "services.h"
|
||||
#include "timeout.h"
|
||||
#include "version.h"
|
||||
#include "datafiles.h"
|
||||
|
||||
/******** Global variables! ********/
|
||||
|
||||
/* Command-line options: (note that configuration variables are in config.c) */
|
||||
char *services_dir = SERVICES_DIR; /* -dir dirname */
|
||||
char *log_filename = LOG_FILENAME; /* -log filename */
|
||||
int debug = 0; /* -debug */
|
||||
int readonly = 0; /* -readonly */
|
||||
int logchan = 0; /* -logchan */
|
||||
int skeleton = 0; /* -skeleton */
|
||||
int nofork = 0; /* -nofork */
|
||||
int forceload = 0; /* -forceload */
|
||||
int noexpire = 0; /* -noexpire */
|
||||
#ifdef IS44_CONVERTER
|
||||
int is44 = 0; /* -is44 */
|
||||
#endif
|
||||
|
||||
#ifdef USE_RDB
|
||||
int do_mysql = 0; /* use mysql ? */
|
||||
#endif
|
||||
|
||||
/* Set to 1 if we are to quit */
|
||||
int quitting = 0;
|
||||
|
||||
/* Set to 1 if we are to quit after saving databases */
|
||||
int delayed_quit = 0;
|
||||
|
||||
/* Contains a message as to why services is terminating */
|
||||
char *quitmsg = NULL;
|
||||
|
||||
/* Input buffer - global, so we can dump it if something goes wrong */
|
||||
char inbuf[BUFSIZE];
|
||||
|
||||
/* Socket for talking to server */
|
||||
int servsock = -1;
|
||||
|
||||
/* Should we update the databases now? */
|
||||
int save_data = 0;
|
||||
|
||||
/* At what time were we started? */
|
||||
time_t start_time;
|
||||
|
||||
/* Parameters and environment */
|
||||
char **my_av, **my_envp;
|
||||
|
||||
/******** Local variables! ********/
|
||||
|
||||
/* Set to 1 if we are waiting for input */
|
||||
static int waiting = 0;
|
||||
|
||||
/* Set to 1 after we've set everything up */
|
||||
static int started = 0;
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Run expiration routines */
|
||||
|
||||
static void expire_all(void)
|
||||
{
|
||||
waiting = -3;
|
||||
if (debug)
|
||||
alog("debug: Running expire routines");
|
||||
if (!skeleton) {
|
||||
waiting = -21;
|
||||
expire_nicks();
|
||||
waiting = -22;
|
||||
expire_chans();
|
||||
waiting = -23;
|
||||
expire_requests();
|
||||
}
|
||||
waiting = -25;
|
||||
expire_akills();
|
||||
#ifdef IRC_BAHAMUT
|
||||
waiting = -26;
|
||||
expire_sglines();
|
||||
#endif
|
||||
waiting = -28;
|
||||
expire_sqlines();
|
||||
#ifdef IRC_BAHAMUT
|
||||
waiting = -27;
|
||||
expire_szlines();
|
||||
#endif
|
||||
#ifndef STREAMLINED
|
||||
expire_exceptions();
|
||||
#endif
|
||||
#ifdef USE_THREADS
|
||||
if (ProxyDetect)
|
||||
proxy_expire();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void save_databases(void)
|
||||
{
|
||||
waiting = -2;
|
||||
if (debug)
|
||||
alog("debug: Saving FFF databases");
|
||||
waiting = -10;
|
||||
backup_databases();
|
||||
if (!skeleton) {
|
||||
waiting = -11;
|
||||
save_ns_dbase();
|
||||
waiting = -12;
|
||||
if (PreNickDBName) {
|
||||
save_ns_req_dbase();
|
||||
waiting = -13;
|
||||
}
|
||||
save_cs_dbase();
|
||||
if (s_BotServ) {
|
||||
waiting = -14;
|
||||
save_bs_dbase();
|
||||
}
|
||||
if (s_HostServ) {
|
||||
waiting = -15;
|
||||
save_hs_dbase();
|
||||
}
|
||||
}
|
||||
waiting = -16;
|
||||
save_os_dbase();
|
||||
waiting = -17;
|
||||
save_news();
|
||||
waiting = -18;
|
||||
save_exceptions();
|
||||
|
||||
#ifdef USE_RDB
|
||||
if (do_mysql) {
|
||||
if (debug)
|
||||
alog("debug: Saving RDB databases");
|
||||
waiting = -10;
|
||||
if (!skeleton) {
|
||||
waiting = -11;
|
||||
save_ns_rdb_dbase();
|
||||
waiting = -12;
|
||||
save_cs_rdb_dbase();
|
||||
if (PreNickDBName) {
|
||||
save_ns_req_rdb_dbase();
|
||||
waiting = -13;
|
||||
}
|
||||
/* Temporary fix to avoid unwanted timeouts... */
|
||||
send_cmd(ServerName, "PONG %s", ServerName);
|
||||
if (s_BotServ) {
|
||||
waiting = -14;
|
||||
save_bs_rdb_dbase();
|
||||
}
|
||||
if (s_HostServ) {
|
||||
waiting = -15;
|
||||
save_hs_rdb_dbase();
|
||||
}
|
||||
waiting = -16;
|
||||
save_os_rdb_dbase();
|
||||
waiting = -17;
|
||||
save_rdb_news();
|
||||
waiting = -18;
|
||||
save_rdb_exceptions();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Restarts services */
|
||||
|
||||
static void services_restart(void)
|
||||
{
|
||||
alog("Restarting");
|
||||
if (!quitmsg)
|
||||
quitmsg = "Restarting";
|
||||
send_cmd(ServerName, "SQUIT %s :%s", ServerName, quitmsg);
|
||||
disconn(servsock);
|
||||
close_log();
|
||||
#if defined(LINUX20) || defined(LINUX22)
|
||||
pthread_kill_other_threads_np();
|
||||
#endif
|
||||
execve(SERVICES_BIN, my_av, my_envp);
|
||||
if (!readonly) {
|
||||
open_log();
|
||||
log_perror("Restart failed");
|
||||
close_log();
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/**
|
||||
* Added to allow do_restart from operserv access to the static functions without making them
|
||||
* fair game to every other function - not exactly ideal :|
|
||||
**/
|
||||
void do_restart_services(void)
|
||||
{
|
||||
expire_all();
|
||||
save_databases();
|
||||
services_restart();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Terminates services */
|
||||
|
||||
static void services_shutdown(void)
|
||||
{
|
||||
if (!quitmsg)
|
||||
quitmsg = "Terminating, reason unknown";
|
||||
alog("%s", quitmsg);
|
||||
if (started)
|
||||
send_cmd(ServerName, "SQUIT %s :%s", ServerName, quitmsg);
|
||||
disconn(servsock);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* If we get a weird signal, come here. */
|
||||
|
||||
void sighandler(int signum)
|
||||
{
|
||||
if (started) {
|
||||
if (signum == SIGHUP) { /* SIGHUP = save databases and restart */
|
||||
signal(SIGHUP, SIG_IGN);
|
||||
alog("Received SIGHUP, restarting.");
|
||||
|
||||
expire_all();
|
||||
save_databases();
|
||||
|
||||
if (!quitmsg)
|
||||
quitmsg = "Restarting on SIGHUP";
|
||||
|
||||
#ifdef SERVICES_BIN
|
||||
services_restart();
|
||||
exit(1);
|
||||
#else
|
||||
quitmsg =
|
||||
"Restart attempt failed--SERVICES_BIN not defined (rerun configure)";
|
||||
#endif
|
||||
} else if (signum == SIGTERM) {
|
||||
signal(SIGTERM, SIG_IGN);
|
||||
signal(SIGHUP, SIG_IGN);
|
||||
|
||||
alog("Received SIGTERM, exiting.");
|
||||
|
||||
expire_all();
|
||||
save_databases();
|
||||
quitmsg = "Shutting down on SIGTERM";
|
||||
services_shutdown();
|
||||
exit(0);
|
||||
} else if (signum == SIGINT || signum == SIGQUIT) {
|
||||
/* nothing -- terminate below */
|
||||
} else if (!waiting) {
|
||||
alog("PANIC! buffer = %s", inbuf);
|
||||
/* Cut off if this would make IRC command >510 characters. */
|
||||
if (strlen(inbuf) > 448) {
|
||||
inbuf[446] = '>';
|
||||
inbuf[447] = '>';
|
||||
inbuf[448] = 0;
|
||||
}
|
||||
wallops(NULL, "PANIC! buffer = %s\r\n", inbuf);
|
||||
} else if (waiting < 0) {
|
||||
/* This is static on the off-chance we run low on stack */
|
||||
static char buf[BUFSIZE];
|
||||
switch (waiting) {
|
||||
case -1:
|
||||
snprintf(buf, sizeof(buf), "in timed_update");
|
||||
break;
|
||||
case -10:
|
||||
snprintf(buf, sizeof(buf), "backing up databases");
|
||||
break;
|
||||
case -11:
|
||||
snprintf(buf, sizeof(buf), "saving %s", NickDBName);
|
||||
break;
|
||||
case -12:
|
||||
snprintf(buf, sizeof(buf), "saving %s", ChanDBName);
|
||||
break;
|
||||
case -13:
|
||||
snprintf(buf, sizeof(buf), "saving %s", PreNickDBName);
|
||||
break;
|
||||
case -14:
|
||||
snprintf(buf, sizeof(buf), "saving %s", BotDBName);
|
||||
break;
|
||||
case -15:
|
||||
snprintf(buf, sizeof(buf), "saving %s", HostDBName);
|
||||
break;
|
||||
case -16:
|
||||
snprintf(buf, sizeof(buf), "saving %s", OperDBName);
|
||||
break;
|
||||
case -17:
|
||||
snprintf(buf, sizeof(buf), "saving %s", NewsDBName);
|
||||
break;
|
||||
case -18:
|
||||
snprintf(buf, sizeof(buf), "saving %s", ExceptionDBName);
|
||||
break;
|
||||
case -21:
|
||||
snprintf(buf, sizeof(buf), "expiring nicknames");
|
||||
break;
|
||||
case -22:
|
||||
snprintf(buf, sizeof(buf), "expiring channels");
|
||||
break;
|
||||
case -25:
|
||||
snprintf(buf, sizeof(buf), "expiring autokills");
|
||||
break;
|
||||
#ifdef IRC_BAHAMUT
|
||||
case -26:
|
||||
snprintf(buf, sizeof(buf), "expiring SGLINEs");
|
||||
break;
|
||||
case -27:
|
||||
snprintf(buf, sizeof(buf), "expiring SZLINEs");
|
||||
break;
|
||||
#endif
|
||||
case -28:
|
||||
snprintf(buf, sizeof(buf), "expiring SQLINEs");
|
||||
break;
|
||||
default:
|
||||
snprintf(buf, sizeof(buf), "waiting=%d", waiting);
|
||||
}
|
||||
wallops(NULL, "PANIC! %s (%s)", buf, strsignal(signum));
|
||||
alog("PANIC! %s (%s)", buf, strsignal(signum));
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
#if !defined(USE_THREADS) || !defined(LINUX20)
|
||||
signum == SIGUSR1 ||
|
||||
#endif
|
||||
!(quitmsg = calloc(BUFSIZE, 1))) {
|
||||
quitmsg = "Out of memory!";
|
||||
} else {
|
||||
#if HAVE_STRSIGNAL
|
||||
snprintf(quitmsg, BUFSIZE, "Services terminating: %s",
|
||||
strsignal(signum));
|
||||
#else
|
||||
snprintf(quitmsg, BUFSIZE, "Services terminating on signal %d",
|
||||
signum);
|
||||
#endif
|
||||
}
|
||||
if (started) {
|
||||
services_shutdown();
|
||||
exit(0);
|
||||
} else {
|
||||
alog("%s", quitmsg);
|
||||
if (isatty(2))
|
||||
fprintf(stderr, "%s\n", quitmsg);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Main routine. (What does it look like? :-) ) */
|
||||
|
||||
int main(int ac, char **av, char **envp)
|
||||
{
|
||||
volatile time_t last_update; /* When did we last update the databases? */
|
||||
volatile time_t last_expire; /* When did we last expire nicks/channels? */
|
||||
volatile time_t last_check; /* When did we last check timeouts? */
|
||||
volatile time_t last_DefCon; /* When was DefCon last checked? */
|
||||
|
||||
int i;
|
||||
char *progname;
|
||||
|
||||
my_av = av;
|
||||
my_envp = envp;
|
||||
|
||||
/* Find program name. */
|
||||
if ((progname = strrchr(av[0], '/')) != NULL)
|
||||
progname++;
|
||||
else
|
||||
progname = av[0];
|
||||
|
||||
/* Were we run under "listnicks" or "listchans"? Do appropriate stuff
|
||||
* if so. */
|
||||
if (strcmp(progname, "listnicks") == 0) {
|
||||
do_listnicks(ac, av);
|
||||
return 0;
|
||||
} else if (strcmp(progname, "listchans") == 0) {
|
||||
do_listchans(ac, av);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Initialization stuff. */
|
||||
if ((i = init(ac, av)) != 0)
|
||||
return i;
|
||||
|
||||
|
||||
/* We have a line left over from earlier, so process it first. */
|
||||
process();
|
||||
|
||||
/* Set up timers. */
|
||||
last_update = time(NULL);
|
||||
last_expire = time(NULL);
|
||||
last_check = time(NULL);
|
||||
last_DefCon = time(NULL);
|
||||
|
||||
started = 1;
|
||||
|
||||
/*** Main loop. ***/
|
||||
|
||||
while (!quitting) {
|
||||
time_t t = time(NULL);
|
||||
|
||||
if (debug >= 2)
|
||||
alog("debug: Top of main loop");
|
||||
|
||||
if (!noexpire && !readonly
|
||||
&& (save_data || t - last_expire >= ExpireTimeout)) {
|
||||
expire_all();
|
||||
last_expire = t;
|
||||
}
|
||||
|
||||
if (!readonly && (save_data || t - last_update >= UpdateTimeout)) {
|
||||
if (delayed_quit)
|
||||
wallops(NULL,
|
||||
"Updating databases on shutdown, please wait.");
|
||||
|
||||
save_databases();
|
||||
|
||||
if (save_data < 0)
|
||||
break; /* out of main loop */
|
||||
|
||||
save_data = 0;
|
||||
last_update = t;
|
||||
}
|
||||
|
||||
if ((DefConTimeOut) && (t - last_DefCon >= dotime(DefConTimeOut))) {
|
||||
resetDefCon(5);
|
||||
last_DefCon = t;
|
||||
}
|
||||
|
||||
if (delayed_quit)
|
||||
break;
|
||||
|
||||
moduleCallBackRun();
|
||||
|
||||
waiting = -1;
|
||||
if (t - last_check >= TimeoutCheck) {
|
||||
check_timeouts();
|
||||
last_check = t;
|
||||
}
|
||||
|
||||
waiting = 1;
|
||||
i = (int) (long) sgets2(inbuf, sizeof(inbuf), servsock);
|
||||
waiting = 0;
|
||||
if (i > 0) {
|
||||
process();
|
||||
} else if (i == 0) {
|
||||
int errno_save = errno;
|
||||
quitmsg = scalloc(BUFSIZE, 1);
|
||||
if (quitmsg) {
|
||||
snprintf(quitmsg, BUFSIZE, "Read error from server: %s",
|
||||
strerror(errno_save));
|
||||
} else {
|
||||
quitmsg = "Read error from server";
|
||||
}
|
||||
quitting = 1;
|
||||
}
|
||||
waiting = -4;
|
||||
}
|
||||
|
||||
|
||||
/* Check for restart instead of exit */
|
||||
if (save_data == -2) {
|
||||
#ifdef SERVICES_BIN
|
||||
alog("Restarting");
|
||||
if (!quitmsg)
|
||||
quitmsg = "Restarting";
|
||||
send_cmd(ServerName, "SQUIT %s :%s", ServerName, quitmsg);
|
||||
disconn(servsock);
|
||||
close_log();
|
||||
#if defined(LINUX20) || defined(LINUX22)
|
||||
pthread_kill_other_threads_np();
|
||||
#endif
|
||||
execve(SERVICES_BIN, av, envp);
|
||||
if (!readonly) {
|
||||
open_log();
|
||||
log_perror("Restart failed");
|
||||
close_log();
|
||||
}
|
||||
return 1;
|
||||
#else
|
||||
quitmsg =
|
||||
"Restart attempt failed--SERVICES_BIN not defined (rerun configure)";
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Disconnect and exit */
|
||||
services_shutdown();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
@@ -0,0 +1,96 @@
|
||||
/* Memory management routines.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: memory.c,v 1.7 2003/07/20 01:15:49 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "services.h"
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* smalloc, scalloc, srealloc, sstrdup:
|
||||
* Versions of the memory allocation functions which will cause the
|
||||
* program to terminate with an "Out of memory" error if the memory
|
||||
* cannot be allocated. (Hence, the return value from these functions
|
||||
* is never NULL.)
|
||||
*/
|
||||
|
||||
void *smalloc(long size)
|
||||
{
|
||||
void *buf;
|
||||
|
||||
if (!size) {
|
||||
size = 1;
|
||||
}
|
||||
buf = malloc(size);
|
||||
if (!buf)
|
||||
#if !defined(USE_THREADS) || !defined(LINUX20)
|
||||
raise(SIGUSR1);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
return buf;
|
||||
}
|
||||
|
||||
void *scalloc(long elsize, long els)
|
||||
{
|
||||
void *buf;
|
||||
|
||||
if (!elsize || !els) {
|
||||
elsize = els = 1;
|
||||
}
|
||||
buf = calloc(elsize, els);
|
||||
if (!buf)
|
||||
#if !defined(USE_THREADS) || !defined(LINUX20)
|
||||
raise(SIGUSR1);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
return buf;
|
||||
}
|
||||
|
||||
void *srealloc(void *oldptr, long newsize)
|
||||
{
|
||||
void *buf;
|
||||
|
||||
if (!newsize) {
|
||||
newsize = 1;
|
||||
}
|
||||
buf = realloc(oldptr, newsize);
|
||||
if (!buf)
|
||||
#if !defined(USE_THREADS) || !defined(LINUX20)
|
||||
raise(SIGUSR1);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *sstrdup(const char *s)
|
||||
{
|
||||
char *t = strdup(s);
|
||||
if (!t)
|
||||
#if !defined(USE_THREADS) || !defined(LINUX20)
|
||||
raise(SIGUSR1);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
return t;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* In the future: malloc() replacements that tell us if we're leaking and
|
||||
* maybe do sanity checks too... */
|
||||
|
||||
/*************************************************************************/
|
||||
+1175
File diff suppressed because it is too large
Load Diff
+1196
File diff suppressed because it is too large
Load Diff
+23
@@ -0,0 +1,23 @@
|
||||
/* Declarations of IRC message structures, variables, and functions.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: messages.h,v 1.5 2003/07/20 01:15:49 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
/*************************************************************************/
|
||||
#include "modules.h"
|
||||
|
||||
extern Message messages[];
|
||||
extern void moduleAddMsgs(void);
|
||||
extern Message *find_message(const char *name);
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
@@ -0,0 +1,642 @@
|
||||
/* Miscellaneous routines.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: misc.c,v 1.14 2004/01/31 18:57:18 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "services.h"
|
||||
#include "language.h"
|
||||
|
||||
/* Cheaper than isspace() or isblank() */
|
||||
#define issp(c) ((c) == 32)
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* toupper/tolower: Like the ANSI functions, but make sure we return an
|
||||
* int instead of a (signed) char.
|
||||
*/
|
||||
|
||||
int toupper(char c)
|
||||
{
|
||||
if (islower(c))
|
||||
return (unsigned char) c - ('a' - 'A');
|
||||
else
|
||||
return (unsigned char) c;
|
||||
}
|
||||
|
||||
int tolower(char c)
|
||||
{
|
||||
if (isupper(c))
|
||||
return (unsigned char) c + ('a' - 'A');
|
||||
else
|
||||
return (unsigned char) c;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* strscpy: Copy at most len-1 characters from a string to a buffer, and
|
||||
* add a null terminator after the last character copied.
|
||||
*/
|
||||
|
||||
char *strscpy(char *d, const char *s, size_t len)
|
||||
{
|
||||
char *d_orig = d;
|
||||
|
||||
if (!len)
|
||||
return d;
|
||||
while (--len && (*d++ = *s++));
|
||||
*d = '\0';
|
||||
return d_orig;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* stristr: Search case-insensitively for string s2 within string s1,
|
||||
* returning the first occurrence of s2 or NULL if s2 was not
|
||||
* found.
|
||||
*/
|
||||
|
||||
char *stristr(char *s1, char *s2)
|
||||
{
|
||||
register char *s = s1, *d = s2;
|
||||
|
||||
while (*s1) {
|
||||
if (tolower(*s1) == tolower(*d)) {
|
||||
s1++;
|
||||
d++;
|
||||
if (*d == 0)
|
||||
return s;
|
||||
} else {
|
||||
s = ++s1;
|
||||
d = s2;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* strnrepl: Replace occurrences of `old' with `new' in string `s'. Stop
|
||||
* replacing if a replacement would cause the string to exceed
|
||||
* `size' bytes (including the null terminator). Return the
|
||||
* string.
|
||||
*/
|
||||
|
||||
char *strnrepl(char *s, int32 size, const char *old, const char *new)
|
||||
{
|
||||
char *ptr = s;
|
||||
int32 left = strlen(s);
|
||||
int32 avail = size - (left + 1);
|
||||
int32 oldlen = strlen(old);
|
||||
int32 newlen = strlen(new);
|
||||
int32 diff = newlen - oldlen;
|
||||
|
||||
while (left >= oldlen) {
|
||||
if (strncmp(ptr, old, oldlen) != 0) {
|
||||
left--;
|
||||
ptr++;
|
||||
continue;
|
||||
}
|
||||
if (diff > avail)
|
||||
break;
|
||||
if (diff != 0)
|
||||
memmove(ptr + oldlen + diff, ptr + oldlen, left + 1);
|
||||
strncpy(ptr, new, newlen);
|
||||
ptr += newlen;
|
||||
left -= oldlen;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* merge_args: Take an argument count and argument vector and merge them
|
||||
* into a single string in which each argument is separated by
|
||||
* a space.
|
||||
*/
|
||||
|
||||
char *merge_args(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
static char s[4096];
|
||||
char *t;
|
||||
|
||||
t = s;
|
||||
for (i = 0; i < argc; i++)
|
||||
t += snprintf(t, sizeof(s) - (t - s), "%s%s", *argv++,
|
||||
(i < argc - 1) ? " " : "");
|
||||
return s;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* match_wild: Attempt to match a string to a pattern which might contain
|
||||
* '*' or '?' wildcards. Return 1 if the string matches the
|
||||
* pattern, 0 if not.
|
||||
*/
|
||||
|
||||
static int do_match_wild(const char *pattern, const char *str, int docase)
|
||||
{
|
||||
char c;
|
||||
const char *s;
|
||||
|
||||
/* This WILL eventually terminate: either by *pattern == 0, or by a
|
||||
* trailing '*'. */
|
||||
|
||||
for (;;) {
|
||||
switch (c = *pattern++) {
|
||||
case 0:
|
||||
if (!*str)
|
||||
return 1;
|
||||
return 0;
|
||||
case '?':
|
||||
if (!*str)
|
||||
return 0;
|
||||
str++;
|
||||
break;
|
||||
case '*':
|
||||
if (!*pattern)
|
||||
return 1; /* trailing '*' matches everything else */
|
||||
s = str;
|
||||
while (*s) {
|
||||
if ((docase ? (*s == *pattern)
|
||||
: (tolower(*s) == tolower(*pattern)))
|
||||
&& do_match_wild(pattern, s, docase))
|
||||
return 1;
|
||||
s++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (docase ? (*str++ != c) : (tolower(*str++) != tolower(c)))
|
||||
return 0;
|
||||
break;
|
||||
} /* switch */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int match_wild(const char *pattern, const char *str)
|
||||
{
|
||||
return do_match_wild(pattern, str, 1);
|
||||
}
|
||||
|
||||
int match_wild_nocase(const char *pattern, const char *str)
|
||||
{
|
||||
return do_match_wild(pattern, str, 0);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* Process a string containing a number/range list in the form
|
||||
* "n1[-n2][,n3[-n4]]...", calling a caller-specified routine for each
|
||||
* number in the list. If the callback returns -1, stop immediately.
|
||||
* Returns the sum of all nonnegative return values from the callback.
|
||||
* If `count' is non-NULL, it will be set to the total number of times the
|
||||
* callback was called.
|
||||
*
|
||||
* The callback should be of type range_callback_t, which is defined as:
|
||||
* int (*range_callback_t)(User *u, int num, va_list args)
|
||||
*/
|
||||
|
||||
int process_numlist(const char *numstr, int *count_ret,
|
||||
range_callback_t callback, User * u, ...)
|
||||
{
|
||||
int n1, n2, i;
|
||||
int res = 0, retval = 0, count = 0;
|
||||
va_list args;
|
||||
|
||||
va_start(args, u);
|
||||
|
||||
/*
|
||||
* This algorithm ignores invalid characters, ignores a dash
|
||||
* when it precedes a comma, and ignores everything from the
|
||||
* end of a valid number or range to the next comma or null.
|
||||
*/
|
||||
for (;;) {
|
||||
n1 = n2 = strtol(numstr, (char **) &numstr, 10);
|
||||
numstr += strcspn(numstr, "0123456789,-");
|
||||
if (*numstr == '-') {
|
||||
numstr++;
|
||||
numstr += strcspn(numstr, "0123456789,");
|
||||
if (isdigit(*numstr)) {
|
||||
n2 = strtol(numstr, (char **) &numstr, 10);
|
||||
numstr += strcspn(numstr, "0123456789,-");
|
||||
}
|
||||
}
|
||||
for (i = n1; i <= n2 && i >= 0; i++) {
|
||||
int res = callback(u, i, args);
|
||||
count++;
|
||||
if (res < 0)
|
||||
break;
|
||||
retval += res;
|
||||
if (count >= 32767) {
|
||||
if (count_ret)
|
||||
*count_ret = count;
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
if (res < -1)
|
||||
break;
|
||||
numstr += strcspn(numstr, ",");
|
||||
if (*numstr)
|
||||
numstr++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (count_ret)
|
||||
*count_ret = count;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* dotime: Return the number of seconds corresponding to the given time
|
||||
* string. If the given string does not represent a valid time,
|
||||
* return -1.
|
||||
*
|
||||
* A time string is either a plain integer (representing a number
|
||||
* of seconds), or an integer followed by one of these characters:
|
||||
* "s" (seconds), "m" (minutes), "h" (hours), or "d" (days).
|
||||
*/
|
||||
|
||||
int dotime(const char *s)
|
||||
{
|
||||
int amount;
|
||||
|
||||
amount = strtol(s, (char **) &s, 10);
|
||||
if (*s) {
|
||||
switch (*s) {
|
||||
case 's':
|
||||
return amount;
|
||||
case 'm':
|
||||
return amount * 60;
|
||||
case 'h':
|
||||
return amount * 3600;
|
||||
case 'd':
|
||||
return amount * 86400;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return amount;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Expresses in a string the period of time represented by a given amount
|
||||
of seconds (with days/hours/minutes). */
|
||||
|
||||
char *duration(NickAlias * na, char *buf, int bufsize, time_t seconds)
|
||||
{
|
||||
int days = 0, hours = 0, minutes = 0;
|
||||
int need_comma = 0;
|
||||
|
||||
char buf2[64], *end;
|
||||
char *comma = getstring(na, COMMA_SPACE);
|
||||
|
||||
/* We first calculate everything */
|
||||
days = seconds / 86400;
|
||||
seconds -= (days * 86400);
|
||||
hours = seconds / 3600;
|
||||
seconds -= (hours * 3600);
|
||||
minutes = seconds / 60;
|
||||
|
||||
if (!days && !hours && !minutes) {
|
||||
snprintf(buf, bufsize,
|
||||
getstring(na,
|
||||
(seconds <=
|
||||
1 ? DURATION_SECOND : DURATION_SECONDS)),
|
||||
seconds);
|
||||
} else {
|
||||
end = buf;
|
||||
if (days) {
|
||||
snprintf(buf2, sizeof(buf2),
|
||||
getstring(na,
|
||||
(days == 1 ? DURATION_DAY : DURATION_DAYS)),
|
||||
days);
|
||||
end += snprintf(end, bufsize - (end - buf), "%s", buf2);
|
||||
need_comma = 1;
|
||||
}
|
||||
if (hours) {
|
||||
snprintf(buf2, sizeof(buf2),
|
||||
getstring(na,
|
||||
(hours ==
|
||||
1 ? DURATION_HOUR : DURATION_HOURS)),
|
||||
hours);
|
||||
end +=
|
||||
snprintf(end, bufsize - (end - buf), "%s%s",
|
||||
(need_comma ? comma : ""), buf2);
|
||||
need_comma = 1;
|
||||
}
|
||||
if (minutes) {
|
||||
snprintf(buf2, sizeof(buf2),
|
||||
getstring(na,
|
||||
(minutes ==
|
||||
1 ? DURATION_MINUTE : DURATION_MINUTES)),
|
||||
minutes);
|
||||
end +=
|
||||
snprintf(end, bufsize - (end - buf), "%s%s",
|
||||
(need_comma ? comma : ""), buf2);
|
||||
need_comma = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Generates a human readable string of type "expires in ..." */
|
||||
|
||||
char *expire_left(NickAlias * na, char *buf, int len, time_t expires)
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
|
||||
if (!expires) {
|
||||
strncpy(buf, getstring(na, NO_EXPIRE), len);
|
||||
} else if (expires <= now) {
|
||||
strncpy(buf, getstring(na, EXPIRES_SOON), len);
|
||||
} else {
|
||||
time_t diff = expires - now + 59;
|
||||
|
||||
if (diff >= 86400) {
|
||||
int days = diff / 86400;
|
||||
snprintf(buf, len,
|
||||
getstring(na, (days == 1) ? EXPIRES_1D : EXPIRES_D),
|
||||
days);
|
||||
} else {
|
||||
if (diff <= 3600) {
|
||||
int minutes = diff / 60;
|
||||
snprintf(buf, len,
|
||||
getstring(na,
|
||||
(minutes ==
|
||||
1) ? EXPIRES_1M : EXPIRES_M), minutes);
|
||||
} else {
|
||||
int hours = diff / 3600, minutes;
|
||||
diff -= (hours * 3600);
|
||||
minutes = diff / 60;
|
||||
snprintf(buf, len,
|
||||
getstring(na,
|
||||
((hours == 1
|
||||
&& minutes ==
|
||||
1) ? EXPIRES_1H1M : ((hours == 1
|
||||
&& minutes !=
|
||||
1) ? EXPIRES_1HM
|
||||
: ((hours != 1
|
||||
&& minutes ==
|
||||
1) ?
|
||||
EXPIRES_H1M :
|
||||
EXPIRES_HM)))),
|
||||
hours, minutes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return 1 if a host is valid, 0 if it isnt.
|
||||
* host = string to check
|
||||
* type = format, 1 = ip4addr, 2 = hostname
|
||||
*
|
||||
* shortname = ( letter / digit ) *( letter / digit / "-" ) *( letter / digit )
|
||||
* hostname = shortname *( "." shortname )
|
||||
* ip4addr = 1*3digit "." 1*3digit "." 1*3digit "." 1*3digit
|
||||
*
|
||||
**/
|
||||
|
||||
int doValidHost(const char *host, int type)
|
||||
{
|
||||
int idx = 0;
|
||||
int len = 0;
|
||||
int sec_len = 0;
|
||||
int dots = 1;
|
||||
if (type != 1 && type != 2) {
|
||||
return 0;
|
||||
}
|
||||
if (!host) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = strlen(host);
|
||||
|
||||
if (len > HOSTMAX) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case 1:
|
||||
for (idx = 0; idx < len; idx++) {
|
||||
if (isdigit(host[idx])) {
|
||||
if (sec_len < 3) {
|
||||
sec_len++;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (idx == 0) {
|
||||
return 0;
|
||||
} /* cant start with a non-digit */
|
||||
if (host[idx] != '.') {
|
||||
return 0;
|
||||
} /* only . is a valid non-digit */
|
||||
if (sec_len > 3) {
|
||||
return 0;
|
||||
} /* sections cant be more than 3 digits */
|
||||
sec_len = 0;
|
||||
dots++;
|
||||
}
|
||||
}
|
||||
if (dots != 4) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
dots = 0;
|
||||
for (idx = 0; idx < len; idx++) {
|
||||
if (!isalnum(host[idx])) {
|
||||
if (idx == 0) {
|
||||
return 0;
|
||||
}
|
||||
if ((host[idx] != '.') && (host[idx] != '-')) {
|
||||
return 0;
|
||||
}
|
||||
if (host[idx] == '.') {
|
||||
dots++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (host[len - 1] == '.') {
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* Ultimate3 dosnt like a non-dotted hosts at all, nor does unreal,
|
||||
* so just dont allow them.
|
||||
**/
|
||||
if (dots == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return 1 if a host is valid, 0 if it isnt.
|
||||
* host = string to check
|
||||
* type = format, 1 = ip4addr, 2 = hostname, 3 = either
|
||||
*
|
||||
* shortname = ( letter / digit ) *( letter / digit / "-" ) *( letter / digit )
|
||||
* hostname = shortname *( "." shortname )
|
||||
* ip4addr = 1*3digit "." 1*3digit "." 1*3digit "." 1*3digit
|
||||
*
|
||||
**/
|
||||
int isValidHost(const char *host, int type)
|
||||
{
|
||||
int status = 0;
|
||||
if (type == 3) {
|
||||
if (!(status = doValidHost(host, 1))) {
|
||||
status = doValidHost(host, 2);
|
||||
}
|
||||
} else {
|
||||
status = doValidHost(host, type);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
int isvalidchar(const char c)
|
||||
{
|
||||
if (((c >= 'A') && (c <= 'Z')) ||
|
||||
((c >= 'a') && (c <= 'z')) ||
|
||||
((c >= '0') && (c <= '9')) || (c == '.') || (c == '-'))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *myStrGetToken(const char *str, const char dilim, int token_number)
|
||||
{
|
||||
int len, idx, counter = 0, start_pos = 0;
|
||||
char *substring = NULL;
|
||||
if (!str) {
|
||||
return NULL;
|
||||
}
|
||||
len = strlen(str);
|
||||
for (idx = 0; idx <= len; idx++) {
|
||||
if ((str[idx] == dilim) || (idx == len)) {
|
||||
if (counter == token_number) {
|
||||
substring = myStrSubString(str, start_pos, idx);
|
||||
counter++;
|
||||
} else {
|
||||
start_pos = idx + 1;
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return substring;
|
||||
}
|
||||
|
||||
char *myStrGetOnlyToken(const char *str, const char dilim,
|
||||
int token_number)
|
||||
{
|
||||
int len, idx, counter = 0, start_pos = 0;
|
||||
char *substring = NULL;
|
||||
if (!str) {
|
||||
return NULL;
|
||||
}
|
||||
len = strlen(str);
|
||||
for (idx = 0; idx <= len; idx++) {
|
||||
if (str[idx] == dilim) {
|
||||
if (counter == token_number) {
|
||||
if (str[idx] == '\r')
|
||||
substring = myStrSubString(str, start_pos, idx - 1);
|
||||
else
|
||||
substring = myStrSubString(str, start_pos, idx);
|
||||
counter++;
|
||||
} else {
|
||||
start_pos = idx + 1;
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return substring;
|
||||
}
|
||||
|
||||
char *myStrGetTokenRemainder(const char *str, const char dilim,
|
||||
int token_number)
|
||||
{
|
||||
int len, idx, counter = 0, start_pos = 0;
|
||||
char *substring = NULL;
|
||||
if (!str) {
|
||||
return NULL;
|
||||
}
|
||||
len = strlen(str);
|
||||
|
||||
for (idx = 0; idx <= len; idx++) {
|
||||
if ((str[idx] == dilim) || (idx == len)) {
|
||||
if (counter == token_number) {
|
||||
substring = myStrSubString(str, start_pos, len);
|
||||
counter++;
|
||||
} else {
|
||||
start_pos = idx + 1;
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return substring;
|
||||
}
|
||||
|
||||
char *myStrSubString(const char *src, int start, int end)
|
||||
{
|
||||
char *substring = NULL;
|
||||
int len, idx;
|
||||
if (!src) {
|
||||
return NULL;
|
||||
}
|
||||
len = strlen(src);
|
||||
if (((start >= 0) && (end <= len)) && (end > start)) {
|
||||
substring = (char *) malloc(sizeof(char) * ((end - start) + 1));
|
||||
for (idx = 0; idx <= end - start; idx++) {
|
||||
substring[idx] = src[start + idx];
|
||||
}
|
||||
substring[end - start] = '\0';
|
||||
}
|
||||
return substring;
|
||||
}
|
||||
|
||||
void doCleanBuffer(char *str)
|
||||
{
|
||||
char *in = str;
|
||||
char *out = str;
|
||||
char ch;
|
||||
|
||||
while (issp(ch = *in++));
|
||||
if (ch != '\0')
|
||||
for (;;) {
|
||||
*out++ = ch;
|
||||
ch = *in++;
|
||||
if (ch == '\0')
|
||||
break;
|
||||
if (!issp(ch))
|
||||
continue;
|
||||
while (issp(ch = *in++));
|
||||
if (ch == '\0')
|
||||
break;
|
||||
*out++ = ' ';
|
||||
}
|
||||
*out = ch; // == '\0'
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
/* Modular support
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: modules.h,v 1.16 2004/03/11 16:50:01 rob Exp $
|
||||
*/
|
||||
|
||||
#ifndef MODULES_H
|
||||
#define MODULES_H
|
||||
|
||||
#include <time.h>
|
||||
#include "services.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/*************************************************************************/
|
||||
#define CMD_HASH(x) (((x)[0]&31)<<5 | ((x)[1]&31)) /* Will gen a hash from a string :) */
|
||||
#define MAX_CMD_HASH 1024
|
||||
|
||||
#define MOD_STOP 1
|
||||
#define MOD_CONT 0
|
||||
|
||||
#define HOSTSERV HS_cmdTable /* using HOSTSERV etc. looks nicer than HS_cmdTable for modules */
|
||||
#define BOTSERV BS_cmdTable
|
||||
#define MEMOSERV MS_cmdTable
|
||||
#define NICKSERV NS_cmdTable
|
||||
#define CHANSERV CS_cmdTable
|
||||
#define HELPSERV HE_cmdTable
|
||||
#define OPERSERV OS_cmdTable
|
||||
#define IRCD IRCD_cmdTable
|
||||
#define MODULE_HASH Module_table
|
||||
|
||||
/**********************************************************************
|
||||
* Module Returns
|
||||
**********************************************************************/
|
||||
#define MOD_ERR_OK 0
|
||||
#define MOD_ERR_MEMORY 1
|
||||
#define MOD_ERR_PARAMS 2
|
||||
#define MOD_ERR_EXISTS 3
|
||||
#define MOD_ERR_NOEXIST 4
|
||||
#define MOD_ERR_NOUSER 5
|
||||
#define MOD_ERR_NOLOAD 6
|
||||
#define MOD_ERR_NOUNLOAD 7
|
||||
#define MOD_ERR_SYNTAX 8
|
||||
#define MOD_ERR_NODELETE 9
|
||||
#define MOD_ERR_UNKNOWN 10
|
||||
#define MOD_ERR_FILE_IO 11
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Structure for information about a *Serv command. */
|
||||
|
||||
typedef struct Command_ Command;
|
||||
typedef struct CommandHash_ CommandHash;
|
||||
typedef struct Module_ Module;
|
||||
typedef struct ModuleHash_ ModuleHash;
|
||||
typedef struct Message_ Message;
|
||||
typedef struct MessageHash_ MessageHash;
|
||||
typedef struct ModuleCallBack_ ModuleCallBack;
|
||||
|
||||
extern CommandHash *HOSTSERV[MAX_CMD_HASH];
|
||||
extern CommandHash *BOTSERV[MAX_CMD_HASH];
|
||||
extern CommandHash *MEMOSERV[MAX_CMD_HASH];
|
||||
extern CommandHash *NICKSERV[MAX_CMD_HASH];
|
||||
extern CommandHash *CHANSERV[MAX_CMD_HASH];
|
||||
extern CommandHash *HELPSERV[MAX_CMD_HASH];
|
||||
extern CommandHash *OPERSERV[MAX_CMD_HASH];
|
||||
extern MessageHash *IRCD[MAX_CMD_HASH];
|
||||
|
||||
struct Module_ {
|
||||
char *name;
|
||||
char *filename;
|
||||
void *handle;
|
||||
time_t time;
|
||||
char *version;
|
||||
char *author;
|
||||
|
||||
void (*nickHelp)(User *u); /* service 1 */
|
||||
void (*chanHelp)(User *u); /* 2 */
|
||||
void (*memoHelp)(User *u); /* 3 */
|
||||
void (*botHelp)(User *u); /* 4 */
|
||||
void (*operHelp)(User *u); /* 5 */
|
||||
void (*hostHelp)(User *u); /* 6 */
|
||||
void (*helpHelp)(User *u); /* 7 */
|
||||
|
||||
// CommandHash *cmdList[MAX_CMD_HASH];
|
||||
MessageHash *msgList[MAX_CMD_HASH];
|
||||
};
|
||||
|
||||
struct ModuleHash_ {
|
||||
char *name;
|
||||
Module *m;
|
||||
ModuleHash *next;
|
||||
};
|
||||
|
||||
struct Command_ {
|
||||
char *name;
|
||||
int (*routine)(User *u);
|
||||
int (*has_priv)(User *u); /* Returns 1 if user may use command, else 0 */
|
||||
|
||||
/* Regrettably, these are hard-coded to correspond to current privilege
|
||||
* levels (v4.0). Suggestions for better ways to do this are
|
||||
* appreciated.
|
||||
*/
|
||||
int helpmsg_all; /* Displayed to all users; -1 = no message */
|
||||
int helpmsg_reg; /* Displayed to regular users only */
|
||||
int helpmsg_oper; /* Displayed to Services operators only */
|
||||
int helpmsg_admin; /* Displayed to Services admins only */
|
||||
int helpmsg_root; /* Displayed to Services root only */
|
||||
char *help_param1;
|
||||
char *help_param2;
|
||||
char *help_param3;
|
||||
char *help_param4;
|
||||
|
||||
/* Module related stuff */
|
||||
int core; /* Can this command be deleted? */
|
||||
char *mod_name; /* Name of the module who owns us, NULL for core's */
|
||||
char *service; /* Service we provide this command for */
|
||||
int (*all_help)(User *u);
|
||||
int (*regular_help)(User *u);
|
||||
int (*oper_help)(User *u);
|
||||
int (*admin_help)(User *u);
|
||||
int (*root_help)(User *u);
|
||||
|
||||
Command *next; /* Next command responsible for the same command */
|
||||
};
|
||||
|
||||
struct CommandHash_ {
|
||||
char *name; /* Name of the command */
|
||||
Command *c; /* Actual command */
|
||||
CommandHash *next; /* Next command */
|
||||
};
|
||||
|
||||
struct Message_ {
|
||||
char *name;
|
||||
int (*func)(char *source, int ac, char **av);
|
||||
int core;
|
||||
char *mod_name;
|
||||
Message *next;
|
||||
};
|
||||
|
||||
struct MessageHash_ {
|
||||
char *name;
|
||||
Message *m;
|
||||
MessageHash *next;
|
||||
};
|
||||
|
||||
struct ModuleCallBack_ {
|
||||
char *name;
|
||||
char *owner_name;
|
||||
time_t when;
|
||||
int (*func)(int argc, char *argv[]);
|
||||
int argc;
|
||||
char **argv;
|
||||
ModuleCallBack *next;
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
/* Module Managment Functions */
|
||||
Module *createModule(char *filename); /* Create a new module, using the given name */
|
||||
int destroyModule(Module *m); /* Delete the module */
|
||||
int addModule(Module *m); /* Add a module to the module hash */
|
||||
int delModule(Module *m); /* Remove a module from the module hash */
|
||||
Module *findModule(char *name); /* Find a module */
|
||||
int loadModule(Module *m,User *u); /* Load the given module into the program */
|
||||
int unloadModule(Module *m, User *u); /* Unload the given module from the pro */
|
||||
int prepForUnload(Module *m); /* Prepare the module for unload */
|
||||
void moduleAddVersion(char *version);
|
||||
void moduleAddAuthor(char *author);
|
||||
void modules_init(void);
|
||||
void modules_delayed_init(void);
|
||||
void moduleCallBackPrepForUnload(char *mod_name);
|
||||
void moduleCallBackDeleteEntry(ModuleCallBack * prev);
|
||||
char *moduleGetLastBuffer(void);
|
||||
void moduleSetHelpHelp(void (*func) (User * u));
|
||||
void moduleDisplayHelp(int service, User *u);
|
||||
void moduleSetHostHelp(void (*func) (User * u));
|
||||
void moduleSetOperHelp(void (*func) (User * u));
|
||||
void moduleSetBotHelp(void (*func) (User * u));
|
||||
void moduleSetMemoHelp(void (*func) (User * u));
|
||||
void moduleSetChanHelp(void (*func) (User * u));
|
||||
void moduleSetNickHelp(void (*func) (User * u));
|
||||
int moduleAddHelp(Command * c, int (*func) (User * u));
|
||||
int moduleAddRegHelp(Command * c, int (*func) (User * u));
|
||||
int moduleAddOperHelp(Command * c, int (*func) (User * u));
|
||||
int moduleAddAdminHelp(Command * c, int (*func) (User * u));
|
||||
int moduleAddRootHelp(Command * c, int (*func) (User * u));
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/* Command Managment Functions */
|
||||
Command *createCommand(const char *name,int (*func)(User *u),int (*has_priv)(User *u),int help_all, int help_reg, int help_oper, int help_admin,int help_root);
|
||||
int destroyCommand(Command *c); /* destroy a command */
|
||||
int addCoreCommand(CommandHash *cmdTable[], Command *c); /* Add a command to a command table */
|
||||
int moduleAddCommand(CommandHash *cmdTable[], Command *c, int pos);
|
||||
int addCommand(CommandHash *cmdTable[], Command *c,int pos);
|
||||
int delCommand(CommandHash *cmdTable[], Command *c,char *mod_name); /* Del a command from a cmd table */
|
||||
int moduleDelCommand(CommandHash *cmdTable[],char *name); /* Del a command from a cmd table */
|
||||
Command *findCommand(CommandHash *cmdTable[], const char *name); /* Find a command */
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/* Message Managment Functions */
|
||||
Message *createMessage(char *name,int (*func)(char *source, int ac, char **av));
|
||||
Message *findMessage(MessageHash *msgTable[], const char *name); /* Find a Message */
|
||||
int addMessage(MessageHash *msgTable[], Message *m, int pos); /* Add a Message to a Message table */
|
||||
int addCoreMessage(MessageHash *msgTable[], Message *m); /* Add a Message to a Message table */
|
||||
int moduleAddMessage(Message *m, int pos);
|
||||
int delMessage(MessageHash *msgTable[], Message *m, char *mod_name); /* Del a Message from a msg table */
|
||||
int moduleDelMessage(char *name);
|
||||
int destroyMessage(Message *m); /* destroy a Message*/
|
||||
Message *findMessage(MessageHash *msgTable[], const char *name);
|
||||
/*************************************************************************/
|
||||
int moduleAddCallback(char *name,time_t when,int (*func)(int argc, char *argv[]),int argc, char **argv);
|
||||
void moduleDelCallback(char *name);
|
||||
void moduleCallBackRun(void);
|
||||
/*************************************************************************/
|
||||
|
||||
#endif
|
||||
/* EOF */
|
||||
@@ -0,0 +1,26 @@
|
||||
include ../Makefile.inc
|
||||
include ./Makefile.inc
|
||||
|
||||
OBJECTS= $(SRCS:.c=.o)
|
||||
SO_FILES=$(OBJECTS:.o=.s)
|
||||
CDEFS= -g -rdynamic -Wall
|
||||
CFLAGS=$(BASE_CFLAGS) $(CDEFS)
|
||||
|
||||
all: $(OBJECTS)
|
||||
|
||||
install: $(SO_FILES)
|
||||
$(CP_ALL) ./*.so $(MODULE_PATH)
|
||||
|
||||
distclean: clean spotless
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
.o.s:
|
||||
ld -shared $< -o $*.so
|
||||
|
||||
clean:
|
||||
rm -f *.o core
|
||||
|
||||
spotless: clean
|
||||
rm -f *.so Makefile.inc
|
||||
@@ -0,0 +1 @@
|
||||
Please read the "MODULES" file located on the "docs" directory.
|
||||
Executable
+37
@@ -0,0 +1,37 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Disabled for Anope 1.6 until we figure out a better way to
|
||||
# download modules safely.
|
||||
# if [ "$1" = "getmods" ] ; then
|
||||
# wget -nv -r -l 1 -A c -nd -nc http://modules.anope.org/download/
|
||||
# rm -f robots.txt
|
||||
# exit 0
|
||||
# fi
|
||||
|
||||
if [ ! -f ../Makefile.inc ]; then
|
||||
echo ""
|
||||
echo "*** ERROR: Unable to find ../Makefile.inc. You must ./configure Anope before"
|
||||
echo "*** ERROR: compiling modules. Please read the INSTALL document for details."
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -n "SRCS=" > ./Makefile.inc
|
||||
FIRST=1
|
||||
for oldfile in *.c
|
||||
do
|
||||
if [ "$FIRST" = 1 ] ; then
|
||||
echo -n " "$oldfile >> ./Makefile.inc
|
||||
else
|
||||
echo "\\" >> ./Makefile.inc
|
||||
echo -n " " $oldfile >> ./Makefile.inc
|
||||
fi
|
||||
FIRST=0
|
||||
done
|
||||
echo "" >> ./Makefile.inc
|
||||
|
||||
make
|
||||
|
||||
if [ "$1" = "install" ] ; then
|
||||
make install
|
||||
fi
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo -n "SRCS=" > ./Makefile.inc
|
||||
FIRST=1
|
||||
for oldfile in *.c
|
||||
do
|
||||
if [ "$FIRST" = 1 ] ; then
|
||||
echo -n " "$oldfile >> ./Makefile.inc
|
||||
else
|
||||
echo "\\" >> ./Makefile.inc
|
||||
echo -n " " $oldfile >> ./Makefile.inc
|
||||
fi
|
||||
FIRST=0
|
||||
done
|
||||
echo "" >> ./Makefile.inc
|
||||
|
||||
cat <<EOT
|
||||
All done! Now run "make" (or possibly "gmake") to compile your modules.
|
||||
See the INSTALL, README and FAQ files if you have any problems.
|
||||
EOT
|
||||
exit 0
|
||||
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* This is an EXAMPLE module, which adds the "moo" command to HostServ
|
||||
*
|
||||
* This command does NOT do anything useful at all!
|
||||
*
|
||||
* Please visit http://modules.anope.org for useful modules!
|
||||
*
|
||||
**/
|
||||
#include "module.h"
|
||||
|
||||
#define AUTHOR "Anope" /* Set the Author for a modinfo reply */
|
||||
#define VERSION "1.1" /* Set the version for a modinfo reply */
|
||||
|
||||
int hs_moo_show(User * u); /* Function to use when a /hs moo command is recived */
|
||||
int test(int argc, char **argv);
|
||||
void myHostServHelp(User *u); /* Function to display out help in a /hs help response */
|
||||
int myHostServMooHelp(User *u); /* Function to display help to _everyone_ when a /hs help moo is called*/
|
||||
int myHostServMooRegHelp(User *u); /* Function to display extra help to regular-users when a /hs help moo is called*/
|
||||
int myHostServMooOperHelp(User *u); /* Function to display extra help to opers when a /hs help moo is called*/
|
||||
int myHostServMooAdminHelp(User *u); /* Function to display extra help to admins when a /hs help moo is called*/
|
||||
int myHostServMooRootHelp(User *u); /* Function to display extra help to roors when a /hs help moo is called*/
|
||||
|
||||
int AnopeInit(int argc, char **argv) /* This will be executed when the module is loaded */
|
||||
{
|
||||
Command *c; /* Pointer to a Command */
|
||||
c = createCommand("moo", hs_moo_show, NULL, -1, -1, -1, -1, -1); /* Create a new command "moo" pointing to hs_moo */
|
||||
|
||||
moduleAddHelp(c,myHostServMooHelp); /* add help for all users to this command */
|
||||
moduleAddRegHelp(c,myHostServMooRegHelp); /* add extra regular-user only help to this command */
|
||||
moduleAddOperHelp(c,myHostServMooOperHelp); /* add extra oper only help to this command */
|
||||
moduleAddAdminHelp(c,myHostServMooAdminHelp); /* add extra admin only help to this command */
|
||||
moduleAddRootHelp(c,myHostServMooRootHelp); /* add extra root only help to this command */
|
||||
|
||||
moduleSetHostHelp(myHostServHelp); /* add us to the .hs help list */
|
||||
|
||||
|
||||
alog("hs_moo.so: Add Command 'moo' Status: %d", /* Log the command being added */
|
||||
moduleAddCommand(HOSTSERV, c, MOD_HEAD)); /* And add it to the HOSTSERV cmd table */
|
||||
moduleAddCallback("test",time(NULL)+dotime("15s"),test,0,NULL); /* set a call-back function to exec in 3 mins time */
|
||||
moduleDelCallback("test");
|
||||
moduleAddAuthor(AUTHOR); /* tell Anope about the author */
|
||||
moduleAddVersion(VERSION); /* Tell Anope about the verison */
|
||||
return MOD_CONT;
|
||||
}
|
||||
|
||||
int hs_moo_show(User * u)
|
||||
{
|
||||
notice(s_HostServ, u->nick, "MOO! - This command was loaded via a module!"); /* Just notice the user */
|
||||
return MOD_STOP; /* MOD_STOP means we will NOT pass control back to other */
|
||||
} /* modules waiting to handle the /hs moo command! */
|
||||
|
||||
int test(int argc, char **argv) {
|
||||
alog("CallBack from hs_moo with %d paramaters",argc);
|
||||
return MOD_CONT;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************************************************************************/
|
||||
/* The code below here shows various ways of dealing with the module help system */
|
||||
/***************************************************************************************************************************************/
|
||||
|
||||
void myHostServHelp(User *u) {
|
||||
notice(s_HostServ,u->nick, " MOO Moo's at the user!"); /* this will appear in the help list */
|
||||
}
|
||||
|
||||
int myHostServMooHelp(User *u) {
|
||||
notice(s_HostServ,u->nick,"Syntax: Moo"); /* this will be sent to everyone who does /msg hostserv help moo */
|
||||
notice(s_HostServ,u->nick,"This command is an example provided");
|
||||
notice(s_HostServ,u->nick,"by the Anope development team.");
|
||||
return MOD_CONT; /* allow any other module's with help for /hs moo to run */
|
||||
}
|
||||
|
||||
int myHostServMooRootHelp(User *u) { /* this will only be sent to ROOTS ONLY who /msg hostserv moo */
|
||||
myHostServMooAdminHelp(u); /* this line lets us show roots the ADMIN help as well as the root help */
|
||||
notice(s_HostServ,u->nick,"Only roots will see this part of the help");
|
||||
return MOD_CONT;
|
||||
}
|
||||
|
||||
int myHostServMooAdminHelp(User *u) { /* this will only be sent to ADMINS ONLY who /msg hostserv moo */
|
||||
myHostServMooOperHelp(u); /* this line lets us show admins the OPER help as well as the admin help */
|
||||
notice(s_HostServ,u->nick,"Only admins will see this part of the help");
|
||||
notice(s_HostServ,u->nick,"why not visit us on www.anope.org ?");
|
||||
return MOD_CONT;
|
||||
}
|
||||
|
||||
int myHostServMooOperHelp(User *u) { /* this will only be sent to OPERS ONLY who /msg hostserv moo */
|
||||
notice(s_HostServ,u->nick,"Only opers will see this part of the help");
|
||||
notice(s_HostServ,u->nick,"for more help/support with modules");
|
||||
notice(s_HostServ,u->nick,"visit us on irc.anope.org #anope! :)");
|
||||
return MOD_CONT;
|
||||
}
|
||||
|
||||
int myHostServMooRegHelp(User *u) { /* this will only be sent to REGULAR USERS ONLY who /msg hostserv moo */
|
||||
notice(s_HostServ,u->nick,"Only non-opers will see this part of the help");
|
||||
notice(s_HostServ,u->nick,"as we've left it hidden from opers");
|
||||
return MOD_CONT;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,128 @@
|
||||
/**
|
||||
* Simple module to load up a client called CatServ and process commands for it
|
||||
* This module is an example, and has no useful purpose!
|
||||
*
|
||||
* Please visit http://modules.anope.org for useful modules!
|
||||
*
|
||||
**/
|
||||
|
||||
#include "module.h"
|
||||
|
||||
#define AUTHOR "Anope"
|
||||
#define VERSION "1.1"
|
||||
|
||||
int my_privmsg(char *source, int ac, char **av);
|
||||
CommandHash *Catserv_cmdTable[MAX_CMD_HASH];
|
||||
|
||||
void addClient(char *nick, char *realname);
|
||||
void addMessageList(void);
|
||||
void delClient(void);
|
||||
char *s_CatServ = "CatServ";
|
||||
void catserv(User * u, char *buf);
|
||||
|
||||
int do_meow(User * u);
|
||||
int do_purr(User * u);
|
||||
|
||||
int AnopeInit(int argc, char **argv)
|
||||
{
|
||||
Message *msg = NULL;
|
||||
int status;
|
||||
msg = createMessage("PRIVMSG", my_privmsg);
|
||||
status = moduleAddMessage(msg, MOD_HEAD);
|
||||
if (status == MOD_ERR_OK) {
|
||||
addClient(s_CatServ, "meow!");
|
||||
addMessageList();
|
||||
}
|
||||
moduleAddAuthor(AUTHOR);
|
||||
moduleAddVersion(VERSION);
|
||||
alog("ircd_catserv.so: loaded, message status [%d]", status);
|
||||
return MOD_CONT;
|
||||
}
|
||||
|
||||
void AnopeFini(void)
|
||||
{
|
||||
delClient();
|
||||
}
|
||||
|
||||
int my_privmsg(char *source, int ac, char **av)
|
||||
{
|
||||
User *u;
|
||||
char *s;
|
||||
|
||||
/* First, some basic checks */
|
||||
if (ac != 2)
|
||||
return MOD_CONT; /* bleh */
|
||||
if (!(u = finduser(source))) {
|
||||
return MOD_CONT;
|
||||
} /* non-user source */
|
||||
if (*av[0] == '#') {
|
||||
return MOD_CONT;
|
||||
}
|
||||
/* Channel message */
|
||||
/* we should prolly honour the ignore list here, but i cba for this... */
|
||||
s = strchr(av[0], '@');
|
||||
if (s) {
|
||||
*s++ = 0;
|
||||
if (stricmp(s, ServerName) != 0)
|
||||
return MOD_CONT;
|
||||
}
|
||||
if ((stricmp(av[0], s_CatServ)) == 0) { /* its for US! */
|
||||
catserv(u, av[1]);
|
||||
return MOD_STOP;
|
||||
} else { /* ok it isnt us, let the old code have it */
|
||||
return MOD_CONT;
|
||||
}
|
||||
}
|
||||
|
||||
void addClient(char *nick, char *realname)
|
||||
{
|
||||
NEWNICK(nick, "catserv", "meow.meow.land", realname, "+", 1);
|
||||
}
|
||||
|
||||
void delClient(void)
|
||||
{
|
||||
send_cmd(s_CatServ, "QUIT :Module Unloaded!");
|
||||
}
|
||||
|
||||
void addMessageList(void)
|
||||
{
|
||||
Command *c;
|
||||
c = createCommand("meow", do_meow, NULL, -1, -1, -1, -1, -1);
|
||||
addCommand(Catserv_cmdTable, c, MOD_UNIQUE);
|
||||
c = createCommand("purr", do_purr, NULL, -1, -1, -1, -1, -1);
|
||||
addCommand(Catserv_cmdTable, c, MOD_UNIQUE);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Main CatServ routine. */
|
||||
void catserv(User * u, char *buf)
|
||||
{
|
||||
char *cmd, *s;
|
||||
|
||||
cmd = strtok(buf, " ");
|
||||
|
||||
if (!cmd) {
|
||||
return;
|
||||
} else if (stricmp(cmd, "\1PING") == 0) {
|
||||
if (!(s = strtok(NULL, "")))
|
||||
s = "\1";
|
||||
notice(s_CatServ, u->nick, "\1PING %s", s);
|
||||
} else if (skeleton) {
|
||||
notice_lang(s_CatServ, u, SERVICE_OFFLINE, s_CatServ);
|
||||
} else {
|
||||
mod_run_cmd(s_CatServ, u, Catserv_cmdTable, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
int do_meow(User * u)
|
||||
{
|
||||
notice(s_CatServ, u->nick, "MEOW!");
|
||||
return MOD_STOP;
|
||||
}
|
||||
|
||||
int do_purr(User * u)
|
||||
{
|
||||
notice(s_CatServ, u->nick, "PURR!");
|
||||
return MOD_STOP;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#include "../services.h"
|
||||
#include "../commands.h"
|
||||
#include "../language.h"
|
||||
#include "../modules.h"
|
||||
|
||||
#define MOD_UNIQUE 0
|
||||
#define MOD_HEAD 1
|
||||
#define MOD_TAIL 2
|
||||
|
||||
@@ -0,0 +1,869 @@
|
||||
/* MySQL functions.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: mysql.c,v 1.33 2004/03/14 13:02:53 rob Exp $
|
||||
*
|
||||
*/
|
||||
#include "services.h"
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Database Global Variables */
|
||||
MYSQL *mysql; /* MySQL Handler */
|
||||
MYSQL_RES *mysql_res; /* MySQL Result */
|
||||
MYSQL_FIELD *mysql_fields; /* MySQL Fields */
|
||||
MYSQL_ROW mysql_row; /* MySQL Row */
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void db_mysql_error(int severity, char *msg)
|
||||
{
|
||||
static char buf[512];
|
||||
|
||||
if (mysql_error(mysql)) {
|
||||
snprintf(buf, sizeof(buf), "MySQL %s %s: %s", msg,
|
||||
severity == MYSQL_WARNING ? "warning" : "error",
|
||||
mysql_error(mysql));
|
||||
} else {
|
||||
snprintf(buf, sizeof(buf), "MySQL %s %s", msg,
|
||||
severity == MYSQL_WARNING ? "warning" : "error");
|
||||
}
|
||||
|
||||
log_perror(buf);
|
||||
|
||||
if (severity == MYSQL_ERROR) {
|
||||
log_perror("MySQL FATAL error... aborting.");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int db_mysql_init()
|
||||
{
|
||||
|
||||
/* If the host is not defined, assume we don't want MySQL */
|
||||
if (!MysqlHost) {
|
||||
do_mysql = 0;
|
||||
alog("MySQL has been disabled.");
|
||||
} else {
|
||||
do_mysql = 1;
|
||||
alog("MySQL has been enabled.");
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int db_mysql_open()
|
||||
{
|
||||
/* If MySQL is disabled, return 0 */
|
||||
if (!do_mysql)
|
||||
return 0;
|
||||
|
||||
mysql = mysql_init(NULL);
|
||||
if (mysql == NULL)
|
||||
db_mysql_error(MYSQL_WARNING, "Unable to create mysql object");
|
||||
|
||||
if (!MysqlPort)
|
||||
MysqlPort = 3306;
|
||||
|
||||
if (MysqlSock) {
|
||||
if ((!mysql_real_connect
|
||||
(mysql, MysqlHost, MysqlUser, MysqlPass, MysqlName, MysqlPort,
|
||||
MysqlSock, 0))) {
|
||||
log_perror("Cant connect to MySQL: %s\n", mysql_error(mysql));
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if ((!mysql_real_connect
|
||||
(mysql, MysqlHost, MysqlUser, MysqlPass, MysqlName, MysqlPort,
|
||||
NULL, 0))) {
|
||||
log_perror("Cant connect to MySQL: %s\n", mysql_error(mysql));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int db_mysql_query(char *sql)
|
||||
{
|
||||
|
||||
int result, lcv;
|
||||
|
||||
result = mysql_query(mysql, sql);
|
||||
|
||||
if (result) {
|
||||
switch (mysql_errno(mysql)) {
|
||||
case CR_SERVER_GONE_ERROR:
|
||||
case CR_SERVER_LOST:
|
||||
|
||||
for (lcv = 0; lcv < MysqlRetries; lcv++) {
|
||||
if (db_mysql_open()) {
|
||||
result = mysql_query(mysql, sql);
|
||||
return (result);
|
||||
}
|
||||
sleep(MysqlRetryGap);
|
||||
}
|
||||
|
||||
/* If we get here, we could not connect. */
|
||||
log_perror("Unable to reconnect to database: %s\n",
|
||||
mysql_error(mysql));
|
||||
db_mysql_error(MYSQL_ERROR, "connect");
|
||||
|
||||
/* Never reached. */
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Unhandled error. */
|
||||
return (result);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
char *db_mysql_quote(char *sql)
|
||||
{
|
||||
int slen;
|
||||
char *quoted;
|
||||
|
||||
if (!sql) {
|
||||
return sstrdup("");
|
||||
}
|
||||
|
||||
slen = strlen(sql);
|
||||
quoted = malloc((1 + (slen * 2)) * sizeof(char));
|
||||
|
||||
mysql_real_escape_string(mysql, quoted, sql, slen);
|
||||
return quoted;
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* I don't like using res here, maybe we can pass it as a param? */
|
||||
int db_mysql_close()
|
||||
{
|
||||
if (mysql_res)
|
||||
mysql_free_result(mysql_res);
|
||||
mysql_close(mysql);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* NickServ Specific Secion
|
||||
*/
|
||||
|
||||
/*************************************************************************/
|
||||
void db_mysql_save_ns_req(NickRequest * nr)
|
||||
{
|
||||
char *qnick, *qpasscode, *qpassword, *qemail;
|
||||
char sqlcmd[MAX_SQL_BUF];
|
||||
|
||||
qnick = db_mysql_quote(nr->nick);
|
||||
qpasscode = db_mysql_quote(nr->passcode);
|
||||
qpassword = db_mysql_quote(nr->password);
|
||||
qemail = db_mysql_quote(nr->email);
|
||||
|
||||
snprintf(sqlcmd, MAX_SQL_BUF,
|
||||
"REPLACE anope_ns_request (nick,passcode,password,email,requested,active)"
|
||||
" VALUES ('%s','%s','%s','%s','%d','1')",
|
||||
qnick, qpasscode, qpassword, qemail, (int) nr->requested);
|
||||
if (db_mysql_query(sqlcmd)) {
|
||||
log_perror("Can't create sql query: %s", sqlcmd);
|
||||
db_mysql_error(MYSQL_WARNING, "query");
|
||||
}
|
||||
free(qnick);
|
||||
free(qpasscode);
|
||||
free(qpassword);
|
||||
free(qemail);
|
||||
}
|
||||
|
||||
char *db_mysql_secure(char *pass)
|
||||
{
|
||||
|
||||
char epass[BUFSIZE];
|
||||
|
||||
if (!pass) {
|
||||
snprintf(epass, sizeof(epass), "''");
|
||||
} else if ((!MysqlSecure) || (strcmp(MysqlSecure, "") == 0)) {
|
||||
snprintf(epass, sizeof(epass), "'%s'", pass);
|
||||
} else if (strcmp(MysqlSecure, "des") == 0) {
|
||||
snprintf(epass, sizeof(epass), "ENCRYPT('%s')", pass);
|
||||
} else if (strcmp(MysqlSecure, "md5") == 0) {
|
||||
snprintf(epass, sizeof(epass), "MD5('%s')", pass);
|
||||
} else if (strcmp(MysqlSecure, "sha") == 0) {
|
||||
snprintf(epass, sizeof(epass), "SHA('%s')", pass);
|
||||
} else {
|
||||
snprintf(epass, sizeof(epass), "ENCODE('%s','%s')", pass,
|
||||
MysqlSecure);
|
||||
}
|
||||
|
||||
return sstrdup(epass);
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
void db_mysql_save_ns_core(NickCore * nc)
|
||||
{
|
||||
char sqlcmd[MAX_SQL_BUF];
|
||||
int j;
|
||||
char **access;
|
||||
Memo *memos;
|
||||
char *cnick, *cpass, *epass, *cemail, *cgreet, *curl, *caccess,
|
||||
*msender, *mtext;
|
||||
|
||||
cnick = db_mysql_quote(nc->display);
|
||||
cpass = db_mysql_quote(nc->pass);
|
||||
cemail = db_mysql_quote(nc->email);
|
||||
cgreet = db_mysql_quote(nc->greet);
|
||||
curl = db_mysql_quote(nc->url);
|
||||
|
||||
epass = db_mysql_secure(cpass);
|
||||
free(cpass);
|
||||
|
||||
/* Let's take care of the core itself */
|
||||
/* Update the existing records */
|
||||
snprintf(sqlcmd, MAX_SQL_BUF,
|
||||
"UPDATE anope_ns_core SET pass=%s,email='%s',greet='%s',icq='%d',url='%s',flags='%d',"
|
||||
"language='%d',accesscount='%d',memocount='%d',memomax='%d',channelcount='%d'"
|
||||
",channelmax='%d',active='1' WHERE display='%s'",
|
||||
epass, cemail, cgreet, nc->icq, curl, nc->flags,
|
||||
nc->language, nc->accesscount, nc->memos.memocount,
|
||||
nc->memos.memomax, nc->channelcount, nc->channelmax, cnick);
|
||||
if (db_mysql_query(sqlcmd)) {
|
||||
log_perror("Can't create sql query: %s", sqlcmd);
|
||||
db_mysql_error(MYSQL_WARNING, "query");
|
||||
}
|
||||
|
||||
/* need to write a wrapper for mysql_affected_rows */
|
||||
/* Our previous UPDATE affected no rows, therefore this is a new record */
|
||||
if ((int) mysql_affected_rows(mysql) <= 0) {
|
||||
|
||||
/* Let's take care of the core itself */
|
||||
snprintf(sqlcmd, MAX_SQL_BUF,
|
||||
"INSERT DELAYED INTO anope_ns_core (display,pass,email,greet,icq,url,flags,"
|
||||
"language,accesscount,memocount,memomax,channelcount,channelmax,active)"
|
||||
" VALUES ('%s',%s,'%s','%s','%d','%s','%d','%d','%d','%d','%d','%d','%d','1')",
|
||||
cnick, epass, cemail, cgreet, nc->icq, curl, nc->flags,
|
||||
nc->language, nc->accesscount, nc->memos.memocount,
|
||||
nc->memos.memomax, nc->channelcount, nc->channelmax);
|
||||
if (db_mysql_query(sqlcmd)) {
|
||||
log_perror("Can't create sql query: %s", sqlcmd);
|
||||
db_mysql_error(MYSQL_WARNING, "query");
|
||||
}
|
||||
}
|
||||
|
||||
/* Now let's do the access */
|
||||
for (j = 0, access = nc->access; j < nc->accesscount; j++, access++) {
|
||||
caccess = db_mysql_quote(*access);
|
||||
snprintf(sqlcmd, MAX_SQL_BUF,
|
||||
"INSERT DELAYED INTO anope_ns_access (display,access) VALUES ('%s','%s')",
|
||||
cnick, caccess);
|
||||
if (db_mysql_query(sqlcmd)) {
|
||||
log_perror("Can't create sql query: %s", sqlcmd);
|
||||
db_mysql_error(MYSQL_WARNING, "query");
|
||||
}
|
||||
free(caccess);
|
||||
}
|
||||
|
||||
/* And... memos */
|
||||
memos = nc->memos.memos;
|
||||
for (j = 0; j < nc->memos.memocount; j++, memos++) {
|
||||
msender = db_mysql_quote(memos->sender);
|
||||
mtext = db_mysql_quote(memos->text);
|
||||
snprintf(sqlcmd, MAX_SQL_BUF,
|
||||
"INSERT DELAYED INTO anope_ms_info (receiver,number,flags,time,sender,text,serv)"
|
||||
" VALUES ('%s','%d','%d','%d','%s','%s','NICK')",
|
||||
cnick, memos->number, memos->flags,
|
||||
(int) memos->time, msender, mtext);
|
||||
if (db_mysql_query(sqlcmd)) {
|
||||
log_perror("Can't create sql query: %s", sqlcmd);
|
||||
db_mysql_error(MYSQL_WARNING, "query");
|
||||
}
|
||||
free(msender);
|
||||
free(mtext);
|
||||
}
|
||||
|
||||
free(cnick);
|
||||
free(epass);
|
||||
free(cemail);
|
||||
free(cgreet);
|
||||
free(curl);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
void db_mysql_save_ns_alias(NickAlias * na)
|
||||
{
|
||||
char sqlcmd[MAX_SQL_BUF];
|
||||
char *nnick, *nlmask, *nlrname, *nlquit, *nncnick;
|
||||
nnick = db_mysql_quote(na->nick);
|
||||
nlmask = db_mysql_quote(na->last_usermask);
|
||||
nlrname = db_mysql_quote(na->last_realname);
|
||||
nlquit = db_mysql_quote(na->last_quit);
|
||||
nncnick = db_mysql_quote(na->nc->display);
|
||||
snprintf(sqlcmd, MAX_SQL_BUF,
|
||||
"UPDATE anope_ns_alias SET last_usermask='%s',last_realname='%s',last_quit='%s',time_registered='%d',last_seen='%d',status='%d',display='%s',active='1' WHERE nick='%s'",
|
||||
nlmask, nlrname, nlquit, (int) na->time_registered,
|
||||
(int) na->last_seen, (int) na->status, nncnick, nnick);
|
||||
if (db_mysql_query(sqlcmd)) {
|
||||
log_perror("Can't create sql query: %s", sqlcmd);
|
||||
db_mysql_error(MYSQL_WARNING, "query");
|
||||
}
|
||||
/* Our previous UPDATE affected no rows, therefore this is a new record */
|
||||
if ((int) mysql_affected_rows(mysql) <= 0) {
|
||||
snprintf(sqlcmd, MAX_SQL_BUF,
|
||||
"INSERT INTO anope_ns_alias (nick,last_usermask,last_realname,last_quit,time_registered,last_seen,status,display,active) VALUES ('%s','%s','%s','%s','%d','%d','%d','%s','1')",
|
||||
nnick, nlmask, nlrname, nlquit, (int) na->time_registered,
|
||||
(int) na->last_seen, (int) na->status, nncnick);
|
||||
if (db_mysql_query(sqlcmd)) {
|
||||
log_perror("Can't create sql query: %s", sqlcmd);
|
||||
db_mysql_error(MYSQL_WARNING, "query");
|
||||
}
|
||||
}
|
||||
|
||||
free(nnick);
|
||||
free(nlmask);
|
||||
free(nlrname);
|
||||
free(nlquit);
|
||||
free(nncnick);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* ChanServ Specific Secion
|
||||
*/
|
||||
|
||||
/*************************************************************************/
|
||||
void db_mysql_save_cs_info(ChannelInfo * ci)
|
||||
{
|
||||
char sqlcmd[MAX_SQL_BUF];
|
||||
int j, position;
|
||||
Memo *memos;
|
||||
char *ciname, *cifoundernick, *cisuccessornick, *cifounderpass,
|
||||
*cidesc, *ciurl, *ciemail, *cilasttopic, *cilasttopicsetter,
|
||||
*ciforbidby, *ciforbidreason, *cimlock_key, *cimlock_flood,
|
||||
*cimlock_redirect, *cientrymsg, *cibotnick, *msender, *mtext,
|
||||
*ciaccessdisp, *ciakickdisp, *ciakickreason, *ciakickcreator,
|
||||
*cbadwords, *efounderpass;
|
||||
|
||||
ciname = db_mysql_quote(ci->name);
|
||||
cifoundernick =
|
||||
ci->founder ? db_mysql_quote(ci->founder->display) : "";
|
||||
cisuccessornick =
|
||||
ci->successor ? db_mysql_quote(ci->successor->display) : "";
|
||||
cifounderpass = db_mysql_quote(ci->founderpass);
|
||||
cidesc = db_mysql_quote(ci->desc);
|
||||
ciurl = db_mysql_quote(ci->url);
|
||||
ciemail = db_mysql_quote(ci->email);
|
||||
cilasttopic = db_mysql_quote(ci->last_topic);
|
||||
cilasttopicsetter = db_mysql_quote(ci->last_topic_setter);
|
||||
ciforbidby = db_mysql_quote(ci->forbidby);
|
||||
ciforbidreason = db_mysql_quote(ci->forbidreason);
|
||||
cimlock_key = db_mysql_quote(ci->mlock_key);
|
||||
#ifdef HAS_FMODE
|
||||
cimlock_flood = db_mysql_quote(ci->mlock_flood);
|
||||
#else
|
||||
cimlock_flood = NULL;
|
||||
#endif
|
||||
#ifdef HAS_LMODE
|
||||
cimlock_redirect = db_mysql_quote(ci->mlock_redirect);
|
||||
#else
|
||||
cimlock_redirect = NULL;
|
||||
#endif
|
||||
cientrymsg = db_mysql_quote(ci->entry_message);
|
||||
cibotnick = ci->bi ? db_mysql_quote(ci->bi->nick) : "";
|
||||
|
||||
efounderpass = db_mysql_secure(cifounderpass);
|
||||
free(cifounderpass);
|
||||
|
||||
/* Let's take care of the core itself */
|
||||
snprintf(sqlcmd, MAX_SQL_BUF,
|
||||
"UPDATE anope_cs_info SET founder='%s',successor='%s',founderpass=%s,"
|
||||
"descr='%s',url='%s',email='%s',time_registered='%d',last_used='%d',"
|
||||
"last_topic='%s',last_topic_setter='%s',last_topic_time='%d',flags='%d',"
|
||||
"forbidby='%s',forbidreason='%s',bantype='%d',accesscount='%d',"
|
||||
"akickcount='%d',mlock_on='%d',mlock_off='%d',mlock_limit='%d',"
|
||||
"mlock_key='%s',mlock_flood='%s',mlock_redirect='%s',entry_message='%s',"
|
||||
"memomax='%d',botnick='%s',botflags='%d',ttb='%d',bwcount='%d',"
|
||||
"capsmin='%d',capspercent='%d',floodlines='%d',floodsecs='%d',"
|
||||
"repeattimes='%d',active='1' WHERE name='%s'",
|
||||
cifoundernick,
|
||||
cisuccessornick,
|
||||
efounderpass, cidesc, ciurl, ciemail,
|
||||
(int) ci->time_registered, (int) ci->last_used,
|
||||
cilasttopic, cilasttopicsetter,
|
||||
(int) ci->last_topic_time, (int) ci->flags,
|
||||
ciforbidby, ciforbidreason, (int) ci->bantype,
|
||||
(int) ci->accesscount, (int) ci->akickcount,
|
||||
(int) ci->mlock_on, (int) ci->mlock_off,
|
||||
(int) ci->mlock_limit, cimlock_key,
|
||||
#ifdef HAS_FMODE
|
||||
cimlock_flood,
|
||||
#else
|
||||
"",
|
||||
#endif
|
||||
#ifdef HAS_LMODE
|
||||
cimlock_redirect,
|
||||
#else
|
||||
"",
|
||||
#endif
|
||||
cientrymsg,
|
||||
(int) ci->memos.memomax,
|
||||
cibotnick,
|
||||
(int) ci->botflags,
|
||||
(int) ci->ttb,
|
||||
(int) ci->bwcount,
|
||||
(int) ci->capsmin,
|
||||
(int) ci->capspercent,
|
||||
(int) ci->floodlines,
|
||||
(int) ci->floodsecs, (int) ci->repeattimes, ciname);
|
||||
if (db_mysql_query(sqlcmd)) {
|
||||
log_perror("Can't create sql query: %s", sqlcmd);
|
||||
db_mysql_error(MYSQL_WARNING, "query");
|
||||
}
|
||||
|
||||
/* Our previous UPDATE affected no rows, therefore this is a new record */
|
||||
if ((int) mysql_affected_rows(mysql) <= 0) {
|
||||
snprintf(sqlcmd, MAX_SQL_BUF,
|
||||
"INSERT DELAYED INTO anope_cs_info (name,founder,successor,founderpass,"
|
||||
"descr,url,email,time_registered,last_used,last_topic,last_topic_setter"
|
||||
",last_topic_time,flags,forbidby,forbidreason,bantype,accesscount,akickcount"
|
||||
",mlock_on,mlock_off,mlock_limit,mlock_key,mlock_flood,mlock_redirect,"
|
||||
"entry_message,botnick,botflags,bwcount,capsmin,capspercent,floodlines,"
|
||||
"floodsecs,repeattimes,active) VALUES ('%s','%s','%s',%s,'%s','%s','%s'"
|
||||
",'%d','%d','%s','%s','%d','%d','%s','%s','%d','%d','%d','%d','%d','%d',"
|
||||
"'%s','%s','%s','%s','%s','%d','%d','%d','%d','%d','%d','%d','1')",
|
||||
ciname,
|
||||
cifoundernick,
|
||||
cisuccessornick,
|
||||
efounderpass, cidesc, ciurl, ciemail,
|
||||
(int) ci->time_registered, (int) ci->last_used,
|
||||
cilasttopic, cilasttopicsetter,
|
||||
(int) ci->last_topic_time, (int) ci->flags,
|
||||
ciforbidby, ciforbidreason, (int) ci->bantype,
|
||||
(int) ci->accesscount, (int) ci->akickcount,
|
||||
(int) ci->mlock_on, (int) ci->mlock_off,
|
||||
(int) ci->mlock_limit, cimlock_key,
|
||||
#ifdef HAS_FMODE
|
||||
cimlock_flood,
|
||||
#else
|
||||
"",
|
||||
#endif
|
||||
#ifdef HAS_LMODE
|
||||
cimlock_redirect,
|
||||
#else
|
||||
"",
|
||||
#endif
|
||||
cientrymsg,
|
||||
cibotnick,
|
||||
(int) ci->botflags,
|
||||
(int) ci->bwcount,
|
||||
(int) ci->capsmin,
|
||||
(int) ci->capspercent,
|
||||
(int) ci->floodlines,
|
||||
(int) ci->floodsecs, (int) ci->repeattimes);
|
||||
if (db_mysql_query(sqlcmd)) {
|
||||
log_perror("Can't create sql query: %s", sqlcmd);
|
||||
db_mysql_error(MYSQL_WARNING, "query");
|
||||
}
|
||||
}
|
||||
|
||||
/* Memos */
|
||||
memos = ci->memos.memos;
|
||||
for (j = 0; j < ci->memos.memocount; j++, memos++) {
|
||||
msender = db_mysql_quote(memos->sender);
|
||||
mtext = db_mysql_quote(memos->text);
|
||||
snprintf(sqlcmd, MAX_SQL_BUF,
|
||||
"INSERT DELAYED INTO anope_ms_info (receiver,number,flags,time,sender,text,serv)"
|
||||
" VALUES ('%s','%d','%d','%d','%s','%s','CHAN')",
|
||||
ciname, memos->number, memos->flags,
|
||||
(int) memos->time, msender, mtext);
|
||||
if (db_mysql_query(sqlcmd)) {
|
||||
log_perror("Can't create sql query: %s", sqlcmd);
|
||||
db_mysql_error(MYSQL_WARNING, "query");
|
||||
}
|
||||
free(msender);
|
||||
free(mtext);
|
||||
}
|
||||
|
||||
/* Access */
|
||||
for (j = 0; j < ci->accesscount; j++) {
|
||||
if (ci->access[j].in_use) {
|
||||
ciaccessdisp = db_mysql_quote(ci->access[j].nc->display);
|
||||
snprintf(sqlcmd, MAX_SQL_BUF,
|
||||
"INSERT DELAYED INTO anope_cs_access (in_use,level,display,channel,last_seen)"
|
||||
" VALUES ('%d','%d','%s','%s','%d')",
|
||||
(int) ci->access[j].in_use, (int) ci->access[j].level,
|
||||
ciaccessdisp, ciname, (int) ci->access[j].last_seen);
|
||||
if (db_mysql_query(sqlcmd)) {
|
||||
log_perror("Can't create sql query: %s", sqlcmd);
|
||||
db_mysql_error(MYSQL_WARNING, "query");
|
||||
}
|
||||
free(ciaccessdisp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Levels */
|
||||
position = 0;
|
||||
for (j = 0; j < CA_SIZE; j++) {
|
||||
snprintf(sqlcmd, MAX_SQL_BUF,
|
||||
"INSERT DELAYED INTO anope_cs_levels (channel, position, level) VALUES ('%s','%d','%d')",
|
||||
ciname, position++, (int) ci->levels[j]);
|
||||
if (db_mysql_query(sqlcmd)) {
|
||||
log_perror("Can't create sql query: %s", sqlcmd);
|
||||
db_mysql_error(MYSQL_WARNING, "query");
|
||||
}
|
||||
}
|
||||
|
||||
/* Akicks */
|
||||
for (j = 0; j < ci->akickcount; j++) {
|
||||
ciakickdisp =
|
||||
ci->akick[j].flags & AK_USED ? ci->akick[j].
|
||||
flags & AK_ISNICK ? db_mysql_quote(ci->akick[j].u.nc->
|
||||
display) :
|
||||
db_mysql_quote(ci->akick[j].u.mask) : "";
|
||||
ciakickreason =
|
||||
ci->akick[j].flags & AK_USED ? db_mysql_quote(ci->akick[j].
|
||||
reason) : "";
|
||||
ciakickcreator =
|
||||
ci->akick[j].flags & AK_USED ? db_mysql_quote(ci->akick[j].
|
||||
creator) : "";
|
||||
snprintf(sqlcmd, MAX_SQL_BUF,
|
||||
"INSERT DELAYED INTO anope_cs_akicks (channel, flags, dmask, reason, creator,"
|
||||
" addtime) VALUES ('%s','%d','%s','%s','%s','%d')",
|
||||
ciname, (int) ci->akick[j].flags, ciakickdisp,
|
||||
ciakickreason, ciakickcreator,
|
||||
ci->akick[j].flags & AK_USED ? (int) ci->akick[j].
|
||||
addtime : 0);
|
||||
if (db_mysql_query(sqlcmd)) {
|
||||
log_perror("Can't create sql query: %s", sqlcmd);
|
||||
db_mysql_error(MYSQL_WARNING, "query");
|
||||
}
|
||||
if (ci->akick[j].flags & AK_USED) {
|
||||
free(ciakickdisp);
|
||||
free(ciakickreason);
|
||||
free(ciakickcreator);
|
||||
}
|
||||
}
|
||||
|
||||
/* Bad Words */
|
||||
for (j = 0; j < ci->bwcount; j++) {
|
||||
if (ci->badwords[j].in_use) {
|
||||
cbadwords = db_mysql_quote(ci->badwords[j].word);
|
||||
snprintf(sqlcmd, MAX_SQL_BUF,
|
||||
"INSERT DELAYED INTO anope_cs_badwords (channel, word, type)"
|
||||
" VALUES ('%s','%s','%d')", ciname, cbadwords,
|
||||
(int) ci->badwords[j].type);
|
||||
free(cbadwords);
|
||||
if (db_mysql_query(sqlcmd)) {
|
||||
log_perror("Can't create sql query: %s", sqlcmd);
|
||||
db_mysql_error(MYSQL_WARNING, "query");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(ciname);
|
||||
if (!(ci->flags & CI_VERBOTEN)) {
|
||||
free(cifoundernick);
|
||||
if (strlen(cisuccessornick) > 0)
|
||||
free(cisuccessornick);
|
||||
free(efounderpass);
|
||||
free(cidesc);
|
||||
free(ciurl);
|
||||
free(ciemail);
|
||||
free(cilasttopic);
|
||||
free(cilasttopicsetter);
|
||||
free(cimlock_key);
|
||||
free(cimlock_flood);
|
||||
free(cimlock_redirect);
|
||||
free(cientrymsg);
|
||||
if (ci->bi)
|
||||
free(cibotnick);
|
||||
} else {
|
||||
free(ciforbidby);
|
||||
free(ciforbidreason);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
/*
|
||||
* OperServ Specific Section
|
||||
*/
|
||||
|
||||
/*************************************************************************/
|
||||
void db_mysql_save_os_db(unsigned int maxucnt, unsigned int maxutime,
|
||||
SList * ak, SList * sgl, SList * sql, SList * szl,
|
||||
HostCache * hc)
|
||||
{
|
||||
char sqlcmd[MAX_SQL_BUF];
|
||||
Akill *t_ak;
|
||||
SXLine *t_sl;
|
||||
HostCache *t_hc;
|
||||
char *takuser, *takhost, *takby, *takreason, *tslmask, *tslby,
|
||||
*tslreason, *thchost;
|
||||
|
||||
int i, j;
|
||||
|
||||
rdb_clear_table("anope_os_core");
|
||||
|
||||
snprintf(sqlcmd, MAX_SQL_BUF,
|
||||
"INSERT DELAYED INTO anope_os_core (maxusercnt,maxusertime,akills_count,"
|
||||
"sglines_count,sqlines_count,szlines_count) VALUES "
|
||||
"('%d','%d','%d','%d','%d','%d')", maxucnt, maxutime,
|
||||
ak->count, sgl->count, sql->count, szl->count);
|
||||
if (db_mysql_query(sqlcmd)) {
|
||||
log_perror("Can't create sql query: %s", sqlcmd);
|
||||
db_mysql_error(MYSQL_WARNING, "query");
|
||||
}
|
||||
|
||||
/* now the akills saving */
|
||||
rdb_clear_table("anope_os_akills");
|
||||
|
||||
j = ak->count;
|
||||
for (i = 0; i < j; i++) {
|
||||
t_ak = ak->list[i];
|
||||
takuser = db_mysql_quote(t_ak->user);
|
||||
takhost = db_mysql_quote(t_ak->host);
|
||||
takby = db_mysql_quote(t_ak->by);
|
||||
takreason = db_mysql_quote(t_ak->reason);
|
||||
snprintf(sqlcmd, MAX_SQL_BUF,
|
||||
"INSERT DELAYED INTO anope_os_akills (user,host,xby,reason,seton,expire) VALUES ('%s','%s','%s','%s','%d','%d')",
|
||||
takuser,
|
||||
takhost,
|
||||
takby, takreason, (int) t_ak->seton, (int) t_ak->expires);
|
||||
if (db_mysql_query(sqlcmd)) {
|
||||
log_perror("Can't create sql query: %s", sqlcmd);
|
||||
db_mysql_error(MYSQL_WARNING, "query");
|
||||
}
|
||||
free(takuser);
|
||||
free(takhost);
|
||||
free(takby);
|
||||
free(takreason);
|
||||
}
|
||||
|
||||
/* sglines save */
|
||||
rdb_clear_table("anope_os_sglines");
|
||||
|
||||
j = sgl->count;
|
||||
for (i = 0; i < j; i++) {
|
||||
t_sl = sgl->list[i];
|
||||
tslmask = db_mysql_quote(t_sl->mask);
|
||||
tslby = db_mysql_quote(t_sl->by);
|
||||
tslreason = db_mysql_quote(t_sl->reason);
|
||||
snprintf(sqlcmd, MAX_SQL_BUF,
|
||||
"INSERT DELAYED INTO anope_os_sglines (mask,xby,reason,seton,expire) VALUES"
|
||||
" ('%s','%s','%s','%d','%d')",
|
||||
tslmask,
|
||||
tslby, tslreason, (int) t_sl->seton, (int) t_sl->expires);
|
||||
if (db_mysql_query(sqlcmd)) {
|
||||
log_perror("Can't create sql query: %s", sqlcmd);
|
||||
db_mysql_error(MYSQL_WARNING, "query");
|
||||
}
|
||||
free(tslmask);
|
||||
free(tslby);
|
||||
free(tslreason);
|
||||
}
|
||||
|
||||
/* sqlines save */
|
||||
rdb_clear_table("anope_os_sqlines");
|
||||
|
||||
j = sql->count;
|
||||
for (i = 0; i < j; i++) {
|
||||
t_sl = sql->list[i];
|
||||
tslmask = db_mysql_quote(t_sl->mask);
|
||||
tslby = db_mysql_quote(t_sl->by);
|
||||
tslreason = db_mysql_quote(t_sl->reason);
|
||||
snprintf(sqlcmd, MAX_SQL_BUF,
|
||||
"INSERT DELAYED INTO anope_os_sqlines (mask,xby,reason,seton,expire) VALUES ('%s','%s','%s','%d','%d')",
|
||||
tslmask,
|
||||
tslby, tslreason, (int) t_sl->seton, (int) t_sl->expires);
|
||||
if (db_mysql_query(sqlcmd)) {
|
||||
log_perror("Can't create sql query: %s", sqlcmd);
|
||||
db_mysql_error(MYSQL_WARNING, "query");
|
||||
}
|
||||
free(tslmask);
|
||||
free(tslby);
|
||||
free(tslreason);
|
||||
}
|
||||
|
||||
/* szlines save */
|
||||
rdb_clear_table("anope_os_szlines");
|
||||
|
||||
j = szl->count;
|
||||
for (i = 0; i < j; i++) {
|
||||
t_sl = szl->list[i];
|
||||
tslmask = db_mysql_quote(t_sl->mask);
|
||||
tslby = db_mysql_quote(t_sl->by);
|
||||
tslreason = db_mysql_quote(t_sl->reason);
|
||||
snprintf(sqlcmd, MAX_SQL_BUF,
|
||||
"INSERT DELAYED INTO anope_os_szlines (mask,xby,reason,seton,expire) VALUES"
|
||||
" ('%s','%s','%s','%d','%d')",
|
||||
tslmask,
|
||||
tslby, tslreason, (int) t_sl->seton, (int) t_sl->expires);
|
||||
if (db_mysql_query(sqlcmd)) {
|
||||
log_perror("Can't create sql query: %s", sqlcmd);
|
||||
db_mysql_error(MYSQL_WARNING, "query");
|
||||
}
|
||||
free(tslmask);
|
||||
free(tslby);
|
||||
free(tslreason);
|
||||
}
|
||||
|
||||
/* and finally we save hcache */
|
||||
rdb_clear_table("anope_os_hcache");
|
||||
for (i = 0; i < 1024; i++) {
|
||||
for (t_hc = hcache[i]; t_hc; t_hc = t_hc->next) {
|
||||
/* Don't save in-progress scans */
|
||||
if (t_hc->status < HC_NORMAL)
|
||||
continue;
|
||||
thchost = db_mysql_quote(t_hc->host);
|
||||
snprintf(sqlcmd, MAX_SQL_BUF,
|
||||
"INSERT DELAYED INTO anope_os_hcache (mask,status,used) VALUES ('%s','%d','%d')",
|
||||
thchost, (int) t_hc->status, (int) t_hc->used);
|
||||
if (db_mysql_query(sqlcmd)) {
|
||||
log_perror("Can't create sql query: %s", sqlcmd);
|
||||
db_mysql_error(MYSQL_WARNING, "query");
|
||||
}
|
||||
free(thchost);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
void db_mysql_save_news(NewsItem * ni)
|
||||
{
|
||||
char sqlcmd[MAX_SQL_BUF];
|
||||
char *nitext, *niwho;
|
||||
nitext = db_mysql_quote(ni->text);
|
||||
niwho = db_mysql_quote(ni->who);
|
||||
snprintf(sqlcmd, MAX_SQL_BUF,
|
||||
"INSERT DELAYED INTO anope_os_news (type,num,ntext,who,`time`)"
|
||||
" VALUES ('%d','%d','%s','%s','%d')",
|
||||
ni->type, ni->num, nitext, niwho, (int) ni->time);
|
||||
if (db_mysql_query(sqlcmd)) {
|
||||
log_perror("Can't create sql query: %s", sqlcmd);
|
||||
db_mysql_error(MYSQL_WARNING, "query");
|
||||
}
|
||||
free(nitext);
|
||||
free(niwho);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
void db_mysql_save_exceptions(Exception * e)
|
||||
{
|
||||
char sqlcmd[MAX_SQL_BUF];
|
||||
char *emask, *ewho, *ereason;
|
||||
emask = db_mysql_quote(e->mask);
|
||||
ewho = db_mysql_quote(e->who);
|
||||
ereason = db_mysql_quote(e->reason);
|
||||
snprintf(sqlcmd, MAX_SQL_BUF,
|
||||
"INSERT DELAYED INTO anope_os_exceptions (mask,lim,who,reason,`time`,expires)"
|
||||
" VALUES ('%s','%d','%s','%s','%d','%d')",
|
||||
emask, e->limit, ewho,
|
||||
ereason, (int) e->time, (int) e->expires);
|
||||
if (db_mysql_query(sqlcmd)) {
|
||||
log_perror("Can't create sql query: %s", sqlcmd);
|
||||
db_mysql_error(MYSQL_WARNING, "query");
|
||||
}
|
||||
free(emask);
|
||||
free(ewho);
|
||||
free(ereason);
|
||||
return;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
/*
|
||||
* HostServ Specific Section
|
||||
*/
|
||||
|
||||
/*************************************************************************/
|
||||
/* TODO: Add vident to tables! */
|
||||
void db_mysql_save_hs_core(HostCore * hc)
|
||||
{
|
||||
char sqlcmd[MAX_SQL_BUF];
|
||||
char *hcnick, *hcvident, *hcvhost, *hccreator;
|
||||
hcnick = db_mysql_quote(hc->nick);
|
||||
hcvident = db_mysql_quote(hc->vIdent);
|
||||
hcvhost = db_mysql_quote(hc->vHost);
|
||||
hccreator = db_mysql_quote(hc->creator);
|
||||
snprintf(sqlcmd, MAX_SQL_BUF,
|
||||
"INSERT DELAYED INTO anope_hs_core (nick,vident,vhost,creator,`time`)"
|
||||
" VALUES ('%s','%s','%s','%s','%d')",
|
||||
hcnick, hcvident, hcvhost, hccreator, (int) hc->time);
|
||||
if (db_mysql_query(sqlcmd)) {
|
||||
log_perror("Can't create sql query: %s", sqlcmd);
|
||||
db_mysql_error(MYSQL_WARNING, "query");
|
||||
}
|
||||
free(hcnick);
|
||||
free(hcvident);
|
||||
free(hcvhost);
|
||||
free(hccreator);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* HostServ Specific Section
|
||||
*/
|
||||
|
||||
/*************************************************************************/
|
||||
void db_mysql_save_bs_core(BotInfo * bi)
|
||||
{
|
||||
char sqlcmd[MAX_SQL_BUF];
|
||||
char *binick, *biuser, *bihost, *bireal;
|
||||
binick = db_mysql_quote(bi->nick);
|
||||
biuser = db_mysql_quote(bi->user);
|
||||
bihost = db_mysql_quote(bi->host);
|
||||
bireal = db_mysql_quote(bi->real);
|
||||
snprintf(sqlcmd, MAX_SQL_BUF,
|
||||
"INSERT DELAYED INTO anope_bs_core (nick,user,host,rname,flags,created"
|
||||
",chancount) VALUES ('%s','%s','%s','%s','%d','%d','%d')",
|
||||
binick, biuser,
|
||||
bihost, bireal, bi->flags, (int) bi->created, bi->chancount);
|
||||
if (db_mysql_query(sqlcmd)) {
|
||||
log_perror("Can't create sql query: %s", sqlcmd);
|
||||
db_mysql_error(MYSQL_WARNING, "query");
|
||||
}
|
||||
free(binick);
|
||||
free(biuser);
|
||||
free(bihost);
|
||||
free(bireal);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
@@ -0,0 +1,541 @@
|
||||
/* News functions.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: news.c,v 1.11 2004/01/31 17:03:52 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "services.h"
|
||||
#include "pseudo.h"
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static int32 nnews = 0;
|
||||
static int32 news_size = 0;
|
||||
static NewsItem *news = NULL;
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* List of messages for each news type. This simplifies message sending. */
|
||||
|
||||
#define MSG_SYNTAX 0
|
||||
#define MSG_LIST_HEADER 1
|
||||
#define MSG_LIST_ENTRY 2
|
||||
#define MSG_LIST_NONE 3
|
||||
#define MSG_ADD_SYNTAX 4
|
||||
#define MSG_ADD_FULL 5
|
||||
#define MSG_ADDED 6
|
||||
#define MSG_DEL_SYNTAX 7
|
||||
#define MSG_DEL_NOT_FOUND 8
|
||||
#define MSG_DELETED 9
|
||||
#define MSG_DEL_NONE 10
|
||||
#define MSG_DELETED_ALL 11
|
||||
#define MSG_MAX 11
|
||||
|
||||
struct newsmsgs {
|
||||
int16 type;
|
||||
char *name;
|
||||
int msgs[MSG_MAX + 1];
|
||||
};
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
|
||||
struct newsmsgs msgarray[] = {
|
||||
{ NEWS_LOGON, "LOGON",
|
||||
{ NEWS_LOGON_SYNTAX,
|
||||
NEWS_LOGON_LIST_HEADER,
|
||||
NEWS_LOGON_LIST_ENTRY,
|
||||
NEWS_LOGON_LIST_NONE,
|
||||
NEWS_LOGON_ADD_SYNTAX,
|
||||
NEWS_LOGON_ADD_FULL,
|
||||
NEWS_LOGON_ADDED,
|
||||
NEWS_LOGON_DEL_SYNTAX,
|
||||
NEWS_LOGON_DEL_NOT_FOUND,
|
||||
NEWS_LOGON_DELETED,
|
||||
NEWS_LOGON_DEL_NONE,
|
||||
NEWS_LOGON_DELETED_ALL
|
||||
}
|
||||
},
|
||||
{ NEWS_OPER, "OPER",
|
||||
{ NEWS_OPER_SYNTAX,
|
||||
NEWS_OPER_LIST_HEADER,
|
||||
NEWS_OPER_LIST_ENTRY,
|
||||
NEWS_OPER_LIST_NONE,
|
||||
NEWS_OPER_ADD_SYNTAX,
|
||||
NEWS_OPER_ADD_FULL,
|
||||
NEWS_OPER_ADDED,
|
||||
NEWS_OPER_DEL_SYNTAX,
|
||||
NEWS_OPER_DEL_NOT_FOUND,
|
||||
NEWS_OPER_DELETED,
|
||||
NEWS_OPER_DEL_NONE,
|
||||
NEWS_OPER_DELETED_ALL
|
||||
}
|
||||
},
|
||||
{ NEWS_RANDOM, "RANDOM",
|
||||
{ NEWS_RANDOM_SYNTAX,
|
||||
NEWS_RANDOM_LIST_HEADER,
|
||||
NEWS_RANDOM_LIST_ENTRY,
|
||||
NEWS_RANDOM_LIST_NONE,
|
||||
NEWS_RANDOM_ADD_SYNTAX,
|
||||
NEWS_RANDOM_ADD_FULL,
|
||||
NEWS_RANDOM_ADDED,
|
||||
NEWS_RANDOM_DEL_SYNTAX,
|
||||
NEWS_RANDOM_DEL_NOT_FOUND,
|
||||
NEWS_RANDOM_DELETED,
|
||||
NEWS_RANDOM_DEL_NONE,
|
||||
NEWS_RANDOM_DELETED_ALL
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* *INDENT-ON* */
|
||||
|
||||
static int *findmsgs(int16 type, char **typename)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < lenof(msgarray); i++) {
|
||||
if (msgarray[i].type == type) {
|
||||
if (typename)
|
||||
*typename = msgarray[i].name;
|
||||
return msgarray[i].msgs;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Called by the main OperServ routine in response to a NEWS command. */
|
||||
static void do_news(User * u, int16 type);
|
||||
|
||||
/* Lists all a certain type of news. */
|
||||
static void do_news_list(User * u, int16 type, int *msgs);
|
||||
|
||||
/* Add news items. */
|
||||
static void do_news_add(User * u, int16 type, int *msgs,
|
||||
const char *typename);
|
||||
static int add_newsitem(User * u, const char *text, int16 type);
|
||||
|
||||
/* Delete news items. */
|
||||
static void do_news_del(User * u, int16 type, int *msgs,
|
||||
const char *typename);
|
||||
static int del_newsitem(int num, int16 type);
|
||||
|
||||
/*************************************************************************/
|
||||
/****************************** Statistics *******************************/
|
||||
/*************************************************************************/
|
||||
|
||||
void get_news_stats(long *nrec, long *memuse)
|
||||
{
|
||||
long mem;
|
||||
int i;
|
||||
|
||||
mem = sizeof(NewsItem) * news_size;
|
||||
for (i = 0; i < nnews; i++)
|
||||
mem += strlen(news[i].text) + 1;
|
||||
*nrec = nnews;
|
||||
*memuse = mem;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*********************** News item loading/saving ************************/
|
||||
/*************************************************************************/
|
||||
|
||||
#define SAFE(x) do { \
|
||||
if ((x) < 0) { \
|
||||
if (!forceload) \
|
||||
fatal("Read error on %s", NewsDBName); \
|
||||
nnews = i; \
|
||||
break; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
void load_news()
|
||||
{
|
||||
dbFILE *f;
|
||||
int i;
|
||||
int16 n;
|
||||
int32 tmp32;
|
||||
|
||||
if (!(f = open_db(s_OperServ, NewsDBName, "r", NEWS_VERSION)))
|
||||
return;
|
||||
switch (i = get_file_version(f)) {
|
||||
case 9:
|
||||
case 8:
|
||||
case 7:
|
||||
SAFE(read_int16(&n, f));
|
||||
nnews = n;
|
||||
if (nnews < 8)
|
||||
news_size = 16;
|
||||
else if (nnews >= 16384)
|
||||
news_size = 32767;
|
||||
else
|
||||
news_size = 2 * nnews;
|
||||
news = scalloc(sizeof(*news) * news_size, 1);
|
||||
if (!nnews) {
|
||||
close_db(f);
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < nnews; i++) {
|
||||
SAFE(read_int16(&news[i].type, f));
|
||||
SAFE(read_int32(&news[i].num, f));
|
||||
SAFE(read_string(&news[i].text, f));
|
||||
SAFE(read_buffer(news[i].who, f));
|
||||
SAFE(read_int32(&tmp32, f));
|
||||
news[i].time = tmp32;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fatal("Unsupported version (%d) on %s", i, NewsDBName);
|
||||
} /* switch (ver) */
|
||||
|
||||
close_db(f);
|
||||
}
|
||||
|
||||
#undef SAFE
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#define SAFE(x) do { \
|
||||
if ((x) < 0) { \
|
||||
restore_db(f); \
|
||||
log_perror("Write error on %s", NewsDBName); \
|
||||
if (time(NULL) - lastwarn > WarningTimeout) { \
|
||||
wallops(NULL, "Write error on %s: %s", NewsDBName, \
|
||||
strerror(errno)); \
|
||||
lastwarn = time(NULL); \
|
||||
} \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
void save_news()
|
||||
{
|
||||
dbFILE *f;
|
||||
int i;
|
||||
static time_t lastwarn = 0;
|
||||
|
||||
if (!(f = open_db(s_OperServ, NewsDBName, "w", NEWS_VERSION)))
|
||||
return;
|
||||
SAFE(write_int16(nnews, f));
|
||||
for (i = 0; i < nnews; i++) {
|
||||
SAFE(write_int16(news[i].type, f));
|
||||
SAFE(write_int32(news[i].num, f));
|
||||
SAFE(write_string(news[i].text, f));
|
||||
SAFE(write_buffer(news[i].who, f));
|
||||
SAFE(write_int32(news[i].time, f));
|
||||
}
|
||||
close_db(f);
|
||||
}
|
||||
|
||||
#undef SAFE
|
||||
|
||||
void save_rdb_news()
|
||||
{
|
||||
#ifdef USE_RDB
|
||||
int i;
|
||||
NewsItem *ni;
|
||||
|
||||
if (!rdb_open())
|
||||
return;
|
||||
|
||||
rdb_clear_table("anope_os_news");
|
||||
for (i = 0; i < nnews; i++) {
|
||||
ni = &news[i];
|
||||
rdb_save_news(ni);
|
||||
}
|
||||
|
||||
rdb_close();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/***************************** News display ******************************/
|
||||
/*************************************************************************/
|
||||
|
||||
void display_news(User * u, int16 type)
|
||||
{
|
||||
int msg;
|
||||
|
||||
if (type == NEWS_LOGON) {
|
||||
msg = NEWS_LOGON_TEXT;
|
||||
} else if (type == NEWS_OPER) {
|
||||
msg = NEWS_OPER_TEXT;
|
||||
} else if (type == NEWS_RANDOM) {
|
||||
msg = NEWS_RANDOM_TEXT;
|
||||
} else {
|
||||
alog("news: Invalid type (%d) to display_news()", type);
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == NEWS_RANDOM) {
|
||||
static int current_news = -1;
|
||||
int count = 0;
|
||||
|
||||
if (!nnews)
|
||||
return;
|
||||
|
||||
while (count++ < nnews) {
|
||||
if (++current_news >= nnews)
|
||||
current_news = 0;
|
||||
|
||||
if (news[current_news].type == type) {
|
||||
struct tm *tm;
|
||||
char timebuf[64];
|
||||
|
||||
tm = localtime(&news[current_news].time);
|
||||
strftime_lang(timebuf, sizeof(timebuf), u,
|
||||
STRFTIME_SHORT_DATE_FORMAT, tm);
|
||||
notice_lang(s_GlobalNoticer, u, msg, timebuf,
|
||||
news[current_news].text);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int i, count = 0; /* Number we're going to show--not more than 3 */
|
||||
|
||||
for (i = nnews - 1; i >= 0; i--) {
|
||||
if (count >= 3)
|
||||
break;
|
||||
if (news[i].type == type)
|
||||
count++;
|
||||
}
|
||||
while (++i < nnews) {
|
||||
if (news[i].type == type) {
|
||||
struct tm *tm;
|
||||
char timebuf[64];
|
||||
|
||||
tm = localtime(&news[i].time);
|
||||
strftime_lang(timebuf, sizeof(timebuf), u,
|
||||
STRFTIME_SHORT_DATE_FORMAT, tm);
|
||||
notice_lang(s_GlobalNoticer, u, msg, timebuf,
|
||||
news[i].text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/***************************** News editing ******************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* Declared in extern.h */
|
||||
int do_logonnews(User * u)
|
||||
{
|
||||
do_news(u, NEWS_LOGON);
|
||||
return MOD_CONT;
|
||||
}
|
||||
|
||||
/* Declared in extern.h */
|
||||
int do_opernews(User * u)
|
||||
{
|
||||
do_news(u, NEWS_OPER);
|
||||
return MOD_CONT;
|
||||
}
|
||||
|
||||
/* Declared in extern.h */
|
||||
int do_randomnews(User * u)
|
||||
{
|
||||
do_news(u, NEWS_RANDOM);
|
||||
return MOD_CONT;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Main news command handling routine. */
|
||||
void do_news(User * u, short type)
|
||||
{
|
||||
int is_servadmin = is_services_admin(u);
|
||||
char *cmd = strtok(NULL, " ");
|
||||
char *typename;
|
||||
int *msgs;
|
||||
|
||||
msgs = findmsgs(type, &typename);
|
||||
if (!msgs) {
|
||||
alog("news: Invalid type to do_news()");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cmd)
|
||||
cmd = "";
|
||||
|
||||
if (stricmp(cmd, "LIST") == 0) {
|
||||
do_news_list(u, type, msgs);
|
||||
} else if (stricmp(cmd, "ADD") == 0) {
|
||||
if (is_servadmin)
|
||||
do_news_add(u, type, msgs, typename);
|
||||
else
|
||||
notice_lang(s_OperServ, u, PERMISSION_DENIED);
|
||||
|
||||
} else if (stricmp(cmd, "DEL") == 0) {
|
||||
if (is_servadmin)
|
||||
do_news_del(u, type, msgs, typename);
|
||||
else
|
||||
notice_lang(s_OperServ, u, PERMISSION_DENIED);
|
||||
|
||||
} else {
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof(buf), "%sNEWS", typename);
|
||||
syntax_error(s_OperServ, u, buf, msgs[MSG_SYNTAX]);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Handle a {LOGON,OPER}NEWS LIST command. */
|
||||
|
||||
static void do_news_list(User * u, int16 type, int *msgs)
|
||||
{
|
||||
int i, count = 0;
|
||||
char timebuf[64];
|
||||
struct tm *tm;
|
||||
|
||||
for (i = 0; i < nnews; i++) {
|
||||
if (news[i].type == type) {
|
||||
if (count == 0)
|
||||
notice_lang(s_OperServ, u, msgs[MSG_LIST_HEADER]);
|
||||
tm = localtime(&news[i].time);
|
||||
strftime_lang(timebuf, sizeof(timebuf),
|
||||
u, STRFTIME_DATE_TIME_FORMAT, tm);
|
||||
notice_lang(s_OperServ, u, msgs[MSG_LIST_ENTRY],
|
||||
news[i].num, timebuf,
|
||||
*news[i].who ? news[i].who : "<unknown>",
|
||||
news[i].text);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count == 0)
|
||||
notice_lang(s_OperServ, u, msgs[MSG_LIST_NONE]);
|
||||
else {
|
||||
notice_lang(s_OperServ, u, END_OF_ANY_LIST, "News");
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Handle a {LOGON,OPER}NEWS ADD command. */
|
||||
|
||||
static void do_news_add(User * u, int16 type, int *msgs,
|
||||
const char *typename)
|
||||
{
|
||||
char *text = strtok(NULL, "");
|
||||
|
||||
if (!text) {
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof(buf), "%sNEWS", typename);
|
||||
syntax_error(s_OperServ, u, buf, msgs[MSG_ADD_SYNTAX]);
|
||||
} else {
|
||||
int n = add_newsitem(u, text, type);
|
||||
if (n < 0)
|
||||
notice_lang(s_OperServ, u, msgs[MSG_ADD_FULL]);
|
||||
else
|
||||
notice_lang(s_OperServ, u, msgs[MSG_ADDED], n);
|
||||
if (readonly)
|
||||
notice_lang(s_OperServ, u, READ_ONLY_MODE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Actually add a news item. Return the number assigned to the item, or -1
|
||||
* if the news list is full (32767 items).
|
||||
*/
|
||||
|
||||
static int add_newsitem(User * u, const char *text, short type)
|
||||
{
|
||||
int i, num;
|
||||
|
||||
if (nnews >= 32767)
|
||||
return -1;
|
||||
|
||||
if (nnews >= news_size) {
|
||||
if (news_size < 8)
|
||||
news_size = 8;
|
||||
else
|
||||
news_size *= 2;
|
||||
news = srealloc(news, sizeof(*news) * news_size);
|
||||
}
|
||||
num = 0;
|
||||
for (i = nnews - 1; i >= 0; i--) {
|
||||
if (news[i].type == type) {
|
||||
num = news[i].num;
|
||||
break;
|
||||
}
|
||||
}
|
||||
news[nnews].type = type;
|
||||
news[nnews].num = num + 1;
|
||||
news[nnews].text = sstrdup(text);
|
||||
news[nnews].time = time(NULL);
|
||||
strscpy(news[nnews].who, u->nick, NICKMAX);
|
||||
nnews++;
|
||||
return num + 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Handle a {LOGON,OPER}NEWS DEL command. */
|
||||
|
||||
static void do_news_del(User * u, int16 type, int *msgs,
|
||||
const char *typename)
|
||||
{
|
||||
char *text = strtok(NULL, " ");
|
||||
int i;
|
||||
|
||||
if (!text) {
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof(buf), "%sNEWS", typename);
|
||||
syntax_error(s_OperServ, u, buf, msgs[MSG_DEL_SYNTAX]);
|
||||
} else {
|
||||
if (stricmp(text, "ALL") != 0) {
|
||||
int num = atoi(text);
|
||||
if (num > 0 && del_newsitem(num, type)) {
|
||||
notice_lang(s_OperServ, u, msgs[MSG_DELETED], num);
|
||||
/* Reset the order - #0000397 */
|
||||
for (i = 0; i < nnews; i++)
|
||||
news[i].num = i + 1;
|
||||
} else
|
||||
notice_lang(s_OperServ, u, msgs[MSG_DEL_NOT_FOUND], num);
|
||||
} else {
|
||||
if (del_newsitem(0, type))
|
||||
notice_lang(s_OperServ, u, msgs[MSG_DELETED_ALL]);
|
||||
else
|
||||
notice_lang(s_OperServ, u, msgs[MSG_DEL_NONE]);
|
||||
}
|
||||
if (readonly)
|
||||
notice_lang(s_OperServ, u, READ_ONLY_MODE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Actually delete a news item. If `num' is 0, delete all news items of
|
||||
* the given type. Returns the number of items deleted.
|
||||
*/
|
||||
|
||||
static int del_newsitem(int num, short type)
|
||||
{
|
||||
int i;
|
||||
int count = 0;
|
||||
|
||||
for (i = 0; i < nnews; i++) {
|
||||
if (news[i].type == type && (num == 0 || news[i].num == num)) {
|
||||
free(news[i].text);
|
||||
count++;
|
||||
nnews--;
|
||||
if (i < nnews)
|
||||
memcpy(news + i, news + i + 1,
|
||||
sizeof(*news) * (nnews - i));
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
+4010
File diff suppressed because it is too large
Load Diff
+5099
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,268 @@
|
||||
/* Main processing code for Services.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: process.c,v 1.18 2004/01/31 18:57:18 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "services.h"
|
||||
#include "messages.h"
|
||||
#include "modules.h"
|
||||
extern Module *mod_current_module;
|
||||
extern char *mod_current_module_name;
|
||||
extern User *mod_current_user;
|
||||
extern int mod_current_op;
|
||||
extern char *mod_current_buffer;
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* Use ignore code? */
|
||||
int allow_ignore = 1;
|
||||
|
||||
/* People to ignore (hashed by first character of nick). */
|
||||
IgnoreData *ignore[256];
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* add_ignore: Add someone to the ignorance list for the next `delta'
|
||||
* seconds.
|
||||
*/
|
||||
|
||||
void add_ignore(const char *nick, time_t delta)
|
||||
{
|
||||
IgnoreData *ign;
|
||||
char who[NICKMAX];
|
||||
time_t now = time(NULL);
|
||||
IgnoreData **whichlist = &ignore[tolower(nick[0])];
|
||||
|
||||
strscpy(who, nick, NICKMAX);
|
||||
for (ign = *whichlist; ign; ign = ign->next) {
|
||||
if (stricmp(ign->who, who) == 0)
|
||||
break;
|
||||
}
|
||||
if (ign) {
|
||||
if (ign->time > now)
|
||||
ign->time += delta;
|
||||
else
|
||||
ign->time = now + delta;
|
||||
} else {
|
||||
ign = scalloc(sizeof(*ign), 1);
|
||||
strscpy(ign->who, who, sizeof(ign->who));
|
||||
ign->time = now + delta;
|
||||
ign->next = *whichlist;
|
||||
*whichlist = ign;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* get_ignore: Retrieve an ignorance record for a nick. If the nick isn't
|
||||
* being ignored, return NULL and flush the record from the
|
||||
* in-core list if it exists (i.e. ignore timed out).
|
||||
*/
|
||||
|
||||
IgnoreData *get_ignore(const char *nick)
|
||||
{
|
||||
IgnoreData *ign, *prev;
|
||||
time_t now = time(NULL);
|
||||
IgnoreData **whichlist = &ignore[tolower(nick[0])];
|
||||
User *u = finduser(nick);
|
||||
IgnoreData **whichlist2 = NULL;
|
||||
// Bleah, this doesn't work. I need a way to get the first char of u->username.
|
||||
//if (u) whichlist2 = &ignore[tolower(u->username[0])];
|
||||
IgnoreData **whichlistast = &ignore[42]; /* * */
|
||||
IgnoreData **whichlistqst = &ignore[63]; /* ? */
|
||||
int finished = 0;
|
||||
for (ign = *whichlist, prev = NULL; ign; prev = ign, ign = ign->next) {
|
||||
if (stricmp(ign->who, nick) == 0) {
|
||||
finished = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!finished && whichlist2) {
|
||||
for (ign = *whichlist2, prev = NULL; ign;
|
||||
prev = ign, ign = ign->next) {
|
||||
if (match_usermask(ign->who, u)) {
|
||||
finished = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!finished) {
|
||||
for (ign = *whichlistast, prev = NULL; ign;
|
||||
prev = ign, ign = ign->next) {
|
||||
if (match_usermask(ign->who, u)) {
|
||||
finished = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!finished) {
|
||||
for (ign = *whichlistqst, prev = NULL; ign;
|
||||
prev = ign, ign = ign->next) {
|
||||
if (match_usermask(ign->who, u)) {
|
||||
finished = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ign && ign->time <= now) {
|
||||
if (prev)
|
||||
prev->next = ign->next;
|
||||
else
|
||||
*whichlist = ign->next;
|
||||
free(ign);
|
||||
ign = NULL;
|
||||
}
|
||||
return ign;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* split_buf: Split a buffer into arguments and store the arguments in an
|
||||
* argument vector pointed to by argv (which will be malloc'd
|
||||
* as necessary); return the argument count. If colon_special
|
||||
* is non-zero, then treat a parameter with a leading ':' as
|
||||
* the last parameter of the line, per the IRC RFC. Destroys
|
||||
* the buffer by side effect.
|
||||
*/
|
||||
|
||||
int split_buf(char *buf, char ***argv, int colon_special)
|
||||
{
|
||||
int argvsize = 8;
|
||||
int argc;
|
||||
char *s;
|
||||
|
||||
*argv = scalloc(sizeof(char *) * argvsize, 1);
|
||||
argc = 0;
|
||||
while (*buf) {
|
||||
if (argc == argvsize) {
|
||||
argvsize += 8;
|
||||
*argv = srealloc(*argv, sizeof(char *) * argvsize);
|
||||
}
|
||||
if (*buf == ':') {
|
||||
(*argv)[argc++] = buf + 1;
|
||||
buf = "";
|
||||
} else {
|
||||
s = strpbrk(buf, " ");
|
||||
if (s) {
|
||||
*s++ = 0;
|
||||
while (*s == ' ')
|
||||
s++;
|
||||
} else {
|
||||
s = buf + strlen(buf);
|
||||
}
|
||||
(*argv)[argc++] = buf;
|
||||
buf = s;
|
||||
}
|
||||
}
|
||||
return argc;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* process: Main processing routine. Takes the string in inbuf (global
|
||||
* variable) and does something appropriate with it. */
|
||||
|
||||
void process()
|
||||
{
|
||||
int retVal = 0;
|
||||
Message *current = NULL;
|
||||
char source[64];
|
||||
char cmd[64];
|
||||
char buf[512]; /* Longest legal IRC command line */
|
||||
char *s;
|
||||
int ac; /* Parameters for the command */
|
||||
char **av;
|
||||
Message *m;
|
||||
|
||||
|
||||
/* If debugging, log the buffer */
|
||||
if (debug)
|
||||
alog("debug: Received: %s", inbuf);
|
||||
|
||||
/* First make a copy of the buffer so we have the original in case we
|
||||
* crash - in that case, we want to know what we crashed on. */
|
||||
strscpy(buf, inbuf, sizeof(buf));
|
||||
|
||||
doCleanBuffer((char *) buf);
|
||||
|
||||
/* Split the buffer into pieces. */
|
||||
if (*buf == ':') {
|
||||
s = strpbrk(buf, " ");
|
||||
if (!s)
|
||||
return;
|
||||
*s = 0;
|
||||
while (isspace(*++s));
|
||||
strscpy(source, buf + 1, sizeof(source));
|
||||
memmove(buf, s, strlen(s) + 1);
|
||||
} else {
|
||||
*source = 0;
|
||||
}
|
||||
if (!*buf)
|
||||
return;
|
||||
s = strpbrk(buf, " ");
|
||||
if (s) {
|
||||
*s = 0;
|
||||
while (isspace(*++s));
|
||||
} else
|
||||
s = buf + strlen(buf);
|
||||
strscpy(cmd, buf, sizeof(cmd));
|
||||
ac = split_buf(s, &av, 1);
|
||||
if (mod_current_buffer) {
|
||||
free(mod_current_buffer);
|
||||
}
|
||||
if (av[1]) {
|
||||
mod_current_buffer = sstrdup(av[1]);
|
||||
} else {
|
||||
mod_current_buffer = NULL;
|
||||
}
|
||||
/* Do something with the message. */
|
||||
m = find_message(cmd);
|
||||
if (m) {
|
||||
if (m->func) {
|
||||
mod_current_module_name = m->mod_name;
|
||||
retVal = m->func(source, ac, av);
|
||||
mod_current_module_name = NULL;
|
||||
if (retVal == MOD_CONT) {
|
||||
current = m->next;
|
||||
while (current && current->func && retVal == MOD_CONT) {
|
||||
mod_current_module_name = m->mod_name;
|
||||
retVal = current->func(source, ac, av);
|
||||
mod_current_module_name = NULL;
|
||||
current = current->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (debug)
|
||||
alog("unknown message from server (%s)", inbuf);
|
||||
}
|
||||
if (mod_current_op == 1) {
|
||||
alog("trying to load [%s]", mod_current_module->name);
|
||||
alog("status: [%d]",
|
||||
loadModule(mod_current_module, mod_current_user));
|
||||
mod_current_module = NULL;
|
||||
mod_current_user = NULL;
|
||||
mod_current_op = 0;
|
||||
} else if (mod_current_op == 2) {
|
||||
alog("trying to unload [%s]", mod_current_module->name);
|
||||
alog("status: [%d]",
|
||||
unloadModule(mod_current_module, mod_current_user));
|
||||
mod_current_module = NULL;
|
||||
mod_current_user = NULL;
|
||||
mod_current_op = 0;
|
||||
}
|
||||
/* Free argument list we created */
|
||||
free(av);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
+182
@@ -0,0 +1,182 @@
|
||||
/* Simple interfaces to various protocols.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: protocol.c,v 1.11 2003/07/20 01:15:50 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "services.h"
|
||||
|
||||
/* Makes an permanent ban from all the servers. Assumes that the matching clients are killed. */
|
||||
|
||||
void s_akill(char *user, char *host, char *who, time_t when,
|
||||
time_t expires, char *reason)
|
||||
{
|
||||
#if defined(IRC_BAHAMUT)
|
||||
/* send_cmd(NULL, "AKILL %s %s %d %s %ld :%s", host, user, 86400*2, who, when, reason); */
|
||||
send_cmd(NULL, "AKILL %s %s %d %s %ld :%s", host, user,
|
||||
86400 * 2, who, time(NULL), reason);
|
||||
|
||||
#elif defined(IRC_UNREAL)
|
||||
send_cmd(NULL, "TKL + G %s %s %s %ld %ld :%s", user, host, who, time(NULL) + 86400 * 2, /* Avoids filling the akill list of servers too much */
|
||||
when, reason);
|
||||
#elif defined(IRC_DREAMFORGE)
|
||||
send_cmd(NULL, "AKILL %s %s :%s", host, user, reason);
|
||||
#elif defined(IRC_PTLINK)
|
||||
send_cmd(ServerName, "GLINE %s@%s %i %s :%s", user, host, 86400 * 2,
|
||||
who, reason);
|
||||
#elif defined(IRC_HYBRID)
|
||||
send_cmd(s_OperServ, "KLINE * %ld %s %s :%s",
|
||||
(expires - (long) time(NULL)), user, host, reason);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Removes a permanent ban from all the servers. */
|
||||
|
||||
void s_rakill(char *user, char *host)
|
||||
{
|
||||
#if defined(IRC_PTLINK)
|
||||
send_cmd(NULL, "UNGLINE %s@%s", user, host);
|
||||
#elif defined(IRC_UNREAL)
|
||||
send_cmd(NULL, "TKL - G %s %s %s", user, host, s_OperServ);
|
||||
#elif !defined(IRC_HYBRID)
|
||||
send_cmd(NULL, "RAKILL %s %s", host, user);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void s_sgline(char *mask, char *reason)
|
||||
{
|
||||
#ifdef IRC_BAHAMUT
|
||||
/* User *u; */
|
||||
|
||||
send_cmd(NULL, "SGLINE %d :%s:%s", strlen(mask), mask, reason);
|
||||
|
||||
/* Do things properly: kill all corresponding users as this is
|
||||
unfortunately not done by the IRCds :/ */
|
||||
/* Breaks things currently! */
|
||||
/* for (u = firstuser(); u; u = nextuser())
|
||||
if (match_wild_nocase(mask, u->realname))
|
||||
send_cmd(NULL, "SVSKILL %s :G-Lined: %s", u->nick, reason); */
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void s_sqline(char *mask, char *reason)
|
||||
{
|
||||
#ifdef IRC_BAHAMUT
|
||||
if (*mask == '#') {
|
||||
int i;
|
||||
Channel *c, *next;
|
||||
|
||||
char *av[3];
|
||||
struct c_userlist *cu, *cunext;
|
||||
|
||||
send_cmd(NULL, "SQLINE %s :%s", mask, reason);
|
||||
|
||||
for (i = 0; i < 1024; i++) {
|
||||
for (c = chanlist[i]; c; c = next) {
|
||||
next = c->next;
|
||||
|
||||
if (!match_wild_nocase(mask, c->name))
|
||||
continue;
|
||||
|
||||
for (cu = c->users; cu; cu = cunext) {
|
||||
cunext = cu->next;
|
||||
|
||||
if (is_oper(cu->user))
|
||||
continue;
|
||||
|
||||
av[0] = c->name;
|
||||
av[1] = cu->user->nick;
|
||||
av[2] = reason;
|
||||
send_cmd(s_OperServ, "KICK %s %s :Q-Lined: %s", av[0],
|
||||
av[1], av[2]);
|
||||
do_kick(s_ChanServ, 3, av);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
/* int i;
|
||||
User *u, *next; */
|
||||
|
||||
send_cmd(NULL, "SQLINE %s :%s", mask, reason);
|
||||
|
||||
/* for (i = 0; i < 1024; i++) {
|
||||
for (u = userlist[i]; u; u = next) {
|
||||
next = u->next;
|
||||
if (match_wild_nocase(mask, u->nick))
|
||||
#ifdef IRC_BAHAMUT
|
||||
send_cmd(NULL, "SVSKILL %s :%s", u->nick, reason);
|
||||
#else
|
||||
kill_user(s_OperServ, u->nick, reason);
|
||||
#endif
|
||||
}
|
||||
} */
|
||||
#ifdef IRC_BAHAMUT
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void s_svsnoop(char *server, int set)
|
||||
{
|
||||
#ifndef IRC_HYBRID
|
||||
#ifdef IRC_PTLINK
|
||||
send_cmd(NULL, "SVSADMIN %s :%s", server, set ? "noopers" : "rehash");
|
||||
#else
|
||||
send_cmd(NULL, "SVSNOOP %s %s", server, (set ? "+" : "-"));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void s_szline(char *mask, char *reason)
|
||||
{
|
||||
#ifdef IRC_BAHAMUT
|
||||
send_cmd(NULL, "SZLINE %s :%s", mask, reason);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void s_unsgline(char *mask)
|
||||
{
|
||||
#ifdef IRC_BAHAMUT
|
||||
send_cmd(NULL, "UNSGLINE 0 :%s", mask);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void s_unsqline(char *mask)
|
||||
{
|
||||
#ifdef IRC_BAHAMUT
|
||||
send_cmd(NULL, "UNSQLINE 0 %s", mask);
|
||||
#else
|
||||
send_cmd(NULL, "UNSQLINE %s", mask);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void s_unszline(char *mask)
|
||||
{
|
||||
#ifdef IRC_BAHAMUT
|
||||
send_cmd(NULL, "UNSZLINE 0 %s", mask);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,793 @@
|
||||
/* Proxy detector.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: proxy.c,v 1.11 2004/02/14 21:22:55 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "services.h"
|
||||
#include "pseudo.h"
|
||||
#include <fcntl.h>
|
||||
|
||||
/* Hashed list of HostCache; threads must not use it! */
|
||||
HostCache *hcache[1024];
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Equivalent to inet_ntoa */
|
||||
|
||||
void ntoa(struct in_addr addr, char *ipaddr, int len)
|
||||
{
|
||||
unsigned char *bytes = (unsigned char *) &addr.s_addr;
|
||||
snprintf(ipaddr, len, "%u.%u.%u.%u", bytes[0], bytes[1], bytes[2],
|
||||
bytes[3]);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#ifdef USE_THREADS
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#define HASH(host) ((tolower((host)[0])&31)<<5 | (tolower((host)[1])&31))
|
||||
|
||||
/* Proxy queue; access controlled by queuemut */
|
||||
SList pxqueue;
|
||||
|
||||
pthread_mutex_t queuemut = PTHREAD_MUTEX_INITIALIZER;
|
||||
pthread_cond_t queuecond = PTHREAD_COND_INITIALIZER;
|
||||
|
||||
#if !defined(HAS_NICKIP) && !defined(HAVE_GETHOSTBYNAME_R6) && !defined(HAVE_GETHOSTBYNAME_R5) && !defined(HAVE_GETHOSTBYNAME_R3)
|
||||
pthread_mutex_t resmut = PTHREAD_MUTEX_INITIALIZER;
|
||||
#endif
|
||||
|
||||
static uint32 aton(char *ipaddr);
|
||||
static void proxy_akill(char *host);
|
||||
static HostCache *proxy_cache_add(char *host);
|
||||
static void proxy_cache_del(HostCache * hc);
|
||||
static HostCache *proxy_cache_find(char *host);
|
||||
static int proxy_connect(unsigned long ip, unsigned short port);
|
||||
static void proxy_queue_cleanup_unlock(void *arg);
|
||||
static void proxy_queue_lock(void);
|
||||
static void proxy_queue_signal(void);
|
||||
static void proxy_queue_unlock(void);
|
||||
static void proxy_queue_wait(void);
|
||||
static int proxy_read(int s, char *buf, size_t buflen);
|
||||
#ifndef HAS_NICKIP
|
||||
static uint32 proxy_resolve(char *host);
|
||||
#endif
|
||||
static int proxy_scan(uint32 ip);
|
||||
static void *proxy_thread_main(void *arg);
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Equivalent to inet_addr */
|
||||
|
||||
static uint32 aton(char *ipaddr)
|
||||
{
|
||||
int i;
|
||||
long lv;
|
||||
char *endptr;
|
||||
uint32 res;
|
||||
unsigned char *bytes = (unsigned char *) &res;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (!*ipaddr)
|
||||
return INADDR_NONE;
|
||||
|
||||
lv = strtol(ipaddr, &endptr, 10);
|
||||
if (lv < 0 || lv > 255 || (*endptr != 0 && *endptr != '.'))
|
||||
return INADDR_NONE;
|
||||
|
||||
bytes[i] = (unsigned char) lv;
|
||||
ipaddr = (!*endptr ? endptr : ++endptr);
|
||||
}
|
||||
|
||||
if (*endptr)
|
||||
return INADDR_NONE;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void get_proxy_stats(long *nrec, long *memuse)
|
||||
{
|
||||
int i;
|
||||
long mem = 0, count = 0;
|
||||
HostCache *hc;
|
||||
|
||||
for (i = 0; i < 1024; i++) {
|
||||
for (hc = hcache[i]; hc; hc = hc->next) {
|
||||
count += 1;
|
||||
mem += sizeof(HostCache);
|
||||
mem += strlen(hc->host) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
*nrec = count;
|
||||
*memuse = mem;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Akills the given host, and issues a GLOBOPS if configured so */
|
||||
|
||||
static void proxy_akill(char *host)
|
||||
{
|
||||
s_akill("*", host, s_OperServ, time(NULL),
|
||||
time(NULL) + (ProxyExpire ? ProxyExpire : 86400 * 2),
|
||||
ProxyAkillReason);
|
||||
if (WallProxy)
|
||||
wallops(s_OperServ, "Insecure proxy \2%s\2 has been AKILLed.",
|
||||
host);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Adds a cache entry after having it allocated */
|
||||
|
||||
static HostCache *proxy_cache_add(char *host)
|
||||
{
|
||||
HostCache *hc;
|
||||
int index = HASH(host);
|
||||
|
||||
hc = scalloc(1, sizeof(HostCache));
|
||||
hc->host = sstrdup(host);
|
||||
hc->used = time(NULL);
|
||||
|
||||
hc->prev = NULL;
|
||||
hc->next = hcache[index];
|
||||
if (hc->next)
|
||||
hc->next->prev = hc;
|
||||
hcache[index] = hc;
|
||||
|
||||
if (debug)
|
||||
alog("debug: Added %s to host cache", host);
|
||||
|
||||
return hc;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Deletes and frees a proxy cache entry */
|
||||
|
||||
static void proxy_cache_del(HostCache * hc)
|
||||
{
|
||||
/* Just to be sure */
|
||||
if (hc->status < 0)
|
||||
return;
|
||||
|
||||
if (debug)
|
||||
alog("debug: Deleting %s from host cache", hc->host);
|
||||
|
||||
if (hc->status > HC_NORMAL)
|
||||
s_rakill("*", hc->host);
|
||||
|
||||
if (hc->next)
|
||||
hc->next->prev = hc->prev;
|
||||
if (hc->prev)
|
||||
hc->prev->next = hc->next;
|
||||
else
|
||||
hcache[HASH(hc->host)] = hc->next;
|
||||
|
||||
if (hc->host)
|
||||
free(hc->host);
|
||||
|
||||
free(hc);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Finds a proxy cache entry */
|
||||
|
||||
static HostCache *proxy_cache_find(char *host)
|
||||
{
|
||||
HostCache *hc;
|
||||
|
||||
for (hc = hcache[HASH(host)]; hc; hc = hc->next) {
|
||||
if (stricmp(hc->host, host) == 0)
|
||||
return hc;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Checks whether the specified host is in the cache.
|
||||
* If so:
|
||||
* * if it's a proxy, take the appropriate actions, including killing nick
|
||||
* * if it's not a proxy, do nothing
|
||||
* If not:
|
||||
* * add the host to the cache
|
||||
* * add the host to the queue
|
||||
* * send a signal to a waiting thread (if any)
|
||||
*
|
||||
* Returns 0 if nick is to be added to internal list, 1 else
|
||||
*/
|
||||
|
||||
int proxy_check(char *nick, char *host, uint32 ip)
|
||||
{
|
||||
int i;
|
||||
char **message;
|
||||
HostCache *hc;
|
||||
|
||||
if ((hc = proxy_cache_find(host))) {
|
||||
hc->used = time(NULL);
|
||||
|
||||
if (hc->status <= HC_NORMAL)
|
||||
return 0;
|
||||
|
||||
proxy_akill(host);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (message = ProxyMessage, i = 0; i < 8 && *message && **message;
|
||||
message++, i++)
|
||||
notice(s_GlobalNoticer, nick, *message);
|
||||
|
||||
hc = proxy_cache_add(host);
|
||||
#ifdef HAS_NICKIP
|
||||
hc->ip = htonl(ip);
|
||||
#endif
|
||||
hc->status = HC_QUEUED;
|
||||
|
||||
proxy_queue_lock();
|
||||
slist_add(&pxqueue, hc);
|
||||
if (debug)
|
||||
alog("debug: Added %s to proxy queue", hc->host);
|
||||
proxy_queue_signal();
|
||||
proxy_queue_unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Initiates a non-blocking connection */
|
||||
|
||||
static int proxy_connect(unsigned long ip, unsigned short port)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
int s;
|
||||
|
||||
fd_set fds;
|
||||
struct timeval tv;
|
||||
int error, errlen;
|
||||
|
||||
if ((s = socket(PF_INET, SOCK_STREAM, 0)) == -1)
|
||||
return -1;
|
||||
|
||||
if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&sin, 0, sizeof(struct sockaddr_in));
|
||||
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_addr.s_addr = ip;
|
||||
sin.sin_port = htons(port);
|
||||
|
||||
if (connect(s, (struct sockaddr *) &sin, sizeof(struct sockaddr_in)) ==
|
||||
-1 && errno != EINPROGRESS) {
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(s, &fds);
|
||||
|
||||
tv.tv_sec = ProxyTimeout;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
if (select(s + 1, NULL, &fds, NULL, &tv) <= 0) {
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
errlen = sizeof(int);
|
||||
if (getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &errlen) == -1
|
||||
|| error != 0) {
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Deletes expired cache entries */
|
||||
|
||||
void proxy_expire()
|
||||
{
|
||||
int i;
|
||||
HostCache *hc, *next;
|
||||
time_t t = time(NULL);
|
||||
|
||||
for (i = 0; i < 1024; i++) {
|
||||
for (hc = hcache[i]; hc; hc = next) {
|
||||
next = hc->next;
|
||||
|
||||
/* Don't expire not scanned yet entries */
|
||||
if (hc->status < HC_NORMAL)
|
||||
continue;
|
||||
|
||||
if (hc->status == HC_NORMAL
|
||||
&& t - hc->used >= ProxyCacheExpire) {
|
||||
proxy_cache_del(hc);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ProxyExpire && hc->status > HC_NORMAL
|
||||
&& t - hc->used >= ProxyExpire) {
|
||||
alog("proxy: Expiring proxy %s", hc->host);
|
||||
proxy_cache_del(hc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Initializes the proxy detector. Returns 1 on success, 0 on error. */
|
||||
|
||||
int proxy_init(void)
|
||||
{
|
||||
int i;
|
||||
pthread_t th;
|
||||
|
||||
slist_init(&pxqueue);
|
||||
|
||||
for (i = 1; i <= ProxyThreads; i++) {
|
||||
if (pthread_create(&th, NULL, proxy_thread_main, NULL))
|
||||
return 0;
|
||||
if (pthread_detach(th))
|
||||
return 0;
|
||||
if (debug)
|
||||
alog("debug: Creating proxy thread %ld (%d of %d)", (long) th,
|
||||
i, ProxyThreads);
|
||||
}
|
||||
|
||||
alog("Proxy detector initialized");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static void proxy_queue_cleanup_unlock(void *arg)
|
||||
{
|
||||
proxy_queue_unlock();
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static void proxy_queue_lock(void)
|
||||
{
|
||||
if (debug)
|
||||
alog("debug: Thread %ld: Locking proxy queue mutex",
|
||||
(long) pthread_self());
|
||||
pthread_mutex_lock(&queuemut);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static void proxy_queue_signal(void)
|
||||
{
|
||||
if (debug)
|
||||
alog("debug: Thread %ld: Signaling proxy queue condition",
|
||||
(long) pthread_self());
|
||||
pthread_cond_signal(&queuecond);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static void proxy_queue_unlock(void)
|
||||
{
|
||||
if (debug)
|
||||
alog("debug: Thread %ld: Unlocking proxy queue mutex",
|
||||
(long) pthread_self());
|
||||
pthread_mutex_unlock(&queuemut);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static void proxy_queue_wait(void)
|
||||
{
|
||||
if (debug)
|
||||
alog("debug: Thread %ld: waiting proxy queue condition",
|
||||
(long) pthread_self());
|
||||
pthread_cond_wait(&queuecond, &queuemut);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Reads from the socket, in a non-blocking manner */
|
||||
|
||||
static int proxy_read(int s, char *buf, size_t buflen)
|
||||
{
|
||||
fd_set fds;
|
||||
struct timeval tv;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(s, &fds);
|
||||
|
||||
tv.tv_sec = ProxyTimeout;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
if (select(s + 1, &fds, NULL, NULL, &tv) <= 0)
|
||||
return -1;
|
||||
|
||||
return recv(s, buf, buflen, 0);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Resolves hostnames in a thread safe manner */
|
||||
|
||||
#ifndef HAS_NICKIP
|
||||
|
||||
static uint32 proxy_resolve(char *host)
|
||||
{
|
||||
struct hostent *hentp = NULL;
|
||||
uint32 ip = INADDR_NONE;
|
||||
#if defined(HAVE_GETHOSTBYNAME_R6)
|
||||
struct hostent hent;
|
||||
char hbuf[8192];
|
||||
int herrno;
|
||||
|
||||
if (gethostbyname_r(host, &hent, hbuf, sizeof(hbuf), &hentp, &herrno) <
|
||||
0)
|
||||
hentp = NULL;
|
||||
#elif defined(HAVE_GETHOSTBYNAME_R5)
|
||||
struct hostent hent char hbuf[8192];
|
||||
int herrno;
|
||||
hentp = gethostbyname_r(host, &hent, hbuf, sizeof(hbuf), &herrno);
|
||||
#elif defined(HAVE_GETHOSTBYNAME_R3)
|
||||
struct hostent hent;
|
||||
struct hostent_data data;
|
||||
hentp = gethostbyname_r(host, &hent, &data);
|
||||
#else
|
||||
/* Make it safe that way */
|
||||
pthread_mutex_lock(&resmut);
|
||||
hentp = gethostbyname(host);
|
||||
#endif
|
||||
|
||||
if (hentp) {
|
||||
memcpy(&ip, hentp->h_addr, sizeof(hentp->h_length));
|
||||
if (debug) {
|
||||
char ipbuf[16];
|
||||
struct in_addr addr;
|
||||
addr.s_addr = ip;
|
||||
ntoa(addr, ipbuf, sizeof(ipbuf));
|
||||
alog("debug: Thread %ld: resolved %s to %s",
|
||||
(long) pthread_self(), host, ipbuf);
|
||||
}
|
||||
}
|
||||
#if !defined(HAVE_GETHOSTBYNAME_R6) && !defined(HAVE_GETHOSTBYNAME_R5) && !defined(HAVE_GETHOSTBYNAME_R3)
|
||||
pthread_mutex_unlock(&resmut);
|
||||
#endif
|
||||
|
||||
return ip;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Scans the given host for proxy */
|
||||
|
||||
static int proxy_scan(uint32 ip)
|
||||
{
|
||||
int s; /* Socket */
|
||||
int i;
|
||||
|
||||
if (ip == INADDR_NONE)
|
||||
return HC_NORMAL;
|
||||
|
||||
/* Scan for SOCKS (4/5) */
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if ((s = proxy_connect(ip, 1080)) == -1)
|
||||
break;
|
||||
|
||||
if (ProxyCheckSocks4 && i == 0) {
|
||||
/* SOCKS4 */
|
||||
|
||||
char buf[9];
|
||||
uint32 sip;
|
||||
|
||||
sip = aton(ProxyTestServer);
|
||||
sip = htonl(sip);
|
||||
|
||||
buf[0] = 4;
|
||||
buf[1] = 1;
|
||||
buf[2] = (((unsigned short) ProxyTestPort) >> 8) & 0xFF;
|
||||
buf[3] = ((unsigned short) ProxyTestPort) & 0xFF;
|
||||
buf[4] = (sip >> 24) & 0xFF;
|
||||
buf[5] = (sip >> 16) & 0xFF;
|
||||
buf[6] = (sip >> 8) & 0xFF;
|
||||
buf[7] = sip & 0xFF;
|
||||
buf[8] = 0;
|
||||
|
||||
if (send(s, buf, 9, 0) != 9) {
|
||||
close(s);
|
||||
return HC_NORMAL;
|
||||
}
|
||||
|
||||
if (proxy_read(s, buf, 2) != 2) {
|
||||
close(s);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (buf[1] == 90) {
|
||||
close(s);
|
||||
return HC_SOCKS4;
|
||||
}
|
||||
|
||||
} else if (ProxyCheckSocks5 && i == 1) {
|
||||
/* SOCKS5 */
|
||||
|
||||
char buf[10];
|
||||
uint32 sip;
|
||||
|
||||
if (send(s, "\5\1\0", 3, 0) != 3) {
|
||||
close(s);
|
||||
continue;
|
||||
}
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
if (proxy_read(s, buf, 2) != 2) {
|
||||
close(s);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (buf[0] != 5 || buf[1] != 0) {
|
||||
close(s);
|
||||
continue;
|
||||
}
|
||||
|
||||
sip = aton(ProxyTestServer);
|
||||
sip = htonl(sip);
|
||||
|
||||
buf[0] = 5;
|
||||
buf[1] = 1;
|
||||
buf[2] = 0;
|
||||
buf[3] = 1;
|
||||
buf[4] = (sip >> 24) & 0xFF;
|
||||
buf[5] = (sip >> 16) & 0xFF;
|
||||
buf[6] = (sip >> 8) & 0xFF;
|
||||
buf[7] = sip & 0xFF;
|
||||
buf[8] = (((unsigned short) ProxyTestPort) >> 8) & 0xFF;
|
||||
buf[9] = ((unsigned short) ProxyTestPort) & 0xFF;
|
||||
|
||||
if (send(s, buf, 10, 0) != 10) {
|
||||
close(s);
|
||||
continue;
|
||||
}
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
if (proxy_read(s, buf, 2) != 2) {
|
||||
close(s);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (buf[0] == 5 && buf[1] == 0) {
|
||||
close(s);
|
||||
return HC_SOCKS5;
|
||||
}
|
||||
}
|
||||
|
||||
close(s);
|
||||
}
|
||||
|
||||
/* Scan for HTTP proxy */
|
||||
for (i = 0; i < 3; i++) {
|
||||
if ((i ==
|
||||
0 ? ProxyCheckHTTP2 : (i ==
|
||||
1 ? ProxyCheckHTTP1 : ProxyCheckHTTP3))
|
||||
&& (s =
|
||||
proxy_connect(ip,
|
||||
(i == 0 ? 8080 : (i == 1 ? 3128 : 80)))) !=
|
||||
-1) {
|
||||
int bread;
|
||||
char buf[64];
|
||||
|
||||
snprintf(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.0\n\n",
|
||||
ProxyTestServer, ProxyTestPort);
|
||||
if (send(s, buf, strlen(buf), 0) == strlen(buf)) {
|
||||
if ((bread = proxy_read(s, buf, 15)) >= 12) {
|
||||
buf[bread] = 0;
|
||||
|
||||
if (!strnicmp(buf, "HTTP/1.0 200", 12) || !stricmp(buf, "HTTP/1.1 200 Co")) { /* Apache may return 200 OK
|
||||
even if it's not processing
|
||||
the CONNECT request. :/ */
|
||||
close(s);
|
||||
return HC_HTTP;
|
||||
}
|
||||
}
|
||||
}
|
||||
close(s);
|
||||
}
|
||||
}
|
||||
|
||||
/* Scan for Wingate */
|
||||
if (ProxyCheckWingate && (s = proxy_connect(ip, 23)) != -1) {
|
||||
char buf[9];
|
||||
|
||||
if (proxy_read(s, buf, 8) == 8) {
|
||||
buf[8] = '\0';
|
||||
if (!stricmp(buf, "Wingate>") || !stricmp(buf, "Too many")) {
|
||||
close(s);
|
||||
return HC_WINGATE;
|
||||
}
|
||||
}
|
||||
close(s);
|
||||
}
|
||||
|
||||
return HC_NORMAL;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Proxy detector threads entry point */
|
||||
|
||||
static void *proxy_thread_main(void *arg)
|
||||
{
|
||||
while (1) {
|
||||
pthread_cleanup_push(&proxy_queue_cleanup_unlock, NULL);
|
||||
proxy_queue_lock();
|
||||
proxy_queue_wait();
|
||||
pthread_cleanup_pop(1);
|
||||
|
||||
/* We loop until there is no more host to check in the list */
|
||||
while (1) {
|
||||
HostCache *hc = NULL;
|
||||
int status;
|
||||
|
||||
pthread_cleanup_push(&proxy_queue_cleanup_unlock, NULL);
|
||||
proxy_queue_lock();
|
||||
if (pxqueue.count > 0) {
|
||||
hc = pxqueue.list[0];
|
||||
hc->status = HC_PROGRESS;
|
||||
slist_delete(&pxqueue, 0);
|
||||
}
|
||||
pthread_cleanup_pop(1);
|
||||
|
||||
if (!hc)
|
||||
break;
|
||||
|
||||
if (debug) {
|
||||
if (hc->ip) {
|
||||
char ipbuf[16];
|
||||
struct in_addr in;
|
||||
in.s_addr = hc->ip;
|
||||
ntoa(in, ipbuf, sizeof(ipbuf));
|
||||
alog("debug: Scanning host %s [%s] for proxy",
|
||||
hc->host, ipbuf);
|
||||
} else {
|
||||
alog("debug: Scanning host %s for proxy", hc->host);
|
||||
}
|
||||
}
|
||||
#ifndef HAS_NICKIP
|
||||
/* Test if it's an IP, and if not try to resolve the hostname */
|
||||
if ((hc->ip = aton(hc->host)) == INADDR_NONE)
|
||||
hc->ip = proxy_resolve(hc->host);
|
||||
#endif
|
||||
status = proxy_scan(hc->ip);
|
||||
|
||||
if (debug) {
|
||||
char ipbuf[16];
|
||||
struct in_addr in;
|
||||
in.s_addr = hc->ip;
|
||||
ntoa(in, ipbuf, sizeof(ipbuf));
|
||||
alog("debug: Scan for %s [%s] complete, result: %d",
|
||||
hc->host, ipbuf, status);
|
||||
}
|
||||
|
||||
if (status > HC_NORMAL)
|
||||
proxy_akill(hc->host);
|
||||
|
||||
hc->status = status;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* OperServ CACHE */
|
||||
|
||||
int do_cache(User * u)
|
||||
{
|
||||
#ifdef USE_THREADS
|
||||
char *cmd = strtok(NULL, " ");
|
||||
char *pattern = strtok(NULL, " ");
|
||||
|
||||
if (!ProxyDetect) {
|
||||
notice_lang(s_OperServ, u, OPER_CACHE_DISABLED);
|
||||
return MOD_CONT;
|
||||
}
|
||||
|
||||
if (!cmd || !pattern) {
|
||||
syntax_error(s_OperServ, u, "CACHE", OPER_CACHE_SYNTAX);
|
||||
} else if (!stricmp(cmd, "DEL")) {
|
||||
HostCache *hc;
|
||||
|
||||
if (!(hc = proxy_cache_find(pattern))) {
|
||||
notice_lang(s_OperServ, u, OPER_CACHE_NOT_FOUND, pattern);
|
||||
return MOD_CONT;
|
||||
}
|
||||
|
||||
proxy_cache_del(hc);
|
||||
notice_lang(s_OperServ, u, OPER_CACHE_REMOVED, pattern);
|
||||
|
||||
if (readonly)
|
||||
notice_lang(s_OperServ, u, READ_ONLY_MODE);
|
||||
} else if (!stricmp(cmd, "LIST")) {
|
||||
char *option = strtok(NULL, " ");
|
||||
int i, restrict = 0, count = 0, total = 0;
|
||||
HostCache *hc;
|
||||
|
||||
static int statusdesc[7] = {
|
||||
OPER_CACHE_QUEUED,
|
||||
OPER_CACHE_PROGRESS,
|
||||
OPER_CACHE_NORMAL,
|
||||
OPER_CACHE_WINGATE,
|
||||
OPER_CACHE_SOCKS4,
|
||||
OPER_CACHE_SOCKS5,
|
||||
OPER_CACHE_HTTP
|
||||
};
|
||||
|
||||
if (option && !stricmp(option, "QUEUED"))
|
||||
restrict = 1;
|
||||
else if (option && !stricmp(option, "ALL"))
|
||||
restrict = 2;
|
||||
|
||||
notice_lang(s_OperServ, u, OPER_CACHE_HEADER);
|
||||
|
||||
for (i = 0; i < 1024; i++) {
|
||||
for (hc = hcache[i]; hc; hc = hc->next) {
|
||||
if (!match_wild_nocase(pattern, hc->host))
|
||||
continue;
|
||||
if ((restrict == 0 && hc->status <= HC_NORMAL)
|
||||
|| (restrict == 1 && hc->status >= HC_NORMAL))
|
||||
continue;
|
||||
total++;
|
||||
if (count >= ProxyMax)
|
||||
continue;
|
||||
notice_lang(s_OperServ, u, OPER_CACHE_LIST, hc->host,
|
||||
getstring(u->na, statusdesc[hc->status + 2]));
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
notice_lang(s_OperServ, u, OPER_CACHE_FOOTER, count, total);
|
||||
|
||||
} else {
|
||||
syntax_error(s_OperServ, u, "CACHE", OPER_CACHE_SYNTAX);
|
||||
}
|
||||
#else
|
||||
notice_lang(s_OperServ, u, OPER_CACHE_DISABLED);
|
||||
#endif
|
||||
return MOD_CONT;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
@@ -0,0 +1,20 @@
|
||||
/* Include extra includes needed by most/all pseudo-clients.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: pseudo.h,v 1.4 2003/07/20 01:15:50 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "commands.h"
|
||||
#include "language.h"
|
||||
#include "timeout.h"
|
||||
#include "encrypt.h"
|
||||
#include "datafiles.h"
|
||||
#include "slist.h"
|
||||
@@ -0,0 +1,347 @@
|
||||
/* RDB functions.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: rdb.c,v 1.11 2003/08/04 01:09:43 dane Exp $
|
||||
*
|
||||
*/
|
||||
#include "services.h"
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int rdb_init()
|
||||
{
|
||||
|
||||
#ifdef USE_MYSQL
|
||||
return db_mysql_init();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int rdb_open()
|
||||
{
|
||||
|
||||
#ifdef USE_MYSQL
|
||||
return db_mysql_open();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int rdb_close()
|
||||
{
|
||||
|
||||
#ifdef USE_MYSQL
|
||||
return db_mysql_close();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int rdb_tag_table(char *table)
|
||||
{
|
||||
static char buf[1024];
|
||||
|
||||
#ifdef USE_MYSQL
|
||||
snprintf(buf, sizeof(buf), "UPDATE %s SET active='0'", table);
|
||||
return db_mysql_query(buf);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int rdb_clear_table(char *table)
|
||||
{
|
||||
static char buf[1024];
|
||||
|
||||
#ifdef USE_MYSQL
|
||||
snprintf(buf, sizeof(buf), "TRUNCATE TABLE %s", table);
|
||||
return db_mysql_query(buf);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int rdb_scrub_table(char *table, char *clause)
|
||||
{
|
||||
|
||||
static char buf[1024];
|
||||
|
||||
#ifdef USE_MYSQL
|
||||
snprintf(buf, sizeof(buf), "DELETE FROM %s WHERE %s", table, clause);
|
||||
return db_mysql_query(buf);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int rdb_direct_query(char *query)
|
||||
{
|
||||
|
||||
#ifdef USE_MYSQL
|
||||
alog("Direct Query: %s", query);
|
||||
return db_mysql_query(query);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* I still don't really like doing it this way, it should really be done
|
||||
* inside mysql.c and not here. So I'll revisit this later
|
||||
*/
|
||||
int rdb_ns_set_display(char *newnick, char *oldnick)
|
||||
{
|
||||
static char buf[1024];
|
||||
|
||||
#ifdef USE_MYSQL
|
||||
/* Change the display on NS_CORE */
|
||||
snprintf(buf, sizeof(buf),
|
||||
"UPDATE anope_ns_core SET display='%s' WHERE display='%s'",
|
||||
newnick, oldnick);
|
||||
db_mysql_query(buf);
|
||||
|
||||
/* Change the display on NS_ALIAS for all grouped nicks */
|
||||
snprintf(buf, sizeof(buf),
|
||||
"UPDATE anope_ns_alias SET display='%s' WHERE display='%s'",
|
||||
newnick, oldnick);
|
||||
db_mysql_query(buf);
|
||||
|
||||
/* Change the display on ChanServ ACCESS list */
|
||||
snprintf(buf, sizeof(buf),
|
||||
"UPDATE anope_cs_access SET display='%s' WHERE display='%s'",
|
||||
newnick, oldnick);
|
||||
db_mysql_query(buf);
|
||||
|
||||
/* Change the display on ChanServ AKICK list */
|
||||
snprintf(buf, sizeof(buf),
|
||||
"UPDATE anope_cs_access SET creator='%s' WHERE creator='%s'",
|
||||
newnick, oldnick);
|
||||
db_mysql_query(buf);
|
||||
|
||||
/* Change the display on MemoServ sent memos */
|
||||
snprintf(buf, sizeof(buf),
|
||||
"UPDATE anope_ms_info SET sender='%s' WHERE sender='%s'",
|
||||
newnick, oldnick);
|
||||
db_mysql_query(buf);
|
||||
|
||||
/* Change the display on MemoServ received memos */
|
||||
snprintf(buf, sizeof(buf),
|
||||
"UPDATE anope_ms_info SET receiver='%s' WHERE receiver='%s'",
|
||||
newnick, oldnick);
|
||||
db_mysql_query(buf);
|
||||
|
||||
/* Need to do bwords and akills */
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int rdb_cs_deluser(char *nick)
|
||||
{
|
||||
static char buf[1024];
|
||||
|
||||
#ifdef USE_MYSQL
|
||||
snprintf(buf, sizeof(buf),
|
||||
"UPDATE anope_cs_info SET successor=NULL WHERE successor='%s'",
|
||||
nick);
|
||||
db_mysql_query(buf);
|
||||
|
||||
snprintf(buf, sizeof(buf), "display='%s'", nick);
|
||||
rdb_scrub_table("anope_cs_access", buf);
|
||||
snprintf(buf, sizeof(buf), "creator='%s'", nick);
|
||||
rdb_scrub_table("anope_cs_akicks", buf);
|
||||
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int rdb_cs_delchan(ChannelInfo * ci)
|
||||
{
|
||||
static char buf[1024];
|
||||
char *channel = ci->name;
|
||||
|
||||
#ifdef USE_MYSQL
|
||||
snprintf(buf, sizeof(buf),
|
||||
"UPDATE anope_cs_info SET successor=NULL WHERE name='%s'",
|
||||
channel);
|
||||
db_mysql_query(buf);
|
||||
|
||||
snprintf(buf, sizeof(buf), "name='%s'", channel);
|
||||
rdb_scrub_table("anope_cs_info", buf);
|
||||
snprintf(buf, sizeof(buf), "receiver='%s' AND serv='CHAN'", channel);
|
||||
rdb_scrub_table("anope_ms_info", buf);
|
||||
snprintf(buf, sizeof(buf), "channel='%s'", channel);
|
||||
rdb_scrub_table("anope_cs_access", buf);
|
||||
rdb_scrub_table("anope_cs_akicks", buf);
|
||||
rdb_scrub_table("anope_cs_levels", buf);
|
||||
rdb_scrub_table("anope_cs_badwords", buf);
|
||||
if (ci->founder) {
|
||||
snprintf(buf, sizeof(buf),
|
||||
"update anope_ns_core set channelcount=channelcount-1 where display='%s'",
|
||||
ci->founder->display);
|
||||
db_mysql_query(buf);
|
||||
}
|
||||
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int rdb_cs_set_founder(char *channel, char *founder)
|
||||
{
|
||||
static char buf[1024];
|
||||
|
||||
#ifdef USE_MYSQL
|
||||
snprintf(buf, sizeof(buf),
|
||||
"UPDATE anope_cs_info SET founder='%s', successor=NULL WHERE name='%s'",
|
||||
founder, channel);
|
||||
db_mysql_query(buf);
|
||||
|
||||
snprintf(buf, sizeof(buf),
|
||||
"UPDATE anope_ns_core SET channelcount=channelcount+1 WHERE display='%s'",
|
||||
founder);
|
||||
db_mysql_query(buf);
|
||||
|
||||
/* Do i need to scrub the access list for this channel ? */
|
||||
snprintf(buf, sizeof(buf), "display='%s' AND channel='%s'", founder,
|
||||
channel);
|
||||
rdb_scrub_table("anope_cs_access", buf);
|
||||
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void rdb_save_ns_core(NickCore * nc)
|
||||
{
|
||||
|
||||
#ifdef USE_MYSQL
|
||||
db_mysql_save_ns_core(nc);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void rdb_save_ns_alias(NickAlias * na)
|
||||
{
|
||||
|
||||
#ifdef USE_MYSQL
|
||||
db_mysql_save_ns_alias(na);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void rdb_save_ns_req(NickRequest * nr)
|
||||
{
|
||||
|
||||
#ifdef USE_MYSQL
|
||||
db_mysql_save_ns_req(nr);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void rdb_save_cs_info(ChannelInfo * ci)
|
||||
{
|
||||
|
||||
#ifdef USE_MYSQL
|
||||
db_mysql_save_cs_info(ci);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void rdb_save_bs_core(BotInfo * bi)
|
||||
{
|
||||
|
||||
#ifdef USE_MYSQL
|
||||
db_mysql_save_bs_core(bi);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void rdb_save_hs_core(HostCore * hc)
|
||||
{
|
||||
|
||||
#ifdef USE_MYSQL
|
||||
db_mysql_save_hs_core(hc);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void rdb_save_os_db(unsigned int maxucnt, unsigned int maxutime,
|
||||
SList * ak, SList * sgl, SList * sql, SList * szl,
|
||||
HostCache * hc)
|
||||
{
|
||||
|
||||
#ifdef USE_MYSQL
|
||||
db_mysql_save_os_db(maxusercnt, maxusertime, ak, sgl, sql, szl, hc);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void rdb_save_news(NewsItem * ni)
|
||||
{
|
||||
|
||||
#ifdef USE_MYSQL
|
||||
db_mysql_save_news(ni);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void rdb_save_exceptions(Exception * e)
|
||||
{
|
||||
|
||||
#ifdef USE_MYSQL
|
||||
db_mysql_save_exceptions(e);
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
/* Routines for sending stuff to the network.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: send.c,v 1.11 2004/01/18 05:10:47 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "services.h"
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Send a command to the server. The two forms here are like
|
||||
* printf()/vprintf() and friends. */
|
||||
|
||||
void send_cmd(const char *source, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
vsend_cmd(source, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void vsend_cmd(const char *source, const char *fmt, va_list args)
|
||||
{
|
||||
char buf[BUFSIZE];
|
||||
|
||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
if (source) {
|
||||
sockprintf(servsock, ":%s %s\r\n", source, buf);
|
||||
if (debug)
|
||||
alog("debug: Sent: :%s %s", source, buf);
|
||||
} else {
|
||||
sockprintf(servsock, "%s\r\n", buf);
|
||||
if (debug)
|
||||
alog("debug: Sent: %s", buf);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Send out a WALLOPS (a GLOBOPS on ircd.dal). */
|
||||
|
||||
void wallops(const char *source, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char buf[BUFSIZE];
|
||||
|
||||
va_start(args, fmt);
|
||||
|
||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
#ifdef IRC_HYBRID
|
||||
send_cmd(source ? source : ServerName, "WALLOPS :%s", buf);
|
||||
#else
|
||||
send_cmd(source ? source : ServerName, "GLOBOPS :%s", buf);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Send a NOTICE from the given source to the given nick. */
|
||||
void notice(const char *source, const char *dest, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char buf[BUFSIZE];
|
||||
|
||||
va_start(args, fmt);
|
||||
|
||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
send_cmd(source, "%s %s :%s", (UsePrivmsg ? "PRIVMSG" : "NOTICE"),
|
||||
dest, buf);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void notice_user(const char *source, User * u, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char buf[BUFSIZE];
|
||||
|
||||
va_start(args, fmt);
|
||||
|
||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
send_cmd(source, "%s %s :%s",
|
||||
(UsePrivmsg && (!u->na || (u->na->nc->flags & NI_MSG)) ?
|
||||
"PRIVMSG" : "NOTICE"), u->nick, buf);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Send a NULL-terminated array of text as NOTICEs. */
|
||||
void notice_list(const char *source, const char *dest, const char **text)
|
||||
{
|
||||
while (*text) {
|
||||
/* Have to kludge around an ircII bug here: if a notice includes
|
||||
* no text, it is ignored, so we replace blank lines by lines
|
||||
* with a single space.
|
||||
*/
|
||||
if (**text)
|
||||
notice(source, dest, *text);
|
||||
else
|
||||
notice(source, dest, " ");
|
||||
text++;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Send a message in the user's selected language to the user using NOTICE. */
|
||||
void notice_lang(const char *source, User * dest, int message, ...)
|
||||
{
|
||||
va_list args;
|
||||
char buf[4096]; /* because messages can be really big */
|
||||
char *s, *t;
|
||||
const char *fmt;
|
||||
if (!dest)
|
||||
return;
|
||||
va_start(args, message);
|
||||
fmt = getstring(dest->na, message);
|
||||
if (!fmt)
|
||||
return;
|
||||
memset(buf, 0, 4096);
|
||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
s = buf;
|
||||
while (*s) {
|
||||
t = s;
|
||||
s += strcspn(s, "\n");
|
||||
if (*s)
|
||||
*s++ = 0;
|
||||
send_cmd(source, "%s %s :%s", (UsePrivmsg
|
||||
&& (!dest->na || (dest->na->nc->
|
||||
flags &
|
||||
NI_MSG)) ?
|
||||
"PRIVMSG" : "NOTICE"),
|
||||
dest->nick, *t ? t : " ");
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Like notice_lang(), but replace %S by the source. This is an ugly hack
|
||||
* to simplify letting help messages display the name of the pseudoclient
|
||||
* that's sending them.
|
||||
*/
|
||||
void notice_help(const char *source, User * dest, int message, ...)
|
||||
{
|
||||
va_list args;
|
||||
char buf[4096], buf2[4096], outbuf[BUFSIZE];
|
||||
char *s, *t;
|
||||
const char *fmt;
|
||||
|
||||
if (!dest)
|
||||
return;
|
||||
va_start(args, message);
|
||||
fmt = getstring(dest->na, message);
|
||||
if (!fmt)
|
||||
return;
|
||||
/* Some sprintf()'s eat %S or turn it into just S, so change all %S's
|
||||
* into \1\1... we assume this doesn't occur anywhere else in the
|
||||
* string. */
|
||||
strscpy(buf2, fmt, sizeof(buf2));
|
||||
strnrepl(buf2, sizeof(buf2), "%S", "\1\1");
|
||||
vsnprintf(buf, sizeof(buf), buf2, args);
|
||||
s = buf;
|
||||
while (*s) {
|
||||
t = s;
|
||||
s += strcspn(s, "\n");
|
||||
if (*s)
|
||||
*s++ = 0;
|
||||
strscpy(outbuf, t, sizeof(outbuf));
|
||||
strnrepl(outbuf, sizeof(outbuf), "\1\1", source);
|
||||
send_cmd(source, "%s %s :%s",
|
||||
(UsePrivmsg
|
||||
&& (!dest->na
|
||||
|| (dest->na->nc->
|
||||
flags & NI_MSG)) ? "PRIVMSG" : "NOTICE"),
|
||||
dest->nick, *outbuf ? outbuf : " ");
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Send a PRIVMSG from the given source to the given nick. */
|
||||
void privmsg(const char *source, const char *dest, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char buf[BUFSIZE];
|
||||
|
||||
va_start(args, fmt);
|
||||
|
||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
send_cmd(source, "PRIVMSG %s :%s", dest, buf);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
+1198
File diff suppressed because it is too large
Load Diff
+834
@@ -0,0 +1,834 @@
|
||||
/* Session Limiting functions.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: sessions.c,v 1.10 2003/07/20 01:15:50 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "services.h"
|
||||
#include "pseudo.h"
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* SESSION LIMITING
|
||||
*
|
||||
* The basic idea of session limiting is to prevent one host from having more
|
||||
* than a specified number of sessions (client connections/clones) on the
|
||||
* network at any one time. To do this we have a list of sessions and
|
||||
* exceptions. Each session structure records information about a single host,
|
||||
* including how many clients (sessions) that host has on the network. When a
|
||||
* host reaches it's session limit, no more clients from that host will be
|
||||
* allowed to connect.
|
||||
*
|
||||
* When a client connects to the network, we check to see if their host has
|
||||
* reached the default session limit per host, and thus whether it is allowed
|
||||
* any more. If it has reached the limit, we kill the connecting client; all
|
||||
* the other clients are left alone. Otherwise we simply increment the counter
|
||||
* within the session structure. When a client disconnects, we decrement the
|
||||
* counter. When the counter reaches 0, we free the session.
|
||||
*
|
||||
* Exceptions allow one to specify custom session limits for a specific host
|
||||
* or a range thereof. The first exception that the host matches is the one
|
||||
* used.
|
||||
*
|
||||
* "Session Limiting" is likely to slow down services when there are frequent
|
||||
* client connects and disconnects. The size of the exception list can also
|
||||
* play a large role in this performance decrease. It is therefore recommened
|
||||
* that you keep the number of exceptions to a minimum. A very simple hashing
|
||||
* method is currently used to store the list of sessions. I'm sure there is
|
||||
* room for improvement and optimisation of this, along with the storage of
|
||||
* exceptions. Comments and suggestions are more than welcome!
|
||||
*
|
||||
* -TheShadow (02 April 1999)
|
||||
*/
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
typedef struct session_ Session;
|
||||
struct session_ {
|
||||
Session *prev, *next;
|
||||
char *host;
|
||||
int count; /* Number of clients with this host */
|
||||
int hits; /* Number of subsequent kills for a host */
|
||||
};
|
||||
|
||||
/* I'm sure there is a better way to hash the list of hosts for which we are
|
||||
* storing session information. This should be sufficient for the mean time.
|
||||
* -TheShadow */
|
||||
|
||||
#define HASH(host) (((host)[0]&31)<<5 | ((host)[1]&31))
|
||||
|
||||
static Session *sessionlist[1024];
|
||||
static int32 nsessions = 0;
|
||||
|
||||
static Exception *exceptions = NULL;
|
||||
static int16 nexceptions = 0;
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static Session *findsession(const char *host);
|
||||
|
||||
static Exception *find_host_exception(const char *host);
|
||||
static int exception_add(const char *mask, const int limit,
|
||||
const char *reason, const char *who,
|
||||
const time_t expires);
|
||||
|
||||
/*************************************************************************/
|
||||
/****************************** Statistics *******************************/
|
||||
/*************************************************************************/
|
||||
|
||||
void get_session_stats(long *nrec, long *memuse)
|
||||
{
|
||||
Session *session;
|
||||
long mem;
|
||||
int i;
|
||||
|
||||
mem = sizeof(Session) * nsessions;
|
||||
for (i = 0; i < 1024; i++) {
|
||||
for (session = sessionlist[i]; session; session = session->next) {
|
||||
mem += strlen(session->host) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
*nrec = nsessions;
|
||||
*memuse = mem;
|
||||
}
|
||||
|
||||
void get_exception_stats(long *nrec, long *memuse)
|
||||
{
|
||||
long mem;
|
||||
int i;
|
||||
|
||||
mem = sizeof(Exception) * nexceptions;
|
||||
for (i = 0; i < nexceptions; i++) {
|
||||
mem += strlen(exceptions[i].mask) + 1;
|
||||
mem += strlen(exceptions[i].reason) + 1;
|
||||
}
|
||||
*nrec = nexceptions;
|
||||
*memuse = mem;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/************************* Session List Display **************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* Syntax: SESSION LIST threshold
|
||||
* Lists all sessions with atleast threshold clients.
|
||||
* The threshold value must be greater than 1. This is to prevent
|
||||
* accidental listing of the large number of single client sessions.
|
||||
*
|
||||
* Syntax: SESSION VIEW host
|
||||
* Displays detailed session information about the supplied host.
|
||||
*/
|
||||
|
||||
int do_session(User * u)
|
||||
{
|
||||
Session *session;
|
||||
Exception *exception;
|
||||
char *cmd = strtok(NULL, " ");
|
||||
char *param1 = strtok(NULL, " ");
|
||||
int mincount;
|
||||
int i;
|
||||
|
||||
if (!LimitSessions) {
|
||||
notice_lang(s_OperServ, u, OPER_SESSION_DISABLED);
|
||||
return MOD_CONT;
|
||||
}
|
||||
|
||||
if (!cmd)
|
||||
cmd = "";
|
||||
|
||||
if (stricmp(cmd, "LIST") == 0) {
|
||||
if (!param1) {
|
||||
syntax_error(s_OperServ, u, "SESSION",
|
||||
OPER_SESSION_LIST_SYNTAX);
|
||||
|
||||
} else if ((mincount = atoi(param1)) <= 1) {
|
||||
notice_lang(s_OperServ, u, OPER_SESSION_INVALID_THRESHOLD);
|
||||
|
||||
} else {
|
||||
notice_lang(s_OperServ, u, OPER_SESSION_LIST_HEADER, mincount);
|
||||
notice_lang(s_OperServ, u, OPER_SESSION_LIST_COLHEAD);
|
||||
for (i = 0; i < 1024; i++) {
|
||||
for (session = sessionlist[i]; session;
|
||||
session = session->next) {
|
||||
if (session->count >= mincount)
|
||||
notice_lang(s_OperServ, u,
|
||||
OPER_SESSION_LIST_FORMAT,
|
||||
session->count, session->host);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (stricmp(cmd, "VIEW") == 0) {
|
||||
if (!param1) {
|
||||
syntax_error(s_OperServ, u, "SESSION",
|
||||
OPER_SESSION_VIEW_SYNTAX);
|
||||
|
||||
} else {
|
||||
session = findsession(param1);
|
||||
if (!session) {
|
||||
notice_lang(s_OperServ, u, OPER_SESSION_NOT_FOUND, param1);
|
||||
} else {
|
||||
exception = find_host_exception(param1);
|
||||
|
||||
notice_lang(s_OperServ, u, OPER_SESSION_VIEW_FORMAT,
|
||||
param1, session->count,
|
||||
exception ? exception->
|
||||
limit : DefSessionLimit);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
syntax_error(s_OperServ, u, "SESSION", OPER_SESSION_SYNTAX);
|
||||
}
|
||||
return MOD_CONT;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/********************* Internal Session Functions ************************/
|
||||
/*************************************************************************/
|
||||
|
||||
static Session *findsession(const char *host)
|
||||
{
|
||||
Session *session;
|
||||
int i;
|
||||
|
||||
if (!host)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < 1024; i++) {
|
||||
for (session = sessionlist[i]; session; session = session->next) {
|
||||
if (stricmp(host, session->host) == 0) {
|
||||
return session;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Attempt to add a host to the session list. If the addition of the new host
|
||||
* causes the the session limit to be exceeded, kill the connecting user.
|
||||
* Returns 1 if the host was added or 0 if the user was killed.
|
||||
*/
|
||||
|
||||
int add_session(const char *nick, const char *host)
|
||||
{
|
||||
Session *session, **list;
|
||||
Exception *exception;
|
||||
int sessionlimit = 0;
|
||||
|
||||
session = findsession(host);
|
||||
|
||||
if (session) {
|
||||
exception = find_host_exception(host);
|
||||
if (checkDefCon(DEFCON_REDUCE_SESSION)) {
|
||||
sessionlimit =
|
||||
exception ? exception->limit : DefConSessionLimit;
|
||||
} else {
|
||||
sessionlimit = exception ? exception->limit : DefSessionLimit;
|
||||
}
|
||||
|
||||
if (sessionlimit != 0 && session->count >= sessionlimit) {
|
||||
if (SessionLimitExceeded)
|
||||
notice(s_OperServ, nick, SessionLimitExceeded, host);
|
||||
if (SessionLimitDetailsLoc)
|
||||
notice(s_OperServ, nick, SessionLimitDetailsLoc);
|
||||
|
||||
/* We don't use kill_user() because a user stucture has not yet
|
||||
* been created. Simply kill the user. -TheShadow
|
||||
*/
|
||||
#ifdef IRC_BAHAMUT
|
||||
send_cmd(NULL, "SVSKILL %s :Session limit exceeded", nick);
|
||||
#else
|
||||
send_cmd(s_OperServ, "KILL %s :%s (Session limit exceeded)",
|
||||
nick, s_OperServ);
|
||||
#endif
|
||||
session->hits++;
|
||||
if (MaxSessionKill && session->hits >= MaxSessionKill) {
|
||||
char akillmask[BUFSIZE];
|
||||
snprintf(akillmask, sizeof(akillmask), "*@%s", host);
|
||||
add_akill(NULL, akillmask, s_OperServ,
|
||||
time(NULL) + SessionAutoKillExpiry,
|
||||
"Session limit exceeded");
|
||||
wallops(s_OperServ,
|
||||
"Added a temporary AKILL for \2%s\2 due to excessive connections",
|
||||
akillmask);
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
session->count++;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
nsessions++;
|
||||
session = scalloc(sizeof(Session), 1);
|
||||
session->host = sstrdup(host);
|
||||
list = &sessionlist[HASH(session->host)];
|
||||
session->next = *list;
|
||||
if (*list)
|
||||
(*list)->prev = session;
|
||||
*list = session;
|
||||
session->count = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void del_session(const char *host)
|
||||
{
|
||||
Session *session;
|
||||
|
||||
if (debug >= 2)
|
||||
alog("debug: del_session() called");
|
||||
|
||||
session = findsession(host);
|
||||
|
||||
if (!session) {
|
||||
wallops(s_OperServ,
|
||||
"WARNING: Tried to delete non-existant session: \2%s",
|
||||
host);
|
||||
alog("session: Tried to delete non-existant session: %s", host);
|
||||
return;
|
||||
}
|
||||
|
||||
if (session->count > 1) {
|
||||
session->count--;
|
||||
return;
|
||||
}
|
||||
|
||||
if (session->prev)
|
||||
session->prev->next = session->next;
|
||||
else
|
||||
sessionlist[HASH(session->host)] = session->next;
|
||||
if (session->next)
|
||||
session->next->prev = session->prev;
|
||||
|
||||
if (debug >= 2)
|
||||
alog("debug: del_session(): free session structure");
|
||||
|
||||
free(session->host);
|
||||
free(session);
|
||||
|
||||
nsessions--;
|
||||
|
||||
if (debug >= 2)
|
||||
alog("debug: del_session() done");
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/********************** Internal Exception Functions *********************/
|
||||
/*************************************************************************/
|
||||
|
||||
void expire_exceptions(void)
|
||||
{
|
||||
int i;
|
||||
time_t now = time(NULL);
|
||||
|
||||
for (i = 0; i < nexceptions; i++) {
|
||||
if (exceptions[i].expires == 0 || exceptions[i].expires > now)
|
||||
continue;
|
||||
if (WallExceptionExpire)
|
||||
wallops(s_OperServ,
|
||||
"Session limit exception for %s has expired.",
|
||||
exceptions[i].mask);
|
||||
free(exceptions[i].mask);
|
||||
free(exceptions[i].reason);
|
||||
nexceptions--;
|
||||
memmove(exceptions + i, exceptions + i + 1,
|
||||
sizeof(Exception) * (nexceptions - i));
|
||||
exceptions = srealloc(exceptions, sizeof(Exception) * nexceptions);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the first exception this host matches and return it. */
|
||||
|
||||
Exception *find_host_exception(const char *host)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nexceptions; i++) {
|
||||
if (match_wild_nocase(exceptions[i].mask, host)) {
|
||||
return &exceptions[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*********************** Exception Load/Save *****************************/
|
||||
/*************************************************************************/
|
||||
|
||||
#define SAFE(x) do { \
|
||||
if ((x) < 0) { \
|
||||
if (!forceload) \
|
||||
fatal("Read error on %s", ExceptionDBName); \
|
||||
nexceptions = i; \
|
||||
break; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
void load_exceptions()
|
||||
{
|
||||
dbFILE *f;
|
||||
int i;
|
||||
int16 n;
|
||||
int16 tmp16;
|
||||
int32 tmp32;
|
||||
|
||||
if (!
|
||||
(f = open_db(s_OperServ, ExceptionDBName, "r", EXCEPTION_VERSION)))
|
||||
return;
|
||||
switch (i = get_file_version(f)) {
|
||||
case 9:
|
||||
case 8:
|
||||
case 7:
|
||||
SAFE(read_int16(&n, f));
|
||||
nexceptions = n;
|
||||
exceptions = scalloc(sizeof(Exception) * nexceptions, 1);
|
||||
if (!nexceptions) {
|
||||
close_db(f);
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < nexceptions; i++) {
|
||||
SAFE(read_string(&exceptions[i].mask, f));
|
||||
SAFE(read_int16(&tmp16, f));
|
||||
exceptions[i].limit = tmp16;
|
||||
SAFE(read_buffer(exceptions[i].who, f));
|
||||
SAFE(read_string(&exceptions[i].reason, f));
|
||||
SAFE(read_int32(&tmp32, f));
|
||||
exceptions[i].time = tmp32;
|
||||
SAFE(read_int32(&tmp32, f));
|
||||
exceptions[i].expires = tmp32;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fatal("Unsupported version (%d) on %s", i, ExceptionDBName);
|
||||
} /* switch (ver) */
|
||||
|
||||
close_db(f);
|
||||
}
|
||||
|
||||
#undef SAFE
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#define SAFE(x) do { \
|
||||
if ((x) < 0) { \
|
||||
restore_db(f); \
|
||||
log_perror("Write error on %s", ExceptionDBName); \
|
||||
if (time(NULL) - lastwarn > WarningTimeout) { \
|
||||
wallops(NULL, "Write error on %s: %s", ExceptionDBName, \
|
||||
strerror(errno)); \
|
||||
lastwarn = time(NULL); \
|
||||
} \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
void save_exceptions()
|
||||
{
|
||||
dbFILE *f;
|
||||
int i;
|
||||
static time_t lastwarn = 0;
|
||||
|
||||
if (!
|
||||
(f = open_db(s_OperServ, ExceptionDBName, "w", EXCEPTION_VERSION)))
|
||||
return;
|
||||
SAFE(write_int16(nexceptions, f));
|
||||
for (i = 0; i < nexceptions; i++) {
|
||||
SAFE(write_string(exceptions[i].mask, f));
|
||||
SAFE(write_int16(exceptions[i].limit, f));
|
||||
SAFE(write_buffer(exceptions[i].who, f));
|
||||
SAFE(write_string(exceptions[i].reason, f));
|
||||
SAFE(write_int32(exceptions[i].time, f));
|
||||
SAFE(write_int32(exceptions[i].expires, f));
|
||||
}
|
||||
close_db(f);
|
||||
}
|
||||
|
||||
#undef SAFE
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void save_rdb_exceptions()
|
||||
{
|
||||
#ifdef USE_RDB
|
||||
int i;
|
||||
Exception *e;
|
||||
|
||||
if (!rdb_open())
|
||||
return;
|
||||
rdb_clear_table("anope_os_exceptions");
|
||||
for (i = 0; i < nexceptions; i++) {
|
||||
e = &exceptions[i];
|
||||
rdb_save_exceptions(e);
|
||||
}
|
||||
rdb_close();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/************************ Exception Manipulation *************************/
|
||||
/*************************************************************************/
|
||||
|
||||
static int exception_add(const char *mask, const int limit,
|
||||
const char *reason, const char *who,
|
||||
const time_t expires)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Check if an exception already exists for this mask */
|
||||
for (i = 0; i < nexceptions; i++)
|
||||
if (stricmp(mask, exceptions[i].mask) == 0)
|
||||
return 0;
|
||||
|
||||
nexceptions++;
|
||||
exceptions = srealloc(exceptions, sizeof(Exception) * nexceptions);
|
||||
|
||||
exceptions[nexceptions - 1].mask = sstrdup(mask);
|
||||
exceptions[nexceptions - 1].limit = limit;
|
||||
exceptions[nexceptions - 1].reason = sstrdup(reason);
|
||||
exceptions[nexceptions - 1].time = time(NULL);
|
||||
strscpy(exceptions[nexceptions - 1].who, who, NICKMAX);
|
||||
exceptions[nexceptions - 1].expires = expires;
|
||||
exceptions[nexceptions - 1].num = nexceptions - 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static int exception_del(const int index)
|
||||
{
|
||||
if (index < 0 || index >= nexceptions)
|
||||
return 0;
|
||||
|
||||
free(exceptions[index].mask);
|
||||
free(exceptions[index].reason);
|
||||
nexceptions--;
|
||||
memmove(exceptions + index, exceptions + index + 1,
|
||||
sizeof(Exception) * (nexceptions - index));
|
||||
exceptions = srealloc(exceptions, sizeof(Exception) * nexceptions);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* We use the "num" property to keep track of the position of each exception
|
||||
* when deleting using ranges. This is because an exception's position changes
|
||||
* as others are deleted. The positions will be recalculated once the process
|
||||
* is complete. -TheShadow
|
||||
*/
|
||||
|
||||
static int exception_del_callback(User * u, int num, va_list args)
|
||||
{
|
||||
int i;
|
||||
int *last = va_arg(args, int *);
|
||||
|
||||
*last = num;
|
||||
for (i = 0; i < nexceptions; i++) {
|
||||
if (num - 1 == exceptions[i].num)
|
||||
break;
|
||||
}
|
||||
if (i < nexceptions)
|
||||
return exception_del(i);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int exception_list(User * u, const int index, int *sent_header)
|
||||
{
|
||||
if (index < 0 || index >= nexceptions)
|
||||
return 0;
|
||||
if (!*sent_header) {
|
||||
notice_lang(s_OperServ, u, OPER_EXCEPTION_LIST_HEADER);
|
||||
notice_lang(s_OperServ, u, OPER_EXCEPTION_LIST_COLHEAD);
|
||||
*sent_header = 1;
|
||||
}
|
||||
notice_lang(s_OperServ, u, OPER_EXCEPTION_LIST_FORMAT, index + 1,
|
||||
exceptions[index].limit, exceptions[index].mask);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int exception_list_callback(User * u, int num, va_list args)
|
||||
{
|
||||
int *sent_header = va_arg(args, int *);
|
||||
|
||||
return exception_list(u, num - 1, sent_header);
|
||||
}
|
||||
|
||||
static int exception_view(User * u, const int index, int *sent_header)
|
||||
{
|
||||
char timebuf[32], expirebuf[256];
|
||||
struct tm tm;
|
||||
time_t t = time(NULL);
|
||||
|
||||
if (index < 0 || index >= nexceptions)
|
||||
return 0;
|
||||
if (!*sent_header) {
|
||||
notice_lang(s_OperServ, u, OPER_EXCEPTION_LIST_HEADER);
|
||||
*sent_header = 1;
|
||||
}
|
||||
|
||||
tm = *localtime(exceptions[index].time ? &exceptions[index].time : &t);
|
||||
strftime_lang(timebuf, sizeof(timebuf),
|
||||
u, STRFTIME_SHORT_DATE_FORMAT, &tm);
|
||||
|
||||
expire_left(u->na, expirebuf, sizeof(expirebuf),
|
||||
exceptions[index].expires);
|
||||
|
||||
notice_lang(s_OperServ, u, OPER_EXCEPTION_VIEW_FORMAT,
|
||||
index + 1, exceptions[index].mask,
|
||||
*exceptions[index].who ?
|
||||
exceptions[index].who : "<unknown>",
|
||||
timebuf, expirebuf, exceptions[index].limit,
|
||||
exceptions[index].reason);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int exception_view_callback(User * u, int num, va_list args)
|
||||
{
|
||||
int *sent_header = va_arg(args, int *);
|
||||
|
||||
return exception_view(u, num - 1, sent_header);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Syntax: EXCEPTION ADD [+expiry] mask limit reason
|
||||
* Adds mask to the exception list with limit as the maximum session
|
||||
* limit and +expiry as an optional expiry time.
|
||||
*
|
||||
* Syntax: EXCEPTION DEL mask
|
||||
* Deletes the first exception that matches mask exactly.
|
||||
*
|
||||
* Syntax: EXCEPTION LIST [mask]
|
||||
* Lists all exceptions or those matching mask.
|
||||
*
|
||||
* Syntax: EXCEPTION VIEW [mask]
|
||||
* Displays detailed information about each exception or those matching
|
||||
* mask.
|
||||
*
|
||||
* Syntax: EXCEPTION MOVE num position
|
||||
* Moves the exception at position num to position.
|
||||
*/
|
||||
|
||||
int do_exception(User * u)
|
||||
{
|
||||
char *cmd = strtok(NULL, " ");
|
||||
char *mask, *reason, *expiry, *limitstr;
|
||||
int limit, expires;
|
||||
int i;
|
||||
|
||||
if (!LimitSessions) {
|
||||
notice_lang(s_OperServ, u, OPER_EXCEPTION_DISABLED);
|
||||
return MOD_CONT;
|
||||
}
|
||||
|
||||
if (!cmd)
|
||||
cmd = "";
|
||||
|
||||
if (stricmp(cmd, "ADD") == 0) {
|
||||
if (nexceptions >= 32767) {
|
||||
notice_lang(s_OperServ, u, OPER_EXCEPTION_TOO_MANY);
|
||||
return MOD_CONT;
|
||||
}
|
||||
|
||||
mask = strtok(NULL, " ");
|
||||
if (mask && *mask == '+') {
|
||||
expiry = mask;
|
||||
mask = strtok(NULL, " ");
|
||||
} else {
|
||||
expiry = NULL;
|
||||
}
|
||||
limitstr = strtok(NULL, " ");
|
||||
reason = strtok(NULL, "");
|
||||
|
||||
if (!reason) {
|
||||
syntax_error(s_OperServ, u, "EXCEPTION",
|
||||
OPER_EXCEPTION_ADD_SYNTAX);
|
||||
return MOD_CONT;
|
||||
}
|
||||
|
||||
expires = expiry ? dotime(expiry) : ExceptionExpiry;
|
||||
if (expires < 0) {
|
||||
notice_lang(s_OperServ, u, BAD_EXPIRY_TIME);
|
||||
return MOD_CONT;
|
||||
} else if (expires > 0) {
|
||||
expires += time(NULL);
|
||||
}
|
||||
|
||||
limit = (limitstr && isdigit(*limitstr)) ? atoi(limitstr) : -1;
|
||||
|
||||
if (limit < 0 || limit > MaxSessionLimit) {
|
||||
notice_lang(s_OperServ, u, OPER_EXCEPTION_INVALID_LIMIT,
|
||||
MaxSessionLimit);
|
||||
return MOD_CONT;
|
||||
|
||||
} else {
|
||||
if (strchr(mask, '!') || strchr(mask, '@')) {
|
||||
notice_lang(s_OperServ, u,
|
||||
OPER_EXCEPTION_INVALID_HOSTMASK);
|
||||
return MOD_CONT;
|
||||
}
|
||||
|
||||
if (exception_add(mask, limit, reason, u->nick, expires))
|
||||
notice_lang(s_OperServ, u, OPER_EXCEPTION_ADDED, mask,
|
||||
limit);
|
||||
else
|
||||
notice_lang(s_OperServ, u, OPER_EXCEPTION_ALREADY_PRESENT,
|
||||
mask, limit);
|
||||
if (readonly)
|
||||
notice_lang(s_OperServ, u, READ_ONLY_MODE);
|
||||
}
|
||||
} else if (stricmp(cmd, "DEL") == 0) {
|
||||
mask = strtok(NULL, " ");
|
||||
|
||||
if (!mask) {
|
||||
syntax_error(s_OperServ, u, "EXCEPTION",
|
||||
OPER_EXCEPTION_DEL_SYNTAX);
|
||||
return MOD_CONT;
|
||||
}
|
||||
|
||||
if (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask)) {
|
||||
int count, deleted, last = -1;
|
||||
deleted =
|
||||
process_numlist(mask, &count, exception_del_callback, u,
|
||||
&last);
|
||||
if (!deleted) {
|
||||
if (count == 1) {
|
||||
notice_lang(s_OperServ, u,
|
||||
OPER_EXCEPTION_NO_SUCH_ENTRY, last);
|
||||
} else {
|
||||
notice_lang(s_OperServ, u, OPER_EXCEPTION_NO_MATCH);
|
||||
}
|
||||
} else if (deleted == 1) {
|
||||
notice_lang(s_OperServ, u, OPER_EXCEPTION_DELETED_ONE);
|
||||
} else {
|
||||
notice_lang(s_OperServ, u, OPER_EXCEPTION_DELETED_SEVERAL,
|
||||
deleted);
|
||||
}
|
||||
} else {
|
||||
int deleted = 0;
|
||||
|
||||
for (i = 0; i < nexceptions; i++) {
|
||||
if (stricmp(mask, exceptions[i].mask) == 0) {
|
||||
exception_del(i);
|
||||
notice_lang(s_OperServ, u, OPER_EXCEPTION_DELETED,
|
||||
mask);
|
||||
deleted = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!deleted && i == nexceptions)
|
||||
notice_lang(s_OperServ, u, OPER_EXCEPTION_NOT_FOUND, mask);
|
||||
}
|
||||
|
||||
/* Renumber the exception list. I don't believe in having holes in
|
||||
* lists - it makes code more complex, harder to debug and we end up
|
||||
* with huge index numbers. Imho, fixed numbering is only beneficial
|
||||
* when one doesn't have range capable manipulation. -TheShadow */
|
||||
|
||||
for (i = 0; i < nexceptions; i++)
|
||||
exceptions[i].num = i;
|
||||
|
||||
if (readonly)
|
||||
notice_lang(s_OperServ, u, READ_ONLY_MODE);
|
||||
|
||||
} else if (stricmp(cmd, "MOVE") == 0) {
|
||||
Exception *exception;
|
||||
char *n1str = strtok(NULL, " "); /* From position */
|
||||
char *n2str = strtok(NULL, " "); /* To position */
|
||||
int n1, n2;
|
||||
|
||||
if (!n2str) {
|
||||
syntax_error(s_OperServ, u, "EXCEPTION",
|
||||
OPER_EXCEPTION_MOVE_SYNTAX);
|
||||
return MOD_CONT;
|
||||
}
|
||||
|
||||
n1 = atoi(n1str) - 1;
|
||||
n2 = atoi(n2str) - 1;
|
||||
|
||||
if ((n1 >= 0 && n1 < nexceptions) && (n2 >= 0 && n2 < nexceptions)
|
||||
&& (n1 != n2)) {
|
||||
exception = scalloc(sizeof(Exception), 1);
|
||||
memcpy(exception, &exceptions[n1], sizeof(Exception));
|
||||
|
||||
if (n1 < n2) {
|
||||
/* Shift upwards */
|
||||
memmove(&exceptions[n1], &exceptions[n1 + 1],
|
||||
sizeof(Exception) * (n2 - n1));
|
||||
memmove(&exceptions[n2], exception, sizeof(Exception));
|
||||
} else {
|
||||
/* Shift downwards */
|
||||
memmove(&exceptions[n2 + 1], &exceptions[n2],
|
||||
sizeof(Exception) * (n1 - n2));
|
||||
memmove(&exceptions[n2], exception, sizeof(Exception));
|
||||
}
|
||||
|
||||
free(exception);
|
||||
|
||||
notice_lang(s_OperServ, u, OPER_EXCEPTION_MOVED,
|
||||
exceptions[n1].mask, n1 + 1, n2 + 1);
|
||||
|
||||
/* Renumber the exception list. See the DEL block above for why. */
|
||||
for (i = 0; i < nexceptions; i++)
|
||||
exceptions[i].num = i;
|
||||
|
||||
if (readonly)
|
||||
notice_lang(s_OperServ, u, READ_ONLY_MODE);
|
||||
} else {
|
||||
syntax_error(s_OperServ, u, "EXCEPTION",
|
||||
OPER_EXCEPTION_MOVE_SYNTAX);
|
||||
}
|
||||
} else if (stricmp(cmd, "LIST") == 0) {
|
||||
int sent_header = 0;
|
||||
expire_exceptions();
|
||||
mask = strtok(NULL, " ");
|
||||
if (mask && strspn(mask, "1234567890,-") == strlen(mask)) {
|
||||
process_numlist(mask, NULL, exception_list_callback, u,
|
||||
&sent_header);
|
||||
} else {
|
||||
for (i = 0; i < nexceptions; i++) {
|
||||
if (!mask || match_wild_nocase(mask, exceptions[i].mask))
|
||||
exception_list(u, i, &sent_header);
|
||||
}
|
||||
}
|
||||
if (!sent_header)
|
||||
notice_lang(s_OperServ, u, OPER_EXCEPTION_NO_MATCH);
|
||||
|
||||
} else if (stricmp(cmd, "VIEW") == 0) {
|
||||
int sent_header = 0;
|
||||
expire_exceptions();
|
||||
mask = strtok(NULL, " ");
|
||||
if (mask && strspn(mask, "1234567890,-") == strlen(mask)) {
|
||||
process_numlist(mask, NULL, exception_view_callback, u,
|
||||
&sent_header);
|
||||
} else {
|
||||
for (i = 0; i < nexceptions; i++) {
|
||||
if (!mask || match_wild_nocase(mask, exceptions[i].mask))
|
||||
exception_view(u, i, &sent_header);
|
||||
}
|
||||
}
|
||||
if (!sent_header)
|
||||
notice_lang(s_OperServ, u, OPER_EXCEPTION_NO_MATCH);
|
||||
|
||||
} else {
|
||||
syntax_error(s_OperServ, u, "EXCEPTION", OPER_EXCEPTION_SYNTAX);
|
||||
}
|
||||
return MOD_CONT;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
@@ -0,0 +1,325 @@
|
||||
/* Services list handler implementation.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: slist.c,v 1.6 2003/07/20 01:15:50 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "services.h"
|
||||
#include "slist.h"
|
||||
|
||||
static SListOpts slist_defopts = { 0, NULL, NULL, NULL };
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Adds a pointer to the list. Returns the index of the new item.
|
||||
Returns -2 if there are too many items in the list, -3 if the
|
||||
item already exists when the flags of the list contain SLISTF_NODUP. */
|
||||
|
||||
int slist_add(SList * slist, void *item)
|
||||
{
|
||||
if (slist->limit != 0 && slist->count >= slist->limit)
|
||||
return -2;
|
||||
if (slist->opts && (slist->opts->flags & SLISTF_NODUP)
|
||||
&& slist_indexof(slist, item) != -1)
|
||||
return -3;
|
||||
if (slist->capacity == slist->count)
|
||||
slist_setcapacity(slist, slist->capacity + 1);
|
||||
|
||||
if (slist->opts && (slist->opts->flags & SLISTF_SORT)
|
||||
&& slist->opts->compareitem) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < slist->count; i++) {
|
||||
if (slist->opts->compareitem(slist, item, slist->list[i]) <= 0) {
|
||||
memmove(&slist->list[i + 1], &slist->list[i],
|
||||
sizeof(void *) * (slist->count - i));
|
||||
slist->list[i] = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == slist->count)
|
||||
slist->list[slist->count] = item;
|
||||
} else {
|
||||
slist->list[slist->count] = item;
|
||||
}
|
||||
|
||||
return slist->count++;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Clears the list. If free is 1, the freeitem function will be called
|
||||
* for each item before clearing.
|
||||
*/
|
||||
|
||||
void slist_clear(SList * slist, int mustfree)
|
||||
{
|
||||
if (mustfree && slist->opts && slist->opts->freeitem && slist->count) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < slist->count; i++)
|
||||
if (slist->list[i])
|
||||
slist->opts->freeitem(slist, slist->list[i]);
|
||||
}
|
||||
|
||||
if (slist->list) {
|
||||
free(slist->list);
|
||||
slist->list = NULL;
|
||||
}
|
||||
slist->capacity = 0;
|
||||
slist->count = 0;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Deletes an item from the list, by index. Returns 1 if successful,
|
||||
0 otherwise. */
|
||||
|
||||
int slist_delete(SList * slist, int index)
|
||||
{
|
||||
/* Range check */
|
||||
if (index >= slist->count)
|
||||
return 0;
|
||||
|
||||
if (slist->list[index] && slist->opts && slist->opts->freeitem)
|
||||
slist->opts->freeitem(slist, slist->list[index]);
|
||||
|
||||
slist->list[index] = NULL;
|
||||
slist->count--;
|
||||
|
||||
if (index < slist->count)
|
||||
memmove(&slist->list[index], &slist->list[index + 1],
|
||||
sizeof(void *) * (slist->count - index));
|
||||
|
||||
slist_setcapacity(slist, slist->capacity - 1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Deletes a range of entries. Return -1 if the permission was denied,
|
||||
* 0 if no records were deleted, or the number of records deleted
|
||||
*/
|
||||
|
||||
int slist_delete_range(SList * slist, char *range, slist_delcheckcb_t cb,
|
||||
...)
|
||||
{
|
||||
int count = 0, i, n1, n2;
|
||||
va_list args;
|
||||
|
||||
va_start(args, cb);
|
||||
|
||||
for (;;) {
|
||||
n1 = n2 = strtol(range, (char **) &range, 10);
|
||||
range += strcspn(range, "0123456789,-");
|
||||
|
||||
if (*range == '-') {
|
||||
range++;
|
||||
range += strcspn(range, "0123456789,");
|
||||
if (isdigit(*range)) {
|
||||
n2 = strtol(range, (char **) &range, 10);
|
||||
range += strcspn(range, "0123456789,-");
|
||||
}
|
||||
}
|
||||
|
||||
for (i = n1; i <= n2 && i > 0 && i <= slist->count; i++) {
|
||||
if (!slist->list[i - 1])
|
||||
continue;
|
||||
if (cb && !cb(slist, slist->list[i - 1], args))
|
||||
return -1;
|
||||
|
||||
if (slist->opts && slist->opts->freeitem)
|
||||
slist->opts->freeitem(slist, slist->list[i - 1]);
|
||||
slist->list[i - 1] = NULL;
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
range += strcspn(range, ",");
|
||||
if (*range)
|
||||
range++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/* We only really delete the items from the list after having processed
|
||||
* everything because it would change the position of the items in the
|
||||
* list otherwise.
|
||||
*/
|
||||
slist_pack(slist);
|
||||
|
||||
va_end(args);
|
||||
return count;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Enumerates all entries of the list. If range is not NULL, will only
|
||||
* enumerate entries that are in the range. Returns the total number
|
||||
* of entries enumerated.
|
||||
*/
|
||||
|
||||
int slist_enum(SList * slist, char *range, slist_enumcb_t cb, ...)
|
||||
{
|
||||
int count = 0, i, res;
|
||||
va_list args;
|
||||
|
||||
va_start(args, cb);
|
||||
|
||||
if (!range) {
|
||||
for (i = 0; i < slist->count; i++) {
|
||||
if (!slist->list[i]) {
|
||||
alog("SList: warning: NULL pointer in the list (?)");
|
||||
continue;
|
||||
}
|
||||
|
||||
res = cb(slist, i + 1, slist->list[i], args);
|
||||
if (res < 0)
|
||||
break;
|
||||
count += res;
|
||||
}
|
||||
} else {
|
||||
int n1, n2;
|
||||
|
||||
for (;;) {
|
||||
res = 0;
|
||||
n1 = n2 = strtol(range, (char **) &range, 10);
|
||||
range += strcspn(range, "0123456789,-");
|
||||
if (*range == '-') {
|
||||
range++;
|
||||
range += strcspn(range, "0123456789,");
|
||||
if (isdigit(*range)) {
|
||||
n2 = strtol(range, (char **) &range, 10);
|
||||
range += strcspn(range, "0123456789,-");
|
||||
}
|
||||
}
|
||||
for (i = n1; i <= n2 && i > 0 && i <= slist->count; i++) {
|
||||
if (!slist->list[i - 1]) {
|
||||
alog("SList: warning: NULL pointer in the list (?)");
|
||||
continue;
|
||||
}
|
||||
|
||||
res = cb(slist, i, slist->list[i - 1], args);
|
||||
if (res < 0)
|
||||
break;
|
||||
count += res;
|
||||
}
|
||||
if (res < -1)
|
||||
break;
|
||||
range += strcspn(range, ",");
|
||||
if (*range)
|
||||
range++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Determines whether the list is full. */
|
||||
|
||||
int slist_full(SList * slist)
|
||||
{
|
||||
if (slist->limit != 0 && slist->count >= slist->limit)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Initialization of the list. */
|
||||
|
||||
void slist_init(SList * slist)
|
||||
{
|
||||
memset(slist, 0, sizeof(SList));
|
||||
slist->limit = SLIST_DEFAULT_LIMIT;
|
||||
slist->opts = &slist_defopts;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Returns the index of an item in the list, -1 if inexistant. */
|
||||
|
||||
int slist_indexof(SList * slist, void *item)
|
||||
{
|
||||
int16 i;
|
||||
void *entry;
|
||||
|
||||
if (slist->count == 0)
|
||||
return -1;
|
||||
|
||||
for (i = 0, entry = slist->list[0]; i < slist->count;
|
||||
i++, entry = slist->list[i]) {
|
||||
if ((slist->opts
|
||||
&& slist->opts->isequal) ? (slist->opts->isequal(slist, item,
|
||||
entry))
|
||||
: (item == entry))
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Removes all NULL pointers from the list. */
|
||||
|
||||
void slist_pack(SList * slist)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = slist->count - 1; i >= 0; i--)
|
||||
if (!slist->list[i])
|
||||
slist_delete(slist, i);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Removes a specific item from the list. Returns the old index of the
|
||||
deleted item, or -1 if the item was not found. */
|
||||
|
||||
int slist_remove(SList * slist, void *item)
|
||||
{
|
||||
int index = slist_indexof(slist, item);
|
||||
if (index == -1)
|
||||
return -1;
|
||||
slist_delete(slist, index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Sets the maximum capacity of the list */
|
||||
|
||||
int slist_setcapacity(SList * slist, int16 capacity)
|
||||
{
|
||||
if (slist->capacity == capacity)
|
||||
return 1;
|
||||
slist->capacity = capacity;
|
||||
if (slist->capacity)
|
||||
slist->list =
|
||||
srealloc(slist->list, sizeof(void *) * slist->capacity);
|
||||
else {
|
||||
free(slist->list);
|
||||
slist->list = NULL;
|
||||
}
|
||||
if (slist->capacity < slist->count)
|
||||
slist->count = slist->capacity;
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/* Header for Services list handler.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: slist.h,v 1.4 2003/07/20 01:15:50 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SLIST_H
|
||||
#define SLIST_H
|
||||
|
||||
typedef struct slist_ SList;
|
||||
typedef struct slistopts_ SListOpts;
|
||||
|
||||
struct slist_ {
|
||||
void **list;
|
||||
|
||||
int16 count; /* Total entries of the list */
|
||||
int16 capacity; /* Capacity of the list */
|
||||
int16 limit; /* Maximum possible entries on the list */
|
||||
|
||||
SListOpts *opts;
|
||||
};
|
||||
|
||||
struct slistopts_ {
|
||||
int32 flags; /* Flags for the list. See below. */
|
||||
|
||||
int (*compareitem) (SList *slist, void *item1, void *item2); /* Called to compare two items */
|
||||
int (*isequal) (SList *slist, void *item1, void *item2); /* Called by slist_indexof. item1 can be an arbitrary pointer. */
|
||||
void (*freeitem) (SList *slist, void *item); /* Called when an item is removed */
|
||||
};
|
||||
|
||||
#define SLIST_DEFAULT_LIMIT 32767
|
||||
|
||||
#define SLISTF_NODUP 0x00000001 /* No duplicates in the list. */
|
||||
#define SLISTF_SORT 0x00000002 /* Automatically sort the list. Used with compareitem member. */
|
||||
|
||||
/* Note that number is the index in the array + 1 */
|
||||
typedef int (*slist_enumcb_t) (SList *slist, int number, void *item, va_list args);
|
||||
/* Callback to know whether we can delete the entry. */
|
||||
typedef int (*slist_delcheckcb_t) (SList *slist, void *item, va_list args);
|
||||
|
||||
/* Functions for global use */
|
||||
extern int slist_add(SList *slist, void *item);
|
||||
extern void slist_clear(SList *slist, int free);
|
||||
extern int slist_delete(SList *slist, int index);
|
||||
extern int slist_delete_range(SList *slist, char *range, slist_delcheckcb_t cb, ...);
|
||||
extern int slist_enum(SList *slist, char *range, slist_enumcb_t cb, ...);
|
||||
extern int slist_full(SList *slist);
|
||||
extern int slist_indexof(SList *slist, void *item);
|
||||
extern void slist_init(SList *slist);
|
||||
extern void slist_pack(SList *slist);
|
||||
extern int slist_remove(SList *slist, void *item);
|
||||
extern int slist_setcapacity(SList *slist, int16 capacity);
|
||||
|
||||
#endif /* SLIST_H */
|
||||
|
||||
+549
@@ -0,0 +1,549 @@
|
||||
/* Socket utility routines.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: sockutil.c,v 1.7 2003/07/20 01:15:50 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "services.h"
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* Read from a socket with buffering. */
|
||||
|
||||
static char read_netbuf[NET_BUFSIZE];
|
||||
static char *read_curpos = read_netbuf; /* Next byte to return */
|
||||
static char *read_bufend = read_netbuf; /* Next position for data from socket */
|
||||
static char *const read_buftop = read_netbuf + NET_BUFSIZE;
|
||||
int32 total_read = 0;
|
||||
|
||||
|
||||
/* Return amount of data in read buffer. */
|
||||
|
||||
int32 read_buffer_len()
|
||||
{
|
||||
if (read_bufend >= read_curpos)
|
||||
return read_bufend - read_curpos;
|
||||
else
|
||||
return (read_bufend + NET_BUFSIZE) - read_curpos;
|
||||
}
|
||||
|
||||
|
||||
/* Read data. */
|
||||
|
||||
static int buffered_read(int fd, char *buf, int len)
|
||||
{
|
||||
int nread, left = len;
|
||||
fd_set fds;
|
||||
struct timeval tv = { 0, 0 };
|
||||
int errno_save = errno;
|
||||
|
||||
if (fd < 0) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
while (left > 0) {
|
||||
struct timeval *tvptr = (read_bufend == read_curpos ? NULL : &tv);
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
while (read_bufend != read_curpos - 1
|
||||
&& !(read_curpos == read_netbuf
|
||||
&& read_bufend == read_buftop - 1)
|
||||
&& select(fd + 1, &fds, 0, 0, tvptr) == 1) {
|
||||
int maxread;
|
||||
tvptr = &tv; /* don't wait next time */
|
||||
if (read_bufend < read_curpos) /* wrapped around? */
|
||||
maxread = (read_curpos - 1) - read_bufend;
|
||||
else if (read_curpos == read_netbuf)
|
||||
maxread = read_buftop - read_bufend - 1;
|
||||
else
|
||||
maxread = read_buftop - read_bufend;
|
||||
nread = read(fd, read_bufend, maxread);
|
||||
errno_save = errno;
|
||||
if (debug >= 3)
|
||||
alog("debug: buffered_read wanted %d, got %d", maxread,
|
||||
nread);
|
||||
if (nread <= 0)
|
||||
break;
|
||||
read_bufend += nread;
|
||||
if (read_bufend == read_buftop)
|
||||
read_bufend = read_netbuf;
|
||||
}
|
||||
if (read_curpos == read_bufend) /* No more data on socket */
|
||||
break;
|
||||
/* See if we can gobble up the rest of the buffer. */
|
||||
if (read_curpos + left >= read_buftop && read_bufend < read_curpos) {
|
||||
nread = read_buftop - read_curpos;
|
||||
memcpy(buf, read_curpos, nread);
|
||||
buf += nread;
|
||||
left -= nread;
|
||||
read_curpos = read_netbuf;
|
||||
}
|
||||
/* Now everything we need is in a single chunk at read_curpos. */
|
||||
if (read_bufend > read_curpos && read_bufend - read_curpos < left)
|
||||
nread = read_bufend - read_curpos;
|
||||
else
|
||||
nread = left;
|
||||
if (nread) {
|
||||
memcpy(buf, read_curpos, nread);
|
||||
buf += nread;
|
||||
left -= nread;
|
||||
read_curpos += nread;
|
||||
}
|
||||
}
|
||||
total_read += len - left;
|
||||
if (debug >= 4) {
|
||||
alog("debug: buffered_read(%d,%p,%d) returning %d",
|
||||
fd, buf, len, len - left);
|
||||
}
|
||||
errno = errno_save;
|
||||
return len - left;
|
||||
}
|
||||
|
||||
/* Optimized version of the above for reading a single character; returns
|
||||
* the character in an int or EOF, like fgetc(). */
|
||||
|
||||
static int buffered_read_one(int fd)
|
||||
{
|
||||
int nread;
|
||||
fd_set fds;
|
||||
struct timeval tv = { 0, 0 };
|
||||
char c;
|
||||
struct timeval *tvptr = (read_bufend == read_curpos ? NULL : &tv);
|
||||
int errno_save = errno;
|
||||
|
||||
if (fd < 0) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
while (read_bufend != read_curpos - 1
|
||||
&& !(read_curpos == read_netbuf
|
||||
&& read_bufend == read_buftop - 1)
|
||||
&& select(fd + 1, &fds, 0, 0, tvptr) == 1) {
|
||||
int maxread;
|
||||
tvptr = &tv; /* don't wait next time */
|
||||
if (read_bufend < read_curpos) /* wrapped around? */
|
||||
maxread = (read_curpos - 1) - read_bufend;
|
||||
else if (read_curpos == read_netbuf)
|
||||
maxread = read_buftop - read_bufend - 1;
|
||||
else
|
||||
maxread = read_buftop - read_bufend;
|
||||
nread = read(fd, read_bufend, maxread);
|
||||
errno_save = errno;
|
||||
if (debug >= 3)
|
||||
alog("debug: buffered_read_one wanted %d, got %d", maxread,
|
||||
nread);
|
||||
if (nread <= 0)
|
||||
break;
|
||||
read_bufend += nread;
|
||||
if (read_bufend == read_buftop)
|
||||
read_bufend = read_netbuf;
|
||||
}
|
||||
if (read_curpos == read_bufend) { /* No more data on socket */
|
||||
if (debug >= 4)
|
||||
alog("debug: buffered_read_one(%d) returning %d", fd, EOF);
|
||||
errno = errno_save;
|
||||
return EOF;
|
||||
}
|
||||
c = *read_curpos++;
|
||||
if (read_curpos == read_buftop)
|
||||
read_curpos = read_netbuf;
|
||||
total_read++;
|
||||
if (debug >= 4)
|
||||
alog("debug: buffered_read_one(%d) returning %d", fd, c);
|
||||
return (int) c & 0xFF;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Write to a socket with buffering. Note that this assumes only one
|
||||
* socket. */
|
||||
|
||||
static char write_netbuf[NET_BUFSIZE];
|
||||
static char *write_curpos = write_netbuf; /* Next byte to write to socket */
|
||||
static char *write_bufend = write_netbuf; /* Next position for data to socket */
|
||||
static char *const write_buftop = write_netbuf + NET_BUFSIZE;
|
||||
static int write_fd = -1;
|
||||
int32 total_written;
|
||||
|
||||
|
||||
/* Return amount of data in write buffer. */
|
||||
|
||||
int32 write_buffer_len()
|
||||
{
|
||||
if (write_bufend >= write_curpos)
|
||||
return write_bufend - write_curpos;
|
||||
else
|
||||
return (write_bufend + NET_BUFSIZE) - write_curpos;
|
||||
}
|
||||
|
||||
|
||||
/* Helper routine to try and write up to one chunk of data from the buffer
|
||||
* to the socket. Return how much was written. */
|
||||
|
||||
static int flush_write_buffer(int wait)
|
||||
{
|
||||
fd_set fds;
|
||||
struct timeval tv = { 0, 0 };
|
||||
int errno_save = errno;
|
||||
|
||||
if (write_bufend == write_curpos || write_fd == -1)
|
||||
return 0;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(write_fd, &fds);
|
||||
if (select(write_fd + 1, 0, &fds, 0, wait ? NULL : &tv) == 1) {
|
||||
int maxwrite, nwritten;
|
||||
if (write_curpos > write_bufend) /* wrapped around? */
|
||||
maxwrite = write_buftop - write_curpos;
|
||||
else if (write_bufend == write_netbuf)
|
||||
maxwrite = write_buftop - write_curpos - 1;
|
||||
else
|
||||
maxwrite = write_bufend - write_curpos;
|
||||
nwritten = write(write_fd, write_curpos, maxwrite);
|
||||
errno_save = errno;
|
||||
if (debug >= 3)
|
||||
alog("debug: flush_write_buffer wanted %d, got %d", maxwrite,
|
||||
nwritten);
|
||||
if (nwritten > 0) {
|
||||
write_curpos += nwritten;
|
||||
if (write_curpos == write_buftop)
|
||||
write_curpos = write_netbuf;
|
||||
total_written += nwritten;
|
||||
return nwritten;
|
||||
}
|
||||
}
|
||||
errno = errno_save;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Write data. */
|
||||
|
||||
static int buffered_write(int fd, char *buf, int len)
|
||||
{
|
||||
int nwritten, left = len;
|
||||
int errno_save = errno;
|
||||
|
||||
if (fd < 0) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
write_fd = fd;
|
||||
|
||||
while (left > 0) {
|
||||
|
||||
/* Don't try putting anything in the buffer if it's full. */
|
||||
if (write_curpos != write_bufend + 1 &&
|
||||
(write_curpos != write_netbuf
|
||||
|| write_bufend != write_buftop - 1)) {
|
||||
/* See if we need to write up to the end of the buffer. */
|
||||
if (write_bufend + left >= write_buftop
|
||||
&& write_curpos <= write_bufend) {
|
||||
nwritten = write_buftop - write_bufend;
|
||||
memcpy(write_bufend, buf, nwritten);
|
||||
buf += nwritten;
|
||||
left -= nwritten;
|
||||
write_bufend = write_netbuf;
|
||||
}
|
||||
/* Now we can copy a single chunk to write_bufend. */
|
||||
if (write_curpos > write_bufend
|
||||
&& write_curpos - write_bufend - 1 < left)
|
||||
nwritten = write_curpos - write_bufend - 1;
|
||||
else
|
||||
nwritten = left;
|
||||
if (nwritten) {
|
||||
memcpy(write_bufend, buf, nwritten);
|
||||
buf += nwritten;
|
||||
left -= nwritten;
|
||||
write_bufend += nwritten;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now write to the socket as much as we can. */
|
||||
if (write_curpos == write_bufend + 1 ||
|
||||
(write_curpos == write_netbuf
|
||||
&& write_bufend == write_buftop - 1))
|
||||
flush_write_buffer(1);
|
||||
else
|
||||
flush_write_buffer(0);
|
||||
errno_save = errno;
|
||||
if (write_curpos == write_bufend + 1 ||
|
||||
(write_curpos == write_netbuf
|
||||
&& write_bufend == write_buftop - 1)) {
|
||||
/* Write failed on full buffer */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (debug >= 4) {
|
||||
alog("debug: buffered_write(%d,%p,%d) returning %d",
|
||||
fd, buf, len, len - left);
|
||||
}
|
||||
errno = errno_save;
|
||||
return len - left;
|
||||
}
|
||||
|
||||
/* Optimized version of the above for writing a single character; returns
|
||||
* the character in an int or EOF, like fputc(). Commented out because it
|
||||
* isn't currently used. */
|
||||
|
||||
#if 0
|
||||
static int buffered_write_one(int c, int fd)
|
||||
{
|
||||
struct timeval tv = { 0, 0 };
|
||||
|
||||
if (fd < 0) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
write_fd = fd;
|
||||
|
||||
/* Try to flush the buffer if it's full. */
|
||||
if (write_curpos == write_bufend + 1 ||
|
||||
(write_curpos == write_netbuf
|
||||
&& write_bufend == write_buftop - 1)) {
|
||||
flush_write_buffer(1);
|
||||
if (write_curpos == write_bufend + 1 ||
|
||||
(write_curpos == write_netbuf
|
||||
&& write_bufend == write_buftop - 1)) {
|
||||
/* Write failed */
|
||||
if (debug >= 4)
|
||||
alog("debug: buffered_write_one(%d) returning %d", fd,
|
||||
EOF);
|
||||
return EOF;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the character. */
|
||||
*write_bufend++ = c;
|
||||
if (write_bufend == write_buftop)
|
||||
write_bufend = write_netbuf;
|
||||
|
||||
/* Move it to the socket if we can. */
|
||||
flush_write_buffer(0);
|
||||
|
||||
if (debug >= 4)
|
||||
alog("debug: buffered_write_one(%d) returning %d", fd, c);
|
||||
return (int) c & 0xFF;
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
static int lastchar = EOF;
|
||||
|
||||
int sgetc(int s)
|
||||
{
|
||||
int c;
|
||||
|
||||
if (lastchar != EOF) {
|
||||
c = lastchar;
|
||||
lastchar = EOF;
|
||||
return c;
|
||||
}
|
||||
return buffered_read_one(s);
|
||||
}
|
||||
|
||||
int sungetc(int c, int s)
|
||||
{
|
||||
return lastchar = c;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* If connection was broken, return NULL. If the read timed out, return
|
||||
* (char *)-1.
|
||||
*/
|
||||
|
||||
char *sgets(char *buf, int len, int s)
|
||||
{
|
||||
int c = 0;
|
||||
struct timeval tv;
|
||||
fd_set fds;
|
||||
char *ptr = buf;
|
||||
|
||||
if (len == 0)
|
||||
return NULL;
|
||||
FD_SET(s, &fds);
|
||||
tv.tv_sec = ReadTimeout;
|
||||
tv.tv_usec = 0;
|
||||
while (read_buffer_len() == 0 &&
|
||||
(c = select(s + 1, &fds, NULL, NULL, &tv)) < 0) {
|
||||
if (errno != EINTR)
|
||||
break;
|
||||
}
|
||||
if (read_buffer_len() == 0 && c == 0)
|
||||
return (char *) -1;
|
||||
c = sgetc(s);
|
||||
while (--len && (*ptr++ = c) != '\n' && (c = sgetc(s)) >= 0);
|
||||
if (c < 0)
|
||||
return NULL;
|
||||
*ptr = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* sgets2: Read a line of text from a socket, and strip newline and
|
||||
* carriage return characters from the end of the line.
|
||||
*/
|
||||
|
||||
char *sgets2(char *buf, int len, int s)
|
||||
{
|
||||
char *str = sgets(buf, len, s);
|
||||
|
||||
if (!str || str == (char *) -1)
|
||||
return str;
|
||||
str = buf + strlen(buf) - 1;
|
||||
if (*str == '\n')
|
||||
*str-- = 0;
|
||||
if (*str == '\r')
|
||||
*str = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Read from a socket. (Use this instead of read() because it has
|
||||
* buffering.) */
|
||||
|
||||
int sread(int s, char *buf, int len)
|
||||
{
|
||||
return buffered_read(s, buf, len);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int sputs(char *str, int s)
|
||||
{
|
||||
return buffered_write(s, str, strlen(str));
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int sockprintf(int s, char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char buf[16384]; /* Really huge, to try and avoid truncation */
|
||||
|
||||
va_start(args, fmt);
|
||||
return buffered_write(s, buf, vsnprintf(buf, sizeof(buf), fmt, args));
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
#if !HAVE_GETHOSTBYNAME
|
||||
|
||||
/* Translate an IP dotted-quad address to a 4-byte character string.
|
||||
* Return NULL if the given string is not in dotted-quad format.
|
||||
*/
|
||||
|
||||
static char *pack_ip(const char *ipaddr)
|
||||
{
|
||||
static char ipbuf[4];
|
||||
int tmp[4], i;
|
||||
|
||||
if (sscanf(ipaddr, "%d.%d.%d.%d", &tmp[0], &tmp[1], &tmp[2], &tmp[3])
|
||||
!= 4)
|
||||
return NULL;
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (tmp[i] < 0 || tmp[i] > 255)
|
||||
return NULL;
|
||||
ipbuf[i] = tmp[i];
|
||||
}
|
||||
return ipbuf;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* lhost/lport specify the local side of the connection. If they are not
|
||||
* given (lhost==NULL, lport==0), then they are left free to vary.
|
||||
*/
|
||||
|
||||
int conn(const char *host, int port, const char *lhost, int lport)
|
||||
{
|
||||
#if HAVE_GETHOSTBYNAME
|
||||
struct hostent *hp;
|
||||
#else
|
||||
char *addr;
|
||||
#endif
|
||||
struct sockaddr_in sa, lsa;
|
||||
int sock;
|
||||
|
||||
memset(&lsa, 0, sizeof(lsa));
|
||||
if (lhost) {
|
||||
#if HAVE_GETHOSTBYNAME
|
||||
if ((hp = gethostbyname(lhost)) != NULL) {
|
||||
memcpy((char *) &lsa.sin_addr, hp->h_addr, hp->h_length);
|
||||
lsa.sin_family = hp->h_addrtype;
|
||||
#else
|
||||
if (addr = pack_ip(lhost)) {
|
||||
memcpy((char *) &lsa.sin_addr, addr, 4);
|
||||
lsa.sin_family = AF_INET;
|
||||
#endif
|
||||
} else {
|
||||
lhost = NULL;
|
||||
}
|
||||
}
|
||||
if (lport)
|
||||
lsa.sin_port = htons((unsigned short) lport);
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
#if HAVE_GETHOSTBYNAME
|
||||
if (!(hp = gethostbyname(host)))
|
||||
return -1;
|
||||
memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
|
||||
sa.sin_family = hp->h_addrtype;
|
||||
#else
|
||||
if (!(addr = pack_ip(host))) {
|
||||
alog("conn(): `%s' is not a valid IP address", host);
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
memcpy((char *) &sa.sin_addr, addr, 4);
|
||||
sa.sin_family = AF_INET;
|
||||
#endif
|
||||
sa.sin_port = htons((unsigned short) port);
|
||||
|
||||
if ((sock = socket(sa.sin_family, SOCK_STREAM, 0)) < 0)
|
||||
return -1;
|
||||
|
||||
if ((lhost || lport)
|
||||
&& bind(sock, (struct sockaddr *) &lsa, sizeof(lsa)) < 0) {
|
||||
int errno_save = errno;
|
||||
close(sock);
|
||||
errno = errno_save;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (connect(sock, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
|
||||
int errno_save = errno;
|
||||
close(sock);
|
||||
errno = errno_save;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void disconn(int s)
|
||||
{
|
||||
shutdown(s, 2);
|
||||
close(s);
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/* Threads handling.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: threads.c,v 1.5 2003/07/20 01:15:50 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "services.h"
|
||||
|
||||
#ifdef USE_THREADS
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static Thread *threads;
|
||||
|
||||
static int thread_cancel(Thread * thr);
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static int thread_cancel(Thread * thr)
|
||||
{
|
||||
if (pthread_cancel(thr->th))
|
||||
return 0;
|
||||
|
||||
if (thr->next)
|
||||
thr->next->prev = thr->prev;
|
||||
if (thr->prev)
|
||||
thr->prev->next = thr->next;
|
||||
else
|
||||
threads = thr->next;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int thread_create(pthread_t * th, void *(*start_routine) (void *),
|
||||
void *arg)
|
||||
{
|
||||
Thread *thr;
|
||||
|
||||
if (pthread_create(th, NULL, start_routine, arg))
|
||||
return 0;
|
||||
if (pthread_detach(*th))
|
||||
return 0;
|
||||
|
||||
/* Add the thread to our internal list */
|
||||
thr = scalloc(sizeof(Thread), 1);
|
||||
thr->th = *th;
|
||||
thr->next = threads;
|
||||
if (thr->next)
|
||||
thr->next->prev = thr;
|
||||
threads = thr;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int thread_killall(void)
|
||||
{
|
||||
Thread *thr, *next;
|
||||
|
||||
for (thr = threads; thr; thr = next) {
|
||||
next = thr;
|
||||
if (!thread_cancel(thr))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,130 @@
|
||||
/* Routines for time-delayed actions.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: timeout.c,v 1.7 2003/07/20 01:15:50 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "services.h"
|
||||
#include "timeout.h"
|
||||
|
||||
static Timeout *timeouts = NULL;
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#ifdef DEBUG_COMMANDS
|
||||
|
||||
/* Send the timeout list to the given user. */
|
||||
|
||||
void send_timeout_list(User * u)
|
||||
{
|
||||
Timeout *to, *last;
|
||||
|
||||
notice(s_OperServ, u->nick, "Now: %ld", time(NULL));
|
||||
for (to = timeouts, last = NULL; to; last = to, to = to->next) {
|
||||
notice(s_OperServ, u->nick, "%p: %ld: %p (%p)",
|
||||
to, to->timeout, to->code, to->data);
|
||||
if (to->prev != last)
|
||||
notice(s_OperServ, u->nick,
|
||||
" to->prev incorrect! expected=%p seen=%p",
|
||||
last, to->prev);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* DEBUG_COMMANDS */
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Check the timeout list for any pending actions. */
|
||||
|
||||
void check_timeouts(void)
|
||||
{
|
||||
Timeout *to, *to2;
|
||||
time_t t = time(NULL);
|
||||
|
||||
if (debug >= 2)
|
||||
alog("debug: Checking timeouts at %ld", t);
|
||||
|
||||
to = timeouts;
|
||||
while (to) {
|
||||
if (t < to->timeout) {
|
||||
to = to->next;
|
||||
continue;
|
||||
}
|
||||
if (debug >= 4) {
|
||||
alog("debug: Running timeout %p (code=%p repeat=%d)",
|
||||
to, to->code, to->repeat);
|
||||
}
|
||||
to->code(to);
|
||||
if (to->repeat) {
|
||||
to = to->next;
|
||||
continue;
|
||||
}
|
||||
to2 = to->next;
|
||||
if (to->next)
|
||||
to->next->prev = to->prev;
|
||||
if (to->prev)
|
||||
to->prev->next = to->next;
|
||||
else
|
||||
timeouts = to->next;
|
||||
free(to);
|
||||
to = to2;
|
||||
}
|
||||
if (debug >= 2)
|
||||
alog("debug: Finished timeout list");
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Add a timeout to the list to be triggered in `delay' seconds. If
|
||||
* `repeat' is nonzero, do not delete the timeout after it is triggered.
|
||||
* This must maintain the property that timeouts added from within a
|
||||
* timeout routine do not get checked during that run of the timeout list.
|
||||
*/
|
||||
|
||||
Timeout *add_timeout(int delay, void (*code) (Timeout *), int repeat)
|
||||
{
|
||||
Timeout *t = scalloc(sizeof(Timeout), 1);
|
||||
t->settime = time(NULL);
|
||||
t->timeout = t->settime + delay;
|
||||
t->code = code;
|
||||
t->repeat = repeat;
|
||||
t->next = timeouts;
|
||||
t->prev = NULL;
|
||||
if (timeouts)
|
||||
timeouts->prev = t;
|
||||
timeouts = t;
|
||||
return t;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Remove a timeout from the list (if it's there). */
|
||||
|
||||
void del_timeout(Timeout * t)
|
||||
{
|
||||
Timeout *ptr;
|
||||
|
||||
for (ptr = timeouts; ptr; ptr = ptr->next) {
|
||||
if (ptr == t)
|
||||
break;
|
||||
}
|
||||
if (!ptr)
|
||||
return;
|
||||
if (t->prev)
|
||||
t->prev->next = t->next;
|
||||
else
|
||||
timeouts = t->next;
|
||||
if (t->next)
|
||||
t->next->prev = t->prev;
|
||||
free(t);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
@@ -0,0 +1,50 @@
|
||||
/* Time-delay routine include stuff.
|
||||
*
|
||||
* (C) 2003 Anope Team
|
||||
* Contact us at info@anope.org
|
||||
*
|
||||
* Please read COPYING and README for furhter details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*
|
||||
* $Id: timeout.h,v 1.4 2003/07/20 01:15:50 dane Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TIMEOUT_H
|
||||
#define TIMEOUT_H
|
||||
|
||||
#include <time.h>
|
||||
|
||||
|
||||
/* Definitions for timeouts: */
|
||||
typedef struct timeout_ Timeout;
|
||||
struct timeout_ {
|
||||
Timeout *next, *prev;
|
||||
time_t settime, timeout;
|
||||
int repeat; /* Does this timeout repeat indefinitely? */
|
||||
void (*code)(Timeout *); /* This structure is passed to the code */
|
||||
void *data; /* Can be anything */
|
||||
};
|
||||
|
||||
|
||||
/* Check the timeout list for any pending actions. */
|
||||
extern void check_timeouts(void);
|
||||
|
||||
/* Add a timeout to the list to be triggered in `delay' seconds. Any
|
||||
* timeout added from within a timeout routine will not be checked during
|
||||
* that run through the timeout list.
|
||||
*/
|
||||
extern Timeout *add_timeout(int delay, void (*code)(Timeout *), int repeat);
|
||||
|
||||
/* Remove a timeout from the list (if it's there). */
|
||||
extern void del_timeout(Timeout *t);
|
||||
|
||||
#ifdef DEBUG_COMMANDS
|
||||
/* Send the list of timeouts to the given user. */
|
||||
extern void send_timeout_list(User *u);
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* TIMEOUT_H */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user