Heitor Ricardo Alves de Siqueira <hal...@linux.vnet.ibm.com> writes: > This commit rewrites some functions in iprconfig that are used to > display log information to the user. We now use standard C code instead > of system() calls and other OS utilities like grep. To view the > requested log info, the less pager is invoked with the environment > variable LESSSECURE set to 1 to prevent arbitrary command execution. > > This commit also introduces a zlib depency to iprutils. This is needed > so that we can seamlessly work with compressed and uncompressed log files.
Thanks for the patch! A few stylish issues below: > diff --git a/iprconfig.c b/iprconfig.c > index fadf562062ea..644ba1de37da 100644 > --- a/iprconfig.c > +++ b/iprconfig.c > @@ -94,8 +94,7 @@ static int use_curses; > #define for_each_raid_cmd(cmd) for (cmd = raid_cmd_head; cmd; cmd = > cmd->next) > > #define DEFAULT_LOG_DIR "/var/log" > -#define DEFAULT_EDITOR "vi -R" > -#define FAILSAFE_EDITOR "vi -R -" > +#define DEFAULT_EDITOR "/usr/bin/less" I like moving the default editor from vi to less. But I guess we can avoid using the absolute path here... you know the drill :) > > #define IS_CANCEL_KEY(c) ((c == KEY_F(12)) || (c == 'q') || (c == 'Q')) > #define CANCEL_KEY_LABEL "q=Cancel " > @@ -11935,44 +11934,69 @@ int ibm_storage_log_tail(i_container *i_con) > int rc, len; > int log_fd; > char *logfile; > + FILE *logsource; > > logfile = strdup(_PATH_TMP"iprerror-XXXXXX"); > log_fd = mkstemp(logfile); > + if (log_fd < 0) { > + closelog(); > + openlog(tool_name, LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER); > + syslog(LOG_ERR, "Could not create temp log file: %m\n"); > + closelog(); > + openlog(tool_name, LOG_PID | LOG_CONS, LOG_USER); Why do you invoke closelog may times? Is that required? From the manpage, closelog seems to be optional.. > + return 65; Why 65? Is that expected by the caller? Can we change this to use a constant or something more meaningful? > + } > > def_prog_mode(); > + endwin(); > > - if (log_fd == -1) { > - len = sprintf(cmnd, "cd %s; zcat -f messages", log_root_dir); > - > - len += sprintf(cmnd + len," | grep ipr | "); > - len += sprintf(cmnd + len, "sed \"s/ `hostname -s` kernel: > ipr//g\" | "); > - len += sprintf(cmnd + len, "sed \"s/ localhost kernel: ipr//g\" > | "); > - len += sprintf(cmnd + len, "sed \"s/ kernel: ipr//g\" | "); > - len += sprintf(cmnd + len, "sed \"s/\\^M//g\" | "); > - len += sprintf(cmnd + len, FAILSAFE_EDITOR); > + snprintf(cmnd, sizeof(cmnd), "%s/messages", log_root_dir); Guess we could use a more meaningful name than cmnd for this variable, since it doesn't holds a command anymore, but a file name. > + logsource = fopen(cmnd, "r"); > + if (logsource < 0) { > closelog(); > - openlog("iprconfig", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER); > - syslog(LOG_ERR, "Error encountered concatenating log > files...\n"); > - syslog(LOG_ERR, "Using failsafe editor...\n"); > + openlog(tool_name, LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER); > + syslog(LOG_ERR, "Could not open %s: %m\n", cmnd); > closelog(); > - openlog("iprconfig", LOG_PID | LOG_CONS, LOG_USER); > - sleep(3); > - } else { > - len = sprintf(cmnd,"cd %s; zcat -f messages | grep ipr |", > log_root_dir); > - len += sprintf(cmnd + len, "sed \"s/ `hostname -s` kernel: > ipr//g\""); > - len += sprintf(cmnd + len, " | sed \"s/ localhost kernel: > ipr//g\""); > - len += sprintf(cmnd + len, " | sed \"s/ kernel: ipr//g\""); > - len += sprintf(cmnd + len, " | sed \"s/\\^M//g\" "); > - len += sprintf(cmnd + len, ">> %s", logfile); > - system(cmnd); > - > - sprintf(cmnd, "%s %s", editor, logfile); > + openlog(tool_name, LOG_PID | LOG_CONS, LOG_USER); > + close(log_fd); > + return 65; > } > > - rc = system(cmnd); > + while (fgets(cmnd, sizeof(cmnd), logsource)) { > + /* ignore lines that dont contain 'ipr' */ > + if (strstr(cmnd, "ipr") == NULL) > + continue; > > - if (log_fd != -1) > - close(log_fd); > + const char *local_s = "localhost kernel: ipr"; > + const char *kernel_s = "kernel: ipr"; > + char regex[256]; > + char host[256]; > + char *dot; Please move the declarations to the top of the function or to the top of the current code block. I find it bad to mix declarations with actual code. > + > + gethostname(host, sizeof(host)); > + dot = strchr(host, '.'); > + if (dot) > + *dot = '\0'; > + snprintf(regex, sizeof(regex), "%s kernel: ipr", host); > + > + /* erase regex from cmnd */ > + if (dot = strstr(cmnd, regex)) { I was confused by the usage of cmnd here. Wasn't it pointing to the log file name? Let's use another variable here, with a better name. > + memmove(dot, dot + strlen(regex), > + strlen(dot) - strlen(regex) + 1); > + } else if (dot = strstr(cmnd, local_s)) { > + memmove(dot, dot+strlen(local_s), > + strlen(dot) - strlen(local_s) + 1); > + } else if (dot = strstr(cmnd, kernel_s)) { > + memmove(dot, dot+strlen(kernel_s), > + strlen(dot) - strlen(kernel_s) + 1); > + } > + > + write(log_fd, cmnd, strlen(cmnd)); I had a hard time understanding this block. Would please add a comment in the code? :) > int log_fd; > char *logfile; > - > + FILE *logsource; > > sprintf(cmnd,"%s/boot.msg",log_root_dir); > rc = stat(cmnd, &file_stat); > @@ -12488,35 +12534,41 @@ int ibm_boot_log(i_container *i_con) > > logfile = strdup(_PATH_TMP"iprerror-XXXXXX"); > log_fd = mkstemp(logfile); > + if (log_fd < 0) { > + closelog(); > + openlog(tool_name, LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER); > + syslog(LOG_ERR, "Could not create temp log file: %m\n"); > + closelog(); > + openlog(tool_name, LOG_PID | LOG_CONS, LOG_USER); > + return 65; > + } > > def_prog_mode(); > + endwin(); > > - if (log_fd == -1) { > - len = sprintf(cmnd, "cd %s; zcat -f ", log_root_dir); > - > - /* Probably have a read-only root file system */ Do we still handle the case where the rootfs is RO? > - len += sprintf(cmnd + len, "boot.msg"); > - len += sprintf(cmnd + len," | grep ipr |"); > - len += sprintf(cmnd + len, FAILSAFE_EDITOR); > + snprintf(cmnd, sizeof(cmnd), "%s/boot.msg", log_root_dir); > + logsource = fopen(cmnd, "r"); > + if (logsource < 0) { > closelog(); > - openlog("iprconfig", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER); > - syslog(LOG_ERR, "Error encountered concatenating log > files...\n"); > - syslog(LOG_ERR, "Using failsafe editor...\n"); > + openlog(tool_name, LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER); > + syslog(LOG_ERR, "Could not open %s: %m\n", cmnd); > closelog(); > - openlog("iprconfig", LOG_PID | LOG_CONS, LOG_USER); > - sleep(3); > - } else { > - len = sprintf(cmnd,"cd %s; zcat -f boot.msg | grep ipr | " > - "sed 's/<[0-9]>ipr-err: //g' | sed 's/<[0-9]>ipr: > //g'", > - log_root_dir); > - len += sprintf(cmnd + len, ">> %s", logfile); > - system(cmnd); > - sprintf(cmnd, "%s %s", editor, logfile); > + openlog(tool_name, LOG_PID | LOG_CONS, LOG_USER); > + close(log_fd); > + return 65; > } > - rc = system(cmnd); > > - if (log_fd != -1) > - close(log_fd); > + while (fgets(cmnd, sizeof(cmnd), logsource)) { > + /* ignore lines that dont contain 'ipr' */ > + if (strstr(cmnd, "ipr") == NULL) > + continue; > + > + write(log_fd, cmnd, strlen(cmnd)); > + } > + > + fclose(logsource); > + close(log_fd); > + rc = invoke_pager(logfile); > > if ((rc != 0) && (rc != 127)) { > s_status.num = rc; > diff --git a/iprlib.c b/iprlib.c > index c5dfd8bb50c0..26c7a500d29b 100644 > --- a/iprlib.c > +++ b/iprlib.c > @@ -10079,3 +10079,23 @@ int ipr_jbod_sysfs_bind(struct ipr_dev *dev, u8 op) > close(fd); > return 0; > } > + > +int invoke_pager(char *filename) > +{ > + int pid, status; > + char *argv[] = { > + "/usr/bin/less", "-c", Replace with macro DEFAULT_EDITOR. > + filename, NULL > + }; > + > + pid = fork(); > + if (pid) { > + waitpid(pid, &status, 0); > + } else { > + /* disable insecure pager features */ > + putenv("LESSSECURE=1"); > + execv(argv[0], argv); > + _exit(errno); > + } > + return WEXITSTATUS(status); > +} > diff --git a/iprlib.h b/iprlib.h > index 16fe1e162650..cec70cd976a7 100644 > --- a/iprlib.h > +++ b/iprlib.h > @@ -38,6 +38,7 @@ > #include <sys/stat.h> > #include <sys/types.h> > #include <sys/socket.h> > +#include <sys/wait.h> > #include <ctype.h> > #include <syslog.h> > #include <term.h> > @@ -49,6 +50,7 @@ > #include <bits/sockaddr.h> > #include <linux/netlink.h> > #include <time.h> > +#include <zlib.h> > > typedef uint8_t u8; > typedef uint16_t u16; > @@ -2906,6 +2908,7 @@ u32 get_ioa_ucode_version(char *); > int ipr_improper_device_type(struct ipr_dev *); > int ipr_get_fw_version(struct ipr_dev *, u8 release_level[4]); > int ipr_get_live_dump(struct ipr_ioa *); > +int invoke_pager(char *filename); > > static inline u32 ipr_get_dev_res_handle(struct ipr_ioa *ioa, struct > ipr_dev_record *dev_rcd) > { > diff --git a/spec/iprutils.spec b/spec/iprutils.spec > index 461d97799786..fe246e4f7b2c 100644 > --- a/spec/iprutils.spec > +++ b/spec/iprutils.spec > @@ -8,7 +8,7 @@ Vendor: IBM > URL: http://sourceforge.net/projects/iprdd/ > Source0: iprutils-%{version}.tar.gz > BuildRoot: %{_tmppath}/%{name}-root > -BuildRequires: ncurses-devel > +BuildRequires: ncurses-devel zlib-devel > > # Predicate whether we want to build -static package. > %bcond_with static This breaks static build. In a RHEL system, we have the zlib-static package, other distros will have similar packages. Please add them as proper build dependencies for the static subpackage. Thanks, -- Gabriel Krisman Bertazi ------------------------------------------------------------------------------ Site24x7 APM Insight: Get Deep Visibility into Application Performance APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month Monitor end-to-end web transactions and take corrective actions now Troubleshoot faster and improve end-user experience. Signup Now! http://pubads.g.doubleclick.net/gampad/clk?id=267308311&iu=/4140 _______________________________________________ Iprdd-devel mailing list Iprdd-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/iprdd-devel