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