2013-10-21 3 views
0

여러 경로가 포함 된 배열을보고 (예 : ls, wc, cat ... 등) 명령이 나열된 디렉토리에 있는지 확인하는 알고리즘이 있습니다. 배열 파일이 디렉토리 중 하나에서 발견되면 전체 디렉토리 경로를 리턴합니다.파일이있는 경우 디렉토리 배열 검색

char *LookupPath(char **argv, char **dir) 
{ 
    /* String Name To Be Returned */ 
    char *result; 
    char path_name[MAX_PATH_LEN] = {0}; 
    int i; 

    /* Check To See If File Name Is Already An Absolute Path Name */ 
    if(*argv[0] == '/') { 

    } 

    /* Look In Path Directories */ 
    for(i = 0; dir[i] != NULL; i++) { 
     strncat(path_name, dir[i], sizeof(path_name)); 
     strncat(path_name, "/", sizeof(path_name)); 
     strncat(path_name, argv[0], sizeof(path_name)); 
     printf("pathname: %s\n", path_name); 
     result = path_name; 
     if(access(result, F_OK) == 0) { 
      printf("SUCCESS!\n"); 
      printf("result: %s\n", result); 
      return result; 
     } 
     path_name[0] = '\0'; 
    } 

    /* File Name Not Found In Any Path Variable */ 
    return NULL; 
} 

새로운 문제 : 같은 -l LS 또는 다른 것으로 명령을 사용하는 경우 아래의 결과 코드와 같이 결과가 아름답게 작동합니다.

pathname: /usr/lib/lightdm/lightdm/ls 
pathname: /usr/local/sbin/ls 
pathname: /usr/local/bin/ls 
pathname: /usr/sbin/ls 
pathname: /usr/bin/ls 
pathname: /sbin/ls 
pathname: /bin/ls 
SUCCESS! 
result: /bin/ls 

그러나

, 지금은 그런 어떤 이유로, 새로운 라인 문자가 LS에 추가되기 때문에 결과는 ... 거짓에 ...의에 'LS'로 단순한 명령을 사용할 때 ...? 나타납니다

pathname: /usr/lib/lightdm/lightdm/ls 

pathname: /usr/local/sbin/ls 

pathname: /usr/local/bin/ls 

pathname: /usr/sbin/ls 

pathname: /usr/bin/ls 

pathname: /sbin/ls 

pathname: /bin/ls 

pathname: /usr/games/ls 

pathname: /usr/local/games/ls 

ls 
: Command Not Found! 

나는 이유를 알고하지 않습니다. 그것을 'ls'로 줄이는 방법이 있습니까? argv [0]에 새로운 라인 문자가 추가되는 이유를 모르겠다. 그냥 간단한 ls 명령 일 뿐이다. : S

답변

1

dir 문자열을 수정하기 때문에 루프에서 호출 할 수 없습니다. strcat()은 원본 문자열을 수정하여 대상에 추가합니다 (대상 문자열을 대상으로 사용). 또한 확장 된 문자열 길이에 대한 조항을 만들지 않으므로 문자열 메모리의 끝을 지나서 쓰고 다른 메모리가 손상됩니다.

로컬 변수로 충분한 길이의 char 배열을 만들고 거기에 테스트 할 경로 이름을 만들어야합니다. strcat() 대신 snprintf()를 사용하고 생성 된 경로가 문자열에 맞는지 확인하십시오. 또한 로컬 문자열을 반환 할 수 없으므로 성공한 경우 결과 길이의 새 문자열을 malloc()하여 결과를 복사해야합니다.

아직 확인되지 않았으므로 이름의 첫 글자가 '/'인지 확인하십시오. 네가 벌써 한 일이야.

+0

는 strcat와는 (이명 령, SRC) ... 그리고 나는 나에게 이명 령으로 사용 표시되지 않습니다. 그렇다면 적절한 코드는 무엇입니까? : S –

+0

당신은 "result = dir [i];" 다음 "strcat (결과,"/ ");" 결과는 dir [i]와 같습니다. dir [i]가 가리키는 문자열을 수정하고 있습니다. –

+0

좋아요, 이제 배열에 문자가 있습니다. char_name [MAX_SIZE]; 어떻게 구성할까요? : S ... snprintf 사용 ... dir [i]/argv [0] ...을 사용하고 싶습니다 ... –

0

나는이 작업을 수행 할 라이브러리가 있지만 실제 문제는 매번 루프를 통해 dir의 경로에 추가된다는 것입니다.

결과가

이러한 라인이 실제로 추가 PTR입니다/ARGV [0] 때마다 당신이 루프를 입력 경로에있는 각 요소에

result = dir[i]; 
    strcat(result, "/"); 
    strcat(result, argv[0]); 
당신은 임시 문자 버퍼를 작성해야

및 여러 strcats 또는 sprintf를 사용하여 내용을 채 웁니다. FWIW, strncat 또는 길이 매개 변수가있는 유사한 문자열 함수를 사용하는 습관에 실제로 빠져 있어야합니다. 이와 같은 코드는 많은 보안 문제의 시작입니다. 이

 char result[PATH_MAX]; 
    strncpy(dir[i],result,length(dir[i)) 
0

네 같은 뭔가, strcat 여기에 문제가 보인다. char **dir이 문자열의 표준 배열이라고 가정하면 strcat을 입력하면 끝까지 실행되지 않을 수 있습니다. As I've said myself :

아니요! 아니요! 아니 strcat! strcat은 태양과 같이 버퍼 오버런을 처리합니다. ...진지하게, 가 아니다.

루프 내에 일종의 버퍼를 할당해야합니다. (: (300)를 시도 내 야생 추정), BUFSIZE이 충분한 크기로 #define D가

char buf[BUFSIZE] = {0}; 
result = buf; 

을 말한다.

strlcpy(buf, dir[i], BUFSIZE); 
strlcat(buf, "/", BUFSIZE); 
strlcat(buf, argv[0], BUFSIZE); 

경고 :

그런 다음 시도 내가 지금이 권리를 테스트 할 수 없습니다; 나는 단지 라고 생각하고라고 생각합니다. 그래도 괜찮을거야. 당신은 내가 대상으로 디렉토리하지만 체크 마지막으로 사용하고 말을하는지

Information on strlcpy and strlcat