static void LogPromiseContext(const EvalContext *ctx, const Promise *pp) { Rval retval; char *v; if (EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_VERSION, &retval)) { v = (char *) retval.item; } else { v = "not specified"; } const char *sp = PromiseGetHandle(pp); if (sp == NULL) { sp = PromiseID(pp); } if (sp == NULL) { sp = "(unknown)"; } Log(LOG_LEVEL_INFO, "Report relates to a promise with handle '%s'", sp); if (PromiseGetBundle(pp)->source_path) { Log(LOG_LEVEL_INFO, "Made in version '%s' of '%s' near line %zu", v, PromiseGetBundle(pp)->source_path, pp->offset.line); } else { Log(LOG_LEVEL_INFO, "Promise is made internally by CFEngine"); } switch (pp->promisee.type) { case RVAL_TYPE_SCALAR: Log(LOG_LEVEL_INFO,"The promise was made to '%s'", (char *) pp->promisee.item); break; case RVAL_TYPE_LIST: { Writer *w = StringWriter(); RlistWrite(w, pp->promisee.item); Log(LOG_LEVEL_INFO, "The promise was made to (stakeholders) '%s'", StringWriterData(w)); WriterClose(w); break; } default: break; } if (pp->comment) { Log(LOG_LEVEL_INFO, "Comment '%s'", pp->comment); } }
static PromiseResult ExpandPromiseAndDo(EvalContext *ctx, const Promise *pp, Rlist *lists, Rlist *containers, PromiseActuator *ActOnPromise, void *param) { const char *handle = PromiseGetHandle(pp); EvalContextStackPushPromiseFrame(ctx, pp, true); PromiseIterator *iter_ctx = NULL; size_t i = 0; PromiseResult result = PROMISE_RESULT_NOOP; Buffer *expbuf = BufferNew(); for (iter_ctx = PromiseIteratorNew(ctx, pp, lists, containers); PromiseIteratorHasMore(iter_ctx); i++, PromiseIteratorNext(iter_ctx)) { if (handle) { // This ordering is necessary to get automated canonification BufferClear(expbuf); ExpandScalar(ctx, NULL, "this", handle, expbuf); CanonifyNameInPlace(BufferGet(expbuf)); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "handle", BufferData(expbuf), CF_DATA_TYPE_STRING, "source=promise"); } else { EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "handle", PromiseID(pp), CF_DATA_TYPE_STRING, "source=promise"); } const Promise *pexp = EvalContextStackPushPromiseIterationFrame(ctx, i, iter_ctx); if (!pexp) { // excluded result = PromiseResultUpdate(result, PROMISE_RESULT_SKIPPED); continue; } PromiseResult iteration_result = ActOnPromise(ctx, pexp, param); NotifyDependantPromises(ctx, pexp, iteration_result); result = PromiseResultUpdate(result, iteration_result); if (strcmp(pp->parent_promise_type->name, "vars") == 0 || strcmp(pp->parent_promise_type->name, "meta") == 0) { VerifyVarPromise(ctx, pexp, true); } EvalContextStackPopFrame(ctx); } BufferDestroy(expbuf); PromiseIteratorDestroy(iter_ctx); EvalContextStackPopFrame(ctx); return result; }
void PromiseBanner(Promise *pp) { char handle[CF_MAXVARSIZE]; const char *sp; if ((sp = PromiseGetHandle(pp)) || (sp = PromiseID(pp))) { strncpy(handle, sp, CF_MAXVARSIZE - 1); } else { strcpy(handle, "(enterprise only)"); } CfOut(OUTPUT_LEVEL_VERBOSE, "", "\n"); CfOut(OUTPUT_LEVEL_VERBOSE, "", " .........................................................\n"); if (VERBOSE || DEBUG) { printf("%s> Promise's handle: %s\n", VPREFIX, handle); printf("%s> Promise made by: \"%s\"", VPREFIX, pp->promiser); } if (pp->promisee.item) { if (VERBOSE) { printf("\n%s> Promise made to (stakeholders): ", VPREFIX); RvalShow(stdout, pp->promisee); } } if (VERBOSE) { printf("\n"); } if (pp->ref) { CfOut(OUTPUT_LEVEL_VERBOSE, "", "\n"); CfOut(OUTPUT_LEVEL_VERBOSE, "", " Comment: %s\n", pp->ref); } CfOut(OUTPUT_LEVEL_VERBOSE, "", " .........................................................\n"); CfOut(OUTPUT_LEVEL_VERBOSE, "", "\n"); }
void PromiseBanner(Promise *pp) { char handle[CF_MAXVARSIZE]; const char *sp; if ((sp = GetConstraintValue("handle", pp, RVAL_TYPE_SCALAR)) || (sp = PromiseID(pp))) { strncpy(handle, sp, CF_MAXVARSIZE - 1); } else { strcpy(handle, "(enterprise only)"); } CfOut(cf_verbose, "", "\n"); CfOut(cf_verbose, "", " .........................................................\n"); if (VERBOSE || DEBUG) { printf("%s> Promise's handle: %s\n", VPREFIX, handle); printf("%s> Promise made by: \"%s\"", VPREFIX, pp->promiser); } if (pp->promisee.item) { if (VERBOSE) { printf("\n%s> Promise made to (stakeholders): ", VPREFIX); ShowRval(stdout, pp->promisee); } } if (VERBOSE) { printf("\n"); } if (pp->ref) { CfOut(cf_verbose, "", "\n"); CfOut(cf_verbose, "", " Comment: %s\n", pp->ref); } CfOut(cf_verbose, "", " .........................................................\n"); CfOut(cf_verbose, "", "\n"); }
void LogHashChange(char *file, FileState status, char *msg, Promise *pp) { FILE *fp; char fname[CF_BUFSIZE]; time_t now = time(NULL); mode_t perm = 0600; static char prevFile[CF_MAXVARSIZE] = { 0 }; // we might get called twice.. if (strcmp(file, prevFile) == 0) { return; } strlcpy(prevFile, file, CF_MAXVARSIZE); /* This is inefficient but we don't want to lose any data */ snprintf(fname, CF_BUFSIZE, "%s/state/%s", CFWORKDIR, CF_FILECHANGE_NEW); MapName(fname); #ifndef __MINGW32__ struct stat sb; if (cfstat(fname, &sb) != -1) { if (sb.st_mode & (S_IWGRP | S_IWOTH)) { CfOut(OUTPUT_LEVEL_ERROR, "", "File %s (owner %ju) is writable by others (security exception)", fname, (uintmax_t)sb.st_uid); } } #endif /* !__MINGW32__ */ if ((fp = fopen(fname, "a")) == NULL) { CfOut(OUTPUT_LEVEL_ERROR, "fopen", "Could not write to the hash change log"); return; } const char *handle = PromiseID(pp); fprintf(fp, "%ld,%s,%s,%c,%s\n", (long) now, handle, file, FileStateToChar(status), msg); fclose(fp); cf_chmod(fname, perm); }
void PromiseBanner(struct Promise *pp) { char *sp,handle[CF_MAXVARSIZE]; if ((sp = GetConstraint("handle",pp,CF_SCALAR)) || (sp = PromiseID(pp))) { strncpy(handle,sp,CF_MAXVARSIZE-1); } else { strcpy(handle,"(enterprise only)"); } CfOut(cf_verbose,"","\n"); CfOut(cf_verbose,""," .........................................................\n"); if (VERBOSE||DEBUG) { printf ("%s> Promise handle: %s\n",VPREFIX,handle); printf ("%s> Promise made by: %s",VPREFIX,pp->promiser); } if (pp->promisee) { if (VERBOSE) { printf(" -> "); ShowRval(stdout,pp->promisee,pp->petype); } } if (VERBOSE) { printf("\n"); } if (pp->ref) { CfOut(cf_verbose,"","\n"); CfOut(cf_verbose,""," Comment: %s\n",pp->ref); } CfOut(cf_verbose,""," .........................................................\n"); CfOut(cf_verbose,"","\n"); }
static void PutHandleVariable(EvalContext *ctx, const Promise *pp) { char *handle_s; const char *existing_handle = PromiseGetHandle(pp); if (existing_handle != NULL) { // This ordering is necessary to get automated canonification handle_s = ExpandScalar(ctx, NULL, "this", existing_handle, NULL); CanonifyNameInPlace(handle_s); } else { handle_s = xstrdup(PromiseID(pp)); /* default handle */ } EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "handle", handle_s, CF_DATA_TYPE_STRING, "source=promise"); free(handle_s); }
void PromiseBanner(const Promise *pp) { if (!LEGACY_OUTPUT) { if (pp->comment) { Log(LOG_LEVEL_VERBOSE, "Comment '%s'", pp->comment); } return; } char handle[CF_MAXVARSIZE]; const char *sp; if ((sp = PromiseGetHandle(pp)) || (sp = PromiseID(pp))) { strncpy(handle, sp, CF_MAXVARSIZE - 1); } else { strcpy(handle, "(enterprise only)"); } Log(LOG_LEVEL_VERBOSE, " ........................................................."); Log(LOG_LEVEL_VERBOSE, " Promise's handle: '%s'", handle); Log(LOG_LEVEL_VERBOSE, " Promise made by: '%s'", pp->promiser); if (pp->comment) { Log(LOG_LEVEL_VERBOSE, "\n"); Log(LOG_LEVEL_VERBOSE, " Comment: %s", pp->comment); } Log(LOG_LEVEL_VERBOSE, " ........................................................."); Log(LOG_LEVEL_VERBOSE, "\n"); }
static void AmendErrorMessageWithPromiseInformation(EvalContext *ctx, Item **error_message, const Promise *pp) { Rval retval; char *v; if (ScopeControlCommonGet(ctx, COMMON_CONTROL_VERSION, &retval) != DATA_TYPE_NONE) { v = (char *) retval.item; } else { v = "not specified"; } const char *sp; char handle[CF_MAXVARSIZE]; if ((sp = PromiseGetHandle(pp)) || (sp = PromiseID(pp))) { strncpy(handle, sp, CF_MAXVARSIZE - 1); } else { strcpy(handle, "(unknown)"); } char output[CF_BUFSIZE]; if (INFORM || VERBOSE || DEBUG) { snprintf(output, CF_BUFSIZE - 1, "I: Report relates to a promise with handle \"%s\"", handle); AppendItem(error_message, output, NULL); } if (pp && PromiseGetBundle(pp)->source_path) { snprintf(output, CF_BUFSIZE - 1, "I: Made in version \'%s\' of \'%s\' near line %zu", v, PromiseGetBundle(pp)->source_path, pp->offset.line); } else { snprintf(output, CF_BUFSIZE - 1, "I: Promise is made internally by cfengine"); } AppendItem(error_message, output, NULL); if (pp != NULL) { switch (pp->promisee.type) { case RVAL_TYPE_SCALAR: snprintf(output, CF_BUFSIZE - 1, "I: The promise was made to: \'%s\'", (char *) pp->promisee.item); AppendItem(error_message, output, NULL); break; case RVAL_TYPE_LIST: { Writer *w = StringWriter(); WriterWriteF(w, "I: The promise was made to (stakeholders): "); RlistWrite(w, pp->promisee.item); AppendItem(error_message, StringWriterClose(w), NULL); break; } default: break; } if (pp->ref) { snprintf(output, CF_BUFSIZE - 1, "I: Comment: %s\n", pp->ref); AppendItem(error_message, output, NULL); } } }
void cfPS(OutputLevel level, char status, char *errstr, const Promise *pp, Attributes attr, char *fmt, ...) { va_list ap; char buffer[CF_BUFSIZE], output[CF_BUFSIZE], *v, handle[CF_MAXVARSIZE]; const char *sp; Item *mess = NULL; int verbose; Rval retval; if ((fmt == NULL) || (strlen(fmt) == 0)) { return; } va_start(ap, fmt); vsnprintf(buffer, CF_BUFSIZE - 1, fmt, ap); va_end(ap); if (Chop(buffer, CF_EXPANDSIZE) == -1) { CfOut(OUTPUT_LEVEL_ERROR, "", "Chop was called on a string that seemed to have no terminator"); } AppendItem(&mess, buffer, NULL); if ((errstr == NULL) || (strlen(errstr) > 0)) { snprintf(output, CF_BUFSIZE - 1, " !!! System reports error for %s: \"%s\"", errstr, GetErrorStr()); AppendItem(&mess, output, NULL); } if (level == OUTPUT_LEVEL_ERROR) { if (GetVariable("control_common", "version", &retval) != DATA_TYPE_NONE) { v = (char *) retval.item; } else { v = "not specified"; } if ((sp = ConstraintGetRvalValue("handle", pp, RVAL_TYPE_SCALAR)) || (sp = PromiseID(pp))) { strncpy(handle, sp, CF_MAXVARSIZE - 1); } else { strcpy(handle, "(unknown)"); } if (INFORM || VERBOSE || DEBUG) { snprintf(output, CF_BUFSIZE - 1, "I: Report relates to a promise with handle \"%s\"", handle); AppendItem(&mess, output, NULL); } if (pp && (pp->audit)) { snprintf(output, CF_BUFSIZE - 1, "I: Made in version \'%s\' of \'%s\' near line %zu", v, pp->audit->filename, pp->offset.line); } else { snprintf(output, CF_BUFSIZE - 1, "I: Promise is made internally by cfengine"); } AppendItem(&mess, output, NULL); if (pp != NULL) { switch (pp->promisee.type) { case RVAL_TYPE_SCALAR: snprintf(output, CF_BUFSIZE - 1, "I: The promise was made to: \'%s\'", (char *) pp->promisee.item); AppendItem(&mess, output, NULL); break; case RVAL_TYPE_LIST: snprintf(output, CF_BUFSIZE - 1, "I: The promise was made to (stakeholders): "); RlistPrint(output+strlen(output), CF_BUFSIZE, (Rlist *)pp->promisee.item); AppendItem(&mess, output, NULL); break; default: break; } if (pp->ref) { snprintf(output, CF_BUFSIZE - 1, "I: Comment: %s\n", pp->ref); AppendItem(&mess, output, NULL); } } } verbose = (attr.transaction.report_level == OUTPUT_LEVEL_VERBOSE) || VERBOSE; switch (level) { case OUTPUT_LEVEL_INFORM: if (INFORM || verbose || DEBUG || (attr.transaction.report_level == OUTPUT_LEVEL_INFORM)) { LogList(stdout, mess, verbose); } if (attr.transaction.log_level == OUTPUT_LEVEL_INFORM) { MakeLog(mess, level); } break; case OUTPUT_LEVEL_REPORTING: case OUTPUT_LEVEL_CMDOUT: if (attr.report.to_file) { FileReport(mess, verbose, attr.report.to_file); } else { LogList(stdout, mess, verbose); } if (attr.transaction.log_level == OUTPUT_LEVEL_INFORM) { MakeLog(mess, level); } break; case OUTPUT_LEVEL_VERBOSE: if (verbose || DEBUG) { LogList(stdout, mess, verbose); } if (attr.transaction.log_level == OUTPUT_LEVEL_VERBOSE) { MakeLog(mess, level); } break; case OUTPUT_LEVEL_ERROR: if (attr.report.to_file) { FileReport(mess, verbose, attr.report.to_file); } else { LogList(stdout, mess, verbose); } if (attr.transaction.log_level == OUTPUT_LEVEL_ERROR) { MakeLog(mess, level); } break; case OUTPUT_LEVEL_LOG: MakeLog(mess, level); break; default: break; } if (pp != NULL) { LogPromiseResult(pp->promiser, pp->promisee.type, pp->promisee.item, status, attr.transaction.log_level, mess); } /* Now complete the exits status classes and auditing */ if (pp != NULL) { ClassAuditLog(pp, attr, status, buffer); } DeleteItemList(mess); }
static void ExpandPromiseAndDo(EvalContext *ctx, const Promise *pp, Rlist *lists, Rlist *containers, PromiseActuator *ActOnPromise, void *param) { const char *handle = PromiseGetHandle(pp); char v[CF_MAXVARSIZE]; EvalContextStackPushPromiseFrame(ctx, pp, true); PromiseIterator *iter_ctx = NULL; for (iter_ctx = PromiseIteratorNew(ctx, pp, lists, containers); PromiseIteratorHasMore(iter_ctx); PromiseIteratorNext(iter_ctx)) { EvalContextStackPushPromiseIterationFrame(ctx, iter_ctx); char number[CF_SMALLBUF]; /* Allow $(this.handle) etc variables */ if (PromiseGetBundle(pp)->source_path) { EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promise_filename",PromiseGetBundle(pp)->source_path, DATA_TYPE_STRING); snprintf(number, CF_SMALLBUF, "%zu", pp->offset.line); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promise_linenumber", number, DATA_TYPE_STRING); } snprintf(v, CF_MAXVARSIZE, "%d", (int) getuid()); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser_uid", v, DATA_TYPE_INT); snprintf(v, CF_MAXVARSIZE, "%d", (int) getgid()); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser_gid", v, DATA_TYPE_INT); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "bundle", PromiseGetBundle(pp)->name, DATA_TYPE_STRING); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "namespace", PromiseGetNamespace(pp), DATA_TYPE_STRING); /* Must expand $(this.promiser) here for arg dereferencing in things like edit_line and methods, but we might have to adjust again later if the value changes -- need to qualify this so we don't expand too early for some other promsies */ if (pp->has_subbundles) { EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser", pp->promiser, DATA_TYPE_STRING); } if (handle) { char tmp[CF_EXPANDSIZE]; // This ordering is necessary to get automated canonification ExpandScalar(ctx, NULL, "this", handle, tmp); CanonifyNameInPlace(tmp); Log(LOG_LEVEL_DEBUG, "Expanded handle to '%s'", tmp); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "handle", tmp, DATA_TYPE_STRING); } else { EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "handle", PromiseID(pp), DATA_TYPE_STRING); } Promise *pexp = ExpandDeRefPromise(ctx, pp); assert(ActOnPromise); ActOnPromise(ctx, pexp, param); if (strcmp(pp->parent_promise_type->name, "vars") == 0 || strcmp(pp->parent_promise_type->name, "meta") == 0) { VerifyVarPromise(ctx, pexp, true); } PromiseDestroy(pexp); EvalContextStackPopFrame(ctx); } PromiseIteratorDestroy(iter_ctx); EvalContextStackPopFrame(ctx); }
void cfPS(enum cfreport level, char status, char *errstr, const Promise *pp, Attributes attr, char *fmt, ...) { va_list ap; char buffer[CF_BUFSIZE], output[CF_BUFSIZE], *v, handle[CF_MAXVARSIZE]; const char *sp; Item *ip, *mess = NULL; int verbose; Rval retval; if ((fmt == NULL) || (strlen(fmt) == 0)) { return; } va_start(ap, fmt); vsnprintf(buffer, CF_BUFSIZE - 1, fmt, ap); va_end(ap); Chop(buffer); AppendItem(&mess, buffer, NULL); if ((errstr == NULL) || (strlen(errstr) > 0)) { snprintf(output, CF_BUFSIZE - 1, " !!! System reports error for %s: \"%s\"", errstr, GetErrorStr()); AppendItem(&mess, output, NULL); } if (level == cf_error) { if (GetVariable("control_common", "version", &retval) != cf_notype) { v = (char *) retval.item; } else { v = "not specified"; } if ((sp = GetConstraintValue("handle", pp, CF_SCALAR)) || (sp = PromiseID(pp))) { strncpy(handle, sp, CF_MAXVARSIZE - 1); } else { strcpy(handle, "(unknown)"); } if (INFORM || VERBOSE || DEBUG) { snprintf(output, CF_BUFSIZE - 1, "I: Report relates to a promise with handle \"%s\"", handle); AppendItem(&mess, output, NULL); } if (pp && pp->audit) { snprintf(output, CF_BUFSIZE - 1, "I: Made in version \'%s\' of \'%s\' near line %zu", v, pp->audit->filename, pp->offset.line); } else { snprintf(output, CF_BUFSIZE - 1, "I: Promise is made internally by cfengine"); } AppendItem(&mess, output, NULL); if (pp != NULL) { switch (pp->promisee.rtype) { case CF_SCALAR: snprintf(output, CF_BUFSIZE - 1, "I: The promise was made to: \'%s\'", (char *) pp->promisee.item); AppendItem(&mess, output, NULL); break; case CF_LIST: snprintf(output, CF_BUFSIZE - 1, "I: The promise was made to (stakeholders): "); PrintRlist(output+strlen(output), CF_BUFSIZE, (Rlist *)pp->promisee.item); AppendItem(&mess, output, NULL); break; } if (pp->ref) { snprintf(output, CF_BUFSIZE - 1, "I: Comment: %s\n", pp->ref); AppendItem(&mess, output, NULL); } } } verbose = (attr.transaction.report_level == cf_verbose) || VERBOSE; switch (level) { case cf_inform: if (INFORM || verbose || DEBUG || attr.transaction.report_level == cf_inform) { LogList(stdout, mess, verbose); } if (attr.transaction.log_level == cf_inform) { MakeLog(mess, level); } break; case cf_reporting: case cf_cmdout: if (attr.report.to_file) { FileReport(mess, verbose, attr.report.to_file); } else { LogList(stdout, mess, verbose); } if (attr.transaction.log_level == cf_inform) { MakeLog(mess, level); } break; case cf_verbose: if (verbose || DEBUG) { LogList(stdout, mess, verbose); } if (attr.transaction.log_level == cf_verbose) { MakeLog(mess, level); } break; case cf_error: if (attr.report.to_file) { FileReport(mess, verbose, attr.report.to_file); } else { LogList(stdout, mess, verbose); } if (attr.transaction.log_level == cf_error) { MakeLog(mess, level); } break; case cf_log: MakeLog(mess, level); break; default: break; } if (pp != NULL) { LogPromiseResult(pp->promiser, pp->promisee.rtype, pp->promisee.item, status, attr.transaction.log_level, mess); } /* Now complete the exits status classes and auditing */ if (pp != NULL) { for (ip = mess; ip != NULL; ip = ip->next) { ClassAuditLog(pp, attr, ip->name, status, buffer); } } DeleteItemList(mess); }