int optind = 1; int optopt; char *optarg; int getopt(int argc, char *const argv[], const char *optstring) { static int optchr = 1; char *cp; if (optchr == 1) { if (optind >= argc) { /* all arguments processed */ return EOF; } if (argv[optind][0] != '-' || argv[optind][1] == '\0') { /* no option characters */ return EOF; } } if (os_strcmp(argv[optind], "--") == 0) { /* no more options */ optind++; return EOF; } optopt = argv[optind][optchr]; cp = os_strchr(optstring, optopt); if (cp == NULL || optopt == ':') { if (argv[optind][++optchr] == '\0') { optchr = 1; optind++; } return '?'; } if (cp[1] == ':') { /* Argument required */ optchr = 1; if (argv[optind][optchr + 1]) { /* No space between option and argument */ optarg = &argv[optind++][optchr + 1]; } else if (++optind >= argc) { /* option requires an argument */ return '?'; } else { /* Argument in the next argv */ optarg = argv[optind++]; } } else { /* No argument */ if (argv[optind][++optchr] == '\0') { optchr = 1; optind++; } optarg = NULL; } return *cp; }
假设命令是./wpa_cli -p /home/work/pkg_wifi -i wlan0
则char *const argv[] 即为------argv[0]="./wpa_cli",argv[1]="-p",argv[2]="/home/work/pkg_wifi",argv[3]="-i",argv[4]="wlan0" argc=5
和optstring做对比,optstring="a:Bg:G:hi:p:P:v"
static int optchr = 1; char *cp; if (optchr == 1) { if (optind >= argc) { /* all arguments processed */ return EOF; }
optind<5不成立
if (argv[optind][0] != '-' || argv[optind][1] == '\0') { /* no option characters */ return EOF; }
argv[1][0]="-",argv[1]="p"这里防止不规范的输入
if (os_strcmp(argv[optind], "--") == 0) { /* no more options */ optind++; return EOF; }
比较argv[1]和"--"相同则返回0,这里不相同
optopt = argv[optind][optchr]; cp = os_strchr(optstring, optopt); if (cp == NULL || optopt == ':') { if (argv[optind][++optchr] == '\0') { optchr = 1; optind++; } return '?'; }
optopt=argv[1][1]="p"=112(ASC)
os_strchr是查找字符的函数,是C库的标准函数,原型是strchr,这里wpa_supplicant做了两种方案,一种是自己实现的,一种是宏定义了strchr,这么做的原因还没看。
strchr()如果找到了字符'p',这里用ASC码做了强制转换,就返回该字符出现的地址,否则返回0。这里内部的处理要看main函数代码。
if (cp[1] == ':') { /* Argument required */ optchr = 1; if (argv[optind][optchr + 1]) { /* No space between option and argument */ optarg = &argv[optind++][optchr + 1]; } else if (++optind >= argc) { /* option requires an argument */ return '?'; } else { /* Argument in the next argv */ optarg = argv[optind++]; } }
cp="p:P:v",cp[1]=':',argv[1][2]=0。这里如果argv[1][2]=1,那么表示-p,-i 等命令后面没有跟上空格,就成
了argv[0]="./wpa_cli",argv[1]="-p/home/work/pkg_wifi",argv[2]="-iwlan0"那么就将argv[1][3]赋给optarg,
argv[1][3]='/',后面就会直接返回cp,cp="p:P:v",这时optarg=argv[1][3]='/home/work/pkg_wifi'
当argv[1][2]=0时,判断if (++optind >= argc),即2>=5,这里判断有几个参数。然后执行optarg = argv[2]="/home/work/pkg_wifi";
else {
/* No argument */
if (argv[optind][++optchr] == '\0') {
optchr = 1;
optind++;
}
这里表示没有参数的情况,即-B,-v,-h,后台运行,版本信息和帮助。argv[1][1]='p'。optarg = NULL;返回cp="p:P:v"。因为函数的返回值
是int型的,所以返回p的ASC码。在main函数中
case 'p':
ctrl_iface_dir = optarg;
break;
将optarg赋值给ctrl_iface_dir=optarg = argv[2]="/home/work/pkg_wifi"。