#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#define MAX_INPUT_SIZE 4096
#define MAX_TOKEN_SIZE 64
#define MAX_NUM_TOKENS 64
#define TOKEN_CNT 64
typedef enum {false, true} bool;
// 문자열을 공백 단위로 tokenizing해 char *배열로 return하는 함수
// same as parse_line func.
char **tokenize(char *line_p)
{
char **tokens = (char **)malloc(MAX_NUM_TOKENS * sizeof(char *));
char *now_token = (char *)malloc(MAX_TOKEN_SIZE * sizeof(char));
int token_idx = 0; // tokens에서의 idx (현재 몇번째 token인가)
int char_idx = 0; // tokens[token_idx]에서의 idx
for (int i =0; i < strlen(line_p); i++) { // line 순회
char ch = line_p[i];
if (ch == ' ' || ch == '\n' || ch == '\t' || ch == '\0') { // 공백문자일 경우 tokenize
if (char_idx != 0) {
now_token[char_idx] = '\0'; // 현재 token 마지막 null문자 추가
tokens[token_idx] = (char*)malloc(MAX_TOKEN_SIZE*sizeof(char)); // 다음 token 동적 할당
if (!strcmp("pps", now_token) || !strcmp("ttop", now_token)) { // 상대 경로로 변경
strcpy(tokens[token_idx], "./");
strcat(tokens[token_idx++], now_token); // 현재 tokens[token_idx]에 복사
}
else {
strcpy(tokens[token_idx++], now_token); // 현재 tokens[token_idx]에 복사
}
char_idx = 0;
}
}
else {
now_token[char_idx++] = ch;
}
}
free(now_token);
tokens[token_idx] = NULL;
return tokens;
}
// 파이프 처리하는 함수
void do_pipe(char **tokens, int pipe_idx[TOKEN_CNT], int pipe_cnt)
{
int pipes[TOKEN_CNT][2] = {0, }; // 파이프 목록
int pid;
int status;
/***** 1번째 명령어 실행 *****/
pipe(pipes[0]); // 파이프 생성
if ((pid = fork()) < 0) {
fprintf(stderr, "fork() error\n");
exit(1);
}
else if (pid == 0) {
close(STDOUT_FILENO); // stdout close
dup2(pipes[0][1], STDOUT_FILENO); // 0번째 pipe stdout에 복사
close(pipes[0][1]); // pipe close
execvp(tokens[pipe_idx[0]], &tokens[pipe_idx[0]]); // exec
fprintf(stderr, "execvp() error\n");
}
close(pipes[0][1]); // pipe close
wait(&status); // exec 종료까지 대기
if (WIFSIGNALED(status) || WIFSTOPPED(status)) {
exit(1);
}
/***** 마지막 명령어 제외 모두 실행 *****/
for (int i = 0; i < pipe_cnt - 1; i++) {
pipe(pipes[i+1]); // 파이프 생성
if ((pid = fork()) < 0) {
fprintf(stderr, "fork() error\n");
exit(1);
}
else if (pid == 0) {
close(STDIN_FILENO); // stdin close
close(STDOUT_FILENO); // stdout close
dup2(pipes[i][0], STDIN_FILENO); // pipe stdin에 복사
dup2(pipes[i+1][1], STDOUT_FILENO); // pipe stdout에 복사
close(pipes[i][0]); // pipe close
close(pipes[i+1][1]); // pipe close
execvp(tokens[pipe_idx[i+1]], &tokens[pipe_idx[i+1]]); // exec
fprintf(stderr, "execvp() error\n");
}
close(pipes[i+1][1]); // pipe close
wait(&status); // exec 종료까지 대기
if (WIFSIGNALED(status) || WIFSTOPPED(status))
exit(1);
}
/***** 마지막 명령어 실행 *****/
if ((pid = fork()) < 0) {
fprintf(stderr, "fork() error\n");
exit(1);
}
else if (pid == 0) {
close(STDIN_FILENO); // stdin close
dup2(pipes[pipe_cnt-1][0], STDIN_FILENO); // pipe stdin에 복사
close(pipes[pipe_cnt-1][0]); // pipe close
close(pipes[pipe_cnt-1][1]); // pipe close
execvp(tokens[pipe_idx[pipe_cnt]], &tokens[pipe_idx[pipe_cnt]]); // exec
}
wait(&status); // exec 종료까지 대기
if (WIFSIGNALED(status) || WIFSTOPPED(status)) {
exit(1);
}
return;
}
// 명령어 exec하는 함수
void run_commands(char **tokens)
{
bool has_pipe = false;
int pipe_cnt = 0;
int start_idx = 0;
int len = 0;
int pipe_idx[TOKEN_CNT] = {0, };
for (int i = 0; tokens[i] != NULL; i++, len++) { // 파이프 있을 경우 token NULL로 변경
if (!strcmp(tokens[i], "|")) {
tokens[i] = NULL;
pipe_idx[++pipe_cnt] = i+1; // pipdIdx에 pipe로 구분되는 token들 시작 index 저장
has_pipe = true;
}
}
if (has_pipe) {
do_pipe(tokens, pipe_idx, pipe_cnt);
}
else { // 파이프 없을 경우
if (execvp(tokens[0], tokens) < 0) {
if (errno == 2) {
fprintf(stderr, "%s: command not found\n", tokens[0]);
exit(1);
}
else {
fprintf(stderr, "execvp error! errno: %d\n", errno);
exit(1);
}
}
int status;
wait(&status);
if (WIFSIGNALED(status) || WIFSTOPPED(status)) {
exit(1);
}
}
exit(0);
}
void *getCurrentDir(void){
char *currWorkDir, *token;
char buffer[MAX_INPUT_SIZE + 1];
char *directory;
size_t length;
currWorkDir = getcwd(buffer, MAX_INPUT_SIZE + 1 );
token = strrchr(currWorkDir, '/');
if( currWorkDir == NULL ){
printf("Error"); /* You decide here */
exit(1);
}
if (token == NULL) {
printf("Error"); /* You decide here */
exit(1);
}
length = strlen(token);
directory = malloc(length);
memcpy(directory, token+1, length);
return directory;
}
//This is the main function of the program.
int main(int argc, char* argv[])
{
char line_p[MAX_INPUT_SIZE];
char **tokens;
int i;
FILE* fp;
char *dir = getCurrentDir();
if (argc == 2) { // batch mode인 경우
if ((access(argv[1], F_OK)) < 0) {
fprintf(stderr, "File doesn't exists.\n");
return -1;
}
if ((fp = fopen(argv[1],"r")) < 0) {
fprintf(stderr, "fopen error for %s\n", argv[1]);
return -1;
}
}
while (1) { // 무한 반복
/* 입력 시작 */
bzero(line_p, sizeof(line_p));
if (argc == 2) { // batch mode인 경우
if (fgets(line_p, sizeof(line_p), fp) == NULL) { // file 모두 읽었을 경우
break;
}
line_p[strlen(line_p) - 1] = '\0';
}
else { // interactive mode인 경우
printf("gosh@%s> ", dir);
scanf("%[^\n]", line_p);
getchar();
free(dir);
}
/* 입력 완료 */
line_p[strlen(line_p)] = '\n'; // 개행 문자 추가
tokens = tokenize(line_p); // tokenizing
if (!tokens[0]) { // 입력 x 처리
continue;
}
int pid;
if ((pid = fork()) < 0) { // 자식 process 생성
fprintf(stderr, "vfork error!\n");
exit(1);
}
else if (pid == 0) { // 자식 프로세스인 경우
run_commands(tokens);
}
else { // 본 프로세스인 경우
int status;
waitpid(pid, &status, 0);
if (WIFSIGNALED(status) || WIFSTOPPED(status) || WEXITSTATUS(status) == 1) { // 에러 발생 처리
fprintf(stderr, "SSUShell : Incorrect command\n");
}
for (i=0;tokens[i]!=NULL;i++) { // 동적 할당 해제
free(tokens[i]);
}
free(tokens);
}
}
return 0;
}
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#define MAX_INPUT_SIZE 1024
#define MAX_TOKEN_SIZE 64
#define MAX_NUM_TOKENS 64
#define TOKEN_CNT 64
#include "else.h"
typedef enum {false, true} bool;
// 문자열을 공백 단위로 tokenizing해 char *배열로 return하는 함수
char **tokenize(char *line_p)
{
char **tokens = (char **)malloc(MAX_NUM_TOKENS * sizeof(char *));
char *now_token = (char *)malloc(MAX_TOKEN_SIZE * sizeof(char));
int token_idx = 0; // tokens에서의 idx (현재 몇번째 token인가)
int char_idx = 0; // tokens[token_idx]에서의 idx
for (int i =0; i < strlen(line_p); i++) { // line 순회
char ch = line_p[i];
if (ch == ' ' || ch == '\n' || ch == '\t' || ch == '\0') { // 공백문자일 경우 tokenize
if (char_idx != 0) {
now_token[char_idx] = '\0'; // 현재 token 마지막 null문자 추가
tokens[token_idx] = (char*)malloc(MAX_TOKEN_SIZE*sizeof(char)); // 다음 token 동적 할당
if (!strcmp("pps", now_token) || !strcmp("ttop", now_token)) { // 상대 경로로 변경
strcpy(tokens[token_idx], "./");
strcat(tokens[token_idx++], now_token); // 현재 tokens[token_idx]에 복사
}
else {
strcpy(tokens[token_idx++], now_token); // 현재 tokens[token_idx]에 복사
}
char_idx = 0;
}
}
else {
now_token[char_idx++] = ch;
}
}
free(now_token);
tokens[token_idx] = NULL;
return tokens;
}
// 파이프 처리하는 함수
void do_pipe(char **tokens, int pipe_idx[TOKEN_CNT], int pipe_cnt)
{
int pipes[TOKEN_CNT][2] = {0, }; // 파이프 목록
int pid;
int status;
/***** 1번째 명령어 실행 *****/
pipe(pipes[0]); // 파이프 생성
if ((pid = fork()) < 0) {
fprintf(stderr, "fork() error\n");
exit(1);
}
else if (pid == 0) {
close(STDOUT_FILENO); // stdout close
dup2(pipes[0][1], STDOUT_FILENO); // 0번째 pipe stdout에 복사
close(pipes[0][1]); // pipe close
execvp(tokens[pipe_idx[0]], &tokens[pipe_idx[0]]); // exec
fprintf(stderr, "execvp() error\n");
}
close(pipes[0][1]); // pipe close
wait(&status); // exec 종료까지 대기
if (WIFSIGNALED(status) || WIFSTOPPED(status)) {
exit(1);
}
/***** 마지막 명령어 제외 모두 실행 *****/
for (int i = 0; i < pipe_cnt - 1; i++) {
pipe(pipes[i+1]); // 파이프 생성
if ((pid = fork()) < 0) {
fprintf(stderr, "fork() error\n");
exit(1);
}
else if (pid == 0) {
close(STDIN_FILENO); // stdin close
close(STDOUT_FILENO); // stdout close
dup2(pipes[i][0], STDIN_FILENO); // pipe stdin에 복사
dup2(pipes[i+1][1], STDOUT_FILENO); // pipe stdout에 복사
close(pipes[i][0]); // pipe close
close(pipes[i+1][1]); // pipe close
execvp(tokens[pipe_idx[i+1]], &tokens[pipe_idx[i+1]]); // exec
fprintf(stderr, "execvp() error\n");
}
close(pipes[i+1][1]); // pipe close
wait(&status); // exec 종료까지 대기
if (WIFSIGNALED(status) || WIFSTOPPED(status))
exit(1);
}
/***** 마지막 명령어 실행 *****/
if ((pid = fork()) < 0) {
fprintf(stderr, "fork() error\n");
exit(1);
}
else if (pid == 0) {
close(STDIN_FILENO); // stdin close
dup2(pipes[pipe_cnt-1][0], STDIN_FILENO); // pipe stdin에 복사
close(pipes[pipe_cnt-1][0]); // pipe close
close(pipes[pipe_cnt-1][1]); // pipe close
execvp(tokens[pipe_idx[pipe_cnt]], &tokens[pipe_idx[pipe_cnt]]); // exec
}
wait(&status); // exec 종료까지 대기
if (WIFSIGNALED(status) || WIFSTOPPED(status)) {
exit(1);
}
return;
}
// 명령어 exec하는 함수
void run_commands(char **tokens)
{
bool has_pipe = false;
int pipe_cnt = 0;
int start_idx = 0;
int len = 0;
int pipe_idx[TOKEN_CNT] = {0, };
for (int i = 0; tokens[i] != NULL; i++, len++) { // 파이프 있을 경우 token NULL로 변경
if (!strcmp(tokens[i], "|")) {
tokens[i] = NULL;
pipe_idx[++pipe_cnt] = i+1; // pipdIdx에 pipe로 구분되는 token들 시작 index 저장
has_pipe = true;
}
}
if (has_pipe) {
do_pipe(tokens, pipe_idx, pipe_cnt);
}
else { // 파이프 없을 경우
if (execvp(tokens[0], tokens) < 0) {
if (errno == 2) {
fprintf(stderr, "%s: command not found\n", tokens[0]);
exit(1);
}
else {
fprintf(stderr, "execvp error! errno: %d\n", errno);
exit(1);
}
}
int status;
wait(&status);
if (WIFSIGNALED(status) || WIFSTOPPED(status)) {
exit(1);
}
}
exit(0);
}
int main(int argc, char* argv[])
{
char *line;
char **args;
int status;
char line_p[MAX_INPUT_SIZE];
char **tokens;
int i;
FILE* fp;
if (argc == 2) { // batch mode인 경우
if ((access(argv[1], F_OK)) < 0) {
fprintf(stderr, "File doesn't exists.\n");
return -1;
}
if ((fp = fopen(argv[1],"r")) < 0) {
fprintf(stderr, "fopen error for %s\n", argv[1]);
return -1;
}
}
while (1) { // 무한 반복
/* 입력 시작 */
bzero(line_p, sizeof(line_p));
if (argc == 2) { // batch mode인 경우
if (fgets(line_p, sizeof(line_p), fp) == NULL) { // file 모두 읽었을 경우
break;
}
line_p[strlen(line_p) - 1] = '\0';
}
else { // interactive mode인 경우
char *dir = getCurrentDir();
printf("gosh@%s> ", dir);
scanf("%[^\n]", line_p);
getchar();
}
/* 입력 완료 */
line_p[strlen(line_p)] = '\n'; // 개행 문자 추가
tokens = tokenize(line_p); // tokenizing
if (!tokens[0]) { // 입력 x 처리
continue;
}
int pid;
if ((pid = fork()) < 0) { // 자식 process 생성
fprintf(stderr, "vfork error!\n");
exit(1);
}
else if (pid == 0) { // 자식 프로세스인 경우
run_commands(tokens);
}
else { // 본 프로세스인 경우
int status;
waitpid(pid, &status, 0);
if (WIFSIGNALED(status) || WIFSTOPPED(status) || WEXITSTATUS(status) == 1) { // 에러 발생 처리
fprintf(stderr, "SSUShell : Incorrect command\n");
}
for (i=0;tokens[i]!=NULL;i++) { // 동적 할당 해제
free(tokens[i]);
}
free(tokens);
}
line = read_line();
args = parse_line(line);
status = dispatch_command(args);
free(line);
free(args);
}
return 0;
}
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#define PATH_MAX 4096
#include "else.h"
void error(const char *msg)
{
perror(msg);
exit(EXIT_FAILURE);
}
void cisshPipe(char **command1, char **command2)
{
int fd[2];
pid_t childPid;
if (pipe(fd) != 0)
error("failed to create pipe");
if ((childPid = fork()) == -1)
error("failed to fork");
if (childPid == 0)
{
dup2(fd[1], 1);
close(fd[0]);
close(fd[1]);
execvp(command1[0], command1);
error("failed to exec command 1");
}
else
{
dup2(fd[0], 0);
close(fd[0]);
close(fd[1]);
execvp(command2[0], command2);
error("failed to exec command 2");
}
}
//reading the user input.
char *read_line(){
char *line = NULL;
ssize_t bufsize = 0;
getline(&line, &bufsize, stdin);
return line;
}
//parsing the user input.
char **parse_line(char *line){
int bufsize = 64, position = 0;
char **tokens = malloc(bufsize * sizeof(char*));
char *token;
token = strtok(line, " \t\r\n\a");
while (token != NULL) {
tokens[position] = token;
position++;
if (position >= bufsize) {
bufsize += 64;
tokens = realloc(tokens, bufsize * sizeof(char*));
}
token = strtok(NULL, " \t\r\n\a");
}
tokens[position] = NULL;
return tokens;
}
//This function is responsible for executing commands.
int execute_line(char **args){
int status;
pid_t pid;
pid = fork();
if (pid == 0) {
if (execvp(args[0], args) == -1) {
perror("go/sh");
}
exit(EXIT_FAILURE);
} else if (pid < 0) {
perror("go/sh");
} else {
do {
waitpid(pid, &status, WUNTRACED);
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
}
return 1;
}
//This function is responsible for changing the directory.
int cd(char **args){
if (args[1] == NULL) {
fprintf(stderr, "go/sh: expected argument to \"cd\"\n");
} else {
if (chdir(args[1]) != 0) {
perror("go/sh");
}
}
return 1;
}
//This function is responsible for displaying help information.
int help(char **args){
printf("go/sh - Simple UNIX Shell\n\n");
printf("The following are built-in commands supported by go/sh\n");
printf("cd\t\tChange the working directory\n");
printf("help\t\tDisplay this help information\n");
printf("exit\t\tExit go/sh\n");
return 1;
}
//This function is responsible for exiting go/sh.
int go_sh_exit(char **args){
return 0;
}
//This function is responsible for dispatching the commands.
int dispatch_command(char **args){
char *builtin_str[] = {
"cd",
"help",
"exit"
"sort"
"error"
};
int (*builtin_func[]) (char **) = {
&cd,
&help,
&go_sh_exit,
cisshPipe,
error
};
int i;
if (args[0] == NULL) {
return 1;
}
for (i = 0; i < 5; i++) {
if (strcmp(args[0], builtin_str[i]) == 0) {
return (*builtin_func[i])(args);
}
}
return execute_line(args);
}
void *getCurrentDir(void){
char *currWorkDir, *token;
char buffer[PATH_MAX + 1];
char *directory;
size_t length;
currWorkDir = getcwd(buffer, PATH_MAX + 1 );
token = strrchr(currWorkDir, '/');
if( currWorkDir == NULL ){
printf("Error"); /* You decide here */
exit(1);
}
if (token == NULL) {
printf("Error"); /* You decide here */
exit(1);
}
length = strlen(token);
directory = malloc(length);
memcpy(directory, token+1, length);
return directory;
}
#ifndef ELSE_H
#define ELSE_H
#include "else.h"
char *read_line();
char **parse_line(char *line);
int execute_line(char **args);
int cd(char **args);
int help(char **args);
int go_sh_exit(char **args);
int dispatch_command(char **args);
void *getCurrentDir(void);
#endif
pipe : pipe.o else.o
gcc -o pipe pipe.o else.o
pipe.o : pipe.c
gcc -c -o pipe.o pipe.c
else.o : else.c
gcc -c -o else.o else.c
clean :
rm *.o pipe
shell : shell.o else.o
gcc -o shell shell.o else.o
shell.o : shell.c
gcc -c -o shell.o shell.c
else.o : else.c
gcc -c -o else.o else.c
clean :
rm *.o shell
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#define MAX_INPUT_SIZE 1024
#define MAX_TOKEN_SIZE 64
#define MAX_NUM_TOKENS 64
#define TOKEN_CNT 64
#include "else.h"
typedef enum {false, true} bool;
char **tokenize(char *line_p)
{
char **tokens = (char **)malloc(MAX_NUM_TOKENS * sizeof(char *));
char *now_token = (char *)malloc(MAX_TOKEN_SIZE * sizeof(char));
int token_idx = 0;
int char_idx = 0;
for (int i =0; i < strlen(line_p); i++) {
char ch = line_p[i];
if (ch == ' ' || ch == '\n' || ch == '\t' || ch == '\0') {
if (char_idx != 0) {
now_token[char_idx] = '\0';
tokens[token_idx] = (char*)malloc(MAX_TOKEN_SIZE*sizeof(char));
if (!strcmp("pps", now_token) || !strcmp("ttop", now_token)) {
strcpy(tokens[token_idx], "./");
strcat(tokens[token_idx++], now_token);
}
else {
strcpy(tokens[token_idx++], now_token);
}
char_idx = 0;
}
}
else {
now_token[char_idx++] = ch;
}
}
free(now_token);
tokens[token_idx] = NULL;
return tokens;
}
//pipe
void do_pipe(char **tokens, int pipe_idx[TOKEN_CNT], int pipe_cnt)
{
int pipes[TOKEN_CNT][2] = {0, }; // pipes
int pid;
int status;
/***** first command *****/
pipe(pipes[0]); // pipe
if ((pid = fork()) < 0) {
fprintf(stderr, "fork() error\n");
exit(1);
}
else if (pid == 0) {
close(STDOUT_FILENO); // stdout close
dup2(pipes[0][1], STDOUT_FILENO); // cp pipe[0] to stdout
close(pipes[0][1]); // pipe close
execvp(tokens[pipe_idx[0]], &tokens[pipe_idx[0]]); // exec
fprintf(stderr, "execvp() error\n");
}
close(pipes[0][1]); // pipe close
wait(&status); // wit for exec term
if (WIFSIGNALED(status) || WIFSTOPPED(status)) {
exit(1);
}
/***** execute commands except last command *****/
for (int i = 0; i < pipe_cnt - 1; i++) {
pipe(pipes[i+1]); // pipe
if ((pid = fork()) < 0) {
fprintf(stderr, "fork() error\n");
exit(1);
}
else if (pid == 0) {
close(STDIN_FILENO); // stdin close
close(STDOUT_FILENO); // stdout close
dup2(pipes[i][0], STDIN_FILENO); // cp to pipe stdin
dup2(pipes[i+1][1], STDOUT_FILENO); // cp to pipe stdout
close(pipes[i][0]); // pipe close
close(pipes[i+1][1]); // pipe close
execvp(tokens[pipe_idx[i+1]], &tokens[pipe_idx[i+1]]); // exec
fprintf(stderr, "execvp() error\n");
}
close(pipes[i+1][1]); // pipe close
wait(&status); // wait exec terminate
if (WIFSIGNALED(status) || WIFSTOPPED(status))
exit(1);
}
/***** excute last command *****/
if ((pid = fork()) < 0) {
fprintf(stderr, "fork() error\n");
exit(1);
}
else if (pid == 0) {
close(STDIN_FILENO); // stdin close
dup2(pipes[pipe_cnt-1][0], STDIN_FILENO); // cp to pipe stdin
close(pipes[pipe_cnt-1][0]); // pipe close
close(pipes[pipe_cnt-1][1]); // pipe close
execvp(tokens[pipe_idx[pipe_cnt]], &tokens[pipe_idx[pipe_cnt]]); // exec
}
wait(&status); // wait exec terminate
if (WIFSIGNALED(status) || WIFSTOPPED(status)) {
exit(1);
}
return;
}
// function for exec command
void run_commands(char **tokens)
{
bool has_pipe = false;
int pipe_cnt = 0;
int start_idx = 0;
int len = 0;
int pipe_idx[TOKEN_CNT] = {0, };
for (int i = 0; tokens[i] != NULL; i++, len++) { // change token NULL when command exist
if (!strcmp(tokens[i], "|")) {
tokens[i] = NULL;
pipe_idx[++pipe_cnt] = i+1;
has_pipe = true;
}
else if (!strcmp(tokens[i], "<")) {
int fd = open(tokens[i+1], O_RDONLY);
if (fd < 0) {
fprintf(stderr, "Failed to open file '%s'\n", tokens[i+1]);
exit(1);
}
dup2(fd, STDIN_FILENO);
close(fd);
tokens[i] = NULL;
i++;
}
else if (!strcmp(tokens[i], ">")) {
int fd = open(tokens[i+1], O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd < 0) {
fprintf(stderr, "Failed to open file '%s'\n", tokens[i+1]);
exit(1);
}
dup2(fd, STDOUT_FILENO);
close(fd);
tokens[i] = NULL;
i++;
} else if (!strcmp(tokens[i], "sort")) {
// execute sort command
execvp("sort", &tokens[i]);
fprintf(stderr, "Failed to execute sort command\n");
exit(1);
}
}
if (has_pipe) {
do_pipe(tokens, pipe_idx, pipe_cnt);
}
else { // no pipe
if (execvp(tokens[0], tokens) < 0) {
if (errno == 2) {
fprintf(stderr, "%s: command not found\n", tokens[0]);
exit(1);
}
else {
fprintf(stderr, "execvp error! errno: %d\n", errno);
exit(1);
}
}
int status;
wait(&status);
if (WIFSIGNALED(status) || WIFSTOPPED(status)) {
exit(1);
}
}
exit(0);
}
int main(int argc, char* argv[])
{
char *line;
char **args;
int status;
char line_p[MAX_INPUT_SIZE];
char **tokens;
int i;
FILE* fp;
if (argc == 2) { // batch mode
if ((access(argv[1], F_OK)) < 0) {
fprintf(stderr, "File doesn't exists.\n");
return -1;
}
if ((fp = fopen(argv[1],"r")) < 0) {
fprintf(stderr, "fopen error for %s\n", argv[1]);
return -1;
}
}
while (1) { // infinite loop
/* input */
bzero(line_p, sizeof(line_p));
if (argc == 2) { // batch mode
if (fgets(line_p, sizeof(line_p), fp) == NULL) { // read all file
break;
}
line_p[strlen(line_p) - 1] = '\0';
}
else { // interactive mode
char *dir = getCurrentDir();
printf("gosh@%s> ", dir);
scanf("%[^\n]", line_p);
getchar();
}
/* input done */
line_p[strlen(line_p)] = '\n';
tokens = tokenize(line_p); // tokenizing
if (!tokens[0]) {
continue;
}
int pid;
if ((pid = fork()) < 0) { // child process
fprintf(stderr, "vfork error!\n");
exit(1);
}
else if (pid == 0) { // if child procedd
run_commands(tokens);
}
else { // if parent process
int status;
waitpid(pid, &status, 0);
if (WIFSIGNALED(status) || WIFSTOPPED(status) || WEXITSTATUS(status) == 1) { //error
fprintf(stderr, "SSUShell : Incorrect command\n");
}
for (i=0;tokens[i]!=NULL;i++) { // free alloc
free(tokens[i]);
}
free(tokens);
}
line = read_line();
args = parse_line(line);
status = dispatch_command(args);
free(line);
free(args);
}
return 0;
}