示例#1
0
文件: shell.c 项目: coyizumi/cs111
/**
 * Parse the builtin shell specifications and put them into the shell
 * list. Then select the default shell to be the current shell. This
 * is called from main() before any parsing (including MAKEFLAGS and
 * command line) is done.
 */
void
Shell_Init(void)
{
	int i;
	struct Shell *sh;
	Boolean fullSpec;

	for (i = 0; shells_init[i] != NULL; i++) {
		sh = ShellParseSpec(shells_init[i], &fullSpec);
		TAILQ_INSERT_TAIL(&shells, sh, link);
		if (strcmp(sh->name, DEFSHELLNAME) == 0)
			commandShell = sh;
	}
}
示例#2
0
/**
 * Given the line following a .SHELL target, parse it as a shell
 * specification.
 *
 * Results:
 *	A pointer to a Shell structure, or NULL if no the spec was invalid.
 */
Shell *
Shell_Parse(const char line[])
{
	bool	fullSpec;
	Shell	*sh;

	/* parse the specification */
	if ((sh = ShellParseSpec(line, &fullSpec)) == NULL)
		return (NULL);

	if (sh->path == NULL) {
		Shell	*match;
		/*
		 * If no path was given, the user wants one of the pre-defined
		 * shells, yes? So we find the one s/he wants with the help of
		 * ShellMatch and set things up the right way.
		 */
		if (sh->name == NULL) {
			Parse_Error(PARSE_FATAL,
			    "Neither path nor name specified");
			Shell_Destroy(sh);
			return (NULL);
		}
		if (fullSpec) {
			Parse_Error(PARSE_FATAL, "No path specified");
			Shell_Destroy(sh);
			return (NULL);
		}
		if ((match = Shell_Match(sh->name)) == NULL) {
			Parse_Error(PARSE_FATAL, "%s: no matching shell",
			    sh->name);
			Shell_Destroy(sh);
			return (NULL);
		}

		Shell_Destroy(sh);
		return (match);

	} else {
		Shell	*match;

		/*
		 * The user provided a path. If s/he gave nothing else
		 * (fullSpec is false), try and find a matching shell in the
		 * ones we know of. Else we just take the specification at its
		 * word and copy it to a new location. In either case, we need
		 * to record the path the user gave for the shell.
		 */
		if (sh->name == NULL) {
			/* get the base name as the name */
			if ((sh->name = strrchr(sh->path, '/')) == NULL) {
				sh->name = estrdup(sh->path);
			} else {
				sh->name = estrdup(sh->name + 1);
			}
		}
		if (fullSpec) {
			return (sh);
		}
		if ((match = Shell_Match(sh->name)) == NULL) {
			Parse_Error(PARSE_FATAL,
			    "%s: no matching shell", sh->name);
			Shell_Destroy(sh);
			return (NULL);
		}

		free(match->path);
		match->path = sh->path;
		sh->path = NULL;

		Shell_Destroy(sh);
		return (match);
	}
}
示例#3
0
文件: shell.c 项目: coyizumi/cs111
/**
 * Parse a shell specification and set up commandShell appropriately.
 *
 * Results:
 *	TRUE if the specification was correct. FALSE otherwise.
 *
 * Side Effects:
 *	commandShell points to a Shell structure.
 *	created from the shell spec).
 *
 * Notes:
 *	A shell specification consists of a .SHELL target, with dependency
 *	operator, followed by a series of blank-separated words. Double
 *	quotes can be used to use blanks in words. A backslash escapes
 *	anything (most notably a double-quote and a space) and
 *	provides the functionality it does in C. Each word consists of
 *	keyword and value separated by an equal sign. There should be no
 *	unnecessary spaces in the word. The keywords are as follows:
 *	    name	    Name of shell.
 *	    path	    Location of shell. Overrides "name" if given
 *	    quiet	    Command to turn off echoing.
 *	    echo	    Command to turn echoing on
 *	    filter	    Result of turning off echoing that shouldn't be
 *			    printed.
 *	    echoFlag	    Flag to turn echoing on at the start
 *	    errFlag	    Flag to turn error checking on at the start
 *	    hasErrCtl	    True if shell has error checking control
 *	    check	    Command to turn on error checking if hasErrCtl
 *			    is TRUE or template of command to echo a command
 *			    for which error checking is off if hasErrCtl is
 *			    FALSE.
 *	    ignore	    Command to turn off error checking if hasErrCtl
 *			    is TRUE or template of command to execute a
 *			    command so as to ignore any errors it returns if
 *			    hasErrCtl is FALSE.
 *	    builtins	    A space separated list of builtins. If one
 *			    of these builtins is detected when make wants
 *			    to execute a command line, the command line is
 *			    handed to the shell. Otherwise make may try to
 *			    execute the command directly. If this list is empty
 *			    it is assumed, that the command must always be
 *			    handed over to the shell.
 *	    meta	    The shell meta characters. If this is not specified
 *			    or empty, commands are alway passed to the shell.
 *			    Otherwise they are not passed when they contain
 *			    neither a meta character nor a builtin command.
 *	    unsetenv	    Unsetenv("ENV") before executing anything.
 */
Boolean
Shell_Parse(const char line[])
{
	Boolean		fullSpec;
	struct Shell	*sh;
	struct Shell	*match;

	/* parse the specification */
	if ((sh = ShellParseSpec(line, &fullSpec)) == NULL)
		return (FALSE);

	if (sh->path == NULL) {
		/*
		 * If no path was given, the user wants one of the pre-defined
		 * shells, yes? So we find the one s/he wants with the help of
		 * JobMatchShell and set things up the right way.
		 */
		if (sh->name == NULL) {
			Parse_Error(PARSE_FATAL,
			    "Neither path nor name specified");
			ShellFree(sh);
			return (FALSE);
		}
		if (fullSpec) {
			/*
			 * XXX May want to merge sh into match. But this
			 * require ShellParseSpec to return information
			 * which attributes actuall have been specified.
			 */
			Parse_Error(PARSE_FATAL, "No path specified");
			ShellFree(sh);
			return (FALSE);
		}
		if ((match = ShellMatch(sh->name)) == NULL) {
			Parse_Error(PARSE_FATAL, "%s: no matching shell",
			    sh->name);
			ShellFree(sh);
			return (FALSE);
		}
		ShellFree(sh);
		commandShell = match;

		return (TRUE);
	}

	/*
	 * The user provided a path. If s/he gave nothing else
	 * (fullSpec is FALSE), try and find a matching shell in the
	 * ones we know of. Else we just take the specification at its
	 * word and copy it to a new location. In either case, we need
	 * to record the path the user gave for the shell.
	 */
	if (sh->name == NULL) {
		/* get the base name as the name */
		if ((sh->name = strrchr(sh->path, '/')) == NULL) {
			sh->name = estrdup(sh->path);
		} else {
			sh->name = estrdup(sh->name + 1);
		}
	}

	if (!fullSpec) {
		if ((match = ShellMatch(sh->name)) == NULL) {
			Parse_Error(PARSE_FATAL,
			    "%s: no matching shell", sh->name);
			ShellFree(sh);
			return (FALSE);
		}

		/* set the patch on the matching shell */
		free(match->path);
		match->path = sh->path;
		sh->path = NULL;

		ShellFree(sh);
		commandShell = match;
		return (TRUE);
	}

	TAILQ_INSERT_HEAD(&shells, sh, link);

	/* set the new shell */
	commandShell = sh;
	return (TRUE);
}