* accessobject.c (ownercheck): allow a base class access to protected
  objects of its derived classes; allow anything that has an attribute
  named "__privileged__" access to anything.
* object.[ch]: added hasattr() -- test whether getattr() will succeed.
diff --git a/Objects/accessobject.c b/Objects/accessobject.c
index c9b7ce3..6a8981e 100644
--- a/Objects/accessobject.c
+++ b/Objects/accessobject.c
@@ -25,14 +25,12 @@
 /* Access object implementation */
 
 /* XXX TO DO LIST
-   - need a "super user" mechanism for debugger etc.
    - __init__ and __del__ (and all other similar methods)
-     should be usable even when private, not ignored
-   - "from foo import bar" should check access of bar
+     should be usable even when private, not ignored (???)
 */
 
 #include "allobjects.h"
-
+#include "ceval.h"
 #include "structmember.h"
 #include "modsupport.h"		/* For getargs() etc. */
 
@@ -112,9 +110,9 @@
 }
 
 object *
-getaccessvalue(op, owner)
+getaccessvalue(op, caller)
 	object *op;
-	object *owner;
+	object *caller;
 {
 	register accessobject *ap;
 	if (!is_accessobject(op)) {
@@ -123,7 +121,7 @@
 	}
 	ap = (accessobject *)op;
 	
-	if (!ownercheck(owner, ap->ac_owner, AC_R, ap->ac_mode)) {
+	if (!ownercheck(caller, ap->ac_owner, AC_R, ap->ac_mode)) {
 		err_setstr(AccessError, "read access denied");
 		return NULL;
 	}
@@ -137,9 +135,9 @@
 }
 
 int
-setaccessvalue(op, owner, value)
+setaccessvalue(op, caller, value)
 	object *op;
-	object *owner;
+	object *caller;
 	object *value;
 {
 	register accessobject *ap;
@@ -149,7 +147,7 @@
 	}
 	ap = (accessobject *)op;
 	
-	if (!ownercheck(owner, ap->ac_owner, AC_W, ap->ac_mode)) {
+	if (!ownercheck(caller, ap->ac_owner, AC_W, ap->ac_mode)) {
 		err_setstr(AccessError, "write access denied");
 		return -1;
 	}
@@ -230,6 +228,19 @@
 }
 
 static int
+isprivileged(caller)
+	object *caller;
+{
+	object *g;
+	if (caller != NULL && hasattr(caller, "__privileged__"))
+		return 1;
+	g = getglobals();
+	if (g != NULL && dictlookup(g, "__privileged__"))
+		return 1;
+	return 0;
+}
+
+static int
 ownercheck(caller, owner, access, mode)
 	object *caller;
 	object *owner;
@@ -237,12 +248,13 @@
 	int mode;
 {
 	int mask = AC_PUBLIC;
-	if (owner != NULL) {
-		if (caller == owner)
-			mask |= AC_PRIVATE | AC_PROTECTED;
-		else if (is_classobject(owner) && issubclass(caller, owner))
+	if (caller == owner || isprivileged(caller))
+		mask |= AC_PRIVATE | AC_PROTECTED;
+	else if (caller != NULL && owner != NULL &&
+		 is_classobject(owner) && is_classobject(caller) &&
+		 (issubclass(caller, owner) ||
+		  issubclass(owner, caller)))
 			mask |= AC_PROTECTED;
-	}
 	return access & mode & mask;
 }
 
diff --git a/Objects/object.c b/Objects/object.c
index e28158e..a469797 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -194,6 +194,20 @@
 }
 
 int
+hasattr(v, name)
+	object *v;
+	char *name;
+{
+	object *res = getattr(v, name);
+	if (res != NULL) {
+		DECREF(res);
+		return 1;
+	}
+	err_clear();
+	return 0;
+}
+
+int
 setattr(v, name, w)
 	object *v;
 	char *name;