본문 바로가기

LINUX/시스템 프로그래밍

[시스템프로그래밍] 쉘(shell) 만들기

728x90

시스템 프로그래밍 수강하면서 진짜 어려웠던 과제

몇 주를 머리를 싸맸는지 모르겠다.,...............,,,,,,,,,,,, 인터넷에 검색해도 안 나와서 진짜진짜 하다가 너무 화가나서.,.!!!!!!!!!!!!!!!!! 여기다 적는다.......... 이거 말고도 다른 코드들은 나의 깃허브로 커몬..,,,,,,,,, 여러분 고생ㅇ들이 많으세요 무엇보다 나도......고생했다........,,,,,,,,,,,,,,,,,,,,,,,

https://github.com/1000hyrm/SystemProgramming

 

GitHub - 1000hyrm/SystemProgramming: 리눅스 시스템프로그래밍 코드

리눅스 시스템프로그래밍 코드. Contribute to 1000hyrm/SystemProgramming development by creating an account on GitHub.

github.com


리눅스 시스템프로그래밍 마이쉘 프로그램 Linux System programming myShell program

환경 : Ubuntu / Linux 환경 언어 : C언어

  • 기존의 shell과 유사하게 무한 루프를 돌면서, 사용자의 명령을 입력받아, 입력 받은 명령을 child process가 수행하도록 한다.
  • parent process는 child process가 종료할 때까지 기다린다.
  • 이 프로그램이 수행되는 환경에 관한 내용(경로)은 .myshell 파일에 저장되어 있는 것으로 가정한다.
  • 사용자가 myshell 상에서 "date"라고 입력하면, myShell 프로그램에서는 현재 디렉토리에 있는 .myshell파일에서 PATH를 읽어서 각 경로에 "date"라는 명령이 있는지 확인
  • 명령이 있는 경우에 해당 프로그램을 실행

<결과 화면>

 

 

<코드 및 설명>

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>


int main(int argc, char *argv[]) {
	int fd, i, status, pid;
	char *pathPtr[20], allPath[1024], exStr[128], ch, line1[256];

	if ((fd = open (".myshell", O_RDONLY)) <= 0) {
		perror ("open error.");
		exit (-1);
	} //경로가 저장된 파일 오픈

	memset (allPath, 0, 1024); //allPath를 1024크기만큼 0으로 채우기
	while (1) {		// discard "PATH="
		read(fd, &ch, 1);
		if (ch=='=')
			break;
	} //파일에 PATH=라고 시작하며 경로가 저장되어있으니 그걸 제거

	read (fd, allPath, 1024); //경로를 1024만큼 읽어서 allPath에 저장
	pathPtr[0] = strtok(allPath, ":\n");

	i = 0;
	while (pathPtr[i]!=NULL) {
		printf("pathPtr[%d]=[%s]\n", i, pathPtr[i]);  
		i++;
		pathPtr[i] = strtok(NULL, ":\n");
	} //저장된 연속된 경로를 strtok를 이용해 하나씩 빼기(:를 기준으로 이어져있음)
	
    //쉘 시작
	while(1){
		printf("%% ");
		
		fgets(line1, 255, stdin); //명령어 입력
        
		//경로가 저장될 때 \n도 같이 저장되어있으니 이걸 빼주는 작업
		printf("str = %s\n", line1); //\n exist
		line1[strlen(line1)-1]='\0';
		strtok(line1, " ");
		printf("new str = %s\n", line1);
        
		strcpy (exStr, pathPtr[0]); //처음 나오는 경로를 exStr에 저장
		strcat (exStr, "/"); //리눅스에서 '경로/명령어'로 입력해야하니 /를 삽입
		printf ("-->[%s]\n", exStr);
		strcat(exStr, line1); //'경로/명령어'로 나오게끔 명령어를 경로 다음에 삽입
		
        //access는 파일 존재,권한 확인 함수
		if(access(exStr, F_OK) == 0){ //'경로/명령어'가 존재하거나 접근 가능하면
			printf("%s\n", exStr);
			printf("Existed in pathPtr[0]\n");
			
			if(fork() == 0){ //child process를 생성해서
				execl(exStr, "exe", (char *)0); //명령을 실행하도록함
				perror("fork error\n");
				exit(-1);
			}
			pid = wait(&status);
			printf("Parent: child exit. pid = [%d], status = [%x]\n", pid, status); //process id 반환
		}
		else{ //첫번째 경로에 없다면 두번째 경로에서 명령어 찾기
			strcpy(exStr, pathPtr[1]);
			strcat(exStr, "/");
			printf ("try-->[%s]\n", exStr);
			strcat(exStr, line1);
			
			if(access(exStr, F_OK) == 0){ //'경로2/명령어'가 존재한다면
				printf("%s\n", exStr);
				printf("Existed in pathPtr[1]\n");
				
				if(fork() == 0){ //child process를 생성해
					execl(exStr, "exe", (char *)0); //명령어 실행
					perror("fork error\n");
					exit(-1);
				}
				pid = wait(&status);
				printf("Parent: child exit. pid = [%d], status = [%x]\n", pid, status);
			}
			else{ //'경로2/명령어'가 존재하지 않는다면 경로3에서 찾기
				strcpy(exStr, pathPtr[2]);
				strcat(exStr, "/");
				printf ("try2-->[%s]\n", exStr);
				strcat(exStr, line1);
				
				if(access(exStr, F_OK) == 0){ //'경로3/명령어'가 존재한다면
					printf("%s\n", exStr);
					printf("Finally, Existed in pathPtr[2]\n"); //드디어 찾았다!
					
					if(fork() == 0){ //child process를 생성해 명령어 실행
						execl(exStr, "exe", (char *)0);
						perror("fork error\n");
						exit(-1);
					}
					pid = wait(&status);
					printf("Parent: child exit. pid = [%d], status = [%x]\n", pid, status);
				}
				else{ //모든 경로에서도 명령을 찾지 못한다면
					printf("command not found\n");
				}
			}
			
		}
	}
}

 

.myshell 파일은 이렇게 생겼다

PATH=/usr/bin:/usr/local/bin:/bin

PATH=도 떼어주어야하고 :도 떼어주어야한다. 그 과정에서 strtok와 strcat을 사용..

이게 제일 어려웠다..,.,,, C언어를 써서 더더더더더 어려웠음 C언어 한참 전에 배웠는데.,, 포인터도 가물가물 파일 실행도 가물가물..,문자열이 제일 어렵다.,가물가물가물치...

 

시스템 프로그래밍.,,쉽지 않았다 덕분에 리눅스랑 좀 어색해짐

암튼 도움이 되시길 바라ㅇ요..

728x90

'LINUX > 시스템 프로그래밍' 카테고리의 다른 글

[시스템프로그래밍] thread 문제  (0) 2022.06.29