Skip to content

Instantly share code, notes, and snippets.

@SungjinYoo
Last active August 29, 2015 14:09
Show Gist options
  • Save SungjinYoo/817a106c942cf4a7c1ef to your computer and use it in GitHub Desktop.
Save SungjinYoo/817a106c942cf4a7c1ef to your computer and use it in GitHub Desktop.
//
// 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