Changes in / [2fa825b:b8c2ace]


Ignore:
Files:
3 added
9 edited

Legend:

Unmodified
Added
Removed
  • Makefile

    r2fa825b rb8c2ace  
    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

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

    r2fa825b rb8c2ace  
    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

    r2fa825b rb8c2ace  
    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

    r2fa825b rb8c2ace  
    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

    r2fa825b rb8c2ace  
    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

    r2fa825b rb8c2ace  
    2727#include "bitlbee.h"
    2828#include "crypting.h"
     29#include "ipc.h"
    2930
    3031static gboolean irc_userping( gpointer _irc );
     
    173174
    174175/* Because we have no garbage collection, this is quite annoying */
    175 void irc_free( irc_t * irc )
     176void irc_free(irc_t * irc)
    176177{
    177178        account_t *account, *accounttmp;
     
    186187                if( storage_save( irc, TRUE ) != STORAGE_OK )
    187188                        irc_usermsg( irc, "Error while saving settings!" );
     189       
     190        closesocket( irc->fd );
    188191       
    189192        if( irc->ping_source_id > 0 )
     
    307310int irc_process( irc_t *irc )
    308311{
    309         char **lines, *temp;   
     312        char **lines, *temp, **cmd;
    310313        int i;
    311314
    312         if( irc->readbuffer != NULL ) {
    313                 lines = irc_tokenize(irc->readbuffer );
    314                 for( i = 0; *lines[i] != '\0'; i++ ) {
    315                         if( lines[i+1] == NULL ) {
     315        if( irc->readbuffer != NULL )
     316        {
     317                lines = irc_tokenize( irc->readbuffer );
     318               
     319                for( i = 0; *lines[i] != '\0'; i ++ )
     320                {
     321                        if( lines[i+1] == NULL )
     322                        {
    316323                                temp = g_strdup( lines[i] );
    317324                                g_free( irc->readbuffer );
    318325                                irc->readbuffer = temp;
    319                                 i++;
     326                                i ++;
    320327                                break;
    321328                        }                       
    322                         if (!irc_process_line(irc, lines[i])) {
     329                       
     330                        if( ( cmd = irc_parse_line( lines[i] ) ) == NULL )
     331                                continue;
     332                        if( !irc_exec( irc, cmd ) )
     333                        {
     334                                g_free( cmd );
    323335                                g_free( lines );
    324336                                return 0;
    325337                        }
    326                 }
    327                 if(lines[i]!=NULL) {
    328                         g_free(irc->readbuffer);
    329                         irc->readbuffer=NULL;   
    330                 }
     338                       
     339                        g_free( cmd );
     340                }
     341               
     342                if( lines[i] != NULL )
     343                {
     344                        g_free( irc->readbuffer );
     345                        irc->readbuffer = NULL;
     346                }
     347               
    331348                g_free( lines );
    332349        }
     350       
    333351        return 1;       
    334352}
     
    340358
    341359        /* Count the number of elements we're gonna need. */
    342         for(i=0, j=1; buffer[i]!='\0'; i++ ) {
    343                 if(buffer[i]=='\n' )
    344                         if(buffer[i+1]!='\r' && buffer[i+1]!='\n')
    345                                 j++;
     360        for( i = 0, j = 1; buffer[i] != '\0'; i ++ )
     361        {
     362                if( buffer[i] == '\n' )
     363                        if( buffer[i+1] != '\r' && buffer[i+1] != '\n' )
     364                                j ++;
    346365        }
    347366       
    348367        /* Allocate j+1 elements. */
    349         lines=g_new (char *, j+1);
     368        lines = g_new( char *, j + 1 );
    350369       
    351370        /* NULL terminate our list. */
    352         lines[j]=NULL;
    353        
    354         lines[0]=buffer;
     371        lines[j] = NULL;
     372       
     373        lines[0] = buffer;
    355374       
    356375        /* Split the buffer in several strings, using \r\n as our seperator, where \r is optional.
    357376         * Although this is not in the RFC, some braindead ircds (newnet's) use this, so some clients might too.
    358377         */
    359         for( i=0, j=0; buffer[i]!='\0'; i++) {
    360                 if(buffer[i]=='\n') {
    361                         buffer[i]='\0';
    362 
    363                         /* We dont want to read 1 byte before our buffer
    364                          * and (in rare cases) generate a SIGSEGV.
    365                          */
    366                         if(i!=0)
    367                                 if(buffer[i-1]=='\r')
    368                                         buffer[i-1]='\0';
    369                         if(buffer[i+1]!='\r'&&buffer[i+1]!='\n')
    370                                 lines[++j]=buffer+i+1;
    371                 }
    372         }
    373 
    374         return(lines);
    375 }
    376 
    377 int irc_process_line( irc_t *irc, char *line )
     378        for( i = 0, j = 0; buffer[i] != '\0'; i ++)
     379        {
     380                if( buffer[i] == '\n' )
     381                {
     382                        buffer[i] = '\0';
     383                       
     384                        if( i > 0 && buffer[i-1] == '\r' )
     385                                buffer[i-1] = '\0';
     386                        if( buffer[i+1] != '\r' && buffer[i+1] != '\n' )
     387                                lines[++j] = buffer + i + 1;
     388                }
     389        }
     390       
     391        return( lines );
     392}
     393
     394char **irc_parse_line( char *line )
    378395{
    379396        int i, j;
     
    381398       
    382399        /* Move the line pointer to the start of the command, skipping spaces and the optional prefix. */
    383         if(line[0]==':') {
    384                 for(i=0; line[i]!=32; i++);
    385                 line=line+i;
    386         }
    387         for(i=0; line[i]==32; i++);
    388         line=line+i;
    389 
     400        if( line[0] == ':' )
     401        {
     402                for( i = 0; line[i] != ' '; i ++ );
     403                line = line + i;
     404        }
     405        for( i = 0; line[i] == ' '; i ++ );
     406        line = line + i;
     407       
    390408        /* If we're already at the end of the line, return. If not, we're going to need at least one element. */
    391         if(line[0]=='\0')
    392                 return 1;
    393         else
    394                 j=1;   
    395        
    396         /* Count the number of char **cmd elements we're going to need. */     
    397         for(i=0; line[i]!='\0'; i++) {
    398                 if((line[i]==32) && (line[i+1]!=32) && (line[i+1]!='\0') && (line[i+1]!=':'))           
    399                         j++;
    400                 else if((line[i]==':') && (line[i+1]!='\0') && (line[i-1]==32)) {
    401                         j++;
    402                         break;
    403                 }
     409        if( line[0] == '\0')
     410                return NULL;
     411       
     412        /* Count the number of char **cmd elements we're going to need. */
     413        j = 1;
     414        for( i = 0; line[i] != '\0'; i ++ )
     415        {
     416                if( line[i] == ' ' )
     417                {
     418                        j ++;
    404419                       
     420                        if( line[i+1] == ':' )
     421                                break;
     422                }
    405423        }       
    406424
    407425        /* Allocate the space we need. */
    408         cmd=g_new(char *, j+1);
    409         cmd[j]=NULL;
     426        cmd = g_new( char *, j + 1 );
     427        cmd[j] = NULL;
    410428       
    411429        /* Do the actual line splitting, format is:
     
    414432         */
    415433
    416         cmd[0]=line;
    417         for(i=0, j=0; line[i]!='\0'; i++) {
    418                 if((line[i]==32)) {
    419                         line[i]='\0';
    420                         if((line[i+1]!=32) && (line[i+1]!='\0') && (line[i+1]!=':'))           
    421                                 cmd[++j]=line+i+1;
    422                 }
    423                 else if((line[i]==':') && (line[i+1]!='\0') && (line[i-1]=='\0')) {
    424                         cmd[++j]=line+i+1;
    425                         break;
    426                 }
    427         }
    428        
    429         i=irc_exec(irc, cmd);
    430         g_free(cmd);
    431 
    432         return(i);     
    433 }
    434 
    435 int irc_exec( irc_t *irc, char **cmd )
    436 {       
    437         int i;
    438 
    439         if( (global.conf)->authmode == AUTHMODE_CLOSED && irc->status < USTATUS_AUTHORIZED )
    440         {
    441                 if( g_strcasecmp( cmd[0], "PASS" ) == 0 )
    442                 {
    443                         if( !cmd[1] )
     434        cmd[0] = line;
     435        for( i = 0, j = 0; line[i] != '\0'; i ++ )
     436        {
     437                if( line[i] == ' ' )
     438                {
     439                        line[i] = '\0';
     440                        cmd[++j] = line + i + 1;
     441                       
     442                        if( line[i+1] == ':' )
    444443                        {
    445                                 irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
     444                                cmd[j] ++;
     445                                break;
    446446                        }
    447                         else if( strcmp( cmd[1], (global.conf)->auth_pass ) == 0 )
    448                         {
    449                                 irc->status = USTATUS_AUTHORIZED;
    450                         }
    451                         else
    452                         {
    453                                 irc_reply( irc, 464, ":Nope, maybe you should try it again..." );
    454                         }
    455                 }
    456                 else
    457                 {
    458                         irc_reply( irc, 464, ":Uhh, fine, but I want the password first." );
    459                 }
    460                
    461                 return( 1 );
    462         }
    463        
    464         if( g_strcasecmp( cmd[0], "USER" ) == 0 )
    465         {
    466                 if( !( cmd[1] && cmd[2] && cmd[3] && cmd[4] ) )
    467                 {
    468                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    469                 }
    470                 else if( irc->user )
    471                 {
    472                         irc_reply( irc, 462, ":You can't change your nick/userinfo" );
    473                 }
    474                 else
    475                 {
    476                         irc->user = g_strdup( cmd[1] );
    477                         irc->realname = g_strdup( cmd[4] );
    478                         if( irc->nick ) irc_login( irc );
    479                 }
    480                 return( 1 );
    481         }
    482         else if( g_strcasecmp( cmd[0], "NICK" ) == 0 )
    483         {
    484                 if( !cmd[1] )
    485                 {
    486                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    487                 }
    488                 else if( irc->nick )
    489                 {
    490                         irc_reply( irc, 438, ":The hand of the deity is upon thee, thy nick may not change" );
    491                 }
    492                 /* This is not clean, but for now it'll have to be like this... */
    493                 else if( ( nick_cmp( cmd[1], irc->mynick ) == 0 ) || ( nick_cmp( cmd[1], NS_NICK ) == 0 ) )
    494                 {
    495                         irc_reply( irc, 433, ":This nick is already in use" );
    496                 }
    497                 else if( !nick_ok( cmd[1] ) )
    498                 {
    499                         /* [SH] Invalid characters. */
    500                         irc_reply( irc, 432, ":This nick contains invalid characters" );
    501                 }
    502                 else
    503                 {
    504                         irc->nick = g_strdup( cmd[1] );
    505                         if( irc->user ) irc_login( irc );
    506                 }
    507                 return( 1 );
    508         }
    509         else if( g_strcasecmp( cmd[0], "QUIT" ) == 0 )
    510         {
    511                 irc_write( irc, "ERROR :%s%s", cmd[1]?"Quit: ":"", cmd[1]?cmd[1]:"Client Quit" );
    512                 /* g_io_channel_close( irc->io_channel ); */
    513                 return( 0 );
    514         }
    515        
    516         if( !irc->user || !irc->nick )
    517         {
    518                 irc_reply( irc, 451, ":Register first" );
    519                 return( 1 );
    520         }
    521        
    522         if( g_strcasecmp( cmd[0], "PING" ) == 0 )
    523         {
    524                 irc_write( irc, ":%s PONG %s :%s", irc->myhost, irc->myhost, cmd[1]?cmd[1]:irc->myhost );
    525         }
    526         else if( g_strcasecmp( cmd[0], "OPER" ) == 0 )
    527         {
    528                 if( !cmd[2] )
    529                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    530                 else if( strcmp( cmd[2], global.conf->oper_pass ) == 0 )
    531                         irc_umode_set( irc, "+o", 1 );
    532                 // else
    533                         /* FIXME/TODO: Find out which reply to send now. */
    534         }
    535         else if( g_strcasecmp( cmd[0], "MODE" ) == 0 )
    536         {
    537                 if( !cmd[1] )
    538                 {
    539                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    540                 }
    541                 else if( *cmd[1] == '#' || *cmd[1] == '&' )
    542                 {
    543                         if( cmd[2] )
    544                         {
    545                                 if( *cmd[2] == '+' || *cmd[2] == '-' )
    546                                         irc_reply( irc, 477, "%s :Can't change channel modes", cmd[1] );
    547                                 else if( *cmd[2] == 'b' )
    548                                         irc_reply( irc, 368, "%s :No bans possible", cmd[1] );
    549                         }
    550                         else
    551                                 irc_reply( irc, 324, "%s +%s", cmd[1], CMODE );
    552                 }
    553                 else
    554                 {
    555                         if( nick_cmp( cmd[1], irc->nick ) == 0 )
    556                         {
    557                                 if( cmd[2] )
    558                                         irc_umode_set( irc, cmd[2], 0 );
    559                         }
    560                         else
    561                                 irc_reply( irc, 502, ":Don't touch their modes" );
    562                 }
    563         }
    564         else if( g_strcasecmp( cmd[0], "NAMES" ) == 0 )
    565         {
    566                 irc_names( irc, cmd[1]?cmd[1]:irc->channel );
    567         }
    568         else if( g_strcasecmp( cmd[0], "PART" ) == 0 )
    569         {
    570                 struct conversation *c;
    571                
    572                 if( !cmd[1] )
    573                 {
    574                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    575                 }
    576                 else if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
    577                 {
    578                         user_t *u = user_find( irc, irc->nick );
    579                        
    580                         /* Not allowed to leave control channel */
    581                         irc_part( irc, u, irc->channel );
    582                         irc_join( irc, u, irc->channel );
    583                 }
    584                 else if( ( c = conv_findchannel( cmd[1] ) ) )
    585                 {
    586                         user_t *u = user_find( irc, irc->nick );
    587                        
    588                         irc_part( irc, u, c->channel );
    589                        
    590                         if( c->gc && c->gc->prpl )
    591                         {
    592                                 c->joined = 0;
    593                                 c->gc->prpl->chat_leave( c->gc, c->id );
    594                         }
    595                 }
    596                 else
    597                 {
    598                         irc_reply( irc, 403, "%s :No such channel", cmd[1] );
    599                 }
    600         }
    601         else if( g_strcasecmp( cmd[0], "JOIN" ) == 0 )
    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                         ; /* Dude, you're already there...
    609                              RFC doesn't have any reply for that though? */
    610                 else if( cmd[1] )
    611                 {
    612                         if( ( cmd[1][0] == '#' || cmd[1][0] == '&' ) && cmd[1][1] )
    613                         {
    614                                 user_t *u = user_find( irc, cmd[1] + 1 );
    615                                
    616                                 if( u && u->gc && u->gc->prpl && u->gc->prpl->chat_open )
    617                                 {
    618                                         irc_reply( irc, 403, "%s :Initializing groupchat in a different channel", cmd[1] );
    619                                        
    620                                         if( !u->gc->prpl->chat_open( u->gc, u->handle ) )
    621                                         {
    622                                                 irc_usermsg( irc, "Could not open a groupchat with %s, maybe you don't have a connection to him/her yet?", u->nick );
    623                                         }
    624                                 }
    625                                 else
    626                                 {
    627                                         irc_reply( irc, 403, "%s :Groupchats are not possible with %s", cmd[1], cmd[1]+1 );
    628                                 }
    629                         }
    630                         else
    631                         {
    632                                 irc_reply( irc, 403, "%s :No such channel", cmd[1] );
    633                         }
    634                 }
    635         }
    636         else if( g_strcasecmp( cmd[0], "INVITE" ) == 0 )
    637         {
    638                 if( cmd[1] && cmd[2] )
    639                         irc_invite( irc, cmd[1], cmd[2] );
    640                 else
    641                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    642         }
    643         else if( g_strcasecmp( cmd[0], "PRIVMSG" ) == 0 || g_strcasecmp( cmd[0], "NOTICE" ) == 0 )
    644         {
    645                 if( !cmd[1] )
    646                 {
    647                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    648                 }
    649                 else if ( !cmd[2] )
    650                 {
    651                         irc_reply( irc, 412, ":No text to send" );
    652                 }
    653                 else if ( irc->nick && g_strcasecmp( cmd[1], irc->nick ) == 0 )
    654                 {
    655                         irc_write( irc, ":%s!%s@%s %s %s :%s", irc->nick, irc->user, irc->host, cmd[0], cmd[1], cmd[2] );
    656                 }
    657                 else
    658                 {
    659                         if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
    660                         {
    661                                 unsigned int i;
    662                                 char *t = set_getstr( irc, "default_target" );
    663                                
    664                                 if( g_strcasecmp( t, "last" ) == 0 && irc->last_target )
    665                                         cmd[1] = irc->last_target;
    666                                 else if( g_strcasecmp( t, "root" ) == 0 )
    667                                         cmd[1] = irc->mynick;
    668                                
    669                                 for( i = 0; i < strlen( cmd[2] ); i ++ )
    670                                 {
    671                                         if( cmd[2][i] == ' ' ) break;
    672                                         if( cmd[2][i] == ':' || cmd[2][i] == ',' )
    673                                         {
    674                                                 cmd[1] = cmd[2];
    675                                                 cmd[2] += i;
    676                                                 *cmd[2] = 0;
    677                                                 while( *(++cmd[2]) == ' ' );
    678                                                 break;
    679                                         }
    680                                 }
    681                                
    682                                 irc->is_private = 0;
    683                                
    684                                 if( cmd[1] != irc->last_target )
    685                                 {
    686                                         if( irc->last_target )
    687                                                 g_free( irc->last_target );
    688                                         irc->last_target = g_strdup( cmd[1] );
    689                                 }
    690                         }
    691                         else
    692                         {
    693                                 irc->is_private = 1;
    694                         }
    695                         irc_send( irc, cmd[1], cmd[2], ( g_strcasecmp( cmd[0], "NOTICE" ) == 0 ) ? IM_FLAG_AWAY : 0 );
    696                 }
    697         }
    698         else if( g_strcasecmp( cmd[0], "WHO" ) == 0 )
    699         {
    700                 irc_who( irc, cmd[1] );
    701         }
    702         else if( g_strcasecmp( cmd[0], "USERHOST" ) == 0 )
    703         {
    704                 user_t *u;
    705                
    706                 if( !cmd[1] )
    707                 {
    708                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    709                 }
    710                 /* [TV] Usable USERHOST-implementation according to
    711                         RFC1459. Without this, mIRC shows an error
    712                         while connecting, and the used way of rejecting
    713                         breaks standards.
    714                 */
    715                
    716                 for( i = 1; cmd[i]; i ++ )
    717                         if( ( u = user_find( irc, cmd[i] ) ) )
    718                         {
    719                                 if( u->online && u->away )
    720                                         irc_reply( irc, 302, ":%s=-%s@%s", u->nick, u->user, u->host );
    721                                 else
    722                                         irc_reply( irc, 302, ":%s=+%s@%s", u->nick, u->user, u->host );
    723                         }
    724         }
    725         else if( g_strcasecmp( cmd[0], "ISON" ) == 0 )
    726         {
    727                 user_t *u;
    728                 char buff[IRC_MAX_LINE];
    729                 int lenleft;
    730                
    731                 buff[0] = '\0';
    732                
    733                 /* [SH] Leave room for : and \0 */
    734                 lenleft = IRC_MAX_LINE - 2;
    735                
    736                 for( i = 1; cmd[i]; i ++ )
    737                 {
    738                         if( ( u = user_find( irc, cmd[i] ) ) && u->online )
    739                         {
    740                                 /* [SH] Make sure we don't use too much buffer space. */
    741                                 lenleft -= strlen( u->nick ) + 1;
    742                                
    743                                 if( lenleft < 0 )
    744                                 {
    745                                         break;
    746                                 }
    747                                
    748                                 /* [SH] Add the nick to the buffer. Note
    749                                  * that an extra space is always added. Even
    750                                  * if it's the last nick in the list. Who
    751                                  * cares?
    752                                  */
    753                                
    754                                 strcat( buff, u->nick );
    755                                 strcat( buff, " " );
    756                         }
    757                 }
    758                
    759                 /* [WvG] Well, maybe someone cares, so why not remove it? */
    760                 if( strlen( buff ) > 0 )
    761                         buff[strlen(buff)-1] = '\0';
    762                
    763                 /* [SH] By the way, that really *was* WvG talking. */
    764                 /* [WvG] Really? */
    765                 /* [SH] Yeah... But *this* is WvG talking too. ;-P */
    766                 /* [WvG] *sigh* */
    767                
    768                 irc_reply( irc, 303, ":%s", buff );
    769         }
    770         else if( g_strcasecmp( cmd[0], "WATCH" ) == 0 )
    771         {
    772                 /* Obviously we could also mark a user structure as being
    773                    watched, but what if the WATCH command is sent right
    774                    after connecting? The user won't exist yet then... */
    775                 for( i = 1; cmd[i]; i ++ )
    776                 {
    777                         char *nick;
    778                         user_t *u;
    779                        
    780                         if( !cmd[i][0] || !cmd[i][1] )
    781                                 break;
    782                        
    783                         nick = g_strdup( cmd[i] + 1 );
    784                         nick_lc( nick );
    785                        
    786                         u = user_find( irc, nick );
    787                        
    788                         if( cmd[i][0] == '+' )
    789                         {
    790                                 if( !g_hash_table_lookup( irc->watches, nick ) )
    791                                         g_hash_table_insert( irc->watches, nick, nick );
    792                                
    793                                 if( u && u->online )
    794                                         irc_reply( irc, 604, "%s %s %s %d :%s", u->nick, u->user, u->host, time( NULL ), "is online" );
    795                                 else
    796                                         irc_reply( irc, 605, "%s %s %s %d :%s", nick, "*", "*", time( NULL ), "is offline" );
    797                         }
    798                         else if( cmd[i][0] == '-' )
    799                         {
    800                                 gpointer okey, ovalue;
    801                                
    802                                 if( g_hash_table_lookup_extended( irc->watches, nick, &okey, &ovalue ) )
    803                                 {
    804                                         g_free( okey );
    805                                         g_hash_table_remove( irc->watches, okey );
    806                                        
    807                                         irc_reply( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" );
    808                                 }
    809                         }
    810                 }
    811         }
    812         else if( g_strcasecmp( cmd[0], "TOPIC" ) == 0 )
    813         {
    814                 if( cmd[1] && cmd[2] )
    815                         irc_reply( irc, 482, "%s :Cannot change topic", cmd[1] );
    816                 else if( cmd[1] )
    817                         irc_topic( irc, cmd[1] );
    818                 else
    819                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    820         }
    821         else if( g_strcasecmp( cmd[0], "AWAY" ) == 0 )
    822         {
    823                 irc_away( irc, cmd[1] );
    824         }
    825         else if( g_strcasecmp( cmd[0], "WHOIS" ) == 0 )
    826         {
    827                 if( cmd[1] )
    828                 {
    829                         irc_whois( irc, cmd[1] );
    830                 }
    831                 else
    832                 {
    833                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    834                 }
    835         }
    836         else if( g_strcasecmp( cmd[0], "WHOWAS" ) == 0 )
    837         {
    838                 /* For some reason irssi tries a whowas when whois fails. We can
    839                    ignore this, but then the user never gets a "user not found"
    840                    message from irssi which is a bit annoying. So just respond
    841                    with not-found and irssi users will get better error messages */
    842                
    843                 if( cmd[1] )
    844                 {
    845                         irc_reply( irc, 406, "%s :Nick does not exist", cmd[1] );
    846                         irc_reply( irc, 369, "%s :End of WHOWAS", cmd[1] );
    847                 }
    848                 else
    849                 {
    850                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    851                 }
    852         }
    853         else if( ( g_strcasecmp( cmd[0], "NICKSERV" ) == 0 ) || ( g_strcasecmp( cmd[0], "NS" ) == 0 ) )
    854         {
    855                 /* [SH] This aliases the NickServ command to PRIVMSG root */
    856                 /* [TV] This aliases the NS command to PRIVMSG root as well */
    857                 root_command( irc, cmd + 1 );
    858         }
    859         else if( g_strcasecmp( cmd[0], "MOTD" ) == 0 )
    860         {
    861                 irc_motd( irc );
    862         }
    863         else if( g_strcasecmp( cmd[0], "PONG" ) == 0 )
    864         {
    865                 /* We could check the value we get back from the user, but in
    866                    fact we don't care, we're just happy he's still alive. */
    867                 irc->last_pong = gettime();
    868                 irc->pinging = 0;
    869         }
    870         else if( g_strcasecmp( cmd[0], "COMPLETIONS" ) == 0 )
    871         {
    872                 user_t *u = user_find( irc, irc->mynick );
    873                 help_t *h;
    874                 set_t *s;
    875                 int i;
    876                
    877                 irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", "OK" );
    878                
    879                 for( i = 0; commands[i].command; i ++ )
    880                         irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", commands[i].command );
    881                
    882                 for( h = global.help; h; h = h->next )
    883                         irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS help ", h->string );
    884                
    885                 for( s = irc->set; s; s = s->next )
    886                         irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS set ", s->key );
    887                
    888                 irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", "END" );
    889         }
    890         else if( set_getint( irc, "debug" ) )
    891         {
    892                 irc_usermsg( irc, "\002--- Unknown command:" );
    893                 for( i = 0; cmd[i]; i ++ ) irc_usermsg( irc, "%s", cmd[i] );
    894                 irc_usermsg( irc, "\002--------------------" );
    895         }
    896        
    897         return( 1 );
     447                }
     448        }
     449       
     450        return cmd;
     451}
     452
     453char *irc_build_line( char **cmd )
     454{
     455        int i, len;
     456        char *s;
     457       
     458        if( cmd[0] == NULL )
     459                return NULL;
     460       
     461        len = 1;
     462        for( i = 0; cmd[i]; i ++ )
     463                len += strlen( cmd[i] ) + 1;
     464       
     465        if( strchr( cmd[i-1], ' ' ) != NULL )
     466                len ++;
     467       
     468        s = g_new0( char, len + 1 );
     469        for( i = 0; cmd[i]; i ++ )
     470        {
     471                if( cmd[i+1] == NULL && strchr( cmd[i], ' ' ) != NULL )
     472                        strcat( s, ":" );
     473               
     474                strcat( s, cmd[i] );
     475               
     476                if( cmd[i+1] )
     477                        strcat( s, " " );
     478        }
     479        strcat( s, "\r\n" );
     480       
     481        return s;
    898482}
    899483
     
    1054638}
    1055639
    1056 void irc_who( irc_t *irc, char *channel )
    1057 {
    1058         user_t *u = irc->users;
    1059         struct conversation *c;
    1060         GList *l;
    1061        
    1062         if( !channel || *channel == '0' || *channel == '*' || !*channel )
    1063                 while( u )
    1064                 {
    1065                         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 );
    1066                         u = u->next;
    1067                 }
    1068         else if( g_strcasecmp( channel, irc->channel ) == 0 )
    1069                 while( u )
    1070                 {
    1071                         if( u->online )
    1072                                 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 );
    1073                         u = u->next;
    1074                 }
    1075         else if( ( c = conv_findchannel( channel ) ) )
    1076                 for( l = c->in_room; l; l = l->next )
    1077                 {
    1078                         if( ( u = user_findhandle( c->gc, l->data ) ) )
    1079                                 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 );
    1080                 }
    1081         else if( ( u = user_find( irc, channel ) ) )
    1082                 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 );
    1083        
    1084         irc_reply( irc, 315, "%s :End of /WHO list.", channel?channel:"**" );
     640int irc_check_login( irc_t *irc )
     641{
     642        if( irc->user && irc->nick )
     643        {
     644                if( global.conf->authmode == AUTHMODE_CLOSED && irc->status < USTATUS_AUTHORIZED )
     645                {
     646                        irc_reply( irc, 464, ":This server is password-protected." );
     647                        return 0;
     648                }
     649                else
     650                {
     651                        irc_login( irc );
     652                        return 1;
     653                }
     654        }
     655        else
     656        {
     657                /* More information needed. */
     658                return 0;
     659        }
    1085660}
    1086661
     
    1117692        u->realname = g_strdup( irc->realname );
    1118693        u->online = 1;
    1119 //      u->send_handler = msg_echo;
    1120694        irc_spawn( irc, u );
    1121695       
    1122696        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." );
     697       
     698        if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON )
     699                ipc_to_master_str( "CLIENT %s %s :%s\r\n", irc->host, irc->nick, irc->realname );
    1123700       
    1124701        irc->status = USTATUS_LOGGED_IN;
     
    1194771}
    1195772
    1196 void irc_whois( irc_t *irc, char *nick )
    1197 {
    1198         user_t *u = user_find( irc, nick );
    1199        
    1200         if( u )
    1201         {
    1202                 irc_reply( irc, 311, "%s %s %s * :%s", u->nick, u->user, u->host, u->realname );
    1203                
    1204                 if( u->gc )
    1205                         irc_reply( irc, 312, "%s %s.%s :%s network", u->nick, u->gc->user->username,
    1206                                    *u->gc->user->proto_opt[0] ? u->gc->user->proto_opt[0] : "", u->gc->prpl->name );
    1207                 else
    1208                         irc_reply( irc, 312, "%s %s :%s", u->nick, irc->myhost, IRCD_INFO );
    1209                
    1210                 if( !u->online )
    1211                         irc_reply( irc, 301, "%s :%s", u->nick, "User is offline" );
    1212                 else if( u->away )
    1213                         irc_reply( irc, 301, "%s :%s", u->nick, u->away );
    1214                
    1215                 irc_reply( irc, 318, "%s :End of /WHOIS list", nick );
    1216         }
    1217         else
    1218         {
    1219                 irc_reply( irc, 401, "%s :Nick does not exist", nick );
    1220         }
    1221 }
    1222 
    1223 
    1224773void irc_umode_set( irc_t *irc, char *s, int allow_priv )
    1225774{
     
    1251800}
    1252801
    1253 int irc_away( irc_t *irc, char *away )
    1254 {
    1255         user_t *u = user_find( irc, irc->nick );
    1256         GSList *c = get_connections();
    1257        
    1258         if( !u ) return( 0 );
    1259        
    1260         if( away && *away )
    1261         {
    1262                 int i, j;
    1263                
    1264                 /* Copy away string, but skip control chars. Mainly because
    1265                    Jabber really doesn't like them. */
    1266                 u->away = g_malloc( strlen( away ) + 1 );
    1267                 for( i = j = 0; away[i]; i ++ )
    1268                         if( ( u->away[j] = away[i] ) >= ' ' )
    1269                                 j ++;
    1270                 u->away[j] = 0;
    1271                
    1272                 irc_reply( irc, 306, ":You're now away: %s", u->away );
    1273                 /* irc_umode_set( irc, irc->myhost, "+a" ); */
    1274         }
    1275         else
    1276         {
    1277                 if( u->away ) g_free( u->away );
    1278                 u->away = NULL;
    1279                 /* irc_umode_set( irc, irc->myhost, "-a" ); */
    1280                 irc_reply( irc, 305, ":Welcome back" );
    1281         }
    1282        
    1283         while( c )
    1284         {
    1285                 if( ((struct gaim_connection *)c->data)->flags & OPT_LOGGED_IN )
    1286                         proto_away( c->data, u->away );
    1287                
    1288                 c = c->next;
    1289         }
    1290        
    1291         return( 1 );
    1292 }
    1293 
    1294802void irc_spawn( irc_t *irc, user_t *u )
    1295803{
     
    1343851        }
    1344852        g_free( nick );
    1345 }
    1346 
    1347 void irc_invite( irc_t *irc, char *nick, char *channel )
    1348 {
    1349         struct conversation *c = conv_findchannel( channel );
    1350         user_t *u = user_find( irc, nick );
    1351        
    1352         if( u && c && ( u->gc == c->gc ) )
    1353                 if( c->gc && c->gc->prpl && c->gc->prpl->chat_invite )
    1354                 {
    1355                         c->gc->prpl->chat_invite( c->gc, c->id, "", u->handle );
    1356                         irc_reply( irc, 341, "%s %s", nick, channel );
    1357                         return;
    1358                 }
    1359        
    1360         irc_reply( irc, 482, "%s :Invite impossible; User/Channel non-existent or incompatible", channel );
    1361853}
    1362854
  • irc.h

    r2fa825b rb8c2ace  
    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

    r2fa825b rb8c2ace  
    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.