void BalancedBTreeRemove( BalancedBTree_t *btree, BalancedBTreeItem_t *item, Locked_t locked, bool rebalance ) { BalancedBTreeItem_t *replace; if( btree == NULL ) { return; } if( item != NULL && item->btree != btree ) { LogPrint( LOG_CRIT, "Item %p not on btree %p! (on %p)", (void *)item, (void *)btree, (void *)item->btree ); return; } if( locked == UNLOCKED ) { BalancedBTreeLock( btree ); } if( item == NULL ) { if( rebalance ) { BalancedBTreeRebalance( btree, btree->root ); } if( locked == UNLOCKED ) { BalancedBTreeLock( btree ); } return; } /* OK, it's on the btree, and we have it locked */ if( BalancedBTreeWeight( item->left ) > BalancedBTreeWeight( item->right ) ) { /* There's more stuff on the left subtree, relink taking * the greatest entry on the left subtree, moving it here */ replace = BalancedBTreeFindGreatest( item->left ); } else { /* Either more on the right subtree or they are balanced, relink * taking the least entry on the right subtree, moving it here */ replace = BalancedBTreeFindLeast( item->right ); } BalancedBTreeReplace( btree, item, replace ); item->btree = NULL; if( rebalance ) { BalancedBTreeRebalance( btree, btree->root ); } if( locked == UNLOCKED ) { BalancedBTreeUnlock( btree ); } }
void mainVersions( void *arg ) { BalancedBTreeLock( versionTree ); versionShowRecurse( versionTree->root, 0 ); BalancedBTreeUnlock( versionTree ); cursesKeyhandleRegister( cursesDetailsKeyhandle ); }
void mainSighup( int signum, void *arg ) { /* * Need to rescan the plugins */ LogPrintNoArg( LOG_INFO, "Reloading plugins..." ); plugins_sighup(); /* * Reload server & channel info -- NOTE: this happens before the bot * threads get signalled */ LogPrintNoArg( LOG_INFO, "Reloading servers & channels..." ); BalancedBTreeLock( ServerTree ); serverUnvisit( ServerTree->root ); db_load_servers(); db_load_channels(); while( serverFlushUnvisited( ServerTree->root ) ) { /* * If an unvisited entry is found, we need to loop as removing it can * mess up the recursion */ } BalancedBTreeAdd( ServerTree, NULL, LOCKED, TRUE ); BalancedBTreeUnlock( ServerTree ); }
void bot_start(void) { /* Create the server tree */ ServerTree = BalancedBTreeCreate( BTREE_KEY_INT ); versionAdd( "botnet", BN_GetVersion() ); BalancedBTreeLock( ServerTree ); /* Read the list of servers */ cursesMenuItemAdd( 2, MENU_SERVERS, "New Server", cursesServerNew, NULL ); db_load_servers(); /* Read the list of channels */ cursesMenuItemAdd( 2, MENU_CHANNELS, "New Channel", cursesChannelNew, NULL ); db_load_channels(); ChannelsLoaded = TRUE; serverStartTree( ServerTree->root ); BalancedBTreeUnlock( ServerTree ); }
void plugins_initialize( void ) { static char *command = "plugin"; LinkedList_t *list; extBlock = ProtectedDataCreate(); if( !extBlock ) { LogPrintNoArg( LOG_CRIT, "No memory to create plugin extension " "protected structure!!"); exit(1); } extBlock->data = NULL; pluginTree = BalancedBTreeCreate( BTREE_KEY_STRING ); if( !pluginTree ) { return; } list = pluginFindPlugins( "plugin_", ".so" ); db_check_plugins( list ); LinkedListDestroy( list ); LogPrint( LOG_NOTICE, "Plugin path: %s", PLUGIN_PATH ); BalancedBTreeLock( pluginTree ); db_get_plugins( pluginTree ); pluginInitializeTree( pluginTree->root ); BalancedBTreeUnlock( pluginTree ); botCmd_add( (const char **)&command, botCmdPlugin, NULL, NULL ); }
void ThreadAllKill( int signum ) { BalancedBTreeLock( ThreadTree ); ThreadRecurseKill( ThreadTree->root, signum ); BalancedBTreeUnlock( ThreadTree ); }
void pluginUnloadAll( void ) { if( !pluginTree ) { return; } BalancedBTreeLock( pluginTree ); pluginUnloadTree( pluginTree->root ); BalancedBTreeUnlock( pluginTree ); }
int FindServerWithChannel( int channelId ) { IRCServer_t *server; if( !ChannelsLoaded ) { return( -1 ); } BalancedBTreeLock( ServerTree ); server = RecurseFindServerWithChannel( ServerTree->root, channelId ); BalancedBTreeUnlock( ServerTree ); if( server ) { return( server->serverId ); } return( -1 ); }
void plugins_sighup( void ) { BalancedBTreeLock( pluginTree ); pluginUnvisitTree( pluginTree->root ); db_get_plugins( pluginTree ); pluginInitializeTree( pluginTree->root ); while( pluginFlushUnvisited( pluginTree->root ) ) { /* * Keep calling until nothing's been flushed. This allows for the * fact that the tree will shift around as we delete things, and the * recursion will be messed up by this. */ } /* Rebalance the tree */ BalancedBTreeAdd( pluginTree, NULL, LOCKED, TRUE ); BalancedBTreeUnlock( pluginTree ); }
void *bot_shutdown(void *arg) { if( ServerTree ) { BalancedBTreeLock( ServerTree ); while( serverKillTree( ServerTree->root, FALSE ) ) { /* * This recurses and kills off every entry in the tree, which * messes up recursion, so needs restarting */ } BalancedBTreeDestroy( ServerTree ); ServerTree = NULL; } LogPrintNoArg( LOG_NOTICE, "Shutdown all bot threads" ); BotDone = true; return( NULL ); }
void *BalancedBTreeFind( BalancedBTree_t *btree, void *key, Locked_t locked ) { BalancedBTreeItem_t *item; bool found; int res; if( btree == NULL || key == NULL ) { return( NULL ); } if( locked == UNLOCKED ) { BalancedBTreeLock( btree ); } for( found = FALSE, item = btree->root; item && !found; ) { res = btree->keyCompare( key, item->key ); if( res == 0 ) { /* Found it */ found = TRUE; continue; } else if ( res < 0 ) { item = item->left; } else { item = item->right; } } if( locked == UNLOCKED ) { BalancedBTreeUnlock( btree ); } return( item ); }
void BalancedBTreeAdd( BalancedBTree_t *btree, BalancedBTreeItem_t *item, Locked_t locked, bool rebalance ) { int res; if( btree == NULL ) { return; } if( locked == UNLOCKED ) { BalancedBTreeLock( btree ); } if( item == NULL ) { if( rebalance ) { BalancedBTreeRebalance( btree, btree->root ); } if( locked == UNLOCKED ) { BalancedBTreeUnlock( btree ); } return; } item->btree = btree; item->left = NULL; item->right = NULL; item->parent = BalancedBTreeFindParent( btree, item ); if( item->parent == NULL) { btree->root = item; } else { res = btree->keyCompare( item->key, item->parent->key ); if( res > 0 ) { /* item greater than parent */ item->parent->right = item; } else if( res < 0 ) { /* item less than parent */ item->parent->left = item; } else { switch( btree->keyType ) { case BTREE_KEY_INT: LogPrint( LOG_CRIT, "Duplicate key (INT): %d", *(int *)item->key ); btree->keyCompare = KeyCompareInt; break; case BTREE_KEY_STRING: LogPrint( LOG_CRIT, "Duplicate key (STRING): %s", *(char **)item->key ); btree->keyCompare = KeyCompareString; break; case BTREE_KEY_PTHREAD: LogPrint( LOG_CRIT, "Duplicate key (PTHREAD): %d", *(int *)item->key ); break; default: LogPrintNoArg( LOG_CRIT, "Duplicate key" ); break; } } } if( rebalance ) { BalancedBTreeRebalance( btree, btree->root ); } if( locked == UNLOCKED ) { BalancedBTreeUnlock( btree ); } }
void serverKill( BalancedBTreeItem_t *node, IRCServer_t *server, bool unalloc ) { LinkedListItem_t *listItem, *next; IRCChannel_t *channel; BalancedBTreeItem_t *item; if( server->enabled || server->enabledChanged ) { server->threadAbort = TRUE; thread_deregister( server->txThreadId ); thread_deregister( server->threadId ); server->threadAbort = FALSE; } if( unalloc ) { BalancedBTreeRemove( node->btree, node, LOCKED, FALSE ); } else { server->enabled = FALSE; } if( server->txQueue ) { /* This *might* leak the contents of any queue entries? */ QueueClear( server->txQueue, TRUE ); QueueLock( server->txQueue ); QueueDestroy( server->txQueue ); server->txQueue = NULL; } if( server->channels ) { LinkedListLock( server->channels ); BalancedBTreeLock( server->channelName ); BalancedBTreeLock( server->channelNum ); for( listItem = server->channels->head; listItem; listItem = next ) { next = listItem->next; channel = (IRCChannel_t *)listItem; regexpBotCmdRemove( server, channel ); LinkedListRemove( server->channels, listItem, LOCKED ); item = BalancedBTreeFind( server->channelName, &channel->channel, LOCKED ); if( item ) { BalancedBTreeRemove( server->channelName, item, LOCKED, FALSE ); } item = BalancedBTreeFind( server->channelNum, &channel->channelId, LOCKED ); if( item ) { BalancedBTreeRemove( server->channelNum, item, LOCKED, FALSE ); } ThreadAllNotifyChannel( channel ); cursesMenuItemRemove( 2, MENU_CHANNELS, channel->menuText ); free( channel->menuText ); free( channel->channel ); free( channel->fullspec ); free( channel->url ); free( channel ); } LinkedListDestroy( server->channels ); BalancedBTreeDestroy( server->channelName ); BalancedBTreeDestroy( server->channelNum ); server->channels = NULL; server->channelName = NULL; server->channelNum = NULL; } if( unalloc ) { free( server->server ); free( server->password ); free( server->nick ); free( server->username ); free( server->realname ); free( server->nickserv ); free( server->nickservmsg ); free( server->ircInfo.Server ); } LinkedListLock( server->floodList ); for( listItem = server->floodList->head; listItem; listItem = next ) { next = listItem->next; LinkedListRemove( server->floodList, listItem, LOCKED ); free( listItem ); } LinkedListDestroy( server->floodList ); server->floodList = NULL; ThreadAllNotifyServer( server ); if( unalloc ) { cursesMenuItemRemove( 2, MENU_SERVERS, server->menuText ); free( server->menuText ); free( server->threadName ); free( server->txThreadName ); free( server ); free( node ); } }
void botSighup( int signum, void *arg ) { IRCServer_t *server; LinkedListItem_t *listItem, *next; BalancedBTreeItem_t *item; IRCChannel_t *channel; bool newChannel = FALSE; server = (IRCServer_t *)arg; if( !server ) { return; } /* * Check each channel on the server, leave those no longer needed */ if( server->channels ) { LinkedListLock( server->channels ); BalancedBTreeLock( server->channelName ); BalancedBTreeLock( server->channelNum ); for( listItem = server->channels->head; listItem; listItem = next ) { next = listItem->next; channel = (IRCChannel_t *)listItem; if( !channel->visited ) { channelLeave( server, channel, channel->channel ); regexpBotCmdRemove( server, channel ); LinkedListRemove( server->channels, listItem, LOCKED ); item = BalancedBTreeFind( server->channelName, &channel->channel, LOCKED ); if( item ) { BalancedBTreeRemove( server->channelName, item, LOCKED, FALSE ); } item = BalancedBTreeFind( server->channelNum, &channel->channelId, LOCKED ); if( item ) { BalancedBTreeRemove( server->channelNum, item, LOCKED, FALSE ); } ThreadAllNotifyChannel( channel ); cursesMenuItemRemove( 2, MENU_CHANNELS, channel->menuText ); free( channel->menuText ); free( channel->channel ); free( channel->fullspec ); free( channel->url ); free( channel ); } else if( channel->newChannel && channel->enabled && !channel->joined && !newChannel ) { newChannel = TRUE; transmitMsg( server, TX_JOIN, channel->channel, NULL ); } else if( channel->newChannel && !channel->enabled ) { channel->newChannel = FALSE; } } BalancedBTreeUnlock( server->channelNum ); BalancedBTreeUnlock( server->channelName ); LinkedListUnlock( server->channels ); } }
void botCmdPlugin( IRCServer_t *server, IRCChannel_t *channel, char *who, char *msg, void *tag ) { int len; char *line; char *command; char *message; bool ret; static char *notauth = "You are not authorized, you can't do that!"; if( !server || channel ) { return; } if( !authenticate_check( server, who ) ) { transmitMsg( server, TX_PRIVMSG, who, notauth ); return; } line = strstr( msg, " " ); if( line ) { /* Command has trailing text, skip the space */ len = line - msg; line++; command = (char *)malloc( len + 2 ); strncpy( command, msg, len ); command[len] = '\0'; } else { /* Command is the whole line */ command = strdup( msg ); } /* Strip trailing spaces */ if( line ) { for( len = strlen(line); len && line[len-1] == ' '; len = strlen(line) ) { line[len-1] = '\0'; } if( *line == '\0' ) { line = NULL; } } if( !strcmp( command, "list" ) ) { BalancedBTreeLock( pluginTree ); if( line && !strcmp( line, "all" ) ) { message = botCmdDepthFirst( pluginTree->root, false ); } else { message = botCmdDepthFirst( pluginTree->root, true ); } BalancedBTreeUnlock( pluginTree ); } else if( !strcmp( command, "load" ) && line ) { ret = pluginLoad( line ); message = (char *)malloc(strlen(line) + 32); if( ret ) { sprintf( message, "Loaded module %s", line ); } else { sprintf( message, "Module %s already loaded", line ); } } else if( !strcmp( command, "unload" ) && line ) { ret = pluginUnload( line ); message = (char *)malloc(strlen(line) + 32); if( ret ) { sprintf( message, "Unloaded module %s", line ); } else { sprintf( message, "Module %s already unloaded", line ); } } else { message = NULL; free( command ); return; } transmitMsg( server, TX_MESSAGE, who, message ); free( message ); free( command ); }