void MonitorStartServer(const Policy *policy, const ReportContext *report_context) { char timekey[CF_SMALLBUF]; Averages averages; Promise *pp = NewPromise("monitor_cfengine", "the monitor daemon"); Attributes dummyattr; CfLock thislock; #ifdef __MINGW32__ if (!NO_FORK) { CfOut(cf_verbose, "", "Windows does not support starting processes in the background - starting in foreground"); } #else /* !__MINGW32__ */ if ((!NO_FORK) && (fork() != 0)) { CfOut(cf_inform, "", "cf-monitord: starting\n"); _exit(0); } if (!NO_FORK) { ActAsDaemon(0); } #endif /* !__MINGW32__ */ memset(&dummyattr, 0, sizeof(dummyattr)); dummyattr.transaction.ifelapsed = 0; dummyattr.transaction.expireafter = 0; thislock = AcquireLock(pp->promiser, VUQNAME, CFSTARTTIME, dummyattr, pp, false); if (thislock.lock == NULL) { return; } WritePID("cf-monitord.pid"); MonNetworkSnifferOpen(); while (!IsPendingTermination()) { GetQ(policy, report_context); snprintf(timekey, sizeof(timekey), "%s", GenTimeKey(time(NULL))); averages = EvalAvQ(timekey); LeapDetection(); ArmClasses(averages, timekey); ZeroArrivals(); MonNetworkSnifferSniff(ITER, CF_THIS); ITER++; } }
/* Might be called back from NovaWin_StartExecService */ void StartServer(EvalContext *ctx, Policy *policy, GenericAgentConfig *config, ExecConfig *exec_config) { #if !defined(__MINGW32__) time_t now = time(NULL); #endif pthread_attr_init(&threads_attrs); pthread_attr_setdetachstate(&threads_attrs, PTHREAD_CREATE_DETACHED); pthread_attr_setstacksize(&threads_attrs, (size_t)2048*1024); Banner("Starting executor"); #ifndef __MINGW32__ if (!ONCE) { /* Kill previous instances of cf-execd if those are still running */ Apoptosis(); } #endif #ifdef __MINGW32__ if (!NO_FORK) { CfOut(OUTPUT_LEVEL_VERBOSE, "", "Windows does not support starting processes in the background - starting in foreground"); } #else /* !__MINGW32__ */ if ((!NO_FORK) && (fork() != 0)) { CfOut(OUTPUT_LEVEL_INFORM, "", "cf-execd starting %.24s\n", cf_ctime(&now)); _exit(0); } if (!NO_FORK) { ActAsDaemon(0); } #endif /* !__MINGW32__ */ WritePID("cf-execd.pid"); signal(SIGINT, HandleSignalsForDaemon); signal(SIGTERM, HandleSignalsForDaemon); signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGUSR1, HandleSignalsForDaemon); signal(SIGUSR2, HandleSignalsForDaemon); umask(077); if (ONCE) { LocalExec(exec_config); CloseLog(); } else { while (!IsPendingTermination()) { if (ScheduleRun(ctx, &policy, config, exec_config)) { CfOut(OUTPUT_LEVEL_VERBOSE, "", "Sleeping for splaytime %d seconds\n\n", exec_config->splay_time); sleep(exec_config->splay_time); if (!LocalExecInThread(exec_config)) { CfOut(OUTPUT_LEVEL_INFORM, "", "Unable to run agent in thread, falling back to blocking execution"); LocalExec(exec_config); } } } } }
/* Might be called back from NovaWin_StartExecService */ void StartServer(Policy *policy, GenericAgentConfig *config, ExecConfig *exec_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; pthread_attr_init(&threads_attrs); pthread_attr_setdetachstate(&threads_attrs, PTHREAD_CREATE_DETACHED); pthread_attr_setstacksize(&threads_attrs, (size_t)2048*1024); 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) { PromiseDestroy(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 __MINGW32__ if (!NO_FORK) { CfOut(OUTPUT_LEVEL_VERBOSE, "", "Windows does not support starting processes in the background - starting in foreground"); } #else /* !__MINGW32__ */ if ((!NO_FORK) && (fork() != 0)) { CfOut(OUTPUT_LEVEL_INFORM, "", "cf-execd starting %.24s\n", cf_ctime(&now)); _exit(0); } if (!NO_FORK) { ActAsDaemon(0); } #endif /* !__MINGW32__ */ WritePID("cf-execd.pid"); signal(SIGINT, HandleSignalsForDaemon); signal(SIGTERM, HandleSignalsForDaemon); signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGUSR1, HandleSignalsForDaemon); signal(SIGUSR2, HandleSignalsForDaemon); umask(077); if (ONCE) { CfOut(OUTPUT_LEVEL_VERBOSE, "", "Sleeping for splaytime %d seconds\n\n", SPLAYTIME); sleep(SPLAYTIME); LocalExec(exec_config); CloseLog(); } else { while (!IsPendingTermination()) { if (ScheduleRun(&policy, config, exec_config, report_context)) { CfOut(OUTPUT_LEVEL_VERBOSE, "", "Sleeping for splaytime %d seconds\n\n", SPLAYTIME); sleep(SPLAYTIME); if (!LocalExecInThread(exec_config)) { CfOut(OUTPUT_LEVEL_INFORM, "", "Unable to run agent in thread, falling back to blocking execution"); LocalExec(exec_config); } } } YieldCurrentLock(thislock); } }
void MonitorStartServer(EvalContext *ctx, const Policy *policy) { char timekey[CF_SMALLBUF]; Averages averages; Policy *monitor_cfengine_policy = PolicyNew(); Promise *pp = NULL; { Bundle *bp = PolicyAppendBundle(monitor_cfengine_policy, NamespaceDefault(), "monitor_cfengine_bundle", "agent", NULL, NULL); PromiseType *tp = BundleAppendPromiseType(bp, "monitor_cfengine"); pp = PromiseTypeAppendPromise(tp, "the monitor daemon", (Rval) { NULL, RVAL_TYPE_NOPROMISEE }, NULL); } assert(pp); CfLock thislock; #ifdef __MINGW32__ if (!NO_FORK) { Log(LOG_LEVEL_VERBOSE, "Windows does not support starting processes in the background - starting in foreground"); } #else /* !__MINGW32__ */ if ((!NO_FORK) && (fork() != 0)) { Log(LOG_LEVEL_INFO, "cf-monitord: starting"); _exit(0); } if (!NO_FORK) { ActAsDaemon(0); } #endif /* !__MINGW32__ */ TransactionContext tc = { .ifelapsed = 0, .expireafter = 0, }; thislock = AcquireLock(ctx, pp->promiser, VUQNAME, CFSTARTTIME, tc, pp, false); if (thislock.lock == NULL) { PolicyDestroy(monitor_cfengine_policy); return; } WritePID("cf-monitord.pid"); MonNetworkSnifferOpen(); while (!IsPendingTermination()) { GetQ(ctx, policy); snprintf(timekey, sizeof(timekey), "%s", GenTimeKey(time(NULL))); averages = EvalAvQ(ctx, timekey); LeapDetection(); ArmClasses(averages, timekey); ZeroArrivals(); MonNetworkSnifferSniff(ITER, CF_THIS); ITER++; } PolicyDestroy(monitor_cfengine_policy); } /*********************************************************************/ static void GetQ(EvalContext *ctx, const Policy *policy) { MonEntropyClassesReset(); ZeroArrivals(); MonProcessesGatherData(CF_THIS); #ifndef __MINGW32__ MonCPUGatherData(CF_THIS); MonLoadGatherData(CF_THIS); MonDiskGatherData(CF_THIS); MonNetworkGatherData(CF_THIS); MonNetworkSnifferGatherData(); MonTempGatherData(CF_THIS); #endif /* !__MINGW32__ */ MonOtherGatherData(CF_THIS); GatherPromisedMeasures(ctx, policy); }
/* Prepare synthetic agent promise and lock it. */ static CfLock AcquireServerLock(EvalContext *ctx, GenericAgentConfig *config, Policy *server_policy) { Promise *pp = NULL; { Bundle *bp = PolicyAppendBundle(server_policy, NamespaceDefault(), "server_cfengine_bundle", "agent", NULL, NULL); PromiseType *tp = BundleAppendPromiseType(bp, "server_cfengine"); pp = PromiseTypeAppendPromise(tp, config->input_file, (Rval) { NULL, RVAL_TYPE_NOPROMISEE }, NULL, NULL); } assert(pp); TransactionContext tc = { .ifelapsed = 0, .expireafter = 1, }; return AcquireLock(ctx, pp->promiser, VUQNAME, CFSTARTTIME, tc, pp, false); } /* Final preparations for running as server */ static void PrepareServer(int sd) { if (sd != -1) { Log(LOG_LEVEL_VERBOSE, "Listening for connections on socket descriptor %d ...", sd); } if (!NO_FORK) #ifdef __MINGW32__ { Log(LOG_LEVEL_VERBOSE, "Windows does not support starting processes in the background - running in foreground"); } #else { if (fork() != 0) /* parent */ { _exit(EXIT_SUCCESS); } ActAsDaemon(); } #endif /* Close sd on exec, needed for not passing the socket to cf-runagent * spawned commands. */ SetCloseOnExec(sd, true); Log(LOG_LEVEL_NOTICE, "Server is starting..."); WritePID("cf-serverd.pid"); /* Arranges for atexit() to tidy it away */ } /* Wait for connection-handler threads to finish their work. * * @return Number of live threads remaining after waiting. */ static int WaitOnThreads() { int result = 1; for (int i = 2; i > 0; i--) { if (ThreadLock(cft_server_children)) { result = ACTIVE_THREADS; ThreadUnlock(cft_server_children); } if (result == 0) { break; } Log(LOG_LEVEL_VERBOSE, "Waiting %ds for %d connection threads to finish", i, result); sleep(1); } if (result > 0) { Log(LOG_LEVEL_VERBOSE, "There are %d connection threads left, exiting anyway", result); } else { assert(result == 0); Log(LOG_LEVEL_VERBOSE, "All threads are done, cleaning up allocations"); ClearAuthAndACLs(); ServerTLSDeInitialize(); } return result; }
/* Might be called back from NovaWin_StartExecService */ void StartServer(EvalContext *ctx, Policy *policy, GenericAgentConfig *config, ExecdConfig **execd_config, ExecConfig **exec_config) { pthread_attr_init(&threads_attrs); pthread_attr_setdetachstate(&threads_attrs, PTHREAD_CREATE_DETACHED); pthread_attr_setstacksize(&threads_attrs, (size_t)2048*1024); Banner("Starting executor"); #ifndef __MINGW32__ if (!ONCE) { /* Kill previous instances of cf-execd if those are still running */ Apoptosis(); } time_t now = time(NULL); if ((!NO_FORK) && (fork() != 0)) { Log(LOG_LEVEL_INFO, "cf-execd starting %.24s", ctime(&now)); _exit(EXIT_SUCCESS); } if (!NO_FORK) { ActAsDaemon(); } #else /* __MINGW32__ */ if (!NO_FORK) { Log(LOG_LEVEL_VERBOSE, "Windows does not support starting processes in the background - starting in foreground"); } #endif WritePID("cf-execd.pid"); signal(SIGINT, HandleSignalsForDaemon); signal(SIGTERM, HandleSignalsForDaemon); signal(SIGHUP, HandleSignalsForDaemon); signal(SIGPIPE, SIG_IGN); signal(SIGUSR1, HandleSignalsForDaemon); signal(SIGUSR2, HandleSignalsForDaemon); umask(077); if (ONCE) { LocalExec(*exec_config); CloseLog(); } else { while (!IsPendingTermination()) { if (ScheduleRun(ctx, &policy, config, execd_config, exec_config)) { MaybeSleepLog(LOG_LEVEL_VERBOSE, "Sleeping for splaytime %u seconds", (*execd_config)->splay_time); // We are sleeping both above and inside ScheduleRun(), so make // sure a terminating signal did not arrive during that time. if (IsPendingTermination()) { break; } if (!LocalExecInThread(*exec_config)) { Log(LOG_LEVEL_INFO, "Unable to run agent in thread, falling back to blocking execution"); LocalExec(*exec_config); } } } } PolicyDestroy(policy); }
void StartServer(Policy *policy, GenericAgentConfig *config, const ReportContext *report_context) { int sd = -1, sd_reply; fd_set rset; struct timeval timeout; int ret_val; Promise *pp = NewPromise("server_cfengine", config->input_file); Attributes dummyattr = { {0} }; CfLock thislock; time_t starttime = time(NULL), last_collect = 0; #if defined(HAVE_GETADDRINFO) socklen_t addrlen = sizeof(struct sockaddr_in6); struct sockaddr_in6 cin; #else socklen_t addrlen = sizeof(struct sockaddr_in); struct sockaddr_in cin; #endif memset(&dummyattr, 0, sizeof(dummyattr)); signal(SIGINT, HandleSignalsForDaemon); signal(SIGTERM, HandleSignalsForDaemon); signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGUSR1, HandleSignalsForDaemon); signal(SIGUSR2, HandleSignalsForDaemon); sd = SetServerListenState(QUEUESIZE); dummyattr.transaction.ifelapsed = 0; dummyattr.transaction.expireafter = 1; thislock = AcquireLock(pp->promiser, VUQNAME, CFSTARTTIME, dummyattr, pp, false); if (thislock.lock == NULL) { return; } CfOut(cf_inform, "", "cf-serverd starting %.24s\n", cf_ctime(&starttime)); if (sd != -1) { CfOut(cf_verbose, "", "Listening for connections ...\n"); } #ifdef __MINGW32__ if (!NO_FORK) { CfOut(cf_verbose, "", "Windows does not support starting processes in the background - starting in foreground"); } #else /* !__MINGW32__ */ if ((!NO_FORK) && (fork() != 0)) { _exit(0); } if (!NO_FORK) { ActAsDaemon(sd); } #endif /* !__MINGW32__ */ WritePID("cf-serverd.pid"); /* Andrew Stribblehill <*****@*****.**> -- close sd on exec */ #ifndef __MINGW32__ fcntl(sd, F_SETFD, FD_CLOEXEC); #endif while (!IsPendingTermination()) { time_t now = time(NULL); /* Note that this loop logic is single threaded, but ACTIVE_THREADS might still change in threads pertaining to service handling */ if (ThreadLock(cft_server_children)) { if (ACTIVE_THREADS == 0) { CheckFileChanges(&policy, config, report_context); } ThreadUnlock(cft_server_children); } // Check whether we should try to establish peering with a hub if ((COLLECT_INTERVAL > 0) && ((now - last_collect) > COLLECT_INTERVAL)) { TryCollectCall(); last_collect = now; continue; } /* check if listening is working */ if (sd != -1) { // Look for normal incoming service requests FD_ZERO(&rset); FD_SET(sd, &rset); timeout.tv_sec = 10; /* Set a 10 second timeout for select */ timeout.tv_usec = 0; CfDebug(" -> Waiting at incoming select...\n"); ret_val = select((sd + 1), &rset, NULL, NULL, &timeout); if (ret_val == -1) /* Error received from call to select */ { if (errno == EINTR) { continue; } else { CfOut(cf_error, "select", "select failed"); exit(1); } } else if (!ret_val) /* No data waiting, we must have timed out! */ { continue; } CfOut(cf_verbose, "", " -> Accepting a connection\n"); if ((sd_reply = accept(sd, (struct sockaddr *) &cin, &addrlen)) != -1) { char ipaddr[CF_MAXVARSIZE]; memset(ipaddr, 0, CF_MAXVARSIZE); ThreadLock(cft_getaddr); snprintf(ipaddr, CF_MAXVARSIZE - 1, "%s", sockaddr_ntop((struct sockaddr *) &cin)); ThreadUnlock(cft_getaddr); ServerEntryPoint(sd_reply, ipaddr, SV); } } } }
void StartServer(EvalContext *ctx, Policy **policy, GenericAgentConfig *config) { int sd = -1; fd_set rset; int ret_val; CfLock thislock; time_t last_policy_reload = 0; extern int COLLECT_WINDOW; struct sockaddr_storage cin; socklen_t addrlen = sizeof(cin); MakeSignalPipe(); signal(SIGINT, HandleSignalsForDaemon); signal(SIGTERM, HandleSignalsForDaemon); signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGUSR1, HandleSignalsForDaemon); signal(SIGUSR2, HandleSignalsForDaemon); ServerTLSInitialize(); sd = SetServerListenState(ctx, QUEUESIZE, SERVER_LISTEN, &InitServer); TransactionContext tc = { .ifelapsed = 0, .expireafter = 1, }; Policy *server_cfengine_policy = PolicyNew(); Promise *pp = NULL; { Bundle *bp = PolicyAppendBundle(server_cfengine_policy, NamespaceDefault(), "server_cfengine_bundle", "agent", NULL, NULL); PromiseType *tp = BundleAppendPromiseType(bp, "server_cfengine"); pp = PromiseTypeAppendPromise(tp, config->input_file, (Rval) { NULL, RVAL_TYPE_NOPROMISEE }, NULL); } assert(pp); thislock = AcquireLock(ctx, pp->promiser, VUQNAME, CFSTARTTIME, tc, pp, false); if (thislock.lock == NULL) { PolicyDestroy(server_cfengine_policy); return; } if (sd != -1) { Log(LOG_LEVEL_VERBOSE, "Listening for connections ..."); } #ifdef __MINGW32__ if (!NO_FORK) { Log(LOG_LEVEL_VERBOSE, "Windows does not support starting processes in the background - starting in foreground"); } #else /* !__MINGW32__ */ if ((!NO_FORK) && (fork() != 0)) { _exit(EXIT_SUCCESS); } if (!NO_FORK) { ActAsDaemon(); } #endif /* !__MINGW32__ */ WritePID("cf-serverd.pid"); /* Andrew Stribblehill <*****@*****.**> -- close sd on exec */ #ifndef __MINGW32__ fcntl(sd, F_SETFD, FD_CLOEXEC); #endif CollectCallStart(COLLECT_INTERVAL); while (!IsPendingTermination()) { /* Note that this loop logic is single threaded, but ACTIVE_THREADS might still change in threads pertaining to service handling */ if (ThreadLock(cft_server_children)) { if (ACTIVE_THREADS == 0) { CheckFileChanges(ctx, policy, config, &last_policy_reload); } ThreadUnlock(cft_server_children); } // Check whether we have established peering with a hub if (CollectCallHasPending()) { int waiting_queue = 0; int new_client = CollectCallGetPending(&waiting_queue); if (waiting_queue > COLLECT_WINDOW) { Log(LOG_LEVEL_INFO, "Closing collect call because it would take" "longer than the allocated window [%d]", COLLECT_WINDOW); } ConnectionInfo *info = ConnectionInfoNew(); if (info) { ConnectionInfoSetSocket(info, new_client); ServerEntryPoint(ctx, POLICY_SERVER, info); CollectCallMarkProcessed(); } } else { /* check if listening is working */ if (sd != -1) { // Look for normal incoming service requests int signal_pipe = GetSignalPipe(); FD_ZERO(&rset); FD_SET(sd, &rset); FD_SET(signal_pipe, &rset); Log(LOG_LEVEL_DEBUG, "Waiting at incoming select..."); struct timeval timeout = { .tv_sec = 60, .tv_usec = 0 }; int max_fd = (sd > signal_pipe) ? (sd + 1) : (signal_pipe + 1); ret_val = select(max_fd, &rset, NULL, NULL, &timeout); // Empty the signal pipe. We don't need the values. unsigned char buf; while (recv(signal_pipe, &buf, 1, 0) > 0) {} if (ret_val == -1) /* Error received from call to select */ { if (errno == EINTR) { continue; } else { Log(LOG_LEVEL_ERR, "select failed. (select: %s)", GetErrorStr()); exit(1); } } else if (!ret_val) /* No data waiting, we must have timed out! */ { continue; } if (FD_ISSET(sd, &rset)) { int new_client = accept(sd, (struct sockaddr *)&cin, &addrlen); if (new_client == -1) { continue; } /* Just convert IP address to string, no DNS lookup. */ char ipaddr[CF_MAX_IP_LEN] = ""; getnameinfo((struct sockaddr *) &cin, addrlen, ipaddr, sizeof(ipaddr), NULL, 0, NI_NUMERICHOST); ConnectionInfo *info = ConnectionInfoNew(); if (info) { ConnectionInfoSetSocket(info, new_client); ServerEntryPoint(ctx, ipaddr, info); } } } } } CollectCallStop(); PolicyDestroy(server_cfengine_policy); } /*********************************************************************/ /* Level 2 */ /*********************************************************************/ int InitServer(size_t queue_size) { int sd = -1; if ((sd = OpenReceiverChannel()) == -1) { Log(LOG_LEVEL_ERR, "Unable to start server"); exit(EXIT_FAILURE); } if (listen(sd, queue_size) == -1) { Log(LOG_LEVEL_ERR, "listen failed. (listen: %s)", GetErrorStr()); exit(EXIT_FAILURE); } return sd; }
void StartServer(int argc,char **argv) { int pid,time_to_run = false; time_t now = time(NULL); #ifdef HAVE_PTHREAD_H pthread_t tid = 1; #else int tid = -1 #endif Banner("Starting server"); if ((!NO_FORK) && (fork() != 0)) { snprintf(OUTPUT,CF_BUFSIZE*2,"cfexecd starting %.24s\n",ctime(&now)); CfLog(cfinform,OUTPUT,""); exit(0); } if (!ONCE) { if (!GetLock("cfexecd","execd",0,0,VUQNAME,now)) { snprintf(OUTPUT,CF_BUFSIZE*2,"cfexecd: Couldn't get a lock -- exists or too soon: IfElapsed %d, ExpireAfter %d\n",0,0); CfLog(cfverbose,OUTPUT,""); return; } SaveExecLock(); } if (!NO_FORK) { ActAsDaemon(0); } WritePID("cfexecd.pid"); signal(SIGINT,(void *)ExitCleanly); signal(SIGTERM,(void *)ExitCleanly); signal(SIGHUP,SIG_IGN); signal(SIGPIPE,SIG_IGN); signal(SIGUSR1,HandleSignal); signal(SIGUSR2,HandleSignal); umask(077); if (ONCE) { GetCfStuff(); LocalExec((void *)0); } else { char **nargv; int i; /* * Append --once option to our arguments for spawned monitor process. */ nargv = malloc(sizeof(char *) * (argc+2)); for (i = 0; i < argc; i++) { nargv[i] = argv[i]; } nargv[i++] = strdup("--once"); nargv[i++] = NULL; GetCfStuff(); while (true) { time_to_run = ScheduleRun(); if (time_to_run) { if (!GetLock("cfd","exec",CF_EXEC_IFELAPSED,CF_EXEC_EXPIREAFTER,VUQNAME,time(NULL))) { snprintf(OUTPUT,CF_BUFSIZE*2,"cfexecd: Couldn't get exec lock -- exists or too soon: IfElapsed %d, ExpireAfter %d\n",CF_EXEC_IFELAPSED,CF_EXEC_EXPIREAFTER); CfLog(cfverbose,OUTPUT,""); continue; } GetCfStuff(); #ifdef NT /* * Spawn a separate process - spawn will work if the cfexecd binary * has changed (where cygwin's fork() would fail). */ Debug("Spawning %s\n", nargv[0]); pid = _spawnvp((int)_P_NOWAIT,nargv[0],nargv); if (pid < 1) { CfLog(cfinform,"Can't spawn run","spawnvp"); } #endif #ifndef NT #if (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) pthread_attr_init(&PTHREADDEFAULTS); pthread_attr_setdetachstate(&PTHREADDEFAULTS,PTHREAD_CREATE_DETACHED); #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE pthread_attr_setstacksize(&PTHREADDEFAULTS,(size_t)2048*1024); #endif if (pthread_create(&tid,&PTHREADDEFAULTS,LocalExec,(void *)1) != 0) { CfLog(cfinform,"Can't create thread!","pthread_create"); LocalExec((void *)1); } pthread_attr_destroy(&PTHREADDEFAULTS); #else LocalExec((void *)1); #endif #endif ReleaseCurrentLock(); } } } }
void StartServer(EvalContext *ctx, Policy **policy, GenericAgentConfig *config) { int sd = -1, sd_reply; fd_set rset; struct timeval timeout; int ret_val; CfLock thislock; time_t starttime = time(NULL), last_collect = 0; struct sockaddr_storage cin; socklen_t addrlen = sizeof(cin); signal(SIGINT, HandleSignalsForDaemon); signal(SIGTERM, HandleSignalsForDaemon); signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGUSR1, HandleSignalsForDaemon); signal(SIGUSR2, HandleSignalsForDaemon); sd = SetServerListenState(ctx, QUEUESIZE); TransactionContext tc = { .ifelapsed = 0, .expireafter = 1, }; Policy *server_cfengine_policy = PolicyNew(); Promise *pp = NULL; { Bundle *bp = PolicyAppendBundle(server_cfengine_policy, NamespaceDefault(), "server_cfengine_bundle", "agent", NULL, NULL); PromiseType *tp = BundleAppendPromiseType(bp, "server_cfengine"); pp = PromiseTypeAppendPromise(tp, config->input_file, (Rval) { NULL, RVAL_TYPE_NOPROMISEE }, NULL); } assert(pp); thislock = AcquireLock(ctx, pp->promiser, VUQNAME, CFSTARTTIME, tc, pp, false); if (thislock.lock == NULL) { PolicyDestroy(server_cfengine_policy); return; } Log(LOG_LEVEL_INFO, "cf-serverd starting %.24s", ctime(&starttime)); if (sd != -1) { Log(LOG_LEVEL_VERBOSE, "Listening for connections ..."); } #ifdef __MINGW32__ if (!NO_FORK) { Log(LOG_LEVEL_VERBOSE, "Windows does not support starting processes in the background - starting in foreground"); } #else /* !__MINGW32__ */ if ((!NO_FORK) && (fork() != 0)) { _exit(0); } if (!NO_FORK) { ActAsDaemon(sd); } #endif /* !__MINGW32__ */ WritePID("cf-serverd.pid"); /* Andrew Stribblehill <*****@*****.**> -- close sd on exec */ #ifndef __MINGW32__ fcntl(sd, F_SETFD, FD_CLOEXEC); #endif while (!IsPendingTermination()) { time_t now = time(NULL); /* Note that this loop logic is single threaded, but ACTIVE_THREADS might still change in threads pertaining to service handling */ if (ThreadLock(cft_server_children)) { if (ACTIVE_THREADS == 0) { CheckFileChanges(ctx, policy, config); } ThreadUnlock(cft_server_children); } // Check whether we should try to establish peering with a hub if ((COLLECT_INTERVAL > 0) && ((now - last_collect) > COLLECT_INTERVAL)) { TryCollectCall(); last_collect = now; continue; } /* check if listening is working */ if (sd != -1) { // Look for normal incoming service requests FD_ZERO(&rset); FD_SET(sd, &rset); /* Set 1 second timeout for select, so that signals are handled in * a timely manner */ timeout.tv_sec = 1; timeout.tv_usec = 0; Log(LOG_LEVEL_DEBUG, "Waiting at incoming select..."); ret_val = select((sd + 1), &rset, NULL, NULL, &timeout); if (ret_val == -1) /* Error received from call to select */ { if (errno == EINTR) { continue; } else { Log(LOG_LEVEL_ERR, "select failed. (select: %s)", GetErrorStr()); exit(1); } } else if (!ret_val) /* No data waiting, we must have timed out! */ { continue; } Log(LOG_LEVEL_VERBOSE, "Accepting a connection"); if ((sd_reply = accept(sd, (struct sockaddr *) &cin, &addrlen)) != -1) { /* Just convert IP address to string, no DNS lookup. */ char ipaddr[CF_MAX_IP_LEN] = ""; getnameinfo((struct sockaddr *) &cin, addrlen, ipaddr, sizeof(ipaddr), NULL, 0, NI_NUMERICHOST); ServerEntryPoint(ctx, sd_reply, ipaddr); } } } PolicyDestroy(server_cfengine_policy); } /*********************************************************************/ /* Level 2 */ /*********************************************************************/ int InitServer(size_t queue_size) { int sd = -1; if ((sd = OpenReceiverChannel()) == -1) { Log(LOG_LEVEL_ERR, "Unable to start server"); exit(1); } if (listen(sd, queue_size) == -1) { Log(LOG_LEVEL_ERR, "listen failed. (listen: %s)", GetErrorStr()); exit(1); } return sd; }