Last active
August 29, 2015 14:09
-
-
Save SungjinYoo/817a106c942cf4a7c1ef to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// main.c | |
// minishell | |
// | |
// Created by SungJinYoo on 11/7/14. | |
// Copyright (c) 2014 SungJinYoo. All rights reserved. | |
// | |
#include <libgen.h> | |
#include <fcntl.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include "types.h" | |
#include "list.h" | |
#include "command.h" | |
const size_t BUFFER_SIZE = 256; | |
struct Queue* _history_queue = NULL; | |
struct Queue* get_history_queue() | |
{ | |
if(_history_queue == NULL) | |
_history_queue = queue_create(); | |
return _history_queue; | |
} | |
void for_each_history_node(struct Node* history_node, int node_index) | |
{ | |
printf("%d: %s\n", node_index, (char*)history_node->item); | |
} | |
void append_history(char* history) | |
{ | |
struct Queue* history_queue = get_history_queue(); | |
queue_enqueue(history_queue, history); | |
} | |
void print_history() | |
{ | |
struct Queue* history_queue = get_history_queue(); | |
queue_for_each(history_queue, for_each_history_node); | |
} | |
void execute_simple_command(struct SimpleCommand* command) | |
{ | |
/* handle command history */ | |
if(strcmp(command->param_list[0], "history") == 0){ | |
print_history(); | |
} | |
/* handle command cd */ | |
else if(strcmp(command->param_list[0], "cd") == 0){ | |
if(command->param_count < 2){ | |
fprintf(stderr, "cd error\n"); | |
} | |
else{ | |
chdir(command->param_list[1]); | |
} | |
} | |
else{ | |
if(execvp(command->param_list[0], command->param_list) < 0) | |
fprintf(stderr, "execvp error\n"); | |
} | |
} | |
void execute_redirection(struct Redirection* redirection) | |
{ | |
struct SimpleCommand* command = redirection->dest; | |
if(redirection->src != NULL){ | |
if(redirection->is_write){ | |
int option = O_WRONLY|O_CREAT; | |
int fd = -1; | |
if(!redirection->override) option |= O_APPEND; | |
if(!redirection->check_exists) option |= O_CREAT; | |
if(redirection->check_exists && access(redirection->dest->param_list[0], F_OK ) != -1 ) { // check for file existence | |
// behavior of >! is if the file does not exists make a redirection | |
return; | |
} | |
fd = open(redirection->dest->param_list[0], option, 0644); | |
if(fd < 0){ | |
fprintf(stderr, "no such file : %s\n", redirection->dest->param_list[0]); | |
} | |
close(STDOUT_FILENO); | |
dup(fd); | |
command = redirection->src; | |
} | |
else{ | |
int fd = open(redirection->src->param_list[0], O_RDONLY, 0644); | |
close(STDIN_FILENO); | |
dup(fd); | |
command = redirection->dest; | |
} | |
} | |
execute_simple_command(command); | |
} | |
void for_each_command_node(struct Node* node, int node_index) | |
{ | |
int status; | |
struct Command* command = (struct Command*)node->item; | |
struct Pipeline* pipeline = command->pipeline; | |
pid_t pid; | |
if((pid = fork()) == 0) | |
{ | |
if(pipeline->redirection_list->length > 1) // use pipe | |
{ | |
int redirection_node_index = 0; | |
struct Node* redirection_node = pipeline->redirection_list->tail; | |
while(redirection_node_index < pipeline->redirection_list->length - 1) | |
{ | |
int pipe_fd[2]; | |
struct Node* next_node = redirection_node->prev; | |
if(pipe(pipe_fd) < 0) | |
{ | |
perror("pipe error\n"); | |
break; | |
} | |
if(fork() == 0) | |
{ | |
close(pipe_fd[0]); | |
close(STDOUT_FILENO); | |
dup(pipe_fd[1]); | |
execute_redirection((struct Redirection*)redirection_node->item); | |
} | |
close(pipe_fd[1]); | |
close(STDIN_FILENO); | |
dup(pipe_fd[0]); | |
redirection_node_index++; | |
redirection_node = next_node; | |
if(redirection_node_index == pipeline->redirection_list->length - 1){ | |
execute_redirection((struct Redirection*)redirection_node->item); | |
} | |
} | |
} | |
execute_redirection((struct Redirection*)pipeline->redirection_list->head->item); | |
} | |
if(!pipeline->run_in_background){ | |
waitpid(pid, &status, 0); | |
} | |
} | |
void print_shell_info() | |
{ | |
printf("System Programming minishell\n"); | |
} | |
void print_cwdir() | |
{ | |
char cwdir[BUFFER_SIZE]; | |
char* to_print = NULL; | |
getcwd(cwdir, BUFFER_SIZE); | |
to_print = strcat(basename(cwdir), "$ "); | |
write(STDOUT_FILENO, to_print, strlen(to_print)); | |
} | |
int main(int argc, const char * argv[]) | |
{ | |
char* input_buffer=(char*)malloc(BUFFER_SIZE); | |
ssize_t bytes_read = 0; | |
print_shell_info(); | |
print_cwdir(); | |
while((bytes_read = read(STDIN_FILENO, input_buffer, BUFFER_SIZE))) | |
{ | |
char* input_string = NULL; | |
struct Queue* command_queue = NULL; | |
struct Queue* history_queue = NULL; | |
if(bytes_read < 0) continue; | |
input_string = strndup(input_buffer, strlen(input_buffer)); | |
history_queue = get_history_queue(); | |
append_history(strndup(input_string, strlen(input_string) - 1)); | |
command_queue = parse_input_string(input_string); | |
queue_for_each(command_queue, &for_each_command_node); | |
queue_delete(command_queue); | |
memset(input_buffer, 0, BUFFER_SIZE); | |
free(input_string); | |
fflush(stdin); | |
print_cwdir(); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment