Search code examples
ccompiler-errorsbotsirc

IRC Bot Written in C


I've picked up an IRC bot skeleton from here and it doesn't compile, although the author says it should do. gcc basically throws up these errors

/tmp/cc39tOaX.o: In function raw': bot.c:(.text+0x73): undefined reference tova_start' bot.c:(.text+0xaa): undefined reference to `va_end' collect2: error: ld returned 1 exit status

Which seems to mean these two functions were not defined before they were called in function raw?

Anyway, here is the code. Any help in getting started working it out would be a great help.

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <netdb.h>

int conn;
char sbuf[512];

void raw(char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
vsnprintf(sbuf, 512, fmt, ap);
va_end(ap);
printf("<< %s", sbuf);
write(conn, sbuf, strlen(sbuf));
}

int main() {

char *nick = "test";
char *channel = NULL;
char *host = "irc.dav7.net";
char *port = "6667";

char *user, *command, *where, *message, *sep, *target;
int i, j, l, sl, o = -1, start, wordcount;
char buf[513];
struct addrinfo hints, *res;

memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
getaddrinfo(host, port, &hints, &res);
conn = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
connect(conn, res->ai_addr, res->ai_addrlen);

raw("USER %s 0 0 :%s\r\n", nick, nick);
raw("NICK %s\r\n", nick);

while ((sl = read(conn, sbuf, 512))) {
    for (i = 0; i < sl; i++) {
        o++;
        buf[o] = sbuf[i];
        if ((i > 0 && sbuf[i] == '\n' && sbuf[i - 1] == '\r') || o == 512) {
            buf[o + 1] = '\0';
            l = o;
            o = -1;

            printf(">> %s", buf);

            if (!strncmp(buf, "PING", 4)) {
                buf[1] = 'O';
                raw(buf);
            } else if (buf[0] == ':') {
                wordcount = 0;
                user = command = where = message = NULL;
                for (j = 1; j < l; j++) {
                    if (buf[j] == ' ') {
                        buf[j] = '\0';
                        wordcount++;
                        switch(wordcount) {
                            case 1: user = buf + 1; break;
                            case 2: command = buf + start; break;
                            case 3: where = buf + start; break;
                        }
                        if (j == l - 1) continue;
                        start = j + 1;
                    } else if (buf[j] == ':' && wordcount == 3) {
                        if (j < l - 1) message = buf + j + 1;
                        break;
                    }
                }

                if (wordcount < 2) continue;

                if (!strncmp(command, "001", 3) && channel != NULL) {
                    raw("JOIN %s\r\n", channel);
                } else if (!strncmp(command, "PRIVMSG", 7) || !strncmp(command, "NOTICE", 6)) {
                    if (where == NULL || message == NULL) continue;
                    if ((sep = strchr(user, '!')) != NULL) user[sep - user] = '\0';
                    if (where[0] == '#' || where[0] == '&' || where[0] == '+' || where[0] == '!') target = where; else target = user;
                    printf("[from: %s] [reply-with: %s] [where: %s] [reply-to: %s] %s", user, command, where, target, message);
                    //raw("%s %s :%s", command, target, message); // If you enable this the IRCd will get its "*** Looking up your hostname..." messages thrown back at it but it works...
                }
            }

        }
    }

}

return 0;

}

I've tried defining the va_start and va_end before the function raw() with

void va_start();
void va_end();

but this didn't change anything..


Solution

  • man va_start
    

    gives me that :

    SYNOPSIS
           #include <stdarg.h>
    
           void va_start(va_list ap, last);
           type va_arg(va_list ap, type);
           void va_end(va_list ap);
           void va_copy(va_list dest, va_list src);
    

    By adding #include <stdarg.h> that work for me.