Initial Layout
authorMarkus Bröker <mbroeker@largo.dyndns.tv>
Sat, 13 Dec 2008 15:27:30 +0100
changeset 0 586472add385
child 1 5d249c79842d
Initial Layout committer: Markus Bröker <mbroeker@largo.homelinux.org>
INSTALL
TODO
config/.mcbotrc
config/.screenrc
debian/changelog
debian/compat
debian/control
debian/copyright
debian/dirs
debian/docs
debian/postinst
debian/postrm
debian/preinst
debian/rules
include/config.h
include/database.h
include/irc.h
include/mcbot.h
locale/de/LC_MESSAGES/.keep
locale/de/mcbot.po
scripts/mcbot.cgi
scripts/runbot
src/CMakeLists.txt
src/config.c
src/database.c
src/dbtool.c
src/irc.c
src/main.c
src/parse.c
new file mode 100644
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,24 @@
+MCBOT INSTALLATION
+------------------
+
+STEP 1)
+  REGISTER YOUR BOT TO AN IRC SERVER
+  EDIT /var/lib/nobody/.mcbotrc 
+  
+STEP 2)
+  FIX PERMISSIONS AND HIDE YOUR REGISTRATION DATA
+  chown -R nobody:nogroup /var/lib/nobody
+  chmod 775 /var/lib/nobody
+  chmod 600 /var/lib/nobody/.mcbotrc
+
+STEP 3)
+  /etc/init.d/mcbot start
+
+STEP 4)
+	dbtool -a -k mcbot.cgi -v http://your.domain.com/cgi-bin/mcbot.cgi
+	dbtool -a -k mcbot.user -v <admin nick>         # mbroeker
+	dbtool -a -k mcbot.email -v <admin-hostmask>    # pppool.de
+
+STEP 5)
+	Check your locale settings in /etc/init.d/mcbot
+	LANGUAGE="de_DE.UTF-8" or LANGUAGE="en_US.UTF-8" for example
new file mode 100644
--- /dev/null
+++ b/TODO
@@ -0,0 +1,18 @@
+#
+# Project : mcbot
+#
+
+Known Bugs:
+	* no known bugs :)
+	* PRIVMSG for n=some@unaffiliated/users
+
+Todo:
+	* UTF-8 aware Character-Encoding
+	* Dynamic Loading of plugins with dlopen
+	* implementation of some fun stuff  
+
+Author:
+	* Markus Broeker mbroeker@largo.homelinux.org
+	
+Comments:
+	* scanner/parser rewritten
new file mode 100644
--- /dev/null
+++ b/config/.mcbotrc
@@ -0,0 +1,10 @@
+#
+# This is a simple ~/.mcbotrc
+# NO SPACING, PLEASE !!
+#
+NICK:test
+PASSWORD:test
+SERVER:irc.freenode.net
+PORT:6667
+CHANNEL:#test
+TOPIC:[:test:] Support Channel || ENTER !help for help || Source: http://largo.homelinux.org/svn/c/mcbot/trunk
new file mode 100644
--- /dev/null
+++ b/config/.screenrc
@@ -0,0 +1,1 @@
+termcapinfo xterm|xterms|xs|rxvt ti@te@
new file mode 100644
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,9 @@
+mcbot (0.93-2) unstable; urgency=low
+
+  * Initial Release
+  * the location of mcbot.cgi is stored in the db
+  * never include malloc, use stdlib instead
+  * mcbot.email and mcbot.user holds the admin information
+  * Locale Settings changed to C
+
+ -- Markus Broeker <mbroeker@largo.homelinux.org>  Sun, 27 Apr 2008 09:05:54 +0200
new file mode 100644
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1,1 @@
+5
new file mode 100644
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,12 @@
+Source: mcbot
+Section: net
+Priority: extra
+Maintainer: Markus Broeker <mbroeker@largo.homelinux.org>
+Build-Depends: debhelper (>= 5)
+Standards-Version: 3.7.2
+
+Package: mcbot
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: mcbot is an irc bot
+ mcbot is a small irc bot with a factoids database.
new file mode 100644
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,22 @@
+This package was debianized by Markus Broeker <mbroeker@largo.homelinux.org> on
+Tue, 25 Mar 2008 20:32:44 +0100.
+
+It was downloaded from http://largo.homelinux.org
+
+Upstream Author(s): 
+
+	mbroeker@largo.homelinux.org
+
+Copyright: 
+
+	mbroeker@largo.homelinux.org
+
+License:
+
+    GPL
+
+The Debian packaging is (C) 2008, Markus Broeker <mbroeker@largo.homelinux.org> and
+is licensed under the GPL, see `/usr/share/common-licenses/GPL'.
+
+# Please also look if there are files or directories which have a
+# different copyright/license attached and list them here.
new file mode 100644
--- /dev/null
+++ b/debian/dirs
@@ -0,0 +1,2 @@
+var/lib/nobody/data
+var/lib/nobody
new file mode 100644
--- /dev/null
+++ b/debian/docs
@@ -0,0 +1,1 @@
+TODO
new file mode 100644
--- /dev/null
+++ b/debian/postinst
@@ -0,0 +1,57 @@
+#!/bin/sh
+# postinst script for mcbot
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+#        * <postinst> `configure' <most-recently-configured-version>
+#        * <old-postinst> `abort-upgrade' <new version>
+#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>
+#          <new-version>
+#        * <postinst> `abort-remove'
+#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
+#          <failed-install-package> <version> `removing'
+#          <conflicting-package> <version>
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+    configure)
+	if [ ! -f /var/lib/nobody/data/mcbot.dat ];
+	then		
+		echo "Creating initial database in /var/lib/nobody/data";
+		dbtool -a -k 1 -v 1;
+		dbtool -d 1;
+	fi
+
+	if [ -f /var/lib/nobody/.mcbotrc.dpkg-old ];
+	then
+		mv -f /var/lib/nobody/.mcbotrc.dpkg-old /var/lib/nobody/.mcbotrc;
+	fi
+
+	echo "Changing ownership in /var/lib/nobody"
+	usermod -s /bin/bash -d /var/lib/nobody nobody
+	chown -R nobody:nogroup /var/lib/nobody
+	echo "Setting permissions for /var/lib/nobody/.mcbotrc to 600"
+	chmod 600 /var/lib/nobody/.mcbotrc
+	echo "ENTER /etc/init.d/mcbot start after editing .mcbotrc"
+    ;;
+
+    abort-upgrade|abort-remove|abort-deconfigure)
+    ;;
+
+    *)
+        echo "postinst called with unknown argument \`$1'" >&2
+        exit 1
+    ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
new file mode 100644
--- /dev/null
+++ b/debian/postrm
@@ -0,0 +1,47 @@
+#!/bin/sh
+# postrm script for mcbot
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+#        * <postrm> `remove'
+#        * <postrm> `purge'
+#        * <old-postrm> `upgrade' <new-version>
+#        * <new-postrm> `failed-upgrade' <old-version>
+#        * <new-postrm> `abort-install'
+#        * <new-postrm> `abort-install' <old-version>
+#        * <new-postrm> `abort-upgrade' <old-version>
+#        * <disappearer's-postrm> `disappear' <overwriter>
+#          <overwriter-version>
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+    purge)
+	rm -rf /var/lib/nobody/data;
+	rm -f /var/lib/nobody/.mcbotrc;
+	rm -f /var/lib/nobody/mcbot-*.log;
+	usermod -d /nonexistent -s /bin/bash nobody
+    ;;
+    
+    remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
+	usermod -d /nonexistent -s /bin/bash nobody
+	;;
+	
+    *)
+        echo "postrm called with unknown argument \`$1'" >&2
+        exit 1
+    ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
+
+
new file mode 100644
--- /dev/null
+++ b/debian/preinst
@@ -0,0 +1,46 @@
+#!/bin/sh
+# preinst script for mcbot
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+#        * <new-preinst> `install'
+#        * <new-preinst> `install' <old-version>
+#        * <new-preinst> `upgrade' <old-version>
+#        * <old-preinst> `abort-upgrade' <new-version>
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+    install|upgrade)
+	if [ -x /etc/init.d/mcbot ]; 
+	then
+		/etc/init.d/mcbot stop;
+	fi
+
+	if [ -f /var/lib/nobody/.mcbotrc ]; 
+	then
+		cp -f /var/lib/nobody/.mcbotrc /var/lib/nobody/.mcbotrc.dpkg-old
+	fi
+    ;;
+
+    abort-upgrade)
+    ;;
+
+    *)
+        echo "preinst called with unknown argument \`$1'" >&2
+        exit 1
+    ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
+
+
new file mode 100755
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,91 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+
+
+
+configure: configure-stamp
+configure-stamp:
+	dh_testdir
+	# Add here commands to configure the package.
+
+	cmake src/
+	touch configure-stamp
+
+
+build: build-stamp
+
+build-stamp: configure-stamp 
+	dh_testdir
+
+	# Add here commands to compile the package.
+	$(MAKE)
+	#docbook-to-man debian/mcbot.sgml > mcbot.1
+
+	touch $@
+
+clean:
+	dh_testdir
+	dh_testroot
+	rm -f build-stamp configure-stamp
+
+	# Add here commands to clean up after the build process.
+	if [ -f Makefile ]; then $(MAKE) clean; fi
+	rm -rf Makefile CMake* install* mcbot dbtool cmake_install.cmake
+	dh_clean 
+
+install: build
+	dh_testdir
+	dh_testroot
+	dh_clean -k 
+	dh_installdirs
+
+	# Add here commands to install the package into debian/mcbot.
+	$(MAKE) DESTDIR=$(CURDIR)/debian/mcbot install
+	cp config/.mcbotrc debian/mcbot/var/lib/nobody/
+
+# Build architecture-independent files here.
+binary-indep: build install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+	dh_testdir
+	dh_testroot
+	dh_installchangelogs 
+	dh_installdocs
+	dh_installexamples
+#	dh_install
+#	dh_installmenu
+#	dh_installdebconf	
+#	dh_installlogrotate
+#	dh_installemacsen
+#	dh_installpam
+#	dh_installmime
+#	dh_python
+#	dh_installinit
+#	dh_installcron
+#	dh_installinfo
+	dh_installman
+	dh_link
+	dh_strip
+	dh_compress
+	dh_fixperms
+#	dh_perl
+#	dh_makeshlibs
+	dh_installdeb
+	dh_shlibdeps
+	dh_gencontrol
+	dh_md5sums
+	dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install configure
new file mode 100644
--- /dev/null
+++ b/include/config.h
@@ -0,0 +1,23 @@
+/**
+ *  $Id: config.h 51 2008-01-10 00:19:39Z mbroeker $
+ * $URL: http://localhost/svn/c/mcbot/trunk/include/config.h $
+ *
+ */
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+struct UserConfig {
+    char *nick;
+    char *pass;
+    char *server;
+    int port;
+    char *topic;
+    char *channel;
+};
+
+typedef struct UserConfig UC;
+
+int config (UC *, char *);
+
+#endif
new file mode 100644
--- /dev/null
+++ b/include/database.h
@@ -0,0 +1,16 @@
+/**
+ *  $Id: database.h 46 2008-01-09 23:59:17Z mbroeker $
+ * $URL: http://localhost/svn/c/mcbot/trunk/include/database.h $
+ *
+ */
+
+#ifndef DATABASE_H
+#define DATABASE_H
+
+char *db_insert (char *, char *, char *, int);
+char *db_remove (char *, char *);
+char *db_lookup (char *, char *);
+char *db_list (char *);
+char *db_elements (char *);
+char *db_vaccuum (char *);
+#endif
new file mode 100644
--- /dev/null
+++ b/include/irc.h
@@ -0,0 +1,29 @@
+/**
+ *  $Id: irc.h 51 2008-01-10 00:19:39Z mbroeker $
+ * $URL: http://localhost/svn/c/mcbot/trunk/include/irc.h $
+ *
+ */
+
+#ifndef IRC_H
+#define IRC_H
+
+#define IRC_GENERAL_ERROR -50
+#define   IRC_LOGIN_ERROR -51
+#define IRC_CONNECT_ERROR -52
+
+struct Message {
+    FILE *stream;
+    char *nick;
+    char *user;
+    char *email;
+    char *command;
+    char *channel;
+    char *line;
+};
+
+typedef struct Message MSG;
+
+FILE *irc_connect (char *, unsigned int);
+int irc_login (FILE *, char *, char *);
+char *irc_parsemessage (const char *, MSG *);
+#endif
new file mode 100644
--- /dev/null
+++ b/include/mcbot.h
@@ -0,0 +1,19 @@
+/**
+ *  $Id: mcbot.h 46 2008-01-09 23:59:17Z mbroeker $
+ * $URL: http://localhost/svn/c/mcbot/trunk/include/mcbot.h $
+ *
+ */
+
+#ifndef MCBOT_H
+#define MCBOT_H
+
+#ifndef VERSION
+#define VERSION 0.0
+#endif
+
+#ifndef IRC_H
+#include <irc.h>
+#endif
+
+char *parse (MSG *, short *);
+#endif
new file mode 100644
new file mode 100644
--- /dev/null
+++ b/locale/de/mcbot.po
@@ -0,0 +1,57 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-12-26 15:44+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Markus Broeker <mbroeker@largo.homelinux.org>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: parse.c:78
+msgid "Request cannot be performed"
+msgstr "Operation kann nicht durchgefuehrt werden"
+
+#: parse.c:94
+msgid "What's up"
+msgstr "Was ist los"
+
+#: parse.c:149
+msgid "I need more parameters to add"
+msgstr "Ich brauche zwei Parameter zum Anfuegen"
+
+#: parse.c:164
+msgid "I need more parameters to replace"
+msgstr "Ich brauche zwei Parameter zum Ersetzen"
+
+#: parse.c:177
+msgid "I need a key to delete"
+msgstr "Ich brauche einen Schluessel zum Loeschen"
+
+#: parse.c:195
+msgid "I need a key to lookup"
+msgstr "Ich brauche einen Parameter zum Aufsuchen"
+
+#: parse.c:214
+msgid "Autolearn enabled for channel"
+msgstr "Autolearn ist aktiviert im Channel"
+
+#: parse.c:220
+msgid "Autolearn disabled for channel"
+msgstr "Autolearn ist deaktiviert im Channel"
+
+#: parse.c:240
+msgid "Bye, have a nice day!"
+msgstr "Machts gut, ich brauch ne Pause!"
+
+#: parse.c:268
+msgid "It is"
+msgstr "Es ist"
new file mode 100755
--- /dev/null
+++ b/scripts/mcbot.cgi
@@ -0,0 +1,32 @@
+#!/usr/bin/perl -W
+
+use strict;
+
+my $line;
+my $a;
+my $b;
+
+print "CONTENT-TYPE: text/html\n\n";
+
+print "<html>\n\t<head>\n\t\t<title>Factoids</title>\n\t</head>\n<body>\n";
+open(FD, "dbtool -l |") or die("Cannot open file");
+
+foreach $line(<FD>) {
+	($a, $b) = split(/:/, $line, 2);
+	$a =~ s/^[\t ]+//;					# skip blanks
+	$b =~ s/^[\t ]+//;					# skip blanks
+	$b =~ s/[\n]+//;					# for html source :)
+
+	if ($b) {
+		if($b =~ /^http/ ) {
+			print "$a - <a href=\"$b\">$b</a><br>";
+		} else {
+			print "$a - $b<br>";
+		}
+	}
+}
+
+print "\n<br>$a\n";
+
+print "</body></html>\n";
+close(FD);
new file mode 100755
--- /dev/null
+++ b/scripts/runbot
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+BINARY="mcbot"
+DIRECTORY="/usr/local/sbin/"
+LANGUAGE="de_DE.UTF-8"
+
+[[ ! -x "${DIRECTORY}/${BINARY}" ]] && exit 0
+
+start() {
+	echo -n "Starting ${BINARY}"
+	su - nobody -c "LANG=$LANGUAGE ${DIRECTORY}/${BINARY} &>/var/lib/nobody/mcbot-`date "+%d-%m-%y"`.log &"
+	if [ "$?" == 0 ]; then
+		echo " [started]"
+	fi
+}
+
+stop() {
+	echo -n "Stopping ${BINARY}"
+	pid=`pidof ${BINARY}`
+	if [ "$pid" != "" ]; then
+		kill -TERM `pidof ${BINARY}`
+		sleep 5
+	fi
+	echo " [stopped]"
+}
+
+status() {
+	pid="`pidof ${BINARY}`"
+	if [ "$pid" != "" ]; then
+		echo "${BINARY} is started as ${pid}"
+	else
+		echo "${BINARY} is not running"
+	fi
+}
+
+case "$1" in
+	start)
+		start
+	;;
+	stop)
+		stop
+	;;
+	status)
+		status
+	;;
+	restart)
+		echo "Restarting ${BINARY}"
+		stop
+		start
+	;;
+	*)
+		echo "Usage: start|stop|restart|status"
+	;;
+esac
+
+exit 0
new file mode 100644
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,37 @@
+PROJECT(mc_bot)
+
+# Project Settings
+SET(CMAKE_VERBOSE_MAKEFILE Off)
+SET(CMAKE_BUILD_TYPE Release)
+SET(CMAKE_C_FLAGS_RELEASE "-g -ggdb")
+
+# C-Definitions
+ADD_DEFINITIONS(-Wall -O2 -ansi -pedantic)
+ADD_DEFINITIONS(-D_XOPEN_SOURCE=500)
+ADD_DEFINITIONS(-DVERSION=0.91)
+
+# Includes
+INCLUDE_DIRECTORIES(../include)
+
+# Target Definitions
+ADD_EXECUTABLE(mcbot config.c database.c irc.c main.c parse.c)
+ADD_EXECUTABLE(dbtool database.c dbtool.c)
+
+# Install Rules
+INSTALL(TARGETS mcbot RUNTIME DESTINATION sbin)
+INSTALL(TARGETS dbtool RUNTIME DESTINATION bin)
+INSTALL(DIRECTORY ../locale/ DESTINATION /var/lib/nobody/data/locale)
+INSTALL(PROGRAMS ../scripts/runbot DESTINATION /etc/init.d/ 
+	RENAME mcbot)
+
+EXEC_PROGRAM(msgfmt ../locale ARGS -o de/LC_MESSAGES/mcbot.mo de/mcbot.po)
+
+# Search required libraries
+FIND_LIBRARY(GDBM_LIB NAMES gdbm
+	PATHS /usr/lib/ /usr/local/lib)
+IF (GDBM_LIB)
+	TARGET_LINK_LIBRARIES(mcbot ${GDBM_LIB})
+	TARGET_LINK_LIBRARIES(dbtool ${GDBM_LIB})
+ELSE(GDBM_LIB)
+	MESSAGE("YOU NEED TO INSTALL libgdbm-dev")
+ENDIF (GDBM_LIB)
new file mode 100644
--- /dev/null
+++ b/src/config.c
@@ -0,0 +1,110 @@
+/**
+ *  $Id: config.c 51 2008-01-10 00:19:39Z mbroeker $
+ * $URL: http://localhost/svn/c/mcbot/trunk/src/config.c $
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <config.h>
+
+const
+char *CONFIG_OPTIONS[] = {
+    "NICK", "PASSWORD", "SERVER", "PORT",
+    "CHANNEL", "TOPIC",
+    NULL
+};
+
+int config (UC * uc, char *fname)
+{
+    FILE *f;
+    char buffer[513];
+    static char **line;
+    char *token;
+    char *value;
+    int i = 0;
+
+    if ((f = fopen (fname, "r")) == NULL)
+        return -1;
+
+    while (CONFIG_OPTIONS[i] != NULL)
+        i++;
+
+    line = calloc (i, sizeof (char *));
+
+    /*
+     * We can easily provide default values ...
+     */
+    uc->nick = uc->pass = uc->server = uc->channel = uc->topic = 0;
+    uc->port = 6667;
+
+    fgets (buffer, 512, f);
+
+    token = buffer;
+
+    while (!feof (f)) {
+        /*
+         * eat trailing tabs
+         */
+        while (*token == '\t')
+            token++;
+
+        /*
+         * eat trailing whitespaces
+         */
+        while (*token == ' ')
+            token++;
+
+        token = strtok (token, ":");
+
+        if (token != NULL) {
+            value = strtok (NULL, "\n");
+            i = 0;
+            while (CONFIG_OPTIONS[i] != NULL) {
+                if (!strcmp (token, CONFIG_OPTIONS[i])) {
+                    line[i] = malloc (strlen (value) + 1);
+                    strncpy (line[i], value, strlen (value));
+                }
+                i++;
+            }
+        }
+        *buffer = 0;
+        fgets (buffer, 512, f);
+    }
+
+    if (fclose (f) != 0)
+        return -1;
+
+    i = 0;
+    while (CONFIG_OPTIONS[i] != NULL) {
+        if (line[i] != NULL)
+            switch (i) {
+            case 0:            /* NICK */
+                uc->nick = line[i];
+                break;
+            case 1:            /* PASSWORD */
+                uc->pass = line[i];
+                break;
+            case 2:            /* SERVER */
+                uc->server = line[i];
+                break;
+            case 3:            /* PORT */
+                uc->port = atoi (line[i]);
+                break;
+            case 4:            /* CHANNEL */
+                uc->channel = line[i];
+                break;
+            case 5:            /* TOPIC */
+                uc->topic = line[i];
+                break;
+            }
+        i++;
+    }
+
+    if (!(uc->nick && uc->pass && uc->server && uc->channel))
+        return -2;
+
+    return 0;
+}
new file mode 100644
--- /dev/null
+++ b/src/database.c
@@ -0,0 +1,150 @@
+/**
+ *  $Id: database.c 108 2008-04-17 01:01:52Z mbroeker $
+ * $URL: http://localhost/svn/c/mcbot/trunk/src/database.c $
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gdbm.h>
+
+#include <database.h>
+
+char *db_insert (char *file_name, char *name, char *msg, int mode)
+{
+    GDBM_FILE dbf;
+    datum key;
+    datum content;
+    int ret;
+
+    if ((dbf = gdbm_open (file_name, 512, GDBM_WRCREAT, 0644, 0)) == NULL)
+        return "db_insert error";
+
+    key.dptr = name;
+    key.dsize = strlen (name) + 1;
+
+    content.dptr = msg;
+    content.dsize = strlen (msg) + 1;
+
+    if (mode)
+        ret = gdbm_store (dbf, key, content, GDBM_REPLACE);
+    else
+        ret = gdbm_store (dbf, key, content, GDBM_INSERT);
+
+    gdbm_close (dbf);
+
+    if (!ret)
+        return "Key added";
+
+    return "error: key not added";
+}
+
+char *db_remove (char *file_name, char *name)
+{
+    GDBM_FILE dbf;
+    datum key;
+    int ret;
+
+    if ((dbf = gdbm_open (file_name, 512, GDBM_WRITER, 0, 0)) == NULL)
+        return "db_remove error";
+
+    key.dptr = name;
+    key.dsize = strlen (name) + 1;
+
+    ret = gdbm_delete (dbf, key);
+
+    gdbm_close (dbf);
+
+    if (!ret)
+        return "Key removed";
+    return "error: key not removed";
+}
+
+char *db_lookup (char *file_name, char *entry)
+{
+    GDBM_FILE dbf;
+    datum content;
+    datum key;
+    static char msg[513];
+
+    if ((dbf = gdbm_open (file_name, 512, GDBM_READER, 0, 0)) == NULL)
+        return "db_lookup error";
+
+    key.dptr = entry;
+    key.dsize = strlen (entry) + 1;
+
+    content = gdbm_fetch (dbf, key);
+    if (content.dptr != NULL)
+        snprintf (msg, 512, "%s", content.dptr);
+    else
+        snprintf (msg, 512, "I haven't heard anything about %s.", entry);
+
+    gdbm_close (dbf);
+    return msg;
+}
+
+char *db_elements (char *file_name)
+{
+    GDBM_FILE dbf;
+    datum key;
+    int count;
+    static char msg[81];
+
+    if ((dbf = gdbm_open (file_name, 512, GDBM_READER, 0, 0)) == NULL)
+        return "db_lookup error";
+
+    key = gdbm_firstkey (dbf);
+
+    count = 0;
+    while (key.dptr != NULL) {
+        key = gdbm_nextkey (dbf, key);
+        count++;
+    }
+
+    gdbm_close (dbf);
+    snprintf (msg, 80, "I am holding %d %s in my database.", count, (count > 0) ? "rows" : "row");
+    return msg;
+}
+
+char *db_list (char *file_name)
+{
+    GDBM_FILE dbf;
+    datum content;
+    datum key;
+    static char msg[81];
+    int count;
+
+    if ((dbf = gdbm_open (file_name, 512, GDBM_READER, 0, 0)) == NULL)
+        return "db_list error";
+
+    key = gdbm_firstkey (dbf);
+
+    count = 0;
+    while (key.dptr) {
+        content = gdbm_fetch (dbf, key);
+        printf ("%11s: %s\n", key.dptr, content.dptr);
+        free (content.dptr);
+        key = gdbm_nextkey (dbf, key);
+        count++;
+    }
+
+    gdbm_close (dbf);
+    snprintf (msg, 80, "I am holding %d %s in my database.", count, (count > 0) ? "rows" : "row");
+    return msg;
+}
+
+char *db_vaccuum (char *file_name)
+{
+    GDBM_FILE dbf;
+    static char msg[81];
+
+    if ((dbf = gdbm_open (file_name, 512, GDBM_WRITER, 0, 0)) == NULL)
+        return "db_vaccuum error";
+
+    gdbm_reorganize (dbf);
+
+    gdbm_close (dbf);
+    snprintf (msg, 80, "I reorganized the database.");
+    return msg;
+}
new file mode 100644
--- /dev/null
+++ b/src/dbtool.c
@@ -0,0 +1,137 @@
+/**
+ *  $Id: dbtool.c 51 2008-01-10 00:19:39Z mbroeker $
+ * $URL: http://localhost/svn/c/mcbot/trunk/src/dbtool.c $
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <database.h>
+
+#ifndef FILE_NAME
+#define FILE_NAME "/var/lib/nobody/data/mcbot.dat"
+#endif
+
+void help (char *prgname)
+{
+    printf ("Usage: %s [[-a|-r] -k <key> -v <value>]\n", prgname);
+    printf ("       %s [-d <key>]\n", prgname);
+    printf ("       %s [-f <file>]\n", prgname);
+    printf ("       %s [-s <key>]\n", prgname);
+    printf ("       %s [-h|-?]\n\n", prgname);
+    printf ("Administration tool for adding/replacing, deleting, ... of DataBase Entries.\n\n");
+    printf ("Options:\n");
+    printf ("  -a\t\tadds a new key <key> with value <value> to the db\n");
+    printf ("  -r\t\treplaces a key <key> with value <value> in the db\n");
+    printf ("  -d\t\tdeletes a <key> from the db\n");
+    printf ("  -f\t\tsets the db file\n");
+    printf ("  -l\t\tlists the db entries\n");
+    printf ("  -s\t\tsearches the db entry <key>\n");
+    printf ("  -V\t\treorganizes the db\n");
+    printf ("  -h\t\tprints this help\n");
+    printf ("  -?\t\tprints this help\n\n");
+    printf ("Report bugs to mbroeker@largo.homelinux.org\n");
+    exit (0);
+}
+
+#define     ADD 1
+#define REPLACE 2
+#define  DELETE 3
+#define  SEARCH 4
+#define    LIST 5
+#define VACCUUM 6
+
+int main (int argc, char **argv)
+{
+    int i;
+    int mode = 0;
+    char *key = NULL;
+    char *value = NULL;
+    char *file_name = NULL;
+
+    while ((i = getopt (argc, argv, "arlVh?d:f:k:s:v:")) > 0) {
+        switch (i) {
+        case '?':
+        case 'h':
+            help (argv[0]);
+            break;
+        case 'a':
+            mode = ADD;
+            break;
+        case 'r':
+            mode = REPLACE;
+            break;
+        case 'd':
+            mode = DELETE;
+            key = optarg;
+            break;
+        case 'f':
+            file_name = optarg;
+            break;
+        case 'k':
+            key = optarg;
+            break;
+        case 's':
+            key = optarg;
+            mode = SEARCH;
+            break;
+        case 'v':
+            value = optarg;
+            break;
+        case 'l':
+            mode = LIST;
+            break;
+        case 'V':
+            mode = VACCUUM;
+            break;
+        default:
+            printf ("Unknown Option %c\n", i);
+        }
+    }
+
+    for (i = optind; i < argc; i++) {
+        printf ("Unknown Parameter: %s\n", argv[i]);
+    }
+
+    if (!file_name)
+        file_name = FILE_NAME;
+
+    switch (mode) {
+    case ADD:
+        if ((key != NULL) && (value != NULL))
+            printf ("%s\n", db_insert (file_name, key, value, 0));
+        else
+            help (argv[0]);
+        break;
+    case REPLACE:
+        if ((key != NULL) && (value != NULL))
+            printf ("%s\n", db_insert (file_name, key, value, 1));
+        else
+            help (argv[0]);
+        break;
+    case DELETE:
+        if (key != NULL)
+            printf ("%s\n", db_remove (file_name, key));
+        else
+            help (argv[0]);
+        break;
+    case SEARCH:
+        if (key != NULL)
+            printf ("%s\n", db_lookup (file_name, key));
+        else
+            help (argv[0]);
+        break;
+    case LIST:
+        printf ("%s\n", db_list (file_name));
+        break;
+    case VACCUUM:
+        printf ("%s\n", db_vaccuum (file_name));
+        break;
+    default:
+        printf ("Nothing to do: Try %s -h\n", argv[0]);
+    }
+
+    return EXIT_SUCCESS;
+}
new file mode 100644
--- /dev/null
+++ b/src/irc.c
@@ -0,0 +1,323 @@
+/**
+ *  $Id: irc.c 51 2008-01-10 00:19:39Z mbroeker $
+ * $URL: http://localhost/svn/c/mcbot/trunk/src/irc.c $
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <pwd.h>
+
+#include <irc.h>
+
+#define VERSION_STRING "MCBOT on GNU/LINUX"
+
+const char *IRC_Commands[] = {
+    "NOTICE", "MODE", "JOIN", "PART",
+    "TOPIC", "PING", "ENOMEM", "ERROR",
+    "VERSION", "PRIVMSG", "QUIT", "NICK",
+    NULL,
+};
+
+FILE *irc_connect (char *server, unsigned int port)
+{
+    struct hostent *he;
+    char *ip;
+    struct sockaddr_in ca;
+    int csocket;
+    FILE *stream;
+
+    he = gethostbyname (server);
+    if (he == NULL) {
+        perror ("GETHOSTBYNAME");
+        return NULL;
+    }
+
+    if ((ip = inet_ntoa (*((struct in_addr *)he->h_addr_list[0]))) == NULL) {
+        perror ("GETHOSTBYNAME");
+        return NULL;
+    } else
+        printf ("IP: %s\n", ip);
+
+    ca.sin_family = AF_INET;
+    ca.sin_addr.s_addr = inet_addr (ip);
+    ca.sin_port = htons (port);
+
+    csocket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
+    if (connect (csocket, (struct sockaddr *)&ca, (socklen_t) sizeof (ca)) == -1) {
+        perror ("CONNECT");
+        return NULL;
+    }
+
+    /*
+     * rw mode,but many seek errors ...
+     */
+    stream = fdopen (csocket, "a+");
+    return stream;
+}
+
+int irc_login (FILE * stream, char *nick, char *password)
+{
+    MSG message;
+    char msg[513];
+    char *user;
+    struct passwd *pwd = NULL;
+
+    if ((user = getenv ("USER")) != NULL)
+        if ((pwd = getpwnam (user)) == NULL)
+            return IRC_GENERAL_ERROR;
+
+    if (strlen (password) == 0)
+        return IRC_LOGIN_ERROR;
+
+    if (stream == NULL)
+        return IRC_GENERAL_ERROR;
+
+    fprintf (stream, "NICK %s\r\n", nick);
+
+    fprintf (stream, "USER %s 0 irc.freenode.net %s\r\n", user, pwd->pw_gecos);
+
+    fprintf (stream, "PRIVMSG NICKSERV :IDENTIFY %s\r\n", password);
+
+    for (;;) {
+        fgets (msg, 512, stream);
+        if ((user = irc_parsemessage (msg, &message)) != NULL)
+            printf ("%10s %s\n", user, message.line);
+
+        if (strstr (msg, "VERSION") != NULL) {
+            printf ("%10s %s", "VERSION", msg);
+            printf ("%10s %s %s :%s\n", "WRITE", message.command, message.user, VERSION_STRING);
+            fprintf (stream, "VERSION :%s\r\n", VERSION_STRING);
+        }
+
+        if (strstr (msg, ":Password accepted") != NULL) {
+            break;
+        }
+
+        if (strstr (msg, ":Password Incorrect") != NULL) {
+            return IRC_LOGIN_ERROR;
+        }
+
+        if (strstr (msg, "ERROR :Closing Link") != NULL) {
+            return IRC_GENERAL_ERROR;
+        }
+
+        if (strstr (msg, "is not registered") != NULL) {
+            return IRC_LOGIN_ERROR;
+        }
+    }
+
+    sleep (2);
+    return 0;
+}
+
+static char *irc_getmessage (const char *line, MSG * message)
+{
+    char *theLine;
+    char *token;
+    char *ptr;
+
+    if ((theLine = strdup (line)) == NULL)
+        return "ENOMEM";
+
+    message->user = message->email = NULL;
+    message->command = NULL;
+    message->channel = message->line = NULL;
+
+    token = strtok (theLine, " ");
+    if (*token != ':') {
+        /*
+         * SERVER MESSAGES
+         */
+        if ((ptr = strtok (NULL, "\r\n")) != NULL)
+            ++ptr;
+        message->line = ptr;
+        return token;
+    }
+
+    message->user = ++token;
+    message->command = strtok (NULL, " ");
+
+    message->line = strtok (NULL, "\r\n");
+
+    return message->command;
+}
+
+/*
+ * Main prints ("%10s %s %s\n", MSG->command MSG->channel MSG->line).
+ * This functions makes sure, that there will be someting to print...
+ */
+
+char *irc_parsemessage (const char *line, MSG * message)
+{
+    int i;
+    char *command;
+    char *ptr;
+    int value;
+
+    i = 0;
+    if ((command = irc_getmessage (line, message)) != NULL) {
+        while (IRC_Commands[i] != NULL) {
+            if (strcmp (IRC_Commands[i], command) == 0) {
+                switch (i) {
+
+                case 0:        /* NOTICE */
+                    if (message->line == NULL) {
+                        message->channel = "*";
+                        message->line = "*";
+                    } else {
+                        message->channel = strtok (message->line, " ");
+                        if ((message->line = strtok (NULL, "\r\n")) != NULL)
+                            ++message->line;
+                    }
+                    return command;
+                case 1:        /* MODE */
+                    message->channel = strtok (message->line, " ");
+                    message->line = strtok (NULL, "\r\n");
+                    return command;
+                case 2:        /* JOIN */
+                case 3:        /* PART */
+                    if ((message->channel = strchr (message->line, ':')))
+                        ++message->channel;
+                    message->line = message->user;
+                    return command;
+                case 4:        /* TOPIC */
+                    message->channel = strtok (message->line, " ");
+                    if ((message->line = strtok (NULL, "\r\n")))
+                        ++message->line;
+                    return command;
+                case 5:        /* PING */
+#ifdef DEBUG
+                    printf ("%10s %s localhost\n", "PING", message->line);
+#endif
+                    fprintf (message->stream, "PONG :%s\r\n", message->line);
+                    message->channel = "localhost";
+#ifdef DEBUG
+                    return "PONG";
+#else
+                    return NULL;
+#endif
+                case 6:        /* ENOMEM */
+                case 7:        /* ERROR */
+                    exit (-1);
+                    break;
+                case 8:        /* VERSION */
+                    if ((ptr = strchr (message->user, ' ')))
+                        *ptr = 0;
+                    return command;
+                case 9:        /* PRIVMSG */
+                    if ((message->email = strchr (message->user, '=')))
+                        ++message->email;
+                    if ((ptr = strchr (message->user, '!')))
+                        *ptr = 0;
+
+                    message->channel = strtok (message->line, " ");
+                    message->line = strtok (NULL, "\r\n");
+                    message->line++;
+                    printf ("%10s %s %s :%s\n", "READ", message->command, message->channel, message->line);
+                    return NULL;
+                case 10:       /* QUIT */
+                    message->channel = message->user;
+                    return command;
+                case 11:       /* NICK */
+                    message->channel = message->user;
+                    return command;
+                }
+            }
+            i++;
+        }
+
+        if ((value = atoi (command)) != 0) {
+            switch (value) {
+            case 1:            /* CONNECTION INFOS */
+            case 2:
+            case 3:
+            case 4:
+            case 5:
+            case 250:
+            case 251:
+            case 252:
+            case 254:
+            case 255:
+            case 265:
+            case 266:
+                /*
+                 * prints as is in irc_login
+                 */
+                return command;
+                break;
+            case 311:
+            case 312:
+            case 315:          /* END OF WHO */
+            case 318:
+                message->channel = strtok (message->line, " ");
+                message->line = strtok (NULL, "\r\n");
+                return command;
+            case 319:
+                message->channel = strtok (message->line, " ");
+                message->line = strtok (NULL, "\r\n");
+                fprintf (message->stream, "PRIVMSG %s :%s\r\n", "#mcbot", message->line);
+                return command;
+            case 320:
+            case 332:          /* TOPIC OF CHANNEL */
+            case 333:          /* NAMES IN CHANNEL */
+                message->channel = strtok (message->line, " ");
+                message->line = strtok (NULL, "\r\n");
+                return command;
+            case 351:          /* SVERSION */
+                message->channel = strtok (message->line, " ");
+                message->line = strtok (NULL, "\r\n");
+                return command;
+            case 352:          /* WHO LIST */
+                message->channel = strtok (message->line, " ");
+                message->line = strtok (NULL, "\r\n");
+                /*
+                 * MORE THAN 3 LINES AND YOU WILL be KICKED
+                 */
+                return command;
+                break;
+            case 353:
+            case 365:
+            case 366:          /* END OF NAMES */
+                message->channel = strtok (message->line, " ");
+                message->line = strtok (NULL, "\r\n");
+                return command;
+                break;
+            case 372:          /* MOTD MESSAGES */
+            case 375:
+            case 376:          /* END OF MOTD */
+                return command;
+                break;
+            case 401:          /* NO SUCH NICK/CHANNEL */
+            case 403:          /* That CHANNEL doesnt exist */
+                return command;
+                break;
+            case 474:
+            case 475:
+            case 476:
+            case 477:
+                message->channel = strtok (message->line, " ");
+                message->line = strtok (NULL, "\r\n");
+                return command;
+                break;
+            default:
+                printf ("DEBUG   %s", line);
+                printf ("Unknown Value: %d\n", value);
+            }
+        }
+        printf ("DEBUG   %s", line);
+        printf ("Unknown Command: %s\n", command);
+        return command;
+    }
+    printf ("DEBUG   %s", line);
+    return NULL;
+}
new file mode 100644
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,135 @@
+/**
+ *  $Id: main.c 51 2008-01-10 00:19:39Z mbroeker $
+ * $URL: http://localhost/svn/c/mcbot/trunk/src/main.c $
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <signal.h>
+#include <locale.h>
+#include <libintl.h>
+
+#include <mcbot.h>
+#include <config.h>
+
+#ifndef CONFIG_FILE
+#define CONFIG_FILE "/var/lib/nobody/.mcbotrc"
+#endif
+
+#ifndef LOCALE_PATH
+#define LOCALE_PATH "/var/lib/nobody/data/locale"
+#endif
+
+short active = 1;
+
+void sigproc ()
+{
+    signal (SIGTERM, sigproc);
+    active = 0;
+}
+
+int main (int argc, char **argv)
+{
+    UC uc;
+    MSG message;
+    char buf[513];
+    char *msg;
+    char *command;
+    int len;
+
+    if (bindtextdomain ("mcbot", LOCALE_PATH) != NULL) {
+        (void)textdomain ("mcbot");
+        (void)setlocale (LC_MESSAGES, "");
+    }
+
+    printf ("mcbot-%1.2f\n", VERSION);
+
+    if ((len = config (&uc, CONFIG_FILE)) != 0) {
+        switch (len) {
+        case -1:
+            printf ("You need to create a config file %s\n", CONFIG_FILE);
+            break;
+        case -2:
+            printf
+                ("You need at least entries for user, password, server and channel in your config file %s\n",
+                 CONFIG_FILE);
+            break;
+        }
+        return len;
+    }
+
+    if (uc.nick)
+        message.nick = uc.nick;
+    else
+        return -1;
+
+    if (!(message.stream = irc_connect (uc.server, uc.port)))
+        return EXIT_FAILURE;
+
+    if ((len = irc_login (message.stream, uc.nick, uc.pass)) != 0) {
+        switch (len) {
+        case IRC_GENERAL_ERROR:
+            printf ("GENERAL ERROR\n");
+            break;
+        case IRC_LOGIN_ERROR:
+            printf ("LOGIN ERROR\n");
+            break;
+        default:
+            printf ("Unknown Error %d\n", len);
+        }
+        return len;
+    }
+
+    signal (SIGTERM, sigproc);
+
+    if (uc.channel) {
+        fprintf (message.stream, "JOIN :%s\r\n", uc.channel);
+        if (uc.topic)
+            fprintf (message.stream, "TOPIC %s :%s\r\n", uc.channel, uc.topic);
+    }
+
+    while (active) {
+        if (fgets (buf, 512, message.stream) == NULL) {
+            active = 0;
+            break;
+        }
+
+        if ((command = irc_parsemessage (buf, &message))) {
+            printf ("%10s %s %s\n", command, message.channel, message.line);
+        } else {
+            if ((msg = parse (&message, &active)) != NULL) {
+                fprintf (message.stream, "%s\r\n", msg);
+                printf ("%10s %s", "WRITE", msg);
+            }
+        }
+        *buf = 0;
+    }
+    printf ("\n\nClosing Connection\n\n");
+    fclose (message.stream);
+
+    /*
+     * cleanup
+     */
+
+    if (uc.nick)
+        free (uc.nick);
+    if (uc.pass)
+        free (uc.pass);
+    if (uc.server)
+        free (uc.server);
+    if (uc.channel)
+        free (uc.channel);
+    if (uc.topic)
+        free (uc.topic);
+
+    return EXIT_SUCCESS;
+}
new file mode 100644
--- /dev/null
+++ b/src/parse.c
@@ -0,0 +1,278 @@
+/**
+ *  $Id: parse.c 153 2008-04-27 07:26:15Z mbroeker $
+ * $URL: http://localhost/svn/c/mcbot/trunk/src/parse.c $
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <mcbot.h>
+#include <database.h>
+
+#include <locale.h>
+#include <libintl.h>
+
+#ifndef DATABASE_FILE
+#define DATABASE_FILE "/var/lib/nobody/data/mcbot.dat"
+#endif
+
+const
+char *COMMAND_LIST[] = {
+    "!help      Known Commands: join(1), leave(2), add(3), replace(4), delete(5), list(6), search(7), info(8)\r\n",
+    "!join:     Joins a new channel\r\n",
+    "!leave:    Parts from the current channel\r\n",
+    "!add:      adds an entry\r\n",
+    "!replace:  replaces an entry\r\n",
+    "!delete:   deletes an entry\r\n",
+    "!list:     lists the number of stored values\r\n",
+    "!search:   searches an entry up\r\n",
+    "!info:     Prints the current Bot-Version\r\n",
+    "!ping:     pings an host\r\n",
+    "!on:       enables autolearning mode\r\n",
+    "!off:      disables autolearning\r\n",
+    "!debug:    prints some debug infos\r\n",
+    "!vaccuum:  reorganizes the database\r\n",
+    "!logout:   Protected logout function\r\n",
+    NULL,
+};
+
+const
+char ITEMS = 14;
+
+const
+char *Bot_Commands[] = {
+    "!help", "!join", "!leave",
+    "!add", "!replace", "!delete",
+    "!list", "!search", "!info",
+    "!ping", "!on", "!off",
+    "!debug", "!vaccuum", "!logout",
+    "!who", "!whois", "!time", "!tell",
+    "!op",
+    NULL,
+};
+
+char *parse (MSG * message, short *active)
+{
+    static char msg[513];
+    int cmd = -1;
+    int i;
+    char *token;
+    char *parameters;
+
+    time_t t;
+    struct tm *timeptr;
+    static int counter = 0;
+
+    /*
+     * default message
+     */
+    snprintf (msg, 512, "PRIVMSG %s :%s.\r\n", message->channel, gettext ("Request cannot be performed"));
+
+    /*
+     * PRIVATE MESSAGES
+     */
+    if (!strcmp (message->channel, message->nick))
+        message->channel = message->user;
+
+    if (strstr (message->line, message->nick)) {
+        if (*message->line != '!') {
+            /*
+             * DEAD - LOCK - CHECK
+             */
+            if (strcmp (message->user, message->nick)) {
+                snprintf (msg, 512, "PRIVMSG %s :%s, %s?\r\n", message->channel, gettext ("What's up"), message->user);
+                if (counter++ > 3)
+                    return NULL;
+                return msg;
+            }
+            /*
+             * DEAD - LOCK - CHECK ENDS
+             */
+        }
+        return NULL;
+    }
+
+    counter = 0;
+
+    /*
+     * NO BOT Commands
+     */
+    if (*message->line != '!') {
+        return NULL;
+    }
+
+    i = 0;
+    token = strtok (message->line, " ");
+    while (Bot_Commands[i]) {
+        if (!strcmp (token, Bot_Commands[i])) {
+            switch (i) {
+            case 0:            /* !help */
+                if ((token = strtok (NULL, "\r\n")))
+                    cmd = atoi (token);
+                if ((cmd > 0) && (cmd < ITEMS))
+                    snprintf (msg, 512, "PRIVMSG %s :%s\r\n", message->channel, COMMAND_LIST[cmd]);
+                else
+                    snprintf (msg, 512, "PRIVMSG %s :%s\r\n", message->channel, COMMAND_LIST[0]);
+                return msg;
+
+            case 1:            /* !join */
+                if ((token = strtok (NULL, "\r\n")))
+                    snprintf (msg, 512, "JOIN %s\r\n", token);
+                return msg;
+
+            case 2:            /* !leave */
+                if (*message->channel != '#')
+                    return NULL;
+                snprintf (msg, 512, "PART %s :Leaving.\r\n", message->channel);
+                return msg;
+
+            case 3:            /* !add */
+                if ((token = strtok (NULL, " "))) {
+                    if ((parameters = strtok (NULL, "\r\n"))) {
+                        snprintf (msg, 512, "PRIVMSG %s :%s, %s\r\n",
+                                  message->channel, message->user, db_insert (DATABASE_FILE, token, parameters, 0));
+                    } else {
+                        snprintf (msg, 512,
+                                  "PRIVMSG %s :%s, %s!\r\n",
+                                  message->channel, gettext ("I need more parameters to add"), message->user);
+                    }
+                }
+                return msg;
+
+            case 4:            /* !replace */
+                if ((token = strtok (NULL, " "))) {
+                    if ((parameters = strtok (NULL, "\r\n"))) {
+                        snprintf (msg, 512, "PRIVMSG %s :%s, %s\r\n",
+                                  message->channel, message->user, db_insert (DATABASE_FILE, token, parameters, 1));
+                    } else {
+                        snprintf (msg, 512,
+                                  "PRIVMSG %s :%s, %s!\r\n",
+                                  message->channel, gettext ("I need more parameters to replace"), message->user);
+                    }
+                }
+                return msg;
+
+            case 5:            /* !delete */
+                if ((token = strtok (NULL, "\r\n"))) {
+                    snprintf (msg, 512, "PRIVMSG %s :%s, %s\r\n",
+                              message->channel, message->user, db_remove (DATABASE_FILE, token));
+                } else {
+                    snprintf (msg, 512,
+                              "PRIVMSG %s :%s, %s!\r\n",
+                              message->channel, gettext ("I need a key to delete"), message->user);
+                }
+                return msg;
+
+            case 6:            /* !count */
+                snprintf (msg, 512, "PRIVMSG %s :%s %s\r\n", message->channel,
+                          db_elements (DATABASE_FILE), db_lookup(DATABASE_FILE, "mcbot.cgi"));
+                return msg;
+
+            case 7:            /* !search */
+                if ((token = strtok (NULL, "\r\n"))) {
+                    snprintf (msg, 512, "PRIVMSG %s :%s, %s\r\n",
+                              message->channel, message->user, db_lookup (DATABASE_FILE, token));
+                } else {
+                    snprintf (msg, 512,
+                              "PRIVMSG %s :%s, %s!\r\n",
+                              message->channel, gettext ("I need a key to lookup"), message->user);
+                }
+                return msg;
+
+            case 8:            /* !info */
+                snprintf (msg, 512,
+                          "PRIVMSG %s :I am MCBot-%1.2f and my source code can be found on %s\r\n",
+                          message->channel, VERSION, "http://largo.homelinux.org/svn/c/mcbot/trunk");
+                return msg;
+
+            case 9:            /* !ping */
+                if ((token = strtok (NULL, "\r\n")))
+                    snprintf (msg, 512, "PRIVMSG %s :PING 0815\r\n", token);
+                return msg;
+
+            case 10:           /* !on */
+                snprintf (msg, 512,
+                          "PRIVMSG %s :%s %s.\r\n",
+                          message->user, gettext ("Autolearn enabled for channel"), message->channel);
+                return msg;
+
+            case 11:           /* !off */
+                snprintf (msg, 512,
+                          "PRIVMSG %s :%s %s.\r\n",
+                          message->user, gettext ("Autolearn disabled for channel"), message->channel);
+                return msg;
+
+            case 12:           /* !debug */
+                snprintf (msg, 512,
+                          "PRIVMSG %s :USER: %s EMAIL: %s CHANNEL: %s LINE: %s\r\n",
+                          message->channel, message->user, message->email, message->channel, message->line);
+                return msg;
+
+            case 13:           /* !vaccum */
+                snprintf (msg, 512, "PRIVMSG %s :%s\r\n", message->channel, db_vaccuum (DATABASE_FILE));
+                return msg;
+
+            case 14:           /* !logout */
+                if (strstr (message->user, db_lookup(DATABASE_FILE, "mcbot.user"))) {
+                    if (strstr (message->email, db_lookup(DATABASE_FILE, "mcbot.email"))) {
+                        snprintf (msg, 512,
+                                  "PRIVMSG %s :%s!\r\nQUIT\r\n", message->channel, gettext ("Bye, have a nice day!"));
+                        *active = 0;
+                    }
+                }
+                /*
+                 * the returned message is either the default one or the generated one
+                 */
+                return msg;
+
+            case 15:           /* !who */
+                if ((token = strtok (NULL, "\r\n")) != NULL) {
+                    snprintf (msg, 512, "WHO %s\r\n", token);
+                }
+                return msg;
+                break;
+
+            case 16:           /* !whois */
+                if ((token = strtok (NULL, "\r\n")) != NULL) {
+                    snprintf (msg, 512, "WHOIS %s\r\n", token);
+                }
+                return msg;
+                break;
+            case 17:           /* time */
+                t = time (NULL);
+                timeptr = localtime (&t);
+                if ((token = malloc (81))) {
+                    strftime (token, 80, "%I:%M:%S %p", timeptr);
+                    snprintf (msg, 512, "PRIVMSG %s :%s %s, %s!\r\n",
+                              message->channel, gettext ("It is"), token, message->user);
+                    free (token);
+                }
+                return msg;
+                break;
+            case 18:           /* tell */
+                if ((token = strtok (NULL, " "))) {
+                    if ((parameters = strtok (NULL, "\r\n"))) {
+                        snprintf (msg, 512, "PRIVMSG %s :%s, %s\r\n",
+                                  (*token ==
+                                   '*') ? ++token : message->channel, token, db_lookup (DATABASE_FILE, parameters));
+                    }
+                }
+                return msg;
+                break;
+            case 19:           /* op */
+                if ((token = strtok (NULL, "\r\n")) != NULL) {
+                    if (strstr (message->email, db_lookup(DATABASE_FILE, "mcbot.email")))
+                        snprintf (msg, 512, "MODE %s +o %s\r\n", message->channel, token);
+                }
+                return msg;
+                break;
+            }
+        }
+        i++;
+    }
+
+    return NULL;
+}