]> jfr.im git - irc/rqf/shadowircd.git/commitdiff
New custom channel mode API allowing reloading such modules.
authorJilles Tjoelker <redacted>
Wed, 31 Mar 2010 23:16:16 +0000 (01:16 +0200)
committerJilles Tjoelker <redacted>
Wed, 31 Mar 2010 23:16:16 +0000 (01:16 +0200)
Additionally, attempting to use too many modes or two times
the same letter is now detected and prevented.

Modules now request that a channel mode be added/orphaned,
instead of ugly manipulation from which that request had
to be guessed.

Slight changes are needed to modules that provide channel modes.
From the old API, one important function has been made static,
the other important function has been renamed, so loading old
modules should fail safely.

extensions/chm_adminonly.c
extensions/chm_operonly.c
extensions/chm_sslonly.c
include/channel.h
include/chmode.h
src/chmode.c
src/ircd.c

index 9380c3df7b9fa360c010378e7d92ed9eb1edd3f3..c478e91e531438cc37336daa9784e6bff07f7c1d 100644 (file)
@@ -17,13 +17,14 @@ mapi_hfn_list_av1 adminonly_hfnlist[] = {
        { NULL, NULL }
 };
 
+static unsigned int mymode;
+
 static int
 _modinit(void)
 {
-       chmode_table['A'].mode_type = find_cflag_slot();
-       chmode_table['A'].set_func = chm_staff;
-
-       construct_noparam_modes();
+       mymode = cflag_add('A', chm_staff);
+       if (mymode == 0)
+               return -1;
 
        return 0;
 }
@@ -31,9 +32,7 @@ _modinit(void)
 static void
 _moddeinit(void)
 {
-       chmode_table['A'].mode_type = 0;
-
-       construct_noparam_modes();
+       cflag_orphan('A');
 }
 
 DECLARE_MODULE_AV1(chm_adminonly, _modinit, _moddeinit, NULL, NULL, adminonly_hfnlist, "$Revision$");
@@ -44,7 +43,7 @@ h_can_join(hook_data_channel *data)
        struct Client *source_p = data->client;
        struct Channel *chptr = data->chptr;
 
-       if((chptr->mode.mode & chmode_flags['A']) && !IsAdmin(source_p)) {
+       if((chptr->mode.mode & mymode) && !IsAdmin(source_p)) {
                sendto_one_numeric(source_p, 519, "%s :Cannot join channel (+A) - you are not an IRC server administrator", chptr->chname);
                data->approved = ERR_CUSTOM;
        }
index 4912e5a7488eacefd39e96b7edbed816cbae1e8b..5cb87ab31be2ab5d53590eb1b85d02b71cc8f6c7 100644 (file)
@@ -17,7 +17,7 @@ mapi_hfn_list_av1 operonly_hfnlist[] = {
        { NULL, NULL }
 };
 
-
+static unsigned int mymode;
 
 /* This is a simple example of how to use dynamic channel modes.
  * Not tested enough yet, use at own risk.
@@ -26,27 +26,18 @@ mapi_hfn_list_av1 operonly_hfnlist[] = {
 static int
 _modinit(void)
 {
-       /* add the channel mode to the available slot */
-       chmode_table['O'].mode_type = find_cflag_slot();
-       chmode_table['O'].set_func = chm_staff;
-
-       construct_noparam_modes();
+       mymode = cflag_add('O', chm_staff);
+       if (mymode == 0)
+               return -1;
 
        return 0;
 }
 
 
-/* Well, the first ugly thing is that we changle chmode_table in _modinit
- * and chmode_flags in _moddeinit (different arrays) - must be fixed.
- * -- dwr
- */
 static void
 _moddeinit(void)
 {
-       /* disable the channel mode and remove it from the available list */
-       chmode_table['O'].mode_type = 0;
-
-       construct_noparam_modes();
+       cflag_orphan('O');
 }
 
 DECLARE_MODULE_AV1(chm_operonly, _modinit, _moddeinit, NULL, NULL, operonly_hfnlist, "$Revision$");
@@ -57,7 +48,7 @@ h_can_join(hook_data_channel *data)
        struct Client *source_p = data->client;
        struct Channel *chptr = data->chptr;
 
-       if((chptr->mode.mode & chmode_flags['O']) && !IsOper(source_p)) {
+       if((chptr->mode.mode & mymode) && !IsOper(source_p)) {
                sendto_one_numeric(source_p, 520, "%s :Cannot join channel (+O) - you are not an IRC operator", chptr->chname);
                data->approved = ERR_CUSTOM;
        }
index 197aac6992bc23aefe5c9ff6cf2efeb1499d8926..2808bb18ace7782fd0645ad426d207f76700a7e0 100644 (file)
@@ -17,13 +17,14 @@ mapi_hfn_list_av1 sslonly_hfnlist[] = {
        { NULL, NULL }
 };
 
+static unsigned int mymode;
+
 static int
 _modinit(void)
 {
-       chmode_table['S'].mode_type = find_cflag_slot();
-       chmode_table['S'].set_func = chm_simple;
-
-       construct_noparam_modes();
+       mymode = cflag_add('S', chm_simple);
+       if (mymode == 0)
+               return -1;
 
        return 0;
 }
@@ -32,9 +33,7 @@ _modinit(void)
 static void
 _moddeinit(void)
 {
-       chmode_table['S'].mode_type = 0;
-
-       construct_noparam_modes();
+       cflag_orphan('S');
 }
 
 DECLARE_MODULE_AV1(chm_sslonly, _modinit, _moddeinit, NULL, NULL, sslonly_hfnlist, "$Revision$");
@@ -45,7 +44,7 @@ h_can_join(hook_data_channel *data)
        struct Client *source_p = data->client;
        struct Channel *chptr = data->chptr;
 
-       if((chptr->mode.mode & chmode_flags['S']) && !IsSSLClient(source_p)) {
+       if((chptr->mode.mode & mymode) && !IsSSLClient(source_p)) {
                sendto_one_notice(source_p, ":Only users using SSL could join this channel!");
                data->approved = ERR_CUSTOM;
        }
index cc8a18c395b89701062f831d38f3d413e2a95c46..3a74689bd45f859ad1f4f852f08b1837f2bea5a3 100644 (file)
@@ -127,11 +127,13 @@ struct ChCapCombo
        int cap_no;
 };
 
+typedef void (*ChannelModeFunc)(struct Client *source_p, struct Channel *chptr,
+               int alevel, int parc, int *parn,
+               const char **parv, int *errors, int dir, char c, long mode_type);
+
 struct ChannelMode
 {
-       void (*set_func) (struct Client * source_p, struct Channel * chptr,
-                     int alevel, int parc, int *parn,
-                     const char **parv, int *errors, int dir, char c, long mode_type);
+       ChannelModeFunc set_func;
        long mode_type;
 };
 
index 9fd623c6d32bb4a7989058391bb791f6818f9ff8..82d8ecd5d4069196a791f1b4bf7aef36b056536a 100644 (file)
@@ -82,9 +82,9 @@ extern void chm_voice(struct Client *source_p, struct Channel *chptr,
           int alevel, int parc, int *parn,
           const char **parv, int *errors, int dir, char c, long mode_type);
 
-extern void construct_noparam_modes(void);
-extern void find_orphaned_cflags(void);
-extern unsigned int find_cflag_slot(void);
+extern unsigned int cflag_add(char c, ChannelModeFunc function);
+extern void cflag_orphan(char c);
+extern void construct_cflags_strings(void);
 extern char cflagsbuf[256];
 extern char cflagsmyinfo[256];
 
index 3161b645c7a683fc3e3adfda696b22877141974e..583e30c3a657aec6078cc982f6d2c301caca30cb 100644 (file)
@@ -74,12 +74,11 @@ int chmode_flags[256];
 
 /* OPTIMIZE ME! -- dwr */
 void
-construct_noparam_modes(void)
+construct_cflags_strings(void)
 {
        int i;
         char *ptr = cflagsbuf;
        char *ptr2 = cflagsmyinfo;
-        static int prev_chmode_flags[256];
         
         *ptr = '\0';
        *ptr2 = '\0';
@@ -103,22 +102,6 @@ construct_noparam_modes(void)
                        chmode_flags[i] = 0;
                }
                 
-               if (prev_chmode_flags[i] != 0 && prev_chmode_flags[i] != chmode_flags[i])
-               {
-                       if (chmode_flags[i] == 0)
-                       {
-                                chmode_table[i].set_func = chm_orphaned;
-                               sendto_realops_snomask(SNO_DEBUG, L_ALL, "Cmode +%c is now orphaned", i);
-                       }
-                       else
-                       {
-                               sendto_realops_snomask(SNO_DEBUG, L_ALL, "Orphaned cmode +%c is picked up by module", i);
-                       }
-                       chmode_flags[i] = prev_chmode_flags[i];
-               }
-               else
-                       prev_chmode_flags[i] = chmode_flags[i];
-                
                switch (chmode_flags[i])
                {
                    case MODE_EXLIMIT:
@@ -162,7 +145,7 @@ construct_noparam_modes(void)
  *                0 if no cflags are available
  * side effects - NONE
  */
-unsigned int
+static unsigned int
 find_cflag_slot(void)
 {
        unsigned int all_cflags = 0, my_cflag = 0, i;
@@ -176,6 +159,34 @@ find_cflag_slot(void)
        return my_cflag;
 }
 
+unsigned int
+cflag_add(char c_, ChannelModeFunc function)
+{
+       int c = (unsigned char)c_;
+
+       if (chmode_table[c].set_func != chm_nosuch &&
+                       chmode_table[c].set_func != chm_orphaned)
+               return 0;
+
+       if (chmode_table[c].set_func == chm_nosuch)
+               chmode_table[c].mode_type = find_cflag_slot();
+       if (chmode_table[c].mode_type == 0)
+               return 0;
+       chmode_table[c].set_func = function;
+       construct_cflags_strings();
+       return chmode_table[c].mode_type;
+}
+
+void
+cflag_orphan(char c_)
+{
+       int c = (unsigned char)c_;
+
+       s_assert(chmode_flags[c] != 0);
+       chmode_table[c].set_func = chm_orphaned;
+       construct_cflags_strings();
+}
+
 static int
 get_channel_access(struct Client *source_p, struct membership *msptr)
 {
index 8577081bffeb1ad2d7aa033796681288568c57ef..a9f6cfbd1ef4cf2446d609b78f4d6051da981746 100644 (file)
@@ -649,13 +649,7 @@ main(int argc, char *argv[])
        init_monitor();
        init_isupport();
 
-       /* noparam core modes have to be initialized before the module
-        * system is initialized, otherwise we have a table collision.
-        *
-        * modules call this after they are done initializing...
-        *    --nenolod
-        */
-        construct_noparam_modes();
+        construct_cflags_strings();
 
        load_all_modules(1);
 #ifndef STATIC_MODULES