本文目錄一覽:
如何在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] = ‘\0’;
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 exec\n”);
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;
}
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/245548.html