Changes in / [8e419cb:a4dc9f7]


Ignore:
Files:
5 added
2 deleted
24 edited

Legend:

Unmodified
Added
Removed
  • Makefile

    r8e419cb ra4dc9f7  
    1010
    1111# Program variables
    12 objects = account.o bitlbee.o commands.o crypting.o help.o ini.o irc.o nick.o query.o set.o storage.o storage_text.o url.o user.o util.o
     12objects = 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
    1313subdirs = protocols
    1414
  • bitlbee.c

    r8e419cb ra4dc9f7  
    2929#include "protocols/nogaim.h"
    3030#include "help.h"
     31#include "ipc.h"
    3132#include <signal.h>
    3233#include <stdio.h>
    3334#include <errno.h>
    3435
    35 gboolean bitlbee_io_new_client( GIOChannel *source, GIOCondition condition, gpointer data )
    36 {
    37         size_t size = sizeof( struct sockaddr_in );
    38         struct sockaddr_in conn_info;
    39         int new_socket = accept( global.listen_socket, (struct sockaddr *) &conn_info, &size );
    40         pid_t client_pid = 0;
    41        
    42         if( global.conf->runmode == RUNMODE_FORKDAEMON )
    43                 client_pid = fork();
    44        
    45         if( client_pid == 0 )
    46         {
    47                 log_message( LOGLVL_INFO, "Creating new connection with fd %d.", new_socket );
    48                 irc_new( new_socket );
    49                
    50                 if( global.conf->runmode == RUNMODE_FORKDAEMON )
    51                 {
    52                         /* Close the listening socket, we're a client. */
    53                         close( global.listen_socket );
    54                         g_source_remove( global.listen_watch_source_id );
    55                 }
    56         }
    57         else
    58         {
    59                 /* We don't need this one, only the client does. */
    60                 close( new_socket );
    61                
    62                 /* Or maybe we didn't even get a child process... */
    63                 if( client_pid == -1 )
    64                         log_message( LOGLVL_ERROR, "Failed to fork() subprocess for client: %s", strerror( errno ) );
    65         }
    66        
    67         return TRUE;
    68 }
    69  
    70 
     36gboolean bitlbee_io_new_client( GIOChannel *source, GIOCondition condition, gpointer data );
    7137
    7238int bitlbee_daemon_init()
     
    7945        int i;
    8046        GIOChannel *ch;
     47        FILE *fp;
    8148       
    8249        log_link( LOGLVL_ERROR, LOGOUTPUT_SYSLOG );
     
    8956                return( -1 );
    9057        }
     58       
     59        /* TIME_WAIT (?) sucks.. */
     60        i = 1;
     61        setsockopt( global.listen_socket, SOL_SOCKET, SO_REUSEADDR, &i, sizeof( i ) );
    9162       
    9263#ifdef IPV6
     
    134105                else if( i != 0 )
    135106                        exit( 0 );
    136                 close( 0 );
    137                 close( 1 );
    138                 close( 2 );
     107               
    139108                chdir( "/" );
     109               
     110                /* Sometimes std* are already closed (for example when we're in a RESTARTed
     111                   BitlBee process. So let's only close TTY-fds. */
     112                if( isatty( 0 ) ) close( 0 );
     113                if( isatty( 0 ) ) close( 1 );
     114                if( isatty( 0 ) ) close( 2 );
    140115        }
    141116#endif
     117       
     118        if( global.conf->runmode == RUNMODE_FORKDAEMON )
     119                ipc_master_load_state();
     120
     121        if( global.conf->runmode == RUNMODE_DAEMON ||
     122                global.conf->runmode == RUNMODE_FORKDAEMON )
     123                ipc_master_listen_socket();
     124       
     125        if( ( fp = fopen( global.conf->pidfile, "w" ) ) )
     126        {
     127                fprintf( fp, "%d\n", (int) getpid() );
     128                fclose( fp );
     129        }
     130        else
     131        {
     132                log_message( LOGLVL_WARNING, "Warning: Couldn't write PID to `%s'", global.conf->pidfile );
     133        }
    142134       
    143135        return( 0 );
     
    160152        if( condition & G_IO_ERR || condition & G_IO_HUP )
    161153        {
    162                 irc_free( irc );
     154                irc_abort( irc, 1, "Read error" );
    163155                return FALSE;
    164156        }
     
    167159        if( st == 0 )
    168160        {
    169                 irc_free( irc );
     161                irc_abort( irc, 1, "Connection reset by peer" );
    170162                return FALSE;
    171163        }
     
    178170                else
    179171                {
    180                         irc_free( irc );
     172                        irc_abort( irc, 1, "Read error: %s", strerror( errno ) );
    181173                        return FALSE;
    182174                }
     
    194186        }
    195187       
    196         if( !irc_process( irc ) )
    197         {
    198                 log_message( LOGLVL_INFO, "Destroying connection with fd %d.", irc->fd );
    199                 irc_free( irc );
     188        irc_process( irc );
     189       
     190        /* Normally, irc_process() shouldn't call irc_free() but irc_abort(). Just in case: */
     191        if( !g_slist_find( irc_connection_list, irc ) )
     192        {
     193                log_message( LOGLVL_WARNING, "Abnormal termination of connection with fd %d.", irc->fd );
    200194                return FALSE;
    201195        }
     
    204198        if( irc->readbuffer && ( strlen( irc->readbuffer ) > 1024 ) )
    205199        {
    206                 log_message( LOGLVL_ERROR, "Maximum line length exceeded." );
    207                 irc_free( irc );
     200                irc_abort( irc, 0, "Maximum line length exceeded" );
    208201                return FALSE;
    209202        }
     
    224217        st = write( irc->fd, irc->sendbuffer, size );
    225218       
    226         if( st <= 0 )
    227         {
    228                 if( sockerr_again() )
    229                 {
    230                         return TRUE;
    231                 }
    232                 else
    233                 {
    234                         irc_free( irc );
    235                         return FALSE;
    236                 }
     219        if( st == 0 || ( st < 0 && !sockerr_again() ) )
     220        {
     221                irc_abort( irc, 1, "Write error: %s", strerror( errno ) );
     222                return FALSE;
     223        }
     224        else if( st < 0 ) /* && sockerr_again() */
     225        {
     226                return TRUE;
    237227        }
    238228       
     
    241231                g_free( irc->sendbuffer );
    242232                irc->sendbuffer = NULL;
    243                
    244233                irc->w_watch_source_id = 0;
     234               
     235                if( irc->status == USTATUS_SHUTDOWN )
     236                        irc_free( irc );
     237               
    245238                return( FALSE );
    246239        }
     
    255248}
    256249
     250gboolean bitlbee_io_new_client( GIOChannel *source, GIOCondition condition, gpointer data )
     251{
     252        size_t size = sizeof( struct sockaddr_in );
     253        struct sockaddr_in conn_info;
     254        int new_socket = accept( global.listen_socket, (struct sockaddr *) &conn_info, &size );
     255        pid_t client_pid = 0;
     256       
     257        if( new_socket == -1 )
     258        {
     259                log_message( LOGLVL_WARNING, "Could not accept new connection: %s", strerror( errno ) );
     260                return TRUE;
     261        }
     262       
     263        if( global.conf->runmode == RUNMODE_FORKDAEMON )
     264        {
     265                int fds[2];
     266               
     267                if( socketpair( AF_UNIX, SOCK_STREAM, 0, fds ) == -1 )
     268                {
     269                        log_message( LOGLVL_WARNING, "Could not create IPC socket for client: %s", strerror( errno ) );
     270                        fds[0] = fds[1] = -1;
     271                }
     272               
     273                sock_make_nonblocking( fds[0] );
     274                sock_make_nonblocking( fds[1] );
     275               
     276                client_pid = fork();
     277               
     278                if( client_pid > 0 && fds[0] != -1 )
     279                {
     280                        struct bitlbee_child *child;
     281                       
     282                        child = g_new0( struct bitlbee_child, 1 );
     283                        child->pid = client_pid;
     284                        child->ipc_fd = fds[0];
     285                        child->ipc_inpa = gaim_input_add( child->ipc_fd, GAIM_INPUT_READ, ipc_master_read, child );
     286                        child_list = g_slist_append( child_list, child );
     287                       
     288                        log_message( LOGLVL_INFO, "Creating new subprocess with pid %d.", client_pid );
     289                       
     290                        /* Close some things we don't need in the parent process. */
     291                        close( new_socket );
     292                        close( fds[1] );
     293                }
     294                else if( client_pid == 0 )
     295                {
     296                        irc_t *irc;
     297                       
     298                        /* Close the listening socket, we're a client. */
     299                        close( global.listen_socket );
     300                        g_source_remove( global.listen_watch_source_id );
     301                       
     302                        /* Make the connection. */
     303                        irc = irc_new( new_socket );
     304                       
     305                        /* We can store the IPC fd there now. */
     306                        global.listen_socket = fds[1];
     307                        global.listen_watch_source_id = gaim_input_add( fds[1], GAIM_INPUT_READ, ipc_child_read, irc );
     308                       
     309                        close( fds[0] );
     310                       
     311                        ipc_master_free_all();
     312                }
     313        }
     314        else
     315        {
     316                log_message( LOGLVL_INFO, "Creating new connection with fd %d.", new_socket );
     317                irc_new( new_socket );
     318        }
     319       
     320        return TRUE;
     321}
     322
    257323void bitlbee_shutdown( gpointer data )
    258324{
  • bitlbee.h

    r8e419cb ra4dc9f7  
    109109#include "sock.h"
    110110
    111 typedef struct global_t {
     111typedef struct global {
     112        /* In forked mode, child processes store the fd of the IPC socket here. */
    112113        int listen_socket;
    113114        gint listen_watch_source_id;
     
    117118        char *helpfile;
    118119        GMainLoop *loop;
     120        int restart;
    119121} global_t;
    120122
     
    125127gboolean bitlbee_io_current_client_write( GIOChannel *source, GIOCondition condition, gpointer data );
    126128
    127 int root_command_string( irc_t *irc, user_t *u, char *command, int flags );
    128 int root_command( irc_t *irc, char *command[] );
     129void root_command_string( irc_t *irc, user_t *u, char *command, int flags );
     130void root_command( irc_t *irc, char *command[] );
    129131void bitlbee_shutdown( gpointer data );
    130132double gettime( void );
  • commands.h

    r8e419cb ra4dc9f7  
    2929#include "bitlbee.h"
    3030
    31 typedef struct command_t
     31typedef struct command
    3232{
    3333        char *command;
    3434        int required_parameters;
    35         int (*execute)(irc_t *, char **args);
     35        void (*execute)(irc_t *, char **args);
     36        int flags;
    3637} command_t;
    37 
    38 int cmd_account( irc_t *irc, char **cmd );
    39 int cmd_help( irc_t *irc, char **args);
    40 int cmd_info( irc_t *irc, char **args);
    41 int cmd_add( irc_t *irc, char **args) ;
    42 int cmd_rename( irc_t *irc, char **args );
    43 int cmd_remove( irc_t *irc, char **args );
    44 int cmd_block( irc_t *irc, char **args );
    45 int cmd_allow( irc_t *irc, char **args );
    46 int cmd_save( irc_t *irc, char **args );
    47 int cmd_set( irc_t *irc, char **args );
    48 int cmd_yesno( irc_t *irc, char **args );
    49 int cmd_identify( irc_t *irc, char **args );
    50 int cmd_register( irc_t *irc, char **args );
    51 int cmd_drop( irc_t *irc, char **args );
    52 int cmd_blist( irc_t *irc, char **cmd );
    53 int cmd_nick( irc_t *irc, char **cmd );
    54 int cmd_qlist( irc_t *irc, char **cmd );
    55 int cmd_import_buddies( irc_t *irc, char **cmd );
    56 int cmd_dump( irc_t *irc, char **cmd );
    5738
    5839extern const command_t commands[];
    5940
     41#define IRC_CMD_PRE_LOGIN       1
     42#define IRC_CMD_LOGGED_IN       2
     43#define IRC_CMD_OPER_ONLY       4
     44#define IRC_CMD_TO_MASTER       8
     45
     46#define IPC_CMD_TO_CHILDREN     1
     47
    6048#endif
  • conf.c

    r8e419cb ra4dc9f7  
    3232#include "ini.h"
    3333#include "url.h"
     34#include "ipc.h"
    3435
    3536#include "protocols/proxy.h"
     
    6162        conf->configdir = g_strdup( CONFIG );
    6263        conf->plugindir = g_strdup( PLUGINDIR );
     64        conf->pidfile = g_strdup( "/var/run/bitlbee.pid" );
    6365        conf->motdfile = g_strdup( ETCDIR "/motd.txt" );
    6466        conf->ping_interval = 180;
    6567        conf->ping_timeout = 300;
     68        proxytype = 0;
    6669       
    6770        i = conf_loadini( conf, CONF_FILE );
     
    7679        }
    7780       
    78         while( ( opt = getopt( argc, argv, "i:p:nvIDFc:d:h" ) ) >= 0 )
     81        while( argc > 0 && ( opt = getopt( argc, argv, "i:p:P:nvIDFc:d:hR:" ) ) >= 0 )
     82        /*     ^^^^ Just to make sure we skip this step from the REHASH handler. */
    7983        {
    8084                if( opt == 'i' )
     
    9195                        conf->port = i;
    9296                }
     97                else if( opt == 'p' )
     98                {
     99                        g_free( conf->pidfile );
     100                        conf->pidfile = g_strdup( optarg );
     101                }
    93102                else if( opt == 'n' )
    94                         conf->nofork=1;
     103                        conf->nofork = 1;
    95104                else if( opt == 'v' )
    96                         conf->verbose=1;
     105                        conf->verbose = 1;
    97106                else if( opt == 'I' )
    98                         conf->runmode=RUNMODE_INETD;
     107                        conf->runmode = RUNMODE_INETD;
    99108                else if( opt == 'D' )
    100                         conf->runmode=RUNMODE_DAEMON;
     109                        conf->runmode = RUNMODE_DAEMON;
    101110                else if( opt == 'F' )
    102                         conf->runmode=RUNMODE_FORKDAEMON;
     111                        conf->runmode = RUNMODE_FORKDAEMON;
    103112                else if( opt == 'c' )
    104113                {
     
    108117                                CONF_FILE = g_strdup( optarg );
    109118                                g_free( conf );
     119                                /* Re-evaluate arguments. Don't use this option twice,
     120                                   you'll end up in an infinite loop! Hope this trick
     121                                   works with all libcs BTW.. */
     122                                optind = 1;
    110123                                return( conf_load( argc, argv ) );
    111124                        }
     
    126139                                "  -D  Daemon mode. (Still EXPERIMENTAL!)\n"
    127140                                "  -F  Forking daemon. (one process per client)\n"
     141                                "  -P  Specify PID-file (not for inetd mode)\n"
    128142                                "  -i  Specify the interface (by IP address) to listen on.\n"
    129143                                "      (Default: 0.0.0.0 (any interface))\n"
     
    136150                        return( NULL );
    137151                }
     152                else if( opt == 'R' )
     153                {
     154                        /* We can't load the statefile yet (and should make very sure we do this
     155                           only once), so set the filename here and load the state information
     156                           when initializing ForkDaemon. (This option only makes sense in that
     157                           mode anyway!) */
     158                        ipc_master_set_statefile( optarg );
     159                }
    138160        }
    139161       
     
    169191                                else
    170192                                        conf->runmode = RUNMODE_INETD;
     193                        }
     194                        else if( g_strcasecmp( ini->key, "pidfile" ) == 0 )
     195                        {
     196                                g_free( conf->pidfile );
     197                                conf->pidfile = g_strdup( ini->value );
    171198                        }
    172199                        else if( g_strcasecmp( ini->key, "daemoninterface" ) == 0 )
  • conf.h

    r8e419cb ra4dc9f7  
    4343        char *configdir;
    4444        char *plugindir;
     45        char *pidfile;
    4546        char *motdfile;
    4647        char *primary_storage;
  • configure

    r8e419cb ra4dc9f7  
    1414datadir='$prefix/share/bitlbee/'
    1515config='/var/lib/bitlbee/'
     16pidfile='/var/run/bitlbee.pid'
     17ipcsocket='/var/run/bitlbee'
    1618plugindir='$prefix/lib/bitlbee'
    1719
     
    4648--datadir=...                                           $datadir
    4749--plugindir=...                                         $plugindir
     50--pidfile=...                                           $pidfile
    4851--config=...                                            $config
     52--ipcsocket=...                                         $ipcsocket
    4953
    5054--msn=0/1       Disable/enable MSN part                 $msn
     
    7478config=`eval echo "$config/" | sed 's/\/\{1,\}/\//g'`
    7579plugindir=`eval echo "$plugindir/" | sed 's/\/\{1,\}/\//g'`
     80pidfile=`eval echo "$pidfile" | sed 's/\/\{1,\}/\//g'`
     81ipcsocket=`eval echo "$ipcsocket" | sed 's/\/\{1,\}/\//g'`
    7682
    7783cat<<EOF>Makefile.settings
     
    8490PLUGINDIR=$plugindir
    8591CONFIG=$config
     92IPCSOCKET=$ipcsocket
    8693
    8794ARCH=$arch
     
    104111#define VARDIR "$datadir"
    105112#define PLUGINDIR "$plugindir"
     113#define PIDFILE "$pidfile"
     114#define IPCSOCKET "$ipcsocket"
    106115#define ARCH "$arch"
    107116#define CPU "$cpu"
  • doc/README

    r8e419cb ra4dc9f7  
    5050
    5151These days, MSN Messenger clients have to connect to the MS Passport servers
    52 through HTTPS. BitlBee can use serveral SSL libraries for this: GnuTLS, NSS
     52through HTTPS. BitlBee can use several SSL libraries for this: GnuTLS, NSS
    5353(which comes with Mozilla) and OpenSSL. OpenSSL is not GPL-compatible in some
    5454situations, so using GnuTLS or NSS is preferred. However, especially on *BSD,
  • irc.c

    r8e419cb ra4dc9f7  
    2727#include "bitlbee.h"
    2828#include "crypting.h"
     29#include "ipc.h"
    2930
    3031static gboolean irc_userping( gpointer _irc );
     
    151152}
    152153
     154/* immed=1 makes this function pretty much equal to irc_free(), except that
     155   this one will "log". In case the connection is already broken and we
     156   shouldn't try to write to it. */
     157void irc_abort( irc_t *irc, int immed, char *format, ... )
     158{
     159        if( format != NULL )
     160        {
     161                va_list params;
     162                char *reason;
     163               
     164                va_start( params, format );
     165                reason = g_strdup_vprintf( format, params );
     166                va_end( params );
     167               
     168                if( !immed )
     169                        irc_write( irc, "ERROR :Closing link: %s", reason );
     170               
     171                ipc_to_master_str( "OPERMSG :Client exiting: %s@%s [%s]\r\n",
     172                                   irc->nick ? irc->nick : "(NONE)", irc->host, reason );
     173               
     174                g_free( reason );
     175        }
     176        else
     177        {
     178                if( !immed )
     179                        irc_write( irc, "ERROR :Closing link" );
     180               
     181                ipc_to_master_str( "OPERMSG :Client exiting: %s@%s [%s]\r\n",
     182                                   irc->nick ? irc->nick : "(NONE)", irc->host, "No reason given" );
     183        }
     184       
     185        irc->status = USTATUS_SHUTDOWN;
     186        if( irc->sendbuffer && !immed )
     187        {
     188                /* We won't read from this socket anymore. Instead, we'll connect a timer
     189                   to it that should shut down the connection in a second, just in case
     190                   bitlbee_.._write doesn't do it first. */
     191               
     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 );
     194        }
     195        else
     196        {
     197                irc_free( irc );
     198        }
     199}
     200
    153201static gboolean irc_free_userhash( gpointer key, gpointer value, gpointer data )
    154202{
     
    172220                if( storage_save( irc, TRUE ) != STORAGE_OK )
    173221                        irc_usermsg( irc, "Error while saving settings!" );
     222       
     223        closesocket( irc->fd );
    174224       
    175225        if( irc->ping_source_id > 0 )
     
    291341}
    292342
    293 int irc_process( irc_t *irc )
    294 {
    295         char **lines, *temp;   
     343void irc_process( irc_t *irc )
     344{
     345        char **lines, *temp, **cmd;
    296346        int i;
    297347
    298         if( irc->readbuffer != NULL ) {
    299                 lines = irc_tokenize(irc->readbuffer );
    300                 for( i = 0; *lines[i] != '\0'; i++ ) {
    301                         if( lines[i+1] == NULL ) {
     348        if( irc->readbuffer != NULL )
     349        {
     350                lines = irc_tokenize( irc->readbuffer );
     351               
     352                for( i = 0; *lines[i] != '\0'; i ++ )
     353                {
     354                        if( lines[i+1] == NULL )
     355                        {
    302356                                temp = g_strdup( lines[i] );
    303357                                g_free( irc->readbuffer );
    304358                                irc->readbuffer = temp;
    305                                 i++;
     359                                i ++;
    306360                                break;
    307361                        }                       
    308                         if (!irc_process_line(irc, lines[i])) {
     362                       
     363                        if( ( cmd = irc_parse_line( lines[i] ) ) == NULL )
     364                                continue;
     365                        irc_exec( irc, cmd );
     366                       
     367                        g_free( cmd );
     368                       
     369                        /* Shouldn't really happen, but just in case... */
     370                        if( !g_slist_find( irc_connection_list, irc ) )
     371                        {
    309372                                g_free( lines );
    310                                 return 0;
     373                                return;
    311374                        }
    312375                }
    313                 if(lines[i]!=NULL) {
    314                         g_free(irc->readbuffer);
    315                         irc->readbuffer=NULL;   
    316                 }
     376               
     377                if( lines[i] != NULL )
     378                {
     379                        g_free( irc->readbuffer );
     380                        irc->readbuffer = NULL;
     381                }
     382               
    317383                g_free( lines );
    318384        }
    319         return 1;       
    320385}
    321386
     
    326391
    327392        /* Count the number of elements we're gonna need. */
    328         for(i=0, j=1; buffer[i]!='\0'; i++ ) {
    329                 if(buffer[i]=='\n' )
    330                         if(buffer[i+1]!='\r' && buffer[i+1]!='\n')
    331                                 j++;
     393        for( i = 0, j = 1; buffer[i] != '\0'; i ++ )
     394        {
     395                if( buffer[i] == '\n' )
     396                        if( buffer[i+1] != '\r' && buffer[i+1] != '\n' )
     397                                j ++;
    332398        }
    333399       
    334400        /* Allocate j+1 elements. */
    335         lines=g_new (char *, j+1);
     401        lines = g_new( char *, j + 1 );
    336402       
    337403        /* NULL terminate our list. */
    338         lines[j]=NULL;
    339        
    340         lines[0]=buffer;
     404        lines[j] = NULL;
     405       
     406        lines[0] = buffer;
    341407       
    342408        /* Split the buffer in several strings, using \r\n as our seperator, where \r is optional.
    343409         * Although this is not in the RFC, some braindead ircds (newnet's) use this, so some clients might too.
    344410         */
    345         for( i=0, j=0; buffer[i]!='\0'; i++) {
    346                 if(buffer[i]=='\n') {
    347                         buffer[i]='\0';
    348 
    349                         /* We dont want to read 1 byte before our buffer
    350                          * and (in rare cases) generate a SIGSEGV.
    351                          */
    352                         if(i!=0)
    353                                 if(buffer[i-1]=='\r')
    354                                         buffer[i-1]='\0';
    355                         if(buffer[i+1]!='\r'&&buffer[i+1]!='\n')
    356                                 lines[++j]=buffer+i+1;
    357                 }
    358         }
    359 
    360         return(lines);
    361 }
    362 
    363 int irc_process_line( irc_t *irc, char *line )
     411        for( i = 0, j = 0; buffer[i] != '\0'; i ++)
     412        {
     413                if( buffer[i] == '\n' )
     414                {
     415                        buffer[i] = '\0';
     416                       
     417                        if( i > 0 && buffer[i-1] == '\r' )
     418                                buffer[i-1] = '\0';
     419                        if( buffer[i+1] != '\r' && buffer[i+1] != '\n' )
     420                                lines[++j] = buffer + i + 1;
     421                }
     422        }
     423       
     424        return( lines );
     425}
     426
     427char **irc_parse_line( char *line )
    364428{
    365429        int i, j;
     
    367431       
    368432        /* Move the line pointer to the start of the command, skipping spaces and the optional prefix. */
    369         if(line[0]==':') {
    370                 for(i=0; line[i]!=32; i++);
    371                 line=line+i;
    372         }
    373         for(i=0; line[i]==32; i++);
    374         line=line+i;
    375 
     433        if( line[0] == ':' )
     434        {
     435                for( i = 0; line[i] != ' '; i ++ );
     436                line = line + i;
     437        }
     438        for( i = 0; line[i] == ' '; i ++ );
     439        line = line + i;
     440       
    376441        /* If we're already at the end of the line, return. If not, we're going to need at least one element. */
    377         if(line[0]=='\0')
    378                 return 1;
    379         else
    380                 j=1;   
    381        
    382         /* Count the number of char **cmd elements we're going to need. */     
    383         for(i=0; line[i]!='\0'; i++) {
    384                 if((line[i]==32) && (line[i+1]!=32) && (line[i+1]!='\0') && (line[i+1]!=':'))           
    385                         j++;
    386                 else if((line[i]==':') && (line[i+1]!='\0') && (line[i-1]==32)) {
    387                         j++;
    388                         break;
    389                 }
     442        if( line[0] == '\0')
     443                return NULL;
     444       
     445        /* Count the number of char **cmd elements we're going to need. */
     446        j = 1;
     447        for( i = 0; line[i] != '\0'; i ++ )
     448        {
     449                if( line[i] == ' ' )
     450                {
     451                        j ++;
    390452                       
     453                        if( line[i+1] == ':' )
     454                                break;
     455                }
    391456        }       
    392457
    393458        /* Allocate the space we need. */
    394         cmd=g_new(char *, j+1);
    395         cmd[j]=NULL;
     459        cmd = g_new( char *, j + 1 );
     460        cmd[j] = NULL;
    396461       
    397462        /* Do the actual line splitting, format is:
     
    400465         */
    401466
    402         cmd[0]=line;
    403         for(i=0, j=0; line[i]!='\0'; i++) {
    404                 if((line[i]==32)) {
    405                         line[i]='\0';
    406                         if((line[i+1]!=32) && (line[i+1]!='\0') && (line[i+1]!=':'))           
    407                                 cmd[++j]=line+i+1;
    408                 }
    409                 else if((line[i]==':') && (line[i+1]!='\0') && (line[i-1]=='\0')) {
    410                         cmd[++j]=line+i+1;
    411                         break;
    412                 }
    413         }
    414        
    415         i=irc_exec(irc, cmd);
    416         g_free(cmd);
    417 
    418         return(i);     
    419 }
    420 
    421 int irc_exec( irc_t *irc, char **cmd )
    422 {       
    423         int i;
    424 
    425         if( (global.conf)->authmode == AUTHMODE_CLOSED && irc->status < USTATUS_AUTHORIZED )
    426         {
    427                 if( g_strcasecmp( cmd[0], "PASS" ) == 0 )
    428                 {
    429                         if( !cmd[1] )
     467        cmd[0] = line;
     468        for( i = 0, j = 0; line[i] != '\0'; i ++ )
     469        {
     470                if( line[i] == ' ' )
     471                {
     472                        line[i] = '\0';
     473                        cmd[++j] = line + i + 1;
     474                       
     475                        if( line[i+1] == ':' )
    430476                        {
    431                                 irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
     477                                cmd[j] ++;
     478                                break;
    432479                        }
    433                         else if( strcmp( cmd[1], (global.conf)->auth_pass ) == 0 )
    434                         {
    435                                 irc->status = USTATUS_AUTHORIZED;
    436                         }
    437                         else
    438                         {
    439                                 irc_reply( irc, 464, ":Nope, maybe you should try it again..." );
    440                         }
    441                 }
    442                 else
    443                 {
    444                         irc_reply( irc, 464, ":Uhh, fine, but I want the password first." );
    445                 }
    446                
    447                 return( 1 );
    448         }
    449        
    450         if( g_strcasecmp( cmd[0], "USER" ) == 0 )
    451         {
    452                 if( !( cmd[1] && cmd[2] && cmd[3] && cmd[4] ) )
    453                 {
    454                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    455                 }
    456                 else if( irc->user )
    457                 {
    458                         irc_reply( irc, 462, ":You can't change your nick/userinfo" );
    459                 }
    460                 else
    461                 {
    462                         irc->user = g_strdup( cmd[1] );
    463                         irc->realname = g_strdup( cmd[4] );
    464                         if( irc->nick ) irc_login( irc );
    465                 }
    466                 return( 1 );
    467         }
    468         else if( g_strcasecmp( cmd[0], "NICK" ) == 0 )
    469         {
    470                 if( !cmd[1] )
    471                 {
    472                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    473                 }
    474                 else if( irc->nick )
    475                 {
    476                         irc_reply( irc, 438, ":The hand of the deity is upon thee, thy nick may not change" );
    477                 }
    478                 /* This is not clean, but for now it'll have to be like this... */
    479                 else if( ( nick_cmp( cmd[1], irc->mynick ) == 0 ) || ( nick_cmp( cmd[1], NS_NICK ) == 0 ) )
    480                 {
    481                         irc_reply( irc, 433, ":This nick is already in use" );
    482                 }
    483                 else if( !nick_ok( cmd[1] ) )
    484                 {
    485                         /* [SH] Invalid characters. */
    486                         irc_reply( irc, 432, ":This nick contains invalid characters" );
    487                 }
    488                 else
    489                 {
    490                         irc->nick = g_strdup( cmd[1] );
    491                         if( irc->user ) irc_login( irc );
    492                 }
    493                 return( 1 );
    494         }
    495         else if( g_strcasecmp( cmd[0], "QUIT" ) == 0 )
    496         {
    497                 irc_write( irc, "ERROR :%s%s", cmd[1]?"Quit: ":"", cmd[1]?cmd[1]:"Client Quit" );
    498                 g_io_channel_close( irc->io_channel );
    499                 return( 0 );
    500         }
    501        
    502         if( !irc->user || !irc->nick )
    503         {
    504                 irc_reply( irc, 451, ":Register first" );
    505                 return( 1 );
    506         }
    507        
    508         if( g_strcasecmp( cmd[0], "PING" ) == 0 )
    509         {
    510                 irc_write( irc, ":%s PONG %s :%s", irc->myhost, irc->myhost, cmd[1]?cmd[1]:irc->myhost );
    511         }
    512         else if( g_strcasecmp( cmd[0], "OPER" ) == 0 )
    513         {
    514                 if( !cmd[2] )
    515                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    516                 else if( strcmp( cmd[2], global.conf->oper_pass ) == 0 )
    517                         irc_umode_set( irc, "+o", 1 );
    518                 // else
    519                         /* FIXME/TODO: Find out which reply to send now. */
    520         }
    521         else if( g_strcasecmp( cmd[0], "MODE" ) == 0 )
    522         {
    523                 if( !cmd[1] )
    524                 {
    525                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    526                 }
    527                 else if( *cmd[1] == '#' || *cmd[1] == '&' )
    528                 {
    529                         if( cmd[2] )
    530                         {
    531                                 if( *cmd[2] == '+' || *cmd[2] == '-' )
    532                                         irc_reply( irc, 477, "%s :Can't change channel modes", cmd[1] );
    533                                 else if( *cmd[2] == 'b' )
    534                                         irc_reply( irc, 368, "%s :No bans possible", cmd[1] );
    535                         }
    536                         else
    537                                 irc_reply( irc, 324, "%s +%s", cmd[1], CMODE );
    538                 }
    539                 else
    540                 {
    541                         if( nick_cmp( cmd[1], irc->nick ) == 0 )
    542                         {
    543                                 if( cmd[2] )
    544                                         irc_umode_set( irc, cmd[2], 0 );
    545                         }
    546                         else
    547                                 irc_reply( irc, 502, ":Don't touch their modes" );
    548                 }
    549         }
    550         else if( g_strcasecmp( cmd[0], "NAMES" ) == 0 )
    551         {
    552                 irc_names( irc, cmd[1]?cmd[1]:irc->channel );
    553         }
    554         else if( g_strcasecmp( cmd[0], "PART" ) == 0 )
    555         {
    556                 struct conversation *c;
    557                
    558                 if( !cmd[1] )
    559                 {
    560                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    561                 }
    562                 else if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
    563                 {
    564                         user_t *u = user_find( irc, irc->nick );
    565                        
    566                         /* Not allowed to leave control channel */
    567                         irc_part( irc, u, irc->channel );
    568                         irc_join( irc, u, irc->channel );
    569                 }
    570                 else if( ( c = conv_findchannel( cmd[1] ) ) )
    571                 {
    572                         user_t *u = user_find( irc, irc->nick );
    573                        
    574                         irc_part( irc, u, c->channel );
    575                        
    576                         if( c->gc && c->gc->prpl )
    577                         {
    578                                 c->joined = 0;
    579                                 c->gc->prpl->chat_leave( c->gc, c->id );
    580                         }
    581                 }
    582                 else
    583                 {
    584                         irc_reply( irc, 403, "%s :No such channel", cmd[1] );
    585                 }
    586         }
    587         else if( g_strcasecmp( cmd[0], "JOIN" ) == 0 )
    588         {
    589                 if( !cmd[1] )
    590                 {
    591                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    592                 }
    593                 else if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
    594                         ; /* Dude, you're already there...
    595                              RFC doesn't have any reply for that though? */
    596                 else if( cmd[1] )
    597                 {
    598                         if( ( cmd[1][0] == '#' || cmd[1][0] == '&' ) && cmd[1][1] )
    599                         {
    600                                 user_t *u = user_find( irc, cmd[1] + 1 );
    601                                
    602                                 if( u && u->gc && u->gc->prpl && u->gc->prpl->chat_open )
    603                                 {
    604                                         irc_reply( irc, 403, "%s :Initializing groupchat in a different channel", cmd[1] );
    605                                        
    606                                         if( !u->gc->prpl->chat_open( u->gc, u->handle ) )
    607                                         {
    608                                                 irc_usermsg( irc, "Could not open a groupchat with %s, maybe you don't have a connection to him/her yet?", u->nick );
    609                                         }
    610                                 }
    611                                 else
    612                                 {
    613                                         irc_reply( irc, 403, "%s :Groupchats are not possible with %s", cmd[1], cmd[1]+1 );
    614                                 }
    615                         }
    616                         else
    617                         {
    618                                 irc_reply( irc, 403, "%s :No such channel", cmd[1] );
    619                         }
    620                 }
    621         }
    622         else if( g_strcasecmp( cmd[0], "INVITE" ) == 0 )
    623         {
    624                 if( cmd[1] && cmd[2] )
    625                         irc_invite( irc, cmd[1], cmd[2] );
    626                 else
    627                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    628         }
    629         else if( g_strcasecmp( cmd[0], "PRIVMSG" ) == 0 || g_strcasecmp( cmd[0], "NOTICE" ) == 0 )
    630         {
    631                 if( !cmd[1] )
    632                 {
    633                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    634                 }
    635                 else if ( !cmd[2] )
    636                 {
    637                         irc_reply( irc, 412, ":No text to send" );
    638                 }
    639                 else if ( irc->nick && g_strcasecmp( cmd[1], irc->nick ) == 0 )
    640                 {
    641                         irc_write( irc, ":%s!%s@%s %s %s :%s", irc->nick, irc->user, irc->host, cmd[0], cmd[1], cmd[2] );
    642                 }
    643                 else
    644                 {
    645                         if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
    646                         {
    647                                 unsigned int i;
    648                                 char *t = set_getstr( irc, "default_target" );
    649                                
    650                                 if( g_strcasecmp( t, "last" ) == 0 && irc->last_target )
    651                                         cmd[1] = irc->last_target;
    652                                 else if( g_strcasecmp( t, "root" ) == 0 )
    653                                         cmd[1] = irc->mynick;
    654                                
    655                                 for( i = 0; i < strlen( cmd[2] ); i ++ )
    656                                 {
    657                                         if( cmd[2][i] == ' ' ) break;
    658                                         if( cmd[2][i] == ':' || cmd[2][i] == ',' )
    659                                         {
    660                                                 cmd[1] = cmd[2];
    661                                                 cmd[2] += i;
    662                                                 *cmd[2] = 0;
    663                                                 while( *(++cmd[2]) == ' ' );
    664                                                 break;
    665                                         }
    666                                 }
    667                                
    668                                 irc->is_private = 0;
    669                                
    670                                 if( cmd[1] != irc->last_target )
    671                                 {
    672                                         if( irc->last_target )
    673                                                 g_free( irc->last_target );
    674                                         irc->last_target = g_strdup( cmd[1] );
    675                                 }
    676                         }
    677                         else
    678                         {
    679                                 irc->is_private = 1;
    680                         }
    681                         irc_send( irc, cmd[1], cmd[2], ( g_strcasecmp( cmd[0], "NOTICE" ) == 0 ) ? IM_FLAG_AWAY : 0 );
    682                 }
    683         }
    684         else if( g_strcasecmp( cmd[0], "WHO" ) == 0 )
    685         {
    686                 irc_who( irc, cmd[1] );
    687         }
    688         else if( g_strcasecmp( cmd[0], "USERHOST" ) == 0 )
    689         {
    690                 user_t *u;
    691                
    692                 if( !cmd[1] )
    693                 {
    694                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    695                 }
    696                 /* [TV] Usable USERHOST-implementation according to
    697                         RFC1459. Without this, mIRC shows an error
    698                         while connecting, and the used way of rejecting
    699                         breaks standards.
    700                 */
    701                
    702                 for( i = 1; cmd[i]; i ++ )
    703                         if( ( u = user_find( irc, cmd[i] ) ) )
    704                         {
    705                                 if( u->online && u->away )
    706                                         irc_reply( irc, 302, ":%s=-%s@%s", u->nick, u->user, u->host );
    707                                 else
    708                                         irc_reply( irc, 302, ":%s=+%s@%s", u->nick, u->user, u->host );
    709                         }
    710         }
    711         else if( g_strcasecmp( cmd[0], "ISON" ) == 0 )
    712         {
    713                 user_t *u;
    714                 char buff[IRC_MAX_LINE];
    715                 int lenleft;
    716                
    717                 buff[0] = '\0';
    718                
    719                 /* [SH] Leave room for : and \0 */
    720                 lenleft = IRC_MAX_LINE - 2;
    721                
    722                 for( i = 1; cmd[i]; i ++ )
    723                 {
    724                         if( ( u = user_find( irc, cmd[i] ) ) && u->online )
    725                         {
    726                                 /* [SH] Make sure we don't use too much buffer space. */
    727                                 lenleft -= strlen( u->nick ) + 1;
    728                                
    729                                 if( lenleft < 0 )
    730                                 {
    731                                         break;
    732                                 }
    733                                
    734                                 /* [SH] Add the nick to the buffer. Note
    735                                  * that an extra space is always added. Even
    736                                  * if it's the last nick in the list. Who
    737                                  * cares?
    738                                  */
    739                                
    740                                 strcat( buff, u->nick );
    741                                 strcat( buff, " " );
    742                         }
    743                 }
    744                
    745                 /* [WvG] Well, maybe someone cares, so why not remove it? */
    746                 if( strlen( buff ) > 0 )
    747                         buff[strlen(buff)-1] = '\0';
    748                
    749                 /* [SH] By the way, that really *was* WvG talking. */
    750                 /* [WvG] Really? */
    751                 /* [SH] Yeah... But *this* is WvG talking too. ;-P */
    752                 /* [WvG] *sigh* */
    753                
    754                 irc_reply( irc, 303, ":%s", buff );
    755         }
    756         else if( g_strcasecmp( cmd[0], "WATCH" ) == 0 )
    757         {
    758                 /* Obviously we could also mark a user structure as being
    759                    watched, but what if the WATCH command is sent right
    760                    after connecting? The user won't exist yet then... */
    761                 for( i = 1; cmd[i]; i ++ )
    762                 {
    763                         char *nick;
    764                         user_t *u;
    765                        
    766                         if( !cmd[i][0] || !cmd[i][1] )
    767                                 break;
    768                        
    769                         nick = g_strdup( cmd[i] + 1 );
    770                         nick_lc( nick );
    771                        
    772                         u = user_find( irc, nick );
    773                        
    774                         if( cmd[i][0] == '+' )
    775                         {
    776                                 if( !g_hash_table_lookup( irc->watches, nick ) )
    777                                         g_hash_table_insert( irc->watches, nick, nick );
    778                                
    779                                 if( u && u->online )
    780                                         irc_reply( irc, 604, "%s %s %s %d :%s", u->nick, u->user, u->host, time( NULL ), "is online" );
    781                                 else
    782                                         irc_reply( irc, 605, "%s %s %s %d :%s", nick, "*", "*", time( NULL ), "is offline" );
    783                         }
    784                         else if( cmd[i][0] == '-' )
    785                         {
    786                                 gpointer okey, ovalue;
    787                                
    788                                 if( g_hash_table_lookup_extended( irc->watches, nick, &okey, &ovalue ) )
    789                                 {
    790                                         g_free( okey );
    791                                         g_hash_table_remove( irc->watches, okey );
    792                                        
    793                                         irc_reply( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" );
    794                                 }
    795                         }
    796                 }
    797         }
    798         else if( g_strcasecmp( cmd[0], "TOPIC" ) == 0 )
    799         {
    800                 if( cmd[1] && cmd[2] )
    801                         irc_reply( irc, 482, "%s :Cannot change topic", cmd[1] );
    802                 else if( cmd[1] )
    803                         irc_topic( irc, cmd[1] );
    804                 else
    805                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    806         }
    807         else if( g_strcasecmp( cmd[0], "AWAY" ) == 0 )
    808         {
    809                 irc_away( irc, cmd[1] );
    810         }
    811         else if( g_strcasecmp( cmd[0], "WHOIS" ) == 0 )
    812         {
    813                 if( cmd[1] )
    814                 {
    815                         irc_whois( irc, cmd[1] );
    816                 }
    817                 else
    818                 {
    819                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    820                 }
    821         }
    822         else if( g_strcasecmp( cmd[0], "WHOWAS" ) == 0 )
    823         {
    824                 /* For some reason irssi tries a whowas when whois fails. We can
    825                    ignore this, but then the user never gets a "user not found"
    826                    message from irssi which is a bit annoying. So just respond
    827                    with not-found and irssi users will get better error messages */
    828                
    829                 if( cmd[1] )
    830                 {
    831                         irc_reply( irc, 406, "%s :Nick does not exist", cmd[1] );
    832                         irc_reply( irc, 369, "%s :End of WHOWAS", cmd[1] );
    833                 }
    834                 else
    835                 {
    836                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    837                 }
    838         }
    839         else if( ( g_strcasecmp( cmd[0], "NICKSERV" ) == 0 ) || ( g_strcasecmp( cmd[0], "NS" ) == 0 ) )
    840         {
    841                 /* [SH] This aliases the NickServ command to PRIVMSG root */
    842                 /* [TV] This aliases the NS command to PRIVMSG root as well */
    843                 root_command( irc, cmd + 1 );
    844         }
    845         else if( g_strcasecmp( cmd[0], "MOTD" ) == 0 )
    846         {
    847                 irc_motd( irc );
    848         }
    849         else if( g_strcasecmp( cmd[0], "PONG" ) == 0 )
    850         {
    851                 /* We could check the value we get back from the user, but in
    852                    fact we don't care, we're just happy he's still alive. */
    853                 irc->last_pong = gettime();
    854                 irc->pinging = 0;
    855         }
    856         else if( g_strcasecmp( cmd[0], "COMPLETIONS" ) == 0 )
    857         {
    858                 user_t *u = user_find( irc, irc->mynick );
    859                 help_t *h;
    860                 set_t *s;
    861                 int i;
    862                
    863                 irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", "OK" );
    864                
    865                 for( i = 0; commands[i].command; i ++ )
    866                         irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", commands[i].command );
    867                
    868                 for( h = global.help; h; h = h->next )
    869                         irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS help ", h->string );
    870                
    871                 for( s = irc->set; s; s = s->next )
    872                         irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS set ", s->key );
    873                
    874                 irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", "END" );
    875         }
    876         else if( set_getint( irc, "debug" ) )
    877         {
    878                 irc_usermsg( irc, "\002--- Unknown command:" );
    879                 for( i = 0; cmd[i]; i ++ ) irc_usermsg( irc, "%s", cmd[i] );
    880                 irc_usermsg( irc, "\002--------------------" );
    881         }
    882        
    883         return( 1 );
     480                }
     481        }
     482       
     483        return cmd;
     484}
     485
     486char *irc_build_line( char **cmd )
     487{
     488        int i, len;
     489        char *s;
     490       
     491        if( cmd[0] == NULL )
     492                return NULL;
     493       
     494        len = 1;
     495        for( i = 0; cmd[i]; i ++ )
     496                len += strlen( cmd[i] ) + 1;
     497       
     498        if( strchr( cmd[i-1], ' ' ) != NULL )
     499                len ++;
     500       
     501        s = g_new0( char, len + 1 );
     502        for( i = 0; cmd[i]; i ++ )
     503        {
     504                if( cmd[i+1] == NULL && strchr( cmd[i], ' ' ) != NULL )
     505                        strcat( s, ":" );
     506               
     507                strcat( s, cmd[i] );
     508               
     509                if( cmd[i+1] )
     510                        strcat( s, " " );
     511        }
     512        strcat( s, "\r\n" );
     513       
     514        return s;
    884515}
    885516
     
    1040671}
    1041672
    1042 void irc_who( irc_t *irc, char *channel )
    1043 {
    1044         user_t *u = irc->users;
    1045         struct conversation *c;
    1046         GList *l;
    1047        
    1048         if( !channel || *channel == '0' || *channel == '*' || !*channel )
    1049                 while( u )
    1050                 {
    1051                         irc_reply( irc, 352, "%s %s %s %s %s %c :0 %s", u->online ? irc->channel : "*", u->user, u->host, irc->myhost, u->nick, u->online ? ( u->away ? 'G' : 'H' ) : 'G', u->realname );
    1052                         u = u->next;
    1053                 }
    1054         else if( g_strcasecmp( channel, irc->channel ) == 0 )
    1055                 while( u )
    1056                 {
    1057                         if( u->online )
    1058                                 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 );
    1059                         u = u->next;
    1060                 }
    1061         else if( ( c = conv_findchannel( channel ) ) )
    1062                 for( l = c->in_room; l; l = l->next )
    1063                 {
    1064                         if( ( u = user_findhandle( c->gc, l->data ) ) )
    1065                                 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 );
    1066                 }
    1067         else if( ( u = user_find( irc, channel ) ) )
    1068                 irc_reply( irc, 352, "%s %s %s %s %s %c :0 %s", channel, u->user, u->host, irc->myhost, u->nick, u->online ? ( u->away ? 'G' : 'H' ) : 'G', u->realname );
    1069        
    1070         irc_reply( irc, 315, "%s :End of /WHO list.", channel?channel:"**" );
     673int irc_check_login( irc_t *irc )
     674{
     675        if( irc->user && irc->nick )
     676        {
     677                if( global.conf->authmode == AUTHMODE_CLOSED && irc->status < USTATUS_AUTHORIZED )
     678                {
     679                        irc_reply( irc, 464, ":This server is password-protected." );
     680                        return 0;
     681                }
     682                else
     683                {
     684                        irc_login( irc );
     685                        return 1;
     686                }
     687        }
     688        else
     689        {
     690                /* More information needed. */
     691                return 0;
     692        }
    1071693}
    1072694
     
    1103725        u->realname = g_strdup( irc->realname );
    1104726        u->online = 1;
    1105 //      u->send_handler = msg_echo;
    1106727        irc_spawn( irc, u );
    1107728       
    1108729        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." );
     730       
     731        if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON )
     732                ipc_to_master_str( "CLIENT %s %s :%s\r\n", irc->host, irc->nick, irc->realname );
    1109733       
    1110734        irc->status = USTATUS_LOGGED_IN;
     
    1159783                }
    1160784                irc_reply( irc, 376, ":End of MOTD" );
    1161                 closesocket( fd );
     785                close( fd );
    1162786        }
    1163787}
     
    1180804}
    1181805
    1182 void irc_whois( irc_t *irc, char *nick )
    1183 {
    1184         user_t *u = user_find( irc, nick );
    1185        
    1186         if( u )
    1187         {
    1188                 irc_reply( irc, 311, "%s %s %s * :%s", u->nick, u->user, u->host, u->realname );
    1189                
    1190                 if( u->gc )
    1191                         irc_reply( irc, 312, "%s %s.%s :%s network", u->nick, u->gc->user->username,
    1192                                    *u->gc->user->proto_opt[0] ? u->gc->user->proto_opt[0] : "", u->gc->prpl->name );
    1193                 else
    1194                         irc_reply( irc, 312, "%s %s :%s", u->nick, irc->myhost, IRCD_INFO );
    1195                
    1196                 if( !u->online )
    1197                         irc_reply( irc, 301, "%s :%s", u->nick, "User is offline" );
    1198                 else if( u->away )
    1199                         irc_reply( irc, 301, "%s :%s", u->nick, u->away );
    1200                
    1201                 irc_reply( irc, 318, "%s :End of /WHOIS list", nick );
    1202         }
    1203         else
    1204         {
    1205                 irc_reply( irc, 401, "%s :Nick does not exist", nick );
    1206         }
    1207 }
    1208 
    1209 
    1210806void irc_umode_set( irc_t *irc, char *s, int allow_priv )
    1211807{
     
    1237833}
    1238834
    1239 int irc_away( irc_t *irc, char *away )
    1240 {
    1241         user_t *u = user_find( irc, irc->nick );
    1242         GSList *c = get_connections();
    1243        
    1244         if( !u ) return( 0 );
    1245        
    1246         if( away && *away )
    1247         {
    1248                 int i, j;
    1249                
    1250                 /* Copy away string, but skip control chars. Mainly because
    1251                    Jabber really doesn't like them. */
    1252                 u->away = g_malloc( strlen( away ) + 1 );
    1253                 for( i = j = 0; away[i]; i ++ )
    1254                         if( ( u->away[j] = away[i] ) >= ' ' )
    1255                                 j ++;
    1256                 u->away[j] = 0;
    1257                
    1258                 irc_reply( irc, 306, ":You're now away: %s", u->away );
    1259                 /* irc_umode_set( irc, irc->myhost, "+a" ); */
    1260         }
    1261         else
    1262         {
    1263                 if( u->away ) g_free( u->away );
    1264                 u->away = NULL;
    1265                 /* irc_umode_set( irc, irc->myhost, "-a" ); */
    1266                 irc_reply( irc, 305, ":Welcome back" );
    1267         }
    1268        
    1269         while( c )
    1270         {
    1271                 if( ((struct gaim_connection *)c->data)->flags & OPT_LOGGED_IN )
    1272                         proto_away( c->data, u->away );
    1273                
    1274                 c = c->next;
    1275         }
    1276        
    1277         return( 1 );
    1278 }
    1279 
    1280835void irc_spawn( irc_t *irc, user_t *u )
    1281836{
     
    1329884        }
    1330885        g_free( nick );
    1331 }
    1332 
    1333 void irc_invite( irc_t *irc, char *nick, char *channel )
    1334 {
    1335         struct conversation *c = conv_findchannel( channel );
    1336         user_t *u = user_find( irc, nick );
    1337        
    1338         if( u && c && ( u->gc == c->gc ) )
    1339                 if( c->gc && c->gc->prpl && c->gc->prpl->chat_invite )
    1340                 {
    1341                         c->gc->prpl->chat_invite( c->gc, c->id, "", u->handle );
    1342                         irc_reply( irc, 341, "%s %s", nick, channel );
    1343                         return;
    1344                 }
    1345        
    1346         irc_reply( irc, 482, "%s :Invite impossible; User/Channel non-existent or incompatible", channel );
    1347886}
    1348887
     
    1435974               
    1436975                if( u->send_handler )
    1437                         return( u->send_handler( irc, u, s, flags ) );
     976                {
     977                        u->send_handler( irc, u, s, flags );
     978                        return 1;
     979                }
    1438980        }
    1439981        else if( c && c->gc && c->gc->prpl )
     
    14611003}
    14621004
    1463 int buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags )
    1464 {
    1465         if( !u || !u->gc ) return( 0 );
     1005void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags )
     1006{
     1007        if( !u || !u->gc ) return;
    14661008       
    14671009        if( set_getint( irc, "buddy_sendbuffer" ) && set_getint( irc, "buddy_sendbuffer_delay" ) > 0 )
     
    14991041                        g_source_remove( u->sendbuf_timer );
    15001042                u->sendbuf_timer = g_timeout_add( delay, buddy_send_handler_delayed, u );
    1501                
    1502                 return( 1 );
    15031043        }
    15041044        else
    15051045        {
    1506                 return( serv_send_im( irc, u, msg, flags ) );
     1046                serv_send_im( irc, u, msg, flags );
    15071047        }
    15081048}
     
    16091149        if( rv > 0 )
    16101150        {
    1611                 irc_write( irc, "ERROR :Closing Link: Ping Timeout: %d seconds", rv );
    1612                 irc_free( irc );
     1151                irc_abort( irc, 0, "Ping Timeout: %d seconds", rv );
    16131152                return FALSE;
    16141153        }
  • irc.h

    r8e419cb ra4dc9f7  
    3333#define IRC_PING_STRING "PinglBee"
    3434
    35 #define UMODES "ias"
     35#define UMODES "iasw"
    3636#define UMODES_PRIV "Ro"
    3737#define CMODES "nt"
     
    4141typedef enum
    4242{
    43         USTATUS_OFFLINE,
     43        USTATUS_OFFLINE = 0,
    4444        USTATUS_AUTHORIZED,
    4545        USTATUS_LOGGED_IN,
    46         USTATUS_IDENTIFIED
     46        USTATUS_IDENTIFIED,
     47        USTATUS_SHUTDOWN = -1
    4748} irc_status_t;
    4849
     
    104105
    105106irc_t *irc_new( int fd );
     107void irc_abort( irc_t *irc, int immed, char *format, ... );
    106108void irc_free( irc_t *irc );
    107109
    108 int irc_exec( irc_t *irc, char **cmd );
    109 int irc_process( irc_t *irc );
    110 int irc_process_line( irc_t *irc, char *line );
     110void irc_exec( irc_t *irc, char **cmd );
     111void irc_process( irc_t *irc );
     112char **irc_parse_line( char *line );
     113char *irc_build_line( char **cmd );
    111114
    112115void irc_vawrite( irc_t *irc, char *format, va_list params );
     
    118121
    119122void irc_login( irc_t *irc );
     123int irc_check_login( irc_t *irc );
    120124void irc_motd( irc_t *irc );
    121125void irc_names( irc_t *irc, char *channel );
     
    130134void irc_invite( irc_t *irc, char *nick, char *channel );
    131135void irc_whois( irc_t *irc, char *nick );
    132 int irc_away( irc_t *irc, char *away );
    133136void irc_setpass( irc_t *irc, const char *pass ); /* USE WITH CAUTION! */
    134137
     
    138141int irc_noticefrom( irc_t *irc, char *nick, char *msg );
    139142
    140 int buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags );
     143void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags );
    141144
    142145#endif
  • log.c

    r8e419cb ra4dc9f7  
    3838        openlog("bitlbee", LOG_PID, LOG_DAEMON);       
    3939
    40         logoutput.informational=&log_null;
    41         logoutput.warning=&log_null;
    42         logoutput.error=&log_null;
     40        logoutput.informational = &log_null;
     41        logoutput.warning = &log_null;
     42        logoutput.error = &log_null;
    4343#ifdef DEBUG
    44         logoutput.debug=&log_null;
     44        logoutput.debug = &log_null;
    4545#endif
    4646
     
    5151        /* I know it's ugly, but it works and I didn't feel like messing with pointer to function pointers */
    5252
    53         if(level==LOGLVL_INFO) {
    54                 if(output==LOGOUTPUT_NULL)
    55                         logoutput.informational=&log_null;     
    56                 else if(output==LOGOUTPUT_IRC)
    57                         logoutput.informational=&log_irc;       
    58                 else if(output==LOGOUTPUT_SYSLOG)
    59                         logoutput.informational=&log_syslog;   
    60                 else if(output==LOGOUTPUT_CONSOLE)
    61                         logoutput.informational=&log_console;   
     53        if(level == LOGLVL_INFO) {
     54                if(output == LOGOUTPUT_NULL)
     55                        logoutput.informational = &log_null;   
     56                else if(output == LOGOUTPUT_IRC)
     57                        logoutput.informational = &log_irc;     
     58                else if(output == LOGOUTPUT_SYSLOG)
     59                        logoutput.informational = &log_syslog; 
     60                else if(output == LOGOUTPUT_CONSOLE)
     61                        logoutput.informational = &log_console;
    6262        }
    63         else if(level==LOGLVL_WARNING) {
    64                 if(output==LOGOUTPUT_NULL)
    65                         logoutput.warning=&log_null;
    66                 else if(output==LOGOUTPUT_IRC)
    67                         logoutput.warning=&log_irc;
    68                 else if(output==LOGOUTPUT_SYSLOG)
    69                         logoutput.warning=&log_syslog;
    70                 else if(output==LOGOUTPUT_CONSOLE)
    71                         logoutput.warning=&log_console;
     63        else if(level == LOGLVL_WARNING) {
     64                if(output == LOGOUTPUT_NULL)
     65                        logoutput.warning = &log_null;
     66                else if(output == LOGOUTPUT_IRC)
     67                        logoutput.warning = &log_irc;
     68                else if(output == LOGOUTPUT_SYSLOG)
     69                        logoutput.warning = &log_syslog;
     70                else if(output == LOGOUTPUT_CONSOLE)
     71                        logoutput.warning = &log_console;
    7272        }
    73         else if(level==LOGLVL_ERROR) {
    74                 if(output==LOGOUTPUT_NULL)
    75                         logoutput.error=&log_null;
    76                 else if(output==LOGOUTPUT_IRC)
    77                         logoutput.error=&log_irc;
    78                 else if(output==LOGOUTPUT_SYSLOG)
    79                         logoutput.error=&log_syslog;
    80                 else if(output==LOGOUTPUT_CONSOLE)
    81                         logoutput.error=&log_console;
     73        else if(level == LOGLVL_ERROR) {
     74                if(output == LOGOUTPUT_NULL)
     75                        logoutput.error = &log_null;
     76                else if(output == LOGOUTPUT_IRC)
     77                        logoutput.error = &log_irc;
     78                else if(output == LOGOUTPUT_SYSLOG)
     79                        logoutput.error = &log_syslog;
     80                else if(output == LOGOUTPUT_CONSOLE)
     81                        logoutput.error = &log_console;
    8282        }
    8383#ifdef DEBUG
    84         else if(level==LOGLVL_DEBUG) {
    85                 if(output==LOGOUTPUT_NULL)
    86                         logoutput.debug=&log_null;
    87                 else if(output==LOGOUTPUT_IRC)
    88                         logoutput.debug=&log_irc;
    89                 else if(output==LOGOUTPUT_SYSLOG)
    90                         logoutput.debug=&log_syslog;
    91                 else if(output==LOGOUTPUT_CONSOLE)
    92                         logoutput.debug=&log_console;
     84        else if(level == LOGLVL_DEBUG) {
     85                if(output == LOGOUTPUT_NULL)
     86                        logoutput.debug = &log_null;
     87                else if(output == LOGOUTPUT_IRC)
     88                        logoutput.debug = &log_irc;
     89                else if(output == LOGOUTPUT_SYSLOG)
     90                        logoutput.debug = &log_syslog;
     91                else if(output == LOGOUTPUT_CONSOLE)
     92                        logoutput.debug = &log_console;
    9393        }
    9494#endif
     
    106106        va_end(ap);
    107107
    108         if(level==LOGLVL_INFO)
     108        if(level == LOGLVL_INFO)
    109109                (*(logoutput.informational))(level, msgstring);
    110         if(level==LOGLVL_WARNING)
     110        if(level == LOGLVL_WARNING)
    111111                (*(logoutput.warning))(level, msgstring);
    112         if(level==LOGLVL_ERROR)
     112        if(level == LOGLVL_ERROR)
    113113                (*(logoutput.error))(level, msgstring);
    114114#ifdef DEBUG
    115         if(level==LOGLVL_DEBUG)
     115        if(level == LOGLVL_DEBUG)
    116116                (*(logoutput.debug))(level, msgstring);
    117117#endif
     
    133133
    134134static void log_irc(int level, char *message) {
    135         if(level==LOGLVL_ERROR)
     135        if(level == LOGLVL_ERROR)
    136136                irc_write_all(1, "ERROR :Error: %s", message);
    137         if(level==LOGLVL_WARNING)
     137        if(level == LOGLVL_WARNING)
    138138                irc_write_all(0, "ERROR :Warning: %s", message);
    139         if(level==LOGLVL_INFO)
     139        if(level == LOGLVL_INFO)
    140140                irc_write_all(0, "ERROR :Informational: %s", message); 
    141141#ifdef DEBUG
    142         if(level==LOGLVL_DEBUG)
     142        if(level == LOGLVL_DEBUG)
    143143                irc_write_all(0, "ERROR :Debug: %s", message); 
    144144#endif 
     
    148148
    149149static void log_syslog(int level, char *message) {
    150         if(level==LOGLVL_ERROR)
     150        if(level == LOGLVL_ERROR)
    151151                syslog(LOG_ERR, "%s", message);
    152         if(level==LOGLVL_WARNING)
     152        if(level == LOGLVL_WARNING)
    153153                syslog(LOG_WARNING, "%s", message);
    154         if(level==LOGLVL_INFO)
     154        if(level == LOGLVL_INFO)
    155155                syslog(LOG_INFO, "%s", message);
    156156#ifdef DEBUG
    157         if(level==LOGLVL_DEBUG)
     157        if(level == LOGLVL_DEBUG)
    158158                syslog(LOG_DEBUG, "%s", message);
    159159#endif
     
    162162
    163163static void log_console(int level, char *message) {
    164         if(level==LOGLVL_ERROR)
     164        if(level == LOGLVL_ERROR)
    165165                fprintf(stderr, "Error: %s\n", message);
    166         if(level==LOGLVL_WARNING)
     166        if(level == LOGLVL_WARNING)
    167167                fprintf(stderr, "Warning: %s\n", message);
    168         if(level==LOGLVL_INFO)
     168        if(level == LOGLVL_INFO)
    169169                fprintf(stdout, "Informational: %s\n", message);
    170170#ifdef DEBUG
    171         if(level==LOGLVL_DEBUG)
     171        if(level == LOGLVL_DEBUG)
    172172                fprintf(stdout, "Debug: %s\n", message);
    173173#endif
  • protocols/jabber/jabber.c

    r8e419cb ra4dc9f7  
    413413                if (jd->die)
    414414                        signoff(GJ_GC(gjc));
    415         } else if (len < 0 || errno != EAGAIN) {
     415        } else if (len == 0 || (len < 0 && (!sockerr_again() || gjc->ssl))) {
    416416                STATE_EVT(JCONN_STATE_OFF)
    417417        }
  • protocols/msn/msn.c

    r8e419cb ra4dc9f7  
    8484                {
    8585                        m = l->data;
     86               
     87                        serv_got_crap( gc, "Warning: Closing down MSN connection with unsent message to %s, you'll have to resend it.", m->who );
    8688                        g_free( m->who );
    8789                        g_free( m->text );
     
    8991                }
    9092                g_slist_free( md->msgq );
    91                
    92                 serv_got_crap( gc, "Warning: Closing down MSN connection with unsent message(s), you'll have to resend them." );
    9393        }
    9494       
  • protocols/msn/sb.c

    r8e419cb ra4dc9f7  
    213213                {
    214214                        m = l->data;
     215
    215216                        g_free( m->who );
    216217                        g_free( m->text );
     
    219220                g_slist_free( sb->msgq );
    220221               
    221                 serv_got_crap( gc, "Warning: Closing down MSN switchboard connection with unsent message(s), you'll have to resend them." );
     222                serv_got_crap( gc, "Warning: Closing down MSN switchboard connection with "
     223                                   "unsent message to %s, you'll have to resend it.",
     224                                   m->who ? m->who : "(unknown)" );
    222225        }
    223226       
  • protocols/oscar/oscar.c

    r8e419cb ra4dc9f7  
    608608                return;
    609609        }
     610        /* [WvG] Wheeeee! Who needs error checking anyway? ;-) */
    610611        read(pos->fd, m, 16);
    611612        m[16] = '\0';
  • protocols/oscar/rxqueue.c

    r8e419cb ra4dc9f7  
    353353                return -1; /* its a aim_conn_close()'d connection */
    354354
    355         if (conn->fd < 3)  /* can happen when people abuse the interface */
     355        /* KIDS, THIS IS WHAT HAPPENS IF YOU USE CODE WRITTEN FOR GUIS IN A DAEMON!
     356           
     357           And wouldn't it make sense to return something that prevents this function
     358           from being called again IMMEDIATELY (and making the program suck up all
     359           CPU time)?...
     360           
     361        if (conn->fd < 3)
    356362                return 0;
     363        */
    357364
    358365        if (conn->status & AIM_CONN_STATUS_INPROGRESS)
  • protocols/oscar/service.c

    r8e419cb ra4dc9f7  
    736736
    737737        tlvlen = aim_addtlvtochain32(&tl, 0x0006, data);
    738 
    739         printf("%d\n", tlvlen);
    740738
    741739        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 8)))
  • protocols/ssl_openssl.c

    r8e419cb ra4dc9f7  
    55  \********************************************************************/
    66
    7 /* SSL module - GnuTLS version                                          */
     7/* SSL module - OpenTLS version                                          */
    88
    99/*
     
    4141struct scd
    4242{
    43         ssl_input_function func;
     43        SslInputFunction func;
    4444        gpointer data;
    4545        int fd;
    4646        gboolean established;
    4747       
    48         int inpa;
    49         int lasterr;            /* Necessary for SSL_get_error */
    5048        SSL *ssl;
    5149        SSL_CTX *ssl_ctx;
     
    5654
    5755
    58 void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )
     56void *ssl_connect( char *host, int port, SslInputFunction func, gpointer data )
    5957{
    6058        struct scd *conn = g_new0( struct scd, 1 );
     
    9593}
    9694
    97 static void ssl_handshake( gpointer data, gint source, GaimInputCondition cond );
    98 
    9995static void ssl_connected( gpointer data, gint source, GaimInputCondition cond )
    10096{
     
    10298       
    10399        if( source == -1 )
    104                 return ssl_handshake( data, -1, cond );
     100                goto ssl_connected_failure;
    105101       
    106         /* Make it non-blocking at least during the handshake... */
    107         sock_make_nonblocking( conn->fd );
    108102        SSL_set_fd( conn->ssl, conn->fd );
    109103       
    110         return ssl_handshake( data, source, cond );
    111 }       
    112 
    113 static void ssl_handshake( gpointer data, gint source, GaimInputCondition cond )
    114 {
    115         struct scd *conn = data;
    116         int st;
    117        
    118         if( conn->inpa != -1 )
    119         {
    120                 gaim_input_remove( conn->inpa );
    121                 conn->inpa = -1;
    122         }
    123        
    124         if( ( st = SSL_connect( conn->ssl ) ) < 0 )
    125         {
    126                 conn->lasterr = SSL_get_error( conn->ssl, st );
    127                 if( conn->lasterr != SSL_ERROR_WANT_READ && conn->lasterr != SSL_ERROR_WANT_WRITE )
    128                         goto ssl_connected_failure;
    129                
    130                 conn->inpa = gaim_input_add( conn->fd, ssl_getdirection( conn ), ssl_handshake, data );
    131                 return;
    132         }
     104        if( SSL_connect( conn->ssl ) < 0 )
     105                goto ssl_connected_failure;
    133106       
    134107        conn->established = TRUE;
    135         sock_make_blocking( conn->fd );         /* For now... */
    136108        conn->func( conn->data, conn, cond );
    137109        return;
     
    155127int ssl_read( void *conn, char *buf, int len )
    156128{
    157         int st;
     129        if( !((struct scd*)conn)->established )
     130                return( 0 );
    158131       
    159         if( !((struct scd*)conn)->established )
    160         {
    161                 ssl_errno = SSL_NOHANDSHAKE;
    162                 return -1;
    163         }
    164        
    165         st = SSL_read( ((struct scd*)conn)->ssl, buf, len );
    166        
    167         ssl_errno = SSL_OK;
    168         if( st <= 0 )
    169         {
    170                 ((struct scd*)conn)->lasterr = SSL_get_error( ((struct scd*)conn)->ssl, st );
    171                 if( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_READ || ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE )
    172                         ssl_errno = SSL_AGAIN;
    173         }
    174        
    175         return st;
     132        return( SSL_read( ((struct scd*)conn)->ssl, buf, len ) );
    176133}
    177134
    178135int ssl_write( void *conn, const char *buf, int len )
    179136{
    180         int st;
     137        if( !((struct scd*)conn)->established )
     138                return( 0 );
    181139       
    182         if( !((struct scd*)conn)->established )
    183         {
    184                 ssl_errno = SSL_NOHANDSHAKE;
    185                 return -1;
    186         }
    187        
    188         st = SSL_write( ((struct scd*)conn)->ssl, buf, len );
    189        
    190         ssl_errno = SSL_OK;
    191         if( st <= 0 )
    192         {
    193                 ((struct scd*)conn)->lasterr = SSL_get_error( ((struct scd*)conn)->ssl, st );
    194                 if( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_READ || ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE )
    195                         ssl_errno = SSL_AGAIN;
    196         }
    197        
    198         return st;
     140        return( SSL_write( ((struct scd*)conn)->ssl, buf, len ) );
    199141}
    200142
     
    202144{
    203145        struct scd *conn = conn_;
    204        
    205         if( conn->inpa != -1 )
    206                 gaim_input_remove( conn->inpa );
    207146       
    208147        if( conn->established )
     
    220159        return( ((struct scd*)conn)->fd );
    221160}
    222 
    223 GaimInputCondition ssl_getdirection( void *conn )
    224 {
    225         return( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE ? GAIM_INPUT_WRITE : GAIM_INPUT_READ );
    226 }
  • protocols/yahoo/Makefile

    r8e419cb ra4dc9f7  
    1010
    1111# [SH] Program variables
    12 objects = yahoo.o crypt.o libyahoo2.o yahoo_fn.o yahoo_httplib.o yahoo_list.o yahoo_util.o
     12objects = yahoo.o crypt.o libyahoo2.o yahoo_fn.o yahoo_httplib.o yahoo_util.o
    1313
    1414CFLAGS += -Wall -DSTDC_HEADERS -DHAVE_STRING_H -DHAVE_STRCHR -DHAVE_MEMCPY -DHAVE_GLIB
  • protocols/yahoo/yahoo.c

    r8e419cb ra4dc9f7  
    189189{
    190190        struct byahoo_data *yd = (struct byahoo_data *) gc->proto_data;
    191 
     191       
    192192        gc->away = NULL;
    193 
    194         if (msg)
     193       
     194        if( msg )
    195195        {
    196196                yd->current_status = YAHOO_STATUS_CUSTOM;
    197197                gc->away = "";
    198198        }
    199         else if (state)
     199        if( state )
    200200        {
    201201                gc->away = "";
    202                 if( g_strcasecmp(state, "Available" ) == 0 )
     202                if( g_strcasecmp( state, "Available" ) == 0 )
    203203                {
    204204                        yd->current_status = YAHOO_STATUS_AVAILABLE;
     
    235235                }
    236236        }
    237         else if ( gc->is_idle )
     237        else if( gc->is_idle )
    238238                yd->current_status = YAHOO_STATUS_IDLE;
    239239        else
    240240                yd->current_status = YAHOO_STATUS_AVAILABLE;
    241241       
    242         yahoo_set_away( yd->y2_id, yd->current_status, msg, gc->away != NULL );
     242        if( yd->current_status == YAHOO_STATUS_INVISIBLE )
     243                yahoo_set_away( yd->y2_id, yd->current_status, NULL, gc->away != NULL );
     244        else
     245                yahoo_set_away( yd->y2_id, yd->current_status, msg, gc->away != NULL );
    243246}
    244247
  • protocols/yahoo/yahoo_list.h

    r8e419cb ra4dc9f7  
    2121 */
    2222
    23 /*
    24  * This is a replacement for the GList.  It only provides functions that
    25  * we use in Ayttm.  Thanks to Meredyyd from everybuddy dev for doing
    26  * most of it.
    27  */
    28 
    2923#ifndef __YLIST_H__
    3024#define __YLIST_H__
    3125
    32 #ifdef __cplusplus
    33 extern "C" {
     26/* GLib has linked list already, so I don't see why libyahoo2 has to copy this... */
     27
     28typedef GList YList;
     29
     30#define y_list_append g_list_append
     31#define y_list_concat g_list_concat
     32#define y_list_copy g_list_copy
     33#define y_list_empty g_list_empty
     34#define y_list_find g_list_find
     35#define y_list_find_custom g_list_find_custom
     36#define y_list_foreach g_list_foreach
     37#define y_list_free g_list_free
     38#define y_list_free_1 g_list_free_1
     39#define y_list_insert_sorted g_list_insert_sorted
     40#define y_list_length g_list_length
     41#define y_list_next g_list_next
     42#define y_list_nth g_list_nth
     43#define y_list_prepend g_list_prepend
     44#define y_list_remove g_list_remove
     45#define y_list_remove_link g_list_remove_link
     46#define y_list_singleton g_list_singleton
     47
    3448#endif
    35 
    36 typedef struct _YList {
    37         struct _YList *next;
    38         struct _YList *prev;
    39         void *data;
    40 } YList;
    41 
    42 typedef int (*YListCompFunc) (const void *, const void *);
    43 typedef void (*YListFunc) (void *, void *);
    44 
    45 YList *y_list_append(YList * list, void *data);
    46 YList *y_list_prepend(YList * list, void *data);
    47 YList *y_list_remove_link(YList * list, const YList * link);
    48 YList *y_list_remove(YList * list, void *data);
    49 
    50 YList *y_list_insert_sorted(YList * list, void * data, YListCompFunc comp);
    51 
    52 YList *y_list_copy(YList * list);
    53 
    54 YList *y_list_concat(YList * list, YList * add);
    55 
    56 YList *y_list_find(YList * list, const void *data);
    57 YList *y_list_find_custom(YList * list, const void *data, YListCompFunc comp);
    58 
    59 YList *y_list_nth(YList * list, int n);
    60 
    61 void y_list_foreach(YList * list, YListFunc fn, void *user_data);
    62 
    63 void y_list_free_1(YList * list);
    64 void y_list_free(YList * list);
    65 int  y_list_length(const YList * list);
    66 int  y_list_empty(const YList * list);
    67 int  y_list_singleton(const YList * list);
    68 
    69 #define y_list_next(list)       list->next
    70 
    71 #ifdef __cplusplus
    72 }
    73 #endif
    74 #endif
  • unix.c

    r8e419cb ra4dc9f7  
    2929#include "protocols/nogaim.h"
    3030#include "help.h"
     31#include "ipc.h"
    3132#include <signal.h>
    3233#include <unistd.h>
     
    3839static void sighandler( int signal );
    3940
    40 int main( int argc, char *argv[] )
     41int main( int argc, char *argv[], char **envp )
    4142{
    4243        int i = 0;
     44        char *old_cwd = NULL;
    4345        struct sigaction sig, old;
    4446       
     
    7981        else if( global.conf->runmode == RUNMODE_FORKDAEMON )
    8082        {
     83                /* In case the operator requests a restart, we need this. */
     84                old_cwd = g_malloc( 256 );
     85                if( getcwd( old_cwd, 255 ) == NULL )
     86                {
     87                        log_message( LOGLVL_WARNING, "Could not save current directory: %s", strerror( errno ) );
     88                        g_free( old_cwd );
     89                        old_cwd = NULL;
     90                }
     91               
    8192                i = bitlbee_daemon_init();
    8293                log_message( LOGLVL_INFO, "Bitlbee %s starting in forking daemon mode.", BITLBEE_VERSION );
     
    114125        g_main_run( global.loop );
    115126       
     127        if( global.restart )
     128        {
     129                char *fn = ipc_master_save_state();
     130                char **args;
     131                int n, i;
     132               
     133                chdir( old_cwd );
     134               
     135                n = 0;
     136                args = g_new0( char *, argc + 3 );
     137                args[n++] = argv[0];
     138                if( fn )
     139                {
     140                        args[n++] = "-R";
     141                        args[n++] = fn;
     142                }
     143                for( i = 1; argv[i] && i < argc; i ++ )
     144                {
     145                        if( strcmp( argv[i], "-R" ) == 0 )
     146                                i += 2;
     147                       
     148                        args[n++] = argv[i];
     149                }
     150               
     151                close( global.listen_socket );
     152               
     153                execve( args[0], args, envp );
     154        }
     155       
    116156        return( 0 );
    117157}
  • url.c

    r8e419cb ra4dc9f7  
    4040        else
    4141        {
    42                 if( g_strncasecmp( set_url, "https", i - set_url ) == 0 )
     42                if( g_strncasecmp( set_url, "http", i - set_url ) == 0 )
     43                        url->proto = PROTO_HTTP;
     44                else if( g_strncasecmp( set_url, "https", i - set_url ) == 0 )
    4345                        url->proto = PROTO_HTTPS;
    44                 else if( g_strncasecmp( set_url, "http", i - set_url ) == 0 )
    45                         url->proto = PROTO_HTTP;
    4646                else if( g_strncasecmp( set_url, "socks4", i - set_url ) == 0 )
    4747                        url->proto = PROTO_SOCKS4;
  • user.h

    r8e419cb ra4dc9f7  
    4545        int sendbuf_flags;
    4646       
    47         int (*send_handler) ( irc_t *irc, struct __USER *u, char *msg, int flags );
     47        void (*send_handler) ( irc_t *irc, struct __USER *u, char *msg, int flags );
    4848       
    4949        struct __USER *next;
Note: See TracChangeset for help on using the changeset viewer.