Add meta to free routine
[dragonfly.git] / usr.bin / make / shell.c
1 /*-
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
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * Adam de Boor.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
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.
26  *
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
37  * SUCH DAMAGE.
38  *
39  * $DragonFly: src/usr.bin/make/shell.c,v 1.17 2005/06/16 20:29:23 okumoto Exp $
40  */
41
42 #include <string.h>
43 #include <stdlib.h>
44
45 #include "make.h"
46 #include "parse.h"
47 #include "pathnames.h"
48 #include "shell.h"
49 #include "str.h"
50 #include "util.h"
51
52 struct Shell    *commandShell = NULL;
53
54 /**
55  * Find a matching shell in 'shells' given its final component.
56  *
57  * Descriptions for various shells. What the list of builtins should contain
58  * is debatable: either all builtins or only those which may specified on
59  * a single line without use of meta-characters. For correct makefiles that
60  * contain only correct command lines there is no difference. But if a command
61  * line, for example, is: 'if -foo bar' and there is an executable named 'if'
62  * in the path, the first possibility would execute that 'if' while in the
63  * second case the shell would give an error. Histerically only a small
64  * subset of the builtins and no reserved words where given in the list which
65  * corresponds roughly to the first variant. So go with this but add missing
66  * words.
67  *
68  * @result
69  *      A pointer to a Shell structure, or NULL if no shell with
70  *      the given name is found.
71  */
72 static struct Shell *
73 ShellMatch(const char name[])
74 {
75         struct Shell    *shell;
76         const char      *shellDir = PATH_DEFSHELLDIR;
77
78         shell = emalloc(sizeof(struct Shell));
79
80         if (strcmp(name, "csh") == 0) {
81                 /*
82                  * CSH description. The csh can do echo control by playing
83                  * with the setting of the 'echo' shell variable. Sadly,
84                  * however, it is unable to do error control nicely.
85                  */
86                 shell->name             = strdup(name);
87                 shell->path             = str_concat(shellDir, '/', name);
88                 shell->hasEchoCtl       = TRUE;
89                 shell->echoOff          = strdup("unset verbose");
90                 shell->echoOn           = strdup("set verbose");
91                 shell->noPrint          = strdup("unset verbose");
92                 shell->hasErrCtl        = FALSE;
93                 shell->errCheck         = strdup("echo \"%s\"\n");
94                 shell->ignErr           = strdup("csh -c \"%s || exit 0\"");
95                 shell->echo             = strdup("v");
96                 shell->exit             = strdup("e");
97                 shell->meta             = strdup("#=|^(){};&<>*?[]:$`\\@\n");
98                 brk_string(&shell->builtins,
99                     "alias cd eval exec exit read set ulimit unalias "
100                     "umask unset wait", TRUE);
101
102         } else if (strcmp(name, "sh") == 0) {
103                 /*
104                  * SH description. Echo control is also possible and, under
105                  * sun UNIX anyway, one can even control error checking.
106                  */
107
108                 shell->name             = strdup(name);
109                 shell->path             = str_concat(shellDir, '/', name);
110                 shell->hasEchoCtl       = TRUE;
111                 shell->echoOff          = strdup("set -");
112                 shell->echoOn           = strdup("set -v");
113                 shell->noPrint          = strdup("set -");
114 #ifdef OLDBOURNESHELL
115                 shell->hasErrCtl        = FALSE;
116                 shell->errCheck         = strdup("echo \"%s\"\n");
117                 shell->ignErr           = strdup("sh -c '%s || exit 0'\n");
118 #else
119                 shell->hasErrCtl        = TRUE;
120                 shell->errCheck         = strdup("set -e");
121                 shell->ignErr           = strdup("set +e");
122 #endif
123                 shell->echo             = strdup("v");
124                 shell->exit             = strdup("e");
125                 shell->meta             = strdup("#=|^(){};&<>*?[]:$`\\\n");
126                 brk_string(&shell->builtins,
127                     "alias cd eval exec exit read set ulimit unalias "
128                     "umask unset wait", TRUE);
129
130         } else if (strcmp(name, "ksh") == 0) {
131                 /*
132                  * KSH description. The Korn shell has a superset of
133                  * the Bourne shell's functionality.  There are probably
134                  * builtins missing here.
135                  */
136                 shell->name             = strdup(name);
137                 shell->path             = str_concat(shellDir, '/', name);
138                 shell->hasEchoCtl       = TRUE;
139                 shell->echoOff          = strdup("set -");
140                 shell->echoOn           = strdup("set -v");
141                 shell->noPrint          = strdup("set -");
142                 shell->hasErrCtl        = TRUE;
143                 shell->errCheck         = strdup("set -e");
144                 shell->ignErr           = strdup("set +e");
145                 shell->echo             = strdup("v");
146                 shell->exit             = strdup("e");
147                 shell->meta             = strdup("#=|^(){};&<>*?[]:$`\\\n");
148                 brk_string(&shell->builtins,
149                     "alias cd eval exec exit read set ulimit unalias "
150                     "umask unset wait", TRUE);
151
152         } else {
153                 free(shell);
154                 shell = NULL;
155         }
156
157         return (shell);
158 }
159
160 /**
161  * Free a shell structure and all associated strings.
162  */
163 static void
164 ShellFree(struct Shell *sh)
165 {
166
167         if (sh != NULL) {
168                 free(sh->name);
169                 free(sh->path);
170                 free(sh->echoOff);
171                 free(sh->echoOn);
172                 free(sh->noPrint);
173                 free(sh->errCheck);
174                 free(sh->ignErr);
175                 free(sh->echo);
176                 free(sh->exit);
177                 ArgArray_Done(&sh->builtins);
178                 free(sh->meta);
179                 free(sh);
180         }
181 }
182
183 static int
184 sort_builtins(const void *p1, const void *p2)
185 {
186         return (strcmp(*(const char* const*)p1, *(const char* const*)p2));
187 }
188
189 /**
190  * Parse a shell specification line and return the new Shell structure.
191  * In case of an error a message is printed and NULL is returned.
192  */
193 static struct Shell *
194 ShellParseSpec(const char *spec, Boolean *fullSpec)
195 {
196         ArgArray        aa;
197         struct Shell    *sh;
198         char            *eq;
199         char            *keyw;
200         int             arg;
201
202         *fullSpec = FALSE;
203
204         sh = emalloc(sizeof(*sh));
205         memset(sh, 0, sizeof(*sh));
206         ArgArray_Init(&sh->builtins);
207
208         /*
209          * Parse the specification by keyword but skip the first word
210          */
211         brk_string(&aa, spec, TRUE);
212
213         for (arg = 1; arg < aa.argc; arg++) {
214                 /*
215                  * Split keyword and value
216                  */
217                 keyw = aa.argv[arg];
218                 if ((eq = strchr(keyw, '=')) == NULL) {
219                         Parse_Error(PARSE_FATAL, "missing '=' in shell "
220                             "specification keyword '%s'", keyw);
221                         ArgArray_Done(&aa);
222                         ShellFree(sh);
223                         return (NULL);
224                 }
225                 *eq++ = '\0';
226
227                 if (strcmp(keyw, "path") == 0) {
228                         free(sh->path);
229                         sh->path = estrdup(eq);
230                 } else if (strcmp(keyw, "name") == 0) {
231                         free(sh->name);
232                         sh->name = estrdup(eq);
233                 } else if (strcmp(keyw, "quiet") == 0) {
234                         free(sh->echoOff);
235                         sh->echoOff = estrdup(eq);
236                         *fullSpec = TRUE;
237                 } else if (strcmp(keyw, "echo") == 0) {
238                         free(sh->echoOn);
239                         sh->echoOn = estrdup(eq);
240                         *fullSpec = TRUE;
241                 } else if (strcmp(keyw, "filter") == 0) {
242                         free(sh->noPrint);
243                         sh->noPrint = estrdup(eq);
244                         *fullSpec = TRUE;
245                 } else if (strcmp(keyw, "echoFlag") == 0) {
246                         free(sh->echo);
247                         sh->echo = estrdup(eq);
248                         *fullSpec = TRUE;
249                 } else if (strcmp(keyw, "errFlag") == 0) {
250                         free(sh->exit);
251                         sh->exit = estrdup(eq);
252                         *fullSpec = TRUE;
253                 } else if (strcmp(keyw, "hasErrCtl") == 0) {
254                         sh->hasErrCtl = (*eq == 'Y' || *eq == 'y' ||
255                             *eq == 'T' || *eq == 't');
256                         *fullSpec = TRUE;
257                 } else if (strcmp(keyw, "check") == 0) {
258                         free(sh->errCheck);
259                         sh->errCheck = estrdup(eq);
260                         *fullSpec = TRUE;
261                 } else if (strcmp(keyw, "ignore") == 0) {
262                         free(sh->ignErr);
263                         sh->ignErr = estrdup(eq);
264                         *fullSpec = TRUE;
265                 } else if (strcmp(keyw, "builtins") == 0) {
266                         ArgArray_Done(&sh->builtins);
267                         brk_string(&sh->builtins, eq, TRUE);
268                         qsort(sh->builtins.argv + 1, sh->builtins.argc - 1,
269                             sizeof(char *), sort_builtins);
270                         *fullSpec = TRUE;
271                 } else if (strcmp(keyw, "meta") == 0) {
272                         free(sh->meta);
273                         sh->meta = estrdup(eq);
274                         *fullSpec = TRUE;
275                 } else {
276                         Parse_Error(PARSE_FATAL, "unknown keyword in shell "
277                             "specification '%s'", keyw);
278                         ArgArray_Done(&aa);
279                         ShellFree(sh);
280                         return (NULL);
281                 }
282         }
283         ArgArray_Done(&aa);
284
285         /*
286          * Some checks (could be more)
287          */
288         if (*fullSpec) {
289                 if ((sh->echoOn != NULL) ^ (sh->echoOff != NULL)) {
290                         Parse_Error(PARSE_FATAL, "Shell must have either both "
291                             "echoOff and echoOn or none of them");
292                         ShellFree(sh);
293                         return (NULL);
294                 }
295
296                 if (sh->echoOn != NULL && sh->echoOff != NULL)
297                         sh->hasEchoCtl = TRUE;
298         }
299
300         return (sh);
301 }
302
303 /**
304  * Given the line following a .SHELL target, parse the
305  * line as a shell specification. Returns FALSE if the
306  * spec was incorrect.
307  *
308  * Parse a shell specification and set up commandShell.
309  *
310  * Results:
311  *      TRUE if the specification was correct. FALSE otherwise.
312  *
313  * Side Effects:
314  *      commandShell points to a Shell structure (either predefined or
315  *      created from the shell spec)
316  *
317  * Notes:
318  *      A shell specification consists of a .SHELL target, with dependency
319  *      operator, followed by a series of blank-separated words. Double
320  *      quotes can be used to use blanks in words. A backslash escapes
321  *      anything (most notably a double-quote and a space) and
322  *      provides the functionality it does in C. Each word consists of
323  *      keyword and value separated by an equal sign. There should be no
324  *      unnecessary spaces in the word. The keywords are as follows:
325  *          name            Name of shell.
326  *          path            Location of shell. Overrides "name" if given
327  *          quiet           Command to turn off echoing.
328  *          echo            Command to turn echoing on
329  *          filter          Result of turning off echoing that shouldn't be
330  *                          printed.
331  *          echoFlag        Flag to turn echoing on at the start
332  *          errFlag         Flag to turn error checking on at the start
333  *          hasErrCtl       True if shell has error checking control
334  *          check           Command to turn on error checking if hasErrCtl
335  *                          is TRUE or template of command to echo a command
336  *                          for which error checking is off if hasErrCtl is
337  *                          FALSE.
338  *          ignore          Command to turn off error checking if hasErrCtl
339  *                          is TRUE or template of command to execute a
340  *                          command so as to ignore any errors it returns if
341  *                          hasErrCtl is FALSE.
342  *          builtins        A space separated list of builtins. If one
343  *                          of these builtins is detected when make wants
344  *                          to execute a command line, the command line is
345  *                          handed to the shell. Otherwise make may try to
346  *                          execute the command directly. If this list is empty
347  *                          it is assumed, that the command must always be
348  *                          handed over to the shell.
349  *          meta            The shell meta characters. If this is not specified
350  *                          or empty, commands are alway passed to the shell.
351  *                          Otherwise they are not passed when they contain
352  *                          neither a meta character nor a builtin command.
353  */
354 Boolean
355 Shell_Parse(const char line[])
356 {
357         Boolean         fullSpec;
358         struct Shell    *sh;
359
360         /* parse the specification */
361         if ((sh = ShellParseSpec(line, &fullSpec)) == NULL)
362                 return (FALSE);
363
364         if (sh->path == NULL) {
365                 struct Shell    *match;
366                 /*
367                  * If no path was given, the user wants one of the pre-defined
368                  * shells, yes? So we find the one s/he wants with the help of
369                  * ShellMatch and set things up the right way.
370                  */
371                 if (sh->name == NULL) {
372                         Parse_Error(PARSE_FATAL,
373                             "Neither path nor name specified");
374                         ShellFree(sh);
375                         return (FALSE);
376                 }
377                 if (fullSpec) {
378                         Parse_Error(PARSE_FATAL, "No path specified");
379                         ShellFree(sh);
380                         return (FALSE);
381                 }
382                 if ((match = ShellMatch(sh->name)) == NULL) {
383                         Parse_Error(PARSE_FATAL, "%s: no matching shell",
384                             sh->name);
385                         ShellFree(sh);
386                         return (FALSE);
387                 }
388                 ShellFree(sh);
389                 sh = match;
390
391         } else {
392                 /*
393                  * The user provided a path. If s/he gave nothing else
394                  * (fullSpec is FALSE), try and find a matching shell in the
395                  * ones we know of. Else we just take the specification at its
396                  * word and copy it to a new location. In either case, we need
397                  * to record the path the user gave for the shell.
398                  */
399                 if (sh->name == NULL) {
400                         /* get the base name as the name */
401                         if ((sh->name = strrchr(sh->path, '/')) == NULL) {
402                                 sh->name = estrdup(sh->path);
403                         } else {
404                                 sh->name = estrdup(sh->name + 1);
405                         }
406                 }
407
408                 if (!fullSpec) {
409                         struct Shell    *match;
410
411                         if ((match = ShellMatch(sh->name)) == NULL) {
412                                 Parse_Error(PARSE_FATAL,
413                                     "%s: no matching shell", sh->name);
414                                 ShellFree(sh);
415                                 return (FALSE);
416                         }
417                         free(match->path);
418                         match->path = sh->path;
419                         sh->path = NULL;
420                         ShellFree(sh);
421                         sh = match;
422                 }
423         }
424
425         /* Release the old shell and set the new shell */
426         ShellFree(commandShell);
427         commandShell = sh;
428
429         return (TRUE);
430 }
431
432 void
433 Shell_Init(void)
434 {
435         commandShell = ShellMatch(DEFSHELLNAME);
436 }
437
438 /**
439  * Dump a shell specification to stderr.
440  */
441 void
442 Shell_Dump(const struct Shell *sh)
443 {
444         int i;
445
446         fprintf(stderr, "Shell %p:\n", sh);
447         fprintf(stderr, "  name='%s' path='%s'\n", sh->name, sh->path);
448         fprintf(stderr, "  hasEchoCtl=%d echoOff='%s' echoOn='%s'\n",
449             sh->hasEchoCtl, sh->echoOff, sh->echoOn);
450         fprintf(stderr, "  noPrint='%s'\n", sh->noPrint);
451         fprintf(stderr, "  hasErrCtl=%d errCheck='%s' ignErr='%s'\n",
452             sh->hasErrCtl, sh->errCheck, sh->ignErr);
453         fprintf(stderr, "  echo='%s' exit='%s'\n", sh->echo, sh->exit);
454         fprintf(stderr, "  builtins=%d\n", sh->builtins.argc - 1);
455         for (i = 1; i < sh->builtins.argc; i++)
456                 fprintf(stderr, " '%s'", sh->builtins.argv[i]);
457         fprintf(stderr, "\n  meta='%s'\n", sh->meta);
458 }
459