시험 시작
id / pw⇒exam / exam- shell에 바로
examshell이라고 치기./examshell이라고 치면 실행이 안됨.
git init치지 말아야 함! 중요!rendu폴더에서git add .git commit -mgit push하기
문제
python
Assignment name : microshell
Expected files : *.c *.h
Allowed functions: malloc, free, write, close, fork, waitpid, signal, kill, exit, chdir, execve, dup, dup2, pipe, strcmp, strncmp
--------------------------------------------------------------------------------------
Write a program that will behave like executing a shell command
- The command line to execute will be the arguments of this program
- Executable's path will be absolute or relative but your program must not build a path (from the PATH variable for example)
- You must implement "|" and ";" like in bash
- we will never try a "|" immediately followed or preceded by nothing or "|" or ";"
- Your program must implement the built-in command cd only with a path as argument (no '-' or without parameters)
- if cd has the wrong number of argument your program should print in STDERR "error: cd: bad arguments" followed by a '\n'
- if cd failed your program should print in STDERR "error: cd: cannot change directory to path_to_change" followed by a '\n' with path_to_change replaced by the argument to cd
- a cd command will never be immediately followed or preceded by a "|"
- You don't need to manage any type of wildcards (*, ~ etc...)
- You don't need to manage environment variables ($BLA ...)
- If a system call, except execve and chdir, returns an error your program should immediatly print "error: fatal" in STDERR followed by a '\n' and the program should exit
- If execve failed you should print "error: cannot execute executable_that_failed" in STDERR followed by a '\n' with executable_that_failed replaced with the path of the failed executable (It should be the first argument of execve)
- Your program should be able to manage more than hundreds of "|" even if we limit the number of "open files" to less than 30.
for example this should work:
$>./microshell /bin/ls "|" /usr/bin/grep microshell ";" /bin/echo i love my microshell
microshell
i love my microshell
$>
Hints:
Don't forget to pass the environment variable to execve
Hints:
Do not leak file descriptors!
구현
헤더
c
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
main 함수
c
int main(int ac, char **av, char **env)
{
int i = 0;
int status = 0;
if (ac > 1)
{
while (av[i] && av[++i])
{
av += i; // 포인터 av의 위치는 항상 |나 ;로 가게끔 설정
i = 0;
while (av[i] && strcmp(av[i], "|") && strcmp(av[i], ";"))
i++;
if (!strcmp(*av, "cd")) // 포인터 *av가 cd를 가리킬 경우
status = cd(av, i);
else if (i)
status = exec(av, env, i);
}
}
return (status);
}
cd 함수와 err 함수
c
int err(char *str)
{
while (*str)
write(2, str++, 1);
return (1);
}
int cd(char **av, int i)
{
if (i != 2)
return (err("error: cd: bad arguments\n"));
else if (chdir(av[1]) == -1)
return (err("error: cd : cannot change directory to "), err(av[1]), err("\n"));
return (0);
}
exec 함수
c
int exec(char **av, char **env, int i)
{
int fd[2];
int status;
int has_pipe = av[i] && !strcmp(av[i], "|");
if (has_pipe && pipe(fd) == -1)
return (err("error: fatal\n"));
int pid = fork();
if (!pid)
{
av[i] = 0;
if (has_pipe && (dup2(fd[1], 1) == -1 || close(fd[0]) == -1 || close(fd[1]) == -1))
return (err("error: fatal\n"));
execve(*av, av, env);
return (err("error: cannot execute "), err(*av), err("\n"));
}
waitpid(pid, &status, 0);
if (has_pipe && (dup2(fd[0], 0) == -1 || close(fd[0]) == -1 || close(fd[1]) == -1))
return (err("error: fatal\n"));
return (WIFEXITED(status) && WEXITSTATUS(status));
}
참고 사이트
github.com/pasqualerossi/42-School-Exam-Rank-04 github.com/JCluzet/42_EXAMc
bash -c "$(curl https://grademe.fr)"