zoukankan      html  css  js  c++  java
  • 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命令。

  • 相关阅读:
    python 元类
    python中__init__()、__new__()、__call__()、__del__()用法
    python内置数据结构方法的时间复杂度
    时间复杂度和空间复杂度
    数据结构及算法(1)
    sys模块python
    python中的文本操作
    python 中的os模块
    python 几种不同的格式化输出
    【js】null 和 undefined的区别?
  • 原文地址:https://www.cnblogs.com/quiet/p/2392259.html
Copyright © 2011-2022 走看看