char *StringSubstring(const char *source, size_t source_len, int start, int len) { size_t end = -1; if (len == 0) { return SafeStringDuplicate(""); } else if (len < 0) { end = source_len + len - 1; } else { end = start + len - 1; } end = MIN(end, source_len - 1); if (start < 0) { start = source_len + start; } if (start >= end) { return NULL; } char *result = xcalloc(end - start + 2, sizeof(char)); strncpy(result, source + start, end - start + 1); return result; }
static void ResolvePackageManagerBody(EvalContext *ctx, const Body *pm_body) { PackageModuleBody *new_manager = xcalloc(1, sizeof(PackageModuleBody)); new_manager->name = SafeStringDuplicate(pm_body->name); for (size_t i = 0; i < SeqLength(pm_body->conlist); i++) { Constraint *cp = SeqAt(pm_body->conlist, i); Rval returnval = {0}; if (IsDefinedClass(ctx, cp->classes)) { returnval = ExpandPrivateRval(ctx, NULL, "body", cp->rval.item, cp->rval.type); } if (returnval.item == NULL || returnval.type == RVAL_TYPE_NOPROMISEE) { Log(LOG_LEVEL_VERBOSE, "have invalid constraint while resolving" "package promise body: %s", cp->lval); RvalDestroy(returnval); continue; } if (strcmp(cp->lval, "query_installed_ifelapsed") == 0) { new_manager->installed_ifelapsed = (int)IntFromString(RvalScalarValue(returnval)); } else if (strcmp(cp->lval, "query_updates_ifelapsed") == 0) { new_manager->updates_ifelapsed = (int)IntFromString(RvalScalarValue(returnval)); } else if (strcmp(cp->lval, "default_options") == 0) { new_manager->options = RlistCopy(RvalRlistValue(returnval)); } else { /* This should be handled by the parser. */ assert(0); } RvalDestroy(returnval); } AddPackageModuleToContext(ctx, new_manager); }
int main(int argc, char *argv[]) { signal(SIGINT, HandleSignal); signal(SIGTERM, HandleSignal); Log(LOG_LEVEL_VERBOSE, "Starting cf-testd"); cfnet_init(NULL, NULL); MakeSignalPipe(); long n_threads = 1; CFTestD_Config *config = CFTestD_CheckOpts(argc, argv, &n_threads); if (config->address == NULL) { /* default to localhost */ config->address = xstrdup("127.0.0.1"); } CFTestD_Config **thread_configs = (CFTestD_Config**) xcalloc(n_threads, sizeof(CFTestD_Config*)); for (int i = 0; i < n_threads; i++) { thread_configs[i] = (CFTestD_Config*) xmalloc(sizeof(CFTestD_Config)); if (config->report_file != NULL && strstr(config->report_file, "%d") != NULL) { /* replace the '%d' with the thread number */ asprintf(&(thread_configs[i]->report_file), config->report_file, i); } else { thread_configs[i]->report_file = SafeStringDuplicate(config->report_file); } if (config->key_file != NULL && strstr(config->key_file, "%d") != NULL) { /* replace the '%d' with the thread number */ asprintf(&(thread_configs[i]->key_file), config->key_file, i); } else { thread_configs[i]->key_file = SafeStringDuplicate(config->key_file); } if (i == 0) { thread_configs[i]->address = xstrdup(config->address); } else { thread_configs[i]->address = IncrementIPaddress(thread_configs[i-1]->address); } } CFTestD_ConfigDestroy(config); bool failure = false; for (int i = 0; !failure && (i < n_threads); i++) { int ret = pthread_create(&(thread_configs[i]->t_id), NULL, CFTestD_ServeReport, thread_configs[i]); if (ret != 0) { Log(LOG_LEVEL_ERR, "Failed to create a new thread nr. %d: %s\n", i, strerror(ret)); failure = true; } } if (failure) { return EXIT_FAILURE; } for (int i = 0; i < n_threads; i++) { int ret = pthread_join(thread_configs[i]->t_id, NULL); if (ret != 0) { Log(LOG_LEVEL_ERR, "Failed to join the thread nr. %d: %s\n", i, strerror(ret)); } else { failure = failure && (thread_configs[i]->ret != 0); } CFTestD_ConfigDestroy(thread_configs[i]); } return failure ? EXIT_FAILURE : EXIT_SUCCESS; }
void KeepPromises(Policy *policy, ExecConfig *config) { bool schedule_is_specified = false; Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_EXECUTOR); if (constraints) { for (size_t i = 0; i < SeqLength(constraints); i++) { Constraint *cp = SeqAt(constraints, i); if (IsExcluded(cp->classes, NULL)) { continue; } Rval retval; if (GetVariable("control_executor", cp->lval, &retval) == DATA_TYPE_NONE) { CfOut(OUTPUT_LEVEL_ERROR, "", "Unknown lval %s in exec control body", cp->lval); continue; } if (strcmp(cp->lval, CFEX_CONTROLBODY[cfex_mailfrom].lval) == 0) { free(config->mail_from_address); config->mail_from_address = SafeStringDuplicate(retval.item); CfDebug("mailfrom = %s\n", config->mail_from_address); } if (strcmp(cp->lval, CFEX_CONTROLBODY[cfex_mailto].lval) == 0) { free(config->mail_to_address); config->mail_to_address = SafeStringDuplicate(retval.item); CfDebug("mailto = %s\n", config->mail_to_address); } if (strcmp(cp->lval, CFEX_CONTROLBODY[cfex_smtpserver].lval) == 0) { free(config->mail_server); config->mail_server = SafeStringDuplicate(retval.item); CfDebug("smtpserver = %s\n", config->mail_server); } if (strcmp(cp->lval, CFEX_CONTROLBODY[cfex_execcommand].lval) == 0) { free(config->exec_command); config->exec_command = SafeStringDuplicate(retval.item); CfDebug("exec_command = %s\n", config->exec_command); } if (strcmp(cp->lval, CFEX_CONTROLBODY[cfex_agent_expireafter].lval) == 0) { config->agent_expireafter = IntFromString(retval.item); CfDebug("agent_expireafter = %d\n", config->agent_expireafter); } if (strcmp(cp->lval, CFEX_CONTROLBODY[cfex_executorfacility].lval) == 0) { SetFacility(retval.item); continue; } if (strcmp(cp->lval, CFEX_CONTROLBODY[cfex_mailmaxlines].lval) == 0) { config->mail_max_lines = IntFromString(retval.item); CfDebug("maxlines = %d\n", config->mail_max_lines); } if (strcmp(cp->lval, CFEX_CONTROLBODY[cfex_splaytime].lval) == 0) { int time = IntFromString(RvalScalarValue(retval)); SPLAYTIME = (int) (time * SECONDS_PER_MINUTE * GetSplay()); } if (strcmp(cp->lval, CFEX_CONTROLBODY[cfex_schedule].lval) == 0) { CfDebug("Loading user-defined schedule...\n"); DeleteItemList(SCHEDULE); SCHEDULE = NULL; schedule_is_specified = true; for (const Rlist *rp = retval.item; rp; rp = rp->next) { if (!IsItemIn(SCHEDULE, rp->item)) { AppendItem(&SCHEDULE, rp->item, NULL); } } } } } if (!schedule_is_specified) { LoadDefaultSchedule(); } }
int main(int argc, char *argv[]) { GenericAgentConfig *config = CheckOpts(argc, argv); ReportContext *report_context = OpenReports(config->agent_type); GenericAgentDiscoverContext(config, report_context); Policy *policy = NULL; if (GenericAgentCheckPolicy(config, report_context, false)) { policy = GenericAgentLoadPolicy(config->agent_type, config, report_context); } else if (config->tty_interactive) { FatalError("CFEngine was not able to get confirmation of promises from cf-promises, please verify input file\n"); } else { CfOut(OUTPUT_LEVEL_ERROR, "", "CFEngine was not able to get confirmation of promises from cf-promises, so going to failsafe\n"); HardClass("failsafe_fallback"); GenericAgentConfigSetInputFile(config, "failsafe.cf"); policy = GenericAgentLoadPolicy(config->agent_type, config, report_context); } CheckLicenses(); ThisAgentInit(); ExecConfig exec_config = { .scheduled_run = !ONCE, .exec_command = SafeStringDuplicate(""), .mail_server = SafeStringDuplicate(""), .mail_from_address = SafeStringDuplicate(""), .mail_to_address = SafeStringDuplicate(""), .mail_max_lines = 30, .fq_name = VFQNAME, .ip_address = VIPADDRESS, .agent_expireafter = 10080, }; KeepPromises(policy, &exec_config); #ifdef __MINGW32__ if (WINSERVICE) { NovaWin_StartExecService(); } else #endif /* __MINGW32__ */ { StartServer(policy, config, &exec_config, report_context); } ReportContextDestroy(report_context); GenericAgentConfigDestroy(config); return 0; } /*****************************************************************************/ /* Level 1 */ /*****************************************************************************/ static GenericAgentConfig *CheckOpts(int argc, char **argv) { extern char *optarg; int optindex = 0; int c; char ld_library_path[CF_BUFSIZE]; GenericAgentConfig *config = GenericAgentConfigNewDefault(AGENT_TYPE_EXECUTOR); while ((c = getopt_long(argc, argv, "dvnKIf:D:N:VxL:hFOV1gMW", OPTIONS, &optindex)) != EOF) { switch ((char) c) { case 'f': if (optarg && strlen(optarg) < 5) { FatalError(" -f used but argument \"%s\" incorrect", optarg); } GenericAgentConfigSetInputFile(config, optarg); MINUSF = true; break; case 'd': HardClass("opt_debug"); DEBUG = true; break; case 'K': IGNORELOCK = true; break; case 'D': NewClassesFromString(optarg); break; case 'N': NegateClassesFromString(optarg); break; case 'I': INFORM = true; break; case 'v': VERBOSE = true; NO_FORK = true; break; case 'n': DONTDO = true; IGNORELOCK = true; HardClass("opt_dry_run"); break; case 'L': snprintf(ld_library_path, CF_BUFSIZE - 1, "LD_LIBRARY_PATH=%s", optarg); if (putenv(xstrdup(ld_library_path)) != 0) { } break; case 'W': WINSERVICE = false; break; case 'F': NO_FORK = true; break; case 'O': ONCE = true; break; case 'V': PrintVersionBanner("cf-execd"); exit(0); case 'h': Syntax("cf-execd - cfengine's execution agent", OPTIONS, HINTS, ID); exit(0); case 'M': ManPage("cf-execd - cfengine's execution agent", OPTIONS, HINTS, ID); exit(0); case 'x': CfOut(OUTPUT_LEVEL_ERROR, "", "Self-diagnostic functionality is retired."); exit(0); default: Syntax("cf-execd - cfengine's execution agent", OPTIONS, HINTS, ID); exit(1); } } if (argv[optind] != NULL) { CfOut(OUTPUT_LEVEL_ERROR, "", "Unexpected argument with no preceding option: %s\n", argv[optind]); } return config; } /*****************************************************************************/ static void LoadDefaultSchedule(void) { CfDebug("Loading default schedule...\n"); DeleteItemList(SCHEDULE); SCHEDULE = NULL; AppendItem(&SCHEDULE, "Min00", NULL); AppendItem(&SCHEDULE, "Min05", NULL); AppendItem(&SCHEDULE, "Min10", NULL); AppendItem(&SCHEDULE, "Min15", NULL); AppendItem(&SCHEDULE, "Min20", NULL); AppendItem(&SCHEDULE, "Min25", NULL); AppendItem(&SCHEDULE, "Min30", NULL); AppendItem(&SCHEDULE, "Min35", NULL); AppendItem(&SCHEDULE, "Min40", NULL); AppendItem(&SCHEDULE, "Min45", NULL); AppendItem(&SCHEDULE, "Min50", NULL); AppendItem(&SCHEDULE, "Min55", NULL); }
PromiseResult HandleNewPackagePromiseType(EvalContext *ctx, const Promise *pp, Attributes a, char **promise_log_msg, LogLevel *log_lvl) { Log(LOG_LEVEL_DEBUG, "New package promise handler"); if (!NewPackagePromiseSanityCheck(a)) { *promise_log_msg = SafeStringDuplicate("New package promise failed sanity check."); *log_lvl = LOG_LEVEL_ERR; return PROMISE_RESULT_FAIL; } PromiseBanner(ctx, pp); PackagePromiseGlobalLock global_lock = AcquireGlobalPackagePromiseLock(ctx); CfLock package_promise_lock; char promise_lock[CF_BUFSIZE]; snprintf(promise_lock, sizeof(promise_lock), "new-package-%s-%s", pp->promiser, a.new_packages.module_body->name); if (global_lock.g_lock.lock == NULL) { *promise_log_msg = SafeStringDuplicate("Can not acquire global lock for package " "promise. Skipping promise evaluation"); *log_lvl = LOG_LEVEL_INFO; return PROMISE_RESULT_SKIPPED; } package_promise_lock = AcquireLock(ctx, promise_lock, VUQNAME, CFSTARTTIME, a.transaction, pp, false); if (package_promise_lock.lock == NULL) { Log(LOG_LEVEL_DEBUG, "Skipping promise execution due to locking."); YieldGlobalPackagePromiseLock(global_lock); *promise_log_msg = StringFormat("Can not acquire lock for '%s' package promise. " "Skipping promise evaluation", pp->promiser); *log_lvl = LOG_LEVEL_VERBOSE; return PROMISE_RESULT_SKIPPED; } PackageModuleWrapper *package_module = NewPackageModuleWrapper(a.new_packages.module_body); if (!package_module) { *promise_log_msg = StringFormat("Some error occurred while contacting package " "module - promise: %s", pp->promiser); *log_lvl = LOG_LEVEL_ERR; YieldCurrentLock(package_promise_lock); YieldGlobalPackagePromiseLock(global_lock); return PROMISE_RESULT_FAIL; } PromiseResult result = PROMISE_RESULT_FAIL; switch (a.new_packages.package_policy) { case NEW_PACKAGE_ACTION_ABSENT: result = HandleAbsentPromiseAction(ctx, pp->promiser, &a.new_packages, package_module, a.transaction.action); switch (result) { case PROMISE_RESULT_FAIL: *log_lvl = LOG_LEVEL_ERR; *promise_log_msg = StringFormat("Error removing package '%s'", pp->promiser); break; case PROMISE_RESULT_CHANGE: *log_lvl = LOG_LEVEL_INFO; *promise_log_msg = StringFormat("Successfully removed package '%s'", pp->promiser); break; case PROMISE_RESULT_NOOP: *log_lvl = LOG_LEVEL_VERBOSE; *promise_log_msg = StringFormat("Package '%s' was not installed", pp->promiser); break; default: ProgrammingError( "Absent promise action evaluation returned " "unsupported result: %d", result); break; } break; case NEW_PACKAGE_ACTION_PRESENT: result = HandlePresentPromiseAction(ctx, pp->promiser, &a.new_packages, package_module, a.transaction.action); switch (result) { case PROMISE_RESULT_FAIL: *log_lvl = LOG_LEVEL_ERR; *promise_log_msg = StringFormat("Error installing package '%s'", pp->promiser); break; case PROMISE_RESULT_CHANGE: *log_lvl = LOG_LEVEL_INFO; *promise_log_msg = StringFormat("Successfully installed package '%s'", pp->promiser); break; case PROMISE_RESULT_NOOP: *log_lvl = LOG_LEVEL_VERBOSE; *promise_log_msg = StringFormat("Package '%s' already installed", pp->promiser); break; default: ProgrammingError( "Present promise action evaluation returned " "unsupported result: %d", result); break; } break; case NEW_PACKAGE_ACTION_NONE: default: ProgrammingError("Unsupported package action: %d", a.new_packages.package_policy); break; } DeletePackageModuleWrapper(package_module); YieldCurrentLock(package_promise_lock); YieldGlobalPackagePromiseLock(global_lock); return result; }
int main(int argc, char *argv[]) { GenericAgentConfig config = CheckOpts(argc, argv); ReportContext *report_context = OpenReports("executor"); Policy *policy = GenericInitialize("executor", config, report_context); ThisAgentInit(); ExecConfig exec_config = { .scheduled_run = !ONCE, .exec_command = SafeStringDuplicate(""), .mail_server = SafeStringDuplicate(""), .mail_from_address = SafeStringDuplicate(""), .mail_to_address = SafeStringDuplicate(""), .mail_max_lines = 30, .fq_name = VFQNAME, .ip_address = VIPADDRESS, .agent_expireafter = 10080, }; KeepPromises(policy, &exec_config); #ifdef MINGW if (WINSERVICE) { NovaWin_StartExecService(); } else #endif /* MINGW */ { StartServer(policy, &exec_config, report_context); } ReportContextDestroy(report_context); return 0; } /*****************************************************************************/ /* Level 1 */ /*****************************************************************************/ static GenericAgentConfig CheckOpts(int argc, char **argv) { extern char *optarg; int optindex = 0; int c; char ld_library_path[CF_BUFSIZE]; GenericAgentConfig config = GenericAgentDefaultConfig(AGENT_TYPE_EXECUTOR); while ((c = getopt_long(argc, argv, "dvnKIf:D:N:VxL:hFOV1gMW", OPTIONS, &optindex)) != EOF) { switch ((char) c) { case 'f': if (optarg && strlen(optarg) < 5) { FatalError(" -f used but argument \"%s\" incorrect", optarg); } SetInputFile(optarg); MINUSF = true; break; case 'd': HardClass("opt_debug"); DEBUG = true; break; case 'K': IGNORELOCK = true; break; case 'D': NewClassesFromString(optarg); break; case 'N': NegateClassesFromString(optarg); break; case 'I': INFORM = true; break; case 'v': VERBOSE = true; NO_FORK = true; break; case 'n': DONTDO = true; IGNORELOCK = true; HardClass("opt_dry_run"); break; case 'L': snprintf(ld_library_path, CF_BUFSIZE - 1, "LD_LIBRARY_PATH=%s", optarg); if (putenv(xstrdup(ld_library_path)) != 0) { } break; case 'W': WINSERVICE = false; break; case 'F': NO_FORK = true; break; case 'O': ONCE = true; break; case 'V': PrintVersionBanner("cf-execd"); exit(0); case 'h': Syntax("cf-execd - cfengine's execution agent", OPTIONS, HINTS, ID); exit(0); case 'M': ManPage("cf-execd - cfengine's execution agent", OPTIONS, HINTS, ID); exit(0); case 'x': SelfDiagnostic(); exit(0); default: Syntax("cf-execd - cfengine's execution agent", OPTIONS, HINTS, ID); exit(1); } } if (argv[optind] != NULL) { CfOut(cf_error, "", "Unexpected argument with no preceding option: %s\n", argv[optind]); } return config; } /*****************************************************************************/ static void LoadDefaultSchedule(void) { CfDebug("Loading default schedule...\n"); DeleteItemList(SCHEDULE); SCHEDULE = NULL; AppendItem(&SCHEDULE, "Min00", NULL); AppendItem(&SCHEDULE, "Min05", NULL); AppendItem(&SCHEDULE, "Min10", NULL); AppendItem(&SCHEDULE, "Min15", NULL); AppendItem(&SCHEDULE, "Min20", NULL); AppendItem(&SCHEDULE, "Min25", NULL); AppendItem(&SCHEDULE, "Min30", NULL); AppendItem(&SCHEDULE, "Min35", NULL); AppendItem(&SCHEDULE, "Min40", NULL); AppendItem(&SCHEDULE, "Min45", NULL); AppendItem(&SCHEDULE, "Min50", NULL); AppendItem(&SCHEDULE, "Min55", NULL); }
void KeepPromises(Policy *policy, ExecConfig *config) { for (Constraint *cp = ControlBodyConstraints(policy, cf_executor); cp != NULL; cp = cp->next) { if (IsExcluded(cp->classes, NULL)) { continue; } Rval retval; if (GetVariable("control_executor", cp->lval, &retval) == cf_notype) { CfOut(cf_error, "", "Unknown lval %s in exec control body", cp->lval); continue; } if (strcmp(cp->lval, CFEX_CONTROLBODY[cfex_mailfrom].lval) == 0) { free(config->mail_from_address); config->mail_from_address = SafeStringDuplicate(retval.item); CfDebug("mailfrom = %s\n", config->mail_from_address); } if (strcmp(cp->lval, CFEX_CONTROLBODY[cfex_mailto].lval) == 0) { free(config->mail_to_address); config->mail_to_address = SafeStringDuplicate(retval.item); CfDebug("mailto = %s\n", config->mail_to_address); } if (strcmp(cp->lval, CFEX_CONTROLBODY[cfex_smtpserver].lval) == 0) { free(config->mail_server); config->mail_server = SafeStringDuplicate(retval.item); CfDebug("smtpserver = %s\n", config->mail_server); } if (strcmp(cp->lval, CFEX_CONTROLBODY[cfex_execcommand].lval) == 0) { free(config->exec_command); config->exec_command = SafeStringDuplicate(retval.item); CfDebug("exec_command = %s\n", config->exec_command); } if (strcmp(cp->lval, CFEX_CONTROLBODY[cfex_agent_expireafter].lval) == 0) { config->agent_expireafter = Str2Int(retval.item); CfDebug("agent_expireafter = %d\n", config->agent_expireafter); } if (strcmp(cp->lval, CFEX_CONTROLBODY[cfex_executorfacility].lval) == 0) { SetFacility(retval.item); continue; } if (strcmp(cp->lval, CFEX_CONTROLBODY[cfex_mailmaxlines].lval) == 0) { config->mail_max_lines = Str2Int(retval.item); CfDebug("maxlines = %d\n", config->mail_max_lines); } if (strcmp(cp->lval, CFEX_CONTROLBODY[cfex_splaytime].lval) == 0) { int time = Str2Int(ScalarRvalValue(retval)); SPLAYTIME = (int) (time * SECONDS_PER_MINUTE * GetSplay()); } if (strcmp(cp->lval, CFEX_CONTROLBODY[cfex_schedule].lval) == 0) { Rlist *rp; CfDebug("schedule ...\n"); DeleteItemList(SCHEDULE); SCHEDULE = NULL; for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next) { if (!IsItemIn(SCHEDULE, rp->item)) { AppendItem(&SCHEDULE, rp->item, NULL); } } } } }