Linux/쉘, 쉘 명령어 구현하기

    [쉘 구현하기] cat 기본 명령어 구현

    첫 번째 인자의 내용을 stdout으로 출력하는 기본 cat 명령어를 구현했다. argc가 1인 경우에는 사용법을 출력하도록 했고, argc가 2인 경우 기본 cat 명령어를 수행하도록 했다. 코드는 간단하다. 두 번째 인자를 읽기 전용으로 열어서 파일의 끝을 만날 때까지 읽어서 출력한다. // my_cat.c #include #include #include #include #define BUFFER_SIZE 4096 void cat(int argc, char **argv) { char buf[BUFFER_SIZE]; if (argc == 1) { fprintf(stderr, "Usage : %s {FILENAME}+\n", argv[0]); fprintf(stderr, " %s {FILENAME}+ >..

    [쉘 구현하기] cp 명령어 구현

    첫 번째 인자 파일을 두 번째 인자 파일에 복사하는 cp 명령어를 추가했다. 코드는 복잡하진 않았다. 첫 번째 인자의 파일 디스크립터(fd1)로부터 내용을 읽어서 두 번째 인자의 파일 디스크립터(fd2)로 쓰는 작업을 진행했다. 파일을 읽는 과정은 파일의 끝(EOF)을 읽을 때까지 반복된다. // my_cp.c #include #include #include #include #define BUFFER_SIZE 4096 #define PATH_MAX 4096 void cp(int argc, char **argv) { int fd1, fd2; char buf[BUFFER_SIZE]; int length; if (argc < 3) { fprintf(stderr, "Usage: %s \n", argv[0]); ..

    [쉘 구현하기] cd 명령어 에러 처리 추가

    전에 cd 명령어를 구현했을 때 존재하지 않는 디렉토리를 인자로 줬을 때 에러를 처리하는 코드를 작성하지 않았다. 그래서 "chdir error" 문장을 출력하고 프로그램이 비정상 종료가 돼버린다. 이 문제를 해결해보자. (cd 명령어를 호출 시 "이동 전 경로 -> 이동 후 경로" 문자열을 출력하는 코드는 삭제했다.) 전달 받은 인자로 chdir() 호출에 실패했을 경우 에러 발생 문장을 출력하고 exit(1)이 아닌 return ;만 하도록 수정했다. void cdExec(int argCnt, char **argList) { if (argCnt == 1) { if (chdir(homePath) < 0) { fprintf(stderr, "chdir error\n"); exit(1); } getcwd(e..

    [쉘 구현하기] cd 명령어 오류 수정

    [쉘 구현하기] cd 명령어 구현 작업 디렉토리를 변경하는 cd 명령어를 추가했다. 인자를 전달하면 해당 인자로 작업 디렉토리를 이동하고, 인자를 전달하지 않으면 홈 디렉토리로 이동한다. chdir() 함수는 프로세스 생성 시 부 seongmoahn.tistory.com cd 명령어 사용 시 프로세스를 생성하는 명령어들이 동작하지 않는 오류가 생겼다. cd 명령어 사용 시 현재 작업 디렉토리가 소스코드가 있는 위치가 아닐 경우 my_*.c 파일을 호출하는 코드들이 동작하지 않는 오류가 생겼다. 아마 execv() 함수를 호출할 때 첫 번째 인자로 전달한 경로가 현재 작업 디렉토리이기 때문인 것 같다. else if (pid == 0) { execv(execName, argList); exit(0); } ..

    [쉘 구현하기] cd 명령어 구현

    작업 디렉토리를 변경하는 cd 명령어를 추가했다. 인자를 전달하면 해당 인자로 작업 디렉토리를 이동하고, 인자를 전달하지 않으면 홈 디렉토리로 이동한다. chdir() 함수는 프로세스 생성 시 부모 프로세스에는 영향을 주지 않으므로, 프로세스를 생성하지 않았다. void cdExec(int argCnt, char **argList) { printf("%s -> ", execPath); if (argCnt == 1) { if (chdir(homePath) < 0) { fprintf(stderr, "chdir error\n"); exit(1); } getcwd(execPath, PATH_MAX); } else { if (chdir(argList[1]) < 0) { fprintf(stderr, "chdir e..

    [쉘 구현하기] vim 실행하는 명령어 구현

    SM_shell에서 vim(vi)을 실행할 수 있게 명령어를 추가했다. vim(vi)만 입력할 수도 있고, 편집(생성)할 파일의 이름을 전달할 수도 있다. // SM_shell.c #include "my_header.h" ... void vimExec(char **argList) { pid_t pid; char path[PATH_MAX]; sprintf(path, "/usr/bin/%s", argList[0]); if ((pid = fork()) < 0) { fprintf(stderr, "fork error\n"); exit(1); } else if (pid == 0) { execv(path, argList); exit(0); } else { pid = wait(NULL); } printf("\n"); ..

    [쉘 구현하기] ls 명령어 -l 옵션 추가

    ls 명령어에 -l 옵션을 추가해보자. -l 옵션은 파일 목록을 리스트 형식으로 출력하며 추가적인 정보도 함께 보여준다. 기본적으로 -l 옵션만 사용한다면 숨김 파일을 제외하고 출력한다. 출력할 때는 파일의 접근 권한, 파일의 크기, 파일의 이름을 출력한다. 옵션을 복합적으로 사용할 수도 있는데 -a 옵션과 함께 사용한다면 다음과 같이 사용할 수 있다. printList() 함수 이름을 -l 옵션을 위한 함수로 사용하기 위해 기존 printList() 함수의 이름을 printFiles() 로 변경했다. -l 옵션이 사용됐을 때는 printFiles() 함수에서 printList() 함수를 호출한다. -l 옵션을 사용하면 파일의 접근 권한도 출력해야 하기 때문에 이를 확인해 문자열로 반환하는 함수를 만들었..

    [쉘 구현하기] ls 명령어 -a 옵션 추가

    ls 명령어에 -a 옵션을 추가해보자. -a 옵션은 숨김 파일(' . '으로 시작하는 파일)도 출력하게 하는 옵션이다. 옵션은 getopt() 함수를 사용해서 검사했다. 이전 코드와 달리 printList() 함수를 호출할 때 옵션을 인식하는 매크로를 전달해줬다. (추후 다른 옵션 추가) #define OPT_A 0b00001 #define OPT_L 0b00010 #define OPT_I 0b00100 void ls(int argc, char **argv) { int opt = 0b00000; int cmd; while ((cmd = getopt(argc, argv, "a")) != -1) { switch(cmd) { case 'a': opt |= OPT_A; break; case '?': printf..