Changeset 85d7b85


Ignore:
Timestamp:
2008-04-02T14:22:57Z (13 years ago)
Author:
Jelmer Vernooij <jelmer@…>
Branches:
master
Children:
f9dbc99
Parents:
875ad42 (diff), dd34575 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge trunk.

Files:
65 added
34 deleted
80 edited
13 moved

Legend:

Unmodified
Added
Removed
  • .bzrignore

    r875ad42 r85d7b85  
    2121bitlbee.pc
    2222.gdb_history
     23tests/check
     24*.gcda
     25*.gcov
     26*.gcno
     27*.o
     28coverage
     29bitlbee.info
  • Makefile

    r875ad42 r85d7b85  
    1010
    1111# Program variables
    12 objects = account.o bitlbee.o crypting.o help.o ini.o ipc.o irc.o irc_commands.o nick.o query.o root_commands.o set.o storage.o storage_text.o url.o user.o util.o
    13 headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ini.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h url.h user.h protocols/http_client.h protocols/md5.h protocols/nogaim.h protocols/proxy.h protocols/sha.h protocols/ssl_client.h
    14 subdirs = protocols
     12objects = account.o bitlbee.o crypting.o help.o ipc.o irc.o irc_commands.o nick.o query.o root_commands.o set.o storage.o $(STORAGE_OBJS) user.o
     13headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h user.h lib/events.h lib/http_client.h lib/ini.h lib/md5.h lib/misc.h lib/proxy.h lib/sha1.h lib/ssl_client.h lib/url.h protocols/nogaim.h
     14subdirs = lib protocols
    1515
    1616ifeq ($(ARCH),Windows)
     
    4646clean: $(subdirs)
    4747        rm -f *.o $(OUTFILE) core utils/bitlbeed encode decode
     48        $(MAKE) -C tests clean
    4849
    4950distclean: clean $(subdirs)
    50         rm -f Makefile.settings config.h
     51        rm -f Makefile.settings config.h bitlbee.pc
    5152        find . -name 'DEADJOE' -o -name '*.orig' -o -name '*.rej' -o -name '*~' -exec rm -f {} \;
     53        $(MAKE) -C tests distclean
     54
     55check: all
     56        $(MAKE) -C tests
     57
     58gcov: check
     59        gcov *.c
     60
     61lcov: check
     62        lcov --directory . --capture --output-file bitlbee.info
     63        genhtml -o coverage bitlbee.info
    5264
    5365install-doc:
     
    109121
    110122encode: crypting.c
    111         $(CC) crypting.c protocols/md5.c $(CFLAGS) -o encode -DCRYPTING_MAIN $(CFLAGS) $(EFLAGS) $(LFLAGS)
     123        $(CC) crypting.c lib/md5.c $(CFLAGS) -o encode -DCRYPTING_MAIN $(CFLAGS) $(EFLAGS) $(LFLAGS)
    112124
    113125decode: encode
  • account.c

    r875ad42 r85d7b85  
    3131{
    3232        account_t *a;
     33        set_t *s;
    3334       
    3435        if( irc->accounts )
    3536        {
    3637                for( a = irc->accounts; a->next; a = a->next );
    37                 a = a->next = g_new0 ( account_t, 1 );
     38                a = a->next = g_new0( account_t, 1 );
    3839        }
    3940        else
     
    4546        a->user = g_strdup( user );
    4647        a->pass = g_strdup( pass );
     48        a->auto_connect = 1;
    4749        a->irc = irc;
    4850       
     51        s = set_add( &a->set, "auto_connect", "true", set_eval_account, a );
     52        s->flags |= ACC_SET_NOSAVE;
     53       
     54        s = set_add( &a->set, "auto_reconnect", "true", set_eval_bool, a );
     55       
     56        s = set_add( &a->set, "password", NULL, set_eval_account, a );
     57        s->flags |= ACC_SET_NOSAVE;
     58       
     59        s = set_add( &a->set, "username", NULL, set_eval_account, a );
     60        s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY;
     61        set_setstr( &a->set, "username", user );
     62       
     63        a->nicks = g_hash_table_new_full( g_str_hash, g_str_equal, g_free, g_free );
     64       
     65        /* This function adds some more settings (and might want to do more
     66           things that have to be done now, although I can't think of anything. */
     67        if( prpl->init )
     68                prpl->init( a );
     69       
    4970        return( a );
     71}
     72
     73char *set_eval_account( set_t *set, char *value )
     74{
     75        account_t *acc = set->data;
     76       
     77        /* Double-check: We refuse to edit on-line accounts. */
     78        if( set->flags & ACC_SET_OFFLINE_ONLY && acc->ic )
     79                return NULL;
     80       
     81        if( strcmp( set->key, "username" ) == 0 )
     82        {
     83                g_free( acc->user );
     84                acc->user = g_strdup( value );
     85                return value;
     86        }
     87        else if( strcmp( set->key, "password" ) == 0 )
     88        {
     89                g_free( acc->pass );
     90                acc->pass = g_strdup( value );
     91                return NULL;    /* password shouldn't be visible in plaintext! */
     92        }
     93        else if( strcmp( set->key, "server" ) == 0 )
     94        {
     95                g_free( acc->server );
     96                if( *value )
     97                {
     98                        acc->server = g_strdup( value );
     99                        return value;
     100                }
     101                else
     102                {
     103                        acc->server = NULL;
     104                        return g_strdup( set->def );
     105                }
     106        }
     107        else if( strcmp( set->key, "auto_connect" ) == 0 )
     108        {
     109                if( !is_bool( value ) )
     110                        return NULL;
     111               
     112                acc->auto_connect = bool2int( value );
     113                return value;
     114        }
     115       
     116        return NULL;
    50117}
    51118
     
    68135                        for( a = irc->accounts; a; a = a->next )
    69136                                if( a->prpl == proto &&
    70                                     a->prpl->cmp_buddynames( handle, a->user ) == 0 )
     137                                    a->prpl->handle_cmp( handle, a->user ) == 0 )
    71138                                        ret = a;
    72139                }
     
    115182        account_t *a, *l = NULL;
    116183       
     184        if( acc->ic )
     185                /* Caller should have checked, accounts still in use can't be deleted. */
     186                return;
     187       
    117188        for( a = irc->accounts; a; a = (l=a)->next )
    118189                if( a == acc )
    119190                {
    120                         if( a->gc ) return; /* Caller should have checked, accounts still in use can't be deleted. */
    121                        
    122191                        if( l )
    123                         {
    124192                                l->next = a->next;
    125                         }
    126193                        else
    127                         {
    128194                                irc->accounts = a->next;
    129                         }
     195                       
     196                        while( a->set )
     197                                set_del( &a->set, a->set->key );
     198                       
     199                        g_hash_table_destroy( a->nicks );
    130200                       
    131201                        g_free( a->user );
    132202                        g_free( a->pass );
    133                         if( a->server ) g_free( a->server );
     203                        g_free( a->server );
    134204                        if( a->reconnect )      /* This prevents any reconnect still queued to happen */
    135205                                cancel_auto_reconnect( a );
     
    142212void account_on( irc_t *irc, account_t *a )
    143213{
    144         struct aim_user *u;
    145        
    146         if( a->gc )
     214        if( a->ic )
    147215        {
    148216                /* Trying to enable an already-enabled account */
     
    152220        cancel_auto_reconnect( a );
    153221       
    154         u = g_new0 ( struct aim_user, 1 );
    155         u->irc = irc;
    156         u->prpl = a->prpl;
    157         strncpy( u->username, a->user, sizeof( u->username ) - 1 );
    158         strncpy( u->password, a->pass, sizeof( u->password ) - 1 );
    159         if( a->server) strncpy( u->proto_opt[0], a->server, sizeof( u->proto_opt[0] ) - 1 );
    160        
    161         a->gc = (struct gaim_connection *) u; /* Bit hackish :-/ */
    162222        a->reconnect = 0;
    163        
    164         a->prpl->login( u );
     223        a->prpl->login( a );
    165224}
    166225
    167226void account_off( irc_t *irc, account_t *a )
    168227{
    169         a->gc->wants_to_die = TRUE;
    170         signoff( a->gc );
    171         a->gc = NULL;
     228        imc_logout( a->ic, FALSE );
     229        a->ic = NULL;
    172230        if( a->reconnect )
    173231        {
  • account.h

    r875ad42 r85d7b85  
    3434        char *server;
    3535       
     36        int auto_connect;
    3637        int reconnect;
    3738       
     39        set_t *set;
     40        GHashTable *nicks;
     41       
    3842        struct irc *irc;
    39         struct gaim_connection *gc;
     43        struct im_connection *ic;
    4044        struct account *next;
    4145} account_t;
     
    4751void account_off( irc_t *irc, account_t *a );
    4852
     53char *set_eval_account( set_t *set, char *value );
     54
     55#define ACC_SET_NOSAVE          1
     56#define ACC_SET_OFFLINE_ONLY    2
     57#define ACC_SET_ONLINE_ONLY     4
     58
    4959#endif
  • bitlbee.c

    r875ad42 r85d7b85  
    3434#include <errno.h>
    3535
    36 gboolean bitlbee_io_new_client( GIOChannel *source, GIOCondition condition, gpointer data );
     36static gboolean bitlbee_io_new_client( gpointer data, gint fd, b_input_condition condition );
    3737
    3838int bitlbee_daemon_init()
    3939{
    40 #ifdef IPV6
    41         struct sockaddr_in6 listen_addr;
    42 #else
    43         struct sockaddr_in listen_addr;
    44 #endif
     40        struct addrinfo *res, hints, *addrinfo_bind;
    4541        int i;
    46         GIOChannel *ch;
    4742        FILE *fp;
    4843       
     
    5045        log_link( LOGLVL_WARNING, LOGOUTPUT_SYSLOG );
    5146       
    52         global.listen_socket = socket( AF_INETx, SOCK_STREAM, 0 );
    53         if( global.listen_socket == -1 )
    54         {
    55                 log_error( "socket" );
    56                 return( -1 );
    57         }
    58        
    59         /* TIME_WAIT (?) sucks.. */
    60         i = 1;
    61         setsockopt( global.listen_socket, SOL_SOCKET, SO_REUSEADDR, &i, sizeof( i ) );
    62        
    63 #ifdef IPV6
    64         listen_addr.sin6_family = AF_INETx;
    65         listen_addr.sin6_port = htons( global.conf->port );
    66         i = inet_pton( AF_INETx, ipv6_wrap( global.conf->iface ), &listen_addr.sin6_addr );
    67 #else
    68         listen_addr.sin_family = AF_INETx;
    69         listen_addr.sin_port = htons( global.conf->port );
    70         i = inet_pton( AF_INETx, global.conf->iface, &listen_addr.sin_addr );
     47        memset( &hints, 0, sizeof( hints ) );
     48        hints.ai_family = PF_UNSPEC;
     49        hints.ai_socktype = SOCK_STREAM;
     50        hints.ai_flags = AI_PASSIVE
     51#ifdef AI_ADDRCONFIG
     52                       | AI_ADDRCONFIG
    7153#endif
    72        
    73         if( i != 1 )
    74         {
    75                 log_message( LOGLVL_ERROR, "Couldn't parse address `%s'", global.conf->iface );
    76                 return( -1 );
    77         }
    78        
    79         i = bind( global.listen_socket, (struct sockaddr *) &listen_addr, sizeof( listen_addr ) );
    80         if( i == -1 )
    81         {
    82                 log_error( "bind" );
    83                 return( -1 );
    84         }
    85        
     54        ;
     55
     56        i = getaddrinfo( global.conf->iface, global.conf->port, &hints, &addrinfo_bind );
     57        if( i )
     58        {
     59                log_message( LOGLVL_ERROR, "Couldn't parse address `%s': %s",
     60                                           global.conf->iface, gai_strerror(i) );
     61                return -1;
     62        }
     63
     64        global.listen_socket = -1;
     65
     66        for( res = addrinfo_bind; res; res = res->ai_next )
     67        {
     68                global.listen_socket = socket( res->ai_family, res->ai_socktype, res->ai_protocol );
     69                if( global.listen_socket < 0 )
     70                        continue;
     71
     72                /* TIME_WAIT (?) sucks.. */
     73                i = 1;
     74                setsockopt( global.listen_socket, SOL_SOCKET, SO_REUSEADDR, &i, sizeof( i ) );
     75
     76                i = bind( global.listen_socket, res->ai_addr, res->ai_addrlen );
     77                if( i == -1 )
     78                {
     79                        log_error( "bind" );
     80                        return( -1 );
     81                }
     82
     83                break;
     84        }
     85
     86        freeaddrinfo( addrinfo_bind );
     87
    8688        i = listen( global.listen_socket, 10 );
    8789        if( i == -1 )
     
    9193        }
    9294       
    93         ch = g_io_channel_unix_new( global.listen_socket );
    94         global.listen_watch_source_id = g_io_add_watch( ch, G_IO_IN, bitlbee_io_new_client, NULL );
     95        global.listen_watch_source_id = b_input_add( global.listen_socket, GAIM_INPUT_READ, bitlbee_io_new_client, NULL );
    9596       
    9697#ifndef _WIN32
     
    119120                ipc_master_load_state();
    120121
    121         if( global.conf->runmode == RUNMODE_DAEMON ||
    122                 global.conf->runmode == RUNMODE_FORKDAEMON )
     122        if( global.conf->runmode == RUNMODE_DAEMON || global.conf->runmode == RUNMODE_FORKDAEMON )
    123123                ipc_master_listen_socket();
    124124       
     
    146146}
    147147
    148 gboolean bitlbee_io_current_client_read( GIOChannel *source, GIOCondition condition, gpointer data )
     148gboolean bitlbee_io_current_client_read( gpointer data, gint fd, b_input_condition cond )
    149149{
    150150        irc_t *irc = data;
     
    152152        int st;
    153153       
    154         if( condition & G_IO_ERR || condition & G_IO_HUP )
    155         {
    156                 irc_abort( irc, 1, "Read error" );
    157                 return FALSE;
    158         }
    159        
    160154        st = read( irc->fd, line, sizeof( line ) - 1 );
    161155        if( st == 0 )
     
    193187        if( !g_slist_find( irc_connection_list, irc ) )
    194188        {
    195                 log_message( LOGLVL_WARNING, "Abnormal termination of connection with fd %d.", irc->fd );
     189                log_message( LOGLVL_WARNING, "Abnormal termination of connection with fd %d.", fd );
    196190                return FALSE;
    197191        }
     
    207201}
    208202
    209 gboolean bitlbee_io_current_client_write( GIOChannel *source, GIOCondition condition, gpointer data )
     203gboolean bitlbee_io_current_client_write( gpointer data, gint fd, b_input_condition cond )
    210204{
    211205        irc_t *irc = data;
     
    214208
    215209        if( irc->sendbuffer == NULL )
    216                 return( FALSE );
     210                return FALSE;
    217211       
    218212        size = strlen( irc->sendbuffer );
     
    235229                irc->w_watch_source_id = 0;
    236230               
    237                 if( irc->status == USTATUS_SHUTDOWN )
     231                if( irc->status & USTATUS_SHUTDOWN )
    238232                        irc_free( irc );
    239233               
    240                 return( FALSE );
     234                return FALSE;
    241235        }
    242236        else
     
    246240                irc->sendbuffer = temp;
    247241               
    248                 return( TRUE );
    249         }
    250 }
    251 
    252 gboolean bitlbee_io_new_client( GIOChannel *source, GIOCondition condition, gpointer data )
    253 {
    254         size_t size = sizeof( struct sockaddr_in );
     242                return TRUE;
     243        }
     244}
     245
     246static gboolean bitlbee_io_new_client( gpointer data, gint fd, b_input_condition condition )
     247{
     248        socklen_t size = sizeof( struct sockaddr_in );
    255249        struct sockaddr_in conn_info;
    256250        int new_socket = accept( global.listen_socket, (struct sockaddr *) &conn_info, &size );
     
    286280                        child->pid = client_pid;
    287281                        child->ipc_fd = fds[0];
    288                         child->ipc_inpa = gaim_input_add( child->ipc_fd, GAIM_INPUT_READ, ipc_master_read, child );
     282                        child->ipc_inpa = b_input_add( child->ipc_fd, GAIM_INPUT_READ, ipc_master_read, child );
    289283                        child_list = g_slist_append( child_list, child );
    290284                       
    291                         log_message( LOGLVL_INFO, "Creating new subprocess with pid %d.", client_pid );
     285                        log_message( LOGLVL_INFO, "Creating new subprocess with pid %d.", (int) client_pid );
    292286                       
    293287                        /* Close some things we don't need in the parent process. */
     
    299293                        irc_t *irc;
    300294                       
     295                        /* Since we're fork()ing here, let's make sure we won't
     296                           get the same random numbers as the parent/siblings. */
     297                        srand( time( NULL ) ^ getpid() );
     298                       
     299                        b_main_init();
     300                       
    301301                        /* Close the listening socket, we're a client. */
    302302                        close( global.listen_socket );
    303                         g_source_remove( global.listen_watch_source_id );
     303                        b_event_remove( global.listen_watch_source_id );
    304304                       
    305305                        /* Make the connection. */
     
    308308                        /* We can store the IPC fd there now. */
    309309                        global.listen_socket = fds[1];
    310                         global.listen_watch_source_id = gaim_input_add( fds[1], GAIM_INPUT_READ, ipc_child_read, irc );
     310                        global.listen_watch_source_id = b_input_add( fds[1], GAIM_INPUT_READ, ipc_child_read, irc );
    311311                       
    312312                        close( fds[0] );
     
    325325}
    326326
    327 void bitlbee_shutdown( gpointer data )
     327gboolean bitlbee_shutdown( gpointer data, gint fd, b_input_condition cond )
    328328{
    329329        /* Try to save data for all active connections (if desired). */
     
    332332       
    333333        /* We'll only reach this point when not running in inetd mode: */
    334         g_main_quit( global.loop );
    335 }
     334        b_main_quit();
     335       
     336        return FALSE;
     337}
  • bitlbee.conf

    r875ad42 r85d7b85  
    1919##
    2020# RunMode = Inetd
     21
     22## User:
     23##
     24## If BitlBee is started by root as a daemon, it can drop root privileges,
     25## and change to the specified user.
     26##
     27# User = bitlbee
    2128
    2229## DaemonPort/DaemonInterface:
     
    4249##
    4350## Password the user should enter when logging into a closed BitlBee server.
     51## You can also have an MD5-encrypted password here. Format: "md5:", followed
     52## by a hash as generated for the <user password=""> attribute in a BitlBee
     53## XML file (for now there's no easier way to generate the hash).
    4454##
    4555# AuthPassword = ItllBeBitlBee   ## Heh.. Our slogan. ;-)
     56## or
     57# AuthPassword = md5:gzkK0Ox/1xh+1XTsQjXxBJ571Vgl
    4658
    4759## OperPassword
     
    5062##
    5163# OperPassword = ChangeMe!
     64## or
     65# OperPassword = md5:I0mnZbn1t4R731zzRdDN2/pK7lRX
    5266
    5367## HostName
  • bitlbee.h

    r875ad42 r85d7b85  
    3030
    3131#define PACKAGE "BitlBee"
    32 #define BITLBEE_VERSION "BZR"
     32#define BITLBEE_VERSION "1.2"
    3333#define VERSION BITLBEE_VERSION
    3434
    35 #define MAX_STRING 128
     35#define MAX_STRING 511
    3636
    3737#if HAVE_CONFIG_H
     
    5959/* The following functions should not be used if we want to maintain Windows compatibility... */
    6060#undef free
    61 #define free            __PLEASE_USE_THE_GLIB_MEMORY_ALLOCATION_SYSTEM_INSTEAD__
     61#define free            __PLEASE_USE_THE_GLIB_MEMORY_ALLOCATION_SYSTEM__
    6262#undef malloc
    63 #define malloc          __PLEASE_USE_THE_GLIB_MEMORY_ALLOCATION_SYSTEM_INSTEAD__
     63#define malloc          __PLEASE_USE_THE_GLIB_MEMORY_ALLOCATION_SYSTEM__
    6464#undef calloc
    65 #define calloc          __PLEASE_USE_THE_GLIB_MEMORY_ALLOCATION_SYSTEM_INSTEAD__
     65#define calloc          __PLEASE_USE_THE_GLIB_MEMORY_ALLOCATION_SYSTEM__
    6666#undef realloc
    67 #define realloc         __PLEASE_USE_THE_GLIB_MEMORY_ALLOCATION_SYSTEM_INSTEAD__
     67#define realloc         __PLEASE_USE_THE_GLIB_MEMORY_ALLOCATION_SYSTEM__
    6868#undef strdup
    69 #define strdup          __PLEASE_USE_THE_GLIB_STRDUP_FUNCTIONS_SYSTEM_INSTEAD__
     69#define strdup          __PLEASE_USE_THE_GLIB_STRDUP_FUNCTIONS_SYSTEM__
    7070#undef strndup
    71 #define strndup         __PLEASE_USE_THE_GLIB_STRDUP_FUNCTIONS_SYSTEM_INSTEAD__
     71#define strndup         __PLEASE_USE_THE_GLIB_STRDUP_FUNCTIONS_SYSTEM__
    7272#undef snprintf
    73 #define snprintf        __PLEASE_USE_G_SNPRINTF_INSTEAD__
     73#define snprintf        __PLEASE_USE_G_SNPRINTF__
    7474#undef strcasecmp
    75 #define strcasecmp      __PLEASE_USE_G_STRCASECMP_INSTEAD__
     75#define strcasecmp      __PLEASE_USE_G_STRCASECMP__
    7676#undef strncasecmp
    77 #define strncasecmp     __PLEASE_USE_G_STRNCASECMP_INSTEAD__
     77#define strncasecmp     __PLEASE_USE_G_STRNCASECMP__
     78
     79/* And the following functions shouldn't be used anymore to keep compatibility
     80   with other event handling libs than GLib. */
     81#undef g_timeout_add
     82#define g_timeout_add           __PLEASE_USE_B_TIMEOUT_ADD__
     83#undef g_timeout_add_full
     84#define g_timeout_add_full      __PLEASE_USE_B_TIMEOUT_ADD__
     85#undef g_io_add_watch
     86#define g_io_add_watch          __PLEASE_USE_B_INPUT_ADD__
     87#undef g_io_add_watch_full
     88#define g_io_add_watch_full     __PLEASE_USE_B_INPUT_ADD__
     89#undef g_source_remove
     90#define g_source_remove         __PLEASE_USE_B_EVENT_REMOVE__
     91#undef g_source_remove_by_user_data
     92#define g_source_remove_by_user_data    __PLEASE_USE_B_SOURCE_REMOVE_BY_USER_DATA__
     93#undef g_main_run
     94#define g_main_run              __PLEASE_USE_B_MAIN_RUN__
     95#undef g_main_quit
     96#define g_main_quit             __PLEASE_USE_B_MAIN_QUIT__
     97
     98#ifndef F_OK
     99#define F_OK 0
     100#endif
     101
     102#ifndef G_GNUC_MALLOC
     103/* Doesn't exist in GLib <=2.4 while everything else in BitlBee should
     104   work with it, so let's fake this one. */
     105#define G_GNUC_MALLOC
     106#endif
    78107
    79108#define _( x ) x
     
    94123#define CONF_FILE_DEF ETCDIR "bitlbee.conf"
    95124
    96 extern char *CONF_FILE;
    97 
    98125#include "irc.h"
    99126#include "storage.h"
     
    102129#include "commands.h"
    103130#include "account.h"
     131#include "nick.h"
    104132#include "conf.h"
    105133#include "log.h"
     
    108136#include "query.h"
    109137#include "sock.h"
    110 #include "util.h"
     138#include "misc.h"
     139#include "proxy.h"
    111140
    112141typedef struct global {
     
    115144        gint listen_watch_source_id;
    116145        help_t *help;
     146        char *conf_file;
    117147        conf_t *conf;
    118148        GList *storage; /* The first backend in the list will be used for saving */
    119149        char *helpfile;
    120         GMainLoop *loop;
    121150        int restart;
    122151} global_t;
     
    125154int bitlbee_inetd_init( void );
    126155
    127 gboolean bitlbee_io_current_client_read( GIOChannel *source, GIOCondition condition, gpointer data );
    128 gboolean bitlbee_io_current_client_write( GIOChannel *source, GIOCondition condition, gpointer data );
     156gboolean bitlbee_io_current_client_read( gpointer data, gint source, b_input_condition cond );
     157gboolean bitlbee_io_current_client_write( gpointer data, gint source, b_input_condition cond );
    129158
    130159void root_command_string( irc_t *irc, user_t *u, char *command, int flags );
    131160void root_command( irc_t *irc, char *command[] );
    132 void bitlbee_shutdown( gpointer data );
     161gboolean bitlbee_shutdown( gpointer data, gint fd, b_input_condition cond );
    133162
    134163extern global_t global;
  • conf.c

    r875ad42 r85d7b85  
    3434#include "ipc.h"
    3535
    36 #include "protocols/proxy.h"
    37 
    38 char *CONF_FILE;
     36#include "proxy.h"
    3937
    4038static int conf_loadini( conf_t *conf, char *file );
     
    4341{
    4442        conf_t *conf;
    45         int opt, i;
     43        int opt, i, config_missing = 0;
    4644       
    4745        conf = g_new0( conf_t, 1 );
    4846       
    49 #ifdef IPV6
    50         conf->iface = "::";
    51 #else
    52         conf->iface = "0.0.0.0";
    53 #endif
    54         conf->port = 6667;
     47        conf->iface = NULL;
     48        conf->port = g_strdup( "6667" );
    5549        conf->nofork = 0;
    5650        conf->verbose = 0;
    57         conf->primary_storage = "text";
     51        conf->primary_storage = g_strdup( "xml" );
     52        conf->migrate_storage = g_strsplit( "text", ",", -1 );
    5853        conf->runmode = RUNMODE_INETD;
    5954        conf->authmode = AUTHMODE_OPEN;
     
    6257        conf->configdir = g_strdup( CONFIG );
    6358        conf->plugindir = g_strdup( PLUGINDIR );
    64         conf->pidfile = g_strdup( "/var/run/bitlbee.pid" );
     59        conf->pidfile = g_strdup( PIDFILE );
    6560        conf->motdfile = g_strdup( ETCDIR "/motd.txt" );
    6661        conf->ping_interval = 180;
    6762        conf->ping_timeout = 300;
     63        conf->user = NULL;
    6864        proxytype = 0;
    6965       
    70         i = conf_loadini( conf, CONF_FILE );
     66        i = conf_loadini( conf, global.conf_file );
    7167        if( i == 0 )
    7268        {
    73                 fprintf( stderr, "Error: Syntax error in configuration file `%s'.\n", CONF_FILE );
    74                 return( NULL );
     69                fprintf( stderr, "Error: Syntax error in configuration file `%s'.\n", global.conf_file );
     70                return NULL;
    7571        }
    7672        else if( i == -1 )
    7773        {
    78                 fprintf( stderr, "Warning: Unable to read configuration file `%s'.\n", CONF_FILE );
    79         }
    80        
    81         while( argc > 0 && ( opt = getopt( argc, argv, "i:p:P:nvIDFc:d:hR:" ) ) >= 0 )
     74                config_missing ++;
     75                /* Whine after parsing the options if there was no -c pointing
     76                   at a *valid* configuration file. */
     77        }
     78       
     79        while( argc > 0 && ( opt = getopt( argc, argv, "i:p:P:nvIDFc:d:hR:u:" ) ) >= 0 )
    8280        /*     ^^^^ Just to make sure we skip this step from the REHASH handler. */
    8381        {
     
    8886                else if( opt == 'p' )
    8987                {
    90                         if( ( sscanf( optarg, "%d", &i ) != 1 ) || ( i <= 0 ) || ( i > 65535 ) )
    91                         {
    92                                 fprintf( stderr, "Invalid port number: %s\n", optarg );
    93                                 return( NULL );
    94                         }
    95                         conf->port = i;
     88                        g_free( conf->port );
     89                        conf->port = g_strdup( optarg );
    9690                }
    9791                else if( opt == 'P' )
     
    112106                else if( opt == 'c' )
    113107                {
    114                         if( strcmp( CONF_FILE, optarg ) != 0 )
    115                         {
    116                                 g_free( CONF_FILE );
    117                                 CONF_FILE = g_strdup( optarg );
     108                        if( strcmp( global.conf_file, optarg ) != 0 )
     109                        {
     110                                g_free( global.conf_file );
     111                                global.conf_file = g_strdup( optarg );
    118112                                g_free( conf );
    119113                                /* Re-evaluate arguments. Don't use this option twice,
     
    121115                                   works with all libcs BTW.. */
    122116                                optind = 1;
    123                                 return( conf_load( argc, argv ) );
     117                                return conf_load( argc, argv );
    124118                        }
    125119                }
     
    131125                else if( opt == 'h' )
    132126                {
    133                         printf( "Usage: bitlbee [-D [-i <interface>] [-p <port>] [-n] [-v]] [-I]\n"
     127                        printf( "Usage: bitlbee [-D/-F [-i <interface>] [-p <port>] [-n] [-v]] [-I]\n"
    134128                                "               [-c <file>] [-d <dir>] [-h]\n"
    135129                                "\n"
     
    139133                                "  -D  Daemon mode. (Still EXPERIMENTAL!)\n"
    140134                                "  -F  Forking daemon. (one process per client)\n"
     135                                "  -u  Run daemon as specified user.\n"
    141136                                "  -P  Specify PID-file (not for inetd mode)\n"
    142137                                "  -i  Specify the interface (by IP address) to listen on.\n"
     
    148143                                "  -d  Specify alternative user configuration directory\n"
    149144                                "  -h  Show this help page.\n" );
    150                         return( NULL );
     145                        return NULL;
    151146                }
    152147                else if( opt == 'R' )
     
    158153                        ipc_master_set_statefile( optarg );
    159154                }
     155                else if( opt == 'u' )
     156                {
     157                        g_free( conf->user );
     158                        conf->user = g_strdup( optarg );
     159                }
    160160        }
    161161       
     
    169169        }
    170170       
    171         return( conf );
     171        if( config_missing )
     172                fprintf( stderr, "Warning: Unable to read configuration file `%s'.\n", global.conf_file );
     173       
     174        return conf;
    172175}
    173176
     
    178181       
    179182        ini = ini_open( file );
    180         if( ini == NULL ) return( -1 );
     183        if( ini == NULL ) return -1;
    181184        while( ini_read( ini ) )
    182185        {
     
    199202                        else if( g_strcasecmp( ini->key, "daemoninterface" ) == 0 )
    200203                        {
     204                                g_free( conf->iface );
    201205                                conf->iface = g_strdup( ini->value );
    202206                        }
    203207                        else if( g_strcasecmp( ini->key, "daemonport" ) == 0 )
    204208                        {
    205                                 if( ( sscanf( ini->value, "%d", &i ) != 1 ) || ( i <= 0 ) || ( i > 65535 ) )
    206                                 {
    207                                         fprintf( stderr, "Invalid port number: %s\n", ini->value );
    208                                         return( 0 );
    209                                 }
    210                                 conf->port = i;
     209                                g_free( conf->port );
     210                                conf->port = g_strdup( ini->value );
    211211                        }
    212212                        else if( g_strcasecmp( ini->key, "authmode" ) == 0 )
     
    221221                        else if( g_strcasecmp( ini->key, "authpassword" ) == 0 )
    222222                        {
     223                                g_free( conf->auth_pass );
    223224                                conf->auth_pass = g_strdup( ini->value );
    224225                        }
    225226                        else if( g_strcasecmp( ini->key, "operpassword" ) == 0 )
    226227                        {
     228                                g_free( conf->oper_pass );
    227229                                conf->oper_pass = g_strdup( ini->value );
    228230                        }
    229231                        else if( g_strcasecmp( ini->key, "hostname" ) == 0 )
    230232                        {
     233                                g_free( conf->hostname );
    231234                                conf->hostname = g_strdup( ini->value );
    232235                        }
     
    249252                        {
    250253                                g_strfreev( conf->migrate_storage );
    251                                 conf->migrate_storage = g_strsplit( ini->value, " \t,;", -1 );
     254                                conf->migrate_storage = g_strsplit_set( ini->value, " \t,;", -1 );
    252255                        }
    253256                        else if( g_strcasecmp( ini->key, "pinginterval" ) == 0 )
     
    256259                                {
    257260                                        fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value );
    258                                         return( 0 );
     261                                        return 0;
    259262                                }
    260263                                conf->ping_interval = i;
     
    265268                                {
    266269                                        fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value );
    267                                         return( 0 );
     270                                        return 0;
    268271                                }
    269272                                conf->ping_timeout = i;
     
    277280                                        fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value );
    278281                                        g_free( url );
    279                                         return( 0 );
     282                                        return 0;
    280283                                }
    281284                               
     
    293296                                g_free( url );
    294297                        }
     298                        else if( g_strcasecmp( ini->key, "user" ) == 0 )
     299                        {
     300                                g_free( conf->user );
     301                                conf->user = g_strdup( ini->value );
     302                        }
    295303                        else
    296304                        {
    297305                                fprintf( stderr, "Error: Unknown setting `%s` in configuration file.\n", ini->key );
    298                                 return( 0 );
     306                                return 0;
    299307                                /* For now just ignore unknown keys... */
    300308                        }
     
    304312                        fprintf( stderr, "Error: Unknown section [%s] in configuration file. "
    305313                                         "BitlBee configuration must be put in a [settings] section!\n", ini->section );
    306                         return( 0 );
     314                        return 0;
    307315                }
    308316        }
    309317        ini_close( ini );
    310318       
    311         return( 1 );
     319        return 1;
    312320}
    313321
     
    316324        ini_t *ini;
    317325       
    318         ini = ini_open( CONF_FILE );
     326        ini = ini_open( global.conf_file );
    319327        if( ini == NULL ) return;
    320328        while( ini_read( ini ) )
     
    322330                if( g_strcasecmp( ini->section, "defaults" ) == 0 )
    323331                {
    324                         set_t *s = set_find( irc, ini->key );
     332                        set_t *s = set_find( &irc->set, ini->key );
    325333                       
    326334                        if( s )
  • conf.h

    r875ad42 r85d7b85  
    3333{
    3434        char *iface;
    35         signed int port;
     35        char *port;
    3636        int nofork;
    3737        int verbose;
     
    4949        int ping_interval;
    5050        int ping_timeout;
     51        char *user;
    5152} conf_t;
    5253
    53 conf_t *conf_load( int argc, char *argv[] );
     54G_GNUC_MALLOC conf_t *conf_load( int argc, char *argv[] );
    5455void conf_loaddefaults( irc_t *irc );
    5556
  • configure

    r875ad42 r85d7b85  
    1414datadir='$prefix/share/bitlbee/'
    1515config='/var/lib/bitlbee/'
     16plugindir='$prefix/lib/bitlbee/'
     17includedir='$prefix/include/bitlbee/'
     18libevent='/usr/'
    1619pidfile='/var/run/bitlbee.pid'
    17 ipcsocket='/var/run/bitlbee'
    18 plugindir='$prefix/lib/bitlbee'
     20ipcsocket='/var/run/bitlbee.sock'
    1921pcdir='$prefix/lib/pkgconfig'
    20 includedir='$prefix/include/bitlbee'
    2122
    2223msn=1
     
    2728debug=0
    2829strip=1
    29 ipv6=1
     30gcov=0
     31plugins=1
     32
     33events=glib
     34ldap=0
    3035ssl=auto
    3136
    3237arch=`uname -s`
    3338cpu=`uname -m`
     39
     40GLIB_MIN_VERSION=2.4
    3441
    3542echo BitlBee configure
     
    6168--debug=0/1     Disable/enable debugging                $debug
    6269--strip=0/1     Disable/enable binary stripping         $strip
    63 
    64 --ipv6=0/1      IPv6 socket support                     $ipv6
    65 
    66 --ssl=...       SSL library to use (gnutls, nss, openssl, sspi, bogus, auto)
     70--gcov=0/1      Disable/enable test coverage reporting  $gcov
     71--plugins=0/1   Disable/enable plugins support          $plugins
     72
     73--events=...    Event handler (glib, libevent)          $events
     74--ssl=...       SSL library to use (gnutls, nss, openssl, bogus, auto)
    6775                                                        $ssl
    6876--arch=...  Override target architecture $arch
     
    8290config=`eval echo "$config/" | sed 's/\/\{1,\}/\//g'`
    8391plugindir=`eval echo "$plugindir/" | sed 's/\/\{1,\}/\//g'`
     92includedir=`eval echo "$includedir"/ | sed 's/\/\{1,\}/\//g'`
     93libevent=`eval echo "$libevent"/ | sed 's/\/\{1,\}/\//g'`
     94
    8495pidfile=`eval echo "$pidfile" | sed 's/\/\{1,\}/\//g'`
    8596ipcsocket=`eval echo "$ipcsocket" | sed 's/\/\{1,\}/\//g'`
    86 includedir=`eval echo "$includedir" | sed 's/\/\{1,\}/\//g'`
    8797pcdir=`eval echo "$pcdir" | sed 's/\/\{1,\}/\//g'`
    8898
     
    96106PLUGINDIR=$plugindir
    97107CONFIG=$config
    98 IPCSOCKET=$ipcsocket
    99108INCLUDEDIR=$includedir
    100109PCDIR=$pcdir
     
    125134EOF
    126135
    127 if [ "$ipv6" = "1" ]; then
    128         echo '#define IPV6' >> config.h
    129 fi
    130 
    131136if [ "$debug" = "1" ]; then
    132         echo 'CFLAGS=-g' >> Makefile.settings
     137        [ -z "$CFLAGS" ] && CFLAGS=-g
    133138        echo 'DEBUG=1' >> Makefile.settings
    134         echo '#define DEBUG' >> config.h
    135 else
    136         echo 'CFLAGS=-O3' >> Makefile.settings
    137 fi
    138 
    139 echo CFLAGS+=-I`pwd` -I`pwd`/protocols -I. >> Makefile.settings
     139        CFLAGS="$CFLAGS -DDEBUG"
     140else
     141        [ -z "$CFLAGS" ] && CFLAGS="-O2 -fno-strict-aliasing"
     142fi
     143
     144echo CFLAGS=$CFLAGS >> Makefile.settings
     145echo CFLAGS+=-I`pwd` -I`pwd`/lib -I`pwd`/protocols -I. >> Makefile.settings
    140146
    141147echo CFLAGS+=-DHAVE_CONFIG_H >> Makefile.settings
    142148
    143149if [ -n "$CC" ]; then
    144         echo "CC=$CC" >> Makefile.settings;
     150        CC=$CC
    145151elif type gcc > /dev/null 2> /dev/null; then
    146         echo "CC=gcc" >> Makefile.settings;
     152        CC=gcc
    147153elif type cc > /dev/null 2> /dev/null; then
    148         echo "CC=cc" >> Makefile.settings;
     154        CC=cc
    149155else
    150156        echo 'Cannot find a C compiler, aborting.'
    151157        exit 1;
    152158fi
     159
     160echo "CC=$CC" >> Makefile.settings;
    153161
    154162if [ -n "$LD" ]; then
     
    165173fi
    166174
    167 GLIB=0
    168 
    169175if $PKG_CONFIG --version > /dev/null 2>/dev/null && $PKG_CONFIG glib-2.0; then
    170         cat<<EOF>>Makefile.settings
     176        if $PKG_CONFIG glib-2.0 --atleast-version=$GLIB_MIN_VERSION; then
     177                cat<<EOF>>Makefile.settings
    171178EFLAGS+=`$PKG_CONFIG --libs glib-2.0 gmodule-2.0`
    172179CFLAGS+=`$PKG_CONFIG --cflags glib-2.0 gmodule-2.0`
    173180EOF
    174         echo '#define GLIB2' >> config.h
    175         GLIB=2
    176 elif type glib-config > /dev/null 2> /dev/null; then
    177         cat<<EOF>>Makefile.settings
    178 EFLAGS+=`glib-config --libs`
    179 CFLAGS+=`glib-config --cflags`
    180 EOF
    181         echo '#define GLIB1' >> config.h
    182         GLIB=1
    183 else
    184         echo 'Cannot find glib development libraries, aborting. (Install libglib-dev?)'
    185         exit 1;
    186 fi
    187 
    188 if [ GLIB = 1 -o -r /usr/include/iconv.h ]; then
    189         :;
    190 elif [ -r /usr/local/include/iconv.h ]; then
    191         echo CFLAGS+=-I/usr/local/include >> Makefile.settings;
    192 else
    193         echo
    194         echo 'Warning: Could not find iconv.h, you might have to install it and/or modify'
    195         echo 'Makefile.settings to tell where this file is.';
    196 fi
    197 
     181        else
     182                echo
     183                echo 'Found glib2 '`$PKG_CONFIG glib-2.0 --modversion`', but version '$GLIB_MIN_VERSION' or newer is required.'
     184                exit 1
     185        fi
     186else
     187        echo
     188        echo 'Cannot find glib2 development libraries, aborting. (Install libglib2-dev?)'
     189        exit 1
     190fi
     191
     192if [ "$events" = "libevent" ]; then
     193        if ! [ -f "${libevent}include/event.h" ]; then
     194                echo
     195                echo 'Warning: Could not find event.h, you might have to install it and/or specify'
     196                echo 'its location using the --libevent= argument. (Example: If event.h is in'
     197                echo '/usr/local/include and binaries are in /usr/local/lib: --libevent=/usr/local)'
     198        fi
     199       
     200        echo '#define EVENTS_LIBEVENT' >> config.h
     201        cat <<EOF>>Makefile.settings
     202EFLAGS+=-levent -L${libevent}lib
     203CFLAGS+=-I${libevent}include
     204EOF
     205elif [ "$events" = "glib" ]; then
     206        ## We already use glib anyway, so this is all we need (and in fact not even this, but just to be sure...):
     207        echo '#define EVENTS_GLIB' >> config.h
     208else
     209        echo
     210        echo 'ERROR: Unknown event handler specified.'
     211        exit 1
     212fi
     213echo 'EVENT_HANDLER=events_'$events'.o' >> Makefile.settings
    198214
    199215detect_gnutls()
     
    227243}
    228244
    229 if [ "$msn" = 1 -o "$jabber" = 1 ]; then
    230         if [ "$ssl" = "auto" ]; then
    231                 detect_gnutls
    232                 if [ "$ret" = "0" ]; then
    233                         detect_nss
    234                 fi;
    235         elif [ "$ssl" = "gnutls" ]; then
    236                 detect_gnutls;
    237         elif [ "$ssl" = "nss" ]; then
    238                 detect_nss;
    239         elif [ "$ssl" = "sspi" ]; then
     245detect_ldap()
     246{
     247        TMPFILE=`mktemp`
     248        if $CC -o $TMPFILE -shared -lldap 2>/dev/null >/dev/null; then
     249                cat<<EOF>>Makefile.settings
     250EFLAGS+=-lldap
     251CFLAGS+=
     252EOF
     253                ldap=1
     254                rm -f $TMPFILE
     255                ret=1
     256        else
     257                ldap=0
     258                ret=0
     259        fi
     260}
     261
     262if [ "$ssl" = "auto" ]; then
     263        detect_gnutls
     264        if [ "$ret" = "0" ]; then
     265                detect_nss
     266        fi
     267elif [ "$ssl" = "gnutls" ]; then
     268        detect_gnutls
     269elif [ "$ssl" = "nss" ]; then
     270        detect_nss
     271elif [ "$ssl" = "sspi" ]; then
     272        echo
     273elif [ "$ssl" = "openssl" ]; then
     274        echo
     275        echo 'No detection code exists for OpenSSL. Make sure that you have a complete'
     276        echo 'install of OpenSSL (including devel/header files) before reporting'
     277        echo 'compilation problems.'
     278        echo
     279        echo 'Also, keep in mind that the OpenSSL is, according to some people, not'
     280        echo 'completely GPL-compatible. Using GnuTLS or NSS is recommended and better'
     281        echo 'supported by us. However, on many BSD machines, OpenSSL can be considered'
     282        echo 'part of the operating system, which makes it GPL-compatible.'
     283        echo
     284        echo 'For more info, see: http://www.openssl.org/support/faq.html#LEGAL2'
     285        echo '                    http://www.gnome.org/~markmc/openssl-and-the-gpl.html'
     286        echo
     287        echo 'Please note that distributing a BitlBee binary which links to OpenSSL is'
     288        echo 'probably illegal. If you want to create and distribute a binary BitlBee'
     289        echo 'package, you really should use GnuTLS or NSS instead.'
     290        echo
     291        echo 'Also, the OpenSSL license requires us to say this:'
     292        echo ' *    "This product includes software developed by the OpenSSL Project'
     293        echo ' *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"'
     294       
     295        echo 'EFLAGS+=-lssl -lcrypto' >> Makefile.settings
     296       
     297        ret=1
     298elif [ "$ssl" = "bogus" ]; then
     299        echo
     300        echo 'Using bogus SSL code. This means some features will not work properly.'
     301       
     302        ## Yes, you, at the console! How can you authenticate if you don't have any SSL!?
     303        if [ "$msn" = "1" ]; then
    240304                echo
    241         elif [ "$ssl" = "openssl" ]; then
    242                 echo
    243                 echo 'No detection code exists for OpenSSL. Make sure that you have a complete'
    244                 echo 'install of OpenSSL (including devel/header files) before reporting'
    245                 echo 'compilation problems.'
    246                 echo
    247                 echo 'Also, keep in mind that the OpenSSL is, according to some people, not'
    248                 echo 'completely GPL-compatible. Using GnuTLS or NSS is recommended and better'
    249                 echo 'supported by us. However, on many BSD machines, OpenSSL can be considered'
    250                 echo 'part of the operating system, which makes it GPL-compatible.'
    251                 echo
    252                 echo 'For more info, see: http://www.openssl.org/support/faq.html#LEGAL2'
    253                 echo '                    http://www.gnome.org/~markmc/openssl-and-the-gpl.html'
    254                 echo
    255                 echo 'Please note that distributing a BitlBee binary which links to OpenSSL is'
    256                 echo 'probably illegal. If you want to create and distribute a binary BitlBee'
    257                 echo 'package, you really should use GnuTLS or NSS instead.'
    258                 echo
    259                 echo 'Also, the OpenSSL license requires us to say this:'
    260                 echo ' *    "This product includes software developed by the OpenSSL Project'
    261                 echo ' *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"'
    262                
    263                 echo 'EFLAGS+=-lssl -lcrypto' >> Makefile.settings
    264                
    265                 ret=1;
    266         elif [ "$ssl" = "bogus" ]; then
    267                 echo
    268                 echo 'Using bogus SSL code. This will not make the MSN module work, but it will'
    269                 echo 'allow you to use the Jabber module - although without working SSL support.'
    270                
    271                 ret=1;
    272         else
    273                 echo
    274                 echo 'ERROR: Unknown SSL library specified.'
    275                 exit 1;
    276         fi
    277        
    278         if [ "$ret" = "0" ]; then
    279                 echo
    280                 echo 'ERROR: Could not find a suitable SSL library (GnuTLS, libnss or OpenSSL).'
    281                 echo '       This is necessary for MSN and full Jabber support. To continue,'
    282                 echo '       install a suitable SSL library or disable MSN support (--msn=0).'
    283                 echo '       If you want Jabber without SSL support you can try --ssl=bogus.'
    284                
    285                 exit 1;
    286         fi;
    287        
    288         echo 'SSL_CLIENT=ssl_'$ssl'.o' >> Makefile.settings
    289 fi
     305                echo 'Real SSL support is necessary for MSN authentication, will build without'
     306                echo 'MSN protocol support.'
     307                msn=0
     308        fi
     309       
     310        ret=1
     311else
     312        echo
     313        echo 'ERROR: Unknown SSL library specified.'
     314        exit 1
     315fi
     316
     317if [ "$ret" = "0" ]; then
     318        echo
     319        echo 'ERROR: Could not find a suitable SSL library (GnuTLS, libnss or OpenSSL).'
     320        echo '       Please note that this script doesn'\''t have detection code for OpenSSL,'
     321        echo '       so if you want to use that, you have to select it by hand. If you don'\''t'
     322        echo '       need SSL support, you can select the "bogus" SSL library. (--ssl=bogus)'
     323       
     324        exit 1
     325fi;
     326
     327echo 'SSL_CLIENT=ssl_'$ssl'.o' >> Makefile.settings
     328
     329for i in /lib /usr/lib /usr/local/lib; do
     330        if [ -f $i/libresolv.a ]; then
     331                echo '#define HAVE_RESOLV_A' >> config.h
     332                echo 'EFLAGS+='$i'/libresolv.a' >> Makefile.settings
     333                break
     334        fi
     335done
     336
     337STORAGES="text xml"
     338
     339if [ "$ldap" = "auto" ]; then
     340        detect_ldap
     341fi
     342
     343if [ "$ldap" = 0 ]; then
     344        echo "#undef WITH_LDAP" >> config.h
     345elif [ "$ldap" = 1 ]; then
     346        echo
     347        echo 'LDAP support is a work in progress and does NOT work AT ALL right now.'
     348        echo
     349        exit 1
     350       
     351        echo "#define WITH_LDAP 1" >> config.h
     352        STORAGES="$STORAGES ldap"
     353fi
     354
     355for i in $STORAGES; do
     356        STORAGE_OBJS="$STORAGE_OBJS storage_$i.o"
     357done
     358echo "STORAGE_OBJS="$STORAGE_OBJS >> Makefile.settings
    290359
    291360if [ "$strip" = 0 ]; then
     
    301370        elif type strip > /dev/null 2> /dev/null; then
    302371                echo "STRIP=strip" >> Makefile.settings;
    303         elif /bin/test -x /usr/ccs/bin/strip; then
    304                 echo "STRIP=/usr/ccs/bin/strip" >> Makefile.settings;
    305372        else
    306373                echo
     
    309376                strip=0;
    310377        fi;
     378fi
     379
     380if [ "$gcov" = "1" ]; then
     381        echo "CFLAGS+=--coverage" >> Makefile.settings
     382        echo "EFLAGS+=--coverage" >> Makefile.settings
     383fi
     384
     385if [ "$plugins" = 0 ]; then
     386        echo '#undef WITH_PLUGINS' >> config.h
     387else
     388        echo '#define WITH_PLUGINS' >> config.h
    311389fi
    312390
     
    380458
    381459if [ "$protocols" = "PROTOCOLS = " ]; then
    382         echo "WARNING: You haven't selected any communication protocol to compile!"
    383         echo "         Bitlbee will run, but you will be unable to connect to IM servers!"
     460        echo "Warning: You haven't selected any communication protocol to compile!"
     461        echo "         BitlBee will run, but you will be unable to connect to IM servers!"
    384462fi
    385463
     
    394472;;
    395473*BSD )
    396         echo 'EFLAGS+=-liconv' >> Makefile.settings;
     474;;
     475Darwin )
     476;;
     477IRIX )
    397478;;
    398479SunOS )
    399480        echo 'EFLAGS+=-lresolv -lnsl -lsocket' >> Makefile.settings
    400481        echo 'STRIP=\# skip strip' >> Makefile.settings
    401         echo 'EFLAGS+=-liconv' >> Makefile.settings;
    402 ;;
    403 Darwin )
    404         echo 'EFLAGS+=-liconv' >> Makefile.settings;
    405 ;;
    406 IRIX )
     482;;
     483AIX )
     484        echo 'EFLAGS+=-Wl,-brtl' >> Makefile.settings
    407485;;
    408486CYGWIN* )
     
    424502
    425503if [ "$debug" = "1" ]; then
    426         echo '  Debugging enabled.';
    427 else
    428         echo '  Debugging disabled.';
     504        echo '  Debugging enabled.'
     505else
     506        echo '  Debugging disabled.'
    429507fi
    430508
    431509if [ "$strip" = "1" ]; then
    432         echo '  Binary stripping enabled.';
    433 else
    434         echo '  Binary stripping disabled.';
    435 fi
    436 
    437 if [ "$msn" = "1" ]; then
    438         echo '  Using SSL library: '$ssl;
    439 fi
    440 
    441 #if [ "$flood" = "0" ]; then
    442 #       echo '  Flood protection disabled.';
    443 #else
    444 #       echo '  Flood protection enabled.';
    445 #fi
     510        echo '  Binary stripping enabled.'
     511else
     512        echo '  Binary stripping disabled.'
     513fi
     514
     515echo '  Using event handler: '$events
     516echo '  Using SSL library: '$ssl
     517echo '  Building with these storage backends: '$STORAGES
    446518
    447519if [ -n "$protocols" ]; then
    448         echo '  Building with these protocols:' $protocols;
    449 else
    450         echo '  Building without IM-protocol support. We wish you a lot of fun...';
    451 fi
     520        echo '  Building with these protocols:' $protocols
     521else
     522        echo '  Building without IM-protocol support. We wish you a lot of fun...'
     523fi
  • crypting.c

    r875ad42 r85d7b85  
    2929   the programs will be built. */
    3030
     31#include <bitlbee.h>
    3132#include "md5.h"
    3233#include "crypting.h"
    33 #include <string.h>
    34 #include <stdio.h>
    35 #include <stdlib.h>
    3634
    3735/*\
  • crypting.h

    r875ad42 r85d7b85  
    2525
    2626int checkpass (const char *password, const char *md5sum);
    27 char *hashpass (const char *password);
    28 char *obfucrypt (char *line, const char *password);
    29 char *deobfucrypt (char *line, const char *password);
     27G_GNUC_MALLOC char *hashpass (const char *password);
     28G_GNUC_MALLOC char *obfucrypt (char *line, const char *password);
     29G_GNUC_MALLOC char *deobfucrypt (char *line, const char *password);
  • doc/CHANGES

    r875ad42 r85d7b85  
     1Version 1.2.1:
     2- Fixed proxy support.
     3- Fixed stalling issues while connecting to Jabber when using the OpenSSL
     4  module.
     5- Fixed problem with GLib and ForkDaemon where processes didn't die when
     6  the client disconnects.
     7- Fixed handling of "set charset none". (Which pretty much breaks the account
     8  completely in 1.2.)
     9- You can now automatically identify yourself to BitlBee by setting a server
     10  password in your IRC client.
     11- Compatible with all crazy kinds of line endings that clients can send.
     12
     13Finished ...
     14
     15Version 1.2:
     16- Added ForkDaemon mode next to the existing Daemon- and inetd modes. With
     17  ForkDaemon you can run BitlBee as a stand-alone daemon and every connection
     18  will run in its own process. No more need to configure inetd, and still you
     19  don't get the stability problems BitlBee unfortunately still has in ordinary
     20  (one-process) daemon mode.
     21- Added inter-process/connection communication. This made it possible to
     22  implement some IRC operator features like WALLOPs, KILL, DIE, REHASH and
     23  more.
     24- Added hooks for using libevent instead of GLib for event handling. This
     25  should improve scalability, although this won't really be useful yet because
     26  the one-process daemon mode is not reliable enough.
     27- BitlBee now makes the buddy quits when doing "account off" look like a
     28  netsplit. Modern IRC clients show this in a different, more compact way.
     29  (This can be disabled if your client doesn't support this.)
     30- GLib 1.x compatibility was dropped. BitlBee now requires GLib 2.4 or newer.
     31  This allows us to use more GLib features (like the XML parser). By now GLib
     32  1.x is so old that supporting it really isn't necessary anymore.
     33- Many, many, MANY little changes, improvements, fixes. Using non-blocking
     34  I/O as much as possible, replaced the Gaim (0.59, IOW heavily outdated)
     35  API, fixed lots of little bugs (including bugs that affected daemon mode
     36  stability). See the bzr logs for more information.
     37- One of the user-visible changes from the API change: You can finally see
     38  all away states/messages properly.
     39- Added units tests. Test coverage is very minimal for now.
     40- Better charset handling: Everything is just converted from/to UTF-8 right
     41  in the IRC core, and charset mismatches are detected (if possible) and the
     42  user is asked to resolve this before continuing. Also, UTF-8 is the default
     43  setting now, since that's how the world seems to work these days.
     44- One can now keep hashed passwords in bitlbee.conf instead of the cleartext
     45  version.
     46- Most important change: New file format for user data (accounts, nicks and
     47  settings). Migration to the new format should happen transparently,
     48  BitlBee will read the old files and once you quit/save it will save in the
     49  new format. It is recommended to delete the old files (BitlBee doesn't do
     50  this automatically, it will just ignore them) since they won't be used
     51  anymore (and since the old file format is a security risk). Some advantages
     52  of this file format switch:
     53  * Safer format, since the identify-password is now salted before generating
     54    a checksum. This way one can't use MD5 reverse lookup databases to crack
     55    passwords. Also, the IM-account passwords are encrypted using RC4 instead
     56    of the simple obfuscation scheme which BitlBee used so far.
     57  * Easier to extend than the previous format (at least the .nicks format was
     58    horribly limited).
     59  * Nicknames for buddies are now saved per-account instead of per-protocol.
     60    So far having one buddy on multiple accounts of the same protocol was a
     61    problem because the nicks generated for the two "instances" of this buddy
     62    were very unpredictable.
     63    NOTE: This also means that "account del" removes not just the account,
     64    BUT ALSO ALL NICKNAMES! If you're changing IM accounts and don't want to
     65    lose the nicknames, you can now use "account set" to change the username
     66    and password for the existing connection.
     67  * Per-account settings (see the new "account set" command).
     68- A brand new Jabber module. Besides the major code cleanup, it also has
     69  has these new features:
     70  * Pretty complete XMPP support: RFC3920, RFC3921 plus a number of XEPs
     71    including XEP45, XEP73 and XEP85. (See http://www.xmpp.org/ for what all
     72    these things mean exactly.) Privacy lists are not supported for obvious
     73    reasons.
     74  * This complete support also includes TLS and SASL support and SRV record
     75    lookup. This means that specifying a server tag for connections should
     76    (almost) never be necessary anymore, BitlBee can find the server and can
     77    automatically convert plaintext connections to TLS-encrypted ones.
     78  * XEP45: Jabber chatroom support!
     79  * XEP85 means typing notifications. The older XEP22 (still used by some
     80    clients including Gaim <2.0) is not supported.
     81  * Better handling of buddies who have more than one resource on-line. As
     82    long as one resource is on-line (and visible), BitlBee will show this.
     83    (The previous module didn't keep track of resources and sent an offline
     84    event as soon as any resource disappears.)
     85  * You can now set your resource priority.
     86  * The info command now gives away state/message information for all
     87    resources available for that buddy. (Of course this only works if the
     88    buddy is in your contact list.)
     89  * An XML console (add xmlconsole to your contact list or see "help set
     90    xmlconsole" if you want it permanently).
     91- The Yahoo! module now says it supports YMSG protocol version 12, which will
     92  hopefully keep the Yahoo module working after 2008-04-02 (when Yahoo! is
     93  dropping support for version 6.x of their client).
     94- MSN switchboard handling changes. Hopefully less messages will get lost now,
     95  although things are still not perfect.
     96
     97Finished 17 Mar 2008
     98
     99Version 1.0.4:
     100- Removed sethostent(), which causes problems for many people, especially on
     101  *BSD. This is basically the reason for this release.
     102- "allow" command actually displays the allow list, not the block list.
     103- Yahoo away state/msg fix.
     104- Don't display "Gender: Male" by default if nothing's filled in (OSCAR
     105  "info" command)
     106- Fixed account cleanup (possible infinite loop) in irc_free().
     107- Fixed configdir error message to not always display the compile-time
     108  setting.
     109
     110Finished 20 Aug 2007
     111
     112Version 1.0.3:
     113- Fixed ugliness in block/allow list commands (still not perfect though, the
     114  list is empty or not up-to-date for most protocols).
     115- OSCAR module doesn't send the ICQ web-aware flag anymore, which seems to
     116  get rid of a lot of ICQ spam.
     117- added show_got_added(), BitlBee asks you, after authorizing someone, if you
     118  want to add him/her to your list too.
     119- add -tmp, mainly convenient if you want to talk to people who are not in
     120  your list.
     121- Fixed ISON command, should work better with irssi now.
     122- Fixed compilation with tcc.
     123- Fixed xinetd-file.
     124- Misc. (crash)bug fixes, including one in the root command parsing that
     125  caused mysterious error messages sometimes.
     126
     127Finished 24 Jun 2006 (Happy 4th birthday, BitlBee!)
     128
     129Version 1.0.2:
     130- Pieces of code cleanup, fixes for possible problems in error checking.
     131- Fixed an auto-reconnect cleanup problem that caused crashes in daemon mode.
     132- /AWAY in daemon mode now doesn't set the away state for every connection
     133  anymore.
     134- Fixed a crash-bug on empty help subjects.
     135- Jabber now correctly sets the current away state when connecting.
     136- Added Invisible and Hidden to the away state alias list, invisible mode
     137  should be pretty usable now.
     138- Fixed handling of iconv(): It's now done for everything that goes between
     139  BitlBee and the IRC client, instead of doing it (almost) every time
     140  something goes to or come from the IM-modules. Should've thought about
     141  that before. :-)
     142- When cleaning up MSN switchboards with unsent msgs, it now also says which
     143  contact those messages were meant for.
     144- You can now use the block and allow commands to see your current block/
     145  allow list.
     146
     147Finished 1 Apr 2006
     148
     149Version 1.0.1:
     150- Support for AIM groupchats.
     151- Improved typing notification support for at least AIM.
     152- BitlBee sends a 005 reply when logging in, this informs modern IRC clients
     153  of some of BitlBee's capabilities. This might also solve problems some
     154  people were having with the new control channel name.
     155- MSN switchboards are now properly reset when talking to a person who is
     156  offline. This fixes problems with messages to MSN people that sometimes
     157  didn't arrive.
     158- Fixed one of the problems that made BitlBee show online Jabber people as
     159  offline.
     160- Fixed problems with commas in MSN passwords.
     161- Added some consts for read-only data, which should make the BitlBee per-
     162  process memory footprint a bit smaller.
     163- Other bits of code cleanup.
     164
     165Finished 14 Jan 2006
     166
    1167Version 1.0:
    2168- Removed some crashy debugging code.
  • doc/CREDITS

    r875ad42 r85d7b85  
    5050- Frank Thieme, for the info-command enhancements and other patches.
    5151- Marcus Dennis, for some bitlbeed enhancements.
    52 - 1nfamus, for security auditing BitlBee code.
     52- infamous41md, for security auditing BitlBee code.
    5353- Tijmen Ruizendaal, for some useful BitlBee-related irssi scripts.
    5454- Ed Schouten, for reporting bugs.
     55- Greg (gropeep.org), for updating the Yahoo! module to fix some issues
     56  that were there for quite some time already.
     57- misc@mandriva.org for lots of Jabber contributions.
    5558
    5659- And all other users who help us by sending useful bug reports, positive
  • doc/README

    r875ad42 r85d7b85  
    4242directory is read-/writable by this user only.
    4343
     44--- (Fork)Daemon mode
     45
     46If you don't want to run any inetd daemon, you can run BitlBee in Daemon
     47mode. Right now, daemon mode may be a bad idea on servers with multiple
     48users, since possible fatal BitlBee bugs will crash the BitlBee process and
     49disconnect all connected users at once. Instead, you can use ForkDaemon
     50mode, which serves every user from a separate process, without depending on
     51an inetd daemon.
     52
     53To use BitlBee in daemon mode, just start it with the right flags or enable
     54it in bitlbee.conf. You probably want to write an init script to start
     55BitlBee automatically after a reboot. (This is where you realise using
     56a package from your distro would've been a better idea. :-P)
     57
    4458
    4559DEPENDENCIES
     
    4761
    4862BitlBee's only real dependency is GLib. This is available on virtually every
    49 platform. Any recent version of GLib (including 1.x versions) will work.
     63platform. Any recent version of GLib (2.4 or higher) will work.
    5064
    5165These days, MSN Messenger clients have to connect to the MS Passport servers
     
    155169====================
    156170
    157 BitlBee stores the accounts and settings (not your contact list though) in
    158 some sort of encrypted/obfuscated format.
    159 
    160 *** THIS IS NOT A SAFE FORMAT! ***
    161 
    162 You should still make sure the rights to the configuration directory and
    163 files are set so that only root and the BitlBee user can read/write them.
    164 
    165 This format is not to prevent malicicous users from running with your
    166 passwords, but to prevent accidental glimpses of the administrators to cause
    167 any harm. You have no choice but to trust root though.
     171There used to be a note here about the simple obfuscation method used to
     172make the passwords in the configuration files unreadable. However, BitlBee
     173now uses a better format (and real encryption (salted MD5 and RC4)) to store
     174the passwords. This means that people who somehow get their hands on your
     175configuration files can't easily extract your passwords from them anymore.
     176
     177However, once you log into the BitlBee server and send your password, an
     178intruder with tcpdump can still read your passwords. This can't really be
     179avoided, of course. The new format is a lot more reliable (because it can't
     180be cracked with just very basic crypto analysis anymore), but you still have
     181to be careful. The main extra protection offered by the new format is that
     182the files can only be cracked with some help from the user (by sending the
     183password at login time).
     184
     185So if you run a public server, it's most important that you don't give root
     186access to people who like to play with tcpdump. Also, it's a good idea to
     187delete all *.nicks/*.accounts files as soon as BitlBee converted them to the
     188new format (which happens as soon as the user logs in, it can't be done
     189automatically because it needs the password for that account). You won't
     190need them anymore (unless you want to switch back to an older BitlBee
     191version) and they only make it easier for others to crack your passwords.
    168192
    169193
     
    174198file COPYING for this license.
    175199
    176 Unfortunately some parts of the Gaim Jabber plugin (most notably the XML
    177 code) were licensed under the MPL (Mozilla Public License) version 1.1. We
    178 could not relicense this code under the GPL. As such it is still licensed
    179 under the MPL. The parts of the code to which this applies are marked as
    180 such.
    181 
    182 The MPL is provided in the file MPL-1.1.txt. This license is not GPL
    183 compatible. It is however a free software license.
    184 
    185 Another part (the md5 algorithm) is licensed under the Aladdin license.
    186 This license can be found in the files, to which this applies.
     200The MD5 algorithm code is licensed under the Aladdin license. This license
     201can be found in the files, to which this applies. The SHA1 algorithm code
     202is licensed under the Mozilla Public License, see http://www.mozilla.org/MPL/
     203for details.
    187204
    188205The Yahoo! library used by BitlBee is libyahoo2 <http://libyahoo2.sf.net/>,
     
    192209        BitlBee - An IRC to other chat networks gateway
    193210                  <http://www.bitlbee.org/>
    194         Copyright (C) 2002-2005  Wilmer van der Gaast <wilmer@gaast.net>
     211        Copyright (C) 2002-2007  Wilmer van der Gaast <wilmer@gaast.net>
    195212                                 and others
  • doc/bitlbee.8

    r875ad42 r85d7b85  
    6363waits for new connections. All clients will be served from one process.
    6464This is still experimental. See the note above for more information.
     65.IP "-F"
     66Run in ForkDaemon mode. This is similar to ordinary daemon mode, but every
     67client gets its own process. Easier to set up than inetd mode, but without
     68the possible stability issues.
    6569.IP "-i \fIaddress\fP"
    6670Only useful when running in daemon mode, to specify the network interface
  • doc/user-guide/Makefile

    r875ad42 r85d7b85  
    2828        xsltproc --xinclude --output $@ docbook.xsl $<
    2929
    30 help.txt: help.xml help.xsl
     30help.txt: help.xml help.xsl commands.xml misc.xml quickstart.xml
    3131        xsltproc --stringparam extraparanewline "$(EXTRAPARANEWLINE)" --xinclude help.xsl $< | perl -0077 -pe 's/\n\n%/\n%/s; s/_b_/\002/g;' > $@
    3232
  • doc/user-guide/Support.xml

    r875ad42 r85d7b85  
    44
    55<sect1>
    6 <title>BitlBee is beta software</title>
     6<title>Disclaimer</title>
    77
    88<para>
    9 Although BitlBee has quite some functionality it is still beta. That means it
    10 can crash at any time, corrupt your data or whatever. Don't use it in
    11 any production environment and don't rely on it.
     9BitlBee doesn't come with a warranty and is still (and will probably always
     10be) under development. That means it can crash at any time, corrupt your
     11data or whatever. Don't use it in any production environment and don't rely
     12on it, or at least don't blame us if things blow up. :-)
    1213</para>
    1314
  • doc/user-guide/commands.xml

    r875ad42 r85d7b85  
    1111
    1212                        <para>
    13                                 Available actions: add, del, list, on, off. See <emphasis>help account &lt;action&gt;</emphasis> for more information.
     13                                Available actions: add, del, list, on, off and set. See <emphasis>help account &lt;action&gt;</emphasis> for more information.
    1414                        </para>
    1515
     
    1717
    1818                <bitlbee-command name="add">
    19                         <syntax>account add &lt;protocol&gt; &lt;username&gt; &lt;password&gt; [&lt;server&gt;]</syntax>
     19                        <syntax>account add &lt;protocol&gt; &lt;username&gt; &lt;password&gt;</syntax>
    2020
    2121                        <description>
     
    2626                       
    2727                        <bitlbee-command name="jabber">
    28                                 <syntax>account add jabber &lt;handle&gt; &lt;password&gt; [&lt;servertag&gt;]</syntax>
     28                                <syntax>account add jabber &lt;handle@server.tld&gt; &lt;password&gt;</syntax>
    2929
    3030                                <description>
    3131                                        <para>
    32                                                 Note that the servertag argument is optional. You only have to use it if the part after the @ in your handle isn't the hostname of your Jabber server, or if you want to use SSL/connect to a non-standard port number. The format is simple: [&lt;servername&gt;[:&lt;portnumber&gt;][:ssl]]. For example, this is how you can connect to Google Talk:
     32                                                The handle should be a full handle, including the domain name. You can specify a servername if necessary. Normally BitlBee doesn't need this though, since it's able to find out the server by doing DNS SRV lookups.
    3333                                        </para>
    34                                 </description>
    35 
    36                                 <ircexample>
    37                                         <ircline nick="wilmer">account add jabber example@gmail.com hobbelmeeuw talk.google.com:5223:ssl</ircline>
    38                                         <ircline nick="root">Account successfully added</ircline>
    39                                 </ircexample>
    40 
    41                                 <description>
     34
    4235                                        <para>
    43                                                 Note that Google talk is SSL-only, but officially reachable over both port 5222 and 5223. However, for some people only port 5222 works, for some people only 5223. This is something you'll have to try out.
     36                                                In previous versions it was also possible to specify port numbers and/or SSL in the server tag. This is deprecated and should now be done using the <emphasis>account set</emphasis> command. This also applies to specifying a resource in the handle (like <emphasis>wilmer@bitlbee.org/work</emphasis>).
    4437                                        </para>
    4538                                </description>
     
    4740
    4841                        <bitlbee-command name="msn">
    49                                 <syntax>account add msn &lt;handle&gt; &lt;password&gt;</syntax>
     42                                <syntax>account add msn &lt;handle@server.tld&gt; &lt;password&gt;</syntax>
    5043
    5144                                <description>
     
    5750                       
    5851                        <bitlbee-command name="oscar">
    59                                 <syntax>account add oscar &lt;handle&gt; &lt;password&gt; [&lt;servername&gt;]</syntax>
     52                                <syntax>account add oscar &lt;handle&gt; &lt;password&gt;</syntax>
    6053
    6154                                <description>
    6255                                        <para>
    63                                                 Specifying a server is required for OSCAR, since OSCAR can be used for both ICQ- and AIM-connections. Although these days it's supposed to be possible to connect to ICQ via AIM-servers and vice versa, we like to stick with this separation for now. For ICQ connections, the servername is <emphasis>login.icq.com</emphasis>, for AIM connections it's <emphasis>login.oscar.aol.com</emphasis>.
     56                                                OSCAR is the protocol used to connect to AIM and/or ICQ. The servers will automatically detect if you're using a numeric or non-numeric username so there's no need to tell which network you want to connect to.
    6457                                        </para>
    6558                                </description>
    6659
    6760                                <ircexample>
    68                                         <ircline nick="wilmer">account add oscar 72696705 hobbelmeeuw login.icq.com</ircline>
     61                                        <ircline nick="wilmer">account add oscar 72696705 hobbelmeeuw</ircline>
    6962                                        <ircline nick="root">Account successfully added</ircline>
    7063                                </ircexample>
     
    10396                        <description>
    10497                                <para>
    105                                         This command will try to log into the specified account. If no account is specified, BitlBee will log into all the accounts. (Including accounts awaiting a reconnection)
     98                                        This command will try to log into the specified account. If no account is specified, BitlBee will log into all the accounts that have the auto_connect flag set.
    10699                                </para>
    107100
     
    118111                        <description>
    119112                                <para>
    120                                         This command disconnects the connection for the specified account. If no account is specified, BitlBee will deactivate all active accounts. (Including accounts awaiting a reconnection)
     113                                        This command disconnects the connection for the specified account. If no account is specified, BitlBee will deactivate all active accounts and cancel all pending reconnects.
    121114                                </para>
    122115
     
    133126                                <para>
    134127                                        This command gives you a list of all the accounts known by BitlBee, including the numbers you'll need for most account commands.
     128                                </para>
     129                        </description>
     130                </bitlbee-command>
     131
     132                <bitlbee-command name="set">
     133                        <syntax>account set &lt;account id&gt;</syntax>
     134                        <syntax>account set &lt;account id&gt;/&lt;setting&gt;</syntax>
     135                        <syntax>account set &lt;account id&gt;/&lt;setting&gt; &lt;value&gt;</syntax>
     136                        <syntax>account set -del &lt;account id&gt;/&lt;setting&gt;</syntax>
     137
     138                        <description>
     139                                <para>
     140                                        This account can be used to change various settings for IM accounts. For all protocols, this command can be used to change the handle or the password BitlBee uses to log in and if it should be logged in automatically. Some protocols have additional settings. You can see the settings available for a connection by typing <emphasis>account set &lt;account id&gt;</emphasis>.
     141                                </para>
     142                               
     143                                <para>
     144                                        For more infomation about a setting, see <emphasis>help set &lt;setting&gt;</emphasis>. For details about the syntax of this command, see <emphasis>help set</emphasis>.
     145                                </para>
     146                               
     147                                <para>
     148                                        The account ID can be a number (see <emphasis>account list</emphasis>), the protocol name or (part of) the screenname, as long as it matches only one connection.
    135149                                </para>
    136150                        </description>
     
    149163
    150164                        <para>
    151                                 If you want, you can also tell BitlBee what nick to give the new contact. Of course you can also use the <emphasis>rename</emphasis> command for that, but sometimes this might be more convenient.
    152                         </para>
    153                        
    154                         <para>
    155                                 Adding -tmp adds the buddy to the internal BitlBee structures only, not to the real contact list (like done by <emphasis>set handle_unknown add</emphasis>). This allows you to talk to people who are not in your contact list.
     165                                If you want, you can also tell BitlBee what nick to give the new contact. The -tmp option adds the buddy to the internal BitlBee structures only, not to the real contact list (like done by <emphasis>set handle_unknown add</emphasis>). This allows you to talk to people who are not in your contact list. This normally won't show you any presence notifications.
    156166                        </para>
    157167                </description>
     
    233243        <bitlbee-command name="set">
    234244                <short-description>Miscellaneous settings</short-description>
    235                 <syntax>set [&lt;variable&gt; [&lt;value&gt;]]</syntax>
    236 
    237                 <description>
    238 
    239                         <para>
    240                                 Without any arguments, this command lists all the set variables. You can also specify a single argument, a variable name, to get that variable's value. To change this value, specify the new value as the second argument.
     245                <syntax>set</syntax>
     246                <syntax>set &lt;variable&gt;</syntax>
     247                <syntax>set &lt;variable&gt; &lt;value&gt;</syntax>
     248                <syntax>set -del &lt;variable&gt;</syntax>
     249
     250                <description>
     251
     252                        <para>
     253                                Without any arguments, this command lists all the set variables. You can also specify a single argument, a variable name, to get that variable's value. To change this value, specify the new value as the second argument. With <emphasis>-del</emphasis> you can reset a setting to its default value.
    241254                        </para>
    242255
     
    276289        </bitlbee-command>
    277290
    278         <bitlbee-setting name="charset" type="string">
    279                 <default>iso8859-1</default>
     291        <bitlbee-setting name="auto_connect" type="boolean" scope="both">
     292                <default>true</default>
     293
     294                <description>
     295                        <para>
     296                                With this option enabled, when you identify BitlBee will automatically connect to your accounts, with this disabled it will not do this.
     297                        </para>
     298                       
     299                        <para>
     300                                This setting can also be changed for specific accounts using the <emphasis>account set</emphasis> command. (However, these values will be ignored if the global <emphasis>auto_connect</emphasis> setting is disabled!)
     301                        </para>
     302                </description>
     303        </bitlbee-setting>
     304
     305        <bitlbee-setting name="auto_reconnect" type="boolean" scope="both">
     306                <default>false</default>
     307
     308                <description>
     309                        <para>
     310                                If an IM-connections breaks, you're supposed to bring it back up yourself. Having BitlBee do this automatically might not always be a good idea, for several reasons. If you want the connections to be restored automatically, you can enable this setting.
     311                        </para>
     312
     313                        <para>
     314                                See also the <emphasis>auto_reconnect_delay</emphasis> setting.
     315                        </para>
     316
     317                        <para>
     318                                This setting can also be changed for specific accounts using the <emphasis>account set</emphasis> command. (However, these values will be ignored if the global <emphasis>auto_reconnect</emphasis> setting is disabled!)
     319                        </para>
     320                </description>
     321        </bitlbee-setting>
     322
     323        <bitlbee-setting name="auto_reconnect_delay" type="integer" scope="global">
     324                <default>300</default>
     325
     326                <description>
     327                        <para>
     328                                Tell BitlBee after how many seconds it should attempt to bring an IM-connection back up after a crash. It's not a good idea to set this value very low, it will cause too much useless traffic when an IM-server is down for a few hours.
     329                        </para>
     330
     331                        <para>
     332                                See also the <emphasis>auto_reconnect</emphasis> setting.
     333                        </para>
     334                </description>
     335        </bitlbee-setting>
     336
     337        <bitlbee-setting name="away_devoice" type="boolean" scope="global">
     338                <default>true</default>
     339
     340                <description>
     341                        <para>
     342                                With this option enabled, the root user devoices people when they go away (just away, not offline) and gives the voice back when they come back. You might dislike the voice-floods you'll get if your contact list is huge, so this option can be disabled.
     343                        </para>
     344                </description>
     345        </bitlbee-setting>
     346
     347        <bitlbee-setting name="buddy_sendbuffer" type="boolean" scope="global">
     348                <default>false</default>
     349
     350                <description>
     351                        <para>
     352                                By default, when you send a message to someone, BitlBee forwards this message to the user immediately. When you paste a large number of lines, the lines will be sent in separate messages, which might not be very nice to read. If you enable this setting, BitlBee will buffer your messages and wait for more data.
     353                        </para>
     354
     355                        <para>
     356                                Using the <emphasis>buddy_sendbuffer_delay</emphasis> setting you can specify the number of seconds BitlBee should wait for more data before the complete message is sent.
     357                        </para>
     358
     359                        <para>
     360                                Please note that if you remove a buddy from your list (or if the connection to that user drops) and there's still data in the buffer, this data will be lost. BitlBee will not try to send the message to the user in those cases.
     361                        </para>
     362                </description>
     363        </bitlbee-setting>
     364
     365        <bitlbee-setting name="buddy_sendbuffer_delay" type="integer" scope="global">
     366                <default>200</default>
     367
     368                <description>
     369
     370                        <para>
     371                                Tell BitlBee after how many (mili)seconds a buffered message should be sent. Values greater than 5 will be interpreted as miliseconds, 5 and lower as seconds.
     372                        </para>
     373
     374                        <para>
     375                                See also the <emphasis>buddy_sendbuffer</emphasis> setting.
     376                        </para>
     377                </description>
     378        </bitlbee-setting>
     379
     380        <bitlbee-setting name="charset" type="string" scope="global">
     381                <default>utf-8</default>
    280382                <possible-values>you can get a list of all possible values by doing 'iconv -l' in a shell</possible-values>
    281383
    282384                <description>
    283385                        <para>
    284                                 The charset setting enables you to use different character sets in BitlBee. These get converted to UTF-8 before sending and from UTF-8 when receiving.
    285                         </para>
    286 
    287                         <para>
    288                                 If you don't know what's the best value for this, at least iso8859-1 is the best choice for most Western countries. You can try to find what works best for you on http://czyborra.com/charsets/iso8859.html
    289                         </para>
    290                 </description>
    291 
    292         </bitlbee-setting>
    293 
    294         <bitlbee-setting name="private" type="boolean">
    295                 <default>True</default>
    296 
    297                 <description>
    298 
    299                         <para>
    300                                 If value is true, messages from users will appear in separate query windows. If false, messages from users will appear in the control channel.
    301                         </para>
    302 
    303                         <para>
    304                                 This setting is remembered (during one session) per-user, this setting only changes the default state. This option takes effect as soon as you reconnect.
    305                         </para>
    306                 </description>
    307         </bitlbee-setting>
    308 
    309         <bitlbee-setting name="save_on_quit" type="boolean">
    310                 <default>True</default>
    311 
    312                 <description>
    313                         <para>
    314                                 If enabled causes BitlBee to save all current settings and account details when user disconnects. This is enabled by default, and these days there's not really a reason to have it disabled anymore.
    315                         </para>
    316                 </description>
    317         </bitlbee-setting>
    318 
    319         <bitlbee-setting name="strip_html" type="boolean">
    320                 <default>True</default>
    321 
    322                 <description>
    323                         <para>
    324                                 Determines what BitlBee should do with HTML in messages. Normally this is turned on and HTML will be stripped from messages, if BitlBee thinks there is HTML.
    325                         </para>
    326                         <para>
    327                                 If BitlBee fails to detect this sometimes (most likely in AIM messages over an ICQ connection), you can set this setting to <emphasis>always</emphasis>, but this might sometimes accidentally strip non-HTML things too.
    328                         </para>
    329                 </description>
    330         </bitlbee-setting>
    331 
    332         <bitlbee-setting name="debug" type="boolean">
    333                 <default>False</default>
     386                                This setting tells BitlBee what your IRC client sends and expects. It should be equal to the charset setting of your IRC client if you want to be able to send and receive non-ASCII text properly.
     387                        </para>
     388
     389                        <para>
     390                                Most systems use UTF-8 these days. On older systems, an iso8859 charset may work better. For example, iso8859-1 is the best choice for most Western countries. You can try to find what works best for you on http://www.unicodecharacter.com/charsets/iso8859.html
     391                        </para>
     392                </description>
     393
     394        </bitlbee-setting>
     395
     396        <bitlbee-setting name="debug" type="boolean" scope="global">
     397                <default>false</default>
    334398
    335399                <description>
     
    340404        </bitlbee-setting>
    341405
    342         <bitlbee-setting name="to_char" type="string">
    343                 <default>": "</default>
    344 
    345                 <description>
    346 
    347                         <para>
    348                                 It's customary that messages meant for one specific person on an IRC channel are prepended by his/her alias followed by a colon ':'. BitlBee does this by default. If you prefer a different character, you can set it using <emphasis>set to_char</emphasis>.
    349                         </para>
    350 
    351                         <para>
    352                                 Please note that this setting is only used for incoming messages. For outgoing messages you can use ':' (colon) or ',' to separate the destination nick from the message, and this is not configurable.
    353                         </para>
    354                 </description>
    355         </bitlbee-setting>
    356 
    357         <bitlbee-setting name="typing_notice" type="boolean">
    358                 <default>False</default>
    359 
    360                 <description>
    361                         <para>
    362                                 Sends you a /notice when a user starts typing a message (if the protocol supports it, MSN for example). This is a bug, not a feature. (But please don't report it.. ;-) You don't want to use it. Really. In fact the typing-notification is just one of the least useful 'innovations' ever. It's just there because some guy will probably ask me about it anyway. ;-)
    363                         </para>
    364                 </description>
    365         </bitlbee-setting>
    366 
    367         <bitlbee-setting name="ops" type="string">
    368                 <default>both</default>
    369                 <possible-values>both, root, user, none</possible-values>
    370 
    371                 <description>
    372                         <para>
    373                                 Some people prefer themself and root to have operator status in &amp;bitlbee, other people don't. You can change these states using this setting.
    374                         </para>
    375 
    376                         <para>
    377                                 The value "both" means both user and root get ops. "root" means, well, just root. "user" means just the user. "none" means nobody will get operator status.
    378                         </para>
    379                 </description>
    380         </bitlbee-setting>
    381 
    382         <bitlbee-setting name="away_devoice" type="boolean">
    383                 <default>True</default>
    384 
    385                 <description>
    386                         <para>
    387                                 With this option enabled, the root user devoices people when they go away (just away, not offline) and gives the voice back when they come back. You might dislike the voice-floods you'll get if your contact list is huge, so this option can be disabled.
    388                         </para>
    389                 </description>
    390         </bitlbee-setting>
    391 
    392         <bitlbee-setting name="handle_unknown" type="string">
     406        <bitlbee-setting name="default_target" type="string" scope="global">
     407                <default>root</default>
     408                <possible-values>root, last</possible-values>
     409
     410                <description>
     411                        <para>
     412                                With this value set to <emphasis>root</emphasis>, lines written in the control channel without any nickname in front of them will be interpreted as commands. If you want BitlBee to send those lines to the last person you addressed in the control channel, set this to <emphasis>last</emphasis>.
     413                        </para>
     414                </description>
     415        </bitlbee-setting>
     416
     417        <bitlbee-setting name="display_name" type="string" scope="account">
     418                <description>
     419                        <para>
     420                                Currently only available for MSN connections. This setting allows you to read and change your "friendly name" for this connection. Since this is a server-side setting, it can't be changed when the account is off-line.
     421                        </para>
     422                </description>
     423        </bitlbee-setting>
     424
     425        <bitlbee-setting name="display_namechanges" type="boolean" scope="global">
     426                <default>false</default>
     427
     428                <description>
     429                        <para>
     430                                With this option enabled, root will inform you when someone in your buddy list changes his/her "friendly name".
     431                        </para>
     432                </description>
     433        </bitlbee-setting>
     434
     435        <bitlbee-setting name="handle_unknown" type="string" scope="global">
    393436                <default>root</default>
    394437                <possible-values>root, add, add_private, add_channel, ignore</possible-values>
     
    417460        </bitlbee-setting>
    418461
    419         <bitlbee-setting name="auto_connect" type="boolean">
    420                 <default>True</default>
    421 
    422                 <description>
    423                         <para>
    424                                 With this option enabled, when you identify BitlBee will automatically connect to your accounts, with this disabled it will not do this.
    425                         </para>
    426                 </description>
    427         </bitlbee-setting>
    428 
    429         <bitlbee-setting name="auto_reconnect" type="boolean">
    430                 <default>False</default>
    431 
    432                 <description>
    433                         <para>
    434                                 If an IM-connections breaks, you're supposed to bring it back up yourself. Having BitlBee do this automatically might not always be a good idea, for several reasons. If you want the connections to be restored automatically, you can enable this setting.
    435                         </para>
    436 
    437                         <para>
    438                                 See also the <emphasis>auto_reconnect_delay</emphasis> setting.
    439                         </para>
    440                 </description>
    441 
    442         </bitlbee-setting>
    443 
    444         <bitlbee-setting name="auto_reconnect_delay" type="integer">
    445                 <default>300</default>
    446 
    447                 <description>
    448 
    449                         <para>
    450                                 Tell BitlBee after how many seconds it should attempt to bring an IM-connection back up after a crash. It's not a good idea to set this value very low, it will cause too much useless traffic when an IM-server is down for a few hours.
    451                         </para>
    452 
    453                         <para>
    454                                 See also the <emphasis>auto_reconnect</emphasis> setting.
    455                         </para>
    456                 </description>
    457         </bitlbee-setting>
    458 
    459         <bitlbee-setting name="buddy_sendbuffer" type="boolean">
    460                 <default>False</default>
    461 
    462                 <description>
    463 
    464                         <para>
    465                                 By default, when you send a message to someone, BitlBee forwards this message to the user immediately. When you paste a large number of lines, the lines will be sent in separate messages, which might not be very nice to read. If you enable this setting, BitlBee will buffer your messages and wait for more data.
    466                         </para>
    467 
    468                         <para>
    469                                 Using the <emphasis>buddy_sendbuffer_delay</emphasis> setting you can specify the number of seconds BitlBee should wait for more data before the complete message is sent.
    470                         </para>
    471 
    472                         <para>
    473                                 Please note that if you remove a buddy from your list (or if the connection to that user drops) and there's still data in the buffer, this data will be lost. BitlBee will not try to send the message to the user in those cases.
    474                         </para>
    475                 </description>
    476 
    477         </bitlbee-setting>
    478 
    479         <bitlbee-setting name="buddy_sendbuffer_delay" type="integer">
    480                 <default>200</default>
    481 
    482                 <description>
    483 
    484                         <para>
    485                                 Tell BitlBee after how many (mili)seconds a buffered message should be sent. Values greater than 5 will be interpreted as miliseconds, 5 and lower as seconds.
    486                         </para>
    487 
    488                         <para>
    489                                 See also the <emphasis>buddy_sendbuffer</emphasis> setting.
    490                         </para>
    491                 </description>
    492 
    493         </bitlbee-setting>
    494 
    495         <bitlbee-setting name="default_target" type="string">
    496                 <default>root</default>
    497                 <possible-values>root, last</possible-values>
    498 
    499                 <description>
    500                         <para>
    501                                 With this value set to <emphasis>root</emphasis>, lines written in the control channel without any nickname in front of them will be interpreted as commands. If you want BitlBee to send those lines to the last person you addressed in the control channel, set this to <emphasis>last</emphasis>.
    502                         </para>
    503                 </description>
    504 
    505         </bitlbee-setting>
    506 
    507         <bitlbee-setting name="display_namechanges" type="boolean">
    508                 <default>False</default>
    509 
    510                 <para>
    511                         With this option enabled, root will inform you when someone in your buddy list changes his/her "friendly name".
    512                 </para>
    513         </bitlbee-setting>
    514 
    515         <bitlbee-setting name="password" type="string">
    516                 <description>
    517                         <para>
    518                                 Use this setting to change your "NickServ" password.
    519                         </para>
    520                 </description>
    521         </bitlbee-setting>
    522 
    523         <bitlbee-setting name="query_order" type="string">
     462        <bitlbee-setting name="lcnicks" type="boolean" scope="global">
     463                <default>true</default>
     464
     465                <description>
     466                        <para>
     467                                Hereby you can change whether you want all lower case nick names or leave the case as it intended by your peer.
     468                        </para>
     469                </description>
     470
     471        </bitlbee-setting>
     472
     473        <bitlbee-setting name="mail_notifications" type="boolean" scope="account">
     474                <default>false</default>
     475
     476                <description>
     477                        <para>
     478                                Some protocols (MSN, Yahoo!) can notify via IM about new e-mail. Since most people use their Hotmail/Yahoo! addresses as a spam-box, this is disabled default. If you want these notifications, you can enable this setting.
     479                        </para>
     480                </description>
     481
     482        </bitlbee-setting>
     483
     484        <bitlbee-setting name="ops" type="string" scope="global">
     485                <default>both</default>
     486                <possible-values>both, root, user, none</possible-values>
     487
     488                <description>
     489                        <para>
     490                                Some people prefer themself and root to have operator status in &amp;bitlbee, other people don't. You can change these states using this setting.
     491                        </para>
     492
     493                        <para>
     494                                The value "both" means both user and root get ops. "root" means, well, just root. "user" means just the user. "none" means nobody will get operator status.
     495                        </para>
     496                </description>
     497        </bitlbee-setting>
     498
     499        <bitlbee-setting name="password" type="string" scope="both">
     500                <description>
     501                        <para>
     502                                Use this global setting to change your "NickServ" password.
     503                        </para>
     504                       
     505                        <para>
     506                                This setting is also available for all IM accounts to change the password BitlBee uses to connect to the service.
     507                        </para>
     508                       
     509                        <para>
     510                                Note that BitlBee will always say this setting is empty. This doesn't mean there is no password, it just means that, for security reasons, BitlBee stores passwords somewhere else so they can't just be retrieved in plain text.
     511                        </para>
     512                </description>
     513        </bitlbee-setting>
     514       
     515        <bitlbee-setting name="port" type="integer" scope="account">
     516                <description>
     517                        <para>
     518                                Currently only available for Jabber connections. Specifies the port number to connect to. Usually this should be set to 5222, or 5223 for SSL-connections.
     519                        </para>
     520                </description>
     521        </bitlbee-setting>
     522
     523        <bitlbee-setting name="priority" type="integer" scope="account">
     524                <default>0</default>
     525
     526                <description>
     527                        <para>
     528                                Can be set for Jabber connections. When connecting to one account from multiple places, this priority value will help the server to determine where to deliver incoming messages (that aren't addressed to a specific resource already).
     529                        </para>
     530
     531                        <para>
     532                                According to RFC 3921 servers will always deliver messages to the server with the highest priority value. Mmessages will not be delivered to resources with a negative priority setting (and should be saved as an off-line message if all available resources have a negative priority value).
     533                        </para>
     534                </description>
     535        </bitlbee-setting>
     536
     537        <bitlbee-setting name="private" type="boolean" scope="global">
     538                <default>true</default>
     539
     540                <description>
     541                        <para>
     542                                If value is true, messages from users will appear in separate query windows. If false, messages from users will appear in the control channel.
     543                        </para>
     544
     545                        <para>
     546                                This setting is remembered (during one session) per-user, this setting only changes the default state. This option takes effect as soon as you reconnect.
     547                        </para>
     548                </description>
     549        </bitlbee-setting>
     550
     551        <bitlbee-setting name="query_order" type="string" scope="global">
    524552                <default>lifo</default>
    525553                <possible-values>lifo, fifo</possible-values>
     
    536564        </bitlbee-setting>
    537565
    538         <bitlbee-setting name="lcnicks" type="boolean">
    539                 <default>True</default>
    540 
    541                 <description>
    542                         <para>
    543                                 Hereby you can change whether you want all lower case nick names or leave the case as it intended by your peer.
    544                         </para>
    545                 </description>
    546 
     566        <bitlbee-setting name="resource" type="string" scope="account">
     567                <default>BitlBee</default>
     568
     569                <description>
     570                        <para>
     571                                Can be set for Jabber connections. You can use this to connect to your Jabber account from multiple clients at once, with every client using a different resource string.
     572                        </para>
     573                </description>
     574        </bitlbee-setting>
     575
     576        <bitlbee-setting name="resource_select" type="string" scope="account">
     577                <default>priority</default>
     578                <possible-values>priority, time</possible-values>
     579
     580                <description>
     581                        <para>
     582                                Because the IRC interface makes it pretty hard to specify the resource to talk to (when a buddy is online through different resources), this setting was added.
     583                        </para>
     584
     585                        <para>
     586                                Normally it's set to <emphasis>priority</emphasis> which means messages will always be delivered to the buddy's resource with the highest priority. If the setting is set to <emphasis>time</emphasis>, messages will be delivered to the resource that was last used to send you a message (or the resource that most recently connected).
     587                        </para>
     588                </description>
     589        </bitlbee-setting>
     590
     591        <bitlbee-setting name="save_on_quit" type="boolean" scope="global">
     592                <default>true</default>
     593
     594                <description>
     595                        <para>
     596                                If enabled causes BitlBee to save all current settings and account details when user disconnects. This is enabled by default, and these days there's not really a reason to have it disabled anymore.
     597                        </para>
     598                </description>
     599        </bitlbee-setting>
     600
     601        <bitlbee-setting name="server" type="string" scope="account">
     602                <description>
     603                        <para>
     604                                Can be set for Jabber- and OSCAR-connections. For Jabber, you might have to set this if the servername isn't equal to the part after the @ in the Jabber handle. For OSCAR this shouldn't be necessary anymore in recent BitlBee versions.
     605                        </para>
     606                </description>
     607        </bitlbee-setting>
     608
     609        <bitlbee-setting name="simulate_netsplit" type="boolean" scope="global">
     610                <default>true</default>
     611
     612                <description>
     613                        <para>
     614                                Some IRC clients parse quit messages sent by the IRC server to see if someone really left or just disappeared because of a netsplit. By default, BitlBee tries to simulate netsplit-like quit messages to keep the control channel window clean. If you don't like this (or if your IRC client doesn't support this) you can disable this setting.
     615                        </para>
     616                </description>
     617        </bitlbee-setting>
     618
     619        <bitlbee-setting name="ssl" type="boolean" scope="account">
     620                <default>false</default>
     621
     622                <description>
     623                        <para>
     624                                Currently only available for Jabber connections. Set this to true if the server accepts SSL connections.
     625                        </para>
     626                </description>
     627        </bitlbee-setting>
     628
     629        <bitlbee-setting name="strip_html" type="boolean" scope="global">
     630                <default>true</default>
     631
     632                <description>
     633                        <para>
     634                                Determines what BitlBee should do with HTML in messages. Normally this is turned on and HTML will be stripped from messages, if BitlBee thinks there is HTML.
     635                        </para>
     636                        <para>
     637                                If BitlBee fails to detect this sometimes (most likely in AIM messages over an ICQ connection), you can set this setting to <emphasis>always</emphasis>, but this might sometimes accidentally strip non-HTML things too.
     638                        </para>
     639                </description>
     640        </bitlbee-setting>
     641
     642        <bitlbee-setting name="tls" type="boolean" scope="account">
     643                <default>try</default>
     644
     645                <description>
     646                        <para>
     647                                Newer Jabber servers allow clients to convert a plain-text session to a TLS/SSL-encrypted session. Normally (with this setting set to <emphasis>try</emphasis>) BitlBee will do this, if possible.
     648                        </para>
     649
     650                        <para>
     651                                If you want to force BitlBee to use TLS sessions only (and to give up if that doesn't seem to be possible) you can set this setting to <emphasis>true</emphasis>. Set it to <emphasis>false</emphasis> if you want the session to remain plain-text.
     652                        </para>
     653                </description>
     654        </bitlbee-setting>
     655
     656        <bitlbee-setting name="to_char" type="string" scope="global">
     657                <default>": "</default>
     658
     659                <description>
     660                        <para>
     661                                It's customary that messages meant for one specific person on an IRC channel are prepended by his/her alias followed by a colon ':'. BitlBee does this by default. If you prefer a different character, you can set it using <emphasis>set to_char</emphasis>.
     662                        </para>
     663
     664                        <para>
     665                                Please note that this setting is only used for incoming messages. For outgoing messages you can use ':' (colon) or ',' to separate the destination nick from the message, and this is not configurable.
     666                        </para>
     667                </description>
     668        </bitlbee-setting>
     669
     670        <bitlbee-setting name="typing_notice" type="boolean" scope="global">
     671                <default>false</default>
     672
     673                <description>
     674                        <para>
     675                                Sends you a /notice when a user starts typing a message (if supported by the IM protocol and the user's client). To use this, you most likely want to use a script in your IRC client to show this information in a more sensible way.
     676                        </para>
     677                </description>
     678        </bitlbee-setting>
     679
     680        <bitlbee-setting name="web_aware" type="string" scope="account">
     681                <default>false</default>
     682
     683                <description>
     684                        <para>
     685                                ICQ allows people to see if you're on-line via a CGI-script. (http://status.icq.com/online.gif?icq=UIN) This can be nice to put on your website, but it seems that spammers also use it to see if you're online without having to add you to their contact list. So to prevent ICQ spamming, recent versions of BitlBee disable this feature by default.
     686                        </para>
     687
     688                        <para>
     689                                Unless you really intend to use this feature somewhere (on forums or maybe a website), it's probably better to keep this setting disabled.
     690                        </para>
     691                </description>
     692        </bitlbee-setting>
     693
     694        <bitlbee-setting name="xmlconsole" type="boolean" scope="account">
     695                <default>false</default>
     696
     697                <description>
     698                        <para>
     699                                The Jabber module allows you to add a buddy <emphasis>xmlconsole</emphasis> to your contact list, which will then show you the raw XMPP stream between you and the server. You can also send XMPP packets to this buddy, which will then be sent to the server.
     700                        </para>
     701                        <para>
     702                                If you want to enable this XML console permanently (and at login time already), you can set this setting.
     703                        </para>
     704                </description>
    547705        </bitlbee-setting>
    548706
     
    668826                <short-description>Change friendly name, nick</short-description>
    669827                <syntax>nick &lt;connection&gt; [&lt;new nick&gt;]</syntax>
    670                 <syntax>nick</syntax>
    671 
    672                 <description>
    673                         <para>
    674                                 This command allows to set the friendly name of an im account. If no new name is specified the command will report the current name. When the name contains spaces, don't forget to quote the whole nick in double quotes. Currently this command is only supported by the MSN protocol.
     828                <syntax>nick &lt;connection&gt;</syntax>
     829
     830                <description>
     831                        <para>
     832                                Deprecated: Use the per-account <emphasis>display_name</emphasis> setting to read and change this information.
    675833                        </para>
    676834                </description>
    677835
    678836                <ircexample>
    679                         <ircline nick="wouter">nick 1 "Wouter Paesen"</ircline>
    680                         <ircline nick="root">Setting your name on connection 1 to `Wouter Paesen'</ircline>
     837                        <ircline nick="wouter">account set 1/display_name "The majestik møøse"</ircline>
     838                        <ircline nick="root">display_name = `The majestik møøse'</ircline>
    681839                </ircexample>
    682840
    683841        </bitlbee-command>
    684842
    685         <bitlbee-command name="import_buddies">
    686                 <short-description>Copy local buddy list to server (normally only needed when upgrading)</short-description>
    687                 <syntax>import_buddies &lt;connection&gt; [clear]</syntax>
    688 
    689                 <description>
    690                         <para>
    691                                 This command copies the locally stored buddy list to the server. This command exists for upgrading purposes. Previous versions of BitlBee didn't support server-side buddy lists for ICQ, so the list was stored locally.
    692                         </para>
    693 
    694                         <para>
    695                                 Since version 0.91 however, server-side contact lists are supported for all protocols, so the local list is now ignored. When upgrading from an older BitlBee to version 0.91, you might need this command to get your buddy list back.
    696                         </para>
    697 
    698                         <para>
    699                                 The only argument this command needs is your ICQ account identification. If your serverside buddy list contains some old buddies you don't want anymore, you can pass <emphasis>clear</emphasis> as a second argument.
    700                         </para>
    701 
    702                         <para>
    703                                 After giving this command, you have to wait for a while before all the adds are handled, because of ICQ's rate limiting. If your buddy list is very large and the ICQ server starts complaining, you might have to reconnect and enter this command again.
    704                         </para>
    705                 </description>
     843        <bitlbee-command name="join_chat">
     844                <short-description>Join a named groupchat/conference room</short-description>
     845                <syntax>join_chat &lt;connection&gt; &lt;room name&gt; [&lt;channel name&gt;] [&lt;room nickname&gt;] [&lt;password&gt;]</syntax>
     846
     847                <description>
     848                        <para>
     849                                On most IM-networks groupchats can be started using the /join command. (<emphasis>/join #foo</emphasis> to start a chatroom with you and <emphasis>foo</emphasis>) This doesn't work with names groupchats though (which exist on Jabber networks and AIM, for example), instead you can use this command.
     850                        </para>
     851
     852                        <para>
     853                                The first two arguments are required. <emphasis>room name</emphasis> is the name of the chatroom on the IM-network. <emphasis>channel name</emphasis> is the IRC channel name BitlBee should map this to. <emphasis>room nickname</emphasis> is the nickname you want to have in this channel. If you don't give these options, BitlBee will do the right guesses.
     854                        </para>
     855
     856                        <para>
     857                                The following command will join you to the chatroom called <emphasis>bitlbee@conference.bitlbee.org</emphasis>. The channel will be called <emphasis>&amp;bitlbee-help</emphasis> because <emphasis>&amp;bitlbee</emphasis> will already be in use. Your nickname will be <emphasis>help-me</emphasis>.
     858                        </para>
     859                </description>
     860
     861                <ircexample>
     862                        <ircline nick="wilmer">join_chat jabber bitlbee@conference.bitlbee.org &amp;bitlbee-help help-me</ircline>
     863                </ircexample>
    706864
    707865        </bitlbee-command>
  • doc/user-guide/docbook.xsl

    r875ad42 r85d7b85  
    8383
    8484        <xsl:template name="cmd">
     85                <xsl:param name="prefix"/>
    8586                <xsl:variable name="thiscmd"><xsl:value-of select="$prefix"/><xsl:value-of select="@name"/></xsl:variable>
    8687                <xsl:attribute name="id">
  • doc/user-guide/help.xsl

    r875ad42 r85d7b85  
    77        version="1.1">
    88
    9         <xsl:output method="text" encoding="iso-8859-1" standalone="yes"/>
     9        <xsl:output method="text" encoding="utf-8" standalone="yes"/>
    1010        <xsl:strip-space elements="*"/>
    1111
     
    3131
    3232        <xsl:template name="subject">
     33                <xsl:param name="id"/>
    3334                <xsl:message><xsl:text>Processing: </xsl:text><xsl:value-of select="$id"/></xsl:message>
    3435                <xsl:text>?</xsl:text><xsl:value-of select="$id"/><xsl:text>&#10;</xsl:text>
     
    5859                        <xsl:text>?set </xsl:text><xsl:value-of select="@name"/><xsl:text>&#10;</xsl:text>
    5960                        <xsl:text>_b_Type:_b_ </xsl:text><xsl:value-of select="@type"/><xsl:text>&#10;</xsl:text>
    60                         <xsl:text>_b_Default:_b_ </xsl:text><xsl:value-of select="default"/><xsl:text>&#10;</xsl:text>
     61                        <xsl:text>_b_Scope:_b_ </xsl:text><xsl:value-of select="@scope"/><xsl:text>&#10;</xsl:text>
     62                        <xsl:if test="default">
     63                                <xsl:text>_b_Default:_b_ </xsl:text><xsl:value-of select="default"/><xsl:text>&#10;</xsl:text>
     64                        </xsl:if>
    6165                        <xsl:if test="possible-values">
    6266                                <xsl:text>_b_Possible Values:_b_ </xsl:text><xsl:value-of select="possible-values"/><xsl:text>&#10;</xsl:text>
     
    119123
    120124        <xsl:template name="cmd">
     125                <xsl:param name="prefix"/>
    121126                <xsl:variable name="thiscmd"><xsl:value-of select="$prefix"/><xsl:value-of select="@name"/></xsl:variable>
    122127                <xsl:message><xsl:text>Processing command '</xsl:text><xsl:value-of select="$thiscmd"/><xsl:text>'</xsl:text></xsl:message>
  • doc/user-guide/misc.xml

    r875ad42 r85d7b85  
    4747</variablelist>
    4848
    49 <para>
    50 This list was extracted from <ulink url="http://help.msn.com/!data/en_us/data/messengerv50.its51/$content$/EMOTICONS.HTM?H_APP=">http://help.msn.com/!data/en_us/data/messengerv50.its51/$content$/EMOTICONS.HTM?H_APP=</ulink>.
    51 </para>
    52 
    5349</sect1>
    5450
     
    5652<title>Groupchats</title>
    5753<para>
    58 Since version 0.8x, BitlBee supports groupchats on the MSN and Yahoo! networks. This text will try to explain you how they work.
     54BitlBee now supports groupchats on all IM networks. This text will try to explain you how they work.
    5955</para>
    6056
     
    7369
    7470<para>
    75 If you want to start a groupchat with the person <emphasis>jim_msn</emphasis> in it, just join the channel <emphasis>#jim_msn</emphasis>. BitlBee will refuse to join you to the channel with that name, but it will create a new virtual channel with root, you and jim_msn in it.
     71If you want to start a groupchat with the person <emphasis>lisa_msn</emphasis> in it, just join the channel <emphasis>#lisa_msn</emphasis>. BitlBee will refuse to join you to the channel with that name, but it will create a new virtual channel with root, you and lisa_msn in it.
    7672</para>
    7773
     
    8177
    8278<para>
    83 This is all you'll probably need to know. If you have any problems, please read <emphasis>help groupchats3</emphasis>.
    84 </para>
    85 
    86 </sect1>
    87 
    88 <sect1 id="groupchats3">
    89 <title>Groupchat channel names</title>
    90 
    91 <para>
    92 Obviously the (numbered) channel names don't make a lot of sense. Problem is that groupchats usually don't have names at all in the IM-world, while IRC insists on a name. So BitlBee just generates something random, just don't pay attention to it. :-)
    93 </para>
    94 
    95 <para>
    96 Please also note that BitlBee doesn't support groupchats for all protocols yet. BitlBee will tell you so. Support for other protocols will hopefully come later.
     79Some protocols (like Jabber) also support named groupchats. BitlBee now supports these too. You can use the <emphasis>join_chat</emphasis> command to join them. See <emphasis>help join_chat</emphasis> for more information.
    9780</para>
    9881
     
    117100        <member>On the phone, Phone, On phone</member>
    118101        <member>Out to lunch, Lunch, Food</member>
     102        <member>Invisible, Hidden</member>
    119103</simplelist>
    120104
     
    124108
    125109<para>
    126 You can also add more information to your away message. Setting it to "Busy - Fixing BitlBee bugs" will set your IM-away-states to Busy, but your away message will be more descriptive for people on IRC. Protocols like Yahoo! and Jabber will also show this complete away message to your buddies.
     110You can also add more information to your away message. Setting it to "Busy - Fixing BitlBee bugs" will set your IM-away-states to Busy, but your away message will be more descriptive for people on IRC. Most IM-protocols can also show this additional information to your buddies.
    127111</para>
    128112
  • doc/user-guide/quickstart.xml

    r875ad42 r85d7b85  
    3434
    3535<para>
    36 For instance, suppose you have an ICQ account with UIN <emphasis>72696705</emphasis> with password <emphasis>QuickStart</emphasis>, you would:
     36For instance, suppose you have a Jabber account at jabber.org with handle <emphasis>bitlbee@jabber.org</emphasis> with password <emphasis>QuickStart</emphasis>, you would:
    3737</para>
    3838
    3939<ircexample>
    40         <ircline nick="you">account add oscar 72696705 QuickStart login.icq.com</ircline>
     40        <ircline nick="you">account add jabber bitlbee@jabber.org QuickStart</ircline>
    4141        <ircline nick="root">Account successfully added</ircline>
    4242</ircexample>
    4343
    4444<para>
    45 Other available IM protocols are jabber, msn, and yahoo. Oscar is the protocol used by ICQ and AOL. For oscar, you need to specify the IM-server as a fourth argument (for msn and yahoo there is no fourth argument). For AOL Instant Messenger, the server name is <emphasis>login.oscar.aol.com</emphasis>. For ICQ, the server name is <emphasis>login.icq.com</emphasis>.
     45Other available IM protocols are msn, oscar, and yahoo. OSCAR is the protocol used by ICQ and AOL. For more information about the <emphasis>account add</emphasis> command, see <emphasis>help account add</emphasis>.
    4646</para>
    4747
     
    6161
    6262<para>
    63 For most protocols (currently MSN, Jabber, Yahoo and AOL) BitlBee can download the contact list automatically from the IM server and all the on-line users should appear in the control channel when you log in.
     63Now BitlBee logs in and downloads the contact list from the IM server. In a few seconds, all your on-line buddies should show up in the control channel.
    6464</para>
    6565
    6666<para>
    67 BitlBee will convert names into irc-friendly form (for instance: tux@example.com will be given the nickname tux). If you have more than one person who would have the same name by this logic (for instance: tux@example.com and tux@bitlbee.org) the second one to log on will be tux_. The same is true if you have a tux log on to AOL and a tux log on from Yahoo.
     67BitlBee will convert names into IRC-friendly form (for instance: tux@example.com will be given the nickname tux). If you have more than one person who would have the same name by this logic (for instance: tux@example.com and tux@bitlbee.org) the second one to log on will be tux_. The same is true if you have a tux log on to AOL and a tux log on from Yahoo.
    6868</para>
    6969
     
    127127<ircexample>
    128128        <ircline nick="you">tux: hey, how's the weather down there?</ircline>
    129         <ircline nick="tux"> you: a bit chilly!</ircline>
     129        <ircline nick="tux">you: a bit chilly!</ircline>
    130130</ircexample>
    131131
    132132<para>
    133 If you'd rather chat with them in a separate window use the <emphasis>/msg</emphasis> or <emphasis>/query</emphasis> command, just like you would for a private message in IRC.  If you want to have messages automatically come up in private messages rather than in the &amp;bitlbee channel, use the <emphasis>set private</emphasis> command: <emphasis>set private true</emphasis> (<emphasis>set private false</emphasis> to change back).
     133Note that, although all contacts are in the &amp;bitlbee channel, only tux will actually receive this message. The &amp;bitlbee channel shouldn't be confused with a real IRC channel.
     134</para>
     135
     136<para>
     137If you prefer chatting in a separate window, use the <emphasis>/msg</emphasis> or <emphasis>/query</emphasis> command, just like on real IRC. BitlBee will remember how you talk to someone and show his/her responses the same way. If you want to change the default behaviour (for people you haven't talked to yet), see <emphasis>help set private</emphasis>.
    134138</para>
    135139
  • help.c

    r875ad42 r85d7b85  
    3131#define BUFSIZE 1100
    3232
    33 help_t *help_init( help_t **help )
     33help_t *help_init( help_t **help, const char *helpfile )
    3434{
    3535        int i, buflen = 0;
     
    4141        *help = h = g_new0 ( help_t, 1 );
    4242       
    43         h->fd = open( global.helpfile, O_RDONLY
     43        h->fd = open( helpfile, O_RDONLY
    4444#ifdef _WIN32
    4545                                  | O_BINARY
     
    7171                {
    7272                        /* FIXME: Clean up */
    73 //                      help_close( *help );
    74                         *help = NULL;
     73                        help_free( help );
    7574                        g_free( s );
    76                         return( NULL );
     75                        return NULL;
    7776                }
    7877                i = strchr( s, '\n' ) - s;
    7978               
    80                 if( h->string )
     79                if( h->title )
    8180                {
    8281                        h = h->next = g_new0( help_t, 1 );
    8382                }
    84                 h->string = g_new ( char, i );
     83                h->title = g_new ( char, i );
    8584               
    86                 strncpy( h->string, s + 1, i - 1 );
    87                 h->string[i-1] = 0;
     85                strncpy( h->title, s + 1, i - 1 );
     86                h->title[i-1] = 0;
    8887                h->fd = (*help)->fd;
    8988                h->offset.file_offset = lseek( h->fd, 0, SEEK_CUR ) - buflen + i + 1;
     
    103102}
    104103
    105 char *help_get( help_t **help, char *string )
     104void help_free( help_t **help )
     105{
     106        help_t *h, *oh;
     107        int last_fd = -1; /* Weak de-dupe */
     108       
     109        if( help == NULL || *help == NULL )
     110                return;
     111       
     112        h = *help;
     113        while( h )
     114        {
     115                if( h->fd != last_fd )
     116                {
     117                        close( h->fd );
     118                        last_fd = h->fd;
     119                }
     120                g_free( h->title );
     121                h = (oh=h)->next;
     122                g_free( oh );
     123        }
     124       
     125        *help = NULL;
     126}
     127
     128char *help_get( help_t **help, char *title )
    106129{
    107130        time_t mtime;
     
    109132        help_t *h;
    110133
    111         h=*help;       
    112 
    113         while( h )
     134        for( h = *help; h; h = h->next )
    114135        {
    115                 if( g_strcasecmp( h->string, string ) == 0 ) break;
    116                 h = h->next;
     136                if( h->title != NULL && g_strcasecmp( h->title, title ) == 0 )
     137                        break;
    117138        }
    118139        if( h && h->length > 0 )
     
    120141                char *s = g_new( char, h->length + 1 );
    121142               
    122                 if( fstat( h->fd, stat ) != 0 )
    123                 {
    124                         g_free( h );
    125                         *help = NULL;
    126                         return NULL;
    127                 }
    128                 mtime = stat->st_mtime;
    129                
    130                 if( mtime > h->mtime )
    131                         return NULL;
    132                
    133143                s[h->length] = 0;
    134144                if( h->fd >= 0 )
    135145                {
     146                        if( fstat( h->fd, stat ) != 0 )
     147                        {
     148                                g_free( s );
     149                                return NULL;
     150                        }
     151                        mtime = stat->st_mtime;
     152               
     153                        if( mtime > h->mtime )
     154                        {
     155                                g_free( s );
     156                                return NULL;
     157                        }
     158                       
    136159                        lseek( h->fd, h->offset.file_offset, SEEK_SET );
    137160                        read( h->fd, s, h->length );
  • help.h

    r875ad42 r85d7b85  
    3737        int fd;
    3838        time_t mtime;
    39         char *string;
     39        char *title;
    4040        help_off_t offset;
    4141        int length;
     
    4343} help_t;
    4444
    45 help_t *help_init( help_t **help );
    46 char *help_get( help_t **help, char *string );
     45G_GNUC_MALLOC help_t *help_init( help_t **help, const char *helpfile );
     46void help_free( help_t **help );
     47char *help_get( help_t **help, char *title );
    4748
    4849#endif
  • ipc.c

    r875ad42 r85d7b85  
    5252        if( g_strcasecmp( cmd[0], "CLIENT" ) == 0 )
    5353                ipc_to_children_str( "OPERMSG :Client connecting (PID=%d): %s@%s (%s)\r\n",
    54                                      child ? child->pid : -1, cmd[2], cmd[1], cmd[3] );
     54                                     (int) ( child ? child->pid : -1 ), cmd[2], cmd[1], cmd[3] );
    5555}
    5656
     
    6060                ipc_to_children_str( "DIE\r\n" );
    6161       
    62         bitlbee_shutdown( NULL );
     62        bitlbee_shutdown( NULL, -1, 0 );
    6363}
    6464
     
    9191       
    9292        global.restart = -1;
    93         bitlbee_shutdown( NULL );
     93        bitlbee_shutdown( NULL, -1, 0 );
    9494}
    9595
     
    9999        { "die",        0, ipc_master_cmd_die,        0 },
    100100        { "wallops",    1, NULL,                      IPC_CMD_TO_CHILDREN },
    101         { "lilo",       1, NULL,                      IPC_CMD_TO_CHILDREN },
     101        { "wall",       1, NULL,                      IPC_CMD_TO_CHILDREN },
    102102        { "opermsg",    1, NULL,                      IPC_CMD_TO_CHILDREN },
    103103        { "rehash",     0, ipc_master_cmd_rehash,     0 },
     
    115115static void ipc_child_cmd_wallops( irc_t *irc, char **cmd )
    116116{
    117         if( irc->status < USTATUS_LOGGED_IN )
     117        if( !( irc->status & USTATUS_LOGGED_IN ) )
    118118                return;
    119119       
     
    122122}
    123123
    124 static void ipc_child_cmd_lilo( irc_t *irc, char **cmd )
    125 {
    126         if( irc->status < USTATUS_LOGGED_IN )
     124static void ipc_child_cmd_wall( irc_t *irc, char **cmd )
     125{
     126        if( !( irc->status & USTATUS_LOGGED_IN ) )
    127127                return;
    128128       
     
    133133static void ipc_child_cmd_opermsg( irc_t *irc, char **cmd )
    134134{
    135         if( irc->status < USTATUS_LOGGED_IN )
     135        if( !( irc->status & USTATUS_LOGGED_IN ) )
    136136                return;
    137137       
     
    154154static void ipc_child_cmd_kill( irc_t *irc, char **cmd )
    155155{
    156         if( irc->status < USTATUS_LOGGED_IN )
     156        if( !( irc->status & USTATUS_LOGGED_IN ) )
    157157                return;
    158158       
     
    166166static void ipc_child_cmd_hello( irc_t *irc, char **cmd )
    167167{
    168         if( irc->status < USTATUS_LOGGED_IN )
     168        if( !( irc->status & USTATUS_LOGGED_IN ) )
    169169                ipc_to_master_str( "HELLO\r\n" );
    170170        else
     
    175175        { "die",        0, ipc_child_cmd_die,         0 },
    176176        { "wallops",    1, ipc_child_cmd_wallops,     0 },
    177         { "lilo",       1, ipc_child_cmd_lilo,        0 },
     177        { "wall",       1, ipc_child_cmd_wall,        0 },
    178178        { "opermsg",    1, ipc_child_cmd_opermsg,     0 },
    179179        { "rehash",     0, ipc_child_cmd_rehash,      0 },
     
    246246}
    247247
    248 void ipc_master_read( gpointer data, gint source, GaimInputCondition cond )
     248gboolean ipc_master_read( gpointer data, gint source, b_input_condition cond )
    249249{
    250250        char *buf, **cmd;
     
    258258        else
    259259        {
     260                ipc_master_free_fd( source );
     261        }
     262       
     263        return TRUE;
     264}
     265
     266gboolean ipc_child_read( gpointer data, gint source, b_input_condition cond )
     267{
     268        char *buf, **cmd;
     269       
     270        if( ( buf = ipc_readline( source ) ) )
     271        {
     272                cmd = irc_parse_line( buf );
     273                if( cmd )
     274                        ipc_command_exec( data, cmd, ipc_child_commands );
     275        }
     276        else
     277        {
     278                ipc_child_disable();
     279        }
     280       
     281        return TRUE;
     282}
     283
     284void ipc_to_master( char **cmd )
     285{
     286        if( global.conf->runmode == RUNMODE_FORKDAEMON )
     287        {
     288                char *s = irc_build_line( cmd );
     289                ipc_to_master_str( "%s", s );
     290                g_free( s );
     291        }
     292        else if( global.conf->runmode == RUNMODE_DAEMON )
     293        {
     294                ipc_command_exec( NULL, cmd, ipc_master_commands );
     295        }
     296}
     297
     298void ipc_to_master_str( char *format, ... )
     299{
     300        char *msg_buf;
     301        va_list params;
     302
     303        va_start( params, format );
     304        msg_buf = g_strdup_vprintf( format, params );
     305        va_end( params );
     306       
     307        if( strlen( msg_buf ) > 512 )
     308        {
     309                /* Don't send it, it's too long... */
     310        }
     311        else if( global.conf->runmode == RUNMODE_FORKDAEMON )
     312        {
     313                if( global.listen_socket >= 0 )
     314                        if( write( global.listen_socket, msg_buf, strlen( msg_buf ) ) <= 0 )
     315                                ipc_child_disable();
     316        }
     317        else if( global.conf->runmode == RUNMODE_DAEMON )
     318        {
     319                char **cmd, *s;
     320               
     321                if( ( s = strchr( msg_buf, '\r' ) ) )
     322                        *s = 0;
     323               
     324                cmd = irc_parse_line( msg_buf );
     325                ipc_command_exec( NULL, cmd, ipc_master_commands );
     326                g_free( cmd );
     327        }
     328       
     329        g_free( msg_buf );
     330}
     331
     332void ipc_to_children( char **cmd )
     333{
     334        if( global.conf->runmode == RUNMODE_FORKDAEMON )
     335        {
     336                char *msg_buf = irc_build_line( cmd );
     337                ipc_to_children_str( "%s", msg_buf );
     338                g_free( msg_buf );
     339        }
     340        else if( global.conf->runmode == RUNMODE_DAEMON )
     341        {
    260342                GSList *l;
    261                 struct bitlbee_child *c;
    262                
    263                 for( l = child_list; l; l = l->next )
     343               
     344                for( l = irc_connection_list; l; l = l->next )
     345                        ipc_command_exec( l->data, cmd, ipc_child_commands );
     346        }
     347}
     348
     349void ipc_to_children_str( char *format, ... )
     350{
     351        char *msg_buf;
     352        va_list params;
     353
     354        va_start( params, format );
     355        msg_buf = g_strdup_vprintf( format, params );
     356        va_end( params );
     357       
     358        if( strlen( msg_buf ) > 512 )
     359        {
     360                /* Don't send it, it's too long... */
     361        }
     362        else if( global.conf->runmode == RUNMODE_FORKDAEMON )
     363        {
     364                int msg_len = strlen( msg_buf );
     365                GSList *l, *next;
     366               
     367                for( l = child_list; l; l = next )
    264368                {
    265                         c = l->data;
    266                         if( c->ipc_fd == source )
     369                        struct bitlbee_child *c = l->data;
     370                       
     371                        next = l->next;
     372                        if( write( c->ipc_fd, msg_buf, msg_len ) <= 0 )
    267373                        {
    268374                                ipc_master_free_one( c );
    269375                                child_list = g_slist_remove( child_list, c );
    270                                 break;
    271376                        }
    272                 }
    273         }
    274 }
    275 
    276 void ipc_child_read( gpointer data, gint source, GaimInputCondition cond )
    277 {
    278         char *buf, **cmd;
    279        
    280         if( ( buf = ipc_readline( source ) ) )
    281         {
    282                 cmd = irc_parse_line( buf );
    283                 if( cmd )
    284                         ipc_command_exec( data, cmd, ipc_child_commands );
    285         }
    286         else
    287         {
    288                 gaim_input_remove( global.listen_watch_source_id );
    289                 close( global.listen_socket );
    290                
    291                 global.listen_socket = -1;
    292         }
    293 }
    294 
    295 void ipc_to_master( char **cmd )
    296 {
    297         if( global.conf->runmode == RUNMODE_FORKDAEMON )
    298         {
    299                 char *s = irc_build_line( cmd );
    300                 ipc_to_master_str( "%s", s );
    301                 g_free( s );
    302         }
    303         else if( global.conf->runmode == RUNMODE_DAEMON )
    304         {
    305                 ipc_command_exec( NULL, cmd, ipc_master_commands );
    306         }
    307 }
    308 
    309 void ipc_to_master_str( char *format, ... )
    310 {
    311         char *msg_buf;
    312         va_list params;
    313 
    314         va_start( params, format );
    315         msg_buf = g_strdup_vprintf( format, params );
    316         va_end( params );
    317        
    318         if( strlen( msg_buf ) > 512 )
    319         {
    320                 /* Don't send it, it's too long... */
    321         }
    322         else if( global.conf->runmode == RUNMODE_FORKDAEMON )
    323         {
    324                 write( global.listen_socket, msg_buf, strlen( msg_buf ) );
    325         }
    326         else if( global.conf->runmode == RUNMODE_DAEMON )
    327         {
    328                 char **cmd, *s;
    329                
    330                 if( ( s = strchr( msg_buf, '\r' ) ) )
    331                         *s = 0;
    332                
    333                 cmd = irc_parse_line( msg_buf );
    334                 ipc_command_exec( NULL, cmd, ipc_master_commands );
    335                 g_free( cmd );
    336         }
    337        
    338         g_free( msg_buf );
    339 }
    340 
    341 void ipc_to_children( char **cmd )
    342 {
    343         if( global.conf->runmode == RUNMODE_FORKDAEMON )
    344         {
    345                 char *msg_buf = irc_build_line( cmd );
    346                 ipc_to_children_str( "%s", msg_buf );
    347                 g_free( msg_buf );
    348         }
    349         else if( global.conf->runmode == RUNMODE_DAEMON )
    350         {
    351                 GSList *l;
    352                
    353                 for( l = irc_connection_list; l; l = l->next )
    354                         ipc_command_exec( l->data, cmd, ipc_child_commands );
    355         }
    356 }
    357 
    358 void ipc_to_children_str( char *format, ... )
    359 {
    360         char *msg_buf;
    361         va_list params;
    362 
    363         va_start( params, format );
    364         msg_buf = g_strdup_vprintf( format, params );
    365         va_end( params );
    366        
    367         if( strlen( msg_buf ) > 512 )
    368         {
    369                 /* Don't send it, it's too long... */
    370         }
    371         else if( global.conf->runmode == RUNMODE_FORKDAEMON )
    372         {
    373                 int msg_len = strlen( msg_buf );
    374                 GSList *l;
    375                
    376                 for( l = child_list; l; l = l->next )
    377                 {
    378                         struct bitlbee_child *c = l->data;
    379                         write( c->ipc_fd, msg_buf, msg_len );
    380377                }
    381378        }
     
    397394void ipc_master_free_one( struct bitlbee_child *c )
    398395{
    399         gaim_input_remove( c->ipc_inpa );
     396        b_event_remove( c->ipc_inpa );
    400397        closesocket( c->ipc_fd );
    401398       
     
    406403}
    407404
     405void ipc_master_free_fd( int fd )
     406{
     407        GSList *l;
     408        struct bitlbee_child *c;
     409       
     410        for( l = child_list; l; l = l->next )
     411        {
     412                c = l->data;
     413                if( c->ipc_fd == fd )
     414                {
     415                        ipc_master_free_one( c );
     416                        child_list = g_slist_remove( child_list, c );
     417                        break;
     418                }
     419        }
     420}
     421
    408422void ipc_master_free_all()
    409423{
     
    415429        g_slist_free( child_list );
    416430        child_list = NULL;
     431}
     432
     433void ipc_child_disable()
     434{
     435        b_event_remove( global.listen_watch_source_id );
     436        close( global.listen_socket );
     437       
     438        global.listen_socket = -1;
    417439}
    418440
     
    443465       
    444466        for( l = child_list; l; l = l->next )
    445                 fprintf( fp, "%d %d\n", ((struct bitlbee_child*)l->data)->pid,
     467                fprintf( fp, "%d %d\n", (int) ((struct bitlbee_child*)l->data)->pid,
    446468                                        ((struct bitlbee_child*)l->data)->ipc_fd );
    447469       
     
    464486
    465487
    466 static gboolean new_ipc_client (GIOChannel *gio, GIOCondition cond, gpointer data)
     488static gboolean new_ipc_client( gpointer data, gint serversock, b_input_condition cond )
    467489{
    468490        struct bitlbee_child *child = g_new0( struct bitlbee_child, 1 );
    469         int serversock;
    470 
    471         serversock = g_io_channel_unix_get_fd(gio);
    472 
    473         child->ipc_fd = accept(serversock, NULL, 0);
    474 
    475         if (child->ipc_fd == -1) {
     491       
     492        child->ipc_fd = accept( serversock, NULL, 0 );
     493       
     494        if( child->ipc_fd == -1 )
     495        {
    476496                log_message( LOGLVL_WARNING, "Unable to accept connection on UNIX domain socket: %s", strerror(errno) );
    477497                return TRUE;
    478498        }
    479499               
    480         child->ipc_inpa = gaim_input_add( child->ipc_fd, GAIM_INPUT_READ, ipc_master_read, child );
    481                
     500        child->ipc_inpa = b_input_add( child->ipc_fd, GAIM_INPUT_READ, ipc_master_read, child );
     501       
    482502        child_list = g_slist_append( child_list, child );
    483 
     503       
    484504        return TRUE;
    485505}
     
    489509        struct sockaddr_un un_addr;
    490510        int serversock;
    491         GIOChannel *gio;
    492511
    493512        /* Clean up old socket files that were hanging around.. */
     
    517536        }
    518537       
    519         gio = g_io_channel_unix_new(serversock);
    520        
    521         if (gio == NULL) {
    522                 log_message( LOGLVL_WARNING, "Unable to create IO channel for unix socket" );
    523                 return 0;
    524         }
    525 
    526         g_io_add_watch(gio, G_IO_IN, new_ipc_client, NULL);
     538        b_input_add( serversock, GAIM_INPUT_READ, new_ipc_client, NULL );
     539       
    527540        return 1;
    528541}
     
    560573                child = g_new0( struct bitlbee_child, 1 );
    561574               
    562                 if( fscanf( fp, "%d %d", &child->pid, &child->ipc_fd ) != 2 )
     575                if( fscanf( fp, "%d %d", (int *) &child->pid, &child->ipc_fd ) != 2 )
    563576                {
    564577                        log_message( LOGLVL_WARNING, "Unexpected end of file: Only processed %d clients.", i );
     
    567580                        return 0;
    568581                }
    569                 child->ipc_inpa = gaim_input_add( child->ipc_fd, GAIM_INPUT_READ, ipc_master_read, child );
     582                child->ipc_inpa = b_input_add( child->ipc_fd, GAIM_INPUT_READ, ipc_master_read, child );
    570583               
    571584                child_list = g_slist_append( child_list, child );
  • ipc.h

    r875ad42 r85d7b85  
    4040
    4141
    42 void ipc_master_read( gpointer data, gint source, GaimInputCondition cond );
    43 void ipc_child_read( gpointer data, gint source, GaimInputCondition cond );
     42gboolean ipc_master_read( gpointer data, gint source, b_input_condition cond );
     43gboolean ipc_child_read( gpointer data, gint source, b_input_condition cond );
    4444
    4545void ipc_master_free_one( struct bitlbee_child *child );
     46void ipc_master_free_fd( int fd );
    4647void ipc_master_free_all();
     48
     49void ipc_child_disable();
    4750
    4851void ipc_to_master( char **cmd );
  • irc.c

    r875ad42 r85d7b85  
    2929#include "ipc.h"
    3030
    31 static gboolean irc_userping( gpointer _irc );
     31static gboolean irc_userping( gpointer _irc, int fd, b_input_condition cond );
    3232
    3333GSList *irc_connection_list = NULL;
    3434
    35 static char *passchange (irc_t *irc, void *set, char *value)
    36 {
    37         irc_setpass (irc, value);
    38         return (NULL);
     35static char *passchange( set_t *set, char *value )
     36{
     37        irc_t *irc = set->data;
     38       
     39        irc_setpass( irc, value );
     40        irc_usermsg( irc, "Password successfully changed" );
     41        return NULL;
     42}
     43
     44static char *set_eval_charset( set_t *set, char *value )
     45{
     46        irc_t *irc = set->data;
     47        GIConv ic, oc;
     48
     49        if( g_strcasecmp( value, "none" ) == 0 )
     50                value = g_strdup( "utf-8" );
     51
     52        if( ( ic = g_iconv_open( "utf-8", value ) ) == (GIConv) -1 )
     53        {
     54                return NULL;
     55        }
     56        if( ( oc = g_iconv_open( value, "utf-8" ) ) == (GIConv) -1 )
     57        {
     58                g_iconv_close( ic );
     59                return NULL;
     60        }
     61       
     62        if( irc->iconv != (GIConv) -1 )
     63                g_iconv_close( irc->iconv );
     64        if( irc->oconv != (GIConv) -1 )
     65                g_iconv_close( irc->oconv );
     66       
     67        irc->iconv = ic;
     68        irc->oconv = oc;
     69
     70        return value;
    3971}
    4072
     
    4274{
    4375        irc_t *irc;
    44         struct hostent *peer;
    45         unsigned int i;
    46         char buf[128];
    47 #ifdef IPV6
    48         struct sockaddr_in6 sock[1];
    49 #else
    50         struct sockaddr_in sock[1];
    51 #endif
     76        struct sockaddr_storage sock;
     77        socklen_t socklen = sizeof( sock );
    5278       
    5379        irc = g_new0( irc_t, 1 );
    5480       
    5581        irc->fd = fd;
    56         irc->io_channel = g_io_channel_unix_new( fd );
    57 #ifdef GLIB2
    58         g_io_channel_set_encoding (irc->io_channel, NULL, NULL);
    59         g_io_channel_set_buffered (irc->io_channel, FALSE);
    60         g_io_channel_set_flags( irc->io_channel, G_IO_FLAG_NONBLOCK, NULL );
    61 #else
    62         fcntl( irc->fd, F_SETFL, O_NONBLOCK);
    63 #endif
    64         irc->r_watch_source_id = g_io_add_watch( irc->io_channel, G_IO_IN | G_IO_ERR | G_IO_HUP, bitlbee_io_current_client_read, irc );
     82        sock_make_nonblocking( irc->fd );
     83       
     84        irc->r_watch_source_id = b_input_add( irc->fd, GAIM_INPUT_READ, bitlbee_io_current_client_read, irc );
    6585       
    6686        irc->status = USTATUS_OFFLINE;
     
    7494        irc->channel = g_strdup( ROOT_CHAN );
    7595       
    76         i = sizeof( *sock );
     96        irc->iconv = (GIConv) -1;
     97        irc->oconv = (GIConv) -1;
    7798       
    7899        if( global.conf->hostname )
     100        {
    79101                irc->myhost = g_strdup( global.conf->hostname );
    80 #ifdef IPV6
    81         else if( getsockname( irc->fd, (struct sockaddr*) sock, &i ) == 0 && sock->sin6_family == AF_INETx )
    82         {
    83                 if( ( peer = gethostbyaddr( (char*) &sock->sin6_addr, sizeof( sock->sin6_addr ), AF_INETx ) ) )
    84                         irc->myhost = g_strdup( peer->h_name );
    85                 else if( inet_ntop( AF_INETx, &sock->sin6_addr, buf, sizeof( buf ) - 1 ) != NULL )
     102        }
     103        else if( getsockname( irc->fd, (struct sockaddr*) &sock, &socklen ) == 0 )
     104        {
     105                char buf[NI_MAXHOST+1];
     106
     107                if( getnameinfo( (struct sockaddr *) &sock, socklen, buf,
     108                                 NI_MAXHOST, NULL, 0, 0 ) == 0 )
     109                {
    86110                        irc->myhost = g_strdup( ipv6_unwrap( buf ) );
    87         }
    88 #else
    89         else if( getsockname( irc->fd, (struct sockaddr*) sock, &i ) == 0 && sock->sin_family == AF_INETx )
    90         {
    91                 if( ( peer = gethostbyaddr( (char*) &sock->sin_addr, sizeof( sock->sin_addr ), AF_INETx ) ) )
    92                         irc->myhost = g_strdup( peer->h_name );
    93                 else if( inet_ntop( AF_INETx, &sock->sin_addr, buf, sizeof( buf ) - 1 ) != NULL )
    94                         irc->myhost = g_strdup( buf );
    95         }
    96 #endif
    97        
    98         i = sizeof( *sock );
    99 #ifdef IPV6
    100         if( getpeername( irc->fd, (struct sockaddr*) sock, &i ) == 0 && sock->sin6_family == AF_INETx )
    101         {
    102                 if( ( peer = gethostbyaddr( (char*) &sock->sin6_addr, sizeof( sock->sin6_addr ), AF_INETx ) ) )
    103                         irc->host = g_strdup( peer->h_name );
    104                 else if( inet_ntop( AF_INETx, &sock->sin6_addr, buf, sizeof( buf ) - 1 ) != NULL )
     111                }
     112        }
     113       
     114        if( getpeername( irc->fd, (struct sockaddr*) &sock, &socklen ) == 0 )
     115        {
     116                char buf[NI_MAXHOST+1];
     117
     118                if( getnameinfo( (struct sockaddr *)&sock, socklen, buf,
     119                                 NI_MAXHOST, NULL, 0, 0 ) == 0 )
     120                {
    105121                        irc->host = g_strdup( ipv6_unwrap( buf ) );
    106         }
    107 #else
    108         if( getpeername( irc->fd, (struct sockaddr*) sock, &i ) == 0 && sock->sin_family == AF_INETx )
    109         {
    110                 if( ( peer = gethostbyaddr( (char*) &sock->sin_addr, sizeof( sock->sin_addr ), AF_INETx ) ) )
    111                         irc->host = g_strdup( peer->h_name );
    112                 else if( inet_ntop( AF_INETx, &sock->sin_addr, buf, sizeof( buf ) - 1 ) != NULL )
    113                         irc->host = g_strdup( buf );
    114         }
    115 #endif
    116        
    117         /* Rare, but possible. */
    118         if( !irc->host ) irc->host = g_strdup( "localhost." );
    119         if( !irc->myhost ) irc->myhost = g_strdup( "localhost." );
    120 
     122                }
     123        }
     124       
     125        if( irc->host == NULL )
     126                irc->host = g_strdup( "localhost.localdomain" );
     127        if( irc->myhost == NULL )
     128                irc->myhost = g_strdup( "localhost.localdomain" );
     129       
    121130        if( global.conf->ping_interval > 0 && global.conf->ping_timeout > 0 )
    122                 irc->ping_source_id = g_timeout_add( global.conf->ping_interval * 1000, irc_userping, irc );
     131                irc->ping_source_id = b_timeout_add( global.conf->ping_interval * 1000, irc_userping, irc );
    123132       
    124133        irc_write( irc, ":%s NOTICE AUTH :%s", irc->myhost, "BitlBee-IRCd initialized, please go on" );
     
    126135        irc_connection_list = g_slist_append( irc_connection_list, irc );
    127136       
    128         set_add( irc, "away_devoice", "true",  set_eval_away_devoice );
    129         set_add( irc, "auto_connect", "true", set_eval_bool );
    130         set_add( irc, "auto_reconnect", "false", set_eval_bool );
    131         set_add( irc, "auto_reconnect_delay", "300", set_eval_int );
    132         set_add( irc, "buddy_sendbuffer", "false", set_eval_bool );
    133         set_add( irc, "buddy_sendbuffer_delay", "200", set_eval_int );
    134         set_add( irc, "charset", "iso8859-1", set_eval_charset );
    135         set_add( irc, "debug", "false", set_eval_bool );
    136         set_add( irc, "default_target", "root", NULL );
    137         set_add( irc, "display_namechanges", "false", set_eval_bool );
    138         set_add( irc, "handle_unknown", "root", NULL );
    139         set_add( irc, "lcnicks", "true", set_eval_bool );
    140         set_add( irc, "ops", "both", set_eval_ops );
    141         set_add( irc, "private", "true", set_eval_bool );
    142         set_add( irc, "query_order", "lifo", NULL );
    143         set_add( irc, "save_on_quit", "true", set_eval_bool );
    144         set_add( irc, "strip_html", "true", NULL );
    145         set_add( irc, "to_char", ": ", set_eval_to_char );
    146         set_add( irc, "typing_notice", "false", set_eval_bool );
    147         set_add( irc, "password", NULL, passchange);
     137        set_add( &irc->set, "away_devoice", "true",  set_eval_away_devoice, irc );
     138        set_add( &irc->set, "auto_connect", "true", set_eval_bool, irc );
     139        set_add( &irc->set, "auto_reconnect", "false", set_eval_bool, irc );
     140        set_add( &irc->set, "auto_reconnect_delay", "300", set_eval_int, irc );
     141        set_add( &irc->set, "buddy_sendbuffer", "false", set_eval_bool, irc );
     142        set_add( &irc->set, "buddy_sendbuffer_delay", "200", set_eval_int, irc );
     143        set_add( &irc->set, "charset", "utf-8", set_eval_charset, irc );
     144        set_add( &irc->set, "debug", "false", set_eval_bool, irc );
     145        set_add( &irc->set, "default_target", "root", NULL, irc );
     146        set_add( &irc->set, "display_namechanges", "false", set_eval_bool, irc );
     147        set_add( &irc->set, "handle_unknown", "root", NULL, irc );
     148        set_add( &irc->set, "lcnicks", "true", set_eval_bool, irc );
     149        set_add( &irc->set, "ops", "both", set_eval_ops, irc );
     150        set_add( &irc->set, "password", NULL, passchange, irc );
     151        set_add( &irc->set, "private", "true", set_eval_bool, irc );
     152        set_add( &irc->set, "query_order", "lifo", NULL, irc );
     153        set_add( &irc->set, "save_on_quit", "true", set_eval_bool, irc );
     154        set_add( &irc->set, "simulate_netsplit", "true", set_eval_bool, irc );
     155        set_add( &irc->set, "strip_html", "true", NULL, irc );
     156        set_add( &irc->set, "to_char", ": ", set_eval_to_char, irc );
     157        set_add( &irc->set, "typing_notice", "false", set_eval_bool, irc );
    148158       
    149159        conf_loaddefaults( irc );
     160       
     161        /* Evaluator sets the iconv/oconv structures. */
     162        set_eval_charset( set_find( &irc->set, "charset" ), set_getstr( &irc->set, "charset" ) );
    150163       
    151164        return( irc );
     
    183196        }
    184197       
    185         irc->status = USTATUS_SHUTDOWN;
     198        irc->status |= USTATUS_SHUTDOWN;
    186199        if( irc->sendbuffer && !immed )
    187200        {
     
    190203                   bitlbee_.._write doesn't do it first. */
    191204               
    192                 g_source_remove( irc->r_watch_source_id );
    193                 irc->r_watch_source_id = g_timeout_add_full( G_PRIORITY_HIGH, 1000, (GSourceFunc) irc_free, irc, NULL );
     205                b_event_remove( irc->r_watch_source_id );
     206                irc->r_watch_source_id = b_timeout_add( 1000, (b_event_handler) irc_free, irc );
    194207        }
    195208        else
     
    207220
    208221/* Because we have no garbage collection, this is quite annoying */
    209 void irc_free(irc_t * irc)
    210 {
    211         account_t *account, *accounttmp;
     222void irc_free( irc_t * irc )
     223{
    212224        user_t *user, *usertmp;
    213         nick_t *nick, *nicktmp;
    214         help_t *helpnode, *helpnodetmp;
    215         set_t *setnode, *setnodetmp;
    216225       
    217226        log_message( LOGLVL_INFO, "Destroying connection with fd %d", irc->fd );
    218227       
    219         if( irc->status >= USTATUS_IDENTIFIED && set_getint( irc, "save_on_quit" ) )
     228        if( irc->status & USTATUS_IDENTIFIED && set_getbool( &irc->set, "save_on_quit" ) )
    220229                if( storage_save( irc, TRUE ) != STORAGE_OK )
    221230                        irc_usermsg( irc, "Error while saving settings!" );
    222231       
    223         closesocket( irc->fd );
    224        
    225         if( irc->ping_source_id > 0 )
    226                 g_source_remove( irc->ping_source_id );
    227         g_source_remove( irc->r_watch_source_id );
    228         if( irc->w_watch_source_id > 0 )
    229                 g_source_remove( irc->w_watch_source_id );
    230        
    231         g_io_channel_unref( irc->io_channel );
    232232        irc_connection_list = g_slist_remove( irc_connection_list, irc );
    233233       
    234         for (account = irc->accounts; account; account = account->next) {
    235                 if (account->gc) {
    236                         account->gc->wants_to_die = TRUE;
    237                         signoff(account->gc);
    238                 } else if (account->reconnect) {
    239                         cancel_auto_reconnect(account);
    240                 }
    241         }
    242        
    243         g_free(irc->sendbuffer);
    244         g_free(irc->readbuffer);
    245        
    246         g_free(irc->nick);
    247         g_free(irc->user);
    248         g_free(irc->host);
    249         g_free(irc->realname);
    250         g_free(irc->password);
    251        
    252         g_free(irc->myhost);
    253         g_free(irc->mynick);
    254        
    255         g_free(irc->channel);
    256        
    257         while (irc->queries != NULL)
    258                 query_del(irc, irc->queries);
    259        
    260         if (irc->accounts != NULL) {
    261                 account = irc->accounts;
    262                 while (account != NULL) {
    263                         g_free(account->user);
    264                         g_free(account->pass);
    265                         g_free(account->server);
    266                         accounttmp = account;
    267                         account = account->next;
    268                         g_free(accounttmp);
    269                 }
    270         }
    271        
    272         if (irc->users != NULL) {
     234        while( irc->accounts )
     235        {
     236                if( irc->accounts->ic )
     237                        imc_logout( irc->accounts->ic, FALSE );
     238                else if( irc->accounts->reconnect )
     239                        cancel_auto_reconnect( irc->accounts );
     240               
     241                if( irc->accounts->ic == NULL )
     242                        account_del( irc, irc->accounts );
     243                else
     244                        /* Nasty hack, but account_del() doesn't work in this
     245                           case and we don't want infinite loops, do we? ;-) */
     246                        irc->accounts = irc->accounts->next;
     247        }
     248       
     249        while( irc->queries != NULL )
     250                query_del( irc, irc->queries );
     251       
     252        while( irc->set )
     253                set_del( &irc->set, irc->set->key );
     254       
     255        if (irc->users != NULL)
     256        {
    273257                user = irc->users;
    274                 while (user != NULL) {
    275                         g_free(user->nick);
    276                         g_free(user->away);
    277                         g_free(user->handle);
    278                         if(user->user!=user->nick) g_free(user->user);
    279                         if(user->host!=user->nick) g_free(user->host);
    280                         if(user->realname!=user->nick) g_free(user->realname);
    281                         gaim_input_remove(user->sendbuf_timer);
     258                while( user != NULL )
     259                {
     260                        g_free( user->nick );
     261                        g_free( user->away );
     262                        g_free( user->handle );
     263                        if( user->user != user->nick ) g_free( user->user );
     264                        if( user->host != user->nick ) g_free( user->host );
     265                        if( user->realname != user->nick ) g_free( user->realname );
     266                        b_event_remove( user->sendbuf_timer );
    282267                                       
    283268                        usertmp = user;
    284269                        user = user->next;
    285                         g_free(usertmp);
    286                 }
    287         }
    288        
    289         g_hash_table_foreach_remove(irc->userhash, irc_free_hashkey, NULL);
    290         g_hash_table_destroy(irc->userhash);
    291        
    292         g_hash_table_foreach_remove(irc->watches, irc_free_hashkey, NULL);
    293         g_hash_table_destroy(irc->watches);
    294        
    295         if (irc->nicks != NULL) {
    296                 nick = irc->nicks;
    297                 while (nick != NULL) {
    298                         g_free(nick->nick);
    299                         g_free(nick->handle);
    300                                        
    301                         nicktmp = nick;
    302                         nick = nick->next;
    303                         g_free(nicktmp);
    304                 }
    305         }
    306         if (irc->help != NULL) {
    307                 helpnode = irc->help;
    308                 while (helpnode != NULL) {
    309                         g_free(helpnode->string);
    310                        
    311                         helpnodetmp = helpnode;
    312                         helpnode = helpnode->next;
    313                         g_free(helpnodetmp);
    314                 }
    315         }
    316         if (irc->set != NULL) {
    317                 setnode = irc->set;
    318                 while (setnode != NULL) {
    319                         g_free(setnode->key);
    320                         g_free(setnode->def);
    321                         g_free(setnode->value);
    322                        
    323                         setnodetmp = setnode;
    324                         setnode = setnode->next;
    325                         g_free(setnodetmp);
    326                 }
    327         }
    328         g_free(irc);
     270                        g_free( usertmp );
     271                }
     272        }
     273       
     274        if( irc->ping_source_id > 0 )
     275                b_event_remove( irc->ping_source_id );
     276        b_event_remove( irc->r_watch_source_id );
     277        if( irc->w_watch_source_id > 0 )
     278                b_event_remove( irc->w_watch_source_id );
     279       
     280        closesocket( irc->fd );
     281        irc->fd = -1;
     282       
     283        g_hash_table_foreach_remove( irc->userhash, irc_free_hashkey, NULL );
     284        g_hash_table_destroy( irc->userhash );
     285       
     286        g_hash_table_foreach_remove( irc->watches, irc_free_hashkey, NULL );
     287        g_hash_table_destroy( irc->watches );
     288       
     289        if( irc->iconv != (GIConv) -1 )
     290                g_iconv_close( irc->iconv );
     291        if( irc->oconv != (GIConv) -1 )
     292                g_iconv_close( irc->oconv );
     293       
     294        g_free( irc->sendbuffer );
     295        g_free( irc->readbuffer );
     296       
     297        g_free( irc->nick );
     298        g_free( irc->user );
     299        g_free( irc->host );
     300        g_free( irc->realname );
     301        g_free( irc->password );
     302       
     303        g_free( irc->myhost );
     304        g_free( irc->mynick );
     305       
     306        g_free( irc->channel );
     307       
     308        g_free( irc->last_target );
     309       
     310        g_free( irc );
    329311       
    330312        if( global.conf->runmode == RUNMODE_INETD || global.conf->runmode == RUNMODE_FORKDAEMON )
    331                 g_main_quit( global.loop );
     313                b_main_quit();
    332314}
    333315
     
    336318void irc_setpass (irc_t *irc, const char *pass)
    337319{
    338         if (irc->password) g_free (irc->password);
     320        g_free (irc->password);
    339321       
    340322        if (pass) {
    341323                irc->password = g_strdup (pass);
    342                 irc_usermsg (irc, "Password successfully changed");
    343324        } else {
    344325                irc->password = NULL;
     
    348329void irc_process( irc_t *irc )
    349330{
    350         char **lines, *temp, **cmd, *cs;
     331        char **lines, *temp, **cmd;
    351332        int i;
    352333
     
    357338                for( i = 0; *lines[i] != '\0'; i ++ )
    358339                {
    359                         char conv[IRC_MAX_LINE+1];
     340                        char *conv = NULL;
    360341                       
    361                         /* [WvG] Because irc_tokenize splits at every newline, the lines[] list
    362                             should end with an empty string. This is why this actually works.
    363                             Took me a while to figure out, Maurits. :-P */
     342                        /* [WvG] If the last line isn't empty, it's an incomplete line and we
     343                           should wait for the rest to come in before processing it. */
    364344                        if( lines[i+1] == NULL )
    365345                        {
     
    371351                        }
    372352                       
    373                         if( ( cs = set_getstr( irc, "charset" ) ) && ( g_strcasecmp( cs, "utf-8" ) != 0 ) )
    374                         {
    375                                 conv[IRC_MAX_LINE] = 0;
    376                                 if( do_iconv( cs, "UTF-8", lines[i], conv, 0, IRC_MAX_LINE - 2 ) != -1 )
    377                                         lines[i] = conv;
     353                        if( irc->iconv != (GIConv) -1 )
     354                        {
     355                                gsize bytes_read, bytes_written;
     356                               
     357                                conv = g_convert_with_iconv( lines[i], -1, irc->iconv,
     358                                                             &bytes_read, &bytes_written, NULL );
     359                               
     360                                if( conv == NULL || bytes_read != strlen( lines[i] ) )
     361                                {
     362                                        /* GLib can do strange things if things are not in the expected charset,
     363                                           so let's be a little bit paranoid here: */
     364                                        if( irc->status & USTATUS_LOGGED_IN )
     365                                        {
     366                                                irc_usermsg( irc, "Error: Charset mismatch detected. The charset "
     367                                                                  "setting is currently set to %s, so please make "
     368                                                                  "sure your IRC client will send and accept text in "
     369                                                                  "that charset, or tell BitlBee which charset to "
     370                                                                  "expect by changing the charset setting. See "
     371                                                                  "`help set charset' for more information. Your "
     372                                                                  "message was ignored.",
     373                                                                  set_getstr( &irc->set, "charset" ) );
     374                                               
     375                                                g_free( conv );
     376                                                conv = NULL;
     377                                        }
     378                                        else
     379                                        {
     380                                                irc_write( irc, ":%s NOTICE AUTH :%s", irc->myhost,
     381                                                           "Warning: invalid characters received at login time." );
     382                                               
     383                                                conv = g_strdup( lines[i] );
     384                                                for( temp = conv; *temp; temp ++ )
     385                                                        if( *temp & 0x80 )
     386                                                                *temp = '?';
     387                                        }
     388                                }
     389                                lines[i] = conv;
    378390                        }
    379391                       
    380                         if( ( cmd = irc_parse_line( lines[i] ) ) == NULL )
    381                                 continue;
    382                         irc_exec( irc, cmd );
     392                        if( lines[i] )
     393                        {
     394                                if( ( cmd = irc_parse_line( lines[i] ) ) == NULL )
     395                                        continue;
     396                                irc_exec( irc, cmd );
     397                                g_free( cmd );
     398                        }
    383399                       
    384                         g_free( cmd );
     400                        g_free( conv );
    385401                       
    386402                        /* Shouldn't really happen, but just in case... */
     
    406422char **irc_tokenize( char *buffer )
    407423{
    408         int i, j;
     424        int i, j, n = 3;
    409425        char **lines;
    410426
    411         /* Count the number of elements we're gonna need. */
    412         for( i = 0, j = 1; buffer[i] != '\0'; i ++ )
    413         {
    414                 if( buffer[i] == '\n' )
    415                         if( buffer[i+1] != '\r' && buffer[i+1] != '\n' )
    416                                 j ++;
    417         }
    418        
    419         /* Allocate j+1 elements. */
    420         lines = g_new( char *, j + 1 );
     427        /* Allocate n+1 elements. */
     428        lines = g_new( char *, n + 1 );
     429       
     430        lines[0] = buffer;
     431       
     432        /* Split the buffer in several strings, and accept any kind of line endings,
     433         * knowing that ERC on Windows may send something interesting like \r\r\n,
     434         * and surely there must be clients that think just \n is enough... */
     435        for( i = 0, j = 0; buffer[i] != '\0'; i ++ )
     436        {
     437                if( buffer[i] == '\r' || buffer[i] == '\n' )
     438                {
     439                        while( buffer[i] == '\r' || buffer[i] == '\n' )
     440                                buffer[i++] = '\0';
     441                       
     442                        lines[++j] = buffer + i;
     443                       
     444                        if( j >= n )
     445                        {
     446                                n *= 2;
     447                                lines = g_renew( char *, lines, n + 1 );
     448                        }
     449
     450                        if( buffer[i] == '\0' )
     451                                break;
     452                }
     453        }
    421454       
    422455        /* NULL terminate our list. */
    423         lines[j] = NULL;
    424        
    425         lines[0] = buffer;
    426        
    427         /* Split the buffer in several strings, using \r\n as our seperator, where \r is optional.
    428          * Although this is not in the RFC, some braindead ircds (newnet's) use this, so some clients might too.
    429          */
    430         for( i = 0, j = 0; buffer[i] != '\0'; i ++)
    431         {
    432                 if( buffer[i] == '\n' )
    433                 {
    434                         buffer[i] = '\0';
    435                        
    436                         if( i > 0 && buffer[i-1] == '\r' )
    437                                 buffer[i-1] = '\0';
    438                         if( buffer[i+1] != '\r' && buffer[i+1] != '\n' )
    439                                 lines[++j] = buffer + i + 1;
    440                 }
    441         }
    442        
    443         return( lines );
     456        lines[++j] = NULL;
     457       
     458        return lines;
    444459}
    445460
     
    575590
    576591        return;
    577 
    578592}
    579593
     
    581595{
    582596        int size;
    583         char line[IRC_MAX_LINE+1], *cs;
    584                
    585         if( irc->quit )
     597        char line[IRC_MAX_LINE+1];
     598               
     599        /* Don't try to write anything new anymore when shutting down. */
     600        if( irc->status & USTATUS_SHUTDOWN )
    586601                return;
    587602       
    588         line[IRC_MAX_LINE] = 0;
     603        memset( line, 0, sizeof( line ) );
    589604        g_vsnprintf( line, IRC_MAX_LINE - 2, format, params );
    590        
    591605        strip_newlines( line );
    592         if( ( cs = set_getstr( irc, "charset" ) ) && ( g_strcasecmp( cs, "utf-8" ) != 0 ) )
    593         {
    594                 char conv[IRC_MAX_LINE+1];
    595                
    596                 conv[IRC_MAX_LINE] = 0;
    597                 if( do_iconv( "UTF-8", cs, line, conv, 0, IRC_MAX_LINE - 2 ) != -1 )
    598                         strcpy( line, conv );
    599         }
    600         strcat( line, "\r\n" );
    601        
    602         if( irc->sendbuffer != NULL ) {
     606       
     607        if( irc->oconv != (GIConv) -1 )
     608        {
     609                gsize bytes_read, bytes_written;
     610                char *conv;
     611               
     612                conv = g_convert_with_iconv( line, -1, irc->oconv,
     613                                             &bytes_read, &bytes_written, NULL );
     614
     615                if( bytes_read == strlen( line ) )
     616                        strncpy( line, conv, IRC_MAX_LINE - 2 );
     617               
     618                g_free( conv );
     619        }
     620        g_strlcat( line, "\r\n", IRC_MAX_LINE + 1 );
     621       
     622        if( irc->sendbuffer != NULL )
     623        {
    603624                size = strlen( irc->sendbuffer ) + strlen( line );
    604625                irc->sendbuffer = g_renew ( char, irc->sendbuffer, size + 1 );
    605626                strcpy( ( irc->sendbuffer + strlen( irc->sendbuffer ) ), line );
    606627        }
    607         else
    608                 irc->sendbuffer = g_strdup(line);       
     628        else
     629        {
     630                irc->sendbuffer = g_strdup(line);
     631        }
    609632       
    610633        if( irc->w_watch_source_id == 0 )
    611634        {
    612                 irc->w_watch_source_id = g_io_add_watch( irc->io_channel, G_IO_OUT, bitlbee_io_current_client_write, irc );
     635                /* If the buffer is empty we can probably write, so call the write event handler
     636                   immediately. If it returns TRUE, it should be called again, so add the event to
     637                   the queue. If it's FALSE, we emptied the buffer and saved ourselves some work
     638                   in the event queue. */
     639                /* Really can't be done as long as the code doesn't do error checking very well:
     640                if( bitlbee_io_current_client_write( irc, irc->fd, GAIM_INPUT_WRITE ) ) */
     641               
     642                /* So just always do it via the event handler. */
     643                irc->w_watch_source_id = b_input_add( irc->fd, GAIM_INPUT_WRITE, bitlbee_io_current_client_write, irc );
    613644        }
    614645       
     
    636667                if( now )
    637668                {
    638                         bitlbee_io_current_client_write( irc->io_channel, G_IO_OUT, irc );
     669                        bitlbee_io_current_client_write( irc, irc->fd, GAIM_INPUT_WRITE );
    639670                }
    640671                temp = temp->next;
     
    647678void irc_names( irc_t *irc, char *channel )
    648679{
    649         user_t *u = irc->users;
    650         char *s;
    651         int control = ( g_strcasecmp( channel, irc->channel ) == 0 );
    652         struct conversation *c = NULL;
    653        
    654         if( !control )
    655                 c = conv_findchannel( channel );
    656        
    657         /* RFC's say there is no error reply allowed on NAMES, so when the
     680        user_t *u;
     681        char namelist[385] = "";
     682        struct groupchat *c = NULL;
     683        char *ops = set_getstr( &irc->set, "ops" );
     684       
     685        /* RFCs say there is no error reply allowed on NAMES, so when the
    658686           channel is invalid, just give an empty reply. */
    659687       
    660         if( control || c ) while( u )
    661         {
    662                 if( u->online )
    663                 {
    664                         if( u->gc && control )
    665                         {
    666                                 if( set_getint( irc, "away_devoice" ) && !u->away )
    667                                         s = "+";
    668                                 else
    669                                         s = "";
    670                                
    671                                 irc_reply( irc, 353, "@ %s :%s%s", channel, s, u->nick );
    672                         }
    673                         else if( !u->gc )
    674                         {
    675                                 if( strcmp( u->nick, irc->mynick ) == 0 && ( strcmp( set_getstr( irc, "ops" ), "root" ) == 0 || strcmp( set_getstr( irc, "ops" ), "both" ) == 0 ) )
    676                                         s = "@";
    677                                 else if( strcmp( u->nick, irc->nick ) == 0 && ( strcmp( set_getstr( irc, "ops" ), "user" ) == 0 || strcmp( set_getstr( irc, "ops" ), "both" ) == 0 ) )
    678                                         s = "@";
    679                                 else
    680                                         s = "";
    681                                
    682                                 irc_reply( irc, 353, "@ %s :%s%s", channel, s, u->nick );
    683                         }
    684                 }
    685                
    686                 u = u->next;
    687         }
    688        
    689         /* For non-controlchannel channels (group conversations) only root and
    690            you are listed now. Time to show the channel people: */
    691         if( !control && c )
     688        if( g_strcasecmp( channel, irc->channel ) == 0 )
     689        {
     690                for( u = irc->users; u; u = u->next ) if( u->online )
     691                {
     692                        if( strlen( namelist ) + strlen( u->nick ) > sizeof( namelist ) - 4 )
     693                        {
     694                                irc_reply( irc, 353, "= %s :%s", channel, namelist );
     695                                *namelist = 0;
     696                        }
     697                       
     698                        if( u->ic && !u->away && set_getbool( &irc->set, "away_devoice" ) )
     699                                strcat( namelist, "+" );
     700                        else if( ( strcmp( u->nick, irc->mynick ) == 0 && ( strcmp( ops, "root" ) == 0 || strcmp( ops, "both" ) == 0 ) ) ||
     701                                 ( strcmp( u->nick, irc->nick ) == 0 && ( strcmp( ops, "user" ) == 0 || strcmp( ops, "both" ) == 0 ) ) )
     702                                strcat( namelist, "@" );
     703                       
     704                        strcat( namelist, u->nick );
     705                        strcat( namelist, " " );
     706                }
     707        }
     708        else if( ( c = irc_chat_by_channel( irc, channel ) ) )
    692709        {
    693710                GList *l;
    694711               
    695                 for( l = c->in_room; l; l = l->next )
    696                         if( ( u = user_findhandle( c->gc, l->data ) ) )
    697                                 irc_reply( irc, 353, "@ %s :%s%s", channel, "", u->nick );
    698         }
     712                /* root and the user aren't in the channel userlist but should
     713                   show up in /NAMES, so list them first: */
     714                sprintf( namelist, "%s%s %s%s ", strcmp( ops, "root" ) == 0 || strcmp( ops, "both" ) ? "@" : "", irc->mynick,
     715                                                 strcmp( ops, "user" ) == 0 || strcmp( ops, "both" ) ? "@" : "", irc->nick );
     716               
     717                for( l = c->in_room; l; l = l->next ) if( ( u = user_findhandle( c->ic, l->data ) ) )
     718                {
     719                        if( strlen( namelist ) + strlen( u->nick ) > sizeof( namelist ) - 4 )
     720                        {
     721                                irc_reply( irc, 353, "= %s :%s", channel, namelist );
     722                                *namelist = 0;
     723                        }
     724                       
     725                        strcat( namelist, u->nick );
     726                        strcat( namelist, " " );
     727                }
     728        }
     729       
     730        if( *namelist )
     731                irc_reply( irc, 353, "= %s :%s", channel, namelist );
    699732       
    700733        irc_reply( irc, 366, "%s :End of /NAMES list", channel );
     
    705738        if( irc->user && irc->nick )
    706739        {
    707                 if( global.conf->authmode == AUTHMODE_CLOSED && irc->status < USTATUS_AUTHORIZED )
     740                if( global.conf->authmode == AUTHMODE_CLOSED && !( irc->status & USTATUS_AUTHORIZED ) )
    708741                {
    709742                        irc_reply( irc, 464, ":This server is password-protected." );
     
    733766        irc_reply( irc,   5, "PREFIX=(ov)@+ CHANTYPES=#& CHANMODES=,,,%s NICKLEN=%d NETWORK=BitlBee CASEMAPPING=rfc1459 MAXTARGETS=1 WATCH=128 :are supported by this server", CMODES, MAX_NICK_LENGTH - 1 );
    734767        irc_motd( irc );
     768        irc->umode[0] = '\0';
    735769        irc_umode_set( irc, "+" UMODE, 1 );
    736770
     
    757791        irc_spawn( irc, u );
    758792       
    759         irc_usermsg( irc, "Welcome to the BitlBee gateway!\n\nIf you've never used BitlBee before, please do read the help information using the \x02help\x02 command. Lots of FAQ's are answered there." );
     793        irc_usermsg( irc, "Welcome to the BitlBee gateway!\n\n"
     794                          "If you've never used BitlBee before, please do read the help "
     795                          "information using the \x02help\x02 command. Lots of FAQs are "
     796                          "answered there.\n"
     797                          "If you already have an account on this server, just use the "
     798                          "\x02identify\x02 command to identify yourself." );
    760799       
    761800        if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON )
    762801                ipc_to_master_str( "CLIENT %s %s :%s\r\n", irc->host, irc->nick, irc->realname );
    763802       
    764         irc->status = USTATUS_LOGGED_IN;
     803        irc->status |= USTATUS_LOGGED_IN;
     804       
     805        /* This is for bug #209 (use PASS to identify to NickServ). */
     806        if( irc->password != NULL )
     807        {
     808                char *send_cmd[] = { "identify", g_strdup( irc->password ), NULL };
     809               
     810                irc_setpass( irc, NULL );
     811                root_command( irc, send_cmd );
     812                g_free( send_cmd[1] );
     813        }
    765814}
    766815
     
    819868void irc_topic( irc_t *irc, char *channel )
    820869{
    821         if( g_strcasecmp( channel, irc->channel ) == 0 )
    822         {
     870        struct groupchat *c = irc_chat_by_channel( irc, channel );
     871       
     872        if( c && c->topic )
     873                irc_reply( irc, 332, "%s :%s", channel, c->topic );
     874        else if( g_strcasecmp( channel, irc->channel ) == 0 )
    823875                irc_reply( irc, 332, "%s :%s", channel, CONTROL_TOPIC );
    824         }
    825876        else
    826         {
    827                 struct conversation *c = conv_findchannel( channel );
    828                
    829                 if( c )
    830                         irc_reply( irc, 332, "%s :BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!", channel, c->title );
    831                 else
    832                         irc_reply( irc, 331, "%s :No topic for this channel", channel );
    833         }
     877                irc_reply( irc, 331, "%s :No topic for this channel", channel );
    834878}
    835879
     
    840884        char m[256], st = 1, *t;
    841885        int i;
     886        char changes[512], *p, st2 = 2;
     887        char badflag = 0;
    842888       
    843889        memset( m, 0, sizeof( m ) );
     
    845891        for( t = irc->umode; *t; t ++ )
    846892                m[(int)*t] = 1;
    847        
     893
     894        p = changes;
    848895        for( t = s; *t; t ++ )
    849896        {
     
    851898                        st = *t == '+';
    852899                else if( st == 0 || ( strchr( UMODES, *t ) || ( allow_priv && strchr( UMODES_PRIV, *t ) ) ) )
     900                {
     901                        if( m[(int)*t] != st)
     902                        {
     903                                if( st != st2 )
     904                                        st2 = st, *p++ = st ? '+' : '-';
     905                                *p++ = *t;
     906                        }
    853907                        m[(int)*t] = st;
    854         }
     908                }
     909                else
     910                        badflag = 1;
     911        }
     912        *p = '\0';
    855913       
    856914        memset( irc->umode, 0, sizeof( irc->umode ) );
     
    860918                        irc->umode[strlen(irc->umode)] = i;
    861919       
    862         irc_reply( irc, 221, "+%s", irc->umode );
     920        if( badflag )
     921                irc_reply( irc, 501, ":Unknown MODE flag" );
     922        /* Deliberately no !user@host on the prefix here */
     923        if( *changes )
     924                irc_write( irc, ":%s MODE %s %s", irc->nick, irc->nick, changes );
    863925}
    864926
     
    903965void irc_kill( irc_t *irc, user_t *u )
    904966{
    905         char *nick;
    906        
    907         irc_write( irc, ":%s!%s@%s QUIT :%s", u->nick, u->user, u->host, "Leaving..." );
     967        char *nick, *s;
     968        char reason[128];
     969       
     970        if( u->ic && u->ic->flags & OPT_LOGGING_OUT && set_getbool( &irc->set, "simulate_netsplit" ) )
     971        {
     972                if( u->ic->acc->server )
     973                        g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost,
     974                                    u->ic->acc->server );
     975                else if( ( s = strchr( u->ic->acc->user, '@' ) ) )
     976                        g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost,
     977                                    s + 1 );
     978                else
     979                        g_snprintf( reason, sizeof( reason ), "%s %s.%s", irc->myhost,
     980                                    u->ic->acc->prpl->name, irc->myhost );
     981               
     982                /* proto_opt might contain garbage after the : */
     983                if( ( s = strchr( reason, ':' ) ) )
     984                        *s = 0;
     985        }
     986        else
     987        {
     988                strcpy( reason, "Leaving..." );
     989        }
     990       
     991        irc_write( irc, ":%s!%s@%s QUIT :%s", u->nick, u->user, u->host, reason );
    908992       
    909993        nick = g_strdup( u->nick );
     
    9181002int irc_send( irc_t *irc, char *nick, char *s, int flags )
    9191003{
    920         struct conversation *c = NULL;
     1004        struct groupchat *c = NULL;
    9211005        user_t *u = NULL;
    9221006       
    9231007        if( *nick == '#' || *nick == '&' )
    9241008        {
    925                 if( !( c = conv_findchannel( nick ) ) )
     1009                if( !( c = irc_chat_by_channel( irc, nick ) ) )
    9261010                {
    9271011                        irc_reply( irc, 403, "%s :Channel does not exist", nick );
     
    9701054                else if( g_strncasecmp( s + 1, "TYPING", 6 ) == 0 )
    9711055                {
    972                         if( u && u->gc && u->gc->prpl->send_typing && strlen( s ) >= 10 )
     1056                        if( u && u->ic && u->ic->acc->prpl->send_typing && strlen( s ) >= 10 )
    9731057                        {
    9741058                                time_t current_typing_notice = time( NULL );
     
    9761060                                if( current_typing_notice - u->last_typing_notice >= 5 )
    9771061                                {
    978                                         u->gc->prpl->send_typing( u->gc, u->handle, s[8] == '1' );
     1062                                        u->ic->acc->prpl->send_typing( u->ic, u->handle, ( s[8] - '0' ) << 8 );
    9791063                                        u->last_typing_notice = current_typing_notice;
    9801064                                }
     
    10091093                }
    10101094        }
    1011         else if( c && c->gc && c->gc->prpl )
    1012         {
    1013                 return( bim_chat_msg( c->gc, c->id, s ) );
     1095        else if( c && c->ic && c->ic->acc && c->ic->acc->prpl )
     1096        {
     1097                return( imc_chat_msg( c, s, 0 ) );
    10141098        }
    10151099       
     
    10171101}
    10181102
    1019 gboolean buddy_send_handler_delayed( gpointer data )
     1103static gboolean buddy_send_handler_delayed( gpointer data, gint fd, b_input_condition cond )
    10201104{
    10211105        user_t *u = data;
     
    10261110       
    10271111        u->sendbuf[u->sendbuf_len-2] = 0; /* Cut off the last newline */
    1028         bim_buddy_msg( u->gc, u->handle, u->sendbuf, u->sendbuf_flags );
     1112        imc_buddy_msg( u->ic, u->handle, u->sendbuf, u->sendbuf_flags );
    10291113       
    10301114        g_free( u->sendbuf );
     
    10391123void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags )
    10401124{
    1041         if( !u || !u->gc ) return;
    1042        
    1043         if( set_getint( irc, "buddy_sendbuffer" ) && set_getint( irc, "buddy_sendbuffer_delay" ) > 0 )
     1125        if( !u || !u->ic ) return;
     1126       
     1127        if( set_getbool( &irc->set, "buddy_sendbuffer" ) && set_getint( &irc->set, "buddy_sendbuffer_delay" ) > 0 )
    10441128        {
    10451129                int delay;
     
    10481132                {
    10491133                        /* Flush the buffer */
    1050                         g_source_remove( u->sendbuf_timer );
    1051                         buddy_send_handler_delayed( u );
     1134                        b_event_remove( u->sendbuf_timer );
     1135                        buddy_send_handler_delayed( u, -1, 0 );
    10521136                }
    10531137
     
    10681152                strcat( u->sendbuf, "\n" );
    10691153               
    1070                 delay = set_getint( irc, "buddy_sendbuffer_delay" );
     1154                delay = set_getint( &irc->set, "buddy_sendbuffer_delay" );
    10711155                if( delay <= 5 )
    10721156                        delay *= 1000;
    10731157               
    10741158                if( u->sendbuf_timer > 0 )
    1075                         g_source_remove( u->sendbuf_timer );
    1076                 u->sendbuf_timer = g_timeout_add( delay, buddy_send_handler_delayed, u );
     1159                        b_event_remove( u->sendbuf_timer );
     1160                u->sendbuf_timer = b_timeout_add( delay, buddy_send_handler_delayed, u );
    10771161        }
    10781162        else
    10791163        {
    1080                 bim_buddy_msg( u->gc, u->handle, msg, flags );
     1164                imc_buddy_msg( u->ic, u->handle, msg, flags );
    10811165        }
    10821166}
     
    11331217                int len = strlen( irc->nick) + 3;
    11341218                prefix = g_new (char, len );
    1135                 g_snprintf( prefix, len, "%s%s", irc->nick, set_getstr( irc, "to_char" ) );
     1219                g_snprintf( prefix, len, "%s%s", irc->nick, set_getstr( &irc->set, "to_char" ) );
    11361220                prefix[len-1] = 0;
    11371221        }
     
    11581242   pongs from the user. When not connected yet, we don't ping but drop the
    11591243   connection when the user fails to connect in IRC_LOGIN_TIMEOUT secs. */
    1160 static gboolean irc_userping( gpointer _irc )
     1244static gboolean irc_userping( gpointer _irc, gint fd, b_input_condition cond )
    11611245{
    11621246        irc_t *irc = _irc;
    11631247        int rv = 0;
    11641248       
    1165         if( irc->status < USTATUS_LOGGED_IN )
     1249        if( !( irc->status & USTATUS_LOGGED_IN ) )
    11661250        {
    11671251                if( gettime() > ( irc->last_pong + IRC_LOGIN_TIMEOUT ) )
     
    11891273        return TRUE;
    11901274}
     1275
     1276struct groupchat *irc_chat_by_channel( irc_t *irc, char *channel )
     1277{
     1278        struct groupchat *c;
     1279        account_t *a;
     1280       
     1281        /* This finds the connection which has a conversation which belongs to this channel */
     1282        for( a = irc->accounts; a; a = a->next )
     1283        {
     1284                if( a->ic == NULL )
     1285                        continue;
     1286               
     1287                c = a->ic->groupchats;
     1288                while( c )
     1289                {
     1290                        if( c->channel && g_strcasecmp( c->channel, channel ) == 0 )
     1291                                return c;
     1292                       
     1293                        c = c->next;
     1294                }
     1295        }
     1296       
     1297        return NULL;
     1298}
  • irc.h

    r875ad42 r85d7b85  
    4242{
    4343        USTATUS_OFFLINE = 0,
    44         USTATUS_AUTHORIZED,
    45         USTATUS_LOGGED_IN,
    46         USTATUS_IDENTIFIED,
    47         USTATUS_SHUTDOWN = -1
     44        USTATUS_AUTHORIZED = 1,
     45        USTATUS_LOGGED_IN = 2,
     46        USTATUS_IDENTIFIED = 4,
     47        USTATUS_SHUTDOWN = 8
    4848} irc_status_t;
    4949
     
    6161        char *sendbuffer;
    6262        char *readbuffer;
    63         int quit;
     63        GIConv iconv, oconv;
    6464
    6565        int sentbytes;
     
    7070        char *host;
    7171        char *realname;
    72         char *password;
     72        char *password; /* HACK: Used to save the user's password, but before
     73                           logging in, this may contain a password we should
     74                           send to identify after USER/NICK are received. */
    7375
    7476        char umode[8];
     
    9092        GHashTable *watches;
    9193        struct __NICK *nicks;
    92         struct help *help;
    9394        struct set *set;
    9495
    95         GIOChannel *io_channel;
    9696        gint r_watch_source_id;
    9797        gint w_watch_source_id;
     
    100100
    101101#include "user.h"
    102 #include "nick.h"
     102// #include "nick.h"
    103103
    104104extern GSList *irc_connection_list;
     
    142142
    143143void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags );
     144struct groupchat *irc_chat_by_channel( irc_t *irc, char *channel );
    144145
    145146#endif
  • irc_commands.c

    r875ad42 r85d7b85  
    3030static void irc_cmd_pass( irc_t *irc, char **cmd )
    3131{
    32         if( global.conf->auth_pass && strcmp( cmd[1], global.conf->auth_pass ) == 0 )
    33         {
    34                 irc->status = USTATUS_AUTHORIZED;
     32        if( irc->status & USTATUS_LOGGED_IN )
     33        {
     34                char *send_cmd[] = { "identify", cmd[1], NULL };
     35               
     36                /* We're already logged in, this client seems to send the PASS
     37                   command last. (Possibly it won't send it at all if it turns
     38                   out we don't require it, which will break this feature.)
     39                   Try to identify using the given password. */
     40                return root_command( irc, send_cmd );
     41        }
     42        /* Handling in pre-logged-in state, first see if this server is
     43           password-protected: */
     44        else if( global.conf->auth_pass &&
     45            ( strncmp( global.conf->auth_pass, "md5:", 4 ) == 0 ?
     46                md5_verify_password( cmd[1], global.conf->auth_pass + 4 ) == 0 :
     47                strcmp( cmd[1], global.conf->auth_pass ) == 0 ) )
     48        {
     49                irc->status |= USTATUS_AUTHORIZED;
    3550                irc_check_login( irc );
    3651        }
    37         else
     52        else if( global.conf->auth_pass )
    3853        {
    3954                irc_reply( irc, 464, ":Incorrect password" );
     55        }
     56        else
     57        {
     58                /* Remember the password and try to identify after USER/NICK. */
     59                irc_setpass( irc, cmd[1] );
     60                irc_check_login( irc );
    4061        }
    4162}
     
    88109static void irc_cmd_oper( irc_t *irc, char **cmd )
    89110{
    90         if( global.conf->oper_pass && strcmp( cmd[2], global.conf->oper_pass ) == 0 )
     111        if( global.conf->oper_pass &&
     112            ( strncmp( global.conf->oper_pass, "md5:", 4 ) == 0 ?
     113                md5_verify_password( cmd[2], global.conf->oper_pass + 4 ) == 0 :
     114                strcmp( cmd[2], global.conf->oper_pass ) == 0 ) )
    91115        {
    92116                irc_umode_set( irc, "+o", 1 );
     
    119143                        if( cmd[2] )
    120144                                irc_umode_set( irc, cmd[2], 0 );
     145                        else
     146                                irc_reply( irc, 221, "+%s", irc->umode );
    121147                }
    122148                else
     
    132158static void irc_cmd_part( irc_t *irc, char **cmd )
    133159{
    134         struct conversation *c;
     160        struct groupchat *c;
    135161       
    136162        if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
     
    142168                irc_join( irc, u, irc->channel );
    143169        }
    144         else if( ( c = conv_findchannel( cmd[1] ) ) )
     170        else if( ( c = irc_chat_by_channel( irc, cmd[1] ) ) )
    145171        {
    146172                user_t *u = user_find( irc, irc->nick );
     
    148174                irc_part( irc, u, c->channel );
    149175               
    150                 if( c->gc && c->gc->prpl )
     176                if( c->ic )
    151177                {
    152178                        c->joined = 0;
    153                         c->gc->prpl->chat_leave( c->gc, c->id );
     179                        c->ic->acc->prpl->chat_leave( c );
    154180                }
    155181        }
     
    171197                        user_t *u = user_find( irc, cmd[1] + 1 );
    172198                       
    173                         if( u && u->gc && u->gc->prpl && u->gc->prpl->chat_open )
     199                        if( u && u->ic && u->ic->acc->prpl->chat_with )
    174200                        {
    175201                                irc_reply( irc, 403, "%s :Initializing groupchat in a different channel", cmd[1] );
    176202                               
    177                                 if( !u->gc->prpl->chat_open( u->gc, u->handle ) )
     203                                if( !u->ic->acc->prpl->chat_with( u->ic, u->handle ) )
    178204                                {
    179                                         irc_usermsg( irc, "Could not open a groupchat with %s, maybe you don't have a connection to him/her yet?", u->nick );
     205                                        irc_usermsg( irc, "Could not open a groupchat with %s.", u->nick );
    180206                                }
    181207                        }
     
    199225{
    200226        char *nick = cmd[1], *channel = cmd[2];
    201         struct conversation *c = conv_findchannel( channel );
     227        struct groupchat *c = irc_chat_by_channel( irc, channel );
    202228        user_t *u = user_find( irc, nick );
    203229       
    204         if( u && c && ( u->gc == c->gc ) )
    205                 if( c->gc && c->gc->prpl && c->gc->prpl->chat_invite )
    206                 {
    207                         c->gc->prpl->chat_invite( c->gc, c->id, "", u->handle );
     230        if( u && c && ( u->ic == c->ic ) )
     231                if( c->ic && c->ic->acc->prpl->chat_invite )
     232                {
     233                        c->ic->acc->prpl->chat_invite( c, u->handle, NULL );
    208234                        irc_reply( irc, 341, "%s %s", nick, channel );
    209235                        return;
     
    228254                {
    229255                        unsigned int i;
    230                         char *t = set_getstr( irc, "default_target" );
     256                        char *t = set_getstr( &irc->set, "default_target" );
    231257                       
    232258                        if( g_strcasecmp( t, "last" ) == 0 && irc->last_target )
     
    252278                        if( cmd[1] != irc->last_target )
    253279                        {
    254                                 if( irc->last_target )
    255                                         g_free( irc->last_target );
     280                                g_free( irc->last_target );
    256281                                irc->last_target = g_strdup( cmd[1] );
    257282                        }
     
    261286                        irc->is_private = 1;
    262287                }
    263                 irc_send( irc, cmd[1], cmd[2], ( g_strcasecmp( cmd[0], "NOTICE" ) == 0 ) ? IM_FLAG_AWAY : 0 );
     288                irc_send( irc, cmd[1], cmd[2], ( g_strcasecmp( cmd[0], "NOTICE" ) == 0 ) ? OPT_AWAY : 0 );
    264289        }
    265290}
     
    269294        char *channel = cmd[1];
    270295        user_t *u = irc->users;
    271         struct conversation *c;
     296        struct groupchat *c;
    272297        GList *l;
    273298       
     
    285310                        u = u->next;
    286311                }
    287         else if( ( c = conv_findchannel( channel ) ) )
     312        else if( ( c = irc_chat_by_channel( irc, channel ) ) )
    288313                for( l = c->in_room; l; l = l->next )
    289314                {
    290                         if( ( u = user_findhandle( c->gc, l->data ) ) )
     315                        if( ( u = user_findhandle( c->ic, l->data ) ) )
    291316                                irc_reply( irc, 352, "%s %s %s %s %s %c :0 %s", channel, u->user, u->host, irc->myhost, u->nick, u->away ? 'G' : 'H', u->realname );
    292317                }
     
    331356        for( i = 1; cmd[i]; i ++ )
    332357        {
    333                 if( ( u = user_find( irc, cmd[i] ) ) && u->online )
    334                 {
    335                         /* [SH] Make sure we don't use too much buffer space. */
    336                         lenleft -= strlen( u->nick ) + 1;
    337                        
    338                         if( lenleft < 0 )
     358                char *this, *next;
     359               
     360                this = cmd[i];
     361                while( *this )
     362                {
     363                        if( ( next = strchr( this, ' ' ) ) )
     364                                *next = 0;
     365                       
     366                        if( ( u = user_find( irc, this ) ) && u->online )
     367                        {
     368                                lenleft -= strlen( u->nick ) + 1;
     369                               
     370                                if( lenleft < 0 )
     371                                        break;
     372                               
     373                                strcat( buff, u->nick );
     374                                strcat( buff, " " );
     375                        }
     376                       
     377                        if( next )
     378                        {
     379                                *next = ' ';
     380                                this = next + 1;
     381                        }
     382                        else
    339383                        {
    340384                                break;
    341                         }
    342                        
    343                         /* [SH] Add the nick to the buffer. Note
    344                          * that an extra space is always added. Even
    345                          * if it's the last nick in the list. Who
    346                          * cares?
    347                          */
    348                        
    349                         strcat( buff, u->nick );
    350                         strcat( buff, " " );
    351                 }
    352         }
    353        
    354         /* [WvG] Well, maybe someone cares, so why not remove it? */
     385                        }   
     386                }
     387               
     388                /* *sigh* */
     389                if( lenleft < 0 )
     390                        break;
     391        }
     392       
    355393        if( strlen( buff ) > 0 )
    356394                buff[strlen(buff)-1] = '\0';
     
    406444static void irc_cmd_topic( irc_t *irc, char **cmd )
    407445{
    408         if( cmd[2] )
    409                 irc_reply( irc, 482, "%s :Cannot change topic", cmd[1] );
    410         else
    411                 irc_topic( irc, cmd[1] );
     446        char *channel = cmd[1];
     447        char *topic = cmd[2];
     448       
     449        if( topic )
     450        {
     451                /* Send the topic */
     452                struct groupchat *c = irc_chat_by_channel( irc, channel );
     453                if( c && c->ic && c->ic->acc->prpl->chat_topic )
     454                        c->ic->acc->prpl->chat_topic( c, topic );
     455        }
     456        else
     457        {
     458                /* Get the topic */
     459                irc_topic( irc, channel );
     460        }
    412461}
    413462
     
    445494        for( a = irc->accounts; a; a = a->next )
    446495        {
    447                 struct gaim_connection *gc = a->gc;
    448                
    449                 if( gc && gc->flags & OPT_LOGGED_IN )
    450                         bim_set_away( gc, u->away );
     496                struct im_connection *ic = a->ic;
     497               
     498                if( ic && ic->flags & OPT_LOGGED_IN )
     499                        imc_set_away( ic, u->away );
    451500        }
    452501}