diff options
author | Mike Frysinger <vapier@gentoo.org> | 2009-05-27 17:06:25 -0400 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2009-05-27 17:06:25 -0400 |
commit | 93cadc2fddbf8e640501dfd0ed0344119cb892ee (patch) | |
tree | b242123984a72e8ccd0da1c595b6c8a17111fd62 | |
parent | 673e945052fd6a5de31249a9a630f4f2bf7ec4ef (diff) | |
download | busybox-w32-93cadc2fddbf8e640501dfd0ed0344119cb892ee.tar.gz busybox-w32-93cadc2fddbf8e640501dfd0ed0344119cb892ee.tar.bz2 busybox-w32-93cadc2fddbf8e640501dfd0ed0344119cb892ee.zip |
hush: implement `type`
Implement support for the POSIX `type` command. Only POSIX stuff is
supported here, no bash extensions like -p or -P.
In the process, split the $PATH searching code out of builtin_source() and
into its own find_in_path() function so we don't duplicate it.
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
-rw-r--r-- | shell/hush.c | 105 |
1 files changed, 78 insertions, 27 deletions
diff --git a/shell/hush.c b/shell/hush.c index 7167de701..efa93c1a6 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -539,6 +539,7 @@ static int builtin_shift(char **argv); | |||
539 | static int builtin_source(char **argv); | 539 | static int builtin_source(char **argv); |
540 | static int builtin_test(char **argv); | 540 | static int builtin_test(char **argv); |
541 | static int builtin_trap(char **argv); | 541 | static int builtin_trap(char **argv); |
542 | static int builtin_type(char **argv); | ||
542 | static int builtin_true(char **argv); | 543 | static int builtin_true(char **argv); |
543 | static int builtin_umask(char **argv); | 544 | static int builtin_umask(char **argv); |
544 | static int builtin_unset(char **argv); | 545 | static int builtin_unset(char **argv); |
@@ -610,6 +611,7 @@ static const struct built_in_command bltins[] = { | |||
610 | BLTIN("shift" , builtin_shift , "Shift positional parameters"), | 611 | BLTIN("shift" , builtin_shift , "Shift positional parameters"), |
611 | BLTIN("test" , builtin_test , "Test condition"), | 612 | BLTIN("test" , builtin_test , "Test condition"), |
612 | BLTIN("trap" , builtin_trap , "Trap signals"), | 613 | BLTIN("trap" , builtin_trap , "Trap signals"), |
614 | BLTIN("type" , builtin_type , "Write a description of command type"), | ||
613 | // BLTIN("ulimit" , builtin_return , "Control resource limits"), | 615 | // BLTIN("ulimit" , builtin_return , "Control resource limits"), |
614 | BLTIN("umask" , builtin_umask , "Set file creation mask"), | 616 | BLTIN("umask" , builtin_umask , "Set file creation mask"), |
615 | BLTIN("unset" , builtin_unset , "Unset environment variable"), | 617 | BLTIN("unset" , builtin_unset , "Unset environment variable"), |
@@ -2865,6 +2867,39 @@ static struct pipe *parse_stream(char **pstring, | |||
2865 | static void parse_and_run_string(const char *s); | 2867 | static void parse_and_run_string(const char *s); |
2866 | 2868 | ||
2867 | 2869 | ||
2870 | static char *find_in_path(const char *arg) | ||
2871 | { | ||
2872 | char *ret = NULL; | ||
2873 | const char *PATH = get_local_var_value("PATH"); | ||
2874 | |||
2875 | if (!PATH) | ||
2876 | return NULL; | ||
2877 | |||
2878 | while (1) { | ||
2879 | const char *end = strchrnul(PATH, ':'); | ||
2880 | int sz = end - PATH; /* must be int! */ | ||
2881 | |||
2882 | free(ret); | ||
2883 | if (sz != 0) { | ||
2884 | ret = xasprintf("%.*s/%s", sz, PATH, arg); | ||
2885 | } else { | ||
2886 | /* We have xxx::yyyy in $PATH, | ||
2887 | * it means "use current dir" */ | ||
2888 | ret = xstrdup(arg); | ||
2889 | } | ||
2890 | if (access(ret, F_OK) == 0) | ||
2891 | break; | ||
2892 | |||
2893 | if (*end == '\0') { | ||
2894 | free(ret); | ||
2895 | return NULL; | ||
2896 | } | ||
2897 | PATH = end + 1; | ||
2898 | } | ||
2899 | |||
2900 | return ret; | ||
2901 | } | ||
2902 | |||
2868 | static const struct built_in_command* find_builtin(const char *name) | 2903 | static const struct built_in_command* find_builtin(const char *name) |
2869 | { | 2904 | { |
2870 | const struct built_in_command *x; | 2905 | const struct built_in_command *x; |
@@ -6728,6 +6763,43 @@ static int builtin_trap(char **argv) | |||
6728 | goto process_sig_list; | 6763 | goto process_sig_list; |
6729 | } | 6764 | } |
6730 | 6765 | ||
6766 | /* http://www.opengroup.org/onlinepubs/9699919799/utilities/type.html */ | ||
6767 | static int builtin_type(char **argv) | ||
6768 | { | ||
6769 | int i, ret = EXIT_SUCCESS; | ||
6770 | |||
6771 | for (i = 1; argv[i]; ++i) { | ||
6772 | void *path; | ||
6773 | const void *find_ret; | ||
6774 | const char *type; | ||
6775 | |||
6776 | type = path = NULL; | ||
6777 | |||
6778 | if (0) {} /* make conditional compile easier below */ | ||
6779 | /*else if ((find_ret = find_alias(argv[i]))) | ||
6780 | type = "an alias";*/ | ||
6781 | #if ENABLE_HUSH_FUNCTIONS | ||
6782 | else if ((find_ret = find_function(argv[i]))) | ||
6783 | type = "a function"; | ||
6784 | #endif | ||
6785 | else if ((find_ret = find_builtin(argv[i]))) | ||
6786 | type = "a shell builtin"; | ||
6787 | else if ((find_ret = path = find_in_path(argv[i]))) | ||
6788 | type = find_ret; | ||
6789 | |||
6790 | if (!type) { | ||
6791 | bb_error_msg("type: %s: not found", argv[i]); | ||
6792 | ret = EXIT_FAILURE; | ||
6793 | } else | ||
6794 | printf("%s is %s\n", argv[i], type); | ||
6795 | |||
6796 | if (path) | ||
6797 | free(path); | ||
6798 | } | ||
6799 | |||
6800 | return ret; | ||
6801 | } | ||
6802 | |||
6731 | #if ENABLE_HUSH_JOB | 6803 | #if ENABLE_HUSH_JOB |
6732 | /* built-in 'fg' and 'bg' handler */ | 6804 | /* built-in 'fg' and 'bg' handler */ |
6733 | static int builtin_fg_bg(char **argv) | 6805 | static int builtin_fg_bg(char **argv) |
@@ -6986,7 +7058,7 @@ static int builtin_shift(char **argv) | |||
6986 | 7058 | ||
6987 | static int builtin_source(char **argv) | 7059 | static int builtin_source(char **argv) |
6988 | { | 7060 | { |
6989 | const char *PATH; | 7061 | char *arg_path; |
6990 | FILE *input; | 7062 | FILE *input; |
6991 | save_arg_t sv; | 7063 | save_arg_t sv; |
6992 | #if ENABLE_HUSH_FUNCTIONS | 7064 | #if ENABLE_HUSH_FUNCTIONS |
@@ -6996,36 +7068,15 @@ static int builtin_source(char **argv) | |||
6996 | if (*++argv == NULL) | 7068 | if (*++argv == NULL) |
6997 | return EXIT_FAILURE; | 7069 | return EXIT_FAILURE; |
6998 | 7070 | ||
6999 | if (strchr(*argv, '/') == NULL | 7071 | if (strchr(*argv, '/') == NULL && (arg_path = find_in_path(*argv)) != NULL) { |
7000 | && (PATH = get_local_var_value("PATH")) != NULL | 7072 | input = fopen_for_read(arg_path); |
7001 | ) { | 7073 | free(arg_path); |
7002 | /* Search through $PATH */ | 7074 | } else |
7003 | while (1) { | 7075 | input = fopen_or_warn(*argv, "r"); |
7004 | const char *end = strchrnul(PATH, ':'); | ||
7005 | int sz = end - PATH; /* must be int! */ | ||
7006 | |||
7007 | if (sz != 0) { | ||
7008 | char *tmp = xasprintf("%.*s/%s", sz, PATH, *argv); | ||
7009 | input = fopen_for_read(tmp); | ||
7010 | free(tmp); | ||
7011 | } else { | ||
7012 | /* We have xxx::yyyy in $PATH, | ||
7013 | * it means "use current dir" */ | ||
7014 | input = fopen_for_read(*argv); | ||
7015 | } | ||
7016 | if (input) | ||
7017 | goto opened_ok; | ||
7018 | if (*end == '\0') | ||
7019 | break; | ||
7020 | PATH = end + 1; | ||
7021 | } | ||
7022 | } | ||
7023 | input = fopen_or_warn(*argv, "r"); | ||
7024 | if (!input) { | 7076 | if (!input) { |
7025 | /* bb_perror_msg("%s", *argv); - done by fopen_or_warn */ | 7077 | /* bb_perror_msg("%s", *argv); - done by fopen_or_warn */ |
7026 | return EXIT_FAILURE; | 7078 | return EXIT_FAILURE; |
7027 | } | 7079 | } |
7028 | opened_ok: | ||
7029 | close_on_exec_on(fileno(input)); | 7080 | close_on_exec_on(fileno(input)); |
7030 | 7081 | ||
7031 | #if ENABLE_HUSH_FUNCTIONS | 7082 | #if ENABLE_HUSH_FUNCTIONS |