我正在建立一个像shell这样的Linux,而我正试图执行外部命令,就像在Linux中使用" ./"在开始。
这是我阅读命令的方式:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
#include "commands/commands.h"
bool starts_with(const char *a, const char *b){
if(strncmp(a,b,strlen(b)) == 0){
return 1;
}
return 0;
}
int main(int argc, char *argv[]){
char cmd[500];
do{
printf("$ > ");
fgets(cmd, 499, stdin);
if(starts_with(cmd, "./")){
execute_external_command(cmd);
}else{
//execute_interal_command(cmd);
}
}while(strcmp(cmd, "exit\n") != 0);
return 0;
}
这就是我的子进程被新进程取代的过程,这个程序名为&#34; hello&#34;。它只是打印&#34; Hello World&#34;到了屏幕。
else{
//Child process
dup2(commpipe[0],0);
close(commpipe[1]);
//Replace child process with a new process
if(execl("hello", "hello", NULL) == -1){
fprintf(stderr, "Error executing new process!\n");
exit(3);
}
}
}
它运作得很好。但我想替换那个&#34;你好&#34;有一个变量就像我输入&#34; ./ hello&#34;获得&#34;你好&#34;从那里开始,并将其用作execl()函数中的变量。
我试着这样做,但似乎无法找到&#34;你好&#34;。我试着在屏幕上打印它,然后打印出#34;你好&#34;喜欢它。任何想法为什么不执行该过程?
else{
//Child process
dup2(commpipe[0],0);
close(commpipe[1]);
char program[10];
int len = strlen(cmd) - 2;
memcpy(program, &cmd[2],len);
//Replace child process with a new process
if(execl(program, program, NULL) == -1){
fprintf(stderr, "Error executing new process!\n");
exit(3);
}
}
}
第二个问题:在我的第一个执行方法中,它执行得很好用&#34;你好&#34;作为execl()函数中的字符串。我总是打印那个&#34; $&gt; &#34;字符串o屏幕,要求输入。但是当子进程完成执行时,整个程序就会停止。如何让他打印出来#34; $&gt; &#34;屏幕上的字符串再次让我执行其他命令,如果我想要的话。提前致谢
UPDATE:执行外部命令的函数
void execute_external_command(char cmd[]){
pid_t pid;
int rv;
int commpipe[2];
//Creting pipe
if(pipe(commpipe)){
fprintf(stderr, "Error creating pipe!!\n");
exit(1);
}
if((pid=fork()) == -1){
fprintf(stderr, "Error forking ew process!\n");
exit(2);
}
if(pid){
//Parent process
dup2(commpipe[1],1);
close(commpipe[0]);
setvbuf(stdout,(char*)NULL,_IONBF,0);
wait(&rv);
fprintf(stderr, "Child exited with a %d value", rv);
}else{
//Child process
dup2(commpipe[0],0);
close(commpipe[1]);
int len = strlen(cmd) - 2;
char program[len];
memcpy(program, &cmd[2],len);
program[len-1] = '\0';
//Replace child process with a new process
if(execl(program, program, NULL) == -1){
fprintf(stderr, "Error executing new process!\n");
exit(3);
}
}
}
答案 0 :(得分:2)
fgets
包含字符串中的尾部换行符。你必须剥离它才能正确调用二进制文件。此外,您的memcpy不会将必要的zerobyte复制为字符串终止符。尝试:
program[len-1] = '\0';
在memcpy()
之后。 这应该会有所帮助。
另一个注意事项:此代码容易出现缓冲区溢出,因为程序固定为10个字节,而cmd可能更长。 你可以这样做:
int len = strlen(cmd) - 2;
char program[len];
memcpy(program, &cmd[2],len);
program[len-1] = '\0';
防止这种情况发生。如果您不关心修改cmd,您也可以这样做:
cmd[strlen(cmd)-1] = '\0';
if (execl(cmd+2, cmd+2, NULL) ...
还有一件事:
甚至没有必要删除./
- 部分,execl也可以正常使用它。
在父进程中:
if(pid){
//Parent process
dup2(commpipe[1],1);
将进程的stdout设置为commpipe。因此,所有后续的printf都会尝试写入损坏的管道,因此SIGPIPE会终止您的父进程。 我根本没有看到为什么你需要这里的模板,我想你可以完全放弃它。