diff --git a/tools/perf/util/exec_cmd.c b/tools/perf/util/exec_cmd.c index 701111ac7699..e7f9ed7943e3 100644 --- a/tools/perf/util/exec_cmd.c +++ b/tools/perf/util/exec_cmd.c @@ -1,12 +1,17 @@ -#include "cache.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "subcmd-util.h" #include "exec_cmd.h" -#include "quote.h" #include "subcmd-config.h" -#include -#include "subcmd-util.h" - #define MAX_ARGS 32 +#define PATH_MAX 4096 static const char *argv_exec_path; static const char *argv0_path; @@ -20,6 +25,49 @@ void exec_cmd_init(const char *exec_name, const char *prefix, subcmd_config.exec_path_env = exec_path_env; } +#define is_dir_sep(c) ((c) == '/') + +static int is_absolute_path(const char *path) +{ + return path[0] == '/'; +} + +static const char *get_pwd_cwd(void) +{ + static char cwd[PATH_MAX + 1]; + char *pwd; + struct stat cwd_stat, pwd_stat; + if (getcwd(cwd, PATH_MAX) == NULL) + return NULL; + pwd = getenv("PWD"); + if (pwd && strcmp(pwd, cwd)) { + stat(cwd, &cwd_stat); + if (!stat(pwd, &pwd_stat) && + pwd_stat.st_dev == cwd_stat.st_dev && + pwd_stat.st_ino == cwd_stat.st_ino) { + strlcpy(cwd, pwd, PATH_MAX); + } + } + return cwd; +} + +static const char *make_nonrelative_path(const char *path) +{ + static char buf[PATH_MAX + 1]; + + if (is_absolute_path(path)) { + if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX) + die("Too long path: %.*s", 60, path); + } else { + const char *cwd = get_pwd_cwd(); + if (!cwd) + die("Cannot determine the current working directory"); + if (snprintf(buf, PATH_MAX, "%s/%s", cwd, path) >= PATH_MAX) + die("Too long path: %.*s", 60, path); + } + return buf; +} + char *system_path(const char *path) { char *buf = NULL; @@ -151,8 +199,10 @@ int execl_cmd(const char *cmd,...) break; } va_end(param); - if (MAX_ARGS <= argc) - return error("too many args to run %s", cmd); + if (MAX_ARGS <= argc) { + fprintf(stderr, " Error: too many args to run %s\n", cmd); + return -1; + } argv[argc] = NULL; return execv_cmd(argv); diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c index 303a347ee234..8169480066c6 100644 --- a/tools/perf/util/help.c +++ b/tools/perf/util/help.c @@ -1,8 +1,15 @@ -#include "cache.h" -#include "../builtin.h" -#include "exec_cmd.h" -#include "help.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "subcmd-util.h" +#include "help.h" +#include "exec_cmd.h" void add_cmdname(struct cmdnames *cmds, const char *name, size_t len) { @@ -70,6 +77,28 @@ void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes) cmds->cnt = cj; } +static void get_term_dimensions(struct winsize *ws) +{ + char *s = getenv("LINES"); + + if (s != NULL) { + ws->ws_row = atoi(s); + s = getenv("COLUMNS"); + if (s != NULL) { + ws->ws_col = atoi(s); + if (ws->ws_row && ws->ws_col) + return; + } + } +#ifdef TIOCGWINSZ + if (ioctl(1, TIOCGWINSZ, ws) == 0 && + ws->ws_row && ws->ws_col) + return; +#endif + ws->ws_row = 25; + ws->ws_col = 80; +} + static void pretty_print_string_list(struct cmdnames *cmds, int longest) { int cols = 1, rows; @@ -113,6 +142,14 @@ static int is_executable(const char *name) return st.st_mode & S_IXUSR; } +static int has_extension(const char *filename, const char *ext) +{ + size_t len = strlen(filename); + size_t extlen = strlen(ext); + + return len > extlen && !memcmp(filename + len - extlen, ext, extlen); +} + static void list_commands_in_dir(struct cmdnames *cmds, const char *path, const char *prefix) @@ -168,7 +205,7 @@ void load_command_list(const char *prefix, char *paths, *path, *colon; path = paths = strdup(env_path); while (1) { - if ((colon = strchr(path, PATH_SEP))) + if ((colon = strchr(path, ':'))) *colon = 0; if (!exec_path || strcmp(path, exec_path)) list_commands_in_dir(other_cmds, path, prefix); diff --git a/tools/perf/util/help.h b/tools/perf/util/help.h index 14851b0e44f5..096c8bc45cd7 100644 --- a/tools/perf/util/help.h +++ b/tools/perf/util/help.h @@ -1,12 +1,14 @@ #ifndef __PERF_HELP_H #define __PERF_HELP_H +#include + struct cmdnames { size_t alloc; size_t cnt; struct cmdname { size_t len; /* also used for similarity index in help.c */ - char name[FLEX_ARRAY]; + char name[]; } **names; }; diff --git a/tools/perf/util/pager.c b/tools/perf/util/pager.c index d5ef62eaa413..d50f3b58606b 100644 --- a/tools/perf/util/pager.c +++ b/tools/perf/util/pager.c @@ -1,4 +1,9 @@ -#include "cache.h" +#include +#include +#include +#include +#include +#include "pager.h" #include "run-command.h" #include "sigchain.h" #include "subcmd-config.h" diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c index c1da2a53ed4e..981bb4481fd5 100644 --- a/tools/perf/util/parse-options.c +++ b/tools/perf/util/parse-options.c @@ -1,10 +1,14 @@ -#include "util.h" +#include +#include +#include +#include +#include +#include +#include #include "subcmd-util.h" #include "parse-options.h" -#include "cache.h" -#include "header.h" #include "subcmd-config.h" -#include +#include "pager.h" #define OPT_SHORT 1 #define OPT_UNSET 2 @@ -14,20 +18,29 @@ char *error_buf; static int opterror(const struct option *opt, const char *reason, int flags) { if (flags & OPT_SHORT) - return error("switch `%c' %s", opt->short_name, reason); - if (flags & OPT_UNSET) - return error("option `no-%s' %s", opt->long_name, reason); - return error("option `%s' %s", opt->long_name, reason); + fprintf(stderr, " Error: switch `%c' %s", opt->short_name, reason); + else if (flags & OPT_UNSET) + fprintf(stderr, " Error: option `no-%s' %s", opt->long_name, reason); + else + fprintf(stderr, " Error: option `%s' %s", opt->long_name, reason); + + return -1; +} + +static const char *skip_prefix(const char *str, const char *prefix) +{ + size_t len = strlen(prefix); + return strncmp(str, prefix, len) ? NULL : str + len; } static void optwarning(const struct option *opt, const char *reason, int flags) { if (flags & OPT_SHORT) - warning("switch `%c' %s", opt->short_name, reason); + fprintf(stderr, " Warning: switch `%c' %s", opt->short_name, reason); else if (flags & OPT_UNSET) - warning("option `no-%s' %s", opt->long_name, reason); + fprintf(stderr, " Warning: option `no-%s' %s", opt->long_name, reason); else - warning("option `%s' %s", opt->long_name, reason); + fprintf(stderr, " Warning: option `%s' %s", opt->long_name, reason); } static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt, @@ -71,11 +84,11 @@ static int get_value(struct parse_opt_ctx_t *p, if (((flags & OPT_SHORT) && p->excl_opt->short_name) || p->excl_opt->long_name == NULL) { - scnprintf(msg, sizeof(msg), "cannot be used with switch `%c'", - p->excl_opt->short_name); + snprintf(msg, sizeof(msg), "cannot be used with switch `%c'", + p->excl_opt->short_name); } else { - scnprintf(msg, sizeof(msg), "cannot be used with %s", - p->excl_opt->long_name); + snprintf(msg, sizeof(msg), "cannot be used with %s", + p->excl_opt->long_name); } opterror(opt, msg, flags); return -3; @@ -401,14 +414,16 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg, return get_value(p, options, flags); } - if (ambiguous_option) - return error("Ambiguous option: %s " - "(could be --%s%s or --%s%s)", - arg, - (ambiguous_flags & OPT_UNSET) ? "no-" : "", - ambiguous_option->long_name, - (abbrev_flags & OPT_UNSET) ? "no-" : "", - abbrev_option->long_name); + if (ambiguous_option) { + fprintf(stderr, + " Error: Ambiguous option: %s (could be --%s%s or --%s%s)", + arg, + (ambiguous_flags & OPT_UNSET) ? "no-" : "", + ambiguous_option->long_name, + (abbrev_flags & OPT_UNSET) ? "no-" : "", + abbrev_option->long_name); + return -1; + } if (abbrev_option) return get_value(p, abbrev_option, abbrev_flags); return -2; @@ -420,7 +435,7 @@ static void check_typos(const char *arg, const struct option *options) return; if (!prefixcmp(arg, "no-")) { - error ("did you mean `--%s` (with two dashes ?)", arg); + fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg); exit(129); } @@ -428,7 +443,7 @@ static void check_typos(const char *arg, const struct option *options) if (!options->long_name) continue; if (!prefixcmp(options->long_name, arg)) { - error ("did you mean `--%s` (with two dashes ?)", arg); + fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg); exit(129); } } @@ -746,16 +761,18 @@ static int option__cmp(const void *va, const void *vb) static struct option *options__order(const struct option *opts) { - int nr_opts = 0; + int nr_opts = 0, len; const struct option *o = opts; struct option *ordered; for (o = opts; o->type != OPTION_END; o++) ++nr_opts; - ordered = memdup(opts, sizeof(*o) * (nr_opts + 1)); - if (ordered == NULL) + len = sizeof(*o) * (nr_opts + 1); + ordered = malloc(len); + if (!ordered) goto out; + memcpy(ordered, opts, len); qsort(ordered, nr_opts, sizeof(*o), option__cmp); out: diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h index d1544069c7c0..dec893f10477 100644 --- a/tools/perf/util/parse-options.h +++ b/tools/perf/util/parse-options.h @@ -1,8 +1,8 @@ #ifndef __PERF_PARSE_OPTIONS_H #define __PERF_PARSE_OPTIONS_H -#include #include +#include enum parse_opt_type { /* special types */ diff --git a/tools/perf/util/run-command.c b/tools/perf/util/run-command.c index 910c0f6479f4..fed37d6ae070 100644 --- a/tools/perf/util/run-command.c +++ b/tools/perf/util/run-command.c @@ -1,7 +1,15 @@ -#include "cache.h" +#include +#include +#include +#include +#include +#include +#include +#include "subcmd-util.h" #include "run-command.h" #include "exec_cmd.h" -#include "debug.h" + +#define STRERR_BUFSIZE 128 static inline void close_pair(int fd[2]) { @@ -164,8 +172,8 @@ static int wait_or_whine(pid_t pid) if (waiting < 0) { if (errno == EINTR) continue; - error("waitpid failed (%s)", - strerror_r(errno, sbuf, sizeof(sbuf))); + fprintf(stderr, " Error: waitpid failed (%s)", + strerror_r(errno, sbuf, sizeof(sbuf))); return -ERR_RUN_COMMAND_WAITPID; } if (waiting != pid) diff --git a/tools/perf/util/run-command.h b/tools/perf/util/run-command.h index cf7d655ee2a3..4a55393a6547 100644 --- a/tools/perf/util/run-command.h +++ b/tools/perf/util/run-command.h @@ -1,6 +1,8 @@ #ifndef __PERF_RUN_COMMAND_H #define __PERF_RUN_COMMAND_H +#include + enum { ERR_RUN_COMMAND_FORK = 10000, ERR_RUN_COMMAND_EXEC, diff --git a/tools/perf/util/sigchain.c b/tools/perf/util/sigchain.c index ba785e9b1841..3537c348a18e 100644 --- a/tools/perf/util/sigchain.c +++ b/tools/perf/util/sigchain.c @@ -1,5 +1,6 @@ +#include +#include "subcmd-util.h" #include "sigchain.h" -#include "cache.h" #define SIGCHAIN_MAX_SIGNALS 32 diff --git a/tools/perf/util/subcmd-util.h b/tools/perf/util/subcmd-util.h index 98fb9f9270eb..321aeb11a381 100644 --- a/tools/perf/util/subcmd-util.h +++ b/tools/perf/util/subcmd-util.h @@ -1,8 +1,66 @@ #ifndef __PERF_SUBCMD_UTIL_H #define __PERF_SUBCMD_UTIL_H +#include +#include #include +#define NORETURN __attribute__((__noreturn__)) + +static inline void report(const char *prefix, const char *err, va_list params) +{ + char msg[1024]; + vsnprintf(msg, sizeof(msg), err, params); + fprintf(stderr, " %s%s\n", prefix, msg); +} + +static NORETURN inline void die(const char *err, ...) +{ + va_list params; + + va_start(params, err); + report(" Fatal: ", err, params); + exit(128); + va_end(params); +} + +#define zfree(ptr) ({ free(*ptr); *ptr = NULL; }) + +#define alloc_nr(x) (((x)+16)*3/2) + +/* + * Realloc the buffer pointed at by variable 'x' so that it can hold + * at least 'nr' entries; the number of entries currently allocated + * is 'alloc', using the standard growing factor alloc_nr() macro. + * + * DO NOT USE any expression with side-effect for 'x' or 'alloc'. + */ +#define ALLOC_GROW(x, nr, alloc) \ + do { \ + if ((nr) > alloc) { \ + if (alloc_nr(alloc) < (nr)) \ + alloc = (nr); \ + else \ + alloc = alloc_nr(alloc); \ + x = xrealloc((x), alloc * sizeof(*(x))); \ + } \ + } while(0) + +static inline void *xrealloc(void *ptr, size_t size) +{ + void *ret = realloc(ptr, size); + if (!ret && !size) + ret = realloc(ptr, 1); + if (!ret) { + ret = realloc(ptr, size); + if (!ret && !size) + ret = realloc(ptr, 1); + if (!ret) + die("Out of memory, realloc failed"); + } + return ret; +} + #define astrcatf(out, fmt, ...) \ ({ \ char *tmp = *(out); \ @@ -21,4 +79,13 @@ static inline void astrcat(char **out, const char *add) free(tmp); } +static inline int prefixcmp(const char *str, const char *prefix) +{ + for (; ; str++, prefix++) + if (!*prefix) + return 0; + else if (*str != *prefix) + return (unsigned char)*prefix - (unsigned char)*str; +} + #endif /* __PERF_SUBCMD_UTIL_H */ diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 150858f3b4f0..4b519c59bdc3 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -151,12 +151,6 @@ extern void set_warning_routine(void (*routine)(const char *err, va_list params) extern int prefixcmp(const char *str, const char *prefix); extern void set_buildid_dir(const char *dir); -static inline const char *skip_prefix(const char *str, const char *prefix) -{ - size_t len = strlen(prefix); - return strncmp(str, prefix, len) ? NULL : str + len; -} - #ifdef __GLIBC_PREREQ #if __GLIBC_PREREQ(2, 1) #define HAVE_STRCHRNUL @@ -187,14 +181,6 @@ static inline void *zalloc(size_t size) #define zfree(ptr) ({ free(*ptr); *ptr = NULL; }) -static inline int has_extension(const char *filename, const char *ext) -{ - size_t len = strlen(filename); - size_t extlen = strlen(ext); - - return len > extlen && !memcmp(filename + len - extlen, ext, extlen); -} - /* Sane ctype - no locale, and works with signed chars */ #undef isascii #undef isspace