void VerifyEnvironmentsPromise(Promise *pp) { Attributes a = { {0} }; CfLock thislock; Promise *pexp; a = GetEnvironmentsAttributes(pp); if (EnvironmentsSanityChecks(a, pp)) { thislock = AcquireLock("virtual", VUQNAME, CFSTARTTIME, a, pp, false); if (thislock.lock == NULL) { return; } CF_OCCUR++; PromiseBanner(pp); NewScalar("this", "promiser", pp->promiser, cf_str); pexp = ExpandDeRefPromise("this", pp); VerifyEnvironments(a, pp); DeletePromise(pexp); } YieldCurrentLock(thislock); }
void TestExpandPromise(const ReportContext *report_context) { Promise pp = { 0 }, *pcopy; printf("%d. Testing promise duplication and expansion\n", ++NR); pp.promiser = "the originator"; pp.promisee = (Rval) { "the recipient", CF_SCALAR }; pp.classes = "upper classes"; pp.offset.line = 12; pp.audit = NULL; pp.conlist = NULL; pp.bundletype = "bundle_type"; pp.bundle = "test_bundle"; pp.ref = "commentary"; pp.agentsubtype = NULL; pp.done = false; pp.next = NULL; pp.cache = NULL; pp.inode_cache = NULL; pp.this_server = NULL; pp.donep = &(pp.done); pp.conn = NULL; ConstraintAppendToPromise(&pp, "lval1", (Rval) { xstrdup("rval1"), CF_SCALAR }, "lower classes1", false); ConstraintAppendToPromise(&pp, "lval2", (Rval) { xstrdup("rval2"), CF_SCALAR }, "lower classes2", false); //getuid ConstraintAppendToPromise(&pp,"lval2",,CF_SCALAR,"lower classes2"); /* Now copy promise and delete */ pcopy = DeRefCopyPromise("diagnostic-scope", &pp); if (VERBOSE || DEBUG) { printf("-----------------------------------------------------------\n"); printf("Raw test promises\n\n"); ShowPromise(report_context, REPORT_OUTPUT_TYPE_TEXT, &pp, 4); ShowPromise(report_context, REPORT_OUTPUT_TYPE_HTML, &pp, 4); ShowPromise(report_context, REPORT_OUTPUT_TYPE_TEXT, pcopy, 6); ShowPromise(report_context, REPORT_OUTPUT_TYPE_HTML, pcopy, 6); } DeletePromise(pcopy); }
int main(int argc, char *argv[]) { Rlist *rp; Promise *pp; #if !defined(__MINGW32__) int count = 0; int status; int pid; #endif GenericAgentConfig *config = CheckOpts(argc, argv); ReportContext *report_context = OpenReports("runagent"); Policy *policy = GenericInitialize("runagent", config, report_context); ThisAgentInit(); KeepControlPromises(policy); // Set RUNATTR using copy if (BACKGROUND && INTERACTIVE) { CfOut(cf_error, "", " !! You cannot specify background mode and interactive mode together"); exit(1); } pp = MakeDefaultRunAgentPromise(); /* HvB */ if (HOSTLIST) { rp = HOSTLIST; while (rp != NULL) { #ifdef __MINGW32__ if (BACKGROUND) { CfOut(cf_verbose, "", "Windows does not support starting processes in the background - starting in foreground"); BACKGROUND = false; } #else if (BACKGROUND) /* parallel */ { if (count <= MAXCHILD) { if (fork() == 0) /* child process */ { HailServer(rp->item, RUNATTR, pp); exit(0); } else /* parent process */ { rp = rp->next; count++; } } else { pid = wait(&status); CfDebug("child = %d, child number = %d\n", pid, count); count--; } } else /* serial */ #endif /* __MINGW32__ */ { HailServer(rp->item, RUNATTR, pp); rp = rp->next; } } /* end while */ } /* end if HOSTLIST */ #ifndef __MINGW32__ if (BACKGROUND) { printf("Waiting for child processes to finish\n"); while (count > 1) { pid = wait(&status); CfOut(cf_verbose, "", "Child = %d ended, number = %d\n", pid, count); count--; } } #endif DeletePromise(pp); GenericAgentConfigDestroy(config); ReportContextDestroy(report_context); return 0; }
/* Might be called back from NovaWin_StartExecService */ void StartServer(Policy *policy, ExecConfig *config, const ReportContext *report_context) { #if !defined(__MINGW32__) time_t now = time(NULL); #endif Promise *pp = NewPromise("exec_cfengine", "the executor agent"); Attributes dummyattr; CfLock thislock; #if defined(HAVE_PTHREAD) pthread_attr_init(&threads_attrs); pthread_attr_setdetachstate(&threads_attrs, PTHREAD_CREATE_DETACHED); pthread_attr_setstacksize(&threads_attrs, (size_t)2048*1024); #endif Banner("Starting executor"); memset(&dummyattr, 0, sizeof(dummyattr)); dummyattr.restart_class = "nonce"; dummyattr.transaction.ifelapsed = CF_EXEC_IFELAPSED; dummyattr.transaction.expireafter = CF_EXEC_EXPIREAFTER; if (!ONCE) { thislock = AcquireLock(pp->promiser, VUQNAME, CFSTARTTIME, dummyattr, pp, false); if (thislock.lock == NULL) { DeletePromise(pp); return; } /* Kill previous instances of cf-execd if those are still running */ Apoptosis(); /* FIXME: kludge. This code re-sets "last" lock to the one we have acquired a few lines before. If the cf-execd is terminated, this lock will be removed, and subsequent restart of cf-execd won't fail. The culprit is Apoptosis(), which creates a promise and executes it, taking locks during it, so CFLOCK/CFLAST/CFLOG get reset. Proper fix is to keep all the taken locks in the memory, and release all of them during process termination. */ strcpy(CFLOCK, thislock.lock); strcpy(CFLAST, thislock.last ? thislock.last : ""); strcpy(CFLOG, thislock.log ? thislock.log : ""); } #ifdef MINGW if (!NO_FORK) { CfOut(cf_verbose, "", "Windows does not support starting processes in the background - starting in foreground"); } #else /* NOT MINGW */ if ((!NO_FORK) && (fork() != 0)) { CfOut(cf_inform, "", "cf-execd starting %.24s\n", cf_ctime(&now)); _exit(0); } if (!NO_FORK) { ActAsDaemon(0); } #endif /* NOT MINGW */ WritePID("cf-execd.pid"); signal(SIGINT, HandleSignals); signal(SIGTERM, HandleSignals); signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGUSR1, HandleSignals); signal(SIGUSR2, HandleSignals); umask(077); if (ONCE) { CfOut(cf_verbose, "", "Sleeping for splaytime %d seconds\n\n", SPLAYTIME); sleep(SPLAYTIME); LocalExec(config); CloseLog(); } else { while (true) { if (ScheduleRun(&policy, config, report_context)) { CfOut(cf_verbose, "", "Sleeping for splaytime %d seconds\n\n", SPLAYTIME); sleep(SPLAYTIME); #if defined(HAVE_PTHREAD) if (!LocalExecInThread(config)) { CfOut(cf_inform, "", "Unable to run agent in thread, falling back to blocking execution"); #endif LocalExec(config); #if defined(HAVE_PTHREAD) } #endif } } } if (!ONCE) { YieldCurrentLock(thislock); } }