Changeset 55ec2d6


Ignore:
Timestamp:
2006-01-20T12:22:30Z (13 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Branches:
master
Children:
f73b969
Parents:
fc50d48 (diff), b8c2ace (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:

Merging IPC branch, it's too different from the main code to keep it
separated (and it's pretty stable now). Have fun. :-)

Files:
3 added
9 edited

Legend:

Unmodified
Added
Removed
  • Makefile

    rfc50d48 r55ec2d6  
    1010
    1111# Program variables
    12 objects = account.o bitlbee.o commands.o conf.o crypting.o help.o ini.o irc.o log.o nick.o query.o set.o storage.o storage_text.o unix.o url.o user.o util.o
     12objects = account.o bitlbee.o commands.o conf.o crypting.o help.o ini.o ipc.o irc.o irc_commands.o log.o nick.o query.o set.o storage.o storage_text.o unix.o url.o user.o util.o
    1313subdirs = protocols
    1414
  • bitlbee.c

    rfc50d48 r55ec2d6  
    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()
     
    8955                return( -1 );
    9056        }
     57       
     58        /* TIME_WAIT (?) sucks.. */
     59        i = 1;
     60        setsockopt( global.listen_socket, SOL_SOCKET, SO_REUSEADDR, &i, sizeof( i ) );
    9161       
    9262#ifdef IPV6
     
    257227}
    258228
     229gboolean bitlbee_io_new_client( GIOChannel *source, GIOCondition condition, gpointer data )
     230{
     231        size_t size = sizeof( struct sockaddr_in );
     232        struct sockaddr_in conn_info;
     233        int new_socket = accept( global.listen_socket, (struct sockaddr *) &conn_info, &size );
     234        pid_t client_pid = 0;
     235       
     236        if( global.conf->runmode == RUNMODE_FORKDAEMON )
     237        {
     238                int fds[2];
     239               
     240                if( socketpair( AF_UNIX, SOCK_STREAM, 0, fds ) == -1 )
     241                {
     242                        log_message( LOGLVL_WARNING, "Could not create IPC socket for client: %s", strerror( errno ) );
     243                        fds[0] = fds[1] = -1;
     244                }
     245               
     246                sock_make_nonblocking( fds[0] );
     247                sock_make_nonblocking( fds[1] );
     248               
     249                client_pid = fork();
     250               
     251                if( client_pid > 0 && fds[0] != -1 )
     252                {
     253                        struct bitlbee_child *child;
     254                       
     255                        child = g_new0( struct bitlbee_child, 1 );
     256                        child->pid = client_pid;
     257                        child->ipc_fd = fds[0];
     258                        child->ipc_inpa = gaim_input_add( child->ipc_fd, GAIM_INPUT_READ, ipc_master_read, child );
     259                        child_list = g_slist_append( child_list, child );
     260                       
     261                        log_message( LOGLVL_INFO, "Creating new subprocess with pid %d.", client_pid );
     262                       
     263                        /* Close some things we don't need in the parent process. */
     264                        close( new_socket );
     265                        close( fds[1] );
     266                }
     267                else if( client_pid == 0 )
     268                {
     269                        irc_t *irc;
     270                       
     271                        /* Close the listening socket, we're a client. */
     272                        close( global.listen_socket );
     273                        g_source_remove( global.listen_watch_source_id );
     274                       
     275                        /* Make the connection. */
     276                        irc = irc_new( new_socket );
     277                       
     278                        /* We can store the IPC fd there now. */
     279                        global.listen_socket = fds[1];
     280                        global.listen_watch_source_id = gaim_input_add( fds[1], GAIM_INPUT_READ, ipc_child_read, irc );
     281                       
     282                        close( fds[0] );
     283                       
     284                        ipc_master_free_all();
     285                }
     286        }
     287        else
     288        {
     289                log_message( LOGLVL_INFO, "Creating new connection with fd %d.", new_socket );
     290                irc_new( new_socket );
     291        }
     292       
     293        return TRUE;
     294}
     295
    259296void bitlbee_shutdown( gpointer data )
    260297{
  • bitlbee.h

    rfc50d48 r55ec2d6  
    112112#include "sock.h"
    113113
    114 typedef struct global_t {
     114typedef struct global {
     115        /* In forked mode, child processes store the fd of the IPC socket here. */
    115116        int listen_socket;
    116117        gint listen_watch_source_id;
  • commands.c

    rfc50d48 r55ec2d6  
    3232#include <string.h>
    3333
    34 const command_t commands[] = {
    35         { "help",           0, cmd_help },
    36         { "identify",       1, cmd_identify },
    37         { "register",       1, cmd_register },
    38         { "drop",           1, cmd_drop },
    39         { "account",        1, cmd_account },
    40         { "add",            2, cmd_add },
    41         { "info",           1, cmd_info },
    42         { "rename",         2, cmd_rename },
    43         { "remove",         1, cmd_remove },
    44         { "block",          1, cmd_block },
    45         { "allow",          1, cmd_allow },
    46         { "save",           0, cmd_save },
    47         { "set",            0, cmd_set },
    48         { "yes",            0, cmd_yesno },
    49         { "no",             0, cmd_yesno },
    50         { "blist",          0, cmd_blist },
    51         { "nick",           1, cmd_nick },
    52         { "import_buddies", 1, cmd_import_buddies },
    53         { "qlist",          0, cmd_qlist },
    54         { NULL }
    55 };
    56 
    5734int root_command_string( irc_t *irc, user_t *u, char *command, int flags )
    5835{
     
    11491}
    11592
    116 int cmd_help( irc_t *irc, char **cmd )
     93static int cmd_help( irc_t *irc, char **cmd )
    11794{
    11895        char param[80];
     
    143120}
    144121
    145 int cmd_identify( irc_t *irc, char **cmd )
     122static int cmd_identify( irc_t *irc, char **cmd )
    146123{
    147124        storage_status_t status = storage_load( irc->nick, cmd[1], irc );
     
    166143}
    167144
    168 int cmd_register( irc_t *irc, char **cmd )
     145static int cmd_register( irc_t *irc, char **cmd )
    169146{
    170147        if( global.conf->authmode == AUTHMODE_REGISTERED )
     
    193170}
    194171
    195 int cmd_drop( irc_t *irc, char **cmd )
     172static int cmd_drop( irc_t *irc, char **cmd )
    196173{
    197174        storage_status_t status;
     
    217194}
    218195
    219 int cmd_account( irc_t *irc, char **cmd )
     196static int cmd_account( irc_t *irc, char **cmd )
    220197{
    221198        account_t *a;
     
    377354}
    378355
    379 int cmd_add( irc_t *irc, char **cmd )
     356static int cmd_add( irc_t *irc, char **cmd )
    380357{
    381358        account_t *a;
     
    417394}
    418395
    419 int cmd_info( irc_t *irc, char **cmd )
     396static int cmd_info( irc_t *irc, char **cmd )
    420397{
    421398        struct gaim_connection *gc;
     
    454431}
    455432
    456 int cmd_rename( irc_t *irc, char **cmd )
     433static int cmd_rename( irc_t *irc, char **cmd )
    457434{
    458435        user_t *u;
     
    495472}
    496473
    497 int cmd_remove( irc_t *irc, char **cmd )
     474static int cmd_remove( irc_t *irc, char **cmd )
    498475{
    499476        user_t *u;
     
    517494}
    518495
    519 int cmd_block( irc_t *irc, char **cmd )
     496static int cmd_block( irc_t *irc, char **cmd )
    520497{
    521498        struct gaim_connection *gc;
     
    558535}
    559536
    560 int cmd_allow( irc_t *irc, char **cmd )
     537static int cmd_allow( irc_t *irc, char **cmd )
    561538{
    562539        struct gaim_connection *gc;
     
    600577}
    601578
    602 int cmd_yesno( irc_t *irc, char **cmd )
     579static int cmd_yesno( irc_t *irc, char **cmd )
    603580{
    604581        query_t *q = NULL;
     
    640617}
    641618
    642 int cmd_set( irc_t *irc, char **cmd )
     619static int cmd_set( irc_t *irc, char **cmd )
    643620{
    644621        if( cmd[1] && cmd[2] )
     
    666643}
    667644
    668 int cmd_save( irc_t *irc, char **cmd )
     645static int cmd_save( irc_t *irc, char **cmd )
    669646{
    670647        if( storage_save( irc, TRUE ) == STORAGE_OK )
     
    676653}
    677654
    678 int cmd_blist( irc_t *irc, char **cmd )
     655static int cmd_blist( irc_t *irc, char **cmd )
    679656{
    680657        int online = 0, away = 0, offline = 0;
     
    722699}
    723700
    724 int cmd_nick( irc_t *irc, char **cmd )
     701static int cmd_nick( irc_t *irc, char **cmd )
    725702{
    726703        account_t *a;
     
    758735}
    759736
    760 int cmd_qlist( irc_t *irc, char **cmd )
     737static int cmd_qlist( irc_t *irc, char **cmd )
    761738{
    762739        query_t *q = irc->queries;
     
    780757}
    781758
    782 int cmd_import_buddies( irc_t *irc, char **cmd )
     759static int cmd_import_buddies( irc_t *irc, char **cmd )
    783760{
    784761        struct gaim_connection *gc;
     
    832809        return( 0 );
    833810}
     811
     812const command_t commands[] = {
     813        { "help",           0, cmd_help,           0 },
     814        { "identify",       1, cmd_identify,       0 },
     815        { "register",       1, cmd_register,       0 },
     816        { "drop",           1, cmd_drop,           0 },
     817        { "account",        1, cmd_account,        0 },
     818        { "add",            2, cmd_add,            0 },
     819        { "info",           1, cmd_info,           0 },
     820        { "rename",         2, cmd_rename,         0 },
     821        { "remove",         1, cmd_remove,         0 },
     822        { "block",          1, cmd_block,          0 },
     823        { "allow",          1, cmd_allow,          0 },
     824        { "save",           0, cmd_save,           0 },
     825        { "set",            0, cmd_set,            0 },
     826        { "yes",            0, cmd_yesno,          0 },
     827        { "no",             0, cmd_yesno,          0 },
     828        { "blist",          0, cmd_blist,          0 },
     829        { "nick",           1, cmd_nick,           0 },
     830        { "import_buddies", 1, cmd_import_buddies, 0 },
     831        { "qlist",          0, cmd_qlist,          0 },
     832        { NULL }
     833};
  • commands.h

    rfc50d48 r55ec2d6  
    2929#include "bitlbee.h"
    3030
    31 typedef struct command_t
     31typedef struct command
    3232{
    3333        char *command;
    3434        int required_parameters;
    3535        int (*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

    rfc50d48 r55ec2d6  
    6464        conf->ping_interval = 180;
    6565        conf->ping_timeout = 300;
     66        proxytype = 0;
    6667       
    6768        i = conf_loadini( conf, CONF_FILE );
     
    7677        }
    7778       
    78         while( ( opt = getopt( argc, argv, "i:p:nvIDFc:d:h" ) ) >= 0 )
     79        while( argc > 0 && ( opt = getopt( argc, argv, "i:p:nvIDFc:d:h" ) ) >= 0 )
     80        /*     ^^^^ Just to make sure we skip this step from the REHASH handler. */
    7981        {
    8082                if( opt == 'i' )
     
    9294                }
    9395                else if( opt == 'n' )
    94                         conf->nofork=1;
     96                        conf->nofork = 1;
    9597                else if( opt == 'v' )
    96                         conf->verbose=1;
     98                        conf->verbose = 1;
    9799                else if( opt == 'I' )
    98                         conf->runmode=RUNMODE_INETD;
     100                        conf->runmode = RUNMODE_INETD;
    99101                else if( opt == 'D' )
    100                         conf->runmode=RUNMODE_DAEMON;
     102                        conf->runmode = RUNMODE_DAEMON;
    101103                else if( opt == 'F' )
    102                         conf->runmode=RUNMODE_FORKDAEMON;
     104                        conf->runmode = RUNMODE_FORKDAEMON;
    103105                else if( opt == 'c' )
    104106                {
     
    108110                                CONF_FILE = g_strdup( optarg );
    109111                                g_free( conf );
     112                                /* Re-evaluate arguments. Don't use this option twice,
     113                                   you'll end up in an infinite loop! Hope this trick
     114                                   works with all libcs BTW.. */
     115                                optind = 1;
    110116                                return( conf_load( argc, argv ) );
    111117                        }
  • irc.c

    rfc50d48 r55ec2d6  
    2727#include "bitlbee.h"
    2828#include "crypting.h"
     29#include "ipc.h"
    2930
    3031static gboolean irc_userping( gpointer _irc );
     
    204205
    205206/* Because we have no garbage collection, this is quite annoying */
    206 void irc_free( irc_t * irc )
     207void irc_free(irc_t * irc)
    207208{
    208209        account_t *account, *accounttmp;
     
    217218                if( storage_save( irc, TRUE ) != STORAGE_OK )
    218219                        irc_usermsg( irc, "Error while saving settings!" );
     220       
     221        closesocket( irc->fd );
    219222       
    220223        if( irc->ping_source_id > 0 )
     
    338341int irc_process( irc_t *irc )
    339342{
    340         char **lines, *temp;   
     343        char **lines, *temp, **cmd;
    341344        int i;
    342345
    343         if( irc->readbuffer != NULL ) {
    344                 lines = irc_tokenize(irc->readbuffer );
    345                 for( i = 0; *lines[i] != '\0'; i++ ) {
    346                         if( lines[i+1] == NULL ) {
     346        if( irc->readbuffer != NULL )
     347        {
     348                lines = irc_tokenize( irc->readbuffer );
     349               
     350                for( i = 0; *lines[i] != '\0'; i ++ )
     351                {
     352                        if( lines[i+1] == NULL )
     353                        {
    347354                                temp = g_strdup( lines[i] );
    348355                                g_free( irc->readbuffer );
    349356                                irc->readbuffer = temp;
    350                                 i++;
     357                                i ++;
    351358                                break;
    352359                        }                       
    353                         if (!irc_process_line(irc, lines[i])) {
     360                       
     361                        if( ( cmd = irc_parse_line( lines[i] ) ) == NULL )
     362                                continue;
     363                        if( !irc_exec( irc, cmd ) )
     364                        {
     365                                g_free( cmd );
    354366                                g_free( lines );
    355367                                return 0;
    356368                        }
    357                 }
    358                 if(lines[i]!=NULL) {
    359                         g_free(irc->readbuffer);
    360                         irc->readbuffer=NULL;   
    361                 }
     369                       
     370                        g_free( cmd );
     371                }
     372               
     373                if( lines[i] != NULL )
     374                {
     375                        g_free( irc->readbuffer );
     376                        irc->readbuffer = NULL;
     377                }
     378               
    362379                g_free( lines );
    363380        }
     381       
    364382        return 1;       
    365383}
     
    371389
    372390        /* Count the number of elements we're gonna need. */
    373         for(i=0, j=1; buffer[i]!='\0'; i++ ) {
    374                 if(buffer[i]=='\n' )
    375                         if(buffer[i+1]!='\r' && buffer[i+1]!='\n')
    376                                 j++;
     391        for( i = 0, j = 1; buffer[i] != '\0'; i ++ )
     392        {
     393                if( buffer[i] == '\n' )
     394                        if( buffer[i+1] != '\r' && buffer[i+1] != '\n' )
     395                                j ++;
    377396        }
    378397       
    379398        /* Allocate j+1 elements. */
    380         lines=g_new (char *, j+1);
     399        lines = g_new( char *, j + 1 );
    381400       
    382401        /* NULL terminate our list. */
    383         lines[j]=NULL;
    384        
    385         lines[0]=buffer;
     402        lines[j] = NULL;
     403       
     404        lines[0] = buffer;
    386405       
    387406        /* Split the buffer in several strings, using \r\n as our seperator, where \r is optional.
    388407         * Although this is not in the RFC, some braindead ircds (newnet's) use this, so some clients might too.
    389408         */
    390         for( i=0, j=0; buffer[i]!='\0'; i++) {
    391                 if(buffer[i]=='\n') {
    392                         buffer[i]='\0';
    393 
    394                         /* We dont want to read 1 byte before our buffer
    395                          * and (in rare cases) generate a SIGSEGV.
    396                          */
    397                         if(i!=0)
    398                                 if(buffer[i-1]=='\r')
    399                                         buffer[i-1]='\0';
    400                         if(buffer[i+1]!='\r'&&buffer[i+1]!='\n')
    401                                 lines[++j]=buffer+i+1;
    402                 }
    403         }
    404 
    405         return(lines);
    406 }
    407 
    408 int irc_process_line( irc_t *irc, char *line )
     409        for( i = 0, j = 0; buffer[i] != '\0'; i ++)
     410        {
     411                if( buffer[i] == '\n' )
     412                {
     413                        buffer[i] = '\0';
     414                       
     415                        if( i > 0 && buffer[i-1] == '\r' )
     416                                buffer[i-1] = '\0';
     417                        if( buffer[i+1] != '\r' && buffer[i+1] != '\n' )
     418                                lines[++j] = buffer + i + 1;
     419                }
     420        }
     421       
     422        return( lines );
     423}
     424
     425char **irc_parse_line( char *line )
    409426{
    410427        int i, j;
     
    412429       
    413430        /* Move the line pointer to the start of the command, skipping spaces and the optional prefix. */
    414         if(line[0]==':') {
    415                 for(i=0; line[i]!=32; i++);
    416                 line=line+i;
    417         }
    418         for(i=0; line[i]==32; i++);
    419         line=line+i;
    420 
     431        if( line[0] == ':' )
     432        {
     433                for( i = 0; line[i] != ' '; i ++ );
     434                line = line + i;
     435        }
     436        for( i = 0; line[i] == ' '; i ++ );
     437        line = line + i;
     438       
    421439        /* If we're already at the end of the line, return. If not, we're going to need at least one element. */
    422         if(line[0]=='\0')
    423                 return 1;
    424         else
    425                 j=1;   
    426        
    427         /* Count the number of char **cmd elements we're going to need. */     
    428         for(i=0; line[i]!='\0'; i++) {
    429                 if((line[i]==32) && (line[i+1]!=32) && (line[i+1]!='\0') && (line[i+1]!=':'))           
    430                         j++;
    431                 else if((line[i]==':') && (line[i+1]!='\0') && (line[i-1]==32)) {
    432                         j++;
    433                         break;
    434                 }
     440        if( line[0] == '\0')
     441                return NULL;
     442       
     443        /* Count the number of char **cmd elements we're going to need. */
     444        j = 1;
     445        for( i = 0; line[i] != '\0'; i ++ )
     446        {
     447                if( line[i] == ' ' )
     448                {
     449                        j ++;
    435450                       
     451                        if( line[i+1] == ':' )
     452                                break;
     453                }
    436454        }       
    437455
    438456        /* Allocate the space we need. */
    439         cmd=g_new(char *, j+1);
    440         cmd[j]=NULL;
     457        cmd = g_new( char *, j + 1 );
     458        cmd[j] = NULL;
    441459       
    442460        /* Do the actual line splitting, format is:
     
    445463         */
    446464
    447         cmd[0]=line;
    448         for(i=0, j=0; line[i]!='\0'; i++) {
    449                 if((line[i]==32)) {
    450                         line[i]='\0';
    451                         if((line[i+1]!=32) && (line[i+1]!='\0') && (line[i+1]!=':'))           
    452                                 cmd[++j]=line+i+1;
    453                 }
    454                 else if((line[i]==':') && (line[i+1]!='\0') && (line[i-1]=='\0')) {
    455                         cmd[++j]=line+i+1;
    456                         break;
    457                 }
    458         }
    459        
    460         i=irc_exec(irc, cmd);
    461         g_free(cmd);
    462 
    463         return(i);     
    464 }
    465 
    466 int irc_exec( irc_t *irc, char **cmd )
    467 {       
    468         int i;
    469 
    470         if( (global.conf)->authmode == AUTHMODE_CLOSED && irc->status < USTATUS_AUTHORIZED )
    471         {
    472                 if( g_strcasecmp( cmd[0], "PASS" ) == 0 )
    473                 {
    474                         if( !cmd[1] )
     465        cmd[0] = line;
     466        for( i = 0, j = 0; line[i] != '\0'; i ++ )
     467        {
     468                if( line[i] == ' ' )
     469                {
     470                        line[i] = '\0';
     471                        cmd[++j] = line + i + 1;
     472                       
     473                        if( line[i+1] == ':' )
    475474                        {
    476                                 irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
     475                                cmd[j] ++;
     476                                break;
    477477                        }
    478                         else if( strcmp( cmd[1], (global.conf)->auth_pass ) == 0 )
    479                         {
    480                                 irc->status = USTATUS_AUTHORIZED;
    481                         }
    482                         else
    483                         {
    484                                 irc_reply( irc, 464, ":Nope, maybe you should try it again..." );
    485                         }
    486                 }
    487                 else
    488                 {
    489                         irc_reply( irc, 464, ":Uhh, fine, but I want the password first." );
    490                 }
    491                
    492                 return( 1 );
    493         }
    494        
    495         if( g_strcasecmp( cmd[0], "USER" ) == 0 )
    496         {
    497                 if( !( cmd[1] && cmd[2] && cmd[3] && cmd[4] ) )
    498                 {
    499                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    500                 }
    501                 else if( irc->user )
    502                 {
    503                         irc_reply( irc, 462, ":You can't change your nick/userinfo" );
    504                 }
    505                 else
    506                 {
    507                         irc->user = g_strdup( cmd[1] );
    508                         irc->realname = g_strdup( cmd[4] );
    509                         if( irc->nick ) irc_login( irc );
    510                 }
    511                 return( 1 );
    512         }
    513         else if( g_strcasecmp( cmd[0], "NICK" ) == 0 )
    514         {
    515                 if( !cmd[1] )
    516                 {
    517                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    518                 }
    519                 else if( irc->nick )
    520                 {
    521                         irc_reply( irc, 438, ":The hand of the deity is upon thee, thy nick may not change" );
    522                 }
    523                 /* This is not clean, but for now it'll have to be like this... */
    524                 else if( ( nick_cmp( cmd[1], irc->mynick ) == 0 ) || ( nick_cmp( cmd[1], NS_NICK ) == 0 ) )
    525                 {
    526                         irc_reply( irc, 433, ":This nick is already in use" );
    527                 }
    528                 else if( !nick_ok( cmd[1] ) )
    529                 {
    530                         /* [SH] Invalid characters. */
    531                         irc_reply( irc, 432, ":This nick contains invalid characters" );
    532                 }
    533                 else
    534                 {
    535                         irc->nick = g_strdup( cmd[1] );
    536                         if( irc->user ) irc_login( irc );
    537                 }
    538                 return( 1 );
    539         }
    540         else if( g_strcasecmp( cmd[0], "QUIT" ) == 0 )
    541         {
    542                 irc_write( irc, "ERROR :%s%s", cmd[1]?"Quit: ":"", cmd[1]?cmd[1]:"Client Quit" );
    543                 /* g_io_channel_close( irc->io_channel ); */
    544                 return( 0 );
    545         }
    546        
    547         if( !irc->user || !irc->nick )
    548         {
    549                 irc_reply( irc, 451, ":Register first" );
    550                 return( 1 );
    551         }
    552        
    553         if( g_strcasecmp( cmd[0], "PING" ) == 0 )
    554         {
    555                 irc_write( irc, ":%s PONG %s :%s", irc->myhost, irc->myhost, cmd[1]?cmd[1]:irc->myhost );
    556         }
    557         else if( g_strcasecmp( cmd[0], "OPER" ) == 0 )
    558         {
    559                 if( !cmd[2] )
    560                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    561                 else if( strcmp( cmd[2], global.conf->oper_pass ) == 0 )
    562                         irc_umode_set( irc, "+o", 1 );
    563                 // else
    564                         /* FIXME/TODO: Find out which reply to send now. */
    565         }
    566         else if( g_strcasecmp( cmd[0], "MODE" ) == 0 )
    567         {
    568                 if( !cmd[1] )
    569                 {
    570                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    571                 }
    572                 else if( *cmd[1] == '#' || *cmd[1] == '&' )
    573                 {
    574                         if( cmd[2] )
    575                         {
    576                                 if( *cmd[2] == '+' || *cmd[2] == '-' )
    577                                         irc_reply( irc, 477, "%s :Can't change channel modes", cmd[1] );
    578                                 else if( *cmd[2] == 'b' )
    579                                         irc_reply( irc, 368, "%s :No bans possible", cmd[1] );
    580                         }
    581                         else
    582                                 irc_reply( irc, 324, "%s +%s", cmd[1], CMODE );
    583                 }
    584                 else
    585                 {
    586                         if( nick_cmp( cmd[1], irc->nick ) == 0 )
    587                         {
    588                                 if( cmd[2] )
    589                                         irc_umode_set( irc, cmd[2], 0 );
    590                         }
    591                         else
    592                                 irc_reply( irc, 502, ":Don't touch their modes" );
    593                 }
    594         }
    595         else if( g_strcasecmp( cmd[0], "NAMES" ) == 0 )
    596         {
    597                 irc_names( irc, cmd[1]?cmd[1]:irc->channel );
    598         }
    599         else if( g_strcasecmp( cmd[0], "PART" ) == 0 )
    600         {
    601                 struct conversation *c;
    602                
    603                 if( !cmd[1] )
    604                 {
    605                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    606                 }
    607                 else if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
    608                 {
    609                         user_t *u = user_find( irc, irc->nick );
    610                        
    611                         /* Not allowed to leave control channel */
    612                         irc_part( irc, u, irc->channel );
    613                         irc_join( irc, u, irc->channel );
    614                 }
    615                 else if( ( c = conv_findchannel( cmd[1] ) ) )
    616                 {
    617                         user_t *u = user_find( irc, irc->nick );
    618                        
    619                         irc_part( irc, u, c->channel );
    620                        
    621                         if( c->gc && c->gc->prpl )
    622                         {
    623                                 c->joined = 0;
    624                                 c->gc->prpl->chat_leave( c->gc, c->id );
    625                         }
    626                 }
    627                 else
    628                 {
    629                         irc_reply( irc, 403, "%s :No such channel", cmd[1] );
    630                 }
    631         }
    632         else if( g_strcasecmp( cmd[0], "JOIN" ) == 0 )
    633         {
    634                 if( !cmd[1] )
    635                 {
    636                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    637                 }
    638                 else if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
    639                         ; /* Dude, you're already there...
    640                              RFC doesn't have any reply for that though? */
    641                 else if( cmd[1] )
    642                 {
    643                         if( ( cmd[1][0] == '#' || cmd[1][0] == '&' ) && cmd[1][1] )
    644                         {
    645                                 user_t *u = user_find( irc, cmd[1] + 1 );
    646                                
    647                                 if( u && u->gc && u->gc->prpl && u->gc->prpl->chat_open )
    648                                 {
    649                                         irc_reply( irc, 403, "%s :Initializing groupchat in a different channel", cmd[1] );
    650                                        
    651                                         if( !u->gc->prpl->chat_open( u->gc, u->handle ) )
    652                                         {
    653                                                 irc_usermsg( irc, "Could not open a groupchat with %s, maybe you don't have a connection to him/her yet?", u->nick );
    654                                         }
    655                                 }
    656                                 else
    657                                 {
    658                                         irc_reply( irc, 403, "%s :Groupchats are not possible with %s", cmd[1], cmd[1]+1 );
    659                                 }
    660                         }
    661                         else
    662                         {
    663                                 irc_reply( irc, 403, "%s :No such channel", cmd[1] );
    664                         }
    665                 }
    666         }
    667         else if( g_strcasecmp( cmd[0], "INVITE" ) == 0 )
    668         {
    669                 if( cmd[1] && cmd[2] )
    670                         irc_invite( irc, cmd[1], cmd[2] );
    671                 else
    672                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    673         }
    674         else if( g_strcasecmp( cmd[0], "PRIVMSG" ) == 0 || g_strcasecmp( cmd[0], "NOTICE" ) == 0 )
    675         {
    676                 if( !cmd[1] )
    677                 {
    678                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    679                 }
    680                 else if ( !cmd[2] )
    681                 {
    682                         irc_reply( irc, 412, ":No text to send" );
    683                 }
    684                 else if ( irc->nick && g_strcasecmp( cmd[1], irc->nick ) == 0 )
    685                 {
    686                         irc_write( irc, ":%s!%s@%s %s %s :%s", irc->nick, irc->user, irc->host, cmd[0], cmd[1], cmd[2] );
    687                 }
    688                 else
    689                 {
    690                         if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
    691                         {
    692                                 unsigned int i;
    693                                 char *t = set_getstr( irc, "default_target" );
    694                                
    695                                 if( g_strcasecmp( t, "last" ) == 0 && irc->last_target )
    696                                         cmd[1] = irc->last_target;
    697                                 else if( g_strcasecmp( t, "root" ) == 0 )
    698                                         cmd[1] = irc->mynick;
    699                                
    700                                 for( i = 0; i < strlen( cmd[2] ); i ++ )
    701                                 {
    702                                         if( cmd[2][i] == ' ' ) break;
    703                                         if( cmd[2][i] == ':' || cmd[2][i] == ',' )
    704                                         {
    705                                                 cmd[1] = cmd[2];
    706                                                 cmd[2] += i;
    707                                                 *cmd[2] = 0;
    708                                                 while( *(++cmd[2]) == ' ' );
    709                                                 break;
    710                                         }
    711                                 }
    712                                
    713                                 irc->is_private = 0;
    714                                
    715                                 if( cmd[1] != irc->last_target )
    716                                 {
    717                                         if( irc->last_target )
    718                                                 g_free( irc->last_target );
    719                                         irc->last_target = g_strdup( cmd[1] );
    720                                 }
    721                         }
    722                         else
    723                         {
    724                                 irc->is_private = 1;
    725                         }
    726                         irc_send( irc, cmd[1], cmd[2], ( g_strcasecmp( cmd[0], "NOTICE" ) == 0 ) ? IM_FLAG_AWAY : 0 );
    727                 }
    728         }
    729         else if( g_strcasecmp( cmd[0], "WHO" ) == 0 )
    730         {
    731                 irc_who( irc, cmd[1] );
    732         }
    733         else if( g_strcasecmp( cmd[0], "USERHOST" ) == 0 )
    734         {
    735                 user_t *u;
    736                
    737                 if( !cmd[1] )
    738                 {
    739                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    740                 }
    741                 /* [TV] Usable USERHOST-implementation according to
    742                         RFC1459. Without this, mIRC shows an error
    743                         while connecting, and the used way of rejecting
    744                         breaks standards.
    745                 */
    746                
    747                 for( i = 1; cmd[i]; i ++ )
    748                         if( ( u = user_find( irc, cmd[i] ) ) )
    749                         {
    750                                 if( u->online && u->away )
    751                                         irc_reply( irc, 302, ":%s=-%s@%s", u->nick, u->user, u->host );
    752                                 else
    753                                         irc_reply( irc, 302, ":%s=+%s@%s", u->nick, u->user, u->host );
    754                         }
    755         }
    756         else if( g_strcasecmp( cmd[0], "ISON" ) == 0 )
    757         {
    758                 user_t *u;
    759                 char buff[IRC_MAX_LINE];
    760                 int lenleft;
    761                
    762                 buff[0] = '\0';
    763                
    764                 /* [SH] Leave room for : and \0 */
    765                 lenleft = IRC_MAX_LINE - 2;
    766                
    767                 for( i = 1; cmd[i]; i ++ )
    768                 {
    769                         if( ( u = user_find( irc, cmd[i] ) ) && u->online )
    770                         {
    771                                 /* [SH] Make sure we don't use too much buffer space. */
    772                                 lenleft -= strlen( u->nick ) + 1;
    773                                
    774                                 if( lenleft < 0 )
    775                                 {
    776                                         break;
    777                                 }
    778                                
    779                                 /* [SH] Add the nick to the buffer. Note
    780                                  * that an extra space is always added. Even
    781                                  * if it's the last nick in the list. Who
    782                                  * cares?
    783                                  */
    784                                
    785                                 strcat( buff, u->nick );
    786                                 strcat( buff, " " );
    787                         }
    788                 }
    789                
    790                 /* [WvG] Well, maybe someone cares, so why not remove it? */
    791                 if( strlen( buff ) > 0 )
    792                         buff[strlen(buff)-1] = '\0';
    793                
    794                 /* [SH] By the way, that really *was* WvG talking. */
    795                 /* [WvG] Really? */
    796                 /* [SH] Yeah... But *this* is WvG talking too. ;-P */
    797                 /* [WvG] *sigh* */
    798                
    799                 irc_reply( irc, 303, ":%s", buff );
    800         }
    801         else if( g_strcasecmp( cmd[0], "WATCH" ) == 0 )
    802         {
    803                 /* Obviously we could also mark a user structure as being
    804                    watched, but what if the WATCH command is sent right
    805                    after connecting? The user won't exist yet then... */
    806                 for( i = 1; cmd[i]; i ++ )
    807                 {
    808                         char *nick;
    809                         user_t *u;
    810                        
    811                         if( !cmd[i][0] || !cmd[i][1] )
    812                                 break;
    813                        
    814                         nick = g_strdup( cmd[i] + 1 );
    815                         nick_lc( nick );
    816                        
    817                         u = user_find( irc, nick );
    818                        
    819                         if( cmd[i][0] == '+' )
    820                         {
    821                                 if( !g_hash_table_lookup( irc->watches, nick ) )
    822                                         g_hash_table_insert( irc->watches, nick, nick );
    823                                
    824                                 if( u && u->online )
    825                                         irc_reply( irc, 604, "%s %s %s %d :%s", u->nick, u->user, u->host, time( NULL ), "is online" );
    826                                 else
    827                                         irc_reply( irc, 605, "%s %s %s %d :%s", nick, "*", "*", time( NULL ), "is offline" );
    828                         }
    829                         else if( cmd[i][0] == '-' )
    830                         {
    831                                 gpointer okey, ovalue;
    832                                
    833                                 if( g_hash_table_lookup_extended( irc->watches, nick, &okey, &ovalue ) )
    834                                 {
    835                                         g_free( okey );
    836                                         g_hash_table_remove( irc->watches, okey );
    837                                        
    838                                         irc_reply( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" );
    839                                 }
    840                         }
    841                 }
    842         }
    843         else if( g_strcasecmp( cmd[0], "TOPIC" ) == 0 )
    844         {
    845                 if( cmd[1] && cmd[2] )
    846                         irc_reply( irc, 482, "%s :Cannot change topic", cmd[1] );
    847                 else if( cmd[1] )
    848                         irc_topic( irc, cmd[1] );
    849                 else
    850                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    851         }
    852         else if( g_strcasecmp( cmd[0], "AWAY" ) == 0 )
    853         {
    854                 irc_away( irc, cmd[1] );
    855         }
    856         else if( g_strcasecmp( cmd[0], "WHOIS" ) == 0 )
    857         {
    858                 if( cmd[1] )
    859                 {
    860                         irc_whois( irc, cmd[1] );
    861                 }
    862                 else
    863                 {
    864                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    865                 }
    866         }
    867         else if( g_strcasecmp( cmd[0], "WHOWAS" ) == 0 )
    868         {
    869                 /* For some reason irssi tries a whowas when whois fails. We can
    870                    ignore this, but then the user never gets a "user not found"
    871                    message from irssi which is a bit annoying. So just respond
    872                    with not-found and irssi users will get better error messages */
    873                
    874                 if( cmd[1] )
    875                 {
    876                         irc_reply( irc, 406, "%s :Nick does not exist", cmd[1] );
    877                         irc_reply( irc, 369, "%s :End of WHOWAS", cmd[1] );
    878                 }
    879                 else
    880                 {
    881                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    882                 }
    883         }
    884         else if( ( g_strcasecmp( cmd[0], "NICKSERV" ) == 0 ) || ( g_strcasecmp( cmd[0], "NS" ) == 0 ) )
    885         {
    886                 /* [SH] This aliases the NickServ command to PRIVMSG root */
    887                 /* [TV] This aliases the NS command to PRIVMSG root as well */
    888                 root_command( irc, cmd + 1 );
    889         }
    890         else if( g_strcasecmp( cmd[0], "MOTD" ) == 0 )
    891         {
    892                 irc_motd( irc );
    893         }
    894         else if( g_strcasecmp( cmd[0], "PONG" ) == 0 )
    895         {
    896                 /* We could check the value we get back from the user, but in
    897                    fact we don't care, we're just happy he's still alive. */
    898                 irc->last_pong = gettime();
    899                 irc->pinging = 0;
    900         }
    901         else if( g_strcasecmp( cmd[0], "COMPLETIONS" ) == 0 )
    902         {
    903                 user_t *u = user_find( irc, irc->mynick );
    904                 help_t *h;
    905                 set_t *s;
    906                 int i;
    907                
    908                 irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", "OK" );
    909                
    910                 for( i = 0; commands[i].command; i ++ )
    911                         irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", commands[i].command );
    912                
    913                 for( h = global.help; h; h = h->next )
    914                         irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS help ", h->string );
    915                
    916                 for( s = irc->set; s; s = s->next )
    917                         irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS set ", s->key );
    918                
    919                 irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", "END" );
    920         }
    921         else if( set_getint( irc, "debug" ) )
    922         {
    923                 irc_usermsg( irc, "\002--- Unknown command:" );
    924                 for( i = 0; cmd[i]; i ++ ) irc_usermsg( irc, "%s", cmd[i] );
    925                 irc_usermsg( irc, "\002--------------------" );
    926         }
    927        
    928         return( 1 );
     478                }
     479        }
     480       
     481        return cmd;
     482}
     483
     484char *irc_build_line( char **cmd )
     485{
     486        int i, len;
     487        char *s;
     488       
     489        if( cmd[0] == NULL )
     490                return NULL;
     491       
     492        len = 1;
     493        for( i = 0; cmd[i]; i ++ )
     494                len += strlen( cmd[i] ) + 1;
     495       
     496        if( strchr( cmd[i-1], ' ' ) != NULL )
     497                len ++;
     498       
     499        s = g_new0( char, len + 1 );
     500        for( i = 0; cmd[i]; i ++ )
     501        {
     502                if( cmd[i+1] == NULL && strchr( cmd[i], ' ' ) != NULL )
     503                        strcat( s, ":" );
     504               
     505                strcat( s, cmd[i] );
     506               
     507                if( cmd[i+1] )
     508                        strcat( s, " " );
     509        }
     510        strcat( s, "\r\n" );
     511       
     512        return s;
    929513}
    930514
     
    1085669}
    1086670
    1087 void irc_who( irc_t *irc, char *channel )
    1088 {
    1089         user_t *u = irc->users;
    1090         struct conversation *c;
    1091         GList *l;
    1092        
    1093         if( !channel || *channel == '0' || *channel == '*' || !*channel )
    1094                 while( u )
    1095                 {
    1096                         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 );
    1097                         u = u->next;
    1098                 }
    1099         else if( g_strcasecmp( channel, irc->channel ) == 0 )
    1100                 while( u )
    1101                 {
    1102                         if( u->online )
    1103                                 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 );
    1104                         u = u->next;
    1105                 }
    1106         else if( ( c = conv_findchannel( channel ) ) )
    1107                 for( l = c->in_room; l; l = l->next )
    1108                 {
    1109                         if( ( u = user_findhandle( c->gc, l->data ) ) )
    1110                                 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 );
    1111                 }
    1112         else if( ( u = user_find( irc, channel ) ) )
    1113                 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 );
    1114        
    1115         irc_reply( irc, 315, "%s :End of /WHO list.", channel?channel:"**" );
     671int irc_check_login( irc_t *irc )
     672{
     673        if( irc->user && irc->nick )
     674        {
     675                if( global.conf->authmode == AUTHMODE_CLOSED && irc->status < USTATUS_AUTHORIZED )
     676                {
     677                        irc_reply( irc, 464, ":This server is password-protected." );
     678                        return 0;
     679                }
     680                else
     681                {
     682                        irc_login( irc );
     683                        return 1;
     684                }
     685        }
     686        else
     687        {
     688                /* More information needed. */
     689                return 0;
     690        }
    1116691}
    1117692
     
    1148723        u->realname = g_strdup( irc->realname );
    1149724        u->online = 1;
    1150 //      u->send_handler = msg_echo;
    1151725        irc_spawn( irc, u );
    1152726       
    1153727        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." );
     728       
     729        if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON )
     730                ipc_to_master_str( "CLIENT %s %s :%s\r\n", irc->host, irc->nick, irc->realname );
    1154731       
    1155732        irc->status = USTATUS_LOGGED_IN;
     
    1225802}
    1226803
    1227 void irc_whois( irc_t *irc, char *nick )
    1228 {
    1229         user_t *u = user_find( irc, nick );
    1230        
    1231         if( u )
    1232         {
    1233                 irc_reply( irc, 311, "%s %s %s * :%s", u->nick, u->user, u->host, u->realname );
    1234                
    1235                 if( u->gc )
    1236                         irc_reply( irc, 312, "%s %s.%s :%s network", u->nick, u->gc->user->username,
    1237                                    *u->gc->user->proto_opt[0] ? u->gc->user->proto_opt[0] : "", u->gc->prpl->name );
    1238                 else
    1239                         irc_reply( irc, 312, "%s %s :%s", u->nick, irc->myhost, IRCD_INFO );
    1240                
    1241                 if( !u->online )
    1242                         irc_reply( irc, 301, "%s :%s", u->nick, "User is offline" );
    1243                 else if( u->away )
    1244                         irc_reply( irc, 301, "%s :%s", u->nick, u->away );
    1245                
    1246                 irc_reply( irc, 318, "%s :End of /WHOIS list", nick );
    1247         }
    1248         else
    1249         {
    1250                 irc_reply( irc, 401, "%s :Nick does not exist", nick );
    1251         }
    1252 }
    1253 
    1254 
    1255804void irc_umode_set( irc_t *irc, char *s, int allow_priv )
    1256805{
     
    1282831}
    1283832
    1284 int irc_away( irc_t *irc, char *away )
    1285 {
    1286         user_t *u = user_find( irc, irc->nick );
    1287         GSList *c = get_connections();
    1288        
    1289         if( !u ) return( 0 );
    1290        
    1291         if( away && *away )
    1292         {
    1293                 int i, j;
    1294                
    1295                 /* Copy away string, but skip control chars. Mainly because
    1296                    Jabber really doesn't like them. */
    1297                 u->away = g_malloc( strlen( away ) + 1 );
    1298                 for( i = j = 0; away[i]; i ++ )
    1299                         if( ( u->away[j] = away[i] ) >= ' ' )
    1300                                 j ++;
    1301                 u->away[j] = 0;
    1302                
    1303                 irc_reply( irc, 306, ":You're now away: %s", u->away );
    1304                 /* irc_umode_set( irc, irc->myhost, "+a" ); */
    1305         }
    1306         else
    1307         {
    1308                 if( u->away ) g_free( u->away );
    1309                 u->away = NULL;
    1310                 /* irc_umode_set( irc, irc->myhost, "-a" ); */
    1311                 irc_reply( irc, 305, ":Welcome back" );
    1312         }
    1313        
    1314         while( c )
    1315         {
    1316                 if( ((struct gaim_connection *)c->data)->flags & OPT_LOGGED_IN )
    1317                         proto_away( c->data, u->away );
    1318                
    1319                 c = c->next;
    1320         }
    1321        
    1322         return( 1 );
    1323 }
    1324 
    1325833void irc_spawn( irc_t *irc, user_t *u )
    1326834{
     
    1374882        }
    1375883        g_free( nick );
    1376 }
    1377 
    1378 void irc_invite( irc_t *irc, char *nick, char *channel )
    1379 {
    1380         struct conversation *c = conv_findchannel( channel );
    1381         user_t *u = user_find( irc, nick );
    1382        
    1383         if( u && c && ( u->gc == c->gc ) )
    1384                 if( c->gc && c->gc->prpl && c->gc->prpl->chat_invite )
    1385                 {
    1386                         c->gc->prpl->chat_invite( c->gc, c->id, "", u->handle );
    1387                         irc_reply( irc, 341, "%s %s", nick, channel );
    1388                         return;
    1389                 }
    1390        
    1391         irc_reply( irc, 482, "%s :Invite impossible; User/Channel non-existent or incompatible", channel );
    1392884}
    1393885
  • irc.h

    rfc50d48 r55ec2d6  
    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,
    4646        USTATUS_IDENTIFIED,
    47         USTATUS_SHUTDOWN
     47        USTATUS_SHUTDOWN = -1
    4848} irc_status_t;
    4949
     
    110110int irc_exec( irc_t *irc, char **cmd );
    111111int irc_process( irc_t *irc );
    112 int irc_process_line( irc_t *irc, char *line );
     112char **irc_parse_line( char *line );
     113char *irc_build_line( char **cmd );
    113114
    114115void irc_vawrite( irc_t *irc, char *format, va_list params );
     
    120121
    121122void irc_login( irc_t *irc );
     123int irc_check_login( irc_t *irc );
    122124void irc_motd( irc_t *irc );
    123125void irc_names( irc_t *irc, char *channel );
  • url.c

    rfc50d48 r55ec2d6  
    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;
Note: See TracChangeset for help on using the changeset viewer.