首页 > 编程知识 正文

c语言开源shell,c语言开源项目推荐

时间:2023-12-29 20:32:01 阅读:331077 作者:RGMS

本文目录一览:

如何在C语言中调用shell命令

在linux操作系统中,很多shell命令使用起来非常简单,这些shell命令的程序实现已经被底层实现好。有时候需要在程序中调用shell命令,这样可以就不用在控制台上手动输入shell命令了,下面就以三个函数为例来讲解如何在C语言中调用shell命令。

1、system(执行shell 命令)

相关函数 fork,execve,waitpid,popen

表头文件 #includestdlib.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()会

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

范例:

#includestdlib.h

main()

{

system(“ls -al /etc/passwd /etc/shadow”);

}

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

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

表头文件 #includestdio.h

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

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

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

代表写入。

如何在C语言中执行shell命令

在c语言中调用shell命令的方法实现。

c程序调用shell脚本共有两种方法

:system()、popen(),分别如下:

system()

不用自己去创建进程,系统已经封装了这一步,直接加入自己的命令即可

popen()

也可以实现执行的命令,比system

开销小

以下分别说明:

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

来确认履行

成功

system命令以其简略

高效的作用得到很很广泛

的利用

,下面是一个例子

例:在/tmp/testdir/目录下有shell脚本tsh.sh,内容为

#!/bin/sh

wget

$1

echo

"done!"

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

main

{

file

*

fp;

charbuffer[80];

fp=popen(“~/myprogram/test.sh”,”r”);

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

printf(“%s”,buffer);

pclose(fp);

}

如何用c语言写一个shell

鸟哥是不会有这个的,可以这样想(感觉这样很麻烦,只用一对管道应该也可以,流程也能简单,控制好进程顺序就行。这个编得过):

#include stdio.h

#include stdlib.h

#include string.h

#include fcntl.h

#include unistd.h

#include sys/wait.h

#define CMD_LINE 1024

#define PIPE_MAX 16

#define ARG_MAX 10

typedef struct {

char *arg[ARG_MAX];

char *in;

char *out;

} cmd_t;

extern int parse_token(char *buf, cmd_t cmd[]);

extern int parse(char *buf, cmd_t * cmd);

extern int test_parse(cmd_t cmd[], int len);

int main(int argc, char *argv[])

{

char buf[CMD_LINE];

cmd_t cmd[PIPE_MAX + 1];

int fd[PIPE_MAX][2];

int j, i;

int cmd_len, pipe_len;

pid_t pid;

while (1) {

printf("my_shell#");

fgets(buf, CMD_LINE, stdin);

buf[strlen(buf) - 1] = '';

cmd_len = parse_token(buf, cmd);

pipe_len = cmd_len - 1;

if (pipe_len PIPE_MAX)

continue;

for (i = 0; i pipe_len; ++i)

pipe(fd[i]);

for (i = 0; i cmd_len; ++i)

if ((pid = fork()) == 0)

break;

if (pid == 0) {

if (pipe_len) {

if (i == 0) {

close(fd[i][0]);

dup2(fd[i][1], 1);

close(fd[i][1]);

for (j = 1; j pipe_len; ++j)

close(fd[j][0]),

close(fd[j][1]);

} else if (i == pipe_len) {

close(fd[i - 1][1]);

dup2(fd[i - 1][0], 0);

close(fd[i - 1][0]);

for (j = 0; j pipe_len - 1; ++j)

close(fd[j][0]),

close(fd[j][1]);

} else {

dup2(fd[i - 1][0], 0);

close(fd[i][0]);

dup2(fd[i][1], 1);

close(fd[i][1]);

for (j = 0; j pipe_len; ++j) {

if ((j != i - 1)

|| (j != i))

close(fd[j][0]),

close(fd[j]

[1]);

}

}

}

if (cmd[i].in) {

int fd = open(cmd[i].in, O_RDONLY);

dup2(fd, STDIN_FILENO);

close(fd);

}

if (cmd[i].out) {

int fd =

open(cmd[i].out,

O_RDWR | O_CREAT | O_TRUNC, 0644);

dup2(fd, STDOUT_FILENO);

close(fd);

}

execvp(cmd[i].arg[0], cmd[i].arg);

fprintf(stderr, "Failed execn");

exit(127);

}

/* parent */

for (i = 0; i pipe_len; ++i)

close(fd[i][0]), close(fd[i][1]);

for (i = 0; i cmd_len; ++i)

wait(NULL);

}

return 0;

}

int parse_token(char *buf, cmd_t cmd[])

{

int n = 0;

#if 1

char *save_p;

char *p = strtok_r(buf, "|", save_p);

while (p != NULL) {

parse(p, cmd[n++]);

p = strtok_r(NULL, "|", save_p);

}

#else

cmd[n].arg[0] = "ls";

cmd[n].arg[1] = "-l";

cmd[n].arg[2] = NULL;

#endif

return n;

}

int test_parse(cmd_t cmd[], int len)

{

int i;

for (i = 0; i len; ++i) {

printf("cmd[%d]:", i);

int j = 0;

while (cmd[i].arg[j])

printf(" %s", cmd[i].arg[j++]);

if (cmd[i].in)

printf("tin:%s", cmd[i].in);

if (cmd[i].out)

printf("tout:%s", cmd[i].out);

printf("n");

}

return 0;

}

int parse(char *buf, cmd_t * cmd)

{

int i = 0;

cmd-in = NULL;

cmd-out = NULL;

char *p = strtok(buf, " ");

while (p) {

if (*p == '') {

if (*(p + 1))

cmd-in = p + 1;

else

cmd-in = strtok(NULL, " ");

} else if (*p == '') {

if (*(p + 1))

cmd-out = p + 1;

else

cmd-out = strtok(NULL, " ");

} else

cmd-arg[i++] = p;

p = strtok(NULL, " ");

}

cmd-arg[i] = NULL;

return 0;

}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。