From f73b9697f9be18e04ec7458634520f9dd2e2432f Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 20 Jan 2006 16:15:49 +0100 Subject: Renamed commands.c, got rid of return values in all command functions. --- Makefile | 2 +- bitlbee.c | 8 +- bitlbee.h | 4 +- commands.c | 833 -------------------------------------------------------- commands.h | 2 +- ipc.c | 54 ++-- ipc.h | 2 +- irc.c | 43 +-- irc.h | 7 +- irc_commands.c | 147 ++++------ root_commands.c | 800 +++++++++++++++++++++++++++++++++++++++++++++++++++++ user.h | 2 +- 12 files changed, 901 insertions(+), 1003 deletions(-) delete mode 100644 commands.c create mode 100644 root_commands.c diff --git a/Makefile b/Makefile index 26dd3d0f..295fe69e 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ -include Makefile.settings # Program variables -objects = account.o bitlbee.o commands.o conf.o crypting.o help.o ini.o ipc.o irc.o irc_commands.o log.o nick.o query.o set.o storage.o storage_text.o unix.o url.o user.o util.o +objects = account.o bitlbee.o conf.o crypting.o help.o ini.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_text.o unix.o url.o user.o util.o subdirs = protocols # Expansion of variables diff --git a/bitlbee.c b/bitlbee.c index 218caf01..9a4688d8 100644 --- a/bitlbee.c +++ b/bitlbee.c @@ -166,10 +166,12 @@ gboolean bitlbee_io_current_client_read( GIOChannel *source, GIOCondition condit strcpy( ( irc->readbuffer + strlen( irc->readbuffer ) ), line ); } - if( !irc_process( irc ) ) + irc_process( irc ); + + /* Normally, irc_process() shouldn't call irc_free() but irc_abort(). Just in case: */ + if( !g_slist_find( irc_connection_list, irc ) ) { - log_message( LOGLVL_INFO, "Destroying connection with fd %d.", irc->fd ); - irc_abort( irc ); + log_message( LOGLVL_WARNING, "Abnormal termination of connection with fd %d.", irc->fd ); return FALSE; } diff --git a/bitlbee.h b/bitlbee.h index 0bd7c90e..e459f07d 100644 --- a/bitlbee.h +++ b/bitlbee.h @@ -128,8 +128,8 @@ int bitlbee_inetd_init( void ); gboolean bitlbee_io_current_client_read( GIOChannel *source, GIOCondition condition, gpointer data ); gboolean bitlbee_io_current_client_write( GIOChannel *source, GIOCondition condition, gpointer data ); -int root_command_string( irc_t *irc, user_t *u, char *command, int flags ); -int root_command( irc_t *irc, char *command[] ); +void root_command_string( irc_t *irc, user_t *u, char *command, int flags ); +void root_command( irc_t *irc, char *command[] ); void bitlbee_shutdown( gpointer data ); double gettime( void ); G_MODULE_EXPORT void http_encode( char *s ); diff --git a/commands.c b/commands.c deleted file mode 100644 index fbe378f6..00000000 --- a/commands.c +++ /dev/null @@ -1,833 +0,0 @@ - /********************************************************************\ - * BitlBee -- An IRC to other IM-networks gateway * - * * - * Copyright 2002-2004 Wilmer van der Gaast and others * - \********************************************************************/ - -/* User manager (root) commands */ - -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License with - the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; - if not, write to the Free Software Foundation, Inc., 59 Temple Place, - Suite 330, Boston, MA 02111-1307 USA -*/ - -#define BITLBEE_CORE -#include "commands.h" -#include "crypting.h" -#include "bitlbee.h" -#include "help.h" - -#include - -int root_command_string( irc_t *irc, user_t *u, char *command, int flags ) -{ - char *cmd[IRC_MAX_ARGS]; - char *s; - int k; - char q = 0; - - memset( cmd, 0, sizeof( cmd ) ); - cmd[0] = command; - k = 1; - for( s = command; *s && k < ( IRC_MAX_ARGS - 1 ); s ++ ) - if( *s == ' ' && !q ) - { - *s = 0; - while( *++s == ' ' ); - if( *s == '"' || *s == '\'' ) - { - q = *s; - s ++; - } - if( *s ) - { - cmd[k++] = s; - s --; - } - } - else if( *s == q ) - { - q = *s = 0; - } - cmd[k] = NULL; - - return( root_command( irc, cmd ) ); -} - -int root_command( irc_t *irc, char *cmd[] ) -{ - int i; - - if( !cmd[0] ) - return( 0 ); - - for( i = 0; commands[i].command; i++ ) - if( g_strcasecmp( commands[i].command, cmd[0] ) == 0 ) - { - if( !cmd[commands[i].required_parameters] ) - { - irc_usermsg( irc, "Not enough parameters given (need %d)", commands[i].required_parameters ); - return( 0 ); - } - commands[i].execute( irc, cmd ); - return( 1 ); - } - - irc_usermsg( irc, "Unknown command: %s. Please use \x02help commands\x02 to get a list of available commands.", cmd[0] ); - - return( 1 ); -} - -static int cmd_help( irc_t *irc, char **cmd ) -{ - char param[80]; - int i; - char *s; - - memset( param, 0, sizeof(param) ); - for ( i = 1; (cmd[i] != NULL && ( strlen(param) < (sizeof(param)-1) ) ); i++ ) { - if ( i != 1 ) // prepend space except for the first parameter - strcat(param, " "); - strncat( param, cmd[i], sizeof(param) - strlen(param) - 1 ); - } - - s = help_get( &(global.help), param ); - if( !s ) s = help_get( &(global.help), "" ); - - if( s ) - { - irc_usermsg( irc, "%s", s ); - g_free( s ); - return( 1 ); - } - else - { - irc_usermsg( irc, "Error opening helpfile." ); - return( 0 ); - } -} - -static int cmd_identify( irc_t *irc, char **cmd ) -{ - storage_status_t status = storage_load( irc->nick, cmd[1], irc ); - - switch (status) { - case STORAGE_INVALID_PASSWORD: - irc_usermsg( irc, "Incorrect password" ); - break; - case STORAGE_NO_SUCH_USER: - irc_usermsg( irc, "The nick is (probably) not registered" ); - break; - case STORAGE_OK: - irc_usermsg( irc, "Password accepted" ); - irc_umode_set( irc, "+R", 1 ); - break; - default: - irc_usermsg( irc, "Something very weird happened" ); - break; - } - - return( 0 ); -} - -static int cmd_register( irc_t *irc, char **cmd ) -{ - if( global.conf->authmode == AUTHMODE_REGISTERED ) - { - irc_usermsg( irc, "This server does not allow registering new accounts" ); - return( 0 ); - } - - irc_setpass( irc, cmd[1] ); - switch( storage_save( irc, FALSE )) { - case STORAGE_ALREADY_EXISTS: - irc_usermsg( irc, "Nick is already registered" ); - break; - - case STORAGE_OK: - irc->status = USTATUS_IDENTIFIED; - irc_umode_set( irc, "+R", 1 ); - break; - - default: - irc_usermsg( irc, "Error registering" ); - break; - } - - return( 0 ); -} - -static int cmd_drop( irc_t *irc, char **cmd ) -{ - storage_status_t status; - - status = storage_remove (irc->nick, cmd[1]); - switch (status) { - case STORAGE_NO_SUCH_USER: - irc_usermsg( irc, "That account does not exist" ); - return( 0 ); - case STORAGE_INVALID_PASSWORD: - irc_usermsg( irc, "Password invalid" ); - return( 0 ); - case STORAGE_OK: - irc_setpass( irc, NULL ); - irc->status = USTATUS_LOGGED_IN; - irc_umode_set( irc, "-R", 1 ); - irc_usermsg( irc, "Account `%s' removed", irc->nick ); - return( 0 ); - default: - irc_usermsg( irc, "Error: '%d'", status ); - return( 0 ); - } -} - -static int cmd_account( irc_t *irc, char **cmd ) -{ - account_t *a; - - if( global.conf->authmode == AUTHMODE_REGISTERED && irc->status < USTATUS_IDENTIFIED ) - { - irc_usermsg( irc, "This server only accepts registered users" ); - return( 0 ); - } - - if( g_strcasecmp( cmd[1], "add" ) == 0 ) - { - struct prpl *prpl; - - if( cmd[2] == NULL || cmd[3] == NULL || cmd[4] == NULL ) - { - irc_usermsg( irc, "Not enough parameters" ); - return( 0 ); - } - - prpl = find_protocol(cmd[2]); - - if( prpl == NULL ) - { - irc_usermsg( irc, "Unknown protocol" ); - return( 0 ); - } - - a = account_add( irc, prpl, cmd[3], cmd[4] ); - - if( cmd[5] ) - a->server = g_strdup( cmd[5] ); - - irc_usermsg( irc, "Account successfully added" ); - } - else if( g_strcasecmp( cmd[1], "del" ) == 0 ) - { - if( !cmd[2] ) - { - irc_usermsg( irc, "Not enough parameters given (need %d)", 2 ); - } - else if( !( a = account_get( irc, cmd[2] ) ) ) - { - irc_usermsg( irc, "Invalid account" ); - } - else if( a->gc ) - { - irc_usermsg( irc, "Account is still logged in, can't delete" ); - } - else - { - account_del( irc, a ); - irc_usermsg( irc, "Account deleted" ); - } - } - else if( g_strcasecmp( cmd[1], "list" ) == 0 ) - { - int i = 0; - - for( a = irc->accounts; a; a = a->next ) - { - char *con; - - if( a->gc && ( a->gc->flags & OPT_LOGGED_IN ) ) - con = " (connected)"; - else if( a->gc ) - con = " (connecting)"; - else if( a->reconnect ) - con = " (awaiting reconnect)"; - else - con = ""; - - irc_usermsg( irc, "%2d. %s, %s%s", i, a->prpl->name, a->user, con ); - - i ++; - } - irc_usermsg( irc, "End of account list" ); - } - else if( g_strcasecmp( cmd[1], "on" ) == 0 ) - { - if( cmd[2] ) - { - if( ( a = account_get( irc, cmd[2] ) ) ) - { - if( a->gc ) - { - irc_usermsg( irc, "Account already online" ); - return( 0 ); - } - else - { - account_on( irc, a ); - } - } - else - { - irc_usermsg( irc, "Invalid account" ); - return( 0 ); - } - } - else - { - if ( irc->accounts ) { - irc_usermsg( irc, "Trying to get all accounts connected..." ); - - for( a = irc->accounts; a; a = a->next ) - if( !a->gc ) - account_on( irc, a ); - } - else - { - irc_usermsg( irc, "No accounts known. Use 'account add' to add one." ); - } - } - } - else if( g_strcasecmp( cmd[1], "off" ) == 0 ) - { - if( !cmd[2] ) - { - irc_usermsg( irc, "Deactivating all active (re)connections..." ); - - for( a = irc->accounts; a; a = a->next ) - { - if( a->gc ) - account_off( irc, a ); - else if( a->reconnect ) - cancel_auto_reconnect( a ); - } - } - else if( ( a = account_get( irc, cmd[2] ) ) ) - { - if( a->gc ) - { - account_off( irc, a ); - } - else if( a->reconnect ) - { - cancel_auto_reconnect( a ); - irc_usermsg( irc, "Reconnect cancelled" ); - } - else - { - irc_usermsg( irc, "Account already offline" ); - return( 0 ); - } - } - else - { - irc_usermsg( irc, "Invalid account" ); - return( 0 ); - } - } - else - { - irc_usermsg( irc, "Unknown command: account %s. Please use \x02help commands\x02 to get a list of available commands.", cmd[1] ); - } - - return( 1 ); -} - -static int cmd_add( irc_t *irc, char **cmd ) -{ - account_t *a; - - if( !( a = account_get( irc, cmd[1] ) ) ) - { - irc_usermsg( irc, "Invalid account" ); - return( 1 ); - } - else if( !( a->gc && ( a->gc->flags & OPT_LOGGED_IN ) ) ) - { - irc_usermsg( irc, "That account is not on-line" ); - return( 1 ); - } - - if( cmd[3] ) - { - if( !nick_ok( cmd[3] ) ) - { - irc_usermsg( irc, "The requested nick `%s' is invalid", cmd[3] ); - return( 0 ); - } - else if( user_find( irc, cmd[3] ) ) - { - irc_usermsg( irc, "The requested nick `%s' already exists", cmd[3] ); - return( 0 ); - } - else - { - nick_set( irc, cmd[2], a->gc->prpl, cmd[3] ); - } - } - a->gc->prpl->add_buddy( a->gc, cmd[2] ); - add_buddy( a->gc, NULL, cmd[2], cmd[2] ); - - irc_usermsg( irc, "User `%s' added to your contact list as `%s'", cmd[2], user_findhandle( a->gc, cmd[2] )->nick ); - - return( 0 ); -} - -static int cmd_info( irc_t *irc, char **cmd ) -{ - struct gaim_connection *gc; - account_t *a; - - if( !cmd[2] ) - { - user_t *u = user_find( irc, cmd[1] ); - if( !u || !u->gc ) - { - irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] ); - return( 1 ); - } - gc = u->gc; - cmd[2] = u->handle; - } - else if( !( a = account_get( irc, cmd[1] ) ) ) - { - irc_usermsg( irc, "Invalid account" ); - return( 1 ); - } - else if( !( ( gc = a->gc ) && ( a->gc->flags & OPT_LOGGED_IN ) ) ) - { - irc_usermsg( irc, "That account is not on-line" ); - return( 1 ); - } - - if( !gc->prpl->get_info ) - { - irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] ); - return( 1 ); - } - gc->prpl->get_info( gc, cmd[2] ); - - return( 0 ); -} - -static int cmd_rename( irc_t *irc, char **cmd ) -{ - user_t *u; - - if( g_strcasecmp( cmd[1], irc->nick ) == 0 ) - { - irc_usermsg( irc, "Nick `%s' can't be changed", cmd[1] ); - return( 1 ); - } - if( user_find( irc, cmd[2] ) && ( nick_cmp( cmd[1], cmd[2] ) != 0 ) ) - { - irc_usermsg( irc, "Nick `%s' already exists", cmd[2] ); - return( 1 ); - } - if( !nick_ok( cmd[2] ) ) - { - irc_usermsg( irc, "Nick `%s' is invalid", cmd[2] ); - return( 1 ); - } - if( !( u = user_find( irc, cmd[1] ) ) ) - { - irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] ); - return( 1 ); - } - user_rename( irc, cmd[1], cmd[2] ); - irc_write( irc, ":%s!%s@%s NICK %s", cmd[1], u->user, u->host, cmd[2] ); - if( g_strcasecmp( cmd[1], irc->mynick ) == 0 ) - { - g_free( irc->mynick ); - irc->mynick = g_strdup( cmd[2] ); - } - else if( u->send_handler == buddy_send_handler ) - { - nick_set( irc, u->handle, u->gc->prpl, cmd[2] ); - } - - irc_usermsg( irc, "Nick successfully changed" ); - - return( 0 ); -} - -static int cmd_remove( irc_t *irc, char **cmd ) -{ - user_t *u; - char *s; - - if( !( u = user_find( irc, cmd[1] ) ) || !u->gc ) - { - irc_usermsg( irc, "Buddy `%s' not found", cmd[1] ); - return( 1 ); - } - s = g_strdup( u->handle ); - - u->gc->prpl->remove_buddy( u->gc, u->handle, NULL ); - user_del( irc, cmd[1] ); - nick_del( irc, cmd[1] ); - - irc_usermsg( irc, "Buddy `%s' (nick %s) removed from contact list", s, cmd[1] ); - g_free( s ); - - return( 0 ); -} - -static int cmd_block( irc_t *irc, char **cmd ) -{ - struct gaim_connection *gc; - account_t *a; - - if( !cmd[2] ) - { - user_t *u = user_find( irc, cmd[1] ); - if( !u || !u->gc ) - { - irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] ); - return( 1 ); - } - gc = u->gc; - cmd[2] = u->handle; - } - else if( !( a = account_get( irc, cmd[1] ) ) ) - { - irc_usermsg( irc, "Invalid account" ); - return( 1 ); - } - else if( !( ( gc = a->gc ) && ( a->gc->flags & OPT_LOGGED_IN ) ) ) - { - irc_usermsg( irc, "That account is not on-line" ); - return( 1 ); - } - - if( !gc->prpl->add_deny || !gc->prpl->rem_permit ) - { - irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] ); - } - else - { - gc->prpl->rem_permit( gc, cmd[2] ); - gc->prpl->add_deny( gc, cmd[2] ); - irc_usermsg( irc, "Buddy `%s' moved from your permit- to your deny-list", cmd[2] ); - } - - return( 0 ); -} - -static int cmd_allow( irc_t *irc, char **cmd ) -{ - struct gaim_connection *gc; - account_t *a; - - if( !cmd[2] ) - { - user_t *u = user_find( irc, cmd[1] ); - if( !u || !u->gc ) - { - irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] ); - return( 1 ); - } - gc = u->gc; - cmd[2] = u->handle; - } - else if( !( a = account_get( irc, cmd[1] ) ) ) - { - irc_usermsg( irc, "Invalid account" ); - return( 1 ); - } - else if( !( ( gc = a->gc ) && ( a->gc->flags & OPT_LOGGED_IN ) ) ) - { - irc_usermsg( irc, "That account is not on-line" ); - return( 1 ); - } - - if( !gc->prpl->rem_deny || !gc->prpl->add_permit ) - { - irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] ); - } - else - { - gc->prpl->rem_deny( gc, cmd[2] ); - gc->prpl->add_permit( gc, cmd[2] ); - - irc_usermsg( irc, "Buddy `%s' moved from your deny- to your permit-list", cmd[2] ); - } - - return( 0 ); -} - -static int cmd_yesno( irc_t *irc, char **cmd ) -{ - query_t *q = NULL; - int numq = 0; - - if( irc->queries == NULL ) - { - irc_usermsg( irc, "Did I ask you something?" ); - return( 0 ); - } - - /* If there's an argument, the user seems to want to answer another question than the - first/last (depending on the query_order setting) one. */ - if( cmd[1] ) - { - if( sscanf( cmd[1], "%d", &numq ) != 1 ) - { - irc_usermsg( irc, "Invalid query number" ); - return( 0 ); - } - - for( q = irc->queries; q; q = q->next, numq -- ) - if( numq == 0 ) - break; - - if( !q ) - { - irc_usermsg( irc, "Uhm, I never asked you something like that..." ); - return( 0 ); - } - } - - if( g_strcasecmp( cmd[0], "yes" ) == 0 ) - query_answer( irc, q, 1 ); - else if( g_strcasecmp( cmd[0], "no" ) == 0 ) - query_answer( irc, q, 0 ); - - return( 1 ); -} - -static int cmd_set( irc_t *irc, char **cmd ) -{ - if( cmd[1] && cmd[2] ) - { - set_setstr( irc, cmd[1], cmd[2] ); - } - if( cmd[1] ) /* else 'forgotten' on purpose.. Must show new value after changing */ - { - char *s = set_getstr( irc, cmd[1] ); - if( s ) - irc_usermsg( irc, "%s = `%s'", cmd[1], s ); - } - else - { - set_t *s = irc->set; - while( s ) - { - if( s->value || s->def ) - irc_usermsg( irc, "%s = `%s'", s->key, s->value?s->value:s->def ); - s = s->next; - } - } - - return( 0 ); -} - -static int cmd_save( irc_t *irc, char **cmd ) -{ - if( storage_save( irc, TRUE ) == STORAGE_OK ) - irc_usermsg( irc, "Configuration saved" ); - else - irc_usermsg( irc, "Configuration could not be saved!" ); - - return( 0 ); -} - -static int cmd_blist( irc_t *irc, char **cmd ) -{ - int online = 0, away = 0, offline = 0; - user_t *u; - char s[64]; - int n_online = 0, n_away = 0, n_offline = 0; - - if( cmd[1] && g_strcasecmp( cmd[1], "all" ) == 0 ) - online = offline = away = 1; - else if( cmd[1] && g_strcasecmp( cmd[1], "offline" ) == 0 ) - offline = 1; - else if( cmd[1] && g_strcasecmp( cmd[1], "away" ) == 0 ) - away = 1; - else if( cmd[1] && g_strcasecmp( cmd[1], "online" ) == 0 ) - online = 1; - else - online = away = 1; - - irc_usermsg( irc, "%-16.16s %-40.40s %s", "Nick", "User/Host/Network", "Status" ); - - if( online == 1 ) for( u = irc->users; u; u = u->next ) if( u->gc && u->online && !u->away ) - { - g_snprintf( s, 63, "%s@%s (%s)", u->user, u->host, u->gc->user->prpl->name ); - irc_usermsg( irc, "%-16.16s %-40.40s %s", u->nick, s, "Online" ); - n_online ++; - } - - if( away == 1 ) for( u = irc->users; u; u = u->next ) if( u->gc && u->online && u->away ) - { - g_snprintf( s, 63, "%s@%s (%s)", u->user, u->host, u->gc->user->prpl->name ); - irc_usermsg( irc, "%-16.16s %-40.40s %s", u->nick, s, u->away ); - n_away ++; - } - - if( offline == 1 ) for( u = irc->users; u; u = u->next ) if( u->gc && !u->online ) - { - g_snprintf( s, 63, "%s@%s (%s)", u->user, u->host, u->gc->user->prpl->name ); - irc_usermsg( irc, "%-16.16s %-40.40s %s", u->nick, s, "Offline" ); - n_offline ++; - } - - irc_usermsg( irc, "%d buddies (%d available, %d away, %d offline)", n_online + n_away + n_offline, n_online, n_away, n_offline ); - - return( 0 ); -} - -static int cmd_nick( irc_t *irc, char **cmd ) -{ - account_t *a; - - if( !cmd[1] || !( a = account_get( irc, cmd[1] ) ) ) - { - irc_usermsg( irc, "Invalid account"); - } - else if( !( a->gc && ( a->gc->flags & OPT_LOGGED_IN ) ) ) - { - irc_usermsg( irc, "That account is not on-line" ); - } - else if ( !cmd[2] ) - { - irc_usermsg( irc, "Your name is `%s'" , a->gc->displayname ? a->gc->displayname : "NULL" ); - } - else if ( !a->gc->prpl->set_info ) - { - irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] ); - } - else - { - char utf8[1024]; - - irc_usermsg( irc, "Setting your name to `%s'", cmd[2] ); - - if( g_strncasecmp( set_getstr( irc, "charset" ), "none", 4 ) != 0 && - do_iconv( set_getstr( irc, "charset" ), "UTF-8", cmd[2], utf8, 0, 1024 ) != -1 ) - a->gc->prpl->set_info( a->gc, utf8 ); - else - a->gc->prpl->set_info( a->gc, cmd[2] ); - } - - return( 1 ); -} - -static int cmd_qlist( irc_t *irc, char **cmd ) -{ - query_t *q = irc->queries; - int num; - - if( !q ) - { - irc_usermsg( irc, "There are no pending questions." ); - return( 0 ); - } - - irc_usermsg( irc, "Pending queries:" ); - - for( num = 0; q; q = q->next, num ++ ) - if( q->gc ) /* Not necessary yet, but it might come later */ - irc_usermsg( irc, "%d, %s(%s): %s", num, q->gc->prpl->name, q->gc->username, q->question ); - else - irc_usermsg( irc, "%d, BitlBee: %s", num, q->question ); - - return( 0 ); -} - -static int cmd_import_buddies( irc_t *irc, char **cmd ) -{ - struct gaim_connection *gc; - account_t *a; - nick_t *n; - - if( !( a = account_get( irc, cmd[1] ) ) ) - { - irc_usermsg( irc, "Invalid account" ); - return( 0 ); - } - else if( !( ( gc = a->gc ) && ( a->gc->flags & OPT_LOGGED_IN ) ) ) - { - irc_usermsg( irc, "That account is not on-line" ); - return( 0 ); - } - - if( cmd[2] ) - { - if( g_strcasecmp( cmd[2], "clear" ) == 0 ) - { - user_t *u; - - for( u = irc->users; u; u = u->next ) - if( u->gc == gc ) - { - u->gc->prpl->remove_buddy( u->gc, u->handle, NULL ); - user_del( irc, u->nick ); - } - - irc_usermsg( irc, "Old buddy list cleared." ); - } - else - { - irc_usermsg( irc, "Invalid argument: %s", cmd[2] ); - return( 0 ); - } - } - - for( n = gc->irc->nicks; n; n = n->next ) - { - if( n->proto == gc->prpl && !user_findhandle( gc, n->handle ) ) - { - gc->prpl->add_buddy( gc, n->handle ); - add_buddy( gc, NULL, n->handle, NULL ); - } - } - - irc_usermsg( irc, "Sent all add requests. Please wait for a while, the server needs some time to handle all the adds." ); - - return( 0 ); -} - -const command_t commands[] = { - { "help", 0, cmd_help, 0 }, - { "identify", 1, cmd_identify, 0 }, - { "register", 1, cmd_register, 0 }, - { "drop", 1, cmd_drop, 0 }, - { "account", 1, cmd_account, 0 }, - { "add", 2, cmd_add, 0 }, - { "info", 1, cmd_info, 0 }, - { "rename", 2, cmd_rename, 0 }, - { "remove", 1, cmd_remove, 0 }, - { "block", 1, cmd_block, 0 }, - { "allow", 1, cmd_allow, 0 }, - { "save", 0, cmd_save, 0 }, - { "set", 0, cmd_set, 0 }, - { "yes", 0, cmd_yesno, 0 }, - { "no", 0, cmd_yesno, 0 }, - { "blist", 0, cmd_blist, 0 }, - { "nick", 1, cmd_nick, 0 }, - { "import_buddies", 1, cmd_import_buddies, 0 }, - { "qlist", 0, cmd_qlist, 0 }, - { NULL } -}; diff --git a/commands.h b/commands.h index a881499a..38572360 100644 --- a/commands.h +++ b/commands.h @@ -32,7 +32,7 @@ typedef struct command { char *command; int required_parameters; - int (*execute)(irc_t *, char **args); + void (*execute)(irc_t *, char **args); int flags; } command_t; diff --git a/ipc.c b/ipc.c index e0bf1319..8d44e4eb 100644 --- a/ipc.c +++ b/ipc.c @@ -31,7 +31,7 @@ GSList *child_list = NULL; -static int ipc_master_cmd_client( irc_t *data, char **cmd ) +static void ipc_master_cmd_client( irc_t *data, char **cmd ) { struct bitlbee_child *child = (void*) data; @@ -44,21 +44,17 @@ static int ipc_master_cmd_client( irc_t *data, char **cmd ) ipc_to_children_str( "OPERMSG :Client connecting (PID=%d): %s@%s (%s)\r\n", child ? child->pid : -1, cmd[2], cmd[1], cmd[3] ); - - return 1; } -static int ipc_master_cmd_die( irc_t *data, char **cmd ) +static void ipc_master_cmd_die( irc_t *data, char **cmd ) { if( global.conf->runmode == RUNMODE_FORKDAEMON ) ipc_to_children_str( "DIE\r\n" ); bitlbee_shutdown( NULL ); - - return 1; } -int ipc_master_cmd_rehash( irc_t *data, char **cmd ) +void ipc_master_cmd_rehash( irc_t *data, char **cmd ) { runmode_t oldmode; @@ -75,8 +71,6 @@ int ipc_master_cmd_rehash( irc_t *data, char **cmd ) if( global.conf->runmode == RUNMODE_FORKDAEMON ) ipc_to_children( cmd ); - - return 1; } static const command_t ipc_master_commands[] = { @@ -91,50 +85,39 @@ static const command_t ipc_master_commands[] = { }; -static int ipc_child_cmd_die( irc_t *irc, char **cmd ) +static void ipc_child_cmd_die( irc_t *irc, char **cmd ) { - if( irc->status >= USTATUS_LOGGED_IN ) - irc_write( irc, "ERROR :Operator requested server shutdown, bye bye!" ); - - irc_abort( irc ); - - return 1; + irc_abort( irc, 1, "Shutdown requested by operator" ); } -static int ipc_child_cmd_wallops( irc_t *irc, char **cmd ) +static void ipc_child_cmd_wallops( irc_t *irc, char **cmd ) { if( irc->status < USTATUS_LOGGED_IN ) - return 1; + return; if( strchr( irc->umode, 'w' ) ) irc_write( irc, ":%s WALLOPS :%s", irc->myhost, cmd[1] ); - - return 1; } -static int ipc_child_cmd_lilo( irc_t *irc, char **cmd ) +static void ipc_child_cmd_lilo( irc_t *irc, char **cmd ) { if( irc->status < USTATUS_LOGGED_IN ) - return 1; + return; if( strchr( irc->umode, 's' ) ) irc_write( irc, ":%s NOTICE %s :%s", irc->myhost, irc->nick, cmd[1] ); - - return 1; } -static int ipc_child_cmd_opermsg( irc_t *irc, char **cmd ) +static void ipc_child_cmd_opermsg( irc_t *irc, char **cmd ) { if( irc->status < USTATUS_LOGGED_IN ) - return 1; + return; if( strchr( irc->umode, 'o' ) ) irc_write( irc, ":%s NOTICE %s :*** OperMsg *** %s", irc->myhost, irc->nick, cmd[1] ); - - return 1; } -static int ipc_child_cmd_rehash( irc_t *irc, char **cmd ) +static void ipc_child_cmd_rehash( irc_t *irc, char **cmd ) { runmode_t oldmode; @@ -144,23 +127,18 @@ static int ipc_child_cmd_rehash( irc_t *irc, char **cmd ) global.conf = conf_load( 0, NULL ); global.conf->runmode = oldmode; - - return 1; } -static int ipc_child_cmd_kill( irc_t *irc, char **cmd ) +static void ipc_child_cmd_kill( irc_t *irc, char **cmd ) { if( irc->status < USTATUS_LOGGED_IN ) - return 1; + return; if( nick_cmp( cmd[1], irc->nick ) != 0 ) - return 1; /* It's not for us. */ + return; /* It's not for us. */ irc_write( irc, ":%s!%s@%s KILL %s :%s", irc->mynick, irc->mynick, irc->myhost, irc->nick, cmd[2] ); - irc_abort( irc ); - /* g_io_channel_close( irc->io_channel ); */ - - return 0; + irc_abort( irc, 0, "Killed by operator: %s", cmd[2] ); } static const command_t ipc_child_commands[] = { diff --git a/ipc.h b/ipc.h index 308b6e4b..b69a6ae5 100644 --- a/ipc.h +++ b/ipc.h @@ -51,7 +51,7 @@ void ipc_to_children( char **cmd ); void ipc_to_children_str( char *format, ... ); /* We need this function in inetd mode, so let's just make it non-static. */ -int ipc_master_cmd_rehash( irc_t *data, char **cmd ); +void ipc_master_cmd_rehash( irc_t *data, char **cmd ); extern GSList *child_list; diff --git a/irc.c b/irc.c index 5c1b0e69..93cbc293 100644 --- a/irc.c +++ b/irc.c @@ -151,23 +151,25 @@ irc_t *irc_new( int fd ) return( irc ); } +/* immed=1 makes this function pretty much equal to irc_free(), except that + this one will "log". In case the connection is already broken and we + shouldn't try to write to it. */ void irc_abort( irc_t *irc, int immed, char *format, ... ) { - va_list params; - if( format != NULL ) { + va_list params; char *reason; va_start( params, format ); - reason = g_strdup_printf( format, params ); + reason = g_strdup_vprintf( format, params ); va_end( params ); if( !immed ) irc_write( irc, "ERROR :Closing link: %s", reason ); ipc_to_master_str( "OPERMSG :Client exiting: %s@%s [%s]\r\n", - irc->nick, irc->host, reason" ); + irc->nick ? irc->nick : "(NONE)", irc->host, reason ); g_free( reason ); } @@ -177,7 +179,7 @@ void irc_abort( irc_t *irc, int immed, char *format, ... ) irc_write( irc, "ERROR :Closing link" ); ipc_to_master_str( "OPERMSG :Client exiting: %s@%s [%s]\r\n", - irc->nick, irc->host, "No reason given" ); + irc->nick ? irc->nick : "(NONE)", irc->host, "No reason given" ); } irc->status = USTATUS_SHUTDOWN; @@ -338,7 +340,7 @@ void irc_setpass (irc_t *irc, const char *pass) } } -int irc_process( irc_t *irc ) +void irc_process( irc_t *irc ) { char **lines, *temp, **cmd; int i; @@ -360,14 +362,16 @@ int irc_process( irc_t *irc ) if( ( cmd = irc_parse_line( lines[i] ) ) == NULL ) continue; - if( !irc_exec( irc, cmd ) ) + irc_exec( irc, cmd ); + + g_free( cmd ); + + /* Shouldn't really happen, but just in case... */ + if( !g_slist_find( irc_connection_list, irc ) ) { - g_free( cmd ); g_free( lines ); - return 0; + return; } - - g_free( cmd ); } if( lines[i] != NULL ) @@ -378,8 +382,6 @@ int irc_process( irc_t *irc ) g_free( lines ); } - - return 1; } char **irc_tokenize( char *buffer ) @@ -971,7 +973,10 @@ int irc_send( irc_t *irc, char *nick, char *s, int flags ) } if( u->send_handler ) - return( u->send_handler( irc, u, s, flags ) ); + { + u->send_handler( irc, u, s, flags ); + return 1; + } } else if( c && c->gc && c->gc->prpl ) { @@ -997,9 +1002,9 @@ gboolean buddy_send_handler_delayed( gpointer data ) return( FALSE ); } -int buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags ) +void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags ) { - if( !u || !u->gc ) return( 0 ); + if( !u || !u->gc ) return; if( set_getint( irc, "buddy_sendbuffer" ) && set_getint( irc, "buddy_sendbuffer_delay" ) > 0 ) { @@ -1035,12 +1040,10 @@ int buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags ) if( u->sendbuf_timer > 0 ) g_source_remove( u->sendbuf_timer ); u->sendbuf_timer = g_timeout_add( delay, buddy_send_handler_delayed, u ); - - return( 1 ); } else { - return( serv_send_im( irc, u, msg, flags ) ); + serv_send_im( irc, u, msg, flags ); } } @@ -1145,7 +1148,7 @@ static gboolean irc_userping( gpointer _irc ) if( rv > 0 ) { - irc_abort( irc, "ERROR :Closing Link: Ping Timeout: %d seconds", rv ); + irc_abort( irc, 0, "Ping Timeout: %d seconds", rv ); return FALSE; } diff --git a/irc.h b/irc.h index 1cf39504..5c53273a 100644 --- a/irc.h +++ b/irc.h @@ -107,8 +107,8 @@ irc_t *irc_new( int fd ); void irc_abort( irc_t *irc, int immed, char *format, ... ); void irc_free( irc_t *irc ); -int irc_exec( irc_t *irc, char **cmd ); -int irc_process( irc_t *irc ); +void irc_exec( irc_t *irc, char **cmd ); +void irc_process( irc_t *irc ); char **irc_parse_line( char *line ); char *irc_build_line( char **cmd ); @@ -133,7 +133,6 @@ void irc_kick( irc_t *irc, user_t *u, char *channel, user_t *kicker ); void irc_kill( irc_t *irc, user_t *u ); void irc_invite( irc_t *irc, char *nick, char *channel ); void irc_whois( irc_t *irc, char *nick ); -int irc_away( irc_t *irc, char *away ); void irc_setpass( irc_t *irc, const char *pass ); /* USE WITH CAUTION! */ int irc_send( irc_t *irc, char *nick, char *s, int flags ); @@ -141,6 +140,6 @@ int irc_privmsg( irc_t *irc, user_t *u, char *type, char *to, char *prefix, char int irc_msgfrom( irc_t *irc, char *nick, char *msg ); int irc_noticefrom( irc_t *irc, char *nick, char *msg ); -int buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags ); +void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags ); #endif diff --git a/irc_commands.c b/irc_commands.c index e31a92e8..e4dc4f3e 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -27,7 +27,7 @@ #include "bitlbee.h" #include "ipc.h" -static int irc_cmd_pass( irc_t *irc, char **cmd ) +static void irc_cmd_pass( irc_t *irc, char **cmd ) { if( global.conf->auth_pass && strcmp( cmd[1], global.conf->auth_pass ) == 0 ) { @@ -38,21 +38,17 @@ static int irc_cmd_pass( irc_t *irc, char **cmd ) { irc_reply( irc, 464, ":Incorrect password" ); } - - return( 1 ); } -static int irc_cmd_user( irc_t *irc, char **cmd ) +static void irc_cmd_user( irc_t *irc, char **cmd ) { irc->user = g_strdup( cmd[1] ); irc->realname = g_strdup( cmd[4] ); irc_check_login( irc ); - - return( 1 ); } -static int irc_cmd_nick( irc_t *irc, char **cmd ) +static void irc_cmd_nick( irc_t *irc, char **cmd ) { if( irc->nick ) { @@ -74,26 +70,22 @@ static int irc_cmd_nick( irc_t *irc, char **cmd ) irc_check_login( irc ); } - - return( 1 ); } -static int irc_cmd_quit( irc_t *irc, char **cmd ) +static void irc_cmd_quit( irc_t *irc, char **cmd ) { - irc_write( irc, "ERROR :%s%s", cmd[1]?"Quit: ":"", cmd[1]?cmd[1]:"Client Quit" ); - /* g_io_channel_close( irc->io_channel ); */ - - return( 0 ); + if( cmd[1] && *cmd[1] ) + irc_abort( irc, 0, "Quit: %s", cmd[1] ); + else + irc_abort( irc, 0, "Leaving..." ); } -static int irc_cmd_ping( irc_t *irc, char **cmd ) +static void irc_cmd_ping( irc_t *irc, char **cmd ) { irc_write( irc, ":%s PONG %s :%s", irc->myhost, irc->myhost, cmd[1]?cmd[1]:irc->myhost ); - - return( 1 ); } -static int irc_cmd_oper( irc_t *irc, char **cmd ) +static void irc_cmd_oper( irc_t *irc, char **cmd ) { if( global.conf->oper_pass && strcmp( cmd[2], global.conf->oper_pass ) == 0 ) { @@ -104,11 +96,9 @@ static int irc_cmd_oper( irc_t *irc, char **cmd ) { irc_reply( irc, 432, ":Incorrect password" ); } - - return( 1 ); } -static int irc_cmd_mode( irc_t *irc, char **cmd ) +static void irc_cmd_mode( irc_t *irc, char **cmd ) { if( *cmd[1] == '#' || *cmd[1] == '&' ) { @@ -132,18 +122,14 @@ static int irc_cmd_mode( irc_t *irc, char **cmd ) else irc_reply( irc, 502, ":Don't touch their modes" ); } - - return( 1 ); } -static int irc_cmd_names( irc_t *irc, char **cmd ) +static void irc_cmd_names( irc_t *irc, char **cmd ) { irc_names( irc, cmd[1]?cmd[1]:irc->channel ); - - return( 1 ); } -static int irc_cmd_part( irc_t *irc, char **cmd ) +static void irc_cmd_part( irc_t *irc, char **cmd ) { struct conversation *c; @@ -171,11 +157,9 @@ static int irc_cmd_part( irc_t *irc, char **cmd ) { irc_reply( irc, 403, "%s :No such channel", cmd[1] ); } - - return( 1 ); } -static int irc_cmd_join( irc_t *irc, char **cmd ) +static void irc_cmd_join( irc_t *irc, char **cmd ) { if( g_strcasecmp( cmd[1], irc->channel ) == 0 ) ; /* Dude, you're already there... @@ -209,11 +193,9 @@ static int irc_cmd_join( irc_t *irc, char **cmd ) irc_reply( irc, 403, "%s :No such channel", cmd[1] ); } } - - return( 1 ); } -static int irc_cmd_invite( irc_t *irc, char **cmd ) +static void irc_cmd_invite( irc_t *irc, char **cmd ) { char *nick = cmd[1], *channel = cmd[2]; struct conversation *c = conv_findchannel( channel ); @@ -224,15 +206,13 @@ static int irc_cmd_invite( irc_t *irc, char **cmd ) { c->gc->prpl->chat_invite( c->gc, c->id, "", u->handle ); irc_reply( irc, 341, "%s %s", nick, channel ); - return( 1 ); + return; } irc_reply( irc, 482, "%s :Invite impossible; User/Channel non-existent or incompatible", channel ); - - return( 1 ); } -static int irc_cmd_privmsg( irc_t *irc, char **cmd ) +static void irc_cmd_privmsg( irc_t *irc, char **cmd ) { if ( !cmd[2] ) { @@ -282,11 +262,9 @@ static int irc_cmd_privmsg( irc_t *irc, char **cmd ) } irc_send( irc, cmd[1], cmd[2], ( g_strcasecmp( cmd[0], "NOTICE" ) == 0 ) ? IM_FLAG_AWAY : 0 ); } - - return( 1 ); } -static int irc_cmd_who( irc_t *irc, char **cmd ) +static void irc_cmd_who( irc_t *irc, char **cmd ) { char *channel = cmd[1]; user_t *u = irc->users; @@ -316,11 +294,9 @@ static int irc_cmd_who( irc_t *irc, char **cmd ) irc_reply( irc, 352, "%s %s %s %s %s %c :0 %s", channel, u->user, u->host, irc->myhost, u->nick, u->online ? ( u->away ? 'G' : 'H' ) : 'G', u->realname ); irc_reply( irc, 315, "%s :End of /WHO list", channel?channel:"**" ); - - return( 1 ); } -static int irc_cmd_userhost( irc_t *irc, char **cmd ) +static void irc_cmd_userhost( irc_t *irc, char **cmd ) { user_t *u; int i; @@ -339,11 +315,9 @@ static int irc_cmd_userhost( irc_t *irc, char **cmd ) else irc_reply( irc, 302, ":%s=+%s@%s", u->nick, u->user, u->host ); } - - return( 1 ); } -static int irc_cmd_ison( irc_t *irc, char **cmd ) +static void irc_cmd_ison( irc_t *irc, char **cmd ) { user_t *u; char buff[IRC_MAX_LINE]; @@ -382,11 +356,9 @@ static int irc_cmd_ison( irc_t *irc, char **cmd ) buff[strlen(buff)-1] = '\0'; irc_reply( irc, 303, ":%s", buff ); - - return( 1 ); } -static int irc_cmd_watch( irc_t *irc, char **cmd ) +static void irc_cmd_watch( irc_t *irc, char **cmd ) { int i; @@ -429,27 +401,23 @@ static int irc_cmd_watch( irc_t *irc, char **cmd ) } } } - - return( 1 ); } -static int irc_cmd_topic( irc_t *irc, char **cmd ) +static void irc_cmd_topic( irc_t *irc, char **cmd ) { if( cmd[2] ) irc_reply( irc, 482, "%s :Cannot change topic", cmd[1] ); else irc_topic( irc, cmd[1] ); - - return( 1 ); } -static int irc_cmd_away( irc_t *irc, char **cmd ) +static void irc_cmd_away( irc_t *irc, char **cmd ) { user_t *u = user_find( irc, irc->nick ); GSList *c = get_connections(); char *away = cmd[1]; - if( !u ) return( 1 ); + if( !u ) return; if( away && *away ) { @@ -481,11 +449,9 @@ static int irc_cmd_away( irc_t *irc, char **cmd ) c = c->next; } - - return( 1 ); } -static int irc_cmd_whois( irc_t *irc, char **cmd ) +static void irc_cmd_whois( irc_t *irc, char **cmd ) { char *nick = cmd[1]; user_t *u = user_find( irc, nick ); @@ -511,11 +477,9 @@ static int irc_cmd_whois( irc_t *irc, char **cmd ) { irc_reply( irc, 401, "%s :Nick does not exist", nick ); } - - return( 1 ); } -static int irc_cmd_whowas( irc_t *irc, char **cmd ) +static void irc_cmd_whowas( irc_t *irc, char **cmd ) { /* For some reason irssi tries a whowas when whois fails. We can ignore this, but then the user never gets a "user not found" @@ -524,37 +488,29 @@ static int irc_cmd_whowas( irc_t *irc, char **cmd ) irc_reply( irc, 406, "%s :Nick does not exist", cmd[1] ); irc_reply( irc, 369, "%s :End of WHOWAS", cmd[1] ); - - return( 1 ); } -static int irc_cmd_nickserv( irc_t *irc, char **cmd ) +static void irc_cmd_nickserv( irc_t *irc, char **cmd ) { /* [SH] This aliases the NickServ command to PRIVMSG root */ /* [TV] This aliases the NS command to PRIVMSG root as well */ root_command( irc, cmd + 1 ); - - return( 1 ); } -static int irc_cmd_motd( irc_t *irc, char **cmd ) +static void irc_cmd_motd( irc_t *irc, char **cmd ) { irc_motd( irc ); - - return( 1 ); } -static int irc_cmd_pong( irc_t *irc, char **cmd ) +static void irc_cmd_pong( irc_t *irc, char **cmd ) { /* We could check the value we get back from the user, but in fact we don't care, we're just happy he's still alive. */ irc->last_pong = gettime(); irc->pinging = 0; - - return( 1 ); } -static int irc_cmd_completions( irc_t *irc, char **cmd ) +static void irc_cmd_completions( irc_t *irc, char **cmd ) { user_t *u = user_find( irc, irc->mynick ); help_t *h; @@ -573,11 +529,9 @@ static int irc_cmd_completions( irc_t *irc, char **cmd ) irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS set ", s->key ); irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", "END" ); - - return( 1 ); } -static int irc_cmd_rehash( irc_t *irc, char **cmd ) +static void irc_cmd_rehash( irc_t *irc, char **cmd ) { if( global.conf->runmode == RUNMODE_INETD ) ipc_master_cmd_rehash( NULL, NULL ); @@ -585,8 +539,6 @@ static int irc_cmd_rehash( irc_t *irc, char **cmd ) ipc_to_master( cmd ); irc_reply( irc, 382, "%s :Rehashing", CONF_FILE ); - - return( 1 ); } static const command_t irc_commands[] = { @@ -624,12 +576,12 @@ static const command_t irc_commands[] = { { NULL } }; -int irc_exec( irc_t *irc, char *cmd[] ) +void irc_exec( irc_t *irc, char *cmd[] ) { - int i, j; + int i; if( !cmd[0] ) - return( 1 ); + return; for( i = 0; irc_commands[i].command; i++ ) if( g_strcasecmp( irc_commands[i].command, cmd[0] ) == 0 ) @@ -637,33 +589,30 @@ int irc_exec( irc_t *irc, char *cmd[] ) if( irc_commands[i].flags & IRC_CMD_PRE_LOGIN && irc->status >= USTATUS_LOGGED_IN ) { irc_reply( irc, 462, ":Only allowed before logging in" ); - return( 1 ); } - if( irc_commands[i].flags & IRC_CMD_LOGGED_IN && irc->status < USTATUS_LOGGED_IN ) + else if( irc_commands[i].flags & IRC_CMD_LOGGED_IN && irc->status < USTATUS_LOGGED_IN ) { irc_reply( irc, 451, ":Register first" ); - return( 1 ); } - if( irc_commands[i].flags & IRC_CMD_OPER_ONLY && !strchr( irc->umode, 'o' ) ) + else if( irc_commands[i].flags & IRC_CMD_OPER_ONLY && !strchr( irc->umode, 'o' ) ) { irc_reply( irc, 481, ":Permission denied - You're not an IRC operator" ); - return( 1 ); } - - for( j = 1; j <= irc_commands[i].required_parameters; j ++ ) - if( !cmd[j] ) - { - irc_reply( irc, 461, "%s :Need more parameters", cmd[0] ); - return( 1 ); - } - - if( irc_commands[i].flags & IRC_CMD_TO_MASTER ) + else if( !cmd[irc_commands[i].required_parameters] ) + { + irc_reply( irc, 461, "%s :Need more parameters", cmd[0] ); + } + else if( irc_commands[i].flags & IRC_CMD_TO_MASTER ) + { /* IPC doesn't make sense in inetd mode, but the function will catch that. */ ipc_to_master( cmd ); + } else - return irc_commands[i].execute( irc, cmd ); + { + irc_commands[i].execute( irc, cmd ); + } + + break; } - - return( 1 ); } diff --git a/root_commands.c b/root_commands.c new file mode 100644 index 00000000..426cf6e8 --- /dev/null +++ b/root_commands.c @@ -0,0 +1,800 @@ + /********************************************************************\ + * BitlBee -- An IRC to other IM-networks gateway * + * * + * Copyright 2002-2004 Wilmer van der Gaast and others * + \********************************************************************/ + +/* User manager (root) commands */ + +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA +*/ + +#define BITLBEE_CORE +#include "commands.h" +#include "crypting.h" +#include "bitlbee.h" +#include "help.h" + +#include + +void root_command_string( irc_t *irc, user_t *u, char *command, int flags ) +{ + char *cmd[IRC_MAX_ARGS]; + char *s; + int k; + char q = 0; + + memset( cmd, 0, sizeof( cmd ) ); + cmd[0] = command; + k = 1; + for( s = command; *s && k < ( IRC_MAX_ARGS - 1 ); s ++ ) + if( *s == ' ' && !q ) + { + *s = 0; + while( *++s == ' ' ); + if( *s == '"' || *s == '\'' ) + { + q = *s; + s ++; + } + if( *s ) + { + cmd[k++] = s; + s --; + } + } + else if( *s == q ) + { + q = *s = 0; + } + cmd[k] = NULL; + + root_command( irc, cmd ); +} + +void root_command( irc_t *irc, char *cmd[] ) +{ + int i; + + if( !cmd[0] ) + return; + + for( i = 0; commands[i].command; i++ ) + if( g_strcasecmp( commands[i].command, cmd[0] ) == 0 ) + { + if( !cmd[commands[i].required_parameters] ) + { + irc_usermsg( irc, "Not enough parameters given (need %d)", commands[i].required_parameters ); + return; + } + commands[i].execute( irc, cmd ); + return; + } + + irc_usermsg( irc, "Unknown command: %s. Please use \x02help commands\x02 to get a list of available commands.", cmd[0] ); +} + +static void cmd_help( irc_t *irc, char **cmd ) +{ + char param[80]; + int i; + char *s; + + memset( param, 0, sizeof(param) ); + for ( i = 1; (cmd[i] != NULL && ( strlen(param) < (sizeof(param)-1) ) ); i++ ) { + if ( i != 1 ) // prepend space except for the first parameter + strcat(param, " "); + strncat( param, cmd[i], sizeof(param) - strlen(param) - 1 ); + } + + s = help_get( &(global.help), param ); + if( !s ) s = help_get( &(global.help), "" ); + + if( s ) + { + irc_usermsg( irc, "%s", s ); + g_free( s ); + } + else + { + irc_usermsg( irc, "Error opening helpfile." ); + } +} + +static void cmd_identify( irc_t *irc, char **cmd ) +{ + storage_status_t status = storage_load( irc->nick, cmd[1], irc ); + + switch (status) { + case STORAGE_INVALID_PASSWORD: + irc_usermsg( irc, "Incorrect password" ); + break; + case STORAGE_NO_SUCH_USER: + irc_usermsg( irc, "The nick is (probably) not registered" ); + break; + case STORAGE_OK: + irc_usermsg( irc, "Password accepted" ); + irc_umode_set( irc, "+R", 1 ); + break; + default: + irc_usermsg( irc, "Something very weird happened" ); + break; + } +} + +static void cmd_register( irc_t *irc, char **cmd ) +{ + if( global.conf->authmode == AUTHMODE_REGISTERED ) + { + irc_usermsg( irc, "This server does not allow registering new accounts" ); + return; + } + + irc_setpass( irc, cmd[1] ); + switch( storage_save( irc, FALSE )) { + case STORAGE_ALREADY_EXISTS: + irc_usermsg( irc, "Nick is already registered" ); + break; + + case STORAGE_OK: + irc->status = USTATUS_IDENTIFIED; + irc_umode_set( irc, "+R", 1 ); + break; + + default: + irc_usermsg( irc, "Error registering" ); + break; + } +} + +static void cmd_drop( irc_t *irc, char **cmd ) +{ + storage_status_t status; + + status = storage_remove (irc->nick, cmd[1]); + switch (status) { + case STORAGE_NO_SUCH_USER: + irc_usermsg( irc, "That account does not exist" ); + break; + case STORAGE_INVALID_PASSWORD: + irc_usermsg( irc, "Password invalid" ); + break; + case STORAGE_OK: + irc_setpass( irc, NULL ); + irc->status = USTATUS_LOGGED_IN; + irc_umode_set( irc, "-R", 1 ); + irc_usermsg( irc, "Account `%s' removed", irc->nick ); + break; + default: + irc_usermsg( irc, "Error: '%d'", status ); + break; + } +} + +static void cmd_account( irc_t *irc, char **cmd ) +{ + account_t *a; + + if( global.conf->authmode == AUTHMODE_REGISTERED && irc->status < USTATUS_IDENTIFIED ) + { + irc_usermsg( irc, "This server only accepts registered users" ); + return; + } + + if( g_strcasecmp( cmd[1], "add" ) == 0 ) + { + struct prpl *prpl; + + if( cmd[2] == NULL || cmd[3] == NULL || cmd[4] == NULL ) + { + irc_usermsg( irc, "Not enough parameters" ); + return; + } + + prpl = find_protocol(cmd[2]); + + if( prpl == NULL ) + { + irc_usermsg( irc, "Unknown protocol" ); + return; + } + + a = account_add( irc, prpl, cmd[3], cmd[4] ); + + if( cmd[5] ) + a->server = g_strdup( cmd[5] ); + + irc_usermsg( irc, "Account successfully added" ); + } + else if( g_strcasecmp( cmd[1], "del" ) == 0 ) + { + if( !cmd[2] ) + { + irc_usermsg( irc, "Not enough parameters given (need %d)", 2 ); + } + else if( !( a = account_get( irc, cmd[2] ) ) ) + { + irc_usermsg( irc, "Invalid account" ); + } + else if( a->gc ) + { + irc_usermsg( irc, "Account is still logged in, can't delete" ); + } + else + { + account_del( irc, a ); + irc_usermsg( irc, "Account deleted" ); + } + } + else if( g_strcasecmp( cmd[1], "list" ) == 0 ) + { + int i = 0; + + for( a = irc->accounts; a; a = a->next ) + { + char *con; + + if( a->gc && ( a->gc->flags & OPT_LOGGED_IN ) ) + con = " (connected)"; + else if( a->gc ) + con = " (connecting)"; + else if( a->reconnect ) + con = " (awaiting reconnect)"; + else + con = ""; + + irc_usermsg( irc, "%2d. %s, %s%s", i, a->prpl->name, a->user, con ); + + i ++; + } + irc_usermsg( irc, "End of account list" ); + } + else if( g_strcasecmp( cmd[1], "on" ) == 0 ) + { + if( cmd[2] ) + { + if( ( a = account_get( irc, cmd[2] ) ) ) + { + if( a->gc ) + { + irc_usermsg( irc, "Account already online" ); + return; + } + else + { + account_on( irc, a ); + } + } + else + { + irc_usermsg( irc, "Invalid account" ); + return; + } + } + else + { + if ( irc->accounts ) { + irc_usermsg( irc, "Trying to get all accounts connected..." ); + + for( a = irc->accounts; a; a = a->next ) + if( !a->gc ) + account_on( irc, a ); + } + else + { + irc_usermsg( irc, "No accounts known. Use 'account add' to add one." ); + } + } + } + else if( g_strcasecmp( cmd[1], "off" ) == 0 ) + { + if( !cmd[2] ) + { + irc_usermsg( irc, "Deactivating all active (re)connections..." ); + + for( a = irc->accounts; a; a = a->next ) + { + if( a->gc ) + account_off( irc, a ); + else if( a->reconnect ) + cancel_auto_reconnect( a ); + } + } + else if( ( a = account_get( irc, cmd[2] ) ) ) + { + if( a->gc ) + { + account_off( irc, a ); + } + else if( a->reconnect ) + { + cancel_auto_reconnect( a ); + irc_usermsg( irc, "Reconnect cancelled" ); + } + else + { + irc_usermsg( irc, "Account already offline" ); + return; + } + } + else + { + irc_usermsg( irc, "Invalid account" ); + return; + } + } + else + { + irc_usermsg( irc, "Unknown command: account %s. Please use \x02help commands\x02 to get a list of available commands.", cmd[1] ); + } +} + +static void cmd_add( irc_t *irc, char **cmd ) +{ + account_t *a; + + if( !( a = account_get( irc, cmd[1] ) ) ) + { + irc_usermsg( irc, "Invalid account" ); + return; + } + else if( !( a->gc && ( a->gc->flags & OPT_LOGGED_IN ) ) ) + { + irc_usermsg( irc, "That account is not on-line" ); + return; + } + + if( cmd[3] ) + { + if( !nick_ok( cmd[3] ) ) + { + irc_usermsg( irc, "The requested nick `%s' is invalid", cmd[3] ); + return; + } + else if( user_find( irc, cmd[3] ) ) + { + irc_usermsg( irc, "The requested nick `%s' already exists", cmd[3] ); + return; + } + else + { + nick_set( irc, cmd[2], a->gc->prpl, cmd[3] ); + } + } + a->gc->prpl->add_buddy( a->gc, cmd[2] ); + add_buddy( a->gc, NULL, cmd[2], cmd[2] ); + + irc_usermsg( irc, "User `%s' added to your contact list as `%s'", cmd[2], user_findhandle( a->gc, cmd[2] )->nick ); +} + +static void cmd_info( irc_t *irc, char **cmd ) +{ + struct gaim_connection *gc; + account_t *a; + + if( !cmd[2] ) + { + user_t *u = user_find( irc, cmd[1] ); + if( !u || !u->gc ) + { + irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] ); + return; + } + gc = u->gc; + cmd[2] = u->handle; + } + else if( !( a = account_get( irc, cmd[1] ) ) ) + { + irc_usermsg( irc, "Invalid account" ); + return; + } + else if( !( ( gc = a->gc ) && ( a->gc->flags & OPT_LOGGED_IN ) ) ) + { + irc_usermsg( irc, "That account is not on-line" ); + return; + } + + if( !gc->prpl->get_info ) + { + irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] ); + } + else + { + gc->prpl->get_info( gc, cmd[2] ); + } +} + +static void cmd_rename( irc_t *irc, char **cmd ) +{ + user_t *u; + + if( g_strcasecmp( cmd[1], irc->nick ) == 0 ) + { + irc_usermsg( irc, "Nick `%s' can't be changed", cmd[1] ); + } + else if( user_find( irc, cmd[2] ) && ( nick_cmp( cmd[1], cmd[2] ) != 0 ) ) + { + irc_usermsg( irc, "Nick `%s' already exists", cmd[2] ); + } + else if( !nick_ok( cmd[2] ) ) + { + irc_usermsg( irc, "Nick `%s' is invalid", cmd[2] ); + } + else if( !( u = user_find( irc, cmd[1] ) ) ) + { + irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] ); + } + else + { + user_rename( irc, cmd[1], cmd[2] ); + irc_write( irc, ":%s!%s@%s NICK %s", cmd[1], u->user, u->host, cmd[2] ); + if( g_strcasecmp( cmd[1], irc->mynick ) == 0 ) + { + g_free( irc->mynick ); + irc->mynick = g_strdup( cmd[2] ); + } + else if( u->send_handler == buddy_send_handler ) + { + nick_set( irc, u->handle, u->gc->prpl, cmd[2] ); + } + + irc_usermsg( irc, "Nick successfully changed" ); + } +} + +static void cmd_remove( irc_t *irc, char **cmd ) +{ + user_t *u; + char *s; + + if( !( u = user_find( irc, cmd[1] ) ) || !u->gc ) + { + irc_usermsg( irc, "Buddy `%s' not found", cmd[1] ); + return; + } + s = g_strdup( u->handle ); + + u->gc->prpl->remove_buddy( u->gc, u->handle, NULL ); + user_del( irc, cmd[1] ); + nick_del( irc, cmd[1] ); + + irc_usermsg( irc, "Buddy `%s' (nick %s) removed from contact list", s, cmd[1] ); + g_free( s ); + + return; +} + +static void cmd_block( irc_t *irc, char **cmd ) +{ + struct gaim_connection *gc; + account_t *a; + + if( !cmd[2] ) + { + user_t *u = user_find( irc, cmd[1] ); + if( !u || !u->gc ) + { + irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] ); + return; + } + gc = u->gc; + cmd[2] = u->handle; + } + else if( !( a = account_get( irc, cmd[1] ) ) ) + { + irc_usermsg( irc, "Invalid account" ); + return; + } + else if( !( ( gc = a->gc ) && ( a->gc->flags & OPT_LOGGED_IN ) ) ) + { + irc_usermsg( irc, "That account is not on-line" ); + return; + } + + if( !gc->prpl->add_deny || !gc->prpl->rem_permit ) + { + irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] ); + } + else + { + gc->prpl->rem_permit( gc, cmd[2] ); + gc->prpl->add_deny( gc, cmd[2] ); + irc_usermsg( irc, "Buddy `%s' moved from your permit- to your deny-list", cmd[2] ); + } +} + +static void cmd_allow( irc_t *irc, char **cmd ) +{ + struct gaim_connection *gc; + account_t *a; + + if( !cmd[2] ) + { + user_t *u = user_find( irc, cmd[1] ); + if( !u || !u->gc ) + { + irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] ); + return; + } + gc = u->gc; + cmd[2] = u->handle; + } + else if( !( a = account_get( irc, cmd[1] ) ) ) + { + irc_usermsg( irc, "Invalid account" ); + return; + } + else if( !( ( gc = a->gc ) && ( a->gc->flags & OPT_LOGGED_IN ) ) ) + { + irc_usermsg( irc, "That account is not on-line" ); + return; + } + + if( !gc->prpl->rem_deny || !gc->prpl->add_permit ) + { + irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] ); + } + else + { + gc->prpl->rem_deny( gc, cmd[2] ); + gc->prpl->add_permit( gc, cmd[2] ); + + irc_usermsg( irc, "Buddy `%s' moved from your deny- to your permit-list", cmd[2] ); + } +} + +static void cmd_yesno( irc_t *irc, char **cmd ) +{ + query_t *q = NULL; + int numq = 0; + + if( irc->queries == NULL ) + { + irc_usermsg( irc, "Did I ask you something?" ); + return; + } + + /* If there's an argument, the user seems to want to answer another question than the + first/last (depending on the query_order setting) one. */ + if( cmd[1] ) + { + if( sscanf( cmd[1], "%d", &numq ) != 1 ) + { + irc_usermsg( irc, "Invalid query number" ); + return; + } + + for( q = irc->queries; q; q = q->next, numq -- ) + if( numq == 0 ) + break; + + if( !q ) + { + irc_usermsg( irc, "Uhm, I never asked you something like that..." ); + return; + } + } + + if( g_strcasecmp( cmd[0], "yes" ) == 0 ) + query_answer( irc, q, 1 ); + else if( g_strcasecmp( cmd[0], "no" ) == 0 ) + query_answer( irc, q, 0 ); +} + +static void cmd_set( irc_t *irc, char **cmd ) +{ + if( cmd[1] && cmd[2] ) + { + set_setstr( irc, cmd[1], cmd[2] ); + } + if( cmd[1] ) /* else 'forgotten' on purpose.. Must show new value after changing */ + { + char *s = set_getstr( irc, cmd[1] ); + if( s ) + irc_usermsg( irc, "%s = `%s'", cmd[1], s ); + } + else + { + set_t *s = irc->set; + while( s ) + { + if( s->value || s->def ) + irc_usermsg( irc, "%s = `%s'", s->key, s->value?s->value:s->def ); + s = s->next; + } + } +} + +static void cmd_save( irc_t *irc, char **cmd ) +{ + if( storage_save( irc, TRUE ) == STORAGE_OK ) + irc_usermsg( irc, "Configuration saved" ); + else + irc_usermsg( irc, "Configuration could not be saved!" ); +} + +static void cmd_blist( irc_t *irc, char **cmd ) +{ + int online = 0, away = 0, offline = 0; + user_t *u; + char s[64]; + int n_online = 0, n_away = 0, n_offline = 0; + + if( cmd[1] && g_strcasecmp( cmd[1], "all" ) == 0 ) + online = offline = away = 1; + else if( cmd[1] && g_strcasecmp( cmd[1], "offline" ) == 0 ) + offline = 1; + else if( cmd[1] && g_strcasecmp( cmd[1], "away" ) == 0 ) + away = 1; + else if( cmd[1] && g_strcasecmp( cmd[1], "online" ) == 0 ) + online = 1; + else + online = away = 1; + + irc_usermsg( irc, "%-16.16s %-40.40s %s", "Nick", "User/Host/Network", "Status" ); + + if( online == 1 ) for( u = irc->users; u; u = u->next ) if( u->gc && u->online && !u->away ) + { + g_snprintf( s, 63, "%s@%s (%s)", u->user, u->host, u->gc->user->prpl->name ); + irc_usermsg( irc, "%-16.16s %-40.40s %s", u->nick, s, "Online" ); + n_online ++; + } + + if( away == 1 ) for( u = irc->users; u; u = u->next ) if( u->gc && u->online && u->away ) + { + g_snprintf( s, 63, "%s@%s (%s)", u->user, u->host, u->gc->user->prpl->name ); + irc_usermsg( irc, "%-16.16s %-40.40s %s", u->nick, s, u->away ); + n_away ++; + } + + if( offline == 1 ) for( u = irc->users; u; u = u->next ) if( u->gc && !u->online ) + { + g_snprintf( s, 63, "%s@%s (%s)", u->user, u->host, u->gc->user->prpl->name ); + irc_usermsg( irc, "%-16.16s %-40.40s %s", u->nick, s, "Offline" ); + n_offline ++; + } + + irc_usermsg( irc, "%d buddies (%d available, %d away, %d offline)", n_online + n_away + n_offline, n_online, n_away, n_offline ); +} + +static void cmd_nick( irc_t *irc, char **cmd ) +{ + account_t *a; + + if( !cmd[1] || !( a = account_get( irc, cmd[1] ) ) ) + { + irc_usermsg( irc, "Invalid account"); + } + else if( !( a->gc && ( a->gc->flags & OPT_LOGGED_IN ) ) ) + { + irc_usermsg( irc, "That account is not on-line" ); + } + else if ( !cmd[2] ) + { + irc_usermsg( irc, "Your name is `%s'" , a->gc->displayname ? a->gc->displayname : "NULL" ); + } + else if ( !a->gc->prpl->set_info ) + { + irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] ); + } + else + { + char utf8[1024]; + + irc_usermsg( irc, "Setting your name to `%s'", cmd[2] ); + + if( g_strncasecmp( set_getstr( irc, "charset" ), "none", 4 ) != 0 && + do_iconv( set_getstr( irc, "charset" ), "UTF-8", cmd[2], utf8, 0, 1024 ) != -1 ) + a->gc->prpl->set_info( a->gc, utf8 ); + else + a->gc->prpl->set_info( a->gc, cmd[2] ); + } +} + +static void cmd_qlist( irc_t *irc, char **cmd ) +{ + query_t *q = irc->queries; + int num; + + if( !q ) + { + irc_usermsg( irc, "There are no pending questions." ); + return; + } + + irc_usermsg( irc, "Pending queries:" ); + + for( num = 0; q; q = q->next, num ++ ) + if( q->gc ) /* Not necessary yet, but it might come later */ + irc_usermsg( irc, "%d, %s(%s): %s", num, q->gc->prpl->name, q->gc->username, q->question ); + else + irc_usermsg( irc, "%d, BitlBee: %s", num, q->question ); +} + +static void cmd_import_buddies( irc_t *irc, char **cmd ) +{ + struct gaim_connection *gc; + account_t *a; + nick_t *n; + + if( !( a = account_get( irc, cmd[1] ) ) ) + { + irc_usermsg( irc, "Invalid account" ); + return; + } + else if( !( ( gc = a->gc ) && ( a->gc->flags & OPT_LOGGED_IN ) ) ) + { + irc_usermsg( irc, "That account is not on-line" ); + return; + } + + if( cmd[2] ) + { + if( g_strcasecmp( cmd[2], "clear" ) == 0 ) + { + user_t *u; + + for( u = irc->users; u; u = u->next ) + if( u->gc == gc ) + { + u->gc->prpl->remove_buddy( u->gc, u->handle, NULL ); + user_del( irc, u->nick ); + } + + irc_usermsg( irc, "Old buddy list cleared." ); + } + else + { + irc_usermsg( irc, "Invalid argument: %s", cmd[2] ); + return; + } + } + + for( n = gc->irc->nicks; n; n = n->next ) + { + if( n->proto == gc->prpl && !user_findhandle( gc, n->handle ) ) + { + gc->prpl->add_buddy( gc, n->handle ); + add_buddy( gc, NULL, n->handle, NULL ); + } + } + + irc_usermsg( irc, "Sent all add requests. Please wait for a while, the server needs some time to handle all the adds." ); +} + +const command_t commands[] = { + { "help", 0, cmd_help, 0 }, + { "identify", 1, cmd_identify, 0 }, + { "register", 1, cmd_register, 0 }, + { "drop", 1, cmd_drop, 0 }, + { "account", 1, cmd_account, 0 }, + { "add", 2, cmd_add, 0 }, + { "info", 1, cmd_info, 0 }, + { "rename", 2, cmd_rename, 0 }, + { "remove", 1, cmd_remove, 0 }, + { "block", 1, cmd_block, 0 }, + { "allow", 1, cmd_allow, 0 }, + { "save", 0, cmd_save, 0 }, + { "set", 0, cmd_set, 0 }, + { "yes", 0, cmd_yesno, 0 }, + { "no", 0, cmd_yesno, 0 }, + { "blist", 0, cmd_blist, 0 }, + { "nick", 1, cmd_nick, 0 }, + { "import_buddies", 1, cmd_import_buddies, 0 }, + { "qlist", 0, cmd_qlist, 0 }, + { NULL } +}; diff --git a/user.h b/user.h index 79b5ed0e..da657a4d 100644 --- a/user.h +++ b/user.h @@ -44,7 +44,7 @@ typedef struct __USER guint sendbuf_timer; int sendbuf_flags; - int (*send_handler) ( irc_t *irc, struct __USER *u, char *msg, int flags ); + void (*send_handler) ( irc_t *irc, struct __USER *u, char *msg, int flags ); struct __USER *next; } user_t; -- cgit v1.2.3