Ejemplo n.º 1
0
//parses a stage, returning a command struct
//modifies global variable t
CMD *stage()
{
	CMD *tmp;
	CMD *cmd = 0;
	if (!t)
		return 0;
	tmp = mallocCMD();
	while (t && (ISREDOUT(t->type) || ISREDIN(t->type)))
		tmp = redirect(tmp);
	if (!tmp)
		return 0;
	else if (!t)
	{
		DIE("Parse: null command\n");
		return 0;
	}
	else if (t->type == PAR_LEFT)
	{
		cmd = mallocCMD();
		cmd->type = SUBCMD;
		t = t->next;
		cmd->left = command();
		if (!cmd->left)
		{
			DIE("Parse: null command\n");
			freeCMD(cmd);
			return 0;
		}
		else if (!t || t->type != PAR_RIGHT)
		{
			DIE("Parse: unbalanced parens\n");
			freeCMD(cmd);
			return 0;
		}
		else 
		{
			t = t->next;
			while(t && cmd && (ISREDOUT(t->type) 
				|| ISREDIN(t->type)))
				cmd = redirect(cmd);
		}
	}
	else
		cmd = simple();
	cmd = merge(cmd, tmp);
	freeCMD(tmp);
	return cmd;
}
Ejemplo n.º 2
0
CMD *parseSimple(token **lstHead)
{
	CMD *cmd = mallocCMD();
	while((*lstHead) && ((*lstHead)->type == SIMPLE || IS_RED((*lstHead)->type)))
	{
		cmd->type = SIMPLE;
		if((*lstHead)->type == SIMPLE)
		{
			//not a redirection
			cmd->argv[cmd->argc] = copyText((*lstHead)->text);
			cmd->argc++;
			cmd->argv = realloc(cmd->argv,(cmd->argc+1)*sizeof(char*));
			cmd->argv[cmd->argc] = NULL;
			*lstHead = (*lstHead)->next;
		}
		else
		{
			//redirection found
			cmd = parseRedirect(lstHead,cmd);
			if(cmd->type == ERROR)
			{
				//if error occurred in parseRedirect
				return cmd;
			}
		}			
	}

	if(cmd && cmd->type == NONE)
	{
		//case where no SIMPLE was found
		freeCMD(cmd);
		return NULL;
	}
	return cmd;
}
Ejemplo n.º 3
0
CMD *parseCommand(token **lstHead)
{
	CMD *cmd = parseAndOr(lstHead);
	if(cmd->type == ERROR)
	{
		//propagate an error
		return cmd;
	}

	//check to make sure that end of linked list not reached
	if(cmd && *lstHead && ((*lstHead)->type == SEP_END || 
							(*lstHead)->type == SEP_BG))
	{
		CMD *andorCMD = cmd;
		cmd = mallocCMD();
		cmd->type = (*lstHead)->type;
		cmd->left = andorCMD;
		*lstHead = (*lstHead)->next;
		if(*lstHead)
		{
			cmd->right = parseCommand(lstHead);
			if(cmd->right->type == ERROR)
			{
				//propagate along an error
				return cmd->right;
			}
		}
	}
	return cmd;
}
Ejemplo n.º 4
0
//parses a pipeline, returning command struct
//modifies global variable t
CMD *pipeline()
{
	CMD *cmd = 0, *tmp = 0;
	cmd = stage();
	while (t && ISPIPE(t->type))
	{
		if (!cmd)
		{
			DIE("Parse: null command\n");
			freeCMD(cmd);
			return 0;
		}
		if (cmd->toType != NONE)
		{
			DIE("Parse: two output redirects\n");
			freeCMD(cmd);
			return 0;
		}
		tmp = cmd;
		cmd = mallocCMD();
		cmd->type = t->type;
		cmd->left = tmp;
		t = t->next;
		cmd->right = pipeline();
		if (!cmd->right)
		{
			DIE("Parse: null command\n");
			freeCMD(cmd);
			return 0;
		}
	}
	return cmd;
}
Ejemplo n.º 5
0
//parses an and-or statement, returning command struct
//modifies global variable t
CMD *andOr()
{
	CMD *cmd = 0 /*output*/, *tmp = 0; //swap
	cmd = pipeline();
	while (t && (t->type == SEP_AND || t->type == SEP_OR))
	{
		if (!cmd)
		{
			DIE("Parse: null command\n");
			freeCMD(cmd);
			return 0;
		}
		tmp = cmd;
		cmd = mallocCMD();
		cmd->type = t->type;
		cmd->left = tmp;
		t = t->next;
		cmd->right = andOr();
		if (!cmd->right)
		{
			DIE("Parse: null command\n");
			freeCMD(cmd);
			return 0;
		}
	}
	return cmd;
}
Ejemplo n.º 6
0
//parses a SIMPLE statement, returning command struct
//modifies global variable t
CMD *simple()
{
	CMD *cmd;
	cmd = mallocCMD();
	cmd->type = SIMPLE;
	while (t && cmd != NULL)
	{
		if (t->type == SIMPLE)
		{
			(cmd->argc)++;
			cmd->argv = realloc(cmd->argv, sizeof(char*) 
				* (cmd->argc + 1));
			cmd->argv[cmd->argc] = 0;
			cmd->argv[cmd->argc - 1] = malloc(strlen(t->text) + 1);
			strcpy(cmd->argv[cmd->argc - 1], t->text);
			t = t->next;
		}
		else if (ISREDOUT(t->type) || ISREDIN(t->type))
			cmd = redirect(cmd);
		else 
			break;
	}
	if (!cmd || !cmd->argc)
		return 0;
	else
		return cmd;
}
Ejemplo n.º 7
0
CMD* make_cmd(token_list** list_ref)
{
    token_list* list = *list_ref;
    if (!list) return make_error_cmd("could not form command (no tokens)");

    CMD* cmd_tree = make_andor(&list);
    if (cmd_tree->type == ERROR) return cmd_tree;

    int next_type = type(list);
    if (next_type == SEP_END || next_type == SEP_BG) {
        advance(&list);

        CMD* parent = mallocCMD();
        parent->type = next_type;
        parent->left = cmd_tree;
        cmd_tree = parent;

        // See if it is possible to make a subcommand; if not, return to initial
        // state (because subcommand is optional following ; or &
        token_list* old_head = list; // Hold onto a copy in case sub command
                                     // returns an error
        CMD* sub_cmd = make_cmd(&list);
        if (sub_cmd->type == ERROR) {
            freeCMD(sub_cmd);
            sub_cmd = NULL;
            list = old_head;
        }
        cmd_tree->right = sub_cmd;
    }

    *list_ref = list;
    return cmd_tree;
}
Ejemplo n.º 8
0
CMD* make_andor(token_list** list_ref)
{
    token_list* list = *list_ref;
    if (!list) return make_error_cmd("could not form and-or (no tokens)");

    CMD* andor_tree = make_pipeline(&list);
    if (andor_tree->type == ERROR) return andor_tree;

    int next_type = type(list);
    if (next_type == SEP_AND || next_type == SEP_OR) {
        advance(&list);

        CMD* parent = mallocCMD(); // TODO: make sure all initialized to NULL
        parent->type = next_type;
        parent->left = andor_tree;
        andor_tree = parent;

        CMD* sub_andor = make_andor(&list);
        if (sub_andor->type == ERROR) {
            freeCMD(andor_tree);
            return sub_andor;
        }
        andor_tree->right = sub_andor;
    }

    *list_ref = list;
    return andor_tree;
}
Ejemplo n.º 9
0
CMD* make_pipeline(token_list** list_ref)
{
    token_list* list = *list_ref;
    if (!list) return make_error_cmd("could not form pipeline (no tokens)");

    CMD* pipeline_tree = make_stage(&list);
    if (pipeline_tree->type == ERROR) return pipeline_tree;

    int next_type = type(list);
    if (next_type == PIPE || next_type == PIPE_ERR) {
        advance(&list);

        CMD* parent = mallocCMD();
        parent->type = next_type;
        parent->left = pipeline_tree;
        pipeline_tree = parent;

        CMD* sub_pipeline = make_pipeline(&list);
        if (sub_pipeline->type == ERROR) {
            freeCMD(pipeline_tree);
            return sub_pipeline;
        }
        pipeline_tree->right = sub_pipeline;
    }

    *list_ref = list;
    return pipeline_tree;
}
Ejemplo n.º 10
0
/* Makes a command with type ERROR as an error-handling mechanism
 *
 * Usage notes: Memory must be freed with freeCMD(). Error message is stored in
 * argv[0], for use by error handler in outputting messages.
 *
 * @message = error message
 */
CMD* make_error_cmd(char* message)
{
    CMD* error_cmd = mallocCMD();
    error_cmd->type = ERROR;
    error_cmd->argv = realloc(error_cmd->argv, 2 * sizeof(char*));
    error_cmd->argv[0] = strdup(message);
    error_cmd->argv[1] = NULL;
    return error_cmd;
}
Ejemplo n.º 11
0
CMD *errorCMD(CMD *toFree)
{
	if(toFree)
	{
		freeCMD(toFree);
	}
	CMD *cmd = mallocCMD();
	cmd->type = ERROR;
	return cmd;
}
Ejemplo n.º 12
0
CMD *parsePipeline(token **lstHead)
{
	CMD *cmd = parseStage(lstHead);
	if(cmd->type == ERROR)
	{
		//propagate an error
		return cmd;
	}

	//check to make sure that end of linked list not reached and cmd not NULL!
	if(cmd && *lstHead && ISPIPE((*lstHead)->type))
	{
		CMD *stageCMD = cmd;
		cmd = mallocCMD();
		cmd->type = (*lstHead)->type;
		cmd->left = stageCMD;
		*lstHead = (*lstHead)->next;
		if(*lstHead == NULL)
		{
			//error..incomplete pipeline!
			fprintf(stderr,"%s\n","Error: Incomplete pipeline command");
			return errorCMD(cmd);
		}
		cmd->right = parsePipeline(lstHead);

		if(cmd->right == NULL)
		{
			//case of no right argument for pipe
			fprintf(stderr,"%s\n","Error: Incomplete pipeline command");
			return errorCMD(cmd);
		}

		if(cmd->right->type == ERROR)
		{
			//propagate along an error
			return cmd->right;
		}

		if(stageCMD->toFile != NULL || cmd->right->fromFile != NULL)
		{
			//case of multiple redirections involving a pipeline
			fprintf(stderr,"%s\n","Error: Multiple redirections");
			return errorCMD(cmd);
		}
	}
	return cmd;
}
Ejemplo n.º 13
0
CMD *parseAndOr(token **lstHead)
{
	CMD *cmd = parsePipeline(lstHead);
	if(cmd->type == ERROR)
	{
		//propagate an error
		return cmd;
	}

	//check to make sure that end of linked list not reached
	if(cmd && *lstHead && ((*lstHead)->type == SEP_AND || 
							(*lstHead)->type == SEP_OR))
	{
		CMD *pipelineCMD = cmd;
		cmd = mallocCMD();
		cmd->type = (*lstHead)->type;
		cmd->left = pipelineCMD;
		*lstHead = (*lstHead)->next;
		if(*lstHead == NULL)
		{
			//error..incomplete and/or
			fprintf(stderr,"%s\n","Error: Incomplete and/or command");
			return errorCMD(cmd);
		}
		cmd->right = parseAndOr(lstHead);

		if(cmd->right == NULL)
		{
			//case of no right arguments for and/or
			fprintf(stderr,"%s\n","Error: Incomplete and/or command");
			return errorCMD(cmd);
		}

		if(cmd->right->type == ERROR)
		{
			//propagate along an error
			return cmd->right;
		}
	}
	return cmd;
}
Ejemplo n.º 14
0
//parses a command, returning command struct
//modifies global variable t
CMD *command()
{
	CMD *cmd = 0 /*output*/, *tmp = 0; //swap variable
	cmd = andOr();
	while (t && (t->type == SEP_END || t->type == SEP_BG))
	{
		if (!cmd)
		{
			DIE("Parse: null command\n");
			freeCMD(cmd);
			return 0;
		}
		tmp = cmd;
		cmd = mallocCMD();
		cmd->type = t->type;
		cmd->left = tmp;
		t = t->next;
		cmd->right = command();
	}
	return cmd;
}
Ejemplo n.º 15
0
CMD *parseStage(token **lstHead)
{
	CMD *cmd = parseSimple(lstHead);
	if(cmd && cmd->type == ERROR)
	{
		//propagate along an error
		return cmd;
	}

	/*if(*lstHead && (*lstHead)->type == PAR_RIGHT)
	{
		//right parenthesis before left...error!
		fprintf(stderr,"%s\n","Error: Right parenthesis before left");
		return errorCMD(cmd);
	}*/

	if(*lstHead && (*lstHead)->type == PAR_LEFT)
	{
		if(cmd)
		{
			//error..subcommand after command
			fprintf(stderr,"%s\n","Error: Subcommand after command");
			return errorCMD(cmd);
		}

		*lstHead = (*lstHead)->next;
		cmd = mallocCMD();

		if(*lstHead == NULL)
		{
			//error..invalid subcommand
			fprintf(stderr,"%s\n","Error: Invalid subcommand");
			return errorCMD(cmd);
		}

		cmd->type = SUBCMD;
		cmd->left = parseCommand(lstHead);

		if(cmd->left->type == ERROR)
		{
			//propagate error
			return cmd->left;
		}
		
		if(*lstHead == NULL || ((*lstHead)->type != PAR_RIGHT && 
									!IS_RED((*lstHead)->type)))
		{
			//error...parens incorrectly nested
			fprintf(stderr,"%s\n","Error: Incorrect parenthesis nesting");
			return errorCMD(cmd);
		}

		*lstHead = (*lstHead)->next;
		
		if(*lstHead && IS_RED((*lstHead)->type))
		{
			//redirection found
			cmd = parseRedirect(lstHead,cmd);
			if(cmd->type == ERROR)
			{
				//if error occurred in parseRedirect
				return cmd;
			}
		}
	}
	return cmd;
}
Ejemplo n.º 16
0
CMD* make_stage(token_list** list_ref)
{
    token_list* list = *list_ref;
    if (!list) return make_error_cmd("could not form stage (no tokens)");

    CMD* stage_tree = mallocCMD(); // Current type is NONE

    int next_type = NONE; // Hold the type of the head token of list
    bool redir_in = false; // Has there been a previous input redirection?
    bool redir_out = false;

    // Loop until hit a pipe or a separator; raise an error if multiple redirect
    // or both a command and subcommand
    while ((next_type = type(list)) != -1 &&
        !ISSEP(next_type) && !ISPIPE(next_type) && next_type != PAR_RIGHT) {

        bool error = false; // Signals whether the current action results in an
                            // error
        if (next_type == SIMPLE && stage_tree->type != SUBCMD) {
            int argc = stage_tree->argc + 1;
            char** argv = stage_tree->argv;
            argv = realloc(argv, (argc + 1) * sizeof(char*)); // +1 for trailing
                                                              // NULL required
                                                              // by freeCMD
            argv[argc - 1] = strdup(text(list));
            argv[argc] = NULL;
            stage_tree->argc = argc;
            stage_tree->argv = argv;
            stage_tree->type = SIMPLE;
        } else if ((next_type == RED_IN || next_type == RED_HERE)
            && !redir_in) {
            error = make_redirect(stage_tree, &redir_in, next_type, &list);
        } else if (ISREDOUT(next_type) && !redir_out) {
            error = make_redirect(stage_tree, &redir_out, next_type, &list);
        } else if (next_type == PAR_LEFT &&
            stage_tree->type == NONE) { // Can't have two subcommands in a stage

            advance(&list); // Advance past left parentheses

            CMD* subcmd_tree = make_cmd(&list);
            error = subcmd_tree->type == ERROR || type(list) != PAR_RIGHT;

            stage_tree->type = SUBCMD;
            stage_tree->left = subcmd_tree;
        } else {
            error = true;
        }

        if (error) {
            freeCMD(stage_tree);
            return make_error_cmd("Invalid stage");
        }

        advance(&list);
    }

    // Make sure we didn't double-redirect
    if (ISPIPE(next_type) && redir_out) {
        freeCMD(stage_tree);
        return make_error_cmd("Double redirect - pipe and >");
    }

    // Make sure there was actually an argument
    if (stage_tree->type == NONE) {
        freeCMD(stage_tree);
        return make_error_cmd("No arguments for simple command");
    }

    assert(stage_tree->type != NONE);

    *list_ref = list;
    return stage_tree;
}