2010-04-27 4 views
13

getopt 또는 getopt_long이 잘못된 옵션을 만날 경우 불쾌한 옵션 문자가 optopt에 저장됩니다. 불법적 인 옵션이 길이가 옵션 인 경우 옵션의 위치는 어디에서 확인할 수 있습니까? 의미있는 것은 optopt에 저장됩니까?getopt_long은 인식 할 수없는 옵션을 어디에 저장합니까?

나는 자동으로 인쇄 된 오류 메시지를 표시하지 않기 위해 opterr = 0을 설정했습니다. 내가 원하는 곳에 인쇄하거나 로그 할 수있는 자체 메시지를 만들고 싶지만 인식 할 수없는 옵션의 이름을 포함하고 싶습니다.

답변

3

가장 가까운 찾을 수있는 것은 BADCH을 반환하면 그 원인이 된 argv 항목이 argv[optind-1]입니다. 문제의 주장을 찾는 더 좋은 방법이있는 것처럼 보입니다.

6

맨 페이지에서 이러한 세부 정보를 바로 볼 수 있지만, glibc-x.y.z/posix/getopt.c의 _getopt_internal_r에있는 glibc의 구현과 같이 소스 코드에서 충분한 힌트를 얻을 수 있습니다. (아마도이 ​​GNU 확장 함수의 유일한 흥미로운 구현입니까?) optopt이 잘못된 길이 옵션과 구별하는 것이 유용하다고 생각하는 잘못된 long 옵션을 만났을 때 코드는 optopt을 0으로 설정합니다. 반드시 NUL이 아니어야합니다.

opterr != 0은 주로 오류가있는 긴 옵션을 argv[optind]으로 인쇄하고 나중에 (항상 또는 거의 보수적으로) 나중에 코드를 optind으로 변경하여 반환합니다.

따라서이 프로그램을 고려 :

#include <getopt.h> 
#include <stdio.h> 

int main(int argc, char **argv) { 
    struct option longopts[] = { 
    { "foo", no_argument, NULL, 'F' }, 
    { NULL, 0, NULL, 0 } 
    }; 
    int c; 

    do { 
    int curind = optind; 
    c = getopt_long(argc, argv, "f", longopts, NULL); 
    switch (c) { 
    case 'f': printf("-f\n"); break; 
    case 'F': printf("--foo\n"); break; 
    case '?': 
     if (optopt) printf("bad short opt '%c'\n", optopt); 
     else printf("bad long opt \"%s\"\n", argv[curind]); 
     break; 
    case -1: 
     break; 
    default: 
     printf("returned %d\n", c); 
     break; 
    } 
    } while (c != -1); 

    return 0; 
} 

을 $ ./longopt -f -x --bar --foo
-f
./longopt : 잘못된 옵션 - 'X'
나쁜 짧은 옵트 'X'
./longopt :
--foo

"--bar"
나쁜 긴 옵트 '--bar'알 수없는 옵션3210

이렇게 이러한 경우에 메시지와 동일한 잘못된 옵션을 쉽게 인쇄 할 수 있습니다.

glibc 구현의 argv[optind] ("인식 할 수없는 옵션"의 경우)보다 glibc 구현 자체가 __nextchar을 사용하므로 학습하기에 충분하지만 시작하기에 충분해야합니다.

optind과 반복되는 호출 getopt_long의 관계에 대해 신중하게 생각하면 argv[cached_optind]을 인쇄하는 것이 꽤 안전 할 것이라고 생각합니다. optopt은 짧은 옵션의 경우 단어 내의 어느 문자가 문제인지를 알아야하기 때문에 필요하지만 긴 옵션의 경우 문제는 전체 현재 단어입니다 (옵션 인수 인 양식 =param 제외). 현재 단어는 getopt_long이 (수신) optind 값으로보고있는 단어입니다.

설명서에 명시된 보증이 없으면 optopt = 0 동작을 이용하는 것에 대해 다소 낙담 할 것입니다.

+0

이것은 유망 해 보이지만, 테스트 할 때, 적어도 솔라리스 시스템에서는이 해결책이'getopt_long'이하는 인수 순열에 더 민감한 것으로 보입니다. 나는'optind - 1'을 고집합니다. –

+0

당신이 (나 같은) 매우 까다 롭다면'char * eq = index (argv [optind-1], '=');로 표시하기 전에 매개 변수를 제거 할 수 있습니다. if (eq! = NULL) * eq = '\ 0';'. –

관련 문제