├── .gitignore ├── .gitmodules ├── LICENCE ├── Makefile ├── README.md ├── bsextra └── target_module.mk ├── config.h ├── configure.ac ├── doc ├── bantracker │ ├── configuration-guide.txt │ ├── operators-guide.txt │ ├── schema-mysql.sql │ ├── schema-pg.sql │ └── schema-sqlite3.sql ├── build.mk └── eir.conf.example ├── libjson ├── build.mk ├── json │ ├── autolink.h │ ├── config.h │ ├── forwards.h │ ├── json.h │ ├── reader.h │ ├── value.h │ └── writer.h ├── json_batchallocator.h ├── json_internalarray.inl ├── json_internalmap.inl ├── json_reader.cpp ├── json_value.cpp ├── json_valueiterator.inl └── json_writer.cpp ├── modules ├── build.mk ├── config.cpp ├── core │ ├── channel.cpp │ ├── ctcp.cpp │ ├── die.cpp │ ├── error.cpp │ ├── join_channels.cpp │ ├── mode.cpp │ ├── nickserv.cpp │ ├── oper.cpp │ └── ping.cpp ├── dump_isupport.cpp ├── echo.cpp ├── help.cpp ├── logs │ ├── channel.cpp │ └── stderr.cpp ├── perl │ ├── api │ │ ├── HashWrappers.cpp │ │ ├── HashWrappers.h │ │ ├── api.xs │ │ ├── capabilities.xs │ │ ├── clients.xs │ │ ├── handlers.xs │ │ ├── helpers.xs │ │ ├── logger.xs │ │ ├── messages.xs │ │ ├── perl_helpers.cpp │ │ ├── perl_helpers.hh │ │ ├── storage.xs │ │ ├── typemap │ │ ├── value.xs │ │ ├── value_wrapper.cpp │ │ └── value_wrapper.hh │ ├── build.mk │ ├── definitions.h │ ├── extra.mk │ ├── lib │ │ ├── Eir.pm │ │ └── init.pl │ ├── perl.cpp │ ├── stupid_perl_workarounds.h │ └── util │ │ ├── call_perl.hh │ │ └── type_maps.h ├── privileges.cpp ├── privs │ ├── account.cpp │ └── hostmask.cpp ├── snote.cpp ├── storage │ ├── extra.mk │ └── json.cpp ├── userlist.cpp ├── voicebot.cpp └── whoami.cpp ├── paludis └── util │ ├── attributes.hh │ ├── build.mk │ ├── destringify.cc │ ├── destringify.hh │ ├── exception.cc │ ├── exception.hh │ ├── instantiation_policy-impl.hh │ ├── instantiation_policy.hh │ ├── join.hh │ ├── member_iterator-fwd.hh │ ├── member_iterator-impl.hh │ ├── member_iterator.hh │ ├── mutex-fwd.hh │ ├── mutex.cc │ ├── mutex.hh │ ├── operators.hh │ ├── private_implementation_pattern-impl.hh │ ├── private_implementation_pattern.hh │ ├── save.hh │ ├── stringify.hh │ ├── tokeniser.cc │ ├── tokeniser.hh │ ├── wrapped_forward_iterator-fwd.hh │ ├── wrapped_forward_iterator-impl.hh │ └── wrapped_forward_iterator.hh ├── scripts ├── bantracker.pl ├── eir_cap_sasl.pl └── patchlist.pl ├── settings.mk.in └── src ├── bot.cpp ├── bot.h ├── bot_command.cpp ├── build.mk ├── capability.cpp ├── capability.h ├── client.cpp ├── client.h ├── command.cpp ├── command.h ├── eir.h ├── event.cpp ├── event.h ├── event_internal.h ├── exceptions.cpp ├── exceptions.h ├── handler.h ├── help.h ├── logger.cpp ├── logger.h ├── main.cpp ├── match.cpp ├── match.h ├── match_internal.h ├── message.cpp ├── message.h ├── modload.cpp ├── modules.cpp ├── modules.h ├── privilege.cpp ├── privilege.h ├── server.cpp ├── server.h ├── settings.cpp ├── settings.h ├── storage.cpp ├── storage.h ├── string_util.cpp ├── string_util.h ├── supported.cpp ├── supported.h ├── times.h ├── value.cpp └── value.h /.gitignore: -------------------------------------------------------------------------------- 1 | .*.swp 2 | .*.swo 3 | tags 4 | 5 | configure 6 | config.log 7 | config.status 8 | settings.mk 9 | autom4te.cache 10 | 11 | build 12 | intermediate 13 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "bs"] 2 | path = bs 3 | url = git://github.com/spb/bs.git 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CXXFLAGS = -O0 -fno-inline-functions -ggdb3 -I. -pedantic -std=c++0x 2 | 3 | SUBDIRS = \ 4 | paludis/util \ 5 | src \ 6 | libjson \ 7 | modules \ 8 | doc 9 | 10 | include settings.mk 11 | 12 | include bsextra/target_module.mk 13 | include bs/bs.mk 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Eir 2 | === 3 | 4 | Eir is an IRC client bot framework, written primarily for freenode utility 5 | functions. It is, however, highly extensible using C++ or Perl, and is used by 6 | other projects as well. 7 | 8 | Installation 9 | ============ 10 | 11 | If you just want to know how to build and install it, do the following after 12 | making sure you have the obvious pre-reqs (`build-essential`, `libperl-dev`) 13 | installed: 14 | 15 | ``` 16 | git submodule init 17 | git submodule update 18 | autoconf 19 | ./configure --prefix=SOMEWHERE 20 | make 21 | make install 22 | ``` 23 | 24 | To install on FreeBSD, you will need `g++` and `gmake`, so something like this: 25 | ``` 26 | # if not already available do the following: 27 | sudo pkg install gcc6 gmake 28 | git submodule init 29 | git submodule update 30 | autoconf 31 | ./configure --prefix=SOMEWHERE 32 | CXX=g++6 gmake 33 | gmake install 34 | 35 | ``` 36 | 37 | Then go to SOMEWHERE/etc, and write eir.conf. There is an example config file 38 | installed. 39 | 40 | Scripts 41 | ======= 42 | 43 | Eir comes with a few perl script modules, including Bantracker.pl, and a module 44 | for sasl-auth login. You will want to copy these to your install location 45 | -------------------------------------------------------------------------------- /bsextra/target_module.mk: -------------------------------------------------------------------------------- 1 | ifndef TARGETS_MODULE_MK 2 | TARGETS_MODULE_MK=1 3 | 4 | _BS_SUPPORTED_TARGETS += MODULE 5 | 6 | _BS_DEFAULT_OUTPUT_MODULE = $(MODDIR)/$(1).so 7 | 8 | define _BS_EXTRA_TARGET_SETTINGS_MODULE 9 | 10 | $(2)_SOURCES ?= $(2).cpp 11 | 12 | endef 13 | #= LIBRARY_NAME_$(1)/$(2) = $(2) 14 | 15 | # one argument: target internal name 16 | define _BS_TARGET_RULE_MODULE 17 | 18 | $(call add-dir,$(call dirname,$(_BS_BUILD_TARGET_$(1)))) 19 | 20 | $(_BS_BUILD_TARGET_$(1)): $(_BS_OBJECTS_$(1)) | $(call dirname,$(_BS_BUILD_TARGET_$(1))) 21 | rm -f $$@ 22 | $(CXX) -shared -o $$@ \ 23 | $(call expand-target-variable,$(1),LDFLAGS) \ 24 | -L$(BUILDDIR)/$(LIBDIR) \ 25 | $(call expand-target-dependencies,$(1)) \ 26 | $(_BS_OBJECTS_$(1)) 27 | 28 | endef 29 | 30 | endif 31 | -------------------------------------------------------------------------------- /config.h: -------------------------------------------------------------------------------- 1 | #define HAVE_CXA_DEMANGLE 2 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT([eir], [0.0.1]) 2 | 3 | AC_PREFIX_DEFAULT([~/eir]) 4 | 5 | AC_SUBST([PACKAGE_VERSION]) 6 | 7 | AC_MSG_CHECKING([whether to modify moduledir]) 8 | AC_ARG_WITH(moduledir, 9 | AC_HELP_STRING([--with-moduledir=DIR], 10 | [Directory to install modules.]), 11 | [ MODDIR=`echo $withval | sed 's/\/$//'` 12 | AC_MSG_RESULT(yes) 13 | AC_DEFINE(MODDIR, MODDIR, [Prefix where modules are installed.]) 14 | AC_SUBST([MODDIR]) ], 15 | [ MODDIR='${prefix}/modules' 16 | AC_MSG_RESULT(no) 17 | AC_DEFINE(MODDIR, MODDIR, [Prefix where modules are installed.]) 18 | AC_SUBST([MODDIR])] 19 | ) 20 | 21 | 22 | AC_MSG_CHECKING([whether to modify confdir]) 23 | AC_ARG_WITH(confdir, 24 | AC_HELP_STRING([--with-confdir=DIR], 25 | [Location of configuration files.]), 26 | [ ETCDIR=`echo $withval | sed 's/\/$//'` 27 | AC_MSG_RESULT(yes) 28 | AC_DEFINE(ETCDIR, ETCDIR, [Location of configuration files.]) 29 | AC_SUBST([ETCDIR]) ], 30 | [ ETCDIR='${prefix}/etc' 31 | AC_MSG_RESULT(no) 32 | AC_DEFINE(ETCDIR, ETCDIR, [Location of configuration files.]) 33 | AC_SUBST([ETCDIR])] 34 | ) 35 | 36 | 37 | AC_MSG_CHECKING([whether to modify datadir]) 38 | AC_ARG_WITH(datadir, 39 | AC_HELP_STRING([--with-datadir=DIR], 40 | [Location of data files.]), 41 | [ DATADIR=`echo $withval | sed 's/\/$//'` 42 | AC_MSG_RESULT(yes) 43 | AC_DEFINE(DATADIR, DATADIR, [Location of data files.]) 44 | AC_SUBST([DATADIR]) ], 45 | [ DATADIR='${prefix}/data' 46 | AC_MSG_RESULT(no) 47 | AC_DEFINE(DATADIR, DATADIR, [Location of data files.]) 48 | AC_SUBST([DATADIR])] 49 | ) 50 | 51 | AC_ARG_ENABLE([warnings], 52 | [AS_HELP_STRING([--enable-warnings],[Enable warnings.])], 53 | [enable_warnings=$enableval], 54 | [enable_warnings="no"]) 55 | 56 | AS_IF([test "x$enable_warnings" != "xno"], 57 | [WARNINGS_CFLAGS="-Wall -Werror -Wextra"]) 58 | AC_SUBST(WARNINGS_CFLAGS) 59 | 60 | AC_ARG_ENABLE([perl], 61 | [AS_HELP_STRING([--disable-perl],[Disable building perl scripting module.])], 62 | [enable_perl=$enableval], 63 | [enable_perl="yes"]) 64 | 65 | AS_IF([test "x$enable_perl" != "xno"], 66 | [ 67 | AC_PATH_PROG(perlpath, perl) 68 | if test -n "$perlpath"; then 69 | ENABLE_PERL=perl 70 | PERL_CFLAGS=`perl -MExtUtils::Embed -e ccopts` 71 | PERL_LIBS=`perl -MExtUtils::Embed -e ldopts` 72 | fi 73 | ]) 74 | 75 | AS_IF([test "x$enable_perl" = "xyes" && test "x$PERL_CFLAGS" = "x"], 76 | [AC_MSG_ERROR([Perl support was requested but Perl could not be found.])]) 77 | 78 | AC_SUBST(ENABLE_PERL) 79 | AC_SUBST(PERL_CFLAGS) 80 | AC_SUBST(PERL_LIBS) 81 | 82 | AC_OUTPUT([settings.mk]) 83 | -------------------------------------------------------------------------------- /doc/bantracker/configuration-guide.txt: -------------------------------------------------------------------------------- 1 | Authorised users can configure bantracker by way of the 'btconfig' command. 2 | 3 | Note that changes affect the in-memory configuration - to commit changes to disk issue the command 'btsaveconfig'. 4 | 5 | BOT SETTINGS 6 | 7 | these are set in eir's configuration file, or with the 'set' command 8 | 9 | bantracker_dsn A perl DBI dsn defining the database that bantracker will use 10 | bantracker_dbuser The username to be used when connecting to the database, if required. 11 | bantracker_dbpass The password to be used when connecting to the database, if required. 12 | bantracker_dbtype The type of database in use - currently sqlite and mysql are supported. 13 | bantracker_admins A regular expression specifying who may configure bantracker (change with caution) 14 | bantracker_debug If set to '1', enable debuging commands and output 15 | bantracker_enable_logging If set to '1', enable channel logging features (experimental) 16 | bantracker_urlprefix URL prefix for public log access 17 | 18 | CHANNEL SETTINGS 19 | 20 | The follow can be set on a per-channel basis using "btconfig #channel " 21 | 22 | enabled If set, bantracker will follow bans on this channel 23 | report If set, bantracker will report the addition, removal and expiry of bans to the named channel or user 24 | reporton Comma separated list defining which events bantracker should send to the report target available (new,exp,rem) 25 | frequency How often should bantracker check for expired bans 26 | admins A regular expression specifying which users may edit bans other than those they set for this channel 27 | query A regular expression specifying which users may query the database for bans other than their own 28 | bantime Default expiry time for new bans 29 | ops If set, bantracker will not relinquish operator status after removing bans - s 30 | trackmodes Defines which channel modes bantracker will monitor - 'qb' will follow quiets and bans 31 | action What should bantracker do when a ban expires - see below 32 | 33 | ACTIONS 34 | 35 | The 'action' channel setting defines what bantracker should do when a ban expires on the specified channel. 36 | 37 | '0' instructs bantracker to report the expired ban to the report channel only, or do nothing if there is no report channel 38 | '1' instructs bantracker to remove the ban if it has operator status, or report the ban as above 39 | '2' instructs bantracker to try and obtain operator status to remove the ban. If this is not possible no action will be taken. 40 | 41 | -------------------------------------------------------------------------------- /doc/bantracker/operators-guide.txt: -------------------------------------------------------------------------------- 1 | GENERAL USAGE 2 | 3 | Commands may be sent via private message, or prefixed with ! in channels. 4 | 5 | Commands submitted in channel will be replied to in channel (not private). 6 | 7 | COMMANDS 8 | 9 | btinfo 10 | 11 | btinfo returns entries matching 12 | btinfo returns entries set by 13 | btinfo <#channel> returns entries set on <#channel> 14 | 15 | btcheck <#channel> 16 | 17 | Returns entries set on #channel matching or 18 | 19 | btpending <#channel|nickname> 20 | 21 | Returns uncommented (pending) entries set on <#channel>, or set by . 22 | 23 | btexpired <#channel> 24 | 25 | Returns expired entries set on <#channel> 26 | 27 | btset <[[action]~[timespec]] [comment]> 28 | 29 | Sets the action, expiry time and/or comment for an existing entry. 30 | 31 | One of [timespec] or [comment], or both (in order) is required. 32 | 33 | [action] may only be specified with a [timespec], not without. 34 | 35 | Examples: 36 | 37 | btset 43221 Trolling 38 | btset 43221 ~48h 39 | btset 43221 ~48h Trolling 40 | 41 | For details on [timespec], see TIME SPECIFICATION section below 42 | For details on [action], see ACTIONS section below. 43 | 44 | COMMENTS 45 | 46 | For each new ban added in a channel (with +b), the bantracker bot will private 47 | message the user who set the ban, asking for a comment (reason) to be added. 48 | 49 | The content of the reply to that message is saved, and then visible in btinfo 50 | results. If more than one ban was set, you will be prompted for a comment for 51 | each in turn. 52 | 53 | The default expiry time of the ban (channel dependent, typically 24 hours) can 54 | be changed when adding a [comment], by prefixing it with a ~[timespec]. For 55 | example: "~14d Trolling" 56 | 57 | TIME SPECIFICATION 58 | 59 | When adding a comment or using the btset command, times can be specified in 60 | [y]ears, [M]onths, [w]eeks, [d]ays, [h]ours, [m]inutes, [s]econds or in any combination together. 61 | 62 | Examples: 63 | 64 | ~1h 1 hour from the time it is set. 65 | ~4h1m4s 4 hours, 1 minute and 4 seconds from the time it is set. 66 | ~48h 48 hours from the time it is set. (Equivalent to ~2d). 67 | ~14d 14 days from the time it is set. 68 | ~2w 2 weeks from the time it is set. (Equivalent to ~14d) 69 | 70 | ACTIONS 71 | 72 | Expiry time specifications (timespec) can optionally be prefixed 73 | with a single character that sets the action that should be taken 74 | when that ban entry expires. 75 | 76 | # - Reports the expired ban to the report channel only, or does nothing if a 77 | report channel is not set. 78 | @ - Removes the ban if the bot has operator status, or report the ban (as above) 79 | if it does not. 80 | % - Bot attempts to gain operator status using ChanServ and remove the ban. Takes 81 | no further action if this cannot be done. 82 | -------------------------------------------------------------------------------- /doc/bantracker/schema-mysql.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE bans ( i INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, channel VARCHAR(512), setter VARCHAR(512), mask VARCHAR(512), isSet BOOL, setDate DATETIME, reason VARCHAR(512), action INTEGER, actionDate DATETIME, `affected` TEXT, unbanner VARCHAR(512), unbanDate DATETIME, type VARCHAR(20), nagged INTEGER); 2 | CREATE TABLE log (i INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, channel VARCHAR(512), sender VARCHAR(512), command VARCHAR(512), data VARCHAR(512), date DATETIME); 3 | -------------------------------------------------------------------------------- /doc/bantracker/schema-pg.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE bans ( i SERIAL PRIMARY KEY, channel VARCHAR(512), setter VARCHAR(512), mask VARCHAR(512), isSet BOOL, setDate TIMESTAMP, reason VARCHAR(512), action INTEGER, actionDate TIMESTAMP, affected TEXT, unbanner VARCHAR(512), unbanDate TIMESTAMP, type VARCHAR(20), nagged INTEGER); 2 | CREATE TABLE log (i SERIAL PRIMARY KEY, channel VARCHAR(512), sender VARCHAR(512), command VARCHAR(512), data VARCHAR(512), date TIMESTAMP); 3 | 4 | -------------------------------------------------------------------------------- /doc/bantracker/schema-sqlite3.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE bans ( i INTEGER PRIMARY KEY, channel VARCHAR, setter VARCHAR, mask VARCHAR, isSet BOOL, setDate DATETIME, reason VARCHAR, action INTEGER, actionDate DATETIME, "affected" TEXT, unbanner TEXT, unbanDate DATETIME, type varchar, nagged integer); 2 | CREATE TABLE log (i INTEGER PRIMARY KEY, channel VARCHAR, operator VARCHAR, mask VARCHAR, action VARCHAR, date DATETIME); 3 | -------------------------------------------------------------------------------- /doc/build.mk: -------------------------------------------------------------------------------- 1 | DATADIR = $(ETCDIR) 2 | DATA = eir.conf.example 3 | -------------------------------------------------------------------------------- /doc/eir.conf.example: -------------------------------------------------------------------------------- 1 | modload "storage/json.so" 2 | default_storage json 3 | 4 | modload "core/ping.so" 5 | modload "core/nickserv.so" 6 | modload "core/channel.so" 7 | modload "whoami.so" 8 | modload "core/join_channels.so" 9 | modload "core/die.so" 10 | modload "core/mode.so" 11 | modload "core/error.so" 12 | modload "userlist.so" 13 | modload "logs/stderr.so" 14 | modload "logs/channel.so" 15 | modload "help.so" 16 | 17 | server 127.0.0.2 6667 eir 18 | 19 | set command_chars . 20 | 21 | modload privileges.so 22 | modload privs/hostmask.so 23 | modload privs/account.so 24 | 25 | #privilege host *!*@127.0.0.2 admin 26 | privilege account spb admin 27 | 28 | channel #eir 29 | channel #asdf 30 | 31 | log stderr - raw info admin command warning 32 | 33 | log channel #eir admin command warning 34 | 35 | modload "perl.so" 36 | 37 | # Use one or the other of these two blocks, not both 38 | 39 | # Normal nickserv auth... 40 | set nickserv_user eir 41 | set nickserv_pass thisisnotarealpassword 42 | 43 | # ... or SASL (recommended on freenode) 44 | loadscript scripts/eir_cap_sasl.pl 45 | set sasl_user eir 46 | set sasl_password thisisnotarealpassword 47 | set sasl_mechanism plain 48 | 49 | -------------------------------------------------------------------------------- /libjson/build.mk: -------------------------------------------------------------------------------- 1 | DSOS = json 2 | 3 | json_SOURCES = json_reader.cpp json_writer.cpp json_value.cpp 4 | 5 | CXXFLAGS = -Ilibjson -Wno-error -fPIC 6 | -------------------------------------------------------------------------------- /libjson/json/autolink.h: -------------------------------------------------------------------------------- 1 | #ifndef JSON_AUTOLINK_H_INCLUDED 2 | # define JSON_AUTOLINK_H_INCLUDED 3 | 4 | # include "config.h" 5 | 6 | # ifdef JSON_IN_CPPTL 7 | # include 8 | # endif 9 | 10 | # if !defined(JSON_NO_AUTOLINK) && !defined(JSON_DLL_BUILD) && !defined(JSON_IN_CPPTL) 11 | # define CPPTL_AUTOLINK_NAME "json" 12 | # undef CPPTL_AUTOLINK_DLL 13 | # ifdef JSON_DLL 14 | # define CPPTL_AUTOLINK_DLL 15 | # endif 16 | # include "autolink.h" 17 | # endif 18 | 19 | #endif // JSON_AUTOLINK_H_INCLUDED 20 | -------------------------------------------------------------------------------- /libjson/json/config.h: -------------------------------------------------------------------------------- 1 | #ifndef JSON_CONFIG_H_INCLUDED 2 | # define JSON_CONFIG_H_INCLUDED 3 | 4 | /// If defined, indicates that json library is embedded in CppTL library. 5 | //# define JSON_IN_CPPTL 1 6 | 7 | /// If defined, indicates that json may leverage CppTL library 8 | //# define JSON_USE_CPPTL 1 9 | /// If defined, indicates that cpptl vector based map should be used instead of std::map 10 | /// as Value container. 11 | //# define JSON_USE_CPPTL_SMALLMAP 1 12 | /// If defined, indicates that Json specific container should be used 13 | /// (hash table & simple deque container with customizable allocator). 14 | /// THIS FEATURE IS STILL EXPERIMENTAL! 15 | //# define JSON_VALUE_USE_INTERNAL_MAP 1 16 | /// Force usage of standard new/malloc based allocator instead of memory pool based allocator. 17 | /// The memory pools allocator used optimization (initializing Value and ValueInternalLink 18 | /// as if it was a POD) that may cause some validation tool to report errors. 19 | /// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined. 20 | //# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1 21 | 22 | 23 | # ifdef JSON_IN_CPPTL 24 | # include 25 | # ifndef JSON_USE_CPPTL 26 | # define JSON_USE_CPPTL 1 27 | # endif 28 | # endif 29 | 30 | # ifdef JSON_IN_CPPTL 31 | # define JSON_API CPPTL_API 32 | # elif defined(JSON_DLL_BUILD) 33 | # define JSON_API __declspec(dllexport) 34 | # elif defined(JSON_DLL) 35 | # define JSON_API __declspec(dllimport) 36 | # else 37 | # define JSON_API 38 | # endif 39 | 40 | #endif // JSON_CONFIG_H_INCLUDED 41 | -------------------------------------------------------------------------------- /libjson/json/forwards.h: -------------------------------------------------------------------------------- 1 | #ifndef JSON_FORWARDS_H_INCLUDED 2 | # define JSON_FORWARDS_H_INCLUDED 3 | 4 | # include "config.h" 5 | 6 | namespace Json { 7 | 8 | class FastWriter; 9 | class Reader; 10 | class StyledWriter; 11 | 12 | // value.h 13 | class StaticString; 14 | class Path; 15 | class PathArgument; 16 | class Value; 17 | class ValueIteratorBase; 18 | class ValueIterator; 19 | class ValueConstIterator; 20 | #ifdef JSON_VALUE_USE_INTERNAL_MAP 21 | class ValueAllocator; 22 | class ValueMapAllocator; 23 | class ValueInternalLink; 24 | class ValueInternalArray; 25 | class ValueInternalMap; 26 | #endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP 27 | 28 | } // namespace Json 29 | 30 | 31 | #endif // JSON_FORWARDS_H_INCLUDED 32 | -------------------------------------------------------------------------------- /libjson/json/json.h: -------------------------------------------------------------------------------- 1 | #ifndef JSON_JSON_H_INCLUDED 2 | # define JSON_JSON_H_INCLUDED 3 | 4 | # include "autolink.h" 5 | # include "value.h" 6 | # include "reader.h" 7 | # include "writer.h" 8 | 9 | #endif // JSON_JSON_H_INCLUDED 10 | -------------------------------------------------------------------------------- /libjson/json_batchallocator.h: -------------------------------------------------------------------------------- 1 | #ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED 2 | # define JSONCPP_BATCHALLOCATOR_H_INCLUDED 3 | 4 | # include 5 | # include 6 | 7 | # ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION 8 | 9 | namespace Json { 10 | 11 | /* Fast memory allocator. 12 | * 13 | * This memory allocator allocates memory for a batch of object (specified by 14 | * the page size, the number of object in each page). 15 | * 16 | * It does not allow the destruction of a single object. All the allocated objects 17 | * can be destroyed at once. The memory can be either released or reused for future 18 | * allocation. 19 | * 20 | * The in-place new operator must be used to construct the object using the pointer 21 | * returned by allocate. 22 | */ 23 | template 25 | class BatchAllocator 26 | { 27 | public: 28 | typedef AllocatedType Type; 29 | 30 | BatchAllocator( unsigned int objectsPerPage = 255 ) 31 | : freeHead_( 0 ) 32 | , objectsPerPage_( objectsPerPage ) 33 | { 34 | // printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() ); 35 | assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space. 36 | assert( objectsPerPage >= 16 ); 37 | batches_ = allocateBatch( 0 ); // allocated a dummy page 38 | currentBatch_ = batches_; 39 | } 40 | 41 | ~BatchAllocator() 42 | { 43 | for ( BatchInfo *batch = batches_; batch; ) 44 | { 45 | BatchInfo *nextBatch = batch->next_; 46 | free( batch ); 47 | batch = nextBatch; 48 | } 49 | } 50 | 51 | /// allocate space for an array of objectPerAllocation object. 52 | /// @warning it is the responsability of the caller to call objects constructors. 53 | AllocatedType *allocate() 54 | { 55 | if ( freeHead_ ) // returns node from free list. 56 | { 57 | AllocatedType *object = freeHead_; 58 | freeHead_ = *(AllocatedType **)object; 59 | return object; 60 | } 61 | if ( currentBatch_->used_ == currentBatch_->end_ ) 62 | { 63 | currentBatch_ = currentBatch_->next_; 64 | while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ ) 65 | currentBatch_ = currentBatch_->next_; 66 | 67 | if ( !currentBatch_ ) // no free batch found, allocate a new one 68 | { 69 | currentBatch_ = allocateBatch( objectsPerPage_ ); 70 | currentBatch_->next_ = batches_; // insert at the head of the list 71 | batches_ = currentBatch_; 72 | } 73 | } 74 | AllocatedType *allocated = currentBatch_->used_; 75 | currentBatch_->used_ += objectPerAllocation; 76 | return allocated; 77 | } 78 | 79 | /// Release the object. 80 | /// @warning it is the responsability of the caller to actually destruct the object. 81 | void release( AllocatedType *object ) 82 | { 83 | assert( object != 0 ); 84 | *(AllocatedType **)object = freeHead_; 85 | freeHead_ = object; 86 | } 87 | 88 | private: 89 | struct BatchInfo 90 | { 91 | BatchInfo *next_; 92 | AllocatedType *used_; 93 | AllocatedType *end_; 94 | AllocatedType buffer_[objectPerAllocation]; 95 | }; 96 | 97 | // disabled copy constructor and assignement operator. 98 | BatchAllocator( const BatchAllocator & ); 99 | void operator =( const BatchAllocator &); 100 | 101 | static BatchInfo *allocateBatch( unsigned int objectsPerPage ) 102 | { 103 | const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation 104 | + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage; 105 | BatchInfo *batch = static_cast( malloc( mallocSize ) ); 106 | batch->next_ = 0; 107 | batch->used_ = batch->buffer_; 108 | batch->end_ = batch->buffer_ + objectsPerPage; 109 | return batch; 110 | } 111 | 112 | BatchInfo *batches_; 113 | BatchInfo *currentBatch_; 114 | /// Head of a single linked list within the allocated space of freeed object 115 | AllocatedType *freeHead_; 116 | unsigned int objectsPerPage_; 117 | }; 118 | 119 | 120 | } // namespace Json 121 | 122 | # endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION 123 | 124 | #endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED 125 | 126 | -------------------------------------------------------------------------------- /modules/build.mk: -------------------------------------------------------------------------------- 1 | MODULES = \ 2 | config \ 3 | echo \ 4 | help \ 5 | privileges \ 6 | snote \ 7 | userlist \ 8 | voicebot \ 9 | whoami \ 10 | core/channel \ 11 | core/ctcp \ 12 | core/die \ 13 | core/error \ 14 | core/join_channels \ 15 | core/mode \ 16 | core/nickserv \ 17 | core/oper \ 18 | core/ping \ 19 | logs/channel \ 20 | logs/stderr \ 21 | privs/account \ 22 | privs/hostmask \ 23 | storage/json 24 | 25 | storage/json_CXXFLAGS = -Ilibjson 26 | storage/json_LDFLAGS = -Wl,-rpath,$(LIBDIR) 27 | storage/json_LIBRARIES = libjson/json 28 | 29 | SUBDIRS = $(ENABLE_PERL) 30 | 31 | CXXFLAGS = -Isrc -fPIC 32 | 33 | # This might as well be here 34 | CREATE_DIRS = $(EIR_DATADIR) 35 | -------------------------------------------------------------------------------- /modules/config.cpp: -------------------------------------------------------------------------------- 1 | #include "eir.h" 2 | #include "handler.h" 3 | 4 | using namespace eir; 5 | 6 | struct Config : CommandHandlerBase, Module 7 | { 8 | void config(const Message *m) 9 | { 10 | if (m->args.empty()) 11 | { 12 | m->source.error("I need a setting name"); 13 | return; 14 | } 15 | 16 | Bot::SettingsIterator it1 = m->bot->find_setting(m->args[0]); 17 | if (it1 != m->bot->end_settings()) 18 | { 19 | m->source.reply(m->args[0] + " for " + m->bot->name() + " is " + (std::string)it1->second); 20 | return; 21 | } 22 | 23 | m->source.error("Can't find setting " + m->args[0]); 24 | } 25 | 26 | CommandHolder _id; 27 | 28 | Config() { _id = add_handler(filter_command_type("config", sourceinfo::IrcCommand), &Config::config); } 29 | }; 30 | 31 | MODULE_CLASS(Config) 32 | 33 | 34 | -------------------------------------------------------------------------------- /modules/core/ctcp.cpp: -------------------------------------------------------------------------------- 1 | #include "eir.h" 2 | 3 | #include 4 | 5 | using namespace eir; 6 | 7 | struct CtcpHandler : CommandHandlerBase, Module 8 | { 9 | void on_notice(const Message *m) 10 | { 11 | // Shouldn't happen, but check anyway. 12 | if (m->args.empty()) 13 | return; 14 | 15 | std::string text = m->args[0]; 16 | 17 | if (text[0] != '\001') 18 | return; 19 | 20 | text = text.substr(1); 21 | std::string::size_type pos = text.rfind('\001'); 22 | if (pos != std::string::npos) 23 | text.erase(pos); 24 | 25 | pos = text.find(' '); 26 | std::string command = text.substr(0, pos); 27 | std::string arg = text.substr(pos + 1); 28 | 29 | Message m2(*m, "ctcp_reply", sourceinfo::Internal); 30 | m2.args.push_back(command); 31 | m2.args.push_back(arg); 32 | CommandRegistry::get_instance()->dispatch(&m2); 33 | } 34 | 35 | CommandHolder _id; 36 | 37 | CtcpHandler() 38 | { 39 | _id = add_handler(filter_command_type("notice", sourceinfo::RawIrc), &CtcpHandler::on_notice); 40 | } 41 | }; 42 | 43 | MODULE_CLASS(CtcpHandler) 44 | 45 | -------------------------------------------------------------------------------- /modules/core/die.cpp: -------------------------------------------------------------------------------- 1 | #include "eir.h" 2 | 3 | #include "handler.h" 4 | 5 | using namespace eir; 6 | 7 | struct Die : CommandHandlerBase, Module 8 | { 9 | void die(const Message *m) 10 | { 11 | m->source.reply("Bye bye..."); 12 | Logger::get_instance()->Log(m->bot, m->source.client, Logger::Command, "DIE"); 13 | Logger::get_instance()->Log(m->bot, m->source.client, Logger::Admin, "DIE from " + m->source.raw); 14 | m->bot->disconnect("Shutting down (" + m->source.name + ")"); 15 | dispatch_internal_message(m->bot, "shutting_down"); 16 | throw DieException(m->source.client->nuh()); 17 | } 18 | void restart(const Message *m) 19 | { 20 | m->source.reply("Restarting..."); 21 | Logger::get_instance()->Log(m->bot, m->source.client, Logger::Command, "RESTART"); 22 | Logger::get_instance()->Log(m->bot, m->source.client, Logger::Admin, "RESTART from " + m->source.raw); 23 | m->bot->disconnect("Restarting (" + m->source.name + ")"); 24 | dispatch_internal_message(m->bot, "shutting_down"); 25 | throw RestartException(); 26 | } 27 | 28 | CommandHolder die_id, restart_id; 29 | 30 | Die() 31 | { 32 | die_id = add_handler(filter_command_privilege("die", "admin"), &Die::die); 33 | restart_id = add_handler(filter_command_privilege("restart", "admin"), &Die::restart); 34 | } 35 | }; 36 | 37 | MODULE_CLASS(Die) 38 | -------------------------------------------------------------------------------- /modules/core/error.cpp: -------------------------------------------------------------------------------- 1 | #include "eir.h" 2 | 3 | #include "handler.h" 4 | 5 | using namespace eir; 6 | 7 | struct ErrorHandler : CommandHandlerBase, Module 8 | { 9 | void error(const Message *m) 10 | { 11 | // ERROR is a strange command without a destination. 12 | // What we parse as the destination string is actually the error string. 13 | throw DisconnectedException(m->source.destination); 14 | } 15 | CommandHolder id; 16 | 17 | ErrorHandler() 18 | { 19 | id = add_handler(filter_command_type("ERROR", sourceinfo::RawIrc), &ErrorHandler::error); 20 | } 21 | }; 22 | 23 | MODULE_CLASS(ErrorHandler) 24 | -------------------------------------------------------------------------------- /modules/core/join_channels.cpp: -------------------------------------------------------------------------------- 1 | #include "eir.h" 2 | 3 | #include "handler.h" 4 | 5 | #include 6 | 7 | using namespace eir; 8 | 9 | struct JoinChannels : CommandHandlerBase, Module 10 | { 11 | std::list bot_channels; 12 | 13 | void add_channel(const Message *m) 14 | { 15 | if (m->args.empty()) 16 | { 17 | m->source.error("I need a channel name to join"); 18 | return; 19 | } 20 | 21 | bot_channels.push_back(m->args[0]); 22 | if (m->bot && m->bot->connected()) 23 | m->bot->send("JOIN " + m->args[0]); 24 | 25 | m->source.reply("Added channel " + m->args[0]); 26 | 27 | Logger::get_instance()->Log(m->bot, m->source.client, Logger::Info, "Adding channel " + m->args[0]); 28 | if (m->source.client) 29 | Logger::get_instance()->Log(m->bot, m->source.client, Logger::Command, m->raw); 30 | } 31 | 32 | void remove_channel(const Message *m) 33 | { 34 | if (m->args.empty()) 35 | { 36 | m->source.reply("Part where?"); 37 | return; 38 | } 39 | 40 | for (std::list::iterator it = bot_channels.begin(); 41 | it != bot_channels.end(); ++it) 42 | { 43 | if (*it == m->args[0]) 44 | bot_channels.erase(it++); 45 | } 46 | 47 | if (m->bot && m->bot->connected()) 48 | m->bot->send("PART " + m->args[0]); 49 | 50 | m->source.reply("Removed channel " + m->args[0]); 51 | 52 | Logger::get_instance()->Log(m->bot, m->source.client, Logger::Info, "Removing channel " + m->args[0]); 53 | if (m->source.client) 54 | Logger::get_instance()->Log(m->bot, m->source.client, Logger::Command, m->raw); 55 | } 56 | 57 | void on_connect(const Message *m) 58 | { 59 | for (std::list::iterator it = bot_channels.begin(); 60 | it != bot_channels.end(); ++it) 61 | { 62 | m->bot->send("JOIN " + *it); 63 | } 64 | } 65 | 66 | CommandHolder addch_id, join_id, rmch_id, part_id, conn_id; 67 | 68 | JoinChannels() 69 | { 70 | addch_id = add_handler(filter_command("channel").source_type(sourceinfo::ConfigFile), 71 | &JoinChannels::add_channel); 72 | join_id = add_handler(filter_command_type("join", sourceinfo::IrcCommand).requires_privilege("admin"), 73 | &JoinChannels::add_channel); 74 | part_id = add_handler(filter_command_type("part", sourceinfo::IrcCommand).requires_privilege("admin"), 75 | &JoinChannels::remove_channel); 76 | conn_id = add_handler(filter_command("001").source_type(sourceinfo::RawIrc), 77 | &JoinChannels::on_connect); 78 | } 79 | }; 80 | 81 | MODULE_CLASS(JoinChannels) 82 | 83 | 84 | -------------------------------------------------------------------------------- /modules/core/mode.cpp: -------------------------------------------------------------------------------- 1 | #include "eir.h" 2 | 3 | #include "handler.h" 4 | 5 | using namespace eir; 6 | 7 | struct ModeParser : CommandHandlerBase, Module 8 | { 9 | void check_mode_changes(const Message *m) 10 | { 11 | if (m->args.size() < 2) 12 | return; 13 | 14 | Message m2(*m, "mode " + m->args[1], sourceinfo::Internal); 15 | m2.args.push_back(m->args[0]); 16 | if (m->args.size() >= 3) 17 | m2.args.push_back(m->args[2]); 18 | 19 | CommandRegistry::get_instance()->dispatch(&m2); 20 | 21 | if (m->bot->supported()->get_mode_type(m->args[1][0]) == ISupport::prefix_mode && 22 | m->args.size() >= 3) 23 | { 24 | // Prefix mode -- update the client's Membership list. 25 | Client::ptr c = m->bot->find_client(m->args[2]); 26 | if (!c) 27 | return; 28 | 29 | Membership::ptr mem = c->find_membership(m->source.destination); 30 | if (!mem) 31 | return; 32 | 33 | if (m->args[0] == "add" && !mem->has_mode(m->args[1][0])) 34 | mem->modes += m->args[1][0]; 35 | else if (m->args[0] == "remove" && mem->has_mode(m->args[1][0])) 36 | mem->modes.erase(mem->modes.find(m->args[1][0])); 37 | } 38 | } 39 | 40 | void parse_mode(const Message *m) 41 | { 42 | if (! m->bot->supported()->is_channel_name(m->source.destination)) 43 | return; 44 | 45 | std::vector::const_iterator nextarg = m->args.begin(); 46 | std::string modes = *nextarg++; 47 | 48 | int dir = 0; 49 | for ( std::string::iterator ch = modes.begin(); ch != modes.end(); ++ch) 50 | { 51 | if (*ch == '+') 52 | dir = 1; 53 | else if (*ch == '-') 54 | dir = -1; 55 | else 56 | { 57 | Message m2(*m, "mode_change", sourceinfo::Internal); 58 | 59 | m2.args.push_back(dir > 0 ? "add" : "remove"); 60 | m2.args.push_back(std::string(1, *ch)); 61 | m2.raw = std::string("mode_change ") + m2.args[0] + " " + m2.args[1]; 62 | 63 | if (m->bot->supported()->mode_has_param(*ch, dir>0)) 64 | { 65 | m2.raw += " " + *nextarg; 66 | m2.args.push_back(*nextarg++); 67 | } 68 | 69 | CommandRegistry::get_instance()->dispatch(&m2); 70 | 71 | check_mode_changes(&m2); 72 | } 73 | } 74 | } 75 | 76 | CommandHolder mode_id; 77 | 78 | ModeParser() 79 | { 80 | mode_id = add_handler(filter_command_type("MODE", sourceinfo::RawIrc), &ModeParser::parse_mode); 81 | } 82 | }; 83 | 84 | MODULE_CLASS(ModeParser) 85 | -------------------------------------------------------------------------------- /modules/core/nickserv.cpp: -------------------------------------------------------------------------------- 1 | #include "eir.h" 2 | 3 | #include 4 | 5 | using namespace eir; 6 | 7 | struct Identifier : CommandHandlerBase, Module 8 | { 9 | void identify(const Message *m) 10 | { 11 | Bot::SettingsIterator it = m->bot->find_setting("nickserv_pass"); 12 | if(it == m->bot->end_settings()) 13 | return; 14 | 15 | std::string pass = it->second; 16 | 17 | std::string user(""); 18 | it = m->bot->find_setting("nickserv_user"); 19 | if(it != m->bot->end_settings()) 20 | user = (std::string)it->second; 21 | 22 | m->bot->send("NS IDENTIFY " + user + " " + pass); 23 | } 24 | 25 | CommandHolder _id; 26 | 27 | Identifier() { 28 | _id = add_handler(filter_command_type("001", sourceinfo::RawIrc), &Identifier::identify); 29 | } 30 | }; 31 | 32 | MODULE_CLASS(Identifier) 33 | -------------------------------------------------------------------------------- /modules/core/oper.cpp: -------------------------------------------------------------------------------- 1 | #include "eir.h" 2 | 3 | #include 4 | 5 | using namespace eir; 6 | 7 | struct Operer : CommandHandlerBase, Module 8 | { 9 | void oper(const Message *m) 10 | { 11 | Bot::SettingsIterator it = m->bot->find_setting("oper_pass"); 12 | if (it == m->bot->end_settings()) 13 | return; 14 | 15 | std::string pass = it->second; 16 | 17 | std::string user(m->bot->nick()); 18 | it = m->bot->find_setting("oper_name"); 19 | if(it != m->bot->end_settings()) 20 | user = (std::string)it->second; 21 | 22 | m->bot->send("OPER " + user + " " + pass); 23 | } 24 | 25 | void set_umode(const Message *m) 26 | { 27 | Bot::SettingsIterator it = m->bot->find_setting("oper_mode"); 28 | if (it == m->bot->end_settings()) 29 | return; 30 | 31 | std::string mode = it->second; 32 | 33 | m->bot->send("MODE " + m->bot->nick() + " " + mode); 34 | } 35 | 36 | CommandHolder connect_id, oper_up_id; 37 | 38 | Operer() { 39 | connect_id = add_handler(filter_command_type("001", sourceinfo::RawIrc), &Operer::oper); 40 | oper_up_id = add_handler(filter_command_type("381", sourceinfo::RawIrc), &Operer::set_umode); 41 | } 42 | }; 43 | 44 | MODULE_CLASS(Operer) 45 | -------------------------------------------------------------------------------- /modules/core/ping.cpp: -------------------------------------------------------------------------------- 1 | #include "eir.h" 2 | #include "handler.h" 3 | 4 | #include 5 | 6 | using namespace eir; 7 | 8 | struct Ponger : CommandHandlerBase, Module 9 | { 10 | CommandHolder _id; 11 | 12 | void pong(const eir::Message *m) 13 | { 14 | std::string response("PONG :" + m->source.destination); 15 | m->bot->send(response); 16 | } 17 | 18 | Ponger() { 19 | _id = add_handler(filter_command_type("PING", sourceinfo::RawIrc), &Ponger::pong); 20 | } 21 | }; 22 | 23 | MODULE_CLASS(Ponger) 24 | -------------------------------------------------------------------------------- /modules/dump_isupport.cpp: -------------------------------------------------------------------------------- 1 | #if 0 2 | #include "bot.h" 3 | #include "handler.h" 4 | 5 | using namespace eir; 6 | using namespace std::tr1::placeholders; 7 | 8 | struct Dumper : public CommandHandlerBase 9 | { 10 | void do_dump(const Message *m) 11 | { 12 | m->source.reply("simple modes: " + m->bot->supported()->simple_modes()); 13 | m->source.reply("list modes: " + m->bot->supported()->list_modes()); 14 | m->source.reply("oneparam modes: " + m->bot->supported()->oneparam_modes()); 15 | 16 | m->source.reply("isupport tokens:"); 17 | for(ISupport::simple_iterator it = m->bot->supported()->begin_simple_tokens(), 18 | ite = m->bot->supported()->end_simple_tokens(); 19 | it != ite; ++it) 20 | m->source.reply(" " + *it); 21 | 22 | m->source.reply("key-value tokens:"); 23 | for(ISupport::kv_iterator it = m->bot->supported()->begin_kv(), 24 | ite = m->bot->supported()->end_kv(); 25 | it != ite; ++it) 26 | m->source.reply(" " + it->first + " = " + it->second); 27 | 28 | } 29 | Dumper() { _id = add_handler("isupport", sourceinfo::IrcCommand, &Dumper::do_dump); } 30 | CommandHolder _id; 31 | } cd; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /modules/echo.cpp: -------------------------------------------------------------------------------- 1 | #include "eir.h" 2 | #include "handler.h" 3 | 4 | using namespace eir; 5 | 6 | struct echo : CommandHandlerBase, Module 7 | { 8 | void do_echo(const Message *m) 9 | { 10 | m->source.reply(m->args.at(0)); 11 | } 12 | 13 | CommandHolder _id; 14 | 15 | echo() { _id = add_handler(filter_command_type("echo", sourceinfo::IrcCommand), &echo::do_echo); } 16 | }; 17 | 18 | MODULE_CLASS(echo) 19 | 20 | -------------------------------------------------------------------------------- /modules/help.cpp: -------------------------------------------------------------------------------- 1 | #include "eir.h" 2 | #include "handler.h" 3 | #include "help.h" 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | using namespace eir; 11 | 12 | namespace 13 | { 14 | const char *help_help = "help -- Gives help on a given topic or command."; 15 | } 16 | 17 | struct helper : CommandHandlerBase, Module 18 | { 19 | void do_help(const Message *m, std::string topic) 20 | { 21 | Value& help_root = GlobalSettingsManager::get_instance()->get("help_root"); 22 | if (help_root.Type() != Value::kvarray) 23 | { 24 | m->source.error("No help has been defined"); 25 | return; 26 | } 27 | 28 | Value& help_topic = help_root[topic]; 29 | if (help_topic.Type() != Value::kvarray || 30 | ( !!help_topic["priv"] && 31 | (!m->source.client || !m->source.client->privs().has_privilege(help_topic["priv"])))) 32 | { 33 | m->source.error("No help for '" + topic + "'."); 34 | return; 35 | } 36 | 37 | if (!m->source.reply_func) 38 | return; 39 | 40 | std::list reply; 41 | paludis::tokenise 42 | (help_topic["text"], "\r\n", "", std::back_inserter(reply)); 43 | std::for_each(reply.begin(), reply.end(), m->source.reply_func); 44 | } 45 | 46 | void do_help_index(const Message *m) 47 | { 48 | std::list topics; 49 | Value& help_index = GlobalSettingsManager::get_instance()->get("help_index"); 50 | for (KeyValueArray::iterator it = help_index.KV().begin(); it != help_index.KV().end(); ++it) 51 | { 52 | if (it->second.String().empty() || 53 | (m->source.client && m->source.client->privs().has_privilege(it->second))) 54 | { 55 | topics.push_back(it->first); 56 | } 57 | } 58 | m->source.reply("Available help topics are: " + paludis::join(topics.begin(), topics.end(), " ")); 59 | } 60 | 61 | void help(const Message *m) 62 | { 63 | if (m->args.empty()) 64 | do_help_index(m); 65 | else 66 | do_help(m, m->args[0]); 67 | } 68 | 69 | CommandHolder _id; 70 | HelpTopicHolder helptopic; 71 | HelpIndexHolder index; 72 | 73 | helper() : helptopic("help", "", help_help), index("help", "") 74 | { _id = add_handler(filter_command_type("help", sourceinfo::IrcCommand), &helper::help); } 75 | }; 76 | 77 | MODULE_CLASS(helper) 78 | 79 | 80 | -------------------------------------------------------------------------------- /modules/logs/channel.cpp: -------------------------------------------------------------------------------- 1 | #include "eir.h" 2 | 3 | using namespace eir; 4 | 5 | struct ChannelLogger : public Module 6 | { 7 | struct Destination : public LogDestination 8 | { 9 | std::string channel; 10 | 11 | void Log(Bot *b, Client *c, std::string text) 12 | { 13 | if (b->connected()) 14 | b->send("PRIVMSG " + channel + " :(" + (c ? c->nick() : "") + ") " + text); 15 | } 16 | 17 | Destination(std::string ch) 18 | : channel(ch) 19 | { } 20 | }; 21 | 22 | struct Backend : public LogBackend 23 | { 24 | LogDestination *create_destination(std::string channel) 25 | { 26 | return new Destination(channel); 27 | } 28 | }; 29 | 30 | LogBackendHolder id; 31 | 32 | ChannelLogger() 33 | { 34 | id = Logger::get_instance()->register_backend("channel", new Backend); 35 | } 36 | }; 37 | 38 | MODULE_CLASS(ChannelLogger) 39 | 40 | -------------------------------------------------------------------------------- /modules/logs/stderr.cpp: -------------------------------------------------------------------------------- 1 | #include "eir.h" 2 | 3 | #include 4 | 5 | using namespace eir; 6 | 7 | struct StdErrLogger : public Module 8 | { 9 | struct Destination : public LogDestination 10 | { 11 | void Log(Bot *b, Client *, std::string text) 12 | { 13 | std::string::size_type p = text.rfind("\r\n"); 14 | if(p != std::string::npos) 15 | text = text.substr(0, p); 16 | else 17 | { 18 | p = text.rfind("\n"); 19 | if (p != std::string::npos) 20 | text = text.substr(0, p); 21 | } 22 | 23 | if (b) 24 | std::cerr << "[" << b->name() << "] "; 25 | std::cerr << text << std::endl; 26 | } 27 | }; 28 | 29 | struct Backend : public LogBackend 30 | { 31 | LogDestination *create_destination(std::string) 32 | { 33 | return new Destination; 34 | } 35 | }; 36 | 37 | LogBackendHolder id; 38 | 39 | StdErrLogger() 40 | { 41 | id = Logger::get_instance()->register_backend("stderr", new Backend); 42 | } 43 | }; 44 | 45 | MODULE_CLASS(StdErrLogger) 46 | -------------------------------------------------------------------------------- /modules/perl/api/HashWrappers.h: -------------------------------------------------------------------------------- 1 | #ifndef hash_wrappers_h 2 | #define hash_wrappers_h 3 | 4 | #include "bot.h" 5 | 6 | namespace eir 7 | { 8 | namespace perl 9 | { 10 | 11 | class BotChannelHash 12 | { 13 | Bot *_bot; 14 | public: 15 | BotChannelHash(Bot *b); 16 | Channel *FETCH(char *nick); 17 | bool EXISTS(char *nick); 18 | const char* FIRSTKEY(); 19 | const char* NEXTKEY(char *prevnick); 20 | int SCALAR(); 21 | }; 22 | 23 | class BotClientHash 24 | { 25 | Bot *_bot; 26 | public: 27 | BotClientHash(Bot *b); 28 | Client *FETCH(char *nick); 29 | bool EXISTS(char *nick); 30 | const char* FIRSTKEY(); 31 | const char* NEXTKEY(char *prevnick); 32 | int SCALAR(); 33 | }; 34 | 35 | class BotSettingsHash 36 | { 37 | Bot *_bot; 38 | public: 39 | BotSettingsHash(Bot *b); 40 | SV* FETCH(pTHX_ char *name); 41 | void STORE(pTHX_ char *name, SV *value); 42 | void DELETE(char *name); 43 | bool EXISTS(char *name); 44 | std::string FIRSTKEY(); 45 | std::string NEXTKEY(char *prevname); 46 | int SCALAR(); 47 | }; 48 | 49 | class ClientMembershipHash 50 | { 51 | Client *_client; 52 | public: 53 | ClientMembershipHash(Client *b); 54 | Membership *FETCH(char *nick); 55 | bool EXISTS(char *nick); 56 | const char* FIRSTKEY(); 57 | const char* NEXTKEY(char *prevnick); 58 | int SCALAR(); 59 | }; 60 | 61 | class ChannelMembershipHash 62 | { 63 | Channel *_channel; 64 | public: 65 | ChannelMembershipHash(Channel *b); 66 | Membership *FETCH(char *nick); 67 | bool EXISTS(char *nick); 68 | const char* FIRSTKEY(); 69 | const char* NEXTKEY(char *prevnick); 70 | int SCALAR(); 71 | }; 72 | 73 | } 74 | } 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /modules/perl/api/api.xs: -------------------------------------------------------------------------------- 1 | #include "stupid_perl_workarounds.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "eir.h" 8 | 9 | #include "HashWrappers.h" 10 | #include "perl_helpers.hh" 11 | #include "value_wrapper.hh" 12 | 13 | #include 14 | using namespace std::placeholders; 15 | 16 | 17 | using namespace eir; 18 | using namespace eir::perl; 19 | using std::string; 20 | 21 | // Include order matters here. type_maps.h MUST come after HashWrappers.h 22 | // and perl_helpers.hh, after the above using directives, and before 23 | // call_perl.hh. 24 | #include "util/type_maps.h" 25 | 26 | #include "util/call_perl.hh" 27 | 28 | 29 | // Macros used to turn xsubpp's exception-handling stubs into something vaguely useful. 30 | #define TRY try 31 | #define BEGHANDLERS catch (eir::Exception & e) \ 32 | { snprintf(errbuf, sizeof errbuf, "%s (%s)", e.message().c_str(), e.what()); } \ 33 | catch (std::exception & e) \ 34 | { snprintf(errbuf, sizeof errbuf, "Unknown exception (%s)", e.what()); } 35 | #define CATCHALL catch (...) { const char *Xname = "Unknown error", *Xreason = ""; 36 | #define ENDHANDLERS } 37 | 38 | MODULE = Eir PACKAGE = Eir 39 | 40 | Bot * 41 | find_bot(const char *name) 42 | CODE: 43 | RETVAL = BotManager::get_instance()->find(name); 44 | OUTPUT: 45 | RETVAL 46 | 47 | MODULE = Eir PACKAGE = Eir::Bot 48 | 49 | void 50 | Bot::send(char* name) 51 | 52 | string 53 | Bot::nick() 54 | 55 | string 56 | Bot::name() 57 | 58 | Capabilities * 59 | Bot::capabilities() 60 | 61 | 62 | INCLUDE: clients.xs 63 | INCLUDE: helpers.xs 64 | INCLUDE: messages.xs 65 | INCLUDE: handlers.xs 66 | INCLUDE: value.xs 67 | INCLUDE: logger.xs 68 | INCLUDE: storage.xs 69 | INCLUDE: capabilities.xs 70 | 71 | -------------------------------------------------------------------------------- /modules/perl/api/capabilities.xs: -------------------------------------------------------------------------------- 1 | MODULE = Eir PACKAGE = Eir::Capabilities 2 | 3 | void 4 | Capabilities::request(const char * cap) 5 | 6 | void 7 | Capabilities::hold() 8 | 9 | void 10 | Capabilities::finish() 11 | -------------------------------------------------------------------------------- /modules/perl/api/clients.xs: -------------------------------------------------------------------------------- 1 | MODULE = Eir PACKAGE = Eir::Client 2 | 3 | string 4 | Client::nick() 5 | 6 | string 7 | Client::user() 8 | 9 | string 10 | Client::host() 11 | 12 | string 13 | Client::nuh() 14 | 15 | string 16 | Client::account() 17 | 18 | int 19 | Client::has_privilege(...) 20 | CODE: 21 | const char *channel = "", *priv; 22 | if (items > 2) 23 | { 24 | channel = SvPV_nolen(ST(1)); 25 | priv = SvPV_nolen(ST(2)); 26 | } 27 | else 28 | { 29 | priv = SvPV_nolen(ST(1)); 30 | } 31 | RETVAL = THIS->privs().has_privilege(channel, priv); 32 | OUTPUT: 33 | RETVAL 34 | 35 | 36 | MODULE = Eir PACKAGE = Eir::Channel 37 | 38 | string 39 | Channel::name() 40 | 41 | MODULE = Eir PACKAGE = Eir::Membership 42 | 43 | Client * 44 | Membership::client() 45 | CODE: 46 | RETVAL = THIS->client.get(); 47 | OUTPUT: 48 | RETVAL 49 | 50 | Channel * 51 | Membership::channel() 52 | CODE: 53 | RETVAL = THIS->channel.get(); 54 | OUTPUT: 55 | RETVAL 56 | 57 | string 58 | Membership::modes() 59 | CODE: 60 | RETVAL = THIS->modes; 61 | OUTPUT: 62 | RETVAL 63 | 64 | int 65 | Membership::has_mode(char m) 66 | 67 | 68 | -------------------------------------------------------------------------------- /modules/perl/api/handlers.xs: -------------------------------------------------------------------------------- 1 | 2 | MODULE = Eir PACKAGE = Eir::CommandRegistry 3 | 4 | PerlHolder * 5 | add_handler(Filter *filter, SV *func, ...) 6 | CODE: 7 | bool quiet = false; 8 | Message::Order order = Message::normal; 9 | if (items > 2) 10 | quiet = (bool)SvIV(ST(2)); 11 | if (items > 3) 12 | order = (Message::Order)SvIV(ST(3)); 13 | CommandRegistry::id id = CommandRegistry::get_instance()->add_handler( 14 | *filter, 15 | std::bind(call_perl, 16 | aTHX_ "Eir::Init::call_wrapper", func, _1), 17 | quiet, 18 | order); 19 | RETVAL = new PerlCommandHolder(aTHX_ id, func); 20 | OUTPUT: 21 | RETVAL 22 | 23 | MODULE = Eir PACKAGE = Eir::EventManager 24 | 25 | PerlHolder * 26 | add_event(int time, SV *func) 27 | CODE: 28 | EventManager::id id = EventManager::get_instance()->add_event( 29 | time, 30 | std::bind(call_perl, 31 | aTHX_ "Eir::Init::call_wrapper", func)); 32 | RETVAL = new PerlEventHolder(aTHX_ id, func); 33 | OUTPUT: 34 | RETVAL 35 | 36 | PerlHolder * 37 | add_recurring_event(int time, SV *func) 38 | CODE: 39 | EventManager::id id = EventManager::get_instance()->add_recurring_event( 40 | time, 41 | std::bind(call_perl, 42 | aTHX_ "Eir::Init::call_wrapper", func)); 43 | RETVAL = new PerlEventHolder(aTHX_ id, func); 44 | OUTPUT: 45 | RETVAL 46 | -------------------------------------------------------------------------------- /modules/perl/api/helpers.xs: -------------------------------------------------------------------------------- 1 | MODULE = Eir PACKAGE = Eir::Internal::BotClientHash 2 | 3 | BotClientHash * 4 | TIEHASH(char *classname, Bot* bot) 5 | CODE: 6 | RETVAL = new BotClientHash(bot); 7 | OUTPUT: 8 | RETVAL 9 | 10 | Client * 11 | BotClientHash::FETCH(char *nick) 12 | 13 | void 14 | BotClientHash::STORE(char *nick, SV *foo) 15 | CODE: 16 | Perl_croak(aTHX_ "Tried to modify a read-only tied hash Bot::Clients"); 17 | 18 | void 19 | BotClientHash::DELETE(char *nick) 20 | CODE: 21 | Perl_croak(aTHX_ "Tried to modify a read-only tied hash Bot::Clients"); 22 | 23 | int 24 | BotClientHash::EXISTS(char *nick) 25 | 26 | const char * 27 | BotClientHash::FIRSTKEY() 28 | 29 | const char * 30 | BotClientHash::NEXTKEY(char *prev) 31 | 32 | void 33 | BotClientHash::DESTROY() 34 | 35 | int 36 | BotClientHash::SCALAR() 37 | 38 | 39 | MODULE = Eir PACKAGE = Eir::Internal::BotChannelHash 40 | 41 | BotChannelHash * 42 | TIEHASH(char *classname, Bot* bot) 43 | CODE: 44 | RETVAL = new BotChannelHash(bot); 45 | OUTPUT: 46 | RETVAL 47 | 48 | Channel * 49 | BotChannelHash::FETCH(char *nick) 50 | 51 | void 52 | BotChannelHash::STORE(char *nick, SV *foo) 53 | CODE: 54 | Perl_croak(aTHX_ "Tried to modify a read-only tied hash Bot::Channels"); 55 | 56 | void 57 | BotChannelHash::DELETE(char *nick) 58 | CODE: 59 | Perl_croak(aTHX_ "Tried to modify a read-only tied hash Bot::Channels"); 60 | 61 | int 62 | BotChannelHash::EXISTS(char *nick) 63 | 64 | const char * 65 | BotChannelHash::FIRSTKEY() 66 | 67 | const char * 68 | BotChannelHash::NEXTKEY(char *prev) 69 | 70 | void 71 | BotChannelHash::DESTROY() 72 | 73 | int 74 | BotChannelHash::SCALAR() 75 | 76 | 77 | MODULE = Eir PACKAGE = Eir::Internal::BotSettingsHash 78 | 79 | BotSettingsHash * 80 | TIEHASH(char *classname, Bot* bot) 81 | CODE: 82 | RETVAL = new BotSettingsHash(bot); 83 | OUTPUT: 84 | RETVAL 85 | 86 | SV * 87 | BotSettingsHash::FETCH(char *name) 88 | CODE: 89 | RETVAL = THIS->FETCH(aTHX_ name); 90 | OUTPUT: 91 | RETVAL 92 | 93 | void 94 | BotSettingsHash::STORE(char *name, SV *value) 95 | CODE: 96 | THIS->STORE(aTHX_ name, value); 97 | 98 | void 99 | BotSettingsHash::DELETE(char *name) 100 | 101 | int 102 | BotSettingsHash::EXISTS(char *name) 103 | 104 | string 105 | BotSettingsHash::FIRSTKEY() 106 | 107 | string 108 | BotSettingsHash::NEXTKEY(char *prev) 109 | 110 | void 111 | BotSettingsHash::DESTROY() 112 | 113 | int 114 | BotSettingsHash::SCALAR() 115 | 116 | 117 | MODULE = Eir PACKAGE = Eir::Internal::ClientMembershipHash 118 | 119 | ClientMembershipHash * 120 | TIEHASH(char *classname, Client* client) 121 | CODE: 122 | RETVAL = new ClientMembershipHash(client); 123 | OUTPUT: 124 | RETVAL 125 | 126 | Membership * 127 | ClientMembershipHash::FETCH(char *name) 128 | 129 | void 130 | ClientMembershipHash::STORE(char *name, SV *foo) 131 | CODE: 132 | Perl_croak(aTHX_ "Tried to modify a read-only tied hash Bot::Channels"); 133 | 134 | void 135 | ClientMembershipHash::DELETE(char *name) 136 | CODE: 137 | Perl_croak(aTHX_ "Tried to modify a read-only tied hash Bot::Channels"); 138 | 139 | int 140 | ClientMembershipHash::EXISTS(char *name) 141 | 142 | const char * 143 | ClientMembershipHash::FIRSTKEY() 144 | 145 | const char * 146 | ClientMembershipHash::NEXTKEY(char *prev) 147 | 148 | void 149 | ClientMembershipHash::DESTROY() 150 | 151 | int 152 | ClientMembershipHash::SCALAR() 153 | 154 | 155 | MODULE = Eir PACKAGE = Eir::Internal::ChannelMembershipHash 156 | 157 | ChannelMembershipHash * 158 | TIEHASH(char *classname, Channel* channel) 159 | CODE: 160 | RETVAL = new ChannelMembershipHash(channel); 161 | OUTPUT: 162 | RETVAL 163 | 164 | Membership * 165 | ChannelMembershipHash::FETCH(char *name) 166 | 167 | void 168 | ChannelMembershipHash::STORE(char *name, SV *foo) 169 | CODE: 170 | Perl_croak(aTHX_ "Tried to modify a read-only tied hash Bot::Channels"); 171 | 172 | void 173 | ChannelMembershipHash::DELETE(char *name) 174 | CODE: 175 | Perl_croak(aTHX_ "Tried to modify a read-only tied hash Bot::Channels"); 176 | 177 | int 178 | ChannelMembershipHash::EXISTS(char *name) 179 | 180 | const char * 181 | ChannelMembershipHash::FIRSTKEY() 182 | 183 | const char * 184 | ChannelMembershipHash::NEXTKEY(char *prev) 185 | 186 | void 187 | ChannelMembershipHash::DESTROY() 188 | 189 | int 190 | ChannelMembershipHash::SCALAR() 191 | 192 | 193 | MODULE = Eir PACKAGE = Eir::Internal::PerlHolder 194 | 195 | void 196 | PerlHolder::DESTROY() 197 | 198 | 199 | -------------------------------------------------------------------------------- /modules/perl/api/logger.xs: -------------------------------------------------------------------------------- 1 | 2 | MODULE = Eir PACKAGE = Eir::Logger 3 | 4 | int 5 | Debug() 6 | CODE: 7 | RETVAL = Logger::Debug; 8 | OUTPUT: 9 | RETVAL 10 | 11 | int 12 | Command() 13 | CODE: 14 | RETVAL = Logger::Command; 15 | OUTPUT: 16 | RETVAL 17 | 18 | int 19 | Info() 20 | CODE: 21 | RETVAL = Logger::Info; 22 | OUTPUT: 23 | RETVAL 24 | 25 | int 26 | Privs() 27 | CODE: 28 | RETVAL = Logger::Privs; 29 | OUTPUT: 30 | RETVAL 31 | 32 | int 33 | Warning() 34 | CODE: 35 | RETVAL = Logger::Warning; 36 | OUTPUT: 37 | RETVAL 38 | 39 | int 40 | Raw() 41 | CODE: 42 | RETVAL = Logger::Raw; 43 | OUTPUT: 44 | RETVAL 45 | 46 | int 47 | Admin() 48 | CODE: 49 | RETVAL = Logger::Admin; 50 | OUTPUT: 51 | RETVAL 52 | 53 | void 54 | Log(...) 55 | PPCODE: 56 | if (items < 2) 57 | Perl_croak(aTHX_ "usage: Eir::Logger::Log([bot,[client,]] type, text)"); 58 | 59 | Bot *bot = 0; 60 | Client *client = 0; 61 | int type = 0; 62 | const char *text = 0; 63 | int argc = 0; 64 | if (sv_isobject(ST(argc)) && sv_derived_from(ST(argc), PerlClassMap::name())) 65 | { 66 | bot = (Bot*)SvIV((SV*)SvRV(ST(argc))); 67 | ++argc; 68 | if (sv_isobject(ST(argc)) && sv_derived_from(ST(argc), PerlClassMap::name())) 69 | { 70 | client = (Client*)SvIV((SV*)SvRV(ST(argc))); 71 | ++argc; 72 | } 73 | } 74 | if (items < argc + 2) 75 | Perl_croak(aTHX_ "usage: Eir::Logger::Log([bot,[client,]] type, text)"); 76 | 77 | type = SvIV(ST(argc)); 78 | ++argc; 79 | text = SvPV_nolen(ST(argc)); 80 | Logger::get_instance()->Log(bot, client, type, text); 81 | -------------------------------------------------------------------------------- /modules/perl/api/messages.xs: -------------------------------------------------------------------------------- 1 | MODULE = Eir PACKAGE = Eir::Filter 2 | 3 | Filter * 4 | do_new(const char *classname) 5 | CODE: 6 | RETVAL = new Filter(); 7 | OUTPUT: 8 | RETVAL 9 | 10 | Filter * 11 | Filter::is_command(const char *cmd) 12 | CODE: 13 | THIS->is_command(cmd); 14 | RETVAL = THIS; 15 | OUTPUT: 16 | RETVAL 17 | 18 | Filter * 19 | Filter::source_type(int type) 20 | CODE: 21 | THIS->source_type(type); 22 | RETVAL = THIS; 23 | OUTPUT: 24 | RETVAL 25 | 26 | Filter * 27 | Filter::source_named(const char *src) 28 | CODE: 29 | THIS->source_named(src); 30 | RETVAL = THIS; 31 | OUTPUT: 32 | RETVAL 33 | 34 | Filter * 35 | Filter::from_bot(Bot *b) 36 | CODE: 37 | THIS->from_bot(b); 38 | RETVAL = THIS; 39 | OUTPUT: 40 | RETVAL 41 | 42 | Filter * 43 | Filter::in_private() 44 | CODE: 45 | THIS->in_private(); 46 | RETVAL = THIS; 47 | OUTPUT: 48 | RETVAL 49 | 50 | Filter * 51 | Filter::in_channel(const char *chan) 52 | CODE: 53 | THIS->in_channel(chan); 54 | RETVAL = THIS; 55 | OUTPUT: 56 | RETVAL 57 | 58 | Filter * 59 | Filter::requires_privilege(const char *priv) 60 | CODE: 61 | THIS->requires_privilege(priv); 62 | RETVAL = THIS; 63 | OUTPUT: 64 | RETVAL 65 | 66 | Filter * 67 | Filter::or_config() 68 | CODE: 69 | THIS->or_config(); 70 | RETVAL = THIS; 71 | OUTPUT: 72 | RETVAL 73 | 74 | int 75 | Filter::match(const Message *m) 76 | 77 | 78 | MODULE = Eir PACKAGE = Eir::Message 79 | 80 | int 81 | First() 82 | CODE: 83 | RETVAL = Message::first; 84 | OUTPUT: 85 | RETVAL 86 | 87 | int 88 | Normal() 89 | CODE: 90 | RETVAL = Message::normal; 91 | OUTPUT: 92 | RETVAL 93 | 94 | int 95 | Last() 96 | CODE: 97 | RETVAL = Message::last; 98 | OUTPUT: 99 | RETVAL 100 | 101 | Bot * 102 | Message::bot() const 103 | CODE: 104 | RETVAL = THIS->bot; 105 | OUTPUT: 106 | RETVAL 107 | 108 | string 109 | Message::command() const 110 | CODE: 111 | RETVAL = THIS->command; 112 | OUTPUT: 113 | RETVAL 114 | 115 | string 116 | Message::raw() const 117 | CODE: 118 | RETVAL = THIS->raw; 119 | OUTPUT: 120 | RETVAL 121 | 122 | SV * 123 | Message::args() const 124 | CODE: 125 | AV *ret = newAV(); 126 | for (auto it = THIS->args.begin(); it != THIS->args.end(); ++it) 127 | av_push(ret, newSVpv(it->c_str(), 0)); 128 | RETVAL = newRV_noinc((SV*)ret); 129 | OUTPUT: 130 | RETVAL 131 | 132 | SV * 133 | Message::source() const 134 | CODE: 135 | HV *ret = newHV(); 136 | hv_store(ret, "type", 4, newSViv(THIS->source.type), 0); 137 | SV *client = newSV(0); 138 | sv_setref_pv(client, "Eir::Client", THIS->source.client.get()); 139 | hv_store(ret, "client", 6, client, 0); 140 | hv_store(ret, "name", 4, newSVpv(THIS->source.name.c_str(), 0), 0); 141 | hv_store(ret, "raw", 3, newSVpv(THIS->source.raw.c_str(), 0), 0); 142 | hv_store(ret, "destination", 11, newSVpv(THIS->source.destination.c_str(), 0), 0); 143 | 144 | RETVAL = newRV_noinc((SV*)ret); 145 | OUTPUT: 146 | RETVAL 147 | 148 | void 149 | Message::error(const char *str) const 150 | CODE: 151 | THIS->source.error(str); 152 | 153 | 154 | void 155 | Message::reply(const char *str) const 156 | CODE: 157 | THIS->source.reply(str); 158 | 159 | 160 | MODULE = Eir PACKAGE = Eir::Source 161 | 162 | int 163 | RawIrc() 164 | CODE: 165 | RETVAL = sourceinfo::RawIrc; 166 | OUTPUT: 167 | RETVAL 168 | 169 | int 170 | ConfigFile() 171 | CODE: 172 | RETVAL = sourceinfo::ConfigFile; 173 | OUTPUT: 174 | RETVAL 175 | 176 | int 177 | SystemConsole() 178 | CODE: 179 | RETVAL = sourceinfo::SystemConsole; 180 | OUTPUT: 181 | RETVAL 182 | 183 | int 184 | Signal() 185 | CODE: 186 | RETVAL = sourceinfo::Signal; 187 | OUTPUT: 188 | RETVAL 189 | 190 | int 191 | Internal() 192 | CODE: 193 | RETVAL = sourceinfo::Internal; 194 | OUTPUT: 195 | RETVAL 196 | 197 | int 198 | IrcCommand() 199 | CODE: 200 | RETVAL = sourceinfo::IrcCommand; 201 | OUTPUT: 202 | RETVAL 203 | 204 | int 205 | Any() 206 | CODE: 207 | RETVAL = sourceinfo::Any; 208 | OUTPUT: 209 | RETVAL 210 | 211 | -------------------------------------------------------------------------------- /modules/perl/api/perl_helpers.cpp: -------------------------------------------------------------------------------- 1 | #include "stupid_perl_workarounds.h" 2 | #include 3 | #include 4 | 5 | #include "eir.h" 6 | #include "perl_helpers.hh" 7 | 8 | using namespace eir::perl; 9 | 10 | PerlHolder::~PerlHolder() 11 | { 12 | } 13 | -------------------------------------------------------------------------------- /modules/perl/api/perl_helpers.hh: -------------------------------------------------------------------------------- 1 | #ifndef perl_helpers_hh 2 | #define perl_helpers_hh 3 | 4 | #include 5 | 6 | namespace eir 7 | { 8 | namespace perl 9 | { 10 | class PerlHolder 11 | { 12 | public: 13 | virtual ~PerlHolder() = 0; 14 | }; 15 | 16 | class PerlCommandHolder : public PerlHolder 17 | { 18 | CommandRegistry::id _id; 19 | SV *_command; 20 | PerlInterpreter *_perl; 21 | 22 | public: 23 | PerlCommandHolder(pTHX_ CommandRegistry::id i, SV *cmd) 24 | : _id(i), _command(cmd), _perl(aTHX) 25 | { 26 | SvREFCNT_inc(cmd); 27 | } 28 | 29 | ~PerlCommandHolder() 30 | { 31 | PerlInterpreter *my_perl = _perl; 32 | CommandRegistry::get_instance()->remove_handler(_id); 33 | SvREFCNT_dec(_command); 34 | } 35 | }; 36 | 37 | class PerlEventHolder : public PerlHolder 38 | { 39 | EventManager::id _id; 40 | SV *_handler; 41 | PerlInterpreter *_perl; 42 | 43 | public: 44 | PerlEventHolder(pTHX_ EventManager::id i, SV *h) 45 | : _id(i), _handler(h), _perl(aTHX) 46 | { 47 | SvREFCNT_inc(h); 48 | } 49 | ~PerlEventHolder() 50 | { 51 | PerlInterpreter *my_perl = _perl; 52 | EventManager::get_instance()->remove_event(_id); 53 | SvREFCNT_dec(_handler); 54 | } 55 | }; 56 | } 57 | } 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /modules/perl/api/storage.xs: -------------------------------------------------------------------------------- 1 | 2 | MODULE = Eir PACKAGE = Eir::Storage 3 | 4 | void 5 | Save(SV *ref, const char *dest) 6 | CODE: 7 | StorageManager::get_instance()->Save(value_from_sv(aTHX_ ref), dest); 8 | 9 | void 10 | auto_save(SV *ref, const char *dest) 11 | CODE: 12 | Value *v = value_star_from_sv(aTHX_ ref); 13 | if (!v) 14 | Perl_croak(aTHX_ "Eir::Storage::auto_save requires a persistent Value reference"); 15 | 16 | StorageManager::get_instance()->auto_save(v, dest); 17 | 18 | SV * 19 | Load(const char *source) 20 | CODE: 21 | Value *v = new Value; 22 | *v = StorageManager::get_instance()->Load(source); 23 | RETVAL = sv_from_value(aTHX_ v, true); 24 | OUTPUT: 25 | RETVAL 26 | -------------------------------------------------------------------------------- /modules/perl/api/typemap: -------------------------------------------------------------------------------- 1 | TYPEMAP 2 | Bot * O_OBJECT 3 | Client * O_OBJECT 4 | Channel * O_OBJECT 5 | Membership * O_OBJECT 6 | Capabilities * O_OBJECT 7 | 8 | Filter * O_OBJECT 9 | const Message * O_OBJECT 10 | 11 | BotClientHash * O_OBJECT 12 | BotChannelHash * O_OBJECT 13 | BotSettingsHash * O_OBJECT 14 | ClientMembershipHash * O_OBJECT 15 | ChannelMembershipHash * O_OBJECT 16 | PerlHolder * O_OBJECT 17 | 18 | ArrayValueWrapper * O_OBJECT 19 | HashValueWrapper * O_OBJECT 20 | 21 | string O_STDSTRING 22 | 23 | OUTPUT 24 | O_OBJECT 25 | sv_setref_pv( $arg, PerlClassMap<${(my $ntt=$ntype)=~s/Ptr$/*/;\$ntt}>::name(), (void*)$var ); 26 | 27 | O_STDSTRING 28 | sv_setpv($arg, $var.c_str()); 29 | 30 | INPUT 31 | O_OBJECT 32 | if (sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG) && 33 | sv_derived_from($arg, PerlClassMap<${(my $ntt=$ntype)=~s/Ptr$/*/;\$ntt}>::name())) 34 | $var = ($type)SvIV((SV*)SvRV($arg)); 35 | else 36 | { 37 | Perl_croak(aTHX_ \"${Package}::$func_name() -- $var is not a blessed SV reference\" ); 38 | XSRETURN_UNDEF; 39 | } 40 | -------------------------------------------------------------------------------- /modules/perl/api/value.xs: -------------------------------------------------------------------------------- 1 | 2 | MODULE = Eir PACKAGE = Eir::Settings 3 | 4 | SV* 5 | Add(const char *name, SV *val) 6 | CODE: 7 | GlobalSettingsManager::get_instance()->add(name, value_from_sv(aTHX_ val)); 8 | RETVAL = sv_from_value(aTHX_ &GlobalSettingsManager::get_instance()->get(name)); 9 | OUTPUT: 10 | RETVAL 11 | 12 | 13 | SV* 14 | Find(const char *name) 15 | CODE: 16 | RETVAL = sv_from_value(aTHX_ &GlobalSettingsManager::get_instance()->get(name)); 17 | OUTPUT: 18 | RETVAL 19 | 20 | 21 | 22 | MODULE = Eir PACKAGE = Eir::Internal::ArrayValueWrapper 23 | 24 | SV * 25 | ArrayValueWrapper::FETCH(int idx) 26 | CODE: 27 | RETVAL = THIS->FETCH(aTHX_ idx); 28 | OUTPUT: 29 | RETVAL 30 | 31 | int 32 | ArrayValueWrapper::FETCHSIZE() 33 | CODE: 34 | RETVAL = THIS->FETCHSIZE(aTHX); 35 | OUTPUT: 36 | RETVAL 37 | 38 | void 39 | ArrayValueWrapper::STORE(int idx, SV *sv) 40 | CODE: 41 | THIS->STORE(aTHX_ idx, sv); 42 | 43 | void 44 | ArrayValueWrapper::STORESIZE(int newsize) 45 | CODE: 46 | THIS->STORESIZE(aTHX_ newsize); 47 | 48 | void 49 | ArrayValueWrapper::EXTEND(int by) 50 | CODE: 51 | THIS->_EXTEND(aTHX_ by); 52 | 53 | int 54 | ArrayValueWrapper::EXISTS(int idx) 55 | CODE: 56 | RETVAL = THIS->EXISTS(aTHX_ idx); 57 | OUTPUT: 58 | RETVAL 59 | 60 | void 61 | ArrayValueWrapper::DELETE(int idx) 62 | CODE: 63 | THIS->DELETE(aTHX_ idx); 64 | 65 | void 66 | ArrayValueWrapper::CLEAR() 67 | CODE: 68 | THIS->CLEAR(aTHX); 69 | 70 | void 71 | ArrayValueWrapper::PUSH(...) 72 | CODE: 73 | // Start at 1; assume ST(0) == THIS 74 | for (int i=1; i < items; ++i) 75 | THIS->PUSH(aTHX_ ST(i)); 76 | 77 | SV * 78 | ArrayValueWrapper::POP() 79 | CODE: 80 | RETVAL = THIS->POP(aTHX); 81 | OUTPUT: 82 | RETVAL 83 | 84 | SV * 85 | ArrayValueWrapper::SHIFT() 86 | CODE: 87 | RETVAL = THIS->SHIFT(aTHX); 88 | OUTPUT: 89 | RETVAL 90 | 91 | void 92 | ArrayValueWrapper::UNSHIFT() 93 | CODE: 94 | for (int i=1; i < items; ++i) 95 | THIS->UNSHIFT(aTHX_ ST(i)); 96 | 97 | void 98 | ArrayValueWrapper::DESTROY() 99 | 100 | MODULE = Eir PACKAGE = Eir::Internal::HashValueWrapper 101 | 102 | SV * 103 | HashValueWrapper::FETCH(SV *key) 104 | CODE: 105 | RETVAL = THIS->FETCH(aTHX_ key); 106 | OUTPUT: 107 | RETVAL 108 | 109 | void 110 | HashValueWrapper::STORE(SV *key, SV *val) 111 | CODE: 112 | THIS->STORE(aTHX_ key, val); 113 | 114 | void 115 | HashValueWrapper::DELETE(SV *key) 116 | CODE: 117 | THIS->DELETE(aTHX_ key); 118 | 119 | void 120 | HashValueWrapper::CLEAR() 121 | CODE: 122 | THIS->CLEAR(aTHX); 123 | 124 | int 125 | HashValueWrapper::EXISTS(SV *key) 126 | CODE: 127 | RETVAL = THIS->EXISTS(aTHX_ key); 128 | OUTPUT: 129 | RETVAL 130 | 131 | SV * 132 | HashValueWrapper::FIRSTKEY() 133 | CODE: 134 | RETVAL = THIS->FIRSTKEY(aTHX); 135 | OUTPUT: 136 | RETVAL 137 | 138 | SV * 139 | HashValueWrapper::NEXTKEY(SV *prevkey) 140 | CODE: 141 | RETVAL = THIS->NEXTKEY(aTHX_ prevkey); 142 | OUTPUT: 143 | RETVAL 144 | 145 | void 146 | HashValueWrapper::DESTROY() 147 | -------------------------------------------------------------------------------- /modules/perl/api/value_wrapper.hh: -------------------------------------------------------------------------------- 1 | #ifndef value_wrapper_hh 2 | #define value_wrapper_hh 3 | 4 | namespace eir 5 | { 6 | namespace perl 7 | { 8 | SV *sv_from_value(pTHX_ Value *, bool owned = false); 9 | Value value_from_sv(pTHX_ SV *); 10 | Value* value_star_from_sv(pTHX_ SV *); 11 | 12 | struct ArrayValueWrapper 13 | { 14 | Value *_value; 15 | bool _owned; 16 | 17 | ArrayValueWrapper(pTHX_ Value *, bool = false); 18 | ~ArrayValueWrapper(); 19 | SV *FETCH(pTHX_ int); 20 | int FETCHSIZE(pTHX); 21 | void STORE(pTHX_ int, SV *); 22 | void STORESIZE(pTHX_ int); 23 | void _EXTEND(pTHX_ int); 24 | int EXISTS(pTHX_ int); 25 | void DELETE(pTHX_ int); 26 | void CLEAR(pTHX); 27 | void PUSH(pTHX_ SV *); 28 | SV *POP(pTHX); 29 | SV *SHIFT(pTHX); 30 | void UNSHIFT(pTHX_ SV *); 31 | }; 32 | 33 | struct HashValueWrapper 34 | { 35 | Value *_value; 36 | bool _owned; 37 | 38 | HashValueWrapper(pTHX_ Value *, bool = false); 39 | ~HashValueWrapper(); 40 | SV *FETCH(pTHX_ SV*); 41 | void STORE(pTHX_ SV*, SV*); 42 | void DELETE(pTHX_ SV*); 43 | void CLEAR(pTHX); 44 | int EXISTS(pTHX_ SV*); 45 | SV* FIRSTKEY(pTHX); 46 | SV* NEXTKEY(pTHX_ SV*); 47 | }; 48 | } 49 | } 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /modules/perl/build.mk: -------------------------------------------------------------------------------- 1 | MODULES = perl 2 | perl_SOURCES = perl.cpp perlxsi.c 3 | 4 | $(GENERATED_SOURCE_DIR)/perlxsi.c: 5 | perl -MExtUtils::Embed -e xsinit -- -o $@ 6 | 7 | DSOS = api 8 | 9 | api_FILENAME = $(MODDIR)/perl/api/Eir.so 10 | 11 | api_SOURCES = HashWrappers.cpp perl_helpers.cpp value_wrapper.cpp api.xs 12 | api_SRCDIRS = api 13 | api_CXXFLAGS = -Imodules/perl/api 14 | 15 | CPPFLAGS = -fPIC -Isrc -Imodules/perl $(PERL_CFLAGS) \ 16 | -Wno-unused-parameter -Wno-unused-but-set-variable \ 17 | -Wno-unused-variable -Wno-write-strings -Wno-format-security -DPERL_GCC_PEDANTIC 18 | 19 | LDFLAGS = $(PERL_LIBS) 20 | 21 | XSFLAGS = -except -typemap typemap 22 | 23 | DATADIR = $(MODDIR)/perl 24 | DATA = lib 25 | -------------------------------------------------------------------------------- /modules/perl/definitions.h: -------------------------------------------------------------------------------- 1 | #define MODULE_DATA_PATH "modules/perl/" 2 | 3 | #define PERL_INIT_FILE MODULE_DATA_PATH "lib/init.pl" 4 | -------------------------------------------------------------------------------- /modules/perl/extra.mk: -------------------------------------------------------------------------------- 1 | PERL_INCLUDES := $(shell perl -MExtUtils::Embed -e ccopts) -Imodules/perl/ -Wno-format-security 2 | PERL_LDFLAGS := $(shell perl -MExtUtils::Embed -e ldopts) 3 | 4 | APIDIR=modules/perl/api 5 | 6 | # First, add the right compiler flags to build the main perl.so module 7 | 8 | EXTRA_CXXFLAGS_perl= $(PERL_INCLUDES) $(PERL_LDFLAGS) \ 9 | -Wno-unused-variable -Wno-write-strings \ 10 | -DPERL_GCC_PEDANTIC 11 | 12 | # The perl module also require the generated definition of xs_init... 13 | modules/perl/perl.so: modules/perl/perlxsi.c 14 | 15 | modules/perl/perlxsi.c: 16 | perl -MExtUtils::Embed -e xsinit -- -o $@ 17 | 18 | # Then, define how to build the api library. 19 | 20 | modules/perl/perl.so: | $(APIDIR)/Eir.so 21 | 22 | PERLAPI_SOURCES = api_XS.cpp HashWrappers.cpp perl_helpers.cpp value_wrapper.cpp 23 | 24 | .PRECIOUS: $(APIDIR)/%_XS.cpp 25 | 26 | # The perl substitution here is necessary as xsubpp seems to have a stupid bug in its 27 | # -except handling (using '\0' in a heredoc), causing it to put NUL characters into the 28 | # generated source file. GCC does not like this. 29 | $(APIDIR)/%_XS.cpp: $(APIDIR)/%.xs $(APIDIR)/typemap $(wildcard $(APIDIR)/*.xs) 30 | xsubpp -csuffix _XS.cpp -typemap typemap -except $< | perl -pe 's/\0/\\0/g' >$@ ; [[ $$PIPESTATUS -eq 0 ]] || ( rm -f $@; false ) 31 | 32 | PERLAPI_OBJS = $(addprefix $(APIDIR)/,$(addsuffix .o,$(basename $(PERLAPI_SOURCES)))) 33 | 34 | $(APIDIR)/%.o: $(APIDIR)/%.cpp 35 | $(CXX) $(CXXFLAGS) $(mod_INCLUDES) $(PERL_INCLUDES) \ 36 | -Wno-unused-variable -Wno-write-strings -Wno-unused \ 37 | -DPERL_GCC_PEDANTIC \ 38 | -fPIC -c -o$@ $< 39 | 40 | $(APIDIR)/Eir.so: $(PERLAPI_OBJS) 41 | $(CXX) -shared -o $@ $^ 42 | 43 | 44 | $(APIDIR)/.depend: $(addprefix $(APIDIR)/,$(PERLAPI_SOURCES)) 45 | $(CXX) -MM -MG $(CXXFLAGS) $(PERL_INCLUDES) $(mod_INCLUDES) $^ 2>/dev/null | sed 's!\(^[^ ]*\.o\):!$(APIDIR)/\1:!' >$@ 46 | 47 | clean_perl: 48 | rm -f modules/perl/api/Eir.so $(PERLAPI_OBJS) 49 | 50 | clean: clean_perl 51 | 52 | 53 | -include $(APIDIR)/.depend 54 | -------------------------------------------------------------------------------- /modules/perl/lib/Eir.pm: -------------------------------------------------------------------------------- 1 | package Eir; 2 | 3 | require Exporter; 4 | require DynaLoader; 5 | @ISA = qw(Exporter DynaLoader); 6 | @EXPORT = qw( find_bot ); 7 | 8 | bootstrap Eir; 9 | 10 | package Eir::Bot; 11 | 12 | sub Clients { 13 | my ($self) = @_; 14 | my $ret = {}; 15 | tie %$ret, 'Eir::Internal::BotClientHash', $self; 16 | return $ret; 17 | } 18 | 19 | sub Channels { 20 | my ($self) = @_; 21 | my $ret = {}; 22 | tie %$ret, 'Eir::Internal::BotChannelHash', $self; 23 | return $ret; 24 | } 25 | 26 | sub Settings { 27 | my ($self) = @_; 28 | my $ret = {}; 29 | tie %$ret, 'Eir::Internal::BotSettingsHash', $self; 30 | return $ret; 31 | } 32 | 33 | package Eir::Client; 34 | 35 | sub Channels { 36 | my ($self) = @_; 37 | my $ret = {}; 38 | tie %$ret, 'Eir::Internal::ClientMembershipHash', $self; 39 | return $ret; 40 | } 41 | 42 | package Eir::Channel; 43 | 44 | sub Members { 45 | my ($self) = @_; 46 | my $ret = {}; 47 | tie %$ret, 'Eir::Internal::ChannelMembershipHash', $self; 48 | return $ret; 49 | } 50 | 51 | package Eir::Filter; 52 | 53 | sub new { 54 | my ($class, $args) = @_; 55 | $class = ref $class || $class; 56 | my $self = $class->do_new; 57 | 58 | foreach my $key (keys %$args) { 59 | if ($key eq 'command') { 60 | $self->is_command($args->{$key}); 61 | } elsif ($key eq 'type') { 62 | $self->source_type($args->{$key}); 63 | } elsif ($key eq 'source_name' ) { 64 | $self->source_named($args->{$key}); 65 | } elsif ($key eq 'bot' ) { 66 | $self->from_bot($args->{$key}); 67 | } elsif ($key eq 'private') { 68 | $self->in_private if $args->{$key}; 69 | } elsif ($key eq 'channel') { 70 | $self->in_channel($args->{$key}); 71 | } elsif ($key eq 'privilege') { 72 | $self->requires_privilege($args->{$key}); 73 | } elsif ($key eq 'config') { 74 | $self->or_config if $args->{$key}; 75 | } 76 | } 77 | return $self; 78 | } 79 | 80 | package Eir::Help; 81 | 82 | sub AddTopic { 83 | my ($name, $text, $privilege) = @_; 84 | $privilege ||= ""; 85 | my $topic = { name => $name, priv => $privilege, text => $text }; 86 | my $helproot = Eir::Settings::Find("help_root"); 87 | 88 | $helproot->{$name} = $topic; 89 | 90 | return bless \$name; 91 | } 92 | 93 | sub AddIndex { 94 | my ($name, $text, $privilege) = @_; 95 | $privilege ||= ""; 96 | my $ret = AddTopic(@_); 97 | my $index = Eir::Settings::Find("help_index"); 98 | $index->{$name} = $privilege; 99 | return $ret; 100 | } 101 | 102 | sub DESTROY { 103 | my ($self) = @_; 104 | my $help_root = Eir::Settings::Find("help_root"); 105 | delete $help_root->{$$self}; 106 | my $index = Eir::Settings::find("help_index"); 107 | delete $index->{$$self}; 108 | } 109 | 110 | 1; 111 | -------------------------------------------------------------------------------- /modules/perl/lib/init.pl: -------------------------------------------------------------------------------- 1 | package Eir::Init; 2 | 3 | =head1 init.pl -- perl initialisation for eir. 4 | 5 | This file is processed on initialising the perl interpreter in C. It is 6 | mainly concerned with setting up the Perl environment, maintaining the list of 7 | loaded perl scripts, and providing the means to load and unload them. 8 | 9 | Much of the code herein has been copied almost verbatim from the examples in 10 | perlembed(1), with minor changes to reflect their purpose in the eir 11 | environment. 12 | 13 | =cut 14 | 15 | use strict; 16 | use warnings; 17 | 18 | use FindBin; 19 | use Symbol qw(delete_package); 20 | 21 | use lib "$FindBin::Bin"; 22 | use lib "$FindBin::Bin/../api"; 23 | 24 | our %Scripts; 25 | 26 | sub package_name_ify { 27 | my ($filename) = @_; 28 | 29 | $filename =~ s/([^A-Za-z0-9\/])/sprintf("_%2x",unpack("C",$1))/eg; 30 | # second pass only for words starting with a digit 31 | $filename =~ s|/(\d)|sprintf("/_%2x",unpack("C",$1))|eg; 32 | 33 | # Dress it up as a real package name 34 | $filename =~ s|/|::|g; 35 | return "Embed" . $filename; 36 | } 37 | 38 | sub load_script { 39 | call_wrapper(\&do_load_script, @_); 40 | } 41 | 42 | sub do_load_script { 43 | my ($filename, $message, $nonfatal) = @_; 44 | my $packagename = package_name_ify($filename); 45 | 46 | if (defined $Scripts{$packagename}) 47 | { 48 | if ($nonfatal) { 49 | $message->reply("$filename is already loaded"); 50 | return; 51 | } 52 | 53 | # This will always be called with G_EVAL, so this die can be translated 54 | # into a C++ exception. 55 | die "$filename is already loaded."; 56 | } 57 | 58 | local *FH; 59 | open FH, $filename or die "Couldn't open $filename: $!"; 60 | local ($/) = undef; 61 | my $script_text = ; 62 | close FH; 63 | 64 | my $eval = qq{package $packagename; $script_text }; 65 | { 66 | my ($filename, $packagename, $script_text); 67 | eval $eval; 68 | } 69 | if ($@) { 70 | delete_package $packagename; 71 | die $@; 72 | } 73 | 74 | $Scripts{$packagename} = 1; 75 | } 76 | 77 | sub unload_script { 78 | my ($filename, $message) = @_; 79 | my $packagename = package_name_ify($filename); 80 | 81 | if (!defined $Scripts{$packagename}) 82 | { 83 | die "$filename is not loaded"; 84 | } 85 | 86 | eval "${packagename}::unload(\$message)"; 87 | 88 | delete_package($packagename); 89 | delete $Scripts{$packagename}; 90 | } 91 | 92 | sub do_eval { 93 | my ($text, $message) = @_; 94 | my $sub = sub { 95 | use Eir; 96 | sub reply { $message->reply(shift); } 97 | sub bot { $message->bot; } 98 | sub client { $message->source->{"client"} } 99 | eval "$text"; 100 | die $@ if $@; 101 | }; 102 | call_wrapper($sub); 103 | } 104 | 105 | sub call_wrapper { 106 | my $sub = shift; 107 | my $saved_alarm=$SIG{ALRM}; 108 | $SIG{ALRM} = sub { die "Script used too much running time"; }; 109 | eval { 110 | alarm 1; 111 | &$sub(@_); 112 | }; 113 | alarm 0; 114 | $SIG{ALRM} = $saved_alarm; 115 | die $@ if $@; 116 | } 117 | -------------------------------------------------------------------------------- /modules/perl/perl.cpp: -------------------------------------------------------------------------------- 1 | #include "stupid_perl_workarounds.h" 2 | 3 | #include "eir.h" 4 | #include "handler.h" 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include "definitions.h" 12 | 13 | #include 14 | 15 | using namespace eir; 16 | 17 | #define TYPE_MAPS_LIGHT 18 | #include "util/type_maps.h" 19 | #include "util/call_perl.hh" 20 | 21 | // Defined in perlxsi.c, generated at build time 22 | extern "C" void xs_init(pTHX); 23 | 24 | struct PerlModule : CommandHandlerBase, Module 25 | { 26 | PerlInterpreter *my_perl; 27 | void *libperl_handle; 28 | 29 | void do_script_load(const Message *m) 30 | { 31 | if (m->args.empty()) 32 | { 33 | m->source.error("I need a file name to load."); 34 | return; 35 | } 36 | call_perl(aTHX_ "Eir::Init::load_script", m->args[0], m, 1); 37 | m->source.reply("Successfully loaded " + m->args[0]); 38 | } 39 | 40 | void do_script_unload(const Message *m) 41 | { 42 | if (m->args.empty()) 43 | { 44 | m->source.error("I need a file name to unload."); 45 | return; 46 | } 47 | call_perl(aTHX_ "Eir::Init::unload_script", m->args[0], m); 48 | m->source.reply("Successfully unloaded " + m->args[0]); 49 | } 50 | 51 | void do_script_exec(const Message *m) 52 | { 53 | if (m->args.empty()) 54 | { 55 | m->source.error("I can't execute nothing."); 56 | return; 57 | } 58 | call_perl(aTHX_ "Eir::Init::do_eval", 59 | paludis::join(m->args.begin(), m->args.end()," "), m); 60 | m->source.reply("Done."); 61 | } 62 | 63 | void startup() 64 | { 65 | // Hack alert: Perl extension .sos aren't linked against libperl; they 66 | // rely on libperl already being loaded when they are. 67 | // However, this doesn't work for eir because this module, which is what 68 | // brought in libperl, was loaded with RTLD_LOCAL. 69 | // So, we re-open libperl with RTLD_GLOBAL to make its symbols visible. 70 | if (!(libperl_handle = dlopen("libperl.so", RTLD_GLOBAL | RTLD_LAZY | RTLD_NOLOAD))) 71 | throw InternalError("Couldn't re-open libperl.so"); 72 | 73 | const char *_perl_argv[] = { "", PERL_INIT_FILE, }; 74 | char **perl_argv = const_cast(_perl_argv); 75 | int perl_argc = 2; 76 | char **env = NULL; 77 | PERL_SYS_INIT3(&perl_argc, &perl_argv, &env); 78 | 79 | my_perl = perl_alloc(); 80 | if (!my_perl) 81 | throw InternalError("Couldn't create a perl interpreter."); 82 | 83 | perl_construct(my_perl); 84 | 85 | PL_origalen = 1; 86 | int exitstatus = perl_parse(my_perl, xs_init, perl_argc, perl_argv, NULL); 87 | PL_exit_flags |= PERL_EXIT_DESTRUCT_END; 88 | 89 | if (exitstatus != 0) 90 | throw InternalError("Couldn't start the perl interpreter."); 91 | 92 | perl_run(my_perl); 93 | } 94 | 95 | void shutdown() 96 | { 97 | PL_perl_destruct_level = 0; 98 | perl_destruct(my_perl); 99 | perl_free(my_perl); 100 | my_perl = 0; 101 | PERL_SYS_TERM(); 102 | 103 | if (libperl_handle) 104 | dlclose(libperl_handle); 105 | } 106 | 107 | CommandHolder load_id, unload_id, exec_id; 108 | 109 | PerlModule() 110 | : my_perl(0) 111 | { 112 | startup(); 113 | load_id = add_handler(filter_command_privilege("loadscript", "admin").or_config(), 114 | &PerlModule::do_script_load); 115 | unload_id = add_handler(filter_command_privilege("unloadscript", "admin").or_config(), 116 | &PerlModule::do_script_unload); 117 | exec_id = add_handler(filter_command_privilege("execscript", "admin"), 118 | &PerlModule::do_script_exec); 119 | } 120 | 121 | ~PerlModule() 122 | { 123 | shutdown(); 124 | } 125 | }; 126 | 127 | MODULE_CLASS(PerlModule) 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /modules/perl/stupid_perl_workarounds.h: -------------------------------------------------------------------------------- 1 | #include 2 | #undef __THROW 3 | #define __THROW 4 | #undef __NTH 5 | #define __NTH(f) f 6 | #include 7 | -------------------------------------------------------------------------------- /modules/perl/util/call_perl.hh: -------------------------------------------------------------------------------- 1 | #ifndef call_perl_h 2 | #define call_perl_h 3 | 4 | #include 5 | #include 6 | 7 | #include "exceptions.h" 8 | #include 9 | 10 | enum class PerlContext { 11 | Void, 12 | Scalar, 13 | Array 14 | }; 15 | 16 | namespace eir 17 | { 18 | struct PerlException : public eir::Exception 19 | { 20 | PerlException(std::string s) : Exception("Perl call raised error: " + s) { } 21 | }; 22 | } 23 | 24 | SV* sv_from(pTHX_ int i) 25 | { 26 | return sv_2mortal(newSViv(i)); 27 | } 28 | SV* sv_from(pTHX_ long i) 29 | { 30 | return sv_2mortal(newSViv(i)); 31 | } 32 | SV* sv_from(pTHX_ double d) 33 | { 34 | return sv_2mortal(newSVnv(d)); 35 | } 36 | SV* sv_from(pTHX_ const char *s) 37 | { 38 | return sv_2mortal(newSVpv(s, 0)); 39 | } 40 | SV* sv_from(pTHX_ std::string s) 41 | { 42 | return sv_from(aTHX_ s.c_str()); 43 | } 44 | SV* sv_from(pTHX_ SV* sv) 45 | { 46 | PERL_UNUSED_CONTEXT; 47 | return sv; 48 | } 49 | 50 | namespace call_perl_internals 51 | { 52 | typedef std::vector sv_list; 53 | 54 | template 55 | void push_perl_args(pTHX_ sv_list& arglist, _First arg) 56 | { 57 | arglist.push_back(sv_from(aTHX_ arg)); 58 | } 59 | 60 | template 61 | void push_perl_args(pTHX_ sv_list& arglist, _First firstarg, _Rest... rest) 62 | { 63 | arglist.push_back(sv_from(aTHX_ firstarg)); 64 | push_perl_args(aTHX_ arglist, rest...); 65 | } 66 | 67 | int do_call_perl(pTHX_ const char *name, int flags) 68 | { 69 | return call_pv(name, flags); 70 | } 71 | 72 | int do_call_perl(pTHX_ SV *func, int flags) 73 | { 74 | return call_sv(func, flags); 75 | } 76 | 77 | template 78 | struct PerlCallAttrs 79 | { 80 | }; 81 | 82 | template <> 83 | struct PerlCallAttrs 84 | { 85 | typedef void ReturnType; 86 | 87 | static ReturnType extract_return_value(sv_list&) 88 | { 89 | } 90 | static void cleanup_errors(pTHX) 91 | { 92 | PERL_UNUSED_CONTEXT; 93 | } 94 | 95 | enum { callflag = G_VOID | G_DISCARD }; 96 | }; 97 | template <> 98 | struct PerlCallAttrs 99 | { 100 | typedef sv_list::value_type ReturnType; 101 | 102 | static ReturnType extract_return_value(sv_list& v) 103 | { 104 | return v[0]; 105 | } 106 | static void cleanup_errors(pTHX) 107 | { 108 | dSP; 109 | POPi; 110 | } 111 | 112 | enum { callflag = G_SCALAR }; 113 | }; 114 | template <> 115 | struct PerlCallAttrs 116 | { 117 | typedef sv_list ReturnType; 118 | 119 | static ReturnType extract_return_value(sv_list& v) 120 | { 121 | return v; 122 | } 123 | static void cleanup_errors(pTHX) 124 | { 125 | PERL_UNUSED_CONTEXT; 126 | } 127 | 128 | enum { callflag = G_ARRAY }; 129 | }; 130 | } 131 | 132 | template 133 | typename call_perl_internals::PerlCallAttrs<_C>::ReturnType 134 | call_perl(pTHX_ _Func func, ArgTypes... args) 135 | { 136 | call_perl_internals::sv_list arglist; 137 | call_perl_internals::push_perl_args(aTHX_ arglist, args...); 138 | bool _Eval = true; 139 | 140 | int flags = call_perl_internals::PerlCallAttrs<_C>::callflag; 141 | if (_Eval) 142 | flags |= G_EVAL; 143 | 144 | dSP; 145 | ENTER; 146 | SAVETMPS; 147 | PUSHMARK(SP); 148 | 149 | for (auto it = arglist.begin(); it != arglist.end(); ++it) 150 | XPUSHs(*it); 151 | 152 | PUTBACK; 153 | int count = call_perl_internals::do_call_perl(aTHX_ func, flags); 154 | SPAGAIN; 155 | 156 | if (_Eval && SvTRUE(ERRSV)) 157 | { 158 | call_perl_internals::PerlCallAttrs<_C>::cleanup_errors(aTHX); 159 | throw eir::PerlException(SvPV_nolen(ERRSV)); 160 | } 161 | 162 | call_perl_internals::sv_list returnlist; 163 | for (int i=0; i < count; ++i) 164 | { 165 | returnlist.push_back(POPs); 166 | } 167 | 168 | PUTBACK; 169 | FREETMPS; 170 | LEAVE; 171 | 172 | return call_perl_internals::PerlCallAttrs<_C>::extract_return_value(returnlist); 173 | } 174 | 175 | #endif 176 | -------------------------------------------------------------------------------- /modules/perl/util/type_maps.h: -------------------------------------------------------------------------------- 1 | #ifndef type_maps_hh 2 | #define type_maps_hh 3 | 4 | template 5 | struct PerlClassMap 6 | { 7 | }; 8 | 9 | #define TYPE_MAP_(t, n) \ 10 | inline SV* sv_from(pTHX_ t *p) { \ 11 | SV *ret = newSV(0); \ 12 | sv_setref_pv(ret, n, (void*)p); \ 13 | return sv_2mortal(ret); \ 14 | } \ 15 | template <> \ 16 | struct PerlClassMap { static const char *name() { return n; } }; 17 | 18 | #define TYPE_MAP(x) TYPE_MAP_(x, "Eir::"#x) 19 | #define TYPE_MAP_INTERNAL(x) TYPE_MAP_(x, "Eir::Internal::"#x) 20 | 21 | TYPE_MAP(Bot) 22 | 23 | TYPE_MAP(Client) 24 | TYPE_MAP(Channel) 25 | TYPE_MAP(Membership) 26 | TYPE_MAP(Filter) 27 | TYPE_MAP(CommandRegistry) 28 | TYPE_MAP(Capabilities) 29 | 30 | TYPE_MAP_(const Message, "Eir::Message") 31 | 32 | #ifndef TYPE_MAPS_LIGHT 33 | 34 | TYPE_MAP_INTERNAL(BotClientHash) 35 | TYPE_MAP_INTERNAL(BotChannelHash) 36 | TYPE_MAP_INTERNAL(BotSettingsHash) 37 | TYPE_MAP_INTERNAL(ClientMembershipHash) 38 | TYPE_MAP_INTERNAL(ChannelMembershipHash) 39 | TYPE_MAP_INTERNAL(PerlHolder) 40 | 41 | TYPE_MAP_INTERNAL(ArrayValueWrapper) 42 | TYPE_MAP_INTERNAL(HashValueWrapper) 43 | 44 | #endif 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /modules/privs/account.cpp: -------------------------------------------------------------------------------- 1 | #include "eir.h" 2 | #include "handler.h" 3 | #include "match.h" 4 | 5 | using namespace eir; 6 | 7 | struct AccountPrivilege : CommandHandlerBase, Module 8 | { 9 | Value * _cache_priv_entries; 10 | Value * _cache_priv_types; 11 | Value & priv_entries() { if (!_cache_priv_entries) _cache_priv_entries = &GlobalSettingsManager::get_instance()->get("privileges"); return *_cache_priv_entries; } 12 | Value & priv_types() { if (!_cache_priv_types) _cache_priv_types = &GlobalSettingsManager::get_instance()->get("privilege_types"); return *_cache_priv_types; } 13 | 14 | void calculate_account_privileges(const Message *m) 15 | { 16 | for (auto it = priv_entries().begin(); it != priv_entries().end(); ++it) 17 | { 18 | if ((*it)["type"] == "account" && 19 | (*it)["match"] == m->source.client->account()) 20 | { 21 | m->source.client->privs().add_privilege((*it)["channel"], (*it)["priv"]); 22 | } 23 | } 24 | } 25 | 26 | CommandHolder calc_handler; 27 | 28 | AccountPrivilege() 29 | : _cache_priv_entries(0), _cache_priv_types(0) 30 | { 31 | calc_handler = add_handler(filter_command_type("calculate_client_privileges", sourceinfo::Internal), 32 | &AccountPrivilege::calculate_account_privileges); 33 | 34 | priv_types()["account"] = 1; 35 | } 36 | 37 | ~AccountPrivilege() 38 | { 39 | priv_types()["account"] = 0; 40 | } 41 | }; 42 | 43 | MODULE_CLASS(AccountPrivilege) 44 | -------------------------------------------------------------------------------- /modules/privs/hostmask.cpp: -------------------------------------------------------------------------------- 1 | #include "eir.h" 2 | #include "handler.h" 3 | #include "match.h" 4 | 5 | using namespace eir; 6 | 7 | struct HostmaskPrivilege : CommandHandlerBase, Module 8 | { 9 | Value * _cache_priv_entries; 10 | Value * _cache_priv_types; 11 | Value & priv_entries() { if (!_cache_priv_entries) _cache_priv_entries = &GlobalSettingsManager::get_instance()->get("privileges"); return *_cache_priv_entries; } 12 | Value & priv_types() { if (!_cache_priv_types) _cache_priv_types = &GlobalSettingsManager::get_instance()->get("privilege_types"); return *_cache_priv_types; } 13 | 14 | void calculate_hostmask_privileges(const Message *m) 15 | { 16 | for (auto it = priv_entries().begin(); it != priv_entries().end(); ++it) 17 | { 18 | if ((*it)["type"] == "host" && 19 | match((*it)["match"], m->source.client->nuh())) 20 | { 21 | m->source.client->privs().add_privilege((*it)["channel"], (*it)["priv"]); 22 | } 23 | } 24 | } 25 | 26 | CommandHolder calc_handler; 27 | 28 | HostmaskPrivilege() 29 | : _cache_priv_entries(0), _cache_priv_types(0) 30 | { 31 | calc_handler = add_handler(filter_command_type("calculate_client_privileges", sourceinfo::Internal), 32 | &HostmaskPrivilege::calculate_hostmask_privileges); 33 | 34 | priv_types()["host"] = 1; 35 | } 36 | 37 | ~HostmaskPrivilege() 38 | { 39 | priv_types()["host"] = 0; 40 | } 41 | }; 42 | 43 | MODULE_CLASS(HostmaskPrivilege) 44 | -------------------------------------------------------------------------------- /modules/snote.cpp: -------------------------------------------------------------------------------- 1 | #include "eir.h" 2 | 3 | #include 4 | 5 | using namespace eir; 6 | 7 | struct SnoteHandler : CommandHandlerBase, Module 8 | { 9 | void on_notice(const Message *m) 10 | { 11 | // Shouldn't happen, but check anyway. 12 | if (m->args.empty()) 13 | return; 14 | 15 | // We're only interested in notices from a server 16 | if (m->source.raw.find(".") == std::string::npos) 17 | return; 18 | 19 | std::string text = m->args[0]; 20 | std::string prefix = "*** Notice -- "; 21 | if (text.compare(0, prefix.size(), prefix) != 0) 22 | return; 23 | text = text.substr(prefix.size()); 24 | 25 | Message m2(*m, "incoming_snote", sourceinfo::Internal); 26 | m2.args.push_back(text); 27 | CommandRegistry::get_instance()->dispatch(&m2); 28 | } 29 | 30 | CommandHolder _id; 31 | 32 | SnoteHandler() 33 | { 34 | _id = add_handler(filter_command_type("notice", sourceinfo::RawIrc), &SnoteHandler::on_notice); 35 | } 36 | }; 37 | 38 | MODULE_CLASS(SnoteHandler) 39 | 40 | -------------------------------------------------------------------------------- /modules/storage/extra.mk: -------------------------------------------------------------------------------- 1 | EXTRA_CXXFLAGS_json=-Ilibjson -L. -ljson -Wl,--rpath `pwd` 2 | 3 | modules/storage/json.so: libjson.so 4 | -------------------------------------------------------------------------------- /modules/storage/json.cpp: -------------------------------------------------------------------------------- 1 | #include "eir.h" 2 | #include "storage.h" 3 | 4 | #include 5 | #include 6 | 7 | #include "json/json.h" 8 | 9 | using namespace eir; 10 | 11 | namespace 12 | { 13 | Json::Value EirValueToJsonValue(const eir::Value &v) 14 | { 15 | switch (v.Type()) 16 | { 17 | case Value::empty: 18 | return Json::Value::null; 19 | 20 | case Value::integer: 21 | return Json::Value(v.Int()); 22 | 23 | case Value::string: 24 | return Json::Value(v.String()); 25 | 26 | case Value::array: 27 | { 28 | Json::Value ret(Json::arrayValue); 29 | for (eir::ValueArray::const_iterator it = v.Array().begin(), it_e = v.Array().end(); 30 | it != it_e; ++it) 31 | { 32 | ret.append(EirValueToJsonValue(*it)); 33 | } 34 | return ret; 35 | } 36 | case Value::kvarray: 37 | { 38 | Json::Value ret(Json::objectValue); 39 | for (eir::KeyValueArray::const_iterator it = v.KV().begin(), it_e = v.KV().end(); 40 | it != it_e; ++it) 41 | { 42 | ret[it->first] = EirValueToJsonValue(it->second); 43 | } 44 | return ret; 45 | } 46 | default: 47 | throw InternalError("Unknown value type when converting to json"); 48 | } 49 | } 50 | 51 | eir::Value JsonValueToEirValue(const Json::Value &v) 52 | { 53 | switch (v.type()) 54 | { 55 | case Json::nullValue: 56 | return Value(Value::empty); 57 | 58 | case Json::intValue: 59 | case Json::uintValue: 60 | case Json::booleanValue: 61 | return Value(v.asInt()); 62 | 63 | case Json::realValue: 64 | throw InternalError("Can't represent floating-point numbers"); 65 | 66 | case Json::stringValue: 67 | return Value(v.asString()); 68 | 69 | case Json::arrayValue: 70 | { 71 | Value ret(Value::array); 72 | for (Json::ValueIterator it = v.begin(); it != v.end(); ++it) 73 | { 74 | ret.push_back(JsonValueToEirValue(*it)); 75 | } 76 | return ret; 77 | } 78 | 79 | case Json::objectValue: 80 | { 81 | Value ret(Value::kvarray); 82 | Json::Value::Members members(v.getMemberNames()); 83 | for (Json::Value::Members::iterator it = members.begin(); it != members.end(); ++it) 84 | { 85 | ret.KV().insert(*it, JsonValueToEirValue(v.get(*it, Json::Value::null))); 86 | } 87 | return ret; 88 | } 89 | default: 90 | throw InternalError("Unknown json value type"); 91 | } 92 | } 93 | } 94 | 95 | struct JsonStorage : Module, StorageBackend 96 | { 97 | void Save(const Value & v, std::string target) 98 | { 99 | Json::Value jv = EirValueToJsonValue(v); 100 | Json::StyledWriter writer; 101 | std::string filename(DATADIR "/" + target); 102 | std::ofstream fs(filename.c_str()); 103 | fs << writer.write(jv); 104 | if (!fs) 105 | throw IOError("Error writing json output to " + filename); 106 | } 107 | 108 | Value Load(std::string source) 109 | { 110 | std::string filename(DATADIR "/" + source); 111 | std::ifstream fs(filename.c_str()); 112 | Json::Reader reader; 113 | Json::Value jv; 114 | std::string raw; 115 | 116 | // Icky hack coming up 117 | std::stringstream ss; 118 | ss << fs.rdbuf(); 119 | raw = ss.str(); 120 | 121 | if (!fs || !ss) 122 | throw IOError("Error reading from " + filename); 123 | 124 | if (!reader.parse(raw, jv)) 125 | throw IOError("Couldn't parse json input from " + filename); 126 | 127 | return JsonValueToEirValue(jv); 128 | } 129 | 130 | StorageBackendHolder backendid; 131 | 132 | JsonStorage() 133 | { 134 | backendid = StorageManager::get_instance()->register_backend("json", this); 135 | } 136 | }; 137 | 138 | MODULE_CLASS(JsonStorage) 139 | -------------------------------------------------------------------------------- /modules/userlist.cpp: -------------------------------------------------------------------------------- 1 | #include "eir.h" 2 | 3 | #include "handler.h" 4 | 5 | using namespace eir; 6 | 7 | struct UserLister : CommandHandlerBase, Module 8 | { 9 | void list(const Message *m) 10 | { 11 | std::string channelname; 12 | 13 | unsigned int modeindex = 0; 14 | 15 | if (m->bot->supported()->is_channel_name(m->source.destination)) 16 | channelname = m->source.destination; 17 | 18 | if (!m->args.empty() && m->bot->supported()->is_channel_name(m->args[0])) 19 | { 20 | channelname = m->args[0]; 21 | ++modeindex; 22 | } 23 | 24 | if (channelname.empty()) 25 | { 26 | m->source.error("I need a channel name"); 27 | return; 28 | } 29 | 30 | Channel::ptr ch = m->bot->find_channel(channelname); 31 | 32 | if (!ch) 33 | { 34 | m->source.error("I don't seem to be in that channel."); 35 | return; 36 | } 37 | 38 | std::string reply; 39 | 40 | for (Channel::MemberIterator it = ch->begin_members(), ite = ch->end_members(); 41 | it != ite; ++it) 42 | { 43 | if (m->args.size() <= modeindex || (*it)->has_mode(m->args[modeindex][0])) 44 | reply += (*it)->client->nick() + " "; 45 | } 46 | 47 | if (reply.empty()) 48 | m->source.reply(""); 49 | else 50 | m->source.reply(reply); 51 | } 52 | 53 | CommandHolder _id; 54 | 55 | UserLister() 56 | { 57 | _id = add_handler(filter_command_type("names", sourceinfo::IrcCommand), &UserLister::list); 58 | } 59 | }; 60 | 61 | MODULE_CLASS(UserLister) 62 | 63 | -------------------------------------------------------------------------------- /modules/whoami.cpp: -------------------------------------------------------------------------------- 1 | #include "eir.h" 2 | 3 | #include 4 | 5 | using namespace eir; 6 | 7 | struct Whoami : CommandHandlerBase, Module 8 | { 9 | void whoami(const Message *m) 10 | { 11 | if (!m->source.client) 12 | { 13 | m->source.reply("I don't know who you are."); 14 | return; 15 | } 16 | 17 | m->source.reply("You are " + m->source.client->nick()); 18 | 19 | if (m->source.client->account().empty()) 20 | m->source.reply("You are not logged in"); 21 | else 22 | m->source.reply("You are logged in as " + m->source.client->account()); 23 | 24 | std::string privbuf; 25 | std::map chanprivbuf; 26 | 27 | for(PrivilegeSet::iterator it = m->source.client->privs().begin(); 28 | it != m->source.client->privs().end(); ++it) 29 | { 30 | if (it->first.empty()) 31 | privbuf += it->second + " "; 32 | else 33 | chanprivbuf[it->first] += it->second + " "; 34 | } 35 | 36 | if (!privbuf.empty()) 37 | m->source.reply("You have privileges " + privbuf); 38 | for (std::map::iterator it = chanprivbuf.begin(); it != chanprivbuf.end(); ++it) 39 | m->source.reply("You have privileges " + it->second + "in channel " + it->first); 40 | } 41 | 42 | CommandHolder _id; 43 | 44 | Whoami() 45 | { 46 | _id = add_handler(filter_command_type("whoami", sourceinfo::IrcCommand), &Whoami::whoami); 47 | } 48 | }; 49 | 50 | MODULE_CLASS(Whoami) 51 | -------------------------------------------------------------------------------- /paludis/util/attributes.hh: -------------------------------------------------------------------------------- 1 | /* vim: set sw=4 sts=4 et foldmethod=syntax : */ 2 | 3 | /* 4 | * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh 5 | * 6 | * This file is part of the Paludis package manager. Paludis is free software; 7 | * you can redistribute it and/or modify it under the terms of the GNU General 8 | * Public License version 2, as published by the Free Software Foundation. 9 | * 10 | * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY 11 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 17 | * Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef PALUDIS_GUARD_PALUDIS_ATTRIBUTES_HH 21 | #define PALUDIS_GUARD_PALUDIS_ATTRIBUTES_HH 1 22 | 23 | /** \file 24 | * Declare the PALUDIS_ATTRIBUTE macros. 25 | * 26 | * \ingroup g_utils 27 | * 28 | * \section Examples 29 | * 30 | * - None at this time. 31 | */ 32 | 33 | /** \def PALUDIS_ATTRIBUTE 34 | * If we're using a recent GCC or ICC, expands to __attribute__, otherwise 35 | * discards its arguments. 36 | * 37 | * \ingroup g_utils 38 | */ 39 | 40 | /** \def PALUDIS_VISIBLE 41 | * Marker used to represent 'make visible', if visibility is enabled. 42 | * 43 | * \ingroup g_utils 44 | */ 45 | 46 | /** \def PALUDIS_HIDDEN 47 | * Marker used to represent 'make hidden', if visibility is enabled. 48 | * 49 | * \ingroup g_utils 50 | */ 51 | 52 | #if (defined(__GNUC__) && ! defined(DOXYGEN)) 53 | # if defined(__ICC) 54 | # define PALUDIS_ATTRIBUTE(x) 55 | # else 56 | # if ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) 57 | # define PALUDIS_ATTRIBUTE(x) __attribute__(x) 58 | # define PALUDIS_CAN_USE_ATTRIBUTE 1 59 | # else 60 | # define PALUDIS_ATTRIBUTE(x) 61 | # endif 62 | # endif 63 | #else 64 | # define PALUDIS_ATTRIBUTE(x) 65 | #endif 66 | 67 | #if (defined(PALUDIS_ENABLE_VISIBILITY) && ! defined(DOXYGEN)) 68 | # define PALUDIS_VISIBLE PALUDIS_ATTRIBUTE((visibility("default"))) 69 | # define PALUDIS_HIDDEN PALUDIS_ATTRIBUTE((visibility("hidden"))) 70 | #else 71 | # define PALUDIS_VISIBLE 72 | # define PALUDIS_HIDDEN 73 | #endif 74 | 75 | #ifdef PALUDIS_ENABLE_THREADS 76 | # define PALUDIS_TLS static __thread 77 | #else 78 | # define PALUDIS_TLS static 79 | #endif 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /paludis/util/build.mk: -------------------------------------------------------------------------------- 1 | DSOS = paludisutil 2 | 3 | paludisutil_SOURCES = destringify.cc \ 4 | exception.cc \ 5 | mutex.cc \ 6 | tokeniser.cc 7 | 8 | CXXFLAGS += -fPIC 9 | -------------------------------------------------------------------------------- /paludis/util/destringify.cc: -------------------------------------------------------------------------------- 1 | /* vim: set sw=4 sts=4 et foldmethod=syntax : */ 2 | 3 | /* 4 | * Copyright (c) 2006 Stephen Bennett 5 | * 6 | * This file is part of the Paludis package manager. Paludis is free software; 7 | * you can redistribute it and/or modify it under the terms of the GNU General 8 | * Public License version 2, as published by the Free Software Foundation. 9 | * 10 | * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY 11 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 17 | * Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include 21 | 22 | using namespace paludis; 23 | 24 | DestringifyError::DestringifyError(const std::string & str) throw () : 25 | Exception("Couldn't destringify '" + str + "'") 26 | { 27 | } 28 | 29 | -------------------------------------------------------------------------------- /paludis/util/instantiation_policy-impl.hh: -------------------------------------------------------------------------------- 1 | /* vim: set sw=4 sts=4 et foldmethod=syntax : */ 2 | 3 | /* 4 | * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh 5 | * 6 | * This file is part of the Paludis package manager. Paludis is free software; 7 | * you can redistribute it and/or modify it under the terms of the GNU General 8 | * Public License version 2, as published by the Free Software Foundation. 9 | * 10 | * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY 11 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 17 | * Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef PALUDIS_GUARD_PALUDIS_UTIL_INSTANTIATION_POLICY_IMPL_HH 21 | #define PALUDIS_GUARD_PALUDIS_UTIL_INSTANTIATION_POLICY_IMPL_HH 1 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | /** \file 30 | * Implementation for paludis/util/instantiation_policy.hh . 31 | * 32 | * \ingroup g_oo 33 | */ 34 | 35 | template 36 | void 37 | paludis::InstantiationPolicy::_delete(OurType_ * const p) 38 | { 39 | delete p; 40 | } 41 | 42 | template 43 | class paludis::InstantiationPolicy::DeleteOnDestruction 44 | { 45 | private: 46 | OurType_ * * const _ptr; 47 | 48 | public: 49 | DeleteOnDestruction(OurType_ * * const p) : 50 | _ptr(p) 51 | { 52 | } 53 | 54 | ~DeleteOnDestruction() 55 | { 56 | paludis::InstantiationPolicy::_delete(* _ptr); 57 | * _ptr = 0; 58 | } 59 | }; 60 | 61 | template 62 | OurType_ * * 63 | paludis::InstantiationPolicy::_get_instance_ptr() 64 | { 65 | static OurType_ * instance(0); 66 | static DeleteOnDestruction delete_instance(&instance); 67 | 68 | return &instance; 69 | } 70 | 71 | template 72 | OurType_ * 73 | paludis::InstantiationPolicy::get_instance() 74 | { 75 | OurType_ * * i(_get_instance_ptr()); 76 | 77 | if (0 == *i) 78 | { 79 | PALUDIS_TLS bool recursive(false); 80 | if (recursive) 81 | throw paludis::InternalError(PALUDIS_HERE, "Recursive instantiation"); 82 | Save save_recursive(&recursive, true); 83 | 84 | static Mutex m; 85 | Lock l(m); 86 | 87 | i = _get_instance_ptr(); 88 | if (0 == *i) 89 | *i = new OurType_; 90 | } 91 | 92 | return *i; 93 | } 94 | 95 | template 96 | void 97 | paludis::InstantiationPolicy::destroy_instance() 98 | { 99 | OurType_ * * i(_get_instance_ptr()); 100 | delete *i; 101 | *i = 0; 102 | } 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /paludis/util/join.hh: -------------------------------------------------------------------------------- 1 | /* vim: set sw=4 sts=4 et foldmethod=syntax : */ 2 | 3 | /* 4 | * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh 5 | * 6 | * This file is part of the Paludis package manager. Paludis is free software; 7 | * you can redistribute it and/or modify it under the terms of the GNU General 8 | * Public License version 2, as published by the Free Software Foundation. 9 | * 10 | * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY 11 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 17 | * Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef PALUDIS_GUARD_PALUDIS_JOIN_HH 21 | #define PALUDIS_GUARD_PALUDIS_JOIN_HH 1 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #ifdef PALUDIS_HAVE_CONCEPTS 28 | # include 29 | #endif 30 | 31 | /** \file 32 | * Declarations for the join function. 33 | * 34 | * \ingroup g_strings 35 | * 36 | * \section Examples 37 | * 38 | * - None at this time. 39 | */ 40 | 41 | namespace paludis 42 | { 43 | #ifdef PALUDIS_HAVE_CONCEPTS 44 | auto concept IsJoinResult 45 | { 46 | requires std::DefaultConstructible; 47 | requires std::CopyConstructible; 48 | void T_::operator+= (const T_ &); 49 | void T_::operator+= (const std::string &); 50 | }; 51 | 52 | auto concept IsJoinStringifier 53 | { 54 | T_ operator() (const F_ &, const I_ &); 55 | }; 56 | #endif 57 | 58 | /** 59 | * Join together the items from i to end using joiner. 60 | * 61 | * \ingroup g_strings 62 | */ 63 | template 64 | #ifdef PALUDIS_HAVE_CONCEPTS 65 | requires 66 | std::ForwardIterator, 67 | IsStringifiable, 68 | IsJoinResult 69 | #endif 70 | T_ join(I_ i, I_ end, const T_ & joiner) 71 | { 72 | T_ result; 73 | if (i != end) 74 | while (true) 75 | { 76 | result += stringify(*i); 77 | if (++i == end) 78 | break; 79 | result += joiner; 80 | } 81 | return result; 82 | } 83 | 84 | /** 85 | * Join together the items from i to end using joiner, using 86 | * a function other than stringify. 87 | * 88 | * \ingroup g_strings 89 | */ 90 | template 91 | #ifdef PALUDIS_HAVE_CONCEPTS 92 | requires 93 | std::ForwardIterator, 94 | IsJoinResult, 95 | IsJoinStringifier 96 | #endif 97 | T_ join(I_ i, I_ end, const T_ & joiner, const F_ & f) 98 | { 99 | T_ result; 100 | if (i != end) 101 | while (true) 102 | { 103 | result += (f)(*i); 104 | if (++i == end) 105 | break; 106 | result += joiner; 107 | } 108 | return result; 109 | } 110 | 111 | /** 112 | * Convenience alternative join allowing a char * to be used for a 113 | * string. 114 | * 115 | * \ingroup g_strings 116 | */ 117 | template 118 | #ifdef PALUDIS_HAVE_CONCEPTS 119 | requires 120 | std::ForwardIterator, 121 | IsStringifiable 122 | #endif 123 | std::string join(I_ begin, const I_ end, const char * const t) 124 | { 125 | return join(begin, end, std::string(t)); 126 | } 127 | 128 | /** 129 | * Convenience alternative join allowing a char * to be used for a 130 | * string, using a function other than stringify. 131 | * 132 | * \ingroup g_strings 133 | */ 134 | template 135 | #ifdef PALUDIS_HAVE_CONCEPTS 136 | requires 137 | std::ForwardIterator, 138 | IsJoinStringifier 139 | #endif 140 | std::string join(I_ begin, const I_ end, const char * const t, const F_ & f) 141 | { 142 | return join(begin, end, std::string(t), f); 143 | } 144 | } 145 | 146 | #endif 147 | -------------------------------------------------------------------------------- /paludis/util/member_iterator-fwd.hh: -------------------------------------------------------------------------------- 1 | /* vim: set sw=4 sts=4 et foldmethod=syntax : */ 2 | 3 | /* 4 | * Copyright (c) 2007, 2008 Ciaran McCreesh 5 | * Copyright (c) 2007 David Leverton 6 | * 7 | * This file is part of the Paludis package manager. Paludis is free software; 8 | * you can redistribute it and/or modify it under the terms of the GNU General 9 | * Public License version 2, as published by the Free Software Foundation. 10 | * 11 | * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 14 | * details. 15 | * 16 | * You should have received a copy of the GNU General Public License along with 17 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 18 | * Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | #ifndef PALUDIS_GUARD_PALUDIS_UTIL_MEMBER_ITERATOR_FWD_HH 22 | #define PALUDIS_GUARD_PALUDIS_UTIL_MEMBER_ITERATOR_FWD_HH 1 23 | 24 | #include 25 | #include 26 | 27 | namespace paludis 28 | { 29 | template ::value_type>::type::* member_> 31 | class MemberIterator; 32 | 33 | template 34 | struct FirstIteratorTypes; 35 | 36 | template 37 | typename FirstIteratorTypes::Type 38 | first_iterator(Iterator_); 39 | 40 | template 41 | struct SecondIteratorTypes; 42 | 43 | template 44 | typename SecondIteratorTypes::Type 45 | second_iterator(Iterator_); 46 | } 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /paludis/util/member_iterator-impl.hh: -------------------------------------------------------------------------------- 1 | /* vim: set sw=4 sts=4 et foldmethod=syntax : */ 2 | 3 | /* 4 | * Copyright (c) 2007, 2008 Ciaran McCreesh 5 | * Copyright (c) 2007 David Leverton 6 | * 7 | * This file is part of the Paludis package manager. Paludis is free software; 8 | * you can redistribute it and/or modify it under the terms of the GNU General 9 | * Public License version 2, as published by the Free Software Foundation. 10 | * 11 | * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 14 | * details. 15 | * 16 | * You should have received a copy of the GNU General Public License along with 17 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 18 | * Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | #ifndef PALUDIS_GUARD_PALUDIS_UTIL_MEMBER_ITERATOR_IMPL_HH 22 | #define PALUDIS_GUARD_PALUDIS_UTIL_MEMBER_ITERATOR_IMPL_HH 1 23 | 24 | #include 25 | 26 | namespace paludis 27 | { 28 | template ::value_type>::type::* member_> 30 | MemberIterator::MemberIterator() 31 | { 32 | } 33 | 34 | template ::value_type>::type::* member_> 36 | MemberIterator::MemberIterator(const MemberIterator & other) : 37 | _iter(other._iter) 38 | { 39 | } 40 | 41 | template ::value_type>::type::* member_> 43 | MemberIterator::MemberIterator(const Iterator_ & iter) : 44 | _iter(iter) 45 | { 46 | } 47 | 48 | template ::value_type>::type::* member_> 50 | MemberIterator & 51 | MemberIterator::operator= (const MemberIterator & other) 52 | { 53 | _iter = other._iter; 54 | return *this; 55 | } 56 | 57 | template ::value_type>::type::* member_> 59 | MemberIterator & 60 | MemberIterator::operator++ () 61 | { 62 | ++_iter; 63 | return *this; 64 | } 65 | 66 | template ::value_type>::type::* member_> 68 | MemberIterator 69 | MemberIterator::operator++ (int) 70 | { 71 | MemberIterator result(*this); 72 | ++_iter; 73 | return result; 74 | } 75 | 76 | template ::value_type>::type::* member_> 78 | typename MemberIterator::pointer 79 | MemberIterator::operator-> () const 80 | { 81 | return &((*_iter).*member_); 82 | } 83 | 84 | template ::value_type>::type::* member_> 86 | typename MemberIterator::reference 87 | MemberIterator::operator* () const 88 | { 89 | return (*_iter).*member_; 90 | } 91 | 92 | template ::value_type>::type::* member_> 94 | bool 95 | MemberIterator::operator== (const MemberIterator & other) const 96 | { 97 | return _iter == other._iter; 98 | } 99 | 100 | template 101 | typename FirstIteratorTypes::Type 102 | first_iterator(Iterator_ i) 103 | { 104 | return typename FirstIteratorTypes::Type(i); 105 | } 106 | 107 | template 108 | typename SecondIteratorTypes::Type 109 | second_iterator(Iterator_ i) 110 | { 111 | return typename SecondIteratorTypes::Type(i); 112 | } 113 | } 114 | 115 | #endif 116 | -------------------------------------------------------------------------------- /paludis/util/member_iterator.hh: -------------------------------------------------------------------------------- 1 | /* vim: set sw=4 sts=4 et foldmethod=syntax : */ 2 | 3 | /* 4 | * Copyright (c) 2007, 2008 Ciaran McCreesh 5 | * Copyright (c) 2007 David Leverton 6 | * 7 | * This file is part of the Paludis package manager. Paludis is free software; 8 | * you can redistribute it and/or modify it under the terms of the GNU General 9 | * Public License version 2, as published by the Free Software Foundation. 10 | * 11 | * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 14 | * details. 15 | * 16 | * You should have received a copy of the GNU General Public License along with 17 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 18 | * Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | #ifndef PALUDIS_GUARD_PALUDIS_UTIL_MEMBER_ITERATOR_HH 22 | #define PALUDIS_GUARD_PALUDIS_UTIL_MEMBER_ITERATOR_HH 1 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #ifdef PALUDIS_HAVE_CONCEPTS 29 | # include 30 | #endif 31 | 32 | 33 | namespace paludis 34 | { 35 | template 36 | struct FirstIteratorTypes 37 | { 38 | typedef MemberIterator< 39 | typename std::tr1::remove_reference::value_type>::type::first_type, 40 | Iterator_, 41 | &std::tr1::remove_reference::value_type>::type::first> 42 | Type; 43 | }; 44 | 45 | template 46 | struct SecondIteratorTypes 47 | { 48 | typedef MemberIterator< 49 | typename std::tr1::remove_reference::value_type>::type::second_type, 50 | Iterator_, 51 | &std::tr1::remove_reference::value_type>::type::second> 52 | Type; 53 | }; 54 | 55 | /** 56 | * A MemberIterator is a wrapper around a forward iterator to a struct, 57 | * selecting one particular member of that struct for the value. 58 | * 59 | * \ingroup g_iterator 60 | * \since 0.26 61 | */ 62 | template ::value_type>::type::* member_> 64 | class MemberIterator : 65 | public equality_operators::HasEqualityOperators 66 | { 67 | private: 68 | Iterator_ _iter; 69 | 70 | public: 71 | ///\name Basic operations 72 | ///\{ 73 | 74 | MemberIterator(); 75 | MemberIterator(const MemberIterator &); 76 | MemberIterator(const Iterator_ &); 77 | 78 | MemberIterator & operator= (const MemberIterator &); 79 | 80 | ///\} 81 | 82 | ///\name Standard library typedefs 83 | ///\{ 84 | 85 | typedef typename std::tr1::remove_const::type>::type value_type; 86 | typedef const typename std::tr1::remove_reference::type & reference; 87 | typedef const typename std::tr1::remove_reference::type * pointer; 88 | typedef std::ptrdiff_t difference_type; 89 | typedef std::forward_iterator_tag iterator_category; 90 | 91 | ///\} 92 | 93 | ///\name Increment 94 | ///\{ 95 | 96 | MemberIterator & operator++ (); 97 | MemberIterator operator++ (int); 98 | 99 | ///\} 100 | 101 | ///\name Dereference 102 | ///\{ 103 | 104 | pointer operator-> () const; 105 | reference operator* () const; 106 | 107 | ///\} 108 | 109 | ///\name Equality 110 | ///\{ 111 | 112 | bool operator== (const MemberIterator &) const; 113 | 114 | ///\} 115 | }; 116 | } 117 | 118 | #ifdef PALUDIS_HAVE_CONCEPTS 119 | namespace std 120 | { 121 | template ::value_type>::type::* member_> 123 | concept_map ForwardIterator > 124 | { 125 | }; 126 | } 127 | #endif 128 | 129 | #endif 130 | -------------------------------------------------------------------------------- /paludis/util/mutex-fwd.hh: -------------------------------------------------------------------------------- 1 | /* vim: set sw=4 sts=4 et foldmethod=syntax : */ 2 | 3 | /* 4 | * Copyright (c) 2008 Ciaran McCreesh 5 | * 6 | * This file is part of the Paludis package manager. Paludis is free software; 7 | * you can redistribute it and/or modify it under the terms of the GNU General 8 | * Public License version 2, as published by the Free Software Foundation. 9 | * 10 | * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY 11 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 17 | * Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef PALUDIS_GUARD_PALUDIS_UTIL_MUTEX_FWD_HH 21 | #define PALUDIS_GUARD_PALUDIS_UTIL_MUTEX_FWD_HH 1 22 | 23 | namespace paludis 24 | { 25 | class Mutex; 26 | class Lock; 27 | class TryLock; 28 | } 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /paludis/util/mutex.cc: -------------------------------------------------------------------------------- 1 | /* vim: set sw=4 sts=4 et foldmethod=syntax : */ 2 | 3 | /* 4 | * Copyright (c) 2007 Ciaran McCreesh 5 | * 6 | * This file is part of the Paludis package manager. Paludis is free software; 7 | * you can redistribute it and/or modify it under the terms of the GNU General 8 | * Public License version 2, as published by the Free Software Foundation. 9 | * 10 | * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY 11 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 17 | * Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | using namespace paludis; 26 | 27 | #ifdef PALUDIS_ENABLE_THREADS 28 | 29 | Mutex::Mutex() : 30 | _attr(new pthread_mutexattr_t), 31 | _mutex(new pthread_mutex_t) 32 | { 33 | pthread_mutexattr_init(_attr); 34 | pthread_mutexattr_settype(_attr, PTHREAD_MUTEX_RECURSIVE); 35 | pthread_mutex_init(_mutex, _attr); 36 | } 37 | 38 | Mutex::~Mutex() 39 | { 40 | int r(0); 41 | if (0 != ((r = pthread_mutex_destroy(_mutex)))) 42 | throw InternalError(PALUDIS_HERE, "mutex destory failed: " + stringify(strerror(r))); 43 | pthread_mutexattr_destroy(_attr); 44 | 45 | delete _mutex; 46 | delete _attr; 47 | } 48 | 49 | pthread_mutex_t * 50 | Mutex::posix_mutex() 51 | { 52 | return _mutex; 53 | } 54 | 55 | Lock::Lock(Mutex & m) : 56 | _mutex(&m) 57 | { 58 | int r(0); 59 | if (0 != ((r = pthread_mutex_lock(_mutex->posix_mutex())))) 60 | throw InternalError(PALUDIS_HERE, "mutex lock failed: " + stringify(strerror(r))); 61 | } 62 | 63 | Lock::~Lock() 64 | { 65 | int r(0); 66 | if (0 != ((r = pthread_mutex_unlock(_mutex->posix_mutex())))) 67 | throw InternalError(PALUDIS_HERE, "mutex unlock failed: " + stringify(strerror(r))); 68 | } 69 | 70 | void 71 | Lock::acquire_then_release_old(Mutex & m) 72 | { 73 | int r(0); 74 | if (0 != ((r = pthread_mutex_lock(m.posix_mutex())))) 75 | throw InternalError(PALUDIS_HERE, "mutex lock failed: " + stringify(strerror(r))); 76 | if (0 != ((r = pthread_mutex_unlock(_mutex->posix_mutex())))) 77 | throw InternalError(PALUDIS_HERE, "mutex unlock failed: " + stringify(strerror(r))); 78 | _mutex = &m; 79 | } 80 | 81 | TryLock::TryLock(Mutex & m) : 82 | _mutex(&m) 83 | { 84 | if (0 != pthread_mutex_trylock(_mutex->posix_mutex())) 85 | _mutex = 0; 86 | } 87 | 88 | TryLock::~TryLock() 89 | { 90 | int r(0); 91 | if (_mutex) 92 | if (0 != ((r = pthread_mutex_unlock(_mutex->posix_mutex())))) 93 | throw InternalError(PALUDIS_HERE, "mutex unlock failed: " + stringify(strerror(r))); 94 | } 95 | 96 | bool 97 | TryLock::operator() () const 98 | { 99 | return _mutex; 100 | } 101 | 102 | #else 103 | 104 | Mutex::Mutex() 105 | { 106 | } 107 | 108 | Mutex::~Mutex() 109 | { 110 | } 111 | 112 | Lock::Lock(Mutex &) 113 | { 114 | } 115 | 116 | void 117 | Lock::acquire_then_release_old(Mutex &) 118 | { 119 | } 120 | 121 | Lock::~Lock() 122 | { 123 | } 124 | 125 | TryLock::TryLock(Mutex &) 126 | { 127 | } 128 | 129 | TryLock::~TryLock() 130 | { 131 | } 132 | 133 | bool 134 | TryLock::operator() () const 135 | { 136 | return true; 137 | } 138 | 139 | #endif 140 | 141 | -------------------------------------------------------------------------------- /paludis/util/mutex.hh: -------------------------------------------------------------------------------- 1 | /* vim: set sw=4 sts=4 et foldmethod=syntax : */ 2 | 3 | /* 4 | * Copyright (c) 2007, 2008 Ciaran McCreesh 5 | * 6 | * This file is part of the Paludis package manager. Paludis is free software; 7 | * you can redistribute it and/or modify it under the terms of the GNU General 8 | * Public License version 2, as published by the Free Software Foundation. 9 | * 10 | * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY 11 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 17 | * Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef PALUDIS_GUARD_PALUDIS_UTIL_MUTEX_HH 21 | #define PALUDIS_GUARD_PALUDIS_UTIL_MUTEX_HH 1 22 | 23 | #include 24 | #include 25 | 26 | #ifdef PALUDIS_ENABLE_THREADS 27 | # include 28 | #endif 29 | 30 | /** 31 | * Declarations for Mutex, Lock and TryLock. 32 | * 33 | * \ingroup g_threads 34 | * 35 | * \section Examples 36 | * 37 | * - None at this time. 38 | */ 39 | 40 | namespace paludis 41 | { 42 | /** 43 | * A simple mutex class, which can be locked using Lock and TryLock. 44 | * 45 | * \ingroup g_threads 46 | * \since 0.26 47 | */ 48 | class PALUDIS_VISIBLE Mutex 49 | { 50 | private: 51 | Mutex(const Mutex &); 52 | Mutex & operator= (const Mutex &); 53 | 54 | #ifdef PALUDIS_ENABLE_THREADS 55 | pthread_mutexattr_t * const _attr; 56 | pthread_mutex_t * const _mutex; 57 | #endif 58 | 59 | public: 60 | ///\name Basic operations 61 | ///\{ 62 | 63 | explicit Mutex(); 64 | ~Mutex(); 65 | 66 | ///\} 67 | 68 | #ifdef PALUDIS_ENABLE_THREADS 69 | pthread_mutex_t * posix_mutex() PALUDIS_ATTRIBUTE((warn_unused_result)); 70 | #endif 71 | }; 72 | 73 | /** 74 | * A RAII lock for a Mutex. 75 | * 76 | * If threading is disabled, locking is a no-op. 77 | * 78 | * \ingroup g_threads 79 | * \nosubgrouping 80 | * \since 0.26 81 | */ 82 | class PALUDIS_VISIBLE Lock 83 | { 84 | private: 85 | Lock(const Lock &); 86 | Lock & operator= (const Lock &); 87 | 88 | #ifdef PALUDIS_ENABLE_THREADS 89 | Mutex * _mutex; 90 | #endif 91 | 92 | public: 93 | ///\name Basic operations 94 | ///\{ 95 | 96 | explicit Lock(Mutex &); 97 | ~Lock(); 98 | 99 | ///\} 100 | 101 | /** 102 | * Acquire a lock on the provided Mutex, and then release our 103 | * previously owned lock. 104 | * 105 | * Use with caution -- this is a good way of creating deadlocks. 106 | */ 107 | void acquire_then_release_old(Mutex &); 108 | }; 109 | 110 | /** 111 | * A RAII trylock for a Mutex. 112 | * 113 | * If threading is disabled, locking is a no-op and the try always succeeds. 114 | * 115 | * \ingroup g_threads 116 | * \since 0.26 117 | * \nosubgrouping 118 | */ 119 | class PALUDIS_VISIBLE TryLock 120 | { 121 | private: 122 | TryLock(const TryLock &); 123 | TryLock & operator= (const TryLock &); 124 | 125 | #ifdef PALUDIS_ENABLE_THREADS 126 | Mutex * _mutex; 127 | #endif 128 | 129 | public: 130 | ///\name Basic operations 131 | ///\{ 132 | 133 | explicit TryLock(Mutex &); 134 | ~TryLock(); 135 | 136 | ///\} 137 | 138 | /** 139 | * Did the lock succeed? 140 | */ 141 | bool operator() () const PALUDIS_ATTRIBUTE((warn_unused_result)); 142 | }; 143 | } 144 | 145 | #endif 146 | -------------------------------------------------------------------------------- /paludis/util/private_implementation_pattern-impl.hh: -------------------------------------------------------------------------------- 1 | /* vim: set sw=4 sts=4 et foldmethod=syntax : */ 2 | 3 | /* 4 | * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh 5 | * 6 | * This file is part of the Paludis package manager. Paludis is free software; 7 | * you can redistribute it and/or modify it under the terms of the GNU General 8 | * Public License version 2, as published by the Free Software Foundation. 9 | * 10 | * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY 11 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 17 | * Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef PALUDIS_GUARD_PALUDIS_UTIL_PRIVATE_IMPLEMENTATION_PATTERN_IMPL_HH 21 | #define PALUDIS_GUARD_PALUDIS_UTIL_PRIVATE_IMPLEMENTATION_PATTERN_IMPL_HH 1 22 | 23 | #include 24 | 25 | /** \file 26 | * Implementation for paludis/util/private_implementation_pattern.hh . 27 | * 28 | * \ingroup g_oo 29 | */ 30 | 31 | template 32 | paludis::PrivateImplementationPattern::ImpPtr::ImpPtr(Implementation * p) : 33 | _ptr(p) 34 | { 35 | } 36 | 37 | template 38 | paludis::PrivateImplementationPattern::ImpPtr::~ImpPtr() 39 | { 40 | delete _ptr; 41 | } 42 | 43 | template 44 | paludis::Implementation * 45 | paludis::PrivateImplementationPattern::ImpPtr::get() 46 | { 47 | return _ptr; 48 | } 49 | 50 | template 51 | const paludis::Implementation * 52 | paludis::PrivateImplementationPattern::ImpPtr::get() const 53 | { 54 | return _ptr; 55 | } 56 | 57 | template 58 | void 59 | paludis::PrivateImplementationPattern::ImpPtr::reset(Implementation * p) 60 | { 61 | delete _ptr; 62 | _ptr = p; 63 | } 64 | 65 | template 66 | paludis::PrivateImplementationPattern::PrivateImplementationPattern(Implementation * i) : 67 | _imp(i) 68 | { 69 | } 70 | 71 | template 72 | paludis::PrivateImplementationPattern::~PrivateImplementationPattern() 73 | { 74 | } 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /paludis/util/private_implementation_pattern.hh: -------------------------------------------------------------------------------- 1 | /* vim: set sw=4 sts=4 et foldmethod=syntax : */ 2 | 3 | /* 4 | * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh 5 | * 6 | * This file is part of the Paludis package manager. Paludis is free software; 7 | * you can redistribute it and/or modify it under the terms of the GNU General 8 | * Public License version 2, as published by the Free Software Foundation. 9 | * 10 | * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY 11 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 17 | * Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef PALUDIS_GUARD_PALUDIS_PRIVATE_IMPLEMENTATION_PATTERN_HH 21 | #define PALUDIS_GUARD_PALUDIS_PRIVATE_IMPLEMENTATION_PATTERN_HH 1 22 | 23 | #include 24 | 25 | /** \file 26 | * Declarations for the PrivateImplementationPattern pattern. 27 | * 28 | * \ingroup g_oo 29 | * 30 | * \section Examples 31 | * 32 | * - None at this time. 33 | */ 34 | 35 | namespace paludis 36 | { 37 | /** 38 | * Private implementation data, to be specialised for any class that 39 | * uses PrivateImplementationPattern. 40 | * 41 | * \ingroup g_oo 42 | */ 43 | template 44 | struct Implementation; 45 | 46 | /** 47 | * A class descended from PrivateImplementationPattern has an associated 48 | * Implementation instance. 49 | * 50 | * \ingroup g_oo 51 | */ 52 | template 53 | class PrivateImplementationPattern : 54 | private InstantiationPolicy, instantiation_method::NonCopyableTag> 55 | { 56 | protected: 57 | /** 58 | * Smart pointer to our implementation. 59 | * 60 | * \see PrivateImplementationPattern 61 | * \ingroup g_oo 62 | */ 63 | class ImpPtr 64 | { 65 | private: 66 | ImpPtr(const ImpPtr &); 67 | void operator= (const ImpPtr &); 68 | Implementation * _ptr; 69 | 70 | public: 71 | ///\name Basic operations 72 | ///\{ 73 | 74 | ImpPtr(Implementation * p); 75 | 76 | ~ImpPtr(); 77 | 78 | ///\} 79 | 80 | ///\name Dereference operators 81 | //\{ 82 | 83 | inline Implementation * operator-> (); 84 | 85 | inline const Implementation * operator-> () const; 86 | 87 | Implementation * get(); 88 | const Implementation * get() const; 89 | 90 | ///\} 91 | 92 | /** 93 | * Reset to a new Implementation. 94 | */ 95 | void reset(Implementation * p); 96 | }; 97 | 98 | /** 99 | * Pointer to our implementation data. 100 | */ 101 | ImpPtr _imp; 102 | 103 | public: 104 | /** 105 | * Constructor. 106 | */ 107 | explicit PrivateImplementationPattern(Implementation * i); 108 | 109 | ~PrivateImplementationPattern(); 110 | }; 111 | } 112 | 113 | template 114 | paludis::Implementation * 115 | paludis::PrivateImplementationPattern::ImpPtr::operator-> () 116 | { 117 | return _ptr; 118 | } 119 | 120 | template 121 | const paludis::Implementation * 122 | paludis::PrivateImplementationPattern::ImpPtr::operator-> () const 123 | { 124 | return _ptr; 125 | } 126 | 127 | #endif 128 | -------------------------------------------------------------------------------- /paludis/util/save.hh: -------------------------------------------------------------------------------- 1 | /* vim: set sw=4 sts=4 et foldmethod=syntax : */ 2 | 3 | /* 4 | * Copyright (c) 2005, 2006, 2007, 2008 Ciaran McCreesh 5 | * 6 | * This file is part of the Paludis package manager. Paludis is free software; 7 | * you can redistribute it and/or modify it under the terms of the GNU General 8 | * Public License version 2, as published by the Free Software Foundation. 9 | * 10 | * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY 11 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 17 | * Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef PALUDIS_GUARD_PALUDIS_SAVE_HH 21 | #define PALUDIS_GUARD_PALUDIS_SAVE_HH 1 22 | 23 | #include 24 | #include 25 | 26 | /** \file 27 | * Declarations for the Save and RunOnDestruction classes. 28 | * 29 | * \ingroup g_utils 30 | * 31 | * \section Examples 32 | * 33 | * - None at this time. 34 | */ 35 | 36 | namespace paludis 37 | { 38 | /** 39 | * Save the value of a particular variable and assign it a new value for the 40 | * duration of the Save instance's lifetime (RAII, see \ref EffCpp item 13 or 41 | * \ref TCppPL section 14.4). 42 | * 43 | * \ingroup g_utils 44 | * \nosubgrouping 45 | */ 46 | template 47 | class Save 48 | { 49 | private: 50 | T_ * const _ptr; 51 | const T_ _value; 52 | 53 | Save(const Save &); 54 | void operator= (const Save &); 55 | 56 | public: 57 | ///\name Basic operations 58 | ///\{ 59 | 60 | /** 61 | * Constructor. 62 | */ 63 | Save(T_ * const p) : 64 | _ptr(p), 65 | _value(*p) 66 | { 67 | } 68 | 69 | /** 70 | * Constructor, with convenience assignment to new_value. 71 | */ 72 | Save(T_ * const p, const T_ & new_value) : 73 | _ptr(p), 74 | _value(*p) 75 | { 76 | *p = new_value; 77 | } 78 | 79 | /** 80 | * Destructor. 81 | */ 82 | ~Save() 83 | { 84 | *_ptr = _value; 85 | } 86 | 87 | ///\} 88 | }; 89 | 90 | /** 91 | * Run the supplied function when the class is destructed. 92 | * 93 | * \ingroup g_utils 94 | * \since 0.26 95 | */ 96 | class PALUDIS_VISIBLE RunOnDestruction 97 | { 98 | private: 99 | RunOnDestruction(const RunOnDestruction &); 100 | void operator= (const RunOnDestruction &); 101 | 102 | const std::tr1::function _f; 103 | 104 | public: 105 | RunOnDestruction(const std::tr1::function & f) : 106 | _f(f) 107 | { 108 | } 109 | 110 | ~RunOnDestruction() 111 | { 112 | _f(); 113 | } 114 | }; 115 | 116 | } 117 | 118 | #endif 119 | 120 | -------------------------------------------------------------------------------- /paludis/util/tokeniser.cc: -------------------------------------------------------------------------------- 1 | /* vim: set sw=4 sts=4 et foldmethod=syntax : */ 2 | 3 | /* 4 | * Copyright (c) 2007 Ciaran McCreesh 5 | * 6 | * This file is part of the Paludis package manager. Paludis is free software; 7 | * you can redistribute it and/or modify it under the terms of the GNU General 8 | * Public License version 2, as published by the Free Software Foundation. 9 | * 10 | * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY 11 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 17 | * Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include 21 | 22 | using namespace paludis; 23 | 24 | TokeniserError::TokeniserError(const std::string & s, const std::string & msg) throw () : 25 | Exception("When tokenising '" + s + "': " + msg) 26 | { 27 | } 28 | 29 | -------------------------------------------------------------------------------- /paludis/util/wrapped_forward_iterator-fwd.hh: -------------------------------------------------------------------------------- 1 | /* vim: set sw=4 sts=4 et foldmethod=syntax : */ 2 | 3 | /* 4 | * Copyright (c) 2007 Ciaran McCreesh 5 | * 6 | * This file is part of the Paludis package manager. Paludis is free software; 7 | * you can redistribute it and/or modify it under the terms of the GNU General 8 | * Public License version 2, as published by the Free Software Foundation. 9 | * 10 | * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY 11 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 17 | * Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef PALUDIS_GUARD_PALUDIS_UTIL_WRAPPED_FORWARD_ITERATOR_FWD_HH 21 | #define PALUDIS_GUARD_PALUDIS_UTIL_WRAPPED_FORWARD_ITERATOR_FWD_HH 1 22 | 23 | namespace paludis 24 | { 25 | template 26 | struct WrappedForwardIterator; 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /paludis/util/wrapped_forward_iterator.hh: -------------------------------------------------------------------------------- 1 | /* vim: set sw=4 sts=4 et foldmethod=syntax : */ 2 | 3 | /* 4 | * Copyright (c) 2007, 2008 Ciaran McCreesh 5 | * 6 | * This file is part of the Paludis package manager. Paludis is free software; 7 | * you can redistribute it and/or modify it under the terms of the GNU General 8 | * Public License version 2, as published by the Free Software Foundation. 9 | * 10 | * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY 11 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 17 | * Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef PALUDIS_GUARD_PALUDIS_UTIL_WRAPPED_FORWARD_ITERATOR_HH 21 | #define PALUDIS_GUARD_PALUDIS_UTIL_WRAPPED_FORWARD_ITERATOR_HH 1 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #ifdef PALUDIS_HAVE_CONCEPTS 31 | # include 32 | #endif 33 | 34 | namespace paludis 35 | { 36 | /** 37 | * A WrappedForwardIterator is a generic wrapper around a forward iterator, 38 | * hiding the underlying base iterator. 39 | * 40 | * \ingroup g_iterator 41 | * \since 0.26 42 | */ 43 | template 44 | class PALUDIS_VISIBLE WrappedForwardIterator : 45 | public equality_operators::HasEqualityOperators 46 | { 47 | private: 48 | struct Base; 49 | template struct BaseImpl; 50 | 51 | Base * _base; 52 | 53 | public: 54 | ///\name Basic operations 55 | ///\{ 56 | 57 | WrappedForwardIterator(); 58 | ~WrappedForwardIterator(); 59 | WrappedForwardIterator(const WrappedForwardIterator &); 60 | 61 | template 62 | WrappedForwardIterator(const T_ &); 63 | 64 | WrappedForwardIterator & operator= (const WrappedForwardIterator &); 65 | 66 | ///\} 67 | 68 | ///\name Standard library typedefs 69 | ///\{ 70 | 71 | typedef typename std::tr1::remove_reference::type & value_type; 72 | typedef typename std::tr1::remove_reference::type & reference; 73 | typedef typename std::tr1::remove_reference::type * pointer; 74 | typedef std::ptrdiff_t difference_type; 75 | typedef std::forward_iterator_tag iterator_category; 76 | 77 | ///\} 78 | 79 | ///\name Increment 80 | ///\{ 81 | 82 | WrappedForwardIterator & operator++ (); 83 | WrappedForwardIterator operator++ (int); 84 | 85 | ///\} 86 | 87 | ///\name Dereference 88 | ///\{ 89 | 90 | pointer operator-> () const; 91 | reference operator* () const; 92 | 93 | ///\} 94 | 95 | ///\name Equality 96 | ///\{ 97 | 98 | bool operator== (const WrappedForwardIterator &) const; 99 | 100 | ///\} 101 | 102 | ///\name Underlying iterator 103 | ///\{ 104 | 105 | template T_ & underlying_iterator(); 106 | template const T_ & underlying_iterator() const; 107 | 108 | ///\} 109 | }; 110 | } 111 | 112 | #ifdef PALUDIS_HAVE_CONCEPTS 113 | namespace std 114 | { 115 | template 116 | concept_map ForwardIterator > 117 | { 118 | }; 119 | } 120 | #endif 121 | 122 | #endif 123 | -------------------------------------------------------------------------------- /settings.mk.in: -------------------------------------------------------------------------------- 1 | ENABLE_PERL = @ENABLE_PERL@ 2 | PERL_CFLAGS = @PERL_CFLAGS@ 3 | PERL_LIBS = @PERL_LIBS@ 4 | 5 | WARNINGS_CFLAGS = @WARNINGS_CFLAGS@ 6 | 7 | # Really we want these uppercase, but autoconf will always set the lowercase one 8 | prefix = @prefix@ 9 | exec_prefix = @exec_prefix@ 10 | bindir = @bindir@ 11 | libdir = @libdir@ 12 | 13 | PREFIX = $(prefix) 14 | LIBDIR = $(libdir) 15 | BINDIR = $(bindir) 16 | 17 | MODDIR = @MODDIR@ 18 | ETCDIR = @ETCDIR@ 19 | EIR_DATADIR = @DATADIR@ 20 | 21 | CXXFLAGS += $(WARNINGS_CFLAGS) -DMODDIR=\"$(MODDIR)\" -DETCDIR=\"$(ETCDIR)\" -DDATADIR=\"$(EIR_DATADIR)\" 22 | -------------------------------------------------------------------------------- /src/bot.h: -------------------------------------------------------------------------------- 1 | #ifndef bot_h 2 | #define bot_h 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "supported.h" 11 | #include "capability.h" 12 | #include "client.h" 13 | #include "message.h" 14 | #include "value.h" 15 | 16 | namespace eir 17 | { 18 | class Bot : public paludis::PrivateImplementationPattern 19 | { 20 | public: 21 | Bot(std::string name); 22 | 23 | void connect(std::string host, std::string port, std::string nick, std::string pass); 24 | 25 | const std::string& nick() const; 26 | const std::string& name() const; 27 | const Client::ptr me() const; 28 | 29 | void run(); 30 | 31 | void disconnect(std::string); 32 | 33 | bool connected() const; 34 | 35 | void send(std::string); 36 | 37 | struct ClientIteratorTag; 38 | typedef paludis::WrappedForwardIterator ClientIterator; 39 | ClientIterator begin_clients(); 40 | ClientIterator end_clients(); 41 | ClientIterator find_client_it(std::string nick); 42 | Client::ptr find_client(std::string nick); 43 | std::pair add_client(Client::ptr c); 44 | unsigned long remove_client(Client::ptr c); 45 | 46 | struct ChannelIteratorTag; 47 | typedef paludis::WrappedForwardIterator ChannelIterator; 48 | ChannelIterator begin_channels(); 49 | ChannelIterator end_channels(); 50 | ChannelIterator find_channel_it(std::string name); 51 | Channel::ptr find_channel(std::string name); 52 | std::pair add_channel(Channel::ptr c); 53 | unsigned long remove_channel(Channel::ptr c); 54 | void remove_channel(ChannelIterator c); 55 | 56 | struct SettingsIteratorTag; 57 | typedef paludis::WrappedForwardIterator > SettingsIterator; 59 | SettingsIterator begin_settings(); 60 | SettingsIterator end_settings(); 61 | SettingsIterator find_setting(std::string name); 62 | Value get_setting(std::string name); 63 | Value get_setting_with_default(std::string name, std::string _default); 64 | std::pair add_setting(std::string n, Value v); 65 | unsigned long remove_setting(std::string n); 66 | void remove_setting(SettingsIterator it); 67 | 68 | const ISupport *supported() const; 69 | Capabilities *capabilities(); 70 | 71 | bool use_account_tracking() const; 72 | 73 | ~Bot(); 74 | }; 75 | 76 | class BotManager : public paludis::InstantiationPolicy, 78 | public paludis::PrivateImplementationPattern 79 | { 80 | public: 81 | friend class Bot; 82 | 83 | Bot *find(std::string name); 84 | BotManager(); 85 | ~BotManager(); 86 | }; 87 | 88 | } 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /src/bot_command.cpp: -------------------------------------------------------------------------------- 1 | #include "eir.h" 2 | 3 | #include "handler.h" 4 | 5 | #include 6 | 7 | using namespace eir; 8 | 9 | namespace { 10 | void notice_to(Bot *b, std::string dest, std::string text) 11 | { 12 | b->send("NOTICE " + dest + " :" + text); 13 | } 14 | } 15 | 16 | struct BotCommandHandler : public CommandHandlerBase 17 | { 18 | CommandHolder _id; 19 | 20 | void handle_privmsg(const Message *m) 21 | { 22 | std::string line, reply_dest; 23 | if (m->source.destination == m->bot->nick()) 24 | { 25 | line = m->args[0]; 26 | reply_dest = m->source.name; 27 | } 28 | else if (m->bot->get_setting("command_chars").String().find(m->args[0][0]) != std::string::npos) 29 | { 30 | line = m->args[0].substr(1); 31 | reply_dest = m->source.destination; 32 | } 33 | else if (m->args[0].substr(0, m->args[0].find_first_of(",: ")) == m->bot->nick()) 34 | { 35 | line = m->args[0].substr(m->args[0].find_first_of(",: ") + 1); 36 | reply_dest = m->source.destination; 37 | } 38 | else 39 | return; 40 | 41 | std::list tokens; 42 | paludis::tokenise_whitespace(line, std::back_inserter(tokens)); 43 | 44 | if(tokens.empty()) 45 | return; 46 | 47 | Message m2(*m, *tokens.begin(), sourceinfo::IrcCommand); 48 | 49 | tokens.pop_front(); 50 | std::copy(tokens.begin(), tokens.end(), std::back_inserter(m2.args)); 51 | 52 | m2.raw = line; 53 | 54 | CommandRegistry::get_instance()->dispatch(&m2); 55 | } 56 | 57 | BotCommandHandler() 58 | { 59 | _id = add_handler(filter_command("PRIVMSG").source_type(sourceinfo::RawIrc), 60 | &BotCommandHandler::handle_privmsg); 61 | } 62 | } bot_command_handler; 63 | 64 | -------------------------------------------------------------------------------- /src/build.mk: -------------------------------------------------------------------------------- 1 | EXECUTABLES = eir 2 | 3 | eir_SOURCES = bot.cpp \ 4 | bot_command.cpp \ 5 | capability.cpp \ 6 | client.cpp \ 7 | command.cpp \ 8 | event.cpp \ 9 | exceptions.cpp \ 10 | logger.cpp \ 11 | main.cpp \ 12 | match.cpp \ 13 | message.cpp \ 14 | modload.cpp \ 15 | modules.cpp \ 16 | privilege.cpp \ 17 | server.cpp \ 18 | settings.cpp \ 19 | storage.cpp \ 20 | string_util.cpp \ 21 | supported.cpp \ 22 | value.cpp \ 23 | 24 | eir_LDFLAGS = -Wl,-export-dynamic -Wl,-rpath,$(LIBDIR) 25 | ifeq ($(shell uname),FreeBSD) 26 | eir_LIBRARIES = paludis/util/paludisutil 27 | else 28 | eir_LIBRARIES = -ldl paludis/util/paludisutil 29 | endif 30 | -------------------------------------------------------------------------------- /src/capability.h: -------------------------------------------------------------------------------- 1 | #ifndef capability_h 2 | #define capability_h 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace eir 10 | { 11 | class Bot; 12 | 13 | class Capabilities : private paludis::InstantiationPolicy, 14 | private paludis::PrivateImplementationPattern 15 | { 16 | public: 17 | struct CapTokenIteratorTag; 18 | typedef paludis::WrappedForwardIterator iterator; 19 | 20 | iterator begin_available() const; 21 | iterator end_available() const; 22 | bool is_available(std::string cap) const; 23 | 24 | iterator begin_enabled() const; 25 | iterator end_enabled() const; 26 | bool is_enabled(std::string cap) const; 27 | 28 | void request(std::string cap); 29 | 30 | /* 31 | * If a CAP handler (e.g. SASL) needs to keep cap negotiation open to do its own processing, 32 | * then it should call hold() in response to the cap being enabled and finish() once it has 33 | * finished. Such a hold will time out in a few seconds. 34 | */ 35 | void hold(); 36 | void finish(); 37 | 38 | Capabilities(Bot * b); 39 | ~Capabilities(); 40 | }; 41 | } 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /src/client.h: -------------------------------------------------------------------------------- 1 | #ifndef client_h 2 | #define client_h 3 | 4 | #include "privilege.h" 5 | #include "value.h" 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | namespace eir 14 | { 15 | class Bot; 16 | 17 | struct Channel; 18 | typedef std::shared_ptr ChannelPtr; 19 | struct Client; 20 | typedef std::shared_ptr ClientPtr; 21 | struct Membership; 22 | typedef std::shared_ptr MembershipPtr; 23 | 24 | struct Client : private paludis::PrivateImplementationPattern, 25 | private paludis::InstantiationPolicy, 26 | public std::enable_shared_from_this 27 | { 28 | const std::string& nick() const; 29 | const std::string& user() const; 30 | const std::string& host() const; 31 | const std::string& nuh() const; 32 | const std::string& account() const; 33 | 34 | void change_nick(std::string newnick); 35 | void set_account(std::string accountname); 36 | 37 | struct AttributeIteratorTag; 38 | typedef paludis::WrappedForwardIterator > AttributeIterator; 40 | 41 | AttributeIterator attr_begin(); 42 | AttributeIterator attr_end(); 43 | 44 | Value attr(const std::string &); 45 | void set_attr(const std::string &, const Value &); 46 | 47 | Client(Bot *, std::string, std::string, std::string); 48 | ~Client(); 49 | 50 | MembershipPtr join_chan(ChannelPtr); 51 | void leave_chan(ChannelPtr); 52 | void leave_chan(MembershipPtr); 53 | 54 | struct ChannelIteratorTag; 55 | typedef paludis::WrappedForwardIterator ChannelIterator; 56 | ChannelIterator begin_channels(); 57 | ChannelIterator end_channels(); 58 | MembershipPtr find_membership(std::string channel); 59 | ChannelIterator find_membership_it(std::string channel); 60 | const MembershipPtr find_membership(std::string channel) const; 61 | 62 | PrivilegeSet& privs(); 63 | 64 | typedef std::shared_ptr ptr; 65 | }; 66 | 67 | struct Channel : private paludis::PrivateImplementationPattern, 68 | private paludis::InstantiationPolicy, 69 | public std::enable_shared_from_this 70 | { 71 | const std::string& name(); 72 | 73 | struct MemberIteratorTag; 74 | typedef paludis::WrappedForwardIterator MemberIterator; 75 | MemberIterator begin_members(); 76 | MemberIterator end_members(); 77 | MembershipPtr find_member(std::string nick); 78 | MemberIterator find_member_it(std::string nick); 79 | 80 | bool add_member(MembershipPtr); 81 | bool remove_member(MembershipPtr); 82 | 83 | struct AttributeIteratorTag; 84 | typedef paludis::WrappedForwardIterator > AttributeIterator; 86 | 87 | AttributeIterator attr_begin(); 88 | AttributeIterator attr_end(); 89 | 90 | Value attr(const std::string &); 91 | void set_attr(const std::string &, const Value &); 92 | 93 | Channel(std::string); 94 | ~Channel(); 95 | 96 | typedef std::shared_ptr ptr; 97 | }; 98 | 99 | struct Membership : private paludis::InstantiationPolicy 100 | { 101 | Client::ptr client; 102 | Channel::ptr channel; 103 | 104 | std::string modes; 105 | 106 | bool has_mode(char m) { return modes.find(m) != std::string::npos; } 107 | 108 | typedef std::shared_ptr ptr; 109 | 110 | Membership(Client::ptr cl, Channel::ptr ch) 111 | : client(cl), channel(ch) 112 | { } 113 | }; 114 | } 115 | 116 | #endif 117 | -------------------------------------------------------------------------------- /src/command.cpp: -------------------------------------------------------------------------------- 1 | #include "command.h" 2 | #include "exceptions.h" 3 | #include "logger.h" 4 | #include "string_util.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | using namespace eir; 13 | using namespace paludis; 14 | 15 | template class paludis::InstantiationPolicy; 16 | 17 | namespace 18 | { 19 | struct HandlerMapEntry { 20 | CommandRegistry::id id; 21 | Filter filter; 22 | CommandRegistry::handler handler; 23 | bool quiet; 24 | HandlerMapEntry(CommandRegistry::id i, Filter f, CommandRegistry::handler h, bool q) 25 | : id(i), filter(f), handler(h), quiet(q) 26 | { } 27 | }; 28 | } 29 | 30 | namespace paludis 31 | { 32 | template <> 33 | struct Implementation 34 | { 35 | typedef std::multimap HandlerMap; 36 | std::vector _handlers; 37 | 38 | Implementation() : _handlers(3) 39 | { 40 | } 41 | 42 | void try_dispatch(const HandlerMapEntry & he, const Message *m, bool fatal_errors) 43 | { 44 | if (he.filter.match(m)) 45 | { 46 | try 47 | { 48 | he.handler(m); 49 | } 50 | catch (eir::Exception &e) 51 | { 52 | if (e.fatal() || fatal_errors) 53 | throw; 54 | 55 | if (!(he.quiet)) 56 | m->source.error("I have suffered a terrible failure. (" + e.message() + ") (" + e.what() + ")"); 57 | 58 | Logger::get_instance()->Log(m->bot, m->source.client, Logger::Warning, 59 | "Error processing message " + m->command + ": " + e.message() + " (" + e.what() + ")"); 60 | } 61 | catch (std::exception &e) 62 | { 63 | if (fatal_errors) 64 | throw; 65 | m->source.error(std::string("I have suffered a terrible failure. (") + e.what() + ")"); 66 | Logger::get_instance()->Log(m->bot, m->source.client, Logger::Warning, 67 | "Unknown error processing message " + m->command + ": " + e.what()); 68 | } 69 | } 70 | } 71 | }; 72 | } 73 | 74 | CommandRegistry::CommandRegistry() 75 | : paludis::PrivateImplementationPattern(new Implementation) 76 | { 77 | } 78 | 79 | CommandRegistry::~CommandRegistry() 80 | { 81 | } 82 | 83 | void CommandRegistry::dispatch(const Message *m, bool fatal_errors) 84 | { 85 | for (int i=0; i < 3; ++i) 86 | { 87 | auto range = _imp->_handlers[i].equal_range(""); 88 | for ( auto it = range.first; it != range.second; ++it ) 89 | { 90 | _imp->try_dispatch(it->second, m, fatal_errors); 91 | } 92 | 93 | range = _imp->_handlers[i].equal_range(lowercase(m->command)); 94 | for ( auto it = range.first; it != range.second; ++it ) 95 | { 96 | _imp->try_dispatch(it->second, m, fatal_errors); 97 | } 98 | } 99 | } 100 | 101 | CommandRegistry::id CommandRegistry::add_handler(Filter f, const CommandRegistry::handler & h, bool quiet_errors, Message::Order order) 102 | { 103 | static uintptr_t next_id = 1; 104 | 105 | Context ctx("Registering new handler"); 106 | 107 | next_id++; 108 | 109 | _imp->_handlers[order].insert(std::make_pair(lowercase(f.command()), 110 | HandlerMapEntry(CommandRegistry::id(next_id) ,f, h, quiet_errors))); 111 | return id(next_id); 112 | } 113 | 114 | void CommandRegistry::remove_handler(id h) 115 | { 116 | for (int i=0; i < 3; ++i) 117 | { 118 | for (Implementation::HandlerMap::iterator it = _imp->_handlers[i].begin(); 119 | it != _imp->_handlers[i].end(); ++it) 120 | { 121 | if (it->second.id == h) 122 | { 123 | _imp->_handlers[i].erase(it); 124 | break; 125 | } 126 | } 127 | } 128 | } 129 | 130 | -------------------------------------------------------------------------------- /src/command.h: -------------------------------------------------------------------------------- 1 | #ifndef command_h 2 | #define command_h 3 | 4 | #include 5 | #include 6 | #include 7 | #include "message.h" 8 | #include 9 | 10 | namespace eir 11 | { 12 | class CommandRegistry : 13 | public paludis::InstantiationPolicy, 14 | public paludis::PrivateImplementationPattern 15 | { 16 | public: 17 | typedef std::function handler; 18 | typedef struct _id { } *id; 19 | 20 | void dispatch(const Message *, bool = false); 21 | 22 | id add_handler(Filter, const handler &, bool = false, Message::Order = Message::normal); 23 | void remove_handler(id); 24 | 25 | CommandRegistry(); 26 | ~CommandRegistry(); 27 | }; 28 | } 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /src/eir.h: -------------------------------------------------------------------------------- 1 | #ifndef eir_h 2 | #define eir_h 3 | 4 | #include "message.h" 5 | #include "bot.h" 6 | #include "command.h" 7 | #include "modules.h" 8 | #include "exceptions.h" 9 | #include "match.h" 10 | #include "handler.h" 11 | #include "logger.h" 12 | #include "settings.h" 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/event.cpp: -------------------------------------------------------------------------------- 1 | #include "event_internal.h" 2 | 3 | using namespace eir; 4 | 5 | EventManager *EventManager::get_instance() 6 | { 7 | static EventManagerImpl _instance; 8 | return &_instance; 9 | } 10 | 11 | static EventManager::id next_id = 1; 12 | 13 | EventManager::id EventManagerImpl::add_event(time_t t, EventManager::event_func f) 14 | { 15 | event::ptr e(new event(next_id++, t, 0, f)); 16 | events.push_back(e); 17 | return e->_id; 18 | } 19 | 20 | EventManager::id EventManagerImpl::add_recurring_event(time_t i, EventManager::event_func f) 21 | { 22 | event::ptr e(new event(next_id++, time(NULL) + i, i, f)); 23 | events.push_back(e); 24 | return e->_id; 25 | } 26 | 27 | void EventManagerImpl::remove_event(EventManager::id id) 28 | { 29 | event_list::iterator it = events.begin(); 30 | while (it != events.end()) 31 | { 32 | event_list::iterator it2 = it++; 33 | if ((*it2)->_id == id) 34 | events.erase(it2); 35 | } 36 | } 37 | 38 | time_t EventManagerImpl::next_event_time() const 39 | { 40 | time_t t = 0; 41 | for (event_list::const_iterator it = events.begin(); it != events.end(); ++it) 42 | if (t == 0 || (*it)->next_time < t) 43 | t = (*it)->next_time; 44 | return t; 45 | } 46 | 47 | void EventManagerImpl::run_events() 48 | { 49 | time_t current_time = time(NULL); 50 | for (event_list::iterator it = events.begin(); it != events.end(); ) 51 | { 52 | if ((*it)->next_time <= current_time) 53 | { 54 | (*it)->func(); 55 | 56 | if ((*it)->interval) 57 | (*it)->next_time += (*it)->interval; 58 | else 59 | { 60 | events.erase(it++); 61 | continue; 62 | } 63 | } 64 | it++; 65 | } 66 | } 67 | 68 | -------------------------------------------------------------------------------- /src/event.h: -------------------------------------------------------------------------------- 1 | #ifndef event_h 2 | #define event_h 3 | 4 | #include 5 | #include 6 | 7 | namespace eir 8 | { 9 | class EventManager 10 | { 11 | public: 12 | typedef std::function event_func; 13 | typedef unsigned int id; 14 | 15 | virtual id add_event(time_t t, event_func f) = 0; 16 | virtual id add_recurring_event(time_t interval, event_func f) = 0; 17 | 18 | virtual void remove_event(id) = 0; 19 | 20 | static EventManager *get_instance(); 21 | }; 22 | } 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/event_internal.h: -------------------------------------------------------------------------------- 1 | #include "event.h" 2 | #include 3 | #include 4 | 5 | namespace eir 6 | { 7 | class EventManagerImpl : public EventManager 8 | { 9 | public: 10 | virtual id add_event(time_t t, event_func f); 11 | virtual id add_recurring_event(time_t interval, event_func f); 12 | 13 | virtual void remove_event(id); 14 | 15 | time_t next_event_time() const; 16 | void run_events(); 17 | 18 | private: 19 | struct event { 20 | id _id; 21 | time_t next_time; 22 | time_t interval; 23 | event_func func; 24 | event(id i, time_t t, time_t in, event_func f) 25 | : _id(i), next_time(t), interval(in), func(f) 26 | { } 27 | typedef std::shared_ptr ptr; 28 | }; 29 | typedef std::list event_list; 30 | event_list events; 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /src/exceptions.cpp: -------------------------------------------------------------------------------- 1 | // This file shouldn't really exist. 2 | // Unfortunately, type info for all the exception classes has to 3 | // exist inside the main executable, or throwing an exception from 4 | // one module that's caught in another will fail. 5 | 6 | #include "exceptions.h" 7 | 8 | using namespace eir; 9 | 10 | namespace { 11 | void silly_dummy_function() 12 | { 13 | DieException a(""); 14 | RestartException b; 15 | NotConnectedException c; 16 | ConnectionError d(""); 17 | ModuleError e(""); 18 | ConfigurationError f(""); 19 | InternalError g(""); 20 | StorageError h(""); 21 | IOError i(""); 22 | NotFoundError j(""); 23 | DisconnectedException k(""); 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /src/exceptions.h: -------------------------------------------------------------------------------- 1 | #ifndef exceptions_h 2 | #define exceptions_h 3 | 4 | #include 5 | #include 6 | 7 | #ifndef assert 8 | #define assert(x) if(!x) throw paludis::InternalError(PALUDIS_HERE, "Assertion failed: "#x) 9 | #endif 10 | 11 | namespace eir { 12 | using paludis::Context; 13 | 14 | struct Exception : public paludis::Exception 15 | { 16 | private: 17 | bool _fatal; 18 | public: 19 | Exception(std::string m, bool fatal = false) 20 | : paludis::Exception(m), _fatal(fatal) 21 | { } 22 | 23 | bool fatal() const { return _fatal; } 24 | }; 25 | 26 | struct DieException : public Exception 27 | { 28 | DieException(std::string who) : Exception("Shut down by " + who, true) 29 | { } 30 | }; 31 | 32 | struct RestartException : public Exception 33 | { 34 | RestartException() : Exception("Restarting...", true) 35 | { } 36 | }; 37 | 38 | struct DisconnectedException : public Exception 39 | { 40 | DisconnectedException(std::string s) : Exception(s, true) 41 | { } 42 | }; 43 | 44 | struct NotConnectedException : public Exception 45 | { 46 | NotConnectedException() : Exception("Not connected to server") 47 | { } 48 | }; 49 | 50 | struct ConnectionError : public Exception 51 | { 52 | ConnectionError(std::string s) : Exception(s) 53 | { } 54 | }; 55 | 56 | struct ModuleError : public Exception 57 | { 58 | ModuleError(std::string s) : Exception(s, false) { } 59 | }; 60 | 61 | struct ConfigurationError : public Exception 62 | { 63 | ConfigurationError(std::string s) : Exception(s) { } 64 | }; 65 | 66 | struct InternalError : public Exception 67 | { 68 | InternalError(std::string s) : Exception(s) { } 69 | }; 70 | 71 | struct StorageError : public Exception 72 | { 73 | StorageError(std::string s) : Exception(s) { } 74 | }; 75 | 76 | struct IOError : public Exception 77 | { 78 | IOError(std::string s) : Exception(s) { } 79 | }; 80 | 81 | struct NotFoundError : public Exception 82 | { 83 | NotFoundError(std::string s) : Exception(s) { } 84 | }; 85 | 86 | } 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /src/handler.h: -------------------------------------------------------------------------------- 1 | #ifndef handler_h 2 | #define handler_h 3 | 4 | #include "command.h" 5 | #include "event.h" 6 | #include "logger.h" 7 | #include "storage.h" 8 | #include 9 | 10 | 11 | namespace eir 12 | { 13 | template 14 | struct CommandHandlerBase 15 | { 16 | template 17 | CommandRegistry::id add_handler(Filter f, F_ h, bool quiet = false, Message::Order o = Message::normal) 18 | { 19 | return eir::CommandRegistry::get_instance()->add_handler(f, 20 | std::bind(h, static_cast(this), std::placeholders::_1), 21 | quiet, o); 22 | } 23 | 24 | template 25 | EventManager::id add_event(time_t t, F_ h) 26 | { 27 | return EventManager::get_instance()->add_event(t, 28 | std::bind(h, static_cast(this))); 29 | } 30 | 31 | template 32 | EventManager::id add_recurring_event(time_t t, F_ h) 33 | { 34 | return EventManager::get_instance()->add_recurring_event(t, 35 | std::bind(h, static_cast(this))); 36 | } 37 | }; 38 | 39 | class CommandHolder : 40 | public paludis::InstantiationPolicy 41 | { 42 | private: 43 | CommandRegistry::id _id; 44 | 45 | void _release() { if (_id) CommandRegistry::get_instance()->remove_handler(_id); _id = 0; } 46 | 47 | public: 48 | CommandHolder() : _id(0) 49 | { } 50 | CommandHolder(CommandRegistry::id id) : _id(id) 51 | { } 52 | const CommandHolder & operator= (CommandRegistry::id id) 53 | { _release(); _id = id; return *this; } 54 | 55 | ~CommandHolder() { _release(); } 56 | }; 57 | 58 | class EventHolder : 59 | public paludis::InstantiationPolicy 60 | { 61 | private: 62 | EventManager::id _id; 63 | 64 | void _release() { if (_id) EventManager::get_instance()->remove_event(_id); _id = 0; } 65 | 66 | public: 67 | EventHolder() : _id(0) 68 | { } 69 | EventHolder(EventManager::id id) : _id(id) 70 | { } 71 | const EventHolder & operator= (EventManager::id id) 72 | { _release(); _id = id; return *this; } 73 | 74 | ~EventHolder() { _release(); } 75 | }; 76 | 77 | class LogBackendHolder : 78 | public paludis::InstantiationPolicy 79 | { 80 | private: 81 | Logger::BackendId _id; 82 | 83 | void _release() { if (_id) Logger::get_instance()->unregister_backend(_id); _id = 0; } 84 | 85 | public: 86 | LogBackendHolder() : _id(0) 87 | { } 88 | LogBackendHolder(Logger::BackendId id) : _id(id) 89 | { } 90 | const LogBackendHolder & operator= (Logger::BackendId id) 91 | { _release(); _id = id; return *this; } 92 | 93 | ~LogBackendHolder() { _release(); } 94 | }; 95 | 96 | class StorageBackendHolder : 97 | public paludis::InstantiationPolicy 98 | { 99 | private: 100 | StorageManager::BackendId _id; 101 | 102 | void _release() { if (_id) StorageManager::get_instance()->unregister_backend(_id); _id = 0; } 103 | 104 | public: 105 | StorageBackendHolder() : _id(0) 106 | { } 107 | StorageBackendHolder(StorageManager::BackendId id) : _id(id) 108 | { } 109 | const StorageBackendHolder & operator= (StorageManager::BackendId id) 110 | { _release(); _id = id; return *this; } 111 | 112 | ~StorageBackendHolder() { _release(); } 113 | }; 114 | 115 | inline void dispatch_internal_message(Bot *b, std::string cmd) 116 | { 117 | Message m(b, cmd, sourceinfo::Internal); 118 | CommandRegistry::get_instance()->dispatch(&m); 119 | } 120 | } 121 | 122 | #endif 123 | -------------------------------------------------------------------------------- /src/help.h: -------------------------------------------------------------------------------- 1 | #ifndef help_h 2 | #define help_h 3 | 4 | #include "settings.h" 5 | 6 | namespace eir 7 | { 8 | struct HelpTopicHolder 9 | { 10 | std::string name; 11 | HelpTopicHolder(std::string n, std::string priv, std::string text) 12 | :name(n) 13 | { 14 | Value& help_root = GlobalSettingsManager::get_instance()->get("help_root"); 15 | 16 | if (help_root.Type() != Value::kvarray) 17 | help_root = Value(Value::kvarray); 18 | 19 | Value help_topic(Value::kvarray); 20 | help_topic["name"] = name; 21 | help_topic["priv"] = priv; 22 | help_topic["text"] = text; 23 | 24 | help_root[name] = help_topic; 25 | } 26 | ~HelpTopicHolder() 27 | { 28 | Value& help_root = GlobalSettingsManager::get_instance()->get("help_root"); 29 | if (help_root.Type() != Value::kvarray) 30 | return; 31 | help_root.KV().erase(name); 32 | } 33 | }; 34 | struct HelpIndexHolder 35 | { 36 | std::string name; 37 | HelpIndexHolder(std::string n, std::string priv) 38 | :name(n) 39 | { 40 | Value& help_index = GlobalSettingsManager::get_instance()->get("help_index"); 41 | if (help_index.Type() != Value::kvarray) 42 | help_index = Value(Value::kvarray); 43 | help_index[name] = priv; 44 | } 45 | ~HelpIndexHolder() 46 | { 47 | Value& help_index = GlobalSettingsManager::get_instance()->get("help_index"); 48 | if (help_index.Type() != Value::kvarray) 49 | return; 50 | help_index.KV().erase(name); 51 | } 52 | }; 53 | } 54 | 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /src/logger.h: -------------------------------------------------------------------------------- 1 | #ifndef logger_h 2 | #define logger_h 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace eir 12 | { 13 | class Bot; 14 | class Client; 15 | 16 | class LogDestination 17 | { 18 | public: 19 | virtual void Log(Bot *, Client *, std::string) = 0; 20 | virtual ~LogDestination() { } 21 | }; 22 | 23 | class LogBackend 24 | { 25 | public: 26 | virtual LogDestination* create_destination(std::string) = 0; 27 | virtual ~LogBackend() { } 28 | }; 29 | 30 | 31 | class Logger : public paludis::PrivateImplementationPattern, 32 | public paludis::InstantiationPolicy 33 | { 34 | public: 35 | enum 36 | { 37 | Debug = 0x01, 38 | Command = 0x02, 39 | Info = 0x04, 40 | Privs = 0x08, 41 | Warning = 0x10, 42 | Raw = 0x20, 43 | Admin = 0x40, 44 | 45 | All = 0xffffffff 46 | }; 47 | typedef unsigned int Type; 48 | 49 | void Log(Bot *, Client *, Type, std::string); 50 | void Log(Bot *, std::shared_ptr, Type, std::string); 51 | 52 | typedef unsigned int BackendId; 53 | BackendId register_backend(std::string, LogBackend *); 54 | void unregister_backend(BackendId); 55 | 56 | typedef unsigned int DestinationId; 57 | DestinationId add_destination(std::string type, std::string arg, Type types); 58 | void remove_destination(DestinationId); 59 | 60 | void clear_logs(); 61 | 62 | Logger(); 63 | ~Logger(); 64 | }; 65 | } 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | /* vim: set sw=4 sts=4 et : */ 2 | 3 | #include "bot.h" 4 | 5 | #include "message.h" 6 | #include "modules.h" 7 | #include "command.h" 8 | 9 | #include 10 | #include "exceptions.h" 11 | 12 | #include 13 | 14 | #include 15 | 16 | using namespace eir; 17 | 18 | void print_cerr(std::string s) 19 | { 20 | std::cerr << s << std::endl; 21 | } 22 | 23 | int main(int, char **argv) 24 | { 25 | std::string botname("eir"); 26 | 27 | if (argv[1] && argv[1][0]) 28 | botname = argv[1]; 29 | 30 | // We want a regular write error, not a SIGPIPE, if the socket is closed. 31 | signal(SIGPIPE, SIG_IGN); 32 | 33 | std::shared_ptr bot; 34 | 35 | while (true) 36 | { 37 | try 38 | { 39 | if (!bot) 40 | bot.reset(new Bot(botname)); 41 | 42 | bot->run(); 43 | } 44 | catch (DisconnectedException &e) 45 | { 46 | std::cerr << "Reconnecting due to error: " << e.message() << std::endl; 47 | continue; 48 | } 49 | catch (RestartException &e) 50 | { 51 | execv(argv[0], argv); 52 | } 53 | catch (DieException &e) 54 | { 55 | std::cerr << "Shutting down. " << e.message() << std::endl; 56 | return 0; 57 | } 58 | catch (paludis::Exception & e) 59 | { 60 | std::cerr << "Aborting due to exception:" << std::endl 61 | << e.backtrace("\n * ") 62 | << e.message() << " (" << e.what() << ")" << std::endl; 63 | return 1; 64 | } 65 | } 66 | 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /src/match.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ircd-ratbox: A slightly useful ircd. 3 | * irc_string.h: A header for the ircd string functions. 4 | * 5 | * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center 6 | * Copyright (C) 1996-2002 Hybrid Development Team 7 | * Copyright (C) 2002-2004 ircd-ratbox development team 8 | * 9 | * This program is free software; you can redistribute it and/or modify 10 | * it under the terms of the GNU General Public License as published by 11 | * the Free Software Foundation; either version 2 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program; if not, write to the Free Software 21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 22 | * USA 23 | * 24 | * $Id: irc_string.h 3538 2007-07-26 14:21:57Z jilles $ 25 | */ 26 | 27 | #ifndef INCLUDED_match_h 28 | #define INCLUDED_match_h 29 | 30 | /* 31 | * match - compare name with mask, mask may contain * and ? as wildcards 32 | * match - returns 1 on successful match, 0 otherwise 33 | * 34 | * mask_match - compare one mask to another 35 | * match_esc - compare with support for escaping chars 36 | * match_cidr - compares u!h@addr with u!h@addr/cidr 37 | * match_ips - compares addr with addr/cidr in ascii form 38 | */ 39 | int match(std::string mask, std::string name); 40 | int mask_match(std::string oldmask, std::string newmask); 41 | int match_esc(std::string mask, std::string name); 42 | 43 | /* 44 | * collapse - collapse a string in place, converts multiple adjacent *'s 45 | * into a single *. 46 | * collapse - modifies the contents of pattern 47 | * 48 | * collapse_esc() - collapse with support for escaping chars 49 | */ 50 | std::string collapse(std::string pattern); 51 | std::string collapse_esc(std::string pattern); 52 | 53 | #endif /* INCLUDED_match_h */ 54 | -------------------------------------------------------------------------------- /src/match_internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * character macros 3 | */ 4 | extern const unsigned char ToLowerTab[]; 5 | #define ToLower(c) (ToLowerTab[(unsigned char)(c)]) 6 | 7 | extern const unsigned char ToUpperTab[]; 8 | #define ToUpper(c) (ToUpperTab[(unsigned char)(c)]) 9 | 10 | extern const unsigned int CharAttrs[]; 11 | 12 | #define PRINT_C 0x001 13 | #define CNTRL_C 0x002 14 | #define ALPHA_C 0x004 15 | #define PUNCT_C 0x008 16 | #define DIGIT_C 0x010 17 | #define SPACE_C 0x020 18 | #define NICK_C 0x040 19 | #define CHAN_C 0x080 20 | #define KWILD_C 0x100 21 | #define CHANPFX_C 0x200 22 | #define USER_C 0x400 23 | #define HOST_C 0x800 24 | #define NONEOS_C 0x1000 25 | #define SERV_C 0x2000 26 | #define EOL_C 0x4000 27 | #define MWILD_C 0x8000 28 | #define LET_C 0x10000 /* an actual letter */ 29 | #define FCHAN_C 0x20000 /* a 'fake' channel char */ 30 | 31 | #define IsHostChar(c) (CharAttrs[(unsigned char)(c)] & HOST_C) 32 | #define IsUserChar(c) (CharAttrs[(unsigned char)(c)] & USER_C) 33 | #define IsChanPrefix(c) (CharAttrs[(unsigned char)(c)] & CHANPFX_C) 34 | #define IsChanChar(c) (CharAttrs[(unsigned char)(c)] & CHAN_C) 35 | #define IsFakeChanChar(c) (CharAttrs[(unsigned char)(c)] & FCHAN_C) 36 | #define IsKWildChar(c) (CharAttrs[(unsigned char)(c)] & KWILD_C) 37 | #define IsMWildChar(c) (CharAttrs[(unsigned char)(c)] & MWILD_C) 38 | #define IsNickChar(c) (CharAttrs[(unsigned char)(c)] & NICK_C) 39 | #define IsServChar(c) (CharAttrs[(unsigned char)(c)] & (NICK_C | SERV_C)) 40 | #define IsIdChar(c) (CharAttrs[(unsigned char)(c)] & (DIGIT_C | LET_C)) 41 | #define IsLetter(c) (CharAttrs[(unsigned char)(c)] & LET_C) 42 | #define IsCntrl(c) (CharAttrs[(unsigned char)(c)] & CNTRL_C) 43 | #define IsAlpha(c) (CharAttrs[(unsigned char)(c)] & ALPHA_C) 44 | #define IsSpace(c) (CharAttrs[(unsigned char)(c)] & SPACE_C) 45 | #define IsLower(c) (IsAlpha((c)) && ((unsigned char)(c) > 0x5f)) 46 | #define IsUpper(c) (IsAlpha((c)) && ((unsigned char)(c) < 0x60)) 47 | #define IsDigit(c) (CharAttrs[(unsigned char)(c)] & DIGIT_C) 48 | #define IsXDigit(c) (IsDigit(c) || ('a' <= (c) && (c) <= 'f') || \ 49 | ('A' <= (c) && (c) <= 'F')) 50 | #define IsAlNum(c) (CharAttrs[(unsigned char)(c)] & (DIGIT_C | ALPHA_C)) 51 | #define IsPrint(c) (CharAttrs[(unsigned char)(c)] & PRINT_C) 52 | #define IsAscii(c) ((unsigned char)(c) < 0x80) 53 | #define IsGraph(c) (IsPrint((c)) && ((unsigned char)(c) != 0x32)) 54 | #define IsPunct(c) (!(CharAttrs[(unsigned char)(c)] & \ 55 | (CNTRL_C | ALPHA_C | DIGIT_C))) 56 | 57 | #define IsNonEOS(c) (CharAttrs[(unsigned char)(c)] & NONEOS_C) 58 | #define IsEol(c) (CharAttrs[(unsigned char)(c)] & EOL_C) 59 | 60 | 61 | -------------------------------------------------------------------------------- /src/message.cpp: -------------------------------------------------------------------------------- 1 | #include "message.h" 2 | #include "string_util.h" 3 | #include "match.h" 4 | #include "bot.h" 5 | 6 | using namespace eir; 7 | 8 | Filter::Filter() 9 | : matches(0), bot(0), sourcetype(0) 10 | { 11 | } 12 | 13 | Filter& Filter::is_command(std::string c) 14 | { 15 | matches |= match_command; 16 | commandname = c; 17 | return *this; 18 | } 19 | 20 | Filter& Filter::source_type(unsigned int t) 21 | { 22 | matches |= match_source_type; 23 | sourcetype = t; 24 | return *this; 25 | } 26 | 27 | Filter& Filter::source_named(std::string n) 28 | { 29 | matches |= match_source_name; 30 | source = n; 31 | return *this; 32 | } 33 | 34 | Filter& Filter::from_bot(Bot *b) 35 | { 36 | matches |= match_bot; 37 | bot = b; 38 | return *this; 39 | } 40 | 41 | Filter& Filter::in_private() 42 | { 43 | matches |= match_private; 44 | return *this; 45 | } 46 | 47 | Filter& Filter::in_channel(std::string c) 48 | { 49 | matches |= match_in_channel; 50 | channel = c; 51 | return *this; 52 | } 53 | 54 | Filter& Filter::requires_privilege(std::string p) 55 | { 56 | matches |= match_privilege; 57 | privilege = p; 58 | return *this; 59 | } 60 | 61 | Filter& Filter::or_config() 62 | { 63 | matches |= match_config_overrides; 64 | return *this; 65 | } 66 | 67 | bool Filter::match(const Message *m) const 68 | { 69 | if (matches & match_source_type && 0 == (sourcetype & m->source.type)) 70 | return false; 71 | if (matches & match_command && ! cistring::equal(commandname, m->command)) 72 | return false; 73 | if (matches & match_bot && bot != m->bot) 74 | return false; 75 | if (matches & match_config_overrides && m->source.type == sourceinfo::ConfigFile) 76 | return true; 77 | if (matches & match_privilege && ! ( m->source.client && m->source.client->privs().has_privilege(privilege))) 78 | return false; 79 | if (matches & match_private && m->source.destination != m->bot->nick()) 80 | return false; 81 | if (matches & match_in_channel && m->source.destination != channel) 82 | return false; 83 | if (matches & match_source_name && ! ::match(source, m->source.name)) 84 | return false; 85 | 86 | return true; 87 | } 88 | 89 | -------------------------------------------------------------------------------- /src/message.h: -------------------------------------------------------------------------------- 1 | #ifndef message_h 2 | #define message_h 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "client.h" 10 | 11 | namespace eir { 12 | class Bot; 13 | 14 | struct sourceinfo { 15 | // If non-zero, this message came from somewhere other than the server, 16 | // and the value tells us where. 17 | enum { 18 | RawIrc = 0x01, 19 | ConfigFile = 0x02, 20 | SystemConsole = 0x04, 21 | Signal = 0x08, 22 | Internal = 0x10, 23 | IrcCommand = 0x20, 24 | Any = 0xff 25 | }; 26 | unsigned int type; 27 | 28 | // If client is null, source was a server or doesn't share 29 | // any channels with us. 30 | Client::ptr client; 31 | std::string name; 32 | 33 | // The raw source string that the server sent us 34 | std::string raw; 35 | 36 | // The raw destination string. 37 | std::string destination; 38 | 39 | // Function to send a reply to this. 40 | std::function reply_func, error_func; 41 | void reply(std::string text) const { 42 | if(reply_func) reply_func(text); 43 | } 44 | void error(std::string text) const { 45 | if(error_func) error_func(text); 46 | } 47 | 48 | sourceinfo(unsigned int t, Client::ptr c) 49 | : type(t), client(c), name(c->nick()) 50 | { } 51 | sourceinfo() : type(Internal) 52 | { } 53 | }; 54 | 55 | struct Message { 56 | 57 | enum Order 58 | { 59 | first = 0, 60 | normal, 61 | last 62 | }; 63 | 64 | Bot *bot; 65 | sourceinfo source; 66 | std::string command; 67 | std::vector args; 68 | 69 | std::string raw; 70 | 71 | Message(Bot *b) : bot(b) { } 72 | Message(Bot *b, std::string c) : bot(b), command(c) { } 73 | Message(Bot *b, std::string cmd, unsigned int t, Client::ptr cl) 74 | : bot(b), source(t, cl), command(cmd) 75 | { } 76 | 77 | Message(const Message& m, std::string c, unsigned int type) 78 | : bot(m.bot), source(m.source), command(c) 79 | { source.type = type; } 80 | }; 81 | 82 | class Filter { 83 | enum { 84 | match_command = 1, 85 | match_bot = 2, 86 | match_privilege = 4, 87 | match_private = 8, 88 | match_in_channel = 16, 89 | match_source_type = 32, 90 | match_source_name = 64, 91 | match_config_overrides = 128 92 | }; 93 | unsigned matches; 94 | std::string commandname, privilege, channel, source; 95 | Bot *bot; 96 | unsigned sourcetype; 97 | 98 | public: 99 | Filter(); 100 | Filter& is_command(std::string); 101 | Filter& source_type(unsigned int); 102 | Filter& source_named(std::string); 103 | Filter& from_bot(Bot *); 104 | Filter& in_private(); 105 | Filter& in_channel(std::string); 106 | Filter& requires_privilege(std::string); 107 | Filter& or_config(); 108 | 109 | bool match(const Message *) const; 110 | const std::string & command() const { return commandname; } 111 | }; 112 | 113 | inline Filter filter_type(unsigned int type) 114 | { return Filter().source_type(type); } 115 | 116 | inline Filter filter_command(std::string cmd) 117 | { return Filter().is_command(cmd); } 118 | 119 | inline Filter filter_command_type(std::string cmd, unsigned int type) 120 | { return Filter().is_command(cmd).source_type(type); } 121 | 122 | inline Filter filter_command_privilege(std::string cmd, std::string priv) 123 | { return Filter().is_command(cmd).requires_privilege(priv); } 124 | 125 | inline Filter filter_bot(Bot *b) 126 | { return Filter().from_bot(b); } 127 | 128 | inline Filter filter() { return Filter(); } 129 | } 130 | 131 | #endif 132 | -------------------------------------------------------------------------------- /src/modload.cpp: -------------------------------------------------------------------------------- 1 | #include "eir.h" 2 | 3 | #include "handler.h" 4 | 5 | using namespace eir; 6 | 7 | struct Modloader : public CommandHandlerBase 8 | { 9 | eir::CommandHolder modload_id, modunload_id, modreload_id; 10 | 11 | void do_modload(const eir::Message *m) 12 | { 13 | if (ModuleRegistry::get_instance()->is_loaded(m->args[0])) 14 | { 15 | m->source.reply(m->args[0] + " is already loaded."); 16 | } 17 | 18 | ModuleRegistry::get_instance()->load(m->args[0]); 19 | m->source.reply("Loaded " + m->args[0]); 20 | 21 | if (m->source.client) 22 | Logger::get_instance()->Log(m->bot, m->source.client, Logger::Command, 23 | "MODLOAD " + m->args[0]); 24 | Logger::get_instance()->Log(m->bot, m->source.client, Logger::Admin, 25 | "Loaded " + m->args[0]); 26 | } 27 | 28 | void do_modunload(const eir::Message *m) 29 | { 30 | Context ctx("Processing MODUNLOAD " + m->args[0]); 31 | 32 | ModuleRegistry::get_instance()->unload(m->args[0]); 33 | m->source.reply("Unloaded " + m->args[0]); 34 | 35 | if (m->source.client) 36 | Logger::get_instance()->Log(m->bot, m->source.client, Logger::Command, 37 | "MODUNLOAD " + m->args[0]); 38 | Logger::get_instance()->Log(m->bot, m->source.client, Logger::Admin, 39 | "Unloaded " + m->args[0]); 40 | } 41 | 42 | void do_modreload(const eir::Message *m) 43 | { 44 | Context ctx("Processing MODRELOAD " + m->args[0]); 45 | 46 | if (ModuleRegistry::get_instance()->is_loaded(m->args[0])) 47 | { 48 | ModuleRegistry::get_instance()->unload(m->args[0]); 49 | m->source.reply("Unloaded " + m->args[0]); 50 | } 51 | ModuleRegistry::get_instance()->load(m->args[0]); 52 | m->source.reply("Loaded " + m->args[0]); 53 | 54 | if (m->source.client) 55 | Logger::get_instance()->Log(m->bot, m->source.client, Logger::Command, 56 | "MODRELOAD " + m->args[0]); 57 | Logger::get_instance()->Log(m->bot, m->source.client, Logger::Admin, 58 | "Reloaded " + m->args[0]); 59 | } 60 | 61 | Modloader() { 62 | modload_id = add_handler(filter_command("modload").requires_privilege("admin").or_config(), 63 | &Modloader::do_modload); 64 | modunload_id = add_handler(filter_command("modunload").requires_privilege("admin").or_config(), 65 | &Modloader::do_modunload); 66 | modreload_id = add_handler(filter_command("modreload").requires_privilege("admin").or_config(), 67 | &Modloader::do_modreload); 68 | } 69 | }; 70 | 71 | Modloader m; 72 | -------------------------------------------------------------------------------- /src/modules.cpp: -------------------------------------------------------------------------------- 1 | #include "modules.h" 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | using namespace eir; 13 | using namespace paludis; 14 | 15 | template class paludis::InstantiationPolicy; 16 | 17 | namespace 18 | { 19 | struct loaded_module 20 | { 21 | std::string name; 22 | void *handle; 23 | Module *obj; 24 | }; 25 | 26 | std::string module_path() 27 | { 28 | const char *env = getenv("EIR_MODULE_DIR"); 29 | if (env) 30 | return std::string(env); 31 | 32 | return MODDIR; 33 | } 34 | } 35 | 36 | namespace paludis 37 | { 38 | template <> 39 | struct Implementation 40 | { 41 | std::list modules; 42 | }; 43 | } 44 | 45 | void ModuleRegistry::load(std::string name) throw(ModuleError) 46 | { 47 | if (is_loaded(name)) 48 | return; 49 | 50 | loaded_module mod; 51 | 52 | mod.name = name; 53 | mod.obj = 0; 54 | 55 | std::string path = module_path() + "/" + name; 56 | 57 | mod.handle = dlopen(path.c_str(), RTLD_LOCAL|RTLD_NOW); 58 | 59 | // If the above fails, perhaps it's an absolute path 60 | // if (!mod.handle) 61 | // mod.handle = dlopen(name.c_str(), RTLD_LOCAL|RTLD_NOW); 62 | 63 | if (!mod.handle) 64 | throw ModuleError(dlerror()); 65 | 66 | try 67 | { 68 | Module* (*create)() = reinterpret_cast( 69 | reinterpret_cast(dlsym(mod.handle, "create"))); 70 | if (!create) 71 | throw ModuleError("Module " + name + " does not contain a create() function."); 72 | 73 | mod.obj = create(); 74 | if (!mod.obj) 75 | throw ModuleError("Module initialisation failed in " + name); 76 | 77 | _imp->modules.push_back(mod); 78 | } 79 | catch (ModuleError &) 80 | { 81 | dlclose(mod.handle); 82 | 83 | throw; 84 | } 85 | catch (Exception & e) 86 | { 87 | dlclose(mod.handle); 88 | 89 | throw ModuleError(e.message()); 90 | } 91 | catch (std::exception & e) 92 | { 93 | dlclose(mod.handle); 94 | 95 | throw ModuleError(e.what()); 96 | } 97 | } 98 | 99 | bool ModuleRegistry::unload(std::string name) 100 | { 101 | std::list::iterator mod = _imp->modules.end(); 102 | for (std::list::iterator it = _imp->modules.begin(); it != _imp->modules.end(); ++it) 103 | { 104 | if (it->name == name) 105 | mod = it; 106 | } 107 | 108 | if (mod == _imp->modules.end()) 109 | return false; 110 | 111 | if (mod->obj) 112 | delete mod->obj; 113 | mod->obj = 0; 114 | 115 | if(dlclose(mod->handle) != 0) 116 | throw ModuleError(dlerror()); 117 | 118 | _imp->modules.erase(mod); 119 | 120 | return true; 121 | } 122 | 123 | bool ModuleRegistry::is_loaded(std::string name) 124 | { 125 | for (std::list::iterator it = _imp->modules.begin(); it != _imp->modules.end(); ++it) 126 | { 127 | if (it->name == name) 128 | return true; 129 | } 130 | return false; 131 | } 132 | 133 | ModuleRegistry::ModuleRegistry() 134 | : PrivateImplementationPattern(new Implementation) 135 | { 136 | } 137 | 138 | ModuleRegistry::~ModuleRegistry() 139 | { 140 | } 141 | 142 | Module::~Module() 143 | { 144 | } 145 | -------------------------------------------------------------------------------- /src/modules.h: -------------------------------------------------------------------------------- 1 | #ifndef modules_h 2 | #define modules_h 3 | 4 | #include 5 | #include "exceptions.h" 6 | #include 7 | #include 8 | 9 | namespace eir { 10 | 11 | class ModuleRegistry : public paludis::InstantiationPolicy, 12 | public paludis::PrivateImplementationPattern 13 | { 14 | public: 15 | void load(std::string) throw(ModuleError); 16 | bool unload(std::string); 17 | 18 | bool is_loaded(std::string); 19 | 20 | ModuleRegistry(); 21 | ~ModuleRegistry(); 22 | }; 23 | 24 | // A module's create() function should return a pointer to one of these. It will be destroyed 25 | // before unloading the module. 26 | class Module 27 | { 28 | public: 29 | virtual ~Module() = 0; 30 | }; 31 | } 32 | 33 | // Utility macro to save typing in module source files 34 | #define MODULE_CLASS(x) extern "C" Module *create() { return new x;} 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/privilege.cpp: -------------------------------------------------------------------------------- 1 | #include "privilege.h" 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | using namespace eir; 9 | 10 | namespace paludis 11 | { 12 | template <> 13 | struct Implementation 14 | { 15 | std::set > privs; 16 | }; 17 | } 18 | 19 | PrivilegeSet::iterator PrivilegeSet::begin() 20 | { 21 | return _imp->privs.begin(); 22 | } 23 | 24 | PrivilegeSet::iterator PrivilegeSet::end() 25 | { 26 | return _imp->privs.end(); 27 | } 28 | 29 | bool PrivilegeSet::has_privilege(std::string c, std::string p) 30 | { 31 | return _imp->privs.find(make_pair(c, p)) != _imp->privs.end() || 32 | _imp->privs.find(make_pair("", p)) != _imp->privs.end(); 33 | } 34 | 35 | void PrivilegeSet::add_privilege(std::string c, std::string p) 36 | { 37 | _imp->privs.insert(make_pair(c, p)); 38 | } 39 | 40 | bool PrivilegeSet::has_privilege(std::string p) 41 | { 42 | return _imp->privs.find(make_pair("", p)) != _imp->privs.end(); 43 | } 44 | 45 | void PrivilegeSet::add_privilege(std::string p) 46 | { 47 | _imp->privs.insert(make_pair("", p)); 48 | } 49 | 50 | void PrivilegeSet::clear() 51 | { 52 | _imp->privs.clear(); 53 | } 54 | 55 | PrivilegeSet::PrivilegeSet() 56 | : paludis::PrivateImplementationPattern(new paludis::Implementation()) 57 | { 58 | } 59 | 60 | PrivilegeSet::~PrivilegeSet() 61 | { 62 | } 63 | 64 | template class paludis::WrappedForwardIterator >; 66 | 67 | -------------------------------------------------------------------------------- /src/privilege.h: -------------------------------------------------------------------------------- 1 | #ifndef privilege_h 2 | #define privilege_h 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace eir 9 | { 10 | class PrivilegeSet : public paludis::PrivateImplementationPattern 11 | { 12 | public: 13 | struct PrivilegeIteratorTag; 14 | typedef paludis::WrappedForwardIterator > iterator; 16 | 17 | iterator begin(); 18 | iterator end(); 19 | 20 | // One-argument forms are for global privilege; two-argument forms for channel privs. 21 | bool has_privilege(std::string); 22 | void add_privilege(std::string); 23 | 24 | bool has_privilege(std::string, std::string); 25 | void add_privilege(std::string, std::string); 26 | 27 | void clear(); 28 | 29 | PrivilegeSet(); 30 | ~PrivilegeSet(); 31 | }; 32 | } 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/server.h: -------------------------------------------------------------------------------- 1 | #ifndef server_h 2 | #define server_h 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "bot.h" 10 | 11 | namespace eir 12 | { 13 | class Server : private paludis::PrivateImplementationPattern 14 | { 15 | public: 16 | typedef std::function Handler; 17 | Server(const Handler&, Bot *); 18 | ~Server(); 19 | 20 | void connect(std::string host, std::string port); 21 | 22 | void send(std::string); 23 | 24 | void purge(); 25 | 26 | void disconnect(std::string message); 27 | 28 | void run(); 29 | 30 | void set_throttle(int burst, int time, int num); 31 | 32 | private: 33 | Server(); 34 | Server (const Server &); 35 | }; 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /src/settings.cpp: -------------------------------------------------------------------------------- 1 | #include "settings.h" 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace eir; 10 | using namespace paludis; 11 | 12 | template class paludis::WrappedForwardIterator >; 13 | template class paludis::InstantiationPolicy; 14 | 15 | namespace paludis 16 | { 17 | template <> 18 | struct Implementation 19 | { 20 | std::map _map; 21 | }; 22 | } 23 | 24 | GlobalSettingsManager::iterator GlobalSettingsManager::begin() 25 | { 26 | return _imp->_map.begin(); 27 | } 28 | 29 | GlobalSettingsManager::iterator GlobalSettingsManager::end() 30 | { 31 | return _imp->_map.end(); 32 | } 33 | 34 | GlobalSettingsManager::iterator GlobalSettingsManager::find(std::string name) 35 | { 36 | return _imp->_map.find(name); 37 | } 38 | 39 | Value& GlobalSettingsManager::get(std::string name) 40 | { 41 | return _imp->_map[name]; 42 | } 43 | 44 | Value GlobalSettingsManager::get_with_default(std::string name, Value _default) 45 | { 46 | iterator it = find(name); 47 | if (it == end()) 48 | return _default; 49 | return it->second; 50 | } 51 | 52 | bool GlobalSettingsManager::add(std::string name, Value v) 53 | { 54 | return _imp->_map.insert(std::make_pair(name, v)).second; 55 | } 56 | 57 | size_t GlobalSettingsManager::remove(std::string n) 58 | { 59 | return _imp->_map.erase(n); 60 | } 61 | 62 | void GlobalSettingsManager::remove(GlobalSettingsManager::iterator it) 63 | { 64 | _imp->_map.erase(it.underlying_iterator::iterator>()); 65 | } 66 | 67 | GlobalSettingsManager::GlobalSettingsManager() 68 | : PrivateImplementationPattern(new Implementation) 69 | { 70 | } 71 | 72 | GlobalSettingsManager::~GlobalSettingsManager() 73 | { 74 | } 75 | -------------------------------------------------------------------------------- /src/settings.h: -------------------------------------------------------------------------------- 1 | #ifndef settings_h 2 | #define settings_h 3 | 4 | #include "value.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace eir 11 | { 12 | class GlobalSettingsManager : public paludis::PrivateImplementationPattern, 13 | public paludis::InstantiationPolicy 14 | { 15 | public: 16 | struct IteratorTag; 17 | typedef paludis::WrappedForwardIterator > iterator; 19 | iterator begin(); 20 | iterator end(); 21 | 22 | iterator find(std::string name); 23 | 24 | Value& get(std::string name); 25 | Value get_with_default(std::string name, Value _default); 26 | 27 | bool add(std::string n, Value v); 28 | 29 | size_t remove(std::string n); 30 | void remove(iterator it); 31 | 32 | GlobalSettingsManager(); 33 | ~GlobalSettingsManager(); 34 | }; 35 | } 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/storage.h: -------------------------------------------------------------------------------- 1 | #ifndef storage_h 2 | #define storage_h 3 | 4 | #include "value.h" 5 | 6 | namespace eir 7 | { 8 | class StorageBackend 9 | { 10 | public: 11 | virtual void Save(const eir::Value &, std::string) = 0; 12 | virtual eir::Value Load(std::string) = 0; 13 | 14 | virtual ~StorageBackend() { } 15 | }; 16 | 17 | class StorageManager : public paludis::PrivateImplementationPattern, 18 | public paludis::InstantiationPolicy 19 | { 20 | public: 21 | void Save(const eir::Value &, std::string); 22 | eir::Value Load(std::string); 23 | void auto_save(const eir::Value *, std::string); 24 | 25 | typedef unsigned int BackendId; 26 | BackendId register_backend(std::string, StorageBackend *); 27 | void unregister_backend(BackendId); 28 | 29 | std::string default_backend(); 30 | void default_backend(std::string); 31 | 32 | StorageManager(); 33 | ~StorageManager(); 34 | }; 35 | } 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/string_util.cpp: -------------------------------------------------------------------------------- 1 | #include "string_util.h" 2 | 3 | namespace eir 4 | { 5 | namespace cistring 6 | { 7 | /* stolen shamelessly from ircd source code, and encoding rfc1459 casemapping rules */ 8 | unsigned char tolowertab[256] = { 9 | 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 10 | 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 11 | 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 12 | 0x1e, 0x1f, 13 | ' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')', 14 | '*', '+', ',', '-', '.', '/', 15 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 16 | ':', ';', '<', '=', '>', '?', 17 | '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 18 | 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 19 | 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', 20 | '_', 21 | '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 22 | 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 23 | 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', 24 | 0x7f, 25 | 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 26 | 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 27 | 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 28 | 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 29 | 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 30 | 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 31 | 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 32 | 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 33 | 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 34 | 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 35 | 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 36 | 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 37 | 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 38 | 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 39 | 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 40 | 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff 41 | }; 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /src/string_util.h: -------------------------------------------------------------------------------- 1 | #ifndef string_util_h 2 | #define string_util_h 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace eir 10 | { 11 | inline std::string lowercase(std::string s) 12 | { 13 | std::string ret; 14 | std::transform(s.begin(), s.end(), std::back_inserter(ret), 15 | static_cast(std::tolower)); 16 | return ret; 17 | } 18 | 19 | namespace cistring 20 | { 21 | extern unsigned char tolowertab[256]; 22 | 23 | inline bool equal(std::string lhs, std::string rhs) 24 | { 25 | if (lhs.size() != rhs.size()) return false; 26 | 27 | for (std::string::size_type i=0; i < lhs.size(); i++) 28 | { 29 | if (tolowertab[(unsigned char)lhs[i]] != tolowertab[(unsigned char)rhs[i]]) return false; 30 | } 31 | return true; 32 | } 33 | 34 | inline bool less(std::string lhs, std::string rhs) 35 | { 36 | for (std::string::size_type i=0; ; i++) 37 | { 38 | if (i == lhs.size()) return true; 39 | if (i == rhs.size()) return false; 40 | if (tolowertab[(unsigned char)lhs[i]] < tolowertab[(unsigned char)rhs[i]]) return true; 41 | if (tolowertab[(unsigned char)lhs[i]] > tolowertab[(unsigned char)rhs[i]]) return false; 42 | } 43 | return false; 44 | } 45 | 46 | inline unsigned long hash(std::string arg) 47 | { 48 | unsigned long ret = 5381; 49 | for (std::string::size_type i=0; i < arg.size(); ++i) 50 | ret = ret * 33 ^ tolowertab[(unsigned char)arg[i]]; 51 | return ret; 52 | } 53 | 54 | struct is_equal 55 | { 56 | bool operator() (std::string l, std::string r) const { return equal(l, r); } 57 | }; 58 | struct is_less 59 | { 60 | bool operator() (std::string l, std::string r) const { return less(l, r); } 61 | }; 62 | struct hasher 63 | { 64 | bool operator() (std::string s) const { return hash(s); } 65 | }; 66 | } 67 | } 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /src/supported.h: -------------------------------------------------------------------------------- 1 | #ifndef supported_h 2 | #define supported_h 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace eir 11 | { 12 | struct Message; 13 | class Bot; 14 | 15 | class ISupport : private paludis::InstantiationPolicy, 16 | private paludis::PrivateImplementationPattern 17 | { 18 | public: 19 | typedef std::set::const_iterator simple_iterator; 20 | 21 | enum ModeType { 22 | simple_mode, 23 | list_mode, 24 | oneparam_mode, 25 | oneparam2_mode, 26 | prefix_mode, 27 | unknown_mode 28 | }; 29 | 30 | simple_iterator begin_simple_tokens() const; 31 | simple_iterator end_simple_tokens() const; 32 | simple_iterator find_simple_token(std::string s) const; 33 | 34 | bool supports(std::string s) const; 35 | 36 | typedef std::map::const_iterator kv_iterator; 37 | 38 | kv_iterator begin_kv() const; 39 | kv_iterator end_kv() const; 40 | kv_iterator find_kv(std::string s) const; 41 | 42 | std::pair get_value(std::string s) const; 43 | 44 | int max_modes() const; 45 | std::string list_modes() const; 46 | std::string simple_modes() const; 47 | std::string oneparam_modes() const; 48 | std::string prefix_modes() const; 49 | 50 | char get_prefix_mode(char prefix) const; 51 | char get_mode_prefix(char mode) const; 52 | 53 | ModeType get_mode_type(char c) const; 54 | 55 | bool is_mode_prefix(char c) const; 56 | 57 | bool mode_has_param(char modeletter, bool adding = true) const; 58 | 59 | bool is_channel_name(std::string) const; 60 | 61 | ISupport(Bot*); 62 | ~ISupport(); 63 | }; 64 | } 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /src/times.h: -------------------------------------------------------------------------------- 1 | #ifndef times_h 2 | #define times_h 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "exceptions.h" 9 | 10 | namespace eir 11 | { 12 | /* Parses "" into a number of seconds. 13 | * h == hour, d == day, m == month (four weeks, for simplicity) 14 | */ 15 | time_t parse_time(std::string ts) 16 | { 17 | std::string::iterator b = ts.begin(), e = ts.end(); 18 | int val = 0, mult; 19 | 20 | if (*b == '~') 21 | ++b; 22 | switch (*--e) 23 | { 24 | case 'm': 25 | mult = 60; 26 | e = ts.erase(e); 27 | break; 28 | case 'h': 29 | mult = 3600; 30 | e = ts.erase(e); 31 | break; 32 | case 'd': 33 | mult = 3600 * 24; 34 | e = ts.erase(e); 35 | break; 36 | default: 37 | mult = 1; 38 | break; 39 | } 40 | 41 | val = atoi(std::string(b, ++e).c_str()); 42 | 43 | return val * mult; 44 | } 45 | 46 | } 47 | 48 | #endif 49 | --------------------------------------------------------------------------------