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); } } } }
/* 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); } }