Ejemplo n.º 1
0
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);
            }
        }
    }
}
Ejemplo n.º 2
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);
    }
}