Beispiel #1
0
void KeepControlPromises(Policy *policy)
{
    Rval retval;
    Rlist *rp;

    Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_AGENT);
    if (constraints)
    {
        for (size_t i = 0; i < SeqLength(constraints); i++)
        {
            Constraint *cp = SeqAt(constraints, i);

            if (IsExcluded(cp->classes, NULL))
            {
                continue;
            }

            if (GetVariable("control_common", cp->lval, &retval) != DATA_TYPE_NONE)
            {
                /* Already handled in generic_agent */
                continue;
            }

            if (GetVariable("control_agent", cp->lval, &retval) == DATA_TYPE_NONE)
            {
                CfOut(cf_error, "", "Unknown lval %s in agent control body", cp->lval);
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_maxconnections].lval) == 0)
            {
                CFA_MAXTHREADS = (int) Str2Int(retval.item);
                CfOut(cf_verbose, "", "SET maxconnections = %d\n", CFA_MAXTHREADS);
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_checksum_alert_time].lval) == 0)
            {
                CF_PERSISTENCE = (int) Str2Int(retval.item);
                CfOut(cf_verbose, "", "SET checksum_alert_time = %d\n", CF_PERSISTENCE);
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_agentfacility].lval) == 0)
            {
                SetFacility(retval.item);
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_agentaccess].lval) == 0)
            {
                ACCESSLIST = (Rlist *) retval.item;
                CheckAgentAccess(ACCESSLIST, InputFiles(policy));
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_refresh_processes].lval) == 0)
            {
                Rlist *rp;

                if (VERBOSE)
                {
                    printf("%s> SET refresh_processes when starting: ", VPREFIX);

                    for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next)
                    {
                        printf(" %s", (char *) rp->item);
                        PrependItem(&PROCESSREFRESH, rp->item, NULL);
                    }

                    printf("\n");
                }

                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_abortclasses].lval) == 0)
            {
                Rlist *rp;

                CfOut(cf_verbose, "", "SET Abort classes from ...\n");

                for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next)
                {
                    char name[CF_MAXVARSIZE] = "";

                    strncpy(name, rp->item, CF_MAXVARSIZE - 1);

                    AddAbortClass(name, cp->classes);
                }

                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_abortbundleclasses].lval) == 0)
            {
                Rlist *rp;

                CfOut(cf_verbose, "", "SET Abort bundle classes from ...\n");

                for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next)
                {
                    char name[CF_MAXVARSIZE] = "";

                    strncpy(name, rp->item, CF_MAXVARSIZE - 1);

                    if (!IsItemIn(ABORTBUNDLEHEAP, name))
                    {
                        AppendItem(&ABORTBUNDLEHEAP, name, cp->classes);
                    }
                }

                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_addclasses].lval) == 0)
            {
                Rlist *rp;

                CfOut(cf_verbose, "", "-> Add classes ...\n");

                for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next)
                {
                    CfOut(cf_verbose, "", " -> ... %s\n", ScalarValue(rp));
                    NewClass(rp->item, NULL);
                }

                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_auditing].lval) == 0)
            {
                CfOut(cf_verbose, "", "This option does nothing and is retained for compatibility reasons");
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_alwaysvalidate].lval) == 0)
            {
                ALWAYS_VALIDATE = GetBoolean(retval.item);
                CfOut(cf_verbose, "", "SET alwaysvalidate = %d\n", ALWAYS_VALIDATE);
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_allclassesreport].lval) == 0)
            {
                ALLCLASSESREPORT = GetBoolean(retval.item);
                CfOut(cf_verbose, "", "SET allclassesreport = %d\n", ALLCLASSESREPORT);
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_secureinput].lval) == 0)
            {
                CFPARANOID = GetBoolean(retval.item);
                CfOut(cf_verbose, "", "SET secure input = %d\n", CFPARANOID);
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_binarypaddingchar].lval) == 0)
            {
                CfOut(cf_verbose, "", "binarypaddingchar is obsolete and does nothing\n");
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_bindtointerface].lval) == 0)
            {
                strncpy(BINDINTERFACE, retval.item, CF_BUFSIZE - 1);
                CfOut(cf_verbose, "", "SET bindtointerface = %s\n", BINDINTERFACE);
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_hashupdates].lval) == 0)
            {
                bool enabled = GetBoolean(retval.item);

                SetChecksumUpdates(enabled);
                CfOut(cf_verbose, "", "SET ChecksumUpdates %d\n", enabled);
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_exclamation].lval) == 0)
            {
                CfOut(cf_verbose, "", "exclamation control is deprecated and does not do anything\n");
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_childlibpath].lval) == 0)
            {
                char output[CF_BUFSIZE];

                snprintf(output, CF_BUFSIZE, "LD_LIBRARY_PATH=%s", (char *) retval.item);
                if (putenv(xstrdup(output)) == 0)
                {
                    CfOut(cf_verbose, "", "Setting %s\n", output);
                }
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_defaultcopytype].lval) == 0)
            {
                DEFAULT_COPYTYPE = (char *) retval.item;
                CfOut(cf_verbose, "", "SET defaultcopytype = %s\n", DEFAULT_COPYTYPE);
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_fsinglecopy].lval) == 0)
            {
                SINGLE_COPY_LIST = (Rlist *) retval.item;
                CfOut(cf_verbose, "", "SET file single copy list\n");
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_fautodefine].lval) == 0)
            {
                SetFileAutoDefineList(ListRvalValue(retval));
                CfOut(cf_verbose, "", "SET file auto define list\n");
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_dryrun].lval) == 0)
            {
                DONTDO = GetBoolean(retval.item);
                CfOut(cf_verbose, "", "SET dryrun = %c\n", DONTDO);
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_inform].lval) == 0)
            {
                INFORM = GetBoolean(retval.item);
                CfOut(cf_verbose, "", "SET inform = %c\n", INFORM);
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_verbose].lval) == 0)
            {
                VERBOSE = GetBoolean(retval.item);
                CfOut(cf_verbose, "", "SET inform = %c\n", VERBOSE);
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_repository].lval) == 0)
            {
                SetRepositoryLocation(retval.item);
                CfOut(cf_verbose, "", "SET repository = %s\n", ScalarRvalValue(retval));
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_skipidentify].lval) == 0)
            {
                bool enabled = GetBoolean(retval.item);

                SetSkipIdentify(enabled);
                CfOut(cf_verbose, "", "SET skipidentify = %d\n", (int) enabled);
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_suspiciousnames].lval) == 0)
            {

                for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next)
                {
                    AddFilenameToListOfSuspicious(ScalarValue(rp));
                    CfOut(cf_verbose, "", "-> Considering %s as suspicious file", ScalarValue(rp));
                }

                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_repchar].lval) == 0)
            {
                char c = *(char *) retval.item;

                SetRepositoryChar(c);
                CfOut(cf_verbose, "", "SET repchar = %c\n", c);
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_mountfilesystems].lval) == 0)
            {
                CF_MOUNTALL = GetBoolean(retval.item);
                CfOut(cf_verbose, "", "SET mountfilesystems = %d\n", CF_MOUNTALL);
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_editfilesize].lval) == 0)
            {
                EDITFILESIZE = Str2Int(retval.item);
                CfOut(cf_verbose, "", "SET EDITFILESIZE = %d\n", EDITFILESIZE);
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_ifelapsed].lval) == 0)
            {
                VIFELAPSED = Str2Int(retval.item);
                CfOut(cf_verbose, "", "SET ifelapsed = %d\n", VIFELAPSED);
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_expireafter].lval) == 0)
            {
                VEXPIREAFTER = Str2Int(retval.item);
                CfOut(cf_verbose, "", "SET ifelapsed = %d\n", VEXPIREAFTER);
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_timeout].lval) == 0)
            {
                CONNTIMEOUT = Str2Int(retval.item);
                CfOut(cf_verbose, "", "SET timeout = %jd\n", (intmax_t) CONNTIMEOUT);
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_max_children].lval) == 0)
            {
                CFA_BACKGROUND_LIMIT = Str2Int(retval.item);
                CfOut(cf_verbose, "", "SET MAX_CHILDREN = %d\n", CFA_BACKGROUND_LIMIT);
                if (CFA_BACKGROUND_LIMIT > 10)
                {
                    CfOut(cf_error, "", "Silly value for max_children in agent control promise (%d > 10)",
                          CFA_BACKGROUND_LIMIT);
                    CFA_BACKGROUND_LIMIT = 1;
                }
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_syslog].lval) == 0)
            {
                CfOut(cf_verbose, "", "SET syslog = %d\n", GetBoolean(retval.item));
                continue;
            }

            if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_environment].lval) == 0)
            {
                Rlist *rp;

                CfOut(cf_verbose, "", "SET environment variables from ...\n");

                for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next)
                {
                    if (putenv(rp->item) != 0)
                    {
                        CfOut(cf_error, "putenv", "Failed to set environment variable %s", ScalarValue(rp));
                    }
                }

                continue;
            }
        }
    }

    if (GetVariable("control_common", CFG_CONTROLBODY[cfg_lastseenexpireafter].lval, &retval) != DATA_TYPE_NONE)
    {
        LASTSEENEXPIREAFTER = Str2Int(retval.item) * 60;
    }

    if (GetVariable("control_common", CFG_CONTROLBODY[cfg_fips_mode].lval, &retval) != DATA_TYPE_NONE)
    {
        FIPS_MODE = GetBoolean(retval.item);
        CfOut(cf_verbose, "", "SET FIPS_MODE = %d\n", FIPS_MODE);
    }

    if (GetVariable("control_common", CFG_CONTROLBODY[cfg_syslog_port].lval, &retval) != DATA_TYPE_NONE)
    {
        SetSyslogPort(Str2Int(retval.item));
        CfOut(cf_verbose, "", "SET syslog_port to %s", ScalarRvalValue(retval));
    }

    if (GetVariable("control_common", CFG_CONTROLBODY[cfg_syslog_host].lval, &retval) != DATA_TYPE_NONE)
    {
        SetSyslogHost(Hostname2IPString(retval.item));
        CfOut(cf_verbose, "", "SET syslog_host to %s", Hostname2IPString(retval.item));
    }

#ifdef HAVE_NOVA
    Nova_Initialize();
#endif
}
Beispiel #2
0
static void test_rval_to_scalar2(void **state)
{
    Rval rval = { NULL, CF_FNCALL };
    expect_assert_failure(ScalarRvalValue(rval));
}
Beispiel #3
0
void KeepControlPromises()
{
    Constraint *cp;
    Rval retval;

    CFD_MAXPROCESSES = 30;
    MAXTRIES = 5;
    CFD_INTERVAL = 0;
    DENYBADCLOCKS = true;
    CFRUNCOMMAND[0] = '\0';
    SetChecksumUpdates(true);

/* Keep promised agent behaviour - control bodies */

    Banner("Server control promises..");

    HashControls();

/* Now expand */

    for (cp = ControlBodyConstraints(cf_server); cp != NULL; cp = cp->next)
    {
        if (IsExcluded(cp->classes))
        {
            continue;
        }

        if (GetVariable("control_server", cp->lval, &retval) == cf_notype)
        {
            CfOut(cf_error, "", "Unknown lval %s in server control body", cp->lval);
            continue;
        }

        if (strcmp(cp->lval, CFS_CONTROLBODY[cfs_serverfacility].lval) == 0)
        {
            SetFacility(retval.item);
            continue;
        }

        if (strcmp(cp->lval, CFS_CONTROLBODY[cfs_denybadclocks].lval) == 0)
        {
            DENYBADCLOCKS = GetBoolean(retval.item);
            CfOut(cf_verbose, "", "SET denybadclocks = %d\n", DENYBADCLOCKS);
            continue;
        }

        if (strcmp(cp->lval, CFS_CONTROLBODY[cfs_logencryptedtransfers].lval) == 0)
        {
            LOGENCRYPT = GetBoolean(retval.item);
            CfOut(cf_verbose, "", "SET LOGENCRYPT = %d\n", LOGENCRYPT);
            continue;
        }

        if (strcmp(cp->lval, CFS_CONTROLBODY[cfs_logallconnections].lval) == 0)
        {
            LOGCONNS = GetBoolean(retval.item);
            CfOut(cf_verbose, "", "SET LOGCONNS = %d\n", LOGCONNS);
            continue;
        }

        if (strcmp(cp->lval, CFS_CONTROLBODY[cfs_maxconnections].lval) == 0)
        {
            CFD_MAXPROCESSES = (int) Str2Int(retval.item);
            MAXTRIES = CFD_MAXPROCESSES / 3;
            CfOut(cf_verbose, "", "SET maxconnections = %d\n", CFD_MAXPROCESSES);
            continue;
        }

        if (strcmp(cp->lval, CFS_CONTROLBODY[cfs_cfruncommand].lval) == 0)
        {
            strncpy(CFRUNCOMMAND, retval.item, CF_BUFSIZE - 1);
            CfOut(cf_verbose, "", "SET cfruncommand = %s\n", CFRUNCOMMAND);
            continue;
        }

        if (strcmp(cp->lval, CFS_CONTROLBODY[cfs_allowconnects].lval) == 0)
        {
            Rlist *rp;

            CfOut(cf_verbose, "", "SET Allowing connections from ...\n");

            for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next)
            {
                if (!IsItemIn(NONATTACKERLIST, rp->item))
                {
                    AppendItem(&NONATTACKERLIST, rp->item, cp->classes);
                }
            }

            continue;
        }

        if (strcmp(cp->lval, CFS_CONTROLBODY[cfs_denyconnects].lval) == 0)
        {
            Rlist *rp;

            CfOut(cf_verbose, "", "SET Denying connections from ...\n");

            for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next)
            {
                if (!IsItemIn(ATTACKERLIST, rp->item))
                {
                    AppendItem(&ATTACKERLIST, rp->item, cp->classes);
                }
            }

            continue;
        }

        if (strcmp(cp->lval, CFS_CONTROLBODY[cfs_skipverify].lval) == 0)
        {
            Rlist *rp;

            CfOut(cf_verbose, "", "SET Skip verify connections from ...\n");

            for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next)
            {
                if (!IsItemIn(SKIPVERIFY, rp->item))
                {
                    AppendItem(&SKIPVERIFY, rp->item, cp->classes);
                }
            }

            continue;
        }

        if (strcmp(cp->lval, CFS_CONTROLBODY[cfs_dynamicaddresses].lval) == 0)
        {
            Rlist *rp;

            CfOut(cf_verbose, "", "SET Dynamic addresses from ...\n");

            for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next)
            {
                if (!IsItemIn(DHCPLIST, rp->item))
                {
                    AppendItem(&DHCPLIST, rp->item, cp->classes);
                }
            }

            continue;
        }

        if (strcmp(cp->lval, CFS_CONTROLBODY[cfs_allowallconnects].lval) == 0)
        {
            Rlist *rp;

            CfOut(cf_verbose, "", "SET Allowing multiple connections from ...\n");

            for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next)
            {
                if (!IsItemIn(MULTICONNLIST, rp->item))
                {
                    AppendItem(&MULTICONNLIST, rp->item, cp->classes);
                }
            }

            continue;
        }

        if (strcmp(cp->lval, CFS_CONTROLBODY[cfs_allowusers].lval) == 0)
        {
            Rlist *rp;

            CfOut(cf_verbose, "", "SET Allowing users ...\n");

            for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next)
            {
                if (!IsItemIn(ALLOWUSERLIST, rp->item))
                {
                    AppendItem(&ALLOWUSERLIST, rp->item, cp->classes);
                }
            }

            continue;
        }

        if (strcmp(cp->lval, CFS_CONTROLBODY[cfs_trustkeysfrom].lval) == 0)
        {
            Rlist *rp;

            CfOut(cf_verbose, "", "SET Trust keys from ...\n");

            for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next)
            {
                if (!IsItemIn(TRUSTKEYLIST, rp->item))
                {
                    AppendItem(&TRUSTKEYLIST, rp->item, cp->classes);
                }
            }

            continue;
        }

        if (strcmp(cp->lval, CFS_CONTROLBODY[cfs_portnumber].lval) == 0)
        {
            SHORT_CFENGINEPORT = (short) Str2Int(retval.item);
            strncpy(STR_CFENGINEPORT, retval.item, 15);
            CfOut(cf_verbose, "", "SET default portnumber = %u = %s = %s\n", (int) SHORT_CFENGINEPORT, STR_CFENGINEPORT,
                  ScalarRvalValue(retval));
            SHORT_CFENGINEPORT = htons((short) Str2Int(retval.item));
            continue;
        }

        if (strcmp(cp->lval, CFS_CONTROLBODY[cfs_keyttl].lval) == 0)
        {
            CfOut(cf_verbose, "", "Ignoring deprecated option keycacheTTL");
            continue;
        }

        if (strcmp(cp->lval, CFS_CONTROLBODY[cfs_bindtointerface].lval) == 0)
        {
            strncpy(BINDINTERFACE, retval.item, CF_BUFSIZE - 1);
            CfOut(cf_verbose, "", "SET bindtointerface = %s\n", BINDINTERFACE);
            continue;
        }
    }

    if (GetVariable("control_common", CFG_CONTROLBODY[cfg_syslog_host].lval, &retval) != cf_notype)
    {
        SetSyslogHost(Hostname2IPString(retval.item));
    }

    if (GetVariable("control_common", CFG_CONTROLBODY[cfg_syslog_port].lval, &retval) != cf_notype)
    {
        SetSyslogPort(Str2Int(retval.item));
    }

    if (GetVariable("control_common", CFG_CONTROLBODY[cfg_fips_mode].lval, &retval) != cf_notype)
    {
        FIPS_MODE = GetBoolean(retval.item);
        CfOut(cf_verbose, "", "SET FIPS_MODE = %d\n", FIPS_MODE);
    }

    if (GetVariable("control_common", CFG_CONTROLBODY[cfg_lastseenexpireafter].lval, &retval) != cf_notype)
    {
        LASTSEENEXPIREAFTER = Str2Int(retval.item) * 60;
    }
}
Beispiel #4
0
static void test_rval_to_scalar(void **state)
{
    Rval rval = { "abc", CF_SCALAR };
    assert_string_equal("abc", ScalarRvalValue(rval));
}
Beispiel #5
0
void KeepPromises(Policy *policy, ExecConfig *config)
{
    bool schedule_is_specified = false;

    for (Constraint *cp = ControlBodyConstraints(policy, AGENT_TYPE_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)
        {
            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();
    }
}