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;
+}