说在前面:在实际编程中尽量减少使用system函数。
int system(const char *command);
说明: system()通过调用/ bin / sh -c命令执行命令中指定的命令,并在命令完成后返回。在执行该命令期间,SIGCHLD将被阻塞,并且SIGINT和SIGQUIT将被忽略。
返回值:
实际上system调用了三个函数:fork()、exec()、waitpid()。因此有三种返回值:
1>fork()失败或者waitpid()返回除了EINTR之外的出错,则system返回-1.而且errno
中设置了错误类型值。
2>如果exec失败(表示不能执行shell),则其返回值如同shell执行了exit(127)一样
3>如果三个函数都执行成功,并且system的返回值是shell的终止状态,其格式已在已在waitpid中说明。
system的实现:
int system(const char * cmdstring) { pid_t pid; int status; if(cmdstring == NULL) { return (1); } if((pid = fork())<0) { status = -1; } else if(pid = 0) { execl("/bin/sh", "sh", "-c", cmdstring, (char *)0); -exit(127); //子进程正常执行则不会执行此语句 } else { while(waitpid(pid, &status, 0) < 0) { if(errno != EINTER){ status = -1; break; } } } return status; }
简单的使用:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> int main() { int status = 0; status = system("ls -a"); if(-1 == status) { perror("system"); exit(1); } if(WIFEXITED(status) != 0) //正常退出 { if(WEXITSTATUS(status) == 0) //操作正确 { printf("run command success\n"); } else { printf("run error\n"); } } else //异常退出 { printf("exit error is %d\n", WEXITSTATUS(status)); } return 0; }
通过上面的代码我们可以看到,system在使用时的一个弊端,由于返回值太多,要安全的使用它就要进行许多步的出错处理。
所以,不太建议使用system。
使用system需要注意:
建议使用popen函数取代system();
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);返回值: command的终止状态, 出错返回-1
popen()函数较于system()函数的优势在于使用简单,popen()函数只返回两个值:
成功返回子进程的status,使用WIFEXITED相关宏就可以取得command的返回结果;
失败返回-1,我们可以使用perro()函数或strerror()函数得到有用的错误信息。
popen先执行fork,然后调用exec以执行command并返回一个标准I/O文件指针。如果type是“r”,则文件指针链接到command的标准输出。如果type是“w”,则文件指针链接到command的标准输入。将popen和fopen进行类比,方便记忆其最后一个参数及其作用,如果type是“r”,则返回文件指针是刻度的,如果type是是“w”,则是可写的。
简单使用:
#include <stdio.h> #include <stdlib.h> int main() { FILE* fp = NULL; char buf[1024] = {0}; fp = popen("ls -a", "r"); if(NULL == fp) { perror("popen"); exit(1); } while(fgets(buf, 1024, fp) != NULL) { fprintf(stdout, "%s", buf); } pclose(fp); return 0; }
注意,popen绝不应该由设置用户ID或设置组ID程序调用。当它执行命令
popen等同于execl("/bin/sh", "sh", "-c", command
,NULL);
它在从调用者继承的环境中执行shell,并由shell解释执行command。一个心怀不轨的用户可以
操纵这种环境,使得shell能以设置ID文件模式所授予的提升了
的权限以及非预期的方式执行命令。
popen特别适用于构造简单的过滤程序,它变换运行命令的输入或输出。
当命令希望构建自己的管道线时就是这种情形。