static int SelectExecRegexMatch(char *filename, char *crit, char *prog) { char line[CF_BUFSIZE]; FILE *pp; char buf[CF_MAXVARSIZE]; // insert real value of $(this.promiser) in command ReplaceStr(prog, buf, sizeof(buf), "$(this.promiser)", filename); ReplaceStr(prog, buf, sizeof(buf), "${this.promiser}", filename); if ((pp = cf_popen(buf, "r")) == NULL) { CfOut(cf_error, "cf_popen", "Couldn't open pipe to command %s\n", buf); return false; } while (!feof(pp)) { line[0] = '\0'; CfReadLine(line, CF_BUFSIZE, pp); /* One buffer only */ if (FullTextMatch(crit, line)) { cf_pclose(pp); return true; } } cf_pclose(pp); return false; }
int VerifyMount(char *name, Attributes a, Promise *pp) { char comm[CF_BUFSIZE], line[CF_BUFSIZE]; FILE *pfp; char *host, *rmountpt, *mountpt; host = a.mount.mount_server; rmountpt = a.mount.mount_source; mountpt = name; if (!DONTDO) { snprintf(comm, CF_BUFSIZE, "%s %s:%s %s", GetArg0(VMOUNTCOMM[VSYSTEMHARDCLASS]), host, rmountpt, mountpt); if ((pfp = cf_popen(comm, "r")) == NULL) { CfOut(cf_error, "", " !! Failed to open pipe from %s\n", GetArg0(VMOUNTCOMM[VSYSTEMHARDCLASS])); return 0; } CfReadLine(line, CF_BUFSIZE, pfp); if (strstr(line, "busy") || strstr(line, "Busy")) { cfPS(cf_inform, CF_INTERPT, "", pp, a, " !! The device under %s cannot be mounted\n", mountpt); cf_pclose(pfp); return 1; } cf_pclose(pfp); } cfPS(cf_inform, CF_CHG, "", pp, a, " -> Mounting %s to keep promise\n", mountpt); return 0; }
int VerifyUnmount(char *name, Attributes a, Promise *pp) { char comm[CF_BUFSIZE], line[CF_BUFSIZE]; FILE *pfp; char *mountpt; mountpt = name; if (!DONTDO) { snprintf(comm, CF_BUFSIZE, "%s %s", VUNMOUNTCOMM[VSYSTEMHARDCLASS], mountpt); if ((pfp = cf_popen(comm, "r")) == NULL) { CfOut(cf_error, "", " !! Failed to open pipe from %s\n", VUNMOUNTCOMM[VSYSTEMHARDCLASS]); return 0; } CfReadLine(line, CF_BUFSIZE, pfp); if ((strstr(line, "busy")) || (strstr(line, "Busy"))) { cfPS(cf_inform, CF_INTERPT, "", pp, a, " !! The device under %s cannot be unmounted\n", mountpt); cf_pclose(pfp); return 1; } cf_pclose(pfp); } cfPS(cf_inform, CF_CHG, "", pp, a, " -> Unmounting %s to keep promise\n", mountpt); return 0; }
int VerifyMount(EvalContext *ctx, char *name, Attributes a, Promise *pp) { char comm[CF_BUFSIZE], line[CF_BUFSIZE]; FILE *pfp; char *host, *rmountpt, *mountpt, *opts=NULL; host = a.mount.mount_server; rmountpt = a.mount.mount_source; mountpt = name; /* Check for options required for this mount - i.e., -o ro,rsize, etc. */ if (a.mount.mount_options) { opts = Rlist2String(a.mount.mount_options, ","); } else { opts = xstrdup(VMOUNTOPTS[VSYSTEMHARDCLASS]); } if (!DONTDO) { snprintf(comm, CF_BUFSIZE, "%s -o %s %s:%s %s", CommandArg0(VMOUNTCOMM[VSYSTEMHARDCLASS]), opts, host, rmountpt, mountpt); if ((pfp = cf_popen(comm, "r", true)) == NULL) { Log(LOG_LEVEL_ERR, "Failed to open pipe from %s", CommandArg0(VMOUNTCOMM[VSYSTEMHARDCLASS])); return 0; } ssize_t res = CfReadLine(line, CF_BUFSIZE, pfp); if (res == -1) { Log(LOG_LEVEL_ERR, "Unable to read output of mount command. (fread: %s)", GetErrorStr()); cf_pclose(pfp); return 0; } if (res != 0 && ((strstr(line, "busy")) || (strstr(line, "Busy")))) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_INTERRUPTED, pp, a, "The device under %s cannot be mounted\n", mountpt); cf_pclose(pfp); return 1; } cf_pclose(pfp); } /* Since opts is either Rlist2String or xstrdup'd, we need to always free it */ free(opts); cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Mounting %s to keep promise\n", mountpt); return 0; }
int VerifyMount(char *name, Attributes a, Promise *pp) { char comm[CF_BUFSIZE], line[CF_BUFSIZE]; FILE *pfp; char *host, *rmountpt, *mountpt, *opts=NULL; host = a.mount.mount_server; rmountpt = a.mount.mount_source; mountpt = name; /* Check for options required for this mount - i.e., -o ro,rsize, etc. */ if (a.mount.mount_options) { opts = Rlist2String(a.mount.mount_options, ","); } else { opts = xstrdup(VMOUNTOPTS[VSYSTEMHARDCLASS]); } if (!DONTDO) { snprintf(comm, CF_BUFSIZE, "%s -o %s %s:%s %s", GetArg0(VMOUNTCOMM[VSYSTEMHARDCLASS]), opts, host, rmountpt, mountpt); if ((pfp = cf_popen(comm, "r")) == NULL) { CfOut(cf_error, "", " !! Failed to open pipe from %s\n", GetArg0(VMOUNTCOMM[VSYSTEMHARDCLASS])); return 0; } if (CfReadLine(line, CF_BUFSIZE, pfp) == -1) { FatalError("Error in CfReadLine"); } if ((strstr(line, "busy")) || (strstr(line, "Busy"))) { cfPS(cf_inform, CF_INTERPT, "", pp, a, " !! The device under %s cannot be mounted\n", mountpt); cf_pclose(pfp); return 1; } cf_pclose(pfp); } /* Since opts is either Rlist2String or xstrdup'd, we need to always free it */ free(opts); cfPS(cf_inform, CF_CHG, "", pp, a, " -> Mounting %s to keep promise\n", mountpt); return 0; }
PromiseResult VerifyUnmount(EvalContext *ctx, char *name, const Attributes *a, const Promise *pp) { char comm[CF_BUFSIZE]; FILE *pfp; char *mountpt; mountpt = name; PromiseResult result = PROMISE_RESULT_NOOP; if (!DONTDO) { snprintf(comm, CF_BUFSIZE, "%s %s", VUNMOUNTCOMM[VSYSTEMHARDCLASS], mountpt); if ((pfp = cf_popen(comm, "r", true)) == NULL) { Log(LOG_LEVEL_ERR, "Failed to open pipe from %s", VUNMOUNTCOMM[VSYSTEMHARDCLASS]); return result; } size_t line_size = CF_BUFSIZE; char *line = xmalloc(line_size); ssize_t res = CfReadLine(&line, &line_size, pfp); if (res == -1) { cf_pclose(pfp); free(line); if (!feof(pfp)) { Log(LOG_LEVEL_ERR, "Unable to read output of unmount command. (fread: %s)", GetErrorStr()); return result; } } else if (res > 0 && ((strstr(line, "busy")) || (strstr(line, "Busy")))) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_INTERRUPTED, pp, a, "The device under '%s' cannot be unmounted", mountpt); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); cf_pclose(pfp); free(line); return result; } } cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Unmounting '%s' to keep promise", mountpt); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); return result; }
static bool SelectExecRegexMatch(EvalContext *ctx, char *filename, char *crit, char *prog) { // insert real value of $(this.promiser) in command char *buf_tmp = SearchAndReplace(prog, "$(this.promiser)", filename); char *buf = SearchAndReplace(buf_tmp, "${this.promiser}", filename); free(buf_tmp); FILE *pp = cf_popen(buf, "r", true); if (pp == NULL) { Log(LOG_LEVEL_ERR, "Couldn't open pipe to command '%s'. (cf_popen: %s)", buf, GetErrorStr()); free(buf); return false; } size_t line_size = CF_BUFSIZE; char *line = xmalloc(line_size); for (;;) { ssize_t res = CfReadLine(&line, &line_size, pp); if (res == -1) { if (!feof(pp)) { Log(LOG_LEVEL_ERR, "Error reading output from command '%s'. (fgets: %s)", buf, GetErrorStr()); } cf_pclose(pp); free(line); free(buf); return false; } if (FullTextMatch(ctx, crit, line)) { cf_pclose(pp); free(line); free(buf); return true; } } cf_pclose(pp); free(line); free(buf); return false; }
static VersionCmpResult RunCmpCommand(const char *command, const char *v1, const char *v2, Attributes a, Promise *pp) { char expanded_command[CF_EXPANDSIZE]; SetNewScope("cf_pack_context"); NewScalar("cf_pack_context", "v1", v1, cf_str); NewScalar("cf_pack_context", "v2", v2, cf_str); ExpandScalar(command, expanded_command); DeleteScope("cf_pack_context"); FILE *pfp = a.packages.package_commands_useshell ? cf_popen_sh(expanded_command, "w") : cf_popen(expanded_command, "w"); if (pfp == NULL) { cfPS(cf_error, CF_FAIL, "cf_popen", pp, a, "Can not start package version comparison command: %s", expanded_command); return VERCMP_ERROR; } CfOut(cf_verbose, "", "Executing %s", expanded_command); int retcode = cf_pclose(pfp); if (retcode == -1) { cfPS(cf_error, CF_FAIL, "cf_pclose", pp, a, "Error during package version comparison command execution: %s", expanded_command); return VERCMP_ERROR; } return retcode == 0; }
void MonNetworkSnifferOpen(void) { char tcpbuffer[CF_BUFSIZE]; if (TCPDUMP) { struct stat statbuf; char buffer[CF_MAXVARSIZE]; sscanf(CF_TCPDUMP_COMM, "%s", buffer); if (stat(buffer, &statbuf) != -1) { if ((TCPPIPE = cf_popen(CF_TCPDUMP_COMM, "r", true)) == NULL) { TCPDUMP = false; } /* Skip first banner */ if (fgets(tcpbuffer, sizeof(tcpbuffer), TCPPIPE) == NULL) { UnexpectedError("Failed to read output from '%s'", CF_TCPDUMP_COMM); cf_pclose(TCPPIPE); TCPPIPE = NULL; TCPDUMP = false; } } else { TCPDUMP = false; } } }
static bool SupportsOption(const char *cmd, const char *option) { bool supports_option = false; char help_argument[] = " --help"; char help_command[strlen(cmd) + sizeof(help_argument)]; xsnprintf(help_command, sizeof(help_command), "%s%s", cmd, help_argument); FILE *fptr = cf_popen(help_command, "r", true); char *buf = NULL; size_t bufsize = 0; size_t optlen = strlen(option); while (CfReadLine(&buf, &bufsize, fptr) >= 0) { char *m_pos = buf; while ((m_pos = strstr(m_pos, option))) { // Check against false alarms, e.g. hyphenated words in normal text or an // option (say, "-M") that is part of "--M". if ((m_pos == buf || (m_pos[-1] != '-' && (isspace(m_pos[-1]) || ispunct(m_pos[-1])))) && (m_pos[optlen] == '\0' || (isspace(m_pos[optlen]) || ispunct(m_pos[optlen])))) { supports_option = true; // Break out of strstr loop, but read till the end to avoid broken pipes. break; } m_pos++; } } cf_pclose(fptr); free(buf); return supports_option; }
static bool SelectExecRegexMatch(EvalContext *ctx, char *filename, char *crit, char *prog) { char line[CF_BUFSIZE]; FILE *pp; char buf[CF_MAXVARSIZE]; // insert real value of $(this.promiser) in command ReplaceStr(prog, buf, sizeof(buf), "$(this.promiser)", filename); ReplaceStr(prog, buf, sizeof(buf), "${this.promiser}", filename); if ((pp = cf_popen(buf, "r", true)) == NULL) { Log(LOG_LEVEL_ERR, "Couldn't open pipe to command '%s'. (cf_popen: %s)", buf, GetErrorStr()); return false; } for (;;) { ssize_t res = CfReadLine(line, CF_BUFSIZE, pp); if (res == -1) { Log(LOG_LEVEL_ERR, "Error reading output from command '%s'. (fgets: %s)", buf, GetErrorStr()); cf_pclose(pp); return false; } if (res == 0) { cf_pclose(pp); return false; } if (FullTextMatch(ctx, crit, line)) { cf_pclose(pp); return true; } } cf_pclose(pp); return false; }
static bool ChangePasswordHashUsingChpasswd(const char *puser, const char *password) { int status; const char *cmd_str = CHPASSWD " -e"; Log(LOG_LEVEL_VERBOSE, "Changing password hash for user '%s'. (command: '%s')", puser, cmd_str); FILE *cmd = cf_popen_sh(cmd_str, "w"); if (!cmd) { Log(LOG_LEVEL_ERR, "Could not launch password changing command '%s': %s.", cmd_str, GetErrorStr()); return false; } // String lengths plus a ':' and a '\n', but not including '\0'. size_t total_len = strlen(puser) + strlen(password) + 2; char change_string[total_len + 1]; xsnprintf(change_string, total_len + 1, "%s:%s\n", puser, password); clearerr(cmd); if (fwrite(change_string, total_len, 1, cmd) != 1) { const char *error_str; if (ferror(cmd)) { error_str = GetErrorStr(); } else { error_str = "Unknown error"; } Log(LOG_LEVEL_ERR, "Could not write password to password changing command '%s': %s.", cmd_str, error_str); cf_pclose(cmd); return false; } status = cf_pclose(cmd); if (status) { Log(LOG_LEVEL_ERR, "'%s' returned non-zero status: %i\n", cmd_str, status); return false; } return true; }
int VerifyUnmount(EvalContext *ctx, char *name, Attributes a, Promise *pp) { char comm[CF_BUFSIZE], line[CF_BUFSIZE]; FILE *pfp; char *mountpt; mountpt = name; if (!DONTDO) { snprintf(comm, CF_BUFSIZE, "%s %s", VUNMOUNTCOMM[VSYSTEMHARDCLASS], mountpt); if ((pfp = cf_popen(comm, "r", true)) == NULL) { Log(LOG_LEVEL_ERR, "Failed to open pipe from %s", VUNMOUNTCOMM[VSYSTEMHARDCLASS]); return 0; } ssize_t res = CfReadLine(line, CF_BUFSIZE, pfp); if (res == -1) { Log(LOG_LEVEL_ERR, "Unable to read output of unmount command. (fread: %s)", GetErrorStr()); cf_pclose(pfp); return 0; } if (res != 0 && ((strstr(line, "busy")) || (strstr(line, "Busy")))) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_INTERRUPTED, pp, a, "The device under %s cannot be unmounted\n", mountpt); cf_pclose(pfp); return 1; } cf_pclose(pfp); } cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Unmounting %s to keep promise\n", mountpt); return 0; }
static void MD5Random(unsigned char digest[EVP_MAX_MD_SIZE + 1]) /* Make a decent random number by crunching some system states & garbage through MD5. We can use this as a seed for pseudo random generator */ { unsigned char buffer[CF_BUFSIZE]; char pscomm[CF_BUFSIZE]; char uninitbuffer[100]; int md_len; const EVP_MD *md; EVP_MD_CTX context; FILE *pp; CfOut(cf_verbose, "", "Looking for a random number seed...\n"); #ifdef HAVE_NOVA md = EVP_get_digestbyname("sha256"); #else md = EVP_get_digestbyname("md5"); #endif EVP_DigestInit(&context, md); CfOut(cf_verbose, "", "...\n"); snprintf(buffer, CF_BUFSIZE, "%d%d%25s", (int) CFSTARTTIME, (int) *digest, VFQNAME); EVP_DigestUpdate(&context, buffer, CF_BUFSIZE); snprintf(pscomm, CF_BUFSIZE, "%s %s", VPSCOMM[VSYSTEMHARDCLASS], VPSOPTS[VSYSTEMHARDCLASS]); if ((pp = cf_popen(pscomm, "r")) != NULL) { CfOut(cf_error, "cf_popen", "Couldn't open the process list with command %s\n", pscomm); while (!feof(pp)) { CfReadLine(buffer, CF_BUFSIZE, pp); EVP_DigestUpdate(&context, buffer, CF_BUFSIZE); } } uninitbuffer[99] = '\0'; snprintf(buffer, CF_BUFSIZE - 1, "%ld %s", time(NULL), uninitbuffer); EVP_DigestUpdate(&context, buffer, CF_BUFSIZE); cf_pclose(pp); EVP_DigestFinal(&context, digest, &md_len); }
static VersionCmpResult RunCmpCommand(EvalContext *ctx, const char *command, const char *v1, const char *v2, Attributes a, const Promise *pp, PromiseResult *result) { Buffer *expanded_command = BufferNew(); { VarRef *ref_v1 = VarRefParseFromScope("v1", PACKAGES_CONTEXT); EvalContextVariablePut(ctx, ref_v1, v1, CF_DATA_TYPE_STRING, "source=promise"); VarRef *ref_v2 = VarRefParseFromScope("v2", PACKAGES_CONTEXT); EvalContextVariablePut(ctx, ref_v2, v2, CF_DATA_TYPE_STRING, "source=promise"); ExpandScalar(ctx, NULL, PACKAGES_CONTEXT, command, expanded_command); EvalContextVariableRemove(ctx, ref_v1); VarRefDestroy(ref_v1); EvalContextVariableRemove(ctx, ref_v2); VarRefDestroy(ref_v2); } FILE *pfp = a.packages.package_commands_useshell ? cf_popen_sh(BufferData(expanded_command), "w") : cf_popen(BufferData(expanded_command), "w", true); if (pfp == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Can not start package version comparison command '%s'. (cf_popen: %s)", BufferData(expanded_command), GetErrorStr()); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); BufferDestroy(expanded_command); return VERCMP_ERROR; } Log(LOG_LEVEL_VERBOSE, "Executing '%s'", BufferData(expanded_command)); int retcode = cf_pclose(pfp); if (retcode == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Error during package version comparison command execution '%s'. (cf_pclose: %s)", BufferData(expanded_command), GetErrorStr()); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); BufferDestroy(expanded_command); return VERCMP_ERROR; } BufferDestroy(expanded_command); return retcode == 0; }
static void Sniff(Item *ip_addresses, long iteration, double *cf_this) { char tcpbuffer[CF_BUFSIZE]; Log(LOG_LEVEL_VERBOSE, "Reading from tcpdump..."); memset(tcpbuffer, 0, CF_BUFSIZE); signal(SIGALRM, CfenvTimeOut); alarm(SLEEPTIME); TCPPAUSE = false; while (!feof(TCPPIPE) && !IsPendingTermination()) { if (TCPPAUSE) { break; } if (fgets(tcpbuffer, sizeof(tcpbuffer), TCPPIPE) == NULL) { UnexpectedError("Unable to read data from tcpdump; closing pipe"); cf_pclose(TCPPIPE); TCPPIPE = NULL; TCPDUMP = false; break; } if (TCPPAUSE) { break; } if (strstr(tcpbuffer, "tcpdump:")) /* Error message protect sleeptime */ { Log(LOG_LEVEL_DEBUG, "Error - '%s'", tcpbuffer); alarm(0); TCPDUMP = false; break; } AnalyzeArrival(ip_addresses, iteration, tcpbuffer, cf_this); } signal(SIGALRM, SIG_DFL); TCPPAUSE = false; fflush(TCPPIPE); }
static int Unix_GatherProcessUsers(struct Item **userList, int *userListSz, int *numRootProcs, int *numOtherProcs) { FILE *pp; char pscomm[CF_BUFSIZE]; char user[CF_MAXVARSIZE]; char vbuff[CF_BUFSIZE]; snprintf(pscomm,CF_BUFSIZE,"%s %s",VPSCOMM[VSYSTEMHARDCLASS],VPSOPTS[VSYSTEMHARDCLASS]); if ((pp = cf_popen(pscomm,"r")) == NULL) { return false; } CfReadLine(vbuff,CF_BUFSIZE,pp); while (!feof(pp)) { CfReadLine(vbuff,CF_BUFSIZE,pp); sscanf(vbuff,"%s",user); if (strcmp(user,"USER") == 0) { continue; } if (!IsItemIn(*userList,user)) { PrependItem(userList,user,NULL); (*userListSz)++; } if (strcmp(user,"root") == 0) { (*numRootProcs)++; } else { (*numOtherProcs)++; } } cf_pclose(pp); return true; }
static VersionCmpResult RunCmpCommand(EvalContext *ctx, const char *command, const char *v1, const char *v2, Attributes a, Promise *pp) { char expanded_command[CF_EXPANDSIZE]; { VarRef *ref_v1 = VarRefParseFromScope("v1", "cf_pack_context"); EvalContextVariablePut(ctx, ref_v1, (Rval) { v1, RVAL_TYPE_SCALAR }, DATA_TYPE_STRING); VarRef *ref_v2 = VarRefParseFromScope("v2", "cf_pack_context"); EvalContextVariablePut(ctx, ref_v2, (Rval) { v2, RVAL_TYPE_SCALAR }, DATA_TYPE_STRING); ExpandScalar(ctx, NULL, "cf_pack_context", command, expanded_command); EvalContextVariableRemove(ctx, ref_v1); VarRefDestroy(ref_v1); EvalContextVariableRemove(ctx, ref_v2); VarRefDestroy(ref_v2); } FILE *pfp = a.packages.package_commands_useshell ? cf_popen_sh(expanded_command, "w") : cf_popen(expanded_command, "w", true); if (pfp == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Can not start package version comparison command '%s'. (cf_popen: %s)", expanded_command, GetErrorStr()); return VERCMP_ERROR; } Log(LOG_LEVEL_VERBOSE, "Executing '%s'", expanded_command); int retcode = cf_pclose(pfp); if (retcode == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Error during package version comparison command execution '%s'. (cf_pclose: %s)", expanded_command, GetErrorStr()); return VERCMP_ERROR; } return retcode == 0; }
static void LoadPlatformExtraTable(void) { if (UCB_PS_MAP) { return; } UCB_PS_MAP = StringMapNew(); FILE *cmd = OpenUcbPsPipe(); if (!cmd) { return; } ReadFromUcbPsPipe(cmd); if (cf_pclose(cmd) != 0) { Log(LOG_LEVEL_WARNING, "Command returned non-zero while gathering " "extra process information."); // Make an empty map, in this case. The information can't be trusted. StringMapClear(UCB_PS_MAP); } }
void MountAll() { char line[CF_BUFSIZE]; FILE *pp; if (DONTDO) { CfOut(cf_verbose, "", "Promised to mount filesystem, but not on this trial run\n"); return; } else { CfOut(cf_verbose, "", " -> Attempting to mount all filesystems.\n"); } #if defined(__CYGWIN__) /* This is a shell script. Make sure it hasn't been compromised. */ struct stat sb; if (cfstat("/etc/fstab", &sb) == -1) { int fd; if ((fd = creat("/etc/fstab", 0755)) > 0) { if (write(fd, "#!/bin/sh\n\n", 10) != 10) { UnexpectedError("Failed to write to file '/etc/fstab'"); } close(fd); } else { if (sb.st_mode & (S_IWOTH | S_IWGRP)) { CfOut(cf_error, "", "File /etc/fstab was insecure. Cannot mount filesystems.\n"); return; } } } #endif SetTimeOut(RPCTIMEOUT); if ((pp = cf_popen(VMOUNTCOMM[VSYSTEMHARDCLASS], "r")) == NULL) { CfOut(cf_error, "cf_popen", "Failed to open pipe from %s\n", VMOUNTCOMM[VSYSTEMHARDCLASS]); return; } while (!feof(pp)) { if (ferror(pp)) /* abortable */ { CfOut(cf_inform, "ferror", "Error mounting filesystems\n"); break; } if (CfReadLine(line, CF_BUFSIZE, pp) == -1) { FatalError("Error in CfReadLine"); } if (ferror(pp)) /* abortable */ { CfOut(cf_inform, "ferror", "Error mounting filesystems\n"); break; } if ((strstr(line, "already mounted")) || (strstr(line, "exceeded")) || (strstr(line, "determined"))) { continue; } if (strstr(line, "not supported")) { continue; } if ((strstr(line, "denied")) || (strstr(line, "RPC"))) { CfOut(cf_error, "", "There was a mount error, trying to mount one of the filesystems on this host.\n"); break; } if ((strstr(line, "trying")) && (!strstr(line, "NFS version 2")) && (!strstr(line, "vers 3"))) { CfOut(cf_error, "", "Attempting abort because mount went into a retry loop.\n"); break; } } alarm(0); signal(SIGALRM, SIG_DFL); cf_pclose(pp); }
void MonNetworkGatherData(double *cf_this) { FILE *pp; char local[CF_BUFSIZE], remote[CF_BUFSIZE], comm[CF_BUFSIZE]; Item *in[ATTR], *out[ATTR]; char *sp; int i; char vbuff[CF_BUFSIZE]; enum cf_netstat_type { cfn_new, cfn_old } type = cfn_new; enum cf_packet_type { cfn_tcp4, cfn_tcp6 } packet = cfn_tcp4; CfDebug("GatherSocketData()\n"); for (i = 0; i < ATTR; i++) { in[i] = out[i] = NULL; } DeleteItemList(ALL_INCOMING); ALL_INCOMING = NULL; sscanf(VNETSTAT[VSYSTEMHARDCLASS], "%s", comm); strcat(comm, " -an"); if ((pp = cf_popen(comm, "r")) == NULL) { return; } while (!feof(pp)) { memset(local, 0, CF_BUFSIZE); memset(remote, 0, CF_BUFSIZE); CfReadLine(vbuff, CF_BUFSIZE, pp); if (strstr(vbuff, "UNIX")) { break; } if (!(strstr(vbuff, ":") || strstr(vbuff, "."))) { continue; } /* Different formats here ... ugh.. pick a model */ // If this is old style, we look for chapter headings, e.g. "TCP: IPv4" if (strncmp(vbuff,"TCP:",4) == 0 && strstr(vbuff+4,"6")) { packet = cfn_tcp6; type = cfn_old; continue; } else if (strncmp(vbuff,"TCP:",4) == 0 && strstr(vbuff+4,"4")) { packet = cfn_tcp4; type = cfn_old; continue; } // Line by line state in modern/linux output if (strncmp(vbuff,"tcp6",4) == 0) { packet = cfn_tcp6; type = cfn_new; } else if (strncmp(vbuff,"tcp",3) == 0) { packet = cfn_tcp4; type = cfn_new; } // End extract type switch (type) { case cfn_new: sscanf(vbuff, "%*s %*s %*s %s %s", local, remote); /* linux-like */ break; case cfn_old: sscanf(vbuff, "%s %s", local, remote); break; } if (strlen(local) == 0) { continue; } // Extract the port number from the end of the string for (sp = local + strlen(local); (*sp != '.') && (*sp != ':') && (sp > local); sp--) { } *sp = '\0'; // Separate address from port number sp++; if (strstr(vbuff, "LISTEN")) { // General bucket IdempPrependItem(&ALL_INCOMING, sp, NULL); // Categories the incoming ports by packet types switch (packet) { case cfn_tcp4: IdempPrependItem(&MON_TCP4, sp, local); break; case cfn_tcp6: IdempPrependItem(&MON_TCP6, sp, local); break; default: break; } } // Now look at outgoing for (sp = remote + strlen(remote); (sp >= remote) && !isdigit((int) *sp); sp--) { } sp++; // Now look for the specific vital signs to count frequencies for (i = 0; i < ATTR; i++) { char *spend; for (spend = local + strlen(local) - 1; isdigit((int) *spend); spend--) { } spend++; if (strcmp(spend, ECGSOCKS[i].portnr) == 0) { cf_this[ECGSOCKS[i].in]++; AppendItem(&in[i], vbuff, ""); } for (spend = remote + strlen(remote) - 1; (sp >= remote) && isdigit((int) *spend); spend--) { } spend++; if (strcmp(spend, ECGSOCKS[i].portnr) == 0) { cf_this[ECGSOCKS[i].out]++; AppendItem(&out[i], vbuff, ""); } } } cf_pclose(pp); /* Now save the state for ShowState() the state is not smaller than the last or at least 40 minutes older. This mirrors the persistence of the maxima classes */ for (i = 0; i < ATTR; i++) { struct stat statbuf; time_t now = time(NULL); CfDebug("save incoming %s\n", ECGSOCKS[i].name); snprintf(vbuff, CF_MAXVARSIZE, "%s/state/cf_incoming.%s", CFWORKDIR, ECGSOCKS[i].name); if (cfstat(vbuff, &statbuf) != -1) { if ((ByteSizeList(in[i]) < statbuf.st_size) && (now < statbuf.st_mtime + 40 * 60)) { CfOut(cf_verbose, "", "New state %s is smaller, retaining old for 40 mins longer\n", ECGSOCKS[i].name); DeleteItemList(in[i]); continue; } } SetNetworkEntropyClasses(ECGSOCKS[i].name, "in", in[i]); RawSaveItemList(in[i], vbuff); DeleteItemList(in[i]); CfDebug("Saved in netstat data in %s\n", vbuff); } for (i = 0; i < ATTR; i++) { struct stat statbuf; time_t now = time(NULL); CfDebug("save outgoing %s\n", ECGSOCKS[i].name); snprintf(vbuff, CF_MAXVARSIZE, "%s/state/cf_outgoing.%s", CFWORKDIR, ECGSOCKS[i].name); if (cfstat(vbuff, &statbuf) != -1) { if ((ByteSizeList(out[i]) < statbuf.st_size) && (now < statbuf.st_mtime + 40 * 60)) { CfOut(cf_verbose, "", "New state %s is smaller, retaining old for 40 mins longer\n", ECGSOCKS[i].name); DeleteItemList(out[i]); continue; } } SetNetworkEntropyClasses(ECGSOCKS[i].name, "out", out[i]); RawSaveItemList(out[i], vbuff); CfDebug("Saved out netstat data in %s\n", vbuff); DeleteItemList(out[i]); } }
bool GetExecOutput(const char *command, char *buffer, bool useshell) /* Buffer initially contains whole exec string */ { int offset = 0; char line[CF_EXPANDSIZE]; FILE *pp; CfDebug("GetExecOutput(%s,%s) - use shell = %d\n", command, buffer, useshell); if (useshell) { pp = cf_popen_sh(command, "r"); } else { pp = cf_popen(command, "r", true); } if (pp == NULL) { CfOut(OUTPUT_LEVEL_ERROR, "cf_popen", "Couldn't open pipe to command %s\n", command); return false; } memset(buffer, 0, CF_EXPANDSIZE); for (;;) { ssize_t res = CfReadLine(line, CF_EXPANDSIZE, pp); if (res == 0) { break; } if (res == -1) { CfOut(OUTPUT_LEVEL_ERROR, "fread", "Unable to read output of command %s", command); cf_pclose(pp); return false; } if (strlen(line) + offset > CF_EXPANDSIZE - 10) { CfOut(OUTPUT_LEVEL_ERROR, "", "Buffer exceeded %d bytes in exec %s\n", CF_EXPANDSIZE, command); break; } snprintf(buffer + offset, CF_EXPANDSIZE, "%s\n", line); offset += strlen(line) + 1; } if (offset > 0) { if (Chop(buffer, CF_EXPANDSIZE) == -1) { CfOut(OUTPUT_LEVEL_ERROR, "", "Chop was called on a string that seemed to have no terminator"); } } CfDebug("GetExecOutput got: [%s]\n", buffer); cf_pclose(pp); return true; }
int LoadMountInfo(Rlist **list) /* This is, in fact, the most portable way to read the mount info! */ /* Depressing, isn't it? */ { FILE *pp; char buf1[CF_BUFSIZE], buf2[CF_BUFSIZE], buf3[CF_BUFSIZE]; char host[CF_MAXVARSIZE], source[CF_BUFSIZE], mounton[CF_BUFSIZE], vbuff[CF_BUFSIZE]; int i, nfs = false; for (i = 0; VMOUNTCOMM[VSYSTEMHARDCLASS][i] != ' '; i++) { buf1[i] = VMOUNTCOMM[VSYSTEMHARDCLASS][i]; } buf1[i] = '\0'; SetTimeOut(RPCTIMEOUT); if ((pp = cf_popen(buf1, "r")) == NULL) { CfOut(cf_error, "cf_popen", "Can't open %s\n", buf1); return false; } do { vbuff[0] = buf1[0] = buf2[0] = buf3[0] = source[0] = '\0'; if (ferror(pp)) /* abortable */ { CfOut(cf_error, "ferror", "Error getting mount info\n"); break; } CfReadLine(vbuff, CF_BUFSIZE, pp); if (ferror(pp)) /* abortable */ { CfOut(cf_error, "ferror", "Error getting mount info\n"); break; } if (strstr(vbuff, "nfs")) { nfs = true; } sscanf(vbuff, "%s%s%s", buf1, buf2, buf3); if ((vbuff[0] == '\0') || (vbuff[0] == '\n')) { break; } if (strstr(vbuff, "not responding")) { CfOut(cf_error, "", "%s\n", vbuff); } if (strstr(vbuff, "be root")) { CfOut(cf_error, "", "Mount access is denied. You must be root.\n"); CfOut(cf_error, "", "Use the -n option to run safely."); } if ((strstr(vbuff, "retrying")) || (strstr(vbuff, "denied")) || (strstr(vbuff, "backgrounding"))) { continue; } if ((strstr(vbuff, "exceeded")) || (strstr(vbuff, "busy"))) { continue; } if (strstr(vbuff, "RPC")) { CfOut(cf_inform, "", "There was an RPC timeout. Aborting mount operations.\n"); CfOut(cf_inform, "", "Session failed while trying to talk to remote host\n"); CfOut(cf_inform, "", "%s\n", vbuff); cf_pclose(pp); return false; } switch (VSYSTEMHARDCLASS) { case darwin: case linuxx: case unix_sv: case freebsd: case netbsd: case openbsd: case qnx: case crayos: case dragonfly: if (IsAbsoluteFileName(buf1)) { strcpy(host, "localhost"); strcpy(mounton, buf3); } else { sscanf(buf1, "%[^:]:%s", host, source); strcpy(mounton, buf3); } break; case solaris: case hp: if (IsAbsoluteFileName(buf3)) { strcpy(host, "localhost"); strcpy(mounton, buf1); } else { sscanf(buf1, "%[^:]:%s", host, source); strcpy(mounton, buf1); } break; case aix: /* skip header */ if (IsAbsoluteFileName(buf1)) { strcpy(host, "localhost"); strcpy(mounton, buf2); } else { strcpy(host, buf1); strcpy(source, buf1); strcpy(mounton, buf3); } break; case cfnt: strcpy(mounton, buf2); strcpy(host, buf1); break; case cfsco: CfOut(cf_error, "", "Don't understand SCO mount format, no data"); default: printf("cfengine software error: case %d = %s\n", VSYSTEMHARDCLASS, CLASSTEXT[VSYSTEMHARDCLASS]); FatalError("System error in GetMountInfo - no such class!"); } CfDebug("GOT: host=%s, source=%s, mounton=%s\n", host, source, mounton); if (nfs) { AugmentMountInfo(list, host, source, mounton, "nfs"); } else { AugmentMountInfo(list, host, source, mounton, NULL); } } while (!feof(pp)); alarm(0); signal(SIGALRM, SIG_DFL); cf_pclose(pp); return true; }
static bool GetLMSensors(double *cf_this) { FILE *pp; Item *ip, *list = NULL; double temp = 0; char name[CF_BUFSIZE]; int count; cf_this[ob_temp0] = 0.0; cf_this[ob_temp1] = 0.0; cf_this[ob_temp2] = 0.0; cf_this[ob_temp3] = 0.0; if ((pp = cf_popen("/usr/bin/sensors", "r", true)) == NULL) { LMSENSORS = false; /* Broken */ return false; } { size_t vbuff_size = CF_BUFSIZE; char *vbuff = xmalloc(vbuff_size); ssize_t res = CfReadLine(&vbuff, &vbuff_size, pp); if (res <= 0) { /* FIXME: do we need to log anything here? */ cf_pclose(pp); free(vbuff); return false; } for (;;) { ssize_t res = CfReadLine(&vbuff, &vbuff_size, pp); if (res == -1) { if (!feof(pp)) { /* FIXME: Do we need to log anything here? */ cf_pclose(pp); free(vbuff); return false; } else { break; } } if (strstr(vbuff, "Temp") || strstr(vbuff, "temp")) { PrependItem(&list, vbuff, NULL); } } cf_pclose(pp); free(vbuff); } if (ListLen(list) > 0) { Log(LOG_LEVEL_DEBUG, "LM Sensors seemed to return ok data"); } else { return false; } /* lmsensor names are hopelessly inconsistent - so try a few things */ for (ip = list; ip != NULL; ip = ip->next) { for (count = 0; count < 4; count++) { snprintf(name, 16, "CPU%d Temp:", count); if (strncmp(ip->name, name, strlen(name)) == 0) { sscanf(ip->name, "%*[^:]: %lf", &temp); switch (count) { case 0: cf_this[ob_temp0] = temp; break; case 1: cf_this[ob_temp1] = temp; break; case 2: cf_this[ob_temp2] = temp; break; case 3: cf_this[ob_temp3] = temp; break; } Log(LOG_LEVEL_DEBUG, "Set temp%d to %lf from what looks like cpu temperature", count, temp); } } } if (cf_this[ob_temp0] != 0) { /* We got something plausible */ return true; } /* Alternative name Core x: */ for (ip = list; ip != NULL; ip = ip->next) { for (count = 0; count < 4; count++) { snprintf(name, 16, "Core %d:", count); if (strncmp(ip->name, name, strlen(name)) == 0) { sscanf(ip->name, "%*[^:]: %lf", &temp); switch (count) { case 0: cf_this[ob_temp0] = temp; break; case 1: cf_this[ob_temp1] = temp; break; case 2: cf_this[ob_temp2] = temp; break; case 3: cf_this[ob_temp3] = temp; break; } Log(LOG_LEVEL_DEBUG, "Set temp%d to %lf from what looks like core temperatures", count, temp); } } } if (cf_this[ob_temp0] != 0) { /* We got something plausible */ return true; } for (ip = list; ip != NULL; ip = ip->next) { if (strncmp(ip->name, "CPU Temp:", strlen("CPU Temp:")) == 0) { sscanf(ip->name, "%*[^:]: %lf", &temp); Log(LOG_LEVEL_DEBUG, "Setting temp0 to CPU Temp"); cf_this[ob_temp0] = temp; } if (strncmp(ip->name, "M/B Temp:", strlen("M/B Temp:")) == 0) { sscanf(ip->name, "%*[^:]: %lf", &temp); Log(LOG_LEVEL_DEBUG, "Setting temp0 to M/B Temp"); cf_this[ob_temp1] = temp; } if (strncmp(ip->name, "Sys Temp:", strlen("Sys Temp:")) == 0) { sscanf(ip->name, "%*[^:]: %lf", &temp); Log(LOG_LEVEL_DEBUG, "Setting temp0 to Sys Temp"); cf_this[ob_temp2] = temp; } if (strncmp(ip->name, "AUX Temp:", strlen("AUX Temp:")) == 0) { sscanf(ip->name, "%*[^:]: %lf", &temp); Log(LOG_LEVEL_DEBUG, "Setting temp0 to AUX Temp"); cf_this[ob_temp3] = temp; } } if (cf_this[ob_temp0] != 0) { /* We got something plausible */ return true; } /* Alternative name Core x: */ for (ip = list; ip != NULL; ip = ip->next) { for (count = 0; count < 4; count++) { snprintf(name, 16, "temp%d:", count); if (strncmp(ip->name, name, strlen(name)) == 0) { sscanf(ip->name, "%*[^:]: %lf", &temp); switch (count) { case 0: cf_this[ob_temp0] = temp; break; case 1: cf_this[ob_temp1] = temp; break; case 2: cf_this[ob_temp2] = temp; break; case 3: cf_this[ob_temp3] = temp; break; } Log(LOG_LEVEL_DEBUG, "Set temp%d to %lf", count, temp); } } } /* Give up? */ DeleteItemList(list); return true; }
void LocalExec(const ExecConfig *config) { FILE *pp; char line[CF_BUFSIZE], line_escaped[sizeof(line) * 2], filename[CF_BUFSIZE], *sp; char cmd[CF_BUFSIZE], esc_command[CF_BUFSIZE]; int print, count = 0; void *thread_name; time_t starttime = time(NULL); char starttime_str[64]; FILE *fp; char canonified_fq_name[CF_BUFSIZE]; thread_name = ThreadUniqueName(); cf_strtimestamp_local(starttime, starttime_str); CfOut(cf_verbose, "", "------------------------------------------------------------------\n\n"); CfOut(cf_verbose, "", " LocalExec(%sscheduled) at %s\n", config->scheduled_run ? "" : "not ", starttime_str); CfOut(cf_verbose, "", "------------------------------------------------------------------\n"); /* Need to make sure we have LD_LIBRARY_PATH here or children will die */ if (strlen(config->exec_command) > 0) { strncpy(cmd, config->exec_command, CF_BUFSIZE - 1); if (!strstr(cmd, "-Dfrom_cfexecd")) { strcat(cmd, " -Dfrom_cfexecd"); } } else { ConstructFailsafeCommand(config->scheduled_run, cmd); } strncpy(esc_command, MapName(cmd), CF_BUFSIZE - 1); snprintf(line, CF_BUFSIZE - 1, "_%jd_%s", (intmax_t) starttime, CanonifyName(cf_ctime(&starttime))); strlcpy(canonified_fq_name, config->fq_name, CF_BUFSIZE); CanonifyNameInPlace(canonified_fq_name); snprintf(filename, CF_BUFSIZE - 1, "%s/outputs/cf_%s_%s_%p", CFWORKDIR, canonified_fq_name, line, thread_name); MapName(filename); /* What if no more processes? Could sacrifice and exec() - but we need a sentinel */ if ((fp = fopen(filename, "w")) == NULL) { CfOut(cf_error, "fopen", "!! Couldn't open \"%s\" - aborting exec\n", filename); return; } #if !defined(__MINGW32__) /* * Don't inherit this file descriptor on fork/exec */ if (fileno(fp) != -1) { fcntl(fileno(fp), F_SETFD, FD_CLOEXEC); } #endif CfOut(cf_verbose, "", " -> Command => %s\n", cmd); if ((pp = cf_popen_sh(esc_command, "r")) == NULL) { CfOut(cf_error, "cf_popen", "!! Couldn't open pipe to command \"%s\"\n", cmd); fclose(fp); return; } CfOut(cf_verbose, "", " -> Command is executing...%s\n", esc_command); while (!feof(pp)) { if(!IsReadReady(fileno(pp), (config->agent_expireafter * SECONDS_PER_MINUTE))) { char errmsg[CF_MAXVARSIZE]; snprintf(errmsg, sizeof(errmsg), "cf-execd: !! Timeout waiting for output from agent (agent_expireafter=%d) - terminating it", config->agent_expireafter); CfOut(cf_error, "", "%s", errmsg); fprintf(fp, "%s\n", errmsg); count++; pid_t pid_agent; if(PipeToPid(&pid_agent, pp)) { ProcessSignalTerminate(pid_agent); } else { CfOut(cf_error, "", "!! Could not get PID of agent"); } break; } { ssize_t num_read = CfReadLine(line, CF_BUFSIZE, pp); if (num_read == -1) { FatalError("Cannot continue on CfReadLine error"); } else if (num_read == 0) { break; } } if(!CfReadLine(line, CF_BUFSIZE, pp)) { break; } if (ferror(pp)) { fflush(pp); break; } print = false; for (sp = line; *sp != '\0'; sp++) { if (!isspace((int) *sp)) { print = true; break; } } if (print) { // we must escape print format chars (%) from output ReplaceStr(line, line_escaped, sizeof(line_escaped), "%", "%%"); fprintf(fp, "%s\n", line_escaped); count++; /* If we can't send mail, log to syslog */ if (strlen(config->mail_to_address) == 0) { strncat(line_escaped, "\n", sizeof(line_escaped) - 1 - strlen(line_escaped)); if ((strchr(line_escaped, '\n')) == NULL) { line_escaped[sizeof(line_escaped) - 2] = '\n'; } CfOut(cf_inform, "", "%s", line_escaped); } line[0] = '\0'; line_escaped[0] = '\0'; } } cf_pclose(pp); CfDebug("Closing fp\n"); fclose(fp); CfOut(cf_verbose, "", " -> Command is complete\n"); if (count) { CfOut(cf_verbose, "", " -> Mailing result\n"); MailResult(config, filename); } else { CfOut(cf_verbose, "", " -> No output\n"); unlink(filename); } }
int LoadProcessTable(EvalContext *ctx, Item **procdata) { FILE *prp; char pscomm[CF_MAXLINKSIZE], vbuff[CF_BUFSIZE], *sp; Item *rootprocs = NULL; Item *otherprocs = NULL; if (PROCESSTABLE) { Log(LOG_LEVEL_VERBOSE, "Reusing cached process table"); return true; } const char *psopts = GetProcessOptions(); snprintf(pscomm, CF_MAXLINKSIZE, "%s %s", VPSCOMM[VSYSTEMHARDCLASS], 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; } for (;;) { ssize_t res = CfReadLine(vbuff, CF_BUFSIZE, prp); if (res == 0) { break; } if (res == -1) { Log(LOG_LEVEL_ERR, "Unable to read process list with command '%s'. (fread: %s)", pscomm, GetErrorStr()); cf_pclose(prp); return false; } for (sp = vbuff + strlen(vbuff) - 1; (sp > vbuff) && (isspace((int)*sp)); sp--) { *sp = '\0'; } if (ForeignZone(vbuff)) { continue; } AppendItem(procdata, vbuff, ""); } cf_pclose(prp); /* Now save the data */ snprintf(vbuff, CF_MAXVARSIZE, "%s/state/cf_procs", CFWORKDIR); RawSaveItemList(*procdata, vbuff); CopyList(&rootprocs, *procdata); CopyList(&otherprocs, *procdata); while (DeleteItemNotContaining(ctx, &rootprocs, "root")) { } while (DeleteItemContaining(ctx, &otherprocs, "root")) { } if (otherprocs) { PrependItem(&rootprocs, otherprocs->name, NULL); } snprintf(vbuff, CF_MAXVARSIZE, "%s/state/cf_rootprocs", CFWORKDIR); RawSaveItemList(rootprocs, vbuff); DeleteItemList(rootprocs); snprintf(vbuff, CF_MAXVARSIZE, "%s/state/cf_otherprocs", CFWORKDIR); RawSaveItemList(otherprocs, vbuff); DeleteItemList(otherprocs); return true; }
int LoadMountInfo(Rlist **list) /* This is, in fact, the most portable way to read the mount info! */ /* Depressing, isn't it? */ { FILE *pp; char buf1[CF_BUFSIZE], buf2[CF_BUFSIZE], buf3[CF_BUFSIZE]; char host[CF_MAXVARSIZE], source[CF_BUFSIZE], mounton[CF_BUFSIZE], vbuff[CF_BUFSIZE]; int i, nfs = false; for (i = 0; VMOUNTCOMM[VSYSTEMHARDCLASS][i] != ' '; i++) { buf1[i] = VMOUNTCOMM[VSYSTEMHARDCLASS][i]; } buf1[i] = '\0'; SetTimeOut(RPCTIMEOUT); if ((pp = cf_popen(buf1, "r")) == NULL) { CfOut(cf_error, "cf_popen", "Can't open %s\n", buf1); return false; } do { vbuff[0] = buf1[0] = buf2[0] = buf3[0] = source[0] = '\0'; if (ferror(pp)) /* abortable */ { CfOut(cf_error, "ferror", "Error getting mount info\n"); break; } if (CfReadLine(vbuff, CF_BUFSIZE, pp) == -1) { FatalError("Error in CfReadLine"); } if (ferror(pp)) /* abortable */ { CfOut(cf_error, "ferror", "Error getting mount info\n"); break; } if (strstr(vbuff, "nfs")) { nfs = true; } sscanf(vbuff, "%s%s%s", buf1, buf2, buf3); if ((vbuff[0] == '\0') || (vbuff[0] == '\n')) { break; } if (strstr(vbuff, "not responding")) { CfOut(cf_error, "", "%s\n", vbuff); } if (strstr(vbuff, "be root")) { CfOut(cf_error, "", "Mount access is denied. You must be root.\n"); CfOut(cf_error, "", "Use the -n option to run safely."); } if ((strstr(vbuff, "retrying")) || (strstr(vbuff, "denied")) || (strstr(vbuff, "backgrounding"))) { continue; } if ((strstr(vbuff, "exceeded")) || (strstr(vbuff, "busy"))) { continue; } if (strstr(vbuff, "RPC")) { CfOut(cf_inform, "", "There was an RPC timeout. Aborting mount operations.\n"); CfOut(cf_inform, "", "Session failed while trying to talk to remote host\n"); CfOut(cf_inform, "", "%s\n", vbuff); cf_pclose(pp); return false; } #if defined(__sun) || defined(__hpux) if (IsAbsoluteFileName(buf3)) { strcpy(host, "localhost"); strcpy(mounton, buf1); } else { sscanf(buf1, "%[^:]:%s", host, source); strcpy(mounton, buf1); } #elif defined(_AIX) /* skip header */ if (IsAbsoluteFileName(buf1)) { strcpy(host, "localhost"); strcpy(mounton, buf2); } else { strcpy(host, buf1); strcpy(source, buf1); strcpy(mounton, buf3); } #elif defined(__CYGWIN__) strcpy(mounton, buf2); strcpy(host, buf1); #elif defined(sco) || defined(__SCO_DS) CfOut(cf_error, "", "Don't understand SCO mount format, no data"); #else if (IsAbsoluteFileName(buf1)) { strcpy(host, "localhost"); strcpy(mounton, buf3); } else { sscanf(buf1, "%[^:]:%s", host, source); strcpy(mounton, buf3); } #endif CfDebug("GOT: host=%s, source=%s, mounton=%s\n", host, source, mounton); if (nfs) { AugmentMountInfo(list, host, source, mounton, "nfs"); } else { AugmentMountInfo(list, host, source, mounton, NULL); } } while (!feof(pp)); alarm(0); signal(SIGALRM, SIG_DFL); cf_pclose(pp); return true; }
int VerifyNotInFstab(char *name, Attributes a, Promise *pp) /* Ensure filesystem is NOT in fstab, and return no of changes */ { char regex[CF_BUFSIZE]; char *host, *mountpt, *opts; Item *ip; if (!FSTABLIST) { if (!LoadFileAsItemList(&FSTABLIST, VFSTAB[VSYSTEMHARDCLASS], a, pp)) { CfOut(cf_error, "", "Couldn't open %s!\n", VFSTAB[VSYSTEMHARDCLASS]); return false; } else { FSTAB_EDITS = 0; } } if (a.mount.mount_options) { opts = Rlist2String(a.mount.mount_options, ","); } else { opts = xstrdup(VMOUNTOPTS[VSYSTEMHARDCLASS]); } host = a.mount.mount_server; mountpt = name; if (MatchFSInFstab(mountpt)) { if (a.mount.editfstab) { #if defined(_AIX) FILE *pfp; char line[CF_BUFSIZE], aixcomm[CF_BUFSIZE]; snprintf(aixcomm, CF_BUFSIZE, "/usr/sbin/rmnfsmnt -f %s", mountpt); if ((pfp = cf_popen(aixcomm, "r")) == NULL) { cfPS(cf_error, CF_FAIL, "", pp, a, "Failed to invoke /usr/sbin/rmnfsmnt to edit fstab"); return 0; } while (!feof(pfp)) { if (CfReadLine(line, CF_BUFSIZE, pfp) == -1) { FatalError("Error in CfReadLine"); } if (line[0] == '#') { continue; } if (strstr(line, "busy")) { cfPS(cf_inform, CF_INTERPT, "", pp, a, "The device under %s cannot be removed from %s\n", mountpt, VFSTAB[VSYSTEMHARDCLASS]); return 0; } } cf_pclose(pfp); return 0; /* ignore internal editing for aix , always returns 0 changes */ #else snprintf(regex, CF_BUFSIZE, ".*[\\s]+%s[\\s]+.*", mountpt); for (ip = FSTABLIST; ip != NULL; ip = ip->next) { if (FullTextMatch(regex, ip->name)) { cfPS(cf_inform, CF_CHG, "", pp, a, "Deleting file system mounted on %s.\n", host); // Check host name matches too? DeleteThisItem(&FSTABLIST, ip); FSTAB_EDITS++; } } #endif } } if (a.mount.mount_options) { free(opts); } return 0; }
static bool IsReadReady(int fd, int timeout_sec) { fd_set rset; FD_ZERO(&rset); FD_SET(fd, &rset); struct timeval tv = { .tv_sec = timeout_sec, .tv_usec = 0, }; int ret = select(fd + 1, &rset, NULL, NULL, &tv); if(ret < 0) { Log(LOG_LEVEL_ERR, "IsReadReady: Failed checking for data. (select: %s)", GetErrorStr()); return false; } if(FD_ISSET(fd, &rset)) { return true; } if(ret == 0) // timeout { return false; } // can we get here? Log(LOG_LEVEL_ERR, "IsReadReady: Unknown outcome (ret > 0 but our only fd is not set). (select: %s)", GetErrorStr()); return false; } #if defined(__hpux) && defined(__GNUC__) #pragma GCC diagnostic warning "-Wstrict-aliasing" #endif #endif /* __MINGW32__ */ void LocalExec(const ExecConfig *config) { time_t starttime = time(NULL); void *thread_name = ThreadUniqueName(); { char starttime_str[64]; cf_strtimestamp_local(starttime, starttime_str); if (LEGACY_OUTPUT) { Log(LOG_LEVEL_VERBOSE, "------------------------------------------------------------------"); Log(LOG_LEVEL_VERBOSE, " LocalExec(%sscheduled) at %s", config->scheduled_run ? "" : "not ", starttime_str); Log(LOG_LEVEL_VERBOSE, "------------------------------------------------------------------"); } else { Log(LOG_LEVEL_VERBOSE, "LocalExec(%sscheduled) at %s", config->scheduled_run ? "" : "not ", starttime_str); } } /* Need to make sure we have LD_LIBRARY_PATH here or children will die */ char cmd[CF_BUFSIZE]; if (strlen(config->exec_command) > 0) { strncpy(cmd, config->exec_command, CF_BUFSIZE - 1); if (!strstr(cmd, "-Dfrom_cfexecd")) { strcat(cmd, " -Dfrom_cfexecd"); } } else { ConstructFailsafeCommand(config->scheduled_run, cmd); } char esc_command[CF_BUFSIZE]; strncpy(esc_command, MapName(cmd), CF_BUFSIZE - 1); char line[CF_BUFSIZE]; snprintf(line, CF_BUFSIZE - 1, "_%jd_%s", (intmax_t) starttime, CanonifyName(ctime(&starttime))); char filename[CF_BUFSIZE]; { char canonified_fq_name[CF_BUFSIZE]; strlcpy(canonified_fq_name, config->fq_name, CF_BUFSIZE); CanonifyNameInPlace(canonified_fq_name); snprintf(filename, CF_BUFSIZE - 1, "%s/outputs/cf_%s_%s_%p", CFWORKDIR, canonified_fq_name, line, thread_name); MapName(filename); } /* What if no more processes? Could sacrifice and exec() - but we need a sentinel */ FILE *fp = fopen(filename, "w"); if (!fp) { Log(LOG_LEVEL_ERR, "Couldn't open '%s' - aborting exec. (fopen: %s)", filename, GetErrorStr()); return; } #if !defined(__MINGW32__) /* * Don't inherit this file descriptor on fork/exec */ if (fileno(fp) != -1) { fcntl(fileno(fp), F_SETFD, FD_CLOEXEC); } #endif Log(LOG_LEVEL_VERBOSE, "Command => %s", cmd); FILE *pp = cf_popen_sh(esc_command, "r"); if (!pp) { Log(LOG_LEVEL_ERR, "Couldn't open pipe to command '%s'. (cf_popen: %s)", cmd, GetErrorStr()); fclose(fp); return; } Log(LOG_LEVEL_VERBOSE, "Command is executing...%s", esc_command); int count = 0; for (;;) { if(!IsReadReady(fileno(pp), (config->agent_expireafter * SECONDS_PER_MINUTE))) { char errmsg[CF_MAXVARSIZE]; snprintf(errmsg, sizeof(errmsg), "cf-execd: !! Timeout waiting for output from agent (agent_expireafter=%d) - terminating it", config->agent_expireafter); Log(LOG_LEVEL_ERR, "%s", errmsg); fprintf(fp, "%s\n", errmsg); count++; pid_t pid_agent; if(PipeToPid(&pid_agent, pp)) { ProcessSignalTerminate(pid_agent); } else { Log(LOG_LEVEL_ERR, "Could not get PID of agent"); } break; } ssize_t res = CfReadLine(line, CF_BUFSIZE, pp); if (res == 0) { break; } if (res == -1) { Log(LOG_LEVEL_ERR, "Unable to read output from command '%s'. (cfread: %s)", cmd, GetErrorStr()); cf_pclose(pp); return; } bool print = false; for (const char *sp = line; *sp != '\0'; sp++) { if (!isspace((int) *sp)) { print = true; break; } } if (print) { char line_escaped[sizeof(line) * 2]; // we must escape print format chars (%) from output ReplaceStr(line, line_escaped, sizeof(line_escaped), "%", "%%"); fprintf(fp, "%s\n", line_escaped); count++; /* If we can't send mail, log to syslog */ if (strlen(config->mail_to_address) == 0) { strncat(line_escaped, "\n", sizeof(line_escaped) - 1 - strlen(line_escaped)); if ((strchr(line_escaped, '\n')) == NULL) { line_escaped[sizeof(line_escaped) - 2] = '\n'; } Log(LOG_LEVEL_INFO, "%s", line_escaped); } line[0] = '\0'; line_escaped[0] = '\0'; } } cf_pclose(pp); Log(LOG_LEVEL_DEBUG, "Closing fp"); fclose(fp); Log(LOG_LEVEL_VERBOSE, "Command is complete"); if (count) { Log(LOG_LEVEL_VERBOSE, "Mailing result"); MailResult(config, filename); } else { Log(LOG_LEVEL_VERBOSE, "No output"); unlink(filename); } }
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; }