--- a/help.conf	Fri May 10 19:32:14 2013 +0200
+++ b/help.conf	Mon May 13 21:41:43 2013 -0600
@@ -180,6 +180,7 @@
 	" N = No Nickname changes are permitted in the channel [o]";
 	" n = Users outside the channel can not send PRIVMSGs to the channel [h]";
 	" O = IRC Operator only channel (settable by IRCops)";
+	" P = Permanent channel (the channel is not destroyed when empty) [o]";
 	" p = Private channel [o]";
 	" Q = No kicks allowed [o]";
 	" R = Only registered (+r) users may join the channel [o]";
diff -r e63bf7596cda include/h.h
--- a/include/h.h	Fri May 10 19:32:14 2013 +0200
+++ b/include/h.h	Mon May 13 21:41:43 2013 -0600
@@ -474,6 +474,7 @@
 #endif
 extern MODVAR Cmode_t EXTMODE_JOINTHROTTLE;
 #endif
+extern MODVAR Cmode_t EXTMODE_PERMANENT;
 
 #ifndef HAVE_STRLCPY
 size_t strlcpy(char *dst, const char *src, size_t size);
diff -r e63bf7596cda src/channel.c
--- a/src/channel.c	Fri May 10 19:32:14 2013 +0200
+++ b/src/channel.c	Mon May 13 21:41:43 2013 -0600
@@ -1370,7 +1370,7 @@
 	Link *lp;
 
         /* if (--chptr->users <= 0) */
-	if (chptr->users == 0 || --chptr->users == 0)
+	if ((chptr->users == 0 || --chptr->users == 0) && !(chptr->mode.extmode & EXTMODE_PERMANENT))
 	{
 		/*
 		 * Now, find all invite links from channel structure
diff -r e63bf7596cda src/extcmodes.c
--- a/src/extcmodes.c	Fri May 10 19:32:14 2013 +0200
+++ b/src/extcmodes.c	Mon May 13 21:41:43 2013 -0600
@@ -57,6 +57,7 @@
 #ifdef STRIPBADWORDS
 Cmode_t EXTMODE_STRIPBADWORDS = 0L;
 #endif
+Cmode_t EXTMODE_PERMANENT = 0L;
 
 #ifdef JOINTHROTTLE
 /* cmode j stuff... */
@@ -73,6 +74,7 @@
 #ifdef STRIPBADWORDS
 int extcmode_cmodeG_requirechop(aClient *cptr, aChannel *chptr, char *para, int checkt, int what);
 #endif
+int extcmode_cmodeP_requirechop(aClient *cptr, aChannel *chptr, char *para, int checkt, int what);
 
 void make_extcmodestr()
 {
@@ -111,6 +113,11 @@
 	req.is_ok = extcmode_cmodeT_requirechop;
 	req.flag = 'T';
 	CmodeAdd(NULL, req, &EXTMODE_NONOTICE);
+
+	req.flag = 'P';
+	req.is_ok = extcmode_cmodeP_requirechop;
+	CmodeAdd(NULL, req, &EXTMODE_PERMANENT);
+
 #ifdef STRIPBADWORDS
 	req.flag = 'G';
 	req.is_ok = extcmode_cmodeG_requirechop;
@@ -401,6 +408,15 @@
 	return EX_DENY;
 }
 
+int extcmode_cmodeP_requirechop(aClient *cptr, aChannel *chptr, char *para, int checkt, int what)
+{
+	if (IsPerson(cptr) && is_chan_op(cptr, chptr))
+		return EX_ALLOW;
+	if (checkt == EXCHK_ACCESS_ERR) /* can only be due to being halfop */
+		sendto_one(cptr, err_str(ERR_NOTFORHALFOPS), me.name, cptr->name, 'P');
+	return EX_DENY;
+}
+
 #ifdef JOINTHROTTLE
 /*** CHANNEL MODE +j STUFF ******/
 int cmodej_is_ok(aClient *sptr, aChannel *chptr, char *para, int type, int what)
