/* * memory.c * (C) Peter Salanki 2002 * This program is copyright, and covered by the Gnu Public License. * The Natasha bot. * sorcer@linux.se */ #include #include #include #include #include #include #include #include #include #include "globals.h" #include "bottypes.h" struct activeuser *addauser (char *nick, char *username, char *hostname) { struct activeuser *newuser; pthread_mutex_lock(&globalusermutex); newuser = (struct activeuser *) malloc (sizeof (struct activeuser)); if (newuser == NULL) { printf ("Debug: malloc() FAILED!\a\n"); return newuser; } memset (newuser, 0, sizeof (struct activeuser)); // printf("Debug: Space allocated for %s.\n", nick); strncpy (newuser->nick, nick, NICKLEN); newuser->username = strdup(username); newuser->hostname = strdup(hostname); newuser->auth = 0; newuser->userid = 0; newuser->lastseen = time(NULL); newuser->isinhome = 0; newuser->requestok = 0; #ifdef Q_AUTOAUTH newuser->check = 0; #endif newuser->firstlink = NULL; newuser->lastlink = NULL; newuser->last = lastauser; newuser->next = NULL; if (lastauser != NULL) { lastauser->next = newuser; } else { /* * No final user yet defined, so this one must be the * very first one. */ firstauser = newuser; } lastauser = newuser; pthread_mutex_unlock(&globalusermutex); return newuser; } struct aculink *addaculink (struct activeuser *u, struct activechanuser *acu) { struct aculink *newaculink; newaculink = (struct aculink *) malloc (sizeof (struct aculink)); if (newaculink == NULL) { printf ("Debug: malloc() FAILED!\a\n"); return newaculink; } memset (newaculink, 0, sizeof (struct aculink)); newaculink->link = acu; newaculink->last = u->lastlink; newaculink->next = NULL; if (u->lastlink != NULL) { u->lastlink->next = newaculink; } else { /* * No final user yet defined, so this one must be the * very first one. */ u->firstlink = newaculink; } u->lastlink = newaculink; return newaculink; } /* Add an arm */ void addarm (char *nick, int aid, int type) { struct arm *newarm; if (findarm(nick) == NULL) { newarm = (struct arm *) malloc (sizeof (struct arm)); if (newarm == NULL) { printf ("Debug: malloc() FAILED!\a\n"); return; } memset (newarm, 0, sizeof (struct arm)); #ifdef DEBUG printf("Debug: Space allocated for arm: %s.\n", nick); #endif strncpy (newarm->nick, nick, NICKLEN); strncpy (newarm->server, SERVER, 50); #ifdef OUTGOING_VHOST strncpy (newarm->vhost, DEFAULT_VHOST, 150); #endif newarm->id = aid; newarm->fd = 0; newarm->datasent = 0; newarm->datainbuff = 0; newarm->lastreset = 0; newarm->nextsend = 0; newarm->status = 0; newarm->channels = 0; newarm->activethread = 0; newarm->type = type; newarm->connect = 1; /* Parsevar malloc() */ newarm->parsevars = (struct parsevars *) malloc (sizeof (struct parsevars)); /* Mutex Inits */ pthread_mutex_init(&newarm->sendqmutex, NULL); newarm->last = lastarm; newarm->next = NULL; if (lastarm != NULL) { lastarm->next = newarm; } else { /* * No final user yet defined, so this one must be the * very first one. */ firstarm = newarm; } lastarm = newarm; } } /* Loadmodule */ void loadmodule (char path[100], short fatal) { struct module *newmodule = NULL; const char *err; char msg[512]; void (*cmd)(struct module *m); if (findmodulebypath(path) == NULL) { newmodule = (struct module *) malloc (sizeof (struct module)); if (newmodule == NULL) { printf ("Debug: malloc() FAILED!\a\n"); return; } memset(newmodule, 0, sizeof (struct module)); strncpy(newmodule->path, path, 100); newmodule->fl = dlopen(path, RTLD_NOW); err = dlerror(); if(err) { snprintf(msg, 512, "%c4Warning:%c Module load failed (%c%s%c). Error: %s", COLORS, COLORS, BOLD, path, BOLD, err); privmsg(HOMECHAN, msg); printf("Error opening module: %s.\n", err); free(newmodule); if(fatal == 1) exit(1); return; } else { strncpy(newmodule->name, "UnNamed", 20); } newmodule->last = lastmodule; newmodule->next = NULL; if (lastmodule != NULL) { lastmodule->next = newmodule; } else { /* * No final user yet defined, so this one must be the * very first one. */ firstmodule = newmodule; } lastmodule = newmodule; } cmd = dlsym(newmodule->fl, "_module_init"); err = dlerror(); if(err) { snprintf(msg, 512, "%c4Error:%c Init function does not exist in module. Module load aborted.", COLORS, COLORS); privmsg(HOMECHAN, msg); unloadmodule("UnNamed"); return; } cmd(newmodule); printf("Successfully loaded: %s version: %0.2f\n", newmodule->name, newmodule->version); } void unloadmodule (char *name) { struct module *m; const char *err; void (*cmd)(struct module *m); m = findmodule(name); if (m == NULL) return; cmd = dlsym(m->fl, "_module_destroy"); err = dlerror(); if(err) printf("Warning: destroy function in module: %s is missing\n", name); else cmd(m); dlclose(m->fl); if (m->last != NULL) { m->last->next = m->next; /* Reset the next pointer */ } else { firstmodule = m->next; } if (m->next != NULL) { m->next->last = m->last; /* and the last pointer */ } else { lastmodule = m->last; } free(m); /* And remove the module from memory. */ } /* Add an active channel user */ struct activechanuser *addachanuser (char *nick, char *channel) { struct activechanuser *newactivechanuser; struct activeuser *u; u = findauser(nick); if(findchannel(channel) == NULL || u == NULL) { if(u != NULL && strcasecmp(channel, HOMECHAN) == 0) { u->isinhome = 1; return NULL; } return NULL; } if(findachanuser(nick, channel) != NULL) return NULL; pthread_mutex_lock(&globalacumutex); newactivechanuser = (struct activechanuser *) malloc (sizeof (struct activechanuser)); if (newactivechanuser == NULL) { printf ("Debug: malloc() FAILED!\a\n"); return NULL; } memset (newactivechanuser, 0, sizeof (struct activechanuser)); #ifdef DEBUG printf("Debug: Space allocated for active channel user %s.\n", nick); // Debugging code #endif newactivechanuser->channel = findchannel(channel); newactivechanuser->user = u; newactivechanuser->op = 0; newactivechanuser->voice = 0; newactivechanuser->warned = 0; newactivechanuser->lastreset = time(NULL); newactivechanuser->rows = 0; newactivechanuser->last = lastacu; newactivechanuser->next = NULL; if (lastacu != NULL) { lastacu->next = newactivechanuser; } else { /* * No final user yet defined, so this one must be the * very first one. */ firstacu = newactivechanuser; } lastacu = newactivechanuser; addaculink(u, newactivechanuser); pthread_mutex_unlock(&globalacumutex); return newactivechanuser; } /* Add a ban on a channel */ void addban (char *channel, char *host, char *reason, int setby, int expire) { struct banlist *newban; struct channel *c; char msg[CHANNELLEN+10+BANLEN]; c = findchannel(channel); if(c == NULL || findban(host, channel) != NULL) return; newban = (struct banlist *) malloc (sizeof (struct banlist)); if (newban == NULL) { printf ("Debug: malloc() FAILED!\a\n"); return; } memset (newban, 0, sizeof (struct banlist)); strcpy(newban->host, host); strcpy(newban->reason, reason); newban->setby = setby; newban->expire = expire; newban->last = c->lastbanlist; newban->next = NULL; if (c->lastbanlist != NULL) { c->lastbanlist->next = newban; } else { /* * No final user yet defined, so this one must be the * very first one. */ c->firstbanlist = newban; } c->lastbanlist = newban; /* We ban from channel */ sprintf(msg, "MODE %s +b %s\n\r", channel, host); putserver(msg, c->arm); } /* Add a row to sendqueue */ void putserver (char *data, struct arm *a) { struct sendqueue *newsendqueue; if(a == NULL) { printf("FATAL: arm == NULL in putserver()\n"); return; } a->datainbuff = a->datainbuff + strlen(data); pthread_mutex_lock(&a->sendqmutex); newsendqueue = (struct sendqueue *) malloc (sizeof (struct sendqueue)); if (newsendqueue == NULL) { printf ("Debug: malloc() FAILED!\a\n"); pthread_mutex_unlock(&a->sendqmutex); return; } memset (newsendqueue, 0, sizeof (struct sendqueue)); strcpy(newsendqueue->data, data); newsendqueue->last = a->lastsendqueue; newsendqueue->next = NULL; if (a->lastsendqueue != NULL) { a->lastsendqueue->next = newsendqueue; } else { /* * No final user yet defined, so this one must be the * very first one. */ a->firstsendqueue = newsendqueue; } a->lastsendqueue = newsendqueue; pthread_mutex_unlock(&a->sendqmutex); } /* Add a channel */ void addchannel (char *channel, short id, char *modes, char *key, short autoop, short autovoice, short bitch, short ftopic, char *mvoice, short advertise, char *flood, short peak, short greet, short tv, short vote, short infobot, short stats, struct arm *arm, char *onjoin) { struct channel *newchan; if(findchannel(channel) != NULL || arm == NULL) return; newchan = (struct channel *) malloc (sizeof (struct channel)); if (newchan == NULL) { printf ("Debug: malloc() FAILED!\a\n"); return; } memset (newchan, 0, sizeof (struct channel)); #ifdef DEBUG printf("Debug: Space allocated for channel %s.\n", channel); #endif newchan->id = id; newchan->isop = 1; // Assume we have ops newchan->ison = 0; // Assume we are not on the channel #ifdef SPAMSCAN newchan->nextspam = time(NULL); #endif strncpy(newchan->topic, "", TOPICLEN); strcpy(newchan->name, channel); strcpy(newchan->modes, modes); strcpy(newchan->key, key); newchan->autoop = autoop; newchan->autovoice = autovoice; newchan->bitch = bitch; newchan->ftopic = ftopic; strcpy(newchan->mvoice, mvoice); strcpy(newchan->onjoin, onjoin); newchan->advertise = advertise; sscanf(flood, "%i:%i", &newchan->floodrep, &newchan->floodtime); newchan->peak = peak; newchan->greet = greet; newchan->tv = tv; newchan->vote = vote; newchan->infobot = infobot; newchan->stats = stats; newchan->votestruct = NULL; newchan->arm = arm; newchan->firstbanlist = NULL; newchan->lastbanlist = NULL; newchan->last = lastchan; newchan->next = NULL; if (lastchan != NULL) { lastchan->next = newchan; } else { /* * No final channel yet defined, so this one must be the * very first one. */ firstchan = newchan; } lastchan = newchan; } /* Add a channel user */ void addchanuser (struct channel *channel, int uid, int level, char *greet) { struct chanuser *newchanuser; newchanuser = (struct chanuser *) malloc (sizeof (struct chanuser)); if (newchanuser == NULL) { printf ("Debug: malloc() FAILED!\a\n"); return; } memset (newchanuser, 0, sizeof (struct chanuser)); #ifdef DEBUG printf("Debug: Space allocated for channel user %d.\n", uid); // Debugging code #endif newchanuser->channel = channel; newchanuser->uid = uid; newchanuser->level = level; strcpy(newchanuser->greet, greet); newchanuser->last = lastchanuser; newchanuser->next = NULL; if (lastchanuser != NULL) { lastchanuser->next = newchanuser; } else { /* * No final user yet defined, so this one must be the * very first one. */ firstchanuser = newchanuser; } lastchanuser = newchanuser; } struct arm *findarm (char *nick) { struct arm *a; a = firstarm; while ((a != NULL) && (strcasecmp (a->nick, nick) != 0)) { a = a->next; } return a; } struct module *findmodule (char name[20]) { struct module *m; m = firstmodule; while ((m != NULL) && (strcasecmp (m->name, name) != 0)) { m = m->next; } return m; } struct module *findmodulebypath (char path[100]) { struct module *m; m = firstmodule; while ((m != NULL) && (strcasecmp (m->path, path) != 0)) { m = m->next; } return m; } struct arm *findarmbyid (int id) { struct arm *a; a = firstarm; while (a != NULL && a->id != id) { a = a->next; } return a; } struct arm *findarmbytype (int type) { struct arm *a; a = firstarm; while (a != NULL && a->type != type) { a = a->next; } return a; } /* * Find active user by nick. Handy for deleting them, checking authentication * and so on. */ struct activeuser *findauser (char *nick) { struct activeuser *u; u = firstauser; while ((u != NULL) && (irc_strcmp (u->nick, nick) != 0)) { u = u->next; } #ifdef DEBUG // if (u == NULL && strcmp(nick, remote_server) != 0) printf("Didn't find user: %s Segfault may be eminent\n", nick); // Debug #endif return u; } /* Find a channel by name */ struct channel *findchannel (char *name) { struct channel *c; c = firstchan; while ((c != NULL) && (irc_strcmp (c->name, name) != 0)) { c = c->next; } #ifdef DEBUG // if (c == NULL) printf("Didn't find channel: %s Segfault may be approaching\n", name); // Debug #endif return c; } struct channel *findchannelbyid (int id) { struct channel *c; c = firstchan; while ((c != NULL) && (id != c->id)) { c = c->next; } return c; } /* Find a channel user by uid */ struct chanuser *findchanuser (int uid, int cid) { struct chanuser *cu; struct channel *c; if ((c = findchannelbyid(cid)) == NULL) return NULL; cu = firstchanuser; while (cu != NULL) { if(cu->channel == c && cu->uid == uid) { // printf("Found and returning. uid: %i cid: %i\n", uid, cid); return cu; } cu = cu->next; } #ifdef DEBUG // if (cu == NULL) printf("Didn't find chanuser Segfault may be approaching\n"); // Debug #endif return NULL; } struct activechanuser *findachanuser (char *nick, char *channel) { struct aculink *aculink; struct activeuser *u; if((u = findauser(nick)) == NULL) return NULL; // To be refactored aculink = u->firstlink; while (aculink != NULL) { /* Dirty debug code if(aculink->link == NULL) printf("link == NULL\n"); else printf("link != NULL\n"); if(aculink->link->channel == NULL) printf("link->channel == NULL\n"); else printf("link->channel != NULL\n"); if(aculink->link->channel->name == NULL) printf("link->channel->name == NULL\n"); else printf("link->channel->name != NULL, name: %s\n", nick); printf("acurun: %s %s\n", nick, aculink->link->channel->name); */ if(strcasecmp(aculink->link->channel->name, channel) == 0) return aculink->link; aculink = aculink->next; } return NULL; } struct banlist *findban (char *host, char *channel) { struct banlist *ban; struct channel *c; c = findchannel(channel); if(c == NULL) return NULL; ban = c->firstbanlist; while (ban != NULL && strcasecmp(ban->host, host) != 0) { ban = ban->next; } return ban; } void delarm (char *arm) { struct arm *a; a = findarm (arm); if (a == NULL) { return; } else { if(a->status == 1) { puttoserver("QUIT :This ARM is being removed\n\r", a); linkbreak(a); } /* Free parsevars */ free(a->parsevars); /* Mutex destructs */ pthread_mutex_destroy(&a->sendqmutex); /* Join thread */ if(pthread_join(a->thread, NULL)) printf("Error joining thread for (by delete) %s.", a->nick); } if (a->last != NULL) { a->last->next = a->next; /* Reset the next pointer */ } else { firstarm = a->next; } if (a->next != NULL) { a->next->last = a->last; /* and the last pointer */ } else { lastarm = a->last; } free(a); /* And remove the user from memory. */ } void deluser (struct activeuser *u) { if (u == NULL) { /* printf("Debug: Failed to find user %s.\n",nick); */ return; } if (u->last != NULL) { u->last->next = u->next; /* Reset the next pointer */ } else { firstauser = u->next; } if (u->next != NULL) { u->next->last = u->last; /* and the last pointer */ } else { lastauser = u->last; } free(u->username); /* Free submallocs */ free(u->hostname); free(u); /* And remove the user from memory. */ } void delaculink (struct activeuser *u, struct activechanuser *acu) { struct aculink *aculink; short done = 0; if (u == NULL) { /* printf("Debug: Failed to find user %s.\n",nick); */ return; } aculink = u->firstlink; while (aculink != NULL && done == 0) { if(aculink->link == acu) done = 1; else aculink = aculink->next; } if (aculink->last != NULL) { aculink->last->next = aculink->next; /* Reset the next pointer */ } else { u->firstlink = aculink->next; } if (aculink->next != NULL) { aculink->next->last = aculink->last; /* and the last pointer */ } else { u->lastlink = aculink->last; } free(aculink); /* And remove the user from memory. */ } /* Delete user on channel */ int delachanuser (char *nick, char *channel) { struct activechanuser *acu; struct activeuser *u; struct channel *c; pthread_mutex_lock(&globalacumutex); acu = findachanuser(nick, channel); u = findauser(nick); c = findchannel(channel); if (acu == NULL) { if(u != NULL && strcasecmp(channel, HOMECHAN) == 0) { u->isinhome = 0; } #ifdef DEBUG else printf("Debug: Failed to find user(1) for acudel %s.\n", nick); #endif } else { // printf ("Debug: Deleting active channel user nick %s\n", nick); delaculink(u, acu); // Delete the link if (acu->last != NULL) { acu->last->next = acu->next; /* Reset the next pointer */ } else { firstacu = acu->next; } if (acu->next != NULL) { acu->next->last = acu->last; /* and the last pointer */ } else { lastacu = acu->last; } free(acu); /* And remove the user from memory. */ } /* Check if user is on any chans now */ if(u != NULL && u->auth == 0) { if(u->firstlink == NULL && u->isinhome == 0) { #ifdef DEBUG printf("User: %s not seen on any channel, deleted. (now parted: %s)\n", u->nick, channel); #endif deluser(u); pthread_mutex_unlock(&globalacumutex); return 1; } } pthread_mutex_unlock(&globalacumutex); return 0; } /* Delete ban from channel */ void delban (char *host, char *channel) { struct channel *c; struct banlist *ban; char msg[CHANNELLEN+10+BANLEN]; c = findchannel(channel); ban = findban(host, channel); if (ban != NULL) { sprintf(msg, "MODE %s -b %s\n\r", channel, ban->host); putserver(msg, c->arm); if (ban->last != NULL) { ban->last->next = ban->next; /* Reset the next pointer */ } else { c->firstbanlist = ban->next; } if (ban->next != NULL) { ban->next->last = ban->last; /* and the last pointer */ } else { c->lastbanlist = ban->last; } free(ban); /* And remove the user from memory. */ } } /* Delete first sendqueue row from arm */ void delsendqueue (struct arm *a) { struct sendqueue *sendqueue; sendqueue = a->firstsendqueue; a->datainbuff = a->datainbuff - strlen(sendqueue->data); // while (sendqueue != NULL) sendqueue = sendqueue->next; This is wrong, we need to start sending the queue from back to front pthread_mutex_lock(&a->sendqmutex); if (sendqueue != NULL) { if (sendqueue->last != NULL) { //sendqueue->last->next = sendqueue->next; /* Reset the next pointer */ This should never be true printf("BUG BUG BUG BUG!!!!!!!!\n"); } else { a->firstsendqueue = sendqueue->next; } if (sendqueue->next != NULL) { sendqueue->next->last = sendqueue->last; /* and the last pointer */ } else { a->lastsendqueue = sendqueue->last; } free(sendqueue); /* And remove the sendqueue from memory. */ } pthread_mutex_unlock(&a->sendqmutex); } /* Delete channel */ void delchannel (struct channel *c) { if (c->last != NULL) { c->last->next = c->next; /* Reset the next pointer */ } else { firstchan = c->next; } if (c->next != NULL) { c->next->last = c->last; /* and the last pointer */ } else { lastchan = c->last; } free(c); /* And remove the channel from memory. */ } struct vote *AllocateVote(struct channel *c) { struct vote *newvote; if(c->votestruct != NULL) return NULL; // Vote already running newvote = (struct vote *) malloc (sizeof (struct vote)); if (newvote == NULL) { printf ("Debug: malloc() FAILED!\a\n"); return NULL; } memset (newvote, 0, sizeof (struct vote)); newvote->yes = 0; newvote->no = 0; newvote->lastvid = 0; c->votestruct = newvote; return newvote; } int FreeVote (struct channel *c) { if(c->votestruct == NULL) return 0; /* No vote on channel */ free(c->votestruct); c->votestruct = NULL; return 1; }