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.13 2005/06/15 18:01:47 okumoto Exp $
47 #include "pathnames.h"
52 struct Shell *commandShell = NULL;
55 * Find a matching shell in 'shells' given its final component.
58 * A pointer to a Shell structure, or NULL if no shell with
59 * the given name is found.
62 ShellMatch(const char name[])
65 const char *shellDir = PATH_DEFSHELLDIR;
67 shell = emalloc(sizeof(struct Shell));
69 if (strcmp(name, "csh") == 0) {
71 * CSH description. The csh can do echo control by playing
72 * with the setting of the 'echo' shell variable. Sadly,
73 * however, it is unable to do error control nicely.
75 shell->name = strdup(name);
76 shell->path = str_concat(shellDir, '/', name);
77 shell->hasEchoCtl = TRUE;
78 shell->echoOff = strdup("unset verbose");
79 shell->echoOn = strdup("set verbose");
80 shell->noPrint = strdup("unset verbose");
81 shell->hasErrCtl = FALSE;
82 shell->errCheck = strdup("echo \"%s\"\n");
83 shell->ignErr = strdup("csh -c \"%s || exit 0\"");
84 shell->echo = strdup("v");
85 shell->exit = strdup("e");
87 } else if (strcmp(name, "sh") == 0) {
89 * SH description. Echo control is also possible and, under
90 * sun UNIX anyway, one can even control error checking.
93 shell->name = strdup(name);
94 shell->path = str_concat(shellDir, '/', name);
95 shell->hasEchoCtl = TRUE;
96 shell->echoOff = strdup("set -");
97 shell->echoOn = strdup("set -v");
98 shell->noPrint = strdup("set -");
100 shell->hasErrCtl = FALSE;
101 shell->errCheck = strdup("echo \"%s\"\n");
102 shell->ignErr = strdup("sh -c '%s || exit 0'\n");
104 shell->hasErrCtl = TRUE;
105 shell->errCheck = strdup("set -e");
106 shell->ignErr = strdup("set +e");
108 shell->echo = strdup("v");
109 shell->exit = strdup("e");
110 } else if (strcmp(name, "ksh") == 0) {
112 * KSH description. The Korn shell has a superset of
113 * the Bourne shell's functionality.
115 shell->name = strdup(name);
116 shell->path = str_concat(shellDir, '/', name);
117 shell->hasEchoCtl = TRUE;
118 shell->echoOff = strdup("set -");
119 shell->echoOn = strdup("set -v");
120 shell->noPrint = strdup("set -");
121 shell->hasErrCtl = TRUE;
122 shell->errCheck = strdup("set -e");
123 shell->ignErr = strdup("set +e");
124 shell->echo = strdup("v");
125 shell->exit = strdup("e");
135 * Make a new copy of the shell structure including a copy of the strings
136 * in it. This also defaults some fields in case they are NULL.
139 * The function returns a pointer to the new shell structure.
141 static struct Shell *
142 ShellCopy(const struct Shell *o)
146 n = emalloc(sizeof(struct Shell));
147 n->name = estrdup(o->name);
148 n->path = estrdup(o->path);
149 n->hasEchoCtl = o->hasEchoCtl;
150 n->echoOff = o->echoOff ? estrdup(o->echoOff) : NULL;
151 n->echoOn = o->echoOn ? estrdup(o->echoOn) : NULL;
152 n->noPrint = o->noPrint ? estrdup(o->noPrint) : NULL;
153 n->hasErrCtl = o->hasErrCtl;
154 n->errCheck = o->errCheck ? estrdup(o->errCheck) : estrdup("");
155 n->ignErr = o->ignErr ? estrdup(o->ignErr) : estrdup("%s");
156 n->echo = o->echo ? estrdup(o->echo) : estrdup("");
157 n->exit = o->exit ? estrdup(o->exit) : estrdup("");
163 * Free a shell structure and all associated strings.
166 ShellFree(struct Shell *sh)
184 * Given the line following a .SHELL target, parse the
185 * line as a shell specification. Returns FALSE if the
186 * spec was incorrect.
188 * Parse a shell specification and set up commandShell.
191 * TRUE if the specification was correct. FALSE otherwise.
194 * commandShell points to a Shell structure (either predefined or
195 * created from the shell spec)
198 * A shell specification consists of a .SHELL target, with dependency
199 * operator, followed by a series of blank-separated words. Double
200 * quotes can be used to use blanks in words. A backslash escapes
201 * anything (most notably a double-quote and a space) and
202 * provides the functionality it does in C. Each word consists of
203 * keyword and value separated by an equal sign. There should be no
204 * unnecessary spaces in the word. The keywords are as follows:
205 * name Name of shell.
206 * path Location of shell. Overrides "name" if given
207 * quiet Command to turn off echoing.
208 * echo Command to turn echoing on
209 * filter Result of turning off echoing that shouldn't be
211 * echoFlag Flag to turn echoing on at the start
212 * errFlag Flag to turn error checking on at the start
213 * hasErrCtl True if shell has error checking control
214 * check Command to turn on error checking if hasErrCtl
215 * is TRUE or template of command to echo a command
216 * for which error checking is off if hasErrCtl is
218 * ignore Command to turn off error checking if hasErrCtl
219 * is TRUE or template of command to execute a
220 * command so as to ignore any errors it returns if
221 * hasErrCtl is FALSE.
224 Shell_Parse(const char line[])
229 Boolean fullSpec = FALSE;
230 struct Shell newShell;
233 memset(&newShell, 0, sizeof(newShell));
236 * Parse the specification by keyword but skip the first word
238 brk_string(&aa, line, TRUE);
240 for (argc = aa.argc - 1, argv = aa.argv + 1; argc != 0; argc--, argv++)
245 * Split keyword and value
247 if ((eq = strchr(*argv, '=')) == NULL) {
248 Parse_Error(PARSE_FATAL,
249 "missing '=' in shell specification keyword '%s'",
256 if (strcmp(*argv, "path") == 0) {
258 } else if (strcmp(*argv, "name") == 0) {
260 } else if (strcmp(*argv, "quiet") == 0) {
261 newShell.echoOff = eq;
263 } else if (strcmp(*argv, "echo") == 0) {
264 newShell.echoOn = eq;
266 } else if (strcmp(*argv, "filter") == 0) {
267 newShell.noPrint = eq;
269 } else if (strcmp(*argv, "echoFlag") == 0) {
272 } else if (strcmp(*argv, "errFlag") == 0) {
275 } else if (strcmp(*argv, "hasErrCtl") == 0) {
276 newShell.hasErrCtl = (*eq == 'Y' || *eq == 'y' ||
277 *eq == 'T' || *eq == 't');
279 } else if (strcmp(*argv, "check") == 0) {
280 newShell.errCheck = eq;
282 } else if (strcmp(*argv, "ignore") == 0) {
283 newShell.ignErr = eq;
286 Parse_Error(PARSE_FATAL,
287 "unknown keyword in shell specification '%s'",
295 * Some checks (could be more)
298 if ((newShell.echoOn != NULL) ^ (newShell.echoOff != NULL))
299 Parse_Error(PARSE_FATAL,
300 "Shell must have either both "
301 "echoOff and echoOn or none of them");
303 if (newShell.echoOn != NULL && newShell.echoOff)
304 newShell.hasEchoCtl = TRUE;
307 if (newShell.path == NULL) {
309 * If no path was given, the user wants one of the pre-defined
310 * shells, yes? So we find the one s/he wants with the help of
311 * ShellMatch and set things up the right way.
313 if (newShell.name == NULL) {
314 Parse_Error(PARSE_FATAL,
315 "Neither path nor name specified");
319 if ((sh = ShellMatch(newShell.name)) == NULL) {
320 Parse_Error(PARSE_FATAL, "%s: no matching shell",
328 * The user provided a path. If s/he gave nothing else
329 * (fullSpec is FALSE), try and find a matching shell in the
330 * ones we know of. Else we just take the specification at its
331 * word and copy it to a new location. In either case, we need
332 * to record the path the user gave for the shell.
334 if (newShell.name == NULL) {
335 /* get the base name as the name */
336 newShell.name = strrchr(newShell.path, '/');
337 if (newShell.name == NULL) {
338 newShell.name = newShell.path;
345 if ((sh = ShellMatch(newShell.name)) == NULL) {
346 Parse_Error(PARSE_FATAL,
347 "%s: no matching shell", newShell.name);
352 sh = ShellCopy(&newShell);
356 /* Release the old shell and set the new shell */
357 ShellFree(commandShell);
367 commandShell = ShellMatch(DEFSHELLNAME);