getopt、getopt_long的可重入版本----linux交互式应用程序

来源:互联网 发布:comsol正规软件多少钱 编辑:程序博客网 时间:2024/05/16 04:18
默认的getopt、getopt_long是不可重入的,也就是说,假设你使用它开发交互式应用程序,循环获取用户命令,它只能正确解析第一次命令行输入。
你可以先看这个问题
http://topic.csdn.net/u/20080531/22/f058cc59-558e-4f21-9924-2889ca37746f.html
还有一个以前的帖子
http://topic.csdn.net/t/20050804/15/4188861.html
这个帖子给的解决方案发现并不能解决问题。
 
于是我决定把libc的源文件自己下载下来,编译链接到自己的程序里,另我惊喜的是,glibc-2.7,已经实现了它的可重入版本,于是我想直接使用这个可重入版本的函数_getopt_long_r。
ftp://sources.redhat.com/pub/glibc/releases/glibc-2.7.tar.gz
它的posix目录下有getopt.h getopt_int.h getopt.c getopt1.c
拷到你自己的项目文件夹下使用
使用时添加上
#include "getopt.h"
#include "getopt_int.h"
 
但是当我使用_getopt_long_r时,编译器老报,这个函数没有定义的错误(undefined),也就是说,我的库里面没有包含这个函数,其实我的/usr/include下根本没有getopt_int.h这个头文件。
于是我决定测试一下这个getopt.c和getopt1.c
gcc -c getopt.c
objdump -t getopt.c
结果发现
getopt.o:     file format elf32-i386
SYMBOL TABLE:
00000000 l    df *ABS*  00000000 getopt.c
00000000 l    d  .text  00000000 .text
00000000 l    d  .data  00000000 .data
00000000 l    d  .bss   00000000 .bss
00000000 l    d  .note.GNU-stack        00000000 .note.GNU-stack
00000000 l    d  .comment       00000000 .comment
说明编译出来的文件一个符号都没有,这样链接还是链接到c库,而c库里没有包含的函数,比如_getopt_long_r肯定是找不到了。
 
而假设你自己写个文件
//test.c

#include <stdio.h>

void fun(){}

int main(int argc, char *argv[])
{
    printf("test\n");
}

gcc -c test.c

objdump -t test.o

test.o:     file format elf32-i386

SYMBOL TABLE:
00000000 l    df *ABS*  00000000 test.c
00000000 l    d  .text  00000000 .text
00000000 l    d  .data  00000000 .data
00000000 l    d  .bss   00000000 .bss
00000000 l    d  .rodata        00000000 .rodata
00000000 l    d  .note.GNU-stack        00000000 .note.GNU-stack
00000000 l    d  .comment       00000000 .comment
00000000 g     F .text  00000005 fun
00000005 g     F .text  00000026 main
00000000         *UND*  00000000 puts
说明了一个问题,那就是getopt中的函数并没有真正进行编译。

要不然它应该会有类似下面的结果,符号表里应该包括fun,即函数名

在getopt.c如下位置添加#define _LIBC 和#define _(x) (x)

35:#include <stdio.h>
36:#define _LIBC
37:#define _(x) (x)

同理在getopt1.c中修改为

33:#include <stdio.h>
34:#define _LIBC

代码实例:

//test.c 和getopt.c getopt1.c getopt.h getopt_int.h在同一目录下

#include <stdio.h>
#include "getopt.h"
#include "getopt_int.h"
static char *common_options = "?V";
static struct option common_long_options[] = {
           {"version", 0, NULL, 'V'},
           {"help", 0, NULL, '?'},
           {0, 0, 0, 0}
    };

int main(int argc, char *argv[])
{
    char opt;
    int option_index = 0;
    
    struct _getopt_data local_opt_data = _GETOPT_DATA_INITIALIZER;
    while(-1 != (opt = _getopt_long_r(argc, argv, common_options, common_long_options,
            &option_index, &local_opt_data))){
        switch(opt){
            case 0:
                if(!strcmp(common_long_options[option_index].name, "process"))
                    ;
                else
                    printf("the param for display is not right\n");
            case 'V':
                printf("\tmysnort 0.0.1\n");
                break;        
            case ':':
                printf("option needs a value\n");
                break;
            default://'?'

                fprintf(stderr, "\t%serror usage, type help\n",argv[0]);
        }
    }
    if(local_opt_data.optind < argc) {
        printf("non-option argv-elements: ");
        while (local_opt_data.optind < argc)
            printf("%s ,try \"help\"", argv[local_opt_data.optind++]);
        printf("\n");
    }
    return 0;
}

编译gcc test.c getopt.c getopt1.c

./a.out

运行结果

root@xsf-pc:/my/study/project# ./a.out -V
        mysnort 0.0.1
此时,_getopt_long_r已经成功调用了,要使用这个做交互式应用程序,还需要自己定义函数实现argc,argv的重写,当然你也可以定义二维数组,将输入的参数字符串读入到二维数组中,然后将这个数组和数组包含的字符串数传入_getopt_long_r,二维数组必须以null结尾,而字符串数不包括null,具体怎么做,读者自己写写程序试试,在此就不剥夺读者自己写程序的权利了。由于_getopt_long_r是可重入的,你将正确解析的命令行字符串输入传入这个分析函数,就能进行连续分析了。这样linux的交互式程序设计就实现了。就像gdb似的。

你解析的参数应如下所示。

int n = 2;

char *argv[24] = {"help" , "-V", NULL};

 

阅读(536) | 评论(0) | 转发(0) |
0

上一篇:指针和数组一致的情况及二维数组初始化

下一篇:业界盘点:Linux和微软应该相互学习的5件事?

相关热门文章
  • 文件系统的制作 yaffs2 jffs2 ...
  • java之路,基础知识5
  • 从PHP官网被攻击,到熟悉SSL(...
  • 进程上下文VS中断上下文...
  • sowasp 2013 十大web应用程序...
  • linux 常见服务端口
  • 【ROOTFS搭建】busybox的httpd...
  • 什么是shell
  • linux socket的bug??
  • linux的线程是否受到了保护?...
  • ChinaUnix & ITPUB社区12周年...
  • ssh连接出现以下提示,求解...
  • 如何扩展MYSQL
  • 准备做一个大型门户,用户什么...
  • gbk or utf8
给主人留下些什么吧!~~
原创粉丝点击