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