C程序调用shell脚本共有三种方式:system()、popen()、exec系列函数
1)system (shell命令或shell脚本路径);
执行过程:system() 会调用 fork() 产生子进程,由子进程来调用 /bin/sh-c string 来执行参数 string 字符串所代表的命令,此命令执行完后随即返回原调用的进程。在调用 system() 期间 SIGCHLD 信号会被暂时搁置, SIGINT 和 SIGQUIT 信号则会被忽略。
返回值: 如果 system() 在调用 /bin/sh 时失败则返回 127 ,其他失败原因返回 -1 。若参数 string 为空指针 (NULL) ,则返回非零值。如果 system() 调用成功则最后会返回执行 shell 命令后的返回值,但是此返回值也有可能为 system() 调用 /bin/sh 失败所返回的 127 ,因此最好能再检查 errno 来确认执行成功。
注意:在编写具有 SUID/SGID 权限的程序时最好不要使用 system() , system() 会继承环境变量,通过环境变量可能会造成系统安全的问题。
例:在~/myprogram/目录下有shell脚本test.sh,内容为
#!bin/bash
#test.sh
echo $HOME
在该目录下新建一个c文件systemtest.c,内容为:
#include<stdlib.h>
/*This program is used to test function system*/
main()
{
system("~/myprogram/test.sh");
}
执行结果如下:
xiakeyou@ubuntu:~/myprogram$ gcc systemtest.c -o systemtest
xiakeyou@ubuntu:~/myprogram$ ./systemtest
/home/d/e/xiakeyou
xiakeyou@ubuntu:~/myprogram$
2)popen( char *command,char *type)
执行过程: popen() 会调用 fork() 产生子进程,然后从子进程中调用 /bin/sh -c 来执行参数 command 的指令。参数 type 可使用“ r ”代表读取,“ w ”代表写入。依照此 type 值, popen() 会建立管道连到子进程的标准输出设备或标准输入设备,然后返回一个文件指针。随后进程便可利用此文件指针来读取子进程的输出设备或是写入到子进程的标准输入设备中。此外,所有使用文件指针 (FILE*) 操作的函数也都可以使用,除了 fclose() 以外。
返回值:若成功则返回文件指针,否则返回 NULL ,错误原因存于 errno 中。
注意:在编写具 SUID/SGID 权限的程序时请尽量避免使用 popen() , popen() 会继承环境变量,通过环境变量可能会造成系统安全的问题。
例:C程序popentest.c内容如下:
#include<stdio.h>
main()
{
FILE * fp;
charbuffer[80];
fp=popen(“~/myprogram/test.sh”,”r”);
fgets(buffer,sizeof(buffer),fp);
printf(“%s”,buffer);
pclose(fp);
}
执行结果如下:
xiakeyou@ubuntu:~/myprogram$ vim popentest.c
xiakeyou@ubuntu:~/myprogram$ gcc popentest.c -o popentest
xiakeyou@ubuntu:~/myprogram$ ./popentest
/home/d/e/xiakeyou
xiakeyou@ubuntu:~/myprogram$
1)system (shell命令或shell脚本路径);
执行过程:system() 会调用 fork() 产生子进程,由子进程来调用 /bin/sh-c string 来执行参数 string 字符串所代表的命令,此命令执行完后随即返回原调用的进程。在调用 system() 期间 SIGCHLD 信号会被暂时搁置, SIGINT 和 SIGQUIT 信号则会被忽略。
返回值: 如果 system() 在调用 /bin/sh 时失败则返回 127 ,其他失败原因返回 -1 。若参数 string 为空指针 (NULL) ,则返回非零值。如果 system() 调用成功则最后会返回执行 shell 命令后的返回值,但是此返回值也有可能为 system() 调用 /bin/sh 失败所返回的 127 ,因此最好能再检查 errno 来确认执行成功。
注意:在编写具有 SUID/SGID 权限的程序时最好不要使用 system() , system() 会继承环境变量,通过环境变量可能会造成系统安全的问题。
例:在~/myprogram/目录下有shell脚本test.sh,内容为
#!bin/bash
#test.sh
echo $HOME
在该目录下新建一个c文件systemtest.c,内容为:
#include<stdlib.h>
/*This program is used to test function system*/
main()
{
system("~/myprogram/test.sh");
}
执行结果如下:
xiakeyou@ubuntu:~/myprogram$ gcc systemtest.c -o systemtest
xiakeyou@ubuntu:~/myprogram$ ./systemtest
/home/d/e/xiakeyou
xiakeyou@ubuntu:~/myprogram$
2)popen( char *command,char *type)
执行过程: popen() 会调用 fork() 产生子进程,然后从子进程中调用 /bin/sh -c 来执行参数 command 的指令。参数 type 可使用“ r ”代表读取,“ w ”代表写入。依照此 type 值, popen() 会建立管道连到子进程的标准输出设备或标准输入设备,然后返回一个文件指针。随后进程便可利用此文件指针来读取子进程的输出设备或是写入到子进程的标准输入设备中。此外,所有使用文件指针 (FILE*) 操作的函数也都可以使用,除了 fclose() 以外。
返回值:若成功则返回文件指针,否则返回 NULL ,错误原因存于 errno 中。
注意:在编写具 SUID/SGID 权限的程序时请尽量避免使用 popen() , popen() 会继承环境变量,通过环境变量可能会造成系统安全的问题。
例:C程序popentest.c内容如下:
#include<stdio.h>
main()
{
FILE * fp;
charbuffer[80];
fp=popen(“~/myprogram/test.sh”,”r”);
fgets(buffer,sizeof(buffer),fp);
printf(“%s”,buffer);
pclose(fp);
}
执行结果如下:
xiakeyou@ubuntu:~/myprogram$ vim popentest.c
xiakeyou@ubuntu:~/myprogram$ gcc popentest.c -o popentest
xiakeyou@ubuntu:~/myprogram$ ./popentest
/home/d/e/xiakeyou
xiakeyou@ubuntu:~/myprogram$