• 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

    */
     
  • 相关阅读:
    生成XML文件。
    使用EHCache需要注意的几个问题
    Spring @Value取值为null或@Autowired注入失败
    Windows安装mosquitto
    Linux学习
    hive 日期格式转换
    正则表达式验证字符串是否为IP
    string字符串根据指定字符进行截取转成对应的集合
    CENTOS7自用简单配置
    git的简单使用
  • 原文地址:https://www.cnblogs.com/helloweworld/p/2695854.html
Copyright © 2020-2023  润新知