access(): Erstellen der access-closure ausgelagert.

Das Neuerzeugen der channel-access closure und das Loeschen
der Ebene im Misserfolgsfall wurden in eine separate
Funktion ausgelagert.

Change-Id: I20ecab3f24d70a63d7aff9fd3794b96679b43c40
diff --git a/p/daemon/channeld.c b/p/daemon/channeld.c
index 3dade1c..502a943 100644
--- a/p/daemon/channeld.c
+++ b/p/daemon/channeld.c
@@ -33,7 +33,9 @@
                                           closure access_rights,
                                           string channel_desc,
                                           string|object master_object,
-                                          string readable_channelname }) ]) */
+                                          string readable_channelname }) ])
+ The master_object is also called the supervisor.
+ */
 private nosave mapping channels = ([]);
 //private nosave mapping lowerch; // unused
 
@@ -604,31 +606,11 @@
 #define MASTER_OB(x) channels[x][I_MASTER]
 #define ACC_CLOSURE(x) channels[x][I_ACCESS]
 
-// access() - check access by looking for the right argument types and
-//            calling access closures respectively
-// SEE: new, join, leave, send, list, users
-// Note: <pl> is usually an object, only the master supplies a string during
-//       runtime error handling.
-// Wertebereich: 0 fuer Zugriff verweigert, 1 fuer Zugriff erlaubt, 2 fuer
-// Zugriff erlaubt fuer privilegierte Objekte, die senden duerfen ohne
-// Zuhoerer zu sein.
-varargs private int access(string ch, object|string pl, string cmd,
-                           string txt)
+// Stellt sicher, dass einen Ebenen-Supervisor gibt.
+// Wenn dies nicht moeglich ist (z.b. leere Ebene), dann wird die Ebene
+// geloescht und 0 zurueckgegeben.
+private int assert_supervisor(string ch)
 {
-  if (!sizeof(ch))
-    return 0;
-
-  ch = lower_case(ch);
-  if(!pointerp(channels[ch]))
-    return 0;
-
-  if ( !previous_object(1) || !extern_call() ||
-       previous_object(1) == this_object() ||
-       (stringp(MASTER_OB(ch)) &&
-        previous_object(1) == find_object(MASTER_OB(ch))) ||
-        getuid(previous_object(1)) == ROOTID)
-    return 2;
-
   // Es ist keine Closure vorhanden, d.h. der Ebenenbesitzer wurde zerstoert.
   if (!closurep(ACC_CLOSURE(ch)))
   {
@@ -669,6 +651,34 @@
     // Der neue Ebenenbesitzer tritt auch gleich der Ebene bei.
     this_object()->join(ch, find_object(MASTER_OB(ch)));
   }
+  return 1;
+}
+
+// access() - check access by looking for the right argument types and
+//            calling access closures respectively
+// SEE: new, join, leave, send, list, users
+// Note: <pl> is usually an object, only the master supplies a string during
+//       runtime error handling.
+// Wertebereich: 0 fuer Zugriff verweigert, 1 fuer Zugriff erlaubt, 2 fuer
+// Zugriff erlaubt fuer privilegierte Objekte, die senden duerfen ohne
+// Zuhoerer zu sein. (Die Aufrufer akzeptieren aber auch alle negativen Werte
+// als Erfolg und alles ueber >2 als privilegiert.)
+varargs private int access(string ch, object|string pl, string cmd,
+                           string txt)
+{
+  if (!sizeof(ch))
+    return 0;
+
+  ch = lower_case(ch);
+  if(!pointerp(channels[ch]))
+    return 0;
+
+  if ( !previous_object(1) || !extern_call() ||
+       previous_object(1) == this_object() ||
+       (stringp(MASTER_OB(ch)) &&
+        previous_object(1) == find_object(MASTER_OB(ch))) ||
+        getuid(previous_object(1)) == ROOTID)
+    return 2;
 
   if (!objectp(pl) ||
       ((previous_object(1) != pl) && (previous_object(1) != this_object())))
@@ -677,7 +687,7 @@
   if (IsBanned(pl, cmd))
     return 0;
 
-  if (!ACC_CLOSURE(ch))
+  if (!assert_supervisor(ch))
     return 1;
 
   return funcall(ACC_CLOSURE(ch), ch, pl, cmd, &txt);