Release bumped to "gts4".
[tac_plus.git] / cfgeval.c
index 8b2f33c..f0aed72 100644 (file)
--- a/cfgeval.c
+++ b/cfgeval.c
@@ -379,12 +379,14 @@ struct expr *parent;
        switch (expr->type) {
 
        case S_not:
-           expr_sink_internal(expr->u.not.child, membership, expr /* parent */);
+           if (expr_sink_internal(expr->u.not.child, membership, expr /* parent */))
+               return (1);
            break;
 
        case S_and:
        case S_or:
-           expr_sink_internal(expr->u.and_or.child_first, membership, expr /* parent */);
+           if (expr_sink_internal(expr->u.and_or.child_first, membership, expr /* parent */))
+               return (1);
            break;
 
        case S_user:
@@ -392,11 +394,18 @@ struct expr *parent;
        case S_group:
            tac_list_node_init(&expr->eval_scan.u.entity.notify_expr_node);
            expr->u.entity.entity = entity_lookup(expr->type, expr->u.entity.name);
+           if (!expr->u.entity.entity && expr->type == S_host) {
+               expr->u.entity.entity = new_entity(expr->type, (char *)expr->u.entity.name, expr->line);
+               if (!expr->u.entity.entity)
+                   return (1);
+               expr->u.entity.name = NULL;
+           }
            if (!expr->u.entity.entity) {
                report(LOG_ERR, "referenced entity %s %s not found on line %d",
                        entity_type_to_string(expr->type), expr->u.entity.name, expr->line);
                return (1);
-               }
+           }
+           /* already NULLed for not-yet-existing S_host */
            free((char *) expr->u.entity.name);
            expr->u.entity.name = NULL;
            break;
@@ -1067,8 +1076,15 @@ struct expr *expr;
        report(LOG_DEBUG, "expr_eval_notify_expr: REGISTERED notify " PF_EXPR " when " PF_ENTITY " is known",
                PA_EXPR(expr), PA_ENTITY(entity));
 
-    if (tac_list_node_get_list(&expr->eval_scan.u.entity.notify_expr_node))
+    if (tac_list_node_get_list(&expr->eval_scan.u.entity.notify_expr_node)) {
+#ifdef SCAN_PARANOIA
+       if (&entity->eval_scan.notify_expr_list
+        != tac_list_node_get_list(&expr->eval_scan.u.entity.notify_expr_node))
+           report(LOG_ERR, "Another " PF_ENTITY " already registered in notify node of " PF_EXPR,
+               PA_ENTITY(EXPR_ENTITY_TO_NOTIFYING_ENTITY(expr)), PA_EXPR(expr));
+#endif
        return;
+    }
 
     tac_list_addtail(&entity->eval_scan.notify_expr_list,
            &expr->eval_scan.u.entity.notify_expr_node);
@@ -1319,6 +1335,13 @@ top_down:
                    report(LOG_DEBUG, "expr_eval_immediate: bottom_up and_or: full scan: " PF_EXPR,
                            PA_EXPR(expr_single));
 
+               /* It would be nice to pretend that all 'veto' decisions already made in the child
+                * had to set our 'result' to the correct value. But 'consent' decisions don't set
+                * us and the behaviour of auto-set from the child in 'veto' case may get changed
+                * in the future versions.
+                * So we rather don't depend on it.
+                * This overhead doesn't change altgorithmic complexity anyway.
+                */
                result_parent = consent;
                for (expr_child = expr_parent->u.and_or.child_first; expr_child; expr_child = expr_child->next)
                {
@@ -1447,10 +1470,13 @@ struct membership *membership;
     child_entity = MEMBERSHIP_TO_CHILD_ENTITY( membership);
     check_request_scan_entity( child_entity, 0);
 
+#if 0 /* non-valid membership doesn't YET solve the parent! */
     if (child_entity->request_scan.belongs == ER_FALSE || membership_valid == ER_FALSE) {
        membership_parent_solve(membership, ER_FALSE);
        return;
     }
+#endif
+
     if (child_entity->request_scan.belongs == ER_TRUE  && membership_valid == ER_TRUE ) {
        membership_parent_solve(membership, ER_TRUE );
        return;
@@ -1461,8 +1487,8 @@ struct membership *membership;
     if (parent_entity->request_scan.belongs == ER_UNKNOWN)
        register_kicked_entity(parent_entity, 0 /* priority */);
 
-    if ( child_entity->request_scan.belongs != ER_UNKNOWN
-     && parent_entity->request_scan.belongs != ER_UNKNOWN)
+    if (parent_entity->request_scan.belongs != ER_UNKNOWN
+     || (child_entity->request_scan.belongs == ER_FALSE || membership_valid == ER_FALSE))
        membership_solved(membership);
 
     if (debug & DEBUG_CFGEVAL_FLAG)