No specific user configuration
[platform/upstream/bash.git] / builtins / type.def
index 3af018f..bd9ecfc 100644 (file)
@@ -1,52 +1,59 @@
 This file is type.def, from which is created type.c.
 It implements the builtin "type" in Bash.
 
 This file is type.def, from which is created type.c.
 It implements the builtin "type" in Bash.
 
-Copyright (C) 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
+Copyright (C) 1987-2011 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
-Bash is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 1, or (at your option) any later
-version.
+Bash is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 
-Bash is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
+Bash is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
 
 
-You should have received a copy of the GNU General Public License along
-with Bash; see the file COPYING.  If not, write to the Free Software
-Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+You should have received a copy of the GNU General Public License
+along with Bash.  If not, see <http://www.gnu.org/licenses/>.
 
 $PRODUCES type.c
 
 $BUILTIN type
 $FUNCTION type_builtin
 
 $PRODUCES type.c
 
 $BUILTIN type
 $FUNCTION type_builtin
-$SHORT_DOC type [-apt] name [name ...]
+$SHORT_DOC type [-afptP] name [name ...]
+Display information about command type.
+
 For each NAME, indicate how it would be interpreted if used as a
 command name.
 
 For each NAME, indicate how it would be interpreted if used as a
 command name.
 
-If the -t option is used, returns a single word which is one of
-`alias', `keyword', `function', `builtin', `file' or `', if NAME is an
-alias, shell reserved word, shell function, shell builtin, disk file,
-or unfound, respectively.
-
-If the -p flag is used, either returns the name of the disk file
-that would be executed, or nothing if -t would not return `file'.
-
-If the -a flag is used, displays all of the places that contain an
-executable named `file'.  This includes aliases and functions, if and
-only if the -p flag is not also used.
-
-Type accepts -all, -path, and -type in place of -a, -p, and -t,
-respectively.
+Options:
+  -a   display all locations containing an executable named NAME;
+       includes aliases, builtins, and functions, if and only if
+       the `-p' option is not also used
+  -f   suppress shell function lookup
+  -P   force a PATH search for each NAME, even if it is an alias,
+       builtin, or function, and returns the name of the disk file
+       that would be executed
+  -p   returns either the name of the disk file that would be executed,
+       or nothing if `type -t NAME' would not return `file'.
+  -t   output a single word which is one of `alias', `keyword',
+       `function', `builtin', `file' or `', if NAME is an alias, shell
+       reserved word, shell function, shell builtin, disk file, or not 
+       found, respectively
+
+Arguments:
+  NAME Command name to be interpreted.
+
+Exit Status:
+Returns success if all of the NAMEs are found; fails if any are not found.
 $END
 
 #include <config.h>
 
 #include "../bashtypes.h"
 $END
 
 #include <config.h>
 
 #include "../bashtypes.h"
-#include "../posixstat.h"
+#include "posixstat.h"
 
 #if defined (HAVE_UNISTD_H)
 #  include <unistd.h>
 
 #if defined (HAVE_UNISTD_H)
 #  include <unistd.h>
@@ -54,9 +61,10 @@ $END
 
 #include <stdio.h>
 #include "../bashansi.h"
 
 #include <stdio.h>
 #include "../bashansi.h"
+#include "../bashintl.h"
 
 #include "../shell.h"
 
 #include "../shell.h"
-#include "../execute_cmd.h"
+#include "../findcmd.h"
 #include "../hashcmd.h"
 
 #if defined (ALIAS)
 #include "../hashcmd.h"
 
 #if defined (ALIAS)
@@ -64,23 +72,33 @@ $END
 #endif /* ALIAS */
 
 #include "common.h"
 #endif /* ALIAS */
 
 #include "common.h"
+#include "bashgetopt.h"
+
+extern int find_reserved_word __P((char *));
 
 
-extern int find_reserved_word ();
+extern char *this_command_name;
+extern int expand_aliases, posixly_correct;
 
 /* For each word in LIST, find out what the shell is going to do with
    it as a simple command. i.e., which file would this shell use to
    execve, or if it is a builtin command, or an alias.  Possible flag
    arguments:
 
 /* For each word in LIST, find out what the shell is going to do with
    it as a simple command. i.e., which file would this shell use to
    execve, or if it is a builtin command, or an alias.  Possible flag
    arguments:
-       -type           Returns the "type" of the object, one of
+       -t              Returns the "type" of the object, one of
                        `alias', `keyword', `function', `builtin',
                        or `file'.
 
                        `alias', `keyword', `function', `builtin',
                        or `file'.
 
-       -path           Returns the pathname of the file if -type is
+       -p              Returns the pathname of the file if -type is
                        a file.
 
                        a file.
 
-       -all            Returns all occurrences of words, whether they
+       -a              Returns all occurrences of words, whether they
                        be a filename in the path, alias, function,
                        or builtin.
                        be a filename in the path, alias, function,
                        or builtin.
+
+       -f              Suppress shell function lookup, like `command'.
+
+       -P              Force a path search even in the presence of other
+                       definitions.
+
    Order of evaluation:
        alias
        keyword
    Order of evaluation:
        alias
        keyword
@@ -88,188 +106,200 @@ extern int find_reserved_word ();
        builtin
        file
  */
        builtin
        file
  */
+
 int
 type_builtin (list)
      WORD_LIST *list;
 {
 int
 type_builtin (list)
      WORD_LIST *list;
 {
-  int path_only, type_only, all, verbose;
-  int successful_finds;
+  int dflags, any_failed, opt;
+  WORD_LIST *this;
 
   if (list == 0)
     return (EXECUTION_SUCCESS);
 
 
   if (list == 0)
     return (EXECUTION_SUCCESS);
 
-  path_only = type_only = all = 0;
-  successful_finds = 0;
+  dflags = CDESC_SHORTDESC;    /* default */
+  any_failed = 0;
 
 
-  while (list && *(list->word->word) == '-')
+  /* Handle the obsolescent `-type', `-path', and `-all' by prescanning
+     the arguments and converting those options to the form that
+     internal_getopt recognizes. Converts `--type', `--path', and `--all'
+     also. THIS SHOULD REALLY GO AWAY. */
+  for (this = list; this && this->word->word[0] == '-'; this = this->next)
     {
     {
-      char *flag = &(list->word->word[1]);
+      char *flag = &(this->word->word[1]);
 
 
-      if (flag[0] == 't' && (!flag[1] || strcmp (flag + 1, "ype") == 0))
+      if (STREQ (flag, "type") || STREQ (flag, "-type"))
        {
        {
-         type_only = 1;
-         path_only = 0;
+         this->word->word[1] = 't';
+         this->word->word[2] = '\0';
        }
        }
-      else if (flag[0] == 'p' && (!flag[1] || strcmp (flag + 1, "ath") == 0))
+      else if (STREQ (flag, "path") || STREQ (flag, "-path"))
        {
        {
-         path_only = 1;
-         type_only = 0;
+         this->word->word[1] = 'p';
+         this->word->word[2] = '\0';
        }
        }
-      else if (flag[0] == 'a' && (!flag[1] || strcmp (flag + 1, "ll") == 0))
+      else if (STREQ (flag, "all") || STREQ (flag, "-all"))
        {
        {
-         all = 1;
+         this->word->word[1] = 'a';
+         this->word->word[2] = '\0';
        }
        }
-      else
+    }
+
+  reset_internal_getopt ();
+  while ((opt = internal_getopt (list, "afptP")) != -1)
+    {
+      switch (opt)
        {
        {
-         bad_option (flag);
+       case 'a':
+         dflags |= CDESC_ALL;
+         break;
+       case 'f':
+         dflags |= CDESC_NOFUNCS;
+         break;
+       case 'p':
+         dflags |= CDESC_PATH_ONLY;
+         dflags &= ~(CDESC_TYPE|CDESC_SHORTDESC);
+         break;
+       case 't':
+         dflags |= CDESC_TYPE;
+         dflags &= ~(CDESC_PATH_ONLY|CDESC_SHORTDESC);
+         break;
+       case 'P':       /* shorthand for type -ap */
+         dflags |= (CDESC_PATH_ONLY|CDESC_FORCE_PATH);
+         dflags &= ~(CDESC_TYPE|CDESC_SHORTDESC);
+         break;
+       default:
          builtin_usage ();
          return (EX_USAGE);
        }
          builtin_usage ();
          return (EX_USAGE);
        }
-      list = list->next;
     }
     }
-
-  if (type_only)
-    verbose = 1;
-  else if (path_only == 0)
-    verbose = 2;
-  else if (path_only)
-    verbose = 3;
-  else
-    verbose = 0;
+  list = loptend;
 
   while (list)
     {
       int found;
 
 
   while (list)
     {
       int found;
 
-      found = describe_command (list->word->word, verbose, all);
+      found = describe_command (list->word->word, dflags);
 
 
-      if (!found && !path_only && !type_only)
-       builtin_error ("%s: not found", list->word->word);
+      if (!found && (dflags & (CDESC_PATH_ONLY|CDESC_TYPE)) == 0)
+       sh_notfound (list->word->word);
 
 
-      successful_finds += found;
+      any_failed += found == 0;
       list = list->next;
     }
 
       list = list->next;
     }
 
-  fflush (stdout);
-
-  if (successful_finds != 0)
-    return (EXECUTION_SUCCESS);
-  else
-    return (EXECUTION_FAILURE);
+  opt = (any_failed == 0) ? EXECUTION_SUCCESS : EXECUTION_FAILURE;
+  return (sh_chkwrite (opt));
 }
 
 /*
 }
 
 /*
- * Describe COMMAND as required by the type builtin.
+ * Describe COMMAND as required by the type and command builtins.
  *
  *
- * If VERBOSE == 0, don't print anything
- * If VERBOSE == 1, print short description as for `type -t'
- * If VERBOSE == 2, print long description as for `type' and `command -V'
- * If VERBOSE == 3, print path name only for disk files
- * If VERBOSE == 4, print string used to invoke COMMAND, for `command -v'
+ * Behavior is controlled by DFLAGS.  Flag values are
+ *     CDESC_ALL       print all descriptions of a command
+ *     CDESC_SHORTDESC print the description for type and command -V
+ *     CDESC_REUSABLE  print in a format that may be reused as input
+ *     CDESC_TYPE      print the type for type -t
+ *     CDESC_PATH_ONLY print the path for type -p
+ *     CDESC_FORCE_PATH        force a path search for type -P
+ *     CDESC_NOFUNCS   skip function lookup for type -f
+ *     CDESC_ABSPATH   convert to absolute path, no ./ prefix
  *
  *
- * ALL says whether or not to look for all occurrences of COMMAND, or
+ * CDESC_ALL says whether or not to look for all occurrences of COMMAND, or
  * return after finding it once.
  */
 int
  * return after finding it once.
  */
 int
-describe_command (command, verbose, all)
+describe_command (command, dflags)
      char *command;
      char *command;
-     int verbose, all;
+     int dflags;
 {
 {
-  int found, i, found_file;
-  char *full_path;
+  int found, i, found_file, f, all;
+  char *full_path, *x;
   SHELL_VAR *func;
 #if defined (ALIAS)
   alias_t *alias;
 #endif
 
   SHELL_VAR *func;
 #if defined (ALIAS)
   alias_t *alias;
 #endif
 
+  all = (dflags & CDESC_ALL) != 0;
   found = found_file = 0;
   full_path = (char *)NULL;
 
 #if defined (ALIAS)
   /* Command is an alias? */
   found = found_file = 0;
   full_path = (char *)NULL;
 
 #if defined (ALIAS)
   /* Command is an alias? */
-  alias = find_alias (command);
-
-  if (alias)
+  if (((dflags & CDESC_FORCE_PATH) == 0) && expand_aliases && (alias = find_alias (command)))
     {
     {
-      if (verbose == 1)
+      if (dflags & CDESC_TYPE)
        puts ("alias");
        puts ("alias");
-      else if (verbose == 2)
-       printf ("%s is aliased to `%s'\n", command, alias->value);
-      else if (verbose == 4)
+      else if (dflags & CDESC_SHORTDESC)
+       printf (_("%s is aliased to `%s'\n"), command, alias->value);
+      else if (dflags & CDESC_REUSABLE)
        {
        {
-         char *x = single_quote (alias->value);
+         x = sh_single_quote (alias->value);
          printf ("alias %s=%s\n", command, x);
          free (x);
        }
 
       found = 1;
 
          printf ("alias %s=%s\n", command, x);
          free (x);
        }
 
       found = 1;
 
-      if (!all)
+      if (all == 0)
        return (1);
     }
 #endif /* ALIAS */
 
   /* Command is a shell reserved word? */
        return (1);
     }
 #endif /* ALIAS */
 
   /* Command is a shell reserved word? */
-  i = find_reserved_word (command);
-  if (i >= 0)
+  if (((dflags & CDESC_FORCE_PATH) == 0) && (i = find_reserved_word (command)) >= 0)
     {
     {
-      if (verbose == 1)
+      if (dflags & CDESC_TYPE)
        puts ("keyword");
        puts ("keyword");
-      else if (verbose == 2)
-       printf ("%s is a shell keyword\n", command);
-      else if (verbose == 4)
+      else if (dflags & CDESC_SHORTDESC)
+       printf (_("%s is a shell keyword\n"), command);
+      else if (dflags & CDESC_REUSABLE)
        printf ("%s\n", command);
 
       found = 1;
 
        printf ("%s\n", command);
 
       found = 1;
 
-      if (!all)
+      if (all == 0)
        return (1);
     }
 
   /* Command is a function? */
        return (1);
     }
 
   /* Command is a function? */
-  func = find_function (command);
-
-  if (func)
+  if (((dflags & (CDESC_FORCE_PATH|CDESC_NOFUNCS)) == 0) && (func = find_function (command)))
     {
     {
-      if (verbose == 1)
+      if (dflags & CDESC_TYPE)
        puts ("function");
        puts ("function");
-      else if (verbose == 2)
+      else if (dflags & CDESC_SHORTDESC)
        {
        {
-#define PRETTY_PRINT_FUNC 1
          char *result;
 
          char *result;
 
-         printf ("%s is a function\n", command);
+         printf (_("%s is a function\n"), command);
 
          /* We're blowing away THE_PRINTED_COMMAND here... */
 
 
          /* We're blowing away THE_PRINTED_COMMAND here... */
 
-         result = named_function_string (command,
-                                         (COMMAND *) function_cell (func),
-                                         PRETTY_PRINT_FUNC);
+         result = named_function_string (command, function_cell (func), FUNC_MULTILINE|FUNC_EXTERNAL);
          printf ("%s\n", result);
          printf ("%s\n", result);
-#undef PRETTY_PRINT_FUNC
        }
        }
-      else if (verbose == 4)
+      else if (dflags & CDESC_REUSABLE)
        printf ("%s\n", command);
 
       found = 1;
 
        printf ("%s\n", command);
 
       found = 1;
 
-      if (!all)
+      if (all == 0)
        return (1);
     }
 
   /* Command is a builtin? */
        return (1);
     }
 
   /* Command is a builtin? */
-  if (find_shell_builtin (command))
+  if (((dflags & CDESC_FORCE_PATH) == 0) && find_shell_builtin (command))
     {
     {
-      if (verbose == 1)
+      if (dflags & CDESC_TYPE)
        puts ("builtin");
        puts ("builtin");
-      else if (verbose == 2)
-       printf ("%s is a shell builtin\n", command);
-      else if (verbose == 4)
+      else if (dflags & CDESC_SHORTDESC)
+       printf (_("%s is a shell builtin\n"), command);
+      else if (dflags & CDESC_REUSABLE)
        printf ("%s\n", command);
 
       found = 1;
 
        printf ("%s\n", command);
 
       found = 1;
 
-      if (!all)
+      if (all == 0)
        return (1);
     }
 
        return (1);
     }
 
@@ -278,34 +308,34 @@ describe_command (command, verbose, all)
      check to see if it is executable. */
   if (absolute_program (command))
     {
      check to see if it is executable. */
   if (absolute_program (command))
     {
-      int f = file_status (command);
+      f = file_status (command);
       if (f & FS_EXECABLE)
       if (f & FS_EXECABLE)
-        {
-         if (verbose == 1)
+       {
+         if (dflags & CDESC_TYPE)
            puts ("file");
            puts ("file");
-         else if (verbose == 2)
-           printf ("%s is %s\n", command, command);
-         else if (verbose == 3 || verbose == 4)
+         else if (dflags & CDESC_SHORTDESC)
+           printf (_("%s is %s\n"), command, command);
+         else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY))
            printf ("%s\n", command);
 
          /* There's no use looking in the hash table or in $PATH,
             because they're not consulted when an absolute program
             name is supplied. */
          return (1);
            printf ("%s\n", command);
 
          /* There's no use looking in the hash table or in $PATH,
             because they're not consulted when an absolute program
             name is supplied. */
          return (1);
-        }
+       }
     }
 
     }
 
-  /* If the user isn't doing "-all", then we might care about
+  /* If the user isn't doing "-a", then we might care about
      whether the file is present in our hash table. */
      whether the file is present in our hash table. */
-  if (!all)
+  if (all == 0 || (dflags & CDESC_FORCE_PATH))
     {
     {
-      if ((full_path = find_hashed_filename (command)) != (char *)NULL)
+      if (full_path = phash_search (command))
        {
        {
-         if (verbose == 1)
+         if (dflags & CDESC_TYPE)
            puts ("file");
            puts ("file");
-         else if (verbose == 2)
-           printf ("%s is hashed (%s)\n", command, full_path);
-         else if (verbose == 3 || verbose == 4)
+         else if (dflags & CDESC_SHORTDESC)
+           printf (_("%s is hashed (%s)\n"), command, full_path);
+         else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY))
            printf ("%s\n", full_path);
 
          free (full_path);
            printf ("%s\n", full_path);
 
          free (full_path);
@@ -316,30 +346,58 @@ describe_command (command, verbose, all)
   /* Now search through $PATH. */
   while (1)
     {
   /* Now search through $PATH. */
   while (1)
     {
-      if (!all)
+      if (all == 0)
        full_path = find_user_command (command);
       else
        full_path =
          user_command_matches (command, FS_EXEC_ONLY, found_file);
          /* XXX - should that be FS_EXEC_PREFERRED? */
 
        full_path = find_user_command (command);
       else
        full_path =
          user_command_matches (command, FS_EXEC_ONLY, found_file);
          /* XXX - should that be FS_EXEC_PREFERRED? */
 
-      if (!full_path)
+      if (full_path == 0)
        break;
 
        break;
 
+      /* If we found the command as itself by looking through $PATH, it
+        probably doesn't exist.  Check whether or not the command is an
+        executable file.  If it's not, don't report a match.  This is
+        the default posix mode behavior */
+      if (STREQ (full_path, command) || posixly_correct)
+       {
+         f = file_status (full_path);
+         if ((f & FS_EXECABLE) == 0)
+           {
+             free (full_path);
+             full_path = (char *)NULL;
+             if (all == 0)
+               break;
+           }
+         else if (ABSPATH (full_path))
+           ;   /* placeholder; don't need to do anything yet */
+         else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY|CDESC_SHORTDESC))
+           {
+             f = MP_DOCWD | ((dflags & CDESC_ABSPATH) ? MP_RMDOT : 0);
+             x = sh_makepath ((char *)NULL, full_path, f);
+             free (full_path);
+             full_path = x;
+           }
+       }
+      /* If we require a full path and don't have one, make one */
+      else if ((dflags & CDESC_ABSPATH) && ABSPATH (full_path) == 0)
+       full_path = sh_makepath ((char *)NULL, full_path, MP_DOCWD|MP_RMDOT);
+
       found_file++;
       found = 1;
 
       found_file++;
       found = 1;
 
-      if (verbose == 1)
+      if (dflags & CDESC_TYPE)
        puts ("file");
        puts ("file");
-      else if (verbose == 2)
-       printf ("%s is %s\n", command, full_path);
-      else if (verbose == 3 || verbose == 4)
+      else if (dflags & CDESC_SHORTDESC)
+       printf (_("%s is %s\n"), command, full_path);
+      else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY))
        printf ("%s\n", full_path);
 
       free (full_path);
       full_path = (char *)NULL;
 
        printf ("%s\n", full_path);
 
       free (full_path);
       full_path = (char *)NULL;
 
-      if (!all)
+      if (all == 0)
        break;
     }
 
        break;
     }