您的位置:首页 > 运维架构 > Shell

linux下C程序插入执行shell脚本

2014-02-27 22:58 399 查看

linux下C程序插入执行shell脚本

最近在看深入理解计算机系统,看到一个函数叫做execve(),这个函数很有意思,可以在一个进程插入另外一个进程执行,但是又不像fork()一样产生一个子进程,execve()插入的进程和原进程共享进程号,就好像执行这进程就像执行过程调用一般随意。

函数原型如下:

int execve(const char *filename, char *const argv[], char *const envp[]);

EXAMPLE
The following program is designed to be execed by the second program below.  It just echoes its command-line one per line.

/* myecho.c */

#include <stdio.h>
#include <stdlib.h>

int
main(int argc, char *argv[])
{
int j;

for (j = 0; j < argc; j++)
printf("argv[%d]: %s\n", j, argv[j]);

exit(EXIT_SUCCESS);
}

This program can be used to exec the program named in its command-line argument:

/* execve.c */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int
main(int argc, char *argv[])
{
char *newargv[] = { NULL, "hello", "world", NULL };
char *newenviron[] = { NULL };

if (argc != 2) {
fprintf(stderr, "Usage: %s <file-to-exec>\n", argv[0]);
exit(EXIT_FAILURE);
}

newargv[0] = argv[1];

execve(argv[1], newargv, newenviron);
perror("execve");   /* execve() only returns on error */
exit(EXIT_FAILURE);
}

We can use the second program to exec the first as follows:

$ cc myecho.c -o myecho
$ cc execve.c -o execve
$ ./execve ./myecho
argv[0]: ./myecho
argv[1]: hello
argv[2]: world


插入一个shell脚本执行:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int
main(int argc, char *argv[])
{
char *newargv[] = { "/etc" };
char *newenviron[] = { NULL };
if (argc != 2)
{
fprintf(stderr, "Usage: %s <file-to-exec>\n", argv[0]);
exit(EXIT_FAILURE);
}

newargv[0] = argv[1];

execve(argv[1], newargv, newenviron);
perror("execve");   /* execve() only returns on error */
exit(EXIT_FAILURE);
}


script.sh如下:

#!/bin/bash
ls


执行:

./execve ./script.sh

会在当前终端下输出所有的文件

yca@ubuntu:~/桌面/hello$ ./execve ./script.sh
1          execve     hello1    hello3      hello5      hello_lex
1.txt          execve.c     hello1.c  hello3.cpp  hello5.c   k_max
Bubble          hello     hello1.o  hello3.o    hello5.o   k_max.c
Bubble.c      hello.c     hello2.c  hello3.s    hello5.s   lex.yy.c
QuickSort.c   hello.lex  hello2.o  hello4      hello5.s1  script.sh
Quicksort1.c  hello.sh     hello2.s  hello4.c    hello51.s


很好很强大~~

1、system(执行shell命令)

相关函数 fork,execve,waitpid,popen

表头文件 #include<stdlib.h>

定义函数 int system(const char * string);

函数说明 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()会

继承环境变量,通过环境变量可能会造成系统安全的问题。

范例:

#include<stdlib.h>
main()
{
system(“ls -al /etc/passwd /etc/shadow”);
}

2、popen(建立管道I/O)

相关函数 pipe,mkfifo,pclose,fork,system,fopen

表头文件 #include<stdio.h>

定义函数 FILE * popen( const char * command,const char *type);

函数说明 popen()会调用fork()产生子进程,然后从子进程中调用/bin/sh -c

来执行参数command的指令。参数type可使用“r”代表读取,“w”

代表写入。依照此type值,popen()会建立管道连到子进程的标准输

出设备或标准输入设备,然后返回一个文件指针。随后进程便可利

用此文件指针来读取子进程的输出设备或是写入到子进程的标准输

入设备中。此外,所有使用文件指针(FILE*)操作的函数也都可以使

用,除了fclose()以外。

返回值 若成功则返回文件指针,否则返回NULL,错误原因存于errno中。

错误代码 EINVAL参数type不合法。

注意事项 在编写具SUID/SGID权限的程序时请尽量避免使用popen(),popen()

会继承环境变量,通过环境变量可能会造成系统安全的问题。

范例:

#include<stdio.h>


main()


{


FILE
* fp;


char
buffer[80];


fp=popen(“cat
/etc/passwd”,”r”);


fgets(buffer,
sizeof
(buffer),fp);


printf(“%s”,buffer);


pclose(fp);


}


执行 root :x:0 0: root: /root: /bin/bash

3、使用vfork()新建子进程,然后调用exec函数族

#include<unistd.h>
main()
{
char* argv[ ]={“ls”,”-al”,”/etc/passwd”,(char*)};

if(vfork() = =0)
{
execv(“/bin/ls”,argv);
}else{
printf(“This is the parentprocess\n”);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: