• popen和变长参数库函数(va_xxx)用法举例及命令执行失败情况探讨


      在python里可以通过os.popen()和os.system()执行shell命令,C代码里自然也有相应的接口。

    如下一段代码:

     1 /*
    2 ** sample program by virHappy
    3 */
    4
    5 #include <stdio.h>
    6 #include <stdlib.h>
    7 #include <string.h>
    8 #include <stdarg.h>
    9
    10 #define MAX_BUF_LEN 8192
    11
    12 /*
    13 ** conbine some string together accroding to the formate.
    14 */
    15 static inline char* do_combin_str(unsigned int max_len, const char *format, ...)
    16 {
    17 int n;
    18 char *str = NULL;
    19 va_list args;
    20
    21 if ((str = malloc(max_len)) == NULL) {
    22 fprintf(stderr, "malloc failed\n");
    23 exit(-1);
    24 }
    25
    26 va_start(args, format);
    27 n = vsnprintf(str, max_len, format, args);
    28 va_end(args);
    29
    30 if (n >= max_len) {
    31 free(str);
    32 fprintf(stderr, "vsnprintf error!\n");
    33 exit(-2);
    34 }
    35
    36 return str;
    37 }
    38
    39 /*
    40 ** execute the shell commond with popen
    41 */
    42 int run_sh_cmd(char* cmd)
    43 {
    44 FILE *fp;
    45 int ret = 0;
    46 if (!cmd) {
    47 fprintf(stderr, "cmd is NULL\n");
    48 return -1;
    49 }
    50
    51 if ((fp = popen(cmd, "r")) == NULL) {
    52 fprintf(stderr, "popen error\n");
    53 return -2;
    54 }
    55
    56 ret = pclose(fp);
    57 return ret;
    58 }
    59
    60 int main(int argc, char** argv)
    61 {
    62 if (argc != 2 ){
    63 fprintf(stderr, "error!\nUsage:%s \"cmd\" \n", argv[0]);
    64 fprintf(stderr, "Sample Usage: %s \"touch file\" \n", argv[0]);
    65 exit(-1);
    66 }
    67
    68
    69 char* cmd = do_combin_str(MAX_BUF_LEN,"%s",argv[1]);
    70 if ( run_sh_cmd(cmd) < 0 ) {
    71 fprintf(stderr, "error in run_sh_cmd\n");
    72 exit(-3);
    73 }else {
    74 printf("success!\n");
    75 }
    76
    77
    78 return 0;
    79 }


       这里特意用了va_xxx函数,按照程序逻辑,使用snprintf也是可以的。

    PS: 

       如何处理popen中命令执行失败的情况(不因为popen自身分配内存或者pipe失败)呢?

    查了下man手册,对于popen的返回值是这样描述的:

    man的输出

    RETURN VALUE

           The popen() function returns NULL if the fork(2) or pipe(2) calls fail, or if it cannot allocate memory. 

           The pclose() function returns -1 if wait4() returns an error, or some other error is detected. 

    ERRORS

           The popen() function does not set errno if memory allocation fails.  If the underlying fork() or  pipe()  fails,  errno  is  set

           appropriately.  If the type argument is invalid, and this condition is detected, errno is set to EINVAL. 

           If pclose() cannot obtain the child status, errno is set to ECHILD.

    设置场景: 执行rmdir命令, 删除的目录对象里面有文件。 如手动创建一个目录tdir, 在tdir里面创建文件,然后执行./rsc "rmdir tdir": (rsc为上面代码的目标文件)

    [root@host]# ./rsc "rmdir tdir"
    rmdir: tdir: Directory not empty
    success!

    这里popen执行成功,pclose也执行成功,但实际上dir并没有删除掉,这种情况有办法处理吗?

       留意到popen出错时会设置errno,当遇到这种情况时,popen并不返回NULL,不设置errno。

    续:

     popen只负责执行程序,对于这种情况,由于rmdir这个命令自身不能删除空的目录,popen是检测不到的(?)。

    可以通过rm -rf 替换rmdir命令。

  • 相关阅读:
    关于一个简单面试题(。net)
    写一个TT模板自动生成spring.net下面的配置文件。
    EF自动生成的(T4模板) 关联属性元数据修改
    关于面向切面编程的部分内容-错误处理机制
    memcache 安装
    Newtonsoft.Json工具类
    关于Memcache使用的工具类
    关于 Log4Net
    今天开始写博客
    OC 协议
  • 原文地址:https://www.cnblogs.com/quiet/p/2392259.html
Copyright © 2020-2023  润新知