2017-04-21 1 views
1

C에서 쉘 명령을 복사하는 프로젝트가 있습니다. 명령 중 하나가 | 배관을 사용하여 제작해야합니다. 내 다른 명령은 작동하지만 나는 (ls | sort) 작업을 할 수 없었다. 그것은 LS가 액세스 할 수 없음을 말한다 | : 그런 파일이나 디렉토리 LS는 종류에 액세스 할 수 없습니다 : 그런 파일이나 디렉토리특정 파이프 설명자를 작성하지 않고 파이핑

나는 누군가가 나를 배관 문제를 해결하는 방법을 알아내는 데 도움 주셨으면를? 그것은 각 명령에 대해 별도의 파이프를 만들 필요가 없도록하기 위해 시작 했으므로 for 루프를 통해 실행했습니다.

대부분의 작업을 수행하는 기능은 실행됩니다. Runsource와 Rundest는 파이프에서 정보를 열고 전송합니다.

void execute(char *cmdline) 
{ 
    int pid, async; 
    char *args[MAX_ARGS]; 
    char *pargs[MAX_ARGS]; 
    int i = 1; 
    int j; 

    int nargs = get_args(cmdline, args); 
    if (nargs <= 0) 
     return; 

    if (!strcmp(args[0], "quit") || !strcmp(args[0], "exit")) 
    { 
     exit(0); 
    } 

    int npargs = get_pipe(cmdline, pargs); 
    if (npargs > 1) 
    { 
     int pdes[2]; 
     pipe(pdes); 

     for (j = 0; i < npargs; j++) 
     { 
      nargs = get_args(pargs[j], pargs); 
      runsource(pdes, j, pargs, npargs); 
      rundest(pdes, j + 1, pargs, npargs); 
      close(pdes[0]); 
      close(pdes[1]); 
     } 
    } 
    else 
    { 
     while (args[i] < args[nargs]) 
     { 
      if (strcmp(args[i], ">")) 
      { 
       freopen(args[i + 1], "w", stdout); 
       args[i] = NULL; 
      } 

      if (strcmp(args[i], ">>")) 
      { 
       freopen(args[i + 1], "a", stdout); 
       args[i] = NULL; 
      } 

      if (strcmp(args[i], "<")) 
      { 
       freopen(args[i + 1], "r", stdin); 
       args[i] = NULL; 
      } 
     } 
    } 


    /* check if async call */ 
    if (!strcmp(args[nargs - 1], "&")) 
    { 
     async = 1; 
     args[--nargs] = 0; 
    } 
    else 
     async = 0; 

    pid = fork(); 
    if (pid == 0) /* child process */ 
    { 
     execvp(args[0], args); 
/* return only when exec fails */ 
     perror("exec failed"); 
     exit(-1); 
    } 
    else if (pid > 0) /* parent process */ 
    { 
     if (!async) 
      waitpid(pid, NULL, 0); 
     else 
      printf("this is an async call\n"); 
    } 
    else /* error occurred */ 
    { 
     perror("fork failed"); 
     exit(1); 
    } 
} 

int main(int argc, char *argv[]) 
{ 
    char cmdline[BUFFSIZE]; 

    for (; ;) 
    { 
     printf("COP4338$ "); 
     if (fgets(cmdline, BUFFSIZE, stdin) == NULL) 
     { 
      perror("fgets failed"); 
      exit(1); 
     } 
     execute(cmdline); 
    } 
    return 0; 
} 
+0

코드에 탭이 없도록 복사하여 붙여 넣은 다음 들여 쓰기를하십시오. 엉망이됩니다. –

+0

예, 파이프 전후에 명령을 처리하기 전에 파이프에 대해 알아야합니다. 'get_pipe()'함수를 호출했지만 질문에 그 함수를 포함시키지 마십시오. 다른 누락 된 기능도 있습니다. 이것은 MCVE가 아닙니다 ([MCVE]). 'get_pipe()'함수가 무엇을 하는지를 아는 것은 어렵다. 당신은'ls -l | 정렬 -k2n -k5n | sed 's/*// g'| less "를 4 개의 명령 세트와 인수로 분리하면 파이프가 인수 목록에 나타나지 않습니다. 'sed' 커맨드는 단지 두 개의 인수 만 필요하고 따옴표는 필요하지 않습니다 (쉘은 그것을 제거합니다). 인용 된 인수 항목을 건너 뛸 수 있습니다. –

답변

0

나는 당신이 "<"와 ">"문자를 처리하는 특수 코드를 볼 수 있지만 내가 처리 당신의 대답에 코드를 볼 수 없습니다 "|", 그래서 어떻게 당신도 그것을 기대하고 있었다 작업? 문제는 이제 당신이 "|" ls에 대한 인수로 실제로 파이프 뒤의 것을 명령의 표준 출력 인 ls을 해당 명령의 표준 입력으로 보내는 명령으로 실행해야 할 때입니다.

왜 파싱을하고 수동으로 파이프를 설정하여 셸을 처음부터 고안하려고합니까? 대신 쉘 명령을 실행하기 위해 system()을 사용할 수 없습니까?

+0

당신은 "|" 왜냐하면 당신이 ls를 실행하기 전에 거기에 있었기 때문에 실행되고 표준에 보내 졌을 때 대신 다음 명령으로 보내길 원했을 것입니다. –

+0

또한 할당의 주요 포인트 중 하나는 파이핑을 통합하는 것이 었습니다. 파이프를 수동으로 코딩하는 것보다 코드를 작성할 때 코드를 작성하는 데 문제가 있습니다. –

+0

아니요,'system()'호출의 전체 점은 쉘에서 명령을 실행한다는 것입니다 ('/ bin/sh '내 대답에 링크 된 문서에 따르면). 쉘은 파이프 문자를 구문 분석하고 적절한 작업을 수행합니다. 쉘이 수행해야하는 주요 작업 중 하나이기 때문입니다. 이것이 숙제라면 교사는 명시 적으로'system()'을 사용하거나 sh 또는 bash와 같은 외부 쉘을 실행할 수 없다고 말했습니까? –

관련 문제