EvalContext *EvalContextNew(void) { EvalContext *ctx = xmalloc(sizeof(EvalContext)); ctx->heap_soft = StringSetNew(); ctx->heap_hard = StringSetNew(); return ctx; }
Policy *GenericAgentLoadPolicy(EvalContext *ctx, GenericAgentConfig *config) { config->policy_last_read_attempt = time(NULL); StringSet *parsed_files = StringSetNew(); StringSet *failed_files = StringSetNew(); Policy *policy = LoadPolicyFile(ctx, config, config->input_file, parsed_files, failed_files); if (StringSetSize(failed_files) > 0) { Log(LOG_LEVEL_ERR, "There are syntax errors in policy files"); exit(EXIT_FAILURE); } StringSetDestroy(parsed_files); StringSetDestroy(failed_files); { Seq *errors = SeqNew(100, PolicyErrorDestroy); if (PolicyCheckPartial(policy, errors)) { if (!config->bundlesequence && (PolicyIsRunnable(policy) || config->check_runnable)) { Log(LOG_LEVEL_VERBOSE, "Running full policy integrity checks"); PolicyCheckRunnable(ctx, policy, errors, config->ignore_missing_bundles); } } if (SeqLength(errors) > 0) { Writer *writer = FileWriter(stderr); for (size_t i = 0; i < errors->length; i++) { PolicyErrorWrite(writer, errors->data[i]); } WriterClose(writer); exit(EXIT_FAILURE); // TODO: do not exit } SeqDestroy(errors); } if (LogGetGlobalLevel() >= LOG_LEVEL_VERBOSE) { ShowContext(ctx); } if (policy) { VerifyPromises(ctx, policy, config); } return policy; }
static StackFrame *StackFrameNewBundle(const Bundle *owner, bool inherit_previous) { StackFrame *frame = StackFrameNew(STACK_FRAME_TYPE_BUNDLE, inherit_previous); frame->data.bundle.owner = owner; frame->data.bundle.contexts = StringSetNew(); frame->data.bundle.contexts_negated = StringSetNew(); return frame; }
static StackFrame *StackFrameNew(bool inherit_previous) { StackFrame *frame = xmalloc(sizeof(StackFrame)); frame->contexts = StringSetNew(); frame->contexts_negated = StringSetNew(); frame->inherits_previous = inherit_previous; return frame; }
EvalContext *EvalContextNew(void) { EvalContext *ctx = xmalloc(sizeof(EvalContext)); ctx->heap_soft = StringSetNew(); ctx->heap_hard = StringSetNew(); ctx->heap_negated = StringSetNew(); ctx->heap_abort = NULL; ctx->heap_abort_current_bundle = NULL; ctx->stack = SeqNew(10, StackFrameDestroy); ctx->dependency_handles = StringSetNew(); return ctx; }
StringSet *StringSetFromString(const char *str, char delimiter) { StringSet *set = StringSetNew(); StringSetAddSplit(set, str, delimiter); return set; }
static int SelectOwnerMatch(EvalContext *ctx, char *path, struct stat *lstatptr, Rlist *crit) { Rlist *rp; char ownerName[CF_BUFSIZE]; int gotOwner; StringSet *leafattrib = StringSetNew(); #ifndef __MINGW32__ // no uids on Windows char buffer[CF_SMALLBUF]; snprintf(buffer, CF_SMALLBUF, "%jd", (uintmax_t) lstatptr->st_uid); StringSetAdd(leafattrib, xstrdup(buffer)); #endif /* __MINGW32__ */ gotOwner = GetOwnerName(path, lstatptr, ownerName, sizeof(ownerName)); if (gotOwner) { StringSetAdd(leafattrib, xstrdup(ownerName)); } else { StringSetAdd(leafattrib, xstrdup("none")); } for (rp = crit; rp != NULL; rp = rp->next) { if (EvalFileResult((char *) rp->item, leafattrib)) { Log(LOG_LEVEL_DEBUG, "Select owner match"); StringSetDestroy(leafattrib); return true; } if (gotOwner && (FullTextMatch(ctx, RlistScalarValue(rp), ownerName))) { Log(LOG_LEVEL_DEBUG, "Select owner match"); StringSetDestroy(leafattrib); return true; } #ifndef __MINGW32__ if (FullTextMatch(ctx, RlistScalarValue(rp), buffer)) { Log(LOG_LEVEL_DEBUG, "Select owner match"); StringSetDestroy(leafattrib); return true; } #endif /* !__MINGW32__ */ } StringSetDestroy(leafattrib); return false; }
static void TransformGidsToGroups(StringSet **list) { StringSet *new_list = StringSetNew(); StringSetIterator i = StringSetIteratorInit(*list); const char *data; for (data = StringSetIteratorNext(&i); data; data = StringSetIteratorNext(&i)) { if (strlen(data) != strspn(data, "0123456789")) { // Cannot possibly be a gid. StringSetAdd(new_list, xstrdup(data)); continue; } // In groups vs gids, groups take precedence. So check if it exists. struct group *group_info = GetGrEntry(data, &EqualGroupName); if (!group_info) { if (errno == 0) { group_info = GetGrEntry(data, &EqualGid); if (!group_info) { if (errno != 0) { Log(LOG_LEVEL_ERR, "Error while checking group name '%s': %s", data, GetErrorStr()); StringSetDestroy(new_list); return; } // Neither group nor gid is found. This will lead to an error later, but we don't // handle that here. } else { // Replace gid with group name. StringSetAdd(new_list, xstrdup(group_info->gr_name)); } } else { Log(LOG_LEVEL_ERR, "Error while checking group name '%s': '%s'", data, GetErrorStr()); StringSetDestroy(new_list); return; } } else { StringSetAdd(new_list, xstrdup(data)); } } StringSet *old_list = *list; *list = new_list; StringSetDestroy(old_list); }
ExecConfig *ExecConfigNewDefault(bool scheduled_run, const char *fq_name, const char *ip_address) { ExecConfig *exec_config = xcalloc(1, sizeof(ExecConfig)); exec_config->scheduled_run = scheduled_run; exec_config->fq_name = xstrdup(fq_name); exec_config->ip_address = xstrdup(ip_address); exec_config->schedule = StringSetNew(); ExecConfigResetDefault(exec_config); return exec_config; }
static int SelectGroupMatch(EvalContext *ctx, struct stat *lstatptr, Rlist *crit) { char buffer[CF_SMALLBUF]; struct group *gr; Rlist *rp; StringSet *leafattrib = StringSetNew(); snprintf(buffer, CF_SMALLBUF, "%jd", (uintmax_t) lstatptr->st_gid); StringSetAdd(leafattrib, xstrdup(buffer)); if ((gr = getgrgid(lstatptr->st_gid)) != NULL) { StringSetAdd(leafattrib, xstrdup(gr->gr_name)); } else { StringSetAdd(leafattrib, xstrdup("none")); } for (rp = crit; rp != NULL; rp = rp->next) { if (EvalFileResult((char *) rp->item, leafattrib)) { Log(LOG_LEVEL_DEBUG, "Select group match"); StringSetDestroy(leafattrib); return true; } if (gr && (FullTextMatch(ctx, (char *) rp->item, gr->gr_name))) { Log(LOG_LEVEL_DEBUG, "Select group match"); StringSetDestroy(leafattrib); return true; } if (FullTextMatch(ctx, (char *) rp->item, buffer)) { Log(LOG_LEVEL_DEBUG, "Select group match"); StringSetDestroy(leafattrib); return true; } } StringSetDestroy(leafattrib); return false; }
StringSet *StringSetFromString(const char *str, char delimiter) { StringSet *set = StringSetNew(); char delimiters[2] = { 0 }; delimiters[0] = delimiter; char *copy = xstrdup(str); char *curr = NULL; while ((curr = strsep(©, delimiters))) { StringSetAdd(set, xstrdup(curr)); } free(copy); return set; }
static bool VerifyIfUserNeedsModifs (const char *puser, const User *u, const struct passwd *passwd_info, uint32_t *changemap) { assert(u != NULL); if (u->description != NULL && strcmp (u->description, passwd_info->pw_gecos)) { CFUSR_SETBIT (*changemap, i_comment); } if (u->uid != NULL && (atoi (u->uid) != passwd_info->pw_uid)) { CFUSR_SETBIT (*changemap, i_uid); } if (u->home_dir != NULL && strcmp (u->home_dir, passwd_info->pw_dir)) { CFUSR_SETBIT (*changemap, i_home); } if (u->shell != NULL && strcmp (u->shell, passwd_info->pw_shell)) { CFUSR_SETBIT (*changemap, i_shell); } bool account_is_locked = IsAccountLocked(puser, passwd_info); if ((!account_is_locked && u->policy == USER_STATE_LOCKED) || (account_is_locked && u->policy != USER_STATE_LOCKED)) { CFUSR_SETBIT(*changemap, i_locked); } // Don't bother with passwords if the account is going to be locked anyway. if (u->password != NULL && strcmp (u->password, "") && u->policy != USER_STATE_LOCKED) { if (!IsPasswordCorrect(puser, u->password, u->password_format, passwd_info)) { CFUSR_SETBIT (*changemap, i_password); } } if (SafeStringLength(u->group_primary)) { bool group_could_be_gid = (strlen(u->group_primary) == strspn(u->group_primary, "0123456789")); int gid; // We try name first, even if it looks like a gid. Only fall back to gid. struct group *group_info; errno = 0; group_info = GetGrEntry(u->group_primary, &EqualGroupName); if (!group_info && errno != 0) { Log(LOG_LEVEL_ERR, "Could not obtain information about group '%s': %s", u->group_primary, GetErrorStr()); gid = -1; } else if (!group_info) { if (group_could_be_gid) { gid = atoi(u->group_primary); } else { Log(LOG_LEVEL_ERR, "No such group '%s'.", u->group_primary); gid = -1; } } else { gid = group_info->gr_gid; } if (gid != passwd_info->pw_gid) { CFUSR_SETBIT (*changemap, i_group); } } if (u->groups_secondary_given) { StringSet *wanted_groups = StringSetNew(); for (Rlist *ptr = u->groups_secondary; ptr; ptr = ptr->next) { StringSetAdd(wanted_groups, xstrdup(RvalScalarValue(ptr->val))); } TransformGidsToGroups(&wanted_groups); StringSet *current_groups = StringSetNew(); if (!GroupGetUserMembership (puser, current_groups)) { CFUSR_SETBIT (*changemap, i_groups); } else if (!StringSetIsEqual (current_groups, wanted_groups)) { CFUSR_SETBIT (*changemap, i_groups); } StringSetDestroy(current_groups); StringSetDestroy(wanted_groups); } //////////////////////////////////////////// if (*changemap == 0) { return false; } else { return true; } }
static int SelectProcess(char *procentry, char **names, int *start, int *end, ProcessSelect a) { int result = true, i; char *column[CF_PROCCOLS]; Rlist *rp; StringSet *proc_attr = StringSetNew(); if (!SplitProcLine(procentry, names, start, end, column)) { return false; } for (i = 0; names[i] != NULL; i++) { Log(LOG_LEVEL_DEBUG, "In SelectProcess, COL[%s] = '%s'", names[i], column[i]); } for (rp = a.owner; rp != NULL; rp = rp->next) { if (SelectProcRegexMatch("USER", "UID", (char *) rp->item, names, column)) { StringSetAdd(proc_attr, xstrdup("process_owner")); break; } } if (SelectProcRangeMatch("PID", "PID", a.min_pid, a.max_pid, names, column)) { StringSetAdd(proc_attr, xstrdup("pid")); } if (SelectProcRangeMatch("PPID", "PPID", a.min_ppid, a.max_ppid, names, column)) { StringSetAdd(proc_attr, xstrdup("ppid")); } if (SelectProcRangeMatch("PGID", "PGID", a.min_pgid, a.max_pgid, names, column)) { StringSetAdd(proc_attr, xstrdup("pgid")); } if (SelectProcRangeMatch("VSZ", "SZ", a.min_vsize, a.max_vsize, names, column)) { StringSetAdd(proc_attr, xstrdup("vsize")); } if (SelectProcRangeMatch("RSS", "RSS", a.min_rsize, a.max_rsize, names, column)) { StringSetAdd(proc_attr, xstrdup("rsize")); } if (SelectProcTimeCounterRangeMatch("TIME", "TIME", a.min_ttime, a.max_ttime, names, column)) { StringSetAdd(proc_attr, xstrdup("ttime")); } if (SelectProcTimeAbsRangeMatch ("STIME", "START", a.min_stime, a.max_stime, names, column)) { StringSetAdd(proc_attr, xstrdup("stime")); } if (SelectProcRangeMatch("NI", "PRI", a.min_pri, a.max_pri, names, column)) { StringSetAdd(proc_attr, xstrdup("priority")); } if (SelectProcRangeMatch("NLWP", "NLWP", a.min_thread, a.max_thread, names, column)) { StringSetAdd(proc_attr, xstrdup("threads")); } if (SelectProcRegexMatch("S", "STAT", a.status, names, column)) { StringSetAdd(proc_attr, xstrdup("status")); } if (SelectProcRegexMatch("CMD", "COMMAND", a.command, names, column)) { StringSetAdd(proc_attr, xstrdup("command")); } if (SelectProcRegexMatch("TTY", "TTY", a.tty, names, column)) { StringSetAdd(proc_attr, xstrdup("tty")); } result = EvalProcessResult(a.process_result, proc_attr); StringSetDestroy(proc_attr); for (i = 0; column[i] != NULL; i++) { free(column[i]); } return result; }
int SelectLeaf(EvalContext *ctx, char *path, struct stat *sb, FileSelect fs) { int result = true; Rlist *rp; StringSet *leaf_attr = StringSetNew(); #ifdef __MINGW32__ if (fs.issymlinkto != NULL) { Log(LOG_LEVEL_VERBOSE, "files_select.issymlinkto is ignored on Windows (symbolic links are not supported by Windows)"); } if (fs.groups != NULL) { Log(LOG_LEVEL_VERBOSE, "files_select.search_groups is ignored on Windows (file groups are not supported by Windows)"); } if (fs.bsdflags != NULL) { Log(LOG_LEVEL_VERBOSE, "files_select.search_bsdflags is ignored on Windows"); } #endif /* __MINGW32__ */ if (fs.name == NULL) { StringSetAdd(leaf_attr, xstrdup("leaf_name")); } for (rp = fs.name; rp != NULL; rp = rp->next) { if (SelectNameRegexMatch(ctx, path, rp->item)) { StringSetAdd(leaf_attr, xstrdup("leaf_name")); break; } } if (fs.path == NULL) { StringSetAdd(leaf_attr, xstrdup("leaf_path")); } for (rp = fs.path; rp != NULL; rp = rp->next) { if (SelectPathRegexMatch(ctx, path, rp->item)) { StringSetAdd(leaf_attr, xstrdup("path_name")); break; } } if (SelectTypeMatch(sb, fs.filetypes)) { StringSetAdd(leaf_attr, xstrdup("file_types")); } if ((fs.owners) && (SelectOwnerMatch(ctx, path, sb, fs.owners))) { StringSetAdd(leaf_attr, xstrdup("owner")); } if (fs.owners == NULL) { StringSetAdd(leaf_attr, xstrdup("owner")); } #ifdef __MINGW32__ StringSetAdd(leaf_attr, xstrdup("group")); #else /* !__MINGW32__ */ if ((fs.groups) && (SelectGroupMatch(ctx, sb, fs.groups))) { StringSetAdd(leaf_attr, xstrdup("group")); } if (fs.groups == NULL) { StringSetAdd(leaf_attr, xstrdup("group")); } #endif /* !__MINGW32__ */ if (SelectModeMatch(sb, fs.perms)) { StringSetAdd(leaf_attr, xstrdup("mode")); } #if defined HAVE_CHFLAGS if (SelectBSDMatch(sb, fs.bsdflags)) { StringSetAdd(leaf_attr, xstrdup("bsdflags")); } #endif if (SelectTimeMatch(sb->st_atime, fs.min_atime, fs.max_atime)) { StringSetAdd(leaf_attr, xstrdup("atime")); } if (SelectTimeMatch(sb->st_ctime, fs.min_ctime, fs.max_ctime)) { StringSetAdd(leaf_attr, xstrdup("ctime")); } if (SelectSizeMatch(sb->st_size, fs.min_size, fs.max_size)) { StringSetAdd(leaf_attr, xstrdup("size")); } if (SelectTimeMatch(sb->st_mtime, fs.min_mtime, fs.max_mtime)) { StringSetAdd(leaf_attr, xstrdup("mtime")); } if ((fs.issymlinkto) && (SelectIsSymLinkTo(ctx, path, fs.issymlinkto))) { StringSetAdd(leaf_attr, xstrdup("issymlinkto")); } if ((fs.exec_regex) && (SelectExecRegexMatch(ctx, path, fs.exec_regex, fs.exec_program))) { StringSetAdd(leaf_attr, xstrdup("exec_regex")); } if ((fs.exec_program) && (SelectExecProgram(path, fs.exec_program))) { StringSetAdd(leaf_attr, xstrdup("exec_program")); } result = EvalFileResult(fs.result, leaf_attr); Log(LOG_LEVEL_DEBUG, "Select result '%s' on '%s' was %d", fs.result, path, result); StringSetDestroy(leaf_attr); return result; }
static int SelectTypeMatch(struct stat *lstatptr, Rlist *crit) { Rlist *rp; StringSet *leafattrib = StringSetNew(); if (S_ISREG(lstatptr->st_mode)) { StringSetAdd(leafattrib, xstrdup("reg")); StringSetAdd(leafattrib, xstrdup("plain")); } if (S_ISDIR(lstatptr->st_mode)) { StringSetAdd(leafattrib, xstrdup("dir")); } #ifndef __MINGW32__ if (S_ISLNK(lstatptr->st_mode)) { StringSetAdd(leafattrib, xstrdup("symlink")); } if (S_ISFIFO(lstatptr->st_mode)) { StringSetAdd(leafattrib, xstrdup("fifo")); } if (S_ISSOCK(lstatptr->st_mode)) { StringSetAdd(leafattrib, xstrdup("socket")); } if (S_ISCHR(lstatptr->st_mode)) { StringSetAdd(leafattrib, xstrdup("char")); } if (S_ISBLK(lstatptr->st_mode)) { StringSetAdd(leafattrib, xstrdup("block")); } #endif /* !__MINGW32__ */ #ifdef HAVE_DOOR_CREATE if (S_ISDOOR(lstatptr->st_mode)) { StringSetAdd(leafattrib, xstrdup("door")); } #endif for (rp = crit; rp != NULL; rp = rp->next) { if (EvalFileResult((char *) rp->item, leafattrib)) { StringSetDestroy(leafattrib); return true; } } StringSetDestroy(leafattrib); return false; }
static void TransformGidsToGroups(StringSet **list) { StringSet *new_list = StringSetNew(); StringSetIterator i = StringSetIteratorInit(*list); const char *data; for (data = StringSetIteratorNext(&i); data; data = StringSetIteratorNext(&i)) { if (strlen(data) != strspn(data, "0123456789")) { // Cannot possibly be a gid. StringSetAdd(new_list, xstrdup(data)); continue; } // In groups vs gids, groups take precedence. So check if it exists. errno = 0; struct group *group_info = getgrnam(data); if (!group_info) { switch (errno) { case 0: case ENOENT: case EBADF: case ESRCH: case EWOULDBLOCK: case EPERM: // POSIX is apparently ambiguous here. All values mean "not found". errno = 0; group_info = getgrgid(atoi(data)); if (!group_info) { switch (errno) { case 0: case ENOENT: case EBADF: case ESRCH: case EWOULDBLOCK: case EPERM: // POSIX is apparently ambiguous here. All values mean "not found". // // Neither group nor gid is found. This will lead to an error later, but we don't // handle that here. break; default: Log(LOG_LEVEL_ERR, "Error while checking group name '%s'. (getgrgid: '%s')", data, GetErrorStr()); StringSetDestroy(new_list); return; } } else { // Replace gid with group name. StringSetAdd(new_list, xstrdup(group_info->gr_name)); } break; default: Log(LOG_LEVEL_ERR, "Error while checking group name '%s'. (getgrnam: '%s')", data, GetErrorStr()); StringSetDestroy(new_list); return; } } else { StringSetAdd(new_list, xstrdup(data)); } } StringSet *old_list = *list; *list = new_list; StringSetDestroy(old_list); }
Policy *LoadPolicy(EvalContext *ctx, GenericAgentConfig *config) { StringSet *parsed_files_and_checksums = StringSetNew(); StringSet *failed_files = StringSetNew(); Policy *policy = LoadPolicyFile(ctx, config, config->input_file, parsed_files_and_checksums, failed_files); if (StringSetSize(failed_files) > 0) { Log(LOG_LEVEL_ERR, "There are syntax errors in policy files"); exit(EXIT_FAILURE); } StringSetDestroy(parsed_files_and_checksums); StringSetDestroy(failed_files); { Seq *errors = SeqNew(100, PolicyErrorDestroy); if (PolicyCheckPartial(policy, errors)) { if (!config->bundlesequence && (PolicyIsRunnable(policy) || config->check_runnable)) { Log(LOG_LEVEL_VERBOSE, "Running full policy integrity checks"); PolicyCheckRunnable(ctx, policy, errors, config->ignore_missing_bundles); } } if (SeqLength(errors) > 0) { Writer *writer = FileWriter(stderr); for (size_t i = 0; i < errors->length; i++) { PolicyErrorWrite(writer, errors->data[i]); } WriterClose(writer); exit(EXIT_FAILURE); // TODO: do not exit } SeqDestroy(errors); } if (LogGetGlobalLevel() >= LOG_LEVEL_VERBOSE) { ShowContext(ctx); } if (policy) { for (size_t i = 0; i < SeqLength(policy->bundles); i++) { Bundle *bp = SeqAt(policy->bundles, i); EvalContextStackPushBundleFrame(ctx, bp, NULL, false); for (size_t j = 0; j < SeqLength(bp->promise_types); j++) { PromiseType *sp = SeqAt(bp->promise_types, j); EvalContextStackPushPromiseTypeFrame(ctx, sp); for (size_t ppi = 0; ppi < SeqLength(sp->promises); ppi++) { Promise *pp = SeqAt(sp->promises, ppi); ExpandPromise(ctx, pp, CommonEvalPromise, NULL); } EvalContextStackPopFrame(ctx); } EvalContextStackPopFrame(ctx); } PolicyResolve(ctx, policy, config); // TODO: need to move this inside PolicyCheckRunnable eventually. if (!config->bundlesequence && config->check_runnable) { // only verify policy-defined bundlesequence for cf-agent, cf-promises if ((config->agent_type == AGENT_TYPE_AGENT) || (config->agent_type == AGENT_TYPE_COMMON)) { if (!VerifyBundleSequence(ctx, policy, config)) { FatalError(ctx, "Errors in promise bundles: could not verify bundlesequence"); } } } } JsonElement *validated_doc = ReadReleaseIdFileFromInputs(); if (validated_doc) { const char *release_id = JsonObjectGetAsString(validated_doc, "releaseId"); if (release_id) { policy->release_id = xstrdup(release_id); } JsonDestroy(validated_doc); } return policy; }
static int SelectProcess(EvalContext *ctx, char *procentry, char **names, int *start, int *end, ProcessSelect a) { int result = true, i; char *column[CF_PROCCOLS]; Rlist *rp; StringSet *process_select_attributes = StringSetNew(); if (!SplitProcLine(procentry, names, start, end, column)) { return false; } for (i = 0; names[i] != NULL; i++) { Log(LOG_LEVEL_DEBUG, "In SelectProcess, COL[%s] = '%s'", names[i], column[i]); } for (rp = a.owner; rp != NULL; rp = rp->next) { if (SelectProcRegexMatch(ctx, "USER", "UID", RlistScalarValue(rp), names, column)) { StringSetAdd(process_select_attributes, xstrdup("process_owner")); break; } } if (SelectProcRangeMatch("PID", "PID", a.min_pid, a.max_pid, names, column)) { StringSetAdd(process_select_attributes, xstrdup("pid")); } if (SelectProcRangeMatch("PPID", "PPID", a.min_ppid, a.max_ppid, names, column)) { StringSetAdd(process_select_attributes, xstrdup("ppid")); } if (SelectProcRangeMatch("PGID", "PGID", a.min_pgid, a.max_pgid, names, column)) { StringSetAdd(process_select_attributes, xstrdup("pgid")); } if (SelectProcRangeMatch("VSZ", "SZ", a.min_vsize, a.max_vsize, names, column)) { StringSetAdd(process_select_attributes, xstrdup("vsize")); } if (SelectProcRangeMatch("RSS", "RSS", a.min_rsize, a.max_rsize, names, column)) { StringSetAdd(process_select_attributes, xstrdup("rsize")); } if (SelectProcTimeCounterRangeMatch("TIME", "TIME", a.min_ttime, a.max_ttime, names, column)) { StringSetAdd(process_select_attributes, xstrdup("ttime")); } if (SelectProcTimeAbsRangeMatch ("STIME", "START", a.min_stime, a.max_stime, names, column)) { StringSetAdd(process_select_attributes, xstrdup("stime")); } if (SelectProcRangeMatch("NI", "PRI", a.min_pri, a.max_pri, names, column)) { StringSetAdd(process_select_attributes, xstrdup("priority")); } if (SelectProcRangeMatch("NLWP", "NLWP", a.min_thread, a.max_thread, names, column)) { StringSetAdd(process_select_attributes, xstrdup("threads")); } if (SelectProcRegexMatch(ctx, "S", "STAT", a.status, names, column)) { StringSetAdd(process_select_attributes, xstrdup("status")); } if (SelectProcRegexMatch(ctx, "CMD", "COMMAND", a.command, names, column)) { StringSetAdd(process_select_attributes, xstrdup("command")); } if (SelectProcRegexMatch(ctx, "TTY", "TTY", a.tty, names, column)) { StringSetAdd(process_select_attributes, xstrdup("tty")); } if (!a.process_result) { if (StringSetSize(process_select_attributes) == 0) { result = EvalProcessResult("", process_select_attributes); } else { Writer *w = StringWriter(); StringSetIterator iter = StringSetIteratorInit(process_select_attributes); char *attr = StringSetIteratorNext(&iter); WriterWrite(w, attr); while ((attr = StringSetIteratorNext(&iter))) { WriterWriteChar(w, '.'); WriterWrite(w, attr); } result = EvalProcessResult(StringWriterData(w), process_select_attributes); WriterClose(w); } } else { result = EvalProcessResult(a.process_result, process_select_attributes); } StringSetDestroy(process_select_attributes); for (i = 0; column[i] != NULL; i++) { free(column[i]); } return result; }
static bool SelectProcess(const char *procentry, time_t pstime, char **names, int *start, int *end, const char *process_regex, ProcessSelect a, bool attrselect) { bool result = true; char *column[CF_PROCCOLS]; Rlist *rp; assert(process_regex); StringSet *process_select_attributes = StringSetNew(); memset(column, 0, sizeof(column)); if (!SplitProcLine(procentry, pstime, names, start, end, PS_COLUMN_ALGORITHM[VPSHARDCLASS], column)) { result = false; goto cleanup; } ApplyPlatformExtraTable(names, column); for (int i = 0; names[i] != NULL; i++) { Log(LOG_LEVEL_DEBUG, "In SelectProcess, COL[%s] = '%s'", names[i], column[i]); } if (!SelectProcRegexMatch("CMD", "COMMAND", process_regex, false, names, column)) { result = false; goto cleanup; } if (!attrselect) { // If we are not considering attributes, then the matching is done. goto cleanup; } for (rp = a.owner; rp != NULL; rp = rp->next) { if (SelectProcRegexMatch("USER", "UID", RlistScalarValue(rp), true, names, column)) { StringSetAdd(process_select_attributes, xstrdup("process_owner")); break; } } if (SelectProcRangeMatch("PID", "PID", a.min_pid, a.max_pid, names, column)) { StringSetAdd(process_select_attributes, xstrdup("pid")); } if (SelectProcRangeMatch("PPID", "PPID", a.min_ppid, a.max_ppid, names, column)) { StringSetAdd(process_select_attributes, xstrdup("ppid")); } if (SelectProcRangeMatch("PGID", "PGID", a.min_pgid, a.max_pgid, names, column)) { StringSetAdd(process_select_attributes, xstrdup("pgid")); } if (SelectProcRangeMatch("VSZ", "SZ", a.min_vsize, a.max_vsize, names, column)) { StringSetAdd(process_select_attributes, xstrdup("vsize")); } if (SelectProcRangeMatch("RSS", "RSS", a.min_rsize, a.max_rsize, names, column)) { StringSetAdd(process_select_attributes, xstrdup("rsize")); } if (SelectProcTimeCounterRangeMatch("TIME", "TIME", a.min_ttime, a.max_ttime, names, column)) { StringSetAdd(process_select_attributes, xstrdup("ttime")); } if (SelectProcTimeAbsRangeMatch ("STIME", "START", a.min_stime, a.max_stime, names, column)) { StringSetAdd(process_select_attributes, xstrdup("stime")); } if (SelectProcRangeMatch("NI", "PRI", a.min_pri, a.max_pri, names, column)) { StringSetAdd(process_select_attributes, xstrdup("priority")); } if (SelectProcRangeMatch("NLWP", "NLWP", a.min_thread, a.max_thread, names, column)) { StringSetAdd(process_select_attributes, xstrdup("threads")); } if (SelectProcRegexMatch("S", "STAT", a.status, true, names, column)) { StringSetAdd(process_select_attributes, xstrdup("status")); } if (SelectProcRegexMatch("CMD", "COMMAND", a.command, true, names, column)) { StringSetAdd(process_select_attributes, xstrdup("command")); } if (SelectProcRegexMatch("TTY", "TTY", a.tty, true, names, column)) { StringSetAdd(process_select_attributes, xstrdup("tty")); } if (!a.process_result) { if (StringSetSize(process_select_attributes) == 0) { result = EvalProcessResult("", process_select_attributes); } else { Writer *w = StringWriter(); StringSetIterator iter = StringSetIteratorInit(process_select_attributes); char *attr = StringSetIteratorNext(&iter); WriterWrite(w, attr); while ((attr = StringSetIteratorNext(&iter))) { WriterWriteChar(w, '.'); WriterWrite(w, attr); } result = EvalProcessResult(StringWriterData(w), process_select_attributes); WriterClose(w); } } else { result = EvalProcessResult(a.process_result, process_select_attributes); } cleanup: StringSetDestroy(process_select_attributes); for (int i = 0; column[i] != NULL; i++) { free(column[i]); } return result; }