Item *SelectProcesses(const Item *processes, const char *process_name, ProcessSelect a, bool attrselect) { Item *result = NULL; if (processes == NULL) { return result; } char *names[CF_PROCCOLS]; int start[CF_PROCCOLS]; int end[CF_PROCCOLS]; GetProcessColumnNames(processes->name, &names[0], start, end); pcre *rx = CompileRegex(process_name); if (rx) { /* TODO: use actual time of ps-run, as time(NULL) may be later. */ time_t pstime = time(NULL); for (Item *ip = processes->next; ip != NULL; ip = ip->next) { int s, e; if (StringMatchWithPrecompiledRegex(rx, ip->name, &s, &e)) { if (NULL_OR_EMPTY(ip->name)) { continue; } if (attrselect && !SelectProcess(ip->name, pstime, names, start, end, a)) { continue; } pid_t pid = ExtractPid(ip->name, names, end); if (pid == -1) { Log(LOG_LEVEL_VERBOSE, "Unable to extract pid while looking for %s", process_name); continue; } PrependItem(&result, ip->name, ""); result->counter = (int)pid; } } pcre_free(rx); } for (int i = 0; i < CF_PROCCOLS; i++) { free(names[i]); } return result; }
void ZCopyProcessList(Item **dest, const Item *source, Seq *pidlist, char **names, int *end) { int gpid = ExtractPid(source->name, names, end); if (PidInSeq(pidlist, gpid)) { PrependItem(dest, source->name, ""); } }
Item *SelectProcesses(EvalContext *ctx, const Item *processes, const char *process_name, ProcessSelect a, bool attrselect) { Item *result = NULL; if (processes == NULL) { return result; } char *names[CF_PROCCOLS]; int start[CF_PROCCOLS]; int end[CF_PROCCOLS]; GetProcessColumnNames(processes->name, &names[0], start, end); for (Item *ip = processes->next; ip != NULL; ip = ip->next) { int s, e; if (BlockTextMatch(ctx, process_name, ip->name, &s, &e)) { if (NULL_OR_EMPTY(ip->name)) { continue; } if (attrselect && !SelectProcess(ctx, ip->name, names, start, end, a)) { continue; } pid_t pid = ExtractPid(ip->name, names, end); if (pid == -1) { Log(LOG_LEVEL_VERBOSE, "Unable to extract pid while looking for %s", process_name); continue; } PrependItem(&result, ip->name, ""); result->counter = (int)pid; } } for (int i = 0; i < CF_PROCCOLS; i++) { free(names[i]); } return result; }
Item *SelectProcesses(const char *process_name, const ProcessSelect *a, bool attrselect) { assert(a != NULL); const Item *processes = PROCESSTABLE; Item *result = NULL; if (processes == NULL) { return result; } char *names[CF_PROCCOLS]; int start[CF_PROCCOLS]; int end[CF_PROCCOLS]; GetProcessColumnNames(processes->name, names, start, end); /* TODO: use actual time of ps-run, as time(NULL) may be later. */ time_t pstime = time(NULL); for (Item *ip = processes->next; ip != NULL; ip = ip->next) { if (NULL_OR_EMPTY(ip->name)) { continue; } if (!SelectProcess(ip->name, pstime, names, start, end, process_name, a, attrselect)) { continue; } pid_t pid = ExtractPid(ip->name, names, end); if (pid == -1) { Log(LOG_LEVEL_VERBOSE, "Unable to extract pid while looking for %s", process_name); continue; } PrependItem(&result, ip->name, ""); result->counter = (int)pid; } for (int i = 0; i < CF_PROCCOLS; i++) { free(names[i]); } return result; }
int LoadProcessTable() { FILE *prp; char pscomm[CF_MAXLINKSIZE]; Item *rootprocs = NULL; Item *otherprocs = NULL; if (PROCESSTABLE) { Log(LOG_LEVEL_VERBOSE, "Reusing cached process table"); return true; } LoadPlatformExtraTable(); CheckPsLineLimitations(); const char *psopts = GetProcessOptions(); snprintf(pscomm, CF_MAXLINKSIZE, "%s %s", VPSCOMM[VPSHARDCLASS], psopts); Log(LOG_LEVEL_VERBOSE, "Observe process table with %s", pscomm); if ((prp = cf_popen(pscomm, "r", false)) == NULL) { Log(LOG_LEVEL_ERR, "Couldn't open the process list with command '%s'. (popen: %s)", pscomm, GetErrorStr()); return false; } size_t vbuff_size = CF_BUFSIZE; char *vbuff = xmalloc(vbuff_size); # ifdef HAVE_GETZONEID char *names[CF_PROCCOLS]; int start[CF_PROCCOLS]; int end[CF_PROCCOLS]; Seq *pidlist = SeqNew(1, NULL); Seq *rootpidlist = SeqNew(1, NULL); bool global_zone = IsGlobalZone(); if (global_zone) { int res = ZLoadProcesstable(pidlist, rootpidlist); if (res == false) { Log(LOG_LEVEL_ERR, "Unable to load solaris zone process table."); return false; } } # endif ARG_UNUSED bool header = true; /* used only if HAVE_GETZONEID */ for (;;) { ssize_t res = CfReadLine(&vbuff, &vbuff_size, prp); if (res == -1) { if (!feof(prp)) { Log(LOG_LEVEL_ERR, "Unable to read process list with command '%s'. (fread: %s)", pscomm, GetErrorStr()); cf_pclose(prp); free(vbuff); return false; } else { break; } } Chop(vbuff, vbuff_size); # ifdef HAVE_GETZONEID if (global_zone) { if (header) { /* this is the banner so get the column header names for later use*/ GetProcessColumnNames(vbuff, &names[0], start, end); } else { int gpid = ExtractPid(vbuff, names, end); if (!IsGlobalProcess(gpid, pidlist, rootpidlist)) { continue; } } } # endif AppendItem(&PROCESSTABLE, vbuff, ""); header = false; } cf_pclose(prp); /* Now save the data */ const char* const statedir = GetStateDir(); snprintf(vbuff, CF_MAXVARSIZE, "%s%ccf_procs", statedir, FILE_SEPARATOR); RawSaveItemList(PROCESSTABLE, vbuff, NewLineMode_Unix); # ifdef HAVE_GETZONEID if (global_zone) /* pidlist and rootpidlist are empty if we're not in the global zone */ { Item *ip = PROCESSTABLE; while (ip != NULL) { ZCopyProcessList(&rootprocs, ip, rootpidlist, names, end); ip = ip->next; } ReverseItemList(rootprocs); ip = PROCESSTABLE; while (ip != NULL) { ZCopyProcessList(&otherprocs, ip, pidlist, names, end); ip = ip->next; } ReverseItemList(otherprocs); } else # endif { CopyList(&rootprocs, PROCESSTABLE); CopyList(&otherprocs, PROCESSTABLE); while (DeleteItemNotContaining(&rootprocs, "root")) { } while (DeleteItemContaining(&otherprocs, "root")) { } } if (otherprocs) { PrependItem(&rootprocs, otherprocs->name, NULL); } snprintf(vbuff, CF_MAXVARSIZE, "%s%ccf_rootprocs", statedir, FILE_SEPARATOR); RawSaveItemList(rootprocs, vbuff, NewLineMode_Unix); DeleteItemList(rootprocs); snprintf(vbuff, CF_MAXVARSIZE, "%s%ccf_otherprocs", statedir, FILE_SEPARATOR); RawSaveItemList(otherprocs, vbuff, NewLineMode_Unix); DeleteItemList(otherprocs); free(vbuff); return true; }
/* Load processes using zone-aware ps * to obtain solaris list of global * process ids for root and non-root * users to lookup later */ int ZLoadProcesstable(Seq *pidlist, Seq *rootpidlist) { char *names[CF_PROCCOLS]; int start[CF_PROCCOLS]; int end[CF_PROCCOLS]; const char *pscmd = "/usr/bin/ps -Aleo zone,user,pid"; FILE *psf = cf_popen(pscmd, "r", false); if (psf == NULL) { Log(LOG_LEVEL_ERR, "ZLoadProcesstable: Couldn't open the process list with command %s.", pscmd); return false; } size_t pbuff_size = CF_BUFSIZE; char *pbuff = xmalloc(pbuff_size); bool header = true; while (true) { ssize_t res = CfReadLine(&pbuff, &pbuff_size, psf); if (res == -1) { if (!feof(psf)) { Log(LOG_LEVEL_ERR, "IsGlobalProcess(char **, int): Unable to read process list with command '%s'. (fread: %s)", pscmd, GetErrorStr()); cf_pclose(psf); free(pbuff); return false; } else { break; } } Chop(pbuff, pbuff_size); if (header) /* This line is the header. */ { GetProcessColumnNames(pbuff, &names[0], start, end); } else { int pid = ExtractPid(pbuff, &names[0], end); size_t zone_offset = strspn(pbuff, " "); size_t zone_end_offset = strcspn(pbuff + zone_offset, " ") + zone_offset; size_t user_offset = strspn(pbuff + zone_end_offset, " ") + zone_end_offset; size_t user_end_offset = strcspn(pbuff + user_offset, " ") + user_offset; bool is_global = (zone_end_offset - zone_offset == 6 && strncmp(pbuff + zone_offset, "global", 6) == 0); bool is_root = (user_end_offset - user_offset == 4 && strncmp(pbuff + user_offset, "root", 4) == 0); if (is_global && is_root) { SeqAppend(rootpidlist, (void*)(intptr_t)pid); } else if (is_global && !is_root) { SeqAppend(pidlist, (void*)(intptr_t)pid); } } header = false; } cf_pclose(psf); free(pbuff); return true; }
static int FindPidMatches(Item *procdata, Item **killlist, Attributes a, Promise *pp) { Item *ip; int pid = -1, matches = 0, i, s, e, promised_zero; pid_t cfengine_pid = getpid(); char *names[CF_PROCCOLS]; /* ps headers */ int start[CF_PROCCOLS]; int end[CF_PROCCOLS]; if (procdata == NULL) { return 0; } GetProcessColumnNames(procdata->name, (char **) names, start, end); for (ip = procdata->next; ip != NULL; ip = ip->next) { CF_OCCUR++; if (BlockTextMatch(pp->promiser, ip->name, &s, &e)) { if (NULL_OR_EMPTY(ip->name)) { continue; } if (!SelectProcess(ip->name, names, start, end, a, pp)) { continue; } pid = ExtractPid(ip->name, names, start, end); if (pid == -1) { CfOut(cf_verbose, "", "Unable to extract pid while looking for %s\n", pp->promiser); continue; } CfOut(cf_verbose, "", " -> Found matching pid %d\n (%s)", pid, ip->name); matches++; if (pid == 1) { if ((RlistLen(a.signals) == 1) && IsStringIn(a.signals, "hup")) { CfOut(cf_verbose, "", "(Okay to send only HUP to init)\n"); } else { continue; } } if (pid < 4 && a.signals) { CfOut(cf_verbose, "", "Will not signal or restart processes 0,1,2,3 (occurred while looking for %s)\n", pp->promiser); continue; } promised_zero = a.process_count.min_range == 0 && a.process_count.max_range == 0; if (a.transaction.action == cfa_warn && promised_zero) { CfOut(cf_error, "", "Process alert: %s\n", procdata->name); /* legend */ CfOut(cf_error, "", "Process alert: %s\n", ip->name); continue; } if (pid == cfengine_pid && a.signals) { CfOut(cf_verbose, "", " !! cf-agent will not signal itself!\n"); continue; } PrependItem(killlist, ip->name, ""); (*killlist)->counter = pid; } } // Free up allocated memory for (i = 0; i < CF_PROCCOLS; i++) { if (names[i] != NULL) { free(names[i]); } } return matches; }