static PromiseResult VerifyProcessOp(EvalContext *ctx, Item *procdata, Attributes a, const Promise *pp) { bool do_signals = true; int out_of_range; int killed = 0; bool need_to_restart = true; Item *killlist = NULL; int matches = FindPidMatches(procdata, &killlist, a, pp->promiser); /* promise based on number of matches */ PromiseResult result = PROMISE_RESULT_NOOP; if (a.process_count.min_range != CF_NOINT) /* if a range is specified */ { if ((matches < a.process_count.min_range) || (matches > a.process_count.max_range)) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Process count for '%s' was out of promised range (%d found)", pp->promiser, matches); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); for (const Rlist *rp = a.process_count.out_of_range_define; rp != NULL; rp = rp->next) { ClassRef ref = ClassRefParse(RlistScalarValue(rp)); EvalContextClassPutSoft(ctx, RlistScalarValue(rp), CONTEXT_SCOPE_NAMESPACE, "source=promise"); ClassRefDestroy(ref); } out_of_range = true; } else { for (const Rlist *rp = a.process_count.in_range_define; rp != NULL; rp = rp->next) { ClassRef ref = ClassRefParse(RlistScalarValue(rp)); EvalContextClassPutSoft(ctx, RlistScalarValue(rp), CONTEXT_SCOPE_NAMESPACE, "source=promise"); ClassRefDestroy(ref); } cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Process promise for '%s' is kept", pp->promiser); out_of_range = false; } } else { out_of_range = true; } if (!out_of_range) { DeleteItemList(killlist); return result; } if (a.transaction.action == cfa_warn) { do_signals = false; result = PromiseResultUpdate(result, PROMISE_RESULT_WARN); } else { do_signals = true; } /* signal/kill promises for existing matches */ if (do_signals && (matches > 0)) { if (a.process_stop != NULL) { if (DONTDO) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Need to keep process-stop promise for '%s', but only a warning is promised", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_WARN); } else { if (IsExecutable(CommandArg0(a.process_stop))) { ShellCommandReturnsZero(a.process_stop, SHELL_TYPE_NONE); } else { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Process promise to stop '%s' could not be kept because '%s' the stop operator failed", pp->promiser, a.process_stop); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); DeleteItemList(killlist); return result; } } } killed = DoAllSignals(ctx, killlist, a, pp, &result); } /* delegated promise to restart killed or non-existent entries */ need_to_restart = (a.restart_class != NULL) && (killed || (matches == 0)); DeleteItemList(killlist); if (!need_to_restart) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "No restart promised for %s", pp->promiser); return result; } else { if (a.transaction.action == cfa_warn) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Need to keep restart promise for '%s', but only a warning is promised", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_WARN); } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Making a one-time restart promise for '%s'", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); EvalContextClassPutSoft(ctx, a.restart_class, CONTEXT_SCOPE_NAMESPACE, "source=promise"); } } return result; }
static void VerifyProcessOp(EvalContext *ctx, Item *procdata, Attributes a, Promise *pp) { int matches = 0, do_signals = true, out_of_range, killed = 0, need_to_restart = true; Item *killlist = NULL; matches = FindPidMatches(ctx, procdata, &killlist, a, pp->promiser); /* promise based on number of matches */ if (a.process_count.min_range != CF_NOINT) /* if a range is specified */ { if ((matches < a.process_count.min_range) || (matches > a.process_count.max_range)) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Process count for '%s' was out of promised range (%d found)", pp->promiser, matches); for (const Rlist *rp = a.process_count.out_of_range_define; rp != NULL; rp = rp->next) { if (!EvalContextHeapContainsSoft(ctx, rp->item)) { EvalContextHeapAddSoft(ctx, rp->item, PromiseGetNamespace(pp)); } } out_of_range = true; } else { for (const Rlist *rp = a.process_count.in_range_define; rp != NULL; rp = rp->next) { if (!EvalContextHeapContainsSoft(ctx, rp->item)) { EvalContextHeapAddSoft(ctx, rp->item, PromiseGetNamespace(pp)); } } cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Process promise for '%s' is kept", pp->promiser); out_of_range = false; } } else { out_of_range = true; } if (!out_of_range) { return; } if (a.transaction.action == cfa_warn) { do_signals = false; } else { do_signals = true; } /* signal/kill promises for existing matches */ if (do_signals && (matches > 0)) { if (a.process_stop != NULL) { if (DONTDO) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Need to keep process-stop promise for '%s', but only a warning is promised", pp->promiser); } else { if (IsExecutable(CommandArg0(a.process_stop))) { ShellCommandReturnsZero(a.process_stop, SHELL_TYPE_NONE); } else { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_FAIL, pp, a, "Process promise to stop '%s' could not be kept because '%s' the stop operator failed", pp->promiser, a.process_stop); DeleteItemList(killlist); return; } } } killed = DoAllSignals(ctx, killlist, a, pp); } /* delegated promise to restart killed or non-existent entries */ need_to_restart = (a.restart_class != NULL) && (killed || (matches == 0)); DeleteItemList(killlist); if (!need_to_restart) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "No restart promised for %s", pp->promiser); return; } else { if (a.transaction.action == cfa_warn) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Need to keep restart promise for '%s', but only a warning is promised", pp->promiser); } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Making a one-time restart promise for '%s'", pp->promiser); EvalContextHeapAddSoft(ctx, a.restart_class, PromiseGetNamespace(pp)); } } }
static void VerifyProcessOp(Item *procdata, Attributes a, Promise *pp) { int matches = 0, do_signals = true, out_of_range, killed = 0, need_to_restart = true; Item *killlist = NULL; CfDebug("VerifyProcessOp\n"); matches = FindPidMatches(procdata, &killlist, a, pp); /* promise based on number of matches */ if (a.process_count.min_range != CF_NOINT) /* if a range is specified */ { if (matches < a.process_count.min_range || matches > a.process_count.max_range) { cfPS(cf_error, CF_CHG, "", pp, a, " !! Process count for \'%s\' was out of promised range (%d found)\n", pp->promiser, matches); AddEphemeralClasses(a.process_count.out_of_range_define); out_of_range = true; } else { AddEphemeralClasses(a.process_count.in_range_define); cfPS(cf_verbose, CF_NOP, "", pp, a, " -> Process promise for %s is kept", pp->promiser); out_of_range = false; } } else { out_of_range = true; } if (!out_of_range) { return; } if (a.transaction.action == cfa_warn) { do_signals = false; } else { do_signals = true; } /* signal/kill promises for existing matches */ if (do_signals && matches > 0) { if (a.process_stop != NULL) { if (DONTDO) { cfPS(cf_error, CF_WARN, "", pp, a, " -- Need to keep process-stop promise for %s, but only a warning is promised", pp->promiser); } else { if (IsExecutable(GetArg0(a.process_stop))) { ShellCommandReturnsZero(a.process_stop, false); } else { cfPS(cf_verbose, CF_FAIL, "", pp, a, "Process promise to stop %s could not be kept because %s the stop operator failed", pp->promiser, a.process_stop); DeleteItemList(killlist); return; } } } killed = DoAllSignals(killlist, a, pp); } /* delegated promise to restart killed or non-existent entries */ need_to_restart = (a.restart_class != NULL) && (killed || matches == 0); DeleteItemList(killlist); if (!need_to_restart) { cfPS(cf_verbose, CF_NOP, "", pp, a, " -> No restart promised for %s\n", pp->promiser); return; } else { if (a.transaction.action == cfa_warn) { cfPS(cf_error, CF_WARN, "", pp, a, " -- Need to keep restart promise for %s, but only a warning is promised", pp->promiser); } else { cfPS(cf_inform, CF_CHG, "", pp, a, " -> Making a one-time restart promise for %s", pp->promiser); NewClass(a.restart_class); } } }