ex) 200500001$ ./a.out &
2. redirect(>), more(|)를 추가 구현하라.
ex) 200500001$ ./a.out >output
200500001$ ./a.out | more
shell.c
more..
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#define MAX 256
int main()
{
char *i;
char buf[MAX], buf1[MAX], buf2[MAX];
int fd[2],fp ,n ,status;
pid_t pid;
printf("$ 200103937 >> "); // prompt
while(fgets(buf, MAX, stdin) != NULL) // 키보드로부터 입력을기다린다.
{
// '\n' 문자만입력돠었을때, 즉only Enter press.
if(strlen(buf) == 1 || (buf[0] == NULL)){
printf("$ 200203937 >> ");
continue // 다시 키보드로부터 입력을 기다린다.
}
buf[strlen(buf)-1] = NULL;
if(!strcmp(buf,"exit")) exit(0);
// buf에 해당문자열이 있는지 검사한다.
if((i = index(buf,'|')) != NULL || (i = index(buf,'>')) != NULL || (i = index(buf,'&')) != NULL)
{
if( *i == '|') // a.out | more
{
// buf 문자열중에 exec할 파일경로를 buf1에 복사..
strncpy(buf1, buf, i - buf - 1);
pipe(fd); // 파이프생성.
pid = fork();
if(pid < 0)
{
perror(" Fork Error!! \n");
exit(1);
}
else if(pid == 0) // ./a.out
{
/* ./a.out 하여 얻은 데이터를 stdout 대신에pipe를 연결하여
pipe의 write 채널로 연결시킨다. */
close(1); // stdout close.
close(fd[0]); // pipe fd[0] close.
dup(fd[1]); // stdout 자리에pipe fd[1] 복사.
close(fd[1]); // pipe fd[1] close.
execlp(buf1,buf1,0); // 다른프로그램으로exec.
perror("execlp error!!"); // exec 실패시에러출력.
exit(1);
}
if(fork() == 0) // more exec.
{
/* stdin 채널을닫고 그 자리에 pipe의read 채널을 복사하여
pipe로부터 데이터를 read 한다. */
close(0); // stdin close.
close(fd[1]); // pipe fd[1] close.
dup(fd[0]); // stdin 자리에pipe fd[0] 복사.
close(fd[0]); // pipe fd[0] close.
// 다른프로그램으로exec.
execl("/bin/more","more", NULL, NULL);
perror(" execl error!! "); // exec 실패시에러출력.
exit(1);
}
close(fd[0]);
close(fd[1]);
wait(0); // wait child process.
wait(0); // wait child process.
}
else if( *i == '>') // ./a.out > output.
{
// buf 문자열중에 exec할 파일경로를 buf1 에복사.
strncpy(buf1, buf, i - buf - 1);
// buf 문자열중에 파일로 출력할 파일경로를 buf2 에복사.
strncpy(buf2, i + 2, buf + strlen(buf) - i - 2);
fp = creat(buf2, 0666); // 출력할 파일을 새로만든다.
pipe(fd); // 파이프생성.
pid = fork(); // process 생성
if(pid < 0){
perror(" Fork Error!! \n");
exit(0);
}
else if(pid == 0) // child process.
{
close(0); // stdin close
dup(fd[0]); // stdin 자리에pipe의write 채널을 복사한다.
close(1); // stdout close.
dup(fp); // stdin 자리에fp 복사.
close(fd[0]);
close(fd[1]);
execlp(buf1, buf1, (char*)0); // 다른 프로그램으로 exec.
perror("execlp error!!"); // exec 실패시 에러출력.
exit(1);
}
wait(0); // wait child process.
close(fp);
printf("$ 200103937 >> ");
}
else // ./a.out&
{
if(*i == '&') // buf 에background 표시가 있을때.
{
buf[strlen(buf)-1] = NULL; // exec 을위해'&' 문자제거.
}
if((pid = fork()) == 0) // child process
{
execlp(buf, buf, (char*)0); // 다른 프로그램으로 exec.
perror(" execlp error!! "); // exec 실패시 에러출력.
exit(1);
}
printf("$ 200103937 >> ");
continue
}
}
else // foreground
{
if((pid = fork()) == 0) // child process
{
execlp(buf, buf, (char*)0); // 다른 프로그램으로 exec.
perror("execlp error!!"); // exec 실패시 에러출력.
exit(1);
}
// foreground 일경우. 즉, child process 의종료를 기다린다.
// 사용자쉘은 뜨지않고 수행이 끝날때까지 block 된다.
while(wait(&status)!= pid);
printf("$ 200103937 >> ");
}
} // end of while
return 0 ;
}
댓글 없음:
댓글 쓰기