Modultils工具源码分析之insmod篇 (3续)

本文详细解析了insmod处理配置文件的过程,包括split_line函数如何分割字符串,gen_file_conf函数如何处理配置项,以及decode_list函数如何解码列表。

我们继续看meta_expand余下的代码。251~255行处理“"/'”这样的元符号,其实就是字符串引用符号。257~260行则是处理普通字符及仅有“=”的情况。函数split_line也在同一文件中。

Insmod——split_line函数

47    /*

48    * Split into words delimited by whitespace,

49    * handle remaining quotes though...

50    * If strip_quotes != 0 then strip one level of quotes from the line.

51    */

52    static void split_line(GLOB_LIST *g, char *line, int strip_quotes)

53    {

54           int len;

55           char *d;

56           char *e;

57           char *p;

58           char tmpline[PATH_MAX];

59

60           for (p = line; *p; p = e) {

61                  /* Skip leading whitespace */

62                  while (*p && isspace(*p))

63                         ++p;

64

65                  /* find end of word */

66                  d = tmpline;

67                  for (e = p; *e && !(isspace(*e)); ++e) {

68                         char match;

69

70                         /* Quote handling */

71                         switch (*e) {

72                         case '//':

73                                if (!strip_quotes)

74                                       *d++ = *e;

75                                break;

76

77                         case '"':

78                         case '/'':

79                                match = *e;

80                                if (!strip_quotes)

81                                       *d++ = *e;

82                                for (++e; *e && *e != match; ++e) {

83                                       *d++ = *e;

84                                       if (*e == '//' && *(e + 1) == match)

85                                              *d++ = *++e;

86                                }

87                                if (!strip_quotes)

88                                       *d++ = *e;

89                                break;

90

91                         default:

92                                *d++ = *e;

93                                break;

94                         }

95                  }

96

97                  if ((len = (int)(d - tmpline)) > 0) {

98                         char *str = xmalloc(len + 1);

99                         strncpy(str, tmpline, len);

100                       str[len] = '/0';

101                       g->pathv = (char **)xrealloc(g->pathv,

102                                 (g->pathc + 2) * sizeof(char *));

103                       g->pathv[g->pathc++] = str;

104                }

105         }

106

107         if (g->pathc)

108                g->pathv[g->pathc] = NULL;

109  }

 

在“=”的情况下,没有特别的处理,只是将字符拷入缓存,注意8485行处理了转义字符。267~275行是对Shell的元符号的处理,他们是:[]~?*如果允许使用Shell变量,还包括$。如果处理不了,继续往下走,277~281行又是对“=”进行处理。。如果不止是“=”,而且glob也无法处理。那么就只好请echo帮忙了。297~310行构建echo命令行。311~313行则通过管道执行echo命令。320~328行则是从管道获取输出。在330~335行对这些输出用split_line分割参数。

回到do_read函数,1303~1311行,将解析好的路径信息存到modpath中。到此Example.module.conf的第6 行处理完毕。然后,进入1325for循环,不过因为one_err=0。所以,实际上没有执行。函数gen_file_conf也在config.c中。

Insmod——gen_file_conf函数

423  /* Read a config option for a generated filename */

424  static int gen_file_conf(struct gen_files *gf, int assgn, const char *parm, const char *arg)

425  {

426

427         int l = strlen(gf->base);

428         if (assgn &&

429             strncmp(parm, gf->base, l) == 0 &&

430             strcmp(parm+l, "file") == 0 &&

431             !gf->name) {

432                gf->name = xstrdup(arg);

433                return(0);

434         }

435         return(1);

436          }

 

显然,这是察看形如x=xxx这样的式子是否定义了gen_file的路径。one_errassign1parm不等于insmod_optpathpersistdir时,为1。将进入gen_file_conf函数。

接着看第8行。insmod调用do_read时,all设为1。因此,进入1142行的else if块。decode_list在同一文件中。arg此时为 scsi_hostadapter

Insmod——decode_list函数

323  static void decode_list(int *n, OPT_LIST **list, char *arg, int adding,

324                char *version, int opts)

325  {

326         GLOB_LIST *pg;

327         GLOB_LIST *prevlist = NULL;

328         int i, autoclean = 1;

329         int where = *n;

330         char *arg2 = next_word(arg);

331

332         if (opts && !strcmp (arg, "-k")) {

333                if (!*arg2)

334                       error("Missing module argument after -k/n");

335                arg = arg2;

336                arg2 = next_word(arg);

337                autoclean = 0;

338         }

339

340         for (i = 0; i < *n; ++i) {

341                if (strcmp((*list)[i].name, arg) == 0) {

342                       if (adding)

343                              prevlist = (*list)[i].opts;

344                       else

345                              free((*list)[i].opts);

346                       (*list)[i].opts = NULL;

347                       where = i;

348                       break;

349                }

350         }

351         if (where == *n) {

352                (*list) = (OPT_LIST *)xrealloc((*list),

353                         (*n + 2) * sizeof(OPT_LIST));

354                (*list)[*n].name = xstrdup(arg);

355                (*list)[*n].autoclean = autoclean;

356                *n += 1;

357                memset(&(*list)[*n], 0, sizeof(OPT_LIST));

358         } else if (!autoclean)

359                (*list)[where].autoclean = 0;

360         pg = (GLOB_LIST *)xmalloc(sizeof(GLOB_LIST));

361         meta_expand(arg2, pg, NULL, version, ME_ALL);

362         (*list)[where].opts = addlist(prevlist, pg);

363          }

 

有了上面代码的基础,这段代码相当简单。首先处理-k选项,然后根据是否设定了adding,添加或覆盖对应的项。至此,Example.module.conf的第8行也已处理完。第9101113行的处理也是类似的,此处就略过了。第22行中`kernelversion`的处理我们也已经看过了。因此,直接跳到第28行。经过类似的处理后,parm = ifarg = -f。进入do_read950行的if块中,这时level=0Arg=-f是要测试文件的存在,因此,在973行获取文件路径后,在974行通过meta_expand对可能存在的元符号进行处理,这个我们已经看过了。然后通过access函数测试文件的存在与否。这里假定文件存在。注意此时level=1,这个if块下面的代码处理比较操作符及取反操作符,比较简单,不赘述了。

接下来处理第29行,if块里的语句。注意在1063行,因为此时state[level]=1(我们假设文件存在),因此跳过了这个if块。同时注意在646行,函数第一次运行时将state[0]设为0。直到1082行,同样首先使用meta_expandinclude文件的路径进行元字符处理。注意,如果路径中不包含元字符,也没有分行,meta_expand,将不做任何处理,g.pathc将为0。然后这个路径将作为conf_file传给do_read做递归调用,然后经过同样漫长的过程,最终返回来。

处理endif的语句在897~906行,非常简单。好了,我们顺便看看910~945行,elseelseif的处理。else的处理很简单,将state[level]取反即可,state[level]自会照顾else块里代码的解析。elseif就要花点心思,首先如果elseif之前的if条件为真,那么为了实现3个以上的分支,将state[level]设为2,这样可以通过927行和1063行的if检测。相反,如果elseif之前的条件测试均没通过,那么就将parm置为if,用处理if的语句来处理。这个实现,可说相当的巧妙。

Example.module.conf的最后一行,看似不同,但实际上还是通过decode_list来处理。所以,就不看了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值