getopt 和argc argv的联合使用

vtun如何解析启动客户端或服务器的命令行参数?

Usage:
  Server:
    vtund <-s> [-f file] [-P port] [-L local address]
  Client:
    vtund [-f file] [-p] [-m] [-t timeout] <host profile> <server address>

预备知识:

-s –f –P 等称为选项;

file port称为选项对应的参数;

host file server address ——暂且称它们为非选项字符串吧。

解析代码在main.c中。

在vtun源码中是这样实现的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
  /*每调用一次getopt返回一个选项,optarg是指向对应选项的参数指针。*/
while
( (opt=getopt(argc,argv,"misf:P:L:t:npq")) != EOF ){
        switch(opt)
        {
            case 'm':
                if (mlockall(MCL_CURRENT | MCL_FUTURE) < 0)
                {
                    perror("Unable to mlockall()");
                    exit(-1);
                }
                break;
            case 'i':
                vtun.svr_type = VTUN_INETD;
            case 's':
                svr = 1;
                break;
            case 'L':
                vtun.svr_addr = strdup(optarg);
                break;
            case 'P':
                vtun.bind_addr.port = atoi(optarg);
                break;
            case 'f':
                vtun.cfg_file = strdup(optarg);
                break;
            case 'n':
                daemon = 0;
                break;
            case 'p':
                vtun.persist = 1;
                break;
            case 't':
                    vtun.timeout = atoi(optarg);
                    break;
            case 'q':
                vtun.quiet = 1;
                break;
            default:
                usage();
                exit(1);
        }
    }//end while

/*getopt不能解决非选项字符串问题,故有了下面的代码以解决非选项字符串问题*/

if(!svr)
    {

        /*argc-optind<2的意思是如果少于两个(或者说只有0个或1个)非选项的字符串,则退出。
        *为什么?由usage我们知道client端的命令至少有两个有两个非选项字符串:
        *<host profile>或<server address>.
        */
        if( argc - optind < 2 ){  

            usage();
            exit(1);
        }

        hst = argv[optind++];    //argv[optind++]指的是第一个非选项字符串host或者server,可以理解为本次会话的名称。

        if( !(host = find_host(hst)) )
        {
            vtun_syslog(LOG_ERR,"Host %s not found in %s", hst, vtun.cfg_file);
            exit(1);
        }

        vtun.svr_name = strdup(argv[optind]);  //上面optind加1了,所以此处的argv[optind]指的是profile或address.
    }

void usage(void)
{
     printf("VTun ver %s\n", VTUN_VER);
     printf("Usage: \n");
     printf("  Server:\n");
     printf("\tvtund <-s> [-f file] [-P port] [-L local address]\n");
     printf("  Client:\n");
     /* I don't think these work. I'm disabling the suggestion - bish 20050601*/
     printf("\tvtund [-f file] " /* [-P port] [-L local address] */
        "[-p] [-m] [-t timeout] <host profile> <server address>\n");
}

为充分理解getopt和argc,argv的关系,再看一个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
  #include <unistd.h>
 
int main(int argc, char **argv)
{
    int opt;
    opterr = 0;
   
    while( (opt = getopt(argc, argv, "ab:c::d::")) != -1 )
    {
         switch(opt)
          {
              case 'a':
                  printf("option=a, opt=%d, optarg=%s, optind=%d, optopt=%d\n", opt, optarg, optind, optopt);
                  break;
              case 'b':
                  printf("option=b, opt=%d, optarg=%s, optind=%d, optopt=%d\n", opt, optarg, optind, optopt);
                    break;
              case 'c':
                  printf("option=c, opt=%d, optarg=%s, optind=%d, optopt=%d\n", opt, optarg, optind, optopt);
                     break;
              case 'd':
                  printf("option=d, opt=%d, optarg=%s, optind=%d, optopt=%d\n", opt, optarg, optind, optopt);
                     break;
              case '?':
                  printf("option=?, opt=%d, optarg=%s, optind=%d, optopt=%d\n", opt, optarg, optind, optopt);
                   break;
                default:
                  printf("option=default, opt=%d, optarg=%s, optind=%d, optopt=%d\n", opt, optarg, optind, optopt);
                     break;
          }
    }
    printf("after getopt,optind=%d\n",optind);         //最后的optind位置是最后的有效选项或参数的下一个字符串。
    printf("argc-optind=%d\n", (argc - optind));
    printf("argv[optind]=%s\n", argv[optind]);
    printf("argv[optind++]=%s\n", argv[optind++]);
    return 0;
 
/*

root@ubuntu:~/eclipseworkspace# ./a.out -b barg ee ff
option=b, opt=98, optarg=barg, optind=3, optopt=0
after getopt,optind=3               //此时optind在ee位置
argc-optind=2
argv[optind]=ee
argv[optind++]=ee

*/
 
原文地址:https://www.cnblogs.com/helloweworld/p/2695854.html