嵌入式 wget 参数解析篇

2019-07-12 18:25发布

1 整体概括:

前提说明: 本篇wget分析仅仅是参数解析内容,不包括wget的递归和非递归下载,后面文章会陆续进行分析。本次主要分析参数为tries(t) timeout(T) no-clobber quiet(q) recursive(r) help(h)version(V) append-output(a) execute(e) no(n) clobber, 其中括号里面的为wget短选项,括号前面的为长选项。   在wget运行下载文件或页面时,用户可以通过参数来改变wget的行为,比如想查看wget的调试和http数据包可以使用 wget --debugwww.baidu.com/index.html   我们这次分析下载url以baidu 搜索页面(http://www.baidu.com/index.html)为样本,进行分析不同类型的参数,以达到抛砖引玉的目的。wget支持长选项和短选项,比如输出调试信息短选项为-d长选项为—debug   wget有全局的struct options opt;保存着wget用户参数设置值,来修改wget行为。本篇主要讲解用户输入参数如何转化为 opt的成员。   wget分析的版本为1.13,gcc版本为3.4.5,linux内核版本2.6.9_5-9-0-0

2 详细代码解析:

2.1数据结构

wget 对于配置转化,设置struct options opt 有两张表和长短选项数组 命令行表: struct cmdline_option option_data 此表保存着wget支持的长短选项和长短选项属性 命令转化设置opt表: commands 此表用于设置根据参数来设置opt成员。 长选项: struct option long_options[2*countof(option_data) + 1] 短选项: struct char short_options[128]

2.2参数解析流程


Main 首先根据不同平台来设置使用时间函数,blog里有monotonic time和wall time讲解,这里就不分析。

2.2.1 defaults();

然后调用defaults函数,该函数主要是给全局opt设置默认值(因为代码太长,给出部分代码)。
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //#######################src/init.c  
  2. /* Reset the variables to default values.  */  
  3.   void  
  4.   defaults (void)  
  5.   {  
  6.     char *tmp;  
  7.     
  8.     /* Most of the default values are 0 (and 0.0, NULL, and false). 
  9.        Just reset everything, and fill in the non-zero values.  Note 
  10.        that initializing pointers to NULL this way is technically 
  11.        illegal, but porting Wget to a machine where NULL is not all-zero 
  12.        bit pattern will be the least of the implementors' worries.  */  
  13.     xzero (opt);  
  14.     
  15.     opt.cookies = true;  
  16.     opt.verbose = -1;  
  17.     opt.ntry = 20;  
  18.     opt.reclevel = 5;  
  19.     opt.add_hostdir = true;  
  20.     opt.netrc = true;  
  21.     opt.ftp_glob = true;  

2.2.2 init_switches()

函数很简单,追加一些ch注释 [cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. static void  
  2.   init_switches (void)  
  3.   {  
  4.     //p指向短选项数组  
  5.     char *p = short_options;  
  6.     size_t i, o = 0;  
  7.     //遍历所有选项  
  8.     for (i = 0; i < countof (option_data); i++)  
  9.       {  
  10.         struct cmdline_option *opt = &option_data[i];  
  11.         struct option *longopt;  
  12.     
  13.         //如果这个选项数据没有长选项,直接跳过  
  14.         if (!opt->long_name)  
  15.           /* The option is disabled. */  
  16.           continue;  
  17.     
  18.         //longopt指向长选项一个依次节点  
  19.         longopt = &long_options[o++];  
  20.         //长选项name指向opt的long_name  
  21.         longopt->name = opt->long_name;  
  22.         //长选项val执行opt的数组索引,用于根据长选项查找opt  
  23.         longopt->val = i;  
  24.         if (opt->short_name)  
  25.          {  
  26.             //如果存在短选项,把opt short_name保存在short_options中  
  27.             *p++ = opt->short_name;  
  28.             //用optmap保存short_name的value 来索引长选项数组  
  29.             optmap[opt->short_name - 32] = longopt - long_options;  
  30.           }  
  31.         switch (opt->type)  
  32.           {  
  33.           case OPT_VALUE:  
  34.            //参数需要值  
  35.            longopt->has_arg = required_argument;  
  36.           //如果参数需要设置值,并且短选项存在,就需要字符":"  
  37.             if (opt->short_name)  
  38.               *p++ = ':';  
  39.             break;  
  40.           case OPT_BOOLEAN:  
  41.             /* 如果是bool类型(开关类型参数) 需要支持--option=off and --no-option .look the note of the blow*/  
  42.             /* Specify an optional argument for long options, so that 
  43.                --option=off works the same as --no-option, for 
  44.                compatibility with pre-1.10 Wget.  However, don't specify 
  45.                optional arguments short-option booleans because they 
  46.                prevent combining of short options.  */  
  47.             longopt->has_arg = optional_argument;  
  48.             /* For Boolean options, add the "--no-FOO" variant, which is 
  49.                identical to "--foo", except it has opposite meaning and 
  50.                it doesn't allow an argument.  */  
  51.             longopt = &long_options[o++];  
  52.             longopt->name = no_prefix (opt->long_name);  
  53.             longopt->has_arg = no_argument;  
  54.             /* Mask the value so we'll be able to recognize that we're 
  55.                dealing with the false value.  */  
  56.             //索引加一个负数符号  
  57.             longopt->val = i | BOOLEAN_NEG_MARKER;  
  58.             break;  
  59.           default:  
  60.             //others 根据情况设置不同的值  
  61.             assert (opt->argtype != -1);  
  62.             longopt->has_arg = opt->argtype;  
  63.             if (opt->short_name)  
  64.               {  
  65.