1146572Sharti/*- 2146572Sharti * Copyright (c) 1988, 1989, 1990, 1993 3146572Sharti * The Regents of the University of California. All rights reserved. 4146572Sharti * Copyright (c) 1988, 1989 by Adam de Boor 5146572Sharti * Copyright (c) 1989 by Berkeley Softworks 6146572Sharti * All rights reserved. 7146572Sharti * 8146572Sharti * This code is derived from software contributed to Berkeley by 9146572Sharti * Adam de Boor. 10146572Sharti * 11146572Sharti * Redistribution and use in source and binary forms, with or without 12146572Sharti * modification, are permitted provided that the following conditions 13146572Sharti * are met: 14146572Sharti * 1. Redistributions of source code must retain the above copyright 15146572Sharti * notice, this list of conditions and the following disclaimer. 16146572Sharti * 2. Redistributions in binary form must reproduce the above copyright 17146572Sharti * notice, this list of conditions and the following disclaimer in the 18146572Sharti * documentation and/or other materials provided with the distribution. 19146572Sharti * 3. All advertising materials mentioning features or use of this software 20146572Sharti * must display the following acknowledgement: 21146572Sharti * This product includes software developed by the University of 22146572Sharti * California, Berkeley and its contributors. 23146572Sharti * 4. Neither the name of the University nor the names of its contributors 24146572Sharti * may be used to endorse or promote products derived from this software 25146572Sharti * without specific prior written permission. 26146572Sharti * 27146572Sharti * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28146572Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29146572Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30146572Sharti * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31146572Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32146572Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33146572Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34146572Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35146572Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36146572Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37146572Sharti * SUCH DAMAGE. 38146572Sharti */ 39146572Sharti 40146572Sharti#include <sys/cdefs.h> 41146572Sharti__FBSDID("$FreeBSD$"); 42146572Sharti 43146572Sharti#include <sys/queue.h> 44146572Sharti#include <stdio.h> 45146572Sharti#include <stdlib.h> 46146572Sharti#include <string.h> 47146572Sharti 48146572Sharti#include "parse.h" 49146572Sharti#include "pathnames.h" 50146572Sharti#include "shell.h" 51146572Sharti#include "util.h" 52146572Sharti 53146572Sharti/* 54146572Sharti * Descriptions for various shells. What the list of builtins should contain 55146572Sharti * is debatable: either all builtins or only those which may specified on 56146572Sharti * a single line without use of meta-characters. For correct makefiles that 57146572Sharti * contain only correct command lines there is no difference. But if a command 58146572Sharti * line, for example, is: 'if -foo bar' and there is an executable named 'if' 59146572Sharti * in the path, the first possibility would execute that 'if' while in the 60146572Sharti * second case the shell would give an error. Histerically only a small 61146572Sharti * subset of the builtins and no reserved words where given in the list which 62146572Sharti * corresponds roughly to the first variant. So go with this but add missing 63146572Sharti * words. 64146572Sharti */ 65146572Sharti#define CSH_BUILTINS \ 66146572Sharti "alias cd eval exec exit read set ulimit unalias " \ 67146572Sharti "umask unset wait" 68146572Sharti 69146572Sharti#define SH_BUILTINS \ 70146572Sharti "alias cd eval exec exit read set ulimit unalias " \ 71146572Sharti "umask unset wait" 72146572Sharti 73146572Sharti#define CSH_META "#=|^(){};&<>*?[]:$`\\@\n" 74146572Sharti#define SH_META "#=|^(){};&<>*?[]:$`\\\n" 75146572Sharti 76146572Shartistatic const char *const shells_init[] = { 77146572Sharti /* 78146572Sharti * CSH description. The csh can do echo control by playing 79146572Sharti * with the setting of the 'echo' shell variable. Sadly, 80146572Sharti * however, it is unable to do error control nicely. 81146572Sharti */ 82146572Sharti "name=csh path='" PATH_DEFSHELLDIR "/csh' " 83146572Sharti "quiet='unset verbose' echo='set verbose' filter='unset verbose' " 84146572Sharti "hasErrCtl=N check='echo \"%s\"\n' ignore='csh -c \"%s || exit 0\"' " 85146572Sharti "echoFlag=v errFlag=e " 86146572Sharti "meta='" CSH_META "' builtins='" CSH_BUILTINS "'", 87146572Sharti 88146572Sharti /* 89146572Sharti * SH description. Echo control is also possible and, under 90146572Sharti * sun UNIX anyway, one can even control error checking. 91146572Sharti */ 92146572Sharti "name=sh path='" PATH_DEFSHELLDIR "/sh' " 93146572Sharti "quiet='set -' echo='set -v' filter='set -' " 94146572Sharti "hasErrCtl=Y check='set -e' ignore='set +e' " 95146572Sharti "echoFlag=v errFlag=e " 96146572Sharti "meta='" SH_META "' builtins='" SH_BUILTINS "'", 97146572Sharti 98146572Sharti /* 99146572Sharti * KSH description. The Korn shell has a superset of 100146572Sharti * the Bourne shell's functionality. There are probably builtins 101146572Sharti * missing here. 102146572Sharti */ 103146572Sharti "name=ksh path='" PATH_DEFSHELLDIR "/ksh' " 104146572Sharti "quiet='set -' echo='set -v' filter='set -' " 105146572Sharti "hasErrCtl=Y check='set -e' ignore='set +e' " 106146572Sharti "echoFlag=v errFlag=e " 107146572Sharti "meta='" SH_META "' builtins='" SH_BUILTINS "' unsetenv=T", 108146572Sharti 109146572Sharti NULL 110146572Sharti}; 111146572Sharti 112146572Sharti/* 113146572Sharti * This is the shell to which we pass all commands in the Makefile. 114146572Sharti * It is set by the Job_ParseShell function. 115146572Sharti */ 116146572Shartistruct Shell *commandShell; 117146572Sharti 118146572Sharti/* 119146572Sharti * This is the list of all known shells. 120146572Sharti */ 121146572Shartistatic struct Shells shells = TAILQ_HEAD_INITIALIZER(shells); 122146572Sharti 123146572Shartivoid ShellDump(const struct Shell *) __unused; 124146572Sharti 125146572Sharti/** 126146572Sharti * Helper function for sorting the builtin list alphabetically. 127146572Sharti */ 128146572Shartistatic int 129146572Shartisort_builtins(const void *p1, const void *p2) 130146572Sharti{ 131146572Sharti 132146572Sharti return (strcmp(*(const char* const*)p1, *(const char* const*)p2)); 133146572Sharti} 134146572Sharti 135146572Sharti/** 136146572Sharti * Free a shell structure and all associated strings. 137146572Sharti */ 138146572Shartistatic void 139146572ShartiShellFree(struct Shell *sh) 140146572Sharti{ 141146572Sharti 142146572Sharti if (sh != NULL) { 143146572Sharti free(sh->name); 144146572Sharti free(sh->path); 145146572Sharti free(sh->echoOff); 146146572Sharti free(sh->echoOn); 147146572Sharti free(sh->noPrint); 148146572Sharti free(sh->errCheck); 149146572Sharti free(sh->ignErr); 150146572Sharti free(sh->echo); 151146572Sharti free(sh->exit); 152146572Sharti ArgArray_Done(&sh->builtins); 153146572Sharti free(sh->meta); 154146572Sharti free(sh); 155146572Sharti } 156146572Sharti} 157146572Sharti 158146572Sharti/** 159146572Sharti * Dump a shell specification to stderr. 160146572Sharti */ 161146572Shartivoid 162146572ShartiShellDump(const struct Shell *sh) 163146572Sharti{ 164146572Sharti int i; 165146572Sharti 166146572Sharti fprintf(stderr, "Shell %p:\n", sh); 167146572Sharti fprintf(stderr, " name='%s' path='%s'\n", sh->name, sh->path); 168146572Sharti fprintf(stderr, " hasEchoCtl=%d echoOff='%s' echoOn='%s'\n", 169146572Sharti sh->hasEchoCtl, sh->echoOff, sh->echoOn); 170146572Sharti fprintf(stderr, " noPrint='%s'\n", sh->noPrint); 171146572Sharti fprintf(stderr, " hasErrCtl=%d errCheck='%s' ignErr='%s'\n", 172146572Sharti sh->hasErrCtl, sh->errCheck, sh->ignErr); 173146572Sharti fprintf(stderr, " echo='%s' exit='%s'\n", sh->echo, sh->exit); 174146572Sharti fprintf(stderr, " builtins=%d\n", sh->builtins.argc - 1); 175146572Sharti for (i = 1; i < sh->builtins.argc; i++) 176146572Sharti fprintf(stderr, " '%s'", sh->builtins.argv[i]); 177146572Sharti fprintf(stderr, "\n meta='%s'\n", sh->meta); 178146572Sharti fprintf(stderr, " unsetenv=%d\n", sh->unsetenv); 179146572Sharti} 180146572Sharti 181146572Sharti/** 182146572Sharti * Parse a shell specification line and return the new Shell structure. 183146572Sharti * In case of an error a message is printed and NULL is returned. 184146572Sharti */ 185146572Shartistatic struct Shell * 186146572ShartiShellParseSpec(const char *spec, Boolean *fullSpec) 187146572Sharti{ 188146572Sharti ArgArray aa; 189146572Sharti struct Shell *sh; 190146572Sharti char *eq; 191146572Sharti char *keyw; 192146572Sharti int arg; 193146572Sharti 194146572Sharti *fullSpec = FALSE; 195146572Sharti 196146572Sharti sh = emalloc(sizeof(*sh)); 197146572Sharti memset(sh, 0, sizeof(*sh)); 198146572Sharti ArgArray_Init(&sh->builtins); 199146572Sharti 200146572Sharti /* 201146572Sharti * Parse the specification by keyword but skip the first word 202146572Sharti */ 203146572Sharti brk_string(&aa, spec, TRUE); 204146572Sharti 205146572Sharti for (arg = 1; arg < aa.argc; arg++) { 206146572Sharti /* 207146572Sharti * Split keyword and value 208146572Sharti */ 209146572Sharti keyw = aa.argv[arg]; 210146572Sharti if ((eq = strchr(keyw, '=')) == NULL) { 211146572Sharti Parse_Error(PARSE_FATAL, "missing '=' in shell " 212146572Sharti "specification keyword '%s'", keyw); 213146572Sharti ArgArray_Done(&aa); 214146572Sharti ShellFree(sh); 215146572Sharti return (NULL); 216146572Sharti } 217146572Sharti *eq++ = '\0'; 218146572Sharti 219146572Sharti if (strcmp(keyw, "path") == 0) { 220146572Sharti free(sh->path); 221146572Sharti sh->path = estrdup(eq); 222146572Sharti } else if (strcmp(keyw, "name") == 0) { 223146572Sharti free(sh->name); 224146572Sharti sh->name = estrdup(eq); 225146572Sharti } else if (strcmp(keyw, "quiet") == 0) { 226146572Sharti free(sh->echoOff); 227146572Sharti sh->echoOff = estrdup(eq); 228146572Sharti *fullSpec = TRUE; 229146572Sharti } else if (strcmp(keyw, "echo") == 0) { 230146572Sharti free(sh->echoOn); 231146572Sharti sh->echoOn = estrdup(eq); 232146572Sharti *fullSpec = TRUE; 233146572Sharti } else if (strcmp(keyw, "filter") == 0) { 234146572Sharti free(sh->noPrint); 235146572Sharti sh->noPrint = estrdup(eq); 236146572Sharti *fullSpec = TRUE; 237146572Sharti } else if (strcmp(keyw, "echoFlag") == 0) { 238146572Sharti free(sh->echo); 239146572Sharti sh->echo = estrdup(eq); 240146572Sharti *fullSpec = TRUE; 241146572Sharti } else if (strcmp(keyw, "errFlag") == 0) { 242146572Sharti free(sh->exit); 243146572Sharti sh->exit = estrdup(eq); 244146572Sharti *fullSpec = TRUE; 245146572Sharti } else if (strcmp(keyw, "hasErrCtl") == 0) { 246146572Sharti sh->hasErrCtl = (*eq == 'Y' || *eq == 'y' || 247146572Sharti *eq == 'T' || *eq == 't'); 248146572Sharti *fullSpec = TRUE; 249146572Sharti } else if (strcmp(keyw, "check") == 0) { 250146572Sharti free(sh->errCheck); 251146572Sharti sh->errCheck = estrdup(eq); 252146572Sharti *fullSpec = TRUE; 253146572Sharti } else if (strcmp(keyw, "ignore") == 0) { 254146572Sharti free(sh->ignErr); 255146572Sharti sh->ignErr = estrdup(eq); 256146572Sharti *fullSpec = TRUE; 257146572Sharti } else if (strcmp(keyw, "builtins") == 0) { 258146572Sharti ArgArray_Done(&sh->builtins); 259146572Sharti brk_string(&sh->builtins, eq, TRUE); 260146572Sharti qsort(sh->builtins.argv + 1, sh->builtins.argc - 1, 261146572Sharti sizeof(char *), sort_builtins); 262146572Sharti *fullSpec = TRUE; 263146572Sharti } else if (strcmp(keyw, "meta") == 0) { 264146572Sharti free(sh->meta); 265146572Sharti sh->meta = estrdup(eq); 266146572Sharti *fullSpec = TRUE; 267146572Sharti } else if (strcmp(keyw, "unsetenv") == 0) { 268146572Sharti sh->unsetenv = (*eq == 'Y' || *eq == 'y' || 269146572Sharti *eq == 'T' || *eq == 't'); 270146572Sharti *fullSpec = TRUE; 271146572Sharti } else { 272146572Sharti Parse_Error(PARSE_FATAL, "unknown keyword in shell " 273146572Sharti "specification '%s'", keyw); 274146572Sharti ArgArray_Done(&aa); 275146572Sharti ShellFree(sh); 276146572Sharti return (NULL); 277146572Sharti } 278146572Sharti } 279146572Sharti ArgArray_Done(&aa); 280146572Sharti 281146572Sharti /* 282146572Sharti * Some checks (could be more) 283146572Sharti */ 284146572Sharti if (*fullSpec) { 285146572Sharti if ((sh->echoOn != NULL) ^ (sh->echoOff != NULL)) { 286146572Sharti Parse_Error(PARSE_FATAL, "Shell must have either both " 287146572Sharti "echoOff and echoOn or none of them"); 288146572Sharti ShellFree(sh); 289146572Sharti return (NULL); 290146572Sharti } 291146572Sharti 292146572Sharti if (sh->echoOn != NULL && sh->echoOff != NULL) 293146572Sharti sh->hasEchoCtl = TRUE; 294146572Sharti } 295146572Sharti 296146572Sharti return (sh); 297146572Sharti} 298146572Sharti 299146572Sharti/** 300146572Sharti * Parse the builtin shell specifications and put them into the shell 301146572Sharti * list. Then select the default shell to be the current shell. This 302146572Sharti * is called from main() before any parsing (including MAKEFLAGS and 303146572Sharti * command line) is done. 304146572Sharti */ 305146572Shartivoid 306146572ShartiShell_Init(void) 307146572Sharti{ 308146572Sharti int i; 309146572Sharti struct Shell *sh; 310146572Sharti Boolean fullSpec; 311146572Sharti 312146572Sharti for (i = 0; shells_init[i] != NULL; i++) { 313146572Sharti sh = ShellParseSpec(shells_init[i], &fullSpec); 314146572Sharti TAILQ_INSERT_TAIL(&shells, sh, link); 315146572Sharti if (strcmp(sh->name, DEFSHELLNAME) == 0) 316146572Sharti commandShell = sh; 317146572Sharti } 318146572Sharti} 319146572Sharti 320146572Sharti/** 321146572Sharti * Find a matching shell in 'shells' given its final component. 322146572Sharti * 323146572Sharti * Results: 324146572Sharti * A pointer to a freshly allocated Shell structure with the contents 325146572Sharti * from static description or NULL if no shell with the given name 326146572Sharti * is found. 327146572Sharti */ 328146572Shartistatic struct Shell * 329146572ShartiShellMatch(const char *name) 330146572Sharti{ 331146572Sharti struct Shell *sh; 332146572Sharti 333146572Sharti TAILQ_FOREACH(sh, &shells, link) 334146572Sharti if (strcmp(sh->name, name) == 0) 335146572Sharti return (sh); 336146572Sharti 337146572Sharti return (NULL); 338146572Sharti} 339146572Sharti 340146572Sharti/** 341146572Sharti * Parse a shell specification and set up commandShell appropriately. 342146572Sharti * 343146572Sharti * Results: 344146572Sharti * TRUE if the specification was correct. FALSE otherwise. 345146572Sharti * 346146572Sharti * Side Effects: 347146572Sharti * commandShell points to a Shell structure. 348146572Sharti * created from the shell spec). 349146572Sharti * 350146572Sharti * Notes: 351146572Sharti * A shell specification consists of a .SHELL target, with dependency 352146572Sharti * operator, followed by a series of blank-separated words. Double 353146572Sharti * quotes can be used to use blanks in words. A backslash escapes 354146572Sharti * anything (most notably a double-quote and a space) and 355146572Sharti * provides the functionality it does in C. Each word consists of 356146572Sharti * keyword and value separated by an equal sign. There should be no 357146572Sharti * unnecessary spaces in the word. The keywords are as follows: 358146572Sharti * name Name of shell. 359146572Sharti * path Location of shell. Overrides "name" if given 360146572Sharti * quiet Command to turn off echoing. 361146572Sharti * echo Command to turn echoing on 362146572Sharti * filter Result of turning off echoing that shouldn't be 363146572Sharti * printed. 364146572Sharti * echoFlag Flag to turn echoing on at the start 365146572Sharti * errFlag Flag to turn error checking on at the start 366146572Sharti * hasErrCtl True if shell has error checking control 367146572Sharti * check Command to turn on error checking if hasErrCtl 368146572Sharti * is TRUE or template of command to echo a command 369146572Sharti * for which error checking is off if hasErrCtl is 370146572Sharti * FALSE. 371146572Sharti * ignore Command to turn off error checking if hasErrCtl 372146572Sharti * is TRUE or template of command to execute a 373146572Sharti * command so as to ignore any errors it returns if 374146572Sharti * hasErrCtl is FALSE. 375146572Sharti * builtins A space separated list of builtins. If one 376146572Sharti * of these builtins is detected when make wants 377146572Sharti * to execute a command line, the command line is 378146572Sharti * handed to the shell. Otherwise make may try to 379146572Sharti * execute the command directly. If this list is empty 380146572Sharti * it is assumed, that the command must always be 381146572Sharti * handed over to the shell. 382146572Sharti * meta The shell meta characters. If this is not specified 383146572Sharti * or empty, commands are alway passed to the shell. 384146572Sharti * Otherwise they are not passed when they contain 385146572Sharti * neither a meta character nor a builtin command. 386146572Sharti * unsetenv Unsetenv("ENV") before executing anything. 387146572Sharti */ 388146572ShartiBoolean 389146572ShartiShell_Parse(const char line[]) 390146572Sharti{ 391146572Sharti Boolean fullSpec; 392146572Sharti struct Shell *sh; 393146572Sharti struct Shell *match; 394146572Sharti 395146572Sharti /* parse the specification */ 396146572Sharti if ((sh = ShellParseSpec(line, &fullSpec)) == NULL) 397146572Sharti return (FALSE); 398146572Sharti 399146572Sharti if (sh->path == NULL) { 400146572Sharti /* 401146572Sharti * If no path was given, the user wants one of the pre-defined 402146572Sharti * shells, yes? So we find the one s/he wants with the help of 403146572Sharti * JobMatchShell and set things up the right way. 404146572Sharti */ 405146572Sharti if (sh->name == NULL) { 406146572Sharti Parse_Error(PARSE_FATAL, 407146572Sharti "Neither path nor name specified"); 408146572Sharti ShellFree(sh); 409146572Sharti return (FALSE); 410146572Sharti } 411146572Sharti if (fullSpec) { 412146572Sharti /* 413146572Sharti * XXX May want to merge sh into match. But this 414146572Sharti * require ShellParseSpec to return information 415146572Sharti * which attributes actuall have been specified. 416146572Sharti */ 417146572Sharti Parse_Error(PARSE_FATAL, "No path specified"); 418146572Sharti ShellFree(sh); 419146572Sharti return (FALSE); 420146572Sharti } 421146572Sharti if ((match = ShellMatch(sh->name)) == NULL) { 422146572Sharti Parse_Error(PARSE_FATAL, "%s: no matching shell", 423146572Sharti sh->name); 424146572Sharti ShellFree(sh); 425146572Sharti return (FALSE); 426146572Sharti } 427146572Sharti ShellFree(sh); 428146572Sharti commandShell = match; 429146572Sharti 430146572Sharti return (TRUE); 431146572Sharti } 432146572Sharti 433146572Sharti /* 434146572Sharti * The user provided a path. If s/he gave nothing else 435146572Sharti * (fullSpec is FALSE), try and find a matching shell in the 436146572Sharti * ones we know of. Else we just take the specification at its 437146572Sharti * word and copy it to a new location. In either case, we need 438146572Sharti * to record the path the user gave for the shell. 439146572Sharti */ 440146572Sharti if (sh->name == NULL) { 441146572Sharti /* get the base name as the name */ 442146572Sharti if ((sh->name = strrchr(sh->path, '/')) == NULL) { 443146572Sharti sh->name = estrdup(sh->path); 444146572Sharti } else { 445146572Sharti sh->name = estrdup(sh->name + 1); 446146572Sharti } 447146572Sharti } 448146572Sharti 449146572Sharti if (!fullSpec) { 450146572Sharti if ((match = ShellMatch(sh->name)) == NULL) { 451146572Sharti Parse_Error(PARSE_FATAL, 452146572Sharti "%s: no matching shell", sh->name); 453146572Sharti ShellFree(sh); 454146572Sharti return (FALSE); 455146572Sharti } 456146572Sharti 457146572Sharti /* set the patch on the matching shell */ 458146572Sharti free(match->path); 459146572Sharti match->path = sh->path; 460146572Sharti sh->path = NULL; 461146572Sharti 462146572Sharti ShellFree(sh); 463146572Sharti commandShell = match; 464146572Sharti return (TRUE); 465146572Sharti } 466146572Sharti 467146572Sharti TAILQ_INSERT_HEAD(&shells, sh, link); 468146572Sharti 469146572Sharti /* set the new shell */ 470146572Sharti commandShell = sh; 471146572Sharti return (TRUE); 472146572Sharti} 473