接着分析:
这段是将刚才那些模糊匹配的结构写入stderr文件.
_IO_flockfile (stderr);它完成的是用本线程对stderr进行加锁,目的是它占用用来输出错误信息给终端。[code]
563 int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
564 ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; /*==++> #define _IO_FLAGS2_NOTCANCEL 2*/
565
566 __fxprintf (NULL, "%s", buf);1、______________---------------->
567
568 ((_IO_FILE *) stderr)->_flags2 = old_flags2;
569 _IO_funlockfile (stderr); /*解锁,把缓冲区释放*/
570
571 free (buf);
572 }
573 }
[/code][code]
此结构定义在libio/libio.h, stderr是个io文件。
271 struct _IO_FILE {
272 int _flags; /* High-order word is _IO_MAGIC; rest is flags. */
273 #define _IO_file_flags _flags /*=======>文件中有定义*/
274
275 /* The following pointers correspond to the C++ streambuf protocol. */
. . . . .
306 char _shortbuf[1];
307
308 /* char* _save_gptr; char* _save_egptr; */
309
310 _IO_lock_t *_lock;
311 #ifdef _IO_USE_OLD_IO_FILE
312 };
[/code][code]
1、_____________-------------------->
30 __fxprintf (FILE *fp, const char *fmt, ...) /*将数据打印到某个文件中*/
31 {
32 if (fp == NULL)
33 fp = stderr; /*这里是stderr文件*/
34
35 va_list ap; /*va_list是规定指向一个可变参数的动态指针结构*/
36 va_start (ap, fmt); /*初始化为指向第一个元素*/
37
38 int res;
39 if (_IO_fwide (fp, 0) > 0)
40 {
41 size_t len = strlen (fmt) + 1; /*size_t使用 详见博客size_t。*/
42 wchar_t wfmt[len]; /*GNU Libc规定wchar_t为32位*/
43 for (size_t i = 0; i < len; ++i)
44 {
45 assert (isascii (fmt[i])); /*断言是数组内字符是ascii码*/
46 wfmt[i] = fmt[i]; /*将其中的值赋给wfmt[i];*/
47 }
48 res = __vfwprintf (fp, wfmt, ap); /*写入文件中 外部定义的 extern int __vfwprintf (__FILE *__restrict __s, __const wchar_t *__restrict __format,__gnuc_va_list __arg)*/
49 }
50 else
51 res = INTUSE(_IO_vfprintf) (fp, fmt, ap); /*输入文件*/
52
53 va_end (ap);
54
55 return res;
56 }
[/code][code]
<---------------------_________________
/*如果没有定义libc和libio等就用这种直接写的方式*/
574 #else
575 fprintf (stderr,
576 _("%s: option '%s' is ambiguous; possibilities:"),
577 argv[0], argv[d->optind]);
578 do
579 {
580 fprintf (stderr, " '--%s'", ambig_list->p->name);
581 ambig_list = ambig_list->next;
582 }
583 while (ambig_list != NULL);
584
585 fputc ('\n', stderr);
586 #endif
587 }
588 d->__nextchar += strlen (d->__nextchar); /*nextchar 是指针类型,指向下一个*/
589 d->optind++; /*下个选项*/
590 d->optopt = 0;
591 return '?'; /*返回0*/
592 }这些是将所有的模糊匹配的都打印出来*/
594 while (ambig_list != NULL)
595 {
596 struct option_list *pn = ambig_list->next;
597 free (ambig_list);
598 ambig_list = pn;
599 }
整层函数都是返回错误提示的。比如返回?的字符值。如果有参数并且短选项为空,代表没有短选项那么就打印?的字符值否则打印:的字符值。
[/code][code]
<----------------__________________
返回到 ,这里将optind等参数根据返回情况从新赋值*/
1128 _getopt_internal (int argc, char **argv, const char *optstring,
1129 const struct option *longopts, int *longind, int long_only,
1130 int posixly_correct)
1131 {
1132 int result;
1133
1134 getopt_data.optind = optind;
1135 getopt_data.opterr = opterr;
1136
1137 result = _getopt_internal_r (argc, argv, optstring, longopts,
1138 longind, long_only, &getopt_data,
1139 posixly_correct);
1140
1141 optind = getopt_data.optind;
1142 optarg = getopt_data.optarg;
1143 optopt = getopt_data.optopt;
1144
1145 return result; /*返回的仍然是上面的那些字符,如果返回的是-1,说明查找到了选项*/
}
[/code][code]
<------------------------_____________________
927 while ((retconf = getopt_long (argc, argv,
928 short_options, long_options, &longindex)) != -1)
929 {
930 int confval;
931 bool userrc_ret = true;
932 struct cmdline_option *config_opt;
933 confval = long_options[longindex].val;
934 config_opt = &option_data[confval & ~BOOLEAN_NEG_MARKER];
935 if (strcmp (config_opt->long_name, "config") == 0)
936 {
937 userrc_ret &= run_wgetrc (optarg); /*run_wgetrc记录数据optarg文件中*/3、_____--->
938 use_userconfig = true;
939 }
940 if (!userrc_ret) /*如果返回NULL,说明出错*/
941 {
942 printf ("Exiting due to error in %s\n", optarg);
943 exit (2);
944 }
945 else /*如果没有注册,就直接返回错误*/
946 break;
947 }
[/code][code] 将一些可以接受的模式打印进一个文件中,供应用程序判断。和防火墙类似,好像再从用户这里得到规则。
3、__________----------------->
529 bool
530 run_wgetrc (const char *file)
531 {
532 FILE *fp;
533 char *line;
534 int ln;
535 int errcnt = 0;
536
537 fp = fopen (file, "r"); 打开optarg文件。
538 if (!fp)
539 {
540 fprintf (stderr, _("%s: Cannot read %s (%s).\n"), exec_name,
541 file, strerror (errno));
542 return true; /* not a fatal error */
543 }
544 ln = 1;
545 while ((line = read_whole_line (fp)) != NULL)
546 {
547 char *com = NULL, *val = NULL;
548 int comind;
549
550 /* Parse the line. 解析行中的参数*/
551 switch (parse_line (line, &com, &val, &comind)) /*这个函数返回命令和参数*/
552 {
553 case line_ok:
554 /* If everything is OK, set the value. */
555 if (!setval_internal_tilde (comind, com, val)) /*这里是将命令的可接受的模式列表(从home开始)组合起来并把他们放入&opt.place指向的地址。
556 {
557 fprintf (stderr, _("%s: Error in %s at line %d.\n"),
558 exec_name, file, ln);
559 ++errcnt;
560 }
561 break;
562 case line_syntax_error: /*其他的错误就打印出来*'/
563 fprintf (stderr, _("%s: Syntax error in %s at line %d.\n"),
564 exec_name, file, ln);
565 ++errcnt;
566 break;
567 case line_unknown_command:
568 fprintf (stderr, _("%s: Unknown command %s in %s at line %d.\n"),
569 exec_name, quote (com), file, ln);
570 ++errcnt;
571 break;
572 case line_empty:
573 break;
574 default:
575 abort ();
576 }
577 xfree_null (com); /*释放*/
578 xfree_null (val);
579 xfree (line);
580 ++ln;
581 }
582 fclose (fp);
583
584 return errcnt == 0;
585 }
[/code]
阅读(1003) | 评论(0) | 转发(0) |