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 /shell | |
| 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>
Diffstat (limited to 'shell')
| -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 |
