2 * Copyright (c) 1988, 1989, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 1988, 1989 by Adam de Boor
5 * Copyright (c) 1989 by Berkeley Softworks
8 * This code is derived from software contributed to Berkeley by
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * $DragonFly: src/usr.bin/make/shell.c,v 1.24 2005/09/17 11:07:23 okumoto Exp $
47 #include "pathnames.h"
52 struct Shell *commandShell = NULL;
55 * Helper function for sorting the builtin list alphabetically.
58 sort_builtins(const void *p1, const void *p2)
60 return (strcmp(*(const char* const*)p1, *(const char* const*)p2));
64 * Free a shell structure and all associated strings.
67 Shell_Destroy(Shell *sh)
79 ArgArray_Done(&sh->builtins);
86 * Dump a shell specification to stderr.
89 Shell_Dump(const Shell *sh)
93 fprintf(stderr, "Shell %p:\n", sh);
94 fprintf(stderr, " name='%s' path='%s'\n", sh->name, sh->path);
95 fprintf(stderr, " hasEchoCtl=%d echoOff='%s' echoOn='%s'\n",
96 sh->hasEchoCtl, sh->echoOff, sh->echoOn);
97 fprintf(stderr, " noPrint='%s'\n", sh->noPrint);
98 fprintf(stderr, " hasErrCtl=%d errCheck='%s' ignErr='%s'\n",
99 sh->hasErrCtl, sh->errCheck, sh->ignErr);
100 fprintf(stderr, " echo='%s' exit='%s'\n", sh->echo, sh->exit);
101 fprintf(stderr, " builtins=%d\n", sh->builtins.argc - 1);
102 for (i = 1; i < sh->builtins.argc; i++)
103 fprintf(stderr, " '%s'", sh->builtins.argv[i]);
104 fprintf(stderr, "\n meta='%s'\n", sh->meta);
105 fprintf(stderr, " unsetenv=%d\n", sh->unsetenv);
109 * Parse a shell specification line and return the new Shell structure.
110 * In case of an error a message is printed and NULL is returned.
113 * A shell specification consists of a .SHELL target, with dependency
114 * operator, followed by a series of blank-separated words. Double
115 * quotes can be used to use blanks in words. A backslash escapes
116 * anything (most notably a double-quote and a space) and
117 * provides the functionality it does in C. Each word consists of
118 * keyword and value separated by an equal sign. There should be no
119 * unnecessary spaces in the word. The keywords are as follows:
120 * name Name of shell.
121 * path Location of shell. Overrides "name" if given
122 * quiet Command to turn off echoing.
123 * echo Command to turn echoing on
124 * filter Result of turning off echoing that shouldn't be
126 * echoFlag Flag to turn echoing on at the start
127 * errFlag Flag to turn error checking on at the start
128 * hasErrCtl True if shell has error checking control
129 * check Command to turn on error checking if hasErrCtl
130 * is true or template of command to echo a command
131 * for which error checking is off if hasErrCtl is
133 * ignore Command to turn off error checking if hasErrCtl
134 * is true or template of command to execute a
135 * command so as to ignore any errors it returns if
136 * hasErrCtl is false.
137 * builtins A space separated list of builtins. If one
138 * of these builtins is detected when make wants
139 * to execute a command line, the command line is
140 * handed to the shell. Otherwise make may try to
141 * execute the command directly. If this list is empty
142 * it is assumed, that the command must always be
143 * handed over to the shell.
144 * meta The shell meta characters. If this is not specified
145 * or empty, commands are alway passed to the shell.
146 * Otherwise they are not passed when they contain
147 * neither a meta character nor a builtin command.
150 ShellParseSpec(const char spec[], bool *fullSpec)
160 sh = emalloc(sizeof(*sh));
161 memset(sh, 0, sizeof(*sh));
162 ArgArray_Init(&sh->builtins);
165 * Parse the specification by keyword but skip the first word
167 brk_string(&aa, spec, true);
169 for (arg = 1; arg < aa.argc; arg++) {
171 * Split keyword and value
174 if ((eq = strchr(keyw, '=')) == NULL) {
175 Parse_Error(PARSE_FATAL, "missing '=' in shell "
176 "specification keyword '%s'", keyw);
183 if (strcmp(keyw, "path") == 0) {
185 sh->path = estrdup(eq);
186 } else if (strcmp(keyw, "name") == 0) {
188 sh->name = estrdup(eq);
189 } else if (strcmp(keyw, "quiet") == 0) {
191 sh->echoOff = estrdup(eq);
193 } else if (strcmp(keyw, "echo") == 0) {
195 sh->echoOn = estrdup(eq);
197 } else if (strcmp(keyw, "filter") == 0) {
199 sh->noPrint = estrdup(eq);
201 } else if (strcmp(keyw, "echoFlag") == 0) {
203 sh->echo = estrdup(eq);
205 } else if (strcmp(keyw, "errFlag") == 0) {
207 sh->exit = estrdup(eq);
209 } else if (strcmp(keyw, "hasErrCtl") == 0) {
211 *eq == 'Y' || *eq == 'y' ||
212 *eq == 'T' || *eq == 't');
214 } else if (strcmp(keyw, "check") == 0) {
216 sh->errCheck = estrdup(eq);
218 } else if (strcmp(keyw, "ignore") == 0) {
220 sh->ignErr = estrdup(eq);
222 } else if (strcmp(keyw, "builtins") == 0) {
223 ArgArray_Done(&sh->builtins);
224 brk_string(&sh->builtins, eq, true);
225 qsort(sh->builtins.argv + 1, sh->builtins.argc - 1,
226 sizeof(char *), sort_builtins);
228 } else if (strcmp(keyw, "meta") == 0) {
230 sh->meta = estrdup(eq);
232 } else if (strcmp(keyw, "unsetenv") == 0) {
234 *eq == 'Y' || *eq == 'y' ||
235 *eq == 'T' || *eq == 't');
238 Parse_Error(PARSE_FATAL, "unknown keyword in shell "
239 "specification '%s'", keyw);
248 * Some checks (could be more)
251 if ((sh->echoOn != NULL) ^ (sh->echoOff != NULL)) {
252 Parse_Error(PARSE_FATAL, "Shell must have either both "
253 "echoOff and echoOn or none of them");
258 if (sh->echoOn != NULL && sh->echoOff != NULL)
259 sh->hasEchoCtl = true;
266 * Find a matching shell in 'shells' given its final component.
268 * Descriptions for various shells. What the list of builtins should contain
269 * is debatable: either all builtins or only those which may specified on
270 * a single line without use of meta-characters. For correct makefiles that
271 * contain only correct command lines there is no difference. But if a command
272 * line, for example, is: 'if -foo bar' and there is an executable named 'if'
273 * in the path, the first possibility would execute that 'if' while in the
274 * second case the shell would give an error. Histerically only a small
275 * subset of the builtins and no reserved words where given in the list which
276 * corresponds roughly to the first variant. So go with this but add missing
280 * A pointer to a Shell structure, or NULL if no shell with
281 * the given name is found.
284 Shell_Match(const char name[])
287 const char *shellDir = PATH_DEFSHELLDIR;
289 shell = emalloc(sizeof(Shell));
291 if (strcmp(name, "csh") == 0) {
293 * CSH description. The csh can do echo control by playing
294 * with the setting of the 'echo' shell variable. Sadly,
295 * however, it is unable to do error control nicely.
297 shell->name = strdup(name);
298 shell->path = str_concat(shellDir, '/', name);
299 shell->hasEchoCtl = true;
300 shell->echoOff = strdup("unset verbose");
301 shell->echoOn = strdup("set verbose");
302 shell->noPrint = strdup("unset verbose");
303 shell->hasErrCtl = false;
304 shell->errCheck = strdup("echo \"%s\"\n");
305 shell->ignErr = strdup("csh -c \"%s || exit 0\"");
306 shell->echo = strdup("v");
307 shell->exit = strdup("e");
308 shell->meta = strdup("#=|^(){};&<>*?[]:$`\\@\n");
309 brk_string(&shell->builtins,
310 "alias cd eval exec exit read set ulimit unalias "
311 "umask unset wait", true);
312 shell->unsetenv = false;
314 } else if (strcmp(name, "sh") == 0) {
316 * SH description. Echo control is also possible and, under
317 * sun UNIX anyway, one can even control error checking.
320 shell->name = strdup(name);
321 shell->path = str_concat(shellDir, '/', name);
322 shell->hasEchoCtl = true;
323 shell->echoOff = strdup("set -");
324 shell->echoOn = strdup("set -v");
325 shell->noPrint = strdup("set -");
326 #ifdef OLDBOURNESHELL
327 shell->hasErrCtl = false;
328 shell->errCheck = strdup("echo \"%s\"\n");
329 shell->ignErr = strdup("sh -c '%s || exit 0'\n");
331 shell->hasErrCtl = true;
332 shell->errCheck = strdup("set -e");
333 shell->ignErr = strdup("set +e");
335 shell->echo = strdup("v");
336 shell->exit = strdup("e");
337 shell->meta = strdup("#=|^(){};&<>*?[]:$`\\\n");
338 brk_string(&shell->builtins,
339 "alias cd eval exec exit read set ulimit unalias "
340 "umask unset wait", true);
341 shell->unsetenv = false;
343 } else if (strcmp(name, "ksh") == 0) {
345 * KSH description. The Korn shell has a superset of
346 * the Bourne shell's functionality. There are probably
347 * builtins missing here.
349 shell->name = strdup(name);
350 shell->path = str_concat(shellDir, '/', name);
351 shell->hasEchoCtl = true;
352 shell->echoOff = strdup("set -");
353 shell->echoOn = strdup("set -v");
354 shell->noPrint = strdup("set -");
355 shell->hasErrCtl = true;
356 shell->errCheck = strdup("set -e");
357 shell->ignErr = strdup("set +e");
358 shell->echo = strdup("v");
359 shell->exit = strdup("e");
360 shell->meta = strdup("#=|^(){};&<>*?[]:$`\\\n");
361 brk_string(&shell->builtins,
362 "alias cd eval exec exit read set ulimit unalias "
363 "umask unset wait", true);
364 shell->unsetenv = true;
375 * Given the line following a .SHELL target, parse it as a shell
379 * A pointer to a Shell structure, or NULL if no the spec was invalid.
382 Shell_Parse(const char line[])
387 /* parse the specification */
388 if ((sh = ShellParseSpec(line, &fullSpec)) == NULL)
391 if (sh->path == NULL) {
394 * If no path was given, the user wants one of the pre-defined
395 * shells, yes? So we find the one s/he wants with the help of
396 * ShellMatch and set things up the right way.
398 if (sh->name == NULL) {
399 Parse_Error(PARSE_FATAL,
400 "Neither path nor name specified");
405 Parse_Error(PARSE_FATAL, "No path specified");
409 if ((match = Shell_Match(sh->name)) == NULL) {
410 Parse_Error(PARSE_FATAL, "%s: no matching shell",
423 * The user provided a path. If s/he gave nothing else
424 * (fullSpec is false), try and find a matching shell in the
425 * ones we know of. Else we just take the specification at its
426 * word and copy it to a new location. In either case, we need
427 * to record the path the user gave for the shell.
429 if (sh->name == NULL) {
430 /* get the base name as the name */
431 if ((sh->name = strrchr(sh->path, '/')) == NULL) {
432 sh->name = estrdup(sh->path);
434 sh->name = estrdup(sh->name + 1);
440 if ((match = Shell_Match(sh->name)) == NULL) {
441 Parse_Error(PARSE_FATAL,
442 "%s: no matching shell", sh->name);
448 match->path = sh->path;