blob: 5a5b74594f0057f834428391b509720ed919ba4a [file] [log] [blame]
Dan Pasanenc6e37862014-10-02 14:08:59 -05001/* command.c, created from command.def. */
2#line 22 "./command.def"
3
4#line 41 "./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 defined (RESTRICTED_SHELL)
68 if (use_standard_path && restricted)
69 {
70 sh_restricted ("-p");
71 return (EXECUTION_FAILURE);
72 }
73#endif
74
75 begin_unwind_frame ("command_builtin");
76
77 if (use_standard_path)
78 {
79 old_path = get_string_value ("PATH");
80 /* If old_path is NULL, $PATH is unset. If so, we want to make sure
81 it's unset after this command completes. */
82 if (old_path)
83 old_path = savestring (old_path);
84 add_unwind_protect ((Function *)restore_path, old_path);
85
86 standard_path = get_standard_path ();
87 bind_variable ("PATH", standard_path ? standard_path : "", 0);
88 stupidly_hack_special_variables ("PATH");
89 FREE (standard_path);
90 }
91
92 if (verbose)
93 {
94 int found, any_found;
95
96 for (any_found = 0; list; list = list->next)
97 {
98 found = describe_command (list->word->word, verbose);
99
100 if (found == 0 && verbose != CDESC_REUSABLE)
101 sh_notfound (list->word->word);
102
103 any_found += found;
104 }
105
106 run_unwind_frame ("command_builtin");
107 return (any_found ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
108 }
109
110#define COMMAND_BUILTIN_FLAGS (CMD_NO_FUNCTIONS | CMD_INHIBIT_EXPANSION | CMD_COMMAND_BUILTIN)
111
112 /* We don't want this to be reparsed (consider command echo 'foo &'), so
113 just make a simple_command structure and call execute_command with it. */
114 command = make_bare_simple_command ();
115 command->value.Simple->words = (WORD_LIST *)copy_word_list (list);
116 command->value.Simple->redirects = (REDIRECT *)NULL;
117 command->flags |= COMMAND_BUILTIN_FLAGS;
118 command->value.Simple->flags |= COMMAND_BUILTIN_FLAGS;
119#if 0
120 /* This breaks for things like ( cd /tmp ; command z ababa ; echo next )
121 or $(command echo a ; command echo b;) or even
122 { command echo a; command echo b; } & */
123 /* If we're in a subshell, see if we can get away without forking
124 again, since we've already forked to run this builtin. */
125 if (subshell_environment)
126 {
127 command->flags |= CMD_NO_FORK;
128 command->value.Simple->flags |= CMD_NO_FORK;
129 }
130#endif
131 add_unwind_protect ((char *)dispose_command, command);
132 result = execute_command (command);
133
134 run_unwind_frame ("command_builtin");
135
136 return (result);
137}
138
139/* Restore the value of the $PATH variable after replacing it when
140 executing `command -p'. */
141static void
142restore_path (var)
143 char *var;
144{
145 if (var)
146 {
147 bind_variable ("PATH", var, 0);
148 free (var);
149 }
150 else
151 unbind_variable ("PATH");
152
153 stupidly_hack_special_variables ("PATH");
154}
155
156/* Return a value for PATH that is guaranteed to find all of the standard
157 utilities. This uses Posix.2 configuration variables, if present. It
158 uses a value defined in config.h as a last resort. */
159static char *
160get_standard_path ()
161{
162#if defined (_CS_PATH) && defined (HAVE_CONFSTR)
163 char *p;
164 size_t len;
165
166 len = (size_t)confstr (_CS_PATH, (char *)NULL, (size_t)0);
167 if (len > 0)
168 {
169 p = (char *)xmalloc (len + 2);
170 *p = '\0';
171 confstr (_CS_PATH, p, len);
172 return (p);
173 }
174 else
175 return (savestring (STANDARD_UTILS_PATH));
176#else /* !_CS_PATH || !HAVE_CONFSTR */
177# if defined (CS_PATH)
178 return (savestring (CS_PATH));
179# else
180 return (savestring (STANDARD_UTILS_PATH));
181# endif /* !CS_PATH */
182#endif /* !_CS_PATH || !HAVE_CONFSTR */
183}