여러분의 쉘은 반드시:
Program name | minishell |
---|---|
Makefile | Yes |
External functs | printf, malloc, free, write, open, read, close, fork, wait, waitpid, wait3, wait4, signal, kill, exit, getcwd, chdir, stat, lstat, fstat, exec, dup, dup2, pipe, opendir, readdir, closedir, strerror, errno |
Lift authorized | Yes |
Description | Write a shell |
int main(int argc, char *argv[], char **envp)
{
get_g()->envs = get_key_value_list(envp); // 환경변수 세팅
while (1)
{
write(2, ">$ ", 3);
if (!get_line()) // 사용자 입력받기
continue ;
if (!(parse_words())) // 문자열 파싱하기
continue;
if (!set_cmd(get_g(), -1, 1)) // 파싱 결과 구조체에 담기
{
free_cmd(); // 오류 발생 시 메모리 해제
continue ;
}
exec_cmd(); // cmd 순서로 실행하기
free_cmd(); // 메모리 해제
}
return (0);
}
fork(), exec(), wait() 와 같은 Process 생성과 제어를 위한 System call
// test.c 파일
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
int main(int argc, char *argv[]) {
printf("pid : %d", (int) getpid()); // pid : 29260
int rc = fork();
if (rc < 0) { // (1) fork 실패
exit(1);
}
else if (rc == 0) { // (2) child 인 경우 (fork 값이 0)
printf("child (pid : %d)", (int) getpid());
char *myargs[3];
myargs[0] = strdup("cat"); // 내가 실행할 파일 이름
myargs[1] = strdup("exec.c"); // 실행할 파일에 넘겨줄 argument
myargs[2] = NULL; // end of array
execvp(myargs[0], myargs); // wc 파일 실행.
printf("this shouldn't print out"); // 실행되지 않음. ⭐️
}
else { // (3) parent case
int wc = wait(NULL); // child의 실행이 끝날 때까지 기다림
printf("parent : %d (wc : %d / pid : %d)", wc, rc, (int)getpid());
}
return 0;
}
결과
➜ webserv git:(master) ✗ gcc test.c
➜ webserv git:(master) ✗ ./a.out
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
int main(int argc, char *argv[]) {
printf("pid : %d", (int) getpid()); // pid : 29260
int rc = fork();
if (rc < 0) { // (1) fork 실패
exit(1);
}
else if (rc == 0) { // (2) child 인 경우 (fork 값이 0)
printf("child (pid : %d)", (int) getpid());
char *myargs[3];
myargs[0] = strdup("cat"); // 내가 실행할 파일 이름
myargs[1] = strdup("test.c"); // 실행할 파일에 넘겨줄 argument
myargs[2] = NULL; // end of array
execvp(myargs[0], myargs); // wc 파일 실행.
printf("this shouldn't print out"); // 실행되지 않음. ⭐️
}
else { // (3) parent case
int wc = wait(NULL); // child의 실행이 끝날 때까지 기다림
printf("\nparent of %d (wc : %d / pid : %d)", wc, rc, (int)getpid());
}
return 0;
}pid : 69260
parent of 69261 (wc : 69261 / pid : 69260)%
#include <unistd.h>
int dup(int oldfd);
int dup2(int oldfd, int newfd);
/* dup2.c */
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
int main(int argc, char **argv)
{
int fd;
if (argc != 2)
{
fprintf(stderr, "usage: %s [file name]\n", argv[0]);
return (1);
}
fd = open(argv[1], O_WRONLY);
if (fd < 0)
{
perror("failed open");
return (1);
}
if (dup2(fd, STDOUT_FILENO) == -1)
{
perror("failed dup2");
return (1);
}
printf("hello world\n");
close(fd);
return (0);
}
👉 결과
➜ Webserv_BR31 git:(master) ✗ touch a.txt
➜ Webserv_BR31 git:(master) ✗ ./a.out a.txt
➜ Webserv_BR31 git:(master) ✗ cat a.txt
hello world