pax_global_header00006660000000000000000000000064112427374100014513gustar00rootroot0000000000000052 comment=a65cfffc50801c09551b70d6bbd7a19e6b2c57dd manderlbot-manderlbot-0.9.3/000077500000000000000000000000001124273741000160005ustar00rootroot00000000000000manderlbot-manderlbot-0.9.3/LICENSE000066400000000000000000000431311124273741000170070ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. manderlbot-manderlbot-0.9.3/Makefile.in000066400000000000000000000134071124273741000200520ustar00rootroot00000000000000#### CONFIGURE VARIABLE # export ERLC_EMULATOR to fix a bug in R9B with native compilation ERLC_EMULATOR=@ERL@ export ERLC_EMULATOR ERL=@ERL@ ERLC=@ERLC@ SED=@SED@ ERL_OPTS=@ERL_OPTS@ ERLDIR=@ERLDIR@ export ERLDIR ERLANG_XMERL_DIR=@ERLANG_XMERL_DIR@ raw_erlang_prefix=@libdir@/erlang/ prefix=$(DESTDIR)@prefix@ exec_prefix=@exec_prefix@ bindir=@bindir@ sysconfdir=@sysconfdir@ libdir=@libdir@ datadir=@datadir@ CONFIGURE_DEPENDENCIES=@CONFIGURE_DEPENDENCIES@ CONFIG_STATUS_DEPENDENCIES=@CONFIG_STATUS_DEPENDENCIES@ VERSION=@PACKAGE_VERSION@ PACKAGE=@PACKAGE_NAME@ DTD=@DTD@ #### END OF SUBSTITUTION SVN_REVISION=$Revision$ ERL_COMPILER_OPTIONS="[warn_unused_vars]" export ERL_COMPILER_OPTIONS ifeq ($(TYPE),debug) OPT =+debug_info -DDEBUG else ifeq ($(TYPE),native) OPT:=+native else OPT = endif endif INC = ./inc CC = $(ERLC) ESRC = ./src EBIN = ./ebin ifeq ($(TYPE),snapshot) DAY=$(shell date +"%Y%m%d") distdir = $(PACKAGE)-$(VERSION)-$(DAY) else distdir = $(PACKAGE)-$(VERSION) endif # installation path BINDIR = $(bindir) CONFDIR = $(sysconfdir)/manderlbot/ SHARE_DIR = $(datadir)/manderlbot/ MAN_DIR = $(datadir)/man/ DOC_DIR = $(datadir)/doc/manderlbot ERLANG_LIB_DIR = $(libdir)/erlang/lib APPLICATION = manderlbot TARGETDIR = $(ERLANG_LIB_DIR)/$(APPLICATION)-$(VERSION) TMP = $(wildcard *~) $(wildcard src/*~) $(wildcard inc/*~) INC_FILES = $(wildcard $(INC)/*.hrl) LIBSRC = $(wildcard $(ESRC)/lib/*.erl) SRC = $(wildcard $(ESRC)/*.erl) CONFFILE = conf/config.xml $(wildcard conf/*fortune) PERL_SCRIPTS_SRC = $(wildcard $(ESRC)/*.pl.in) PERL_SCRIPTS = $(basename $(PERL_SCRIPTS_SRC)) TARGET = $(addsuffix .beam, $(basename \ $(addprefix $(EBIN)/, $(notdir $(SRC))))) DEBIAN = debian/changelog debian/control debian/copyright debian/docs debian/manderlbot.dirs debian/rules SRC_APPFILES = $(ESRC)/$(APPLICATION).app.src $(ESRC)/$(APPLICATION).rel.src TGT_APPFILES_E = $(EBIN)/$(APPLICATION).app TGT_APPFILES_P = priv/$(APPLICATION)* SCRIPT = $(BINDIR)/manderlbot PWD = $(shell pwd) BUILD_OPTIONS = '[{systools, \ [{variables,[ \ {"MANDERLBOTPATH", "$(PWD)/temp/"}] \ }]}, \ {sh_script, none}, \ {make_app, true }, {make_rel, true}].' BUILD_OPTIONS_DOT = $(subst $(PWD)/temp/,./,$(BUILD_OPTIONS)) BUILD_OPTIONS_FILE = ./BUILD_OPTIONS DIST_COMMON=Makefile.in $(CONFFILE) manderlbot.sh.in .PHONY: doc manderlbot: Makefile config.status manderlbot.sh ebin $(TARGET) all: clean manderlbot debug: $(MAKE) TYPE=debug native: $(MAKE) TYPE=native validate: $(CONFFILE) @for i in $(CONFFILE); do xmlproc_val $$i; done deb: fakeroot debian/rules clean debian/rules build fakeroot debian/rules binary ebin: mkdir ebin clean: -cd priv && rm -f $(shell ls priv | grep -v builder\.erl| grep -v CVS) && cd .. -rm -f $(TARGET) $(TMP) $(BUILD_OPTIONS_FILE) builder.beam -rm -f $(TGT_APPFILES_P) $(TGT_APPFILES_E) manderlbot.sh -rm -f ebin/*.beam manderlbot.sh manderlbot.xml install: doc boot $(CONFFILE) -rm -f $(TMP) install -d $(TARGETDIR)/priv install -d $(TARGETDIR)/ebin install -d $(TARGETDIR)/src install -d $(TARGETDIR)/include install -d $(BINDIR)/ cp $(INC_FILES) $(TARGETDIR)/include cp $(TARGET) $(TARGETDIR)/ebin cp builder.beam $(TARGETDIR)/ebin cp $(TGT_APPFILES_E) $(TARGETDIR)/ebin cp $(TGT_APPFILES_P) $(TARGETDIR)/priv cp $(SRC) $(SRC_APPFILES) $(TARGETDIR)/src echo $(BUILD_OPTIONS_DOT) > $(TARGETDIR)/BUILD_OPTIONS # install the man pages install -d $(MAN_DIR)/man1 install -d $(MAN_DIR)/man5 install doc/manderlbot.1 $(MAN_DIR)/man1 install doc/manderlbot.conf.5 $(MAN_DIR)/man5 # create startup script install manderlbot.sh $(SCRIPT) install -d $(CONFDIR) cp $(CONFFILE) $(CONFDIR) uninstall: rm -rf $(TARGETDIR) $(SCRIPT) boot: manderlbot priv/manderlbot.boot priv/manderlbot.boot: builder.beam $(SRC_APPFILES) # use builder to make boot file @rm -rf temp @mkdir -p temp/lib/$(APPLICATION)-$(VERSION) @ln -sf $(PWD)/ebin temp/lib/$(APPLICATION)-$(VERSION)/ebin @ln -sf $(PWD)/src/ temp/lib/$(APPLICATION)-$(VERSION)/src @ln -sf $(PWD)/inc temp/lib/$(APPLICATION)-$(VERSION)/include @ln -sf $(PWD)/priv temp/lib/$(APPLICATION)-$(VERSION)/priv @ln -sf $(PWD)/builder.beam temp/lib/$(APPLICATION)-$(VERSION)/ @ln -sf $(PWD) temp/lib/$(APPLICATION)-$(VERSION) @echo -n "build main app boot script ... " @(cd temp/lib/$(APPLICATION)-$(VERSION) \ && echo $(BUILD_OPTIONS) > $(BUILD_OPTIONS_FILE) \ && $(ERL) -s builder go -s init stop > /dev/null 2>&1 \ ) @rm -rf temp @echo "done" Makefile: Makefile.in config.status @$(SHELL) ./config.status --file=$@ %.pl: %.pl.in vsn.mk @$(SHELL) ./config.status --file=$@ %.xml: %.xml.in @$(SHELL) ./config.status --file=$@ %.sh :%.sh.in vsn.mk @$(SHELL) ./config.status --file=$@ config.status: configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck configure: configure.in $(CONFIGURE_DEPENDENCIES) @echo "running autoconf" @autoconf doc: $(MAKE) -C doc release: Makefile doc rm -fr $(distdir) mkdir -p $(distdir) tar zcf tmp.tgz $(SRC) $(SRC_APPFILES) $(INC_FILES) $(LIBSRC) \ doc/Makefile doc/*.sgml doc/*.1 \ LICENSE README TODO $(CONFFILE) $(DEBIAN)\ priv/builder.erl manderlbot.sh.in vsn.mk \ configure configure.in Makefile.in tar -C $(distdir) -zxf tmp.tgz mkdir $(distdir)/ebin tar zvcf $(distdir).tar.gz $(distdir) rm -fr $(distdir) rm -fr tmp.tgz snapshot: $(MAKE) TYPE=snapshot release builder.beam: priv/builder.erl @$(CC) -W0 $(OPT) -I $(INC) $< ebin: mkdir ebin ebin/%.beam: src/lib/%.erl $(INC_FILES) @echo "Compiling $< ... " @$(CC) -W0 $(OPT) -I $(INC) -I $(ERLANG_XMERL_DIR) -o ebin $< ebin/%.beam: src/%.erl $(INC_FILES) @echo "Compiling $< ... " @$(CC) $(OPT) -I $(INC) -I $(ERLANG_XMERL_DIR) -o ebin $< %:%.sh # Override makefile default implicit rule manderlbot-manderlbot-0.9.3/README000066400000000000000000000014551124273741000166650ustar00rootroot00000000000000This is manderlbot, an attempt to write an irc bot in erlang, with a XML based configuration. To use it, install erlang, then xmerl-0.15 http://www.erlang.org/user.html#xmerl-0.15 On my system this means install the compiled files in /usr/lib/erlang/lib/xmerl-0.15 make install will provide you /usr/bin/manderlbot to start the bot. If you have installed the debian package, you don't have to make install. Once manderlbot is running, you can obtain a shell on the erlang VM it is running in, by launching another VM and connecting to the former. erl -setcookie mdb -sname control (control@node)1> Then you hit ^G and connect to the manderlbot VM: User switch command --> r manderlbot@node --> c 3 If you want to stop manderlbot, you can now type in (manderlbot@node)1> application:stop(manderlbot). manderlbot-manderlbot-0.9.3/TODO000066400000000000000000000025251124273741000164740ustar00rootroot00000000000000$Id$ Behaviours Mood Add some mood elements in config, and provides mood switchers in the config. Then allow each behaviour to be choosen on a mood base. Mail Manderlbot should be abble to send a mail a configured address Prefix To prefix the commands to be given to manderlbot. To be done on a per channel base. Prefix example : '!' Serializer And we could have a behaviour:add() function to play with, and we could even add behaviours from irc ! Config DTD Behaviours lists, inheritance Add a file parameter to channel element, where to log irc messages. RELEASE PLAN FOR 1.0 -=-=-=-=-=-=-=-=-=-=- manderlbot 1.0 should be able to . connect to irc server, identify itself . register its name to nickserv when relevant . log channels, one per file . react to what is said on irc (matching on nick/action/to/message) by launching the configured behaviour . have some mood and be able to change whether on reaction to some irc event or just with time, all configurable . speak by itself from time to time, with some special behaviours to choose what to say, depending on its mood LATTER PLANS -=-=-=-=-=-=- . distributed erlang application : configure some manderlbot nodes to manage failover . manderlbot has to be abble to ghost itself (nickserv) . edit the config from irc manderlbot-manderlbot-0.9.3/conf/000077500000000000000000000000001124273741000167255ustar00rootroot00000000000000manderlbot-manderlbot-0.9.3/conf/bofh.fortune000066400000000000000000000403431124273741000212530ustar00rootroot00000000000000% clock speed % solar flares % electromagnetic radiation from satellite debris % static from nylon underwear % static from plastic slide rules % global warming % poor power conditioning % static buildup % doppler effect % hardware stress fractures % magnetic interferance from money/credit cards % dry joints on cable plug % we're waiting for [the phone company] to fix that line % sounds like a Windows problem, try calling Microsoft support % temporary routing anomoly % somebody was calculating pi on the server % fat electrons in the lines % excess surge protection % floating point processor overflow % divide-by-zero error % POSIX complience problem % monitor resolution too high % improperly oriented keyboard % network packets travelling uphill (use a carrier pigeon) % Decreasing electron flux % first Saturday after first full moon in Winter % radiosity depletion % CPU radiator broken % It works the way the Wang did, what's the problem % positron router malfunction % cellular telephone interference % techtonic stress % pizeo-electric interference % (l)user error % working as designed % dynamic software linking table corrupted % heavy gravity fluctuation, move computer to floor rapidly % secretary plugged hairdryer into UPS % terrorist activities % not enough memory, go get system upgrade % interrupt configuration error % spaghetti cable cause packet failure % boss forgot system password % bank holiday - system operating credits not recharged % virus attack, luser responsible % waste water tank overflowed onto computer % Complete Transient Lockout % bad ether in the cables % Bogon emissions % Change in Earth's rotational speed % Cosmic ray particles crashed through the hard disk platter % Smell from unhygenic janitorial staff wrecked the tape heads % Evil dogs hypnotized the night shift % Plumber mistook routing panel for decorative wall fixture % Electricians made popcorn in the power supply % Groundskeepers stole the root password % high pressure system failure % failed trials, system needs redesigned % system has been recalled % not approved by the FCC % need to wrap system in aluminum foil to fix problem % not properly grounded, please bury computer % CPU needs recalibration % bit bucket overflow % descramble code needed from software company % only available on a need to know basis % knot in cables caused data stream to become twisted and kinked % nesting roaches shorted out the ether cable % The file system is full of it % Satan did it % Daemons did it % You're out of memory % There isn't any problem % Unoptimized hard drive % Typo in the code % Yes, yes, its called a desgin limitation % Look, buddy: Windows 3.1 IS A General Protection Fault. % Support staff hung over, send aspirin and come back LATER. % Someone is standing on the ethernet cable, causeing a kink in the cable % Windows 95 undocumented "feature" % Runt packets % Password is too complex to decrypt % Boss' kid fucked up the machine % Electromagnetic energy loss % Budget cuts % Mouse chewed through power cable % Stale file handle (next time use Tupperware(tm)!) % Feature not yet implimented % Internet outage % Pentium FDIV bug % Vendor no longer supports the product % Small animal kamikaze attack on power supplies % The vendor put the bug there. % SIMM crosstalk. % IRQ dropout % Collapsed Backbone % Power company testing new voltage spike (creation) equipment % operators on strike due to broken coffee machine % backup tape overwritten with copy of system manager's favourite CD % UPS interrupted the server's power % The electrician didn't know what the yellow cable was so he yanked the ethernet out. % The keyboard isn't plugged in % The air conditioning water supply pipe ruptured over the machine room % The electricity substation in the car park blew up. % The rolling stones concert down the road caused a brown out % The salesman drove over the CPU board. % Root nameservers are out of sync % electro-magnetic pulses from French above ground nuke testing. % your keyboard's space bar is generating spurious keycodes. % the real ttys became pseudo ttys and vice-versa. % the printer thinks its a router. % the router thinks its a printer. % we just switched to FDDI. % halon system went off and killed the operators. % user to computer ratio too high. % user to computer ration too low. % Sticky bits on disk. % Power Company having EMP problems with their reactor % The ring needs another token % SCSI Chain overterminated % because of network lag due to too many people playing deathmatch % Daemons loose in system. % BNC (brain not (user brain not connected) % UBNC (user brain not connected) % LBNC (luser brain not connected) % disks spinning backwards - toggle the hemisphere jumper. % new guy cross-connected phone lines with ac power bus. % had to use hammer to free stuck disk drive heads. % Too few computrons available. % Flat tire on station wagon with tapes. ("Never underestimate the bandwidth of a station wagon full of tapes hurling down the highway" Andrew S. Tanenbaum) % Communications satellite used by the military for star wars. % Party-bug in the Aloha protocol. % Insert coin for new game % Dew on the telephone lines. % Arcserve crashed the server again. % Some one needed the powerstrip, so they pulled the switch plug. % My pony-tail hit the on/off switch on the power strip. % Big to little endian conversion error % You can tune a file system, but you can't tune a fish (from most tunefs man pages) % Dumb terminal % Zombie processes haunting the computer % Incorrect time syncronization % Defunct processes % Stubborn processes % non-redundant fan failure % monitor VLF leakage % bugs in the RAID % no "any" key on keyboard % root rot % Backbone Scoliosis % mv /pub/lunch % excessive collisions and not enough packet ambulances % le0: no carrier: transceiver cable problem? % broadcast packets on wrong frequency % popper unable to process jumbo kernel % NOTICE: alloc: /dev/null: filesystem full % pseudo-user on a pseudo-terminal % Recursive traversal of loopback mount points % Backbone adjustment % OS swapped to disk % vapors from evaporating sticky-note adhesives % sticktion % short leg on process table % multicasts on broken packets % ether leak % Atilla the Hub % endothermal recalibration % filesystem not big enough for Jumbo Kernel Patch % loop found in loop in redundant loopback % system consumed all the paper for paging % permission denied % Reformatting Page. Wait... % SCSI's too wide. % Proprietary Information. % Just type 'mv * /dev/null'. % runaway cat on system. % We only support a 1200 bps connection. % Me no internet, only janitor, me just wax floors. % I'm sorry a pentium won't do, you need an SGI to connect with us. % Post-it Note Sludge leaked into the monitor. % the curls in your keyboard cord are losing electricity. % The monitor needs another box of pixels. % RPC_PMAP_FAILURE % kernel panic: write-only-memory (/dev/wom0) capacity exceeded. % Write-only-memory subsystem too slow for this machine. Contact your local dealer. % Quantum dynamics are affecting the transistors % Police are examining all internet packets in the search for a narco-net-traficer % We are currently trying a new concept of using a live mouse. Unfortuantely, one has yet to survive being hooked up to the computer.....please bear with us. % We didn't pay the Internet bill and it's been cut off. % Lightning strikes. % Of course it doesn't work. We've performed a software upgrade. % Change your language to Finnish. % Flourescent lights are generating negative ions. If turning them off doesn't work, take them out and put tin foil on the ends. % High nuclear activity in your area. % The MGs ran out of gas. % The UPS doesn't have a battery backup. % Recursivity. Call back if it happens again. % Someone thought The Big Red Button was a light switch. % The mainframe needs to rest. % Try calling the Internet's head office -- it's in the book. % The lines are all busy (busied out, that is -- why let them in to begin with?). % A star wars satellite accidently blew up the WAN. % Fatal error right in front of screen % wrong polarity of neutron flow % Lusers learning curve appears to be fractal % We had to turn off that service to comply with the CDA Bill. % Ionisation from the air-conditioning % TCP/IP UDP alarm threshold is set too low. % Someone is broadcasting pigmy packets and the router dosn't know how to deal with them. % The new frame relay network hasn't bedded down the software loop transmitter yet. % Fanout dropping voltage too much, try cutting some of those little traces % Plate voltage too low on demodulator tube % CPU needs bearings repacked % Too many little pins on CPU confusing it, bend back and forth until 10-20% are neatly removed. Do _not_ leave metal bits visible! % Software uses US measurements, but the OS is in metric... % The computer fletely, mouse and all. % Too much radiation coming from the soil. % Program load too heavy for processor to lift. % Processes running slowly due to weak power supply % Our ISP is having {switching,routing,SMDS,frame relay} problems % We've run out of licenses % Interference from lunar radiation % Standing room only on the bus. % You need to install an RTFM interface. % That would be because the software doesn't work. % That's easy to fix, but I can't be bothered. % Someone's tie is caught in the printer, and if anything else gets printed, he'll be in it too. % We're upgrading /dev/null % The Usenet news is out of date % Our POP server was kidnapped by a weasel. % It's stuck in the Web. % Your modem doesn't speak English. % The mouse escaped. % All of the packets are empty. % The UPS is on strike. % Neutrino overload on the nameserver % Melting hard drives % Someone has messed up the kernel pointers % The kernel license has expired % The cord jumped over and hit the power switch. % Bit rot % The Dilithium Cyrstals need to be rotated. % The static electricity routing is acting up... % Traceroute says that there is a routing problem in the backbone. It's not our problem. % The co-locator cannot verify the frame-relay gateway to the ISDN server. % Lawn mower blade in your fan need sharpening % Electrons on a bender % Telecommunications is upgrading. % Telecommunications is downgrading. % Telecommunications is downshifting. % Hard drive sleeping. Let it wake up on it's own... % Interference between the keyboard and the chair. % The CPU has shifted, and become decentralized. % Due to the CDA, we no longer have a root account. % We ran out of dial tone and we're and waiting for the phone company to deliver another bottle. % You must've hit the wrong anykey. % PCMCIA slave driver % The Token fell out of the ring. Call us when you find it. % The hardware bus needs a new token. % Too many interrupts % Not enough interrupts % The data on your hard drive is out of balance. % Digital Manipulator exceeding velocity parameters % appears to be a Slow/Narrow SCSI-0 Interface problem % microelectronic Riemannian curved-space fault in write-only file system % fractal radiation jamming the backbone % routing problems on the neural net % IRQ-problems with the Un-Interruptable-Power-Supply % CPU-angle has to be adjusted because of vibrations coming from the nearby road % emissions from GSM-phones % CD-ROM server needs recalibration % firewall needs cooling % asynchronous inode failure % transient bus protocol violation % incompatible bit-registration operators % your process is not ISO 9000 compliant % You need to upgrade your VESA local bus to a MasterCard local bus. % The recent proliferation of Nuclear Testing % Elves on strike. (Why do they call EMAG Elf Magic) % Internet exceeded Luser level, please wait until a luser logs off before attempting to log back on. % Your EMAIL is now being delivered by the USPS. % Your computer hasn't been returning all the bits it gets from the Internet. % You've been infected by the Telescoping Hubble virus. % Scheduled global CPU outage % processor has processed too many intructions. % packets were eaten by the terminator % The POP server is out of Coke % Fiber optics caused gas main leak % Server depressed, needs Prozak % quatnum decoherence % those damn racoons! % suboptimal routing experience % A plumber is needed, the network drain is clogged % 50% of the manual is in .pdf readme files % the AA battery in the wallclock sends magnetic interference % the xy axis in the trackball is coordinated with the summer soltice % the butane lighter causes the pincushioning % old inkjet cartridges emanate barium-based fumes % manager in the cable duct % HTTPD Error 666 : BOFH was here % HTTPD Error 4004 : very old Intel cpu - insufficient processing power % Network failure - call NBC % Having to manually track the satellite. % The rubber band broke % We're on Token Ring, and it looks like the token got loose. % Stray Alpha Particles from memory packaging caused Hard Memory Error on Server. % paradigm shift...without a clutch % PEBKAC (Problem Exists Between Keyboard And Chair) % The cables are not the same length. % Second-sytem effect. % Chewing gum on /dev/sd3c % Boredom in the Kernel. % struck by the Good Times virus % YOU HAVE AN I/O ERROR -> Incompetent Operator error % Your parity check is overdrawn and you're out of cache. % Plasma conduit breach % Out of cards on drive D: % Sand fleas eating the Internet cables % parallel processors running perpendicular today % ATM cell has no roaming feature turned on, notebooks can't connect % Webmasters kidnapped by evil cult. % Failure to adjust for daylight savings time. % Virus transmitted from computer to sysadmins. % Virus due to computers having unsafe sex. % Incorrectly configured static routes on the corerouters. % Forced to support NT servers; sysadmins quit. % Suspicious pointer corrupted virtual machine % Its the InterNIC's fault. % Root name servers corrupted. % Budget cuts forced us to sell all the power cords for the servers. % Someone hooked the twisted pair wires into the answering machine. % Operators killed by year 2000 bug bite. % We've picked COBOL as the language of choice. % Operators killed when huge stack of backup tapes fell over. % Robotic tape changer mistook operator's tie for a backup tape. % t's an ID-10-T error % Dyslexics retyping hosts file on servers % The Internet is being scanned for viruses. % Your computer's union contract is set to expire at midnight. % Bad user karma. % /dev/clue was linked to /dev/null % Increased sunspot activity. % It's union rules. There's nothing we can do about it. Sorry. % Interferance from the Van Allen Belt. % Jupiter is aligned with Mars. % Redundant ACLs. % Mail server hit by UniSpammer. % T-1's congested due to porn traffic to the news server. % Data for intranet got routed through the extranet and landed on the internet. % What you are experiencing is not a problem; it is an undocumented feature. % Secretary sent chain letter to all 5000 employees. % Sysadmin accidentally destroyed pager with a large hammer. % Bad cafeteria food landed all the sysadmins in the hospital. % Route flapping at the NAP. % Computers under water due to SYN flooding. % The vulcan-death-grip ping has been applied. % Electrical conduits in machine room are melting. % Traffic jam on the Information Superhighway. % Radial Telemetry Infiltration % Cow-tippers tipped a cow onto the server. % tachyon emissions overloading the system % Maintence window broken % Computer room being moved. Our systems are down for the weekend. % Sysadmins busy fighting SPAM. % Repeated reboots of the system failed to solve problem % Domain controler not responding % Someone stole your IP address, call the Internet detectives. % operation failed because: there is no message for this error (#1014) % stop bit received % internet is needed to catch the etherbunny % network down, IP packets delivered via UPS % Firmware update in the coffee machine % Mouse has out-of-cheese-error % Borg implants are failing % Borg nanites have infested the server % error: one bad user found in front of screen % Please state the nature of the technical emergency % Internet shut down due to maintainance % Daemon escaped from pentagram % crop circles in the corn shell % sticky bit has come loose % Hot Java has gone cold % Cache miss - please take better aim next time % Hash table has woodworm % Trojan horse ran out of hay % Zombie processess detected, machine is haunted. % overflow error in /dev/null % Browser's cookie is corrupted - someone's been nibbling on it. % Mailer-daemon is busy burning your message in hell. % vi needs to be upgraded to vii manderlbot-manderlbot-0.9.3/conf/config.xml000066400000000000000000000037771124273741000207320ustar00rootroot00000000000000 rejoin /etc/manderlbot/config.xml Hello world mute debian_pkg debian_file pyramid google wn jargon poh plic plic plic %R.T.F.M. %I do not like newbies %http://www.tuxedo.org/~esr/faqs/smart-questions.html %http://www.gnurou.org/documents/smart-questions-fr.html %http://michel.arboi.free.fr/humeur/nioubis.html %http://www.readthefuckingmanual.com /etc/manderlbot/bofh.fortune manderlbot-manderlbot-0.9.3/configure000077500000000000000000002251261124273741000177170ustar00rootroot00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.59 for manderlbot 0.9.3. # # Report bugs to . # # Copyright (C) 2003 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # Work around bugs in pre-3.0 UWIN ksh. $as_unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)$' \| \ . : '\(.\)' 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } /^X\/\(\/\/\)$/{ s//\1/; q; } /^X\/\(\/\).*/{ s//\1/; q; } s/.*/./; q'` # PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" || { # Find who we are. Look in the path if we contain no path at all # relative or not. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 { (exit 1); exit 1; }; } fi case $CONFIG_SHELL in '') as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for as_base in sh bash ksh sh5; do case $as_dir in /*) if ("$as_dir/$as_base" -c ' as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } CONFIG_SHELL=$as_dir/$as_base export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" ${1+"$@"} fi;; esac done done ;; esac # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line before each line; the second 'sed' does the real # work. The second script uses 'N' to pair each line-number line # with the numbered line, and appends trailing '-' during # substitution so that $LINENO is not a special case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) sed '=' <$as_myself | sed ' N s,$,-, : loop s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, t loop s,-$,, s,^['$as_cr_digits']*\n,, ' >$as_me.lineno && chmod +x $as_me.lineno || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensible to this). . ./$as_me.lineno # Exit status is that of the last command. exit } case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then # We could just check for DJGPP; but this test a) works b) is more generic # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). if test -f conf$$.exe; then # Don't use ln at all; we don't have any links as_ln_s='cp -p' else as_ln_s='ln -s' fi elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` exec 6>&1 # # Initializations. # ac_default_prefix=/usr/local ac_config_libobj_dir=. cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Maximum number of lines to put in a shell here document. # This variable seems obsolete. It should probably be removed, and # only ac_max_sed_lines should be used. : ${ac_max_here_lines=38} # Identity of this package. PACKAGE_NAME='manderlbot' PACKAGE_TARNAME='manderlbot' PACKAGE_VERSION='0.9.3' PACKAGE_STRING='manderlbot 0.9.3' PACKAGE_BUGREPORT='dev@manderlbot.org' ac_unique_file="src/manderlbot.erl" ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CONFIG_STATUS_DEPENDENCIES CONFIGURE_DEPENDENCIES SED ERLC ac_pt_ERLC ERL ac_pt_ERL ac_prefix_program ERLANG_XMERL_DIR ERLDIR DTD SET_MAKE LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. ac_init_help= ac_init_version=false # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datadir='${prefix}/share' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' libdir='${exec_prefix}/lib' includedir='${prefix}/include' oldincludedir='/usr/include' infodir='${prefix}/info' mandir='${prefix}/man' ac_prev= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval "$ac_prev=\$ac_option" ac_prev= continue fi ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_option in -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad | --data | --dat | --da) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ | --da=*) datadir=$ac_optarg ;; -disable-* | --disable-*) ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/-/_/g'` eval "enable_$ac_feature=no" ;; -enable-* | --enable-*) ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac eval "enable_$ac_feature='$ac_optarg'" ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst \ | --locals | --local | --loca | --loc | --lo) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* \ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package| sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac eval "with_$ac_package='$ac_optarg'" ;; -without-* | --without-*) ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/-/_/g'` eval "with_$ac_package=no" ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) { echo "$as_me: error: unrecognized option: $ac_option Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 { (exit 1); exit 1; }; } ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` eval "$ac_envvar='$ac_optarg'" export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` { echo "$as_me: error: missing argument to $ac_option" >&2 { (exit 1); exit 1; }; } fi # Be sure to have absolute paths. for ac_var in exec_prefix prefix do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* | NONE | '' ) ;; *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; };; esac done # Be sure to have absolute paths. for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ localstatedir libdir includedir oldincludedir infodir mandir do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* ) ;; *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; };; esac done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then its parent. ac_confdir=`(dirname "$0") 2>/dev/null || $as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$0" : 'X\(//\)[^/]' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$0" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` srcdir=$ac_confdir if test ! -r $srcdir/$ac_unique_file; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r $srcdir/$ac_unique_file; then if test "$ac_srcdir_defaulted" = yes; then { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 { (exit 1); exit 1; }; } else { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 { (exit 1); exit 1; }; } fi fi (cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 { (exit 1); exit 1; }; } srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` ac_env_build_alias_set=${build_alias+set} ac_env_build_alias_value=$build_alias ac_cv_env_build_alias_set=${build_alias+set} ac_cv_env_build_alias_value=$build_alias ac_env_host_alias_set=${host_alias+set} ac_env_host_alias_value=$host_alias ac_cv_env_host_alias_set=${host_alias+set} ac_cv_env_host_alias_value=$host_alias ac_env_target_alias_set=${target_alias+set} ac_env_target_alias_value=$target_alias ac_cv_env_target_alias_set=${target_alias+set} ac_cv_env_target_alias_value=$target_alias # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures manderlbot 0.9.3 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] _ACEOF cat <<_ACEOF Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --datadir=DIR read-only architecture-independent data [PREFIX/share] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --infodir=DIR info documentation [PREFIX/info] --mandir=DIR man documentation [PREFIX/man] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of manderlbot 0.9.3:";; esac cat <<\_ACEOF Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-erlang=PREFIX path to erlc and erl Report bugs to . _ACEOF fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. ac_popdir=`pwd` for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d $ac_dir || continue ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac cd $ac_dir # Check for guested configure; otherwise get Cygnus style configure. if test -f $ac_srcdir/configure.gnu; then echo $SHELL $ac_srcdir/configure.gnu --help=recursive elif test -f $ac_srcdir/configure; then echo $SHELL $ac_srcdir/configure --help=recursive elif test -f $ac_srcdir/configure.ac || test -f $ac_srcdir/configure.in; then echo $ac_configure --help else echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi cd $ac_popdir done fi test -n "$ac_init_help" && exit 0 if $ac_init_version; then cat <<\_ACEOF manderlbot configure 0.9.3 generated by GNU Autoconf 2.59 Copyright (C) 2003 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit 0 fi exec 5>config.log cat >&5 <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by manderlbot $as_me 0.9.3, which was generated by GNU Autoconf 2.59. Invocation command line was $ $0 $@ _ACEOF { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` hostinfo = `(hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. echo "PATH: $as_dir" done } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_sep= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; 2) ac_configure_args1="$ac_configure_args1 '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" # Get rid of the leading space. ac_sep=" " ;; esac done done $as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } $as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Be sure not to use single quotes in there, as some shells, # such as our DU 5.0 friend, will then `close' the trap. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, { (set) 2>&1 | case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in *ac_space=\ *) sed -n \ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" ;; *) sed -n \ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=$`echo $ac_var` echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------- ## ## Output files. ## ## ------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=$`echo $ac_var` echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo sed "/^$/d" confdefs.h | sort echo fi test "$ac_signal" != 0 && echo "$as_me: caught signal $ac_signal" echo "$as_me: exit $exit_status" } >&5 rm -f core *.core && rm -rf conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -rf conftest* confdefs.h # AIX cpp loses on an empty file, so make sure it contains at least a newline. echo >confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer explicitly selected file to automatically selected ones. if test -z "$CONFIG_SITE"; then if test "x$prefix" != xNONE; then CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" else CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi fi for ac_site_file in $CONFIG_SITE; do if test -r "$ac_site_file"; then { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in `(set) 2>&1 | sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val="\$ac_cv_env_${ac_var}_value" eval ac_new_val="\$ac_env_${ac_var}_value" case $ac_old_set,$ac_new_set in set,) { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 echo "$as_me: former value: $ac_old_val" >&2;} { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 echo "$as_me: current value: $ac_new_val" >&2;} ac_cache_corrupted=: fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 echo "$as_me: error: changes in the environment can compromise the build" >&2;} { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CONFIG_STATUS_DEPENDENCIES=vsn.mk CONFIGURE_DEPENDENCIES=vsn.mk # Extract the first word of "sed", so it can be a program name with args. set dummy sed; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_path_SED+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $SED in [\\/]* | ?:[\\/]*) ac_cv_path_SED="$SED" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_SED="$as_dir/$ac_word$ac_exec_ext" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done ;; esac fi SED=$ac_cv_path_SED if test -n "$SED"; then echo "$as_me:$LINENO: result: $SED" >&5 echo "${ECHO_T}$SED" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi # Check whether --with-erlang or --without-erlang was given. if test "${with_erlang+set}" = set; then withval="$with_erlang" fi; if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}erlc", so it can be a program name with args. set dummy ${ac_tool_prefix}erlc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_path_ERLC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $ERLC in [\\/]* | ?:[\\/]*) ac_cv_path_ERLC="$ERLC" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="$with_erlang:$with_erlang/bin:$PATH" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ERLC="$as_dir/$ac_word$ac_exec_ext" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done ;; esac fi ERLC=$ac_cv_path_ERLC if test -n "$ERLC"; then echo "$as_me:$LINENO: result: $ERLC" >&5 echo "${ECHO_T}$ERLC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_path_ERLC"; then ac_pt_ERLC=$ERLC # Extract the first word of "erlc", so it can be a program name with args. set dummy erlc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_path_ac_pt_ERLC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $ac_pt_ERLC in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_ERLC="$ac_pt_ERLC" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="$with_erlang:$with_erlang/bin:$PATH" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_ERLC="$as_dir/$ac_word$ac_exec_ext" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done ;; esac fi ac_pt_ERLC=$ac_cv_path_ac_pt_ERLC if test -n "$ac_pt_ERLC"; then echo "$as_me:$LINENO: result: $ac_pt_ERLC" >&5 echo "${ECHO_T}$ac_pt_ERLC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi ERLC=$ac_pt_ERLC else ERLC="$ac_cv_path_ERLC" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}erl", so it can be a program name with args. set dummy ${ac_tool_prefix}erl; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_path_ERL+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $ERL in [\\/]* | ?:[\\/]*) ac_cv_path_ERL="$ERL" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="$with_erlang:$with_erlang/bin:$PATH" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ERL="$as_dir/$ac_word$ac_exec_ext" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done ;; esac fi ERL=$ac_cv_path_ERL if test -n "$ERL"; then echo "$as_me:$LINENO: result: $ERL" >&5 echo "${ECHO_T}$ERL" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_path_ERL"; then ac_pt_ERL=$ERL # Extract the first word of "erl", so it can be a program name with args. set dummy erl; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_path_ac_pt_ERL+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $ac_pt_ERL in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_ERL="$ac_pt_ERL" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="$with_erlang:$with_erlang/bin:$PATH" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_ERL="$as_dir/$ac_word$ac_exec_ext" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done ;; esac fi ac_pt_ERL=$ac_cv_path_ac_pt_ERL if test -n "$ac_pt_ERL"; then echo "$as_me:$LINENO: result: $ac_pt_ERL" >&5 echo "${ECHO_T}$ac_pt_ERL" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi ERL=$ac_pt_ERL else ERL="$ac_cv_path_ERL" fi if test "z$ERLC" == "z" || test "z$ERL" == "z"; then { { echo "$as_me:$LINENO: error: erlang not found" >&5 echo "$as_me: error: erlang not found" >&2;} { (exit 1); exit 1; }; } fi ERLDIR=`echo "${ERL}" | sed 's/\/bin\/*erl.*//'` if test "x$prefix" = xNONE; then echo $ECHO_N "checking for prefix by $ECHO_C" >&6 # Extract the first word of "erl", so it can be a program name with args. set dummy erl; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_path_ac_prefix_program+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $ac_prefix_program in [\\/]* | ?:[\\/]*) ac_cv_path_ac_prefix_program="$ac_prefix_program" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_prefix_program="$as_dir/$ac_word$ac_exec_ext" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done ;; esac fi ac_prefix_program=$ac_cv_path_ac_prefix_program if test -n "$ac_prefix_program"; then echo "$as_me:$LINENO: result: $ac_prefix_program" >&5 echo "${ECHO_T}$ac_prefix_program" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi if test -n "$ac_prefix_program"; then prefix=`(dirname "$ac_prefix_program") 2>/dev/null || $as_expr X"$ac_prefix_program" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_prefix_program" : 'X\(//\)[^/]' \| \ X"$ac_prefix_program" : 'X\(//\)$' \| \ X"$ac_prefix_program" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_prefix_program" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` prefix=`(dirname "$prefix") 2>/dev/null || $as_expr X"$prefix" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$prefix" : 'X\(//\)[^/]' \| \ X"$prefix" : 'X\(//\)$' \| \ X"$prefix" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$prefix" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` fi fi echo "$as_me:$LINENO: checking xmerl.hrl" >&5 echo $ECHO_N "checking xmerl.hrl... $ECHO_C" >&6 cat >>conftest.erl <<_EOF -module(conftest). -author('nicolas@niclux.org'). -export([start/0]). start() -> case code:lib_dir("xmerl") of {error,bad_name} -> file:write_file("conftest.out", "notfound\n"); XMerlDirS -> file:write_file("conftest.out", XMerlDirS) end, halt(). _EOF if ! $ERLC conftest.erl; then { { echo "$as_me:$LINENO: error: could not compile sample program" >&5 echo "$as_me: error: could not compile sample program" >&2;} { (exit 1); exit 1; }; } fi if ! $ERL -s conftest -noshell ; then { { echo "$as_me:$LINENO: error: could not run sample program" >&5 echo "$as_me: error: could not run sample program" >&2;} { (exit 1); exit 1; }; } fi if ! test -f conftest.out; then { { echo "$as_me:$LINENO: error: erlang program was not properly executed, (conftest.out was not produced)" >&5 echo "$as_me: error: erlang program was not properly executed, (conftest.out was not produced)" >&2;} { (exit 1); exit 1; }; } fi ERLANG_XMERL_DIR=`head -1 < conftest.out` if test -f "$ERLANG_XMERL_DIR/inc/xmerl.hrl"; then ERLANG_XMERL_DIR="$ERLANG_XMERL_DIR/inc/" echo "$as_me:$LINENO: result: $ERLANG_XMERL_DIR" >&5 echo "${ECHO_T}$ERLANG_XMERL_DIR" >&6 elif test -f "$ERLANG_XMERL_DIR/include/xmerl.hrl"; then ERLANG_XMERL_DIR="$ERLANG_XMERL_DIR/include/" echo "$as_me:$LINENO: result: $ERLANG_XMERL_DIR" >&5 echo "${ECHO_T}$ERLANG_XMERL_DIR" >&6 else { { echo "$as_me:$LINENO: error: xmerl not found" >&5 echo "$as_me: error: xmerl not found" >&2;} { (exit 1); exit 1; }; } fi DTD=manderlbot.dtd echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'` if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.make <<\_ACEOF all: @echo 'ac_maketemp="$(MAKE)"' _ACEOF # GNU make sometimes prints "make[1]: Entering...", which would confuse us. eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` if test -n "$ac_maketemp"; then eval ac_cv_prog_make_${ac_make}_set=yes else eval ac_cv_prog_make_${ac_make}_set=no fi rm -f conftest.make fi if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 SET_MAKE= else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 SET_MAKE="MAKE=${MAKE-make}" fi # AC_PROG_INSTALL ac_config_files="$ac_config_files Makefile manderlbot.sh" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, don't put newlines in cache variables' values. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. { (set) 2>&1 | case `(ac_space=' '; set | grep ac_space) 2>&1` in *ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n \ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } | sed ' t clear : clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ : end' >>confcache if diff $cache_file confcache >/dev/null 2>&1; then :; else if test -w $cache_file; then test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" cat confcache >$cache_file else echo "not updating unwritable cache $cache_file" fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/; s/:*\${srcdir}:*/:/; s/:*@srcdir@:*/:/; s/^\([^=]*=[ ]*\):*/\1/; s/:*$//; s/^[^=]*=[ ]*$//; }' fi # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then we branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. cat >confdef2opt.sed <<\_ACEOF t clear : clear s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\),-D\1=\2,g t quote s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\),-D\1=\2,g t quote d : quote s,[ `~#$^&*(){}\\|;'"<>?],\\&,g s,\[,\\&,g s,\],\\&,g s,\$,$$,g p _ACEOF # We use echo to avoid assuming a particular line-breaking character. # The extra dot is to prevent the shell from consuming trailing # line-breaks from the sub-command output. A line-break within # single-quotes doesn't work because, if this script is created in a # platform that uses two characters for line-breaks (e.g., DOS), tr # would break. ac_LF_and_DOT=`echo; echo .` DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'` rm -f confdef2opt.sed ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_i=`echo "$ac_i" | sed 's/\$U\././;s/\.o$//;s/\.obj$//'` # 2. Add them. ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : ${CONFIG_STATUS=./config.status} ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 echo "$as_me: creating $CONFIG_STATUS" >&6;} cat >$CONFIG_STATUS <<_ACEOF #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # Work around bugs in pre-3.0 UWIN ksh. $as_unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)$' \| \ . : '\(.\)' 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } /^X\/\(\/\/\)$/{ s//\1/; q; } /^X\/\(\/\).*/{ s//\1/; q; } s/.*/./; q'` # PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" || { # Find who we are. Look in the path if we contain no path at all # relative or not. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} { (exit 1); exit 1; }; } fi case $CONFIG_SHELL in '') as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for as_base in sh bash ksh sh5; do case $as_dir in /*) if ("$as_dir/$as_base" -c ' as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } CONFIG_SHELL=$as_dir/$as_base export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" ${1+"$@"} fi;; esac done done ;; esac # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line before each line; the second 'sed' does the real # work. The second script uses 'N' to pair each line-number line # with the numbered line, and appends trailing '-' during # substitution so that $LINENO is not a special case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) sed '=' <$as_myself | sed ' N s,$,-, : loop s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, t loop s,-$,, s,^['$as_cr_digits']*\n,, ' >$as_me.lineno && chmod +x $as_me.lineno || { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensible to this). . ./$as_me.lineno # Exit status is that of the last command. exit } case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then # We could just check for DJGPP; but this test a) works b) is more generic # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). if test -f conf$$.exe; then # Don't use ln at all; we don't have any links as_ln_s='cp -p' else as_ln_s='ln -s' fi elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH exec 6>&1 # Open the log real soon, to keep \$[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. Logging --version etc. is OK. exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX } >&5 cat >&5 <<_CSEOF This file was extended by manderlbot $as_me 0.9.3, which was generated by GNU Autoconf 2.59. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ _CSEOF echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 echo >&5 _ACEOF # Files that config.status was made for. if test -n "$ac_config_files"; then echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS fi if test -n "$ac_config_headers"; then echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS fi if test -n "$ac_config_links"; then echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS fi if test -n "$ac_config_commands"; then echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS fi cat >>$CONFIG_STATUS <<\_ACEOF ac_cs_usage="\ \`$as_me' instantiates files from templates according to the current configuration. Usage: $0 [OPTIONS] [FILE]... -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ manderlbot config.status 0.9.3 configured by $0, generated by GNU Autoconf 2.59, with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2003 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." srcdir=$srcdir _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If no file are specified by the user, then we need to provide default # value. By we need to know if files were specified by the user. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "x$1" : 'x\([^=]*\)='` ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` ac_shift=: ;; -*) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; *) # This is not an option, so the user has probably given explicit # arguments. ac_option=$1 ac_need_defaults=false;; esac case $ac_option in # Handling of the options. _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --vers* | -V ) echo "$ac_cs_version"; exit 0 ;; --he | --h) # Conflict between --help and --header { { echo "$as_me:$LINENO: error: ambiguous option: $1 Try \`$0 --help' for more information." >&5 echo "$as_me: error: ambiguous option: $1 Try \`$0 --help' for more information." >&2;} { (exit 1); exit 1; }; };; --help | --hel | -h ) echo "$ac_cs_usage"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift CONFIG_FILES="$CONFIG_FILES $ac_optarg" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" ac_need_defaults=false;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 Try \`$0 --help' for more information." >&5 echo "$as_me: error: unrecognized option: $1 Try \`$0 --help' for more information." >&2;} { (exit 1); exit 1; }; } ;; *) ac_config_targets="$ac_config_targets $1" ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF if \$ac_cs_recheck; then echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF for ac_config_target in $ac_config_targets do case "$ac_config_target" in # Handling of arguments. "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; "manderlbot.sh" ) CONFIG_FILES="$CONFIG_FILES manderlbot.sh" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} { (exit 1); exit 1; }; };; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason to put it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Create a temporary directory, and hook for its removal unless debugging. $debug || { trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 trap '{ (exit 1); exit 1; }' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./confstat$$-$RANDOM (umask 077 && mkdir $tmp) } || { echo "$me: cannot create a temporary directory in ." >&2 { (exit 1); exit 1; } } _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # # CONFIG_FILES section. # # No need to generate the scripts if there are no CONFIG_FILES. # This happens for instance when ./config.status config.h if test -n "\$CONFIG_FILES"; then # Protect against being on the right side of a sed subst in config.status. sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF s,@SHELL@,$SHELL,;t t s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t s,@exec_prefix@,$exec_prefix,;t t s,@prefix@,$prefix,;t t s,@program_transform_name@,$program_transform_name,;t t s,@bindir@,$bindir,;t t s,@sbindir@,$sbindir,;t t s,@libexecdir@,$libexecdir,;t t s,@datadir@,$datadir,;t t s,@sysconfdir@,$sysconfdir,;t t s,@sharedstatedir@,$sharedstatedir,;t t s,@localstatedir@,$localstatedir,;t t s,@libdir@,$libdir,;t t s,@includedir@,$includedir,;t t s,@oldincludedir@,$oldincludedir,;t t s,@infodir@,$infodir,;t t s,@mandir@,$mandir,;t t s,@build_alias@,$build_alias,;t t s,@host_alias@,$host_alias,;t t s,@target_alias@,$target_alias,;t t s,@DEFS@,$DEFS,;t t s,@ECHO_C@,$ECHO_C,;t t s,@ECHO_N@,$ECHO_N,;t t s,@ECHO_T@,$ECHO_T,;t t s,@LIBS@,$LIBS,;t t s,@CONFIG_STATUS_DEPENDENCIES@,$CONFIG_STATUS_DEPENDENCIES,;t t s,@CONFIGURE_DEPENDENCIES@,$CONFIGURE_DEPENDENCIES,;t t s,@SED@,$SED,;t t s,@ERLC@,$ERLC,;t t s,@ac_pt_ERLC@,$ac_pt_ERLC,;t t s,@ERL@,$ERL,;t t s,@ac_pt_ERL@,$ac_pt_ERL,;t t s,@ac_prefix_program@,$ac_prefix_program,;t t s,@ERLANG_XMERL_DIR@,$ERLANG_XMERL_DIR,;t t s,@ERLDIR@,$ERLDIR,;t t s,@DTD@,$DTD,;t t s,@SET_MAKE@,$SET_MAKE,;t t s,@LIBOBJS@,$LIBOBJS,;t t s,@LTLIBOBJS@,$LTLIBOBJS,;t t CEOF _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # Split the substitutions into bite-sized pieces for seds with # small command number limits, like on Digital OSF/1 and HP-UX. ac_max_sed_lines=48 ac_sed_frag=1 # Number of current file. ac_beg=1 # First line for current file. ac_end=$ac_max_sed_lines # Line after last line for current file. ac_more_lines=: ac_sed_cmds= while $ac_more_lines; do if test $ac_beg -gt 1; then sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag else sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag fi if test ! -s $tmp/subs.frag; then ac_more_lines=false else # The purpose of the label and of the branching condition is to # speed up the sed processing (if there are no `@' at all, there # is no need to browse any of the substitutions). # These are the two extra sed commands mentioned above. (echo ':t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed if test -z "$ac_sed_cmds"; then ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" else ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" fi ac_sed_frag=`expr $ac_sed_frag + 1` ac_beg=$ac_end ac_end=`expr $ac_end + $ac_max_sed_lines` fi done if test -z "$ac_sed_cmds"; then ac_sed_cmds=cat fi fi # test -n "$CONFIG_FILES" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case $ac_file in - | *:- | *:-:* ) # input from stdin cat >$tmp/stdin ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; * ) ac_file_in=$ac_file.in ;; esac # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. ac_dir=`(dirname "$ac_file") 2>/dev/null || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p "$ac_dir" else as_dir="$ac_dir" as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac if test x"$ac_file" != x-; then { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} rm -f "$ac_file" fi # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ if test x"$ac_file" = x-; then configure_input= else configure_input="$ac_file. " fi configure_input=$configure_input"Generated from `echo $ac_file_in | sed 's,.*/,,'` by configure." # First look for the input files in the build tree, otherwise in the # src tree. ac_file_inputs=`IFS=: for f in $ac_file_in; do case $f in -) echo $tmp/stdin ;; [\\/$]*) # Absolute (can't be DOS-style, as IFS=:) test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } echo "$f";; *) # Relative if test -f "$f"; then # Build tree echo "$f" elif test -f "$srcdir/$f"; then # Source tree echo "$srcdir/$f" else # /dev/null tree { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } fi;; esac done` || { (exit 1); exit 1; } _ACEOF cat >>$CONFIG_STATUS <<_ACEOF sed "$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s,@configure_input@,$configure_input,;t t s,@srcdir@,$ac_srcdir,;t t s,@abs_srcdir@,$ac_abs_srcdir,;t t s,@top_srcdir@,$ac_top_srcdir,;t t s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t s,@builddir@,$ac_builddir,;t t s,@abs_builddir@,$ac_abs_builddir,;t t s,@top_builddir@,$ac_top_builddir,;t t s,@abs_top_builddir@,$ac_abs_top_builddir,;t t " $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out rm -f $tmp/stdin if test x"$ac_file" != x-; then mv $tmp/out $ac_file else cat $tmp/out rm -f $tmp/out fi done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF { (exit 0); exit 0; } _ACEOF chmod +x $CONFIG_STATUS ac_clean_files=$ac_clean_files_save # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || { (exit 1); exit 1; } fi manderlbot-manderlbot-0.9.3/configure.in000066400000000000000000000041131124273741000203100ustar00rootroot00000000000000DNA define([AC_CACHE_LOAD], )dnl dnl define([AC_CACHE_SAVE], )dnl AC_INIT([manderlbot], m4_normalize(m4_include([vsn.mk])),[dev@manderlbot.org]) AC_CONFIG_SRCDIR(src/manderlbot.erl) dnl AM_INIT_AUTOMAKE() AC_SUBST([CONFIG_STATUS_DEPENDENCIES],[vsn.mk]) AC_SUBST([CONFIGURE_DEPENDENCIES],[vsn.mk]) dnl work out who the cpu, vendor and OS are dnl AC_CANONICAL_SYSTEM dnl AC_DEFINE_UNQUOTED(CPU_VENDOR_OS, "$target") AC_PATH_PROG(SED, sed) AC_ARG_WITH(erlang, [ --with-erlang=PREFIX path to erlc and erl ]) AC_PATH_TOOL(ERLC, erlc, , $with_erlang:$with_erlang/bin:$PATH) AC_PATH_TOOL(ERL, erl, , $with_erlang:$with_erlang/bin:$PATH) if test "z$ERLC" == "z" || test "z$ERL" == "z"; then AC_MSG_ERROR([erlang not found]) fi ERLDIR=`echo "${ERL}" | sed 's/\/bin\/*erl.*//'` AC_PREFIX_PROGRAM(erl) dnl check for xmerl include path AC_MSG_CHECKING(xmerl.hrl) cat >>conftest.erl <<_EOF -module(conftest). -author('nicolas@niclux.org'). -export([[start/0]]). start() -> case code:lib_dir("xmerl") of {error,bad_name} -> file:write_file("conftest.out", "notfound\n"); XMerlDirS -> file:write_file("conftest.out", XMerlDirS) end, halt(). _EOF if ! $ERLC conftest.erl; then AC_MSG_ERROR([could not compile sample program]) fi if ! $ERL -s conftest -noshell ; then AC_MSG_ERROR([could not run sample program]) fi if ! test -f conftest.out; then AC_MSG_ERROR([erlang program was not properly executed, (conftest.out was not produced)]) fi ERLANG_XMERL_DIR=`head -1 < conftest.out` if test -f "$ERLANG_XMERL_DIR/inc/xmerl.hrl"; then ERLANG_XMERL_DIR="$ERLANG_XMERL_DIR/inc/" AC_MSG_RESULT($ERLANG_XMERL_DIR) elif test -f "$ERLANG_XMERL_DIR/include/xmerl.hrl"; then ERLANG_XMERL_DIR="$ERLANG_XMERL_DIR/include/" AC_MSG_RESULT($ERLANG_XMERL_DIR) else AC_MSG_ERROR([xmerl not found]) fi AC_SUBST(ERLANG_XMERL_DIR) AC_SUBST(SED) AC_SUBST(ERL) AC_SUBST(ERLC) AC_SUBST(ERLDIR) AC_SUBST(DTD,[manderlbot.dtd]) AC_PROG_MAKE_SET # AC_PROG_INSTALL AC_CONFIG_FILES([Makefile manderlbot.sh]) AC_OUTPUT manderlbot-manderlbot-0.9.3/debian/000077500000000000000000000000001124273741000172225ustar00rootroot00000000000000manderlbot-manderlbot-0.9.3/debian/changelog000066400000000000000000000014551124273741000211010ustar00rootroot00000000000000manderlbot (0.9.3-1) unstable; urgency=low * New upstream release -- Nicolas Niclausse Fri, 17 Mar 2006 12:39:54 +0100 manderlbot (0.9.2-1) unstable; urgency=low * New upstream release -- Julien Danjou Fri, 12 Dec 2003 14:39:54 +0100 manderlbot (0.9.1-1) unstable; urgency=low * New upstream release -- Julien Danjou Tue, 26 Aug 2003 16:48:40 +0200 manderlbot (0.9.0-1) unstable; urgency=low * New upstream release * License is now GPL with exception (Closes: #193571) * FTBFS fixed (Closes: #191897) -- Julien Danjou Fri, 22 Aug 2003 11:35:01 +0200 manderlbot (0.8.2-1) unstable; urgency=low * Initial Release. (Closes: #178047) -- Julien Danjou Thu, 23 Jan 2003 16:14:07 +0100 manderlbot-manderlbot-0.9.3/debian/control000066400000000000000000000012051124273741000206230ustar00rootroot00000000000000Source: manderlbot Section: net Priority: optional Maintainer: Julien Danjou Build-Depends-Indep: debhelper (>> 3.0.0), erlang, lyx, docbook-utils, hevea Standards-Version: 3.6.1.0 Package: manderlbot Architecture: all Depends: erlang (>= 9.2-1) Description: An IRC bot, written in erlang Manderlbot is an IRC bot with XML configuration file, allowing you to launch it on several servers and channels at once, each channel will have its own set of behaviours. . Behaviours are generics, and you can easily make your own set. If you want some not-already-implemented generic behaviour, you'll have to code some erlang ! manderlbot-manderlbot-0.9.3/debian/copyright000066400000000000000000000022351124273741000211570ustar00rootroot00000000000000This package was debianized by Julien Danjou on Thu, 23 Jan 2003 14:36:48 +0100. It was downloaded from http://manderlbot.tuxfamily.org Upstream Author: Dimitri Fontaine Copyright: Manderlbot is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Manderlbot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. See /usr/share/common-licenses/GPL In addition, as a special exception, you have the permission to link the code of this program with any library released under the EPL license and distribute linked combinations including the two. If you modify this file, you may extend this exception to your version of the file, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. manderlbot-manderlbot-0.9.3/debian/docs000066400000000000000000000000071124273741000200720ustar00rootroot00000000000000README manderlbot-manderlbot-0.9.3/debian/manderlbot.dirs000066400000000000000000000000401124273741000222260ustar00rootroot00000000000000etc/ usr/bin usr/lib/erlang/lib manderlbot-manderlbot-0.9.3/debian/rules000077500000000000000000000023471124273741000203100ustar00rootroot00000000000000#!/usr/bin/make -f # Sample debian/rules that uses debhelper. # GNU copyright 1997 to 1999 by Joey Hess. # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 # This is the debhelper compatibility version to use. export DH_COMPAT=3 configure: configure-stamp configure-stamp: dh_testdir # Add here commands to configure the package. ./configure touch configure-stamp build: build-stamp build-stamp: configure-stamp dh_testdir # Add here commands to compile the package. $(MAKE) touch build-stamp clean: dh_testdir dh_testroot rm -f build-stamp configure-stamp # Add here commands to clean up after the build process. -$(MAKE) clean dh_clean install: build dh_testdir dh_testroot #dh_clean -k dh_installdirs # Add here commands to install the package into debian/manderlbot. make install DESTDIR=$(CURDIR)/debian/manderlbot/ # Build architecture-independent files here. binary-indep: build install # We have nothing to do by default. dh_testdir dh_testroot dh_installdocs dh_installchangelogs dh_link dh_strip dh_compress dh_fixperms # dh_makeshlibs dh_installdeb # dh_perl dh_shlibdeps dh_gencontrol dh_md5sums dh_builddeb binary: binary-indep .PHONY: build clean binary-indep install configure manderlbot-manderlbot-0.9.3/doc/000077500000000000000000000000001124273741000165455ustar00rootroot00000000000000manderlbot-manderlbot-0.9.3/doc/Makefile000066400000000000000000000003521124273741000202050ustar00rootroot00000000000000# $Id$ MANPAGES = manderlbot.1 manderlbot.conf.5 all: man man: $(MANPAGES) %.1:%.1.sgml docbook2man $< >/dev/null 2>&1 %.5:%.5.sgml docbook2man $< >/dev/null 2>&1 clean: -rm -f *~ -rm -f manpage.links manpage.refs *.1 *.5 manderlbot-manderlbot-0.9.3/doc/manderlbot.1.sgml000066400000000000000000000052271124273741000217250ustar00rootroot00000000000000
dim@tuxfamily.org
Dimitri Fontaine Décembre 2003 2003 Dimitri Fontaine
manderlbot 1 manderlbot An erlang IRC bot manderlbot configuration file log file log level description manderlbot is an irc bot aimed at saying idioties or doing some little searches on the internet. It is not an eggdrop bot. The default config file can be found in /etc/manderlbot/config.xml. It can includes some fortune files, wich you can provide in the same directory. options specifies the configuration file to use. specifies the log file to use. specifies the log_level from wich you want manderlbot to log in the log_file. You can specify one of the following entries : Bugs There should be none... :) Authors manderlbot was written by Dimitri Fontaine dim@tuxfamily.org and Nicolas Niclausse nico@niclux.org. It is based on a earlier version made by Mickael Rémond and Thierry Mallard.
manderlbot-manderlbot-0.9.3/doc/manderlbot.conf.5.sgml000066400000000000000000000276321124273741000226610ustar00rootroot00000000000000
dim@tuxfamily.org
Dimitri Fontaine Avril 2004 2004 Dimitri Fontaine
manderlbot.conf 5 manderlbot.conf Configuring the manderlbot IRC robot. description manderlbot is an irc bot aimed at saying idioties or doing some little searches on the internet. It is not an eggdrop bot. Configuration The configuration file is an XML file containing the following elements: manderlbot the opening XML element of the configuration, it contains the properties name and controler. The name will be shown as the bot fullname, the controller property may contain one or more nicknames separated by spaces, only those people will then be allowed to operate on the running bot from irc channel. All the following sections, otherwise stated, are to be found under this one. dict is the section where to define the dictionnary server you may want to use. See dict.org for details about the protocol and servers. Be aware that you can run a dict server locally, and download some useful dictionnaries. The properties to define here are the dict server host, the port, and the default dictionnary to use. server allows you to define which servers manderlbot should connect to. The properties are host and port. You have to define a server section for each and every irc server you want manderlbot to connect to. channel section is where to configure the manderlbot behaviour and name. This section has to be embedded in the server one. You have to define a channel section per channel you want manderlbot to join on a server. The properties of channel section are name, the channel name, botname, the manderlbot nickname on that channel, and behaviours, a list of behaviours name you want to activate for that channel. behaviours will just contain your behaviour list behaviour have to be found under the behaviours section. You define here your behaviour, which properties are name, the name to use in the channel definition, the action, defining what will be done, and one or more of the followings pattern elements: pattern, op, to, option and from. You can even prefix those properties with exl_ to get an exclude pattern match (see ). This element contains data wich will be used as the action parameter, as explain in section [sub:Implemented-actions]. Behaviour matching So when you define a behaviour, you want manderlbot to react on some event on irc channel it is connected to, and take some action. Here we see how to define the event you want it to react to. As on irc all you do is sending lines of text, an event as to be text line oriented. So manderlbot configuration allows you to define some Regular Expressions to match the lines received. If the line is matched, the associated action is done. Please note the regexp are all considered case insensitive ones. You can define some regexp on the following parts of the received line (containing some server informations relative to IRC protocol): pattern will try to match the user input, that is what your ordinary irc client will show you op will try to match the irc operation, see the RFC for complete list (op can be kick or join for example) to irc protocol field, will probably contain the channel name, so you won't need that... option irc protocol option field from the nickname of the one who typed the current line, on the form nick!~user@host.domain.tld And in order to make it even more powerful and readable, you can define the same patterns with an 'exl_' prefix, this will prevent the action to being taken if it matches. So you can define the parameters exl_pattern, exl_op, exl_to, exl_option and exl_from. Of course, you can use any combination of the listed parameters, thus being quite precise on what you want to react to. Implemented actions The action parameter of the behaviour configuration element defines the manderlbot behaviour on matching a line. Here is a list of provided actions you can use. If you want manderlbot to take an action not described here, you will have to write some erlang code to teach him what you want! The argument of the action is the xml data given enclosed in the behaviour element. action send the given argument as if manderlbot had typed it after the /me irc command. answer send the line prefixed with the sender name and a colon. bloto this will count the matched lines per user, and first obtaining 5 points has won the business loto game. Just define your buzzwords set and make it a regexp! debian_file will search the irc given file using the debian web site cgi. The argument is not used. debian_pkg will search the irc given package using the debian web site cgi. The argument is not used. dict will ask your defined dict server for the given word. The argument may be the dictionnary name to use in the query, but defaults to the 'default' entry of the dict config element. google will ask google for the rest of the irc line. The argument is not used. mute mute will mute the bot, you have to be a controler to use that. The argument is not used. pyramid pyramid is a game named after a french TV game. You have to make guess a world to an irc fellow on that channel, in a given number or tries. The argument is not used. random will say one of the sentences listed in the arguments randomly. The sentences have to be separated by '%' signs. fortune same behaviour as random, but this time the argument is the name of a traditionnal separate fortune file. reconf will ask the bot to re-read its configuration. It allows you to handle dynamically your configuration, no need to restart the bot, and irc control! You have to be in the controler list to use this action. rejoin allows you te rejoin a channel (useful on kick, just add a op="kick" parameter to the behaviour element definition). say say will say the arguments. timer will say the first argument, then wait for a random time, and say the other arguments. The args have to be separated bu a '%' char. Interacting with the running bot, from irc You can use the reconf and mute actions to control the bot from irc, and you define who can do that in the first configuration element, with the controler property. Example Please see the given configuration file, in /etc/manderlbot/config.xml. History But why did we wrote this software ? Well, I wanted an irc bot to play with, in order to have it say some silly things automatically on answer to our own idioties. I did not want an eggdrop or whatever controlling channel bot. I saw that manderlbot project existing, was already familiar with erlang developpment, so I began using it. The existing project was on early stage of development, and I wanted the bot to do more and more things. So I wrote some code to make it fit my needs. As the original authors would not consider my patches, I forked the project, keeping the name (they seemed not to work on their version at all), and hosting it on the TuxFamily services. Authors manderlbot was written by Dimitri Fontaine dim@tuxfamily.org and Nicolas Niclausse nico@niclux.org.
manderlbot-manderlbot-0.9.3/inc/000077500000000000000000000000001124273741000165515ustar00rootroot00000000000000manderlbot-manderlbot-0.9.3/inc/config.hrl000066400000000000000000000021161124273741000205250ustar00rootroot00000000000000%%%---------------------------------------------------------------------- %%% File : config.hrl %%% Author : Dimitri Fontaine %%% Purpose : Define some config element as erlang structures %%% Created : 19 Feb 2002 by Dimitri Fontaine %%%---------------------------------------------------------------------- -author('dim@tuxfamily.org'). -define(arg_conffile, conf). -define(arg_logfile, log). -record(config, {name, % the name of the bot controler=[], % the nick of the one wich % controls the bot from irc dict={"localhost", "2628", "wn"}, servers=[], behaviours=[] }). -record(server, {host, port, passwd, channels = [] }). -record(channel, {name, botname, behaviours = [] }). %% The behavior as found in the config file %% With some patterns and some exclude patterns -record(cfg_behaviour, {name, action, from, to, op, option, pattern, exl_from, exl_to, exl_op, exl_option, exl_pattern, data = [] }). manderlbot-manderlbot-0.9.3/inc/irc.hrl000066400000000000000000000005621124273741000200400ustar00rootroot00000000000000%%% File : irc.hrl %%% Author : Dimitri Fontaine %%% Purpose : Define some irc related data structures %%% Created : 12 Nov 2002 by Dimitri Fontaine -author('dim@tuxfamily.org'). %% --- #tuxfamily ~fontaine dim.net1.nerim.net irc.localnet dim H :0 Dimitri -record(user, {login, from, nick, name}). manderlbot-manderlbot-0.9.3/inc/log.hrl000066400000000000000000000013371124273741000200450ustar00rootroot00000000000000%%% File : log.hrl %%% Author : Dimitri Fontaine %%% Description : Definitions for logger module (mdb_logger) %%% Created : 4 Nov 2003 by Dimitri Fontaine -record(log, {fd, level }). %% -define(EMERG, 0). % The system is unusable. -define(ALERT, 1). % Action should be taken immediately to address the problem. -define(CRIT, 2). % A critical condition has occurred. -define(ERR, 3). % An error has occurred. -define(WARN, 4). % A significant event that may require attention has occurred. -define(NOTICE,5). % An event that does not affect system operation has occurred. -define(INFO, 6). % An normal operation has occurred. -define(DEB, 7). % Debugging info manderlbot-manderlbot-0.9.3/inc/mdb.hrl000066400000000000000000000035171124273741000200300ustar00rootroot00000000000000%mdb.hrl -------------------------- %% Parameters to start a bot -record(params, {server="", port=0, password="", channel="", nickserv_password="", nickname="", realname=""}). %% ---------------------- %% Used to keep track of %% who is connecting to %% the channel -record(spy, {nickname="", user="", last_phrase_date={}, last_phrase="", join_date={}, quit_date={}, quit_reason=""}). %% ---------------------- %% Used by mdb_bot.erl %% Parsed incoming IRC data -define(nodata, '_'). -record(data, {body = ?nodata, header_from = ?nodata, header_op = ?nodata, header_to = ?nodata, header_options = ?nodata}). -define(TIME, 2000). -define(RNDTIME, 3000). %% Bot process state -record(state, {bot_pid = "", channel = "", nickname = "", realname = "", passwd = "", controler = "", socket = "", buffer = <<>>, behaviours = [], bot_state={}, date={}, host = "", port = "", joined = false, mode = unmuted % will either be muted or unmuted atom }). %% Behaviour description -record(behaviour, {id="", pattern, exclude_pattern, function, data}). %% ---------------------- %% Used by mdb_srv.erl %% Use to keep trace of the networks that we can connect to -record(network, {network_id=0, network_name="", server="", ip_port=0}). %% Use to keep track of running bots -record(bot, {bot_id, network_id, password, channel, nickserv_password, nickname, real_name, botpid, %% socket, date}). %% State of the server -record(srv_state, {networks=[], bots=[]}). -record(search_state, {requests = []}). -record(search_param, {server, port, type}). manderlbot-manderlbot-0.9.3/inc/mdb_macros.hrl000066400000000000000000000005631124273741000213720ustar00rootroot00000000000000%% Debugging macro %% If the macro debug is defined before including this file, %% the debug print-outs are enabled. -define(debug, true). -ifdef(debug). -define(dbg(Fmt, Args), ok=io:format("~p: " ++ Fmt ++ "~n", [?LINE|Args])). -define(trace, ok=io:format("<<~p:~p>>~n", [?MODULE, ?LINE])). -else. -define(dbg(Fmt, Args), no_debug). -define(trace, no_debug). -endif. manderlbot-manderlbot-0.9.3/manderlbot.sh.in000066400000000000000000000041441124273741000210730ustar00rootroot00000000000000#!/bin/bash # # This script allows to launch manderlbot and control it while running # # $Id$ INSTALL_DIR=@prefix@/lib/erlang/ ERL=@ERL@ VERSION=@PACKAGE_VERSION@ BOOT_SCRIPT="$INSTALL_DIR/lib/manderlbot-$VERSION/priv/manderlbot" COOKIE="-setcookie mdb" RUN_OPTIONS="-detached $COOKIE" MANDERLBOTPATH=$INSTALL_DIR/lib/manderlbot-$VERSION/ebin ERTS_RUN=`$ERL -version 2>&1 | tr -d '[A-Za-z] (),\f\n\r'` ERTS_BOOT=`grep erts $MANDERLBOTPATH/../priv/manderlbot.rel | tr -d 'a-z{}"" ,\n'` usage() { prog=`basename $1` echo "$prog start|stop|restart|status" } start() { echo "erl -sname manderlbot $RUN_OPTIONS -boot $BOOT_SCRIPT $CONF_OPT $LOG_OPT \ $LOG_LEVEL_OPT" $ERL -sname manderlbot -pa $MANDERLBOTPATH $RUN_OPTIONS -boot $BOOT_SCRIPT $CONF_OPT $LOG_OPT \ $LOG_LEVEL_OPT -boot_var MANDERLBOTPATH $INSTALL_DIR } stop() { $ERL -sname control $RUN_OPTIONS -s mdb_control stop \ -boot_var MANDERLBOTPATH $INSTALL_DIR } status() { pid=`ps -edaf | awk '/-[s]name manderlbot/ {print $2}'` if [ "zz$pid" != "zz" ]; then $ERL -sname control -noshell $COOKIE -s mdb_control status \ -boot_var MANDERLBOTPATH $INSTALL_DIR -pa $MANDERLBOTPATH echo $LOG_OPT echo $CONF_OPT else echo "manderlbot is not running" echo $LOG_OPT echo $CONF_OPT fi } checkversion() { if [ $ERTS_RUN != $ERTS_BOOT ] then echo "Erlang version has changed ! [$ERTS_BOOT] != [$ERTS_RUN]" echo "Must create new boot files (you may have to run this one time as root ! )" makebootfiles fi } makebootfiles() { cd $MANDERLBOTPATH/.. echo "creating boot file" $ERL -noshell -pa $MANDERLBOTPATH -s builder go -s init stop > /dev/null } while getopts ":c:l:f:" Option do case $Option in c) CONF_OPT="-manderlbot config_file \"$OPTARG\" ";; f) LOG_OPT="-manderlbot log_file \"$OPTARG\" ";; l) LOG_LEVEL_OPT="-manderlbot log_level '$OPTARG' ";; *) usage ;; esac done shift $(($OPTIND - 1)) case $1 in start) checkversion start;; stop) stop;; status) status;; restart) stop && start;; *) usage $0 esac manderlbot-manderlbot-0.9.3/priv/000077500000000000000000000000001124273741000167605ustar00rootroot00000000000000manderlbot-manderlbot-0.9.3/priv/builder.erl000066400000000000000000001321321124273741000211140ustar00rootroot00000000000000%%%---------------------------------------------------------------------- %%% File : builder.erl %%% Author : Mats Cronqvist %%% : Ulf Wiger %%% Purpose : Simplify build of OTP applications & boot scripts %%% Created : 2 Jan 2001 by Mats Cronqvist %%%---------------------------------------------------------------------- %%% @doc OTP release script builder. %%% %%%

This program compiles .rel, .script, .boot and sys.config files %%% for erlang applications. It supports incremental and recursive builds, %%% and is intended to be (much) easier and safer to use than doing it all %%% manually. This program does not generate beam code from Erlang source %%% files.

%%% %%%

The program makes some assumptions:

%%%
  • The application is store in a directory whose name is %%% composed with the name of the application '-' the version %%% number of the application (i.e. myapp-1.0)
  • %%%
  • The release and app file used in input are simplified subset %%% of the final Erlang release and app file. Some differences: %%% Versions are handled automatically; You do not need to add %%% the erts version tuple in the rel.src file; the application, %%% currently being built is mandatory in the list of apps in the %%% rel.src file; etc.
  • %%%
%%% %%%

The program (henceforth called 'builder') can be customized %%% using a number of options. The options are prioritized in %%% the following order: (1) those given as arguments to the %%% builder:go/1 function, those in the BUILD_OPTIONS %%% file, and (3) the hard-coded defaults.

%%% %%%

Valid options are

%%%
%%%
{app_dir, dirname()}
%%%
The application directory of the application being built. %%% The default value is Current Working Directory.
%%% %%%
{build_options, filename()}
%%%
A filename pointing to a BUILD_OPTIONS file. This is a file %%% containing erlang expressions, each terminated by "." -- just %%% like a file processed using file:eval/1. The last expression %%% in the file should result in a list of %%% {Key,Value} options. %%% If this option is not given, builder will look in [AppDir] and %%% [AppDir]/src for a file called BUILD_OPTIONS.
%%% Pre-bound variables are: %%%
    %%%
  • ScriptName : filename(), %%% the name of the script file.
  • %%%
%%%
{report, Level : atom()}
%%%
Specifies the reporting level. The following levels are recognized: %%% none, progress, verbose, debug.
%%% %%%
{out_dir, dirname()}
%%%
Specifies where [AppName].script, [AppName].boot, and sys.config %%% should be written. Default is [AppDir]/priv.
%%% %%%
{sys_config, filename()}
%%%
Specifies the location of the sys.config file. Default is %%% [OutDir]/sys.config.
%%% %%%
{rel_file, filename()}
%%%
Specifies which .rel file should be used as input for the %%% build process. Default is %%% [AppDir]/src/[AppName].rel.src.
%%% %%%
{rel_name, string()}
%%%
This option can be used if the release should be called something %%% other than [AppName] or whatever is in the %%% .rel file.
%%% %%%
{app_vsn, string()}
%%%
This option can be used to assign a version to the current %%% application. If the application directory has a version suffix, %%% the version suffix will override this option. If the directory %%% has no suffix, the default vsn will be "BLDR", unless 'app_vsn' %%% has been specified.
%%% %%%
{apps, [App : AppName | {AppName,Vsn} | {AppName,Vsn,EbinDir}]}
%%%
This is a way to identify which applications should be included %%% in the build. The way builder determines which applications should %%% be included is this:
    %%%
  • If there is a .rel.src file, the applications %%% listed in this file are included first, in the order in which %%% they are listed.
  • %%%
  • After this, all applications listed in the 'applications' %%% attribute of the .app.src file are added (if not %%% already listed), also in the order in which they are listed.
  • %%%
  • Then, all remaining applications in the 'apps' list are added %%% in order.
  • %%%
  • Finally, any included applications listed in the %%% .rel.src file, not already listed, are added. %%% (note that applications listed in 'included_applications' of %%% the .app.src file are not included here. The %%% .rel file can be used to override this definition, %%% so it would be an error to include it at this point.)
  • %%%
%%%
%%% %%%
{path, [PathExpr]}
%%%
Specifies the search path when locating applications. Default is %%% code:get_path(). PathExpr can contain wildcards, e.g. %%% "/OTP/lib/kernel*/ebin" (basically anything that %%% regexp:sh_to_awk/1 understands.)
%%% %%%
{skip, [ModuleName : atom()]}
%%%
Lists modules that should not be included in the generated .app %%% file for the current application. If not specified, builder will %%% locate all modules under [AppDir]/src, extract %%% their module names, and include these module names in the %%% 'modules' list of the .app file.
%%% %%%
{make_app, true | false | auto}
%%%
If true, builder will generate an .app file from an .app.src %%% file; if false, it will try to use an existing .app file; if %%% auto, it will build an .app file if no .app file exists %%% Default is 'auto'.
%%% %%%
{make_rel, true | false}
%%%
If true, builder will generate a .rel file from a .rel.src file; %%% if false, it will assume that there is a working .rel file. %%% Default: false if the rel_file option has been specified; true %%% otherwise.
%%% %%%
{make_boot, true | false}
%%%
If true, builder will run systools:make_script() %%% to generate .script and .boot files in [OutDir]. If false, it %%% will assume that there is a working .boot file. Default is true.
%%%
%%% %%%
{systools, Options : [Opt]}
%%%
If specified, Options will be passed to the %%% systools:make_script() command for building the %%% .boot script. Note that the 'path' option %%% is generated by builder. It cannot be overridden. %%% See erl -man systools for available options.
%%% %%%
{sh_script, auto | none}
%%%
If 'auto', builder will generate a small sh script %%% that makes it easier to start the system; If 'none', %%% no script will be generated. Default is 'none' on %%% non-UNIX systems and 'auto' on UNIX systems.
%%% %%%
{erl_opts, Opts : string()}
%%%
If specified, and if a sh_script is generated (see above), %%% Opts will be appended to the erl %%% command line. The builder will automatically put in options to %%% identify the boot script, sys.config, and possible boot variables.
%%% %%%
{config, Config : {file, filename()} | {M,F,A} | Data}
%%%
If present, this option should either point to a file that %%% contains a subset of data for a sys.config file (same format as %%% sys.config), or give a {M,F,A} tuple, where %%% apply(M,F,A) results in a list, %%% [{AppName, [{Key, Value}]}], or finally just specify %%% the data in place. The builder will look for similar config %%% directives in any BUILD_OPTIONS files of other applications that %%% are part of the build, and all inputs will be merged %%% into a common sys.config.
%%% %%%
{{config,OtherApp}, Config}
%%%
This is a way to specify environment variables for another %%% application in the build options. Config in this case %%% is the same as Config above. The difference between %%% this option and specifying environment variables for the other %%% application using the above option, is that with a simple %%% {config, ...} directive, builder will also check %%% for a similar directive in the other application, and all %%% different inputs will be merged. Using a {{config,App},...} %%% option, builder will not look into that application further.
%%% @end %%% ===================================================================== -module(builder). -author('mats.cronquist@etx.ericsson.se'). -author('ulf.wiger@ericsson.com'). -export([go/0, go/1, find_app/2]). -export([early_debug_on/0]). -compile(export_all). -include_lib("kernel/include/file.hrl"). -import(dict, [fetch/2]). -define(report(Level, Format, Args), case do_report(Level) of true -> io:format("[~p:~p] " ++ Format, [?MODULE,?LINE|Args]); false -> ok end). -define(f(D, Expr), fun(D) -> Expr end). -define(herewith(D), fun(D) -> ?report(debug, "herewith~n", []), D end). early_debug_on() -> put(builder_debug, true). go() -> go([]). go(Options) -> %% We use a dictionary for the options. The options are prioritized in %% the following order: (1) those given as arguments to the go/1 function, %% those in the BUILD_OPTIONS file, and (3) the hard-coded defaults. %% The options stored last in the dictionary take precedence, but since %% we want to allow for the Options list to guide us in finding the %% BUILD_OPTIONS file (under certain circumstances), we store the defaults %% and Options list in the dictionary, then locate and read the file, then %% store the Options list again. Dict0 = mk_dict(default_options() ++ Options), Dict = with(Dict0, [fun(D) -> read_options_file(D) end, ?herewith(D), % to help debugging fun(D) -> store_options(Options, D) end, ?herewith(D), fun(D) -> post_process_options(D) end, ?herewith(D), fun(D) -> {Path, [App, Vsn]} = get_app(D), store_options([{app_name, list_to_atom(App)}, {app_vsn, Vsn}], D) end, ?herewith(D), fun(D) -> [Descr, Id, Reg, Apps, Env, Mod, Phases] = read_app_file(D), Vsn = fetch(app_vsn, D), store_options([{app, [{vsn,Vsn}, Descr, Id, Reg, Apps, Env, Mod, Phases]}], D) end, ?herewith(D), fun(D) -> case dict:find(rel_name, D) of {ok,_} -> D; error -> RelName = atom_to_list( fetch(app_name, D)), dict:store(rel_name, RelName, D) end end, ?herewith(D), fun(D) -> RelFname = get_rel_filename(D), case file:consult(RelFname) of {ok, [{release,{_Name,_RelVsn}, _RelApps}= Rel]} -> ?report(debug,"rel_src = ~p~n",[Rel]), dict:store(rel_src,Rel, D); _ -> D end end, ?herewith(D), fun(D) -> AppInfo = find_apps(D), ?report(debug, "find_apps(D) -> ~p~n", [AppInfo]), dict:store(app_info, AppInfo, D) end, ?herewith(D), fun(D) -> BootVars = boot_vars(D), dict:store(boot_vars, BootVars, D) end]), case lists:member({ok,true}, [dict:find(make_boot,Dict), dict:find(make_rel,Dict), dict:find(make_config, Dict)]) of true -> verify_dir(fetch(out_dir,Dict)); false -> ok end, Dict1 = make_rel(Dict), make_app(Dict1), Res = make_boot(Dict1), make_config(Dict1), make_sh_script(Dict1), cleanup(Dict1), Res. find_app(App, Path) -> {Found,_} = expand_path(Path, [App], [], []), Found. post_process_options(Dict) -> D = with(Dict, [fun(D) -> case dict:find(out_dir, D) of {ok,_} -> D; error -> dict:store(out_dir, out_dir(D), D) end end, fun(D) -> case dict:find(rel_file, D) of {ok,_} -> dict:store(make_rel, false); error -> dict:store(make_rel, true, D) end end, fun(D) -> case dict:find(config, D) of {ok,_} -> dict:store(make_config, true, D); _ -> D end end, fun(D) -> case dict:find(make_boot, D) of {ok, _} -> D; error -> dict:store(make_boot, true, D) end end, fun(D) -> case dict:find(make_app, D) of {ok,_} -> D; error -> dict:store(make_app, auto, D) end end, fun(D) -> case dict:find(sh_script, D) of {ok, _} -> D; error -> case os:type() of {unix,_} -> dict:store(sh_script,auto,D); _ -> dict:store(sh_script,none,D) end end end, fun(D) -> case dict:find(systools, D) of {ok, _} -> D; error -> dict:store(systools, [], D) end end]), ?report(debug, "Options = ~p~n", [dict:to_list(D)]), D. with(Dict, Actions) -> lists:foldl(fun(F,D) -> F(D) end, Dict, Actions). cleanup(Dict) -> pop_report_level(). default_options() -> [{app_dir, cwd()}, {skip, []}, {path, code:get_path()}]. read_options_file(Dict) -> case dict:find(build_options, Dict) of {ok, BuildOptsF} -> case script(BuildOptsF) of {error, empty_script} -> %% We accept this Dict; {ok, Terms} -> ?report(debug, "Stored terms (~s) =~n ~p~n", [BuildOptsF, Terms]), store_options(Terms, Dict); {error, Reason} -> exit({bad_options_file, {BuildOptsF, Reason}}) end; error -> Path = case dict:find(app_dir, Dict) of {ok, AppDir} -> [AppDir, filename:join(AppDir, "src")]; error -> [".", "src"] end, case path_script(Path, "BUILD_OPTIONS") of {ok, Terms, Fullname} -> Dict1 = store_options(Terms, Dict), ?report(debug, "Stored terms (~s) =~n ~p~n", [Fullname, Terms]), Dict1; {error, enoent} -> Dict; Error -> exit({build_options, Error}) end end. mk_dict(Options) -> %% pust a unique ref onto the dictionary. This will allow us to %% redefine e.g. the report_level (for the same instance of %% the dictionary, and stack the same (for new instances of the %% dictionary -- recursive build.) store_options([{'#ref#', make_ref()}|Options], dict:new()). store_options(Options, Dict) -> ?report(debug, "store_options(~p)~n", [Options]), lists:foldl( fun({report, Level}, D) -> push_report_level(Level, D), dict:store(report, Level, D); ({Key,Value}, D) -> dict:store(Key,Value,D) end, Dict, Options). make_rel(Dict) -> case dict:find(make_rel, Dict) of {ok,true} -> ?report(debug, "will make rel~n", []), App = atom_to_list(fetch(app_name, Dict)), Vsn = fetch_key(vsn, fetch(app, Dict)), Apps = fetch(app_info, Dict), AppInfo = [{A,V} || {A,V,F} <- Apps], ?report(debug,"AppInfo = ~p~n", [AppInfo]), {RelName, Rel} = case dict:find(rel_src, Dict) of %% mremond: Added this case clause: %% Without it you get an error if you define %% the erts version in your release file subset. %% The ERTS version is anyway replace by the %% system ERTS {ok, {release,{Name,RelVsn}, {erts, ErtsVsn}, RelApps}} -> ?report(debug,"found rel_src: RelApps=~p~n", [RelApps]), {Name, {release, {Name,RelVsn}, {erts, get_erts_vsn()}, AppInfo}}; {ok, {release,{Name,RelVsn},RelApps}} -> %% here we should check that Apps is a subset of %% RelApps; if so, use RelApps; otherwise exit ?report(debug,"found rel_src: RelApps=~p~n", [RelApps]), {Name, {release, {Name,RelVsn}, {erts, get_erts_vsn()}, AppInfo}}; error -> {App, {release, {App, Vsn}, {erts, get_erts_vsn()}, AppInfo}} end, RelFileTarget = filename:join(fetch(out_dir,Dict), RelName ++ ".rel"), out(RelFileTarget, Rel), store_options([{rel_name, RelName}, {rel_file, RelFileTarget}], Dict); _ -> ?report(debug, "will NOT make rel~n", []), Dict end. make_config(Dict) -> AppInfo = fetch(app_info, Dict), AppName = fetch(app_name, Dict), ForeignData = lists:foldl( fun({A,V,Ebin}, Acc) when A =/= AppName -> Acc ++ try_get_config(A,Ebin,Dict); (_, Acc) -> Acc end, [], AppInfo), Data = case dict:find(config, Dict) of {ok, Type} -> get_config_data(Type); error -> [] end, merge_config(Data ++ ForeignData, Dict). try_get_config(AppName, Ebin, Dict) -> case dict:find({config, AppName}, Dict) of {ok, Type} -> get_config_data(Type); error -> BuildOpts = filename:join( filename:join(filename:dirname(Ebin), "src"), "BUILD_OPTIONS"), case script(BuildOpts) of {error, enoent} -> []; {ok, Result} -> ?report(debug, "script(~p) ->~n ~p~n", [BuildOpts, Result]), case lists:keysearch(config, 1, Result) of {value, {_, Type}} -> get_config_data(Type); false -> [] end end end. get_config_data({file,F}) -> ?report(debug, "get_config_data({file, ~p})~n", [F]), case file:consult(F) of {ok, [Terms]} when list(Terms) -> Terms; {error, Reason} -> exit({config, {F, Reason}}) end; get_config_data({M,F,A}) -> ?report(debug, "get_config_data(~p)~n", [{M,F,A}]), apply(M,F,A); get_config_data(Data) when list(Data) -> Data. merge_config([], Dict) -> ok; merge_config(Data, Dict) -> ConfigF = sys_config(Dict), case file:consult(ConfigF) of {error, enoent} -> out(ConfigF, Data); {ok, [Terms]} -> ?report(debug, "merging terms (~p,~p), F = ~p~n", [Data,Terms, ConfigF]), NewData = merge_terms(Data, Terms), out(ConfigF, NewData) end. merge_terms([{App,Vars}|Data], Old) -> case lists:keysearch(App, 1, Old) of false -> merge_terms(Data, Old ++ [{App,Vars}]); {value, {_, OldVars}} -> ?report(debug, "merging vars (~p,~p) for ~p~n", [Vars,OldVars, App]), NewVars = merge_vars(Vars, OldVars, App), merge_terms(Data, lists:keyreplace(App,1,Old,{App,NewVars})) end; merge_terms([], Data) -> Data. merge_vars([{Key,Vals}|Data], Old, App) -> case lists:keysearch(Key, 1, Old) of {value, {_, OldVals}} when OldVals =/= Vals -> exit({config_conflict, {App, Key}}); {value, {_, OldVals}} when OldVals == Vals -> merge_vars(Data, Old, App); false -> merge_vars(Data, Old ++ [{Key,Vals}], App) end; merge_vars([], Data, _App) -> Data. fetch_key(Key, L) -> {value, {_, Value}} = lists:keysearch(Key, 1, L), Value. make_app(Dict) -> case dict:find(make_app, Dict) of {ok,true} -> do_make_app(Dict); {ok,auto} -> AppName = fetch(app_name, Dict), AppF = filename:join(ebin_dir(Dict), atom_to_list(AppName) ++ ".app"), case file:read_file_info(AppF) of {ok, _} -> ok; {error, enoent} -> do_make_app(AppF, AppName, Dict) end; _ -> ok end. do_make_app(Dict) -> AppName = fetch(app_name, Dict), AppF = filename:join(ebin_dir(Dict), atom_to_list(AppName) ++ ".app"), do_make_app(AppF, AppName, Dict). do_make_app(AppF, AppName, Dict) -> [Vsn, Descr, Id, Reg, Apps, Env, Mod, Phases] = fetch(app, Dict), Modules = modules(Dict), Remove = case {Mod, Phases} of {{_,[]},{_,undefined}} -> [Mod, Phases]; {{_,{_,_}},{_,undefined}} -> [Phases]; {{_,[]}, {_,_}} -> [Mod]; _ -> [] end, Options = [Vsn, Descr, Id, Modules, Reg, Apps, Env, Mod, Phases] -- Remove, out(AppF, {application, AppName, Options}). make_boot(Dict) -> case dict:find(make_boot, Dict) of {ok,true} -> ensure_rel_file(Dict), App = fetch(app_name, Dict), CWD = cwd(), ok = file:set_cwd(fetch(out_dir,Dict)), SystoolsOpts0 = merge_opts([{path, systools_path(Dict)}], fetch(systools, Dict)), SystoolsOpts = maybe_local(SystoolsOpts0, Dict), ?report(debug, "SystoolsOpts = ~p~n", [SystoolsOpts]), RelName = fetch(rel_name, Dict), Res = systools:make_script(RelName, SystoolsOpts), ?report(progress, "systools:make_script() -> ~p~n", [Res]), make_load_script(RelName), ok = file:set_cwd(CWD), case Res of error -> exit(error_in_make_script); ok -> ok end; _ -> ok end. maybe_local(Opts, Dict) -> case lists:keymember(variables, 1, Opts) of true -> Opts; false -> [local|Opts -- [local]] end. make_load_script(RelName) -> {ok, Bin} = file:read_file(RelName ++ ".boot"), {script,Id,Cmds} = binary_to_term(Bin), Keep = lists:filter( fun({apply,{application,start_boot,[kernel,Type]}}) -> true; ({apply,{application,start_boot,[stdlib,Type]}}) -> true; ({apply,{application,start_boot,[sasl,Type]}}) -> true; ({apply,{application,start_boot,[_,Type]}}) -> false; (_) -> true end, Cmds), NewScript = {script,Id,Keep}, file:write_file(RelName ++ "_load.boot", term_to_binary(NewScript)), out(RelName ++ "_load.script", NewScript). boot_vars(Dict) -> case dict:find(systools, Dict) of {ok, Opts} when Opts =/= [] -> ?report(debug, "systools opts = ~p~n", [Opts]), case lists:keysearch(variables, 1, Opts) of {value, {_, Vars}} -> Vars; false -> [] end; _ -> ?report(debug,"will make boot_vars~n", []), {ok,[[Root]]} = init:get_argument(root), Apps = dict:fetch(app_info, Dict), prefixes(Apps, [{"ROOT",Root}]) end. prefixes([{A,_,D}|Apps], Prefixes) -> case [P || {_,P} <- Prefixes, lists:prefix(P, D)] of [] -> prefixes(Apps, guess_root(D, Prefixes)); [_|_] -> prefixes(Apps, Prefixes) end; prefixes([], Prefixes) -> Prefixes. guess_root(D, Pfxs) -> case lists:reverse(filename:split(D)) of ["ebin",App,"lib",Dir|T] -> guess(to_upper(Dir), 0, filename:join(lists:reverse([Dir|T])), Pfxs); ["ebin",App,Dir|T] -> guess(to_upper(Dir), 0, filename:join(lists:reverse([Dir|T])), Pfxs) end. guess(Guess,N,RootDir, Pfxs) -> case lists:keymember(Guess,1,Pfxs) of false -> ?report(debug, "manufactured boot_var {~p,~p}~n", [Guess,RootDir]), [{Guess,RootDir}|Pfxs]; true -> ?report(debug, "duplicate Guess = ~p~n", [Guess]), guess(increment(Guess,N), N+1, RootDir, Pfxs) end. increment(Guess,0) -> Guess ++ "-1"; increment(Guess,N) when N < 10 -> [_,$-|T] = lists:reverse(Guess), lists:reverse(T) ++ [$-|integer_to_list(N+1)]. to_upper([H|T]) when H >= $a, H =< $z -> [$A+(H-$a)|to_upper(T)]; to_upper([H|T]) -> [H|T]; to_upper([]) -> []. make_sh_script(Dict) -> case dict:find(sh_script, Dict) of {ok, auto} -> OutDir = fetch(out_dir, Dict), RelName = fetch(rel_name, Dict), StartF = filename:join(OutDir, RelName ++ ".start"), LoadF = filename:join(OutDir, RelName ++ ".load"), do_make_sh_script(StartF,start,Dict), do_make_sh_script(LoadF,load,Dict); _ -> ok end. do_make_sh_script(ScriptF, Type, Dict) -> ok = file:write_file(ScriptF, list_to_binary(sh_script(Type,Dict))), {ok,FI} = file:read_file_info(ScriptF), Mode = FI#file_info.mode bor 8#00100, ok = file:write_file_info(ScriptF, FI#file_info{mode = Mode}). sh_script(Mode,Dict) -> OutDir = fetch(out_dir, Dict), AppDir = fetch(app_dir, Dict), XOpts = case dict:find(erl_opts, Dict) of {ok, Opts} -> [" ", Opts]; error -> "" end, %% mremond: The path it need to be sure the script is predictible % Path = [" -pa ", filename:join(AppDir, "ebin")], RelName = fetch(rel_name, Dict), Boot = case Mode of start -> [" -boot ", filename:join(OutDir, RelName)]; load -> [" -boot ", filename:join(OutDir, RelName++"_load")] end, Sys = case dict:find(make_config, Dict) of {ok, true} -> [" -config ", filename:join(OutDir, "sys")]; _ -> [] end, BootVars = [[" -boot_var ", Var, " ", Dir] || {Var,Dir} <- dict:fetch(boot_vars, Dict)], % ["#/bin/sh\n" % "erl ", Path, Boot, Sys, BootVars, XOpts, "\n"]. ["#/bin/sh\n" "erl ", Boot, Sys, BootVars, XOpts, "\n"]. ensure_rel_file(Dict) -> OutDir = fetch(out_dir, Dict), case dict:find(rel_file, Dict) of {ok, F} -> case filename:dirname(F) of D when D == OutDir -> ok; _ -> %% This doesn't necessarily mean that it's not there RelName = fetch(rel_name, Dict), {ok, [{release, {N,Vsn}, Erts, Apps}]} = file:consult(F), RelF = filename:join(OutDir, fetch(rel_name,Dict) ++ ".rel"), out(RelF, {release, {RelName,Vsn}, Erts, Apps}) end; error -> exit(no_rel_file) end. systools_path(Dict) -> AppInfo = fetch(app_info, Dict), [D || {_A,_V,D} <- AppInfo]. merge_opts(Opts, [{path,P}|Opts2]) -> exit({not_allowed, {systools, {path,P}}}); merge_opts(Opts, [Opt|Opts2]) -> [Opt|merge_opts(Opts, Opts2)]; merge_opts(Opts, []) -> Opts. cwd() -> {ok, CWD} = file:get_cwd(), CWD. out_dir(Dict) -> case dict:find(out_dir, Dict) of {ok, OutDir} -> OutDir; error -> filename:join(fetch(app_dir,Dict), "priv") end. ebin_dir(Dict) -> AppDir = fetch(app_dir, Dict), filename:join(AppDir, "ebin"). sys_config(Dict) -> case dict:find(sys_config, Dict) of {ok, Filename} -> Filename; error -> filename:join(fetch(out_dir,Dict), "sys.config") end. get_app(Dict) -> AppDir = fetch(app_dir, Dict), %% mremond: The program was crashing when the directory where not %% containing the application version %% Now we assume that version number is "BLDR" by default. case string:tokens(hd(lists:reverse(string:tokens(AppDir, "/"))), "-") of [App, Vsn] -> {AppDir, [App, Vsn]}; [App] -> case dict:find(app_vsn, Dict) of {ok, Vsn} -> {AppDir, [App, Vsn]}; error -> {AppDir, [App, "BLDR"]} end end. get_app_filename(App, Dict) -> AppDir = fetch(app_dir, Dict), filename:join([AppDir, "src", App++".app.src"]). get_rel_filename(Dict) -> App = atom_to_list(dict:fetch(app_name, Dict)), AppDir = fetch(app_dir, Dict), filename:join([AppDir, "src", App++".rel.src"]). modules(Dict) -> Ebin = ebin_dir(Dict), Ext = code:objfile_extension(), L = recursive_list_dir(Ebin), ?report(debug, "L = ~p~n", [L]), Skip = fetch(skip, Dict), ?report(debug, "Skip = ~p~n", [Skip]), Modules = lists:foldr( fun(F, Acc) -> case make_mod(F) of {ok, M} -> [M|Acc]; error -> Acc end end, [], [F || F <- L, check_f(F, Ext)]), {modules, Modules -- Skip}. recursive_list_dir(Dir) -> {ok, Fs} = file:list_dir(Dir), lists:concat([f_expand(F,Dir) || F <- Fs]). f_expand(Name,Dir) -> Fname = filename:join(Dir,Name), case file:read_file_info(Fname) of {ok, #file_info{type=regular}} -> [Fname]; {ok, #file_info{type=directory}} -> ?report(debug, "~p is a directory under ~p~n", [Fname, Dir]), {ok, Fs} = file:list_dir(Fname), lists:concat([f_expand(F,Fname) || F <- Fs]); {ok, Finfo} -> ?report(debug, "~p not a directory or a regular file. Ignoring~n", [Fname]), []; {error, Reason} -> ?report(error, "*** read_file_info(~p) -> {error, ~p}~n", [Fname, Reason]), [] end. make_mod(F) -> case beam_lib:version(F) of {ok, {Module, Vsn}} -> {ok, Module}; _ -> error end. % {ok,Fd} = file:open(F, [read]), % parse_for_mod(Fd, F). % {ok,Bin} = file:read_file(F), % Text = binary_to_list(Bin), % {match,Start,Len} = % regexp:first_match(Text, % "^[ ]*-[ ]*module[ ]*[(][ ]*.*[ ]*[)][ ]*\."), % Name = case string:substr(Text, Start+8,Len-10) of % "'" ++ Quoted -> % "'" ++ Rest = lists:reverse(Quoted), % list_to_atom(lists:reverse(Rest)); % Str -> % list_to_atom(Str) % end. parse_for_mod(Fd, F) -> parse_for_mod(Fd, io:parse_erl_exprs(Fd,''), F). parse_for_mod(Fd, {ok,[{op,_,'-',{call,_,{atom,_,module},[Mod]}}],_}, F) -> {ok,parse_mod_expr(Mod)}; % parse_for_mod(Fd, {ok,[{op,_,'-', % {call,_,{atom,_,module},[{atom,_,Mod}]}}],_}, F) -> % {ok,Mod}; parse_for_mod(Fd, {ok,_,_}, F) -> parse_for_mod(Fd, io:parse_erl_exprs(Fd,''), F); parse_for_mod(Fd, {error,_,_}=Error, F) -> io:format("*** Error parsing ~s: ~p~n", [F, Error]), error; parse_for_mod(Fd, {eof,_}, F) -> io:format("*** No module attribute found in ~s~n", [F]), error. parse_mod_expr(Expr) -> list_to_atom(parse_mod_expr1(Expr)). parse_mod_expr1({atom,_,A}) -> atom_to_list(A); parse_mod_expr1({record_field,_,R,{atom,_,A}}) -> parse_mod_expr1(R) ++ "." ++ atom_to_list(A). check_f(F, Ext) -> case regexp:match(F, ".*"++Ext++"\$") of {match, _, _} -> true; _ -> false end. find_apps(Dict) -> App = fetch(app, Dict), {value, {_, NeededApps}} = lists:keysearch(applications, 1, App), AppInfo = case dict:find(apps, Dict) of {ok, As} -> app_info(As, Dict); error -> [] end, RelApps = case dict:find(rel_src, Dict) of {ok, {release, _, RA}} -> RA; error -> [] end, AppName = dict:fetch(app_name, Dict), Apps = merge_apps(RelApps, NeededApps, AppInfo) -- [AppName], ?report(debug, "Apps = ~p~n", [Apps]), KnownApps = [{A,V,D} || {A,V,D} <- AppInfo, V =/= unknown, D =/= unknown], search_apps(Apps, Dict, AppInfo, KnownApps). merge_apps(RelApps, AppApps, AppInfo) -> ?report(debug, "merge_apps(~p, ~p, ~p)~n", [RelApps, AppApps, AppInfo]), Acc0 = lists:map(fun({App,Vsn,Incl}) -> App; ({App,Vsn}) -> App; (App) when atom(App) -> App end, RelApps), with(Acc0, [fun(Acc) -> Acc ++ [A || {A,_,_} <- AppInfo, not(lists:member(A, Acc))] end, fun(Acc) -> Acc ++ [A || A <- AppApps, not(lists:member(A, Acc))] end, fun(Acc) -> InclApps = lists:foldl( fun({_,_,Incls}, AccX) -> AccX ++ Incls; (_, AccX) -> AccX end, [], RelApps), Acc ++ [A || A <- InclApps, not(lists:member(A, Acc))] end]). app_info(Apps, Dict) -> MyName = dict:fetch(app_name, Dict), MyVsn = dict:fetch(app_vsn, Dict), MyEbin = ebin_dir(Dict), Info = lists:map( fun(A) when atom(A) -> {A,unknown,unknown}; ({A,V}) -> {A,V,unknown}; ({A,V,D}) -> {A,V,D} end, Apps), AppName = dict:fetch(app_name, Dict), case lists:keysearch(AppName, 1, Info) of {value, {Ai,Vi,Di}} -> [Version,Dir] = lists:foldr( fun({unknown,Vx}, Acc) -> [Vx|Acc]; ({Vx,Vx}, Acc) -> [Vx|Acc]; ({V1,V2},_) -> exit({conflicting_info_in_apps, {{Ai,Vi,Di}, {MyName,MyVsn,MyEbin}}}) end, [], [{Vi,MyVsn},{Di,MyEbin}]), lists:keyreplace(AppName, 1, Info, {AppName, Version, Dir}); false -> Info ++ [{AppName, dict:fetch(app_vsn, Dict), ebin_dir(Dict)}] end. search_apps(Apps, Dict, AppInfo, InitAcc) -> ?report(debug,"search_apps(~p,Dict,~p,~p)~n", [Apps,AppInfo,InitAcc]), Path = fetch(path, Dict), Ebin = ebin_dir(Dict), Path1 = Path ++ [Ebin], MyAppName = dict:fetch(app_name, Dict), MyApp = {MyAppName, dict:fetch(app_vsn,Dict), ebin_dir(Dict)}, ?report(debug, "Search Path = ~p~n", [Path1]), Found = case expand_path(Path ++ [Ebin], Apps, AppInfo, InitAcc) of {FoundInfo, []} -> ?report(debug, "LeftApps = [], FoundInfo = ~p~n", [FoundInfo]), check_found(FoundInfo, Dict); {FoundInfo, LeftApps} -> %% LeftApps may still include applications for which we've %% found versions (but didn't know if they were the right ones) ?report(debug, "LeftApps = ~p,~nFoundInfo = ~p~n", [LeftApps, FoundInfo]), case [A || A <- LeftApps, not(lists:keymember(A, 1, FoundInfo))] of [] -> check_found(FoundInfo, Dict); NotFound -> exit({not_found, NotFound}) end end, replaceadd(MyAppName,1,Found,MyApp). check_found(FoundInfo, Dict) -> case lists:foldr( fun({A,unknown,D}, {Found,Left}) -> AppF = filename:join(D,atom_to_list(A) ++ ".app"), case vsn_from_app_file(AppF) of unknown -> {Found,[{A,unknown,D}|Left]}; FoundVsn -> {[{A,FoundVsn,D}|Found], Left} end; (GoodApp, {Found,Left}) -> {[GoodApp|Found], Left} end, {[],[]}, FoundInfo) of {Found, []} -> ?report(debug, "Found apps:~n ~p~n", [FoundInfo]), Found; {Found, UnknownVsns} -> %% These app directories didn't have a version %% suffix. This is allowed, but we must then %% extract the version some other way.... FFS ?report(debug, "Should find the versions of" " these apps:~n ~p~n", [UnknownVsns]), Found end. replaceadd(Key,Pos,[H|T],Obj) when element(Pos,H) == Key -> [Obj|T]; replaceadd(Key,Pos,[H|T],Obj) -> [H|replaceadd(Key,Pos,T,Obj)]; replaceadd(Key,Pos,[],Obj) -> [Obj]. vsn_from_app_file(AppF) -> case file:consult(AppF) of {ok, [{application,_,Opts}]} -> case lists:keysearch(vsn,1,Opts) of {value,{_,Vsn}} -> Vsn; false -> unknown end; Other -> ?report(debug, "file:consult(~p) -> ~p~n", [AppF,Other]), unknown end. %%% expand_path/2 takes a list of path expressions, where each expression %%% may contain wildcards (sh expressions) expand_path([Dir|Ds], Apps, AppInfo, Acc) -> ?report(debug, "Dir = ~p~n", [Dir]), SplitDir = filename:split(Dir), case file:read_file_info(Dir) of {ok, #file_info{type = directory}} -> case lists:reverse(SplitDir) of ["ebin",AppDir|_] -> case string:tokens(AppDir, "-") of [App,Vsn] -> ?report(debug, "App = ~p, Vsn = ~p~n", [App,Vsn]), AppA = list_to_atom(App), {Acc1,Apps1} = case lists:member(AppA, Apps) of true -> maybe_save_app(AppA, Vsn, Dir, Apps, AppInfo, Acc); false -> {Acc, Apps} end, expand_path(Ds, Apps1, AppInfo, Acc1); [App] -> %% App dir without version suffix -- legal, %% but we must extract the version somehow AppA = list_to_atom(App), AppF = filename:join(Dir, App ++ ".app"), Vsn = vsn_from_app_file(AppF), case lists:member(AppA, Apps) of true -> {Acc1,Apps1} = maybe_save_app(AppA, Vsn, Dir, Apps, AppInfo, Acc), expand_path(Ds, Apps1, AppInfo, Acc1); false -> expand_path(Ds, Apps, AppInfo, Acc) end; Other -> ?report(debug, "*** strange app dir ~p~n", [AppDir]), expand_path(Ds, Apps, AppInfo, Acc) end; _ -> expand_path(Ds, Apps, AppInfo, Acc) end; {error, enoent} -> %% assume it is a regexp {Acc1, RestApps} = expand_path( d_expand(SplitDir), Apps, AppInfo, Acc), expand_path(Ds, RestApps, AppInfo, Acc1); _ -> %% something else -- ignore expand_path(Ds, Apps, AppInfo, Acc) end; expand_path([], Apps, AppInfo, Acc) -> {Acc, Apps}. maybe_save_app(AppA, Vsn, Dir, Apps, AppInfo, Acc) -> ?report(debug, ("maybe_save_app(~p,~p,~p,_,~n" " ~p,~n" " ~p)~n"), [AppA,Vsn,Dir,AppInfo, Acc]), case lists:keysearch(AppA, 1, Acc) of {value, {_,unknown,unknown}} -> {lists:keyreplace( AppA,1,Acc,{AppA,Vsn,Dir}), Apps}; {value, {_,Vsn,_}} -> %% We already have this version {Acc, Apps}; Result -> case lists:keysearch(AppA, 1, AppInfo) of {value, {_,unknown,_}} -> case Result of {value, {_,OtherVsn,_}} -> case later_vsn(Vsn, OtherVsn) of true -> {lists:keyreplace( AppA,1,Acc,{AppA,Vsn,Dir}), Apps}; false -> {Acc, Apps} end; false -> {[{AppA,Vsn,Dir}|Acc], Apps} end; {value, {_, Vsn, unknown}} -> %% This is the version we want. Look no further for %% this app. {[{AppA,Vsn,Dir}|Acc], Apps -- [AppA]}; {value, {_, OtherVsn, _}} -> %% This is not the version we want {Acc, Apps}; false -> %% We have no prior knowledge of this app, other than %% that it should be included case Result of {value, {_,OtherVsn,_}} -> case later_vsn(Vsn, OtherVsn) of true -> {[{AppA,Vsn,Dir}|Acc], Apps}; false -> {Acc, Apps} end; false -> {[{AppA,Vsn,Dir}|Acc], Apps} end end end. %%% later_vsn(VsnA, VsnB) -> true | false. %%% true if VsnA > VsnB, false otherwise later_vsn(unknown,_) -> false; later_vsn(_,unknown) -> true; later_vsn(Vsn, Vsn) -> false; later_vsn(VsnA, VsnB) -> case get_newest([{VsnB,[]},{VsnA,[]}]) of {VsnB,_} -> false; {VsnA,[]} -> true end. %%% get_newest([{Vsn,Info}]) -> {NewestVsn,RelatedInfo}. %%% get_newest([{Vsn,_}] =X) -> X; get_newest([{Vsn1,_}=X1, {Vsn2,_}=X2 | Rest]) -> V1 = split(Vsn1), V2 = split(Vsn2), Newest = get_newest1(V1, V2, X1, X2), get_newest([Newest | Rest]). get_newest1([H1|T1], [H2|T2], X1, X2) -> if H1 > H2 -> X1; H2 > H1 -> X2; H1 == H2 -> get_newest1(T1, T2, X1, X2) end; get_newest1([], [], X1, X2) -> X1; get_newest1([H1|_], [], X1, X2) -> X1; get_newest1([], [H2|_], X1, X2) -> X2. split(VStr) -> split(VStr, undefined, [], []). split([], Mode, Acc1, Acc) -> lists:reverse([subv(Mode, lists:reverse(Acc1)) | Acc]); split("." ++ T, Mode, Acc1, Acc) -> split(T, Mode, [], [subv(Mode, lists:reverse(Acc1)) | Acc]); split([I|T], string, Acc1, Acc) when $0 =< I, I =< $9 -> split(T, integer, [I], [subv(string, lists:reverse(Acc1)) | Acc]); split([I|T], integer, Acc1, Acc) when $0 =< I, I =< $9 -> split(T, integer, [I|Acc1], Acc); split([C|T], integer, Acc1, Acc) -> split(T, string, [C], [subv(integer, lists:reverse(Acc1)) | Acc]); split([I|T], undefined, [], Acc) when $0 =< I, I =< $9 -> split(T, integer, [I], Acc); split([C|T], undefined, [], Acc) -> split(T, string, [C], Acc). subv(integer, SubV) -> list_to_integer(SubV); subv(string, SubV) -> SubV. %%% end later_vsn() member_of(AppName, [AppName|As]) -> {true, AppName}; member_of(AppName, [{AppName,Vsn}|As]) -> {true, {AppName, Vsn}}; member_of(AppName, [_|As]) -> member_of(AppName, As); member_of(_, []) -> false. d_expand(["/"|Ds]) -> d_expand(Ds, ["/"]); d_expand(Ds) -> {ok,Cwd} = file:get_cwd(), d_expand(Ds, [Cwd]). d_expand([D|Ds], Cur) -> Pat = regexp:sh_to_awk(D), Cur1 = lists:foldl( fun(C, Acc) -> case list_dir(C) of [] -> Acc; Fs -> Matches = [F || F <- Fs, matches(F, Pat)], Acc ++ [filename:join(C,F) || F <- Matches, is_dir(C,F)] end end, [], Cur), d_expand(Ds, Cur1); d_expand([], Cur) -> Cur. matches(Str, Pat) -> case regexp:match(Str,Pat) of {match,_,_} -> true; nomatch -> false end. is_dir(Parent, Dir) -> case file:read_file_info(filename:join(Parent, Dir)) of {ok, #file_info{type=directory}} -> true; _ -> false end. list_dir(Dir) -> case file:read_file_info(Dir) of {ok, #file_info{type=directory}} -> case file:list_dir(Dir) of {ok, Fs} -> Fs; _ -> [] end; _ -> [] end. apps(Apps, Dict) -> Path = fetch(path, Dict), Pat = [filename:basename(filename:dirname(Dir))||Dir<-get_path(Dict)], Vss = [string:tokens(D,"-") || D <- Pat, app(D)], do_apps(Apps, Vss). app(D) -> case regexp:match(D,".*-[0-9].*") of nomatch -> false; _ -> true end. do_apps([], Vss) -> []; do_apps([App|Apps], Vss) when list(App) -> do_apps([list_to_atom(App)|Apps], Vss); do_apps([App|Apps], Vss) when atom(App) -> [{App, get_vsn(atom_to_list(App), Vss)}|do_apps(Apps, Vss)]. get_vsn(App, [[App, Vsn]|_]) -> Vsn; get_vsn(App, [_|T]) -> get_vsn(App, T). get_erts_vsn() -> {ok, [[Root]]} = init:get_argument(root), {ok, Fs} = file:list_dir(Root), get_erts_vsn(Fs). get_erts_vsn([[$e,$r,$t,$s,$-|Vsn]|_]) -> Vsn; get_erts_vsn([_|T]) -> get_erts_vsn(T). out(Dir, App, Ext, Term) -> FN = filename:join(Dir, App++Ext), out(FN, Term). out(FN, Term) -> ?report(debug, "out(~p,~p)~n", [FN,Term]), case file:open(FN, [write]) of {ok, FD} -> io:fwrite(FD, "~p.~n", [Term]), file:close(FD); {error, R} -> exit({bad_filename, {FN, R}}) end. read_app_file(Dict) -> AppName = fetch(app_name, Dict), AppNameS = atom_to_list(AppName), AppF = get_app_filename(AppNameS, Dict), App = case file:consult(AppF) of {ok, [{application, _Name, Options}]} -> app_options(Options); {ok, [Options]} when list(Options) -> app_options(Options); {error, enoent} -> RealAppF = filename:join(ebin_dir(Dict), AppNameS ++ ".app"), case file:consult(RealAppF) of {ok, [{application, _Name, Options}]} -> app_options(Options); {error, enoent} -> ?report(debug, "no app file (~p) -- must generate one.~n", [AppName]), Options = app_options( [{description, "auto-generated app file for " ++ AppNameS}, {applications, [kernel,stdlib]}]) end; Other -> exit({error_reading_app_file, {AppF, Other}}) end, ?report(debug, "App = ~p~n", [App]), App. app_options(Opts) -> [opt(description,Opts,""), opt(id,Opts,""), opt(registered,Opts,[]), opt(applications,Opts,[kernel,stdlib]), opt(env,Opts,[]), opt(mod,Opts,[]), opt(start_phases,Opts,undefined)]. opt(Key,List,Default) -> case lists:keysearch(Key,1,List) of {value, {_, Value}} -> {Key, Value}; false -> {Key, Default} end. get_path(Dict) -> AppPath = ebin_dir(Dict), Path = code:get_path(), case lists:member(AppPath, Path) of true -> Path; false -> Path ++ [AppPath] end. % otp_path(Dict) -> % case dict:find(otp_path, Dict) of % {ok, Path} -> % Path; % error -> % {ok,[[Root]]} = init:get_argument(root), % filename:join([Root,"lib","*","ebin"]) % end. script(File) -> script(File, erl_eval:new_bindings()). script(File, Bs) -> case file:open(File, [read]) of {ok, Fd} -> Bs1 = erl_eval:add_binding('ScriptName',File,Bs), R = case eval_stream(Fd, Bs1) of {ok, Result} -> {ok, Result}; Error -> Error end, file:close(Fd), R; Error -> Error end. path_script(Path, File) -> path_script(Path, File, erl_eval:new_bindings()). path_script(Path, File, Bs) -> case file:path_open(Path, File, [read]) of {ok,Fd,Full} -> Bs1 = erl_eval:add_binding('ScriptName',Full,Bs), case eval_stream(Fd, Bs1) of {error,E} -> file:close(Fd), {error, {E, Full}}; {ok, R} -> file:close(Fd), {ok,R,Full} end; Error -> Error end. eval_stream(Fd, Bs) -> eval_stream(Fd, undefined, Bs). eval_stream(Fd, Last, Bs) -> eval_stream(io:parse_erl_exprs(Fd, ''), Fd, Last, Bs). eval_stream({ok,Form,EndLine}, Fd, Last, Bs0) -> case catch erl_eval:exprs(Form, Bs0) of {value,V,Bs} -> eval_stream(Fd, {V}, Bs); {'EXIT',Reason} -> {error, Reason} end; eval_stream({error,What,EndLine}, Fd, L, Bs) -> {error, {parse_error, {What,EndLine}}}; eval_stream({eof,EndLine}, Fd, Last, Bs) -> case Last of {Val} -> {ok, Val}; undefined -> %% empty script {error, empty_script} end. do_report(error) -> %% always report errors true; do_report(Level) -> LevelN = rpt_level(Level), case get(builder_debug) of true -> true; false -> false; undefined -> case get(builder_report_level) of undefined -> false; [{AtLevel,_}|_] when AtLevel >= LevelN -> true; _ -> false end end. rpt_level(none) -> 0; rpt_level(progress) -> 1; rpt_level(verbose) -> 2; rpt_level(debug) -> 3; rpt_level(N) when integer(N), N >= 0 -> N. push_report_level(Level, Dict) -> Ref = fetch('#ref#', Dict), N = rpt_level(Level), case get(builder_report_level) of undefined -> put(builder_report_level, [{N,Ref}]), io:format("pushed 1st report level ~p(~p)~n",[Level,N]); [{Prev,Ref}|Tail] -> put(builder_report_level, [{N,Ref}|Tail]), io:format("redefined report level ~p(~p)~n",[Level,N]); [_|_] = Levels -> put(builder_report_level, [{N,Ref}|Levels]), io:format("pushed next report level ~p(~p)~n",[Level,N]) end. pop_report_level() -> Level = get(builder_report_level), case Level of [_] -> erase(builder_report_level); [_|Tail] -> put(builder_report_level, Tail); undefined -> ok end. verify_dir(Dir) -> case file:read_file_info(Dir) of {ok, FI} when FI#file_info.type == directory, FI#file_info.access == read_write -> ok; {ok, FI} when FI#file_info.type == directory -> exit({access, Dir}); {error, enoent} -> try_create(Dir) end. try_create("/") -> exit({create, "/"}); try_create(".") -> exit({create, "/"}); try_create(Dir) -> case file:make_dir(Dir) of {error, Reason} -> try_create(filename:dirname(Dir)), try_create(Dir); ok -> ok end. manderlbot-manderlbot-0.9.3/src/000077500000000000000000000000001124273741000165675ustar00rootroot00000000000000manderlbot-manderlbot-0.9.3/src/config.erl000066400000000000000000000207451124273741000205500ustar00rootroot00000000000000%%%---------------------------------------------------------------------- %%% File : config.erl %%% Author : Dimitri Fontaine %%% Purpose : Read the manderlbot XML xonfig file %%% Created : 19 Feb 2002 by Dimitri Fontaine %%%---------------------------------------------------------------------- %%% %%% This file is part of Manderlbot. %%% %%% Manderlbot is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%% Manderlbot is distributed in the hope that it will be useful, %%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %%% GNU General Public License for more details. %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%% %%%---------------------------------------------------------------------- -module(config). -author('dim@tuxfamily.org'). -include("config.hrl"). -include_lib("xmerl.hrl"). -include("log.hrl"). -define(default_passwd, "h4ckd4w0rld"). -export([read/1]). -export([read_fortunes/1]). %%%---------------------------------------------------------------------- %%% Function: read/1 %%% Purpose: read the xml config file %%%---------------------------------------------------------------------- read(Filename) -> case xmerl_scan:file(Filename,[{space, normalize}]) of {ok, Root = #xmlElement{}} -> % xmerl-0.15 mdb_logger:debug("root: ~p~n~p~n", [Root#xmlElement.name, Root#xmlElement.content]), {ok, parse(Root, #config{})}; {Root = #xmlElement{}, Tail} -> % xmerl-0.19 mdb_logger:debug("root: ~p~n~p~n", [Root#xmlElement.name, Root#xmlElement.content]), {ok, parse(Root, #config{})}; Error -> {error, Error} end. %%%---------------------------------------------------------------------- %%% Function: parse/2 %%% Purpose: parse the xmerl structure %%%---------------------------------------------------------------------- parse(Element = #xmlElement{parents = []}, #config{}) -> Name = getAttr(Element#xmlElement.attributes, name), Controler = build_list( getAttr(Element#xmlElement.attributes, controler), ", "), lists:foldl(fun parse/2, #config{name = Name, controler = Controler}, Element#xmlElement.content); %% parsing the Dict elements parse(Element = #xmlElement{name=dict}, Conf = #config{dict=Dict}) -> Server = getAttr(Element#xmlElement.attributes, host), Port = getAttr(Element#xmlElement.attributes, port), Default = getAttr(Element#xmlElement.attributes, default), {ok, [{integer,1,IPort}],1} = erl_scan:string(Port), lists:foldl(fun parse/2, Conf#config{dict = {Server, IPort, Default}}, Element#xmlElement.content); %% parsing the Server elements parse(Element = #xmlElement{name=server}, Conf = #config{servers=SList}) -> Server = getAttr(Element#xmlElement.attributes, host), Port = getAttr(Element#xmlElement.attributes, port), Passwd = getAttr(Element#xmlElement.attributes, password, ?default_passwd), {ok, [{integer,1,IPort}],1} = erl_scan:string(Port), lists:foldl(fun parse/2, Conf#config{servers = [#server{host=Server, port=IPort, passwd=Passwd }|SList]}, Element#xmlElement.content); %% Parsing the Channel element parse(Element = #xmlElement{name=channel}, Conf = #config{servers=[CurServ|SList]}) -> ChanList = CurServ#server.channels, Chan = getAttr(Element#xmlElement.attributes, name), Bot = getAttr(Element#xmlElement.attributes, botname), {ok, List, _Count} = regexp:gsub(getAttr(Element#xmlElement.attributes, behaviours), "\s+|\t+|\n+", ","), B = string:tokens(List, ","), lists:foldl(fun parse/2, Conf#config{servers = [CurServ#server{channels = [#channel{name=Chan, botname=Bot, behaviours=B} |ChanList]} |SList]}, Element#xmlElement.content); %% Parsing the behaviour element parse(Element = #xmlElement{name=behaviour}, Conf = #config{servers=[CurServ|SList], behaviours=BList}) -> [CurChan|ChanList] = CurServ#server.channels, Name = getAttr(Element#xmlElement.attributes, name), Action = getAttr(Element#xmlElement.attributes, action), From = getAttr(Element#xmlElement.attributes, from, '_'), To = getAttr(Element#xmlElement.attributes, to, '_'), Op = getAttr(Element#xmlElement.attributes, op, '_'), Option = getAttr(Element#xmlElement.attributes, option, '_'), Pattern = getAttr(Element#xmlElement.attributes, pattern, '_'), EFrom = getAttr(Element#xmlElement.attributes, exl_from, '_'), ETo = getAttr(Element#xmlElement.attributes, exl_to, '_'), EOp = getAttr(Element#xmlElement.attributes, exl_op, '_'), EOption = getAttr(Element#xmlElement.attributes, exl_option, '_'), EPattern = getAttr(Element#xmlElement.attributes, exl_pattern, '_'), Data = getText(Action, Element#xmlElement.content), lists:foldl(fun parse/2, Conf#config{behaviours = [#cfg_behaviour{name=Name, action=Action, from=From, to=To, op=Op, option=Option, pattern = Pattern, exl_from=EFrom, exl_to=ETo, exl_op=EOp, exl_option=EOption, exl_pattern = EPattern, data=Data} | BList]}, Element#xmlElement.content); %% Parsing other elements parse(Element = #xmlElement{}, Conf = #config{}) -> lists:foldl(fun parse/2, Conf, Element#xmlElement.content); %% Parsing non #xmlElement elements parse(Element, Conf = #config{}) -> Conf. %%%---------------------------------------------------------------------- %%% Function: getAttr/2 %%% Purpose: search the attibute list for the given one %%%---------------------------------------------------------------------- getAttr(Attr, Name) -> getAttr(Attr, Name, ""). getAttr([Attr = #xmlAttribute{name=Name}|Tail], Name, Default) -> case Attr#xmlAttribute.value of [] -> Default; A -> A end; getAttr([H|T], Name, Default) -> getAttr(T, Name, Default); getAttr([], Name, Default) -> Default. %%%---------------------------------------------------------------------- %%% Function: getText/2 %%% Purpose: get the text of the XML node %%%---------------------------------------------------------------------- getText("fortune", [Text = #xmlText{value=Value}|Tail]) -> %% The value is a file name, we have to read it as a fortune file {ok,Str,_Count} = regexp:gsub(Value,"\n",""), % remove newline mdb_logger:debug("filename =str=~p count=~p~n",[Str,_Count]), read_fortunes(string:strip(Str, both)); getText(Action, [Text = #xmlText{value=Value}|Tail]) -> build_list(string:strip(Value, both)); getText(Action, _Other) -> "". %%%---------------------------------------------------------------------- %%% Function: build_list/1, build_list/2 %%% Purpose: Build a list from a string, using given separator. %%% Default separator is '%' %%%---------------------------------------------------------------------- build_list(String) -> build_list(String, "%"). build_list(String, Sep) -> string:tokens(String, Sep). %%%---------------------------------------------------------------------- %%% Function: getText/2 %%% Purpose: get the text of the XML node %%%---------------------------------------------------------------------- read_fortunes(Filename) -> case file:read_file(Filename) of {ok, Content} -> {ok, Fortunes} = regexp:split(binary_to_list(Content), "\n%\n"), mdb_logger:debug("Read ~p fortunes in file ~s~n",[length(Fortunes), Filename]), FLines = lists:map(fun(F) -> string:tokens(F,"\r\n") end, Fortunes), FLines; {error, Reason} -> mdb_logger:error("Config: could not read fortune file ~s: ~s", [Filename, Reason]), [] end. manderlbot-manderlbot-0.9.3/src/config_srv.erl000066400000000000000000000242101124273741000214310ustar00rootroot00000000000000%%%---------------------------------------------------------------------- %%% File : mdb_behaviours_srv.erl %%% Author : Dimitri Fontaine %%% Purpose : Manage the manderlbot config %%% Created : 2 Mar 2002 by Dimitri Fontaine %%%---------------------------------------------------------------------- %%% %%% This file is part of Manderlbot. %%% %%% Manderlbot is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%% Manderlbot is distributed in the hope that it will be useful, %%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %%% GNU General Public License for more details. %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%% %%%---------------------------------------------------------------------- -module(config_srv). -author('fontaine@whitestar'). %%-compile(export_all). %%-export([Function/Arity, ...]). -behaviour(gen_server). %% External exports -export([start_link/1, getConf/0, getDictConf/0, readConf/0, reconf/3, getBList/2, getBehaviours/1]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -include("config.hrl"). -include("mdb.hrl"). -include("log.hrl"). %% We need a big timeout in order to be able to launch new bots. -define(timeout, 10000). %%%---------------------------------------------------------------------- %%% API %%%---------------------------------------------------------------------- start_link(ConfigFile) -> gen_server:start_link({local, ?MODULE}, ?MODULE, [ConfigFile], []). getConf() -> gen_server:call(?MODULE, {getConf}, ?timeout). getDictConf() -> gen_server:call(?MODULE, {getDictConf}, ?timeout). readConf() -> gen_server:call(?MODULE, {readConf}, ?timeout). reconf(Chan, BotName, ConfigFile) -> gen_server:call(?MODULE, {reconf, Chan, BotName, ConfigFile}, ?timeout). getBList(Channel, BotName) -> gen_server:call(?MODULE, {getlist, Channel, BotName}, ?timeout). getBehaviours(BNames) -> gen_server:call(?MODULE, {getBehaviours, BNames}, ?timeout). %%%---------------------------------------------------------------------- %%% Callback functions from gen_server %%%---------------------------------------------------------------------- %%---------------------------------------------------------------------- %% Func: init/1 %% Returns: {ok, State} | %% {ok, State, Timeout} | %% ignore | %% {stop, Reason} %%---------------------------------------------------------------------- init([ConfigFile]) -> {ok, {filename, ConfigFile}}. %%---------------------------------------------------------------------- %% Func: handle_call/3 %% Returns: {reply, Reply, State} | %% {reply, Reply, State, Timeout} | %% {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, Reply, State} | (terminate/2 is called) %% {stop, Reason, State} (terminate/2 is called) %%---------------------------------------------------------------------- handle_call({getConf}, From, Config) -> {reply, {ok, Config}, Config}; handle_call({getDictConf}, From, Config = #config{dict=Dict}) -> {reply, {ok, Dict}, Config}; handle_call({readConf}, From, {filename, ConfigFile}) -> case config:read(ConfigFile) of {ok, Config} -> %% Here we launch all the configured bots checkForNewChans(Config), {reply, ok, Config}; {error, Reason} -> {reply, {error, Reason}, ConfigFile} end; handle_call({reconf, Channel, BotName, ConfigFile}, From, Config) -> case config:read(ConfigFile) of {ok, NewConfig = #config{}} -> %% Don't forget to check for new chans to join checkForNewChans(NewConfig), {reply, {ok, getBehaviours(NewConfig, Channel, BotName)}, NewConfig}; Error -> {reply, Error, Config} end; handle_call({getlist, Channel, BotName}, From, Conf) -> {reply, {ok, getBehaviours(Conf, Channel, BotName)}, Conf}; handle_call({getBehaviours, notfound}, From, Conf) -> {reply, {ok, []}, Conf}; handle_call({getBehaviours, BNames}, From, Conf=#config{behaviours=BList}) -> mdb_logger:debug("BNames: ~p~n", [BNames]), {reply, {ok, lists:filter(fun(Behaviour=#behaviour{id=Id}) -> lists:member(Id, BNames) end, build_behaviours_list(BList, []))}, Conf}; handle_call(Request, From, State) -> Reply = ok, {reply, Reply, State}. %%---------------------------------------------------------------------- %% Func: handle_cast/2 %% Returns: {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} (terminate/2 is called) %%---------------------------------------------------------------------- handle_cast(Msg, State) -> {noreply, State}. %%---------------------------------------------------------------------- %% Func: handle_info/2 %% Returns: {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} (terminate/2 is called) %%---------------------------------------------------------------------- handle_info(Info, State) -> {noreply, State}. %%---------------------------------------------------------------------- %% Func: terminate/2 %% Purpose: Shutdown the server %% Returns: any (ignored by gen_server) %%---------------------------------------------------------------------- terminate(Reason, State) -> ok. %%---------------------------------------------------------------------- %% Func: code_change/3 %%---------------------------------------------------------------------- code_change(OldVsn, State, Extra) -> {ok, State}. %%%---------------------------------------------------------------------- %%% Internal functions %%%---------------------------------------------------------------------- %%---------------------------------------------------------------------- %% build_behaviours_list/2 %% Build a behaviour list from the behaviours found in the %% config file %%---------------------------------------------------------------------- build_behaviours_list([], Acc) -> Acc; build_behaviours_list([BC=#cfg_behaviour{action=Action}|BClist], Acc) -> %% Here we map the actions defined in the config file %% With the code to use in order to make the action Behaviour = #behaviour{id = BC#cfg_behaviour.name, pattern = #data{ header_from = {regexp, BC#cfg_behaviour.from}, header_to = {regexp, BC#cfg_behaviour.to}, header_op = {regexp, BC#cfg_behaviour.op}, header_options = {regexp, BC#cfg_behaviour.option}, body = {regexp, BC#cfg_behaviour.pattern}}, exclude_pattern = #data{ header_from = {regexp, BC#cfg_behaviour.exl_from}, header_to = {regexp, BC#cfg_behaviour.exl_to}, header_op = {regexp, BC#cfg_behaviour.exl_op}, header_options = {regexp, BC#cfg_behaviour.exl_option}, body = {regexp, BC#cfg_behaviour.exl_pattern}}, function = getFun(Action), data = BC#cfg_behaviour.data}, build_behaviours_list(BClist, [Behaviour|Acc]). %%%---------------------------------------------------------------------- %%% Function: getFun/1 %%% Purpose: Given the action name, returns the Module and Function to %%% call. %%%---------------------------------------------------------------------- getFun(Action) -> %% calling list_to_atom, this may be dangerous (DoS) {list_to_atom("mdb_bhv_" ++ Action), behaviour}. %%---------------------------------------------------------------------- %% getBehaviours/3 %% Read the config and find on it our behaviours %%---------------------------------------------------------------------- getBehaviours(#config{servers=SList}, Chan, BotName) -> getBehaviours(SList, Chan, BotName); getBehaviours([#server{channels=CList}|STail], Chan, BotName) -> case getBehaviours(CList, Chan, BotName) of notfound -> getBehaviours(STail, Chan, BotName); BList -> BList end; getBehaviours([#channel{name=Chan, botname=BotName, behaviours=BList}|CTail], Chan, BotName) -> BList; getBehaviours([#channel{}|CTail], Chan, BotName) -> getBehaviours(CTail, Chan, BotName); getBehaviours([], Chan, BotName) -> notfound. %%---------------------------------------------------------------------- %% checkForNewChans/3 %% For each server/chan in the config, add it to the mdb_botlist. %% If no bot instance is connected, a new one will be started, %% calling mdb_botlist:add(Name, Controler, Host, Port, Chan) %%---------------------------------------------------------------------- checkForNewChans(Config) -> checkForNewChans(Config, [], Config). checkForNewChans(#config{name=Name, controler=Ctlr, servers=SList}, Params, Config ) -> checkForNewChans(SList, [Name, Ctlr], Config); checkForNewChans([#server{host=Host, port=Port, passwd=Pass, channels=CList}|Stail], [Name, Ctlr], Config ) -> checkForNewChans(CList, [Name, Ctlr, Host, Port, Pass], Config), checkForNewChans(Stail, [Name, Ctlr], Config); checkForNewChans([Channel=#channel{name=Chan, botname=BotName}|CTail], [Name, Ctlr, Host, Port, Pass], Config) -> %% In order to avoid a re-entrance which faults in timeout, %% we pass directly from here the new bot BList ! mdb_botlist:add(Name, Ctlr, Host, Port, Pass, Channel, getBehaviours(Config, Chan, BotName)), checkForNewChans(CTail, [Name, Ctlr, Host, Port, Pass], Config); checkForNewChans([], Params, Config) -> done. manderlbot-manderlbot-0.9.3/src/debian.erl000066400000000000000000000120601124273741000205140ustar00rootroot00000000000000%%% File : debian.erl %%% Author : Nicolas Niclausse %%% Purpose : search for debian package names or files in debian package %%% Created : 23 Jul 2002 by Nicolas Niclausse %%%---------------------------------------------------------------------- %%% %%% This file is part of Manderlbot. %%% %%% Manderlbot is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%% Manderlbot is distributed in the hope that it will be useful, %%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %%% GNU General Public License for more details. %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%% %%%---------------------------------------------------------------------- -module(debian). -author('nico@niclux.org'). -revision(' $Id$ '). -vsn(' $Revision$ '). -export([search/5, parse/1, set_request/1]). -include("mdb.hrl"). -define(debian_name, "packages.debian.org"). -define(debian_port, 80). -define(package_desc_start, "):"). -define(margin, 50). % left margin for file results search(Keywords, Input, BotPid, BotName, Channel) -> mdb_search:search({Keywords, Input, BotPid, BotName, Channel, #search_param{type = ?MODULE, server = ?debian_name, port = ?debian_port } }). %%---------------------------------------------------------------------- %% Func: parse/1 %% Purpose: Parse data %% Returns: {stop, Result} | {stop} | {continue} | {continue, Result} %% continue -> continue parsing of incoming data %% stop -> stop parsing of incoming data %% Result -> String to be printed by mdb %%---------------------------------------------------------------------- parse("HTTP/1.1 404" ++ Data) -> {stop, "HTTP not found"}; parse("HTTP/1.0 404" ++ Data) -> {stop, "HTTP not found"}; parse("" ++ Data) -> {stop}; parse("No responses" ++ Data) -> {stop,"not found"}; %% Package short description parse("

Package " ++ Data) -> [Description | _Other ] = string:tokens(Data,"<"), {continue, " " ++ Description}; parse("  " ++ Data) -> [Description | _Other ] = string:tokens(Data,"<"), {continue, " " ++ Description}; %% URL and description of package (new version of packages.debian.org) parse("
  • [URL | List ] = string:tokens(Data,"\""), Desc= lists:append(List), mdb_logger:debug("Debian got desc ~p~n", [Desc]), Pos= string:str(Desc,?package_desc_start) +length(?package_desc_start)+1, case catch string:substr(Desc, Pos) of Desc2 when is_list(Desc2) -> {continue, URL++" : " ++ Desc2}; Other -> mdb_logger:info("Debian desc error= ~p~n", [Other]), {continue, URL} end; %% Package short description, caps parse("  " ++ Data) -> [Description | _Other ] = string:tokens(Data,"<"), {continue, " " ++ Description}; %% URL of package, caps parse("\t [URL | _Other ] = string:tokens(Data,"\""), {continue, URL }; parse(Data) -> %% search for files case regexp:first_match(Data, "[^\t]+\t+\s+ % ok, found case httpd_util:split(Data, "(<|>)", 10) of {ok, [File, URL, Package | _Other ]} -> {continue, string:left(File, ?margin, $ )++ Package }; _ -> {continue} end; _B -> {continue} end. %%---------------------------------------------------------------------- %% Func: set_request/1 %% Purpose: Set the request given Keywords %% Returns: String %%---------------------------------------------------------------------- set_request([Type, Keyword]) -> set_request([Type, Keyword, "testing"]); set_request([package, Keyword, Version]) -> "GET /cgi-bin/search_packages.pl?keywords=" ++ Keyword ++ "&searchon=names&subword=1&version=" ++ Version ++"&release=all HTTP/1.1" ++ io_lib:nl() ++ "Host: " ++ ?debian_name ++io_lib:nl() ++io_lib:nl(); set_request([file, Keyword, Version]) -> "GET /cgi-bin/search_contents.pl?word=" ++ Keyword ++ "&searchmode=searchfiles&case=insensitive&version=" ++ Version ++ "&arch=i386&directories=yes HTTP/1.1" ++ io_lib:nl() ++ "Host: " ++ ?debian_name ++ io_lib:nl() ++ io_lib:nl(). manderlbot-manderlbot-0.9.3/src/irc_lib.erl000066400000000000000000000203241124273741000206770ustar00rootroot00000000000000%%%---------------------------------------------------------------------- %%% File : irc_lib.erl %%% Author : Mickaël Rémond %%% Purpose : This library gathers all functions to format and send %%% IRC commands. %%% It manage IRC server connexion, automatically answer to %%% server pings (necessary to stay online) and behaviour %%% management. %%% Created : 11 Sep 2001, Mickaël Rémond %%%---------------------------------------------------------------------- %%% %%% This program is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%%---------------------------------------------------------------------- %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%%---------------------------------------------------------------------- -module(irc_lib). -author('mickael.remond@erlang-fr.org'). -created('Date: 20010911'). -revision(' $Id$ '). -vsn(' $Revision$ '). %% IRC operations -export([pong/2, join/2, quit/2, say/3, action/3, login/4, who/4]). %% IRC helper functions -export([is_chanop/1, nickname/1, split_nick_user/1]). -include("irc.hrl"). -include("log.hrl"). %%---------------------------------------------------------------------- %% Function: pong/2 %% Purpose: Send a pong answer with the right id %% Args: Sock = socket %% Id = ping id to send back to the server %% Returns: ok %% or {error, Reason} (if the process is dead) %%---------------------------------------------------------------------- pong(Sock, Id)-> Pong = lists:append("PONG ", Id), command(Sock, Pong). %%---------------------------------------------------------------------- %% join/2 %% Join a discussion channel %%---------------------------------------------------------------------- join(Sock, Channel) -> Command = lists:append("JOIN ", Channel), command(Sock, Command). %%---------------------------------------------------------------------- %% quit/2 %% Inform the server we are quitting %%---------------------------------------------------------------------- quit(Sock, Message) -> Command = lists:append("QUIT :", Message), command(Sock, Command). %%---------------------------------------------------------------------- %% say/3 %% Say something in the given channel %%---------------------------------------------------------------------- say(Sock, Channel, Message) -> Command = lists:concat(["PRIVMSG ", Channel, " :", Message]), %% Command = io_lib:format("PRIVMSG ~s :~s", [Channel, Message]), command(Sock, Command). %%---------------------------------------------------------------------- %% say/3 %% Say something in the given channel %%---------------------------------------------------------------------- action(Sock, Channel, Message) -> Command = "PRIVMSG " ++ Channel ++ " :" ++ [1] ++ "ACTION " ++ Message ++ [1], command(Sock, Command). %%---------------------------------------------------------------------- %% login/4 %% Send the user information to terminate the log in phase %%---------------------------------------------------------------------- login(Sock, Nickname, Passwd, Realname) -> PassCommand = "PASS " ++ Passwd, command(Sock, PassCommand), NickCommand = "NICK " ++ Nickname, command(Sock, NickCommand), %% The username, hostname, servername and realname. Hostname and %% servername are only used in server to server communication UserCommand = lists:concat(["USER ", Nickname, " dummy dummy :", Realname]), command(Sock, UserCommand). %%---------------------------------------------------------------------- %% who/4 %% Get the list of people connected to the given channel. %% %% In order not to break the way manderlbot get the data and parses them, %% I have prefered to open a new connexion here. %%---------------------------------------------------------------------- who(Host, Port, Channel, Botname) -> case mdb_connection:connect(Host, Port) of {ok, Sock} -> login(Sock, "manderlbot", "passwd", Botname), command(Sock, "who " ++ Channel), {ok, String} = getData(Sock, []), gen_tcp:close(Sock), Lines = string:tokens(String, "\r\n"), KeepRE = ":" ++ Host ++ " 352", UserList = lists:filter(fun(Line) -> case regexp:match(Line, KeepRE) of {match, S, L} -> true; NoMatch -> false end end, Lines), lists:map(fun parseUserLine/1, UserList); Whatever -> [] end. %%---------------------------------------------------------------------- %% getData/2 %% internal who/4 function, used to get the data from the server. %%---------------------------------------------------------------------- getData(Sock, Buffer) -> receive {tcp, Sock, Data} -> case regexp:match(binary_to_list(Data), ":End of /WHO list.") of {match, S, L} -> {ok, Buffer ++ binary_to_list(Data)}; NoMatch -> getData(Sock, Buffer ++ binary_to_list(Data)) end; {Error, Sock} -> mdb_logger:error("Error: ~p~n", [Error]), {error, Buffer}; Whatever -> mdb_logger:notice("Whatever: ~p~n", [Whatever]), getData(Sock, Buffer) after 10000 -> {ok, Buffer} end. %%---------------------------------------------------------------------- %% parseUserLine/1 %% internal who/4 function, used to build the records from the irc line. %%---------------------------------------------------------------------- parseUserLine(Line) -> %% sample irc line received here %% :calvino.freenode.net 311 asr_ asr ~gaetan 2001:7a8:26cc:0:0:0:0:1 * :Gaetan RYCKEBOER %% :calvino.freenode.net 352 asr_ #manderlbot gaetan leeloo.lee-loo.net irc.freenode.net asr___ H :0 Gaetan RYCKEBOER [[$:|Server], Command, NickName, Channel, Login, From, To | Tail] = string:tokens(Line, " "), RealName = case Tail of [[$:|First], Last] -> First ++ " " ++ Last; [Nick, Status, _, First, Last] -> First ++ " " ++ Last; Other -> Other end, #user{login = Login, from = From, nick = NickName, name = RealName}. %%---------------------------------------------------------------------- %% command/2 %% Send a command to the IRC server %%---------------------------------------------------------------------- command(Sock, Command) -> CompleteCmd = io_lib:format("~s~s", [Command, "\r\n"]), mdb_logger:debug("COMMAND: ~s~n", [Command]), gen_tcp:send(Sock, CompleteCmd). %%---------------------------------------------------------------------- %% is_chanop/1 %% Returns true if the given nick is a chanop or false otherwise %% A chanop as an '@' before its nickname. %%---------------------------------------------------------------------- is_chanop([$@ | Nickname]) -> true; is_chanop(Nickname) -> false. %%---------------------------------------------------------------------- %% nickname/1 %% Return the nickname (removing '@' to chanop) %% A chanop as an '@' before its nickname. %%---------------------------------------------------------------------- nickname([$@ | Nickname]) -> Nickname; nickname(Nickname) -> Nickname. %%---------------------------------------------------------------------- %% split_nick_user/1 %% Return the nickname in lower case and %% the user %%---------------------------------------------------------------------- split_nick_user(HeaderFrom) -> %% Split the string between Nick and User (separated by !) [Nick, User] = string:tokens(HeaderFrom, "!"), %% Remove chanop indicator from nick Nick2 = nickname(Nick), %% convert Nickname to lowercase Nick3 = misc_tools:lower_string(Nick2), %% Return a list: Nick, User [Nick3, User]. manderlbot-manderlbot-0.9.3/src/manderlbot.app.src000066400000000000000000000016141124273741000222100ustar00rootroot00000000000000%% Manderlbot Application Configuration File %manderlbot.app.src ----- %% {application, manderlbot, [ {description, "Manderlbot"}, {vsn, "%VSN%"}, {id, "Manderlbot"}, {modules, [misc_tools, manderlbot, manderlbot_sup, mdb_connection, mdb_dispatch, mdb_logger, mdb_bhv_google, mdb_botlist, mdb_control, config, config_srv, debian, irc_lib, mdb_bhv_action, mdb_bhv_answer, mdb_bhv_bloto, mdb_bhv_debian_file, mdb_bhv_debian_pkg, mdb_bhv_dict, mdb_bhv_mute, mdb_bhv_pyramid, mdb_bhv_random, mdb_bhv_reconf, mdb_bhv_rejoin, mdb_bhv_say, mdb_bhv_think, mdb_bhv_timer, mdb_bot, mdb_bot_sup, mdb_search]}, {registered, []}, {applications, [kernel, stdlib]}, {env, [ {config_file, "/etc/manderlbot/config.xml"}, {log_file, "/var/log/manderlbot.log"}, {log_level, notice} ]}, {mod, {manderlbot, []}} ] }. manderlbot-manderlbot-0.9.3/src/manderlbot.erl000066400000000000000000000072001124273741000214210ustar00rootroot00000000000000%%%---------------------------------------------------------------------- %%% File : manderlbot.erl %%% Author : Dimitri Fontaine %%% Purpose : This app is an IRC bot %%% Created : 19 Feb 2002 by Dimitri Fontaine %%%---------------------------------------------------------------------- %%% %%% This file is part of Manderlbot. %%% %%% Manderlbot is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%% Manderlbot is distributed in the hope that it will be useful, %%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %%% GNU General Public License for more details. %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%% %%%---------------------------------------------------------------------- -module(manderlbot). -author('dim@tuxfamily.org'). -include("config.hrl"). -include("log.hrl"). -behaviour(application). %% application callbacks -export([start/2, stop/1]). %%%---------------------------------------------------------------------- %%% Callback functions from application %%%---------------------------------------------------------------------- %%---------------------------------------------------------------------- %% Func: start/2 %% Returns: {ok, Pid} | %% {ok, Pid, State} | %% {error, Reason} %%---------------------------------------------------------------------- start(Type, StartArgs) -> %% First read args {Config_file, Log_file, Log_level} = read_args(), case manderlbot_sup:start_link(Config_file, Log_file) of {ok, Pid} -> %% init the manderlbot system case init(Config_file, Log_file, Log_level) of ok -> {ok, Pid}; {error, Reason} -> {error, Reason} end; Error -> Error end. %%---------------------------------------------------------------------- %% Func: stop/1 %% Returns: any %%---------------------------------------------------------------------- stop(State) -> ok. %%%---------------------------------------------------------------------- %%% Internal functions %%%---------------------------------------------------------------------- init(Config_file, Log_file, Log_level) -> %% Init first the logger mdb_logger:add_handler({Log_file, Log_level}), mdb_logger:notice("Manderlbot starting with ~s~n", [Config_file]), %% Read the config and start the bots case config_srv:readConf() of ok -> ok; {error, Reason} -> mdb_logger:error("Could not init manderlbot: ~p~n", [Reason]), {error, Reason} end. %%---------------------------------------------------------------------- %% Func: read_args/0 %% Returns: {Config_file, Log_file} %%---------------------------------------------------------------------- read_args() -> %% We take the manderlbot application defaults {ok, ConfigFile} = application:get_env(manderlbot, config_file), {ok, LogFile} = application:get_env(manderlbot, log_file), {ok, LogLevel} = application:get_env(manderlbot, log_level), {ConfigFile, LogFile, LogLevel}. manderlbot-manderlbot-0.9.3/src/manderlbot.rel.src000066400000000000000000000001761124273741000222140ustar00rootroot00000000000000{release, {"Manderlbot", "&manderlbot_vsn&"}, {erts, "&erts_vsn&"}, [{kernel,"&kernel_vsn&"}, {stdlib,"&stdlib_vsn&"}]}. manderlbot-manderlbot-0.9.3/src/manderlbot_sup.erl000066400000000000000000000066371124273741000223250ustar00rootroot00000000000000%%%---------------------------------------------------------------------- %%% File : mdb_sup.erl %%% Author : Dimitri Fontaine %%% Purpose : Supervise all the bot instances (dynamic) %%% Created : 19 Feb 2002 by Dimitri Fontaine %%%---------------------------------------------------------------------- %%% %%% This file is part of Manderlbot. %%% %%% Manderlbot is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%% Manderlbot is distributed in the hope that it will be useful, %%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %%% GNU General Public License for more details. %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%% %%%---------------------------------------------------------------------- -module(manderlbot_sup). -author('dim@tuxfamily.org'). -include("mdb.hrl"). -include("config.hrl"). -behaviour(supervisor). %% External exports -export([start_link/2]). %% supervisor callbacks -export([init/1]). %%%---------------------------------------------------------------------- %%% API %%%---------------------------------------------------------------------- start_link(Config_file, Log_file) -> supervisor:start_link({local, ?MODULE}, ?MODULE, [Config_file, Log_file]). %%%---------------------------------------------------------------------- %%% Callback functions from supervisor %%%---------------------------------------------------------------------- %%---------------------------------------------------------------------- %% Func: init/1 %% Returns: {ok, {SupFlags, [ChildSpec]}} | %% ignore | %% {error, Reason} %%---------------------------------------------------------------------- init([Config_file, Log_file]) -> Logger = {mdb_logger, {mdb_logger, start_link, []}, permanent, 2000, worker, [mdb_logger]}, BotSup = {mdb_bot_sup, {mdb_bot_sup, start_link, []}, permanent, 2000, supervisor, [mdb_bot_sup]}, BotLst = {mdb_botlist, {mdb_botlist, start_link, []}, permanent, 2000, worker, [mdb_botlist]}, BServ = {config_srv, {config_srv, start_link, [Config_file]}, permanent, 2000, worker, [config_srv]}, BLoto = {mdb_bhv_bloto, {mdb_bhv_bloto, start_link, []}, permanent, 2000, worker, [mdb_bhv_bloto]}, Pyramid = {mdb_bhv_pyramid, {mdb_bhv_pyramid, start_link, []}, permanent, 2000, worker, [mdb_bhv_pyramid]}, BSearch = {mdb_search, {mdb_search, start_link, []}, permanent, 2000, worker, [mdb_search]}, {ok, {{one_for_one, 3, 60}, [Logger, BotSup, BotLst, BServ, BLoto, Pyramid, BSearch]}}. %%%---------------------------------------------------------------------- %%% Internal functions %%%---------------------------------------------------------------------- manderlbot-manderlbot-0.9.3/src/mdb_bhv_action.erl000066400000000000000000000035171124273741000222370ustar00rootroot00000000000000%%% File : mdb_bhv_action.erl %%% Author : Nicolas Niclausse %%% Purpose : Answer with Action IRC usage %%% Created : 12 Aug 2003 by Nicolas Niclausse %%%---------------------------------------------------------------------- %%% %%% This file is part of Manderlbot. %%% %%% Manderlbot is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%% Manderlbot is distributed in the hope that it will be useful, %%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %%% GNU General Public License for more details. %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%% %%%---------------------------------------------------------------------- -module(mdb_bhv_action). -vc('$Id$ '). -author('nico@niclux.org'). -export([behaviour/5]). % MDB behaviour API -include("mdb.hrl"). %%%---------------------------------------------------------------------- %%% Function: behaviour/5 %%% Purpose: Answer with Action IRC usage - /me %%%---------------------------------------------------------------------- behaviour(Input, BotName, Data, BotPid, Channel) -> lists:map(fun(String) -> mdb_bot:action(BotPid, String) end, Data). manderlbot-manderlbot-0.9.3/src/mdb_bhv_answer.erl000066400000000000000000000042211124273741000222520ustar00rootroot00000000000000%%% File : mdb_bhv_answer.erl %%% Author : Nicolas Niclausse %%% Purpose : %%% Created : 12 Aug 2003 by Nicolas Niclausse %%%---------------------------------------------------------------------- %%% %%% This file is part of Manderlbot. %%% %%% Manderlbot is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%% Manderlbot is distributed in the hope that it will be useful, %%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %%% GNU General Public License for more details. %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%% %%%---------------------------------------------------------------------- -module(mdb_bhv_answer). -vc('$Id$ '). -author('nico@niclux.org'). -export([behaviour/5]). % MDB behaviour API -include("mdb.hrl"). %%%---------------------------------------------------------------------- %%% Function: behaviour/5 %%% Purpose: Answer the given (config) data to the one who talk %%%---------------------------------------------------------------------- behaviour(Input = #data{header_to=BotName}, BotName, Data, BotPid, Channel) -> [NickFrom|IpFrom] = string:tokens(Input#data.header_from, "!"), lists:map(fun(String) -> mdb_bot:say(BotPid, String, NickFrom) end, Data); behaviour(Input, BotName, Data, BotPid, Channel) -> [NickFrom|IpFrom] = string:tokens(Input#data.header_from, "!"), lists:map(fun(String) -> mdb_bot:say(BotPid, NickFrom ++ ": " ++ String) end, Data). manderlbot-manderlbot-0.9.3/src/mdb_bhv_bloto.erl000066400000000000000000000136631124273741000221040ustar00rootroot00000000000000%%%---------------------------------------------------------------------- %%% File : mdb_bhv_bloto.erl %%% Author : Dimitri Fontaine %%% Purpose : Count the buzzwords and give a winner %%% Created : 6 Mar 2002 by Dimitri Fontaine %%%---------------------------------------------------------------------- %%% %%% This file is part of Manderlbot. %%% %%% Manderlbot is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%% Manderlbot is distributed in the hope that it will be useful, %%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %%% GNU General Public License for more details. %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%% %%%---------------------------------------------------------------------- -module(mdb_bhv_bloto). -author('tux@tuxfamily.org'). %%-compile(export_all). %%-export([Function/Arity, ...]). -behaviour(gen_server). %% External exports -export([behaviour/5]). % MDB behaviour API -export([start_link/0, add/2, reset/2]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -include("mdb.hrl"). -define(timeout, 5000). -define(MAX, 4). %% put here MAX-1 %%%---------------------------------------------------------------------- %%% API %%%---------------------------------------------------------------------- %%%---------------------------------------------------------------------- %%% Function: behaviour/5 %%% Purpose: Play to business loto... %%%---------------------------------------------------------------------- behaviour(Input, BotName, Data, BotPid, Channel) -> [NickFrom|IpFrom] = string:tokens(Input#data.header_from, "!"), case add(NickFrom, Channel) of {winner, Nick} -> mdb_bot:say(BotPid, Nick ++ " " ++ Data); Other -> ok end. start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). add(Nick, Channel) -> gen_server:call(?MODULE, {add, Nick, Channel}, ?timeout). %%%---------------------------------------------------------------------- %%% Callback functions from gen_server %%%---------------------------------------------------------------------- %%---------------------------------------------------------------------- %% Func: init/1 %% Returns: {ok, State} | %% {ok, State, Timeout} | %% ignore | %% {stop, Reason} %%---------------------------------------------------------------------- init([]) -> {ok, []}. %%---------------------------------------------------------------------- %% Func: handle_call/3 %% Returns: {reply, Reply, State} | %% {reply, Reply, State, Timeout} | %% {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, Reply, State} | (terminate/2 is called) %% {stop, Reason, State} (terminate/2 is called) %%---------------------------------------------------------------------- handle_call({add, Nick, Channel}, From, List) -> case lists:keysearch({Nick, Channel}, 1, List) of {value, {{Nick, Channel}, ?MAX}} -> {reply, {winner, Nick}, reset(Channel, List)}; {value, {{Nick, Channel}, N}} -> NewList = lists:keyreplace({Nick, Channel}, 1, List, {{Nick, Channel}, N+1}), {reply, ok, NewList}; false -> {reply, ok, [{{Nick, Channel}, 1}|List]} end; handle_call(Request, From, State) -> Reply = ok, {reply, Reply, State}. %%---------------------------------------------------------------------- %% Func: handle_cast/2 %% Returns: {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} (terminate/2 is called) %%---------------------------------------------------------------------- handle_cast(Msg, State) -> {noreply, State}. %%---------------------------------------------------------------------- %% Func: handle_info/2 %% Returns: {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} (terminate/2 is called) %%---------------------------------------------------------------------- handle_info(Info, State) -> {noreply, State}. %%---------------------------------------------------------------------- %% Func: terminate/2 %% Purpose: Shutdown the server %% Returns: any (ignored by gen_server) %%---------------------------------------------------------------------- terminate(Reason, State) -> ok. %%---------------------------------------------------------------------- %% Func: code_change/3 %%---------------------------------------------------------------------- code_change(OldVsn, State, Extra) -> {ok, State}. %%%---------------------------------------------------------------------- %%% Internal functions %%%---------------------------------------------------------------------- %%---------------------------------------------------------------------- %% Func: reset/3 %% Clean the List of all the Chan occurences %%---------------------------------------------------------------------- reset(Chan, List) -> reset(Chan, List, []). reset(Chan, [], Acc) -> lists:reverse(Acc); reset(Chan, [{{_Nick, Chan}, _Score}|Tail], Acc) -> reset(Chan, Tail, Acc); reset(Chan, [Head|Tail], Acc) -> reset(Chan, Tail, [Head|Acc]). manderlbot-manderlbot-0.9.3/src/mdb_bhv_debian_file.erl000066400000000000000000000044421124273741000232010ustar00rootroot00000000000000%%% File : mdb_bhv_debian_pkg.erl %%% Author : Nicolas Niclausse %%% Purpose : search for files in debian package %%% Created : 12 Aug 2003 by Nicolas Niclausse %%%---------------------------------------------------------------------- %%% %%% This file is part of Manderlbot. %%% %%% Manderlbot is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%% Manderlbot is distributed in the hope that it will be useful, %%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %%% GNU General Public License for more details. %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%% %%%---------------------------------------------------------------------- -module(mdb_bhv_debian_file). -vc('$Id$ '). -author('nico@niclux.org'). -export([behaviour/5]). % MDB behaviour API -include("mdb.hrl"). -include("log.hrl"). %%%---------------------------------------------------------------------- %%% Function: behaviour/5 %%% Purpose: search for files in debian package %%%---------------------------------------------------------------------- behaviour(Input, BotName, Data, BotPid, Channel) -> mdb_logger:info("DEBIAN file input: ~p~n", [Input#data.body]), [Key, String | Args] = string:tokens(Input#data.body," "), case Args of [] -> mdb_logger:info("DEBIAN criteria: ~p~n", [String]), debian:search([file, String], Input, BotPid, BotName, Channel); [Version | _] -> % which debian distrib mdb_logger:info("DEBIAN criteria: ~p,~p~n", [String, Version]), debian:search([file, String, Version], Input, BotPid, BotName, Channel) end. manderlbot-manderlbot-0.9.3/src/mdb_bhv_debian_pkg.erl000066400000000000000000000043631124273741000230450ustar00rootroot00000000000000%%% File : mdb_bhv_debian_pkg.erl %%% Author : Nicolas Niclausse %%% Purpose : search for debian packages %%% Created : 12 Aug 2003 by Nicolas Niclausse %%%---------------------------------------------------------------------- %%% %%% This file is part of Manderlbot. %%% %%% Manderlbot is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%% Manderlbot is distributed in the hope that it will be useful, %%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %%% GNU General Public License for more details. %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%% %%%---------------------------------------------------------------------- -module(mdb_bhv_debian_pkg). -vc('$Id$ '). -author('nico@niclux.org'). -export([behaviour/5]). % MDB behaviour API -include("mdb.hrl"). -include("log.hrl"). %%%---------------------------------------------------------------------- %%% Function: behaviour/5 %%% Purpose: search for debian packages %%%---------------------------------------------------------------------- behaviour(Input, BotName, Data, BotPid, Channel) -> mdb_logger:info("DEBIAN package input: ~p~n", [Input#data.body]), [Key, String | Args] = string:tokens(Input#data.body," "), case Args of [] -> mdb_logger:info("DEBIAN criteria: ~p~n", [String]), debian:search([package, String], Input, BotPid, BotName, Channel); [Version | _] -> % which debian distrib mdb_logger:info("DEBIAN criteria: ~p,~p~n", [String, Version]), debian:search([package, String, Version], Input, BotPid, BotName, Channel) end. manderlbot-manderlbot-0.9.3/src/mdb_bhv_dict.erl000066400000000000000000000101421124273741000216750ustar00rootroot00000000000000%%% File : mdb_bhv_dict.erl %%% Author : Nicolas Niclausse %%% Purpose : search for word definition using the DICT protocol (RFC 2229) %%% Created : 16 Jul 2002 by Nicolas Niclausse %%%---------------------------------------------------------------------- %%% %%% This file is part of Manderlbot. %%% %%% Manderlbot is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%% Manderlbot is distributed in the hope that it will be useful, %%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %%% GNU General Public License for more details. %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%% %%%---------------------------------------------------------------------- -module(mdb_bhv_dict). -author('nniclausse@idealx.com'). -revision(' $Id$ '). -vsn(' $Revision$ '). -export([behaviour/5]). % MDB behaviour API -export([search/5, search/6, parse/1, set_request/1]). -include("mdb.hrl"). -include("log.hrl"). %%%---------------------------------------------------------------------- %%% Function: dict/5 %%% Purpose: ask dict for a word definition %%%---------------------------------------------------------------------- behaviour(Input, BotName, Data, BotPid, Channel) -> [DictName] = Data, mdb_logger:info("DICT input: ~p~n", [Input#data.body]), mdb_logger:info("DICT name: ~p~n", [DictName]), [Key | Args] = string:tokens(Input#data.body," "), Criteria = string:strip(Args), mdb_logger:info("DICT criteria: ~p~n", [Criteria]), case DictName of [] -> search(Criteria, Input, BotPid, BotName, Channel); _ -> search(Criteria, Input, BotPid, BotName, Channel, DictName) end. %% search with default dictionnary search(Keywords, Input, BotPid, BotName, Channel) -> mdb_logger:debug("params: ~p~n", [getConf()]), mdb_search:search({Keywords, Input, BotPid, BotName, Channel, getConf()}). search(Keywords, Input, BotPid, BotName, Channel, Dict) -> mdb_logger:debug("params: ~p~n", [getConf()]), mdb_search:search({[Keywords, Dict], Input, BotPid, BotName, Channel, getConf()}). getConf() -> {ok, {Host, Port, Default}} = config_srv:getDictConf(), #search_param{type = ?MODULE, server = Host, port = Port}. %%---------------------------------------------------------------------- %% Func: parse/1 %% Purpose: Parse data %% Returns: {stop, Result} | {stop} | {continue} | {continue, Result} %% continue -> continue parsing of incoming data %% stop -> stop parsing of incoming data %% Result -> String to be printed by mdb %%---------------------------------------------------------------------- parse("250" ++ Data) -> %% completed {stop}; parse("552" ++ Data) -> %% no match {stop, "not found"}; parse("150" ++ Data) -> %% response headers (n def. found) {continue}; parse("151" ++ Data) -> %% response headers (database name) {continue}; parse("") -> {continue}; parse(".\r\n") -> {continue}; parse(Data) -> case regexp:first_match(Data, "^[0-9][0-9][0-9] ") of {match,Start,Length} -> % skip protocol data {continue}; _ -> {continue, lists:subtract(Data,"\r\n")} end. %%%search using Dict dictionnary set_request([Keyword, Dict]) -> set_request(Keyword, Dict); %%% get default dict configuration set_request(Keyword) -> {ok, {_, _, Default}} = config_srv:getDictConf(), set_request(Keyword, Default). set_request(Keyword, Dict) -> "DEFINE " ++ Dict ++ " " ++ Keyword ++ io_lib:nl(). manderlbot-manderlbot-0.9.3/src/mdb_bhv_fortune.erl000066400000000000000000000045641124273741000224470ustar00rootroot00000000000000%%% File : mdb_bhv_fortune.erl %%% Author : Dimitri Fontaine %%% Purpose : Choose at random a line in Data and answer it. %%% Created : 5 Dec 2003 by Dimitri Fontaine %%%---------------------------------------------------------------------- %%% %%% This file is part of Manderlbot. %%% %%% Manderlbot is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%% Manderlbot is distributed in the hope that it will be useful, %%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %%% GNU General Public License for more details. %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%% %%%---------------------------------------------------------------------- -module(mdb_bhv_fortune). -vc('$Id$ '). -author('dim@tuxfamily.org'). -export([behaviour/5]). % MDB behaviour API -include("mdb.hrl"). %%%---------------------------------------------------------------------- %%% Function: behaviour/5 %%% Purpose: Choose at random a line in Data and answer it. %%%---------------------------------------------------------------------- behaviour(Input = #data{header_to=BotName}, BotName, Data, BotPid, Channel) -> [NickFrom|IpFrom] = string:tokens(Input#data.header_from, "!"), {A, B, C} = now(), random:seed(A, B, C), lists:foreach(fun(Message) -> mdb_bot:say(BotPid, Message, NickFrom) end, lists:nth(random:uniform(length(Data)), Data)); behaviour(Input, BotName, Data, BotPid, Channel) -> {A, B, C} = now(), random:seed(A, B, C), lists:foreach(fun(Message) -> mdb_bot:say(BotPid, Message) end, lists:nth(random:uniform(length(Data)), Data)). manderlbot-manderlbot-0.9.3/src/mdb_bhv_google.erl000066400000000000000000000067371124273741000222450ustar00rootroot00000000000000%%% File : mdb_bhv_google.erl %%% Author : Nicolas Niclausse %%% Purpose : ask google for the first match of a given keyword %%% Created : 16 Jul 2002 by Nicolas Niclausse %%%---------------------------------------------------------------------- %%% %%% This file is part of Manderlbot. %%% %%% Manderlbot is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%% Manderlbot is distributed in the hope that it will be useful, %%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %%% GNU General Public License for more details. %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%% %%%---------------------------------------------------------------------- -module(mdb_bhv_google). -author('nico@niclux.org'). -revision(' $Id$ '). -vsn(' $Revision$ '). -export([behaviour/5]). % MDB behaviour API -export([search/5, parse/1, set_request/1]). -include("mdb.hrl"). -include("log.hrl"). -define(google_name, "www.google.com"). -define(google_port, 80). -define(notfound, "

    Aucun document ne correspond"). -define(CR, "\n"). %%%---------------------------------------------------------------------- %%% Function: behaviour/5 %%% Purpose: ask google and give the first response %%%---------------------------------------------------------------------- behaviour(Input, BotName, Data, BotPid, Channel) -> mdb_logger:debug("GOOGLE input: ~p~n", [Input#data.body]), [Key | Args] = string:tokens(Input#data.body," "), Criteria= misc_tools:join("+", Args), mdb_logger:debug("GOOGLE criteria: ~p~n", [Criteria]), search(Criteria, Input, BotPid, BotName, Channel). search(Keywords, Input, BotPid, BotName, Channel) -> mdb_search:search({Keywords, Input, BotPid, BotName, Channel, #search_param{type = ?MODULE, server = ?google_name, port = ?google_port } }). %%---------------------------------------------------------------------- %% Func: parse/1 %% Purpose: Parse data %% Returns: {stop, Result} | {stop} | {continue} | {continue, Result} %% continue -> continue parsing of incoming data %% stop -> stop parsing of incoming data %% Result -> String to be printed by mdb %%---------------------------------------------------------------------- parse("Location: " ++ URL) -> {stop, URL }; parse(?notfound ++ _Data) -> {stop, "not found"}; parse(Data) -> {continue}. %%---------------------------------------------------------------------- %% Func: set_request/1 %% Purpose: Set the request given Keywords %% Returns: String %%---------------------------------------------------------------------- set_request(Keywords) -> "GET /search?q=" ++ Keywords ++"&hl=fr&btnI=J%27ai+de+la+chance HTTP/1.0" ++ ?CR ++ ?CR. manderlbot-manderlbot-0.9.3/src/mdb_bhv_mute.erl000066400000000000000000000036431124273741000217340ustar00rootroot00000000000000%%% File : mdb_bhv_mute.erl %%% Author : Nicolas Niclausse %%% Purpose : allow the bot not to react for a while %%% Created : 12 Aug 2003 by Nicolas Niclausse %%%---------------------------------------------------------------------- %%% %%% This file is part of Manderlbot. %%% %%% Manderlbot is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%% Manderlbot is distributed in the hope that it will be useful, %%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %%% GNU General Public License for more details. %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%% %%%---------------------------------------------------------------------- -module(mdb_bhv_mute). -vc('$Id$ '). -author('nico@niclux.org'). -export([behaviour/5]). % MDB behaviour API -include("mdb.hrl"). -include("log.hrl"). %%%---------------------------------------------------------------------- %%% Function: behaviour/5 %%% Purpose: allow the bot not to react for a while %%%---------------------------------------------------------------------- behaviour(Input, BotName, Data, BotPid, Channel) -> [NickFrom|IpFrom] = string:tokens(Input#data.header_from, "!"), mdb_logger:debug("mute ~n", []), mdb_bot:mute(BotPid, NickFrom). manderlbot-manderlbot-0.9.3/src/mdb_bhv_pyramid.erl000066400000000000000000000234061124273741000224260ustar00rootroot00000000000000%%%------------------------------------------------------------------- %%% File : mdb_bhv_pyramid.erl %%% Author : Dimitri Fontaine %%% Description : Implementation of french TV game « Pyramide » %%% %%% Created : 7 Nov 2002 by Dimitri Fontaine %%%---------------------------------------------------------------------- %%% %%% This file is part of Manderlbot. %%% %%% Manderlbot is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%% Manderlbot is distributed in the hope that it will be useful, %%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %%% GNU General Public License for more details. %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%% %%%---------------------------------------------------------------------- -module(mdb_bhv_pyramid). -behaviour(gen_server). %%-------------------------------------------------------------------- %% Include files %%-------------------------------------------------------------------- -include("mdb.hrl"). -include("log.hrl"). %%-------------------------------------------------------------------- %% External exports -export([start_link/0, setWord/3, start/4, guess/3, behaviour/5]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -define(timeout, 5000). %%==================================================================== %% External functions %%==================================================================== %%-------------------------------------------------------------------- %% Function: start_link/0 %% Description: Starts the server %%-------------------------------------------------------------------- start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). setWord(Nick, Channel, Word) -> gen_server:call(?MODULE, {setWord, Nick, Channel, Word}, ?timeout). start(Nick, Channel, Player2, Nguess) -> gen_server:call(?MODULE, {start, Nick, Channel, Player2, Nguess}, ?timeout). guess(Nick, Channel, Word) -> gen_server:call(?MODULE, {guess, Nick, Channel, Word}, ?timeout). %%%---------------------------------------------------------------------- %%% Function: pyramid/5 %%% Purpose: implements a pyramid game, see comments %%%---------------------------------------------------------------------- behaviour(Input = #data{header_to=BotName}, BotName, Data, BotPid, Channel) -> %% - first player giving the bot the answer, before beginning the game, %% in private dialog [NickFrom|IpFrom] = string:tokens(Input#data.header_from, "!"), [Header, Word] = string:tokens(Input#data.body, ": "), case setWord(NickFrom, Channel, misc_tools:downcase(string:strip(Word))) of {ok, Message} -> mdb_bot:say(BotPid, Message, NickFrom), mdb_bot:say(BotPid, NickFrom ++ " has set a word to guess !"); {error, Reason} -> mdb_bot:say(BotPid, Reason, NickFrom) end; behaviour(Input, BotName, Data, BotPid, Channel) -> %% For this game, we have to detect some different cases on the %% same behaviour, that is : %% %% - beginning of game, first player inviting second and giving the %% number of tries %% %% - second player guess [NickFrom|IpFrom] = string:tokens(Input#data.header_from, "!"), mdb_logger:info("body: ~p~n", [Input#data.body]), case regexp:match(Input#data.body, "[A-Za-z0-9_]+/[0-9]+") of {match, S, L} -> [Player2, Nguess] = string:tokens(string:substr(Input#data.body, S, L), "/"), {ok, [{integer, 1, Iguess}],1} = erl_scan:string(Nguess), mdb_logger:info("pyramid: ~p invite ~p in ~p~n", [NickFrom, Player2, Iguess]), {_ok, SMsg} = start(NickFrom, Channel, Player2, Iguess), mdb_bot:say(BotPid, SMsg); _Whatever -> %% That is a guess [Header, Word] = string:tokens(Input#data.body, ": "), {_State, GMsg} = guess(NickFrom, Channel, misc_tools:downcase(string:strip(Word))), mdb_bot:say(BotPid, GMsg) end. %%==================================================================== %% Server functions %%==================================================================== %%-------------------------------------------------------------------- %% Function: init/1 %% Description: Initiates the server %% Returns: {ok, State} | %% {ok, State, Timeout} | %% ignore | %% {stop, Reason} %%-------------------------------------------------------------------- init([]) -> {ok, []}. %%-------------------------------------------------------------------- %% Function: handle_call/3 %% Description: Handling call messages %% Returns: {reply, Reply, State} | %% {reply, Reply, State, Timeout} | %% {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, Reply, State} | (terminate/2 is called) %% {stop, Reason, State} (terminate/2 is called) %%-------------------------------------------------------------------- handle_call({setWord, Nick, Channel, Word}, From, State) -> %% We receive the word to guess in private. The game has to be started %% to be able to set the word. case lists:keysearch({Nick, Channel}, 1, State) of {value, {{Player1, Channel}, noword, Player2, Nguess, Ntries}} -> {reply, {ok, Word ++ " has been set"}, lists:keyreplace({Player1, Channel}, 1, State, {{Player1, Channel}, Word, Player2, Nguess, Ntries}) }; {value, {{Player1, Channel}, GWord, Player2, Nguess, Ntries}} -> {reply, {error, "word to guess has already been set to: " ++ GWord}, State}; false -> {reply, {error, "No game started"}, State} end; handle_call({start, Nick, Channel, Player2, Nguess}, From, State) -> %% The game will start once the word to guess will be given in private %% We juste prepare and tell the players %% Attention: one game at a time ! case lists:keysearch({Nick, Channel}, 1, State) of {value, _} -> %% Game already started {reply, {error, "Game already started"}, State}; false -> %% Check the second player is not engaged case lists:keysearch(Player2, 3, State) of {value, _} -> {reply, {error, Player2 ++ " is already playing."}, State}; false -> %% We can start a new game {reply, {ok, Nick ++ ": please give me the word to guess (pv)"}, [{{Nick, Channel}, noword, Player2, Nguess, 1}|State]} end end; handle_call({guess, Nick, Channel, Word}, From, State) -> %% The second player is trying to guess the word case lists:keysearch(Nick, 3, State) of {value, {{Player1, Channel}, noword, Player2, Nguess, Ntries}} -> {reply, {ko, Player2 ++ ": please wait for " ++ Player1 ++ " to give a word to guess"}, State}; {value, {{Player1, Channel}, Word, Player2, Nguess, Ntries}} -> {reply, {ok, Player2 ++ " won in " ++ [48+Ntries] ++ " tries !"}, lists:keydelete({Player1, Channel}, 1, State)}; {value, {{Player1, Channel}, GWord, Player2, Nguess, Nguess}} -> {reply, {ko, Player2 ++ " failed to guess the word: " ++ GWord}, lists:keydelete({Player1, Channel}, 1, State)}; {value, {{Player1, Channel}, GWord, Player2, Nguess, Ntries}} -> %% Don't forget to increment the Ntries {reply, {ko, Player2 ++ ": try again ! "}, lists:keyreplace({Player1, Channel}, 1, State, {{Player1, Channel}, GWord, Player2, Nguess, Ntries + 1})}; false -> {reply, {ko, "No game started"}, State} end; handle_call(Request, From, State) -> Reply = ok, {reply, Reply, State}. %%-------------------------------------------------------------------- %% Function: handle_cast/2 %% Description: Handling cast messages %% Returns: {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} (terminate/2 is called) %%-------------------------------------------------------------------- handle_cast(Msg, State) -> {noreply, State}. %%-------------------------------------------------------------------- %% Function: handle_info/2 %% Description: Handling all non call/cast messages %% Returns: {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} (terminate/2 is called) %%-------------------------------------------------------------------- handle_info(Info, State) -> {noreply, State}. %%-------------------------------------------------------------------- %% Function: terminate/2 %% Description: Shutdown the server %% Returns: any (ignored by gen_server) %%-------------------------------------------------------------------- terminate(Reason, State) -> ok. %%-------------------------------------------------------------------- %% Func: code_change/3 %% Purpose: Convert process state when code is changed %% Returns: {ok, NewState} %%-------------------------------------------------------------------- code_change(OldVsn, State, Extra) -> {ok, State}. %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- manderlbot-manderlbot-0.9.3/src/mdb_bhv_random.erl000066400000000000000000000042441124273741000222400ustar00rootroot00000000000000%%% File : mdb_bhv_random.erl %%% Author : Nicolas Niclausse %%% Purpose : Choose at random a line in Data and answer it. %%% Created : 12 Aug 2003 by Nicolas Niclausse %%%---------------------------------------------------------------------- %%% %%% This file is part of Manderlbot. %%% %%% Manderlbot is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%% Manderlbot is distributed in the hope that it will be useful, %%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %%% GNU General Public License for more details. %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%% %%%---------------------------------------------------------------------- -module(mdb_bhv_random). -vc('$Id$ '). -author('nico@niclux.org'). -export([behaviour/5]). % MDB behaviour API -include("mdb.hrl"). %%%---------------------------------------------------------------------- %%% Function: behaviour/5 %%% Purpose: Choose at random a line in Data and answer it. %%%---------------------------------------------------------------------- behaviour(Input = #data{header_to=BotName}, BotName, Data, BotPid, Channel) -> [NickFrom|IpFrom] = string:tokens(Input#data.header_from, "!"), {A, B, C} = now(), random:seed(A, B, C), mdb_bot:say(BotPid, lists:nth(random:uniform(length(Data)), Data), NickFrom); behaviour(Input, BotName, Data, BotPid, Channel) -> {A, B, C} = now(), random:seed(A, B, C), mdb_bot:say(BotPid, lists:nth(random:uniform(length(Data)), Data)). manderlbot-manderlbot-0.9.3/src/mdb_bhv_reconf.erl000066400000000000000000000035471124273741000222410ustar00rootroot00000000000000%%% File : mdb_bhv_reconf.erl %%% Author : Nicolas Niclausse %%% Purpose : Re-read the config file %%% Created : 12 Aug 2003 by Nicolas Niclausse %%%---------------------------------------------------------------------- %%% %%% This file is part of Manderlbot. %%% %%% Manderlbot is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%% Manderlbot is distributed in the hope that it will be useful, %%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %%% GNU General Public License for more details. %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%% %%%---------------------------------------------------------------------- -module(mdb_bhv_reconf). -vc('$Id$ '). -author('nico@niclux.org'). -export([behaviour/5]). % MDB behaviour API -include("mdb.hrl"). %%%---------------------------------------------------------------------- %%% Function: behaviour/5 %%% Purpose: Re-read now the config file %%%---------------------------------------------------------------------- behaviour(Input, BotName, ConfigFile, BotPid, Channel) -> [NickFrom|IpFrom] = string:tokens(Input#data.header_from, "!"), mdb_bot:reconf(BotPid, NickFrom, ConfigFile). manderlbot-manderlbot-0.9.3/src/mdb_bhv_rejoin.erl000066400000000000000000000034061124273741000222450ustar00rootroot00000000000000%%% File : mdb_bhv_reconf.erl %%% Author : Nicolas Niclausse %%% Purpose : When kicked, rejoin the chan %%% Created : 12 Aug 2003 by Nicolas Niclausse %%%---------------------------------------------------------------------- %%% %%% This file is part of Manderlbot. %%% %%% Manderlbot is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%% Manderlbot is distributed in the hope that it will be useful, %%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %%% GNU General Public License for more details. %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%% %%%---------------------------------------------------------------------- -module(mdb_bhv_rejoin). -vc('$Id$ '). -author('nico@niclux.org'). -export([behaviour/5]). % MDB behaviour API -include("mdb.hrl"). %%%---------------------------------------------------------------------- %%% Function: behaviour/5 %%% Purpose: When kicked, rejoin the chan %%%---------------------------------------------------------------------- behaviour(Input, BotName, Data, BotPid, Channel) -> mdb_bot:rejoin(BotPid). manderlbot-manderlbot-0.9.3/src/mdb_bhv_say.erl000066400000000000000000000041341124273741000215520ustar00rootroot00000000000000%%% File : mdb_bhv_say.erl %%% Author : Nicolas Niclausse %%% Purpose : Say the data in the channel or to the speaker %%% Created : 12 Aug 2003 by Nicolas Niclausse %%%---------------------------------------------------------------------- %%% %%% This file is part of Manderlbot. %%% %%% Manderlbot is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%% Manderlbot is distributed in the hope that it will be useful, %%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %%% GNU General Public License for more details. %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%% %%%---------------------------------------------------------------------- -module(mdb_bhv_say). -vc('$Id$ '). -author('nico@niclux.org'). -export([behaviour/5]). % MDB behaviour API -include("mdb.hrl"). %%%---------------------------------------------------------------------- %%% Function: behaviour/5 %%% Purpose: Say the data in the channel or to the speaker %%%---------------------------------------------------------------------- behaviour(Input = #data{header_to=BotName}, BotName, Data, BotPid, Channel) -> [NickFrom|IpFrom] = string:tokens(Input#data.header_from, "!"), lists:map(fun(String) -> mdb_bot:say(BotPid, String, NickFrom) end, Data); behaviour(Input, BotName, Data, BotPid, Channel) -> lists:map(fun(String) -> mdb_bot:say(BotPid, String) end, Data). manderlbot-manderlbot-0.9.3/src/mdb_bhv_think.erl000066400000000000000000000036341124273741000220770ustar00rootroot00000000000000%%% File : mdb_bhv_think.erl %%% Author : Nicolas Niclausse %%% Purpose : Answer the given data, but waiting for random time %%% Created : 12 Aug 2003 by Nicolas Niclausse %%%---------------------------------------------------------------------- %%% %%% This file is part of Manderlbot. %%% %%% Manderlbot is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%% Manderlbot is distributed in the hope that it will be useful, %%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %%% GNU General Public License for more details. %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%% %%%---------------------------------------------------------------------- -module(mdb_bhv_think). -vc('$Id$ '). -author('nico@niclux.org'). -export([behaviour/5]). % MDB behaviour API -include("mdb.hrl"). %%%---------------------------------------------------------------------- %%% Function: behaviour/5 %%% Purpose: Answer the given data, but waiting for random time %%% between the 2 lines to say. %%%---------------------------------------------------------------------- behaviour(Input, BotName, Data, BotPid, Channel) -> lists:map(fun(String) -> mdb_bot:action(BotPid, String) end, Data). manderlbot-manderlbot-0.9.3/src/mdb_bhv_timer.erl000066400000000000000000000052011124273741000220720ustar00rootroot00000000000000%%% File : mdb_bhv_timer.erl %%% Author : Nicolas Niclausse %%% Purpose : %%% Created : 12 Aug 2003 by Nicolas Niclausse %%%---------------------------------------------------------------------- %%% %%% This file is part of Manderlbot. %%% %%% Manderlbot is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%% Manderlbot is distributed in the hope that it will be useful, %%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %%% GNU General Public License for more details. %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%% %%%---------------------------------------------------------------------- -module(mdb_bhv_timer). -vc('$Id$ '). -author('nico@niclux.org'). -export([behaviour/5]). % MDB behaviour API -include("mdb.hrl"). %%%---------------------------------------------------------------------- %%% Function: behaviour/5 %%% Purpose: Answer the given data, but waiting for random time %%% between the 2 lines to say. %%%---------------------------------------------------------------------- behaviour(Input = #data{header_to=BotName}, BotName, Data, BotPid, Channel) -> [NickFrom|IpFrom] = string:tokens(Input#data.header_from, "!"), behaviour2(Input, BotName, Data, BotPid, Channel, NickFrom); behaviour(Input, BotName, Data, BotPid, Channel) -> behaviour2(Input, BotName, Data, BotPid, Channel, []). behaviour2(Input, BotName, [], BotPid, Channel, NickFrom) -> ok; behaviour2(Input, BotName, [Data], BotPid, Channel, NickFrom) -> say(BotPid, Data, NickFrom); behaviour2(Input, BotName, [Data| Rest], BotPid, Channel, NickFrom) -> say(BotPid, Data, NickFrom), %% we sleep for a random time {A, B, C} = now(), random:seed(A, B, C), timer:sleep(random:uniform(?RNDTIME) + ?TIME), behaviour2(Input, BotName, Rest, BotPid, Channel, NickFrom). say(BotPid, String, []) -> mdb_bot:say(BotPid, String); say(BotPid, String, NickFrom) -> mdb_bot:say(BotPid, String, NickFrom). manderlbot-manderlbot-0.9.3/src/mdb_bot.erl000066400000000000000000000235341124273741000207100ustar00rootroot00000000000000%%%---------------------------------------------------------------------- %%% File : mdb_bot.erl %%% Author : Dimitri Fontaine %%% Purpose : Bot behaviours and connection manager %%% Created : 11 Aug 2002 by Dimitri Fontaine %%%---------------------------------------------------------------------- %%% %%% This file is part of Manderlbot. %%% %%% Manderlbot is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%% Manderlbot is distributed in the hope that it will be useful, %%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %%% GNU General Public License for more details. %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%% %%%---------------------------------------------------------------------- -module(mdb_bot). -author('dim@tuxfamily.org'). %%-compile(export_all). %%-export([Function/Arity, ...]). -behaviour(gen_server). %% External exports -export([start_link/0, start_link/1, stop/0]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -export([say/2, say/3, action/2, mute/2, rejoin/1, reconf/3]). -define(timeout, 25000). %% Configure debugging mode: -include("mdb_macros.hrl"). %% Include record description -include("mdb.hrl"). -include("config.hrl"). -include("log.hrl"). %%%---------------------------------------------------------------------- %%% API %%%---------------------------------------------------------------------- start_link() -> gen_server:start_link(?MODULE, [], []). start_link(Args) -> gen_server:start_link(?MODULE, Args, []). stop() -> gen_server:cast(?MODULE, {stop}). %% Controling the bot environment %% Send a message a the channel the bot is connected to say(BotPid, Message) -> gen_server:call(BotPid, {say, Message}, ?timeout). say(BotPid, Message, To) -> gen_server:call(BotPid, {say, Message, To}, ?timeout). action(BotPid, Message) -> gen_server:call(BotPid, {action, Message}, ?timeout). mute(BotPid, NickName) -> gen_server:call(BotPid, {mute, NickName}, ?timeout). %% Rejoin the channel (Use it when you have been kicked) rejoin(BotPid) -> gen_server:call(BotPid, rejoin, ?timeout). reconf(BotPid, NickName, ConfigFile) -> gen_server:call(BotPid, {reconf, NickName, ConfigFile}, ?timeout). %%%---------------------------------------------------------------------- %%% Callback functions from gen_server %%%---------------------------------------------------------------------- %%---------------------------------------------------------------------- %% Func: init/1 %% Returns: {ok, State} | %% {ok, State, Timeout} | %% ignore | %% {stop, Reason} %%---------------------------------------------------------------------- init([RealName, Controler, Host, Port, Passwd, Channel, BList]) -> mdb_logger:debug("launching a new bot: ~p~n", [Channel]), {ok, Sock} = mdb_connection:connect(Host, Port), mdb_connection:log(Sock, Channel, Passwd, RealName), %% To avoid some re-entrance issue when starting bot from a reconf, %% we may start the bot giving it its behaviours list... {ok, RealBList} = case BList of [] -> config_srv:getBList(Channel#channel.name, Channel#channel.botname); List -> {ok, BList} end, State = #state{bot_pid=self(), channel = Channel#channel.name, controler = Controler, socket = Sock, nickname = Channel#channel.botname, realname = RealName, passwd = Passwd, date = calendar:local_time(), behaviours = RealBList, host = Host, port = Port, joined = false, mode = unmuted }, {ok, State}. %%---------------------------------------------------------------------- %% Func: handle_call/3 %% Returns: {reply, Reply, State} | %% {reply, Reply, State, Timeout} | %% {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, Reply, State} | (terminate/2 is called) %% {stop, Reason, State} (terminate/2 is called) %%---------------------------------------------------------------------- handle_call({say, Message}, From, State=#state{socket=Sock, channel=Chan}) -> irc_lib:say(Sock, Chan, Message), {reply, ok, State}; handle_call({say, Message, To}, From, State=#state{socket=Sock, channel=Chan}) -> irc_lib:say(Sock, To, Message), {reply, ok, State}; handle_call({action, Message}, From, State=#state{socket=Sock, channel=Chan}) -> irc_lib:action(Sock, Chan, Message), {reply, ok, State}; handle_call(rejoin, From, State=#state{socket=Sock, channel=Chan}) -> irc_lib:join(Sock, Chan), {reply, ok, State}; handle_call({reconf, NickName, ConfigFile}, From, State=#state{socket=Sock, nickname=Nick, channel=Chan}) -> %% First read the conf file given %% Then get our behaviours list, and replace it in the State case is_controler(NickName, State#state.controler) of true -> case config_srv:reconf(Chan, Nick, ConfigFile) of {ok, BList} -> irc_lib:say(Sock, Chan, NickName ++ ": reconf done !"), {reply, ok, State#state{behaviours=BList}}; Error -> ErrorStr = io_lib:format("~p",[Error]), irc_lib:say(Sock, Chan, NickName ++ ": could not reconf " ++ ConfigFile ++ " " ++ ErrorStr ++ " !"), {reply, {error, reconf}, State} end; false -> irc_lib:say(Sock, Chan, NickName ++ ": " ++ "Who do you think you are to 'reconf' me ?"), {reply, {error, controller}, State} end; handle_call({mute, NickName}, From, State=#state{socket=Sock, channel=Chan}) -> case is_controler(NickName, State#state.controler) of true -> case State#state.mode of muted -> irc_lib:action(Sock, Chan, "is back"), {reply, ok, State#state{mode = unmuted}}; unmuted -> irc_lib:action(Sock, Chan, "is away"), {reply, ok, State#state{mode = muted}} end; false -> irc_lib:say(Sock, Chan, NickName ++ ": " ++ "Who do you think you are to mute me ?"), {reply, {error, controller}, State} end. %%---------------------------------------------------------------------- %% Func: handle_cast/2 %% Returns: {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} (terminate/2 is called) %%---------------------------------------------------------------------- handle_cast(Msg, State) -> {noreply, State}. %%---------------------------------------------------------------------- %% Func: handle_info/2 %% Returns: {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} (terminate/2 is called) %%---------------------------------------------------------------------- handle_info({tcp, Socket, Data}, State = #state{joined = false}) -> Buffer = binary_to_list(State#state.buffer), List = Buffer ++ binary_to_list(Data), case mdb_dispatch:process_data(Socket, List, State) of {joined, Rest} -> {noreply, State#state{joined = true, buffer=list_to_binary(Rest)}}; {pong, Rest} -> %% This was just a 'ping' request %% We can now join the channel irc_lib:join(Socket, State#state.channel), {noreply, State#state{joined = true, buffer=list_to_binary(Rest)}}; {ok, Rest} -> {noreply, State#state{buffer=list_to_binary(Rest)}} end; handle_info({tcp, Socket, Data}, State) -> Buffer = binary_to_list(State#state.buffer), List = Buffer ++ binary_to_list(Data), case mdb_dispatch:process_data(Socket, List, State) of {pong, Rest} -> {noreply, State#state{buffer=list_to_binary(Rest)}}; {ok, Rest} -> {noreply, State#state{buffer=list_to_binary(Rest)}} end; handle_info({tcp_einval, Socket}, State) -> {noreply, State}; handle_info({tcp_error, Socket, Reason}, State) -> mdb_logger:error("tcp error: reconnect ~p on ~p [~p]~n", [State#state.nickname, State#state.channel, Reason]), {ok, NewState} = mdb_connection:manage_reconnect(State), {noreply, NewState}; handle_info({tcp_closed, Socket}, State) -> {ok, NewState} = mdb_connection:manage_reconnect(State), {noreply, NewState}. %%---------------------------------------------------------------------- %% Func: terminate/2 %% Purpose: Shutdown the server %% Returns: any (ignored by gen_server) %%---------------------------------------------------------------------- terminate(Reason, State) -> mdb_logger:notice("~p is quitting ~p [~p]~n", [State#state.nickname, State#state.channel, Reason]), irc_lib:quit(State#state.socket, Reason), ok. %%---------------------------------------------------------------------- %% Func: code_change/3 %%---------------------------------------------------------------------- code_change(OldVsn, State, Extra) -> {ok, State}. %%%---------------------------------------------------------------------- %%% Internal functions %%%---------------------------------------------------------------------- %% This function support old way where controler is not a list is_controler(Nickname, Nickname) -> true; is_controler(Nickname, Controlers) -> lists:member(Nickname, Controlers). manderlbot-manderlbot-0.9.3/src/mdb_bot_sup.erl000066400000000000000000000057221124273741000215760ustar00rootroot00000000000000%%%---------------------------------------------------------------------- %%% File : mdb_sup.erl %%% Author : Dimitri Fontaine %%% Purpose : Supervise all the bot instances (dynamic) %%% Created : 19 Feb 2002 by Dimitri Fontaine %%%---------------------------------------------------------------------- %%% %%% This file is part of Manderlbot. %%% %%% Manderlbot is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%% Manderlbot is distributed in the hope that it will be useful, %%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %%% GNU General Public License for more details. %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%% %%%---------------------------------------------------------------------- -module(mdb_bot_sup). -author('dim@tuxfamily.org'). -include("mdb.hrl"). -include("config.hrl"). -behaviour(supervisor). %% External exports -export([start_link/0, start_child/6, start_child/7]). %% supervisor callbacks -export([init/1]). %%%---------------------------------------------------------------------- %%% API %%%---------------------------------------------------------------------- start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). start_child(Name, Controler, Host, Port, Pass, Chan) -> supervisor: start_child(?MODULE, [[Name, Controler, Host, Port, Pass, Chan, []]]). start_child(Name, Controler, Host, Port, Pass, Chan, BList) -> supervisor: start_child(?MODULE, [[Name, Controler, Host, Port, Pass, Chan, BList]]). %%%---------------------------------------------------------------------- %%% Callback functions from supervisor %%%---------------------------------------------------------------------- %%---------------------------------------------------------------------- %% Func: init/1 %% Returns: {ok, {SupFlags, [ChildSpec]}} | %% ignore | %% {error, Reason} %%---------------------------------------------------------------------- init([]) -> Bot = {manderlbot, {mdb_bot, start_link, []}, transient, 2000, worker, [mdb_bot]}, {ok, {{simple_one_for_one, 3, 60}, [Bot]}}. %%%---------------------------------------------------------------------- %%% Internal functions %%%---------------------------------------------------------------------- manderlbot-manderlbot-0.9.3/src/mdb_botlist.erl000066400000000000000000000135521124273741000216030ustar00rootroot00000000000000%%%---------------------------------------------------------------------- %%% File : mdb_botlist.erl %%% Author : Dimitri Fontaine %%% Purpose : Manage the mbd_bot running servers, and the Sockets %%% already in use for each bot. %%% Created : 16 Aug 2002 by Dimitri Fontaine %%%---------------------------------------------------------------------- %%% %%% This file is part of Manderlbot. %%% %%% Manderlbot is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%% Manderlbot is distributed in the hope that it will be useful, %%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %%% GNU General Public License for more details. %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%% %%%---------------------------------------------------------------------- -module(mdb_botlist). -author('dim@tuxfamily.org'). %%-compile(export_all). %%-export([Function/Arity, ...]). -behaviour(gen_server). %% External exports -export([start_link/0]). -export([add/6, add/7, list/0]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2]). -export([code_change/3]). -include("config.hrl"). -include("log.hrl"). %% We need a big timeout in order to be able to connect to the server. -define(timeout, 10000). %%%---------------------------------------------------------------------- %%% API %%%---------------------------------------------------------------------- start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). add(Name, Controler, Host, Port, Passwd, Chan) -> gen_server:call(?MODULE, {add, Name, Controler, Host, Port, Passwd, Chan, []}, ?timeout). add(Name, Controler, Host, Port, Passwd, Chan, BList) -> gen_server:call(?MODULE, {add, Name, Controler, Host, Port, Passwd, Chan, BList}, ?timeout). list() -> gen_server:call(?MODULE, {list}, ?timeout). %%%---------------------------------------------------------------------- %%% Callback functions from gen_server %%%---------------------------------------------------------------------- %%---------------------------------------------------------------------- %% Func: init/1 %% Returns: {ok, State} | %% {ok, State, Timeout} | %% ignore | %% {stop, Reason} %%---------------------------------------------------------------------- init([]) -> {ok, []}. %%---------------------------------------------------------------------- %% Func: handle_call/3 %% Returns: {reply, Reply, State} | %% {reply, Reply, State, Timeout} | %% {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, Reply, State} | (terminate/2 is called) %% {stop, Reason, State} (terminate/2 is called) %%---------------------------------------------------------------------- handle_call( {add, Name, Controler, Host, Port, Pass, Chan, BList}, From, State) -> AlreadyStarted = fun({H, C}) when H == Host, C == Chan -> true; (_) -> false end, %% We search our entry in the State case length(lists:filter(AlreadyStarted, State)) of 1 -> %% This Bot is already running mdb_logger:notice( "Bot ~p already running on ~p ~n", [Name, Chan#channel.name]), {reply, {error, running}, State}; NotFound -> %% We have to start this bot mdb_logger:notice("starting bot ~p on ~p~n", [Name, Chan#channel.name]), case mdb_bot_sup:start_child(Name, Controler, Host, Port, Pass, Chan, BList) of {ok, Sock} -> {reply, ok, State ++ [{Host, Chan}]}; {error, Reason} -> {reply, {error, Reason}, State} end end; handle_call({list}, From, State) -> {reply, {ok, State}, State}; handle_call(Request, From, State) -> Reply = ok, {reply, Reply, State}. %%---------------------------------------------------------------------- %% Func: handle_cast/2 %% Returns: {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} (terminate/2 is called) %%---------------------------------------------------------------------- handle_cast(Msg, State) -> {noreply, State}. %%---------------------------------------------------------------------- %% Func: handle_info/2 %% Returns: {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} (terminate/2 is called) %%---------------------------------------------------------------------- handle_info(Info, State) -> {noreply, State}. %%---------------------------------------------------------------------- %% Func: terminate/2 %% Purpose: Shutdown the server %% Returns: any (ignored by gen_server) %%---------------------------------------------------------------------- terminate(Reason, State) -> ok. %%---------------------------------------------------------------------- %% Func: code_change/3 %%---------------------------------------------------------------------- code_change(OldVsn, State, Extra) -> {ok, State}. %%%---------------------------------------------------------------------- %%% Internal functions %%%---------------------------------------------------------------------- manderlbot-manderlbot-0.9.3/src/mdb_connection.erl000066400000000000000000000075011124273741000222570ustar00rootroot00000000000000%%%---------------------------------------------------------------------- %%% File : mdb_connection.erl %%% Author : Mickaël Rémond %%% Purpose : Connection management library. %%% Used by mdb_bot.erl %%% Created : 16 Sep 2001, Mickaël Rémond %%%---------------------------------------------------------------------- %%% %%% This program is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%%---------------------------------------------------------------------- %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%%---------------------------------------------------------------------- -module(mdb_connection). -author('mickael.remond@erlang-fr.org'). -created('Date: 20010916'). -revision(' $Id$ '). -vsn(' $Revision$ '). %% External exports (API) -export([connect/2, log/4, manage_reconnect/1]). %% Configure debugging mode: -include("mdb_macros.hrl"). -include("config.hrl"). -include("mdb.hrl"). %%---------------------------------------------------------------------- %% connect/2 %% Physically connects to the IRC server %%---------------------------------------------------------------------- connect(Server, Ip_port) -> %% TCP connection to the IRC server Connect = fun() -> gen_tcp:connect(Server, Ip_port, [binary, {packet, 0}, {nodelay, true}, {keepalive, true}, {active, true}, {reuseaddr, true}]) end, case Connect() of {ok, Sock} -> mdb_logger:debug("Connected to: ~p~n", [Server]), {ok, Sock}; {error, Reason} -> %% If there is an error, wait 30 secondes and try to reconnect mdb_logger:warn("Server connection error: ~p~n", [Reason]), timer:sleep(30000), connect(Server, Ip_port) end. %%---------------------------------------------------------------------- %% log/3 %% connect to a given channel %%---------------------------------------------------------------------- log(Sock, Channel = #channel{}, Passwd, RealName) -> %% Logging in log_in(Sock, Channel#channel.botname, Passwd, RealName), %% Join the given channel irc_lib:join(Sock, Channel#channel.name). %%---------------------------------------------------------------------- %% log_in/3 %% Logging in: Give nick and realname to the server %%---------------------------------------------------------------------- %%log_in(Sock, Nickname, RealName, Password) -> log_in(Sock, Nickname, Passwd, RealName) -> irc_lib:login(Sock, Nickname, Passwd, RealName). %%irc_lib:passwd(Sock, "Password") %%---------------------------------------------------------------------- %% manage_reconnect/1 %% When something fails, automatically reconnects the bot %%---------------------------------------------------------------------- manage_reconnect(State) -> Host = State#state.host, Port = State#state.port, Chan = State#state.channel, Pass = State#state.passwd, Nick = State#state.nickname, RealName = State#state.realname, {ok, Sock} = connect(Host, Port), log(Sock, #channel{name=Chan, botname=Nick}, Pass, RealName), {ok, State#state{socket = Sock, date = calendar:local_time(), buffer = << >>, joined = false }}. manderlbot-manderlbot-0.9.3/src/mdb_control.erl000066400000000000000000000021141124273741000215730ustar00rootroot00000000000000%%%---------------------------------------------------------------------- %%% File : mdb_control.erl %%% Author : Dimitri Fontaine %%% Purpose : Control manderlbot, rpc to the running node %%% Created : 26 Aug 2003 by Dimitri Fontaine %%%---------------------------------------------------------------------- -module(mdb_control). -author('dim@tuxfamily.org'). -export([stop/0, status/0]). -include("config.hrl"). -include("log.hrl"). -define(mdb_node, "manderlbot"). %% %% The main control function %% stop() -> rpc:call(getNode(), application, stop, [manderlbot]), rpc:call(getNode(), init, stop, []), init:stop(). status() -> {ok, List} = rpc:call(getNode(), mdb_botlist, list, []), lists:map(fun({Host, Chan = #channel{}}) -> io:format("~s connected on ~s ~s~n", [Chan#channel.botname, Host, Chan#channel.name]) end, List), init:stop(). %% %% Some util functions %% getNode() -> [Node, Host] = string:tokens(atom_to_list(node()), "@"), list_to_atom(?mdb_node ++ "@" ++ Host). manderlbot-manderlbot-0.9.3/src/mdb_dispatch.erl000066400000000000000000000264771124273741000217340ustar00rootroot00000000000000%%%---------------------------------------------------------------------- %%% File : mdb_dispatch.erl %%% Author : Mickaël Rémond %%% Purpose : Library gather the process of IRC event and the execution %%% of "behaviours" (event handling code). %%% Created : 16 Sep 2001, Mickaël Rémond %%%---------------------------------------------------------------------- %%% %%% This program is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%%---------------------------------------------------------------------- %%% %%% See COPYING for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%%---------------------------------------------------------------------- -module(mdb_dispatch). -author('mickael.remond@erlang-fr.org'). -created('Date: 20010916'). -revision(' $Id$ '). -vsn(' $Revision$ '). %% External exports (API) -export([process_data/3, treat_recv/3, append_botname/2]). %% -- Includes -- %% Configure debugging mode: -include("mdb_macros.hrl"). %% Include record description -include("mdb.hrl"). -include("config.hrl"). -define(NL, "\r\n"). -define(BOTNAME, "%BOTNAME"). %%---------------------------------------------------------------------- %% process_data/3 %% Parse the incoming data into lines, %% and spawn a treat_recv process on each one %%---------------------------------------------------------------------- process_data(Sock, [], State=#state{}) -> {ok, []}; process_data(Sock, [$P, $I, $N, $G, $ , $: | Tail], State=#state{}) -> %% We consider PING separately {Id, Rest} = cut_line(Tail), irc_lib:pong(Sock, Id), {pong, Rest}; process_data(Sock, Data, State=#state{joined = false}) -> %% When we do not have joined, we have to test for a join chan %% response. This can occurs when server require a pong before %% anything else %% So this code will manage the MOTD of the server {Line, Rest} = cut_line(Data), %% mdb_logger:log("MOTD ~p~n", [Line]), Chan = [$: | State#state.channel], case string:tokens(Line, " ") of [_Name, "JOIN", Chan | Tail] -> mdb_logger:log( "~s joined channel ~s~n", [State#state.nickname, State#state.channel]), %% There could be some behaviours on login process_data(Sock, Line ++ ?NL, State#state{joined=true}), {joined, Rest}; _ -> process_data(Sock, Rest, State) end; process_data(Sock, Data, State=#state{joined = true}) -> case cut_line(Data) of %% If we don't find ?NL in the data, then we add it in the buffer {Data, []} -> {ok, Data}; {Line, Rest} -> proc_lib:spawn(?MODULE, treat_recv, [Sock, list_to_binary(Line), State]), process_data(Sock, Rest, State) end; process_data(Sock, Data, State) -> mdb_logger:debug("process_data: ~p ~p ~p ~n", [Sock, Data, State]), {ok, []}. cut_line(Data) -> Pos = string:str(Data, ?NL), case Pos of 0 -> {Data, []}; _ -> Line = string:substr( Data, 1, Pos-1 ), Rest = string:substr( Data, Pos+2, string:len(Data) - (Pos-1) ), {Line, Rest} end. %%---------------------------------------------------------------------- %% treat_recv/3 %% Otherwise: %%---------------------------------------------------------------------- treat_recv(Sock, Data, State=#state{}) -> Result = binary_to_list(Data), %% The Parsed_Result is a list of data records. Parsed_result = input_to_record(Result), %% Get the list of behaviours that match to the current IRC line %% And for which the corresponding fun will be executed {ok, BList} = config_srv:getBehaviours(State#state.behaviours), %% mdb_logger:log("BList: ~p~n", [State#state.behaviours]), lists:map(fun(X) -> MatchingList = match_event(X, BList, State#state.nickname), dispatch_message(MatchingList, X, State) end, Parsed_result), %% Trace lists:map(fun(Res) -> [NickFrom|_] = string:tokens(Res#data.header_from, "!"), mdb_logger:info("~s ~s <~s> ~s~n", [State#state.nickname, Res#data.header_to, NickFrom, Res#data.body]) end, Parsed_result). %%---------------------------------------------------------------------- %% dispatch_message/3 %% We are executing the behaviour whose pattern is matching with %% the input from the IRC server %%---------------------------------------------------------------------- dispatch_message(Behaviours, Input, State = #state{mode=muted}) -> lists:map(fun(Behaviour = #behaviour{id = "mute"}) -> {M, F} = Behaviour#behaviour.function, apply(M, F, [Input, State#state.nickname, Behaviour#behaviour.data, State#state.bot_pid, State#state.channel]); (_) -> mdb_logger:log("~s MUTED", [State#state.nickname]) end, Behaviours); dispatch_message(Behaviours, Input, State = #state{}) -> lists:map(fun(Behaviour) -> mdb_logger:log("Match= ~p~n", [Behaviour#behaviour.function]), {M, F} = Behaviour#behaviour.function, apply(M, F, [Input, State#state.nickname, Behaviour#behaviour.data, State#state.bot_pid, State#state.channel]) end, Behaviours). %%---------------------------------------------------------------------- %% input_to_record/1 %% Convert a given input to a list of preparsed data records %%---------------------------------------------------------------------- input_to_record(ServerData) -> Lines = string:tokens(ServerData, ?NL), parse_lines(Lines, []). %%---------------------------------------------------------------------- %% parse_lines/2 %% Each input line will be a data record %%---------------------------------------------------------------------- parse_lines([], Result) -> lists:reverse(Result); parse_lines([Line|Lines], Result) -> parse_lines(Lines, [parse_line(Line) | Result]). %%---------------------------------------------------------------------- %% parse_line/1 %% Each line is split between the data record fields %%---------------------------------------------------------------------- parse_line([$: | ServerData]) -> BodyPos = string:chr(ServerData, $:), case BodyPos > 0 of true -> Header = string:substr(ServerData, 1, BodyPos - 1), Body = string:substr(ServerData, BodyPos + 1), Result = string:tokens(Header, " "), [Header_from, Header_op, Header_to, Header_options] = case Result of [From] -> [From, ?nodata, ?nodata, ?nodata]; [From, Op] -> [From, Op, ?nodata, ?nodata]; [From, Op, To | Options] -> [From, Op, To, lists:flatten(Options)] end, #data{header_from = Header_from, header_op = Header_op, header_to = Header_to, header_options = Header_options, body = Body}; false -> [Header_from, Header_op, Header_to | _Rest] = string:tokens(ServerData, " "), #data{header_from = Header_from, header_op = Header_op, header_to = Header_to, body = ""} end; %% I think that missing a ping generate a message that fall in this case and %% crash the process parse_line(ServerData) -> mdb_logger:debug("In ParseLine: unidentified: ~p", [ServerData]), %% Ignore. #data{}. %%---------------------------------------------------------------------- %% match_event/3 %% Returns the list of behaviour that should be executed on an irc input %%---------------------------------------------------------------------- match_event(Data, Behaviours, Nickname) -> match_event(data_as_list(Data), Behaviours, Nickname, []). match_event(Data, [], Nickname, Acc) -> lists:reverse(Acc); match_event(Data, [Behaviour|Behaviours], Nickname, Acc) -> MatchCritList = append_botname(data_as_list(Behaviour#behaviour.pattern), Nickname), ExlCritList = append_botname( data_as_list(Behaviour#behaviour.exclude_pattern), Nickname), %% We react on the behaviour only when the pattern is matched and %% the exclude pattern is not case {is_matching(Data, MatchCritList), is_matching(Data, ExlCritList, exclude)} of {true, false} -> match_event(Data, Behaviours, Nickname, [Behaviour|Acc]); _DontMatch -> match_event(Data, Behaviours, Nickname, Acc) end. %%---------------------------------------------------------------------- %% data_as_list/1 %% Convert the data record to a list of values %%---------------------------------------------------------------------- data_as_list(Data) -> DataList = tuple_to_list(Data), [RecordName | Rest] = DataList, Rest. %%---------------------------------------------------------------------- %% append_botname/2 %% Convert '%BOTNAME' wherever in the list by its real name %%---------------------------------------------------------------------- append_botname(List, Botname) -> lists:map(fun(Exp = {regexp, '_'}) -> Exp; ({regexp, String}) -> {ok, NewString, _C} = regexp:sub(String, ?BOTNAME, Botname), {regexp, NewString}; (Other) -> Other end, List). %%---------------------------------------------------------------------- %% is_matching/3 %% Check if the first list (data record field values) match the %% Criterium %% %% The last parameter is the mathing mode. %% %%---------------------------------------------------------------------- is_matching(Data, Criterium) -> is_matching(Data, Criterium, true, normal). is_matching(Data, Criterium, exclude) -> %% Weh excluding, we fail the test by default is_matching(Data, Criterium, false, exclude). is_matching(_Data, _Criterium, Result = false, normal) -> %% We cut the tests when in normal mode and found false result Result; is_matching(_Data, _Criterium, Result = true, exclude) -> %% We cut the tests when in exclude mode and found true result Result; is_matching([],[], Result, Mode) -> Result; is_matching([E|Elements], [C|Criteria], Result, Mode) -> %% mdb_logger:log("is_matching: ~p ~p~n", [C, E]), %% %% When we have no criterium, in exclude mode, we consider %% the match has failed. NoCrit = case Mode of normal -> true; exclude -> false end, case C of ?nodata -> is_matching(Elements, Criteria, lop(NoCrit, Result, Mode), Mode); {regexp, ?nodata} -> is_matching(Elements, Criteria, lop(NoCrit, Result, Mode), Mode); {regexp, Expr} -> is_matching(Elements, Criteria, misc_tools:is_matching_regexp(E, Expr), Mode); %% Should tag the Criterium value as {exact, Criterium} E -> is_matching(Elements, Criteria, lop(true, Result, Mode), Mode); _Other -> is_matching(Elements, Criteria, lop(false, Result, Mode), Mode) end. %% Logic Operator %% When excluding, keep current state if there is no criterium lop(false, true, exclude) -> true; lop(Bool, State, Mode) -> Bool. manderlbot-manderlbot-0.9.3/src/mdb_logger.erl000066400000000000000000000144221124273741000213770ustar00rootroot00000000000000%%%---------------------------------------------------------------------- %%% File : mdb_logger.erl %%% Author : Dimitri Fontaine %%% Purpose : Manage to write the logs to a file %%% Created : 7 Oct 2003 by Dimitri Fontaine %%%---------------------------------------------------------------------- %%% %%% This file is part of Manderlbot. %%% %%% Manderlbot is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%% Manderlbot is distributed in the hope that it will be useful, %%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %%% GNU General Public License for more details. %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%% %%%---------------------------------------------------------------------- -module(mdb_logger). -author('dim@tuxfamily.org'). %%-export([Function/Arity, ...]). -behaviour(gen_event). %% External exports -export([start_link/0, add_handler/1, change_loglevel/1]). -export([log/2, log/3, emerg/2, alert/2, critic/2, error/2, warn/2, notice/2, info/2, debug/2]). %% gen_event callbacks -export([init/1, handle_event/2, handle_call/2, handle_info/2, terminate/2, code_change/3]). %% include -include("log.hrl"). %%%---------------------------------------------------------------------- %%% API %%%---------------------------------------------------------------------- start_link() -> gen_event:start_link({local, ?MODULE}). add_handler({LogFile, Level}) -> gen_event:add_handler(?MODULE, ?MODULE, [LogFile, Level]). %% change_loglevel(Level) -> gen_event:notify(?MODULE, {change_loglevel, Level}). %% Default to DEBUG level log(Mesg, Args) -> log(Mesg, Args, ?DEB). %% log with given level log(Mesg, Args, Level) -> gen_event:notify(?MODULE, {log, Mesg, Args, Level}). %% specific logs emerg(Mesg, Args) -> gen_event:notify(?MODULE, {log, Mesg, Args, ?EMERG}). alert(Mesg, Args) -> gen_event:notify(?MODULE, {log, Mesg, Args, ?ALERT}). critic(Mesg, Args) -> gen_event:notify(?MODULE, {log, Mesg, Args, ?CRIT}). error(Mesg, Args) -> gen_event:notify(?MODULE, {log, Mesg, Args, ?ERR}). warn(Mesg, Args) -> gen_event:notify(?MODULE, {log, Mesg, Args, ?WARN}). notice(Mesg, Args) -> gen_event:notify(?MODULE, {log, Mesg, Args, ?NOTICE}). info(Mesg, Args) -> gen_event:notify(?MODULE, {log, Mesg, Args, ?INFO}). debug(Mesg, Args) -> gen_event:notify(?MODULE, {log, Mesg, Args, ?DEB}). %%%---------------------------------------------------------------------- %%% Callback functions from gen_event %%%---------------------------------------------------------------------- %%---------------------------------------------------------------------- %% Func: init/1 %% Returns: {ok, State} | %% Other %%---------------------------------------------------------------------- init([LogFile, Level]) -> {ok, Fd} = file:open(LogFile, write), Level_num = lvl2numeric(Level), {ok, #log{fd=Fd, level=Level_num}}. %%---------------------------------------------------------------------- %% Func: handle_event/2 %% Returns: {ok, State} | %% {swap_handler, Args1, State1, Mod2, Args2} | %% remove_handler %%---------------------------------------------------------------------- handle_event({change_loglevel, Level}, State) -> Level_num = lvl2numeric(Level), {ok, State#log{level=Level_num}}; handle_event({log, Mesg, Args}, State) -> do_log(Mesg, Args, State#log.fd), {ok, State}; %% when the loglevel is given, log only if the level is high enough handle_event({log, Mesg, Args, Level}, State) when State#log.level >= Level -> do_log(Mesg, Args, State#log.fd), {ok, State}; handle_event(Event, State) -> {ok, State}. %%---------------------------------------------------------------------- %% Func: handle_call/2 %% Returns: {ok, Reply, State} | %% {swap_handler, Reply, Args1, State1, Mod2, Args2} | %% {remove_handler, Reply} %%---------------------------------------------------------------------- handle_call(Request, State) -> Reply = ok, {ok, Reply, State}. %%---------------------------------------------------------------------- %% Func: handle_info/2 %% Returns: {ok, State} | %% {swap_handler, Args1, State1, Mod2, Args2} | %% remove_handler %%---------------------------------------------------------------------- handle_info(Info, State) -> {ok, State}. %%---------------------------------------------------------------------- %% Func: terminate/2 %% Purpose: Shutdown the server %% Returns: any %%---------------------------------------------------------------------- terminate(Reason, State) -> file:close(State#log.fd). %%---------------------------------------------------------------------- %% Func: code_change/3 %%---------------------------------------------------------------------- code_change(OldVsn, State, Extra) -> {ok, State}. %%%---------------------------------------------------------------------- %%% Internal functions %%%---------------------------------------------------------------------- do_log(Mesg, Args, Fd) -> {{Y, Mth, D}, {H, Min, S}} = calendar:local_time(), io:format(Fd, "~p/~p/~p ~p:~p:~p ", [Y, Mth, D, H, Min, S]), io:format(Fd, Mesg, Args). lvl2numeric(emerg) -> ?EMERG; lvl2numeric(alert) -> ?ALERT; lvl2numeric(crit) -> ?CRIT; lvl2numeric(err) -> ?ERR; lvl2numeric(warn) -> ?WARN; lvl2numeric(notice) -> ?NOTICE; lvl2numeric(info) -> ?INFO; lvl2numeric(debug) -> ?DEB; lvl2numeric(_) -> ?DEB. manderlbot-manderlbot-0.9.3/src/mdb_search.erl000066400000000000000000000226421124273741000213700ustar00rootroot00000000000000%%%---------------------------------------------------------------------- %%% File : mdb_search.erl %%% Author : Nicolas Niclausse %%% Purpose : generic server for sending search requests and parsing %%% responses from remote servers %%% Created : 10 Aug 2002 by Nicolas Niclausse %%%---------------------------------------------------------------------- %%% %%% This file is part of Manderlbot. %%% %%% Manderlbot is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%% Manderlbot is distributed in the hope that it will be useful, %%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %%% GNU General Public License for more details. %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%% %%%---------------------------------------------------------------------- -module(mdb_search). -author('nico@niclux.org'). -revision(' $Id$ '). -vsn(' $Revision$ '). %%-compile(export_all). %%-export([Function/Arity, ...]). -behaviour(gen_server). %% External exports -export([start_link/1]). -export([start_link/0]). -export([say_slow/5]). -export([stop/0, search/1]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2]). -export([code_change/3]). -include("mdb.hrl"). -define(tcp_timeout, 10000). % 10sec -define(say_sleep, 2000). % 2sec wait between each line to avoid flooding -define(max_lines, 8). % if more that max_lines to say, say it in private %%%---------------------------------------------------------------------- %%% API %%%---------------------------------------------------------------------- start_link(Args) -> gen_server:start_link({local, ?MODULE}, ?MODULE, Args, []). start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). stop() -> gen_server:cast(?MODULE, {stop}). %% asynchronous search search({Keywords, Input, BotPid, BotName, Channel, Params}) -> gen_server:cast(?MODULE, {search, Keywords, Input, BotPid, BotName, Channel, Params}). %%%---------------------------------------------------------------------- %%% Callback functions from gen_server %%%---------------------------------------------------------------------- %%---------------------------------------------------------------------- %% Func: init/1 %% Returns: {ok, State} | %% {ok, State, Timeout} | %% ignore | %% {stop, Reason} %%---------------------------------------------------------------------- init(Args) -> {ok, #search_state{}}. %%---------------------------------------------------------------------- %% Func: handle_call/3 %% Returns: {reply, Reply, State} | %% {reply, Reply, State, Timeout} | %% {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, Reply, State} | (terminate/2 is called) %% {stop, Reason, State} (terminate/2 is called) %%---------------------------------------------------------------------- handle_call(Args, From, State) -> {noreply, State}. %%---------------------------------------------------------------------- %% Func: handle_cast/2 %% Returns: {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} (terminate/2 is called) %%---------------------------------------------------------------------- handle_cast({search, Keywords, Input, BotPid, BotName, Channel, Params}, State) -> case gen_tcp:connect(Params#search_param.server, Params#search_param.port, [list, {packet, line}, {active, true}], ?tcp_timeout) of {ok, Socket} -> Request = apply(Params#search_param.type, set_request, [Keywords]), gen_tcp:send(Socket, Request), %% the request is identified by the Socket {noreply, State#search_state{requests=[{Socket, Input, BotPid, BotName, Channel, Params#search_param.type, []} | State#search_state.requests]}}; {error, Reason} -> say(Input, BotName, [atom_to_list(Params#search_param.type)++" connection failed"], BotPid, Channel), {noreply, State} end; handle_cast({stop}, State) -> {stop, normal, State}. %%---------------------------------------------------------------------- %% Func: handle_info/2 %% Returns: {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} (terminate/2 is called) %%---------------------------------------------------------------------- handle_info({tcp, Socket, Data}, State) -> case lists:keysearch(Socket, 1 , State#search_state.requests) of {value, {Socket, Input, BotPid, BotName, Channel, Type, Buffer}} -> case apply(Type, parse, [Data]) of {stop, Result} -> %% stop this connection and say result NewState = remove(Socket, State), say(Input, BotName, Buffer ++ [Result], BotPid, Channel), {noreply, NewState}; {continue, Result} -> %% continue and push string in buffer NewRequests = lists:keyreplace(Socket, 1, State#search_state.requests, {Socket, Input, BotPid, BotName, Channel, Type, Buffer ++ [Result]}), {noreply, State#search_state{requests= NewRequests}}; {say, Result} -> %% say result and continue to read data say(Input, BotName, Buffer ++ [Result], BotPid, Channel), {noreply, State}; {continue} -> %% continue to read {noreply, State}; {stop} -> %% close connection say(Input, BotName, Buffer, BotPid, Channel), NewState = remove(Socket, State), {noreply, NewState} end; _ -> {noreply, State} end; handle_info({tcp_einval, Socket}, State) -> {noreply, State}; handle_info({tcp_error, Socket}, State) -> NewState = remove(Socket, State), {noreply, NewState}; handle_info({tcp_closed, Socket}, State) -> NewState = remove(Socket, State), {noreply, NewState}. %%---------------------------------------------------------------------- %% Func: terminate/2 %% Purpose: Shutdown the server %% Returns: any (ignored by gen_server) %%---------------------------------------------------------------------- terminate(Reason, State) -> ok. %%---------------------------------------------------------------------- %% Func: code_change/3 %%---------------------------------------------------------------------- code_change(OldVsn, State, Extra) -> {ok, State}. %%%---------------------------------------------------------------------- %%% Internal functions %%%---------------------------------------------------------------------- %%---------------------------------------------------------------------- %% Func: say/4 %% Purpose: say a string to chan or to private %%---------------------------------------------------------------------- say(Input, BotName, [], BotPid, Channel) -> empty; %% list of strings to say in private, use mdb_bhv_say behaviour say(Input = #data{header_to=BotName}, BotName, Data, BotPid, Channel) -> spawn_link(?MODULE, say_slow, [Input, BotName, Data, BotPid, Channel]); %%% too much lines, talk in private say(Input, BotName, Data, BotPid, Channel) when length(Data) > ?max_lines -> %% set header_to to say it in private mdb_bot:say(BotPid, "answer in private"), %% spawn a new process to talk in private, with a sleep between each line spawn_link(?MODULE, say_slow, [Input#data{header_to=BotName}, BotName, Data, BotPid, Channel]); %%% talk in the channel say(Input, BotName, Data, BotPid, Channel) -> mdb_bhv_say:behaviour(Input, BotName, Data, BotPid, Channel). %%---------------------------------------------------------------------- %% Func: say_slow/4 %% Purpose: say a list of string with sleep intervals %%---------------------------------------------------------------------- say_slow(Input, BotName, [], BotPid, Channel) -> empty; say_slow(Input, BotName, [String | Data], BotPid, Channel) -> mdb_bhv_say:behaviour(Input, BotName, [String], BotPid, Channel), timer:sleep(?say_sleep), say_slow(Input, BotName, Data, BotPid, Channel). %%---------------------------------------------------------------------- %% Func: remove/2 %% Purpose: remove (and close) Socket entry if found in requests list %% Returns: new state %%---------------------------------------------------------------------- remove(Socket, State) -> gen_tcp:close(Socket), NewList = lists:keydelete(Socket, 1, State#search_state.requests), State#search_state{requests = NewList}. manderlbot-manderlbot-0.9.3/src/misc_tools.erl000066400000000000000000000166041124273741000214550ustar00rootroot00000000000000%%%---------------------------------------------------------------------- %%% File : misc_tools.erl %%% Author : Mickael Remond %%% Purpose : This module gather various generic functions %%% we used for Manderlbot developpment %%% Created : 16 Nov 2000, Mickael Remond %%% %%%---------------------------------------------------------------------- %%% %%% This program is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by %%% the Free Software Foundation; either version 2 of the License, or %%% (at your option) any later version. %%% %%%---------------------------------------------------------------------- %%% %%% See LICENSE for detailled license %%% %%% In addition, as a special exception, you have the permission to %%% link the code of this program with any library released under %%% the EPL license and distribute linked combinations including %%% the two. If you modify this file, you may extend this exception %%% to your version of the file, but you are not obligated to do %%% so. If you do not wish to do so, delete this exception %%% statement from your version. %%% %%%---------------------------------------------------------------------- -module(misc_tools). -author('mickael.remond@erlang-fr.org'). -created('Date: 20001116'). -revision(' $Revision$ '). -vsn(' $Id$ '). -export([nth/2, regexpize/1, date_to_integer/1, date_to_string/2, join/2, last_event/1, lower_string/1, upper_string/1, downcase/1, is_matching_regexp/2, is_matching_regexp/3]). -include("log.hrl"). %%---------------------------------------------------------------------- %% Function: nth/2 %% Purpose: Returns the element of a list according to its position %% Args: N = element position %% List = list to extract the element from %% Returns: The requested element %% or "" if the requested element does not exist %%---------------------------------------------------------------------- nth(N,List) when N > length(List) -> ""; nth(N, List) when N =< length(List) -> lists:nth(N, List). %%--------------------------------------------------------------------- %% Utility fonction : regexpize %% arg : a token in caps (ex DATE) %% return : a regexp allowing any combination of uppercase/lowercase %% for example : DATE gives [Dd][Aa][Tt][Ee] %% -------------------------------------------------------------------- regexpize(Token) when list(Token) -> %% This fonction transform the element "E" for example to %% "[Ee]" F = fun(Element) -> "["++ [Element] ++ [lower_char(Element)] ++ "]" end, %% Convert all the token using this function lists:flatmap(F, Token). %%-------------------------------------------------------------------- %% lower_char/1 %% It seems there isn't a lower/upper function in stdlib, so here's a %% quick hack, using specific ASCII charset %% FIXME : maybe not portable %%-------------------------------------------------------------------- lower_char(Char) when Char >= $A, Char =< $Z -> Char + 32 ; lower_char(OtherChar) -> OtherChar. %%---------------------------------------------------------------------- %% Function: lower_string/1 %% Purpose: Convert a string to lower case. %% It seems there isn't a lower/upper function in stdlib, so here it is %% Args: String is an erlang string. %% Returns: A string %%---------------------------------------------------------------------- lower_string(String) -> lower_string(String, []). lower_string([], Acc) -> lists:reverse(Acc); lower_string([H|T], Acc) when H >= $A, H =< $Z -> LowerChar = H + 32, lower_string(T, [LowerChar|Acc]); lower_string([H|T], Acc) -> lower_string(T, [H|Acc]). %%---------------------------------------------------------------------- %% Function: upper_string/1 %% Purpose: Convert a string to upper case. %% Args: String is an erlang string. %% Returns: A string %%---------------------------------------------------------------------- upper_string(String) -> upper_string(String, []). upper_string([], Acc) -> lists:reverse(Acc); upper_string([H|T], Acc) when H >= $a, H =< $z -> UpperChar = H - 32, upper_string(T, [UpperChar|Acc]); upper_string([H|T], Acc) -> upper_string(T, [H|Acc]). %%-------------------------------------------------------------------- %% date_to_integer/1 %% Converts a date to an Integer %%-------------------------------------------------------------------- date_to_integer({}) -> 0; date_to_integer({Date,Time}) -> {Year, Month, Day} = Date, {Hour, Minute, Second} = Time, Second + (Minute * 100) + (Hour * 10000) + (Day * 1000000) + (Month * 100000000) + (Year * 10000000000). %%-------------------------------------------------------------------- %% date_to_string/2 %% Converts a date into an English string %%-------------------------------------------------------------------- date_to_string(_Language, {}) -> ""; date_to_string(en, {Date, Time}) -> {Year, Month, Day} = Date, {Hour, Minute, Second} = Time, integer_to_list(Year) ++ "-" ++ integer_to_list(Month) ++ "-" ++ integer_to_list(Day) ++ " " ++ integer_to_list(Hour) ++ ":" ++ integer_to_list(Minute) ++ ":" ++ integer_to_list(Second). %%-------------------------------------------------------------------- %% last_event/1 %% TODO: Rewrite it to make it more generic and pass it to misc_tools. %% Return the last event from a given list of events: %% Events are of the form: %% {eventname, Date} %% Return the eventname of the latest event. %%-------------------------------------------------------------------- last_event(Events) -> last_event(Events, {none, {{0,0,0}, {0,0,0}}}). last_event([], LastEvent)-> LastEvent; last_event([Event|Events], LastEvent) -> {EventName, Date} = Event, {LastEventName, LastDate} = LastEvent, DateInt = date_to_integer(Date), LastDateInt = date_to_integer(LastDate), case DateInt > LastDateInt of true -> last_event(Events, Event); false -> last_event(Events, LastEvent) end. %% A Perl-style join --- concatenates all strings in Strings, %% separated by Sep. join(Sep, []) -> []; join(Sep, [First | List]) -> lists:foldl(fun(X, Sum) -> X ++ Sep ++ Sum end, First, List). %%---------------------------------------------------------------------- %% downcase/1 %% All upper cars of the String will be down cased %%---------------------------------------------------------------------- downcase(String) -> lists:map(fun(X) when $A =< X, X =< $Z -> X + $a - $A; (X) -> X end, String). %%---------------------------------------------------------------------- %% is_matching_regexp/2 %% is_matching_regexp/3 %% Check the match based on a regexp expression %% Here again you can pass in arguments the true and false values to be %% used. %%---------------------------------------------------------------------- is_matching_regexp(String, Regexp) -> is_matching_regexp(String, Regexp, {true, false}). is_matching_regexp(String, Regexp, {True, False}) -> mdb_logger:debug("is_matching_regexp: ~p ~p~n", [String, Regexp]), case regexp:match(misc_tools:downcase(String), misc_tools:downcase(Regexp)) of {match, _Start, _Length} -> True; nomatch -> False; {error, Error} -> False end. manderlbot-manderlbot-0.9.3/vsn.mk000066400000000000000000000000061124273741000171330ustar00rootroot000000000000000.9.3