1/* command.c, created from command.def. */
2#line 23 "command.def"
3
4#line 34 "command.def"
5
6#include <config.h>
7
8#if defined (HAVE_UNISTD_H)
9#  ifdef _MINIX
10#    include <sys/types.h>
11#  endif
12#  include <unistd.h>
13#endif
14
15#include "../bashansi.h"
16
17#include "../shell.h"
18#include "../execute_cmd.h"
19#include "../flags.h"
20#include "bashgetopt.h"
21#include "common.h"
22
23#if defined (_CS_PATH) && defined (HAVE_CONFSTR) && !HAVE_DECL_CONFSTR
24extern size_t confstr __P((int, char *, size_t));
25#endif
26
27extern int subshell_environment;
28
29static void restore_path __P((char *));
30static char *get_standard_path __P((void));
31
32/* Run the commands mentioned in LIST without paying attention to shell
33   functions. */
34int
35command_builtin (list)
36     WORD_LIST *list;
37{
38  int result, verbose, use_standard_path, opt;
39  char *old_path, *standard_path;
40  COMMAND *command;
41
42  verbose = use_standard_path = 0;
43  reset_internal_getopt ();
44  while ((opt = internal_getopt (list, "pvV")) != -1)
45    {
46      switch (opt)
47	{
48	case 'p':
49	  use_standard_path = 1;
50	  break;
51	case 'V':
52	  verbose = CDESC_SHORTDESC|CDESC_ABSPATH;	/* look in common.h for constants */
53	  break;
54	case 'v':
55	  verbose = CDESC_REUSABLE;	/* ditto */
56	  break;
57	default:
58	  builtin_usage ();
59	  return (EX_USAGE);
60	}
61    }
62  list = loptend;
63
64  if (list == 0)
65    return (EXECUTION_SUCCESS);
66
67  if (verbose)
68    {
69      int found, any_found;
70
71      for (any_found = 0; list; list = list->next)
72	{
73	  found = describe_command (list->word->word, verbose);
74
75	  if (found == 0 && verbose != CDESC_REUSABLE)
76	    sh_notfound (list->word->word);
77
78	  any_found += found;
79	}
80      return (any_found ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
81    }
82
83#if defined (RESTRICTED_SHELL)
84  if (use_standard_path && restricted)
85    {
86      sh_restricted ("-p");
87      return (EXECUTION_FAILURE);
88    }
89#endif
90
91  begin_unwind_frame ("command_builtin");
92
93  /* We don't want this to be reparsed (consider command echo 'foo &'), so
94     just make a simple_command structure and call execute_command with it. */
95  if (use_standard_path)
96    {
97      old_path = get_string_value ("PATH");
98      /* If old_path is NULL, $PATH is unset.  If so, we want to make sure
99	 it's unset after this command completes. */
100      if (old_path)
101	old_path = savestring (old_path);
102      add_unwind_protect ((Function *)restore_path, old_path);
103
104      standard_path = get_standard_path ();
105      bind_variable ("PATH", standard_path ? standard_path : "", 0);
106      FREE (standard_path);
107    }
108
109#define COMMAND_BUILTIN_FLAGS (CMD_NO_FUNCTIONS | CMD_INHIBIT_EXPANSION | CMD_COMMAND_BUILTIN)
110
111  command = make_bare_simple_command ();
112  command->value.Simple->words = (WORD_LIST *)copy_word_list (list);
113  command->value.Simple->redirects = (REDIRECT *)NULL;
114  command->flags |= COMMAND_BUILTIN_FLAGS;
115  command->value.Simple->flags |= COMMAND_BUILTIN_FLAGS;
116#if 0
117  /* This breaks for things like ( cd /tmp ; command z ababa ; echo next )
118     or $(command echo a ; command echo b;) or even
119     { command echo a; command echo b; } & */
120  /* If we're in a subshell, see if we can get away without forking
121     again, since we've already forked to run this builtin. */
122  if (subshell_environment)
123    {
124      command->flags |= CMD_NO_FORK;
125      command->value.Simple->flags |= CMD_NO_FORK;
126    }
127#endif
128  add_unwind_protect ((char *)dispose_command, command);
129  result = execute_command (command);
130
131  run_unwind_frame ("command_builtin");
132
133  return (result);
134}
135
136/* Restore the value of the $PATH variable after replacing it when
137   executing `command -p'. */
138static void
139restore_path (var)
140     char *var;
141{
142  if (var)
143    {
144      bind_variable ("PATH", var, 0);
145      free (var);
146    }
147  else
148    unbind_variable ("PATH");
149}
150
151/* Return a value for PATH that is guaranteed to find all of the standard
152   utilities.  This uses Posix.2 configuration variables, if present.  It
153   uses a value defined in config.h as a last resort. */
154static char *
155get_standard_path ()
156{
157#if defined (_CS_PATH) && defined (HAVE_CONFSTR)
158  char *p;
159  size_t len;
160
161  len = (size_t)confstr (_CS_PATH, (char *)NULL, (size_t)0);
162  if (len > 0)
163    {
164      p = (char *)xmalloc (len + 2);
165      *p = '\0';
166      confstr (_CS_PATH, p, len);
167      return (p);
168    }
169  else
170    return (savestring (STANDARD_UTILS_PATH));
171#else /* !_CS_PATH || !HAVE_CONFSTR  */
172#  if defined (CS_PATH)
173  return (savestring (CS_PATH));
174#  else
175  return (savestring (STANDARD_UTILS_PATH));
176#  endif /* !CS_PATH */
177#endif /* !_CS_PATH || !HAVE_CONFSTR */
178}
179