Source

sh142 / src / interpreter.c

Steven! Ragnarök ee54ff6 
Steven! Ragnarök 4b60576 
Steven! Ragnarök 8812d52 
Steven! Ragnarök ee54ff6 
Steven! Ragnarök fde20ee 
Steven! Ragnarök ee54ff6 

Steven! Ragnarök 57ba8d0 


Steven! Ragnarök ee54ff6 
Steven! Ragnarök 4b60576 
Steven! Ragnarök 005dafe 
Steven! Ragnarök 4b60576 
Steven! Ragnarök 005dafe 
Steven! Ragnarök a32e33a 
Steven! Ragnarök ee54ff6 
Steven! Ragnarök 4b60576 


Steven! Ragnarök a5d8a02 
Steven! Ragnarök ee54ff6 


Steven! Ragnarök 4b60576 
Steven! Ragnarök 96c172c 
Steven! Ragnarök fde20ee 
Steven! Ragnarök 1f4ffa1 
Steven! Ragnarök a5d8a02 
Steven! Ragnarök a32e33a 
Steven! Ragnarök 1f4ffa1 
Steven! Ragnarök 8812d52 
Steven! Ragnarök 1f4ffa1 
Steven! Ragnarök a32e33a 
Steven! Ragnarök a5d8a02 










Steven! Ragnarök 8812d52 
Steven! Ragnarök ee54ff6 
Steven! Ragnarök 8812d52 
Steven! Ragnarök 1f4ffa1 

Steven! Ragnarök fde20ee 

Steven! Ragnarök 96c172c 




Steven! Ragnarök fde20ee 


Steven! Ragnarök 4b60576 
Steven! Ragnarök ee54ff6 
Steven! Ragnarök fde20ee 
Steven! Ragnarök 005dafe 









Steven! Ragnarök 4b60576 
Steven! Ragnarök 57ba8d0 


Steven! Ragnarök 4b60576 
Steven! Ragnarök 57ba8d0 

Steven! Ragnarök 8812d52 














Steven! Ragnarök 4b60576 

















Steven! Ragnarök a5d8a02 


















#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include "../include/interpreter.h"

/* A Non-zero integer for overwriting environment variables with setenv */
#define OVERWRITE 1

void interpret(ast_node *root) {
	int exit_status;
	if (root->type == VARASSIGN) {
		exit_status = interpret_var_assign(root);
	} else {
		exit_status = interpret_command(root);
	}

	fifo_push(MAX_SAVED_EXITSTATUSES, exitstatuses, exitstatus_head, exit_status);
	set_exitstatuses();
	free_ast(root);
	return;
}

int interpret_command(ast_node* command) {
	int cmdstats, argc = 0, execerr;
	pid_t cmdpid;
	char *argv[MAX_TOKEN_LENGTH];
	ast_nodelist *arg;

	/* Build the values to pass to execvp */
	argv[argc] = interpret_value(command);
	++argc;

	if (command->children != NULL && command->children->node->type == ARGLIST) {
		arg = command->children->node->children;

		while (arg != NULL) {
			if (arg->node->type == VARIABLE) {
				argv[argc] = interpret_variable(arg->node);
			} else {
				argv[argc] = interpret_value(arg->node);
			}
			++argc;
			arg = arg->next;
		}
	}

	/* Null-terminate the list as per execvp's documentation. */
	argv[argc] = NULL;
	cmdpid = fork();
	if (!cmdpid)  {
		execerr = execvp(command->token, argv);
		if (execerr == -1) {
			fprintf(stderr, "sh142: %s: command not found.\n", argv[0]);
			exit(127);
		}
	} else {
		waitpid(cmdpid, &cmdstats, 0);
	}
	return WEXITSTATUS(cmdstats);
}

int interpret_negated_command(ast_node *command) {
	int command_status;
	command_status = interpret_command(command);
	if (command_status == 0) {
		return 1;
	} else {
		return 0;
	}
}

int interpret_var_assign(ast_node *var_assign) {
	char *varname, *value;
	varname = var_assign->children->node->token;
	value = var_assign->children->next->node->token;
	return setenv(varname, value, OVERWRITE);
}

char *interpret_variable(ast_node *variable) {
	char *value = (char*)malloc(sizeof(char) * MAX_STRING_LENGTH);
	char *envar = getenv(variable->token);
	if (envar != NULL) {
		strncpy(value, envar, MAX_STRING_LENGTH);
	} else {
		strncpy(value, "", MAX_STRING_LENGTH);
	}
	return value;
}

char *interpret_value(ast_node *value) {
	return value->token;
}

void set_exitstatuses() {
	int i, status;
	char var[2]; /* Only need 3 characters. Since statuses range from 0-255. */
	char val[3]; /* Only need 3 characters. Since statuses range from 0-255. */
	for (i = 0; i < MAX_SAVED_EXITSTATUSES; i++) {
		sprintf(var, "?%1d", i);
		status = fifo_peek(MAX_SAVED_EXITSTATUSES, exitstatuses,
				exitstatus_head, i);
		if (status != UNSET_STATUS) {
			sprintf(val, "%3d", status);
			setenv(var, val, OVERWRITE);
		} else {
			unsetenv(var);
		}
	}
	return;
}

void free_ast(ast_node *root) {
	if (root != NULL) {
		if (root->children == NULL) {
			free(root);
		} else {
			free_ast_list(root->children);
		}
	}
}

void free_ast_list(ast_nodelist *list) {
	ast_nodelist *next;
	while (list != NULL) {
		next = list->next;
		free_ast(list->node);
		free(list);
		list = next;
	}
}