aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2009-05-27 17:06:25 -0400
committerMike Frysinger <vapier@gentoo.org>2009-05-27 17:06:25 -0400
commit93cadc2fddbf8e640501dfd0ed0344119cb892ee (patch)
treeb242123984a72e8ccd0da1c595b6c8a17111fd62
parent673e945052fd6a5de31249a9a630f4f2bf7ec4ef (diff)
downloadbusybox-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.c105
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);
539static int builtin_source(char **argv); 539static int builtin_source(char **argv);
540static int builtin_test(char **argv); 540static int builtin_test(char **argv);
541static int builtin_trap(char **argv); 541static int builtin_trap(char **argv);
542static int builtin_type(char **argv);
542static int builtin_true(char **argv); 543static int builtin_true(char **argv);
543static int builtin_umask(char **argv); 544static int builtin_umask(char **argv);
544static int builtin_unset(char **argv); 545static 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,
2865static void parse_and_run_string(const char *s); 2867static void parse_and_run_string(const char *s);
2866 2868
2867 2869
2870static 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
2868static const struct built_in_command* find_builtin(const char *name) 2903static 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 */
6767static 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 */
6733static int builtin_fg_bg(char **argv) 6805static int builtin_fg_bg(char **argv)
@@ -6986,7 +7058,7 @@ static int builtin_shift(char **argv)
6986 7058
6987static int builtin_source(char **argv) 7059static 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