[42seoul] minishell (1)

ppparkta·2023년 3월 7일
1

42Seoul

목록 보기
6/7

built-in

특정 실행파일을 직접 만들어서 minishell 안에서 실행시켜야 한다. 만들어야 하는 함수는 총 7개이다. ( cd, pwd, echo, env, export, unset, exit )


pwd

char *getcwd (char *buff, size_t buff_size)

  • getcwdbuff에 현재 절대경로를 할당한다.
  • 반환값
    • 성공 시 buff에 NULL이 아닌 값
    • 실패 시 NULL

현재 절대경로를 출력하는 함수이다. 따라서 getcwd만 사용하면 바로 구현할 수 있다.


cd

int chdir(const char *path)

  • 현재 작업 디렉터리를 변경한다.
  • path : 변경할 디렉터리 경로
  • 반환값
    • 성공 시 0
    • 실패 시 -1

상대경로, 절대경로를 고려해서 위치를 이동시키는 함수이다. 마찬가지로 getcwd()를 사용해서 현재 경로를 구한 뒤 chdir()을 사용해서 입력받은 경로로 이동해야 한다.

특징 1

$cd .		#현재 폴더
$cd ..		#현재 폴더의 상위 폴더
$cd ~		#루트 경로

., ..은 경로 중간에 들어가도 괜찮은 듯 하지만 ~은 경로 중간에 들어가면 오류를 뱉는다. 항상 가장 처음에 와야 한다.

특징 2

$cd /minishell		#오류 반환
$cd ./minishell		#정상 이동

가장 처음에 /가 와도 오류를 뱉는다. 이런 부분은 어떻게 고려해야 하는지 고민했는데 chdir을 사용하면 쉽게 해결...!

고려사항

  • cd ~는 직접 구현해야 함
  • built-in으로 cd를 구현해서 실행시키면 환경변수 $PWD의 값은 변하지 않는다. 따라서 환경변수의 값을 수동으로 관리해야 한다.
  • cd로 인해 $PWD의 값이 변경된 경우, 이전 $PWD를 의미하는 $OLDPWD의 값이 추가된다.
  • unset PWD로 PWD의 환경변수를 삭제한 경우, cd로 PWD의 값이 변경돼도 환경변수가 새로 생기지 않는다.

env

이 함수는 모든 환경변수를 출력하는 함수이다.
cd함수를 만들면서, 환경변수를 고려해야 하는 함수가 많다는걸 깨달았다...! cd, echo, export, unset 모두 환경변수를 고려해야 한다. 그래서 우선 env를 만들기로 했다.

우리 팀은 환경변수를 연결리스트로 새로 만들어서 관리하기로 했다. 수정 / 삭제가 필요하기 때문에 원활한 관리를 위해 다음과 같이 구조체를 설정했다.

typedef struct s_env
{
  char			*key;
  char			*value;
  struct s_env	*next;
}	t_env;

연결리스트만 잘 만들어주면 그 연결리스트를 형식대로 출력하면 되므로 간단히 완성했다.


export

export는 인자가 없을 때 환경변수의 값을 출력하고, 인자가 있을 때 환경변수를 추가/수정하는 함수이다.

인자가 없는 경우 간단히 출력만 하면 되고, 인자가 있는 경우 신경써야 할 조건이 많다. 여러개의 부속 함수를 만들어서 아래의 고려사항을 충족하는 함수를 만들었다.

개인적으로 빌트인 함수 중 가장 고려할 부분이 많아서 구현이 까다로웠다.

고려사항

  • 환경변수의 key 첫글자에는 알파벳과 _ 만 올 수 있다.
  • 첫글자 다음의 글자에는 알파벳, 숫자, _만 올 수 있다.
  • 형식은 항상 환경변수명=값 의 형태로 받아와야 한다. 띄어쓰기 금지!
  • =이 없는 경우에도 값을 추가한다. 다만 env로 출력되지는 않는다.
  • =이 여러개일 때 가장 처음 나온 문자를 기준으로 split한다.
  • 인자가 여러개일 때 모든 인자에 대해 처리한다.
  • 인자가 없을 때 모든 환경변수 목록을 특정한 형태로 출력한다.

내 로직

  • 들어온 문자열에서 key와 value를 구한다.
  • 구한 key가 유효한 값인지 확인한다.
    • 환경변수 리스트가 비었다면 새 노드를 만들어서 반환한다.
    • 노드가 하나라도 존재하고 key가 환경변수에 없다면 새 노드를 만들어서 리스트 마지막에 추가하고 추가한 노드를 반환한다.
    • 반환받은 노드의 value를 수정한다.

unset

export가 환경변수를 추가하는 함수였다면, unset은 환경변수를 삭제하는 함수이다.

고려사항

  • 마찬가지로 첫글자에 알파벳, _만 올 수 있고 그 뒤에는 알파벳, 숫자, _만 올 수 있다.
  • 인자가 여러개일 때 모든 인자에 대해 처리한다.
  • 인자가 없는 경우 아무 작동 없이 종료된다.

echo

echo는 인자로 받은 값을 터미널에 출력하는 함수이다. 빌트인 함수 중 유일하게 옵션을 신경써야 하는 함수이다.

고려사항

  • -n 옵션, 해당 옵션을 사용할 시 개행을 모두 제거하고 출력해야 한다.
  • -nnnnnnnnnnnn 도 n옵션으로 처리해야 한다. (-n2n 은 해당 안 됨)
  • -n -n -n -n -n 도 n옵션으로 처리해야 한다.
  • $로 시작하는 인자는 환경변수의 value을 출력해야 한다. (이건 파싱할 때 처리해야 함)

exit

exit은 프로세스를 끝내는 함수이다. 인자가 있는 경우, 없는 경우 모두 고려해야 한다.

고려사항

  • 인자가 없는 경우 정상적으로 프로세스를 종료해야 한다.
  • 인자가 두개 이상인 경우 exit: too many arguments라는 오류 문구와 함께 터미널로 돌아가야 한다. (프로세스가 종료되지 않음)
  • 인자에 숫자가 아닌 값이 들어간 경우 numeric argument required라는 오류 문구와 함께 프로세스가 종료돼야 한다.
  • 그 외의 경우 인자를 exit의 인자로 끝내야 한다.

추가

  • 임시 연결리스트 만들어서 출력 결과 확인해야 함.
  • 현재 코드는 built-in함수를 사용할 때 환경변수 포인터를 인자로 받아오는데, exit status와 함께 전역변수로 관리해야 예외처리할 때 더 편할거같다.
profile
겉촉속촉

0개의 댓글