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命令。

转载于:https://www.cnblogs.com/quiet/archive/2012/03/12/2392259.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值