Heitor Ricardo Alves de Siqueira <[email protected]> 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
[email protected]
https://lists.sourceforge.net/lists/listinfo/iprdd-devel