+ if (r == class_none)
+ return (l);
+
+ /* --- Do the job --- */
+
+ return (class__binop(l, r, clNode_diff));
+}
+
+/* --- @class_isect@ --- *
+ *
+ * Arguments: @class_node *l@ = left argument
+ * @class_node *r@ = right argument
+ *
+ * Returns: A class node representing the intersection of the two
+ * classes.
+ *
+ * Use: Performs the intersecion operation on classes. If the types
+ * don't match, then a null pointer is returned. Both @l@ and
+ * @r@ may be modified, and will be decremented before they get
+ * returned to you. If you don't want that to happen, ensure
+ * that you've claimed a reference to the original versions.
+ */
+
+class_node *class_isect(class_node *l, class_node *r)
+{
+ /* --- Check for the really simple cases --- */
+
+ if (l == class_none || r == class_none) {
+ class_dec(l);
+ class_dec(r);
+ return (class_none);
+ }
+
+ if (l == class_all)
+ return (r);
+ if (r == class_all)
+ return (l);
+
+ /* --- Do the job --- */
+
+ return (class__binop(l, r, clNode_isect));
+}
+
+/*----- Building the predefined classes -----------------------------------*/
+
+/* --- @class_addUser@ --- *
+ *
+ * Arguments: @class_node *c@ = pointer to a class node (may be null)
+ * @uid_t u@ = user id number
+ *
+ * Returns: Pointer to the combined node.
+ *
+ * Use: Adds a user to a node, maybe hashifying it.
+ */
+
+class_node *class_addUser(class_node *c, uid_t u)
+{
+ if (!c)
+ return (class_fromUser(clType_user, u));
+ if ((c->type & clNode_mask) == clNode_immed)
+ c = class__hashify(c);
+ sym_find(&c->v.t, (char *)&u, sizeof(u), sizeof(sym_base), 0);
+ return (c);
+}
+
+/* --- @class_addString@ --- *
+ *
+ * Arguments: @class_node *c@ = pointer to a class node (may be null)
+ * @const char *s@ = pointer to a string
+ *
+ * Returns: Pointer to the combined node.
+ *
+ * Use: Adds a user to a node, maybe hashifying it.
+ */
+
+class_node *class_addString(class_node *c, const char *s)
+{
+ class_node *n = class_fromString(clType_host, s); /* hack */
+ if (c)
+ return (class_union(c, n));
+ else
+ return (n);
+}
+
+/*----- Matching functions ------------------------------------------------*/
+
+/* --- @class_matchUser@ --- *
+ *
+ * Arguments: @class_node *c@ = pointer to root class node
+ * @uid_t u@ = user id number
+ *
+ * Returns: Nonzero if it matches, zero if it doesn't.
+ *
+ * Use: Determines whether a user is matched by a class. Assumes
+ * that the types are correct.
+ */
+
+int class_matchUser(class_node *c, uid_t u)
+{
+ class_node *cc;
+
+ for (cc = 0; c; c = cc, cc = 0) {
+ if (c == class_none)
+ return (0);
+ if (c == class_all)
+ return (1);
+ switch (c->type & clNode_mask) {
+ case clNode_immed:
+ return (u == c->v.u);
+ break;
+ case clNode_hash:
+ return (sym_find(&c->v.t, (char *)&u, sizeof(u), 0, 0) != 0);
+ break;
+ case clNode_union:
+ if (class_matchUser(c->v.c.l, u))