通过popen查看selinux是否打开:
#include <stdio.h>
#include <stdlib.h>
int main () {
char cmd[64] = {0};
char buf[64] = {0};
FILE *fd;
sprintf(cmd,"getenforce\n");
fd = popen(cmd, "r" );
if(NULL == fd) {
LOGD("%s: popen error.\n", __FUNCTION__);
return 0;
}
fread(buf, sizeof(char), sizeof(buf), fd);
LOGD("chenpuo popen buf=%s",buf);
rc= pclose(fd2);
if(-1==rc){
ALOGD("getenforce close file failed");
if(ECHILD==errno) {
ALOGD("cyx pclose cannot obtain the child status.\n");
} else {
ALOGD( "getenforce Close file failed. %s, with errno %d.\n", strerror(errno), errno);
}
}else{
ALOGD("cmd getenforce child proccess %d status=%d strerr=%s\r\n", rc, WEXITSTATUS(rc), strerror(errno));
}
}
注意:这里cmd只要执行成功,则errno就为success;
奇怪的ls /data/test.log命令,如果文件不存在errno居然也是success,此时 No such file or directory 信息似乎打印不出来,buf为空。如果存在则buf为正常,为/data/test.log
#include “stdio.h”
#include “stdlib.h”
int main()
{
FILE *fp;
char buf[200] = {0};
if((fp = popen(“cat > test1″, “w”)) == NULL) {
perror(“Fail to popen\n”);
exit(1);
}
fwrite(“Read pipe successfully !”, 1, sizeof(“Read pipe successfully !”), fp);
pclose(fp);
return 0;
}
int main()
{
FILE * fp;
char buf[40] = {0};
fp = popen(NULL, "w");
if(NULL == fp)
{
perror("popen error.\n");
return -1;
}
printf("Input command:");
fgets(buf, 40, stdin);
fputs(buf, fp);
pclose(fp);
return 0;
}
执行结果:
[root@localhost codetest]# ./a.out
sh: -c: option requires an argument
Input command:pwd
==============================system函数====================================
看到popen就很容易想到system, system这个函数在老的平台里经常看到。现在很少看到使用了。 究其原因:
1)system 缺点:
|
1
2
|
#include <stdlib.h>
int
system(const
char
*command);
|
system()函数执行过程为:fork()->exec()->waitpid()。
system() executes a command specified in command by calling /bin/sh -c command, and returns after the command has been completed. During execution of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT will be ignored.
system()函数用起来很容易出错,返回值太多,而且返回值很容易跟command的返回值混淆
system的实际问题:
转自 http://my.oschina.net/renhc/blog/54582 这里自己看后比较有感受,遂简单转述了下。
简单概括就是:系统的同事在LIBGEN 里新增加了SIGCHLD的处理。将其ignore。为了避免僵尸进程的产生。 于是我们调用system就会出错ECHILD 即No child processes 。man手册查找system函数,没有此errno;再看waitpid里正好有此errno。
最好如下修改可以:
typedef
void
(*sighandler_t)(int);int
pox_system(const
char
*cmd_line)
{
int
ret = 0;
sighandler_t old_handler;
++ old_handler =signal(SIGCHLD, SIG_DFL);
ret =system(cmd_line);
++ signal(SIGCHLD, old_handler);
return
ret;
}
|
这里推荐使用popen()函数替代,关于popen()函数的简单使用也可以通过上面的链接查看。
popen()函数较于system()函数的优势在于使用简单,popen()函数只返回两个值:
成功返回子进程的status,使用WIFEXITED相关宏就可以取得command的返回结果;
失败返回-1,我们可以使用perro()函数或strerror()函数得到有用的错误信息。
=================================最后PS================================
在特权(setuid、setgid)进程中千万注意不要使用system和popen
popen()、popen()会继承环境变量,通过环境变量可能会造成系统安全的问题。
static char *popen_excuter(char *cmd, char *res, int rlen)
{
FILE *fp = NULL;
int readn = 0;
char *tmp = res;
char cmdtmp[128] = {0};
if (cmd == NULL || res == NULL) {
ALOGE("excute cmd res null\n");
return NULL;
}
memset(res, 0, rlen);
strcpy(cmdtmp, cmd);
ALOGE("cmd %s entry\n", cmdtmp);
fp = popen(cmdtmp, "r");
if (fp == NULL) {
ALOGE("excute %s fail\n", cmdtmp);
return NULL;
}
while (!feof(fp)) {
if(fgets(tmp, rlen, fp) != NULL) {
readn = strlen(tmp);
if (readn != 1 || *tmp != '\n') {
tmp += readn;
}
}
}
ALOGE("cmd %s end, errno=%d\n", cmdtmp, errno);
pclose(fp);
return res;
}
static int system_excuter(char *cmd)
{
pid_t status;
if (cmd == NULL) {
ALOGE("excute cmd res null\n");
return -1;
}
ALOGE("system excuter=%s\n", cmd);
status = system(cmd);
if (-1 == status) {
printf("system error!");
} else {
if (WIFEXITED(status)) {
if (0 != WEXITSTATUS(status)) {
printf("run shell script fail, status=0x%x, script exit code: %d\n",
status, WEXITSTATUS(status));
}
} else {
printf("status=0x%x, exit code = [%d]\n", status, WEXITSTATUS(status));
}
}
return 0;
}
本文详细介绍了如何使用popen和system函数执行命令,并强调了在特权进程中使用这些函数时的安全风险。文章还提供了使用popen替代system函数的方法,以及在调用system函数前设置SIGCHLD信号的解决方案。
1026

被折叠的 条评论
为什么被折叠?



