/* * For some reason arguments passed to kernel are not correctly splitted * in argv array - in our case all arguments are stored in one string argv[1], * but we want to keep every argument in separate argv entry. This function * tokenize all argv strings and store every single token into individual entry * of new array. * * For our needs we also convert passed environment variables and put them * into new argv array. * * Example: * * For arguments: * argc=3; * argv={"test.elf", "arg1 arg2=val arg3=foobar ", " init=/bin/sh "}; * envp={"memsize", "128MiB", "uart.speed", "115200"}; * * instruction: * setup_kenv(argc, argv, envp); * * will set global variable _kenv as follows: * _kenv.argc=5; * _kenv.argv={"test.elf", "arg1", "arg2=val", "arg3=foobar", * "init=/bin/sh", "memsize=128MiB", "uart.speed=115200"}; */ static void setup_kenv(int argc, char **argv, char **envp) { unsigned ntokens = 0; for (int i = 0; i < argc; ++i) ntokens += count_tokens(argv[i]); for (char **pair = envp; *pair; pair += 2) ntokens++; _kenv.argc = ntokens; char **tokens = kernel_sbrk(ntokens * sizeof(char *)); _kenv.argv = tokens; for (int i = 0; i < argc; ++i) tokens = extract_tokens(argv[i], tokens); for (char **pair = envp; *pair; pair += 2) *tokens++ = make_pair(pair[0], pair[1]); }
/* main */ int main() { bool exit_flag = false; int oldest_history = HISTORY_SIZE - 1, status; char *username, input[MAX_INPUT_SIZE], history[HISTORY_SIZE][MAX_INPUT_SIZE] = {'\0'}, *tokens[CMD_MAX]; signal(SIGINT, handle_sigint); //shell loop while(!exit_flag) { //print the prompt and get the input printf("%s> " , get_username()); fgets(input, MAX_INPUT_SIZE, stdin); format_input(input); //built-in exit function if(!strcmp(input, "exit")) exit_flag = true; //built-in history function else if(!strcmp(input, "history")) { int i; for(i = oldest_history+1; i!=oldest_history; i = (i+1)%HISTORY_SIZE) { if(history[i][0] != '\0') printf("%s\n", history[i]); } } //non-built-in function else if(strcmp(input, "")) { int token_index, num_tokens; pid_t pid; char *tokens[CMD_MAX]; //get the token list and size num_tokens = make_tokenlist(input, tokens); //fork a child process pid = fork(); //parent: wait for child to finish if(pid > 0) { pid = wait(&status); } //child: execute command if(pid == 0) { //redirect output token_index = contains_token(tokens, num_tokens, ">"); if(token_index >= 0 && token_index+1 < num_tokens) { int fd_o = open(tokens[token_index+1], O_CREAT|O_TRUNC|O_WRONLY, 0644); if(dup2(fd_o, STDOUT_FILENO)<0) { perror("dup2 error"); exit(EXIT_FAILURE); } close(fd_o); //remove ">" and the output file from the list of arguments tokens[token_index ] = '\0'; tokens[token_index+1] = '\0'; } //redirect input token_index = contains_token(tokens, num_tokens, "<"); if(token_index >= 0 && token_index+1 < num_tokens) { int fd_i = open(tokens[token_index+1], O_RDONLY); dup2(fd_i, STDIN_FILENO); close(fd_i); //remove "<" and the input file from the list of arguments tokens[token_index ] = '\0'; tokens[token_index+1] = '\0'; } //handle pipe int num_pipes = count_pipes(tokens, num_tokens); if(num_pipes > 0) { //get the indices of the pipes to extract the commands int pipe_indices[CMD_MAX]; get_pipe_indices(tokens, num_tokens, pipe_indices); //extract all the commands char *commands[CMD_MAX][CMD_MAX]; for(int i=0; i<=num_pipes; i++) { extract_tokens(tokens, commands[i], pipe_indices[i]+1, pipe_indices[i+1]); } //connect and run all the pipe commands int fds[2], in = STDIN_FILENO; for(int i=0; i<num_pipes; i++) { pipe(fds); execute_piped_process(in, fds[1], commands[i]); close(fds[1]); in = fds[0]; } //execute the last command if(in != STDIN_FILENO) dup2(in, STDIN_FILENO); execvp(commands[num_pipes][0], commands[num_pipes]); } //execute command execvp(tokens[0], tokens); printf("%s: invalid command\n", tokens[0]); exit(EXIT_FAILURE); } } //update history if(strcmp(input, "") && status==0) { strcpy( history[oldest_history], input ); oldest_history--; if(oldest_history < 0) oldest_history = HISTORY_SIZE - 1; } } }
int main (int argc, char *argv[]) { char buffer[10000]; token tokens[500]; int t; //total number of tokens int i; //general use counter int res; FILE *fp; if (argc < 2) { //check if the number of arguments is correct printf("Usage: %s <input_file> -o <output_file>\n", argv[0]); return 1; } else if ((fp = fopen(argv[1], "r")) == NULL) { //try to open the input file printf("%s\n", strerror(errno)); return 2; } else { /*Phase 0: Put instuctions from the input file to the buffer serialized*/ res = serialize_input(buffer, fp); /*If is on DEBUG_MODE print debuggin info*/ if (DEBUG_MODE) { printf("Phase 0: Put instuctions from the input file to the buffer serialized:\n%s\n\n", buffer); } close(fp); if (res == 0) { puts("Empty input file."); return 3; } } /*Phase 1: Parse the code*/ validate_tokens(buffer); /*If is on DEBUG_MODE print debuggin info*/ if (DEBUG_MODE) { printf("Phase 1: Remove lines with invalid tokens:\n%s\n\n", buffer); } /*Phase 2: Extract the tokens*/ t = extract_tokens(buffer, tokens); /*If is on DEBUG_MODE print debuggin info*/ if (DEBUG_MODE) { puts("Phase 2: Extract the tokens:"); print_tokens(tokens, t); putchar('\n'); } /*Phase 3: Do syntax analysis on the tokens*/ t = analize_tokens(tokens, t); /*If is on DEBUG_MODE print debuggin info*/ if (DEBUG_MODE) { puts("Phase 3: Do syntax analysis on the tokens:"); print_tokens(tokens, t); putchar('\n'); } /*Phase 4: Do optimization on the tokens*/ t = optimize_tokens(tokens, t); /*If is on DEBUG_MODE print debuggin info*/ if (DEBUG_MODE) { puts("Phase 4: Do optimization on the tokens:"); print_tokens(tokens, t); putchar('\n'); } /*Phase 5: Do code generation based on the tokens*/ generate_code(buffer, tokens, t); /*If is on DEBUG_MODE print debuggin info*/ if (DEBUG_MODE) { printf("Phase 5: Do code generation based on the tokens:\n%s\n\n", buffer); } /*Print errors buffer*/ if (error_cnt != 0) { puts(error_buffer); } else { puts("No Errors"); } /*Final Phase: Save the code in a file*/ if (argc == 4 && strcmp(argv[2], "-o") == 0) { //check if user provided output file name save_code(buffer, argv[3]); } else { save_code(buffer, "out.c"); } return 0; }