Date: Thu, 4 Jan 2001 12:23:54 +0200
From: Peter Pentchev <CENSORED>
Reply-To: hybrid@the-project.org
To: hybrid@the-project.org
Subject: proposed default channel mode patch

Hi,

First of all, great work on hybrid-6!

I tarried with sending this patch because of the feature freeze, but here
it is now.  It provides a compile-time tweak to change the server's default
mode for newly created channels.  In the near future I'll look into making
it /quote set'table, but for the present, it's only settable in config.h.

Hope that helps, and keep up the good work!

G'luck,
Peter

-- 
What would this sentence be like if it weren't self-referential?

diff -urN ircd-hybrid-6.0/include/config.h ircd-hybrid-6.0+defcmode/include/config.h
--- ircd-hybrid-6.0/include/config.h	Mon Nov 27 06:11:47 2000
+++ ircd-hybrid-6.0+defcmode/include/config.h	Thu Jan  4 12:11:23 2001
@@ -993,6 +993,16 @@
  */
 #undef CHROOTDIR
 
+/* DEFAULT_CHANMODE - default mode set on creating a channel
+ * Define this if you do not like the default setting of "nt".
+ *
+ * NOTE: Defining this may have a negative performance impact e.g. on big
+ * netjoins.  Even defining this to its default value "nt" includes
+ * some additional code.  Use at your own risk.
+ */
+#undef DEFAULT_CHANMODE
+/* #define DEFAULT_CHANMODE "pnlk 1 lame" */
+
 /* ------------------------- END CONFIGURATION SECTION -------------------- */
 #define MAX_CLIENTS INIT_MAXCLIENTS
 
diff -urN ircd-hybrid-6.0/include/ircd.h ircd-hybrid-6.0+defcmode/include/ircd.h
--- ircd-hybrid-6.0/include/ircd.h	Sun Dec 31 02:11:55 2000
+++ ircd-hybrid-6.0+defcmode/include/ircd.h	Thu Jan  4 12:11:23 2001
@@ -134,6 +134,10 @@
 extern time_t         nextconnect;
 extern time_t         nextping;
 
+#ifdef DEFAULT_CHANMODE
+extern char	      defcmodestr[];
+extern struct Mode    defcmode;
+#endif
 
 extern struct Client* local_cptr_list;
 extern struct Client* oper_cptr_list;
diff -urN ircd-hybrid-6.0/src/channel.c ircd-hybrid-6.0+defcmode/src/channel.c
--- ircd-hybrid-6.0/src/channel.c	Mon Nov 27 06:11:49 2000
+++ ircd-hybrid-6.0+defcmode/src/channel.c	Thu Jan  4 12:11:23 2001
@@ -3327,9 +3327,10 @@
         {
           if( flags & CHFL_CHANOP )
             {
-              chptr->mode.mode |= MODE_TOPICLIMIT;
-              chptr->mode.mode |= MODE_NOPRIVMSGS;
-
+#ifndef DEFAULT_CHANMODE
+	      /* not overridden, use +nt */
+	      chptr->mode.mode |= MODE_TOPICLIMIT | MODE_NOPRIVMSGS;
+	      
               sendto_channel_butserv(chptr, sptr,
                                  ":%s MODE %s +nt",
                                  me.name, chptr->chname);
@@ -3337,6 +3338,23 @@
               sendto_match_servs(chptr, sptr, 
                                  ":%s MODE %s +nt",
                                  me.name, chptr->chname);
+#else
+	      /* copy default mode */
+	      chptr->mode.mode |= defcmode.mode;
+	      if ((chptr->mode.limit == 0) && (defcmode.limit != 0))
+		chptr->mode.limit = defcmode.limit;
+	      if ((chptr->mode.key[0] == 0) && (defcmode.key[0] != 0))
+		memcpy(chptr->mode.key, defcmode.key, sizeof(chptr->mode.key));
+
+	      /* send correct mode string */
+	      sendto_channel_butserv(chptr, sptr,
+				 ":%s MODE %s +%s",
+				 me.name, chptr->chname, defcmodestr);
+	      
+	      sendto_match_servs(chptr, sptr, 
+				 ":%s MODE %s +%s",
+				 me.name, chptr->chname, defcmodestr);
+#endif
             }
 
           del_invite(sptr, chptr);
diff -urN ircd-hybrid-6.0/src/ircd.c ircd-hybrid-6.0+defcmode/src/ircd.c
--- ircd-hybrid-6.0/src/ircd.c	Sun Dec 31 02:12:00 2000
+++ ircd-hybrid-6.0+defcmode/src/ircd.c	Thu Jan  4 12:11:23 2001
@@ -167,6 +167,10 @@
 time_t LCF = LOADCFREQ;
 float currlife = 0.0;
 
+#ifdef DEFAULT_CHANMODE
+char   defcmodestr[65];	/* arbitrary.. */
+struct Mode defcmode = {0, 0, ""};
+#endif
 
 /*
  * get_vm_top - get the operating systems notion of the resident set size
@@ -638,6 +642,103 @@
 }
 
 
+/*
+** next_word
+**	str	- string to examine
+*/
+
+const char *next_word(const char *str, unsigned *plen, const char **pstr) {
+  const char *p;
+  unsigned int len = 0;
+
+  if (str == NULL) {
+    p = NULL;
+  } else if (p = strchr(str, ' '), p != NULL) {
+    len = p - str;
+    while(*p && isspace(*p))
+      p++;
+    if (*p == '\0')
+      p = NULL;
+  }
+  
+  if (plen) *plen = len;
+  if (pstr) *pstr = p;
+  return p;
+}
+
+/*
+** string_to_mode
+**	str	- mode string
+**	pmode	- value/result mode
+*/
+
+static struct {
+  char c;
+  unsigned mode;
+} modechar[] = {
+  {'p', MODE_PRIVATE},
+  {'s', MODE_SECRET},
+  {'m', MODE_MODERATED},
+  {'t', MODE_TOPICLIMIT},
+  {'i', MODE_INVITEONLY},
+  {'n', MODE_NOPRIVMSGS}
+};
+#define MODECHAR_CNT	(sizeof(modechar)/sizeof(modechar[0]))
+
+int string_to_mode(const char *str, struct Mode *pmode) {
+  const char *p, *w;
+
+  next_word(str, NULL, &w);
+  
+  for(p = str; *p && !isspace(*p); p++) {
+    unsigned i, l;
+    const char *nw;
+
+    /* is it a simple flag? */
+    for(i = 0; i < MODECHAR_CNT; i++)
+      if (modechar[i].c == *p)
+	break;
+
+    if (i < MODECHAR_CNT) {
+      /* yes, set it and go on */
+      pmode->mode |= modechar[i].mode;
+      continue;
+    }
+
+    /* it probably takes an argument; find the end and len of the argument */
+    if (w == NULL) {
+      /* some kind of error? */
+      continue;
+    }
+    if (next_word(w, &l, &nw) == NULL)
+      l = strlen(w);
+    /* if next_word() returns non-null, it has already updated l */
+    
+    switch(*p) {
+      case 'k':
+	if (l > KEYLEN)
+	  l = KEYLEN;
+	
+	strncpy(pmode->key, w, l);
+	pmode->key[l] = '\0';
+	pmode->mode |= MODE_KEY;
+	break;
+	
+      case 'l':
+	pmode->limit = atoi(w);
+	pmode->mode |= MODE_LIMIT;
+	break;
+	
+      default:
+	/* some kind of error? */
+    }
+    
+    /* skip the argument for further processing */
+    w = nw;
+  }
+}
+
+
 int main(int argc, char *argv[])
 {
   uid_t       uid;
@@ -835,6 +936,13 @@
   me.serv->up = me.name;
   me.lasttime = me.since = me.firsttime = CurrentTime;
   add_to_client_hash_table(me.name, &me);
+
+#ifdef DEFAULT_CHANMODE
+  strncpy(defcmodestr, DEFAULT_CHANMODE, sizeof(defcmodestr));
+  defcmodestr[sizeof(defcmodestr)-1] = '\0';
+  memset(&defcmode, 0, sizeof(defcmode));
+  string_to_mode(defcmodestr, &defcmode);
+#endif
 
   check_class();
   write_pidfile();
